srv6-mobile: Implement SRv6 mobile API funcs
[vpp.git] / src / plugins / srv6-mobile / sr_mobile_api.c
1 /*
2  *------------------------------------------------------------------
3  * sr_mobile_api.c - ipv6 segment routing for mobile u-plane api
4  *
5  * Copyright (c) 2022 BBSakura Networks Inc and/or its affiliates.
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at:
9  *
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *------------------------------------------------------------------
18  */
19
20 #include <stdint.h>
21 #include <vnet/vnet.h>
22 #include <vnet/srv6/sr.h>
23 #include <vlibmemory/api.h>
24
25 #include <vnet/interface.h>
26 #include <vnet/api_errno.h>
27 #include <vnet/feature/feature.h>
28 #include <vnet/fib/fib_table.h>
29 #include <vnet/ip/ip_types_api.h>
30
31 #include <vnet/format_fns.h>
32 #include <vnet/srv6/sr.api_enum.h>
33 #include <vnet/srv6/sr.api_types.h>
34
35 #include <srv6-mobile/mobile.h>
36 #include <srv6-mobile/sr_mobile.api_types.h>
37 #include <srv6-mobile/sr_mobile_types.api_types.h>
38 #include <srv6-mobile/sr_mobile.api_enum.h>
39
40 #include <srv6-mobile/sr_mobile_api.h>
41
42 u16 msg_id_base;
43 #define REPLY_MSG_ID_BASE msg_id_base
44 #include <vlibapi/api_helper_macros.h>
45
46 static inline uint16_t
47 sr_plugin_localsid_fn_num_find_by (ip6_sr_main_t *sm, const char *keyword_str,
48                                    size_t keyword_len)
49 {
50   sr_localsid_fn_registration_t *plugin = 0, **vec_plugins = 0;
51   sr_localsid_fn_registration_t **plugin_it = 0;
52   pool_foreach (plugin, sm->plugin_functions)
53     {
54       vec_add1 (vec_plugins, plugin);
55     }
56
57   vec_foreach (plugin_it, vec_plugins)
58     {
59       if (!srv6_mobile_strcmp_with_size (keyword_str, keyword_len,
60                                          (char *) (*plugin_it)->keyword_str))
61         {
62           return (*plugin_it)->sr_localsid_function_number;
63         }
64     }
65   return UINT16_MAX;
66 }
67
68 static inline uint16_t
69 sr_plugin_policy_fn_num_find_by (ip6_sr_main_t *sm, const char *keyword_str,
70                                  size_t keyword_len)
71 {
72   sr_policy_fn_registration_t *plugin = 0, **vec_plugins = 0;
73   sr_policy_fn_registration_t **plugin_it = 0;
74   pool_foreach (plugin, sm->policy_plugin_functions)
75     {
76       vec_add1 (vec_plugins, plugin);
77     }
78
79   vec_foreach (plugin_it, vec_plugins)
80     {
81       if (!srv6_mobile_strcmp_with_size (keyword_str, keyword_len,
82                                          (char *) (*plugin_it)->keyword_str))
83         {
84           return (*plugin_it)->sr_policy_function_number;
85         }
86     }
87   return UINT16_MAX;
88 }
89
90 static void
91 vl_api_sr_mobile_localsid_add_del_t_handler (
92   vl_api_sr_mobile_localsid_add_del_t *mp)
93 {
94   ip6_sr_main_t *sm = &sr_main;
95   vl_api_sr_mobile_localsid_add_del_reply_t *rmp;
96   int rv = 0;
97   ip6_address_t localsid;
98   u16 localsid_prefix_len = 128;
99   void *ls_plugin_mem = 0;
100   u16 behavior = 0;
101   u32 dt_type;
102   size_t behavior_size = 0;
103   mobile_localsid_function_list_t kind_fn =
104     SRV6_MOBILE_LOCALSID_UNKNOWN_FUNCTION;
105
106   mp->behavior[sizeof (mp->behavior) - 1] = '\0';
107   behavior_size = sizeof (mp->behavior);
108   // search behavior index
109   if (mp->behavior[0])
110     {
111       if (!srv6_mobile_strcmp_with_size ((char *) mp->behavior, behavior_size,
112                                          "end.m.gtp4.e"))
113         {
114           kind_fn = SRV6_MOBILE_LOCALSID_END_M_GTP4_E;
115         }
116       else if (!srv6_mobile_strcmp_with_size ((char *) mp->behavior,
117                                               behavior_size, "end.m.gtp6.e"))
118         {
119           kind_fn = SRV6_MOBILE_LOCALSID_END_M_GTP6_E;
120         }
121       else if (!srv6_mobile_strcmp_with_size ((char *) mp->behavior,
122                                               behavior_size, "end.m.gtp6.d"))
123         {
124           kind_fn = SRV6_MOBILE_LOCALSID_END_M_GTP6_D;
125         }
126       else if (!srv6_mobile_strcmp_with_size (
127                  (char *) mp->behavior, behavior_size, "end.m.gtp6.d.di"))
128         {
129           kind_fn = SRV6_MOBILE_LOCALSID_END_M_GTP6_D_DI;
130         }
131       else if (!srv6_mobile_strcmp_with_size (
132                  (char *) mp->behavior, behavior_size, "end.m.gtp6.d.dt4"))
133         {
134           kind_fn = SRV6_MOBILE_LOCALSID_END_M_GTP6_D_DT4;
135           dt_type = SRV6_GTP6_DT4;
136         }
137       else if (!srv6_mobile_strcmp_with_size (
138                  (char *) mp->behavior, behavior_size, "end.m.gtp6.d.dt6"))
139         {
140           kind_fn = SRV6_MOBILE_LOCALSID_END_M_GTP6_D_DT6;
141           dt_type = SRV6_GTP6_DT6;
142         }
143       else if (!srv6_mobile_strcmp_with_size (
144                  (char *) mp->behavior, behavior_size, "end.m.gtp6.d.dt46"))
145         {
146           kind_fn = SRV6_MOBILE_LOCALSID_END_M_GTP6_D_DT46;
147           dt_type = SRV6_GTP6_DT46;
148         }
149       else
150         {
151           return;
152         }
153       switch (kind_fn)
154         {
155         case SRV6_MOBILE_LOCALSID_END_M_GTP4_E:
156           alloc_param_srv6_end_m_gtp4_e (&ls_plugin_mem, &mp->v4src_addr,
157                                          ntohl (mp->v4src_position),
158                                          ntohl (mp->fib_table));
159           break;
160         case SRV6_MOBILE_LOCALSID_END_M_GTP6_E:
161           alloc_param_srv6_end_m_gtp6_e (&ls_plugin_mem,
162                                          ntohl (mp->fib_table));
163           break;
164         case SRV6_MOBILE_LOCALSID_END_M_GTP6_D:
165           alloc_param_srv6_end_m_gtp6_d (
166             &ls_plugin_mem, &mp->sr_prefix.address, mp->sr_prefix.len,
167             (u8) ntohl (mp->nhtype), mp->drop_in, ntohl (mp->fib_table));
168           break;
169         case SRV6_MOBILE_LOCALSID_END_M_GTP6_D_DI:
170           alloc_param_srv6_end_m_gtp6_di (
171             &ls_plugin_mem, &mp->sr_prefix.address, mp->sr_prefix.len,
172             (u8) ntohl (mp->nhtype));
173           break;
174         case SRV6_MOBILE_LOCALSID_END_M_GTP6_D_DT4:
175         case SRV6_MOBILE_LOCALSID_END_M_GTP6_D_DT6:
176         case SRV6_MOBILE_LOCALSID_END_M_GTP6_D_DT46:
177           alloc_param_srv6_end_m_gtp6_dt (
178             &ls_plugin_mem, ntohl (mp->fib_table), ntohl (mp->local_fib_table),
179             dt_type);
180           break;
181         case SRV6_MOBILE_LOCALSID_UNKNOWN_FUNCTION:
182         default:
183           return; // error
184         }
185       behavior = sr_plugin_localsid_fn_num_find_by (sm, (char *) mp->behavior,
186                                                     behavior_size);
187       if (behavior == UINT16_MAX)
188         return;
189     }
190   else
191     {
192       return;
193     }
194   ip6_address_decode (mp->localsid_prefix.address, &localsid);
195   localsid_prefix_len = mp->localsid_prefix.len;
196
197   rv = sr_cli_localsid (mp->is_del, &localsid, localsid_prefix_len,
198                         0, // ignore end_psp
199                         behavior,
200                         0, // ignore sw_if_index
201                         0, // ignore vlan_index
202                         ntohl (mp->fib_table),
203                         NULL, // ignore nh_addr
204                         0,    // ignore usid_len
205                         ls_plugin_mem);
206
207   REPLY_MACRO (VL_API_SR_MOBILE_LOCALSID_ADD_DEL_REPLY);
208 }
209
210 static void
211 vl_api_sr_mobile_policy_add_t_handler (vl_api_sr_mobile_policy_add_t *mp)
212 {
213   ip6_sr_main_t *sm = &sr_main;
214   vl_api_sr_mobile_policy_add_reply_t *rmp;
215   ip6_address_t bsid_addr;
216   ip6_address_t encap_src;
217   void *ls_plugin_mem = 0;
218   u16 behavior = 0;
219   size_t behavior_size = 0;
220
221   u32 dt_type;
222   mobile_policy_function_list_t kind_fn = SRV6_MOBILE_POLICY_UNKNOWN_FUNCTION;
223
224   ip6_address_decode (mp->bsid_addr, &bsid_addr);
225   ip6_address_decode (mp->encap_src, &encap_src);
226   if (ip6_address_is_zero (&encap_src))
227     {
228       encap_src = *sr_get_encaps_source ();
229     }
230   mp->behavior[sizeof (mp->behavior) - 1] = '\0';
231   behavior_size = sizeof (mp->behavior);
232
233   // search behavior index
234   if (mp->behavior[0])
235     {
236       if (!srv6_mobile_strcmp_with_size ((char *) mp->behavior, behavior_size,
237                                          "t.m.gtp4.d"))
238         {
239           kind_fn = SRV6_MOBILE_POLICY_T_M_GTP4_D;
240         }
241       else if (!srv6_mobile_strcmp_with_size ((char *) mp->behavior,
242                                               behavior_size, "t.m.gtp4.dt4"))
243         {
244           kind_fn = SRV6_MOBILE_POLICY_T_M_GTP4_DT4;
245           dt_type = SRV6_GTP4_DT4;
246         }
247       else if (!srv6_mobile_strcmp_with_size ((char *) mp->behavior,
248                                               behavior_size, "t.m.gtp4.dt6"))
249         {
250           kind_fn = SRV6_MOBILE_POLICY_T_M_GTP4_DT6;
251           dt_type = SRV6_GTP4_DT6;
252         }
253       else if (!srv6_mobile_strcmp_with_size ((char *) mp->behavior,
254                                               behavior_size, "t.m.gtp4.dt46"))
255         {
256           kind_fn = SRV6_MOBILE_POLICY_T_M_GTP4_DT46;
257           dt_type = SRV6_GTP4_DT46;
258         }
259       else if (!srv6_mobile_strcmp_with_size ((char *) mp->behavior,
260                                               behavior_size, "end.m.gtp6.d"))
261         {
262           kind_fn = SRV6_MOBILE_POLICY_END_M_GTP6_D;
263         }
264       else
265         {
266           return;
267         }
268
269       switch (kind_fn)
270         {
271         case SRV6_MOBILE_POLICY_T_M_GTP4_D:
272           alloc_param_srv6_t_m_gtp4_d (
273             &ls_plugin_mem, &mp->v6src_prefix.address, mp->v6src_prefix.len,
274             &mp->sr_prefix.address, mp->sr_prefix.len, ntohl (mp->fib_table),
275             mp->nhtype, mp->drop_in);
276           break;
277         case SRV6_MOBILE_POLICY_END_M_GTP6_D:
278           alloc_param_srv6_end_m_gtp6_d (
279             &ls_plugin_mem, &mp->sr_prefix.address, mp->sr_prefix.len,
280             mp->nhtype, mp->drop_in, ntohl (mp->fib_table));
281           break;
282         case SRV6_MOBILE_POLICY_T_M_GTP4_DT4:
283         case SRV6_MOBILE_POLICY_T_M_GTP4_DT6:
284         case SRV6_MOBILE_POLICY_T_M_GTP4_DT46:
285           alloc_param_srv6_t_m_gtp4_dt (&ls_plugin_mem, ntohl (mp->fib_table),
286                                         ntohl (mp->local_fib_table), dt_type);
287           break;
288         case SRV6_MOBILE_POLICY_UNKNOWN_FUNCTION:
289         default:
290           return; // error
291         }
292
293       behavior = sr_plugin_policy_fn_num_find_by (sm, (char *) mp->behavior,
294                                                   behavior_size);
295       if (behavior == UINT16_MAX)
296         return;
297     }
298   else
299     {
300       return;
301     }
302
303   int rv = 0;
304   ip6_address_t *segments = 0, *this_seg;
305   vec_add2 (segments, this_seg, 1);
306   clib_memset (this_seg, 0, sizeof (*this_seg));
307
308   rv = sr_policy_add (&bsid_addr,
309                       segments, // ignore segments
310                       &encap_src,
311                       (u32) ~0,               // ignore weight
312                       SR_POLICY_TYPE_DEFAULT, // ignore type
313                       (u32) ~0,               // ignore fib_table
314                       1,                      // ignore is_encap,
315                       behavior, ls_plugin_mem);
316   vec_free (segments);
317   REPLY_MACRO (VL_API_SR_MOBILE_POLICY_ADD_REPLY);
318 }
319
320 #include <srv6-mobile/sr_mobile.api.c>
321 static clib_error_t *
322 sr_mobile_api_hookup (vlib_main_t *vm)
323 {
324   /*
325    * Set up the (msg_name, crc, message-id) table
326    */
327   REPLY_MSG_ID_BASE = setup_message_id_table ();
328
329   return 0;
330 }
331
332 VLIB_API_INIT_FUNCTION (sr_mobile_api_hookup);
333 /*
334  * fd.io coding-style-patch-verification: ON
335  *
336  * Local Variables:
337  * eval: (c-set-style "gnu")
338  * End:
339  */