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