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