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