]> git.proxmox.com Git - mirror_frr.git/blame - zebra/interface.c
Merge pull request #1904 from qlyoung/docuser
[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;
870
871 zif = ifp->info;
872 zif->up_count++;
873 quagga_timestamp(2, zif->up_last, sizeof(zif->up_last));
874
875 /* Notify the protocol daemons. */
876 if (ifp->ptm_enable && (ifp->ptm_status == ZEBRA_PTM_STATUS_DOWN)) {
877 zlog_warn("%s: interface %s hasn't passed ptm check\n",
878 __func__, ifp->name);
879 return;
880 }
881 zebra_interface_up_update(ifp);
882
883 if_nbr_ipv6ll_to_ipv4ll_neigh_add_all(ifp);
884
885#if defined(HAVE_RTADV)
886 /* Enable fast tx of RA if enabled && RA interval is not in msecs */
887 if (zif->rtadv.AdvSendAdvertisements
888 && (zif->rtadv.MaxRtrAdvInterval >= 1000)) {
889 zif->rtadv.inFastRexmit = 1;
890 zif->rtadv.NumFastReXmitsRemain = RTADV_NUM_FAST_REXMITS;
891 }
9c3bf1ce 892#endif
6c9678b4 893
d62a17ae 894 /* Install connected routes to the kernel. */
895 if_install_connected(ifp);
896
897 if (IS_ZEBRA_DEBUG_RIB_DETAILED)
898 zlog_debug("%u: IF %s up, scheduling RIB processing",
899 ifp->vrf_id, ifp->name);
900 rib_update(ifp->vrf_id, RIB_UPDATE_IF_CHANGE);
901
d62a17ae 902 /* Handle interface up for specific types for EVPN. Non-VxLAN interfaces
903 * are checked to see if (remote) neighbor entries need to be installed
904 * on them for ARP suppression.
905 */
906 if (IS_ZEBRA_IF_VXLAN(ifp))
907 zebra_vxlan_if_up(ifp);
908 else if (IS_ZEBRA_IF_BRIDGE(ifp)) {
909 link_if = ifp;
910 zebra_vxlan_svi_up(ifp, link_if);
911 } else if (IS_ZEBRA_IF_VLAN(ifp)) {
71349e03
MK
912 link_if = if_lookup_by_index_per_ns(zebra_ns_lookup(NS_DEFAULT),
913 zif->link_ifindex);
d62a17ae 914 if (link_if)
915 zebra_vxlan_svi_up(ifp, link_if);
916 }
718e3744 917}
918
919/* Interface goes down. We have to manage different behavior of based
920 OS. */
d62a17ae 921void if_down(struct interface *ifp)
922{
923 struct zebra_if *zif;
924 struct interface *link_if;
925
926 zif = ifp->info;
927 zif->down_count++;
928 quagga_timestamp(2, zif->down_last, sizeof(zif->down_last));
929
930 /* Handle interface down for specific types for EVPN. Non-VxLAN
931 * interfaces
932 * are checked to see if (remote) neighbor entries need to be purged
933 * for ARP suppression.
934 */
935 if (IS_ZEBRA_IF_VXLAN(ifp))
936 zebra_vxlan_if_down(ifp);
937 else if (IS_ZEBRA_IF_BRIDGE(ifp)) {
938 link_if = ifp;
939 zebra_vxlan_svi_down(ifp, link_if);
940 } else if (IS_ZEBRA_IF_VLAN(ifp)) {
71349e03
MK
941 link_if = if_lookup_by_index_per_ns(zebra_ns_lookup(NS_DEFAULT),
942 zif->link_ifindex);
d62a17ae 943 if (link_if)
944 zebra_vxlan_svi_down(ifp, link_if);
945 }
2232a77c 946
13d60d35 947
d62a17ae 948 /* Notify to the protocol daemons. */
949 zebra_interface_down_update(ifp);
718e3744 950
d62a17ae 951 /* Uninstall connected routes from the kernel. */
952 if_uninstall_connected(ifp);
718e3744 953
d62a17ae 954 if (IS_ZEBRA_DEBUG_RIB_DETAILED)
955 zlog_debug("%u: IF %s down, scheduling RIB processing",
956 ifp->vrf_id, ifp->name);
957 rib_update(ifp->vrf_id, RIB_UPDATE_IF_CHANGE);
5c610faf 958
d62a17ae 959 if_nbr_ipv6ll_to_ipv4ll_neigh_del_all(ifp);
a197c47c 960
d62a17ae 961 /* Delete all neighbor addresses learnt through IPv6 RA */
962 if_down_del_nbr_connected(ifp);
718e3744 963}
964
d62a17ae 965void if_refresh(struct interface *ifp)
718e3744 966{
d62a17ae 967 if_get_flags(ifp);
718e3744 968}
969
d62a17ae 970void zebra_if_update_link(struct interface *ifp, ifindex_t link_ifindex)
6675513d 971{
d62a17ae 972 struct zebra_if *zif;
6675513d 973
d62a17ae 974 zif = (struct zebra_if *)ifp->info;
975 zif->link_ifindex = link_ifindex;
976 zif->link = if_lookup_by_index_per_ns(zebra_ns_lookup(NS_DEFAULT),
977 link_ifindex);
6675513d 978}
979
d5a5c8f0 980
718e3744 981/* Output prefix string to vty. */
d62a17ae 982static int prefix_vty_out(struct vty *vty, struct prefix *p)
718e3744 983{
d62a17ae 984 char str[INET6_ADDRSTRLEN];
718e3744 985
d62a17ae 986 inet_ntop(p->family, &p->u.prefix, str, sizeof(str));
987 vty_out(vty, "%s", str);
988 return strlen(str);
718e3744 989}
990
991/* Dump if address information to vty. */
d62a17ae 992static void connected_dump_vty(struct vty *vty, struct connected *connected)
718e3744 993{
d62a17ae 994 struct prefix *p;
718e3744 995
d62a17ae 996 /* Print interface address. */
997 p = connected->address;
998 vty_out(vty, " %s ", prefix_family_str(p));
999 prefix_vty_out(vty, p);
1000 vty_out(vty, "/%d", p->prefixlen);
718e3744 1001
d62a17ae 1002 /* If there is destination address, print it. */
1003 if (connected->destination) {
1004 vty_out(vty,
1005 (CONNECTED_PEER(connected) ? " peer " : " broadcast "));
1006 prefix_vty_out(vty, connected->destination);
abffde07
DL
1007 if (CONNECTED_PEER(connected))
1008 vty_out(vty, "/%d", connected->destination->prefixlen);
d62a17ae 1009 }
718e3744 1010
d62a17ae 1011 if (CHECK_FLAG(connected->flags, ZEBRA_IFA_SECONDARY))
1012 vty_out(vty, " secondary");
718e3744 1013
d62a17ae 1014 if (CHECK_FLAG(connected->flags, ZEBRA_IFA_UNNUMBERED))
1015 vty_out(vty, " unnumbered");
525c1839 1016
d62a17ae 1017 if (connected->label)
1018 vty_out(vty, " %s", connected->label);
718e3744 1019
d62a17ae 1020 vty_out(vty, "\n");
718e3744 1021}
1022
a80beece 1023/* Dump interface neighbor address information to vty. */
d62a17ae 1024static void nbr_connected_dump_vty(struct vty *vty,
1025 struct nbr_connected *connected)
a80beece 1026{
d62a17ae 1027 struct prefix *p;
a80beece 1028
d62a17ae 1029 /* Print interface address. */
1030 p = connected->address;
1031 vty_out(vty, " %s ", prefix_family_str(p));
1032 prefix_vty_out(vty, p);
1033 vty_out(vty, "/%d", p->prefixlen);
a80beece 1034
d62a17ae 1035 vty_out(vty, "\n");
a80beece
DS
1036}
1037
d62a17ae 1038static const char *zebra_ziftype_2str(zebra_iftype_t zif_type)
6675513d 1039{
d62a17ae 1040 switch (zif_type) {
1041 case ZEBRA_IF_OTHER:
1042 return "Other";
1043 break;
6675513d 1044
d62a17ae 1045 case ZEBRA_IF_BRIDGE:
1046 return "Bridge";
1047 break;
6675513d 1048
d62a17ae 1049 case ZEBRA_IF_VLAN:
1050 return "Vlan";
1051 break;
6675513d 1052
d62a17ae 1053 case ZEBRA_IF_VXLAN:
1054 return "Vxlan";
1055 break;
6675513d 1056
d62a17ae 1057 case ZEBRA_IF_VRF:
1058 return "VRF";
1059 break;
6675513d 1060
d62a17ae 1061 default:
1062 return "Unknown";
1063 break;
1064 }
6675513d 1065}
1066
718e3744 1067/* Interface's information print out to vty interface. */
d62a17ae 1068static void if_dump_vty(struct vty *vty, struct interface *ifp)
1069{
1070 struct connected *connected;
1071 struct nbr_connected *nbr_connected;
1072 struct listnode *node;
1073 struct route_node *rn;
1074 struct zebra_if *zebra_if;
1075 struct vrf *vrf;
1076
1077 zebra_if = ifp->info;
1078
1079 vty_out(vty, "Interface %s is ", ifp->name);
1080 if (if_is_up(ifp)) {
1081 vty_out(vty, "up, line protocol ");
1082
1083 if (CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_LINKDETECTION)) {
1084 if (if_is_running(ifp))
1085 vty_out(vty, "is up\n");
1086 else
1087 vty_out(vty, "is down\n");
1088 } else {
1089 vty_out(vty, "detection is disabled\n");
1090 }
1091 } else {
1092 vty_out(vty, "down\n");
1093 }
1094
1095 vty_out(vty, " Link ups: %5u last: %s\n", zebra_if->up_count,
1096 zebra_if->up_last[0] ? zebra_if->up_last : "(never)");
1097 vty_out(vty, " Link downs: %5u last: %s\n", zebra_if->down_count,
1098 zebra_if->down_last[0] ? zebra_if->down_last : "(never)");
1099
1100 zebra_ptm_show_status(vty, ifp);
1101
1102 vrf = vrf_lookup_by_id(ifp->vrf_id);
1103 vty_out(vty, " vrf: %s\n", vrf->name);
1104
1105 if (ifp->desc)
1106 vty_out(vty, " Description: %s\n", ifp->desc);
1107 if (ifp->ifindex == IFINDEX_INTERNAL) {
1108 vty_out(vty, " pseudo interface\n");
1109 return;
1110 } else if (!CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE)) {
1111 vty_out(vty, " index %d inactive interface\n", ifp->ifindex);
1112 return;
1113 }
1114
1115 vty_out(vty, " index %d metric %d mtu %d speed %u ", ifp->ifindex,
1116 ifp->metric, ifp->mtu, ifp->speed);
1117 if (ifp->mtu6 != ifp->mtu)
1118 vty_out(vty, "mtu6 %d ", ifp->mtu6);
1119 vty_out(vty, "\n flags: %s\n", if_flag_dump(ifp->flags));
1120
1121 /* Hardware address. */
1122 vty_out(vty, " Type: %s\n", if_link_type_str(ifp->ll_type));
1123 if (ifp->hw_addr_len != 0) {
1124 int i;
1125
1126 vty_out(vty, " HWaddr: ");
1127 for (i = 0; i < ifp->hw_addr_len; i++)
1128 vty_out(vty, "%s%02x", i == 0 ? "" : ":",
1129 ifp->hw_addr[i]);
1130 vty_out(vty, "\n");
1131 }
1132
1133 /* Bandwidth in Mbps */
1134 if (ifp->bandwidth != 0) {
1135 vty_out(vty, " bandwidth %u Mbps", ifp->bandwidth);
1136 vty_out(vty, "\n");
1137 }
1138
1139 for (rn = route_top(zebra_if->ipv4_subnets); rn; rn = route_next(rn)) {
1140 if (!rn->info)
1141 continue;
1142
1143 for (ALL_LIST_ELEMENTS_RO((struct list *)rn->info, node,
1144 connected))
1145 connected_dump_vty(vty, connected);
1146 }
1147
1148 for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, connected)) {
1149 if (CHECK_FLAG(connected->conf, ZEBRA_IFC_REAL)
1150 && (connected->address->family == AF_INET6))
1151 connected_dump_vty(vty, connected);
1152 }
1153
1154 vty_out(vty, " Interface Type %s\n",
1155 zebra_ziftype_2str(zebra_if->zif_type));
1156 if (IS_ZEBRA_IF_BRIDGE(ifp)) {
1157 struct zebra_l2info_bridge *bridge_info;
1158
1159 bridge_info = &zebra_if->l2info.br;
1160 vty_out(vty, " Bridge VLAN-aware: %s\n",
1161 bridge_info->vlan_aware ? "yes" : "no");
1162 } else if (IS_ZEBRA_IF_VLAN(ifp)) {
1163 struct zebra_l2info_vlan *vlan_info;
1164
1165 vlan_info = &zebra_if->l2info.vl;
1166 vty_out(vty, " VLAN Id %u\n", vlan_info->vid);
1167 } else if (IS_ZEBRA_IF_VXLAN(ifp)) {
1168 struct zebra_l2info_vxlan *vxlan_info;
1169
1170 vxlan_info = &zebra_if->l2info.vxl;
1171 vty_out(vty, " VxLAN Id %u", vxlan_info->vni);
1172 if (vxlan_info->vtep_ip.s_addr != INADDR_ANY)
1173 vty_out(vty, " VTEP IP: %s",
1174 inet_ntoa(vxlan_info->vtep_ip));
1175 if (vxlan_info->access_vlan)
1176 vty_out(vty, " Access VLAN Id %u",
1177 vxlan_info->access_vlan);
1178 vty_out(vty, "\n");
1179 }
1180
1181 if (IS_ZEBRA_IF_BRIDGE_SLAVE(ifp)) {
1182 struct zebra_l2info_brslave *br_slave;
1183
1184 br_slave = &zebra_if->brslave_info;
1185 if (br_slave->bridge_ifindex != IFINDEX_INTERNAL)
1186 vty_out(vty, " Master (bridge) ifindex %u\n",
1187 br_slave->bridge_ifindex);
1188 }
1189
1190 if (zebra_if->link_ifindex != IFINDEX_INTERNAL)
1191 vty_out(vty, " Link ifindex %u\n", zebra_if->link_ifindex);
1192
1193 if (HAS_LINK_PARAMS(ifp)) {
1194 int i;
1195 struct if_link_params *iflp = ifp->link_params;
1196 vty_out(vty, " Traffic Engineering Link Parameters:\n");
1197 if (IS_PARAM_SET(iflp, LP_TE_METRIC))
1198 vty_out(vty, " TE metric %u\n", iflp->te_metric);
1199 if (IS_PARAM_SET(iflp, LP_MAX_BW))
1200 vty_out(vty, " Maximum Bandwidth %g (Byte/s)\n",
1201 iflp->max_bw);
1202 if (IS_PARAM_SET(iflp, LP_MAX_RSV_BW))
1203 vty_out(vty,
1204 " Maximum Reservable Bandwidth %g (Byte/s)\n",
1205 iflp->max_rsv_bw);
1206 if (IS_PARAM_SET(iflp, LP_UNRSV_BW)) {
1207 vty_out(vty,
1208 " Unreserved Bandwidth per Class Type in Byte/s:\n");
1209 for (i = 0; i < MAX_CLASS_TYPE; i += 2)
1210 vty_out(vty,
1211 " [%d]: %g (Bytes/sec),\t[%d]: %g (Bytes/sec)\n",
1212 i, iflp->unrsv_bw[i], i + 1,
1213 iflp->unrsv_bw[i + 1]);
1214 }
1215
1216 if (IS_PARAM_SET(iflp, LP_ADM_GRP))
1217 vty_out(vty, " Administrative Group:%u\n",
1218 iflp->admin_grp);
1219 if (IS_PARAM_SET(iflp, LP_DELAY)) {
1220 vty_out(vty, " Link Delay Average: %u (micro-sec.)",
1221 iflp->av_delay);
1222 if (IS_PARAM_SET(iflp, LP_MM_DELAY)) {
1223 vty_out(vty, " Min: %u (micro-sec.)",
1224 iflp->min_delay);
1225 vty_out(vty, " Max: %u (micro-sec.)",
1226 iflp->max_delay);
1227 }
1228 vty_out(vty, "\n");
1229 }
1230 if (IS_PARAM_SET(iflp, LP_DELAY_VAR))
1231 vty_out(vty,
1232 " Link Delay Variation %u (micro-sec.)\n",
1233 iflp->delay_var);
1234 if (IS_PARAM_SET(iflp, LP_PKT_LOSS))
1235 vty_out(vty, " Link Packet Loss %g (in %%)\n",
1236 iflp->pkt_loss);
1237 if (IS_PARAM_SET(iflp, LP_AVA_BW))
1238 vty_out(vty, " Available Bandwidth %g (Byte/s)\n",
1239 iflp->ava_bw);
1240 if (IS_PARAM_SET(iflp, LP_RES_BW))
1241 vty_out(vty, " Residual Bandwidth %g (Byte/s)\n",
1242 iflp->res_bw);
1243 if (IS_PARAM_SET(iflp, LP_USE_BW))
1244 vty_out(vty, " Utilized Bandwidth %g (Byte/s)\n",
1245 iflp->use_bw);
1246 if (IS_PARAM_SET(iflp, LP_RMT_AS))
1247 vty_out(vty, " Neighbor ASBR IP: %s AS: %u \n",
1248 inet_ntoa(iflp->rmt_ip), iflp->rmt_as);
1249 }
1250
2eb27eec
DL
1251 hook_call(zebra_if_extra_info, vty, ifp);
1252
d62a17ae 1253 if (listhead(ifp->nbr_connected))
1254 vty_out(vty, " Neighbor address(s):\n");
1255 for (ALL_LIST_ELEMENTS_RO(ifp->nbr_connected, node, nbr_connected))
1256 nbr_connected_dump_vty(vty, nbr_connected);
718e3744 1257
1258#ifdef HAVE_PROC_NET_DEV
d62a17ae 1259 /* Statistics print out using proc file system. */
1260 vty_out(vty,
1261 " %lu input packets (%lu multicast), %lu bytes, "
1262 "%lu dropped\n",
1263 ifp->stats.rx_packets, ifp->stats.rx_multicast,
1264 ifp->stats.rx_bytes, ifp->stats.rx_dropped);
1265
1266 vty_out(vty,
1267 " %lu input errors, %lu length, %lu overrun,"
1268 " %lu CRC, %lu frame\n",
1269 ifp->stats.rx_errors, ifp->stats.rx_length_errors,
1270 ifp->stats.rx_over_errors, ifp->stats.rx_crc_errors,
1271 ifp->stats.rx_frame_errors);
1272
1273 vty_out(vty, " %lu fifo, %lu missed\n", ifp->stats.rx_fifo_errors,
1274 ifp->stats.rx_missed_errors);
1275
1276 vty_out(vty, " %lu output packets, %lu bytes, %lu dropped\n",
1277 ifp->stats.tx_packets, ifp->stats.tx_bytes,
1278 ifp->stats.tx_dropped);
1279
1280 vty_out(vty,
1281 " %lu output errors, %lu aborted, %lu carrier,"
1282 " %lu fifo, %lu heartbeat\n",
1283 ifp->stats.tx_errors, ifp->stats.tx_aborted_errors,
1284 ifp->stats.tx_carrier_errors, ifp->stats.tx_fifo_errors,
1285 ifp->stats.tx_heartbeat_errors);
1286
1287 vty_out(vty, " %lu window, %lu collisions\n",
1288 ifp->stats.tx_window_errors, ifp->stats.collisions);
718e3744 1289#endif /* HAVE_PROC_NET_DEV */
1290
1291#ifdef HAVE_NET_RT_IFLIST
d62a17ae 1292#if defined(__bsdi__) || defined(__NetBSD__)
1293 /* Statistics print out using sysctl (). */
1294 vty_out(vty,
1295 " input packets %llu, bytes %llu, dropped %llu,"
1296 " multicast packets %llu\n",
1297 (unsigned long long)ifp->stats.ifi_ipackets,
1298 (unsigned long long)ifp->stats.ifi_ibytes,
1299 (unsigned long long)ifp->stats.ifi_iqdrops,
1300 (unsigned long long)ifp->stats.ifi_imcasts);
1301
1302 vty_out(vty, " input errors %llu\n",
1303 (unsigned long long)ifp->stats.ifi_ierrors);
1304
1305 vty_out(vty,
1306 " output packets %llu, bytes %llu,"
1307 " multicast packets %llu\n",
1308 (unsigned long long)ifp->stats.ifi_opackets,
1309 (unsigned long long)ifp->stats.ifi_obytes,
1310 (unsigned long long)ifp->stats.ifi_omcasts);
1311
1312 vty_out(vty, " output errors %llu\n",
1313 (unsigned long long)ifp->stats.ifi_oerrors);
1314
1315 vty_out(vty, " collisions %llu\n",
1316 (unsigned long long)ifp->stats.ifi_collisions);
718e3744 1317#else
d62a17ae 1318 /* Statistics print out using sysctl (). */
1319 vty_out(vty,
1320 " input packets %lu, bytes %lu, dropped %lu,"
1321 " multicast packets %lu\n",
1322 ifp->stats.ifi_ipackets, ifp->stats.ifi_ibytes,
1323 ifp->stats.ifi_iqdrops, ifp->stats.ifi_imcasts);
718e3744 1324
d62a17ae 1325 vty_out(vty, " input errors %lu\n", ifp->stats.ifi_ierrors);
718e3744 1326
d62a17ae 1327 vty_out(vty,
1328 " output packets %lu, bytes %lu, multicast packets %lu\n",
1329 ifp->stats.ifi_opackets, ifp->stats.ifi_obytes,
1330 ifp->stats.ifi_omcasts);
718e3744 1331
d62a17ae 1332 vty_out(vty, " output errors %lu\n", ifp->stats.ifi_oerrors);
718e3744 1333
d62a17ae 1334 vty_out(vty, " collisions %lu\n", ifp->stats.ifi_collisions);
718e3744 1335#endif /* __bsdi__ || __NetBSD__ */
1336#endif /* HAVE_NET_RT_IFLIST */
1337}
1338
d62a17ae 1339static void interface_update_stats(void)
78860b9f
DS
1340{
1341#ifdef HAVE_PROC_NET_DEV
d62a17ae 1342 /* If system has interface statistics via proc file system, update
1343 statistics. */
1344 ifstat_update_proc();
78860b9f
DS
1345#endif /* HAVE_PROC_NET_DEV */
1346#ifdef HAVE_NET_RT_IFLIST
d62a17ae 1347 ifstat_update_sysctl();
78860b9f
DS
1348#endif /* HAVE_NET_RT_IFLIST */
1349}
1350
d62a17ae 1351struct cmd_node interface_node = {INTERFACE_NODE, "%s(config-if)# ", 1};
718e3744 1352
8b87bdf4 1353/* Show all interfaces to vty. */
8b3f0677
DW
1354DEFUN (show_interface,
1355 show_interface_cmd,
b62ecea5 1356 "show interface [vrf NAME]",
8b87bdf4 1357 SHOW_STR
b62ecea5
QY
1358 "Interface status and configuration\n"
1359 VRF_CMD_HELP_STR)
8b87bdf4 1360{
f4e14fdb 1361 struct vrf *vrf;
d62a17ae 1362 struct interface *ifp;
1363 vrf_id_t vrf_id = VRF_DEFAULT;
8b87bdf4 1364
d62a17ae 1365 interface_update_stats();
8b87bdf4 1366
d62a17ae 1367 if (argc > 2)
1368 VRF_GET_ID(vrf_id, argv[3]->arg);
8b87bdf4 1369
d62a17ae 1370 /* All interface print. */
f4e14fdb 1371 vrf = vrf_lookup_by_id(vrf_id);
451fda4f 1372 FOR_ALL_INTERFACES (vrf, ifp)
d62a17ae 1373 if_dump_vty(vty, ifp);
8b87bdf4 1374
d62a17ae 1375 return CMD_SUCCESS;
8b87bdf4
FL
1376}
1377
8b87bdf4
FL
1378
1379/* Show all interfaces to vty. */
8b3f0677
DW
1380DEFUN (show_interface_vrf_all,
1381 show_interface_vrf_all_cmd,
9ccf14f7 1382 "show interface vrf all",
8b87bdf4
FL
1383 SHOW_STR
1384 "Interface status and configuration\n"
1385 VRF_ALL_CMD_HELP_STR)
718e3744 1386{
d62a17ae 1387 struct vrf *vrf;
d62a17ae 1388 struct interface *ifp;
8b87bdf4 1389
d62a17ae 1390 interface_update_stats();
718e3744 1391
d62a17ae 1392 /* All interface print. */
a2addae8 1393 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name)
451fda4f 1394 FOR_ALL_INTERFACES (vrf, ifp)
a2addae8 1395 if_dump_vty(vty, ifp);
8b87bdf4 1396
d62a17ae 1397 return CMD_SUCCESS;
8b87bdf4
FL
1398}
1399
1400/* Show specified interface to vty. */
1721646e
DS
1401
1402DEFUN (show_interface_name_vrf,
1403 show_interface_name_vrf_cmd,
9ccf14f7 1404 "show interface IFNAME vrf NAME",
8b87bdf4
FL
1405 SHOW_STR
1406 "Interface status and configuration\n"
1721646e
DS
1407 "Interface name\n"
1408 VRF_CMD_HELP_STR)
8b87bdf4 1409{
d62a17ae 1410 int idx_ifname = 2;
1411 int idx_name = 4;
1412 struct interface *ifp;
0439cb9d 1413 vrf_id_t vrf_id;
8b87bdf4 1414
d62a17ae 1415 interface_update_stats();
8b87bdf4 1416
d62a17ae 1417 VRF_GET_ID(vrf_id, argv[idx_name]->arg);
8b87bdf4 1418
d62a17ae 1419 /* Specified interface print. */
1420 ifp = if_lookup_by_name(argv[idx_ifname]->arg, vrf_id);
1421 if (ifp == NULL) {
1422 vty_out(vty, "%% Can't find interface %s\n",
1423 argv[idx_ifname]->arg);
1424 return CMD_WARNING;
1425 }
1426 if_dump_vty(vty, ifp);
718e3744 1427
d62a17ae 1428 return CMD_SUCCESS;
718e3744 1429}
1430
8b87bdf4 1431/* Show specified interface to vty. */
8b3f0677
DW
1432DEFUN (show_interface_name_vrf_all,
1433 show_interface_name_vrf_all_cmd,
b62ecea5 1434 "show interface IFNAME [vrf all]",
8b87bdf4
FL
1435 SHOW_STR
1436 "Interface status and configuration\n"
1721646e 1437 "Interface name\n"
8b87bdf4
FL
1438 VRF_ALL_CMD_HELP_STR)
1439{
d62a17ae 1440 int idx_ifname = 2;
1441 struct vrf *vrf;
1442 struct interface *ifp;
1443 int found = 0;
8b87bdf4 1444
d62a17ae 1445 interface_update_stats();
8b87bdf4 1446
d62a17ae 1447 /* All interface print. */
a2addae8 1448 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
d62a17ae 1449 /* Specified interface print. */
1450 ifp = if_lookup_by_name(argv[idx_ifname]->arg, vrf->vrf_id);
1451 if (ifp) {
1452 if_dump_vty(vty, ifp);
1453 found++;
1454 }
1455 }
8b87bdf4 1456
d62a17ae 1457 if (!found) {
1458 vty_out(vty, "%% Can't find interface %s\n",
1459 argv[idx_ifname]->arg);
1460 return CMD_WARNING;
1461 }
8b87bdf4 1462
d62a17ae 1463 return CMD_SUCCESS;
8b87bdf4
FL
1464}
1465
1721646e 1466
d62a17ae 1467static void if_show_description(struct vty *vty, vrf_id_t vrf_id)
ed9bb6d5 1468{
f4e14fdb 1469 struct vrf *vrf = vrf_lookup_by_id(vrf_id);
d62a17ae 1470 struct interface *ifp;
ed9bb6d5 1471
d62a17ae 1472 vty_out(vty, "Interface Status Protocol Description\n");
451fda4f 1473 FOR_ALL_INTERFACES (vrf, ifp) {
d62a17ae 1474 int len;
ed9bb6d5 1475
d62a17ae 1476 len = vty_out(vty, "%s", ifp->name);
1477 vty_out(vty, "%*s", (16 - len), " ");
1478
1479 if (if_is_up(ifp)) {
1480 vty_out(vty, "up ");
1481 if (CHECK_FLAG(ifp->status,
1482 ZEBRA_INTERFACE_LINKDETECTION)) {
1483 if (if_is_running(ifp))
1484 vty_out(vty, "up ");
1485 else
1486 vty_out(vty, "down ");
1487 } else {
1488 vty_out(vty, "unknown ");
1489 }
1490 } else {
1491 vty_out(vty, "down down ");
1492 }
ed9bb6d5 1493
d62a17ae 1494 if (ifp->desc)
1495 vty_out(vty, "%s", ifp->desc);
1496 vty_out(vty, "\n");
1497 }
8b87bdf4
FL
1498}
1499
1500DEFUN (show_interface_desc,
1501 show_interface_desc_cmd,
b62ecea5 1502 "show interface description [vrf NAME]",
8b87bdf4
FL
1503 SHOW_STR
1504 "Interface status and configuration\n"
b62ecea5
QY
1505 "Interface description\n"
1506 VRF_CMD_HELP_STR)
8b87bdf4 1507{
d62a17ae 1508 vrf_id_t vrf_id = VRF_DEFAULT;
8b87bdf4 1509
d62a17ae 1510 if (argc > 3)
1511 VRF_GET_ID(vrf_id, argv[4]->arg);
8b87bdf4 1512
d62a17ae 1513 if_show_description(vty, vrf_id);
8b87bdf4 1514
d62a17ae 1515 return CMD_SUCCESS;
8b87bdf4
FL
1516}
1517
8b87bdf4
FL
1518
1519DEFUN (show_interface_desc_vrf_all,
1520 show_interface_desc_vrf_all_cmd,
9ccf14f7 1521 "show interface description vrf all",
8b87bdf4
FL
1522 SHOW_STR
1523 "Interface status and configuration\n"
1524 "Interface description\n"
1525 VRF_ALL_CMD_HELP_STR)
1526{
d62a17ae 1527 struct vrf *vrf;
8b87bdf4 1528
a2addae8 1529 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name)
996c9314 1530 if (!RB_EMPTY(if_name_head, &vrf->ifaces_by_name)) {
a2addae8
RW
1531 vty_out(vty, "\n\tVRF %u\n\n", vrf->vrf_id);
1532 if_show_description(vty, vrf->vrf_id);
1533 }
8b87bdf4 1534
d62a17ae 1535 return CMD_SUCCESS;
ed9bb6d5 1536}
1537
718e3744 1538DEFUN (multicast,
1539 multicast_cmd,
1540 "multicast",
1541 "Set multicast flag to interface\n")
1542{
d62a17ae 1543 VTY_DECLVAR_CONTEXT(interface, ifp);
1544 int ret;
1545 struct zebra_if *if_data;
718e3744 1546
d62a17ae 1547 if (CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE)) {
1548 ret = if_set_flags(ifp, IFF_MULTICAST);
1549 if (ret < 0) {
1550 vty_out(vty, "Can't set multicast flag\n");
1551 return CMD_WARNING_CONFIG_FAILED;
1552 }
1553 if_refresh(ifp);
48b33aaf 1554 }
d62a17ae 1555 if_data = ifp->info;
1556 if_data->multicast = IF_ZEBRA_MULTICAST_ON;
48b33aaf 1557
d62a17ae 1558 return CMD_SUCCESS;
718e3744 1559}
1560
1561DEFUN (no_multicast,
1562 no_multicast_cmd,
1563 "no multicast",
1564 NO_STR
1565 "Unset multicast flag to interface\n")
1566{
d62a17ae 1567 VTY_DECLVAR_CONTEXT(interface, ifp);
1568 int ret;
1569 struct zebra_if *if_data;
718e3744 1570
d62a17ae 1571 if (CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE)) {
1572 ret = if_unset_flags(ifp, IFF_MULTICAST);
1573 if (ret < 0) {
1574 vty_out(vty, "Can't unset multicast flag\n");
1575 return CMD_WARNING_CONFIG_FAILED;
1576 }
1577 if_refresh(ifp);
48b33aaf 1578 }
d62a17ae 1579 if_data = ifp->info;
1580 if_data->multicast = IF_ZEBRA_MULTICAST_OFF;
718e3744 1581
d62a17ae 1582 return CMD_SUCCESS;
718e3744 1583}
1584
2e3b2e47 1585DEFUN (linkdetect,
1586 linkdetect_cmd,
1587 "link-detect",
1588 "Enable link detection on interface\n")
1589{
d62a17ae 1590 VTY_DECLVAR_CONTEXT(interface, ifp);
1591 int if_was_operative;
2e3b2e47 1592
d62a17ae 1593 if_was_operative = if_is_no_ptm_operative(ifp);
1594 SET_FLAG(ifp->status, ZEBRA_INTERFACE_LINKDETECTION);
2e3b2e47 1595
d62a17ae 1596 /* When linkdetection is enabled, if might come down */
1597 if (!if_is_no_ptm_operative(ifp) && if_was_operative)
1598 if_down(ifp);
2e3b2e47 1599
d62a17ae 1600 /* FIXME: Will defer status change forwarding if interface
1601 does not come down! */
1602
1603 return CMD_SUCCESS;
2e3b2e47 1604}
1605
1606
1607DEFUN (no_linkdetect,
1608 no_linkdetect_cmd,
1609 "no link-detect",
1610 NO_STR
1611 "Disable link detection on interface\n")
1612{
d62a17ae 1613 VTY_DECLVAR_CONTEXT(interface, ifp);
1614 int if_was_operative;
1615
1616 if_was_operative = if_is_no_ptm_operative(ifp);
1617 UNSET_FLAG(ifp->status, ZEBRA_INTERFACE_LINKDETECTION);
2e3b2e47 1618
d62a17ae 1619 /* Interface may come up after disabling link detection */
1620 if (if_is_operative(ifp) && !if_was_operative)
1621 if_up(ifp);
2e3b2e47 1622
d62a17ae 1623 /* FIXME: see linkdetect_cmd */
2e3b2e47 1624
d62a17ae 1625 return CMD_SUCCESS;
2e3b2e47 1626}
1627
718e3744 1628DEFUN (shutdown_if,
1629 shutdown_if_cmd,
1630 "shutdown",
1631 "Shutdown the selected interface\n")
1632{
d62a17ae 1633 VTY_DECLVAR_CONTEXT(interface, ifp);
1634 int ret;
1635 struct zebra_if *if_data;
718e3744 1636
d62a17ae 1637 if (ifp->ifindex != IFINDEX_INTERNAL) {
1638 ret = if_unset_flags(ifp, IFF_UP);
1639 if (ret < 0) {
1640 vty_out(vty, "Can't shutdown interface\n");
1641 return CMD_WARNING_CONFIG_FAILED;
1642 }
1643 if_refresh(ifp);
1644 }
1645 if_data = ifp->info;
1646 if_data->shutdown = IF_ZEBRA_SHUTDOWN_ON;
718e3744 1647
d62a17ae 1648 return CMD_SUCCESS;
718e3744 1649}
1650
1651DEFUN (no_shutdown_if,
1652 no_shutdown_if_cmd,
1653 "no shutdown",
1654 NO_STR
1655 "Shutdown the selected interface\n")
1656{
d62a17ae 1657 VTY_DECLVAR_CONTEXT(interface, ifp);
1658 int ret;
1659 struct zebra_if *if_data;
718e3744 1660
d62a17ae 1661 if (ifp->ifindex != IFINDEX_INTERNAL) {
1662 ret = if_set_flags(ifp, IFF_UP | IFF_RUNNING);
1663 if (ret < 0) {
1664 vty_out(vty, "Can't up interface\n");
1665 return CMD_WARNING_CONFIG_FAILED;
1666 }
1667 if_refresh(ifp);
bfac8dcd 1668
d62a17ae 1669 /* Some addresses (in particular, IPv6 addresses on Linux) get
1670 * removed when the interface goes down. They need to be
1671 * readded.
1672 */
1673 if_addr_wakeup(ifp);
1674 }
bfac8dcd 1675
d62a17ae 1676 if_data = ifp->info;
1677 if_data->shutdown = IF_ZEBRA_SHUTDOWN_OFF;
718e3744 1678
d62a17ae 1679 return CMD_SUCCESS;
718e3744 1680}
1681
1682DEFUN (bandwidth_if,
1683 bandwidth_if_cmd,
6147e2c6 1684 "bandwidth (1-100000)",
718e3744 1685 "Set bandwidth informational parameter\n"
70bd3c43 1686 "Bandwidth in megabits\n")
718e3744 1687{
d62a17ae 1688 int idx_number = 1;
1689 VTY_DECLVAR_CONTEXT(interface, ifp);
1690 unsigned int bandwidth;
1691
1692 bandwidth = strtol(argv[idx_number]->arg, NULL, 10);
1693
1694 /* bandwidth range is <1-100000> */
1695 if (bandwidth < 1 || bandwidth > 100000) {
1696 vty_out(vty, "Bandwidth is invalid\n");
1697 return CMD_WARNING_CONFIG_FAILED;
1698 }
1699
1700 ifp->bandwidth = bandwidth;
718e3744 1701
d62a17ae 1702 /* force protocols to recalculate routes due to cost change */
1703 if (if_is_operative(ifp))
1704 zebra_interface_up_update(ifp);
718e3744 1705
d62a17ae 1706 return CMD_SUCCESS;
718e3744 1707}
1708
1709DEFUN (no_bandwidth_if,
1710 no_bandwidth_if_cmd,
b62ecea5 1711 "no bandwidth [(1-100000)]",
718e3744 1712 NO_STR
b62ecea5
QY
1713 "Set bandwidth informational parameter\n"
1714 "Bandwidth in megabits\n")
718e3744 1715{
d62a17ae 1716 VTY_DECLVAR_CONTEXT(interface, ifp);
718e3744 1717
d62a17ae 1718 ifp->bandwidth = 0;
718e3744 1719
d62a17ae 1720 /* force protocols to recalculate routes due to cost change */
1721 if (if_is_operative(ifp))
1722 zebra_interface_up_update(ifp);
1723
1724 return CMD_SUCCESS;
718e3744 1725}
1726
6b0655a2 1727
d62a17ae 1728struct cmd_node link_params_node = {
9d303b37 1729 LINK_PARAMS_NODE, "%s(config-link-params)# ", 1,
16f1b9ee
OD
1730};
1731
d62a17ae 1732static void link_param_cmd_set_uint32(struct interface *ifp, uint32_t *field,
1733 uint32_t type, uint32_t value)
16f1b9ee 1734{
d62a17ae 1735 /* Update field as needed */
1736 if (IS_PARAM_UNSET(ifp->link_params, type) || *field != value) {
1737 *field = value;
1738 SET_PARAM(ifp->link_params, type);
16f1b9ee 1739
d62a17ae 1740 /* force protocols to update LINK STATE due to parameters change
1741 */
1742 if (if_is_operative(ifp))
1743 zebra_interface_parameters_update(ifp);
1744 }
16f1b9ee 1745}
d62a17ae 1746static void link_param_cmd_set_float(struct interface *ifp, float *field,
1747 uint32_t type, float value)
16f1b9ee
OD
1748{
1749
d62a17ae 1750 /* Update field as needed */
1751 if (IS_PARAM_UNSET(ifp->link_params, type) || *field != value) {
1752 *field = value;
1753 SET_PARAM(ifp->link_params, type);
16f1b9ee 1754
d62a17ae 1755 /* force protocols to update LINK STATE due to parameters change
1756 */
1757 if (if_is_operative(ifp))
1758 zebra_interface_parameters_update(ifp);
1759 }
16f1b9ee
OD
1760}
1761
d62a17ae 1762static void link_param_cmd_unset(struct interface *ifp, uint32_t type)
16f1b9ee 1763{
d62a17ae 1764 if (ifp->link_params == NULL)
1765 return;
16f1b9ee 1766
d62a17ae 1767 /* Unset field */
1768 UNSET_PARAM(ifp->link_params, type);
16f1b9ee 1769
d62a17ae 1770 /* force protocols to update LINK STATE due to parameters change */
1771 if (if_is_operative(ifp))
1772 zebra_interface_parameters_update(ifp);
16f1b9ee
OD
1773}
1774
505e5056 1775DEFUN_NOSH (link_params,
16f1b9ee
OD
1776 link_params_cmd,
1777 "link-params",
1778 LINK_PARAMS_STR)
1779{
d62a17ae 1780 /* vty->qobj_index stays the same @ interface pointer */
1781 vty->node = LINK_PARAMS_NODE;
16f1b9ee 1782
d62a17ae 1783 return CMD_SUCCESS;
16f1b9ee
OD
1784}
1785
505e5056 1786DEFUN_NOSH (exit_link_params,
03f99d9a
DS
1787 exit_link_params_cmd,
1788 "exit-link-params",
1789 "Exit from Link Params configuration mode\n")
1790{
d62a17ae 1791 if (vty->node == LINK_PARAMS_NODE)
1792 vty->node = INTERFACE_NODE;
1793 return CMD_SUCCESS;
03f99d9a
DS
1794}
1795
16f1b9ee
OD
1796/* Specific Traffic Engineering parameters commands */
1797DEFUN (link_params_enable,
1798 link_params_enable_cmd,
1799 "enable",
1800 "Activate link parameters on this interface\n")
1801{
d62a17ae 1802 VTY_DECLVAR_CONTEXT(interface, ifp);
16f1b9ee 1803
d62a17ae 1804 /* This command could be issue at startup, when activate MPLS TE */
1805 /* on a new interface or after a ON / OFF / ON toggle */
1806 /* In all case, TE parameters are reset to their default factory */
1807 if (IS_ZEBRA_DEBUG_EVENT)
1808 zlog_debug(
1809 "Link-params: enable TE link parameters on interface %s",
1810 ifp->name);
16f1b9ee 1811
d62a17ae 1812 if (!if_link_params_get(ifp)) {
1813 if (IS_ZEBRA_DEBUG_EVENT)
1814 zlog_debug(
1815 "Link-params: failed to init TE link parameters %s",
1816 ifp->name);
16f1b9ee 1817
d62a17ae 1818 return CMD_WARNING_CONFIG_FAILED;
1819 }
16f1b9ee 1820
d62a17ae 1821 /* force protocols to update LINK STATE due to parameters change */
1822 if (if_is_operative(ifp))
1823 zebra_interface_parameters_update(ifp);
16f1b9ee 1824
d62a17ae 1825 return CMD_SUCCESS;
16f1b9ee
OD
1826}
1827
1828DEFUN (no_link_params_enable,
1829 no_link_params_enable_cmd,
1830 "no enable",
1831 NO_STR
1832 "Disable link parameters on this interface\n")
1833{
d62a17ae 1834 VTY_DECLVAR_CONTEXT(interface, ifp);
16f1b9ee 1835
d62a17ae 1836 zlog_debug("MPLS-TE: disable TE link parameters on interface %s",
1837 ifp->name);
16f1b9ee 1838
d62a17ae 1839 if_link_params_free(ifp);
16f1b9ee 1840
d62a17ae 1841 /* force protocols to update LINK STATE due to parameters change */
1842 if (if_is_operative(ifp))
1843 zebra_interface_parameters_update(ifp);
16f1b9ee 1844
d62a17ae 1845 return CMD_SUCCESS;
16f1b9ee
OD
1846}
1847
1848/* STANDARD TE metrics */
1849DEFUN (link_params_metric,
1850 link_params_metric_cmd,
6147e2c6 1851 "metric (0-4294967295)",
16f1b9ee
OD
1852 "Link metric for MPLS-TE purpose\n"
1853 "Metric value in decimal\n")
1854{
d62a17ae 1855 int idx_number = 1;
1856 VTY_DECLVAR_CONTEXT(interface, ifp);
1857 struct if_link_params *iflp = if_link_params_get(ifp);
1858 u_int32_t metric;
16f1b9ee 1859
d62a17ae 1860 metric = strtoul(argv[idx_number]->arg, NULL, 10);
16f1b9ee 1861
d62a17ae 1862 /* Update TE metric if needed */
1863 link_param_cmd_set_uint32(ifp, &iflp->te_metric, LP_TE_METRIC, metric);
16f1b9ee 1864
d62a17ae 1865 return CMD_SUCCESS;
16f1b9ee
OD
1866}
1867
1868DEFUN (no_link_params_metric,
1869 no_link_params_metric_cmd,
1870 "no metric",
1871 NO_STR
3ddccf18 1872 "Disable Link Metric on this interface\n")
16f1b9ee 1873{
d62a17ae 1874 VTY_DECLVAR_CONTEXT(interface, ifp);
16f1b9ee 1875
d62a17ae 1876 /* Unset TE Metric */
1877 link_param_cmd_unset(ifp, LP_TE_METRIC);
16f1b9ee 1878
d62a17ae 1879 return CMD_SUCCESS;
16f1b9ee
OD
1880}
1881
1882DEFUN (link_params_maxbw,
1883 link_params_maxbw_cmd,
1884 "max-bw BANDWIDTH",
1885 "Maximum bandwidth that can be used\n"
1886 "Bytes/second (IEEE floating point format)\n")
1887{
d62a17ae 1888 int idx_bandwidth = 1;
1889 VTY_DECLVAR_CONTEXT(interface, ifp);
1890 struct if_link_params *iflp = if_link_params_get(ifp);
1891
1892 float bw;
1893
1894 if (sscanf(argv[idx_bandwidth]->arg, "%g", &bw) != 1) {
1895 vty_out(vty, "link_params_maxbw: fscanf: %s\n",
1896 safe_strerror(errno));
1897 return CMD_WARNING_CONFIG_FAILED;
1898 }
1899
1900 /* Check that Maximum bandwidth is not lower than other bandwidth
1901 * parameters */
1902 if ((bw <= iflp->max_rsv_bw) || (bw <= iflp->unrsv_bw[0])
1903 || (bw <= iflp->unrsv_bw[1]) || (bw <= iflp->unrsv_bw[2])
1904 || (bw <= iflp->unrsv_bw[3]) || (bw <= iflp->unrsv_bw[4])
1905 || (bw <= iflp->unrsv_bw[5]) || (bw <= iflp->unrsv_bw[6])
1906 || (bw <= iflp->unrsv_bw[7]) || (bw <= iflp->ava_bw)
1907 || (bw <= iflp->res_bw) || (bw <= iflp->use_bw)) {
1908 vty_out(vty,
1909 "Maximum Bandwidth could not be lower than others bandwidth\n");
1910 return CMD_WARNING_CONFIG_FAILED;
1911 }
1912
1913 /* Update Maximum Bandwidth if needed */
1914 link_param_cmd_set_float(ifp, &iflp->max_bw, LP_MAX_BW, bw);
1915
1916 return CMD_SUCCESS;
16f1b9ee
OD
1917}
1918
1919DEFUN (link_params_max_rsv_bw,
1920 link_params_max_rsv_bw_cmd,
1921 "max-rsv-bw BANDWIDTH",
1922 "Maximum bandwidth that may be reserved\n"
1923 "Bytes/second (IEEE floating point format)\n")
1924{
d62a17ae 1925 int idx_bandwidth = 1;
1926 VTY_DECLVAR_CONTEXT(interface, ifp);
1927 struct if_link_params *iflp = if_link_params_get(ifp);
1928 float bw;
16f1b9ee 1929
d62a17ae 1930 if (sscanf(argv[idx_bandwidth]->arg, "%g", &bw) != 1) {
1931 vty_out(vty, "link_params_max_rsv_bw: fscanf: %s\n",
1932 safe_strerror(errno));
1933 return CMD_WARNING_CONFIG_FAILED;
1934 }
16f1b9ee 1935
d62a17ae 1936 /* Check that bandwidth is not greater than maximum bandwidth parameter
1937 */
1938 if (bw > iflp->max_bw) {
1939 vty_out(vty,
1940 "Maximum Reservable Bandwidth could not be greater than Maximum Bandwidth (%g)\n",
1941 iflp->max_bw);
1942 return CMD_WARNING_CONFIG_FAILED;
1943 }
16f1b9ee 1944
d62a17ae 1945 /* Update Maximum Reservable Bandwidth if needed */
1946 link_param_cmd_set_float(ifp, &iflp->max_rsv_bw, LP_MAX_RSV_BW, bw);
16f1b9ee 1947
d62a17ae 1948 return CMD_SUCCESS;
16f1b9ee
OD
1949}
1950
1951DEFUN (link_params_unrsv_bw,
1952 link_params_unrsv_bw_cmd,
6147e2c6 1953 "unrsv-bw (0-7) BANDWIDTH",
16f1b9ee
OD
1954 "Unreserved bandwidth at each priority level\n"
1955 "Priority\n"
1956 "Bytes/second (IEEE floating point format)\n")
1957{
d62a17ae 1958 int idx_number = 1;
1959 int idx_bandwidth = 2;
1960 VTY_DECLVAR_CONTEXT(interface, ifp);
1961 struct if_link_params *iflp = if_link_params_get(ifp);
1962 int priority;
1963 float bw;
1964
1965 /* We don't have to consider about range check here. */
1966 if (sscanf(argv[idx_number]->arg, "%d", &priority) != 1) {
1967 vty_out(vty, "link_params_unrsv_bw: fscanf: %s\n",
1968 safe_strerror(errno));
1969 return CMD_WARNING_CONFIG_FAILED;
1970 }
1971
1972 if (sscanf(argv[idx_bandwidth]->arg, "%g", &bw) != 1) {
1973 vty_out(vty, "link_params_unrsv_bw: fscanf: %s\n",
1974 safe_strerror(errno));
1975 return CMD_WARNING_CONFIG_FAILED;
1976 }
1977
1978 /* Check that bandwidth is not greater than maximum bandwidth parameter
1979 */
1980 if (bw > iflp->max_bw) {
1981 vty_out(vty,
1982 "UnReserved Bandwidth could not be greater than Maximum Bandwidth (%g)\n",
1983 iflp->max_bw);
1984 return CMD_WARNING_CONFIG_FAILED;
1985 }
1986
1987 /* Update Unreserved Bandwidth if needed */
1988 link_param_cmd_set_float(ifp, &iflp->unrsv_bw[priority], LP_UNRSV_BW,
1989 bw);
1990
1991 return CMD_SUCCESS;
16f1b9ee
OD
1992}
1993
1994DEFUN (link_params_admin_grp,
1995 link_params_admin_grp_cmd,
1996 "admin-grp BITPATTERN",
1997 "Administrative group membership\n"
1998 "32-bit Hexadecimal value (e.g. 0xa1)\n")
1999{
d62a17ae 2000 int idx_bitpattern = 1;
2001 VTY_DECLVAR_CONTEXT(interface, ifp);
2002 struct if_link_params *iflp = if_link_params_get(ifp);
2003 unsigned long value;
16f1b9ee 2004
d62a17ae 2005 if (sscanf(argv[idx_bitpattern]->arg, "0x%lx", &value) != 1) {
2006 vty_out(vty, "link_params_admin_grp: fscanf: %s\n",
2007 safe_strerror(errno));
2008 return CMD_WARNING_CONFIG_FAILED;
2009 }
16f1b9ee 2010
d62a17ae 2011 /* Update Administrative Group if needed */
2012 link_param_cmd_set_uint32(ifp, &iflp->admin_grp, LP_ADM_GRP, value);
16f1b9ee 2013
d62a17ae 2014 return CMD_SUCCESS;
16f1b9ee
OD
2015}
2016
2017DEFUN (no_link_params_admin_grp,
2018 no_link_params_admin_grp_cmd,
2019 "no admin-grp",
2020 NO_STR
3ddccf18 2021 "Disable Administrative group membership on this interface\n")
16f1b9ee 2022{
d62a17ae 2023 VTY_DECLVAR_CONTEXT(interface, ifp);
16f1b9ee 2024
d62a17ae 2025 /* Unset Admin Group */
2026 link_param_cmd_unset(ifp, LP_ADM_GRP);
16f1b9ee 2027
d62a17ae 2028 return CMD_SUCCESS;
16f1b9ee
OD
2029}
2030
2031/* RFC5392 & RFC5316: INTER-AS */
2032DEFUN (link_params_inter_as,
2033 link_params_inter_as_cmd,
6147e2c6 2034 "neighbor A.B.C.D as (1-4294967295)",
16f1b9ee
OD
2035 "Configure remote ASBR information (Neighbor IP address and AS number)\n"
2036 "Remote IP address in dot decimal A.B.C.D\n"
2037 "Remote AS number\n"
2038 "AS number in the range <1-4294967295>\n")
2039{
d62a17ae 2040 int idx_ipv4 = 1;
2041 int idx_number = 3;
16f1b9ee 2042
d62a17ae 2043 VTY_DECLVAR_CONTEXT(interface, ifp);
2044 struct if_link_params *iflp = if_link_params_get(ifp);
2045 struct in_addr addr;
2046 u_int32_t as;
16f1b9ee 2047
d62a17ae 2048 if (!inet_aton(argv[idx_ipv4]->arg, &addr)) {
2049 vty_out(vty, "Please specify Router-Addr by A.B.C.D\n");
2050 return CMD_WARNING_CONFIG_FAILED;
2051 }
16f1b9ee 2052
d62a17ae 2053 as = strtoul(argv[idx_number]->arg, NULL, 10);
16f1b9ee 2054
d62a17ae 2055 /* Update Remote IP and Remote AS fields if needed */
2056 if (IS_PARAM_UNSET(iflp, LP_RMT_AS) || iflp->rmt_as != as
2057 || iflp->rmt_ip.s_addr != addr.s_addr) {
16f1b9ee 2058
d62a17ae 2059 iflp->rmt_as = as;
2060 iflp->rmt_ip.s_addr = addr.s_addr;
2061 SET_PARAM(iflp, LP_RMT_AS);
16f1b9ee 2062
d62a17ae 2063 /* force protocols to update LINK STATE due to parameters change
2064 */
2065 if (if_is_operative(ifp))
2066 zebra_interface_parameters_update(ifp);
2067 }
2068 return CMD_SUCCESS;
16f1b9ee
OD
2069}
2070
2071DEFUN (no_link_params_inter_as,
2072 no_link_params_inter_as_cmd,
2073 "no neighbor",
2074 NO_STR
2075 "Remove Neighbor IP address and AS number for Inter-AS TE\n")
2076{
d62a17ae 2077 VTY_DECLVAR_CONTEXT(interface, ifp);
2078 struct if_link_params *iflp = if_link_params_get(ifp);
16f1b9ee 2079
d62a17ae 2080 /* Reset Remote IP and AS neighbor */
2081 iflp->rmt_as = 0;
2082 iflp->rmt_ip.s_addr = 0;
2083 UNSET_PARAM(iflp, LP_RMT_AS);
16f1b9ee 2084
d62a17ae 2085 /* force protocols to update LINK STATE due to parameters change */
2086 if (if_is_operative(ifp))
2087 zebra_interface_parameters_update(ifp);
16f1b9ee 2088
d62a17ae 2089 return CMD_SUCCESS;
16f1b9ee
OD
2090}
2091
d62a17ae 2092/* RFC7471: OSPF Traffic Engineering (TE) Metric extensions &
2093 * draft-ietf-isis-metric-extensions-07.txt */
16f1b9ee
OD
2094DEFUN (link_params_delay,
2095 link_params_delay_cmd,
b62ecea5 2096 "delay (0-16777215) [min (0-16777215) max (0-16777215)]",
16f1b9ee 2097 "Unidirectional Average Link Delay\n"
b62ecea5
QY
2098 "Average delay in micro-second as decimal (0...16777215)\n"
2099 "Minimum delay\n"
2100 "Minimum delay in micro-second as decimal (0...16777215)\n"
2101 "Maximum delay\n"
2102 "Maximum delay in micro-second as decimal (0...16777215)\n")
16f1b9ee 2103{
d62a17ae 2104 /* Get and Check new delay values */
2105 u_int32_t delay = 0, low = 0, high = 0;
2106 delay = strtoul(argv[1]->arg, NULL, 10);
2107 if (argc == 6) {
2108 low = strtoul(argv[3]->arg, NULL, 10);
2109 high = strtoul(argv[5]->arg, NULL, 10);
2110 }
2111
2112 VTY_DECLVAR_CONTEXT(interface, ifp);
2113 struct if_link_params *iflp = if_link_params_get(ifp);
2114 u_int8_t update = 0;
2115
2116 if (argc == 2) {
2117 /* Check new delay value against old Min and Max delays if set
2118 */
2119 if (IS_PARAM_SET(iflp, LP_MM_DELAY)
2120 && (delay <= iflp->min_delay || delay >= iflp->max_delay)) {
2121 vty_out(vty,
2122 "Average delay should be comprise between Min (%d) and Max (%d) delay\n",
2123 iflp->min_delay, iflp->max_delay);
2124 return CMD_WARNING_CONFIG_FAILED;
2125 }
2126 /* Update delay if value is not set or change */
2127 if (IS_PARAM_UNSET(iflp, LP_DELAY) || iflp->av_delay != delay) {
2128 iflp->av_delay = delay;
2129 SET_PARAM(iflp, LP_DELAY);
2130 update = 1;
2131 }
2132 /* Unset Min and Max delays if already set */
2133 if (IS_PARAM_SET(iflp, LP_MM_DELAY)) {
2134 iflp->min_delay = 0;
2135 iflp->max_delay = 0;
2136 UNSET_PARAM(iflp, LP_MM_DELAY);
2137 update = 1;
2138 }
2139 } else {
2140 /* Check new delays value coherency */
2141 if (delay <= low || delay >= high) {
2142 vty_out(vty,
2143 "Average delay should be comprise between Min (%d) and Max (%d) delay\n",
2144 low, high);
2145 return CMD_WARNING_CONFIG_FAILED;
2146 }
2147 /* Update Delays if needed */
2148 if (IS_PARAM_UNSET(iflp, LP_DELAY)
2149 || IS_PARAM_UNSET(iflp, LP_MM_DELAY)
2150 || iflp->av_delay != delay || iflp->min_delay != low
2151 || iflp->max_delay != high) {
2152 iflp->av_delay = delay;
2153 SET_PARAM(iflp, LP_DELAY);
2154 iflp->min_delay = low;
2155 iflp->max_delay = high;
2156 SET_PARAM(iflp, LP_MM_DELAY);
2157 update = 1;
2158 }
2159 }
2160
2161 /* force protocols to update LINK STATE due to parameters change */
2162 if (update == 1 && if_is_operative(ifp))
2163 zebra_interface_parameters_update(ifp);
2164
2165 return CMD_SUCCESS;
16f1b9ee
OD
2166}
2167
16f1b9ee
OD
2168DEFUN (no_link_params_delay,
2169 no_link_params_delay_cmd,
2170 "no delay",
2171 NO_STR
3ddccf18 2172 "Disable Unidirectional Average, Min & Max Link Delay on this interface\n")
16f1b9ee 2173{
d62a17ae 2174 VTY_DECLVAR_CONTEXT(interface, ifp);
2175 struct if_link_params *iflp = if_link_params_get(ifp);
16f1b9ee 2176
d62a17ae 2177 /* Unset Delays */
2178 iflp->av_delay = 0;
2179 UNSET_PARAM(iflp, LP_DELAY);
2180 iflp->min_delay = 0;
2181 iflp->max_delay = 0;
2182 UNSET_PARAM(iflp, LP_MM_DELAY);
16f1b9ee 2183
d62a17ae 2184 /* force protocols to update LINK STATE due to parameters change */
2185 if (if_is_operative(ifp))
2186 zebra_interface_parameters_update(ifp);
16f1b9ee 2187
d62a17ae 2188 return CMD_SUCCESS;
16f1b9ee
OD
2189}
2190
2191DEFUN (link_params_delay_var,
2192 link_params_delay_var_cmd,
6147e2c6 2193 "delay-variation (0-16777215)",
16f1b9ee
OD
2194 "Unidirectional Link Delay Variation\n"
2195 "delay variation in micro-second as decimal (0...16777215)\n")
2196{
d62a17ae 2197 int idx_number = 1;
2198 VTY_DECLVAR_CONTEXT(interface, ifp);
2199 struct if_link_params *iflp = if_link_params_get(ifp);
2200 u_int32_t value;
16f1b9ee 2201
d62a17ae 2202 value = strtoul(argv[idx_number]->arg, NULL, 10);
16f1b9ee 2203
d62a17ae 2204 /* Update Delay Variation if needed */
2205 link_param_cmd_set_uint32(ifp, &iflp->delay_var, LP_DELAY_VAR, value);
16f1b9ee 2206
d62a17ae 2207 return CMD_SUCCESS;
16f1b9ee
OD
2208}
2209
2210DEFUN (no_link_params_delay_var,
2211 no_link_params_delay_var_cmd,
2212 "no delay-variation",
2213 NO_STR
3ddccf18 2214 "Disable Unidirectional Delay Variation on this interface\n")
16f1b9ee 2215{
d62a17ae 2216 VTY_DECLVAR_CONTEXT(interface, ifp);
16f1b9ee 2217
d62a17ae 2218 /* Unset Delay Variation */
2219 link_param_cmd_unset(ifp, LP_DELAY_VAR);
16f1b9ee 2220
d62a17ae 2221 return CMD_SUCCESS;
16f1b9ee
OD
2222}
2223
2224DEFUN (link_params_pkt_loss,
2225 link_params_pkt_loss_cmd,
2226 "packet-loss PERCENTAGE",
2227 "Unidirectional Link Packet Loss\n"
2228 "percentage of total traffic by 0.000003% step and less than 50.331642%\n")
2229{
d62a17ae 2230 int idx_percentage = 1;
2231 VTY_DECLVAR_CONTEXT(interface, ifp);
2232 struct if_link_params *iflp = if_link_params_get(ifp);
2233 float fval;
16f1b9ee 2234
d62a17ae 2235 if (sscanf(argv[idx_percentage]->arg, "%g", &fval) != 1) {
2236 vty_out(vty, "link_params_pkt_loss: fscanf: %s\n",
2237 safe_strerror(errno));
2238 return CMD_WARNING_CONFIG_FAILED;
2239 }
16f1b9ee 2240
d62a17ae 2241 if (fval > MAX_PKT_LOSS)
2242 fval = MAX_PKT_LOSS;
16f1b9ee 2243
d62a17ae 2244 /* Update Packet Loss if needed */
2245 link_param_cmd_set_float(ifp, &iflp->pkt_loss, LP_PKT_LOSS, fval);
16f1b9ee 2246
d62a17ae 2247 return CMD_SUCCESS;
16f1b9ee
OD
2248}
2249
2250DEFUN (no_link_params_pkt_loss,
2251 no_link_params_pkt_loss_cmd,
2252 "no packet-loss",
2253 NO_STR
3ddccf18 2254 "Disable Unidirectional Link Packet Loss on this interface\n")
16f1b9ee 2255{
d62a17ae 2256 VTY_DECLVAR_CONTEXT(interface, ifp);
16f1b9ee 2257
d62a17ae 2258 /* Unset Packet Loss */
2259 link_param_cmd_unset(ifp, LP_PKT_LOSS);
16f1b9ee 2260
d62a17ae 2261 return CMD_SUCCESS;
16f1b9ee
OD
2262}
2263
2264DEFUN (link_params_res_bw,
2265 link_params_res_bw_cmd,
2266 "res-bw BANDWIDTH",
2267 "Unidirectional Residual Bandwidth\n"
2268 "Bytes/second (IEEE floating point format)\n")
2269{
d62a17ae 2270 int idx_bandwidth = 1;
2271 VTY_DECLVAR_CONTEXT(interface, ifp);
2272 struct if_link_params *iflp = if_link_params_get(ifp);
2273 float bw;
16f1b9ee 2274
d62a17ae 2275 if (sscanf(argv[idx_bandwidth]->arg, "%g", &bw) != 1) {
2276 vty_out(vty, "link_params_res_bw: fscanf: %s\n",
2277 safe_strerror(errno));
2278 return CMD_WARNING_CONFIG_FAILED;
2279 }
16f1b9ee 2280
d62a17ae 2281 /* Check that bandwidth is not greater than maximum bandwidth parameter
2282 */
2283 if (bw > iflp->max_bw) {
2284 vty_out(vty,
2285 "Residual Bandwidth could not be greater than Maximum Bandwidth (%g)\n",
2286 iflp->max_bw);
2287 return CMD_WARNING_CONFIG_FAILED;
2288 }
16f1b9ee 2289
d62a17ae 2290 /* Update Residual Bandwidth if needed */
2291 link_param_cmd_set_float(ifp, &iflp->res_bw, LP_RES_BW, bw);
16f1b9ee 2292
d62a17ae 2293 return CMD_SUCCESS;
16f1b9ee
OD
2294}
2295
2296DEFUN (no_link_params_res_bw,
2297 no_link_params_res_bw_cmd,
2298 "no res-bw",
2299 NO_STR
3ddccf18 2300 "Disable Unidirectional Residual Bandwidth on this interface\n")
16f1b9ee 2301{
d62a17ae 2302 VTY_DECLVAR_CONTEXT(interface, ifp);
16f1b9ee 2303
d62a17ae 2304 /* Unset Residual Bandwidth */
2305 link_param_cmd_unset(ifp, LP_RES_BW);
16f1b9ee 2306
d62a17ae 2307 return CMD_SUCCESS;
16f1b9ee
OD
2308}
2309
2310DEFUN (link_params_ava_bw,
2311 link_params_ava_bw_cmd,
2312 "ava-bw BANDWIDTH",
2313 "Unidirectional Available Bandwidth\n"
2314 "Bytes/second (IEEE floating point format)\n")
2315{
d62a17ae 2316 int idx_bandwidth = 1;
2317 VTY_DECLVAR_CONTEXT(interface, ifp);
2318 struct if_link_params *iflp = if_link_params_get(ifp);
2319 float bw;
16f1b9ee 2320
d62a17ae 2321 if (sscanf(argv[idx_bandwidth]->arg, "%g", &bw) != 1) {
2322 vty_out(vty, "link_params_ava_bw: fscanf: %s\n",
2323 safe_strerror(errno));
2324 return CMD_WARNING_CONFIG_FAILED;
2325 }
16f1b9ee 2326
d62a17ae 2327 /* Check that bandwidth is not greater than maximum bandwidth parameter
2328 */
2329 if (bw > iflp->max_bw) {
2330 vty_out(vty,
2331 "Available Bandwidth could not be greater than Maximum Bandwidth (%g)\n",
2332 iflp->max_bw);
2333 return CMD_WARNING_CONFIG_FAILED;
2334 }
16f1b9ee 2335
d62a17ae 2336 /* Update Residual Bandwidth if needed */
2337 link_param_cmd_set_float(ifp, &iflp->ava_bw, LP_AVA_BW, bw);
16f1b9ee 2338
d62a17ae 2339 return CMD_SUCCESS;
16f1b9ee
OD
2340}
2341
2342DEFUN (no_link_params_ava_bw,
2343 no_link_params_ava_bw_cmd,
2344 "no ava-bw",
2345 NO_STR
3ddccf18 2346 "Disable Unidirectional Available Bandwidth on this interface\n")
16f1b9ee 2347{
d62a17ae 2348 VTY_DECLVAR_CONTEXT(interface, ifp);
16f1b9ee 2349
d62a17ae 2350 /* Unset Available Bandwidth */
2351 link_param_cmd_unset(ifp, LP_AVA_BW);
16f1b9ee 2352
d62a17ae 2353 return CMD_SUCCESS;
16f1b9ee
OD
2354}
2355
2356DEFUN (link_params_use_bw,
2357 link_params_use_bw_cmd,
2358 "use-bw BANDWIDTH",
2359 "Unidirectional Utilised Bandwidth\n"
2360 "Bytes/second (IEEE floating point format)\n")
2361{
d62a17ae 2362 int idx_bandwidth = 1;
2363 VTY_DECLVAR_CONTEXT(interface, ifp);
2364 struct if_link_params *iflp = if_link_params_get(ifp);
2365 float bw;
16f1b9ee 2366
d62a17ae 2367 if (sscanf(argv[idx_bandwidth]->arg, "%g", &bw) != 1) {
2368 vty_out(vty, "link_params_use_bw: fscanf: %s\n",
2369 safe_strerror(errno));
2370 return CMD_WARNING_CONFIG_FAILED;
2371 }
16f1b9ee 2372
d62a17ae 2373 /* Check that bandwidth is not greater than maximum bandwidth parameter
2374 */
2375 if (bw > iflp->max_bw) {
2376 vty_out(vty,
2377 "Utilised Bandwidth could not be greater than Maximum Bandwidth (%g)\n",
2378 iflp->max_bw);
2379 return CMD_WARNING_CONFIG_FAILED;
2380 }
16f1b9ee 2381
d62a17ae 2382 /* Update Utilized Bandwidth if needed */
2383 link_param_cmd_set_float(ifp, &iflp->use_bw, LP_USE_BW, bw);
16f1b9ee 2384
d62a17ae 2385 return CMD_SUCCESS;
16f1b9ee
OD
2386}
2387
2388DEFUN (no_link_params_use_bw,
2389 no_link_params_use_bw_cmd,
2390 "no use-bw",
2391 NO_STR
3ddccf18 2392 "Disable Unidirectional Utilised Bandwidth on this interface\n")
16f1b9ee 2393{
d62a17ae 2394 VTY_DECLVAR_CONTEXT(interface, ifp);
16f1b9ee 2395
d62a17ae 2396 /* Unset Utilised Bandwidth */
2397 link_param_cmd_unset(ifp, LP_USE_BW);
16f1b9ee 2398
d62a17ae 2399 return CMD_SUCCESS;
16f1b9ee
OD
2400}
2401
d62a17ae 2402static int ip_address_install(struct vty *vty, struct interface *ifp,
2403 const char *addr_str, const char *peer_str,
2404 const char *label)
718e3744 2405{
d62a17ae 2406 struct zebra_if *if_data;
a07df329 2407 struct prefix_ipv4 lp, pp;
d62a17ae 2408 struct connected *ifc;
2409 struct prefix_ipv4 *p;
2410 int ret;
718e3744 2411
d62a17ae 2412 if_data = ifp->info;
bfac8dcd 2413
a07df329 2414 ret = str2prefix_ipv4(addr_str, &lp);
d62a17ae 2415 if (ret <= 0) {
2416 vty_out(vty, "%% Malformed address \n");
2417 return CMD_WARNING_CONFIG_FAILED;
2418 }
718e3744 2419
a07df329 2420 if (ipv4_martian(&lp.prefix)) {
d62a17ae 2421 vty_out(vty, "%% Invalid address\n");
2422 return CMD_WARNING_CONFIG_FAILED;
2423 }
d914d5ff 2424
a07df329
DL
2425 if (peer_str) {
2426 if (lp.prefixlen != 32) {
2427 vty_out(vty,
2428 "%% Local prefix length for P-t-P address must be /32\n");
2429 return CMD_WARNING_CONFIG_FAILED;
2430 }
2431
2432 ret = str2prefix_ipv4(peer_str, &pp);
2433 if (ret <= 0) {
2434 vty_out(vty, "%% Malformed peer address\n");
2435 return CMD_WARNING_CONFIG_FAILED;
2436 }
2437 }
2438
2439 ifc = connected_check_ptp(ifp, &lp, peer_str ? &pp : NULL);
d62a17ae 2440 if (!ifc) {
2441 ifc = connected_new();
2442 ifc->ifp = ifp;
2443
2444 /* Address. */
2445 p = prefix_ipv4_new();
a07df329 2446 *p = lp;
d62a17ae 2447 ifc->address = (struct prefix *)p;
2448
a07df329
DL
2449 if (peer_str) {
2450 SET_FLAG(ifc->flags, ZEBRA_IFA_PEER);
2451 p = prefix_ipv4_new();
2452 *p = pp;
2453 ifc->destination = (struct prefix *)p;
2454 } else if (p->prefixlen <= IPV4_MAX_PREFIXLEN - 2) {
d62a17ae 2455 p = prefix_ipv4_new();
a07df329 2456 *p = lp;
d62a17ae 2457 p->prefix.s_addr = ipv4_broadcast_addr(p->prefix.s_addr,
2458 p->prefixlen);
2459 ifc->destination = (struct prefix *)p;
2460 }
718e3744 2461
d62a17ae 2462 /* Label. */
2463 if (label)
2464 ifc->label = XSTRDUP(MTYPE_CONNECTED_LABEL, label);
718e3744 2465
d62a17ae 2466 /* Add to linked list. */
2467 listnode_add(ifp->connected, ifc);
718e3744 2468 }
2469
d62a17ae 2470 /* This address is configured from zebra. */
2471 if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED))
2472 SET_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED);
2473
2474 /* In case of this route need to install kernel. */
2475 if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_QUEUED)
2476 && CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE)
2477 && !(if_data && if_data->shutdown == IF_ZEBRA_SHUTDOWN_ON)) {
2478 /* Some system need to up the interface to set IP address. */
2479 if (!if_is_up(ifp)) {
2480 if_set_flags(ifp, IFF_UP | IFF_RUNNING);
2481 if_refresh(ifp);
2482 }
2483
2484 ret = if_set_prefix(ifp, ifc);
2485 if (ret < 0) {
2486 vty_out(vty, "%% Can't set interface IP address: %s.\n",
2487 safe_strerror(errno));
2488 return CMD_WARNING_CONFIG_FAILED;
2489 }
2490
2491 SET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED);
2492 /* The address will be advertised to zebra clients when the
2493 * notification
2494 * from the kernel has been received.
2495 * It will also be added to the subnet chain list, then. */
2496 }
2497
2498 return CMD_SUCCESS;
2499}
2500
2501static int ip_address_uninstall(struct vty *vty, struct interface *ifp,
2502 const char *addr_str, const char *peer_str,
2503 const char *label)
2504{
a07df329 2505 struct prefix_ipv4 lp, pp;
d62a17ae 2506 struct connected *ifc;
2507 int ret;
2508
2509 /* Convert to prefix structure. */
a07df329 2510 ret = str2prefix_ipv4(addr_str, &lp);
d62a17ae 2511 if (ret <= 0) {
2512 vty_out(vty, "%% Malformed address \n");
2513 return CMD_WARNING_CONFIG_FAILED;
2514 }
2515
a07df329
DL
2516 if (peer_str) {
2517 if (lp.prefixlen != 32) {
2518 vty_out(vty,
2519 "%% Local prefix length for P-t-P address must be /32\n");
2520 return CMD_WARNING_CONFIG_FAILED;
2521 }
2522
2523 ret = str2prefix_ipv4(peer_str, &pp);
2524 if (ret <= 0) {
2525 vty_out(vty, "%% Malformed peer address\n");
2526 return CMD_WARNING_CONFIG_FAILED;
2527 }
2528 }
2529
d62a17ae 2530 /* Check current interface address. */
a07df329 2531 ifc = connected_check_ptp(ifp, &lp, peer_str ? &pp : NULL);
d62a17ae 2532 if (!ifc) {
2533 vty_out(vty, "%% Can't find address\n");
2534 return CMD_WARNING_CONFIG_FAILED;
2535 }
2536
2537 /* This is not configured address. */
2538 if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED))
2539 return CMD_WARNING_CONFIG_FAILED;
2540
2541 UNSET_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED);
2542
2543 /* This is not real address or interface is not active. */
2544 if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_QUEUED)
2545 || !CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE)) {
2546 listnode_delete(ifp->connected, ifc);
2547 connected_free(ifc);
2548 return CMD_WARNING_CONFIG_FAILED;
2549 }
2550
2551 /* This is real route. */
2552 ret = if_unset_prefix(ifp, ifc);
2553 if (ret < 0) {
2554 vty_out(vty, "%% Can't unset interface IP address: %s.\n",
2555 safe_strerror(errno));
2556 return CMD_WARNING_CONFIG_FAILED;
2557 }
2558 UNSET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED);
2559 /* we will receive a kernel notification about this route being removed.
2560 * this will trigger its removal from the connected list. */
2561 return CMD_SUCCESS;
718e3744 2562}
2563
2564DEFUN (ip_address,
2565 ip_address_cmd,
2566 "ip address A.B.C.D/M",
2567 "Interface Internet Protocol config commands\n"
2568 "Set the IP address of an interface\n"
2569 "IP address (e.g. 10.0.0.1/8)\n")
2570{
d62a17ae 2571 int idx_ipv4_prefixlen = 2;
2572 VTY_DECLVAR_CONTEXT(interface, ifp);
2573 return ip_address_install(vty, ifp, argv[idx_ipv4_prefixlen]->arg, NULL,
2574 NULL);
718e3744 2575}
2576
2577DEFUN (no_ip_address,
2578 no_ip_address_cmd,
2579 "no ip address A.B.C.D/M",
2580 NO_STR
2581 "Interface Internet Protocol config commands\n"
2582 "Set the IP address of an interface\n"
efd7904e 2583 "IP Address (e.g. 10.0.0.1/8)\n")
718e3744 2584{
d62a17ae 2585 int idx_ipv4_prefixlen = 3;
2586 VTY_DECLVAR_CONTEXT(interface, ifp);
2587 return ip_address_uninstall(vty, ifp, argv[idx_ipv4_prefixlen]->arg,
2588 NULL, NULL);
718e3744 2589}
2590
60466a63
QY
2591DEFUN(ip_address_peer,
2592 ip_address_peer_cmd,
2593 "ip address A.B.C.D peer A.B.C.D/M",
2594 "Interface Internet Protocol config commands\n"
2595 "Set the IP address of an interface\n"
2596 "Local IP (e.g. 10.0.0.1) for P-t-P address\n"
2597 "Specify P-t-P address\n"
2598 "Peer IP address (e.g. 10.0.0.1/8)\n")
a07df329
DL
2599{
2600 VTY_DECLVAR_CONTEXT(interface, ifp);
2601 return ip_address_install(vty, ifp, argv[2]->arg, argv[4]->arg, NULL);
2602}
2603
60466a63
QY
2604DEFUN(no_ip_address_peer,
2605 no_ip_address_peer_cmd,
2606 "no ip address A.B.C.D peer A.B.C.D/M",
2607 NO_STR
2608 "Interface Internet Protocol config commands\n"
2609 "Set the IP address of an interface\n"
2610 "Local IP (e.g. 10.0.0.1) for P-t-P address\n"
2611 "Specify P-t-P address\n"
2612 "Peer IP address (e.g. 10.0.0.1/8)\n")
a07df329
DL
2613{
2614 VTY_DECLVAR_CONTEXT(interface, ifp);
2615 return ip_address_uninstall(vty, ifp, argv[3]->arg, argv[5]->arg, NULL);
2616}
986aa00f 2617
718e3744 2618#ifdef HAVE_NETLINK
718e3744 2619DEFUN (ip_address_label,
2620 ip_address_label_cmd,
2621 "ip address A.B.C.D/M label LINE",
2622 "Interface Internet Protocol config commands\n"
2623 "Set the IP address of an interface\n"
2624 "IP address (e.g. 10.0.0.1/8)\n"
2625 "Label of this address\n"
2626 "Label\n")
2627{
d62a17ae 2628 int idx_ipv4_prefixlen = 2;
2629 int idx_line = 4;
2630 VTY_DECLVAR_CONTEXT(interface, ifp);
2631 return ip_address_install(vty, ifp, argv[idx_ipv4_prefixlen]->arg, NULL,
2632 argv[idx_line]->arg);
718e3744 2633}
2634
2635DEFUN (no_ip_address_label,
2636 no_ip_address_label_cmd,
2637 "no ip address A.B.C.D/M label LINE",
2638 NO_STR
2639 "Interface Internet Protocol config commands\n"
2640 "Set the IP address of an interface\n"
2641 "IP address (e.g. 10.0.0.1/8)\n"
2642 "Label of this address\n"
2643 "Label\n")
2644{
d62a17ae 2645 int idx_ipv4_prefixlen = 3;
2646 int idx_line = 5;
2647 VTY_DECLVAR_CONTEXT(interface, ifp);
2648 return ip_address_uninstall(vty, ifp, argv[idx_ipv4_prefixlen]->arg,
2649 NULL, argv[idx_line]->arg);
718e3744 2650}
2651#endif /* HAVE_NETLINK */
2652
d62a17ae 2653static int ipv6_address_install(struct vty *vty, struct interface *ifp,
2654 const char *addr_str, const char *peer_str,
2655 const char *label, int secondary)
2656{
2657 struct zebra_if *if_data;
2658 struct prefix_ipv6 cp;
2659 struct connected *ifc;
2660 struct prefix_ipv6 *p;
2661 int ret;
2662
2663 if_data = ifp->info;
2664
2665 ret = str2prefix_ipv6(addr_str, &cp);
2666 if (ret <= 0) {
2667 vty_out(vty, "%% Malformed address \n");
2668 return CMD_WARNING_CONFIG_FAILED;
718e3744 2669 }
2670
d62a17ae 2671 if (ipv6_martian(&cp.prefix)) {
2672 vty_out(vty, "%% Invalid address\n");
2673 return CMD_WARNING_CONFIG_FAILED;
2674 }
718e3744 2675
d62a17ae 2676 ifc = connected_check(ifp, (struct prefix *)&cp);
2677 if (!ifc) {
2678 ifc = connected_new();
2679 ifc->ifp = ifp;
2680
2681 /* Address. */
2682 p = prefix_ipv6_new();
2683 *p = cp;
2684 ifc->address = (struct prefix *)p;
2685
2686 /* Secondary. */
2687 if (secondary)
2688 SET_FLAG(ifc->flags, ZEBRA_IFA_SECONDARY);
2689
2690 /* Label. */
2691 if (label)
2692 ifc->label = XSTRDUP(MTYPE_CONNECTED_LABEL, label);
2693
2694 /* Add to linked list. */
2695 listnode_add(ifp->connected, ifc);
718e3744 2696 }
2697
d62a17ae 2698 /* This address is configured from zebra. */
2699 if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED))
2700 SET_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED);
2701
2702 /* In case of this route need to install kernel. */
2703 if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_QUEUED)
2704 && CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE)
2705 && !(if_data && if_data->shutdown == IF_ZEBRA_SHUTDOWN_ON)) {
2706 /* Some system need to up the interface to set IP address. */
2707 if (!if_is_up(ifp)) {
2708 if_set_flags(ifp, IFF_UP | IFF_RUNNING);
2709 if_refresh(ifp);
2710 }
2711
2712 ret = if_prefix_add_ipv6(ifp, ifc);
2713
2714 if (ret < 0) {
2715 vty_out(vty, "%% Can't set interface IP address: %s.\n",
2716 safe_strerror(errno));
2717 return CMD_WARNING_CONFIG_FAILED;
2718 }
2719
2720 SET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED);
2721 /* The address will be advertised to zebra clients when the
2722 * notification
2723 * from the kernel has been received. */
2724 }
718e3744 2725
d62a17ae 2726 return CMD_SUCCESS;
718e3744 2727}
2728
b6120505 2729/* Return true if an ipv6 address is configured on ifp */
d62a17ae 2730int ipv6_address_configured(struct interface *ifp)
2731{
2732 struct connected *connected;
2733 struct listnode *node;
2734
2735 for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, connected))
2736 if (CHECK_FLAG(connected->conf, ZEBRA_IFC_REAL)
2737 && (connected->address->family == AF_INET6))
2738 return 1;
2739
2740 return 0;
2741}
2742
2743static int ipv6_address_uninstall(struct vty *vty, struct interface *ifp,
2744 const char *addr_str, const char *peer_str,
2745 const char *label, int secondry)
2746{
2747 struct prefix_ipv6 cp;
2748 struct connected *ifc;
2749 int ret;
2750
2751 /* Convert to prefix structure. */
2752 ret = str2prefix_ipv6(addr_str, &cp);
2753 if (ret <= 0) {
2754 vty_out(vty, "%% Malformed address \n");
2755 return CMD_WARNING_CONFIG_FAILED;
2756 }
2757
2758 /* Check current interface address. */
2759 ifc = connected_check(ifp, (struct prefix *)&cp);
2760 if (!ifc) {
2761 vty_out(vty, "%% Can't find address\n");
2762 return CMD_WARNING_CONFIG_FAILED;
2763 }
2764
2765 /* This is not configured address. */
2766 if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED))
2767 return CMD_WARNING_CONFIG_FAILED;
2768
2769 UNSET_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED);
2770
2771 /* This is not real address or interface is not active. */
2772 if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_QUEUED)
2773 || !CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE)) {
2774 listnode_delete(ifp->connected, ifc);
2775 connected_free(ifc);
2776 return CMD_WARNING_CONFIG_FAILED;
2777 }
2778
2779 /* This is real route. */
2780 ret = if_prefix_delete_ipv6(ifp, ifc);
2781 if (ret < 0) {
2782 vty_out(vty, "%% Can't unset interface IP address: %s.\n",
2783 safe_strerror(errno));
2784 return CMD_WARNING_CONFIG_FAILED;
2785 }
2786
2787 UNSET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED);
2788 /* This information will be propagated to the zclients when the
2789 * kernel notification is received. */
2790 return CMD_SUCCESS;
718e3744 2791}
2792
2793DEFUN (ipv6_address,
2794 ipv6_address_cmd,
2795 "ipv6 address X:X::X:X/M",
e23949c0 2796 "Interface IPv6 config commands\n"
718e3744 2797 "Set the IP address of an interface\n"
2798 "IPv6 address (e.g. 3ffe:506::1/48)\n")
2799{
d62a17ae 2800 int idx_ipv6_prefixlen = 2;
2801 VTY_DECLVAR_CONTEXT(interface, ifp);
2802 return ipv6_address_install(vty, ifp, argv[idx_ipv6_prefixlen]->arg,
2803 NULL, NULL, 0);
718e3744 2804}
2805
2806DEFUN (no_ipv6_address,
2807 no_ipv6_address_cmd,
2808 "no ipv6 address X:X::X:X/M",
2809 NO_STR
e23949c0 2810 "Interface IPv6 config commands\n"
718e3744 2811 "Set the IP address of an interface\n"
2812 "IPv6 address (e.g. 3ffe:506::1/48)\n")
2813{
d62a17ae 2814 int idx_ipv6_prefixlen = 3;
2815 VTY_DECLVAR_CONTEXT(interface, ifp);
2816 return ipv6_address_uninstall(vty, ifp, argv[idx_ipv6_prefixlen]->arg,
2817 NULL, NULL, 0);
2818}
2819
2820static int link_params_config_write(struct vty *vty, struct interface *ifp)
2821{
2822 int i;
2823
2824 if ((ifp == NULL) || !HAS_LINK_PARAMS(ifp))
2825 return -1;
986aa00f 2826
d62a17ae 2827 struct if_link_params *iflp = ifp->link_params;
2828
2829 vty_out(vty, " link-params\n");
2830 vty_out(vty, " enable\n");
2831 if (IS_PARAM_SET(iflp, LP_TE_METRIC) && iflp->te_metric != ifp->metric)
2832 vty_out(vty, " metric %u\n", iflp->te_metric);
2833 if (IS_PARAM_SET(iflp, LP_MAX_BW) && iflp->max_bw != iflp->default_bw)
2834 vty_out(vty, " max-bw %g\n", iflp->max_bw);
2835 if (IS_PARAM_SET(iflp, LP_MAX_RSV_BW)
2836 && iflp->max_rsv_bw != iflp->default_bw)
2837 vty_out(vty, " max-rsv-bw %g\n", iflp->max_rsv_bw);
2838 if (IS_PARAM_SET(iflp, LP_UNRSV_BW)) {
2839 for (i = 0; i < 8; i++)
2840 if (iflp->unrsv_bw[i] != iflp->default_bw)
2841 vty_out(vty, " unrsv-bw %d %g\n", i,
2842 iflp->unrsv_bw[i]);
2843 }
2844 if (IS_PARAM_SET(iflp, LP_ADM_GRP))
2845 vty_out(vty, " admin-grp 0x%x\n", iflp->admin_grp);
2846 if (IS_PARAM_SET(iflp, LP_DELAY)) {
2847 vty_out(vty, " delay %u", iflp->av_delay);
2848 if (IS_PARAM_SET(iflp, LP_MM_DELAY)) {
2849 vty_out(vty, " min %u", iflp->min_delay);
2850 vty_out(vty, " max %u", iflp->max_delay);
2851 }
2852 vty_out(vty, "\n");
bfac8dcd 2853 }
d62a17ae 2854 if (IS_PARAM_SET(iflp, LP_DELAY_VAR))
2855 vty_out(vty, " delay-variation %u\n", iflp->delay_var);
2856 if (IS_PARAM_SET(iflp, LP_PKT_LOSS))
2857 vty_out(vty, " packet-loss %g\n", iflp->pkt_loss);
2858 if (IS_PARAM_SET(iflp, LP_AVA_BW))
2859 vty_out(vty, " ava-bw %g\n", iflp->ava_bw);
2860 if (IS_PARAM_SET(iflp, LP_RES_BW))
2861 vty_out(vty, " res-bw %g\n", iflp->res_bw);
2862 if (IS_PARAM_SET(iflp, LP_USE_BW))
2863 vty_out(vty, " use-bw %g\n", iflp->use_bw);
2864 if (IS_PARAM_SET(iflp, LP_RMT_AS))
2865 vty_out(vty, " neighbor %s as %u\n", inet_ntoa(iflp->rmt_ip),
2866 iflp->rmt_as);
2867 vty_out(vty, " exit-link-params\n");
2868 return 0;
2869}
2870
2871static int if_config_write(struct vty *vty)
2872{
2873 struct vrf *vrf;
d62a17ae 2874 struct interface *ifp;
2875
2876 zebra_ptm_write(vty);
2877
a2addae8 2878 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name)
451fda4f 2879 FOR_ALL_INTERFACES (vrf, ifp) {
a2addae8
RW
2880 struct zebra_if *if_data;
2881 struct listnode *addrnode;
2882 struct connected *ifc;
2883 struct prefix *p;
2884 struct vrf *vrf;
d62a17ae 2885
a2addae8
RW
2886 if_data = ifp->info;
2887 vrf = vrf_lookup_by_id(ifp->vrf_id);
d62a17ae 2888
a2addae8
RW
2889 if (ifp->vrf_id == VRF_DEFAULT)
2890 vty_frame(vty, "interface %s\n", ifp->name);
2891 else
2892 vty_frame(vty, "interface %s vrf %s\n",
2893 ifp->name, vrf->name);
d62a17ae 2894
a2addae8
RW
2895 if (if_data) {
2896 if (if_data->shutdown == IF_ZEBRA_SHUTDOWN_ON)
2897 vty_out(vty, " shutdown\n");
d62a17ae 2898
a2addae8
RW
2899 zebra_ptm_if_write(vty, if_data);
2900 }
bfac8dcd 2901
a2addae8
RW
2902 if (ifp->desc)
2903 vty_out(vty, " description %s\n", ifp->desc);
2904
2905 /* Assign bandwidth here to avoid unnecessary interface
2906 flap
2907 while processing config script */
2908 if (ifp->bandwidth != 0)
2909 vty_out(vty, " bandwidth %u\n", ifp->bandwidth);
2910
2911 if (!CHECK_FLAG(ifp->status,
2912 ZEBRA_INTERFACE_LINKDETECTION))
2913 vty_out(vty, " no link-detect\n");
2914
2915 for (ALL_LIST_ELEMENTS_RO(ifp->connected, addrnode,
2916 ifc)) {
2917 if (CHECK_FLAG(ifc->conf,
2918 ZEBRA_IFC_CONFIGURED)) {
2919 char buf[INET6_ADDRSTRLEN];
2920 p = ifc->address;
2921 vty_out(vty, " ip%s address %s",
2922 p->family == AF_INET ? ""
2923 : "v6",
a07df329 2924 inet_ntop(p->family,
60466a63
QY
2925 &p->u.prefix, buf,
2926 sizeof(buf)));
a2addae8
RW
2927 if (CONNECTED_PEER(ifc)) {
2928 p = ifc->destination;
2929 vty_out(vty, " peer %s",
2930 inet_ntop(p->family,
2931 &p->u.prefix,
2932 buf,
2933 sizeof(buf)));
2934 }
2935 vty_out(vty, "/%d", p->prefixlen);
718e3744 2936
a2addae8
RW
2937 if (ifc->label)
2938 vty_out(vty, " label %s",
2939 ifc->label);
718e3744 2940
a2addae8
RW
2941 vty_out(vty, "\n");
2942 }
d62a17ae 2943 }
718e3744 2944
a2addae8
RW
2945 if (if_data) {
2946 if (if_data->multicast
2947 != IF_ZEBRA_MULTICAST_UNSPEC)
2948 vty_out(vty, " %smulticast\n",
2949 if_data->multicast
2950 == IF_ZEBRA_MULTICAST_ON
2951 ? ""
2952 : "no ");
2953 }
718e3744 2954
a2addae8 2955 hook_call(zebra_if_config_wr, vty, ifp);
ca776988 2956
a2addae8 2957 link_params_config_write(vty, ifp);
16f1b9ee 2958
a2addae8
RW
2959 vty_endframe(vty, "!\n");
2960 }
d62a17ae 2961 return 0;
718e3744 2962}
2963
2964/* Allocate and initialize interface vector. */
d62a17ae 2965void zebra_if_init(void)
2966{
2967 /* Initialize interface and new hook. */
ce19a04a
DL
2968 hook_register_prio(if_add, 0, if_zebra_new_hook);
2969 hook_register_prio(if_del, 0, if_zebra_delete_hook);
d62a17ae 2970
2971 /* Install configuration write function. */
2972 install_node(&interface_node, if_config_write);
2973 install_node(&link_params_node, NULL);
2974 if_cmd_init();
2975
2976 install_element(VIEW_NODE, &show_interface_cmd);
2977 install_element(VIEW_NODE, &show_interface_vrf_all_cmd);
2978 install_element(VIEW_NODE, &show_interface_name_vrf_cmd);
2979 install_element(VIEW_NODE, &show_interface_name_vrf_all_cmd);
2980
2981 install_element(ENABLE_NODE, &show_interface_desc_cmd);
2982 install_element(ENABLE_NODE, &show_interface_desc_vrf_all_cmd);
2983 install_element(INTERFACE_NODE, &multicast_cmd);
2984 install_element(INTERFACE_NODE, &no_multicast_cmd);
2985 install_element(INTERFACE_NODE, &linkdetect_cmd);
2986 install_element(INTERFACE_NODE, &no_linkdetect_cmd);
2987 install_element(INTERFACE_NODE, &shutdown_if_cmd);
2988 install_element(INTERFACE_NODE, &no_shutdown_if_cmd);
2989 install_element(INTERFACE_NODE, &bandwidth_if_cmd);
2990 install_element(INTERFACE_NODE, &no_bandwidth_if_cmd);
2991 install_element(INTERFACE_NODE, &ip_address_cmd);
2992 install_element(INTERFACE_NODE, &no_ip_address_cmd);
a07df329
DL
2993 install_element(INTERFACE_NODE, &ip_address_peer_cmd);
2994 install_element(INTERFACE_NODE, &no_ip_address_peer_cmd);
d62a17ae 2995 install_element(INTERFACE_NODE, &ipv6_address_cmd);
2996 install_element(INTERFACE_NODE, &no_ipv6_address_cmd);
718e3744 2997#ifdef HAVE_NETLINK
d62a17ae 2998 install_element(INTERFACE_NODE, &ip_address_label_cmd);
2999 install_element(INTERFACE_NODE, &no_ip_address_label_cmd);
718e3744 3000#endif /* HAVE_NETLINK */
d62a17ae 3001 install_element(INTERFACE_NODE, &link_params_cmd);
3002 install_default(LINK_PARAMS_NODE);
3003 install_element(LINK_PARAMS_NODE, &link_params_enable_cmd);
3004 install_element(LINK_PARAMS_NODE, &no_link_params_enable_cmd);
3005 install_element(LINK_PARAMS_NODE, &link_params_metric_cmd);
3006 install_element(LINK_PARAMS_NODE, &no_link_params_metric_cmd);
3007 install_element(LINK_PARAMS_NODE, &link_params_maxbw_cmd);
3008 install_element(LINK_PARAMS_NODE, &link_params_max_rsv_bw_cmd);
3009 install_element(LINK_PARAMS_NODE, &link_params_unrsv_bw_cmd);
3010 install_element(LINK_PARAMS_NODE, &link_params_admin_grp_cmd);
3011 install_element(LINK_PARAMS_NODE, &no_link_params_admin_grp_cmd);
3012 install_element(LINK_PARAMS_NODE, &link_params_inter_as_cmd);
3013 install_element(LINK_PARAMS_NODE, &no_link_params_inter_as_cmd);
3014 install_element(LINK_PARAMS_NODE, &link_params_delay_cmd);
3015 install_element(LINK_PARAMS_NODE, &no_link_params_delay_cmd);
3016 install_element(LINK_PARAMS_NODE, &link_params_delay_var_cmd);
3017 install_element(LINK_PARAMS_NODE, &no_link_params_delay_var_cmd);
3018 install_element(LINK_PARAMS_NODE, &link_params_pkt_loss_cmd);
3019 install_element(LINK_PARAMS_NODE, &no_link_params_pkt_loss_cmd);
3020 install_element(LINK_PARAMS_NODE, &link_params_ava_bw_cmd);
3021 install_element(LINK_PARAMS_NODE, &no_link_params_ava_bw_cmd);
3022 install_element(LINK_PARAMS_NODE, &link_params_res_bw_cmd);
3023 install_element(LINK_PARAMS_NODE, &no_link_params_res_bw_cmd);
3024 install_element(LINK_PARAMS_NODE, &link_params_use_bw_cmd);
3025 install_element(LINK_PARAMS_NODE, &no_link_params_use_bw_cmd);
3026 install_element(LINK_PARAMS_NODE, &exit_link_params_cmd);
718e3744 3027}