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