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