summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/plugins/dhcp/dhcp6_ia_na_client_cp.c4
-rw-r--r--src/plugins/dhcp/dhcp6_pd_client_cp.c2
-rw-r--r--src/vnet/ip/ip6_forward.c6
-rw-r--r--src/vnet/ip/ip6_link.c16
-rw-r--r--src/vnet/ip/ip6_link.h5
-rw-r--r--src/vnet/ip/ip_api.c4
-rw-r--r--src/vnet/ip6-nd/rd_cp.c4
-rw-r--r--test/test_ip6.py94
-rw-r--r--test/vpp_ip_route.py25
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):