From c4c205b091934d96a173f4c0d75ef7e888298ac7 Mon Sep 17 00:00:00 2001 From: Takeru Hayasaka Date: Fri, 30 Dec 2022 16:41:44 +0900 Subject: sr: support define src ipv6 per encap policy Can to define src ip of outer IPv6 Hdr for each encap policy. Along with that, I decided to develop it as API version V2. This is useful in the SRv6 MUP case. For example, it will be possible to handle multiple UPF destinations. Type: feature Change-Id: I44ff7b54e8868619069621ab53e194e2c7a17435 Signed-off-by: Takeru Hayasaka --- src/vnet/srv6/sr_policy_rewrite.c | 62 ++++++++++++++++++++++++++------------- 1 file changed, 42 insertions(+), 20 deletions(-) (limited to 'src/vnet/srv6/sr_policy_rewrite.c') diff --git a/src/vnet/srv6/sr_policy_rewrite.c b/src/vnet/srv6/sr_policy_rewrite.c index 8ad857153e4..69a4d5e398c 100644 --- a/src/vnet/srv6/sr_policy_rewrite.c +++ b/src/vnet/srv6/sr_policy_rewrite.c @@ -193,11 +193,12 @@ VLIB_CLI_COMMAND (set_sr_hop_limit_command, static) = { * @brief SR rewrite string computation for IPv6 encapsulation (inline) * * @param sl is a vector of IPv6 addresses composing the Segment List + * @param src_v6addr is a encaps IPv6 source addr * * @return precomputed rewrite string for encapsulation */ static inline u8 * -compute_rewrite_encaps (ip6_address_t *sl, u8 type) +compute_rewrite_encaps (ip6_address_t *sl, ip6_address_t *src_v6addr, u8 type) { ip6_header_t *iph; ip6_sr_header_t *srh; @@ -225,8 +226,8 @@ compute_rewrite_encaps (ip6_address_t *sl, u8 type) iph = (ip6_header_t *) rs; iph->ip_version_traffic_class_and_flow_label = clib_host_to_net_u32 (0 | ((6 & 0xF) << 28)); - iph->src_address.as_u64[0] = sr_pr_encaps_src.as_u64[0]; - iph->src_address.as_u64[1] = sr_pr_encaps_src.as_u64[1]; + iph->src_address.as_u64[0] = src_v6addr->as_u64[0]; + iph->src_address.as_u64[1] = src_v6addr->as_u64[1]; iph->payload_length = header_length - IPv6_DEFAULT_HEADER_LENGTH; iph->protocol = IP_PROTOCOL_IPV6; iph->hop_limit = sr_pr_encaps_hop_limit; @@ -370,18 +371,20 @@ compute_rewrite_bsid (ip6_address_t * sl) * * @param sr_policy is the SR policy where the SL will be added * @param sl is a vector of IPv6 addresses composing the Segment List + * @param encap_src is a encaps IPv6 source addr. optional. * @param weight is the weight of the SegmentList (for load-balancing purposes) * @param is_encap represents the mode (SRH insertion vs Encapsulation) * * @return pointer to the just created segment list */ static inline ip6_sr_sl_t * -create_sl (ip6_sr_policy_t * sr_policy, ip6_address_t * sl, u32 weight, - u8 is_encap) +create_sl (ip6_sr_policy_t *sr_policy, ip6_address_t *sl, + ip6_address_t *encap_src, u32 weight, u8 is_encap) { ip6_sr_main_t *sm = &sr_main; ip6_sr_sl_t *segment_list; sr_policy_fn_registration_t *plugin = 0; + ip6_address_t encap_srcv6 = sr_pr_encaps_src; pool_get (sm->sid_lists, segment_list); clib_memset (segment_list, 0, sizeof (*segment_list)); @@ -400,8 +403,14 @@ create_sl (ip6_sr_policy_t * sr_policy, ip6_address_t * sl, u32 weight, if (is_encap) { - segment_list->rewrite = compute_rewrite_encaps (sl, sr_policy->type); + if (encap_src) + { + clib_memcpy_fast (&encap_srcv6, encap_src, sizeof (ip6_address_t)); + } + segment_list->rewrite = + compute_rewrite_encaps (sl, &encap_srcv6, sr_policy->type); segment_list->rewrite_bsid = segment_list->rewrite; + sr_policy->encap_src = encap_srcv6; } else { @@ -660,17 +669,19 @@ update_replicate (ip6_sr_policy_t * sr_policy) * * @param bsid is the bindingSID of the SR Policy * @param segments is a vector of IPv6 address composing the segment list + * @param encap_src is a encaps IPv6 source addr. optional. * @param weight is the weight of the sid list. optional. * @param behavior is the behavior of the SR policy. (default//spray) * @param fib_table is the VRF where to install the FIB entry for the BSID - * @param is_encap (bool) whether SR policy should behave as Encap/SRH Insertion + * @param is_encap (bool) whether SR policy should behave as Encap/SRH + * Insertion * * @return 0 if correct, else error */ int -sr_policy_add (ip6_address_t *bsid, ip6_address_t *segments, u32 weight, - u8 type, u32 fib_table, u8 is_encap, u16 plugin, - void *ls_plugin_mem) +sr_policy_add (ip6_address_t *bsid, ip6_address_t *segments, + ip6_address_t *encap_src, u32 weight, u8 type, u32 fib_table, + u8 is_encap, u16 plugin, void *ls_plugin_mem) { ip6_sr_main_t *sm = &sr_main; ip6_sr_policy_t *sr_policy = 0; @@ -726,7 +737,7 @@ sr_policy_add (ip6_address_t *bsid, ip6_address_t *segments, u32 weight, NULL); /* Create a segment list and add the index to the SR policy */ - create_sl (sr_policy, segments, weight, is_encap); + create_sl (sr_policy, segments, encap_src, weight, is_encap); /* If FIB doesnt exist, create them */ if (sm->fib_table_ip6 == (u32) ~ 0) @@ -856,6 +867,7 @@ sr_policy_del (ip6_address_t * bsid, u32 index) * @param fib_table is the VRF where to install the FIB entry for the BSID * @param operation is the operation to perform (among the top ones) * @param segments is a vector of IPv6 address composing the segment list + * @param encap_src is a encaps IPv6 source addr. optional. * @param sl_index is the index of the Segment List to modify/delete * @param weight is the weight of the sid list. optional. * @param is_encap Mode. Encapsulation or SRH insertion. @@ -863,8 +875,8 @@ sr_policy_del (ip6_address_t * bsid, u32 index) * @return 0 if correct, else error */ int -sr_policy_mod (ip6_address_t * bsid, u32 index, u32 fib_table, - u8 operation, ip6_address_t * segments, u32 sl_index, +sr_policy_mod (ip6_address_t *bsid, u32 index, u32 fib_table, u8 operation, + ip6_address_t *segments, ip6_address_t *encap_src, u32 sl_index, u32 weight) { ip6_sr_main_t *sm = &sr_main; @@ -889,8 +901,8 @@ sr_policy_mod (ip6_address_t * bsid, u32 index, u32 fib_table, if (operation == 1) /* Add SR List to an existing SR policy */ { /* Create the new SL */ - segment_list = - create_sl (sr_policy, segments, weight, sr_policy->is_encap); + segment_list = create_sl (sr_policy, segments, encap_src, weight, + sr_policy->is_encap); /* Create a new LB DPO */ if (sr_policy->type == SR_POLICY_TYPE_DEFAULT) @@ -963,7 +975,7 @@ sr_policy_command_fn (vlib_main_t * vm, unformat_input_t * input, int rv = -1; char is_del = 0, is_add = 0, is_mod = 0; char policy_set = 0; - ip6_address_t bsid, next_address; + ip6_address_t bsid, next_address, src_v6addr; u32 sr_policy_index = (u32) ~ 0, sl_index = (u32) ~ 0; u32 weight = (u32) ~ 0, fib_table = (u32) ~ 0; ip6_address_t *segments = 0, *this_seg; @@ -972,6 +984,7 @@ sr_policy_command_fn (vlib_main_t * vm, unformat_input_t * input, u8 type = SR_POLICY_TYPE_DEFAULT; u16 behavior = 0; void *ls_plugin_mem = 0; + ip6_address_t *encap_src = 0; while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) { @@ -995,6 +1008,10 @@ sr_policy_command_fn (vlib_main_t * vm, unformat_input_t * input, clib_memcpy_fast (this_seg->as_u8, next_address.as_u8, sizeof (*this_seg)); } + else if (unformat (input, "v6src %U", unformat_ip6_address, &src_v6addr)) + { + encap_src = &src_v6addr; + } else if (unformat (input, "add sl")) operation = 1; else if (unformat (input, "del sl index %d", &sl_index)) @@ -1059,8 +1076,8 @@ sr_policy_command_fn (vlib_main_t * vm, unformat_input_t * input, if (vec_len (segments) == 0) return clib_error_return (0, "No Segment List specified"); - rv = sr_policy_add (&bsid, segments, weight, type, fib_table, is_encap, - behavior, ls_plugin_mem); + rv = sr_policy_add (&bsid, segments, encap_src, weight, type, fib_table, + is_encap, behavior, ls_plugin_mem); vec_free (segments); } @@ -1078,9 +1095,9 @@ sr_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_policy_mod ((sr_policy_index != (u32) ~ 0 ? NULL : &bsid), + rv = sr_policy_mod ((sr_policy_index != (u32) ~0 ? NULL : &bsid), sr_policy_index, fib_table, operation, segments, - sl_index, weight); + encap_src, sl_index, weight); if (segments) vec_free (segments); @@ -1170,6 +1187,11 @@ show_sr_policies_command_fn (vlib_main_t * vm, unformat_input_t * input, vlib_cli_output (vm, "\tBehavior: %s", (sr_policy->is_encap ? "Encapsulation" : "SRH insertion")); + if (sr_policy->is_encap) + { + vlib_cli_output (vm, "\tEncapSrcIP: %U", format_ip6_address, + &sr_policy->encap_src); + } switch (sr_policy->type) { case SR_POLICY_TYPE_SPRAY: -- cgit 1.2.3-korg