在設備驅動收包之后,會通過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 }