back to topotato report
topotato coverage report
Current view: top level - zebra - interface.c (source / functions) Hit Total Coverage
Test: test_pim6_basic.py::PIM6Basic Lines: 413 2249 18.4 %
Date: 2023-02-24 18:38:38 Functions: 32 125 25.6 %

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

Generated by: LCOV version v1.16-topotato