zoukankan      html  css  js  c++  java
  • 网卡的包是怎么处理

    网卡的包是怎么处理的?

    在一个CPU上收包,然后多个CPU负责收包

    我的机器上的网卡中断都绑定在了CPU1上,注意是:

     查看中断号: cat /proc/interrupts

    /proc/irq/<中断号>/smp_affinity

    /proc/irq/<中断号>/smp_affinity_list

    也就是说中断全部来自于CPU1,通过perf抓的数据包显示都是来自于CPU1,到这里还都是硬中断过程

    irq/35-iwlwifi   502 [001]  6699.127356: net:netif_receive_skb: dev=wlp4s0 skbaddr=0xffff88005e245000 len=52
                      91a46d __netif_receive_skb_core (/usr/lib/debug/boot/vmlinux-4.4.0-21-generic)
                      91ab28 __netif_receive_skb (/usr/lib/debug/boot/vmlinux-4.4.0-21-generic)
                      91aba2 netif_receive_skb_internal (/usr/lib/debug/boot/vmlinux-4.4.0-21-generic)
                      91b823 napi_gro_receive (/usr/lib/debug/boot/vmlinux-4.4.0-21-generic)
                       24572 ieee80211_deliver_skb ([mac80211])
                       26879 ieee80211_rx_handlers ([mac80211])
                       28203 ieee80211_prepare_and_rx_handle ([mac80211])
                       28ddd ieee80211_rx_napi ([mac80211])
                        f7d6 iwl_mvm_rx_rx_mpdu ([iwlmvm])
                        a3a8 iwl_mvm_rx ([iwlmvm])
                        73bf iwl_pcie_rx_handle ([iwlwifi])
                        8787 iwl_pcie_irq_handler ([iwlwifi])
                      2dbae0 irq_thread_fn (/usr/lib/debug/boot/vmlinux-4.4.0-21-generic)
                      2dbe28 irq_thread (/usr/lib/debug/boot/vmlinux-4.4.0-21-generic)
                      2a0528 kthread (/usr/lib/debug/boot/vmlinux-4.4.0-21-generic)
                      a2488f ret_from_fork (/usr/lib/debug/boot/vmlinux-4.4.0-21-generic)

    上面的栈是软中断处理流程,【咋感觉开启中断线程化了呢】,无所谓了,好像linux内核从2.6开始就开启了中断线程化,但是无所了,反正也是绑核操作了【中断耗时部分被从中断中分离出来放到了软中断中去做,现在中断也被分离,整个硬件中断就比较轻量级了,实时进程有福了,中断进程的优先级咋计算?不会一直被占用的吧,处理中断程序时还关中断么?
    【中断会不会被调度到其他的核上去执行?】答:不会的;被调度的只有进程,中断并不是进程上下文,只会如hard code一般在特定的CPU上执行【对于中断线程化的场景,线程也是绑定到特定的CPU的,不会跳到其他的CPU上去执行】

    那问题来了,我上面抓到的这个栈应该是中断上下文了【并不是软中断上下文,那参考书的资料都是有误的么...】

    网络收包处理过程中,哪些是硬中断哪些是软中断?

    http://blog.yufeng.info/archives/2037

    储霸的文章,不明觉厉。

    上面是我无线网卡的情形,感觉无线网卡和有线网卡的抓包情形不太相同,索性看下有线网卡抓包的情况

    swapper     0 [001] 14639.534928: net:netif_receive_skb: dev=enp0s25 skbaddr=0xffff88005e047700 len=84
                      91a46d __netif_receive_skb_core (/usr/lib/debug/boot/vmlinux-4.4.0-21-generic)
                      91ab28 __netif_receive_skb (/usr/lib/debug/boot/vmlinux-4.4.0-21-generic)
                      91aba2 netif_receive_skb_internal (/usr/lib/debug/boot/vmlinux-4.4.0-21-generic)
                      91b823 napi_gro_receive (/usr/lib/debug/boot/vmlinux-4.4.0-21-generic)
                       15e86 e1000_receive_skb ([e1000e])
                       17b20 e1000_clean_rx_irq ([e1000e])
                       1efac e1000e_poll ([e1000e])
                      91b06e net_rx_action (/usr/lib/debug/boot/vmlinux-4.4.0-21-generic)
                      2859a1 __do_softirq (/usr/lib/debug/boot/vmlinux-4.4.0-21-generic)
                      285ca3 irq_exit (/usr/lib/debug/boot/vmlinux-4.4.0-21-generic)
                      a26ee4 do_IRQ (/usr/lib/debug/boot/vmlinux-4.4.0-21-generic)
                      a24fc2 ret_from_intr (/usr/lib/debug/boot/vmlinux-4.4.0-21-generic)
                      8bbbc7 cpuidle_enter (/usr/lib/debug/boot/vmlinux-4.4.0-21-generic)
                      2c3d52 call_cpuidle (/usr/lib/debug/boot/vmlinux-4.4.0-21-generic)
                      2c4010 cpu_startup_entry (/usr/lib/debug/boot/vmlinux-4.4.0-21-generic)
                      2516f4 start_secondary (/usr/lib/debug/boot/vmlinux-4.4.0-21-generic)

    swapper     0 [001] 14640.534883: net:netif_receive_skb: dev=enp0s25 skbaddr=0xffff8800474fcf00 len=84

         在这里把包交给了上层协议
                      91a46d __netif_receive_skb_core (/usr/lib/debug/boot/vmlinux-4.4.0-21-generic)
                      91ab28 __netif_receive_skb (/usr/lib/debug/boot/vmlinux-4.4.0-21-generic)
                      91aba2 netif_receive_skb_internal (/usr/lib/debug/boot/vmlinux-4.4.0-21-generic)
                      91b823 napi_gro_receive (/usr/lib/debug/jboot/vmlinux-4.4.0-21-generic)
                       15e86 e1000_receive_skb ([e1000e])
                       17b20 e1000_clean_rx_irq ([e1000e]) 该函数中说明了如何从e1000_ring中如何取出内存然后初始化成skb的,skb第一次出现也是在这里
                       1efac e1000e_poll ([e1000e])
                      91b06e net_rx_action (/usr/lib/debug/boot/vmlinux-4.4.0-21-generic)
                      2859a1 __do_softirq (/usr/lib/debug/boot/vmlinux-4.4.0-21-generic)
                      285ca3 irq_exit (/usr/lib/debug/boot/vmlinux-4.4.0-21-generic)
                      a26ee4 do_IRQ (/usr/lib/debug/boot/vmlinux-4.4.0-21-generic)
                      a24fc2 ret_from_intr (/usr/lib/debug/boot/vmlinux-4.4.0-21-generic)
                      8bbbc7 cpuidle_enter (/usr/lib/debug/boot/vmlinux-4.4.0-21-generic)
                      2c3d52 call_cpuidle (/usr/lib/debug/boot/vmlinux-4.4.0-21-generic)
                      2c4010 cpu_startup_entry (/usr/lib/debug/boot/vmlinux-4.4.0-21-generic)
                      2516f4 start_secondary (/usr/lib/debug/boot/vmlinux-4.4.0-21-generic)
    有线网卡就比较像教科书上说的那样了

    那么这里我们知道了,硬件中断完成的啥东西,硬件中断负责把网络数据拷贝到驱动的一块内存中去,然后软件中断就不断从内存中去读数据;

    看下rps机制是如何负载均衡数据包的.

    skb中为啥会有queue_map信息?一个RPS/RFS是说为了说应用在哪个CPU核上我就把这个数据包放在哪个CPU上,如何判断?端口号是个不错的选择?系统中肯定存在端口号和进程号的映射,如果是我,我会查看这个信息

    这篇文章中提到:驱动其实是不识别网络包中的元组信息

    这是为什么?因为简单低端网卡硬件不识别网络流,即它只能识别到这是一个数据包,
    而不能识别到数据包的元组信息。如果一个数据流的第一个数据包被分发到了CPU1,
    而第二个数据包分发到了CPU2,那么对于流的公共数据,比如nf_conntrack中记录的东西,
    CPU cache的利用率就会比较低,cache抖动会比较厉害。
    对于TCP流而言,可能还会因为TCP串行包并行处理的延迟不确定性导致数据包乱序。
    因此最直接的想法就是将属于一个流的所有数据包分发了一个CPU上。

     要知道,Linux的RPS特性是google人员引入的,他们的目标在于提升服务器的处理效率。因此他们着重考虑了以下的信息:
    哪个CPU在为这个数据流提供服务;
    哪个CPU被接收了该流数据包的网卡所中断;
    哪个CPU运行处理该流数据包的软中断。
    理想情况,为了达到CPU cache的高效利用,上面的三个CPU应该是同一个CPU。而原生RPS实现就是这个目的。当然,为了这个目的,内核中不得不维护一个”流表“,里面记录了上面三类CPU信息。这个流表并不是真正的基于元组的流表,而是仅仅记录上述CPU信息的表。

    __skb_get_hash

     741 /** 
     742  * __skb_get_hash: calculate a flow hash
     743  * @skb: sk_buff to calculate flow hash from
     744  *
     745  * This function calculates a flow hash based on src/dst addresses
     746  * and src/dst port numbers.  Sets hash in skb to non-zero hash value
     747  * on success, zero indicates no valid hash.  Also, sets l4_hash in skb
     748  * if hash is a canonical 4-tuple hash over transport ports.
     749  */
     750 void __skb_get_hash(struct sk_buff *skb)
     751 {
     752     struct flow_keys keys;
     753     u32 hash;
     754 
     755     __flow_hash_secret_init();
     756 
     757     hash = ___skb_get_hash(skb, &keys, hashrnd);
     758 
     759     __skb_set_sw_hash(skb, hash, flow_keys_have_l4(&keys));
     760 }
     761 EXPORT_SYMBOL(__skb_get_hash);
    
  • 相关阅读:
    MT【305】丹德林双球
    MT【304】反射路径长度比
    MT【303】估计
    MT【302】利用值域宽度求范围
    MT【301】值域宽度
    MT【300】余弦的三倍角公式
    MT【299】对数型数列不等式
    MT【298】双参数非齐次
    xadmin 自定义actions
    xadmin 添加自定义权限
  • 原文地址:https://www.cnblogs.com/honpey/p/8763483.html
Copyright © 2011-2022 走看看