ip: allow addrs from the same prefix on intf
[vpp.git] / test / test_ip6.py
index 35061b0..f2c4c00 100644 (file)
@@ -20,10 +20,11 @@ from six import moves
 
 from framework import VppTestCase, VppTestRunner
 from util import ppp, ip6_normalize, mk_ll_addr
-from vpp_ip import DpoProto
+from vpp_ip import DpoProto, VppIpAddress
 from vpp_ip_route import VppIpRoute, VppRoutePath, find_route, VppIpMRoute, \
     VppMRoutePath, MRouteItfFlags, MRouteEntryFlags, VppMplsIpBind, \
-    VppMplsRoute, VppMplsTable, VppIpTable, FibPathType
+    VppMplsRoute, VppMplsTable, VppIpTable, FibPathType, \
+    VppIpInterfaceAddress
 from vpp_neighbor import find_nbr, VppNeighbor
 from vpp_pg_interface import is_ipv6_misc
 from vpp_sub_interface import VppSubInterface, VppDot1QSubint
@@ -615,7 +616,7 @@ class TestIPv6(TestIPv6ND):
             # the options are nested in the scapy packet in way that i cannot
             # decipher how to decode. this 1st layer of option always returns
             # nested classes, so a direct obj1=obj2 comparison always fails.
-            # however, the getlayer(.., 2) does give one instnace.
+            # however, the getlayer(.., 2) does give one instance.
             # so we cheat here and construct a new opt instance for comparison
             rd = ICMPv6NDOptPrefixInfo(
                 prefixlen=raos.prefixlen,
@@ -628,7 +629,9 @@ class TestIPv6(TestIPv6ND):
                     rd = rx.getlayer(
                         ICMPv6NDOptPrefixInfo, ii + 2)
             else:
-                self.assertEqual(pi_opt, raos)
+                self.assertEqual(pi_opt, raos, 'Expected: %s, received: %s'
+                                 % (pi_opt.show(dump=True),
+                                    raos.show(dump=True)))
 
     def send_and_expect_ra(self, intf, pkts, remark, dst_ip=None,
                            filter_out_fn=is_ipv6_misc,
@@ -743,8 +746,8 @@ class TestIPv6(TestIPv6ND):
         #
         # Configure The RA to announce the links prefix
         #
-        self.pg0.ip6_ra_prefix(self.pg0.local_ip6,
-                               self.pg0.local_ip6_prefix_len)
+        self.pg0.ip6_ra_prefix('%s/%s' % (self.pg0.local_ip6,
+                               self.pg0.local_ip6_prefix_len))
 
         #
         # RAs should now contain the prefix information option
@@ -769,8 +772,8 @@ class TestIPv6(TestIPv6ND):
         # Change the prefix info to not off-link
         #  L-flag is clear
         #
-        self.pg0.ip6_ra_prefix(self.pg0.local_ip6,
-                               self.pg0.local_ip6_prefix_len,
+        self.pg0.ip6_ra_prefix('%s/%s' % (self.pg0.local_ip6,
+                               self.pg0.local_ip6_prefix_len),
                                off_link=1)
 
         opt = ICMPv6NDOptPrefixInfo(
@@ -789,8 +792,8 @@ class TestIPv6(TestIPv6ND):
         # Change the prefix info to not off-link, no-autoconfig
         #  L and A flag are clear in the advert
         #
-        self.pg0.ip6_ra_prefix(self.pg0.local_ip6,
-                               self.pg0.local_ip6_prefix_len,
+        self.pg0.ip6_ra_prefix('%s/%s' % (self.pg0.local_ip6,
+                               self.pg0.local_ip6_prefix_len),
                                off_link=1,
                                no_autoconfig=1)
 
@@ -810,8 +813,8 @@ class TestIPv6(TestIPv6ND):
         # Change the flag settings back to the defaults
         #  L and A flag are set in the advert
         #
-        self.pg0.ip6_ra_prefix(self.pg0.local_ip6,
-                               self.pg0.local_ip6_prefix_len)
+        self.pg0.ip6_ra_prefix('%s/%s' % (self.pg0.local_ip6,
+                               self.pg0.local_ip6_prefix_len))
 
         opt = ICMPv6NDOptPrefixInfo(
             prefixlen=self.pg0.local_ip6_prefix_len,
@@ -829,8 +832,8 @@ class TestIPv6(TestIPv6ND):
         # Change the prefix info to not off-link, no-autoconfig
         #  L and A flag are clear in the advert
         #
-        self.pg0.ip6_ra_prefix(self.pg0.local_ip6,
-                               self.pg0.local_ip6_prefix_len,
+        self.pg0.ip6_ra_prefix('%s/%s' % (self.pg0.local_ip6,
+                               self.pg0.local_ip6_prefix_len),
                                off_link=1,
                                no_autoconfig=1)
 
@@ -850,8 +853,8 @@ class TestIPv6(TestIPv6ND):
         # Use the reset to defaults option to revert to defaults
         #  L and A flag are clear in the advert
         #
-        self.pg0.ip6_ra_prefix(self.pg0.local_ip6,
-                               self.pg0.local_ip6_prefix_len,
+        self.pg0.ip6_ra_prefix('%s/%s' % (self.pg0.local_ip6,
+                               self.pg0.local_ip6_prefix_len),
                                use_default=1)
 
         opt = ICMPv6NDOptPrefixInfo(
@@ -869,8 +872,8 @@ class TestIPv6(TestIPv6ND):
         #
         # Advertise Another prefix. With no L-flag/A-flag
         #
-        self.pg0.ip6_ra_prefix(self.pg1.local_ip6,
-                               self.pg1.local_ip6_prefix_len,
+        self.pg0.ip6_ra_prefix('%s/%s' % (self.pg1.local_ip6,
+                               self.pg1.local_ip6_prefix_len),
                                off_link=1,
                                no_autoconfig=1)
 
@@ -899,8 +902,8 @@ class TestIPv6(TestIPv6ND):
         # Remove the first prefix-info - expect the second is still in the
         # advert
         #
-        self.pg0.ip6_ra_prefix(self.pg0.local_ip6,
-                               self.pg0.local_ip6_prefix_len,
+        self.pg0.ip6_ra_prefix('%s/%s' % (self.pg0.local_ip6,
+                               self.pg0.local_ip6_prefix_len),
                                is_no=1)
 
         opt = ICMPv6NDOptPrefixInfo(
@@ -918,8 +921,8 @@ class TestIPv6(TestIPv6ND):
         #
         # Remove the second prefix-info - expect no prefix-info in the adverts
         #
-        self.pg0.ip6_ra_prefix(self.pg1.local_ip6,
-                               self.pg1.local_ip6_prefix_len,
+        self.pg0.ip6_ra_prefix('%s/%s' % (self.pg1.local_ip6,
+                               self.pg1.local_ip6_prefix_len),
                                is_no=1)
 
         self.pg0.ip6_ra_config(send_unicast=1)
@@ -933,6 +936,80 @@ class TestIPv6(TestIPv6ND):
         self.pg0.ip6_ra_config(no=1, suppress=1, send_unicast=0)
 
 
+class TestIPv6IfAddrRoute(VppTestCase):
+    """ IPv6 Interface Addr Route Test Case """
+
+    @classmethod
+    def setUpClass(cls):
+        super(TestIPv6IfAddrRoute, cls).setUpClass()
+
+    @classmethod
+    def tearDownClass(cls):
+        super(TestIPv6IfAddrRoute, cls).tearDownClass()
+
+    def setUp(self):
+        super(TestIPv6IfAddrRoute, self).setUp()
+
+        # create 1 pg interface
+        self.create_pg_interfaces(range(1))
+
+        for i in self.pg_interfaces:
+            i.admin_up()
+            i.config_ip6()
+            i.resolve_ndp()
+
+    def tearDown(self):
+        super(TestIPv6IfAddrRoute, self).tearDown()
+        for i in self.pg_interfaces:
+            i.unconfig_ip6()
+            i.admin_down()
+
+    def test_ipv6_ifaddrs_same_prefix(self):
+        """ IPv6 Interface Addresses Same Prefix test
+
+        Test scenario:
+
+            - Verify no route in FIB for prefix 2001:10::/64
+            - Configure IPv4 address 2001:10::10/64  on an interface
+            - Verify route in FIB for prefix 2001:10::/64
+            - Configure IPv4 address 2001:10::20/64 on an interface
+            - Delete 2001:10::10/64 from interface
+            - Verify route in FIB for prefix 2001:10::/64
+            - Delete 2001:10::20/64 from interface
+            - Verify no route in FIB for prefix 2001:10::/64
+        """
+
+        addr1 = "2001:10::10"
+        addr2 = "2001:10::20"
+
+        if_addr1 = VppIpInterfaceAddress(self, self.pg0,
+                                         VppIpAddress(addr1), 64)
+        if_addr2 = VppIpInterfaceAddress(self, self.pg0,
+                                         VppIpAddress(addr2), 64)
+        self.assertFalse(if_addr1.query_vpp_config())  # 2001:10::/64
+        self.assertFalse(find_route(self, addr1, 128))
+        self.assertFalse(find_route(self, addr2, 128))
+
+        # configure first address, verify route present
+        if_addr1.add_vpp_config()
+        self.assertTrue(if_addr1.query_vpp_config())  # 2001:10::/64
+        self.assertTrue(find_route(self, addr1, 128))
+        self.assertFalse(find_route(self, addr2, 128))
+
+        # configure second address, delete first, verify route not removed
+        if_addr2.add_vpp_config()
+        if_addr1.remove_vpp_config()
+        self.assertTrue(if_addr1.query_vpp_config())  # 2001:10::/64
+        self.assertFalse(find_route(self, addr1, 128))
+        self.assertTrue(find_route(self, addr2, 128))
+
+        # delete second address, verify route removed
+        if_addr2.remove_vpp_config()
+        self.assertFalse(if_addr1.query_vpp_config())  # 2001:10::/64
+        self.assertFalse(find_route(self, addr1, 128))
+        self.assertFalse(find_route(self, addr2, 128))
+
+
 class TestICMPv6Echo(VppTestCase):
     """ ICMPv6 Echo Test Case """