lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite for Android: free password hash cracker in your pocket
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date:   Mon, 2 Oct 2017 12:36:33 -0700
From:   Tom Herbert <tom@...bertland.com>
To:     Simon Horman <simon.horman@...ronome.com>
Cc:     David Miller <davem@...emloft.net>, Jiri Pirko <jiri@...lanox.com>,
        Jamal Hadi Salim <jhs@...atatu.com>,
        Cong Wang <xiyou.wangcong@...il.com>,
        Linux Kernel Network Developers <netdev@...r.kernel.org>,
        oss-drivers@...ronome.com
Subject: Re: [PATCH net-next 2/2] flow_dissector: dissect tunnel info

On Mon, Oct 2, 2017 at 1:41 AM, Simon Horman <simon.horman@...ronome.com> wrote:
> Move dissection of tunnel info from the flower classifier to the flow
> dissector where all other dissection occurs.  This should not have any
> behavioural affect on other users of the flow dissector.
>
> Signed-off-by: Simon Horman <simon.horman@...ronome.com>
> Reviewed-by: Jakub Kicinski <jakub.kicinski@...ronome.com>
> ---
>  net/core/flow_dissector.c | 100 ++++++++++++++++++++++++++++++++++++++++++++++
>  net/sched/cls_flower.c    |  25 ------------
>  2 files changed, 100 insertions(+), 25 deletions(-)
>
> diff --git a/net/core/flow_dissector.c b/net/core/flow_dissector.c
> index 0a977373d003..1f5caafb4492 100644
> --- a/net/core/flow_dissector.c
> +++ b/net/core/flow_dissector.c
> @@ -5,6 +5,7 @@
>  #include <linux/ipv6.h>
>  #include <linux/if_vlan.h>
>  #include <net/dsa.h>
> +#include <net/dst_metadata.h>
>  #include <net/ip.h>
>  #include <net/ipv6.h>
>  #include <net/gre.h>
> @@ -115,6 +116,102 @@ __be32 __skb_flow_get_ports(const struct sk_buff *skb, int thoff, u8 ip_proto,
>  }
>  EXPORT_SYMBOL(__skb_flow_get_ports);
>
> +static void
> +skb_flow_dissect_set_enc_addr_type(enum flow_dissector_key_id type,
> +                                  struct flow_dissector *flow_dissector,
> +                                  void *target_container)
> +{
> +       struct flow_dissector_key_control *ctrl;
> +
> +       if (!dissector_uses_key(flow_dissector, FLOW_DISSECTOR_KEY_ENC_CONTROL))
> +               return;
> +
> +       ctrl = skb_flow_dissector_target(flow_dissector,
> +                                        FLOW_DISSECTOR_KEY_ENC_CONTROL,
> +                                        target_container);
> +       ctrl->addr_type = type;
> +}
> +
> +static void
> +__skb_flow_dissect_tunnel_info(const struct sk_buff *skb,
> +                              struct flow_dissector *flow_dissector,
> +                              void *target_container)
> +{
> +       struct ip_tunnel_info *info;
> +       struct ip_tunnel_key *key;
> +
> +       /* A quick check to see if there might be something to do. */
> +       if (!dissector_uses_key(flow_dissector,
> +                               FLOW_DISSECTOR_KEY_ENC_KEYID) &&
> +           !dissector_uses_key(flow_dissector,
> +                               FLOW_DISSECTOR_KEY_ENC_IPV4_ADDRS) &&
> +           !dissector_uses_key(flow_dissector,
> +                               FLOW_DISSECTOR_KEY_ENC_IPV6_ADDRS) &&
> +           !dissector_uses_key(flow_dissector,
> +                               FLOW_DISSECTOR_KEY_ENC_CONTROL) &&
> +           !dissector_uses_key(flow_dissector,
> +                               FLOW_DISSECTOR_KEY_ENC_PORTS))
> +               return;

This complex conditional is now in the path of every call to flow
dissector regardless of whether a classifier is enabled or tunnels
are. What does the assembly show in terms of number of branches? Can
we at least get this down to one check (might be a use case for
FLOW_DISSECTOR_F_FLOWER ;-) ), or even better use the static key when
encap or is enabled?

> +
> +       info = skb_tunnel_info(skb);
> +       if (!info)
> +               return;
> +
> +       key = &info->key;
> +
> +       switch (ip_tunnel_info_af(info)) {
> +       case AF_INET:
> +               skb_flow_dissect_set_enc_addr_type(FLOW_DISSECTOR_KEY_IPV4_ADDRS,
> +                                                  flow_dissector,
> +                                                  target_container);
> +               if (dissector_uses_key(flow_dissector,
> +                                      FLOW_DISSECTOR_KEY_ENC_IPV4_ADDRS)) {
> +                       struct flow_dissector_key_ipv4_addrs *ipv4;
> +
> +                       ipv4 = skb_flow_dissector_target(flow_dissector,
> +                                                        FLOW_DISSECTOR_KEY_ENC_IPV4_ADDRS,
> +                                                        target_container);
> +                       ipv4->src = key->u.ipv4.src;
> +                       ipv4->dst = key->u.ipv4.dst;
> +               }
> +               break;
> +       case AF_INET6:
> +               skb_flow_dissect_set_enc_addr_type(FLOW_DISSECTOR_KEY_IPV6_ADDRS,
> +                                                  flow_dissector,
> +                                                  target_container);
> +               if (dissector_uses_key(flow_dissector,
> +                                      FLOW_DISSECTOR_KEY_ENC_IPV6_ADDRS)) {
> +                       struct flow_dissector_key_ipv6_addrs *ipv6;
> +
> +                       ipv6 = skb_flow_dissector_target(flow_dissector,
> +                                                        FLOW_DISSECTOR_KEY_ENC_IPV6_ADDRS,
> +                                                        target_container);
> +                       ipv6->src = key->u.ipv6.src;
> +                       ipv6->dst = key->u.ipv6.dst;
> +               }
> +               break;
> +       }
> +
> +       if (dissector_uses_key(flow_dissector, FLOW_DISSECTOR_KEY_ENC_KEYID)) {
> +               struct flow_dissector_key_keyid *keyid;
> +
> +               keyid = skb_flow_dissector_target(flow_dissector,
> +                                                 FLOW_DISSECTOR_KEY_ENC_KEYID,
> +                                                 target_container);
> +               keyid->keyid = tunnel_id_to_key32(key->tun_id);
> +       }
> +
> +       if (dissector_uses_key(flow_dissector, FLOW_DISSECTOR_KEY_ENC_PORTS)) {
> +               struct flow_dissector_key_ports *tp;
> +
> +               tp = skb_flow_dissector_target(flow_dissector,
> +                                              FLOW_DISSECTOR_KEY_ENC_PORTS,
> +                                              target_container);
> +               tp->src = key->tp_src;
> +               tp->dst = key->tp_dst;
> +       }
> +}
> +
>  static enum flow_dissect_ret
>  __skb_flow_dissect_mpls(const struct sk_buff *skb,
>                         struct flow_dissector *flow_dissector,
> @@ -478,6 +575,9 @@ bool __skb_flow_dissect(const struct sk_buff *skb,
>                                               FLOW_DISSECTOR_KEY_BASIC,
>                                               target_container);
>
> +       __skb_flow_dissect_tunnel_info(skb, flow_dissector,
> +                                      target_container);
> +
>         if (dissector_uses_key(flow_dissector,
>                                FLOW_DISSECTOR_KEY_ETH_ADDRS)) {
>                 struct ethhdr *eth = eth_hdr(skb);
> diff --git a/net/sched/cls_flower.c b/net/sched/cls_flower.c
> index d230cb4c8094..db831ac708f6 100644
> --- a/net/sched/cls_flower.c
> +++ b/net/sched/cls_flower.c
> @@ -152,37 +152,12 @@ static int fl_classify(struct sk_buff *skb, const struct tcf_proto *tp,
>         struct cls_fl_filter *f;
>         struct fl_flow_key skb_key;
>         struct fl_flow_key skb_mkey;
> -       struct ip_tunnel_info *info;
>
>         if (!atomic_read(&head->ht.nelems))
>                 return -1;
>
>         fl_clear_masked_range(&skb_key, &head->mask);
>
> -       info = skb_tunnel_info(skb);
> -       if (info) {
> -               struct ip_tunnel_key *key = &info->key;
> -
> -               switch (ip_tunnel_info_af(info)) {
> -               case AF_INET:
> -                       skb_key.enc_control.addr_type =
> -                               FLOW_DISSECTOR_KEY_IPV4_ADDRS;
> -                       skb_key.enc_ipv4.src = key->u.ipv4.src;
> -                       skb_key.enc_ipv4.dst = key->u.ipv4.dst;
> -                       break;
> -               case AF_INET6:
> -                       skb_key.enc_control.addr_type =
> -                               FLOW_DISSECTOR_KEY_IPV6_ADDRS;
> -                       skb_key.enc_ipv6.src = key->u.ipv6.src;
> -                       skb_key.enc_ipv6.dst = key->u.ipv6.dst;
> -                       break;
> -               }
> -
> -               skb_key.enc_key_id.keyid = tunnel_id_to_key32(key->tun_id);
> -               skb_key.enc_tp.src = key->tp_src;
> -               skb_key.enc_tp.dst = key->tp_dst;
> -       }
> -
>         skb_key.indev_ifindex = skb->skb_iif;
>         /* skb_flow_dissect() does not set n_proto in case an unknown protocol,
>          * so do it rather here.
> --
> 2.1.4
>

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ