back to topotato report
topotato coverage report
Current view: top level - zebra - redistribute.c (source / functions) Hit Total Coverage
Test: test_bgp_ecmp_enhe.py::BGP_Unnumbered_ECMP Lines: 156 442 35.3 %
Date: 2023-11-16 17:19:14 Functions: 13 54 24.1 %

          Line data    Source code
       1             : // SPDX-License-Identifier: GPL-2.0-or-later
       2             : /* Redistribution Handler
       3             :  * Copyright (C) 1998 Kunihiro Ishiguro
       4             :  */
       5             : 
       6             : #include <zebra.h>
       7             : 
       8             : #include "vector.h"
       9             : #include "vty.h"
      10             : #include "command.h"
      11             : #include "prefix.h"
      12             : #include "table.h"
      13             : #include "stream.h"
      14             : #include "zclient.h"
      15             : #include "linklist.h"
      16             : #include "log.h"
      17             : #include "vrf.h"
      18             : #include "srcdest_table.h"
      19             : #include "frrdistance.h"
      20             : 
      21             : #include "zebra/rib.h"
      22             : #include "zebra/zebra_router.h"
      23             : #include "zebra/zebra_ns.h"
      24             : #include "zebra/zebra_vrf.h"
      25             : #include "zebra/zebra_routemap.h"
      26             : #include "zebra/redistribute.h"
      27             : #include "zebra/debug.h"
      28             : #include "zebra/router-id.h"
      29             : #include "zebra/zapi_msg.h"
      30             : #include "zebra/zebra_vxlan.h"
      31             : #include "zebra/zebra_errors.h"
      32             : #include "zebra/zebra_neigh.h"
      33             : 
      34             : #define ZEBRA_PTM_SUPPORT
      35             : 
      36             : /* array holding redistribute info about table redistribution */
      37             : /* bit AFI is set if that AFI is redistributing routes from this table */
      38             : static int zebra_import_table_used[AFI_MAX][ZEBRA_KERNEL_TABLE_MAX];
      39             : static uint32_t zebra_import_table_distance[AFI_MAX][ZEBRA_KERNEL_TABLE_MAX];
      40             : 
      41          56 : int is_zebra_import_table_enabled(afi_t afi, vrf_id_t vrf_id, uint32_t table_id)
      42             : {
      43             :         /*
      44             :          * Make sure that what we are called with actualy makes sense
      45             :          */
      46          56 :         if (afi == AFI_MAX)
      47             :                 return 0;
      48             : 
      49          56 :         if (is_zebra_valid_kernel_table(table_id) &&
      50             :             table_id < ZEBRA_KERNEL_TABLE_MAX)
      51           0 :                 return zebra_import_table_used[afi][table_id];
      52             :         return 0;
      53             : }
      54             : 
      55           0 : static void zebra_redistribute_default(struct zserv *client, vrf_id_t vrf_id)
      56             : {
      57           0 :         int afi;
      58           0 :         struct prefix p;
      59           0 :         struct route_table *table;
      60           0 :         struct route_node *rn;
      61           0 :         struct route_entry *newre;
      62             : 
      63           0 :         for (afi = AFI_IP; afi <= AFI_IP6; afi++) {
      64             : 
      65           0 :                 if (!vrf_bitmap_check(&client->redist_default[afi], vrf_id))
      66           0 :                         continue;
      67             : 
      68             :                 /* Lookup table.  */
      69           0 :                 table = zebra_vrf_table(afi, SAFI_UNICAST, vrf_id);
      70           0 :                 if (!table)
      71           0 :                         continue;
      72             : 
      73             :                 /* Lookup default route. */
      74           0 :                 memset(&p, 0, sizeof(p));
      75           0 :                 p.family = afi2family(afi);
      76           0 :                 rn = route_node_lookup(table, &p);
      77           0 :                 if (!rn)
      78           0 :                         continue;
      79             : 
      80           0 :                 RNODE_FOREACH_RE (rn, newre) {
      81           0 :                         if (CHECK_FLAG(newre->flags, ZEBRA_FLAG_SELECTED))
      82           0 :                                 zsend_redistribute_route(ZEBRA_REDISTRIBUTE_ROUTE_ADD,
      83             :                                                          client, rn, newre, false);
      84             :                 }
      85             : 
      86           0 :                 route_unlock_node(rn);
      87             :         }
      88           0 : }
      89             : 
      90             : /* Redistribute routes. */
      91           2 : static void zebra_redistribute(struct zserv *client, int type,
      92             :                                unsigned short instance, struct zebra_vrf *zvrf,
      93             :                                int afi)
      94             : {
      95           2 :         struct route_entry *newre;
      96           2 :         struct route_table *table;
      97           2 :         struct route_node *rn;
      98           2 :         bool is_table_direct = false;
      99           2 :         vrf_id_t vrf_id = zvrf_id(zvrf);
     100             : 
     101           2 :         if (type == ZEBRA_ROUTE_TABLE_DIRECT) {
     102           0 :                 if (vrf_id == VRF_DEFAULT) {
     103           0 :                         table = zebra_router_find_table(zvrf, instance, afi,
     104             :                                                         SAFI_UNICAST);
     105           0 :                         type = ZEBRA_ROUTE_ALL;
     106           0 :                         is_table_direct = true;
     107             :                 } else
     108             :                         return;
     109             :         } else
     110           2 :                 table = zebra_vrf_table(afi, SAFI_UNICAST, vrf_id);
     111             : 
     112           2 :         if (!table)
     113             :                 return;
     114             : 
     115          10 :         for (rn = route_top(table); rn; rn = srcdest_route_next(rn))
     116          24 :                 RNODE_FOREACH_RE (rn, newre) {
     117           4 :                         if (IS_ZEBRA_DEBUG_RIB)
     118           4 :                                 zlog_debug(
     119             :                                         "%s: client %s %pRN(%u:%u) checking: selected=%d, type=%s, instance=%u, distance=%d, metric=%d zebra_check_addr=%d",
     120             :                                         __func__,
     121             :                                         zebra_route_string(client->proto), rn,
     122             :                                         vrf_id, newre->instance,
     123             :                                         !!CHECK_FLAG(newre->flags,
     124             :                                                      ZEBRA_FLAG_SELECTED),
     125             :                                         zebra_route_string(newre->type),
     126             :                                         newre->instance,
     127             :                                         newre->distance,
     128             :                                         newre->metric,
     129             :                                         zebra_check_addr(&rn->p));
     130             : 
     131           4 :                         if (!CHECK_FLAG(newre->flags, ZEBRA_FLAG_SELECTED))
     132           0 :                                 continue;
     133           4 :                         if ((type != ZEBRA_ROUTE_ALL
     134           4 :                              && (newre->type != type
     135           4 :                                  || newre->instance != instance)))
     136           0 :                                 continue;
     137           4 :                         if (!zebra_check_addr(&rn->p))
     138           0 :                                 continue;
     139             : 
     140           4 :                         zsend_redistribute_route(ZEBRA_REDISTRIBUTE_ROUTE_ADD,
     141             :                                                  client, rn, newre, is_table_direct);
     142             :                 }
     143             : }
     144             : 
     145             : /*
     146             :  * Function to return a valid table id value if table-direct is used
     147             :  * return 0 otherwise
     148             :  * This function can be called only if zebra_redistribute_check returns TRUE
     149             :  */
     150           3 : static bool zebra_redistribute_is_table_direct(const struct route_entry *re)
     151             : {
     152           3 :         struct zebra_vrf *zvrf;
     153             : 
     154           3 :         zvrf = zebra_vrf_lookup_by_id(re->vrf_id);
     155           3 :         if (re->vrf_id == VRF_DEFAULT && zvrf->table_id != re->table)
     156           0 :                 return true;
     157             :         return false;
     158             : }
     159             : 
     160             : /*
     161             :  * Function to check if prefix is candidate for
     162             :  * redistribute.
     163             :  */
     164          63 : static bool zebra_redistribute_check(const struct route_node *rn,
     165             :                                      const struct route_entry *re,
     166             :                                      struct zserv *client)
     167             : {
     168          63 :         struct zebra_vrf *zvrf;
     169          63 :         afi_t afi;
     170             : 
     171             :         /* Process only if there is valid re */
     172          63 :         if (!re)
     173             :                 return false;
     174             : 
     175          32 :         afi = family2afi(rn->p.family);
     176          32 :         zvrf = zebra_vrf_lookup_by_id(re->vrf_id);
     177          32 :         if (re->vrf_id == VRF_DEFAULT && zvrf->table_id != re->table) {
     178           0 :                 if (re->table &&
     179           0 :                     redist_check_instance(&client->mi_redist
     180             :                                                    [afi][ZEBRA_ROUTE_TABLE_DIRECT],
     181             :                                           re->table)) {
     182             :                         /* table-direct redistribution only for route entries which
     183             :                          * are on the default vrf, and that have table id different
     184             :                          * from the default table.
     185             :                          */
     186             :                         return true;
     187             :                 }
     188           0 :                 return false;
     189             :         }
     190             : 
     191             :         /* If default route and redistributed */
     192          32 :         if (is_default_prefix(&rn->p) &&
     193           0 :             vrf_bitmap_check(&client->redist_default[afi], re->vrf_id))
     194             :                 return true;
     195             : 
     196             :         /* If redistribute in enabled for zebra route all */
     197          32 :         if (vrf_bitmap_check(&client->redist[afi][ZEBRA_ROUTE_ALL], re->vrf_id))
     198             :                 return true;
     199             : 
     200             :         /*
     201             :          * If multi-instance then check for route
     202             :          * redistribution for given instance.
     203             :          */
     204          32 :         if (re->instance) {
     205           0 :                 if (redist_check_instance(&client->mi_redist[afi][re->type],
     206             :                                           re->instance))
     207             :                         return true;
     208             :                 else
     209             :                         return false;
     210             :         }
     211             : 
     212             :         /* If redistribution is enabled for give route type. */
     213          32 :         if (vrf_bitmap_check(&client->redist[afi][re->type], re->vrf_id))
     214             :                 return true;
     215             : 
     216             :         return false;
     217             : }
     218             : 
     219             : /* Either advertise a route for redistribution to registered clients or */
     220             : /* withdraw redistribution if add cannot be done for client */
     221          24 : void redistribute_update(const struct route_node *rn,
     222             :                          const struct route_entry *re,
     223             :                          const struct route_entry *prev_re)
     224             : {
     225          24 :         struct listnode *node, *nnode;
     226          24 :         struct zserv *client;
     227          24 :         bool is_table_direct;
     228             : 
     229          24 :         if (IS_ZEBRA_DEBUG_RIB)
     230          24 :                 zlog_debug(
     231             :                         "(%u:%u):%pRN(%u): Redist update re %p (%s), old %p (%s)",
     232             :                         re->vrf_id, re->table, rn, re->instance, re,
     233             :                         zebra_route_string(re->type), prev_re,
     234             :                         prev_re ? zebra_route_string(prev_re->type) : "None");
     235             : 
     236          24 :         if (!zebra_check_addr(&rn->p)) {
     237           6 :                 if (IS_ZEBRA_DEBUG_RIB)
     238           6 :                         zlog_debug("Redist update filter prefix %pRN", rn);
     239           6 :                 return;
     240             :         }
     241             : 
     242             : 
     243          52 :         for (ALL_LIST_ELEMENTS(zrouter.client_list, node, nnode, client)) {
     244          16 :                 if (zebra_redistribute_check(rn, re, client)) {
     245           1 :                         if (IS_ZEBRA_DEBUG_RIB) {
     246           1 :                                 zlog_debug(
     247             :                                         "%s: client %s %pRN(%u:%u), type=%d, distance=%d, metric=%d",
     248             :                                         __func__,
     249             :                                         zebra_route_string(client->proto), rn,
     250             :                                         re->vrf_id, re->table, re->type,
     251             :                                         re->distance, re->metric);
     252             :                         }
     253           1 :                         is_table_direct = zebra_redistribute_is_table_direct(re);
     254           1 :                         zsend_redistribute_route(ZEBRA_REDISTRIBUTE_ROUTE_ADD,
     255             :                                                  client, rn, re,
     256             :                                                  is_table_direct);
     257          15 :                 } else if (zebra_redistribute_check(rn, prev_re, client)) {
     258           0 :                         is_table_direct = zebra_redistribute_is_table_direct(prev_re);
     259           0 :                         zsend_redistribute_route(ZEBRA_REDISTRIBUTE_ROUTE_DEL,
     260             :                                                  client, rn, prev_re,
     261             :                                                  is_table_direct);
     262             :                 }
     263             :         }
     264             : }
     265             : 
     266             : /*
     267             :  * During a route delete, where 'new_re' is NULL, redist a delete to all
     268             :  * clients registered for the type of 'old_re'.
     269             :  * During a route update, redist a delete to any clients who will not see
     270             :  * an update when the new route is installed. There are cases when a client
     271             :  * may have seen a redist for 'old_re', but will not see
     272             :  * the redist for 'new_re'.
     273             :  */
     274           8 : void redistribute_delete(const struct route_node *rn,
     275             :                          const struct route_entry *old_re,
     276             :                          const struct route_entry *new_re)
     277             : {
     278           8 :         struct listnode *node, *nnode;
     279           8 :         struct zserv *client;
     280           8 :         vrf_id_t vrfid;
     281           8 :         bool is_table_direct;
     282             : 
     283           8 :         if (old_re)
     284           8 :                 vrfid = old_re->vrf_id;
     285           0 :         else if (new_re)
     286           0 :                 vrfid = new_re->vrf_id;
     287             :         else
     288             :                 return;
     289             : 
     290           8 :         if (IS_ZEBRA_DEBUG_RIB) {
     291           8 :                 uint8_t old_inst, new_inst;
     292           8 :                 uint32_t table = 0;
     293             : 
     294           8 :                 old_inst = new_inst = 0;
     295             : 
     296           8 :                 if (old_re) {
     297           8 :                         old_inst = old_re->instance;
     298           8 :                         table = old_re->table;
     299             :                 }
     300           8 :                 if (new_re) {
     301           0 :                         new_inst = new_re->instance;
     302           0 :                         table = new_re->table;
     303             :                 }
     304             : 
     305           8 :                 zlog_debug("(%u:%u):%pRN: Redist del: re %p (%u:%s), new re %p (%u:%s)",
     306             :                            vrfid, table, rn, old_re, old_inst,
     307             :                            old_re ? zebra_route_string(old_re->type) : "None",
     308             :                            new_re, new_inst,
     309             :                            new_re ? zebra_route_string(new_re->type) : "None");
     310             :         }
     311             : 
     312             :         /* Skip invalid (e.g. linklocal) prefix */
     313           8 :         if (!zebra_check_addr(&rn->p)) {
     314           0 :                 if (IS_ZEBRA_DEBUG_RIB) {
     315           0 :                         zlog_debug(
     316             :                                 "%u:%pRN: Redist del old: skipping invalid prefix",
     317             :                                 vrfid, rn);
     318             :                 }
     319           0 :                 return;
     320             :         }
     321             : 
     322          32 :         for (ALL_LIST_ELEMENTS(zrouter.client_list, node, nnode, client)) {
     323             :                 /* Do not send unsolicited messages to synchronous clients. */
     324          16 :                 if (client->synchronous)
     325           0 :                         continue;
     326             :                 /*
     327             :                  * Skip this client if it will receive an update for the
     328             :                  * 'new' re
     329             :                  */
     330          16 :                 if (zebra_redistribute_check(rn, new_re, client))
     331           0 :                         continue;
     332             : 
     333             :                 /* Send a delete for the 'old' re to any subscribed client. */
     334          16 :                 if (zebra_redistribute_check(rn, old_re, client)) {
     335           2 :                         is_table_direct = zebra_redistribute_is_table_direct(old_re);
     336           2 :                         zsend_redistribute_route(ZEBRA_REDISTRIBUTE_ROUTE_DEL,
     337             :                                                  client, rn, old_re,
     338             :                                                  is_table_direct);
     339             :                 }
     340             :         }
     341             : }
     342             : 
     343             : 
     344           2 : void zebra_redistribute_add(ZAPI_HANDLER_ARGS)
     345             : {
     346           2 :         afi_t afi = 0;
     347           2 :         int type = 0;
     348           2 :         unsigned short instance;
     349             : 
     350           2 :         STREAM_GETC(msg, afi);
     351           2 :         STREAM_GETC(msg, type);
     352           2 :         STREAM_GETW(msg, instance);
     353             : 
     354           2 :         if (IS_ZEBRA_DEBUG_EVENT)
     355           0 :                 zlog_debug(
     356             :                         "%s: client proto %s afi=%d, wants %s, vrf %s(%u), instance=%d",
     357             :                         __func__, zebra_route_string(client->proto), afi,
     358             :                         zebra_route_string(type), VRF_LOGNAME(zvrf->vrf),
     359             :                         zvrf_id(zvrf), instance);
     360             : 
     361           2 :         if (afi == 0 || afi >= AFI_MAX) {
     362           0 :                 flog_warn(EC_ZEBRA_REDISTRIBUTE_UNKNOWN_AF,
     363             :                           "%s: Specified afi %d does not exist", __func__, afi);
     364           0 :                 return;
     365             :         }
     366             : 
     367           2 :         if (type == 0 || type >= ZEBRA_ROUTE_MAX) {
     368           0 :                 zlog_debug("%s: Specified Route Type %d does not exist",
     369             :                            __func__, type);
     370           0 :                 return;
     371             :         }
     372             : 
     373           2 :         if (instance) {
     374           0 :                 if (!redist_check_instance(&client->mi_redist[afi][type],
     375             :                                            instance)) {
     376           0 :                         redist_add_instance(&client->mi_redist[afi][type],
     377             :                                             instance);
     378           0 :                         zebra_redistribute(client, type, instance, zvrf, afi);
     379             :                 }
     380             :         } else {
     381           4 :                 if (!vrf_bitmap_check(&client->redist[afi][type],
     382             :                                       zvrf_id(zvrf))) {
     383           2 :                         if (IS_ZEBRA_DEBUG_EVENT)
     384           0 :                                 zlog_debug(
     385             :                                         "%s: setting vrf %s(%u) redist bitmap",
     386             :                                         __func__, VRF_LOGNAME(zvrf->vrf),
     387             :                                         zvrf_id(zvrf));
     388           4 :                         vrf_bitmap_set(&client->redist[afi][type],
     389             :                                        zvrf_id(zvrf));
     390           2 :                         zebra_redistribute(client, type, 0, zvrf, afi);
     391             :                 }
     392             :         }
     393             : 
     394           0 : stream_failure:
     395             :         return;
     396             : }
     397             : 
     398           2 : void zebra_redistribute_delete(ZAPI_HANDLER_ARGS)
     399             : {
     400           2 :         afi_t afi = 0;
     401           2 :         int type = 0;
     402           2 :         unsigned short instance;
     403             : 
     404           2 :         STREAM_GETC(msg, afi);
     405           2 :         STREAM_GETC(msg, type);
     406           2 :         STREAM_GETW(msg, instance);
     407             : 
     408           2 :         if (IS_ZEBRA_DEBUG_EVENT)
     409           0 :                 zlog_debug(
     410             :                         "%s: client proto %s afi=%d, no longer wants %s, vrf %s(%u), instance=%d",
     411             :                         __func__, zebra_route_string(client->proto), afi,
     412             :                         zebra_route_string(type), VRF_LOGNAME(zvrf->vrf),
     413             :                         zvrf_id(zvrf), instance);
     414             : 
     415             : 
     416           2 :         if (afi == 0 || afi >= AFI_MAX) {
     417           0 :                 flog_warn(EC_ZEBRA_REDISTRIBUTE_UNKNOWN_AF,
     418             :                           "%s: Specified afi %d does not exist", __func__, afi);
     419           0 :                 return;
     420             :         }
     421             : 
     422           2 :         if (type == 0 || type >= ZEBRA_ROUTE_MAX) {
     423           0 :                 zlog_debug("%s: Specified Route Type %d does not exist",
     424             :                            __func__, type);
     425           0 :                 return;
     426             :         }
     427             : 
     428             :         /*
     429             :          * NOTE: no need to withdraw the previously advertised routes. The
     430             :          * clients
     431             :          * themselves should keep track of the received routes from zebra and
     432             :          * withdraw them when necessary.
     433             :          */
     434           2 :         if (instance)
     435           0 :                 redist_del_instance(&client->mi_redist[afi][type], instance);
     436             :         else
     437           4 :                 vrf_bitmap_unset(&client->redist[afi][type], zvrf_id(zvrf));
     438             : 
     439           2 : stream_failure:
     440             :         return;
     441             : }
     442             : 
     443           0 : void zebra_redistribute_default_add(ZAPI_HANDLER_ARGS)
     444             : {
     445           0 :         afi_t afi = 0;
     446             : 
     447           0 :         STREAM_GETC(msg, afi);
     448             : 
     449           0 :         if (afi == 0 || afi >= AFI_MAX) {
     450           0 :                 flog_warn(EC_ZEBRA_REDISTRIBUTE_UNKNOWN_AF,
     451             :                           "%s: Specified afi %u does not exist", __func__, afi);
     452           0 :                 return;
     453             :         }
     454             : 
     455           0 :         vrf_bitmap_set(&client->redist_default[afi], zvrf_id(zvrf));
     456           0 :         zebra_redistribute_default(client, zvrf_id(zvrf));
     457             : 
     458           0 : stream_failure:
     459             :         return;
     460             : }
     461             : 
     462           0 : void zebra_redistribute_default_delete(ZAPI_HANDLER_ARGS)
     463             : {
     464           0 :         afi_t afi = 0;
     465             : 
     466           0 :         STREAM_GETC(msg, afi);
     467             : 
     468           0 :         if (afi == 0 || afi >= AFI_MAX) {
     469           0 :                 flog_warn(EC_ZEBRA_REDISTRIBUTE_UNKNOWN_AF,
     470             :                           "%s: Specified afi %u does not exist", __func__, afi);
     471           0 :                 return;
     472             :         }
     473             : 
     474           0 :         vrf_bitmap_unset(&client->redist_default[afi], zvrf_id(zvrf));
     475             : 
     476           0 : stream_failure:
     477             :         return;
     478             : }
     479             : 
     480             : /* Interface up information. */
     481           6 : void zebra_interface_up_update(struct interface *ifp)
     482             : {
     483           6 :         struct listnode *node, *nnode;
     484           6 :         struct zserv *client;
     485             : 
     486           6 :         if (IS_ZEBRA_DEBUG_EVENT)
     487           0 :                 zlog_debug("MESSAGE: ZEBRA_INTERFACE_UP %s vrf %s(%u)",
     488             :                            ifp->name, ifp->vrf->name, ifp->vrf->vrf_id);
     489             : 
     490           6 :         if (ifp->ptm_status || !ifp->ptm_enable) {
     491          24 :                 for (ALL_LIST_ELEMENTS(zrouter.client_list, node, nnode,
     492             :                                        client)) {
     493             :                         /* Do not send unsolicited messages to synchronous
     494             :                          * clients.
     495             :                          */
     496          12 :                         if (client->synchronous)
     497           0 :                                 continue;
     498             : 
     499          12 :                         zsend_interface_update(ZEBRA_INTERFACE_UP,
     500             :                                                client, ifp);
     501          12 :                         zsend_interface_link_params(client, ifp);
     502             :                 }
     503             :         }
     504           6 : }
     505             : 
     506             : /* Interface down information. */
     507           3 : void zebra_interface_down_update(struct interface *ifp)
     508             : {
     509           3 :         struct listnode *node, *nnode;
     510           3 :         struct zserv *client;
     511             : 
     512           3 :         if (IS_ZEBRA_DEBUG_EVENT)
     513           0 :                 zlog_debug("MESSAGE: ZEBRA_INTERFACE_DOWN %s vrf %s(%u)",
     514             :                            ifp->name, ifp->vrf->name, ifp->vrf->vrf_id);
     515             : 
     516          12 :         for (ALL_LIST_ELEMENTS(zrouter.client_list, node, nnode, client)) {
     517             :                 /* Do not send unsolicited messages to synchronous clients. */
     518           6 :                 if (client->synchronous)
     519           0 :                         continue;
     520             : 
     521           6 :                 zsend_interface_update(ZEBRA_INTERFACE_DOWN, client, ifp);
     522             :         }
     523             : 
     524           3 :         zebra_neigh_del_all(ifp);
     525           3 : }
     526             : 
     527             : /* Interface information update. */
     528           8 : void zebra_interface_add_update(struct interface *ifp)
     529             : {
     530           8 :         struct listnode *node, *nnode;
     531           8 :         struct zserv *client;
     532             : 
     533           8 :         if (IS_ZEBRA_DEBUG_EVENT)
     534           0 :                 zlog_debug("MESSAGE: ZEBRA_INTERFACE_ADD %s vrf %s(%u)",
     535             :                            ifp->name, ifp->vrf->name, ifp->vrf->vrf_id);
     536             : 
     537          16 :         for (ALL_LIST_ELEMENTS(zrouter.client_list, node, nnode, client)) {
     538             :                 /* Do not send unsolicited messages to synchronous clients. */
     539           0 :                 if (client->synchronous)
     540           0 :                         continue;
     541             : 
     542           0 :                 client->ifadd_cnt++;
     543           0 :                 zsend_interface_add(client, ifp);
     544           0 :                 zsend_interface_link_params(client, ifp);
     545             :         }
     546           8 : }
     547             : 
     548           0 : void zebra_interface_delete_update(struct interface *ifp)
     549             : {
     550           0 :         struct listnode *node, *nnode;
     551           0 :         struct zserv *client;
     552             : 
     553           0 :         if (IS_ZEBRA_DEBUG_EVENT)
     554           0 :                 zlog_debug("MESSAGE: ZEBRA_INTERFACE_DELETE %s vrf %s(%u)",
     555             :                            ifp->name, ifp->vrf->name, ifp->vrf->vrf_id);
     556             : 
     557           0 :         for (ALL_LIST_ELEMENTS(zrouter.client_list, node, nnode, client)) {
     558             :                 /* Do not send unsolicited messages to synchronous clients. */
     559           0 :                 if (client->synchronous)
     560           0 :                         continue;
     561             : 
     562           0 :                 client->ifdel_cnt++;
     563           0 :                 zsend_interface_delete(client, ifp);
     564             :         }
     565           0 : }
     566             : 
     567             : /* Interface address addition. */
     568          23 : void zebra_interface_address_add_update(struct interface *ifp,
     569             :                                         struct connected *ifc)
     570             : {
     571          23 :         struct listnode *node, *nnode;
     572          23 :         struct zserv *client;
     573             : 
     574          23 :         if (IS_ZEBRA_DEBUG_EVENT)
     575           0 :                 zlog_debug(
     576             :                         "MESSAGE: ZEBRA_INTERFACE_ADDRESS_ADD %pFX on %s vrf %s(%u)",
     577             :                         ifc->address, ifp->name, ifp->vrf->name,
     578             :                         ifp->vrf->vrf_id);
     579             : 
     580          23 :         if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_REAL))
     581           0 :                 flog_warn(
     582             :                         EC_ZEBRA_ADVERTISING_UNUSABLE_ADDR,
     583             :                         "advertising address to clients that is not yet usable.");
     584             : 
     585          23 :         zebra_vxlan_add_del_gw_macip(ifp, ifc->address, 1);
     586             : 
     587          23 :         router_id_add_address(ifc);
     588             : 
     589          68 :         for (ALL_LIST_ELEMENTS(zrouter.client_list, node, nnode, client)) {
     590             :                 /* Do not send unsolicited messages to synchronous clients. */
     591          22 :                 if (client->synchronous)
     592           0 :                         continue;
     593             : 
     594          22 :                 if (CHECK_FLAG(ifc->conf, ZEBRA_IFC_REAL)) {
     595          22 :                         client->connected_rt_add_cnt++;
     596          22 :                         zsend_interface_address(ZEBRA_INTERFACE_ADDRESS_ADD,
     597             :                                                 client, ifp, ifc);
     598             :                 }
     599             :         }
     600             :         /* interface associated NHGs may have been deleted,
     601             :          * re-sync zebra -> dplane NHGs
     602             :          */
     603          23 :         zebra_interface_nhg_reinstall(ifp);
     604          23 : }
     605             : 
     606             : /* Interface address deletion. */
     607           4 : void zebra_interface_address_delete_update(struct interface *ifp,
     608             :                                            struct connected *ifc)
     609             : {
     610           4 :         struct listnode *node, *nnode;
     611           4 :         struct zserv *client;
     612             : 
     613           4 :         if (IS_ZEBRA_DEBUG_EVENT)
     614           0 :                 zlog_debug(
     615             :                         "MESSAGE: ZEBRA_INTERFACE_ADDRESS_DELETE %pFX on %s vrf %s(%u)",
     616             :                         ifc->address, ifp->name, ifp->vrf->name,
     617             :                         ifp->vrf->vrf_id);
     618             : 
     619           4 :         zebra_vxlan_add_del_gw_macip(ifp, ifc->address, 0);
     620             : 
     621           4 :         router_id_del_address(ifc);
     622             : 
     623          16 :         for (ALL_LIST_ELEMENTS(zrouter.client_list, node, nnode, client)) {
     624             :                 /* Do not send unsolicited messages to synchronous clients. */
     625           8 :                 if (client->synchronous)
     626           0 :                         continue;
     627             : 
     628           8 :                 if (CHECK_FLAG(ifc->conf, ZEBRA_IFC_REAL)) {
     629           8 :                         client->connected_rt_del_cnt++;
     630           8 :                         zsend_interface_address(ZEBRA_INTERFACE_ADDRESS_DELETE,
     631             :                                                 client, ifp, ifc);
     632             :                 }
     633             :         }
     634           4 : }
     635             : 
     636             : /* Interface VRF change. May need to delete from clients not interested in
     637             :  * the new VRF. Note that this function is invoked *prior* to the VRF change.
     638             :  */
     639           0 : void zebra_interface_vrf_update_del(struct interface *ifp, vrf_id_t new_vrf_id)
     640             : {
     641           0 :         struct listnode *node, *nnode;
     642           0 :         struct zserv *client;
     643             : 
     644           0 :         if (IS_ZEBRA_DEBUG_EVENT)
     645           0 :                 zlog_debug("MESSAGE: ZEBRA_INTERFACE_DELETE %s VRF Id %u -> %u",
     646             :                            ifp->name, ifp->vrf->vrf_id, new_vrf_id);
     647             : 
     648           0 :         for (ALL_LIST_ELEMENTS(zrouter.client_list, node, nnode, client)) {
     649             :                 /* Do not send unsolicited messages to synchronous clients. */
     650           0 :                 if (client->synchronous)
     651           0 :                         continue;
     652             : 
     653             :                 /* Need to delete if the client is not interested in the new
     654             :                  * VRF. */
     655           0 :                 zsend_interface_update(ZEBRA_INTERFACE_DOWN, client, ifp);
     656           0 :                 client->ifdel_cnt++;
     657           0 :                 zsend_interface_delete(client, ifp);
     658             :         }
     659           0 : }
     660             : 
     661             : /* Interface VRF change. This function is invoked *post* VRF change and sends an
     662             :  * add to clients who are interested in the new VRF but not in the old VRF.
     663             :  */
     664           0 : void zebra_interface_vrf_update_add(struct interface *ifp, vrf_id_t old_vrf_id)
     665             : {
     666           0 :         struct listnode *node, *nnode;
     667           0 :         struct zserv *client;
     668             : 
     669           0 :         if (IS_ZEBRA_DEBUG_EVENT)
     670           0 :                 zlog_debug("MESSAGE: ZEBRA_INTERFACE_ADD %s VRF Id %u -> %u",
     671             :                            ifp->name, old_vrf_id, ifp->vrf->vrf_id);
     672             : 
     673           0 :         for (ALL_LIST_ELEMENTS(zrouter.client_list, node, nnode, client)) {
     674             :                 /* Do not send unsolicited messages to synchronous clients. */
     675           0 :                 if (client->synchronous)
     676           0 :                         continue;
     677             : 
     678             :                 /* Need to add if the client is interested in the new VRF. */
     679           0 :                 client->ifadd_cnt++;
     680           0 :                 zsend_interface_add(client, ifp);
     681           0 :                 zsend_interface_addresses(client, ifp);
     682             :         }
     683           0 : }
     684             : 
     685           0 : int zebra_add_import_table_entry(struct zebra_vrf *zvrf, struct route_node *rn,
     686             :                                  struct route_entry *re, const char *rmap_name)
     687             : {
     688           0 :         struct route_entry *newre;
     689           0 :         struct route_entry *same;
     690           0 :         struct prefix p;
     691           0 :         struct nexthop_group *ng;
     692           0 :         route_map_result_t ret = RMAP_PERMITMATCH;
     693           0 :         afi_t afi;
     694             : 
     695           0 :         afi = family2afi(rn->p.family);
     696           0 :         if (rmap_name)
     697           0 :                 ret = zebra_import_table_route_map_check(afi, re, &rn->p,
     698           0 :                                                          re->nhe->nhg.nexthop,
     699             :                                                          rmap_name);
     700             : 
     701           0 :         if (ret != RMAP_PERMITMATCH) {
     702           0 :                 UNSET_FLAG(re->flags, ZEBRA_FLAG_SELECTED);
     703           0 :                 zebra_del_import_table_entry(zvrf, rn, re);
     704           0 :                 return 0;
     705             :         }
     706             : 
     707           0 :         prefix_copy(&p, &rn->p);
     708             : 
     709           0 :         RNODE_FOREACH_RE (rn, same) {
     710           0 :                 if (CHECK_FLAG(same->status, ROUTE_ENTRY_REMOVED))
     711           0 :                         continue;
     712             : 
     713           0 :                 if (same->type == re->type && same->instance == re->instance
     714           0 :                     && same->table == re->table
     715           0 :                     && same->type != ZEBRA_ROUTE_CONNECT)
     716             :                         break;
     717             :         }
     718             : 
     719           0 :         if (same) {
     720           0 :                 UNSET_FLAG(same->flags, ZEBRA_FLAG_SELECTED);
     721           0 :                 zebra_del_import_table_entry(zvrf, rn, same);
     722             :         }
     723             : 
     724           0 :         UNSET_FLAG(re->flags, ZEBRA_FLAG_RR_USE_DISTANCE);
     725             : 
     726           0 :         newre = zebra_rib_route_entry_new(
     727             :                 0, ZEBRA_ROUTE_TABLE, re->table, re->flags, re->nhe_id,
     728             :                 zvrf->table_id, re->metric, re->mtu,
     729           0 :                 zebra_import_table_distance[afi][re->table], re->tag);
     730             : 
     731           0 :         ng = nexthop_group_new();
     732           0 :         copy_nexthops(&ng->nexthop, re->nhe->nhg.nexthop, NULL);
     733             : 
     734           0 :         rib_add_multipath(afi, SAFI_UNICAST, &p, NULL, newre, ng, false);
     735           0 :         nexthop_group_delete(&ng);
     736             : 
     737           0 :         return 0;
     738             : }
     739             : 
     740           0 : int zebra_del_import_table_entry(struct zebra_vrf *zvrf, struct route_node *rn,
     741             :                                  struct route_entry *re)
     742             : {
     743           0 :         struct prefix p;
     744           0 :         afi_t afi;
     745             : 
     746           0 :         afi = family2afi(rn->p.family);
     747           0 :         prefix_copy(&p, &rn->p);
     748             : 
     749           0 :         rib_delete(afi, SAFI_UNICAST, zvrf->vrf->vrf_id, ZEBRA_ROUTE_TABLE,
     750           0 :                    re->table, re->flags, &p, NULL, re->nhe->nhg.nexthop,
     751           0 :                    re->nhe_id, zvrf->table_id, re->metric, re->distance,
     752             :                    false);
     753             : 
     754           0 :         return 0;
     755             : }
     756             : 
     757             : /* Assuming no one calls this with the main routing table */
     758           0 : int zebra_import_table(afi_t afi, vrf_id_t vrf_id, uint32_t table_id,
     759             :                        uint32_t distance, const char *rmap_name, int add)
     760             : {
     761           0 :         struct route_table *table;
     762           0 :         struct route_entry *re;
     763           0 :         struct route_node *rn;
     764           0 :         struct zebra_vrf *zvrf = zebra_vrf_lookup_by_id(vrf_id);
     765             : 
     766           0 :         if (!is_zebra_valid_kernel_table(table_id)
     767           0 :             || (table_id == rt_table_main_id))
     768             :                 return -1;
     769             : 
     770           0 :         if (afi >= AFI_MAX)
     771             :                 return -1;
     772             : 
     773           0 :         table = zebra_vrf_get_table_with_table_id(afi, SAFI_UNICAST, vrf_id,
     774             :                                                   table_id);
     775           0 :         if (table == NULL) {
     776             :                 return 0;
     777           0 :         } else if (IS_ZEBRA_DEBUG_RIB) {
     778           0 :                 zlog_debug("%s routes from table %d",
     779             :                            add ? "Importing" : "Unimporting", table_id);
     780             :         }
     781             : 
     782           0 :         if (add) {
     783           0 :                 if (rmap_name)
     784           0 :                         zebra_add_import_table_route_map(afi, rmap_name,
     785             :                                                          table_id);
     786             :                 else {
     787           0 :                         rmap_name =
     788           0 :                                 zebra_get_import_table_route_map(afi, table_id);
     789           0 :                         if (rmap_name) {
     790           0 :                                 zebra_del_import_table_route_map(afi, table_id);
     791           0 :                                 rmap_name = NULL;
     792             :                         }
     793             :                 }
     794             : 
     795           0 :                 zebra_import_table_used[afi][table_id] = 1;
     796           0 :                 zebra_import_table_distance[afi][table_id] = distance;
     797             :         } else {
     798           0 :                 zebra_import_table_used[afi][table_id] = 0;
     799           0 :                 zebra_import_table_distance[afi][table_id] =
     800             :                         ZEBRA_TABLE_DISTANCE_DEFAULT;
     801             : 
     802           0 :                 rmap_name = zebra_get_import_table_route_map(afi, table_id);
     803           0 :                 if (rmap_name) {
     804           0 :                         zebra_del_import_table_route_map(afi, table_id);
     805           0 :                         rmap_name = NULL;
     806             :                 }
     807             :         }
     808             : 
     809           0 :         for (rn = route_top(table); rn; rn = route_next(rn)) {
     810             :                 /* For each entry in the non-default routing table,
     811             :                  * add the entry in the main table
     812             :                  */
     813           0 :                 if (!rn->info)
     814           0 :                         continue;
     815             : 
     816           0 :                 RNODE_FOREACH_RE (rn, re) {
     817           0 :                         if (CHECK_FLAG(re->status, ROUTE_ENTRY_REMOVED))
     818           0 :                                 continue;
     819             :                         break;
     820             :                 }
     821             : 
     822           0 :                 if (!re)
     823           0 :                         continue;
     824             : 
     825           0 :                 if (((afi == AFI_IP) && (rn->p.family == AF_INET))
     826           0 :                     || ((afi == AFI_IP6) && (rn->p.family == AF_INET6))) {
     827           0 :                         if (add)
     828           0 :                                 zebra_add_import_table_entry(zvrf, rn, re,
     829             :                                                              rmap_name);
     830             :                         else
     831           0 :                                 zebra_del_import_table_entry(zvrf, rn, re);
     832             :                 }
     833             :         }
     834             :         return 0;
     835             : }
     836             : 
     837           0 : int zebra_import_table_config(struct vty *vty, vrf_id_t vrf_id)
     838             : {
     839           0 :         int i;
     840           0 :         afi_t afi;
     841           0 :         int write = 0;
     842           0 :         char afi_str[AFI_MAX][10] = {"", "ip", "ipv6", "ethernet"};
     843           0 :         const char *rmap_name;
     844             : 
     845           0 :         for (afi = AFI_IP; afi < AFI_MAX; afi++) {
     846           0 :                 for (i = 1; i < ZEBRA_KERNEL_TABLE_MAX; i++) {
     847           0 :                         if (!is_zebra_import_table_enabled(afi, vrf_id, i))
     848           0 :                                 continue;
     849             : 
     850           0 :                         if (zebra_import_table_distance[afi][i]
     851             :                             != ZEBRA_TABLE_DISTANCE_DEFAULT) {
     852           0 :                                 vty_out(vty, "%s import-table %d distance %d",
     853           0 :                                         afi_str[afi], i,
     854             :                                         zebra_import_table_distance[afi][i]);
     855             :                         } else {
     856           0 :                                 vty_out(vty, "%s import-table %d", afi_str[afi],
     857             :                                         i);
     858             :                         }
     859             : 
     860           0 :                         rmap_name = zebra_get_import_table_route_map(afi, i);
     861           0 :                         if (rmap_name)
     862           0 :                                 vty_out(vty, " route-map %s", rmap_name);
     863             : 
     864           0 :                         vty_out(vty, "\n");
     865           0 :                         write = 1;
     866             :                 }
     867             :         }
     868             : 
     869           0 :         return write;
     870             : }
     871             : 
     872           0 : static void zebra_import_table_rm_update_vrf_afi(struct zebra_vrf *zvrf,
     873             :                                                  afi_t afi, int table_id,
     874             :                                                  const char *rmap)
     875             : {
     876           0 :         struct route_table *table;
     877           0 :         struct route_entry *re;
     878           0 :         struct route_node *rn;
     879           0 :         const char *rmap_name;
     880             : 
     881           0 :         rmap_name = zebra_get_import_table_route_map(afi, table_id);
     882           0 :         if ((!rmap_name) || (strcmp(rmap_name, rmap) != 0))
     883             :                 return;
     884             : 
     885           0 :         table = zebra_vrf_get_table_with_table_id(afi, SAFI_UNICAST,
     886           0 :                                                   zvrf->vrf->vrf_id, table_id);
     887           0 :         if (!table) {
     888           0 :                 if (IS_ZEBRA_DEBUG_RIB_DETAILED)
     889           0 :                         zlog_debug("%s: Table id=%d not found", __func__,
     890             :                                    table_id);
     891           0 :                 return;
     892             :         }
     893             : 
     894           0 :         for (rn = route_top(table); rn; rn = route_next(rn)) {
     895             :                 /*
     896             :                  * For each entry in the non-default routing table,
     897             :                  * add the entry in the main table
     898             :                  */
     899           0 :                 if (!rn->info)
     900           0 :                         continue;
     901             : 
     902           0 :                 RNODE_FOREACH_RE (rn, re) {
     903           0 :                         if (CHECK_FLAG(re->status, ROUTE_ENTRY_REMOVED))
     904           0 :                                 continue;
     905             :                         break;
     906             :                 }
     907             : 
     908           0 :                 if (!re)
     909           0 :                         continue;
     910             : 
     911           0 :                 if (((afi == AFI_IP) && (rn->p.family == AF_INET))
     912           0 :                     || ((afi == AFI_IP6) && (rn->p.family == AF_INET6)))
     913           0 :                         zebra_add_import_table_entry(zvrf, rn, re, rmap_name);
     914             :         }
     915             : 
     916             :         return;
     917             : }
     918             : 
     919           0 : static void zebra_import_table_rm_update_vrf(struct zebra_vrf *zvrf,
     920             :                                              const char *rmap)
     921             : {
     922           0 :         afi_t afi;
     923           0 :         int i;
     924             : 
     925           0 :         for (afi = AFI_IP; afi < AFI_MAX; afi++) {
     926           0 :                 for (i = 1; i < ZEBRA_KERNEL_TABLE_MAX; i++) {
     927           0 :                         if (!is_zebra_import_table_enabled(
     928           0 :                                     afi, zvrf->vrf->vrf_id, i))
     929           0 :                                 continue;
     930             : 
     931           0 :                         zebra_import_table_rm_update_vrf_afi(zvrf, afi, i,
     932             :                                                              rmap);
     933             :                 }
     934             :         }
     935           0 : }
     936             : 
     937           0 : void zebra_import_table_rm_update(const char *rmap)
     938             : {
     939           0 :         struct vrf *vrf;
     940           0 :         struct zebra_vrf *zvrf;
     941             : 
     942           0 :         RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
     943           0 :                 zvrf = vrf->info;
     944             : 
     945           0 :                 if (!zvrf)
     946           0 :                         continue;
     947             : 
     948           0 :                 zebra_import_table_rm_update_vrf(zvrf, rmap);
     949             :         }
     950           0 : }
     951             : 
     952             : /* Interface parameters update */
     953           0 : void zebra_interface_parameters_update(struct interface *ifp)
     954             : {
     955           0 :         struct listnode *node, *nnode;
     956           0 :         struct zserv *client;
     957             : 
     958           0 :         if (IS_ZEBRA_DEBUG_EVENT)
     959           0 :                 zlog_debug("MESSAGE: ZEBRA_INTERFACE_LINK_PARAMS %s vrf %s(%u)",
     960             :                            ifp->name, ifp->vrf->name, ifp->vrf->vrf_id);
     961             : 
     962           0 :         for (ALL_LIST_ELEMENTS(zrouter.client_list, node, nnode, client)) {
     963             :                 /* Do not send unsolicited messages to synchronous clients. */
     964           0 :                 if (client->synchronous)
     965           0 :                         continue;
     966             : 
     967           0 :                 zsend_interface_link_params(client, ifp);
     968             :         }
     969           0 : }

Generated by: LCOV version v1.16-topotato