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 : /*
16 : * ip/ip6.h: ip6 main include file
17 : *
18 : * Copyright (c) 2008 Eliot Dresselhaus
19 : *
20 : * Permission is hereby granted, free of charge, to any person obtaining
21 : * a copy of this software and associated documentation files (the
22 : * "Software"), to deal in the Software without restriction, including
23 : * without limitation the rights to use, copy, modify, merge, publish,
24 : * distribute, sublicense, and/or sell copies of the Software, and to
25 : * permit persons to whom the Software is furnished to do so, subject to
26 : * the following conditions:
27 : *
28 : * The above copyright notice and this permission notice shall be
29 : * included in all copies or substantial portions of the Software.
30 : *
31 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
32 : * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
33 : * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
34 : * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
35 : * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
36 : * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
37 : * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
38 : */
39 :
40 : #ifndef included_ip_ip6_h
41 : #define included_ip_ip6_h
42 :
43 : #include <stdbool.h>
44 :
45 : #include <vlib/buffer.h>
46 :
47 : #include <vnet/ip/ip6_packet.h>
48 : #include <vnet/ip/ip46_address.h>
49 : #include <vnet/ip/ip6_hop_by_hop_packet.h>
50 : #include <vnet/ip/lookup.h>
51 : #include <vnet/ip/ip_interface.h>
52 : #include <vnet/ip/ip_flow_hash.h>
53 :
54 : typedef struct
55 : {
56 : ip6_address_t addr;
57 : u32 dst_address_length;
58 : u32 vrf_index;
59 : } ip6_fib_key_t;
60 :
61 : typedef struct
62 : {
63 : /* required for pool_get_aligned. */
64 : CLIB_CACHE_LINE_ALIGN_MARK (cacheline0);
65 :
66 : /* Table ID (hash key) for this FIB. */
67 : u32 table_id;
68 :
69 : /* Index into FIB vector. */
70 : u32 index;
71 : } ip6_fib_t;
72 :
73 : typedef struct ip6_mfib_t
74 : {
75 : /* required for pool_get_aligned. */
76 : CLIB_CACHE_LINE_ALIGN_MARK (cacheline0);
77 :
78 : /* Table ID (hash key) for this FIB. */
79 : u32 table_id;
80 :
81 : /* Index into FIB vector. */
82 : u32 index;
83 : } ip6_mfib_t;
84 :
85 : struct ip6_main_t;
86 :
87 : typedef void (ip6_add_del_interface_address_function_t)
88 : (struct ip6_main_t * im,
89 : uword opaque,
90 : u32 sw_if_index,
91 : ip6_address_t * address,
92 : u32 address_length, u32 if_address_index, u32 is_del);
93 :
94 : typedef struct
95 : {
96 : ip6_add_del_interface_address_function_t *function;
97 : uword function_opaque;
98 : } ip6_add_del_interface_address_callback_t;
99 :
100 : typedef void (ip6_table_bind_function_t)
101 : (struct ip6_main_t * im,
102 : uword opaque, u32 sw_if_index, u32 new_fib_index, u32 old_fib_index);
103 :
104 : typedef struct
105 : {
106 : ip6_table_bind_function_t *function;
107 : uword function_opaque;
108 : } ip6_table_bind_callback_t;
109 :
110 : typedef struct ip6_main_t
111 : {
112 : ip_lookup_main_t lookup_main;
113 :
114 : /* Pool of FIBs. */
115 : struct fib_table_t_ *fibs;
116 :
117 : /* Pool of V6 FIBs. */
118 : ip6_fib_t *v6_fibs;
119 :
120 : /** Vector of MFIBs. */
121 : struct mfib_table_t_ *mfibs;
122 :
123 : /* Network byte orders subnet mask for each prefix length */
124 : ip6_address_t fib_masks[129];
125 :
126 : /* Table index indexed by software interface. */
127 : u32 *fib_index_by_sw_if_index;
128 :
129 : /** Table index indexed by software interface. */
130 : u32 *mfib_index_by_sw_if_index;
131 :
132 : /* IP6 enabled count by software interface */
133 : u8 *ip_enabled_by_sw_if_index;
134 :
135 : /* Hash table mapping table id to fib index.
136 : ID space is not necessarily dense; index space is dense. */
137 : uword *fib_index_by_table_id;
138 :
139 : /** Hash table mapping table id to multicast fib index.
140 : ID space is not necessarily dense; index space is dense. */
141 : uword *mfib_index_by_table_id;
142 :
143 : /* Hash table mapping interface rewrite adjacency index by sw if index. */
144 : uword *interface_route_adj_index_by_sw_if_index;
145 :
146 : /* Functions to call when interface address changes. */
147 : ip6_add_del_interface_address_callback_t
148 : * add_del_interface_address_callbacks;
149 :
150 : /** Functions to call when interface to table biding changes. */
151 : ip6_table_bind_callback_t *table_bind_callbacks;
152 :
153 : /* Seed for Jenkins hash used to compute ip6 flow hash. */
154 : u32 flow_hash_seed;
155 :
156 : struct
157 : {
158 : /* TTL to use for host generated packets. */
159 : u8 ttl;
160 :
161 : u8 pad[3];
162 : } host_config;
163 :
164 : /* HBH processing enabled? */
165 : u8 hbh_enabled;
166 : } ip6_main_t;
167 :
168 : #define ND_THROTTLE_BITS 512
169 :
170 : /* Global ip6 main structure. */
171 : extern ip6_main_t ip6_main;
172 :
173 : /* Global ip6 input node. Errors get attached to ip6 input node. */
174 : extern vlib_node_registration_t ip6_input_node;
175 : extern vlib_node_registration_t ip6_rewrite_node;
176 : extern vlib_node_registration_t ip6_rewrite_mcast_node;
177 : extern vlib_node_registration_t ip6_rewrite_local_node;
178 : extern vlib_node_registration_t ip6_discover_neighbor_node;
179 : extern vlib_node_registration_t ip6_glean_node;
180 : extern vlib_node_registration_t ip6_midchain_node;
181 : extern vlib_node_registration_t ip6_punt_node;
182 :
183 : extern void ip6_forward_next_trace (vlib_main_t * vm,
184 : vlib_node_runtime_t * node,
185 : vlib_frame_t * frame,
186 : vlib_rx_or_tx_t which_adj_index);
187 :
188 : always_inline uword
189 28058 : ip6_destination_matches_route (const ip6_main_t * im,
190 : const ip6_address_t * key,
191 : const ip6_address_t * dest, uword dest_length)
192 : {
193 : int i;
194 72274 : for (i = 0; i < ARRAY_LEN (key->as_uword); i++)
195 : {
196 50174 : if ((key->as_uword[i] ^ dest->as_uword[i]) & im->
197 50174 : fib_masks[dest_length].as_uword[i])
198 5958 : return 0;
199 : }
200 22100 : return 1;
201 : }
202 :
203 : always_inline uword
204 : ip6_destination_matches_interface (ip6_main_t * im,
205 : ip6_address_t * key,
206 : ip_interface_address_t * ia)
207 : {
208 : ip6_address_t *a = ip_interface_address_get_address (&im->lookup_main, ia);
209 : return ip6_destination_matches_route (im, key, a, ia->address_length);
210 : }
211 :
212 : /* As above but allows for unaligned destinations (e.g. works right from IP header of packet). */
213 : always_inline uword
214 : ip6_unaligned_destination_matches_route (ip6_main_t * im,
215 : ip6_address_t * key,
216 : ip6_address_t * dest,
217 : uword dest_length)
218 : {
219 : int i;
220 : for (i = 0; i < ARRAY_LEN (key->as_uword); i++)
221 : {
222 : if ((clib_mem_unaligned (&key->as_uword[i], uword) ^ dest->as_uword[i])
223 : & im->fib_masks[dest_length].as_uword[i])
224 : return 0;
225 : }
226 : return 1;
227 : }
228 :
229 : /* Find interface address which matches destination. */
230 : always_inline ip6_address_t *
231 0 : ip6_interface_address_matching_destination (ip6_main_t * im,
232 : const ip6_address_t * dst,
233 : u32 sw_if_index,
234 : ip_interface_address_t **
235 : result_ia)
236 : {
237 0 : ip_lookup_main_t *lm = &im->lookup_main;
238 : ip_interface_address_t *ia;
239 0 : ip6_address_t *result = 0;
240 :
241 : /* *INDENT-OFF* */
242 0 : foreach_ip_interface_address (lm, ia, sw_if_index,
243 : 1 /* honor unnumbered */,
244 : ({
245 : ip6_address_t * a = ip_interface_address_get_address (lm, ia);
246 : if (ip6_destination_matches_route (im, dst, a, ia->address_length))
247 : {
248 : result = a;
249 : break;
250 : }
251 : }));
252 : /* *INDENT-ON* */
253 0 : if (result_ia)
254 0 : *result_ia = result ? ia : 0;
255 0 : return result;
256 : }
257 :
258 : clib_error_t *ip6_add_del_interface_address (vlib_main_t * vm,
259 : u32 sw_if_index,
260 : ip6_address_t * address,
261 : u32 address_length, u32 is_del);
262 : void ip6_sw_interface_enable_disable (u32 sw_if_index, u32 is_enable);
263 :
264 : /**
265 : * @brief get first IPv6 interface address
266 : */
267 : ip6_address_t *ip6_interface_first_address (ip6_main_t * im, u32 sw_if_index);
268 :
269 : int ip6_address_compare (ip6_address_t * a1, ip6_address_t * a2);
270 :
271 : uword
272 : ip6_udp_register_listener (vlib_main_t * vm,
273 : u16 dst_port, u32 next_node_index);
274 :
275 : u16 ip6_tcp_udp_icmp_compute_checksum (vlib_main_t * vm, vlib_buffer_t * p0,
276 : ip6_header_t * ip0,
277 : int *bogus_lengthp);
278 :
279 : void ip6_register_protocol (u32 protocol, u32 node_index);
280 : void ip6_unregister_protocol (u32 protocol);
281 : void ip6_local_hop_by_hop_register_protocol (u32 protocol, u32 node_index);
282 :
283 : serialize_function_t serialize_vnet_ip6_main, unserialize_vnet_ip6_main;
284 :
285 : u8 *format_ip6_forward_next_trace (u8 * s, va_list * args);
286 :
287 : u32 ip6_tcp_udp_icmp_validate_checksum (vlib_main_t * vm, vlib_buffer_t * p0);
288 :
289 : void ip6_punt_policer_add_del (u8 is_add, u32 policer_index);
290 : void ip6_punt_redirect_add_paths (u32 rx_sw_if_index,
291 : const fib_route_path_t *paths);
292 : void ip6_punt_redirect_del (u32 rx_sw_if_index);
293 :
294 : int vnet_set_ip6_classify_intfc (vlib_main_t * vm, u32 sw_if_index,
295 : u32 table_index);
296 : extern vlib_node_registration_t ip6_lookup_node;
297 :
298 : u8 *format_ip6_hop_by_hop_ext_hdr (u8 * s, va_list * args);
299 : /*
300 : * Hop-by-Hop handling
301 : */
302 : typedef struct
303 : {
304 : /* Array of function pointers to HBH option handling routines */
305 : int (*options[256]) (vlib_buffer_t * b, ip6_header_t * ip,
306 : ip6_hop_by_hop_option_t * opt);
307 : u8 *(*trace[256]) (u8 * s, ip6_hop_by_hop_option_t * opt);
308 : uword next_override;
309 : } ip6_hop_by_hop_main_t;
310 :
311 : extern ip6_hop_by_hop_main_t ip6_hop_by_hop_main;
312 :
313 : int ip6_hbh_register_option (u8 option,
314 : int options (vlib_buffer_t * b,
315 : ip6_header_t * ip,
316 : ip6_hop_by_hop_option_t * opt),
317 : u8 * trace (u8 * s,
318 : ip6_hop_by_hop_option_t * opt));
319 : int ip6_hbh_unregister_option (u8 option);
320 : void ip6_hbh_set_next_override (uword next);
321 :
322 : always_inline u32
323 42 : vlib_buffer_get_ip6_fib_index (vlib_buffer_t * b)
324 : {
325 : u32 fib_index, sw_if_index;
326 42 : sw_if_index = vnet_buffer (b)->sw_if_index[VLIB_RX];
327 42 : fib_index = vnet_buffer (b)->sw_if_index[VLIB_TX];
328 : return (fib_index == (u32) ~ 0) ?
329 42 : vec_elt (ip6_main.fib_index_by_sw_if_index, sw_if_index) : fib_index;
330 : }
331 : #endif /* included_ip_ip6_h */
332 :
333 : /*
334 : * fd.io coding-style-patch-verification: ON
335 : *
336 : * Local Variables:
337 : * eval: (c-set-style "gnu")
338 : * End:
339 : */
|