Skip to content

Commit

Permalink
Merge branch 'flow_dissector-dissect-tunnel-info'
Browse files Browse the repository at this point in the history
Simon Horman says:

====================
flow_dissector: dissect tunnel info

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: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed Oct 2, 2017
2 parents 0929567 + a38402b commit 08e2091
Show file tree
Hide file tree
Showing 3 changed files with 103 additions and 27 deletions.
5 changes: 3 additions & 2 deletions include/net/dst_metadata.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ struct metadata_dst {
} u;
};

static inline struct metadata_dst *skb_metadata_dst(struct sk_buff *skb)
static inline struct metadata_dst *skb_metadata_dst(const struct sk_buff *skb)
{
struct metadata_dst *md_dst = (struct metadata_dst *) skb_dst(skb);

Expand All @@ -34,7 +34,8 @@ static inline struct metadata_dst *skb_metadata_dst(struct sk_buff *skb)
return NULL;
}

static inline struct ip_tunnel_info *skb_tunnel_info(struct sk_buff *skb)
static inline struct ip_tunnel_info *
skb_tunnel_info(const struct sk_buff *skb)
{
struct metadata_dst *md_dst = skb_metadata_dst(skb);
struct dst_entry *dst;
Expand Down
100 changes: 100 additions & 0 deletions net/core/flow_dissector.c
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down Expand Up @@ -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;

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,
Expand Down Expand Up @@ -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);
Expand Down
25 changes: 0 additions & 25 deletions net/sched/cls_flower.c
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down

0 comments on commit 08e2091

Please sign in to comment.