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