]> git.puffer.fish Git - mirror/frr.git/commitdiff
zebra: add redistribute table-direct support
authorPhilippe Guibert <philippe.guibert@6wind.com>
Wed, 17 Jun 2020 12:11:35 +0000 (14:11 +0200)
committerPhilippe Guibert <philippe.guibert@6wind.com>
Fri, 20 Oct 2023 11:28:52 +0000 (13:28 +0200)
Redistributing routes from a specific routing table to a particular routing
protocol necessitates copying route entries to the main routing table using the
"ip import-table" command. Once copied, these routes are assigned a distinct
"table" route type, which the "redistribute table" command of the routing
protocol then picks up.

For illustration, here is a configuration that showcases the use of
"import-table" and "redistribute":

> # show running-config
> [..]
> ip route 172.31.0.10/32 172.31.1.10 table 100
> router bgp 65500
>  address-family ipv4 unicast
>   redistribute table 100
>  exit-address-family
> exit
> ip import-table 100
>
> # show ip route vrf default
> [..]
> T[100]>* 172.31.0.10/32 [15/0] via 172.31.1.10, r2-eth1, weight 1, 00:00:05

However, this method has inherent constraints:

- The 'import-table' parameter only handles route table id up to 252. The
253/254/255 table ids are reserved in the linux system, and adding other table
IDs above 255 leads to a design issue, where the size of some tables is directly
related to the maximum number of table ids to support.
- Duplicated route entries might interfere with original default table routes,
leading to potential conflicts. There is no guarantee that the zebra RIB will
favor these duplicated entries during redistribution.
- There are cases where the table ID can be checked independently of the default
routing table, as seen in Linux where the "ip rule" command is able to divert
traffic to that routing table. In that case, there is no need to duplicate route
entries in the default routing table.

To overcome these issues, a new redistribution type is proposed to redistribute
route entries directly from a specified routing table, eliminating the need for
an initial import into the default table.

Add a 'ZEBRA_ROUTE_TABLE_DIRECT' type to the 'REDISTRIBUTE' ZAPI messages. It
allows sending routes from a given non default table ID from zebra to a routing
daemon. The destination routing protocol table must be the default table.
The redistributed route inherit from the default distance value of 14: this is
the distance value reserved for routes redistributed via ROUTE_TABLE_DIRECT.

Signed-off-by: Philippe Guibert <philippe.guibert@6wind.com>
zebra/redistribute.c
zebra/zapi_msg.c
zebra/zapi_msg.h
zebra/zebra_rib.c

index 4069f7dd7039cfdc5162478cebe50f5b228df919..71e7956324b023c6ae7f906440db76894ef4fe75 100644 (file)
@@ -77,9 +77,8 @@ static void zebra_redistribute_default(struct zserv *client, vrf_id_t vrf_id)
 
                RNODE_FOREACH_RE (rn, newre) {
                        if (CHECK_FLAG(newre->flags, ZEBRA_FLAG_SELECTED))
-                               zsend_redistribute_route(
-                                       ZEBRA_REDISTRIBUTE_ROUTE_ADD, client,
-                                       rn, newre);
+                               zsend_redistribute_route(ZEBRA_REDISTRIBUTE_ROUTE_ADD,
+                                                        client, rn, newre, false);
                }
 
                route_unlock_node(rn);
@@ -88,14 +87,26 @@ static void zebra_redistribute_default(struct zserv *client, vrf_id_t vrf_id)
 
 /* Redistribute routes. */
 static void zebra_redistribute(struct zserv *client, int type,
-                              unsigned short instance, vrf_id_t vrf_id,
+                              unsigned short instance, struct zebra_vrf *zvrf,
                               int afi)
 {
        struct route_entry *newre;
        struct route_table *table;
        struct route_node *rn;
+       bool is_table_direct = false;
+       vrf_id_t vrf_id = zvrf_id(zvrf);
+
+       if (type == ZEBRA_ROUTE_TABLE_DIRECT) {
+               if (vrf_id == VRF_DEFAULT) {
+                       table = zebra_router_find_table(zvrf, instance, afi,
+                                                       SAFI_UNICAST);
+                       type = ZEBRA_ROUTE_ALL;
+                       is_table_direct = true;
+               } else
+                       return;
+       } else
+               table = zebra_vrf_table(afi, SAFI_UNICAST, vrf_id);
 
-       table = zebra_vrf_table(afi, SAFI_UNICAST, vrf_id);
        if (!table)
                return;
 
@@ -124,11 +135,30 @@ static void zebra_redistribute(struct zserv *client, int type,
                        if (!zebra_check_addr(&rn->p))
                                continue;
 
+                       if (type == ZEBRA_ROUTE_ADD && is_table_direct &&
+                           newre->vrf_id != VRF_DEFAULT)
+                               continue;
+
                        zsend_redistribute_route(ZEBRA_REDISTRIBUTE_ROUTE_ADD,
-                                                client, rn, newre);
+                                                client, rn, newre, is_table_direct);
                }
 }
 
+/*
+ * Function to return a valid table id value if table-direct is used
+ * return 0 otherwise
+ * This function can be called only if zebra_redistribute_check returns TRUE
+ */
+static bool zebra_redistribute_is_table_direct(const struct route_entry *re)
+{
+       struct zebra_vrf *zvrf;
+
+       zvrf = zebra_vrf_lookup_by_id(re->vrf_id);
+       if (re->vrf_id == VRF_DEFAULT && zvrf->table_id != re->table)
+               return true;
+       return false;
+}
+
 /*
  * Function to check if prefix is candidate for
  * redistribute.
@@ -146,8 +176,19 @@ static bool zebra_redistribute_check(const struct route_node *rn,
 
        afi = family2afi(rn->p.family);
        zvrf = zebra_vrf_lookup_by_id(re->vrf_id);
-       if (re->vrf_id == VRF_DEFAULT && zvrf->table_id != re->table)
+       if (re->vrf_id == VRF_DEFAULT && zvrf->table_id != re->table) {
+               if (re->table &&
+                   redist_check_instance(&client->mi_redist
+                                                  [afi][ZEBRA_ROUTE_TABLE_DIRECT],
+                                         re->table)) {
+                       /* table-direct redistribution only for route entries which
+                        * are on the default vrf, and that have table id different
+                        * from the default table.
+                        */
+                       return true;
+               }
                return false;
+       }
 
        /* If default route and redistributed */
        if (is_default_prefix(&rn->p) &&
@@ -185,6 +226,7 @@ void redistribute_update(const struct route_node *rn,
 {
        struct listnode *node, *nnode;
        struct zserv *client;
+       bool is_table_direct;
 
        if (IS_ZEBRA_DEBUG_RIB)
                zlog_debug(
@@ -210,11 +252,16 @@ void redistribute_update(const struct route_node *rn,
                                        re->vrf_id, re->table, re->type,
                                        re->distance, re->metric);
                        }
+                       is_table_direct = zebra_redistribute_is_table_direct(re);
                        zsend_redistribute_route(ZEBRA_REDISTRIBUTE_ROUTE_ADD,
-                                                client, rn, re);
-               } else if (zebra_redistribute_check(rn, prev_re, client))
+                                                client, rn, re,
+                                                is_table_direct);
+               } else if (zebra_redistribute_check(rn, prev_re, client)) {
+                       is_table_direct = zebra_redistribute_is_table_direct(prev_re);
                        zsend_redistribute_route(ZEBRA_REDISTRIBUTE_ROUTE_DEL,
-                                                client, rn, prev_re);
+                                                client, rn, prev_re,
+                                                is_table_direct);
+               }
        }
 }
 
@@ -233,6 +280,7 @@ void redistribute_delete(const struct route_node *rn,
        struct listnode *node, *nnode;
        struct zserv *client;
        vrf_id_t vrfid;
+       bool is_table_direct;
 
        if (old_re)
                vrfid = old_re->vrf_id;
@@ -285,9 +333,12 @@ void redistribute_delete(const struct route_node *rn,
                        continue;
 
                /* Send a delete for the 'old' re to any subscribed client. */
-               if (zebra_redistribute_check(rn, old_re, client))
+               if (zebra_redistribute_check(rn, old_re, client)) {
+                       is_table_direct = zebra_redistribute_is_table_direct(old_re);
                        zsend_redistribute_route(ZEBRA_REDISTRIBUTE_ROUTE_DEL,
-                                                client, rn, old_re);
+                                                client, rn, old_re,
+                                                is_table_direct);
+               }
        }
 }
 
@@ -326,8 +377,7 @@ void zebra_redistribute_add(ZAPI_HANDLER_ARGS)
                                           instance)) {
                        redist_add_instance(&client->mi_redist[afi][type],
                                            instance);
-                       zebra_redistribute(client, type, instance,
-                                          zvrf_id(zvrf), afi);
+                       zebra_redistribute(client, type, instance, zvrf, afi);
                }
        } else {
                if (!vrf_bitmap_check(&client->redist[afi][type],
@@ -339,7 +389,7 @@ void zebra_redistribute_add(ZAPI_HANDLER_ARGS)
                                        zvrf_id(zvrf));
                        vrf_bitmap_set(&client->redist[afi][type],
                                       zvrf_id(zvrf));
-                       zebra_redistribute(client, type, 0, zvrf_id(zvrf), afi);
+                       zebra_redistribute(client, type, 0, zvrf, afi);
                }
        }
 
index 92a81f6828735068208bdc3c29d8559bf7699eae..856c906bdcb2f7e609249320987e6c1ca23b3067 100644 (file)
@@ -510,7 +510,7 @@ int zsend_interface_update(int cmd, struct zserv *client, struct interface *ifp)
 
 int zsend_redistribute_route(int cmd, struct zserv *client,
                             const struct route_node *rn,
-                            const struct route_entry *re)
+                            const struct route_entry *re, bool is_table_direct)
 {
        struct zapi_route api;
        struct zapi_nexthop *api_nh;
@@ -526,7 +526,11 @@ int zsend_redistribute_route(int cmd, struct zserv *client,
        api.vrf_id = re->vrf_id;
        api.type = re->type;
        api.safi = SAFI_UNICAST;
-       api.instance = re->instance;
+       if (is_table_direct) {
+               api.instance = re->table;
+               api.type = ZEBRA_ROUTE_TABLE_DIRECT;
+       } else
+               api.instance = re->instance;
        api.flags = re->flags;
 
        afi = family2afi(p->family);
@@ -593,7 +597,10 @@ int zsend_redistribute_route(int cmd, struct zserv *client,
 
        /* Attributes. */
        SET_FLAG(api.message, ZAPI_MESSAGE_DISTANCE);
-       api.distance = re->distance;
+       if (is_table_direct)
+               api.distance = ZEBRA_TABLEDIRECT_DISTANCE_DEFAULT;
+       else
+               api.distance = re->distance;
        SET_FLAG(api.message, ZAPI_MESSAGE_METRIC);
        api.metric = re->metric;
        if (re->tag) {
index a01cbf675d51bcdf44c060462fbc61d928ccb209..def1e8a1bdff6f37ad44016632499f2f4dac824d 100644 (file)
@@ -53,7 +53,8 @@ extern int zsend_interface_update(int cmd, struct zserv *client,
                                  struct interface *ifp);
 extern int zsend_redistribute_route(int cmd, struct zserv *zclient,
                                    const struct route_node *rn,
-                                   const struct route_entry *re);
+                                   const struct route_entry *re,
+                                   bool is_table_direct);
 
 extern int zsend_router_id_update(struct zserv *zclient, afi_t afi,
                                  struct prefix *p, vrf_id_t vrf_id);
index 97b6a7decfea406d965f18fea4b5d6829780778e..37c042c04482c804f914f8993f97789d39220093 100644 (file)
@@ -130,6 +130,7 @@ static const struct {
        [ZEBRA_ROUTE_OLSR] = {ZEBRA_ROUTE_OLSR, ZEBRA_MAX_DISTANCE_DEFAULT,
                              META_QUEUE_OTHER},
        [ZEBRA_ROUTE_TABLE] = {ZEBRA_ROUTE_TABLE, ZEBRA_TABLE_DISTANCE_DEFAULT, META_QUEUE_STATIC},
+       [ZEBRA_ROUTE_TABLE_DIRECT] = {ZEBRA_ROUTE_TABLE_DIRECT, ZEBRA_TABLEDIRECT_DISTANCE_DEFAULT, META_QUEUE_STATIC},
        [ZEBRA_ROUTE_LDP] = {ZEBRA_ROUTE_LDP, ZEBRA_LDP_DISTANCE_DEFAULT,
                             META_QUEUE_OTHER},
        [ZEBRA_ROUTE_VNC] = {ZEBRA_ROUTE_VNC, ZEBRA_EBGP_DISTANCE_DEFAULT,