]> git.proxmox.com Git - mirror_frr.git/blame - zebra/interface.c
Merge branch 'master' into stylechecker
[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"
25#include "vty.h"
26#include "sockunion.h"
27#include "prefix.h"
28#include "command.h"
29#include "memory.h"
4a1ab8e4 30#include "zebra_memory.h"
718e3744 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"
718e3744 43#include "zebra/zserv.h"
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"
88177fe3 49#include "zebra/interface.h"
13d60d35 50#include "zebra/zebra_vxlan.h"
c3c04063 51#include "zebra/zebra_static.h"
244c1cdc
DS
52
53#define ZEBRA_PTM_SUPPORT
718e3744 54
996c9314
LB
55DEFINE_HOOK(zebra_if_extra_info, (struct vty * vty, struct interface *ifp),
56 (vty, ifp))
57DEFINE_HOOK(zebra_if_config_wr, (struct vty * vty, struct interface *ifp),
58 (vty, ifp))
718e3744 59
dc7b3cae 60
d62a17ae 61static void if_down_del_nbr_connected(struct interface *ifp);
c8e264b6 62
dc7b3cae
DS
63static int if_zebra_speed_update(struct thread *thread)
64{
65 struct interface *ifp = THREAD_ARG(thread);
66 struct zebra_if *zif = ifp->info;
67 uint32_t new_speed;
68
69 zif->speed_update = NULL;
70
71 new_speed = kernel_get_speed(ifp);
72 if (new_speed != ifp->speed) {
73 zlog_info("%s: %s old speed: %u new speed: %u",
996c9314
LB
74 __PRETTY_FUNCTION__, ifp->name, ifp->speed,
75 new_speed);
dc7b3cae
DS
76 ifp->speed = new_speed;
77 if_add_update(ifp);
78 }
79
80 return 1;
81}
82
d62a17ae 83static void zebra_if_node_destroy(route_table_delegate_t *delegate,
84 struct route_table *table,
85 struct route_node *node)
58ac32e2 86{
d62a17ae 87 if (node->info)
affe9e99 88 list_delete_and_null((struct list **)&node->info);
d62a17ae 89 route_node_destroy(delegate, table, node);
58ac32e2
RW
90}
91
92route_table_delegate_t zebra_if_table_delegate = {
d62a17ae 93 .create_node = route_node_create,
94 .destroy_node = zebra_if_node_destroy};
58ac32e2 95
718e3744 96/* Called when new interface is added. */
d62a17ae 97static int if_zebra_new_hook(struct interface *ifp)
98{
99 struct zebra_if *zebra_if;
100
101 zebra_if = XCALLOC(MTYPE_TMP, sizeof(struct zebra_if));
102
103 zebra_if->multicast = IF_ZEBRA_MULTICAST_UNSPEC;
104 zebra_if->shutdown = IF_ZEBRA_SHUTDOWN_OFF;
105 zebra_ptm_if_init(zebra_if);
106
107 ifp->ptm_enable = zebra_ptm_get_enable_state();
108#if defined(HAVE_RTADV)
109 {
110 /* Set default router advertise values. */
111 struct rtadvconf *rtadv;
112
113 rtadv = &zebra_if->rtadv;
114
115 rtadv->AdvSendAdvertisements = 0;
116 rtadv->MaxRtrAdvInterval = RTADV_MAX_RTR_ADV_INTERVAL;
117 rtadv->MinRtrAdvInterval = RTADV_MIN_RTR_ADV_INTERVAL;
118 rtadv->AdvIntervalTimer = 0;
119 rtadv->AdvManagedFlag = 0;
120 rtadv->AdvOtherConfigFlag = 0;
121 rtadv->AdvHomeAgentFlag = 0;
122 rtadv->AdvLinkMTU = 0;
123 rtadv->AdvReachableTime = 0;
124 rtadv->AdvRetransTimer = 0;
125 rtadv->AdvCurHopLimit = 0;
126 rtadv->AdvDefaultLifetime =
127 -1; /* derive from MaxRtrAdvInterval */
128 rtadv->HomeAgentPreference = 0;
129 rtadv->HomeAgentLifetime =
130 -1; /* derive from AdvDefaultLifetime */
131 rtadv->AdvIntervalOption = 0;
132 rtadv->DefaultPreference = RTADV_PREF_MEDIUM;
133
134 rtadv->AdvPrefixList = list_new();
135 }
8da4e946 136#endif /* HAVE_RTADV */
718e3744 137
d62a17ae 138 /* Initialize installed address chains tree. */
139 zebra_if->ipv4_subnets =
140 route_table_init_with_delegate(&zebra_if_table_delegate);
eef1fe11 141
d62a17ae 142 ifp->info = zebra_if;
dc7b3cae
DS
143
144 /*
145 * Some platforms are telling us that the interface is
146 * up and ready to go. When we check the speed we
147 * sometimes get the wrong value. Wait a couple
148 * of seconds and ask again. Hopefully it's all settled
149 * down upon startup.
150 */
996c9314
LB
151 thread_add_timer(zebrad.master, if_zebra_speed_update, ifp, 15,
152 &zebra_if->speed_update);
d62a17ae 153 return 0;
718e3744 154}
155
156/* Called when interface is deleted. */
d62a17ae 157static int if_zebra_delete_hook(struct interface *ifp)
718e3744 158{
d62a17ae 159 struct zebra_if *zebra_if;
eef1fe11 160
d62a17ae 161 if (ifp->info) {
162 zebra_if = ifp->info;
3f6d6a5d 163
d62a17ae 164 /* Free installed address chains tree. */
165 if (zebra_if->ipv4_subnets)
166 route_table_finish(zebra_if->ipv4_subnets);
167#if defined(HAVE_RTADV)
3f6d6a5d 168
d62a17ae 169 struct rtadvconf *rtadv;
eef1fe11 170
d62a17ae 171 rtadv = &zebra_if->rtadv;
acdf5e25 172 list_delete_and_null(&rtadv->AdvPrefixList);
d62a17ae 173#endif /* HAVE_RTADV */
eef1fe11 174
dc7b3cae
DS
175 THREAD_OFF(zebra_if->speed_update);
176
d62a17ae 177 XFREE(MTYPE_TMP, zebra_if);
178 }
179
180 return 0;
eef1fe11 181}
182
12f6fb97 183/* Build the table key */
d62a17ae 184static void if_build_key(u_int32_t ifindex, struct prefix *p)
12f6fb97 185{
d62a17ae 186 p->family = AF_INET;
187 p->prefixlen = IPV4_MAX_BITLEN;
188 p->u.prefix4.s_addr = ifindex;
12f6fb97
DS
189}
190
191/* Link an interface in a per NS interface tree */
d62a17ae 192struct interface *if_link_per_ns(struct zebra_ns *ns, struct interface *ifp)
12f6fb97 193{
d62a17ae 194 struct prefix p;
195 struct route_node *rn;
12f6fb97 196
d62a17ae 197 if (ifp->ifindex == IFINDEX_INTERNAL)
198 return NULL;
12f6fb97 199
d62a17ae 200 if_build_key(ifp->ifindex, &p);
201 rn = route_node_get(ns->if_table, &p);
202 if (rn->info) {
203 ifp = (struct interface *)rn->info;
204 route_unlock_node(rn); /* get */
205 return ifp;
206 }
12f6fb97 207
d62a17ae 208 rn->info = ifp;
209 ifp->node = rn;
12f6fb97 210
d62a17ae 211 return ifp;
12f6fb97
DS
212}
213
214/* Delete a VRF. This is called in vrf_terminate(). */
d62a17ae 215void if_unlink_per_ns(struct interface *ifp)
12f6fb97 216{
d62a17ae 217 ifp->node->info = NULL;
218 route_unlock_node(ifp->node);
219 ifp->node = NULL;
12f6fb97
DS
220}
221
222/* Look up an interface by identifier within a NS */
d62a17ae 223struct interface *if_lookup_by_index_per_ns(struct zebra_ns *ns,
224 u_int32_t ifindex)
225{
226 struct prefix p;
227 struct route_node *rn;
228 struct interface *ifp = NULL;
229
230 if_build_key(ifindex, &p);
231 rn = route_node_lookup(ns->if_table, &p);
232 if (rn) {
233 ifp = (struct interface *)rn->info;
234 route_unlock_node(rn); /* lookup */
235 }
236 return ifp;
12f6fb97
DS
237}
238
b8af3fbb 239/* Look up an interface by name within a NS */
d62a17ae 240struct interface *if_lookup_by_name_per_ns(struct zebra_ns *ns,
241 const char *ifname)
b8af3fbb 242{
d62a17ae 243 struct route_node *rn;
244 struct interface *ifp;
b8af3fbb 245
d62a17ae 246 for (rn = route_top(ns->if_table); rn; rn = route_next(rn)) {
247 ifp = (struct interface *)rn->info;
248 if (ifp && strcmp(ifp->name, ifname) == 0)
249 return (ifp);
250 }
b8af3fbb 251
d62a17ae 252 return NULL;
b8af3fbb
RW
253}
254
d62a17ae 255const char *ifindex2ifname_per_ns(struct zebra_ns *zns, unsigned int ifindex)
a815b788 256{
d62a17ae 257 struct interface *ifp;
a815b788 258
d62a17ae 259 return ((ifp = if_lookup_by_index_per_ns(zns, ifindex)) != NULL)
260 ? ifp->name
261 : "unknown";
a815b788 262}
12f6fb97 263
eef1fe11 264/* Tie an interface address to its derived subnet list of addresses. */
d62a17ae 265int if_subnet_add(struct interface *ifp, struct connected *ifc)
266{
267 struct route_node *rn;
268 struct zebra_if *zebra_if;
269 struct prefix cp;
270 struct list *addr_list;
271
272 assert(ifp && ifp->info && ifc);
273 zebra_if = ifp->info;
274
275 /* Get address derived subnet node and associated address list, while
276 marking
277 address secondary attribute appropriately. */
abffde07 278 cp = *CONNECTED_PREFIX(ifc);
d62a17ae 279 apply_mask(&cp);
280 rn = route_node_get(zebra_if->ipv4_subnets, &cp);
281
282 if ((addr_list = rn->info))
283 SET_FLAG(ifc->flags, ZEBRA_IFA_SECONDARY);
284 else {
285 UNSET_FLAG(ifc->flags, ZEBRA_IFA_SECONDARY);
286 rn->info = addr_list = list_new();
287 route_lock_node(rn);
288 }
289
290 /* Tie address at the tail of address list. */
291 listnode_add(addr_list, ifc);
292
293 /* Return list element count. */
294 return (addr_list->count);
eef1fe11 295}
296
297/* Untie an interface address from its derived subnet list of addresses. */
d62a17ae 298int if_subnet_delete(struct interface *ifp, struct connected *ifc)
299{
300 struct route_node *rn;
301 struct zebra_if *zebra_if;
302 struct list *addr_list;
abffde07 303 struct prefix cp;
d62a17ae 304
305 assert(ifp && ifp->info && ifc);
306 zebra_if = ifp->info;
307
abffde07
DL
308 cp = *CONNECTED_PREFIX(ifc);
309 apply_mask(&cp);
310
d62a17ae 311 /* Get address derived subnet node. */
abffde07 312 rn = route_node_lookup(zebra_if->ipv4_subnets, &cp);
d62a17ae 313 if (!(rn && rn->info)) {
314 zlog_warn(
315 "Trying to remove an address from an unknown subnet."
316 " (please report this bug)");
317 return -1;
318 }
319 route_unlock_node(rn);
320
321 /* Untie address from subnet's address list. */
322 addr_list = rn->info;
323
324 /* Deleting an address that is not registered is a bug.
325 * In any case, we shouldn't decrement the lock counter if the address
326 * is unknown. */
327 if (!listnode_lookup(addr_list, ifc)) {
328 zlog_warn(
329 "Trying to remove an address from a subnet where it is not"
330 " currently registered. (please report this bug)");
331 return -1;
332 }
333
334 listnode_delete(addr_list, ifc);
335 route_unlock_node(rn);
336
337 /* Return list element count, if not empty. */
338 if (addr_list->count) {
339 /* If deleted address is primary, mark subsequent one as such
340 * and distribute. */
341 if (!CHECK_FLAG(ifc->flags, ZEBRA_IFA_SECONDARY)) {
342 ifc = listgetdata(
343 (struct listnode *)listhead(addr_list));
344 zebra_interface_address_delete_update(ifp, ifc);
345 UNSET_FLAG(ifc->flags, ZEBRA_IFA_SECONDARY);
346 /* XXX: Linux kernel removes all the secondary addresses
347 * when the primary
348 * address is removed. We could try to work around that,
349 * though this is
350 * non-trivial. */
351 zebra_interface_address_add_update(ifp, ifc);
352 }
353
354 return addr_list->count;
355 }
356
357 /* Otherwise, free list and route node. */
acdf5e25 358 list_delete_and_null(&addr_list);
d62a17ae 359 rn->info = NULL;
360 route_unlock_node(rn);
361
362 return 0;
718e3744 363}
364
5c78b3d0 365/* if_flags_mangle: A place for hacks that require mangling
366 * or tweaking the interface flags.
367 *
368 * ******************** Solaris flags hacks **************************
369 *
370 * Solaris IFF_UP flag reflects only the primary interface as the
d62a17ae 371 * routing socket only sends IFINFO for the primary interface. Hence
372 * ~IFF_UP does not per se imply all the logical interfaces are also
5c78b3d0 373 * down - which we only know of as addresses. Instead we must determine
d62a17ae 374 * whether the interface really is up or not according to how many
5c78b3d0 375 * addresses are still attached. (Solaris always sends RTM_DELADDR if
376 * an interface, logical or not, goes ~IFF_UP).
377 *
378 * Ie, we mangle IFF_UP to *additionally* reflect whether or not there
379 * are addresses left in struct connected, not just the actual underlying
380 * IFF_UP flag.
381 *
382 * We must hence remember the real state of IFF_UP, which we do in
383 * struct zebra_if.primary_state.
384 *
385 * Setting IFF_UP within zebra to administratively shutdown the
386 * interface will affect only the primary interface/address on Solaris.
387 ************************End Solaris flags hacks ***********************
388 */
d62a17ae 389static void if_flags_mangle(struct interface *ifp, uint64_t *newflags)
5c78b3d0 390{
391#ifdef SUNOS_5
d62a17ae 392 struct zebra_if *zif = ifp->info;
393
394 zif->primary_state = *newflags & (IFF_UP & 0xff);
395
396 if (CHECK_FLAG(zif->primary_state, IFF_UP)
397 || listcount(ifp->connected) > 0)
398 SET_FLAG(*newflags, IFF_UP);
399 else
400 UNSET_FLAG(*newflags, IFF_UP);
5c78b3d0 401#endif /* SUNOS_5 */
402}
403
404/* Update the flags field of the ifp with the new flag set provided.
405 * Take whatever actions are required for any changes in flags we care
406 * about.
407 *
408 * newflags should be the raw value, as obtained from the OS.
409 */
d62a17ae 410void if_flags_update(struct interface *ifp, uint64_t newflags)
411{
412 if_flags_mangle(ifp, &newflags);
413
414 if (if_is_no_ptm_operative(ifp)) {
415 /* operative -> inoperative? */
416 ifp->flags = newflags;
417 if (!if_is_operative(ifp))
418 if_down(ifp);
419 } else {
420 /* inoperative -> operative? */
421 ifp->flags = newflags;
422 if (if_is_operative(ifp))
423 if_up(ifp);
424 }
5c78b3d0 425}
426
718e3744 427/* Wake up configured address if it is not in current kernel
428 address. */
d62a17ae 429static void if_addr_wakeup(struct interface *ifp)
430{
431 struct listnode *node, *nnode;
432 struct connected *ifc;
433 struct prefix *p;
434 int ret;
eef1fe11 435
d62a17ae 436 for (ALL_LIST_ELEMENTS(ifp->connected, node, nnode, ifc)) {
437 p = ifc->address;
718e3744 438
d62a17ae 439 if (CHECK_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED)
440 && !CHECK_FLAG(ifc->conf, ZEBRA_IFC_QUEUED)) {
441 /* Address check. */
442 if (p->family == AF_INET) {
443 if (!if_is_up(ifp)) {
444 /* Assume zebra is configured like
445 * following:
446 *
447 * interface gre0
448 * ip addr 192.0.2.1/24
449 * !
450 *
451 * As soon as zebra becomes first aware
452 * that gre0 exists in the
453 * kernel, it will set gre0 up and
454 * configure its addresses.
455 *
456 * (This may happen at startup when the
457 * interface already exists
458 * or during runtime when the interface
459 * is added to the kernel)
460 *
461 * XXX: IRDP code is calling here via
462 * if_add_update - this seems
463 * somewhat weird.
464 * XXX: RUNNING is not a settable flag
465 * on any system
466 * I (paulj) am aware of.
9d303b37 467 */
d62a17ae 468 if_set_flags(ifp, IFF_UP | IFF_RUNNING);
469 if_refresh(ifp);
470 }
471
472 ret = if_set_prefix(ifp, ifc);
473 if (ret < 0) {
474 zlog_warn(
475 "Can't set interface's address: %s",
476 safe_strerror(errno));
477 continue;
478 }
479
480 SET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED);
481 /* The address will be advertised to zebra
482 * clients when the notification
483 * from the kernel has been received.
484 * It will also be added to the interface's
485 * subnet list then. */
486 }
487 if (p->family == AF_INET6) {
488 if (!if_is_up(ifp)) {
489 /* See long comment above */
490 if_set_flags(ifp, IFF_UP | IFF_RUNNING);
491 if_refresh(ifp);
492 }
493
494 ret = if_prefix_add_ipv6(ifp, ifc);
495 if (ret < 0) {
496 zlog_warn(
497 "Can't set interface's address: %s",
498 safe_strerror(errno));
499 continue;
500 }
501
502 SET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED);
503 /* The address will be advertised to zebra
504 * clients when the notification
505 * from the kernel has been received. */
506 }
718e3744 507 }
718e3744 508 }
718e3744 509}
510
511/* Handle interface addition */
d62a17ae 512void if_add_update(struct interface *ifp)
718e3744 513{
d62a17ae 514 struct zebra_if *if_data;
fe533c56 515 struct zebra_ns *zns;
009f8ad5 516 struct zebra_vrf *zvrf = vrf_info_lookup(ifp->vrf_id);
48b33aaf 517
009f8ad5
PG
518 /* case interface populate before vrf enabled */
519 if (zvrf->zns)
520 zns = zvrf->zns;
fe533c56
PG
521 else
522 zns = zebra_ns_lookup(NS_DEFAULT);
523 if_link_per_ns(zns, ifp);
d62a17ae 524 if_data = ifp->info;
525 assert(if_data);
06b420a4 526
d62a17ae 527 if (if_data->multicast == IF_ZEBRA_MULTICAST_ON)
528 if_set_flags(ifp, IFF_MULTICAST);
529 else if (if_data->multicast == IF_ZEBRA_MULTICAST_OFF)
530 if_unset_flags(ifp, IFF_MULTICAST);
48b33aaf 531
d62a17ae 532 zebra_ptm_if_set_ptm_state(ifp, if_data);
986aa00f 533
d62a17ae 534 zebra_interface_add_update(ifp);
718e3744 535
d62a17ae 536 if (!CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE)) {
537 SET_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE);
718e3744 538
0af35d90 539 if (if_data->shutdown == IF_ZEBRA_SHUTDOWN_ON) {
d62a17ae 540 if (IS_ZEBRA_DEBUG_KERNEL)
541 zlog_debug(
542 "interface %s vrf %u index %d is shutdown. "
543 "Won't wake it up.",
544 ifp->name, ifp->vrf_id, ifp->ifindex);
545 return;
546 }
bfac8dcd 547
d62a17ae 548 if_addr_wakeup(ifp);
718e3744 549
d62a17ae 550 if (IS_ZEBRA_DEBUG_KERNEL)
551 zlog_debug(
552 "interface %s vrf %u index %d becomes active.",
553 ifp->name, ifp->vrf_id, ifp->ifindex);
c3c04063
DL
554
555 static_ifindex_update(ifp, true);
d62a17ae 556 } else {
557 if (IS_ZEBRA_DEBUG_KERNEL)
558 zlog_debug("interface %s vrf %u index %d is added.",
559 ifp->name, ifp->vrf_id, ifp->ifindex);
560 }
718e3744 561}
562
c8e264b6 563/* Install connected routes corresponding to an interface. */
d62a17ae 564static void if_install_connected(struct interface *ifp)
565{
566 struct listnode *node;
567 struct listnode *next;
568 struct connected *ifc;
d62a17ae 569
570 if (ifp->connected) {
571 for (ALL_LIST_ELEMENTS(ifp->connected, node, next, ifc)) {
572 if (CHECK_FLAG(ifc->conf, ZEBRA_IFC_REAL))
573 zebra_interface_address_add_update(ifp, ifc);
574
ae87977c 575 connected_up(ifp, ifc);
d62a17ae 576 }
c8e264b6 577 }
c8e264b6 578}
579
580/* Uninstall connected routes corresponding to an interface. */
d62a17ae 581static void if_uninstall_connected(struct interface *ifp)
582{
583 struct listnode *node;
584 struct listnode *next;
585 struct connected *ifc;
d62a17ae 586
587 if (ifp->connected) {
588 for (ALL_LIST_ELEMENTS(ifp->connected, node, next, ifc)) {
d62a17ae 589 zebra_interface_address_delete_update(ifp, ifc);
11461c63 590 connected_down(ifp, ifc);
d62a17ae 591 }
c8e264b6 592 }
c8e264b6 593}
718e3744 594
c8e264b6 595/* Uninstall and delete connected routes corresponding to an interface. */
596/* TODO - Check why IPv4 handling here is different from install or if_down */
d62a17ae 597static void if_delete_connected(struct interface *ifp)
598{
599 struct connected *ifc;
a3008857 600 struct prefix cp;
d62a17ae 601 struct route_node *rn;
602 struct zebra_if *zebra_if;
070b4959
DS
603 struct listnode *node;
604 struct listnode *last = NULL;
d62a17ae 605
606 zebra_if = ifp->info;
607
070b4959
DS
608 if (!ifp->connected)
609 return;
d62a17ae 610
996c9314 611 while ((node = (last ? last->next : listhead(ifp->connected)))) {
070b4959 612 ifc = listgetdata(node);
d62a17ae 613
070b4959
DS
614 cp = *CONNECTED_PREFIX(ifc);
615 apply_mask(&cp);
a3008857 616
070b4959 617 if (cp.family == AF_INET
996c9314 618 && (rn = route_node_lookup(zebra_if->ipv4_subnets, &cp))) {
070b4959
DS
619 struct listnode *anode;
620 struct listnode *next;
621 struct listnode *first;
622 struct list *addr_list;
d62a17ae 623
070b4959
DS
624 route_unlock_node(rn);
625 addr_list = (struct list *)rn->info;
d62a17ae 626
070b4959
DS
627 /* Remove addresses, secondaries first. */
628 first = listhead(addr_list);
629 if (first)
d62a17ae 630 for (anode = first->next; anode || first;
631 anode = next) {
632 if (!anode) {
633 anode = first;
634 first = NULL;
635 }
636 next = anode->next;
637
638 ifc = listgetdata(anode);
11461c63 639 connected_down(ifp, ifc);
d62a17ae 640
641 /* XXX: We have to send notifications
642 * here explicitly, because we destroy
643 * the ifc before receiving the
644 * notification about the address being
645 * deleted.
646 */
647 zebra_interface_address_delete_update(
648 ifp, ifc);
649
650 UNSET_FLAG(ifc->conf, ZEBRA_IFC_REAL);
651 UNSET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED);
652
653 /* Remove from subnet chain. */
654 list_delete_node(addr_list, anode);
655 route_unlock_node(rn);
656
657 /* Remove from interface address list
658 * (unconditionally). */
659 if (!CHECK_FLAG(ifc->conf,
660 ZEBRA_IFC_CONFIGURED)) {
661 listnode_delete(ifp->connected,
662 ifc);
663 connected_free(ifc);
664 } else
665 last = node;
666 }
667
070b4959
DS
668 /* Free chain list and respective route node. */
669 list_delete_and_null(&addr_list);
670 rn->info = NULL;
671 route_unlock_node(rn);
672 } else if (cp.family == AF_INET6) {
673 connected_down(ifp, ifc);
d62a17ae 674
070b4959 675 zebra_interface_address_delete_update(ifp, ifc);
d62a17ae 676
070b4959
DS
677 UNSET_FLAG(ifc->conf, ZEBRA_IFC_REAL);
678 UNSET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED);
d62a17ae 679
070b4959 680 if (CHECK_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED))
d62a17ae 681 last = node;
070b4959
DS
682 else {
683 listnode_delete(ifp->connected, ifc);
684 connected_free(ifc);
d62a17ae 685 }
070b4959
DS
686 } else {
687 last = node;
eef1fe11 688 }
718e3744 689 }
c8e264b6 690}
691
692/* Handle an interface delete event */
d62a17ae 693void if_delete_update(struct interface *ifp)
c8e264b6 694{
d62a17ae 695 struct zebra_if *zif;
d2fc8896 696
d62a17ae 697 if (if_is_up(ifp)) {
698 zlog_err(
699 "interface %s vrf %u index %d is still up while being deleted.",
700 ifp->name, ifp->vrf_id, ifp->ifindex);
701 return;
702 }
6675513d 703
d62a17ae 704 /* Mark interface as inactive */
705 UNSET_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE);
706
707 if (IS_ZEBRA_DEBUG_KERNEL)
708 zlog_debug("interface %s vrf %u index %d is now inactive.",
709 ifp->name, ifp->vrf_id, ifp->ifindex);
710
c3c04063
DL
711 static_ifindex_update(ifp, false);
712
d62a17ae 713 /* Delete connected routes from the kernel. */
714 if_delete_connected(ifp);
715
716 /* Send out notification on interface delete. */
717 zebra_interface_delete_update(ifp);
718
719 if_unlink_per_ns(ifp);
720
721 /* Update ifindex after distributing the delete message. This is in
722 case any client needs to have the old value of ifindex available
723 while processing the deletion. Each client daemon is responsible
724 for setting ifindex to IFINDEX_INTERNAL after processing the
725 interface deletion message. */
ff880b78 726 if_set_index(ifp, IFINDEX_INTERNAL);
d62a17ae 727 ifp->node = NULL;
728
729 /* if the ifp is in a vrf, move it to default so vrf can be deleted if
730 * desired */
731 if (ifp->vrf_id)
732 if_handle_vrf_change(ifp, VRF_DEFAULT);
733
734 /* Reset some zebra interface params to default values. */
735 zif = ifp->info;
736 if (zif) {
737 zif->zif_type = ZEBRA_IF_OTHER;
738 zif->zif_slave_type = ZEBRA_IF_SLAVE_NONE;
739 memset(&zif->l2info, 0, sizeof(union zebra_l2if_info));
740 memset(&zif->brslave_info, 0,
741 sizeof(struct zebra_l2info_brslave));
742 }
718e3744 743}
744
c8e264b6 745/* VRF change for an interface */
d62a17ae 746void if_handle_vrf_change(struct interface *ifp, vrf_id_t vrf_id)
c8e264b6 747{
d62a17ae 748 vrf_id_t old_vrf_id;
c8e264b6 749
d62a17ae 750 old_vrf_id = ifp->vrf_id;
c8e264b6 751
6201e30b
DL
752 static_ifindex_update(ifp, false);
753
d62a17ae 754 /* Uninstall connected routes. */
755 if_uninstall_connected(ifp);
c8e264b6 756
d62a17ae 757 /* Delete any IPv4 neighbors created to implement RFC 5549 */
758 if_nbr_ipv6ll_to_ipv4ll_neigh_del_all(ifp);
c8e264b6 759
d62a17ae 760 /* Delete all neighbor addresses learnt through IPv6 RA */
761 if_down_del_nbr_connected(ifp);
c8e264b6 762
d62a17ae 763 /* Send out notification on interface VRF change. */
764 /* This is to issue an UPDATE or a DELETE, as appropriate. */
765 zebra_interface_vrf_update_del(ifp, vrf_id);
c8e264b6 766
d62a17ae 767 /* update VRF */
768 if_update_to_new_vrf(ifp, vrf_id);
c8e264b6 769
d62a17ae 770 /* Send out notification on interface VRF change. */
771 /* This is to issue an ADD, if needed. */
772 zebra_interface_vrf_update_add(ifp, old_vrf_id);
c8e264b6 773
d62a17ae 774 /* Install connected routes (in new VRF). */
4030583f 775 if (if_is_operative(ifp))
776 if_install_connected(ifp);
c8e264b6 777
6201e30b
DL
778 static_ifindex_update(ifp, true);
779
d62a17ae 780 /* Due to connected route change, schedule RIB processing for both old
781 * and new VRF.
782 */
783 if (IS_ZEBRA_DEBUG_RIB_DETAILED)
784 zlog_debug("%u: IF %s VRF change, scheduling RIB processing",
785 ifp->vrf_id, ifp->name);
786 rib_update(old_vrf_id, RIB_UPDATE_IF_CHANGE);
787 rib_update(ifp->vrf_id, RIB_UPDATE_IF_CHANGE);
c8e264b6 788}
789
d62a17ae 790static void ipv6_ll_address_to_mac(struct in6_addr *address, u_char *mac)
5c610faf 791{
d62a17ae 792 mac[0] = address->s6_addr[8] ^ 0x02;
793 mac[1] = address->s6_addr[9];
794 mac[2] = address->s6_addr[10];
795 mac[3] = address->s6_addr[13];
796 mac[4] = address->s6_addr[14];
797 mac[5] = address->s6_addr[15];
5c610faf
DS
798}
799
d62a17ae 800void if_nbr_ipv6ll_to_ipv4ll_neigh_update(struct interface *ifp,
801 struct in6_addr *address, int add)
5c610faf 802{
d62a17ae 803 struct zebra_vrf *zvrf = vrf_info_lookup(ifp->vrf_id);
804 char buf[16] = "169.254.0.1";
805 struct in_addr ipv4_ll;
806 char mac[6];
5895d33f 807 ns_id_t ns_id;
5c610faf 808
d62a17ae 809 inet_pton(AF_INET, buf, &ipv4_ll);
5c610faf 810
d62a17ae 811 ipv6_ll_address_to_mac(address, (u_char *)mac);
009f8ad5 812 ns_id = zvrf->zns->ns_id;
d1479ec8 813
a8a4fa89 814 /*
f26bc773 815 * Remove existed arp record for the interface as netlink
816 * protocol does not have update message types
817 *
818 * supported message types are RTM_NEWNEIGH and RTM_DELNEIGH
819 */
5895d33f 820 kernel_neigh_update(0, ifp->ifindex, ipv4_ll.s_addr, mac, 6, ns_id);
d1479ec8 821
822 /* Add arp record */
5895d33f 823 kernel_neigh_update(add, ifp->ifindex, ipv4_ll.s_addr, mac, 6, ns_id);
d62a17ae 824 zvrf->neigh_updates++;
5c610faf
DS
825}
826
d62a17ae 827static void if_nbr_ipv6ll_to_ipv4ll_neigh_add_all(struct interface *ifp)
5c610faf 828{
d62a17ae 829 if (listhead(ifp->nbr_connected)) {
830 struct nbr_connected *nbr_connected;
831 struct listnode *node;
5c610faf 832
d62a17ae 833 for (ALL_LIST_ELEMENTS_RO(ifp->nbr_connected, node,
834 nbr_connected))
835 if_nbr_ipv6ll_to_ipv4ll_neigh_update(
836 ifp, &nbr_connected->address->u.prefix6, 1);
837 }
5c610faf
DS
838}
839
d62a17ae 840void if_nbr_ipv6ll_to_ipv4ll_neigh_del_all(struct interface *ifp)
5c610faf 841{
d62a17ae 842 if (listhead(ifp->nbr_connected)) {
843 struct nbr_connected *nbr_connected;
844 struct listnode *node;
5c610faf 845
d62a17ae 846 for (ALL_LIST_ELEMENTS_RO(ifp->nbr_connected, node,
847 nbr_connected))
848 if_nbr_ipv6ll_to_ipv4ll_neigh_update(
849 ifp, &nbr_connected->address->u.prefix6, 0);
850 }
5c610faf
DS
851}
852
d62a17ae 853static void if_down_del_nbr_connected(struct interface *ifp)
a197c47c 854{
d62a17ae 855 struct nbr_connected *nbr_connected;
856 struct listnode *node, *nnode;
a197c47c 857
d62a17ae 858 for (ALL_LIST_ELEMENTS(ifp->nbr_connected, node, nnode,
859 nbr_connected)) {
860 listnode_delete(ifp->nbr_connected, nbr_connected);
861 nbr_connected_free(nbr_connected);
862 }
a197c47c
DS
863}
864
718e3744 865/* Interface is up. */
d62a17ae 866void if_up(struct interface *ifp)
867{
868 struct zebra_if *zif;
869 struct interface *link_if;
154a3944 870 struct zebra_vrf *zvrf = vrf_info_lookup(ifp->vrf_id);
d62a17ae 871
872 zif = ifp->info;
873 zif->up_count++;
874 quagga_timestamp(2, zif->up_last, sizeof(zif->up_last));
875
876 /* Notify the protocol daemons. */
877 if (ifp->ptm_enable && (ifp->ptm_status == ZEBRA_PTM_STATUS_DOWN)) {
878 zlog_warn("%s: interface %s hasn't passed ptm check\n",
879 __func__, ifp->name);
880 return;
881 }
882 zebra_interface_up_update(ifp);
883
884 if_nbr_ipv6ll_to_ipv4ll_neigh_add_all(ifp);
885
886#if defined(HAVE_RTADV)
887 /* Enable fast tx of RA if enabled && RA interval is not in msecs */
888 if (zif->rtadv.AdvSendAdvertisements
889 && (zif->rtadv.MaxRtrAdvInterval >= 1000)) {
890 zif->rtadv.inFastRexmit = 1;
891 zif->rtadv.NumFastReXmitsRemain = RTADV_NUM_FAST_REXMITS;
892 }
9c3bf1ce 893#endif
6c9678b4 894
d62a17ae 895 /* Install connected routes to the kernel. */
896 if_install_connected(ifp);
897
898 if (IS_ZEBRA_DEBUG_RIB_DETAILED)
899 zlog_debug("%u: IF %s up, scheduling RIB processing",
900 ifp->vrf_id, ifp->name);
901 rib_update(ifp->vrf_id, RIB_UPDATE_IF_CHANGE);
902
d62a17ae 903 /* Handle interface up for specific types for EVPN. Non-VxLAN interfaces
904 * are checked to see if (remote) neighbor entries need to be installed
905 * on them for ARP suppression.
906 */
907 if (IS_ZEBRA_IF_VXLAN(ifp))
908 zebra_vxlan_if_up(ifp);
909 else if (IS_ZEBRA_IF_BRIDGE(ifp)) {
910 link_if = ifp;
911 zebra_vxlan_svi_up(ifp, link_if);
912 } else if (IS_ZEBRA_IF_VLAN(ifp)) {
154a3944 913 link_if = if_lookup_by_index_per_ns(zvrf->zns,
71349e03 914 zif->link_ifindex);
d62a17ae 915 if (link_if)
916 zebra_vxlan_svi_up(ifp, link_if);
917 }
718e3744 918}
919
920/* Interface goes down. We have to manage different behavior of based
921 OS. */
d62a17ae 922void if_down(struct interface *ifp)
923{
924 struct zebra_if *zif;
925 struct interface *link_if;
154a3944 926 struct zebra_vrf *zvrf = vrf_info_lookup(ifp->vrf_id);
d62a17ae 927
928 zif = ifp->info;
929 zif->down_count++;
930 quagga_timestamp(2, zif->down_last, sizeof(zif->down_last));
931
932 /* Handle interface down for specific types for EVPN. Non-VxLAN
933 * interfaces
934 * are checked to see if (remote) neighbor entries need to be purged
935 * for ARP suppression.
936 */
937 if (IS_ZEBRA_IF_VXLAN(ifp))
938 zebra_vxlan_if_down(ifp);
939 else if (IS_ZEBRA_IF_BRIDGE(ifp)) {
940 link_if = ifp;
941 zebra_vxlan_svi_down(ifp, link_if);
942 } else if (IS_ZEBRA_IF_VLAN(ifp)) {
154a3944 943 link_if = if_lookup_by_index_per_ns(zvrf->zns,
71349e03 944 zif->link_ifindex);
d62a17ae 945 if (link_if)
946 zebra_vxlan_svi_down(ifp, link_if);
947 }
2232a77c 948
13d60d35 949
d62a17ae 950 /* Notify to the protocol daemons. */
951 zebra_interface_down_update(ifp);
718e3744 952
d62a17ae 953 /* Uninstall connected routes from the kernel. */
954 if_uninstall_connected(ifp);
718e3744 955
d62a17ae 956 if (IS_ZEBRA_DEBUG_RIB_DETAILED)
957 zlog_debug("%u: IF %s down, scheduling RIB processing",
958 ifp->vrf_id, ifp->name);
959 rib_update(ifp->vrf_id, RIB_UPDATE_IF_CHANGE);
5c610faf 960
d62a17ae 961 if_nbr_ipv6ll_to_ipv4ll_neigh_del_all(ifp);
a197c47c 962
d62a17ae 963 /* Delete all neighbor addresses learnt through IPv6 RA */
964 if_down_del_nbr_connected(ifp);
718e3744 965}
966
d62a17ae 967void if_refresh(struct interface *ifp)
718e3744 968{
d62a17ae 969 if_get_flags(ifp);
718e3744 970}
971
d62a17ae 972void zebra_if_update_link(struct interface *ifp, ifindex_t link_ifindex)
6675513d 973{
d62a17ae 974 struct zebra_if *zif;
6675513d 975
d62a17ae 976 zif = (struct zebra_if *)ifp->info;
977 zif->link_ifindex = link_ifindex;
978 zif->link = if_lookup_by_index_per_ns(zebra_ns_lookup(NS_DEFAULT),
979 link_ifindex);
6675513d 980}
981
d5a5c8f0 982
718e3744 983/* Output prefix string to vty. */
d62a17ae 984static int prefix_vty_out(struct vty *vty, struct prefix *p)
718e3744 985{
d62a17ae 986 char str[INET6_ADDRSTRLEN];
718e3744 987
d62a17ae 988 inet_ntop(p->family, &p->u.prefix, str, sizeof(str));
989 vty_out(vty, "%s", str);
990 return strlen(str);
718e3744 991}
992
993/* Dump if address information to vty. */
d62a17ae 994static void connected_dump_vty(struct vty *vty, struct connected *connected)
718e3744 995{
d62a17ae 996 struct prefix *p;
718e3744 997
d62a17ae 998 /* Print interface address. */
999 p = connected->address;
1000 vty_out(vty, " %s ", prefix_family_str(p));
1001 prefix_vty_out(vty, p);
1002 vty_out(vty, "/%d", p->prefixlen);
718e3744 1003
d62a17ae 1004 /* If there is destination address, print it. */
1005 if (connected->destination) {
1006 vty_out(vty,
1007 (CONNECTED_PEER(connected) ? " peer " : " broadcast "));
1008 prefix_vty_out(vty, connected->destination);
abffde07
DL
1009 if (CONNECTED_PEER(connected))
1010 vty_out(vty, "/%d", connected->destination->prefixlen);
d62a17ae 1011 }
718e3744 1012
d62a17ae 1013 if (CHECK_FLAG(connected->flags, ZEBRA_IFA_SECONDARY))
1014 vty_out(vty, " secondary");
718e3744 1015
d62a17ae 1016 if (CHECK_FLAG(connected->flags, ZEBRA_IFA_UNNUMBERED))
1017 vty_out(vty, " unnumbered");
525c1839 1018
d62a17ae 1019 if (connected->label)
1020 vty_out(vty, " %s", connected->label);
718e3744 1021
d62a17ae 1022 vty_out(vty, "\n");
718e3744 1023}
1024
a80beece 1025/* Dump interface neighbor address information to vty. */
d62a17ae 1026static void nbr_connected_dump_vty(struct vty *vty,
1027 struct nbr_connected *connected)
a80beece 1028{
d62a17ae 1029 struct prefix *p;
a80beece 1030
d62a17ae 1031 /* Print interface address. */
1032 p = connected->address;
1033 vty_out(vty, " %s ", prefix_family_str(p));
1034 prefix_vty_out(vty, p);
1035 vty_out(vty, "/%d", p->prefixlen);
a80beece 1036
d62a17ae 1037 vty_out(vty, "\n");
a80beece
DS
1038}
1039
d62a17ae 1040static const char *zebra_ziftype_2str(zebra_iftype_t zif_type)
6675513d 1041{
d62a17ae 1042 switch (zif_type) {
1043 case ZEBRA_IF_OTHER:
1044 return "Other";
1045 break;
6675513d 1046
d62a17ae 1047 case ZEBRA_IF_BRIDGE:
1048 return "Bridge";
1049 break;
6675513d 1050
d62a17ae 1051 case ZEBRA_IF_VLAN:
1052 return "Vlan";
1053 break;
6675513d 1054
d62a17ae 1055 case ZEBRA_IF_VXLAN:
1056 return "Vxlan";
1057 break;
6675513d 1058
d62a17ae 1059 case ZEBRA_IF_VRF:
1060 return "VRF";
1061 break;
6675513d 1062
d62a17ae 1063 default:
1064 return "Unknown";
1065 break;
1066 }
6675513d 1067}
1068
718e3744 1069/* Interface's information print out to vty interface. */
d62a17ae 1070static void if_dump_vty(struct vty *vty, struct interface *ifp)
1071{
1072 struct connected *connected;
1073 struct nbr_connected *nbr_connected;
1074 struct listnode *node;
1075 struct route_node *rn;
1076 struct zebra_if *zebra_if;
1077 struct vrf *vrf;
1078
1079 zebra_if = ifp->info;
1080
1081 vty_out(vty, "Interface %s is ", ifp->name);
1082 if (if_is_up(ifp)) {
1083 vty_out(vty, "up, line protocol ");
1084
1085 if (CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_LINKDETECTION)) {
1086 if (if_is_running(ifp))
1087 vty_out(vty, "is up\n");
1088 else
1089 vty_out(vty, "is down\n");
1090 } else {
1091 vty_out(vty, "detection is disabled\n");
1092 }
1093 } else {
1094 vty_out(vty, "down\n");
1095 }
1096
1097 vty_out(vty, " Link ups: %5u last: %s\n", zebra_if->up_count,
1098 zebra_if->up_last[0] ? zebra_if->up_last : "(never)");
1099 vty_out(vty, " Link downs: %5u last: %s\n", zebra_if->down_count,
1100 zebra_if->down_last[0] ? zebra_if->down_last : "(never)");
1101
1102 zebra_ptm_show_status(vty, ifp);
1103
1104 vrf = vrf_lookup_by_id(ifp->vrf_id);
1105 vty_out(vty, " vrf: %s\n", vrf->name);
1106
1107 if (ifp->desc)
1108 vty_out(vty, " Description: %s\n", ifp->desc);
1109 if (ifp->ifindex == IFINDEX_INTERNAL) {
1110 vty_out(vty, " pseudo interface\n");
1111 return;
1112 } else if (!CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE)) {
1113 vty_out(vty, " index %d inactive interface\n", ifp->ifindex);
1114 return;
1115 }
1116
1117 vty_out(vty, " index %d metric %d mtu %d speed %u ", ifp->ifindex,
1118 ifp->metric, ifp->mtu, ifp->speed);
1119 if (ifp->mtu6 != ifp->mtu)
1120 vty_out(vty, "mtu6 %d ", ifp->mtu6);
1121 vty_out(vty, "\n flags: %s\n", if_flag_dump(ifp->flags));
1122
1123 /* Hardware address. */
1124 vty_out(vty, " Type: %s\n", if_link_type_str(ifp->ll_type));
1125 if (ifp->hw_addr_len != 0) {
1126 int i;
1127
1128 vty_out(vty, " HWaddr: ");
1129 for (i = 0; i < ifp->hw_addr_len; i++)
1130 vty_out(vty, "%s%02x", i == 0 ? "" : ":",
1131 ifp->hw_addr[i]);
1132 vty_out(vty, "\n");
1133 }
1134
1135 /* Bandwidth in Mbps */
1136 if (ifp->bandwidth != 0) {
1137 vty_out(vty, " bandwidth %u Mbps", ifp->bandwidth);
1138 vty_out(vty, "\n");
1139 }
1140
1141 for (rn = route_top(zebra_if->ipv4_subnets); rn; rn = route_next(rn)) {
1142 if (!rn->info)
1143 continue;
1144
1145 for (ALL_LIST_ELEMENTS_RO((struct list *)rn->info, node,
1146 connected))
1147 connected_dump_vty(vty, connected);
1148 }
1149
1150 for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, connected)) {
1151 if (CHECK_FLAG(connected->conf, ZEBRA_IFC_REAL)
1152 && (connected->address->family == AF_INET6))
1153 connected_dump_vty(vty, connected);
1154 }
1155
1156 vty_out(vty, " Interface Type %s\n",
1157 zebra_ziftype_2str(zebra_if->zif_type));
1158 if (IS_ZEBRA_IF_BRIDGE(ifp)) {
1159 struct zebra_l2info_bridge *bridge_info;
1160
1161 bridge_info = &zebra_if->l2info.br;
1162 vty_out(vty, " Bridge VLAN-aware: %s\n",
1163 bridge_info->vlan_aware ? "yes" : "no");
1164 } else if (IS_ZEBRA_IF_VLAN(ifp)) {
1165 struct zebra_l2info_vlan *vlan_info;
1166
1167 vlan_info = &zebra_if->l2info.vl;
1168 vty_out(vty, " VLAN Id %u\n", vlan_info->vid);
1169 } else if (IS_ZEBRA_IF_VXLAN(ifp)) {
1170 struct zebra_l2info_vxlan *vxlan_info;
1171
1172 vxlan_info = &zebra_if->l2info.vxl;
1173 vty_out(vty, " VxLAN Id %u", vxlan_info->vni);
1174 if (vxlan_info->vtep_ip.s_addr != INADDR_ANY)
1175 vty_out(vty, " VTEP IP: %s",
1176 inet_ntoa(vxlan_info->vtep_ip));
1177 if (vxlan_info->access_vlan)
1178 vty_out(vty, " Access VLAN Id %u",
1179 vxlan_info->access_vlan);
1180 vty_out(vty, "\n");
1181 }
1182
1183 if (IS_ZEBRA_IF_BRIDGE_SLAVE(ifp)) {
1184 struct zebra_l2info_brslave *br_slave;
1185
1186 br_slave = &zebra_if->brslave_info;
1187 if (br_slave->bridge_ifindex != IFINDEX_INTERNAL)
1188 vty_out(vty, " Master (bridge) ifindex %u\n",
1189 br_slave->bridge_ifindex);
1190 }
1191
1192 if (zebra_if->link_ifindex != IFINDEX_INTERNAL)
1193 vty_out(vty, " Link ifindex %u\n", zebra_if->link_ifindex);
1194
1195 if (HAS_LINK_PARAMS(ifp)) {
1196 int i;
1197 struct if_link_params *iflp = ifp->link_params;
1198 vty_out(vty, " Traffic Engineering Link Parameters:\n");
1199 if (IS_PARAM_SET(iflp, LP_TE_METRIC))
1200 vty_out(vty, " TE metric %u\n", iflp->te_metric);
1201 if (IS_PARAM_SET(iflp, LP_MAX_BW))
1202 vty_out(vty, " Maximum Bandwidth %g (Byte/s)\n",
1203 iflp->max_bw);
1204 if (IS_PARAM_SET(iflp, LP_MAX_RSV_BW))
1205 vty_out(vty,
1206 " Maximum Reservable Bandwidth %g (Byte/s)\n",
1207 iflp->max_rsv_bw);
1208 if (IS_PARAM_SET(iflp, LP_UNRSV_BW)) {
1209 vty_out(vty,
1210 " Unreserved Bandwidth per Class Type in Byte/s:\n");
1211 for (i = 0; i < MAX_CLASS_TYPE; i += 2)
1212 vty_out(vty,
1213 " [%d]: %g (Bytes/sec),\t[%d]: %g (Bytes/sec)\n",
1214 i, iflp->unrsv_bw[i], i + 1,
1215 iflp->unrsv_bw[i + 1]);
1216 }
1217
1218 if (IS_PARAM_SET(iflp, LP_ADM_GRP))
1219 vty_out(vty, " Administrative Group:%u\n",
1220 iflp->admin_grp);
1221 if (IS_PARAM_SET(iflp, LP_DELAY)) {
1222 vty_out(vty, " Link Delay Average: %u (micro-sec.)",
1223 iflp->av_delay);
1224 if (IS_PARAM_SET(iflp, LP_MM_DELAY)) {
1225 vty_out(vty, " Min: %u (micro-sec.)",
1226 iflp->min_delay);
1227 vty_out(vty, " Max: %u (micro-sec.)",
1228 iflp->max_delay);
1229 }
1230 vty_out(vty, "\n");
1231 }
1232 if (IS_PARAM_SET(iflp, LP_DELAY_VAR))
1233 vty_out(vty,
1234 " Link Delay Variation %u (micro-sec.)\n",
1235 iflp->delay_var);
1236 if (IS_PARAM_SET(iflp, LP_PKT_LOSS))
1237 vty_out(vty, " Link Packet Loss %g (in %%)\n",
1238 iflp->pkt_loss);
1239 if (IS_PARAM_SET(iflp, LP_AVA_BW))
1240 vty_out(vty, " Available Bandwidth %g (Byte/s)\n",
1241 iflp->ava_bw);
1242 if (IS_PARAM_SET(iflp, LP_RES_BW))
1243 vty_out(vty, " Residual Bandwidth %g (Byte/s)\n",
1244 iflp->res_bw);
1245 if (IS_PARAM_SET(iflp, LP_USE_BW))
1246 vty_out(vty, " Utilized Bandwidth %g (Byte/s)\n",
1247 iflp->use_bw);
1248 if (IS_PARAM_SET(iflp, LP_RMT_AS))
1249 vty_out(vty, " Neighbor ASBR IP: %s AS: %u \n",
1250 inet_ntoa(iflp->rmt_ip), iflp->rmt_as);
1251 }
1252
2eb27eec
DL
1253 hook_call(zebra_if_extra_info, vty, ifp);
1254
d62a17ae 1255 if (listhead(ifp->nbr_connected))
1256 vty_out(vty, " Neighbor address(s):\n");
1257 for (ALL_LIST_ELEMENTS_RO(ifp->nbr_connected, node, nbr_connected))
1258 nbr_connected_dump_vty(vty, nbr_connected);
718e3744 1259
1260#ifdef HAVE_PROC_NET_DEV
d62a17ae 1261 /* Statistics print out using proc file system. */
1262 vty_out(vty,
1263 " %lu input packets (%lu multicast), %lu bytes, "
1264 "%lu dropped\n",
1265 ifp->stats.rx_packets, ifp->stats.rx_multicast,
1266 ifp->stats.rx_bytes, ifp->stats.rx_dropped);
1267
1268 vty_out(vty,
1269 " %lu input errors, %lu length, %lu overrun,"
1270 " %lu CRC, %lu frame\n",
1271 ifp->stats.rx_errors, ifp->stats.rx_length_errors,
1272 ifp->stats.rx_over_errors, ifp->stats.rx_crc_errors,
1273 ifp->stats.rx_frame_errors);
1274
1275 vty_out(vty, " %lu fifo, %lu missed\n", ifp->stats.rx_fifo_errors,
1276 ifp->stats.rx_missed_errors);
1277
1278 vty_out(vty, " %lu output packets, %lu bytes, %lu dropped\n",
1279 ifp->stats.tx_packets, ifp->stats.tx_bytes,
1280 ifp->stats.tx_dropped);
1281
1282 vty_out(vty,
1283 " %lu output errors, %lu aborted, %lu carrier,"
1284 " %lu fifo, %lu heartbeat\n",
1285 ifp->stats.tx_errors, ifp->stats.tx_aborted_errors,
1286 ifp->stats.tx_carrier_errors, ifp->stats.tx_fifo_errors,
1287 ifp->stats.tx_heartbeat_errors);
1288
1289 vty_out(vty, " %lu window, %lu collisions\n",
1290 ifp->stats.tx_window_errors, ifp->stats.collisions);
718e3744 1291#endif /* HAVE_PROC_NET_DEV */
1292
1293#ifdef HAVE_NET_RT_IFLIST
d62a17ae 1294#if defined(__bsdi__) || defined(__NetBSD__)
1295 /* Statistics print out using sysctl (). */
1296 vty_out(vty,
1297 " input packets %llu, bytes %llu, dropped %llu,"
1298 " multicast packets %llu\n",
1299 (unsigned long long)ifp->stats.ifi_ipackets,
1300 (unsigned long long)ifp->stats.ifi_ibytes,
1301 (unsigned long long)ifp->stats.ifi_iqdrops,
1302 (unsigned long long)ifp->stats.ifi_imcasts);
1303
1304 vty_out(vty, " input errors %llu\n",
1305 (unsigned long long)ifp->stats.ifi_ierrors);
1306
1307 vty_out(vty,
1308 " output packets %llu, bytes %llu,"
1309 " multicast packets %llu\n",
1310 (unsigned long long)ifp->stats.ifi_opackets,
1311 (unsigned long long)ifp->stats.ifi_obytes,
1312 (unsigned long long)ifp->stats.ifi_omcasts);
1313
1314 vty_out(vty, " output errors %llu\n",
1315 (unsigned long long)ifp->stats.ifi_oerrors);
1316
1317 vty_out(vty, " collisions %llu\n",
1318 (unsigned long long)ifp->stats.ifi_collisions);
718e3744 1319#else
d62a17ae 1320 /* Statistics print out using sysctl (). */
1321 vty_out(vty,
1322 " input packets %lu, bytes %lu, dropped %lu,"
1323 " multicast packets %lu\n",
1324 ifp->stats.ifi_ipackets, ifp->stats.ifi_ibytes,
1325 ifp->stats.ifi_iqdrops, ifp->stats.ifi_imcasts);
718e3744 1326
d62a17ae 1327 vty_out(vty, " input errors %lu\n", ifp->stats.ifi_ierrors);
718e3744 1328
d62a17ae 1329 vty_out(vty,
1330 " output packets %lu, bytes %lu, multicast packets %lu\n",
1331 ifp->stats.ifi_opackets, ifp->stats.ifi_obytes,
1332 ifp->stats.ifi_omcasts);
718e3744 1333
d62a17ae 1334 vty_out(vty, " output errors %lu\n", ifp->stats.ifi_oerrors);
718e3744 1335
d62a17ae 1336 vty_out(vty, " collisions %lu\n", ifp->stats.ifi_collisions);
718e3744 1337#endif /* __bsdi__ || __NetBSD__ */
1338#endif /* HAVE_NET_RT_IFLIST */
1339}
1340
d62a17ae 1341static void interface_update_stats(void)
78860b9f
DS
1342{
1343#ifdef HAVE_PROC_NET_DEV
d62a17ae 1344 /* If system has interface statistics via proc file system, update
1345 statistics. */
1346 ifstat_update_proc();
78860b9f
DS
1347#endif /* HAVE_PROC_NET_DEV */
1348#ifdef HAVE_NET_RT_IFLIST
d62a17ae 1349 ifstat_update_sysctl();
78860b9f
DS
1350#endif /* HAVE_NET_RT_IFLIST */
1351}
1352
d62a17ae 1353struct cmd_node interface_node = {INTERFACE_NODE, "%s(config-if)# ", 1};
718e3744 1354
8b87bdf4 1355/* Show all interfaces to vty. */
8b3f0677
DW
1356DEFUN (show_interface,
1357 show_interface_cmd,
b62ecea5 1358 "show interface [vrf NAME]",
8b87bdf4 1359 SHOW_STR
b62ecea5
QY
1360 "Interface status and configuration\n"
1361 VRF_CMD_HELP_STR)
8b87bdf4 1362{
f4e14fdb 1363 struct vrf *vrf;
d62a17ae 1364 struct interface *ifp;
1365 vrf_id_t vrf_id = VRF_DEFAULT;
8b87bdf4 1366
d62a17ae 1367 interface_update_stats();
8b87bdf4 1368
d62a17ae 1369 if (argc > 2)
1370 VRF_GET_ID(vrf_id, argv[3]->arg);
8b87bdf4 1371
d62a17ae 1372 /* All interface print. */
f4e14fdb 1373 vrf = vrf_lookup_by_id(vrf_id);
451fda4f 1374 FOR_ALL_INTERFACES (vrf, ifp)
d62a17ae 1375 if_dump_vty(vty, ifp);
8b87bdf4 1376
d62a17ae 1377 return CMD_SUCCESS;
8b87bdf4
FL
1378}
1379
8b87bdf4
FL
1380
1381/* Show all interfaces to vty. */
8b3f0677
DW
1382DEFUN (show_interface_vrf_all,
1383 show_interface_vrf_all_cmd,
9ccf14f7 1384 "show interface vrf all",
8b87bdf4
FL
1385 SHOW_STR
1386 "Interface status and configuration\n"
1387 VRF_ALL_CMD_HELP_STR)
718e3744 1388{
d62a17ae 1389 struct vrf *vrf;
d62a17ae 1390 struct interface *ifp;
8b87bdf4 1391
d62a17ae 1392 interface_update_stats();
718e3744 1393
d62a17ae 1394 /* All interface print. */
a2addae8 1395 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name)
451fda4f 1396 FOR_ALL_INTERFACES (vrf, ifp)
a2addae8 1397 if_dump_vty(vty, ifp);
8b87bdf4 1398
d62a17ae 1399 return CMD_SUCCESS;
8b87bdf4
FL
1400}
1401
1402/* Show specified interface to vty. */
1721646e
DS
1403
1404DEFUN (show_interface_name_vrf,
1405 show_interface_name_vrf_cmd,
9ccf14f7 1406 "show interface IFNAME vrf NAME",
8b87bdf4
FL
1407 SHOW_STR
1408 "Interface status and configuration\n"
1721646e
DS
1409 "Interface name\n"
1410 VRF_CMD_HELP_STR)
8b87bdf4 1411{
d62a17ae 1412 int idx_ifname = 2;
1413 int idx_name = 4;
1414 struct interface *ifp;
0439cb9d 1415 vrf_id_t vrf_id;
8b87bdf4 1416
d62a17ae 1417 interface_update_stats();
8b87bdf4 1418
d62a17ae 1419 VRF_GET_ID(vrf_id, argv[idx_name]->arg);
8b87bdf4 1420
d62a17ae 1421 /* Specified interface print. */
1422 ifp = if_lookup_by_name(argv[idx_ifname]->arg, vrf_id);
1423 if (ifp == NULL) {
1424 vty_out(vty, "%% Can't find interface %s\n",
1425 argv[idx_ifname]->arg);
1426 return CMD_WARNING;
1427 }
1428 if_dump_vty(vty, ifp);
718e3744 1429
d62a17ae 1430 return CMD_SUCCESS;
718e3744 1431}
1432
8b87bdf4 1433/* Show specified interface to vty. */
8b3f0677
DW
1434DEFUN (show_interface_name_vrf_all,
1435 show_interface_name_vrf_all_cmd,
b62ecea5 1436 "show interface IFNAME [vrf all]",
8b87bdf4
FL
1437 SHOW_STR
1438 "Interface status and configuration\n"
1721646e 1439 "Interface name\n"
8b87bdf4
FL
1440 VRF_ALL_CMD_HELP_STR)
1441{
d62a17ae 1442 int idx_ifname = 2;
1443 struct vrf *vrf;
1444 struct interface *ifp;
1445 int found = 0;
8b87bdf4 1446
d62a17ae 1447 interface_update_stats();
8b87bdf4 1448
d62a17ae 1449 /* All interface print. */
a2addae8 1450 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
d62a17ae 1451 /* Specified interface print. */
1452 ifp = if_lookup_by_name(argv[idx_ifname]->arg, vrf->vrf_id);
1453 if (ifp) {
1454 if_dump_vty(vty, ifp);
1455 found++;
1456 }
1457 }
8b87bdf4 1458
d62a17ae 1459 if (!found) {
1460 vty_out(vty, "%% Can't find interface %s\n",
1461 argv[idx_ifname]->arg);
1462 return CMD_WARNING;
1463 }
8b87bdf4 1464
d62a17ae 1465 return CMD_SUCCESS;
8b87bdf4
FL
1466}
1467
1721646e 1468
d62a17ae 1469static void if_show_description(struct vty *vty, vrf_id_t vrf_id)
ed9bb6d5 1470{
f4e14fdb 1471 struct vrf *vrf = vrf_lookup_by_id(vrf_id);
d62a17ae 1472 struct interface *ifp;
ed9bb6d5 1473
d62a17ae 1474 vty_out(vty, "Interface Status Protocol Description\n");
451fda4f 1475 FOR_ALL_INTERFACES (vrf, ifp) {
d62a17ae 1476 int len;
ed9bb6d5 1477
d62a17ae 1478 len = vty_out(vty, "%s", ifp->name);
1479 vty_out(vty, "%*s", (16 - len), " ");
1480
1481 if (if_is_up(ifp)) {
1482 vty_out(vty, "up ");
1483 if (CHECK_FLAG(ifp->status,
1484 ZEBRA_INTERFACE_LINKDETECTION)) {
1485 if (if_is_running(ifp))
1486 vty_out(vty, "up ");
1487 else
1488 vty_out(vty, "down ");
1489 } else {
1490 vty_out(vty, "unknown ");
1491 }
1492 } else {
1493 vty_out(vty, "down down ");
1494 }
ed9bb6d5 1495
d62a17ae 1496 if (ifp->desc)
1497 vty_out(vty, "%s", ifp->desc);
1498 vty_out(vty, "\n");
1499 }
8b87bdf4
FL
1500}
1501
1502DEFUN (show_interface_desc,
1503 show_interface_desc_cmd,
b62ecea5 1504 "show interface description [vrf NAME]",
8b87bdf4
FL
1505 SHOW_STR
1506 "Interface status and configuration\n"
b62ecea5
QY
1507 "Interface description\n"
1508 VRF_CMD_HELP_STR)
8b87bdf4 1509{
d62a17ae 1510 vrf_id_t vrf_id = VRF_DEFAULT;
8b87bdf4 1511
d62a17ae 1512 if (argc > 3)
1513 VRF_GET_ID(vrf_id, argv[4]->arg);
8b87bdf4 1514
d62a17ae 1515 if_show_description(vty, vrf_id);
8b87bdf4 1516
d62a17ae 1517 return CMD_SUCCESS;
8b87bdf4
FL
1518}
1519
8b87bdf4
FL
1520
1521DEFUN (show_interface_desc_vrf_all,
1522 show_interface_desc_vrf_all_cmd,
9ccf14f7 1523 "show interface description vrf all",
8b87bdf4
FL
1524 SHOW_STR
1525 "Interface status and configuration\n"
1526 "Interface description\n"
1527 VRF_ALL_CMD_HELP_STR)
1528{
d62a17ae 1529 struct vrf *vrf;
8b87bdf4 1530
a2addae8 1531 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name)
996c9314 1532 if (!RB_EMPTY(if_name_head, &vrf->ifaces_by_name)) {
a2addae8
RW
1533 vty_out(vty, "\n\tVRF %u\n\n", vrf->vrf_id);
1534 if_show_description(vty, vrf->vrf_id);
1535 }
8b87bdf4 1536
d62a17ae 1537 return CMD_SUCCESS;
ed9bb6d5 1538}
1539
718e3744 1540DEFUN (multicast,
1541 multicast_cmd,
1542 "multicast",
1543 "Set multicast flag to interface\n")
1544{
d62a17ae 1545 VTY_DECLVAR_CONTEXT(interface, ifp);
1546 int ret;
1547 struct zebra_if *if_data;
718e3744 1548
d62a17ae 1549 if (CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE)) {
1550 ret = if_set_flags(ifp, IFF_MULTICAST);
1551 if (ret < 0) {
1552 vty_out(vty, "Can't set multicast flag\n");
1553 return CMD_WARNING_CONFIG_FAILED;
1554 }
1555 if_refresh(ifp);
48b33aaf 1556 }
d62a17ae 1557 if_data = ifp->info;
1558 if_data->multicast = IF_ZEBRA_MULTICAST_ON;
48b33aaf 1559
d62a17ae 1560 return CMD_SUCCESS;
718e3744 1561}
1562
1563DEFUN (no_multicast,
1564 no_multicast_cmd,
1565 "no multicast",
1566 NO_STR
1567 "Unset multicast flag to interface\n")
1568{
d62a17ae 1569 VTY_DECLVAR_CONTEXT(interface, ifp);
1570 int ret;
1571 struct zebra_if *if_data;
718e3744 1572
d62a17ae 1573 if (CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE)) {
1574 ret = if_unset_flags(ifp, IFF_MULTICAST);
1575 if (ret < 0) {
1576 vty_out(vty, "Can't unset multicast flag\n");
1577 return CMD_WARNING_CONFIG_FAILED;
1578 }
1579 if_refresh(ifp);
48b33aaf 1580 }
d62a17ae 1581 if_data = ifp->info;
1582 if_data->multicast = IF_ZEBRA_MULTICAST_OFF;
718e3744 1583
d62a17ae 1584 return CMD_SUCCESS;
718e3744 1585}
1586
2e3b2e47 1587DEFUN (linkdetect,
1588 linkdetect_cmd,
1589 "link-detect",
1590 "Enable link detection on interface\n")
1591{
d62a17ae 1592 VTY_DECLVAR_CONTEXT(interface, ifp);
1593 int if_was_operative;
2e3b2e47 1594
d62a17ae 1595 if_was_operative = if_is_no_ptm_operative(ifp);
1596 SET_FLAG(ifp->status, ZEBRA_INTERFACE_LINKDETECTION);
2e3b2e47 1597
d62a17ae 1598 /* When linkdetection is enabled, if might come down */
1599 if (!if_is_no_ptm_operative(ifp) && if_was_operative)
1600 if_down(ifp);
2e3b2e47 1601
d62a17ae 1602 /* FIXME: Will defer status change forwarding if interface
1603 does not come down! */
1604
1605 return CMD_SUCCESS;
2e3b2e47 1606}
1607
1608
1609DEFUN (no_linkdetect,
1610 no_linkdetect_cmd,
1611 "no link-detect",
1612 NO_STR
1613 "Disable link detection on interface\n")
1614{
d62a17ae 1615 VTY_DECLVAR_CONTEXT(interface, ifp);
1616 int if_was_operative;
1617
1618 if_was_operative = if_is_no_ptm_operative(ifp);
1619 UNSET_FLAG(ifp->status, ZEBRA_INTERFACE_LINKDETECTION);
2e3b2e47 1620
d62a17ae 1621 /* Interface may come up after disabling link detection */
1622 if (if_is_operative(ifp) && !if_was_operative)
1623 if_up(ifp);
2e3b2e47 1624
d62a17ae 1625 /* FIXME: see linkdetect_cmd */
2e3b2e47 1626
d62a17ae 1627 return CMD_SUCCESS;
2e3b2e47 1628}
1629
718e3744 1630DEFUN (shutdown_if,
1631 shutdown_if_cmd,
1632 "shutdown",
1633 "Shutdown the selected interface\n")
1634{
d62a17ae 1635 VTY_DECLVAR_CONTEXT(interface, ifp);
1636 int ret;
1637 struct zebra_if *if_data;
718e3744 1638
d62a17ae 1639 if (ifp->ifindex != IFINDEX_INTERNAL) {
1640 ret = if_unset_flags(ifp, IFF_UP);
1641 if (ret < 0) {
1642 vty_out(vty, "Can't shutdown interface\n");
1643 return CMD_WARNING_CONFIG_FAILED;
1644 }
1645 if_refresh(ifp);
1646 }
1647 if_data = ifp->info;
1648 if_data->shutdown = IF_ZEBRA_SHUTDOWN_ON;
718e3744 1649
d62a17ae 1650 return CMD_SUCCESS;
718e3744 1651}
1652
1653DEFUN (no_shutdown_if,
1654 no_shutdown_if_cmd,
1655 "no shutdown",
1656 NO_STR
1657 "Shutdown the selected interface\n")
1658{
d62a17ae 1659 VTY_DECLVAR_CONTEXT(interface, ifp);
1660 int ret;
1661 struct zebra_if *if_data;
718e3744 1662
d62a17ae 1663 if (ifp->ifindex != IFINDEX_INTERNAL) {
1664 ret = if_set_flags(ifp, IFF_UP | IFF_RUNNING);
1665 if (ret < 0) {
1666 vty_out(vty, "Can't up interface\n");
1667 return CMD_WARNING_CONFIG_FAILED;
1668 }
1669 if_refresh(ifp);
bfac8dcd 1670
d62a17ae 1671 /* Some addresses (in particular, IPv6 addresses on Linux) get
1672 * removed when the interface goes down. They need to be
1673 * readded.
1674 */
1675 if_addr_wakeup(ifp);
1676 }
bfac8dcd 1677
d62a17ae 1678 if_data = ifp->info;
1679 if_data->shutdown = IF_ZEBRA_SHUTDOWN_OFF;
718e3744 1680
d62a17ae 1681 return CMD_SUCCESS;
718e3744 1682}
1683
1684DEFUN (bandwidth_if,
1685 bandwidth_if_cmd,
6147e2c6 1686 "bandwidth (1-100000)",
718e3744 1687 "Set bandwidth informational parameter\n"
70bd3c43 1688 "Bandwidth in megabits\n")
718e3744 1689{
d62a17ae 1690 int idx_number = 1;
1691 VTY_DECLVAR_CONTEXT(interface, ifp);
1692 unsigned int bandwidth;
1693
1694 bandwidth = strtol(argv[idx_number]->arg, NULL, 10);
1695
1696 /* bandwidth range is <1-100000> */
1697 if (bandwidth < 1 || bandwidth > 100000) {
1698 vty_out(vty, "Bandwidth is invalid\n");
1699 return CMD_WARNING_CONFIG_FAILED;
1700 }
1701
1702 ifp->bandwidth = bandwidth;
718e3744 1703
d62a17ae 1704 /* force protocols to recalculate routes due to cost change */
1705 if (if_is_operative(ifp))
1706 zebra_interface_up_update(ifp);
718e3744 1707
d62a17ae 1708 return CMD_SUCCESS;
718e3744 1709}
1710
1711DEFUN (no_bandwidth_if,
1712 no_bandwidth_if_cmd,
b62ecea5 1713 "no bandwidth [(1-100000)]",
718e3744 1714 NO_STR
b62ecea5
QY
1715 "Set bandwidth informational parameter\n"
1716 "Bandwidth in megabits\n")
718e3744 1717{
d62a17ae 1718 VTY_DECLVAR_CONTEXT(interface, ifp);
718e3744 1719
d62a17ae 1720 ifp->bandwidth = 0;
718e3744 1721
d62a17ae 1722 /* force protocols to recalculate routes due to cost change */
1723 if (if_is_operative(ifp))
1724 zebra_interface_up_update(ifp);
1725
1726 return CMD_SUCCESS;
718e3744 1727}
1728
6b0655a2 1729
d62a17ae 1730struct cmd_node link_params_node = {
9d303b37 1731 LINK_PARAMS_NODE, "%s(config-link-params)# ", 1,
16f1b9ee
OD
1732};
1733
d62a17ae 1734static void link_param_cmd_set_uint32(struct interface *ifp, uint32_t *field,
1735 uint32_t type, uint32_t value)
16f1b9ee 1736{
d62a17ae 1737 /* Update field as needed */
1738 if (IS_PARAM_UNSET(ifp->link_params, type) || *field != value) {
1739 *field = value;
1740 SET_PARAM(ifp->link_params, type);
16f1b9ee 1741
d62a17ae 1742 /* force protocols to update LINK STATE due to parameters change
1743 */
1744 if (if_is_operative(ifp))
1745 zebra_interface_parameters_update(ifp);
1746 }
16f1b9ee 1747}
d62a17ae 1748static void link_param_cmd_set_float(struct interface *ifp, float *field,
1749 uint32_t type, float value)
16f1b9ee
OD
1750{
1751
d62a17ae 1752 /* Update field as needed */
1753 if (IS_PARAM_UNSET(ifp->link_params, type) || *field != value) {
1754 *field = value;
1755 SET_PARAM(ifp->link_params, type);
16f1b9ee 1756
d62a17ae 1757 /* force protocols to update LINK STATE due to parameters change
1758 */
1759 if (if_is_operative(ifp))
1760 zebra_interface_parameters_update(ifp);
1761 }
16f1b9ee
OD
1762}
1763
d62a17ae 1764static void link_param_cmd_unset(struct interface *ifp, uint32_t type)
16f1b9ee 1765{
d62a17ae 1766 if (ifp->link_params == NULL)
1767 return;
16f1b9ee 1768
d62a17ae 1769 /* Unset field */
1770 UNSET_PARAM(ifp->link_params, type);
16f1b9ee 1771
d62a17ae 1772 /* force protocols to update LINK STATE due to parameters change */
1773 if (if_is_operative(ifp))
1774 zebra_interface_parameters_update(ifp);
16f1b9ee
OD
1775}
1776
505e5056 1777DEFUN_NOSH (link_params,
16f1b9ee
OD
1778 link_params_cmd,
1779 "link-params",
1780 LINK_PARAMS_STR)
1781{
d62a17ae 1782 /* vty->qobj_index stays the same @ interface pointer */
1783 vty->node = LINK_PARAMS_NODE;
16f1b9ee 1784
d62a17ae 1785 return CMD_SUCCESS;
16f1b9ee
OD
1786}
1787
505e5056 1788DEFUN_NOSH (exit_link_params,
03f99d9a
DS
1789 exit_link_params_cmd,
1790 "exit-link-params",
1791 "Exit from Link Params configuration mode\n")
1792{
d62a17ae 1793 if (vty->node == LINK_PARAMS_NODE)
1794 vty->node = INTERFACE_NODE;
1795 return CMD_SUCCESS;
03f99d9a
DS
1796}
1797
16f1b9ee
OD
1798/* Specific Traffic Engineering parameters commands */
1799DEFUN (link_params_enable,
1800 link_params_enable_cmd,
1801 "enable",
1802 "Activate link parameters on this interface\n")
1803{
d62a17ae 1804 VTY_DECLVAR_CONTEXT(interface, ifp);
16f1b9ee 1805
d62a17ae 1806 /* This command could be issue at startup, when activate MPLS TE */
1807 /* on a new interface or after a ON / OFF / ON toggle */
1808 /* In all case, TE parameters are reset to their default factory */
1809 if (IS_ZEBRA_DEBUG_EVENT)
1810 zlog_debug(
1811 "Link-params: enable TE link parameters on interface %s",
1812 ifp->name);
16f1b9ee 1813
d62a17ae 1814 if (!if_link_params_get(ifp)) {
1815 if (IS_ZEBRA_DEBUG_EVENT)
1816 zlog_debug(
1817 "Link-params: failed to init TE link parameters %s",
1818 ifp->name);
16f1b9ee 1819
d62a17ae 1820 return CMD_WARNING_CONFIG_FAILED;
1821 }
16f1b9ee 1822
d62a17ae 1823 /* force protocols to update LINK STATE due to parameters change */
1824 if (if_is_operative(ifp))
1825 zebra_interface_parameters_update(ifp);
16f1b9ee 1826
d62a17ae 1827 return CMD_SUCCESS;
16f1b9ee
OD
1828}
1829
1830DEFUN (no_link_params_enable,
1831 no_link_params_enable_cmd,
1832 "no enable",
1833 NO_STR
1834 "Disable link parameters on this interface\n")
1835{
d62a17ae 1836 VTY_DECLVAR_CONTEXT(interface, ifp);
16f1b9ee 1837
d62a17ae 1838 zlog_debug("MPLS-TE: disable TE link parameters on interface %s",
1839 ifp->name);
16f1b9ee 1840
d62a17ae 1841 if_link_params_free(ifp);
16f1b9ee 1842
d62a17ae 1843 /* force protocols to update LINK STATE due to parameters change */
1844 if (if_is_operative(ifp))
1845 zebra_interface_parameters_update(ifp);
16f1b9ee 1846
d62a17ae 1847 return CMD_SUCCESS;
16f1b9ee
OD
1848}
1849
1850/* STANDARD TE metrics */
1851DEFUN (link_params_metric,
1852 link_params_metric_cmd,
6147e2c6 1853 "metric (0-4294967295)",
16f1b9ee
OD
1854 "Link metric for MPLS-TE purpose\n"
1855 "Metric value in decimal\n")
1856{
d62a17ae 1857 int idx_number = 1;
1858 VTY_DECLVAR_CONTEXT(interface, ifp);
1859 struct if_link_params *iflp = if_link_params_get(ifp);
1860 u_int32_t metric;
16f1b9ee 1861
d62a17ae 1862 metric = strtoul(argv[idx_number]->arg, NULL, 10);
16f1b9ee 1863
d62a17ae 1864 /* Update TE metric if needed */
1865 link_param_cmd_set_uint32(ifp, &iflp->te_metric, LP_TE_METRIC, metric);
16f1b9ee 1866
d62a17ae 1867 return CMD_SUCCESS;
16f1b9ee
OD
1868}
1869
1870DEFUN (no_link_params_metric,
1871 no_link_params_metric_cmd,
1872 "no metric",
1873 NO_STR
3ddccf18 1874 "Disable Link Metric on this interface\n")
16f1b9ee 1875{
d62a17ae 1876 VTY_DECLVAR_CONTEXT(interface, ifp);
16f1b9ee 1877
d62a17ae 1878 /* Unset TE Metric */
1879 link_param_cmd_unset(ifp, LP_TE_METRIC);
16f1b9ee 1880
d62a17ae 1881 return CMD_SUCCESS;
16f1b9ee
OD
1882}
1883
1884DEFUN (link_params_maxbw,
1885 link_params_maxbw_cmd,
1886 "max-bw BANDWIDTH",
1887 "Maximum bandwidth that can be used\n"
1888 "Bytes/second (IEEE floating point format)\n")
1889{
d62a17ae 1890 int idx_bandwidth = 1;
1891 VTY_DECLVAR_CONTEXT(interface, ifp);
1892 struct if_link_params *iflp = if_link_params_get(ifp);
1893
1894 float bw;
1895
1896 if (sscanf(argv[idx_bandwidth]->arg, "%g", &bw) != 1) {
1897 vty_out(vty, "link_params_maxbw: fscanf: %s\n",
1898 safe_strerror(errno));
1899 return CMD_WARNING_CONFIG_FAILED;
1900 }
1901
1902 /* Check that Maximum bandwidth is not lower than other bandwidth
1903 * parameters */
1904 if ((bw <= iflp->max_rsv_bw) || (bw <= iflp->unrsv_bw[0])
1905 || (bw <= iflp->unrsv_bw[1]) || (bw <= iflp->unrsv_bw[2])
1906 || (bw <= iflp->unrsv_bw[3]) || (bw <= iflp->unrsv_bw[4])
1907 || (bw <= iflp->unrsv_bw[5]) || (bw <= iflp->unrsv_bw[6])
1908 || (bw <= iflp->unrsv_bw[7]) || (bw <= iflp->ava_bw)
1909 || (bw <= iflp->res_bw) || (bw <= iflp->use_bw)) {
1910 vty_out(vty,
1911 "Maximum Bandwidth could not be lower than others bandwidth\n");
1912 return CMD_WARNING_CONFIG_FAILED;
1913 }
1914
1915 /* Update Maximum Bandwidth if needed */
1916 link_param_cmd_set_float(ifp, &iflp->max_bw, LP_MAX_BW, bw);
1917
1918 return CMD_SUCCESS;
16f1b9ee
OD
1919}
1920
1921DEFUN (link_params_max_rsv_bw,
1922 link_params_max_rsv_bw_cmd,
1923 "max-rsv-bw BANDWIDTH",
1924 "Maximum bandwidth that may be reserved\n"
1925 "Bytes/second (IEEE floating point format)\n")
1926{
d62a17ae 1927 int idx_bandwidth = 1;
1928 VTY_DECLVAR_CONTEXT(interface, ifp);
1929 struct if_link_params *iflp = if_link_params_get(ifp);
1930 float bw;
16f1b9ee 1931
d62a17ae 1932 if (sscanf(argv[idx_bandwidth]->arg, "%g", &bw) != 1) {
1933 vty_out(vty, "link_params_max_rsv_bw: fscanf: %s\n",
1934 safe_strerror(errno));
1935 return CMD_WARNING_CONFIG_FAILED;
1936 }
16f1b9ee 1937
d62a17ae 1938 /* Check that bandwidth is not greater than maximum bandwidth parameter
1939 */
1940 if (bw > iflp->max_bw) {
1941 vty_out(vty,
1942 "Maximum Reservable Bandwidth could not be greater than Maximum Bandwidth (%g)\n",
1943 iflp->max_bw);
1944 return CMD_WARNING_CONFIG_FAILED;
1945 }
16f1b9ee 1946
d62a17ae 1947 /* Update Maximum Reservable Bandwidth if needed */
1948 link_param_cmd_set_float(ifp, &iflp->max_rsv_bw, LP_MAX_RSV_BW, bw);
16f1b9ee 1949
d62a17ae 1950 return CMD_SUCCESS;
16f1b9ee
OD
1951}
1952
1953DEFUN (link_params_unrsv_bw,
1954 link_params_unrsv_bw_cmd,
6147e2c6 1955 "unrsv-bw (0-7) BANDWIDTH",
16f1b9ee
OD
1956 "Unreserved bandwidth at each priority level\n"
1957 "Priority\n"
1958 "Bytes/second (IEEE floating point format)\n")
1959{
d62a17ae 1960 int idx_number = 1;
1961 int idx_bandwidth = 2;
1962 VTY_DECLVAR_CONTEXT(interface, ifp);
1963 struct if_link_params *iflp = if_link_params_get(ifp);
1964 int priority;
1965 float bw;
1966
1967 /* We don't have to consider about range check here. */
1968 if (sscanf(argv[idx_number]->arg, "%d", &priority) != 1) {
1969 vty_out(vty, "link_params_unrsv_bw: fscanf: %s\n",
1970 safe_strerror(errno));
1971 return CMD_WARNING_CONFIG_FAILED;
1972 }
1973
1974 if (sscanf(argv[idx_bandwidth]->arg, "%g", &bw) != 1) {
1975 vty_out(vty, "link_params_unrsv_bw: fscanf: %s\n",
1976 safe_strerror(errno));
1977 return CMD_WARNING_CONFIG_FAILED;
1978 }
1979
1980 /* Check that bandwidth is not greater than maximum bandwidth parameter
1981 */
1982 if (bw > iflp->max_bw) {
1983 vty_out(vty,
1984 "UnReserved Bandwidth could not be greater than Maximum Bandwidth (%g)\n",
1985 iflp->max_bw);
1986 return CMD_WARNING_CONFIG_FAILED;
1987 }
1988
1989 /* Update Unreserved Bandwidth if needed */
1990 link_param_cmd_set_float(ifp, &iflp->unrsv_bw[priority], LP_UNRSV_BW,
1991 bw);
1992
1993 return CMD_SUCCESS;
16f1b9ee
OD
1994}
1995
1996DEFUN (link_params_admin_grp,
1997 link_params_admin_grp_cmd,
1998 "admin-grp BITPATTERN",
1999 "Administrative group membership\n"
2000 "32-bit Hexadecimal value (e.g. 0xa1)\n")
2001{
d62a17ae 2002 int idx_bitpattern = 1;
2003 VTY_DECLVAR_CONTEXT(interface, ifp);
2004 struct if_link_params *iflp = if_link_params_get(ifp);
2005 unsigned long value;
16f1b9ee 2006
d62a17ae 2007 if (sscanf(argv[idx_bitpattern]->arg, "0x%lx", &value) != 1) {
2008 vty_out(vty, "link_params_admin_grp: fscanf: %s\n",
2009 safe_strerror(errno));
2010 return CMD_WARNING_CONFIG_FAILED;
2011 }
16f1b9ee 2012
d62a17ae 2013 /* Update Administrative Group if needed */
2014 link_param_cmd_set_uint32(ifp, &iflp->admin_grp, LP_ADM_GRP, value);
16f1b9ee 2015
d62a17ae 2016 return CMD_SUCCESS;
16f1b9ee
OD
2017}
2018
2019DEFUN (no_link_params_admin_grp,
2020 no_link_params_admin_grp_cmd,
2021 "no admin-grp",
2022 NO_STR
3ddccf18 2023 "Disable Administrative group membership on this interface\n")
16f1b9ee 2024{
d62a17ae 2025 VTY_DECLVAR_CONTEXT(interface, ifp);
16f1b9ee 2026
d62a17ae 2027 /* Unset Admin Group */
2028 link_param_cmd_unset(ifp, LP_ADM_GRP);
16f1b9ee 2029
d62a17ae 2030 return CMD_SUCCESS;
16f1b9ee
OD
2031}
2032
2033/* RFC5392 & RFC5316: INTER-AS */
2034DEFUN (link_params_inter_as,
2035 link_params_inter_as_cmd,
6147e2c6 2036 "neighbor A.B.C.D as (1-4294967295)",
16f1b9ee
OD
2037 "Configure remote ASBR information (Neighbor IP address and AS number)\n"
2038 "Remote IP address in dot decimal A.B.C.D\n"
2039 "Remote AS number\n"
2040 "AS number in the range <1-4294967295>\n")
2041{
d62a17ae 2042 int idx_ipv4 = 1;
2043 int idx_number = 3;
16f1b9ee 2044
d62a17ae 2045 VTY_DECLVAR_CONTEXT(interface, ifp);
2046 struct if_link_params *iflp = if_link_params_get(ifp);
2047 struct in_addr addr;
2048 u_int32_t as;
16f1b9ee 2049
d62a17ae 2050 if (!inet_aton(argv[idx_ipv4]->arg, &addr)) {
2051 vty_out(vty, "Please specify Router-Addr by A.B.C.D\n");
2052 return CMD_WARNING_CONFIG_FAILED;
2053 }
16f1b9ee 2054
d62a17ae 2055 as = strtoul(argv[idx_number]->arg, NULL, 10);
16f1b9ee 2056
d62a17ae 2057 /* Update Remote IP and Remote AS fields if needed */
2058 if (IS_PARAM_UNSET(iflp, LP_RMT_AS) || iflp->rmt_as != as
2059 || iflp->rmt_ip.s_addr != addr.s_addr) {
16f1b9ee 2060
d62a17ae 2061 iflp->rmt_as = as;
2062 iflp->rmt_ip.s_addr = addr.s_addr;
2063 SET_PARAM(iflp, LP_RMT_AS);
16f1b9ee 2064
d62a17ae 2065 /* force protocols to update LINK STATE due to parameters change
2066 */
2067 if (if_is_operative(ifp))
2068 zebra_interface_parameters_update(ifp);
2069 }
2070 return CMD_SUCCESS;
16f1b9ee
OD
2071}
2072
2073DEFUN (no_link_params_inter_as,
2074 no_link_params_inter_as_cmd,
2075 "no neighbor",
2076 NO_STR
2077 "Remove Neighbor IP address and AS number for Inter-AS TE\n")
2078{
d62a17ae 2079 VTY_DECLVAR_CONTEXT(interface, ifp);
2080 struct if_link_params *iflp = if_link_params_get(ifp);
16f1b9ee 2081
d62a17ae 2082 /* Reset Remote IP and AS neighbor */
2083 iflp->rmt_as = 0;
2084 iflp->rmt_ip.s_addr = 0;
2085 UNSET_PARAM(iflp, LP_RMT_AS);
16f1b9ee 2086
d62a17ae 2087 /* force protocols to update LINK STATE due to parameters change */
2088 if (if_is_operative(ifp))
2089 zebra_interface_parameters_update(ifp);
16f1b9ee 2090
d62a17ae 2091 return CMD_SUCCESS;
16f1b9ee
OD
2092}
2093
d62a17ae 2094/* RFC7471: OSPF Traffic Engineering (TE) Metric extensions &
2095 * draft-ietf-isis-metric-extensions-07.txt */
16f1b9ee
OD
2096DEFUN (link_params_delay,
2097 link_params_delay_cmd,
b62ecea5 2098 "delay (0-16777215) [min (0-16777215) max (0-16777215)]",
16f1b9ee 2099 "Unidirectional Average Link Delay\n"
b62ecea5
QY
2100 "Average delay in micro-second as decimal (0...16777215)\n"
2101 "Minimum delay\n"
2102 "Minimum delay in micro-second as decimal (0...16777215)\n"
2103 "Maximum delay\n"
2104 "Maximum delay in micro-second as decimal (0...16777215)\n")
16f1b9ee 2105{
d62a17ae 2106 /* Get and Check new delay values */
2107 u_int32_t delay = 0, low = 0, high = 0;
2108 delay = strtoul(argv[1]->arg, NULL, 10);
2109 if (argc == 6) {
2110 low = strtoul(argv[3]->arg, NULL, 10);
2111 high = strtoul(argv[5]->arg, NULL, 10);
2112 }
2113
2114 VTY_DECLVAR_CONTEXT(interface, ifp);
2115 struct if_link_params *iflp = if_link_params_get(ifp);
2116 u_int8_t update = 0;
2117
2118 if (argc == 2) {
2119 /* Check new delay value against old Min and Max delays if set
2120 */
2121 if (IS_PARAM_SET(iflp, LP_MM_DELAY)
2122 && (delay <= iflp->min_delay || delay >= iflp->max_delay)) {
2123 vty_out(vty,
2124 "Average delay should be comprise between Min (%d) and Max (%d) delay\n",
2125 iflp->min_delay, iflp->max_delay);
2126 return CMD_WARNING_CONFIG_FAILED;
2127 }
2128 /* Update delay if value is not set or change */
2129 if (IS_PARAM_UNSET(iflp, LP_DELAY) || iflp->av_delay != delay) {
2130 iflp->av_delay = delay;
2131 SET_PARAM(iflp, LP_DELAY);
2132 update = 1;
2133 }
2134 /* Unset Min and Max delays if already set */
2135 if (IS_PARAM_SET(iflp, LP_MM_DELAY)) {
2136 iflp->min_delay = 0;
2137 iflp->max_delay = 0;
2138 UNSET_PARAM(iflp, LP_MM_DELAY);
2139 update = 1;
2140 }
2141 } else {
2142 /* Check new delays value coherency */
2143 if (delay <= low || delay >= high) {
2144 vty_out(vty,
2145 "Average delay should be comprise between Min (%d) and Max (%d) delay\n",
2146 low, high);
2147 return CMD_WARNING_CONFIG_FAILED;
2148 }
2149 /* Update Delays if needed */
2150 if (IS_PARAM_UNSET(iflp, LP_DELAY)
2151 || IS_PARAM_UNSET(iflp, LP_MM_DELAY)
2152 || iflp->av_delay != delay || iflp->min_delay != low
2153 || iflp->max_delay != high) {
2154 iflp->av_delay = delay;
2155 SET_PARAM(iflp, LP_DELAY);
2156 iflp->min_delay = low;
2157 iflp->max_delay = high;
2158 SET_PARAM(iflp, LP_MM_DELAY);
2159 update = 1;
2160 }
2161 }
2162
2163 /* force protocols to update LINK STATE due to parameters change */
2164 if (update == 1 && if_is_operative(ifp))
2165 zebra_interface_parameters_update(ifp);
2166
2167 return CMD_SUCCESS;
16f1b9ee
OD
2168}
2169
16f1b9ee
OD
2170DEFUN (no_link_params_delay,
2171 no_link_params_delay_cmd,
2172 "no delay",
2173 NO_STR
3ddccf18 2174 "Disable Unidirectional Average, Min & Max Link Delay on this interface\n")
16f1b9ee 2175{
d62a17ae 2176 VTY_DECLVAR_CONTEXT(interface, ifp);
2177 struct if_link_params *iflp = if_link_params_get(ifp);
16f1b9ee 2178
d62a17ae 2179 /* Unset Delays */
2180 iflp->av_delay = 0;
2181 UNSET_PARAM(iflp, LP_DELAY);
2182 iflp->min_delay = 0;
2183 iflp->max_delay = 0;
2184 UNSET_PARAM(iflp, LP_MM_DELAY);
16f1b9ee 2185
d62a17ae 2186 /* force protocols to update LINK STATE due to parameters change */
2187 if (if_is_operative(ifp))
2188 zebra_interface_parameters_update(ifp);
16f1b9ee 2189
d62a17ae 2190 return CMD_SUCCESS;
16f1b9ee
OD
2191}
2192
2193DEFUN (link_params_delay_var,
2194 link_params_delay_var_cmd,
6147e2c6 2195 "delay-variation (0-16777215)",
16f1b9ee
OD
2196 "Unidirectional Link Delay Variation\n"
2197 "delay variation in micro-second as decimal (0...16777215)\n")
2198{
d62a17ae 2199 int idx_number = 1;
2200 VTY_DECLVAR_CONTEXT(interface, ifp);
2201 struct if_link_params *iflp = if_link_params_get(ifp);
2202 u_int32_t value;
16f1b9ee 2203
d62a17ae 2204 value = strtoul(argv[idx_number]->arg, NULL, 10);
16f1b9ee 2205
d62a17ae 2206 /* Update Delay Variation if needed */
2207 link_param_cmd_set_uint32(ifp, &iflp->delay_var, LP_DELAY_VAR, value);
16f1b9ee 2208
d62a17ae 2209 return CMD_SUCCESS;
16f1b9ee
OD
2210}
2211
2212DEFUN (no_link_params_delay_var,
2213 no_link_params_delay_var_cmd,
2214 "no delay-variation",
2215 NO_STR
3ddccf18 2216 "Disable Unidirectional Delay Variation on this interface\n")
16f1b9ee 2217{
d62a17ae 2218 VTY_DECLVAR_CONTEXT(interface, ifp);
16f1b9ee 2219
d62a17ae 2220 /* Unset Delay Variation */
2221 link_param_cmd_unset(ifp, LP_DELAY_VAR);
16f1b9ee 2222
d62a17ae 2223 return CMD_SUCCESS;
16f1b9ee
OD
2224}
2225
2226DEFUN (link_params_pkt_loss,
2227 link_params_pkt_loss_cmd,
2228 "packet-loss PERCENTAGE",
2229 "Unidirectional Link Packet Loss\n"
2230 "percentage of total traffic by 0.000003% step and less than 50.331642%\n")
2231{
d62a17ae 2232 int idx_percentage = 1;
2233 VTY_DECLVAR_CONTEXT(interface, ifp);
2234 struct if_link_params *iflp = if_link_params_get(ifp);
2235 float fval;
16f1b9ee 2236
d62a17ae 2237 if (sscanf(argv[idx_percentage]->arg, "%g", &fval) != 1) {
2238 vty_out(vty, "link_params_pkt_loss: fscanf: %s\n",
2239 safe_strerror(errno));
2240 return CMD_WARNING_CONFIG_FAILED;
2241 }
16f1b9ee 2242
d62a17ae 2243 if (fval > MAX_PKT_LOSS)
2244 fval = MAX_PKT_LOSS;
16f1b9ee 2245
d62a17ae 2246 /* Update Packet Loss if needed */
2247 link_param_cmd_set_float(ifp, &iflp->pkt_loss, LP_PKT_LOSS, fval);
16f1b9ee 2248
d62a17ae 2249 return CMD_SUCCESS;
16f1b9ee
OD
2250}
2251
2252DEFUN (no_link_params_pkt_loss,
2253 no_link_params_pkt_loss_cmd,
2254 "no packet-loss",
2255 NO_STR
3ddccf18 2256 "Disable Unidirectional Link Packet Loss on this interface\n")
16f1b9ee 2257{
d62a17ae 2258 VTY_DECLVAR_CONTEXT(interface, ifp);
16f1b9ee 2259
d62a17ae 2260 /* Unset Packet Loss */
2261 link_param_cmd_unset(ifp, LP_PKT_LOSS);
16f1b9ee 2262
d62a17ae 2263 return CMD_SUCCESS;
16f1b9ee
OD
2264}
2265
2266DEFUN (link_params_res_bw,
2267 link_params_res_bw_cmd,
2268 "res-bw BANDWIDTH",
2269 "Unidirectional Residual Bandwidth\n"
2270 "Bytes/second (IEEE floating point format)\n")
2271{
d62a17ae 2272 int idx_bandwidth = 1;
2273 VTY_DECLVAR_CONTEXT(interface, ifp);
2274 struct if_link_params *iflp = if_link_params_get(ifp);
2275 float bw;
16f1b9ee 2276
d62a17ae 2277 if (sscanf(argv[idx_bandwidth]->arg, "%g", &bw) != 1) {
2278 vty_out(vty, "link_params_res_bw: fscanf: %s\n",
2279 safe_strerror(errno));
2280 return CMD_WARNING_CONFIG_FAILED;
2281 }
16f1b9ee 2282
d62a17ae 2283 /* Check that bandwidth is not greater than maximum bandwidth parameter
2284 */
2285 if (bw > iflp->max_bw) {
2286 vty_out(vty,
2287 "Residual Bandwidth could not be greater than Maximum Bandwidth (%g)\n",
2288 iflp->max_bw);
2289 return CMD_WARNING_CONFIG_FAILED;
2290 }
16f1b9ee 2291
d62a17ae 2292 /* Update Residual Bandwidth if needed */
2293 link_param_cmd_set_float(ifp, &iflp->res_bw, LP_RES_BW, bw);
16f1b9ee 2294
d62a17ae 2295 return CMD_SUCCESS;
16f1b9ee
OD
2296}
2297
2298DEFUN (no_link_params_res_bw,
2299 no_link_params_res_bw_cmd,
2300 "no res-bw",
2301 NO_STR
3ddccf18 2302 "Disable Unidirectional Residual Bandwidth on this interface\n")
16f1b9ee 2303{
d62a17ae 2304 VTY_DECLVAR_CONTEXT(interface, ifp);
16f1b9ee 2305
d62a17ae 2306 /* Unset Residual Bandwidth */
2307 link_param_cmd_unset(ifp, LP_RES_BW);
16f1b9ee 2308
d62a17ae 2309 return CMD_SUCCESS;
16f1b9ee
OD
2310}
2311
2312DEFUN (link_params_ava_bw,
2313 link_params_ava_bw_cmd,
2314 "ava-bw BANDWIDTH",
2315 "Unidirectional Available Bandwidth\n"
2316 "Bytes/second (IEEE floating point format)\n")
2317{
d62a17ae 2318 int idx_bandwidth = 1;
2319 VTY_DECLVAR_CONTEXT(interface, ifp);
2320 struct if_link_params *iflp = if_link_params_get(ifp);
2321 float bw;
16f1b9ee 2322
d62a17ae 2323 if (sscanf(argv[idx_bandwidth]->arg, "%g", &bw) != 1) {
2324 vty_out(vty, "link_params_ava_bw: fscanf: %s\n",
2325 safe_strerror(errno));
2326 return CMD_WARNING_CONFIG_FAILED;
2327 }
16f1b9ee 2328
d62a17ae 2329 /* Check that bandwidth is not greater than maximum bandwidth parameter
2330 */
2331 if (bw > iflp->max_bw) {
2332 vty_out(vty,
2333 "Available Bandwidth could not be greater than Maximum Bandwidth (%g)\n",
2334 iflp->max_bw);
2335 return CMD_WARNING_CONFIG_FAILED;
2336 }
16f1b9ee 2337
d62a17ae 2338 /* Update Residual Bandwidth if needed */
2339 link_param_cmd_set_float(ifp, &iflp->ava_bw, LP_AVA_BW, bw);
16f1b9ee 2340
d62a17ae 2341 return CMD_SUCCESS;
16f1b9ee
OD
2342}
2343
2344DEFUN (no_link_params_ava_bw,
2345 no_link_params_ava_bw_cmd,
2346 "no ava-bw",
2347 NO_STR
3ddccf18 2348 "Disable Unidirectional Available Bandwidth on this interface\n")
16f1b9ee 2349{
d62a17ae 2350 VTY_DECLVAR_CONTEXT(interface, ifp);
16f1b9ee 2351
d62a17ae 2352 /* Unset Available Bandwidth */
2353 link_param_cmd_unset(ifp, LP_AVA_BW);
16f1b9ee 2354
d62a17ae 2355 return CMD_SUCCESS;
16f1b9ee
OD
2356}
2357
2358DEFUN (link_params_use_bw,
2359 link_params_use_bw_cmd,
2360 "use-bw BANDWIDTH",
2361 "Unidirectional Utilised Bandwidth\n"
2362 "Bytes/second (IEEE floating point format)\n")
2363{
d62a17ae 2364 int idx_bandwidth = 1;
2365 VTY_DECLVAR_CONTEXT(interface, ifp);
2366 struct if_link_params *iflp = if_link_params_get(ifp);
2367 float bw;
16f1b9ee 2368
d62a17ae 2369 if (sscanf(argv[idx_bandwidth]->arg, "%g", &bw) != 1) {
2370 vty_out(vty, "link_params_use_bw: fscanf: %s\n",
2371 safe_strerror(errno));
2372 return CMD_WARNING_CONFIG_FAILED;
2373 }
16f1b9ee 2374
d62a17ae 2375 /* Check that bandwidth is not greater than maximum bandwidth parameter
2376 */
2377 if (bw > iflp->max_bw) {
2378 vty_out(vty,
2379 "Utilised Bandwidth could not be greater than Maximum Bandwidth (%g)\n",
2380 iflp->max_bw);
2381 return CMD_WARNING_CONFIG_FAILED;
2382 }
16f1b9ee 2383
d62a17ae 2384 /* Update Utilized Bandwidth if needed */
2385 link_param_cmd_set_float(ifp, &iflp->use_bw, LP_USE_BW, bw);
16f1b9ee 2386
d62a17ae 2387 return CMD_SUCCESS;
16f1b9ee
OD
2388}
2389
2390DEFUN (no_link_params_use_bw,
2391 no_link_params_use_bw_cmd,
2392 "no use-bw",
2393 NO_STR
3ddccf18 2394 "Disable Unidirectional Utilised Bandwidth on this interface\n")
16f1b9ee 2395{
d62a17ae 2396 VTY_DECLVAR_CONTEXT(interface, ifp);
16f1b9ee 2397
d62a17ae 2398 /* Unset Utilised Bandwidth */
2399 link_param_cmd_unset(ifp, LP_USE_BW);
16f1b9ee 2400
d62a17ae 2401 return CMD_SUCCESS;
16f1b9ee
OD
2402}
2403
d62a17ae 2404static int ip_address_install(struct vty *vty, struct interface *ifp,
2405 const char *addr_str, const char *peer_str,
2406 const char *label)
718e3744 2407{
d62a17ae 2408 struct zebra_if *if_data;
a07df329 2409 struct prefix_ipv4 lp, pp;
d62a17ae 2410 struct connected *ifc;
2411 struct prefix_ipv4 *p;
2412 int ret;
718e3744 2413
d62a17ae 2414 if_data = ifp->info;
bfac8dcd 2415
a07df329 2416 ret = str2prefix_ipv4(addr_str, &lp);
d62a17ae 2417 if (ret <= 0) {
2418 vty_out(vty, "%% Malformed address \n");
2419 return CMD_WARNING_CONFIG_FAILED;
2420 }
718e3744 2421
a07df329 2422 if (ipv4_martian(&lp.prefix)) {
d62a17ae 2423 vty_out(vty, "%% Invalid address\n");
2424 return CMD_WARNING_CONFIG_FAILED;
2425 }
d914d5ff 2426
a07df329
DL
2427 if (peer_str) {
2428 if (lp.prefixlen != 32) {
2429 vty_out(vty,
2430 "%% Local prefix length for P-t-P address must be /32\n");
2431 return CMD_WARNING_CONFIG_FAILED;
2432 }
2433
2434 ret = str2prefix_ipv4(peer_str, &pp);
2435 if (ret <= 0) {
2436 vty_out(vty, "%% Malformed peer address\n");
2437 return CMD_WARNING_CONFIG_FAILED;
2438 }
2439 }
2440
2441 ifc = connected_check_ptp(ifp, &lp, peer_str ? &pp : NULL);
d62a17ae 2442 if (!ifc) {
2443 ifc = connected_new();
2444 ifc->ifp = ifp;
2445
2446 /* Address. */
2447 p = prefix_ipv4_new();
a07df329 2448 *p = lp;
d62a17ae 2449 ifc->address = (struct prefix *)p;
2450
a07df329
DL
2451 if (peer_str) {
2452 SET_FLAG(ifc->flags, ZEBRA_IFA_PEER);
2453 p = prefix_ipv4_new();
2454 *p = pp;
2455 ifc->destination = (struct prefix *)p;
2456 } else if (p->prefixlen <= IPV4_MAX_PREFIXLEN - 2) {
d62a17ae 2457 p = prefix_ipv4_new();
a07df329 2458 *p = lp;
d62a17ae 2459 p->prefix.s_addr = ipv4_broadcast_addr(p->prefix.s_addr,
2460 p->prefixlen);
2461 ifc->destination = (struct prefix *)p;
2462 }
718e3744 2463
d62a17ae 2464 /* Label. */
2465 if (label)
2466 ifc->label = XSTRDUP(MTYPE_CONNECTED_LABEL, label);
718e3744 2467
d62a17ae 2468 /* Add to linked list. */
2469 listnode_add(ifp->connected, ifc);
718e3744 2470 }
2471
d62a17ae 2472 /* This address is configured from zebra. */
2473 if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED))
2474 SET_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED);
2475
2476 /* In case of this route need to install kernel. */
2477 if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_QUEUED)
2478 && CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE)
2479 && !(if_data && if_data->shutdown == IF_ZEBRA_SHUTDOWN_ON)) {
2480 /* Some system need to up the interface to set IP address. */
2481 if (!if_is_up(ifp)) {
2482 if_set_flags(ifp, IFF_UP | IFF_RUNNING);
2483 if_refresh(ifp);
2484 }
2485
2486 ret = if_set_prefix(ifp, ifc);
2487 if (ret < 0) {
2488 vty_out(vty, "%% Can't set interface IP address: %s.\n",
2489 safe_strerror(errno));
2490 return CMD_WARNING_CONFIG_FAILED;
2491 }
2492
2493 SET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED);
2494 /* The address will be advertised to zebra clients when the
2495 * notification
2496 * from the kernel has been received.
2497 * It will also be added to the subnet chain list, then. */
2498 }
2499
2500 return CMD_SUCCESS;
2501}
2502
2503static int ip_address_uninstall(struct vty *vty, struct interface *ifp,
2504 const char *addr_str, const char *peer_str,
2505 const char *label)
2506{
a07df329 2507 struct prefix_ipv4 lp, pp;
d62a17ae 2508 struct connected *ifc;
2509 int ret;
2510
2511 /* Convert to prefix structure. */
a07df329 2512 ret = str2prefix_ipv4(addr_str, &lp);
d62a17ae 2513 if (ret <= 0) {
2514 vty_out(vty, "%% Malformed address \n");
2515 return CMD_WARNING_CONFIG_FAILED;
2516 }
2517
a07df329
DL
2518 if (peer_str) {
2519 if (lp.prefixlen != 32) {
2520 vty_out(vty,
2521 "%% Local prefix length for P-t-P address must be /32\n");
2522 return CMD_WARNING_CONFIG_FAILED;
2523 }
2524
2525 ret = str2prefix_ipv4(peer_str, &pp);
2526 if (ret <= 0) {
2527 vty_out(vty, "%% Malformed peer address\n");
2528 return CMD_WARNING_CONFIG_FAILED;
2529 }
2530 }
2531
d62a17ae 2532 /* Check current interface address. */
a07df329 2533 ifc = connected_check_ptp(ifp, &lp, peer_str ? &pp : NULL);
d62a17ae 2534 if (!ifc) {
2535 vty_out(vty, "%% Can't find address\n");
2536 return CMD_WARNING_CONFIG_FAILED;
2537 }
2538
2539 /* This is not configured address. */
2540 if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED))
2541 return CMD_WARNING_CONFIG_FAILED;
2542
2543 UNSET_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED);
2544
2545 /* This is not real address or interface is not active. */
2546 if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_QUEUED)
2547 || !CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE)) {
2548 listnode_delete(ifp->connected, ifc);
2549 connected_free(ifc);
2550 return CMD_WARNING_CONFIG_FAILED;
2551 }
2552
2553 /* This is real route. */
2554 ret = if_unset_prefix(ifp, ifc);
2555 if (ret < 0) {
2556 vty_out(vty, "%% Can't unset interface IP address: %s.\n",
2557 safe_strerror(errno));
2558 return CMD_WARNING_CONFIG_FAILED;
2559 }
2560 UNSET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED);
2561 /* we will receive a kernel notification about this route being removed.
2562 * this will trigger its removal from the connected list. */
2563 return CMD_SUCCESS;
718e3744 2564}
2565
2566DEFUN (ip_address,
2567 ip_address_cmd,
2568 "ip address A.B.C.D/M",
2569 "Interface Internet Protocol config commands\n"
2570 "Set the IP address of an interface\n"
2571 "IP address (e.g. 10.0.0.1/8)\n")
2572{
d62a17ae 2573 int idx_ipv4_prefixlen = 2;
2574 VTY_DECLVAR_CONTEXT(interface, ifp);
2575 return ip_address_install(vty, ifp, argv[idx_ipv4_prefixlen]->arg, NULL,
2576 NULL);
718e3744 2577}
2578
2579DEFUN (no_ip_address,
2580 no_ip_address_cmd,
2581 "no ip address A.B.C.D/M",
2582 NO_STR
2583 "Interface Internet Protocol config commands\n"
2584 "Set the IP address of an interface\n"
efd7904e 2585 "IP Address (e.g. 10.0.0.1/8)\n")
718e3744 2586{
d62a17ae 2587 int idx_ipv4_prefixlen = 3;
2588 VTY_DECLVAR_CONTEXT(interface, ifp);
2589 return ip_address_uninstall(vty, ifp, argv[idx_ipv4_prefixlen]->arg,
2590 NULL, NULL);
718e3744 2591}
2592
60466a63
QY
2593DEFUN(ip_address_peer,
2594 ip_address_peer_cmd,
2595 "ip address A.B.C.D peer A.B.C.D/M",
2596 "Interface Internet Protocol config commands\n"
2597 "Set the IP address of an interface\n"
2598 "Local IP (e.g. 10.0.0.1) for P-t-P address\n"
2599 "Specify P-t-P address\n"
2600 "Peer IP address (e.g. 10.0.0.1/8)\n")
a07df329
DL
2601{
2602 VTY_DECLVAR_CONTEXT(interface, ifp);
2603 return ip_address_install(vty, ifp, argv[2]->arg, argv[4]->arg, NULL);
2604}
2605
60466a63
QY
2606DEFUN(no_ip_address_peer,
2607 no_ip_address_peer_cmd,
2608 "no ip address A.B.C.D peer A.B.C.D/M",
2609 NO_STR
2610 "Interface Internet Protocol config commands\n"
2611 "Set the IP address of an interface\n"
2612 "Local IP (e.g. 10.0.0.1) for P-t-P address\n"
2613 "Specify P-t-P address\n"
2614 "Peer IP address (e.g. 10.0.0.1/8)\n")
a07df329
DL
2615{
2616 VTY_DECLVAR_CONTEXT(interface, ifp);
2617 return ip_address_uninstall(vty, ifp, argv[3]->arg, argv[5]->arg, NULL);
2618}
986aa00f 2619
718e3744 2620#ifdef HAVE_NETLINK
718e3744 2621DEFUN (ip_address_label,
2622 ip_address_label_cmd,
2623 "ip address A.B.C.D/M label LINE",
2624 "Interface Internet Protocol config commands\n"
2625 "Set the IP address of an interface\n"
2626 "IP address (e.g. 10.0.0.1/8)\n"
2627 "Label of this address\n"
2628 "Label\n")
2629{
d62a17ae 2630 int idx_ipv4_prefixlen = 2;
2631 int idx_line = 4;
2632 VTY_DECLVAR_CONTEXT(interface, ifp);
2633 return ip_address_install(vty, ifp, argv[idx_ipv4_prefixlen]->arg, NULL,
2634 argv[idx_line]->arg);
718e3744 2635}
2636
2637DEFUN (no_ip_address_label,
2638 no_ip_address_label_cmd,
2639 "no ip address A.B.C.D/M label LINE",
2640 NO_STR
2641 "Interface Internet Protocol config commands\n"
2642 "Set the IP address of an interface\n"
2643 "IP address (e.g. 10.0.0.1/8)\n"
2644 "Label of this address\n"
2645 "Label\n")
2646{
d62a17ae 2647 int idx_ipv4_prefixlen = 3;
2648 int idx_line = 5;
2649 VTY_DECLVAR_CONTEXT(interface, ifp);
2650 return ip_address_uninstall(vty, ifp, argv[idx_ipv4_prefixlen]->arg,
2651 NULL, argv[idx_line]->arg);
718e3744 2652}
2653#endif /* HAVE_NETLINK */
2654
d62a17ae 2655static int ipv6_address_install(struct vty *vty, struct interface *ifp,
2656 const char *addr_str, const char *peer_str,
2657 const char *label, int secondary)
2658{
2659 struct zebra_if *if_data;
2660 struct prefix_ipv6 cp;
2661 struct connected *ifc;
2662 struct prefix_ipv6 *p;
2663 int ret;
2664
2665 if_data = ifp->info;
2666
2667 ret = str2prefix_ipv6(addr_str, &cp);
2668 if (ret <= 0) {
2669 vty_out(vty, "%% Malformed address \n");
2670 return CMD_WARNING_CONFIG_FAILED;
718e3744 2671 }
2672
d62a17ae 2673 if (ipv6_martian(&cp.prefix)) {
2674 vty_out(vty, "%% Invalid address\n");
2675 return CMD_WARNING_CONFIG_FAILED;
2676 }
718e3744 2677
d62a17ae 2678 ifc = connected_check(ifp, (struct prefix *)&cp);
2679 if (!ifc) {
2680 ifc = connected_new();
2681 ifc->ifp = ifp;
2682
2683 /* Address. */
2684 p = prefix_ipv6_new();
2685 *p = cp;
2686 ifc->address = (struct prefix *)p;
2687
2688 /* Secondary. */
2689 if (secondary)
2690 SET_FLAG(ifc->flags, ZEBRA_IFA_SECONDARY);
2691
2692 /* Label. */
2693 if (label)
2694 ifc->label = XSTRDUP(MTYPE_CONNECTED_LABEL, label);
2695
2696 /* Add to linked list. */
2697 listnode_add(ifp->connected, ifc);
718e3744 2698 }
2699
d62a17ae 2700 /* This address is configured from zebra. */
2701 if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED))
2702 SET_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED);
2703
2704 /* In case of this route need to install kernel. */
2705 if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_QUEUED)
2706 && CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE)
2707 && !(if_data && if_data->shutdown == IF_ZEBRA_SHUTDOWN_ON)) {
2708 /* Some system need to up the interface to set IP address. */
2709 if (!if_is_up(ifp)) {
2710 if_set_flags(ifp, IFF_UP | IFF_RUNNING);
2711 if_refresh(ifp);
2712 }
2713
2714 ret = if_prefix_add_ipv6(ifp, ifc);
2715
2716 if (ret < 0) {
2717 vty_out(vty, "%% Can't set interface IP address: %s.\n",
2718 safe_strerror(errno));
2719 return CMD_WARNING_CONFIG_FAILED;
2720 }
2721
2722 SET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED);
2723 /* The address will be advertised to zebra clients when the
2724 * notification
2725 * from the kernel has been received. */
2726 }
718e3744 2727
d62a17ae 2728 return CMD_SUCCESS;
718e3744 2729}
2730
b6120505 2731/* Return true if an ipv6 address is configured on ifp */
d62a17ae 2732int ipv6_address_configured(struct interface *ifp)
2733{
2734 struct connected *connected;
2735 struct listnode *node;
2736
2737 for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, connected))
2738 if (CHECK_FLAG(connected->conf, ZEBRA_IFC_REAL)
2739 && (connected->address->family == AF_INET6))
2740 return 1;
2741
2742 return 0;
2743}
2744
2745static int ipv6_address_uninstall(struct vty *vty, struct interface *ifp,
2746 const char *addr_str, const char *peer_str,
2747 const char *label, int secondry)
2748{
2749 struct prefix_ipv6 cp;
2750 struct connected *ifc;
2751 int ret;
2752
2753 /* Convert to prefix structure. */
2754 ret = str2prefix_ipv6(addr_str, &cp);
2755 if (ret <= 0) {
2756 vty_out(vty, "%% Malformed address \n");
2757 return CMD_WARNING_CONFIG_FAILED;
2758 }
2759
2760 /* Check current interface address. */
2761 ifc = connected_check(ifp, (struct prefix *)&cp);
2762 if (!ifc) {
2763 vty_out(vty, "%% Can't find address\n");
2764 return CMD_WARNING_CONFIG_FAILED;
2765 }
2766
2767 /* This is not configured address. */
2768 if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED))
2769 return CMD_WARNING_CONFIG_FAILED;
2770
2771 UNSET_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED);
2772
2773 /* This is not real address or interface is not active. */
2774 if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_QUEUED)
2775 || !CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE)) {
2776 listnode_delete(ifp->connected, ifc);
2777 connected_free(ifc);
2778 return CMD_WARNING_CONFIG_FAILED;
2779 }
2780
2781 /* This is real route. */
2782 ret = if_prefix_delete_ipv6(ifp, ifc);
2783 if (ret < 0) {
2784 vty_out(vty, "%% Can't unset interface IP address: %s.\n",
2785 safe_strerror(errno));
2786 return CMD_WARNING_CONFIG_FAILED;
2787 }
2788
2789 UNSET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED);
2790 /* This information will be propagated to the zclients when the
2791 * kernel notification is received. */
2792 return CMD_SUCCESS;
718e3744 2793}
2794
2795DEFUN (ipv6_address,
2796 ipv6_address_cmd,
2797 "ipv6 address X:X::X:X/M",
e23949c0 2798 "Interface IPv6 config commands\n"
718e3744 2799 "Set the IP address of an interface\n"
2800 "IPv6 address (e.g. 3ffe:506::1/48)\n")
2801{
d62a17ae 2802 int idx_ipv6_prefixlen = 2;
2803 VTY_DECLVAR_CONTEXT(interface, ifp);
2804 return ipv6_address_install(vty, ifp, argv[idx_ipv6_prefixlen]->arg,
2805 NULL, NULL, 0);
718e3744 2806}
2807
2808DEFUN (no_ipv6_address,
2809 no_ipv6_address_cmd,
2810 "no ipv6 address X:X::X:X/M",
2811 NO_STR
e23949c0 2812 "Interface IPv6 config commands\n"
718e3744 2813 "Set the IP address of an interface\n"
2814 "IPv6 address (e.g. 3ffe:506::1/48)\n")
2815{
d62a17ae 2816 int idx_ipv6_prefixlen = 3;
2817 VTY_DECLVAR_CONTEXT(interface, ifp);
2818 return ipv6_address_uninstall(vty, ifp, argv[idx_ipv6_prefixlen]->arg,
2819 NULL, NULL, 0);
2820}
2821
2822static int link_params_config_write(struct vty *vty, struct interface *ifp)
2823{
2824 int i;
2825
2826 if ((ifp == NULL) || !HAS_LINK_PARAMS(ifp))
2827 return -1;
986aa00f 2828
d62a17ae 2829 struct if_link_params *iflp = ifp->link_params;
2830
2831 vty_out(vty, " link-params\n");
2832 vty_out(vty, " enable\n");
2833 if (IS_PARAM_SET(iflp, LP_TE_METRIC) && iflp->te_metric != ifp->metric)
2834 vty_out(vty, " metric %u\n", iflp->te_metric);
2835 if (IS_PARAM_SET(iflp, LP_MAX_BW) && iflp->max_bw != iflp->default_bw)
2836 vty_out(vty, " max-bw %g\n", iflp->max_bw);
2837 if (IS_PARAM_SET(iflp, LP_MAX_RSV_BW)
2838 && iflp->max_rsv_bw != iflp->default_bw)
2839 vty_out(vty, " max-rsv-bw %g\n", iflp->max_rsv_bw);
2840 if (IS_PARAM_SET(iflp, LP_UNRSV_BW)) {
2841 for (i = 0; i < 8; i++)
2842 if (iflp->unrsv_bw[i] != iflp->default_bw)
2843 vty_out(vty, " unrsv-bw %d %g\n", i,
2844 iflp->unrsv_bw[i]);
2845 }
2846 if (IS_PARAM_SET(iflp, LP_ADM_GRP))
2847 vty_out(vty, " admin-grp 0x%x\n", iflp->admin_grp);
2848 if (IS_PARAM_SET(iflp, LP_DELAY)) {
2849 vty_out(vty, " delay %u", iflp->av_delay);
2850 if (IS_PARAM_SET(iflp, LP_MM_DELAY)) {
2851 vty_out(vty, " min %u", iflp->min_delay);
2852 vty_out(vty, " max %u", iflp->max_delay);
2853 }
2854 vty_out(vty, "\n");
bfac8dcd 2855 }
d62a17ae 2856 if (IS_PARAM_SET(iflp, LP_DELAY_VAR))
2857 vty_out(vty, " delay-variation %u\n", iflp->delay_var);
2858 if (IS_PARAM_SET(iflp, LP_PKT_LOSS))
2859 vty_out(vty, " packet-loss %g\n", iflp->pkt_loss);
2860 if (IS_PARAM_SET(iflp, LP_AVA_BW))
2861 vty_out(vty, " ava-bw %g\n", iflp->ava_bw);
2862 if (IS_PARAM_SET(iflp, LP_RES_BW))
2863 vty_out(vty, " res-bw %g\n", iflp->res_bw);
2864 if (IS_PARAM_SET(iflp, LP_USE_BW))
2865 vty_out(vty, " use-bw %g\n", iflp->use_bw);
2866 if (IS_PARAM_SET(iflp, LP_RMT_AS))
2867 vty_out(vty, " neighbor %s as %u\n", inet_ntoa(iflp->rmt_ip),
2868 iflp->rmt_as);
2869 vty_out(vty, " exit-link-params\n");
2870 return 0;
2871}
2872
2873static int if_config_write(struct vty *vty)
2874{
2875 struct vrf *vrf;
d62a17ae 2876 struct interface *ifp;
2877
2878 zebra_ptm_write(vty);
2879
a2addae8 2880 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name)
451fda4f 2881 FOR_ALL_INTERFACES (vrf, ifp) {
a2addae8
RW
2882 struct zebra_if *if_data;
2883 struct listnode *addrnode;
2884 struct connected *ifc;
2885 struct prefix *p;
2886 struct vrf *vrf;
d62a17ae 2887
a2addae8
RW
2888 if_data = ifp->info;
2889 vrf = vrf_lookup_by_id(ifp->vrf_id);
d62a17ae 2890
a2addae8
RW
2891 if (ifp->vrf_id == VRF_DEFAULT)
2892 vty_frame(vty, "interface %s\n", ifp->name);
2893 else
2894 vty_frame(vty, "interface %s vrf %s\n",
2895 ifp->name, vrf->name);
d62a17ae 2896
a2addae8
RW
2897 if (if_data) {
2898 if (if_data->shutdown == IF_ZEBRA_SHUTDOWN_ON)
2899 vty_out(vty, " shutdown\n");
d62a17ae 2900
a2addae8
RW
2901 zebra_ptm_if_write(vty, if_data);
2902 }
bfac8dcd 2903
a2addae8
RW
2904 if (ifp->desc)
2905 vty_out(vty, " description %s\n", ifp->desc);
2906
2907 /* Assign bandwidth here to avoid unnecessary interface
2908 flap
2909 while processing config script */
2910 if (ifp->bandwidth != 0)
2911 vty_out(vty, " bandwidth %u\n", ifp->bandwidth);
2912
2913 if (!CHECK_FLAG(ifp->status,
2914 ZEBRA_INTERFACE_LINKDETECTION))
2915 vty_out(vty, " no link-detect\n");
2916
2917 for (ALL_LIST_ELEMENTS_RO(ifp->connected, addrnode,
2918 ifc)) {
2919 if (CHECK_FLAG(ifc->conf,
2920 ZEBRA_IFC_CONFIGURED)) {
2921 char buf[INET6_ADDRSTRLEN];
2922 p = ifc->address;
2923 vty_out(vty, " ip%s address %s",
2924 p->family == AF_INET ? ""
2925 : "v6",
a07df329 2926 inet_ntop(p->family,
60466a63
QY
2927 &p->u.prefix, buf,
2928 sizeof(buf)));
a2addae8
RW
2929 if (CONNECTED_PEER(ifc)) {
2930 p = ifc->destination;
2931 vty_out(vty, " peer %s",
2932 inet_ntop(p->family,
2933 &p->u.prefix,
2934 buf,
2935 sizeof(buf)));
2936 }
2937 vty_out(vty, "/%d", p->prefixlen);
718e3744 2938
a2addae8
RW
2939 if (ifc->label)
2940 vty_out(vty, " label %s",
2941 ifc->label);
718e3744 2942
a2addae8
RW
2943 vty_out(vty, "\n");
2944 }
d62a17ae 2945 }
718e3744 2946
a2addae8
RW
2947 if (if_data) {
2948 if (if_data->multicast
2949 != IF_ZEBRA_MULTICAST_UNSPEC)
2950 vty_out(vty, " %smulticast\n",
2951 if_data->multicast
2952 == IF_ZEBRA_MULTICAST_ON
2953 ? ""
2954 : "no ");
2955 }
718e3744 2956
a2addae8 2957 hook_call(zebra_if_config_wr, vty, ifp);
ca776988 2958
a2addae8 2959 link_params_config_write(vty, ifp);
16f1b9ee 2960
a2addae8
RW
2961 vty_endframe(vty, "!\n");
2962 }
d62a17ae 2963 return 0;
718e3744 2964}
2965
2966/* Allocate and initialize interface vector. */
d62a17ae 2967void zebra_if_init(void)
2968{
2969 /* Initialize interface and new hook. */
ce19a04a
DL
2970 hook_register_prio(if_add, 0, if_zebra_new_hook);
2971 hook_register_prio(if_del, 0, if_zebra_delete_hook);
d62a17ae 2972
2973 /* Install configuration write function. */
2974 install_node(&interface_node, if_config_write);
2975 install_node(&link_params_node, NULL);
2976 if_cmd_init();
2977
2978 install_element(VIEW_NODE, &show_interface_cmd);
2979 install_element(VIEW_NODE, &show_interface_vrf_all_cmd);
2980 install_element(VIEW_NODE, &show_interface_name_vrf_cmd);
2981 install_element(VIEW_NODE, &show_interface_name_vrf_all_cmd);
2982
2983 install_element(ENABLE_NODE, &show_interface_desc_cmd);
2984 install_element(ENABLE_NODE, &show_interface_desc_vrf_all_cmd);
2985 install_element(INTERFACE_NODE, &multicast_cmd);
2986 install_element(INTERFACE_NODE, &no_multicast_cmd);
2987 install_element(INTERFACE_NODE, &linkdetect_cmd);
2988 install_element(INTERFACE_NODE, &no_linkdetect_cmd);
2989 install_element(INTERFACE_NODE, &shutdown_if_cmd);
2990 install_element(INTERFACE_NODE, &no_shutdown_if_cmd);
2991 install_element(INTERFACE_NODE, &bandwidth_if_cmd);
2992 install_element(INTERFACE_NODE, &no_bandwidth_if_cmd);
2993 install_element(INTERFACE_NODE, &ip_address_cmd);
2994 install_element(INTERFACE_NODE, &no_ip_address_cmd);
a07df329
DL
2995 install_element(INTERFACE_NODE, &ip_address_peer_cmd);
2996 install_element(INTERFACE_NODE, &no_ip_address_peer_cmd);
d62a17ae 2997 install_element(INTERFACE_NODE, &ipv6_address_cmd);
2998 install_element(INTERFACE_NODE, &no_ipv6_address_cmd);
718e3744 2999#ifdef HAVE_NETLINK
d62a17ae 3000 install_element(INTERFACE_NODE, &ip_address_label_cmd);
3001 install_element(INTERFACE_NODE, &no_ip_address_label_cmd);
718e3744 3002#endif /* HAVE_NETLINK */
d62a17ae 3003 install_element(INTERFACE_NODE, &link_params_cmd);
3004 install_default(LINK_PARAMS_NODE);
3005 install_element(LINK_PARAMS_NODE, &link_params_enable_cmd);
3006 install_element(LINK_PARAMS_NODE, &no_link_params_enable_cmd);
3007 install_element(LINK_PARAMS_NODE, &link_params_metric_cmd);
3008 install_element(LINK_PARAMS_NODE, &no_link_params_metric_cmd);
3009 install_element(LINK_PARAMS_NODE, &link_params_maxbw_cmd);
3010 install_element(LINK_PARAMS_NODE, &link_params_max_rsv_bw_cmd);
3011 install_element(LINK_PARAMS_NODE, &link_params_unrsv_bw_cmd);
3012 install_element(LINK_PARAMS_NODE, &link_params_admin_grp_cmd);
3013 install_element(LINK_PARAMS_NODE, &no_link_params_admin_grp_cmd);
3014 install_element(LINK_PARAMS_NODE, &link_params_inter_as_cmd);
3015 install_element(LINK_PARAMS_NODE, &no_link_params_inter_as_cmd);
3016 install_element(LINK_PARAMS_NODE, &link_params_delay_cmd);
3017 install_element(LINK_PARAMS_NODE, &no_link_params_delay_cmd);
3018 install_element(LINK_PARAMS_NODE, &link_params_delay_var_cmd);
3019 install_element(LINK_PARAMS_NODE, &no_link_params_delay_var_cmd);
3020 install_element(LINK_PARAMS_NODE, &link_params_pkt_loss_cmd);
3021 install_element(LINK_PARAMS_NODE, &no_link_params_pkt_loss_cmd);
3022 install_element(LINK_PARAMS_NODE, &link_params_ava_bw_cmd);
3023 install_element(LINK_PARAMS_NODE, &no_link_params_ava_bw_cmd);
3024 install_element(LINK_PARAMS_NODE, &link_params_res_bw_cmd);
3025 install_element(LINK_PARAMS_NODE, &no_link_params_res_bw_cmd);
3026 install_element(LINK_PARAMS_NODE, &link_params_use_bw_cmd);
3027 install_element(LINK_PARAMS_NODE, &no_link_params_use_bw_cmd);
3028 install_element(LINK_PARAMS_NODE, &exit_link_params_cmd);
718e3744 3029}