From mboxrd@z Thu Jan  1 00:00:00 1970
Return-Path: <dev-bounces@dpdk.org>
Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124])
	by inbox.dpdk.org (Postfix) with ESMTP id 9396C41D63;
	Fri, 24 Feb 2023 12:06:30 +0100 (CET)
Received: from mails.dpdk.org (localhost [127.0.0.1])
	by mails.dpdk.org (Postfix) with ESMTP id 73AD040697;
	Fri, 24 Feb 2023 12:06:30 +0100 (CET)
Received: from mail-wm1-f53.google.com (mail-wm1-f53.google.com
 [209.85.128.53]) by mails.dpdk.org (Postfix) with ESMTP id 1D55240693
 for <dev@dpdk.org>; Fri, 24 Feb 2023 12:06:29 +0100 (CET)
Received: by mail-wm1-f53.google.com with SMTP id
 d41-20020a05600c4c2900b003e9e066550fso1488847wmp.4
 for <dev@dpdk.org>; Fri, 24 Feb 2023 03:06:29 -0800 (PST)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112;
 h=content-transfer-encoding:mime-version:message-id:date:subject:cc
 :to:from:from:to:cc:subject:date:message-id:reply-to;
 bh=NpwUD7q1UT78xG4hzHuN3KGwnr20rw/6fGf1ERB3cA0=;
 b=SvKB7IMyX2KfJY5iKJpwHPjOC2q1IJJ5JubBTxr9X6XF3rhoXLf4nLt7ryCP/h1FJ2
 51G6rtTocxbjjbi10qSyWgcSoLGOCQs5ldSxCGZgYuBiIRTFRvSCh7w99NrGE5mv8h+3
 Xzy9uDqX/KIINCIQ7cQ9997G+GBwovM1PTY/7VxzSnXUMjLzTsX3nOvxRa66VXA+UeKg
 9KbPs5bXKJGWQ+ypgCgFe5yESPhlmgp8t+NQy7TvEYrTubYSY4YH7l125pwVRTwcZXgz
 VJlHimwoFxzbTCXudjdr3C8Kvtqxj/oHlilKjmK5/EwIHDUjKvdQRTC+XCBefiEzM8Wk
 Yj3Q==
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
 d=1e100.net; s=20210112;
 h=content-transfer-encoding:mime-version:message-id:date:subject:cc
 :to:from:x-gm-message-state:from:to:cc:subject:date:message-id
 :reply-to;
 bh=NpwUD7q1UT78xG4hzHuN3KGwnr20rw/6fGf1ERB3cA0=;
 b=W7l69QS47hg5UHeqXohlrzMeafsUzO8DKyPFgoRIHSSxbZ55sxMKs7sn6Jgx4d3SRl
 9cFFmjd/ssYT0JCsZta1wd1qFKjjxli4P1HVquhMDKa5G1b7MMyLIE1O8r7mEHRp8BI2
 rBs1BnMZNx3XJmBs0J8b9aHcwQCe2zBvmIW2n5GGwzvEVyBEfeMDfFf/bJ41fsFdy630
 JxYgerhcBfx3uvuLFwtPIVmkWOrJ7KPkfT+WFLbnOLHvGsPd9nFwom5GRK+5d3qoY6jC
 j8LvZ6rw5sqMNvlfMbMRv9W5nzj6g5HLuT71vjIADr9E3ZxJ+pBEno4BMircFy5mzV71
 G1Nw==
X-Gm-Message-State: AO0yUKXzqtW1n+OtIIW44uQDM1vJuH/mO+Pmdg6wWYLdOfvqRfYq+//I
 2xAPiljvz3EOIjKlDROvYks=
X-Google-Smtp-Source: AK7set/PnmTcXqfH7iaEGE4izVPr3UvVHADcd4TbogrTanyvrOz3ffJdvyukSWz/+wlSe4tSGf2AtA==
X-Received: by 2002:a05:600c:1d0a:b0:3ea:c654:acf1 with SMTP id
 l10-20020a05600c1d0a00b003eac654acf1mr3226792wms.3.1677236788717; 
 Fri, 24 Feb 2023 03:06:28 -0800 (PST)
Received: from DESKTOP-KPIMD3E.localdomain
 ([2407:d000:f:9db9:a92c:5562:804c:14b1])
 by smtp.gmail.com with ESMTPSA id
 q15-20020a05600000cf00b002c559843748sm13880991wrx.10.2023.02.24.03.06.27
 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);
 Fri, 24 Feb 2023 03:06:28 -0800 (PST)
From: Tanzeel-inline <tanxeel1.ahmed@gmail.com>
To: olivier.matz@6wind.com,
	thomas@monjalon.net,
	tanzeelahmed713@gmail.com
Cc: dev@dpdk.org,
	Tanzeel Ahmed <tanxeel1.ahmed@gmail.com>
Subject: [PATCH v3] lib/net: add MPLS insert and strip functionality
Date: Fri, 24 Feb 2023 16:06:19 +0500
Message-Id: <20230224110619.665-1-tanxeel1.ahmed@gmail.com>
X-Mailer: git-send-email 2.34.1
MIME-Version: 1.0
Content-Transfer-Encoding: 8bit
X-BeenThere: dev@dpdk.org
X-Mailman-Version: 2.1.29
Precedence: list
List-Id: DPDK patches and discussions <dev.dpdk.org>
List-Unsubscribe: <https://mails.dpdk.org/options/dev>,
 <mailto:dev-request@dpdk.org?subject=unsubscribe>
List-Archive: <http://mails.dpdk.org/archives/dev/>
List-Post: <mailto:dev@dpdk.org>
List-Help: <mailto:dev-request@dpdk.org?subject=help>
List-Subscribe: <https://mails.dpdk.org/listinfo/dev>,
 <mailto:dev-request@dpdk.org?subject=subscribe>
Errors-To: dev-bounces@dpdk.org

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