<div dir="ltr">Gentle Ping</div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Tue, Apr 18, 2023 at 6:18 PM Tanzeel Ahmed <<a href="mailto:tanxeel1.ahmed@gmail.com">tanxeel1.ahmed@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr">Ping.</div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Thu, Mar 9, 2023 at 11:35 PM Tanzeel Ahmed <<a href="mailto:tanxeel1.ahmed@gmail.com" target="_blank">tanxeel1.ahmed@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr">Any updates?</div><div dir="ltr"><br></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Sat, Feb 25, 2023 at 6:53 PM Tanzeel-inline <<a href="mailto:tanxeel1.ahmed@gmail.com" target="_blank">tanxeel1.ahmed@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">From: Tanzeel Ahmed <<a href="mailto:tanxeel1.ahmed@gmail.com" target="_blank">tanxeel1.ahmed@gmail.com</a>><br>
<br>
This patch is new version of [PATCH] lib/net: added push MPLS header API.<br>
I have also added the MPLS strip functionality to address the question<br>
asked in last patch.<br>
<br>
> You should explain why you add this function.<br>
None of the foundational NICs currently supports MPLS insertion and<br>
stripping, this functionality can help users who rely on MPLS in their<br>
network application.<br>
<br>
> I'm not sure it should be inline<br>
I did for performance in high-traffic application.<br>
<br>
Signed-off-by: Tanzeel Ahmed <<a href="mailto:tanxeel1.ahmed@gmail.com" target="_blank">tanxeel1.ahmed@gmail.com</a>><br>
<br>
---<br>
v4:<br>
* Removed extra void cast.<br>
* rte_pktmbuf_append/mtod now return void*.<br>
  The memmove result is casted to rte_ether_hdr*.<br>
<br>
v3:<br>
* fixed patch check failure issue<br>
<br>
v2:<br>
* marked experimental<br>
* coding style fixed<br>
* changed rte_memcpy to memcpy<br>
* mpls header marked as const in parameter<br>
* added MPLS stripping functionality<br>
---<br>
 .mailmap           |  1 +<br>
 lib/net/rte_mpls.h | 97 ++++++++++++++++++++++++++++++++++++++++++++++++++++++<br>
 2 files changed, 98 insertions(+)<br>
<br>
diff --git a/.mailmap b/.mailmap<br>
index a9f4f28..2af4e0d 100644<br>
--- a/.mailmap<br>
+++ b/.mailmap<br>
@@ -1312,6 +1312,7 @@ Takeshi Yoshimura <<a href="mailto:tyos@jp.ibm.com" target="_blank">tyos@jp.ibm.com</a>> <<a href="mailto:t.yoshimura8869@gmail.com" target="_blank">t.yoshimura8869@gmail.com</a>><br>
 Takuya Asada <<a href="mailto:syuu@cloudius-systems.com" target="_blank">syuu@cloudius-systems.com</a>><br>
 Tal Avraham <<a href="mailto:talavr@annapurnalabs.com" target="_blank">talavr@annapurnalabs.com</a>><br>
 Tal Shnaiderman <<a href="mailto:talshn@nvidia.com" target="_blank">talshn@nvidia.com</a>> <<a href="mailto:talshn@mellanox.com" target="_blank">talshn@mellanox.com</a>><br>
+Tanzeel Ahmed <<a href="mailto:tanxeel1.ahmed@gmail.com" target="_blank">tanxeel1.ahmed@gmail.com</a>><br>
 Tao Y Yang <<a href="mailto:tao.y.yang@intel.com" target="_blank">tao.y.yang@intel.com</a>><br>
 Tao Zhu <<a href="mailto:taox.zhu@intel.com" target="_blank">taox.zhu@intel.com</a>><br>
 Taripin Samuel <<a href="mailto:samuel.taripin@intel.com" target="_blank">samuel.taripin@intel.com</a>><br>
diff --git a/lib/net/rte_mpls.h b/lib/net/rte_mpls.h<br>
index 51523e7..d7e267f 100644<br>
--- a/lib/net/rte_mpls.h<br>
+++ b/lib/net/rte_mpls.h<br>
@@ -13,6 +13,8 @@<br>
<br>
 #include <stdint.h><br>
 #include <rte_byteorder.h><br>
+#include <rte_ether.h><br>
+#include <rte_mbuf.h><br>
<br>
 #ifdef __cplusplus<br>
 extern "C" {<br>
@@ -36,6 +38,101 @@ struct rte_mpls_hdr {<br>
        uint8_t  ttl;       /**< Time to live. */<br>
 } __rte_packed;<br>
<br>
+#define RTE_MPLS_HLEN 4 /**< Length of MPLS header. */<br>
+<br>
+/**<br>
+ * @warning<br>
+ * @b EXPERIMENTAL: this API may change without prior notice.<br>
+ *<br>
+ * Insert MPLS header into the packet.<br>
+ * If it's first MPLS header to be inserted in the packet,<br>
+ *  - Updates the ether type.<br>
+ *  - Sets the MPLS bottom-of-stack bit to 1.<br>
+ *<br>
+ * @param m<br>
+ *   The pointer to the mbuf.<br>
+ * @param mp<br>
+ *   The pointer to the MPLS header.<br>
+ * @return<br>
+ *   0 on success, -1 on error<br>
+ */<br>
+__rte_experimental<br>
+static inline int<br>
+rte_mpls_push_over_l2(struct rte_mbuf **m, const struct rte_mpls_hdr *mp)<br>
+{<br>
+       void *os, *ns;<br>
+       struct rte_ether_hdr *nh;<br>
+       struct rte_mpls_hdr *mph;<br>
+<br>
+       /* Can't insert header if mbuf is shared */<br>
+       if (!RTE_MBUF_DIRECT(*m) || rte_mbuf_refcnt_read(*m) > 1)<br>
+               return -EINVAL;<br>
+<br>
+       /* Can't insert header if ethernet frame doesn't exist */<br>
+       if (rte_pktmbuf_data_len(*m) < RTE_ETHER_HDR_LEN)<br>
+               return -EINVAL;<br>
+<br>
+       os = rte_pktmbuf_mtod(*m, void *);<br>
+       ns = (void *)rte_pktmbuf_prepend(*m, sizeof(struct rte_mpls_hdr));<br>
+       if (ns == NULL)<br>
+               return -ENOSPC;<br>
+<br>
+       nh = (struct rte_ether_hdr *)memmove(ns, os, RTE_ETHER_HDR_LEN);<br>
+<br>
+       /* Copy the MPLS header after ethernet frame */<br>
+       mph = rte_pktmbuf_mtod_offset(*m, struct rte_mpls_hdr*,<br>
+                       sizeof(struct rte_ether_hdr));<br>
+       memcpy(mph, mp, RTE_MPLS_HLEN);<br>
+<br>
+       mph->tag_msb = rte_cpu_to_be_16(mp->tag_msb);<br>
+<br>
+       /* If first MPLS header, update ether type and bottom-of-stack bit */<br>
+       if (nh->ether_type != rte_cpu_to_be_16(RTE_ETHER_TYPE_MPLS)) {<br>
+               nh->ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_MPLS);<br>
+               mph->bs = 1;<br>
+       } else {<br>
+               mph->bs = 0;<br>
+       }<br>
+<br>
+       return 0;<br>
+}<br>
+<br>
+/**<br>
+ * @warning<br>
+ * @b EXPERIMENTAL: this API may change without prior notice.<br>
+ *<br>
+ * Strips MPLS from the packet. Doesn't update the ether type<br>
+ *<br>
+ * @param m<br>
+ *   The pointer to the mbuf.<br>
+ * @return<br>
+ *   0 on success, -1 on error<br>
+ */<br>
+__rte_experimental<br>
+static inline int<br>
+rte_mpls_strip_over_l2(struct rte_mbuf *m)<br>
+{<br>
+       struct rte_ether_hdr *eh = rte_pktmbuf_mtod(m, struct rte_ether_hdr *);<br>
+       struct rte_mpls_hdr *mph;<br>
+       bool mpls_exist = true;<br>
+<br>
+       if (eh->ether_type != rte_cpu_to_be_16(RTE_ETHER_TYPE_MPLS))<br>
+               return -1;<br>
+<br>
+       /* Stripping all MPLS header */<br>
+       while (mpls_exist) {<br>
+               mph = rte_pktmbuf_mtod_offset(m, struct rte_mpls_hdr*,<br>
+               sizeof(struct rte_ether_hdr));<br>
+               if (mph->bs & 1)<br>
+                       mpls_exist = false;<br>
+               memmove(rte_pktmbuf_adj(m, sizeof(struct rte_mpls_hdr)),<br>
+               eh, sizeof(struct rte_ether_hdr));<br>
+               eh = rte_pktmbuf_mtod(m, struct rte_ether_hdr *);<br>
+       }<br>
+<br>
+       return 0;<br>
+}<br>
+<br>
 #ifdef __cplusplus<br>
 }<br>
 #endif<br>
-- <br>
1.8.3.1<br>
<br>
</blockquote></div>
</blockquote></div>
</blockquote></div>