back to topotato report
topotato coverage report
Current view: top level - pimd - pim_zebra.c (source / functions) Hit Total Coverage
Test: test_pim_bfd.py::PIMBFDTest Lines: 104 209 49.8 %
Date: 2023-02-24 18:39:40 Functions: 12 20 60.0 %

          Line data    Source code
       1             : /*
       2             :  * PIM for Quagga
       3             :  * Copyright (C) 2008  Everton da Silva Marques
       4             :  *
       5             :  * This program is free software; you can redistribute it and/or modify
       6             :  * it under the terms of the GNU General Public License as published by
       7             :  * the Free Software Foundation; either version 2 of the License, or
       8             :  * (at your option) any later version.
       9             :  *
      10             :  * This program is distributed in the hope that it will be useful, but
      11             :  * WITHOUT ANY WARRANTY; without even the implied warranty of
      12             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      13             :  * General Public License for more details.
      14             :  *
      15             :  * You should have received a copy of the GNU General Public License along
      16             :  * with this program; see the file COPYING; if not, write to the Free Software
      17             :  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
      18             :  */
      19             : 
      20             : #include <zebra.h>
      21             : 
      22             : #include "if.h"
      23             : #include "log.h"
      24             : #include "prefix.h"
      25             : #include "zclient.h"
      26             : #include "stream.h"
      27             : #include "network.h"
      28             : #include "vty.h"
      29             : #include "plist.h"
      30             : #include "lib/bfd.h"
      31             : 
      32             : #include "pimd.h"
      33             : #include "pim_pim.h"
      34             : #include "pim_zebra.h"
      35             : #include "pim_iface.h"
      36             : #include "pim_str.h"
      37             : #include "pim_oil.h"
      38             : #include "pim_rpf.h"
      39             : #include "pim_time.h"
      40             : #include "pim_join.h"
      41             : #include "pim_zlookup.h"
      42             : #include "pim_ifchannel.h"
      43             : #include "pim_rp.h"
      44             : #include "pim_igmpv3.h"
      45             : #include "pim_jp_agg.h"
      46             : #include "pim_nht.h"
      47             : #include "pim_ssm.h"
      48             : #include "pim_vxlan.h"
      49             : #include "pim_mlag.h"
      50             : 
      51             : #undef PIM_DEBUG_IFADDR_DUMP
      52             : #define PIM_DEBUG_IFADDR_DUMP
      53             : 
      54             : struct zclient *zclient;
      55             : 
      56             : 
      57             : /* Router-id update message from zebra. */
      58           4 : static int pim_router_id_update_zebra(ZAPI_CALLBACK_ARGS)
      59             : {
      60           4 :         struct prefix router_id;
      61             : 
      62           4 :         zebra_router_id_update_read(zclient->ibuf, &router_id);
      63             : 
      64           4 :         return 0;
      65             : }
      66             : 
      67           0 : static int pim_zebra_interface_vrf_update(ZAPI_CALLBACK_ARGS)
      68             : {
      69           0 :         struct interface *ifp;
      70           0 :         vrf_id_t new_vrf_id;
      71             : 
      72           0 :         ifp = zebra_interface_vrf_update_read(zclient->ibuf, vrf_id,
      73             :                                               &new_vrf_id);
      74           0 :         if (!ifp)
      75             :                 return 0;
      76             : 
      77           0 :         if (PIM_DEBUG_ZEBRA)
      78           0 :                 zlog_debug("%s: %s updating from %u to %u", __func__, ifp->name,
      79             :                            vrf_id, new_vrf_id);
      80             : 
      81           0 :         if_update_to_new_vrf(ifp, new_vrf_id);
      82             : 
      83           0 :         return 0;
      84             : }
      85             : 
      86             : #ifdef PIM_DEBUG_IFADDR_DUMP
      87           0 : static void dump_if_address(struct interface *ifp)
      88             : {
      89           0 :         struct connected *ifc;
      90           0 :         struct listnode *node;
      91             : 
      92           0 :         zlog_debug("%s %s: interface %s addresses:", __FILE__, __func__,
      93             :                    ifp->name);
      94             : 
      95           0 :         for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, ifc)) {
      96           0 :                 struct prefix *p = ifc->address;
      97             : 
      98           0 :                 if (p->family != AF_INET)
      99           0 :                         continue;
     100             : 
     101           0 :                 zlog_debug("%s %s: interface %s address %pI4 %s", __FILE__,
     102             :                            __func__, ifp->name, &p->u.prefix4,
     103             :                            CHECK_FLAG(ifc->flags, ZEBRA_IFA_SECONDARY)
     104             :                                    ? "secondary"
     105             :                                    : "primary");
     106             :         }
     107           0 : }
     108             : #endif
     109             : 
     110          42 : static int pim_zebra_if_address_add(ZAPI_CALLBACK_ARGS)
     111             : {
     112          42 :         struct connected *c;
     113          42 :         struct prefix *p;
     114          42 :         struct pim_interface *pim_ifp;
     115             : 
     116             :         /*
     117             :           zebra api notifies address adds/dels events by using the same call
     118             :           interface_add_read below, see comments in lib/zclient.c
     119             : 
     120             :           zebra_interface_address_read(ZEBRA_INTERFACE_ADDRESS_ADD, ...)
     121             :           will add address to interface list by calling
     122             :           connected_add_by_prefix()
     123             :         */
     124          42 :         c = zebra_interface_address_read(cmd, zclient->ibuf, vrf_id);
     125          42 :         if (!c)
     126             :                 return 0;
     127             : 
     128          42 :         pim_ifp = c->ifp->info;
     129          42 :         p = c->address;
     130             : 
     131          42 :         if (PIM_DEBUG_ZEBRA) {
     132           0 :                 zlog_debug("%s: %s(%u) connected IP address %pFX flags %u %s",
     133             :                            __func__, c->ifp->name, vrf_id, p, c->flags,
     134             :                            CHECK_FLAG(c->flags, ZEBRA_IFA_SECONDARY)
     135             :                                    ? "secondary"
     136             :                                    : "primary");
     137             : 
     138             : #ifdef PIM_DEBUG_IFADDR_DUMP
     139           0 :                 dump_if_address(c->ifp);
     140             : #endif
     141             :         }
     142             : 
     143             : #if PIM_IPV == 4
     144          42 :         if (p->family != PIM_AF)
     145          15 :                 SET_FLAG(c->flags, ZEBRA_IFA_SECONDARY);
     146          27 :         else if (!CHECK_FLAG(c->flags, ZEBRA_IFA_SECONDARY)) {
     147             :                 /* trying to add primary address? */
     148          27 :                 pim_addr primary_addr = pim_find_primary_addr(c->ifp);
     149          27 :                 pim_addr addr = pim_addr_from_prefix(p);
     150             : 
     151          27 :                 if (pim_addr_cmp(primary_addr, addr)) {
     152           0 :                         if (PIM_DEBUG_ZEBRA)
     153           0 :                                 zlog_warn(
     154             :                                         "%s: %s : forcing secondary flag on %pFX",
     155             :                                         __func__, c->ifp->name, p);
     156           0 :                         SET_FLAG(c->flags, ZEBRA_IFA_SECONDARY);
     157             :                 }
     158             :         }
     159             : #else /* PIM_IPV != 4 */
     160             :         if (p->family != PIM_AF)
     161             :                 return 0;
     162             : #endif
     163             : 
     164          42 :         pim_if_addr_add(c);
     165          42 :         if (pim_ifp) {
     166          26 :                 struct pim_instance *pim;
     167             : 
     168          26 :                 pim = pim_get_pim_instance(vrf_id);
     169          26 :                 if (!pim) {
     170           0 :                         if (PIM_DEBUG_ZEBRA)
     171           0 :                                 zlog_debug("%s: Unable to find pim instance",
     172             :                                            __func__);
     173           0 :                         return 0;
     174             :                 }
     175             : 
     176          26 :                 pim_ifp->pim = pim;
     177             : 
     178          26 :                 pim_rp_check_on_if_add(pim_ifp);
     179             :         }
     180             : 
     181          42 :         if (if_is_loopback(c->ifp)) {
     182          16 :                 struct vrf *vrf = vrf_lookup_by_id(vrf_id);
     183          16 :                 struct interface *ifp;
     184             : 
     185          88 :                 FOR_ALL_INTERFACES (vrf, ifp) {
     186          56 :                         if (!if_is_loopback(ifp) && if_is_operative(ifp))
     187          12 :                                 pim_if_addr_add_all(ifp);
     188             :                 }
     189             :         }
     190             :         return 0;
     191             : }
     192             : 
     193           8 : static int pim_zebra_if_address_del(ZAPI_CALLBACK_ARGS)
     194             : {
     195           8 :         struct connected *c;
     196           8 :         struct prefix *p;
     197           8 :         struct vrf *vrf = vrf_lookup_by_id(vrf_id);
     198             : 
     199           8 :         if (!vrf)
     200             :                 return 0;
     201             : 
     202             :         /*
     203             :           zebra api notifies address adds/dels events by using the same call
     204             :           interface_add_read below, see comments in lib/zclient.c
     205             : 
     206             :           zebra_interface_address_read(ZEBRA_INTERFACE_ADDRESS_DELETE, ...)
     207             :           will remove address from interface list by calling
     208             :           connected_delete_by_prefix()
     209             :         */
     210           8 :         c = zebra_interface_address_read(cmd, zclient->ibuf, vrf_id);
     211           8 :         if (!c)
     212             :                 return 0;
     213             : 
     214           8 :         p = c->address;
     215             : 
     216           8 :         if (PIM_DEBUG_ZEBRA) {
     217           0 :                 zlog_debug(
     218             :                         "%s: %s(%u) disconnected IP address %pFX flags %u %s",
     219             :                         __func__, c->ifp->name, vrf_id, p, c->flags,
     220             :                         CHECK_FLAG(c->flags, ZEBRA_IFA_SECONDARY)
     221             :                                 ? "secondary"
     222             :                                 : "primary");
     223             : #ifdef PIM_DEBUG_IFADDR_DUMP
     224           0 :                 dump_if_address(c->ifp);
     225             : #endif
     226             :         }
     227             : 
     228           8 :         if (p->family == PIM_AF) {
     229           7 :                 struct pim_instance *pim;
     230             : 
     231           7 :                 pim = vrf->info;
     232           7 :                 pim_if_addr_del(c, 0);
     233           7 :                 pim_rp_setup(pim);
     234           7 :                 pim_i_am_rp_re_evaluate(pim);
     235             :         }
     236             : 
     237           8 :         connected_free(&c);
     238           8 :         return 0;
     239             : }
     240             : 
     241           8 : void pim_zebra_update_all_interfaces(struct pim_instance *pim)
     242             : {
     243           8 :         struct interface *ifp;
     244             : 
     245          48 :         FOR_ALL_INTERFACES (pim->vrf, ifp) {
     246          32 :                 struct pim_interface *pim_ifp = ifp->info;
     247          32 :                 struct pim_iface_upstream_switch *us;
     248          32 :                 struct listnode *node;
     249             : 
     250          32 :                 if (!pim_ifp)
     251           8 :                         continue;
     252             : 
     253          48 :                 for (ALL_LIST_ELEMENTS_RO(pim_ifp->upstream_switch_list, node,
     254             :                                           us)) {
     255           0 :                         struct pim_rpf rpf;
     256             : 
     257           0 :                         rpf.source_nexthop.interface = ifp;
     258           0 :                         rpf.rpf_addr = us->address;
     259           0 :                         pim_joinprune_send(&rpf, us->us);
     260           0 :                         pim_jp_agg_clear_group(us->us);
     261             :                 }
     262             :         }
     263           8 : }
     264             : 
     265           0 : void pim_zebra_upstream_rpf_changed(struct pim_instance *pim,
     266             :                                     struct pim_upstream *up,
     267             :                                     struct pim_rpf *old)
     268             : {
     269           0 :         if (old->source_nexthop.interface) {
     270           0 :                 struct pim_neighbor *nbr;
     271             : 
     272           0 :                 nbr = pim_neighbor_find(old->source_nexthop.interface,
     273             :                                         old->rpf_addr);
     274           0 :                 if (nbr)
     275           0 :                         pim_jp_agg_remove_group(nbr->upstream_jp_agg, up, nbr);
     276             : 
     277             :                 /*
     278             :                  * We have detected a case where we might need
     279             :                  * to rescan the inherited o_list so do it.
     280             :                  */
     281           0 :                 if (up->channel_oil->oil_inherited_rescan) {
     282           0 :                         pim_upstream_inherited_olist_decide(pim, up);
     283           0 :                         up->channel_oil->oil_inherited_rescan = 0;
     284             :                 }
     285             : 
     286           0 :                 if (up->join_state == PIM_UPSTREAM_JOINED) {
     287             :                         /*
     288             :                          * If we come up real fast we can be here
     289             :                          * where the mroute has not been installed
     290             :                          * so install it.
     291             :                          */
     292           0 :                         if (!up->channel_oil->installed)
     293           0 :                                 pim_upstream_mroute_add(up->channel_oil,
     294             :                                                         __func__);
     295             : 
     296             :                         /*
     297             :                          * RFC 4601: 4.5.7.  Sending (S,G)
     298             :                          * Join/Prune Messages
     299             :                          *
     300             :                          * Transitions from Joined State
     301             :                          *
     302             :                          * RPF'(S,G) changes not due to an Assert
     303             :                          *
     304             :                          * The upstream (S,G) state machine remains
     305             :                          * in Joined state. Send Join(S,G) to the new
     306             :                          * upstream neighbor, which is the new value
     307             :                          * of RPF'(S,G).  Send Prune(S,G) to the old
     308             :                          * upstream neighbor, which is the old value
     309             :                          * of RPF'(S,G).  Set the Join Timer (JT) to
     310             :                          * expire after t_periodic seconds.
     311             :                          */
     312           0 :                         pim_jp_agg_switch_interface(old, &up->rpf, up);
     313             : 
     314           0 :                         pim_upstream_join_timer_restart(up, old);
     315             :                 } /* up->join_state == PIM_UPSTREAM_JOINED */
     316             :         }
     317             : 
     318             :         else {
     319             :                 /*
     320             :                  * We have detected a case where we might need
     321             :                  * to rescan the inherited o_list so do it.
     322             :                  */
     323           0 :                 if (up->channel_oil->oil_inherited_rescan) {
     324           0 :                         pim_upstream_inherited_olist_decide(pim, up);
     325           0 :                         up->channel_oil->oil_inherited_rescan = 0;
     326             :                 }
     327             : 
     328           0 :                 if (up->join_state == PIM_UPSTREAM_JOINED)
     329           0 :                         pim_jp_agg_switch_interface(old, &up->rpf, up);
     330             : 
     331           0 :                 if (!up->channel_oil->installed)
     332           0 :                         pim_upstream_mroute_add(up->channel_oil, __func__);
     333             :         }
     334             : 
     335             :         /* FIXME can join_desired actually be changed by pim_rpf_update()
     336             :          * returning PIM_RPF_CHANGED ?
     337             :          */
     338           0 :         pim_upstream_update_join_desired(pim, up);
     339           0 : }
     340             : 
     341             : __attribute__((unused))
     342           0 : static int pim_zebra_vxlan_sg_proc(ZAPI_CALLBACK_ARGS)
     343             : {
     344           0 :         struct stream *s;
     345           0 :         struct pim_instance *pim;
     346           0 :         pim_sgaddr sg;
     347           0 :         size_t prefixlen;
     348             : 
     349           0 :         pim = pim_get_pim_instance(vrf_id);
     350           0 :         if (!pim)
     351             :                 return 0;
     352             : 
     353           0 :         s = zclient->ibuf;
     354             : 
     355           0 :         prefixlen = stream_getl(s);
     356           0 :         stream_get(&sg.src, s, prefixlen);
     357           0 :         stream_get(&sg.grp, s, prefixlen);
     358             : 
     359           0 :         if (PIM_DEBUG_ZEBRA)
     360           0 :                 zlog_debug("%u:recv SG %s %pSG", vrf_id,
     361             :                            (cmd == ZEBRA_VXLAN_SG_ADD) ? "add" : "del", &sg);
     362             : 
     363           0 :         if (cmd == ZEBRA_VXLAN_SG_ADD)
     364           0 :                 pim_vxlan_sg_add(pim, &sg);
     365             :         else
     366           0 :                 pim_vxlan_sg_del(pim, &sg);
     367             : 
     368             :         return 0;
     369             : }
     370             : 
     371             : __attribute__((unused))
     372           4 : static void pim_zebra_vxlan_replay(void)
     373             : {
     374           4 :         struct stream *s = NULL;
     375             : 
     376             :         /* Check socket. */
     377           4 :         if (!zclient || zclient->sock < 0)
     378             :                 return;
     379             : 
     380           4 :         s = zclient->obuf;
     381           4 :         stream_reset(s);
     382             : 
     383           4 :         zclient_create_header(s, ZEBRA_VXLAN_SG_REPLAY, VRF_DEFAULT);
     384           4 :         stream_putw_at(s, 0, stream_get_endp(s));
     385             : 
     386           4 :         zclient_send_message(zclient);
     387             : }
     388             : 
     389           9 : void pim_scan_oil(struct pim_instance *pim)
     390             : {
     391           9 :         struct channel_oil *c_oil;
     392             : 
     393           9 :         pim->scan_oil_last = pim_time_monotonic_sec();
     394           9 :         ++pim->scan_oil_events;
     395             : 
     396          18 :         frr_each (rb_pim_oil, &pim->channel_oil_head, c_oil)
     397           0 :                 pim_upstream_mroute_iif_update(c_oil, __func__);
     398           9 : }
     399             : 
     400           9 : static void on_rpf_cache_refresh(struct thread *t)
     401             : {
     402           9 :         struct pim_instance *pim = THREAD_ARG(t);
     403             : 
     404             :         /* update kernel multicast forwarding cache (MFC) */
     405           9 :         pim_scan_oil(pim);
     406             : 
     407           9 :         pim->rpf_cache_refresh_last = pim_time_monotonic_sec();
     408           9 :         ++pim->rpf_cache_refresh_events;
     409             : 
     410             :         // It is called as part of pim_neighbor_add
     411             :         // pim_rp_setup ();
     412           9 : }
     413             : 
     414          16 : void sched_rpf_cache_refresh(struct pim_instance *pim)
     415             : {
     416          16 :         ++pim->rpf_cache_refresh_requests;
     417             : 
     418          16 :         pim_rpf_set_refresh_time(pim);
     419             : 
     420          16 :         if (pim->rpf_cache_refresher) {
     421             :                 /* Refresh timer is already running */
     422             :                 return;
     423             :         }
     424             : 
     425             :         /* Start refresh timer */
     426             : 
     427          12 :         if (PIM_DEBUG_ZEBRA) {
     428           0 :                 zlog_debug("%s: triggering %ld msec timer", __func__,
     429             :                            router->rpf_cache_refresh_delay_msec);
     430             :         }
     431             : 
     432          12 :         thread_add_timer_msec(router->master, on_rpf_cache_refresh, pim,
     433             :                               router->rpf_cache_refresh_delay_msec,
     434             :                               &pim->rpf_cache_refresher);
     435             : }
     436             : 
     437           4 : static void pim_zebra_connected(struct zclient *zclient)
     438             : {
     439             : #if PIM_IPV == 4
     440             :         /* Send the client registration */
     441           4 :         bfd_client_sendmsg(zclient, ZEBRA_BFD_CLIENT_REGISTER, router->vrf_id);
     442             : #endif
     443             : 
     444           4 :         zclient_send_reg_requests(zclient, router->vrf_id);
     445             : 
     446             : #if PIM_IPV == 4
     447             :         /* request for VxLAN BUM group addresses */
     448           4 :         pim_zebra_vxlan_replay();
     449             : #endif
     450           4 : }
     451             : 
     452           4 : static void pim_zebra_capabilities(struct zclient_capabilities *cap)
     453             : {
     454           4 :         router->mlag_role = cap->role;
     455           4 :         router->multipath = cap->ecmp;
     456           4 : }
     457             : 
     458             : static zclient_handler *const pim_handlers[] = {
     459             :         [ZEBRA_INTERFACE_ADDRESS_ADD] = pim_zebra_if_address_add,
     460             :         [ZEBRA_INTERFACE_ADDRESS_DELETE] = pim_zebra_if_address_del,
     461             : 
     462             :         [ZEBRA_NEXTHOP_UPDATE] = pim_parse_nexthop_update,
     463             :         [ZEBRA_ROUTER_ID_UPDATE] = pim_router_id_update_zebra,
     464             :         [ZEBRA_INTERFACE_VRF_UPDATE] = pim_zebra_interface_vrf_update,
     465             : 
     466             : #if PIM_IPV == 4
     467             :         [ZEBRA_VXLAN_SG_ADD] = pim_zebra_vxlan_sg_proc,
     468             :         [ZEBRA_VXLAN_SG_DEL] = pim_zebra_vxlan_sg_proc,
     469             : 
     470             :         [ZEBRA_MLAG_PROCESS_UP] = pim_zebra_mlag_process_up,
     471             :         [ZEBRA_MLAG_PROCESS_DOWN] = pim_zebra_mlag_process_down,
     472             :         [ZEBRA_MLAG_FORWARD_MSG] = pim_zebra_mlag_handle_msg,
     473             : #endif
     474             : };
     475             : 
     476           4 : void pim_zebra_init(void)
     477             : {
     478             :         /* Socket for receiving updates from Zebra daemon */
     479           4 :         zclient = zclient_new(router->master, &zclient_options_default,
     480             :                               pim_handlers, array_size(pim_handlers));
     481             : 
     482           4 :         zclient->zebra_capabilities = pim_zebra_capabilities;
     483           4 :         zclient->zebra_connected = pim_zebra_connected;
     484             : 
     485           4 :         zclient_init(zclient, ZEBRA_ROUTE_PIM, 0, &pimd_privs);
     486           4 :         if (PIM_DEBUG_PIM_TRACE) {
     487           0 :                 zlog_notice("%s: zclient socket initialized", __func__);
     488             :         }
     489             : 
     490           4 :         zclient_lookup_new();
     491           4 : }
     492             : 
     493           0 : void pim_forward_start(struct pim_ifchannel *ch)
     494             : {
     495           0 :         struct pim_upstream *up = ch->upstream;
     496           0 :         uint32_t mask = 0;
     497             : 
     498           0 :         if (PIM_DEBUG_PIM_TRACE)
     499           0 :                 zlog_debug("%s: (S,G)=%pSG oif=%s (%pPA)", __func__, &ch->sg,
     500             :                            ch->interface->name, &up->upstream_addr);
     501             : 
     502           0 :         if (PIM_IF_FLAG_TEST_PROTO_IGMP(ch->flags))
     503           0 :                 mask = PIM_OIF_FLAG_PROTO_GM;
     504             : 
     505           0 :         if (PIM_IF_FLAG_TEST_PROTO_PIM(ch->flags))
     506           0 :                 mask |= PIM_OIF_FLAG_PROTO_PIM;
     507             : 
     508           0 :         pim_channel_add_oif(up->channel_oil, ch->interface,
     509             :                         mask, __func__);
     510           0 : }
     511             : 
     512           0 : void pim_forward_stop(struct pim_ifchannel *ch)
     513             : {
     514           0 :         struct pim_upstream *up = ch->upstream;
     515             : 
     516           0 :         if (PIM_DEBUG_PIM_TRACE) {
     517           0 :                 zlog_debug("%s: (S,G)=%s oif=%s installed: %d",
     518             :                            __func__, ch->sg_str, ch->interface->name,
     519             :                            up->channel_oil->installed);
     520             :         }
     521             : 
     522             :         /*
     523             :          * If a channel is being removed, check to see if we still need
     524             :          * to inherit the interface.  If so make sure it is added in
     525             :          */
     526           0 :         if (pim_upstream_evaluate_join_desired_interface(up, ch, ch->parent))
     527           0 :                 pim_channel_add_oif(up->channel_oil, ch->interface,
     528             :                                     PIM_OIF_FLAG_PROTO_PIM, __func__);
     529             :         else
     530           0 :                 pim_channel_del_oif(up->channel_oil, ch->interface,
     531             :                                     PIM_OIF_FLAG_PROTO_PIM, __func__);
     532           0 : }
     533             : 
     534           0 : void pim_zebra_zclient_update(struct vty *vty)
     535             : {
     536           0 :         vty_out(vty, "Zclient update socket: ");
     537             : 
     538           0 :         if (zclient) {
     539           0 :                 vty_out(vty, "%d failures=%d\n", zclient->sock, zclient->fail);
     540             :         } else {
     541           0 :                 vty_out(vty, "<null zclient>\n");
     542             :         }
     543           0 : }
     544             : 
     545          52 : struct zclient *pim_zebra_zclient_get(void)
     546             : {
     547          52 :         if (zclient)
     548             :                 return zclient;
     549             :         else
     550           0 :                 return NULL;
     551             : }
     552             : 
     553           0 : void pim_zebra_interface_set_master(struct interface *vrf,
     554             :                                     struct interface *ifp)
     555             : {
     556           0 :         zclient_interface_set_master(zclient, vrf, ifp);
     557           0 : }

Generated by: LCOV version v1.16-topotato