[dpdk-dev] [PATCH] ip_pipeline: routing pipeline improvements

Jasvinder Singh jasvinder.singh at intel.com
Sat May 7 01:57:51 CEST 2016


This patch implements the tracking mechanism for the routing pipeline in
order to identify the physical nic port where a specific output port of
the rotuing pipeline is eventually connected. Depending upon the
application, tracking could involve traversing the other intermediate
pipelines.

Typically, tracking is successful through those intermediate pipelines
where each input port is connected to a single out port for example
pass-through (RX, TX and TM), flow-actions etc. In such pipelines, all
the packets from the current port can only go out of the idetified output
port. In contrast, the pipelines such as flow-classification, firewall
don't allow the tracking mechanism due to one to many mapping between input
and output ports.

As a result of tracking mechainsm, routing pipeline uses the real MAC
addresses of the network interfaces instead of hardcoded default value.
Furthermore, it allows adding/removing the implicit routes every time when
the corresponding physical nic port is brought up/down.

Signed-off-by: Jasvinder Singh <jasvinder.singh at intel.com>
---
 examples/ip_pipeline/app.h                         | 137 +++++++++++++++++++++
 examples/ip_pipeline/pipeline/pipeline_common_fe.c |  88 +++++++++++++
 examples/ip_pipeline/pipeline/pipeline_common_fe.h |   5 +
 examples/ip_pipeline/pipeline/pipeline_routing.c   |  62 +++++++++-
 examples/ip_pipeline/pipeline/pipeline_routing.h   |   7 ++
 .../ip_pipeline/pipeline/pipeline_routing_be.c     |  37 ++++--
 .../ip_pipeline/pipeline/pipeline_routing_be.h     |  15 +++
 7 files changed, 341 insertions(+), 10 deletions(-)

diff --git a/examples/ip_pipeline/app.h b/examples/ip_pipeline/app.h
index 55a9841..803e42e 100644
--- a/examples/ip_pipeline/app.h
+++ b/examples/ip_pipeline/app.h
@@ -665,6 +665,40 @@ app_swq_get_readers(struct app_params *app, struct app_pktq_swq_params *swq)
 	return n_readers;
 }
 
+static inline struct app_pipeline_params *
+app_swq_get_reader(struct app_params *app, struct app_pktq_swq_params *swq,
+	uint32_t *pktq_in_id)
+{
+	struct app_pipeline_params *reader;
+	uint32_t pos = swq - app->swq_params;
+	uint32_t n_pipelines = RTE_MIN(app->n_pipelines,
+		RTE_DIM(app->pipeline_params));
+	uint32_t n_readers = 0, id, i;
+
+	for (i = 0; i < n_pipelines; i++) {
+		struct app_pipeline_params *p = &app->pipeline_params[i];
+		uint32_t n_pktq_in = RTE_MIN(p->n_pktq_in, RTE_DIM(p->pktq_in));
+		uint32_t j;
+
+		for (j = 0; j < n_pktq_in; j++) {
+			struct app_pktq_in_params *pktq = &p->pktq_in[j];
+
+			if ((pktq->type == APP_PKTQ_IN_SWQ) &&
+				(pktq->id == pos)) {
+				n_readers++;
+				reader = p;
+				id = j;
+			}
+		}
+	}
+
+	if (n_readers != 1)
+		return NULL;
+
+	*pktq_in_id = id;
+	return reader;
+}
+
 static inline uint32_t
 app_tm_get_readers(struct app_params *app, struct app_pktq_tm_params *tm)
 {
@@ -690,6 +724,40 @@ app_tm_get_readers(struct app_params *app, struct app_pktq_tm_params *tm)
 	return n_readers;
 }
 
+static inline struct app_pipeline_params *
+app_tm_get_reader(struct app_params *app, struct app_pktq_tm_params *tm,
+	uint32_t *pktq_in_id)
+{
+	struct app_pipeline_params *reader;
+	uint32_t pos = tm - app->tm_params;
+	uint32_t n_pipelines = RTE_MIN(app->n_pipelines,
+		RTE_DIM(app->pipeline_params));
+	uint32_t n_readers = 0, id, i;
+
+	for (i = 0; i < n_pipelines; i++) {
+		struct app_pipeline_params *p = &app->pipeline_params[i];
+		uint32_t n_pktq_in = RTE_MIN(p->n_pktq_in, RTE_DIM(p->pktq_in));
+		uint32_t j;
+
+		for (j = 0; j < n_pktq_in; j++) {
+			struct app_pktq_in_params *pktq = &p->pktq_in[j];
+
+			if ((pktq->type == APP_PKTQ_IN_TM) &&
+				(pktq->id == pos)) {
+				n_readers++;
+				reader = p;
+				id = j;
+			}
+		}
+	}
+
+	if (n_readers != 1)
+		return NULL;
+
+	*pktq_in_id = id;
+	return reader;
+}
+
 static inline uint32_t
 app_source_get_readers(struct app_params *app,
 struct app_pktq_source_params *source)
@@ -789,6 +857,41 @@ app_swq_get_writers(struct app_params *app, struct app_pktq_swq_params *swq)
 	return n_writers;
 }
 
+static inline struct app_pipeline_params *
+app_swq_get_writer(struct app_params *app, struct app_pktq_swq_params *swq,
+	uint32_t *pktq_out_id)
+{
+	struct app_pipeline_params *writer;
+	uint32_t pos = swq - app->swq_params;
+	uint32_t n_pipelines = RTE_MIN(app->n_pipelines,
+		RTE_DIM(app->pipeline_params));
+	uint32_t n_writers = 0, id, i;
+
+	for (i = 0; i < n_pipelines; i++) {
+		struct app_pipeline_params *p = &app->pipeline_params[i];
+		uint32_t n_pktq_out = RTE_MIN(p->n_pktq_out,
+			RTE_DIM(p->pktq_out));
+		uint32_t j;
+
+		for (j = 0; j < n_pktq_out; j++) {
+			struct app_pktq_out_params *pktq = &p->pktq_out[j];
+
+			if ((pktq->type == APP_PKTQ_OUT_SWQ) &&
+				(pktq->id == pos)) {
+				n_writers++;
+				writer = p;
+				id = j;
+			}
+		}
+	}
+
+	if (n_writers != 1)
+		return NULL;
+
+	*pktq_out_id = id;
+	return writer;
+}
+
 static inline uint32_t
 app_tm_get_writers(struct app_params *app, struct app_pktq_tm_params *tm)
 {
@@ -815,6 +918,40 @@ app_tm_get_writers(struct app_params *app, struct app_pktq_tm_params *tm)
 	return n_writers;
 }
 
+static inline struct app_pipeline_params *
+app_tm_get_writer(struct app_params *app, struct app_pktq_tm_params *tm,
+	uint32_t *pktq_out_id)
+{
+	struct app_pipeline_params *writer;
+	uint32_t pos = tm - app->tm_params;
+	uint32_t n_pipelines = RTE_MIN(app->n_pipelines,
+		RTE_DIM(app->pipeline_params));
+	uint32_t n_writers = 0, id, i;
+
+	for (i = 0; i < n_pipelines; i++) {
+		struct app_pipeline_params *p = &app->pipeline_params[i];
+		uint32_t n_pktq_out = RTE_MIN(p->n_pktq_out,
+			RTE_DIM(p->pktq_out));
+		uint32_t j;
+
+		for (j = 0; j < n_pktq_out; j++) {
+			struct app_pktq_out_params *pktq = &p->pktq_out[j];
+
+			if ((pktq->type == APP_PKTQ_OUT_TM) &&
+				(pktq->id == pos))
+				n_writers++;
+				writer = p;
+				id = j;
+		}
+	}
+
+	if (n_writers != 1)
+		return NULL;
+
+	*pktq_out_id = id;
+	return writer;
+}
+
 static inline uint32_t
 app_sink_get_writers(struct app_params *app, struct app_pktq_sink_params *sink)
 {
diff --git a/examples/ip_pipeline/pipeline/pipeline_common_fe.c b/examples/ip_pipeline/pipeline/pipeline_common_fe.c
index a691d42..e29d9a1 100644
--- a/examples/ip_pipeline/pipeline/pipeline_common_fe.c
+++ b/examples/ip_pipeline/pipeline/pipeline_common_fe.c
@@ -49,6 +49,94 @@
 
 #include "pipeline_common_fe.h"
 
+struct app_link_params *
+app_pipeline_track_pktq_out_to_link(struct app_params *app,
+	uint32_t pipeline_id,
+	uint32_t pktq_out_id)
+{
+	struct app_pipeline_params *p;
+
+	/* Check input arguments */
+	if (app == NULL)
+		return NULL;
+
+	APP_PARAM_FIND_BY_ID(app->pipeline_params, "PIPELINE", pipeline_id, p);
+	if (p == NULL)
+		return NULL;
+
+	for ( ; ; ) {
+		struct app_pktq_out_params *pktq_out =
+			&p->pktq_out[pktq_out_id];
+
+		switch (pktq_out->type) {
+		case APP_PKTQ_OUT_HWQ:
+		{
+			struct app_pktq_hwq_out_params *hwq_out;
+
+			hwq_out = &app->hwq_out_params[pktq_out->id];
+
+			return app_get_link_for_txq(app, hwq_out);
+		}
+
+		case APP_PKTQ_OUT_SWQ:
+		{
+			struct app_pipeline_data *pdata;
+			struct app_pktq_swq_params *swq;
+			uint32_t pktq_in_id;
+			int status;
+
+			swq = &app->swq_params[pktq_out->id];
+			p = app_swq_get_reader(app, swq, &pktq_in_id);
+			if (p == NULL)
+				return NULL;
+
+			pipeline_id = p - app->pipeline_params;
+			pdata = &app->pipeline_data[pipeline_id];
+			if (pdata->ptype->be_ops->f_track == NULL)
+				return NULL;
+
+			status = pdata->ptype->be_ops->f_track(pdata->be,
+				pktq_in_id,
+				&pktq_out_id);
+			if (status)
+				return NULL;
+
+			break;
+		}
+
+		case APP_PKTQ_OUT_TM:
+		{
+			struct app_pipeline_data *pdata;
+			struct app_pktq_tm_params *tm;
+			uint32_t pktq_in_id;
+			int status;
+
+			tm = &app->tm_params[pktq_out->id];
+			p = app_tm_get_reader(app, tm, &pktq_in_id);
+			if (p == NULL)
+				return NULL;
+
+			pipeline_id = p - app->pipeline_params;
+			pdata = &app->pipeline_data[pipeline_id];
+			if (pdata->ptype->be_ops->f_track == NULL)
+				return NULL;
+
+			status = pdata->ptype->be_ops->f_track(pdata->be,
+				pktq_in_id,
+				&pktq_out_id);
+			if (status)
+				return NULL;
+
+			break;
+		}
+
+		case APP_PKTQ_OUT_SINK:
+		default:
+			return NULL;
+		}
+	}
+}
+
 int
 app_pipeline_ping(struct app_params *app,
 	uint32_t pipeline_id)
diff --git a/examples/ip_pipeline/pipeline/pipeline_common_fe.h b/examples/ip_pipeline/pipeline/pipeline_common_fe.h
index cfad963..7fa6ea9 100644
--- a/examples/ip_pipeline/pipeline/pipeline_common_fe.h
+++ b/examples/ip_pipeline/pipeline/pipeline_common_fe.h
@@ -182,6 +182,11 @@ app_msg_send_recv(struct app_params *app,
 	return msg_recv;
 }
 
+struct app_link_params *
+app_pipeline_track_pktq_out_to_link(struct app_params *app,
+	uint32_t pipeline_id,
+	uint32_t pktq_out_id);
+
 int
 app_pipeline_ping(struct app_params *app,
 	uint32_t pipeline_id);
diff --git a/examples/ip_pipeline/pipeline/pipeline_routing.c b/examples/ip_pipeline/pipeline/pipeline_routing.c
index eab89f2..d890cc8 100644
--- a/examples/ip_pipeline/pipeline/pipeline_routing.c
+++ b/examples/ip_pipeline/pipeline/pipeline_routing.c
@@ -81,10 +81,11 @@ struct pipeline_routing {
 
 static void *
 pipeline_routing_init(struct pipeline_params *params,
-	__rte_unused void *arg)
+	void *arg)
 {
+	struct app_params *app = (struct app_params *) arg;
 	struct pipeline_routing *p;
-	uint32_t size;
+	uint32_t pipeline_id, size;
 
 	/* Check input arguments */
 	if ((params == NULL) ||
@@ -108,6 +109,9 @@ pipeline_routing_init(struct pipeline_params *params,
 	TAILQ_INIT(&p->arp_entries);
 	p->n_arp_entries = 0;
 
+	APP_PARAM_GET_ID(params, "PIPELINE", pipeline_id);
+	app_pipeline_routing_set_macaddr(app, pipeline_id);
+
 	return p;
 }
 
@@ -853,6 +857,60 @@ app_pipeline_routing_delete_default_arp_entry(struct app_params *app,
 	return 0;
 }
 
+int
+app_pipeline_routing_set_macaddr(struct app_params *app,
+	uint32_t pipeline_id)
+{
+	struct pipeline_routing *p;
+
+	struct pipeline_routing_set_macaddr_msg_req *req;
+	struct pipeline_routing_set_macaddr_msg_rsp *rsp;
+	uint32_t port_id;
+
+	/* Check input arguments */
+	if (app == NULL)
+		return -1;
+
+	p = app_pipeline_data_fe(app, pipeline_id, &pipeline_routing);
+	if (p == NULL)
+		return -EINVAL;
+
+	/* Allocate and write request */
+	req = app_msg_alloc(app);
+	if (req == NULL)
+		return -ENOMEM;
+
+	req->type = PIPELINE_MSG_REQ_CUSTOM;
+	req->subtype = PIPELINE_ROUTING_MSG_REQ_SET_MACADDR;
+
+	memset(req->macaddr, 0, sizeof(req->macaddr));
+	for (port_id = 0; port_id < p->n_ports_out; port_id++) {
+		struct app_link_params *link;
+
+		link = app_pipeline_track_pktq_out_to_link(app,
+			pipeline_id,
+			port_id);
+		if (link)
+			req->macaddr[port_id] = link->mac_addr;
+	}
+
+	/* Send request and wait for response */
+	rsp = app_msg_send_recv(app, pipeline_id, req, MSG_TIMEOUT_DEFAULT);
+	if (rsp == NULL)
+		return -ETIMEDOUT;
+
+	/* Read response and write entry */
+	if (rsp->status) {
+		app_msg_free(app, rsp);
+		return rsp->status;
+	}
+
+	/* Free response */
+	app_msg_free(app, rsp);
+
+	return 0;
+}
+
 static int
 parse_labels(char *string, uint32_t *labels, uint32_t *n_labels)
 {
diff --git a/examples/ip_pipeline/pipeline/pipeline_routing.h b/examples/ip_pipeline/pipeline/pipeline_routing.h
index fa41642..0197449 100644
--- a/examples/ip_pipeline/pipeline/pipeline_routing.h
+++ b/examples/ip_pipeline/pipeline/pipeline_routing.h
@@ -86,6 +86,13 @@ app_pipeline_routing_delete_default_arp_entry(struct app_params *app,
 	uint32_t pipeline_id);
 
 /*
+ * SETTINGS
+ */
+int
+app_pipeline_routing_set_macaddr(struct app_params *app,
+	uint32_t pipeline_id);
+
+/*
  * Pipeline type
  */
 extern struct pipeline_type pipeline_routing;
diff --git a/examples/ip_pipeline/pipeline/pipeline_routing_be.c b/examples/ip_pipeline/pipeline/pipeline_routing_be.c
index bc5bf7a..d22a465 100644
--- a/examples/ip_pipeline/pipeline/pipeline_routing_be.c
+++ b/examples/ip_pipeline/pipeline/pipeline_routing_be.c
@@ -65,8 +65,6 @@
 	((((uint64_t) (pipe)) & 0xFFFFFFFF) << 32))
 
 
-#define MAC_SRC_DEFAULT 0x112233445566ULL
-
 #ifndef PIPELINE_ROUTING_LPM_TABLE_NUMBER_TABLE8s
 #define PIPELINE_ROUTING_LPM_TABLE_NUMBER_TABLE8s 256
 #endif
@@ -74,6 +72,7 @@
 struct pipeline_routing {
 	struct pipeline p;
 	struct pipeline_routing_params params;
+	uint64_t macaddr[PIPELINE_MAX_PORT_OUT];
 	pipeline_msg_req_handler custom_handlers[PIPELINE_ROUTING_MSG_REQS];
 } __rte_cache_aligned;
 
@@ -132,6 +131,10 @@ static void *
 pipeline_routing_msg_req_arp_del_default_handler(struct pipeline *p,
 	void *msg);
 
+static void *
+pipeline_routing_msg_req_set_macaddr_handler(struct pipeline *p,
+	void *msg);
+
 static pipeline_msg_req_handler custom_handlers[] = {
 	[PIPELINE_ROUTING_MSG_REQ_ROUTE_ADD] =
 		pipeline_routing_msg_req_route_add_handler,
@@ -149,6 +152,8 @@ static pipeline_msg_req_handler custom_handlers[] = {
 		pipeline_routing_msg_req_arp_add_default_handler,
 	[PIPELINE_ROUTING_MSG_REQ_ARP_DEL_DEFAULT] =
 		pipeline_routing_msg_req_arp_del_default_handler,
+	[PIPELINE_ROUTING_MSG_REQ_SET_MACADDR] =
+		pipeline_routing_msg_req_set_macaddr_handler,
 };
 
 /*
@@ -1534,7 +1539,7 @@ pipeline_routing_msg_req_route_add_handler(struct pipeline *p, void *msg)
 	/* Ether - ARP off */
 	if ((p_rt->params.encap == PIPELINE_ROUTING_ENCAP_ETHERNET) &&
 		(p_rt->params.n_arp_entries == 0)) {
-		uint64_t macaddr_src = MAC_SRC_DEFAULT;
+		uint64_t macaddr_src = p_rt->macaddr[req->data.port_id];
 		uint64_t macaddr_dst;
 		uint64_t ethertype = ETHER_TYPE_IPv4;
 
@@ -1556,7 +1561,7 @@ pipeline_routing_msg_req_route_add_handler(struct pipeline *p, void *msg)
 	/* Ether - ARP on */
 	if ((p_rt->params.encap == PIPELINE_ROUTING_ENCAP_ETHERNET) &&
 		p_rt->params.n_arp_entries) {
-		uint64_t macaddr_src = MAC_SRC_DEFAULT;
+		uint64_t macaddr_src = p_rt->macaddr[req->data.port_id];
 		uint64_t ethertype = ETHER_TYPE_IPv4;
 
 		entry_arp1.slab[0] = rte_bswap64((macaddr_src << 16) |
@@ -1571,7 +1576,7 @@ pipeline_routing_msg_req_route_add_handler(struct pipeline *p, void *msg)
 	/* Ether QinQ - ARP off */
 	if ((p_rt->params.encap == PIPELINE_ROUTING_ENCAP_ETHERNET_QINQ) &&
 		(p_rt->params.n_arp_entries == 0)) {
-		uint64_t macaddr_src = MAC_SRC_DEFAULT;
+		uint64_t macaddr_src = p_rt->macaddr[req->data.port_id];
 		uint64_t macaddr_dst;
 		uint64_t ethertype_ipv4 = ETHER_TYPE_IPv4;
 		uint64_t ethertype_vlan = 0x8100;
@@ -1603,7 +1608,7 @@ pipeline_routing_msg_req_route_add_handler(struct pipeline *p, void *msg)
 	/* Ether QinQ - ARP on */
 	if ((p_rt->params.encap == PIPELINE_ROUTING_ENCAP_ETHERNET_QINQ) &&
 		p_rt->params.n_arp_entries) {
-		uint64_t macaddr_src = MAC_SRC_DEFAULT;
+		uint64_t macaddr_src = p_rt->macaddr[req->data.port_id];
 		uint64_t ethertype_ipv4 = ETHER_TYPE_IPv4;
 		uint64_t ethertype_vlan = 0x8100;
 		uint64_t ethertype_qinq = 0x9100;
@@ -1628,7 +1633,7 @@ pipeline_routing_msg_req_route_add_handler(struct pipeline *p, void *msg)
 	/* Ether MPLS - ARP off */
 	if ((p_rt->params.encap == PIPELINE_ROUTING_ENCAP_ETHERNET_MPLS) &&
 		(p_rt->params.n_arp_entries == 0)) {
-		uint64_t macaddr_src = MAC_SRC_DEFAULT;
+		uint64_t macaddr_src = p_rt->macaddr[req->data.port_id];
 		uint64_t macaddr_dst;
 		uint64_t ethertype_mpls = 0x8847;
 
@@ -1714,7 +1719,7 @@ pipeline_routing_msg_req_route_add_handler(struct pipeline *p, void *msg)
 	/* Ether MPLS - ARP on */
 	if ((p_rt->params.encap == PIPELINE_ROUTING_ENCAP_ETHERNET_MPLS) &&
 		p_rt->params.n_arp_entries) {
-		uint64_t macaddr_src = MAC_SRC_DEFAULT;
+		uint64_t macaddr_src = p_rt->macaddr[req->data.port_id];
 		uint64_t ethertype_mpls = 0x8847;
 
 		uint64_t label0 = req->data.l2.mpls.labels[0];
@@ -1961,6 +1966,22 @@ pipeline_routing_msg_req_arp_del_default_handler(struct pipeline *p, void *msg)
 	return rsp;
 }
 
+void *
+pipeline_routing_msg_req_set_macaddr_handler(struct pipeline *p, void *msg)
+{
+	struct pipeline_routing *p_rt = (struct pipeline_routing *) p;
+	struct pipeline_routing_set_macaddr_msg_req *req = msg;
+	struct pipeline_routing_set_macaddr_msg_rsp *rsp = msg;
+	uint32_t port_id;
+
+	for (port_id = 0; port_id < p->n_ports_out; port_id++)
+		p_rt->macaddr[port_id] = req->macaddr[port_id];
+
+	rsp->status = 0;
+
+	return rsp;
+}
+
 struct pipeline_be_ops pipeline_routing_be_ops = {
 	.f_init = pipeline_routing_init,
 	.f_free = pipeline_routing_free,
diff --git a/examples/ip_pipeline/pipeline/pipeline_routing_be.h b/examples/ip_pipeline/pipeline/pipeline_routing_be.h
index ec767b2..822995b 100644
--- a/examples/ip_pipeline/pipeline/pipeline_routing_be.h
+++ b/examples/ip_pipeline/pipeline/pipeline_routing_be.h
@@ -160,6 +160,7 @@ enum pipeline_routing_msg_req_type {
 	PIPELINE_ROUTING_MSG_REQ_ARP_DEL,
 	PIPELINE_ROUTING_MSG_REQ_ARP_ADD_DEFAULT,
 	PIPELINE_ROUTING_MSG_REQ_ARP_DEL_DEFAULT,
+	PIPELINE_ROUTING_MSG_REQ_SET_MACADDR,
 	PIPELINE_ROUTING_MSG_REQS
 };
 
@@ -291,6 +292,20 @@ struct pipeline_routing_arp_delete_default_msg_rsp {
 	int status;
 };
 
+/*
+ * MSG SET MACADDR
+ */
+struct pipeline_routing_set_macaddr_msg_req {
+	enum pipeline_msg_req_type type;
+	enum pipeline_routing_msg_req_type subtype;
+
+	uint64_t macaddr[PIPELINE_MAX_PORT_OUT];
+};
+
+struct pipeline_routing_set_macaddr_msg_rsp {
+	int status;
+};
+
 extern struct pipeline_be_ops pipeline_routing_be_ops;
 
 #endif
-- 
2.5.5



More information about the dev mailing list