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