back to topotato report
topotato coverage report
Current view: top level - lib - if.c (source / functions) Hit Total Coverage
Test: test_rip.py::RIPBasic Lines: 309 795 38.9 %
Date: 2023-02-24 18:39:46 Functions: 55 109 50.5 %

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

Generated by: LCOV version v1.16-topotato