ip: allow the 'ip6 enable' on tunnel interface types 03/32403/8
authorNeale Ranns <neale@graphiant.com>
Thu, 20 May 2021 16:28:12 +0000 (16:28 +0000)
committerBeno�t Ganne <bganne@cisco.com>
Thu, 27 May 2021 12:06:57 +0000 (12:06 +0000)
Type: feature

This was limited to HW interface types (for historical reason AFAICT)

Signed-off-by: Neale Ranns <neale@graphiant.com>
Change-Id: I3785a356ae31722fa60d84f64ec9aa53ebdd615f

src/vnet/ip/ip6_link.c
test/test_ip6.py

index 0527b2f..afa9d8e 100644 (file)
@@ -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 (&ethernet_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 (&ethernet_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);
 }
 
index 7635a01..6eabf5a 100644 (file)
@@ -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 """