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 }


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值