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