ip: Setting the Link-Local address from the API enables IPv6 on the 54/26654/4
authorNeale Ranns <nranns@cisco.com>
Thu, 23 Apr 2020 07:36:12 +0000 (07:36 +0000)
committerOle Trøan <otroan@employees.org>
Fri, 24 Apr 2020 09:24:43 +0000 (09:24 +0000)
interface

Type: fix

Signed-off-by: Neale Ranns <nranns@cisco.com>
Change-Id: I0b7c189006e30a357cd6be4f3c9c61fded4157cb

src/plugins/dhcp/dhcp6_ia_na_client_cp.c
src/plugins/dhcp/dhcp6_pd_client_cp.c
src/vnet/ip/ip6_forward.c
src/vnet/ip/ip6_link.c
src/vnet/ip/ip6_link.h
src/vnet/ip/ip_api.c
src/vnet/ip6-nd/rd_cp.c
test/test_ip6.py
test/vpp_ip_route.py

index 4d59f60..975a7e0 100644 (file)
@@ -412,7 +412,7 @@ dhcp6_client_cp_process (vlib_main_t * vm, vlib_node_runtime_t * rt,
                     clib_warning ("Failed to delete interface address");
                 pool_put (rm->address_pool, address_info);
                 /* make sure ip6 stays enabled */
-                ip6_link_enable (sw_if_index);
+                ip6_link_enable (sw_if_index, NULL);
                 client_state = &rm->client_state_by_sw_if_index[sw_if_index];
                 if (--client_state->address_count == 0)
                   {
@@ -645,7 +645,7 @@ dhcp6_client_enable_disable (u32 sw_if_index, u8 enable)
          dhcp6_clients_enable_disable (1);
        }
 
-      ip6_link_enable (sw_if_index);
+      ip6_link_enable (sw_if_index, NULL);
       send_client_message_start_stop (sw_if_index, ~0, DHCPV6_MSG_SOLICIT,
                                      0, 1);
     }
index 077b4a3..2328dfd 100644 (file)
@@ -1287,7 +1287,7 @@ dhcp6_pd_client_enable_disable (u32 sw_if_index,
          dhcp6_clients_enable_disable (1);
        }
 
-      ip6_link_enable (sw_if_index);
+      ip6_link_enable (sw_if_index, NULL);
       send_client_message_start_stop (sw_if_index, ~0, DHCPV6_MSG_SOLICIT,
                                      0, 1);
     }
index 0325627..0a45535 100644 (file)
@@ -320,7 +320,7 @@ ip6_add_del_interface_address (vlib_main_t * vm,
        {
          int rv;
 
-         rv = ip6_set_link_local_address (sw_if_index, address);
+         rv = ip6_link_set_local_address (sw_if_index, address);
 
          if (rv)
            {
@@ -342,6 +342,8 @@ ip6_add_del_interface_address (vlib_main_t * vm,
              return clib_error_create ("address not found");
            }
        }
+
+      return (NULL);
     }
 
   vec_validate (im->fib_index_by_sw_if_index, sw_if_index);
@@ -479,7 +481,7 @@ ip6_add_del_interface_address (vlib_main_t * vm,
 
   ip6_sw_interface_enable_disable (sw_if_index, !is_del);
   if (!is_del)
-    ip6_link_enable (sw_if_index);
+    ip6_link_enable (sw_if_index, NULL);
 
   /* intf addr routes are added/deleted on admin up/down */
   if (vnet_sw_interface_is_admin_up (vnm, sw_if_index))
index 35b718e..d2142f9 100644 (file)
@@ -146,7 +146,7 @@ ip6_link_is_enabled (u32 sw_if_index)
 
 
 int
-ip6_link_enable (u32 sw_if_index)
+ip6_link_enable (u32 sw_if_index, const ip6_address_t * link_local_addr)
 {
   ip6_link_t *il;
   int rv;
@@ -187,9 +187,11 @@ ip6_link_enable (u32 sw_if_index)
 
       sw = vnet_get_sup_sw_interface (vnm, sw_if_index);
 
-      if (sw->type == VNET_SW_INTERFACE_TYPE_SUB ||
-         sw->type == VNET_SW_INTERFACE_TYPE_PIPE ||
-         sw->type == VNET_SW_INTERFACE_TYPE_P2P)
+      if (NULL != link_local_addr)
+       ip6_address_copy (&il->il_ll_addr, link_local_addr);
+      else if (sw->type == VNET_SW_INTERFACE_TYPE_SUB ||
+              sw->type == VNET_SW_INTERFACE_TYPE_PIPE ||
+              sw->type == VNET_SW_INTERFACE_TYPE_P2P)
        {
          il->il_ll_addr.as_u64[0] =
            clib_host_to_net_u64 (0xFE80000000000000ULL);
@@ -367,7 +369,7 @@ ip6_src_address_for_packet (u32 sw_if_index,
 }
 
 int
-ip6_set_link_local_address (u32 sw_if_index, const ip6_address_t * address)
+ip6_link_set_local_address (u32 sw_if_index, const ip6_address_t * address)
 {
   ip6_link_delegate_t *ild;
   ip6_link_t *il;
@@ -375,7 +377,7 @@ ip6_set_link_local_address (u32 sw_if_index, const ip6_address_t * address)
   il = ip6_link_get (sw_if_index);
 
   if (NULL == il)
-    return (VNET_API_ERROR_IP6_NOT_ENABLED);
+    return ip6_link_enable (sw_if_index, address);
 
   ip6_ll_prefix_t ilp = {
     .ilp_addr = il->il_ll_addr,
@@ -794,7 +796,7 @@ enable_ip6_interface_cmd (vlib_main_t * vm,
 
   if (unformat_user (input, unformat_vnet_sw_interface, vnm, &sw_if_index))
     {
-      if (ip6_link_enable (sw_if_index))
+      if (ip6_link_enable (sw_if_index, NULL))
        error = clib_error_return (0, "Failed\n");
     }
   else
index 01506bb..a9dfa5e 100644 (file)
  * IPv6 Configuration on an interface
  */
 
-extern int ip6_link_enable (u32 sw_if_index);
+extern int ip6_link_enable (u32 sw_if_index,
+                           const ip6_address_t * link_local_addr);
 extern bool ip6_link_is_enabled (u32 sw_if_index);
 extern int ip6_link_disable (u32 sw_if_index);
 
 extern const ip6_address_t *ip6_get_link_local_address (u32 sw_if_index);
 
-extern int ip6_set_link_local_address (u32 sw_if_index,
+extern int ip6_link_set_local_address (u32 sw_if_index,
                                       const ip6_address_t * address);
 extern adj_index_t ip6_link_get_mcast_adj (u32 sw_if_index);
 
index 5c0784f..3bc46fe 100644 (file)
@@ -111,7 +111,7 @@ static void
   VALIDATE_SW_IF_INDEX (mp);
 
   rv = ((mp->enable == 1) ?
-       ip6_link_enable (ntohl (mp->sw_if_index)) :
+       ip6_link_enable (ntohl (mp->sw_if_index), NULL) :
        ip6_link_disable (ntohl (mp->sw_if_index)));
 
   BAD_SW_IF_INDEX_LABEL;
@@ -1262,7 +1262,7 @@ static void
 
   ip6_address_decode (mp->ip, &ip);
 
-  rv = ip6_set_link_local_address (ntohl (mp->sw_if_index), &ip);
+  rv = ip6_link_set_local_address (ntohl (mp->sw_if_index), &ip);
 
   BAD_SW_IF_INDEX_LABEL;
   REPLY_MACRO (VL_API_SW_INTERFACE_IP6_SET_LINK_LOCAL_ADDRESS_REPLY);
index ee7c323..9c5d2b9 100644 (file)
@@ -428,7 +428,7 @@ rd_cp_process (vlib_main_t * vm, vlib_node_runtime_t * rt, vlib_frame_t * f)
                 u32 sw_if_index = slaac_address->sw_if_index;
                 remove_slaac_address (vm, slaac_address);
                 /* make sure ip6 stays enabled */
-                ip6_link_enable (sw_if_index);
+                ip6_link_enable (sw_if_index, NULL);
               }
           }));
           pool_foreach_index (index, rm->default_route_pool,
@@ -504,7 +504,7 @@ rd_cp_set_address_autoconfig (u32 sw_if_index,
   if_config = &rm->config_by_sw_if_index[sw_if_index];
 
   if (!if_config->enabled && enable)
-    ip6_link_enable (sw_if_index);
+    ip6_link_enable (sw_if_index, NULL);
 
   if ((!if_config->enabled && enable)
       || (!if_config->install_default_routes && install_default_routes))
index 990b53e..c92ebb5 100644 (file)
@@ -25,7 +25,8 @@ from vpp_ip import DpoProto
 from vpp_ip_route import VppIpRoute, VppRoutePath, find_route, VppIpMRoute, \
     VppMRoutePath, MRouteItfFlags, MRouteEntryFlags, VppMplsIpBind, \
     VppMplsRoute, VppMplsTable, VppIpTable, FibPathType, FibPathProto, \
-    VppIpInterfaceAddress, find_route_in_dump, find_mroute_in_dump
+    VppIpInterfaceAddress, find_route_in_dump, find_mroute_in_dump, \
+    VppIp6LinkLocalAddress
 from vpp_neighbor import find_nbr, VppNeighbor
 from vpp_pg_interface import is_ipv6_misc
 from vpp_sub_interface import VppSubInterface, VppDot1QSubint
@@ -2442,7 +2443,6 @@ class TestIPReplace(VppTestCase):
         for i in self.pg_interfaces:
             i.admin_up()
             i.config_ip6()
-            i.resolve_arp()
             i.generate_remote_hosts(2)
             self.tables.append(VppIpTable(self, table_id,
                                           True).add_vpp_config())
@@ -2452,7 +2452,7 @@ class TestIPReplace(VppTestCase):
         super(TestIPReplace, self).tearDown()
         for i in self.pg_interfaces:
             i.admin_down()
-            i.unconfig_ip4()
+            i.unconfig_ip6()
 
     def test_replace(self):
         """ IP Table Replace """
@@ -2721,5 +2721,93 @@ class TestIP6Replace(VppTestCase):
             self.assertTrue(pfx.query_vpp_config())
 
 
+class TestIP6LinkLocal(VppTestCase):
+    """ IPv6 Link Local """
+
+    @classmethod
+    def setUpClass(cls):
+        super(TestIP6LinkLocal, cls).setUpClass()
+
+    @classmethod
+    def tearDownClass(cls):
+        super(TestIP6LinkLocal, cls).tearDownClass()
+
+    def setUp(self):
+        super(TestIP6LinkLocal, self).setUp()
+
+        self.create_pg_interfaces(range(2))
+
+        for i in self.pg_interfaces:
+            i.admin_up()
+
+    def tearDown(self):
+        super(TestIP6LinkLocal, self).tearDown()
+        for i in self.pg_interfaces:
+            i.admin_down()
+
+    def test_ip6_ll(self):
+        """ IPv6 Link Local """
+
+        #
+        # two APIs to add a link local address.
+        #   1 - just like any other prefix
+        #   2 - with the special set LL API
+        #
+
+        #
+        # First with the API to set a 'normal' prefix
+        #
+        ll1 = "fe80:1::1"
+        ll2 = "fe80:2::2"
+        ll3 = "fe80:3::3"
+
+        VppIpInterfaceAddress(self, self.pg0, ll1, 128).add_vpp_config()
+
+        #
+        # should be able to ping the ll
+        #
+        p_echo_request_1 = (Ether(src=self.pg0.remote_mac,
+                                  dst=self.pg0.local_mac) /
+                            IPv6(src=ll2,
+                                 dst=ll1) /
+                            ICMPv6EchoRequest())
+
+        self.send_and_expect(self.pg0, [p_echo_request_1], self.pg0)
+
+        #
+        # change the link-local on pg0
+        #
+        v_ll3 = VppIpInterfaceAddress(self, self.pg0,
+                                      ll3, 128).add_vpp_config()
+
+        p_echo_request_3 = (Ether(src=self.pg0.remote_mac,
+                                  dst=self.pg0.local_mac) /
+                            IPv6(src=ll2,
+                                 dst=ll3) /
+                            ICMPv6EchoRequest())
+
+        self.send_and_expect(self.pg0, [p_echo_request_3], self.pg0)
+
+        #
+        # set a normal v6 prefix on the link
+        #
+        self.pg0.config_ip6()
+
+        self.send_and_expect(self.pg0, [p_echo_request_3], self.pg0)
+
+        # the link-local cannot be removed
+        with self.vapi.assert_negative_api_retval():
+            v_ll3.remove_vpp_config()
+
+        #
+        # Use the specific link-local API on pg1
+        #
+        VppIp6LinkLocalAddress(self, self.pg1, ll1).add_vpp_config()
+        self.send_and_expect(self.pg1, [p_echo_request_1], self.pg1)
+
+        VppIp6LinkLocalAddress(self, self.pg1, ll3).add_vpp_config()
+        self.send_and_expect(self.pg1, [p_echo_request_3], self.pg1)
+
+
 if __name__ == '__main__':
     unittest.main(testRunner=VppTestRunner)
index d871f7a..4bb6c93 100644 (file)
@@ -303,6 +303,31 @@ class VppIpInterfaceAddress(VppObject):
                                           self.prefix)
 
 
+class VppIp6LinkLocalAddress(VppObject):
+
+    def __init__(self, test, intf, addr):
+        self._test = test
+        self.intf = intf
+        self.addr = addr
+
+    def add_vpp_config(self):
+        self._test.vapi.sw_interface_ip6_set_link_local_address(
+            sw_if_index=self.intf.sw_if_index, ip=self.addr)
+        self._test.registry.register(self, self._test.logger)
+        return self
+
+    def remove_vpp_config(self):
+        # link locals can't be removed, only changed
+        pass
+
+    def query_vpp_config(self):
+        # no API to query
+        return False
+
+    def object_id(self):
+        return "ip6-link-local-%s-%s" % (self.intf, self.addr)
+
+
 class VppIpInterfaceBind(VppObject):
 
     def __init__(self, test, intf, table):