back to topotato report
topotato coverage report
Current view: top level - zebra - if_netlink.c (source / functions) Hit Total Coverage
Test: aggregated run ( view descriptions ) Lines: 483 1181 40.9 %
Date: 2023-02-24 19:38:44 Functions: 21 42 50.0 %

          Line data    Source code
       1             : /*
       2             :  * Interface looking up by netlink.
       3             :  * Copyright (C) 1998 Kunihiro Ishiguro
       4             :  *
       5             :  * This file is part of GNU Zebra.
       6             :  *
       7             :  * GNU Zebra is free software; you can redistribute it and/or modify it
       8             :  * under the terms of the GNU General Public License as published by the
       9             :  * Free Software Foundation; either version 2, or (at your option) any
      10             :  * later version.
      11             :  *
      12             :  * GNU Zebra is distributed in the hope that it will be useful, but
      13             :  * WITHOUT ANY WARRANTY; without even the implied warranty of
      14             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      15             :  * General Public License for more details.
      16             :  *
      17             :  * You should have received a copy of the GNU General Public License along
      18             :  * with this program; see the file COPYING; if not, write to the Free Software
      19             :  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
      20             :  */
      21             : 
      22             : #include <zebra.h>
      23             : 
      24             : #ifdef GNU_LINUX
      25             : 
      26             : /* The following definition is to workaround an issue in the Linux kernel
      27             :  * header files with redefinition of 'struct in6_addr' in both
      28             :  * netinet/in.h and linux/in6.h.
      29             :  * Reference - https://sourceware.org/ml/libc-alpha/2013-01/msg00599.html
      30             :  */
      31             : #define _LINUX_IN6_H
      32             : #define _LINUX_IF_H
      33             : #define _LINUX_IP_H
      34             : 
      35             : #include <netinet/if_ether.h>
      36             : #include <linux/if_bridge.h>
      37             : #include <linux/if_link.h>
      38             : #include <linux/if_tunnel.h>
      39             : #include <net/if_arp.h>
      40             : #include <linux/sockios.h>
      41             : #include <linux/ethtool.h>
      42             : 
      43             : #include "linklist.h"
      44             : #include "if.h"
      45             : #include "log.h"
      46             : #include "prefix.h"
      47             : #include "connected.h"
      48             : #include "table.h"
      49             : #include "memory.h"
      50             : #include "rib.h"
      51             : #include "thread.h"
      52             : #include "privs.h"
      53             : #include "nexthop.h"
      54             : #include "vrf.h"
      55             : #include "vrf_int.h"
      56             : #include "mpls.h"
      57             : #include "lib_errors.h"
      58             : 
      59             : #include "vty.h"
      60             : #include "zebra/zserv.h"
      61             : #include "zebra/zebra_ns.h"
      62             : #include "zebra/zebra_vrf.h"
      63             : #include "zebra/rt.h"
      64             : #include "zebra/redistribute.h"
      65             : #include "zebra/interface.h"
      66             : #include "zebra/debug.h"
      67             : #include "zebra/rtadv.h"
      68             : #include "zebra/zebra_ptm.h"
      69             : #include "zebra/zebra_mpls.h"
      70             : #include "zebra/kernel_netlink.h"
      71             : #include "zebra/rt_netlink.h"
      72             : #include "zebra/if_netlink.h"
      73             : #include "zebra/zebra_errors.h"
      74             : #include "zebra/zebra_vxlan.h"
      75             : #include "zebra/zebra_evpn_mh.h"
      76             : #include "zebra/zebra_l2.h"
      77             : #include "zebra/netconf_netlink.h"
      78             : #include "zebra/zebra_trace.h"
      79             : 
      80             : extern struct zebra_privs_t zserv_privs;
      81             : uint8_t frr_protodown_r_bit = FRR_PROTODOWN_REASON_DEFAULT_BIT;
      82             : 
      83             : /* Note: on netlink systems, there should be a 1-to-1 mapping between interface
      84             :    names and ifindex values. */
      85         562 : static void set_ifindex(struct interface *ifp, ifindex_t ifi_index,
      86             :                         struct zebra_ns *zns)
      87             : {
      88         562 :         struct interface *oifp;
      89             : 
      90         562 :         if (((oifp = if_lookup_by_index_per_ns(zns, ifi_index)) != NULL)
      91         305 :             && (oifp != ifp)) {
      92           0 :                 if (ifi_index == IFINDEX_INTERNAL)
      93           0 :                         flog_err(
      94             :                                 EC_LIB_INTERFACE,
      95             :                                 "Netlink is setting interface %s ifindex to reserved internal value %u",
      96             :                                 ifp->name, ifi_index);
      97             :                 else {
      98           0 :                         if (IS_ZEBRA_DEBUG_KERNEL)
      99           0 :                                 zlog_debug(
     100             :                                         "interface index %d was renamed from %s to %s",
     101             :                                         ifi_index, oifp->name, ifp->name);
     102           0 :                         if (if_is_up(oifp))
     103           0 :                                 flog_err(
     104             :                                         EC_LIB_INTERFACE,
     105             :                                         "interface rename detected on up interface: index %d was renamed from %s to %s, results are uncertain!",
     106             :                                         ifi_index, oifp->name, ifp->name);
     107           0 :                         if_delete_update(&oifp);
     108             :                 }
     109             :         }
     110         562 :         if_set_index(ifp, ifi_index);
     111         562 : }
     112             : 
     113             : /* Utility function to parse hardware link-layer address and update ifp */
     114         562 : static void netlink_interface_update_hw_addr(struct rtattr **tb,
     115             :                                              struct interface *ifp)
     116             : {
     117         562 :         int i;
     118             : 
     119         562 :         if (tb[IFLA_ADDRESS]) {
     120         484 :                 int hw_addr_len;
     121             : 
     122         484 :                 hw_addr_len = RTA_PAYLOAD(tb[IFLA_ADDRESS]);
     123             : 
     124         484 :                 if (hw_addr_len > INTERFACE_HWADDR_MAX)
     125           0 :                         zlog_debug("Hardware address is too large: %d",
     126             :                                    hw_addr_len);
     127             :                 else {
     128         484 :                         ifp->hw_addr_len = hw_addr_len;
     129         484 :                         memcpy(ifp->hw_addr, RTA_DATA(tb[IFLA_ADDRESS]),
     130             :                                hw_addr_len);
     131             : 
     132        1042 :                         for (i = 0; i < hw_addr_len; i++)
     133         949 :                                 if (ifp->hw_addr[i] != 0)
     134             :                                         break;
     135             : 
     136         484 :                         if (i == hw_addr_len)
     137          93 :                                 ifp->hw_addr_len = 0;
     138             :                         else
     139         391 :                                 ifp->hw_addr_len = hw_addr_len;
     140             :                 }
     141             :         }
     142         562 : }
     143             : 
     144         562 : static enum zebra_link_type netlink_to_zebra_link_type(unsigned int hwt)
     145             : {
     146         562 :         switch (hwt) {
     147             :         case ARPHRD_ETHER:
     148             :                 return ZEBRA_LLT_ETHER;
     149           0 :         case ARPHRD_EETHER:
     150           0 :                 return ZEBRA_LLT_EETHER;
     151           0 :         case ARPHRD_AX25:
     152           0 :                 return ZEBRA_LLT_AX25;
     153           0 :         case ARPHRD_PRONET:
     154           0 :                 return ZEBRA_LLT_PRONET;
     155           0 :         case ARPHRD_IEEE802:
     156           0 :                 return ZEBRA_LLT_IEEE802;
     157           0 :         case ARPHRD_ARCNET:
     158           0 :                 return ZEBRA_LLT_ARCNET;
     159           0 :         case ARPHRD_APPLETLK:
     160           0 :                 return ZEBRA_LLT_APPLETLK;
     161           0 :         case ARPHRD_DLCI:
     162           0 :                 return ZEBRA_LLT_DLCI;
     163           0 :         case ARPHRD_ATM:
     164           0 :                 return ZEBRA_LLT_ATM;
     165           0 :         case ARPHRD_METRICOM:
     166           0 :                 return ZEBRA_LLT_METRICOM;
     167           0 :         case ARPHRD_IEEE1394:
     168           0 :                 return ZEBRA_LLT_IEEE1394;
     169           0 :         case ARPHRD_EUI64:
     170           0 :                 return ZEBRA_LLT_EUI64;
     171           0 :         case ARPHRD_INFINIBAND:
     172           0 :                 return ZEBRA_LLT_INFINIBAND;
     173           0 :         case ARPHRD_SLIP:
     174           0 :                 return ZEBRA_LLT_SLIP;
     175           0 :         case ARPHRD_CSLIP:
     176           0 :                 return ZEBRA_LLT_CSLIP;
     177           0 :         case ARPHRD_SLIP6:
     178           0 :                 return ZEBRA_LLT_SLIP6;
     179           0 :         case ARPHRD_CSLIP6:
     180           0 :                 return ZEBRA_LLT_CSLIP6;
     181           0 :         case ARPHRD_RSRVD:
     182           0 :                 return ZEBRA_LLT_RSRVD;
     183           0 :         case ARPHRD_ADAPT:
     184           0 :                 return ZEBRA_LLT_ADAPT;
     185           0 :         case ARPHRD_ROSE:
     186           0 :                 return ZEBRA_LLT_ROSE;
     187           0 :         case ARPHRD_X25:
     188           0 :                 return ZEBRA_LLT_X25;
     189           0 :         case ARPHRD_PPP:
     190           0 :                 return ZEBRA_LLT_PPP;
     191           0 :         case ARPHRD_CISCO:
     192           0 :                 return ZEBRA_LLT_CHDLC;
     193           0 :         case ARPHRD_LAPB:
     194           0 :                 return ZEBRA_LLT_LAPB;
     195           0 :         case ARPHRD_RAWHDLC:
     196           0 :                 return ZEBRA_LLT_RAWHDLC;
     197           0 :         case ARPHRD_TUNNEL:
     198           0 :                 return ZEBRA_LLT_IPIP;
     199           0 :         case ARPHRD_TUNNEL6:
     200           0 :                 return ZEBRA_LLT_IPIP6;
     201           0 :         case ARPHRD_FRAD:
     202           0 :                 return ZEBRA_LLT_FRAD;
     203           0 :         case ARPHRD_SKIP:
     204           0 :                 return ZEBRA_LLT_SKIP;
     205          93 :         case ARPHRD_LOOPBACK:
     206          93 :                 return ZEBRA_LLT_LOOPBACK;
     207           0 :         case ARPHRD_LOCALTLK:
     208           0 :                 return ZEBRA_LLT_LOCALTLK;
     209           0 :         case ARPHRD_FDDI:
     210           0 :                 return ZEBRA_LLT_FDDI;
     211           0 :         case ARPHRD_SIT:
     212           0 :                 return ZEBRA_LLT_SIT;
     213           0 :         case ARPHRD_IPDDP:
     214           0 :                 return ZEBRA_LLT_IPDDP;
     215           0 :         case ARPHRD_IPGRE:
     216           0 :                 return ZEBRA_LLT_IPGRE;
     217          78 :         case ARPHRD_PIMREG:
     218          78 :                 return ZEBRA_LLT_PIMREG;
     219           0 :         case ARPHRD_HIPPI:
     220           0 :                 return ZEBRA_LLT_HIPPI;
     221           0 :         case ARPHRD_ECONET:
     222           0 :                 return ZEBRA_LLT_ECONET;
     223           0 :         case ARPHRD_IRDA:
     224           0 :                 return ZEBRA_LLT_IRDA;
     225           0 :         case ARPHRD_FCPP:
     226           0 :                 return ZEBRA_LLT_FCPP;
     227           0 :         case ARPHRD_FCAL:
     228           0 :                 return ZEBRA_LLT_FCAL;
     229           0 :         case ARPHRD_FCPL:
     230           0 :                 return ZEBRA_LLT_FCPL;
     231           0 :         case ARPHRD_FCFABRIC:
     232           0 :                 return ZEBRA_LLT_FCFABRIC;
     233           0 :         case ARPHRD_IEEE802_TR:
     234           0 :                 return ZEBRA_LLT_IEEE802_TR;
     235           0 :         case ARPHRD_IEEE80211:
     236           0 :                 return ZEBRA_LLT_IEEE80211;
     237             : #ifdef ARPHRD_IEEE802154
     238           0 :         case ARPHRD_IEEE802154:
     239           0 :                 return ZEBRA_LLT_IEEE802154;
     240             : #endif
     241             : #ifdef ARPHRD_IP6GRE
     242             :         case ARPHRD_IP6GRE:
     243             :                 return ZEBRA_LLT_IP6GRE;
     244             : #endif
     245             : #ifdef ARPHRD_IEEE802154_PHY
     246           0 :         case ARPHRD_IEEE802154_PHY:
     247           0 :                 return ZEBRA_LLT_IEEE802154_PHY;
     248             : #endif
     249             : 
     250           0 :         default:
     251           0 :                 return ZEBRA_LLT_UNKNOWN;
     252             :         }
     253             : }
     254             : 
     255         562 : static inline void zebra_if_set_ziftype(struct interface *ifp,
     256             :                                         enum zebra_iftype zif_type,
     257             :                                         enum zebra_slave_iftype zif_slave_type)
     258             : {
     259         562 :         struct zebra_if *zif;
     260             : 
     261         562 :         zif = (struct zebra_if *)ifp->info;
     262         562 :         zif->zif_slave_type = zif_slave_type;
     263             : 
     264         562 :         if (zif->zif_type != zif_type) {
     265         138 :                 zif->zif_type = zif_type;
     266             :                 /* If the if_type has been set to bond initialize ES info
     267             :                  * against it. XXX - note that we don't handle the case where
     268             :                  * a zif changes from bond to non-bond; it is really
     269             :                  * an unexpected/error condition.
     270             :                  */
     271         138 :                 zebra_evpn_if_init(zif);
     272             :         }
     273         562 : }
     274             : 
     275         391 : static void netlink_determine_zebra_iftype(const char *kind,
     276             :                                            enum zebra_iftype *zif_type)
     277             : {
     278         391 :         *zif_type = ZEBRA_IF_OTHER;
     279             : 
     280         391 :         if (!kind)
     281             :                 return;
     282             : 
     283         391 :         if (strcmp(kind, "vrf") == 0)
     284           0 :                 *zif_type = ZEBRA_IF_VRF;
     285         391 :         else if (strcmp(kind, "bridge") == 0)
     286           0 :                 *zif_type = ZEBRA_IF_BRIDGE;
     287         391 :         else if (strcmp(kind, "vlan") == 0)
     288           0 :                 *zif_type = ZEBRA_IF_VLAN;
     289         391 :         else if (strcmp(kind, "vxlan") == 0)
     290           0 :                 *zif_type = ZEBRA_IF_VXLAN;
     291         391 :         else if (strcmp(kind, "macvlan") == 0)
     292           0 :                 *zif_type = ZEBRA_IF_MACVLAN;
     293         391 :         else if (strcmp(kind, "veth") == 0)
     294         391 :                 *zif_type = ZEBRA_IF_VETH;
     295           0 :         else if (strcmp(kind, "bond") == 0)
     296           0 :                 *zif_type = ZEBRA_IF_BOND;
     297           0 :         else if (strcmp(kind, "bond_slave") == 0)
     298           0 :                 *zif_type = ZEBRA_IF_BOND_SLAVE;
     299           0 :         else if (strcmp(kind, "gre") == 0)
     300           0 :                 *zif_type = ZEBRA_IF_GRE;
     301             : }
     302             : 
     303           0 : static void netlink_vrf_change(struct nlmsghdr *h, struct rtattr *tb,
     304             :                                uint32_t ns_id, const char *name)
     305             : {
     306           0 :         struct ifinfomsg *ifi;
     307           0 :         struct rtattr *linkinfo[IFLA_INFO_MAX + 1];
     308           0 :         struct rtattr *attr[IFLA_VRF_MAX + 1];
     309           0 :         struct vrf *vrf = NULL;
     310           0 :         struct zebra_vrf *zvrf;
     311           0 :         uint32_t nl_table_id;
     312             : 
     313           0 :         ifi = NLMSG_DATA(h);
     314             : 
     315           0 :         netlink_parse_rtattr_nested(linkinfo, IFLA_INFO_MAX, tb);
     316             : 
     317           0 :         if (!linkinfo[IFLA_INFO_DATA]) {
     318           0 :                 if (IS_ZEBRA_DEBUG_KERNEL)
     319           0 :                         zlog_debug(
     320             :                                 "%s: IFLA_INFO_DATA missing from VRF message: %s",
     321             :                                 __func__, name);
     322           0 :                 return;
     323             :         }
     324             : 
     325           0 :         netlink_parse_rtattr_nested(attr, IFLA_VRF_MAX,
     326             :                                     linkinfo[IFLA_INFO_DATA]);
     327           0 :         if (!attr[IFLA_VRF_TABLE]) {
     328           0 :                 if (IS_ZEBRA_DEBUG_KERNEL)
     329           0 :                         zlog_debug(
     330             :                                 "%s: IFLA_VRF_TABLE missing from VRF message: %s",
     331             :                                 __func__, name);
     332           0 :                 return;
     333             :         }
     334             : 
     335           0 :         nl_table_id = *(uint32_t *)RTA_DATA(attr[IFLA_VRF_TABLE]);
     336             : 
     337           0 :         if (h->nlmsg_type == RTM_NEWLINK) {
     338           0 :                 if (IS_ZEBRA_DEBUG_KERNEL)
     339           0 :                         zlog_debug("RTM_NEWLINK for VRF %s(%u) table %u", name,
     340             :                                    ifi->ifi_index, nl_table_id);
     341             : 
     342           0 :                 if (!vrf_lookup_by_id((vrf_id_t)ifi->ifi_index)) {
     343           0 :                         vrf_id_t exist_id;
     344             : 
     345           0 :                         exist_id = vrf_lookup_by_table(nl_table_id, ns_id);
     346           0 :                         if (exist_id != VRF_DEFAULT) {
     347           0 :                                 vrf = vrf_lookup_by_id(exist_id);
     348             : 
     349           0 :                                 flog_err(
     350             :                                         EC_ZEBRA_VRF_MISCONFIGURED,
     351             :                                         "VRF %s id %u table id overlaps existing vrf %s, misconfiguration exiting",
     352             :                                         name, ifi->ifi_index, vrf->name);
     353           0 :                                 exit(-1);
     354             :                         }
     355             :                 }
     356             : 
     357           0 :                 vrf = vrf_update((vrf_id_t)ifi->ifi_index, name);
     358           0 :                 if (!vrf) {
     359           0 :                         flog_err(EC_LIB_INTERFACE, "VRF %s id %u not created",
     360             :                                  name, ifi->ifi_index);
     361           0 :                         return;
     362             :                 }
     363             : 
     364             :                 /*
     365             :                  * This is the only place that we get the actual kernel table_id
     366             :                  * being used.  We need it to set the table_id of the routes
     367             :                  * we are passing to the kernel.... And to throw some totally
     368             :                  * awesome parties. that too.
     369             :                  *
     370             :                  * At this point we *must* have a zvrf because the vrf_create
     371             :                  * callback creates one.  We *must* set the table id
     372             :                  * before the vrf_enable because of( at the very least )
     373             :                  * static routes being delayed for installation until
     374             :                  * during the vrf_enable callbacks.
     375             :                  */
     376           0 :                 zvrf = (struct zebra_vrf *)vrf->info;
     377           0 :                 zvrf->table_id = nl_table_id;
     378             : 
     379             :                 /* Enable the created VRF. */
     380           0 :                 if (!vrf_enable(vrf)) {
     381           0 :                         flog_err(EC_LIB_INTERFACE,
     382             :                                  "Failed to enable VRF %s id %u", name,
     383             :                                  ifi->ifi_index);
     384           0 :                         return;
     385             :                 }
     386             : 
     387             :         } else // h->nlmsg_type == RTM_DELLINK
     388             :         {
     389           0 :                 if (IS_ZEBRA_DEBUG_KERNEL)
     390           0 :                         zlog_debug("RTM_DELLINK for VRF %s(%u)", name,
     391             :                                    ifi->ifi_index);
     392             : 
     393           0 :                 vrf = vrf_lookup_by_id((vrf_id_t)ifi->ifi_index);
     394             : 
     395           0 :                 if (!vrf) {
     396           0 :                         flog_warn(EC_ZEBRA_VRF_NOT_FOUND, "%s: vrf not found",
     397             :                                   __func__);
     398           0 :                         return;
     399             :                 }
     400             : 
     401           0 :                 vrf_delete(vrf);
     402             :         }
     403             : }
     404             : 
     405         275 : static uint32_t get_iflink_speed(struct interface *interface, int *error)
     406             : {
     407         275 :         struct ifreq ifdata;
     408         275 :         struct ethtool_cmd ecmd;
     409         275 :         int sd;
     410         275 :         int rc;
     411         275 :         const char *ifname = interface->name;
     412             : 
     413         275 :         if (error)
     414          44 :                 *error = 0;
     415             :         /* initialize struct */
     416         275 :         memset(&ifdata, 0, sizeof(ifdata));
     417             : 
     418             :         /* set interface name */
     419         275 :         strlcpy(ifdata.ifr_name, ifname, sizeof(ifdata.ifr_name));
     420             : 
     421             :         /* initialize ethtool interface */
     422         275 :         memset(&ecmd, 0, sizeof(ecmd));
     423         275 :         ecmd.cmd = ETHTOOL_GSET; /* ETHTOOL_GLINK */
     424         275 :         ifdata.ifr_data = (caddr_t)&ecmd;
     425             : 
     426             :         /* use ioctl to get speed of an interface */
     427         550 :         frr_with_privs(&zserv_privs) {
     428         550 :                 sd = vrf_socket(PF_INET, SOCK_DGRAM, IPPROTO_IP,
     429         275 :                                 interface->vrf->vrf_id, NULL);
     430         275 :                 if (sd < 0) {
     431           0 :                         if (IS_ZEBRA_DEBUG_KERNEL)
     432           0 :                                 zlog_debug("Failure to read interface %s speed: %d %s",
     433             :                                            ifname, errno, safe_strerror(errno));
     434             :                         /* no vrf socket creation may probably mean vrf issue */
     435           0 :                         if (error)
     436           0 :                                 *error = -1;
     437           0 :                         return 0;
     438             :                 }
     439             :                 /* Get the current link state for the interface */
     440         275 :                 rc = vrf_ioctl(interface->vrf->vrf_id, sd, SIOCETHTOOL,
     441             :                                (char *)&ifdata);
     442             :         }
     443         275 :         if (rc < 0) {
     444         116 :                 if (errno != EOPNOTSUPP && IS_ZEBRA_DEBUG_KERNEL)
     445           0 :                         zlog_debug(
     446             :                                 "IOCTL failure to read interface %s speed: %d %s",
     447             :                                 ifname, errno, safe_strerror(errno));
     448             :                 /* no device means interface unreachable */
     449         116 :                 if (errno == ENODEV && error)
     450           0 :                         *error = -1;
     451         116 :                 ecmd.speed_hi = 0;
     452         116 :                 ecmd.speed = 0;
     453             :         }
     454             : 
     455         275 :         close(sd);
     456             : 
     457         275 :         return ((uint32_t)ecmd.speed_hi << 16) | ecmd.speed;
     458             : }
     459             : 
     460          44 : uint32_t kernel_get_speed(struct interface *ifp, int *error)
     461             : {
     462          44 :         return get_iflink_speed(ifp, error);
     463             : }
     464             : 
     465             : static ssize_t
     466           0 : netlink_gre_set_msg_encoder(struct zebra_dplane_ctx *ctx, void *buf,
     467             :                             size_t buflen)
     468             : {
     469           0 :         struct {
     470             :                 struct nlmsghdr n;
     471             :                 struct ifinfomsg ifi;
     472             :                 char buf[];
     473           0 :         } *req = buf;
     474           0 :         uint32_t link_idx;
     475           0 :         unsigned int mtu;
     476           0 :         struct rtattr *rta_info, *rta_data;
     477           0 :         const struct zebra_l2info_gre *gre_info;
     478             : 
     479           0 :         if (buflen < sizeof(*req))
     480             :                 return 0;
     481           0 :         memset(req, 0, sizeof(*req));
     482             : 
     483           0 :         req->n.nlmsg_type =  RTM_NEWLINK;
     484           0 :         req->n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
     485           0 :         req->n.nlmsg_flags = NLM_F_REQUEST;
     486             : 
     487           0 :         req->ifi.ifi_index = dplane_ctx_get_ifindex(ctx);
     488             : 
     489           0 :         gre_info = dplane_ctx_gre_get_info(ctx);
     490           0 :         if (!gre_info)
     491             :                 return 0;
     492             : 
     493           0 :         req->ifi.ifi_change = 0xFFFFFFFF;
     494           0 :         link_idx = dplane_ctx_gre_get_link_ifindex(ctx);
     495           0 :         mtu = dplane_ctx_gre_get_mtu(ctx);
     496             : 
     497           0 :         if (mtu && !nl_attr_put32(&req->n, buflen, IFLA_MTU, mtu))
     498             :                 return 0;
     499             : 
     500           0 :         rta_info = nl_attr_nest(&req->n, buflen, IFLA_LINKINFO);
     501           0 :         if (!rta_info)
     502             :                 return 0;
     503             : 
     504           0 :         if (!nl_attr_put(&req->n, buflen, IFLA_INFO_KIND, "gre", 3))
     505             :                 return 0;
     506             : 
     507           0 :         rta_data = nl_attr_nest(&req->n, buflen, IFLA_INFO_DATA);
     508           0 :         if (!rta_data)
     509             :                 return 0;
     510             : 
     511           0 :         if (!nl_attr_put32(&req->n, buflen, IFLA_GRE_LINK, link_idx))
     512             :                 return 0;
     513             : 
     514           0 :         if (gre_info->vtep_ip.s_addr &&
     515           0 :             !nl_attr_put32(&req->n, buflen, IFLA_GRE_LOCAL,
     516             :                            gre_info->vtep_ip.s_addr))
     517             :                 return 0;
     518             : 
     519           0 :         if (gre_info->vtep_ip_remote.s_addr &&
     520           0 :             !nl_attr_put32(&req->n, buflen, IFLA_GRE_REMOTE,
     521             :                            gre_info->vtep_ip_remote.s_addr))
     522             :                 return 0;
     523             : 
     524           0 :         if (gre_info->ikey &&
     525           0 :             !nl_attr_put32(&req->n, buflen, IFLA_GRE_IKEY,
     526             :                            gre_info->ikey))
     527             :                 return 0;
     528           0 :         if (gre_info->okey &&
     529           0 :             !nl_attr_put32(&req->n, buflen, IFLA_GRE_IKEY,
     530             :                            gre_info->okey))
     531             :                 return 0;
     532             : 
     533           0 :         nl_attr_nest_end(&req->n, rta_data);
     534           0 :         nl_attr_nest_end(&req->n, rta_info);
     535             : 
     536           0 :         return NLMSG_ALIGN(req->n.nlmsg_len);
     537             : }
     538             : 
     539           0 : static int netlink_extract_bridge_info(struct rtattr *link_data,
     540             :                                        struct zebra_l2info_bridge *bridge_info)
     541             : {
     542           0 :         struct rtattr *attr[IFLA_BR_MAX + 1];
     543             : 
     544           0 :         memset(bridge_info, 0, sizeof(*bridge_info));
     545           0 :         netlink_parse_rtattr_nested(attr, IFLA_BR_MAX, link_data);
     546           0 :         if (attr[IFLA_BR_VLAN_FILTERING])
     547           0 :                 bridge_info->vlan_aware =
     548             :                         *(uint8_t *)RTA_DATA(attr[IFLA_BR_VLAN_FILTERING]);
     549           0 :         return 0;
     550             : }
     551             : 
     552           0 : static int netlink_extract_vlan_info(struct rtattr *link_data,
     553             :                                      struct zebra_l2info_vlan *vlan_info)
     554             : {
     555           0 :         struct rtattr *attr[IFLA_VLAN_MAX + 1];
     556           0 :         vlanid_t vid_in_msg;
     557             : 
     558           0 :         memset(vlan_info, 0, sizeof(*vlan_info));
     559           0 :         netlink_parse_rtattr_nested(attr, IFLA_VLAN_MAX, link_data);
     560           0 :         if (!attr[IFLA_VLAN_ID]) {
     561           0 :                 if (IS_ZEBRA_DEBUG_KERNEL)
     562           0 :                         zlog_debug("IFLA_VLAN_ID missing from VLAN IF message");
     563           0 :                 return -1;
     564             :         }
     565             : 
     566           0 :         vid_in_msg = *(vlanid_t *)RTA_DATA(attr[IFLA_VLAN_ID]);
     567           0 :         vlan_info->vid = vid_in_msg;
     568           0 :         return 0;
     569             : }
     570             : 
     571           0 : static int netlink_extract_gre_info(struct rtattr *link_data,
     572             :                                     struct zebra_l2info_gre *gre_info)
     573             : {
     574           0 :         struct rtattr *attr[IFLA_GRE_MAX + 1];
     575             : 
     576           0 :         memset(gre_info, 0, sizeof(*gre_info));
     577           0 :         memset(attr, 0, sizeof(attr));
     578           0 :         netlink_parse_rtattr_nested(attr, IFLA_GRE_MAX, link_data);
     579             : 
     580           0 :         if (!attr[IFLA_GRE_LOCAL]) {
     581           0 :                 if (IS_ZEBRA_DEBUG_KERNEL)
     582           0 :                         zlog_debug(
     583             :                                 "IFLA_GRE_LOCAL missing from GRE IF message");
     584             :         } else
     585           0 :                 gre_info->vtep_ip =
     586             :                         *(struct in_addr *)RTA_DATA(attr[IFLA_GRE_LOCAL]);
     587           0 :         if (!attr[IFLA_GRE_REMOTE]) {
     588           0 :                 if (IS_ZEBRA_DEBUG_KERNEL)
     589           0 :                         zlog_debug(
     590             :                                 "IFLA_GRE_REMOTE missing from GRE IF message");
     591             :         } else
     592           0 :                 gre_info->vtep_ip_remote =
     593             :                         *(struct in_addr *)RTA_DATA(attr[IFLA_GRE_REMOTE]);
     594             : 
     595           0 :         if (!attr[IFLA_GRE_LINK]) {
     596           0 :                 if (IS_ZEBRA_DEBUG_KERNEL)
     597           0 :                         zlog_debug("IFLA_GRE_LINK missing from GRE IF message");
     598             :         } else {
     599           0 :                 gre_info->ifindex_link =
     600             :                         *(ifindex_t *)RTA_DATA(attr[IFLA_GRE_LINK]);
     601           0 :                 if (IS_ZEBRA_DEBUG_KERNEL)
     602           0 :                         zlog_debug("IFLA_GRE_LINK obtained is %u",
     603             :                                    gre_info->ifindex_link);
     604             :         }
     605           0 :         if (attr[IFLA_GRE_IKEY])
     606           0 :                 gre_info->ikey = *(uint32_t *)RTA_DATA(attr[IFLA_GRE_IKEY]);
     607           0 :         if (attr[IFLA_GRE_OKEY])
     608           0 :                 gre_info->okey = *(uint32_t *)RTA_DATA(attr[IFLA_GRE_OKEY]);
     609           0 :         return 0;
     610             : }
     611             : 
     612           0 : static int netlink_extract_vxlan_info(struct rtattr *link_data,
     613             :                                       struct zebra_l2info_vxlan *vxl_info)
     614             : {
     615           0 :         struct rtattr *attr[IFLA_VXLAN_MAX + 1];
     616           0 :         vni_t vni_in_msg;
     617           0 :         struct in_addr vtep_ip_in_msg;
     618           0 :         ifindex_t ifindex_link;
     619             : 
     620           0 :         memset(vxl_info, 0, sizeof(*vxl_info));
     621           0 :         netlink_parse_rtattr_nested(attr, IFLA_VXLAN_MAX, link_data);
     622           0 :         if (!attr[IFLA_VXLAN_ID]) {
     623           0 :                 if (IS_ZEBRA_DEBUG_KERNEL)
     624           0 :                         zlog_debug(
     625             :                                 "IFLA_VXLAN_ID missing from VXLAN IF message");
     626           0 :                 return -1;
     627             :         }
     628             : 
     629           0 :         vni_in_msg = *(vni_t *)RTA_DATA(attr[IFLA_VXLAN_ID]);
     630           0 :         vxl_info->vni = vni_in_msg;
     631           0 :         if (!attr[IFLA_VXLAN_LOCAL]) {
     632           0 :                 if (IS_ZEBRA_DEBUG_KERNEL)
     633           0 :                         zlog_debug(
     634             :                                 "IFLA_VXLAN_LOCAL missing from VXLAN IF message");
     635             :         } else {
     636           0 :                 vtep_ip_in_msg =
     637             :                         *(struct in_addr *)RTA_DATA(attr[IFLA_VXLAN_LOCAL]);
     638           0 :                 vxl_info->vtep_ip = vtep_ip_in_msg;
     639             :         }
     640             : 
     641           0 :         if (attr[IFLA_VXLAN_GROUP]) {
     642           0 :                 vxl_info->mcast_grp =
     643             :                         *(struct in_addr *)RTA_DATA(attr[IFLA_VXLAN_GROUP]);
     644             :         }
     645             : 
     646           0 :         if (!attr[IFLA_VXLAN_LINK]) {
     647           0 :                 if (IS_ZEBRA_DEBUG_KERNEL)
     648           0 :                         zlog_debug("IFLA_VXLAN_LINK missing from VXLAN IF message");
     649             :         } else {
     650           0 :                 ifindex_link =
     651             :                         *(ifindex_t *)RTA_DATA(attr[IFLA_VXLAN_LINK]);
     652           0 :                 vxl_info->ifindex_link = ifindex_link;
     653             :         }
     654             :         return 0;
     655             : }
     656             : 
     657             : /*
     658             :  * Extract and save L2 params (of interest) for an interface. When a
     659             :  * bridge interface is added or updated, take further actions to map
     660             :  * its members. Likewise, for VxLAN interface.
     661             :  */
     662         562 : static void netlink_interface_update_l2info(struct interface *ifp,
     663             :                                             struct rtattr *link_data, int add,
     664             :                                             ns_id_t link_nsid)
     665             : {
     666         562 :         if (!link_data)
     667             :                 return;
     668             : 
     669           0 :         if (IS_ZEBRA_IF_BRIDGE(ifp)) {
     670           0 :                 struct zebra_l2info_bridge bridge_info;
     671             : 
     672           0 :                 netlink_extract_bridge_info(link_data, &bridge_info);
     673           0 :                 zebra_l2_bridge_add_update(ifp, &bridge_info, add);
     674           0 :         } else if (IS_ZEBRA_IF_VLAN(ifp)) {
     675           0 :                 struct zebra_l2info_vlan vlan_info;
     676             : 
     677           0 :                 netlink_extract_vlan_info(link_data, &vlan_info);
     678           0 :                 zebra_l2_vlanif_update(ifp, &vlan_info);
     679           0 :                 zebra_evpn_acc_bd_svi_set(ifp->info, NULL,
     680           0 :                                           !!if_is_operative(ifp));
     681           0 :         } else if (IS_ZEBRA_IF_VXLAN(ifp)) {
     682           0 :                 struct zebra_l2info_vxlan vxlan_info;
     683             : 
     684           0 :                 netlink_extract_vxlan_info(link_data, &vxlan_info);
     685           0 :                 vxlan_info.link_nsid = link_nsid;
     686           0 :                 zebra_l2_vxlanif_add_update(ifp, &vxlan_info, add);
     687           0 :                 if (link_nsid != NS_UNKNOWN &&
     688           0 :                     vxlan_info.ifindex_link)
     689           0 :                         zebra_if_update_link(ifp, vxlan_info.ifindex_link,
     690             :                                              link_nsid);
     691           0 :         } else if (IS_ZEBRA_IF_GRE(ifp)) {
     692           0 :                 struct zebra_l2info_gre gre_info;
     693             : 
     694           0 :                 netlink_extract_gre_info(link_data, &gre_info);
     695           0 :                 gre_info.link_nsid = link_nsid;
     696           0 :                 zebra_l2_greif_add_update(ifp, &gre_info, add);
     697           0 :                 if (link_nsid != NS_UNKNOWN &&
     698           0 :                     gre_info.ifindex_link)
     699           0 :                         zebra_if_update_link(ifp, gre_info.ifindex_link,
     700             :                                              link_nsid);
     701             :         }
     702             : }
     703             : 
     704           0 : static int netlink_bridge_vxlan_update(struct interface *ifp,
     705             :                 struct rtattr *af_spec)
     706             : {
     707           0 :         struct rtattr *aftb[IFLA_BRIDGE_MAX + 1];
     708           0 :         struct bridge_vlan_info *vinfo;
     709           0 :         vlanid_t access_vlan;
     710             : 
     711           0 :         if (!af_spec)
     712             :                 return 0;
     713             : 
     714             :         /* There is a 1-to-1 mapping of VLAN to VxLAN - hence
     715             :          * only 1 access VLAN is accepted.
     716             :          */
     717           0 :         netlink_parse_rtattr_nested(aftb, IFLA_BRIDGE_MAX, af_spec);
     718           0 :         if (!aftb[IFLA_BRIDGE_VLAN_INFO])
     719             :                 return 0;
     720             : 
     721           0 :         vinfo = RTA_DATA(aftb[IFLA_BRIDGE_VLAN_INFO]);
     722           0 :         if (!(vinfo->flags & BRIDGE_VLAN_INFO_PVID))
     723             :                 return 0;
     724             : 
     725           0 :         access_vlan = (vlanid_t)vinfo->vid;
     726           0 :         if (IS_ZEBRA_DEBUG_KERNEL)
     727           0 :                 zlog_debug("Access VLAN %u for VxLAN IF %s(%u)", access_vlan,
     728             :                                 ifp->name, ifp->ifindex);
     729           0 :         zebra_l2_vxlanif_update_access_vlan(ifp, access_vlan);
     730           0 :         return 0;
     731             : }
     732             : 
     733           0 : static void netlink_bridge_vlan_update(struct interface *ifp,
     734             :                 struct rtattr *af_spec)
     735             : {
     736           0 :         struct rtattr *i;
     737           0 :         int rem;
     738           0 :         uint16_t vid_range_start = 0;
     739           0 :         struct zebra_if *zif;
     740           0 :         bitfield_t old_vlan_bitmap;
     741           0 :         struct bridge_vlan_info *vinfo;
     742             : 
     743           0 :         zif = (struct zebra_if *)ifp->info;
     744             : 
     745             :         /* cache the old bitmap addrs */
     746           0 :         old_vlan_bitmap = zif->vlan_bitmap;
     747             :         /* create a new bitmap space for re-eval */
     748           0 :         bf_init(zif->vlan_bitmap, IF_VLAN_BITMAP_MAX);
     749             : 
     750           0 :         if (af_spec) {
     751           0 :                 for (i = RTA_DATA(af_spec), rem = RTA_PAYLOAD(af_spec);
     752           0 :                      RTA_OK(i, rem); i = RTA_NEXT(i, rem)) {
     753             : 
     754           0 :                         if (i->rta_type != IFLA_BRIDGE_VLAN_INFO)
     755           0 :                                 continue;
     756             : 
     757           0 :                         vinfo = RTA_DATA(i);
     758             : 
     759           0 :                         if (vinfo->flags & BRIDGE_VLAN_INFO_RANGE_BEGIN) {
     760           0 :                                 vid_range_start = vinfo->vid;
     761           0 :                                 continue;
     762             :                         }
     763             : 
     764           0 :                         if (!(vinfo->flags & BRIDGE_VLAN_INFO_RANGE_END))
     765           0 :                                 vid_range_start = vinfo->vid;
     766             : 
     767           0 :                         zebra_vlan_bitmap_compute(ifp, vid_range_start,
     768           0 :                                                   vinfo->vid);
     769             :                 }
     770             :         }
     771             : 
     772           0 :         zebra_vlan_mbr_re_eval(ifp, old_vlan_bitmap);
     773             : 
     774           0 :         bf_free(old_vlan_bitmap);
     775           0 : }
     776             : 
     777           0 : static int netlink_bridge_interface(struct nlmsghdr *h, int len, ns_id_t ns_id,
     778             :                                     int startup)
     779             : {
     780           0 :         char *name = NULL;
     781           0 :         struct ifinfomsg *ifi;
     782           0 :         struct rtattr *tb[IFLA_MAX + 1];
     783           0 :         struct interface *ifp;
     784           0 :         struct zebra_if *zif;
     785           0 :         struct rtattr *af_spec;
     786             : 
     787             :         /* Fetch name and ifindex */
     788           0 :         ifi = NLMSG_DATA(h);
     789           0 :         netlink_parse_rtattr(tb, IFLA_MAX, IFLA_RTA(ifi), len);
     790             : 
     791           0 :         if (tb[IFLA_IFNAME] == NULL)
     792             :                 return -1;
     793           0 :         name = (char *)RTA_DATA(tb[IFLA_IFNAME]);
     794             : 
     795             :         /* The interface should already be known, if not discard. */
     796           0 :         ifp = if_lookup_by_index_per_ns(zebra_ns_lookup(ns_id), ifi->ifi_index);
     797           0 :         if (!ifp) {
     798           0 :                 zlog_debug("Cannot find bridge IF %s(%u)", name,
     799             :                            ifi->ifi_index);
     800           0 :                 return 0;
     801             :         }
     802             : 
     803             :         /* We are only interested in the access VLAN i.e., AF_SPEC */
     804           0 :         af_spec = tb[IFLA_AF_SPEC];
     805             : 
     806           0 :         if (IS_ZEBRA_IF_VXLAN(ifp))
     807           0 :                 return netlink_bridge_vxlan_update(ifp, af_spec);
     808             : 
     809             :         /* build vlan bitmap associated with this interface if that
     810             :          * device type is interested in the vlans
     811             :          */
     812           0 :         zif = (struct zebra_if *)ifp->info;
     813           0 :         if (bf_is_inited(zif->vlan_bitmap))
     814           0 :                 netlink_bridge_vlan_update(ifp, af_spec);
     815             : 
     816             :         return 0;
     817             : }
     818             : 
     819           0 : static bool is_if_protodown_reason_only_frr(uint32_t rc_bitfield)
     820             : {
     821             :         /* This shouldn't be possible */
     822           0 :         assert(frr_protodown_r_bit < 32);
     823           0 :         return (rc_bitfield == (((uint32_t)1) << frr_protodown_r_bit));
     824             : }
     825             : 
     826             : /*
     827             :  * Process interface protodown dplane update.
     828             :  *
     829             :  * If the interface is an es bond member then it must follow EVPN's
     830             :  * protodown setting.
     831             :  */
     832         562 : static void netlink_proc_dplane_if_protodown(struct zebra_if *zif,
     833             :                                              struct rtattr **tb)
     834             : {
     835         562 :         bool protodown;
     836         562 :         bool old_protodown;
     837         562 :         uint32_t rc_bitfield = 0;
     838         562 :         struct rtattr *pd_reason_info[IFLA_MAX + 1];
     839             : 
     840         562 :         protodown = !!*(uint8_t *)RTA_DATA(tb[IFLA_PROTO_DOWN]);
     841             : 
     842         562 :         if (tb[IFLA_PROTO_DOWN_REASON]) {
     843           0 :                 netlink_parse_rtattr_nested(pd_reason_info, IFLA_INFO_MAX,
     844             :                                             tb[IFLA_PROTO_DOWN_REASON]);
     845             : 
     846           0 :                 if (pd_reason_info[IFLA_PROTO_DOWN_REASON_VALUE])
     847           0 :                         rc_bitfield = *(uint32_t *)RTA_DATA(
     848             :                                 pd_reason_info[IFLA_PROTO_DOWN_REASON_VALUE]);
     849             :         }
     850             : 
     851             :         /*
     852             :          * Set our reason code to note it wasn't us.
     853             :          * If the reason we got from the kernel is ONLY frr though, don't
     854             :          * set it.
     855             :          */
     856         562 :         COND_FLAG(zif->protodown_rc, ZEBRA_PROTODOWN_EXTERNAL,
     857             :                   protodown && rc_bitfield &&
     858             :                           !is_if_protodown_reason_only_frr(rc_bitfield));
     859             : 
     860             : 
     861         562 :         old_protodown = !!ZEBRA_IF_IS_PROTODOWN(zif);
     862         562 :         if (protodown == old_protodown)
     863         562 :                 return;
     864             : 
     865           0 :         if (IS_ZEBRA_DEBUG_EVPN_MH_ES || IS_ZEBRA_DEBUG_KERNEL)
     866           0 :                 zlog_debug("interface %s dplane change, protdown %s",
     867             :                            zif->ifp->name, protodown ? "on" : "off");
     868             : 
     869             :         /* Set protodown, respectively */
     870           0 :         COND_FLAG(zif->flags, ZIF_FLAG_PROTODOWN, protodown);
     871             : 
     872           0 :         if (zebra_evpn_is_es_bond_member(zif->ifp)) {
     873             :                 /* Check it's not already being sent to the dplane first */
     874           0 :                 if (protodown &&
     875           0 :                     CHECK_FLAG(zif->flags, ZIF_FLAG_SET_PROTODOWN)) {
     876           0 :                         if (IS_ZEBRA_DEBUG_EVPN_MH_ES || IS_ZEBRA_DEBUG_KERNEL)
     877           0 :                                 zlog_debug(
     878             :                                         "bond mbr %s protodown on recv'd but already sent protodown on to the dplane",
     879             :                                         zif->ifp->name);
     880           0 :                         return;
     881             :                 }
     882             : 
     883           0 :                 if (!protodown &&
     884           0 :                     CHECK_FLAG(zif->flags, ZIF_FLAG_UNSET_PROTODOWN)) {
     885           0 :                         if (IS_ZEBRA_DEBUG_EVPN_MH_ES || IS_ZEBRA_DEBUG_KERNEL)
     886           0 :                                 zlog_debug(
     887             :                                         "bond mbr %s protodown off recv'd but already sent protodown off to the dplane",
     888             :                                         zif->ifp->name);
     889           0 :                         return;
     890             :                 }
     891             : 
     892           0 :                 if (IS_ZEBRA_DEBUG_EVPN_MH_ES || IS_ZEBRA_DEBUG_KERNEL)
     893           0 :                         zlog_debug(
     894             :                                 "bond mbr %s reinstate protodown %s in the dplane",
     895             :                                 zif->ifp->name, old_protodown ? "on" : "off");
     896             : 
     897           0 :                 if (old_protodown)
     898           0 :                         SET_FLAG(zif->flags, ZIF_FLAG_SET_PROTODOWN);
     899             :                 else
     900           0 :                         SET_FLAG(zif->flags, ZIF_FLAG_UNSET_PROTODOWN);
     901             : 
     902           0 :                 dplane_intf_update(zif->ifp);
     903             :         }
     904             : }
     905             : 
     906           0 : static uint8_t netlink_parse_lacp_bypass(struct rtattr **linkinfo)
     907             : {
     908           0 :         uint8_t bypass = 0;
     909           0 :         struct rtattr *mbrinfo[IFLA_BOND_SLAVE_MAX + 1];
     910             : 
     911           0 :         netlink_parse_rtattr_nested(mbrinfo, IFLA_BOND_SLAVE_MAX,
     912             :                                     linkinfo[IFLA_INFO_SLAVE_DATA]);
     913           0 :         if (mbrinfo[IFLA_BOND_SLAVE_AD_RX_BYPASS])
     914           0 :                 bypass = *(uint8_t *)RTA_DATA(
     915             :                         mbrinfo[IFLA_BOND_SLAVE_AD_RX_BYPASS]);
     916             : 
     917           0 :         return bypass;
     918             : }
     919             : 
     920             : /*
     921             :  * Only called at startup to cleanup leftover protodown reasons we may
     922             :  * have not cleaned up. We leave protodown set though.
     923             :  */
     924         231 : static void if_sweep_protodown(struct zebra_if *zif)
     925             : {
     926         231 :         bool protodown;
     927             : 
     928         231 :         protodown = !!ZEBRA_IF_IS_PROTODOWN(zif);
     929             : 
     930         231 :         if (!protodown)
     931             :                 return;
     932             : 
     933           0 :         if (IS_ZEBRA_DEBUG_KERNEL)
     934           0 :                 zlog_debug("interface %s sweeping protodown %s reason 0x%x",
     935             :                            zif->ifp->name, protodown ? "on" : "off",
     936             :                            zif->protodown_rc);
     937             : 
     938             :         /* Only clear our reason codes, leave external if it was set */
     939           0 :         UNSET_FLAG(zif->protodown_rc, ZEBRA_PROTODOWN_ALL);
     940           0 :         dplane_intf_update(zif->ifp);
     941             : }
     942             : 
     943             : /*
     944             :  * Called from interface_lookup_netlink().  This function is only used
     945             :  * during bootstrap.
     946             :  */
     947         231 : static int netlink_interface(struct nlmsghdr *h, ns_id_t ns_id, int startup)
     948             : {
     949         231 :         int len;
     950         231 :         struct ifinfomsg *ifi;
     951         231 :         struct rtattr *tb[IFLA_MAX + 1];
     952         231 :         struct rtattr *linkinfo[IFLA_MAX + 1];
     953         231 :         struct interface *ifp;
     954         231 :         char *name = NULL;
     955         231 :         char *kind = NULL;
     956         231 :         char *desc = NULL;
     957         231 :         char *slave_kind = NULL;
     958         231 :         struct zebra_ns *zns = NULL;
     959         231 :         vrf_id_t vrf_id = VRF_DEFAULT;
     960         231 :         enum zebra_iftype zif_type = ZEBRA_IF_OTHER;
     961         231 :         enum zebra_slave_iftype zif_slave_type = ZEBRA_IF_SLAVE_NONE;
     962         231 :         ifindex_t bridge_ifindex = IFINDEX_INTERNAL;
     963         231 :         ifindex_t link_ifindex = IFINDEX_INTERNAL;
     964         231 :         ifindex_t bond_ifindex = IFINDEX_INTERNAL;
     965         231 :         struct zebra_if *zif;
     966         231 :         ns_id_t link_nsid = ns_id;
     967         231 :         uint8_t bypass = 0;
     968             : 
     969         231 :         frrtrace(3, frr_zebra, netlink_interface, h, ns_id, startup);
     970             : 
     971         231 :         zns = zebra_ns_lookup(ns_id);
     972         231 :         ifi = NLMSG_DATA(h);
     973             : 
     974         231 :         if (h->nlmsg_type != RTM_NEWLINK)
     975             :                 return 0;
     976             : 
     977         231 :         len = h->nlmsg_len - NLMSG_LENGTH(sizeof(struct ifinfomsg));
     978         231 :         if (len < 0) {
     979           0 :                 zlog_err(
     980             :                         "%s: Message received from netlink is of a broken size: %d %zu",
     981             :                         __func__, h->nlmsg_len,
     982             :                         (size_t)NLMSG_LENGTH(sizeof(struct ifinfomsg)));
     983           0 :                 return -1;
     984             :         }
     985             : 
     986             :         /* We are interested in some AF_BRIDGE notifications. */
     987         231 :         if (ifi->ifi_family == AF_BRIDGE)
     988           0 :                 return netlink_bridge_interface(h, len, ns_id, startup);
     989             : 
     990             :         /* Looking up interface name. */
     991         231 :         memset(linkinfo, 0, sizeof(linkinfo));
     992         231 :         netlink_parse_rtattr_flags(tb, IFLA_MAX, IFLA_RTA(ifi), len,
     993             :                                    NLA_F_NESTED);
     994             : 
     995             :         /* check for wireless messages to ignore */
     996         231 :         if ((tb[IFLA_WIRELESS] != NULL) && (ifi->ifi_change == 0)) {
     997           0 :                 if (IS_ZEBRA_DEBUG_KERNEL)
     998           0 :                         zlog_debug("%s: ignoring IFLA_WIRELESS message",
     999             :                                    __func__);
    1000           0 :                 return 0;
    1001             :         }
    1002             : 
    1003         231 :         if (tb[IFLA_IFNAME] == NULL)
    1004             :                 return -1;
    1005         231 :         name = (char *)RTA_DATA(tb[IFLA_IFNAME]);
    1006             : 
    1007         231 :         if (tb[IFLA_IFALIAS])
    1008           0 :                 desc = (char *)RTA_DATA(tb[IFLA_IFALIAS]);
    1009             : 
    1010         231 :         if (tb[IFLA_LINKINFO]) {
    1011         138 :                 netlink_parse_rtattr_nested(linkinfo, IFLA_INFO_MAX,
    1012             :                                             tb[IFLA_LINKINFO]);
    1013             : 
    1014         138 :                 if (linkinfo[IFLA_INFO_KIND])
    1015         138 :                         kind = RTA_DATA(linkinfo[IFLA_INFO_KIND]);
    1016             : 
    1017         138 :                 if (linkinfo[IFLA_INFO_SLAVE_KIND])
    1018           0 :                         slave_kind = RTA_DATA(linkinfo[IFLA_INFO_SLAVE_KIND]);
    1019             : 
    1020           0 :                 if ((slave_kind != NULL) && strcmp(slave_kind, "bond") == 0)
    1021           0 :                         netlink_determine_zebra_iftype("bond_slave", &zif_type);
    1022             :                 else
    1023         138 :                         netlink_determine_zebra_iftype(kind, &zif_type);
    1024             :         }
    1025             : 
    1026             :         /* If VRF, create the VRF structure itself. */
    1027         231 :         if (zif_type == ZEBRA_IF_VRF && !vrf_is_backend_netns()) {
    1028           0 :                 netlink_vrf_change(h, tb[IFLA_LINKINFO], ns_id, name);
    1029           0 :                 vrf_id = (vrf_id_t)ifi->ifi_index;
    1030             :         }
    1031             : 
    1032         231 :         if (tb[IFLA_MASTER]) {
    1033           0 :                 if (slave_kind && (strcmp(slave_kind, "vrf") == 0)
    1034           0 :                     && !vrf_is_backend_netns()) {
    1035           0 :                         zif_slave_type = ZEBRA_IF_SLAVE_VRF;
    1036           0 :                         vrf_id = *(uint32_t *)RTA_DATA(tb[IFLA_MASTER]);
    1037           0 :                 } else if (slave_kind && (strcmp(slave_kind, "bridge") == 0)) {
    1038           0 :                         zif_slave_type = ZEBRA_IF_SLAVE_BRIDGE;
    1039           0 :                         bridge_ifindex =
    1040           0 :                                 *(ifindex_t *)RTA_DATA(tb[IFLA_MASTER]);
    1041           0 :                 } else if (slave_kind && (strcmp(slave_kind, "bond") == 0)) {
    1042           0 :                         zif_slave_type = ZEBRA_IF_SLAVE_BOND;
    1043           0 :                         bond_ifindex = *(ifindex_t *)RTA_DATA(tb[IFLA_MASTER]);
    1044           0 :                         bypass = netlink_parse_lacp_bypass(linkinfo);
    1045             :                 } else
    1046             :                         zif_slave_type = ZEBRA_IF_SLAVE_OTHER;
    1047             :         }
    1048         231 :         if (vrf_is_backend_netns())
    1049           0 :                 vrf_id = (vrf_id_t)ns_id;
    1050             : 
    1051             :         /* If linking to another interface, note it. */
    1052         231 :         if (tb[IFLA_LINK])
    1053         138 :                 link_ifindex = *(ifindex_t *)RTA_DATA(tb[IFLA_LINK]);
    1054             : 
    1055         231 :         if (tb[IFLA_LINK_NETNSID]) {
    1056         138 :                 link_nsid = *(ns_id_t *)RTA_DATA(tb[IFLA_LINK_NETNSID]);
    1057         138 :                 link_nsid = ns_id_get_absolute(ns_id, link_nsid);
    1058             :         }
    1059             : 
    1060         231 :         ifp = if_get_by_name(name, vrf_id, NULL);
    1061         231 :         set_ifindex(ifp, ifi->ifi_index, zns); /* add it to ns struct */
    1062             : 
    1063         231 :         ifp->flags = ifi->ifi_flags & 0x0000fffff;
    1064         231 :         ifp->mtu6 = ifp->mtu = *(uint32_t *)RTA_DATA(tb[IFLA_MTU]);
    1065         231 :         ifp->metric = 0;
    1066         231 :         ifp->speed = get_iflink_speed(ifp, NULL);
    1067         231 :         ifp->ptm_status = ZEBRA_PTM_STATUS_UNKNOWN;
    1068             : 
    1069             :         /* Set zebra interface type */
    1070         231 :         zebra_if_set_ziftype(ifp, zif_type, zif_slave_type);
    1071         231 :         if (IS_ZEBRA_IF_VRF(ifp))
    1072           0 :                 SET_FLAG(ifp->status, ZEBRA_INTERFACE_VRF_LOOPBACK);
    1073             : 
    1074             :         /*
    1075             :          * Just set the @link/lower-device ifindex. During nldump interfaces are
    1076             :          * not ordered in any fashion so we may end up getting upper devices
    1077             :          * before lower devices. We will setup the real linkage once the dump
    1078             :          * is complete.
    1079             :          */
    1080         231 :         zif = (struct zebra_if *)ifp->info;
    1081         231 :         zif->link_ifindex = link_ifindex;
    1082             : 
    1083         231 :         if (desc) {
    1084           0 :                 XFREE(MTYPE_ZIF_DESC, zif->desc);
    1085           0 :                 zif->desc = XSTRDUP(MTYPE_ZIF_DESC, desc);
    1086             :         }
    1087             : 
    1088             :         /* Hardware type and address. */
    1089         231 :         ifp->ll_type = netlink_to_zebra_link_type(ifi->ifi_type);
    1090             : 
    1091         231 :         netlink_interface_update_hw_addr(tb, ifp);
    1092             : 
    1093         231 :         if_add_update(ifp);
    1094             : 
    1095             :         /* Extract and save L2 interface information, take additional actions.
    1096             :          */
    1097         231 :         netlink_interface_update_l2info(ifp, linkinfo[IFLA_INFO_DATA],
    1098             :                                         1, link_nsid);
    1099         231 :         if (IS_ZEBRA_IF_BOND(ifp))
    1100           0 :                 zebra_l2if_update_bond(ifp, true);
    1101         231 :         if (IS_ZEBRA_IF_BRIDGE_SLAVE(ifp))
    1102           0 :                 zebra_l2if_update_bridge_slave(ifp, bridge_ifindex, ns_id,
    1103             :                                                ZEBRA_BRIDGE_NO_ACTION);
    1104         231 :         else if (IS_ZEBRA_IF_BOND_SLAVE(ifp))
    1105           0 :                 zebra_l2if_update_bond_slave(ifp, bond_ifindex, !!bypass);
    1106             : 
    1107         231 :         if (tb[IFLA_PROTO_DOWN]) {
    1108         231 :                 netlink_proc_dplane_if_protodown(zif, tb);
    1109         231 :                 if_sweep_protodown(zif);
    1110             :         }
    1111             : 
    1112             :         return 0;
    1113             : }
    1114             : 
    1115             : /* Request for specific interface or address information from the kernel */
    1116         372 : static int netlink_request_intf_addr(struct nlsock *netlink_cmd, int family,
    1117             :                                      int type, uint32_t filter_mask)
    1118             : {
    1119         372 :         struct {
    1120             :                 struct nlmsghdr n;
    1121             :                 struct ifinfomsg ifm;
    1122             :                 char buf[256];
    1123             :         } req;
    1124             : 
    1125         372 :         frrtrace(4, frr_zebra, netlink_request_intf_addr, netlink_cmd, family,
    1126             :                  type, filter_mask);
    1127             : 
    1128             :         /* Form the request, specifying filter (rtattr) if needed. */
    1129         372 :         memset(&req, 0, sizeof(req));
    1130         372 :         req.n.nlmsg_type = type;
    1131         372 :         req.n.nlmsg_flags = NLM_F_ROOT | NLM_F_MATCH | NLM_F_REQUEST;
    1132         372 :         req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
    1133         372 :         req.ifm.ifi_family = family;
    1134             : 
    1135             :         /* Include filter, if specified. */
    1136         372 :         if (filter_mask)
    1137          93 :                 nl_attr_put32(&req.n, sizeof(req), IFLA_EXT_MASK, filter_mask);
    1138             : 
    1139         372 :         return netlink_request(netlink_cmd, &req);
    1140             : }
    1141             : 
    1142             : enum netlink_msg_status
    1143           0 : netlink_put_gre_set_msg(struct nl_batch *bth, struct zebra_dplane_ctx *ctx)
    1144             : {
    1145           0 :         enum dplane_op_e op;
    1146           0 :         enum netlink_msg_status ret;
    1147             : 
    1148           0 :         op = dplane_ctx_get_op(ctx);
    1149           0 :         assert(op == DPLANE_OP_GRE_SET);
    1150             : 
    1151           0 :         ret = netlink_batch_add_msg(bth, ctx, netlink_gre_set_msg_encoder, false);
    1152             : 
    1153           0 :         return ret;
    1154             : }
    1155             : 
    1156             : /* Interface lookup by netlink socket. */
    1157          93 : int interface_lookup_netlink(struct zebra_ns *zns)
    1158             : {
    1159          93 :         int ret;
    1160          93 :         struct zebra_dplane_info dp_info;
    1161          93 :         struct nlsock *netlink_cmd = &zns->netlink_cmd;
    1162             : 
    1163             :         /* Capture key info from ns struct */
    1164          93 :         zebra_dplane_info_from_zns(&dp_info, zns, true /*is_cmd*/);
    1165             : 
    1166             :         /* Get interface information. */
    1167          93 :         ret = netlink_request_intf_addr(netlink_cmd, AF_PACKET, RTM_GETLINK, 0);
    1168          93 :         if (ret < 0)
    1169             :                 return ret;
    1170          93 :         ret = netlink_parse_info(netlink_interface, netlink_cmd, &dp_info, 0,
    1171             :                                  true);
    1172          93 :         if (ret < 0)
    1173             :                 return ret;
    1174             : 
    1175             :         /* Get interface information - for bridge interfaces. */
    1176          93 :         ret = netlink_request_intf_addr(netlink_cmd, AF_BRIDGE, RTM_GETLINK,
    1177             :                                         RTEXT_FILTER_BRVLAN);
    1178          93 :         if (ret < 0)
    1179             :                 return ret;
    1180          93 :         ret = netlink_parse_info(netlink_interface, netlink_cmd, &dp_info, 0,
    1181             :                                  true);
    1182          93 :         if (ret < 0)
    1183             :                 return ret;
    1184             : 
    1185             :         /*
    1186             :          * So netlink_tunneldump_read will initiate a request
    1187             :          * per tunnel to get data.  If we are on a kernel that
    1188             :          * does not support this then we will get X error messages
    1189             :          * (one per tunnel request )back which netlink_parse_info will
    1190             :          * stop after the first one.  So we need to read equivalent
    1191             :          * error messages per tunnel then we can continue.
    1192             :          * if we do not gather all the read failures then
    1193             :          * later requests will not work right.
    1194             :          */
    1195          93 :         ret = netlink_tunneldump_read(zns);
    1196          93 :         if (ret < 0)
    1197             :                 return ret;
    1198             : 
    1199             :         /* fixup linkages */
    1200          93 :         zebra_if_update_all_links(zns);
    1201          93 :         return 0;
    1202             : }
    1203             : 
    1204             : /**
    1205             :  * interface_addr_lookup_netlink() - Look up interface addresses
    1206             :  *
    1207             :  * @zns:        Zebra netlink socket
    1208             :  * Return:      Result status
    1209             :  */
    1210          93 : static int interface_addr_lookup_netlink(struct zebra_ns *zns)
    1211             : {
    1212          93 :         int ret;
    1213          93 :         struct zebra_dplane_info dp_info;
    1214          93 :         struct nlsock *netlink_cmd = &zns->netlink_cmd;
    1215             : 
    1216             :         /* Capture key info from ns struct */
    1217          93 :         zebra_dplane_info_from_zns(&dp_info, zns, true /*is_cmd*/);
    1218             : 
    1219             :         /* Get IPv4 address of the interfaces. */
    1220          93 :         ret = netlink_request_intf_addr(netlink_cmd, AF_INET, RTM_GETADDR, 0);
    1221          93 :         if (ret < 0)
    1222             :                 return ret;
    1223          93 :         ret = netlink_parse_info(netlink_interface_addr, netlink_cmd, &dp_info,
    1224             :                                  0, true);
    1225          93 :         if (ret < 0)
    1226             :                 return ret;
    1227             : 
    1228             :         /* Get IPv6 address of the interfaces. */
    1229          93 :         ret = netlink_request_intf_addr(netlink_cmd, AF_INET6, RTM_GETADDR, 0);
    1230          93 :         if (ret < 0)
    1231             :                 return ret;
    1232          93 :         ret = netlink_parse_info(netlink_interface_addr, netlink_cmd, &dp_info,
    1233             :                                  0, true);
    1234          93 :         if (ret < 0)
    1235             :                 return ret;
    1236             : 
    1237             :         return 0;
    1238             : }
    1239             : 
    1240           0 : int kernel_interface_set_master(struct interface *master,
    1241             :                                 struct interface *slave)
    1242             : {
    1243           0 :         struct zebra_ns *zns = zebra_ns_lookup(NS_DEFAULT);
    1244             : 
    1245           0 :         struct {
    1246             :                 struct nlmsghdr n;
    1247             :                 struct ifinfomsg ifa;
    1248             :                 char buf[NL_PKT_BUF_SIZE];
    1249             :         } req;
    1250             : 
    1251           0 :         memset(&req, 0, sizeof(req));
    1252             : 
    1253           0 :         req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
    1254           0 :         req.n.nlmsg_flags = NLM_F_REQUEST;
    1255           0 :         req.n.nlmsg_type = RTM_SETLINK;
    1256           0 :         req.n.nlmsg_pid = zns->netlink_cmd.snl.nl_pid;
    1257             : 
    1258           0 :         req.ifa.ifi_index = slave->ifindex;
    1259             : 
    1260           0 :         nl_attr_put32(&req.n, sizeof(req), IFLA_MASTER, master->ifindex);
    1261           0 :         nl_attr_put32(&req.n, sizeof(req), IFLA_LINK, slave->ifindex);
    1262             : 
    1263           0 :         return netlink_talk(netlink_talk_filter, &req.n, &zns->netlink_cmd, zns,
    1264             :                             false);
    1265             : }
    1266             : 
    1267             : /* Interface address modification. */
    1268           5 : static ssize_t netlink_address_msg_encoder(struct zebra_dplane_ctx *ctx,
    1269             :                                            void *buf, size_t buflen)
    1270             : {
    1271           5 :         int bytelen;
    1272           5 :         const struct prefix *p;
    1273           5 :         int cmd;
    1274           5 :         const char *label;
    1275             : 
    1276           5 :         struct {
    1277             :                 struct nlmsghdr n;
    1278             :                 struct ifaddrmsg ifa;
    1279             :                 char buf[0];
    1280           5 :         } *req = buf;
    1281             : 
    1282           5 :         if (buflen < sizeof(*req))
    1283             :                 return 0;
    1284             : 
    1285           5 :         p = dplane_ctx_get_intf_addr(ctx);
    1286           5 :         memset(req, 0, sizeof(*req));
    1287             : 
    1288           5 :         bytelen = (p->family == AF_INET ? 4 : 16);
    1289             : 
    1290           5 :         req->n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg));
    1291           5 :         req->n.nlmsg_flags = NLM_F_REQUEST;
    1292             : 
    1293           5 :         if (dplane_ctx_get_op(ctx) == DPLANE_OP_ADDR_INSTALL)
    1294             :                 cmd = RTM_NEWADDR;
    1295             :         else
    1296           0 :                 cmd = RTM_DELADDR;
    1297             : 
    1298           5 :         req->n.nlmsg_type = cmd;
    1299           5 :         req->ifa.ifa_family = p->family;
    1300             : 
    1301           5 :         req->ifa.ifa_index = dplane_ctx_get_ifindex(ctx);
    1302             : 
    1303           5 :         if (!nl_attr_put(&req->n, buflen, IFA_LOCAL, &p->u.prefix, bytelen))
    1304             :                 return 0;
    1305             : 
    1306           5 :         if (p->family == AF_INET) {
    1307           0 :                 if (dplane_ctx_intf_is_connected(ctx)) {
    1308           0 :                         p = dplane_ctx_get_intf_dest(ctx);
    1309           0 :                         if (!nl_attr_put(&req->n, buflen, IFA_ADDRESS,
    1310           0 :                                          &p->u.prefix, bytelen))
    1311             :                                 return 0;
    1312           0 :                 } else if (cmd == RTM_NEWADDR) {
    1313           0 :                         struct in_addr broad = {
    1314           0 :                                 .s_addr = ipv4_broadcast_addr(p->u.prefix4.s_addr,
    1315           0 :                                                         p->prefixlen)
    1316             :                         };
    1317           0 :                         if (!nl_attr_put(&req->n, buflen, IFA_BROADCAST, &broad,
    1318             :                                          bytelen))
    1319           0 :                                 return 0;
    1320             :                 }
    1321             :         }
    1322             : 
    1323             :         /* p is now either address or destination/bcast addr */
    1324           5 :         req->ifa.ifa_prefixlen = p->prefixlen;
    1325             : 
    1326           5 :         if (dplane_ctx_intf_is_secondary(ctx))
    1327           0 :                 SET_FLAG(req->ifa.ifa_flags, IFA_F_SECONDARY);
    1328             : 
    1329           5 :         if (dplane_ctx_intf_has_label(ctx)) {
    1330           0 :                 label = dplane_ctx_get_intf_label(ctx);
    1331           0 :                 if (!nl_attr_put(&req->n, buflen, IFA_LABEL, label,
    1332           0 :                                  strlen(label) + 1))
    1333             :                         return 0;
    1334             :         }
    1335             : 
    1336           5 :         return NLMSG_ALIGN(req->n.nlmsg_len);
    1337             : }
    1338             : 
    1339             : enum netlink_msg_status
    1340           5 : netlink_put_address_update_msg(struct nl_batch *bth,
    1341             :                                struct zebra_dplane_ctx *ctx)
    1342             : {
    1343           5 :         return netlink_batch_add_msg(bth, ctx, netlink_address_msg_encoder,
    1344             :                                      false);
    1345             : }
    1346             : 
    1347           0 : static ssize_t netlink_intf_msg_encoder(struct zebra_dplane_ctx *ctx, void *buf,
    1348             :                                         size_t buflen)
    1349             : {
    1350           0 :         enum dplane_op_e op;
    1351           0 :         int cmd = 0;
    1352             : 
    1353           0 :         op = dplane_ctx_get_op(ctx);
    1354             : 
    1355           0 :         switch (op) {
    1356           0 :         case DPLANE_OP_INTF_UPDATE:
    1357           0 :                 cmd = RTM_SETLINK;
    1358           0 :                 break;
    1359           0 :         case DPLANE_OP_INTF_INSTALL:
    1360           0 :                 cmd = RTM_NEWLINK;
    1361           0 :                 break;
    1362           0 :         case DPLANE_OP_INTF_DELETE:
    1363           0 :                 cmd = RTM_DELLINK;
    1364           0 :                 break;
    1365           0 :         case DPLANE_OP_NONE:
    1366             :         case DPLANE_OP_ROUTE_INSTALL:
    1367             :         case DPLANE_OP_ROUTE_UPDATE:
    1368             :         case DPLANE_OP_ROUTE_DELETE:
    1369             :         case DPLANE_OP_ROUTE_NOTIFY:
    1370             :         case DPLANE_OP_NH_INSTALL:
    1371             :         case DPLANE_OP_NH_UPDATE:
    1372             :         case DPLANE_OP_NH_DELETE:
    1373             :         case DPLANE_OP_LSP_INSTALL:
    1374             :         case DPLANE_OP_LSP_DELETE:
    1375             :         case DPLANE_OP_LSP_NOTIFY:
    1376             :         case DPLANE_OP_LSP_UPDATE:
    1377             :         case DPLANE_OP_PW_INSTALL:
    1378             :         case DPLANE_OP_PW_UNINSTALL:
    1379             :         case DPLANE_OP_SYS_ROUTE_ADD:
    1380             :         case DPLANE_OP_SYS_ROUTE_DELETE:
    1381             :         case DPLANE_OP_ADDR_INSTALL:
    1382             :         case DPLANE_OP_ADDR_UNINSTALL:
    1383             :         case DPLANE_OP_MAC_INSTALL:
    1384             :         case DPLANE_OP_MAC_DELETE:
    1385             :         case DPLANE_OP_NEIGH_INSTALL:
    1386             :         case DPLANE_OP_NEIGH_UPDATE:
    1387             :         case DPLANE_OP_NEIGH_DELETE:
    1388             :         case DPLANE_OP_NEIGH_DISCOVER:
    1389             :         case DPLANE_OP_VTEP_ADD:
    1390             :         case DPLANE_OP_VTEP_DELETE:
    1391             :         case DPLANE_OP_RULE_ADD:
    1392             :         case DPLANE_OP_RULE_DELETE:
    1393             :         case DPLANE_OP_RULE_UPDATE:
    1394             :         case DPLANE_OP_BR_PORT_UPDATE:
    1395             :         case DPLANE_OP_IPTABLE_ADD:
    1396             :         case DPLANE_OP_IPTABLE_DELETE:
    1397             :         case DPLANE_OP_IPSET_ADD:
    1398             :         case DPLANE_OP_IPSET_ENTRY_ADD:
    1399             :         case DPLANE_OP_IPSET_ENTRY_DELETE:
    1400             :         case DPLANE_OP_IPSET_DELETE:
    1401             :         case DPLANE_OP_NEIGH_IP_INSTALL:
    1402             :         case DPLANE_OP_NEIGH_IP_DELETE:
    1403             :         case DPLANE_OP_NEIGH_TABLE_UPDATE:
    1404             :         case DPLANE_OP_GRE_SET:
    1405             :         case DPLANE_OP_INTF_ADDR_ADD:
    1406             :         case DPLANE_OP_INTF_ADDR_DEL:
    1407             :         case DPLANE_OP_INTF_NETCONFIG:
    1408             :         case DPLANE_OP_TC_QDISC_INSTALL:
    1409             :         case DPLANE_OP_TC_QDISC_UNINSTALL:
    1410             :         case DPLANE_OP_TC_CLASS_ADD:
    1411             :         case DPLANE_OP_TC_CLASS_DELETE:
    1412             :         case DPLANE_OP_TC_CLASS_UPDATE:
    1413             :         case DPLANE_OP_TC_FILTER_ADD:
    1414             :         case DPLANE_OP_TC_FILTER_DELETE:
    1415             :         case DPLANE_OP_TC_FILTER_UPDATE:
    1416           0 :                 flog_err(
    1417             :                         EC_ZEBRA_NHG_FIB_UPDATE,
    1418             :                         "Context received for kernel interface update with incorrect OP code (%u)",
    1419             :                         op);
    1420           0 :                 return -1;
    1421             :         }
    1422             : 
    1423           0 :         return netlink_intf_msg_encode(cmd, ctx, buf, buflen);
    1424             : }
    1425             : 
    1426             : enum netlink_msg_status
    1427           0 : netlink_put_intf_update_msg(struct nl_batch *bth, struct zebra_dplane_ctx *ctx)
    1428             : {
    1429           0 :         return netlink_batch_add_msg(bth, ctx, netlink_intf_msg_encoder, false);
    1430             : }
    1431             : 
    1432         592 : int netlink_interface_addr(struct nlmsghdr *h, ns_id_t ns_id, int startup)
    1433             : {
    1434         592 :         int len;
    1435         592 :         struct ifaddrmsg *ifa;
    1436         592 :         struct rtattr *tb[IFA_MAX + 1];
    1437         592 :         struct interface *ifp;
    1438         592 :         void *addr;
    1439         592 :         void *broad;
    1440         592 :         uint8_t flags = 0;
    1441         592 :         char *label = NULL;
    1442         592 :         struct zebra_ns *zns;
    1443         592 :         uint32_t metric = METRIC_MAX;
    1444         592 :         uint32_t kernel_flags = 0;
    1445             : 
    1446         592 :         frrtrace(3, frr_zebra, netlink_interface_addr, h, ns_id, startup);
    1447             : 
    1448         592 :         zns = zebra_ns_lookup(ns_id);
    1449         592 :         ifa = NLMSG_DATA(h);
    1450             : 
    1451         592 :         if (ifa->ifa_family != AF_INET && ifa->ifa_family != AF_INET6) {
    1452           0 :                 flog_warn(
    1453             :                         EC_ZEBRA_UNKNOWN_FAMILY,
    1454             :                         "Invalid address family: %u received from kernel interface addr change: %s",
    1455             :                         ifa->ifa_family, nl_msg_type_to_str(h->nlmsg_type));
    1456           0 :                 return 0;
    1457             :         }
    1458             : 
    1459         592 :         if (h->nlmsg_type != RTM_NEWADDR && h->nlmsg_type != RTM_DELADDR)
    1460             :                 return 0;
    1461             : 
    1462         592 :         len = h->nlmsg_len - NLMSG_LENGTH(sizeof(struct ifaddrmsg));
    1463         592 :         if (len < 0) {
    1464           0 :                 zlog_err(
    1465             :                         "%s: Message received from netlink is of a broken size: %d %zu",
    1466             :                         __func__, h->nlmsg_len,
    1467             :                         (size_t)NLMSG_LENGTH(sizeof(struct ifaddrmsg)));
    1468           0 :                 return -1;
    1469             :         }
    1470             : 
    1471         592 :         netlink_parse_rtattr(tb, IFA_MAX, IFA_RTA(ifa), len);
    1472             : 
    1473         592 :         ifp = if_lookup_by_index_per_ns(zns, ifa->ifa_index);
    1474         592 :         if (ifp == NULL) {
    1475           0 :                 if (startup) {
    1476             :                         /* During startup, failure to lookup the referenced
    1477             :                          * interface should not be an error, so we have
    1478             :                          * downgraded this condition to warning, and we permit
    1479             :                          * the startup interface state retrieval to continue.
    1480             :                          */
    1481           0 :                         flog_warn(EC_LIB_INTERFACE,
    1482             :                                   "%s: can't find interface by index %d",
    1483             :                                   __func__, ifa->ifa_index);
    1484           0 :                         return 0;
    1485             :                 } else {
    1486           0 :                         flog_err(EC_LIB_INTERFACE,
    1487             :                                  "%s: can't find interface by index %d",
    1488             :                                  __func__, ifa->ifa_index);
    1489           0 :                         return -1;
    1490             :                 }
    1491             :         }
    1492             : 
    1493             :         /* Flags passed through */
    1494         592 :         if (tb[IFA_FLAGS])
    1495         592 :                 kernel_flags = *(int *)RTA_DATA(tb[IFA_FLAGS]);
    1496             :         else
    1497           0 :                 kernel_flags = ifa->ifa_flags;
    1498             : 
    1499         592 :         if (IS_ZEBRA_DEBUG_KERNEL) /* remove this line to see initial ifcfg */
    1500             :         {
    1501           0 :                 char buf[BUFSIZ];
    1502           0 :                 zlog_debug("%s %s %s flags 0x%x:", __func__,
    1503             :                            nl_msg_type_to_str(h->nlmsg_type), ifp->name,
    1504             :                            kernel_flags);
    1505           0 :                 if (tb[IFA_LOCAL])
    1506           0 :                         zlog_debug("  IFA_LOCAL     %s/%d",
    1507             :                                    inet_ntop(ifa->ifa_family,
    1508             :                                              RTA_DATA(tb[IFA_LOCAL]), buf,
    1509             :                                              BUFSIZ),
    1510             :                                    ifa->ifa_prefixlen);
    1511           0 :                 if (tb[IFA_ADDRESS])
    1512           0 :                         zlog_debug("  IFA_ADDRESS   %s/%d",
    1513             :                                    inet_ntop(ifa->ifa_family,
    1514             :                                              RTA_DATA(tb[IFA_ADDRESS]), buf,
    1515             :                                              BUFSIZ),
    1516             :                                    ifa->ifa_prefixlen);
    1517           0 :                 if (tb[IFA_BROADCAST])
    1518           0 :                         zlog_debug("  IFA_BROADCAST %s/%d",
    1519             :                                    inet_ntop(ifa->ifa_family,
    1520             :                                              RTA_DATA(tb[IFA_BROADCAST]), buf,
    1521             :                                              BUFSIZ),
    1522             :                                    ifa->ifa_prefixlen);
    1523           0 :                 if (tb[IFA_LABEL] && strcmp(ifp->name, RTA_DATA(tb[IFA_LABEL])))
    1524           0 :                         zlog_debug("  IFA_LABEL     %s",
    1525             :                                    (char *)RTA_DATA(tb[IFA_LABEL]));
    1526             : 
    1527           0 :                 if (tb[IFA_CACHEINFO]) {
    1528           0 :                         struct ifa_cacheinfo *ci = RTA_DATA(tb[IFA_CACHEINFO]);
    1529           0 :                         zlog_debug("  IFA_CACHEINFO pref %d, valid %d",
    1530             :                                    ci->ifa_prefered, ci->ifa_valid);
    1531             :                 }
    1532             :         }
    1533             : 
    1534             :         /* logic copied from iproute2/ip/ipaddress.c:print_addrinfo() */
    1535         592 :         if (tb[IFA_LOCAL] == NULL)
    1536         271 :                 tb[IFA_LOCAL] = tb[IFA_ADDRESS];
    1537         592 :         if (tb[IFA_ADDRESS] == NULL)
    1538           0 :                 tb[IFA_ADDRESS] = tb[IFA_LOCAL];
    1539             : 
    1540             :         /* local interface address */
    1541         592 :         addr = (tb[IFA_LOCAL] ? RTA_DATA(tb[IFA_LOCAL]) : NULL);
    1542             : 
    1543             :         /* is there a peer address? */
    1544         592 :         if (tb[IFA_ADDRESS]
    1545         592 :             && memcmp(RTA_DATA(tb[IFA_ADDRESS]), RTA_DATA(tb[IFA_LOCAL]),
    1546         592 :                       RTA_PAYLOAD(tb[IFA_ADDRESS]))) {
    1547             :                 broad = RTA_DATA(tb[IFA_ADDRESS]);
    1548             :                 SET_FLAG(flags, ZEBRA_IFA_PEER);
    1549             :         } else
    1550             :                 /* seeking a broadcast address */
    1551         592 :                 broad = (tb[IFA_BROADCAST] ? RTA_DATA(tb[IFA_BROADCAST])
    1552         592 :                                            : NULL);
    1553             : 
    1554             :         /* addr is primary key, SOL if we don't have one */
    1555         592 :         if (addr == NULL) {
    1556           0 :                 zlog_debug("%s: Local Interface Address is NULL for %s",
    1557             :                            __func__, ifp->name);
    1558           0 :                 return -1;
    1559             :         }
    1560             : 
    1561             :         /* Flags. */
    1562         592 :         if (kernel_flags & IFA_F_SECONDARY)
    1563           0 :                 SET_FLAG(flags, ZEBRA_IFA_SECONDARY);
    1564             : 
    1565             :         /* Label */
    1566         592 :         if (tb[IFA_LABEL])
    1567         321 :                 label = (char *)RTA_DATA(tb[IFA_LABEL]);
    1568             : 
    1569         321 :         if (label && strcmp(ifp->name, label) == 0)
    1570         592 :                 label = NULL;
    1571             : 
    1572         592 :         if (tb[IFA_RT_PRIORITY])
    1573           0 :                 metric = *(uint32_t *)RTA_DATA(tb[IFA_RT_PRIORITY]);
    1574             : 
    1575             :         /* Register interface address to the interface. */
    1576         592 :         if (ifa->ifa_family == AF_INET) {
    1577         321 :                 if (ifa->ifa_prefixlen > IPV4_MAX_BITLEN) {
    1578           0 :                         zlog_err(
    1579             :                                 "Invalid prefix length: %u received from kernel interface addr change: %s",
    1580             :                                 ifa->ifa_prefixlen,
    1581             :                                 nl_msg_type_to_str(h->nlmsg_type));
    1582           0 :                         return -1;
    1583             :                 }
    1584             : 
    1585         321 :                 if (h->nlmsg_type == RTM_NEWADDR)
    1586         321 :                         connected_add_ipv4(ifp, flags, (struct in_addr *)addr,
    1587             :                                            ifa->ifa_prefixlen,
    1588             :                                            (struct in_addr *)broad, label,
    1589             :                                            metric);
    1590           0 :                 else if (CHECK_FLAG(flags, ZEBRA_IFA_PEER)) {
    1591             :                         /* Delete with a peer address */
    1592           0 :                         connected_delete_ipv4(
    1593             :                                 ifp, flags, (struct in_addr *)addr,
    1594             :                                 ifa->ifa_prefixlen, broad);
    1595             :                 } else
    1596           0 :                         connected_delete_ipv4(
    1597             :                                 ifp, flags, (struct in_addr *)addr,
    1598             :                                 ifa->ifa_prefixlen, NULL);
    1599             :         }
    1600             : 
    1601         592 :         if (ifa->ifa_family == AF_INET6) {
    1602         271 :                 if (ifa->ifa_prefixlen > IPV6_MAX_BITLEN) {
    1603           0 :                         zlog_err(
    1604             :                                 "Invalid prefix length: %u received from kernel interface addr change: %s",
    1605             :                                 ifa->ifa_prefixlen,
    1606             :                                 nl_msg_type_to_str(h->nlmsg_type));
    1607           0 :                         return -1;
    1608             :                 }
    1609         271 :                 if (h->nlmsg_type == RTM_NEWADDR) {
    1610             :                         /* Only consider valid addresses; we'll not get a
    1611             :                          * notification from
    1612             :                          * the kernel till IPv6 DAD has completed, but at init
    1613             :                          * time, Quagga
    1614             :                          * does query for and will receive all addresses.
    1615             :                          */
    1616         271 :                         if (!(kernel_flags
    1617         271 :                               & (IFA_F_DADFAILED | IFA_F_TENTATIVE)))
    1618         271 :                                 connected_add_ipv6(ifp, flags,
    1619             :                                                    (struct in6_addr *)addr,
    1620             :                                                    (struct in6_addr *)broad,
    1621             :                                                    ifa->ifa_prefixlen, label,
    1622             :                                                    metric);
    1623             :                 } else
    1624           0 :                         connected_delete_ipv6(ifp, (struct in6_addr *)addr,
    1625             :                                               NULL, ifa->ifa_prefixlen);
    1626             :         }
    1627             : 
    1628             :         /*
    1629             :          * Linux kernel does not send route delete on interface down/addr del
    1630             :          * so we have to re-process routes it owns (i.e. kernel routes)
    1631             :          */
    1632         592 :         if (h->nlmsg_type != RTM_NEWADDR)
    1633           0 :                 rib_update(RIB_UPDATE_KERNEL);
    1634             : 
    1635             :         return 0;
    1636             : }
    1637             : 
    1638             : /*
    1639             :  * Parse and validate an incoming interface address change message,
    1640             :  * generating a dplane context object.
    1641             :  * This runs in the dplane pthread; the context is enqueued to the
    1642             :  * main pthread for processing.
    1643             :  */
    1644         148 : int netlink_interface_addr_dplane(struct nlmsghdr *h, ns_id_t ns_id,
    1645             :                                   int startup /*ignored*/)
    1646             : {
    1647         148 :         int len;
    1648         148 :         struct ifaddrmsg *ifa;
    1649         148 :         struct rtattr *tb[IFA_MAX + 1];
    1650         148 :         void *addr;
    1651         148 :         void *broad;
    1652         148 :         char *label = NULL;
    1653         148 :         uint32_t metric = METRIC_MAX;
    1654         148 :         uint32_t kernel_flags = 0;
    1655         148 :         struct zebra_dplane_ctx *ctx;
    1656         148 :         struct prefix p;
    1657             : 
    1658         148 :         ifa = NLMSG_DATA(h);
    1659             : 
    1660             :         /* Validate message types */
    1661         148 :         if (h->nlmsg_type != RTM_NEWADDR && h->nlmsg_type != RTM_DELADDR)
    1662             :                 return 0;
    1663             : 
    1664         148 :         if (ifa->ifa_family != AF_INET && ifa->ifa_family != AF_INET6) {
    1665           0 :                 if (IS_ZEBRA_DEBUG_KERNEL)
    1666           0 :                         zlog_debug("%s: %s: Invalid address family: %u",
    1667             :                                    __func__, nl_msg_type_to_str(h->nlmsg_type),
    1668             :                                    ifa->ifa_family);
    1669           0 :                 return 0;
    1670             :         }
    1671             : 
    1672         148 :         len = h->nlmsg_len - NLMSG_LENGTH(sizeof(struct ifaddrmsg));
    1673         148 :         if (len < 0) {
    1674           0 :                 if (IS_ZEBRA_DEBUG_KERNEL)
    1675           0 :                         zlog_debug("%s: %s: netlink msg bad size: %d %zu",
    1676             :                                    __func__, nl_msg_type_to_str(h->nlmsg_type),
    1677             :                                    h->nlmsg_len,
    1678             :                                    (size_t)NLMSG_LENGTH(
    1679             :                                            sizeof(struct ifaddrmsg)));
    1680           0 :                 return -1;
    1681             :         }
    1682             : 
    1683         148 :         netlink_parse_rtattr(tb, IFA_MAX, IFA_RTA(ifa), len);
    1684             : 
    1685             :         /* Flags passed through */
    1686         148 :         if (tb[IFA_FLAGS])
    1687         148 :                 kernel_flags = *(int *)RTA_DATA(tb[IFA_FLAGS]);
    1688             :         else
    1689           0 :                 kernel_flags = ifa->ifa_flags;
    1690             : 
    1691         148 :         if (IS_ZEBRA_DEBUG_KERNEL) { /* remove this line to see initial ifcfg */
    1692           0 :                 char buf[PREFIX_STRLEN];
    1693             : 
    1694           0 :                 zlog_debug("%s: %s nsid %u ifindex %u flags 0x%x:", __func__,
    1695             :                            nl_msg_type_to_str(h->nlmsg_type), ns_id,
    1696             :                            ifa->ifa_index, kernel_flags);
    1697           0 :                 if (tb[IFA_LOCAL])
    1698           0 :                         zlog_debug("  IFA_LOCAL     %s/%d",
    1699             :                                    inet_ntop(ifa->ifa_family,
    1700             :                                              RTA_DATA(tb[IFA_LOCAL]), buf,
    1701             :                                              sizeof(buf)),
    1702             :                                    ifa->ifa_prefixlen);
    1703           0 :                 if (tb[IFA_ADDRESS])
    1704           0 :                         zlog_debug("  IFA_ADDRESS   %s/%d",
    1705             :                                    inet_ntop(ifa->ifa_family,
    1706             :                                              RTA_DATA(tb[IFA_ADDRESS]), buf,
    1707             :                                              sizeof(buf)),
    1708             :                                    ifa->ifa_prefixlen);
    1709           0 :                 if (tb[IFA_BROADCAST])
    1710           0 :                         zlog_debug("  IFA_BROADCAST %s/%d",
    1711             :                                    inet_ntop(ifa->ifa_family,
    1712             :                                              RTA_DATA(tb[IFA_BROADCAST]), buf,
    1713             :                                              sizeof(buf)),
    1714             :                                    ifa->ifa_prefixlen);
    1715           0 :                 if (tb[IFA_LABEL])
    1716           0 :                         zlog_debug("  IFA_LABEL     %s",
    1717             :                                    (const char *)RTA_DATA(tb[IFA_LABEL]));
    1718             : 
    1719           0 :                 if (tb[IFA_CACHEINFO]) {
    1720           0 :                         struct ifa_cacheinfo *ci = RTA_DATA(tb[IFA_CACHEINFO]);
    1721             : 
    1722           0 :                         zlog_debug("  IFA_CACHEINFO pref %d, valid %d",
    1723             :                                    ci->ifa_prefered, ci->ifa_valid);
    1724             :                 }
    1725             :         }
    1726             : 
    1727             :         /* Validate prefix length */
    1728             : 
    1729         148 :         if (ifa->ifa_family == AF_INET
    1730           0 :             && ifa->ifa_prefixlen > IPV4_MAX_BITLEN) {
    1731           0 :                 if (IS_ZEBRA_DEBUG_KERNEL)
    1732           0 :                         zlog_debug("%s: %s: Invalid prefix length: %u",
    1733             :                                    __func__, nl_msg_type_to_str(h->nlmsg_type),
    1734             :                                    ifa->ifa_prefixlen);
    1735           0 :                 return -1;
    1736             :         }
    1737             : 
    1738         148 :         if (ifa->ifa_family == AF_INET6) {
    1739         148 :                 if (ifa->ifa_prefixlen > IPV6_MAX_BITLEN) {
    1740           0 :                         if (IS_ZEBRA_DEBUG_KERNEL)
    1741           0 :                                 zlog_debug("%s: %s: Invalid prefix length: %u",
    1742             :                                            __func__,
    1743             :                                            nl_msg_type_to_str(h->nlmsg_type),
    1744             :                                            ifa->ifa_prefixlen);
    1745           0 :                         return -1;
    1746             :                 }
    1747             : 
    1748             :                 /* Only consider valid addresses; we'll not get a kernel
    1749             :                  * notification till IPv6 DAD has completed, but at init
    1750             :                  * time, FRR does query for and will receive all addresses.
    1751             :                  */
    1752         148 :                 if (h->nlmsg_type == RTM_NEWADDR
    1753         148 :                     && (kernel_flags & (IFA_F_DADFAILED | IFA_F_TENTATIVE))) {
    1754           5 :                         if (IS_ZEBRA_DEBUG_KERNEL)
    1755           0 :                                 zlog_debug("%s: %s: Invalid/tentative addr",
    1756             :                                            __func__,
    1757             :                                            nl_msg_type_to_str(h->nlmsg_type));
    1758           5 :                         return 0;
    1759             :                 }
    1760             :         }
    1761             : 
    1762             :         /* logic copied from iproute2/ip/ipaddress.c:print_addrinfo() */
    1763         143 :         if (tb[IFA_LOCAL] == NULL)
    1764         143 :                 tb[IFA_LOCAL] = tb[IFA_ADDRESS];
    1765         143 :         if (tb[IFA_ADDRESS] == NULL)
    1766           0 :                 tb[IFA_ADDRESS] = tb[IFA_LOCAL];
    1767             : 
    1768             :         /* local interface address */
    1769         143 :         addr = (tb[IFA_LOCAL] ? RTA_DATA(tb[IFA_LOCAL]) : NULL);
    1770             : 
    1771             :         /* addr is primary key, SOL if we don't have one */
    1772         143 :         if (addr == NULL) {
    1773           0 :                 if (IS_ZEBRA_DEBUG_KERNEL)
    1774           0 :                         zlog_debug("%s: %s: No local interface address",
    1775             :                                    __func__, nl_msg_type_to_str(h->nlmsg_type));
    1776           0 :                 return -1;
    1777             :         }
    1778             : 
    1779             :         /* Allocate a context object, now that validation is done. */
    1780         143 :         ctx = dplane_ctx_alloc();
    1781         143 :         if (h->nlmsg_type == RTM_NEWADDR)
    1782         143 :                 dplane_ctx_set_op(ctx, DPLANE_OP_INTF_ADDR_ADD);
    1783             :         else
    1784           0 :                 dplane_ctx_set_op(ctx, DPLANE_OP_INTF_ADDR_DEL);
    1785             : 
    1786         143 :         dplane_ctx_set_ifindex(ctx, ifa->ifa_index);
    1787         143 :         dplane_ctx_set_ns_id(ctx, ns_id);
    1788             : 
    1789             :         /* Convert addr to prefix */
    1790         143 :         memset(&p, 0, sizeof(p));
    1791         143 :         p.family = ifa->ifa_family;
    1792         143 :         p.prefixlen = ifa->ifa_prefixlen;
    1793         143 :         if (p.family == AF_INET)
    1794           0 :                 p.u.prefix4 = *(struct in_addr *)addr;
    1795             :         else
    1796         143 :                 p.u.prefix6 = *(struct in6_addr *)addr;
    1797             : 
    1798         143 :         dplane_ctx_set_intf_addr(ctx, &p);
    1799             : 
    1800             :         /* is there a peer address? */
    1801         143 :         if (tb[IFA_ADDRESS]
    1802         143 :             && memcmp(RTA_DATA(tb[IFA_ADDRESS]), RTA_DATA(tb[IFA_LOCAL]),
    1803         143 :                       RTA_PAYLOAD(tb[IFA_ADDRESS]))) {
    1804           0 :                 broad = RTA_DATA(tb[IFA_ADDRESS]);
    1805           0 :                 dplane_ctx_intf_set_connected(ctx);
    1806         143 :         } else if (tb[IFA_BROADCAST]) {
    1807             :                 /* seeking a broadcast address */
    1808           0 :                 broad = RTA_DATA(tb[IFA_BROADCAST]);
    1809           0 :                 dplane_ctx_intf_set_broadcast(ctx);
    1810             :         } else
    1811             :                 broad = NULL;
    1812             : 
    1813           0 :         if (broad) {
    1814             :                 /* Convert addr to prefix */
    1815           0 :                 memset(&p, 0, sizeof(p));
    1816           0 :                 p.family = ifa->ifa_family;
    1817           0 :                 p.prefixlen = ifa->ifa_prefixlen;
    1818           0 :                 if (p.family == AF_INET)
    1819           0 :                         p.u.prefix4 = *(struct in_addr *)broad;
    1820             :                 else
    1821           0 :                         p.u.prefix6 = *(struct in6_addr *)broad;
    1822             : 
    1823           0 :                 dplane_ctx_set_intf_dest(ctx, &p);
    1824             :         }
    1825             : 
    1826             :         /* Flags. */
    1827         143 :         if (kernel_flags & IFA_F_SECONDARY)
    1828           0 :                 dplane_ctx_intf_set_secondary(ctx);
    1829             : 
    1830             :         /* Label */
    1831         143 :         if (tb[IFA_LABEL]) {
    1832           0 :                 label = (char *)RTA_DATA(tb[IFA_LABEL]);
    1833           0 :                 dplane_ctx_set_intf_label(ctx, label);
    1834             :         }
    1835             : 
    1836         143 :         if (tb[IFA_RT_PRIORITY])
    1837           0 :                 metric = *(uint32_t *)RTA_DATA(tb[IFA_RT_PRIORITY]);
    1838             : 
    1839         143 :         dplane_ctx_set_intf_metric(ctx, metric);
    1840             : 
    1841             :         /* Enqueue ctx for main pthread to process */
    1842         143 :         dplane_provider_enqueue_to_zebra(ctx);
    1843             : 
    1844         143 :         return 0;
    1845             : }
    1846             : 
    1847         357 : int netlink_link_change(struct nlmsghdr *h, ns_id_t ns_id, int startup)
    1848             : {
    1849         357 :         int len;
    1850         357 :         struct ifinfomsg *ifi;
    1851         357 :         struct rtattr *tb[IFLA_MAX + 1];
    1852         357 :         struct rtattr *linkinfo[IFLA_MAX + 1];
    1853         357 :         struct interface *ifp;
    1854         357 :         char *name = NULL;
    1855         357 :         char *kind = NULL;
    1856         357 :         char *desc = NULL;
    1857         357 :         char *slave_kind = NULL;
    1858         357 :         struct zebra_ns *zns;
    1859         357 :         vrf_id_t vrf_id = VRF_DEFAULT;
    1860         357 :         enum zebra_iftype zif_type = ZEBRA_IF_OTHER;
    1861         357 :         enum zebra_slave_iftype zif_slave_type = ZEBRA_IF_SLAVE_NONE;
    1862         357 :         ifindex_t bridge_ifindex = IFINDEX_INTERNAL;
    1863         357 :         ifindex_t bond_ifindex = IFINDEX_INTERNAL;
    1864         357 :         ifindex_t link_ifindex = IFINDEX_INTERNAL;
    1865         357 :         uint8_t old_hw_addr[INTERFACE_HWADDR_MAX];
    1866         357 :         struct zebra_if *zif;
    1867         357 :         ns_id_t link_nsid = ns_id;
    1868         357 :         ifindex_t master_infindex = IFINDEX_INTERNAL;
    1869         357 :         uint8_t bypass = 0;
    1870             : 
    1871         357 :         zns = zebra_ns_lookup(ns_id);
    1872         357 :         ifi = NLMSG_DATA(h);
    1873             : 
    1874             :         /* assume if not default zns, then new VRF */
    1875         357 :         if (!(h->nlmsg_type == RTM_NEWLINK || h->nlmsg_type == RTM_DELLINK)) {
    1876             :                 /* If this is not link add/delete message so print warning. */
    1877           0 :                 zlog_debug("%s: wrong kernel message %s", __func__,
    1878             :                            nl_msg_type_to_str(h->nlmsg_type));
    1879           0 :                 return 0;
    1880             :         }
    1881             : 
    1882         357 :         if (!(ifi->ifi_family == AF_UNSPEC || ifi->ifi_family == AF_BRIDGE
    1883             :               || ifi->ifi_family == AF_INET6)) {
    1884           0 :                 flog_warn(
    1885             :                         EC_ZEBRA_UNKNOWN_FAMILY,
    1886             :                         "Invalid address family: %u received from kernel link change: %s",
    1887             :                         ifi->ifi_family, nl_msg_type_to_str(h->nlmsg_type));
    1888           0 :                 return 0;
    1889             :         }
    1890             : 
    1891         357 :         len = h->nlmsg_len - NLMSG_LENGTH(sizeof(struct ifinfomsg));
    1892         357 :         if (len < 0) {
    1893           0 :                 zlog_err(
    1894             :                         "%s: Message received from netlink is of a broken size %d %zu",
    1895             :                         __func__, h->nlmsg_len,
    1896             :                         (size_t)NLMSG_LENGTH(sizeof(struct ifinfomsg)));
    1897           0 :                 return -1;
    1898             :         }
    1899             : 
    1900             :         /* We are interested in some AF_BRIDGE notifications. */
    1901         357 :         if (ifi->ifi_family == AF_BRIDGE)
    1902           0 :                 return netlink_bridge_interface(h, len, ns_id, startup);
    1903             : 
    1904             :         /* Looking up interface name. */
    1905         357 :         memset(linkinfo, 0, sizeof(linkinfo));
    1906         357 :         netlink_parse_rtattr_flags(tb, IFLA_MAX, IFLA_RTA(ifi), len,
    1907             :                                    NLA_F_NESTED);
    1908             : 
    1909             :         /* check for wireless messages to ignore */
    1910         357 :         if ((tb[IFLA_WIRELESS] != NULL) && (ifi->ifi_change == 0)) {
    1911           0 :                 if (IS_ZEBRA_DEBUG_KERNEL)
    1912           0 :                         zlog_debug("%s: ignoring IFLA_WIRELESS message",
    1913             :                                    __func__);
    1914           0 :                 return 0;
    1915             :         }
    1916             : 
    1917         357 :         if (tb[IFLA_IFNAME] == NULL)
    1918             :                 return -1;
    1919         357 :         name = (char *)RTA_DATA(tb[IFLA_IFNAME]);
    1920             : 
    1921             :         /* Must be valid string. */
    1922         357 :         len = RTA_PAYLOAD(tb[IFLA_IFNAME]);
    1923         357 :         if (len < 2 || name[len - 1] != '\0') {
    1924           0 :                 if (IS_ZEBRA_DEBUG_KERNEL)
    1925           0 :                         zlog_debug("%s: invalid intf name", __func__);
    1926           0 :                 return -1;
    1927             :         }
    1928             : 
    1929         357 :         if (tb[IFLA_LINKINFO]) {
    1930         253 :                 netlink_parse_rtattr_nested(linkinfo, IFLA_INFO_MAX,
    1931             :                                             tb[IFLA_LINKINFO]);
    1932             : 
    1933         253 :                 if (linkinfo[IFLA_INFO_KIND])
    1934         253 :                         kind = RTA_DATA(linkinfo[IFLA_INFO_KIND]);
    1935             : 
    1936         253 :                 if (linkinfo[IFLA_INFO_SLAVE_KIND])
    1937           0 :                         slave_kind = RTA_DATA(linkinfo[IFLA_INFO_SLAVE_KIND]);
    1938             : 
    1939         253 :                 netlink_determine_zebra_iftype(kind, &zif_type);
    1940             :         }
    1941             : 
    1942             :         /* If linking to another interface, note it. */
    1943         357 :         if (tb[IFLA_LINK])
    1944         357 :                 link_ifindex = *(ifindex_t *)RTA_DATA(tb[IFLA_LINK]);
    1945             : 
    1946         357 :         if (tb[IFLA_LINK_NETNSID]) {
    1947         253 :                 link_nsid = *(ns_id_t *)RTA_DATA(tb[IFLA_LINK_NETNSID]);
    1948         253 :                 link_nsid = ns_id_get_absolute(ns_id, link_nsid);
    1949             :         }
    1950         357 :         if (tb[IFLA_IFALIAS]) {
    1951           0 :                 desc = (char *)RTA_DATA(tb[IFLA_IFALIAS]);
    1952             :         }
    1953             : 
    1954             :         /* See if interface is present. */
    1955         357 :         ifp = if_lookup_by_name_per_ns(zns, name);
    1956             : 
    1957         357 :         if (h->nlmsg_type == RTM_NEWLINK) {
    1958             :                 /* If VRF, create or update the VRF structure itself. */
    1959         331 :                 if (zif_type == ZEBRA_IF_VRF && !vrf_is_backend_netns()) {
    1960           0 :                         netlink_vrf_change(h, tb[IFLA_LINKINFO], ns_id, name);
    1961           0 :                         vrf_id = (vrf_id_t)ifi->ifi_index;
    1962             :                 }
    1963             : 
    1964         331 :                 if (tb[IFLA_MASTER]) {
    1965           0 :                         if (slave_kind && (strcmp(slave_kind, "vrf") == 0)
    1966           0 :                             && !vrf_is_backend_netns()) {
    1967           0 :                                 zif_slave_type = ZEBRA_IF_SLAVE_VRF;
    1968           0 :                                 master_infindex = vrf_id =
    1969           0 :                                         *(uint32_t *)RTA_DATA(tb[IFLA_MASTER]);
    1970             :                         } else if (slave_kind
    1971           0 :                                    && (strcmp(slave_kind, "bridge") == 0)) {
    1972           0 :                                 zif_slave_type = ZEBRA_IF_SLAVE_BRIDGE;
    1973           0 :                                 master_infindex = bridge_ifindex =
    1974           0 :                                         *(ifindex_t *)RTA_DATA(tb[IFLA_MASTER]);
    1975             :                         } else if (slave_kind
    1976           0 :                                    && (strcmp(slave_kind, "bond") == 0)) {
    1977           0 :                                 zif_slave_type = ZEBRA_IF_SLAVE_BOND;
    1978           0 :                                 master_infindex = bond_ifindex =
    1979           0 :                                         *(ifindex_t *)RTA_DATA(tb[IFLA_MASTER]);
    1980           0 :                                 bypass = netlink_parse_lacp_bypass(linkinfo);
    1981             :                         } else
    1982             :                                 zif_slave_type = ZEBRA_IF_SLAVE_OTHER;
    1983             :                 }
    1984         331 :                 if (vrf_is_backend_netns())
    1985           0 :                         vrf_id = (vrf_id_t)ns_id;
    1986         331 :                 if (ifp == NULL
    1987         305 :                     || !CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE)) {
    1988             :                         /* Add interface notification from kernel */
    1989          26 :                         if (IS_ZEBRA_DEBUG_KERNEL)
    1990           0 :                                 zlog_debug(
    1991             :                                         "RTM_NEWLINK ADD for %s(%u) vrf_id %u type %d sl_type %d master %u flags 0x%x",
    1992             :                                         name, ifi->ifi_index, vrf_id, zif_type,
    1993             :                                         zif_slave_type, master_infindex,
    1994             :                                         ifi->ifi_flags);
    1995             : 
    1996          26 :                         if (ifp == NULL) {
    1997             :                                 /* unknown interface */
    1998          26 :                                 ifp = if_get_by_name(name, vrf_id, NULL);
    1999             :                         } else {
    2000             :                                 /* pre-configured interface, learnt now */
    2001           0 :                                 if (ifp->vrf->vrf_id != vrf_id)
    2002           0 :                                         if_update_to_new_vrf(ifp, vrf_id);
    2003             :                         }
    2004             : 
    2005             :                         /* Update interface information. */
    2006          26 :                         set_ifindex(ifp, ifi->ifi_index, zns);
    2007          26 :                         ifp->flags = ifi->ifi_flags & 0x0000fffff;
    2008          26 :                         if (!tb[IFLA_MTU]) {
    2009           0 :                                 zlog_debug(
    2010             :                                         "RTM_NEWLINK for interface %s(%u) without MTU set",
    2011             :                                         name, ifi->ifi_index);
    2012           0 :                                 return 0;
    2013             :                         }
    2014          26 :                         ifp->mtu6 = ifp->mtu = *(int *)RTA_DATA(tb[IFLA_MTU]);
    2015          26 :                         ifp->metric = 0;
    2016          26 :                         ifp->ptm_status = ZEBRA_PTM_STATUS_UNKNOWN;
    2017             : 
    2018             :                         /* Set interface type */
    2019          26 :                         zebra_if_set_ziftype(ifp, zif_type, zif_slave_type);
    2020          26 :                         if (IS_ZEBRA_IF_VRF(ifp))
    2021           0 :                                 SET_FLAG(ifp->status,
    2022             :                                          ZEBRA_INTERFACE_VRF_LOOPBACK);
    2023             : 
    2024             :                         /* Update link. */
    2025          26 :                         zebra_if_update_link(ifp, link_ifindex, link_nsid);
    2026             : 
    2027          26 :                         ifp->ll_type =
    2028          26 :                                 netlink_to_zebra_link_type(ifi->ifi_type);
    2029          26 :                         netlink_interface_update_hw_addr(tb, ifp);
    2030             : 
    2031             :                         /* Inform clients, install any configured addresses. */
    2032          26 :                         if_add_update(ifp);
    2033             : 
    2034             :                         /* Extract and save L2 interface information, take
    2035             :                          * additional actions. */
    2036          26 :                         netlink_interface_update_l2info(
    2037             :                                 ifp, linkinfo[IFLA_INFO_DATA],
    2038             :                                 1, link_nsid);
    2039          26 :                         if (IS_ZEBRA_IF_BRIDGE_SLAVE(ifp))
    2040           0 :                                 zebra_l2if_update_bridge_slave(
    2041             :                                         ifp, bridge_ifindex, ns_id,
    2042             :                                         ZEBRA_BRIDGE_NO_ACTION);
    2043          26 :                         else if (IS_ZEBRA_IF_BOND_SLAVE(ifp))
    2044           0 :                                 zebra_l2if_update_bond_slave(ifp, bond_ifindex,
    2045             :                                                              !!bypass);
    2046             : 
    2047          26 :                         if (tb[IFLA_PROTO_DOWN])
    2048          26 :                                 netlink_proc_dplane_if_protodown(ifp->info, tb);
    2049             : 
    2050         305 :                 } else if (ifp->vrf->vrf_id != vrf_id) {
    2051             :                         /* VRF change for an interface. */
    2052           0 :                         if (IS_ZEBRA_DEBUG_KERNEL)
    2053           0 :                                 zlog_debug(
    2054             :                                         "RTM_NEWLINK vrf-change for %s(%u) vrf_id %u -> %u flags 0x%x",
    2055             :                                         name, ifp->ifindex, ifp->vrf->vrf_id,
    2056             :                                         vrf_id, ifi->ifi_flags);
    2057             : 
    2058           0 :                         if_handle_vrf_change(ifp, vrf_id);
    2059             :                 } else {
    2060         305 :                         bool was_bridge_slave, was_bond_slave;
    2061         305 :                         uint8_t chgflags = ZEBRA_BRIDGE_NO_ACTION;
    2062         305 :                         zif = ifp->info;
    2063             : 
    2064             :                         /* Interface update. */
    2065         305 :                         if (IS_ZEBRA_DEBUG_KERNEL)
    2066           0 :                                 zlog_debug(
    2067             :                                         "RTM_NEWLINK update for %s(%u) sl_type %d master %u flags 0x%x",
    2068             :                                         name, ifp->ifindex, zif_slave_type,
    2069             :                                         master_infindex, ifi->ifi_flags);
    2070             : 
    2071         305 :                         set_ifindex(ifp, ifi->ifi_index, zns);
    2072         305 :                         if (!tb[IFLA_MTU]) {
    2073           0 :                                 zlog_debug(
    2074             :                                         "RTM_NEWLINK for interface %s(%u) without MTU set",
    2075             :                                         name, ifi->ifi_index);
    2076           0 :                                 return 0;
    2077             :                         }
    2078         305 :                         ifp->mtu6 = ifp->mtu = *(int *)RTA_DATA(tb[IFLA_MTU]);
    2079         305 :                         ifp->metric = 0;
    2080             : 
    2081             :                         /* Update interface type - NOTE: Only slave_type can
    2082             :                          * change. */
    2083         305 :                         was_bridge_slave = IS_ZEBRA_IF_BRIDGE_SLAVE(ifp);
    2084         305 :                         was_bond_slave = IS_ZEBRA_IF_BOND_SLAVE(ifp);
    2085         305 :                         zebra_if_set_ziftype(ifp, zif_type, zif_slave_type);
    2086             : 
    2087         305 :                         memcpy(old_hw_addr, ifp->hw_addr, INTERFACE_HWADDR_MAX);
    2088             : 
    2089             :                         /* Update link. */
    2090         305 :                         zebra_if_update_link(ifp, link_ifindex, link_nsid);
    2091             : 
    2092         305 :                         ifp->ll_type =
    2093         305 :                                 netlink_to_zebra_link_type(ifi->ifi_type);
    2094         305 :                         netlink_interface_update_hw_addr(tb, ifp);
    2095             : 
    2096         305 :                         if (tb[IFLA_PROTO_DOWN])
    2097         305 :                                 netlink_proc_dplane_if_protodown(ifp->info, tb);
    2098             : 
    2099         305 :                         if (if_is_no_ptm_operative(ifp)) {
    2100         181 :                                 bool is_up = if_is_operative(ifp);
    2101         181 :                                 ifp->flags = ifi->ifi_flags & 0x0000fffff;
    2102         181 :                                 if (!if_is_no_ptm_operative(ifp) ||
    2103          64 :                                     CHECK_FLAG(zif->flags,
    2104             :                                                ZIF_FLAG_PROTODOWN)) {
    2105         117 :                                         if (IS_ZEBRA_DEBUG_KERNEL)
    2106           0 :                                                 zlog_debug(
    2107             :                                                         "Intf %s(%u) has gone DOWN",
    2108             :                                                         name, ifp->ifindex);
    2109         117 :                                         if_down(ifp);
    2110         117 :                                         rib_update(RIB_UPDATE_KERNEL);
    2111          64 :                                 } else if (if_is_operative(ifp)) {
    2112          64 :                                         bool mac_updated = false;
    2113             : 
    2114             :                                         /* Must notify client daemons of new
    2115             :                                          * interface status. */
    2116          64 :                                         if (IS_ZEBRA_DEBUG_KERNEL)
    2117           0 :                                                 zlog_debug(
    2118             :                                                         "Intf %s(%u) PTM up, notifying clients",
    2119             :                                                         name, ifp->ifindex);
    2120          64 :                                         if_up(ifp, !is_up);
    2121             : 
    2122             :                                         /* Update EVPN VNI when SVI MAC change
    2123             :                                          */
    2124          64 :                                         if (memcmp(old_hw_addr, ifp->hw_addr,
    2125             :                                                    INTERFACE_HWADDR_MAX))
    2126           0 :                                                 mac_updated = true;
    2127          64 :                                         if (IS_ZEBRA_IF_VLAN(ifp)
    2128           0 :                                             && mac_updated) {
    2129           0 :                                                 struct interface *link_if;
    2130             : 
    2131           0 :                                                 link_if =
    2132           0 :                                                 if_lookup_by_index_per_ns(
    2133             :                                                 zebra_ns_lookup(NS_DEFAULT),
    2134             :                                                                 link_ifindex);
    2135           0 :                                                 if (link_if)
    2136           0 :                                                         zebra_vxlan_svi_up(ifp,
    2137             :                                                                 link_if);
    2138          64 :                                         } else if (mac_updated
    2139           0 :                                                    && IS_ZEBRA_IF_BRIDGE(ifp)) {
    2140           0 :                                                 zlog_debug(
    2141             :                                                         "Intf %s(%u) bridge changed MAC address",
    2142             :                                                         name, ifp->ifindex);
    2143           0 :                                                 chgflags =
    2144             :                                                         ZEBRA_BRIDGE_MASTER_MAC_CHANGE;
    2145             :                                         }
    2146             :                                 }
    2147             :                         } else {
    2148         124 :                                 ifp->flags = ifi->ifi_flags & 0x0000fffff;
    2149         124 :                                 if (if_is_operative(ifp) &&
    2150         124 :                                     !CHECK_FLAG(zif->flags,
    2151             :                                                 ZIF_FLAG_PROTODOWN)) {
    2152         124 :                                         if (IS_ZEBRA_DEBUG_KERNEL)
    2153           0 :                                                 zlog_debug(
    2154             :                                                         "Intf %s(%u) has come UP",
    2155             :                                                         name, ifp->ifindex);
    2156         124 :                                         if_up(ifp, true);
    2157         124 :                                         if (IS_ZEBRA_IF_BRIDGE(ifp))
    2158         305 :                                                 chgflags =
    2159             :                                                         ZEBRA_BRIDGE_MASTER_UP;
    2160             :                                 } else {
    2161           0 :                                         if (IS_ZEBRA_DEBUG_KERNEL)
    2162           0 :                                                 zlog_debug(
    2163             :                                                         "Intf %s(%u) has gone DOWN",
    2164             :                                                         name, ifp->ifindex);
    2165           0 :                                         if_down(ifp);
    2166           0 :                                         rib_update(RIB_UPDATE_KERNEL);
    2167             :                                 }
    2168             :                         }
    2169             : 
    2170             :                         /* Extract and save L2 interface information, take
    2171             :                          * additional actions. */
    2172         305 :                         netlink_interface_update_l2info(
    2173             :                                 ifp, linkinfo[IFLA_INFO_DATA],
    2174             :                                 0, link_nsid);
    2175         305 :                         if (IS_ZEBRA_IF_BRIDGE(ifp))
    2176           0 :                                 zebra_l2if_update_bridge(ifp, chgflags);
    2177         305 :                         if (IS_ZEBRA_IF_BOND(ifp))
    2178           0 :                                 zebra_l2if_update_bond(ifp, true);
    2179         305 :                         if (IS_ZEBRA_IF_BRIDGE_SLAVE(ifp) || was_bridge_slave)
    2180           0 :                                 zebra_l2if_update_bridge_slave(
    2181             :                                         ifp, bridge_ifindex, ns_id, chgflags);
    2182         305 :                         else if (IS_ZEBRA_IF_BOND_SLAVE(ifp) || was_bond_slave)
    2183           0 :                                 zebra_l2if_update_bond_slave(ifp, bond_ifindex,
    2184             :                                                              !!bypass);
    2185             :                 }
    2186             : 
    2187         331 :                 zif = ifp->info;
    2188         331 :                 if (zif) {
    2189         331 :                         XFREE(MTYPE_ZIF_DESC, zif->desc);
    2190         331 :                         if (desc)
    2191           0 :                                 zif->desc = XSTRDUP(MTYPE_ZIF_DESC, desc);
    2192             :                 }
    2193             :         } else {
    2194             :                 /* Delete interface notification from kernel */
    2195          26 :                 if (ifp == NULL) {
    2196           0 :                         if (IS_ZEBRA_DEBUG_KERNEL)
    2197           0 :                                 zlog_debug(
    2198             :                                         "RTM_DELLINK for unknown interface %s(%u)",
    2199             :                                         name, ifi->ifi_index);
    2200           0 :                         return 0;
    2201             :                 }
    2202             : 
    2203          26 :                 if (IS_ZEBRA_DEBUG_KERNEL)
    2204           0 :                         zlog_debug("RTM_DELLINK for %s(%u)", name,
    2205             :                                    ifp->ifindex);
    2206             : 
    2207          26 :                 UNSET_FLAG(ifp->status, ZEBRA_INTERFACE_VRF_LOOPBACK);
    2208             : 
    2209          26 :                 if (IS_ZEBRA_IF_BOND(ifp))
    2210           0 :                         zebra_l2if_update_bond(ifp, false);
    2211          26 :                 if (IS_ZEBRA_IF_BOND_SLAVE(ifp))
    2212           0 :                         zebra_l2if_update_bond_slave(ifp, bond_ifindex, false);
    2213             :                 /* Special handling for bridge or VxLAN interfaces. */
    2214          26 :                 if (IS_ZEBRA_IF_BRIDGE(ifp))
    2215           0 :                         zebra_l2_bridge_del(ifp);
    2216          26 :                 else if (IS_ZEBRA_IF_VXLAN(ifp))
    2217           0 :                         zebra_l2_vxlanif_del(ifp);
    2218             : 
    2219          26 :                 if_delete_update(&ifp);
    2220             : 
    2221             :                 /* If VRF, delete the VRF structure itself. */
    2222          26 :                 if (zif_type == ZEBRA_IF_VRF && !vrf_is_backend_netns())
    2223           0 :                         netlink_vrf_change(h, tb[IFLA_LINKINFO], ns_id, name);
    2224             :         }
    2225             : 
    2226             :         return 0;
    2227             : }
    2228             : 
    2229             : /**
    2230             :  * Interface encoding helper function.
    2231             :  *
    2232             :  * \param[in] cmd netlink command.
    2233             :  * \param[in] ctx dataplane context (information snapshot).
    2234             :  * \param[out] buf buffer to hold the packet.
    2235             :  * \param[in] buflen amount of buffer bytes.
    2236             :  */
    2237             : 
    2238           0 : ssize_t netlink_intf_msg_encode(uint16_t cmd,
    2239             :                                 const struct zebra_dplane_ctx *ctx, void *buf,
    2240             :                                 size_t buflen)
    2241             : {
    2242           0 :         struct {
    2243             :                 struct nlmsghdr n;
    2244             :                 struct ifinfomsg ifa;
    2245             :                 char buf[];
    2246           0 :         } *req = buf;
    2247             : 
    2248           0 :         struct rtattr *nest_protodown_reason;
    2249           0 :         ifindex_t ifindex = dplane_ctx_get_ifindex(ctx);
    2250           0 :         bool down = dplane_ctx_intf_is_protodown(ctx);
    2251           0 :         bool pd_reason_val = dplane_ctx_get_intf_pd_reason_val(ctx);
    2252           0 :         struct nlsock *nl =
    2253           0 :                 kernel_netlink_nlsock_lookup(dplane_ctx_get_ns_sock(ctx));
    2254             : 
    2255           0 :         if (buflen < sizeof(*req))
    2256             :                 return 0;
    2257             : 
    2258           0 :         memset(req, 0, sizeof(*req));
    2259             : 
    2260           0 :         if (cmd != RTM_SETLINK)
    2261           0 :                 flog_err(
    2262             :                         EC_ZEBRA_INTF_UPDATE_FAILURE,
    2263             :                         "Only RTM_SETLINK message type currently supported in dplane pthread");
    2264             : 
    2265           0 :         req->n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
    2266           0 :         req->n.nlmsg_flags = NLM_F_REQUEST;
    2267           0 :         req->n.nlmsg_type = cmd;
    2268           0 :         req->n.nlmsg_pid = nl->snl.nl_pid;
    2269             : 
    2270           0 :         req->ifa.ifi_index = ifindex;
    2271             : 
    2272           0 :         nl_attr_put8(&req->n, buflen, IFLA_PROTO_DOWN, down);
    2273           0 :         nl_attr_put32(&req->n, buflen, IFLA_LINK, ifindex);
    2274             : 
    2275             :         /* Reason info nest */
    2276           0 :         nest_protodown_reason =
    2277           0 :                 nl_attr_nest(&req->n, buflen, IFLA_PROTO_DOWN_REASON);
    2278             : 
    2279           0 :         if (!nest_protodown_reason)
    2280             :                 return -1;
    2281             : 
    2282           0 :         nl_attr_put32(&req->n, buflen, IFLA_PROTO_DOWN_REASON_MASK,
    2283           0 :                       (1 << frr_protodown_r_bit));
    2284           0 :         nl_attr_put32(&req->n, buflen, IFLA_PROTO_DOWN_REASON_VALUE,
    2285           0 :                       ((int)pd_reason_val) << frr_protodown_r_bit);
    2286             : 
    2287           0 :         nl_attr_nest_end(&req->n, nest_protodown_reason);
    2288             : 
    2289           0 :         if (IS_ZEBRA_DEBUG_KERNEL)
    2290           0 :                 zlog_debug("%s: %s, protodown=%d reason_val=%d ifindex=%u",
    2291             :                            __func__, nl_msg_type_to_str(cmd), down,
    2292             :                            pd_reason_val, ifindex);
    2293             : 
    2294           0 :         return NLMSG_ALIGN(req->n.nlmsg_len);
    2295             : }
    2296             : 
    2297             : /* Interface information read by netlink. */
    2298          93 : void interface_list(struct zebra_ns *zns)
    2299             : {
    2300          93 :         interface_lookup_netlink(zns);
    2301             :         /* We add routes for interface address,
    2302             :          * so we need to get the nexthop info
    2303             :          * from the kernel before we can do that
    2304             :          */
    2305          93 :         netlink_nexthop_read(zns);
    2306             : 
    2307          93 :         interface_addr_lookup_netlink(zns);
    2308          93 : }
    2309             : 
    2310           0 : void if_netlink_set_frr_protodown_r_bit(uint8_t bit)
    2311             : {
    2312           0 :         if (IS_ZEBRA_DEBUG_KERNEL)
    2313           0 :                 zlog_debug(
    2314             :                         "Protodown reason bit index changed: bit-index %u -> bit-index %u",
    2315             :                         frr_protodown_r_bit, bit);
    2316             : 
    2317           0 :         frr_protodown_r_bit = bit;
    2318           0 : }
    2319             : 
    2320           0 : void if_netlink_unset_frr_protodown_r_bit(void)
    2321             : {
    2322           0 :         if (IS_ZEBRA_DEBUG_KERNEL)
    2323           0 :                 zlog_debug(
    2324             :                         "Protodown reason bit index changed: bit-index %u -> bit-index %u",
    2325             :                         frr_protodown_r_bit, FRR_PROTODOWN_REASON_DEFAULT_BIT);
    2326             : 
    2327           0 :         frr_protodown_r_bit = FRR_PROTODOWN_REASON_DEFAULT_BIT;
    2328           0 : }
    2329             : 
    2330             : 
    2331           0 : bool if_netlink_frr_protodown_r_bit_is_set(void)
    2332             : {
    2333           0 :         return (frr_protodown_r_bit != FRR_PROTODOWN_REASON_DEFAULT_BIT);
    2334             : }
    2335             : 
    2336           0 : uint8_t if_netlink_get_frr_protodown_r_bit(void)
    2337             : {
    2338           0 :         return frr_protodown_r_bit;
    2339             : }
    2340             : 
    2341             : /**
    2342             :  * netlink_request_tunneldump() - Request all tunnels from the linux kernel
    2343             :  *
    2344             :  * @zns:        Zebra namespace
    2345             :  * @family:     AF_* netlink family
    2346             :  * @type:       RTM_* (RTM_GETTUNNEL) route type
    2347             :  *
    2348             :  * Return:      Result status
    2349             :  */
    2350           0 : static int netlink_request_tunneldump(struct zebra_ns *zns, int family,
    2351             :                                       int ifindex)
    2352             : {
    2353           0 :         struct {
    2354             :                 struct nlmsghdr n;
    2355             :                 struct tunnel_msg tmsg;
    2356             :                 char buf[256];
    2357             :         } req;
    2358             : 
    2359             :         /* Form the request */
    2360           0 :         memset(&req, 0, sizeof(req));
    2361           0 :         req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct tunnel_msg));
    2362           0 :         req.n.nlmsg_type = RTM_GETTUNNEL;
    2363           0 :         req.n.nlmsg_flags = NLM_F_ROOT | NLM_F_MATCH | NLM_F_REQUEST;
    2364           0 :         req.tmsg.family = family;
    2365           0 :         req.tmsg.ifindex = ifindex;
    2366             : 
    2367           0 :         return netlink_request(&zns->netlink_cmd, &req);
    2368             : }
    2369             : 
    2370             : /*
    2371             :  * Currently we only ask for vxlan l3svd vni information.
    2372             :  * In the future this can be expanded.
    2373             :  */
    2374          93 : int netlink_tunneldump_read(struct zebra_ns *zns)
    2375             : {
    2376          93 :         int ret = 0;
    2377          93 :         struct zebra_dplane_info dp_info;
    2378          93 :         struct route_node *rn;
    2379          93 :         struct interface *tmp_if = NULL;
    2380          93 :         struct zebra_if *zif;
    2381          93 :         struct nlsock *netlink_cmd = &zns->netlink_cmd;
    2382             : 
    2383          93 :         zebra_dplane_info_from_zns(&dp_info, zns, true /*is_cmd*/);
    2384             : 
    2385         462 :         for (rn = route_top(zns->if_table); rn; rn = route_next(rn)) {
    2386         369 :                 tmp_if = (struct interface *)rn->info;
    2387         369 :                 if (!tmp_if)
    2388         138 :                         continue;
    2389         231 :                 zif = tmp_if->info;
    2390         231 :                 if (!zif || zif->zif_type != ZEBRA_IF_VXLAN)
    2391         231 :                         continue;
    2392             : 
    2393           0 :                 ret = netlink_request_tunneldump(zns, PF_BRIDGE,
    2394             :                                                  tmp_if->ifindex);
    2395           0 :                 if (ret < 0)
    2396           0 :                         return ret;
    2397             : 
    2398           0 :                 ret = netlink_parse_info(netlink_interface, netlink_cmd,
    2399             :                                          &dp_info, 0, true);
    2400             : 
    2401           0 :                 if (ret < 0)
    2402           0 :                         return ret;
    2403             :         }
    2404             : 
    2405             :         return 0;
    2406             : }
    2407             : #endif /* GNU_LINUX */

Generated by: LCOV version v1.16-topotato