diff options
Diffstat (limited to 'zebra/zebra_nhg.c')
| -rw-r--r-- | zebra/zebra_nhg.c | 93 |
1 files changed, 84 insertions, 9 deletions
diff --git a/zebra/zebra_nhg.c b/zebra/zebra_nhg.c index 9bfd7aacb7..b8faaa43fd 100644 --- a/zebra/zebra_nhg.c +++ b/zebra/zebra_nhg.c @@ -28,6 +28,7 @@ #include "lib/mpls.h" #include "lib/jhash.h" #include "lib/debug.h" +#include "lib/lib_errors.h" #include "zebra/connected.h" #include "zebra/debug.h" @@ -36,6 +37,7 @@ #include "zebra/zebra_rnh.h" #include "zebra/zebra_routemap.h" #include "zebra/zebra_memory.h" +#include "zebra/zebra_srte.h" #include "zebra/zserv.h" #include "zebra/rt.h" #include "zebra_errors.h" @@ -1620,7 +1622,8 @@ void zebra_nhg_increment_ref(struct nhg_hash_entry *nhe) } static void nexthop_set_resolved(afi_t afi, const struct nexthop *newhop, - struct nexthop *nexthop) + struct nexthop *nexthop, + struct zebra_sr_policy *policy) { struct nexthop *resolved_hop; uint8_t num_labels = 0; @@ -1684,7 +1687,21 @@ static void nexthop_set_resolved(afi_t afi, const struct nexthop *newhop, resolved_hop->flags |= NEXTHOP_FLAG_ONLINK; /* Copy labels of the resolved route and the parent resolving to it */ - if (newhop->nh_label) { + if (policy) { + int i = 0; + + /* + * Don't push the first SID if the corresponding action in the + * LFIB is POP. + */ + if (!newhop->nh_label || !newhop->nh_label->num_labels + || newhop->nh_label->label[0] == MPLS_LABEL_IMPLICIT_NULL) + i = 1; + + for (; i < policy->segment_list.label_num; i++) + labels[num_labels++] = policy->segment_list.labels[i]; + label_type = policy->segment_list.type; + } else if (newhop->nh_label) { for (i = 0; i < newhop->nh_label->num_labels; i++) { /* Be a bit picky about overrunning the local array */ if (num_labels >= MPLS_MAX_LABELS) { @@ -1771,10 +1788,13 @@ static int nexthop_active(afi_t afi, struct route_entry *re, struct route_node *rn; struct route_entry *match = NULL; int resolved; + zebra_nhlfe_t *nhlfe; struct nexthop *newhop; struct interface *ifp; rib_dest_t *dest; struct zebra_vrf *zvrf; + struct in_addr local_ipv4; + struct in_addr *ipv4; if ((nexthop->type == NEXTHOP_TYPE_IPV4) || nexthop->type == NEXTHOP_TYPE_IPV6) @@ -1835,13 +1855,63 @@ static int nexthop_active(afi_t afi, struct route_entry *re, return 0; } + /* Validation for ipv4 mapped ipv6 nexthop. */ + if (IS_MAPPED_IPV6(&nexthop->gate.ipv6)) { + afi = AFI_IP; + ipv4 = &local_ipv4; + ipv4_mapped_ipv6_to_ipv4(&nexthop->gate.ipv6, ipv4); + } else { + ipv4 = &nexthop->gate.ipv4; + } + + if (nexthop->srte_color) { + struct ipaddr endpoint = {0}; + struct zebra_sr_policy *policy; + + switch (afi) { + case AFI_IP: + endpoint.ipa_type = IPADDR_V4; + endpoint.ipaddr_v4 = *ipv4; + break; + case AFI_IP6: + endpoint.ipa_type = IPADDR_V6; + endpoint.ipaddr_v6 = nexthop->gate.ipv6; + break; + default: + flog_err(EC_LIB_DEVELOPMENT, + "%s: unknown address-family: %u", __func__, + afi); + exit(1); + } + + policy = zebra_sr_policy_find(nexthop->srte_color, &endpoint); + if (policy && policy->status == ZEBRA_SR_POLICY_UP) { + resolved = 0; + frr_each_safe (nhlfe_list, &policy->lsp->nhlfe_list, + nhlfe) { + if (!CHECK_FLAG(nhlfe->flags, + NHLFE_FLAG_SELECTED) + || CHECK_FLAG(nhlfe->flags, + NHLFE_FLAG_DELETED)) + continue; + SET_FLAG(nexthop->flags, + NEXTHOP_FLAG_RECURSIVE); + nexthop_set_resolved(afi, nhlfe->nexthop, + nexthop, policy); + resolved = 1; + } + if (resolved) + return 1; + } + } + /* Make lookup prefix. */ memset(&p, 0, sizeof(struct prefix)); switch (afi) { case AFI_IP: p.family = AF_INET; p.prefixlen = IPV4_MAX_PREFIXLEN; - p.u.prefix4 = nexthop->gate.ipv4; + p.u.prefix4 = *ipv4; break; case AFI_IP6: p.family = AF_INET6; @@ -1951,8 +2021,11 @@ static int nexthop_active(afi_t afi, struct route_entry *re, goto done_with_match; } - /* Examine installed nexthops */ - nhg = &match->nhe->nhg; + /* Examine installed nexthops; note that there + * may not be any installed primary nexthops if + * only backups are installed. + */ + nhg = rib_get_fib_nhg(match); for (ALL_NEXTHOPS_PTR(nhg, newhop)) { if (!nexthop_valid_resolve(nexthop, newhop)) continue; @@ -1964,7 +2037,8 @@ static int nexthop_active(afi_t afi, struct route_entry *re, SET_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE); - nexthop_set_resolved(afi, newhop, nexthop); + nexthop_set_resolved(afi, newhop, nexthop, + NULL); resolved = 1; } @@ -1973,8 +2047,7 @@ static int nexthop_active(afi_t afi, struct route_entry *re, * dedicated fib list. */ nhg = rib_get_fib_backup_nhg(match); - if (nhg == NULL || - nhg == zebra_nhg_get_backup_nhg(match->nhe)) + if (nhg == NULL || nhg->nexthop == NULL) goto done_with_match; for (ALL_NEXTHOPS_PTR(nhg, newhop)) { @@ -1988,7 +2061,8 @@ static int nexthop_active(afi_t afi, struct route_entry *re, SET_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE); - nexthop_set_resolved(afi, newhop, nexthop); + nexthop_set_resolved(afi, newhop, nexthop, + NULL); resolved = 1; } done_with_match: @@ -2589,6 +2663,7 @@ void zebra_nhg_dplane_result(struct zebra_dplane_ctx *ctx) case DPLANE_OP_RULE_ADD: case DPLANE_OP_RULE_DELETE: case DPLANE_OP_RULE_UPDATE: + case DPLANE_OP_NEIGH_DISCOVER: case DPLANE_OP_NONE: break; } |
