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