back to topotato report
topotato coverage report
Current view: top level - lib - if.c (source / functions) Hit Total Coverage
Test: test_bgp_ecmp_enhe.py::BGP_Unnumbered_ECMP Lines: 260 804 32.3 %
Date: 2023-11-16 17:19:14 Functions: 54 220 24.5 %

          Line data    Source code
       1             : // SPDX-License-Identifier: GPL-2.0-or-later
       2             : /*
       3             :  * Interface functions.
       4             :  * Copyright (C) 1997, 98 Kunihiro Ishiguro
       5             :  */
       6             : 
       7             : #include <zebra.h>
       8             : 
       9             : #include "linklist.h"
      10             : #include "vector.h"
      11             : #include "lib_errors.h"
      12             : #include "vty.h"
      13             : #include "command.h"
      14             : #include "vrf.h"
      15             : #include "if.h"
      16             : #include "sockunion.h"
      17             : #include "prefix.h"
      18             : #include "memory.h"
      19             : #include "table.h"
      20             : #include "buffer.h"
      21             : #include "log.h"
      22             : #include "northbound_cli.h"
      23             : #include "admin_group.h"
      24             : #include "lib/if_clippy.c"
      25             : 
      26          12 : DEFINE_MTYPE_STATIC(LIB, IF, "Interface");
      27          12 : DEFINE_MTYPE_STATIC(LIB, IFDESC, "Intf Desc");
      28          12 : DEFINE_MTYPE_STATIC(LIB, CONNECTED, "Connected");
      29          12 : DEFINE_MTYPE_STATIC(LIB, NBR_CONNECTED, "Neighbor Connected");
      30          12 : DEFINE_MTYPE(LIB, CONNECTED_LABEL, "Connected interface label");
      31          12 : DEFINE_MTYPE_STATIC(LIB, IF_LINK_PARAMS, "Informational Link Parameters");
      32             : 
      33             : static void if_set_name(struct interface *ifp, const char *name);
      34             : static struct interface *if_lookup_by_ifindex(ifindex_t ifindex,
      35             :                                               vrf_id_t vrf_id);
      36             : static struct interface *if_lookup_by_index_all_vrf(ifindex_t ifindex);
      37             : static int if_cmp_func(const struct interface *, const struct interface *);
      38             : static int if_cmp_index_func(const struct interface *ifp1,
      39             :                              const struct interface *ifp2);
      40         322 : RB_GENERATE(if_name_head, interface, name_entry, if_cmp_func);
      41         668 : RB_GENERATE(if_index_head, interface, index_entry, if_cmp_index_func);
      42             : 
      43             : DEFINE_QOBJ_TYPE(interface);
      44             : 
      45          32 : DEFINE_HOOK(if_add, (struct interface *ifp), (ifp));
      46          32 : DEFINE_KOOH(if_del, (struct interface *ifp), (ifp));
      47             : 
      48          48 : DEFINE_HOOK(if_real, (struct interface *ifp), (ifp));
      49           0 : DEFINE_KOOH(if_unreal, (struct interface *ifp), (ifp));
      50             : 
      51          24 : DEFINE_HOOK(if_up, (struct interface *ifp), (ifp));
      52          12 : DEFINE_KOOH(if_down, (struct interface *ifp), (ifp));
      53             : 
      54             : /* Compare interface names, returning an integer greater than, equal to, or
      55             :  * less than 0, (following the strcmp convention), according to the
      56             :  * relationship between ifp1 and ifp2.  Interface names consist of an
      57             :  * alphabetic prefix and a numeric suffix.  The primary sort key is
      58             :  * lexicographic by name, and then numeric by number.  No number sorts
      59             :  * before all numbers.  Examples: de0 < de1, de100 < fxp0 < xl0, devpty <
      60             :  * devpty0, de0 < del0
      61             :  */
      62         177 : int if_cmp_name_func(const char *p1, const char *p2)
      63             : {
      64         177 :         unsigned int l1, l2;
      65         177 :         long int x1, x2;
      66         177 :         int res;
      67             : 
      68         354 :         while (*p1 && *p2) {
      69         290 :                 char *tmp1, *tmp2;
      70             : 
      71             :                 /* look up to any number */
      72         290 :                 l1 = strcspn(p1, "0123456789");
      73         290 :                 l2 = strcspn(p2, "0123456789");
      74             : 
      75             :                 /* name lengths are different -> compare names */
      76         290 :                 if (l1 != l2)
      77         113 :                         return (strcmp(p1, p2));
      78             : 
      79             :                 /* Note that this relies on all numbers being less than all
      80             :                  * letters, so
      81             :                  * that de0 < del0.
      82             :                  */
      83         212 :                 res = strncmp(p1, p2, l1);
      84             : 
      85             :                 /* names are different -> compare them */
      86         212 :                 if (res)
      87           0 :                         return res;
      88             : 
      89             :                 /* with identical name part, go to numeric part */
      90         212 :                 p1 += l1;
      91         212 :                 p2 += l1;
      92             : 
      93         212 :                 if (!*p1 && !*p2)
      94             :                         return 0;
      95         204 :                 if (!*p1)
      96             :                         return -1;
      97         204 :                 if (!*p2)
      98             :                         return 1;
      99             : 
     100         204 :                 x1 = strtol(p1, &tmp1, 10);
     101         204 :                 x2 = strtol(p2, &tmp2, 10);
     102             : 
     103             :                 /* let's compare numbers now */
     104         204 :                 if (x1 < x2)
     105             :                         return -1;
     106         204 :                 if (x1 > x2)
     107             :                         return 1;
     108             : 
     109             :                 /* Compare string if numbers are equal (distinguish foo-1 from foo-001) */
     110         177 :                 l1 = strspn(p1, "0123456789");
     111         177 :                 l2 = strspn(p2, "0123456789");
     112         177 :                 if (l1 != l2)
     113           0 :                         return (strcmp(p1, p2));
     114             : 
     115             :                 /* Continue to parse the rest of the string */
     116         177 :                 p1 = (const char *)tmp1;
     117         177 :                 p2 = (const char *)tmp2;
     118             : 
     119             :                 /* numbers were equal, lets do it again..
     120             :                 (it happens with name like "eth123.456:789") */
     121             :         }
     122          64 :         if (*p1)
     123             :                 return 1;
     124          64 :         if (*p2)
     125          16 :                 return -1;
     126             :         return 0;
     127             : }
     128             : 
     129         161 : static int if_cmp_func(const struct interface *ifp1,
     130             :                        const struct interface *ifp2)
     131             : {
     132         161 :         return if_cmp_name_func(ifp1->name, ifp2->name);
     133             : }
     134             : 
     135         334 : static int if_cmp_index_func(const struct interface *ifp1,
     136             :                              const struct interface *ifp2)
     137             : {
     138         334 :         if (ifp1->ifindex == ifp2->ifindex)
     139             :                 return 0;
     140         181 :         else if (ifp1->ifindex > ifp2->ifindex)
     141             :                 return 1;
     142             :         else
     143          24 :                 return -1;
     144             : }
     145             : 
     146          36 : static void ifp_connected_free(void *arg)
     147             : {
     148          36 :         struct connected *c = arg;
     149             : 
     150          36 :         connected_free(&c);
     151          36 : }
     152             : 
     153             : /* Create new interface structure. */
     154          16 : static struct interface *if_new(struct vrf *vrf)
     155             : {
     156          16 :         struct interface *ifp;
     157             : 
     158          16 :         assert(vrf);
     159             : 
     160          16 :         ifp = XCALLOC(MTYPE_IF, sizeof(struct interface));
     161             : 
     162          16 :         ifp->ifindex = IFINDEX_INTERNAL;
     163          16 :         ifp->name[0] = '\0';
     164             : 
     165          16 :         ifp->vrf = vrf;
     166             : 
     167          16 :         ifp->connected = list_new();
     168          16 :         ifp->connected->del = ifp_connected_free;
     169             : 
     170          16 :         ifp->nbr_connected = list_new();
     171          16 :         ifp->nbr_connected->del = (void (*)(void *))nbr_connected_free;
     172             : 
     173             :         /* Enable Link-detection by default */
     174          16 :         SET_FLAG(ifp->status, ZEBRA_INTERFACE_LINKDETECTION);
     175             : 
     176          16 :         QOBJ_REG(ifp, interface);
     177          16 :         return ifp;
     178             : }
     179             : 
     180          24 : void if_new_via_zapi(struct interface *ifp)
     181             : {
     182          24 :         hook_call(if_real, ifp);
     183          24 : }
     184             : 
     185           0 : void if_destroy_via_zapi(struct interface *ifp)
     186             : {
     187           0 :         hook_call(if_unreal, ifp);
     188             : 
     189           0 :         ifp->oldifindex = ifp->ifindex;
     190           0 :         if_set_index(ifp, IFINDEX_INTERNAL);
     191             : 
     192           0 :         if (!ifp->configured)
     193           0 :                 if_delete(&ifp);
     194           0 : }
     195             : 
     196          12 : void if_up_via_zapi(struct interface *ifp)
     197             : {
     198          12 :         hook_call(if_up, ifp);
     199          12 : }
     200             : 
     201           6 : void if_down_via_zapi(struct interface *ifp)
     202             : {
     203           6 :         hook_call(if_down, ifp);
     204           6 : }
     205             : 
     206          16 : static struct interface *if_create_name(const char *name, struct vrf *vrf)
     207             : {
     208          16 :         struct interface *ifp;
     209             : 
     210          16 :         ifp = if_new(vrf);
     211             : 
     212          16 :         if_set_name(ifp, name);
     213             : 
     214          16 :         hook_call(if_add, ifp);
     215          16 :         return ifp;
     216             : }
     217             : 
     218             : /* Create new interface structure. */
     219           0 : void if_update_to_new_vrf(struct interface *ifp, vrf_id_t vrf_id)
     220             : {
     221           0 :         struct vrf *old_vrf, *vrf;
     222             : 
     223             :         /* remove interface from old master vrf list */
     224           0 :         old_vrf = ifp->vrf;
     225             : 
     226           0 :         if (ifp->name[0] != '\0')
     227           0 :                 IFNAME_RB_REMOVE(old_vrf, ifp);
     228             : 
     229           0 :         if (ifp->ifindex != IFINDEX_INTERNAL)
     230           0 :                 IFINDEX_RB_REMOVE(old_vrf, ifp);
     231             : 
     232           0 :         vrf = vrf_get(vrf_id, NULL);
     233           0 :         ifp->vrf = vrf;
     234             : 
     235           0 :         if (ifp->name[0] != '\0')
     236           0 :                 IFNAME_RB_INSERT(vrf, ifp);
     237             : 
     238           0 :         if (ifp->ifindex != IFINDEX_INTERNAL)
     239           0 :                 IFINDEX_RB_INSERT(vrf, ifp);
     240           0 : }
     241             : 
     242             : 
     243             : /* Delete interface structure. */
     244          16 : void if_delete_retain(struct interface *ifp)
     245             : {
     246          16 :         hook_call(if_del, ifp);
     247          16 :         QOBJ_UNREG(ifp);
     248             : 
     249             :         /* Free connected address list */
     250          16 :         list_delete_all_node(ifp->connected);
     251             : 
     252             :         /* Free connected nbr address list */
     253          16 :         list_delete_all_node(ifp->nbr_connected);
     254          16 : }
     255             : 
     256             : /* Delete and free interface structure. */
     257          16 : void if_delete(struct interface **ifp)
     258             : {
     259          16 :         struct interface *ptr = *ifp;
     260          16 :         struct vrf *vrf = ptr->vrf;
     261             : 
     262          16 :         IFNAME_RB_REMOVE(vrf, ptr);
     263          16 :         if (ptr->ifindex != IFINDEX_INTERNAL)
     264          16 :                 IFINDEX_RB_REMOVE(vrf, ptr);
     265             : 
     266          16 :         if_delete_retain(ptr);
     267             : 
     268          16 :         list_delete(&ptr->connected);
     269          16 :         list_delete(&ptr->nbr_connected);
     270             : 
     271          16 :         if_link_params_free(ptr);
     272             : 
     273          16 :         XFREE(MTYPE_IFDESC, ptr->desc);
     274             : 
     275          16 :         XFREE(MTYPE_IF, ptr);
     276          16 :         *ifp = NULL;
     277          16 : }
     278             : 
     279             : /* Used only internally to check within VRF only */
     280         169 : static struct interface *if_lookup_by_ifindex(ifindex_t ifindex,
     281             :                                               vrf_id_t vrf_id)
     282             : {
     283         169 :         struct vrf *vrf;
     284         169 :         struct interface if_tmp;
     285             : 
     286         169 :         vrf = vrf_lookup_by_id(vrf_id);
     287         169 :         if (!vrf)
     288             :                 return NULL;
     289             : 
     290         169 :         if_tmp.ifindex = ifindex;
     291         169 :         return RB_FIND(if_index_head, &vrf->ifaces_by_index, &if_tmp);
     292             : }
     293             : 
     294             : /* Interface existence check by index. */
     295         153 : struct interface *if_lookup_by_index(ifindex_t ifindex, vrf_id_t vrf_id)
     296             : {
     297         153 :         switch (vrf_get_backend()) {
     298           0 :         case VRF_BACKEND_UNKNOWN:
     299             :         case VRF_BACKEND_NETNS:
     300           0 :                 return(if_lookup_by_ifindex(ifindex, vrf_id));
     301         153 :         case VRF_BACKEND_VRF_LITE:
     302         153 :                 return(if_lookup_by_index_all_vrf(ifindex));
     303             :         }
     304             :         return NULL;
     305             : }
     306             : 
     307             : /* Interface existence check by index. */
     308           0 : struct interface *if_vrf_lookup_by_index_next(ifindex_t ifindex,
     309             :                                               vrf_id_t vrf_id)
     310             : {
     311           0 :         struct vrf *vrf = vrf_lookup_by_id(vrf_id);
     312           0 :         struct interface *tmp_ifp;
     313           0 :         bool found = false;
     314             : 
     315           0 :         if (!vrf)
     316             :                 return NULL;
     317             : 
     318           0 :         if (ifindex == 0) {
     319           0 :                 tmp_ifp = RB_MIN(if_index_head, &vrf->ifaces_by_index);
     320             :                 /* skip the vrf interface */
     321           0 :                 if (tmp_ifp && if_is_vrf(tmp_ifp))
     322           0 :                         ifindex = tmp_ifp->ifindex;
     323             :                 else
     324           0 :                         return tmp_ifp;
     325             :         }
     326             : 
     327           0 :         RB_FOREACH (tmp_ifp, if_index_head, &vrf->ifaces_by_index) {
     328           0 :                 if (found) {
     329             :                         /* skip the vrf interface */
     330           0 :                         if (tmp_ifp && if_is_vrf(tmp_ifp))
     331           0 :                                 continue;
     332             :                         else
     333           0 :                                 return tmp_ifp;
     334             :                 }
     335           0 :                 if (tmp_ifp->ifindex == ifindex)
     336           0 :                         found = true;
     337             :         }
     338             :         return NULL;
     339             : }
     340             : 
     341           0 : const char *ifindex2ifname(ifindex_t ifindex, vrf_id_t vrf_id)
     342             : {
     343           0 :         struct interface *ifp;
     344             : 
     345           0 :         return ((ifp = if_lookup_by_index(ifindex, vrf_id)) != NULL)
     346             :                        ? ifp->name
     347           0 :                        : "unknown";
     348             : }
     349             : 
     350           2 : ifindex_t ifname2ifindex(const char *name, vrf_id_t vrf_id)
     351             : {
     352           2 :         struct interface *ifp;
     353             : 
     354           2 :         return ((ifp = if_lookup_by_name(name, vrf_id)) != NULL)
     355             :                        ? ifp->ifindex
     356           2 :                        : IFINDEX_INTERNAL;
     357             : }
     358             : 
     359             : /* Interface existence check by interface name. */
     360          40 : struct interface *if_lookup_by_name(const char *name, vrf_id_t vrf_id)
     361             : {
     362          40 :         struct vrf *vrf = vrf_lookup_by_id(vrf_id);
     363          40 :         struct interface if_tmp;
     364             : 
     365          40 :         if (!vrf || !name
     366          40 :             || strnlen(name, INTERFACE_NAMSIZ) == INTERFACE_NAMSIZ)
     367             :                 return NULL;
     368             : 
     369          40 :         strlcpy(if_tmp.name, name, sizeof(if_tmp.name));
     370          40 :         return RB_FIND(if_name_head, &vrf->ifaces_by_name, &if_tmp);
     371             : }
     372             : 
     373          32 : struct interface *if_lookup_by_name_vrf(const char *name, struct vrf *vrf)
     374             : {
     375          32 :         struct interface if_tmp;
     376             : 
     377          32 :         if (!name || strnlen(name, INTERFACE_NAMSIZ) == INTERFACE_NAMSIZ)
     378             :                 return NULL;
     379             : 
     380          32 :         strlcpy(if_tmp.name, name, sizeof(if_tmp.name));
     381          32 :         return RB_FIND(if_name_head, &vrf->ifaces_by_name, &if_tmp);
     382             : }
     383             : 
     384          32 : static struct interface *if_lookup_by_name_all_vrf(const char *name)
     385             : {
     386          32 :         struct vrf *vrf;
     387          32 :         struct interface *ifp;
     388             : 
     389          32 :         if (!name || strnlen(name, INTERFACE_NAMSIZ) == INTERFACE_NAMSIZ)
     390             :                 return NULL;
     391             : 
     392          80 :         RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
     393          32 :                 ifp = if_lookup_by_name_vrf(name, vrf);
     394          32 :                 if (ifp)
     395          16 :                         return ifp;
     396             :         }
     397             : 
     398             :         return NULL;
     399             : }
     400             : 
     401         153 : static struct interface *if_lookup_by_index_all_vrf(ifindex_t ifindex)
     402             : {
     403         153 :         struct vrf *vrf;
     404         153 :         struct interface *ifp;
     405             : 
     406         153 :         if (ifindex == IFINDEX_INTERNAL)
     407             :                 return NULL;
     408             : 
     409         306 :         RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id) {
     410         153 :                 ifp = if_lookup_by_ifindex(ifindex, vrf->vrf_id);
     411         153 :                 if (ifp)
     412         153 :                         return ifp;
     413             :         }
     414             : 
     415             :         return NULL;
     416             : }
     417             : 
     418             : /* Lookup interface by IP address.
     419             :  *
     420             :  * supersedes if_lookup_exact_address(), which didn't care about up/down
     421             :  * state.  but all users we have either only care if the address is local
     422             :  * (=> use if_address_is_local() please), or care about UP interfaces before
     423             :  * anything else
     424             :  *
     425             :  * to accept only UP interfaces, check if_is_up() on the returned ifp.
     426             :  */
     427           0 : struct interface *if_lookup_address_local(const void *src, int family,
     428             :                                           vrf_id_t vrf_id)
     429             : {
     430           0 :         struct vrf *vrf = vrf_lookup_by_id(vrf_id);
     431           0 :         struct listnode *cnode;
     432           0 :         struct interface *ifp, *best_down = NULL;
     433           0 :         struct prefix *p;
     434           0 :         struct connected *c;
     435             : 
     436           0 :         if (family != AF_INET && family != AF_INET6)
     437             :                 return NULL;
     438             : 
     439           0 :         FOR_ALL_INTERFACES (vrf, ifp) {
     440           0 :                 for (ALL_LIST_ELEMENTS_RO(ifp->connected, cnode, c)) {
     441           0 :                         p = c->address;
     442             : 
     443           0 :                         if (!p || p->family != family)
     444           0 :                                 continue;
     445             : 
     446           0 :                         if (family == AF_INET) {
     447           0 :                                 if (!IPV4_ADDR_SAME(&p->u.prefix4,
     448             :                                                     (struct in_addr *)src))
     449           0 :                                         continue;
     450           0 :                         } else if (family == AF_INET6) {
     451           0 :                                 if (!IPV6_ADDR_SAME(&p->u.prefix6,
     452             :                                                     (struct in6_addr *)src))
     453           0 :                                         continue;
     454             :                         }
     455             : 
     456           0 :                         if (if_is_up(ifp))
     457           0 :                                 return ifp;
     458           0 :                         if (!best_down)
     459           0 :                                 best_down = ifp;
     460             :                 }
     461             :         }
     462             :         return best_down;
     463             : }
     464             : 
     465             : /* Lookup interface by IP address. */
     466           0 : struct connected *if_lookup_address(const void *matchaddr, int family,
     467             :                                     vrf_id_t vrf_id)
     468             : {
     469           0 :         struct vrf *vrf = vrf_lookup_by_id(vrf_id);
     470           0 :         struct prefix addr;
     471           0 :         int bestlen = 0;
     472           0 :         struct listnode *cnode;
     473           0 :         struct interface *ifp;
     474           0 :         struct connected *c;
     475           0 :         struct connected *match;
     476             : 
     477           0 :         if (family == AF_INET) {
     478           0 :                 addr.family = AF_INET;
     479           0 :                 addr.u.prefix4 = *((struct in_addr *)matchaddr);
     480           0 :                 addr.prefixlen = IPV4_MAX_BITLEN;
     481           0 :         } else if (family == AF_INET6) {
     482           0 :                 addr.family = AF_INET6;
     483           0 :                 addr.u.prefix6 = *((struct in6_addr *)matchaddr);
     484           0 :                 addr.prefixlen = IPV6_MAX_BITLEN;
     485             :         } else
     486           0 :                 assert(!"Attempted lookup of family not supported");
     487             : 
     488           0 :         match = NULL;
     489             : 
     490           0 :         FOR_ALL_INTERFACES (vrf, ifp) {
     491           0 :                 for (ALL_LIST_ELEMENTS_RO(ifp->connected, cnode, c)) {
     492           0 :                         if (c->address && (c->address->family == AF_INET)
     493           0 :                             && prefix_match(CONNECTED_PREFIX(c), &addr)
     494           0 :                             && (c->address->prefixlen > bestlen)) {
     495           0 :                                 bestlen = c->address->prefixlen;
     496           0 :                                 match = c;
     497             :                         }
     498             :                 }
     499             :         }
     500           0 :         return match;
     501             : }
     502             : 
     503             : /* Lookup interface by prefix */
     504           0 : struct interface *if_lookup_prefix(const struct prefix *prefix, vrf_id_t vrf_id)
     505             : {
     506           0 :         struct vrf *vrf = vrf_lookup_by_id(vrf_id);
     507           0 :         struct listnode *cnode;
     508           0 :         struct interface *ifp;
     509           0 :         struct connected *c;
     510             : 
     511           0 :         FOR_ALL_INTERFACES (vrf, ifp) {
     512           0 :                 for (ALL_LIST_ELEMENTS_RO(ifp->connected, cnode, c)) {
     513           0 :                         if (prefix_cmp(c->address, prefix) == 0) {
     514           0 :                                 return ifp;
     515             :                         }
     516             :                 }
     517             :         }
     518             :         return NULL;
     519             : }
     520             : 
     521           0 : size_t if_lookup_by_hwaddr(const uint8_t *hw_addr, size_t addrsz,
     522             :                            struct interface ***result, vrf_id_t vrf_id)
     523             : {
     524           0 :         struct vrf *vrf = vrf_lookup_by_id(vrf_id);
     525             : 
     526           0 :         struct list *rs = list_new();
     527           0 :         struct interface *ifp;
     528             : 
     529           0 :         FOR_ALL_INTERFACES (vrf, ifp) {
     530           0 :                 if (ifp->hw_addr_len == (int)addrsz
     531           0 :                     && !memcmp(hw_addr, ifp->hw_addr, addrsz))
     532           0 :                         listnode_add(rs, ifp);
     533             :         }
     534             : 
     535           0 :         if (rs->count) {
     536           0 :                 *result = XCALLOC(MTYPE_TMP,
     537             :                                   sizeof(struct interface *) * rs->count);
     538           0 :                 list_to_array(rs, (void **)*result, rs->count);
     539             :         }
     540             : 
     541           0 :         int count = rs->count;
     542             : 
     543           0 :         list_delete(&rs);
     544             : 
     545           0 :         return count;
     546             : }
     547             : 
     548             : /* Get the VRF loopback interface, i.e. the loopback on the default VRF
     549             :  * or the VRF interface.
     550             :  */
     551           0 : struct interface *if_get_vrf_loopback(vrf_id_t vrf_id)
     552             : {
     553           0 :         struct interface *ifp = NULL;
     554           0 :         struct vrf *vrf = vrf_lookup_by_id(vrf_id);
     555             : 
     556           0 :         FOR_ALL_INTERFACES (vrf, ifp)
     557           0 :                 if (if_is_loopback(ifp))
     558           0 :                         return ifp;
     559             : 
     560             :         return NULL;
     561             : }
     562             : 
     563             : /* Get interface by name if given name interface doesn't exist create
     564             :    one. */
     565          32 : struct interface *if_get_by_name(const char *name, vrf_id_t vrf_id,
     566             :                                  const char *vrf_name)
     567             : {
     568          32 :         struct interface *ifp = NULL;
     569          32 :         struct vrf *vrf;
     570             : 
     571          32 :         switch (vrf_get_backend()) {
     572           0 :         case VRF_BACKEND_UNKNOWN:
     573             :         case VRF_BACKEND_NETNS:
     574           0 :                 vrf = vrf_get(vrf_id, vrf_name);
     575           0 :                 assert(vrf);
     576             : 
     577           0 :                 ifp = if_lookup_by_name_vrf(name, vrf);
     578           0 :                 if (ifp) {
     579             :                         /* If it came from the kernel or by way of zclient,
     580             :                          * believe it and update the ifp accordingly.
     581             :                          */
     582           0 :                         if (ifp->vrf->vrf_id != vrf_id && vrf_id != VRF_UNKNOWN)
     583           0 :                                 if_update_to_new_vrf(ifp, vrf_id);
     584             : 
     585           0 :                         return ifp;
     586             :                 }
     587             : 
     588             :                 break;
     589          32 :         case VRF_BACKEND_VRF_LITE:
     590          32 :                 ifp = if_lookup_by_name_all_vrf(name);
     591          32 :                 if (ifp) {
     592             :                         /* If it came from the kernel or by way of zclient,
     593             :                          * believe it and update the ifp accordingly.
     594             :                          */
     595          16 :                         if (ifp->vrf->vrf_id != vrf_id && vrf_id != VRF_UNKNOWN)
     596           0 :                                 if_update_to_new_vrf(ifp, vrf_id);
     597             : 
     598          16 :                         return ifp;
     599             :                 }
     600             : 
     601          16 :                 vrf = vrf_get(vrf_id, vrf_name);
     602          16 :                 assert(vrf);
     603             : 
     604             :                 break;
     605             :         default:
     606             :                 return NULL;
     607             :         }
     608             : 
     609          16 :         return if_create_name(name, vrf);
     610             : }
     611             : 
     612          59 : int if_set_index(struct interface *ifp, ifindex_t ifindex)
     613             : {
     614          59 :         if (ifp->ifindex == ifindex)
     615             :                 return 0;
     616             : 
     617             :         /*
     618             :          * If there is already an interface with this ifindex, we will collide
     619             :          * on insertion, so don't even try.
     620             :          */
     621          16 :         if (if_lookup_by_ifindex(ifindex, ifp->vrf->vrf_id))
     622             :                 return -1;
     623             : 
     624          16 :         if (ifp->ifindex != IFINDEX_INTERNAL)
     625           0 :                 IFINDEX_RB_REMOVE(ifp->vrf, ifp);
     626             : 
     627          16 :         ifp->ifindex = ifindex;
     628             : 
     629          16 :         if (ifp->ifindex != IFINDEX_INTERNAL) {
     630             :                 /*
     631             :                  * This should never happen, since we checked if there was
     632             :                  * already an interface with the desired ifindex at the top of
     633             :                  * the function. Nevertheless.
     634             :                  */
     635          16 :                 if (IFINDEX_RB_INSERT(ifp->vrf, ifp))
     636           0 :                         return -1;
     637             :         }
     638             : 
     639             :         return 0;
     640             : }
     641             : 
     642          16 : static void if_set_name(struct interface *ifp, const char *name)
     643             : {
     644          16 :         if (if_cmp_name_func(ifp->name, name) == 0)
     645             :                 return;
     646             : 
     647          16 :         if (ifp->name[0] != '\0')
     648           0 :                 IFNAME_RB_REMOVE(ifp->vrf, ifp);
     649             : 
     650          16 :         strlcpy(ifp->name, name, sizeof(ifp->name));
     651             : 
     652          16 :         if (ifp->name[0] != '\0')
     653          16 :                 IFNAME_RB_INSERT(ifp->vrf, ifp);
     654             : }
     655             : 
     656             : /* Does interface up ? */
     657           0 : int if_is_up(const struct interface *ifp)
     658             : {
     659           0 :         return ifp->flags & IFF_UP;
     660             : }
     661             : 
     662             : /* Is interface running? */
     663           0 : int if_is_running(const struct interface *ifp)
     664             : {
     665           0 :         return ifp->flags & IFF_RUNNING;
     666             : }
     667             : 
     668             : /* Is the interface operative, eg. either UP & RUNNING
     669             :    or UP & !ZEBRA_INTERFACE_LINK_DETECTION and
     670             :    if ptm checking is enabled, then ptm check has passed */
     671         167 : int if_is_operative(const struct interface *ifp)
     672             : {
     673         167 :         return ((ifp->flags & IFF_UP)
     674         167 :                 && (((ifp->flags & IFF_RUNNING)
     675         159 :                      && (ifp->ptm_status || !ifp->ptm_enable))
     676           8 :                     || !CHECK_FLAG(ifp->status,
     677             :                                    ZEBRA_INTERFACE_LINKDETECTION)));
     678             : }
     679             : 
     680             : /* Is the interface operative, eg. either UP & RUNNING
     681             :    or UP & !ZEBRA_INTERFACE_LINK_DETECTION, without PTM check */
     682          14 : int if_is_no_ptm_operative(const struct interface *ifp)
     683             : {
     684          14 :         return ((ifp->flags & IFF_UP)
     685          14 :                 && ((ifp->flags & IFF_RUNNING)
     686           7 :                     || !CHECK_FLAG(ifp->status,
     687             :                                    ZEBRA_INTERFACE_LINKDETECTION)));
     688             : }
     689             : 
     690             : /* Is this loopback interface ? */
     691         107 : int if_is_loopback_exact(const struct interface *ifp)
     692             : {
     693             :         /* XXX: Do this better, eg what if IFF_WHATEVER means X on platform M
     694             :          * but Y on platform N?
     695             :          */
     696         107 :         return (ifp->flags & (IFF_LOOPBACK | IFF_NOXMIT | IFF_VIRTUAL));
     697             : }
     698             : 
     699             : /* Check interface is VRF */
     700          88 : int if_is_vrf(const struct interface *ifp)
     701             : {
     702          88 :         return CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_VRF_LOOPBACK);
     703             : }
     704             : 
     705             : /* Should this interface be treated as a loopback? */
     706         107 : bool if_is_loopback(const struct interface *ifp)
     707             : {
     708         107 :         if (if_is_loopback_exact(ifp) || if_is_vrf(ifp))
     709          19 :                 return true;
     710             : 
     711             :         return false;
     712             : }
     713             : 
     714             : /* Does this interface support broadcast ? */
     715           0 : int if_is_broadcast(const struct interface *ifp)
     716             : {
     717           0 :         return ifp->flags & IFF_BROADCAST;
     718             : }
     719             : 
     720             : /* Does this interface support pointopoint ? */
     721           2 : int if_is_pointopoint(const struct interface *ifp)
     722             : {
     723           2 :         return ifp->flags & IFF_POINTOPOINT;
     724             : }
     725             : 
     726             : /* Does this interface support multicast ? */
     727           0 : int if_is_multicast(const struct interface *ifp)
     728             : {
     729           0 :         return ifp->flags & IFF_MULTICAST;
     730             : }
     731             : 
     732             : /* Printout flag information into log */
     733           0 : const char *if_flag_dump(unsigned long flag)
     734             : {
     735           0 :         int separator = 0;
     736           0 :         static char logbuf[BUFSIZ];
     737             : 
     738             : #define IFF_OUT_LOG(X, STR)                                                    \
     739             :         if (flag & (X)) {                                                      \
     740             :                 if (separator)                                                 \
     741             :                         strlcat(logbuf, ",", sizeof(logbuf));                  \
     742             :                 else                                                           \
     743             :                         separator = 1;                                         \
     744             :                 strlcat(logbuf, STR, sizeof(logbuf));                          \
     745             :         }
     746             : 
     747           0 :         strlcpy(logbuf, "<", BUFSIZ);
     748           0 :         IFF_OUT_LOG(IFF_UP, "UP");
     749           0 :         IFF_OUT_LOG(IFF_BROADCAST, "BROADCAST");
     750           0 :         IFF_OUT_LOG(IFF_DEBUG, "DEBUG");
     751           0 :         IFF_OUT_LOG(IFF_LOOPBACK, "LOOPBACK");
     752           0 :         IFF_OUT_LOG(IFF_POINTOPOINT, "POINTOPOINT");
     753           0 :         IFF_OUT_LOG(IFF_NOTRAILERS, "NOTRAILERS");
     754           0 :         IFF_OUT_LOG(IFF_RUNNING, "RUNNING");
     755           0 :         IFF_OUT_LOG(IFF_NOARP, "NOARP");
     756           0 :         IFF_OUT_LOG(IFF_PROMISC, "PROMISC");
     757           0 :         IFF_OUT_LOG(IFF_ALLMULTI, "ALLMULTI");
     758           0 :         IFF_OUT_LOG(IFF_OACTIVE, "OACTIVE");
     759           0 :         IFF_OUT_LOG(IFF_SIMPLEX, "SIMPLEX");
     760           0 :         IFF_OUT_LOG(IFF_LINK0, "LINK0");
     761           0 :         IFF_OUT_LOG(IFF_LINK1, "LINK1");
     762           0 :         IFF_OUT_LOG(IFF_LINK2, "LINK2");
     763           0 :         IFF_OUT_LOG(IFF_MULTICAST, "MULTICAST");
     764           0 :         IFF_OUT_LOG(IFF_NOXMIT, "NOXMIT");
     765           0 :         IFF_OUT_LOG(IFF_NORTEXCH, "NORTEXCH");
     766           0 :         IFF_OUT_LOG(IFF_VIRTUAL, "VIRTUAL");
     767           0 :         IFF_OUT_LOG(IFF_IPV4, "IPv4");
     768           0 :         IFF_OUT_LOG(IFF_IPV6, "IPv6");
     769             : 
     770           0 :         strlcat(logbuf, ">", sizeof(logbuf));
     771             : 
     772           0 :         return logbuf;
     773             : #undef IFF_OUT_LOG
     774             : }
     775             : 
     776             : /* For debugging */
     777           0 : static void if_dump(const struct interface *ifp)
     778             : {
     779           0 :         struct listnode *node;
     780           0 :         struct connected *c __attribute__((unused));
     781             : 
     782           0 :         for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, c))
     783           0 :                 zlog_info(
     784             :                         "Interface %s vrf %s(%u) index %d metric %d mtu %d mtu6 %d %s",
     785             :                         ifp->name, ifp->vrf->name, ifp->vrf->vrf_id,
     786             :                         ifp->ifindex, ifp->metric, ifp->mtu, ifp->mtu6,
     787             :                         if_flag_dump(ifp->flags));
     788           0 : }
     789             : 
     790             : /* Interface printing for all interface. */
     791           0 : void if_dump_all(void)
     792             : {
     793           0 :         struct vrf *vrf;
     794           0 :         void *ifp;
     795             : 
     796           0 :         RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id)
     797           0 :                 FOR_ALL_INTERFACES (vrf, ifp)
     798           0 :                         if_dump(ifp);
     799           0 : }
     800             : 
     801             : /* Allocate connected structure. */
     802          40 : struct connected *connected_new(void)
     803             : {
     804          40 :         return XCALLOC(MTYPE_CONNECTED, sizeof(struct connected));
     805             : }
     806             : 
     807             : /* Allocate nbr connected structure. */
     808           0 : struct nbr_connected *nbr_connected_new(void)
     809             : {
     810           0 :         return XCALLOC(MTYPE_NBR_CONNECTED, sizeof(struct nbr_connected));
     811             : }
     812             : 
     813             : /* Free connected structure. */
     814          40 : void connected_free(struct connected **connected)
     815             : {
     816          40 :         struct connected *ptr = *connected;
     817             : 
     818          40 :         prefix_free(&ptr->address);
     819          40 :         prefix_free(&ptr->destination);
     820             : 
     821          40 :         XFREE(MTYPE_CONNECTED_LABEL, ptr->label);
     822             : 
     823          40 :         XFREE(MTYPE_CONNECTED, ptr);
     824          40 :         *connected = NULL;
     825          40 : }
     826             : 
     827             : /* Free nbr connected structure. */
     828           0 : void nbr_connected_free(struct nbr_connected *connected)
     829             : {
     830           0 :         if (connected->address)
     831           0 :                 prefix_free(&connected->address);
     832             : 
     833           0 :         XFREE(MTYPE_NBR_CONNECTED, connected);
     834           0 : }
     835             : 
     836             : /* If same interface nbr address already exists... */
     837           0 : struct nbr_connected *nbr_connected_check(struct interface *ifp,
     838             :                                           struct prefix *p)
     839             : {
     840           0 :         struct nbr_connected *ifc;
     841           0 :         struct listnode *node;
     842             : 
     843           0 :         for (ALL_LIST_ELEMENTS_RO(ifp->nbr_connected, node, ifc))
     844           0 :                 if (prefix_same(ifc->address, p))
     845           0 :                         return ifc;
     846             : 
     847             :         return NULL;
     848             : }
     849             : 
     850             : /* Print if_addr structure. */
     851             : static void __attribute__((unused))
     852             : connected_log(struct connected *connected, char *str)
     853             : {
     854             :         struct prefix *p;
     855             :         struct interface *ifp;
     856             :         char logbuf[BUFSIZ];
     857             :         char buf[BUFSIZ];
     858             : 
     859             :         ifp = connected->ifp;
     860             :         p = connected->address;
     861             : 
     862             :         snprintf(logbuf, sizeof(logbuf), "%s interface %s vrf %s(%u) %s %pFX ",
     863             :                  str, ifp->name, ifp->vrf->name, ifp->vrf->vrf_id,
     864             :                  prefix_family_str(p), p);
     865             : 
     866             :         p = connected->destination;
     867             :         if (p) {
     868             :                 strlcat(logbuf, inet_ntop(p->family, &p->u.prefix, buf, BUFSIZ),
     869             :                         BUFSIZ);
     870             :         }
     871             :         zlog_info("%s", logbuf);
     872             : }
     873             : 
     874             : /* Print if_addr structure. */
     875             : static void __attribute__((unused))
     876             : nbr_connected_log(struct nbr_connected *connected, char *str)
     877             : {
     878             :         struct prefix *p;
     879             :         struct interface *ifp;
     880             :         char logbuf[BUFSIZ];
     881             : 
     882             :         ifp = connected->ifp;
     883             :         p = connected->address;
     884             : 
     885             :         snprintf(logbuf, sizeof(logbuf), "%s interface %s %s %pFX ", str,
     886             :                  ifp->name, prefix_family_str(p), p);
     887             : 
     888             :         zlog_info("%s", logbuf);
     889             : }
     890             : 
     891             : /* If two connected address has same prefix return 1. */
     892          34 : static int connected_same_prefix(const struct prefix *p1,
     893             :                                  const struct prefix *p2)
     894             : {
     895          34 :         if (p1->family == p2->family) {
     896          23 :                 if (p1->family == AF_INET
     897           5 :                     && IPV4_ADDR_SAME(&p1->u.prefix4, &p2->u.prefix4))
     898             :                         return 1;
     899          18 :                 if (p1->family == AF_INET6
     900          18 :                     && IPV6_ADDR_SAME(&p1->u.prefix6, &p2->u.prefix6))
     901             :                         return 1;
     902             :         }
     903             :         return 0;
     904             : }
     905             : 
     906             : /* count the number of connected addresses that are in the given family */
     907           0 : unsigned int connected_count_by_family(struct interface *ifp, int family)
     908             : {
     909           0 :         struct listnode *cnode;
     910           0 :         struct connected *connected;
     911           0 :         unsigned int cnt = 0;
     912             : 
     913           0 :         for (ALL_LIST_ELEMENTS_RO(ifp->connected, cnode, connected))
     914           0 :                 if (connected->address->family == family)
     915           0 :                         cnt++;
     916             : 
     917           0 :         return cnt;
     918             : }
     919             : 
     920          35 : struct connected *connected_lookup_prefix_exact(struct interface *ifp,
     921             :                                                 const struct prefix *p)
     922             : {
     923          35 :         struct listnode *node;
     924          35 :         struct listnode *next;
     925          35 :         struct connected *ifc;
     926             : 
     927          87 :         for (node = listhead(ifp->connected); node; node = next) {
     928          30 :                 ifc = listgetdata(node);
     929          30 :                 next = node->next;
     930             : 
     931          30 :                 if (connected_same_prefix(ifc->address, p))
     932          13 :                         return ifc;
     933             :         }
     934             :         return NULL;
     935             : }
     936             : 
     937           4 : struct connected *connected_delete_by_prefix(struct interface *ifp,
     938             :                                              struct prefix *p)
     939             : {
     940           4 :         struct listnode *node;
     941           4 :         struct listnode *next;
     942           4 :         struct connected *ifc;
     943             : 
     944             :         /* In case of same prefix come, replace it with new one. */
     945           8 :         for (node = listhead(ifp->connected); node; node = next) {
     946           4 :                 ifc = listgetdata(node);
     947           4 :                 next = node->next;
     948             : 
     949           4 :                 if (connected_same_prefix(ifc->address, p)) {
     950           4 :                         listnode_delete(ifp->connected, ifc);
     951           4 :                         return ifc;
     952             :                 }
     953             :         }
     954             :         return NULL;
     955             : }
     956             : 
     957             : /* Find the address on our side that will be used when packets
     958             :    are sent to dst. */
     959           0 : struct connected *connected_lookup_prefix(struct interface *ifp,
     960             :                                           const struct prefix *addr)
     961             : {
     962           0 :         struct listnode *cnode;
     963           0 :         struct connected *c;
     964           0 :         struct connected *match;
     965             : 
     966           0 :         match = NULL;
     967             : 
     968           0 :         for (ALL_LIST_ELEMENTS_RO(ifp->connected, cnode, c)) {
     969           0 :                 if (c->address && (c->address->family == addr->family)
     970           0 :                     && prefix_match(CONNECTED_PREFIX(c), addr)
     971           0 :                     && (!match
     972           0 :                         || (c->address->prefixlen > match->address->prefixlen)))
     973           0 :                         match = c;
     974             :         }
     975           0 :         return match;
     976             : }
     977             : 
     978          22 : struct connected *connected_add_by_prefix(struct interface *ifp,
     979             :                                           struct prefix *p,
     980             :                                           struct prefix *destination)
     981             : {
     982          22 :         struct connected *ifc;
     983             : 
     984             :         /* Allocate new connected address. */
     985          22 :         ifc = connected_new();
     986          22 :         ifc->ifp = ifp;
     987             : 
     988             :         /* Fetch interface address */
     989          22 :         ifc->address = prefix_new();
     990          22 :         memcpy(ifc->address, p, sizeof(struct prefix));
     991             : 
     992             :         /* Fetch dest address */
     993          22 :         if (destination) {
     994           0 :                 ifc->destination = prefix_new();
     995           0 :                 memcpy(ifc->destination, destination, sizeof(struct prefix));
     996             :         }
     997             : 
     998             :         /* Add connected address to the interface. */
     999          22 :         listnode_add(ifp->connected, ifc);
    1000          22 :         return ifc;
    1001             : }
    1002             : 
    1003          33 : struct connected *connected_get_linklocal(struct interface *ifp)
    1004             : {
    1005          33 :         struct listnode *n;
    1006          33 :         struct connected *c = NULL;
    1007             : 
    1008         110 :         for (ALL_LIST_ELEMENTS_RO(ifp->connected, n, c)) {
    1009          77 :                 if (c->address->family == AF_INET6
    1010          66 :                     && IN6_IS_ADDR_LINKLOCAL(&c->address->u.prefix6))
    1011             :                         break;
    1012             :         }
    1013          33 :         return c;
    1014             : }
    1015             : 
    1016           4 : void if_terminate(struct vrf *vrf)
    1017             : {
    1018           4 :         struct interface *ifp;
    1019             : 
    1020          20 :         while (!RB_EMPTY(if_name_head, &vrf->ifaces_by_name)) {
    1021          16 :                 ifp = RB_ROOT(if_name_head, &vrf->ifaces_by_name);
    1022             : 
    1023          16 :                 if (ifp->node) {
    1024           8 :                         ifp->node->info = NULL;
    1025           8 :                         route_unlock_node(ifp->node);
    1026           8 :                         ifp->node = NULL;
    1027             :                 }
    1028          16 :                 if_delete(&ifp);
    1029             :         }
    1030           4 : }
    1031             : 
    1032           0 : const char *if_link_type_str(enum zebra_link_type llt)
    1033             : {
    1034           0 :         switch (llt) {
    1035             : #define llts(T,S) case (T): return (S)
    1036             :                 llts(ZEBRA_LLT_UNKNOWN, "Unknown");
    1037           0 :                 llts(ZEBRA_LLT_ETHER, "Ethernet");
    1038           0 :                 llts(ZEBRA_LLT_EETHER, "Experimental Ethernet");
    1039           0 :                 llts(ZEBRA_LLT_AX25, "AX.25 Level 2");
    1040           0 :                 llts(ZEBRA_LLT_PRONET, "PROnet token ring");
    1041           0 :                 llts(ZEBRA_LLT_IEEE802, "IEEE 802.2 Ethernet/TR/TB");
    1042           0 :                 llts(ZEBRA_LLT_ARCNET, "ARCnet");
    1043           0 :                 llts(ZEBRA_LLT_APPLETLK, "AppleTalk");
    1044           0 :                 llts(ZEBRA_LLT_DLCI, "Frame Relay DLCI");
    1045           0 :                 llts(ZEBRA_LLT_ATM, "ATM");
    1046           0 :                 llts(ZEBRA_LLT_METRICOM, "Metricom STRIP");
    1047           0 :                 llts(ZEBRA_LLT_IEEE1394, "IEEE 1394 IPv4");
    1048           0 :                 llts(ZEBRA_LLT_EUI64, "EUI-64");
    1049           0 :                 llts(ZEBRA_LLT_INFINIBAND, "InfiniBand");
    1050           0 :                 llts(ZEBRA_LLT_SLIP, "SLIP");
    1051           0 :                 llts(ZEBRA_LLT_CSLIP, "Compressed SLIP");
    1052           0 :                 llts(ZEBRA_LLT_SLIP6, "SLIPv6");
    1053           0 :                 llts(ZEBRA_LLT_CSLIP6, "Compressed SLIPv6");
    1054           0 :                 llts(ZEBRA_LLT_RSRVD, "Reserved");
    1055           0 :                 llts(ZEBRA_LLT_ADAPT, "Adapt");
    1056           0 :                 llts(ZEBRA_LLT_ROSE, "ROSE packet radio");
    1057           0 :                 llts(ZEBRA_LLT_X25, "CCITT X.25");
    1058           0 :                 llts(ZEBRA_LLT_PPP, "PPP");
    1059           0 :                 llts(ZEBRA_LLT_CHDLC, "Cisco HDLC");
    1060           0 :                 llts(ZEBRA_LLT_RAWHDLC, "Raw HDLC");
    1061           0 :                 llts(ZEBRA_LLT_LAPB, "LAPB");
    1062           0 :                 llts(ZEBRA_LLT_IPIP, "IPIP Tunnel");
    1063           0 :                 llts(ZEBRA_LLT_IPIP6, "IPIP6 Tunnel");
    1064           0 :                 llts(ZEBRA_LLT_FRAD, "FRAD");
    1065           0 :                 llts(ZEBRA_LLT_SKIP, "SKIP vif");
    1066           0 :                 llts(ZEBRA_LLT_LOOPBACK, "Loopback");
    1067           0 :                 llts(ZEBRA_LLT_LOCALTLK, "Localtalk");
    1068           0 :                 llts(ZEBRA_LLT_FDDI, "FDDI");
    1069           0 :                 llts(ZEBRA_LLT_SIT, "IPv6-in-IPv4 SIT");
    1070           0 :                 llts(ZEBRA_LLT_IPDDP, "IP-in-DDP tunnel");
    1071           0 :                 llts(ZEBRA_LLT_IPGRE, "GRE over IP");
    1072           0 :                 llts(ZEBRA_LLT_IP6GRE, "GRE over IPv6");
    1073           0 :                 llts(ZEBRA_LLT_PIMREG, "PIMSM registration");
    1074           0 :                 llts(ZEBRA_LLT_HIPPI, "HiPPI");
    1075           0 :                 llts(ZEBRA_LLT_ECONET, "Acorn Econet");
    1076           0 :                 llts(ZEBRA_LLT_IRDA, "IrDA");
    1077           0 :                 llts(ZEBRA_LLT_FCPP, "Fibre-Channel PtP");
    1078           0 :                 llts(ZEBRA_LLT_FCAL, "Fibre-Channel Arbitrated Loop");
    1079           0 :                 llts(ZEBRA_LLT_FCPL, "Fibre-Channel Public Loop");
    1080           0 :                 llts(ZEBRA_LLT_FCFABRIC, "Fibre-Channel Fabric");
    1081           0 :                 llts(ZEBRA_LLT_IEEE802_TR, "IEEE 802.2 Token Ring");
    1082           0 :                 llts(ZEBRA_LLT_IEEE80211, "IEEE 802.11");
    1083           0 :                 llts(ZEBRA_LLT_IEEE80211_RADIOTAP, "IEEE 802.11 Radiotap");
    1084           0 :                 llts(ZEBRA_LLT_IEEE802154, "IEEE 802.15.4");
    1085           0 :                 llts(ZEBRA_LLT_IEEE802154_PHY, "IEEE 802.15.4 Phy");
    1086             : #undef llts
    1087             :         }
    1088           0 :         return NULL;
    1089             : }
    1090             : 
    1091           0 : bool if_link_params_cmp(struct if_link_params *iflp1,
    1092             :                         struct if_link_params *iflp2)
    1093             : {
    1094           0 :         struct if_link_params iflp1_copy, iflp2_copy;
    1095             : 
    1096             :         /* Extended admin-groups in if_link_params contain pointers.
    1097             :          * They cannot be compared with memcpy.
    1098             :          * Make copies of if_link_params without ext. admin-groups
    1099             :          * and compare separately the ext. admin-groups.
    1100             :          */
    1101           0 :         memcpy(&iflp1_copy, iflp1, sizeof(struct if_link_params));
    1102           0 :         memset(&iflp1_copy.ext_admin_grp, 0, sizeof(struct admin_group));
    1103             : 
    1104           0 :         memcpy(&iflp2_copy, iflp2, sizeof(struct if_link_params));
    1105           0 :         memset(&iflp2_copy.ext_admin_grp, 0, sizeof(struct admin_group));
    1106             : 
    1107           0 :         if (memcmp(&iflp1_copy, &iflp2_copy, sizeof(struct if_link_params)))
    1108             :                 return false;
    1109             : 
    1110           0 :         if (!admin_group_cmp(&iflp1->ext_admin_grp, &iflp2->ext_admin_grp))
    1111             :                 return false;
    1112             : 
    1113             :         return true;
    1114             : }
    1115             : 
    1116           0 : void if_link_params_copy(struct if_link_params *dst, struct if_link_params *src)
    1117             : {
    1118           0 :         struct admin_group dst_ag;
    1119             : 
    1120             :         /* backup the admin_group structure that contains a pointer */
    1121           0 :         memcpy(&dst_ag, &dst->ext_admin_grp, sizeof(struct admin_group));
    1122             :         /* copy the if_link_params structure */
    1123           0 :         memcpy(dst, src, sizeof(struct if_link_params));
    1124             :         /* restore the admin_group structure */
    1125           0 :         memcpy(&dst->ext_admin_grp, &dst_ag, sizeof(struct admin_group));
    1126             :         /* copy src->ext_admin_grp data to dst->ext_admin_grp data memory */
    1127           0 :         admin_group_copy(&dst->ext_admin_grp, &src->ext_admin_grp);
    1128           0 : }
    1129             : 
    1130           0 : struct if_link_params *if_link_params_get(struct interface *ifp)
    1131             : {
    1132           0 :         return ifp->link_params;
    1133             : }
    1134             : 
    1135           0 : struct if_link_params *if_link_params_enable(struct interface *ifp)
    1136             : {
    1137           0 :         struct if_link_params *iflp;
    1138           0 :         int i;
    1139             : 
    1140           0 :         iflp = if_link_params_init(ifp);
    1141             : 
    1142             :         /* Compute default bandwidth based on interface */
    1143           0 :         iflp->default_bw =
    1144           0 :                 ((ifp->bandwidth ? ifp->bandwidth : DEFAULT_BANDWIDTH)
    1145           0 :                  * TE_MEGA_BIT / TE_BYTE);
    1146             : 
    1147             :         /* Set Max, Reservable and Unreserved Bandwidth */
    1148           0 :         iflp->max_bw = iflp->default_bw;
    1149           0 :         iflp->max_rsv_bw = iflp->default_bw;
    1150           0 :         for (i = 0; i < MAX_CLASS_TYPE; i++)
    1151           0 :                 iflp->unrsv_bw[i] = iflp->default_bw;
    1152             : 
    1153             :         /* Update Link parameters status */
    1154           0 :         iflp->lp_status = LP_MAX_BW | LP_MAX_RSV_BW | LP_UNRSV_BW;
    1155             : 
    1156             :         /* Set TE metric equal to standard metric only if it is set */
    1157           0 :         if (ifp->metric != 0) {
    1158           0 :                 iflp->te_metric = ifp->metric;
    1159           0 :                 iflp->lp_status |= LP_TE_METRIC;
    1160             :         }
    1161             : 
    1162             :         /* Finally attach newly created Link Parameters */
    1163           0 :         ifp->link_params = iflp;
    1164             : 
    1165           0 :         return iflp;
    1166             : }
    1167             : 
    1168           0 : struct if_link_params *if_link_params_init(struct interface *ifp)
    1169             : {
    1170           0 :         struct if_link_params *iflp = if_link_params_get(ifp);
    1171             : 
    1172           0 :         if (iflp)
    1173             :                 return iflp;
    1174             : 
    1175           0 :         iflp = XCALLOC(MTYPE_IF_LINK_PARAMS, sizeof(struct if_link_params));
    1176             : 
    1177           0 :         admin_group_init(&iflp->ext_admin_grp);
    1178             : 
    1179           0 :         ifp->link_params = iflp;
    1180             : 
    1181           0 :         return iflp;
    1182             : }
    1183             : 
    1184          16 : void if_link_params_free(struct interface *ifp)
    1185             : {
    1186          16 :         if (!ifp->link_params)
    1187             :                 return;
    1188             : 
    1189           0 :         admin_group_term(&ifp->link_params->ext_admin_grp);
    1190           0 :         XFREE(MTYPE_IF_LINK_PARAMS, ifp->link_params);
    1191             : }
    1192             : 
    1193             : /* ----------- CLI commands ----------- */
    1194             : 
    1195             : /* Guess the VRF of an interface. */
    1196           0 : static int vrfname_by_ifname(const char *ifname, const char **vrfname)
    1197             : {
    1198           0 :         struct vrf *vrf;
    1199           0 :         struct interface *ifp;
    1200           0 :         int count = 0;
    1201             : 
    1202           0 :         RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
    1203           0 :                 FOR_ALL_INTERFACES (vrf, ifp) {
    1204           0 :                         if (strmatch(ifp->name, ifname)) {
    1205           0 :                                 *vrfname = vrf->name;
    1206           0 :                                 count++;
    1207             :                         }
    1208             :                 }
    1209             :         }
    1210             : 
    1211           0 :         return count;
    1212             : }
    1213             : 
    1214             : /*
    1215             :  * XPath: /frr-interface:lib/interface
    1216             :  */
    1217           0 : DEFPY_YANG_NOSH (interface,
    1218             :        interface_cmd,
    1219             :        "interface IFNAME [vrf NAME$vrf_name]",
    1220             :        "Select an interface to configure\n"
    1221             :        "Interface's name\n"
    1222             :        VRF_CMD_HELP_STR)
    1223             : {
    1224           0 :         char xpath_list[XPATH_MAXLEN];
    1225           0 :         struct interface *ifp;
    1226           0 :         struct vrf *vrf;
    1227           0 :         int ret, count;
    1228             : 
    1229           0 :         if (vrf_is_backend_netns()) {
    1230             :                 /*
    1231             :                  * For backward compatibility, if the VRF name is not specified
    1232             :                  * and there is exactly one interface with this name in the
    1233             :                  * system, use its VRF. Otherwise fallback to the default VRF.
    1234             :                  */
    1235           0 :                 if (!vrf_name) {
    1236           0 :                         count = vrfname_by_ifname(ifname, &vrf_name);
    1237           0 :                         if (count != 1)
    1238           0 :                                 vrf_name = VRF_DEFAULT_NAME;
    1239             :                 }
    1240             : 
    1241           0 :                 snprintf(xpath_list, XPATH_MAXLEN,
    1242             :                          "/frr-interface:lib/interface[name='%s:%s']", vrf_name,
    1243             :                          ifname);
    1244             :         } else {
    1245           0 :                 snprintf(xpath_list, XPATH_MAXLEN,
    1246             :                          "/frr-interface:lib/interface[name='%s']", ifname);
    1247             :         }
    1248             : 
    1249           0 :         nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL);
    1250           0 :         ret = nb_cli_apply_changes_clear_pending(vty, "%s", xpath_list);
    1251           0 :         if (ret == CMD_SUCCESS) {
    1252           0 :                 VTY_PUSH_XPATH(INTERFACE_NODE, xpath_list);
    1253             : 
    1254             :                 /*
    1255             :                  * For backward compatibility with old commands we still need
    1256             :                  * to use the qobj infrastructure. This can be removed once
    1257             :                  * all interface-level commands are converted to the new
    1258             :                  * northbound model.
    1259             :                  */
    1260           0 :                 if (vrf_is_backend_netns()) {
    1261           0 :                         vrf = vrf_lookup_by_name(vrf_name);
    1262           0 :                         if (vrf)
    1263           0 :                                 ifp = if_lookup_by_name_vrf(ifname, vrf);
    1264             :                         else
    1265             :                                 ifp = NULL;
    1266             :                 } else {
    1267           0 :                         ifp = if_lookup_by_name_all_vrf(ifname);
    1268             :                 }
    1269           0 :                 if (ifp)
    1270           0 :                         VTY_PUSH_CONTEXT(INTERFACE_NODE, ifp);
    1271             :         }
    1272             : 
    1273             :         return ret;
    1274             : }
    1275             : 
    1276           0 : DEFPY_YANG (no_interface,
    1277             :        no_interface_cmd,
    1278             :        "no interface IFNAME [vrf NAME$vrf_name]",
    1279             :        NO_STR
    1280             :        "Delete a pseudo interface's configuration\n"
    1281             :        "Interface's name\n"
    1282             :        VRF_CMD_HELP_STR)
    1283             : {
    1284           0 :         char xpath_list[XPATH_MAXLEN];
    1285           0 :         int count;
    1286             : 
    1287           0 :         if (vrf_is_backend_netns()) {
    1288             :                 /*
    1289             :                  * For backward compatibility, if the VRF name is not specified
    1290             :                  * and there is exactly one interface with this name in the
    1291             :                  * system, use its VRF. Otherwise fallback to the default VRF.
    1292             :                  */
    1293           0 :                 if (!vrf_name) {
    1294           0 :                         count = vrfname_by_ifname(ifname, &vrf_name);
    1295           0 :                         if (count != 1)
    1296           0 :                                 vrf_name = VRF_DEFAULT_NAME;
    1297             :                 }
    1298             : 
    1299           0 :                 snprintf(xpath_list, XPATH_MAXLEN,
    1300             :                          "/frr-interface:lib/interface[name='%s:%s']", vrf_name,
    1301             :                          ifname);
    1302             :         } else {
    1303           0 :                 snprintf(xpath_list, XPATH_MAXLEN,
    1304             :                          "/frr-interface:lib/interface[name='%s']", ifname);
    1305             :         }
    1306             : 
    1307           0 :         nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
    1308             : 
    1309           0 :         return nb_cli_apply_changes(vty, "%s", xpath_list);
    1310             : }
    1311             : 
    1312           0 : static void netns_ifname_split(const char *xpath, char *ifname, char *vrfname)
    1313             : {
    1314           0 :         char *delim;
    1315           0 :         int len;
    1316             : 
    1317           0 :         assert(vrf_is_backend_netns());
    1318             : 
    1319           0 :         delim = strchr(xpath, ':');
    1320           0 :         assert(delim);
    1321             : 
    1322           0 :         len = delim - xpath;
    1323           0 :         memcpy(vrfname, xpath, len);
    1324           0 :         vrfname[len] = 0;
    1325             : 
    1326           0 :         strlcpy(ifname, delim + 1, XPATH_MAXLEN);
    1327           0 : }
    1328             : 
    1329           0 : static void cli_show_interface(struct vty *vty, const struct lyd_node *dnode,
    1330             :                                bool show_defaults)
    1331             : {
    1332           0 :         vty_out(vty, "!\n");
    1333             : 
    1334           0 :         if (vrf_is_backend_netns()) {
    1335           0 :                 char ifname[XPATH_MAXLEN];
    1336           0 :                 char vrfname[XPATH_MAXLEN];
    1337             : 
    1338           0 :                 netns_ifname_split(yang_dnode_get_string(dnode, "./name"),
    1339             :                                    ifname, vrfname);
    1340             : 
    1341           0 :                 vty_out(vty, "interface %s", ifname);
    1342           0 :                 if (!strmatch(vrfname, VRF_DEFAULT_NAME))
    1343           0 :                         vty_out(vty, " vrf %s", vrfname);
    1344             :         } else {
    1345           0 :                 const char *ifname = yang_dnode_get_string(dnode, "./name");
    1346             : 
    1347           0 :                 vty_out(vty, "interface %s", ifname);
    1348             :         }
    1349             : 
    1350           0 :         vty_out(vty, "\n");
    1351           0 : }
    1352             : 
    1353           0 : static void cli_show_interface_end(struct vty *vty,
    1354             :                                    const struct lyd_node *dnode)
    1355             : {
    1356           0 :         vty_out(vty, "exit\n");
    1357           0 : }
    1358             : 
    1359           0 : void if_vty_config_start(struct vty *vty, struct interface *ifp)
    1360             : {
    1361           0 :         vty_frame(vty, "!\n");
    1362           0 :         vty_frame(vty, "interface %s", ifp->name);
    1363             : 
    1364           0 :         if (vrf_is_backend_netns() && strcmp(ifp->vrf->name, VRF_DEFAULT_NAME))
    1365           0 :                 vty_frame(vty, " vrf %s", ifp->vrf->name);
    1366             : 
    1367           0 :         vty_frame(vty, "\n");
    1368           0 : }
    1369             : 
    1370           0 : void if_vty_config_end(struct vty *vty)
    1371             : {
    1372           0 :         vty_endframe(vty, "exit\n!\n");
    1373           0 : }
    1374             : 
    1375             : /*
    1376             :  * XPath: /frr-interface:lib/interface/description
    1377             :  */
    1378           0 : DEFPY_YANG (interface_desc,
    1379             :        interface_desc_cmd,
    1380             :        "description LINE...",
    1381             :        "Interface specific description\n"
    1382             :        "Characters describing this interface\n")
    1383             : {
    1384           0 :         char *desc;
    1385           0 :         int ret;
    1386             : 
    1387           0 :         desc = argv_concat(argv, argc, 1);
    1388           0 :         nb_cli_enqueue_change(vty, "./description", NB_OP_MODIFY, desc);
    1389           0 :         ret = nb_cli_apply_changes(vty, NULL);
    1390           0 :         XFREE(MTYPE_TMP, desc);
    1391             : 
    1392           0 :         return ret;
    1393             : }
    1394             : 
    1395           0 : DEFPY_YANG  (no_interface_desc,
    1396             :         no_interface_desc_cmd,
    1397             :         "no description",
    1398             :         NO_STR
    1399             :         "Interface specific description\n")
    1400             : {
    1401           0 :         nb_cli_enqueue_change(vty, "./description", NB_OP_DESTROY, NULL);
    1402             : 
    1403           0 :         return nb_cli_apply_changes(vty, NULL);
    1404             : }
    1405             : 
    1406           0 : static void cli_show_interface_desc(struct vty *vty,
    1407             :                                     const struct lyd_node *dnode,
    1408             :                                     bool show_defaults)
    1409             : {
    1410           0 :         vty_out(vty, " description %s\n", yang_dnode_get_string(dnode, NULL));
    1411           0 : }
    1412             : 
    1413             : /* Interface autocomplete. */
    1414           0 : static void if_autocomplete(vector comps, struct cmd_token *token)
    1415             : {
    1416           0 :         struct interface *ifp;
    1417           0 :         struct vrf *vrf;
    1418             : 
    1419           0 :         RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
    1420           0 :                 FOR_ALL_INTERFACES (vrf, ifp) {
    1421           0 :                         vector_set(comps, XSTRDUP(MTYPE_COMPLETION, ifp->name));
    1422             :                 }
    1423             :         }
    1424           0 : }
    1425             : 
    1426             : static const struct cmd_variable_handler if_var_handlers[] = {
    1427             :         {/* "interface NAME" */
    1428             :          .varname = "interface",
    1429             :          .completions = if_autocomplete},
    1430             :         {.tokenname = "IFNAME", .completions = if_autocomplete},
    1431             :         {.tokenname = "INTERFACE", .completions = if_autocomplete},
    1432             :         {.completions = NULL}};
    1433             : 
    1434             : static struct cmd_node interface_node = {
    1435             :         .name = "interface",
    1436             :         .node = INTERFACE_NODE,
    1437             :         .parent_node = CONFIG_NODE,
    1438             :         .prompt = "%s(config-if)# ",
    1439             : };
    1440             : 
    1441           0 : static int if_config_write_single(const struct lyd_node *dnode, void *arg)
    1442             : {
    1443           0 :         nb_cli_show_dnode_cmds(arg, dnode, false);
    1444             : 
    1445           0 :         return YANG_ITER_CONTINUE;
    1446             : }
    1447             : 
    1448           0 : static int if_nb_config_write(struct vty *vty)
    1449             : {
    1450           0 :         yang_dnode_iterate(if_config_write_single, vty, running_config->dnode,
    1451             :                            "/frr-interface:lib/interface");
    1452           0 :         return 1;
    1453             : }
    1454             : 
    1455           4 : void if_cmd_init(int (*config_write)(struct vty *))
    1456             : {
    1457           4 :         cmd_variable_handler_register(if_var_handlers);
    1458             : 
    1459           4 :         interface_node.config_write = config_write;
    1460           4 :         install_node(&interface_node);
    1461             : 
    1462           4 :         install_element(CONFIG_NODE, &interface_cmd);
    1463           4 :         install_element(CONFIG_NODE, &no_interface_cmd);
    1464             : 
    1465           4 :         install_default(INTERFACE_NODE);
    1466           4 :         install_element(INTERFACE_NODE, &interface_desc_cmd);
    1467           4 :         install_element(INTERFACE_NODE, &no_interface_desc_cmd);
    1468           4 : }
    1469             : 
    1470           0 : void if_cmd_init_default(void)
    1471             : {
    1472           0 :         if_cmd_init(if_nb_config_write);
    1473           0 : }
    1474             : 
    1475             : /* ------- Northbound callbacks ------- */
    1476             : 
    1477             : /*
    1478             :  * XPath: /frr-interface:lib/interface
    1479             :  */
    1480           0 : static int lib_interface_create(struct nb_cb_create_args *args)
    1481             : {
    1482           0 :         const char *ifname;
    1483           0 :         struct interface *ifp;
    1484             : 
    1485           0 :         ifname = yang_dnode_get_string(args->dnode, "./name");
    1486             : 
    1487           0 :         switch (args->event) {
    1488           0 :         case NB_EV_VALIDATE:
    1489           0 :                 if (vrf_is_backend_netns()) {
    1490           0 :                         char ifname_ns[XPATH_MAXLEN];
    1491           0 :                         char vrfname_ns[XPATH_MAXLEN];
    1492             : 
    1493           0 :                         netns_ifname_split(ifname, ifname_ns, vrfname_ns);
    1494             : 
    1495           0 :                         if (strlen(ifname_ns) > 16) {
    1496           0 :                                 snprintf(
    1497             :                                         args->errmsg, args->errmsg_len,
    1498             :                                         "Maximum interface name length is 16 characters");
    1499           0 :                                 return NB_ERR_VALIDATION;
    1500             :                         }
    1501           0 :                         if (strlen(vrfname_ns) > 36) {
    1502           0 :                                 snprintf(
    1503             :                                         args->errmsg, args->errmsg_len,
    1504             :                                         "Maximum VRF name length is 36 characters");
    1505           0 :                                 return NB_ERR_VALIDATION;
    1506             :                         }
    1507             :                 } else {
    1508           0 :                         if (strlen(ifname) > 16) {
    1509           0 :                                 snprintf(
    1510             :                                         args->errmsg, args->errmsg_len,
    1511             :                                         "Maximum interface name length is 16 characters");
    1512           0 :                                 return NB_ERR_VALIDATION;
    1513             :                         }
    1514             :                 }
    1515             :                 break;
    1516             :         case NB_EV_PREPARE:
    1517             :         case NB_EV_ABORT:
    1518             :                 break;
    1519           0 :         case NB_EV_APPLY:
    1520           0 :                 if (vrf_is_backend_netns()) {
    1521           0 :                         char ifname_ns[XPATH_MAXLEN];
    1522           0 :                         char vrfname_ns[XPATH_MAXLEN];
    1523             : 
    1524           0 :                         netns_ifname_split(ifname, ifname_ns, vrfname_ns);
    1525             : 
    1526           0 :                         ifp = if_get_by_name(ifname_ns, VRF_UNKNOWN,
    1527             :                                              vrfname_ns);
    1528             :                 } else {
    1529           0 :                         ifp = if_get_by_name(ifname, VRF_UNKNOWN,
    1530             :                                              VRF_DEFAULT_NAME);
    1531             :                 }
    1532             : 
    1533           0 :                 ifp->configured = true;
    1534           0 :                 nb_running_set_entry(args->dnode, ifp);
    1535           0 :                 break;
    1536             :         }
    1537             : 
    1538             :         return NB_OK;
    1539             : }
    1540             : 
    1541           0 : static int lib_interface_destroy(struct nb_cb_destroy_args *args)
    1542             : {
    1543           0 :         struct interface *ifp;
    1544           0 :         struct vrf *vrf;
    1545             : 
    1546           0 :         switch (args->event) {
    1547           0 :         case NB_EV_VALIDATE:
    1548           0 :                 ifp = nb_running_get_entry(args->dnode, NULL, true);
    1549           0 :                 if (CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE)) {
    1550           0 :                         snprintf(args->errmsg, args->errmsg_len,
    1551             :                                  "only inactive interfaces can be deleted");
    1552           0 :                         return NB_ERR_VALIDATION;
    1553             :                 }
    1554             :                 break;
    1555             :         case NB_EV_PREPARE:
    1556             :         case NB_EV_ABORT:
    1557             :                 break;
    1558           0 :         case NB_EV_APPLY:
    1559           0 :                 ifp = nb_running_unset_entry(args->dnode);
    1560           0 :                 vrf = ifp->vrf;
    1561             : 
    1562           0 :                 ifp->configured = false;
    1563           0 :                 if_delete(&ifp);
    1564             : 
    1565           0 :                 if (!vrf_is_enabled(vrf))
    1566           0 :                         vrf_delete(vrf);
    1567             :                 break;
    1568             :         }
    1569             : 
    1570             :         return NB_OK;
    1571             : }
    1572             : 
    1573             : /*
    1574             :  * XPath: /frr-interface:lib/interface
    1575             :  */
    1576           0 : static const void *lib_interface_get_next(struct nb_cb_get_next_args *args)
    1577             : {
    1578           0 :         struct vrf *vrf;
    1579           0 :         struct interface *pif = (struct interface *)args->list_entry;
    1580             : 
    1581           0 :         if (args->list_entry == NULL) {
    1582           0 :                 vrf = RB_MIN(vrf_name_head, &vrfs_by_name);
    1583           0 :                 assert(vrf);
    1584           0 :                 pif = RB_MIN(if_name_head, &vrf->ifaces_by_name);
    1585             :         } else {
    1586           0 :                 vrf = pif->vrf;
    1587           0 :                 pif = RB_NEXT(if_name_head, pif);
    1588             :                 /* if no more interfaces, switch to next vrf */
    1589           0 :                 while (pif == NULL) {
    1590           0 :                         vrf = RB_NEXT(vrf_name_head, vrf);
    1591           0 :                         if (!vrf)
    1592             :                                 return NULL;
    1593           0 :                         pif = RB_MIN(if_name_head, &vrf->ifaces_by_name);
    1594             :                 }
    1595             :         }
    1596             : 
    1597             :         return pif;
    1598             : }
    1599             : 
    1600           0 : static int lib_interface_get_keys(struct nb_cb_get_keys_args *args)
    1601             : {
    1602           0 :         const struct interface *ifp = args->list_entry;
    1603             : 
    1604           0 :         args->keys->num = 1;
    1605             : 
    1606           0 :         if (vrf_is_backend_netns())
    1607           0 :                 snprintf(args->keys->key[0], sizeof(args->keys->key[0]),
    1608           0 :                          "%s:%s", ifp->vrf->name, ifp->name);
    1609             :         else
    1610           0 :                 snprintf(args->keys->key[0], sizeof(args->keys->key[0]), "%s",
    1611           0 :                          ifp->name);
    1612             : 
    1613           0 :         return NB_OK;
    1614             : }
    1615             : 
    1616             : static const void *
    1617           0 : lib_interface_lookup_entry(struct nb_cb_lookup_entry_args *args)
    1618             : {
    1619           0 :         if (vrf_is_backend_netns()) {
    1620           0 :                 char ifname[XPATH_MAXLEN];
    1621           0 :                 char vrfname[XPATH_MAXLEN];
    1622           0 :                 struct vrf *vrf;
    1623             : 
    1624           0 :                 netns_ifname_split(args->keys->key[0], ifname, vrfname);
    1625             : 
    1626           0 :                 vrf = vrf_lookup_by_name(vrfname);
    1627             : 
    1628           0 :                 return vrf ? if_lookup_by_name(ifname, vrf->vrf_id) : NULL;
    1629             :         } else {
    1630           0 :                 return if_lookup_by_name_all_vrf(args->keys->key[0]);
    1631             :         }
    1632             : }
    1633             : 
    1634             : /*
    1635             :  * XPath: /frr-interface:lib/interface/description
    1636             :  */
    1637           0 : static int lib_interface_description_modify(struct nb_cb_modify_args *args)
    1638             : {
    1639           0 :         struct interface *ifp;
    1640           0 :         const char *description;
    1641             : 
    1642           0 :         if (args->event != NB_EV_APPLY)
    1643             :                 return NB_OK;
    1644             : 
    1645           0 :         ifp = nb_running_get_entry(args->dnode, NULL, true);
    1646           0 :         XFREE(MTYPE_IFDESC, ifp->desc);
    1647           0 :         description = yang_dnode_get_string(args->dnode, NULL);
    1648           0 :         ifp->desc = XSTRDUP(MTYPE_IFDESC, description);
    1649             : 
    1650           0 :         return NB_OK;
    1651             : }
    1652             : 
    1653           0 : static int lib_interface_description_destroy(struct nb_cb_destroy_args *args)
    1654             : {
    1655           0 :         struct interface *ifp;
    1656             : 
    1657           0 :         if (args->event != NB_EV_APPLY)
    1658             :                 return NB_OK;
    1659             : 
    1660           0 :         ifp = nb_running_get_entry(args->dnode, NULL, true);
    1661           0 :         XFREE(MTYPE_IFDESC, ifp->desc);
    1662             : 
    1663           0 :         return NB_OK;
    1664             : }
    1665             : 
    1666             : /*
    1667             :  * XPath: /frr-interface:lib/interface/vrf
    1668             :  */
    1669             : static struct yang_data *
    1670           0 : lib_interface_vrf_get_elem(struct nb_cb_get_elem_args *args)
    1671             : {
    1672           0 :         const struct interface *ifp = args->list_entry;
    1673             : 
    1674           0 :         return yang_data_new_string(args->xpath, ifp->vrf->name);
    1675             : }
    1676             : 
    1677             : /*
    1678             :  * XPath: /frr-interface:lib/interface/state/if-index
    1679             :  */
    1680             : static struct yang_data *
    1681           0 : lib_interface_state_if_index_get_elem(struct nb_cb_get_elem_args *args)
    1682             : {
    1683           0 :         const struct interface *ifp = args->list_entry;
    1684             : 
    1685           0 :         return yang_data_new_int32(args->xpath, ifp->ifindex);
    1686             : }
    1687             : 
    1688             : /*
    1689             :  * XPath: /frr-interface:lib/interface/state/mtu
    1690             :  */
    1691             : static struct yang_data *
    1692           0 : lib_interface_state_mtu_get_elem(struct nb_cb_get_elem_args *args)
    1693             : {
    1694           0 :         const struct interface *ifp = args->list_entry;
    1695             : 
    1696           0 :         return yang_data_new_uint16(args->xpath, ifp->mtu);
    1697             : }
    1698             : 
    1699             : /*
    1700             :  * XPath: /frr-interface:lib/interface/state/mtu6
    1701             :  */
    1702             : static struct yang_data *
    1703           0 : lib_interface_state_mtu6_get_elem(struct nb_cb_get_elem_args *args)
    1704             : {
    1705           0 :         const struct interface *ifp = args->list_entry;
    1706             : 
    1707           0 :         return yang_data_new_uint32(args->xpath, ifp->mtu6);
    1708             : }
    1709             : 
    1710             : /*
    1711             :  * XPath: /frr-interface:lib/interface/state/speed
    1712             :  */
    1713             : static struct yang_data *
    1714           0 : lib_interface_state_speed_get_elem(struct nb_cb_get_elem_args *args)
    1715             : {
    1716           0 :         const struct interface *ifp = args->list_entry;
    1717             : 
    1718           0 :         return yang_data_new_uint32(args->xpath, ifp->speed);
    1719             : }
    1720             : 
    1721             : /*
    1722             :  * XPath: /frr-interface:lib/interface/state/metric
    1723             :  */
    1724             : static struct yang_data *
    1725           0 : lib_interface_state_metric_get_elem(struct nb_cb_get_elem_args *args)
    1726             : {
    1727           0 :         const struct interface *ifp = args->list_entry;
    1728             : 
    1729           0 :         return yang_data_new_uint32(args->xpath, ifp->metric);
    1730             : }
    1731             : 
    1732             : /*
    1733             :  * XPath: /frr-interface:lib/interface/state/flags
    1734             :  */
    1735             : static struct yang_data *
    1736           0 : lib_interface_state_flags_get_elem(struct nb_cb_get_elem_args *args)
    1737             : {
    1738             :         /* TODO: implement me. */
    1739           0 :         return NULL;
    1740             : }
    1741             : 
    1742             : /*
    1743             :  * XPath: /frr-interface:lib/interface/state/type
    1744             :  */
    1745             : static struct yang_data *
    1746           0 : lib_interface_state_type_get_elem(struct nb_cb_get_elem_args *args)
    1747             : {
    1748             :         /* TODO: implement me. */
    1749           0 :         return NULL;
    1750             : }
    1751             : 
    1752             : /*
    1753             :  * XPath: /frr-interface:lib/interface/state/phy-address
    1754             :  */
    1755             : static struct yang_data *
    1756           0 : lib_interface_state_phy_address_get_elem(struct nb_cb_get_elem_args *args)
    1757             : {
    1758           0 :         const struct interface *ifp = args->list_entry;
    1759           0 :         struct ethaddr macaddr;
    1760             : 
    1761           0 :         memcpy(&macaddr.octet, ifp->hw_addr, ETH_ALEN);
    1762             : 
    1763           0 :         return yang_data_new_mac(args->xpath, &macaddr);
    1764             : }
    1765             : 
    1766             : /* clang-format off */
    1767             : const struct frr_yang_module_info frr_interface_info = {
    1768             :         .name = "frr-interface",
    1769             :         .nodes = {
    1770             :                 {
    1771             :                         .xpath = "/frr-interface:lib/interface",
    1772             :                         .cbs = {
    1773             :                                 .create = lib_interface_create,
    1774             :                                 .destroy = lib_interface_destroy,
    1775             :                                 .cli_show = cli_show_interface,
    1776             :                                 .cli_show_end = cli_show_interface_end,
    1777             :                                 .get_next = lib_interface_get_next,
    1778             :                                 .get_keys = lib_interface_get_keys,
    1779             :                                 .lookup_entry = lib_interface_lookup_entry,
    1780             :                         },
    1781             :                 },
    1782             :                 {
    1783             :                         .xpath = "/frr-interface:lib/interface/description",
    1784             :                         .cbs = {
    1785             :                                 .modify = lib_interface_description_modify,
    1786             :                                 .destroy = lib_interface_description_destroy,
    1787             :                                 .cli_show = cli_show_interface_desc,
    1788             :                         },
    1789             :                 },
    1790             :                 {
    1791             :                         .xpath = "/frr-interface:lib/interface/vrf",
    1792             :                         .cbs = {
    1793             :                                 .get_elem = lib_interface_vrf_get_elem,
    1794             :                         }
    1795             :                 },
    1796             :                 {
    1797             :                         .xpath = "/frr-interface:lib/interface/state/if-index",
    1798             :                         .cbs = {
    1799             :                                 .get_elem = lib_interface_state_if_index_get_elem,
    1800             :                         }
    1801             :                 },
    1802             :                 {
    1803             :                         .xpath = "/frr-interface:lib/interface/state/mtu",
    1804             :                         .cbs = {
    1805             :                                 .get_elem = lib_interface_state_mtu_get_elem,
    1806             :                         }
    1807             :                 },
    1808             :                 {
    1809             :                         .xpath = "/frr-interface:lib/interface/state/mtu6",
    1810             :                         .cbs = {
    1811             :                                 .get_elem = lib_interface_state_mtu6_get_elem,
    1812             :                         }
    1813             :                 },
    1814             :                 {
    1815             :                         .xpath = "/frr-interface:lib/interface/state/speed",
    1816             :                         .cbs = {
    1817             :                                 .get_elem = lib_interface_state_speed_get_elem,
    1818             :                         }
    1819             :                 },
    1820             :                 {
    1821             :                         .xpath = "/frr-interface:lib/interface/state/metric",
    1822             :                         .cbs = {
    1823             :                                 .get_elem = lib_interface_state_metric_get_elem,
    1824             :                         }
    1825             :                 },
    1826             :                 {
    1827             :                         .xpath = "/frr-interface:lib/interface/state/flags",
    1828             :                         .cbs = {
    1829             :                                 .get_elem = lib_interface_state_flags_get_elem,
    1830             :                         }
    1831             :                 },
    1832             :                 {
    1833             :                         .xpath = "/frr-interface:lib/interface/state/type",
    1834             :                         .cbs = {
    1835             :                                 .get_elem = lib_interface_state_type_get_elem,
    1836             :                         }
    1837             :                 },
    1838             :                 {
    1839             :                         .xpath = "/frr-interface:lib/interface/state/phy-address",
    1840             :                         .cbs = {
    1841             :                                 .get_elem = lib_interface_state_phy_address_get_elem,
    1842             :                         }
    1843             :                 },
    1844             :                 {
    1845             :                         .xpath = NULL,
    1846             :                 },
    1847             :         }
    1848             : };

Generated by: LCOV version v1.16-topotato