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 : */
|