L2FIB: add flush test

add tests for flush int/bd/all

Change-Id: Ia589ec5925b9c8acbb2fc16dafbf4842aa1a6eff
Signed-off-by: Eyal Bari <ebari@cisco.com>
diff --git a/test/test_l2_fib.py b/test/test_l2_fib.py
index 3d5d212..c373b14 100644
--- a/test/test_l2_fib.py
+++ b/test/test_l2_fib.py
@@ -75,6 +75,10 @@
     """ L2 FIB Test Case """
 
     @classmethod
+    def bd_ifs(cls, bd_id):
+        return range((bd_id - 1) * cls.n_ifs_per_bd, bd_id * cls.n_ifs_per_bd)
+
+    @classmethod
     def setUpClass(cls):
         """
         Perform standard class setup (defined by class method setUpClass in
@@ -82,49 +86,49 @@
         variables and configure VPP.
 
         :var int bd_id: Bridge domain ID.
-        :var int mac_entries_count: Number of MAC entries for bridge-domain.
         """
         super(TestL2fib, cls).setUpClass()
 
-        # Test variables
-        cls.bd_id = 1
-        cls.mac_entries_count = 200
-
         try:
+            n_brs = cls.n_brs = range(1, 3)
+            cls.n_ifs_per_bd = 4
+            n_ifs = range(cls.n_ifs_per_bd * len(cls.n_brs))
             # Create 4 pg interfaces
-            cls.create_pg_interfaces(range(4))
+            cls.create_pg_interfaces(n_ifs)
 
-            # Packet flows mapping pg0 -> pg1, pg2, pg3 etc.
             cls.flows = dict()
-            cls.flows[cls.pg0] = [cls.pg1, cls.pg2, cls.pg3]
-            cls.flows[cls.pg1] = [cls.pg0, cls.pg2, cls.pg3]
-            cls.flows[cls.pg2] = [cls.pg0, cls.pg1, cls.pg3]
-            cls.flows[cls.pg3] = [cls.pg0, cls.pg1, cls.pg2]
+            for bd_id in n_brs:
+                # Packet flows mapping pg0 -> pg1, pg2, pg3 etc.
+                ifs = cls.bd_ifs(bd_id)
+                for j in ifs:
+                    cls.flows[cls.pg_interfaces[j]] = [
+                        cls.pg_interfaces[x] for x in ifs if x != j]
 
             # Packet sizes
             cls.pg_if_packet_sizes = [64, 512, 1518, 9018]
 
-            # Create BD with MAC learning and unknown unicast flooding disabled
-            # and put interfaces to this BD
-            cls.vapi.bridge_domain_add_del(
-                bd_id=cls.bd_id, uu_flood=0, learn=0)
-            for pg_if in cls.pg_interfaces:
-                cls.vapi.sw_interface_set_l2_bridge(pg_if.sw_if_index,
-                                                    bd_id=cls.bd_id)
+            for bd_id in n_brs:
+                # Create BD with MAC learning and unknown unicast flooding
+                # disabled and put interfaces to this BD
+                cls.vapi.bridge_domain_add_del(
+                    bd_id=bd_id, uu_flood=0, learn=0)
+                ifs = [cls.pg_interfaces[i] for i in cls.bd_ifs(bd_id)]
+                for pg_if in ifs:
+                    cls.vapi.sw_interface_set_l2_bridge(pg_if.sw_if_index,
+                                                        bd_id=bd_id)
 
             # Set up all interfaces
             for i in cls.pg_interfaces:
                 i.admin_up()
 
             # Mapping between packet-generator index and lists of test hosts
-            cls.hosts_by_pg_idx = dict()
+            cls.hosts = dict()
+            cls.fib_hosts = dict()
+            cls.deleted_hosts = dict()
             for pg_if in cls.pg_interfaces:
-                cls.hosts_by_pg_idx[pg_if.sw_if_index] = []
-
-            # Create list of deleted hosts
-            cls.deleted_hosts_by_pg_idx = dict()
-            for pg_if in cls.pg_interfaces:
-                cls.deleted_hosts_by_pg_idx[pg_if.sw_if_index] = []
+                cls.hosts[pg_if.sw_if_index] = []
+                cls.fib_hosts[pg_if.sw_if_index] = []
+                cls.deleted_hosts[pg_if.sw_if_index] = []
 
         except Exception:
             super(TestL2fib, cls).tearDownClass()
@@ -141,78 +145,107 @@
         super(TestL2fib, self).tearDown()
         if not self.vpp_dead:
             self.logger.info(self.vapi.ppcli("show l2fib verbose"))
-            self.logger.info(self.vapi.ppcli("show bridge-domain %s detail"
-                                             % self.bd_id))
+            for bd_id in self.n_brs:
+                self.logger.info(self.vapi.ppcli("show bridge-domain %s detail"
+                                                 % bd_id))
 
-    def create_hosts(self, count, start=0):
+    def create_hosts(self, n_hosts_per_if, subnet):
         """
         Create required number of host MAC addresses and distribute them among
         interfaces. Create host IPv4 address for every host MAC address.
 
-        :param int count: Number of hosts to create MAC/IPv4 addresses for.
-        :param int start: Number to start numbering from.
+        :param int n_hosts_per_if: Number of per interface hosts to
+        create MAC/IPv4 addresses for.
         """
-        n_int = len(self.pg_interfaces)
-        macs_per_if = count / n_int
-        i = -1
+
         for pg_if in self.pg_interfaces:
-            i += 1
-            start_nr = macs_per_if * i + start
-            end_nr = count + start if i == (n_int - 1) \
-                else macs_per_if * (i + 1) + start
-            hosts = self.hosts_by_pg_idx[pg_if.sw_if_index]
-            for j in range(start_nr, end_nr):
-                host = Host(
-                    "00:00:00:ff:%02x:%02x" % (pg_if.sw_if_index, j),
-                    "172.17.1%02x.%u" % (pg_if.sw_if_index, j))
-                hosts.append(host)
+            swif = pg_if.sw_if_index
 
-    def config_l2_fib_entries(self, count, start=0):
+            def mac(j): return "00:00:%02x:ff:%02x:%02x" % (subnet, swif, j)
+
+            def ip(j): return "172.%02u.1%02x.%u" % (subnet, swif, j)
+
+            def h(j): return Host(mac(j), ip(j))
+            self.hosts[swif] = [h(j) for j in range(n_hosts_per_if)]
+
+    def config_l2_fib_entries(self, bd_id, n_hosts_per_if):
         """
-        Create required number of L2 FIB entries.
+        Config required number of L2 FIB entries.
 
+        :param int bd_id: BD's id
         :param int count: Number of L2 FIB entries to be created.
         :param int start: Starting index of the host list. (Default value = 0)
         """
-        n_int = len(self.pg_interfaces)
-        percent = 0
-        counter = 0.0
-        for pg_if in self.pg_interfaces:
-            end_nr = start + count / n_int
-            for j in range(start, end_nr):
-                host = self.hosts_by_pg_idx[pg_if.sw_if_index][j]
+        ifs = [self.pg_interfaces[i] for i in self.bd_ifs(bd_id)]
+        for pg_if in ifs:
+            swif = pg_if.sw_if_index
+            hosts = self.hosts[swif]
+            fhosts = self.fib_hosts[swif]
+            for j in range(n_hosts_per_if):
+                host = hosts.pop()
                 self.vapi.l2fib_add_del(
-                    host.mac, self.bd_id, pg_if.sw_if_index, static_mac=1)
-                counter += 1
-                percentage = counter / count * 100
-                if percentage > percent:
-                    self.logger.info("Configure %d L2 FIB entries .. %d%% done"
-                                     % (count, percentage))
-                    percent += 1
+                    host.mac, bd_id, swif, static_mac=1)
+                fhosts.append(host)
+        #        del hosts[0]
+        self.logger.info("Configure %d L2 FIB entries .." %
+                         len(self.pg_interfaces) * n_hosts_per_if)
         self.logger.info(self.vapi.ppcli("show l2fib"))
 
-    def delete_l2_fib_entry(self, count):
+    def delete_l2_fib_entry(self, bd_id, n_hosts_per_if):
         """
         Delete required number of L2 FIB entries.
 
         :param int count: Number of L2 FIB entries to be created.
         """
-        n_int = len(self.pg_interfaces)
-        percent = 0
-        counter = 0.0
-        for pg_if in self.pg_interfaces:
-            for j in range(count / n_int):
-                host = self.hosts_by_pg_idx[pg_if.sw_if_index][0]
+        ifs = [self.pg_interfaces[i] for i in self.bd_ifs(bd_id)]
+        for pg_if in ifs:
+            swif = pg_if.sw_if_index
+            hosts = self.fib_hosts[swif]
+            dhosts = self.deleted_hosts[swif]
+            for j in range(n_hosts_per_if):
+                host = hosts.pop()
                 self.vapi.l2fib_add_del(
-                    host.mac, self.bd_id, pg_if.sw_if_index, is_add=0)
-                self.deleted_hosts_by_pg_idx[pg_if.sw_if_index].append(host)
-                del self.hosts_by_pg_idx[pg_if.sw_if_index][0]
-                counter += 1
-                percentage = counter / count * 100
-                if percentage > percent:
-                    self.logger.info("Delete %d L2 FIB entries .. %d%% done"
-                                     % (count, percentage))
-                    percent += 1
+                    host.mac, bd_id, swif, is_add=0)
+                dhosts.append(host)
+        self.logger.info(self.vapi.ppcli("show l2fib"))
+
+    def flush_int(self, swif):
+        """
+        Flush swif L2 FIB entries.
+
+        :param int swif: sw if index.
+        """
+        self.vapi.l2fib_flush_int(swif)
+        self.deleted_hosts[swif] = self.fib_hosts[swif] + \
+            self.deleted_hosts[swif]
+        self.fib_hosts[swif] = []
+        self.logger.info(self.vapi.ppcli("show l2fib"))
+
+    def flush_bd(self, bd_id):
+        """
+        Flush bd_id L2 FIB entries.
+
+        :param int bd_id: Bridge Domain id.
+        """
+        self.vapi.l2fib_flush_bd(bd_id)
+        ifs = [self.pg_interfaces[i] for i in self.bd_ifs(bd_id)]
+        for pg_if in ifs:
+            swif = pg_if.sw_if_index
+            self.deleted_hosts[swif] = self.fib_hosts[swif] + \
+                self.deleted_hosts[swif]
+            self.fib_hosts[swif] = []
+        self.logger.info(self.vapi.ppcli("show l2fib"))
+
+    def flush_all(self):
+        """
+        Flush All L2 FIB entries.
+        """
+        self.vapi.l2fib_flush_all()
+        for pg_if in self.pg_interfaces:
+            swif = pg_if.sw_if_index
+            self.deleted_hosts[swif] = self.fib_hosts[swif] + \
+                self.deleted_hosts[swif]
+            self.fib_hosts[swif] = []
         self.logger.info(self.vapi.ppcli("show l2fib"))
 
     def create_stream(self, src_if, packet_sizes, deleted=False):
@@ -225,13 +258,14 @@
         :param boolean deleted: Set to True if deleted_hosts list required.
         :return: Stream of packets.
         """
+        src_hosts = self.fib_hosts[src_if.sw_if_index]
+        if not src_hosts:
+            return []
         pkts = []
-        src_hosts = self.hosts_by_pg_idx[src_if.sw_if_index]
         for dst_if in self.flows[src_if]:
-            dst_hosts = self.deleted_hosts_by_pg_idx[dst_if.sw_if_index]\
-                if deleted else self.hosts_by_pg_idx[dst_if.sw_if_index]
-            n_int = len(dst_hosts)
-            for i in range(0, n_int):
+            dst_hosts = self.deleted_hosts[dst_if.sw_if_index]\
+                if deleted else self.fib_hosts[dst_if.sw_if_index]
+            for i in range(0, len(dst_hosts)):
                 dst_host = dst_hosts[i]
                 src_host = random.choice(src_hosts)
                 pkt_info = self.create_packet_info(src_if, dst_if)
@@ -289,40 +323,44 @@
                 "Port %u: Packet expected from source %u didn't arrive" %
                 (dst_sw_if_index, i.sw_if_index))
 
-    def run_verify_test(self):
+    def run_verify_test(self, bd_id):
         # Test
         # Create incoming packet streams for packet-generator interfaces
-        for i in self.pg_interfaces:
+        self.reset_packet_infos()
+        ifs = [self.pg_interfaces[i] for i in self.bd_ifs(bd_id)]
+        for i in ifs:
             pkts = self.create_stream(i, self.pg_if_packet_sizes)
             i.add_stream(pkts)
 
         # Enable packet capture and start packet sending
-        self.pg_enable_capture(self.pg_interfaces)
+        self.pg_enable_capture(ifs)
         self.pg_start()
 
         # Verify
         # Verify outgoing packet streams per packet-generator interface
-        for i in self.pg_interfaces:
+        for i in ifs:
             capture = i.get_capture()
             self.logger.info("Verifying capture on interface %s" % i.name)
             self.verify_capture(i, capture)
 
-    def run_verify_negat_test(self):
+    def run_verify_negat_test(self, bd_id):
         # Test
         # Create incoming packet streams for packet-generator interfaces for
         # deleted MAC addresses
         self.reset_packet_infos()
-        for i in self.pg_interfaces:
+        ifs = [self.pg_interfaces[i] for i in self.bd_ifs(bd_id)]
+        for i in ifs:
             pkts = self.create_stream(i, self.pg_if_packet_sizes, deleted=True)
-            i.add_stream(pkts)
+            if pkts:
+                i.add_stream(pkts)
 
         # Enable packet capture and start packet sending
-        self.pg_enable_capture(self.pg_interfaces)
+        self.pg_enable_capture(ifs)
         self.pg_start()
 
         # Verify
         # Verify outgoing packet streams per packet-generator interface
-        for i in self.pg_interfaces:
+        for i in ifs:
             i.assert_nothing_captured(remark="outgoing interface")
 
     def test_l2_fib_01(self):
@@ -330,49 +368,106 @@
         """
         # Config 1
         # Create test host entries
-        self.create_hosts(100)
+        self.create_hosts(100, subnet=17)
 
         # Add first 100 MAC entries to L2 FIB
-        self.config_l2_fib_entries(100)
+        self.config_l2_fib_entries(bd_id=1, n_hosts_per_if=100)
 
         # Test 1
-        self.run_verify_test()
+        self.run_verify_test(bd_id=1)
 
     def test_l2_fib_02(self):
         """ L2 FIB test 2 - delete 12 MAC entries
         """
         # Config 2
-        # Delete 12 MAC entries (3 per interface) from L2 FIB
-        self.delete_l2_fib_entry(12)
+        # Delete 12 MAC entries per interface from L2 FIB
+        self.delete_l2_fib_entry(bd_id=1, n_hosts_per_if=12)
 
         # Test 2a
-        self.run_verify_test()
+        self.run_verify_test(bd_id=1)
 
         # Verify 2a
-        self.run_verify_negat_test()
+        self.run_verify_negat_test(bd_id=1)
 
     def test_l2_fib_03(self):
         """ L2 FIB test 3 - program new 100 MAC addresses
         """
         # Config 3
         # Create new test host entries
-        self.create_hosts(100, start=100)
+        self.create_hosts(100, subnet=22)
 
         # Add new 100 MAC entries to L2 FIB
-        self.config_l2_fib_entries(100, start=22)
+        self.config_l2_fib_entries(bd_id=1, n_hosts_per_if=100)
 
         # Test 3
-        self.run_verify_test()
+        self.run_verify_test(bd_id=1)
 
     def test_l2_fib_04(self):
         """ L2 FIB test 4 - delete 160 MAC entries
         """
         # Config 4
-        # Delete 160 MAC entries (40 per interface) from L2 FIB
-        self.delete_l2_fib_entry(160)
+        # Delete 160 MAC entries per interface from L2 FIB
+        self.delete_l2_fib_entry(bd_id=1, n_hosts_per_if=160)
 
         # Test 4a
-        self.run_verify_negat_test()
+        self.run_verify_negat_test(bd_id=1)
+
+    def test_l2_fib_05(self):
+        """ L2 FIB test 5 - flush first interface
+        """
+        self.flush_int(self.pg_interfaces[0].sw_if_index)
+        self.sleep(3)
+        self.create_hosts(1, subnet=31)
+        self.config_l2_fib_entries(bd_id=1, n_hosts_per_if=1)
+        self.run_verify_test(bd_id=1)
+        self.run_verify_negat_test(bd_id=1)
+
+    def test_l2_fib_06(self):
+        """ L2 FIB test 6 - Program 20 new MAC entries
+        """
+        self.create_hosts(20, subnet=33)
+
+        self.config_l2_fib_entries(bd_id=1, n_hosts_per_if=20)
+        self.config_l2_fib_entries(bd_id=2, n_hosts_per_if=20)
+        self.run_verify_test(bd_id=1)
+        self.run_verify_test(bd_id=2)
+
+    def test_l2_fib_07(self):
+        """ L2 FIB test 7 - flush bd_id
+        """
+        self.flush_bd(bd_id=1)
+        self.run_verify_negat_test(bd_id=1)
+        self.run_verify_test(bd_id=2)
+
+    def test_l2_fib_08(self):
+        """ L2 FIB test 8 - Program 20 new MAC entries
+        """
+        self.create_hosts(20, subnet=34)
+
+        self.config_l2_fib_entries(bd_id=1, n_hosts_per_if=20)
+        self.config_l2_fib_entries(bd_id=2, n_hosts_per_if=20)
+        self.run_verify_test(bd_id=1)
+        self.run_verify_test(bd_id=2)
+
+    def test_l2_fib_09(self):
+        """ L2 FIB test 9 - flush all
+        """
+        self.flush_all()
+        self.sleep(3)
+        self.run_verify_negat_test(bd_id=1)
+        self.run_verify_negat_test(bd_id=2)
+
+    def test_l2_fib_10(self):
+        """ L2 FIB test 10 - Program 20 new MAC entries
+        """
+        self.create_hosts(20, subnet=35)
+
+        self.config_l2_fib_entries(bd_id=1, n_hosts_per_if=20)
+        self.config_l2_fib_entries(bd_id=2, n_hosts_per_if=20)
+        self.run_verify_test(bd_id=1)
+        self.run_verify_test(bd_id=2)
+        self.run_verify_negat_test(bd_id=1)
+        self.run_verify_negat_test(bd_id=2)
 
 
 if __name__ == '__main__':