對於沒有自己實現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 }