back to topotato report
topotato coverage report
Current view: top level - zebra - interface.c (source / functions) Hit Total Coverage
Test: test_bgp_ecmp_enhe.py::BGP_Unnumbered_ECMP Lines: 552 2740 20.1 %
Date: 2023-11-16 17:19:14 Functions: 38 300 12.7 %

          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 : }

Generated by: LCOV version v1.16-topotato