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