]> git.proxmox.com Git - mirror_frr.git/blob - zebra/interface.c
Merge pull request #12798 from donaldsharp/rib_match_multicast
[mirror_frr.git] / zebra / interface.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 * Interface function.
4 * Copyright (C) 1997, 1999 Kunihiro Ishiguro
5 */
6
7 #include <zebra.h>
8
9 #include "if.h"
10 #include "lib_errors.h"
11 #include "vty.h"
12 #include "sockunion.h"
13 #include "prefix.h"
14 #include "command.h"
15 #include "memory.h"
16 #include "ioctl.h"
17 #include "connected.h"
18 #include "log.h"
19 #include "zclient.h"
20 #include "vrf.h"
21 #include "lib/northbound_cli.h"
22
23 #include "zebra/rtadv.h"
24 #include "zebra_ns.h"
25 #include "zebra_vrf.h"
26 #include "zebra/interface.h"
27 #include "zebra/rib.h"
28 #include "zebra/rt.h"
29 #include "zebra/zebra_router.h"
30 #include "zebra/redistribute.h"
31 #include "zebra/debug.h"
32 #include "zebra/irdp.h"
33 #include "zebra/zebra_ptm.h"
34 #include "zebra/rt_netlink.h"
35 #include "zebra/if_netlink.h"
36 #include "zebra/interface.h"
37 #include "zebra/zebra_vxlan.h"
38 #include "zebra/zebra_errors.h"
39 #include "zebra/zebra_evpn_mh.h"
40
41 DEFINE_MTYPE_STATIC(ZEBRA, ZINFO, "Zebra Interface Information");
42
43 #define ZEBRA_PTM_SUPPORT
44
45 DEFINE_HOOK(zebra_if_extra_info, (struct vty * vty, struct interface *ifp),
46 (vty, ifp));
47 DEFINE_HOOK(zebra_if_config_wr, (struct vty * vty, struct interface *ifp),
48 (vty, ifp));
49
50 DEFINE_MTYPE(ZEBRA, ZIF_DESC, "Intf desc");
51
52 static void if_down_del_nbr_connected(struct interface *ifp);
53
54 static void if_zebra_speed_update(struct thread *thread)
55 {
56 struct interface *ifp = THREAD_ARG(thread);
57 struct zebra_if *zif = ifp->info;
58 uint32_t new_speed;
59 bool changed = false;
60 int error = 0;
61
62 new_speed = kernel_get_speed(ifp, &error);
63
64 /* error may indicate vrf not available or
65 * interfaces not available.
66 * note that loopback & virtual interfaces can return 0 as speed
67 */
68 if (error < 0)
69 return;
70
71 if (new_speed != ifp->speed) {
72 zlog_info("%s: %s old speed: %u new speed: %u", __func__,
73 ifp->name, ifp->speed, new_speed);
74 ifp->speed = new_speed;
75 if_add_update(ifp);
76 changed = true;
77 }
78
79 if (changed || new_speed == UINT32_MAX) {
80 #define SPEED_UPDATE_SLEEP_TIME 5
81 #define SPEED_UPDATE_COUNT_MAX (4 * 60 / SPEED_UPDATE_SLEEP_TIME)
82 /*
83 * Some interfaces never actually have an associated speed
84 * with them ( I am looking at you bridges ).
85 * So instead of iterating forever, let's give the
86 * system 4 minutes to try to figure out the speed
87 * if after that it it's probably never going to become
88 * useful.
89 * Since I don't know all the wonderful types of interfaces
90 * that may come into existence in the future I am going
91 * to not update the system to keep track of that. This
92 * is far simpler to just stop trying after 4 minutes
93 */
94 if (new_speed == UINT32_MAX &&
95 zif->speed_update_count == SPEED_UPDATE_COUNT_MAX)
96 return;
97
98 zif->speed_update_count++;
99 thread_add_timer(zrouter.master, if_zebra_speed_update, ifp,
100 SPEED_UPDATE_SLEEP_TIME, &zif->speed_update);
101 thread_ignore_late_timer(zif->speed_update);
102 }
103 }
104
105 static void zebra_if_node_destroy(route_table_delegate_t *delegate,
106 struct route_table *table,
107 struct route_node *node)
108 {
109 if (node->info)
110 list_delete((struct list **)&node->info);
111 route_node_destroy(delegate, table, node);
112 }
113
114 static void zebra_if_nhg_dependents_free(struct zebra_if *zebra_if)
115 {
116 nhg_connected_tree_free(&zebra_if->nhg_dependents);
117 }
118
119 static void zebra_if_nhg_dependents_init(struct zebra_if *zebra_if)
120 {
121 nhg_connected_tree_init(&zebra_if->nhg_dependents);
122 }
123
124
125 route_table_delegate_t zebra_if_table_delegate = {
126 .create_node = route_node_create,
127 .destroy_node = zebra_if_node_destroy};
128
129 /* Called when new interface is added. */
130 static int if_zebra_new_hook(struct interface *ifp)
131 {
132 struct zebra_if *zebra_if;
133
134 zebra_if = XCALLOC(MTYPE_ZINFO, sizeof(struct zebra_if));
135 zebra_if->ifp = ifp;
136
137 zebra_if->multicast = IF_ZEBRA_DATA_UNSPEC;
138 zebra_if->shutdown = IF_ZEBRA_DATA_OFF;
139
140 zebra_if_nhg_dependents_init(zebra_if);
141
142 zebra_ptm_if_init(zebra_if);
143
144 ifp->ptm_enable = zebra_ptm_get_enable_state();
145
146 rtadv_if_init(zebra_if);
147
148 memset(&zebra_if->neigh_mac[0], 0, 6);
149
150 /* Initialize installed address chains tree. */
151 zebra_if->ipv4_subnets =
152 route_table_init_with_delegate(&zebra_if_table_delegate);
153
154 ifp->info = zebra_if;
155
156 /*
157 * Some platforms are telling us that the interface is
158 * up and ready to go. When we check the speed we
159 * sometimes get the wrong value. Wait a couple
160 * of seconds and ask again. Hopefully it's all settled
161 * down upon startup.
162 */
163 zebra_if->speed_update_count = 0;
164 thread_add_timer(zrouter.master, if_zebra_speed_update, ifp, 15,
165 &zebra_if->speed_update);
166 thread_ignore_late_timer(zebra_if->speed_update);
167
168 return 0;
169 }
170
171 static void if_nhg_dependents_check_valid(struct nhg_hash_entry *nhe)
172 {
173 zebra_nhg_check_valid(nhe);
174 }
175
176 static void if_down_nhg_dependents(const struct interface *ifp)
177 {
178 struct nhg_connected *rb_node_dep = NULL;
179 struct zebra_if *zif = (struct zebra_if *)ifp->info;
180
181 frr_each(nhg_connected_tree, &zif->nhg_dependents, rb_node_dep)
182 if_nhg_dependents_check_valid(rb_node_dep->nhe);
183 }
184
185 static void if_nhg_dependents_release(const struct interface *ifp)
186 {
187 struct nhg_connected *rb_node_dep = NULL;
188 struct zebra_if *zif = (struct zebra_if *)ifp->info;
189
190 frr_each(nhg_connected_tree, &zif->nhg_dependents, rb_node_dep) {
191 rb_node_dep->nhe->ifp = NULL; /* Null it out */
192 if_nhg_dependents_check_valid(rb_node_dep->nhe);
193 }
194 }
195
196 /* Called when interface is deleted. */
197 static int if_zebra_delete_hook(struct interface *ifp)
198 {
199 struct zebra_if *zebra_if;
200
201 if (ifp->info) {
202 zebra_if = ifp->info;
203
204 /* If we set protodown, clear our reason now from the kernel */
205 if (ZEBRA_IF_IS_PROTODOWN(zebra_if) && zebra_if->protodown_rc &&
206 !ZEBRA_IF_IS_PROTODOWN_ONLY_EXTERNAL(zebra_if))
207 zebra_if_update_protodown_rc(ifp, true,
208 (zebra_if->protodown_rc &
209 ~ZEBRA_PROTODOWN_ALL));
210
211 /* Free installed address chains tree. */
212 if (zebra_if->ipv4_subnets)
213 route_table_finish(zebra_if->ipv4_subnets);
214
215 rtadv_if_fini(zebra_if);
216
217 zebra_l2_bridge_if_cleanup(ifp);
218 zebra_evpn_if_cleanup(zebra_if);
219 zebra_evpn_mac_ifp_del(ifp);
220
221 if_nhg_dependents_release(ifp);
222 zebra_if_nhg_dependents_free(zebra_if);
223
224 XFREE(MTYPE_ZIF_DESC, zebra_if->desc);
225
226 THREAD_OFF(zebra_if->speed_update);
227
228 XFREE(MTYPE_ZINFO, zebra_if);
229 }
230
231 return 0;
232 }
233
234 /* Build the table key */
235 static void if_build_key(uint32_t ifindex, struct prefix *p)
236 {
237 p->family = AF_INET;
238 p->prefixlen = IPV4_MAX_BITLEN;
239 p->u.prefix4.s_addr = ifindex;
240 }
241
242 /* Link an interface in a per NS interface tree */
243 struct interface *if_link_per_ns(struct zebra_ns *ns, struct interface *ifp)
244 {
245 struct prefix p;
246 struct route_node *rn;
247
248 if (ifp->ifindex == IFINDEX_INTERNAL)
249 return NULL;
250
251 if_build_key(ifp->ifindex, &p);
252 rn = route_node_get(ns->if_table, &p);
253 if (rn->info) {
254 ifp = (struct interface *)rn->info;
255 route_unlock_node(rn); /* get */
256 return ifp;
257 }
258
259 rn->info = ifp;
260 ifp->node = rn;
261
262 return ifp;
263 }
264
265 /* Delete a VRF. This is called in vrf_terminate(). */
266 void if_unlink_per_ns(struct interface *ifp)
267 {
268 ifp->node->info = NULL;
269 route_unlock_node(ifp->node);
270 ifp->node = NULL;
271 }
272
273 /* Look up an interface by identifier within a NS */
274 struct interface *if_lookup_by_index_per_ns(struct zebra_ns *ns,
275 uint32_t ifindex)
276 {
277 struct prefix p;
278 struct route_node *rn;
279 struct interface *ifp = NULL;
280
281 if_build_key(ifindex, &p);
282 rn = route_node_lookup(ns->if_table, &p);
283 if (rn) {
284 ifp = (struct interface *)rn->info;
285 route_unlock_node(rn); /* lookup */
286 }
287 return ifp;
288 }
289
290 /* Look up an interface by name within a NS */
291 struct interface *if_lookup_by_name_per_ns(struct zebra_ns *ns,
292 const char *ifname)
293 {
294 struct route_node *rn;
295 struct interface *ifp;
296
297 for (rn = route_top(ns->if_table); rn; rn = route_next(rn)) {
298 ifp = (struct interface *)rn->info;
299 if (ifp && strcmp(ifp->name, ifname) == 0) {
300 route_unlock_node(rn);
301 return (ifp);
302 }
303 }
304
305 return NULL;
306 }
307
308 const char *ifindex2ifname_per_ns(struct zebra_ns *zns, unsigned int ifindex)
309 {
310 struct interface *ifp;
311
312 return ((ifp = if_lookup_by_index_per_ns(zns, ifindex)) != NULL)
313 ? ifp->name
314 : "unknown";
315 }
316
317 /* Tie an interface address to its derived subnet list of addresses. */
318 int if_subnet_add(struct interface *ifp, struct connected *ifc)
319 {
320 struct route_node *rn;
321 struct zebra_if *zebra_if;
322 struct prefix cp;
323 struct list *addr_list;
324
325 assert(ifp && ifp->info && ifc);
326 zebra_if = ifp->info;
327
328 /* Get address derived subnet node and associated address list, while
329 marking
330 address secondary attribute appropriately. */
331 cp = *CONNECTED_PREFIX(ifc);
332 apply_mask(&cp);
333 rn = route_node_get(zebra_if->ipv4_subnets, &cp);
334
335 if ((addr_list = rn->info))
336 SET_FLAG(ifc->flags, ZEBRA_IFA_SECONDARY);
337 else {
338 UNSET_FLAG(ifc->flags, ZEBRA_IFA_SECONDARY);
339 rn->info = addr_list = list_new();
340 route_lock_node(rn);
341 }
342
343 /* Tie address at the tail of address list. */
344 listnode_add(addr_list, ifc);
345
346 /* Return list element count. */
347 return (addr_list->count);
348 }
349
350 /* Untie an interface address from its derived subnet list of addresses. */
351 int if_subnet_delete(struct interface *ifp, struct connected *ifc)
352 {
353 struct route_node *rn;
354 struct zebra_if *zebra_if;
355 struct list *addr_list;
356 struct prefix cp;
357
358 assert(ifp && ifp->info && ifc);
359 zebra_if = ifp->info;
360
361 cp = *CONNECTED_PREFIX(ifc);
362 apply_mask(&cp);
363
364 /* Get address derived subnet node. */
365 rn = route_node_lookup(zebra_if->ipv4_subnets, &cp);
366 if (!(rn && rn->info)) {
367 flog_warn(EC_ZEBRA_REMOVE_ADDR_UNKNOWN_SUBNET,
368 "Trying to remove an address from an unknown subnet. (please report this bug)");
369 return -1;
370 }
371 route_unlock_node(rn);
372
373 /* Untie address from subnet's address list. */
374 addr_list = rn->info;
375
376 /* Deleting an address that is not registered is a bug.
377 * In any case, we shouldn't decrement the lock counter if the address
378 * is unknown. */
379 if (!listnode_lookup(addr_list, ifc)) {
380 flog_warn(
381 EC_ZEBRA_REMOVE_UNREGISTERED_ADDR,
382 "Trying to remove an address from a subnet where it is not currently registered. (please report this bug)");
383 return -1;
384 }
385
386 listnode_delete(addr_list, ifc);
387 route_unlock_node(rn);
388
389 /* Return list element count, if not empty. */
390 if (addr_list->count) {
391 /* If deleted address is primary, mark subsequent one as such
392 * and distribute. */
393 if (!CHECK_FLAG(ifc->flags, ZEBRA_IFA_SECONDARY)) {
394 ifc = listgetdata(
395 (struct listnode *)listhead(addr_list));
396 zebra_interface_address_delete_update(ifp, ifc);
397 UNSET_FLAG(ifc->flags, ZEBRA_IFA_SECONDARY);
398 /* XXX: Linux kernel removes all the secondary addresses
399 * when the primary
400 * address is removed. We could try to work around that,
401 * though this is
402 * non-trivial. */
403 zebra_interface_address_add_update(ifp, ifc);
404 }
405
406 return addr_list->count;
407 }
408
409 /* Otherwise, free list and route node. */
410 list_delete(&addr_list);
411 rn->info = NULL;
412 route_unlock_node(rn);
413
414 return 0;
415 }
416
417 /* if_flags_mangle: A place for hacks that require mangling
418 * or tweaking the interface flags.
419 *
420 * ******************** Solaris flags hacks **************************
421 *
422 * Solaris IFF_UP flag reflects only the primary interface as the
423 * routing socket only sends IFINFO for the primary interface. Hence
424 * ~IFF_UP does not per se imply all the logical interfaces are also
425 * down - which we only know of as addresses. Instead we must determine
426 * whether the interface really is up or not according to how many
427 * addresses are still attached. (Solaris always sends RTM_DELADDR if
428 * an interface, logical or not, goes ~IFF_UP).
429 *
430 * Ie, we mangle IFF_UP to *additionally* reflect whether or not there
431 * are addresses left in struct connected, not just the actual underlying
432 * IFF_UP flag.
433 *
434 * We must hence remember the real state of IFF_UP, which we do in
435 * struct zebra_if.primary_state.
436 *
437 * Setting IFF_UP within zebra to administratively shutdown the
438 * interface will affect only the primary interface/address on Solaris.
439 ************************End Solaris flags hacks ***********************
440 */
441 static void if_flags_mangle(struct interface *ifp, uint64_t *newflags)
442 {
443 return;
444 }
445
446 /* Update the flags field of the ifp with the new flag set provided.
447 * Take whatever actions are required for any changes in flags we care
448 * about.
449 *
450 * newflags should be the raw value, as obtained from the OS.
451 */
452 void if_flags_update(struct interface *ifp, uint64_t newflags)
453 {
454 if_flags_mangle(ifp, &newflags);
455
456 if (if_is_no_ptm_operative(ifp)) {
457 /* operative -> inoperative? */
458 ifp->flags = newflags;
459 if (!if_is_operative(ifp))
460 if_down(ifp);
461 } else {
462 /* inoperative -> operative? */
463 ifp->flags = newflags;
464 if (if_is_operative(ifp))
465 if_up(ifp, true);
466 }
467 }
468
469 /* Wake up configured address if it is not in current kernel
470 address. */
471 void if_addr_wakeup(struct interface *ifp)
472 {
473 struct listnode *node, *nnode;
474 struct connected *ifc;
475 struct prefix *p;
476 enum zebra_dplane_result dplane_res;
477
478 for (ALL_LIST_ELEMENTS(ifp->connected, node, nnode, ifc)) {
479 p = ifc->address;
480
481 if (CHECK_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED)
482 && !CHECK_FLAG(ifc->conf, ZEBRA_IFC_QUEUED)) {
483 /* Address check. */
484 if (p->family == AF_INET) {
485 if (!if_is_up(ifp)) {
486 /* Assume zebra is configured like
487 * following:
488 *
489 * interface gre0
490 * ip addr 192.0.2.1/24
491 * !
492 *
493 * As soon as zebra becomes first aware
494 * that gre0 exists in the
495 * kernel, it will set gre0 up and
496 * configure its addresses.
497 *
498 * (This may happen at startup when the
499 * interface already exists
500 * or during runtime when the interface
501 * is added to the kernel)
502 *
503 * XXX: IRDP code is calling here via
504 * if_add_update - this seems
505 * somewhat weird.
506 * XXX: RUNNING is not a settable flag
507 * on any system
508 * I (paulj) am aware of.
509 */
510 if_set_flags(ifp, IFF_UP | IFF_RUNNING);
511 if_refresh(ifp);
512 }
513
514 dplane_res = dplane_intf_addr_set(ifp, ifc);
515 if (dplane_res ==
516 ZEBRA_DPLANE_REQUEST_FAILURE) {
517 flog_err_sys(
518 EC_ZEBRA_IFACE_ADDR_ADD_FAILED,
519 "Can't set interface's address: %s",
520 dplane_res2str(dplane_res));
521 continue;
522 }
523
524 SET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED);
525 /* The address will be advertised to zebra
526 * clients when the notification
527 * from the kernel has been received.
528 * It will also be added to the interface's
529 * subnet list then. */
530 }
531 if (p->family == AF_INET6) {
532 if (!if_is_up(ifp)) {
533 /* See long comment above */
534 if_set_flags(ifp, IFF_UP | IFF_RUNNING);
535 if_refresh(ifp);
536 }
537
538
539 dplane_res = dplane_intf_addr_set(ifp, ifc);
540 if (dplane_res ==
541 ZEBRA_DPLANE_REQUEST_FAILURE) {
542 flog_err_sys(
543 EC_ZEBRA_IFACE_ADDR_ADD_FAILED,
544 "Can't set interface's address: %s",
545 dplane_res2str(dplane_res));
546 continue;
547 }
548
549 SET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED);
550 /* The address will be advertised to zebra
551 * clients when the notification
552 * from the kernel has been received. */
553 }
554 }
555 }
556 }
557
558 /* Handle interface addition */
559 void if_add_update(struct interface *ifp)
560 {
561 struct zebra_if *if_data;
562 struct zebra_ns *zns;
563 struct zebra_vrf *zvrf = ifp->vrf->info;
564
565 /* case interface populate before vrf enabled */
566 if (zvrf->zns)
567 zns = zvrf->zns;
568 else
569 zns = zebra_ns_lookup(NS_DEFAULT);
570 if_link_per_ns(zns, ifp);
571 if_data = ifp->info;
572 assert(if_data);
573
574 if (if_data->multicast == IF_ZEBRA_DATA_ON)
575 if_set_flags(ifp, IFF_MULTICAST);
576 else if (if_data->multicast == IF_ZEBRA_DATA_OFF)
577 if_unset_flags(ifp, IFF_MULTICAST);
578
579 zebra_ptm_if_set_ptm_state(ifp, if_data);
580
581 zebra_interface_add_update(ifp);
582
583 if (!CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE)) {
584 SET_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE);
585
586 if (if_data->shutdown == IF_ZEBRA_DATA_ON) {
587 if (IS_ZEBRA_DEBUG_KERNEL) {
588 zlog_debug(
589 "interface %s vrf %s(%u) index %d is shutdown. Won't wake it up.",
590 ifp->name, ifp->vrf->name,
591 ifp->vrf->vrf_id, ifp->ifindex);
592 }
593
594 return;
595 }
596
597 if_addr_wakeup(ifp);
598
599 if (IS_ZEBRA_DEBUG_KERNEL)
600 zlog_debug(
601 "interface %s vrf %s(%u) index %d becomes active.",
602 ifp->name, ifp->vrf->name, ifp->vrf->vrf_id,
603 ifp->ifindex);
604
605 } else {
606 if (IS_ZEBRA_DEBUG_KERNEL)
607 zlog_debug("interface %s vrf %s(%u) index %d is added.",
608 ifp->name, ifp->vrf->name, ifp->vrf->vrf_id,
609 ifp->ifindex);
610 }
611 }
612
613 /* Install connected routes corresponding to an interface. */
614 static void if_install_connected(struct interface *ifp)
615 {
616 struct listnode *node;
617 struct listnode *next;
618 struct connected *ifc;
619
620 if (ifp->connected) {
621 for (ALL_LIST_ELEMENTS(ifp->connected, node, next, ifc)) {
622 if (CHECK_FLAG(ifc->conf, ZEBRA_IFC_REAL))
623 zebra_interface_address_add_update(ifp, ifc);
624
625 connected_up(ifp, ifc);
626 }
627 }
628 }
629
630 /* Uninstall connected routes corresponding to an interface. */
631 static void if_uninstall_connected(struct interface *ifp)
632 {
633 struct listnode *node;
634 struct listnode *next;
635 struct connected *ifc;
636
637 if (ifp->connected) {
638 for (ALL_LIST_ELEMENTS(ifp->connected, node, next, ifc)) {
639 zebra_interface_address_delete_update(ifp, ifc);
640 connected_down(ifp, ifc);
641 }
642 }
643 }
644
645 /* Uninstall and delete connected routes corresponding to an interface. */
646 /* TODO - Check why IPv4 handling here is different from install or if_down */
647 static void if_delete_connected(struct interface *ifp)
648 {
649 struct connected *ifc;
650 struct prefix cp;
651 struct route_node *rn;
652 struct zebra_if *zebra_if;
653 struct listnode *node;
654 struct listnode *last = NULL;
655
656 zebra_if = ifp->info;
657
658 if (!ifp->connected)
659 return;
660
661 while ((node = (last ? last->next : listhead(ifp->connected)))) {
662 ifc = listgetdata(node);
663
664 cp = *CONNECTED_PREFIX(ifc);
665 apply_mask(&cp);
666
667 if (cp.family == AF_INET
668 && (rn = route_node_lookup(zebra_if->ipv4_subnets, &cp))) {
669 struct listnode *anode;
670 struct listnode *next;
671 struct listnode *first;
672 struct list *addr_list;
673
674 route_unlock_node(rn);
675 addr_list = (struct list *)rn->info;
676
677 /* Remove addresses, secondaries first. */
678 first = listhead(addr_list);
679 if (first)
680 for (anode = first->next; anode || first;
681 anode = next) {
682 if (!anode) {
683 anode = first;
684 first = NULL;
685 }
686 next = anode->next;
687
688 ifc = listgetdata(anode);
689 connected_down(ifp, ifc);
690
691 /* XXX: We have to send notifications
692 * here explicitly, because we destroy
693 * the ifc before receiving the
694 * notification about the address being
695 * deleted.
696 */
697 zebra_interface_address_delete_update(
698 ifp, ifc);
699
700 UNSET_FLAG(ifc->conf, ZEBRA_IFC_REAL);
701 UNSET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED);
702
703 /* Remove from subnet chain. */
704 list_delete_node(addr_list, anode);
705 route_unlock_node(rn);
706
707 /* Remove from interface address list
708 * (unconditionally). */
709 if (!CHECK_FLAG(ifc->conf,
710 ZEBRA_IFC_CONFIGURED)) {
711 listnode_delete(ifp->connected,
712 ifc);
713 connected_free(&ifc);
714 } else
715 last = node;
716 }
717
718 /* Free chain list and respective route node. */
719 list_delete(&addr_list);
720 rn->info = NULL;
721 route_unlock_node(rn);
722 } else if (cp.family == AF_INET6) {
723 connected_down(ifp, ifc);
724
725 zebra_interface_address_delete_update(ifp, ifc);
726
727 UNSET_FLAG(ifc->conf, ZEBRA_IFC_REAL);
728 UNSET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED);
729
730 if (CHECK_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED))
731 last = node;
732 else {
733 listnode_delete(ifp->connected, ifc);
734 connected_free(&ifc);
735 }
736 } else {
737 last = node;
738 }
739 }
740 }
741
742 /* Handle an interface delete event */
743 void if_delete_update(struct interface **pifp)
744 {
745 struct zebra_if *zif;
746 struct interface *ifp = *pifp;
747
748 if (if_is_up(ifp)) {
749 flog_err(
750 EC_LIB_INTERFACE,
751 "interface %s vrf %s(%u) index %d is still up while being deleted.",
752 ifp->name, ifp->vrf->name, ifp->vrf->vrf_id,
753 ifp->ifindex);
754 return;
755 }
756
757 if (!CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE))
758 return;
759
760 /* Mark interface as inactive */
761 UNSET_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE);
762
763 if (IS_ZEBRA_DEBUG_KERNEL)
764 zlog_debug("interface %s vrf %s(%u) index %d is now inactive.",
765 ifp->name, ifp->vrf->name, ifp->vrf->vrf_id,
766 ifp->ifindex);
767
768 /* Delete connected routes from the kernel. */
769 if_delete_connected(ifp);
770
771 /* Send out notification on interface delete. */
772 zebra_interface_delete_update(ifp);
773
774 if_unlink_per_ns(ifp);
775
776 /* Update ifindex after distributing the delete message. This is in
777 case any client needs to have the old value of ifindex available
778 while processing the deletion. Each client daemon is responsible
779 for setting ifindex to IFINDEX_INTERNAL after processing the
780 interface deletion message. */
781 if_set_index(ifp, IFINDEX_INTERNAL);
782 ifp->node = NULL;
783
784 /* if the ifp is in a vrf, move it to default so vrf can be deleted if
785 * desired. This operation is not done for netns implementation to avoid
786 * collision with interface with the same name in the default vrf (can
787 * occur with this implementation whereas it is not possible with
788 * vrf-lite).
789 */
790 if (ifp->vrf->vrf_id && !vrf_is_backend_netns())
791 if_handle_vrf_change(ifp, VRF_DEFAULT);
792
793 /* Reset some zebra interface params to default values. */
794 zif = ifp->info;
795 if (zif) {
796 zebra_evpn_if_cleanup(zif);
797 zif->zif_type = ZEBRA_IF_OTHER;
798 zif->zif_slave_type = ZEBRA_IF_SLAVE_NONE;
799 memset(&zif->l2info, 0, sizeof(union zebra_l2if_info));
800 memset(&zif->brslave_info, 0,
801 sizeof(struct zebra_l2info_brslave));
802 zebra_evpn_mac_ifp_del(ifp);
803 }
804
805 if (!ifp->configured) {
806 if (IS_ZEBRA_DEBUG_KERNEL)
807 zlog_debug("interface %s is being deleted from the system",
808 ifp->name);
809 if_delete(pifp);
810 }
811 }
812
813 /* VRF change for an interface */
814 void if_handle_vrf_change(struct interface *ifp, vrf_id_t vrf_id)
815 {
816 vrf_id_t old_vrf_id;
817
818 old_vrf_id = ifp->vrf->vrf_id;
819
820 /* Uninstall connected routes. */
821 if_uninstall_connected(ifp);
822
823 /* Delete any IPv4 neighbors created to implement RFC 5549 */
824 if_nbr_ipv6ll_to_ipv4ll_neigh_del_all(ifp);
825
826 /* Delete all neighbor addresses learnt through IPv6 RA */
827 if_down_del_nbr_connected(ifp);
828
829 /* Send out notification on interface VRF change. */
830 /* This is to issue an UPDATE or a DELETE, as appropriate. */
831 zebra_interface_vrf_update_del(ifp, vrf_id);
832
833 /* update VRF */
834 if_update_to_new_vrf(ifp, vrf_id);
835
836 /* Send out notification on interface VRF change. */
837 /* This is to issue an ADD, if needed. */
838 zebra_interface_vrf_update_add(ifp, old_vrf_id);
839 }
840
841 static void ipv6_ll_address_to_mac(struct in6_addr *address, uint8_t *mac)
842 {
843 mac[0] = address->s6_addr[8] ^ 0x02;
844 mac[1] = address->s6_addr[9];
845 mac[2] = address->s6_addr[10];
846 mac[3] = address->s6_addr[13];
847 mac[4] = address->s6_addr[14];
848 mac[5] = address->s6_addr[15];
849 }
850
851 void if_nbr_mac_to_ipv4ll_neigh_update(struct interface *ifp,
852 char mac[6],
853 struct in6_addr *address,
854 int add)
855 {
856 struct zebra_vrf *zvrf = ifp->vrf->info;
857 struct zebra_if *zif = ifp->info;
858 char buf[16] = "169.254.0.1";
859 struct in_addr ipv4_ll;
860 ns_id_t ns_id;
861
862 inet_pton(AF_INET, buf, &ipv4_ll);
863
864 ns_id = zvrf->zns->ns_id;
865
866 /*
867 * Remove and re-add any existing neighbor entry for this address,
868 * since Netlink doesn't currently offer update message types.
869 */
870 kernel_neigh_update(0, ifp->ifindex, (void *)&ipv4_ll.s_addr, mac, 6,
871 ns_id, AF_INET, true);
872
873 /* Add new neighbor entry.
874 *
875 * We force installation even if current neighbor entry is the same.
876 * Since this function is used to refresh our MAC entries after an
877 * interface flap, if we don't force in our custom entries with their
878 * state set to PERMANENT or REACHABLE then the kernel will attempt to
879 * resolve our leftover entries, fail, mark them unreachable and then
880 * they'll be useless to us.
881 */
882 if (add)
883 kernel_neigh_update(add, ifp->ifindex, (void *)&ipv4_ll.s_addr,
884 mac, 6, ns_id, AF_INET, true);
885
886 memcpy(&zif->neigh_mac[0], &mac[0], 6);
887
888 /*
889 * We need to note whether or not we originated a v6
890 * neighbor entry for this interface. So that when
891 * someone unwisely accidentally deletes this entry
892 * we can shove it back in.
893 */
894 zif->v6_2_v4_ll_neigh_entry = !!add;
895 memcpy(&zif->v6_2_v4_ll_addr6, address, sizeof(*address));
896
897 zvrf->neigh_updates++;
898 }
899
900 void if_nbr_ipv6ll_to_ipv4ll_neigh_update(struct interface *ifp,
901 struct in6_addr *address, int add)
902 {
903
904 char mac[6];
905
906 ipv6_ll_address_to_mac(address, (uint8_t *)mac);
907 if_nbr_mac_to_ipv4ll_neigh_update(ifp, mac, address, add);
908 }
909
910 static void if_nbr_ipv6ll_to_ipv4ll_neigh_add_all(struct interface *ifp)
911 {
912 if (listhead(ifp->nbr_connected)) {
913 struct nbr_connected *nbr_connected;
914 struct listnode *node;
915
916 for (ALL_LIST_ELEMENTS_RO(ifp->nbr_connected, node,
917 nbr_connected))
918 if_nbr_ipv6ll_to_ipv4ll_neigh_update(
919 ifp, &nbr_connected->address->u.prefix6, 1);
920 }
921 }
922
923 void if_nbr_ipv6ll_to_ipv4ll_neigh_del_all(struct interface *ifp)
924 {
925 if (listhead(ifp->nbr_connected)) {
926 struct nbr_connected *nbr_connected;
927 struct listnode *node;
928
929 for (ALL_LIST_ELEMENTS_RO(ifp->nbr_connected, node,
930 nbr_connected))
931 if_nbr_ipv6ll_to_ipv4ll_neigh_update(
932 ifp, &nbr_connected->address->u.prefix6, 0);
933 }
934 }
935
936 static void if_down_del_nbr_connected(struct interface *ifp)
937 {
938 struct nbr_connected *nbr_connected;
939 struct listnode *node, *nnode;
940
941 for (ALL_LIST_ELEMENTS(ifp->nbr_connected, node, nnode,
942 nbr_connected)) {
943 listnode_delete(ifp->nbr_connected, nbr_connected);
944 nbr_connected_free(nbr_connected);
945 }
946 }
947
948 void if_nhg_dependents_add(struct interface *ifp, struct nhg_hash_entry *nhe)
949 {
950 if (ifp->info) {
951 struct zebra_if *zif = (struct zebra_if *)ifp->info;
952
953 nhg_connected_tree_add_nhe(&zif->nhg_dependents, nhe);
954 }
955 }
956
957 void if_nhg_dependents_del(struct interface *ifp, struct nhg_hash_entry *nhe)
958 {
959 if (ifp->info) {
960 struct zebra_if *zif = (struct zebra_if *)ifp->info;
961
962 nhg_connected_tree_del_nhe(&zif->nhg_dependents, nhe);
963 }
964 }
965
966 unsigned int if_nhg_dependents_count(const struct interface *ifp)
967 {
968 if (ifp->info) {
969 struct zebra_if *zif = (struct zebra_if *)ifp->info;
970
971 return nhg_connected_tree_count(&zif->nhg_dependents);
972 }
973
974 return 0;
975 }
976
977
978 bool if_nhg_dependents_is_empty(const struct interface *ifp)
979 {
980 if (ifp->info) {
981 struct zebra_if *zif = (struct zebra_if *)ifp->info;
982
983 return nhg_connected_tree_is_empty(&zif->nhg_dependents);
984 }
985
986 return false;
987 }
988
989 /* Interface is up. */
990 void if_up(struct interface *ifp, bool install_connected)
991 {
992 struct zebra_if *zif;
993 struct interface *link_if;
994 struct zebra_vrf *zvrf = ifp->vrf->info;
995
996 zif = ifp->info;
997 zif->up_count++;
998 frr_timestamp(2, zif->up_last, sizeof(zif->up_last));
999
1000 /* Notify the protocol daemons. */
1001 if (ifp->ptm_enable && (ifp->ptm_status == ZEBRA_PTM_STATUS_DOWN)) {
1002 flog_warn(EC_ZEBRA_PTM_NOT_READY,
1003 "%s: interface %s hasn't passed ptm check",
1004 __func__, ifp->name);
1005 return;
1006 }
1007 zebra_interface_up_update(ifp);
1008
1009 if_nbr_ipv6ll_to_ipv4ll_neigh_add_all(ifp);
1010
1011 rtadv_if_up(zif);
1012
1013 /* Install connected routes to the kernel. */
1014 if (install_connected)
1015 if_install_connected(ifp);
1016
1017 /* Handle interface up for specific types for EVPN. Non-VxLAN interfaces
1018 * are checked to see if (remote) neighbor entries need to be installed
1019 * on them for ARP suppression.
1020 */
1021 if (IS_ZEBRA_IF_VXLAN(ifp))
1022 zebra_vxlan_if_up(ifp);
1023 else if (IS_ZEBRA_IF_BRIDGE(ifp)) {
1024 link_if = ifp;
1025 zebra_vxlan_svi_up(ifp, link_if);
1026 } else if (IS_ZEBRA_IF_VLAN(ifp)) {
1027 link_if = if_lookup_by_index_per_ns(zvrf->zns,
1028 zif->link_ifindex);
1029 if (link_if)
1030 zebra_vxlan_svi_up(ifp, link_if);
1031 } else if (IS_ZEBRA_IF_MACVLAN(ifp)) {
1032 zebra_vxlan_macvlan_up(ifp);
1033 }
1034
1035 if (zif->es_info.es)
1036 zebra_evpn_es_if_oper_state_change(zif, true /*up*/);
1037
1038 if (zif->flags & ZIF_FLAG_EVPN_MH_UPLINK)
1039 zebra_evpn_mh_uplink_oper_update(zif);
1040
1041 thread_add_timer(zrouter.master, if_zebra_speed_update, ifp, 0,
1042 &zif->speed_update);
1043 thread_ignore_late_timer(zif->speed_update);
1044 }
1045
1046 /* Interface goes down. We have to manage different behavior of based
1047 OS. */
1048 void if_down(struct interface *ifp)
1049 {
1050 struct zebra_if *zif;
1051 struct interface *link_if;
1052 struct zebra_vrf *zvrf = ifp->vrf->info;
1053
1054 zif = ifp->info;
1055 zif->down_count++;
1056 frr_timestamp(2, zif->down_last, sizeof(zif->down_last));
1057
1058 if_down_nhg_dependents(ifp);
1059
1060 /* Handle interface down for specific types for EVPN. Non-VxLAN
1061 * interfaces
1062 * are checked to see if (remote) neighbor entries need to be purged
1063 * for ARP suppression.
1064 */
1065 if (IS_ZEBRA_IF_VXLAN(ifp))
1066 zebra_vxlan_if_down(ifp);
1067 else if (IS_ZEBRA_IF_BRIDGE(ifp)) {
1068 link_if = ifp;
1069 zebra_vxlan_svi_down(ifp, link_if);
1070 } else if (IS_ZEBRA_IF_VLAN(ifp)) {
1071 link_if = if_lookup_by_index_per_ns(zvrf->zns,
1072 zif->link_ifindex);
1073 if (link_if)
1074 zebra_vxlan_svi_down(ifp, link_if);
1075 } else if (IS_ZEBRA_IF_MACVLAN(ifp)) {
1076 zebra_vxlan_macvlan_down(ifp);
1077 }
1078
1079 if (zif->es_info.es)
1080 zebra_evpn_es_if_oper_state_change(zif, false /*up*/);
1081
1082 if (zif->flags & ZIF_FLAG_EVPN_MH_UPLINK)
1083 zebra_evpn_mh_uplink_oper_update(zif);
1084
1085 /* Notify to the protocol daemons. */
1086 zebra_interface_down_update(ifp);
1087
1088 /* Uninstall connected routes from the kernel. */
1089 if_uninstall_connected(ifp);
1090
1091 if_nbr_ipv6ll_to_ipv4ll_neigh_del_all(ifp);
1092
1093 /* Delete all neighbor addresses learnt through IPv6 RA */
1094 if_down_del_nbr_connected(ifp);
1095 }
1096
1097 void if_refresh(struct interface *ifp)
1098 {
1099 #ifndef GNU_LINUX
1100 if_get_flags(ifp);
1101 #endif
1102 }
1103
1104 void zebra_if_update_link(struct interface *ifp, ifindex_t link_ifindex,
1105 ns_id_t ns_id)
1106 {
1107 struct zebra_if *zif;
1108
1109 if (IS_ZEBRA_IF_VETH(ifp))
1110 return;
1111 zif = (struct zebra_if *)ifp->info;
1112 zif->link_ifindex = link_ifindex;
1113 zif->link = if_lookup_by_index_per_ns(zebra_ns_lookup(ns_id),
1114 link_ifindex);
1115 }
1116
1117 /*
1118 * during initial link dump kernel does not order lower devices before
1119 * upper devices so we need to fixup link dependencies at the end of dump
1120 */
1121 void zebra_if_update_all_links(struct zebra_ns *zns)
1122 {
1123 struct route_node *rn;
1124 struct interface *ifp;
1125 struct zebra_if *zif;
1126
1127 if (IS_ZEBRA_DEBUG_KERNEL)
1128 zlog_info("fixup link dependencies");
1129
1130 for (rn = route_top(zns->if_table); rn; rn = route_next(rn)) {
1131 ifp = (struct interface *)rn->info;
1132 if (!ifp)
1133 continue;
1134 zif = ifp->info;
1135 /* update bond-member to bond linkages */
1136 if ((IS_ZEBRA_IF_BOND_SLAVE(ifp))
1137 && (zif->bondslave_info.bond_ifindex != IFINDEX_INTERNAL)
1138 && !zif->bondslave_info.bond_if) {
1139 if (IS_ZEBRA_DEBUG_EVPN_MH_ES || IS_ZEBRA_DEBUG_KERNEL)
1140 zlog_debug("bond mbr %s map to bond %d",
1141 zif->ifp->name,
1142 zif->bondslave_info.bond_ifindex);
1143 zebra_l2_map_slave_to_bond(zif, ifp->vrf->vrf_id);
1144 }
1145
1146 /* update SVI linkages */
1147 if ((zif->link_ifindex != IFINDEX_INTERNAL) && !zif->link) {
1148 zif->link = if_lookup_by_index_per_ns(
1149 zns, zif->link_ifindex);
1150 if (IS_ZEBRA_DEBUG_KERNEL)
1151 zlog_debug("interface %s/%d's lower fixup to %s/%d",
1152 ifp->name, ifp->ifindex,
1153 zif->link?zif->link->name:"unk",
1154 zif->link_ifindex);
1155 }
1156
1157 /* Update VLAN<=>SVI map */
1158 if (IS_ZEBRA_IF_VLAN(ifp))
1159 zebra_evpn_acc_bd_svi_set(zif, NULL,
1160 !!if_is_operative(ifp));
1161 }
1162 }
1163
1164 static bool if_ignore_set_protodown(const struct interface *ifp, bool new_down,
1165 uint32_t new_protodown_rc)
1166 {
1167 struct zebra_if *zif;
1168 bool old_down, old_set_down, old_unset_down;
1169
1170 zif = ifp->info;
1171
1172 /* Current state as we know it */
1173 old_down = !!(ZEBRA_IF_IS_PROTODOWN(zif));
1174 old_set_down = !!CHECK_FLAG(zif->flags, ZIF_FLAG_SET_PROTODOWN);
1175 old_unset_down = !!CHECK_FLAG(zif->flags, ZIF_FLAG_UNSET_PROTODOWN);
1176
1177 if (new_protodown_rc == zif->protodown_rc) {
1178 /* Early return if already down & reason bitfield matches */
1179 if (new_down == old_down) {
1180 if (IS_ZEBRA_DEBUG_KERNEL)
1181 zlog_debug(
1182 "Ignoring request to set protodown %s for interface %s (%u): protodown %s is already set (reason bitfield: old 0x%x new 0x%x)",
1183 new_down ? "on" : "off", ifp->name,
1184 ifp->ifindex, new_down ? "on" : "off",
1185 zif->protodown_rc, new_protodown_rc);
1186
1187 return true;
1188 }
1189
1190 /* Early return if already set queued & reason bitfield matches
1191 */
1192 if (new_down && old_set_down) {
1193 if (IS_ZEBRA_DEBUG_KERNEL)
1194 zlog_debug(
1195 "Ignoring request to set protodown %s for interface %s (%u): protodown %s is already queued to dplane (reason bitfield: old 0x%x new 0x%x)",
1196 new_down ? "on" : "off", ifp->name,
1197 ifp->ifindex, new_down ? "on" : "off",
1198 zif->protodown_rc, new_protodown_rc);
1199
1200 return true;
1201 }
1202
1203 /* Early return if already unset queued & reason bitfield
1204 * matches */
1205 if (!new_down && old_unset_down) {
1206 if (IS_ZEBRA_DEBUG_KERNEL)
1207 zlog_debug(
1208 "Ignoring request to set protodown %s for interface %s (%u): protodown %s is already queued to dplane (reason bitfield: old 0x%x new 0x%x)",
1209 new_down ? "on" : "off", ifp->name,
1210 ifp->ifindex, new_down ? "on" : "off",
1211 zif->protodown_rc, new_protodown_rc);
1212
1213 return true;
1214 }
1215 }
1216
1217 return false;
1218 }
1219
1220 int zebra_if_update_protodown_rc(struct interface *ifp, bool new_down,
1221 uint32_t new_protodown_rc)
1222 {
1223 struct zebra_if *zif;
1224
1225 zif = ifp->info;
1226
1227 /* Check if we already have this state or it's queued */
1228 if (if_ignore_set_protodown(ifp, new_down, new_protodown_rc))
1229 return 1;
1230
1231 zlog_info(
1232 "Setting protodown %s - interface %s (%u): reason bitfield change from 0x%x --> 0x%x",
1233 new_down ? "on" : "off", ifp->name, ifp->ifindex,
1234 zif->protodown_rc, new_protodown_rc);
1235
1236 zif->protodown_rc = new_protodown_rc;
1237
1238 if (new_down)
1239 SET_FLAG(zif->flags, ZIF_FLAG_SET_PROTODOWN);
1240 else
1241 SET_FLAG(zif->flags, ZIF_FLAG_UNSET_PROTODOWN);
1242
1243 #ifdef HAVE_NETLINK
1244 dplane_intf_update(ifp);
1245 #else
1246 zlog_warn("Protodown is not supported on this platform");
1247 #endif
1248 return 0;
1249 }
1250
1251 int zebra_if_set_protodown(struct interface *ifp, bool new_down,
1252 enum protodown_reasons new_reason)
1253 {
1254 struct zebra_if *zif;
1255 uint32_t new_protodown_rc;
1256
1257 zif = ifp->info;
1258
1259 if (new_down)
1260 new_protodown_rc = zif->protodown_rc | new_reason;
1261 else
1262 new_protodown_rc = zif->protodown_rc & ~new_reason;
1263
1264 return zebra_if_update_protodown_rc(ifp, new_down, new_protodown_rc);
1265 }
1266
1267 /*
1268 * Handle an interface events based on info in a dplane context object.
1269 * This runs in the main pthread, using the info in the context object to
1270 * modify an interface.
1271 */
1272 static void zebra_if_addr_update_ctx(struct zebra_dplane_ctx *ctx,
1273 struct interface *ifp)
1274 {
1275 uint8_t flags = 0;
1276 const char *label = NULL;
1277 uint32_t metric = METRIC_MAX;
1278 const struct prefix *addr, *dest = NULL;
1279 enum dplane_op_e op;
1280
1281 op = dplane_ctx_get_op(ctx);
1282 addr = dplane_ctx_get_intf_addr(ctx);
1283
1284 if (IS_ZEBRA_DEBUG_KERNEL)
1285 zlog_debug("%s: %s: ifindex %s(%u), addr %pFX", __func__,
1286 dplane_op2str(dplane_ctx_get_op(ctx)), ifp->name,
1287 ifp->ifindex, addr);
1288
1289 /* Is there a peer or broadcast address? */
1290 dest = dplane_ctx_get_intf_dest(ctx);
1291 if (dest->prefixlen == 0)
1292 dest = NULL;
1293
1294 if (dplane_ctx_intf_is_connected(ctx))
1295 SET_FLAG(flags, ZEBRA_IFA_PEER);
1296
1297 /* Flags. */
1298 if (dplane_ctx_intf_is_secondary(ctx))
1299 SET_FLAG(flags, ZEBRA_IFA_SECONDARY);
1300
1301 /* Label? */
1302 if (dplane_ctx_intf_has_label(ctx))
1303 label = dplane_ctx_get_intf_label(ctx);
1304
1305 if (label && strcmp(ifp->name, label) == 0)
1306 label = NULL;
1307
1308 metric = dplane_ctx_get_intf_metric(ctx);
1309
1310 /* Register interface address to the interface. */
1311 if (addr->family == AF_INET) {
1312 if (op == DPLANE_OP_INTF_ADDR_ADD)
1313 connected_add_ipv4(
1314 ifp, flags, &addr->u.prefix4, addr->prefixlen,
1315 dest ? &dest->u.prefix4 : NULL, label, metric);
1316 else if (CHECK_FLAG(flags, ZEBRA_IFA_PEER)) {
1317 /* Delete with a peer address */
1318 connected_delete_ipv4(ifp, flags, &addr->u.prefix4,
1319 addr->prefixlen,
1320 &dest->u.prefix4);
1321 } else
1322 connected_delete_ipv4(ifp, flags, &addr->u.prefix4,
1323 addr->prefixlen, NULL);
1324 }
1325
1326 if (addr->family == AF_INET6) {
1327 if (op == DPLANE_OP_INTF_ADDR_ADD) {
1328 connected_add_ipv6(ifp, flags, &addr->u.prefix6,
1329 dest ? &dest->u.prefix6 : NULL,
1330 addr->prefixlen, label, metric);
1331 } else
1332 connected_delete_ipv6(ifp, &addr->u.prefix6, NULL,
1333 addr->prefixlen);
1334 }
1335
1336 /*
1337 * Linux kernel does not send route delete on interface down/addr del
1338 * so we have to re-process routes it owns (i.e. kernel routes)
1339 */
1340 if (op != DPLANE_OP_INTF_ADDR_ADD)
1341 rib_update(RIB_UPDATE_KERNEL);
1342 }
1343
1344 static void zebra_if_update_ctx(struct zebra_dplane_ctx *ctx,
1345 struct interface *ifp)
1346 {
1347 enum zebra_dplane_result dp_res;
1348 struct zebra_if *zif;
1349 bool pd_reason_val;
1350 bool down;
1351
1352 dp_res = dplane_ctx_get_status(ctx);
1353 pd_reason_val = dplane_ctx_get_intf_pd_reason_val(ctx);
1354 down = dplane_ctx_intf_is_protodown(ctx);
1355
1356 if (IS_ZEBRA_DEBUG_KERNEL)
1357 zlog_debug("%s: %s: if %s(%u) ctx-protodown %s ctx-reason %d",
1358 __func__, dplane_op2str(dplane_ctx_get_op(ctx)),
1359 ifp->name, ifp->ifindex, down ? "on" : "off",
1360 pd_reason_val);
1361
1362 zif = ifp->info;
1363 if (!zif) {
1364 if (IS_ZEBRA_DEBUG_KERNEL)
1365 zlog_debug("%s: if %s(%u) zebra info pointer is NULL",
1366 __func__, ifp->name, ifp->ifindex);
1367 return;
1368 }
1369
1370 if (dp_res != ZEBRA_DPLANE_REQUEST_SUCCESS) {
1371 if (IS_ZEBRA_DEBUG_KERNEL)
1372 zlog_debug("%s: if %s(%u) dplane update failed",
1373 __func__, ifp->name, ifp->ifindex);
1374 goto done;
1375 }
1376
1377 /* Update our info */
1378 COND_FLAG(zif->flags, ZIF_FLAG_PROTODOWN, down);
1379
1380 done:
1381 /* Clear our dplane flags */
1382 UNSET_FLAG(zif->flags, ZIF_FLAG_SET_PROTODOWN);
1383 UNSET_FLAG(zif->flags, ZIF_FLAG_UNSET_PROTODOWN);
1384 }
1385
1386 /*
1387 * Handle netconf change from a dplane context object; runs in the main
1388 * pthread so it can update zebra data structs.
1389 */
1390 static void zebra_if_netconf_update_ctx(struct zebra_dplane_ctx *ctx,
1391 struct interface *ifp,
1392 ifindex_t ifindex)
1393 {
1394 struct zebra_if *zif = NULL;
1395 afi_t afi;
1396 enum dplane_netconf_status_e mpls, mcast_on, linkdown;
1397 bool *mcast_set, *linkdown_set;
1398
1399 afi = dplane_ctx_get_afi(ctx);
1400 mpls = dplane_ctx_get_netconf_mpls(ctx);
1401 linkdown = dplane_ctx_get_netconf_linkdown(ctx);
1402 mcast_on = dplane_ctx_get_netconf_mcast(ctx);
1403
1404 if (ifindex == DPLANE_NETCONF_IFINDEX_ALL) {
1405 if (afi == AFI_IP) {
1406 mcast_set = &zrouter.all_mc_forwardingv4;
1407 linkdown_set = &zrouter.all_linkdownv4;
1408 } else {
1409 mcast_set = &zrouter.all_mc_forwardingv6;
1410 linkdown_set = &zrouter.all_linkdownv6;
1411 }
1412 } else if (ifindex == DPLANE_NETCONF_IFINDEX_DEFAULT) {
1413 if (afi == AFI_IP) {
1414 mcast_set = &zrouter.default_mc_forwardingv4;
1415 linkdown_set = &zrouter.default_linkdownv4;
1416 } else {
1417 mcast_set = &zrouter.default_mc_forwardingv6;
1418 linkdown_set = &zrouter.default_linkdownv6;
1419 }
1420 } else {
1421 zif = ifp ? ifp->info : NULL;
1422 if (!zif) {
1423 if (IS_ZEBRA_DEBUG_KERNEL)
1424 zlog_debug(
1425 "%s: if %s(%u) zebra info pointer is NULL",
1426 __func__, ifp ? ifp->name : "(null)",
1427 ifp ? ifp->ifindex : ifindex);
1428 return;
1429 }
1430 if (afi == AFI_IP) {
1431 mcast_set = &zif->v4mcast_on;
1432 linkdown_set = &zif->linkdown;
1433 } else {
1434 mcast_set = &zif->v6mcast_on;
1435 linkdown_set = &zif->linkdownv6;
1436 }
1437
1438 /*
1439 * mpls netconf data is neither v4 or v6 it's AF_MPLS!
1440 */
1441 if (mpls == DPLANE_NETCONF_STATUS_ENABLED) {
1442 zif->mpls = true;
1443 zebra_mpls_turned_on();
1444 } else if (mpls == DPLANE_NETCONF_STATUS_DISABLED)
1445 zif->mpls = false;
1446 }
1447
1448 if (linkdown == DPLANE_NETCONF_STATUS_ENABLED)
1449 *linkdown_set = true;
1450 else if (linkdown == DPLANE_NETCONF_STATUS_DISABLED)
1451 *linkdown_set = false;
1452
1453 if (mcast_on == DPLANE_NETCONF_STATUS_ENABLED)
1454 *mcast_set = true;
1455 else if (mcast_on == DPLANE_NETCONF_STATUS_DISABLED)
1456 *mcast_set = false;
1457
1458 if (IS_ZEBRA_DEBUG_KERNEL)
1459 zlog_debug(
1460 "%s: afi: %d if %s, ifindex %d, mpls %s mc_forwarding: %s linkdown %s",
1461 __func__, afi, ifp ? ifp->name : "Global",
1462 ifp ? ifp->ifindex : ifindex,
1463 (zif ? (zif->mpls ? "ON" : "OFF") : "OFF"),
1464 (*mcast_set ? "ON" : "OFF"),
1465 (*linkdown_set ? "ON" : "OFF"));
1466 }
1467
1468 void zebra_if_dplane_result(struct zebra_dplane_ctx *ctx)
1469 {
1470 struct zebra_ns *zns;
1471 struct interface *ifp;
1472 ns_id_t ns_id;
1473 enum dplane_op_e op;
1474 enum zebra_dplane_result dp_res;
1475 ifindex_t ifindex;
1476
1477 ns_id = dplane_ctx_get_ns_id(ctx);
1478 dp_res = dplane_ctx_get_status(ctx);
1479 op = dplane_ctx_get_op(ctx);
1480 ifindex = dplane_ctx_get_ifindex(ctx);
1481
1482 if (IS_ZEBRA_DEBUG_DPLANE_DETAIL || IS_ZEBRA_DEBUG_KERNEL)
1483 zlog_debug("Intf dplane ctx %p, op %s, ifindex (%u), result %s",
1484 ctx, dplane_op2str(op), ifindex,
1485 dplane_res2str(dp_res));
1486
1487 zns = zebra_ns_lookup(ns_id);
1488 if (zns == NULL) {
1489 /* No ns - deleted maybe? */
1490 if (IS_ZEBRA_DEBUG_KERNEL)
1491 zlog_debug("%s: can't find zns id %u", __func__, ns_id);
1492
1493 return;
1494 }
1495
1496 ifp = if_lookup_by_index_per_ns(zns, ifindex);
1497 if (ifp == NULL) {
1498 if (op != DPLANE_OP_INTF_NETCONFIG ||
1499 (ifindex != -1 && ifindex != -2)) {
1500 if (IS_ZEBRA_DEBUG_KERNEL)
1501 zlog_debug(
1502 "%s: can't find ifp at nsid %u index %d",
1503 __func__, ns_id, ifindex);
1504
1505 return;
1506 }
1507 }
1508
1509 switch (op) {
1510 case DPLANE_OP_INTF_ADDR_ADD:
1511 case DPLANE_OP_INTF_ADDR_DEL:
1512 zebra_if_addr_update_ctx(ctx, ifp);
1513 break;
1514
1515 case DPLANE_OP_INTF_INSTALL:
1516 case DPLANE_OP_INTF_UPDATE:
1517 case DPLANE_OP_INTF_DELETE:
1518 zebra_if_update_ctx(ctx, ifp);
1519 break;
1520
1521 case DPLANE_OP_INTF_NETCONFIG:
1522 zebra_if_netconf_update_ctx(ctx, ifp, ifindex);
1523 break;
1524
1525 case DPLANE_OP_ROUTE_INSTALL:
1526 case DPLANE_OP_ROUTE_UPDATE:
1527 case DPLANE_OP_ROUTE_DELETE:
1528 case DPLANE_OP_NH_DELETE:
1529 case DPLANE_OP_NH_INSTALL:
1530 case DPLANE_OP_NH_UPDATE:
1531 case DPLANE_OP_ROUTE_NOTIFY:
1532 case DPLANE_OP_LSP_INSTALL:
1533 case DPLANE_OP_LSP_UPDATE:
1534 case DPLANE_OP_LSP_DELETE:
1535 case DPLANE_OP_LSP_NOTIFY:
1536 case DPLANE_OP_PW_INSTALL:
1537 case DPLANE_OP_PW_UNINSTALL:
1538 case DPLANE_OP_SYS_ROUTE_ADD:
1539 case DPLANE_OP_SYS_ROUTE_DELETE:
1540 case DPLANE_OP_ADDR_INSTALL:
1541 case DPLANE_OP_ADDR_UNINSTALL:
1542 case DPLANE_OP_MAC_INSTALL:
1543 case DPLANE_OP_MAC_DELETE:
1544 case DPLANE_OP_NEIGH_INSTALL:
1545 case DPLANE_OP_NEIGH_UPDATE:
1546 case DPLANE_OP_NEIGH_DELETE:
1547 case DPLANE_OP_NEIGH_IP_INSTALL:
1548 case DPLANE_OP_NEIGH_IP_DELETE:
1549 case DPLANE_OP_VTEP_ADD:
1550 case DPLANE_OP_VTEP_DELETE:
1551 case DPLANE_OP_RULE_ADD:
1552 case DPLANE_OP_RULE_DELETE:
1553 case DPLANE_OP_RULE_UPDATE:
1554 case DPLANE_OP_NEIGH_DISCOVER:
1555 case DPLANE_OP_BR_PORT_UPDATE:
1556 case DPLANE_OP_NONE:
1557 case DPLANE_OP_IPTABLE_ADD:
1558 case DPLANE_OP_IPTABLE_DELETE:
1559 case DPLANE_OP_IPSET_ADD:
1560 case DPLANE_OP_IPSET_DELETE:
1561 case DPLANE_OP_IPSET_ENTRY_ADD:
1562 case DPLANE_OP_IPSET_ENTRY_DELETE:
1563 case DPLANE_OP_NEIGH_TABLE_UPDATE:
1564 case DPLANE_OP_GRE_SET:
1565 case DPLANE_OP_TC_QDISC_INSTALL:
1566 case DPLANE_OP_TC_QDISC_UNINSTALL:
1567 case DPLANE_OP_TC_CLASS_ADD:
1568 case DPLANE_OP_TC_CLASS_DELETE:
1569 case DPLANE_OP_TC_CLASS_UPDATE:
1570 case DPLANE_OP_TC_FILTER_ADD:
1571 case DPLANE_OP_TC_FILTER_DELETE:
1572 case DPLANE_OP_TC_FILTER_UPDATE:
1573 break; /* should never hit here */
1574 }
1575 }
1576
1577 /* Dump if address information to vty. */
1578 static void connected_dump_vty(struct vty *vty, json_object *json,
1579 struct connected *connected)
1580 {
1581 struct prefix *p;
1582 json_object *json_addr = NULL;
1583
1584 /* Print interface address. */
1585 p = connected->address;
1586
1587 if (json) {
1588 json_addr = json_object_new_object();
1589 json_object_array_add(json, json_addr);
1590 json_object_string_addf(json_addr, "address", "%pFX", p);
1591 } else {
1592 vty_out(vty, " %s %pFX", prefix_family_str(p), p);
1593 }
1594
1595 /* If there is destination address, print it. */
1596 if (CONNECTED_PEER(connected) && connected->destination) {
1597 if (json) {
1598 json_object_string_addf(json_addr, "peer", "%pFX",
1599 connected->destination);
1600 } else {
1601 vty_out(vty, " peer %pFX", connected->destination);
1602 }
1603 }
1604
1605 if (json)
1606 json_object_boolean_add(
1607 json_addr, "secondary",
1608 CHECK_FLAG(connected->flags, ZEBRA_IFA_SECONDARY));
1609 else if (CHECK_FLAG(connected->flags, ZEBRA_IFA_SECONDARY))
1610 vty_out(vty, " secondary");
1611
1612 if (json)
1613 json_object_boolean_add(
1614 json_addr, "unnumbered",
1615 CHECK_FLAG(connected->flags, ZEBRA_IFA_UNNUMBERED));
1616 else if (CHECK_FLAG(connected->flags, ZEBRA_IFA_UNNUMBERED))
1617 vty_out(vty, " unnumbered");
1618
1619 if (connected->label) {
1620 if (json)
1621 json_object_string_add(json_addr, "label",
1622 connected->label);
1623 else
1624 vty_out(vty, " %s", connected->label);
1625 }
1626
1627 if (!json)
1628 vty_out(vty, "\n");
1629 }
1630
1631 /* Dump interface neighbor address information to vty. */
1632 static void nbr_connected_dump_vty(struct vty *vty, json_object *json,
1633 struct nbr_connected *connected)
1634 {
1635 struct prefix *p;
1636 char buf[PREFIX2STR_BUFFER];
1637
1638 /* Print interface address. */
1639 p = connected->address;
1640 if (json)
1641 json_array_string_add(json, prefix2str(p, buf, sizeof(buf)));
1642 else
1643 vty_out(vty, " %s %pFX\n", prefix_family_str(p), p);
1644 }
1645
1646 static const char *
1647 zebra_zifslavetype_2str(enum zebra_slave_iftype zif_slave_type)
1648 {
1649 switch (zif_slave_type) {
1650 case ZEBRA_IF_SLAVE_BRIDGE:
1651 return "Bridge";
1652 case ZEBRA_IF_SLAVE_VRF:
1653 return "Vrf";
1654 case ZEBRA_IF_SLAVE_BOND:
1655 return "Bond";
1656 case ZEBRA_IF_SLAVE_OTHER:
1657 return "Other";
1658 case ZEBRA_IF_SLAVE_NONE:
1659 return "None";
1660 }
1661 return "None";
1662 }
1663
1664 static const char *zebra_ziftype_2str(enum zebra_iftype zif_type)
1665 {
1666 switch (zif_type) {
1667 case ZEBRA_IF_OTHER:
1668 return "Other";
1669
1670 case ZEBRA_IF_BRIDGE:
1671 return "Bridge";
1672
1673 case ZEBRA_IF_VLAN:
1674 return "Vlan";
1675
1676 case ZEBRA_IF_VXLAN:
1677 return "Vxlan";
1678
1679 case ZEBRA_IF_VRF:
1680 return "VRF";
1681
1682 case ZEBRA_IF_VETH:
1683 return "VETH";
1684
1685 case ZEBRA_IF_BOND:
1686 return "bond";
1687
1688 case ZEBRA_IF_BOND_SLAVE:
1689 return "bond_slave";
1690
1691 case ZEBRA_IF_MACVLAN:
1692 return "macvlan";
1693
1694 case ZEBRA_IF_GRE:
1695 return "GRE";
1696
1697 default:
1698 return "Unknown";
1699 }
1700 }
1701
1702 /* Interface's brief information print out to vty interface. */
1703 static void ifs_dump_brief_vty(struct vty *vty, struct vrf *vrf)
1704 {
1705 struct connected *connected;
1706 struct listnode *node;
1707 struct route_node *rn;
1708 struct zebra_if *zebra_if;
1709 struct prefix *p;
1710 struct interface *ifp;
1711 bool print_header = true;
1712
1713 FOR_ALL_INTERFACES (vrf, ifp) {
1714 bool first_pfx_printed = false;
1715
1716 if (print_header) {
1717 vty_out(vty, "%-16s%-8s%-16s%s\n", "Interface",
1718 "Status", "VRF", "Addresses");
1719 vty_out(vty, "%-16s%-8s%-16s%s\n", "---------",
1720 "------", "---", "---------");
1721 print_header = false; /* We have at least 1 iface */
1722 }
1723 zebra_if = ifp->info;
1724
1725 vty_out(vty, "%-16s", ifp->name);
1726
1727 if (if_is_up(ifp))
1728 vty_out(vty, "%-8s", "up");
1729 else
1730 vty_out(vty, "%-8s", "down");
1731
1732 vty_out(vty, "%-16s", vrf->name);
1733
1734 for (rn = route_top(zebra_if->ipv4_subnets); rn;
1735 rn = route_next(rn)) {
1736 if (!rn->info)
1737 continue;
1738 uint32_t list_size = listcount((struct list *)rn->info);
1739
1740 for (ALL_LIST_ELEMENTS_RO((struct list *)rn->info, node,
1741 connected)) {
1742 if (!CHECK_FLAG(connected->flags,
1743 ZEBRA_IFA_SECONDARY)) {
1744 p = connected->address;
1745 if (first_pfx_printed) {
1746 /* padding to prepare row only
1747 * for ip addr */
1748 vty_out(vty, "%-40s", "");
1749 if (list_size > 1)
1750 vty_out(vty, "+ ");
1751 vty_out(vty, "%pFX\n", p);
1752 } else {
1753 if (list_size > 1)
1754 vty_out(vty, "+ ");
1755 vty_out(vty, "%pFX\n", p);
1756 }
1757 first_pfx_printed = true;
1758 break;
1759 }
1760 }
1761 }
1762
1763 uint32_t v6_list_size = 0;
1764 for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, connected)) {
1765 if (CHECK_FLAG(connected->conf, ZEBRA_IFC_REAL)
1766 && (connected->address->family == AF_INET6))
1767 v6_list_size++;
1768 }
1769 for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, connected)) {
1770 if (CHECK_FLAG(connected->conf, ZEBRA_IFC_REAL)
1771 && !CHECK_FLAG(connected->flags,
1772 ZEBRA_IFA_SECONDARY)
1773 && (connected->address->family == AF_INET6)) {
1774 p = connected->address;
1775 /* Don't print link local pfx */
1776 if (!IN6_IS_ADDR_LINKLOCAL(&p->u.prefix6)) {
1777 if (first_pfx_printed) {
1778 /* padding to prepare row only
1779 * for ip addr */
1780 vty_out(vty, "%-40s", "");
1781 if (v6_list_size > 1)
1782 vty_out(vty, "+ ");
1783 vty_out(vty, "%pFX\n", p);
1784 } else {
1785 if (v6_list_size > 1)
1786 vty_out(vty, "+ ");
1787 vty_out(vty, "%pFX\n", p);
1788 }
1789 first_pfx_printed = true;
1790 break;
1791 }
1792 }
1793 }
1794 if (!first_pfx_printed)
1795 vty_out(vty, "\n");
1796 }
1797 vty_out(vty, "\n");
1798 }
1799
1800 static void ifs_dump_brief_vty_json(json_object *json, struct vrf *vrf)
1801 {
1802 struct connected *connected;
1803 struct listnode *node;
1804 struct interface *ifp;
1805
1806 FOR_ALL_INTERFACES (vrf, ifp) {
1807 json_object *json_if;
1808 json_object *json_addrs;
1809
1810 json_if = json_object_new_object();
1811 json_object_object_add(json, ifp->name, json_if);
1812
1813 json_object_string_add(json_if, "status",
1814 if_is_up(ifp) ? "up" : "down");
1815 json_object_string_add(json_if, "vrfName", vrf->name);
1816
1817 json_addrs = json_object_new_array();
1818 json_object_object_add(json_if, "addresses", json_addrs);
1819 for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, connected)) {
1820 if (CHECK_FLAG(connected->conf, ZEBRA_IFC_REAL)
1821 && !CHECK_FLAG(connected->flags,
1822 ZEBRA_IFA_SECONDARY)
1823 && !(connected->address->family == AF_INET6
1824 && IN6_IS_ADDR_LINKLOCAL(
1825 &connected->address->u.prefix6))) {
1826 char buf[PREFIX2STR_BUFFER];
1827
1828 json_array_string_add(
1829 json_addrs,
1830 prefix2str(connected->address, buf,
1831 sizeof(buf)));
1832 }
1833 }
1834 }
1835 }
1836
1837 const char *zebra_protodown_rc_str(uint32_t protodown_rc, char *pd_buf,
1838 uint32_t pd_buf_len)
1839 {
1840 pd_buf[0] = '\0';
1841 size_t len;
1842
1843 strlcat(pd_buf, "(", pd_buf_len);
1844
1845 if (CHECK_FLAG(protodown_rc, ZEBRA_PROTODOWN_EXTERNAL))
1846 strlcat(pd_buf, "external,", pd_buf_len);
1847
1848 if (CHECK_FLAG(protodown_rc, ZEBRA_PROTODOWN_EVPN_STARTUP_DELAY))
1849 strlcat(pd_buf, "startup-delay,", pd_buf_len);
1850
1851 if (CHECK_FLAG(protodown_rc, ZEBRA_PROTODOWN_EVPN_UPLINK_DOWN))
1852 strlcat(pd_buf, "uplinks-down,", pd_buf_len);
1853
1854 if (CHECK_FLAG(protodown_rc, ZEBRA_PROTODOWN_VRRP))
1855 strlcat(pd_buf, "vrrp,", pd_buf_len);
1856
1857 if (CHECK_FLAG(protodown_rc, ZEBRA_PROTODOWN_SHARP))
1858 strlcat(pd_buf, "sharp,", pd_buf_len);
1859
1860 len = strnlen(pd_buf, pd_buf_len);
1861
1862 /* Remove trailing comma */
1863 if (pd_buf[len - 1] == ',')
1864 pd_buf[len - 1] = '\0';
1865
1866 strlcat(pd_buf, ")", pd_buf_len);
1867
1868 return pd_buf;
1869 }
1870
1871 static inline bool if_is_protodown_applicable(struct interface *ifp)
1872 {
1873 if (IS_ZEBRA_IF_BOND(ifp))
1874 return false;
1875
1876 return true;
1877 }
1878
1879 static void zebra_vxlan_if_vni_dump_vty(struct vty *vty,
1880 struct zebra_vxlan_vni *vni)
1881 {
1882 char str[INET6_ADDRSTRLEN];
1883
1884 vty_out(vty, " VxLAN Id %u", vni->vni);
1885 if (vni->access_vlan)
1886 vty_out(vty, " Access VLAN Id %u\n", vni->access_vlan);
1887
1888 if (vni->mcast_grp.s_addr != INADDR_ANY)
1889 vty_out(vty, " Mcast Group %s",
1890 inet_ntop(AF_INET, &vni->mcast_grp, str, sizeof(str)));
1891 }
1892
1893 static void zebra_vxlan_if_vni_hash_dump_vty(struct hash_bucket *bucket,
1894 void *ctxt)
1895 {
1896 struct vty *vty;
1897 struct zebra_vxlan_vni *vni;
1898
1899 vni = (struct zebra_vxlan_vni *)bucket->data;
1900 vty = (struct vty *)ctxt;
1901
1902 zebra_vxlan_if_vni_dump_vty(vty, vni);
1903 }
1904
1905 static void zebra_vxlan_if_dump_vty(struct vty *vty, struct zebra_if *zebra_if)
1906 {
1907 struct zebra_l2info_vxlan *vxlan_info;
1908 struct zebra_vxlan_vni_info *vni_info;
1909
1910 vxlan_info = &zebra_if->l2info.vxl;
1911 vni_info = &vxlan_info->vni_info;
1912
1913 if (vxlan_info->vtep_ip.s_addr != INADDR_ANY)
1914 vty_out(vty, " VTEP IP: %pI4", &vxlan_info->vtep_ip);
1915
1916 if (vxlan_info->ifindex_link && (vxlan_info->link_nsid != NS_UNKNOWN)) {
1917 struct interface *ifp;
1918
1919 ifp = if_lookup_by_index_per_ns(
1920 zebra_ns_lookup(vxlan_info->link_nsid),
1921 vxlan_info->ifindex_link);
1922 vty_out(vty, " Link Interface %s",
1923 ifp == NULL ? "Unknown" : ifp->name);
1924 }
1925
1926 if (IS_ZEBRA_VXLAN_IF_VNI(zebra_if)) {
1927 zebra_vxlan_if_vni_dump_vty(vty, &vni_info->vni);
1928 } else {
1929 hash_iterate(vni_info->vni_table,
1930 zebra_vxlan_if_vni_hash_dump_vty, vty);
1931 }
1932
1933 vty_out(vty, "\n");
1934 }
1935
1936 /* Interface's information print out to vty interface. */
1937 static void if_dump_vty(struct vty *vty, struct interface *ifp)
1938 {
1939 struct connected *connected;
1940 struct nbr_connected *nbr_connected;
1941 struct listnode *node;
1942 struct route_node *rn;
1943 struct zebra_if *zebra_if;
1944 char pd_buf[ZEBRA_PROTODOWN_RC_STR_LEN];
1945
1946 zebra_if = ifp->info;
1947
1948 vty_out(vty, "Interface %s is ", ifp->name);
1949 if (if_is_up(ifp)) {
1950 vty_out(vty, "up, line protocol ");
1951
1952 if (CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_LINKDETECTION)) {
1953 if (if_is_running(ifp))
1954 vty_out(vty, "is up\n");
1955 else
1956 vty_out(vty, "is down\n");
1957 } else {
1958 vty_out(vty, "detection is disabled\n");
1959 }
1960 } else {
1961 vty_out(vty, "down\n");
1962 }
1963
1964 vty_out(vty, " Link ups: %5u last: %s\n", zebra_if->up_count,
1965 zebra_if->up_last[0] ? zebra_if->up_last : "(never)");
1966 vty_out(vty, " Link downs: %5u last: %s\n", zebra_if->down_count,
1967 zebra_if->down_last[0] ? zebra_if->down_last : "(never)");
1968
1969 zebra_ptm_show_status(vty, NULL, ifp);
1970
1971 vty_out(vty, " vrf: %s\n", ifp->vrf->name);
1972
1973 if (ifp->desc)
1974 vty_out(vty, " Description: %s\n", ifp->desc);
1975 if (zebra_if->desc)
1976 vty_out(vty, " OS Description: %s\n", zebra_if->desc);
1977
1978 if (ifp->ifindex == IFINDEX_INTERNAL) {
1979 vty_out(vty, " pseudo interface\n");
1980 return;
1981 } else if (!CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE)) {
1982 vty_out(vty, " index %d inactive interface\n", ifp->ifindex);
1983 return;
1984 }
1985
1986 vty_out(vty, " index %d metric %d mtu %d speed %u ", ifp->ifindex,
1987 ifp->metric, ifp->mtu, ifp->speed);
1988 if (ifp->mtu6 != ifp->mtu)
1989 vty_out(vty, "mtu6 %d ", ifp->mtu6);
1990 vty_out(vty, "\n flags: %s\n", if_flag_dump(ifp->flags));
1991
1992 if (zebra_if->mpls)
1993 vty_out(vty, " MPLS enabled\n");
1994
1995 if (zebra_if->linkdown)
1996 vty_out(vty, " Ignore all v4 routes with linkdown\n");
1997 if (zebra_if->linkdownv6)
1998 vty_out(vty, " Ignore all v6 routes with linkdown\n");
1999
2000 if (zebra_if->v4mcast_on)
2001 vty_out(vty, " v4 Multicast forwarding is on\n");
2002 if (zebra_if->v6mcast_on)
2003 vty_out(vty, " v6 Multicast forwarding is on\n");
2004
2005 /* Hardware address. */
2006 vty_out(vty, " Type: %s\n", if_link_type_str(ifp->ll_type));
2007 if (ifp->hw_addr_len != 0) {
2008 int i;
2009
2010 vty_out(vty, " HWaddr: ");
2011 for (i = 0; i < ifp->hw_addr_len; i++)
2012 vty_out(vty, "%s%02x", i == 0 ? "" : ":",
2013 ifp->hw_addr[i]);
2014 vty_out(vty, "\n");
2015 }
2016
2017 /* Bandwidth in Mbps */
2018 if (ifp->bandwidth != 0) {
2019 vty_out(vty, " bandwidth %u Mbps", ifp->bandwidth);
2020 vty_out(vty, "\n");
2021 }
2022
2023 for (rn = route_top(zebra_if->ipv4_subnets); rn; rn = route_next(rn)) {
2024 if (!rn->info)
2025 continue;
2026
2027 for (ALL_LIST_ELEMENTS_RO((struct list *)rn->info, node,
2028 connected))
2029 connected_dump_vty(vty, NULL, connected);
2030 }
2031
2032 for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, connected)) {
2033 if (CHECK_FLAG(connected->conf, ZEBRA_IFC_REAL)
2034 && (connected->address->family == AF_INET6))
2035 connected_dump_vty(vty, NULL, connected);
2036 }
2037
2038 vty_out(vty, " Interface Type %s\n",
2039 zebra_ziftype_2str(zebra_if->zif_type));
2040 vty_out(vty, " Interface Slave Type %s\n",
2041 zebra_zifslavetype_2str(zebra_if->zif_slave_type));
2042
2043 if (IS_ZEBRA_IF_BRIDGE(ifp)) {
2044 vty_out(vty, " Bridge VLAN-aware: %s\n",
2045 IS_ZEBRA_IF_BRIDGE_VLAN_AWARE(zebra_if) ? "yes" : "no");
2046 } else if (IS_ZEBRA_IF_VLAN(ifp)) {
2047 struct zebra_l2info_vlan *vlan_info;
2048
2049 vlan_info = &zebra_if->l2info.vl;
2050 vty_out(vty, " VLAN Id %u\n", vlan_info->vid);
2051 } else if (IS_ZEBRA_IF_VXLAN(ifp)) {
2052 zebra_vxlan_if_dump_vty(vty, zebra_if);
2053 } else if (IS_ZEBRA_IF_GRE(ifp)) {
2054 struct zebra_l2info_gre *gre_info;
2055
2056 gre_info = &zebra_if->l2info.gre;
2057 if (gre_info->vtep_ip.s_addr != INADDR_ANY) {
2058 vty_out(vty, " VTEP IP: %pI4", &gre_info->vtep_ip);
2059 if (gre_info->vtep_ip_remote.s_addr != INADDR_ANY)
2060 vty_out(vty, " , remote %pI4",
2061 &gre_info->vtep_ip_remote);
2062 vty_out(vty, "\n");
2063 }
2064 if (gre_info->ifindex_link &&
2065 (gre_info->link_nsid != NS_UNKNOWN)) {
2066 struct interface *ifp;
2067
2068 ifp = if_lookup_by_index_per_ns(
2069 zebra_ns_lookup(gre_info->link_nsid),
2070 gre_info->ifindex_link);
2071 vty_out(vty, " Link Interface %s\n",
2072 ifp == NULL ? "Unknown" :
2073 ifp->name);
2074 }
2075 }
2076
2077 if (IS_ZEBRA_IF_BRIDGE_SLAVE(ifp)) {
2078 struct zebra_l2info_brslave *br_slave;
2079
2080 br_slave = &zebra_if->brslave_info;
2081 if (br_slave->bridge_ifindex != IFINDEX_INTERNAL) {
2082 if (br_slave->br_if)
2083 vty_out(vty, " Master interface: %s\n",
2084 br_slave->br_if->name);
2085 else
2086 vty_out(vty, " Master ifindex: %u\n",
2087 br_slave->bridge_ifindex);
2088 }
2089 }
2090
2091 if (IS_ZEBRA_IF_BOND_SLAVE(ifp)) {
2092 struct zebra_l2info_bondslave *bond_slave;
2093
2094 bond_slave = &zebra_if->bondslave_info;
2095 if (bond_slave->bond_ifindex != IFINDEX_INTERNAL) {
2096 if (bond_slave->bond_if)
2097 vty_out(vty, " Master interface: %s\n",
2098 bond_slave->bond_if->name);
2099 else
2100 vty_out(vty, " Master ifindex: %u\n",
2101 bond_slave->bond_ifindex);
2102 }
2103 }
2104
2105 if (zebra_if->flags & ZIF_FLAG_LACP_BYPASS)
2106 vty_out(vty, " LACP bypass: on\n");
2107
2108 zebra_evpn_if_es_print(vty, NULL, zebra_if);
2109 vty_out(vty, " protodown: %s %s\n",
2110 (ZEBRA_IF_IS_PROTODOWN(zebra_if)) ? "on" : "off",
2111 if_is_protodown_applicable(ifp) ? "" : "(n/a)");
2112 if (zebra_if->protodown_rc)
2113 vty_out(vty, " protodown reasons: %s\n",
2114 zebra_protodown_rc_str(zebra_if->protodown_rc, pd_buf,
2115 sizeof(pd_buf)));
2116
2117 if (zebra_if->link_ifindex != IFINDEX_INTERNAL) {
2118 if (zebra_if->link)
2119 vty_out(vty, " Parent interface: %s\n", zebra_if->link->name);
2120 else
2121 vty_out(vty, " Parent ifindex: %d\n", zebra_if->link_ifindex);
2122 }
2123
2124 if (HAS_LINK_PARAMS(ifp)) {
2125 int i;
2126 struct if_link_params *iflp = ifp->link_params;
2127 vty_out(vty, " Traffic Engineering Link Parameters:\n");
2128 if (IS_PARAM_SET(iflp, LP_TE_METRIC))
2129 vty_out(vty, " TE metric %u\n", iflp->te_metric);
2130 if (IS_PARAM_SET(iflp, LP_MAX_BW))
2131 vty_out(vty, " Maximum Bandwidth %g (Byte/s)\n",
2132 iflp->max_bw);
2133 if (IS_PARAM_SET(iflp, LP_MAX_RSV_BW))
2134 vty_out(vty,
2135 " Maximum Reservable Bandwidth %g (Byte/s)\n",
2136 iflp->max_rsv_bw);
2137 if (IS_PARAM_SET(iflp, LP_UNRSV_BW)) {
2138 vty_out(vty,
2139 " Unreserved Bandwidth per Class Type in Byte/s:\n");
2140 for (i = 0; i < MAX_CLASS_TYPE; i += 2)
2141 vty_out(vty,
2142 " [%d]: %g (Bytes/sec),\t[%d]: %g (Bytes/sec)\n",
2143 i, iflp->unrsv_bw[i], i + 1,
2144 iflp->unrsv_bw[i + 1]);
2145 }
2146
2147 if (IS_PARAM_SET(iflp, LP_ADM_GRP))
2148 vty_out(vty, " Administrative Group:%u\n",
2149 iflp->admin_grp);
2150 if (IS_PARAM_SET(iflp, LP_DELAY)) {
2151 vty_out(vty, " Link Delay Average: %u (micro-sec.)",
2152 iflp->av_delay);
2153 if (IS_PARAM_SET(iflp, LP_MM_DELAY)) {
2154 vty_out(vty, " Min: %u (micro-sec.)",
2155 iflp->min_delay);
2156 vty_out(vty, " Max: %u (micro-sec.)",
2157 iflp->max_delay);
2158 }
2159 vty_out(vty, "\n");
2160 }
2161 if (IS_PARAM_SET(iflp, LP_DELAY_VAR))
2162 vty_out(vty,
2163 " Link Delay Variation %u (micro-sec.)\n",
2164 iflp->delay_var);
2165 if (IS_PARAM_SET(iflp, LP_PKT_LOSS))
2166 vty_out(vty, " Link Packet Loss %g (in %%)\n",
2167 iflp->pkt_loss);
2168 if (IS_PARAM_SET(iflp, LP_AVA_BW))
2169 vty_out(vty, " Available Bandwidth %g (Byte/s)\n",
2170 iflp->ava_bw);
2171 if (IS_PARAM_SET(iflp, LP_RES_BW))
2172 vty_out(vty, " Residual Bandwidth %g (Byte/s)\n",
2173 iflp->res_bw);
2174 if (IS_PARAM_SET(iflp, LP_USE_BW))
2175 vty_out(vty, " Utilized Bandwidth %g (Byte/s)\n",
2176 iflp->use_bw);
2177 if (IS_PARAM_SET(iflp, LP_RMT_AS))
2178 vty_out(vty, " Neighbor ASBR IP: %pI4 AS: %u \n",
2179 &iflp->rmt_ip, iflp->rmt_as);
2180 }
2181
2182 hook_call(zebra_if_extra_info, vty, ifp);
2183
2184 if (listhead(ifp->nbr_connected))
2185 vty_out(vty, " Neighbor address(s):\n");
2186 for (ALL_LIST_ELEMENTS_RO(ifp->nbr_connected, node, nbr_connected))
2187 nbr_connected_dump_vty(vty, NULL, nbr_connected);
2188
2189 #ifdef HAVE_PROC_NET_DEV
2190 /* Statistics print out using proc file system. */
2191 vty_out(vty,
2192 " %lu input packets (%lu multicast), %lu bytes, %lu dropped\n",
2193 ifp->stats.rx_packets, ifp->stats.rx_multicast,
2194 ifp->stats.rx_bytes, ifp->stats.rx_dropped);
2195
2196 vty_out(vty,
2197 " %lu input errors, %lu length, %lu overrun, %lu CRC, %lu frame\n",
2198 ifp->stats.rx_errors, ifp->stats.rx_length_errors,
2199 ifp->stats.rx_over_errors, ifp->stats.rx_crc_errors,
2200 ifp->stats.rx_frame_errors);
2201
2202 vty_out(vty, " %lu fifo, %lu missed\n", ifp->stats.rx_fifo_errors,
2203 ifp->stats.rx_missed_errors);
2204
2205 vty_out(vty, " %lu output packets, %lu bytes, %lu dropped\n",
2206 ifp->stats.tx_packets, ifp->stats.tx_bytes,
2207 ifp->stats.tx_dropped);
2208
2209 vty_out(vty,
2210 " %lu output errors, %lu aborted, %lu carrier, %lu fifo, %lu heartbeat\n",
2211 ifp->stats.tx_errors, ifp->stats.tx_aborted_errors,
2212 ifp->stats.tx_carrier_errors, ifp->stats.tx_fifo_errors,
2213 ifp->stats.tx_heartbeat_errors);
2214
2215 vty_out(vty, " %lu window, %lu collisions\n",
2216 ifp->stats.tx_window_errors, ifp->stats.collisions);
2217 #endif /* HAVE_PROC_NET_DEV */
2218
2219 #ifdef HAVE_NET_RT_IFLIST
2220 /* Statistics print out using sysctl (). */
2221 vty_out(vty,
2222 " input packets %llu, bytes %llu, dropped %llu, multicast packets %llu\n",
2223 (unsigned long long)ifp->stats.ifi_ipackets,
2224 (unsigned long long)ifp->stats.ifi_ibytes,
2225 (unsigned long long)ifp->stats.ifi_iqdrops,
2226 (unsigned long long)ifp->stats.ifi_imcasts);
2227
2228 vty_out(vty, " input errors %llu\n",
2229 (unsigned long long)ifp->stats.ifi_ierrors);
2230
2231 vty_out(vty,
2232 " output packets %llu, bytes %llu, multicast packets %llu\n",
2233 (unsigned long long)ifp->stats.ifi_opackets,
2234 (unsigned long long)ifp->stats.ifi_obytes,
2235 (unsigned long long)ifp->stats.ifi_omcasts);
2236
2237 vty_out(vty, " output errors %llu\n",
2238 (unsigned long long)ifp->stats.ifi_oerrors);
2239
2240 vty_out(vty, " collisions %llu\n",
2241 (unsigned long long)ifp->stats.ifi_collisions);
2242 #endif /* HAVE_NET_RT_IFLIST */
2243 }
2244
2245 static void zebra_vxlan_if_vni_dump_vty_json(json_object *json_if,
2246 struct zebra_vxlan_vni *vni)
2247 {
2248 json_object_int_add(json_if, "vxlanId", vni->vni);
2249 if (vni->access_vlan)
2250 json_object_int_add(json_if, "accessVlanId", vni->access_vlan);
2251 if (vni->mcast_grp.s_addr != INADDR_ANY)
2252 json_object_string_addf(json_if, "mcastGroup", "%pI4",
2253 &vni->mcast_grp);
2254 }
2255
2256 static void zebra_vxlan_if_vni_hash_dump_vty_json(struct hash_bucket *bucket,
2257 void *ctxt)
2258 {
2259 json_object *json_if;
2260 struct zebra_vxlan_vni *vni;
2261
2262 vni = (struct zebra_vxlan_vni *)bucket->data;
2263 json_if = (json_object *)ctxt;
2264
2265 zebra_vxlan_if_vni_dump_vty_json(json_if, vni);
2266 }
2267
2268 static void zebra_vxlan_if_dump_vty_json(json_object *json_if,
2269 struct zebra_if *zebra_if)
2270 {
2271 struct zebra_l2info_vxlan *vxlan_info;
2272 struct zebra_vxlan_vni_info *vni_info;
2273
2274 vxlan_info = &zebra_if->l2info.vxl;
2275 vni_info = &vxlan_info->vni_info;
2276
2277 if (vxlan_info->vtep_ip.s_addr != INADDR_ANY)
2278 json_object_string_addf(json_if, "vtepIp", "%pI4",
2279 &vxlan_info->vtep_ip);
2280
2281 if (vxlan_info->ifindex_link && (vxlan_info->link_nsid != NS_UNKNOWN)) {
2282 struct interface *ifp;
2283
2284 ifp = if_lookup_by_index_per_ns(
2285 zebra_ns_lookup(vxlan_info->link_nsid),
2286 vxlan_info->ifindex_link);
2287 json_object_string_add(json_if, "linkInterface",
2288 ifp == NULL ? "Unknown" : ifp->name);
2289 }
2290 if (IS_ZEBRA_VXLAN_IF_VNI(zebra_if)) {
2291 zebra_vxlan_if_vni_dump_vty_json(json_if, &vni_info->vni);
2292 } else {
2293 hash_iterate(vni_info->vni_table,
2294 zebra_vxlan_if_vni_hash_dump_vty_json, json_if);
2295 }
2296 }
2297
2298 static void if_dump_vty_json(struct vty *vty, struct interface *ifp,
2299 json_object *json)
2300 {
2301 struct connected *connected;
2302 struct nbr_connected *nbr_connected;
2303 struct listnode *node;
2304 struct route_node *rn;
2305 struct zebra_if *zebra_if;
2306 char pd_buf[ZEBRA_PROTODOWN_RC_STR_LEN];
2307 char buf[BUFSIZ];
2308 json_object *json_if;
2309 json_object *json_addrs;
2310
2311 json_if = json_object_new_object();
2312 json_object_object_add(json, ifp->name, json_if);
2313
2314 if (if_is_up(ifp)) {
2315 json_object_string_add(json_if, "administrativeStatus", "up");
2316
2317 if (CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_LINKDETECTION)) {
2318 json_object_string_add(json_if, "operationalStatus",
2319 if_is_running(ifp) ? "up"
2320 : "down");
2321 json_object_boolean_add(json_if, "linkDetection", true);
2322 } else {
2323 json_object_boolean_add(json_if, "linkDetection",
2324 false);
2325 }
2326 } else {
2327 json_object_string_add(json_if, "administrativeStatus", "down");
2328 }
2329
2330 zebra_if = ifp->info;
2331
2332 json_object_int_add(json_if, "linkUps", zebra_if->up_count);
2333 json_object_int_add(json_if, "linkDowns", zebra_if->down_count);
2334 if (zebra_if->up_last[0])
2335 json_object_string_add(json_if, "lastLinkUp",
2336 zebra_if->up_last);
2337 if (zebra_if->down_last[0])
2338 json_object_string_add(json_if, "lastLinkDown",
2339 zebra_if->down_last);
2340
2341 zebra_ptm_show_status(vty, json, ifp);
2342
2343 json_object_string_add(json_if, "vrfName", ifp->vrf->name);
2344
2345 if (ifp->desc)
2346 json_object_string_add(json_if, "description", ifp->desc);
2347 if (zebra_if->desc)
2348 json_object_string_add(json_if, "OsDescription",
2349 zebra_if->desc);
2350
2351 json_object_boolean_add(json_if, "mplsEnabled", zebra_if->mpls);
2352 json_object_boolean_add(json_if, "linkDown", zebra_if->linkdown);
2353 json_object_boolean_add(json_if, "linkDownV6", zebra_if->linkdownv6);
2354 json_object_boolean_add(json_if, "mcForwardingV4",
2355 zebra_if->v4mcast_on);
2356 json_object_boolean_add(json_if, "mcForwardingV6",
2357 zebra_if->v6mcast_on);
2358
2359 if (ifp->ifindex == IFINDEX_INTERNAL) {
2360 json_object_boolean_add(json_if, "pseudoInterface", true);
2361 return;
2362 } else if (!CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE)) {
2363 json_object_int_add(json_if, "index", ifp->ifindex);
2364 return;
2365 }
2366
2367 json_object_boolean_add(json_if, "pseudoInterface", false);
2368 json_object_int_add(json_if, "index", ifp->ifindex);
2369 json_object_int_add(json_if, "metric", ifp->metric);
2370 json_object_int_add(json_if, "mtu", ifp->mtu);
2371 if (ifp->mtu6 != ifp->mtu)
2372 json_object_int_add(json_if, "mtu6", ifp->mtu6);
2373 json_object_int_add(json_if, "speed", ifp->speed);
2374 json_object_string_add(json_if, "flags", if_flag_dump(ifp->flags));
2375
2376 /* Hardware address. */
2377 json_object_string_add(json_if, "type", if_link_type_str(ifp->ll_type));
2378 if (ifp->hw_addr_len != 0) {
2379 char hwbuf[BUFSIZ];
2380
2381 hwbuf[0] = '\0';
2382 for (int i = 0; i < ifp->hw_addr_len; i++) {
2383 snprintf(buf, sizeof(buf), "%s%02x", i == 0 ? "" : ":",
2384 ifp->hw_addr[i]);
2385 strlcat(hwbuf, buf, sizeof(hwbuf));
2386 }
2387 json_object_string_add(json_if, "hardwareAddress", hwbuf);
2388 }
2389
2390 /* Bandwidth in Mbps */
2391 if (ifp->bandwidth != 0)
2392 json_object_int_add(json_if, "bandwidth", ifp->bandwidth);
2393
2394
2395 /* IP addresses. */
2396 json_addrs = json_object_new_array();
2397 json_object_object_add(json_if, "ipAddresses", json_addrs);
2398
2399 for (rn = route_top(zebra_if->ipv4_subnets); rn; rn = route_next(rn)) {
2400 if (!rn->info)
2401 continue;
2402
2403 for (ALL_LIST_ELEMENTS_RO((struct list *)rn->info, node,
2404 connected))
2405 connected_dump_vty(vty, json_addrs, connected);
2406 }
2407
2408 for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, connected)) {
2409 if (CHECK_FLAG(connected->conf, ZEBRA_IFC_REAL)
2410 && (connected->address->family == AF_INET6))
2411 connected_dump_vty(vty, json_addrs, connected);
2412 }
2413
2414 json_object_string_add(json_if, "interfaceType",
2415 zebra_ziftype_2str(zebra_if->zif_type));
2416 json_object_string_add(
2417 json_if, "interfaceSlaveType",
2418 zebra_zifslavetype_2str(zebra_if->zif_slave_type));
2419
2420 if (IS_ZEBRA_IF_BRIDGE(ifp)) {
2421 struct zebra_l2info_bridge *bridge_info;
2422
2423 bridge_info = &zebra_if->l2info.br;
2424 json_object_boolean_add(json_if, "bridgeVlanAware",
2425 bridge_info->bridge.vlan_aware);
2426 } else if (IS_ZEBRA_IF_VLAN(ifp)) {
2427 struct zebra_l2info_vlan *vlan_info;
2428
2429 vlan_info = &zebra_if->l2info.vl;
2430 json_object_int_add(json_if, "vlanId", vlan_info->vid);
2431 } else if (IS_ZEBRA_IF_VXLAN(ifp)) {
2432 zebra_vxlan_if_dump_vty_json(json_if, zebra_if);
2433
2434 } else if (IS_ZEBRA_IF_GRE(ifp)) {
2435 struct zebra_l2info_gre *gre_info;
2436
2437 gre_info = &zebra_if->l2info.gre;
2438 if (gre_info->vtep_ip.s_addr != INADDR_ANY) {
2439 json_object_string_addf(json_if, "vtepIp", "%pI4",
2440 &gre_info->vtep_ip);
2441 if (gre_info->vtep_ip_remote.s_addr != INADDR_ANY)
2442 json_object_string_addf(
2443 json_if, "vtepRemoteIp", "%pI4",
2444 &gre_info->vtep_ip_remote);
2445 }
2446 if (gre_info->ifindex_link
2447 && (gre_info->link_nsid != NS_UNKNOWN)) {
2448 struct interface *ifp;
2449
2450 ifp = if_lookup_by_index_per_ns(
2451 zebra_ns_lookup(gre_info->link_nsid),
2452 gre_info->ifindex_link);
2453 json_object_string_add(json_if, "linkInterface",
2454 ifp == NULL ? "Unknown"
2455 : ifp->name);
2456 }
2457 }
2458
2459 if (IS_ZEBRA_IF_BRIDGE_SLAVE(ifp)) {
2460 struct zebra_l2info_brslave *br_slave;
2461
2462 br_slave = &zebra_if->brslave_info;
2463 if (br_slave->bridge_ifindex != IFINDEX_INTERNAL) {
2464 if (br_slave->br_if)
2465 json_object_string_add(json_if,
2466 "masterInterface",
2467 br_slave->br_if->name);
2468 else
2469 json_object_int_add(json_if, "masterIfindex",
2470 br_slave->bridge_ifindex);
2471 }
2472 }
2473
2474 if (IS_ZEBRA_IF_BOND_SLAVE(ifp)) {
2475 struct zebra_l2info_bondslave *bond_slave;
2476
2477 bond_slave = &zebra_if->bondslave_info;
2478 if (bond_slave->bond_ifindex != IFINDEX_INTERNAL) {
2479 if (bond_slave->bond_if)
2480 json_object_string_add(
2481 json_if, "masterInterface",
2482 bond_slave->bond_if->name);
2483 else
2484 json_object_int_add(json_if, "masterIfindex",
2485 bond_slave->bond_ifindex);
2486 }
2487 }
2488
2489 json_object_boolean_add(
2490 json_if, "lacpBypass",
2491 CHECK_FLAG(zebra_if->flags, ZIF_FLAG_LACP_BYPASS));
2492
2493 zebra_evpn_if_es_print(vty, json_if, zebra_if);
2494
2495 if (if_is_protodown_applicable(ifp)) {
2496 json_object_string_add(
2497 json_if, "protodown",
2498 (ZEBRA_IF_IS_PROTODOWN(zebra_if)) ? "on" : "off");
2499 if (zebra_if->protodown_rc)
2500 json_object_string_add(
2501 json_if, "protodownReason",
2502 zebra_protodown_rc_str(zebra_if->protodown_rc,
2503 pd_buf, sizeof(pd_buf)));
2504 }
2505
2506 if (zebra_if->link_ifindex != IFINDEX_INTERNAL) {
2507 if (zebra_if->link)
2508 json_object_string_add(json_if, "parentInterface",
2509 zebra_if->link->name);
2510 else
2511 json_object_int_add(json_if, "parentIfindex",
2512 zebra_if->link_ifindex);
2513 }
2514
2515 if (HAS_LINK_PARAMS(ifp)) {
2516 struct if_link_params *iflp = ifp->link_params;
2517 json_object *json_te;
2518
2519 json_te = json_object_new_object();
2520 json_object_object_add(
2521 json_if, "trafficEngineeringLinkParameters", json_te);
2522
2523 if (IS_PARAM_SET(iflp, LP_TE_METRIC))
2524 json_object_int_add(json_te, "teMetric",
2525 iflp->te_metric);
2526 if (IS_PARAM_SET(iflp, LP_MAX_BW))
2527 json_object_double_add(json_te, "maximumBandwidth",
2528 iflp->max_bw);
2529 if (IS_PARAM_SET(iflp, LP_MAX_RSV_BW))
2530 json_object_double_add(json_te,
2531 "maximumReservableBandwidth",
2532 iflp->max_rsv_bw);
2533 if (IS_PARAM_SET(iflp, LP_UNRSV_BW)) {
2534 json_object *json_bws;
2535
2536 json_bws = json_object_new_object();
2537 json_object_object_add(json_te, "unreservedBandwidth",
2538 json_bws);
2539 for (unsigned int i = 0; i < MAX_CLASS_TYPE; ++i) {
2540 char buf_ct[64];
2541
2542 snprintf(buf_ct, sizeof(buf_ct), "classType%u",
2543 i);
2544 json_object_double_add(json_bws, buf_ct,
2545 iflp->unrsv_bw[i]);
2546 }
2547 }
2548
2549 if (IS_PARAM_SET(iflp, LP_ADM_GRP))
2550 json_object_int_add(json_te, "administrativeGroup",
2551 iflp->admin_grp);
2552 if (IS_PARAM_SET(iflp, LP_DELAY)) {
2553 json_object_int_add(json_te, "linkDelayAverage",
2554 iflp->av_delay);
2555 if (IS_PARAM_SET(iflp, LP_MM_DELAY)) {
2556 json_object_int_add(json_te, "linkDelayMinimum",
2557 iflp->min_delay);
2558 json_object_int_add(json_te, "linkDelayMaximum",
2559 iflp->max_delay);
2560 }
2561 }
2562 if (IS_PARAM_SET(iflp, LP_DELAY_VAR))
2563 json_object_int_add(json_te, "linkDelayVariation",
2564 iflp->delay_var);
2565 if (IS_PARAM_SET(iflp, LP_PKT_LOSS))
2566 json_object_double_add(json_te, "linkPacketLoss",
2567 iflp->pkt_loss);
2568 if (IS_PARAM_SET(iflp, LP_AVA_BW))
2569 json_object_double_add(json_te, "availableBandwidth",
2570 iflp->ava_bw);
2571 if (IS_PARAM_SET(iflp, LP_RES_BW))
2572 json_object_double_add(json_te, "residualBandwidth",
2573 iflp->res_bw);
2574 if (IS_PARAM_SET(iflp, LP_USE_BW))
2575 json_object_double_add(json_te, "utilizedBandwidth",
2576 iflp->use_bw);
2577 if (IS_PARAM_SET(iflp, LP_RMT_AS))
2578 json_object_string_addf(json_te, "neighborAsbrIp",
2579 "%pI4", &iflp->rmt_ip);
2580 json_object_int_add(json_te, "neighborAsbrAs", iflp->rmt_as);
2581 }
2582
2583 if (listhead(ifp->nbr_connected)) {
2584 json_object *json_nbr_addrs;
2585
2586 json_nbr_addrs = json_object_new_array();
2587 json_object_object_add(json_if, "neighborIpAddresses",
2588 json_nbr_addrs);
2589
2590 for (ALL_LIST_ELEMENTS_RO(ifp->nbr_connected, node,
2591 nbr_connected))
2592 nbr_connected_dump_vty(vty, json_nbr_addrs,
2593 nbr_connected);
2594 }
2595
2596 #ifdef HAVE_PROC_NET_DEV
2597 json_object_int_add(json_if, "inputPackets", stats.rx_packets);
2598 json_object_int_add(json_if, "inputBytes", ifp->stats.rx_bytes);
2599 json_object_int_add(json_if, "inputDropped", ifp->stats.rx_dropped);
2600 json_object_int_add(json_if, "inputMulticastPackets",
2601 ifp->stats.rx_multicast);
2602 json_object_int_add(json_if, "inputErrors", ifp->stats.rx_errors);
2603 json_object_int_add(json_if, "inputLengthErrors",
2604 ifp->stats.rx_length_errors);
2605 json_object_int_add(json_if, "inputOverrunErrors",
2606 ifp->stats.rx_over_errors);
2607 json_object_int_add(json_if, "inputCrcErrors",
2608 ifp->stats.rx_crc_errors);
2609 json_object_int_add(json_if, "inputFrameErrors",
2610 ifp->stats.rx_frame_errors);
2611 json_object_int_add(json_if, "inputFifoErrors",
2612 ifp->stats.rx_fifo_errors);
2613 json_object_int_add(json_if, "inputMissedErrors",
2614 ifp->stats.rx_missed_errors);
2615 json_object_int_add(json_if, "outputPackets", ifp->stats.tx_packets);
2616 json_object_int_add(json_if, "outputBytes", ifp->stats.tx_bytes);
2617 json_object_int_add(json_if, "outputDroppedPackets",
2618 ifp->stats.tx_dropped);
2619 json_object_int_add(json_if, "outputErrors", ifp->stats.tx_errors);
2620 json_object_int_add(json_if, "outputAbortedErrors",
2621 ifp->stats.tx_aborted_errors);
2622 json_object_int_add(json_if, "outputCarrierErrors",
2623 ifp->stats.tx_carrier_errors);
2624 json_object_int_add(json_if, "outputFifoErrors",
2625 ifp->stats.tx_fifo_errors);
2626 json_object_int_add(json_if, "outputHeartbeatErrors",
2627 ifp->stats.tx_heartbeat_errors);
2628 json_object_int_add(json_if, "outputWindowErrors",
2629 ifp->stats.tx_window_errors);
2630 json_object_int_add(json_if, "collisions", ifp->stats.collisions);
2631 #endif /* HAVE_PROC_NET_DEV */
2632
2633 #ifdef HAVE_NET_RT_IFLIST
2634 json_object_int_add(json_if, "inputPackets", ifp->stats.ifi_ipackets);
2635 json_object_int_add(json_if, "inputBytes", ifp->stats.ifi_ibytes);
2636 json_object_int_add(json_if, "inputDropd", ifp->stats.ifi_iqdrops);
2637 json_object_int_add(json_if, "inputMulticastPackets",
2638 ifp->stats.ifi_imcasts);
2639 json_object_int_add(json_if, "inputErrors", ifp->stats.ifi_ierrors);
2640 json_object_int_add(json_if, "outputPackets", ifp->stats.ifi_opackets);
2641 json_object_int_add(json_if, "outputBytes", ifp->stats.ifi_obytes);
2642 json_object_int_add(json_if, "outputMulticastPackets",
2643 ifp->stats.ifi_omcasts);
2644 json_object_int_add(json_if, "outputErrors", ifp->stats.ifi_oerrors);
2645 json_object_int_add(json_if, "collisions", ifp->stats.ifi_collisions);
2646 #endif /* HAVE_NET_RT_IFLIST */
2647 }
2648
2649 static void interface_update_stats(void)
2650 {
2651 #ifdef HAVE_PROC_NET_DEV
2652 /* If system has interface statistics via proc file system, update
2653 statistics. */
2654 ifstat_update_proc();
2655 #endif /* HAVE_PROC_NET_DEV */
2656 #ifdef HAVE_NET_RT_IFLIST
2657 ifstat_update_sysctl();
2658 #endif /* HAVE_NET_RT_IFLIST */
2659 }
2660
2661 #include "zebra/interface_clippy.c"
2662 /* Show all interfaces to vty. */
2663 DEFPY(show_interface, show_interface_cmd,
2664 "show interface vrf NAME$vrf_name [brief$brief] [json$uj]",
2665 SHOW_STR
2666 "Interface status and configuration\n"
2667 VRF_CMD_HELP_STR
2668 "Interface status and configuration summary\n"
2669 JSON_STR)
2670 {
2671 struct vrf *vrf;
2672 struct interface *ifp;
2673 json_object *json = NULL;
2674
2675 interface_update_stats();
2676
2677 vrf = vrf_lookup_by_name(vrf_name);
2678 if (!vrf) {
2679 if (uj)
2680 vty_out(vty, "{}\n");
2681 else
2682 vty_out(vty, "%% VRF %s not found\n", vrf_name);
2683 return CMD_WARNING;
2684 }
2685
2686 if (uj)
2687 json = json_object_new_object();
2688
2689 if (brief) {
2690 if (json)
2691 ifs_dump_brief_vty_json(json, vrf);
2692 else
2693 ifs_dump_brief_vty(vty, vrf);
2694 } else {
2695 FOR_ALL_INTERFACES (vrf, ifp) {
2696 if (json)
2697 if_dump_vty_json(vty, ifp, json);
2698 else
2699 if_dump_vty(vty, ifp);
2700 }
2701 }
2702
2703 if (json)
2704 vty_json(vty, json);
2705
2706 return CMD_SUCCESS;
2707 }
2708
2709
2710 /* Show all interfaces to vty. */
2711 DEFPY (show_interface_vrf_all,
2712 show_interface_vrf_all_cmd,
2713 "show interface [vrf all] [brief$brief] [json$uj]",
2714 SHOW_STR
2715 "Interface status and configuration\n"
2716 VRF_ALL_CMD_HELP_STR
2717 "Interface status and configuration summary\n"
2718 JSON_STR)
2719 {
2720 struct vrf *vrf;
2721 struct interface *ifp;
2722 json_object *json = NULL;
2723
2724 interface_update_stats();
2725
2726 if (uj)
2727 json = json_object_new_object();
2728
2729 /* All interface print. */
2730 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
2731 if (brief) {
2732 if (json)
2733 ifs_dump_brief_vty_json(json, vrf);
2734 else
2735 ifs_dump_brief_vty(vty, vrf);
2736 } else {
2737 FOR_ALL_INTERFACES (vrf, ifp) {
2738 if (json)
2739 if_dump_vty_json(vty, ifp, json);
2740 else
2741 if_dump_vty(vty, ifp);
2742 }
2743 }
2744 }
2745
2746 if (json)
2747 vty_json(vty, json);
2748
2749 return CMD_SUCCESS;
2750 }
2751
2752 /* Show specified interface to vty. */
2753
2754 DEFPY (show_interface_name_vrf,
2755 show_interface_name_vrf_cmd,
2756 "show interface IFNAME$ifname vrf NAME$vrf_name [json$uj]",
2757 SHOW_STR
2758 "Interface status and configuration\n"
2759 "Interface name\n"
2760 VRF_CMD_HELP_STR
2761 JSON_STR)
2762 {
2763 struct interface *ifp;
2764 struct vrf *vrf;
2765 json_object *json = NULL;
2766
2767 interface_update_stats();
2768
2769 vrf = vrf_lookup_by_name(vrf_name);
2770 if (!vrf) {
2771 if (uj)
2772 vty_out(vty, "{}\n");
2773 else
2774 vty_out(vty, "%% VRF %s not found\n", vrf_name);
2775 return CMD_WARNING;
2776 }
2777
2778 ifp = if_lookup_by_name_vrf(ifname, vrf);
2779 if (ifp == NULL) {
2780 if (uj)
2781 vty_out(vty, "{}\n");
2782 else
2783 vty_out(vty, "%% Can't find interface %s\n", ifname);
2784 return CMD_WARNING;
2785 }
2786
2787 if (uj)
2788 json = json_object_new_object();
2789
2790 if (json)
2791 if_dump_vty_json(vty, ifp, json);
2792 else
2793 if_dump_vty(vty, ifp);
2794
2795 if (json)
2796 vty_json(vty, json);
2797
2798 return CMD_SUCCESS;
2799 }
2800
2801 /* Show specified interface to vty. */
2802 DEFPY (show_interface_name_vrf_all,
2803 show_interface_name_vrf_all_cmd,
2804 "show interface IFNAME$ifname [vrf all] [json$uj]",
2805 SHOW_STR
2806 "Interface status and configuration\n"
2807 "Interface name\n"
2808 VRF_ALL_CMD_HELP_STR
2809 JSON_STR)
2810 {
2811 struct interface *ifp = NULL;
2812 struct interface *ifptmp;
2813 struct vrf *vrf;
2814 json_object *json = NULL;
2815 int count = 0;
2816
2817 interface_update_stats();
2818
2819 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
2820 ifptmp = if_lookup_by_name_vrf(ifname, vrf);
2821 if (ifptmp) {
2822 ifp = ifptmp;
2823 count++;
2824 if (!vrf_is_backend_netns())
2825 break;
2826 }
2827 }
2828
2829 if (ifp == NULL) {
2830 if (uj)
2831 vty_out(vty, "{}\n");
2832 else
2833 vty_out(vty, "%% Can't find interface %s\n", ifname);
2834 return CMD_WARNING;
2835 }
2836 if (count > 1) {
2837 if (uj) {
2838 vty_out(vty, "{}\n");
2839 } else {
2840 vty_out(vty,
2841 "%% There are multiple interfaces with name %s\n",
2842 ifname);
2843 vty_out(vty, "%% You must specify the VRF name\n");
2844 }
2845 return CMD_WARNING;
2846 }
2847
2848 if (uj)
2849 json = json_object_new_object();
2850
2851 if (json)
2852 if_dump_vty_json(vty, ifp, json);
2853 else
2854 if_dump_vty(vty, ifp);
2855
2856 if (json)
2857 vty_json(vty, json);
2858
2859 return CMD_SUCCESS;
2860 }
2861
2862 static void if_show_description(struct vty *vty, struct vrf *vrf)
2863 {
2864 struct interface *ifp;
2865
2866 vty_out(vty, "Interface Status Protocol Description\n");
2867 FOR_ALL_INTERFACES (vrf, ifp) {
2868 int len;
2869 struct zebra_if *zif;
2870 bool intf_desc;
2871
2872 intf_desc = false;
2873
2874 len = vty_out(vty, "%s", ifp->name);
2875 vty_out(vty, "%*s", (16 - len), " ");
2876
2877 if (if_is_up(ifp)) {
2878 vty_out(vty, "up ");
2879 if (CHECK_FLAG(ifp->status,
2880 ZEBRA_INTERFACE_LINKDETECTION)) {
2881 if (if_is_running(ifp))
2882 vty_out(vty, "up ");
2883 else
2884 vty_out(vty, "down ");
2885 } else {
2886 vty_out(vty, "unknown ");
2887 }
2888 } else {
2889 vty_out(vty, "down down ");
2890 }
2891
2892 if (ifp->desc) {
2893 intf_desc = true;
2894 vty_out(vty, "%s", ifp->desc);
2895 }
2896 zif = ifp->info;
2897 if (zif && zif->desc) {
2898 vty_out(vty, "%s%s",
2899 intf_desc
2900 ? "\n "
2901 : "",
2902 zif->desc);
2903 }
2904
2905 vty_out(vty, "\n");
2906 }
2907 }
2908
2909 DEFUN (show_interface_desc,
2910 show_interface_desc_cmd,
2911 "show interface description vrf NAME",
2912 SHOW_STR
2913 "Interface status and configuration\n"
2914 "Interface description\n"
2915 VRF_CMD_HELP_STR)
2916 {
2917 struct vrf *vrf;
2918
2919 vrf = vrf_lookup_by_name(argv[4]->arg);
2920 if (!vrf) {
2921 vty_out(vty, "%% VRF %s not found\n", argv[4]->arg);
2922 return CMD_WARNING;
2923 }
2924
2925 if_show_description(vty, vrf);
2926
2927 return CMD_SUCCESS;
2928 }
2929
2930
2931 DEFUN (show_interface_desc_vrf_all,
2932 show_interface_desc_vrf_all_cmd,
2933 "show interface description [vrf all]",
2934 SHOW_STR
2935 "Interface status and configuration\n"
2936 "Interface description\n"
2937 VRF_ALL_CMD_HELP_STR)
2938 {
2939 struct vrf *vrf;
2940
2941 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name)
2942 if (!RB_EMPTY(if_name_head, &vrf->ifaces_by_name)) {
2943 vty_out(vty, "\n\tVRF %s(%u)\n\n", VRF_LOGNAME(vrf),
2944 vrf->vrf_id);
2945 if_show_description(vty, vrf);
2946 }
2947
2948 return CMD_SUCCESS;
2949 }
2950
2951 int if_multicast_set(struct interface *ifp)
2952 {
2953 struct zebra_if *if_data;
2954
2955 if (CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE)) {
2956 if (if_set_flags(ifp, IFF_MULTICAST) < 0) {
2957 zlog_debug("Can't set multicast flag on interface %s",
2958 ifp->name);
2959 return -1;
2960 }
2961 if_refresh(ifp);
2962 }
2963 if_data = ifp->info;
2964 if_data->multicast = IF_ZEBRA_DATA_ON;
2965
2966 return 0;
2967 }
2968
2969 DEFUN (multicast,
2970 multicast_cmd,
2971 "multicast",
2972 "Set multicast flag to interface\n")
2973 {
2974 VTY_DECLVAR_CONTEXT(interface, ifp);
2975 int ret;
2976 struct zebra_if *if_data;
2977
2978 if (CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE)) {
2979 ret = if_set_flags(ifp, IFF_MULTICAST);
2980 if (ret < 0) {
2981 vty_out(vty, "Can't set multicast flag\n");
2982 return CMD_WARNING_CONFIG_FAILED;
2983 }
2984 if_refresh(ifp);
2985 }
2986 if_data = ifp->info;
2987 if_data->multicast = IF_ZEBRA_DATA_ON;
2988
2989 return CMD_SUCCESS;
2990 }
2991
2992 DEFPY (mpls,
2993 mpls_cmd,
2994 "[no] mpls enable",
2995 NO_STR
2996 MPLS_STR
2997 "Set mpls to be on for the interface\n")
2998 {
2999 VTY_DECLVAR_CONTEXT(interface, ifp);
3000 struct zebra_if *if_data = ifp->info;
3001
3002 if (no) {
3003 dplane_intf_mpls_modify_state(ifp, false);
3004 if_data->mpls = IF_ZEBRA_DATA_UNSPEC;
3005 } else {
3006 dplane_intf_mpls_modify_state(ifp, true);
3007 if_data->mpls = IF_ZEBRA_DATA_ON;
3008 }
3009
3010 return CMD_SUCCESS;
3011 }
3012
3013 int if_multicast_unset(struct interface *ifp)
3014 {
3015 struct zebra_if *if_data;
3016
3017 if (CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE)) {
3018 if (if_unset_flags(ifp, IFF_MULTICAST) < 0) {
3019 zlog_debug("Can't unset multicast flag on interface %s",
3020 ifp->name);
3021 return -1;
3022 }
3023 if_refresh(ifp);
3024 }
3025 if_data = ifp->info;
3026 if_data->multicast = IF_ZEBRA_DATA_OFF;
3027
3028 return 0;
3029 }
3030
3031 DEFUN (no_multicast,
3032 no_multicast_cmd,
3033 "no multicast",
3034 NO_STR
3035 "Unset multicast flag to interface\n")
3036 {
3037 VTY_DECLVAR_CONTEXT(interface, ifp);
3038 int ret;
3039 struct zebra_if *if_data;
3040
3041 if (CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE)) {
3042 ret = if_unset_flags(ifp, IFF_MULTICAST);
3043 if (ret < 0) {
3044 vty_out(vty, "Can't unset multicast flag\n");
3045 return CMD_WARNING_CONFIG_FAILED;
3046 }
3047 if_refresh(ifp);
3048 }
3049 if_data = ifp->info;
3050 if_data->multicast = IF_ZEBRA_DATA_OFF;
3051
3052 return CMD_SUCCESS;
3053 }
3054
3055 int if_linkdetect(struct interface *ifp, bool detect)
3056 {
3057 int if_was_operative;
3058
3059 if_was_operative = if_is_no_ptm_operative(ifp);
3060 if (detect) {
3061 SET_FLAG(ifp->status, ZEBRA_INTERFACE_LINKDETECTION);
3062
3063 /* When linkdetection is enabled, if might come down */
3064 if (!if_is_no_ptm_operative(ifp) && if_was_operative)
3065 if_down(ifp);
3066 } else {
3067 UNSET_FLAG(ifp->status, ZEBRA_INTERFACE_LINKDETECTION);
3068
3069 /* Interface may come up after disabling link detection */
3070 if (if_is_operative(ifp) && !if_was_operative)
3071 if_up(ifp, true);
3072 }
3073 /* FIXME: Will defer status change forwarding if interface
3074 does not come down! */
3075 return 0;
3076 }
3077
3078 DEFUN(linkdetect, linkdetect_cmd, "link-detect",
3079 "Enable link detection on interface\n")
3080 {
3081 VTY_DECLVAR_CONTEXT(interface, ifp);
3082
3083 if_linkdetect(ifp, true);
3084
3085 return CMD_SUCCESS;
3086 }
3087
3088
3089 DEFUN (no_linkdetect,
3090 no_linkdetect_cmd,
3091 "no link-detect",
3092 NO_STR
3093 "Disable link detection on interface\n")
3094 {
3095 VTY_DECLVAR_CONTEXT(interface, ifp);
3096
3097 if_linkdetect(ifp, false);
3098
3099 return CMD_SUCCESS;
3100 }
3101
3102 int if_shutdown(struct interface *ifp)
3103 {
3104 struct zebra_if *if_data;
3105
3106 if (ifp->ifindex != IFINDEX_INTERNAL) {
3107 /* send RA lifetime of 0 before stopping. rfc4861/6.2.5 */
3108 rtadv_stop_ra(ifp);
3109 if (if_unset_flags(ifp, IFF_UP) < 0) {
3110 zlog_debug("Can't shutdown interface %s", ifp->name);
3111 return -1;
3112 }
3113 if_refresh(ifp);
3114 }
3115 if_data = ifp->info;
3116 if_data->shutdown = IF_ZEBRA_DATA_ON;
3117
3118 return 0;
3119 }
3120
3121 DEFUN (shutdown_if,
3122 shutdown_if_cmd,
3123 "shutdown",
3124 "Shutdown the selected interface\n")
3125 {
3126 VTY_DECLVAR_CONTEXT(interface, ifp);
3127 int ret;
3128 struct zebra_if *if_data;
3129
3130 if (ifp->ifindex != IFINDEX_INTERNAL) {
3131 /* send RA lifetime of 0 before stopping. rfc4861/6.2.5 */
3132 rtadv_stop_ra(ifp);
3133 ret = if_unset_flags(ifp, IFF_UP);
3134 if (ret < 0) {
3135 vty_out(vty, "Can't shutdown interface\n");
3136 return CMD_WARNING_CONFIG_FAILED;
3137 }
3138 if_refresh(ifp);
3139 }
3140 if_data = ifp->info;
3141 if_data->shutdown = IF_ZEBRA_DATA_ON;
3142
3143 return CMD_SUCCESS;
3144 }
3145
3146 int if_no_shutdown(struct interface *ifp)
3147 {
3148 struct zebra_if *if_data;
3149
3150 if (ifp->ifindex != IFINDEX_INTERNAL) {
3151 if (if_set_flags(ifp, IFF_UP | IFF_RUNNING) < 0) {
3152 zlog_debug("Can't up interface %s", ifp->name);
3153 return -1;
3154 }
3155 if_refresh(ifp);
3156
3157 /* Some addresses (in particular, IPv6 addresses on Linux) get
3158 * removed when the interface goes down. They need to be
3159 * readded.
3160 */
3161 if_addr_wakeup(ifp);
3162 }
3163
3164 if_data = ifp->info;
3165 if_data->shutdown = IF_ZEBRA_DATA_OFF;
3166
3167 return 0;
3168 }
3169
3170 DEFUN (no_shutdown_if,
3171 no_shutdown_if_cmd,
3172 "no shutdown",
3173 NO_STR
3174 "Shutdown the selected interface\n")
3175 {
3176 VTY_DECLVAR_CONTEXT(interface, ifp);
3177 int ret;
3178 struct zebra_if *if_data;
3179
3180 if (ifp->ifindex != IFINDEX_INTERNAL) {
3181 ret = if_set_flags(ifp, IFF_UP | IFF_RUNNING);
3182 if (ret < 0) {
3183 vty_out(vty, "Can't up interface\n");
3184 return CMD_WARNING_CONFIG_FAILED;
3185 }
3186 if_refresh(ifp);
3187
3188 /* Some addresses (in particular, IPv6 addresses on Linux) get
3189 * removed when the interface goes down. They need to be
3190 * readded.
3191 */
3192 if_addr_wakeup(ifp);
3193 }
3194
3195 if_data = ifp->info;
3196 if_data->shutdown = IF_ZEBRA_DATA_OFF;
3197
3198 return CMD_SUCCESS;
3199 }
3200
3201 DEFUN (bandwidth_if,
3202 bandwidth_if_cmd,
3203 "bandwidth (1-100000)",
3204 "Set bandwidth informational parameter\n"
3205 "Bandwidth in megabits\n")
3206 {
3207 int idx_number = 1;
3208 VTY_DECLVAR_CONTEXT(interface, ifp);
3209 unsigned int bandwidth;
3210
3211 bandwidth = strtol(argv[idx_number]->arg, NULL, 10);
3212
3213 /* bandwidth range is <1-100000> */
3214 if (bandwidth < 1 || bandwidth > 100000) {
3215 vty_out(vty, "Bandwidth is invalid\n");
3216 return CMD_WARNING_CONFIG_FAILED;
3217 }
3218
3219 ifp->bandwidth = bandwidth;
3220
3221 /* force protocols to recalculate routes due to cost change */
3222 if (if_is_operative(ifp))
3223 zebra_interface_up_update(ifp);
3224
3225 return CMD_SUCCESS;
3226 }
3227
3228 DEFUN (no_bandwidth_if,
3229 no_bandwidth_if_cmd,
3230 "no bandwidth [(1-100000)]",
3231 NO_STR
3232 "Set bandwidth informational parameter\n"
3233 "Bandwidth in megabits\n")
3234 {
3235 VTY_DECLVAR_CONTEXT(interface, ifp);
3236
3237 ifp->bandwidth = 0;
3238
3239 /* force protocols to recalculate routes due to cost change */
3240 if (if_is_operative(ifp))
3241 zebra_interface_up_update(ifp);
3242
3243 return CMD_SUCCESS;
3244 }
3245
3246
3247 struct cmd_node link_params_node = {
3248 .name = "link-params",
3249 .node = LINK_PARAMS_NODE,
3250 .parent_node = INTERFACE_NODE,
3251 .prompt = "%s(config-link-params)# ",
3252 .no_xpath = true,
3253 };
3254
3255 static void link_param_cmd_set_uint32(struct interface *ifp, uint32_t *field,
3256 uint32_t type, uint32_t value)
3257 {
3258 /* Update field as needed */
3259 if (IS_PARAM_UNSET(ifp->link_params, type) || *field != value) {
3260 *field = value;
3261 SET_PARAM(ifp->link_params, type);
3262
3263 /* force protocols to update LINK STATE due to parameters change
3264 */
3265 if (if_is_operative(ifp))
3266 zebra_interface_parameters_update(ifp);
3267 }
3268 }
3269 static void link_param_cmd_set_float(struct interface *ifp, float *field,
3270 uint32_t type, float value)
3271 {
3272
3273 /* Update field as needed */
3274 if (IS_PARAM_UNSET(ifp->link_params, type) || *field != value) {
3275 *field = value;
3276 SET_PARAM(ifp->link_params, type);
3277
3278 /* force protocols to update LINK STATE due to parameters change
3279 */
3280 if (if_is_operative(ifp))
3281 zebra_interface_parameters_update(ifp);
3282 }
3283 }
3284
3285 static void link_param_cmd_unset(struct interface *ifp, uint32_t type)
3286 {
3287 if (ifp->link_params == NULL)
3288 return;
3289
3290 /* Unset field */
3291 UNSET_PARAM(ifp->link_params, type);
3292
3293 /* force protocols to update LINK STATE due to parameters change */
3294 if (if_is_operative(ifp))
3295 zebra_interface_parameters_update(ifp);
3296 }
3297
3298 DEFUN_NOSH (link_params,
3299 link_params_cmd,
3300 "link-params",
3301 LINK_PARAMS_STR)
3302 {
3303 /* vty->qobj_index stays the same @ interface pointer */
3304 vty->node = LINK_PARAMS_NODE;
3305
3306 return CMD_SUCCESS;
3307 }
3308
3309 DEFUN_NOSH (exit_link_params,
3310 exit_link_params_cmd,
3311 "exit-link-params",
3312 "Exit from Link Params configuration mode\n")
3313 {
3314 if (vty->node == LINK_PARAMS_NODE)
3315 vty->node = INTERFACE_NODE;
3316 return CMD_SUCCESS;
3317 }
3318
3319 /* Specific Traffic Engineering parameters commands */
3320 DEFUN (link_params_enable,
3321 link_params_enable_cmd,
3322 "enable",
3323 "Activate link parameters on this interface\n")
3324 {
3325 VTY_DECLVAR_CONTEXT(interface, ifp);
3326
3327 /* This command could be issue at startup, when activate MPLS TE */
3328 /* on a new interface or after a ON / OFF / ON toggle */
3329 /* In all case, TE parameters are reset to their default factory */
3330 if (IS_ZEBRA_DEBUG_EVENT || IS_ZEBRA_DEBUG_MPLS)
3331 zlog_debug(
3332 "Link-params: enable TE link parameters on interface %s",
3333 ifp->name);
3334
3335 if (!if_link_params_get(ifp))
3336 if_link_params_enable(ifp);
3337
3338 /* force protocols to update LINK STATE due to parameters change */
3339 if (if_is_operative(ifp))
3340 zebra_interface_parameters_update(ifp);
3341
3342 return CMD_SUCCESS;
3343 }
3344
3345 DEFUN (no_link_params_enable,
3346 no_link_params_enable_cmd,
3347 "no enable",
3348 NO_STR
3349 "Disable link parameters on this interface\n")
3350 {
3351 char xpath[XPATH_MAXLEN];
3352 int ret;
3353 VTY_DECLVAR_CONTEXT(interface, ifp);
3354
3355 if (IS_ZEBRA_DEBUG_EVENT || IS_ZEBRA_DEBUG_MPLS)
3356 zlog_debug("MPLS-TE: disable TE link parameters on interface %s",
3357 ifp->name);
3358
3359 if_link_params_free(ifp);
3360
3361 snprintf(
3362 xpath, sizeof(xpath),
3363 "/frr-interface:lib/interface[name='%s']/frr-zebra:zebra/link-params/affinities",
3364 ifp->name);
3365 if (yang_dnode_exists(running_config->dnode, xpath))
3366 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
3367
3368 ret = nb_cli_apply_changes(vty, NULL);
3369
3370 if (ret != CMD_SUCCESS)
3371 return ret;
3372
3373 /* force protocols to update LINK STATE due to parameters change */
3374 if (if_is_operative(ifp))
3375 zebra_interface_parameters_update(ifp);
3376
3377 return CMD_SUCCESS;
3378 }
3379
3380 /* STANDARD TE metrics */
3381 DEFUN (link_params_metric,
3382 link_params_metric_cmd,
3383 "metric (0-4294967295)",
3384 "Link metric for MPLS-TE purpose\n"
3385 "Metric value in decimal\n")
3386 {
3387 int idx_number = 1;
3388 VTY_DECLVAR_CONTEXT(interface, ifp);
3389 struct if_link_params *iflp = if_link_params_get(ifp);
3390 uint32_t metric;
3391
3392 metric = strtoul(argv[idx_number]->arg, NULL, 10);
3393
3394 if (!iflp)
3395 iflp = if_link_params_enable(ifp);
3396
3397 /* Update TE metric if needed */
3398 link_param_cmd_set_uint32(ifp, &iflp->te_metric, LP_TE_METRIC, metric);
3399
3400 return CMD_SUCCESS;
3401 }
3402
3403 DEFUN (no_link_params_metric,
3404 no_link_params_metric_cmd,
3405 "no metric",
3406 NO_STR
3407 "Disable Link Metric on this interface\n")
3408 {
3409 VTY_DECLVAR_CONTEXT(interface, ifp);
3410
3411 /* Unset TE Metric */
3412 link_param_cmd_unset(ifp, LP_TE_METRIC);
3413
3414 return CMD_SUCCESS;
3415 }
3416
3417 DEFUN (link_params_maxbw,
3418 link_params_maxbw_cmd,
3419 "max-bw BANDWIDTH",
3420 "Maximum bandwidth that can be used\n"
3421 "Bytes/second (IEEE floating point format)\n")
3422 {
3423 int idx_bandwidth = 1;
3424 VTY_DECLVAR_CONTEXT(interface, ifp);
3425 struct if_link_params *iflp = if_link_params_get(ifp);
3426
3427 float bw;
3428
3429 if (sscanf(argv[idx_bandwidth]->arg, "%g", &bw) != 1) {
3430 vty_out(vty, "link_params_maxbw: fscanf: %s\n",
3431 safe_strerror(errno));
3432 return CMD_WARNING_CONFIG_FAILED;
3433 }
3434
3435 /* Check that Maximum bandwidth is not lower than other bandwidth
3436 * parameters */
3437 if (iflp && ((bw <= iflp->max_rsv_bw) || (bw <= iflp->unrsv_bw[0]) ||
3438 (bw <= iflp->unrsv_bw[1]) || (bw <= iflp->unrsv_bw[2]) ||
3439 (bw <= iflp->unrsv_bw[3]) || (bw <= iflp->unrsv_bw[4]) ||
3440 (bw <= iflp->unrsv_bw[5]) || (bw <= iflp->unrsv_bw[6]) ||
3441 (bw <= iflp->unrsv_bw[7]) || (bw <= iflp->ava_bw) ||
3442 (bw <= iflp->res_bw) || (bw <= iflp->use_bw))) {
3443 vty_out(vty,
3444 "Maximum Bandwidth could not be lower than others bandwidth\n");
3445 return CMD_WARNING_CONFIG_FAILED;
3446 }
3447
3448 if (!iflp)
3449 iflp = if_link_params_enable(ifp);
3450
3451 /* Update Maximum Bandwidth if needed */
3452 link_param_cmd_set_float(ifp, &iflp->max_bw, LP_MAX_BW, bw);
3453
3454 return CMD_SUCCESS;
3455 }
3456
3457 DEFUN (link_params_max_rsv_bw,
3458 link_params_max_rsv_bw_cmd,
3459 "max-rsv-bw BANDWIDTH",
3460 "Maximum bandwidth that may be reserved\n"
3461 "Bytes/second (IEEE floating point format)\n")
3462 {
3463 int idx_bandwidth = 1;
3464 VTY_DECLVAR_CONTEXT(interface, ifp);
3465 struct if_link_params *iflp = if_link_params_get(ifp);
3466 float bw;
3467
3468 if (sscanf(argv[idx_bandwidth]->arg, "%g", &bw) != 1) {
3469 vty_out(vty, "link_params_max_rsv_bw: fscanf: %s\n",
3470 safe_strerror(errno));
3471 return CMD_WARNING_CONFIG_FAILED;
3472 }
3473
3474 /* Check that bandwidth is not greater than maximum bandwidth parameter
3475 */
3476 if (iflp && bw > iflp->max_bw) {
3477 vty_out(vty,
3478 "Maximum Reservable Bandwidth could not be greater than Maximum Bandwidth (%g)\n",
3479 iflp->max_bw);
3480 return CMD_WARNING_CONFIG_FAILED;
3481 }
3482
3483 if (!iflp)
3484 iflp = if_link_params_enable(ifp);
3485
3486 /* Update Maximum Reservable Bandwidth if needed */
3487 link_param_cmd_set_float(ifp, &iflp->max_rsv_bw, LP_MAX_RSV_BW, bw);
3488
3489 return CMD_SUCCESS;
3490 }
3491
3492 DEFUN (link_params_unrsv_bw,
3493 link_params_unrsv_bw_cmd,
3494 "unrsv-bw (0-7) BANDWIDTH",
3495 "Unreserved bandwidth at each priority level\n"
3496 "Priority\n"
3497 "Bytes/second (IEEE floating point format)\n")
3498 {
3499 int idx_number = 1;
3500 int idx_bandwidth = 2;
3501 VTY_DECLVAR_CONTEXT(interface, ifp);
3502 struct if_link_params *iflp = if_link_params_get(ifp);
3503 int priority;
3504 float bw;
3505
3506 /* We don't have to consider about range check here. */
3507 if (sscanf(argv[idx_number]->arg, "%d", &priority) != 1) {
3508 vty_out(vty, "link_params_unrsv_bw: fscanf: %s\n",
3509 safe_strerror(errno));
3510 return CMD_WARNING_CONFIG_FAILED;
3511 }
3512
3513 if (sscanf(argv[idx_bandwidth]->arg, "%g", &bw) != 1) {
3514 vty_out(vty, "link_params_unrsv_bw: fscanf: %s\n",
3515 safe_strerror(errno));
3516 return CMD_WARNING_CONFIG_FAILED;
3517 }
3518
3519 /* Check that bandwidth is not greater than maximum bandwidth parameter
3520 */
3521 if (iflp && bw > iflp->max_bw) {
3522 vty_out(vty,
3523 "UnReserved Bandwidth could not be greater than Maximum Bandwidth (%g)\n",
3524 iflp->max_bw);
3525 return CMD_WARNING_CONFIG_FAILED;
3526 }
3527
3528 if (!iflp)
3529 iflp = if_link_params_enable(ifp);
3530
3531 /* Update Unreserved Bandwidth if needed */
3532 link_param_cmd_set_float(ifp, &iflp->unrsv_bw[priority], LP_UNRSV_BW,
3533 bw);
3534
3535 return CMD_SUCCESS;
3536 }
3537
3538 DEFPY_YANG(link_params_admin_grp, link_params_admin_grp_cmd,
3539 "admin-grp BITPATTERN",
3540 "Administrative group membership\n"
3541 "32-bit Hexadecimal value (e.g. 0xa1)\n")
3542 {
3543 char xpath[XPATH_MAXLEN];
3544 int idx_bitpattern = 1;
3545 unsigned long value;
3546 char value_str[11];
3547
3548 VTY_DECLVAR_CONTEXT(interface, ifp);
3549
3550 snprintf(
3551 xpath, sizeof(xpath),
3552 "/frr-interface:lib/interface[name='%s']/frr-zebra:zebra/link-params/affinities",
3553 ifp->name);
3554 if (yang_dnode_exists(running_config->dnode, xpath)) {
3555 vty_out(vty,
3556 "cannot use the admin-grp command when affinity is set\n");
3557 return CMD_WARNING_CONFIG_FAILED;
3558 }
3559
3560 if (sscanf(argv[idx_bitpattern]->arg, "0x%lx", &value) != 1) {
3561 vty_out(vty, "link_params_admin_grp: fscanf: %s\n",
3562 safe_strerror(errno));
3563 return CMD_WARNING_CONFIG_FAILED;
3564 }
3565
3566 if (value > 0xFFFFFFFF) {
3567 vty_out(vty, "value must be not be superior to 0xFFFFFFFF\n");
3568 return CMD_WARNING_CONFIG_FAILED;
3569 }
3570
3571 snprintf(value_str, sizeof(value_str), "%ld", value);
3572
3573 nb_cli_enqueue_change(
3574 vty, "./frr-zebra:zebra/link-params/legacy-admin-group",
3575 NB_OP_MODIFY, value_str);
3576
3577 return nb_cli_apply_changes(vty, NULL);
3578 }
3579
3580 DEFPY_YANG(no_link_params_admin_grp, no_link_params_admin_grp_cmd,
3581 "no admin-grp",
3582 NO_STR "Disable Administrative group membership on this interface\n")
3583 {
3584 nb_cli_enqueue_change(
3585 vty, "./frr-zebra:zebra/link-params/legacy-admin-group",
3586 NB_OP_DESTROY, NULL);
3587
3588 return nb_cli_apply_changes(vty, NULL);
3589 }
3590
3591 /* RFC5392 & RFC5316: INTER-AS */
3592 DEFUN (link_params_inter_as,
3593 link_params_inter_as_cmd,
3594 "neighbor A.B.C.D as (1-4294967295)",
3595 "Configure remote ASBR information (Neighbor IP address and AS number)\n"
3596 "Remote IP address in dot decimal A.B.C.D\n"
3597 "Remote AS number\n"
3598 "AS number in the range <1-4294967295>\n")
3599 {
3600 int idx_ipv4 = 1;
3601 int idx_number = 3;
3602
3603 VTY_DECLVAR_CONTEXT(interface, ifp);
3604 struct if_link_params *iflp = if_link_params_get(ifp);
3605 struct in_addr addr;
3606 uint32_t as;
3607
3608 if (!inet_aton(argv[idx_ipv4]->arg, &addr)) {
3609 vty_out(vty, "Please specify Router-Addr by A.B.C.D\n");
3610 return CMD_WARNING_CONFIG_FAILED;
3611 }
3612
3613 if (!iflp)
3614 iflp = if_link_params_enable(ifp);
3615
3616 as = strtoul(argv[idx_number]->arg, NULL, 10);
3617
3618 /* Update Remote IP and Remote AS fields if needed */
3619 if (IS_PARAM_UNSET(iflp, LP_RMT_AS) || iflp->rmt_as != as
3620 || iflp->rmt_ip.s_addr != addr.s_addr) {
3621
3622 iflp->rmt_as = as;
3623 iflp->rmt_ip.s_addr = addr.s_addr;
3624 SET_PARAM(iflp, LP_RMT_AS);
3625
3626 /* force protocols to update LINK STATE due to parameters change
3627 */
3628 if (if_is_operative(ifp))
3629 zebra_interface_parameters_update(ifp);
3630 }
3631 return CMD_SUCCESS;
3632 }
3633
3634 DEFUN (no_link_params_inter_as,
3635 no_link_params_inter_as_cmd,
3636 "no neighbor",
3637 NO_STR
3638 "Remove Neighbor IP address and AS number for Inter-AS TE\n")
3639 {
3640 VTY_DECLVAR_CONTEXT(interface, ifp);
3641 struct if_link_params *iflp = if_link_params_get(ifp);
3642
3643 if (!iflp)
3644 return CMD_SUCCESS;
3645
3646 /* Reset Remote IP and AS neighbor */
3647 iflp->rmt_as = 0;
3648 iflp->rmt_ip.s_addr = 0;
3649 UNSET_PARAM(iflp, LP_RMT_AS);
3650
3651 /* force protocols to update LINK STATE due to parameters change */
3652 if (if_is_operative(ifp))
3653 zebra_interface_parameters_update(ifp);
3654
3655 return CMD_SUCCESS;
3656 }
3657
3658 /* RFC7471: OSPF Traffic Engineering (TE) Metric extensions &
3659 * draft-ietf-isis-metric-extensions-07.txt */
3660 DEFUN (link_params_delay,
3661 link_params_delay_cmd,
3662 "delay (0-16777215) [min (0-16777215) max (0-16777215)]",
3663 "Unidirectional Average Link Delay\n"
3664 "Average delay in micro-second as decimal (0...16777215)\n"
3665 "Minimum delay\n"
3666 "Minimum delay in micro-second as decimal (0...16777215)\n"
3667 "Maximum delay\n"
3668 "Maximum delay in micro-second as decimal (0...16777215)\n")
3669 {
3670 /* Get and Check new delay values */
3671 uint32_t delay = 0, low = 0, high = 0;
3672 delay = strtoul(argv[1]->arg, NULL, 10);
3673 if (argc == 6) {
3674 low = strtoul(argv[3]->arg, NULL, 10);
3675 high = strtoul(argv[5]->arg, NULL, 10);
3676 }
3677
3678 VTY_DECLVAR_CONTEXT(interface, ifp);
3679 struct if_link_params *iflp = if_link_params_get(ifp);
3680 uint8_t update = 0;
3681
3682 if (argc == 2) {
3683 /*
3684 * Check new delay value against old Min and Max delays if set
3685 *
3686 * RFC 7471 Section 4.2.7:
3687 * It is possible for min delay and max delay to be
3688 * the same value.
3689 *
3690 * Therefore, it is also allowed that the average
3691 * delay be equal to the min delay or max delay.
3692 */
3693 if (iflp && IS_PARAM_SET(iflp, LP_MM_DELAY) &&
3694 (delay < iflp->min_delay || delay > iflp->max_delay)) {
3695 vty_out(vty,
3696 "Average delay should be in range Min (%d) - Max (%d) delay\n",
3697 iflp->min_delay, iflp->max_delay);
3698 return CMD_WARNING_CONFIG_FAILED;
3699 }
3700
3701 if (!iflp)
3702 iflp = if_link_params_enable(ifp);
3703
3704 /* Update delay if value is not set or change */
3705 if (IS_PARAM_UNSET(iflp, LP_DELAY) || iflp->av_delay != delay) {
3706 iflp->av_delay = delay;
3707 SET_PARAM(iflp, LP_DELAY);
3708 update = 1;
3709 }
3710 /* Unset Min and Max delays if already set */
3711 if (IS_PARAM_SET(iflp, LP_MM_DELAY)) {
3712 iflp->min_delay = 0;
3713 iflp->max_delay = 0;
3714 UNSET_PARAM(iflp, LP_MM_DELAY);
3715 update = 1;
3716 }
3717 } else {
3718 /*
3719 * Check new delays value coherency. See above note
3720 * regarding average delay equal to min/max allowed
3721 */
3722 if (delay < low || delay > high) {
3723 vty_out(vty,
3724 "Average delay should be in range Min (%d) - Max (%d) delay\n",
3725 low, high);
3726 return CMD_WARNING_CONFIG_FAILED;
3727 }
3728
3729 if (!iflp)
3730 iflp = if_link_params_enable(ifp);
3731
3732 /* Update Delays if needed */
3733 if (IS_PARAM_UNSET(iflp, LP_DELAY)
3734 || IS_PARAM_UNSET(iflp, LP_MM_DELAY)
3735 || iflp->av_delay != delay || iflp->min_delay != low
3736 || iflp->max_delay != high) {
3737 iflp->av_delay = delay;
3738 SET_PARAM(iflp, LP_DELAY);
3739 iflp->min_delay = low;
3740 iflp->max_delay = high;
3741 SET_PARAM(iflp, LP_MM_DELAY);
3742 update = 1;
3743 }
3744 }
3745
3746 /* force protocols to update LINK STATE due to parameters change */
3747 if (update == 1 && if_is_operative(ifp))
3748 zebra_interface_parameters_update(ifp);
3749
3750 return CMD_SUCCESS;
3751 }
3752
3753 DEFUN (no_link_params_delay,
3754 no_link_params_delay_cmd,
3755 "no delay",
3756 NO_STR
3757 "Disable Unidirectional Average, Min & Max Link Delay on this interface\n")
3758 {
3759 VTY_DECLVAR_CONTEXT(interface, ifp);
3760 struct if_link_params *iflp = if_link_params_get(ifp);
3761
3762 if (!iflp)
3763 return CMD_SUCCESS;
3764
3765 /* Unset Delays */
3766 iflp->av_delay = 0;
3767 UNSET_PARAM(iflp, LP_DELAY);
3768 iflp->min_delay = 0;
3769 iflp->max_delay = 0;
3770 UNSET_PARAM(iflp, LP_MM_DELAY);
3771
3772 /* force protocols to update LINK STATE due to parameters change */
3773 if (if_is_operative(ifp))
3774 zebra_interface_parameters_update(ifp);
3775
3776 return CMD_SUCCESS;
3777 }
3778
3779 DEFUN (link_params_delay_var,
3780 link_params_delay_var_cmd,
3781 "delay-variation (0-16777215)",
3782 "Unidirectional Link Delay Variation\n"
3783 "delay variation in micro-second as decimal (0...16777215)\n")
3784 {
3785 int idx_number = 1;
3786 VTY_DECLVAR_CONTEXT(interface, ifp);
3787 struct if_link_params *iflp = if_link_params_get(ifp);
3788 uint32_t value;
3789
3790 value = strtoul(argv[idx_number]->arg, NULL, 10);
3791
3792 if (!iflp)
3793 iflp = if_link_params_enable(ifp);
3794
3795 /* Update Delay Variation if needed */
3796 link_param_cmd_set_uint32(ifp, &iflp->delay_var, LP_DELAY_VAR, value);
3797
3798 return CMD_SUCCESS;
3799 }
3800
3801 DEFUN (no_link_params_delay_var,
3802 no_link_params_delay_var_cmd,
3803 "no delay-variation",
3804 NO_STR
3805 "Disable Unidirectional Delay Variation on this interface\n")
3806 {
3807 VTY_DECLVAR_CONTEXT(interface, ifp);
3808
3809 /* Unset Delay Variation */
3810 link_param_cmd_unset(ifp, LP_DELAY_VAR);
3811
3812 return CMD_SUCCESS;
3813 }
3814
3815 DEFUN (link_params_pkt_loss,
3816 link_params_pkt_loss_cmd,
3817 "packet-loss PERCENTAGE",
3818 "Unidirectional Link Packet Loss\n"
3819 "percentage of total traffic by 0.000003% step and less than 50.331642%\n")
3820 {
3821 int idx_percentage = 1;
3822 VTY_DECLVAR_CONTEXT(interface, ifp);
3823 struct if_link_params *iflp = if_link_params_get(ifp);
3824 float fval;
3825
3826 if (sscanf(argv[idx_percentage]->arg, "%g", &fval) != 1) {
3827 vty_out(vty, "link_params_pkt_loss: fscanf: %s\n",
3828 safe_strerror(errno));
3829 return CMD_WARNING_CONFIG_FAILED;
3830 }
3831
3832 if (fval > MAX_PKT_LOSS)
3833 fval = MAX_PKT_LOSS;
3834
3835 if (!iflp)
3836 iflp = if_link_params_enable(ifp);
3837
3838 /* Update Packet Loss if needed */
3839 link_param_cmd_set_float(ifp, &iflp->pkt_loss, LP_PKT_LOSS, fval);
3840
3841 return CMD_SUCCESS;
3842 }
3843
3844 DEFUN (no_link_params_pkt_loss,
3845 no_link_params_pkt_loss_cmd,
3846 "no packet-loss",
3847 NO_STR
3848 "Disable Unidirectional Link Packet Loss on this interface\n")
3849 {
3850 VTY_DECLVAR_CONTEXT(interface, ifp);
3851
3852 /* Unset Packet Loss */
3853 link_param_cmd_unset(ifp, LP_PKT_LOSS);
3854
3855 return CMD_SUCCESS;
3856 }
3857
3858 DEFUN (link_params_res_bw,
3859 link_params_res_bw_cmd,
3860 "res-bw BANDWIDTH",
3861 "Unidirectional Residual Bandwidth\n"
3862 "Bytes/second (IEEE floating point format)\n")
3863 {
3864 int idx_bandwidth = 1;
3865 VTY_DECLVAR_CONTEXT(interface, ifp);
3866 struct if_link_params *iflp = if_link_params_get(ifp);
3867 float bw;
3868
3869 if (sscanf(argv[idx_bandwidth]->arg, "%g", &bw) != 1) {
3870 vty_out(vty, "link_params_res_bw: fscanf: %s\n",
3871 safe_strerror(errno));
3872 return CMD_WARNING_CONFIG_FAILED;
3873 }
3874
3875 /* Check that bandwidth is not greater than maximum bandwidth parameter
3876 */
3877 if (iflp && bw > iflp->max_bw) {
3878 vty_out(vty,
3879 "Residual Bandwidth could not be greater than Maximum Bandwidth (%g)\n",
3880 iflp->max_bw);
3881 return CMD_WARNING_CONFIG_FAILED;
3882 }
3883
3884 if (!iflp)
3885 iflp = if_link_params_enable(ifp);
3886
3887 /* Update Residual Bandwidth if needed */
3888 link_param_cmd_set_float(ifp, &iflp->res_bw, LP_RES_BW, bw);
3889
3890 return CMD_SUCCESS;
3891 }
3892
3893 DEFUN (no_link_params_res_bw,
3894 no_link_params_res_bw_cmd,
3895 "no res-bw",
3896 NO_STR
3897 "Disable Unidirectional Residual Bandwidth on this interface\n")
3898 {
3899 VTY_DECLVAR_CONTEXT(interface, ifp);
3900
3901 /* Unset Residual Bandwidth */
3902 link_param_cmd_unset(ifp, LP_RES_BW);
3903
3904 return CMD_SUCCESS;
3905 }
3906
3907 DEFUN (link_params_ava_bw,
3908 link_params_ava_bw_cmd,
3909 "ava-bw BANDWIDTH",
3910 "Unidirectional Available Bandwidth\n"
3911 "Bytes/second (IEEE floating point format)\n")
3912 {
3913 int idx_bandwidth = 1;
3914 VTY_DECLVAR_CONTEXT(interface, ifp);
3915 struct if_link_params *iflp = if_link_params_get(ifp);
3916 float bw;
3917
3918 if (sscanf(argv[idx_bandwidth]->arg, "%g", &bw) != 1) {
3919 vty_out(vty, "link_params_ava_bw: fscanf: %s\n",
3920 safe_strerror(errno));
3921 return CMD_WARNING_CONFIG_FAILED;
3922 }
3923
3924 /* Check that bandwidth is not greater than maximum bandwidth parameter
3925 */
3926 if (iflp && bw > iflp->max_bw) {
3927 vty_out(vty,
3928 "Available Bandwidth could not be greater than Maximum Bandwidth (%g)\n",
3929 iflp->max_bw);
3930 return CMD_WARNING_CONFIG_FAILED;
3931 }
3932
3933 if (!iflp)
3934 iflp = if_link_params_enable(ifp);
3935
3936 /* Update Residual Bandwidth if needed */
3937 link_param_cmd_set_float(ifp, &iflp->ava_bw, LP_AVA_BW, bw);
3938
3939 return CMD_SUCCESS;
3940 }
3941
3942 DEFUN (no_link_params_ava_bw,
3943 no_link_params_ava_bw_cmd,
3944 "no ava-bw",
3945 NO_STR
3946 "Disable Unidirectional Available Bandwidth on this interface\n")
3947 {
3948 VTY_DECLVAR_CONTEXT(interface, ifp);
3949
3950 /* Unset Available Bandwidth */
3951 link_param_cmd_unset(ifp, LP_AVA_BW);
3952
3953 return CMD_SUCCESS;
3954 }
3955
3956 DEFUN (link_params_use_bw,
3957 link_params_use_bw_cmd,
3958 "use-bw BANDWIDTH",
3959 "Unidirectional Utilised Bandwidth\n"
3960 "Bytes/second (IEEE floating point format)\n")
3961 {
3962 int idx_bandwidth = 1;
3963 VTY_DECLVAR_CONTEXT(interface, ifp);
3964 struct if_link_params *iflp = if_link_params_get(ifp);
3965 float bw;
3966
3967 if (sscanf(argv[idx_bandwidth]->arg, "%g", &bw) != 1) {
3968 vty_out(vty, "link_params_use_bw: fscanf: %s\n",
3969 safe_strerror(errno));
3970 return CMD_WARNING_CONFIG_FAILED;
3971 }
3972
3973 /* Check that bandwidth is not greater than maximum bandwidth parameter
3974 */
3975 if (iflp && bw > iflp->max_bw) {
3976 vty_out(vty,
3977 "Utilised Bandwidth could not be greater than Maximum Bandwidth (%g)\n",
3978 iflp->max_bw);
3979 return CMD_WARNING_CONFIG_FAILED;
3980 }
3981
3982 if (!iflp)
3983 iflp = if_link_params_enable(ifp);
3984
3985 /* Update Utilized Bandwidth if needed */
3986 link_param_cmd_set_float(ifp, &iflp->use_bw, LP_USE_BW, bw);
3987
3988 return CMD_SUCCESS;
3989 }
3990
3991 DEFUN (no_link_params_use_bw,
3992 no_link_params_use_bw_cmd,
3993 "no use-bw",
3994 NO_STR
3995 "Disable Unidirectional Utilised Bandwidth on this interface\n")
3996 {
3997 VTY_DECLVAR_CONTEXT(interface, ifp);
3998
3999 /* Unset Utilised Bandwidth */
4000 link_param_cmd_unset(ifp, LP_USE_BW);
4001
4002 return CMD_SUCCESS;
4003 }
4004
4005 static int ag_change(struct vty *vty, int argc, struct cmd_token **argv,
4006 const char *xpath, bool no, int start_idx)
4007 {
4008 for (int i = start_idx; i < argc; i++)
4009 nb_cli_enqueue_change(vty, xpath,
4010 no ? NB_OP_DESTROY : NB_OP_CREATE,
4011 argv[i]->arg);
4012 return nb_cli_apply_changes(vty, NULL);
4013 }
4014
4015 /*
4016 * XPath:
4017 * /frr-interface:lib/interface/frr-zebra:zebra/link-params/affinities/affinity
4018 */
4019 DEFPY_YANG(link_params_affinity, link_params_affinity_cmd,
4020 "[no] affinity NAME...",
4021 NO_STR
4022 "Interface affinities\n"
4023 "Affinity names\n")
4024 {
4025 VTY_DECLVAR_CONTEXT(interface, ifp);
4026 char xpath[XPATH_MAXLEN];
4027
4028 snprintf(
4029 xpath, sizeof(xpath),
4030 "/frr-interface:lib/interface[name='%s']/frr-zebra:zebra/link-params/legacy-admin-group",
4031 ifp->name);
4032 if (yang_dnode_exists(running_config->dnode, xpath)) {
4033 vty_out(vty,
4034 "cannot use the affinity command when admin-grp is set\n");
4035 return CMD_WARNING_CONFIG_FAILED;
4036 }
4037
4038 return ag_change(vty, argc, argv,
4039 "./frr-zebra:zebra/link-params/affinities/affinity",
4040 no, no ? 2 : 1);
4041 }
4042
4043
4044 /*
4045 * XPath:
4046 * /frr-interface:lib/interface/frr-zebra:zebra/link-params/affinities/affinity-mode
4047 */
4048 DEFPY_YANG(link_params_affinity_mode, link_params_affinity_mode_cmd,
4049 "affinity-mode <standard|extended|both>$affmode",
4050 "Interface affinity mode\n"
4051 "Standard Admin-Group only RFC3630,5305,5329 (default)\n"
4052 "Extended Admin-Group only RFC7308\n"
4053 "Standard and extended Admin-Group format\n")
4054 {
4055 const char *xpath = "./frr-zebra:zebra/link-params/affinity-mode";
4056
4057 nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, affmode);
4058
4059 return nb_cli_apply_changes(vty, NULL);
4060 }
4061
4062 DEFPY_YANG(no_link_params_affinity_mode, no_link_params_affinity_mode_cmd,
4063 "no affinity-mode [<standard|extended|both>]",
4064 NO_STR
4065 "Interface affinity mode\n"
4066 "Standard Admin-Group only RFC3630,5305,5329 (default)\n"
4067 "Extended Admin-Group only RFC7308\n"
4068 "Standard and extended Admin-Group format\n")
4069 {
4070 const char *xpath = "./frr-zebra:zebra/link-params/affinity-mode";
4071
4072 nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, "standard");
4073
4074 return nb_cli_apply_changes(vty, NULL);
4075 }
4076
4077 static int ag_iter_cb(const struct lyd_node *dnode, void *arg)
4078 {
4079 struct vty *vty = (struct vty *)arg;
4080
4081 vty_out(vty, " %s", yang_dnode_get_string(dnode, "."));
4082 return YANG_ITER_CONTINUE;
4083 }
4084
4085 void cli_show_legacy_admin_group(struct vty *vty, const struct lyd_node *dnode,
4086 bool show_defaults)
4087 {
4088 if (!yang_dnode_exists(dnode, "./legacy-admin-group"))
4089 return;
4090
4091 vty_out(vty, " admin-group 0x%x\n",
4092 yang_dnode_get_uint32(dnode, "./legacy-admin-group"));
4093 }
4094
4095 void cli_show_affinity_mode(struct vty *vty, const struct lyd_node *dnode,
4096 bool show_defaults)
4097 {
4098 enum affinity_mode affinity_mode = yang_dnode_get_enum(dnode, ".");
4099
4100 if (affinity_mode == AFFINITY_MODE_STANDARD)
4101 vty_out(vty, " affinity-mode standard\n");
4102 else if (affinity_mode == AFFINITY_MODE_BOTH)
4103 vty_out(vty, " affinity-mode both\n");
4104 }
4105
4106 void cli_show_affinity(struct vty *vty, const struct lyd_node *dnode,
4107 bool show_defaults)
4108 {
4109 if (!yang_dnode_exists(dnode, "./affinity"))
4110 return;
4111
4112 vty_out(vty, " affinity");
4113 yang_dnode_iterate(ag_iter_cb, vty, dnode, "./affinity");
4114 vty_out(vty, "\n");
4115 }
4116
4117 int if_ip_address_install(struct interface *ifp, struct prefix *prefix,
4118 const char *label, struct prefix *pp)
4119 {
4120 struct zebra_if *if_data;
4121 struct prefix_ipv4 lp;
4122 struct prefix_ipv4 *p;
4123 struct connected *ifc;
4124 enum zebra_dplane_result dplane_res;
4125
4126 if_data = ifp->info;
4127
4128 lp.family = prefix->family;
4129 lp.prefix = prefix->u.prefix4;
4130 lp.prefixlen = prefix->prefixlen;
4131 apply_mask_ipv4(&lp);
4132
4133 ifc = connected_check_ptp(ifp, &lp, pp ? pp : NULL);
4134 if (!ifc) {
4135 ifc = connected_new();
4136 ifc->ifp = ifp;
4137
4138 /* Address. */
4139 p = prefix_ipv4_new();
4140 *p = lp;
4141 ifc->address = (struct prefix *)p;
4142
4143 if (pp) {
4144 SET_FLAG(ifc->flags, ZEBRA_IFA_PEER);
4145 p = prefix_ipv4_new();
4146 *p = *(struct prefix_ipv4 *)pp;
4147 ifc->destination = (struct prefix *)p;
4148 }
4149
4150 /* Label. */
4151 if (label)
4152 ifc->label = XSTRDUP(MTYPE_CONNECTED_LABEL, label);
4153
4154 /* Add to linked list. */
4155 listnode_add(ifp->connected, ifc);
4156 }
4157
4158 /* This address is configured from zebra. */
4159 if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED))
4160 SET_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED);
4161
4162 /* In case of this route need to install kernel. */
4163 if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_QUEUED) &&
4164 CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE) &&
4165 !(if_data && if_data->shutdown == IF_ZEBRA_DATA_ON)) {
4166 /* Some system need to up the interface to set IP address. */
4167 if (!if_is_up(ifp)) {
4168 if_set_flags(ifp, IFF_UP | IFF_RUNNING);
4169 if_refresh(ifp);
4170 }
4171
4172 dplane_res = dplane_intf_addr_set(ifp, ifc);
4173 if (dplane_res == ZEBRA_DPLANE_REQUEST_FAILURE) {
4174 zlog_debug(
4175 "dplane can't set interface IP address: %s.",
4176 dplane_res2str(dplane_res));
4177 return NB_ERR;
4178 }
4179
4180 SET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED);
4181 /* The address will be advertised to zebra clients when the
4182 * notification
4183 * from the kernel has been received.
4184 * It will also be added to the subnet chain list, then. */
4185 }
4186
4187 return 0;
4188 }
4189
4190 static int ip_address_install(struct vty *vty, struct interface *ifp,
4191 const char *addr_str, const char *peer_str,
4192 const char *label)
4193 {
4194 struct zebra_if *if_data;
4195 struct prefix_ipv4 lp, pp;
4196 struct connected *ifc;
4197 struct prefix_ipv4 *p;
4198 int ret;
4199 enum zebra_dplane_result dplane_res;
4200
4201 if_data = ifp->info;
4202
4203 ret = str2prefix_ipv4(addr_str, &lp);
4204 if (ret <= 0) {
4205 vty_out(vty, "%% Malformed address \n");
4206 return CMD_WARNING_CONFIG_FAILED;
4207 }
4208
4209 if (ipv4_martian(&lp.prefix)) {
4210 vty_out(vty, "%% Invalid address\n");
4211 return CMD_WARNING_CONFIG_FAILED;
4212 }
4213
4214 if (peer_str) {
4215 if (lp.prefixlen != IPV4_MAX_BITLEN) {
4216 vty_out(vty,
4217 "%% Local prefix length for P-t-P address must be /32\n");
4218 return CMD_WARNING_CONFIG_FAILED;
4219 }
4220
4221 ret = str2prefix_ipv4(peer_str, &pp);
4222 if (ret <= 0) {
4223 vty_out(vty, "%% Malformed peer address\n");
4224 return CMD_WARNING_CONFIG_FAILED;
4225 }
4226 }
4227
4228 ifc = connected_check_ptp(ifp, &lp, peer_str ? &pp : NULL);
4229 if (!ifc) {
4230 ifc = connected_new();
4231 ifc->ifp = ifp;
4232
4233 /* Address. */
4234 p = prefix_ipv4_new();
4235 *p = lp;
4236 ifc->address = (struct prefix *)p;
4237
4238 if (peer_str) {
4239 SET_FLAG(ifc->flags, ZEBRA_IFA_PEER);
4240 p = prefix_ipv4_new();
4241 *p = pp;
4242 ifc->destination = (struct prefix *)p;
4243 }
4244
4245 /* Label. */
4246 if (label)
4247 ifc->label = XSTRDUP(MTYPE_CONNECTED_LABEL, label);
4248
4249 /* Add to linked list. */
4250 listnode_add(ifp->connected, ifc);
4251 }
4252
4253 /* This address is configured from zebra. */
4254 if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED))
4255 SET_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED);
4256
4257 /* In case of this route need to install kernel. */
4258 if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_QUEUED) &&
4259 CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE) &&
4260 !(if_data && if_data->shutdown == IF_ZEBRA_DATA_ON)) {
4261 /* Some system need to up the interface to set IP address. */
4262 if (!if_is_up(ifp)) {
4263 if_set_flags(ifp, IFF_UP | IFF_RUNNING);
4264 if_refresh(ifp);
4265 }
4266
4267 dplane_res = dplane_intf_addr_set(ifp, ifc);
4268 if (dplane_res == ZEBRA_DPLANE_REQUEST_FAILURE) {
4269 vty_out(vty, "%% Can't set interface IP address: %s.\n",
4270 dplane_res2str(dplane_res));
4271 return CMD_WARNING_CONFIG_FAILED;
4272 }
4273
4274 SET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED);
4275 /* The address will be advertised to zebra clients when the
4276 * notification
4277 * from the kernel has been received.
4278 * It will also be added to the subnet chain list, then. */
4279 }
4280
4281 return CMD_SUCCESS;
4282 }
4283
4284 int if_ip_address_uinstall(struct interface *ifp, struct prefix *prefix)
4285 {
4286 struct connected *ifc = NULL;
4287 enum zebra_dplane_result dplane_res;
4288
4289 if (prefix->family == AF_INET) {
4290 /* Check current interface address. */
4291 ifc = connected_check_ptp(ifp, prefix, NULL);
4292 if (!ifc) {
4293 zlog_debug("interface %s Can't find address",
4294 ifp->name);
4295 return -1;
4296 }
4297
4298 } else if (prefix->family == AF_INET6) {
4299 /* Check current interface address. */
4300 ifc = connected_check(ifp, prefix);
4301 }
4302
4303 if (!ifc) {
4304 zlog_debug("interface %s Can't find address", ifp->name);
4305 return -1;
4306 }
4307 UNSET_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED);
4308
4309 /* This is not real address or interface is not active. */
4310 if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_QUEUED)
4311 || !CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE)) {
4312 listnode_delete(ifp->connected, ifc);
4313 connected_free(&ifc);
4314 return CMD_WARNING_CONFIG_FAILED;
4315 }
4316
4317 /* This is real route. */
4318 dplane_res = dplane_intf_addr_unset(ifp, ifc);
4319 if (dplane_res == ZEBRA_DPLANE_REQUEST_FAILURE) {
4320 zlog_debug("Can't unset interface IP address: %s.",
4321 dplane_res2str(dplane_res));
4322 return -1;
4323 }
4324 UNSET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED);
4325
4326 return 0;
4327 }
4328
4329 static int ip_address_uninstall(struct vty *vty, struct interface *ifp,
4330 const char *addr_str, const char *peer_str,
4331 const char *label)
4332 {
4333 struct prefix_ipv4 lp, pp;
4334 struct connected *ifc;
4335 int ret;
4336 enum zebra_dplane_result dplane_res;
4337
4338 /* Convert to prefix structure. */
4339 ret = str2prefix_ipv4(addr_str, &lp);
4340 if (ret <= 0) {
4341 vty_out(vty, "%% Malformed address \n");
4342 return CMD_WARNING_CONFIG_FAILED;
4343 }
4344
4345 if (peer_str) {
4346 if (lp.prefixlen != IPV4_MAX_BITLEN) {
4347 vty_out(vty,
4348 "%% Local prefix length for P-t-P address must be /32\n");
4349 return CMD_WARNING_CONFIG_FAILED;
4350 }
4351
4352 ret = str2prefix_ipv4(peer_str, &pp);
4353 if (ret <= 0) {
4354 vty_out(vty, "%% Malformed peer address\n");
4355 return CMD_WARNING_CONFIG_FAILED;
4356 }
4357 }
4358
4359 /* Check current interface address. */
4360 ifc = connected_check_ptp(ifp, &lp, peer_str ? &pp : NULL);
4361 if (!ifc) {
4362 vty_out(vty, "%% Can't find address\n");
4363 return CMD_WARNING_CONFIG_FAILED;
4364 }
4365
4366 /* This is not configured address. */
4367 if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED))
4368 return CMD_WARNING_CONFIG_FAILED;
4369
4370 UNSET_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED);
4371
4372 /* This is not real address or interface is not active. */
4373 if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_QUEUED)
4374 || !CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE)) {
4375 listnode_delete(ifp->connected, ifc);
4376 connected_free(&ifc);
4377 return CMD_WARNING_CONFIG_FAILED;
4378 }
4379
4380 /* This is real route. */
4381 dplane_res = dplane_intf_addr_unset(ifp, ifc);
4382 if (dplane_res == ZEBRA_DPLANE_REQUEST_FAILURE) {
4383 vty_out(vty, "%% Can't unset interface IP address: %s.\n",
4384 dplane_res2str(dplane_res));
4385 return CMD_WARNING_CONFIG_FAILED;
4386 }
4387 UNSET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED);
4388 /* we will receive a kernel notification about this route being removed.
4389 * this will trigger its removal from the connected list. */
4390 return CMD_SUCCESS;
4391 }
4392
4393 DEFUN (ip_address,
4394 ip_address_cmd,
4395 "ip address A.B.C.D/M",
4396 "Interface Internet Protocol config commands\n"
4397 "Set the IP address of an interface\n"
4398 "IP address (e.g. 10.0.0.1/8)\n")
4399 {
4400 int idx_ipv4_prefixlen = 2;
4401 VTY_DECLVAR_CONTEXT(interface, ifp);
4402 return ip_address_install(vty, ifp, argv[idx_ipv4_prefixlen]->arg, NULL,
4403 NULL);
4404 }
4405
4406 DEFUN (no_ip_address,
4407 no_ip_address_cmd,
4408 "no ip address A.B.C.D/M",
4409 NO_STR
4410 "Interface Internet Protocol config commands\n"
4411 "Set the IP address of an interface\n"
4412 "IP Address (e.g. 10.0.0.1/8)\n")
4413 {
4414 int idx_ipv4_prefixlen = 3;
4415 VTY_DECLVAR_CONTEXT(interface, ifp);
4416 return ip_address_uninstall(vty, ifp, argv[idx_ipv4_prefixlen]->arg,
4417 NULL, NULL);
4418 }
4419
4420 DEFUN(ip_address_peer,
4421 ip_address_peer_cmd,
4422 "ip address A.B.C.D peer A.B.C.D/M",
4423 "Interface Internet Protocol config commands\n"
4424 "Set the IP address of an interface\n"
4425 "Local IP (e.g. 10.0.0.1) for P-t-P address\n"
4426 "Specify P-t-P address\n"
4427 "Peer IP address (e.g. 10.0.0.1/8)\n")
4428 {
4429 VTY_DECLVAR_CONTEXT(interface, ifp);
4430 return ip_address_install(vty, ifp, argv[2]->arg, argv[4]->arg, NULL);
4431 }
4432
4433 DEFUN(no_ip_address_peer,
4434 no_ip_address_peer_cmd,
4435 "no ip address A.B.C.D peer A.B.C.D/M",
4436 NO_STR
4437 "Interface Internet Protocol config commands\n"
4438 "Set the IP address of an interface\n"
4439 "Local IP (e.g. 10.0.0.1) for P-t-P address\n"
4440 "Specify P-t-P address\n"
4441 "Peer IP address (e.g. 10.0.0.1/8)\n")
4442 {
4443 VTY_DECLVAR_CONTEXT(interface, ifp);
4444 return ip_address_uninstall(vty, ifp, argv[3]->arg, argv[5]->arg, NULL);
4445 }
4446
4447 #ifdef HAVE_NETLINK
4448 DEFUN (ip_address_label,
4449 ip_address_label_cmd,
4450 "ip address A.B.C.D/M label LINE",
4451 "Interface Internet Protocol config commands\n"
4452 "Set the IP address of an interface\n"
4453 "IP address (e.g. 10.0.0.1/8)\n"
4454 "Label of this address\n"
4455 "Label\n")
4456 {
4457 int idx_ipv4_prefixlen = 2;
4458 int idx_line = 4;
4459 VTY_DECLVAR_CONTEXT(interface, ifp);
4460 return ip_address_install(vty, ifp, argv[idx_ipv4_prefixlen]->arg, NULL,
4461 argv[idx_line]->arg);
4462 }
4463
4464 DEFUN (no_ip_address_label,
4465 no_ip_address_label_cmd,
4466 "no ip address A.B.C.D/M label LINE",
4467 NO_STR
4468 "Interface Internet Protocol config commands\n"
4469 "Set the IP address of an interface\n"
4470 "IP address (e.g. 10.0.0.1/8)\n"
4471 "Label of this address\n"
4472 "Label\n")
4473 {
4474 int idx_ipv4_prefixlen = 3;
4475 int idx_line = 5;
4476 VTY_DECLVAR_CONTEXT(interface, ifp);
4477 return ip_address_uninstall(vty, ifp, argv[idx_ipv4_prefixlen]->arg,
4478 NULL, argv[idx_line]->arg);
4479 }
4480 #endif /* HAVE_NETLINK */
4481
4482 int if_ipv6_address_install(struct interface *ifp, struct prefix *prefix,
4483 const char *label)
4484 {
4485 struct zebra_if *if_data;
4486 struct prefix_ipv6 cp;
4487 struct connected *ifc;
4488 struct prefix_ipv6 *p;
4489 enum zebra_dplane_result dplane_res;
4490
4491 if_data = ifp->info;
4492
4493 cp.family = prefix->family;
4494 cp.prefixlen = prefix->prefixlen;
4495 cp.prefix = prefix->u.prefix6;
4496 apply_mask_ipv6(&cp);
4497
4498 ifc = connected_check(ifp, (struct prefix *)&cp);
4499 if (!ifc) {
4500 ifc = connected_new();
4501 ifc->ifp = ifp;
4502
4503 /* Address. */
4504 p = prefix_ipv6_new();
4505 *p = cp;
4506 ifc->address = (struct prefix *)p;
4507
4508 /* Label. */
4509 if (label)
4510 ifc->label = XSTRDUP(MTYPE_CONNECTED_LABEL, label);
4511
4512 /* Add to linked list. */
4513 listnode_add(ifp->connected, ifc);
4514 }
4515
4516 /* This address is configured from zebra. */
4517 if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED))
4518 SET_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED);
4519
4520 /* In case of this route need to install kernel. */
4521 if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_QUEUED) &&
4522 CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE) &&
4523 !(if_data && if_data->shutdown == IF_ZEBRA_DATA_ON)) {
4524 /* Some system need to up the interface to set IP address. */
4525 if (!if_is_up(ifp)) {
4526 if_set_flags(ifp, IFF_UP | IFF_RUNNING);
4527 if_refresh(ifp);
4528 }
4529
4530 dplane_res = dplane_intf_addr_set(ifp, ifc);
4531 if (dplane_res == ZEBRA_DPLANE_REQUEST_FAILURE) {
4532 zlog_debug(
4533 "dplane can't set interface IP address: %s.",
4534 dplane_res2str(dplane_res));
4535 return NB_ERR;
4536 }
4537
4538 SET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED);
4539 /* The address will be advertised to zebra clients when the
4540 * notification
4541 * from the kernel has been received. */
4542 }
4543
4544 return 0;
4545 }
4546
4547 static int ipv6_address_install(struct vty *vty, struct interface *ifp,
4548 const char *addr_str, const char *peer_str,
4549 const char *label)
4550 {
4551 struct zebra_if *if_data;
4552 struct prefix_ipv6 cp;
4553 struct connected *ifc;
4554 struct prefix_ipv6 *p;
4555 int ret;
4556 enum zebra_dplane_result dplane_res;
4557
4558 if_data = ifp->info;
4559
4560 ret = str2prefix_ipv6(addr_str, &cp);
4561 if (ret <= 0) {
4562 vty_out(vty, "%% Malformed address \n");
4563 return CMD_WARNING_CONFIG_FAILED;
4564 }
4565
4566 if (ipv6_martian(&cp.prefix)) {
4567 vty_out(vty, "%% Invalid address\n");
4568 return CMD_WARNING_CONFIG_FAILED;
4569 }
4570
4571 ifc = connected_check(ifp, (struct prefix *)&cp);
4572 if (!ifc) {
4573 ifc = connected_new();
4574 ifc->ifp = ifp;
4575
4576 /* Address. */
4577 p = prefix_ipv6_new();
4578 *p = cp;
4579 ifc->address = (struct prefix *)p;
4580
4581 /* Label. */
4582 if (label)
4583 ifc->label = XSTRDUP(MTYPE_CONNECTED_LABEL, label);
4584
4585 /* Add to linked list. */
4586 listnode_add(ifp->connected, ifc);
4587 }
4588
4589 /* This address is configured from zebra. */
4590 if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED))
4591 SET_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED);
4592
4593 /* In case of this route need to install kernel. */
4594 if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_QUEUED) &&
4595 CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE) &&
4596 !(if_data && if_data->shutdown == IF_ZEBRA_DATA_ON)) {
4597 /* Some system need to up the interface to set IP address. */
4598 if (!if_is_up(ifp)) {
4599 if_set_flags(ifp, IFF_UP | IFF_RUNNING);
4600 if_refresh(ifp);
4601 }
4602
4603 dplane_res = dplane_intf_addr_set(ifp, ifc);
4604 if (dplane_res == ZEBRA_DPLANE_REQUEST_FAILURE) {
4605 vty_out(vty, "%% Can't set interface IP address: %s.\n",
4606 dplane_res2str(dplane_res));
4607 return CMD_WARNING_CONFIG_FAILED;
4608 }
4609
4610 SET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED);
4611 /* The address will be advertised to zebra clients when the
4612 * notification
4613 * from the kernel has been received. */
4614 }
4615
4616 return CMD_SUCCESS;
4617 }
4618
4619 /* Return true if an ipv6 address is configured on ifp */
4620 int ipv6_address_configured(struct interface *ifp)
4621 {
4622 struct connected *connected;
4623 struct listnode *node;
4624
4625 for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, connected))
4626 if (CHECK_FLAG(connected->conf, ZEBRA_IFC_REAL)
4627 && (connected->address->family == AF_INET6))
4628 return 1;
4629
4630 return 0;
4631 }
4632
4633 static int ipv6_address_uninstall(struct vty *vty, struct interface *ifp,
4634 const char *addr_str, const char *peer_str,
4635 const char *label)
4636 {
4637 struct prefix_ipv6 cp;
4638 struct connected *ifc;
4639 int ret;
4640 enum zebra_dplane_result dplane_res;
4641
4642 /* Convert to prefix structure. */
4643 ret = str2prefix_ipv6(addr_str, &cp);
4644 if (ret <= 0) {
4645 vty_out(vty, "%% Malformed address \n");
4646 return CMD_WARNING_CONFIG_FAILED;
4647 }
4648
4649 /* Check current interface address. */
4650 ifc = connected_check(ifp, (struct prefix *)&cp);
4651 if (!ifc) {
4652 vty_out(vty, "%% Can't find address\n");
4653 return CMD_WARNING_CONFIG_FAILED;
4654 }
4655
4656 /* This is not configured address. */
4657 if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED))
4658 return CMD_WARNING_CONFIG_FAILED;
4659
4660 UNSET_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED);
4661
4662 /* This is not real address or interface is not active. */
4663 if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_QUEUED)
4664 || !CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE)) {
4665 listnode_delete(ifp->connected, ifc);
4666 connected_free(&ifc);
4667 return CMD_WARNING_CONFIG_FAILED;
4668 }
4669
4670 /* This is real route. */
4671 dplane_res = dplane_intf_addr_unset(ifp, ifc);
4672 if (dplane_res == ZEBRA_DPLANE_REQUEST_FAILURE) {
4673 vty_out(vty, "%% Can't unset interface IP address: %s.\n",
4674 dplane_res2str(dplane_res));
4675 return CMD_WARNING_CONFIG_FAILED;
4676 }
4677
4678 UNSET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED);
4679 /* This information will be propagated to the zclients when the
4680 * kernel notification is received. */
4681 return CMD_SUCCESS;
4682 }
4683
4684 DEFUN (ipv6_address,
4685 ipv6_address_cmd,
4686 "ipv6 address X:X::X:X/M",
4687 "Interface IPv6 config commands\n"
4688 "Set the IP address of an interface\n"
4689 "IPv6 address (e.g. 3ffe:506::1/48)\n")
4690 {
4691 int idx_ipv6_prefixlen = 2;
4692 VTY_DECLVAR_CONTEXT(interface, ifp);
4693 return ipv6_address_install(vty, ifp, argv[idx_ipv6_prefixlen]->arg,
4694 NULL, NULL);
4695 }
4696
4697 DEFUN (no_ipv6_address,
4698 no_ipv6_address_cmd,
4699 "no ipv6 address X:X::X:X/M",
4700 NO_STR
4701 "Interface IPv6 config commands\n"
4702 "Set the IP address of an interface\n"
4703 "IPv6 address (e.g. 3ffe:506::1/48)\n")
4704 {
4705 int idx_ipv6_prefixlen = 3;
4706 VTY_DECLVAR_CONTEXT(interface, ifp);
4707 return ipv6_address_uninstall(vty, ifp, argv[idx_ipv6_prefixlen]->arg,
4708 NULL, NULL);
4709 }
4710
4711 static int link_params_config_write(struct vty *vty, struct interface *ifp)
4712 {
4713 const struct lyd_node *dnode;
4714 char xpath[XPATH_MAXLEN];
4715 int i;
4716
4717 if ((ifp == NULL) || !HAS_LINK_PARAMS(ifp))
4718 return -1;
4719
4720 struct if_link_params *iflp = ifp->link_params;
4721
4722 vty_out(vty, " link-params\n");
4723 vty_out(vty, " enable\n");
4724 if (IS_PARAM_SET(iflp, LP_TE_METRIC) && iflp->te_metric != ifp->metric)
4725 vty_out(vty, " metric %u\n", iflp->te_metric);
4726 if (IS_PARAM_SET(iflp, LP_MAX_BW) && iflp->max_bw != iflp->default_bw)
4727 vty_out(vty, " max-bw %g\n", iflp->max_bw);
4728 if (IS_PARAM_SET(iflp, LP_MAX_RSV_BW)
4729 && iflp->max_rsv_bw != iflp->default_bw)
4730 vty_out(vty, " max-rsv-bw %g\n", iflp->max_rsv_bw);
4731 if (IS_PARAM_SET(iflp, LP_UNRSV_BW)) {
4732 for (i = 0; i < 8; i++)
4733 if (iflp->unrsv_bw[i] != iflp->default_bw)
4734 vty_out(vty, " unrsv-bw %d %g\n", i,
4735 iflp->unrsv_bw[i]);
4736 }
4737
4738 snprintf(
4739 xpath, sizeof(xpath),
4740 "/frr-interface:lib/interface[name='%s']/frr-zebra:zebra/link-params",
4741 ifp->name);
4742 dnode = yang_dnode_get(running_config->dnode, xpath);
4743 if (dnode)
4744 nb_cli_show_dnode_cmds(vty, dnode, false);
4745
4746 if (IS_PARAM_SET(iflp, LP_DELAY)) {
4747 vty_out(vty, " delay %u", iflp->av_delay);
4748 if (IS_PARAM_SET(iflp, LP_MM_DELAY)) {
4749 vty_out(vty, " min %u", iflp->min_delay);
4750 vty_out(vty, " max %u", iflp->max_delay);
4751 }
4752 vty_out(vty, "\n");
4753 }
4754 if (IS_PARAM_SET(iflp, LP_DELAY_VAR))
4755 vty_out(vty, " delay-variation %u\n", iflp->delay_var);
4756 if (IS_PARAM_SET(iflp, LP_PKT_LOSS))
4757 vty_out(vty, " packet-loss %g\n", iflp->pkt_loss);
4758 if (IS_PARAM_SET(iflp, LP_AVA_BW))
4759 vty_out(vty, " ava-bw %g\n", iflp->ava_bw);
4760 if (IS_PARAM_SET(iflp, LP_RES_BW))
4761 vty_out(vty, " res-bw %g\n", iflp->res_bw);
4762 if (IS_PARAM_SET(iflp, LP_USE_BW))
4763 vty_out(vty, " use-bw %g\n", iflp->use_bw);
4764 if (IS_PARAM_SET(iflp, LP_RMT_AS))
4765 vty_out(vty, " neighbor %pI4 as %u\n", &iflp->rmt_ip,
4766 iflp->rmt_as);
4767
4768 vty_out(vty, " exit-link-params\n");
4769 return 0;
4770 }
4771
4772 static int if_config_write(struct vty *vty)
4773 {
4774 struct vrf *vrf;
4775 struct interface *ifp;
4776
4777 zebra_ptm_write(vty);
4778
4779 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name)
4780 FOR_ALL_INTERFACES (vrf, ifp) {
4781 struct zebra_if *if_data;
4782 struct listnode *addrnode;
4783 struct connected *ifc;
4784 struct prefix *p;
4785
4786 if_data = ifp->info;
4787
4788 if_vty_config_start(vty, ifp);
4789
4790 if (if_data) {
4791 if (if_data->shutdown == IF_ZEBRA_DATA_ON)
4792 vty_out(vty, " shutdown\n");
4793
4794 zebra_ptm_if_write(vty, if_data);
4795 }
4796
4797 if (ifp->desc)
4798 vty_out(vty, " description %s\n", ifp->desc);
4799
4800 /* Assign bandwidth here to avoid unnecessary interface
4801 flap
4802 while processing config script */
4803 if (ifp->bandwidth != 0)
4804 vty_out(vty, " bandwidth %u\n", ifp->bandwidth);
4805
4806 if (!CHECK_FLAG(ifp->status,
4807 ZEBRA_INTERFACE_LINKDETECTION))
4808 vty_out(vty, " no link-detect\n");
4809
4810 for (ALL_LIST_ELEMENTS_RO(ifp->connected, addrnode,
4811 ifc)) {
4812 if (CHECK_FLAG(ifc->conf,
4813 ZEBRA_IFC_CONFIGURED)) {
4814 char buf[INET6_ADDRSTRLEN];
4815 p = ifc->address;
4816 vty_out(vty, " ip%s address %s",
4817 p->family == AF_INET ? ""
4818 : "v6",
4819 inet_ntop(p->family,
4820 &p->u.prefix, buf,
4821 sizeof(buf)));
4822 if (CONNECTED_PEER(ifc)) {
4823 p = ifc->destination;
4824 vty_out(vty, " peer %s",
4825 inet_ntop(p->family,
4826 &p->u.prefix,
4827 buf,
4828 sizeof(buf)));
4829 }
4830 vty_out(vty, "/%d", p->prefixlen);
4831
4832 if (ifc->label)
4833 vty_out(vty, " label %s",
4834 ifc->label);
4835
4836 vty_out(vty, "\n");
4837 }
4838 }
4839
4840 if (if_data) {
4841 if (if_data->multicast != IF_ZEBRA_DATA_UNSPEC)
4842 vty_out(vty, " %smulticast\n",
4843 if_data->multicast ==
4844 IF_ZEBRA_DATA_ON
4845 ? ""
4846 : "no ");
4847 if (if_data->mpls == IF_ZEBRA_DATA_ON)
4848 vty_out(vty, " mpls enable\n");
4849 }
4850
4851 hook_call(zebra_if_config_wr, vty, ifp);
4852 zebra_evpn_mh_if_write(vty, ifp);
4853 link_params_config_write(vty, ifp);
4854
4855 if_vty_config_end(vty);
4856 }
4857 return 0;
4858 }
4859
4860 /* Allocate and initialize interface vector. */
4861 void zebra_if_init(void)
4862 {
4863 /* Initialize interface and new hook. */
4864 hook_register_prio(if_add, 0, if_zebra_new_hook);
4865 hook_register_prio(if_del, 0, if_zebra_delete_hook);
4866
4867 /* Install configuration write function. */
4868 if_cmd_init(if_config_write);
4869 install_node(&link_params_node);
4870 /*
4871 * This is *intentionally* setting this to NULL, signaling
4872 * that interface creation for zebra acts differently
4873 */
4874 if_zapi_callbacks(NULL, NULL, NULL, NULL);
4875
4876 install_element(VIEW_NODE, &show_interface_cmd);
4877 install_element(VIEW_NODE, &show_interface_vrf_all_cmd);
4878 install_element(VIEW_NODE, &show_interface_name_vrf_cmd);
4879 install_element(VIEW_NODE, &show_interface_name_vrf_all_cmd);
4880
4881 install_element(ENABLE_NODE, &show_interface_desc_cmd);
4882 install_element(ENABLE_NODE, &show_interface_desc_vrf_all_cmd);
4883 install_element(INTERFACE_NODE, &multicast_cmd);
4884 install_element(INTERFACE_NODE, &no_multicast_cmd);
4885 install_element(INTERFACE_NODE, &mpls_cmd);
4886 install_element(INTERFACE_NODE, &linkdetect_cmd);
4887 install_element(INTERFACE_NODE, &no_linkdetect_cmd);
4888 install_element(INTERFACE_NODE, &shutdown_if_cmd);
4889 install_element(INTERFACE_NODE, &no_shutdown_if_cmd);
4890 install_element(INTERFACE_NODE, &bandwidth_if_cmd);
4891 install_element(INTERFACE_NODE, &no_bandwidth_if_cmd);
4892 install_element(INTERFACE_NODE, &ip_address_cmd);
4893 install_element(INTERFACE_NODE, &no_ip_address_cmd);
4894 install_element(INTERFACE_NODE, &ip_address_peer_cmd);
4895 install_element(INTERFACE_NODE, &no_ip_address_peer_cmd);
4896 install_element(INTERFACE_NODE, &ipv6_address_cmd);
4897 install_element(INTERFACE_NODE, &no_ipv6_address_cmd);
4898 #ifdef HAVE_NETLINK
4899 install_element(INTERFACE_NODE, &ip_address_label_cmd);
4900 install_element(INTERFACE_NODE, &no_ip_address_label_cmd);
4901 #endif /* HAVE_NETLINK */
4902 install_element(INTERFACE_NODE, &link_params_cmd);
4903 install_default(LINK_PARAMS_NODE);
4904 install_element(LINK_PARAMS_NODE, &link_params_enable_cmd);
4905 install_element(LINK_PARAMS_NODE, &no_link_params_enable_cmd);
4906 install_element(LINK_PARAMS_NODE, &link_params_metric_cmd);
4907 install_element(LINK_PARAMS_NODE, &no_link_params_metric_cmd);
4908 install_element(LINK_PARAMS_NODE, &link_params_maxbw_cmd);
4909 install_element(LINK_PARAMS_NODE, &link_params_max_rsv_bw_cmd);
4910 install_element(LINK_PARAMS_NODE, &link_params_unrsv_bw_cmd);
4911 install_element(LINK_PARAMS_NODE, &link_params_admin_grp_cmd);
4912 install_element(LINK_PARAMS_NODE, &no_link_params_admin_grp_cmd);
4913 install_element(LINK_PARAMS_NODE, &link_params_inter_as_cmd);
4914 install_element(LINK_PARAMS_NODE, &no_link_params_inter_as_cmd);
4915 install_element(LINK_PARAMS_NODE, &link_params_delay_cmd);
4916 install_element(LINK_PARAMS_NODE, &no_link_params_delay_cmd);
4917 install_element(LINK_PARAMS_NODE, &link_params_delay_var_cmd);
4918 install_element(LINK_PARAMS_NODE, &no_link_params_delay_var_cmd);
4919 install_element(LINK_PARAMS_NODE, &link_params_pkt_loss_cmd);
4920 install_element(LINK_PARAMS_NODE, &no_link_params_pkt_loss_cmd);
4921 install_element(LINK_PARAMS_NODE, &link_params_ava_bw_cmd);
4922 install_element(LINK_PARAMS_NODE, &no_link_params_ava_bw_cmd);
4923 install_element(LINK_PARAMS_NODE, &link_params_res_bw_cmd);
4924 install_element(LINK_PARAMS_NODE, &no_link_params_res_bw_cmd);
4925 install_element(LINK_PARAMS_NODE, &link_params_use_bw_cmd);
4926 install_element(LINK_PARAMS_NODE, &no_link_params_use_bw_cmd);
4927 install_element(LINK_PARAMS_NODE, &link_params_affinity_cmd);
4928 install_element(LINK_PARAMS_NODE, &link_params_affinity_mode_cmd);
4929 install_element(LINK_PARAMS_NODE, &no_link_params_affinity_mode_cmd);
4930 install_element(LINK_PARAMS_NODE, &exit_link_params_cmd);
4931
4932 /* setup EVPN MH elements */
4933 zebra_evpn_interface_init();
4934 }