diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index a23bffd4ae..b49206adce 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -3070,7 +3070,9 @@ static void bgp_process_evpn_route_injection(struct bgp *bgp, afi_t afi, * the IMPLICIT_NULL label. This is pretty specialized: it's only called * in a path where we basically _know_ this is a BGP-LU route. */ -static bool bgp_lu_need_imp_null(const struct bgp_path_info *new_select) +static bool bgp_lu_need_null_label(struct bgp *bgp, + const struct bgp_path_info *new_select, + afi_t afi, mpls_label_t *label) { /* Certain types get imp null; so do paths where the nexthop is * not labeled. @@ -3079,12 +3081,20 @@ static bool bgp_lu_need_imp_null(const struct bgp_path_info *new_select) || new_select->sub_type == BGP_ROUTE_AGGREGATE || new_select->sub_type == BGP_ROUTE_REDISTRIBUTE) return true; - else if (new_select->extra == NULL || - !bgp_is_valid_label(&new_select->extra->label[0])) - /* TODO -- should be configurable? */ - return true; - else + else if (new_select->extra && + bgp_is_valid_label(&new_select->extra->label[0])) return false; + if (label == NULL) + return true; + if (!!CHECK_FLAG(bgp->flags, BGP_FLAG_LU_EXPLICIT_NULL)) + /* Disable PHP : explicit-null */ + *label = afi == AFI_IP ? MPLS_LABEL_IPV4_EXPLICIT_NULL + : MPLS_LABEL_IPV6_EXPLICIT_NULL; + else + /* Enforced PHP popping: implicit-null */ + *label = MPLS_LABEL_IMPLICIT_NULL; + + return true; } /* @@ -3113,6 +3123,7 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest, struct bgp_path_info *old_select; struct bgp_path_info_pair old_and_new; int debug = 0; + mpls_label_t mpls_label_null; if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)) { if (dest) @@ -3167,7 +3178,7 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest, * Right now, since we only deal with per-prefix labels, it is not * necessary to do this upon changes to best path. Exceptions: * - label index has changed -> recalculate resulting label - * - path_info sub_type changed -> switch to/from implicit-null + * - path_info sub_type changed -> switch to/from null label value * - no valid label (due to removed static label binding) -> get new one */ if (bgp->allocate_mpls_labels[afi][safi]) { @@ -3176,11 +3187,12 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest, || bgp_label_index_differs(new_select, old_select) || new_select->sub_type != old_select->sub_type || !bgp_is_valid_label(&dest->local_label)) { - /* Enforced penultimate hop popping: - * implicit-null for local routes, aggregate - * and redistributed routes + /* control label imposition for local routes, + * aggregate and redistributed routes */ - if (bgp_lu_need_imp_null(new_select)) { + mpls_label_null = MPLS_LABEL_IMPLICIT_NULL; + if (bgp_lu_need_null_label(bgp, new_select, afi, + &mpls_label_null)) { if (CHECK_FLAG( dest->flags, BGP_NODE_REGISTERED_FOR_LABEL) @@ -3189,8 +3201,7 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest, BGP_NODE_LABEL_REQUESTED)) bgp_unregister_for_label(dest); dest->local_label = mpls_lse_encode( - MPLS_LABEL_IMPLICIT_NULL, 0, 0, - 1); + mpls_label_null, 0, 0, 1); bgp_set_valid_label(&dest->local_label); } else bgp_register_for_label(dest, diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index f7b0caf493..de781d6b1e 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -2820,6 +2820,21 @@ DEFUN(no_bgp_ebgp_requires_policy, no_bgp_ebgp_requires_policy_cmd, return CMD_SUCCESS; } +DEFPY(bgp_lu_uses_explicit_null, bgp_lu_uses_explicit_null_cmd, + "[no] bgp labeled-unicast explicit-null", + NO_STR BGP_STR + "BGP Labeled-unicast options\n" + "Use explicit-null label values for local prefixes\n") +{ + VTY_DECLVAR_CONTEXT(bgp, bgp); + + if (no) + UNSET_FLAG(bgp->flags, BGP_FLAG_LU_EXPLICIT_NULL); + else + SET_FLAG(bgp->flags, BGP_FLAG_LU_EXPLICIT_NULL); + return CMD_SUCCESS; +} + DEFUN(bgp_suppress_duplicates, bgp_suppress_duplicates_cmd, "bgp suppress-duplicates", BGP_STR @@ -18235,6 +18250,9 @@ int bgp_config_write(struct vty *vty) ? "" : "no "); + if (!!CHECK_FLAG(bgp->flags, BGP_FLAG_LU_EXPLICIT_NULL)) + vty_out(vty, " bgp labeled-unicast explicit-null\n"); + /* draft-ietf-idr-deprecate-as-set-confed-set */ if (bgp->reject_as_sets) vty_out(vty, " bgp reject-as-sets\n"); @@ -19154,6 +19172,9 @@ void bgp_vty_init(void) install_element(BGP_NODE, &bgp_ebgp_requires_policy_cmd); install_element(BGP_NODE, &no_bgp_ebgp_requires_policy_cmd); + /* bgp labeled-unicast explicit-null */ + install_element(BGP_NODE, &bgp_lu_uses_explicit_null_cmd); + /* bgp suppress-duplicates */ install_element(BGP_NODE, &bgp_suppress_duplicates_cmd); install_element(BGP_NODE, &no_bgp_suppress_duplicates_cmd); diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h index a08a2870ee..b6491bf799 100644 --- a/bgpd/bgpd.h +++ b/bgpd/bgpd.h @@ -500,6 +500,8 @@ struct bgp { #define BGP_FLAG_HARD_ADMIN_RESET (1ULL << 31) /* Evaluate the AIGP attribute during the best path selection process */ #define BGP_FLAG_COMPARE_AIGP (1ULL << 32) +/* For BGP-LU, force local prefixes to use explicit-null label */ +#define BGP_FLAG_LU_EXPLICIT_NULL (1ULL << 33) /* BGP default address-families. * New peers inherit enabled afi/safis from bgp instance. diff --git a/doc/user/bgp.rst b/doc/user/bgp.rst index 946f0699f2..97d7ce6b75 100644 --- a/doc/user/bgp.rst +++ b/doc/user/bgp.rst @@ -2767,6 +2767,17 @@ happened automatically if local-role is set. value of his role (by setting local-role on his side). Otherwise, a Role Mismatch Notification will be sent. +Labeled unicast +--------------- + +*bgpd* supports labeled information, as per :rfc:`3107`. + +.. clicmd:: bgp labeled-unicast explicit-null + +By default, locally advertised prefixes use the `implicit-null` label to +encode in the outgoing NLRI. The following command uses the `explicit-null` +label value for all the BGP instances. + .. _bgp-l3vpn-vrfs: L3VPN VRFs