diff options
author | David S. Miller <davem@davemloft.net> | 2018-02-06 17:32:49 +0100 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2018-02-06 17:32:49 +0100 |
commit | 67ae44e1a6238531a2f324a30b6524d228df3131 (patch) | |
tree | 9f6a56f4d4d7226b735237e1e99510d2ac194b75 | |
parent | cls_u32: fix use after free in u32_destroy_key() (diff) | |
parent | sample/bpf: fix erspan metadata (diff) | |
download | linux-67ae44e1a6238531a2f324a30b6524d228df3131.tar.xz linux-67ae44e1a6238531a2f324a30b6524d228df3131.zip |
Merge branch 'net-erspan-fixes'
William Tu says:
====================
net: erspan fixes
The first patch fixes erspan metadata extraction issue from packet
header due to commit d350a823020e ("net: erspan: create erspan metadata
uapi header"). The commit moves the erspan 'version' in
'struct erspan_metadata' in front of 'struct erspan_md2' for later
extensibility, but breaks the existing metadata extraction code due
to extra 4-byte size 'version'. The second patch fixes the case where
tunnel device receives an erspan packet with different tunnel metadata
(ex: version, index, hwid, direction), existing code overwrites the
tunnel device's erspan configuration. The third patch fixes the bpf
tests due to the above patches.
====================
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | include/net/erspan.h | 26 | ||||
-rw-r--r-- | net/ipv4/ip_gre.c | 14 | ||||
-rw-r--r-- | net/ipv6/ip6_gre.c | 15 | ||||
-rw-r--r-- | samples/bpf/tcbpf2_kern.c | 41 | ||||
-rwxr-xr-x | samples/bpf/test_tunnel_bpf.sh | 4 |
5 files changed, 39 insertions, 61 deletions
diff --git a/include/net/erspan.h b/include/net/erspan.h index 5daa4866412b..d044aa60cc76 100644 --- a/include/net/erspan.h +++ b/include/net/erspan.h @@ -159,13 +159,13 @@ static inline void erspan_build_header(struct sk_buff *skb, struct ethhdr *eth = (struct ethhdr *)skb->data; enum erspan_encap_type enc_type; struct erspan_base_hdr *ershdr; - struct erspan_metadata *ersmd; struct qtag_prefix { __be16 eth_type; __be16 tci; } *qp; u16 vlan_tci = 0; u8 tos; + __be32 *idx; tos = is_ipv4 ? ip_hdr(skb)->tos : (ipv6_hdr(skb)->priority << 4) + @@ -195,8 +195,8 @@ static inline void erspan_build_header(struct sk_buff *skb, set_session_id(ershdr, id); /* Build metadata */ - ersmd = (struct erspan_metadata *)(ershdr + 1); - ersmd->u.index = htonl(index & INDEX_MASK); + idx = (__be32 *)(ershdr + 1); + *idx = htonl(index & INDEX_MASK); } /* ERSPAN GRA: timestamp granularity @@ -225,7 +225,7 @@ static inline void erspan_build_header_v2(struct sk_buff *skb, { struct ethhdr *eth = (struct ethhdr *)skb->data; struct erspan_base_hdr *ershdr; - struct erspan_metadata *md; + struct erspan_md2 *md2; struct qtag_prefix { __be16 eth_type; __be16 tci; @@ -261,15 +261,15 @@ static inline void erspan_build_header_v2(struct sk_buff *skb, set_session_id(ershdr, id); /* Build metadata */ - md = (struct erspan_metadata *)(ershdr + 1); - md->u.md2.timestamp = erspan_get_timestamp(); - md->u.md2.sgt = htons(sgt); - md->u.md2.p = 1; - md->u.md2.ft = 0; - md->u.md2.dir = direction; - md->u.md2.gra = gra; - md->u.md2.o = 0; - set_hwid(&md->u.md2, hwid); + md2 = (struct erspan_md2 *)(ershdr + 1); + md2->timestamp = erspan_get_timestamp(); + md2->sgt = htons(sgt); + md2->p = 1; + md2->ft = 0; + md2->dir = direction; + md2->gra = gra; + md2->o = 0; + set_hwid(md2, hwid); } #endif diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c index 6ec670fbbbdd..45d97e9b2759 100644 --- a/net/ipv4/ip_gre.c +++ b/net/ipv4/ip_gre.c @@ -261,6 +261,7 @@ static int erspan_rcv(struct sk_buff *skb, struct tnl_ptk_info *tpi, struct ip_tunnel_net *itn; struct ip_tunnel *tunnel; const struct iphdr *iph; + struct erspan_md2 *md2; int ver; int len; @@ -313,21 +314,14 @@ static int erspan_rcv(struct sk_buff *skb, struct tnl_ptk_info *tpi, return PACKET_REJECT; md = ip_tunnel_info_opts(&tun_dst->u.tun_info); - memcpy(md, pkt_md, sizeof(*md)); md->version = ver; + md2 = &md->u.md2; + memcpy(md2, pkt_md, ver == 1 ? ERSPAN_V1_MDSIZE : + ERSPAN_V2_MDSIZE); info = &tun_dst->u.tun_info; info->key.tun_flags |= TUNNEL_ERSPAN_OPT; info->options_len = sizeof(*md); - } else { - tunnel->erspan_ver = ver; - if (ver == 1) { - tunnel->index = ntohl(pkt_md->u.index); - } else { - tunnel->dir = pkt_md->u.md2.dir; - tunnel->hwid = get_hwid(&pkt_md->u.md2); - } - } skb_reset_mac_header(skb); diff --git a/net/ipv6/ip6_gre.c b/net/ipv6/ip6_gre.c index 05f070e123e4..3c353125546d 100644 --- a/net/ipv6/ip6_gre.c +++ b/net/ipv6/ip6_gre.c @@ -505,6 +505,7 @@ static int ip6erspan_rcv(struct sk_buff *skb, int gre_hdr_len, struct erspan_base_hdr *ershdr; struct erspan_metadata *pkt_md; const struct ipv6hdr *ipv6h; + struct erspan_md2 *md2; struct ip6_tnl *tunnel; u8 ver; @@ -551,24 +552,16 @@ static int ip6erspan_rcv(struct sk_buff *skb, int gre_hdr_len, info = &tun_dst->u.tun_info; md = ip_tunnel_info_opts(info); - - memcpy(md, pkt_md, sizeof(*md)); md->version = ver; + md2 = &md->u.md2; + memcpy(md2, pkt_md, ver == 1 ? ERSPAN_V1_MDSIZE : + ERSPAN_V2_MDSIZE); info->key.tun_flags |= TUNNEL_ERSPAN_OPT; info->options_len = sizeof(*md); ip6_tnl_rcv(tunnel, skb, tpi, tun_dst, log_ecn_error); } else { - tunnel->parms.erspan_ver = ver; - - if (ver == 1) { - tunnel->parms.index = ntohl(pkt_md->u.index); - } else { - tunnel->parms.dir = pkt_md->u.md2.dir; - tunnel->parms.hwid = get_hwid(&pkt_md->u.md2); - } - ip6_tnl_rcv(tunnel, skb, tpi, NULL, log_ecn_error); } diff --git a/samples/bpf/tcbpf2_kern.c b/samples/bpf/tcbpf2_kern.c index f6bbf8f50da3..efdc16d195ff 100644 --- a/samples/bpf/tcbpf2_kern.c +++ b/samples/bpf/tcbpf2_kern.c @@ -15,6 +15,7 @@ #include <uapi/linux/tcp.h> #include <uapi/linux/filter.h> #include <uapi/linux/pkt_cls.h> +#include <uapi/linux/erspan.h> #include <net/ipv6.h> #include "bpf_helpers.h" #include "bpf_endian.h" @@ -35,24 +36,10 @@ struct geneve_opt { u8 opt_data[8]; /* hard-coded to 8 byte */ }; -struct erspan_md2 { - __be32 timestamp; - __be16 sgt; - __be16 flags; -}; - struct vxlan_metadata { u32 gbp; }; -struct erspan_metadata { - union { - __be32 index; - struct erspan_md2 md2; - } u; - int version; -}; - SEC("gre_set_tunnel") int _gre_set_tunnel(struct __sk_buff *skb) { @@ -156,13 +143,15 @@ int _erspan_set_tunnel(struct __sk_buff *skb) __builtin_memset(&md, 0, sizeof(md)); #ifdef ERSPAN_V1 md.version = 1; - md.u.index = htonl(123); + md.u.index = bpf_htonl(123); #else u8 direction = 1; - u16 hwid = 7; + u8 hwid = 7; md.version = 2; - md.u.md2.flags = htons((direction << 3) | (hwid << 4)); + md.u.md2.dir = direction; + md.u.md2.hwid = hwid & 0xf; + md.u.md2.hwid_upper = (hwid >> 4) & 0x3; #endif ret = bpf_skb_set_tunnel_opt(skb, &md, sizeof(md)); @@ -207,9 +196,9 @@ int _erspan_get_tunnel(struct __sk_buff *skb) char fmt2[] = "\tdirection %d hwid %x timestamp %u\n"; bpf_trace_printk(fmt2, sizeof(fmt2), - (ntohs(md.u.md2.flags) >> 3) & 0x1, - (ntohs(md.u.md2.flags) >> 4) & 0x3f, - bpf_ntohl(md.u.md2.timestamp)); + md.u.md2.dir, + (md.u.md2.hwid_upper << 4) + md.u.md2.hwid, + bpf_ntohl(md.u.md2.timestamp)); #endif return TC_ACT_OK; @@ -242,10 +231,12 @@ int _ip4ip6erspan_set_tunnel(struct __sk_buff *skb) md.version = 1; #else u8 direction = 0; - u16 hwid = 17; + u8 hwid = 17; md.version = 2; - md.u.md2.flags = htons((direction << 3) | (hwid << 4)); + md.u.md2.dir = direction; + md.u.md2.hwid = hwid & 0xf; + md.u.md2.hwid_upper = (hwid >> 4) & 0x3; #endif ret = bpf_skb_set_tunnel_opt(skb, &md, sizeof(md)); @@ -290,9 +281,9 @@ int _ip4ip6erspan_get_tunnel(struct __sk_buff *skb) char fmt2[] = "\tdirection %d hwid %x timestamp %u\n"; bpf_trace_printk(fmt2, sizeof(fmt2), - (ntohs(md.u.md2.flags) >> 3) & 0x1, - (ntohs(md.u.md2.flags) >> 4) & 0x3f, - bpf_ntohl(md.u.md2.timestamp)); + md.u.md2.dir, + (md.u.md2.hwid_upper << 4) + md.u.md2.hwid, + bpf_ntohl(md.u.md2.timestamp)); #endif return TC_ACT_OK; diff --git a/samples/bpf/test_tunnel_bpf.sh b/samples/bpf/test_tunnel_bpf.sh index ae7f7c38309b..43ce049996ee 100755 --- a/samples/bpf/test_tunnel_bpf.sh +++ b/samples/bpf/test_tunnel_bpf.sh @@ -68,7 +68,7 @@ function add_erspan_tunnel { ip netns exec at_ns0 \ ip link add dev $DEV_NS type $TYPE seq key 2 \ local 172.16.1.100 remote 172.16.1.200 \ - erspan_ver 2 erspan_dir 1 erspan_hwid 3 + erspan_ver 2 erspan_dir egress erspan_hwid 3 fi ip netns exec at_ns0 ip link set dev $DEV_NS up ip netns exec at_ns0 ip addr add dev $DEV_NS 10.1.1.100/24 @@ -97,7 +97,7 @@ function add_ip6erspan_tunnel { ip netns exec at_ns0 \ ip link add dev $DEV_NS type $TYPE seq key 2 \ local ::11 remote ::22 \ - erspan_ver 2 erspan_dir 1 erspan_hwid 7 + erspan_ver 2 erspan_dir egress erspan_hwid 7 fi ip netns exec at_ns0 ip addr add dev $DEV_NS 10.1.1.100/24 ip netns exec at_ns0 ip link set dev $DEV_NS up |