这里需要注意的是,对于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 }