hs-test: fixed timed out tests passing in the CI
[vpp.git] / src / vnet / ip / ip6_hop_by_hop.h
1 /*
2  * Copyright (c) 2016 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 #ifndef __included_ip6_hop_by_hop_ioam_h__
16 #define __included_ip6_hop_by_hop_ioam_h__
17
18 #include <vnet/ip/ip6_hop_by_hop_packet.h>
19 #include <vnet/ip/ip.h>
20
21
22 #define MAX_IP6_HBH_OPTION      256
23
24 /* To determine whether a node is decap MS bit is set */
25 #define IOAM_DECAP_BIT 0x80000000
26
27 #define IOAM_DEAP_ENABLED(opaque_data) (opaque_data & IOAM_DECAP_BIT)
28
29 #define IOAM_SET_DECAP(opaque_data) \
30     (opaque_data |= IOAM_DECAP_BIT)
31
32 #define IOAM_MASK_DECAP_BIT(x) (x & ~IOAM_DECAP_BIT)
33
34 /*
35  * Stores the run time flow data of hbh options
36  */
37 typedef struct
38 {
39   u32 ctx[MAX_IP6_HBH_OPTION];
40   u8 flow_name[64];
41 } flow_data_t;
42
43 typedef struct
44 {
45   u8 next_index_by_protocol[256];
46 } ip6_local_hop_by_hop_runtime_t;
47
48 typedef struct
49 {
50   /* The current rewrite we're using */
51   u8 *rewrite;
52
53   /* Trace data processing callback */
54   void *ioam_end_of_path_cb;
55   /* Configuration data */
56   /* Adjacency */
57   ip6_address_t adj;
58 #define IOAM_HBYH_ADD  0
59 #define IOAM_HBYH_MOD  1
60 #define IOAM_HBYH_POP  2
61   u8 ioam_flag;
62   /* time scale transform. Joy. */
63   u32 unix_time_0;
64   f64 vlib_time_0;
65
66
67   /* Trace option */
68   u8 has_trace_option;
69
70   /* Pot option */
71   u8 has_pot_option;
72
73   /* Per Packet Counter option */
74   u8 has_seqno_option;
75
76   /* Enabling analyis of iOAM data on decap node */
77   u8 has_analyse_option;
78
79   /* Array of function pointers to ADD and POP HBH option handling routines */
80   u8 options_size[MAX_IP6_HBH_OPTION];
81   int (*add_options[MAX_IP6_HBH_OPTION]) (u8 * rewrite_string,
82                                           u8 * rewrite_size);
83   int (*pop_options[MAX_IP6_HBH_OPTION]) (vlib_buffer_t * b,
84                                           ip6_header_t * ip,
85                                           ip6_hop_by_hop_option_t * opt);
86   int (*get_sizeof_options[MAX_IP6_HBH_OPTION]) (u32 * rewrite_size);
87   int (*config_handler[MAX_IP6_HBH_OPTION]) (void *data, u8 disable);
88
89   /* Array of function pointers to handle hbh options being used with classifier */
90     u32 (*flow_handler[MAX_IP6_HBH_OPTION]) (u32 flow_ctx, u8 add);
91   flow_data_t *flows;
92
93   ip6_local_hop_by_hop_runtime_t *ip6_local_hbh_runtime;
94
95   /* convenience */
96   vlib_main_t *vlib_main;
97   vnet_main_t *vnet_main;
98 } ip6_hop_by_hop_ioam_main_t;
99
100 extern ip6_hop_by_hop_ioam_main_t ip6_hop_by_hop_ioam_main;
101
102 extern clib_error_t *ip6_ioam_enable (int has_trace_option,
103                                       int has_pot_option,
104                                       int has_seqno_option,
105                                       int has_analyse_option);
106
107 extern int ip6_ioam_set_destination (ip6_address_t * addr, u32 mask_width,
108                                      u32 vrf_id, int is_add, int is_pop,
109                                      int is_none);
110
111 extern clib_error_t *clear_ioam_rewrite_fn (void);
112
113 static inline u8
114 is_zero_ip4_address (ip4_address_t * a)
115 {
116   return (a->as_u32 == 0);
117 }
118
119 static inline void
120 copy_ip6_address (ip6_address_t * dst, ip6_address_t * src)
121 {
122   dst->as_u64[0] = src->as_u64[0];
123   dst->as_u64[1] = src->as_u64[1];
124 }
125
126 static inline void
127 set_zero_ip6_address (ip6_address_t * a)
128 {
129   a->as_u64[0] = 0;
130   a->as_u64[1] = 0;
131 }
132
133 static inline u8
134 cmp_ip6_address (ip6_address_t * a1, ip6_address_t * a2)
135 {
136   return ((a1->as_u64[0] == a2->as_u64[0])
137           && (a1->as_u64[1] == a2->as_u64[1]));
138 }
139
140 static inline u8
141 is_zero_ip6_address (ip6_address_t * a)
142 {
143   return ((a->as_u64[0] == 0) && (a->as_u64[1] == 0));
144 }
145
146 int ip6_hbh_add_register_option (u8 option,
147                                  u8 size,
148                                  int rewrite_options (u8 * rewrite_string,
149                                                       u8 * size));
150 int ip6_hbh_add_unregister_option (u8 option);
151
152 int ip6_hbh_pop_register_option (u8 option,
153                                  int options (vlib_buffer_t * b,
154                                               ip6_header_t * ip,
155                                               ip6_hop_by_hop_option_t * opt));
156 int ip6_hbh_pop_unregister_option (u8 option);
157
158 int
159 ip6_hbh_get_sizeof_register_option (u8 option,
160                                     int get_sizeof_hdr_options (u32 *
161                                                                 rewrite_size));
162
163 int
164 ip6_ioam_set_rewrite (u8 ** rwp, int has_trace_option,
165                       int has_pot_option, int has_seq_no);
166
167 int
168 ip6_hbh_config_handler_register (u8 option,
169                                  int config_handler (void *data, u8 disable));
170
171 int ip6_hbh_config_handler_unregister (u8 option);
172
173 int ip6_hbh_flow_handler_register (u8 option,
174                                    u32 ioam_flow_handler (u32 flow_ctx,
175                                                           u8 add));
176
177 int ip6_hbh_flow_handler_unregister (u8 option);
178
179 u8 *get_flow_name_from_flow_ctx (u32 flow_ctx);
180
181 static inline flow_data_t *
182 get_flow (u32 index)
183 {
184   flow_data_t *flow = NULL;
185   ip6_hop_by_hop_ioam_main_t *hm = &ip6_hop_by_hop_ioam_main;
186
187   if (pool_is_free_index (hm->flows, index))
188     return NULL;
189
190   flow = pool_elt_at_index (hm->flows, index);
191   return flow;
192 }
193
194 static inline u32
195 get_flow_data_from_flow_ctx (u32 flow_ctx, u8 option)
196 {
197   flow_data_t *flow = NULL;
198   ip6_hop_by_hop_ioam_main_t *hm = &ip6_hop_by_hop_ioam_main;
199   u32 index;
200
201   index = IOAM_MASK_DECAP_BIT (flow_ctx);
202   //flow = pool_elt_at_index (hm->flows, index);
203   flow = &hm->flows[index];
204   return (flow->ctx[option]);
205 }
206
207 static inline u8
208 is_seqno_enabled (void)
209 {
210   return (ip6_hop_by_hop_ioam_main.has_seqno_option);
211 }
212
213 int ip6_trace_profile_setup ();
214
215 static inline u32
216 ioam_flow_add (u8 encap, u8 * flow_name)
217 {
218   ip6_hop_by_hop_ioam_main_t *hm = &ip6_hop_by_hop_ioam_main;
219   flow_data_t *flow = 0;
220   u32 index = 0;
221   u8 i;
222
223   pool_get (hm->flows, flow);
224   clib_memset (flow, 0, sizeof (flow_data_t));
225
226   index = flow - hm->flows;
227   strncpy ((char *) flow->flow_name, (char *) flow_name, 31);
228
229   if (!encap)
230     IOAM_SET_DECAP (index);
231
232   for (i = 0; i < 255; i++)
233     {
234       if (hm->flow_handler[i])
235         flow->ctx[i] = hm->flow_handler[i] (index, 1);
236     }
237   return (index);
238 }
239
240 always_inline ip6_hop_by_hop_option_t *
241 ip6_hbh_get_option (ip6_hop_by_hop_header_t * hbh0, u8 option_to_search)
242 {
243   ip6_hop_by_hop_option_t *opt0, *limit0;
244   u8 type0;
245
246   if (!hbh0)
247     return NULL;
248
249   opt0 = (ip6_hop_by_hop_option_t *) (hbh0 + 1);
250   limit0 = (ip6_hop_by_hop_option_t *)
251     ((u8 *) hbh0 + ((hbh0->length + 1) << 3));
252
253   /* Scan the set of h-b-h options, process ones that we understand */
254   while (opt0 < limit0)
255     {
256       type0 = opt0->type;
257       switch (type0)
258         {
259         case 0:         /* Pad1 */
260           opt0 = (ip6_hop_by_hop_option_t *) ((u8 *) opt0) + 1;
261           continue;
262         case 1:         /* PadN */
263           break;
264         default:
265           if (type0 == option_to_search)
266             return opt0;
267           break;
268         }
269       opt0 =
270         (ip6_hop_by_hop_option_t *) (((u8 *) opt0) + opt0->length +
271                                      sizeof (ip6_hop_by_hop_option_t));
272     }
273   return NULL;
274 }
275
276 #endif /* __included_ip6_hop_by_hop_ioam_h__ */
277
278 /*
279  * fd.io coding-style-patch-verification: ON
280  *
281  * Local Variables:
282  * eval: (c-set-style "gnu")
283  * End:
284  */