diff --git a/examples/pipeline/examples/vxlan.spec b/examples/pipeline/examples/vxlan.spec
index 347dca29d..ac62ab2be 100644
--- a/examples/pipeline/examples/vxlan.spec
+++ b/examples/pipeline/examples/vxlan.spec
@@ -60,7 +60,7 @@ metadata instanceof metadata_t
 struct vxlan_encap_args_t {
 	bit<48> ethernet_dst_addr
 	bit<48> ethernet_src_addr
-	bit<16> ethernet_ether_type
+	bit<16> ethernet_ethertype
 	bit<8> ipv4_ver_ihl
 	bit<8> ipv4_diffserv
 	bit<16> ipv4_total_len
@@ -114,11 +114,40 @@ struct vxlan_encap_args_t {
 //
 
 action vxlan_encap args instanceof vxlan_encap_args_t {
-	//Copy from table entry to headers and metadata.
-	dma h.outer_ethernet t.ethernet_dst_addr
-	dma h.outer_ipv4 t.ipv4_ver_ihl
-	dma h.outer_udp t.udp_src_port
-	dma h.outer_vxlan t.vxlan_flags
+	//Set the outer Ethernet header.
+	mov h.outer_ethernet.dst_addr t.ethernet_dst_addr
+	mov h.outer_ethernet.src_addr t.ethernet_src_addr
+	mov h.outer_ethernet.ethertype t.ethernet_ethertype
+	validate h.outer_ethernet
+
+	//Set the outer IPv4 header.
+	mov h.outer_ipv4.ver_ihl t.ipv4_ver_ihl
+	mov h.outer_ipv4.diffserv t.ipv4_diffserv
+	mov h.outer_ipv4.total_len t.ipv4_total_len
+	mov h.outer_ipv4.identification t.ipv4_identification
+	mov h.outer_ipv4.flags_offset t.ipv4_flags_offset
+	mov h.outer_ipv4.ttl t.ipv4_ttl
+	mov h.outer_ipv4.protocol t.ipv4_protocol
+	mov h.outer_ipv4.hdr_checksum t.ipv4_hdr_checksum
+	mov h.outer_ipv4.src_addr t.ipv4_src_addr
+	mov h.outer_ipv4.dst_addr t.ipv4_dst_addr
+	validate h.outer_ipv4
+
+	//Set the outer UDP header.
+	mov h.outer_udp.src_port t.udp_src_port
+	mov h.outer_udp.dst_port t.udp_dst_port
+	mov h.outer_udp.length t.udp_length
+	mov h.outer_udp.checksum t.udp_checksum
+	validate h.outer_udp
+
+	//Set the outer VXLAN header.
+	mov h.outer_vxlan.flags t.vxlan_flags
+	mov h.outer_vxlan.reserved t.vxlan_reserved
+	mov h.outer_vxlan.vni t.vxlan_vni
+	mov h.outer_vxlan.reserved2 t.vxlan_reserved2
+	validate h.outer_vxlan
+
+	//Set the output port.
 	mov m.port_out t.port_out
 
 	//Update h.outer_ipv4.total_len field.
diff --git a/examples/pipeline/examples/vxlan_table.py b/examples/pipeline/examples/vxlan_table.py
index 820c208c7..b1c6f1acd 100755
--- a/examples/pipeline/examples/vxlan_table.py
+++ b/examples/pipeline/examples/vxlan_table.py
@@ -13,28 +13,28 @@
 
 KEY = '0xaabbccdd{0:04x}'
 ACTION = 'vxlan_encap'
-ETHERNET_HEADER = 'ethernet_dst_addr N(0xa0a1a2a3{0:04x}) ' \
-    'ethernet_src_addr N(0xb0b1b2b3{0:04x}) ' \
-    'ethernet_ether_type N(0x0800)'
-IPV4_HEADER = 'ipv4_ver_ihl N(0x45) ' \
-    'ipv4_diffserv N(0) ' \
-    'ipv4_total_len N(50) ' \
-    'ipv4_identification N(0) ' \
-    'ipv4_flags_offset N(0) ' \
-    'ipv4_ttl N(64) ' \
-    'ipv4_protocol N(17) ' \
-    'ipv4_hdr_checksum N(0x{1:04x}) ' \
-    'ipv4_src_addr N(0xc0c1{0:04x}) ' \
-    'ipv4_dst_addr N(0xd0d1{0:04x})'
-UDP_HEADER = 'udp_src_port N(0xe0{0:02x}) ' \
-    'udp_dst_port N(4789) ' \
-    'udp_length N(30) ' \
-    'udp_checksum N(0)'
-VXLAN_HEADER = 'vxlan_flags N(0) ' \
-    'vxlan_reserved N(0) ' \
-    'vxlan_vni N({0:d}) ' \
-    'vxlan_reserved2 N(0)'
-PORT_OUT = 'port_out H({0:d})'
+ETHERNET_HEADER = 'ethernet_dst_addr 0xa0a1a2a3{0:04x} ' \
+    'ethernet_src_addr 0xb0b1b2b3{0:04x} ' \
+    'ethernet_ethertype 0x0800'
+IPV4_HEADER = 'ipv4_ver_ihl 0x45 ' \
+    'ipv4_diffserv 0 ' \
+    'ipv4_total_len 50 ' \
+    'ipv4_identification 0 ' \
+    'ipv4_flags_offset 0 ' \
+    'ipv4_ttl 64 ' \
+    'ipv4_protocol 17 ' \
+    'ipv4_hdr_checksum 0x{1:04x} ' \
+    'ipv4_src_addr 0xc0c1{0:04x} ' \
+    'ipv4_dst_addr 0xd0d1{0:04x}'
+UDP_HEADER = 'udp_src_port 0xe0{0:02x} ' \
+    'udp_dst_port 4789 ' \
+    'udp_length 30 ' \
+    'udp_checksum 0'
+VXLAN_HEADER = 'vxlan_flags 0 ' \
+    'vxlan_reserved 0 ' \
+    'vxlan_vni {0:d} ' \
+    'vxlan_reserved2 0'
+PORT_OUT = 'port_out {0:d}'
 
 def ipv4_header_checksum(i):
     cksum = (0x4500 + 0x0032) + (0x0000 + 0x0000) + (0x4011 + 0x0000) + (0xc0c1 + i) + (0xd0d1 + i)
diff --git a/examples/pipeline/examples/vxlan_table.txt b/examples/pipeline/examples/vxlan_table.txt
index acac80a38..25ca647ab 100644
--- a/examples/pipeline/examples/vxlan_table.txt
+++ b/examples/pipeline/examples/vxlan_table.txt
@@ -1,16 +1,16 @@
-match 0xaabbccdd0000 action vxlan_encap ethernet_dst_addr N(0xa0a1a2a30000) ethernet_src_addr N(0xb0b1b2b30000) ethernet_ether_type N(0x0800) ipv4_ver_ihl N(0x45) ipv4_diffserv N(0) ipv4_total_len N(50) ipv4_identification N(0) ipv4_flags_offset N(0) ipv4_ttl N(64) ipv4_protocol N(17) ipv4_hdr_checksum N(0xe928) ipv4_src_addr N(0xc0c10000) ipv4_dst_addr N(0xd0d10000) udp_src_port N(0xe000) udp_dst_port N(4789) udp_length N(30) udp_checksum N(0) vxlan_flags N(0) vxlan_reserved N(0) vxlan_vni N(0) vxlan_reserved2 N(0) port_out H(0)
-match 0xaabbccdd0001 action vxlan_encap ethernet_dst_addr N(0xa0a1a2a30001) ethernet_src_addr N(0xb0b1b2b30001) ethernet_ether_type N(0x0800) ipv4_ver_ihl N(0x45) ipv4_diffserv N(0) ipv4_total_len N(50) ipv4_identification N(0) ipv4_flags_offset N(0) ipv4_ttl N(64) ipv4_protocol N(17) ipv4_hdr_checksum N(0xe926) ipv4_src_addr N(0xc0c10001) ipv4_dst_addr N(0xd0d10001) udp_src_port N(0xe001) udp_dst_port N(4789) udp_length N(30) udp_checksum N(0) vxlan_flags N(0) vxlan_reserved N(0) vxlan_vni N(1) vxlan_reserved2 N(0) port_out H(1)
-match 0xaabbccdd0002 action vxlan_encap ethernet_dst_addr N(0xa0a1a2a30002) ethernet_src_addr N(0xb0b1b2b30002) ethernet_ether_type N(0x0800) ipv4_ver_ihl N(0x45) ipv4_diffserv N(0) ipv4_total_len N(50) ipv4_identification N(0) ipv4_flags_offset N(0) ipv4_ttl N(64) ipv4_protocol N(17) ipv4_hdr_checksum N(0xe924) ipv4_src_addr N(0xc0c10002) ipv4_dst_addr N(0xd0d10002) udp_src_port N(0xe002) udp_dst_port N(4789) udp_length N(30) udp_checksum N(0) vxlan_flags N(0) vxlan_reserved N(0) vxlan_vni N(2) vxlan_reserved2 N(0) port_out H(2)
-match 0xaabbccdd0003 action vxlan_encap ethernet_dst_addr N(0xa0a1a2a30003) ethernet_src_addr N(0xb0b1b2b30003) ethernet_ether_type N(0x0800) ipv4_ver_ihl N(0x45) ipv4_diffserv N(0) ipv4_total_len N(50) ipv4_identification N(0) ipv4_flags_offset N(0) ipv4_ttl N(64) ipv4_protocol N(17) ipv4_hdr_checksum N(0xe922) ipv4_src_addr N(0xc0c10003) ipv4_dst_addr N(0xd0d10003) udp_src_port N(0xe003) udp_dst_port N(4789) udp_length N(30) udp_checksum N(0) vxlan_flags N(0) vxlan_reserved N(0) vxlan_vni N(3) vxlan_reserved2 N(0) port_out H(3)
-match 0xaabbccdd0004 action vxlan_encap ethernet_dst_addr N(0xa0a1a2a30004) ethernet_src_addr N(0xb0b1b2b30004) ethernet_ether_type N(0x0800) ipv4_ver_ihl N(0x45) ipv4_diffserv N(0) ipv4_total_len N(50) ipv4_identification N(0) ipv4_flags_offset N(0) ipv4_ttl N(64) ipv4_protocol N(17) ipv4_hdr_checksum N(0xe920) ipv4_src_addr N(0xc0c10004) ipv4_dst_addr N(0xd0d10004) udp_src_port N(0xe004) udp_dst_port N(4789) udp_length N(30) udp_checksum N(0) vxlan_flags N(0) vxlan_reserved N(0) vxlan_vni N(4) vxlan_reserved2 N(0) port_out H(0)
-match 0xaabbccdd0005 action vxlan_encap ethernet_dst_addr N(0xa0a1a2a30005) ethernet_src_addr N(0xb0b1b2b30005) ethernet_ether_type N(0x0800) ipv4_ver_ihl N(0x45) ipv4_diffserv N(0) ipv4_total_len N(50) ipv4_identification N(0) ipv4_flags_offset N(0) ipv4_ttl N(64) ipv4_protocol N(17) ipv4_hdr_checksum N(0xe91e) ipv4_src_addr N(0xc0c10005) ipv4_dst_addr N(0xd0d10005) udp_src_port N(0xe005) udp_dst_port N(4789) udp_length N(30) udp_checksum N(0) vxlan_flags N(0) vxlan_reserved N(0) vxlan_vni N(5) vxlan_reserved2 N(0) port_out H(1)
-match 0xaabbccdd0006 action vxlan_encap ethernet_dst_addr N(0xa0a1a2a30006) ethernet_src_addr N(0xb0b1b2b30006) ethernet_ether_type N(0x0800) ipv4_ver_ihl N(0x45) ipv4_diffserv N(0) ipv4_total_len N(50) ipv4_identification N(0) ipv4_flags_offset N(0) ipv4_ttl N(64) ipv4_protocol N(17) ipv4_hdr_checksum N(0xe91c) ipv4_src_addr N(0xc0c10006) ipv4_dst_addr N(0xd0d10006) udp_src_port N(0xe006) udp_dst_port N(4789) udp_length N(30) udp_checksum N(0) vxlan_flags N(0) vxlan_reserved N(0) vxlan_vni N(6) vxlan_reserved2 N(0) port_out H(2)
-match 0xaabbccdd0007 action vxlan_encap ethernet_dst_addr N(0xa0a1a2a30007) ethernet_src_addr N(0xb0b1b2b30007) ethernet_ether_type N(0x0800) ipv4_ver_ihl N(0x45) ipv4_diffserv N(0) ipv4_total_len N(50) ipv4_identification N(0) ipv4_flags_offset N(0) ipv4_ttl N(64) ipv4_protocol N(17) ipv4_hdr_checksum N(0xe91a) ipv4_src_addr N(0xc0c10007) ipv4_dst_addr N(0xd0d10007) udp_src_port N(0xe007) udp_dst_port N(4789) udp_length N(30) udp_checksum N(0) vxlan_flags N(0) vxlan_reserved N(0) vxlan_vni N(7) vxlan_reserved2 N(0) port_out H(3)
-match 0xaabbccdd0008 action vxlan_encap ethernet_dst_addr N(0xa0a1a2a30008) ethernet_src_addr N(0xb0b1b2b30008) ethernet_ether_type N(0x0800) ipv4_ver_ihl N(0x45) ipv4_diffserv N(0) ipv4_total_len N(50) ipv4_identification N(0) ipv4_flags_offset N(0) ipv4_ttl N(64) ipv4_protocol N(17) ipv4_hdr_checksum N(0xe918) ipv4_src_addr N(0xc0c10008) ipv4_dst_addr N(0xd0d10008) udp_src_port N(0xe008) udp_dst_port N(4789) udp_length N(30) udp_checksum N(0) vxlan_flags N(0) vxlan_reserved N(0) vxlan_vni N(8) vxlan_reserved2 N(0) port_out H(0)
-match 0xaabbccdd0009 action vxlan_encap ethernet_dst_addr N(0xa0a1a2a30009) ethernet_src_addr N(0xb0b1b2b30009) ethernet_ether_type N(0x0800) ipv4_ver_ihl N(0x45) ipv4_diffserv N(0) ipv4_total_len N(50) ipv4_identification N(0) ipv4_flags_offset N(0) ipv4_ttl N(64) ipv4_protocol N(17) ipv4_hdr_checksum N(0xe916) ipv4_src_addr N(0xc0c10009) ipv4_dst_addr N(0xd0d10009) udp_src_port N(0xe009) udp_dst_port N(4789) udp_length N(30) udp_checksum N(0) vxlan_flags N(0) vxlan_reserved N(0) vxlan_vni N(9) vxlan_reserved2 N(0) port_out H(1)
-match 0xaabbccdd000a action vxlan_encap ethernet_dst_addr N(0xa0a1a2a3000a) ethernet_src_addr N(0xb0b1b2b3000a) ethernet_ether_type N(0x0800) ipv4_ver_ihl N(0x45) ipv4_diffserv N(0) ipv4_total_len N(50) ipv4_identification N(0) ipv4_flags_offset N(0) ipv4_ttl N(64) ipv4_protocol N(17) ipv4_hdr_checksum N(0xe914) ipv4_src_addr N(0xc0c1000a) ipv4_dst_addr N(0xd0d1000a) udp_src_port N(0xe00a) udp_dst_port N(4789) udp_length N(30) udp_checksum N(0) vxlan_flags N(0) vxlan_reserved N(0) vxlan_vni N(10) vxlan_reserved2 N(0) port_out H(2)
-match 0xaabbccdd000b action vxlan_encap ethernet_dst_addr N(0xa0a1a2a3000b) ethernet_src_addr N(0xb0b1b2b3000b) ethernet_ether_type N(0x0800) ipv4_ver_ihl N(0x45) ipv4_diffserv N(0) ipv4_total_len N(50) ipv4_identification N(0) ipv4_flags_offset N(0) ipv4_ttl N(64) ipv4_protocol N(17) ipv4_hdr_checksum N(0xe912) ipv4_src_addr N(0xc0c1000b) ipv4_dst_addr N(0xd0d1000b) udp_src_port N(0xe00b) udp_dst_port N(4789) udp_length N(30) udp_checksum N(0) vxlan_flags N(0) vxlan_reserved N(0) vxlan_vni N(11) vxlan_reserved2 N(0) port_out H(3)
-match 0xaabbccdd000c action vxlan_encap ethernet_dst_addr N(0xa0a1a2a3000c) ethernet_src_addr N(0xb0b1b2b3000c) ethernet_ether_type N(0x0800) ipv4_ver_ihl N(0x45) ipv4_diffserv N(0) ipv4_total_len N(50) ipv4_identification N(0) ipv4_flags_offset N(0) ipv4_ttl N(64) ipv4_protocol N(17) ipv4_hdr_checksum N(0xe910) ipv4_src_addr N(0xc0c1000c) ipv4_dst_addr N(0xd0d1000c) udp_src_port N(0xe00c) udp_dst_port N(4789) udp_length N(30) udp_checksum N(0) vxlan_flags N(0) vxlan_reserved N(0) vxlan_vni N(12) vxlan_reserved2 N(0) port_out H(0)
-match 0xaabbccdd000d action vxlan_encap ethernet_dst_addr N(0xa0a1a2a3000d) ethernet_src_addr N(0xb0b1b2b3000d) ethernet_ether_type N(0x0800) ipv4_ver_ihl N(0x45) ipv4_diffserv N(0) ipv4_total_len N(50) ipv4_identification N(0) ipv4_flags_offset N(0) ipv4_ttl N(64) ipv4_protocol N(17) ipv4_hdr_checksum N(0xe90e) ipv4_src_addr N(0xc0c1000d) ipv4_dst_addr N(0xd0d1000d) udp_src_port N(0xe00d) udp_dst_port N(4789) udp_length N(30) udp_checksum N(0) vxlan_flags N(0) vxlan_reserved N(0) vxlan_vni N(13) vxlan_reserved2 N(0) port_out H(1)
-match 0xaabbccdd000e action vxlan_encap ethernet_dst_addr N(0xa0a1a2a3000e) ethernet_src_addr N(0xb0b1b2b3000e) ethernet_ether_type N(0x0800) ipv4_ver_ihl N(0x45) ipv4_diffserv N(0) ipv4_total_len N(50) ipv4_identification N(0) ipv4_flags_offset N(0) ipv4_ttl N(64) ipv4_protocol N(17) ipv4_hdr_checksum N(0xe90c) ipv4_src_addr N(0xc0c1000e) ipv4_dst_addr N(0xd0d1000e) udp_src_port N(0xe00e) udp_dst_port N(4789) udp_length N(30) udp_checksum N(0) vxlan_flags N(0) vxlan_reserved N(0) vxlan_vni N(14) vxlan_reserved2 N(0) port_out H(2)
-match 0xaabbccdd000f action vxlan_encap ethernet_dst_addr N(0xa0a1a2a3000f) ethernet_src_addr N(0xb0b1b2b3000f) ethernet_ether_type N(0x0800) ipv4_ver_ihl N(0x45) ipv4_diffserv N(0) ipv4_total_len N(50) ipv4_identification N(0) ipv4_flags_offset N(0) ipv4_ttl N(64) ipv4_protocol N(17) ipv4_hdr_checksum N(0xe90a) ipv4_src_addr N(0xc0c1000f) ipv4_dst_addr N(0xd0d1000f) udp_src_port N(0xe00f) udp_dst_port N(4789) udp_length N(30) udp_checksum N(0) vxlan_flags N(0) vxlan_reserved N(0) vxlan_vni N(15) vxlan_reserved2 N(0) port_out H(3)
+match 0xaabbccdd0000 action vxlan_encap ethernet_dst_addr 0xa0a1a2a30000 ethernet_src_addr 0xb0b1b2b30000 ethernet_ethertype 0x0800 ipv4_ver_ihl 0x45 ipv4_diffserv 0 ipv4_total_len 50 ipv4_identification 0 ipv4_flags_offset 0 ipv4_ttl 64 ipv4_protocol 17 ipv4_hdr_checksum 0xe928 ipv4_src_addr 0xc0c10000 ipv4_dst_addr 0xd0d10000 udp_src_port 0xe000 udp_dst_port 4789 udp_length 30 udp_checksum 0 vxlan_flags 0 vxlan_reserved 0 vxlan_vni 0 vxlan_reserved2 0 port_out 0
+match 0xaabbccdd0001 action vxlan_encap ethernet_dst_addr 0xa0a1a2a30001 ethernet_src_addr 0xb0b1b2b30001 ethernet_ethertype 0x0800 ipv4_ver_ihl 0x45 ipv4_diffserv 0 ipv4_total_len 50 ipv4_identification 0 ipv4_flags_offset 0 ipv4_ttl 64 ipv4_protocol 17 ipv4_hdr_checksum 0xe926 ipv4_src_addr 0xc0c10001 ipv4_dst_addr 0xd0d10001 udp_src_port 0xe001 udp_dst_port 4789 udp_length 30 udp_checksum 0 vxlan_flags 0 vxlan_reserved 0 vxlan_vni 1 vxlan_reserved2 0 port_out 1
+match 0xaabbccdd0002 action vxlan_encap ethernet_dst_addr 0xa0a1a2a30002 ethernet_src_addr 0xb0b1b2b30002 ethernet_ethertype 0x0800 ipv4_ver_ihl 0x45 ipv4_diffserv 0 ipv4_total_len 50 ipv4_identification 0 ipv4_flags_offset 0 ipv4_ttl 64 ipv4_protocol 17 ipv4_hdr_checksum 0xe924 ipv4_src_addr 0xc0c10002 ipv4_dst_addr 0xd0d10002 udp_src_port 0xe002 udp_dst_port 4789 udp_length 30 udp_checksum 0 vxlan_flags 0 vxlan_reserved 0 vxlan_vni 2 vxlan_reserved2 0 port_out 2
+match 0xaabbccdd0003 action vxlan_encap ethernet_dst_addr 0xa0a1a2a30003 ethernet_src_addr 0xb0b1b2b30003 ethernet_ethertype 0x0800 ipv4_ver_ihl 0x45 ipv4_diffserv 0 ipv4_total_len 50 ipv4_identification 0 ipv4_flags_offset 0 ipv4_ttl 64 ipv4_protocol 17 ipv4_hdr_checksum 0xe922 ipv4_src_addr 0xc0c10003 ipv4_dst_addr 0xd0d10003 udp_src_port 0xe003 udp_dst_port 4789 udp_length 30 udp_checksum 0 vxlan_flags 0 vxlan_reserved 0 vxlan_vni 3 vxlan_reserved2 0 port_out 3
+match 0xaabbccdd0004 action vxlan_encap ethernet_dst_addr 0xa0a1a2a30004 ethernet_src_addr 0xb0b1b2b30004 ethernet_ethertype 0x0800 ipv4_ver_ihl 0x45 ipv4_diffserv 0 ipv4_total_len 50 ipv4_identification 0 ipv4_flags_offset 0 ipv4_ttl 64 ipv4_protocol 17 ipv4_hdr_checksum 0xe920 ipv4_src_addr 0xc0c10004 ipv4_dst_addr 0xd0d10004 udp_src_port 0xe004 udp_dst_port 4789 udp_length 30 udp_checksum 0 vxlan_flags 0 vxlan_reserved 0 vxlan_vni 4 vxlan_reserved2 0 port_out 0
+match 0xaabbccdd0005 action vxlan_encap ethernet_dst_addr 0xa0a1a2a30005 ethernet_src_addr 0xb0b1b2b30005 ethernet_ethertype 0x0800 ipv4_ver_ihl 0x45 ipv4_diffserv 0 ipv4_total_len 50 ipv4_identification 0 ipv4_flags_offset 0 ipv4_ttl 64 ipv4_protocol 17 ipv4_hdr_checksum 0xe91e ipv4_src_addr 0xc0c10005 ipv4_dst_addr 0xd0d10005 udp_src_port 0xe005 udp_dst_port 4789 udp_length 30 udp_checksum 0 vxlan_flags 0 vxlan_reserved 0 vxlan_vni 5 vxlan_reserved2 0 port_out 1
+match 0xaabbccdd0006 action vxlan_encap ethernet_dst_addr 0xa0a1a2a30006 ethernet_src_addr 0xb0b1b2b30006 ethernet_ethertype 0x0800 ipv4_ver_ihl 0x45 ipv4_diffserv 0 ipv4_total_len 50 ipv4_identification 0 ipv4_flags_offset 0 ipv4_ttl 64 ipv4_protocol 17 ipv4_hdr_checksum 0xe91c ipv4_src_addr 0xc0c10006 ipv4_dst_addr 0xd0d10006 udp_src_port 0xe006 udp_dst_port 4789 udp_length 30 udp_checksum 0 vxlan_flags 0 vxlan_reserved 0 vxlan_vni 6 vxlan_reserved2 0 port_out 2
+match 0xaabbccdd0007 action vxlan_encap ethernet_dst_addr 0xa0a1a2a30007 ethernet_src_addr 0xb0b1b2b30007 ethernet_ethertype 0x0800 ipv4_ver_ihl 0x45 ipv4_diffserv 0 ipv4_total_len 50 ipv4_identification 0 ipv4_flags_offset 0 ipv4_ttl 64 ipv4_protocol 17 ipv4_hdr_checksum 0xe91a ipv4_src_addr 0xc0c10007 ipv4_dst_addr 0xd0d10007 udp_src_port 0xe007 udp_dst_port 4789 udp_length 30 udp_checksum 0 vxlan_flags 0 vxlan_reserved 0 vxlan_vni 7 vxlan_reserved2 0 port_out 3
+match 0xaabbccdd0008 action vxlan_encap ethernet_dst_addr 0xa0a1a2a30008 ethernet_src_addr 0xb0b1b2b30008 ethernet_ethertype 0x0800 ipv4_ver_ihl 0x45 ipv4_diffserv 0 ipv4_total_len 50 ipv4_identification 0 ipv4_flags_offset 0 ipv4_ttl 64 ipv4_protocol 17 ipv4_hdr_checksum 0xe918 ipv4_src_addr 0xc0c10008 ipv4_dst_addr 0xd0d10008 udp_src_port 0xe008 udp_dst_port 4789 udp_length 30 udp_checksum 0 vxlan_flags 0 vxlan_reserved 0 vxlan_vni 8 vxlan_reserved2 0 port_out 0
+match 0xaabbccdd0009 action vxlan_encap ethernet_dst_addr 0xa0a1a2a30009 ethernet_src_addr 0xb0b1b2b30009 ethernet_ethertype 0x0800 ipv4_ver_ihl 0x45 ipv4_diffserv 0 ipv4_total_len 50 ipv4_identification 0 ipv4_flags_offset 0 ipv4_ttl 64 ipv4_protocol 17 ipv4_hdr_checksum 0xe916 ipv4_src_addr 0xc0c10009 ipv4_dst_addr 0xd0d10009 udp_src_port 0xe009 udp_dst_port 4789 udp_length 30 udp_checksum 0 vxlan_flags 0 vxlan_reserved 0 vxlan_vni 9 vxlan_reserved2 0 port_out 1
+match 0xaabbccdd000a action vxlan_encap ethernet_dst_addr 0xa0a1a2a3000a ethernet_src_addr 0xb0b1b2b3000a ethernet_ethertype 0x0800 ipv4_ver_ihl 0x45 ipv4_diffserv 0 ipv4_total_len 50 ipv4_identification 0 ipv4_flags_offset 0 ipv4_ttl 64 ipv4_protocol 17 ipv4_hdr_checksum 0xe914 ipv4_src_addr 0xc0c1000a ipv4_dst_addr 0xd0d1000a udp_src_port 0xe00a udp_dst_port 4789 udp_length 30 udp_checksum 0 vxlan_flags 0 vxlan_reserved 0 vxlan_vni 10 vxlan_reserved2 0 port_out 2
+match 0xaabbccdd000b action vxlan_encap ethernet_dst_addr 0xa0a1a2a3000b ethernet_src_addr 0xb0b1b2b3000b ethernet_ethertype 0x0800 ipv4_ver_ihl 0x45 ipv4_diffserv 0 ipv4_total_len 50 ipv4_identification 0 ipv4_flags_offset 0 ipv4_ttl 64 ipv4_protocol 17 ipv4_hdr_checksum 0xe912 ipv4_src_addr 0xc0c1000b ipv4_dst_addr 0xd0d1000b udp_src_port 0xe00b udp_dst_port 4789 udp_length 30 udp_checksum 0 vxlan_flags 0 vxlan_reserved 0 vxlan_vni 11 vxlan_reserved2 0 port_out 3
+match 0xaabbccdd000c action vxlan_encap ethernet_dst_addr 0xa0a1a2a3000c ethernet_src_addr 0xb0b1b2b3000c ethernet_ethertype 0x0800 ipv4_ver_ihl 0x45 ipv4_diffserv 0 ipv4_total_len 50 ipv4_identification 0 ipv4_flags_offset 0 ipv4_ttl 64 ipv4_protocol 17 ipv4_hdr_checksum 0xe910 ipv4_src_addr 0xc0c1000c ipv4_dst_addr 0xd0d1000c udp_src_port 0xe00c udp_dst_port 4789 udp_length 30 udp_checksum 0 vxlan_flags 0 vxlan_reserved 0 vxlan_vni 12 vxlan_reserved2 0 port_out 0
+match 0xaabbccdd000d action vxlan_encap ethernet_dst_addr 0xa0a1a2a3000d ethernet_src_addr 0xb0b1b2b3000d ethernet_ethertype 0x0800 ipv4_ver_ihl 0x45 ipv4_diffserv 0 ipv4_total_len 50 ipv4_identification 0 ipv4_flags_offset 0 ipv4_ttl 64 ipv4_protocol 17 ipv4_hdr_checksum 0xe90e ipv4_src_addr 0xc0c1000d ipv4_dst_addr 0xd0d1000d udp_src_port 0xe00d udp_dst_port 4789 udp_length 30 udp_checksum 0 vxlan_flags 0 vxlan_reserved 0 vxlan_vni 13 vxlan_reserved2 0 port_out 1
+match 0xaabbccdd000e action vxlan_encap ethernet_dst_addr 0xa0a1a2a3000e ethernet_src_addr 0xb0b1b2b3000e ethernet_ethertype 0x0800 ipv4_ver_ihl 0x45 ipv4_diffserv 0 ipv4_total_len 50 ipv4_identification 0 ipv4_flags_offset 0 ipv4_ttl 64 ipv4_protocol 17 ipv4_hdr_checksum 0xe90c ipv4_src_addr 0xc0c1000e ipv4_dst_addr 0xd0d1000e udp_src_port 0xe00e udp_dst_port 4789 udp_length 30 udp_checksum 0 vxlan_flags 0 vxlan_reserved 0 vxlan_vni 14 vxlan_reserved2 0 port_out 2
+match 0xaabbccdd000f action vxlan_encap ethernet_dst_addr 0xa0a1a2a3000f ethernet_src_addr 0xb0b1b2b3000f ethernet_ethertype 0x0800 ipv4_ver_ihl 0x45 ipv4_diffserv 0 ipv4_total_len 50 ipv4_identification 0 ipv4_flags_offset 0 ipv4_ttl 64 ipv4_protocol 17 ipv4_hdr_checksum 0xe90a ipv4_src_addr 0xc0c1000f ipv4_dst_addr 0xd0d1000f udp_src_port 0xe00f udp_dst_port 4789 udp_length 30 udp_checksum 0 vxlan_flags 0 vxlan_reserved 0 vxlan_vni 15 vxlan_reserved2 0 port_out 3
diff --git a/lib/librte_pipeline/rte_swx_ctl.c b/lib/librte_pipeline/rte_swx_ctl.c
index ca30767ef..4d1ff9ead 100644
--- a/lib/librte_pipeline/rte_swx_ctl.c
+++ b/lib/librte_pipeline/rte_swx_ctl.c
@@ -1721,30 +1721,19 @@ rte_swx_ctl_pipeline_table_entry_read(struct rte_swx_ctl_pipeline *ctl,
 		struct rte_swx_ctl_action_arg_info *arg = &action->args[i];
 		char *arg_name, *arg_val;
 		uint64_t val;
-		int is_nbo = 0;
 
 		arg_name = tokens[2 + i * 2];
 		arg_val = tokens[2 + i * 2 + 1];
 
-		if (strcmp(arg_name, arg->name) ||
-		    (strlen(arg_val) < 4) ||
-		    ((arg_val[0] != 'H') && (arg_val[0] != 'N')) ||
-		    (arg_val[1] != '(') ||
-		    (arg_val[strlen(arg_val) - 1] != ')'))
+		if (strcmp(arg_name, arg->name))
 			goto error;
 
-		if (arg_val[0] == 'N')
-			is_nbo = 1;
-
-		arg_val[strlen(arg_val) - 1] = 0; /* Remove the ')'. */
-		arg_val += 2; /* Remove the "H(" or "N(". */
-
 		val = strtoull(arg_val, &arg_val, 0);
 		if (arg_val[0])
 			goto error;
 
 		/* Endianness conversion. */
-		if (is_nbo)
+		if (arg->is_network_byte_order)
 			val = field_hton(val, arg->n_bits);
 
 		/* Copy to entry. */
diff --git a/lib/librte_pipeline/rte_swx_ctl.h b/lib/librte_pipeline/rte_swx_ctl.h
index b8f22c516..4e5befb50 100644
--- a/lib/librte_pipeline/rte_swx_ctl.h
+++ b/lib/librte_pipeline/rte_swx_ctl.h
@@ -168,6 +168,12 @@ struct rte_swx_ctl_action_arg_info {
 
 	/** Action argument size (in bits). */
 	uint32_t n_bits;
+
+	/** Non-zero (true) when this action argument must be stored in the
+	 * table in network byte order (NBO), zero when it must be stored in
+	 * host byte order (HBO).
+	 */
+	int is_network_byte_order;
 };
 
 /**
diff --git a/lib/librte_pipeline/rte_swx_pipeline.c b/lib/librte_pipeline/rte_swx_pipeline.c
index ba828cbda..d9f47b07e 100644
--- a/lib/librte_pipeline/rte_swx_pipeline.c
+++ b/lib/librte_pipeline/rte_swx_pipeline.c
@@ -733,6 +733,7 @@ struct action {
 	TAILQ_ENTRY(action) node;
 	char name[RTE_SWX_NAME_SIZE];
 	struct struct_type *st;
+	int *args_endianness; /* 0 = Host Byte Order (HBO). */
 	struct instruction *instructions;
 	uint32_t n_instructions;
 	uint32_t id;
@@ -2342,6 +2343,18 @@ header_find(struct rte_swx_pipeline *p, const char *name)
 	return NULL;
 }
 
+static struct header *
+header_find_by_struct_id(struct rte_swx_pipeline *p, uint32_t struct_id)
+{
+	struct header *elem;
+
+	TAILQ_FOREACH(elem, &p->headers, node)
+		if (elem->struct_id == struct_id)
+			return elem;
+
+	return NULL;
+}
+
 static struct header *
 header_parse(struct rte_swx_pipeline *p,
 	     const char *name)
@@ -3722,37 +3735,6 @@ instr_mov_i_exec(struct rte_swx_pipeline *p)
 /*
  * dma.
  */
-static int
-instr_dma_translate(struct rte_swx_pipeline *p,
-		    struct action *action,
-		    char **tokens,
-		    int n_tokens,
-		    struct instruction *instr,
-		    struct instruction_data *data __rte_unused)
-{
-	char *dst = tokens[1];
-	char *src = tokens[2];
-	struct header *h;
-	struct field *tf;
-
-	CHECK(action, EINVAL);
-	CHECK(n_tokens == 3, EINVAL);
-
-	h = header_parse(p, dst);
-	CHECK(h, EINVAL);
-
-	tf = action_field_parse(action, src);
-	CHECK(tf, EINVAL);
-
-	instr->type = INSTR_DMA_HT;
-	instr->dma.dst.header_id[0] = h->id;
-	instr->dma.dst.struct_id[0] = h->struct_id;
-	instr->dma.n_bytes[0] = h->st->n_bits / 8;
-	instr->dma.src.offset[0] = tf->offset / 8;
-
-	return 0;
-}
-
 static inline void
 __instr_dma_ht_exec(struct rte_swx_pipeline *p, uint32_t n_dma);
 
@@ -7710,14 +7692,6 @@ instr_translate(struct rte_swx_pipeline *p,
 					   instr,
 					   data);
 
-	if (!strcmp(tokens[tpos], "dma"))
-		return instr_dma_translate(p,
-					   action,
-					   &tokens[tpos],
-					   n_tokens - tpos,
-					   instr,
-					   data);
-
 	if (!strcmp(tokens[tpos], "add"))
 		return instr_alu_add_translate(p,
 					       action,
@@ -8294,6 +8268,180 @@ instr_pattern_emit_many_tx_optimize(struct instruction *instructions,
 	return n_instructions;
 }
 
+static uint32_t
+action_arg_src_mov_count(struct action *a,
+			 uint32_t arg_id,
+			 struct instruction *instructions,
+			 struct instruction_data *instruction_data,
+			 uint32_t n_instructions);
+
+static int
+instr_pattern_mov_all_validate_search(struct rte_swx_pipeline *p,
+				      struct action *a,
+				      struct instruction *instr,
+				      struct instruction_data *data,
+				      uint32_t n_instr,
+				      struct instruction *instructions,
+				      struct instruction_data *instruction_data,
+				      uint32_t n_instructions,
+				      uint32_t *n_pattern_instr)
+{
+	struct header *h;
+	uint32_t src_field_id, i, j;
+
+	/* Prerequisites. */
+	if (!a || !a->st)
+		return 0;
+
+	/* First instruction: MOV_HM. */
+	if (data[0].invalid || (instr[0].type != INSTR_MOV_HM))
+		return 0;
+
+	h = header_find_by_struct_id(p, instr[0].mov.dst.struct_id);
+	if (!h)
+		return 0;
+
+	for (src_field_id = 0; src_field_id < a->st->n_fields; src_field_id++)
+		if (instr[0].mov.src.offset == a->st->fields[src_field_id].offset / 8)
+			break;
+
+	if (src_field_id == a->st->n_fields)
+		return 0;
+
+	if (instr[0].mov.dst.offset ||
+	    (instr[0].mov.dst.n_bits != h->st->fields[0].n_bits) ||
+	    instr[0].mov.src.struct_id ||
+	    (instr[0].mov.src.n_bits != a->st->fields[src_field_id].n_bits) ||
+	    (instr[0].mov.dst.n_bits != instr[0].mov.src.n_bits))
+		return 0;
+
+	if ((n_instr < h->st->n_fields + 1) ||
+	     (a->st->n_fields < src_field_id + h->st->n_fields + 1))
+		return 0;
+
+	/* Subsequent instructions: MOV_HM. */
+	for (i = 1; i < h->st->n_fields; i++)
+		if (data[i].invalid ||
+		    data[i].n_users ||
+		    (instr[i].type != INSTR_MOV_HM) ||
+		    (instr[i].mov.dst.struct_id != h->struct_id) ||
+		    (instr[i].mov.dst.offset != h->st->fields[i].offset / 8) ||
+		    (instr[i].mov.dst.n_bits != h->st->fields[i].n_bits) ||
+		    instr[i].mov.src.struct_id ||
+		    (instr[i].mov.src.offset != a->st->fields[src_field_id + i].offset / 8) ||
+		    (instr[i].mov.src.n_bits != a->st->fields[src_field_id + i].n_bits) ||
+		    (instr[i].mov.dst.n_bits != instr[i].mov.src.n_bits))
+			return 0;
+
+	/* Last instruction: HDR_VALIDATE. */
+	if ((instr[i].type != INSTR_HDR_VALIDATE) ||
+	    (instr[i].valid.header_id != h->id))
+		return 0;
+
+	/* Check that none of the action args that are used as source for this
+	 * DMA transfer are not used as source in any other mov instruction.
+	 */
+	for (j = src_field_id; j < src_field_id + h->st->n_fields; j++) {
+		uint32_t n_users;
+
+		n_users = action_arg_src_mov_count(a,
+						   j,
+						   instructions,
+						   instruction_data,
+						   n_instructions);
+		if (n_users > 1)
+			return 0;
+	}
+
+	*n_pattern_instr = 1 + i;
+	return 1;
+}
+
+static void
+instr_pattern_mov_all_validate_replace(struct rte_swx_pipeline *p,
+				       struct action *a,
+				       struct instruction *instr,
+				       struct instruction_data *data,
+				       uint32_t n_instr)
+{
+	struct header *h;
+	uint32_t src_field_id, src_offset, i;
+
+	/* Read from the instructions before they are modified. */
+	h = header_find_by_struct_id(p, instr[0].mov.dst.struct_id);
+	if (!h)
+		return;
+
+	for (src_field_id = 0; src_field_id < a->st->n_fields; src_field_id++)
+		if (instr[0].mov.src.offset == a->st->fields[src_field_id].offset / 8)
+			break;
+
+	if (src_field_id == a->st->n_fields)
+		return;
+
+	src_offset = instr[0].mov.src.offset;
+
+	/* Modify the instructions. */
+	instr[0].type = INSTR_DMA_HT;
+	instr[0].dma.dst.header_id[0] = h->id;
+	instr[0].dma.dst.struct_id[0] = h->struct_id;
+	instr[0].dma.src.offset[0] = (uint8_t)src_offset;
+	instr[0].dma.n_bytes[0] = h->st->n_bits / 8;
+
+	for (i = 1; i < n_instr; i++)
+		data[i].invalid = 1;
+
+	/* Update the endianness of the action arguments to header endianness. */
+	for (i = 0; i < h->st->n_fields; i++)
+		a->args_endianness[src_field_id + i] = 1;
+}
+
+static uint32_t
+instr_pattern_mov_all_validate_optimize(struct rte_swx_pipeline *p,
+					struct action *a,
+					struct instruction *instructions,
+					struct instruction_data *instruction_data,
+					uint32_t n_instructions)
+{
+	uint32_t i;
+
+	if (!a || !a->st)
+		return n_instructions;
+
+	for (i = 0; i < n_instructions; ) {
+		struct instruction *instr = &instructions[i];
+		struct instruction_data *data = &instruction_data[i];
+		uint32_t n_instr = 0;
+		int detected;
+
+		/* Mov all + validate. */
+		detected = instr_pattern_mov_all_validate_search(p,
+								 a,
+								 instr,
+								 data,
+								 n_instructions - i,
+								 instructions,
+								 instruction_data,
+								 n_instructions,
+								 &n_instr);
+		if (detected) {
+			instr_pattern_mov_all_validate_replace(p, a, instr, data, n_instr);
+			i += n_instr;
+			continue;
+		}
+
+		/* No pattern starting at the current instruction. */
+		i++;
+	}
+
+	/* Eliminate the invalid instructions that have been optimized out. */
+	n_instructions = instr_compact(instructions,
+				       instruction_data,
+				       n_instructions);
+
+	return n_instructions;
+}
+
 static int
 instr_pattern_dma_many_search(struct instruction *instr,
 			      struct instruction_data *data,
@@ -8378,7 +8526,9 @@ instr_pattern_dma_many_optimize(struct instruction *instructions,
 }
 
 static uint32_t
-instr_optimize(struct instruction *instructions,
+instr_optimize(struct rte_swx_pipeline *p,
+	       struct action *a,
+	       struct instruction *instructions,
 	       struct instruction_data *instruction_data,
 	       uint32_t n_instructions)
 {
@@ -8392,6 +8542,13 @@ instr_optimize(struct instruction *instructions,
 							     instruction_data,
 							     n_instructions);
 
+	/* Mov all + validate. */
+	n_instructions = instr_pattern_mov_all_validate_optimize(p,
+								 a,
+								 instructions,
+								 instruction_data,
+								 n_instructions);
+
 	/* DMA many. */
 	n_instructions = instr_pattern_dma_many_optimize(instructions,
 							 instruction_data,
@@ -8453,7 +8610,7 @@ instruction_config(struct rte_swx_pipeline *p,
 	if (err)
 		goto error;
 
-	n_instructions = instr_optimize(instr, data, n_instructions);
+	n_instructions = instr_optimize(p, a, instr, data, n_instructions);
 
 	err = instr_jmp_resolve(instr, data, n_instructions);
 	if (err)
@@ -8742,6 +8899,13 @@ rte_swx_pipeline_action_config(struct rte_swx_pipeline *p,
 	/* Node allocation. */
 	a = calloc(1, sizeof(struct action));
 	CHECK(a, ENOMEM);
+	if (args_struct_type) {
+		a->args_endianness = calloc(args_struct_type->n_fields, sizeof(int));
+		if (!a->args_endianness) {
+			free(a);
+			CHECK(0, ENOMEM);
+		}
+	}
 
 	/* Node initialization. */
 	strcpy(a->name, name);
@@ -8751,6 +8915,7 @@ rte_swx_pipeline_action_config(struct rte_swx_pipeline *p,
 	/* Instruction translation. */
 	err = instruction_config(p, a, instructions, n_instructions);
 	if (err) {
+		free(a->args_endianness);
 		free(a);
 		return err;
 	}
@@ -8802,6 +8967,40 @@ action_free(struct rte_swx_pipeline *p)
 	}
 }
 
+static uint32_t
+action_arg_src_mov_count(struct action *a,
+			 uint32_t arg_id,
+			 struct instruction *instructions,
+			 struct instruction_data *instruction_data,
+			 uint32_t n_instructions)
+{
+	uint32_t offset, n_users = 0, i;
+
+	if (!a->st ||
+	    (arg_id >= a->st->n_fields) ||
+	    !instructions ||
+	    !instruction_data ||
+	    !n_instructions)
+		return 0;
+
+	offset = a->st->fields[arg_id].offset / 8;
+
+	for (i = 0; i < n_instructions; i++) {
+		struct instruction *instr = &instructions[i];
+		struct instruction_data *data = &instruction_data[i];
+
+		if (data->invalid ||
+		    ((instr->type != INSTR_MOV) && (instr->type != INSTR_MOV_HM)) ||
+		    instr->mov.src.struct_id ||
+		    (instr->mov.src.offset != offset))
+			continue;
+
+		n_users++;
+	}
+
+	return n_users;
+}
+
 /*
  * Table.
  */
@@ -9898,6 +10097,7 @@ rte_swx_ctl_action_arg_info_get(struct rte_swx_pipeline *p,
 	arg = &a->st->fields[action_arg_id];
 	strcpy(action_arg->name, arg->name);
 	action_arg->n_bits = arg->n_bits;
+	action_arg->is_network_byte_order = a->args_endianness[action_arg_id];
 
 	return 0;
 }
diff --git a/lib/librte_pipeline/rte_swx_pipeline.h b/lib/librte_pipeline/rte_swx_pipeline.h
index 156b1fd67..feeb10a5c 100644
--- a/lib/librte_pipeline/rte_swx_pipeline.h
+++ b/lib/librte_pipeline/rte_swx_pipeline.h
@@ -406,10 +406,6 @@ rte_swx_pipeline_packet_metadata_register(struct rte_swx_pipeline *p,
  *<pre>+------------+----------------------+-------------------+------+--------+</pre>
  *<pre>| mov        | dst = src            | mov dst src       | HMEF | HMEFTI |</pre>
  *<pre>+------------+----------------------+-------------------+------+--------+</pre>
- *<pre>| dma        | memcpy(h.hdr,        | dma h.hdr t.field | hdr  | T      |</pre>
- *<pre>|            |    &t.field,         |                   |      |        |</pre>
- *<pre>|            |    sizeof(h.hdr)     |                   |      |        |</pre>
- *<pre>+------------+----------------------+-------------------+------+--------+</pre>
  *<pre>| add        | dst += src           | add dst src       | HMEF | HMEFTI |</pre>
  *<pre>+------------+----------------------+-------------------+------+--------+</pre>
  *<pre>| sub        | dst -= src           | add dst src       | HMEF | HMEFTI |</pre>
