It is helpful to allow device drivers that don't support hardware VLAN stripping to emulate this in software. Signed-off-by: Stephen Hemminger --- lib/librte_ether/rte_ether.h | 69 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) --- a/lib/librte_ether/rte_ether.h 2014-08-25 19:00:06.978533976 -0700 +++ b/lib/librte_ether/rte_ether.h 2014-08-25 19:00:06.978533976 -0700 @@ -48,6 +48,8 @@ extern "C" { #include #include +#include +#include #define ETHER_ADDR_LEN 6 /**< Length of Ethernet address. */ #define ETHER_TYPE_LEN 2 /**< Length of Ethernet type field. */ @@ -294,6 +296,73 @@ struct vlan_hdr { #define ETHER_TYPE_VLAN 0x8100 /**< IEEE 802.1Q VLAN tagging. */ #define ETHER_TYPE_1588 0x88F7 /**< IEEE 802.1AS 1588 Precise Time Protocol. */ +/** + * Extract VLAN tag information into mbuf + * + * Software version of VLAN stripping + * + * @param m + * The packet mbuf. + * @return + * - 0: Success + * - 1: not a vlan packet + */ +static inline int rte_vlan_strip(struct rte_mbuf *m) +{ + struct ether_hdr *eh + = rte_pktmbuf_mtod(m, struct ether_hdr *); + + if (eh->ether_type != ETHER_TYPE_VLAN) + return -1; + + struct vlan_hdr *vh = (struct vlan_hdr *)(eh + 1); + m->ol_flags |= PKT_RX_VLAN_PKT; + m->pkt.vlan_macip.f.vlan_tci = rte_be_to_cpu_16(vh->vlan_tci); + + /* Copy ether header over rather than moving whole packet */ + memmove(rte_pktmbuf_adj(m, sizeof(struct vlan_hdr)), + eh, 2 * ETHER_ADDR_LEN); + + return 0; +} + +/** + * Insert VLAN tag into mbuf. + * + * Software version of VLAN unstripping + * + * @param m + * The packet mbuf. + * @return + * - 0: On success + * -EPERM: mbuf is is shared overwriting would be unsafe + * -ENOSPC: not enough headroom in mbuf + */ +static inline int rte_vlan_insert(struct rte_mbuf *m) +{ + struct ether_hdr *oh, *nh; + struct vlan_hdr *vh; + +#ifdef RTE_MBUF_SCATTER_GATHER + /* Can't insert header if mbuf is shared */ + if (rte_mbuf_refcnt_read(m) > 1) + return -EINVAL; +#endif + oh = rte_pktmbuf_mtod(m, struct ether_hdr *); + nh = (struct ether_hdr *) + rte_pktmbuf_prepend(m, sizeof(struct vlan_hdr)); + if (nh == NULL) + return -ENOSPC; + + memmove(nh, oh, 2 * ETHER_ADDR_LEN); + nh->ether_type = ETHER_TYPE_VLAN; + + vh = (struct vlan_hdr *) (nh + 1); + vh->vlan_tci = rte_cpu_to_be_16(m->pkt.vlan_macip.f.vlan_tci); + + return 0; +} + #ifdef __cplusplus } #endif