back to topotato report
topotato coverage report
Current view: top level - zebra - redistribute.c (source / functions) Hit Total Coverage
Test: test_pim6_prune_propagate.py::PIM6PrunePropagate Lines: 123 421 29.2 %
Date: 2023-02-24 18:39:23 Functions: 10 26 38.5 %

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

Generated by: LCOV version v1.16-topotato