Commit 67ae44e1 authored by David S. Miller's avatar David S. Miller

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 d350a823 ("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: default avatarDavid S. Miller <davem@davemloft.net>
parents d7cdee5e 9c33ca43
...@@ -159,13 +159,13 @@ static inline void erspan_build_header(struct sk_buff *skb, ...@@ -159,13 +159,13 @@ static inline void erspan_build_header(struct sk_buff *skb,
struct ethhdr *eth = (struct ethhdr *)skb->data; struct ethhdr *eth = (struct ethhdr *)skb->data;
enum erspan_encap_type enc_type; enum erspan_encap_type enc_type;
struct erspan_base_hdr *ershdr; struct erspan_base_hdr *ershdr;
struct erspan_metadata *ersmd;
struct qtag_prefix { struct qtag_prefix {
__be16 eth_type; __be16 eth_type;
__be16 tci; __be16 tci;
} *qp; } *qp;
u16 vlan_tci = 0; u16 vlan_tci = 0;
u8 tos; u8 tos;
__be32 *idx;
tos = is_ipv4 ? ip_hdr(skb)->tos : tos = is_ipv4 ? ip_hdr(skb)->tos :
(ipv6_hdr(skb)->priority << 4) + (ipv6_hdr(skb)->priority << 4) +
...@@ -195,8 +195,8 @@ static inline void erspan_build_header(struct sk_buff *skb, ...@@ -195,8 +195,8 @@ static inline void erspan_build_header(struct sk_buff *skb,
set_session_id(ershdr, id); set_session_id(ershdr, id);
/* Build metadata */ /* Build metadata */
ersmd = (struct erspan_metadata *)(ershdr + 1); idx = (__be32 *)(ershdr + 1);
ersmd->u.index = htonl(index & INDEX_MASK); *idx = htonl(index & INDEX_MASK);
} }
/* ERSPAN GRA: timestamp granularity /* ERSPAN GRA: timestamp granularity
...@@ -225,7 +225,7 @@ static inline void erspan_build_header_v2(struct sk_buff *skb, ...@@ -225,7 +225,7 @@ static inline void erspan_build_header_v2(struct sk_buff *skb,
{ {
struct ethhdr *eth = (struct ethhdr *)skb->data; struct ethhdr *eth = (struct ethhdr *)skb->data;
struct erspan_base_hdr *ershdr; struct erspan_base_hdr *ershdr;
struct erspan_metadata *md; struct erspan_md2 *md2;
struct qtag_prefix { struct qtag_prefix {
__be16 eth_type; __be16 eth_type;
__be16 tci; __be16 tci;
...@@ -261,15 +261,15 @@ static inline void erspan_build_header_v2(struct sk_buff *skb, ...@@ -261,15 +261,15 @@ static inline void erspan_build_header_v2(struct sk_buff *skb,
set_session_id(ershdr, id); set_session_id(ershdr, id);
/* Build metadata */ /* Build metadata */
md = (struct erspan_metadata *)(ershdr + 1); md2 = (struct erspan_md2 *)(ershdr + 1);
md->u.md2.timestamp = erspan_get_timestamp(); md2->timestamp = erspan_get_timestamp();
md->u.md2.sgt = htons(sgt); md2->sgt = htons(sgt);
md->u.md2.p = 1; md2->p = 1;
md->u.md2.ft = 0; md2->ft = 0;
md->u.md2.dir = direction; md2->dir = direction;
md->u.md2.gra = gra; md2->gra = gra;
md->u.md2.o = 0; md2->o = 0;
set_hwid(&md->u.md2, hwid); set_hwid(md2, hwid);
} }
#endif #endif
...@@ -261,6 +261,7 @@ static int erspan_rcv(struct sk_buff *skb, struct tnl_ptk_info *tpi, ...@@ -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_net *itn;
struct ip_tunnel *tunnel; struct ip_tunnel *tunnel;
const struct iphdr *iph; const struct iphdr *iph;
struct erspan_md2 *md2;
int ver; int ver;
int len; int len;
...@@ -313,21 +314,14 @@ static int erspan_rcv(struct sk_buff *skb, struct tnl_ptk_info *tpi, ...@@ -313,21 +314,14 @@ static int erspan_rcv(struct sk_buff *skb, struct tnl_ptk_info *tpi,
return PACKET_REJECT; return PACKET_REJECT;
md = ip_tunnel_info_opts(&tun_dst->u.tun_info); md = ip_tunnel_info_opts(&tun_dst->u.tun_info);
memcpy(md, pkt_md, sizeof(*md));
md->version = ver; 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 = &tun_dst->u.tun_info;
info->key.tun_flags |= TUNNEL_ERSPAN_OPT; info->key.tun_flags |= TUNNEL_ERSPAN_OPT;
info->options_len = sizeof(*md); 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); skb_reset_mac_header(skb);
......
...@@ -505,6 +505,7 @@ static int ip6erspan_rcv(struct sk_buff *skb, int gre_hdr_len, ...@@ -505,6 +505,7 @@ static int ip6erspan_rcv(struct sk_buff *skb, int gre_hdr_len,
struct erspan_base_hdr *ershdr; struct erspan_base_hdr *ershdr;
struct erspan_metadata *pkt_md; struct erspan_metadata *pkt_md;
const struct ipv6hdr *ipv6h; const struct ipv6hdr *ipv6h;
struct erspan_md2 *md2;
struct ip6_tnl *tunnel; struct ip6_tnl *tunnel;
u8 ver; u8 ver;
...@@ -551,24 +552,16 @@ static int ip6erspan_rcv(struct sk_buff *skb, int gre_hdr_len, ...@@ -551,24 +552,16 @@ static int ip6erspan_rcv(struct sk_buff *skb, int gre_hdr_len,
info = &tun_dst->u.tun_info; info = &tun_dst->u.tun_info;
md = ip_tunnel_info_opts(info); md = ip_tunnel_info_opts(info);
memcpy(md, pkt_md, sizeof(*md));
md->version = ver; 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->key.tun_flags |= TUNNEL_ERSPAN_OPT;
info->options_len = sizeof(*md); info->options_len = sizeof(*md);
ip6_tnl_rcv(tunnel, skb, tpi, tun_dst, log_ecn_error); ip6_tnl_rcv(tunnel, skb, tpi, tun_dst, log_ecn_error);
} else { } 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); ip6_tnl_rcv(tunnel, skb, tpi, NULL, log_ecn_error);
} }
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#include <uapi/linux/tcp.h> #include <uapi/linux/tcp.h>
#include <uapi/linux/filter.h> #include <uapi/linux/filter.h>
#include <uapi/linux/pkt_cls.h> #include <uapi/linux/pkt_cls.h>
#include <uapi/linux/erspan.h>
#include <net/ipv6.h> #include <net/ipv6.h>
#include "bpf_helpers.h" #include "bpf_helpers.h"
#include "bpf_endian.h" #include "bpf_endian.h"
...@@ -35,24 +36,10 @@ struct geneve_opt { ...@@ -35,24 +36,10 @@ struct geneve_opt {
u8 opt_data[8]; /* hard-coded to 8 byte */ u8 opt_data[8]; /* hard-coded to 8 byte */
}; };
struct erspan_md2 {
__be32 timestamp;
__be16 sgt;
__be16 flags;
};
struct vxlan_metadata { struct vxlan_metadata {
u32 gbp; u32 gbp;
}; };
struct erspan_metadata {
union {
__be32 index;
struct erspan_md2 md2;
} u;
int version;
};
SEC("gre_set_tunnel") SEC("gre_set_tunnel")
int _gre_set_tunnel(struct __sk_buff *skb) int _gre_set_tunnel(struct __sk_buff *skb)
{ {
...@@ -156,13 +143,15 @@ int _erspan_set_tunnel(struct __sk_buff *skb) ...@@ -156,13 +143,15 @@ int _erspan_set_tunnel(struct __sk_buff *skb)
__builtin_memset(&md, 0, sizeof(md)); __builtin_memset(&md, 0, sizeof(md));
#ifdef ERSPAN_V1 #ifdef ERSPAN_V1
md.version = 1; md.version = 1;
md.u.index = htonl(123); md.u.index = bpf_htonl(123);
#else #else
u8 direction = 1; u8 direction = 1;
u16 hwid = 7; u8 hwid = 7;
md.version = 2; 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 #endif
ret = bpf_skb_set_tunnel_opt(skb, &md, sizeof(md)); ret = bpf_skb_set_tunnel_opt(skb, &md, sizeof(md));
...@@ -207,8 +196,8 @@ int _erspan_get_tunnel(struct __sk_buff *skb) ...@@ -207,8 +196,8 @@ int _erspan_get_tunnel(struct __sk_buff *skb)
char fmt2[] = "\tdirection %d hwid %x timestamp %u\n"; char fmt2[] = "\tdirection %d hwid %x timestamp %u\n";
bpf_trace_printk(fmt2, sizeof(fmt2), bpf_trace_printk(fmt2, sizeof(fmt2),
(ntohs(md.u.md2.flags) >> 3) & 0x1, md.u.md2.dir,
(ntohs(md.u.md2.flags) >> 4) & 0x3f, (md.u.md2.hwid_upper << 4) + md.u.md2.hwid,
bpf_ntohl(md.u.md2.timestamp)); bpf_ntohl(md.u.md2.timestamp));
#endif #endif
...@@ -242,10 +231,12 @@ int _ip4ip6erspan_set_tunnel(struct __sk_buff *skb) ...@@ -242,10 +231,12 @@ int _ip4ip6erspan_set_tunnel(struct __sk_buff *skb)
md.version = 1; md.version = 1;
#else #else
u8 direction = 0; u8 direction = 0;
u16 hwid = 17; u8 hwid = 17;
md.version = 2; 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 #endif
ret = bpf_skb_set_tunnel_opt(skb, &md, sizeof(md)); ret = bpf_skb_set_tunnel_opt(skb, &md, sizeof(md));
...@@ -290,8 +281,8 @@ int _ip4ip6erspan_get_tunnel(struct __sk_buff *skb) ...@@ -290,8 +281,8 @@ int _ip4ip6erspan_get_tunnel(struct __sk_buff *skb)
char fmt2[] = "\tdirection %d hwid %x timestamp %u\n"; char fmt2[] = "\tdirection %d hwid %x timestamp %u\n";
bpf_trace_printk(fmt2, sizeof(fmt2), bpf_trace_printk(fmt2, sizeof(fmt2),
(ntohs(md.u.md2.flags) >> 3) & 0x1, md.u.md2.dir,
(ntohs(md.u.md2.flags) >> 4) & 0x3f, (md.u.md2.hwid_upper << 4) + md.u.md2.hwid,
bpf_ntohl(md.u.md2.timestamp)); bpf_ntohl(md.u.md2.timestamp));
#endif #endif
......
...@@ -68,7 +68,7 @@ function add_erspan_tunnel { ...@@ -68,7 +68,7 @@ function add_erspan_tunnel {
ip netns exec at_ns0 \ ip netns exec at_ns0 \
ip link add dev $DEV_NS type $TYPE seq key 2 \ ip link add dev $DEV_NS type $TYPE seq key 2 \
local 172.16.1.100 remote 172.16.1.200 \ 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 fi
ip netns exec at_ns0 ip link set dev $DEV_NS up 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 ip netns exec at_ns0 ip addr add dev $DEV_NS 10.1.1.100/24
...@@ -97,7 +97,7 @@ function add_ip6erspan_tunnel { ...@@ -97,7 +97,7 @@ function add_ip6erspan_tunnel {
ip netns exec at_ns0 \ ip netns exec at_ns0 \
ip link add dev $DEV_NS type $TYPE seq key 2 \ ip link add dev $DEV_NS type $TYPE seq key 2 \
local ::11 remote ::22 \ local ::11 remote ::22 \
erspan_ver 2 erspan_dir 1 erspan_hwid 7 erspan_ver 2 erspan_dir egress erspan_hwid 7
fi fi
ip netns exec at_ns0 ip addr add dev $DEV_NS 10.1.1.100/24 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 ip netns exec at_ns0 ip link set dev $DEV_NS up
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment