Line data Source code
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 0 : is_zero_ip6_address (ip6_address_t * a)
142 : {
143 0 : 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 0 : get_flow_data_from_flow_ctx (u32 flow_ctx, u8 option)
196 : {
197 0 : flow_data_t *flow = NULL;
198 0 : ip6_hop_by_hop_ioam_main_t *hm = &ip6_hop_by_hop_ioam_main;
199 : u32 index;
200 :
201 0 : index = IOAM_MASK_DECAP_BIT (flow_ctx);
202 : //flow = pool_elt_at_index (hm->flows, index);
203 0 : flow = &hm->flows[index];
204 0 : 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 0 : ioam_flow_add (u8 encap, u8 * flow_name)
217 : {
218 0 : ip6_hop_by_hop_ioam_main_t *hm = &ip6_hop_by_hop_ioam_main;
219 0 : flow_data_t *flow = 0;
220 0 : u32 index = 0;
221 : u8 i;
222 :
223 0 : pool_get (hm->flows, flow);
224 0 : clib_memset (flow, 0, sizeof (flow_data_t));
225 :
226 0 : index = flow - hm->flows;
227 0 : strncpy ((char *) flow->flow_name, (char *) flow_name, 31);
228 :
229 0 : if (!encap)
230 0 : IOAM_SET_DECAP (index);
231 :
232 0 : for (i = 0; i < 255; i++)
233 : {
234 0 : if (hm->flow_handler[i])
235 0 : flow->ctx[i] = hm->flow_handler[i] (index, 1);
236 : }
237 0 : return (index);
238 : }
239 :
240 : always_inline ip6_hop_by_hop_option_t *
241 0 : 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 0 : if (!hbh0)
247 0 : return NULL;
248 :
249 0 : opt0 = (ip6_hop_by_hop_option_t *) (hbh0 + 1);
250 0 : limit0 = (ip6_hop_by_hop_option_t *)
251 0 : ((u8 *) hbh0 + ((hbh0->length + 1) << 3));
252 :
253 : /* Scan the set of h-b-h options, process ones that we understand */
254 0 : while (opt0 < limit0)
255 : {
256 0 : type0 = opt0->type;
257 0 : switch (type0)
258 : {
259 0 : case 0: /* Pad1 */
260 0 : opt0 = (ip6_hop_by_hop_option_t *) ((u8 *) opt0) + 1;
261 0 : continue;
262 0 : case 1: /* PadN */
263 0 : break;
264 0 : default:
265 0 : if (type0 == option_to_search)
266 0 : return opt0;
267 0 : break;
268 : }
269 0 : opt0 =
270 0 : (ip6_hop_by_hop_option_t *) (((u8 *) opt0) + opt0->length +
271 : sizeof (ip6_hop_by_hop_option_t));
272 : }
273 0 : 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 : */
|