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