diff --git a/examples/ip_pipeline/app.h b/examples/ip_pipeline/app.h
index dfdfb51..93e96d0 100644
--- a/examples/ip_pipeline/app.h
+++ b/examples/ip_pipeline/app.h
@@ -205,9 +205,7 @@ struct app_pktq_out_params {
 	uint32_t id; /* Position in the appropriate app array */
 };
 
-#ifndef APP_PIPELINE_TYPE_SIZE
-#define APP_PIPELINE_TYPE_SIZE                   64
-#endif
+#define APP_PIPELINE_TYPE_SIZE                   PIPELINE_TYPE_SIZE
 
 #define APP_MAX_PIPELINE_PKTQ_IN                 PIPELINE_MAX_PORT_IN
 #define APP_MAX_PIPELINE_PKTQ_OUT                PIPELINE_MAX_PORT_OUT
@@ -651,6 +649,41 @@ 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)
 {
@@ -676,6 +709,41 @@ 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)
@@ -775,6 +843,42 @@ 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)
 {
@@ -801,6 +905,41 @@ 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)
 {
@@ -899,6 +1038,10 @@ app_get_link_for_tm(struct app_params *app, struct app_pktq_tm_params *p_tm)
 	return &app->link_params[link_param_idx];
 }
 
+void app_pipeline_params_get(struct app_params *app,
+	struct app_pipeline_params *p_in,
+	struct pipeline_params *p_out);
+
 int app_config_init(struct app_params *app);
 
 int app_config_args(struct app_params *app,
@@ -918,6 +1061,8 @@ int app_config_check(struct app_params *app);
 
 int app_init(struct app_params *app);
 
+int app_post_init(struct app_params *app);
+
 int app_thread(void *arg);
 
 int app_pipeline_type_register(struct app_params *app,
diff --git a/examples/ip_pipeline/init.c b/examples/ip_pipeline/init.c
index b2eafe3..7120bab 100644
--- a/examples/ip_pipeline/init.c
+++ b/examples/ip_pipeline/init.c
@@ -1196,7 +1196,7 @@ app_init_msgq(struct app_params *app)
 	}
 }
 
-static void app_pipeline_params_get(struct app_params *app,
+void app_pipeline_params_get(struct app_params *app,
 	struct app_pipeline_params *p_in,
 	struct pipeline_params *p_out)
 {
@@ -1204,6 +1204,8 @@ static void app_pipeline_params_get(struct app_params *app,
 
 	snprintf(p_out->name, PIPELINE_NAME_SIZE, "%s", p_in->name);
 
+	snprintf(p_out->type, PIPELINE_TYPE_SIZE, "%s", p_in->type);
+
 	p_out->socket_id = (int) p_in->socket_id;
 
 	p_out->log_level = app->log_level;
@@ -1499,6 +1501,27 @@ app_init_pipelines(struct app_params *app)
 }
 
 static void
+app_post_init_pipelines(struct app_params *app)
+{
+	uint32_t p_id;
+
+	for (p_id = 0; p_id < app->n_pipelines; p_id++) {
+		struct app_pipeline_params *params =
+			&app->pipeline_params[p_id];
+		struct app_pipeline_data *data = &app->pipeline_data[p_id];
+		int status;
+
+		if (data->ptype->fe_ops->f_post_init == NULL)
+			continue;
+
+		status = data->ptype->fe_ops->f_post_init(data->fe);
+		if (status)
+			rte_panic("Pipeline instance \"%s\" front-end "
+				"post-init error\n", params->name);
+	}
+}
+
+static void
 app_init_threads(struct app_params *app)
 {
 	uint64_t time = rte_get_tsc_cycles();
@@ -1601,6 +1624,13 @@ int app_init(struct app_params *app)
 	return 0;
 }
 
+int app_post_init(struct app_params *app)
+{
+	app_post_init_pipelines(app);
+
+	return 0;
+}
+
 static int
 app_pipeline_type_cmd_push(struct app_params *app,
 	struct pipeline_type *ptype)
diff --git a/examples/ip_pipeline/pipeline.h b/examples/ip_pipeline/pipeline.h
index dab9c36..14a551d 100644
--- a/examples/ip_pipeline/pipeline.h
+++ b/examples/ip_pipeline/pipeline.h
@@ -42,13 +42,22 @@
  * Pipeline type front-end operations
  */
 
-typedef void* (*pipeline_fe_op_init)(struct pipeline_params *params, void *arg);
+typedef void* (*pipeline_fe_op_init)(struct pipeline_params *params,
+	void *arg);
+
+typedef int (*pipeline_fe_op_post_init)(void *pipeline);
 
 typedef int (*pipeline_fe_op_free)(void *pipeline);
 
+typedef int (*pipeline_fe_op_track)(struct pipeline_params *params,
+	uint32_t port_in,
+	uint32_t *port_out);
+
 struct pipeline_fe_ops {
 	pipeline_fe_op_init f_init;
+	pipeline_fe_op_post_init f_post_init;
 	pipeline_fe_op_free f_free;
+	pipeline_fe_op_track f_track;
 	cmdline_parse_ctx_t *cmds;
 };
 
diff --git a/examples/ip_pipeline/pipeline/pipeline_common_fe.c b/examples/ip_pipeline/pipeline/pipeline_common_fe.c
index dc37a5f..fa0a482 100644
--- a/examples/ip_pipeline/pipeline/pipeline_common_fe.c
+++ b/examples/ip_pipeline/pipeline/pipeline_common_fe.c
@@ -47,6 +47,115 @@
 #include "pipeline_common_fe.h"
 #include "parser.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 pipeline_params pp;
+			struct pipeline_type *ptype;
+			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;
+
+			ptype = app_pipeline_type_find(app, p->type);
+			if ((ptype == NULL) || (ptype->fe_ops->f_track == NULL))
+				return NULL;
+
+			app_pipeline_params_get(app, p, &pp);
+			status = ptype->fe_ops->f_track(&pp,
+				pktq_in_id,
+				&pktq_out_id);
+			if (status)
+				return NULL;
+
+			break;
+		}
+
+		case APP_PKTQ_OUT_TM:
+		{
+			struct pipeline_params pp;
+			struct pipeline_type *ptype;
+			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;
+
+			ptype = app_pipeline_type_find(app, p->type);
+			if ((ptype == NULL) || (ptype->fe_ops->f_track == NULL))
+				return NULL;
+
+			app_pipeline_params_get(app, p, &pp);
+			status = ptype->fe_ops->f_track(&pp,
+				pktq_in_id,
+				&pktq_out_id);
+			if (status)
+				return NULL;
+
+			break;
+		}
+
+		case APP_PKTQ_OUT_SINK:
+		default:
+			return NULL;
+		}
+	}
+}
+
+int
+app_pipeline_track_default(struct pipeline_params *p,
+	uint32_t port_in,
+	uint32_t *port_out)
+{
+	/* Check input arguments */
+	if ((p == NULL) ||
+		(port_in >= p->n_ports_in) ||
+		(port_out == NULL))
+		return -1;
+
+	if (p->n_ports_out == 1) {
+		*port_out = 0;
+		return 0;
+	}
+
+	return -1;
+}
+
 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 f93ff74..8abee4a 100644
--- a/examples/ip_pipeline/pipeline/pipeline_common_fe.h
+++ b/examples/ip_pipeline/pipeline/pipeline_common_fe.h
@@ -182,6 +182,16 @@ 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_track_default(struct pipeline_params *params,
+	uint32_t port_in,
+	uint32_t *port_out);
+
 int
 app_pipeline_ping(struct app_params *app,
 	uint32_t pipeline_id);
diff --git a/examples/ip_pipeline/pipeline/pipeline_firewall.c b/examples/ip_pipeline/pipeline/pipeline_firewall.c
index 30b22a1..a82e552 100644
--- a/examples/ip_pipeline/pipeline/pipeline_firewall.c
+++ b/examples/ip_pipeline/pipeline/pipeline_firewall.c
@@ -1437,7 +1437,9 @@ static cmdline_parse_ctx_t pipeline_cmds[] = {
 
 static struct pipeline_fe_ops pipeline_firewall_fe_ops = {
 	.f_init = app_pipeline_firewall_init,
+	.f_post_init = NULL,
 	.f_free = app_pipeline_firewall_free,
+	.f_track = app_pipeline_track_default,
 	.cmds = pipeline_cmds,
 };
 
diff --git a/examples/ip_pipeline/pipeline/pipeline_firewall_be.c b/examples/ip_pipeline/pipeline/pipeline_firewall_be.c
index 4edca66..b61f303 100644
--- a/examples/ip_pipeline/pipeline/pipeline_firewall_be.c
+++ b/examples/ip_pipeline/pipeline/pipeline_firewall_be.c
@@ -565,27 +565,6 @@ pipeline_firewall_free(void *pipeline)
 }
 
 static int
-pipeline_firewall_track(void *pipeline,
-	__rte_unused uint32_t port_in,
-	uint32_t *port_out)
-{
-	struct pipeline *p = (struct pipeline *) pipeline;
-
-	/* Check input arguments */
-	if ((p == NULL) ||
-		(port_in >= p->n_ports_in) ||
-		(port_out == NULL))
-		return -1;
-
-	if (p->n_ports_in == 1) {
-		*port_out = 0;
-		return 0;
-	}
-
-	return -1;
-}
-
-static int
 pipeline_firewall_timer(void *pipeline)
 {
 	struct pipeline *p = (struct pipeline *) pipeline;
@@ -903,5 +882,4 @@ struct pipeline_be_ops pipeline_firewall_be_ops = {
 	.f_free = pipeline_firewall_free,
 	.f_run = NULL,
 	.f_timer = pipeline_firewall_timer,
-	.f_track = pipeline_firewall_track,
 };
diff --git a/examples/ip_pipeline/pipeline/pipeline_flow_actions.c b/examples/ip_pipeline/pipeline/pipeline_flow_actions.c
index 7560051..bf12fd7 100644
--- a/examples/ip_pipeline/pipeline/pipeline_flow_actions.c
+++ b/examples/ip_pipeline/pipeline/pipeline_flow_actions.c
@@ -1300,7 +1300,9 @@ static cmdline_parse_ctx_t pipeline_cmds[] = {
 
 static struct pipeline_fe_ops pipeline_flow_actions_fe_ops = {
 	.f_init = app_pipeline_fa_init,
+	.f_post_init = NULL,
 	.f_free = app_pipeline_fa_free,
+	.f_track = app_pipeline_track_default,
 	.cmds = pipeline_cmds,
 };
 
diff --git a/examples/ip_pipeline/pipeline/pipeline_flow_actions_be.c b/examples/ip_pipeline/pipeline/pipeline_flow_actions_be.c
index 3ad3ee6..11fcbb7 100644
--- a/examples/ip_pipeline/pipeline/pipeline_flow_actions_be.c
+++ b/examples/ip_pipeline/pipeline/pipeline_flow_actions_be.c
@@ -760,27 +760,6 @@ pipeline_fa_free(void *pipeline)
 }
 
 static int
-pipeline_fa_track(void *pipeline,
-	__rte_unused uint32_t port_in,
-	uint32_t *port_out)
-{
-	struct pipeline *p = (struct pipeline *) pipeline;
-
-	/* Check input arguments */
-	if ((p == NULL) ||
-		(port_in >= p->n_ports_in) ||
-		(port_out == NULL))
-		return -1;
-
-	if (p->n_ports_in == 1) {
-		*port_out = 0;
-		return 0;
-	}
-
-	return -1;
-}
-
-static int
 pipeline_fa_timer(void *pipeline)
 {
 	struct pipeline *p = (struct pipeline *) pipeline;
@@ -1007,5 +986,4 @@ struct pipeline_be_ops pipeline_flow_actions_be_ops = {
 	.f_free = pipeline_fa_free,
 	.f_run = NULL,
 	.f_timer = pipeline_fa_timer,
-	.f_track = pipeline_fa_track,
 };
diff --git a/examples/ip_pipeline/pipeline/pipeline_flow_classification.c b/examples/ip_pipeline/pipeline/pipeline_flow_classification.c
index e49c881..9ef50cc 100644
--- a/examples/ip_pipeline/pipeline/pipeline_flow_classification.c
+++ b/examples/ip_pipeline/pipeline/pipeline_flow_classification.c
@@ -1892,7 +1892,9 @@ static cmdline_parse_ctx_t pipeline_cmds[] = {
 
 static struct pipeline_fe_ops pipeline_flow_classification_fe_ops = {
 	.f_init = app_pipeline_fc_init,
+	.f_post_init = NULL,
 	.f_free = app_pipeline_fc_free,
+	.f_track = app_pipeline_track_default,
 	.cmds = pipeline_cmds,
 };
 
diff --git a/examples/ip_pipeline/pipeline/pipeline_flow_classification_be.c b/examples/ip_pipeline/pipeline/pipeline_flow_classification_be.c
index 70d976d..8a762bc 100644
--- a/examples/ip_pipeline/pipeline/pipeline_flow_classification_be.c
+++ b/examples/ip_pipeline/pipeline/pipeline_flow_classification_be.c
@@ -643,27 +643,6 @@ pipeline_fc_free(void *pipeline)
 }
 
 static int
-pipeline_fc_track(void *pipeline,
-	__rte_unused uint32_t port_in,
-	uint32_t *port_out)
-{
-	struct pipeline *p = (struct pipeline *) pipeline;
-
-	/* Check input arguments */
-	if ((p == NULL) ||
-		(port_in >= p->n_ports_in) ||
-		(port_out == NULL))
-		return -1;
-
-	if (p->n_ports_in == 1) {
-		*port_out = 0;
-		return 0;
-	}
-
-	return -1;
-}
-
-static int
 pipeline_fc_timer(void *pipeline)
 {
 	struct pipeline *p = (struct pipeline *) pipeline;
@@ -807,5 +786,4 @@ struct pipeline_be_ops pipeline_flow_classification_be_ops = {
 	.f_free = pipeline_fc_free,
 	.f_run = NULL,
 	.f_timer = pipeline_fc_timer,
-	.f_track = pipeline_fc_track,
 };
diff --git a/examples/ip_pipeline/pipeline/pipeline_master.c b/examples/ip_pipeline/pipeline/pipeline_master.c
index 1ccdad1..aab58a2 100644
--- a/examples/ip_pipeline/pipeline/pipeline_master.c
+++ b/examples/ip_pipeline/pipeline/pipeline_master.c
@@ -36,7 +36,9 @@
 
 static struct pipeline_fe_ops pipeline_master_fe_ops = {
 	.f_init = NULL,
+	.f_post_init = NULL,
 	.f_free = NULL,
+	.f_track = NULL,
 	.cmds = NULL,
 };
 
diff --git a/examples/ip_pipeline/pipeline/pipeline_master_be.c b/examples/ip_pipeline/pipeline/pipeline_master_be.c
index ac0cbbc..79869a4 100644
--- a/examples/ip_pipeline/pipeline/pipeline_master_be.c
+++ b/examples/ip_pipeline/pipeline/pipeline_master_be.c
@@ -48,6 +48,7 @@
 struct pipeline_master {
 	struct app_params *app;
 	struct cmdline *cl;
+	int post_init_done;
 	int script_file_done;
 } __rte_cache_aligned;
 
@@ -77,6 +78,7 @@ pipeline_init(__rte_unused struct pipeline_params *params, void *arg)
 		return NULL;
 	}
 
+	p->post_init_done = 0;
 	p->script_file_done = 0;
 	if (app->script_file == NULL)
 		p->script_file_done = 1;
@@ -102,8 +104,17 @@ static int
 pipeline_run(void *pipeline)
 {
 	struct pipeline_master *p = (struct pipeline_master *) pipeline;
+	struct app_params *app = p->app;
 	int status;
 
+	/* Application post-init phase */
+	if (p->post_init_done == 0) {
+		app_post_init(app);
+
+		p->post_init_done = 1;
+	}
+
+	/* Run startup script file */
 	if (p->script_file_done == 0) {
 		struct app_params *app = p->app;
 		int fd = open(app->script_file, O_RDONLY);
@@ -124,6 +135,7 @@ pipeline_run(void *pipeline)
 		p->script_file_done = 1;
 	}
 
+	/* Command Line Interface (CLI) */
 	status = cmdline_poll(p->cl);
 	if (status < 0)
 		rte_panic("CLI poll error (%" PRId32 ")\n", status);
@@ -146,5 +158,4 @@ struct pipeline_be_ops pipeline_master_be_ops = {
 		.f_free = pipeline_free,
 		.f_run = pipeline_run,
 		.f_timer = pipeline_timer,
-		.f_track = NULL,
 };
diff --git a/examples/ip_pipeline/pipeline/pipeline_passthrough.c b/examples/ip_pipeline/pipeline/pipeline_passthrough.c
index fc2cae5..63ce147 100644
--- a/examples/ip_pipeline/pipeline/pipeline_passthrough.c
+++ b/examples/ip_pipeline/pipeline/pipeline_passthrough.c
@@ -34,9 +34,36 @@
 #include "pipeline_passthrough.h"
 #include "pipeline_passthrough_be.h"
 
+static int
+app_pipeline_passthrough_track(struct pipeline_params *p,
+	uint32_t port_in,
+	uint32_t *port_out)
+{
+	struct pipeline_passthrough_params pp;
+	int status;
+
+	/* Check input arguments */
+	if ((p == NULL) ||
+		(port_in >= p->n_ports_in) ||
+		(port_out == NULL))
+		return -1;
+
+	status = pipeline_passthrough_parse_args(&pp, p);
+	if (status)
+		return -1;
+
+	if (pp.lb_hash_enabled)
+		return -1;
+
+	*port_out = port_in / (p->n_ports_in / p->n_ports_out);
+	return 0;
+}
+
 static struct pipeline_fe_ops pipeline_passthrough_fe_ops = {
 	.f_init = NULL,
+	.f_post_init = NULL,
 	.f_free = NULL,
+	.f_track = app_pipeline_passthrough_track,
 	.cmds = NULL,
 };
 
diff --git a/examples/ip_pipeline/pipeline/pipeline_passthrough_be.c b/examples/ip_pipeline/pipeline/pipeline_passthrough_be.c
index a0d11ae..6146a28 100644
--- a/examples/ip_pipeline/pipeline/pipeline_passthrough_be.c
+++ b/examples/ip_pipeline/pipeline/pipeline_passthrough_be.c
@@ -547,6 +547,18 @@ pipeline_passthrough_parse_args(struct pipeline_passthrough_params *p,
 			"dma_src_mask", dma_mask_str);
 	}
 
+	if (p->lb_hash_enabled)
+		PIPELINE_ARG_CHECK((params->n_ports_out > 1),
+			"Parse error in section \"%s\": entry \"lb\" not "
+			"allowed for single output port pipeline",
+			params->name);
+	else
+		PIPELINE_ARG_CHECK(((params->n_ports_in >= params->n_ports_out)
+			&& ((params->n_ports_in % params->n_ports_out) == 0)),
+			"Parse error in section \"%s\": n_ports_in needs to be "
+			"a multiple of n_ports_out (lb mode disabled)",
+			params->name);
+
 	return 0;
 }
 
@@ -579,9 +591,7 @@ pipeline_passthrough_init(struct pipeline_params *params,
 	/* Check input arguments */
 	if ((params == NULL) ||
 		(params->n_ports_in == 0) ||
-		(params->n_ports_out == 0) ||
-		(params->n_ports_in < params->n_ports_out) ||
-		(params->n_ports_in % params->n_ports_out))
+		(params->n_ports_out == 0))
 		return NULL;
 
 	/* Memory allocation */
@@ -702,10 +712,13 @@ pipeline_passthrough_init(struct pipeline_params *params,
 
 	/* Add entries to tables */
 	for (i = 0; i < p->n_ports_in; i++) {
+		uint32_t port_out_id = (p_pt->params.lb_hash_enabled == 0) ?
+			(i / (p->n_ports_in / p->n_ports_out)) :
+			0;
+
 		struct rte_pipeline_table_entry default_entry = {
 			.action = RTE_PIPELINE_ACTION_PORT,
-			{.port_id = p->port_out_id[
-				i / (p->n_ports_in / p->n_ports_out)]},
+			{.port_id = p->port_out_id[port_out_id]},
 		};
 
 		struct rte_pipeline_table_entry *default_entry_ptr;
@@ -780,25 +793,9 @@ pipeline_passthrough_timer(void *pipeline)
 	return 0;
 }
 
-static int
-pipeline_passthrough_track(void *pipeline, uint32_t port_in, uint32_t *port_out)
-{
-	struct pipeline *p = (struct pipeline *) pipeline;
-
-	/* Check input arguments */
-	if ((p == NULL) ||
-		(port_in >= p->n_ports_in) ||
-		(port_out == NULL))
-		return -1;
-
-	*port_out = port_in / p->n_ports_in;
-	return 0;
-}
-
 struct pipeline_be_ops pipeline_passthrough_be_ops = {
 	.f_init = pipeline_passthrough_init,
 	.f_free = pipeline_passthrough_free,
 	.f_run = NULL,
 	.f_timer = pipeline_passthrough_timer,
-	.f_track = pipeline_passthrough_track,
 };
diff --git a/examples/ip_pipeline/pipeline/pipeline_routing.c b/examples/ip_pipeline/pipeline/pipeline_routing.c
index c68e470..4d074c1 100644
--- a/examples/ip_pipeline/pipeline/pipeline_routing.c
+++ b/examples/ip_pipeline/pipeline/pipeline_routing.c
@@ -382,8 +382,6 @@ app_pipeline_routing_add_route(struct app_params *app,
 		p->n_routes++;
 	}
 
-	print_route(entry);
-
 	/* Message buffer free */
 	app_msg_free(app, rsp);
 	return 0;
@@ -676,8 +674,6 @@ app_pipeline_routing_add_arp_entry(struct app_params *app, uint32_t pipeline_id,
 		p->n_arp_entries++;
 	}
 
-	print_arp_entry(entry);
-
 	/* Message buffer free */
 	app_msg_free(app, rsp);
 	return 0;
@@ -1390,7 +1386,9 @@ static cmdline_parse_ctx_t pipeline_cmds[] = {
 
 static struct pipeline_fe_ops pipeline_routing_fe_ops = {
 	.f_init = pipeline_routing_init,
+	.f_post_init = NULL,
 	.f_free = app_pipeline_routing_free,
+	.f_track = app_pipeline_track_default,
 	.cmds = pipeline_cmds,
 };
 
diff --git a/examples/ip_pipeline/pipeline/pipeline_routing_be.c b/examples/ip_pipeline/pipeline/pipeline_routing_be.c
index bc5bf7a..e7542a8 100644
--- a/examples/ip_pipeline/pipeline/pipeline_routing_be.c
+++ b/examples/ip_pipeline/pipeline/pipeline_routing_be.c
@@ -1419,27 +1419,6 @@ pipeline_routing_free(void *pipeline)
 }
 
 static int
-pipeline_routing_track(void *pipeline,
-	__rte_unused uint32_t port_in,
-	uint32_t *port_out)
-{
-	struct pipeline *p = (struct pipeline *) pipeline;
-
-	/* Check input arguments */
-	if ((p == NULL) ||
-		(port_in >= p->n_ports_in) ||
-		(port_out == NULL))
-		return -1;
-
-	if (p->n_ports_in == 1) {
-		*port_out = 0;
-		return 0;
-	}
-
-	return -1;
-}
-
-static int
 pipeline_routing_timer(void *pipeline)
 {
 	struct pipeline *p = (struct pipeline *) pipeline;
@@ -1966,5 +1945,4 @@ struct pipeline_be_ops pipeline_routing_be_ops = {
 	.f_free = pipeline_routing_free,
 	.f_run = NULL,
 	.f_timer = pipeline_routing_timer,
-	.f_track = pipeline_routing_track,
 };
diff --git a/examples/ip_pipeline/pipeline_be.h b/examples/ip_pipeline/pipeline_be.h
index 8f858ed..5501ab7 100644
--- a/examples/ip_pipeline/pipeline_be.h
+++ b/examples/ip_pipeline/pipeline_be.h
@@ -203,6 +203,10 @@ pipeline_port_out_params_get_ops(struct pipeline_port_out_params  *p)
 #define PIPELINE_NAME_SIZE                       64
 #endif
 
+#ifndef PIPELINE_TYPE_SIZE
+#define PIPELINE_TYPE_SIZE                       64
+#endif
+
 #ifndef PIPELINE_MAX_PORT_IN
 #define PIPELINE_MAX_PORT_IN                     64
 #endif
@@ -229,6 +233,7 @@ pipeline_port_out_params_get_ops(struct pipeline_port_out_params  *p)
 
 struct pipeline_params {
 	char name[PIPELINE_NAME_SIZE];
+	char type[PIPELINE_TYPE_SIZE];
 
 	struct pipeline_port_in_params port_in[PIPELINE_MAX_PORT_IN];
 	struct pipeline_port_out_params port_out[PIPELINE_MAX_PORT_OUT];
@@ -261,16 +266,11 @@ typedef int (*pipeline_be_op_run)(void *pipeline);
 
 typedef int (*pipeline_be_op_timer)(void *pipeline);
 
-typedef int (*pipeline_be_op_track)(void *pipeline,
-	uint32_t port_in,
-	uint32_t *port_out);
-
 struct pipeline_be_ops {
 	pipeline_be_op_init f_init;
 	pipeline_be_op_free f_free;
 	pipeline_be_op_run f_run;
 	pipeline_be_op_timer f_timer;
-	pipeline_be_op_track f_track;
 };
 
 /* Pipeline specific config parse error messages */
