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 <hayatake396@gmail.com>
diff --git a/src/vnet/srv6/sr.api b/src/vnet/srv6/sr.api
index 08ae9fa..8bebcd1 100644
--- a/src/vnet/srv6/sr.api
+++ b/src/vnet/srv6/sr.api
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-option version = "2.0.0";
+option version = "2.1.0";
import "vnet/interface_types.api";
import "vnet/ip/ip_types.api";
@@ -109,6 +109,65 @@
vl_api_srv6_sid_list_t sids;
};
+enum sr_policy_type : u8
+{
+ SR_API_POLICY_TYPE_DEFAULT = 0,
+ SR_API_POLICY_TYPE_SPRAY = 1,
+ SR_API_POLICY_TYPE_TEF = 2,
+};
+
+/** \brief IPv6 SR policy add
+ @param client_index - opaque cookie to identify the sender
+ @param context - sender context, to match reply w/ request
+ @param bsid is the bindingSID of the SR Policy
+ @param weight is the weight of the sid list. optional.
+ @param is_encap is the behavior of the SR policy. (0.SRH insert // 1.Encapsulation)
+ @param type is the SR policy param. (0.Default // 1.Spray // 2.Tef)
+ @param fib_table is the VRF where to install the FIB entry for the BSID
+ @param sids is a srv6_sid_list object
+ @param encap_src is a encaps IPv6 source addr. optional.
+*/
+autoreply define sr_policy_add_v2
+{
+ u32 client_index;
+ u32 context;
+ vl_api_ip6_address_t bsid_addr;
+ u32 weight;
+ bool is_encap;
+ vl_api_sr_policy_type_t type [default=0x0];
+ u32 fib_table;
+ vl_api_srv6_sid_list_t sids;
+ vl_api_ip6_address_t encap_src;
+ option status="in_progress";
+};
+
+/** \brief IPv6 SR policy modification
+ @param client_index - opaque cookie to identify the sender
+ @param context - sender context, to match reply w/ request
+ @param bsid is the bindingSID of the SR Policy
+ @param sr_policy_index is the index of the SR policy
+ @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 sl_index is the index of the Segment List to modify/delete
+ @param weight is the weight of the sid list. optional.
+ @param sids is a srv6_sid_list object
+ @param encap_src is a encaps IPv6 source addr. optional.
+*/
+autoreply define sr_policy_mod_v2
+{
+ u32 client_index;
+ u32 context;
+ vl_api_ip6_address_t bsid_addr;
+ u32 sr_policy_index;
+ u32 fib_table;
+ vl_api_sr_policy_op_t operation;
+ u32 sl_index;
+ u32 weight;
+ vl_api_srv6_sid_list_t sids;
+ vl_api_ip6_address_t encap_src;
+ option status="in_progress";
+};
+
/** \brief IPv6 SR policy deletion
@param client_index - opaque cookie to identify the sender
@param context - sender context, to match reply w/ request
@@ -248,6 +307,29 @@
vl_api_srv6_sid_list_t sid_lists[num_sid_lists];
};
+/** \brief Dump the list of SR policies v2
+ @param client_index - opaque cookie to identify the sender
+ @param context - sender context, to match reply w/ request
+*/
+define sr_policies_v2_dump
+{
+ u32 client_index;
+ u32 context;
+};
+
+define sr_policies_v2_details
+{
+ u32 context;
+ vl_api_ip6_address_t bsid;
+ vl_api_ip6_address_t encap_src;
+ vl_api_sr_policy_type_t type;
+ bool is_encap;
+ u32 fib_table;
+ u8 num_sid_lists;
+ vl_api_srv6_sid_list_t sid_lists[num_sid_lists];
+ option in_progress;
+};
+
/** \brief Dump the list of SR policies along with actual segment list index on VPP
@param client_index - opaque cookie to identify the sender
@param context - sender context, to match reply w/ request
diff --git a/src/vnet/srv6/sr.h b/src/vnet/srv6/sr.h
index 02ccead..7d8aa73 100644
--- a/src/vnet/srv6/sr.h
+++ b/src/vnet/srv6/sr.h
@@ -112,6 +112,8 @@
u8 is_encap; /**< Mode (0 is SRH insert, 1 Encaps) */
+ ip6_address_t encap_src;
+
u16 plugin;
void *plugin_mem;
} ip6_sr_policy_t;
@@ -345,11 +347,12 @@
sr_p_plugin_callback_t * removal_fn);
extern 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 *plugin_mem);
-extern int sr_policy_mod (ip6_address_t * bsid, u32 index, u32 fib_table,
- u8 operation, ip6_address_t * segments,
- u32 sl_index, u32 weight);
+ ip6_address_t *encap_src, u32 weight, u8 type,
+ u32 fib_table, u8 is_encap, u16 plugin,
+ void *plugin_mem);
+extern int 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);
extern int sr_policy_del (ip6_address_t * bsid, u32 index);
extern int
diff --git a/src/vnet/srv6/sr_api.c b/src/vnet/srv6/sr_api.c
index 1b95125..5594fed 100644
--- a/src/vnet/srv6/sr_api.c
+++ b/src/vnet/srv6/sr_api.c
@@ -82,17 +82,16 @@
ip6_address_decode (mp->bsid_addr, &bsid_addr);
-/*
- * sr_policy_add (ip6_address_t *bsid, ip6_address_t *segments,
- * u32 weight, u8 behavior, u32 fib_table, u8 is_encap,
- * u16 behavior, void *plugin_mem)
- */
+ /*
+ * sr_policy_add (ip6_address_t *bsid, ip6_address_t *segments,
+ * ip6_address_t *encap_src,
+ * u32 weight, u8 behavior, u32 fib_table, u8 is_encap,
+ * u16 behavior, void *plugin_mem)
+ */
int rv = 0;
- rv = sr_policy_add (&bsid_addr,
- segments,
- ntohl (mp->sids.weight),
- mp->is_spray, ntohl (mp->fib_table), mp->is_encap, 0,
- NULL);
+ rv =
+ sr_policy_add (&bsid_addr, segments, NULL, ntohl (mp->sids.weight),
+ mp->is_spray, ntohl (mp->fib_table), mp->is_encap, 0, NULL);
vec_free (segments);
REPLY_MACRO (VL_API_SR_POLICY_ADD_REPLY);
@@ -115,18 +114,93 @@
ip6_address_decode (mp->bsid_addr, &bsid_addr);
int rv = 0;
-/*
- * int
- * sr_policy_mod(ip6_address_t *bsid, u32 index, u32 fib_table,
- * u8 operation, ip6_address_t *segments, u32 sl_index,
- * u32 weight, u8 is_encap)
- */
- rv = sr_policy_mod (&bsid_addr,
- ntohl (mp->sr_policy_index),
- ntohl (mp->fib_table),
- mp->operation,
- segments, ntohl (mp->sl_index),
- ntohl (mp->sids.weight));
+ /*
+ * int
+ * 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, u8 is_encap)
+ */
+ rv = sr_policy_mod (&bsid_addr, ntohl (mp->sr_policy_index),
+ ntohl (mp->fib_table), mp->operation, segments, NULL,
+ ntohl (mp->sl_index), ntohl (mp->sids.weight));
+ vec_free (segments);
+
+ REPLY_MACRO (VL_API_SR_POLICY_MOD_REPLY);
+}
+
+static void
+vl_api_sr_policy_add_v2_t_handler (vl_api_sr_policy_add_v2_t *mp)
+{
+ vl_api_sr_policy_add_v2_reply_t *rmp;
+ ip6_address_t *segments = 0, *seg;
+ ip6_address_t bsid_addr;
+ ip6_address_t encap_src;
+
+ int i;
+ for (i = 0; i < mp->sids.num_sids; i++)
+ {
+ vec_add2 (segments, seg, 1);
+ ip6_address_decode (mp->sids.sids[i], seg);
+ }
+
+ ip6_address_decode (mp->bsid_addr, &bsid_addr);
+ ip6_address_decode (mp->encap_src, &encap_src);
+
+ if (ip6_address_is_zero (&encap_src))
+ {
+ encap_src = *sr_get_encaps_source ();
+ }
+ /*
+ * sr_policy_add (ip6_address_t *bsid, ip6_address_t *segments,
+ * ip6_address_t *encap_src,
+ * u32 weight, u8 behavior, u32 fib_table, u8 is_encap,
+ * u16 behavior, void *plugin_mem)
+ */
+ int rv = 0;
+ rv =
+ sr_policy_add (&bsid_addr, segments, &encap_src, ntohl (mp->sids.weight),
+ mp->type, ntohl (mp->fib_table), mp->is_encap, 0, NULL);
+ vec_free (segments);
+
+ REPLY_MACRO (VL_API_SR_POLICY_ADD_REPLY);
+}
+
+static void
+vl_api_sr_policy_mod_v2_t_handler (vl_api_sr_policy_mod_v2_t *mp)
+{
+ vl_api_sr_policy_mod_v2_reply_t *rmp;
+ ip6_address_t *segments = 0, *seg;
+ ip6_address_t bsid_addr;
+ ip6_address_t encap_src;
+
+ int i;
+ for (i = 0; i < mp->sids.num_sids; i++)
+ {
+ vec_add2 (segments, seg, 1);
+ ip6_address_decode (mp->sids.sids[i], seg);
+ }
+
+ ip6_address_decode (mp->bsid_addr, &bsid_addr);
+ ip6_address_decode (mp->encap_src, &encap_src);
+
+ if (ip6_address_is_zero (&encap_src))
+ {
+ encap_src = *sr_get_encaps_source ();
+ }
+
+ int rv = 0;
+ /*
+ * int
+ * 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, u8 is_encap)
+ */
+ rv =
+ sr_policy_mod (&bsid_addr, ntohl (mp->sr_policy_index),
+ ntohl (mp->fib_table), mp->operation, segments, &encap_src,
+ ntohl (mp->sl_index), ntohl (mp->sids.weight));
vec_free (segments);
REPLY_MACRO (VL_API_SR_POLICY_MOD_REPLY);
@@ -387,7 +461,68 @@
/* *INDENT-ON* */
}
+static void
+send_sr_policies_v2_details (ip6_sr_policy_t *t, vl_api_registration_t *reg,
+ u32 context)
+{
+ vl_api_sr_policies_v2_details_t *rmp;
+ ip6_sr_main_t *sm = &sr_main;
+ u32 *sl_index, slidx = 0;
+ ip6_sr_sl_t *segment_list = 0;
+ ip6_address_t *segment;
+ vl_api_srv6_sid_list_t *api_sid_list;
+
+ rmp = vl_msg_api_alloc (sizeof (*rmp) + vec_len (t->segments_lists) *
+ sizeof (vl_api_srv6_sid_list_t));
+ clib_memset (rmp, 0,
+ (sizeof (*rmp) + vec_len (t->segments_lists) *
+ sizeof (vl_api_srv6_sid_list_t)));
+
+ rmp->_vl_msg_id = ntohs (REPLY_MSG_ID_BASE + VL_API_SR_POLICIES_V2_DETAILS);
+ ip6_address_encode (&t->bsid, rmp->bsid);
+ ip6_address_encode (&t->encap_src, rmp->encap_src);
+ rmp->is_encap = t->is_encap;
+ rmp->type = t->type;
+ rmp->fib_table = htonl (t->fib_table);
+ rmp->num_sid_lists = vec_len (t->segments_lists);
+
+ /* Fill in all the segments lists */
+ vec_foreach (sl_index, t->segments_lists)
+ {
+ segment_list = pool_elt_at_index (sm->sid_lists, *sl_index);
+
+ api_sid_list = &rmp->sid_lists[sl_index - t->segments_lists];
+
+ api_sid_list->num_sids = vec_len (segment_list->segments);
+ api_sid_list->weight = htonl (segment_list->weight);
+ slidx = 0;
+ vec_foreach (segment, segment_list->segments)
+ {
+ ip6_address_encode (segment, api_sid_list->sids[slidx++]);
+ }
+ }
+
+ rmp->context = context;
+ vl_api_send_msg (reg, (u8 *) rmp);
+}
+
+static void
+vl_api_sr_policies_v2_dump_t_handler (vl_api_sr_policies_v2_dump_t *mp)
+{
+ vl_api_registration_t *reg;
+ ip6_sr_main_t *sm = &sr_main;
+ ip6_sr_policy_t *t;
+
+ reg = vl_api_client_index_to_registration (mp->client_index);
+ if (!reg)
+ return;
+
+ pool_foreach (t, sm->sr_policies)
+ {
+ send_sr_policies_v2_details (t, reg, mp->context);
+ }
+}
static void send_sr_policies_details_with_sl_index
(ip6_sr_policy_t * t, vl_api_registration_t * reg, u32 context)
diff --git a/src/vnet/srv6/sr_policy_rewrite.c b/src/vnet/srv6/sr_policy_rewrite.c
index 8ad8571..69a4d5e 100644
--- a/src/vnet/srv6/sr_policy_rewrite.c
+++ b/src/vnet/srv6/sr_policy_rewrite.c
@@ -193,11 +193,12 @@
* @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 @@
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 @@
*
* @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 @@
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 @@
*
* @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 @@
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 @@
* @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 @@
* @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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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:
diff --git a/src/vnet/srv6/sr_test.c b/src/vnet/srv6/sr_test.c
index 85f64e1..be89859 100644
--- a/src/vnet/srv6/sr_test.c
+++ b/src/vnet/srv6/sr_test.c
@@ -80,6 +80,18 @@
}
static int
+api_sr_policy_mod_v2 (vat_main_t *vam)
+{
+ return -1;
+}
+
+static int
+api_sr_policy_add_v2 (vat_main_t *vam)
+{
+ return -1;
+}
+
+static int
api_sr_localsids_dump (vat_main_t *vam)
{
return -1;
@@ -92,6 +104,12 @@
}
static int
+api_sr_policies_v2_dump (vat_main_t *vam)
+{
+ return -1;
+}
+
+static int
api_sr_policies_with_sl_index_dump (vat_main_t *vam)
{
return -1;
@@ -109,6 +127,11 @@
}
static void
+vl_api_sr_policies_v2_details_t_handler (vl_api_sr_policies_v2_details_t *mp)
+{
+}
+
+static void
vl_api_sr_localsids_details_t_handler (vl_api_sr_localsids_details_t *mp)
{
}