Line data Source code
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 : * vnet/buffer.h: vnet buffer flags
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_vnet_buffer_h
41 : #define included_vnet_buffer_h
42 :
43 : #include <vlib/vlib.h>
44 :
45 : /**
46 : * Flags that are set in the high order bits of ((vlib_buffer*)b)->flags
47 : *
48 : */
49 : #define foreach_vnet_buffer_flag \
50 : _ (1, L4_CHECKSUM_COMPUTED, "l4-cksum-computed", 1) \
51 : _ (2, L4_CHECKSUM_CORRECT, "l4-cksum-correct", 1) \
52 : _ (3, VLAN_2_DEEP, "vlan-2-deep", 1) \
53 : _ (4, VLAN_1_DEEP, "vlan-1-deep", 1) \
54 : _ (5, SPAN_CLONE, "span-clone", 1) \
55 : _ (6, LOOP_COUNTER_VALID, "loop-counter-valid", 0) \
56 : _ (7, LOCALLY_ORIGINATED, "local", 1) \
57 : _ (8, IS_IP4, "ip4", 1) \
58 : _ (9, IS_IP6, "ip6", 1) \
59 : _ (10, OFFLOAD, "offload", 0) \
60 : _ (11, IS_NATED, "natted", 1) \
61 : _ (12, L2_HDR_OFFSET_VALID, "l2_hdr_offset_valid", 0) \
62 : _ (13, L3_HDR_OFFSET_VALID, "l3_hdr_offset_valid", 0) \
63 : _ (14, L4_HDR_OFFSET_VALID, "l4_hdr_offset_valid", 0) \
64 : _ (15, FLOW_REPORT, "flow-report", 1) \
65 : _ (16, IS_DVR, "dvr", 1) \
66 : _ (17, QOS_DATA_VALID, "qos-data-valid", 0) \
67 : _ (18, GSO, "gso", 0) \
68 : _ (19, AVAIL1, "avail1", 1) \
69 : _ (20, AVAIL2, "avail2", 1) \
70 : _ (21, AVAIL3, "avail3", 1) \
71 : _ (22, AVAIL4, "avail4", 1) \
72 : _ (23, AVAIL5, "avail5", 1) \
73 : _ (24, AVAIL6, "avail6", 1) \
74 : _ (25, AVAIL7, "avail7", 1) \
75 : _ (26, AVAIL8, "avail8", 1) \
76 : _ (27, AVAIL9, "avail9", 1)
77 :
78 : /*
79 : * Please allocate the FIRST available bit, redefine
80 : * AVAIL 1 ... AVAILn-1, and remove AVAILn. Please maintain the
81 : * VNET_BUFFER_FLAGS_ALL_AVAIL definition.
82 : */
83 :
84 : #define VNET_BUFFER_FLAGS_ALL_AVAIL \
85 : (VNET_BUFFER_F_AVAIL1 | VNET_BUFFER_F_AVAIL2 | VNET_BUFFER_F_AVAIL3 | \
86 : VNET_BUFFER_F_AVAIL4 | VNET_BUFFER_F_AVAIL5 | VNET_BUFFER_F_AVAIL6 | \
87 : VNET_BUFFER_F_AVAIL7 | VNET_BUFFER_F_AVAIL8 | VNET_BUFFER_F_AVAIL9)
88 :
89 : #define VNET_BUFFER_FLAGS_VLAN_BITS \
90 : (VNET_BUFFER_F_VLAN_1_DEEP | VNET_BUFFER_F_VLAN_2_DEEP)
91 :
92 : enum
93 : {
94 : #define _(bit, name, s, v) VNET_BUFFER_F_##name = (1 << LOG2_VLIB_BUFFER_FLAG_USER(bit)),
95 : foreach_vnet_buffer_flag
96 : #undef _
97 : };
98 :
99 : enum
100 : {
101 : #define _(bit, name, s, v) VNET_BUFFER_F_LOG2_##name = LOG2_VLIB_BUFFER_FLAG_USER(bit),
102 : foreach_vnet_buffer_flag
103 : #undef _
104 : };
105 :
106 : /* Make sure that the vnet and vlib bits are disjoint */
107 : STATIC_ASSERT (((VNET_BUFFER_FLAGS_ALL_AVAIL & VLIB_BUFFER_FLAGS_ALL) == 0),
108 : "VLIB / VNET buffer flags overlap");
109 :
110 : #define foreach_vnet_buffer_offload_flag \
111 : _ (0, IP_CKSUM, "offload-ip-cksum", 1) \
112 : _ (1, TCP_CKSUM, "offload-tcp-cksum", 1) \
113 : _ (2, UDP_CKSUM, "offload-udp-cksum", 1) \
114 : _ (3, OUTER_IP_CKSUM, "offload-outer-ip-cksum", 1) \
115 : _ (4, OUTER_UDP_CKSUM, "offload-outer-udp-cksum", 1) \
116 : _ (5, TNL_VXLAN, "offload-vxlan-tunnel", 1) \
117 : _ (6, TNL_IPIP, "offload-ipip-tunnel", 1)
118 :
119 : typedef enum
120 : {
121 : #define _(bit, name, s, v) VNET_BUFFER_OFFLOAD_F_##name = (1 << bit),
122 : foreach_vnet_buffer_offload_flag
123 : #undef _
124 : } vnet_buffer_oflags_t;
125 :
126 : #define VNET_BUFFER_OFFLOAD_F_TNL_MASK \
127 : (VNET_BUFFER_OFFLOAD_F_TNL_VXLAN | VNET_BUFFER_OFFLOAD_F_TNL_IPIP)
128 :
129 : #define foreach_buffer_opaque_union_subtype \
130 : _(ip) \
131 : _(l2) \
132 : _(l2t) \
133 : _(l2_classify) \
134 : _(policer) \
135 : _(ipsec) \
136 : _(map) \
137 : _(map_t) \
138 : _(ip_frag) \
139 : _(mpls) \
140 : _(tcp)
141 :
142 : /*
143 : * vnet stack buffer opaque array overlay structure.
144 : * The vnet_buffer_opaque_t *must* be the same size as the
145 : * vlib_buffer_t "opaque" structure member, 32 bytes.
146 : *
147 : * When adding a union type, please add a stanza to
148 : * foreach_buffer_opaque_union_subtype (directly above).
149 : * Code in vnet_interface_init(...) verifies the size
150 : * of the union, and will announce any deviations in an
151 : * impossible-to-miss manner.
152 : */
153 : typedef struct
154 : {
155 : u32 sw_if_index[VLIB_N_RX_TX];
156 : i16 l2_hdr_offset;
157 : i16 l3_hdr_offset;
158 : i16 l4_hdr_offset;
159 : u8 feature_arc_index;
160 : /* offload flags */
161 : vnet_buffer_oflags_t oflags : 8;
162 :
163 : union
164 : {
165 : /* IP4/6 buffer opaque. */
166 : struct
167 : {
168 : /* Adjacency from destination IP address lookup [VLIB_TX].
169 : Adjacency from source IP address lookup [VLIB_RX].
170 : This gets set to ~0 until source lookup is performed. */
171 : u32 adj_index[VLIB_N_RX_TX];
172 :
173 : union
174 : {
175 : struct
176 : {
177 : /* Flow hash value for this packet computed from IP src/dst address
178 : protocol and ports. */
179 : u32 flow_hash;
180 :
181 : union
182 : {
183 : /* next protocol */
184 : u32 save_protocol;
185 :
186 : /* Hint for transport protocols */
187 : u32 fib_index;
188 : };
189 :
190 : /* Rewrite length */
191 : u8 save_rewrite_length;
192 :
193 : union
194 : {
195 : /* sw_if_index of the local interface the buffer was received on
196 : * - if hitting a DPO_RECEIVE - it is set in ip[46]-receive.
197 : * This is ~0 if the dpo is not a receive dpo, or if the
198 : * interface is not specified (e.g. route add via local) */
199 : u32 rx_sw_if_index;
200 :
201 : /* MFIB RPF ID */
202 : u32 rpf_id;
203 : };
204 : };
205 :
206 : /* ICMP */
207 : struct
208 : {
209 : u8 type;
210 : u8 code;
211 : u32 data;
212 : } icmp;
213 :
214 : /* reassembly */
215 : union
216 : {
217 : /* group input/output to simplify the code, this way
218 : * we can handoff while keeping input variables intact */
219 : struct
220 : {
221 : /* input variables */
222 : struct
223 : {
224 : u32 next_index; /* index of next node - used by custom apps */
225 : u32 error_next_index; /* index of next node if error - used by custom apps */
226 : };
227 : /* handoff variables */
228 : struct
229 : {
230 : u16 owner_thread_index;
231 : };
232 : };
233 : /* output variables */
234 : struct
235 : {
236 : union
237 : {
238 : /* shallow virtual reassembly output variables */
239 : struct
240 : {
241 : u16 l4_src_port; /* tcp/udp/icmp src port */
242 : u16 l4_dst_port; /* tcp/udp/icmp dst port */
243 : u32 tcp_ack_number;
244 : u8 save_rewrite_length;
245 : u8 ip_proto; /* protocol in ip header */
246 : u8 icmp_type_or_tcp_flags;
247 : u8 is_non_first_fragment : 1;
248 : u8 l4_layer_truncated : 7;
249 : u32 tcp_seq_number;
250 : };
251 : /* full reassembly output variables */
252 : struct
253 : {
254 : u16 estimated_mtu; /* estimated MTU calculated during reassembly */
255 : };
256 : };
257 : };
258 : /* internal variables used during reassembly */
259 : struct
260 : {
261 : u16 fragment_first;
262 : u16 fragment_last;
263 : u16 range_first;
264 : u16 range_last;
265 : u32 next_range_bi;
266 : u16 ip6_frag_hdr_offset;
267 : };
268 : } reass;
269 : };
270 : } ip;
271 :
272 : /*
273 : * MPLS:
274 : * data copied from the MPLS header that was popped from the packet
275 : * during the look-up.
276 : */
277 : struct
278 : {
279 : /* do not overlay w/ ip.adj_index[0,1] nor flow hash */
280 : u32 pad[VLIB_N_RX_TX + 1];
281 : u8 ttl;
282 : u8 exp;
283 : u8 first;
284 : u8 pyld_proto:3; /* dpo_proto_t */
285 : u8 rsvd:5;
286 : /* Rewrite length */
287 : u8 save_rewrite_length;
288 : /* Save the mpls header length including all label stack */
289 : u8 mpls_hdr_length;
290 : /*
291 : * BIER - the number of bytes in the header.
292 : * the len field in the header is not authoritative. It's the
293 : * value in the table that counts.
294 : */
295 : struct
296 : {
297 : u8 n_bytes;
298 : } bier;
299 : } mpls;
300 :
301 : /* l2 bridging path, only valid there */
302 : struct opaque_l2
303 : {
304 : u32 feature_bitmap;
305 : u16 bd_index; /* bridge-domain index */
306 : u16 l2fib_sn; /* l2fib bd/int seq_num */
307 : u8 l2_len; /* ethernet header length */
308 : u8 shg; /* split-horizon group */
309 : u8 bd_age; /* aging enabled */
310 : } l2;
311 :
312 : /* l2tpv3 softwire encap, only valid there */
313 : struct
314 : {
315 : u32 pad[4]; /* do not overlay w/ ip.adj_index[0,1] */
316 : u8 next_index;
317 : u32 session_index;
318 : } l2t;
319 :
320 : /* L2 classify */
321 : struct
322 : {
323 : u32 pad[4]; /* do not overlay w/ ip.fib_index nor l2 */
324 : union
325 : {
326 : u32 table_index;
327 : u32 opaque_index;
328 : };
329 : u32 hash;
330 : } l2_classify;
331 :
332 : /* vnet policer */
333 : struct
334 : {
335 : u32 pad[8 - VLIB_N_RX_TX - 1]; /* to end of opaque */
336 : u32 index;
337 : } policer;
338 :
339 : /* interface output features */
340 : struct
341 : {
342 : /* don't overlap the adjcencies nor flow-hash */
343 : u32 __pad[3];
344 : u32 sad_index;
345 : u32 protect_index;
346 : u16 thread_index;
347 : } ipsec;
348 :
349 : /* MAP */
350 : struct
351 : {
352 : u16 mtu;
353 : } map;
354 :
355 : /* MAP-T */
356 : struct
357 : {
358 : u32 map_domain_index;
359 : struct
360 : {
361 : u32 saddr, daddr;
362 : u16 frag_offset; //Fragmentation header offset
363 : u16 l4_offset; //L4 header overall offset
364 : u8 l4_protocol; //The final protocol number
365 : } v6; //Used by ip6_map_t only
366 : u16 checksum_offset; //L4 checksum overall offset
367 : u16 mtu; //Exit MTU
368 : } map_t;
369 :
370 : /* IP Fragmentation */
371 : struct
372 : {
373 : u32 pad[2]; /* do not overlay w/ ip.adj_index[0,1] */
374 : u16 mtu;
375 : u8 next_index;
376 : u8 flags; //See ip_frag.h
377 : } ip_frag;
378 :
379 : /* COP - configurable junk filter(s) */
380 : struct
381 : {
382 : /* Current configuration index. */
383 : u32 current_config_index;
384 : } cop;
385 :
386 : /* LISP */
387 : struct
388 : {
389 : /* overlay address family */
390 : u16 overlay_afi;
391 : } lisp;
392 :
393 : /* TCP */
394 : struct
395 : {
396 : u32 connection_index;
397 : union
398 : {
399 : u32 seq_number;
400 : u32 next_node_opaque;
401 : };
402 : u32 seq_end;
403 : u32 ack_number;
404 : u16 hdr_offset; /**< offset relative to ip hdr */
405 : u16 data_offset; /**< offset relative to ip hdr */
406 : u16 data_len; /**< data len */
407 : u8 flags;
408 : } tcp;
409 :
410 : /* SNAT */
411 : struct
412 : {
413 : u32 flags;
414 : u32 required_thread_index;
415 : } snat;
416 :
417 : u32 unused[6];
418 : };
419 : } vnet_buffer_opaque_t;
420 :
421 : #define VNET_REWRITE_TOTAL_BYTES 128
422 : STATIC_ASSERT (VNET_REWRITE_TOTAL_BYTES <= VLIB_BUFFER_PRE_DATA_SIZE,
423 : "VNET_REWRITE_TOTAL_BYTES too big");
424 :
425 : STATIC_ASSERT (STRUCT_SIZE_OF (vnet_buffer_opaque_t, ip.save_rewrite_length)
426 : == STRUCT_SIZE_OF (vnet_buffer_opaque_t,
427 : ip.reass.save_rewrite_length)
428 : && STRUCT_SIZE_OF (vnet_buffer_opaque_t,
429 : ip.reass.save_rewrite_length) ==
430 : STRUCT_SIZE_OF (vnet_buffer_opaque_t, mpls.save_rewrite_length)
431 : && STRUCT_SIZE_OF (vnet_buffer_opaque_t,
432 : mpls.save_rewrite_length) == 1
433 : && VNET_REWRITE_TOTAL_BYTES < UINT8_MAX,
434 : "save_rewrite_length member must be able to hold the max value of rewrite length");
435 :
436 : STATIC_ASSERT (STRUCT_OFFSET_OF (vnet_buffer_opaque_t, ip.save_rewrite_length)
437 : == STRUCT_OFFSET_OF (vnet_buffer_opaque_t,
438 : ip.reass.save_rewrite_length)
439 : && STRUCT_OFFSET_OF (vnet_buffer_opaque_t,
440 : mpls.save_rewrite_length) ==
441 : STRUCT_OFFSET_OF (vnet_buffer_opaque_t,
442 : ip.reass.save_rewrite_length),
443 : "save_rewrite_length must be aligned so that reass doesn't overwrite it");
444 :
445 : /*
446 : * The opaque field of the vlib_buffer_t is interpreted as a
447 : * vnet_buffer_opaque_t. Hence it should be big enough to accommodate one.
448 : */
449 : STATIC_ASSERT (sizeof (vnet_buffer_opaque_t) <=
450 : STRUCT_SIZE_OF (vlib_buffer_t, opaque),
451 : "VNET buffer meta-data too large for vlib_buffer");
452 :
453 : #define vnet_buffer(b) ((vnet_buffer_opaque_t *) (b)->opaque)
454 :
455 : /* Full cache line (64 bytes) of additional space */
456 : typedef struct
457 : {
458 : /**
459 : * QoS marking data that needs to persist from the recording nodes
460 : * (nominally in the ingress path) to the marking node (in the
461 : * egress path)
462 : */
463 : struct
464 : {
465 : u8 bits;
466 : u8 source;
467 : } qos;
468 :
469 : u8 loop_counter;
470 : u8 __unused[5];
471 :
472 : /**
473 : * The L4 payload size set on input on GSO enabled interfaces
474 : * when we receive a GSO packet (a chain of buffers with the first one
475 : * having GSO bit set), and needs to persist all the way to the interface-output,
476 : * in case the egress interface is not GSO-enabled - then we need to perform
477 : * the segmentation, and use this value to cut the payload appropriately.
478 : */
479 : struct
480 : {
481 : u16 gso_size;
482 : /* size of L4 prototol header */
483 : u16 gso_l4_hdr_sz;
484 : i16 outer_l3_hdr_offset;
485 : i16 outer_l4_hdr_offset;
486 : };
487 :
488 : struct
489 : {
490 : u32 arc_next;
491 : union
492 : {
493 : u32 cached_session_index;
494 : u32 cached_dst_nat_session_index;
495 : };
496 : } nat;
497 :
498 : u32 unused[8];
499 : } vnet_buffer_opaque2_t;
500 :
501 : #define vnet_buffer2(b) ((vnet_buffer_opaque2_t *) (b)->opaque2)
502 :
503 : /*
504 : * The opaque2 field of the vlib_buffer_t is interpreted as a
505 : * vnet_buffer_opaque2_t. Hence it should be big enough to accommodate one.
506 : */
507 : STATIC_ASSERT (sizeof (vnet_buffer_opaque2_t) ==
508 : STRUCT_SIZE_OF (vlib_buffer_t, opaque2),
509 : "VNET buffer opaque2 meta-data too large for vlib_buffer");
510 :
511 : #define gso_mtu_sz(b) (vnet_buffer2(b)->gso_size + \
512 : vnet_buffer2(b)->gso_l4_hdr_sz + \
513 : vnet_buffer(b)->l4_hdr_offset - \
514 : vnet_buffer (b)->l3_hdr_offset)
515 :
516 : format_function_t format_vnet_buffer_no_chain;
517 : format_function_t format_vnet_buffer;
518 : format_function_t format_vnet_buffer_offload;
519 : format_function_t format_vnet_buffer_flags;
520 : format_function_t format_vnet_buffer_opaque;
521 : format_function_t format_vnet_buffer_opaque2;
522 :
523 : static_always_inline void
524 5636794 : vnet_buffer_offload_flags_set (vlib_buffer_t *b, vnet_buffer_oflags_t oflags)
525 : {
526 5636794 : if (b->flags & VNET_BUFFER_F_OFFLOAD)
527 : {
528 : /* add a flag to existing offload */
529 1121615 : vnet_buffer (b)->oflags |= oflags;
530 : }
531 : else
532 : {
533 : /* no offload yet: reset offload flags to new value */
534 4515179 : vnet_buffer (b)->oflags = oflags;
535 4515179 : b->flags |= VNET_BUFFER_F_OFFLOAD;
536 : }
537 5636794 : }
538 :
539 : static_always_inline void
540 11559903 : vnet_buffer_offload_flags_clear (vlib_buffer_t *b, vnet_buffer_oflags_t oflags)
541 : {
542 11559903 : vnet_buffer (b)->oflags &= ~oflags;
543 11559903 : if (0 == vnet_buffer (b)->oflags)
544 11559903 : b->flags &= ~VNET_BUFFER_F_OFFLOAD;
545 11559903 : }
546 :
547 : #endif /* included_vnet_buffer_h */
548 :
549 : /*
550 : * fd.io coding-style-patch-verification: ON
551 : *
552 : * Local Variables:
553 : * eval: (c-set-style "gnu")
554 : * End:
555 : */
|