[PATCH v2] lib/net: add MPLS insert and strip functionality
From: Tanzeel Ahmed This patch is new version of [PATCH] lib/net: added push MPLS header API. I have also added the MPLS strip functionality in the same patch to address the question asked in last patch. > You should explain why you add this function. None of the foundational NICs currently supports MPLS insertion and stripping, this functionality can help users who rely on MPLS in their network application. > I'm not sure it should be inline I did for perfomance in high-traffic application. Signed-off-by: Tanzeel Ahmed --- v2: * marked experimental * coding style fixed * changed rte_memcpy to memcpy * mpls header marked as const in parameter * added MPLS stripping functionality --- .mailmap | 1 + lib/net/rte_mpls.h | 97 ++ 2 files changed, 98 insertions(+) diff --git a/.mailmap b/.mailmap index a9f4f28..2af4e0d 100644 --- a/.mailmap +++ b/.mailmap @@ -1312,6 +1312,7 @@ Takeshi Yoshimura Takuya Asada Tal Avraham Tal Shnaiderman +Tanzeel Ahmed Tao Y Yang Tao Zhu Taripin Samuel diff --git a/lib/net/rte_mpls.h b/lib/net/rte_mpls.h index 51523e7..b51520f 100644 --- a/lib/net/rte_mpls.h +++ b/lib/net/rte_mpls.h @@ -13,6 +13,8 @@ #include #include +#include +#include #ifdef __cplusplus extern "C" { @@ -36,6 +38,101 @@ struct rte_mpls_hdr { uint8_t ttl; /**< Time to live. */ } __rte_packed; +#define RTE_MPLS_HLEN 4 /**< Length of MPLS header. */ + +/** + * @warning + * @b EXPERIMENTAL: this API may change without prior notice. + * + * Insert MPLS header into the packet. + * If it's first MPLS header to be inserted in the packet, + * - Updates the ether type. + * - Sets the MPLS bottom-of-stack bit to 1. + * + * @param m + * The pointer to the mbuf. + * @param mp + * The pointer to the MPLS header. + * @return + * 0 on success, -1 on error + */ +__rte_experimental +static int +rte_mpls_push_over_l2(struct rte_mbuf **m, const struct rte_mpls_hdr *mp) +{ + struct rte_ether_hdr *oh, *nh; + struct rte_mpls_hdr *mph; + + /* Can't insert header if mbuf is shared */ + if (!RTE_MBUF_DIRECT(*m) || rte_mbuf_refcnt_read(*m) > 1) + return -EINVAL; + + /* Can't insert header if ethernet frame doesn't exist */ + if (rte_pktmbuf_data_len(*m) < RTE_ETHER_HDR_LEN) + return -EINVAL; + + oh = rte_pktmbuf_mtod(*m, struct rte_ether_hdr *); + nh = (struct rte_ether_hdr *)(void *) + rte_pktmbuf_prepend(*m, sizeof(struct rte_mpls_hdr)); + if (nh == NULL) + return -ENOSPC; + + memmove(nh, oh, RTE_ETHER_HDR_LEN); + + /* Copy the MPLS header after ethernet frame */ + mph = rte_pktmbuf_mtod_offset(*m, struct rte_mpls_hdr*, + sizeof(struct rte_ether_hdr)); + memcpy(mph, mp, RTE_MPLS_HLEN); + + mph->tag_msb = rte_cpu_to_be_16(mp->tag_msb); + + /* If first MPLS header, update ether type and bottom-of-stack bit */ + if (nh->ether_type != rte_cpu_to_be_16(RTE_ETHER_TYPE_MPLS)) { + nh->ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_MPLS); + mph->bs = 1; + } else { + mph->bs = 0; + } + + return 0; +} + +/** + * @warning + * @b EXPERIMENTAL: this API may change without prior notice. + * + * Strips MPLS from the packet. Doesn't update the ether type + * + * @param m + * The pointer to the mbuf. + * @return + * 0 on success, -1 on error + */ +__rte_experimental +static inline int +rte_mpls_strip_over_l2(struct rte_mbuf *m) +{ + struct rte_ether_hdr *eh = rte_pktmbuf_mtod(m, struct rte_ether_hdr *); + struct rte_mpls_hdr *mph; + bool mpls_exist = true; + + if (eh->ether_type != rte_cpu_to_be_16(RTE_ETHER_TYPE_MPLS)) + return -1; + + /* Stripping all MPLS header */ + while (mpls_exist) { + mph = rte_pktmbuf_mtod_offset(m, struct rte_mpls_hdr*, + sizeof(struct rte_ether_hdr)); + if (mph->bs & 1) + mpls_exist = false; + memmove(rte_pktmbuf_adj(m, sizeof(struct rte_mpls_hdr)), + eh, sizeof(struct rte_ether_hdr)); + eh = rte_pktmbuf_mtod(m, struct rte_ether_hdr *); + } + + return 0; +} + #ifdef __cplusplus } #endif -- 1.8.3.1
[PATCH v3] lib/net: add MPLS insert and strip functionality
From: Tanzeel Ahmed This patch is new version of [PATCH] lib/net: added push MPLS header API. I have also added the MPLS strip functionality to address the question asked in last patch. > You should explain why you add this function. None of the foundational NICs currently supports MPLS insertion and stripping, this functionality can help users who rely on MPLS in their network application. > I'm not sure it should be inline I did for performance in high-traffic application. Signed-off-by: Tanzeel Ahmed --- v3: * fixed patch checks failure v2: * marked experimental * coding style fixed * changed rte_memcpy to memcpy * mpls header marked as const in parameter * added MPLS stripping functionality --- .mailmap | 1 + lib/net/rte_mpls.h | 97 ++ 2 files changed, 98 insertions(+) diff --git a/.mailmap b/.mailmap index a9f4f28..2af4e0d 100644 --- a/.mailmap +++ b/.mailmap @@ -1312,6 +1312,7 @@ Takeshi Yoshimura Takuya Asada Tal Avraham Tal Shnaiderman +Tanzeel Ahmed Tao Y Yang Tao Zhu Taripin Samuel diff --git a/lib/net/rte_mpls.h b/lib/net/rte_mpls.h index 51523e7..14b55fe 100644 --- a/lib/net/rte_mpls.h +++ b/lib/net/rte_mpls.h @@ -13,6 +13,8 @@ #include #include +#include +#include #ifdef __cplusplus extern "C" { @@ -36,6 +38,101 @@ struct rte_mpls_hdr { uint8_t ttl; /**< Time to live. */ } __rte_packed; +#define RTE_MPLS_HLEN 4 /**< Length of MPLS header. */ + +/** + * @warning + * @b EXPERIMENTAL: this API may change without prior notice. + * + * Insert MPLS header into the packet. + * If it's first MPLS header to be inserted in the packet, + * - Updates the ether type. + * - Sets the MPLS bottom-of-stack bit to 1. + * + * @param m + * The pointer to the mbuf. + * @param mp + * The pointer to the MPLS header. + * @return + * 0 on success, -1 on error + */ +__rte_experimental +static inline int +rte_mpls_push_over_l2(struct rte_mbuf **m, const struct rte_mpls_hdr *mp) +{ + struct rte_ether_hdr *oh, *nh; + struct rte_mpls_hdr *mph; + + /* Can't insert header if mbuf is shared */ + if (!RTE_MBUF_DIRECT(*m) || rte_mbuf_refcnt_read(*m) > 1) + return -EINVAL; + + /* Can't insert header if ethernet frame doesn't exist */ + if (rte_pktmbuf_data_len(*m) < RTE_ETHER_HDR_LEN) + return -EINVAL; + + oh = rte_pktmbuf_mtod(*m, struct rte_ether_hdr *); + nh = (struct rte_ether_hdr *)(void *) + rte_pktmbuf_prepend(*m, sizeof(struct rte_mpls_hdr)); + if (nh == NULL) + return -ENOSPC; + + memmove(nh, oh, RTE_ETHER_HDR_LEN); + + /* Copy the MPLS header after ethernet frame */ + mph = rte_pktmbuf_mtod_offset(*m, struct rte_mpls_hdr*, + sizeof(struct rte_ether_hdr)); + memcpy(mph, mp, RTE_MPLS_HLEN); + + mph->tag_msb = rte_cpu_to_be_16(mp->tag_msb); + + /* If first MPLS header, update ether type and bottom-of-stack bit */ + if (nh->ether_type != rte_cpu_to_be_16(RTE_ETHER_TYPE_MPLS)) { + nh->ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_MPLS); + mph->bs = 1; + } else { + mph->bs = 0; + } + + return 0; +} + +/** + * @warning + * @b EXPERIMENTAL: this API may change without prior notice. + * + * Strips MPLS from the packet. Doesn't update the ether type + * + * @param m + * The pointer to the mbuf. + * @return + * 0 on success, -1 on error + */ +__rte_experimental +static inline int +rte_mpls_strip_over_l2(struct rte_mbuf *m) +{ + struct rte_ether_hdr *eh = rte_pktmbuf_mtod(m, struct rte_ether_hdr *); + struct rte_mpls_hdr *mph; + bool mpls_exist = true; + + if (eh->ether_type != rte_cpu_to_be_16(RTE_ETHER_TYPE_MPLS)) + return -1; + + /* Stripping all MPLS header */ + while (mpls_exist) { + mph = rte_pktmbuf_mtod_offset(m, struct rte_mpls_hdr*, + sizeof(struct rte_ether_hdr)); + if (mph->bs & 1) + mpls_exist = false; + memmove(rte_pktmbuf_adj(m, sizeof(struct rte_mpls_hdr)), + eh, sizeof(struct rte_ether_hdr)); + eh = rte_pktmbuf_mtod(m, struct rte_ether_hdr *); + } + + return 0; +} + #ifdef __cplusplus } #endif -- 1.8.3.1
[PATCH v3] lib/net: add MPLS insert and strip functionality
From: Tanzeel Ahmed This patch is new version of [PATCH] lib/net: added push MPLS header API. I have also added the MPLS strip functionality to address the question asked in last patch. > You should explain why you add this function. None of the foundational NICs currently supports MPLS insertion and stripping, this functionality can help users who rely on MPLS in their network application. > I'm not sure it should be inline I did for performance in high-traffic application. Signed-off-by: Tanzeel Ahmed --- v3: * fixed patch checks failure v2: * marked experimental * coding style fixed * changed rte_memcpy to memcpy * mpls header marked as const in parameter * added MPLS stripping functionality --- .mailmap | 1 + lib/net/rte_mpls.h | 97 ++ 2 files changed, 98 insertions(+) diff --git a/.mailmap b/.mailmap index a9f4f28..2af4e0d 100644 --- a/.mailmap +++ b/.mailmap @@ -1312,6 +1312,7 @@ Takeshi Yoshimura Takuya Asada Tal Avraham Tal Shnaiderman +Tanzeel Ahmed Tao Y Yang Tao Zhu Taripin Samuel diff --git a/lib/net/rte_mpls.h b/lib/net/rte_mpls.h index 51523e7..14b55fe 100644 --- a/lib/net/rte_mpls.h +++ b/lib/net/rte_mpls.h @@ -13,6 +13,8 @@ #include #include +#include +#include #ifdef __cplusplus extern "C" { @@ -36,6 +38,101 @@ struct rte_mpls_hdr { uint8_t ttl; /**< Time to live. */ } __rte_packed; +#define RTE_MPLS_HLEN 4 /**< Length of MPLS header. */ + +/** + * @warning + * @b EXPERIMENTAL: this API may change without prior notice. + * + * Insert MPLS header into the packet. + * If it's first MPLS header to be inserted in the packet, + * - Updates the ether type. + * - Sets the MPLS bottom-of-stack bit to 1. + * + * @param m + * The pointer to the mbuf. + * @param mp + * The pointer to the MPLS header. + * @return + * 0 on success, -1 on error + */ +__rte_experimental +static inline int +rte_mpls_push_over_l2(struct rte_mbuf **m, const struct rte_mpls_hdr *mp) +{ + struct rte_ether_hdr *oh, *nh; + struct rte_mpls_hdr *mph; + + /* Can't insert header if mbuf is shared */ + if (!RTE_MBUF_DIRECT(*m) || rte_mbuf_refcnt_read(*m) > 1) + return -EINVAL; + + /* Can't insert header if ethernet frame doesn't exist */ + if (rte_pktmbuf_data_len(*m) < RTE_ETHER_HDR_LEN) + return -EINVAL; + + oh = rte_pktmbuf_mtod(*m, struct rte_ether_hdr *); + nh = (struct rte_ether_hdr *)(void *) + rte_pktmbuf_prepend(*m, sizeof(struct rte_mpls_hdr)); + if (nh == NULL) + return -ENOSPC; + + memmove(nh, oh, RTE_ETHER_HDR_LEN); + + /* Copy the MPLS header after ethernet frame */ + mph = rte_pktmbuf_mtod_offset(*m, struct rte_mpls_hdr*, + sizeof(struct rte_ether_hdr)); + memcpy(mph, mp, RTE_MPLS_HLEN); + + mph->tag_msb = rte_cpu_to_be_16(mp->tag_msb); + + /* If first MPLS header, update ether type and bottom-of-stack bit */ + if (nh->ether_type != rte_cpu_to_be_16(RTE_ETHER_TYPE_MPLS)) { + nh->ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_MPLS); + mph->bs = 1; + } else { + mph->bs = 0; + } + + return 0; +} + +/** + * @warning + * @b EXPERIMENTAL: this API may change without prior notice. + * + * Strips MPLS from the packet. Doesn't update the ether type + * + * @param m + * The pointer to the mbuf. + * @return + * 0 on success, -1 on error + */ +__rte_experimental +static inline int +rte_mpls_strip_over_l2(struct rte_mbuf *m) +{ + struct rte_ether_hdr *eh = rte_pktmbuf_mtod(m, struct rte_ether_hdr *); + struct rte_mpls_hdr *mph; + bool mpls_exist = true; + + if (eh->ether_type != rte_cpu_to_be_16(RTE_ETHER_TYPE_MPLS)) + return -1; + + /* Stripping all MPLS header */ + while (mpls_exist) { + mph = rte_pktmbuf_mtod_offset(m, struct rte_mpls_hdr*, + sizeof(struct rte_ether_hdr)); + if (mph->bs & 1) + mpls_exist = false; + memmove(rte_pktmbuf_adj(m, sizeof(struct rte_mpls_hdr)), + eh, sizeof(struct rte_ether_hdr)); + eh = rte_pktmbuf_mtod(m, struct rte_ether_hdr *); + } + + return 0; +} + #ifdef __cplusplus } #endif -- 1.8.3.1
[PATCH v4] lib/net: add MPLS insert and strip functionality
From: Tanzeel Ahmed This patch is new version of [PATCH] lib/net: added push MPLS header API. I have also added the MPLS strip functionality to address the question asked in last patch. > You should explain why you add this function. None of the foundational NICs currently supports MPLS insertion and stripping, this functionality can help users who rely on MPLS in their network application. > I'm not sure it should be inline I did for performance in high-traffic application. Signed-off-by: Tanzeel Ahmed --- v4: * Removed extra void cast. * rte_pktmbuf_append/mtod now return void*. The memmove result is casted to rte_ether_hdr*. v3: * fixed patch check failure issue v2: * marked experimental * coding style fixed * changed rte_memcpy to memcpy * mpls header marked as const in parameter * added MPLS stripping functionality --- .mailmap | 1 + lib/net/rte_mpls.h | 97 ++ 2 files changed, 98 insertions(+) diff --git a/.mailmap b/.mailmap index a9f4f28..2af4e0d 100644 --- a/.mailmap +++ b/.mailmap @@ -1312,6 +1312,7 @@ Takeshi Yoshimura Takuya Asada Tal Avraham Tal Shnaiderman +Tanzeel Ahmed Tao Y Yang Tao Zhu Taripin Samuel diff --git a/lib/net/rte_mpls.h b/lib/net/rte_mpls.h index 51523e7..d7e267f 100644 --- a/lib/net/rte_mpls.h +++ b/lib/net/rte_mpls.h @@ -13,6 +13,8 @@ #include #include +#include +#include #ifdef __cplusplus extern "C" { @@ -36,6 +38,101 @@ struct rte_mpls_hdr { uint8_t ttl; /**< Time to live. */ } __rte_packed; +#define RTE_MPLS_HLEN 4 /**< Length of MPLS header. */ + +/** + * @warning + * @b EXPERIMENTAL: this API may change without prior notice. + * + * Insert MPLS header into the packet. + * If it's first MPLS header to be inserted in the packet, + * - Updates the ether type. + * - Sets the MPLS bottom-of-stack bit to 1. + * + * @param m + * The pointer to the mbuf. + * @param mp + * The pointer to the MPLS header. + * @return + * 0 on success, -1 on error + */ +__rte_experimental +static inline int +rte_mpls_push_over_l2(struct rte_mbuf **m, const struct rte_mpls_hdr *mp) +{ + void *os, *ns; + struct rte_ether_hdr *nh; + struct rte_mpls_hdr *mph; + + /* Can't insert header if mbuf is shared */ + if (!RTE_MBUF_DIRECT(*m) || rte_mbuf_refcnt_read(*m) > 1) + return -EINVAL; + + /* Can't insert header if ethernet frame doesn't exist */ + if (rte_pktmbuf_data_len(*m) < RTE_ETHER_HDR_LEN) + return -EINVAL; + + os = rte_pktmbuf_mtod(*m, void *); + ns = (void *)rte_pktmbuf_prepend(*m, sizeof(struct rte_mpls_hdr)); + if (ns == NULL) + return -ENOSPC; + + nh = (struct rte_ether_hdr *)memmove(ns, os, RTE_ETHER_HDR_LEN); + + /* Copy the MPLS header after ethernet frame */ + mph = rte_pktmbuf_mtod_offset(*m, struct rte_mpls_hdr*, + sizeof(struct rte_ether_hdr)); + memcpy(mph, mp, RTE_MPLS_HLEN); + + mph->tag_msb = rte_cpu_to_be_16(mp->tag_msb); + + /* If first MPLS header, update ether type and bottom-of-stack bit */ + if (nh->ether_type != rte_cpu_to_be_16(RTE_ETHER_TYPE_MPLS)) { + nh->ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_MPLS); + mph->bs = 1; + } else { + mph->bs = 0; + } + + return 0; +} + +/** + * @warning + * @b EXPERIMENTAL: this API may change without prior notice. + * + * Strips MPLS from the packet. Doesn't update the ether type + * + * @param m + * The pointer to the mbuf. + * @return + * 0 on success, -1 on error + */ +__rte_experimental +static inline int +rte_mpls_strip_over_l2(struct rte_mbuf *m) +{ + struct rte_ether_hdr *eh = rte_pktmbuf_mtod(m, struct rte_ether_hdr *); + struct rte_mpls_hdr *mph; + bool mpls_exist = true; + + if (eh->ether_type != rte_cpu_to_be_16(RTE_ETHER_TYPE_MPLS)) + return -1; + + /* Stripping all MPLS header */ + while (mpls_exist) { + mph = rte_pktmbuf_mtod_offset(m, struct rte_mpls_hdr*, + sizeof(struct rte_ether_hdr)); + if (mph->bs & 1) + mpls_exist = false; + memmove(rte_pktmbuf_adj(m, sizeof(struct rte_mpls_hdr)), + eh, sizeof(struct rte_ether_hdr)); + eh = rte_pktmbuf_mtod(m, struct rte_ether_hdr *); + } + + return 0; +} + #ifdef __cplusplus } #endif -- 1.8.3.1
[PATCH v5] lib/net: add MPLS insert and strip functionality
None of the foundational NICs currently supports MPLS insertion and stripping, this functionality can help users who rely on MPLS in their network application. Signed-off-by: Tanzeel Ahmed --- This patch is new version of [PATCH] lib/net: added push MPLS header API. I have also added the MPLS strip functionality to address the question asked in last patch. > To be honest, I have some doubts about the usefulness of the patch, > especially the function that strips all the MPLS headers. I believe it serves a practical purpose, in scenarios involving tapped traffic where MPLS headers have not been stripped. While some headers in the lib/net folder have well-defined functions, others are limited to their structure alone. It would be advantageous to have basic functions available for all headers. > I think the function should only strip the first MPLS header, it is > symmetric with the previous function, and more flexible. You are right, stripping one header is more flexible. I updated the function to return 1, in case of stripping last MPLS header. v5: * Updated the MPLS strip function to strip one header at a time. * Added the unit test cases. v4: * Removed extra void cast. * rte_pktmbuf_append/mtod now return void*. The memmove result is casted to rte_ether_hdr*. v3: * fixed patch check failure issue v2: * marked experimental * coding style fixed * changed rte_memcpy to memcpy * mpls header marked as const in parameter * added MPLS stripping functionality --- app/test/meson.build | 2 + app/test/test_mpls.c | 180 +++ lib/net/rte_mpls.h | 106 + 3 files changed, 288 insertions(+) create mode 100644 app/test/test_mpls.c diff --git a/app/test/meson.build b/app/test/meson.build index f34d19e3c3..548349399f 100644 --- a/app/test/meson.build +++ b/app/test/meson.build @@ -95,6 +95,7 @@ test_sources = files( 'test_meter.c', 'test_mcslock.c', 'test_mp_secondary.c', +'test_mpls.c', 'test_per_lcore.c', 'test_pflock.c', 'test_pmd_perf.c', @@ -205,6 +206,7 @@ fast_tests = [ ['mempool_autotest', false, true], ['memzone_autotest', false, true], ['meter_autotest', true, true], +['mpls_autotest', false, true], ['multiprocess_autotest', false, false], ['per_lcore_autotest', true, true], ['pflock_autotest', true, true], diff --git a/app/test/test_mpls.c b/app/test/test_mpls.c new file mode 100644 index 00..8ff701f6e0 --- /dev/null +++ b/app/test/test_mpls.c @@ -0,0 +1,180 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2010-2014 Intel Corporation + */ + +#include "test.h" + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#define MEMPOOL_CACHE_SIZE 32 +#define MBUF_DATA_SIZE 2048 +#define NB_MBUF 128 + +static int +test_mpls_fail_push(struct rte_mbuf *m) +{ + struct rte_mpls_hdr mpls; + + /* create dummy MPLS header */ + mpls.tag_msb = 1; + mpls.tag_lsb = 2; + mpls.bs = 1; + mpls.tc = 1; + mpls.ttl = 255; + + /* push first MPLS header */ + if (rte_mpls_push_over_l2(m, &mpls) != 0) + return 0; + return -1; +} + +static int +test_mpls_push(struct rte_mbuf *m) +{ + struct rte_mpls_hdr mpls; + + /* create dummy MPLS header */ + mpls.tag_msb = 1; + mpls.tag_lsb = 2; + mpls.bs = 1; + mpls.tc = 1; + mpls.ttl = 255; + + /* push first MPLS header */ + if (rte_mpls_push_over_l2(m, &mpls) != 0) { + printf("Failed to insert mpls 1\n"); + return -1; + } + if (rte_pktmbuf_pkt_len(m) != RTE_ETHER_HDR_LEN + RTE_MPLS_HLEN) { + printf("Bad pkt length after inserting first mpls header\n"); + return -1; + } + + /* push second MPLS header*/ + if (rte_mpls_push_over_l2(m, &mpls) != 0) { + printf("failed to insert mpls 1\n"); + return -1; + } + if (rte_pktmbuf_pkt_len(m) != RTE_ETHER_HDR_LEN + RTE_MPLS_HLEN * 2) { + printf("bad pkt length after inserting second mpls header\n"); + return -1; + } + return 0; +} + +static int +test_mpls_fail_strip(struct rte_mbuf *m) +{ + /* strip MPLS headers */ + if (rte_mpls_strip_over_l2(m) != 0) + return 0; + return -1; +} + +static int +test_mpls_strip(struct rte_mbuf *m) +{ + /* strip MPLS headers */ + return rte_mpls_strip_over_l2(m); +} + +static int +test_mpls(void) +{ + int ret = -1; + struct rte_mempool *pktmbuf_pool = NULL; + struct rte_mbuf *m = NULL; + char *data; + struct rte_ether_hdr eh; + + /* create pktmbuf pool */ + pktmbuf_pool = rte_pktmbuf_pool_create("test_mpls_pool", +
[PATCH] lib/net: added push MPLS header API
Push MPLS header after ethernet header, updates ethernet type and MPLS bs bit if required. Signed-off-by: Tanzeel Ahmed --- .mailmap | 1 + lib/net/rte_mpls.h | 59 ++ 2 files changed, 60 insertions(+) diff --git a/.mailmap b/.mailmap index 75884b6..5e06669 100644 --- a/.mailmap +++ b/.mailmap @@ -1301,6 +1301,7 @@ Takeshi Yoshimura Takuya Asada Tal Avraham Tal Shnaiderman +Tanzeel Ahmed Tao Y Yang Tao Zhu Taripin Samuel diff --git a/lib/net/rte_mpls.h b/lib/net/rte_mpls.h index 3e8cb90..6ae72df 100644 --- a/lib/net/rte_mpls.h +++ b/lib/net/rte_mpls.h @@ -13,6 +13,8 @@ #include #include +#include +#include #ifdef __cplusplus extern "C" { @@ -36,6 +38,63 @@ struct rte_mpls_hdr { uint8_t ttl; /**< Time to live. */ } __rte_packed; +#define RTE_MPLS_HLEN 4 /**< Length of MPLS header. */ + +/** + * Insert MPLS header into the packet. + * + * If it's first MPLS header to be inserted in the packet, + * - Updates the ether type. + * - Sets the MPLS bottom-of-stack bit to 1. + * + * @param m + * The pointer to the mbuf. + * @param mp + * The pointer to the MPLS header. + * @return + * 0 on success, -1 on error (If no ethernet header exists) + */ +static inline int +rte_mpls_push_over_l2(struct rte_mbuf **m, struct rte_mpls_hdr *mp) +{ + struct rte_ether_hdr *oh, *nh; + + /* Can't insert header if mbuf is shared */ + if (!RTE_MBUF_DIRECT(*m) || rte_mbuf_refcnt_read(*m) > 1) + return -EINVAL; + + /*Can't insert header if ethernet frame doesn't exist*/ + if (rte_pktmbuf_data_len(*m) < RTE_ETHER_HDR_LEN) + return -EINVAL; + + oh = rte_pktmbuf_mtod(*m, struct rte_ether_hdr *); + nh = (struct rte_ether_hdr *)(void *) + rte_pktmbuf_prepend(*m, sizeof(struct rte_mpls_hdr)); + if (nh == NULL) + return -ENOSPC; + + memmove(nh, oh, RTE_ETHER_HDR_LEN); + + mp->tag_msb = rte_cpu_to_be_16(mp->tag_msb); + + /* If first MPLS header, update ether type and bottom-of-stack bit */ + if (nh->ether_type != rte_cpu_to_be_16(RTE_ETHER_TYPE_MPLS)) + { + nh->ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_MPLS); + mp->bs = 1; + } + else + { + mp->bs = 0; + } + + /* Copy the MPLS header after ethernet frame */ + rte_memcpy(rte_pktmbuf_mtod_offset(*m, char*, sizeof(struct rte_ether_hdr)), mp, RTE_MPLS_HLEN); + + (*m)->data_len += RTE_MPLS_HLEN; + return 0; +} + #ifdef __cplusplus } #endif -- 1.8.3.1
[PATCH v2 2/2] lib/net: added push MPLS header API
The mpls hdr can't be const because the bs bit is updated by checking ether type. v2: * marked experimental * trailing blanks removed * space after /* and before */ * updated to bracket cuddle style * changed rte_memcpy to memcpy Signed-off-by: Tanzeel Ahmed --- lib/net/rte_mpls.h | 24 +--- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/lib/net/rte_mpls.h b/lib/net/rte_mpls.h index 6ae72df..5248391 100644 --- a/lib/net/rte_mpls.h +++ b/lib/net/rte_mpls.h @@ -41,21 +41,25 @@ struct rte_mpls_hdr { #define RTE_MPLS_HLEN 4 /**< Length of MPLS header. */ /** + * @warning + * @b EXPERIMENTAL: this API may change, or be removed, without prior notice. + * * Insert MPLS header into the packet. - * + * * If it's first MPLS header to be inserted in the packet, * - Updates the ether type. * - Sets the MPLS bottom-of-stack bit to 1. - * + * * @param m * The pointer to the mbuf. * @param mp * The pointer to the MPLS header. * @return - * 0 on success, -1 on error (If no ethernet header exists) + * 0 on success, -1 on error (If no ethernet header exists) */ +__rte_experimental static inline int -rte_mpls_push_over_l2(struct rte_mbuf **m, struct rte_mpls_hdr *mp) +rte_mpls_push_over_l2(struct rte_mbuf **m, struct rte_mpls_hdr *mp) { struct rte_ether_hdr *oh, *nh; @@ -63,7 +67,7 @@ struct rte_mpls_hdr { if (!RTE_MBUF_DIRECT(*m) || rte_mbuf_refcnt_read(*m) > 1) return -EINVAL; - /*Can't insert header if ethernet frame doesn't exist*/ + /* Can't insert header if ethernet frame doesn't exist */ if (rte_pktmbuf_data_len(*m) < RTE_ETHER_HDR_LEN) return -EINVAL; @@ -78,18 +82,16 @@ struct rte_mpls_hdr { mp->tag_msb = rte_cpu_to_be_16(mp->tag_msb); /* If first MPLS header, update ether type and bottom-of-stack bit */ - if (nh->ether_type != rte_cpu_to_be_16(RTE_ETHER_TYPE_MPLS)) - { + if (nh->ether_type != rte_cpu_to_be_16(RTE_ETHER_TYPE_MPLS)) { nh->ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_MPLS); mp->bs = 1; - } - else - { + } else { mp->bs = 0; } /* Copy the MPLS header after ethernet frame */ - rte_memcpy(rte_pktmbuf_mtod_offset(*m, char*, sizeof(struct rte_ether_hdr)), mp, RTE_MPLS_HLEN); + memcpy(rte_pktmbuf_mtod_offset(*m, struct rte_mpls_hdr*, + sizeof(struct rte_ether_hdr)), mp, RTE_MPLS_HLEN); (*m)->data_len += RTE_MPLS_HLEN; return 0; -- 1.8.3.1