]> git.proxmox.com Git - mirror_frr.git/blame - zebra/interface.c
Merge pull request #8317 from mjstapp/fix_short_printfrr_buf
[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 */
2b6aabe0 901 kernel_neigh_update(0, ifp->ifindex, ipv4_ll.s_addr, mac, 6, ns_id);
d1479ec8 902
2b6aabe0
QY
903 /* Add new neighbor entry.
904 *
905 * We force installation even if current neighbor entry is the same.
906 * Since this function is used to refresh our MAC entries after an
907 * interface flap, if we don't force in our custom entries with their
908 * state set to PERMANENT or REACHABLE then the kernel will attempt to
909 * resolve our leftover entries, fail, mark them unreachable and then
910 * they'll be useless to us.
911 */
912 if (add)
913 kernel_neigh_update(add, ifp->ifindex, ipv4_ll.s_addr, mac, 6,
914 ns_id);
d1479ec8 915
ee98d1f1 916 memcpy(&zif->neigh_mac[0], &mac[0], 6);
20089ae2
DS
917
918 /*
919 * We need to note whether or not we originated a v6
920 * neighbor entry for this interface. So that when
921 * someone unwisely accidently deletes this entry
922 * we can shove it back in.
923 */
924 zif->v6_2_v4_ll_neigh_entry = !!add;
925 memcpy(&zif->v6_2_v4_ll_addr6, address, sizeof(*address));
926
d62a17ae 927 zvrf->neigh_updates++;
5c610faf
DS
928}
929
ee98d1f1
DS
930void if_nbr_ipv6ll_to_ipv4ll_neigh_update(struct interface *ifp,
931 struct in6_addr *address, int add)
932{
933
934 char mac[6];
935
936 ipv6_ll_address_to_mac(address, (uint8_t *)mac);
937 if_nbr_mac_to_ipv4ll_neigh_update(ifp, mac, address, add);
938}
939
d62a17ae 940static void if_nbr_ipv6ll_to_ipv4ll_neigh_add_all(struct interface *ifp)
5c610faf 941{
d62a17ae 942 if (listhead(ifp->nbr_connected)) {
943 struct nbr_connected *nbr_connected;
944 struct listnode *node;
5c610faf 945
d62a17ae 946 for (ALL_LIST_ELEMENTS_RO(ifp->nbr_connected, node,
947 nbr_connected))
948 if_nbr_ipv6ll_to_ipv4ll_neigh_update(
949 ifp, &nbr_connected->address->u.prefix6, 1);
950 }
5c610faf
DS
951}
952
d62a17ae 953void if_nbr_ipv6ll_to_ipv4ll_neigh_del_all(struct interface *ifp)
5c610faf 954{
d62a17ae 955 if (listhead(ifp->nbr_connected)) {
956 struct nbr_connected *nbr_connected;
957 struct listnode *node;
5c610faf 958
d62a17ae 959 for (ALL_LIST_ELEMENTS_RO(ifp->nbr_connected, node,
960 nbr_connected))
961 if_nbr_ipv6ll_to_ipv4ll_neigh_update(
962 ifp, &nbr_connected->address->u.prefix6, 0);
963 }
5c610faf
DS
964}
965
d62a17ae 966static void if_down_del_nbr_connected(struct interface *ifp)
a197c47c 967{
d62a17ae 968 struct nbr_connected *nbr_connected;
969 struct listnode *node, *nnode;
a197c47c 970
d62a17ae 971 for (ALL_LIST_ELEMENTS(ifp->nbr_connected, node, nnode,
972 nbr_connected)) {
973 listnode_delete(ifp->nbr_connected, nbr_connected);
974 nbr_connected_free(nbr_connected);
975 }
a197c47c
DS
976}
977
fe593b78 978void if_nhg_dependents_add(struct interface *ifp, struct nhg_hash_entry *nhe)
602fea61 979{
fe593b78
SW
980 if (ifp->info) {
981 struct zebra_if *zif = (struct zebra_if *)ifp->info;
602fea61 982
37c6708b 983 nhg_connected_tree_add_nhe(&zif->nhg_dependents, nhe);
fe593b78
SW
984 }
985}
602fea61 986
fe593b78
SW
987void if_nhg_dependents_del(struct interface *ifp, struct nhg_hash_entry *nhe)
988{
989 if (ifp->info) {
990 struct zebra_if *zif = (struct zebra_if *)ifp->info;
602fea61 991
37c6708b 992 nhg_connected_tree_del_nhe(&zif->nhg_dependents, nhe);
fe593b78 993 }
602fea61
SW
994}
995
fe593b78 996unsigned int if_nhg_dependents_count(const struct interface *ifp)
602fea61 997{
fe593b78
SW
998 if (ifp->info) {
999 struct zebra_if *zif = (struct zebra_if *)ifp->info;
1000
37c6708b 1001 return nhg_connected_tree_count(&zif->nhg_dependents);
fe593b78
SW
1002 }
1003
1004 return 0;
1005}
1006
1007
1008bool if_nhg_dependents_is_empty(const struct interface *ifp)
1009{
1010 if (ifp->info) {
1011 struct zebra_if *zif = (struct zebra_if *)ifp->info;
1012
37c6708b 1013 return nhg_connected_tree_is_empty(&zif->nhg_dependents);
fe593b78
SW
1014 }
1015
1016 return false;
602fea61
SW
1017}
1018
718e3744 1019/* Interface is up. */
d62a17ae 1020void if_up(struct interface *ifp)
1021{
1022 struct zebra_if *zif;
1023 struct interface *link_if;
a36898e7 1024 struct zebra_vrf *zvrf = vrf_info_lookup(ifp->vrf_id);
d62a17ae 1025
1026 zif = ifp->info;
1027 zif->up_count++;
1028 quagga_timestamp(2, zif->up_last, sizeof(zif->up_last));
1029
1030 /* Notify the protocol daemons. */
1031 if (ifp->ptm_enable && (ifp->ptm_status == ZEBRA_PTM_STATUS_DOWN)) {
e914ccbe 1032 flog_warn(EC_ZEBRA_PTM_NOT_READY,
1d5453d6 1033 "%s: interface %s hasn't passed ptm check",
d62a17ae 1034 __func__, ifp->name);
1035 return;
1036 }
1037 zebra_interface_up_update(ifp);
1038
1039 if_nbr_ipv6ll_to_ipv4ll_neigh_add_all(ifp);
1040
1041#if defined(HAVE_RTADV)
1042 /* Enable fast tx of RA if enabled && RA interval is not in msecs */
1043 if (zif->rtadv.AdvSendAdvertisements
adee8f21
DS
1044 && (zif->rtadv.MaxRtrAdvInterval >= 1000)
1045 && zif->rtadv.UseFastRexmit) {
d62a17ae 1046 zif->rtadv.inFastRexmit = 1;
1047 zif->rtadv.NumFastReXmitsRemain = RTADV_NUM_FAST_REXMITS;
1048 }
9c3bf1ce 1049#endif
6c9678b4 1050
d62a17ae 1051 /* Install connected routes to the kernel. */
1052 if_install_connected(ifp);
1053
d62a17ae 1054 /* Handle interface up for specific types for EVPN. Non-VxLAN interfaces
1055 * are checked to see if (remote) neighbor entries need to be installed
1056 * on them for ARP suppression.
1057 */
1058 if (IS_ZEBRA_IF_VXLAN(ifp))
1059 zebra_vxlan_if_up(ifp);
1060 else if (IS_ZEBRA_IF_BRIDGE(ifp)) {
1061 link_if = ifp;
1062 zebra_vxlan_svi_up(ifp, link_if);
1063 } else if (IS_ZEBRA_IF_VLAN(ifp)) {
154a3944 1064 link_if = if_lookup_by_index_per_ns(zvrf->zns,
71349e03 1065 zif->link_ifindex);
d62a17ae 1066 if (link_if)
1067 zebra_vxlan_svi_up(ifp, link_if);
0056f687
CS
1068 } else if (IS_ZEBRA_IF_MACVLAN(ifp))
1069 zebra_vxlan_macvlan_up(ifp);
1070
ce5160c0
AK
1071 if (zif->es_info.es)
1072 zebra_evpn_es_if_oper_state_change(zif, true /*up*/);
c36e442c
AK
1073
1074 if (zif->flags & ZIF_FLAG_EVPN_MH_UPLINK)
1075 zebra_evpn_mh_uplink_oper_update(zif);
718e3744 1076}
1077
1078/* Interface goes down. We have to manage different behavior of based
1079 OS. */
d62a17ae 1080void if_down(struct interface *ifp)
1081{
1082 struct zebra_if *zif;
1083 struct interface *link_if;
a36898e7 1084 struct zebra_vrf *zvrf = vrf_info_lookup(ifp->vrf_id);
d62a17ae 1085
1086 zif = ifp->info;
1087 zif->down_count++;
1088 quagga_timestamp(2, zif->down_last, sizeof(zif->down_last));
1089
f862383f
SW
1090 if_down_nhg_dependents(ifp);
1091
d62a17ae 1092 /* Handle interface down for specific types for EVPN. Non-VxLAN
1093 * interfaces
1094 * are checked to see if (remote) neighbor entries need to be purged
1095 * for ARP suppression.
1096 */
1097 if (IS_ZEBRA_IF_VXLAN(ifp))
1098 zebra_vxlan_if_down(ifp);
1099 else if (IS_ZEBRA_IF_BRIDGE(ifp)) {
1100 link_if = ifp;
1101 zebra_vxlan_svi_down(ifp, link_if);
1102 } else if (IS_ZEBRA_IF_VLAN(ifp)) {
154a3944 1103 link_if = if_lookup_by_index_per_ns(zvrf->zns,
71349e03 1104 zif->link_ifindex);
d62a17ae 1105 if (link_if)
1106 zebra_vxlan_svi_down(ifp, link_if);
0056f687
CS
1107 } else if (IS_ZEBRA_IF_MACVLAN(ifp))
1108 zebra_vxlan_macvlan_down(ifp);
2232a77c 1109
ce5160c0
AK
1110 if (zif->es_info.es)
1111 zebra_evpn_es_if_oper_state_change(zif, false /*up*/);
13d60d35 1112
c36e442c
AK
1113 if (zif->flags & ZIF_FLAG_EVPN_MH_UPLINK)
1114 zebra_evpn_mh_uplink_oper_update(zif);
1115
d62a17ae 1116 /* Notify to the protocol daemons. */
1117 zebra_interface_down_update(ifp);
718e3744 1118
d62a17ae 1119 /* Uninstall connected routes from the kernel. */
1120 if_uninstall_connected(ifp);
718e3744 1121
d62a17ae 1122 if_nbr_ipv6ll_to_ipv4ll_neigh_del_all(ifp);
a197c47c 1123
d62a17ae 1124 /* Delete all neighbor addresses learnt through IPv6 RA */
1125 if_down_del_nbr_connected(ifp);
718e3744 1126}
1127
d62a17ae 1128void if_refresh(struct interface *ifp)
718e3744 1129{
d62a17ae 1130 if_get_flags(ifp);
718e3744 1131}
1132
680c278f
PG
1133void zebra_if_update_link(struct interface *ifp, ifindex_t link_ifindex,
1134 ns_id_t ns_id)
6675513d 1135{
d62a17ae 1136 struct zebra_if *zif;
6675513d 1137
0e4864ea
PG
1138 if (IS_ZEBRA_IF_VETH(ifp))
1139 return;
d62a17ae 1140 zif = (struct zebra_if *)ifp->info;
1141 zif->link_ifindex = link_ifindex;
680c278f 1142 zif->link = if_lookup_by_index_per_ns(zebra_ns_lookup(ns_id),
d62a17ae 1143 link_ifindex);
6675513d 1144}
1145
98efddf1
DS
1146/*
1147 * during initial link dump kernel does not order lower devices before
1148 * upper devices so we need to fixup link dependencies at the end of dump
1149 */
520ebf72
AK
1150void zebra_if_update_all_links(void)
1151{
1152 struct route_node *rn;
1153 struct interface *ifp;
1154 struct zebra_if *zif;
1155 struct zebra_ns *ns;
1156
1157 if (IS_ZEBRA_DEBUG_KERNEL)
1158 zlog_info("fixup link dependencies");
1159
1160 ns = zebra_ns_lookup(NS_DEFAULT);
1161 for (rn = route_top(ns->if_table); rn; rn = route_next(rn)) {
1162 ifp = (struct interface *)rn->info;
1163 if (!ifp)
1164 continue;
1165 zif = ifp->info;
c36e442c
AK
1166 /* update bond-member to bond linkages */
1167 if ((IS_ZEBRA_IF_BOND_SLAVE(ifp))
1168 && (zif->bondslave_info.bond_ifindex != IFINDEX_INTERNAL)
1169 && !zif->bondslave_info.bond_if) {
1170 if (IS_ZEBRA_DEBUG_EVPN_MH_ES || IS_ZEBRA_DEBUG_KERNEL)
1171 zlog_debug("bond mbr %s map to bond %d",
1172 zif->ifp->name,
1173 zif->bondslave_info.bond_ifindex);
1174 zebra_l2_map_slave_to_bond(zif, ifp->vrf_id);
1175 }
1176
1177 /* update SVI linkages */
520ebf72
AK
1178 if ((zif->link_ifindex != IFINDEX_INTERNAL) && !zif->link) {
1179 zif->link = if_lookup_by_index_per_ns(ns,
1180 zif->link_ifindex);
1181 if (IS_ZEBRA_DEBUG_KERNEL)
1182 zlog_debug("interface %s/%d's lower fixup to %s/%d",
1183 ifp->name, ifp->ifindex,
1184 zif->link?zif->link->name:"unk",
1185 zif->link_ifindex);
1186 }
243b74ed
AK
1187
1188 /* Update VLAN<=>SVI map */
1189 if (IS_ZEBRA_IF_VLAN(ifp))
1190 zebra_evpn_acc_bd_svi_set(zif, NULL,
1191 !!if_is_operative(ifp));
520ebf72
AK
1192 }
1193}
1194
c3bd894e
QY
1195void zebra_if_set_protodown(struct interface *ifp, bool down)
1196{
d8d78e2c 1197#ifdef HAVE_NETLINK
c3bd894e 1198 netlink_protodown(ifp, down);
d8d78e2c
QY
1199#else
1200 zlog_warn("Protodown is not supported on this platform");
1201#endif
c3bd894e 1202}
d5a5c8f0 1203
718e3744 1204/* Output prefix string to vty. */
d62a17ae 1205static int prefix_vty_out(struct vty *vty, struct prefix *p)
718e3744 1206{
d62a17ae 1207 char str[INET6_ADDRSTRLEN];
718e3744 1208
d62a17ae 1209 inet_ntop(p->family, &p->u.prefix, str, sizeof(str));
1210 vty_out(vty, "%s", str);
1211 return strlen(str);
718e3744 1212}
1213
1214/* Dump if address information to vty. */
d62a17ae 1215static void connected_dump_vty(struct vty *vty, struct connected *connected)
718e3744 1216{
d62a17ae 1217 struct prefix *p;
718e3744 1218
d62a17ae 1219 /* Print interface address. */
1220 p = connected->address;
1221 vty_out(vty, " %s ", prefix_family_str(p));
1222 prefix_vty_out(vty, p);
1223 vty_out(vty, "/%d", p->prefixlen);
718e3744 1224
d62a17ae 1225 /* If there is destination address, print it. */
0f3af738
JW
1226 if (CONNECTED_PEER(connected) && connected->destination) {
1227 vty_out(vty, " peer ");
d62a17ae 1228 prefix_vty_out(vty, connected->destination);
0f3af738 1229 vty_out(vty, "/%d", connected->destination->prefixlen);
d62a17ae 1230 }
718e3744 1231
d62a17ae 1232 if (CHECK_FLAG(connected->flags, ZEBRA_IFA_SECONDARY))
1233 vty_out(vty, " secondary");
718e3744 1234
d62a17ae 1235 if (CHECK_FLAG(connected->flags, ZEBRA_IFA_UNNUMBERED))
1236 vty_out(vty, " unnumbered");
525c1839 1237
d62a17ae 1238 if (connected->label)
1239 vty_out(vty, " %s", connected->label);
718e3744 1240
d62a17ae 1241 vty_out(vty, "\n");
718e3744 1242}
1243
a80beece 1244/* Dump interface neighbor address information to vty. */
d62a17ae 1245static void nbr_connected_dump_vty(struct vty *vty,
1246 struct nbr_connected *connected)
a80beece 1247{
d62a17ae 1248 struct prefix *p;
a80beece 1249
d62a17ae 1250 /* Print interface address. */
1251 p = connected->address;
1252 vty_out(vty, " %s ", prefix_family_str(p));
1253 prefix_vty_out(vty, p);
1254 vty_out(vty, "/%d", p->prefixlen);
a80beece 1255
d62a17ae 1256 vty_out(vty, "\n");
a80beece
DS
1257}
1258
d0738ba2
PG
1259static const char *zebra_zifslavetype_2str(zebra_slave_iftype_t zif_slave_type)
1260{
1261 switch (zif_slave_type) {
1262 case ZEBRA_IF_SLAVE_BRIDGE:
1263 return "Bridge";
1264 case ZEBRA_IF_SLAVE_VRF:
1265 return "Vrf";
1266 case ZEBRA_IF_SLAVE_BOND:
1267 return "Bond";
1268 case ZEBRA_IF_SLAVE_OTHER:
1269 return "Other";
1270 case ZEBRA_IF_SLAVE_NONE:
1271 return "None";
1272 }
1273 return "None";
1274}
1275
d62a17ae 1276static const char *zebra_ziftype_2str(zebra_iftype_t zif_type)
6675513d 1277{
d62a17ae 1278 switch (zif_type) {
1279 case ZEBRA_IF_OTHER:
1280 return "Other";
6675513d 1281
d62a17ae 1282 case ZEBRA_IF_BRIDGE:
1283 return "Bridge";
6675513d 1284
d62a17ae 1285 case ZEBRA_IF_VLAN:
1286 return "Vlan";
6675513d 1287
d62a17ae 1288 case ZEBRA_IF_VXLAN:
1289 return "Vxlan";
6675513d 1290
d62a17ae 1291 case ZEBRA_IF_VRF:
1292 return "VRF";
6675513d 1293
0e4864ea
PG
1294 case ZEBRA_IF_VETH:
1295 return "VETH";
0e4864ea 1296
b9368db9
DD
1297 case ZEBRA_IF_BOND:
1298 return "bond";
1299
1300 case ZEBRA_IF_BOND_SLAVE:
1301 return "bond_slave";
1302
1303 case ZEBRA_IF_MACVLAN:
1304 return "macvlan";
1305
d62a17ae 1306 default:
1307 return "Unknown";
d62a17ae 1308 }
6675513d 1309}
1310
49548752
NS
1311/* Interface's brief information print out to vty interface. */
1312static void ifs_dump_brief_vty(struct vty *vty, struct vrf *vrf)
1313{
1314 struct connected *connected;
1315 struct listnode *node;
1316 struct route_node *rn;
1317 struct zebra_if *zebra_if;
1318 struct prefix *p;
1319 struct interface *ifp;
1320 bool print_header = true;
1321
1322 FOR_ALL_INTERFACES (vrf, ifp) {
49548752
NS
1323 bool first_pfx_printed = false;
1324
1325 if (print_header) {
1326 vty_out(vty, "%-16s%-8s%-16s%s\n", "Interface",
1327 "Status", "VRF", "Addresses");
1328 vty_out(vty, "%-16s%-8s%-16s%s\n", "---------",
1329 "------", "---", "---------");
1330 print_header = false; /* We have at least 1 iface */
1331 }
1332 zebra_if = ifp->info;
1333
1334 vty_out(vty, "%-16s", ifp->name);
1335
1336 if (if_is_up(ifp))
1337 vty_out(vty, "%-8s", "up");
1338 else
1339 vty_out(vty, "%-8s", "down");
1340
1341 vty_out(vty, "%-16s", vrf->name);
1342
1343 for (rn = route_top(zebra_if->ipv4_subnets); rn;
1344 rn = route_next(rn)) {
1345 if (!rn->info)
1346 continue;
1347 uint32_t list_size = listcount((struct list *)rn->info);
1348
1349 for (ALL_LIST_ELEMENTS_RO((struct list *)rn->info, node,
1350 connected)) {
1351 if (!CHECK_FLAG(connected->flags,
1352 ZEBRA_IFA_SECONDARY)) {
1353 p = connected->address;
49548752 1354 if (first_pfx_printed) {
2dbe669b
DA
1355 /* padding to prepare row only
1356 * for ip addr */
49548752
NS
1357 vty_out(vty, "%-40s", "");
1358 if (list_size > 1)
1359 vty_out(vty, "+ ");
2dbe669b 1360 vty_out(vty, "%pFX\n", p);
49548752
NS
1361 } else {
1362 if (list_size > 1)
1363 vty_out(vty, "+ ");
2dbe669b 1364 vty_out(vty, "%pFX\n", p);
49548752
NS
1365 }
1366 first_pfx_printed = true;
1367 break;
1368 }
1369 }
1370 }
1371
1372 uint32_t v6_list_size = 0;
1373 for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, connected)) {
1374 if (CHECK_FLAG(connected->conf, ZEBRA_IFC_REAL)
1375 && (connected->address->family == AF_INET6))
1376 v6_list_size++;
1377 }
1378 for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, connected)) {
1379 if (CHECK_FLAG(connected->conf, ZEBRA_IFC_REAL)
1380 && !CHECK_FLAG(connected->flags,
1381 ZEBRA_IFA_SECONDARY)
1382 && (connected->address->family == AF_INET6)) {
1383 p = connected->address;
1384 /* Don't print link local pfx */
1385 if (!IN6_IS_ADDR_LINKLOCAL(&p->u.prefix6)) {
49548752 1386 if (first_pfx_printed) {
2dbe669b
DA
1387 /* padding to prepare row only
1388 * for ip addr */
49548752
NS
1389 vty_out(vty, "%-40s", "");
1390 if (v6_list_size > 1)
1391 vty_out(vty, "+ ");
2dbe669b 1392 vty_out(vty, "%pFX\n", p);
49548752
NS
1393 } else {
1394 if (v6_list_size > 1)
1395 vty_out(vty, "+ ");
2dbe669b 1396 vty_out(vty, "%pFX\n", p);
49548752
NS
1397 }
1398 first_pfx_printed = true;
1399 break;
1400 }
1401 }
1402 }
1403 if (!first_pfx_printed)
1404 vty_out(vty, "\n");
1405 }
1406 vty_out(vty, "\n");
1407}
1408
904e9b05
MS
1409const char *zebra_protodown_rc_str(enum protodown_reasons protodown_rc,
1410 char *pd_buf, uint32_t pd_buf_len)
c36e442c
AK
1411{
1412 bool first = true;
1413
1414 pd_buf[0] = '\0';
1415
904e9b05 1416 strlcat(pd_buf, "(", pd_buf_len);
c36e442c
AK
1417
1418 if (protodown_rc & ZEBRA_PROTODOWN_EVPN_STARTUP_DELAY) {
1419 if (first)
1420 first = false;
1421 else
904e9b05
MS
1422 strlcat(pd_buf, ",", pd_buf_len);
1423 strlcat(pd_buf, "startup-delay", pd_buf_len);
c36e442c
AK
1424 }
1425
1426 if (protodown_rc & ZEBRA_PROTODOWN_EVPN_UPLINK_DOWN) {
904e9b05
MS
1427 if (!first)
1428 strlcat(pd_buf, ",", pd_buf_len);
1429 strlcat(pd_buf, "uplinks-down", pd_buf_len);
c36e442c
AK
1430 }
1431
904e9b05 1432 strlcat(pd_buf, ")", pd_buf_len);
c36e442c
AK
1433
1434 return pd_buf;
1435}
1436
26ba45e3
AK
1437static inline bool if_is_protodown_applicable(struct interface *ifp)
1438{
1439 if (IS_ZEBRA_IF_BOND(ifp))
1440 return false;
1441
1442 return true;
1443}
1444
718e3744 1445/* Interface's information print out to vty interface. */
d62a17ae 1446static void if_dump_vty(struct vty *vty, struct interface *ifp)
1447{
1448 struct connected *connected;
1449 struct nbr_connected *nbr_connected;
1450 struct listnode *node;
1451 struct route_node *rn;
1452 struct zebra_if *zebra_if;
1453 struct vrf *vrf;
c36e442c 1454 char pd_buf[ZEBRA_PROTODOWN_RC_STR_LEN];
d62a17ae 1455
1456 zebra_if = ifp->info;
1457
1458 vty_out(vty, "Interface %s is ", ifp->name);
1459 if (if_is_up(ifp)) {
1460 vty_out(vty, "up, line protocol ");
1461
1462 if (CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_LINKDETECTION)) {
1463 if (if_is_running(ifp))
1464 vty_out(vty, "is up\n");
1465 else
1466 vty_out(vty, "is down\n");
1467 } else {
1468 vty_out(vty, "detection is disabled\n");
1469 }
1470 } else {
1471 vty_out(vty, "down\n");
1472 }
1473
1474 vty_out(vty, " Link ups: %5u last: %s\n", zebra_if->up_count,
1475 zebra_if->up_last[0] ? zebra_if->up_last : "(never)");
1476 vty_out(vty, " Link downs: %5u last: %s\n", zebra_if->down_count,
1477 zebra_if->down_last[0] ? zebra_if->down_last : "(never)");
1478
1479 zebra_ptm_show_status(vty, ifp);
1480
a36898e7 1481 vrf = vrf_lookup_by_id(ifp->vrf_id);
d62a17ae 1482 vty_out(vty, " vrf: %s\n", vrf->name);
1483
1484 if (ifp->desc)
1485 vty_out(vty, " Description: %s\n", ifp->desc);
ba5165ec
DS
1486 if (zebra_if->desc)
1487 vty_out(vty, " OS Description: %s\n", zebra_if->desc);
1488
d62a17ae 1489 if (ifp->ifindex == IFINDEX_INTERNAL) {
1490 vty_out(vty, " pseudo interface\n");
1491 return;
1492 } else if (!CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE)) {
1493 vty_out(vty, " index %d inactive interface\n", ifp->ifindex);
1494 return;
1495 }
1496
1497 vty_out(vty, " index %d metric %d mtu %d speed %u ", ifp->ifindex,
1498 ifp->metric, ifp->mtu, ifp->speed);
1499 if (ifp->mtu6 != ifp->mtu)
1500 vty_out(vty, "mtu6 %d ", ifp->mtu6);
1501 vty_out(vty, "\n flags: %s\n", if_flag_dump(ifp->flags));
1502
1503 /* Hardware address. */
1504 vty_out(vty, " Type: %s\n", if_link_type_str(ifp->ll_type));
1505 if (ifp->hw_addr_len != 0) {
1506 int i;
1507
1508 vty_out(vty, " HWaddr: ");
1509 for (i = 0; i < ifp->hw_addr_len; i++)
1510 vty_out(vty, "%s%02x", i == 0 ? "" : ":",
1511 ifp->hw_addr[i]);
1512 vty_out(vty, "\n");
1513 }
1514
1515 /* Bandwidth in Mbps */
1516 if (ifp->bandwidth != 0) {
1517 vty_out(vty, " bandwidth %u Mbps", ifp->bandwidth);
1518 vty_out(vty, "\n");
1519 }
1520
1521 for (rn = route_top(zebra_if->ipv4_subnets); rn; rn = route_next(rn)) {
1522 if (!rn->info)
1523 continue;
1524
1525 for (ALL_LIST_ELEMENTS_RO((struct list *)rn->info, node,
1526 connected))
1527 connected_dump_vty(vty, connected);
1528 }
1529
1530 for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, connected)) {
1531 if (CHECK_FLAG(connected->conf, ZEBRA_IFC_REAL)
1532 && (connected->address->family == AF_INET6))
1533 connected_dump_vty(vty, connected);
1534 }
1535
1536 vty_out(vty, " Interface Type %s\n",
1537 zebra_ziftype_2str(zebra_if->zif_type));
d0738ba2
PG
1538 vty_out(vty, " Interface Slave Type %s\n",
1539 zebra_zifslavetype_2str(zebra_if->zif_slave_type));
1540
d62a17ae 1541 if (IS_ZEBRA_IF_BRIDGE(ifp)) {
1542 struct zebra_l2info_bridge *bridge_info;
1543
1544 bridge_info = &zebra_if->l2info.br;
1545 vty_out(vty, " Bridge VLAN-aware: %s\n",
1546 bridge_info->vlan_aware ? "yes" : "no");
1547 } else if (IS_ZEBRA_IF_VLAN(ifp)) {
1548 struct zebra_l2info_vlan *vlan_info;
1549
1550 vlan_info = &zebra_if->l2info.vl;
1551 vty_out(vty, " VLAN Id %u\n", vlan_info->vid);
1552 } else if (IS_ZEBRA_IF_VXLAN(ifp)) {
1553 struct zebra_l2info_vxlan *vxlan_info;
1554
1555 vxlan_info = &zebra_if->l2info.vxl;
1556 vty_out(vty, " VxLAN Id %u", vxlan_info->vni);
1557 if (vxlan_info->vtep_ip.s_addr != INADDR_ANY)
9bcef951
MS
1558 vty_out(vty, " VTEP IP: %pI4",
1559 &vxlan_info->vtep_ip);
d62a17ae 1560 if (vxlan_info->access_vlan)
aa0677b4 1561 vty_out(vty, " Access VLAN Id %u\n",
d62a17ae 1562 vxlan_info->access_vlan);
d7fe235c 1563 if (vxlan_info->mcast_grp.s_addr != INADDR_ANY)
9bcef951
MS
1564 vty_out(vty, " Mcast Group %pI4",
1565 &vxlan_info->mcast_grp);
14ddb3d9
PG
1566 if (vxlan_info->ifindex_link &&
1567 (vxlan_info->link_nsid != NS_UNKNOWN)) {
1568 struct interface *ifp;
1569
1570 ifp = if_lookup_by_index_per_ns(
1571 zebra_ns_lookup(vxlan_info->link_nsid),
1572 vxlan_info->ifindex_link);
1573 vty_out(vty, " Link Interface %s",
1574 ifp == NULL ? "Unknown" :
1575 ifp->name);
1576 }
d62a17ae 1577 vty_out(vty, "\n");
1578 }
1579
1580 if (IS_ZEBRA_IF_BRIDGE_SLAVE(ifp)) {
1581 struct zebra_l2info_brslave *br_slave;
1582
1583 br_slave = &zebra_if->brslave_info;
eb4a93fb
DD
1584 if (br_slave->bridge_ifindex != IFINDEX_INTERNAL) {
1585 if (br_slave->br_if)
1586 vty_out(vty, " Master interface: %s\n",
1587 br_slave->br_if->name);
1588 else
1589 vty_out(vty, " Master ifindex: %u\n",
1590 br_slave->bridge_ifindex);
1591 }
d62a17ae 1592 }
1593
b9368db9
DD
1594 if (IS_ZEBRA_IF_BOND_SLAVE(ifp)) {
1595 struct zebra_l2info_bondslave *bond_slave;
1596
1597 bond_slave = &zebra_if->bondslave_info;
eb4a93fb
DD
1598 if (bond_slave->bond_ifindex != IFINDEX_INTERNAL) {
1599 if (bond_slave->bond_if)
1600 vty_out(vty, " Master interface: %s\n",
1601 bond_slave->bond_if->name);
1602 else
1603 vty_out(vty, " Master ifindex: %u\n",
1604 bond_slave->bond_ifindex);
1605 }
b9368db9
DD
1606 }
1607
00a7710c
AK
1608 if (zebra_if->flags & ZIF_FLAG_LACP_BYPASS)
1609 vty_out(vty, " LACP bypass: on\n");
1610
ce5160c0 1611 zebra_evpn_if_es_print(vty, zebra_if);
26ba45e3
AK
1612 vty_out(vty, " protodown: %s %s\n",
1613 (zebra_if->flags & ZIF_FLAG_PROTODOWN) ? "on" : "off",
1614 if_is_protodown_applicable(ifp) ? "" : "(n/a)");
c36e442c 1615 if (zebra_if->protodown_rc)
26ba45e3 1616 vty_out(vty, " protodown reasons: %s\n",
c36e442c
AK
1617 zebra_protodown_rc_str(zebra_if->protodown_rc, pd_buf,
1618 sizeof(pd_buf)));
ce5160c0 1619
8cb73ba4 1620 if (zebra_if->link_ifindex != IFINDEX_INTERNAL) {
8cb73ba4 1621 if (zebra_if->link)
eb4a93fb 1622 vty_out(vty, " Parent interface: %s\n", zebra_if->link->name);
8cb73ba4 1623 else
eb4a93fb 1624 vty_out(vty, " Parent ifindex: %d\n", zebra_if->link_ifindex);
8cb73ba4 1625 }
d62a17ae 1626
1627 if (HAS_LINK_PARAMS(ifp)) {
1628 int i;
1629 struct if_link_params *iflp = ifp->link_params;
1630 vty_out(vty, " Traffic Engineering Link Parameters:\n");
1631 if (IS_PARAM_SET(iflp, LP_TE_METRIC))
1632 vty_out(vty, " TE metric %u\n", iflp->te_metric);
1633 if (IS_PARAM_SET(iflp, LP_MAX_BW))
1634 vty_out(vty, " Maximum Bandwidth %g (Byte/s)\n",
1635 iflp->max_bw);
1636 if (IS_PARAM_SET(iflp, LP_MAX_RSV_BW))
1637 vty_out(vty,
1638 " Maximum Reservable Bandwidth %g (Byte/s)\n",
1639 iflp->max_rsv_bw);
1640 if (IS_PARAM_SET(iflp, LP_UNRSV_BW)) {
1641 vty_out(vty,
1642 " Unreserved Bandwidth per Class Type in Byte/s:\n");
1643 for (i = 0; i < MAX_CLASS_TYPE; i += 2)
1644 vty_out(vty,
1645 " [%d]: %g (Bytes/sec),\t[%d]: %g (Bytes/sec)\n",
1646 i, iflp->unrsv_bw[i], i + 1,
1647 iflp->unrsv_bw[i + 1]);
1648 }
1649
1650 if (IS_PARAM_SET(iflp, LP_ADM_GRP))
1651 vty_out(vty, " Administrative Group:%u\n",
1652 iflp->admin_grp);
1653 if (IS_PARAM_SET(iflp, LP_DELAY)) {
1654 vty_out(vty, " Link Delay Average: %u (micro-sec.)",
1655 iflp->av_delay);
1656 if (IS_PARAM_SET(iflp, LP_MM_DELAY)) {
1657 vty_out(vty, " Min: %u (micro-sec.)",
1658 iflp->min_delay);
1659 vty_out(vty, " Max: %u (micro-sec.)",
1660 iflp->max_delay);
1661 }
1662 vty_out(vty, "\n");
1663 }
1664 if (IS_PARAM_SET(iflp, LP_DELAY_VAR))
1665 vty_out(vty,
1666 " Link Delay Variation %u (micro-sec.)\n",
1667 iflp->delay_var);
1668 if (IS_PARAM_SET(iflp, LP_PKT_LOSS))
1669 vty_out(vty, " Link Packet Loss %g (in %%)\n",
1670 iflp->pkt_loss);
1671 if (IS_PARAM_SET(iflp, LP_AVA_BW))
1672 vty_out(vty, " Available Bandwidth %g (Byte/s)\n",
1673 iflp->ava_bw);
1674 if (IS_PARAM_SET(iflp, LP_RES_BW))
1675 vty_out(vty, " Residual Bandwidth %g (Byte/s)\n",
1676 iflp->res_bw);
1677 if (IS_PARAM_SET(iflp, LP_USE_BW))
1678 vty_out(vty, " Utilized Bandwidth %g (Byte/s)\n",
1679 iflp->use_bw);
1680 if (IS_PARAM_SET(iflp, LP_RMT_AS))
9bcef951
MS
1681 vty_out(vty, " Neighbor ASBR IP: %pI4 AS: %u \n",
1682 &iflp->rmt_ip, iflp->rmt_as);
d62a17ae 1683 }
1684
2eb27eec
DL
1685 hook_call(zebra_if_extra_info, vty, ifp);
1686
d62a17ae 1687 if (listhead(ifp->nbr_connected))
1688 vty_out(vty, " Neighbor address(s):\n");
1689 for (ALL_LIST_ELEMENTS_RO(ifp->nbr_connected, node, nbr_connected))
1690 nbr_connected_dump_vty(vty, nbr_connected);
718e3744 1691
1692#ifdef HAVE_PROC_NET_DEV
d62a17ae 1693 /* Statistics print out using proc file system. */
1694 vty_out(vty,
3efd0893 1695 " %lu input packets (%lu multicast), %lu bytes, %lu dropped\n",
d62a17ae 1696 ifp->stats.rx_packets, ifp->stats.rx_multicast,
1697 ifp->stats.rx_bytes, ifp->stats.rx_dropped);
1698
1699 vty_out(vty,
3efd0893 1700 " %lu input errors, %lu length, %lu overrun, %lu CRC, %lu frame\n",
d62a17ae 1701 ifp->stats.rx_errors, ifp->stats.rx_length_errors,
1702 ifp->stats.rx_over_errors, ifp->stats.rx_crc_errors,
1703 ifp->stats.rx_frame_errors);
1704
1705 vty_out(vty, " %lu fifo, %lu missed\n", ifp->stats.rx_fifo_errors,
1706 ifp->stats.rx_missed_errors);
1707
1708 vty_out(vty, " %lu output packets, %lu bytes, %lu dropped\n",
1709 ifp->stats.tx_packets, ifp->stats.tx_bytes,
1710 ifp->stats.tx_dropped);
1711
1712 vty_out(vty,
3efd0893 1713 " %lu output errors, %lu aborted, %lu carrier, %lu fifo, %lu heartbeat\n",
d62a17ae 1714 ifp->stats.tx_errors, ifp->stats.tx_aborted_errors,
1715 ifp->stats.tx_carrier_errors, ifp->stats.tx_fifo_errors,
1716 ifp->stats.tx_heartbeat_errors);
1717
1718 vty_out(vty, " %lu window, %lu collisions\n",
1719 ifp->stats.tx_window_errors, ifp->stats.collisions);
718e3744 1720#endif /* HAVE_PROC_NET_DEV */
1721
1722#ifdef HAVE_NET_RT_IFLIST
d62a17ae 1723 /* Statistics print out using sysctl (). */
1724 vty_out(vty,
3efd0893 1725 " input packets %llu, bytes %llu, dropped %llu, multicast packets %llu\n",
d62a17ae 1726 (unsigned long long)ifp->stats.ifi_ipackets,
1727 (unsigned long long)ifp->stats.ifi_ibytes,
1728 (unsigned long long)ifp->stats.ifi_iqdrops,
1729 (unsigned long long)ifp->stats.ifi_imcasts);
1730
1731 vty_out(vty, " input errors %llu\n",
1732 (unsigned long long)ifp->stats.ifi_ierrors);
1733
1734 vty_out(vty,
3efd0893 1735 " output packets %llu, bytes %llu, multicast packets %llu\n",
d62a17ae 1736 (unsigned long long)ifp->stats.ifi_opackets,
1737 (unsigned long long)ifp->stats.ifi_obytes,
1738 (unsigned long long)ifp->stats.ifi_omcasts);
1739
1740 vty_out(vty, " output errors %llu\n",
1741 (unsigned long long)ifp->stats.ifi_oerrors);
1742
1743 vty_out(vty, " collisions %llu\n",
1744 (unsigned long long)ifp->stats.ifi_collisions);
718e3744 1745#endif /* HAVE_NET_RT_IFLIST */
1746}
1747
d62a17ae 1748static void interface_update_stats(void)
78860b9f
DS
1749{
1750#ifdef HAVE_PROC_NET_DEV
d62a17ae 1751 /* If system has interface statistics via proc file system, update
1752 statistics. */
1753 ifstat_update_proc();
78860b9f
DS
1754#endif /* HAVE_PROC_NET_DEV */
1755#ifdef HAVE_NET_RT_IFLIST
d62a17ae 1756 ifstat_update_sysctl();
78860b9f
DS
1757#endif /* HAVE_NET_RT_IFLIST */
1758}
1759
612c2c15 1760static int if_config_write(struct vty *vty);
62b346ee 1761struct cmd_node interface_node = {
f4b8291f 1762 .name = "interface",
62b346ee 1763 .node = INTERFACE_NODE,
24389580 1764 .parent_node = CONFIG_NODE,
62b346ee 1765 .prompt = "%s(config-if)# ",
612c2c15 1766 .config_write = if_config_write,
62b346ee 1767};
718e3744 1768
49548752
NS
1769#ifndef VTYSH_EXTRACT_PL
1770#include "zebra/interface_clippy.c"
1771#endif
8b87bdf4 1772/* Show all interfaces to vty. */
49548752 1773DEFPY(show_interface, show_interface_cmd,
a2719d0e 1774 "show interface vrf NAME$vrf_name [brief$brief]",
49548752
NS
1775 SHOW_STR
1776 "Interface status and configuration\n"
1777 VRF_CMD_HELP_STR
1778 "Interface status and configuration summary\n")
8b87bdf4 1779{
a36898e7 1780 struct vrf *vrf;
d62a17ae 1781 struct interface *ifp;
8b87bdf4 1782
d62a17ae 1783 interface_update_stats();
8b87bdf4 1784
a2719d0e
IR
1785 vrf = vrf_lookup_by_name(vrf_name);
1786 if (!vrf) {
1787 vty_out(vty, "%% VRF %s not found\n", vrf_name);
1788 return CMD_WARNING;
1789 }
8b87bdf4 1790
49548752
NS
1791 if (brief) {
1792 ifs_dump_brief_vty(vty, vrf);
1793 } else {
1794 FOR_ALL_INTERFACES (vrf, ifp) {
1795 if_dump_vty(vty, ifp);
1796 }
1797 }
8b87bdf4 1798
d62a17ae 1799 return CMD_SUCCESS;
8b87bdf4
FL
1800}
1801
8b87bdf4
FL
1802
1803/* Show all interfaces to vty. */
a5c7809c 1804DEFPY (show_interface_vrf_all,
8b3f0677 1805 show_interface_vrf_all_cmd,
a2719d0e 1806 "show interface [vrf all] [brief$brief]",
8b87bdf4
FL
1807 SHOW_STR
1808 "Interface status and configuration\n"
a5c7809c
DS
1809 VRF_ALL_CMD_HELP_STR
1810 "Interface status and configuration summary\n")
718e3744 1811{
d62a17ae 1812 struct vrf *vrf;
d62a17ae 1813 struct interface *ifp;
8b87bdf4 1814
d62a17ae 1815 interface_update_stats();
718e3744 1816
d62a17ae 1817 /* All interface print. */
a5c7809c
DS
1818 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
1819 if (brief) {
1820 ifs_dump_brief_vty(vty, vrf);
1821 } else {
1822 FOR_ALL_INTERFACES (vrf, ifp)
1823 if_dump_vty(vty, ifp);
1824 }
1825 }
8b87bdf4 1826
d62a17ae 1827 return CMD_SUCCESS;
8b87bdf4
FL
1828}
1829
1830/* Show specified interface to vty. */
1721646e
DS
1831
1832DEFUN (show_interface_name_vrf,
1833 show_interface_name_vrf_cmd,
9ccf14f7 1834 "show interface IFNAME vrf NAME",
8b87bdf4
FL
1835 SHOW_STR
1836 "Interface status and configuration\n"
1721646e
DS
1837 "Interface name\n"
1838 VRF_CMD_HELP_STR)
8b87bdf4 1839{
d62a17ae 1840 int idx_ifname = 2;
1841 int idx_name = 4;
1842 struct interface *ifp;
a2719d0e 1843 struct vrf *vrf;
8b87bdf4 1844
d62a17ae 1845 interface_update_stats();
8b87bdf4 1846
a2719d0e
IR
1847 vrf = vrf_lookup_by_name(argv[idx_name]->arg);
1848 if (!vrf) {
1849 vty_out(vty, "%% VRF %s not found\n", argv[idx_name]->arg);
1850 return CMD_WARNING;
1851 }
8b87bdf4 1852
a2719d0e 1853 ifp = if_lookup_by_name_vrf(argv[idx_ifname]->arg, vrf);
d62a17ae 1854 if (ifp == NULL) {
1855 vty_out(vty, "%% Can't find interface %s\n",
1856 argv[idx_ifname]->arg);
1857 return CMD_WARNING;
1858 }
1859 if_dump_vty(vty, ifp);
718e3744 1860
d62a17ae 1861 return CMD_SUCCESS;
718e3744 1862}
1863
8b87bdf4 1864/* Show specified interface to vty. */
8b3f0677
DW
1865DEFUN (show_interface_name_vrf_all,
1866 show_interface_name_vrf_all_cmd,
b62ecea5 1867 "show interface IFNAME [vrf all]",
8b87bdf4
FL
1868 SHOW_STR
1869 "Interface status and configuration\n"
1721646e 1870 "Interface name\n"
8b87bdf4
FL
1871 VRF_ALL_CMD_HELP_STR)
1872{
d62a17ae 1873 int idx_ifname = 2;
d62a17ae 1874 struct interface *ifp;
8b87bdf4 1875
d62a17ae 1876 interface_update_stats();
8b87bdf4 1877
a2719d0e
IR
1878 ifp = if_lookup_by_name_all_vrf(argv[idx_ifname]->arg);
1879 if (ifp == NULL) {
d62a17ae 1880 vty_out(vty, "%% Can't find interface %s\n",
1881 argv[idx_ifname]->arg);
1882 return CMD_WARNING;
1883 }
a2719d0e 1884 if_dump_vty(vty, ifp);
8b87bdf4 1885
d62a17ae 1886 return CMD_SUCCESS;
8b87bdf4
FL
1887}
1888
a2719d0e 1889static void if_show_description(struct vty *vty, struct vrf *vrf)
ed9bb6d5 1890{
d62a17ae 1891 struct interface *ifp;
ed9bb6d5 1892
d62a17ae 1893 vty_out(vty, "Interface Status Protocol Description\n");
451fda4f 1894 FOR_ALL_INTERFACES (vrf, ifp) {
d62a17ae 1895 int len;
ba5165ec
DS
1896 struct zebra_if *zif;
1897 bool intf_desc;
1898
1899 intf_desc = false;
ed9bb6d5 1900
d62a17ae 1901 len = vty_out(vty, "%s", ifp->name);
1902 vty_out(vty, "%*s", (16 - len), " ");
1903
1904 if (if_is_up(ifp)) {
1905 vty_out(vty, "up ");
1906 if (CHECK_FLAG(ifp->status,
1907 ZEBRA_INTERFACE_LINKDETECTION)) {
1908 if (if_is_running(ifp))
1909 vty_out(vty, "up ");
1910 else
1911 vty_out(vty, "down ");
1912 } else {
1913 vty_out(vty, "unknown ");
1914 }
1915 } else {
1916 vty_out(vty, "down down ");
1917 }
ed9bb6d5 1918
ba5165ec
DS
1919 if (ifp->desc) {
1920 intf_desc = true;
d62a17ae 1921 vty_out(vty, "%s", ifp->desc);
ba5165ec
DS
1922 }
1923 zif = ifp->info;
1924 if (zif && zif->desc) {
1925 vty_out(vty, "%s%s",
1926 intf_desc
1927 ? "\n "
1928 : "",
1929 zif->desc);
1930 }
1931
d62a17ae 1932 vty_out(vty, "\n");
1933 }
8b87bdf4
FL
1934}
1935
1936DEFUN (show_interface_desc,
1937 show_interface_desc_cmd,
a2719d0e 1938 "show interface description vrf NAME",
8b87bdf4
FL
1939 SHOW_STR
1940 "Interface status and configuration\n"
b62ecea5
QY
1941 "Interface description\n"
1942 VRF_CMD_HELP_STR)
8b87bdf4 1943{
a2719d0e 1944 struct vrf *vrf;
8b87bdf4 1945
a2719d0e
IR
1946 vrf = vrf_lookup_by_name(argv[4]->arg);
1947 if (!vrf) {
1948 vty_out(vty, "%% VRF %s not found\n", argv[4]->arg);
1949 return CMD_WARNING;
1950 }
8b87bdf4 1951
a2719d0e 1952 if_show_description(vty, vrf);
8b87bdf4 1953
d62a17ae 1954 return CMD_SUCCESS;
8b87bdf4
FL
1955}
1956
8b87bdf4
FL
1957
1958DEFUN (show_interface_desc_vrf_all,
1959 show_interface_desc_vrf_all_cmd,
a2719d0e 1960 "show interface description [vrf all]",
8b87bdf4
FL
1961 SHOW_STR
1962 "Interface status and configuration\n"
1963 "Interface description\n"
1964 VRF_ALL_CMD_HELP_STR)
1965{
d62a17ae 1966 struct vrf *vrf;
8b87bdf4 1967
a2addae8 1968 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name)
996c9314 1969 if (!RB_EMPTY(if_name_head, &vrf->ifaces_by_name)) {
c479e756
DS
1970 vty_out(vty, "\n\tVRF %s(%u)\n\n", VRF_LOGNAME(vrf),
1971 vrf->vrf_id);
a2719d0e 1972 if_show_description(vty, vrf);
a2addae8 1973 }
8b87bdf4 1974
d62a17ae 1975 return CMD_SUCCESS;
ed9bb6d5 1976}
1977
09268680
CS
1978int if_multicast_set(struct interface *ifp)
1979{
1980 struct zebra_if *if_data;
1981
1982 if (CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE)) {
1983 if (if_set_flags(ifp, IFF_MULTICAST) < 0) {
1984 zlog_debug("Can't set multicast flag on interface %s",
1985 ifp->name);
1986 return -1;
1987 }
1988 if_refresh(ifp);
1989 }
1990 if_data = ifp->info;
1991 if_data->multicast = IF_ZEBRA_MULTICAST_ON;
1992
1993 return 0;
1994}
1995
718e3744 1996DEFUN (multicast,
1997 multicast_cmd,
1998 "multicast",
1999 "Set multicast flag to interface\n")
2000{
d62a17ae 2001 VTY_DECLVAR_CONTEXT(interface, ifp);
2002 int ret;
2003 struct zebra_if *if_data;
718e3744 2004
d62a17ae 2005 if (CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE)) {
2006 ret = if_set_flags(ifp, IFF_MULTICAST);
2007 if (ret < 0) {
2008 vty_out(vty, "Can't set multicast flag\n");
2009 return CMD_WARNING_CONFIG_FAILED;
2010 }
2011 if_refresh(ifp);
48b33aaf 2012 }
d62a17ae 2013 if_data = ifp->info;
2014 if_data->multicast = IF_ZEBRA_MULTICAST_ON;
48b33aaf 2015
d62a17ae 2016 return CMD_SUCCESS;
718e3744 2017}
2018
09268680
CS
2019int if_multicast_unset(struct interface *ifp)
2020{
2021 struct zebra_if *if_data;
2022
2023 if (CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE)) {
2024 if (if_unset_flags(ifp, IFF_MULTICAST) < 0) {
2025 zlog_debug("Can't unset multicast flag on interface %s",
2026 ifp->name);
2027 return -1;
2028 }
2029 if_refresh(ifp);
2030 }
2031 if_data = ifp->info;
2032 if_data->multicast = IF_ZEBRA_MULTICAST_OFF;
2033
2034 return 0;
2035}
2036
718e3744 2037DEFUN (no_multicast,
2038 no_multicast_cmd,
2039 "no multicast",
2040 NO_STR
2041 "Unset multicast flag to interface\n")
2042{
d62a17ae 2043 VTY_DECLVAR_CONTEXT(interface, ifp);
2044 int ret;
2045 struct zebra_if *if_data;
718e3744 2046
d62a17ae 2047 if (CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE)) {
2048 ret = if_unset_flags(ifp, IFF_MULTICAST);
2049 if (ret < 0) {
2050 vty_out(vty, "Can't unset multicast flag\n");
2051 return CMD_WARNING_CONFIG_FAILED;
2052 }
2053 if_refresh(ifp);
48b33aaf 2054 }
d62a17ae 2055 if_data = ifp->info;
2056 if_data->multicast = IF_ZEBRA_MULTICAST_OFF;
718e3744 2057
d62a17ae 2058 return CMD_SUCCESS;
718e3744 2059}
2060
09268680 2061int if_linkdetect(struct interface *ifp, bool detect)
2e3b2e47 2062{
d62a17ae 2063 int if_was_operative;
2e3b2e47 2064
d62a17ae 2065 if_was_operative = if_is_no_ptm_operative(ifp);
09268680
CS
2066 if (detect) {
2067 SET_FLAG(ifp->status, ZEBRA_INTERFACE_LINKDETECTION);
2e3b2e47 2068
09268680
CS
2069 /* When linkdetection is enabled, if might come down */
2070 if (!if_is_no_ptm_operative(ifp) && if_was_operative)
2071 if_down(ifp);
2072 } else {
2073 UNSET_FLAG(ifp->status, ZEBRA_INTERFACE_LINKDETECTION);
2e3b2e47 2074
09268680
CS
2075 /* Interface may come up after disabling link detection */
2076 if (if_is_operative(ifp) && !if_was_operative)
2077 if_up(ifp);
2078 }
d62a17ae 2079 /* FIXME: Will defer status change forwarding if interface
2080 does not come down! */
09268680
CS
2081 return 0;
2082}
2083
2084DEFUN(linkdetect, linkdetect_cmd, "link-detect",
2085 "Enable link detection on interface\n")
2086{
2087 VTY_DECLVAR_CONTEXT(interface, ifp);
2088
2089 if_linkdetect(ifp, true);
d62a17ae 2090
2091 return CMD_SUCCESS;
2e3b2e47 2092}
2093
2094
2095DEFUN (no_linkdetect,
2096 no_linkdetect_cmd,
2097 "no link-detect",
2098 NO_STR
2099 "Disable link detection on interface\n")
2100{
d62a17ae 2101 VTY_DECLVAR_CONTEXT(interface, ifp);
d62a17ae 2102
09268680
CS
2103 if_linkdetect(ifp, false);
2104
2105 return CMD_SUCCESS;
2106}
2e3b2e47 2107
09268680
CS
2108int if_shutdown(struct interface *ifp)
2109{
2110 struct zebra_if *if_data;
2e3b2e47 2111
09268680
CS
2112 if (ifp->ifindex != IFINDEX_INTERNAL) {
2113 /* send RA lifetime of 0 before stopping. rfc4861/6.2.5 */
2114 rtadv_stop_ra(ifp);
2115 if (if_unset_flags(ifp, IFF_UP) < 0) {
2116 zlog_debug("Can't shutdown interface %s", ifp->name);
2117 return -1;
2118 }
2119 if_refresh(ifp);
2120 }
2121 if_data = ifp->info;
2122 if_data->shutdown = IF_ZEBRA_SHUTDOWN_ON;
2e3b2e47 2123
09268680 2124 return 0;
2e3b2e47 2125}
2126
718e3744 2127DEFUN (shutdown_if,
2128 shutdown_if_cmd,
2129 "shutdown",
2130 "Shutdown the selected interface\n")
2131{
d62a17ae 2132 VTY_DECLVAR_CONTEXT(interface, ifp);
2133 int ret;
2134 struct zebra_if *if_data;
718e3744 2135
d62a17ae 2136 if (ifp->ifindex != IFINDEX_INTERNAL) {
d7fc0e67
DS
2137 /* send RA lifetime of 0 before stopping. rfc4861/6.2.5 */
2138 rtadv_stop_ra(ifp);
d62a17ae 2139 ret = if_unset_flags(ifp, IFF_UP);
2140 if (ret < 0) {
2141 vty_out(vty, "Can't shutdown interface\n");
2142 return CMD_WARNING_CONFIG_FAILED;
2143 }
2144 if_refresh(ifp);
2145 }
2146 if_data = ifp->info;
2147 if_data->shutdown = IF_ZEBRA_SHUTDOWN_ON;
718e3744 2148
d62a17ae 2149 return CMD_SUCCESS;
718e3744 2150}
2151
09268680
CS
2152int if_no_shutdown(struct interface *ifp)
2153{
2154 struct zebra_if *if_data;
2155
2156 if (ifp->ifindex != IFINDEX_INTERNAL) {
2157 if (if_set_flags(ifp, IFF_UP | IFF_RUNNING) < 0) {
2158 zlog_debug("Can't up interface %s", ifp->name);
2159 return -1;
2160 }
2161 if_refresh(ifp);
2162
2163 /* Some addresses (in particular, IPv6 addresses on Linux) get
2164 * removed when the interface goes down. They need to be
2165 * readded.
2166 */
2167 if_addr_wakeup(ifp);
2168 }
2169
2170 if_data = ifp->info;
2171 if_data->shutdown = IF_ZEBRA_SHUTDOWN_OFF;
2172
2173 return 0;
2174}
2175
718e3744 2176DEFUN (no_shutdown_if,
2177 no_shutdown_if_cmd,
2178 "no shutdown",
2179 NO_STR
2180 "Shutdown the selected interface\n")
2181{
d62a17ae 2182 VTY_DECLVAR_CONTEXT(interface, ifp);
2183 int ret;
2184 struct zebra_if *if_data;
718e3744 2185
d62a17ae 2186 if (ifp->ifindex != IFINDEX_INTERNAL) {
2187 ret = if_set_flags(ifp, IFF_UP | IFF_RUNNING);
2188 if (ret < 0) {
2189 vty_out(vty, "Can't up interface\n");
2190 return CMD_WARNING_CONFIG_FAILED;
2191 }
2192 if_refresh(ifp);
bfac8dcd 2193
d62a17ae 2194 /* Some addresses (in particular, IPv6 addresses on Linux) get
2195 * removed when the interface goes down. They need to be
2196 * readded.
2197 */
2198 if_addr_wakeup(ifp);
2199 }
bfac8dcd 2200
d62a17ae 2201 if_data = ifp->info;
2202 if_data->shutdown = IF_ZEBRA_SHUTDOWN_OFF;
718e3744 2203
d62a17ae 2204 return CMD_SUCCESS;
718e3744 2205}
2206
2207DEFUN (bandwidth_if,
2208 bandwidth_if_cmd,
6147e2c6 2209 "bandwidth (1-100000)",
718e3744 2210 "Set bandwidth informational parameter\n"
70bd3c43 2211 "Bandwidth in megabits\n")
718e3744 2212{
d62a17ae 2213 int idx_number = 1;
2214 VTY_DECLVAR_CONTEXT(interface, ifp);
2215 unsigned int bandwidth;
2216
2217 bandwidth = strtol(argv[idx_number]->arg, NULL, 10);
2218
2219 /* bandwidth range is <1-100000> */
2220 if (bandwidth < 1 || bandwidth > 100000) {
2221 vty_out(vty, "Bandwidth is invalid\n");
2222 return CMD_WARNING_CONFIG_FAILED;
2223 }
2224
2225 ifp->bandwidth = bandwidth;
718e3744 2226
d62a17ae 2227 /* force protocols to recalculate routes due to cost change */
2228 if (if_is_operative(ifp))
2229 zebra_interface_up_update(ifp);
718e3744 2230
d62a17ae 2231 return CMD_SUCCESS;
718e3744 2232}
2233
2234DEFUN (no_bandwidth_if,
2235 no_bandwidth_if_cmd,
b62ecea5 2236 "no bandwidth [(1-100000)]",
718e3744 2237 NO_STR
b62ecea5
QY
2238 "Set bandwidth informational parameter\n"
2239 "Bandwidth in megabits\n")
718e3744 2240{
d62a17ae 2241 VTY_DECLVAR_CONTEXT(interface, ifp);
718e3744 2242
d62a17ae 2243 ifp->bandwidth = 0;
718e3744 2244
d62a17ae 2245 /* force protocols to recalculate routes due to cost change */
2246 if (if_is_operative(ifp))
2247 zebra_interface_up_update(ifp);
2248
2249 return CMD_SUCCESS;
718e3744 2250}
2251
6b0655a2 2252
d62a17ae 2253struct cmd_node link_params_node = {
f4b8291f 2254 .name = "link-params",
62b346ee 2255 .node = LINK_PARAMS_NODE,
24389580 2256 .parent_node = INTERFACE_NODE,
62b346ee 2257 .prompt = "%s(config-link-params)# ",
16f1b9ee
OD
2258};
2259
d62a17ae 2260static void link_param_cmd_set_uint32(struct interface *ifp, uint32_t *field,
2261 uint32_t type, uint32_t value)
16f1b9ee 2262{
d62a17ae 2263 /* Update field as needed */
2264 if (IS_PARAM_UNSET(ifp->link_params, type) || *field != value) {
2265 *field = value;
2266 SET_PARAM(ifp->link_params, type);
16f1b9ee 2267
d62a17ae 2268 /* force protocols to update LINK STATE due to parameters change
2269 */
2270 if (if_is_operative(ifp))
2271 zebra_interface_parameters_update(ifp);
2272 }
16f1b9ee 2273}
d62a17ae 2274static void link_param_cmd_set_float(struct interface *ifp, float *field,
2275 uint32_t type, float value)
16f1b9ee
OD
2276{
2277
d62a17ae 2278 /* Update field as needed */
2279 if (IS_PARAM_UNSET(ifp->link_params, type) || *field != value) {
2280 *field = value;
2281 SET_PARAM(ifp->link_params, type);
16f1b9ee 2282
d62a17ae 2283 /* force protocols to update LINK STATE due to parameters change
2284 */
2285 if (if_is_operative(ifp))
2286 zebra_interface_parameters_update(ifp);
2287 }
16f1b9ee
OD
2288}
2289
d62a17ae 2290static void link_param_cmd_unset(struct interface *ifp, uint32_t type)
16f1b9ee 2291{
d62a17ae 2292 if (ifp->link_params == NULL)
2293 return;
16f1b9ee 2294
d62a17ae 2295 /* Unset field */
2296 UNSET_PARAM(ifp->link_params, type);
16f1b9ee 2297
d62a17ae 2298 /* force protocols to update LINK STATE due to parameters change */
2299 if (if_is_operative(ifp))
2300 zebra_interface_parameters_update(ifp);
16f1b9ee
OD
2301}
2302
505e5056 2303DEFUN_NOSH (link_params,
16f1b9ee
OD
2304 link_params_cmd,
2305 "link-params",
2306 LINK_PARAMS_STR)
2307{
d62a17ae 2308 /* vty->qobj_index stays the same @ interface pointer */
2309 vty->node = LINK_PARAMS_NODE;
16f1b9ee 2310
d62a17ae 2311 return CMD_SUCCESS;
16f1b9ee
OD
2312}
2313
505e5056 2314DEFUN_NOSH (exit_link_params,
03f99d9a
DS
2315 exit_link_params_cmd,
2316 "exit-link-params",
2317 "Exit from Link Params configuration mode\n")
2318{
d62a17ae 2319 if (vty->node == LINK_PARAMS_NODE)
2320 vty->node = INTERFACE_NODE;
2321 return CMD_SUCCESS;
03f99d9a
DS
2322}
2323
16f1b9ee
OD
2324/* Specific Traffic Engineering parameters commands */
2325DEFUN (link_params_enable,
2326 link_params_enable_cmd,
2327 "enable",
2328 "Activate link parameters on this interface\n")
2329{
d62a17ae 2330 VTY_DECLVAR_CONTEXT(interface, ifp);
16f1b9ee 2331
d62a17ae 2332 /* This command could be issue at startup, when activate MPLS TE */
2333 /* on a new interface or after a ON / OFF / ON toggle */
2334 /* In all case, TE parameters are reset to their default factory */
14a4d9d0 2335 if (IS_ZEBRA_DEBUG_EVENT || IS_ZEBRA_DEBUG_MPLS)
d62a17ae 2336 zlog_debug(
2337 "Link-params: enable TE link parameters on interface %s",
2338 ifp->name);
16f1b9ee 2339
d62a17ae 2340 if (!if_link_params_get(ifp)) {
14a4d9d0 2341 if (IS_ZEBRA_DEBUG_EVENT || IS_ZEBRA_DEBUG_MPLS)
d62a17ae 2342 zlog_debug(
2343 "Link-params: failed to init TE link parameters %s",
2344 ifp->name);
16f1b9ee 2345
d62a17ae 2346 return CMD_WARNING_CONFIG_FAILED;
2347 }
16f1b9ee 2348
d62a17ae 2349 /* force protocols to update LINK STATE due to parameters change */
2350 if (if_is_operative(ifp))
2351 zebra_interface_parameters_update(ifp);
16f1b9ee 2352
d62a17ae 2353 return CMD_SUCCESS;
16f1b9ee
OD
2354}
2355
2356DEFUN (no_link_params_enable,
2357 no_link_params_enable_cmd,
2358 "no enable",
2359 NO_STR
2360 "Disable link parameters on this interface\n")
2361{
d62a17ae 2362 VTY_DECLVAR_CONTEXT(interface, ifp);
16f1b9ee 2363
14a4d9d0 2364 if (IS_ZEBRA_DEBUG_EVENT || IS_ZEBRA_DEBUG_MPLS)
2365 zlog_debug("MPLS-TE: disable TE link parameters on interface %s",
2366 ifp->name);
16f1b9ee 2367
d62a17ae 2368 if_link_params_free(ifp);
16f1b9ee 2369
d62a17ae 2370 /* force protocols to update LINK STATE due to parameters change */
2371 if (if_is_operative(ifp))
2372 zebra_interface_parameters_update(ifp);
16f1b9ee 2373
d62a17ae 2374 return CMD_SUCCESS;
16f1b9ee
OD
2375}
2376
2377/* STANDARD TE metrics */
2378DEFUN (link_params_metric,
2379 link_params_metric_cmd,
6147e2c6 2380 "metric (0-4294967295)",
16f1b9ee
OD
2381 "Link metric for MPLS-TE purpose\n"
2382 "Metric value in decimal\n")
2383{
d62a17ae 2384 int idx_number = 1;
2385 VTY_DECLVAR_CONTEXT(interface, ifp);
2386 struct if_link_params *iflp = if_link_params_get(ifp);
d7c0a89a 2387 uint32_t metric;
16f1b9ee 2388
d62a17ae 2389 metric = strtoul(argv[idx_number]->arg, NULL, 10);
16f1b9ee 2390
d62a17ae 2391 /* Update TE metric if needed */
2392 link_param_cmd_set_uint32(ifp, &iflp->te_metric, LP_TE_METRIC, metric);
16f1b9ee 2393
d62a17ae 2394 return CMD_SUCCESS;
16f1b9ee
OD
2395}
2396
2397DEFUN (no_link_params_metric,
2398 no_link_params_metric_cmd,
2399 "no metric",
2400 NO_STR
3ddccf18 2401 "Disable Link Metric on this interface\n")
16f1b9ee 2402{
d62a17ae 2403 VTY_DECLVAR_CONTEXT(interface, ifp);
16f1b9ee 2404
d62a17ae 2405 /* Unset TE Metric */
2406 link_param_cmd_unset(ifp, LP_TE_METRIC);
16f1b9ee 2407
d62a17ae 2408 return CMD_SUCCESS;
16f1b9ee
OD
2409}
2410
2411DEFUN (link_params_maxbw,
2412 link_params_maxbw_cmd,
2413 "max-bw BANDWIDTH",
2414 "Maximum bandwidth that can be used\n"
2415 "Bytes/second (IEEE floating point format)\n")
2416{
d62a17ae 2417 int idx_bandwidth = 1;
2418 VTY_DECLVAR_CONTEXT(interface, ifp);
2419 struct if_link_params *iflp = if_link_params_get(ifp);
2420
2421 float bw;
2422
2423 if (sscanf(argv[idx_bandwidth]->arg, "%g", &bw) != 1) {
2424 vty_out(vty, "link_params_maxbw: fscanf: %s\n",
2425 safe_strerror(errno));
2426 return CMD_WARNING_CONFIG_FAILED;
2427 }
2428
2429 /* Check that Maximum bandwidth is not lower than other bandwidth
2430 * parameters */
2431 if ((bw <= iflp->max_rsv_bw) || (bw <= iflp->unrsv_bw[0])
2432 || (bw <= iflp->unrsv_bw[1]) || (bw <= iflp->unrsv_bw[2])
2433 || (bw <= iflp->unrsv_bw[3]) || (bw <= iflp->unrsv_bw[4])
2434 || (bw <= iflp->unrsv_bw[5]) || (bw <= iflp->unrsv_bw[6])
2435 || (bw <= iflp->unrsv_bw[7]) || (bw <= iflp->ava_bw)
2436 || (bw <= iflp->res_bw) || (bw <= iflp->use_bw)) {
2437 vty_out(vty,
2438 "Maximum Bandwidth could not be lower than others bandwidth\n");
2439 return CMD_WARNING_CONFIG_FAILED;
2440 }
2441
2442 /* Update Maximum Bandwidth if needed */
2443 link_param_cmd_set_float(ifp, &iflp->max_bw, LP_MAX_BW, bw);
2444
2445 return CMD_SUCCESS;
16f1b9ee
OD
2446}
2447
2448DEFUN (link_params_max_rsv_bw,
2449 link_params_max_rsv_bw_cmd,
2450 "max-rsv-bw BANDWIDTH",
2451 "Maximum bandwidth that may be reserved\n"
2452 "Bytes/second (IEEE floating point format)\n")
2453{
d62a17ae 2454 int idx_bandwidth = 1;
2455 VTY_DECLVAR_CONTEXT(interface, ifp);
2456 struct if_link_params *iflp = if_link_params_get(ifp);
2457 float bw;
16f1b9ee 2458
d62a17ae 2459 if (sscanf(argv[idx_bandwidth]->arg, "%g", &bw) != 1) {
2460 vty_out(vty, "link_params_max_rsv_bw: fscanf: %s\n",
2461 safe_strerror(errno));
2462 return CMD_WARNING_CONFIG_FAILED;
2463 }
16f1b9ee 2464
d62a17ae 2465 /* Check that bandwidth is not greater than maximum bandwidth parameter
2466 */
2467 if (bw > iflp->max_bw) {
2468 vty_out(vty,
2469 "Maximum Reservable Bandwidth could not be greater than Maximum Bandwidth (%g)\n",
2470 iflp->max_bw);
2471 return CMD_WARNING_CONFIG_FAILED;
2472 }
16f1b9ee 2473
d62a17ae 2474 /* Update Maximum Reservable Bandwidth if needed */
2475 link_param_cmd_set_float(ifp, &iflp->max_rsv_bw, LP_MAX_RSV_BW, bw);
16f1b9ee 2476
d62a17ae 2477 return CMD_SUCCESS;
16f1b9ee
OD
2478}
2479
2480DEFUN (link_params_unrsv_bw,
2481 link_params_unrsv_bw_cmd,
6147e2c6 2482 "unrsv-bw (0-7) BANDWIDTH",
16f1b9ee
OD
2483 "Unreserved bandwidth at each priority level\n"
2484 "Priority\n"
2485 "Bytes/second (IEEE floating point format)\n")
2486{
d62a17ae 2487 int idx_number = 1;
2488 int idx_bandwidth = 2;
2489 VTY_DECLVAR_CONTEXT(interface, ifp);
2490 struct if_link_params *iflp = if_link_params_get(ifp);
2491 int priority;
2492 float bw;
2493
2494 /* We don't have to consider about range check here. */
2495 if (sscanf(argv[idx_number]->arg, "%d", &priority) != 1) {
2496 vty_out(vty, "link_params_unrsv_bw: fscanf: %s\n",
2497 safe_strerror(errno));
2498 return CMD_WARNING_CONFIG_FAILED;
2499 }
2500
2501 if (sscanf(argv[idx_bandwidth]->arg, "%g", &bw) != 1) {
2502 vty_out(vty, "link_params_unrsv_bw: fscanf: %s\n",
2503 safe_strerror(errno));
2504 return CMD_WARNING_CONFIG_FAILED;
2505 }
2506
2507 /* Check that bandwidth is not greater than maximum bandwidth parameter
2508 */
2509 if (bw > iflp->max_bw) {
2510 vty_out(vty,
2511 "UnReserved Bandwidth could not be greater than Maximum Bandwidth (%g)\n",
2512 iflp->max_bw);
2513 return CMD_WARNING_CONFIG_FAILED;
2514 }
2515
2516 /* Update Unreserved Bandwidth if needed */
2517 link_param_cmd_set_float(ifp, &iflp->unrsv_bw[priority], LP_UNRSV_BW,
2518 bw);
2519
2520 return CMD_SUCCESS;
16f1b9ee
OD
2521}
2522
2523DEFUN (link_params_admin_grp,
2524 link_params_admin_grp_cmd,
2525 "admin-grp BITPATTERN",
2526 "Administrative group membership\n"
2527 "32-bit Hexadecimal value (e.g. 0xa1)\n")
2528{
d62a17ae 2529 int idx_bitpattern = 1;
2530 VTY_DECLVAR_CONTEXT(interface, ifp);
2531 struct if_link_params *iflp = if_link_params_get(ifp);
2532 unsigned long value;
16f1b9ee 2533
d62a17ae 2534 if (sscanf(argv[idx_bitpattern]->arg, "0x%lx", &value) != 1) {
2535 vty_out(vty, "link_params_admin_grp: fscanf: %s\n",
2536 safe_strerror(errno));
2537 return CMD_WARNING_CONFIG_FAILED;
2538 }
16f1b9ee 2539
d62a17ae 2540 /* Update Administrative Group if needed */
2541 link_param_cmd_set_uint32(ifp, &iflp->admin_grp, LP_ADM_GRP, value);
16f1b9ee 2542
d62a17ae 2543 return CMD_SUCCESS;
16f1b9ee
OD
2544}
2545
2546DEFUN (no_link_params_admin_grp,
2547 no_link_params_admin_grp_cmd,
2548 "no admin-grp",
2549 NO_STR
3ddccf18 2550 "Disable Administrative group membership on this interface\n")
16f1b9ee 2551{
d62a17ae 2552 VTY_DECLVAR_CONTEXT(interface, ifp);
16f1b9ee 2553
d62a17ae 2554 /* Unset Admin Group */
2555 link_param_cmd_unset(ifp, LP_ADM_GRP);
16f1b9ee 2556
d62a17ae 2557 return CMD_SUCCESS;
16f1b9ee
OD
2558}
2559
2560/* RFC5392 & RFC5316: INTER-AS */
2561DEFUN (link_params_inter_as,
2562 link_params_inter_as_cmd,
6147e2c6 2563 "neighbor A.B.C.D as (1-4294967295)",
16f1b9ee
OD
2564 "Configure remote ASBR information (Neighbor IP address and AS number)\n"
2565 "Remote IP address in dot decimal A.B.C.D\n"
2566 "Remote AS number\n"
2567 "AS number in the range <1-4294967295>\n")
2568{
d62a17ae 2569 int idx_ipv4 = 1;
2570 int idx_number = 3;
16f1b9ee 2571
d62a17ae 2572 VTY_DECLVAR_CONTEXT(interface, ifp);
2573 struct if_link_params *iflp = if_link_params_get(ifp);
2574 struct in_addr addr;
d7c0a89a 2575 uint32_t as;
16f1b9ee 2576
d62a17ae 2577 if (!inet_aton(argv[idx_ipv4]->arg, &addr)) {
2578 vty_out(vty, "Please specify Router-Addr by A.B.C.D\n");
2579 return CMD_WARNING_CONFIG_FAILED;
2580 }
16f1b9ee 2581
d62a17ae 2582 as = strtoul(argv[idx_number]->arg, NULL, 10);
16f1b9ee 2583
d62a17ae 2584 /* Update Remote IP and Remote AS fields if needed */
2585 if (IS_PARAM_UNSET(iflp, LP_RMT_AS) || iflp->rmt_as != as
2586 || iflp->rmt_ip.s_addr != addr.s_addr) {
16f1b9ee 2587
d62a17ae 2588 iflp->rmt_as = as;
2589 iflp->rmt_ip.s_addr = addr.s_addr;
2590 SET_PARAM(iflp, LP_RMT_AS);
16f1b9ee 2591
d62a17ae 2592 /* force protocols to update LINK STATE due to parameters change
2593 */
2594 if (if_is_operative(ifp))
2595 zebra_interface_parameters_update(ifp);
2596 }
2597 return CMD_SUCCESS;
16f1b9ee
OD
2598}
2599
2600DEFUN (no_link_params_inter_as,
2601 no_link_params_inter_as_cmd,
2602 "no neighbor",
2603 NO_STR
2604 "Remove Neighbor IP address and AS number for Inter-AS TE\n")
2605{
d62a17ae 2606 VTY_DECLVAR_CONTEXT(interface, ifp);
2607 struct if_link_params *iflp = if_link_params_get(ifp);
16f1b9ee 2608
d62a17ae 2609 /* Reset Remote IP and AS neighbor */
2610 iflp->rmt_as = 0;
2611 iflp->rmt_ip.s_addr = 0;
2612 UNSET_PARAM(iflp, LP_RMT_AS);
16f1b9ee 2613
d62a17ae 2614 /* force protocols to update LINK STATE due to parameters change */
2615 if (if_is_operative(ifp))
2616 zebra_interface_parameters_update(ifp);
16f1b9ee 2617
d62a17ae 2618 return CMD_SUCCESS;
16f1b9ee
OD
2619}
2620
d62a17ae 2621/* RFC7471: OSPF Traffic Engineering (TE) Metric extensions &
2622 * draft-ietf-isis-metric-extensions-07.txt */
16f1b9ee
OD
2623DEFUN (link_params_delay,
2624 link_params_delay_cmd,
b62ecea5 2625 "delay (0-16777215) [min (0-16777215) max (0-16777215)]",
16f1b9ee 2626 "Unidirectional Average Link Delay\n"
b62ecea5
QY
2627 "Average delay in micro-second as decimal (0...16777215)\n"
2628 "Minimum delay\n"
2629 "Minimum delay in micro-second as decimal (0...16777215)\n"
2630 "Maximum delay\n"
2631 "Maximum delay in micro-second as decimal (0...16777215)\n")
16f1b9ee 2632{
d62a17ae 2633 /* Get and Check new delay values */
d7c0a89a 2634 uint32_t delay = 0, low = 0, high = 0;
d62a17ae 2635 delay = strtoul(argv[1]->arg, NULL, 10);
2636 if (argc == 6) {
2637 low = strtoul(argv[3]->arg, NULL, 10);
2638 high = strtoul(argv[5]->arg, NULL, 10);
2639 }
2640
2641 VTY_DECLVAR_CONTEXT(interface, ifp);
2642 struct if_link_params *iflp = if_link_params_get(ifp);
d7c0a89a 2643 uint8_t update = 0;
d62a17ae 2644
2645 if (argc == 2) {
2646 /* Check new delay value against old Min and Max delays if set
2647 */
2648 if (IS_PARAM_SET(iflp, LP_MM_DELAY)
2649 && (delay <= iflp->min_delay || delay >= iflp->max_delay)) {
2650 vty_out(vty,
2651 "Average delay should be comprise between Min (%d) and Max (%d) delay\n",
2652 iflp->min_delay, iflp->max_delay);
2653 return CMD_WARNING_CONFIG_FAILED;
2654 }
2655 /* Update delay if value is not set or change */
2656 if (IS_PARAM_UNSET(iflp, LP_DELAY) || iflp->av_delay != delay) {
2657 iflp->av_delay = delay;
2658 SET_PARAM(iflp, LP_DELAY);
2659 update = 1;
2660 }
2661 /* Unset Min and Max delays if already set */
2662 if (IS_PARAM_SET(iflp, LP_MM_DELAY)) {
2663 iflp->min_delay = 0;
2664 iflp->max_delay = 0;
2665 UNSET_PARAM(iflp, LP_MM_DELAY);
2666 update = 1;
2667 }
2668 } else {
2669 /* Check new delays value coherency */
2670 if (delay <= low || delay >= high) {
2671 vty_out(vty,
2672 "Average delay should be comprise between Min (%d) and Max (%d) delay\n",
2673 low, high);
2674 return CMD_WARNING_CONFIG_FAILED;
2675 }
2676 /* Update Delays if needed */
2677 if (IS_PARAM_UNSET(iflp, LP_DELAY)
2678 || IS_PARAM_UNSET(iflp, LP_MM_DELAY)
2679 || iflp->av_delay != delay || iflp->min_delay != low
2680 || iflp->max_delay != high) {
2681 iflp->av_delay = delay;
2682 SET_PARAM(iflp, LP_DELAY);
2683 iflp->min_delay = low;
2684 iflp->max_delay = high;
2685 SET_PARAM(iflp, LP_MM_DELAY);
2686 update = 1;
2687 }
2688 }
2689
2690 /* force protocols to update LINK STATE due to parameters change */
2691 if (update == 1 && if_is_operative(ifp))
2692 zebra_interface_parameters_update(ifp);
2693
2694 return CMD_SUCCESS;
16f1b9ee
OD
2695}
2696
16f1b9ee
OD
2697DEFUN (no_link_params_delay,
2698 no_link_params_delay_cmd,
2699 "no delay",
2700 NO_STR
3ddccf18 2701 "Disable Unidirectional Average, Min & Max Link Delay on this interface\n")
16f1b9ee 2702{
d62a17ae 2703 VTY_DECLVAR_CONTEXT(interface, ifp);
2704 struct if_link_params *iflp = if_link_params_get(ifp);
16f1b9ee 2705
d62a17ae 2706 /* Unset Delays */
2707 iflp->av_delay = 0;
2708 UNSET_PARAM(iflp, LP_DELAY);
2709 iflp->min_delay = 0;
2710 iflp->max_delay = 0;
2711 UNSET_PARAM(iflp, LP_MM_DELAY);
16f1b9ee 2712
d62a17ae 2713 /* force protocols to update LINK STATE due to parameters change */
2714 if (if_is_operative(ifp))
2715 zebra_interface_parameters_update(ifp);
16f1b9ee 2716
d62a17ae 2717 return CMD_SUCCESS;
16f1b9ee
OD
2718}
2719
2720DEFUN (link_params_delay_var,
2721 link_params_delay_var_cmd,
6147e2c6 2722 "delay-variation (0-16777215)",
16f1b9ee
OD
2723 "Unidirectional Link Delay Variation\n"
2724 "delay variation in micro-second as decimal (0...16777215)\n")
2725{
d62a17ae 2726 int idx_number = 1;
2727 VTY_DECLVAR_CONTEXT(interface, ifp);
2728 struct if_link_params *iflp = if_link_params_get(ifp);
d7c0a89a 2729 uint32_t value;
16f1b9ee 2730
d62a17ae 2731 value = strtoul(argv[idx_number]->arg, NULL, 10);
16f1b9ee 2732
d62a17ae 2733 /* Update Delay Variation if needed */
2734 link_param_cmd_set_uint32(ifp, &iflp->delay_var, LP_DELAY_VAR, value);
16f1b9ee 2735
d62a17ae 2736 return CMD_SUCCESS;
16f1b9ee
OD
2737}
2738
2739DEFUN (no_link_params_delay_var,
2740 no_link_params_delay_var_cmd,
2741 "no delay-variation",
2742 NO_STR
3ddccf18 2743 "Disable Unidirectional Delay Variation on this interface\n")
16f1b9ee 2744{
d62a17ae 2745 VTY_DECLVAR_CONTEXT(interface, ifp);
16f1b9ee 2746
d62a17ae 2747 /* Unset Delay Variation */
2748 link_param_cmd_unset(ifp, LP_DELAY_VAR);
16f1b9ee 2749
d62a17ae 2750 return CMD_SUCCESS;
16f1b9ee
OD
2751}
2752
2753DEFUN (link_params_pkt_loss,
2754 link_params_pkt_loss_cmd,
2755 "packet-loss PERCENTAGE",
2756 "Unidirectional Link Packet Loss\n"
2757 "percentage of total traffic by 0.000003% step and less than 50.331642%\n")
2758{
d62a17ae 2759 int idx_percentage = 1;
2760 VTY_DECLVAR_CONTEXT(interface, ifp);
2761 struct if_link_params *iflp = if_link_params_get(ifp);
2762 float fval;
16f1b9ee 2763
d62a17ae 2764 if (sscanf(argv[idx_percentage]->arg, "%g", &fval) != 1) {
2765 vty_out(vty, "link_params_pkt_loss: fscanf: %s\n",
2766 safe_strerror(errno));
2767 return CMD_WARNING_CONFIG_FAILED;
2768 }
16f1b9ee 2769
d62a17ae 2770 if (fval > MAX_PKT_LOSS)
2771 fval = MAX_PKT_LOSS;
16f1b9ee 2772
d62a17ae 2773 /* Update Packet Loss if needed */
2774 link_param_cmd_set_float(ifp, &iflp->pkt_loss, LP_PKT_LOSS, fval);
16f1b9ee 2775
d62a17ae 2776 return CMD_SUCCESS;
16f1b9ee
OD
2777}
2778
2779DEFUN (no_link_params_pkt_loss,
2780 no_link_params_pkt_loss_cmd,
2781 "no packet-loss",
2782 NO_STR
3ddccf18 2783 "Disable Unidirectional Link Packet Loss on this interface\n")
16f1b9ee 2784{
d62a17ae 2785 VTY_DECLVAR_CONTEXT(interface, ifp);
16f1b9ee 2786
d62a17ae 2787 /* Unset Packet Loss */
2788 link_param_cmd_unset(ifp, LP_PKT_LOSS);
16f1b9ee 2789
d62a17ae 2790 return CMD_SUCCESS;
16f1b9ee
OD
2791}
2792
2793DEFUN (link_params_res_bw,
2794 link_params_res_bw_cmd,
2795 "res-bw BANDWIDTH",
2796 "Unidirectional Residual Bandwidth\n"
2797 "Bytes/second (IEEE floating point format)\n")
2798{
d62a17ae 2799 int idx_bandwidth = 1;
2800 VTY_DECLVAR_CONTEXT(interface, ifp);
2801 struct if_link_params *iflp = if_link_params_get(ifp);
2802 float bw;
16f1b9ee 2803
d62a17ae 2804 if (sscanf(argv[idx_bandwidth]->arg, "%g", &bw) != 1) {
2805 vty_out(vty, "link_params_res_bw: fscanf: %s\n",
2806 safe_strerror(errno));
2807 return CMD_WARNING_CONFIG_FAILED;
2808 }
16f1b9ee 2809
d62a17ae 2810 /* Check that bandwidth is not greater than maximum bandwidth parameter
2811 */
2812 if (bw > iflp->max_bw) {
2813 vty_out(vty,
2814 "Residual Bandwidth could not be greater than Maximum Bandwidth (%g)\n",
2815 iflp->max_bw);
2816 return CMD_WARNING_CONFIG_FAILED;
2817 }
16f1b9ee 2818
d62a17ae 2819 /* Update Residual Bandwidth if needed */
2820 link_param_cmd_set_float(ifp, &iflp->res_bw, LP_RES_BW, bw);
16f1b9ee 2821
d62a17ae 2822 return CMD_SUCCESS;
16f1b9ee
OD
2823}
2824
2825DEFUN (no_link_params_res_bw,
2826 no_link_params_res_bw_cmd,
2827 "no res-bw",
2828 NO_STR
3ddccf18 2829 "Disable Unidirectional Residual Bandwidth on this interface\n")
16f1b9ee 2830{
d62a17ae 2831 VTY_DECLVAR_CONTEXT(interface, ifp);
16f1b9ee 2832
d62a17ae 2833 /* Unset Residual Bandwidth */
2834 link_param_cmd_unset(ifp, LP_RES_BW);
16f1b9ee 2835
d62a17ae 2836 return CMD_SUCCESS;
16f1b9ee
OD
2837}
2838
2839DEFUN (link_params_ava_bw,
2840 link_params_ava_bw_cmd,
2841 "ava-bw BANDWIDTH",
2842 "Unidirectional Available Bandwidth\n"
2843 "Bytes/second (IEEE floating point format)\n")
2844{
d62a17ae 2845 int idx_bandwidth = 1;
2846 VTY_DECLVAR_CONTEXT(interface, ifp);
2847 struct if_link_params *iflp = if_link_params_get(ifp);
2848 float bw;
16f1b9ee 2849
d62a17ae 2850 if (sscanf(argv[idx_bandwidth]->arg, "%g", &bw) != 1) {
2851 vty_out(vty, "link_params_ava_bw: fscanf: %s\n",
2852 safe_strerror(errno));
2853 return CMD_WARNING_CONFIG_FAILED;
2854 }
16f1b9ee 2855
d62a17ae 2856 /* Check that bandwidth is not greater than maximum bandwidth parameter
2857 */
2858 if (bw > iflp->max_bw) {
2859 vty_out(vty,
2860 "Available Bandwidth could not be greater than Maximum Bandwidth (%g)\n",
2861 iflp->max_bw);
2862 return CMD_WARNING_CONFIG_FAILED;
2863 }
16f1b9ee 2864
d62a17ae 2865 /* Update Residual Bandwidth if needed */
2866 link_param_cmd_set_float(ifp, &iflp->ava_bw, LP_AVA_BW, bw);
16f1b9ee 2867
d62a17ae 2868 return CMD_SUCCESS;
16f1b9ee
OD
2869}
2870
2871DEFUN (no_link_params_ava_bw,
2872 no_link_params_ava_bw_cmd,
2873 "no ava-bw",
2874 NO_STR
3ddccf18 2875 "Disable Unidirectional Available Bandwidth on this interface\n")
16f1b9ee 2876{
d62a17ae 2877 VTY_DECLVAR_CONTEXT(interface, ifp);
16f1b9ee 2878
d62a17ae 2879 /* Unset Available Bandwidth */
2880 link_param_cmd_unset(ifp, LP_AVA_BW);
16f1b9ee 2881
d62a17ae 2882 return CMD_SUCCESS;
16f1b9ee
OD
2883}
2884
2885DEFUN (link_params_use_bw,
2886 link_params_use_bw_cmd,
2887 "use-bw BANDWIDTH",
2888 "Unidirectional Utilised Bandwidth\n"
2889 "Bytes/second (IEEE floating point format)\n")
2890{
d62a17ae 2891 int idx_bandwidth = 1;
2892 VTY_DECLVAR_CONTEXT(interface, ifp);
2893 struct if_link_params *iflp = if_link_params_get(ifp);
2894 float bw;
16f1b9ee 2895
d62a17ae 2896 if (sscanf(argv[idx_bandwidth]->arg, "%g", &bw) != 1) {
2897 vty_out(vty, "link_params_use_bw: fscanf: %s\n",
2898 safe_strerror(errno));
2899 return CMD_WARNING_CONFIG_FAILED;
2900 }
16f1b9ee 2901
d62a17ae 2902 /* Check that bandwidth is not greater than maximum bandwidth parameter
2903 */
2904 if (bw > iflp->max_bw) {
2905 vty_out(vty,
2906 "Utilised Bandwidth could not be greater than Maximum Bandwidth (%g)\n",
2907 iflp->max_bw);
2908 return CMD_WARNING_CONFIG_FAILED;
2909 }
16f1b9ee 2910
d62a17ae 2911 /* Update Utilized Bandwidth if needed */
2912 link_param_cmd_set_float(ifp, &iflp->use_bw, LP_USE_BW, bw);
16f1b9ee 2913
d62a17ae 2914 return CMD_SUCCESS;
16f1b9ee
OD
2915}
2916
2917DEFUN (no_link_params_use_bw,
2918 no_link_params_use_bw_cmd,
2919 "no use-bw",
2920 NO_STR
3ddccf18 2921 "Disable Unidirectional Utilised Bandwidth on this interface\n")
16f1b9ee 2922{
d62a17ae 2923 VTY_DECLVAR_CONTEXT(interface, ifp);
16f1b9ee 2924
d62a17ae 2925 /* Unset Utilised Bandwidth */
2926 link_param_cmd_unset(ifp, LP_USE_BW);
16f1b9ee 2927
d62a17ae 2928 return CMD_SUCCESS;
16f1b9ee
OD
2929}
2930
09268680
CS
2931int if_ip_address_install(struct interface *ifp, struct prefix *prefix,
2932 const char *label, struct prefix *pp)
2933{
2934 struct zebra_if *if_data;
2935 struct prefix_ipv4 lp;
2936 struct prefix_ipv4 *p;
2937 struct connected *ifc;
2938 enum zebra_dplane_result dplane_res;
2939
2940 if_data = ifp->info;
2941
2942 lp.family = prefix->family;
2943 lp.prefix = prefix->u.prefix4;
2944 lp.prefixlen = prefix->prefixlen;
2945 apply_mask_ipv4(&lp);
2946
2947 ifc = connected_check_ptp(ifp, &lp, pp ? pp : NULL);
2948 if (!ifc) {
2949 ifc = connected_new();
2950 ifc->ifp = ifp;
2951
2952 /* Address. */
2953 p = prefix_ipv4_new();
2954 *p = lp;
2955 ifc->address = (struct prefix *)p;
2956
2957 if (pp) {
2958 SET_FLAG(ifc->flags, ZEBRA_IFA_PEER);
2959 p = prefix_ipv4_new();
2960 *p = *(struct prefix_ipv4 *)pp;
2961 ifc->destination = (struct prefix *)p;
2962 }
2963
2964 /* Label. */
2965 if (label)
2966 ifc->label = XSTRDUP(MTYPE_CONNECTED_LABEL, label);
2967
2968 /* Add to linked list. */
2969 listnode_add(ifp->connected, ifc);
2970 }
2971
2972 /* This address is configured from zebra. */
2973 if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED))
2974 SET_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED);
2975
2976 /* In case of this route need to install kernel. */
2977 if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_QUEUED)
2978 && CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE)
2979 && !(if_data && if_data->shutdown == IF_ZEBRA_SHUTDOWN_ON)) {
2980 /* Some system need to up the interface to set IP address. */
2981 if (!if_is_up(ifp)) {
2982 if_set_flags(ifp, IFF_UP | IFF_RUNNING);
2983 if_refresh(ifp);
2984 }
2985
2986 dplane_res = dplane_intf_addr_set(ifp, ifc);
2987 if (dplane_res == ZEBRA_DPLANE_REQUEST_FAILURE) {
2988 zlog_debug(
1d5453d6 2989 "dplane can't set interface IP address: %s.",
09268680
CS
2990 dplane_res2str(dplane_res));
2991 return NB_ERR;
2992 }
2993
2994 SET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED);
2995 /* The address will be advertised to zebra clients when the
2996 * notification
2997 * from the kernel has been received.
2998 * It will also be added to the subnet chain list, then. */
2999 }
3000
3001 return 0;
3002}
3003
d62a17ae 3004static int ip_address_install(struct vty *vty, struct interface *ifp,
3005 const char *addr_str, const char *peer_str,
3006 const char *label)
718e3744 3007{
d62a17ae 3008 struct zebra_if *if_data;
a07df329 3009 struct prefix_ipv4 lp, pp;
d62a17ae 3010 struct connected *ifc;
3011 struct prefix_ipv4 *p;
3012 int ret;
64168803 3013 enum zebra_dplane_result dplane_res;
718e3744 3014
d62a17ae 3015 if_data = ifp->info;
bfac8dcd 3016
a07df329 3017 ret = str2prefix_ipv4(addr_str, &lp);
d62a17ae 3018 if (ret <= 0) {
3019 vty_out(vty, "%% Malformed address \n");
3020 return CMD_WARNING_CONFIG_FAILED;
3021 }
718e3744 3022
a07df329 3023 if (ipv4_martian(&lp.prefix)) {
d62a17ae 3024 vty_out(vty, "%% Invalid address\n");
3025 return CMD_WARNING_CONFIG_FAILED;
3026 }
d914d5ff 3027
a07df329
DL
3028 if (peer_str) {
3029 if (lp.prefixlen != 32) {
3030 vty_out(vty,
3031 "%% Local prefix length for P-t-P address must be /32\n");
3032 return CMD_WARNING_CONFIG_FAILED;
3033 }
3034
3035 ret = str2prefix_ipv4(peer_str, &pp);
3036 if (ret <= 0) {
3037 vty_out(vty, "%% Malformed peer address\n");
3038 return CMD_WARNING_CONFIG_FAILED;
3039 }
3040 }
3041
3042 ifc = connected_check_ptp(ifp, &lp, peer_str ? &pp : NULL);
d62a17ae 3043 if (!ifc) {
3044 ifc = connected_new();
3045 ifc->ifp = ifp;
3046
3047 /* Address. */
3048 p = prefix_ipv4_new();
a07df329 3049 *p = lp;
d62a17ae 3050 ifc->address = (struct prefix *)p;
3051
a07df329
DL
3052 if (peer_str) {
3053 SET_FLAG(ifc->flags, ZEBRA_IFA_PEER);
3054 p = prefix_ipv4_new();
3055 *p = pp;
3056 ifc->destination = (struct prefix *)p;
d62a17ae 3057 }
718e3744 3058
d62a17ae 3059 /* Label. */
3060 if (label)
3061 ifc->label = XSTRDUP(MTYPE_CONNECTED_LABEL, label);
718e3744 3062
d62a17ae 3063 /* Add to linked list. */
3064 listnode_add(ifp->connected, ifc);
718e3744 3065 }
3066
d62a17ae 3067 /* This address is configured from zebra. */
3068 if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED))
3069 SET_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED);
3070
3071 /* In case of this route need to install kernel. */
3072 if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_QUEUED)
3073 && CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE)
3074 && !(if_data && if_data->shutdown == IF_ZEBRA_SHUTDOWN_ON)) {
3075 /* Some system need to up the interface to set IP address. */
3076 if (!if_is_up(ifp)) {
3077 if_set_flags(ifp, IFF_UP | IFF_RUNNING);
3078 if_refresh(ifp);
3079 }
3080
64168803
MS
3081 dplane_res = dplane_intf_addr_set(ifp, ifc);
3082 if (dplane_res == ZEBRA_DPLANE_REQUEST_FAILURE) {
d62a17ae 3083 vty_out(vty, "%% Can't set interface IP address: %s.\n",
64168803 3084 dplane_res2str(dplane_res));
d62a17ae 3085 return CMD_WARNING_CONFIG_FAILED;
3086 }
3087
3088 SET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED);
3089 /* The address will be advertised to zebra clients when the
3090 * notification
3091 * from the kernel has been received.
3092 * It will also be added to the subnet chain list, then. */
3093 }
3094
3095 return CMD_SUCCESS;
3096}
3097
09268680
CS
3098int if_ip_address_uinstall(struct interface *ifp, struct prefix *prefix)
3099{
3100 struct connected *ifc = NULL;
3101 enum zebra_dplane_result dplane_res;
3102
3103 if (prefix->family == AF_INET) {
3104 /* Check current interface address. */
3105 ifc = connected_check_ptp(ifp, prefix, NULL);
3106 if (!ifc) {
1d5453d6 3107 zlog_debug("interface %s Can't find address",
09268680
CS
3108 ifp->name);
3109 return -1;
3110 }
3111
3112 } else if (prefix->family == AF_INET6) {
3113 /* Check current interface address. */
3114 ifc = connected_check(ifp, prefix);
3115 }
3116
3117 if (!ifc) {
1d5453d6 3118 zlog_debug("interface %s Can't find address", ifp->name);
09268680
CS
3119 return -1;
3120 }
3121 UNSET_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED);
3122
3123 /* This is not real address or interface is not active. */
3124 if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_QUEUED)
3125 || !CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE)) {
3126 listnode_delete(ifp->connected, ifc);
3127 connected_free(&ifc);
3128 return CMD_WARNING_CONFIG_FAILED;
3129 }
3130
3131 /* This is real route. */
3132 dplane_res = dplane_intf_addr_unset(ifp, ifc);
3133 if (dplane_res == ZEBRA_DPLANE_REQUEST_FAILURE) {
1d5453d6 3134 zlog_debug("Can't unset interface IP address: %s.",
09268680
CS
3135 dplane_res2str(dplane_res));
3136 return -1;
3137 }
3138 UNSET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED);
3139
3140 return 0;
3141}
3142
d62a17ae 3143static int ip_address_uninstall(struct vty *vty, struct interface *ifp,
3144 const char *addr_str, const char *peer_str,
3145 const char *label)
3146{
a07df329 3147 struct prefix_ipv4 lp, pp;
d62a17ae 3148 struct connected *ifc;
3149 int ret;
64168803 3150 enum zebra_dplane_result dplane_res;
d62a17ae 3151
3152 /* Convert to prefix structure. */
a07df329 3153 ret = str2prefix_ipv4(addr_str, &lp);
d62a17ae 3154 if (ret <= 0) {
3155 vty_out(vty, "%% Malformed address \n");
3156 return CMD_WARNING_CONFIG_FAILED;
3157 }
3158
a07df329
DL
3159 if (peer_str) {
3160 if (lp.prefixlen != 32) {
3161 vty_out(vty,
3162 "%% Local prefix length for P-t-P address must be /32\n");
3163 return CMD_WARNING_CONFIG_FAILED;
3164 }
3165
3166 ret = str2prefix_ipv4(peer_str, &pp);
3167 if (ret <= 0) {
3168 vty_out(vty, "%% Malformed peer address\n");
3169 return CMD_WARNING_CONFIG_FAILED;
3170 }
3171 }
3172
d62a17ae 3173 /* Check current interface address. */
a07df329 3174 ifc = connected_check_ptp(ifp, &lp, peer_str ? &pp : NULL);
d62a17ae 3175 if (!ifc) {
3176 vty_out(vty, "%% Can't find address\n");
3177 return CMD_WARNING_CONFIG_FAILED;
3178 }
3179
3180 /* This is not configured address. */
3181 if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED))
3182 return CMD_WARNING_CONFIG_FAILED;
3183
3184 UNSET_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED);
3185
3186 /* This is not real address or interface is not active. */
3187 if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_QUEUED)
3188 || !CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE)) {
3189 listnode_delete(ifp->connected, ifc);
721c0857 3190 connected_free(&ifc);
d62a17ae 3191 return CMD_WARNING_CONFIG_FAILED;
3192 }
3193
3194 /* This is real route. */
64168803
MS
3195 dplane_res = dplane_intf_addr_unset(ifp, ifc);
3196 if (dplane_res == ZEBRA_DPLANE_REQUEST_FAILURE) {
d62a17ae 3197 vty_out(vty, "%% Can't unset interface IP address: %s.\n",
64168803 3198 dplane_res2str(dplane_res));
d62a17ae 3199 return CMD_WARNING_CONFIG_FAILED;
3200 }
3201 UNSET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED);
3202 /* we will receive a kernel notification about this route being removed.
3203 * this will trigger its removal from the connected list. */
3204 return CMD_SUCCESS;
718e3744 3205}
3206
3207DEFUN (ip_address,
3208 ip_address_cmd,
3209 "ip address A.B.C.D/M",
3210 "Interface Internet Protocol config commands\n"
3211 "Set the IP address of an interface\n"
3212 "IP address (e.g. 10.0.0.1/8)\n")
3213{
d62a17ae 3214 int idx_ipv4_prefixlen = 2;
3215 VTY_DECLVAR_CONTEXT(interface, ifp);
3216 return ip_address_install(vty, ifp, argv[idx_ipv4_prefixlen]->arg, NULL,
3217 NULL);
718e3744 3218}
3219
3220DEFUN (no_ip_address,
3221 no_ip_address_cmd,
3222 "no ip address A.B.C.D/M",
3223 NO_STR
3224 "Interface Internet Protocol config commands\n"
3225 "Set the IP address of an interface\n"
efd7904e 3226 "IP Address (e.g. 10.0.0.1/8)\n")
718e3744 3227{
d62a17ae 3228 int idx_ipv4_prefixlen = 3;
3229 VTY_DECLVAR_CONTEXT(interface, ifp);
3230 return ip_address_uninstall(vty, ifp, argv[idx_ipv4_prefixlen]->arg,
3231 NULL, NULL);
718e3744 3232}
3233
60466a63
QY
3234DEFUN(ip_address_peer,
3235 ip_address_peer_cmd,
3236 "ip address A.B.C.D peer A.B.C.D/M",
3237 "Interface Internet Protocol config commands\n"
3238 "Set the IP address of an interface\n"
3239 "Local IP (e.g. 10.0.0.1) for P-t-P address\n"
3240 "Specify P-t-P address\n"
3241 "Peer IP address (e.g. 10.0.0.1/8)\n")
a07df329
DL
3242{
3243 VTY_DECLVAR_CONTEXT(interface, ifp);
3244 return ip_address_install(vty, ifp, argv[2]->arg, argv[4]->arg, NULL);
3245}
3246
60466a63
QY
3247DEFUN(no_ip_address_peer,
3248 no_ip_address_peer_cmd,
3249 "no ip address A.B.C.D peer A.B.C.D/M",
3250 NO_STR
3251 "Interface Internet Protocol config commands\n"
3252 "Set the IP address of an interface\n"
3253 "Local IP (e.g. 10.0.0.1) for P-t-P address\n"
3254 "Specify P-t-P address\n"
3255 "Peer IP address (e.g. 10.0.0.1/8)\n")
a07df329
DL
3256{
3257 VTY_DECLVAR_CONTEXT(interface, ifp);
3258 return ip_address_uninstall(vty, ifp, argv[3]->arg, argv[5]->arg, NULL);
3259}
986aa00f 3260
718e3744 3261#ifdef HAVE_NETLINK
718e3744 3262DEFUN (ip_address_label,
3263 ip_address_label_cmd,
3264 "ip address A.B.C.D/M label LINE",
3265 "Interface Internet Protocol config commands\n"
3266 "Set the IP address of an interface\n"
3267 "IP address (e.g. 10.0.0.1/8)\n"
3268 "Label of this address\n"
3269 "Label\n")
3270{
d62a17ae 3271 int idx_ipv4_prefixlen = 2;
3272 int idx_line = 4;
3273 VTY_DECLVAR_CONTEXT(interface, ifp);
3274 return ip_address_install(vty, ifp, argv[idx_ipv4_prefixlen]->arg, NULL,
3275 argv[idx_line]->arg);
718e3744 3276}
3277
3278DEFUN (no_ip_address_label,
3279 no_ip_address_label_cmd,
3280 "no ip address A.B.C.D/M label LINE",
3281 NO_STR
3282 "Interface Internet Protocol config commands\n"
3283 "Set the IP address of an interface\n"
3284 "IP address (e.g. 10.0.0.1/8)\n"
3285 "Label of this address\n"
3286 "Label\n")
3287{
d62a17ae 3288 int idx_ipv4_prefixlen = 3;
3289 int idx_line = 5;
3290 VTY_DECLVAR_CONTEXT(interface, ifp);
3291 return ip_address_uninstall(vty, ifp, argv[idx_ipv4_prefixlen]->arg,
3292 NULL, argv[idx_line]->arg);
718e3744 3293}
3294#endif /* HAVE_NETLINK */
3295
09268680
CS
3296int if_ipv6_address_install(struct interface *ifp, struct prefix *prefix,
3297 const char *label)
3298{
3299 struct zebra_if *if_data;
3300 struct prefix_ipv6 cp;
3301 struct connected *ifc;
3302 struct prefix_ipv6 *p;
3303 enum zebra_dplane_result dplane_res;
3304
3305 if_data = ifp->info;
3306
3307 cp.family = prefix->family;
3308 cp.prefixlen = prefix->prefixlen;
3309 cp.prefix = prefix->u.prefix6;
3310 apply_mask_ipv6(&cp);
3311
3312 ifc = connected_check(ifp, (struct prefix *)&cp);
3313 if (!ifc) {
3314 ifc = connected_new();
3315 ifc->ifp = ifp;
3316
3317 /* Address. */
3318 p = prefix_ipv6_new();
3319 *p = cp;
3320 ifc->address = (struct prefix *)p;
3321
3322 /* Label. */
3323 if (label)
3324 ifc->label = XSTRDUP(MTYPE_CONNECTED_LABEL, label);
3325
3326 /* Add to linked list. */
3327 listnode_add(ifp->connected, ifc);
3328 }
3329
3330 /* This address is configured from zebra. */
3331 if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED))
3332 SET_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED);
3333
3334 /* In case of this route need to install kernel. */
3335 if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_QUEUED)
3336 && CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE)
3337 && !(if_data && if_data->shutdown == IF_ZEBRA_SHUTDOWN_ON)) {
3338 /* Some system need to up the interface to set IP address. */
3339 if (!if_is_up(ifp)) {
3340 if_set_flags(ifp, IFF_UP | IFF_RUNNING);
3341 if_refresh(ifp);
3342 }
3343
3344 dplane_res = dplane_intf_addr_set(ifp, ifc);
3345 if (dplane_res == ZEBRA_DPLANE_REQUEST_FAILURE) {
3346 zlog_debug(
1d5453d6 3347 "dplane can't set interface IP address: %s.",
09268680
CS
3348 dplane_res2str(dplane_res));
3349 return NB_ERR;
3350 }
3351
3352 SET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED);
3353 /* The address will be advertised to zebra clients when the
3354 * notification
3355 * from the kernel has been received. */
3356 }
3357
3358 return 0;
3359}
3360
d62a17ae 3361static int ipv6_address_install(struct vty *vty, struct interface *ifp,
3362 const char *addr_str, const char *peer_str,
b1bd1015 3363 const char *label)
d62a17ae 3364{
3365 struct zebra_if *if_data;
3366 struct prefix_ipv6 cp;
3367 struct connected *ifc;
3368 struct prefix_ipv6 *p;
3369 int ret;
0f1f6ce4 3370 enum zebra_dplane_result dplane_res;
d62a17ae 3371
3372 if_data = ifp->info;
3373
3374 ret = str2prefix_ipv6(addr_str, &cp);
3375 if (ret <= 0) {
3376 vty_out(vty, "%% Malformed address \n");
3377 return CMD_WARNING_CONFIG_FAILED;
718e3744 3378 }
3379
d62a17ae 3380 if (ipv6_martian(&cp.prefix)) {
3381 vty_out(vty, "%% Invalid address\n");
3382 return CMD_WARNING_CONFIG_FAILED;
3383 }
718e3744 3384
d62a17ae 3385 ifc = connected_check(ifp, (struct prefix *)&cp);
3386 if (!ifc) {
3387 ifc = connected_new();
3388 ifc->ifp = ifp;
3389
3390 /* Address. */
3391 p = prefix_ipv6_new();
3392 *p = cp;
3393 ifc->address = (struct prefix *)p;
3394
d62a17ae 3395 /* Label. */
3396 if (label)
3397 ifc->label = XSTRDUP(MTYPE_CONNECTED_LABEL, label);
3398
3399 /* Add to linked list. */
3400 listnode_add(ifp->connected, ifc);
718e3744 3401 }
3402
d62a17ae 3403 /* This address is configured from zebra. */
3404 if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED))
3405 SET_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED);
3406
3407 /* In case of this route need to install kernel. */
3408 if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_QUEUED)
3409 && CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE)
3410 && !(if_data && if_data->shutdown == IF_ZEBRA_SHUTDOWN_ON)) {
3411 /* Some system need to up the interface to set IP address. */
3412 if (!if_is_up(ifp)) {
3413 if_set_flags(ifp, IFF_UP | IFF_RUNNING);
3414 if_refresh(ifp);
3415 }
3416
0f1f6ce4
MS
3417 dplane_res = dplane_intf_addr_set(ifp, ifc);
3418 if (dplane_res == ZEBRA_DPLANE_REQUEST_FAILURE) {
d62a17ae 3419 vty_out(vty, "%% Can't set interface IP address: %s.\n",
0f1f6ce4 3420 dplane_res2str(dplane_res));
d62a17ae 3421 return CMD_WARNING_CONFIG_FAILED;
3422 }
3423
3424 SET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED);
3425 /* The address will be advertised to zebra clients when the
3426 * notification
3427 * from the kernel has been received. */
3428 }
718e3744 3429
d62a17ae 3430 return CMD_SUCCESS;
718e3744 3431}
3432
b6120505 3433/* Return true if an ipv6 address is configured on ifp */
d62a17ae 3434int ipv6_address_configured(struct interface *ifp)
3435{
3436 struct connected *connected;
3437 struct listnode *node;
3438
3439 for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, connected))
3440 if (CHECK_FLAG(connected->conf, ZEBRA_IFC_REAL)
3441 && (connected->address->family == AF_INET6))
3442 return 1;
3443
3444 return 0;
3445}
3446
3447static int ipv6_address_uninstall(struct vty *vty, struct interface *ifp,
3448 const char *addr_str, const char *peer_str,
b1bd1015 3449 const char *label)
d62a17ae 3450{
3451 struct prefix_ipv6 cp;
3452 struct connected *ifc;
3453 int ret;
0f1f6ce4 3454 enum zebra_dplane_result dplane_res;
d62a17ae 3455
3456 /* Convert to prefix structure. */
3457 ret = str2prefix_ipv6(addr_str, &cp);
3458 if (ret <= 0) {
3459 vty_out(vty, "%% Malformed address \n");
3460 return CMD_WARNING_CONFIG_FAILED;
3461 }
3462
3463 /* Check current interface address. */
3464 ifc = connected_check(ifp, (struct prefix *)&cp);
3465 if (!ifc) {
3466 vty_out(vty, "%% Can't find address\n");
3467 return CMD_WARNING_CONFIG_FAILED;
3468 }
3469
3470 /* This is not configured address. */
3471 if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED))
3472 return CMD_WARNING_CONFIG_FAILED;
3473
3474 UNSET_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED);
3475
3476 /* This is not real address or interface is not active. */
3477 if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_QUEUED)
3478 || !CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE)) {
3479 listnode_delete(ifp->connected, ifc);
721c0857 3480 connected_free(&ifc);
d62a17ae 3481 return CMD_WARNING_CONFIG_FAILED;
3482 }
3483
3484 /* This is real route. */
0f1f6ce4
MS
3485 dplane_res = dplane_intf_addr_unset(ifp, ifc);
3486 if (dplane_res == ZEBRA_DPLANE_REQUEST_FAILURE) {
d62a17ae 3487 vty_out(vty, "%% Can't unset interface IP address: %s.\n",
0f1f6ce4 3488 dplane_res2str(dplane_res));
d62a17ae 3489 return CMD_WARNING_CONFIG_FAILED;
3490 }
3491
3492 UNSET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED);
3493 /* This information will be propagated to the zclients when the
3494 * kernel notification is received. */
3495 return CMD_SUCCESS;
718e3744 3496}
3497
3498DEFUN (ipv6_address,
3499 ipv6_address_cmd,
3500 "ipv6 address X:X::X:X/M",
e23949c0 3501 "Interface IPv6 config commands\n"
718e3744 3502 "Set the IP address of an interface\n"
3503 "IPv6 address (e.g. 3ffe:506::1/48)\n")
3504{
d62a17ae 3505 int idx_ipv6_prefixlen = 2;
3506 VTY_DECLVAR_CONTEXT(interface, ifp);
3507 return ipv6_address_install(vty, ifp, argv[idx_ipv6_prefixlen]->arg,
b1bd1015 3508 NULL, NULL);
718e3744 3509}
3510
3511DEFUN (no_ipv6_address,
3512 no_ipv6_address_cmd,
3513 "no ipv6 address X:X::X:X/M",
3514 NO_STR
e23949c0 3515 "Interface IPv6 config commands\n"
718e3744 3516 "Set the IP address of an interface\n"
3517 "IPv6 address (e.g. 3ffe:506::1/48)\n")
3518{
d62a17ae 3519 int idx_ipv6_prefixlen = 3;
3520 VTY_DECLVAR_CONTEXT(interface, ifp);
3521 return ipv6_address_uninstall(vty, ifp, argv[idx_ipv6_prefixlen]->arg,
b1bd1015 3522 NULL, NULL);
d62a17ae 3523}
3524
3525static int link_params_config_write(struct vty *vty, struct interface *ifp)
3526{
3527 int i;
3528
3529 if ((ifp == NULL) || !HAS_LINK_PARAMS(ifp))
3530 return -1;
986aa00f 3531
d62a17ae 3532 struct if_link_params *iflp = ifp->link_params;
3533
3534 vty_out(vty, " link-params\n");
3535 vty_out(vty, " enable\n");
3536 if (IS_PARAM_SET(iflp, LP_TE_METRIC) && iflp->te_metric != ifp->metric)
3537 vty_out(vty, " metric %u\n", iflp->te_metric);
3538 if (IS_PARAM_SET(iflp, LP_MAX_BW) && iflp->max_bw != iflp->default_bw)
3539 vty_out(vty, " max-bw %g\n", iflp->max_bw);
3540 if (IS_PARAM_SET(iflp, LP_MAX_RSV_BW)
3541 && iflp->max_rsv_bw != iflp->default_bw)
3542 vty_out(vty, " max-rsv-bw %g\n", iflp->max_rsv_bw);
3543 if (IS_PARAM_SET(iflp, LP_UNRSV_BW)) {
3544 for (i = 0; i < 8; i++)
3545 if (iflp->unrsv_bw[i] != iflp->default_bw)
3546 vty_out(vty, " unrsv-bw %d %g\n", i,
3547 iflp->unrsv_bw[i]);
3548 }
3549 if (IS_PARAM_SET(iflp, LP_ADM_GRP))
3550 vty_out(vty, " admin-grp 0x%x\n", iflp->admin_grp);
3551 if (IS_PARAM_SET(iflp, LP_DELAY)) {
3552 vty_out(vty, " delay %u", iflp->av_delay);
3553 if (IS_PARAM_SET(iflp, LP_MM_DELAY)) {
3554 vty_out(vty, " min %u", iflp->min_delay);
3555 vty_out(vty, " max %u", iflp->max_delay);
3556 }
3557 vty_out(vty, "\n");
bfac8dcd 3558 }
d62a17ae 3559 if (IS_PARAM_SET(iflp, LP_DELAY_VAR))
3560 vty_out(vty, " delay-variation %u\n", iflp->delay_var);
3561 if (IS_PARAM_SET(iflp, LP_PKT_LOSS))
3562 vty_out(vty, " packet-loss %g\n", iflp->pkt_loss);
3563 if (IS_PARAM_SET(iflp, LP_AVA_BW))
3564 vty_out(vty, " ava-bw %g\n", iflp->ava_bw);
3565 if (IS_PARAM_SET(iflp, LP_RES_BW))
3566 vty_out(vty, " res-bw %g\n", iflp->res_bw);
3567 if (IS_PARAM_SET(iflp, LP_USE_BW))
3568 vty_out(vty, " use-bw %g\n", iflp->use_bw);
3569 if (IS_PARAM_SET(iflp, LP_RMT_AS))
9bcef951 3570 vty_out(vty, " neighbor %pI4 as %u\n", &iflp->rmt_ip,
d62a17ae 3571 iflp->rmt_as);
3572 vty_out(vty, " exit-link-params\n");
3573 return 0;
3574}
3575
3576static int if_config_write(struct vty *vty)
3577{
7fe96307 3578 struct vrf *vrf0;
d62a17ae 3579 struct interface *ifp;
3580
3581 zebra_ptm_write(vty);
3582
7fe96307
A
3583 RB_FOREACH (vrf0, vrf_name_head, &vrfs_by_name)
3584 FOR_ALL_INTERFACES (vrf0, ifp) {
a2addae8
RW
3585 struct zebra_if *if_data;
3586 struct listnode *addrnode;
3587 struct connected *ifc;
3588 struct prefix *p;
3589 struct vrf *vrf;
d62a17ae 3590
a2addae8 3591 if_data = ifp->info;
a36898e7 3592 vrf = vrf_lookup_by_id(ifp->vrf_id);
d62a17ae 3593
a36898e7 3594 if (ifp->vrf_id == VRF_DEFAULT)
a2addae8
RW
3595 vty_frame(vty, "interface %s\n", ifp->name);
3596 else
3597 vty_frame(vty, "interface %s vrf %s\n",
3598 ifp->name, vrf->name);
d62a17ae 3599
a2addae8
RW
3600 if (if_data) {
3601 if (if_data->shutdown == IF_ZEBRA_SHUTDOWN_ON)
3602 vty_out(vty, " shutdown\n");
d62a17ae 3603
a2addae8
RW
3604 zebra_ptm_if_write(vty, if_data);
3605 }
bfac8dcd 3606
a2addae8
RW
3607 if (ifp->desc)
3608 vty_out(vty, " description %s\n", ifp->desc);
3609
3610 /* Assign bandwidth here to avoid unnecessary interface
3611 flap
3612 while processing config script */
3613 if (ifp->bandwidth != 0)
3614 vty_out(vty, " bandwidth %u\n", ifp->bandwidth);
3615
3616 if (!CHECK_FLAG(ifp->status,
3617 ZEBRA_INTERFACE_LINKDETECTION))
3618 vty_out(vty, " no link-detect\n");
3619
3620 for (ALL_LIST_ELEMENTS_RO(ifp->connected, addrnode,
3621 ifc)) {
3622 if (CHECK_FLAG(ifc->conf,
3623 ZEBRA_IFC_CONFIGURED)) {
3624 char buf[INET6_ADDRSTRLEN];
3625 p = ifc->address;
3626 vty_out(vty, " ip%s address %s",
3627 p->family == AF_INET ? ""
3628 : "v6",
a07df329 3629 inet_ntop(p->family,
60466a63
QY
3630 &p->u.prefix, buf,
3631 sizeof(buf)));
a2addae8
RW
3632 if (CONNECTED_PEER(ifc)) {
3633 p = ifc->destination;
3634 vty_out(vty, " peer %s",
3635 inet_ntop(p->family,
3636 &p->u.prefix,
3637 buf,
3638 sizeof(buf)));
3639 }
3640 vty_out(vty, "/%d", p->prefixlen);
718e3744 3641
a2addae8
RW
3642 if (ifc->label)
3643 vty_out(vty, " label %s",
3644 ifc->label);
718e3744 3645
a2addae8
RW
3646 vty_out(vty, "\n");
3647 }
d62a17ae 3648 }
718e3744 3649
a2addae8
RW
3650 if (if_data) {
3651 if (if_data->multicast
3652 != IF_ZEBRA_MULTICAST_UNSPEC)
3653 vty_out(vty, " %smulticast\n",
3654 if_data->multicast
3655 == IF_ZEBRA_MULTICAST_ON
3656 ? ""
3657 : "no ");
3658 }
718e3744 3659
a2addae8 3660 hook_call(zebra_if_config_wr, vty, ifp);
ce5160c0 3661 zebra_evpn_mh_if_write(vty, ifp);
a2addae8 3662 link_params_config_write(vty, ifp);
16f1b9ee 3663
a2addae8
RW
3664 vty_endframe(vty, "!\n");
3665 }
d62a17ae 3666 return 0;
718e3744 3667}
3668
3669/* Allocate and initialize interface vector. */
d62a17ae 3670void zebra_if_init(void)
3671{
3672 /* Initialize interface and new hook. */
ce19a04a
DL
3673 hook_register_prio(if_add, 0, if_zebra_new_hook);
3674 hook_register_prio(if_del, 0, if_zebra_delete_hook);
d62a17ae 3675
3676 /* Install configuration write function. */
612c2c15
DL
3677 install_node(&interface_node);
3678 install_node(&link_params_node);
d62a17ae 3679 if_cmd_init();
138c5a74
DS
3680 /*
3681 * This is *intentionally* setting this to NULL, signaling
3682 * that interface creation for zebra acts differently
3683 */
3684 if_zapi_callbacks(NULL, NULL, NULL, NULL);
d62a17ae 3685
3686 install_element(VIEW_NODE, &show_interface_cmd);
3687 install_element(VIEW_NODE, &show_interface_vrf_all_cmd);
3688 install_element(VIEW_NODE, &show_interface_name_vrf_cmd);
3689 install_element(VIEW_NODE, &show_interface_name_vrf_all_cmd);
3690
3691 install_element(ENABLE_NODE, &show_interface_desc_cmd);
3692 install_element(ENABLE_NODE, &show_interface_desc_vrf_all_cmd);
3693 install_element(INTERFACE_NODE, &multicast_cmd);
3694 install_element(INTERFACE_NODE, &no_multicast_cmd);
3695 install_element(INTERFACE_NODE, &linkdetect_cmd);
3696 install_element(INTERFACE_NODE, &no_linkdetect_cmd);
3697 install_element(INTERFACE_NODE, &shutdown_if_cmd);
3698 install_element(INTERFACE_NODE, &no_shutdown_if_cmd);
3699 install_element(INTERFACE_NODE, &bandwidth_if_cmd);
3700 install_element(INTERFACE_NODE, &no_bandwidth_if_cmd);
3701 install_element(INTERFACE_NODE, &ip_address_cmd);
3702 install_element(INTERFACE_NODE, &no_ip_address_cmd);
a07df329
DL
3703 install_element(INTERFACE_NODE, &ip_address_peer_cmd);
3704 install_element(INTERFACE_NODE, &no_ip_address_peer_cmd);
d62a17ae 3705 install_element(INTERFACE_NODE, &ipv6_address_cmd);
3706 install_element(INTERFACE_NODE, &no_ipv6_address_cmd);
718e3744 3707#ifdef HAVE_NETLINK
d62a17ae 3708 install_element(INTERFACE_NODE, &ip_address_label_cmd);
3709 install_element(INTERFACE_NODE, &no_ip_address_label_cmd);
718e3744 3710#endif /* HAVE_NETLINK */
d62a17ae 3711 install_element(INTERFACE_NODE, &link_params_cmd);
3712 install_default(LINK_PARAMS_NODE);
3713 install_element(LINK_PARAMS_NODE, &link_params_enable_cmd);
3714 install_element(LINK_PARAMS_NODE, &no_link_params_enable_cmd);
3715 install_element(LINK_PARAMS_NODE, &link_params_metric_cmd);
3716 install_element(LINK_PARAMS_NODE, &no_link_params_metric_cmd);
3717 install_element(LINK_PARAMS_NODE, &link_params_maxbw_cmd);
3718 install_element(LINK_PARAMS_NODE, &link_params_max_rsv_bw_cmd);
3719 install_element(LINK_PARAMS_NODE, &link_params_unrsv_bw_cmd);
3720 install_element(LINK_PARAMS_NODE, &link_params_admin_grp_cmd);
3721 install_element(LINK_PARAMS_NODE, &no_link_params_admin_grp_cmd);
3722 install_element(LINK_PARAMS_NODE, &link_params_inter_as_cmd);
3723 install_element(LINK_PARAMS_NODE, &no_link_params_inter_as_cmd);
3724 install_element(LINK_PARAMS_NODE, &link_params_delay_cmd);
3725 install_element(LINK_PARAMS_NODE, &no_link_params_delay_cmd);
3726 install_element(LINK_PARAMS_NODE, &link_params_delay_var_cmd);
3727 install_element(LINK_PARAMS_NODE, &no_link_params_delay_var_cmd);
3728 install_element(LINK_PARAMS_NODE, &link_params_pkt_loss_cmd);
3729 install_element(LINK_PARAMS_NODE, &no_link_params_pkt_loss_cmd);
3730 install_element(LINK_PARAMS_NODE, &link_params_ava_bw_cmd);
3731 install_element(LINK_PARAMS_NODE, &no_link_params_ava_bw_cmd);
3732 install_element(LINK_PARAMS_NODE, &link_params_res_bw_cmd);
3733 install_element(LINK_PARAMS_NODE, &no_link_params_res_bw_cmd);
3734 install_element(LINK_PARAMS_NODE, &link_params_use_bw_cmd);
3735 install_element(LINK_PARAMS_NODE, &no_link_params_use_bw_cmd);
3736 install_element(LINK_PARAMS_NODE, &exit_link_params_cmd);
ce5160c0
AK
3737
3738 /* setup EVPN MH elements */
3739 zebra_evpn_interface_init();
718e3744 3740}