Typos. A bunch of typos I've been collecting.
[vpp.git] / test / test_nat.py
index 524301f..b8d3a54 100644 (file)
@@ -3,24 +3,68 @@
 import socket
 import unittest
 import struct
-import StringIO
 import random
 
 from framework import VppTestCase, VppTestRunner, running_extended_tests
+
+import scapy.compat
 from scapy.layers.inet import IP, TCP, UDP, ICMP
 from scapy.layers.inet import IPerror, TCPerror, UDPerror, ICMPerror
 from scapy.layers.inet6 import IPv6, ICMPv6EchoRequest, ICMPv6EchoReply, \
-    ICMPv6ND_NS, ICMPv6ND_NA, ICMPv6NDOptDstLLAddr
+    ICMPv6ND_NS, ICMPv6ND_NA, ICMPv6NDOptDstLLAddr, fragment6
 from scapy.layers.inet6 import ICMPv6DestUnreach, IPerror6, IPv6ExtHdrFragment
 from scapy.layers.l2 import Ether, ARP, GRE
 from scapy.data import IP_PROTOS
 from scapy.packet import bind_layers, Raw
-from scapy.all import fragment6
 from util import ppp
 from ipfix import IPFIX, Set, Template, Data, IPFIXDecoder
 from time import sleep
 from util import ip4_range
-from util import mactobinary
+from vpp_papi import mac_pton
+from syslog_rfc5424_parser import SyslogMessage, ParseError
+from syslog_rfc5424_parser.constants import SyslogFacility, SyslogSeverity
+from vpp_papi_provider import SYSLOG_SEVERITY
+from io import BytesIO
+from vpp_papi import VppEnum
+from scapy.all import bind_layers, Packet, ByteEnumField, ShortField, \
+    IPField, IntField, LongField, XByteField, FlagsField, FieldLenField, \
+    PacketListField
+
+
+# NAT HA protocol event data
+class Event(Packet):
+    name = "Event"
+    fields_desc = [ByteEnumField("event_type", None,
+                                 {1: "add", 2: "del", 3: "refresh"}),
+                   ByteEnumField("protocol", None,
+                                 {0: "udp", 1: "tcp", 2: "icmp"}),
+                   ShortField("flags", 0),
+                   IPField("in_addr", None),
+                   IPField("out_addr", None),
+                   ShortField("in_port", None),
+                   ShortField("out_port", None),
+                   IPField("eh_addr", None),
+                   IPField("ehn_addr", None),
+                   ShortField("eh_port", None),
+                   ShortField("ehn_port", None),
+                   IntField("fib_index", None),
+                   IntField("total_pkts", 0),
+                   LongField("total_bytes", 0)]
+
+    def extract_padding(self, s):
+        return "", s
+
+
+# NAT HA protocol header
+class HANATStateSync(Packet):
+    name = "HA NAT state sync"
+    fields_desc = [XByteField("version", 1),
+                   FlagsField("flags", 0, 8, ['ACK']),
+                   FieldLenField("count", None, count_of="events"),
+                   IntField("sequence_number", 1),
+                   IntField("thread_index", 0),
+                   PacketListField("events", [], Event,
+                                   count_from=lambda pkt: pkt.count)]
 
 
 class MethodHolder(VppTestCase):
@@ -46,12 +90,13 @@ class MethodHolder(VppTestCase):
                 is_add=0)
 
             for intf in [self.pg7, self.pg8]:
-                neighbors = self.vapi.ip_neighbor_dump(intf.sw_if_index)
-                for n in neighbors:
-                    self.vapi.ip_neighbor_add_del(intf.sw_if_index,
-                                                  n.mac_address,
-                                                  n.ip_address,
-                                                  is_add=0)
+                self.vapi.ip_neighbor_add_del(
+                    intf.sw_if_index,
+                    intf.remote_mac,
+                    intf.remote_ip4,
+                    flags=(VppEnum.vl_api_ip_neighbor_flags_t.
+                           IP_API_NEIGHBOR_FLAG_STATIC),
+                    is_add=0)
 
             if self.pg7.has_ip4_config:
                 self.pg7.unconfig_ip4()
@@ -60,15 +105,21 @@ class MethodHolder(VppTestCase):
 
         interfaces = self.vapi.nat44_interface_addr_dump()
         for intf in interfaces:
-            self.vapi.nat44_add_interface_addr(intf.sw_if_index,
-                                               twice_nat=intf.twice_nat,
-                                               is_add=0)
+            self.vapi.nat44_add_del_interface_addr(intf.sw_if_index,
+                                                   twice_nat=intf.twice_nat,
+                                                   is_add=0)
 
-        self.vapi.nat_ipfix(enable=0, src_port=self.ipfix_src_port,
-                            domain_id=self.ipfix_domain_id)
+        self.vapi.nat_ipfix_enable_disable(enable=0,
+                                           src_port=self.ipfix_src_port,
+                                           domain_id=self.ipfix_domain_id)
         self.ipfix_src_port = 4739
         self.ipfix_domain_id = 1
 
+        self.vapi.syslog_set_filter(SYSLOG_SEVERITY.EMERG)
+
+        self.vapi.nat_ha_set_listener('0.0.0.0', 0)
+        self.vapi.nat_ha_set_failover('0.0.0.0', 0)
+
         interfaces = self.vapi.nat44_interface_dump()
         for intf in interfaces:
             if intf.is_inside > 1:
@@ -127,8 +178,8 @@ class MethodHolder(VppTestCase):
                 protocol=id_m.protocol,
                 is_add=0)
 
-        adresses = self.vapi.nat44_address_dump()
-        for addr in adresses:
+        addresses = self.vapi.nat44_address_dump()
+        for addr in addresses:
             self.vapi.nat44_add_del_address_range(addr.ip_address,
                                                   addr.ip_address,
                                                   twice_nat=addr.twice_nat,
@@ -190,7 +241,7 @@ class MethodHolder(VppTestCase):
 
         :param ip: IP address
         :param is_add: 1 if add, 0 if delete (Default add)
-        :param twice_nat: twice NAT address for extenal hosts
+        :param twice_nat: twice NAT address for external hosts
         """
         nat_addr = socket.inet_pton(socket.AF_INET, ip)
         self.vapi.nat44_add_del_address_range(nat_addr, nat_addr, is_add,
@@ -271,7 +322,8 @@ class MethodHolder(VppTestCase):
             pref_n[13] = ip4_n[1]
             pref_n[14] = ip4_n[2]
             pref_n[15] = ip4_n[3]
-        return socket.inet_ntop(socket.AF_INET6, ''.join(pref_n))
+        packed_pref_n = b''.join([scapy.compat.chb(x) for x in pref_n])
+        return socket.inet_ntop(socket.AF_INET6, packed_pref_n)
 
     def extract_ip4(self, ip6, plen):
         """
@@ -429,7 +481,7 @@ class MethodHolder(VppTestCase):
 
         :param capture: Captured packets
         :param nat_ip: Translated IP address (Default use global NAT address)
-        :param same_port: Sorce port number is not translated (Default False)
+        :param same_port: Source port number is not translated (Default False)
         :param dst_ip: Destination IP address (Default do not verify)
         :param is_ip6: If L3 protocol is IPv6 (Default False)
         """
@@ -482,7 +534,7 @@ class MethodHolder(VppTestCase):
 
         :param capture: Captured packets
         :param nat_ip: Translated IP address
-        :param same_port: Sorce port number is not translated (Default False)
+        :param same_port: Source port number is not translated (Default False)
         :param dst_ip: Destination IP address (Default do not verify)
         """
         return self.verify_capture_out(capture, nat_ip, same_port, dst_ip,
@@ -574,7 +626,7 @@ class MethodHolder(VppTestCase):
         for packet in capture:
             try:
                 self.assertEqual(packet[IP].src, src_ip)
-                self.assertTrue(packet.haslayer(ICMP))
+                self.assertEqual(packet.haslayer(ICMP), 1)
                 icmp = packet[ICMP]
                 self.assertEqual(icmp.type, icmp_type)
                 self.assertTrue(icmp.haslayer(IPerror))
@@ -604,7 +656,7 @@ class MethodHolder(VppTestCase):
         for packet in capture:
             try:
                 self.assertEqual(packet[IP].dst, in_if.remote_ip4)
-                self.assertTrue(packet.haslayer(ICMP))
+                self.assertEqual(packet.haslayer(ICMP), 1)
                 icmp = packet[ICMP]
                 self.assertEqual(icmp.type, icmp_type)
                 self.assertTrue(icmp.haslayer(IPerror))
@@ -634,14 +686,14 @@ class MethodHolder(VppTestCase):
         :param data: Payload data
         :param proto: protocol (TCP, UDP, ICMP)
         :param echo_reply: use echo_reply if protocol is ICMP
-        :returns: Fragmets
+        :returns: Fragments
         """
         if proto == IP_PROTOS.tcp:
             p = (IP(src=src_if.remote_ip4, dst=dst) /
                  TCP(sport=sport, dport=dport) /
                  Raw(data))
-            p = p.__class__(str(p))
-            chksum = p['TCP'].chksum
+            p = p.__class__(scapy.compat.raw(p))
+            chksum = p[TCP].chksum
             proto_header = TCP(sport=sport, dport=dport, chksum=chksum)
         elif proto == IP_PROTOS.udp:
             proto_header = UDP(sport=sport, dport=dport)
@@ -696,7 +748,7 @@ class MethodHolder(VppTestCase):
         :param pref: NAT64 prefix
         :param plen: NAT64 prefix length
         :param fragsize: size of fragments
-        :returns: Fragmets
+        :returns: Fragments
         """
         if pref is None:
             dst_ip6 = ''.join(['64:ff9b::', dst])
@@ -721,13 +773,13 @@ class MethodHolder(VppTestCase):
 
         :returns: Reassembled IPv4 packet
         """
-        buffer = StringIO.StringIO()
+        buffer = BytesIO()
         for p in frags:
             self.assertEqual(p[IP].src, src)
             self.assertEqual(p[IP].dst, dst)
             self.assert_ip_checksum_valid(p)
             buffer.seek(p[IP].frag * 8)
-            buffer.write(p[IP].payload)
+            buffer.write(bytes(p[IP].payload))
         ip = IP(src=frags[0][IP].src, dst=frags[0][IP].dst,
                 proto=frags[0][IP].proto)
         if ip.proto == IP_PROTOS.tcp:
@@ -750,12 +802,12 @@ class MethodHolder(VppTestCase):
 
         :returns: Reassembled IPv6 packet
         """
-        buffer = StringIO.StringIO()
+        buffer = BytesIO()
         for p in frags:
             self.assertEqual(p[IPv6].src, src)
             self.assertEqual(p[IPv6].dst, dst)
             buffer.seek(p[IPv6ExtHdrFragment].offset * 8)
-            buffer.write(p[IPv6ExtHdrFragment].payload)
+            buffer.write(bytes(p[IPv6ExtHdrFragment].payload))
         ip = IPv6(src=frags[0][IPv6].src, dst=frags[0][IPv6].dst,
                   nh=frags[0][IPv6ExtHdrFragment].nh)
         if ip.nh == IP_PROTOS.tcp:
@@ -820,8 +872,8 @@ class MethodHolder(VppTestCase):
         self.assertEqual(6, len(data))
         for record in data:
             # natEvent
-            self.assertIn(ord(record[230]), [4, 5])
-            if ord(record[230]) == 4:
+            self.assertIn(scapy.compat.orb(record[230]), [4, 5])
+            if scapy.compat.orb(record[230]) == 4:
                 nat44_ses_create_num += 1
             else:
                 nat44_ses_delete_num += 1
@@ -833,16 +885,16 @@ class MethodHolder(VppTestCase):
             # ingressVRFID
             self.assertEqual(struct.pack("!I", 0), record[234])
             # protocolIdentifier/sourceTransportPort/postNAPTSourceTransportPort
-            if IP_PROTOS.icmp == ord(record[4]):
+            if IP_PROTOS.icmp == scapy.compat.orb(record[4]):
                 self.assertEqual(struct.pack("!H", self.icmp_id_in), record[7])
                 self.assertEqual(struct.pack("!H", self.icmp_id_out),
                                  record[227])
-            elif IP_PROTOS.tcp == ord(record[4]):
+            elif IP_PROTOS.tcp == scapy.compat.orb(record[4]):
                 self.assertEqual(struct.pack("!H", self.tcp_port_in),
                                  record[7])
                 self.assertEqual(struct.pack("!H", self.tcp_port_out),
                                  record[227])
-            elif IP_PROTOS.udp == ord(record[4]):
+            elif IP_PROTOS.udp == scapy.compat.orb(record[4]):
                 self.assertEqual(struct.pack("!H", self.udp_port_in),
                                  record[7])
                 self.assertEqual(struct.pack("!H", self.udp_port_out),
@@ -861,7 +913,7 @@ class MethodHolder(VppTestCase):
         self.assertEqual(1, len(data))
         record = data[0]
         # natEvent
-        self.assertEqual(ord(record[230]), 3)
+        self.assertEqual(scapy.compat.orb(record[230]), 3)
         # natPoolID
         self.assertEqual(struct.pack("!I", 0), record[283])
 
@@ -875,7 +927,7 @@ class MethodHolder(VppTestCase):
         self.assertEqual(1, len(data))
         record = data[0]
         # natEvent
-        self.assertEqual(ord(record[230]), 13)
+        self.assertEqual(scapy.compat.orb(record[230]), 13)
         # natQuotaExceededEvent
         self.assertEqual(struct.pack("I", 1), record[466])
         # maxSessionEntries
@@ -891,7 +943,7 @@ class MethodHolder(VppTestCase):
         self.assertEqual(1, len(data))
         record = data[0]
         # natEvent
-        self.assertEqual(ord(record[230]), 13)
+        self.assertEqual(scapy.compat.orb(record[230]), 13)
         # natQuotaExceededEvent
         self.assertEqual(struct.pack("I", 2), record[466])
         # maxBIBEntries
@@ -908,7 +960,7 @@ class MethodHolder(VppTestCase):
         self.assertEqual(1, len(data))
         record = data[0]
         # natEvent
-        self.assertEqual(ord(record[230]), 13)
+        self.assertEqual(scapy.compat.orb(record[230]), 13)
         # natQuotaExceededEvent
         self.assertEqual(struct.pack("I", 5), record[466])
         # maxFragmentsPendingReassembly
@@ -927,7 +979,7 @@ class MethodHolder(VppTestCase):
         self.assertEqual(1, len(data))
         record = data[0]
         # natEvent
-        self.assertEqual(ord(record[230]), 13)
+        self.assertEqual(scapy.compat.orb(record[230]), 13)
         # natQuotaExceededEvent
         self.assertEqual(struct.pack("I", 5), record[466])
         # maxFragmentsPendingReassembly
@@ -947,15 +999,15 @@ class MethodHolder(VppTestCase):
         record = data[0]
         # natEvent
         if is_create:
-            self.assertEqual(ord(record[230]), 10)
+            self.assertEqual(scapy.compat.orb(record[230]), 10)
         else:
-            self.assertEqual(ord(record[230]), 11)
+            self.assertEqual(scapy.compat.orb(record[230]), 11)
         # sourceIPv6Address
         self.assertEqual(src_addr, record[27])
         # postNATSourceIPv4Address
         self.assertEqual(self.nat_addr_n, record[225])
         # protocolIdentifier
-        self.assertEqual(IP_PROTOS.tcp, ord(record[4]))
+        self.assertEqual(IP_PROTOS.tcp, scapy.compat.orb(record[4]))
         # ingressVRFID
         self.assertEqual(struct.pack("!I", 0), record[234])
         # sourceTransportPort
@@ -978,9 +1030,9 @@ class MethodHolder(VppTestCase):
         record = data[0]
         # natEvent
         if is_create:
-            self.assertEqual(ord(record[230]), 6)
+            self.assertEqual(scapy.compat.orb(record[230]), 6)
         else:
-            self.assertEqual(ord(record[230]), 7)
+            self.assertEqual(scapy.compat.orb(record[230]), 7)
         # sourceIPv6Address
         self.assertEqual(src_addr, record[27])
         # destinationIPv6Address
@@ -995,7 +1047,7 @@ class MethodHolder(VppTestCase):
         self.assertEqual(socket.inet_pton(socket.AF_INET, dst_addr),
                          record[226])
         # protocolIdentifier
-        self.assertEqual(IP_PROTOS.tcp, ord(record[4]))
+        self.assertEqual(IP_PROTOS.tcp, scapy.compat.orb(record[4]))
         # ingressVRFID
         self.assertEqual(struct.pack("!I", 0), record[234])
         # sourceTransportPort
@@ -1011,6 +1063,10 @@ class MethodHolder(VppTestCase):
         """ Verify that there is no NAT44 user """
         users = self.vapi.nat44_user_dump()
         self.assertEqual(len(users), 0)
+        users = self.statistics.get_counter('/nat44/total-users')
+        self.assertEqual(users[0][0], 0)
+        sessions = self.statistics.get_counter('/nat44/total-sessions')
+        self.assertEqual(sessions[0][0], 0)
 
     def verify_ipfix_max_entries_per_user(self, data, limit, src_addr):
         """
@@ -1023,7 +1079,7 @@ class MethodHolder(VppTestCase):
         self.assertEqual(1, len(data))
         record = data[0]
         # natEvent
-        self.assertEqual(ord(record[230]), 13)
+        self.assertEqual(scapy.compat.orb(record[230]), 13)
         # natQuotaExceededEvent
         self.assertEqual(struct.pack("I", 3), record[466])
         # maxEntriesPerUser
@@ -1031,6 +1087,59 @@ class MethodHolder(VppTestCase):
         # sourceIPv4Address
         self.assertEqual(src_addr, record[8])
 
+    def verify_syslog_apmap(self, data, is_add=True):
+        message = data.decode('utf-8')
+        try:
+            message = SyslogMessage.parse(message)
+        except ParseError as e:
+            self.logger.error(e)
+            raise
+        else:
+            self.assertEqual(message.severity, SyslogSeverity.info)
+            self.assertEqual(message.appname, 'NAT')
+            self.assertEqual(message.msgid, 'APMADD' if is_add else 'APMDEL')
+            sd_params = message.sd.get('napmap')
+            self.assertTrue(sd_params is not None)
+            self.assertEqual(sd_params.get('IATYP'), 'IPv4')
+            self.assertEqual(sd_params.get('ISADDR'), self.pg0.remote_ip4)
+            self.assertEqual(sd_params.get('ISPORT'), "%d" % self.tcp_port_in)
+            self.assertEqual(sd_params.get('XATYP'), 'IPv4')
+            self.assertEqual(sd_params.get('XSADDR'), self.nat_addr)
+            self.assertEqual(sd_params.get('XSPORT'), "%d" % self.tcp_port_out)
+            self.assertEqual(sd_params.get('PROTO'), "%d" % IP_PROTOS.tcp)
+            self.assertTrue(sd_params.get('SSUBIX') is not None)
+            self.assertEqual(sd_params.get('SVLAN'), '0')
+
+    def verify_syslog_sess(self, data, is_add=True, is_ip6=False):
+        message = data.decode('utf-8')
+        try:
+            message = SyslogMessage.parse(message)
+        except ParseError as e:
+            self.logger.error(e)
+            raise
+        else:
+            self.assertEqual(message.severity, SyslogSeverity.info)
+            self.assertEqual(message.appname, 'NAT')
+            self.assertEqual(message.msgid, 'SADD' if is_add else 'SDEL')
+            sd_params = message.sd.get('nsess')
+            self.assertTrue(sd_params is not None)
+            if is_ip6:
+                self.assertEqual(sd_params.get('IATYP'), 'IPv6')
+                self.assertEqual(sd_params.get('ISADDR'), self.pg0.remote_ip6)
+            else:
+                self.assertEqual(sd_params.get('IATYP'), 'IPv4')
+                self.assertEqual(sd_params.get('ISADDR'), self.pg0.remote_ip4)
+                self.assertTrue(sd_params.get('SSUBIX') is not None)
+            self.assertEqual(sd_params.get('ISPORT'), "%d" % self.tcp_port_in)
+            self.assertEqual(sd_params.get('XATYP'), 'IPv4')
+            self.assertEqual(sd_params.get('XSADDR'), self.nat_addr)
+            self.assertEqual(sd_params.get('XSPORT'), "%d" % self.tcp_port_out)
+            self.assertEqual(sd_params.get('PROTO'), "%d" % IP_PROTOS.tcp)
+            self.assertEqual(sd_params.get('SVLAN'), '0')
+            self.assertEqual(sd_params.get('XDADDR'), self.pg1.remote_ip4)
+            self.assertEqual(sd_params.get('XDPORT'),
+                             "%d" % self.tcp_external_port)
+
     def verify_mss_value(self, pkt, mss):
         """
         Verify TCP MSS value
@@ -1061,9 +1170,9 @@ class MethodHolder(VppTestCase):
         layer = self.proto2layer(proto)
 
         if proto == IP_PROTOS.tcp:
-            data = "A" * 4 + "B" * 16 + "C" * 3
+            data = b"A" * 4 + b"B" * 16 + b"C" * 3
         else:
-            data = "A" * 16 + "B" * 16 + "C" * 3
+            data = b"A" * 16 + b"B" * 16 + b"C" * 3
         self.port_in = random.randint(1025, 65535)
 
         reass = self.vapi.nat_reass_dump()
@@ -1142,9 +1251,9 @@ class MethodHolder(VppTestCase):
         layer = self.proto2layer(proto)
 
         if proto == IP_PROTOS.tcp:
-            data = "A" * 4 + "B" * 16 + "C" * 3
+            data = b"A" * 4 + b"B" * 16 + b"C" * 3
         else:
-            data = "A" * 16 + "B" * 16 + "C" * 3
+            data = b"A" * 16 + b"B" * 16 + b"C" * 3
         self.port_in = random.randint(1025, 65535)
 
         for i in range(2):
@@ -1211,9 +1320,9 @@ class MethodHolder(VppTestCase):
         layer = self.proto2layer(proto)
 
         if proto == IP_PROTOS.tcp:
-            data = "A" * 4 + "B" * 16 + "C" * 3
+            data = b"A" * 4 + b"B" * 16 + b"C" * 3
         else:
-            data = "A" * 16 + "B" * 16 + "C" * 3
+            data = b"A" * 16 + b"B" * 16 + b"C" * 3
 
         # send packet from host to server
         pkts = self.create_stream_frag(self.pg0,
@@ -1240,9 +1349,9 @@ class MethodHolder(VppTestCase):
         layer = self.proto2layer(proto)
 
         if proto == IP_PROTOS.tcp:
-            data = "A" * 4 + "B" * 16 + "C" * 3
+            data = b"A" * 4 + b"B" * 16 + b"C" * 3
         else:
-            data = "A" * 16 + "B" * 16 + "C" * 3
+            data = b"A" * 16 + b"B" * 16 + b"C" * 3
         self.port_in = random.randint(1025, 65535)
 
         for i in range(2):
@@ -1316,9 +1425,9 @@ class MethodHolder(VppTestCase):
         layer = self.proto2layer(proto)
 
         if proto == IP_PROTOS.tcp:
-            data = "A" * 4 + "B" * 16 + "C" * 3
+            data = b"A" * 4 + b"B" * 16 + b"C" * 3
         else:
-            data = "A" * 16 + "B" * 16 + "C" * 3
+            data = b"A" * 16 + b"B" * 16 + b"C" * 3
         self.port_in = random.randint(1025, 65535)
 
         for i in range(2):
@@ -1397,6 +1506,7 @@ class TestNAT44(MethodHolder):
             cls.ipfix_src_port = 4739
             cls.ipfix_domain_id = 1
             cls.tcp_external_port = 80
+            cls.udp_external_port = 69
 
             cls.create_pg_interfaces(range(10))
             cls.interfaces = list(cls.pg_interfaces[0:4])
@@ -1413,8 +1523,8 @@ class TestNAT44(MethodHolder):
             cls.pg1.configure_ipv4_neighbors()
 
             cls.overlapping_interfaces = list(list(cls.pg_interfaces[4:7]))
-            cls.vapi.ip_table_add_del(10, is_add=1)
-            cls.vapi.ip_table_add_del(20, is_add=1)
+            cls.vapi.ip_table_add_del(is_add=1, table_id=10)
+            cls.vapi.ip_table_add_del(is_add=1, table_id=20)
 
             cls.pg4._local_ip4 = "172.16.255.1"
             cls.pg4._local_ip4n = socket.inet_pton(socket.AF_INET, i.local_ip4)
@@ -1439,9 +1549,9 @@ class TestNAT44(MethodHolder):
             cls.pg9.generate_remote_hosts(2)
             cls.pg9.config_ip4()
             ip_addr_n = socket.inet_pton(socket.AF_INET, "10.0.0.1")
-            cls.vapi.sw_interface_add_del_address(cls.pg9.sw_if_index,
-                                                  ip_addr_n,
-                                                  24)
+            cls.vapi.sw_interface_add_del_address(
+                sw_if_index=cls.pg9.sw_if_index, address=ip_addr_n,
+                address_length=24)
             cls.pg9.admin_up()
             cls.pg9.resolve_arp()
             cls.pg9._remote_hosts[1]._ip4 = cls.pg9._remote_hosts[0]._ip4
@@ -1454,13 +1564,21 @@ class TestNAT44(MethodHolder):
 
     def test_dynamic(self):
         """ NAT44 dynamic translation test """
-
         self.nat44_add_address(self.nat_addr)
         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
                                                   is_inside=0)
 
         # in2out
+        tcpn = self.statistics.get_counter(
+            '/err/nat44-in2out-slowpath/TCP packets')
+        udpn = self.statistics.get_counter(
+            '/err/nat44-in2out-slowpath/UDP packets')
+        icmpn = self.statistics.get_counter(
+            '/err/nat44-in2out-slowpath/ICMP packets')
+        totaln = self.statistics.get_counter(
+            '/err/nat44-in2out-slowpath/good in2out packets processed')
+
         pkts = self.create_stream_in(self.pg0, self.pg1)
         self.pg0.add_stream(pkts)
         self.pg_enable_capture(self.pg_interfaces)
@@ -1468,7 +1586,26 @@ class TestNAT44(MethodHolder):
         capture = self.pg1.get_capture(len(pkts))
         self.verify_capture_out(capture)
 
+        err = self.statistics.get_counter(
+            '/err/nat44-in2out-slowpath/TCP packets')
+        self.assertEqual(err - tcpn, 1)
+        err = self.statistics.get_counter(
+            '/err/nat44-in2out-slowpath/UDP packets')
+        self.assertEqual(err - udpn, 1)
+        err = self.statistics.get_counter(
+            '/err/nat44-in2out-slowpath/ICMP packets')
+        self.assertEqual(err - icmpn, 1)
+        err = self.statistics.get_counter(
+            '/err/nat44-in2out-slowpath/good in2out packets processed')
+        self.assertEqual(err - totaln, 3)
+
         # out2in
+        tcpn = self.statistics.get_counter('/err/nat44-out2in/TCP packets')
+        udpn = self.statistics.get_counter('/err/nat44-out2in/UDP packets')
+        icmpn = self.statistics.get_counter('/err/nat44-out2in/ICMP packets')
+        totaln = self.statistics.get_counter(
+            '/err/nat44-out2in/good out2in packets processed')
+
         pkts = self.create_stream_out(self.pg1)
         self.pg1.add_stream(pkts)
         self.pg_enable_capture(self.pg_interfaces)
@@ -1476,6 +1613,21 @@ class TestNAT44(MethodHolder):
         capture = self.pg0.get_capture(len(pkts))
         self.verify_capture_in(capture, self.pg0)
 
+        err = self.statistics.get_counter('/err/nat44-out2in/TCP packets')
+        self.assertEqual(err - tcpn, 1)
+        err = self.statistics.get_counter('/err/nat44-out2in/UDP packets')
+        self.assertEqual(err - udpn, 1)
+        err = self.statistics.get_counter('/err/nat44-out2in/ICMP packets')
+        self.assertEqual(err - icmpn, 1)
+        err = self.statistics.get_counter(
+            '/err/nat44-out2in/good out2in packets processed')
+        self.assertEqual(err - totaln, 3)
+
+        users = self.statistics.get_counter('/nat44/total-users')
+        self.assertEqual(users[0][0], 1)
+        sessions = self.statistics.get_counter('/nat44/total-sessions')
+        self.assertEqual(sessions[0][0], 3)
+
     def test_dynamic_icmp_errors_in2out_ttl_1(self):
         """ NAT44 handling of client packets with TTL=1 """
 
@@ -1714,7 +1866,7 @@ class TestNAT44(MethodHolder):
                                                   is_inside=0)
         sm = self.vapi.nat44_static_mapping_dump()
         self.assertEqual(len(sm), 1)
-        self.assertEqual((sm[0].tag).split('\0', 1)[0], '')
+        self.assertEqual((sm[0].tag).split(b'\0', 1)[0], b'')
         self.assertEqual(sm[0].protocol, 0)
         self.assertEqual(sm[0].local_port, 0)
         self.assertEqual(sm[0].external_port, 0)
@@ -1742,7 +1894,7 @@ class TestNAT44(MethodHolder):
         self.tcp_port_out = 6303
         self.udp_port_out = 6304
         self.icmp_id_out = 6305
-        tag = "testTAG"
+        tag = b"testTAG"
 
         self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip, tag=tag)
         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
@@ -1750,7 +1902,7 @@ class TestNAT44(MethodHolder):
                                                   is_inside=0)
         sm = self.vapi.nat44_static_mapping_dump()
         self.assertEqual(len(sm), 1)
-        self.assertEqual((sm[0].tag).split('\0', 1)[0], tag)
+        self.assertEqual((sm[0].tag).split(b'\0', 1)[0], tag)
 
         # out2in
         pkts = self.create_stream_out(self.pg1, nat_ip)
@@ -2111,7 +2263,7 @@ class TestNAT44(MethodHolder):
 
         # general user and session dump verifications
         users = self.vapi.nat44_user_dump()
-        self.assertTrue(len(users) >= 3)
+        self.assertGreaterEqual(len(users), 3)
         addresses = self.vapi.nat44_address_dump()
         self.assertEqual(len(addresses), 1)
         for user in users:
@@ -2127,7 +2279,7 @@ class TestNAT44(MethodHolder):
 
         # pg4 session dump
         sessions = self.vapi.nat44_user_session_dump(self.pg4.remote_ip4n, 10)
-        self.assertTrue(len(sessions) >= 4)
+        self.assertGreaterEqual(len(sessions), 4)
         for session in sessions:
             self.assertFalse(session.is_static)
             self.assertEqual(session.inside_ip_address[0:4],
@@ -2137,13 +2289,13 @@ class TestNAT44(MethodHolder):
 
         # pg6 session dump
         sessions = self.vapi.nat44_user_session_dump(self.pg6.remote_ip4n, 20)
-        self.assertTrue(len(sessions) >= 3)
+        self.assertGreaterEqual(len(sessions), 3)
         for session in sessions:
             self.assertTrue(session.is_static)
             self.assertEqual(session.inside_ip_address[0:4],
                              self.pg6.remote_ip4n)
-            self.assertEqual(map(ord, session.outside_ip_address[0:4]),
-                             map(int, static_nat_ip.split('.')))
+            self.assertEqual(session.outside_ip_address,
+                             socket.inet_pton(socket.AF_INET, static_nat_ip))
             self.assertTrue(session.inside_port in
                             [self.tcp_port_in, self.udp_port_in,
                              self.icmp_id_in])
@@ -2429,28 +2581,28 @@ class TestNAT44(MethodHolder):
 
     def test_interface_addr(self):
         """ Acquire NAT44 addresses from interface """
-        self.vapi.nat44_add_interface_addr(self.pg7.sw_if_index)
+        self.vapi.nat44_add_del_interface_addr(self.pg7.sw_if_index)
 
         # no address in NAT pool
-        adresses = self.vapi.nat44_address_dump()
-        self.assertEqual(0, len(adresses))
+        addresses = self.vapi.nat44_address_dump()
+        self.assertEqual(0, len(addresses))
 
         # configure interface address and check NAT address pool
         self.pg7.config_ip4()
-        adresses = self.vapi.nat44_address_dump()
-        self.assertEqual(1, len(adresses))
-        self.assertEqual(adresses[0].ip_address[0:4], self.pg7.local_ip4n)
+        addresses = self.vapi.nat44_address_dump()
+        self.assertEqual(1, len(addresses))
+        self.assertEqual(addresses[0].ip_address[0:4], self.pg7.local_ip4n)
 
         # remove interface address and check NAT address pool
         self.pg7.unconfig_ip4()
-        adresses = self.vapi.nat44_address_dump()
-        self.assertEqual(0, len(adresses))
+        addresses = self.vapi.nat44_address_dump()
+        self.assertEqual(0, len(addresses))
 
     def test_interface_addr_static_mapping(self):
         """ Static mapping with addresses from interface """
-        tag = "testTAG"
+        tag = b"testTAG"
 
-        self.vapi.nat44_add_interface_addr(self.pg7.sw_if_index)
+        self.vapi.nat44_add_del_interface_addr(self.pg7.sw_if_index)
         self.nat44_add_static_mapping(
             '1.2.3.4',
             external_sw_if_index=self.pg7.sw_if_index,
@@ -2461,7 +2613,7 @@ class TestNAT44(MethodHolder):
         self.assertEqual(1, len(static_mappings))
         self.assertEqual(self.pg7.sw_if_index,
                          static_mappings[0].external_sw_if_index)
-        self.assertEqual((static_mappings[0].tag).split('\0', 1)[0], tag)
+        self.assertEqual((static_mappings[0].tag).split(b'\0', 1)[0], tag)
 
         # configure interface address and check static mappings
         self.pg7.config_ip4()
@@ -2472,7 +2624,7 @@ class TestNAT44(MethodHolder):
             if sm.external_sw_if_index == 0xFFFFFFFF:
                 self.assertEqual(sm.external_ip_address[0:4],
                                  self.pg7.local_ip4n)
-                self.assertEqual((sm.tag).split('\0', 1)[0], tag)
+                self.assertEqual((sm.tag).split(b'\0', 1)[0], tag)
                 resolved = True
         self.assertTrue(resolved)
 
@@ -2482,7 +2634,7 @@ class TestNAT44(MethodHolder):
         self.assertEqual(1, len(static_mappings))
         self.assertEqual(self.pg7.sw_if_index,
                          static_mappings[0].external_sw_if_index)
-        self.assertEqual((static_mappings[0].tag).split('\0', 1)[0], tag)
+        self.assertEqual((static_mappings[0].tag).split(b'\0', 1)[0], tag)
 
         # configure interface address again and check static mappings
         self.pg7.config_ip4()
@@ -2493,7 +2645,7 @@ class TestNAT44(MethodHolder):
             if sm.external_sw_if_index == 0xFFFFFFFF:
                 self.assertEqual(sm.external_ip_address[0:4],
                                  self.pg7.local_ip4n)
-                self.assertEqual((sm.tag).split('\0', 1)[0], tag)
+                self.assertEqual((sm.tag).split(b'\0', 1)[0], tag)
                 resolved = True
         self.assertTrue(resolved)
 
@@ -2510,7 +2662,7 @@ class TestNAT44(MethodHolder):
         """ Identity NAT with addresses from interface """
 
         port = 53053
-        self.vapi.nat44_add_interface_addr(self.pg7.sw_if_index)
+        self.vapi.nat44_add_del_interface_addr(self.pg7.sw_if_index)
         self.vapi.nat44_add_del_identity_mapping(
             sw_if_index=self.pg7.sw_if_index,
             port=port,
@@ -2545,10 +2697,10 @@ class TestNAT44(MethodHolder):
                          identity_mappings[0].sw_if_index)
 
     def test_ipfix_nat44_sess(self):
-        """ IPFIX logging NAT44 session created/delted """
+        """ IPFIX logging NAT44 session created/deleted """
         self.ipfix_domain_id = 10
         self.ipfix_src_port = 20202
-        colector_port = 30303
+        collector_port = 30303
         bind_layers(UDP, IPFIX, dport=30303)
         self.nat44_add_address(self.nat_addr)
         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
@@ -2558,9 +2710,9 @@ class TestNAT44(MethodHolder):
                                      src_address=self.pg3.local_ip4n,
                                      path_mtu=512,
                                      template_interval=10,
-                                     collector_port=colector_port)
-        self.vapi.nat_ipfix(domain_id=self.ipfix_domain_id,
-                            src_port=self.ipfix_src_port)
+                                     collector_port=collector_port)
+        self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
+                                           src_port=self.ipfix_src_port)
 
         pkts = self.create_stream_in(self.pg0, self.pg1)
         self.pg0.add_stream(pkts)
@@ -2578,7 +2730,7 @@ class TestNAT44(MethodHolder):
             self.assertEqual(p[IP].src, self.pg3.local_ip4)
             self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
             self.assertEqual(p[UDP].sport, self.ipfix_src_port)
-            self.assertEqual(p[UDP].dport, colector_port)
+            self.assertEqual(p[UDP].dport, collector_port)
             self.assertEqual(p[IPFIX].observationDomainID,
                              self.ipfix_domain_id)
             if p.haslayer(Template):
@@ -2598,8 +2750,8 @@ class TestNAT44(MethodHolder):
                                      src_address=self.pg3.local_ip4n,
                                      path_mtu=512,
                                      template_interval=10)
-        self.vapi.nat_ipfix(domain_id=self.ipfix_domain_id,
-                            src_port=self.ipfix_src_port)
+        self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
+                                           src_port=self.ipfix_src_port)
 
         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
@@ -2629,7 +2781,7 @@ class TestNAT44(MethodHolder):
                 data = ipfix.decode_data_set(p.getlayer(Set))
                 self.verify_ipfix_addr_exhausted(data)
 
-    @unittest.skipUnless(running_extended_tests(), "part of extended tests")
+    @unittest.skipUnless(running_extended_tests, "part of extended tests")
     def test_ipfix_max_sessions(self):
         """ IPFIX logging maximum session entries exceeded """
         self.nat44_add_address(self.nat_addr)
@@ -2656,8 +2808,8 @@ class TestNAT44(MethodHolder):
                                      src_address=self.pg3.local_ip4n,
                                      path_mtu=512,
                                      template_interval=10)
-        self.vapi.nat_ipfix(domain_id=self.ipfix_domain_id,
-                            src_port=self.ipfix_src_port)
+        self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
+                                           src_port=self.ipfix_src_port)
 
         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
@@ -2687,6 +2839,32 @@ class TestNAT44(MethodHolder):
                 data = ipfix.decode_data_set(p.getlayer(Set))
                 self.verify_ipfix_max_sessions(data, max_sessions)
 
+    def test_syslog_apmap(self):
+        """ Test syslog address and port mapping creation and deletion """
+        self.vapi.syslog_set_filter(SYSLOG_SEVERITY.INFO)
+        self.vapi.syslog_set_sender(self.pg3.local_ip4n, self.pg3.remote_ip4n)
+        self.nat44_add_address(self.nat_addr)
+        self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
+        self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
+                                                  is_inside=0)
+
+        p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
+             IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
+             TCP(sport=self.tcp_port_in, dport=20))
+        self.pg0.add_stream(p)
+        self.pg_enable_capture(self.pg_interfaces)
+        self.pg_start()
+        capture = self.pg1.get_capture(1)
+        self.tcp_port_out = capture[0][TCP].sport
+        capture = self.pg3.get_capture(1)
+        self.verify_syslog_apmap(capture[0][Raw].load)
+
+        self.pg_enable_capture(self.pg_interfaces)
+        self.pg_start()
+        self.nat44_add_address(self.nat_addr, is_add=0)
+        capture = self.pg3.get_capture(1)
+        self.verify_syslog_apmap(capture[0][Raw].load, False)
+
     def test_pool_addr_fib(self):
         """ NAT44 add pool addresses to FIB """
         static_addr = '10.0.0.10'
@@ -2758,8 +2936,8 @@ class TestNAT44(MethodHolder):
 
         self.pg0.unconfig_ip4()
         self.pg1.unconfig_ip4()
-        self.vapi.ip_table_add_del(vrf_id1, is_add=1)
-        self.vapi.ip_table_add_del(vrf_id2, is_add=1)
+        self.vapi.ip_table_add_del(is_add=1, table_id=vrf_id1)
+        self.vapi.ip_table_add_del(is_add=1, table_id=vrf_id2)
         self.pg0.set_table_ip4(vrf_id1)
         self.pg1.set_table_ip4(vrf_id2)
         self.pg0.config_ip4()
@@ -2800,8 +2978,8 @@ class TestNAT44(MethodHolder):
             self.pg1.config_ip4()
             self.pg0.resolve_arp()
             self.pg1.resolve_arp()
-            self.vapi.ip_table_add_del(vrf_id1, is_add=0)
-            self.vapi.ip_table_add_del(vrf_id2, is_add=0)
+            self.vapi.ip_table_add_del(is_add=0, table_id=vrf_id1)
+            self.vapi.ip_table_add_del(is_add=0, table_id=vrf_id2)
 
     def test_vrf_feature_independent(self):
         """ NAT44 tenant VRF independent address pool mode """
@@ -2835,14 +3013,18 @@ class TestNAT44(MethodHolder):
     def test_dynamic_ipless_interfaces(self):
         """ NAT44 interfaces without configured IP address """
 
-        self.vapi.ip_neighbor_add_del(self.pg7.sw_if_index,
-                                      mactobinary(self.pg7.remote_mac),
-                                      self.pg7.remote_ip4n,
-                                      is_static=1)
-        self.vapi.ip_neighbor_add_del(self.pg8.sw_if_index,
-                                      mactobinary(self.pg8.remote_mac),
-                                      self.pg8.remote_ip4n,
-                                      is_static=1)
+        self.vapi.ip_neighbor_add_del(
+            self.pg7.sw_if_index,
+            self.pg7.remote_mac,
+            self.pg7.remote_ip4,
+            flags=(VppEnum.vl_api_ip_neighbor_flags_t.
+                   IP_API_NEIGHBOR_FLAG_STATIC))
+        self.vapi.ip_neighbor_add_del(
+            self.pg8.sw_if_index,
+            self.pg8.remote_mac,
+            self.pg8.remote_ip4,
+            flags=(VppEnum.vl_api_ip_neighbor_flags_t.
+                   IP_API_NEIGHBOR_FLAG_STATIC))
 
         self.vapi.ip_add_del_route(dst_address=self.pg7.remote_ip4n,
                                    dst_address_length=32,
@@ -2877,14 +3059,18 @@ class TestNAT44(MethodHolder):
     def test_static_ipless_interfaces(self):
         """ NAT44 interfaces without configured IP address - 1:1 NAT """
 
-        self.vapi.ip_neighbor_add_del(self.pg7.sw_if_index,
-                                      mactobinary(self.pg7.remote_mac),
-                                      self.pg7.remote_ip4n,
-                                      is_static=1)
-        self.vapi.ip_neighbor_add_del(self.pg8.sw_if_index,
-                                      mactobinary(self.pg8.remote_mac),
-                                      self.pg8.remote_ip4n,
-                                      is_static=1)
+        self.vapi.ip_neighbor_add_del(
+            self.pg7.sw_if_index,
+            self.pg7.remote_mac,
+            self.pg7.remote_ip4,
+            flags=(VppEnum.vl_api_ip_neighbor_flags_t.
+                   IP_API_NEIGHBOR_FLAG_STATIC))
+        self.vapi.ip_neighbor_add_del(
+            self.pg8.sw_if_index,
+            self.pg8.remote_mac,
+            self.pg8.remote_ip4,
+            flags=(VppEnum.vl_api_ip_neighbor_flags_t.
+                   IP_API_NEIGHBOR_FLAG_STATIC))
 
         self.vapi.ip_add_del_route(dst_address=self.pg7.remote_ip4n,
                                    dst_address_length=32,
@@ -2923,14 +3109,18 @@ class TestNAT44(MethodHolder):
         self.udp_port_out = 30607
         self.icmp_id_out = 30608
 
-        self.vapi.ip_neighbor_add_del(self.pg7.sw_if_index,
-                                      mactobinary(self.pg7.remote_mac),
-                                      self.pg7.remote_ip4n,
-                                      is_static=1)
-        self.vapi.ip_neighbor_add_del(self.pg8.sw_if_index,
-                                      mactobinary(self.pg8.remote_mac),
-                                      self.pg8.remote_ip4n,
-                                      is_static=1)
+        self.vapi.ip_neighbor_add_del(
+            self.pg7.sw_if_index,
+            self.pg7.remote_mac,
+            self.pg7.remote_ip4,
+            flags=(VppEnum.vl_api_ip_neighbor_flags_t.
+                   IP_API_NEIGHBOR_FLAG_STATIC))
+        self.vapi.ip_neighbor_add_del(
+            self.pg8.sw_if_index,
+            self.pg8.remote_mac,
+            self.pg8.remote_ip4,
+            flags=(VppEnum.vl_api_ip_neighbor_flags_t.
+                   IP_API_NEIGHBOR_FLAG_STATIC))
 
         self.vapi.ip_add_del_route(dst_address=self.pg7.remote_ip4n,
                                    dst_address_length=32,
@@ -2993,7 +3183,7 @@ class TestNAT44(MethodHolder):
         try:
             self.assertEqual(packet[IP].src, nat_ip)
             self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
-            self.assertTrue(packet.haslayer(GRE))
+            self.assertEqual(packet.haslayer(GRE), 1)
             self.assert_packet_checksums_valid(packet)
         except:
             self.logger.error(ppp("Unexpected or invalid packet:", packet))
@@ -3013,7 +3203,7 @@ class TestNAT44(MethodHolder):
         try:
             self.assertEqual(packet[IP].src, self.pg1.remote_ip4)
             self.assertEqual(packet[IP].dst, self.pg0.remote_ip4)
-            self.assertTrue(packet.haslayer(GRE))
+            self.assertEqual(packet.haslayer(GRE), 1)
             self.assert_packet_checksums_valid(packet)
         except:
             self.logger.error(ppp("Unexpected or invalid packet:", packet))
@@ -3048,7 +3238,7 @@ class TestNAT44(MethodHolder):
         try:
             self.assertEqual(packet[IP].src, host_nat_ip)
             self.assertEqual(packet[IP].dst, server.ip4)
-            self.assertTrue(packet.haslayer(GRE))
+            self.assertEqual(packet.haslayer(GRE), 1)
             self.assert_packet_checksums_valid(packet)
         except:
             self.logger.error(ppp("Unexpected or invalid packet:", packet))
@@ -3068,7 +3258,7 @@ class TestNAT44(MethodHolder):
         try:
             self.assertEqual(packet[IP].src, server_nat_ip)
             self.assertEqual(packet[IP].dst, host.ip4)
-            self.assertTrue(packet.haslayer(GRE))
+            self.assertEqual(packet.haslayer(GRE), 1)
             self.assert_packet_checksums_valid(packet)
         except:
             self.logger.error(ppp("Unexpected or invalid packet:", packet))
@@ -3277,6 +3467,11 @@ class TestNAT44(MethodHolder):
             self.logger.error(ppp("Unexpected or invalid packet:", p))
             raise
 
+        err = self.statistics.get_counter('/err/nat44-classify/next in2out')
+        self.assertEqual(err, 1)
+        err = self.statistics.get_counter('/err/nat44-classify/next out2in')
+        self.assertEqual(err, 1)
+
     def test_del_session(self):
         """ Delete NAT44 session """
         self.nat44_add_address(self.nat_addr)
@@ -3341,13 +3536,13 @@ class TestNAT44(MethodHolder):
 
     def test_frag_forwarding(self):
         """ NAT44 forwarding fragment test """
-        self.vapi.nat44_add_interface_addr(self.pg1.sw_if_index)
+        self.vapi.nat44_add_del_interface_addr(self.pg1.sw_if_index)
         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
                                                   is_inside=0)
         self.vapi.nat44_forwarding_enable_disable(1)
 
-        data = "A" * 16 + "B" * 16 + "C" * 3
+        data = b"A" * 16 + b"B" * 16 + b"C" * 3
         pkts = self.create_stream_frag(self.pg1,
                                        self.pg0.remote_ip4,
                                        4789,
@@ -3472,10 +3667,10 @@ class TestNAT44(MethodHolder):
                                      src_address=self.pg3.local_ip4n,
                                      path_mtu=512,
                                      template_interval=10)
-        self.vapi.nat_ipfix(domain_id=self.ipfix_domain_id,
-                            src_port=self.ipfix_src_port)
+        self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
+                                           src_port=self.ipfix_src_port)
 
-        data = "A" * 4 + "B" * 16 + "C" * 3
+        data = b"A" * 4 + b"B" * 16 + b"C" * 3
         self.tcp_port_in = random.randint(1025, 65535)
         pkts = self.create_stream_frag(self.pg0,
                                        self.pg1.remote_ip4,
@@ -3516,8 +3711,8 @@ class TestNAT44(MethodHolder):
 
         self.pg1.unconfig_ip4()
         self.pg2.unconfig_ip4()
-        self.vapi.ip_table_add_del(vrf_id1, is_add=1)
-        self.vapi.ip_table_add_del(vrf_id2, is_add=1)
+        self.vapi.ip_table_add_del(is_add=1, table_id=vrf_id1)
+        self.vapi.ip_table_add_del(is_add=1, table_id=vrf_id2)
         self.pg1.set_table_ip4(vrf_id1)
         self.pg2.set_table_ip4(vrf_id2)
         self.pg1.config_ip4()
@@ -3577,7 +3772,7 @@ class TestNAT44(MethodHolder):
             self.pg1.resolve_arp()
             self.pg2.resolve_arp()
 
-    @unittest.skipUnless(running_extended_tests(), "part of extended tests")
+    @unittest.skipUnless(running_extended_tests, "part of extended tests")
     def test_session_timeout(self):
         """ NAT44 session timeouts """
         self.nat44_add_address(self.nat_addr)
@@ -3655,6 +3850,311 @@ class TestNAT44(MethodHolder):
         # Negotiated MSS value smaller than configured - unchanged
         self.verify_mss_value(capture[0], 1400)
 
+    @unittest.skipUnless(running_extended_tests, "part of extended tests")
+    def test_ha_send(self):
+        """ Send HA session synchronization events (active) """
+        self.nat44_add_address(self.nat_addr)
+        self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
+        self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
+                                                  is_inside=0)
+        self.vapi.nat_ha_set_listener(self.pg3.local_ip4, port=12345)
+        self.vapi.nat_ha_set_failover(self.pg3.remote_ip4, port=12346)
+        bind_layers(UDP, HANATStateSync, sport=12345)
+
+        # create sessions
+        pkts = self.create_stream_in(self.pg0, self.pg1)
+        self.pg0.add_stream(pkts)
+        self.pg_enable_capture(self.pg_interfaces)
+        self.pg_start()
+        capture = self.pg1.get_capture(len(pkts))
+        self.verify_capture_out(capture)
+        # active send HA events
+        self.vapi.nat_ha_flush()
+        stats = self.statistics.get_counter('/nat44/ha/add-event-send')
+        self.assertEqual(stats[0][0], 3)
+        capture = self.pg3.get_capture(1)
+        p = capture[0]
+        self.assert_packet_checksums_valid(p)
+        try:
+            ip = p[IP]
+            udp = p[UDP]
+            hanat = p[HANATStateSync]
+        except IndexError:
+            self.logger.error(ppp("Invalid packet:", p))
+            raise
+        else:
+            self.assertEqual(ip.src, self.pg3.local_ip4)
+            self.assertEqual(ip.dst, self.pg3.remote_ip4)
+            self.assertEqual(udp.sport, 12345)
+            self.assertEqual(udp.dport, 12346)
+            self.assertEqual(hanat.version, 1)
+            self.assertEqual(hanat.thread_index, 0)
+            self.assertEqual(hanat.count, 3)
+            seq = hanat.sequence_number
+            for event in hanat.events:
+                self.assertEqual(event.event_type, 1)
+                self.assertEqual(event.in_addr, self.pg0.remote_ip4)
+                self.assertEqual(event.out_addr, self.nat_addr)
+                self.assertEqual(event.fib_index, 0)
+
+        # ACK received events
+        ack = (Ether(dst=self.pg3.local_mac, src=self.pg3.remote_mac) /
+               IP(src=self.pg3.remote_ip4, dst=self.pg3.local_ip4) /
+               UDP(sport=12346, dport=12345) /
+               HANATStateSync(sequence_number=seq, flags='ACK'))
+        self.pg3.add_stream(ack)
+        self.pg_start()
+        stats = self.statistics.get_counter('/nat44/ha/ack-recv')
+        self.assertEqual(stats[0][0], 1)
+
+        # delete one session
+        self.pg_enable_capture(self.pg_interfaces)
+        self.vapi.nat44_del_session(self.pg0.remote_ip4n, self.tcp_port_in,
+                                    IP_PROTOS.tcp)
+        self.vapi.nat_ha_flush()
+        stats = self.statistics.get_counter('/nat44/ha/del-event-send')
+        self.assertEqual(stats[0][0], 1)
+        capture = self.pg3.get_capture(1)
+        p = capture[0]
+        try:
+            hanat = p[HANATStateSync]
+        except IndexError:
+            self.logger.error(ppp("Invalid packet:", p))
+            raise
+        else:
+            self.assertGreater(hanat.sequence_number, seq)
+
+        # do not send ACK, active retry send HA event again
+        self.pg_enable_capture(self.pg_interfaces)
+        sleep(12)
+        stats = self.statistics.get_counter('/nat44/ha/retry-count')
+        self.assertEqual(stats[0][0], 3)
+        stats = self.statistics.get_counter('/nat44/ha/missed-count')
+        self.assertEqual(stats[0][0], 1)
+        capture = self.pg3.get_capture(3)
+        for packet in capture:
+            self.assertEqual(packet, p)
+
+        # session counters refresh
+        pkts = self.create_stream_out(self.pg1)
+        self.pg1.add_stream(pkts)
+        self.pg_enable_capture(self.pg_interfaces)
+        self.pg_start()
+        self.pg0.get_capture(2)
+        self.vapi.nat_ha_flush()
+        stats = self.statistics.get_counter('/nat44/ha/refresh-event-send')
+        self.assertEqual(stats[0][0], 2)
+        capture = self.pg3.get_capture(1)
+        p = capture[0]
+        self.assert_packet_checksums_valid(p)
+        try:
+            ip = p[IP]
+            udp = p[UDP]
+            hanat = p[HANATStateSync]
+        except IndexError:
+            self.logger.error(ppp("Invalid packet:", p))
+            raise
+        else:
+            self.assertEqual(ip.src, self.pg3.local_ip4)
+            self.assertEqual(ip.dst, self.pg3.remote_ip4)
+            self.assertEqual(udp.sport, 12345)
+            self.assertEqual(udp.dport, 12346)
+            self.assertEqual(hanat.version, 1)
+            self.assertEqual(hanat.count, 2)
+            seq = hanat.sequence_number
+            for event in hanat.events:
+                self.assertEqual(event.event_type, 3)
+                self.assertEqual(event.out_addr, self.nat_addr)
+                self.assertEqual(event.fib_index, 0)
+                self.assertEqual(event.total_pkts, 2)
+                self.assertGreater(event.total_bytes, 0)
+
+        ack = (Ether(dst=self.pg3.local_mac, src=self.pg3.remote_mac) /
+               IP(src=self.pg3.remote_ip4, dst=self.pg3.local_ip4) /
+               UDP(sport=12346, dport=12345) /
+               HANATStateSync(sequence_number=seq, flags='ACK'))
+        self.pg3.add_stream(ack)
+        self.pg_start()
+        stats = self.statistics.get_counter('/nat44/ha/ack-recv')
+        self.assertEqual(stats[0][0], 2)
+
+    def test_ha_recv(self):
+        """ Receive HA session synchronization events (passive) """
+        self.nat44_add_address(self.nat_addr)
+        self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
+        self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
+                                                  is_inside=0)
+        self.vapi.nat_ha_set_listener(self.pg3.local_ip4, port=12345)
+        bind_layers(UDP, HANATStateSync, sport=12345)
+
+        self.tcp_port_out = random.randint(1025, 65535)
+        self.udp_port_out = random.randint(1025, 65535)
+
+        # send HA session add events to failover/passive
+        p = (Ether(dst=self.pg3.local_mac, src=self.pg3.remote_mac) /
+             IP(src=self.pg3.remote_ip4, dst=self.pg3.local_ip4) /
+             UDP(sport=12346, dport=12345) /
+             HANATStateSync(sequence_number=1, events=[
+                 Event(event_type='add', protocol='tcp',
+                       in_addr=self.pg0.remote_ip4, out_addr=self.nat_addr,
+                       in_port=self.tcp_port_in, out_port=self.tcp_port_out,
+                       eh_addr=self.pg1.remote_ip4,
+                       ehn_addr=self.pg1.remote_ip4,
+                       eh_port=self.tcp_external_port,
+                       ehn_port=self.tcp_external_port, fib_index=0),
+                 Event(event_type='add', protocol='udp',
+                       in_addr=self.pg0.remote_ip4, out_addr=self.nat_addr,
+                       in_port=self.udp_port_in, out_port=self.udp_port_out,
+                       eh_addr=self.pg1.remote_ip4,
+                       ehn_addr=self.pg1.remote_ip4,
+                       eh_port=self.udp_external_port,
+                       ehn_port=self.udp_external_port, fib_index=0)]))
+
+        self.pg3.add_stream(p)
+        self.pg_enable_capture(self.pg_interfaces)
+        self.pg_start()
+        # receive ACK
+        capture = self.pg3.get_capture(1)
+        p = capture[0]
+        try:
+            hanat = p[HANATStateSync]
+        except IndexError:
+            self.logger.error(ppp("Invalid packet:", p))
+            raise
+        else:
+            self.assertEqual(hanat.sequence_number, 1)
+            self.assertEqual(hanat.flags, 'ACK')
+            self.assertEqual(hanat.version, 1)
+            self.assertEqual(hanat.thread_index, 0)
+        stats = self.statistics.get_counter('/nat44/ha/ack-send')
+        self.assertEqual(stats[0][0], 1)
+        stats = self.statistics.get_counter('/nat44/ha/add-event-recv')
+        self.assertEqual(stats[0][0], 2)
+        users = self.statistics.get_counter('/nat44/total-users')
+        self.assertEqual(users[0][0], 1)
+        sessions = self.statistics.get_counter('/nat44/total-sessions')
+        self.assertEqual(sessions[0][0], 2)
+        users = self.vapi.nat44_user_dump()
+        self.assertEqual(len(users), 1)
+        self.assertEqual(users[0].ip_address, self.pg0.remote_ip4n)
+        # there should be 2 sessions created by HA
+        sessions = self.vapi.nat44_user_session_dump(users[0].ip_address,
+                                                     users[0].vrf_id)
+        self.assertEqual(len(sessions), 2)
+        for session in sessions:
+            self.assertEqual(session.inside_ip_address, self.pg0.remote_ip4n)
+            self.assertEqual(session.outside_ip_address, self.nat_addr_n)
+            self.assertIn(session.inside_port,
+                          [self.tcp_port_in, self.udp_port_in])
+            self.assertIn(session.outside_port,
+                          [self.tcp_port_out, self.udp_port_out])
+            self.assertIn(session.protocol, [IP_PROTOS.tcp, IP_PROTOS.udp])
+
+        # send HA session delete event to failover/passive
+        p = (Ether(dst=self.pg3.local_mac, src=self.pg3.remote_mac) /
+             IP(src=self.pg3.remote_ip4, dst=self.pg3.local_ip4) /
+             UDP(sport=12346, dport=12345) /
+             HANATStateSync(sequence_number=2, events=[
+                 Event(event_type='del', protocol='udp',
+                       in_addr=self.pg0.remote_ip4, out_addr=self.nat_addr,
+                       in_port=self.udp_port_in, out_port=self.udp_port_out,
+                       eh_addr=self.pg1.remote_ip4,
+                       ehn_addr=self.pg1.remote_ip4,
+                       eh_port=self.udp_external_port,
+                       ehn_port=self.udp_external_port, fib_index=0)]))
+
+        self.pg3.add_stream(p)
+        self.pg_enable_capture(self.pg_interfaces)
+        self.pg_start()
+        # receive ACK
+        capture = self.pg3.get_capture(1)
+        p = capture[0]
+        try:
+            hanat = p[HANATStateSync]
+        except IndexError:
+            self.logger.error(ppp("Invalid packet:", p))
+            raise
+        else:
+            self.assertEqual(hanat.sequence_number, 2)
+            self.assertEqual(hanat.flags, 'ACK')
+            self.assertEqual(hanat.version, 1)
+        users = self.vapi.nat44_user_dump()
+        self.assertEqual(len(users), 1)
+        self.assertEqual(users[0].ip_address, self.pg0.remote_ip4n)
+        # now we should have only 1 session, 1 deleted by HA
+        sessions = self.vapi.nat44_user_session_dump(users[0].ip_address,
+                                                     users[0].vrf_id)
+        self.assertEqual(len(sessions), 1)
+        stats = self.statistics.get_counter('/nat44/ha/del-event-recv')
+        self.assertEqual(stats[0][0], 1)
+
+        stats = self.statistics.get_counter('/err/nat-ha/pkts-processed')
+        self.assertEqual(stats, 2)
+
+        # send HA session refresh event to failover/passive
+        p = (Ether(dst=self.pg3.local_mac, src=self.pg3.remote_mac) /
+             IP(src=self.pg3.remote_ip4, dst=self.pg3.local_ip4) /
+             UDP(sport=12346, dport=12345) /
+             HANATStateSync(sequence_number=3, events=[
+                 Event(event_type='refresh', protocol='tcp',
+                       in_addr=self.pg0.remote_ip4, out_addr=self.nat_addr,
+                       in_port=self.tcp_port_in, out_port=self.tcp_port_out,
+                       eh_addr=self.pg1.remote_ip4,
+                       ehn_addr=self.pg1.remote_ip4,
+                       eh_port=self.tcp_external_port,
+                       ehn_port=self.tcp_external_port, fib_index=0,
+                       total_bytes=1024, total_pkts=2)]))
+        self.pg3.add_stream(p)
+        self.pg_enable_capture(self.pg_interfaces)
+        self.pg_start()
+        # receive ACK
+        capture = self.pg3.get_capture(1)
+        p = capture[0]
+        try:
+            hanat = p[HANATStateSync]
+        except IndexError:
+            self.logger.error(ppp("Invalid packet:", p))
+            raise
+        else:
+            self.assertEqual(hanat.sequence_number, 3)
+            self.assertEqual(hanat.flags, 'ACK')
+            self.assertEqual(hanat.version, 1)
+        users = self.vapi.nat44_user_dump()
+        self.assertEqual(len(users), 1)
+        self.assertEqual(users[0].ip_address, self.pg0.remote_ip4n)
+        sessions = self.vapi.nat44_user_session_dump(users[0].ip_address,
+                                                     users[0].vrf_id)
+        self.assertEqual(len(sessions), 1)
+        session = sessions[0]
+        self.assertEqual(session.total_bytes, 1024)
+        self.assertEqual(session.total_pkts, 2)
+        stats = self.statistics.get_counter('/nat44/ha/refresh-event-recv')
+        self.assertEqual(stats[0][0], 1)
+
+        stats = self.statistics.get_counter('/err/nat-ha/pkts-processed')
+        self.assertEqual(stats, 3)
+
+        # send packet to test session created by HA
+        p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
+             IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
+             TCP(sport=self.tcp_external_port, dport=self.tcp_port_out))
+        self.pg1.add_stream(p)
+        self.pg_enable_capture(self.pg_interfaces)
+        self.pg_start()
+        capture = self.pg0.get_capture(1)
+        p = capture[0]
+        try:
+            ip = p[IP]
+            tcp = p[TCP]
+        except IndexError:
+            self.logger.error(ppp("Invalid packet:", p))
+            raise
+        else:
+            self.assertEqual(ip.src, self.pg1.remote_ip4)
+            self.assertEqual(ip.dst, self.pg0.remote_ip4)
+            self.assertEqual(tcp.sport, self.tcp_external_port)
+            self.assertEqual(tcp.dport, self.tcp_port_in)
+
     def tearDown(self):
         super(TestNAT44, self).tearDown()
         if not self.vpp_dead:
@@ -3668,6 +4168,7 @@ class TestNAT44(MethodHolder):
             self.logger.info(self.vapi.cli("show nat timeouts"))
             self.logger.info(
                 self.vapi.cli("show nat addr-port-assignment-alg"))
+            self.logger.info(self.vapi.cli("show nat ha"))
             self.clear_nat44()
             self.vapi.cli("clear logging")
 
@@ -3713,16 +4214,16 @@ class TestNAT44EndpointDependent(MethodHolder):
             cls.pg4.generate_remote_hosts(2)
             cls.pg4.config_ip4()
             ip_addr_n = socket.inet_pton(socket.AF_INET, "10.0.0.1")
-            cls.vapi.sw_interface_add_del_address(cls.pg4.sw_if_index,
-                                                  ip_addr_n,
-                                                  24)
+            cls.vapi.sw_interface_add_del_address(
+                sw_if_index=cls.pg4.sw_if_index, address=ip_addr_n,
+                address_length=24)
             cls.pg4.admin_up()
             cls.pg4.resolve_arp()
             cls.pg4._remote_hosts[1]._ip4 = cls.pg4._remote_hosts[0]._ip4
             cls.pg4.resolve_arp()
 
             zero_ip4n = socket.inet_pton(socket.AF_INET, "0.0.0.0")
-            cls.vapi.ip_table_add_del(1, is_add=1)
+            cls.vapi.ip_table_add_del(is_add=1, table_id=1)
 
             cls.pg5._local_ip4 = "10.1.1.1"
             cls.pg5._local_ip4n = socket.inet_pton(socket.AF_INET,
@@ -3735,9 +4236,9 @@ class TestNAT44EndpointDependent(MethodHolder):
             cls.pg5.admin_up()
             cls.vapi.ip_add_del_route(dst_address=cls.pg5.remote_ip4n,
                                       dst_address_length=32,
-                                      table_id=1,
+                                      next_hop_address=zero_ip4n,
                                       next_hop_sw_if_index=cls.pg5.sw_if_index,
-                                      next_hop_address=zero_ip4n)
+                                      table_id=1)
 
             cls.pg6._local_ip4 = "10.1.2.1"
             cls.pg6._local_ip4n = socket.inet_pton(socket.AF_INET,
@@ -3750,25 +4251,23 @@ class TestNAT44EndpointDependent(MethodHolder):
             cls.pg6.admin_up()
             cls.vapi.ip_add_del_route(dst_address=cls.pg6.remote_ip4n,
                                       dst_address_length=32,
-                                      table_id=1,
+                                      next_hop_address=zero_ip4n,
                                       next_hop_sw_if_index=cls.pg6.sw_if_index,
-                                      next_hop_address=zero_ip4n)
+                                      table_id=1)
 
             cls.vapi.ip_add_del_route(dst_address=cls.pg6.remote_ip4n,
                                       dst_address_length=16,
-                                      next_hop_address=zero_ip4n,
-                                      table_id=0,
+                                      next_hop_address=zero_ip4n, table_id=0,
                                       next_hop_table_id=1)
             cls.vapi.ip_add_del_route(dst_address=zero_ip4n,
                                       dst_address_length=0,
-                                      next_hop_address=zero_ip4n,
-                                      table_id=1,
+                                      next_hop_address=zero_ip4n, table_id=1,
                                       next_hop_table_id=0)
             cls.vapi.ip_add_del_route(dst_address=zero_ip4n,
                                       dst_address_length=0,
-                                      table_id=0,
+                                      next_hop_address=cls.pg1.local_ip4n,
                                       next_hop_sw_if_index=cls.pg1.sw_if_index,
-                                      next_hop_address=cls.pg1.local_ip4n)
+                                      table_id=0)
 
             cls.pg5.resolve_arp()
             cls.pg6.resolve_arp()
@@ -3929,6 +4428,15 @@ class TestNAT44EndpointDependent(MethodHolder):
         self.assertEqual(1, nat_config.endpoint_dependent)
 
         # in2out
+        tcpn = self.statistics.get_counter(
+            '/err/nat44-ed-in2out-slowpath/TCP packets')
+        udpn = self.statistics.get_counter(
+            '/err/nat44-ed-in2out-slowpath/UDP packets')
+        icmpn = self.statistics.get_counter(
+            '/err/nat44-ed-in2out-slowpath/ICMP packets')
+        totaln = self.statistics.get_counter(
+            '/err/nat44-ed-in2out-slowpath/good in2out packets processed')
+
         pkts = self.create_stream_in(self.pg0, self.pg1)
         self.pg0.add_stream(pkts)
         self.pg_enable_capture(self.pg_interfaces)
@@ -3936,7 +4444,27 @@ class TestNAT44EndpointDependent(MethodHolder):
         capture = self.pg1.get_capture(len(pkts))
         self.verify_capture_out(capture)
 
+        err = self.statistics.get_counter(
+            '/err/nat44-ed-in2out-slowpath/TCP packets')
+        self.assertEqual(err - tcpn, 1)
+        err = self.statistics.get_counter(
+            '/err/nat44-ed-in2out-slowpath/UDP packets')
+        self.assertEqual(err - udpn, 1)
+        err = self.statistics.get_counter(
+            '/err/nat44-ed-in2out-slowpath/ICMP packets')
+        self.assertEqual(err - icmpn, 1)
+        err = self.statistics.get_counter(
+            '/err/nat44-ed-in2out-slowpath/good in2out packets processed')
+        self.assertEqual(err - totaln, 3)
+
         # out2in
+        tcpn = self.statistics.get_counter('/err/nat44-ed-out2in/TCP packets')
+        udpn = self.statistics.get_counter('/err/nat44-ed-out2in/UDP packets')
+        icmpn = self.statistics.get_counter(
+            '/err/nat44-ed-out2in-slowpath/ICMP packets')
+        totaln = self.statistics.get_counter(
+            '/err/nat44-ed-out2in/good out2in packets processed')
+
         pkts = self.create_stream_out(self.pg1)
         self.pg1.add_stream(pkts)
         self.pg_enable_capture(self.pg_interfaces)
@@ -3944,6 +4472,22 @@ class TestNAT44EndpointDependent(MethodHolder):
         capture = self.pg0.get_capture(len(pkts))
         self.verify_capture_in(capture, self.pg0)
 
+        err = self.statistics.get_counter('/err/nat44-ed-out2in/TCP packets')
+        self.assertEqual(err - tcpn, 1)
+        err = self.statistics.get_counter('/err/nat44-ed-out2in/UDP packets')
+        self.assertEqual(err - udpn, 1)
+        err = self.statistics.get_counter(
+            '/err/nat44-ed-out2in-slowpath/ICMP packets')
+        self.assertEqual(err - icmpn, 1)
+        err = self.statistics.get_counter(
+            '/err/nat44-ed-out2in/good out2in packets processed')
+        self.assertEqual(err - totaln, 2)
+
+        users = self.statistics.get_counter('/nat44/total-users')
+        self.assertEqual(users[0][0], 1)
+        sessions = self.statistics.get_counter('/nat44/total-sessions')
+        self.assertEqual(sessions[0][0], 3)
+
     def test_forwarding(self):
         """ NAT44 forwarding test """
 
@@ -4099,7 +4643,7 @@ class TestNAT44EndpointDependent(MethodHolder):
         sessions = self.vapi.nat44_user_session_dump(server.ip4n, 0)
         self.assertEqual(len(sessions), 0)
 
-    @unittest.skipUnless(running_extended_tests(), "part of extended tests")
+    @unittest.skipUnless(running_extended_tests, "part of extended tests")
     def test_static_lb_multi_clients(self):
         """ NAT44 local service load balancing - multiple clients"""
 
@@ -4108,6 +4652,7 @@ class TestNAT44EndpointDependent(MethodHolder):
         local_port = 8080
         server1 = self.pg0.remote_hosts[0]
         server2 = self.pg0.remote_hosts[1]
+        server3 = self.pg0.remote_hosts[2]
 
         locals = [{'addr': server1.ip4n,
                    'port': local_port,
@@ -4146,7 +4691,66 @@ class TestNAT44EndpointDependent(MethodHolder):
                 server1_n += 1
             else:
                 server2_n += 1
-        self.assertTrue(server1_n > server2_n)
+        self.assertGreater(server1_n, server2_n)
+
+        # add new back-end
+        self.vapi.nat44_lb_static_mapping_add_del_local(external_addr_n,
+                                                        external_port,
+                                                        server3.ip4n,
+                                                        local_port,
+                                                        IP_PROTOS.tcp,
+                                                        20)
+        server1_n = 0
+        server2_n = 0
+        server3_n = 0
+        clients = ip4_range(self.pg1.remote_ip4, 60, 110)
+        pkts = []
+        for client in clients:
+            p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
+                 IP(src=client, dst=self.nat_addr) /
+                 TCP(sport=12346, dport=external_port))
+            pkts.append(p)
+        self.assertGreater(len(pkts), 0)
+        self.pg1.add_stream(pkts)
+        self.pg_enable_capture(self.pg_interfaces)
+        self.pg_start()
+        capture = self.pg0.get_capture(len(pkts))
+        for p in capture:
+            if p[IP].dst == server1.ip4:
+                server1_n += 1
+            elif p[IP].dst == server2.ip4:
+                server2_n += 1
+            else:
+                server3_n += 1
+        self.assertGreater(server1_n, 0)
+        self.assertGreater(server2_n, 0)
+        self.assertGreater(server3_n, 0)
+
+        # remove one back-end
+        self.vapi.nat44_lb_static_mapping_add_del_local(external_addr_n,
+                                                        external_port,
+                                                        server2.ip4n,
+                                                        local_port,
+                                                        IP_PROTOS.tcp,
+                                                        10,
+                                                        is_add=0)
+        server1_n = 0
+        server2_n = 0
+        server3_n = 0
+        self.pg1.add_stream(pkts)
+        self.pg_enable_capture(self.pg_interfaces)
+        self.pg_start()
+        capture = self.pg0.get_capture(len(pkts))
+        for p in capture:
+            if p[IP].dst == server1.ip4:
+                server1_n += 1
+            elif p[IP].dst == server2.ip4:
+                server2_n += 1
+            else:
+                server3_n += 1
+        self.assertGreater(server1_n, 0)
+        self.assertEqual(server2_n, 0)
+        self.assertGreater(server3_n, 0)
 
     def test_static_lb_2(self):
         """ NAT44 local service load balancing (asymmetrical rule) """
@@ -4348,7 +4952,7 @@ class TestNAT44EndpointDependent(MethodHolder):
         try:
             self.assertEqual(packet[IP].src, self.nat_addr)
             self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
-            self.assertTrue(packet.haslayer(GRE))
+            self.assertEqual(packet.haslayer(GRE), 1)
             self.assert_packet_checksums_valid(packet)
         except:
             self.logger.error(ppp("Unexpected or invalid packet:", packet))
@@ -4368,7 +4972,7 @@ class TestNAT44EndpointDependent(MethodHolder):
         try:
             self.assertEqual(packet[IP].src, self.pg1.remote_ip4)
             self.assertEqual(packet[IP].dst, self.pg0.remote_ip4)
-            self.assertTrue(packet.haslayer(GRE))
+            self.assertEqual(packet.haslayer(GRE), 1)
             self.assert_packet_checksums_valid(packet)
         except:
             self.logger.error(ppp("Unexpected or invalid packet:", packet))
@@ -4412,7 +5016,7 @@ class TestNAT44EndpointDependent(MethodHolder):
         try:
             self.assertEqual(packet[IP].src, self.nat_addr)
             self.assertEqual(packet[IP].dst, server.ip4)
-            self.assertTrue(packet.haslayer(GRE))
+            self.assertEqual(packet.haslayer(GRE), 1)
             self.assert_packet_checksums_valid(packet)
         except:
             self.logger.error(ppp("Unexpected or invalid packet:", packet))
@@ -4432,7 +5036,7 @@ class TestNAT44EndpointDependent(MethodHolder):
         try:
             self.assertEqual(packet[IP].src, server_nat_ip)
             self.assertEqual(packet[IP].dst, host.ip4)
-            self.assertTrue(packet.haslayer(GRE))
+            self.assertEqual(packet.haslayer(GRE), 1)
             self.assert_packet_checksums_valid(packet)
         except:
             self.logger.error(ppp("Unexpected or invalid packet:", packet))
@@ -4523,7 +5127,7 @@ class TestNAT44EndpointDependent(MethodHolder):
         self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index,
                                                          is_inside=0)
 
-        # session initiaded from service host - translate
+        # session initiated from service host - translate
         pkts = self.create_stream_in(self.pg0, self.pg1)
         self.pg0.add_stream(pkts)
         self.pg_enable_capture(self.pg_interfaces)
@@ -4538,7 +5142,7 @@ class TestNAT44EndpointDependent(MethodHolder):
         capture = self.pg0.get_capture(len(pkts))
         self.verify_capture_in(capture, self.pg0)
 
-        # session initiaded from remote host - do not translate
+        # session initiated from remote host - do not translate
         self.tcp_port_in = 60303
         self.udp_port_in = 60304
         self.icmp_id_in = 60305
@@ -4683,8 +5287,8 @@ class TestNAT44EndpointDependent(MethodHolder):
                 port_in1 = port_in
                 port_in2 = port_in
             else:
-                port_in1 = port_in+1
-                port_in2 = port_in+2
+                port_in1 = port_in + 1
+                port_in2 = port_in + 2
 
         port_out = 80
         eh_port_out = 4567
@@ -4846,7 +5450,8 @@ class TestNAT44EndpointDependent(MethodHolder):
 
     def test_twice_nat_interface_addr(self):
         """ Acquire twice NAT44 addresses from interface """
-        self.vapi.nat44_add_interface_addr(self.pg3.sw_if_index, twice_nat=1)
+        self.vapi.nat44_add_del_interface_addr(self.pg3.sw_if_index,
+                                               twice_nat=1)
 
         # no address in NAT pool
         adresses = self.vapi.nat44_address_dump()
@@ -5362,9 +5967,9 @@ class TestNAT44EndpointDependent(MethodHolder):
                                       local_port, external_port, vrf_id=1,
                                       proto=IP_PROTOS.tcp, out2in_only=1)
         self.nat44_add_static_mapping(
-             self.pg0.remote_ip4, external_sw_if_index=self.pg0.sw_if_index,
-             local_port=local_port, vrf_id=0, external_port=external_port,
-             proto=IP_PROTOS.tcp, out2in_only=1)
+            self.pg0.remote_ip4, external_sw_if_index=self.pg0.sw_if_index,
+            local_port=local_port, vrf_id=0, external_port=external_port,
+            proto=IP_PROTOS.tcp, out2in_only=1)
 
         # from client to service (both VRF1)
         p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
@@ -5632,7 +6237,7 @@ class TestNAT44EndpointDependent(MethodHolder):
             self.logger.error(ppp("Unexpected or invalid packet:", p))
             raise
 
-    @unittest.skipUnless(running_extended_tests(), "part of extended tests")
+    @unittest.skipUnless(running_extended_tests, "part of extended tests")
     def test_session_timeout(self):
         """ NAT44 session timeouts """
         self.nat44_add_address(self.nat_addr)
@@ -5658,7 +6263,7 @@ class TestNAT44EndpointDependent(MethodHolder):
 
         pkts = []
         for i in range(0, max_sessions):
-            src = "10.10.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
+            src = "10.11.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
             p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
                  IP(src=src, dst=self.pg1.remote_ip4) /
                  ICMP(id=1026, type='echo-request'))
@@ -5674,7 +6279,7 @@ class TestNAT44EndpointDependent(MethodHolder):
             nsessions = nsessions + user.nsessions
         self.assertLess(nsessions, 2 * max_sessions)
 
-    @unittest.skipUnless(running_extended_tests(), "part of extended tests")
+    @unittest.skipUnless(running_extended_tests, "part of extended tests")
     def test_session_rst_timeout(self):
         """ NAT44 session RST timeouts """
         self.nat44_add_address(self.nat_addr)
@@ -5683,8 +6288,6 @@ class TestNAT44EndpointDependent(MethodHolder):
                                                   is_inside=0)
         self.vapi.nat_set_timeouts(tcp_transitory=5)
 
-        nat44_config = self.vapi.nat_show_config()
-
         self.initiate_tcp_session(self.pg0, self.pg1)
         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
@@ -5695,18 +6298,6 @@ class TestNAT44EndpointDependent(MethodHolder):
         self.pg_start()
         self.pg1.get_capture(1)
 
-        pkts_num = nat44_config.max_translations_per_user - 1
-        pkts = []
-        for i in range(0, pkts_num):
-            p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
-                 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
-                 UDP(sport=1025 + i, dport=53))
-            pkts.append(p)
-        self.pg0.add_stream(pkts)
-        self.pg_enable_capture(self.pg_interfaces)
-        self.pg_start()
-        self.pg1.get_capture(pkts_num)
-
         sleep(6)
 
         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
@@ -5722,10 +6313,9 @@ class TestNAT44EndpointDependent(MethodHolder):
         users = self.vapi.nat44_user_dump()
         self.assertEqual(len(users), 1)
         self.assertEqual(users[0].ip_address, self.pg0.remote_ip4n)
-        self.assertEqual(users[0].nsessions,
-                         nat44_config.max_translations_per_user)
+        self.assertEqual(users[0].nsessions, 1)
 
-    @unittest.skipUnless(running_extended_tests(), "part of extended tests")
+    @unittest.skipUnless(running_extended_tests, "part of extended tests")
     def test_session_limit_per_user(self):
         """ Maximum sessions per user limit """
         self.nat44_add_address(self.nat_addr)
@@ -5753,8 +6343,8 @@ class TestNAT44EndpointDependent(MethodHolder):
         self.pg_start()
         capture = self.pg1.get_capture(len(pkts))
 
-        self.vapi.nat_ipfix(domain_id=self.ipfix_domain_id,
-                            src_port=self.ipfix_src_port)
+        self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
+                                           src_port=self.ipfix_src_port)
 
         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
@@ -5792,6 +6382,32 @@ class TestNAT44EndpointDependent(MethodHolder):
         self.pg_start()
         self.pg1.get_capture(1)
 
+    def test_syslog_sess(self):
+        """ Test syslog session creation and deletion """
+        self.vapi.syslog_set_filter(SYSLOG_SEVERITY.INFO)
+        self.vapi.syslog_set_sender(self.pg2.local_ip4n, self.pg2.remote_ip4n)
+        self.nat44_add_address(self.nat_addr)
+        self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
+        self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
+                                                  is_inside=0)
+
+        p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
+             IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
+             TCP(sport=self.tcp_port_in, dport=self.tcp_external_port))
+        self.pg0.add_stream(p)
+        self.pg_enable_capture(self.pg_interfaces)
+        self.pg_start()
+        capture = self.pg1.get_capture(1)
+        self.tcp_port_out = capture[0][TCP].sport
+        capture = self.pg2.get_capture(1)
+        self.verify_syslog_sess(capture[0][Raw].load)
+
+        self.pg_enable_capture(self.pg_interfaces)
+        self.pg_start()
+        self.nat44_add_address(self.nat_addr, is_add=0)
+        capture = self.pg2.get_capture(1)
+        self.verify_syslog_sess(capture[0][Raw].load, False)
+
     def tearDown(self):
         super(TestNAT44EndpointDependent, self).tearDown()
         if not self.vpp_dead:
@@ -5840,10 +6456,11 @@ class TestNAT44Out2InDPO(MethodHolder):
             cls.pg1.config_ip6()
             cls.pg1.resolve_ndp()
 
-            cls.vapi.ip_add_del_route(is_ipv6=True, dst_address='\x00'*16,
+            cls.vapi.ip_add_del_route(dst_address=b'\x00' * 16,
                                       dst_address_length=0,
                                       next_hop_address=cls.pg1.remote_ip6n,
-                                      next_hop_sw_if_index=cls.pg1.sw_if_index)
+                                      next_hop_sw_if_index=cls.pg1.sw_if_index,
+                                      is_ipv6=True)
 
         except Exception:
             super(TestNAT44Out2InDPO, cls).tearDownClass()
@@ -5860,8 +6477,7 @@ class TestNAT44Out2InDPO(MethodHolder):
         self.src_ip6_pfx_len = 96
         self.vapi.map_add_domain(self.dst_ip6_pfx_n, self.dst_ip6_pfx_len,
                                  self.src_ip6_pfx_n, self.src_ip6_pfx_len,
-                                 '\x00\x00\x00\x00', 0, is_translation=1,
-                                 is_rfc6052=1)
+                                 '\x00\x00\x00\x00', 0)
 
     @unittest.skip('Temporary disabled')
     def test_464xlat_ce(self):
@@ -6031,7 +6647,7 @@ class TestDeterministicNAT(MethodHolder):
 
         :param capture: Captured packets
         :param nat_ip: Translated IP address (Default use global NAT address)
-        :param same_port: Sorce port number is not translated (Default False)
+        :param same_port: Source port number is not translated (Default False)
         """
         if nat_ip is None:
             nat_ip = self.nat_addr
@@ -6394,7 +7010,7 @@ class TestDeterministicNAT(MethodHolder):
             self.logger.error("TCP session termination failed")
             raise
 
-    @unittest.skipUnless(running_extended_tests(), "part of extended tests")
+    @unittest.skipUnless(running_extended_tests, "part of extended tests")
     def test_session_timeout(self):
         """ Deterministic NAT session timeouts """
         self.vapi.nat_det_add_del_map(self.pg0.remote_ip4n,
@@ -6417,7 +7033,7 @@ class TestDeterministicNAT(MethodHolder):
         dms = self.vapi.nat_det_map_dump()
         self.assertEqual(0, dms[0].ses_num)
 
-    @unittest.skipUnless(running_extended_tests(), "part of extended tests")
+    @unittest.skipUnless(running_extended_tests, "part of extended tests")
     def test_session_limit_per_user(self):
         """ Deterministic NAT maximum sessions per user limit """
         self.vapi.nat_det_add_del_map(self.pg0.remote_ip4n,
@@ -6431,7 +7047,7 @@ class TestDeterministicNAT(MethodHolder):
                                      src_address=self.pg2.local_ip4n,
                                      path_mtu=512,
                                      template_interval=10)
-        self.vapi.nat_ipfix()
+        self.vapi.nat_ipfix_enable_disable()
 
         pkts = []
         for port in range(1025, 2025):
@@ -6491,7 +7107,7 @@ class TestDeterministicNAT(MethodHolder):
         """
         Clear deterministic NAT configuration.
         """
-        self.vapi.nat_ipfix(enable=0)
+        self.vapi.nat_ipfix_enable_disable(enable=0)
         self.vapi.nat_set_timeouts()
         deterministic_mappings = self.vapi.nat_det_map_dump()
         for dsm in deterministic_mappings:
@@ -6539,6 +7155,7 @@ class TestNAT64(MethodHolder):
             cls.udp_port_out = 6304
             cls.icmp_id_in = 6305
             cls.icmp_id_out = 6305
+            cls.tcp_external_port = 80
             cls.nat_addr = '10.0.0.3'
             cls.nat_addr_n = socket.inet_pton(socket.AF_INET, cls.nat_addr)
             cls.vrf1_id = 10
@@ -6553,7 +7170,8 @@ class TestNAT64(MethodHolder):
             cls.ip6_interfaces.append(cls.pg_interfaces[2])
             cls.ip4_interfaces = list(cls.pg_interfaces[1:2])
 
-            cls.vapi.ip_table_add_del(cls.vrf1_id, is_add=1, is_ipv6=1)
+            cls.vapi.ip_table_add_del(is_ipv6=1, is_add=1,
+                                      table_id=cls.vrf1_id)
 
             cls.pg_interfaces[2].set_table_ip6(cls.vrf1_id)
 
@@ -6601,7 +7219,7 @@ class TestNAT64(MethodHolder):
         packet = capture[0]
         try:
             self.assertEqual(packet[IPv6].src, self.pg5.local_ip6)
-            self.assertTrue(packet.haslayer(ICMPv6ND_NS))
+            self.assertEqual(packet.haslayer(ICMPv6ND_NS), 1)
             tgt = packet[ICMPv6ND_NS].tgt
         except:
             self.logger.error(ppp("Unexpected or invalid packet:", packet))
@@ -6629,7 +7247,7 @@ class TestNAT64(MethodHolder):
         try:
             self.assertEqual(packet[IPv6].src, self.pg5.local_ip6)
             self.assertEqual(packet[IPv6].dst, self.pg5.remote_ip6)
-            self.assertTrue(packet.haslayer(ICMPv6EchoReply))
+            self.assertEqual(packet.haslayer(ICMPv6EchoReply), 1)
         except:
             self.logger.error(ppp("Unexpected or invalid packet:", packet))
             raise
@@ -6669,9 +7287,9 @@ class TestNAT64(MethodHolder):
         self.assertTrue(pg1_found)
 
         features = self.vapi.cli("show interface features pg0")
-        self.assertNotEqual(features.find('nat64-in2out'), -1)
+        self.assertIn('nat64-in2out', features)
         features = self.vapi.cli("show interface features pg1")
-        self.assertNotEqual(features.find('nat64-out2in'), -1)
+        self.assertIn('nat64-out2in', features)
 
         self.vapi.nat64_add_del_interface(self.pg0.sw_if_index, is_add=0)
         self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_add=0)
@@ -6703,6 +7321,8 @@ class TestNAT64(MethodHolder):
                 self.assertEqual(bibe.i_port, in_port)
                 self.assertEqual(bibe.o_port, out_port)
         self.assertEqual(static_bib_num, 1)
+        bibs = self.statistics.get_counter('/nat64/total-bibs')
+        self.assertEqual(bibs[0][0], 1)
 
         self.vapi.nat64_add_del_static_bib(in_addr,
                                            out_addr,
@@ -6716,6 +7336,8 @@ class TestNAT64(MethodHolder):
             if bibe.is_static:
                 static_bib_num += 1
         self.assertEqual(static_bib_num, 0)
+        bibs = self.statistics.get_counter('/nat64/total-bibs')
+        self.assertEqual(bibs[0][0], 0)
 
     def test_set_timeouts(self):
         """ Set NAT64 timeouts """
@@ -6749,6 +7371,12 @@ class TestNAT64(MethodHolder):
         self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
 
         # in2out
+        tcpn = self.statistics.get_counter('/err/nat64-in2out/TCP packets')
+        udpn = self.statistics.get_counter('/err/nat64-in2out/UDP packets')
+        icmpn = self.statistics.get_counter('/err/nat64-in2out/ICMP packets')
+        totaln = self.statistics.get_counter(
+            '/err/nat64-in2out/good in2out packets processed')
+
         pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
         self.pg0.add_stream(pkts)
         self.pg_enable_capture(self.pg_interfaces)
@@ -6757,7 +7385,23 @@ class TestNAT64(MethodHolder):
         self.verify_capture_out(capture, nat_ip=self.nat_addr,
                                 dst_ip=self.pg1.remote_ip4)
 
+        err = self.statistics.get_counter('/err/nat64-in2out/TCP packets')
+        self.assertEqual(err - tcpn, 1)
+        err = self.statistics.get_counter('/err/nat64-in2out/UDP packets')
+        self.assertEqual(err - udpn, 1)
+        err = self.statistics.get_counter('/err/nat64-in2out/ICMP packets')
+        self.assertEqual(err - icmpn, 1)
+        err = self.statistics.get_counter(
+            '/err/nat64-in2out/good in2out packets processed')
+        self.assertEqual(err - totaln, 3)
+
         # out2in
+        tcpn = self.statistics.get_counter('/err/nat64-out2in/TCP packets')
+        udpn = self.statistics.get_counter('/err/nat64-out2in/UDP packets')
+        icmpn = self.statistics.get_counter('/err/nat64-out2in/ICMP packets')
+        totaln = self.statistics.get_counter(
+            '/err/nat64-out2in/good out2in packets processed')
+
         pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
         self.pg1.add_stream(pkts)
         self.pg_enable_capture(self.pg_interfaces)
@@ -6766,6 +7410,21 @@ class TestNAT64(MethodHolder):
         ip = IPv6(src=''.join(['64:ff9b::', self.pg1.remote_ip4]))
         self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg0.remote_ip6)
 
+        err = self.statistics.get_counter('/err/nat64-out2in/TCP packets')
+        self.assertEqual(err - tcpn, 1)
+        err = self.statistics.get_counter('/err/nat64-out2in/UDP packets')
+        self.assertEqual(err - udpn, 1)
+        err = self.statistics.get_counter('/err/nat64-out2in/ICMP packets')
+        self.assertEqual(err - icmpn, 1)
+        err = self.statistics.get_counter(
+            '/err/nat64-out2in/good out2in packets processed')
+        self.assertEqual(err - totaln, 3)
+
+        bibs = self.statistics.get_counter('/nat64/total-bibs')
+        self.assertEqual(bibs[0][0], 3)
+        sessions = self.statistics.get_counter('/nat64/total-sessions')
+        self.assertEqual(sessions[0][0], 3)
+
         # in2out
         pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
         self.pg0.add_stream(pkts)
@@ -6862,7 +7521,7 @@ class TestNAT64(MethodHolder):
 
         self.assertEqual(ses_num_end - ses_num_start, 3)
 
-    @unittest.skipUnless(running_extended_tests(), "part of extended tests")
+    @unittest.skipUnless(running_extended_tests, "part of extended tests")
     def test_session_timeout(self):
         """ NAT64 session timeout """
         self.icmp_id_in = 1234
@@ -7208,7 +7867,7 @@ class TestNAT64(MethodHolder):
         try:
             self.assertEqual(packet[IP].src, self.nat_addr)
             self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
-            self.assertTrue(packet.haslayer(GRE))
+            self.assertEqual(packet.haslayer(GRE), 1)
             self.assert_packet_checksums_valid(packet)
         except:
             self.logger.error(ppp("Unexpected or invalid packet:", packet))
@@ -7386,7 +8045,7 @@ class TestNAT64(MethodHolder):
         reass_n_start = len(reass)
 
         # in2out
-        data = 'a' * 200
+        data = b'a' * 200
         pkts = self.create_stream_frag_ip6(self.pg0, self.pg1.remote_ip4,
                                            self.tcp_port_in, 20, data)
         self.pg0.add_stream(pkts)
@@ -7402,7 +8061,7 @@ class TestNAT64(MethodHolder):
         self.assertEqual(data, p[Raw].load)
 
         # out2in
-        data = "A" * 4 + "b" * 16 + "C" * 3
+        data = b"A" * 4 + b"b" * 16 + b"C" * 3
         pkts = self.create_stream_frag(self.pg1,
                                        self.nat_addr,
                                        20,
@@ -7470,7 +8129,7 @@ class TestNAT64(MethodHolder):
         self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
 
         # in2out
-        data = 'a' * 200
+        data = b'a' * 200
         pkts = self.create_stream_frag_ip6(self.pg0, self.pg1.remote_ip4,
                                            self.tcp_port_in, 20, data)
         pkts.reverse()
@@ -7487,7 +8146,7 @@ class TestNAT64(MethodHolder):
         self.assertEqual(data, p[Raw].load)
 
         # out2in
-        data = "A" * 4 + "B" * 16 + "C" * 3
+        data = b"A" * 4 + b"B" * 16 + b"C" * 3
         pkts = self.create_stream_frag(self.pg1,
                                        self.nat_addr,
                                        20,
@@ -7506,11 +8165,11 @@ class TestNAT64(MethodHolder):
 
     def test_interface_addr(self):
         """ Acquire NAT64 pool addresses from interface """
-        self.vapi.nat64_add_interface_addr(self.pg4.sw_if_index)
+        self.vapi.nat64_add_del_interface_addr(self.pg4.sw_if_index)
 
         # no address in NAT64 pool
-        adresses = self.vapi.nat44_address_dump()
-        self.assertEqual(0, len(adresses))
+        addresses = self.vapi.nat44_address_dump()
+        self.assertEqual(0, len(addresses))
 
         # configure interface address and check NAT64 address pool
         self.pg4.config_ip4()
@@ -7521,9 +8180,9 @@ class TestNAT64(MethodHolder):
         # remove interface address and check NAT64 address pool
         self.pg4.unconfig_ip4()
         addresses = self.vapi.nat64_pool_addr_dump()
-        self.assertEqual(0, len(adresses))
+        self.assertEqual(0, len(addresses))
 
-    @unittest.skipUnless(running_extended_tests(), "part of extended tests")
+    @unittest.skipUnless(running_extended_tests, "part of extended tests")
     def test_ipfix_max_bibs_sessions(self):
         """ IPFIX logging maximum session and BIB entries exceeded """
         max_bibs = 1280
@@ -7558,8 +8217,8 @@ class TestNAT64(MethodHolder):
                                      src_address=self.pg3.local_ip4n,
                                      path_mtu=512,
                                      template_interval=10)
-        self.vapi.nat_ipfix(domain_id=self.ipfix_domain_id,
-                            src_port=self.ipfix_src_port)
+        self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
+                                           src_port=self.ipfix_src_port)
 
         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
              IPv6(src=src, dst=remote_host_ip6) /
@@ -7623,10 +8282,10 @@ class TestNAT64(MethodHolder):
                                      src_address=self.pg3.local_ip4n,
                                      path_mtu=512,
                                      template_interval=10)
-        self.vapi.nat_ipfix(domain_id=self.ipfix_domain_id,
-                            src_port=self.ipfix_src_port)
+        self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
+                                           src_port=self.ipfix_src_port)
 
-        data = 'a' * 200
+        data = b'a' * 200
         pkts = self.create_stream_frag_ip6(self.pg0, self.pg1.remote_ip4,
                                            self.tcp_port_in, 20, data)
         pkts.reverse()
@@ -7671,8 +8330,8 @@ class TestNAT64(MethodHolder):
                                      src_address=self.pg3.local_ip4n,
                                      path_mtu=512,
                                      template_interval=10)
-        self.vapi.nat_ipfix(domain_id=self.ipfix_domain_id,
-                            src_port=self.ipfix_src_port)
+        self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
+                                           src_port=self.ipfix_src_port)
 
         # Create
         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
@@ -7701,9 +8360,9 @@ class TestNAT64(MethodHolder):
         for p in capture:
             if p.haslayer(Data):
                 data = ipfix.decode_data_set(p.getlayer(Set))
-                if ord(data[0][230]) == 10:
+                if scapy.compat.orb(data[0][230]) == 10:
                     self.verify_ipfix_bib(data, 1, self.pg0.remote_ip6n)
-                elif ord(data[0][230]) == 6:
+                elif scapy.compat.orb(data[0][230]) == 6:
                     self.verify_ipfix_nat64_ses(data,
                                                 1,
                                                 self.pg0.remote_ip6n,
@@ -7730,9 +8389,9 @@ class TestNAT64(MethodHolder):
                              self.ipfix_domain_id)
             if p.haslayer(Data):
                 data = ipfix.decode_data_set(p.getlayer(Set))
-                if ord(data[0][230]) == 11:
+                if scapy.compat.orb(data[0][230]) == 11:
                     self.verify_ipfix_bib(data, 0, self.pg0.remote_ip6n)
-                elif ord(data[0][230]) == 7:
+                elif scapy.compat.orb(data[0][230]) == 7:
                     self.verify_ipfix_nat64_ses(data,
                                                 0,
                                                 self.pg0.remote_ip6n,
@@ -7741,6 +8400,39 @@ class TestNAT64(MethodHolder):
                 else:
                     self.logger.error(ppp("Unexpected or invalid packet: ", p))
 
+    def test_syslog_sess(self):
+        """ Test syslog session creation and deletion """
+        self.tcp_port_in = random.randint(1025, 65535)
+        remote_host_ip6 = self.compose_ip6(self.pg1.remote_ip4,
+                                           '64:ff9b::',
+                                           96)
+
+        self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
+                                                self.nat_addr_n)
+        self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
+        self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
+        self.vapi.syslog_set_filter(SYSLOG_SEVERITY.INFO)
+        self.vapi.syslog_set_sender(self.pg3.local_ip4n, self.pg3.remote_ip4n)
+
+        p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
+             IPv6(src=self.pg0.remote_ip6, dst=remote_host_ip6) /
+             TCP(sport=self.tcp_port_in, dport=self.tcp_external_port))
+        self.pg0.add_stream(p)
+        self.pg_enable_capture(self.pg_interfaces)
+        self.pg_start()
+        p = self.pg1.get_capture(1)
+        self.tcp_port_out = p[0][TCP].sport
+        capture = self.pg3.get_capture(1)
+        self.verify_syslog_sess(capture[0][Raw].load, is_ip6=True)
+
+        self.pg_enable_capture(self.pg_interfaces)
+        self.pg_start()
+        self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
+                                                self.nat_addr_n,
+                                                is_add=0)
+        capture = self.pg3.get_capture(1)
+        self.verify_syslog_sess(capture[0][Raw].load, False, True)
+
     def nat64_get_ses_num(self):
         """
         Return number of active NAT64 sessions.
@@ -7752,11 +8444,14 @@ class TestNAT64(MethodHolder):
         """
         Clear NAT64 configuration.
         """
-        self.vapi.nat_ipfix(enable=0, src_port=self.ipfix_src_port,
-                            domain_id=self.ipfix_domain_id)
+        self.vapi.nat_ipfix_enable_disable(enable=0,
+                                           src_port=self.ipfix_src_port,
+                                           domain_id=self.ipfix_domain_id)
         self.ipfix_src_port = 4739
         self.ipfix_domain_id = 1
 
+        self.vapi.syslog_set_filter(SYSLOG_SEVERITY.EMERG)
+
         self.vapi.nat_set_timeouts()
 
         interfaces = self.vapi.nat64_interface_dump()
@@ -7794,6 +8489,11 @@ class TestNAT64(MethodHolder):
                                            vrf_id=prefix.vrf_id,
                                            is_add=0)
 
+        bibs = self.statistics.get_counter('/nat64/total-bibs')
+        self.assertEqual(bibs[0][0], 0)
+        sessions = self.statistics.get_counter('/nat64/total-sessions')
+        self.assertEqual(sessions[0][0], 0)
+
     def tearDown(self):
         super(TestNAT64, self).tearDown()
         if not self.vpp_dead:
@@ -7817,7 +8517,7 @@ class TestDSlite(MethodHolder):
             cls.nat_addr = '10.0.0.3'
             cls.nat_addr_n = socket.inet_pton(socket.AF_INET, cls.nat_addr)
 
-            cls.create_pg_interfaces(range(2))
+            cls.create_pg_interfaces(range(3))
             cls.pg0.admin_up()
             cls.pg0.config_ip4()
             cls.pg0.resolve_arp()
@@ -7825,11 +8525,37 @@ class TestDSlite(MethodHolder):
             cls.pg1.config_ip6()
             cls.pg1.generate_remote_hosts(2)
             cls.pg1.configure_ipv6_neighbors()
+            cls.pg2.admin_up()
+            cls.pg2.config_ip4()
+            cls.pg2.resolve_arp()
 
         except Exception:
             super(TestDSlite, cls).tearDownClass()
             raise
 
+    def verify_syslog_apmadd(self, data, isaddr, isport, xsaddr, xsport,
+                             sv6enc, proto):
+        message = data.decode('utf-8')
+        try:
+            message = SyslogMessage.parse(message)
+        except ParseError as e:
+            self.logger.error(e)
+        else:
+            self.assertEqual(message.severity, SyslogSeverity.info)
+            self.assertEqual(message.appname, 'NAT')
+            self.assertEqual(message.msgid, 'APMADD')
+            sd_params = message.sd.get('napmap')
+            self.assertTrue(sd_params is not None)
+            self.assertEqual(sd_params.get('IATYP'), 'IPv4')
+            self.assertEqual(sd_params.get('ISADDR'), isaddr)
+            self.assertEqual(sd_params.get('ISPORT'), "%d" % isport)
+            self.assertEqual(sd_params.get('XATYP'), 'IPv4')
+            self.assertEqual(sd_params.get('XSADDR'), xsaddr)
+            self.assertEqual(sd_params.get('XSPORT'), "%d" % xsport)
+            self.assertEqual(sd_params.get('PROTO'), "%d" % proto)
+            self.assertTrue(sd_params.get('SSUBIX') is not None)
+            self.assertEqual(sd_params.get('SV6ENC'), sv6enc)
+
     def test_dslite(self):
         """ Test DS-Lite """
         nat_config = self.vapi.nat_show_config()
@@ -7842,6 +8568,7 @@ class TestDSlite(MethodHolder):
         aftr_ip6 = '2001:db8:85a3::8a2e:370:1'
         aftr_ip6_n = socket.inet_pton(socket.AF_INET6, aftr_ip6)
         self.vapi.dslite_set_aftr_addr(aftr_ip6_n, aftr_ip4_n)
+        self.vapi.syslog_set_sender(self.pg2.local_ip4n, self.pg2.remote_ip4n)
 
         # UDP
         p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
@@ -7860,6 +8587,10 @@ class TestDSlite(MethodHolder):
         self.assertEqual(capture[UDP].dport, 10000)
         self.assert_packet_checksums_valid(capture)
         out_port = capture[UDP].sport
+        capture = self.pg2.get_capture(1)
+        self.verify_syslog_apmadd(capture[0][Raw].load, '192.168.1.1',
+                                  20000, self.nat_addr, out_port,
+                                  self.pg1.remote_hosts[0].ip6, IP_PROTOS.udp)
 
         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
              IP(dst=self.nat_addr, src=self.pg0.remote_ip4) /
@@ -7956,6 +8687,11 @@ class TestDSlite(MethodHolder):
         self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[1].ip6)
         self.assertTrue(capture.haslayer(ICMPv6EchoReply))
 
+        b4s = self.statistics.get_counter('/dslite/total-b4s')
+        self.assertEqual(b4s[0][0], 2)
+        sessions = self.statistics.get_counter('/dslite/total-sessions')
+        self.assertEqual(sessions[0][0], 3)
+
     def tearDown(self):
         super(TestDSlite, self).tearDown()
         if not self.vpp_dead: