From a3222dc95ca751cdc5f6ac3c9b092b160b73ed9f Mon Sep 17 00:00:00 2001 From: William Tu Date: Thu, 30 Nov 2017 11:51:27 -0800 Subject: ip_gre: Refector the erpsan tunnel code. Move two erspan functions to header file, erspan.h, so ipv6 erspan implementation can use it. Signed-off-by: William Tu Signed-off-by: David S. Miller --- include/net/erspan.h | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) (limited to 'include/net/erspan.h') diff --git a/include/net/erspan.h b/include/net/erspan.h index ca94fc8..6e758d0 100644 --- a/include/net/erspan.h +++ b/include/net/erspan.h @@ -58,4 +58,55 @@ struct erspanhdr { struct erspan_metadata md; }; +static inline u8 tos_to_cos(u8 tos) +{ + u8 dscp, cos; + + dscp = tos >> 2; + cos = dscp >> 3; + return cos; +} + +static inline void erspan_build_header(struct sk_buff *skb, + __be32 id, u32 index, + bool truncate, bool is_ipv4) +{ + struct ethhdr *eth = eth_hdr(skb); + enum erspan_encap_type enc_type; + struct erspanhdr *ershdr; + struct qtag_prefix { + __be16 eth_type; + __be16 tci; + } *qp; + u16 vlan_tci = 0; + u8 tos; + + tos = is_ipv4 ? ip_hdr(skb)->tos : + (ipv6_hdr(skb)->priority << 4) + + (ipv6_hdr(skb)->flow_lbl[0] >> 4); + + enc_type = ERSPAN_ENCAP_NOVLAN; + + /* If mirrored packet has vlan tag, extract tci and + * perserve vlan header in the mirrored frame. + */ + if (eth->h_proto == htons(ETH_P_8021Q)) { + qp = (struct qtag_prefix *)(skb->data + 2 * ETH_ALEN); + vlan_tci = ntohs(qp->tci); + enc_type = ERSPAN_ENCAP_INFRAME; + } + + skb_push(skb, sizeof(*ershdr)); + ershdr = (struct erspanhdr *)skb->data; + memset(ershdr, 0, sizeof(*ershdr)); + + ershdr->ver_vlan = htons((vlan_tci & VLAN_MASK) | + (ERSPAN_VERSION << VER_OFFSET)); + ershdr->session_id = htons((u16)(ntohl(id) & ID_MASK) | + ((tos_to_cos(tos) << COS_OFFSET) & COS_MASK) | + (enc_type << EN_OFFSET & EN_MASK) | + ((truncate << T_OFFSET) & T_MASK)); + ershdr->md.index = htonl(index & INDEX_MASK); +} + #endif -- cgit v1.1 From 1d7e2ed22f8d9171fa8b629754022f22115b3f03 Mon Sep 17 00:00:00 2001 From: William Tu Date: Wed, 13 Dec 2017 16:38:55 -0800 Subject: net: erspan: refactor existing erspan code The patch refactors the existing erspan implementation in order to support erspan version 2, which has additional metadata. So, in stead of having one 'struct erspanhdr' holding erspan version 1, breaks it into 'struct erspan_base_hdr' and 'struct erspan_metadata'. Signed-off-by: William Tu Signed-off-by: David S. Miller --- include/net/erspan.h | 34 ++++++++++++++++++++++++---------- 1 file changed, 24 insertions(+), 10 deletions(-) (limited to 'include/net/erspan.h') diff --git a/include/net/erspan.h b/include/net/erspan.h index 6e758d0..70c40c7 100644 --- a/include/net/erspan.h +++ b/include/net/erspan.h @@ -15,7 +15,7 @@ * s, Recur, Flags, Version fields only S (bit 03) is set to 1. The * other fields are set to zero, so only a sequence number follows. * - * ERSPAN Type II header (8 octets [42:49]) + * ERSPAN Version 1 (Type II) header (8 octets [42:49]) * 0 1 2 3 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ @@ -27,7 +27,7 @@ * GRE proto ERSPAN type II = 0x88BE, type III = 0x22EB */ -#define ERSPAN_VERSION 0x1 +#define ERSPAN_VERSION 0x1 /* ERSPAN type II */ #define VER_MASK 0xf000 #define VLAN_MASK 0x0fff @@ -44,20 +44,29 @@ enum erspan_encap_type { ERSPAN_ENCAP_INFRAME = 0x3, /* VLAN tag perserved in frame */ }; +#define ERSPAN_V1_MDSIZE 4 +#define ERSPAN_V2_MDSIZE 8 struct erspan_metadata { - __be32 index; /* type II */ + union { + __be32 index; /* Version 1 (type II)*/ + } u; }; -struct erspanhdr { +struct erspan_base_hdr { __be16 ver_vlan; #define VER_OFFSET 12 __be16 session_id; #define COS_OFFSET 13 #define EN_OFFSET 11 #define T_OFFSET 10 - struct erspan_metadata md; }; +static inline int erspan_hdr_len(int version) +{ + return sizeof(struct erspan_base_hdr) + + (version == 1 ? ERSPAN_V1_MDSIZE : ERSPAN_V2_MDSIZE); +} + static inline u8 tos_to_cos(u8 tos) { u8 dscp, cos; @@ -73,7 +82,8 @@ static inline void erspan_build_header(struct sk_buff *skb, { struct ethhdr *eth = eth_hdr(skb); enum erspan_encap_type enc_type; - struct erspanhdr *ershdr; + struct erspan_base_hdr *ershdr; + struct erspan_metadata *ersmd; struct qtag_prefix { __be16 eth_type; __be16 tci; @@ -96,17 +106,21 @@ static inline void erspan_build_header(struct sk_buff *skb, enc_type = ERSPAN_ENCAP_INFRAME; } - skb_push(skb, sizeof(*ershdr)); - ershdr = (struct erspanhdr *)skb->data; - memset(ershdr, 0, sizeof(*ershdr)); + skb_push(skb, sizeof(*ershdr) + ERSPAN_V1_MDSIZE); + ershdr = (struct erspan_base_hdr *)skb->data; + memset(ershdr, 0, sizeof(*ershdr) + ERSPAN_V1_MDSIZE); + /* Build base header */ ershdr->ver_vlan = htons((vlan_tci & VLAN_MASK) | (ERSPAN_VERSION << VER_OFFSET)); ershdr->session_id = htons((u16)(ntohl(id) & ID_MASK) | ((tos_to_cos(tos) << COS_OFFSET) & COS_MASK) | (enc_type << EN_OFFSET & EN_MASK) | ((truncate << T_OFFSET) & T_MASK)); - ershdr->md.index = htonl(index & INDEX_MASK); + + /* Build metadata */ + ersmd = (struct erspan_metadata *)(ershdr + 1); + ersmd->u.index = htonl(index & INDEX_MASK); } #endif -- cgit v1.1 From f551c91de262ba36b20c3ac19538afb4f4507441 Mon Sep 17 00:00:00 2001 From: William Tu Date: Wed, 13 Dec 2017 16:38:56 -0800 Subject: net: erspan: introduce erspan v2 for ip_gre The patch adds support for erspan version 2. Not all features are supported in this patch. The SGT (security group tag), GRA (timestamp granularity), FT (frame type) are set to fixed value. Only hardware ID and direction are configurable. Optional subheader is also not supported. Signed-off-by: William Tu Signed-off-by: David S. Miller --- include/net/erspan.h | 120 ++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 118 insertions(+), 2 deletions(-) (limited to 'include/net/erspan.h') diff --git a/include/net/erspan.h b/include/net/erspan.h index 70c40c7..acdf684 100644 --- a/include/net/erspan.h +++ b/include/net/erspan.h @@ -24,11 +24,29 @@ * | Reserved | Index | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * + * + * ERSPAN Version 2 (Type III) header (12 octets [42:49]) + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Ver | VLAN | COS |BSO|T| Session ID | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Timestamp | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | SGT |P| FT | Hw ID |D|Gra|O| + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + * Platform Specific SubHeader (8 octets, optional) + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Platf ID | Platform Specific Info | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Platform Specific Info | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * * GRE proto ERSPAN type II = 0x88BE, type III = 0x22EB */ #define ERSPAN_VERSION 0x1 /* ERSPAN type II */ - #define VER_MASK 0xf000 #define VLAN_MASK 0x0fff #define COS_MASK 0xe000 @@ -37,6 +55,28 @@ #define ID_MASK 0x03ff #define INDEX_MASK 0xfffff +#define ERSPAN_VERSION2 0x2 /* ERSPAN type III*/ +#define BSO_MASK EN_MASK +#define SGT_MASK 0xffff0000 +#define P_MASK 0x8000 +#define FT_MASK 0x7c00 +#define HWID_MASK 0x03f0 +#define DIR_MASK 0x0008 +#define GRA_MASK 0x0006 +#define O_MASK 0x0001 + +/* ERSPAN version 2 metadata header */ +struct erspan_md2 { + __be32 timestamp; + __be16 sgt; /* security group tag */ + __be16 flags; +#define P_OFFSET 15 +#define FT_OFFSET 10 +#define HWID_OFFSET 4 +#define DIR_OFFSET 3 +#define GRA_OFFSET 1 +}; + enum erspan_encap_type { ERSPAN_ENCAP_NOVLAN = 0x0, /* originally without VLAN tag */ ERSPAN_ENCAP_ISL = 0x1, /* originally ISL encapsulated */ @@ -48,8 +88,10 @@ enum erspan_encap_type { #define ERSPAN_V2_MDSIZE 8 struct erspan_metadata { union { - __be32 index; /* Version 1 (type II)*/ + __be32 index; /* Version 1 (type II)*/ + struct erspan_md2 md2; /* Version 2 (type III) */ } u; + int version; }; struct erspan_base_hdr { @@ -58,6 +100,7 @@ struct erspan_base_hdr { __be16 session_id; #define COS_OFFSET 13 #define EN_OFFSET 11 +#define BSO_OFFSET EN_OFFSET #define T_OFFSET 10 }; @@ -123,4 +166,77 @@ static inline void erspan_build_header(struct sk_buff *skb, ersmd->u.index = htonl(index & INDEX_MASK); } +/* ERSPAN GRA: timestamp granularity + * 00b --> granularity = 100 microseconds + * 01b --> granularity = 100 nanoseconds + * 10b --> granularity = IEEE 1588 + * Here we only support 100 microseconds. + */ +static inline __be32 erspan_get_timestamp(void) +{ + u64 h_usecs; + ktime_t kt; + + kt = ktime_get_real(); + h_usecs = ktime_divns(kt, 100 * NSEC_PER_USEC); + + /* ERSPAN base header only has 32-bit, + * so it wraps around 4 days. + */ + return htonl((u32)h_usecs); +} + +static inline void erspan_build_header_v2(struct sk_buff *skb, + __be32 id, u8 direction, u16 hwid, + bool truncate, bool is_ipv4) +{ + struct ethhdr *eth = eth_hdr(skb); + struct erspan_base_hdr *ershdr; + struct erspan_metadata *md; + struct qtag_prefix { + __be16 eth_type; + __be16 tci; + } *qp; + u16 vlan_tci = 0; + u16 session_id; + u8 gra = 0; /* 100 usec */ + u8 bso = 0; /* Bad/Short/Oversized */ + u8 sgt = 0; + u8 tos; + + tos = is_ipv4 ? ip_hdr(skb)->tos : + (ipv6_hdr(skb)->priority << 4) + + (ipv6_hdr(skb)->flow_lbl[0] >> 4); + + /* Unlike v1, v2 does not have En field, + * so only extract vlan tci field. + */ + if (eth->h_proto == htons(ETH_P_8021Q)) { + qp = (struct qtag_prefix *)(skb->data + 2 * ETH_ALEN); + vlan_tci = ntohs(qp->tci); + } + + skb_push(skb, sizeof(*ershdr) + ERSPAN_V2_MDSIZE); + ershdr = (struct erspan_base_hdr *)skb->data; + memset(ershdr, 0, sizeof(*ershdr) + ERSPAN_V2_MDSIZE); + + /* Build base header */ + ershdr->ver_vlan = htons((vlan_tci & VLAN_MASK) | + (ERSPAN_VERSION2 << VER_OFFSET)); + session_id = (u16)(ntohl(id) & ID_MASK) | + ((tos_to_cos(tos) << COS_OFFSET) & COS_MASK) | + (bso << BSO_OFFSET & BSO_MASK) | + ((truncate << T_OFFSET) & T_MASK); + ershdr->session_id = htons(session_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.flags = htons(((1 << P_OFFSET) & P_MASK) | + ((hwid << HWID_OFFSET) & HWID_MASK) | + ((direction << DIR_OFFSET) & DIR_MASK) | + ((gra << GRA_OFFSET) & GRA_MASK)); +} + #endif -- cgit v1.1 From b423d13c08a656c719fa56324a8f4279c835d90c Mon Sep 17 00:00:00 2001 From: William Tu Date: Tue, 23 Jan 2018 17:01:29 -0800 Subject: net: erspan: fix use-after-free When building the erspan header for either v1 or v2, the eth_hdr() does not point to the right inner packet's eth_hdr, causing kasan report use-after-free and slab-out-of-bouds read. The patch fixes the following syzkaller issues: [1] BUG: KASAN: slab-out-of-bounds in erspan_xmit+0x22d4/0x2430 net/ipv4/ip_gre.c:735 [2] BUG: KASAN: slab-out-of-bounds in erspan_build_header+0x3bf/0x3d0 net/ipv4/ip_gre.c:698 [3] BUG: KASAN: use-after-free in erspan_xmit+0x22d4/0x2430 net/ipv4/ip_gre.c:735 [4] BUG: KASAN: use-after-free in erspan_build_header+0x3bf/0x3d0 net/ipv4/ip_gre.c:698 [2] CPU: 0 PID: 3654 Comm: syzkaller377964 Not tainted 4.15.0-rc9+ #185 Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011 Call Trace: __dump_stack lib/dump_stack.c:17 [inline] dump_stack+0x194/0x257 lib/dump_stack.c:53 print_address_description+0x73/0x250 mm/kasan/report.c:252 kasan_report_error mm/kasan/report.c:351 [inline] kasan_report+0x25b/0x340 mm/kasan/report.c:409 __asan_report_load_n_noabort+0xf/0x20 mm/kasan/report.c:440 erspan_build_header+0x3bf/0x3d0 net/ipv4/ip_gre.c:698 erspan_xmit+0x3b8/0x13b0 net/ipv4/ip_gre.c:740 __netdev_start_xmit include/linux/netdevice.h:4042 [inline] netdev_start_xmit include/linux/netdevice.h:4051 [inline] packet_direct_xmit+0x315/0x6b0 net/packet/af_packet.c:266 packet_snd net/packet/af_packet.c:2943 [inline] packet_sendmsg+0x3aed/0x60b0 net/packet/af_packet.c:2968 sock_sendmsg_nosec net/socket.c:638 [inline] sock_sendmsg+0xca/0x110 net/socket.c:648 SYSC_sendto+0x361/0x5c0 net/socket.c:1729 SyS_sendto+0x40/0x50 net/socket.c:1697 do_syscall_32_irqs_on arch/x86/entry/common.c:327 [inline] do_fast_syscall_32+0x3ee/0xf9d arch/x86/entry/common.c:389 entry_SYSENTER_compat+0x54/0x63 arch/x86/entry/entry_64_compat.S:129 RIP: 0023:0xf7fcfc79 RSP: 002b:00000000ffc6976c EFLAGS: 00000286 ORIG_RAX: 0000000000000171 RAX: ffffffffffffffda RBX: 0000000000000004 RCX: 0000000020011000 RDX: 0000000000000000 RSI: 0000000000000000 RDI: 0000000020008000 RBP: 000000000000001c R08: 0000000000000000 R09: 0000000000000000 R10: 0000000000000000 R11: 0000000000000000 R12: 0000000000000000 R13: 0000000000000000 R14: 0000000000000000 R15: 0000000000000000 Fixes: f551c91de262 ("net: erspan: introduce erspan v2 for ip_gre") Fixes: 84e54fe0a5ea ("gre: introduce native tunnel support for ERSPAN") Reported-by: syzbot+9723f2d288e49b492cf0@syzkaller.appspotmail.com Reported-by: syzbot+f0ddeb2b032a8e1d9098@syzkaller.appspotmail.com Reported-by: syzbot+f14b3703cd8d7670203f@syzkaller.appspotmail.com Reported-by: syzbot+eefa384efad8d7997f20@syzkaller.appspotmail.com Signed-off-by: William Tu Signed-off-by: David S. Miller --- include/net/erspan.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'include/net/erspan.h') diff --git a/include/net/erspan.h b/include/net/erspan.h index acdf684..712ea1b 100644 --- a/include/net/erspan.h +++ b/include/net/erspan.h @@ -123,7 +123,7 @@ static inline void erspan_build_header(struct sk_buff *skb, __be32 id, u32 index, bool truncate, bool is_ipv4) { - struct ethhdr *eth = eth_hdr(skb); + struct ethhdr *eth = (struct ethhdr *)skb->data; enum erspan_encap_type enc_type; struct erspan_base_hdr *ershdr; struct erspan_metadata *ersmd; @@ -190,7 +190,7 @@ static inline void erspan_build_header_v2(struct sk_buff *skb, __be32 id, u8 direction, u16 hwid, bool truncate, bool is_ipv4) { - struct ethhdr *eth = eth_hdr(skb); + struct ethhdr *eth = (struct ethhdr *)skb->data; struct erspan_base_hdr *ershdr; struct erspan_metadata *md; struct qtag_prefix { -- cgit v1.1 From c69de58ba84f480879de64571d9dae5102d10ed6 Mon Sep 17 00:00:00 2001 From: William Tu Date: Thu, 25 Jan 2018 13:20:09 -0800 Subject: net: erspan: use bitfield instead of mask and offset Originally the erspan fields are defined as a group into a __be16 field, and use mask and offset to access each field. This is more costly due to calling ntohs/htons. The patch changes it to use bitfields. Signed-off-by: William Tu Acked-by: Pravin B Shelar Signed-off-by: David S. Miller --- include/net/erspan.h | 127 ++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 94 insertions(+), 33 deletions(-) (limited to 'include/net/erspan.h') diff --git a/include/net/erspan.h b/include/net/erspan.h index 712ea1b..6d30fe8 100644 --- a/include/net/erspan.h +++ b/include/net/erspan.h @@ -65,16 +65,30 @@ #define GRA_MASK 0x0006 #define O_MASK 0x0001 +#define HWID_OFFSET 4 +#define DIR_OFFSET 3 + /* ERSPAN version 2 metadata header */ struct erspan_md2 { __be32 timestamp; __be16 sgt; /* security group tag */ - __be16 flags; -#define P_OFFSET 15 -#define FT_OFFSET 10 -#define HWID_OFFSET 4 -#define DIR_OFFSET 3 -#define GRA_OFFSET 1 +#if defined(__LITTLE_ENDIAN_BITFIELD) + __u8 hwid_upper:2, + ft:5, + p:1; + __u8 o:1, + gra:2, + dir:1, + hwid:4; +#elif defined(__BIG_ENDIAN_BITFIELD) + __u8 p:1, + ft:5, + hwid_upper:2; + __u8 hwid:4, + dir:1, + gra:2, + o:1; +#endif }; enum erspan_encap_type { @@ -95,15 +109,62 @@ struct erspan_metadata { }; struct erspan_base_hdr { - __be16 ver_vlan; -#define VER_OFFSET 12 - __be16 session_id; -#define COS_OFFSET 13 -#define EN_OFFSET 11 -#define BSO_OFFSET EN_OFFSET -#define T_OFFSET 10 +#if defined(__LITTLE_ENDIAN_BITFIELD) + __u8 vlan_upper:4, + ver:4; + __u8 vlan:8; + __u8 session_id_upper:2, + t:1, + en:2, + cos:3; + __u8 session_id:8; +#elif defined(__BIG_ENDIAN_BITFIELD) + __u8 ver: 4, + vlan_upper:4; + __u8 vlan:8; + __u8 cos:3, + en:2, + t:1, + session_id_upper:2; + __u8 session_id:8; +#else +#error "Please fix " +#endif }; +static inline void set_session_id(struct erspan_base_hdr *ershdr, u16 id) +{ + ershdr->session_id = id & 0xff; + ershdr->session_id_upper = (id >> 8) & 0x3; +} + +static inline u16 get_session_id(const struct erspan_base_hdr *ershdr) +{ + return (ershdr->session_id_upper << 8) + ershdr->session_id; +} + +static inline void set_vlan(struct erspan_base_hdr *ershdr, u16 vlan) +{ + ershdr->vlan = vlan & 0xff; + ershdr->vlan_upper = (vlan >> 8) & 0xf; +} + +static inline u16 get_vlan(const struct erspan_base_hdr *ershdr) +{ + return (ershdr->vlan_upper << 8) + ershdr->vlan; +} + +static inline void set_hwid(struct erspan_md2 *md2, u8 hwid) +{ + md2->hwid = hwid & 0xf; + md2->hwid_upper = (hwid >> 4) & 0x3; +} + +static inline u8 get_hwid(const struct erspan_md2 *md2) +{ + return (md2->hwid_upper << 4) + md2->hwid; +} + static inline int erspan_hdr_len(int version) { return sizeof(struct erspan_base_hdr) + @@ -120,7 +181,7 @@ static inline u8 tos_to_cos(u8 tos) } static inline void erspan_build_header(struct sk_buff *skb, - __be32 id, u32 index, + u32 id, u32 index, bool truncate, bool is_ipv4) { struct ethhdr *eth = (struct ethhdr *)skb->data; @@ -154,12 +215,12 @@ static inline void erspan_build_header(struct sk_buff *skb, memset(ershdr, 0, sizeof(*ershdr) + ERSPAN_V1_MDSIZE); /* Build base header */ - ershdr->ver_vlan = htons((vlan_tci & VLAN_MASK) | - (ERSPAN_VERSION << VER_OFFSET)); - ershdr->session_id = htons((u16)(ntohl(id) & ID_MASK) | - ((tos_to_cos(tos) << COS_OFFSET) & COS_MASK) | - (enc_type << EN_OFFSET & EN_MASK) | - ((truncate << T_OFFSET) & T_MASK)); + ershdr->ver = ERSPAN_VERSION; + ershdr->cos = tos_to_cos(tos); + ershdr->en = enc_type; + ershdr->t = truncate; + set_vlan(ershdr, vlan_tci); + set_session_id(ershdr, id); /* Build metadata */ ersmd = (struct erspan_metadata *)(ershdr + 1); @@ -187,7 +248,7 @@ static inline __be32 erspan_get_timestamp(void) } static inline void erspan_build_header_v2(struct sk_buff *skb, - __be32 id, u8 direction, u16 hwid, + u32 id, u8 direction, u16 hwid, bool truncate, bool is_ipv4) { struct ethhdr *eth = (struct ethhdr *)skb->data; @@ -198,7 +259,6 @@ static inline void erspan_build_header_v2(struct sk_buff *skb, __be16 tci; } *qp; u16 vlan_tci = 0; - u16 session_id; u8 gra = 0; /* 100 usec */ u8 bso = 0; /* Bad/Short/Oversized */ u8 sgt = 0; @@ -221,22 +281,23 @@ static inline void erspan_build_header_v2(struct sk_buff *skb, memset(ershdr, 0, sizeof(*ershdr) + ERSPAN_V2_MDSIZE); /* Build base header */ - ershdr->ver_vlan = htons((vlan_tci & VLAN_MASK) | - (ERSPAN_VERSION2 << VER_OFFSET)); - session_id = (u16)(ntohl(id) & ID_MASK) | - ((tos_to_cos(tos) << COS_OFFSET) & COS_MASK) | - (bso << BSO_OFFSET & BSO_MASK) | - ((truncate << T_OFFSET) & T_MASK); - ershdr->session_id = htons(session_id); + ershdr->ver = ERSPAN_VERSION2; + ershdr->cos = tos_to_cos(tos); + ershdr->en = bso; + ershdr->t = truncate; + set_vlan(ershdr, vlan_tci); + 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.flags = htons(((1 << P_OFFSET) & P_MASK) | - ((hwid << HWID_OFFSET) & HWID_MASK) | - ((direction << DIR_OFFSET) & DIR_MASK) | - ((gra << GRA_OFFSET) & GRA_MASK)); + 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); } #endif -- cgit v1.1 From d350a823020e71e20a10d1dfa44f1d1d653b0334 Mon Sep 17 00:00:00 2001 From: William Tu Date: Thu, 25 Jan 2018 13:20:10 -0800 Subject: net: erspan: create erspan metadata uapi header The patch adds a new uapi header file, erspan.h, and moves the 'struct erspan_metadata' from internal erspan.h to it. Signed-off-by: William Tu Acked-by: Pravin B Shelar Signed-off-by: David S. Miller --- include/net/erspan.h | 32 ++------------------------------ 1 file changed, 2 insertions(+), 30 deletions(-) (limited to 'include/net/erspan.h') diff --git a/include/net/erspan.h b/include/net/erspan.h index 6d30fe8..5daa486 100644 --- a/include/net/erspan.h +++ b/include/net/erspan.h @@ -46,6 +46,8 @@ * GRE proto ERSPAN type II = 0x88BE, type III = 0x22EB */ +#include + #define ERSPAN_VERSION 0x1 /* ERSPAN type II */ #define VER_MASK 0xf000 #define VLAN_MASK 0x0fff @@ -68,29 +70,6 @@ #define HWID_OFFSET 4 #define DIR_OFFSET 3 -/* ERSPAN version 2 metadata header */ -struct erspan_md2 { - __be32 timestamp; - __be16 sgt; /* security group tag */ -#if defined(__LITTLE_ENDIAN_BITFIELD) - __u8 hwid_upper:2, - ft:5, - p:1; - __u8 o:1, - gra:2, - dir:1, - hwid:4; -#elif defined(__BIG_ENDIAN_BITFIELD) - __u8 p:1, - ft:5, - hwid_upper:2; - __u8 hwid:4, - dir:1, - gra:2, - o:1; -#endif -}; - enum erspan_encap_type { ERSPAN_ENCAP_NOVLAN = 0x0, /* originally without VLAN tag */ ERSPAN_ENCAP_ISL = 0x1, /* originally ISL encapsulated */ @@ -100,13 +79,6 @@ enum erspan_encap_type { #define ERSPAN_V1_MDSIZE 4 #define ERSPAN_V2_MDSIZE 8 -struct erspan_metadata { - union { - __be32 index; /* Version 1 (type II)*/ - struct erspan_md2 md2; /* Version 2 (type III) */ - } u; - int version; -}; struct erspan_base_hdr { #if defined(__LITTLE_ENDIAN_BITFIELD) -- cgit v1.1