From dfef64b4cd99a610159a790faa618584157edc63 Mon Sep 17 00:00:00 2001 From: Neale Ranns Date: Thu, 20 May 2021 16:28:12 +0000 Subject: [PATCH] ip: allow the 'ip6 enable' on tunnel interface types Type: feature This was limited to HW interface types (for historical reason AFAICT) Signed-off-by: Neale Ranns Change-Id: I3785a356ae31722fa60d84f64ec9aa53ebdd615f --- src/vnet/ip/ip6_link.c | 46 ++++++++++++----------------- test/test_ip6.py | 80 ++++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 97 insertions(+), 29 deletions(-) diff --git a/src/vnet/ip/ip6_link.c b/src/vnet/ip/ip6_link.c index 0527b2ffc52..afa9d8e3ea9 100644 --- a/src/vnet/ip/ip6_link.c +++ b/src/vnet/ip/ip6_link.c @@ -155,43 +155,38 @@ ip6_link_enable (u32 sw_if_index, const ip6_address_t * link_local_addr) if (NULL == il) { - const vnet_sw_interface_t *sw, *sw_sup; + const vnet_sw_interface_t *sw_sup; const ethernet_interface_t *eth; vnet_main_t *vnm; + eth = NULL; vnm = vnet_get_main (); IP6_LINK_INFO ("enable: %U", format_vnet_sw_if_index_name, vnm, sw_if_index); sw_sup = vnet_get_sup_sw_interface (vnm, sw_if_index); - if (sw_sup->type != VNET_SW_INTERFACE_TYPE_HARDWARE) - { - rv = VNET_API_ERROR_UNSUPPORTED; - goto out; - } - - eth = ethernet_get_interface (ðernet_main, sw_sup->hw_if_index); - - if (NULL == eth) - { - rv = VNET_API_ERROR_UNSUPPORTED; - goto out; - } - vec_validate (ip6_links, sw_if_index); il = &ip6_links[sw_if_index]; il->il_locks = 0; il->il_sw_if_index = sw_if_index; + il->il_mcast_adj = ADJ_INDEX_INVALID; - sw = vnet_get_sup_sw_interface (vnm, sw_if_index); + if (sw_sup->type == VNET_SW_INTERFACE_TYPE_HARDWARE) + eth = ethernet_get_interface (ðernet_main, sw_sup->hw_if_index); + /* use a user provided LL address if given */ 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) + + /* generate from ethernet MAC */ + if (ip6_address_is_zero (&il->il_ll_addr) && NULL != eth) + ip6_link_local_address_from_mac (&il->il_ll_addr, + eth->address.mac.bytes); + + /* choose a random address */ + if (ip6_address_is_zero (&il->il_ll_addr)) { il->il_ll_addr.as_u64[0] = clib_host_to_net_u64 (0xFE80000000000000ULL); @@ -202,11 +197,6 @@ ip6_link_enable (u32 sw_if_index, const ip6_address_t * link_local_addr) /* clear u bit */ il->il_ll_addr.as_u8[8] &= 0xfd; } - else - { - ip6_link_local_address_from_mac (&il->il_ll_addr, - eth->address.mac.bytes); - } { ip6_ll_prefix_t ilp = { @@ -221,8 +211,11 @@ ip6_link_enable (u32 sw_if_index, const ip6_address_t * link_local_addr) ip6_mfib_interface_enable_disable (sw_if_index, 1); ip6_sw_interface_enable_disable (sw_if_index, 1); - il->il_mcast_adj = adj_mcast_add_or_lock (FIB_PROTOCOL_IP6, - VNET_LINK_IP6, sw_if_index); + /* only ehternet interfaces support MLD and RA, which use the mcast adj + */ + if (NULL != eth) + il->il_mcast_adj = + adj_mcast_add_or_lock (FIB_PROTOCOL_IP6, VNET_LINK_IP6, sw_if_index); /* inform all register clients */ ip6_link_delegate_id_t id; @@ -241,7 +234,6 @@ ip6_link_enable (u32 sw_if_index, const ip6_address_t * link_local_addr) il->il_locks++; -out: return (rv); } diff --git a/test/test_ip6.py b/test/test_ip6.py index 7635a01c7ce..6eabf5af0ec 100644 --- a/test/test_ip6.py +++ b/test/test_ip6.py @@ -7,14 +7,14 @@ import unittest from parameterized import parameterized import scapy.compat import scapy.layers.inet6 as inet6 -from scapy.layers.inet import UDP +from scapy.layers.inet import UDP, IP from scapy.contrib.mpls import MPLS from scapy.layers.inet6 import IPv6, ICMPv6ND_NS, ICMPv6ND_RS, \ ICMPv6ND_RA, ICMPv6NDOptMTU, ICMPv6NDOptSrcLLAddr, ICMPv6NDOptPrefixInfo, \ ICMPv6ND_NA, ICMPv6NDOptDstLLAddr, ICMPv6DestUnreach, icmp6types, \ ICMPv6TimeExceeded, ICMPv6EchoRequest, ICMPv6EchoReply, \ IPv6ExtHdrHopByHop, ICMPv6MLReport2, ICMPv6MLDMultAddrRec -from scapy.layers.l2 import Ether, Dot1Q +from scapy.layers.l2 import Ether, Dot1Q, GRE from scapy.packet import Raw from scapy.utils6 import in6_getnsma, in6_getnsmac, in6_ptop, in6_islladdr, \ in6_mactoifaceid @@ -35,6 +35,8 @@ from vpp_pg_interface import is_ipv6_misc from vpp_sub_interface import VppSubInterface, VppDot1QSubint from vpp_policer import VppPolicer, PolicerAction from ipaddress import IPv6Network, IPv6Address +from vpp_gre_interface import VppGreInterface +from vpp_teib import VppTeib AF_INET6 = socket.AF_INET6 @@ -3002,6 +3004,11 @@ class TestIP6LinkLocal(VppTestCase): ll2 = "fe80:2::2" ll3 = "fe80:3::3" + VppNeighbor(self, + self.pg0.sw_if_index, + self.pg0.remote_mac, + ll2).add_vpp_config() + VppIpInterfaceAddress(self, self.pg0, ll1, 128).add_vpp_config() # @@ -3049,6 +3056,75 @@ class TestIP6LinkLocal(VppTestCase): VppIp6LinkLocalAddress(self, self.pg1, ll3).add_vpp_config() self.send_and_expect(self.pg1, [p_echo_request_3], self.pg1) + def test_ip6_ll_p2p(self): + """ IPv6 Link Local P2P (GRE)""" + + self.pg0.config_ip4() + self.pg0.resolve_arp() + gre_if = VppGreInterface(self, + self.pg0.local_ip4, + self.pg0.remote_ip4).add_vpp_config() + gre_if.admin_up() + + ll1 = "fe80:1::1" + ll2 = "fe80:2::2" + + VppIpInterfaceAddress(self, gre_if, ll1, 128).add_vpp_config() + + self.logger.info(self.vapi.cli("sh ip6-ll gre0 fe80:2::2")) + + p_echo_request_1 = (Ether(src=self.pg0.remote_mac, + dst=self.pg0.local_mac) / + IP(src=self.pg0.remote_ip4, + dst=self.pg0.local_ip4) / + GRE() / + IPv6(src=ll2, dst=ll1) / + ICMPv6EchoRequest()) + self.send_and_expect(self.pg0, [p_echo_request_1], self.pg0) + + self.pg0.unconfig_ip4() + gre_if.remove_vpp_config() + + def test_ip6_ll_p2mp(self): + """ IPv6 Link Local P2MP (GRE)""" + + self.pg0.config_ip4() + self.pg0.resolve_arp() + + gre_if = VppGreInterface( + self, + self.pg0.local_ip4, + "0.0.0.0", + mode=(VppEnum.vl_api_tunnel_mode_t. + TUNNEL_API_MODE_MP)).add_vpp_config() + gre_if.admin_up() + + ll1 = "fe80:1::1" + ll2 = "fe80:2::2" + + VppIpInterfaceAddress(self, gre_if, ll1, 128).add_vpp_config() + + p_echo_request_1 = (Ether(src=self.pg0.remote_mac, + dst=self.pg0.local_mac) / + IP(src=self.pg0.remote_ip4, + dst=self.pg0.local_ip4) / + GRE() / + IPv6(src=ll2, dst=ll1) / + ICMPv6EchoRequest()) + + # no route back at this point + self.send_and_assert_no_replies(self.pg0, [p_echo_request_1]) + + # add teib entry for the peer + teib = VppTeib(self, gre_if, ll2, self.pg0.remote_ip4) + teib.add_vpp_config() + + self.logger.info(self.vapi.cli("sh ip6-ll gre0 %s" % ll2)) + self.send_and_expect(self.pg0, [p_echo_request_1], self.pg0) + + # teardown + self.pg0.unconfig_ip4() + class TestIPv6PathMTU(VppTestCase): """ IPv6 Path MTU """ -- 2.16.6