Skip to content

Commit

Permalink
ip_gre: Refactor the erspan tunnel code.
Browse files Browse the repository at this point in the history
Upstream commit:
    commit a3222dc95ca751cdc5f6ac3c9b092b160b73ed9f
    Author: William Tu <[email protected]>
    Date:   Thu Nov 30 11:51:27 2017 -0800

    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 <[email protected]>
    Signed-off-by: David S. Miller <[email protected]>

Cc: William Tu <[email protected]>
Signed-off-by: Greg Rose <[email protected]>
Signed-off-by: Ben Pfaff <[email protected]>
Acked-by: William Tu <[email protected]>
  • Loading branch information
williamtu authored and blp committed May 22, 2018
1 parent 2ce53c0 commit 29a2945
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 50 deletions.
51 changes: 51 additions & 0 deletions datapath/linux/compat/include/net/erspan.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,57 @@ 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
#else
#include_next <net/erspan.h>
Expand Down
55 changes: 5 additions & 50 deletions datapath/linux/compat/ip_gre.c
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,9 @@
static int gre_tap_net_id __read_mostly;
static int ipgre_net_id __read_mostly;
static unsigned int erspan_net_id __read_mostly;
static void erspan_build_header(struct sk_buff *skb,
__be32 id, u32 index,
bool truncate, bool is_ipv4);

static struct rtnl_link_ops ipgre_link_ops __read_mostly;

Expand Down Expand Up @@ -93,9 +96,6 @@ static __be32 tunnel_id_to_key(__be64 x)
#endif
}

static void erspan_build_header(struct sk_buff *skb,
__be32 id, u32 index, bool truncate);

/* Called with rcu_read_lock and BH disabled. */
static int gre_err(struct sk_buff *skb, u32 info,
const struct tnl_ptk_info *tpi)
Expand Down Expand Up @@ -932,52 +932,6 @@ static netdev_tx_t gre_dev_xmit(struct sk_buff *skb, struct net_device *dev)
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)
{
Expand All @@ -1001,7 +955,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;
Expand Down

0 comments on commit 29a2945

Please sign in to comment.