Loading include/net/erspan.h +51 −0 Original line number Diff line number Diff line Loading @@ -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 net/ipv4/ip_gre.c +5 −49 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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++)); Loading Loading @@ -668,52 +669,6 @@ static netdev_tx_t ipgre_xmit(struct sk_buff *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) { Loading @@ -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; Loading Loading
include/net/erspan.h +51 −0 Original line number Diff line number Diff line Loading @@ -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
net/ipv4/ip_gre.c +5 −49 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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++)); Loading Loading @@ -668,52 +669,6 @@ static netdev_tx_t ipgre_xmit(struct sk_buff *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) { Loading @@ -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; Loading