网络子系统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;
}
时间: 2025-01-30 13:36:46

网络子系统85_inet协议族-l3向上的相关文章

网络子系统79_inet协议族

// inet协议族默认支持的协议类型 // 在inet_init中,通过inet_register_protosw注册到inetsw邻接表 1.1 static struct inet_protosw inetsw_array[] = { //流类型 { .type = SOCK_STREAM, .protocol = IPPROTO_TCP, .prot = &tcp_prot, .ops = &inet_stream_ops, .no_check = 0, .flags = INET

网络子系统86_inet协议族-l4向下(一)

// l4数据向下l3传递 // 步骤: // 1.如果sock->sk_write_queue为空,初始化corking // 1.1 corking信息用于帮助ip层对数据进行分片 1.1 int ip_append_data(struct sock *sk, struct flowi4 *fl4, int getfrag(void *from, char *to, int offset, int len, int odd, struct sk_buff *skb), void *from,

网络子系统80_inet协议族-SOCK_RAW(一)

// SOCK_RAW 1.1 static struct inet_protosw inetsw_array[] = { ... { .type = SOCK_RAW, .protocol = IPPROTO_IP, /* 通配符 */ .prot = &raw_prot, /* Networking protocol blocks attached to sockets */ .ops = &inet_sockraw_ops, .no_check = UDP_CSUM_DEFAULT,

网络子系统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(&

网络子系统81_inet协议族-SOCK_RAW(二)

// struct sock->sk_prot字段 // struct proto为插口层到传输层的接口 4.1 struct proto raw_prot = { .name = "RAW", .owner = THIS_MODULE, .close = raw_close, .destroy = raw_destroy, .connect = ip4_datagram_connect, .disconnect = udp_disconnect, .ioctl = raw_io

网络子系统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

网络子系统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            

网络子系统46_ip协议数据帧的转发

// ip协议数据转发 // ip_forward以回调函数的形式,保存在skb->dst->input,skb->dst在ip_route_input路由封包时被设置 // 调用路径:ip_rcv->ip_rcv_finish->dst_input->(skb->dst->input) // 函数的主要任务: // 1.递减ttl // 2.如果路由被重定向,则向发送方发送icmp重定向报文 // 2.如果有选项,通过ip_forward_options处