Skip to content
  • Pablo Neira's avatar
    netfilter: add netfilter ingress hook after handle_ing() under unique static key · e687ad60
    Pablo Neira authored
    
    
    This patch adds the Netfilter ingress hook just after the existing tc ingress
    hook, that seems to be the consensus solution for this.
    
    Note that the Netfilter hook resides under the global static key that enables
    ingress filtering. Nonetheless, Netfilter still also has its own static key for
    minimal impact on the existing handle_ing().
    
    * Without this patch:
    
    Result: OK: 6216490(c6216338+d152) usec, 100000000 (60byte,0frags)
      16086246pps 7721Mb/sec (7721398080bps) errors: 100000000
    
        42.46%  kpktgend_0   [kernel.kallsyms]   [k] __netif_receive_skb_core
        25.92%  kpktgend_0   [kernel.kallsyms]   [k] kfree_skb
         7.81%  kpktgend_0   [pktgen]            [k] pktgen_thread_worker
         5.62%  kpktgend_0   [kernel.kallsyms]   [k] ip_rcv
         2.70%  kpktgend_0   [kernel.kallsyms]   [k] netif_receive_skb_internal
         2.34%  kpktgend_0   [kernel.kallsyms]   [k] netif_receive_skb_sk
         1.44%  kpktgend_0   [kernel.kallsyms]   [k] __build_skb
    
    * With this patch:
    
    Result: OK: 6214833(c6214731+d101) usec, 100000000 (60byte,0frags)
      16090536pps 7723Mb/sec (7723457280bps) errors: 100000000
    
        41.23%  kpktgend_0      [kernel.kallsyms]  [k] __netif_receive_skb_core
        26.57%  kpktgend_0      [kernel.kallsyms]  [k] kfree_skb
         7.72%  kpktgend_0      [pktgen]           [k] pktgen_thread_worker
         5.55%  kpktgend_0      [kernel.kallsyms]  [k] ip_rcv
         2.78%  kpktgend_0      [kernel.kallsyms]  [k] netif_receive_skb_internal
         2.06%  kpktgend_0      [kernel.kallsyms]  [k] netif_receive_skb_sk
         1.43%  kpktgend_0      [kernel.kallsyms]  [k] __build_skb
    
    * Without this patch + tc ingress:
    
            tc filter add dev eth4 parent ffff: protocol ip prio 1 \
                    u32 match ip dst 4.3.2.1/32
    
    Result: OK: 9269001(c9268821+d179) usec, 100000000 (60byte,0frags)
      10788648pps 5178Mb/sec (5178551040bps) errors: 100000000
    
        40.99%  kpktgend_0   [kernel.kallsyms]  [k] __netif_receive_skb_core
        17.50%  kpktgend_0   [kernel.kallsyms]  [k] kfree_skb
        11.77%  kpktgend_0   [cls_u32]          [k] u32_classify
         5.62%  kpktgend_0   [kernel.kallsyms]  [k] tc_classify_compat
         5.18%  kpktgend_0   [pktgen]           [k] pktgen_thread_worker
         3.23%  kpktgend_0   [kernel.kallsyms]  [k] tc_classify
         2.97%  kpktgend_0   [kernel.kallsyms]  [k] ip_rcv
         1.83%  kpktgend_0   [kernel.kallsyms]  [k] netif_receive_skb_internal
         1.50%  kpktgend_0   [kernel.kallsyms]  [k] netif_receive_skb_sk
         0.99%  kpktgend_0   [kernel.kallsyms]  [k] __build_skb
    
    * With this patch + tc ingress:
    
            tc filter add dev eth4 parent ffff: protocol ip prio 1 \
                    u32 match ip dst 4.3.2.1/32
    
    Result: OK: 9308218(c9308091+d126) usec, 100000000 (60byte,0frags)
      10743194pps 5156Mb/sec (5156733120bps) errors: 100000000
    
        42.01%  kpktgend_0   [kernel.kallsyms]   [k] __netif_receive_skb_core
        17.78%  kpktgend_0   [kernel.kallsyms]   [k] kfree_skb
        11.70%  kpktgend_0   [cls_u32]           [k] u32_classify
         5.46%  kpktgend_0   [kernel.kallsyms]   [k] tc_classify_compat
         5.16%  kpktgend_0   [pktgen]            [k] pktgen_thread_worker
         2.98%  kpktgend_0   [kernel.kallsyms]   [k] ip_rcv
         2.84%  kpktgend_0   [kernel.kallsyms]   [k] tc_classify
         1.96%  kpktgend_0   [kernel.kallsyms]   [k] netif_receive_skb_internal
         1.57%  kpktgend_0   [kernel.kallsyms]   [k] netif_receive_skb_sk
    
    Note that the results are very similar before and after.
    
    I can see gcc gets the code under the ingress static key out of the hot path.
    Then, on that cold branch, it generates the code to accomodate the netfilter
    ingress static key. My explanation for this is that this reduces the pressure
    on the instruction cache for non-users as the new code is out of the hot path,
    and it comes with minimal impact for tc ingress users.
    
    Using gcc version 4.8.4 on:
    
    Architecture:          x86_64
    CPU op-mode(s):        32-bit, 64-bit
    Byte Order:            Little Endian
    CPU(s):                8
    [...]
    L1d cache:             16K
    L1i cache:             64K
    L2 cache:              2048K
    L3 cache:              8192K
    
    Signed-off-by: default avatarPablo Neira Ayuso <pablo@netfilter.org>
    Acked-by: default avatarAlexei Starovoitov <ast@plumgrid.com>
    Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
    e687ad60