]> git.proxmox.com Git - mirror_frr.git/blame - zebra/interface.c
zebra: Convert to `enum zebra_iftype` as per our internal standard
[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++;
1029 quagga_timestamp(2, zif->up_last, sizeof(zif->up_last));
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++;
1093 quagga_timestamp(2, zif->down_last, sizeof(zif->down_last));
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
718e3744 1208/* Dump if address information to vty. */
c15dc24f
RW
1209static void connected_dump_vty(struct vty *vty, json_object *json,
1210 struct connected *connected)
718e3744 1211{
d62a17ae 1212 struct prefix *p;
c15dc24f
RW
1213 json_object *json_addr = NULL;
1214 char buf[PREFIX2STR_BUFFER];
718e3744 1215
d62a17ae 1216 /* Print interface address. */
1217 p = connected->address;
c15dc24f
RW
1218
1219 if (json) {
1220 json_addr = json_object_new_object();
1221 json_object_array_add(json, json_addr);
1222 json_object_string_add(json_addr, "address",
1223 prefix2str(p, buf, sizeof(buf)));
1224 } else {
1225 vty_out(vty, " %s %pFX", prefix_family_str(p), p);
1226 }
718e3744 1227
d62a17ae 1228 /* If there is destination address, print it. */
0f3af738 1229 if (CONNECTED_PEER(connected) && connected->destination) {
c15dc24f
RW
1230 if (json) {
1231 json_object_string_add(
1232 json_addr, "peer",
1233 prefix2str(connected->destination, buf,
1234 sizeof(buf)));
1235 } else {
1236 vty_out(vty, " peer %pFX", connected->destination);
1237 }
d62a17ae 1238 }
718e3744 1239
c15dc24f
RW
1240 if (json)
1241 json_object_boolean_add(
1242 json_addr, "secondary",
1243 CHECK_FLAG(connected->flags, ZEBRA_IFA_SECONDARY));
1244 else if (CHECK_FLAG(connected->flags, ZEBRA_IFA_SECONDARY))
d62a17ae 1245 vty_out(vty, " secondary");
718e3744 1246
c15dc24f
RW
1247 if (json)
1248 json_object_boolean_add(
1249 json_addr, "unnumbered",
1250 CHECK_FLAG(connected->flags, ZEBRA_IFA_UNNUMBERED));
1251 else if (CHECK_FLAG(connected->flags, ZEBRA_IFA_UNNUMBERED))
d62a17ae 1252 vty_out(vty, " unnumbered");
525c1839 1253
c15dc24f
RW
1254 if (connected->label) {
1255 if (json)
1256 json_object_string_add(json_addr, "label",
1257 connected->label);
1258 else
1259 vty_out(vty, " %s", connected->label);
1260 }
718e3744 1261
c15dc24f
RW
1262 if (!json)
1263 vty_out(vty, "\n");
718e3744 1264}
1265
a80beece 1266/* Dump interface neighbor address information to vty. */
c15dc24f 1267static void nbr_connected_dump_vty(struct vty *vty, json_object *json,
d62a17ae 1268 struct nbr_connected *connected)
a80beece 1269{
d62a17ae 1270 struct prefix *p;
c15dc24f 1271 char buf[PREFIX2STR_BUFFER];
a80beece 1272
d62a17ae 1273 /* Print interface address. */
1274 p = connected->address;
c15dc24f
RW
1275 if (json)
1276 json_array_string_add(json, prefix2str(p, buf, sizeof(buf)));
1277 else
1278 vty_out(vty, " %s %pFX\n", prefix_family_str(p), p);
a80beece
DS
1279}
1280
d0738ba2
PG
1281static const char *zebra_zifslavetype_2str(zebra_slave_iftype_t zif_slave_type)
1282{
1283 switch (zif_slave_type) {
1284 case ZEBRA_IF_SLAVE_BRIDGE:
1285 return "Bridge";
1286 case ZEBRA_IF_SLAVE_VRF:
1287 return "Vrf";
1288 case ZEBRA_IF_SLAVE_BOND:
1289 return "Bond";
1290 case ZEBRA_IF_SLAVE_OTHER:
1291 return "Other";
1292 case ZEBRA_IF_SLAVE_NONE:
1293 return "None";
1294 }
1295 return "None";
1296}
1297
e6f2bec0 1298static const char *zebra_ziftype_2str(enum zebra_iftype zif_type)
6675513d 1299{
d62a17ae 1300 switch (zif_type) {
1301 case ZEBRA_IF_OTHER:
1302 return "Other";
6675513d 1303
d62a17ae 1304 case ZEBRA_IF_BRIDGE:
1305 return "Bridge";
6675513d 1306
d62a17ae 1307 case ZEBRA_IF_VLAN:
1308 return "Vlan";
6675513d 1309
d62a17ae 1310 case ZEBRA_IF_VXLAN:
1311 return "Vxlan";
6675513d 1312
d62a17ae 1313 case ZEBRA_IF_VRF:
1314 return "VRF";
6675513d 1315
0e4864ea
PG
1316 case ZEBRA_IF_VETH:
1317 return "VETH";
0e4864ea 1318
b9368db9
DD
1319 case ZEBRA_IF_BOND:
1320 return "bond";
1321
1322 case ZEBRA_IF_BOND_SLAVE:
1323 return "bond_slave";
1324
1325 case ZEBRA_IF_MACVLAN:
1326 return "macvlan";
1327
077c07cc
PG
1328 case ZEBRA_IF_GRE:
1329 return "GRE";
1330
d62a17ae 1331 default:
1332 return "Unknown";
d62a17ae 1333 }
6675513d 1334}
1335
49548752
NS
1336/* Interface's brief information print out to vty interface. */
1337static void ifs_dump_brief_vty(struct vty *vty, struct vrf *vrf)
1338{
1339 struct connected *connected;
1340 struct listnode *node;
1341 struct route_node *rn;
1342 struct zebra_if *zebra_if;
1343 struct prefix *p;
1344 struct interface *ifp;
1345 bool print_header = true;
1346
1347 FOR_ALL_INTERFACES (vrf, ifp) {
49548752
NS
1348 bool first_pfx_printed = false;
1349
1350 if (print_header) {
1351 vty_out(vty, "%-16s%-8s%-16s%s\n", "Interface",
1352 "Status", "VRF", "Addresses");
1353 vty_out(vty, "%-16s%-8s%-16s%s\n", "---------",
1354 "------", "---", "---------");
1355 print_header = false; /* We have at least 1 iface */
1356 }
1357 zebra_if = ifp->info;
1358
1359 vty_out(vty, "%-16s", ifp->name);
1360
1361 if (if_is_up(ifp))
1362 vty_out(vty, "%-8s", "up");
1363 else
1364 vty_out(vty, "%-8s", "down");
1365
1366 vty_out(vty, "%-16s", vrf->name);
1367
1368 for (rn = route_top(zebra_if->ipv4_subnets); rn;
1369 rn = route_next(rn)) {
1370 if (!rn->info)
1371 continue;
1372 uint32_t list_size = listcount((struct list *)rn->info);
1373
1374 for (ALL_LIST_ELEMENTS_RO((struct list *)rn->info, node,
1375 connected)) {
1376 if (!CHECK_FLAG(connected->flags,
1377 ZEBRA_IFA_SECONDARY)) {
1378 p = connected->address;
49548752 1379 if (first_pfx_printed) {
2dbe669b
DA
1380 /* padding to prepare row only
1381 * for ip addr */
49548752
NS
1382 vty_out(vty, "%-40s", "");
1383 if (list_size > 1)
1384 vty_out(vty, "+ ");
2dbe669b 1385 vty_out(vty, "%pFX\n", p);
49548752
NS
1386 } else {
1387 if (list_size > 1)
1388 vty_out(vty, "+ ");
2dbe669b 1389 vty_out(vty, "%pFX\n", p);
49548752
NS
1390 }
1391 first_pfx_printed = true;
1392 break;
1393 }
1394 }
1395 }
1396
1397 uint32_t v6_list_size = 0;
1398 for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, connected)) {
1399 if (CHECK_FLAG(connected->conf, ZEBRA_IFC_REAL)
1400 && (connected->address->family == AF_INET6))
1401 v6_list_size++;
1402 }
1403 for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, connected)) {
1404 if (CHECK_FLAG(connected->conf, ZEBRA_IFC_REAL)
1405 && !CHECK_FLAG(connected->flags,
1406 ZEBRA_IFA_SECONDARY)
1407 && (connected->address->family == AF_INET6)) {
1408 p = connected->address;
1409 /* Don't print link local pfx */
1410 if (!IN6_IS_ADDR_LINKLOCAL(&p->u.prefix6)) {
49548752 1411 if (first_pfx_printed) {
2dbe669b
DA
1412 /* padding to prepare row only
1413 * for ip addr */
49548752
NS
1414 vty_out(vty, "%-40s", "");
1415 if (v6_list_size > 1)
1416 vty_out(vty, "+ ");
2dbe669b 1417 vty_out(vty, "%pFX\n", p);
49548752
NS
1418 } else {
1419 if (v6_list_size > 1)
1420 vty_out(vty, "+ ");
2dbe669b 1421 vty_out(vty, "%pFX\n", p);
49548752
NS
1422 }
1423 first_pfx_printed = true;
1424 break;
1425 }
1426 }
1427 }
1428 if (!first_pfx_printed)
1429 vty_out(vty, "\n");
1430 }
1431 vty_out(vty, "\n");
1432}
1433
c15dc24f
RW
1434static void ifs_dump_brief_vty_json(json_object *json, struct vrf *vrf)
1435{
1436 struct connected *connected;
1437 struct listnode *node;
1438 struct interface *ifp;
1439
1440 FOR_ALL_INTERFACES (vrf, ifp) {
1441 json_object *json_if;
1442 json_object *json_addrs;
1443
1444 json_if = json_object_new_object();
1445 json_object_object_add(json, ifp->name, json_if);
1446
1447 json_object_string_add(json_if, "status",
1448 if_is_up(ifp) ? "up" : "down");
1449 json_object_string_add(json_if, "vrfName", vrf->name);
1450
1451 json_addrs = json_object_new_array();
1452 json_object_object_add(json_if, "addresses", json_addrs);
1453 for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, connected)) {
1454 if (CHECK_FLAG(connected->conf, ZEBRA_IFC_REAL)
1455 && !CHECK_FLAG(connected->flags,
1456 ZEBRA_IFA_SECONDARY)
1457 && !(connected->address->family == AF_INET6
1458 && IN6_IS_ADDR_LINKLOCAL(
1459 &connected->address->u.prefix6))) {
1460 char buf[PREFIX2STR_BUFFER];
1461
1462 json_array_string_add(
1463 json_addrs,
1464 prefix2str(connected->address, buf,
1465 sizeof(buf)));
1466 }
1467 }
1468 }
1469}
1470
904e9b05
MS
1471const char *zebra_protodown_rc_str(enum protodown_reasons protodown_rc,
1472 char *pd_buf, uint32_t pd_buf_len)
c36e442c
AK
1473{
1474 bool first = true;
1475
1476 pd_buf[0] = '\0';
1477
904e9b05 1478 strlcat(pd_buf, "(", pd_buf_len);
c36e442c
AK
1479
1480 if (protodown_rc & ZEBRA_PROTODOWN_EVPN_STARTUP_DELAY) {
1481 if (first)
1482 first = false;
1483 else
904e9b05
MS
1484 strlcat(pd_buf, ",", pd_buf_len);
1485 strlcat(pd_buf, "startup-delay", pd_buf_len);
c36e442c
AK
1486 }
1487
1488 if (protodown_rc & ZEBRA_PROTODOWN_EVPN_UPLINK_DOWN) {
904e9b05
MS
1489 if (!first)
1490 strlcat(pd_buf, ",", pd_buf_len);
1491 strlcat(pd_buf, "uplinks-down", pd_buf_len);
c36e442c
AK
1492 }
1493
904e9b05 1494 strlcat(pd_buf, ")", pd_buf_len);
c36e442c
AK
1495
1496 return pd_buf;
1497}
1498
26ba45e3
AK
1499static inline bool if_is_protodown_applicable(struct interface *ifp)
1500{
1501 if (IS_ZEBRA_IF_BOND(ifp))
1502 return false;
1503
1504 return true;
1505}
1506
718e3744 1507/* Interface's information print out to vty interface. */
d62a17ae 1508static void if_dump_vty(struct vty *vty, struct interface *ifp)
1509{
1510 struct connected *connected;
1511 struct nbr_connected *nbr_connected;
1512 struct listnode *node;
1513 struct route_node *rn;
1514 struct zebra_if *zebra_if;
1515 struct vrf *vrf;
c36e442c 1516 char pd_buf[ZEBRA_PROTODOWN_RC_STR_LEN];
d62a17ae 1517
1518 zebra_if = ifp->info;
1519
1520 vty_out(vty, "Interface %s is ", ifp->name);
1521 if (if_is_up(ifp)) {
1522 vty_out(vty, "up, line protocol ");
1523
1524 if (CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_LINKDETECTION)) {
1525 if (if_is_running(ifp))
1526 vty_out(vty, "is up\n");
1527 else
1528 vty_out(vty, "is down\n");
1529 } else {
1530 vty_out(vty, "detection is disabled\n");
1531 }
1532 } else {
1533 vty_out(vty, "down\n");
1534 }
1535
1536 vty_out(vty, " Link ups: %5u last: %s\n", zebra_if->up_count,
1537 zebra_if->up_last[0] ? zebra_if->up_last : "(never)");
1538 vty_out(vty, " Link downs: %5u last: %s\n", zebra_if->down_count,
1539 zebra_if->down_last[0] ? zebra_if->down_last : "(never)");
1540
c15dc24f 1541 zebra_ptm_show_status(vty, NULL, ifp);
d62a17ae 1542
a36898e7 1543 vrf = vrf_lookup_by_id(ifp->vrf_id);
d62a17ae 1544 vty_out(vty, " vrf: %s\n", vrf->name);
1545
1546 if (ifp->desc)
1547 vty_out(vty, " Description: %s\n", ifp->desc);
ba5165ec
DS
1548 if (zebra_if->desc)
1549 vty_out(vty, " OS Description: %s\n", zebra_if->desc);
1550
d62a17ae 1551 if (ifp->ifindex == IFINDEX_INTERNAL) {
1552 vty_out(vty, " pseudo interface\n");
1553 return;
1554 } else if (!CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE)) {
1555 vty_out(vty, " index %d inactive interface\n", ifp->ifindex);
1556 return;
1557 }
1558
1559 vty_out(vty, " index %d metric %d mtu %d speed %u ", ifp->ifindex,
1560 ifp->metric, ifp->mtu, ifp->speed);
1561 if (ifp->mtu6 != ifp->mtu)
1562 vty_out(vty, "mtu6 %d ", ifp->mtu6);
1563 vty_out(vty, "\n flags: %s\n", if_flag_dump(ifp->flags));
1564
1565 /* Hardware address. */
1566 vty_out(vty, " Type: %s\n", if_link_type_str(ifp->ll_type));
1567 if (ifp->hw_addr_len != 0) {
1568 int i;
1569
1570 vty_out(vty, " HWaddr: ");
1571 for (i = 0; i < ifp->hw_addr_len; i++)
1572 vty_out(vty, "%s%02x", i == 0 ? "" : ":",
1573 ifp->hw_addr[i]);
1574 vty_out(vty, "\n");
1575 }
1576
1577 /* Bandwidth in Mbps */
1578 if (ifp->bandwidth != 0) {
1579 vty_out(vty, " bandwidth %u Mbps", ifp->bandwidth);
1580 vty_out(vty, "\n");
1581 }
1582
1583 for (rn = route_top(zebra_if->ipv4_subnets); rn; rn = route_next(rn)) {
1584 if (!rn->info)
1585 continue;
1586
1587 for (ALL_LIST_ELEMENTS_RO((struct list *)rn->info, node,
1588 connected))
c15dc24f 1589 connected_dump_vty(vty, NULL, connected);
d62a17ae 1590 }
1591
1592 for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, connected)) {
1593 if (CHECK_FLAG(connected->conf, ZEBRA_IFC_REAL)
1594 && (connected->address->family == AF_INET6))
c15dc24f 1595 connected_dump_vty(vty, NULL, connected);
d62a17ae 1596 }
1597
1598 vty_out(vty, " Interface Type %s\n",
1599 zebra_ziftype_2str(zebra_if->zif_type));
d0738ba2
PG
1600 vty_out(vty, " Interface Slave Type %s\n",
1601 zebra_zifslavetype_2str(zebra_if->zif_slave_type));
1602
d62a17ae 1603 if (IS_ZEBRA_IF_BRIDGE(ifp)) {
1604 struct zebra_l2info_bridge *bridge_info;
1605
1606 bridge_info = &zebra_if->l2info.br;
1607 vty_out(vty, " Bridge VLAN-aware: %s\n",
1608 bridge_info->vlan_aware ? "yes" : "no");
1609 } else if (IS_ZEBRA_IF_VLAN(ifp)) {
1610 struct zebra_l2info_vlan *vlan_info;
1611
1612 vlan_info = &zebra_if->l2info.vl;
1613 vty_out(vty, " VLAN Id %u\n", vlan_info->vid);
1614 } else if (IS_ZEBRA_IF_VXLAN(ifp)) {
1615 struct zebra_l2info_vxlan *vxlan_info;
1616
1617 vxlan_info = &zebra_if->l2info.vxl;
1618 vty_out(vty, " VxLAN Id %u", vxlan_info->vni);
1619 if (vxlan_info->vtep_ip.s_addr != INADDR_ANY)
9bcef951
MS
1620 vty_out(vty, " VTEP IP: %pI4",
1621 &vxlan_info->vtep_ip);
d62a17ae 1622 if (vxlan_info->access_vlan)
aa0677b4 1623 vty_out(vty, " Access VLAN Id %u\n",
d62a17ae 1624 vxlan_info->access_vlan);
d7fe235c 1625 if (vxlan_info->mcast_grp.s_addr != INADDR_ANY)
9bcef951
MS
1626 vty_out(vty, " Mcast Group %pI4",
1627 &vxlan_info->mcast_grp);
14ddb3d9
PG
1628 if (vxlan_info->ifindex_link &&
1629 (vxlan_info->link_nsid != NS_UNKNOWN)) {
1630 struct interface *ifp;
1631
1632 ifp = if_lookup_by_index_per_ns(
1633 zebra_ns_lookup(vxlan_info->link_nsid),
1634 vxlan_info->ifindex_link);
1635 vty_out(vty, " Link Interface %s",
1636 ifp == NULL ? "Unknown" :
1637 ifp->name);
1638 }
d62a17ae 1639 vty_out(vty, "\n");
077c07cc
PG
1640 } else if (IS_ZEBRA_IF_GRE(ifp)) {
1641 struct zebra_l2info_gre *gre_info;
1642
1643 gre_info = &zebra_if->l2info.gre;
1644 if (gre_info->vtep_ip.s_addr != INADDR_ANY) {
1645 vty_out(vty, " VTEP IP: %pI4", &gre_info->vtep_ip);
1646 if (gre_info->vtep_ip_remote.s_addr != INADDR_ANY)
1647 vty_out(vty, " , remote %pI4",
1648 &gre_info->vtep_ip_remote);
1649 vty_out(vty, "\n");
1650 }
1651 if (gre_info->ifindex_link &&
1652 (gre_info->link_nsid != NS_UNKNOWN)) {
1653 struct interface *ifp;
1654
1655 ifp = if_lookup_by_index_per_ns(
1656 zebra_ns_lookup(gre_info->link_nsid),
1657 gre_info->ifindex_link);
1658 vty_out(vty, " Link Interface %s\n",
1659 ifp == NULL ? "Unknown" :
1660 ifp->name);
1661 }
d62a17ae 1662 }
1663
1664 if (IS_ZEBRA_IF_BRIDGE_SLAVE(ifp)) {
1665 struct zebra_l2info_brslave *br_slave;
1666
1667 br_slave = &zebra_if->brslave_info;
eb4a93fb
DD
1668 if (br_slave->bridge_ifindex != IFINDEX_INTERNAL) {
1669 if (br_slave->br_if)
1670 vty_out(vty, " Master interface: %s\n",
1671 br_slave->br_if->name);
1672 else
1673 vty_out(vty, " Master ifindex: %u\n",
1674 br_slave->bridge_ifindex);
1675 }
d62a17ae 1676 }
1677
b9368db9
DD
1678 if (IS_ZEBRA_IF_BOND_SLAVE(ifp)) {
1679 struct zebra_l2info_bondslave *bond_slave;
1680
1681 bond_slave = &zebra_if->bondslave_info;
eb4a93fb
DD
1682 if (bond_slave->bond_ifindex != IFINDEX_INTERNAL) {
1683 if (bond_slave->bond_if)
1684 vty_out(vty, " Master interface: %s\n",
1685 bond_slave->bond_if->name);
1686 else
1687 vty_out(vty, " Master ifindex: %u\n",
1688 bond_slave->bond_ifindex);
1689 }
b9368db9
DD
1690 }
1691
00a7710c
AK
1692 if (zebra_if->flags & ZIF_FLAG_LACP_BYPASS)
1693 vty_out(vty, " LACP bypass: on\n");
1694
c15dc24f 1695 zebra_evpn_if_es_print(vty, NULL, zebra_if);
26ba45e3
AK
1696 vty_out(vty, " protodown: %s %s\n",
1697 (zebra_if->flags & ZIF_FLAG_PROTODOWN) ? "on" : "off",
1698 if_is_protodown_applicable(ifp) ? "" : "(n/a)");
c36e442c 1699 if (zebra_if->protodown_rc)
26ba45e3 1700 vty_out(vty, " protodown reasons: %s\n",
c36e442c
AK
1701 zebra_protodown_rc_str(zebra_if->protodown_rc, pd_buf,
1702 sizeof(pd_buf)));
ce5160c0 1703
8cb73ba4 1704 if (zebra_if->link_ifindex != IFINDEX_INTERNAL) {
8cb73ba4 1705 if (zebra_if->link)
eb4a93fb 1706 vty_out(vty, " Parent interface: %s\n", zebra_if->link->name);
8cb73ba4 1707 else
eb4a93fb 1708 vty_out(vty, " Parent ifindex: %d\n", zebra_if->link_ifindex);
8cb73ba4 1709 }
d62a17ae 1710
1711 if (HAS_LINK_PARAMS(ifp)) {
1712 int i;
1713 struct if_link_params *iflp = ifp->link_params;
1714 vty_out(vty, " Traffic Engineering Link Parameters:\n");
1715 if (IS_PARAM_SET(iflp, LP_TE_METRIC))
1716 vty_out(vty, " TE metric %u\n", iflp->te_metric);
1717 if (IS_PARAM_SET(iflp, LP_MAX_BW))
1718 vty_out(vty, " Maximum Bandwidth %g (Byte/s)\n",
1719 iflp->max_bw);
1720 if (IS_PARAM_SET(iflp, LP_MAX_RSV_BW))
1721 vty_out(vty,
1722 " Maximum Reservable Bandwidth %g (Byte/s)\n",
1723 iflp->max_rsv_bw);
1724 if (IS_PARAM_SET(iflp, LP_UNRSV_BW)) {
1725 vty_out(vty,
1726 " Unreserved Bandwidth per Class Type in Byte/s:\n");
1727 for (i = 0; i < MAX_CLASS_TYPE; i += 2)
1728 vty_out(vty,
1729 " [%d]: %g (Bytes/sec),\t[%d]: %g (Bytes/sec)\n",
1730 i, iflp->unrsv_bw[i], i + 1,
1731 iflp->unrsv_bw[i + 1]);
1732 }
1733
1734 if (IS_PARAM_SET(iflp, LP_ADM_GRP))
1735 vty_out(vty, " Administrative Group:%u\n",
1736 iflp->admin_grp);
1737 if (IS_PARAM_SET(iflp, LP_DELAY)) {
1738 vty_out(vty, " Link Delay Average: %u (micro-sec.)",
1739 iflp->av_delay);
1740 if (IS_PARAM_SET(iflp, LP_MM_DELAY)) {
1741 vty_out(vty, " Min: %u (micro-sec.)",
1742 iflp->min_delay);
1743 vty_out(vty, " Max: %u (micro-sec.)",
1744 iflp->max_delay);
1745 }
1746 vty_out(vty, "\n");
1747 }
1748 if (IS_PARAM_SET(iflp, LP_DELAY_VAR))
1749 vty_out(vty,
1750 " Link Delay Variation %u (micro-sec.)\n",
1751 iflp->delay_var);
1752 if (IS_PARAM_SET(iflp, LP_PKT_LOSS))
1753 vty_out(vty, " Link Packet Loss %g (in %%)\n",
1754 iflp->pkt_loss);
1755 if (IS_PARAM_SET(iflp, LP_AVA_BW))
1756 vty_out(vty, " Available Bandwidth %g (Byte/s)\n",
1757 iflp->ava_bw);
1758 if (IS_PARAM_SET(iflp, LP_RES_BW))
1759 vty_out(vty, " Residual Bandwidth %g (Byte/s)\n",
1760 iflp->res_bw);
1761 if (IS_PARAM_SET(iflp, LP_USE_BW))
1762 vty_out(vty, " Utilized Bandwidth %g (Byte/s)\n",
1763 iflp->use_bw);
1764 if (IS_PARAM_SET(iflp, LP_RMT_AS))
9bcef951
MS
1765 vty_out(vty, " Neighbor ASBR IP: %pI4 AS: %u \n",
1766 &iflp->rmt_ip, iflp->rmt_as);
d62a17ae 1767 }
1768
2eb27eec
DL
1769 hook_call(zebra_if_extra_info, vty, ifp);
1770
d62a17ae 1771 if (listhead(ifp->nbr_connected))
1772 vty_out(vty, " Neighbor address(s):\n");
1773 for (ALL_LIST_ELEMENTS_RO(ifp->nbr_connected, node, nbr_connected))
c15dc24f 1774 nbr_connected_dump_vty(vty, NULL, nbr_connected);
718e3744 1775
1776#ifdef HAVE_PROC_NET_DEV
d62a17ae 1777 /* Statistics print out using proc file system. */
1778 vty_out(vty,
3efd0893 1779 " %lu input packets (%lu multicast), %lu bytes, %lu dropped\n",
d62a17ae 1780 ifp->stats.rx_packets, ifp->stats.rx_multicast,
1781 ifp->stats.rx_bytes, ifp->stats.rx_dropped);
1782
1783 vty_out(vty,
3efd0893 1784 " %lu input errors, %lu length, %lu overrun, %lu CRC, %lu frame\n",
d62a17ae 1785 ifp->stats.rx_errors, ifp->stats.rx_length_errors,
1786 ifp->stats.rx_over_errors, ifp->stats.rx_crc_errors,
1787 ifp->stats.rx_frame_errors);
1788
1789 vty_out(vty, " %lu fifo, %lu missed\n", ifp->stats.rx_fifo_errors,
1790 ifp->stats.rx_missed_errors);
1791
1792 vty_out(vty, " %lu output packets, %lu bytes, %lu dropped\n",
1793 ifp->stats.tx_packets, ifp->stats.tx_bytes,
1794 ifp->stats.tx_dropped);
1795
1796 vty_out(vty,
3efd0893 1797 " %lu output errors, %lu aborted, %lu carrier, %lu fifo, %lu heartbeat\n",
d62a17ae 1798 ifp->stats.tx_errors, ifp->stats.tx_aborted_errors,
1799 ifp->stats.tx_carrier_errors, ifp->stats.tx_fifo_errors,
1800 ifp->stats.tx_heartbeat_errors);
1801
1802 vty_out(vty, " %lu window, %lu collisions\n",
1803 ifp->stats.tx_window_errors, ifp->stats.collisions);
718e3744 1804#endif /* HAVE_PROC_NET_DEV */
1805
1806#ifdef HAVE_NET_RT_IFLIST
d62a17ae 1807 /* Statistics print out using sysctl (). */
1808 vty_out(vty,
3efd0893 1809 " input packets %llu, bytes %llu, dropped %llu, multicast packets %llu\n",
d62a17ae 1810 (unsigned long long)ifp->stats.ifi_ipackets,
1811 (unsigned long long)ifp->stats.ifi_ibytes,
1812 (unsigned long long)ifp->stats.ifi_iqdrops,
1813 (unsigned long long)ifp->stats.ifi_imcasts);
1814
1815 vty_out(vty, " input errors %llu\n",
1816 (unsigned long long)ifp->stats.ifi_ierrors);
1817
1818 vty_out(vty,
3efd0893 1819 " output packets %llu, bytes %llu, multicast packets %llu\n",
d62a17ae 1820 (unsigned long long)ifp->stats.ifi_opackets,
1821 (unsigned long long)ifp->stats.ifi_obytes,
1822 (unsigned long long)ifp->stats.ifi_omcasts);
1823
1824 vty_out(vty, " output errors %llu\n",
1825 (unsigned long long)ifp->stats.ifi_oerrors);
1826
1827 vty_out(vty, " collisions %llu\n",
1828 (unsigned long long)ifp->stats.ifi_collisions);
718e3744 1829#endif /* HAVE_NET_RT_IFLIST */
1830}
1831
c15dc24f
RW
1832static void if_dump_vty_json(struct vty *vty, struct interface *ifp,
1833 json_object *json)
1834{
1835 struct connected *connected;
1836 struct nbr_connected *nbr_connected;
1837 struct listnode *node;
1838 struct route_node *rn;
1839 struct zebra_if *zebra_if;
1840 struct vrf *vrf;
1841 char pd_buf[ZEBRA_PROTODOWN_RC_STR_LEN];
1842 char buf[BUFSIZ];
1843 json_object *json_if;
1844 json_object *json_addrs;
1845
1846 json_if = json_object_new_object();
1847 json_object_object_add(json, ifp->name, json_if);
1848
1849 if (if_is_up(ifp)) {
1850 json_object_string_add(json_if, "administrativeStatus", "up");
1851
1852 if (CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_LINKDETECTION)) {
1853 json_object_string_add(json_if, "operationalStatus",
1854 if_is_running(ifp) ? "up"
1855 : "down");
1856 json_object_boolean_add(json_if, "linkDetection", true);
1857 } else {
1858 json_object_boolean_add(json_if, "linkDetection",
1859 false);
1860 }
1861 } else {
1862 json_object_string_add(json_if, "administrativeStatus", "down");
1863 }
1864
1865 zebra_if = ifp->info;
1866
1867 json_object_int_add(json_if, "linkUps", zebra_if->up_count);
1868 json_object_int_add(json_if, "linkDowns", zebra_if->down_count);
1869 if (zebra_if->up_last[0])
1870 json_object_string_add(json_if, "lastLinkUp",
1871 zebra_if->up_last);
1872 if (zebra_if->down_last[0])
1873 json_object_string_add(json_if, "lastLinkDown",
1874 zebra_if->down_last);
1875
1876 zebra_ptm_show_status(vty, json, ifp);
1877
1878 vrf = vrf_lookup_by_id(ifp->vrf_id);
1879 json_object_string_add(json_if, "vrfName", vrf->name);
1880
1881 if (ifp->desc)
1882 json_object_string_add(json_if, "description", ifp->desc);
1883 if (zebra_if->desc)
1884 json_object_string_add(json_if, "OsDescription",
1885 zebra_if->desc);
1886
1887 if (ifp->ifindex == IFINDEX_INTERNAL) {
1888 json_object_boolean_add(json_if, "pseudoInterface", true);
1889 return;
1890 } else if (!CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE)) {
1891 json_object_int_add(json_if, "index", ifp->ifindex);
1892 return;
1893 }
1894
1895 json_object_boolean_add(json_if, "pseudoInterface", false);
1896 json_object_int_add(json_if, "index", ifp->ifindex);
1897 json_object_int_add(json_if, "metric", ifp->metric);
1898 json_object_int_add(json_if, "mtu", ifp->mtu);
1899 if (ifp->mtu6 != ifp->mtu)
1900 json_object_int_add(json_if, "mtu6", ifp->mtu6);
1901 json_object_int_add(json_if, "speed", ifp->speed);
1902 json_object_string_add(json_if, "flags", if_flag_dump(ifp->flags));
1903
1904 /* Hardware address. */
1905 json_object_string_add(json_if, "type", if_link_type_str(ifp->ll_type));
1906 if (ifp->hw_addr_len != 0) {
1907 char hwbuf[BUFSIZ];
1908
1909 hwbuf[0] = '\0';
1910 for (int i = 0; i < ifp->hw_addr_len; i++) {
1911 snprintf(buf, sizeof(buf), "%s%02x", i == 0 ? "" : ":",
1912 ifp->hw_addr[i]);
1913 strlcat(hwbuf, buf, sizeof(hwbuf));
1914 }
1915 json_object_string_add(json_if, "hardwareAddress", hwbuf);
1916 }
1917
1918 /* Bandwidth in Mbps */
1919 if (ifp->bandwidth != 0)
1920 json_object_int_add(json_if, "bandwidth", ifp->bandwidth);
1921
1922
1923 /* IP addresses. */
1924 json_addrs = json_object_new_array();
1925 json_object_object_add(json_if, "ipAddresses", json_addrs);
1926
1927 for (rn = route_top(zebra_if->ipv4_subnets); rn; rn = route_next(rn)) {
1928 if (!rn->info)
1929 continue;
1930
1931 for (ALL_LIST_ELEMENTS_RO((struct list *)rn->info, node,
1932 connected))
1933 connected_dump_vty(vty, json_addrs, connected);
1934 }
1935
1936 for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, connected)) {
1937 if (CHECK_FLAG(connected->conf, ZEBRA_IFC_REAL)
1938 && (connected->address->family == AF_INET6))
1939 connected_dump_vty(vty, json_addrs, connected);
1940 }
1941
1942 json_object_string_add(json_if, "interfaceType",
1943 zebra_ziftype_2str(zebra_if->zif_type));
1944 json_object_string_add(
1945 json_if, "interfaceSlaveType",
1946 zebra_zifslavetype_2str(zebra_if->zif_slave_type));
1947
1948 if (IS_ZEBRA_IF_BRIDGE(ifp)) {
1949 struct zebra_l2info_bridge *bridge_info;
1950
1951 bridge_info = &zebra_if->l2info.br;
1952 json_object_boolean_add(json_if, "bridgeVlanAware",
1953 bridge_info->vlan_aware);
1954 } else if (IS_ZEBRA_IF_VLAN(ifp)) {
1955 struct zebra_l2info_vlan *vlan_info;
1956
1957 vlan_info = &zebra_if->l2info.vl;
1958 json_object_int_add(json_if, "vlanId", vlan_info->vid);
1959 } else if (IS_ZEBRA_IF_VXLAN(ifp)) {
1960 struct zebra_l2info_vxlan *vxlan_info;
1961
1962 vxlan_info = &zebra_if->l2info.vxl;
1963 json_object_int_add(json_if, "vxlanId", vxlan_info->vni);
1964 if (vxlan_info->vtep_ip.s_addr != INADDR_ANY)
1965 json_object_string_add(json_if, "vtepIp",
1966 inet_ntop(AF_INET,
1967 &vxlan_info->vtep_ip,
1968 buf, sizeof(buf)));
1969 if (vxlan_info->access_vlan)
1970 json_object_int_add(json_if, "accessVlanId",
1971 vxlan_info->access_vlan);
1972 if (vxlan_info->mcast_grp.s_addr != INADDR_ANY)
1973 json_object_string_add(json_if, "mcastGroup",
1974 inet_ntop(AF_INET,
1975 &vxlan_info->mcast_grp,
1976 buf, sizeof(buf)));
1977 if (vxlan_info->ifindex_link
1978 && (vxlan_info->link_nsid != NS_UNKNOWN)) {
1979 struct interface *ifp;
1980
1981 ifp = if_lookup_by_index_per_ns(
1982 zebra_ns_lookup(vxlan_info->link_nsid),
1983 vxlan_info->ifindex_link);
1984 json_object_string_add(json_if, "linkInterface",
1985 ifp == NULL ? "Unknown"
1986 : ifp->name);
1987 }
1988 } else if (IS_ZEBRA_IF_GRE(ifp)) {
1989 struct zebra_l2info_gre *gre_info;
1990
1991 gre_info = &zebra_if->l2info.gre;
1992 if (gre_info->vtep_ip.s_addr != INADDR_ANY) {
1993 json_object_string_add(json_if, "vtepIp",
1994 inet_ntop(AF_INET,
1995 &gre_info->vtep_ip,
1996 buf, sizeof(buf)));
1997 if (gre_info->vtep_ip_remote.s_addr != INADDR_ANY)
1998 json_object_string_add(
1999 json_if, "vtepRemoteIp",
2000 inet_ntop(AF_INET,
2001 &gre_info->vtep_ip_remote,
2002 buf, sizeof(buf)));
2003 }
2004 if (gre_info->ifindex_link
2005 && (gre_info->link_nsid != NS_UNKNOWN)) {
2006 struct interface *ifp;
2007
2008 ifp = if_lookup_by_index_per_ns(
2009 zebra_ns_lookup(gre_info->link_nsid),
2010 gre_info->ifindex_link);
2011 json_object_string_add(json_if, "linkInterface",
2012 ifp == NULL ? "Unknown"
2013 : ifp->name);
2014 }
2015 }
2016
2017 if (IS_ZEBRA_IF_BRIDGE_SLAVE(ifp)) {
2018 struct zebra_l2info_brslave *br_slave;
2019
2020 br_slave = &zebra_if->brslave_info;
2021 if (br_slave->bridge_ifindex != IFINDEX_INTERNAL) {
2022 if (br_slave->br_if)
2023 json_object_string_add(json_if,
2024 "masterInterface",
2025 br_slave->br_if->name);
2026 else
2027 json_object_int_add(json_if, "masterIfindex",
2028 br_slave->bridge_ifindex);
2029 }
2030 }
2031
2032 if (IS_ZEBRA_IF_BOND_SLAVE(ifp)) {
2033 struct zebra_l2info_bondslave *bond_slave;
2034
2035 bond_slave = &zebra_if->bondslave_info;
2036 if (bond_slave->bond_ifindex != IFINDEX_INTERNAL) {
2037 if (bond_slave->bond_if)
2038 json_object_string_add(
2039 json_if, "masterInterface",
2040 bond_slave->bond_if->name);
2041 else
2042 json_object_int_add(json_if, "masterIfindex",
2043 bond_slave->bond_ifindex);
2044 }
2045 }
2046
2047 json_object_boolean_add(
2048 json_if, "lacpBypass",
2049 CHECK_FLAG(zebra_if->flags, ZIF_FLAG_LACP_BYPASS));
2050
2051 zebra_evpn_if_es_print(vty, json_if, zebra_if);
2052
2053 if (if_is_protodown_applicable(ifp)) {
2054 json_object_string_add(
2055 json_if, "protodown",
2056 (zebra_if->flags & ZIF_FLAG_PROTODOWN) ? "on" : "off");
2057 if (zebra_if->protodown_rc)
2058 json_object_string_add(
2059 json_if, "protodownReason",
2060 zebra_protodown_rc_str(zebra_if->protodown_rc,
2061 pd_buf, sizeof(pd_buf)));
2062 }
2063
2064 if (zebra_if->link_ifindex != IFINDEX_INTERNAL) {
2065 if (zebra_if->link)
2066 json_object_string_add(json_if, "parentInterface",
2067 zebra_if->link->name);
2068 else
2069 json_object_int_add(json_if, "parentIfindex",
2070 zebra_if->link_ifindex);
2071 }
2072
2073 if (HAS_LINK_PARAMS(ifp)) {
2074 struct if_link_params *iflp = ifp->link_params;
2075 json_object *json_te;
2076
2077 json_te = json_object_new_object();
2078 json_object_object_add(
2079 json_if, "trafficEngineeringLinkParameters", json_te);
2080
2081 if (IS_PARAM_SET(iflp, LP_TE_METRIC))
2082 json_object_int_add(json_te, "teMetric",
2083 iflp->te_metric);
2084 if (IS_PARAM_SET(iflp, LP_MAX_BW))
2085 json_object_double_add(json_te, "maximumBandwidth",
2086 iflp->max_bw);
2087 if (IS_PARAM_SET(iflp, LP_MAX_RSV_BW))
2088 json_object_double_add(json_te,
2089 "maximumReservableBandwidth",
2090 iflp->max_rsv_bw);
2091 if (IS_PARAM_SET(iflp, LP_UNRSV_BW)) {
2092 json_object *json_bws;
2093
2094 json_bws = json_object_new_object();
2095 json_object_object_add(json_te, "unreservedBandwidth",
2096 json_bws);
2097 for (unsigned int i = 0; i < MAX_CLASS_TYPE; ++i) {
2098 char buf_ct[64];
2099
2100 snprintf(buf_ct, sizeof(buf_ct), "classType%u",
2101 i);
2102 json_object_double_add(json_bws, buf_ct,
2103 iflp->unrsv_bw[i]);
2104 }
2105 }
2106
2107 if (IS_PARAM_SET(iflp, LP_ADM_GRP))
2108 json_object_int_add(json_te, "administrativeGroup",
2109 iflp->admin_grp);
2110 if (IS_PARAM_SET(iflp, LP_DELAY)) {
2111 json_object_int_add(json_te, "linkDelayAverage",
2112 iflp->av_delay);
2113 if (IS_PARAM_SET(iflp, LP_MM_DELAY)) {
2114 json_object_int_add(json_te, "linkDelayMinimum",
2115 iflp->min_delay);
2116 json_object_int_add(json_te, "linkDelayMaximum",
2117 iflp->max_delay);
2118 }
2119 }
2120 if (IS_PARAM_SET(iflp, LP_DELAY_VAR))
2121 json_object_int_add(json_te, "linkDelayVariation",
2122 iflp->delay_var);
2123 if (IS_PARAM_SET(iflp, LP_PKT_LOSS))
2124 json_object_double_add(json_te, "linkPacketLoss",
2125 iflp->pkt_loss);
2126 if (IS_PARAM_SET(iflp, LP_AVA_BW))
2127 json_object_double_add(json_te, "availableBandwidth",
2128 iflp->ava_bw);
2129 if (IS_PARAM_SET(iflp, LP_RES_BW))
2130 json_object_double_add(json_te, "residualBandwidth",
2131 iflp->res_bw);
2132 if (IS_PARAM_SET(iflp, LP_USE_BW))
2133 json_object_double_add(json_te, "utilizedBandwidth",
2134 iflp->use_bw);
2135 if (IS_PARAM_SET(iflp, LP_RMT_AS))
2136 json_object_string_add(json_te, "neighborAsbrIp",
2137 inet_ntop(AF_INET, &iflp->rmt_ip,
2138 buf, sizeof(buf)));
2139 json_object_int_add(json_te, "neighborAsbrAs", iflp->rmt_as);
2140 }
2141
2142 if (listhead(ifp->nbr_connected)) {
2143 json_object *json_nbr_addrs;
2144
2145 json_nbr_addrs = json_object_new_array();
2146 json_object_object_add(json_if, "neighborIpAddresses",
2147 json_nbr_addrs);
2148
2149 for (ALL_LIST_ELEMENTS_RO(ifp->nbr_connected, node,
2150 nbr_connected))
2151 nbr_connected_dump_vty(vty, json_nbr_addrs,
2152 nbr_connected);
2153 }
2154
2155#ifdef HAVE_PROC_NET_DEV
2156 json_object_int_add(json_if, "inputPackets", stats.rx_packets);
2157 json_object_int_add(json_if, "inputBytes", ifp->stats.rx_bytes);
2158 json_object_int_add(json_if, "inputDropped", ifp->stats.rx_dropped);
2159 json_object_int_add(json_if, "inputMulticastPackets",
2160 ifp->stats.rx_multicast);
2161 json_object_int_add(json_if, "inputErrors", ifp->stats.rx_errors);
2162 json_object_int_add(json_if, "inputLengthErrors",
2163 ifp->stats.rx_length_errors);
2164 json_object_int_add(json_if, "inputOverrunErrors",
2165 ifp->stats.rx_over_errors);
2166 json_object_int_add(json_if, "inputCrcErrors",
2167 ifp->stats.rx_crc_errors);
2168 json_object_int_add(json_if, "inputFrameErrors",
2169 ifp->stats.rx_frame_errors);
2170 json_object_int_add(json_if, "inputFifoErrors",
2171 ifp->stats.rx_fifo_errors);
2172 json_object_int_add(json_if, "inputMissedErrors",
2173 ifp->stats.rx_missed_errors);
2174 json_object_int_add(json_if, "outputPackets", ifp->stats.tx_packets);
2175 json_object_int_add(json_if, "outputBytes", ifp->stats.tx_bytes);
2176 json_object_int_add(json_if, "outputDroppedPackets",
2177 ifp->stats.tx_dropped);
2178 json_object_int_add(json_if, "outputErrors", ifp->stats.tx_errors);
2179 json_object_int_add(json_if, "outputAbortedErrors",
2180 ifp->stats.tx_aborted_errors);
2181 json_object_int_add(json_if, "outputCarrierErrors",
2182 ifp->stats.tx_carrier_errors);
2183 json_object_int_add(json_if, "outputFifoErrors",
2184 ifp->stats.tx_fifo_errors);
2185 json_object_int_add(json_if, "outputHeartbeatErrors",
2186 ifp->stats.tx_heartbeat_errors);
2187 json_object_int_add(json_if, "outputWindowErrors",
2188 ifp->stats.tx_window_errors);
2189 json_object_int_add(json_if, "collisions", ifp->stats.collisions);
2190#endif /* HAVE_PROC_NET_DEV */
2191
2192#ifdef HAVE_NET_RT_IFLIST
2193 json_object_int_add(json_if, "inputPackets", ifp->stats.ifi_ipackets);
2194 json_object_int_add(json_if, "inputBytes", ifp->stats.ifi_ibytes);
2195 json_object_int_add(json_if, "inputDropd", ifp->stats.ifi_iqdrops);
2196 json_object_int_add(json_if, "inputMulticastPackets",
2197 ifp->stats.ifi_imcasts);
2198 json_object_int_add(json_if, "inputErrors", ifp->stats.ifi_ierrors);
2199 json_object_int_add(json_if, "outputPackets", ifp->stats.ifi_opackets);
2200 json_object_int_add(json_if, "outputBytes", ifp->stats.ifi_obytes);
2201 json_object_int_add(json_if, "outputMulticastPackets",
2202 ifp->stats.ifi_omcasts);
2203 json_object_int_add(json_if, "outputErrors", ifp->stats.ifi_oerrors);
2204 json_object_int_add(json_if, "collisions", ifp->stats.ifi_collisions);
2205#endif /* HAVE_NET_RT_IFLIST */
2206}
2207
d62a17ae 2208static void interface_update_stats(void)
78860b9f
DS
2209{
2210#ifdef HAVE_PROC_NET_DEV
d62a17ae 2211 /* If system has interface statistics via proc file system, update
2212 statistics. */
2213 ifstat_update_proc();
78860b9f
DS
2214#endif /* HAVE_PROC_NET_DEV */
2215#ifdef HAVE_NET_RT_IFLIST
d62a17ae 2216 ifstat_update_sysctl();
78860b9f
DS
2217#endif /* HAVE_NET_RT_IFLIST */
2218}
2219
49548752
NS
2220#ifndef VTYSH_EXTRACT_PL
2221#include "zebra/interface_clippy.c"
2222#endif
8b87bdf4 2223/* Show all interfaces to vty. */
49548752 2224DEFPY(show_interface, show_interface_cmd,
c15dc24f 2225 "show interface vrf NAME$vrf_name [brief$brief] [json$uj]",
49548752
NS
2226 SHOW_STR
2227 "Interface status and configuration\n"
2228 VRF_CMD_HELP_STR
c15dc24f
RW
2229 "Interface status and configuration summary\n"
2230 JSON_STR)
8b87bdf4 2231{
a36898e7 2232 struct vrf *vrf;
d62a17ae 2233 struct interface *ifp;
c15dc24f 2234 json_object *json = NULL;
8b87bdf4 2235
d62a17ae 2236 interface_update_stats();
8b87bdf4 2237
a2719d0e
IR
2238 vrf = vrf_lookup_by_name(vrf_name);
2239 if (!vrf) {
c15dc24f
RW
2240 if (uj)
2241 vty_out(vty, "{}\n");
2242 else
2243 vty_out(vty, "%% VRF %s not found\n", vrf_name);
a2719d0e
IR
2244 return CMD_WARNING;
2245 }
8b87bdf4 2246
c15dc24f
RW
2247 if (uj)
2248 json = json_object_new_object();
2249
49548752 2250 if (brief) {
c15dc24f
RW
2251 if (json)
2252 ifs_dump_brief_vty_json(json, vrf);
2253 else
2254 ifs_dump_brief_vty(vty, vrf);
49548752
NS
2255 } else {
2256 FOR_ALL_INTERFACES (vrf, ifp) {
c15dc24f
RW
2257 if (json)
2258 if_dump_vty_json(vty, ifp, json);
2259 else
2260 if_dump_vty(vty, ifp);
49548752
NS
2261 }
2262 }
8b87bdf4 2263
c15dc24f
RW
2264 if (json) {
2265 vty_out(vty, "%s\n",
2266 json_object_to_json_string_ext(
2267 json, JSON_C_TO_STRING_PRETTY));
2268 json_object_free(json);
2269 }
2270
d62a17ae 2271 return CMD_SUCCESS;
8b87bdf4
FL
2272}
2273
8b87bdf4
FL
2274
2275/* Show all interfaces to vty. */
a5c7809c 2276DEFPY (show_interface_vrf_all,
8b3f0677 2277 show_interface_vrf_all_cmd,
c15dc24f 2278 "show interface [vrf all] [brief$brief] [json$uj]",
8b87bdf4
FL
2279 SHOW_STR
2280 "Interface status and configuration\n"
a5c7809c 2281 VRF_ALL_CMD_HELP_STR
c15dc24f
RW
2282 "Interface status and configuration summary\n"
2283 JSON_STR)
718e3744 2284{
d62a17ae 2285 struct vrf *vrf;
d62a17ae 2286 struct interface *ifp;
c15dc24f 2287 json_object *json = NULL;
8b87bdf4 2288
d62a17ae 2289 interface_update_stats();
718e3744 2290
c15dc24f
RW
2291 if (uj)
2292 json = json_object_new_object();
2293
d62a17ae 2294 /* All interface print. */
a5c7809c
DS
2295 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
2296 if (brief) {
c15dc24f
RW
2297 if (json)
2298 ifs_dump_brief_vty_json(json, vrf);
2299 else
2300 ifs_dump_brief_vty(vty, vrf);
a5c7809c 2301 } else {
c15dc24f
RW
2302 FOR_ALL_INTERFACES (vrf, ifp) {
2303 if (json)
2304 if_dump_vty_json(vty, ifp, json);
2305 else
2306 if_dump_vty(vty, ifp);
2307 }
a5c7809c
DS
2308 }
2309 }
8b87bdf4 2310
c15dc24f
RW
2311 if (json) {
2312 vty_out(vty, "%s\n",
2313 json_object_to_json_string_ext(
2314 json, JSON_C_TO_STRING_PRETTY));
2315 json_object_free(json);
2316 }
2317
d62a17ae 2318 return CMD_SUCCESS;
8b87bdf4
FL
2319}
2320
2321/* Show specified interface to vty. */
1721646e 2322
c15dc24f 2323DEFPY (show_interface_name_vrf,
1721646e 2324 show_interface_name_vrf_cmd,
c15dc24f 2325 "show interface IFNAME$ifname vrf NAME$vrf_name [json$uj]",
8b87bdf4
FL
2326 SHOW_STR
2327 "Interface status and configuration\n"
1721646e 2328 "Interface name\n"
c15dc24f
RW
2329 VRF_CMD_HELP_STR
2330 JSON_STR)
8b87bdf4 2331{
d62a17ae 2332 struct interface *ifp;
a2719d0e 2333 struct vrf *vrf;
c15dc24f 2334 json_object *json = NULL;
8b87bdf4 2335
d62a17ae 2336 interface_update_stats();
8b87bdf4 2337
c15dc24f 2338 vrf = vrf_lookup_by_name(vrf_name);
a2719d0e 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 2347 ifp = if_lookup_by_name_vrf(ifname, vrf);
d62a17ae 2348 if (ifp == NULL) {
c15dc24f
RW
2349 if (uj)
2350 vty_out(vty, "{}\n");
2351 else
2352 vty_out(vty, "%% Can't find interface %s\n", ifname);
d62a17ae 2353 return CMD_WARNING;
2354 }
c15dc24f
RW
2355
2356 if (uj)
2357 json = json_object_new_object();
2358
2359 if (json)
2360 if_dump_vty_json(vty, ifp, json);
2361 else
2362 if_dump_vty(vty, ifp);
2363
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 }
718e3744 2370
d62a17ae 2371 return CMD_SUCCESS;
718e3744 2372}
2373
8b87bdf4 2374/* Show specified interface to vty. */
c15dc24f 2375DEFPY (show_interface_name_vrf_all,
8b3f0677 2376 show_interface_name_vrf_all_cmd,
c15dc24f 2377 "show interface IFNAME$ifname [vrf all] [json$uj]",
8b87bdf4
FL
2378 SHOW_STR
2379 "Interface status and configuration\n"
1721646e 2380 "Interface name\n"
c15dc24f
RW
2381 VRF_ALL_CMD_HELP_STR
2382 JSON_STR)
8b87bdf4 2383{
d62a17ae 2384 struct interface *ifp;
c15dc24f 2385 json_object *json = NULL;
8b87bdf4 2386
d62a17ae 2387 interface_update_stats();
8b87bdf4 2388
c15dc24f 2389 ifp = if_lookup_by_name_all_vrf(ifname);
a2719d0e 2390 if (ifp == NULL) {
c15dc24f
RW
2391 if (uj)
2392 vty_out(vty, "{}\n");
2393 else
2394 vty_out(vty, "%% Can't find interface %s\n", ifname);
d62a17ae 2395 return CMD_WARNING;
2396 }
c15dc24f
RW
2397
2398 if (uj)
2399 json = json_object_new_object();
2400
2401 if (json)
2402 if_dump_vty_json(vty, ifp, json);
2403 else
2404 if_dump_vty(vty, ifp);
2405
2406 if (json) {
2407 vty_out(vty, "%s\n",
2408 json_object_to_json_string_ext(
2409 json, JSON_C_TO_STRING_PRETTY));
2410 json_object_free(json);
2411 }
8b87bdf4 2412
d62a17ae 2413 return CMD_SUCCESS;
8b87bdf4
FL
2414}
2415
a2719d0e 2416static void if_show_description(struct vty *vty, struct vrf *vrf)
ed9bb6d5 2417{
d62a17ae 2418 struct interface *ifp;
ed9bb6d5 2419
d62a17ae 2420 vty_out(vty, "Interface Status Protocol Description\n");
451fda4f 2421 FOR_ALL_INTERFACES (vrf, ifp) {
d62a17ae 2422 int len;
ba5165ec
DS
2423 struct zebra_if *zif;
2424 bool intf_desc;
2425
2426 intf_desc = false;
ed9bb6d5 2427
d62a17ae 2428 len = vty_out(vty, "%s", ifp->name);
2429 vty_out(vty, "%*s", (16 - len), " ");
2430
2431 if (if_is_up(ifp)) {
2432 vty_out(vty, "up ");
2433 if (CHECK_FLAG(ifp->status,
2434 ZEBRA_INTERFACE_LINKDETECTION)) {
2435 if (if_is_running(ifp))
2436 vty_out(vty, "up ");
2437 else
2438 vty_out(vty, "down ");
2439 } else {
2440 vty_out(vty, "unknown ");
2441 }
2442 } else {
2443 vty_out(vty, "down down ");
2444 }
ed9bb6d5 2445
ba5165ec
DS
2446 if (ifp->desc) {
2447 intf_desc = true;
d62a17ae 2448 vty_out(vty, "%s", ifp->desc);
ba5165ec
DS
2449 }
2450 zif = ifp->info;
2451 if (zif && zif->desc) {
2452 vty_out(vty, "%s%s",
2453 intf_desc
2454 ? "\n "
2455 : "",
2456 zif->desc);
2457 }
2458
d62a17ae 2459 vty_out(vty, "\n");
2460 }
8b87bdf4
FL
2461}
2462
2463DEFUN (show_interface_desc,
2464 show_interface_desc_cmd,
a2719d0e 2465 "show interface description vrf NAME",
8b87bdf4
FL
2466 SHOW_STR
2467 "Interface status and configuration\n"
b62ecea5
QY
2468 "Interface description\n"
2469 VRF_CMD_HELP_STR)
8b87bdf4 2470{
a2719d0e 2471 struct vrf *vrf;
8b87bdf4 2472
a2719d0e
IR
2473 vrf = vrf_lookup_by_name(argv[4]->arg);
2474 if (!vrf) {
2475 vty_out(vty, "%% VRF %s not found\n", argv[4]->arg);
2476 return CMD_WARNING;
2477 }
8b87bdf4 2478
a2719d0e 2479 if_show_description(vty, vrf);
8b87bdf4 2480
d62a17ae 2481 return CMD_SUCCESS;
8b87bdf4
FL
2482}
2483
8b87bdf4
FL
2484
2485DEFUN (show_interface_desc_vrf_all,
2486 show_interface_desc_vrf_all_cmd,
a2719d0e 2487 "show interface description [vrf all]",
8b87bdf4
FL
2488 SHOW_STR
2489 "Interface status and configuration\n"
2490 "Interface description\n"
2491 VRF_ALL_CMD_HELP_STR)
2492{
d62a17ae 2493 struct vrf *vrf;
8b87bdf4 2494
a2addae8 2495 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name)
996c9314 2496 if (!RB_EMPTY(if_name_head, &vrf->ifaces_by_name)) {
c479e756
DS
2497 vty_out(vty, "\n\tVRF %s(%u)\n\n", VRF_LOGNAME(vrf),
2498 vrf->vrf_id);
a2719d0e 2499 if_show_description(vty, vrf);
a2addae8 2500 }
8b87bdf4 2501
d62a17ae 2502 return CMD_SUCCESS;
ed9bb6d5 2503}
2504
09268680
CS
2505int if_multicast_set(struct interface *ifp)
2506{
2507 struct zebra_if *if_data;
2508
2509 if (CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE)) {
2510 if (if_set_flags(ifp, IFF_MULTICAST) < 0) {
2511 zlog_debug("Can't set multicast flag on interface %s",
2512 ifp->name);
2513 return -1;
2514 }
2515 if_refresh(ifp);
2516 }
2517 if_data = ifp->info;
2518 if_data->multicast = IF_ZEBRA_MULTICAST_ON;
2519
2520 return 0;
2521}
2522
718e3744 2523DEFUN (multicast,
2524 multicast_cmd,
2525 "multicast",
2526 "Set multicast flag to interface\n")
2527{
d62a17ae 2528 VTY_DECLVAR_CONTEXT(interface, ifp);
2529 int ret;
2530 struct zebra_if *if_data;
718e3744 2531
d62a17ae 2532 if (CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE)) {
2533 ret = if_set_flags(ifp, IFF_MULTICAST);
2534 if (ret < 0) {
2535 vty_out(vty, "Can't set multicast flag\n");
2536 return CMD_WARNING_CONFIG_FAILED;
2537 }
2538 if_refresh(ifp);
48b33aaf 2539 }
d62a17ae 2540 if_data = ifp->info;
2541 if_data->multicast = IF_ZEBRA_MULTICAST_ON;
48b33aaf 2542
d62a17ae 2543 return CMD_SUCCESS;
718e3744 2544}
2545
09268680
CS
2546int if_multicast_unset(struct interface *ifp)
2547{
2548 struct zebra_if *if_data;
2549
2550 if (CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE)) {
2551 if (if_unset_flags(ifp, IFF_MULTICAST) < 0) {
2552 zlog_debug("Can't unset multicast flag on interface %s",
2553 ifp->name);
2554 return -1;
2555 }
2556 if_refresh(ifp);
2557 }
2558 if_data = ifp->info;
2559 if_data->multicast = IF_ZEBRA_MULTICAST_OFF;
2560
2561 return 0;
2562}
2563
718e3744 2564DEFUN (no_multicast,
2565 no_multicast_cmd,
2566 "no multicast",
2567 NO_STR
2568 "Unset multicast flag to interface\n")
2569{
d62a17ae 2570 VTY_DECLVAR_CONTEXT(interface, ifp);
2571 int ret;
2572 struct zebra_if *if_data;
718e3744 2573
d62a17ae 2574 if (CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE)) {
2575 ret = if_unset_flags(ifp, IFF_MULTICAST);
2576 if (ret < 0) {
2577 vty_out(vty, "Can't unset multicast flag\n");
2578 return CMD_WARNING_CONFIG_FAILED;
2579 }
2580 if_refresh(ifp);
48b33aaf 2581 }
d62a17ae 2582 if_data = ifp->info;
2583 if_data->multicast = IF_ZEBRA_MULTICAST_OFF;
718e3744 2584
d62a17ae 2585 return CMD_SUCCESS;
718e3744 2586}
2587
09268680 2588int if_linkdetect(struct interface *ifp, bool detect)
2e3b2e47 2589{
d62a17ae 2590 int if_was_operative;
2e3b2e47 2591
d62a17ae 2592 if_was_operative = if_is_no_ptm_operative(ifp);
09268680
CS
2593 if (detect) {
2594 SET_FLAG(ifp->status, ZEBRA_INTERFACE_LINKDETECTION);
2e3b2e47 2595
09268680
CS
2596 /* When linkdetection is enabled, if might come down */
2597 if (!if_is_no_ptm_operative(ifp) && if_was_operative)
2598 if_down(ifp);
2599 } else {
2600 UNSET_FLAG(ifp->status, ZEBRA_INTERFACE_LINKDETECTION);
2e3b2e47 2601
09268680
CS
2602 /* Interface may come up after disabling link detection */
2603 if (if_is_operative(ifp) && !if_was_operative)
2604 if_up(ifp);
2605 }
d62a17ae 2606 /* FIXME: Will defer status change forwarding if interface
2607 does not come down! */
09268680
CS
2608 return 0;
2609}
2610
2611DEFUN(linkdetect, linkdetect_cmd, "link-detect",
2612 "Enable link detection on interface\n")
2613{
2614 VTY_DECLVAR_CONTEXT(interface, ifp);
2615
2616 if_linkdetect(ifp, true);
d62a17ae 2617
2618 return CMD_SUCCESS;
2e3b2e47 2619}
2620
2621
2622DEFUN (no_linkdetect,
2623 no_linkdetect_cmd,
2624 "no link-detect",
2625 NO_STR
2626 "Disable link detection on interface\n")
2627{
d62a17ae 2628 VTY_DECLVAR_CONTEXT(interface, ifp);
d62a17ae 2629
09268680
CS
2630 if_linkdetect(ifp, false);
2631
2632 return CMD_SUCCESS;
2633}
2e3b2e47 2634
09268680
CS
2635int if_shutdown(struct interface *ifp)
2636{
2637 struct zebra_if *if_data;
2e3b2e47 2638
09268680
CS
2639 if (ifp->ifindex != IFINDEX_INTERNAL) {
2640 /* send RA lifetime of 0 before stopping. rfc4861/6.2.5 */
2641 rtadv_stop_ra(ifp);
2642 if (if_unset_flags(ifp, IFF_UP) < 0) {
2643 zlog_debug("Can't shutdown interface %s", ifp->name);
2644 return -1;
2645 }
2646 if_refresh(ifp);
2647 }
2648 if_data = ifp->info;
2649 if_data->shutdown = IF_ZEBRA_SHUTDOWN_ON;
2e3b2e47 2650
09268680 2651 return 0;
2e3b2e47 2652}
2653
718e3744 2654DEFUN (shutdown_if,
2655 shutdown_if_cmd,
2656 "shutdown",
2657 "Shutdown the selected interface\n")
2658{
d62a17ae 2659 VTY_DECLVAR_CONTEXT(interface, ifp);
2660 int ret;
2661 struct zebra_if *if_data;
718e3744 2662
d62a17ae 2663 if (ifp->ifindex != IFINDEX_INTERNAL) {
d7fc0e67
DS
2664 /* send RA lifetime of 0 before stopping. rfc4861/6.2.5 */
2665 rtadv_stop_ra(ifp);
d62a17ae 2666 ret = if_unset_flags(ifp, IFF_UP);
2667 if (ret < 0) {
2668 vty_out(vty, "Can't shutdown interface\n");
2669 return CMD_WARNING_CONFIG_FAILED;
2670 }
2671 if_refresh(ifp);
2672 }
2673 if_data = ifp->info;
2674 if_data->shutdown = IF_ZEBRA_SHUTDOWN_ON;
718e3744 2675
d62a17ae 2676 return CMD_SUCCESS;
718e3744 2677}
2678
09268680
CS
2679int if_no_shutdown(struct interface *ifp)
2680{
2681 struct zebra_if *if_data;
2682
2683 if (ifp->ifindex != IFINDEX_INTERNAL) {
2684 if (if_set_flags(ifp, IFF_UP | IFF_RUNNING) < 0) {
2685 zlog_debug("Can't up interface %s", ifp->name);
2686 return -1;
2687 }
2688 if_refresh(ifp);
2689
2690 /* Some addresses (in particular, IPv6 addresses on Linux) get
2691 * removed when the interface goes down. They need to be
2692 * readded.
2693 */
2694 if_addr_wakeup(ifp);
2695 }
2696
2697 if_data = ifp->info;
2698 if_data->shutdown = IF_ZEBRA_SHUTDOWN_OFF;
2699
2700 return 0;
2701}
2702
718e3744 2703DEFUN (no_shutdown_if,
2704 no_shutdown_if_cmd,
2705 "no shutdown",
2706 NO_STR
2707 "Shutdown the selected interface\n")
2708{
d62a17ae 2709 VTY_DECLVAR_CONTEXT(interface, ifp);
2710 int ret;
2711 struct zebra_if *if_data;
718e3744 2712
d62a17ae 2713 if (ifp->ifindex != IFINDEX_INTERNAL) {
2714 ret = if_set_flags(ifp, IFF_UP | IFF_RUNNING);
2715 if (ret < 0) {
2716 vty_out(vty, "Can't up interface\n");
2717 return CMD_WARNING_CONFIG_FAILED;
2718 }
2719 if_refresh(ifp);
bfac8dcd 2720
d62a17ae 2721 /* Some addresses (in particular, IPv6 addresses on Linux) get
2722 * removed when the interface goes down. They need to be
2723 * readded.
2724 */
2725 if_addr_wakeup(ifp);
2726 }
bfac8dcd 2727
d62a17ae 2728 if_data = ifp->info;
2729 if_data->shutdown = IF_ZEBRA_SHUTDOWN_OFF;
718e3744 2730
d62a17ae 2731 return CMD_SUCCESS;
718e3744 2732}
2733
2734DEFUN (bandwidth_if,
2735 bandwidth_if_cmd,
6147e2c6 2736 "bandwidth (1-100000)",
718e3744 2737 "Set bandwidth informational parameter\n"
70bd3c43 2738 "Bandwidth in megabits\n")
718e3744 2739{
d62a17ae 2740 int idx_number = 1;
2741 VTY_DECLVAR_CONTEXT(interface, ifp);
2742 unsigned int bandwidth;
2743
2744 bandwidth = strtol(argv[idx_number]->arg, NULL, 10);
2745
2746 /* bandwidth range is <1-100000> */
2747 if (bandwidth < 1 || bandwidth > 100000) {
2748 vty_out(vty, "Bandwidth is invalid\n");
2749 return CMD_WARNING_CONFIG_FAILED;
2750 }
2751
2752 ifp->bandwidth = bandwidth;
718e3744 2753
d62a17ae 2754 /* force protocols to recalculate routes due to cost change */
2755 if (if_is_operative(ifp))
2756 zebra_interface_up_update(ifp);
718e3744 2757
d62a17ae 2758 return CMD_SUCCESS;
718e3744 2759}
2760
2761DEFUN (no_bandwidth_if,
2762 no_bandwidth_if_cmd,
b62ecea5 2763 "no bandwidth [(1-100000)]",
718e3744 2764 NO_STR
b62ecea5
QY
2765 "Set bandwidth informational parameter\n"
2766 "Bandwidth in megabits\n")
718e3744 2767{
d62a17ae 2768 VTY_DECLVAR_CONTEXT(interface, ifp);
718e3744 2769
d62a17ae 2770 ifp->bandwidth = 0;
718e3744 2771
d62a17ae 2772 /* force protocols to recalculate routes due to cost change */
2773 if (if_is_operative(ifp))
2774 zebra_interface_up_update(ifp);
2775
2776 return CMD_SUCCESS;
718e3744 2777}
2778
6b0655a2 2779
d62a17ae 2780struct cmd_node link_params_node = {
f4b8291f 2781 .name = "link-params",
62b346ee 2782 .node = LINK_PARAMS_NODE,
24389580 2783 .parent_node = INTERFACE_NODE,
62b346ee 2784 .prompt = "%s(config-link-params)# ",
16f1b9ee
OD
2785};
2786
d62a17ae 2787static void link_param_cmd_set_uint32(struct interface *ifp, uint32_t *field,
2788 uint32_t type, uint32_t value)
16f1b9ee 2789{
d62a17ae 2790 /* Update field as needed */
2791 if (IS_PARAM_UNSET(ifp->link_params, type) || *field != value) {
2792 *field = value;
2793 SET_PARAM(ifp->link_params, type);
16f1b9ee 2794
d62a17ae 2795 /* force protocols to update LINK STATE due to parameters change
2796 */
2797 if (if_is_operative(ifp))
2798 zebra_interface_parameters_update(ifp);
2799 }
16f1b9ee 2800}
d62a17ae 2801static void link_param_cmd_set_float(struct interface *ifp, float *field,
2802 uint32_t type, float value)
16f1b9ee
OD
2803{
2804
d62a17ae 2805 /* Update field as needed */
2806 if (IS_PARAM_UNSET(ifp->link_params, type) || *field != value) {
2807 *field = value;
2808 SET_PARAM(ifp->link_params, type);
16f1b9ee 2809
d62a17ae 2810 /* force protocols to update LINK STATE due to parameters change
2811 */
2812 if (if_is_operative(ifp))
2813 zebra_interface_parameters_update(ifp);
2814 }
16f1b9ee
OD
2815}
2816
d62a17ae 2817static void link_param_cmd_unset(struct interface *ifp, uint32_t type)
16f1b9ee 2818{
d62a17ae 2819 if (ifp->link_params == NULL)
2820 return;
16f1b9ee 2821
d62a17ae 2822 /* Unset field */
2823 UNSET_PARAM(ifp->link_params, type);
16f1b9ee 2824
d62a17ae 2825 /* force protocols to update LINK STATE due to parameters change */
2826 if (if_is_operative(ifp))
2827 zebra_interface_parameters_update(ifp);
16f1b9ee
OD
2828}
2829
505e5056 2830DEFUN_NOSH (link_params,
16f1b9ee
OD
2831 link_params_cmd,
2832 "link-params",
2833 LINK_PARAMS_STR)
2834{
d62a17ae 2835 /* vty->qobj_index stays the same @ interface pointer */
2836 vty->node = LINK_PARAMS_NODE;
16f1b9ee 2837
d62a17ae 2838 return CMD_SUCCESS;
16f1b9ee
OD
2839}
2840
505e5056 2841DEFUN_NOSH (exit_link_params,
03f99d9a
DS
2842 exit_link_params_cmd,
2843 "exit-link-params",
2844 "Exit from Link Params configuration mode\n")
2845{
d62a17ae 2846 if (vty->node == LINK_PARAMS_NODE)
2847 vty->node = INTERFACE_NODE;
2848 return CMD_SUCCESS;
03f99d9a
DS
2849}
2850
16f1b9ee
OD
2851/* Specific Traffic Engineering parameters commands */
2852DEFUN (link_params_enable,
2853 link_params_enable_cmd,
2854 "enable",
2855 "Activate link parameters on this interface\n")
2856{
d62a17ae 2857 VTY_DECLVAR_CONTEXT(interface, ifp);
16f1b9ee 2858
d62a17ae 2859 /* This command could be issue at startup, when activate MPLS TE */
2860 /* on a new interface or after a ON / OFF / ON toggle */
2861 /* In all case, TE parameters are reset to their default factory */
14a4d9d0 2862 if (IS_ZEBRA_DEBUG_EVENT || IS_ZEBRA_DEBUG_MPLS)
d62a17ae 2863 zlog_debug(
2864 "Link-params: enable TE link parameters on interface %s",
2865 ifp->name);
16f1b9ee 2866
d62a17ae 2867 if (!if_link_params_get(ifp)) {
14a4d9d0 2868 if (IS_ZEBRA_DEBUG_EVENT || IS_ZEBRA_DEBUG_MPLS)
d62a17ae 2869 zlog_debug(
2870 "Link-params: failed to init TE link parameters %s",
2871 ifp->name);
16f1b9ee 2872
d62a17ae 2873 return CMD_WARNING_CONFIG_FAILED;
2874 }
16f1b9ee 2875
d62a17ae 2876 /* force protocols to update LINK STATE due to parameters change */
2877 if (if_is_operative(ifp))
2878 zebra_interface_parameters_update(ifp);
16f1b9ee 2879
d62a17ae 2880 return CMD_SUCCESS;
16f1b9ee
OD
2881}
2882
2883DEFUN (no_link_params_enable,
2884 no_link_params_enable_cmd,
2885 "no enable",
2886 NO_STR
2887 "Disable link parameters on this interface\n")
2888{
d62a17ae 2889 VTY_DECLVAR_CONTEXT(interface, ifp);
16f1b9ee 2890
14a4d9d0 2891 if (IS_ZEBRA_DEBUG_EVENT || IS_ZEBRA_DEBUG_MPLS)
2892 zlog_debug("MPLS-TE: disable TE link parameters on interface %s",
2893 ifp->name);
16f1b9ee 2894
d62a17ae 2895 if_link_params_free(ifp);
16f1b9ee 2896
d62a17ae 2897 /* force protocols to update LINK STATE due to parameters change */
2898 if (if_is_operative(ifp))
2899 zebra_interface_parameters_update(ifp);
16f1b9ee 2900
d62a17ae 2901 return CMD_SUCCESS;
16f1b9ee
OD
2902}
2903
2904/* STANDARD TE metrics */
2905DEFUN (link_params_metric,
2906 link_params_metric_cmd,
6147e2c6 2907 "metric (0-4294967295)",
16f1b9ee
OD
2908 "Link metric for MPLS-TE purpose\n"
2909 "Metric value in decimal\n")
2910{
d62a17ae 2911 int idx_number = 1;
2912 VTY_DECLVAR_CONTEXT(interface, ifp);
2913 struct if_link_params *iflp = if_link_params_get(ifp);
d7c0a89a 2914 uint32_t metric;
16f1b9ee 2915
d62a17ae 2916 metric = strtoul(argv[idx_number]->arg, NULL, 10);
16f1b9ee 2917
d62a17ae 2918 /* Update TE metric if needed */
2919 link_param_cmd_set_uint32(ifp, &iflp->te_metric, LP_TE_METRIC, metric);
16f1b9ee 2920
d62a17ae 2921 return CMD_SUCCESS;
16f1b9ee
OD
2922}
2923
2924DEFUN (no_link_params_metric,
2925 no_link_params_metric_cmd,
2926 "no metric",
2927 NO_STR
3ddccf18 2928 "Disable Link Metric on this interface\n")
16f1b9ee 2929{
d62a17ae 2930 VTY_DECLVAR_CONTEXT(interface, ifp);
16f1b9ee 2931
d62a17ae 2932 /* Unset TE Metric */
2933 link_param_cmd_unset(ifp, LP_TE_METRIC);
16f1b9ee 2934
d62a17ae 2935 return CMD_SUCCESS;
16f1b9ee
OD
2936}
2937
2938DEFUN (link_params_maxbw,
2939 link_params_maxbw_cmd,
2940 "max-bw BANDWIDTH",
2941 "Maximum bandwidth that can be used\n"
2942 "Bytes/second (IEEE floating point format)\n")
2943{
d62a17ae 2944 int idx_bandwidth = 1;
2945 VTY_DECLVAR_CONTEXT(interface, ifp);
2946 struct if_link_params *iflp = if_link_params_get(ifp);
2947
2948 float bw;
2949
2950 if (sscanf(argv[idx_bandwidth]->arg, "%g", &bw) != 1) {
2951 vty_out(vty, "link_params_maxbw: fscanf: %s\n",
2952 safe_strerror(errno));
2953 return CMD_WARNING_CONFIG_FAILED;
2954 }
2955
2956 /* Check that Maximum bandwidth is not lower than other bandwidth
2957 * parameters */
2958 if ((bw <= iflp->max_rsv_bw) || (bw <= iflp->unrsv_bw[0])
2959 || (bw <= iflp->unrsv_bw[1]) || (bw <= iflp->unrsv_bw[2])
2960 || (bw <= iflp->unrsv_bw[3]) || (bw <= iflp->unrsv_bw[4])
2961 || (bw <= iflp->unrsv_bw[5]) || (bw <= iflp->unrsv_bw[6])
2962 || (bw <= iflp->unrsv_bw[7]) || (bw <= iflp->ava_bw)
2963 || (bw <= iflp->res_bw) || (bw <= iflp->use_bw)) {
2964 vty_out(vty,
2965 "Maximum Bandwidth could not be lower than others bandwidth\n");
2966 return CMD_WARNING_CONFIG_FAILED;
2967 }
2968
2969 /* Update Maximum Bandwidth if needed */
2970 link_param_cmd_set_float(ifp, &iflp->max_bw, LP_MAX_BW, bw);
2971
2972 return CMD_SUCCESS;
16f1b9ee
OD
2973}
2974
2975DEFUN (link_params_max_rsv_bw,
2976 link_params_max_rsv_bw_cmd,
2977 "max-rsv-bw BANDWIDTH",
2978 "Maximum bandwidth that may be reserved\n"
2979 "Bytes/second (IEEE floating point format)\n")
2980{
d62a17ae 2981 int idx_bandwidth = 1;
2982 VTY_DECLVAR_CONTEXT(interface, ifp);
2983 struct if_link_params *iflp = if_link_params_get(ifp);
2984 float bw;
16f1b9ee 2985
d62a17ae 2986 if (sscanf(argv[idx_bandwidth]->arg, "%g", &bw) != 1) {
2987 vty_out(vty, "link_params_max_rsv_bw: fscanf: %s\n",
2988 safe_strerror(errno));
2989 return CMD_WARNING_CONFIG_FAILED;
2990 }
16f1b9ee 2991
d62a17ae 2992 /* Check that bandwidth is not greater than maximum bandwidth parameter
2993 */
2994 if (bw > iflp->max_bw) {
2995 vty_out(vty,
2996 "Maximum Reservable Bandwidth could not be greater than Maximum Bandwidth (%g)\n",
2997 iflp->max_bw);
2998 return CMD_WARNING_CONFIG_FAILED;
2999 }
16f1b9ee 3000
d62a17ae 3001 /* Update Maximum Reservable Bandwidth if needed */
3002 link_param_cmd_set_float(ifp, &iflp->max_rsv_bw, LP_MAX_RSV_BW, bw);
16f1b9ee 3003
d62a17ae 3004 return CMD_SUCCESS;
16f1b9ee
OD
3005}
3006
3007DEFUN (link_params_unrsv_bw,
3008 link_params_unrsv_bw_cmd,
6147e2c6 3009 "unrsv-bw (0-7) BANDWIDTH",
16f1b9ee
OD
3010 "Unreserved bandwidth at each priority level\n"
3011 "Priority\n"
3012 "Bytes/second (IEEE floating point format)\n")
3013{
d62a17ae 3014 int idx_number = 1;
3015 int idx_bandwidth = 2;
3016 VTY_DECLVAR_CONTEXT(interface, ifp);
3017 struct if_link_params *iflp = if_link_params_get(ifp);
3018 int priority;
3019 float bw;
3020
3021 /* We don't have to consider about range check here. */
3022 if (sscanf(argv[idx_number]->arg, "%d", &priority) != 1) {
3023 vty_out(vty, "link_params_unrsv_bw: fscanf: %s\n",
3024 safe_strerror(errno));
3025 return CMD_WARNING_CONFIG_FAILED;
3026 }
3027
3028 if (sscanf(argv[idx_bandwidth]->arg, "%g", &bw) != 1) {
3029 vty_out(vty, "link_params_unrsv_bw: fscanf: %s\n",
3030 safe_strerror(errno));
3031 return CMD_WARNING_CONFIG_FAILED;
3032 }
3033
3034 /* Check that bandwidth is not greater than maximum bandwidth parameter
3035 */
3036 if (bw > iflp->max_bw) {
3037 vty_out(vty,
3038 "UnReserved Bandwidth could not be greater than Maximum Bandwidth (%g)\n",
3039 iflp->max_bw);
3040 return CMD_WARNING_CONFIG_FAILED;
3041 }
3042
3043 /* Update Unreserved Bandwidth if needed */
3044 link_param_cmd_set_float(ifp, &iflp->unrsv_bw[priority], LP_UNRSV_BW,
3045 bw);
3046
3047 return CMD_SUCCESS;
16f1b9ee
OD
3048}
3049
3050DEFUN (link_params_admin_grp,
3051 link_params_admin_grp_cmd,
3052 "admin-grp BITPATTERN",
3053 "Administrative group membership\n"
3054 "32-bit Hexadecimal value (e.g. 0xa1)\n")
3055{
d62a17ae 3056 int idx_bitpattern = 1;
3057 VTY_DECLVAR_CONTEXT(interface, ifp);
3058 struct if_link_params *iflp = if_link_params_get(ifp);
3059 unsigned long value;
16f1b9ee 3060
d62a17ae 3061 if (sscanf(argv[idx_bitpattern]->arg, "0x%lx", &value) != 1) {
3062 vty_out(vty, "link_params_admin_grp: fscanf: %s\n",
3063 safe_strerror(errno));
3064 return CMD_WARNING_CONFIG_FAILED;
3065 }
16f1b9ee 3066
d62a17ae 3067 /* Update Administrative Group if needed */
3068 link_param_cmd_set_uint32(ifp, &iflp->admin_grp, LP_ADM_GRP, value);
16f1b9ee 3069
d62a17ae 3070 return CMD_SUCCESS;
16f1b9ee
OD
3071}
3072
3073DEFUN (no_link_params_admin_grp,
3074 no_link_params_admin_grp_cmd,
3075 "no admin-grp",
3076 NO_STR
3ddccf18 3077 "Disable Administrative group membership on this interface\n")
16f1b9ee 3078{
d62a17ae 3079 VTY_DECLVAR_CONTEXT(interface, ifp);
16f1b9ee 3080
d62a17ae 3081 /* Unset Admin Group */
3082 link_param_cmd_unset(ifp, LP_ADM_GRP);
16f1b9ee 3083
d62a17ae 3084 return CMD_SUCCESS;
16f1b9ee
OD
3085}
3086
3087/* RFC5392 & RFC5316: INTER-AS */
3088DEFUN (link_params_inter_as,
3089 link_params_inter_as_cmd,
6147e2c6 3090 "neighbor A.B.C.D as (1-4294967295)",
16f1b9ee
OD
3091 "Configure remote ASBR information (Neighbor IP address and AS number)\n"
3092 "Remote IP address in dot decimal A.B.C.D\n"
3093 "Remote AS number\n"
3094 "AS number in the range <1-4294967295>\n")
3095{
d62a17ae 3096 int idx_ipv4 = 1;
3097 int idx_number = 3;
16f1b9ee 3098
d62a17ae 3099 VTY_DECLVAR_CONTEXT(interface, ifp);
3100 struct if_link_params *iflp = if_link_params_get(ifp);
3101 struct in_addr addr;
d7c0a89a 3102 uint32_t as;
16f1b9ee 3103
d62a17ae 3104 if (!inet_aton(argv[idx_ipv4]->arg, &addr)) {
3105 vty_out(vty, "Please specify Router-Addr by A.B.C.D\n");
3106 return CMD_WARNING_CONFIG_FAILED;
3107 }
16f1b9ee 3108
d62a17ae 3109 as = strtoul(argv[idx_number]->arg, NULL, 10);
16f1b9ee 3110
d62a17ae 3111 /* Update Remote IP and Remote AS fields if needed */
3112 if (IS_PARAM_UNSET(iflp, LP_RMT_AS) || iflp->rmt_as != as
3113 || iflp->rmt_ip.s_addr != addr.s_addr) {
16f1b9ee 3114
d62a17ae 3115 iflp->rmt_as = as;
3116 iflp->rmt_ip.s_addr = addr.s_addr;
3117 SET_PARAM(iflp, LP_RMT_AS);
16f1b9ee 3118
d62a17ae 3119 /* force protocols to update LINK STATE due to parameters change
3120 */
3121 if (if_is_operative(ifp))
3122 zebra_interface_parameters_update(ifp);
3123 }
3124 return CMD_SUCCESS;
16f1b9ee
OD
3125}
3126
3127DEFUN (no_link_params_inter_as,
3128 no_link_params_inter_as_cmd,
3129 "no neighbor",
3130 NO_STR
3131 "Remove Neighbor IP address and AS number for Inter-AS TE\n")
3132{
d62a17ae 3133 VTY_DECLVAR_CONTEXT(interface, ifp);
3134 struct if_link_params *iflp = if_link_params_get(ifp);
16f1b9ee 3135
d62a17ae 3136 /* Reset Remote IP and AS neighbor */
3137 iflp->rmt_as = 0;
3138 iflp->rmt_ip.s_addr = 0;
3139 UNSET_PARAM(iflp, LP_RMT_AS);
16f1b9ee 3140
d62a17ae 3141 /* force protocols to update LINK STATE due to parameters change */
3142 if (if_is_operative(ifp))
3143 zebra_interface_parameters_update(ifp);
16f1b9ee 3144
d62a17ae 3145 return CMD_SUCCESS;
16f1b9ee
OD
3146}
3147
d62a17ae 3148/* RFC7471: OSPF Traffic Engineering (TE) Metric extensions &
3149 * draft-ietf-isis-metric-extensions-07.txt */
16f1b9ee
OD
3150DEFUN (link_params_delay,
3151 link_params_delay_cmd,
b62ecea5 3152 "delay (0-16777215) [min (0-16777215) max (0-16777215)]",
16f1b9ee 3153 "Unidirectional Average Link Delay\n"
b62ecea5
QY
3154 "Average delay in micro-second as decimal (0...16777215)\n"
3155 "Minimum delay\n"
3156 "Minimum delay in micro-second as decimal (0...16777215)\n"
3157 "Maximum delay\n"
3158 "Maximum delay in micro-second as decimal (0...16777215)\n")
16f1b9ee 3159{
d62a17ae 3160 /* Get and Check new delay values */
d7c0a89a 3161 uint32_t delay = 0, low = 0, high = 0;
d62a17ae 3162 delay = strtoul(argv[1]->arg, NULL, 10);
3163 if (argc == 6) {
3164 low = strtoul(argv[3]->arg, NULL, 10);
3165 high = strtoul(argv[5]->arg, NULL, 10);
3166 }
3167
3168 VTY_DECLVAR_CONTEXT(interface, ifp);
3169 struct if_link_params *iflp = if_link_params_get(ifp);
d7c0a89a 3170 uint8_t update = 0;
d62a17ae 3171
3172 if (argc == 2) {
3173 /* Check new delay value against old Min and Max delays if set
3174 */
3175 if (IS_PARAM_SET(iflp, LP_MM_DELAY)
3176 && (delay <= iflp->min_delay || delay >= iflp->max_delay)) {
3177 vty_out(vty,
3178 "Average delay should be comprise between Min (%d) and Max (%d) delay\n",
3179 iflp->min_delay, iflp->max_delay);
3180 return CMD_WARNING_CONFIG_FAILED;
3181 }
3182 /* Update delay if value is not set or change */
3183 if (IS_PARAM_UNSET(iflp, LP_DELAY) || iflp->av_delay != delay) {
3184 iflp->av_delay = delay;
3185 SET_PARAM(iflp, LP_DELAY);
3186 update = 1;
3187 }
3188 /* Unset Min and Max delays if already set */
3189 if (IS_PARAM_SET(iflp, LP_MM_DELAY)) {
3190 iflp->min_delay = 0;
3191 iflp->max_delay = 0;
3192 UNSET_PARAM(iflp, LP_MM_DELAY);
3193 update = 1;
3194 }
3195 } else {
3196 /* Check new delays value coherency */
3197 if (delay <= low || delay >= high) {
3198 vty_out(vty,
3199 "Average delay should be comprise between Min (%d) and Max (%d) delay\n",
3200 low, high);
3201 return CMD_WARNING_CONFIG_FAILED;
3202 }
3203 /* Update Delays if needed */
3204 if (IS_PARAM_UNSET(iflp, LP_DELAY)
3205 || IS_PARAM_UNSET(iflp, LP_MM_DELAY)
3206 || iflp->av_delay != delay || iflp->min_delay != low
3207 || iflp->max_delay != high) {
3208 iflp->av_delay = delay;
3209 SET_PARAM(iflp, LP_DELAY);
3210 iflp->min_delay = low;
3211 iflp->max_delay = high;
3212 SET_PARAM(iflp, LP_MM_DELAY);
3213 update = 1;
3214 }
3215 }
3216
3217 /* force protocols to update LINK STATE due to parameters change */
3218 if (update == 1 && if_is_operative(ifp))
3219 zebra_interface_parameters_update(ifp);
3220
3221 return CMD_SUCCESS;
16f1b9ee
OD
3222}
3223
16f1b9ee
OD
3224DEFUN (no_link_params_delay,
3225 no_link_params_delay_cmd,
3226 "no delay",
3227 NO_STR
3ddccf18 3228 "Disable Unidirectional Average, Min & Max Link Delay on this interface\n")
16f1b9ee 3229{
d62a17ae 3230 VTY_DECLVAR_CONTEXT(interface, ifp);
3231 struct if_link_params *iflp = if_link_params_get(ifp);
16f1b9ee 3232
d62a17ae 3233 /* Unset Delays */
3234 iflp->av_delay = 0;
3235 UNSET_PARAM(iflp, LP_DELAY);
3236 iflp->min_delay = 0;
3237 iflp->max_delay = 0;
3238 UNSET_PARAM(iflp, LP_MM_DELAY);
16f1b9ee 3239
d62a17ae 3240 /* force protocols to update LINK STATE due to parameters change */
3241 if (if_is_operative(ifp))
3242 zebra_interface_parameters_update(ifp);
16f1b9ee 3243
d62a17ae 3244 return CMD_SUCCESS;
16f1b9ee
OD
3245}
3246
3247DEFUN (link_params_delay_var,
3248 link_params_delay_var_cmd,
6147e2c6 3249 "delay-variation (0-16777215)",
16f1b9ee
OD
3250 "Unidirectional Link Delay Variation\n"
3251 "delay variation in micro-second as decimal (0...16777215)\n")
3252{
d62a17ae 3253 int idx_number = 1;
3254 VTY_DECLVAR_CONTEXT(interface, ifp);
3255 struct if_link_params *iflp = if_link_params_get(ifp);
d7c0a89a 3256 uint32_t value;
16f1b9ee 3257
d62a17ae 3258 value = strtoul(argv[idx_number]->arg, NULL, 10);
16f1b9ee 3259
d62a17ae 3260 /* Update Delay Variation if needed */
3261 link_param_cmd_set_uint32(ifp, &iflp->delay_var, LP_DELAY_VAR, value);
16f1b9ee 3262
d62a17ae 3263 return CMD_SUCCESS;
16f1b9ee
OD
3264}
3265
3266DEFUN (no_link_params_delay_var,
3267 no_link_params_delay_var_cmd,
3268 "no delay-variation",
3269 NO_STR
3ddccf18 3270 "Disable Unidirectional Delay Variation on this interface\n")
16f1b9ee 3271{
d62a17ae 3272 VTY_DECLVAR_CONTEXT(interface, ifp);
16f1b9ee 3273
d62a17ae 3274 /* Unset Delay Variation */
3275 link_param_cmd_unset(ifp, LP_DELAY_VAR);
16f1b9ee 3276
d62a17ae 3277 return CMD_SUCCESS;
16f1b9ee
OD
3278}
3279
3280DEFUN (link_params_pkt_loss,
3281 link_params_pkt_loss_cmd,
3282 "packet-loss PERCENTAGE",
3283 "Unidirectional Link Packet Loss\n"
3284 "percentage of total traffic by 0.000003% step and less than 50.331642%\n")
3285{
d62a17ae 3286 int idx_percentage = 1;
3287 VTY_DECLVAR_CONTEXT(interface, ifp);
3288 struct if_link_params *iflp = if_link_params_get(ifp);
3289 float fval;
16f1b9ee 3290
d62a17ae 3291 if (sscanf(argv[idx_percentage]->arg, "%g", &fval) != 1) {
3292 vty_out(vty, "link_params_pkt_loss: fscanf: %s\n",
3293 safe_strerror(errno));
3294 return CMD_WARNING_CONFIG_FAILED;
3295 }
16f1b9ee 3296
d62a17ae 3297 if (fval > MAX_PKT_LOSS)
3298 fval = MAX_PKT_LOSS;
16f1b9ee 3299
d62a17ae 3300 /* Update Packet Loss if needed */
3301 link_param_cmd_set_float(ifp, &iflp->pkt_loss, LP_PKT_LOSS, fval);
16f1b9ee 3302
d62a17ae 3303 return CMD_SUCCESS;
16f1b9ee
OD
3304}
3305
3306DEFUN (no_link_params_pkt_loss,
3307 no_link_params_pkt_loss_cmd,
3308 "no packet-loss",
3309 NO_STR
3ddccf18 3310 "Disable Unidirectional Link Packet Loss on this interface\n")
16f1b9ee 3311{
d62a17ae 3312 VTY_DECLVAR_CONTEXT(interface, ifp);
16f1b9ee 3313
d62a17ae 3314 /* Unset Packet Loss */
3315 link_param_cmd_unset(ifp, LP_PKT_LOSS);
16f1b9ee 3316
d62a17ae 3317 return CMD_SUCCESS;
16f1b9ee
OD
3318}
3319
3320DEFUN (link_params_res_bw,
3321 link_params_res_bw_cmd,
3322 "res-bw BANDWIDTH",
3323 "Unidirectional Residual Bandwidth\n"
3324 "Bytes/second (IEEE floating point format)\n")
3325{
d62a17ae 3326 int idx_bandwidth = 1;
3327 VTY_DECLVAR_CONTEXT(interface, ifp);
3328 struct if_link_params *iflp = if_link_params_get(ifp);
3329 float bw;
16f1b9ee 3330
d62a17ae 3331 if (sscanf(argv[idx_bandwidth]->arg, "%g", &bw) != 1) {
3332 vty_out(vty, "link_params_res_bw: fscanf: %s\n",
3333 safe_strerror(errno));
3334 return CMD_WARNING_CONFIG_FAILED;
3335 }
16f1b9ee 3336
d62a17ae 3337 /* Check that bandwidth is not greater than maximum bandwidth parameter
3338 */
3339 if (bw > iflp->max_bw) {
3340 vty_out(vty,
3341 "Residual Bandwidth could not be greater than Maximum Bandwidth (%g)\n",
3342 iflp->max_bw);
3343 return CMD_WARNING_CONFIG_FAILED;
3344 }
16f1b9ee 3345
d62a17ae 3346 /* Update Residual Bandwidth if needed */
3347 link_param_cmd_set_float(ifp, &iflp->res_bw, LP_RES_BW, bw);
16f1b9ee 3348
d62a17ae 3349 return CMD_SUCCESS;
16f1b9ee
OD
3350}
3351
3352DEFUN (no_link_params_res_bw,
3353 no_link_params_res_bw_cmd,
3354 "no res-bw",
3355 NO_STR
3ddccf18 3356 "Disable Unidirectional Residual Bandwidth on this interface\n")
16f1b9ee 3357{
d62a17ae 3358 VTY_DECLVAR_CONTEXT(interface, ifp);
16f1b9ee 3359
d62a17ae 3360 /* Unset Residual Bandwidth */
3361 link_param_cmd_unset(ifp, LP_RES_BW);
16f1b9ee 3362
d62a17ae 3363 return CMD_SUCCESS;
16f1b9ee
OD
3364}
3365
3366DEFUN (link_params_ava_bw,
3367 link_params_ava_bw_cmd,
3368 "ava-bw BANDWIDTH",
3369 "Unidirectional Available Bandwidth\n"
3370 "Bytes/second (IEEE floating point format)\n")
3371{
d62a17ae 3372 int idx_bandwidth = 1;
3373 VTY_DECLVAR_CONTEXT(interface, ifp);
3374 struct if_link_params *iflp = if_link_params_get(ifp);
3375 float bw;
16f1b9ee 3376
d62a17ae 3377 if (sscanf(argv[idx_bandwidth]->arg, "%g", &bw) != 1) {
3378 vty_out(vty, "link_params_ava_bw: fscanf: %s\n",
3379 safe_strerror(errno));
3380 return CMD_WARNING_CONFIG_FAILED;
3381 }
16f1b9ee 3382
d62a17ae 3383 /* Check that bandwidth is not greater than maximum bandwidth parameter
3384 */
3385 if (bw > iflp->max_bw) {
3386 vty_out(vty,
3387 "Available Bandwidth could not be greater than Maximum Bandwidth (%g)\n",
3388 iflp->max_bw);
3389 return CMD_WARNING_CONFIG_FAILED;
3390 }
16f1b9ee 3391
d62a17ae 3392 /* Update Residual Bandwidth if needed */
3393 link_param_cmd_set_float(ifp, &iflp->ava_bw, LP_AVA_BW, bw);
16f1b9ee 3394
d62a17ae 3395 return CMD_SUCCESS;
16f1b9ee
OD
3396}
3397
3398DEFUN (no_link_params_ava_bw,
3399 no_link_params_ava_bw_cmd,
3400 "no ava-bw",
3401 NO_STR
3ddccf18 3402 "Disable Unidirectional Available Bandwidth on this interface\n")
16f1b9ee 3403{
d62a17ae 3404 VTY_DECLVAR_CONTEXT(interface, ifp);
16f1b9ee 3405
d62a17ae 3406 /* Unset Available Bandwidth */
3407 link_param_cmd_unset(ifp, LP_AVA_BW);
16f1b9ee 3408
d62a17ae 3409 return CMD_SUCCESS;
16f1b9ee
OD
3410}
3411
3412DEFUN (link_params_use_bw,
3413 link_params_use_bw_cmd,
3414 "use-bw BANDWIDTH",
3415 "Unidirectional Utilised Bandwidth\n"
3416 "Bytes/second (IEEE floating point format)\n")
3417{
d62a17ae 3418 int idx_bandwidth = 1;
3419 VTY_DECLVAR_CONTEXT(interface, ifp);
3420 struct if_link_params *iflp = if_link_params_get(ifp);
3421 float bw;
16f1b9ee 3422
d62a17ae 3423 if (sscanf(argv[idx_bandwidth]->arg, "%g", &bw) != 1) {
3424 vty_out(vty, "link_params_use_bw: fscanf: %s\n",
3425 safe_strerror(errno));
3426 return CMD_WARNING_CONFIG_FAILED;
3427 }
16f1b9ee 3428
d62a17ae 3429 /* Check that bandwidth is not greater than maximum bandwidth parameter
3430 */
3431 if (bw > iflp->max_bw) {
3432 vty_out(vty,
3433 "Utilised Bandwidth could not be greater than Maximum Bandwidth (%g)\n",
3434 iflp->max_bw);
3435 return CMD_WARNING_CONFIG_FAILED;
3436 }
16f1b9ee 3437
d62a17ae 3438 /* Update Utilized Bandwidth if needed */
3439 link_param_cmd_set_float(ifp, &iflp->use_bw, LP_USE_BW, bw);
16f1b9ee 3440
d62a17ae 3441 return CMD_SUCCESS;
16f1b9ee
OD
3442}
3443
3444DEFUN (no_link_params_use_bw,
3445 no_link_params_use_bw_cmd,
3446 "no use-bw",
3447 NO_STR
3ddccf18 3448 "Disable Unidirectional Utilised Bandwidth on this interface\n")
16f1b9ee 3449{
d62a17ae 3450 VTY_DECLVAR_CONTEXT(interface, ifp);
16f1b9ee 3451
d62a17ae 3452 /* Unset Utilised Bandwidth */
3453 link_param_cmd_unset(ifp, LP_USE_BW);
16f1b9ee 3454
d62a17ae 3455 return CMD_SUCCESS;
16f1b9ee
OD
3456}
3457
09268680
CS
3458int if_ip_address_install(struct interface *ifp, struct prefix *prefix,
3459 const char *label, struct prefix *pp)
3460{
3461 struct zebra_if *if_data;
3462 struct prefix_ipv4 lp;
3463 struct prefix_ipv4 *p;
3464 struct connected *ifc;
3465 enum zebra_dplane_result dplane_res;
3466
3467 if_data = ifp->info;
3468
3469 lp.family = prefix->family;
3470 lp.prefix = prefix->u.prefix4;
3471 lp.prefixlen = prefix->prefixlen;
3472 apply_mask_ipv4(&lp);
3473
3474 ifc = connected_check_ptp(ifp, &lp, pp ? pp : NULL);
3475 if (!ifc) {
3476 ifc = connected_new();
3477 ifc->ifp = ifp;
3478
3479 /* Address. */
3480 p = prefix_ipv4_new();
3481 *p = lp;
3482 ifc->address = (struct prefix *)p;
3483
3484 if (pp) {
3485 SET_FLAG(ifc->flags, ZEBRA_IFA_PEER);
3486 p = prefix_ipv4_new();
3487 *p = *(struct prefix_ipv4 *)pp;
3488 ifc->destination = (struct prefix *)p;
3489 }
3490
3491 /* Label. */
3492 if (label)
3493 ifc->label = XSTRDUP(MTYPE_CONNECTED_LABEL, label);
3494
3495 /* Add to linked list. */
3496 listnode_add(ifp->connected, ifc);
3497 }
3498
3499 /* This address is configured from zebra. */
3500 if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED))
3501 SET_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED);
3502
3503 /* In case of this route need to install kernel. */
3504 if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_QUEUED)
3505 && CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE)
3506 && !(if_data && if_data->shutdown == IF_ZEBRA_SHUTDOWN_ON)) {
3507 /* Some system need to up the interface to set IP address. */
3508 if (!if_is_up(ifp)) {
3509 if_set_flags(ifp, IFF_UP | IFF_RUNNING);
3510 if_refresh(ifp);
3511 }
3512
3513 dplane_res = dplane_intf_addr_set(ifp, ifc);
3514 if (dplane_res == ZEBRA_DPLANE_REQUEST_FAILURE) {
3515 zlog_debug(
1d5453d6 3516 "dplane can't set interface IP address: %s.",
09268680
CS
3517 dplane_res2str(dplane_res));
3518 return NB_ERR;
3519 }
3520
3521 SET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED);
3522 /* The address will be advertised to zebra clients when the
3523 * notification
3524 * from the kernel has been received.
3525 * It will also be added to the subnet chain list, then. */
3526 }
3527
3528 return 0;
3529}
3530
d62a17ae 3531static int ip_address_install(struct vty *vty, struct interface *ifp,
3532 const char *addr_str, const char *peer_str,
3533 const char *label)
718e3744 3534{
d62a17ae 3535 struct zebra_if *if_data;
a07df329 3536 struct prefix_ipv4 lp, pp;
d62a17ae 3537 struct connected *ifc;
3538 struct prefix_ipv4 *p;
3539 int ret;
64168803 3540 enum zebra_dplane_result dplane_res;
718e3744 3541
d62a17ae 3542 if_data = ifp->info;
bfac8dcd 3543
a07df329 3544 ret = str2prefix_ipv4(addr_str, &lp);
d62a17ae 3545 if (ret <= 0) {
3546 vty_out(vty, "%% Malformed address \n");
3547 return CMD_WARNING_CONFIG_FAILED;
3548 }
718e3744 3549
a07df329 3550 if (ipv4_martian(&lp.prefix)) {
d62a17ae 3551 vty_out(vty, "%% Invalid address\n");
3552 return CMD_WARNING_CONFIG_FAILED;
3553 }
d914d5ff 3554
a07df329 3555 if (peer_str) {
12256b84 3556 if (lp.prefixlen != IPV4_MAX_BITLEN) {
a07df329
DL
3557 vty_out(vty,
3558 "%% Local prefix length for P-t-P address must be /32\n");
3559 return CMD_WARNING_CONFIG_FAILED;
3560 }
3561
3562 ret = str2prefix_ipv4(peer_str, &pp);
3563 if (ret <= 0) {
3564 vty_out(vty, "%% Malformed peer address\n");
3565 return CMD_WARNING_CONFIG_FAILED;
3566 }
3567 }
3568
3569 ifc = connected_check_ptp(ifp, &lp, peer_str ? &pp : NULL);
d62a17ae 3570 if (!ifc) {
3571 ifc = connected_new();
3572 ifc->ifp = ifp;
3573
3574 /* Address. */
3575 p = prefix_ipv4_new();
a07df329 3576 *p = lp;
d62a17ae 3577 ifc->address = (struct prefix *)p;
3578
a07df329
DL
3579 if (peer_str) {
3580 SET_FLAG(ifc->flags, ZEBRA_IFA_PEER);
3581 p = prefix_ipv4_new();
3582 *p = pp;
3583 ifc->destination = (struct prefix *)p;
d62a17ae 3584 }
718e3744 3585
d62a17ae 3586 /* Label. */
3587 if (label)
3588 ifc->label = XSTRDUP(MTYPE_CONNECTED_LABEL, label);
718e3744 3589
d62a17ae 3590 /* Add to linked list. */
3591 listnode_add(ifp->connected, ifc);
718e3744 3592 }
3593
d62a17ae 3594 /* This address is configured from zebra. */
3595 if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED))
3596 SET_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED);
3597
3598 /* In case of this route need to install kernel. */
3599 if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_QUEUED)
3600 && CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE)
3601 && !(if_data && if_data->shutdown == IF_ZEBRA_SHUTDOWN_ON)) {
3602 /* Some system need to up the interface to set IP address. */
3603 if (!if_is_up(ifp)) {
3604 if_set_flags(ifp, IFF_UP | IFF_RUNNING);
3605 if_refresh(ifp);
3606 }
3607
64168803
MS
3608 dplane_res = dplane_intf_addr_set(ifp, ifc);
3609 if (dplane_res == ZEBRA_DPLANE_REQUEST_FAILURE) {
d62a17ae 3610 vty_out(vty, "%% Can't set interface IP address: %s.\n",
64168803 3611 dplane_res2str(dplane_res));
d62a17ae 3612 return CMD_WARNING_CONFIG_FAILED;
3613 }
3614
3615 SET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED);
3616 /* The address will be advertised to zebra clients when the
3617 * notification
3618 * from the kernel has been received.
3619 * It will also be added to the subnet chain list, then. */
3620 }
3621
3622 return CMD_SUCCESS;
3623}
3624
09268680
CS
3625int if_ip_address_uinstall(struct interface *ifp, struct prefix *prefix)
3626{
3627 struct connected *ifc = NULL;
3628 enum zebra_dplane_result dplane_res;
3629
3630 if (prefix->family == AF_INET) {
3631 /* Check current interface address. */
3632 ifc = connected_check_ptp(ifp, prefix, NULL);
3633 if (!ifc) {
1d5453d6 3634 zlog_debug("interface %s Can't find address",
09268680
CS
3635 ifp->name);
3636 return -1;
3637 }
3638
3639 } else if (prefix->family == AF_INET6) {
3640 /* Check current interface address. */
3641 ifc = connected_check(ifp, prefix);
3642 }
3643
3644 if (!ifc) {
1d5453d6 3645 zlog_debug("interface %s Can't find address", ifp->name);
09268680
CS
3646 return -1;
3647 }
3648 UNSET_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED);
3649
3650 /* This is not real address or interface is not active. */
3651 if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_QUEUED)
3652 || !CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE)) {
3653 listnode_delete(ifp->connected, ifc);
3654 connected_free(&ifc);
3655 return CMD_WARNING_CONFIG_FAILED;
3656 }
3657
3658 /* This is real route. */
3659 dplane_res = dplane_intf_addr_unset(ifp, ifc);
3660 if (dplane_res == ZEBRA_DPLANE_REQUEST_FAILURE) {
1d5453d6 3661 zlog_debug("Can't unset interface IP address: %s.",
09268680
CS
3662 dplane_res2str(dplane_res));
3663 return -1;
3664 }
3665 UNSET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED);
3666
3667 return 0;
3668}
3669
d62a17ae 3670static int ip_address_uninstall(struct vty *vty, struct interface *ifp,
3671 const char *addr_str, const char *peer_str,
3672 const char *label)
3673{
a07df329 3674 struct prefix_ipv4 lp, pp;
d62a17ae 3675 struct connected *ifc;
3676 int ret;
64168803 3677 enum zebra_dplane_result dplane_res;
d62a17ae 3678
3679 /* Convert to prefix structure. */
a07df329 3680 ret = str2prefix_ipv4(addr_str, &lp);
d62a17ae 3681 if (ret <= 0) {
3682 vty_out(vty, "%% Malformed address \n");
3683 return CMD_WARNING_CONFIG_FAILED;
3684 }
3685
a07df329 3686 if (peer_str) {
12256b84 3687 if (lp.prefixlen != IPV4_MAX_BITLEN) {
a07df329
DL
3688 vty_out(vty,
3689 "%% Local prefix length for P-t-P address must be /32\n");
3690 return CMD_WARNING_CONFIG_FAILED;
3691 }
3692
3693 ret = str2prefix_ipv4(peer_str, &pp);
3694 if (ret <= 0) {
3695 vty_out(vty, "%% Malformed peer address\n");
3696 return CMD_WARNING_CONFIG_FAILED;
3697 }
3698 }
3699
d62a17ae 3700 /* Check current interface address. */
a07df329 3701 ifc = connected_check_ptp(ifp, &lp, peer_str ? &pp : NULL);
d62a17ae 3702 if (!ifc) {
3703 vty_out(vty, "%% Can't find address\n");
3704 return CMD_WARNING_CONFIG_FAILED;
3705 }
3706
3707 /* This is not configured address. */
3708 if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED))
3709 return CMD_WARNING_CONFIG_FAILED;
3710
3711 UNSET_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED);
3712
3713 /* This is not real address or interface is not active. */
3714 if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_QUEUED)
3715 || !CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE)) {
3716 listnode_delete(ifp->connected, ifc);
721c0857 3717 connected_free(&ifc);
d62a17ae 3718 return CMD_WARNING_CONFIG_FAILED;
3719 }
3720
3721 /* This is real route. */
64168803
MS
3722 dplane_res = dplane_intf_addr_unset(ifp, ifc);
3723 if (dplane_res == ZEBRA_DPLANE_REQUEST_FAILURE) {
d62a17ae 3724 vty_out(vty, "%% Can't unset interface IP address: %s.\n",
64168803 3725 dplane_res2str(dplane_res));
d62a17ae 3726 return CMD_WARNING_CONFIG_FAILED;
3727 }
3728 UNSET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED);
3729 /* we will receive a kernel notification about this route being removed.
3730 * this will trigger its removal from the connected list. */
3731 return CMD_SUCCESS;
718e3744 3732}
3733
3734DEFUN (ip_address,
3735 ip_address_cmd,
3736 "ip address A.B.C.D/M",
3737 "Interface Internet Protocol config commands\n"
3738 "Set the IP address of an interface\n"
3739 "IP address (e.g. 10.0.0.1/8)\n")
3740{
d62a17ae 3741 int idx_ipv4_prefixlen = 2;
3742 VTY_DECLVAR_CONTEXT(interface, ifp);
3743 return ip_address_install(vty, ifp, argv[idx_ipv4_prefixlen]->arg, NULL,
3744 NULL);
718e3744 3745}
3746
3747DEFUN (no_ip_address,
3748 no_ip_address_cmd,
3749 "no ip address A.B.C.D/M",
3750 NO_STR
3751 "Interface Internet Protocol config commands\n"
3752 "Set the IP address of an interface\n"
efd7904e 3753 "IP Address (e.g. 10.0.0.1/8)\n")
718e3744 3754{
d62a17ae 3755 int idx_ipv4_prefixlen = 3;
3756 VTY_DECLVAR_CONTEXT(interface, ifp);
3757 return ip_address_uninstall(vty, ifp, argv[idx_ipv4_prefixlen]->arg,
3758 NULL, NULL);
718e3744 3759}
3760
60466a63
QY
3761DEFUN(ip_address_peer,
3762 ip_address_peer_cmd,
3763 "ip address A.B.C.D peer A.B.C.D/M",
3764 "Interface Internet Protocol config commands\n"
3765 "Set the IP address of an interface\n"
3766 "Local IP (e.g. 10.0.0.1) for P-t-P address\n"
3767 "Specify P-t-P address\n"
3768 "Peer IP address (e.g. 10.0.0.1/8)\n")
a07df329
DL
3769{
3770 VTY_DECLVAR_CONTEXT(interface, ifp);
3771 return ip_address_install(vty, ifp, argv[2]->arg, argv[4]->arg, NULL);
3772}
3773
60466a63
QY
3774DEFUN(no_ip_address_peer,
3775 no_ip_address_peer_cmd,
3776 "no ip address A.B.C.D peer A.B.C.D/M",
3777 NO_STR
3778 "Interface Internet Protocol config commands\n"
3779 "Set the IP address of an interface\n"
3780 "Local IP (e.g. 10.0.0.1) for P-t-P address\n"
3781 "Specify P-t-P address\n"
3782 "Peer IP address (e.g. 10.0.0.1/8)\n")
a07df329
DL
3783{
3784 VTY_DECLVAR_CONTEXT(interface, ifp);
3785 return ip_address_uninstall(vty, ifp, argv[3]->arg, argv[5]->arg, NULL);
3786}
986aa00f 3787
718e3744 3788#ifdef HAVE_NETLINK
718e3744 3789DEFUN (ip_address_label,
3790 ip_address_label_cmd,
3791 "ip address A.B.C.D/M label LINE",
3792 "Interface Internet Protocol config commands\n"
3793 "Set the IP address of an interface\n"
3794 "IP address (e.g. 10.0.0.1/8)\n"
3795 "Label of this address\n"
3796 "Label\n")
3797{
d62a17ae 3798 int idx_ipv4_prefixlen = 2;
3799 int idx_line = 4;
3800 VTY_DECLVAR_CONTEXT(interface, ifp);
3801 return ip_address_install(vty, ifp, argv[idx_ipv4_prefixlen]->arg, NULL,
3802 argv[idx_line]->arg);
718e3744 3803}
3804
3805DEFUN (no_ip_address_label,
3806 no_ip_address_label_cmd,
3807 "no ip address A.B.C.D/M label LINE",
3808 NO_STR
3809 "Interface Internet Protocol config commands\n"
3810 "Set the IP address of an interface\n"
3811 "IP address (e.g. 10.0.0.1/8)\n"
3812 "Label of this address\n"
3813 "Label\n")
3814{
d62a17ae 3815 int idx_ipv4_prefixlen = 3;
3816 int idx_line = 5;
3817 VTY_DECLVAR_CONTEXT(interface, ifp);
3818 return ip_address_uninstall(vty, ifp, argv[idx_ipv4_prefixlen]->arg,
3819 NULL, argv[idx_line]->arg);
718e3744 3820}
3821#endif /* HAVE_NETLINK */
3822
09268680
CS
3823int if_ipv6_address_install(struct interface *ifp, struct prefix *prefix,
3824 const char *label)
3825{
3826 struct zebra_if *if_data;
3827 struct prefix_ipv6 cp;
3828 struct connected *ifc;
3829 struct prefix_ipv6 *p;
3830 enum zebra_dplane_result dplane_res;
3831
3832 if_data = ifp->info;
3833
3834 cp.family = prefix->family;
3835 cp.prefixlen = prefix->prefixlen;
3836 cp.prefix = prefix->u.prefix6;
3837 apply_mask_ipv6(&cp);
3838
3839 ifc = connected_check(ifp, (struct prefix *)&cp);
3840 if (!ifc) {
3841 ifc = connected_new();
3842 ifc->ifp = ifp;
3843
3844 /* Address. */
3845 p = prefix_ipv6_new();
3846 *p = cp;
3847 ifc->address = (struct prefix *)p;
3848
3849 /* Label. */
3850 if (label)
3851 ifc->label = XSTRDUP(MTYPE_CONNECTED_LABEL, label);
3852
3853 /* Add to linked list. */
3854 listnode_add(ifp->connected, ifc);
3855 }
3856
3857 /* This address is configured from zebra. */
3858 if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED))
3859 SET_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED);
3860
3861 /* In case of this route need to install kernel. */
3862 if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_QUEUED)
3863 && CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE)
3864 && !(if_data && if_data->shutdown == IF_ZEBRA_SHUTDOWN_ON)) {
3865 /* Some system need to up the interface to set IP address. */
3866 if (!if_is_up(ifp)) {
3867 if_set_flags(ifp, IFF_UP | IFF_RUNNING);
3868 if_refresh(ifp);
3869 }
3870
3871 dplane_res = dplane_intf_addr_set(ifp, ifc);
3872 if (dplane_res == ZEBRA_DPLANE_REQUEST_FAILURE) {
3873 zlog_debug(
1d5453d6 3874 "dplane can't set interface IP address: %s.",
09268680
CS
3875 dplane_res2str(dplane_res));
3876 return NB_ERR;
3877 }
3878
3879 SET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED);
3880 /* The address will be advertised to zebra clients when the
3881 * notification
3882 * from the kernel has been received. */
3883 }
3884
3885 return 0;
3886}
3887
d62a17ae 3888static int ipv6_address_install(struct vty *vty, struct interface *ifp,
3889 const char *addr_str, const char *peer_str,
b1bd1015 3890 const char *label)
d62a17ae 3891{
3892 struct zebra_if *if_data;
3893 struct prefix_ipv6 cp;
3894 struct connected *ifc;
3895 struct prefix_ipv6 *p;
3896 int ret;
0f1f6ce4 3897 enum zebra_dplane_result dplane_res;
d62a17ae 3898
3899 if_data = ifp->info;
3900
3901 ret = str2prefix_ipv6(addr_str, &cp);
3902 if (ret <= 0) {
3903 vty_out(vty, "%% Malformed address \n");
3904 return CMD_WARNING_CONFIG_FAILED;
718e3744 3905 }
3906
d62a17ae 3907 if (ipv6_martian(&cp.prefix)) {
3908 vty_out(vty, "%% Invalid address\n");
3909 return CMD_WARNING_CONFIG_FAILED;
3910 }
718e3744 3911
d62a17ae 3912 ifc = connected_check(ifp, (struct prefix *)&cp);
3913 if (!ifc) {
3914 ifc = connected_new();
3915 ifc->ifp = ifp;
3916
3917 /* Address. */
3918 p = prefix_ipv6_new();
3919 *p = cp;
3920 ifc->address = (struct prefix *)p;
3921
d62a17ae 3922 /* Label. */
3923 if (label)
3924 ifc->label = XSTRDUP(MTYPE_CONNECTED_LABEL, label);
3925
3926 /* Add to linked list. */
3927 listnode_add(ifp->connected, ifc);
718e3744 3928 }
3929
d62a17ae 3930 /* This address is configured from zebra. */
3931 if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED))
3932 SET_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED);
3933
3934 /* In case of this route need to install kernel. */
3935 if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_QUEUED)
3936 && CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE)
3937 && !(if_data && if_data->shutdown == IF_ZEBRA_SHUTDOWN_ON)) {
3938 /* Some system need to up the interface to set IP address. */
3939 if (!if_is_up(ifp)) {
3940 if_set_flags(ifp, IFF_UP | IFF_RUNNING);
3941 if_refresh(ifp);
3942 }
3943
0f1f6ce4
MS
3944 dplane_res = dplane_intf_addr_set(ifp, ifc);
3945 if (dplane_res == ZEBRA_DPLANE_REQUEST_FAILURE) {
d62a17ae 3946 vty_out(vty, "%% Can't set interface IP address: %s.\n",
0f1f6ce4 3947 dplane_res2str(dplane_res));
d62a17ae 3948 return CMD_WARNING_CONFIG_FAILED;
3949 }
3950
3951 SET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED);
3952 /* The address will be advertised to zebra clients when the
3953 * notification
3954 * from the kernel has been received. */
3955 }
718e3744 3956
d62a17ae 3957 return CMD_SUCCESS;
718e3744 3958}
3959
b6120505 3960/* Return true if an ipv6 address is configured on ifp */
d62a17ae 3961int ipv6_address_configured(struct interface *ifp)
3962{
3963 struct connected *connected;
3964 struct listnode *node;
3965
3966 for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, connected))
3967 if (CHECK_FLAG(connected->conf, ZEBRA_IFC_REAL)
3968 && (connected->address->family == AF_INET6))
3969 return 1;
3970
3971 return 0;
3972}
3973
3974static int ipv6_address_uninstall(struct vty *vty, struct interface *ifp,
3975 const char *addr_str, const char *peer_str,
b1bd1015 3976 const char *label)
d62a17ae 3977{
3978 struct prefix_ipv6 cp;
3979 struct connected *ifc;
3980 int ret;
0f1f6ce4 3981 enum zebra_dplane_result dplane_res;
d62a17ae 3982
3983 /* Convert to prefix structure. */
3984 ret = str2prefix_ipv6(addr_str, &cp);
3985 if (ret <= 0) {
3986 vty_out(vty, "%% Malformed address \n");
3987 return CMD_WARNING_CONFIG_FAILED;
3988 }
3989
3990 /* Check current interface address. */
3991 ifc = connected_check(ifp, (struct prefix *)&cp);
3992 if (!ifc) {
3993 vty_out(vty, "%% Can't find address\n");
3994 return CMD_WARNING_CONFIG_FAILED;
3995 }
3996
3997 /* This is not configured address. */
3998 if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED))
3999 return CMD_WARNING_CONFIG_FAILED;
4000
4001 UNSET_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED);
4002
4003 /* This is not real address or interface is not active. */
4004 if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_QUEUED)
4005 || !CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE)) {
4006 listnode_delete(ifp->connected, ifc);
721c0857 4007 connected_free(&ifc);
d62a17ae 4008 return CMD_WARNING_CONFIG_FAILED;
4009 }
4010
4011 /* This is real route. */
0f1f6ce4
MS
4012 dplane_res = dplane_intf_addr_unset(ifp, ifc);
4013 if (dplane_res == ZEBRA_DPLANE_REQUEST_FAILURE) {
d62a17ae 4014 vty_out(vty, "%% Can't unset interface IP address: %s.\n",
0f1f6ce4 4015 dplane_res2str(dplane_res));
d62a17ae 4016 return CMD_WARNING_CONFIG_FAILED;
4017 }
4018
4019 UNSET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED);
4020 /* This information will be propagated to the zclients when the
4021 * kernel notification is received. */
4022 return CMD_SUCCESS;
718e3744 4023}
4024
4025DEFUN (ipv6_address,
4026 ipv6_address_cmd,
4027 "ipv6 address X:X::X:X/M",
e23949c0 4028 "Interface IPv6 config commands\n"
718e3744 4029 "Set the IP address of an interface\n"
4030 "IPv6 address (e.g. 3ffe:506::1/48)\n")
4031{
d62a17ae 4032 int idx_ipv6_prefixlen = 2;
4033 VTY_DECLVAR_CONTEXT(interface, ifp);
4034 return ipv6_address_install(vty, ifp, argv[idx_ipv6_prefixlen]->arg,
b1bd1015 4035 NULL, NULL);
718e3744 4036}
4037
4038DEFUN (no_ipv6_address,
4039 no_ipv6_address_cmd,
4040 "no ipv6 address X:X::X:X/M",
4041 NO_STR
e23949c0 4042 "Interface IPv6 config commands\n"
718e3744 4043 "Set the IP address of an interface\n"
4044 "IPv6 address (e.g. 3ffe:506::1/48)\n")
4045{
d62a17ae 4046 int idx_ipv6_prefixlen = 3;
4047 VTY_DECLVAR_CONTEXT(interface, ifp);
4048 return ipv6_address_uninstall(vty, ifp, argv[idx_ipv6_prefixlen]->arg,
b1bd1015 4049 NULL, NULL);
d62a17ae 4050}
4051
4052static int link_params_config_write(struct vty *vty, struct interface *ifp)
4053{
4054 int i;
4055
4056 if ((ifp == NULL) || !HAS_LINK_PARAMS(ifp))
4057 return -1;
986aa00f 4058
d62a17ae 4059 struct if_link_params *iflp = ifp->link_params;
4060
4061 vty_out(vty, " link-params\n");
4062 vty_out(vty, " enable\n");
4063 if (IS_PARAM_SET(iflp, LP_TE_METRIC) && iflp->te_metric != ifp->metric)
4064 vty_out(vty, " metric %u\n", iflp->te_metric);
4065 if (IS_PARAM_SET(iflp, LP_MAX_BW) && iflp->max_bw != iflp->default_bw)
4066 vty_out(vty, " max-bw %g\n", iflp->max_bw);
4067 if (IS_PARAM_SET(iflp, LP_MAX_RSV_BW)
4068 && iflp->max_rsv_bw != iflp->default_bw)
4069 vty_out(vty, " max-rsv-bw %g\n", iflp->max_rsv_bw);
4070 if (IS_PARAM_SET(iflp, LP_UNRSV_BW)) {
4071 for (i = 0; i < 8; i++)
4072 if (iflp->unrsv_bw[i] != iflp->default_bw)
4073 vty_out(vty, " unrsv-bw %d %g\n", i,
4074 iflp->unrsv_bw[i]);
4075 }
4076 if (IS_PARAM_SET(iflp, LP_ADM_GRP))
4077 vty_out(vty, " admin-grp 0x%x\n", iflp->admin_grp);
4078 if (IS_PARAM_SET(iflp, LP_DELAY)) {
4079 vty_out(vty, " delay %u", iflp->av_delay);
4080 if (IS_PARAM_SET(iflp, LP_MM_DELAY)) {
4081 vty_out(vty, " min %u", iflp->min_delay);
4082 vty_out(vty, " max %u", iflp->max_delay);
4083 }
4084 vty_out(vty, "\n");
bfac8dcd 4085 }
d62a17ae 4086 if (IS_PARAM_SET(iflp, LP_DELAY_VAR))
4087 vty_out(vty, " delay-variation %u\n", iflp->delay_var);
4088 if (IS_PARAM_SET(iflp, LP_PKT_LOSS))
4089 vty_out(vty, " packet-loss %g\n", iflp->pkt_loss);
4090 if (IS_PARAM_SET(iflp, LP_AVA_BW))
4091 vty_out(vty, " ava-bw %g\n", iflp->ava_bw);
4092 if (IS_PARAM_SET(iflp, LP_RES_BW))
4093 vty_out(vty, " res-bw %g\n", iflp->res_bw);
4094 if (IS_PARAM_SET(iflp, LP_USE_BW))
4095 vty_out(vty, " use-bw %g\n", iflp->use_bw);
4096 if (IS_PARAM_SET(iflp, LP_RMT_AS))
9bcef951 4097 vty_out(vty, " neighbor %pI4 as %u\n", &iflp->rmt_ip,
d62a17ae 4098 iflp->rmt_as);
07679ad9 4099 vty_out(vty, " exit-link-params\n");
d62a17ae 4100 return 0;
4101}
4102
4103static int if_config_write(struct vty *vty)
4104{
7fe96307 4105 struct vrf *vrf0;
d62a17ae 4106 struct interface *ifp;
4107
4108 zebra_ptm_write(vty);
4109
7fe96307
A
4110 RB_FOREACH (vrf0, vrf_name_head, &vrfs_by_name)
4111 FOR_ALL_INTERFACES (vrf0, ifp) {
a2addae8
RW
4112 struct zebra_if *if_data;
4113 struct listnode *addrnode;
4114 struct connected *ifc;
4115 struct prefix *p;
4116 struct vrf *vrf;
d62a17ae 4117
a2addae8 4118 if_data = ifp->info;
a36898e7 4119 vrf = vrf_lookup_by_id(ifp->vrf_id);
d62a17ae 4120
a36898e7 4121 if (ifp->vrf_id == VRF_DEFAULT)
a2addae8
RW
4122 vty_frame(vty, "interface %s\n", ifp->name);
4123 else
4124 vty_frame(vty, "interface %s vrf %s\n",
4125 ifp->name, vrf->name);
d62a17ae 4126
a2addae8
RW
4127 if (if_data) {
4128 if (if_data->shutdown == IF_ZEBRA_SHUTDOWN_ON)
4129 vty_out(vty, " shutdown\n");
d62a17ae 4130
a2addae8
RW
4131 zebra_ptm_if_write(vty, if_data);
4132 }
bfac8dcd 4133
a2addae8
RW
4134 if (ifp->desc)
4135 vty_out(vty, " description %s\n", ifp->desc);
4136
4137 /* Assign bandwidth here to avoid unnecessary interface
4138 flap
4139 while processing config script */
4140 if (ifp->bandwidth != 0)
4141 vty_out(vty, " bandwidth %u\n", ifp->bandwidth);
4142
4143 if (!CHECK_FLAG(ifp->status,
4144 ZEBRA_INTERFACE_LINKDETECTION))
4145 vty_out(vty, " no link-detect\n");
4146
4147 for (ALL_LIST_ELEMENTS_RO(ifp->connected, addrnode,
4148 ifc)) {
4149 if (CHECK_FLAG(ifc->conf,
4150 ZEBRA_IFC_CONFIGURED)) {
4151 char buf[INET6_ADDRSTRLEN];
4152 p = ifc->address;
4153 vty_out(vty, " ip%s address %s",
4154 p->family == AF_INET ? ""
4155 : "v6",
a07df329 4156 inet_ntop(p->family,
60466a63
QY
4157 &p->u.prefix, buf,
4158 sizeof(buf)));
a2addae8
RW
4159 if (CONNECTED_PEER(ifc)) {
4160 p = ifc->destination;
4161 vty_out(vty, " peer %s",
4162 inet_ntop(p->family,
4163 &p->u.prefix,
4164 buf,
4165 sizeof(buf)));
4166 }
4167 vty_out(vty, "/%d", p->prefixlen);
718e3744 4168
a2addae8
RW
4169 if (ifc->label)
4170 vty_out(vty, " label %s",
4171 ifc->label);
718e3744 4172
a2addae8
RW
4173 vty_out(vty, "\n");
4174 }
d62a17ae 4175 }
718e3744 4176
a2addae8
RW
4177 if (if_data) {
4178 if (if_data->multicast
4179 != IF_ZEBRA_MULTICAST_UNSPEC)
4180 vty_out(vty, " %smulticast\n",
4181 if_data->multicast
4182 == IF_ZEBRA_MULTICAST_ON
4183 ? ""
4184 : "no ");
4185 }
718e3744 4186
a2addae8 4187 hook_call(zebra_if_config_wr, vty, ifp);
ce5160c0 4188 zebra_evpn_mh_if_write(vty, ifp);
a2addae8 4189 link_params_config_write(vty, ifp);
16f1b9ee 4190
07679ad9 4191 vty_endframe(vty, "exit\n!\n");
a2addae8 4192 }
d62a17ae 4193 return 0;
718e3744 4194}
4195
4196/* Allocate and initialize interface vector. */
d62a17ae 4197void zebra_if_init(void)
4198{
4199 /* Initialize interface and new hook. */
ce19a04a
DL
4200 hook_register_prio(if_add, 0, if_zebra_new_hook);
4201 hook_register_prio(if_del, 0, if_zebra_delete_hook);
d62a17ae 4202
4203 /* Install configuration write function. */
9da01b0b 4204 if_cmd_init(if_config_write);
612c2c15 4205 install_node(&link_params_node);
138c5a74
DS
4206 /*
4207 * This is *intentionally* setting this to NULL, signaling
4208 * that interface creation for zebra acts differently
4209 */
4210 if_zapi_callbacks(NULL, NULL, NULL, NULL);
d62a17ae 4211
4212 install_element(VIEW_NODE, &show_interface_cmd);
4213 install_element(VIEW_NODE, &show_interface_vrf_all_cmd);
4214 install_element(VIEW_NODE, &show_interface_name_vrf_cmd);
4215 install_element(VIEW_NODE, &show_interface_name_vrf_all_cmd);
4216
4217 install_element(ENABLE_NODE, &show_interface_desc_cmd);
4218 install_element(ENABLE_NODE, &show_interface_desc_vrf_all_cmd);
4219 install_element(INTERFACE_NODE, &multicast_cmd);
4220 install_element(INTERFACE_NODE, &no_multicast_cmd);
4221 install_element(INTERFACE_NODE, &linkdetect_cmd);
4222 install_element(INTERFACE_NODE, &no_linkdetect_cmd);
4223 install_element(INTERFACE_NODE, &shutdown_if_cmd);
4224 install_element(INTERFACE_NODE, &no_shutdown_if_cmd);
4225 install_element(INTERFACE_NODE, &bandwidth_if_cmd);
4226 install_element(INTERFACE_NODE, &no_bandwidth_if_cmd);
4227 install_element(INTERFACE_NODE, &ip_address_cmd);
4228 install_element(INTERFACE_NODE, &no_ip_address_cmd);
a07df329
DL
4229 install_element(INTERFACE_NODE, &ip_address_peer_cmd);
4230 install_element(INTERFACE_NODE, &no_ip_address_peer_cmd);
d62a17ae 4231 install_element(INTERFACE_NODE, &ipv6_address_cmd);
4232 install_element(INTERFACE_NODE, &no_ipv6_address_cmd);
718e3744 4233#ifdef HAVE_NETLINK
d62a17ae 4234 install_element(INTERFACE_NODE, &ip_address_label_cmd);
4235 install_element(INTERFACE_NODE, &no_ip_address_label_cmd);
718e3744 4236#endif /* HAVE_NETLINK */
d62a17ae 4237 install_element(INTERFACE_NODE, &link_params_cmd);
4238 install_default(LINK_PARAMS_NODE);
4239 install_element(LINK_PARAMS_NODE, &link_params_enable_cmd);
4240 install_element(LINK_PARAMS_NODE, &no_link_params_enable_cmd);
4241 install_element(LINK_PARAMS_NODE, &link_params_metric_cmd);
4242 install_element(LINK_PARAMS_NODE, &no_link_params_metric_cmd);
4243 install_element(LINK_PARAMS_NODE, &link_params_maxbw_cmd);
4244 install_element(LINK_PARAMS_NODE, &link_params_max_rsv_bw_cmd);
4245 install_element(LINK_PARAMS_NODE, &link_params_unrsv_bw_cmd);
4246 install_element(LINK_PARAMS_NODE, &link_params_admin_grp_cmd);
4247 install_element(LINK_PARAMS_NODE, &no_link_params_admin_grp_cmd);
4248 install_element(LINK_PARAMS_NODE, &link_params_inter_as_cmd);
4249 install_element(LINK_PARAMS_NODE, &no_link_params_inter_as_cmd);
4250 install_element(LINK_PARAMS_NODE, &link_params_delay_cmd);
4251 install_element(LINK_PARAMS_NODE, &no_link_params_delay_cmd);
4252 install_element(LINK_PARAMS_NODE, &link_params_delay_var_cmd);
4253 install_element(LINK_PARAMS_NODE, &no_link_params_delay_var_cmd);
4254 install_element(LINK_PARAMS_NODE, &link_params_pkt_loss_cmd);
4255 install_element(LINK_PARAMS_NODE, &no_link_params_pkt_loss_cmd);
4256 install_element(LINK_PARAMS_NODE, &link_params_ava_bw_cmd);
4257 install_element(LINK_PARAMS_NODE, &no_link_params_ava_bw_cmd);
4258 install_element(LINK_PARAMS_NODE, &link_params_res_bw_cmd);
4259 install_element(LINK_PARAMS_NODE, &no_link_params_res_bw_cmd);
4260 install_element(LINK_PARAMS_NODE, &link_params_use_bw_cmd);
4261 install_element(LINK_PARAMS_NODE, &no_link_params_use_bw_cmd);
4262 install_element(LINK_PARAMS_NODE, &exit_link_params_cmd);
ce5160c0
AK
4263
4264 /* setup EVPN MH elements */
4265 zebra_evpn_interface_init();
718e3744 4266}