l2: Separating scan-delay and learn-limit into a separate API from want_l2_macs_events 55/30655/6
authorJerome Tollet <jtollet@cisco.com>
Thu, 7 Jan 2021 11:44:17 +0000 (12:44 +0100)
committerJohn Lo <loj@cisco.com>
Fri, 8 Jan 2021 21:46:37 +0000 (21:46 +0000)
Type: feature

Signed-off-by: Jerome Tollet <jtollet@cisco.com>
Change-Id: I6de6dae7da4ec1001e2811975a9b67acfc1a148c

src/vnet/l2/l2.api
src/vnet/l2/l2_api.c
src/vnet/l2/l2_fib.c
test/test_l2_fib.py
test/vpp_papi_provider.py

index ef83082..b0ac23f 100644 (file)
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-option version = "3.0.0";
+option version = "3.1.0";
 
 import "vnet/ip/ip_types.api";
 import "vnet/ethernet/ethernet_types.api";
@@ -151,6 +151,7 @@ autoreply define l2fib_add_del
 */
 autoreply define want_l2_macs_events
 {
+  option deprecated;
   u32 client_index;
   u32 context;
   u32 learn_limit [default=1000];
@@ -160,6 +161,35 @@ autoreply define want_l2_macs_events
   u32 pid;
 };
 
+/** \brief Register to receive L2 MAC events for learned and aged MAC
+    @param client_index - opaque cookie to identify the sender
+    @param context - sender context, to match reply w/ request
+    @param max_macs_in_event - in units of 10 mac entries
+    @param enable_disable - 1 => register for MAC events, 0 => cancel registration
+    @param pid - sender's pid
+*/
+autoreply define want_l2_macs_events2
+{
+  u32 client_index;
+  u32 context;
+  u8  max_macs_in_event [default=10];
+  bool enable_disable [default=true];
+  u32 pid;
+};
+
+/** \brief set l2 table scan delay
+    @param client_index - opaque cookie to identify the sender
+    @param context - sender context, to match reply w/ request
+    @param scan_delay - event scan delay in 10 msec unit
+*/
+autoreply define l2fib_set_scan_delay
+{
+  u32 client_index;
+  u32 context;
+  u16 scan_delay [default=10];
+};
+
+
 enum mac_event_action
 {
        MAC_EVENT_ACTION_API_ADD = 0,
index 97b429d..85e9c31 100644 (file)
@@ -58,7 +58,9 @@
   _ (L2FIB_FLUSH_INT, l2fib_flush_int)                                        \
   _ (L2FIB_FLUSH_BD, l2fib_flush_bd)                                          \
   _ (L2FIB_ADD_DEL, l2fib_add_del)                                            \
+  _ (L2FIB_SET_SCAN_DELAY, l2fib_set_scan_delay)                              \
   _ (WANT_L2_MACS_EVENTS, want_l2_macs_events)                                \
+  _ (WANT_L2_MACS_EVENTS2, want_l2_macs_events2)                              \
   _ (L2_FLAGS, l2_flags)                                                      \
   _ (SW_INTERFACE_SET_L2_XCONNECT, sw_interface_set_l2_xconnect)              \
   _ (SW_INTERFACE_SET_L2_BRIDGE, sw_interface_set_l2_bridge)                  \
@@ -262,22 +264,18 @@ vl_api_l2fib_add_del_t_handler (vl_api_l2fib_add_del_t * mp)
 }
 
 static void
-vl_api_want_l2_macs_events_t_handler (vl_api_want_l2_macs_events_t * mp)
+vl_api_want_l2_macs_events2_t_handler (vl_api_want_l2_macs_events2_t *mp)
 {
   int rv = 0;
-  vl_api_want_l2_macs_events_reply_t *rmp;
+  vl_api_want_l2_macs_events2_reply_t *rmp;
   l2learn_main_t *lm = &l2learn_main;
   l2fib_main_t *fm = &l2fib_main;
   u32 pid = ntohl (mp->pid);
-  u32 learn_limit = ntohl (mp->learn_limit);
 
   if (mp->enable_disable)
     {
-      if (lm->client_pid == 0)
+      if ((lm->client_pid == 0) || (lm->client_pid == pid))
        {
-         lm->client_pid = pid;
-         lm->client_index = mp->client_index;
-
          if (mp->max_macs_in_event)
            fm->max_macs_in_event = mp->max_macs_in_event * 10;
          else
@@ -286,23 +284,58 @@ vl_api_want_l2_macs_events_t_handler (vl_api_want_l2_macs_events_t * mp)
              goto exit;
            }
 
-         if (mp->scan_delay)
-           fm->event_scan_delay = (f64) (mp->scan_delay) * 10e-3;
-         else
-           {
-             rv = VNET_API_ERROR_INVALID_VALUE;
-             goto exit;
-           }
+         /* if scan_delay was not set before */
+         if (fm->event_scan_delay == 0.0)
+           fm->event_scan_delay = (f64) (10) * 10e-3;
 
-         /* change learn limit and flush all learned MACs */
-         if (learn_limit && (learn_limit < L2LEARN_DEFAULT_LIMIT))
-           lm->global_learn_limit = learn_limit;
-         else
+         lm->client_pid = pid;
+         lm->client_index = mp->client_index;
+         l2fib_flush_all_mac (vlib_get_main ());
+       }
+      else if (lm->client_pid != pid)
+       {
+         rv = VNET_API_ERROR_L2_MACS_EVENT_CLINET_PRESENT;
+         goto exit;
+       }
+    }
+  else if (lm->client_pid)
+    {
+      lm->client_pid = 0;
+      lm->client_index = 0;
+    }
+
+exit:
+  REPLY_MACRO (VL_API_WANT_L2_MACS_EVENTS2_REPLY);
+}
+
+static void
+vl_api_want_l2_macs_events_t_handler (vl_api_want_l2_macs_events_t *mp)
+{
+  int rv = 0;
+  vl_api_want_l2_macs_events_reply_t *rmp;
+  l2learn_main_t *lm = &l2learn_main;
+  l2fib_main_t *fm = &l2fib_main;
+  u32 pid = ntohl (mp->pid);
+  u32 learn_limit = ntohl (mp->learn_limit);
+
+  if (mp->enable_disable)
+    {
+      if ((lm->client_pid == 0) || (lm->client_pid == pid))
+       {
+         if ((mp->max_macs_in_event == 0) || (mp->scan_delay == 0) ||
+             (learn_limit == 0) || (learn_limit > L2LEARN_DEFAULT_LIMIT))
            {
              rv = VNET_API_ERROR_INVALID_VALUE;
              goto exit;
            }
+         lm->client_pid = pid;
+         lm->client_index = mp->client_index;
 
+         fm->max_macs_in_event = mp->max_macs_in_event * 10;
+         fm->event_scan_delay = (f64) (mp->scan_delay) * 10e-3;
+
+         /* change learn limit and flush all learned MACs */
+         lm->global_learn_limit = learn_limit;
          l2fib_flush_all_mac (vlib_get_main ());
        }
       else if (lm->client_pid != pid)
@@ -315,7 +348,7 @@ vl_api_want_l2_macs_events_t_handler (vl_api_want_l2_macs_events_t * mp)
     {
       lm->client_pid = 0;
       lm->client_index = 0;
-      if (learn_limit && (learn_limit < L2LEARN_DEFAULT_LIMIT))
+      if (learn_limit && (learn_limit <= L2LEARN_DEFAULT_LIMIT))
        lm->global_learn_limit = learn_limit;
       else
        lm->global_learn_limit = L2LEARN_DEFAULT_LIMIT;
@@ -371,6 +404,29 @@ out:
   REPLY_MACRO (VL_API_L2FIB_FLUSH_BD_REPLY);
 }
 
+static void
+vl_api_l2fib_set_scan_delay_t_handler (vl_api_l2fib_set_scan_delay_t *mp)
+{
+  int rv = 0;
+  l2fib_main_t *fm = &l2fib_main;
+  vl_api_l2fib_set_scan_delay_reply_t *rmp;
+  u16 scan_delay = ntohs (mp->scan_delay);
+
+  if (mp->scan_delay)
+    {
+      fm->event_scan_delay = (f64) (scan_delay) *10e-3;
+      l2fib_flush_all_mac (vlib_get_main ());
+    }
+  else
+    {
+      rv = VNET_API_ERROR_INVALID_VALUE;
+      goto exit;
+    }
+
+exit:
+  REPLY_MACRO (VL_API_L2FIB_SET_SCAN_DELAY_REPLY);
+}
+
 static void
 vl_api_l2_flags_t_handler (vl_api_l2_flags_t * mp)
 {
index 82be6bc..4407cb5 100644 (file)
@@ -845,6 +845,36 @@ VLIB_CLI_COMMAND (l2fib_del_cli, static) = {
 };
 /* *INDENT-ON* */
 
+static clib_error_t *
+l2fib_set_scan_delay (vlib_main_t *vm, unformat_input_t *input,
+                     vlib_cli_command_t *cmd)
+{
+  clib_error_t *error = 0;
+  u32 scan_delay;
+  l2fib_main_t *fm = &l2fib_main;
+
+  if (!unformat (input, "%d", &scan_delay))
+    {
+      error = clib_error_return (0, "expecting delay but got `%U'",
+                                format_unformat_error, input);
+      goto done;
+    }
+  fm->event_scan_delay = (f64) (scan_delay) *10e-3;
+  l2fib_flush_all_mac (vlib_get_main ());
+done:
+  return error;
+}
+
+/*?
+ * This command set scan delay (in 1/10s unit)
+ *
+?*/
+VLIB_CLI_COMMAND (l2fib_set_scan_delay_cli, static) = {
+  .path = "set l2fib scan-delay",
+  .short_help = "set l2fib scan-delay <delay>",
+  .function = l2fib_set_scan_delay,
+};
+
 /**
     Kick off ager to scan MACs to age/delete MAC entries
 */
index 51c1747..9ce289f 100644 (file)
@@ -498,6 +498,29 @@ class TestL2fib(VppTestCase):
         self.vapi.want_l2_macs_events(enable_disable=0)
         self.assertEqual(len(learned_macs ^ macs), 0)
 
+    def test_l2_fib_mac_learn_evs2(self):
+        """ L2 FIB - mac learning events using want_l2_macs_events2
+        """
+        bd1 = 1
+        hosts = self.create_hosts(10, subnet=39)
+
+        self.vapi.l2fib_set_scan_delay(scan_delay=10)
+        self.vapi.want_l2_macs_events2()
+        self.sleep(1)
+        self.learn_hosts(bd1, hosts)
+
+        self.sleep(1)
+        self.logger.info(self.vapi.ppcli("show l2fib"))
+        evs = self.vapi.collect_events()
+        action = VppEnum.vl_api_mac_event_action_t.MAC_EVENT_ACTION_API_ADD
+        learned_macs = {
+            e.mac[i].mac_addr.packed for e in evs for i in range(e.n_macs)
+            if e.mac[i].action == action}
+        macs = {h.bin_mac for swif in self.bd_ifs(bd1)
+                for h in hosts[self.pg_interfaces[swif].sw_if_index]}
+        self.vapi.want_l2_macs_events2(enable_disable=0)
+        self.assertEqual(len(learned_macs ^ macs), 0)
+
     def test_l2_fib_macs_learn_max(self):
         """ L2 FIB - mac learning max macs in event
         """
@@ -525,6 +548,35 @@ class TestL2fib(VppTestCase):
             self.assertLess(len(e), ev_macs * 10)
         self.assertEqual(len(learned_macs ^ macs), 0)
 
+    def test_l2_fib_macs_learn_max2(self):
+        """ L2 FIB - mac learning max macs in event using want_l2_macs_events2
+        """
+        bd1 = 1
+        hosts = self.create_hosts(10, subnet=40)
+
+        ev_macs = 1
+        self.vapi.l2fib_set_scan_delay(scan_delay=10)
+        self.vapi.want_l2_macs_events2(max_macs_in_event=ev_macs)
+        self.sleep(1)
+        self.learn_hosts(bd1, hosts)
+
+        self.sleep(1)
+        self.logger.info(self.vapi.ppcli("show l2fib"))
+        evs = self.vapi.collect_events()
+        self.vapi.want_l2_macs_events2(enable_disable=0)
+
+        self.assertGreater(len(evs), 0)
+        action = VppEnum.vl_api_mac_event_action_t.MAC_EVENT_ACTION_API_ADD
+        learned_macs = {
+            e.mac[i].mac_addr.packed for e in evs for i in range(e.n_macs)
+            if e.mac[i].action == action}
+        macs = {h.bin_mac for swif in self.bd_ifs(bd1)
+                for h in hosts[self.pg_interfaces[swif].sw_if_index]}
+
+        for e in evs:
+            self.assertLess(len(e), ev_macs * 10)
+        self.assertEqual(len(learned_macs ^ macs), 0)
+
 
 if __name__ == '__main__':
     unittest.main(testRunner=VppTestRunner)
index d1a4eaf..c5e8ff0 100644 (file)
@@ -104,6 +104,7 @@ defaultmapping = {
     'want_igmp_events': {'enable': 1, },
     'want_interface_events': {'enable_disable': 1, },
     'want_l2_macs_events': {'enable_disable': 1, 'pid': os.getpid(), },
+    'want_l2_macs_events2': {'enable_disable': 1, 'pid': os.getpid(), },
 }