* [PATCH v3] lib/net: add MPLS insert and strip functionality
@ 2023-02-24 11:06 Tanzeel-inline
2024-10-03 18:46 ` Stephen Hemminger
0 siblings, 1 reply; 4+ messages in thread
From: Tanzeel-inline @ 2023-02-24 11:06 UTC (permalink / raw)
To: olivier.matz, thomas, tanzeelahmed713; +Cc: dev, Tanzeel Ahmed
From: Tanzeel Ahmed <tanxeel1.ahmed@gmail.com>
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 <tanxeel1.ahmed@gmail.com>
---
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 <tyos@jp.ibm.com> <t.yoshimura8869@gmail.com>
Takuya Asada <syuu@cloudius-systems.com>
Tal Avraham <talavr@annapurnalabs.com>
Tal Shnaiderman <talshn@nvidia.com> <talshn@mellanox.com>
+Tanzeel Ahmed <tanxeel1.ahmed@gmail.com>
Tao Y Yang <tao.y.yang@intel.com>
Tao Zhu <taox.zhu@intel.com>
Taripin Samuel <samuel.taripin@intel.com>
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 <stdint.h>
#include <rte_byteorder.h>
+#include <rte_ether.h>
+#include <rte_mbuf.h>
#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
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH v3] lib/net: add MPLS insert and strip functionality
2023-02-24 11:06 [PATCH v3] lib/net: add MPLS insert and strip functionality Tanzeel-inline
@ 2024-10-03 18:46 ` Stephen Hemminger
0 siblings, 0 replies; 4+ messages in thread
From: Stephen Hemminger @ 2024-10-03 18:46 UTC (permalink / raw)
To: Tanzeel-inline; +Cc: olivier.matz, thomas, tanzeelahmed713, dev
On Fri, 24 Feb 2023 16:06:19 +0500
Tanzeel-inline <tanxeel1.ahmed@gmail.com> wrote:
> +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*,
space required (i.e "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;
> +}
This function will fail for the case of segmented mbuf.
Also need to handle case where mbuf is corrupted and just has stack of mpls
tags and the last one is incomplete.
^ permalink raw reply [flat|nested] 4+ messages in thread
* [PATCH v2] lib/net: add MPLS insert and strip functionality
@ 2023-02-19 22:43 Tanzeel-inline
2023-02-24 11:25 ` [PATCH v3] " Tanzeel-inline
0 siblings, 1 reply; 4+ messages in thread
From: Tanzeel-inline @ 2023-02-19 22:43 UTC (permalink / raw)
To: olivier.matz, thomas; +Cc: dev, Tanzeel Ahmed
From: Tanzeel Ahmed <tanxeel1.ahmed@gmail.com>
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 <tanxeel1.ahmed@gmail.com>
---
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 <tyos@jp.ibm.com> <t.yoshimura8869@gmail.com>
Takuya Asada <syuu@cloudius-systems.com>
Tal Avraham <talavr@annapurnalabs.com>
Tal Shnaiderman <talshn@nvidia.com> <talshn@mellanox.com>
+Tanzeel Ahmed <tanxeel1.ahmed@gmail.com>
Tao Y Yang <tao.y.yang@intel.com>
Tao Zhu <taox.zhu@intel.com>
Taripin Samuel <samuel.taripin@intel.com>
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 <stdint.h>
#include <rte_byteorder.h>
+#include <rte_ether.h>
+#include <rte_mbuf.h>
#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
^ permalink raw reply [flat|nested] 4+ messages in thread
* [PATCH v3] lib/net: add MPLS insert and strip functionality
2023-02-19 22:43 [PATCH v2] " Tanzeel-inline
@ 2023-02-24 11:25 ` Tanzeel-inline
2023-02-24 16:29 ` Stephen Hemminger
0 siblings, 1 reply; 4+ messages in thread
From: Tanzeel-inline @ 2023-02-24 11:25 UTC (permalink / raw)
To: olivier.matz, thomas, tanzeelahmed713; +Cc: dev, Tanzeel Ahmed
From: Tanzeel Ahmed <tanxeel1.ahmed@gmail.com>
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 <tanxeel1.ahmed@gmail.com>
---
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 <tyos@jp.ibm.com> <t.yoshimura8869@gmail.com>
Takuya Asada <syuu@cloudius-systems.com>
Tal Avraham <talavr@annapurnalabs.com>
Tal Shnaiderman <talshn@nvidia.com> <talshn@mellanox.com>
+Tanzeel Ahmed <tanxeel1.ahmed@gmail.com>
Tao Y Yang <tao.y.yang@intel.com>
Tao Zhu <taox.zhu@intel.com>
Taripin Samuel <samuel.taripin@intel.com>
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 <stdint.h>
#include <rte_byteorder.h>
+#include <rte_ether.h>
+#include <rte_mbuf.h>
#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
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH v3] lib/net: add MPLS insert and strip functionality
2023-02-24 11:25 ` [PATCH v3] " Tanzeel-inline
@ 2023-02-24 16:29 ` Stephen Hemminger
0 siblings, 0 replies; 4+ messages in thread
From: Stephen Hemminger @ 2023-02-24 16:29 UTC (permalink / raw)
To: Tanzeel-inline; +Cc: olivier.matz, thomas, tanzeelahmed713, dev
On Fri, 24 Feb 2023 16:25:21 +0500
Tanzeel-inline <tanxeel1.ahmed@gmail.com> wrote:
> + oh = rte_pktmbuf_mtod(*m, struct rte_ether_hdr *);
> + nh = (struct rte_ether_hdr *)(void *)
> + rte_pktmbuf_prepend(*m, sizeof(struct rte_mpls_hdr));
Don't need void * cast. Can cast result of prepend (char *) to ether header directly.
Note: rte_pktmbuf_append/prepend should have been written initially to
return void * to reduce the number of casts.
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2024-10-03 18:46 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-02-24 11:06 [PATCH v3] lib/net: add MPLS insert and strip functionality Tanzeel-inline
2024-10-03 18:46 ` Stephen Hemminger
-- strict thread matches above, loose matches on Subject: below --
2023-02-19 22:43 [PATCH v2] " Tanzeel-inline
2023-02-24 11:25 ` [PATCH v3] " Tanzeel-inline
2023-02-24 16:29 ` Stephen Hemminger
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).