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 30 : feature_init (mactime_main_t * mm)
45 : {
46 30 : if (mm->feature_initialized == 0)
47 : {
48 : /* Create the lookup table */
49 1 : clib_bihash_init_8_8 (&mm->lookup_table, "mactime lookup table",
50 : mm->lookup_table_num_buckets,
51 : mm->lookup_table_memory_size);
52 1 : clib_timebase_init (&mm->timebase, mm->timezone_offset,
53 : CLIB_TIMEBASE_DAYLIGHT_USA,
54 1 : &(mm->vlib_main->clib_time));
55 1 : mm->allow_counters.name = "allow";
56 1 : mm->allow_counters.stat_segment_name = "/mactime/allow";
57 1 : mm->drop_counters.name = "drop";
58 1 : mm->drop_counters.stat_segment_name = "/mactime/drop";
59 1 : mm->feature_initialized = 1;
60 : }
61 30 : }
62 :
63 : /** Action function shared between message handler and debug CLI
64 : */
65 : int
66 6 : mactime_enable_disable (mactime_main_t * mm, u32 sw_if_index,
67 : int enable_disable)
68 : {
69 : vnet_sw_interface_t *sw;
70 6 : int rv = 0;
71 : static u8 url_init_done;
72 :
73 6 : feature_init (mm);
74 :
75 : /* Utterly wrong? */
76 6 : if (pool_is_free_index (mm->vnet_main->interface_main.sw_interfaces,
77 : sw_if_index))
78 1 : return VNET_API_ERROR_INVALID_SW_IF_INDEX;
79 :
80 : /* Not a physical port? */
81 5 : sw = vnet_get_sw_interface (mm->vnet_main, sw_if_index);
82 5 : if (sw->type != VNET_SW_INTERFACE_TYPE_HARDWARE)
83 0 : return VNET_API_ERROR_INVALID_SW_IF_INDEX;
84 :
85 5 : vnet_feature_enable_disable ("device-input", "mactime",
86 : sw_if_index, enable_disable, 0, 0);
87 5 : vnet_feature_enable_disable ("interface-output", "mactime-tx",
88 : sw_if_index, enable_disable, 0, 0);
89 5 : if (url_init_done == 0)
90 : {
91 1 : mactime_url_init (mm->vlib_main);
92 1 : url_init_done = 1;
93 : }
94 :
95 5 : return rv;
96 : }
97 :
98 : static clib_error_t *
99 4 : mactime_enable_disable_command_fn (vlib_main_t * vm,
100 : unformat_input_t * input,
101 : vlib_cli_command_t * cmd)
102 : {
103 4 : mactime_main_t *mm = &mactime_main;
104 4 : u32 sw_if_index = ~0;
105 4 : int enable_disable = 1;
106 :
107 : int rv;
108 :
109 9 : while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
110 : {
111 5 : if (unformat (input, "disable"))
112 2 : enable_disable = 0;
113 3 : else if (unformat (input, "%U", unformat_vnet_sw_interface,
114 : mm->vnet_main, &sw_if_index))
115 : ;
116 1 : else if (unformat (input, "sw_if_index %d", &sw_if_index))
117 : ;
118 : else
119 0 : break;
120 : }
121 :
122 4 : if (sw_if_index == ~0)
123 1 : return clib_error_return (0, "Please specify an interface...");
124 :
125 3 : rv = mactime_enable_disable (mm, sw_if_index, enable_disable);
126 :
127 3 : switch (rv)
128 : {
129 2 : case 0:
130 2 : break;
131 :
132 1 : case VNET_API_ERROR_INVALID_SW_IF_INDEX:
133 1 : 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 2 : return 0;
141 : }
142 :
143 : /* *INDENT-OFF* */
144 119959 : 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 3 : 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 3 : mactime_main_t *mm = &mactime_main;
162 : int rv;
163 :
164 3 : VALIDATE_SW_IF_INDEX (mp);
165 :
166 3 : rv = mactime_enable_disable (mm, ntohl (mp->sw_if_index),
167 3 : (int) (mp->enable_disable));
168 3 : BAD_SW_IF_INDEX_LABEL;
169 3 : 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 15 : mactime_send_create_entry_message (u8 * mac_address)
248 : {
249 15 : 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 15 : am = vlibapi_get_main ();
256 15 : shmem_hdr = am->shmem_hdr;
257 15 : mp = vl_msg_api_alloc_as_if_client (sizeof (*mp));
258 15 : clib_memset (mp, 0, sizeof (*mp));
259 15 : mp->_vl_msg_id = ntohs (VL_API_MACTIME_ADD_DEL_RANGE + mm->msg_id_base);
260 15 : name = format (0, "mac-%U", format_mac_address, mac_address);
261 :
262 15 : memcpy (mp->device_name, name, vec_len (name));
263 15 : memcpy (mp->mac_address, mac_address, sizeof (mp->mac_address));
264 : /* $$$ config: create allow / drop / range */
265 15 : mp->allow = 1;
266 15 : mp->is_add = 1;
267 15 : vl_msg_api_send_shmem (shmem_hdr->vl_input_queue, (u8 *) & mp);
268 15 : }
269 :
270 : /** Add or delete static / dynamic accept/drop configuration for a src mac
271 : */
272 :
273 24 : static void vl_api_mactime_add_del_range_t_handler
274 : (vl_api_mactime_add_del_range_t * mp)
275 : {
276 24 : 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 24 : int found = 1;
281 24 : clib_bihash_8_8_t *lut = &mm->lookup_table;
282 : u64 data_quota;
283 24 : int i, rv = 0;
284 :
285 24 : 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 24 : mm->device_table_epoch++;
292 24 : if (PREDICT_FALSE (mm->device_table_epoch == 0))
293 0 : mm->device_table_epoch++;
294 :
295 24 : data_quota = clib_net_to_host_u64 (mp->data_quota);
296 :
297 24 : clib_memset (&kv, 0, sizeof (kv));
298 24 : 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 24 : if (clib_bihash_search_8_8 (lut, &kv, &kv) < 0)
302 9 : found = 0;
303 :
304 : /* Add an entry? */
305 24 : if (mp->is_add)
306 : {
307 : /* Create the device entry? */
308 22 : if (found == 0)
309 : {
310 8 : pool_get (mm->devices, dp);
311 8 : clib_memset (dp, 0, sizeof (*dp));
312 8 : vlib_validate_combined_counter (&mm->allow_counters,
313 8 : dp - mm->devices);
314 8 : vlib_zero_combined_counter (&mm->allow_counters, dp - mm->devices);
315 8 : vlib_validate_combined_counter (&mm->drop_counters,
316 8 : dp - mm->devices);
317 8 : vlib_zero_combined_counter (&mm->drop_counters, dp - mm->devices);
318 8 : mp->device_name[ARRAY_LEN (mp->device_name) - 1] = 0;
319 8 : dp->device_name = format (0, "%s%c", mp->device_name, 0);
320 8 : memcpy (dp->mac_address, mp->mac_address, sizeof (mp->mac_address));
321 29 : for (i = 0; i < clib_net_to_host_u32 (mp->count); i++)
322 : {
323 21 : clib_timebase_range_t _r, *r = &_r;
324 21 : r->start = mp->ranges[i].start;
325 21 : r->end = mp->ranges[i].end;
326 21 : vec_add1 (dp->ranges, r[0]);
327 : }
328 : /* If we found some time ranges */
329 8 : if (i)
330 : {
331 : /* Set allow/drop based on msg flags */
332 3 : if (mp->drop)
333 1 : dp->flags = MACTIME_DEVICE_FLAG_DYNAMIC_DROP;
334 3 : if (mp->allow)
335 2 : dp->flags = MACTIME_DEVICE_FLAG_DYNAMIC_ALLOW;
336 3 : 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 5 : if (mp->drop)
343 1 : dp->flags = MACTIME_DEVICE_FLAG_STATIC_DROP;
344 5 : if (mp->allow)
345 4 : dp->flags = MACTIME_DEVICE_FLAG_STATIC_ALLOW;
346 : }
347 8 : if (mp->no_udp_10001)
348 0 : dp->flags |= MACTIME_DEVICE_FLAG_DROP_UDP_10001;
349 :
350 8 : dp->data_quota = data_quota;
351 :
352 : /* Add the hash table entry */
353 8 : kv.value = dp - mm->devices;
354 8 : clib_bihash_add_del_8_8 (lut, &kv, 1 /* is_add */ );
355 : }
356 : else /* add more ranges, flags, etc. */
357 : {
358 14 : dp = pool_elt_at_index (mm->devices, kv.value);
359 :
360 14 : 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 14 : 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 14 : if (mp->drop)
382 0 : dp->flags = MACTIME_DEVICE_FLAG_STATIC_DROP;
383 14 : if (mp->allow)
384 14 : dp->flags = MACTIME_DEVICE_FLAG_STATIC_ALLOW;
385 : }
386 14 : if (mp->no_udp_10001)
387 0 : dp->flags |= MACTIME_DEVICE_FLAG_DROP_UDP_10001;
388 :
389 14 : dp->data_quota = data_quota;
390 : }
391 : }
392 : else /* delete case */
393 : {
394 2 : if (found == 0)
395 : {
396 1 : rv = VNET_API_ERROR_NO_SUCH_ENTRY;
397 1 : goto reply;
398 : }
399 :
400 : /* find the device entry */
401 1 : dp = pool_elt_at_index (mm->devices, kv.value);
402 :
403 : /* Remove it from the lookup table */
404 1 : clib_bihash_add_del_8_8 (lut, &kv, 0 /* is_add */ );
405 1 : vec_free (dp->ranges);
406 1 : pool_put (mm->devices, dp);
407 : }
408 :
409 24 : reply:
410 24 : REPLY_MACRO (VL_API_MACTIME_ADD_DEL_RANGE_REPLY);
411 : }
412 :
413 : #include <mactime/mactime.api.c>
414 : static clib_error_t *
415 575 : mactime_init (vlib_main_t * vm)
416 : {
417 575 : mactime_main_t *mm = &mactime_main;
418 :
419 575 : mm->vlib_main = vm;
420 575 : mm->vnet_main = vnet_get_main ();
421 :
422 : /* Ask for a correctly-sized block of API message decode slots */
423 575 : mm->msg_id_base = setup_message_id_table ();
424 :
425 575 : mm->lookup_table_num_buckets = MACTIME_NUM_BUCKETS;
426 575 : mm->lookup_table_memory_size = MACTIME_MEMORY_SIZE;
427 575 : mm->timezone_offset = -5; /* US EST / EDT */
428 575 : return 0;
429 : }
430 :
431 : /* *INDENT-OFF* */
432 1151 : 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 575 : mactime_config (vlib_main_t * vm, unformat_input_t * input)
440 : {
441 575 : mactime_main_t *mm = &mactime_main;
442 :
443 575 : 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 575 : return 0;
460 : }
461 :
462 2328 : VLIB_CONFIG_FUNCTION (mactime_config, "mactime");
463 :
464 : /* *INDENT-OFF* */
465 48961 : 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 48961 : 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 7 : format_bytes_with_width (u8 * s, va_list * va)
491 : {
492 7 : uword nbytes = va_arg (*va, u64);
493 7 : int width = va_arg (*va, int);
494 : f64 nbytes_f64;
495 : u8 *fmt;
496 7 : char *suffix = "";
497 :
498 7 : if (width > 0)
499 7 : fmt = format (0, "%%%d.3f%%s%c", width, 0);
500 : else
501 0 : fmt = format (0, "%%.3f%%s%c", 0);
502 :
503 7 : if (nbytes > (1024ULL * 1024ULL * 1024ULL))
504 : {
505 0 : nbytes_f64 = ((f64) nbytes) / (1024.0 * 1024.0 * 1024.0);
506 0 : suffix = "G";
507 : }
508 7 : else if (nbytes > (1024ULL * 1024ULL))
509 : {
510 0 : nbytes_f64 = ((f64) nbytes) / (1024.0 * 1024.0);
511 0 : suffix = "M";
512 : }
513 7 : else if (nbytes > 1024ULL)
514 : {
515 2 : nbytes_f64 = ((f64) nbytes) / (1024.0);
516 2 : suffix = "K";
517 : }
518 : else
519 : {
520 5 : nbytes_f64 = (f64) nbytes;
521 5 : suffix = "B";
522 : }
523 :
524 7 : s = format (s, (char *) fmt, nbytes_f64, suffix);
525 7 : vec_free (fmt);
526 7 : return s;
527 : }
528 :
529 : static walk_rc_t
530 1 : mactime_ip_neighbor_copy (index_t ipni, void *ctx)
531 : {
532 1 : mactime_main_t *mm = ctx;
533 :
534 1 : vec_add1 (mm->arp_cache_copy, ipni);
535 :
536 1 : return (WALK_CONTINUE);
537 : }
538 :
539 : static clib_error_t *
540 1 : show_mactime_command_fn (vlib_main_t * vm,
541 : unformat_input_t * input, vlib_cli_command_t * cmd)
542 : {
543 1 : mactime_main_t *mm = &mactime_main;
544 : mactime_device_t *dp;
545 1 : u8 *macstring = 0;
546 : char *status_string;
547 1 : u32 *pool_indices = 0;
548 1 : int verbose = 0;
549 1 : int current_status = 99;
550 : int i, j;
551 : f64 now;
552 : vlib_counter_t allow, drop;
553 : ip_neighbor_t *ipn;
554 :
555 1 : if (mm->feature_initialized == 0)
556 0 : return clib_error_return
557 : (0,
558 : "Feature not initialized, suggest 'help mactime enable-disable'...");
559 :
560 1 : vec_reset_length (mm->arp_cache_copy);
561 : /* Walk all ip4 neighbours on all interfaces */
562 1 : ip_neighbor_walk (AF_IP4, ~0, mactime_ip_neighbor_copy, mm);
563 :
564 1 : now = clib_timebase_now (&mm->timebase);
565 :
566 1 : if (PREDICT_FALSE ((now - mm->sunday_midnight) > 86400.0 * 7.0))
567 0 : mm->sunday_midnight = clib_timebase_find_sunday_midnight (now);
568 :
569 1 : if (unformat (input, "verbose %d", &verbose))
570 : ;
571 :
572 1 : if (unformat (input, "verbose"))
573 0 : verbose = 1;
574 :
575 1 : if (verbose)
576 1 : vlib_cli_output (vm, "Time now: %U", format_clib_timebase_time, now);
577 :
578 : /* *INDENT-OFF* */
579 8 : pool_foreach (dp, mm->devices)
580 : {
581 7 : vec_add1 (pool_indices, dp - mm->devices);
582 : }
583 : /* *INDENT-ON* */
584 :
585 1 : vlib_cli_output (vm, "%-15s %18s %14s %10s %11s %13s",
586 : "Device Name", "Addresses", "Status",
587 : "AllowPkt", "AllowByte", "DropPkt");
588 :
589 8 : for (i = 0; i < vec_len (pool_indices); i++)
590 : {
591 7 : dp = pool_elt_at_index (mm->devices, pool_indices[i]);
592 :
593 : /* Check dynamic ranges */
594 16 : for (j = 0; j < vec_len (dp->ranges); j++)
595 : {
596 12 : clib_timebase_range_t *r = dp->ranges + j;
597 : f64 start0, end0;
598 :
599 12 : start0 = r->start + mm->sunday_midnight;
600 12 : end0 = r->end + mm->sunday_midnight;
601 12 : if (verbose > 1)
602 12 : vlib_cli_output (vm, " Range %d: %U - %U", j,
603 : format_clib_timebase_time, start0,
604 : format_clib_timebase_time, end0);
605 :
606 12 : if (now >= start0 && now <= end0)
607 : {
608 3 : if (dp->flags & MACTIME_DEVICE_FLAG_DYNAMIC_ALLOW)
609 2 : current_status = 3;
610 1 : else if (dp->flags & MACTIME_DEVICE_FLAG_DYNAMIC_ALLOW_QUOTA)
611 0 : current_status = 5;
612 : else
613 1 : current_status = 2;
614 3 : if (verbose)
615 : {
616 3 : vlib_cli_output (vm, " Time in range %d:", j);
617 3 : vlib_cli_output (vm, " %U - %U",
618 : format_clib_timebase_time, start0,
619 : format_clib_timebase_time, end0);
620 : }
621 3 : goto print;
622 : }
623 : }
624 4 : if (verbose && j)
625 0 : vlib_cli_output (vm, " No range match.");
626 4 : if (dp->flags & MACTIME_DEVICE_FLAG_STATIC_DROP)
627 1 : current_status = 0;
628 4 : if (dp->flags & MACTIME_DEVICE_FLAG_STATIC_ALLOW)
629 3 : current_status = 1;
630 4 : if (dp->flags & MACTIME_DEVICE_FLAG_DYNAMIC_ALLOW)
631 0 : current_status = 2;
632 4 : if (dp->flags & MACTIME_DEVICE_FLAG_DYNAMIC_DROP)
633 0 : current_status = 3;
634 4 : if (dp->flags & MACTIME_DEVICE_FLAG_DYNAMIC_ALLOW_QUOTA)
635 0 : current_status = 4;
636 :
637 4 : print:
638 7 : vec_reset_length (macstring);
639 7 : macstring =
640 7 : format (macstring, "%U", format_mac_address, dp->mac_address);
641 7 : switch (current_status)
642 : {
643 1 : case 0:
644 1 : status_string = "static drop";
645 1 : break;
646 3 : case 1:
647 3 : status_string = "static allow";
648 3 : break;
649 1 : case 2:
650 1 : status_string = "dynamic drop";
651 1 : break;
652 2 : case 3:
653 2 : status_string = "dynamic allow";
654 2 : 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 7 : vlib_get_combined_counter (&mm->allow_counters, dp - mm->devices,
666 : &allow);
667 7 : vlib_get_combined_counter (&mm->drop_counters, dp - mm->devices, &drop);
668 7 : 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 7 : 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 14 : for (j = 0; j < vec_len (mm->arp_cache_copy); j++)
679 : {
680 7 : ipn = ip_neighbor_get (mm->arp_cache_copy[j]);
681 7 : if (!memcmp
682 7 : (dp->mac_address, ipn->ipn_mac.bytes, sizeof (ipn->ipn_mac)))
683 : {
684 1 : vlib_cli_output (vm, "%17s%U", " ", format_ip46_address,
685 : ip_neighbor_get_ip (ipn), IP46_TYPE_IP4);
686 : }
687 : }
688 : }
689 1 : vec_free (macstring);
690 1 : vec_free (pool_indices);
691 :
692 1 : return 0;
693 : }
694 :
695 : /* *INDENT-OFF* */
696 119959 : 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 1 : clear_mactime_command_fn (vlib_main_t * vm,
706 : unformat_input_t * input, vlib_cli_command_t * cmd)
707 : {
708 1 : mactime_main_t *mm = &mactime_main;
709 :
710 1 : if (mm->feature_initialized == 0)
711 0 : return clib_error_return
712 : (0,
713 : "Feature not initialized, suggest 'help mactime enable-disable'...");
714 :
715 1 : vlib_clear_combined_counters (&mm->allow_counters);
716 1 : vlib_clear_combined_counters (&mm->drop_counters);
717 1 : vlib_cli_output (vm, "Mactime counters cleared...");
718 1 : return 0;
719 : }
720 :
721 : /* *INDENT-OFF* */
722 119959 : 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 : */
|