Kernel Source片段 -- 收包(3)2層處理以及進入協議棧前

kernel version:2.6.32.61

對於沒有自己實現poll的驅動,統一使用的是process_backlog, 這個函數會取出處於CPU隊列中的包,然後執行netif_receive_skb。

這裏需要注意的是,對於CPU隊列操作時,需要關閉中斷,因爲這個隊列是共享的。

net/core/dev.c

2725 static int process_backlog(struct napi_struct *napi, int quota)
2726 {
2727         int work = 0;
2728         struct softnet_data *queue = &__get_cpu_var(softnet_data);
2729         unsigned long start_time = jiffies;
2730 
2731         napi->weight = weight_p;
2732         do {
2733                 struct sk_buff *skb;
2734 
// 出隊列前關閉中斷
2735                 local_irq_disable();
2736                 skb = __skb_dequeue(&queue->input_pkt_queue);
2737                 if (!skb) {
2738                         __napi_complete(napi);
2739                         local_irq_enable();
2740                         break;
2741                 }
2742                 local_irq_enable();
2743 
2744                 netif_receive_skb(skb);
2745         } while (++work < quota && jiffies == start_time);
2746 
2747         return work;
2748 }


netif_receive_skb函數主要處理的是在進入三層協議棧之前的動作,包括入口QoS,網橋等處理,最後進入三層協議棧。
net/core/dev.c

2304 int netif_receive_skb(struct sk_buff *skb)
2305 {          
2306         struct packet_type *ptype, *pt_prev;
2307         struct net_device *orig_dev;
2308         struct net_device *null_or_orig;
2309         int ret = NET_RX_DROP;
2310         __be16 type;
2311 
2312         if (!skb->tstamp.tv64)
2313                 net_timestamp(skb);
2314 
2315         if (skb->vlan_tci && vlan_hwaccel_do_receive(skb))
2316                 return NET_RX_SUCCESS;
2317 
2318         /* if we've gotten here through NAPI, check netpoll */
2319         if (netpoll_receive_skb(skb))
2320                 return NET_RX_DROP;
2321    
2322         if (!skb->iif)
2323                 skb->iif = skb->dev->ifindex;
2324 
2325         null_or_orig = NULL;
2326         orig_dev = skb->dev;
2327         if (orig_dev->master) {
2328                 if (skb_bond_should_drop(skb))
2329                         null_or_orig = orig_dev; /* deliver only exact match */
2330                 else
2331                         skb->dev = orig_dev->master;
2332         }
2333 
2334         __get_cpu_var(netdev_rx_stat).total++;
2335 
2336         skb_reset_network_header(skb);
2337         skb_reset_transport_header(skb);
2338         skb->mac_len = skb->network_header - skb->mac_header;
2339 
2340         pt_prev = NULL;
2341 
2342         rcu_read_lock();
2343 
// 入口QoS處理
2344 #ifdef CONFIG_NET_CLS_ACT
2345         if (skb->tc_verd & TC_NCLS) {
2346                 skb->tc_verd = CLR_TC_NCLS(skb->tc_verd);
2347                 goto ncls;
2348         }
2349 #endif
2350 
2351         list_for_each_entry_rcu(ptype, &ptype_all, list) {
2352                 if (ptype->dev == null_or_orig || ptype->dev == skb->dev ||
2353                     ptype->dev == orig_dev) {
2354                         if (pt_prev)
2355                                 ret = deliver_skb(skb, pt_prev, orig_dev);
2356                         pt_prev = ptype;
2357                 }
2358         }
2359 
2360 #ifdef CONFIG_NET_CLS_ACT
2361         skb = handle_ing(skb, &pt_prev, &ret, orig_dev);
2362         if (!skb)
2363                 goto out;
2364 ncls:
2365 #endif
2366 
// 網橋處理
2367         skb = handle_bridge(skb, &pt_prev, &ret, orig_dev);
2368         if (!skb)
2369                 goto out;
2370         skb = handle_macvlan(skb, &pt_prev, &ret, orig_dev);
2371         if (!skb)
2372                 goto out;
2373 
2374         type = skb->protocol;
2375         list_for_each_entry_rcu(ptype,
2376                         &ptype_base[ntohs(type) & PTYPE_HASH_MASK], list) {
2377                 if (ptype->type == type &&
2378                     (ptype->dev == null_or_orig || ptype->dev == skb->dev ||
2379                      ptype->dev == orig_dev)) {
2380                         if (pt_prev)
2381                                 ret = deliver_skb(skb, pt_prev, orig_dev);
2382                         pt_prev = ptype;
2383                 }
2384         }
2385 
2386         if (pt_prev) {
// 進入三層協議棧
2387                 ret = pt_prev->func(skb, skb->dev, pt_prev, orig_dev);
2388         } else {
2389                 kfree_skb(skb);
2390                 /* Jamal, now you will not able to escape explaining
2391                  * me how you were going to use this. :-)
2392                  */
2393                 ret = NET_RX_DROP;
2394         }
2395 
2396 out:
2397         rcu_read_unlock();
2398         return ret;
2399 }


發佈了64 篇原創文章 · 獲贊 9 · 訪問量 30萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章