linux下的tcpip协议栈部分代码意义(1)

两种调用接口:
1、用户进程进行网络调用,通过系统特有的网络调用接口进入内核,在内核中,进一步调用sys_socketcall()结束该过程,在sys_socketcall()中会根据网络系统调用号调用具体的功能。
2、另一种系统调用接口是通过普通文件操作来访问网络子系统。虽然有很多操作是网络专用的,但套接口的输入输出可以被当成典型的文件读写操作来进行。
2、协议无关接口
Linux使用socket来描述套接口,代表通信链路的一端,存储与该链路有关的所有信息。

每一个进程都会实例化一个socket。
Socket结构:/include/linux/net.h
sk指向与该套接口相关的传输控制块,传输层使用传输控制块存放套接口需要的信息。比如各种协议相关函数的指针。TCP、UDP、RAW
ops指向特定的传输协议的操作集接口,不同协议族不同。proto_ops结构中定义的接口函数是从套接口系统调用到传输层调用的入口,因此其成员与socket系统调用基本上是一一对应的。整个proto_ops结构就是一张套接口系统调用的跳转表,其中的某些操作会继续调用proto结构跳转表中的函数,从而进入具体的传输层或网络层的处理。
套接口缓存
保存在进程和网络接口之间相互传递的用户数据,以及其他的一些信息。
SKB定义:include/linux/skbuff.h
SKB操作函数:net/core/skbuff.c
1、SKB的组织
struct sk_buff*next;
struct sk_buff*prev;
内核把sk_buff组织成为双向链表,为了每个SKB能被头部快速找到,在第一个SKB节点的前面会插入另一个辅助的sk_buff_head结构的头结点。
struct sk_buff_head {
/* These two members must be first. */
struct sk_buff*next;
struct sk_buff*prev;


__u32qlen;//SKB链表的节点数,队列长度
spinlock_tlock;//对链表并发操作需要自旋锁
};
2.数据存储相关
struct sock*sk;
SKB的宿主传输控制块。SKB在由本地产生或者本地接收的时候才有效。当SKB在2层或者3层转发的时候,没有意义,NULL。
unsigned intlen,mac_len,data_len
len:SKB中数据部分的长度。Mac_len:以太帧首部长度
data_len:SG类型和FRAGLIST类型聚合分散I/O存储区中的数据长度。
atomic_tusers;
引用计数,标识有多少个实体在使用SKB,以此来确定释放SKB的时机。
unsigned inttruesize;
SKB的实际长度,包括SKB描述符和数据缓存区的长度。如果申请了一个len字节的缓存区,alloc_skb()会将truesize初始化成len+sizeof(sk_buff)
unsigned char*head,*data,*tail,*end;
发送数据时,每一层协议会在head与data之间填充协议首部。
3.通用的成员变量
struct skb_timevaltstamp;
接收时间戳或者发送时间戳,一般通过netif_receive_skb()调用net_timestamp()进行设置
struct net_device*dev;
网络设备指针,该字段的设置与SKB是发送包还是接收包有关。在初始化网络设备驱动的时候会分配接受缓存队列,将该指针指向接收到数据包的网络设备。
发送数据包时这个字段的设置要复杂的多,见后面。
Linux支持虚拟网络设备,dev可能会指向虚拟网络设备。数据包在输入或者输出的时候dev的指针可能会在包处理过程中被改变。
struct net_device*input_dev;
接收报文最原始的设备,本地生成为NULL。
Union{}h、union{}nh、union{}mac
分别指向四层、三层、二层协议的首部,联合体内表示能解析的协议。
报文从二层向三层传递时指针的变化:
发送报文的时候需要为报文加上首部。
struct  dst_entry*dst;
目的路由缓存项。不管是输入还是输出的数据包,都需要经过路由子系统的查询得到目的路由缓存项之后,才能确定数据包的流向。
charcb[48];
SKB信息控制块,用于每层协议私有信息存储空间。
union {
__wsumcsum;
__u32csum_offset;
};
ip_summed
当数据包是一个输入包时,skb->csum表示的是当前数据包的4层的checksum值,skb->ip_summed表示的是四层校验的状态,下面的几个宏定义表示了设备驱动传递给4层的一些信息(通过ip_sumed),这里要注意,一旦当四层接受了这个包,他可能会改变ip_summed的值。
$define CHECKSUM_NONE 0  $
define CHECKSUM_UNNECESSARY 2  
$define CHECKSUM_COMPLETE 3
Checksum的验证有两个步骤:第一个是计算校验和,第二个是验证,和报文中的校验和字段作比较,看是否相等。
CHECKSUM_NONE表示csum域中的校验值是错误的,也就是校验失败。
出现这种情况的原因:硬件不支持,应该由软件来计算校验和。
CHECKSUM_UNNECESSARY表示网卡已经计算和验证了四层的头和校验值。出现这种状态的原因:真的计算和验证了;或者是回环报文,出错概率很低,因此无需验证。
CHECKSUM_COMPLETE表示nic已经计算了4层头的校验,并且csum已经被赋值,此时4层的接收者只需要加伪头并验证校验结果。


当数据包是输出包时的情况,这时候使用csum_offset。表示硬件网卡存放将要计算的校验值的地址。这个时候ip_summed可以被用户设置为:
$define CHECKSUM_PARTIAL 1
表示由硬件来计算校验和。常见的情况:NAT
__u8pkt_type:3,
帧类型,分类是由二层的目的地址来决定的。
__be16protocol;

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值