设备收发包之netif_receive_skb
在设备驱动收包之后,会通过netif_receive_skb将收取的包,按照注册的协议回调,传递到上层进行处理;
1 /* 将skb传递到上层 */ 2 static int __netif_receive_skb_core(struct sk_buff *skb, bool pfmemalloc) 3 { 4 struct packet_type *ptype, *pt_prev; 5 rx_handler_func_t *rx_handler; 6 struct net_device *orig_dev; 7 bool deliver_exact = false; 8 int ret = NET_RX_DROP; 9 __be16 type; 10 11 /* 记录收包时间,netdev_tstamp_prequeue为0,表示可能有包延迟 */ 12 net_timestamp_check(!netdev_tstamp_prequeue, skb); 13 14 trace_netif_receive_skb(skb); 15 16 /* 记录收包设备 */ 17 orig_dev = skb->dev; 18 19 /* 重置各层头部 */ 20 skb_reset_network_header(skb); 21 if (!skb_transport_header_was_set(skb)) 22 skb_reset_transport_header(skb); 23 skb_reset_mac_len(skb); 24 25 /* 26 留下一个节点,最后一次向上层传递时, 27 不需要在inc引用,回调中会free 28 这样相当于少调用了一次free 29 */ 30 pt_prev = NULL; 31 32 another_round: 33 34 /* 接收设备索引号 */ 35 skb->skb_iif = skb->dev->ifindex; 36 37 /* 处理包数统计 */ 38 __this_cpu_inc(softnet_data.processed); 39 40 /* vlan包,则去掉vlan头 */ 41 if (skb->protocol == cpu_to_be16(ETH_P_8021Q) || 42 skb->protocol == cpu_to_be16(ETH_P_8021AD)) { 43 44 /* 45 这里改了三层协议,protocol指向ip等 46 another_round不会再走这里 47 */ 48 skb = skb_vlan_untag(skb); 49 if (unlikely(!skb)) 50 goto out; 51 } 52 53 /* 不对数据包进行分类 */ 54 if (skb_skip_tc_classify(skb)) 55 goto skip_classify; 56 57 /* prmemalloc */ 58 if (pfmemalloc) 59 goto skip_taps; 60 61 62 /* 下面两个是未(指定)设备的所有协议传递的上层传递 */ 63 64 65 /* 如抓包程序未指定设备 */ 66 /* 进行未指定设备的全局链表对应协议的skb上层传递 */ 67 list_for_each_entry_rcu(ptype, &ptype_all, list) { 68 if (pt_prev) 69 ret = deliver_skb(skb, pt_prev, orig_dev); 70 pt_prev = ptype; 71 } 72 73 /* 如抓包程序指定了设备 */ 74 /* 进行指定设备的协议链表的skb上层传递 */ 75 list_for_each_entry_rcu(ptype, &skb->dev->ptype_all, list) { 76 if (pt_prev) 77 ret = deliver_skb(skb, pt_prev, orig_dev); 78 pt_prev = ptype; 79 } 80 81 skip_taps: 82 #ifdef CONFIG_NET_INGRESS 83 if (static_key_false(&ingress_needed)) { 84 skb = sch_handle_ingress(skb, &pt_prev, &ret, orig_dev); 85 if (!skb) 86 goto out; 87 88 if (nf_ingress(skb, &pt_prev, &ret, orig_dev) < 0) 89 goto out; 90 } 91 #endif 92 skb_reset_tc(skb); 93 skip_classify: 94 95 /* 不支持使用pfmemalloc */ 96 if (pfmemalloc && !skb_pfmemalloc_protocol(skb)) 97 goto drop; 98 99 /* 如果是vlan包 */ 100 if (skb_vlan_tag_present(skb)) { 101 /* 处理prev */ 102 if (pt_prev) { 103 ret = deliver_skb(skb, pt_prev, orig_dev); 104 pt_prev = NULL; 105 } 106 107 /* 根据实际的vlan设备调整信息,再走一遍 */ 108 if (vlan_do_receive(&skb)) 109 goto another_round; 110 else if (unlikely(!skb)) 111 goto out; 112 } 113 114 /* 如果有注册handler,那么调用,比如网桥模块 */ 115 rx_handler = rcu_dereference(skb->dev->rx_handler); 116 if (rx_handler) { 117 if (pt_prev) { 118 ret = deliver_skb(skb, pt_prev, orig_dev); 119 pt_prev = NULL; 120 } 121 switch (rx_handler(&skb)) { 122 /* 已处理,无需进一步处理 */ 123 case RX_HANDLER_CONSUMED: 124 ret = NET_RX_SUCCESS; 125 goto out; 126 /* 修改了skb->dev,在处理一次 */ 127 case RX_HANDLER_ANOTHER: 128 goto another_round; 129 /* 精确传递到ptype->dev == skb->dev */ 130 case RX_HANDLER_EXACT: 131 deliver_exact = true; 132 /* 正常传递即可 */ 133 case RX_HANDLER_PASS: 134 break; 135 default: 136 BUG(); 137 } 138 } 139 140 /* 还有vlan标记,说明找不到vlanid对应的设备 */ 141 if (unlikely(skb_vlan_tag_present(skb))) { 142 /* 存在vlanid,则判定是到其他设备的包 */ 143 if (skb_vlan_tag_get_id(skb)) 144 skb->pkt_type = PACKET_OTHERHOST; 145 /* Note: we might in the future use prio bits 146 * and set skb->priority like in vlan_do_receive() 147 * For the time being, just ignore Priority Code Point 148 */ 149 skb->vlan_tci = 0; 150 } 151 152 /* 设置三层协议,下面提交都是按照三层协议提交的 */ 153 type = skb->protocol; 154 155 /* deliver only exact match when indicated */ 156 /* 未设置精确发送,则向未指定设备的指定协议全局发送一份 */ 157 if (likely(!deliver_exact)) { 158 deliver_ptype_list_skb(skb, &pt_prev, orig_dev, type, 159 &ptype_base[ntohs(type) & 160 PTYPE_HASH_MASK]); 161 } 162 163 /* 指定设备的,向原设备上层传递 */ 164 deliver_ptype_list_skb(skb, &pt_prev, orig_dev, type, 165 &orig_dev->ptype_specific); 166 167 /* 当前设备与原设备不同,向当前设备传递 */ 168 if (unlikely(skb->dev != orig_dev)) { 169 deliver_ptype_list_skb(skb, &pt_prev, orig_dev, type, 170 &skb->dev->ptype_specific); 171 } 172 173 if (pt_prev) { 174 if (unlikely(skb_orphan_frags(skb, GFP_ATOMIC))) 175 goto drop; 176 else 177 /* 178 使用pt_prev这里就不需要deliver_skb来inc应用数了 179 func执行内部会free,减少了一次skb_free 180 */ 181 /* 传递到上层*/ 182 ret = pt_prev->func(skb, skb->dev, pt_prev, orig_dev); 183 } else { 184 drop: 185 if (!deliver_exact) 186 atomic_long_inc(&skb->dev->rx_dropped); 187 else 188 atomic_long_inc(&skb->dev->rx_nohandler); 189 kfree_skb(skb); 190 /* Jamal, now you will not able to escape explaining 191 * me how you were going to use this. :-) 192 */ 193 ret = NET_RX_DROP; 194 } 195 196 out: 197 return ret; 198 }