7d8aa732a65042dd6078e2c6ca04ffd1a42df9dc
[vpp.git] / src / vnet / srv6 / sr.h
1 /*
2  * Copyright (c) 2015 Cisco and/or its affiliates.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at:
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15
16 /**
17  * @file
18  * @brief Segment Routing data structures definitions
19  *
20  */
21
22 #ifndef included_vnet_srv6_h
23 #define included_vnet_srv6_h
24
25 #include <vnet/vnet.h>
26 #include <vnet/srv6/sr_packet.h>
27 #include <vnet/ip/ip6_packet.h>
28 #include <vnet/ethernet/ethernet.h>
29
30 #include <stdlib.h>
31 #include <string.h>
32
33 #define IPv6_DEFAULT_HEADER_LENGTH 40
34 #define IPv6_DEFAULT_HOP_LIMIT 64
35 #define IPv6_DEFAULT_MAX_MASK_WIDTH 128
36
37 #define SR_BEHAVIOR_END 1
38 #define SR_BEHAVIOR_X 2
39 #define SR_BEHAVIOR_T 3
40 #define SR_BEHAVIOR_D_FIRST 4   /* Unused. Separator in between regular and D */
41 #define SR_BEHAVIOR_DX2 5
42 #define SR_BEHAVIOR_DX6 6
43 #define SR_BEHAVIOR_DX4 7
44 #define SR_BEHAVIOR_DT6 8
45 #define SR_BEHAVIOR_DT4 9
46 #define SR_BEHAVIOR_END_UN_PERF 10
47 #define SR_BEHAVIOR_END_UN 11
48 #define SR_BEHAVIOR_LAST 12     /* Must always be the last one */
49
50 #define SR_STEER_L2 2
51 #define SR_STEER_IPV4 4
52 #define SR_STEER_IPV6 6
53
54 #define SR_FUNCTION_SIZE 4
55 #define SR_ARGUMENT_SIZE 4
56
57 #define SR_SEGMENT_LIST_WEIGHT_DEFAULT 1
58
59 /* *INDENT-OFF* */
60 typedef struct
61 {
62   ip6_header_t ip;
63   ip6_sr_header_t sr;
64 } __attribute__ ((packed)) ip6srv_combo_header_t;
65 /* *INDENT-ON* */
66
67 /**
68  * @brief SR Segment List (SID list)
69  */
70 typedef struct
71 {
72   ip6_address_t *segments;              /**< SIDs (key) */
73
74   u32 weight;                                           /**< SID list weight (wECMP / UCMP) */
75
76   u8 *rewrite;                                  /**< Precomputed rewrite header */
77   u8 *rewrite_bsid;                             /**< Precomputed rewrite header for bindingSID */
78   u8 policy_type;
79
80   u32 egress_fib_table; /**< Egress FIB table for encap packet */
81
82   dpo_id_t bsid_dpo;                            /**< DPO for Encaps/Insert for BSID */
83   dpo_id_t ip6_dpo;                             /**< DPO for Encaps/Insert IPv6 */
84   dpo_id_t ip4_dpo;                             /**< DPO for Encaps IPv6 */
85
86   u16 plugin;
87   void *plugin_mem;
88 } ip6_sr_sl_t;
89
90 /* SR policy types */
91 #define SR_POLICY_TYPE_DEFAULT 0
92 #define SR_POLICY_TYPE_SPRAY 1
93 #define SR_POLICY_TYPE_TEF     2
94 /**
95  * @brief SR Policy
96  */
97 typedef struct
98 {
99   u32 *segments_lists;          /**< SID lists indexes (vector) */
100
101   ip6_address_t bsid;                   /**< BindingSID (key) */
102
103   u8 type;                                      /**< Type (default is 0) */
104   /* SR Policy specific DPO                                       */
105   /* IF Type = DEFAULT Then Load-Balancer DPO among SID lists     */
106   /* IF Type = SPRAY then Spray DPO with all SID lists            */
107   dpo_id_t bsid_dpo;                    /**< SR Policy specific DPO - BSID */
108   dpo_id_t ip4_dpo;                     /**< SR Policy specific DPO - IPv6 */
109   dpo_id_t ip6_dpo;                     /**< SR Policy specific DPO - IPv4 */
110
111   u32 fib_table;                        /**< FIB table */
112
113   u8 is_encap;                          /**< Mode (0 is SRH insert, 1 Encaps) */
114
115   ip6_address_t encap_src;
116
117   u16 plugin;
118   void *plugin_mem;
119 } ip6_sr_policy_t;
120
121 typedef int (sr_p_plugin_callback_t) (ip6_sr_policy_t * sr);
122
123 /**
124  * @brief SR LocalSID
125  */
126 typedef struct
127 {
128   ip6_address_t localsid;               /**< LocalSID IPv6 address */
129
130   u16 localsid_prefix_len;
131
132   char end_psp;                                 /**< Combined with End.PSP? */
133
134   u8 behavior; /**< Behavior associated to this localsid */
135
136   union
137   {
138     u32 sw_if_index;                            /**< xconnect only */
139     u32 vrf_index;                              /**< vrf only */
140   };
141
142   u32 fib_table;                                /**< FIB table where localsid is registered */
143
144   u32 vlan_index;                               /**< VLAN tag (not an index) */
145
146   ip46_address_t next_hop;              /**< Next_hop for xconnect usage only */
147
148   u32 nh_adj;                                           /**< Next_adj for xconnect usage only */
149
150   ip6_address_t usid_block;
151   ip6_address_t usid_block_mask;
152
153   u8 usid_index;
154   u8 usid_len;
155
156   u8 usid_next_index;
157   u8 usid_next_len;
158
159   void *plugin_mem;                             /**< Memory to be used by the plugin callback functions */
160 } ip6_sr_localsid_t;
161
162 typedef int (sr_plugin_callback_t) (ip6_sr_localsid_t * localsid);
163
164 /**
165  * @brief SR LocalSID behavior registration
166  */
167 typedef struct
168 {
169   u16 sr_localsid_function_number;                      /**< SR LocalSID plugin function (>SR_BEHAVIOR_LAST) */
170
171   u8 *function_name;                                                    /**< Function name. (key). */
172
173   u8 *keyword_str;                                                      /**< Behavior keyword (i.e. End.X) */
174
175   u8 *def_str;                                                          /**< Behavior definition (i.e. Endpoint with cross-connect) */
176
177   u8 *params_str;                                                       /**< Behavior parameters (i.e. <oif> <IP46next_hop>) */
178
179   u8 prefix_length;
180
181   dpo_type_t dpo;                                                       /**< DPO type registration */
182
183   format_function_t *ls_format;                         /**< LocalSID format function */
184
185   unformat_function_t *ls_unformat;                     /**< LocalSID unformat function */
186
187   sr_plugin_callback_t *creation;                       /**< Function within plugin that will be called after localsid creation*/
188
189   sr_plugin_callback_t *removal;                        /**< Function within plugin that will be called before localsid removal */
190 } sr_localsid_fn_registration_t;
191
192 /**
193  * @brief SR Policy behavior registration
194  */
195 typedef struct
196 {
197   u16 sr_policy_function_number;                        /**< SR Policy plugin function */
198
199   u8 *function_name;                                    /**< Function name. (key). */
200
201   u8 *keyword_str;                                      /**< Behavior keyword (i.e. End.X) */
202
203   u8 *def_str;                                          /**< Behavior definition (i.e. Endpoint with cross-connect) */
204
205   u8 *params_str;                                       /**< Behavior parameters (i.e. <oif> <IP46next_hop>) */
206
207   u8 prefix_length;
208
209   dpo_type_t dpo;                                       /**< DPO type registration */
210
211   format_function_t *ls_format;                         /**< LocalSID format function */
212
213   unformat_function_t *ls_unformat;                     /**< LocalSID unformat function */
214
215   sr_p_plugin_callback_t *creation;                     /**< Function within plugin that will be called after localsid creation*/
216
217   sr_p_plugin_callback_t *removal;                      /**< Function within plugin that will be called before localsid removal */
218 } sr_policy_fn_registration_t;
219
220 /**
221  * @brief Steering db key
222  *
223  * L3 is IPv4/IPv6 + mask
224  * L2 is sf_if_index + vlan
225  */
226 typedef struct
227 {
228   union
229   {
230     struct
231     {
232       ip46_address_t prefix;                    /**< IP address of the prefix */
233       u32 mask_width;                                   /**< Mask width of the prefix */
234       u32 fib_table;                                    /**< VRF of the prefix */
235     } l3;
236     struct
237     {
238       u32 sw_if_index;                                  /**< Incoming software interface */
239     } l2;
240   };
241   u8 traffic_type;                                      /**< Traffic type (IPv4, IPv6, L2) */
242   u8 padding[3];
243 } sr_steering_key_t;
244
245 typedef struct
246 {
247   sr_steering_key_t classify;           /**< Traffic classification */
248   u32 sr_policy;                                        /**< SR Policy index */
249 } ip6_sr_steering_policy_t;
250
251 typedef struct
252 {
253   ip6_address_t address;
254   u16 pref_len;
255   u8 padding[2];
256 } sr_localsid_key_t;
257
258 /**
259  * @brief Segment Routing main datastructure
260  */
261 typedef struct
262 {
263   /* L2-input -> SR rewrite next index */
264   u32 l2_sr_policy_rewrite_index;
265
266   /* SR SID lists */
267   ip6_sr_sl_t *sid_lists;
268
269   /* SRv6 policies */
270   ip6_sr_policy_t *sr_policies;
271
272   /* Hash table mapping BindingSID to SRv6 policy */
273   mhash_t sr_policies_index_hash;
274
275   /* Pool of SR localsid instances */
276   ip6_sr_localsid_t *localsids;
277
278   /* Hash table mapping LOC:FUNC to SR LocalSID instance */
279   mhash_t sr_localsids_index_hash;
280
281   /* Pool of SR steer policies instances */
282   ip6_sr_steering_policy_t *steer_policies;
283
284   /* Hash table mapping steering rules to SR steer instance */
285   mhash_t sr_steer_policies_hash;
286
287   /* L2 steering ifaces - sr_policies */
288   u32 *sw_iface_sr_policies;
289
290   /* Spray DPO */
291   dpo_type_t sr_pr_spray_dpo_type;
292
293   /* Plugin functions */
294   sr_localsid_fn_registration_t *plugin_functions;
295
296   /* Find plugin function by name */
297   uword *plugin_functions_by_key;
298
299   /* Plugin functions for Policy */
300   sr_policy_fn_registration_t *policy_plugin_functions;
301
302   /* Find plugin function by name */
303   uword *policy_plugin_functions_by_key;
304
305   /* Counters */
306   vlib_combined_counter_main_t sr_ls_valid_counters;
307   vlib_combined_counter_main_t sr_ls_invalid_counters;
308
309   /* SR Policies FIBs */
310   u32 fib_table_ip6;
311   u32 fib_table_ip4;
312
313   /* convenience */
314   vlib_main_t *vlib_main;
315   vnet_main_t *vnet_main;
316   u16 msg_id_base;
317 } ip6_sr_main_t;
318
319 extern ip6_sr_main_t sr_main;
320
321 extern vlib_node_registration_t sr_policy_rewrite_encaps_node;
322 extern vlib_node_registration_t sr_policy_rewrite_insert_node;
323 extern vlib_node_registration_t sr_localsid_node;
324 extern vlib_node_registration_t sr_localsid_d_node;
325
326 extern void sr_dpo_lock (dpo_id_t * dpo);
327 extern void sr_dpo_unlock (dpo_id_t * dpo);
328
329 extern int
330 sr_localsid_register_function (vlib_main_t * vm, u8 * fn_name,
331                                u8 * keyword_str, u8 * def_str,
332                                u8 * params_str, u8 prefix_length,
333                                dpo_type_t * dpo,
334                                format_function_t * ls_format,
335                                unformat_function_t * ls_unformat,
336                                sr_plugin_callback_t * creation_fn,
337                                sr_plugin_callback_t * removal_fn);
338
339 extern int
340 sr_policy_register_function (vlib_main_t * vm, u8 * fn_name,
341                              u8 * keyword_str, u8 * def_str,
342                              u8 * params_str, u8 prefix_length,
343                              dpo_type_t * dpo,
344                              format_function_t * ls_format,
345                              unformat_function_t * ls_unformat,
346                              sr_p_plugin_callback_t * creation_fn,
347                              sr_p_plugin_callback_t * removal_fn);
348
349 extern int sr_policy_add (ip6_address_t *bsid, ip6_address_t *segments,
350                           ip6_address_t *encap_src, u32 weight, u8 type,
351                           u32 fib_table, u8 is_encap, u16 plugin,
352                           void *plugin_mem);
353 extern int sr_policy_mod (ip6_address_t *bsid, u32 index, u32 fib_table,
354                           u8 operation, ip6_address_t *segments,
355                           ip6_address_t *encap_src, u32 sl_index, u32 weight);
356 extern int sr_policy_del (ip6_address_t * bsid, u32 index);
357
358 extern int
359 sr_cli_localsid (char is_del, ip6_address_t * localsid_addr,
360                  u16 localsid_prefix_len, char end_psp, u8 behavior,
361                  u32 sw_if_index, u32 vlan_index, u32 fib_table,
362                  ip46_address_t * nh_addr, int usid_len, void *ls_plugin_mem);
363
364 extern int
365 sr_steering_policy (int is_del, ip6_address_t * bsid, u32 sr_policy_index,
366                     u32 table_id, ip46_address_t * prefix, u32 mask_width,
367                     u32 sw_if_index, u8 traffic_type);
368
369 extern void sr_set_source (ip6_address_t * address);
370 extern ip6_address_t *sr_get_encaps_source ();
371
372 extern void sr_set_hop_limit (u8 hop_limit);
373 extern u8 sr_get_hop_limit (void);
374
375 /**
376  * @brief SR rewrite string computation for SRH insertion (inline)
377  *
378  * @param sl is a vector of IPv6 addresses composing the Segment List
379  *
380  * @return precomputed rewrite string for SRH insertion
381  */
382 static inline u8 *
383 ip6_sr_compute_rewrite_string_insert (ip6_address_t * sl)
384 {
385   ip6_sr_header_t *srh;
386   ip6_address_t *addrp, *this_address;
387   u32 header_length = 0;
388   u8 *rs = NULL;
389
390   header_length = 0;
391   header_length += sizeof (ip6_sr_header_t);
392   header_length += (vec_len (sl) + 1) * sizeof (ip6_address_t);
393
394   vec_validate (rs, header_length - 1);
395
396   srh = (ip6_sr_header_t *) rs;
397   srh->type = ROUTING_HEADER_TYPE_SR;
398   srh->segments_left = vec_len (sl);
399   srh->last_entry = vec_len (sl);
400   srh->length = ((sizeof (ip6_sr_header_t) +
401                   ((vec_len (sl) + 1) * sizeof (ip6_address_t))) / 8) - 1;
402   srh->flags = 0x00;
403   srh->tag = 0x0000;
404   addrp = srh->segments + vec_len (sl);
405   vec_foreach (this_address, sl)
406   {
407     clib_memcpy_fast (addrp->as_u8, this_address->as_u8,
408                       sizeof (ip6_address_t));
409     addrp--;
410   }
411   return rs;
412 }
413
414 #endif /* included_vnet_sr_h */
415
416 /*
417  * fd.io coding-style-patch-verification: ON
418  *
419  * Local Variables:
420  * eval: (c-set-style "gnu")
421  * End:
422  */