L2: no-flood interface type in the Bridge-Domain 94/11594/4
authorNeale Ranns <neale.ranns@cisco.com>
Mon, 9 Apr 2018 08:53:01 +0000 (01:53 -0700)
committerJohn Lo <loj@cisco.com>
Mon, 9 Apr 2018 17:34:09 +0000 (17:34 +0000)
Change-Id: I50ff0cacf88182f8e0be19840c50f4954de586e2
Signed-off-by: Neale Ranns <neale.ranns@cisco.com>
src/vnet/ethernet/interface.c
src/vnet/interface.h
src/vnet/l2/l2_bd.c
src/vnet/l2/l2_bd.h
src/vnet/l2/l2_input.c

index a29302b..2ed20e1 100644 (file)
@@ -621,6 +621,10 @@ vnet_create_loopback_interface (u32 * sw_if_indexp, u8 * mac_address,
   {
     vnet_sw_interface_t *si = vnet_get_hw_sw_interface (vnm, hw_if_index);
     *sw_if_indexp = si->sw_if_index;
+
+    /* By default don't flood to loopbacks, as packets just keep
+     * coming back ... If this loopback becomes a BVI, we'll change it */
+    si->flood_class = VNET_FLOOD_CLASS_NO_FLOOD;
   }
 
   return 0;
index 6a140d2..c8cda6b 100644 (file)
@@ -597,11 +597,15 @@ typedef struct
 
 typedef enum
 {
+  /* THe BVI interface */
+  VNET_FLOOD_CLASS_BVI,
   /* Always flood */
   VNET_FLOOD_CLASS_NORMAL,
   VNET_FLOOD_CLASS_TUNNEL_MASTER,
   /* Does not flood when tunnel master is in the same L2 BD */
-  VNET_FLOOD_CLASS_TUNNEL_NORMAL
+  VNET_FLOOD_CLASS_TUNNEL_NORMAL,
+  /* Never flood to this type */
+  VNET_FLOOD_CLASS_NO_FLOOD,
 } vnet_flood_class_t;
 
 /* Software-interface.  This corresponds to a Ethernet VLAN, ATM vc, a
index b1abb4c..7c8aef1 100644 (file)
@@ -128,38 +128,46 @@ bd_delete (bd_main_t * bdm, u32 bd_index)
 static void
 update_flood_count (l2_bridge_domain_t * bd_config)
 {
-  bd_config->flood_count = vec_len (bd_config->members) -
-    (bd_config->tun_master_count ? bd_config->tun_normal_count : 0);
+  bd_config->flood_count = (vec_len (bd_config->members) -
+                           (bd_config->tun_master_count ?
+                            bd_config->tun_normal_count : 0));
+  bd_config->flood_count -= bd_config->no_flood_count;
 }
 
 void
 bd_add_member (l2_bridge_domain_t * bd_config, l2_flood_member_t * member)
 {
-  u32 ix;
+  u32 ix = 0;
   vnet_sw_interface_t *sw_if = vnet_get_sw_interface
     (vnet_get_main (), member->sw_if_index);
 
   /*
    * Add one element to the vector
-   * vector is ordered [ bvi, normal/tun_masters..., tun_normals... ]
+   * vector is ordered [ bvi, normal/tun_masters..., tun_normals... no_flood]
    * When flooding, the bvi interface (if present) must be the last member
    * processed due to how BVI processing can change the packet. To enable
    * this order, we make the bvi interface the first in the vector and
-   * flooding walks the vector in reverse.
+   * flooding walks the vector in reverse. The flood-count determines where
+   * in the member list to start the walk from.
    */
   switch (sw_if->flood_class)
     {
+    case VNET_FLOOD_CLASS_NO_FLOOD:
+      bd_config->no_flood_count++;
+      ix = vec_len (bd_config->members);
+      break;
+    case VNET_FLOOD_CLASS_BVI:
+      ix = 0;
+      break;
     case VNET_FLOOD_CLASS_TUNNEL_MASTER:
       bd_config->tun_master_count++;
       /* Fall through */
-    default:
-      /* Fall through */
     case VNET_FLOOD_CLASS_NORMAL:
-      ix = (member->flags & L2_FLOOD_MEMBER_BVI) ? 0 :
-       vec_len (bd_config->members) - bd_config->tun_normal_count;
+      ix = (vec_len (bd_config->members) -
+           bd_config->tun_normal_count - bd_config->no_flood_count);
       break;
     case VNET_FLOOD_CLASS_TUNNEL_NORMAL:
-      ix = vec_len (bd_config->members);
+      ix = (vec_len (bd_config->members) - bd_config->no_flood_count);
       bd_config->tun_normal_count++;
       break;
     }
index fd34ae6..ffc7533 100644 (file)
@@ -78,6 +78,9 @@ typedef struct
   /* Tunnels (Unicast vxlan) are flooded if there are no masters */
   u32 tun_normal_count;
 
+  /* Interface on which packets are not flooded */
+  u32 no_flood_count;
+
   /* hash ip4/ip6 -> mac for arp/nd termination */
   uword *mac_by_ip4;
   uword *mac_by_ip6;
index 5d16b1d..c2df5ac 100644 (file)
@@ -579,6 +579,8 @@ set_int_l2_mode (vlib_main_t * vm, vnet_main_t * vnet_main, /*           */
       /* undo any BVI-related config */
       if (bd_config->bvi_sw_if_index == sw_if_index)
        {
+         vnet_sw_interface_t *si;
+
          bd_config->bvi_sw_if_index = ~0;
          config->bvi = 0;
 
@@ -591,6 +593,10 @@ set_int_l2_mode (vlib_main_t * vm, vnet_main_t * vnet_main,        /*           */
                                                "ethernet-input",
                                                VNET_SIMULATED_ETHERNET_TX_NEXT_ETHERNET_INPUT);
          ASSERT (slot == VNET_SIMULATED_ETHERNET_TX_NEXT_ETHERNET_INPUT);
+
+         /* since this is a no longer BVI interface do not to flood to it */
+         si = vnet_get_sw_interface (vnm, sw_if_index);
+         si->flood_class = VNET_FLOOD_CLASS_NO_FLOOD;
        }
 
       /* Clear MACs learned on the interface */
@@ -673,6 +679,8 @@ set_int_l2_mode (vlib_main_t * vm, vnet_main_t * vnet_main, /*           */
          /* Do BVI interface initializations */
          if (bvi)
            {
+             vnet_sw_interface_t *si;
+
              /* ensure BD has no bvi interface (or replace that one with this??) */
              if (bd_config->bvi_sw_if_index != ~0)
                {
@@ -693,6 +701,10 @@ set_int_l2_mode (vlib_main_t * vm, vnet_main_t * vnet_main,        /*           */
                                                    "l2-input",
                                                    VNET_SIMULATED_ETHERNET_TX_NEXT_ETHERNET_INPUT);
              ASSERT (slot == VNET_SIMULATED_ETHERNET_TX_NEXT_ETHERNET_INPUT);
+
+             /* since this is a BVI interface we want to flood to it */
+             si = vnet_get_sw_interface (vnm, sw_if_index);
+             si->flood_class = VNET_FLOOD_CLASS_BVI;
            }
 
          /* Add interface to bridge-domain flood vector */