net: erspan: fix metadata extraction
authorWilliam Tu <u9012063@gmail.com>
Mon, 5 Feb 2018 21:35:34 +0000 (13:35 -0800)
committerDavid S. Miller <davem@davemloft.net>
Tue, 6 Feb 2018 16:32:48 +0000 (11:32 -0500)
Commit d350a823020e ("net: erspan: create erspan metadata uapi header")
moves the erspan 'version' in front of the 'struct erspan_md2' for
later extensibility reason.  This breaks the existing erspan metadata
extraction code because the erspan_md2 then has a 4-byte offset
to between the erspan_metadata and erspan_base_hdr.  This patch
fixes it.

Fixes: 1a66a836da63 ("gre: add collect_md mode to ERSPAN tunnel")
Fixes: ef7baf5e083c ("ip6_gre: add ip6 erspan collect_md mode")
Fixes: 1d7e2ed22f8d ("net: erspan: refactor existing erspan code")
Signed-off-by: William Tu <u9012063@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
include/net/erspan.h
net/ipv4/ip_gre.c
net/ipv6/ip6_gre.c

index 5daa4866412be5ca28bc6e8fd3a6146a5edd784e..d044aa60cc76ff2490e8b0837d2a357e57e628e8 100644 (file)
@@ -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 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;
        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) +
 
        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 */
        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
 }
 
 /* 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 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;
        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 */
        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
 }
 
 #endif
index 6ec670fbbbddf96c57c33c9816ba15f1b269edef..9b50eddd18823e705274c2d1021a4f74977c4313 100644 (file)
@@ -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 ip_tunnel_net *itn;
        struct ip_tunnel *tunnel;
        const struct iphdr *iph;
+       struct erspan_md2 *md2;
        int ver;
        int len;
 
        int ver;
        int len;
 
@@ -313,8 +314,10 @@ 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);
                                return PACKET_REJECT;
 
                        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->key.tun_flags |= TUNNEL_ERSPAN_OPT;
 
                        info = &tun_dst->u.tun_info;
                        info->key.tun_flags |= TUNNEL_ERSPAN_OPT;
index 05f070e123e4d416dd3b0cd17e564a5145343402..50913dbd0612e985164b0017de2ddbfa45697dfe 100644 (file)
@@ -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_base_hdr *ershdr;
        struct erspan_metadata *pkt_md;
        const struct ipv6hdr *ipv6h;
+       struct erspan_md2 *md2;
        struct ip6_tnl *tunnel;
        u8 ver;
 
        struct ip6_tnl *tunnel;
        u8 ver;
 
@@ -551,9 +552,10 @@ static int ip6erspan_rcv(struct sk_buff *skb, int gre_hdr_len,
 
                        info = &tun_dst->u.tun_info;
                        md = ip_tunnel_info_opts(info);
 
                        info = &tun_dst->u.tun_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->options_len = sizeof(*md);
 
                        info->key.tun_flags |= TUNNEL_ERSPAN_OPT;
                        info->options_len = sizeof(*md);