From ec40a7d2bce4bba67af3b3d971547d40e90fdf97 Mon Sep 17 00:00:00 2001 From: Neale Ranns Date: Thu, 23 Apr 2020 07:36:12 +0000 Subject: ip: Setting the Link-Local address from the API enables IPv6 on the interface Type: fix Signed-off-by: Neale Ranns Change-Id: I0b7c189006e30a357cd6be4f3c9c61fded4157cb --- src/plugins/dhcp/dhcp6_ia_na_client_cp.c | 4 +- src/plugins/dhcp/dhcp6_pd_client_cp.c | 2 +- src/vnet/ip/ip6_forward.c | 6 +- src/vnet/ip/ip6_link.c | 16 +++--- src/vnet/ip/ip6_link.h | 5 +- src/vnet/ip/ip_api.c | 4 +- src/vnet/ip6-nd/rd_cp.c | 4 +- test/test_ip6.py | 94 +++++++++++++++++++++++++++++++- test/vpp_ip_route.py | 25 +++++++++ 9 files changed, 139 insertions(+), 21 deletions(-) diff --git a/src/plugins/dhcp/dhcp6_ia_na_client_cp.c b/src/plugins/dhcp/dhcp6_ia_na_client_cp.c index 4d59f607fe1..975a7e09eed 100644 --- a/src/plugins/dhcp/dhcp6_ia_na_client_cp.c +++ b/src/plugins/dhcp/dhcp6_ia_na_client_cp.c @@ -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); } diff --git a/src/plugins/dhcp/dhcp6_pd_client_cp.c b/src/plugins/dhcp/dhcp6_pd_client_cp.c index 077b4a38639..2328dfda3f5 100644 --- a/src/plugins/dhcp/dhcp6_pd_client_cp.c +++ b/src/plugins/dhcp/dhcp6_pd_client_cp.c @@ -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); } diff --git a/src/vnet/ip/ip6_forward.c b/src/vnet/ip/ip6_forward.c index 0325627a1ef..0a455351ad2 100644 --- a/src/vnet/ip/ip6_forward.c +++ b/src/vnet/ip/ip6_forward.c @@ -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)) diff --git a/src/vnet/ip/ip6_link.c b/src/vnet/ip/ip6_link.c index 35b718e6dcb..d2142f9aced 100644 --- a/src/vnet/ip/ip6_link.c +++ b/src/vnet/ip/ip6_link.c @@ -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 diff --git a/src/vnet/ip/ip6_link.h b/src/vnet/ip/ip6_link.h index 01506bb4765..a9dfa5edcb0 100644 --- a/src/vnet/ip/ip6_link.h +++ b/src/vnet/ip/ip6_link.h @@ -19,13 +19,14 @@ * 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); diff --git a/src/vnet/ip/ip_api.c b/src/vnet/ip/ip_api.c index 5c0784f9cb3..3bc46fee59b 100644 --- a/src/vnet/ip/ip_api.c +++ b/src/vnet/ip/ip_api.c @@ -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); diff --git a/src/vnet/ip6-nd/rd_cp.c b/src/vnet/ip6-nd/rd_cp.c index ee7c323f8b1..9c5d2b9aaf0 100644 --- a/src/vnet/ip6-nd/rd_cp.c +++ b/src/vnet/ip6-nd/rd_cp.c @@ -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)) diff --git a/test/test_ip6.py b/test/test_ip6.py index 990b53ec035..c92ebb5852a 100644 --- a/test/test_ip6.py +++ b/test/test_ip6.py @@ -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) diff --git a/test/vpp_ip_route.py b/test/vpp_ip_route.py index d871f7a0b11..4bb6c9320d3 100644 --- a/test/vpp_ip_route.py +++ b/test/vpp_ip_route.py @@ -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): -- cgit 1.2.3-korg