diff options
Diffstat (limited to 'isisd/isis_zebra.c')
| -rw-r--r-- | isisd/isis_zebra.c | 173 |
1 files changed, 126 insertions, 47 deletions
diff --git a/isisd/isis_zebra.c b/isisd/isis_zebra.c index 9ed868e795..26cc175a52 100644 --- a/isisd/isis_zebra.c +++ b/isisd/isis_zebra.c @@ -168,42 +168,29 @@ static int isis_zebra_link_params(ZAPI_CALLBACK_ARGS) return 0; } -void isis_zebra_route_add_route(struct isis *isis, - struct prefix *prefix, - struct prefix_ipv6 *src_p, - struct isis_route_info *route_info) +enum isis_zebra_nexthop_type { + ISIS_ROUTE_NEXTHOP_MAIN = 0, + ISIS_ROUTE_NEXTHOP_BACKUP, + ISIS_MPLS_NEXTHOP_MAIN, + ISIS_MPLS_NEXTHOP_BACKUP, +}; + +static int isis_zebra_add_nexthops(struct isis *isis, struct list *nexthops, + struct zapi_nexthop zapi_nexthops[], + enum isis_zebra_nexthop_type type, + uint8_t backup_nhs) { - struct zapi_route api; - struct zapi_nexthop *api_nh; struct isis_nexthop *nexthop; struct listnode *node; int count = 0; - if (zclient->sock < 0) - return; - - memset(&api, 0, sizeof(api)); - api.vrf_id = isis->vrf_id; - api.type = PROTO_TYPE; - api.safi = SAFI_UNICAST; - api.prefix = *prefix; - if (src_p && src_p->prefixlen) { - api.src_prefix = *src_p; - SET_FLAG(api.message, ZAPI_MESSAGE_SRCPFX); - } - SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP); - SET_FLAG(api.message, ZAPI_MESSAGE_METRIC); - api.metric = route_info->cost; -#if 0 - SET_FLAG(api.message, ZAPI_MESSAGE_DISTANCE); - api.distance = route_info->depth; -#endif - /* Nexthops */ - for (ALL_LIST_ELEMENTS_RO(route_info->nexthops, node, nexthop)) { + for (ALL_LIST_ELEMENTS_RO(nexthops, node, nexthop)) { + struct zapi_nexthop *api_nh; + if (count >= MULTIPATH_NUM) break; - api_nh = &api.nexthops[count]; + api_nh = &zapi_nexthops[count]; if (fabricd) SET_FLAG(api_nh->flags, ZAPI_NEXTHOP_FLAG_ONLINK); api_nh->vrf_id = isis->vrf_id; @@ -234,11 +221,98 @@ void isis_zebra_route_add_route(struct isis *isis, } api_nh->ifindex = nexthop->ifindex; + + /* Add MPLS label(s). */ + switch (type) { + case ISIS_ROUTE_NEXTHOP_MAIN: + case ISIS_ROUTE_NEXTHOP_BACKUP: + /* + * SR/TI-LFA labels are installed using separate + * messages. + */ + break; + case ISIS_MPLS_NEXTHOP_MAIN: + if (nexthop->sr.label != MPLS_INVALID_LABEL) { + api_nh->label_num = 1; + api_nh->labels[0] = nexthop->sr.label; + } else { + api_nh->label_num = 1; + api_nh->labels[0] = MPLS_LABEL_IMPLICIT_NULL; + } + break; + case ISIS_MPLS_NEXTHOP_BACKUP: + if (nexthop->label_stack) { + api_nh->label_num = + nexthop->label_stack->num_labels; + memcpy(api_nh->labels, + nexthop->label_stack->label, + sizeof(mpls_label_t) + * api_nh->label_num); + } else { + api_nh->label_num = 1; + api_nh->labels[0] = MPLS_LABEL_IMPLICIT_NULL; + } + break; + } + + /* Backup nexthop handling. */ + if (backup_nhs) { + SET_FLAG(api_nh->flags, ZAPI_NEXTHOP_FLAG_HAS_BACKUP); + /* + * If the backup has multiple nexthops, all of them + * protect the same primary nexthop since ECMP routes + * have no backups. + */ + api_nh->backup_num = backup_nhs; + for (int i = 0; i < backup_nhs; i++) + api_nh->backup_idx[i] = i; + } count++; } - if (!count) + + return count; +} + +void isis_zebra_route_add_route(struct isis *isis, struct prefix *prefix, + struct prefix_ipv6 *src_p, + struct isis_route_info *route_info) +{ + struct zapi_route api; + int count = 0; + + if (zclient->sock < 0) return; + memset(&api, 0, sizeof(api)); + api.vrf_id = isis->vrf_id; + api.type = PROTO_TYPE; + api.safi = SAFI_UNICAST; + api.prefix = *prefix; + if (src_p && src_p->prefixlen) { + api.src_prefix = *src_p; + SET_FLAG(api.message, ZAPI_MESSAGE_SRCPFX); + } + SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP); + SET_FLAG(api.message, ZAPI_MESSAGE_METRIC); + api.metric = route_info->cost; + + /* Add backup nexthops first. */ + if (route_info->backup) { + count = isis_zebra_add_nexthops( + isis, route_info->backup->nexthops, api.backup_nexthops, + ISIS_ROUTE_NEXTHOP_BACKUP, 0); + if (count > 0) { + SET_FLAG(api.message, ZAPI_MESSAGE_BACKUP_NEXTHOPS); + api.backup_nexthop_num = count; + } + } + + /* Add primary nexthops. */ + count = isis_zebra_add_nexthops(isis, route_info->nexthops, + api.nexthops, ISIS_ROUTE_NEXTHOP_MAIN, + count); + if (!count) + return; api.nexthop_num = count; zclient_route_send(ZEBRA_ROUTE_ADD, zclient, &api); @@ -274,11 +348,12 @@ void isis_zebra_route_del_route(struct isis *isis, */ static void isis_zebra_prefix_install_prefix_sid(const struct sr_prefix *srp) { + struct isis *isis = srp->srn->area->isis; struct zapi_labels zl; struct zapi_nexthop *znh; - struct listnode *node; - struct isis_nexthop *nexthop; struct interface *ifp; + struct isis_route_info *rinfo; + int count = 0; /* Prepare message. */ memset(&zl, 0, sizeof(zl)); @@ -308,23 +383,27 @@ static void isis_zebra_prefix_install_prefix_sid(const struct sr_prefix *srp) zl.route.type = ZEBRA_ROUTE_ISIS; zl.route.instance = 0; - for (ALL_LIST_ELEMENTS_RO(srp->u.remote.rinfo->nexthops, node, - nexthop)) { - if (nexthop->sr.label == MPLS_INVALID_LABEL) - continue; - - if (zl.nexthop_num >= MULTIPATH_NUM) - break; - - znh = &zl.nexthops[zl.nexthop_num++]; - znh->type = (srp->prefix.family == AF_INET) - ? NEXTHOP_TYPE_IPV4_IFINDEX - : NEXTHOP_TYPE_IPV6_IFINDEX; - znh->gate = nexthop->ip; - znh->ifindex = nexthop->ifindex; - znh->label_num = 1; - znh->labels[0] = nexthop->sr.label; + rinfo = srp->u.remote.rinfo; + + /* Add backup nexthops first. */ + if (rinfo->backup) { + count = isis_zebra_add_nexthops( + isis, rinfo->backup->nexthops, + zl.backup_nexthops, ISIS_MPLS_NEXTHOP_BACKUP, + 0); + if (count > 0) { + SET_FLAG(zl.message, ZAPI_LABELS_HAS_BACKUPS); + zl.backup_nexthop_num = count; + } } + + /* Add primary nexthops. */ + count = isis_zebra_add_nexthops(isis, rinfo->nexthops, + zl.nexthops, + ISIS_MPLS_NEXTHOP_MAIN, count); + if (!count) + return; + zl.nexthop_num = count; break; } |
