ip_gre: Refector the erpsan tunnel code.
authorWilliam Tu <u9012063@gmail.com>
Thu, 30 Nov 2017 19:51:27 +0000 (11:51 -0800)
committerDavid S. Miller <davem@davemloft.net>
Fri, 1 Dec 2017 20:33:26 +0000 (15:33 -0500)
Move two erspan functions to header file, erspan.h, so ipv6
erspan implementation can use it.

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

index ca94fc8..6e758d0 100644 (file)
@@ -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
index bb62391..d828821 100644 (file)
@@ -114,7 +114,8 @@ MODULE_PARM_DESC(log_ecn_error, "Log packets received with corrupted ECN");
 static struct rtnl_link_ops ipgre_link_ops __read_mostly;
 static int ipgre_tunnel_init(struct net_device *dev);
 static void erspan_build_header(struct sk_buff *skb,
-                               __be32 id, u32 index, bool truncate);
+                               __be32 id, u32 index,
+                               bool truncate, bool is_ipv4);
 
 static unsigned int ipgre_net_id __read_mostly;
 static unsigned int gre_tap_net_id __read_mostly;
@@ -589,7 +590,7 @@ static void erspan_fb_xmit(struct sk_buff *skb, struct net_device *dev,
                goto err_free_rt;
 
        erspan_build_header(skb, tunnel_id_to_key32(key->tun_id),
-                           ntohl(md->index), truncate);
+                           ntohl(md->index), truncate, true);
 
        gre_build_header(skb, 8, TUNNEL_SEQ,
                         htons(ETH_P_ERSPAN), 0, htonl(tunnel->o_seqno++));
@@ -668,52 +669,6 @@ free_skb:
        return NETDEV_TX_OK;
 }
 
-static inline u8 tos_to_cos(u8 tos)
-{
-       u8 dscp, cos;
-
-       dscp = tos >> 2;
-       cos = dscp >> 3;
-       return cos;
-}
-
-static void erspan_build_header(struct sk_buff *skb,
-                               __be32 id, u32 index, bool truncate)
-{
-       struct iphdr *iphdr = ip_hdr(skb);
-       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;
-
-       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(iphdr->tos) << COS_OFFSET) & COS_MASK) |
-                          (enc_type << EN_OFFSET & EN_MASK) |
-                          ((truncate << T_OFFSET) & T_MASK));
-       ershdr->md.index = htonl(index & INDEX_MASK);
-}
-
 static netdev_tx_t erspan_xmit(struct sk_buff *skb,
                               struct net_device *dev)
 {
@@ -737,7 +692,8 @@ static netdev_tx_t erspan_xmit(struct sk_buff *skb,
        }
 
        /* Push ERSPAN header */
-       erspan_build_header(skb, tunnel->parms.o_key, tunnel->index, truncate);
+       erspan_build_header(skb, tunnel->parms.o_key, tunnel->index,
+                           truncate, true);
        tunnel->parms.o_flags &= ~TUNNEL_KEY;
        __gre_xmit(skb, dev, &tunnel->parms.iph, htons(ETH_P_ERSPAN));
        return NETDEV_TX_OK;