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