LCOV - code coverage report
Current view: top level - plugins/mactime - mactime.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 20 326 6.1 %
Date: 2023-07-05 22:20:52 Functions: 16 27 59.3 %

          Line data    Source code
       1             : /*
       2             :  * mactime.c - time-based src mac address filtration
       3             :  *
       4             :  * Copyright (c) 2018 Cisco and/or its affiliates.
       5             :  * Licensed under the Apache License, Version 2.0 (the "License");
       6             :  * you may not use this file except in compliance with the License.
       7             :  * You may obtain a copy of the License at:
       8             :  *
       9             :  *     http://www.apache.org/licenses/LICENSE-2.0
      10             :  *
      11             :  * Unless required by applicable law or agreed to in writing, software
      12             :  * distributed under the License is distributed on an "AS IS" BASIS,
      13             :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      14             :  * See the License for the specific language governing permissions and
      15             :  * limitations under the License.
      16             :  */
      17             : 
      18             : #include <vnet/vnet.h>
      19             : #include <vnet/plugin/plugin.h>
      20             : #include <mactime/mactime.h>
      21             : 
      22             : #include <vlibapi/api.h>
      23             : #include <vlibmemory/api.h>
      24             : #include <vpp/app/version.h>
      25             : 
      26             : /* define message IDs */
      27             : #include <vnet/format_fns.h>
      28             : #include <mactime/mactime.api_enum.h>
      29             : #include <mactime/mactime.api_types.h>
      30             : 
      31             : 
      32             : #define REPLY_MSG_ID_BASE mm->msg_id_base
      33             : #include <vlibapi/api_helper_macros.h>
      34             : 
      35             : #include <vnet/ip-neighbor/ip_neighbor.h>
      36             : 
      37             : mactime_main_t mactime_main;
      38             : 
      39             : /** \file mactime.c
      40             :  * time-base src-mac filter device-input feature arc implementation
      41             :  */
      42             : 
      43             : static void
      44           0 : feature_init (mactime_main_t * mm)
      45             : {
      46           0 :   if (mm->feature_initialized == 0)
      47             :     {
      48             :       /* Create the lookup table */
      49           0 :       clib_bihash_init_8_8 (&mm->lookup_table, "mactime lookup table",
      50             :                             mm->lookup_table_num_buckets,
      51             :                             mm->lookup_table_memory_size);
      52           0 :       clib_timebase_init (&mm->timebase, mm->timezone_offset,
      53             :                           CLIB_TIMEBASE_DAYLIGHT_USA,
      54           0 :                           &(mm->vlib_main->clib_time));
      55           0 :       mm->allow_counters.name = "allow";
      56           0 :       mm->allow_counters.stat_segment_name = "/mactime/allow";
      57           0 :       mm->drop_counters.name = "drop";
      58           0 :       mm->drop_counters.stat_segment_name = "/mactime/drop";
      59           0 :       mm->feature_initialized = 1;
      60             :     }
      61           0 : }
      62             : 
      63             : /** Action function shared between message handler and debug CLI
      64             : */
      65             : int
      66           0 : mactime_enable_disable (mactime_main_t * mm, u32 sw_if_index,
      67             :                         int enable_disable)
      68             : {
      69             :   vnet_sw_interface_t *sw;
      70           0 :   int rv = 0;
      71             :   static u8 url_init_done;
      72             : 
      73           0 :   feature_init (mm);
      74             : 
      75             :   /* Utterly wrong? */
      76           0 :   if (pool_is_free_index (mm->vnet_main->interface_main.sw_interfaces,
      77             :                           sw_if_index))
      78           0 :     return VNET_API_ERROR_INVALID_SW_IF_INDEX;
      79             : 
      80             :   /* Not a physical port? */
      81           0 :   sw = vnet_get_sw_interface (mm->vnet_main, sw_if_index);
      82           0 :   if (sw->type != VNET_SW_INTERFACE_TYPE_HARDWARE)
      83           0 :     return VNET_API_ERROR_INVALID_SW_IF_INDEX;
      84             : 
      85           0 :   vnet_feature_enable_disable ("device-input", "mactime",
      86             :                                sw_if_index, enable_disable, 0, 0);
      87           0 :   vnet_feature_enable_disable ("interface-output", "mactime-tx",
      88             :                                sw_if_index, enable_disable, 0, 0);
      89           0 :   if (url_init_done == 0)
      90             :     {
      91           0 :       mactime_url_init (mm->vlib_main);
      92           0 :       url_init_done = 1;
      93             :     }
      94             : 
      95           0 :   return rv;
      96             : }
      97             : 
      98             : static clib_error_t *
      99           0 : mactime_enable_disable_command_fn (vlib_main_t * vm,
     100             :                                    unformat_input_t * input,
     101             :                                    vlib_cli_command_t * cmd)
     102             : {
     103           0 :   mactime_main_t *mm = &mactime_main;
     104           0 :   u32 sw_if_index = ~0;
     105           0 :   int enable_disable = 1;
     106             : 
     107             :   int rv;
     108             : 
     109           0 :   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
     110             :     {
     111           0 :       if (unformat (input, "disable"))
     112           0 :         enable_disable = 0;
     113           0 :       else if (unformat (input, "%U", unformat_vnet_sw_interface,
     114             :                          mm->vnet_main, &sw_if_index))
     115             :         ;
     116           0 :       else if (unformat (input, "sw_if_index %d", &sw_if_index))
     117             :         ;
     118             :       else
     119           0 :         break;
     120             :     }
     121             : 
     122           0 :   if (sw_if_index == ~0)
     123           0 :     return clib_error_return (0, "Please specify an interface...");
     124             : 
     125           0 :   rv = mactime_enable_disable (mm, sw_if_index, enable_disable);
     126             : 
     127           0 :   switch (rv)
     128             :     {
     129           0 :     case 0:
     130           0 :       break;
     131             : 
     132           0 :     case VNET_API_ERROR_INVALID_SW_IF_INDEX:
     133           0 :       return clib_error_return
     134             :         (0, "Invalid interface, only works on physical ports");
     135             :       break;
     136             : 
     137           0 :     default:
     138           0 :       return clib_error_return (0, "mactime_enable_disable returned %d", rv);
     139             :     }
     140           0 :   return 0;
     141             : }
     142             : 
     143             : /* *INDENT-OFF* */
     144      112149 : VLIB_CLI_COMMAND (mactime_enable_disable_command, static) =
     145             : {
     146             :   .path = "mactime enable-disable",
     147             :   .short_help =
     148             :   "mactime enable-disable <interface-name> [disable]",
     149             :   .function = mactime_enable_disable_command_fn,
     150             : };
     151             : /* *INDENT-ON* */
     152             : 
     153             : 
     154             : /** Enable / disable time-base src mac filtration on an interface
     155             :  */
     156             : 
     157           0 : static void vl_api_mactime_enable_disable_t_handler
     158             :   (vl_api_mactime_enable_disable_t * mp)
     159             : {
     160             :   vl_api_mactime_enable_disable_reply_t *rmp;
     161           0 :   mactime_main_t *mm = &mactime_main;
     162             :   int rv;
     163             : 
     164           0 :   VALIDATE_SW_IF_INDEX (mp);
     165             : 
     166           0 :   rv = mactime_enable_disable (mm, ntohl (mp->sw_if_index),
     167           0 :                                (int) (mp->enable_disable));
     168           0 :   BAD_SW_IF_INDEX_LABEL;
     169           0 :   REPLY_MACRO (VL_API_MACTIME_ENABLE_DISABLE_REPLY);
     170             : }
     171             : 
     172             : static void
     173           0 : vl_api_mactime_dump_t_handler (vl_api_mactime_dump_t * mp)
     174             : {
     175             :   vl_api_mactime_details_t *ep;
     176             :   vl_api_mactime_dump_reply_t *rmp;
     177             :   mactime_device_t *dev;
     178           0 :   mactime_main_t *mm = &mactime_main;
     179             :   vl_api_registration_t *rp;
     180           0 :   int rv = 0, i;
     181           0 :   u32 his_table_epoch = clib_net_to_host_u32 (mp->my_table_epoch);
     182             :   u32 message_size;
     183             :   u32 name_len;
     184             :   u32 nranges;
     185             : 
     186           0 :   rp = vl_api_client_index_to_registration (mp->client_index);
     187           0 :   if (rp == 0)
     188           0 :     return;
     189             : 
     190           0 :   if (his_table_epoch == mm->device_table_epoch)
     191             :     {
     192           0 :       rv = VNET_API_ERROR_NO_CHANGE;
     193           0 :       goto send_reply;
     194             :     }
     195             : 
     196             :   /* *INDENT-OFF* */
     197           0 :   pool_foreach (dev, mm->devices)
     198             :    {
     199           0 :     message_size = sizeof(*ep) + vec_len(dev->device_name) +
     200           0 :       vec_len(dev->ranges) * sizeof(ep->ranges[0]);
     201             : 
     202           0 :     ep = vl_msg_api_alloc (message_size);
     203           0 :     memset (ep, 0, message_size);
     204           0 :     ep->_vl_msg_id = clib_host_to_net_u16 (VL_API_MACTIME_DETAILS
     205           0 :                                            + mm->msg_id_base);
     206           0 :     ep->context = mp->context;
     207             :     /* Index is the key for the stats segment combined counters */
     208           0 :     ep->pool_index = clib_host_to_net_u32 (dev - mm->devices);
     209             : 
     210           0 :     clib_memcpy_fast (ep->mac_address, dev->mac_address,
     211             :                       sizeof (ep->mac_address));
     212           0 :     ep->data_quota = clib_host_to_net_u64 (dev->data_quota);
     213           0 :     ep->data_used_in_range = clib_host_to_net_u64 (dev->data_used_in_range);
     214           0 :     ep->flags = clib_host_to_net_u32 (dev->flags);
     215           0 :     nranges = vec_len (dev->ranges);
     216           0 :     ep->nranges = clib_host_to_net_u32 (nranges);
     217             : 
     218           0 :     for (i = 0; i < vec_len (dev->ranges); i++)
     219             :       {
     220           0 :         ep->ranges[i].start = dev->ranges[i].start;
     221           0 :         ep->ranges[i].end = dev->ranges[i].end;
     222             :       }
     223             : 
     224           0 :     name_len = vec_len (dev->device_name);
     225           0 :     name_len = (name_len < ARRAY_LEN(ep->device_name)) ?
     226             :       name_len : ARRAY_LEN(ep->device_name) - 1;
     227             : 
     228           0 :     clib_memcpy_fast (ep->device_name, dev->device_name,
     229             :                       name_len);
     230           0 :     ep->device_name [ARRAY_LEN(ep->device_name) -1] = 0;
     231           0 :     vl_api_send_msg (rp, (u8 *)ep);
     232             :   }
     233             :   /* *INDENT-OFF* */
     234             : 
     235           0 :  send_reply:
     236             :   /* *INDENT-OFF* */
     237           0 :   REPLY_MACRO2 (VL_API_MACTIME_DUMP_REPLY,
     238             :   ({
     239             :     rmp->table_epoch = clib_host_to_net_u32 (mm->device_table_epoch);
     240             :   }));
     241             :   /* *INDENT-ON* */
     242             : }
     243             : 
     244             : /** Create a lookup table entry for the indicated mac address
     245             :  */
     246             : void
     247           0 : mactime_send_create_entry_message (u8 * mac_address)
     248             : {
     249           0 :   mactime_main_t *mm = &mactime_main;
     250             :   api_main_t *am;
     251             :   vl_shmem_hdr_t *shmem_hdr;
     252             :   u8 *name;
     253             :   vl_api_mactime_add_del_range_t *mp;
     254             : 
     255           0 :   am = vlibapi_get_main ();
     256           0 :   shmem_hdr = am->shmem_hdr;
     257           0 :   mp = vl_msg_api_alloc_as_if_client (sizeof (*mp));
     258           0 :   clib_memset (mp, 0, sizeof (*mp));
     259           0 :   mp->_vl_msg_id = ntohs (VL_API_MACTIME_ADD_DEL_RANGE + mm->msg_id_base);
     260           0 :   name = format (0, "mac-%U", format_mac_address, mac_address);
     261             : 
     262           0 :   memcpy (mp->device_name, name, vec_len (name));
     263           0 :   memcpy (mp->mac_address, mac_address, sizeof (mp->mac_address));
     264             :   /* $$$ config: create allow / drop / range */
     265           0 :   mp->allow = 1;
     266           0 :   mp->is_add = 1;
     267           0 :   vl_msg_api_send_shmem (shmem_hdr->vl_input_queue, (u8 *) & mp);
     268           0 : }
     269             : 
     270             : /** Add or delete static / dynamic accept/drop configuration for a src mac
     271             :  */
     272             : 
     273           0 : static void vl_api_mactime_add_del_range_t_handler
     274             :   (vl_api_mactime_add_del_range_t * mp)
     275             : {
     276           0 :   mactime_main_t *mm = &mactime_main;
     277             :   vl_api_mactime_add_del_range_reply_t *rmp;
     278             :   mactime_device_t *dp;
     279             :   clib_bihash_kv_8_8_t kv;
     280           0 :   int found = 1;
     281           0 :   clib_bihash_8_8_t *lut = &mm->lookup_table;
     282             :   u64 data_quota;
     283           0 :   int i, rv = 0;
     284             : 
     285           0 :   feature_init (mm);
     286             : 
     287             :   /*
     288             :    * Change the table epoch. Skip 0 so clients can code my_table_epoch = 0
     289             :    * to receive a full dump.
     290             :    */
     291           0 :   mm->device_table_epoch++;
     292           0 :   if (PREDICT_FALSE (mm->device_table_epoch == 0))
     293           0 :     mm->device_table_epoch++;
     294             : 
     295           0 :   data_quota = clib_net_to_host_u64 (mp->data_quota);
     296             : 
     297           0 :   clib_memset (&kv, 0, sizeof (kv));
     298           0 :   memcpy (&kv.key, mp->mac_address, sizeof (mp->mac_address));
     299             : 
     300             :   /* See if we have a lookup table entry for this src mac address */
     301           0 :   if (clib_bihash_search_8_8 (lut, &kv, &kv) < 0)
     302           0 :     found = 0;
     303             : 
     304             :   /* Add an entry? */
     305           0 :   if (mp->is_add)
     306             :     {
     307             :       /* Create the device entry? */
     308           0 :       if (found == 0)
     309             :         {
     310           0 :           pool_get (mm->devices, dp);
     311           0 :           clib_memset (dp, 0, sizeof (*dp));
     312           0 :           vlib_validate_combined_counter (&mm->allow_counters,
     313           0 :                                           dp - mm->devices);
     314           0 :           vlib_zero_combined_counter (&mm->allow_counters, dp - mm->devices);
     315           0 :           vlib_validate_combined_counter (&mm->drop_counters,
     316           0 :                                           dp - mm->devices);
     317           0 :           vlib_zero_combined_counter (&mm->drop_counters, dp - mm->devices);
     318           0 :           mp->device_name[ARRAY_LEN (mp->device_name) - 1] = 0;
     319           0 :           dp->device_name = format (0, "%s%c", mp->device_name, 0);
     320           0 :           memcpy (dp->mac_address, mp->mac_address, sizeof (mp->mac_address));
     321           0 :           for (i = 0; i < clib_net_to_host_u32 (mp->count); i++)
     322             :             {
     323           0 :               clib_timebase_range_t _r, *r = &_r;
     324           0 :               r->start = mp->ranges[i].start;
     325           0 :               r->end = mp->ranges[i].end;
     326           0 :               vec_add1 (dp->ranges, r[0]);
     327             :             }
     328             :           /* If we found some time ranges */
     329           0 :           if (i)
     330             :             {
     331             :               /* Set allow/drop based on msg flags */
     332           0 :               if (mp->drop)
     333           0 :                 dp->flags = MACTIME_DEVICE_FLAG_DYNAMIC_DROP;
     334           0 :               if (mp->allow)
     335           0 :                 dp->flags = MACTIME_DEVICE_FLAG_DYNAMIC_ALLOW;
     336           0 :               if (mp->allow_quota)
     337           0 :                 dp->flags = MACTIME_DEVICE_FLAG_DYNAMIC_ALLOW_QUOTA;
     338             :             }
     339             :           else
     340             :             {
     341             :               /* no ranges, it's a static allow/drop */
     342           0 :               if (mp->drop)
     343           0 :                 dp->flags = MACTIME_DEVICE_FLAG_STATIC_DROP;
     344           0 :               if (mp->allow)
     345           0 :                 dp->flags = MACTIME_DEVICE_FLAG_STATIC_ALLOW;
     346             :             }
     347           0 :           if (mp->no_udp_10001)
     348           0 :             dp->flags |= MACTIME_DEVICE_FLAG_DROP_UDP_10001;
     349             : 
     350           0 :           dp->data_quota = data_quota;
     351             : 
     352             :           /* Add the hash table entry */
     353           0 :           kv.value = dp - mm->devices;
     354           0 :           clib_bihash_add_del_8_8 (lut, &kv, 1 /* is_add */ );
     355             :         }
     356             :       else                      /* add more ranges, flags, etc. */
     357             :         {
     358           0 :           dp = pool_elt_at_index (mm->devices, kv.value);
     359             : 
     360           0 :           for (i = 0; i < clib_net_to_host_u32 (mp->count); i++)
     361             :             {
     362           0 :               clib_timebase_range_t _r, *r = &_r;
     363           0 :               r->start = mp->ranges[i].start;
     364           0 :               r->end = mp->ranges[i].end;
     365           0 :               vec_add1 (dp->ranges, r[0]);
     366             :             }
     367             : 
     368           0 :           if (vec_len (dp->ranges))
     369             :             {
     370             :               /* Set allow/drop based on msg flags */
     371           0 :               if (mp->drop)
     372           0 :                 dp->flags = MACTIME_DEVICE_FLAG_DYNAMIC_DROP;
     373           0 :               if (mp->allow)
     374           0 :                 dp->flags = MACTIME_DEVICE_FLAG_DYNAMIC_ALLOW;
     375           0 :               if (mp->allow_quota)
     376           0 :                 dp->flags = MACTIME_DEVICE_FLAG_DYNAMIC_ALLOW_QUOTA;
     377             :             }
     378             :           else
     379             :             {
     380             :               /* no ranges, it's a static allow/drop */
     381           0 :               if (mp->drop)
     382           0 :                 dp->flags = MACTIME_DEVICE_FLAG_STATIC_DROP;
     383           0 :               if (mp->allow)
     384           0 :                 dp->flags = MACTIME_DEVICE_FLAG_STATIC_ALLOW;
     385             :             }
     386           0 :           if (mp->no_udp_10001)
     387           0 :             dp->flags |= MACTIME_DEVICE_FLAG_DROP_UDP_10001;
     388             : 
     389           0 :           dp->data_quota = data_quota;
     390             :         }
     391             :     }
     392             :   else                          /* delete case */
     393             :     {
     394           0 :       if (found == 0)
     395             :         {
     396           0 :           rv = VNET_API_ERROR_NO_SUCH_ENTRY;
     397           0 :           goto reply;
     398             :         }
     399             : 
     400             :       /* find the device entry */
     401           0 :       dp = pool_elt_at_index (mm->devices, kv.value);
     402             : 
     403             :       /* Remove it from the lookup table */
     404           0 :       clib_bihash_add_del_8_8 (lut, &kv, 0 /* is_add */ );
     405           0 :       vec_free (dp->ranges);
     406           0 :       pool_put (mm->devices, dp);
     407             :     }
     408             : 
     409           0 : reply:
     410           0 :   REPLY_MACRO (VL_API_MACTIME_ADD_DEL_RANGE_REPLY);
     411             : }
     412             : 
     413             : #include <mactime/mactime.api.c>
     414             : static clib_error_t *
     415         559 : mactime_init (vlib_main_t * vm)
     416             : {
     417         559 :   mactime_main_t *mm = &mactime_main;
     418             : 
     419         559 :   mm->vlib_main = vm;
     420         559 :   mm->vnet_main = vnet_get_main ();
     421             : 
     422             :   /* Ask for a correctly-sized block of API message decode slots */
     423         559 :   mm->msg_id_base = setup_message_id_table ();
     424             : 
     425         559 :   mm->lookup_table_num_buckets = MACTIME_NUM_BUCKETS;
     426         559 :   mm->lookup_table_memory_size = MACTIME_MEMORY_SIZE;
     427         559 :   mm->timezone_offset = -5;  /* US EST / EDT */
     428         559 :   return 0;
     429             : }
     430             : 
     431             : /* *INDENT-OFF* */
     432        1119 : VLIB_INIT_FUNCTION (mactime_init) =
     433             : {
     434             :   .runs_after = VLIB_INITS("ip_neighbor_init"),
     435             : };
     436             : /* *INDENT-ON* */
     437             : 
     438             : static clib_error_t *
     439         559 : mactime_config (vlib_main_t * vm, unformat_input_t * input)
     440             : {
     441         559 :   mactime_main_t *mm = &mactime_main;
     442             : 
     443         559 :   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
     444             :     {
     445           0 :       if (unformat (input, "lookup-table-buckets %u",
     446             :                     &mm->lookup_table_num_buckets))
     447             :         ;
     448           0 :       else if (unformat (input, "lookup-table-memory %U",
     449             :                          unformat_memory_size, &mm->lookup_table_memory_size))
     450             :         ;
     451           0 :       else if (unformat (input, "timezone_offset %d", &mm->timezone_offset))
     452             :         ;
     453             :       else
     454             :         {
     455           0 :           return clib_error_return (0, "unknown input '%U'",
     456             :                                     format_unformat_error, input);
     457             :         }
     458             :     }
     459         559 :   return 0;
     460             : }
     461             : 
     462        2264 : VLIB_CONFIG_FUNCTION (mactime_config, "mactime");
     463             : 
     464             : /* *INDENT-OFF* */
     465       43679 : VNET_FEATURE_INIT (mactime, static) =
     466             : {
     467             :   .arc_name = "device-input",
     468             :   .node_name = "mactime",
     469             :   .runs_before = VNET_FEATURES ("ethernet-input"),
     470             : };
     471             : /* *INDENT-ON */
     472             : 
     473             : /* *INDENT-OFF* */
     474       43679 : VNET_FEATURE_INIT (mactime_tx, static) = {
     475             :   .arc_name = "interface-output",
     476             :   .node_name = "mactime-tx",
     477             :   .runs_before = VNET_FEATURES ("interface-output-arc-end"),
     478             : };
     479             : /* *INDENT-ON */
     480             : 
     481             : /* *INDENT-OFF* */
     482             : VLIB_PLUGIN_REGISTER () =
     483             : {
     484             :   .version = VPP_BUILD_VER,
     485             :   .description = "Time-based MAC Source Address Filter",
     486             : };
     487             : /* *INDENT-ON* */
     488             : 
     489             : u8 *
     490           0 : format_bytes_with_width (u8 * s, va_list * va)
     491             : {
     492           0 :   uword nbytes = va_arg (*va, u64);
     493           0 :   int width = va_arg (*va, int);
     494             :   f64 nbytes_f64;
     495             :   u8 *fmt;
     496           0 :   char *suffix = "";
     497             : 
     498           0 :   if (width > 0)
     499           0 :     fmt = format (0, "%%%d.3f%%s%c", width, 0);
     500             :   else
     501           0 :     fmt = format (0, "%%.3f%%s%c", 0);
     502             : 
     503           0 :   if (nbytes > (1024ULL * 1024ULL * 1024ULL))
     504             :     {
     505           0 :       nbytes_f64 = ((f64) nbytes) / (1024.0 * 1024.0 * 1024.0);
     506           0 :       suffix = "G";
     507             :     }
     508           0 :   else if (nbytes > (1024ULL * 1024ULL))
     509             :     {
     510           0 :       nbytes_f64 = ((f64) nbytes) / (1024.0 * 1024.0);
     511           0 :       suffix = "M";
     512             :     }
     513           0 :   else if (nbytes > 1024ULL)
     514             :     {
     515           0 :       nbytes_f64 = ((f64) nbytes) / (1024.0);
     516           0 :       suffix = "K";
     517             :     }
     518             :   else
     519             :     {
     520           0 :       nbytes_f64 = (f64) nbytes;
     521           0 :       suffix = "B";
     522             :     }
     523             : 
     524           0 :   s = format (s, (char *) fmt, nbytes_f64, suffix);
     525           0 :   vec_free (fmt);
     526           0 :   return s;
     527             : }
     528             : 
     529             : static walk_rc_t
     530           0 : mactime_ip_neighbor_copy (index_t ipni, void *ctx)
     531             : {
     532           0 :   mactime_main_t *mm = ctx;
     533             : 
     534           0 :   vec_add1 (mm->arp_cache_copy, ipni);
     535             : 
     536           0 :   return (WALK_CONTINUE);
     537             : }
     538             : 
     539             : static clib_error_t *
     540           0 : show_mactime_command_fn (vlib_main_t * vm,
     541             :                          unformat_input_t * input, vlib_cli_command_t * cmd)
     542             : {
     543           0 :   mactime_main_t *mm = &mactime_main;
     544             :   mactime_device_t *dp;
     545           0 :   u8 *macstring = 0;
     546             :   char *status_string;
     547           0 :   u32 *pool_indices = 0;
     548           0 :   int verbose = 0;
     549           0 :   int current_status = 99;
     550             :   int i, j;
     551             :   f64 now;
     552             :   vlib_counter_t allow, drop;
     553             :   ip_neighbor_t *ipn;
     554             : 
     555           0 :   if (mm->feature_initialized == 0)
     556           0 :     return clib_error_return
     557             :       (0,
     558             :        "Feature not initialized, suggest 'help mactime enable-disable'...");
     559             : 
     560           0 :   vec_reset_length (mm->arp_cache_copy);
     561             :   /* Walk all ip4 neighbours on all interfaces */
     562           0 :   ip_neighbor_walk (AF_IP4, ~0, mactime_ip_neighbor_copy, mm);
     563             : 
     564           0 :   now = clib_timebase_now (&mm->timebase);
     565             : 
     566           0 :   if (PREDICT_FALSE ((now - mm->sunday_midnight) > 86400.0 * 7.0))
     567           0 :     mm->sunday_midnight = clib_timebase_find_sunday_midnight (now);
     568             : 
     569           0 :   if (unformat (input, "verbose %d", &verbose))
     570             :     ;
     571             : 
     572           0 :   if (unformat (input, "verbose"))
     573           0 :     verbose = 1;
     574             : 
     575           0 :   if (verbose)
     576           0 :     vlib_cli_output (vm, "Time now: %U", format_clib_timebase_time, now);
     577             : 
     578             :   /* *INDENT-OFF* */
     579           0 :   pool_foreach (dp, mm->devices)
     580             :    {
     581           0 :     vec_add1 (pool_indices, dp - mm->devices);
     582             :   }
     583             :   /* *INDENT-ON* */
     584             : 
     585           0 :   vlib_cli_output (vm, "%-15s %18s %14s %10s %11s %13s",
     586             :                    "Device Name", "Addresses", "Status",
     587             :                    "AllowPkt", "AllowByte", "DropPkt");
     588             : 
     589           0 :   for (i = 0; i < vec_len (pool_indices); i++)
     590             :     {
     591           0 :       dp = pool_elt_at_index (mm->devices, pool_indices[i]);
     592             : 
     593             :       /* Check dynamic ranges */
     594           0 :       for (j = 0; j < vec_len (dp->ranges); j++)
     595             :         {
     596           0 :           clib_timebase_range_t *r = dp->ranges + j;
     597             :           f64 start0, end0;
     598             : 
     599           0 :           start0 = r->start + mm->sunday_midnight;
     600           0 :           end0 = r->end + mm->sunday_midnight;
     601           0 :           if (verbose > 1)
     602           0 :             vlib_cli_output (vm, "  Range %d: %U - %U", j,
     603             :                              format_clib_timebase_time, start0,
     604             :                              format_clib_timebase_time, end0);
     605             : 
     606           0 :           if (now >= start0 && now <= end0)
     607             :             {
     608           0 :               if (dp->flags & MACTIME_DEVICE_FLAG_DYNAMIC_ALLOW)
     609           0 :                 current_status = 3;
     610           0 :               else if (dp->flags & MACTIME_DEVICE_FLAG_DYNAMIC_ALLOW_QUOTA)
     611           0 :                 current_status = 5;
     612             :               else
     613           0 :                 current_status = 2;
     614           0 :               if (verbose)
     615             :                 {
     616           0 :                   vlib_cli_output (vm, "  Time in range %d:", j);
     617           0 :                   vlib_cli_output (vm, "     %U - %U",
     618             :                                    format_clib_timebase_time, start0,
     619             :                                    format_clib_timebase_time, end0);
     620             :                 }
     621           0 :               goto print;
     622             :             }
     623             :         }
     624           0 :       if (verbose && j)
     625           0 :         vlib_cli_output (vm, "  No range match.");
     626           0 :       if (dp->flags & MACTIME_DEVICE_FLAG_STATIC_DROP)
     627           0 :         current_status = 0;
     628           0 :       if (dp->flags & MACTIME_DEVICE_FLAG_STATIC_ALLOW)
     629           0 :         current_status = 1;
     630           0 :       if (dp->flags & MACTIME_DEVICE_FLAG_DYNAMIC_ALLOW)
     631           0 :         current_status = 2;
     632           0 :       if (dp->flags & MACTIME_DEVICE_FLAG_DYNAMIC_DROP)
     633           0 :         current_status = 3;
     634           0 :       if (dp->flags & MACTIME_DEVICE_FLAG_DYNAMIC_ALLOW_QUOTA)
     635           0 :         current_status = 4;
     636             : 
     637           0 :     print:
     638           0 :       vec_reset_length (macstring);
     639           0 :       macstring =
     640           0 :         format (macstring, "%U", format_mac_address, dp->mac_address);
     641           0 :       switch (current_status)
     642             :         {
     643           0 :         case 0:
     644           0 :           status_string = "static drop";
     645           0 :           break;
     646           0 :         case 1:
     647           0 :           status_string = "static allow";
     648           0 :           break;
     649           0 :         case 2:
     650           0 :           status_string = "dynamic drop";
     651           0 :           break;
     652           0 :         case 3:
     653           0 :           status_string = "dynamic allow";
     654           0 :           break;
     655           0 :         case 4:
     656           0 :           status_string = "d-quota inact";
     657           0 :           break;
     658           0 :         case 5:
     659           0 :           status_string = "d-quota activ";
     660           0 :           break;
     661           0 :         default:
     662           0 :           status_string = "code bug!";
     663           0 :           break;
     664             :         }
     665           0 :       vlib_get_combined_counter (&mm->allow_counters, dp - mm->devices,
     666             :                                  &allow);
     667           0 :       vlib_get_combined_counter (&mm->drop_counters, dp - mm->devices, &drop);
     668           0 :       vlib_cli_output (vm, "%-15s %18s %14s %10lld %U %13lld",
     669             :                        dp->device_name, macstring, status_string,
     670             :                        allow.packets, format_bytes_with_width, allow.bytes,
     671             :                        10, drop.packets);
     672           0 :       if (dp->data_quota > 0)
     673           0 :         vlib_cli_output (vm, "%-54s %s%U %s%U", " ", "Quota ",
     674             :                          format_bytes_with_width, dp->data_quota, 10,
     675             :                          "Use ", format_bytes_with_width,
     676             :                          dp->data_used_in_range, 8);
     677             :       /* This is really only good for small N... */
     678           0 :       for (j = 0; j < vec_len (mm->arp_cache_copy); j++)
     679             :         {
     680           0 :           ipn = ip_neighbor_get (mm->arp_cache_copy[j]);
     681           0 :           if (!memcmp
     682           0 :               (dp->mac_address, ipn->ipn_mac.bytes, sizeof (ipn->ipn_mac)))
     683             :             {
     684           0 :               vlib_cli_output (vm, "%17s%U", " ", format_ip46_address,
     685             :                                ip_neighbor_get_ip (ipn), IP46_TYPE_IP4);
     686             :             }
     687             :         }
     688             :     }
     689           0 :   vec_free (macstring);
     690           0 :   vec_free (pool_indices);
     691             : 
     692           0 :   return 0;
     693             : }
     694             : 
     695             : /* *INDENT-OFF* */
     696      112149 : VLIB_CLI_COMMAND (show_mactime_command, static) =
     697             : {
     698             :   .path = "show mactime",
     699             :   .short_help = "show mactime [verbose]",
     700             :   .function = show_mactime_command_fn,
     701             : };
     702             : /* *INDENT-ON* */
     703             : 
     704             : static clib_error_t *
     705           0 : clear_mactime_command_fn (vlib_main_t * vm,
     706             :                           unformat_input_t * input, vlib_cli_command_t * cmd)
     707             : {
     708           0 :   mactime_main_t *mm = &mactime_main;
     709             : 
     710           0 :   if (mm->feature_initialized == 0)
     711           0 :     return clib_error_return
     712             :       (0,
     713             :        "Feature not initialized, suggest 'help mactime enable-disable'...");
     714             : 
     715           0 :   vlib_clear_combined_counters (&mm->allow_counters);
     716           0 :   vlib_clear_combined_counters (&mm->drop_counters);
     717           0 :   vlib_cli_output (vm, "Mactime counters cleared...");
     718           0 :   return 0;
     719             : }
     720             : 
     721             : /* *INDENT-OFF* */
     722      112149 : VLIB_CLI_COMMAND (clear_mactime_command, static) =
     723             : {
     724             :   .path = "clear mactime",
     725             :   .short_help = "clear mactime counters",
     726             :   .function = clear_mactime_command_fn,
     727             : };
     728             : /* *INDENT-ON* */
     729             : 
     730             : 
     731             : 
     732             : /*
     733             :  * fd.io coding-style-patch-verification: ON
     734             :  *
     735             :  * Local Variables:
     736             :  * eval: (c-set-style "gnu")
     737             :  * End:
     738             :  */

Generated by: LCOV version 1.14