diff --git a/examples/pipeline/examples/vxlan.spec b/examples/pipeline/examples/vxlan.spec
index b3f28630d..347dca29d 100644
--- a/examples/pipeline/examples/vxlan.spec
+++ b/examples/pipeline/examples/vxlan.spec
@@ -134,8 +134,7 @@ action vxlan_encap args instanceof vxlan_encap_args_t {
 }
 
 action drop args none {
-	mov m.port_out 4
-	tx m.port_out
+	drop
 }
 
 //
diff --git a/lib/librte_pipeline/rte_swx_pipeline.c b/lib/librte_pipeline/rte_swx_pipeline.c
index 6a19b1450..48ac250c1 100644
--- a/lib/librte_pipeline/rte_swx_pipeline.c
+++ b/lib/librte_pipeline/rte_swx_pipeline.c
@@ -281,8 +281,11 @@ enum instruction_type {
 	/* rx m.port_in */
 	INSTR_RX,
 
-	/* tx m.port_out */
-	INSTR_TX,
+	/* tx port_out
+	 * port_out = MI
+	 */
+	INSTR_TX,   /* port_out = M */
+	INSTR_TX_I, /* port_out = I */
 
 	/* extract h.header */
 	INSTR_HDR_EXTRACT,
@@ -582,9 +585,15 @@ struct instr_operand {
 
 struct instr_io {
 	struct {
-		uint8_t offset;
-		uint8_t n_bits;
-		uint8_t pad[2];
+		union {
+			struct {
+				uint8_t offset;
+				uint8_t n_bits;
+				uint8_t pad[2];
+			};
+
+			uint32_t val;
+		};
 	} io;
 
 	struct {
@@ -2490,6 +2499,19 @@ metadata_free(struct rte_swx_pipeline *p)
 /*
  * Instruction.
  */
+static int
+instruction_is_tx(enum instruction_type type)
+{
+	switch (type) {
+	case INSTR_TX:
+	case INSTR_TX_I:
+		return 1;
+
+	default:
+		return 0;
+	}
+}
+
 static int
 instruction_is_jmp(struct instruction *instr)
 {
@@ -2732,16 +2754,42 @@ instr_tx_translate(struct rte_swx_pipeline *p,
 		   struct instruction *instr,
 		   struct instruction_data *data __rte_unused)
 {
+	char *port = tokens[1];
 	struct field *f;
+	uint32_t port_val;
 
 	CHECK(n_tokens == 2, EINVAL);
 
-	f = metadata_field_parse(p, tokens[1]);
-	CHECK(f, EINVAL);
+	f = metadata_field_parse(p, port);
+	if (f) {
+		instr->type = INSTR_TX;
+		instr->io.io.offset = f->offset / 8;
+		instr->io.io.n_bits = f->n_bits;
+		return 0;
+	}
 
-	instr->type = INSTR_TX;
-	instr->io.io.offset = f->offset / 8;
-	instr->io.io.n_bits = f->n_bits;
+	/* TX_I. */
+	port_val = strtoul(port, &port, 0);
+	CHECK(!port[0], EINVAL);
+
+	instr->type = INSTR_TX_I;
+	instr->io.io.val = port_val;
+	return 0;
+}
+
+static int
+instr_drop_translate(struct rte_swx_pipeline *p,
+		     struct action *action __rte_unused,
+		     char **tokens __rte_unused,
+		     int n_tokens,
+		     struct instruction *instr,
+		     struct instruction_data *data __rte_unused)
+{
+	CHECK(n_tokens == 1, EINVAL);
+
+	/* TX_I. */
+	instr->type = INSTR_TX_I;
+	instr->io.io.val = p->n_ports_out - 1;
 	return 0;
 }
 
@@ -2829,6 +2877,30 @@ instr_tx_exec(struct rte_swx_pipeline *p)
 	instr_rx_exec(p);
 }
 
+static inline void
+instr_tx_i_exec(struct rte_swx_pipeline *p)
+{
+	struct thread *t = &p->threads[p->thread_id];
+	struct instruction *ip = t->ip;
+	uint64_t port_id = ip->io.io.val;
+	struct port_out_runtime *port = &p->out[port_id];
+	struct rte_swx_pkt *pkt = &t->pkt;
+
+	TRACE("[Thread %2u]: tx (i) 1 pkt to port %u\n",
+	      p->thread_id,
+	      (uint32_t)port_id);
+
+	/* Headers. */
+	emit_handler(t);
+
+	/* Packet. */
+	port->pkt_tx(port->obj, pkt);
+
+	/* Thread. */
+	thread_ip_reset(p, t);
+	instr_rx_exec(p);
+}
+
 /*
  * extract.
  */
@@ -7308,6 +7380,14 @@ instr_translate(struct rte_swx_pipeline *p,
 					  instr,
 					  data);
 
+	if (!strcmp(tokens[tpos], "drop"))
+		return instr_drop_translate(p,
+					    action,
+					    &tokens[tpos],
+					    n_tokens - tpos,
+					    instr,
+					    data);
+
 	if (!strcmp(tokens[tpos], "extract"))
 		return instr_hdr_extract_translate(p,
 						   action,
@@ -7694,7 +7774,7 @@ instr_verify(struct rte_swx_pipeline *p __rte_unused,
 		for (i = 0; i < n_instructions; i++) {
 			type = instr[i].type;
 
-			if (type == INSTR_TX)
+			if (instruction_is_tx(type))
 				break;
 		}
 		CHECK(i < n_instructions, EINVAL);
@@ -7703,7 +7783,7 @@ instr_verify(struct rte_swx_pipeline *p __rte_unused,
 		 * jump.
 		 */
 		type = instr[n_instructions - 1].type;
-		CHECK((type == INSTR_TX) || (type == INSTR_JMP), EINVAL);
+		CHECK(instruction_is_tx(type) || (type == INSTR_JMP), EINVAL);
 	}
 
 	if (a) {
@@ -7714,7 +7794,7 @@ instr_verify(struct rte_swx_pipeline *p __rte_unused,
 		for (i = 0; i < n_instructions; i++) {
 			type = instr[i].type;
 
-			if ((type == INSTR_RETURN) || (type == INSTR_TX))
+			if ((type == INSTR_RETURN) || instruction_is_tx(type))
 				break;
 		}
 		CHECK(i < n_instructions, EINVAL);
@@ -7794,7 +7874,7 @@ instr_pattern_emit_many_tx_detect(struct instruction *instr,
 	if (!i)
 		return 0;
 
-	if (instr[i].type != INSTR_TX)
+	if (!instruction_is_tx(instr[i].type))
 		return 0;
 
 	if (data[i].n_users)
@@ -8031,6 +8111,7 @@ typedef void (*instr_exec_t)(struct rte_swx_pipeline *);
 static instr_exec_t instruction_table[] = {
 	[INSTR_RX] = instr_rx_exec,
 	[INSTR_TX] = instr_tx_exec,
+	[INSTR_TX_I] = instr_tx_i_exec,
 
 	[INSTR_HDR_EXTRACT] = instr_hdr_extract_exec,
 	[INSTR_HDR_EXTRACT2] = instr_hdr_extract2_exec,
