]> git.puffer.fish Git - mirror/frr.git/commitdiff
lib: add backup nexthops to zapi routes
authorMark Stapp <mjs@voltanet.io>
Mon, 11 Nov 2019 20:50:30 +0000 (15:50 -0500)
committerMark Stapp <mjs@voltanet.io>
Fri, 27 Mar 2020 13:37:02 +0000 (09:37 -0400)
Add backup nexthop info to zapi route messages.

Signed-off-by: Mark Stapp <mjs@voltanet.io>
lib/zclient.c
lib/zclient.h
zebra/zapi_msg.c

index a8f973ab9588f2352dbf9b48874cbddb850adc7d..53ca4e1327e88dc44095d18fb9d8b23a0b0329be 100644 (file)
@@ -948,6 +948,10 @@ int zapi_nexthop_encode(struct stream *s, const struct zapi_nexthop *api_nh,
                stream_put(s, &(api_nh->rmac),
                           sizeof(struct ethaddr));
 
+       /* Index of backup nexthop */
+       if (CHECK_FLAG(nh_flags, ZAPI_NEXTHOP_FLAG_HAS_BACKUP))
+               stream_putc(s, api_nh->backup_idx);
+
 done:
        return ret;
 }
@@ -1007,6 +1011,10 @@ int zapi_route_encode(uint8_t cmd, struct stream *s, struct zapi_route *api)
                        return -1;
                }
 
+               /* We canonicalize the nexthops by sorting them; this allows
+                * zebra to resolve the list of nexthops to a nexthop-group
+                * more efficiently.
+                */
                zapi_nexthop_group_sort(api->nexthops, api->nexthop_num);
 
                stream_putw(s, api->nexthop_num);
@@ -1033,6 +1041,50 @@ int zapi_route_encode(uint8_t cmd, struct stream *s, struct zapi_route *api)
                }
        }
 
+       /* Backup nexthops  */
+       if (CHECK_FLAG(api->message, ZAPI_MESSAGE_BACKUP_NEXTHOPS)) {
+               /* limit the number of nexthops if necessary */
+               if (api->backup_nexthop_num > MULTIPATH_NUM) {
+                       char buf[PREFIX2STR_BUFFER];
+
+                       prefix2str(&api->prefix, buf, sizeof(buf));
+                       flog_err(
+                               EC_LIB_ZAPI_ENCODE,
+                               "%s: prefix %s: can't encode %u backup nexthops (maximum is %u)",
+                               __func__, buf, api->backup_nexthop_num,
+                               MULTIPATH_NUM);
+                       return -1;
+               }
+
+               /* Note that we do not sort the list of backup nexthops -
+                * this list is treated as an array and indexed by each
+                * primary nexthop that is associated with a backup.
+                */
+
+               stream_putw(s, api->backup_nexthop_num);
+
+               for (i = 0; i < api->backup_nexthop_num; i++) {
+                       api_nh = &api->backup_nexthops[i];
+
+                       /* MPLS labels for BGP-LU or Segment Routing */
+                       if (api_nh->label_num > MPLS_MAX_LABELS) {
+                               char buf[PREFIX2STR_BUFFER];
+
+                               prefix2str(&api->prefix, buf, sizeof(buf));
+
+                               flog_err(EC_LIB_ZAPI_ENCODE,
+                                        "%s: prefix %s: backup: can't encode %u labels (maximum is %u)",
+                                        __func__, buf,
+                                        api_nh->label_num,
+                                        MPLS_MAX_LABELS);
+                               return -1;
+                       }
+
+                       if (zapi_nexthop_encode(s, api_nh, api->flags) != 0)
+                               return -1;
+               }
+       }
+
        /* Attributes. */
        if (CHECK_FLAG(api->message, ZAPI_MESSAGE_DISTANCE))
                stream_putc(s, api->distance);
@@ -1108,6 +1160,10 @@ static int zapi_nexthop_decode(struct stream *s, struct zapi_nexthop *api_nh,
                STREAM_GET(&(api_nh->rmac), s,
                           sizeof(struct ethaddr));
 
+       /* Backup nexthop index */
+       if (CHECK_FLAG(api_nh->flags, ZAPI_NEXTHOP_FLAG_HAS_BACKUP))
+               STREAM_GETC(s, api_nh->backup_idx);
+
        /* Success */
        ret = 0;
 
@@ -1214,6 +1270,24 @@ int zapi_route_decode(struct stream *s, struct zapi_route *api)
                }
        }
 
+       /* Backup nexthops. */
+       if (CHECK_FLAG(api->message, ZAPI_MESSAGE_BACKUP_NEXTHOPS)) {
+               STREAM_GETW(s, api->backup_nexthop_num);
+               if (api->backup_nexthop_num > MULTIPATH_NUM) {
+                       flog_err(EC_LIB_ZAPI_ENCODE,
+                                "%s: invalid number of backup nexthops (%u)",
+                                __func__, api->backup_nexthop_num);
+                       return -1;
+               }
+
+               for (i = 0; i < api->backup_nexthop_num; i++) {
+                       api_nh = &api->backup_nexthops[i];
+
+                       if (zapi_nexthop_decode(s, api_nh, api->flags) != 0)
+                               return -1;
+               }
+       }
+
        /* Attributes. */
        if (CHECK_FLAG(api->message, ZAPI_MESSAGE_DISTANCE))
                STREAM_GETC(s, api->distance);
@@ -1424,6 +1498,11 @@ int zapi_nexthop_from_nexthop(struct zapi_nexthop *znh,
        znh->gate = nh->gate;
 
        if (nh->nh_label && (nh->nh_label->num_labels > 0)) {
+
+               /* Validate */
+               if (nh->nh_label->num_labels > MPLS_MAX_LABELS)
+                       return -1;
+
                for (i = 0; i < nh->nh_label->num_labels; i++)
                        znh->labels[i] = nh->nh_label->label[i];
 
index 03d0485f90bac9fe75f46cb220bfd6048a165aca..a2ee264be3d192457c06e41902dd4fbd9224a62a 100644 (file)
@@ -341,6 +341,9 @@ struct zclient {
 #define ZAPI_MESSAGE_TAG      0x08
 #define ZAPI_MESSAGE_MTU      0x10
 #define ZAPI_MESSAGE_SRCPFX   0x20
+/* Backup nexthops are present */
+#define ZAPI_MESSAGE_BACKUP_NEXTHOPS 0x40
+
 /*
  * This should only be used by a DAEMON that needs to communicate
  * the table being used is not in the VRF.  You must pass the
@@ -377,14 +380,21 @@ struct zapi_nexthop {
        struct ethaddr rmac;
 
        uint32_t weight;
+
+       /* Index of backup nexthop */
+       uint8_t backup_idx;
 };
 
 /*
- * ZAPI nexthop flags values
+ * ZAPI nexthop flags values - we're encoding a single octet
+ * initially, so ensure that the on-the-wire encoding continues
+ * to match the number of valid flags.
  */
+
 #define ZAPI_NEXTHOP_FLAG_ONLINK       0x01
 #define ZAPI_NEXTHOP_FLAG_LABEL                0x02
 #define ZAPI_NEXTHOP_FLAG_WEIGHT       0x04
+#define ZAPI_NEXTHOP_FLAG_HAS_BACKUP   0x08 /* Nexthop has a backup */
 
 /*
  * Some of these data structures do not map easily to
@@ -448,6 +458,10 @@ struct zapi_route {
        uint16_t nexthop_num;
        struct zapi_nexthop nexthops[MULTIPATH_NUM];
 
+       /* Support backup routes for IP FRR, TI-LFA, traffic engineering */
+       uint16_t backup_nexthop_num;
+       struct zapi_nexthop backup_nexthops[MULTIPATH_NUM];
+
        uint8_t distance;
 
        uint32_t metric;
index 2190bfab4ff0312b1700ca3bdc0bdb139b62ac0c..93a32b31b7b288a4b8fdb13019db8aefc6e90203 100644 (file)
@@ -1440,8 +1440,8 @@ static void zread_route_add(ZAPI_HANDLER_ARGS)
                char buf_prefix[PREFIX_STRLEN];
 
                prefix2str(&api.prefix, buf_prefix, sizeof(buf_prefix));
-               zlog_debug("%s: p=%s, flags=0x%x",
-                          __func__, buf_prefix, api.flags);
+               zlog_debug("%s: p=%s, msg flags=0x%x, flags=0x%x",
+                          __func__, buf_prefix, (int)api.message, api.flags);
        }
 
        /* Allocate new route. */