网络子系统49_ip协议报头id选取

//more = skb_shinfo(skb)->tso_segs,由tcp传递
1.1 static inline void ip_select_ident_more(struct iphdr *iph, struct dst_entry *dst, struct sock *sk, int more)
{
	if (iph->frag_off & htons(IP_DF)) {//禁止分片
		if (sk && inet_sk(sk)->daddr) {
			iph->id = htons(inet_sk(sk)->id);//使用sock中指定的id
			inet_sk(sk)->id += 1 + more;//sock中id递增
		} else
			iph->id = 0;
	} else
		__ip_select_ident(iph, dst, more);//可分片ip报文选择id
}
//调用路径ip_select_ident_more->__ip_select_ident
//函数主要任务:
//	1.处理路由项与inet_peer的绑定
//	2.通过inet_peer,或者全局ip_fallback_id获取id
1.2 void __ip_select_ident(struct iphdr *iph, struct dst_entry *dst, int more)
{
	struct rtable *rt = (struct rtable *) dst;

	if (rt) {//存在到目的地址的路由
		if (rt->peer == NULL)//inet_peer结构,表示该缓存路由项的目的ip地址对应的主机
			rt_bind_peer(rt, 1);//寻找和该端点相匹配的inet_peer结构,如果不存在,尝试创建一个新的inet_peer

		if (rt->peer) {//通过inet_peer的计数器,生成与接收方相关的递增id
			iph->id = htons(inet_getid(rt->peer, more));
			return;
		}
	} else
		printk(KERN_DEBUG "rt_bind_peer(0) @%p\n", NET_CALLER(iph));
	//之前尝试都失败,通过一个静态变量ip_fallback_id,再和端点的目的地ip地址结合,通过secure_ip_id获取id
	ip_select_fb_ident(iph);
}

//调用路径ip_select_ident_more->__ip_select_ident->inet_getid
1.3 static inline __u16	inet_getid(struct inet_peer *p, int more)
{
	__u16 id;

	spin_lock_bh(&inet_peer_idlock);//获取一个全局的锁
	id = p->ip_id_count;
	p->ip_id_count += 1 + more;//更新inet_peer中的id计数器
	spin_unlock_bh(&inet_peer_idlock);
	return id;
}
时间: 2024-09-02 10:52:52

网络子系统49_ip协议报头id选取的相关文章

网络子系统48_ip协议数据帧的发送

//ip协议与l4协议接口,l4通过此接口向下l3传递数据帧 //函数主要任务: // 1.通过路由子系统路由封包 // 2.填充l3报头 // 3.ip分片 // 4.计算校验和 // 5.衔接邻居子系统,向下层传送封包. 1.1 int ip_queue_xmit(struct sk_buff *skb, int ipfragok) { struct sock *sk = skb->sk; struct inet_sock *inet = inet_sk(sk); struct ip_opt

网络子系统42_ip协议数据帧的接收

//参考 深入理解linux网络技术内幕                                      // 注册l3协议 // ptype_all链表,链接所有ETH_P_ALL类型的l3协议 // ptype_base哈希表,非ETH_P_ALL类型的l3协议 // 注:l3协议可以使用相同的协议号 1.1 void dev_add_pack(struct packet_type *pt) { int hash; //ptype_all ptype_base共用一把锁 ptype

网络子系统56_ip协议分片重组_重组分片

//调用路径ip_defrag->ip_frag_reasm // 所有ip分片都被接收到时,重组ip数据包 // 判断ip所有分片都接收到的条件: // 1.FIRST_IN, LAST_IN // 2.meat = len,即 根据offset推断出的最大封包长度等于已接收到的封包长度 // 重组过程: // 1.将sk_buff链表从ipq->fragments取下 // 2.将第一个分片以后的分片挂在第一个分片的frag_list域 // 3.从分片子系统使用内存中减去该ip数据包的内

网络子系统36_BPDU协议格式

//参考 深入理解linux网络技术内幕 //通过以太网帧的目的地址,判断一个数据帧是否为bpdu数据帧 //1.BPDU封装格式:                                          //2.区分BPDU类型为CONFIG还是TCN,CONFIG类型的BPDU封包长38字节,TCN类型的BPDU封包长度为7字节 //由上图,越过以太网帧头6+6+2+3(llc头),之后为bpdu协议内容,偏移量为3的一个字节,指示封包为CONFIG或TCN            

网络子系统85_inet协议族-l3向上

// ip数据报向本地传递 // 调用路径:ip_rcv->dst_input->...->ip_local_deliver 1.1 int ip_local_deliver(struct sk_buff *skb) { //如果ip数据报被分片,则重组 if (ip_is_fragment(ip_hdr(skb))) { if (ip_defrag(skb, IP_DEFRAG_LOCAL_DELIVER)) return 0; } //通过hook点,向上传递 return NF_H

网络子系统82_inet协议族-SOCK_RAW(三)

// 向raw sock传递skb // 步骤: // 1.根据协议号获取监听指定protocol的sock // 2.向raw sock传递skb 1.1 int raw_local_deliver(struct sk_buff *skb, int protocol) { int hash; struct sock *raw_sk; //获取监听指定协议的raw sock hash = protocol & (RAW_HTABLE_SIZE - 1); raw_sk = sk_head(&

网络子系统54_ip协议分片重组_定位ipq

// 为分片确定正确的ipq结构 // 通过5元组定位ipq,成功后,递增ipq引用计数,返回ipq // 定位5元组 // 1.<id, 源ip, 目的ip, l4协议> 可通过ip报文获取 // 2.user 通过ip_defrag给出,指出重组是由谁发起的,最常见的时IP_DEFRAG_LOCAL_DELIVER,当重组的入口分包要传递给本地时 // ipq中所有分片最迟完成重组的时间为30HZ 1.1 static inline struct ipq *ip_find(struct i

网络子系统44_ip协议源路由选项处理

//skb->pkt_type根据l2地址设置,在eth_type_trans(由驱动调用)中,如果数据帧的目的l2地址为接收接口的l2地址,设置为PACKET_HOST //skb->rt->rt_type根据l3地址设置,在ip_route_input(由ip协议调用)中,如果数据帧的目的l3地址为本机配置的l3地址,设置为RTN_LOCAL //调用路径ip_rcv->ip_rcv_finish->ip_options_rcv_srr // 1.skb->dst非

网络子系统45_ip协议tos处理

//ip报头tos字段,一个字节 // 二进制位:[0 1 2] [3] [4] [5] [6] [7] // 1.[0 1 2] 表示优先级: // 000 路由 // 001 优先级 // 010 立即 // 011 火速 // 100 火速覆盖 // 101 紧急 // 110 互联网控制 // 111 网络控制 // 2.[3] 表示时延 // 0 普通 // 1 最小 // 3.[4] 吞吐量 // 0 普通 // 1 最大 // 4.[5] 可靠性 // 0 普通 // 1.最大 /