back to topotato report
topotato coverage report
Current view: top level - staticd - static_zebra.c (source / functions) Hit Total Coverage
Test: test_rip.py::RIPBasic Lines: 192 297 64.6 %
Date: 2023-02-24 18:39:46 Functions: 27 30 90.0 %

          Line data    Source code
       1             : /*
       2             :  * Zebra connect code.
       3             :  * Copyright (C) 2018 Cumulus Networks, Inc.
       4             :  *               Donald Sharp
       5             :  *
       6             :  * This program is free software; you can redistribute it and/or modify it
       7             :  * under the terms of the GNU General Public License as published by the Free
       8             :  * Software Foundation; either version 2 of the License, or (at your option)
       9             :  * any later version.
      10             :  *
      11             :  * This program is distributed in the hope that it will be useful, but WITHOUT
      12             :  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
      13             :  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
      14             :  * more details.
      15             :  *
      16             :  * You should have received a copy of the GNU General Public License along
      17             :  * with this program; see the file COPYING; if not, write to the Free Software
      18             :  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
      19             :  */
      20             : #include <zebra.h>
      21             : 
      22             : #include "thread.h"
      23             : #include "command.h"
      24             : #include "network.h"
      25             : #include "prefix.h"
      26             : #include "routemap.h"
      27             : #include "table.h"
      28             : #include "srcdest_table.h"
      29             : #include "stream.h"
      30             : #include "memory.h"
      31             : #include "zclient.h"
      32             : #include "filter.h"
      33             : #include "plist.h"
      34             : #include "log.h"
      35             : #include "nexthop.h"
      36             : #include "nexthop_group.h"
      37             : #include "hash.h"
      38             : #include "jhash.h"
      39             : 
      40             : #include "static_vrf.h"
      41             : #include "static_routes.h"
      42             : #include "static_zebra.h"
      43             : #include "static_nht.h"
      44             : #include "static_vty.h"
      45             : #include "static_debug.h"
      46             : 
      47          12 : DEFINE_MTYPE_STATIC(STATIC, STATIC_NHT_DATA, "Static Nexthop tracking data");
      48             : PREDECL_HASH(static_nht_hash);
      49             : 
      50             : struct static_nht_data {
      51             :         struct static_nht_hash_item itm;
      52             : 
      53             :         struct prefix nh;
      54             :         safi_t safi;
      55             : 
      56             :         vrf_id_t nh_vrf_id;
      57             : 
      58             :         uint32_t refcount;
      59             :         uint8_t nh_num;
      60             :         bool registered;
      61             : };
      62             : 
      63          12 : static int static_nht_data_cmp(const struct static_nht_data *nhtd1,
      64             :                                const struct static_nht_data *nhtd2)
      65             : {
      66          12 :         if (nhtd1->nh_vrf_id != nhtd2->nh_vrf_id)
      67           0 :                 return numcmp(nhtd1->nh_vrf_id, nhtd2->nh_vrf_id);
      68          12 :         if (nhtd1->safi != nhtd2->safi)
      69           0 :                 return numcmp(nhtd1->safi, nhtd2->safi);
      70             : 
      71          12 :         return prefix_cmp(&nhtd1->nh, &nhtd2->nh);
      72             : }
      73             : 
      74          16 : static unsigned int static_nht_data_hash(const struct static_nht_data *nhtd)
      75             : {
      76          16 :         unsigned int key = 0;
      77             : 
      78          16 :         key = prefix_hash_key(&nhtd->nh);
      79          16 :         return jhash_2words(nhtd->nh_vrf_id, nhtd->safi, key);
      80             : }
      81             : 
      82          72 : DECLARE_HASH(static_nht_hash, struct static_nht_data, itm, static_nht_data_cmp,
      83             :              static_nht_data_hash);
      84             : 
      85             : static struct static_nht_hash_head static_nht_hash[1];
      86             : 
      87             : /* Zebra structure to hold current status. */
      88             : struct zclient *zclient;
      89             : uint32_t zebra_ecmp_count = MULTIPATH_NUM;
      90             : 
      91             : /* Interface addition message from zebra. */
      92          28 : static int static_ifp_create(struct interface *ifp)
      93             : {
      94          28 :         static_ifindex_update(ifp, true);
      95             : 
      96          28 :         return 0;
      97             : }
      98             : 
      99           0 : static int static_ifp_destroy(struct interface *ifp)
     100             : {
     101           0 :         static_ifindex_update(ifp, false);
     102           0 :         return 0;
     103             : }
     104             : 
     105          40 : static int interface_address_add(ZAPI_CALLBACK_ARGS)
     106             : {
     107          40 :         zebra_interface_address_read(cmd, zclient->ibuf, vrf_id);
     108             : 
     109          40 :         return 0;
     110             : }
     111             : 
     112          10 : static int interface_address_delete(ZAPI_CALLBACK_ARGS)
     113             : {
     114          10 :         struct connected *c;
     115             : 
     116          10 :         c = zebra_interface_address_read(cmd, zclient->ibuf, vrf_id);
     117             : 
     118          10 :         if (!c)
     119             :                 return 0;
     120             : 
     121          10 :         connected_free(&c);
     122          10 :         return 0;
     123             : }
     124             : 
     125          10 : static int static_ifp_up(struct interface *ifp)
     126             : {
     127             :         /* Install any static reliant on this interface coming up */
     128          10 :         static_install_intf_nh(ifp);
     129          10 :         static_ifindex_update(ifp, true);
     130             : 
     131          10 :         return 0;
     132             : }
     133             : 
     134          10 : static int static_ifp_down(struct interface *ifp)
     135             : {
     136          10 :         static_ifindex_update(ifp, false);
     137             : 
     138          10 :         return 0;
     139             : }
     140             : 
     141           5 : static int route_notify_owner(ZAPI_CALLBACK_ARGS)
     142             : {
     143           5 :         struct prefix p;
     144           5 :         enum zapi_route_notify_owner note;
     145           5 :         uint32_t table_id;
     146           5 :         safi_t safi;
     147             : 
     148           5 :         if (!zapi_route_notify_decode(zclient->ibuf, &p, &table_id, &note, NULL,
     149             :                                       &safi))
     150             :                 return -1;
     151             : 
     152           5 :         switch (note) {
     153           1 :         case ZAPI_ROUTE_FAIL_INSTALL:
     154           1 :                 static_nht_mark_state(&p, safi, vrf_id, STATIC_NOT_INSTALLED);
     155           1 :                 zlog_warn("%s: Route %pFX failed to install for table: %u",
     156             :                           __func__, &p, table_id);
     157           1 :                 break;
     158           0 :         case ZAPI_ROUTE_BETTER_ADMIN_WON:
     159           0 :                 static_nht_mark_state(&p, safi, vrf_id, STATIC_NOT_INSTALLED);
     160           0 :                 zlog_warn(
     161             :                         "%s: Route %pFX over-ridden by better route for table: %u",
     162             :                         __func__, &p, table_id);
     163           0 :                 break;
     164           3 :         case ZAPI_ROUTE_INSTALLED:
     165           3 :                 static_nht_mark_state(&p, safi, vrf_id, STATIC_INSTALLED);
     166           3 :                 break;
     167           1 :         case ZAPI_ROUTE_REMOVED:
     168           1 :                 static_nht_mark_state(&p, safi, vrf_id, STATIC_NOT_INSTALLED);
     169           1 :                 break;
     170           0 :         case ZAPI_ROUTE_REMOVE_FAIL:
     171           0 :                 static_nht_mark_state(&p, safi, vrf_id, STATIC_INSTALLED);
     172           0 :                 zlog_warn("%s: Route %pFX failure to remove for table: %u",
     173             :                           __func__, &p, table_id);
     174           0 :                 break;
     175             :         }
     176             : 
     177             :         return 0;
     178             : }
     179             : 
     180           4 : static void zebra_connected(struct zclient *zclient)
     181             : {
     182           4 :         zclient_send_reg_requests(zclient, VRF_DEFAULT);
     183             : 
     184           4 :         static_fixup_vrf_ids(vrf_info_lookup(VRF_DEFAULT));
     185           4 : }
     186             : 
     187             : /* API to check whether the configured nexthop address is
     188             :  * one of its local connected address or not.
     189             :  */
     190             : static bool
     191           4 : static_nexthop_is_local(vrf_id_t vrfid, struct prefix *addr, int family)
     192             : {
     193           4 :         if (family == AF_INET) {
     194           4 :                 if (if_address_is_local(&addr->u.prefix4, AF_INET, vrfid))
     195             :                         return true;
     196           0 :         } else if (family == AF_INET6) {
     197           0 :                 if (if_address_is_local(&addr->u.prefix6, AF_INET6, vrfid))
     198             :                         return true;
     199             :         }
     200             :         return false;
     201             : }
     202          12 : static int static_zebra_nexthop_update(ZAPI_CALLBACK_ARGS)
     203             : {
     204          12 :         struct static_nht_data *nhtd, lookup;
     205          12 :         struct zapi_route nhr;
     206          12 :         struct prefix matched;
     207          12 :         afi_t afi = AFI_IP;
     208             : 
     209          12 :         if (!zapi_nexthop_update_decode(zclient->ibuf, &matched, &nhr)) {
     210           0 :                 zlog_err("Failure to decode nexthop update message");
     211           0 :                 return 1;
     212             :         }
     213             : 
     214          12 :         if (zclient->bfd_integration)
     215          12 :                 bfd_nht_update(&matched, &nhr);
     216             : 
     217          12 :         if (matched.family == AF_INET6)
     218           0 :                 afi = AFI_IP6;
     219             : 
     220          12 :         if (nhr.type == ZEBRA_ROUTE_CONNECT) {
     221           4 :                 if (static_nexthop_is_local(vrf_id, &matched,
     222           4 :                                             nhr.prefix.family))
     223           2 :                         nhr.nexthop_num = 0;
     224             :         }
     225             : 
     226          12 :         memset(&lookup, 0, sizeof(lookup));
     227          12 :         lookup.nh = matched;
     228          12 :         lookup.nh_vrf_id = vrf_id;
     229          12 :         lookup.safi = nhr.safi;
     230             : 
     231          12 :         nhtd = static_nht_hash_find(static_nht_hash, &lookup);
     232             : 
     233          12 :         if (nhtd) {
     234          12 :                 nhtd->nh_num = nhr.nexthop_num;
     235             : 
     236          12 :                 static_nht_reset_start(&matched, afi, nhr.safi,
     237             :                                        nhtd->nh_vrf_id);
     238          12 :                 static_nht_update(NULL, &matched, nhr.nexthop_num, afi,
     239             :                                   nhr.safi, nhtd->nh_vrf_id);
     240             :         } else
     241           0 :                 zlog_err("No nhtd?");
     242             : 
     243             :         return 1;
     244             : }
     245             : 
     246           4 : static void static_zebra_capabilities(struct zclient_capabilities *cap)
     247             : {
     248           4 :         mpls_enabled = cap->mpls_enabled;
     249           4 :         zebra_ecmp_count = cap->ecmp;
     250           4 : }
     251             : 
     252             : static struct static_nht_data *
     253           4 : static_nht_hash_getref(const struct static_nht_data *ref)
     254             : {
     255           4 :         struct static_nht_data *nhtd;
     256             : 
     257           4 :         nhtd = static_nht_hash_find(static_nht_hash, ref);
     258           4 :         if (!nhtd) {
     259           4 :                 nhtd = XCALLOC(MTYPE_STATIC_NHT_DATA, sizeof(*nhtd));
     260             : 
     261           4 :                 prefix_copy(&nhtd->nh, &ref->nh);
     262           4 :                 nhtd->nh_vrf_id = ref->nh_vrf_id;
     263           4 :                 nhtd->safi = ref->safi;
     264             : 
     265           4 :                 static_nht_hash_add(static_nht_hash, nhtd);
     266             :         }
     267             : 
     268           4 :         nhtd->refcount++;
     269           4 :         return nhtd;
     270             : }
     271             : 
     272           0 : static bool static_nht_hash_decref(struct static_nht_data **nhtd_p)
     273             : {
     274           0 :         struct static_nht_data *nhtd = *nhtd_p;
     275             : 
     276           0 :         *nhtd_p = NULL;
     277             : 
     278           0 :         if (--nhtd->refcount > 0)
     279             :                 return true;
     280             : 
     281           0 :         static_nht_hash_del(static_nht_hash, nhtd);
     282           0 :         XFREE(MTYPE_STATIC_NHT_DATA, nhtd);
     283           0 :         return false;
     284             : }
     285             : 
     286           4 : static void static_nht_hash_clear(void)
     287             : {
     288           4 :         struct static_nht_data *nhtd;
     289             : 
     290          12 :         while ((nhtd = static_nht_hash_pop(static_nht_hash)))
     291           8 :                 XFREE(MTYPE_STATIC_NHT_DATA, nhtd);
     292           4 : }
     293             : 
     294           4 : static bool static_zebra_nht_get_prefix(const struct static_nexthop *nh,
     295             :                                         struct prefix *p)
     296             : {
     297           4 :         switch (nh->type) {
     298           0 :         case STATIC_IFNAME:
     299             :         case STATIC_BLACKHOLE:
     300           0 :                 p->family = AF_UNSPEC;
     301           0 :                 return false;
     302             : 
     303           4 :         case STATIC_IPV4_GATEWAY:
     304             :         case STATIC_IPV4_GATEWAY_IFNAME:
     305           4 :                 p->family = AF_INET;
     306           4 :                 p->prefixlen = IPV4_MAX_BITLEN;
     307           4 :                 p->u.prefix4 = nh->addr.ipv4;
     308           4 :                 return true;
     309             : 
     310           0 :         case STATIC_IPV6_GATEWAY:
     311             :         case STATIC_IPV6_GATEWAY_IFNAME:
     312           0 :                 p->family = AF_INET6;
     313           0 :                 p->prefixlen = IPV6_MAX_BITLEN;
     314           0 :                 p->u.prefix6 = nh->addr.ipv6;
     315           0 :                 return true;
     316             :         }
     317             : 
     318           0 :         assertf(0, "BUG: someone forgot to add nexthop type %u", nh->type);
     319             :         return false;
     320             : }
     321             : 
     322           4 : void static_zebra_nht_register(struct static_nexthop *nh, bool reg)
     323             : {
     324           4 :         struct static_path *pn = nh->pn;
     325           4 :         struct route_node *rn = pn->rn;
     326           4 :         struct static_route_info *si = static_route_info_from_rnode(rn);
     327           4 :         struct static_nht_data *nhtd, lookup = {};
     328           4 :         uint32_t cmd;
     329             : 
     330           4 :         if (!static_zebra_nht_get_prefix(nh, &lookup.nh))
     331           0 :                 return;
     332           4 :         lookup.nh_vrf_id = nh->nh_vrf_id;
     333           4 :         lookup.safi = si->safi;
     334             : 
     335           4 :         if (nh->nh_registered) {
     336             :                 /* nh->nh_registered means we own a reference on the nhtd */
     337           0 :                 nhtd = static_nht_hash_find(static_nht_hash, &lookup);
     338             : 
     339           0 :                 assertf(nhtd, "BUG: NH %pFX registered but not in hashtable",
     340             :                         &lookup.nh);
     341           4 :         } else if (reg) {
     342           4 :                 nhtd = static_nht_hash_getref(&lookup);
     343             : 
     344           4 :                 if (nhtd->refcount > 1)
     345           0 :                         DEBUGD(&static_dbg_route,
     346             :                                "Reusing registered nexthop(%pFX) for %pRN %d",
     347             :                                &lookup.nh, rn, nhtd->nh_num);
     348             :         } else {
     349             :                 /* !reg && !nh->nh_registered */
     350           0 :                 zlog_warn("trying to unregister nexthop %pFX twice",
     351             :                           &lookup.nh);
     352           0 :                 return;
     353             :         }
     354             : 
     355           4 :         nh->nh_registered = reg;
     356             : 
     357           4 :         if (reg) {
     358           4 :                 if (nhtd->nh_num) {
     359             :                         /* refresh with existing data */
     360           0 :                         afi_t afi = prefix_afi(&lookup.nh);
     361             : 
     362           0 :                         if (nh->state == STATIC_NOT_INSTALLED)
     363           0 :                                 nh->state = STATIC_START;
     364           0 :                         static_nht_update(&rn->p, &nhtd->nh, nhtd->nh_num, afi,
     365             :                                           si->safi, nh->nh_vrf_id);
     366           0 :                         return;
     367             :                 }
     368             : 
     369           4 :                 if (nhtd->registered)
     370             :                         /* have no data, but did send register */
     371             :                         return;
     372             : 
     373           4 :                 cmd = ZEBRA_NEXTHOP_REGISTER;
     374           4 :                 DEBUGD(&static_dbg_route, "Registering nexthop(%pFX) for %pRN",
     375             :                        &lookup.nh, rn);
     376             :         } else {
     377           0 :                 bool was_zebra_registered;
     378             : 
     379           0 :                 was_zebra_registered = nhtd->registered;
     380           0 :                 if (static_nht_hash_decref(&nhtd))
     381             :                         /* still got references alive */
     382             :                         return;
     383             : 
     384             :                 /* NB: nhtd is now NULL. */
     385           0 :                 if (!was_zebra_registered)
     386             :                         return;
     387             : 
     388           0 :                 cmd = ZEBRA_NEXTHOP_UNREGISTER;
     389           0 :                 DEBUGD(&static_dbg_route,
     390             :                        "Unregistering nexthop(%pFX) for %pRN", &lookup.nh, rn);
     391             :         }
     392             : 
     393           4 :         if (zclient_send_rnh(zclient, cmd, &lookup.nh, si->safi, false, false,
     394             :                              nh->nh_vrf_id) == ZCLIENT_SEND_FAILURE)
     395           0 :                 zlog_warn("%s: Failure to send nexthop %pFX for %pRN to zebra",
     396             :                           __func__, &lookup.nh, rn);
     397           4 :         else if (reg)
     398           4 :                 nhtd->registered = true;
     399             : }
     400             : 
     401          12 : extern void static_zebra_route_add(struct static_path *pn, bool install)
     402             : {
     403          12 :         struct route_node *rn = pn->rn;
     404          12 :         struct static_route_info *si = rn->info;
     405          12 :         struct static_nexthop *nh;
     406          12 :         const struct prefix *p, *src_pp;
     407          12 :         struct zapi_nexthop *api_nh;
     408          12 :         struct zapi_route api;
     409          12 :         uint32_t nh_num = 0;
     410             : 
     411          12 :         p = src_pp = NULL;
     412          12 :         srcdest_rnode_prefixes(rn, &p, &src_pp);
     413             : 
     414          12 :         memset(&api, 0, sizeof(api));
     415          12 :         api.vrf_id = si->svrf->vrf->vrf_id;
     416          12 :         api.type = ZEBRA_ROUTE_STATIC;
     417          12 :         api.safi = si->safi;
     418          12 :         memcpy(&api.prefix, p, sizeof(api.prefix));
     419             : 
     420          12 :         if (src_pp) {
     421           0 :                 SET_FLAG(api.message, ZAPI_MESSAGE_SRCPFX);
     422           0 :                 memcpy(&api.src_prefix, src_pp, sizeof(api.src_prefix));
     423             :         }
     424          12 :         SET_FLAG(api.flags, ZEBRA_FLAG_RR_USE_DISTANCE);
     425          12 :         SET_FLAG(api.flags, ZEBRA_FLAG_ALLOW_RECURSION);
     426          12 :         SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
     427          12 :         if (pn->distance) {
     428          12 :                 SET_FLAG(api.message, ZAPI_MESSAGE_DISTANCE);
     429          12 :                 api.distance = pn->distance;
     430             :         }
     431          12 :         if (pn->tag) {
     432           0 :                 SET_FLAG(api.message, ZAPI_MESSAGE_TAG);
     433           0 :                 api.tag = pn->tag;
     434             :         }
     435          12 :         if (pn->table_id != 0) {
     436           0 :                 SET_FLAG(api.message, ZAPI_MESSAGE_TABLEID);
     437           0 :                 api.tableid = pn->table_id;
     438             :         }
     439          48 :         frr_each(static_nexthop_list, &pn->nexthop_list, nh) {
     440             :                 /* Don't overrun the nexthop array */
     441          12 :                 if (nh_num == zebra_ecmp_count)
     442             :                         break;
     443             : 
     444          12 :                 api_nh = &api.nexthops[nh_num];
     445          12 :                 if (nh->nh_vrf_id == VRF_UNKNOWN)
     446           0 :                         continue;
     447             :                 /* Skip next hop which peer is down. */
     448          12 :                 if (nh->path_down)
     449           0 :                         continue;
     450             : 
     451          12 :                 api_nh->vrf_id = nh->nh_vrf_id;
     452          12 :                 if (nh->onlink)
     453           0 :                         SET_FLAG(api_nh->flags, ZAPI_NEXTHOP_FLAG_ONLINK);
     454          12 :                 if (nh->color != 0) {
     455           0 :                         SET_FLAG(api.message, ZAPI_MESSAGE_SRTE);
     456           0 :                         api_nh->srte_color = nh->color;
     457             :                 }
     458             : 
     459          12 :                 nh->state = STATIC_SENT_TO_ZEBRA;
     460             : 
     461          12 :                 switch (nh->type) {
     462           0 :                 case STATIC_IFNAME:
     463           0 :                         if (nh->ifindex == IFINDEX_INTERNAL)
     464           0 :                                 continue;
     465           0 :                         api_nh->ifindex = nh->ifindex;
     466           0 :                         api_nh->type = NEXTHOP_TYPE_IFINDEX;
     467           0 :                         break;
     468          12 :                 case STATIC_IPV4_GATEWAY:
     469          12 :                         if (!nh->nh_valid)
     470           8 :                                 continue;
     471           4 :                         api_nh->type = NEXTHOP_TYPE_IPV4;
     472           4 :                         api_nh->gate = nh->addr;
     473           4 :                         break;
     474           0 :                 case STATIC_IPV4_GATEWAY_IFNAME:
     475           0 :                         if (nh->ifindex == IFINDEX_INTERNAL)
     476           0 :                                 continue;
     477           0 :                         api_nh->ifindex = nh->ifindex;
     478           0 :                         api_nh->type = NEXTHOP_TYPE_IPV4_IFINDEX;
     479           0 :                         api_nh->gate = nh->addr;
     480           0 :                         break;
     481           0 :                 case STATIC_IPV6_GATEWAY:
     482           0 :                         if (!nh->nh_valid)
     483           0 :                                 continue;
     484           0 :                         api_nh->type = NEXTHOP_TYPE_IPV6;
     485           0 :                         api_nh->gate = nh->addr;
     486           0 :                         break;
     487           0 :                 case STATIC_IPV6_GATEWAY_IFNAME:
     488           0 :                         if (nh->ifindex == IFINDEX_INTERNAL)
     489           0 :                                 continue;
     490           0 :                         api_nh->type = NEXTHOP_TYPE_IPV6_IFINDEX;
     491           0 :                         api_nh->ifindex = nh->ifindex;
     492           0 :                         api_nh->gate = nh->addr;
     493           0 :                         break;
     494           0 :                 case STATIC_BLACKHOLE:
     495           0 :                         api_nh->type = NEXTHOP_TYPE_BLACKHOLE;
     496           0 :                         switch (nh->bh_type) {
     497           0 :                         case STATIC_BLACKHOLE_DROP:
     498             :                         case STATIC_BLACKHOLE_NULL:
     499           0 :                                 api_nh->bh_type = BLACKHOLE_NULL;
     500           0 :                                 break;
     501           0 :                         case STATIC_BLACKHOLE_REJECT:
     502           0 :                                 api_nh->bh_type = BLACKHOLE_REJECT;
     503             :                         }
     504             :                         break;
     505             :                 }
     506             : 
     507           4 :                 if (nh->snh_label.num_labels) {
     508           0 :                         int i;
     509             : 
     510           0 :                         SET_FLAG(api_nh->flags, ZAPI_NEXTHOP_FLAG_LABEL);
     511           0 :                         api_nh->label_num = nh->snh_label.num_labels;
     512           0 :                         for (i = 0; i < api_nh->label_num; i++)
     513           0 :                                 api_nh->labels[i] = nh->snh_label.label[i];
     514             :                 }
     515           4 :                 nh_num++;
     516             :         }
     517             : 
     518          12 :         api.nexthop_num = nh_num;
     519             : 
     520             :         /*
     521             :          * If we have been given an install but nothing is valid
     522             :          * go ahead and delete the route for double plus fun
     523             :          */
     524          12 :         if (!nh_num && install)
     525           8 :                 install = false;
     526             : 
     527          12 :         zclient_route_send(install ?
     528             :                            ZEBRA_ROUTE_ADD : ZEBRA_ROUTE_DELETE,
     529             :                            zclient, &api);
     530          12 : }
     531             : 
     532             : static zclient_handler *const static_handlers[] = {
     533             :         [ZEBRA_INTERFACE_ADDRESS_ADD] = interface_address_add,
     534             :         [ZEBRA_INTERFACE_ADDRESS_DELETE] = interface_address_delete,
     535             :         [ZEBRA_ROUTE_NOTIFY_OWNER] = route_notify_owner,
     536             :         [ZEBRA_NEXTHOP_UPDATE] = static_zebra_nexthop_update,
     537             : };
     538             : 
     539           4 : void static_zebra_init(void)
     540             : {
     541           4 :         struct zclient_options opt = { .receive_notify = true };
     542             : 
     543           4 :         if_zapi_callbacks(static_ifp_create, static_ifp_up,
     544             :                           static_ifp_down, static_ifp_destroy);
     545             : 
     546           4 :         zclient = zclient_new(master, &opt, static_handlers,
     547             :                               array_size(static_handlers));
     548             : 
     549           4 :         zclient_init(zclient, ZEBRA_ROUTE_STATIC, 0, &static_privs);
     550           4 :         zclient->zebra_capabilities = static_zebra_capabilities;
     551           4 :         zclient->zebra_connected = zebra_connected;
     552             : 
     553           4 :         static_nht_hash_init(static_nht_hash);
     554           4 :         static_bfd_initialize(zclient, master);
     555           4 : }
     556             : 
     557             : /* static_zebra_stop used by tests/lib/test_grpc.cpp */
     558           4 : void static_zebra_stop(void)
     559             : {
     560           4 :         static_nht_hash_clear();
     561           4 :         static_nht_hash_fini(static_nht_hash);
     562             : 
     563           4 :         if (!zclient)
     564             :                 return;
     565           4 :         zclient_stop(zclient);
     566           4 :         zclient_free(zclient);
     567           4 :         zclient = NULL;
     568             : }
     569             : 
     570           4 : void static_zebra_vrf_register(struct vrf *vrf)
     571             : {
     572           4 :         if (vrf->vrf_id == VRF_DEFAULT)
     573             :                 return;
     574           0 :         zclient_send_reg_requests(zclient, vrf->vrf_id);
     575             : }
     576             : 
     577           4 : void static_zebra_vrf_unregister(struct vrf *vrf)
     578             : {
     579           4 :         if (vrf->vrf_id == VRF_DEFAULT)
     580             :                 return;
     581           0 :         zclient_send_dereg_requests(zclient, vrf->vrf_id);
     582             : }

Generated by: LCOV version v1.16-topotato