Linuxのポーリング処理のコードを読んでみよう 〜netif_receive_skb編〜
Linuxのポーリング処理のコードを読んでみよう 〜ポーリング編〜 - かーねる・う゛いえむにっきの続き。
e1000_clean()が呼んでいたnetif_receive_skb()の中の処理を見ていく。
2960 int netif_receive_skb(struct sk_buff *skb) 2961 { 2962 if (netdev_tstamp_prequeue) 2963 net_timestamp_check(skb); 2964 2965 if (skb_defer_rx_timestamp(skb)) 2966 return NET_RX_SUCCESS; 2967 2968 #ifdef CONFIG_RPS 2969 { 2970 struct rps_dev_flow voidflow, *rflow = &voidflow; 2971 int cpu, ret; 2972 2973 rcu_read_lock(); 2974 2975 cpu = get_rps_cpu(skb->dev, skb, &rflow); 2976 2977 if (cpu >= 0) { 2978 ret = enqueue_to_backlog(skb, cpu, &rflow->last_qtail); 2979 rcu_read_unlock(); 2980 } else { 2981 rcu_read_unlock(); 2982 ret = __netif_receive_skb(skb); 2983 } 2984 2985 return ret; 2986 } 2987 #else 2988 return __netif_receive_skb(skb); 2989 #endif 2990 } 2991 EXPORT_SYMBOL(netif_receive_skb);
なにやら#ifdef CONFIG_RPSとあるが、これはこの記事で書いたRPSのコードである。
RPSが有効な場合は、get_rps_cpu()でキュー先のCPUを決め、cpuidが0でなければ enqueue_to_backlog()でキューイングを行う。
cpuidが0なら今ポーリングを行っているCPUであるはずだから、__netif_receive_skb()を呼び出してこの場でパケット処理を行う。
(としか読めないのだが、cpu == 0が必ずポーリングを実行しているCPUという仮定はどっから来てるんだろう…)
RPSが無効なら、常に__netif_receive_skb()を呼び出しこの場でパケット処理を行う。
で、こちらが__netif_receive_skb()のコード。
2817 static int __netif_receive_skb(struct sk_buff *skb) 2818 { 2819 struct packet_type *ptype, *pt_prev; 2820 rx_handler_func_t *rx_handler; 2821 struct net_device *orig_dev; 2822 struct net_device *master; 2823 struct net_device *null_or_orig; 2824 struct net_device *orig_or_bond; 2825 int ret = NET_RX_DROP; 2826 __be16 type; 2827 2828 if (!netdev_tstamp_prequeue) 2829 net_timestamp_check(skb); 2830 2831 if (vlan_tx_tag_present(skb) && vlan_hwaccel_do_receive(skb)) 2832 return NET_RX_SUCCESS; 2833 2834 /* if we've gotten here through NAPI, check netpoll */ 2835 if (netpoll_receive_skb(skb)) 2836 return NET_RX_DROP; 2837 2838 if (!skb->skb_iif) 2839 skb->skb_iif = skb->dev->ifindex; 2840 2841 /* 2842 * bonding note: skbs received on inactive slaves should only 2843 * be delivered to pkt handlers that are exact matches. Also 2844 * the deliver_no_wcard flag will be set. If packet handlers 2845 * are sensitive to duplicate packets these skbs will need to 2846 * be dropped at the handler. The vlan accel path may have 2847 * already set the deliver_no_wcard flag. 2848 */ 2849 null_or_orig = NULL; 2850 orig_dev = skb->dev; 2851 master = ACCESS_ONCE(orig_dev->master); 2852 if (skb->deliver_no_wcard) 2853 null_or_orig = orig_dev; 2854 else if (master) { 2855 if (skb_bond_should_drop(skb, master)) { 2856 skb->deliver_no_wcard = 1; 2857 null_or_orig = orig_dev; /* deliver only exact match */ 2858 } else 2859 skb->dev = master; 2860 } 2861 2862 __this_cpu_inc(softnet_data.processed); 2863 skb_reset_network_header(skb); 2864 skb_reset_transport_header(skb); 2865 skb->mac_len = skb->network_header - skb->mac_header; 2866 2867 pt_prev = NULL; 2868 2869 rcu_read_lock(); 2870 2871 #ifdef CONFIG_NET_CLS_ACT 2872 if (skb->tc_verd & TC_NCLS) { 2873 skb->tc_verd = CLR_TC_NCLS(skb->tc_verd); 2874 goto ncls; 2875 } 2876 #endif 2877 2878 list_for_each_entry_rcu(ptype, &ptype_all, list) { 2879 if (ptype->dev == null_or_orig || ptype->dev == skb->dev || 2880 ptype->dev == orig_dev) { 2881 if (pt_prev) 2882 ret = deliver_skb(skb, pt_prev, orig_dev); 2883 pt_prev = ptype; 2884 } 2885 } 2886 2887 #ifdef CONFIG_NET_CLS_ACT 2888 skb = handle_ing(skb, &pt_prev, &ret, orig_dev); 2889 if (!skb) 2890 goto out; 2891 ncls: 2892 #endif 2893 2894 /* Handle special case of bridge or macvlan */ 2895 rx_handler = rcu_dereference(skb->dev->rx_handler); 2896 if (rx_handler) { 2897 if (pt_prev) { 2898 ret = deliver_skb(skb, pt_prev, orig_dev); 2899 pt_prev = NULL; 2900 } 2901 skb = rx_handler(skb); 2902 if (!skb) 2903 goto out; 2904 } 2905 2906 /* 2907 * Make sure frames received on VLAN interfaces stacked on 2908 * bonding interfaces still make their way to any base bonding 2909 * device that may have registered for a specific ptype. The 2910 * handler may have to adjust skb->dev and orig_dev. 2911 */ 2912 orig_or_bond = orig_dev; 2913 if ((skb->dev->priv_flags & IFF_802_1Q_VLAN) && 2914 (vlan_dev_real_dev(skb->dev)->priv_flags & IFF_BONDING)) { 2915 orig_or_bond = vlan_dev_real_dev(skb->dev); 2916 } 2917 2918 type = skb->protocol; 2919 list_for_each_entry_rcu(ptype, 2920 &ptype_base[ntohs(type) & PTYPE_HASH_MASK], list) { 2921 if (ptype->type == type && (ptype->dev == null_or_orig || 2922 ptype->dev == skb->dev || ptype->dev == orig_dev || 2923 ptype->dev == orig_or_bond)) { 2924 if (pt_prev) 2925 ret = deliver_skb(skb, pt_prev, orig_dev); 2926 pt_prev = ptype; 2927 } 2928 } 2929 2930 if (pt_prev) { 2931 ret = pt_prev->func(skb, skb->dev, pt_prev, orig_dev); 2932 } else { 2933 kfree_skb(skb); 2934 /* Jamal, now you will not able to escape explaining 2935 * me how you were going to use this. :-) 2936 */ 2937 ret = NET_RX_DROP; 2938 } 2939 2940 out: 2941 rcu_read_unlock(); 2942 return ret; 2943 }
コードがこんがらがっててわっかりにくいけど、多分2918行目でパケットのプロトコル番号を取得し、続く2919行目でptype_base[]から対応するハンドラを取り出し、deliver_skb()経由でpt_prev->func()を呼び出しているのだと推測される。
2614 static inline int deliver_skb(struct sk_buff *skb, 2615 struct packet_type *pt_prev, 2616 struct net_device *orig_dev) 2617 { 2618 atomic_inc(&skb->users); 2619 return pt_prev->func(skb, skb->dev, pt_prev, orig_dev); 2620 }
では、このptype_base[]とpt_prev->funcとは何か、を調べてみる。
374 /** 375 * dev_add_pack - add packet handler 376 * @pt: packet type declaration 377 * 378 * Add a protocol handler to the networking stack. The passed &packet_type 379 * is linked into kernel lists and may not be freed until it has been 380 * removed from the kernel lists. 381 * 382 * This call does not sleep therefore it can not 383 * guarantee all CPU's that are in middle of receiving packets 384 * will see the new packet type (until the next received packet). 385 */ 386 387 void dev_add_pack(struct packet_type *pt) 388 { 389 int hash; 390 391 spin_lock_bh(&ptype_lock); 392 if (pt->type == htons(ETH_P_ALL)) 393 list_add_rcu(&pt->list, &ptype_all); 394 else { 395 hash = ntohs(pt->type) & PTYPE_HASH_MASK; 396 list_add_rcu(&pt->list, &ptype_base[hash]); 397 } 398 spin_unlock_bh(&ptype_lock); 399 } 400 EXPORT_SYMBOL(dev_add_pack);
ptype_base[]を触ってるコードを探してみるとdev_add_pack()が見つかる。
コメントを読むとadd packet handlerと書いてあって、パケットハンドラを登録する関数だという事がわかる。
ではコレを呼んでるコードはどこにあるんだろうとfxrで調べてみると、34個も表示されて、ああ、色んなプロトコルをサポートしているのだなぁと気づく。
まぁ、ここは素のIPv4じゃないすかね、って事でnet/ipv4/af_inet.cを見てみよう。
dev_add_pack()はinet_init()の最後の方で呼ばれている。
1720 dev_add_pack(&ip_packet_type);
引数にip_packet_typeを取っている。
1606 static struct packet_type ip_packet_type __read_mostly = { 1607 .type = cpu_to_be16(ETH_P_IP), 1608 .func = ip_rcv, 1609 .gso_send_check = inet_gso_send_check, 1610 .gso_segment = inet_gso_segment, 1611 .gro_receive = inet_gro_receive, 1612 .gro_complete = inet_gro_complete, 1613 };
これを見ると、ip_packet_type.funcはip_rcv()である事がわかる。
他の関数はGSOって言ってるのでオフロード関連のコードの筈。
typeは恐らく普通にプロトコル番号でしょう。
という事で、pt_prev->func()を呼ぶとip_rcv()が呼ばれる事が分かった。