linux内核udp校验和计算函数,Linux 内核IP和UDP检验和计算

·IP checksum

a.接收报文

struct iphdr *iph = ip_hdr(skb);

if (unlikely(ip_fast_csum((u8 *)iph, iph->ihl)))

goto checksum_error;

b.发送报文

ip_send_check(iph);

{

iph->check = 0;

iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl);

}

·UDP checksum

a.网卡设备属性

#define NETIF_F_IP_CSUM     2   /* 基于IPv4的L4层checksum. */

#define NETIF_F_NO_CSUM     4   /* 设备可靠不需要L4层checksum. loopack. */

#define NETIF_F_HW_CSUM     8   /* 基于所有协议的L4层checksum*/

#define NETIF_F_IPV6_CSUM   16  /* 基于IPv6的L4层checksum*/

通过ethtool可以查看网卡是否支持硬件checksum

ethtool -k eth0

Offload parameters for eth0:

Cannot get device rx csum settings: Operation not supported

Cannot get device udp large send offload settings: Operation not supported

rx-checksumming: off

tx-checksumming: on

scatter-gather: on

tcp segmentation offload: off

udp fragmentation offload: off

generic segmentation offload: off

tx-checksumming: on  表明支持发送hardware checksum。

b.linux UDP checksum数据结构

union {

__wsum                       csum;

struct {

__u16  csum_start;

__u16  csum_offset;

};

};

1)skb->csum和skb->ip_summed这两个域也是与4层校验相关的,这两个域的含义依赖于skb表示的是一个输入包还是一个输出包。

2)当网卡设备能提供硬件checksum并且作为输出包的时候,表示为skb-> csum_start和skb-> csum_offset

csum_start: Offset from skb->head where checksumming should start

csum_offset: Offset from csum_start where checksum should be stored

当数据包是一个输入包时

skb->ip_summed表示的是四层校验的状态,下面的几个宏定义表示了设备驱动传递给4层的一些信息。

#define CHECKSUM_NONE 0

#define CHECKSUM_UNNECESSARY 1

#define CHECKSUM_COMPLETE 2

skb->csum:存放硬件或者软件计算的payload的checksum不包括伪头,但是是否有意义由skb->ip_summed的值决定。

CHECKSUM_NONE表示csum域中的校验值是无意义的,需要L4层自己校验payload和伪头。有可能是硬件检验出错或者硬件没有校验功能,协议栈软件更改如pskb_trim_rcsum函数。

CHECKSUM_UNNECESSARY表示网卡或者协议栈已经计算和验证了L4层的头和校验值。也就是计算了tcp udp的伪头。还有一种情况就是回环,因为在回环中错误发生的概率太低了,因此就不需要计算校验来节省cpu事件。

CHECKSUM_COMPLETE表示网卡已经计算了L4层payload的校验,并且csum已经被赋值,此时L4层的接收者只需要加伪头并验证校验结果。

1)在L4层发现如果udp->check位段被设为0,那么skb->ip_summed直接设为CHECKSUM_UNNECESSARY,放行该报文。

2)   如果skb->ip_summed为CHECKSUM_COMPLETE,则把skb->csum加上伪头进行校验,成功则将skb->ip_summed设为CHECKSUM_UNNECESSARY,放行该数据包。

3)   通过上述后skb->ip_summed还不是CHECKSUM_UNNECESSARY,那么重新计算伪头赋给skb->csum。

4)    将还不是CHECKSUM_UNNECESSARY的数据报文的payload加上skb->csum进行checksum计算,成功将设为CHECKSUM_UNNECESSARY并放行,失败则丢弃。

udp4_csum_init(skb, uh, proto)

{

const struct iphdr *iph = ip_hdr(skb);

if (uh->check == 0) {

skb->ip_summed = CHECKSUM_UNNECESSARY;

} else if (skb->ip_summed == CHECKSUM_COMPLETE) {

if (!csum_tcpudp_magic(iph->saddr, iph->daddr, skb->len,

proto, skb->csum))

skb->ip_summed = CHECKSUM_UNNECESSARY;

}

if (!skb_csum_unnecessary(skb))

skb->csum = csum_tcpudp_nofold(iph->saddr, iph->daddr,

skb->len, proto, 0);

}

if (udp_lib_checksum_complete(skb))

goto csum_error;

static inline int udp_lib_checksum_complete(struct sk_buff *skb)

{

return !skb_csum_unnecessary(skb) &&

{

sum = csum_fold(skb_checksum(skb, 0, len, skb->csum));

if (likely(!sum)) {

if (unlikely(skb->ip_summed == CHECKSUM_COMPLETE))

netdev_rx_csum_fault(skb->dev);

skb->ip_summed = CHECKSUM_UNNECESSARY;

}

return sum;

}

}

当数据包是输出包时

skb->csum表示为csum_start和csum_offset,它表示硬件网卡存放将要计算的校验值的地址,和最后填充的便宜。这个域在输出包时使用,只在校验值在硬件计算的情况下才对于网卡真正有意义。硬件checksum功能只能用于非分片报文。

而此时ip_summed可以被设置的值有下面两种:

#define CHECKSUM_NONE       0

#define CHECKSUM_PARTIAL 3

CHECKSUM_NONE 表示协议栈计算好了校验值,设备不需要做任何事。CHECKSUM_PARTIAL表示协议栈算好了伪头需要硬件计算payload checksum。

1)对于UDP socket开启了UDP_CSUM_NOXMIT /* UDP csum disabled */

uh->check = 0;

skb->ip_summed = CHECKSUM_NONE;

2)软件udp checksum

struct iphdr *iph = ip_hdr(skb);

struct udphdr *uh = udp_hdr(skb);

uh->check = 0;

skb->csum = csum_partial(skb_transport_header (skb), skb->len, 0);//skb->data指向传输层头

uh->check = csum_tcpudp_magic(iph->saddr, iph->daddr, skb->len, iph->protocol, skb->csum);

skb->ip_summed = CHECKSUM_NONE;

//Todo: scatter and gather

3)  硬件checksum: 只能是ip报文长度小于mtu的数据报(没有分片的报文)。

CHECKSUM_PARTIAL表示使用硬件checksum ,L4层的伪头的校验已经完毕,并且已经加入uh->check字段中,此时只需要设备计算整个头4层头的校验值。

(对于支持scatter and gather的报文必须要传输层头在线性空间才能使用硬件checksum功能)

uh->check = ~csum_tcpudp_magic(iph->saddr, iph->daddr, skb->len, IPPROTO_UDP, 0);

skb->csum_start = skb_transport_header (skb) - skb->head;

skb->csum_offset = offsetof(struct udphdr, check);

skb->ip_summed = CHECKSUM_PARTIAL;

d

最后在dev_queue_xmit发送的时候发现设备不支持硬件checksum就会进行软件计算

int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev,

struct netdev_queue *txq)

{

/* If packet is not checksummed and device does not

* support checksumming for this protocol, complete

* checksumming here.

*/

if (skb->ip_summed == CHECKSUM_PARTIAL) {

skb_set_transport_header(skb,

skb_checksum_start_offset(skb));

if (!(features & NETIF_F_ALL_CSUM) &&

skb_checksum_help(skb))

goto out_kfree_skb;

}

}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/574533.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

各种类型的转换

int.parse() float.parase() double.parse()这些都可以把字符串类型转换为数值类型 **.ToString();把各种类型转换为字符串类型 (int)**代表类型之间的转换有显示转换,也有隐形转换,这种只限于数值之间的转换,即想转换…

stol函数在linux下使用,Linux下ATT汇编语法简介一

这显得很古怪,不过在gcc知道程序员拿这些寄存器做些什么后,这确实能够对gcc的优化操作有所帮助。表5-3中是一些可能会用到的寄存器加载代码及其具体的含义。表5-3 常用寄存器加载代码说明代 码说 明代 码说 明a使用寄存器eaxm使用内存地址b使用寄存器ebx…

linux安装pgsql源码包解压,在Linux(centos)中使用源码安装pgRouting

目录一、解压pgRouting二、配置PostgreSQL的环境变量三、编译源代码四、测试由于pgRouting依赖于PostGIS和PostgreSQL,所以阅读本文之前,务必请先阅读:Linux(centos)中使用源码安装PostgreSQLLinux(centos)中使用源码安装PostGIS按照以上文章…

clientX和clientY属性需要注意的地方

clientX和clientY为可视区鼠标的位置。 1. 随鼠标移动的div块[runjs] 当document有多个页面时,会出现问题。[runjs] 2. 解决方案:scrollTop, scrollLeft 需要注意scrollTop/scrollLeft的兼容性获取; scrollTop document.documentElement.scr…

Android无线测试之—UiAutomator UiObject API介绍二

点击与长按 一、组件区域位置关系 Rect 对象代表一个矩形区域 [Left,Top] [Right,Bottom] 二、点击与长按API 返回值API描述booleanclick()点击对象booleanclickAndWaitForNewWindow(lang timeout)点击对象,等待新窗口出现,参数为等待超长时间booleancli…

linux系统存储文件系统,Linux文件系统的深入分析

【IT168 技术】本人很喜欢Linux,在工作中也很喜欢总结关于Linux文件系统的经验,下面就这个问题来详细说说吧。Linux支持多种文件系统,包括ext2、iso9660、jffs、ext3、vfat、ntfs、romfs和nfs等,为了对各类文件系统进行统一管理&a…

Path Sum I, II

简单题 I Given a binary tree and a sum, determine if the tree has a root-to-leaf path such that adding up all the values along the path equals the given sum. For example:Given the below binary tree and sum 22, 5/ \4 8/ / \11 13 4/ \ \7 2 …

【Python】进程和多进程的使用

原文作者:我辈李想 版权声明:文章原创,转载时请务必加上原文超链接、作者信息和本声明。 文章目录 前言一、进程1.概念理解2.进程的启动3.python进程 二、多进程 前言 进程是指计算机中正在运行的程序实例。 进程可以是操作系统分配的&#…

linux 设置dns缓存周期,如何解决DNS缓存时间问题

理想情况下,各地DNS的缓存时间即为设置的ttl时间,所以可以通过设置ttl时间来控制DNS缓存的时间。ttl时间设置的短,DNS缓存过期快,在机器故障的时候很快切换,对用户的影响小;但是由于ttl设置的太短&#xff…

linux wifi pro6818,GEC6818连接Ubuntu,下载程序至开发板

windows下使用tftp工具下载文件到开发板(linux)1.下载tftp工具,也可以上CSDN找个免费0积分的 http://www.52z.com/soft/11886.html 2.确保开发板和windows在同一网段 比如192.168.101.*段 ...stm32串口烧写程序到开发板前言:我们如果要断电后重启板子还能使用…

表单-图片浏览上传-单选框(二)

一、图片浏览上传 1、依然【table】标签包含&#xff0c; 2、【input】包含了【type】等于【file】。 <table border"1" align"center"><tr><td>图片上传</td><td><input type"file"</td></tr><…

linux吉祥物的名字,知道Linux的吉祥物的名字和性别吗

知道Linux的吉祥物的名字和性别吗发布时间:2007-07-01 16:52:17来源:红联作者:PiOsnoae今天收到了这期的Linux Gazette&#xff0c;才知道原来Linux吉祥物还有一个名字叫Tux(英文直接翻译过来是男士无尾半正式晚礼服&#xff0c;倒是和这个小企鹅的打扮很配)。它是一位男式&…

android WebView总结

浏览器控件是每一个开发环境都具备的&#xff0c;这为马甲神功提供了用武之地。windows的有webbrowser&#xff0c;android和ios都有webview。仅仅是其引擎不同&#xff0c;相对于微软的webbrowser。android及ios的webview的引擎都是webkit&#xff0c;对Html5提供支持。本篇主…

c语言大数倍数,leetcode-1346(检查整数及其两倍数是否存在)--C语言实现

求&#xff1a;给你一个整数数组 arr&#xff0c;请你检查是否存在两个整数 N 和 M&#xff0c;满足 N 是 M 的两倍(即&#xff0c;N 2 * M)。更正式地&#xff0c;检查是否存在两个下标 i 和 j 满足&#xff1a;i ! j0 < i, j < arr.lengtharr[i] 2 * arr[j]示例 1&am…

LeetCode 4 Median of Two Sorted Arrays

There are two sorted arrays nums1 and nums2 of size m and n respectively. Find the median of the two sorted arrays. The overall run time complexity should be O(log (mn)). 题目很简单&#xff0c;比较两数组当前指针指向的值&#xff0c;选择小的添加到新数组&…

Windows消息传递机制详解

Windows是一个消息&#xff08;Message&#xff09;驱动系统。Windows的消息提供了应用程序之间、应用程序与Windows系统之间进行通信的手段。应用程序想要实现的功能由消息来触发&#xff0c;并且靠对消息的响应和处理来完成。必须注意的是&#xff0c;消息并非是抢占性的&…

c语言求树上节点的双亲,用非递归算法求二叉树叶子结点的c语言代码怎样写?...

递归算法&#xff1a;是一种直接或者间接地调用自身的算法。在计算机编写程序中&#xff0c;递归算法对解决一大类问题是十分有效的&#xff0c;它往往使算法的描述简洁而且易于理解。递归算法的特点递归过程一般通过函数或子过程来实现。递归算法&#xff1a;在函数或子过程的…

质数之和c语言编程,C程序检查一个数字是否可以表示为两个质数之和

C程序检查一个数字是否可以表示为两个质数之和在此示例中&#xff0c;您将学习检查用户输入的整数是否可以表示为所有可能组合的两个质数之和。要理解此示例&#xff0c;您应该了解以下C语言编程主题&#xff1a;为了完成此任务&#xff0c;我们将创建一个名为checkPrime()的函…

第二次冲刺阶段 站立会议09

昨天做了什么&#xff1a;昨天把程序进行了整合 今天要做什么&#xff1a;今天我们的项目大体完成了&#xff0c;进行最后一次的测试 遇到的困难&#xff1a;整个项目整合在一起后&#xff0c;运行起来有点卡转载于:https://www.cnblogs.com/yuanyajiao/p/4575945.html

uoj #118. 【UR #8】赴京赶考 水题

#118. 【UR #8】赴京赶考 Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://uoj.ac/problem/118 Description 高中&#xff0c;高中&#xff0c;短暂的三年。NOI是高中结业考试&#xff0c;而高考在每年暑假举行。高二暑假&#xff0c;这是你最后一次参加高考的机会。…