X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=src%2Fvnet%2Fsrmpls%2Fsr_mpls_policy.c;h=8f0804850f137ab903afcef8d01031cf29b0e307;hb=66edaf209fcfa618f42c0e6d21873a31de86b412;hp=d75f2d1e22fc821e2914859e206bbb559226df91;hpb=42998828c9bfa419ff3d9c68fd50cd148e24d4e4;p=vpp.git diff --git a/src/vnet/srmpls/sr_mpls_policy.c b/src/vnet/srmpls/sr_mpls_policy.c old mode 100755 new mode 100644 index d75f2d1e22f..8f0804850f1 --- a/src/vnet/srmpls/sr_mpls_policy.c +++ b/src/vnet/srmpls/sr_mpls_policy.c @@ -34,9 +34,6 @@ #include #include #include -#include -#include -#include #include #include @@ -64,9 +61,10 @@ create_sl (mpls_sr_policy_t * sr_policy, mpls_label_t * sl, u32 weight) { mpls_sr_main_t *sm = &sr_mpls_main; mpls_sr_sl_t *segment_list; + u32 ii; pool_get (sm->sid_lists, segment_list); - memset (segment_list, 0, sizeof (*segment_list)); + clib_memset (segment_list, 0, sizeof (*segment_list)); vec_add1 (sr_policy->segments_lists, segment_list - sm->sid_lists); @@ -75,33 +73,50 @@ create_sl (mpls_sr_policy_t * sr_policy, mpls_label_t * sl, u32 weight) (weight != (u32) ~ 0 ? weight : SR_SEGMENT_LIST_WEIGHT_DEFAULT); segment_list->segments = vec_dup (sl); - fib_route_path_t path = { - .frp_proto = DPO_PROTO_MPLS, - .frp_sw_if_index = ~0, - .frp_fib_index = 0, - .frp_weight = segment_list->weight, - .frp_flags = FIB_ROUTE_PATH_FLAG_NONE, - .frp_label_stack = NULL, - .frp_local_label = sl[0], - }; - - vec_add (path.frp_label_stack, sl + 1, vec_len (sl) - 1); - - fib_route_path_t *paths = NULL; - vec_add1 (paths, path); - mpls_eos_bit_t eos; FOR_EACH_MPLS_EOS_BIT (eos) { - /* *INDENT-OFF* */ - fib_prefix_t pfx = { - .fp_len = 21, - .fp_proto = FIB_PROTOCOL_MPLS, - .fp_label = sr_policy->bsid, - .fp_eos = eos, - .fp_payload_proto = DPO_PROTO_MPLS, - }; - /* *INDENT-ON* */ + fib_route_path_t path = { + .frp_proto = DPO_PROTO_MPLS, + .frp_sw_if_index = ~0, + .frp_fib_index = 0, + .frp_weight = segment_list->weight, + .frp_flags = FIB_ROUTE_PATH_FLAG_NONE, + .frp_label_stack = NULL, + .frp_local_label = sl[0], + }; + + if (vec_len (sl) > 1) + { + vec_validate (path.frp_label_stack, vec_len (sl) - 2); + for (ii = 1; ii < vec_len (sl); ii++) + { + path.frp_label_stack[ii - 1].fml_value = sl[ii]; + } + } + else + { + /* + * add an impliciet NULL label to allow non-eos recursion + */ + fib_mpls_label_t lbl = { + .fml_value = MPLS_IETF_IMPLICIT_NULL_LABEL, + }; + vec_add1 (path.frp_label_stack, lbl); + } + + fib_route_path_t *paths = NULL; + vec_add1 (paths, path); + + /* *INDENT-OFF* */ + fib_prefix_t pfx = { + .fp_len = 21, + .fp_proto = FIB_PROTOCOL_MPLS, + .fp_label = sr_policy->bsid, + .fp_eos = eos, + .fp_payload_proto = DPO_PROTO_MPLS, + }; + /* *INDENT-ON* */ fib_table_entry_path_add2 (0, &pfx, @@ -109,10 +124,9 @@ create_sl (mpls_sr_policy_t * sr_policy, mpls_label_t * sl, u32 weight) (sr_policy->type == SR_POLICY_TYPE_DEFAULT ? FIB_ENTRY_FLAG_NONE : FIB_ENTRY_FLAG_MULTICAST), paths); + vec_free (paths); } - vec_free (paths); - return segment_list; } @@ -145,6 +159,10 @@ sr_mpls_policy_add (mpls_label_t bsid, mpls_label_t * segments, if (!sm->sr_policies_index_hash) sm->sr_policies_index_hash = hash_create (0, sizeof (mpls_label_t)); + /* MPLS SR policies cannot be created unless the MPLS table is present */ + if (~0 == fib_table_find (FIB_PROTOCOL_MPLS, MPLS_FIB_DEFAULT_TABLE_ID)) + return (VNET_API_ERROR_NO_SUCH_TABLE); + /* Search for existing keys (BSID) */ p = hash_get (sm->sr_policies_index_hash, bsid); if (p) @@ -154,7 +172,14 @@ sr_mpls_policy_add (mpls_label_t bsid, mpls_label_t * segments, } /* Add an SR policy object */ pool_get (sm->sr_policies, sr_policy); - memset (sr_policy, 0, sizeof (*sr_policy)); + clib_memset (sr_policy, 0, sizeof (*sr_policy)); + + /* the first policy needs to lock the MPLS table so it doesn't + * disappear with policies in it */ + if (1 == pool_elts (sm->sr_policies)) + fib_table_find_or_create_and_lock (FIB_PROTOCOL_MPLS, + MPLS_FIB_DEFAULT_TABLE_ID, + FIB_SOURCE_SR); sr_policy->bsid = bsid; sr_policy->type = behavior; sr_policy->endpoint_type = 0; @@ -247,6 +272,10 @@ sr_mpls_policy_del (mpls_label_t bsid) hash_unset (sm->sr_policies_index_hash, sr_policy->bsid); pool_put (sm->sr_policies, sr_policy); + if (0 == pool_elts (sm->sr_policies)) + fib_table_unlock (MPLS_FIB_DEFAULT_TABLE_ID, + FIB_PROTOCOL_MPLS, FIB_SOURCE_SR); + return 0; } @@ -488,6 +517,7 @@ sr_mpls_policy_command_fn (vlib_main_t * vm, unformat_input_t * input, rv = sr_mpls_policy_add (bsid, segments, (is_spray ? SR_POLICY_TYPE_SPRAY : SR_POLICY_TYPE_DEFAULT), weight); + vec_free (segments); } else if (is_del) rv = sr_mpls_policy_del (bsid); @@ -502,6 +532,7 @@ sr_mpls_policy_command_fn (vlib_main_t * vm, unformat_input_t * input, if (operation == 3 && weight == (u32) ~ 0) return clib_error_return (0, "No new weight for the SL specified"); rv = sr_mpls_policy_mod (bsid, operation, segments, sl_index, weight); + vec_free (segments); } switch (rv) { @@ -529,6 +560,8 @@ sr_mpls_policy_command_fn (vlib_main_t * vm, unformat_input_t * input, return clib_error_return (0, "Could not modify the segment list. " "The given SL is not associated with such SR policy."); + case VNET_API_ERROR_NO_SUCH_TABLE: + return clib_error_return (0, "the Default MPLS table is not present"); default: return clib_error_return (0, "BUG: sr policy returns %d", rv); } @@ -565,9 +598,9 @@ show_sr_mpls_policies_command_fn (vlib_main_t * vm, unformat_input_t * input, vlib_cli_output (vm, "SR MPLS policies:"); /* *INDENT-OFF* */ - pool_foreach(sr_policy, sm->sr_policies, { + pool_foreach (sr_policy, sm->sr_policies) { vec_add1(vec_policies, sr_policy); - }); + } /* *INDENT-ON* */ vec_foreach_index (i, vec_policies) @@ -665,6 +698,10 @@ sr_mpls_policy_assign_endpoint_color (mpls_label_t bsid, old_value = mhash_get ((mhash_t *) endpoint_table, &sr_policy->endpoint); + /* CID 180995 This should never be NULL unless the two hash tables + * get out of sync */ + ALWAYS_ASSERT (old_value != NULL); + fib_prefix_t pfx = { 0 }; pfx.fp_proto = FIB_PROTOCOL_MPLS; pfx.fp_len = 21; @@ -764,7 +801,11 @@ sr_mpls_policy_assign_endpoint_color (mpls_label_t bsid, FIB_SOURCE_SR, FIB_ENTRY_FLAG_LOOSE_URPF_EXEMPT, paths); - vec_add1 (path.frp_label_stack, MPLS_IETF_IMPLICIT_NULL_LABEL); + fib_mpls_label_t fml = { + .fml_value = MPLS_IETF_IMPLICIT_NULL_LABEL, + }; + + vec_add1 (path.frp_label_stack, fml); pfx.fp_eos = MPLS_NON_EOS; path.frp_eos = MPLS_NON_EOS; @@ -799,7 +840,7 @@ cli_sr_mpls_policy_ec_command_fn (vlib_main_t * vm, unformat_input_t * input, u8 endpoint_type = 0; char clear = 0, color_set = 0, bsid_set = 0; - memset (&endpoint, 0, sizeof (ip46_address_t)); + clib_memset (&endpoint, 0, sizeof (ip46_address_t)); int rv; while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)