diff --git a/src/plugins/srv6-mobile/CMakeLists.txt b/src/plugins/srv6-mobile/CMakeLists.txt index 5a9945c2e4f..a917c8ded82 100644 --- a/src/plugins/srv6-mobile/CMakeLists.txt +++ b/src/plugins/srv6-mobile/CMakeLists.txt @@ -21,6 +21,11 @@ add_vpp_plugin(srv6mobile gtp6_d_di.c gtp6_dt.c node.c + sr_mobile_api.c + + API_FILES + sr_mobile.api + sr_mobile_types.api INSTALL_HEADERS mobile.h diff --git a/src/plugins/srv6-mobile/gtp4_d.c b/src/plugins/srv6-mobile/gtp4_d.c index 269902429d3..d5a5a6a567a 100644 --- a/src/plugins/srv6-mobile/gtp4_d.c +++ b/src/plugins/srv6-mobile/gtp4_d.c @@ -105,11 +105,33 @@ clb_format_srv6_t_m_gtp4_d (u8 * s, va_list * args) return s; } +void +alloc_param_srv6_t_m_gtp4_d (void **plugin_mem_p, const void *v6src_prefix, + const u32 v6src_prefixlen, const void *sr_prefix, + const u32 sr_prefixlen, const u32 fib_index, + const u8 nhtype, const bool drop_in) +{ + srv6_end_gtp4_d_param_t *ls_mem; + ls_mem = clib_mem_alloc (sizeof *ls_mem); + clib_memset (ls_mem, 0, sizeof *ls_mem); + *plugin_mem_p = ls_mem; + + ls_mem->v6src_prefixlen = v6src_prefixlen; + memcpy (&ls_mem->v6src_prefix, v6src_prefix, sizeof (ip6_address_t)); + ls_mem->sr_prefixlen = sr_prefixlen; + memcpy (&ls_mem->sr_prefix, sr_prefix, sizeof (ip6_address_t)); + + ls_mem->nhtype = nhtype; + ls_mem->drop_in = drop_in; + ls_mem->fib_table = fib_index; + ls_mem->fib4_index = ip4_fib_index_from_table_id (fib_index); + ls_mem->fib6_index = ip6_fib_index_from_table_id (fib_index); +} + static uword clb_unformat_srv6_t_m_gtp4_d (unformat_input_t * input, va_list * args) { void **plugin_mem_p = va_arg (*args, void **); - srv6_end_gtp4_d_param_t *ls_mem; ip6_address_t sr_prefix; u32 sr_prefixlen; ip6_address_t v6src_prefix; @@ -172,23 +194,9 @@ clb_unformat_srv6_t_m_gtp4_d (unformat_input_t * input, va_list * args) return 0; } - ls_mem = clib_mem_alloc (sizeof *ls_mem); - clib_memset (ls_mem, 0, sizeof *ls_mem); - *plugin_mem_p = ls_mem; - - ls_mem->sr_prefix = sr_prefix; - ls_mem->sr_prefixlen = sr_prefixlen; - - ls_mem->v6src_prefix = v6src_prefix; - ls_mem->v6src_prefixlen = v6src_prefixlen; - - ls_mem->nhtype = nhtype; - - ls_mem->drop_in = drop_in; - - ls_mem->fib_table = fib_table; - ls_mem->fib4_index = ip4_fib_index_from_table_id (fib_table); - ls_mem->fib6_index = ip6_fib_index_from_table_id (fib_table); + alloc_param_srv6_t_m_gtp4_d (plugin_mem_p, &v6src_prefix, v6src_prefixlen, + &sr_prefix, sr_prefixlen, fib_table, nhtype, + drop_in); return 1; } diff --git a/src/plugins/srv6-mobile/gtp4_dt.c b/src/plugins/srv6-mobile/gtp4_dt.c index 1f6bab1d055..c4752b77557 100644 --- a/src/plugins/srv6-mobile/gtp4_dt.c +++ b/src/plugins/srv6-mobile/gtp4_dt.c @@ -90,11 +90,31 @@ clb_format_srv6_t_m_gtp4_dt (u8 * s, va_list * args) return s; } +void +alloc_param_srv6_t_m_gtp4_dt (void **plugin_mem_p, const u32 fib_index, + const u32 local_fib_index, const u8 type) +{ + srv6_t_gtp4_dt_param_t *ls_mem; + ls_mem = clib_mem_alloc (sizeof *ls_mem); + clib_memset (ls_mem, 0, sizeof *ls_mem); + *plugin_mem_p = ls_mem; + + ls_mem->fib4_index = fib_table_find (FIB_PROTOCOL_IP4, fib_index); + ls_mem->fib6_index = fib_table_find (FIB_PROTOCOL_IP6, fib_index); + + if (type == SRV6_GTP4_DT6 || type == SRV6_GTP4_DT46) + { + ls_mem->local_fib_index = + fib_table_find (FIB_PROTOCOL_IP6, local_fib_index); + } + + ls_mem->type = type; +} + static uword clb_unformat_srv6_t_m_gtp4_dt (unformat_input_t * input, va_list * args) { void **plugin_mem_p = va_arg (*args, void **); - srv6_t_gtp4_dt_param_t *ls_mem; u32 fib_index = 0; u32 local_fib_index = 0; u32 type; @@ -118,20 +138,8 @@ clb_unformat_srv6_t_m_gtp4_dt (unformat_input_t * input, va_list * args) return 0; } - ls_mem = clib_mem_alloc (sizeof *ls_mem); - clib_memset (ls_mem, 0, sizeof *ls_mem); - *plugin_mem_p = ls_mem; - - ls_mem->fib4_index = fib_table_find (FIB_PROTOCOL_IP4, fib_index); - ls_mem->fib6_index = fib_table_find (FIB_PROTOCOL_IP6, fib_index); - - if (type == SRV6_GTP4_DT6 || type == SRV6_GTP4_DT46) - { - ls_mem->local_fib_index = - fib_table_find (FIB_PROTOCOL_IP6, local_fib_index); - } - - ls_mem->type = type; + alloc_param_srv6_t_m_gtp4_dt (plugin_mem_p, fib_index, local_fib_index, + type); return 1; } diff --git a/src/plugins/srv6-mobile/gtp4_e.c b/src/plugins/srv6-mobile/gtp4_e.c index 8efb938cf72..828f924464d 100644 --- a/src/plugins/srv6-mobile/gtp4_e.c +++ b/src/plugins/srv6-mobile/gtp4_e.c @@ -80,11 +80,26 @@ clb_format_srv6_end_m_gtp4_e (u8 * s, va_list * args) return s; } +void +alloc_param_srv6_end_m_gtp4_e (void **plugin_mem_p, const void *v4src_addr, + const u32 v4src_position, const u32 fib_table) +{ + srv6_end_gtp4_e_param_t *ls_mem; + ls_mem = clib_mem_alloc (sizeof *ls_mem); + clib_memset (ls_mem, 0, sizeof *ls_mem); + *plugin_mem_p = ls_mem; + ls_mem->v4src_position = v4src_position; + memcpy (&ls_mem->v4src_addr, v4src_addr, sizeof (ip4_address_t)); + + ls_mem->fib_table = fib_table; + ls_mem->fib4_index = ip4_fib_index_from_table_id (fib_table); + ls_mem->fib6_index = ip6_fib_index_from_table_id (fib_table); +} + static uword clb_unformat_srv6_end_m_gtp4_e (unformat_input_t * input, va_list * args) { void **plugin_mem_p = va_arg (*args, void **); - srv6_end_gtp4_e_param_t *ls_mem; ip4_address_t v4src_addr; u32 v4src_position = 0; u32 fib_table; @@ -113,16 +128,8 @@ clb_unformat_srv6_end_m_gtp4_e (unformat_input_t * input, va_list * args) if (!config) return 0; - ls_mem = clib_mem_alloc (sizeof *ls_mem); - clib_memset (ls_mem, 0, sizeof *ls_mem); - *plugin_mem_p = ls_mem; - - ls_mem->v4src_position = v4src_position; - memcpy (&ls_mem->v4src_addr, &v4src_addr, sizeof (ip4_address_t)); - - ls_mem->fib_table = fib_table; - ls_mem->fib4_index = ip4_fib_index_from_table_id (fib_table); - ls_mem->fib6_index = ip6_fib_index_from_table_id (fib_table); + alloc_param_srv6_end_m_gtp4_e (plugin_mem_p, &v4src_addr, v4src_position, + fib_table); return 1; } diff --git a/src/plugins/srv6-mobile/gtp6_d.c b/src/plugins/srv6-mobile/gtp6_d.c index 79549276c2c..1f5b9ac0d0f 100644 --- a/src/plugins/srv6-mobile/gtp6_d.c +++ b/src/plugins/srv6-mobile/gtp6_d.c @@ -94,11 +94,29 @@ clb_format_srv6_end_m_gtp6_d (u8 * s, va_list * args) return s; } +void +alloc_param_srv6_end_m_gtp6_d (void **plugin_mem_p, const void *sr_prefix, + const u32 sr_prefixlen, const u8 nhtype, + const bool drop_in, const u32 fib_table) +{ + srv6_end_gtp6_d_param_t *ls_mem; + ls_mem = clib_mem_alloc (sizeof *ls_mem); + clib_memset (ls_mem, 0, sizeof *ls_mem); + *plugin_mem_p = ls_mem; + + ls_mem->sr_prefixlen = sr_prefixlen; + memcpy (&ls_mem->sr_prefix, sr_prefix, sizeof (ip6_address_t)); + ls_mem->nhtype = nhtype; + ls_mem->drop_in = drop_in; + ls_mem->fib_table = fib_table; + ls_mem->fib4_index = ip4_fib_index_from_table_id (fib_table); + ls_mem->fib6_index = ip6_fib_index_from_table_id (fib_table); +} + static uword clb_unformat_srv6_end_m_gtp6_d (unformat_input_t * input, va_list * args) { void **plugin_mem_p = va_arg (*args, void **); - srv6_end_gtp6_d_param_t *ls_mem; ip6_address_t sr_prefix; u32 sr_prefixlen; u8 nhtype = SRV6_NHTYPE_NONE; @@ -150,20 +168,8 @@ clb_unformat_srv6_end_m_gtp6_d (unformat_input_t * input, va_list * args) return 0; } - ls_mem = clib_mem_alloc (sizeof *ls_mem); - clib_memset (ls_mem, 0, sizeof *ls_mem); - *plugin_mem_p = ls_mem; - - ls_mem->sr_prefix = sr_prefix; - ls_mem->sr_prefixlen = sr_prefixlen; - - ls_mem->nhtype = nhtype; - - ls_mem->drop_in = drop_in; - - ls_mem->fib_table = fib_table; - ls_mem->fib4_index = ip4_fib_index_from_table_id (fib_table); - ls_mem->fib6_index = ip6_fib_index_from_table_id (fib_table); + alloc_param_srv6_end_m_gtp6_d (plugin_mem_p, &sr_prefix, sr_prefixlen, + nhtype, drop_in, fib_table); return 1; } diff --git a/src/plugins/srv6-mobile/gtp6_d_di.c b/src/plugins/srv6-mobile/gtp6_d_di.c index 601db26aa90..80c0dbcec7c 100644 --- a/src/plugins/srv6-mobile/gtp6_d_di.c +++ b/src/plugins/srv6-mobile/gtp6_d_di.c @@ -91,11 +91,24 @@ clb_format_srv6_end_m_gtp6_d_di (u8 * s, va_list * args) return s; } +void +alloc_param_srv6_end_m_gtp6_di (void **plugin_mem_p, const void *sr_prefix, + const u32 sr_prefixlen, const u8 nhtype) +{ + srv6_end_gtp6_d_param_t *ls_mem; + ls_mem = clib_mem_alloc (sizeof *ls_mem); + clib_memset (ls_mem, 0, sizeof *ls_mem); + *plugin_mem_p = ls_mem; + + ls_mem->sr_prefixlen = sr_prefixlen; + memcpy (&ls_mem->sr_prefix, sr_prefix, sizeof (ip6_address_t)); + ls_mem->nhtype = nhtype; +} + static uword clb_unformat_srv6_end_m_gtp6_d_di (unformat_input_t * input, va_list * args) { void **plugin_mem_p = va_arg (*args, void **); - srv6_end_gtp6_d_param_t *ls_mem; ip6_address_t sr_prefix; u32 sr_prefixlen = 0; u8 nhtype; @@ -125,13 +138,8 @@ clb_unformat_srv6_end_m_gtp6_d_di (unformat_input_t * input, va_list * args) return 0; } - ls_mem = clib_mem_alloc (sizeof *ls_mem); - clib_memset (ls_mem, 0, sizeof *ls_mem); - *plugin_mem_p = ls_mem; - - ls_mem->sr_prefix = sr_prefix; - ls_mem->sr_prefixlen = sr_prefixlen; - ls_mem->nhtype = nhtype; + alloc_param_srv6_end_m_gtp6_di (plugin_mem_p, &sr_prefix, sr_prefixlen, + nhtype); return 1; } diff --git a/src/plugins/srv6-mobile/gtp6_dt.c b/src/plugins/srv6-mobile/gtp6_dt.c index ba8de54bec9..5fc0918621d 100644 --- a/src/plugins/srv6-mobile/gtp6_dt.c +++ b/src/plugins/srv6-mobile/gtp6_dt.c @@ -84,11 +84,31 @@ clb_format_srv6_end_m_gtp6_dt (u8 * s, va_list * args) return s; } +void +alloc_param_srv6_end_m_gtp6_dt (void **plugin_mem_p, const u32 fib_index, + const u32 local_fib_index, const u32 type) +{ + srv6_end_gtp6_dt_param_t *ls_mem; + ls_mem = clib_mem_alloc (sizeof *ls_mem); + clib_memset (ls_mem, 0, sizeof *ls_mem); + *plugin_mem_p = ls_mem; + + ls_mem->fib4_index = fib_table_find (FIB_PROTOCOL_IP4, fib_index); + ls_mem->fib6_index = fib_table_find (FIB_PROTOCOL_IP6, fib_index); + + if (type == SRV6_GTP6_DT6 || type == SRV6_GTP6_DT46) + { + ls_mem->local_fib_index = + fib_table_find (FIB_PROTOCOL_IP6, local_fib_index); + } + + ls_mem->type = type; +} + static uword clb_unformat_srv6_end_m_gtp6_dt (unformat_input_t * input, va_list * args) { void **plugin_mem_p = va_arg (*args, void **); - srv6_end_gtp6_dt_param_t *ls_mem; u32 fib_index = 0; u32 local_fib_index = 0; u32 type; @@ -111,22 +131,8 @@ clb_unformat_srv6_end_m_gtp6_dt (unformat_input_t * input, va_list * args) { return 0; } - - ls_mem = clib_mem_alloc (sizeof *ls_mem); - clib_memset (ls_mem, 0, sizeof *ls_mem); - *plugin_mem_p = ls_mem; - - ls_mem->fib4_index = fib_table_find (FIB_PROTOCOL_IP4, fib_index); - ls_mem->fib6_index = fib_table_find (FIB_PROTOCOL_IP6, fib_index); - - if (type == SRV6_GTP6_DT6 || type == SRV6_GTP6_DT46) - { - ls_mem->local_fib_index = - fib_table_find (FIB_PROTOCOL_IP6, local_fib_index); - } - - ls_mem->type = type; - + alloc_param_srv6_end_m_gtp6_dt (plugin_mem_p, fib_index, local_fib_index, + type); return 1; } diff --git a/src/plugins/srv6-mobile/gtp6_e.c b/src/plugins/srv6-mobile/gtp6_e.c index feaaaf95419..49b1bd1a6d9 100644 --- a/src/plugins/srv6-mobile/gtp6_e.c +++ b/src/plugins/srv6-mobile/gtp6_e.c @@ -76,16 +76,10 @@ clb_format_srv6_end_m_gtp6_e (u8 * s, va_list * args) return s; } -static uword -clb_unformat_srv6_end_m_gtp6_e (unformat_input_t * input, va_list * args) +void +alloc_param_srv6_end_m_gtp6_e (void **plugin_mem_p, const u32 fib_table) { - void **plugin_mem_p = va_arg (*args, void **); srv6_end_gtp6_e_param_t *ls_mem; - u32 fib_table; - - if (!unformat (input, "end.m.gtp6.e fib-table %d", &fib_table)) - return 0; - ls_mem = clib_mem_alloc (sizeof *ls_mem); clib_memset (ls_mem, 0, sizeof *ls_mem); *plugin_mem_p = ls_mem; @@ -93,6 +87,18 @@ clb_unformat_srv6_end_m_gtp6_e (unformat_input_t * input, va_list * args) ls_mem->fib_table = fib_table; ls_mem->fib4_index = ip4_fib_index_from_table_id (fib_table); ls_mem->fib6_index = ip6_fib_index_from_table_id (fib_table); +} + +static uword +clb_unformat_srv6_end_m_gtp6_e (unformat_input_t *input, va_list *args) +{ + void **plugin_mem_p = va_arg (*args, void **); + u32 fib_table; + + if (!unformat (input, "end.m.gtp6.e fib-table %d", &fib_table)) + return 0; + + alloc_param_srv6_end_m_gtp6_e (plugin_mem_p, fib_table); return 1; } diff --git a/src/plugins/srv6-mobile/mobile.h b/src/plugins/srv6-mobile/mobile.h index 5f6064ff10b..921abc90db2 100644 --- a/src/plugins/srv6-mobile/mobile.h +++ b/src/plugins/srv6-mobile/mobile.h @@ -71,6 +71,28 @@ #define GTPU_IE_MAX_SIZ 256 #define SRH_TLV_USER_PLANE_CONTAINER 0x0a /* tentative */ +typedef enum mobile_policy_function_list +{ + SRV6_MOBILE_POLICY_UNKNOWN_FUNCTION = 0, + SRV6_MOBILE_POLICY_T_M_GTP4_D, + SRV6_MOBILE_POLICY_T_M_GTP4_DT4, + SRV6_MOBILE_POLICY_T_M_GTP4_DT6, + SRV6_MOBILE_POLICY_T_M_GTP4_DT46, + SRV6_MOBILE_POLICY_END_M_GTP6_D, +} mobile_policy_function_list_t; + +typedef enum mobile_localsid_function_list +{ + SRV6_MOBILE_LOCALSID_UNKNOWN_FUNCTION = 0, + SRV6_MOBILE_LOCALSID_END_M_GTP4_E, + SRV6_MOBILE_LOCALSID_END_M_GTP6_E, + SRV6_MOBILE_LOCALSID_END_M_GTP6_D, + SRV6_MOBILE_LOCALSID_END_M_GTP6_D_DI, + SRV6_MOBILE_LOCALSID_END_M_GTP6_D_DT4, + SRV6_MOBILE_LOCALSID_END_M_GTP6_D_DT6, + SRV6_MOBILE_LOCALSID_END_M_GTP6_D_DT46, +} mobile_localsid_function_list_t; + /* *INDENT-OFF* */ typedef struct { diff --git a/src/plugins/srv6-mobile/sr_mobile.api b/src/plugins/srv6-mobile/sr_mobile.api new file mode 100644 index 00000000000..1487085a695 --- /dev/null +++ b/src/plugins/srv6-mobile/sr_mobile.api @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2022 BBSakura Networks Inc and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +option version = "0.1.0"; + +import "vnet/interface_types.api"; +import "vnet/ip/ip_types.api"; +import "vnet/srv6/sr_types.api"; +import "vnet/srv6/sr.api"; +import "plugins/srv6-mobile/sr_mobile_types.api"; + +/** \brief IPv6 SR for Mobile LocalSID add/del request + @param client_index - opaque cookie to identify the sender + @param context - sender context, to match reply w/ request + @param is_del - Boolean of whether its a delete instruction + @param localsid_prefix - IPv6 address of the localsid + @param behavior - the behavior of the SR policy. + @param fib_table - FIB table in which we should install the localsid entry + @param local_fib_table - lookup and forward GTP-U packet based on outer IP destination address. optional + @param drop_in - that reconverts to GTPv1 mode. optional + @param nhtype - next-header type. optional. + @param sr_prefix - v6 src ip encoding prefix.optional. + @param v4src_position - bit position where IPv4 src address embedded. optional. +*/ +autoreply define sr_mobile_localsid_add_del +{ + u32 client_index; + u32 context; + bool is_del [default=false]; + vl_api_ip6_prefix_t localsid_prefix; + string behavior[64]; + u32 fib_table; + u32 local_fib_table; + bool drop_in; + vl_api_sr_mobile_nhtype_t nhtype; + vl_api_ip6_prefix_t sr_prefix; + vl_api_ip4_address_t v4src_addr; + u32 v4src_position; +}; + +/** \brief IPv6 SR for Mobile policy add + @param client_index - opaque cookie to identify the sender + @param context - sender context, to match reply w/ request + @param bsid - the bindingSID of the SR Policy + @param sr_prefix - v6 dst ip encoding prefix. optional + @param v6src_position - v6 src prefix. optional + @param behavior - the behavior of the SR policy. + @param fib_table - the VRF where to install the FIB entry for the BSID + @param encap_src is a encaps IPv6 source addr. optional + @param local_fib_table - lookup and forward GTP-U packet based on outer IP destination address. optional + @param drop_in - that reconverts to GTPv1 mode. optional + @param nhtype - next-header type. +*/ +autoreply define sr_mobile_policy_add +{ + u32 client_index; + u32 context; + vl_api_ip6_address_t bsid_addr; + vl_api_ip6_prefix_t sr_prefix; + vl_api_ip6_prefix_t v6src_prefix; + string behavior[64]; + u32 fib_table; + u32 local_fib_table; + vl_api_ip6_address_t encap_src; + bool drop_in; + vl_api_sr_mobile_nhtype_t nhtype; +}; diff --git a/src/plugins/srv6-mobile/sr_mobile_api.c b/src/plugins/srv6-mobile/sr_mobile_api.c new file mode 100644 index 00000000000..51199317a3b --- /dev/null +++ b/src/plugins/srv6-mobile/sr_mobile_api.c @@ -0,0 +1,339 @@ +/* + *------------------------------------------------------------------ + * sr_mobile_api.c - ipv6 segment routing for mobile u-plane api + * + * Copyright (c) 2022 BBSakura Networks Inc and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------ + */ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include + +#include + +u16 msg_id_base; +#define REPLY_MSG_ID_BASE msg_id_base +#include + +static inline uint16_t +sr_plugin_localsid_fn_num_find_by (ip6_sr_main_t *sm, const char *keyword_str, + size_t keyword_len) +{ + sr_localsid_fn_registration_t *plugin = 0, **vec_plugins = 0; + sr_localsid_fn_registration_t **plugin_it = 0; + pool_foreach (plugin, sm->plugin_functions) + { + vec_add1 (vec_plugins, plugin); + } + + vec_foreach (plugin_it, vec_plugins) + { + if (!srv6_mobile_strcmp_with_size (keyword_str, keyword_len, + (char *) (*plugin_it)->keyword_str)) + { + return (*plugin_it)->sr_localsid_function_number; + } + } + return UINT16_MAX; +} + +static inline uint16_t +sr_plugin_policy_fn_num_find_by (ip6_sr_main_t *sm, const char *keyword_str, + size_t keyword_len) +{ + sr_policy_fn_registration_t *plugin = 0, **vec_plugins = 0; + sr_policy_fn_registration_t **plugin_it = 0; + pool_foreach (plugin, sm->policy_plugin_functions) + { + vec_add1 (vec_plugins, plugin); + } + + vec_foreach (plugin_it, vec_plugins) + { + if (!srv6_mobile_strcmp_with_size (keyword_str, keyword_len, + (char *) (*plugin_it)->keyword_str)) + { + return (*plugin_it)->sr_policy_function_number; + } + } + return UINT16_MAX; +} + +static void +vl_api_sr_mobile_localsid_add_del_t_handler ( + vl_api_sr_mobile_localsid_add_del_t *mp) +{ + ip6_sr_main_t *sm = &sr_main; + vl_api_sr_mobile_localsid_add_del_reply_t *rmp; + int rv = 0; + ip6_address_t localsid; + u16 localsid_prefix_len = 128; + void *ls_plugin_mem = 0; + u16 behavior = 0; + u32 dt_type; + size_t behavior_size = 0; + mobile_localsid_function_list_t kind_fn = + SRV6_MOBILE_LOCALSID_UNKNOWN_FUNCTION; + + mp->behavior[sizeof (mp->behavior) - 1] = '\0'; + behavior_size = sizeof (mp->behavior); + // search behavior index + if (mp->behavior[0]) + { + if (!srv6_mobile_strcmp_with_size ((char *) mp->behavior, behavior_size, + "end.m.gtp4.e")) + { + kind_fn = SRV6_MOBILE_LOCALSID_END_M_GTP4_E; + } + else if (!srv6_mobile_strcmp_with_size ((char *) mp->behavior, + behavior_size, "end.m.gtp6.e")) + { + kind_fn = SRV6_MOBILE_LOCALSID_END_M_GTP6_E; + } + else if (!srv6_mobile_strcmp_with_size ((char *) mp->behavior, + behavior_size, "end.m.gtp6.d")) + { + kind_fn = SRV6_MOBILE_LOCALSID_END_M_GTP6_D; + } + else if (!srv6_mobile_strcmp_with_size ( + (char *) mp->behavior, behavior_size, "end.m.gtp6.d.di")) + { + kind_fn = SRV6_MOBILE_LOCALSID_END_M_GTP6_D_DI; + } + else if (!srv6_mobile_strcmp_with_size ( + (char *) mp->behavior, behavior_size, "end.m.gtp6.d.dt4")) + { + kind_fn = SRV6_MOBILE_LOCALSID_END_M_GTP6_D_DT4; + dt_type = SRV6_GTP6_DT4; + } + else if (!srv6_mobile_strcmp_with_size ( + (char *) mp->behavior, behavior_size, "end.m.gtp6.d.dt6")) + { + kind_fn = SRV6_MOBILE_LOCALSID_END_M_GTP6_D_DT6; + dt_type = SRV6_GTP6_DT6; + } + else if (!srv6_mobile_strcmp_with_size ( + (char *) mp->behavior, behavior_size, "end.m.gtp6.d.dt46")) + { + kind_fn = SRV6_MOBILE_LOCALSID_END_M_GTP6_D_DT46; + dt_type = SRV6_GTP6_DT46; + } + else + { + return; + } + switch (kind_fn) + { + case SRV6_MOBILE_LOCALSID_END_M_GTP4_E: + alloc_param_srv6_end_m_gtp4_e (&ls_plugin_mem, &mp->v4src_addr, + ntohl (mp->v4src_position), + ntohl (mp->fib_table)); + break; + case SRV6_MOBILE_LOCALSID_END_M_GTP6_E: + alloc_param_srv6_end_m_gtp6_e (&ls_plugin_mem, + ntohl (mp->fib_table)); + break; + case SRV6_MOBILE_LOCALSID_END_M_GTP6_D: + alloc_param_srv6_end_m_gtp6_d ( + &ls_plugin_mem, &mp->sr_prefix.address, mp->sr_prefix.len, + (u8) ntohl (mp->nhtype), mp->drop_in, ntohl (mp->fib_table)); + break; + case SRV6_MOBILE_LOCALSID_END_M_GTP6_D_DI: + alloc_param_srv6_end_m_gtp6_di ( + &ls_plugin_mem, &mp->sr_prefix.address, mp->sr_prefix.len, + (u8) ntohl (mp->nhtype)); + break; + case SRV6_MOBILE_LOCALSID_END_M_GTP6_D_DT4: + case SRV6_MOBILE_LOCALSID_END_M_GTP6_D_DT6: + case SRV6_MOBILE_LOCALSID_END_M_GTP6_D_DT46: + alloc_param_srv6_end_m_gtp6_dt ( + &ls_plugin_mem, ntohl (mp->fib_table), ntohl (mp->local_fib_table), + dt_type); + break; + case SRV6_MOBILE_LOCALSID_UNKNOWN_FUNCTION: + default: + return; // error + } + behavior = sr_plugin_localsid_fn_num_find_by (sm, (char *) mp->behavior, + behavior_size); + if (behavior == UINT16_MAX) + return; + } + else + { + return; + } + ip6_address_decode (mp->localsid_prefix.address, &localsid); + localsid_prefix_len = mp->localsid_prefix.len; + + rv = sr_cli_localsid (mp->is_del, &localsid, localsid_prefix_len, + 0, // ignore end_psp + behavior, + 0, // ignore sw_if_index + 0, // ignore vlan_index + ntohl (mp->fib_table), + NULL, // ignore nh_addr + 0, // ignore usid_len + ls_plugin_mem); + + REPLY_MACRO (VL_API_SR_MOBILE_LOCALSID_ADD_DEL_REPLY); +} + +static void +vl_api_sr_mobile_policy_add_t_handler (vl_api_sr_mobile_policy_add_t *mp) +{ + ip6_sr_main_t *sm = &sr_main; + vl_api_sr_mobile_policy_add_reply_t *rmp; + ip6_address_t bsid_addr; + ip6_address_t encap_src; + void *ls_plugin_mem = 0; + u16 behavior = 0; + size_t behavior_size = 0; + + u32 dt_type; + mobile_policy_function_list_t kind_fn = SRV6_MOBILE_POLICY_UNKNOWN_FUNCTION; + + 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 (); + } + mp->behavior[sizeof (mp->behavior) - 1] = '\0'; + behavior_size = sizeof (mp->behavior); + + // search behavior index + if (mp->behavior[0]) + { + if (!srv6_mobile_strcmp_with_size ((char *) mp->behavior, behavior_size, + "t.m.gtp4.d")) + { + kind_fn = SRV6_MOBILE_POLICY_T_M_GTP4_D; + } + else if (!srv6_mobile_strcmp_with_size ((char *) mp->behavior, + behavior_size, "t.m.gtp4.dt4")) + { + kind_fn = SRV6_MOBILE_POLICY_T_M_GTP4_DT4; + dt_type = SRV6_GTP4_DT4; + } + else if (!srv6_mobile_strcmp_with_size ((char *) mp->behavior, + behavior_size, "t.m.gtp4.dt6")) + { + kind_fn = SRV6_MOBILE_POLICY_T_M_GTP4_DT6; + dt_type = SRV6_GTP4_DT6; + } + else if (!srv6_mobile_strcmp_with_size ((char *) mp->behavior, + behavior_size, "t.m.gtp4.dt46")) + { + kind_fn = SRV6_MOBILE_POLICY_T_M_GTP4_DT46; + dt_type = SRV6_GTP4_DT46; + } + else if (!srv6_mobile_strcmp_with_size ((char *) mp->behavior, + behavior_size, "end.m.gtp6.d")) + { + kind_fn = SRV6_MOBILE_POLICY_END_M_GTP6_D; + } + else + { + return; + } + + switch (kind_fn) + { + case SRV6_MOBILE_POLICY_T_M_GTP4_D: + alloc_param_srv6_t_m_gtp4_d ( + &ls_plugin_mem, &mp->v6src_prefix.address, mp->v6src_prefix.len, + &mp->sr_prefix.address, mp->sr_prefix.len, ntohl (mp->fib_table), + mp->nhtype, mp->drop_in); + break; + case SRV6_MOBILE_POLICY_END_M_GTP6_D: + alloc_param_srv6_end_m_gtp6_d ( + &ls_plugin_mem, &mp->sr_prefix.address, mp->sr_prefix.len, + mp->nhtype, mp->drop_in, ntohl (mp->fib_table)); + break; + case SRV6_MOBILE_POLICY_T_M_GTP4_DT4: + case SRV6_MOBILE_POLICY_T_M_GTP4_DT6: + case SRV6_MOBILE_POLICY_T_M_GTP4_DT46: + alloc_param_srv6_t_m_gtp4_dt (&ls_plugin_mem, ntohl (mp->fib_table), + ntohl (mp->local_fib_table), dt_type); + break; + case SRV6_MOBILE_POLICY_UNKNOWN_FUNCTION: + default: + return; // error + } + + behavior = sr_plugin_policy_fn_num_find_by (sm, (char *) mp->behavior, + behavior_size); + if (behavior == UINT16_MAX) + return; + } + else + { + return; + } + + int rv = 0; + ip6_address_t *segments = 0, *this_seg; + vec_add2 (segments, this_seg, 1); + clib_memset (this_seg, 0, sizeof (*this_seg)); + + rv = sr_policy_add (&bsid_addr, + segments, // ignore segments + &encap_src, + (u32) ~0, // ignore weight + SR_POLICY_TYPE_DEFAULT, // ignore type + (u32) ~0, // ignore fib_table + 1, // ignore is_encap, + behavior, ls_plugin_mem); + vec_free (segments); + REPLY_MACRO (VL_API_SR_MOBILE_POLICY_ADD_REPLY); +} + +#include +static clib_error_t * +sr_mobile_api_hookup (vlib_main_t *vm) +{ + /* + * Set up the (msg_name, crc, message-id) table + */ + REPLY_MSG_ID_BASE = setup_message_id_table (); + + return 0; +} + +VLIB_API_INIT_FUNCTION (sr_mobile_api_hookup); +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: + * eval: (c-set-style "gnu") + * End: + */ diff --git a/src/plugins/srv6-mobile/sr_mobile_api.h b/src/plugins/srv6-mobile/sr_mobile_api.h new file mode 100644 index 00000000000..28979b1875c --- /dev/null +++ b/src/plugins/srv6-mobile/sr_mobile_api.h @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2022 BBSakura Networks Inc and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @file + * @brief Segment Routing for mobile u-plane api + * + */ + +#ifndef included_sr_mobile_api_h +#define included_sr_mobile_api_h +#include +#include +#include + +#define srv6_mobile_strcmp_with_size(s1, s1len, s2) \ + ({ \ + int __indicator = 0; \ + strcmp_s_inline (s1, s1len, s2, &__indicator); \ + __indicator; \ + }) + +void alloc_param_srv6_end_m_gtp4_e (void **plugin_mem_p, + const void *v4src_addr, + const u32 v4src_position, + const u32 fib_table); + +void alloc_param_srv6_end_m_gtp6_e (void **plugin_mem_p, const u32 fib_table); + +void alloc_param_srv6_end_m_gtp6_d (void **plugin_mem_p, const void *sr_prefix, + const u32 sr_prefixlen, const u8 nhtype, + const bool drop_in, const u32 fib_table); + +void alloc_param_srv6_end_m_gtp6_di (void **plugin_mem_p, + const void *sr_prefix, + const u32 sr_prefixlen, const u8 nhtype); + +void alloc_param_srv6_end_m_gtp6_dt (void **plugin_mem_p, const u32 fib_index, + const u32 local_fib_index, + const u32 type); + +void alloc_param_srv6_t_m_gtp4_d (void **plugin_mem_p, + const void *v6src_prefix, + const u32 v6src_prefixlen, + const void *sr_prefix, + const u32 sr_prefixlen, const u32 fib_index, + const u8 nhtype, const bool drop_in); + +void alloc_param_srv6_t_m_gtp4_dt (void **plugin_mem_p, const u32 fib_index, + const u32 local_fib_index, const u8 type); + +#endif /* included_sr_mobile_api_h */ + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: + * eval: (c-set-style "gnu") + * End: + */ diff --git a/src/plugins/srv6-mobile/sr_mobile_types.api b/src/plugins/srv6-mobile/sr_mobile_types.api new file mode 100644 index 00000000000..f2dbe302d00 --- /dev/null +++ b/src/plugins/srv6-mobile/sr_mobile_types.api @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2022 BBSakura Networks Inc and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +option version = "0.1.0"; + +enum sr_mobile_nhtype : u8 +{ + SRV6_NHTYPE_API_NONE = 0, + SRV6_NHTYPE_API_IPV4 = 1, + SRV6_NHTYPE_API_IPV6 = 2, + SRV6_NHTYPE_API_NON_IP = 3, +}; \ No newline at end of file diff --git a/test/test_srv6_mobile.py b/test/test_srv6_mobile.py index 89ab7a9c9fa..9d39f194015 100644 --- a/test/test_srv6_mobile.py +++ b/test/test_srv6_mobile.py @@ -3,6 +3,14 @@ from framework import VppTestCase from ipaddress import IPv4Address from ipaddress import IPv6Address +from vpp_ip_route import VppIpRoute, VppRoutePath, FibPathProto, VppIpTable + +from vpp_srv6_mobile import ( + SRv6MobileNhtype, + VppSRv6MobilePolicy, + VppSRv6MobileLocalSID, +) + from scapy.contrib.gtp import * from scapy.all import * @@ -67,10 +75,19 @@ class TestSRv6EndMGTP4E(VppTestCase): """test_srv6_mobile""" pkts = self.create_packets([("A::1", "B::1"), ("C::1", "D::1")]) - self.vapi.cli( - "sr localsid address {} behavior end.m.gtp4.e ".format(pkts[0]["IPv6"].dst) - + "v4src_position 64 fib-table 0" + # "sr localsid address {} behavior end.m.gtp4.e v4src_position 64 fib-table 0" + # ".format(pkts[0]["IPv6"].dst) + localsid = VppSRv6MobileLocalSID( + self, + # address params case is length 0 + localsid_prefix="{}/{}".format(pkts[0]["IPv6"].dst, 0), + behavior="end.m.gtp4.e", + v4src_position=64, + fib_table=0, ) + localsid.add_vpp_config() + + # log the localsids self.logger.info(self.vapi.cli("show sr localsid")) self.vapi.cli("clear errors") @@ -150,13 +167,28 @@ class TestSRv6TMGTP4D(VppTestCase): self.vapi.cli("set sr encaps source addr A1::1") self.vapi.cli("sr policy add bsid D4:: next D2:: next D3::") - self.vapi.cli( - "sr policy add bsid D5:: behavior t.m.gtp4.d D4::/32 " - + "v6src_prefix C1::/64 nhtype ipv6 fib-table 0 drop-in" - ) - self.vapi.cli("sr steer l3 {}/32 via bsid D5::".format(self.ip4_dst)) - self.vapi.cli("ip route add D2::/32 via {}".format(self.ip6_dst)) + # sr policy add bsid D5:: behavior t.m.gtp4.d D4::/32 v6src_prefix C1::/64 nhtype ipv6 fib-table 0 drop-in + policy = VppSRv6MobilePolicy( + self, + bsid_addr="D5::", + behavior="t.m.gtp4.d", + sr_prefix="{}/{}".format("D4::", 32), + v6src_prefix="{}/{}".format("C1::", 64), + nhtype=SRv6MobileNhtype.SRV6_NHTYPE_API_IPV6, + fib_table=0, + drop_in=1, + ) + policy.add_vpp_config() + + self.vapi.cli("sr steer l3 {}/32 via bsid D5::".format(self.ip4_dst)) + + # "ip route add D2::/32 via {}".format(self.ip6_dst) + route = VppIpRoute( + self, "D2::", 32, [VppRoutePath(self.ip6_dst, self.pg1.sw_if_index)] + ) + route.add_vpp_config() + self.logger.info(self.vapi.cli("show ip6 fib")) self.logger.info(self.vapi.cli("show sr steer")) self.logger.info(self.vapi.cli("show sr policies")) @@ -239,12 +271,21 @@ class TestSRv6EndMGTP6E(VppTestCase): """test_srv6_mobile""" pkts = self.create_packets([("A::1", "B::1"), ("C::1", "D::1")]) - self.vapi.cli( - "sr localsid prefix {}/64 behavior end.m.gtp6.e fib-table 0".format( - pkts[0]["IPv6"].dst - ) + # "sr localsid prefix {}/64 behavior end.m.gtp6.e fib-table 0" + # .format(pkts[0]["IPv6"].dst) + localsid = VppSRv6MobileLocalSID( + self, + localsid_prefix="{}/{}".format(pkts[0]["IPv6"].dst, 64), + behavior="end.m.gtp6.e", + fib_table=0, ) - self.vapi.cli("ip route add a1::/64 via {}".format(self.ip6_nhop)) + localsid.add_vpp_config() + + # "ip route add a1::/64 via {}".format(self.ip6_nhop) + route = VppIpRoute( + self, "a1::", 64, [VppRoutePath(self.ip6_nhop, self.pg1.sw_if_index)] + ) + route.add_vpp_config() self.logger.info(self.vapi.cli("show sr localsid")) self.vapi.cli("clear errors") @@ -321,12 +362,25 @@ class TestSRv6EndMGTP6D(VppTestCase): self.vapi.cli("set sr encaps source addr A1::1") self.vapi.cli("sr policy add bsid D4:: next D2:: next D3::") - self.vapi.cli( - "sr localsid prefix 2001::/64 behavior end.m.gtp6.d " - + "D4::/64 fib-table 0 drop-in" - ) - self.vapi.cli("ip route add D2::/64 via {}".format(self.ip6_nhop)) + # "sr localsid prefix 2001::/64 behavior end.m.gtp6.d 4::/64 fib-table 0 drop-in" + # .format(self.ip6_nhop) + localsid = VppSRv6MobileLocalSID( + self, + localsid_prefix="{}/{}".format("2001::", 64), + behavior="end.m.gtp6.d", + fib_table=0, + drop_in=1, + sr_prefix="{}/{}".format("D4::", 64), + ) + localsid.add_vpp_config() + + # "ip route add D2::/64 via {}" + # .format(self.ip6_nhop)) + route = VppIpRoute( + self, "D2::", 64, [VppRoutePath(self.ip6_nhop, self.pg1.sw_if_index)] + ) + route.add_vpp_config() self.logger.info(self.vapi.cli("show sr policies")) self.logger.info(self.vapi.cli("show sr localsid")) diff --git a/test/vpp_srv6_mobile.py b/test/vpp_srv6_mobile.py new file mode 100644 index 00000000000..33b6a6905ec --- /dev/null +++ b/test/vpp_srv6_mobile.py @@ -0,0 +1,136 @@ +from vpp_object import VppObject +from socket import inet_pton, inet_ntop, AF_INET, AF_INET6 + + +class SRv6MobileNhtype: + SRV6_NHTYPE_API_NONE = 0 + SRV6_NHTYPE_API_IPV4 = 1 + SRV6_NHTYPE_API_IPV6 = 2 + SRV6_NHTYPE_API_NON_IP = 3 + + +class VppSRv6MobileLocalSID(VppObject): + """ + SRv6 LocalSID + """ + + def __init__( + self, + test, + localsid_prefix, + behavior, + fib_table=0, + local_fib_table=0, + drop_in=0, + nhtype=SRv6MobileNhtype.SRV6_NHTYPE_API_NONE, + sr_prefix="", + v4src_addr="", + v4src_position=0, + ): + self._test = test + self.localsid_prefix = localsid_prefix + self.behavior = behavior + self.fib_table = fib_table + self.local_fib_table = local_fib_table + self.drop_in = drop_in + self.nhtype = nhtype + self.sr_prefix = sr_prefix + self.v4src_addr = v4src_addr + self.v4src_position = v4src_position + self._configured = False + + def add_vpp_config(self): + self._test.vapi.sr_mobile_localsid_add_del( + localsid_prefix=self.localsid_prefix, + behavior=self.behavior, + fib_table=self.fib_table, + local_fib_table=self.local_fib_table, + drop_in=self.drop_in, + sr_prefix=self.sr_prefix, + v4src_addr=self.v4src_addr, + v4src_position=self.v4src_position, + is_del=0, + ) + self._configured = True + + def remove_vpp_config(self): + self._test.vapi.sr_mobile_localsid_add_del( + localsid_prefix=self.localsid_prefix, + behavior=self.behavior, + fib_table=self.fib_table, + local_fib_table=self.local_fib_table, + drop_in=self.drop_in, + sr_prefix=self.sr_prefix, + v4src_addr=self.v4src_addr, + v4src_position=self.v4src_position, + is_del=1, + ) + self._configured = False + + def query_vpp_config(self): + return self._configured + + def object_id(self): + return "%d;%s,%s" % (self.fib_table, self.localsid_prefix, self.behavior) + + +class VppSRv6MobilePolicy(VppObject): + """ + SRv6 Policy + """ + + def __init__( + self, + test, + bsid_addr, + sr_prefix, + v6src_prefix, + behavior, + fib_table=0, + local_fib_table=0, + encap_src=None, + drop_in=0, + nhtype=SRv6MobileNhtype.SRV6_NHTYPE_API_NONE, + ): + self._test = test + self.bsid_addr = bsid_addr + self.sr_prefix = sr_prefix + self.v6src_prefix = v6src_prefix + self.behavior = behavior + self.fib_table = fib_table + self.local_fib_table = local_fib_table + self.drop_in = drop_in + self.nhtype = nhtype + self.encap_src = encap_src + self._configured = False + + def add_vpp_config(self): + self._test.vapi.sr_mobile_policy_add( + bsid_addr=self.bsid_addr, + sr_prefix=self.sr_prefix, + v6src_prefix=self.v6src_prefix, + behavior=self.behavior, + fib_table=self.fib_table, + local_fib_table=self.local_fib_table, + encap_src=self.encap_src, + drop_in=self.drop_in, + nhtype=self.nhtype, + ) + self._configured = True + + def remove_vpp_config(self): + self._test.vapi.sr_policy_del(self.bsid_addr) + self._configured = False + + def query_vpp_config(self): + # no API to query SR Policies + # use _configured flag for now + return self._configured + + def object_id(self): + return "%d;%s-><%s>;%d" % ( + self.sr_type, + self.bsid, + ",".join(self.segments), + self.is_encap, + )