閱讀724 返回首頁    go 阿裏雲 go 技術社區[雲棲]


網絡子係統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_HOOK(NFPROTO_IPV4, NF_INET_LOCAL_IN, skb, skb->dev, NULL,
		       ip_local_deliver_finish);
}


//	ip數據報向本地傳遞
//	步驟:
//		1.向raw套接字傳遞一份skb
//		2.根據ip報頭的協議號在inet_protos中找到l4協議
//		3.調用l4協議處理函數
1.2 static int ip_local_deliver_finish(struct sk_buff *skb)
{
	struct net *net = dev_net(skb->dev);

	//使skb有足夠的ip報頭
	__skb_pull(skb, ip_hdrlen(skb));

	//使指針指向ip報文內容
	skb_reset_transport_header(skb);

	rcu_read_lock();
	{
		int protocol = ip_hdr(skb)->protocol;
		const struct net_protocol *ipprot;
		int raw;

	resubmit:
		//向raw套接字傳遞
		raw = raw_local_deliver(skb, protocol);

		//通過l4協議號查找上層協議
		//在inet_init中,通過inet_add_protocol注冊l4協議到inet_protos數組
		ipprot = rcu_dereference(inet_protos[protocol]);
		if (ipprot != NULL) {
			int ret;

			//l4協議處理函數
			ret = ipprot->handler(skb);
			if (ret < 0) {
				protocol = -ret;
				goto resubmit;
			}
			//snmp統計
			IP_INC_STATS_BH(net, IPSTATS_MIB_INDELIVERS);
		}
		...
	}
 out:
	rcu_read_unlock();

	return 0;
}

最後更新:2017-04-03 12:55:18

  上一篇:go 最長不下降子序列 jobdu 1112
  下一篇:go C# 數字格式化 ToString