tcp: timestamp adjustment
[vpp.git] / src / vnet / sctp / sctp_packet.h
1 /*
2  * Copyright (c) 2017 SUSE LLC.
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_vnet_sctp_packet_h
16 #define included_vnet_sctp_packet_h
17
18 #include <stdbool.h>
19
20 #include <vnet/ip/ip4_packet.h>
21 #include <vnet/ip/ip6_packet.h>
22
23 /*
24  * As per RFC 4960
25  * https://tools.ietf.org/html/rfc4960
26  */
27
28 /*
29  * 0                   1                   2                   3
30  * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
31  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
32  * |     Source Port Number        |     Destination Port Number   |
33  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
34  * |                      Verification Tag                         |
35  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
36  * |                           Checksum                            |
37  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
38  */
39 typedef struct
40 {
41   /*
42    * This is the SCTP sender's port number. It can be used by the
43    * receiver in combination with the source IP address, the SCTP
44    * destination port, and possibly the destination IP address to
45    * identify the association to which this packet belongs.
46    * The port number 0 MUST NOT be used.
47    */
48   u16 src_port;
49
50   /*
51    * This is the SCTP port number to which this packet is destined.
52    * The receiving host will use this port number to de-multiplex the
53    * SCTP packet to the correct receiving endpoint/application.
54    * The port number 0 MUST NOT be used.
55    */
56   u16 dst_port;
57
58   /*
59    * The receiver of this packet uses the Verification Tag to validate
60    * the sender of this SCTP packet.  On transmit, the value of this
61    * Verification Tag MUST be set to the value of the Initiate Tag
62    * received from the peer endpoint during the association
63    * initialization, with the following exceptions:
64    * - A packet containing an INIT chunk MUST have a zero Verification
65    *   Tag.
66    * - A packet containing a SHUTDOWN COMPLETE chunk with the T bit
67    *   set MUST have the Verification Tag copied from the packet with
68    *   the SHUTDOWN ACK chunk.
69    * - A packet containing an ABORT chunk may have the verification tag
70    *   copied from the packet that caused the ABORT to be sent.
71    * An INIT chunk MUST be the only chunk in the SCTP packet carrying it.
72    */
73   u32 verification_tag;
74
75   /*
76    * This field contains the checksum of this SCTP packet.
77    * SCTP uses the CRC32c algorithm.
78    */
79   u32 checksum;
80
81 } sctp_header_t;
82
83 always_inline void
84 vnet_set_sctp_src_port (sctp_header_t * h, u16 src_port)
85 {
86   h->src_port = clib_host_to_net_u16 (src_port);
87 }
88
89 always_inline u16
90 vnet_get_sctp_src_port (sctp_header_t * h)
91 {
92   return (clib_net_to_host_u16 (h->src_port));
93 }
94
95 always_inline void
96 vnet_set_sctp_dst_port (sctp_header_t * h, u16 dst_port)
97 {
98   h->dst_port = clib_host_to_net_u16 (dst_port);
99 }
100
101 always_inline u16
102 vnet_get_sctp_dst_port (sctp_header_t * h)
103 {
104   return (clib_net_to_host_u16 (h->dst_port));
105 }
106
107 always_inline void
108 vnet_set_sctp_verification_tag (sctp_header_t * h, u32 verification_tag)
109 {
110   h->verification_tag = clib_host_to_net_u32 (verification_tag);
111 }
112
113 always_inline u32
114 vnet_get_sctp_verification_tag (sctp_header_t * h)
115 {
116   return (clib_net_to_host_u32 (h->verification_tag));
117 }
118
119 always_inline void
120 vnet_set_sctp_checksum (sctp_header_t * h, u32 checksum)
121 {
122   h->checksum = clib_host_to_net_u32 (checksum);
123 }
124
125 always_inline u32
126 vnet_get_sctp_checksum (sctp_header_t * h)
127 {
128   return (clib_net_to_host_u32 (h->checksum));
129 }
130
131 /*
132  * Multiple chunks can be bundled into one SCTP packet up to the MTU
133  * size, except for the INIT, INIT ACK, and SHUTDOWN COMPLETE chunks.
134  * These chunks MUST NOT be bundled with any other chunk in a packet.
135  *
136  *
137  * 0                   1                   2                   3
138  * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
139  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
140  * |                        Common Header                          |
141  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
142  * |                          Chunk #1                             |
143  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
144  * |                           ...                                 |
145  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
146  * |                          Chunk #n                             |
147  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
148  */
149
150 typedef enum
151 {
152   DATA = 0,
153   INIT,
154   INIT_ACK,
155   SACK,
156   HEARTBEAT,
157   HEARTBEAT_ACK,
158   ABORT,
159   SHUTDOWN,
160   SHUTDOWN_ACK,
161   OPERATION_ERROR,
162   COOKIE_ECHO,
163   COOKIE_ACK,
164   ECNE,
165   CWR,
166   SHUTDOWN_COMPLETE,
167   UNKNOWN
168 } sctp_chunk_type;
169
170 /*
171  * 0                   1                   2                   3
172  * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
173  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
174  * |   Chunk Type  | Chunk  Flags  |        Chunk Length           |
175  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
176  */
177 typedef struct
178 {
179   /*
180    * This field identifies the type of information contained in the
181    * Chunk Value field. It takes a value from 0 to 254.
182    * The value of 255 is reserved for future use as an extension field.
183    *
184    * The values of Chunk Types are defined as follows:
185    * ID Value    Chunk Type
186    * -----       ----------
187    *  0          - Payload Data (DATA)
188    *  1          - Initiation (INIT)
189    *  2          - Initiation Acknowledgement (INIT ACK)
190    *  3          - Selective Acknowledgement (SACK)
191    *  4          - Heartbeat Request (HEARTBEAT)
192    *  5          - Heartbeat Acknowledgement (HEARTBEAT ACK)
193    *  6          - Abort (ABORT)
194    *  7          - Shutdown (SHUTDOWN)
195    *  8          - Shutdown Acknowledgement (SHUTDOWN ACK)
196    *  9          - Operation Error (ERROR)
197    *  10         - State Cookie (COOKIE ECHO)
198    *  11         - Cookie Acknowledgement (COOKIE ACK)
199    *  12         - Reserved for Explicit Congestion Notification Echo (ECNE)
200    *  13         - Reserved for Congestion Window Reduced (CWR)
201    *  14         - Shutdown Complete (SHUTDOWN COMPLETE)
202    *  15 to 62   - available
203    *  63         - reserved for IETF-defined Chunk Extensions
204    *  64 to 126  - available
205    *  127        - reserved for IETF-defined Chunk Extensions
206    *  128 to 190 - available
207    *  191        - reserved for IETF-defined Chunk Extensions
208    *  192 to 254 - available
209    *  255        - reserved for IETF-defined Chunk Extensions
210    *
211    *  Chunk Types are encoded such that the highest-order 2 bits specify
212    *  the action that must be taken if the processing endpoint does not
213    *  recognize the Chunk Type.
214    *  00 -  Stop processing this SCTP packet and discard it, do not
215    *  process any further chunks within it.
216    *  01 -  Stop processing this SCTP packet and discard it, do not
217    *  process any further chunks within it, and report the
218    *  unrecognized chunk in an 'Unrecognized Chunk Type'.
219    *  10 -  Skip this chunk and continue processing.
220    *  11 -  Skip this chunk and continue processing, but report in an
221    *  ERROR chunk using the 'Unrecognized Chunk Type' cause of error.
222    *
223    *  Note: The ECNE and CWR chunk types are reserved for future use of
224    *  Explicit Congestion Notification (ECN);
225    */
226   //u8 type;
227
228   /*
229    * The usage of these bits depends on the Chunk type as given by the
230    * Chunk Type field.  Unless otherwise specified, they are set to 0 on
231    * transmit and are ignored on receipt.
232    */
233   //u8 flags;
234
235   /*
236    * This value represents the size of the chunk in bytes, including
237    * the Chunk Type, Chunk Flags, Chunk Length, and Chunk Value fields.
238    * Therefore, if the Chunk Value field is zero-length, the Length
239    * field will be set to 4.
240    * The Chunk Length field does not count any chunk padding.
241    * Chunks (including Type, Length, and Value fields) are padded out
242    * by the sender with all zero bytes to be a multiple of 4 bytes
243    * long. This padding MUST NOT be more than 3 bytes in total. The
244    * Chunk Length value does not include terminating padding of the
245    * chunk. However, it does include padding of any variable-length
246    * parameter except the last parameter in the chunk. The receiver
247    * MUST ignore the padding.
248    *
249    * Note: A robust implementation should accept the chunk whether or
250    * not the final padding has been included in the Chunk Length.
251    */
252   //u16 length;
253
254   u32 params;
255
256 } sctp_chunks_common_hdr_t;
257
258 typedef struct
259 {
260   sctp_header_t hdr;
261   sctp_chunks_common_hdr_t common_hdr;
262
263 } sctp_full_hdr_t;
264
265 #define CHUNK_TYPE_MASK 0xFF000000
266 #define CHUNK_TYPE_SHIFT 24
267
268 #define CHUNK_FLAGS_MASK 0x00FF0000
269 #define CHUNK_FLAGS_SHIFT 16
270
271 #define CHUNK_UBIT_MASK 0x00040000
272 #define CHUNK_UBIT_SHIFT 18
273
274 #define CHUNK_BBIT_MASK 0x00020000
275 #define CHUNK_BBIT_SHIFT 17
276
277 #define CHUNK_EBIT_MASK 0x00010000
278 #define CHUNK_EBIT_SHIFT 16
279
280 #define CHUNK_LENGTH_MASK 0x0000FFFF
281 #define CHUNK_LENGTH_SHIFT 0
282
283 always_inline void
284 vnet_sctp_common_hdr_params_host_to_net (sctp_chunks_common_hdr_t * h)
285 {
286   h->params = clib_host_to_net_u32 (h->params);
287 }
288
289 always_inline void
290 vnet_sctp_common_hdr_params_net_to_host (sctp_chunks_common_hdr_t * h)
291 {
292   h->params = clib_net_to_host_u32 (h->params);
293 }
294
295 always_inline void
296 vnet_sctp_set_ubit (sctp_chunks_common_hdr_t * h)
297 {
298   h->params &= ~(CHUNK_UBIT_MASK);
299   h->params |= (1 << CHUNK_UBIT_SHIFT) & CHUNK_UBIT_MASK;
300 }
301
302 always_inline u8
303 vnet_sctp_get_ubit (sctp_chunks_common_hdr_t * h)
304 {
305   return ((h->params & CHUNK_UBIT_MASK) >> CHUNK_UBIT_SHIFT);
306 }
307
308 always_inline void
309 vnet_sctp_set_bbit (sctp_chunks_common_hdr_t * h)
310 {
311   h->params &= ~(CHUNK_BBIT_MASK);
312   h->params |= (1 << CHUNK_BBIT_SHIFT) & CHUNK_BBIT_MASK;
313 }
314
315 always_inline u8
316 vnet_sctp_get_bbit (sctp_chunks_common_hdr_t * h)
317 {
318   return ((h->params & CHUNK_BBIT_MASK) >> CHUNK_BBIT_SHIFT);
319 }
320
321 always_inline void
322 vnet_sctp_set_ebit (sctp_chunks_common_hdr_t * h)
323 {
324   h->params &= ~(CHUNK_EBIT_MASK);
325   h->params |= (1 << CHUNK_EBIT_SHIFT) & CHUNK_EBIT_MASK;
326 }
327
328 always_inline u8
329 vnet_sctp_get_ebit (sctp_chunks_common_hdr_t * h)
330 {
331   return ((h->params & CHUNK_EBIT_MASK) >> CHUNK_EBIT_SHIFT);
332 }
333
334 always_inline void
335 vnet_sctp_set_chunk_type (sctp_chunks_common_hdr_t * h, sctp_chunk_type t)
336 {
337   h->params &= ~(CHUNK_TYPE_MASK);
338   h->params |= (t << CHUNK_TYPE_SHIFT) & CHUNK_TYPE_MASK;
339 }
340
341 always_inline u8
342 vnet_sctp_get_chunk_type (sctp_chunks_common_hdr_t * h)
343 {
344   return ((h->params & CHUNK_TYPE_MASK) >> CHUNK_TYPE_SHIFT);
345 }
346
347 always_inline void
348 vnet_sctp_set_chunk_length (sctp_chunks_common_hdr_t * h, u16 length)
349 {
350   h->params &= ~(CHUNK_LENGTH_MASK);
351   h->params |= (length << CHUNK_LENGTH_SHIFT) & CHUNK_LENGTH_MASK;
352 }
353
354 always_inline u16
355 vnet_sctp_get_chunk_length (sctp_chunks_common_hdr_t * h)
356 {
357   return ((h->params & CHUNK_LENGTH_MASK) >> CHUNK_LENGTH_SHIFT);
358 }
359
360 /*
361  * Payload chunk
362  *
363  * 0                   1                   2                   3
364  * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
365  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
366  * |   Type = 0    | Reserved|U|B|E|    Length                     |
367  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
368  * |                              TSN                              |
369  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
370  * |      Stream Identifier S      |   Stream Sequence Number n    |
371  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
372  * |                  Payload Protocol Identifier                  |
373  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
374  * \                                                               \
375  * /                 User Data (seq n of Stream S)                 /
376  * \                                                               \
377  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
378  */
379 typedef struct
380 {
381   sctp_header_t sctp_hdr;
382   /*
383    * Type (8 bits): 0
384    * Flags (8 bits):
385    * -- Reserved (5 bits): all 0s
386    * -- U bit
387    * -- B bit
388    * -- E bit
389    * Length (16 bits): This field indicates the length of the DATA chunk in
390    * bytes from the beginning of the type field to the end of the User Data
391    * field excluding any padding.
392    * A DATA chunk with one byte of user data will have Length set to 17
393    * (indicating 17 bytes). A DATA chunk with a User Data field of length L
394    * will have the Length field set to (16 + L) (indicating 16+L bytes) where
395    * L MUST be greater than 0.
396    */
397
398   /*
399    * Fragment Description Table:
400    *
401    *    B E                  Description
402    * ============================================================
403    * |  1 0 | First piece of a fragmented user message          |
404    * +----------------------------------------------------------+
405    * |  0 0 | Middle piece of a fragmented user message         |
406    * +----------------------------------------------------------+
407    * |  0 1 | Last piece of a fragmented user message           |
408    * +----------------------------------------------------------+
409    * |  1 1 | Unfragmented message                              |
410    * ============================================================
411    */
412   sctp_chunks_common_hdr_t chunk_hdr;
413
414   /*
415    * This value represents the TSN for this DATA chunk.
416    * The valid range of TSN is from 0 to 4294967295 (2**32 - 1).
417    * TSN wraps back to 0 after reaching 4294967295.
418    */
419   u32 tsn;
420
421   /*
422    * Identifies the stream to which the following user data belongs.
423    */
424   u16 stream_id;
425
426   /*
427    * This value represents the Stream Sequence Number of the following user data
428    * within the stream S. Valid range is 0 to 65535.
429    * When a user message is fragmented by SCTP for transport, the same Stream
430    * Sequence Number MUST be carried in each of the fragments of the message.
431    */
432   u16 stream_seq;
433
434   /*
435    * This value represents an application (or upper layer) specified protocol
436    * identifier. This value is passed to SCTP by its upper layer and sent to its
437    * peer. This identifier is not used by SCTP but can be used by certain network
438    * entities, as well as by the peer application, to identify the type of
439    * information being carried in this DATA chunk. This field must be sent even
440    * in fragmented DATA chunks (to make sure it is available for agents in the
441    * middle of the network).  Note that this field is NOT touched by an SCTP
442    * implementation; therefore, its byte order is NOT necessarily big endian.
443    * The upper layer is responsible for any byte order conversions to this field.
444    * The value 0 indicates that no application identifier is specified by the
445    * upper layer for this payload data.
446    */
447   u32 payload_id;
448
449   /*
450    * This is the payload user data. The implementation MUST pad the end of the
451    * data to a 4-byte boundary with all-zero bytes. Any padding MUST NOT be
452    * included in the Length field. A sender MUST never add more than 3 bytes of
453    * padding.
454    */
455   u32 data[];
456
457 } sctp_payload_data_chunk_t;
458
459 always_inline void
460 vnet_sctp_set_tsn (sctp_payload_data_chunk_t * p, u32 tsn)
461 {
462   p->tsn = clib_host_to_net_u32 (tsn);
463 }
464
465 always_inline u32
466 vnet_sctp_get_tsn (sctp_payload_data_chunk_t * p)
467 {
468   return (clib_net_to_host_u32 (p->tsn));
469 }
470
471 always_inline void
472 vnet_sctp_set_stream_id (sctp_payload_data_chunk_t * p, u16 stream_id)
473 {
474   p->stream_id = clib_host_to_net_u16 (stream_id);
475 }
476
477 always_inline u16
478 vnet_sctp_get_stream_id (sctp_payload_data_chunk_t * p)
479 {
480   return (clib_net_to_host_u16 (p->stream_id));
481 }
482
483 always_inline void
484 vnet_sctp_set_stream_seq (sctp_payload_data_chunk_t * p, u16 stream_seq)
485 {
486   p->stream_seq = clib_host_to_net_u16 (stream_seq);
487 }
488
489 always_inline u16
490 vnet_sctp_get_stream_seq (sctp_payload_data_chunk_t * p)
491 {
492   return (clib_net_to_host_u16 (p->stream_seq));
493 }
494
495 always_inline void
496 vnet_sctp_set_payload_id (sctp_payload_data_chunk_t * p, u32 payload_id)
497 {
498   p->payload_id = clib_host_to_net_u32 (payload_id);
499 }
500
501 always_inline u32
502 vnet_sctp_get_payload_id (sctp_payload_data_chunk_t * p)
503 {
504   return (clib_net_to_host_u32 (p->payload_id));
505 }
506
507 always_inline u16
508 vnet_sctp_calculate_padding (u16 base_length)
509 {
510   if (base_length % 4 == 0)
511     return 0;
512
513   return (4 - base_length % 4);
514 }
515
516 #define INBOUND_STREAMS_COUNT 1
517 #define OUTBOUND_STREAMS_COUNT 1
518
519 /*
520  * INIT chunk
521  *
522  * This chunk is used to initiate an SCTP association between two
523  * endpoints.
524  *
525  * 0                   1                   2                   3
526  * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
527  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
528  * |   Type = 1    |  Chunk Flags  |      Chunk Length             |
529  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
530  * |                         Initiate Tag                          |
531  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
532  * |           Advertised Receiver Window Credit (a_rwnd)          |
533  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
534  * |  Number of Outbound Streams   |  Number of Inbound Streams    |
535  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
536  * |                          Initial TSN                          |
537  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
538  * \                                                               \
539  * /              Optional/Variable-Length Parameters              /
540  * \                                                               \
541  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
542  *
543  * The INIT chunk contains the following parameters. Unless otherwise
544  * noted, each parameter MUST only be included once in the INIT chunk.
545  *
546  * Fixed Parameters                     Status
547  * ----------------------------------------------
548  *  Initiate Tag                        Mandatory
549  *  Advertised Receiver Window Credit   Mandatory
550  *  Number of Outbound Streams          Mandatory
551  *  Number of Inbound Streams           Mandatory
552  *  Initial TSN                         Mandatory
553  *
554  * Variable Parameters                  Status     Type Value
555  * -------------------------------------------------------------
556  *  IPv4 Address (Note 1)               Optional    5
557  *  IPv6 Address (Note 1)               Optional    6
558  *  Cookie Preservative                 Optional    9
559  *  Reserved for ECN Capable (Note 2)   Optional    32768 (0x8000)
560  *  Host Name Address (Note 3)          Optional    11
561  *  Supported Address Types (Note 4)    Optional    12
562  *
563  * Note 1: The INIT chunks can contain multiple addresses that can be
564  * IPv4 and/or IPv6 in any combination.
565  *
566  * Note 2: The ECN Capable field is reserved for future use of Explicit
567  * Congestion Notification.
568  *
569  * Note 3: An INIT chunk MUST NOT contain more than one Host Name Address
570  * parameter. Moreover, the sender of the INIT MUST NOT combine any other
571  * address types with the Host Name Address in the INIT. The receiver of
572  * INIT MUST ignore any other address types if the Host Name Address parameter
573  * is present in the received INIT chunk.
574  *
575  * Note 4: This parameter, when present, specifies all the address types the
576  * sending endpoint can support.  The absence of this parameter indicates that
577  * the sending endpoint can support any address type.
578  *
579  * IMPLEMENTATION NOTE: If an INIT chunk is received with known parameters that
580  * are not optional parameters of the INIT chunk, then the receiver SHOULD
581  * process the INIT chunk and send back an INIT ACK. The receiver of the INIT
582  * chunk MAY bundle an ERROR chunk with the COOKIE ACK chunk later.
583  * However, restrictive implementations MAY send back an ABORT chunk in response
584  * to the INIT chunk. The Chunk Flags field in INIT is reserved, and all bits
585  * in it should be set to 0 by the sender and ignored by the receiver.
586  * The sequence of parameters within an INIT can be processed in any order.
587  */
588 typedef struct
589 {
590   sctp_header_t sctp_hdr;
591   sctp_chunks_common_hdr_t chunk_hdr;
592
593   /*
594    * The receiver of the INIT (the responding end) records the value of
595    * the Initiate Tag parameter.
596    * This value MUST be placed into the Verification Tag field of every
597    * SCTP packet that the receiver of the INIT transmits within this association.
598    * The Initiate Tag is allowed to have any value except 0.
599    *
600    * If the value of the Initiate Tag in a received INIT chunk is found
601    * to be 0, the receiver MUST treat it as an error and close the
602    * association by transmitting an ABORT.
603    *
604    * The value of the INIT TAG is recommended to be random for security
605    * reasons. A good method is described in https://tools.ietf.org/html/rfc4086
606    */
607   u32 initiate_tag;
608
609   /*
610    * This value represents the dedicated buffer space, in number of bytes,
611    * the sender of the INIT has reserved in association with this window.
612    * During the life of the association, this buffer space SHOULD NOT be
613    * lessened (i.e., dedicated buffers taken away from this association);
614    * however, an endpoint MAY change the value of a_rwnd it sends in SACK
615    * chunks.
616    */
617   u32 a_rwnd;
618
619   /*
620    * Defines the number of outbound streams the sender of this INIT chunk
621    * wishes to create in this association.
622    * The value of 0 MUST NOT be used.
623    *
624    * Note: A receiver of an INIT with the OS value set to 0 SHOULD abort
625    * the association.
626    */
627   u16 outbound_streams_count;
628
629   /*
630    * Defines the maximum number of streams the sender of this INIT
631    * chunk allows the peer end to create in this association.
632    * The value 0 MUST NOT be used.
633    *
634    * Note: There is no negotiation of the actual number of streams but
635    * instead the two endpoints will use the min(requested, offered).
636    *
637    * Note: A receiver of an INIT with the MIS value of 0 SHOULD abort
638    * the association.
639    */
640   u16 inboud_streams_count;
641
642   /*
643    * Defines the initial TSN that the sender will use.
644    * The valid range is from 0 to 4294967295.
645    * This field MAY be set to the value of the Initiate Tag field.
646    */
647   u32 initial_tsn;
648
649   /* The following field allows to have multiple optional fields which are:
650    * - sctp_ipv4_address
651    * - sctp_ipv6_address
652    * - sctp_cookie_preservative
653    * - sctp_hostname_address
654    * - sctp_supported_address_types
655    */
656   u32 optional_fields[];
657
658 } sctp_init_chunk_t;
659
660 /*
661  * INIT ACK chunk
662  *
663  * The INIT ACK chunk is used to acknowledge the initiation of an SCTP
664  * association. The parameter part of INIT ACK is formatted similarly to the
665  * INIT chunk.
666  *
667  * It uses two extra variable parameters:
668  * - the State Cookie and
669  * - the Unrecognized Parameter:
670  */
671 /*
672  * 0                   1                   2                   3
673  * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
674  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
675  * |   Type = 2    |  Chunk Flags  |      Chunk Length             |
676  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
677  * |                         Initiate Tag                          |
678  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
679  * |              Advertised Receiver Window Credit                |
680  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
681  * |  Number of Outbound Streams   |  Number of Inbound Streams    |
682  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
683  * |                          Initial TSN                          |
684  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
685  * \                                                               \
686  * /              Optional/Variable-Length Parameters              /
687  * \                                                               \
688  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
689  */
690 typedef sctp_init_chunk_t sctp_init_ack_chunk_t;
691
692 typedef struct
693 {
694   u16 type;
695   u16 length;
696
697 } sctp_opt_params_hdr_t;
698
699 #define SHA1_OUTPUT_LENGTH 20
700 /*
701  * 0                   1                   2                   3
702  * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
703  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
704  * |          Parameter Type       |       Parameter Length        |
705  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
706  * \                                                               \
707  * /                       Parameter Value                         /
708  * \                                                               \
709  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
710  */
711 typedef struct
712 {
713   sctp_opt_params_hdr_t param_hdr;
714
715   unsigned char mac[SHA1_OUTPUT_LENGTH];        /* RFC 2104 */
716   u64 creation_time;
717   u32 cookie_lifespan;
718
719 } sctp_state_cookie_param_t;
720
721 /*
722  *  This chunk is used only during the initialization of an association.
723  *  It is sent by the initiator of an association to its peer to complete
724  *  the initialization process.  This chunk MUST precede any DATA chunk
725  *  sent within the association, but MAY be bundled with one or more DATA
726  *  chunks in the same packet.
727  *
728  *  0                   1                   2                   3
729  *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
730  *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
731  *  |   Type = 10   |Chunk  Flags   |         Length                |
732  *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
733  *  /                     Cookie                                    /
734  *  \                                                               \
735  *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
736  */
737 typedef struct
738 {
739   sctp_header_t sctp_hdr;
740   sctp_chunks_common_hdr_t chunk_hdr;
741
742   sctp_state_cookie_param_t cookie;
743
744 } sctp_cookie_echo_chunk_t;
745
746
747 /*
748  * 0                   1                   2                   3
749  * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
750  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
751  * |   Type = 11   |Chunk  Flags   |     Length = 4                |
752  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
753  */
754 typedef struct
755 {
756   sctp_header_t sctp_hdr;
757   sctp_chunks_common_hdr_t chunk_hdr;
758
759 } sctp_cookie_ack_chunk_t;
760
761 /*
762  * 0                   1                   2                   3
763  * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
764  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
765  * |   Type = 14   |Chunk  Flags   |     Length = 4                |
766  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
767  */
768 typedef struct
769 {
770   sctp_header_t sctp_hdr;
771   sctp_chunks_common_hdr_t chunk_hdr;
772
773 } sctp_shutdown_complete_chunk_t;
774
775 /* OPTIONAL or VARIABLE-LENGTH parameters for INIT */
776 #define SCTP_IPV4_ADDRESS_TYPE  5
777 #define SCTP_IPV4_ADDRESS_TYPE_LENGTH 8
778 #define SCTP_IPV6_ADDRESS_TYPE  6
779 #define SCTP_IPV6_ADDRESS_TYPE_LENGTH 20
780 #define SCTP_STATE_COOKIE_TYPE          7
781 #define SCTP_UNRECOGNIZED_TYPE  8
782 #define SCTP_COOKIE_PRESERVATIVE_TYPE   9
783 #define SCTP_COOKIE_PRESERVATIVE_TYPE_LENGTH    8
784 #define SCTP_HOSTNAME_ADDRESS_TYPE      11
785 #define SCTP_SUPPORTED_ADDRESS_TYPES    12
786
787 /*
788  * 0                   1                   2                   3
789  * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
790  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
791  * |        Type = 5               |      Length = 8               |
792  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
793  * |                        IPv4 Address                           |
794  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
795  */
796 typedef struct
797 {
798   sctp_opt_params_hdr_t param_hdr;
799
800   /*
801    * Contains an IPv4 address of the sending endpoint.
802    * It is binary encoded.
803    */
804   ip4_address_t address;
805
806 } sctp_ipv4_addr_param_t;
807
808 always_inline void
809 vnet_sctp_set_ipv4_address (sctp_ipv4_addr_param_t * a, ip4_address_t address)
810 {
811   a->param_hdr.type = clib_host_to_net_u16 (SCTP_IPV4_ADDRESS_TYPE);
812   a->param_hdr.length = clib_host_to_net_u16 (8);
813   a->address.as_u32 = clib_host_to_net_u32 (address.as_u32);
814 }
815
816 always_inline u32
817 vnet_sctp_get_ipv4_address (sctp_ipv4_addr_param_t * a)
818 {
819   return (clib_net_to_host_u32 (a->address.as_u32));
820 }
821
822 /*
823  * 0                   1                   2                   3
824  * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
825  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
826  * |            Type = 6           |          Length = 20          |
827  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
828  * |                                                               |
829  * |                         IPv6 Address                          |
830  * |                                                               |
831  * |                                                               |
832  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
833  */
834 typedef struct
835 {
836   sctp_opt_params_hdr_t param_hdr;
837
838   /*
839    * Contains an IPv6 address of the sending endpoint.
840    * It is binary encoded.
841    */
842   ip6_address_t address;
843
844 } sctp_ipv6_addr_param_t;
845
846 always_inline void
847 vnet_sctp_set_ipv6_address (sctp_ipv6_addr_param_t * a, ip6_address_t address)
848 {
849   a->param_hdr.type = clib_host_to_net_u16 (SCTP_IPV6_ADDRESS_TYPE);
850   a->param_hdr.length = clib_host_to_net_u16 (20);
851   a->address.as_u64[0] = clib_host_to_net_u64 (address.as_u64[0]);
852   a->address.as_u64[1] = clib_host_to_net_u64 (address.as_u64[1]);
853 }
854
855 always_inline ip6_address_t
856 vnet_sctp_get_ipv6_address (sctp_ipv6_addr_param_t * a)
857 {
858   ip6_address_t ip6_address;
859
860   ip6_address.as_u64[0] = clib_net_to_host_u64 (a->address.as_u64[0]);
861   ip6_address.as_u64[1] = clib_net_to_host_u64 (a->address.as_u64[1]);
862
863   return ip6_address;
864 }
865
866 /*
867  * The sender of the INIT shall use this parameter to suggest to the
868  * receiver of the INIT for a longer life-span of the State Cookie.
869  */
870 /*
871  * 0                   1                   2                   3
872  * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
873  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
874  * |          Type = 9             |          Length = 8           |
875  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
876  * |         Suggested Cookie Life-Span Increment (msec.)          |
877  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
878  */
879 typedef struct
880 {
881   sctp_opt_params_hdr_t param_hdr;
882
883   /*
884    * This parameter indicates to the receiver how much increment in
885    * milliseconds the sender wishes the receiver to add to its default
886    * cookie life-span.
887    *
888    * This optional parameter should be added to the INIT chunk by the
889    * sender when it reattempts establishing an association with a peer
890    * to which its previous attempt of establishing the association
891    * failed due to a stale cookie operation error. The receiver MAY
892    * choose to ignore the suggested cookie life-span increase for its
893    * own security reasons.
894    */
895   u32 life_span_inc;
896
897 } sctp_cookie_preservative_param_t;
898
899 always_inline void
900 vnet_sctp_set_cookie_preservative (sctp_cookie_preservative_param_t * c,
901                                    u32 life_span_inc)
902 {
903   c->param_hdr.type = clib_host_to_net_u16 (SCTP_COOKIE_PRESERVATIVE_TYPE);
904   c->param_hdr.length = clib_host_to_net_u16 (8);
905   c->life_span_inc = clib_host_to_net_u32 (life_span_inc);
906 }
907
908 always_inline u32
909 vnet_sctp_get_cookie_preservative (sctp_cookie_preservative_param_t * c)
910 {
911   return (clib_net_to_host_u32 (c->life_span_inc));
912 }
913
914 #define FQDN_MAX_LENGTH 256
915
916 /*
917  * The sender of INIT uses this parameter to pass its Host Name (in
918  * place of its IP addresses) to its peer.
919  * The peer is responsible for resolving the name.
920  * Using this parameter might make it more likely for the association to work
921  * across a NAT box.
922  */
923 /*
924  * 0                   1                   2                   3
925  * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
926  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
927  * |          Type = 11            |          Length               |
928  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
929  * /                          Host Name                            /
930  * \                                                               \
931  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
932  */
933 typedef struct
934 {
935   sctp_opt_params_hdr_t param_hdr;
936
937
938   /*
939    * This field contains a host name in "host name syntax" per RFC 1123
940    * Section 2.1
941    *
942    * Note: At least one null terminator is included in the Host Name
943    * string and must be included in the length.
944    */
945   char hostname[FQDN_MAX_LENGTH];
946
947 } sctp_hostname_param_t;
948
949 always_inline void
950 vnet_sctp_set_hostname_address (sctp_hostname_param_t * h, char *hostname)
951 {
952   h->param_hdr.length = FQDN_MAX_LENGTH;
953   h->param_hdr.type = clib_host_to_net_u16 (SCTP_HOSTNAME_ADDRESS_TYPE);
954   clib_memset (h->hostname, '0', FQDN_MAX_LENGTH);
955   memcpy (h->hostname, hostname, FQDN_MAX_LENGTH);
956 }
957
958 #define MAX_SUPPORTED_ADDRESS_TYPES     3
959
960 /*
961  * The sender of INIT uses this parameter to list all the address types
962  * it can support.
963  */
964 /*
965  * 0                   1                   2                   3
966  * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
967  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
968  * |          Type = 12            |          Length               |
969  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
970  * |        Address Type #1        |        Address Type #2        |
971  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
972  * |                            ......                             |
973  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-++-+-+-+-+-+-+-+-+-+-+-+-+-+-++-+-+-+
974  */
975 typedef struct
976 {
977   sctp_opt_params_hdr_t param_hdr;
978
979   u16 address_type[MAX_SUPPORTED_ADDRESS_TYPES];
980
981 } sctp_supported_addr_types_param_t;
982
983 always_inline void
984 vnet_sctp_set_supported_address_types (sctp_supported_addr_types_param_t * s)
985 {
986   s->param_hdr.type = clib_host_to_net_u16 (SCTP_SUPPORTED_ADDRESS_TYPES);
987   s->param_hdr.length = 4 /* base = type + length */  +
988     MAX_SUPPORTED_ADDRESS_TYPES * 4;    /* each address type is 4 bytes */
989
990   s->address_type[0] = clib_host_to_net_u16 (SCTP_IPV4_ADDRESS_TYPE);
991   s->address_type[1] = clib_host_to_net_u16 (SCTP_IPV6_ADDRESS_TYPE);
992   s->address_type[2] = clib_host_to_net_u16 (SCTP_HOSTNAME_ADDRESS_TYPE);
993 }
994
995 /*
996  * Error cause codes to be used for the sctp_error_cause.cause_code field
997  */
998 #define INVALID_STREAM_IDENTIFIER       1
999 #define MISSING_MANDATORY_PARAMETER     2
1000 #define STALE_COOKIE_ERROR              3
1001 #define OUT_OF_RESOURCE                 4
1002 #define UNRESOLVABLE_ADDRESS            5
1003 #define UNRECOGNIZED_CHUNK_TYPE         6
1004 #define INVALID_MANDATORY_PARAMETER     7
1005 #define UNRECOGNIZED_PARAMETER          8
1006 #define NO_USER_DATA                    9
1007 #define COOKIE_RECEIVED_WHILE_SHUTTING_DOWN     10
1008 #define RESTART_OF_ASSOCIATION_WITH_NEW_ADDR    11
1009 #define USER_INITIATED_ABORT            12
1010 #define PROTOCOL_VIOLATION              13
1011
1012 always_inline void
1013 vnet_sctp_set_state_cookie (sctp_state_cookie_param_t * s)
1014 {
1015   s->param_hdr.type = clib_host_to_net_u16 (SCTP_STATE_COOKIE_TYPE);
1016
1017   /* TODO: length & value to be populated */
1018 }
1019
1020 typedef struct
1021 {
1022   sctp_opt_params_hdr_t param_hdr;
1023
1024   u32 value[];
1025
1026 } sctp_unrecognized_param_t;
1027
1028 always_inline void
1029 vnet_sctp_set_unrecognized_param (sctp_unrecognized_param_t * u)
1030 {
1031   u->param_hdr.type = clib_host_to_net_u16 (UNRECOGNIZED_PARAMETER);
1032
1033   /* TODO: length & value to be populated */
1034 }
1035
1036 /*
1037  * Selective ACK (SACK) chunk
1038  *
1039  * This chunk is sent to the peer endpoint to acknowledge received DATA
1040  * chunks and to inform the peer endpoint of gaps in the received
1041  * subsequences of DATA chunks as represented by their TSNs.
1042  */
1043 /*
1044  * 0                   1                   2                   3
1045  * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
1046  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1047  * |   Type = 3    |Chunk  Flags   |      Chunk Length             |
1048  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1049  * |                      Cumulative TSN Ack                       |
1050  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1051  * |          Advertised Receiver Window Credit (a_rwnd)           |
1052  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1053  * | Number of Gap Ack Blocks = N  |  Number of Duplicate TSNs = X |
1054  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1055  * |  Gap Ack Block #1 Start       |   Gap Ack Block #1 End        |
1056  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1057  * /                                                               /
1058  * \                              ...                              \
1059  * /                                                               /
1060  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1061  * |   Gap Ack Block #N Start      |  Gap Ack Block #N End         |
1062  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1063  * |                       Duplicate TSN 1                         |
1064  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1065  * /                                                               /
1066  * \                              ...                              \
1067  * /                                                               /
1068  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1069  * |                       Duplicate TSN X                         |
1070  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1071  */
1072 typedef struct
1073 {
1074   sctp_header_t sctp_hdr;
1075   sctp_chunks_common_hdr_t chunk_hdr;
1076   /*
1077    * This parameter contains the TSN of the last DATA chunk received in
1078    * sequence before a gap.  In the case where no DATA chunk has been
1079    * received, this value is set to the peer's Initial TSN minus one.
1080    */
1081   u32 cumulative_tsn_ack;
1082
1083   /*
1084    * This field indicates the updated receive buffer space in bytes of
1085    * the sender of this SACK.
1086    */
1087   u32 a_rwnd;
1088
1089   /*
1090    * Indicates the number of Gap Ack Blocks included in this SACK.
1091    */
1092   u16 gap_ack_blocks_count;
1093
1094   /*
1095    * This field contains the number of duplicate TSNs the endpoint has
1096    * received.  Each duplicate TSN is listed following the Gap Ack Block
1097    * list.
1098    */
1099   u16 duplicate_tsn_count;
1100
1101   /*
1102    * Indicates the Start offset TSN for this Gap Ack Block. To calculate
1103    * the actual TSN number the Cumulative TSN Ack is added to this offset
1104    * number. This calculated TSN identifies the first TSN in this Gap Ack
1105    * Block that has been received.
1106    */
1107   u16 *gap_ack_block_start;
1108
1109   /*
1110    * Indicates the End offset TSN for this Gap Ack Block. To calculate
1111    * the actual TSN number, the Cumulative TSN Ack is added to this offset
1112    * number. This calculated TSN identifies the TSN of the last DATA chunk
1113    * received in this Gap Ack Block.
1114    */
1115   u16 *gap_ack_block_end;
1116
1117   /*
1118    * Indicates the number of times a TSN was received in duplicate since
1119    * the last SACK was sent. Every time a receiver gets a duplicate TSN
1120    * (before sending the SACK), it adds it to the list of duplicates.
1121    * The duplicate count is reinitialized to zero after sending each SACK.
1122    */
1123   u32 duplicate_tsn;
1124
1125 } sctp_selective_ack_chunk_t;
1126
1127 always_inline void
1128 vnet_sctp_set_cumulative_tsn_ack (sctp_selective_ack_chunk_t * s,
1129                                   u32 cumulative_tsn_ack)
1130 {
1131   vnet_sctp_set_chunk_type (&s->chunk_hdr, SACK);
1132   s->cumulative_tsn_ack = clib_host_to_net_u32 (cumulative_tsn_ack);
1133 }
1134
1135 always_inline u32
1136 vnet_sctp_get_cumulative_tsn_ack (sctp_selective_ack_chunk_t * s)
1137 {
1138   return clib_net_to_host_u32 (s->cumulative_tsn_ack);
1139 }
1140
1141 always_inline void
1142 vnet_sctp_set_arwnd (sctp_selective_ack_chunk_t * s, u32 a_rwnd)
1143 {
1144   vnet_sctp_set_chunk_type (&s->chunk_hdr, SACK);
1145   s->a_rwnd = clib_host_to_net_u32 (a_rwnd);
1146 }
1147
1148 always_inline u32
1149 vnet_sctp_get_arwnd (sctp_selective_ack_chunk_t * s)
1150 {
1151   return clib_net_to_host_u32 (s->a_rwnd);
1152 }
1153
1154 always_inline void
1155 vnet_sctp_set_gap_ack_blocks_count (sctp_selective_ack_chunk_t * s,
1156                                     u16 gap_ack_blocks_count)
1157 {
1158   vnet_sctp_set_chunk_type (&s->chunk_hdr, SACK);
1159   s->gap_ack_blocks_count = clib_host_to_net_u16 (gap_ack_blocks_count);
1160
1161   if (s->gap_ack_block_start == NULL)
1162     s->gap_ack_block_start =
1163       clib_mem_alloc (sizeof (u16) * gap_ack_blocks_count);
1164   if (s->gap_ack_block_end == NULL)
1165     s->gap_ack_block_end =
1166       clib_mem_alloc (sizeof (u16) * gap_ack_blocks_count);
1167 }
1168
1169 always_inline u16
1170 vnet_sctp_get_gap_ack_blocks_count (sctp_selective_ack_chunk_t * s)
1171 {
1172   return clib_net_to_host_u32 (s->gap_ack_blocks_count);
1173 }
1174
1175 always_inline void
1176 vnet_sctp_set_duplicate_tsn_count (sctp_selective_ack_chunk_t * s,
1177                                    u16 duplicate_tsn_count)
1178 {
1179   vnet_sctp_set_chunk_type (&s->chunk_hdr, SACK);
1180   s->duplicate_tsn_count = clib_host_to_net_u16 (duplicate_tsn_count);
1181 }
1182
1183 always_inline u16
1184 vnet_sctp_get_duplicate_tsn_count (sctp_selective_ack_chunk_t * s)
1185 {
1186   return clib_net_to_host_u16 (s->duplicate_tsn_count);
1187 }
1188
1189 /*
1190  * Heartbeat Info
1191  *
1192  * 0                   1                   2                   3
1193  * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
1194  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1195  * |    Heartbeat Info Type=1      |         HB Info Length        |
1196  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1197  * /                  Sender-Specific Heartbeat Info               /
1198  * \                                                               \
1199  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1200  */
1201 typedef struct
1202 {
1203   sctp_opt_params_hdr_t param_hdr;
1204
1205   /*
1206    * The Sender-Specific Heartbeat Info field should normally include
1207    * information about the sender's current time when this HEARTBEAT
1208    * chunk is sent and the destination transport address to which this
1209    * HEARTBEAT is sent.
1210    * This information is simply reflected back by the receiver in the
1211    * HEARTBEAT ACK message.
1212    *
1213    * Note also that the HEARTBEAT message is both for reachability
1214    * checking and for path verification.
1215    * When a HEARTBEAT chunk is being used for path verification purposes,
1216    * it MUST hold a 64-bit random nonce.
1217    */
1218   u64 hb_info;
1219
1220 } sctp_hb_info_param_t;
1221
1222 always_inline void
1223 vnet_sctp_set_heartbeat_info (sctp_hb_info_param_t * h, u64 hb_info,
1224                               u16 hb_info_length)
1225 {
1226   h->hb_info = clib_host_to_net_u16 (1);
1227   h->param_hdr.length = clib_host_to_net_u16 (hb_info_length);
1228   h->hb_info = clib_host_to_net_u64 (hb_info);
1229 }
1230
1231 /*
1232  * Heartbeat Request
1233  *
1234  * An endpoint should send this chunk to its peer endpoint to probe the
1235  * reachability of a particular destination transport address defined in
1236  * the present association.
1237  * The parameter field contains the Heartbeat Information, which is a
1238  * variable-length opaque data structure understood only by the sender.
1239  */
1240 /*
1241  * 0                   1                   2                   3
1242  * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
1243  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1244  * |   Type = 4    | Chunk  Flags  |      Heartbeat Length         |
1245  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1246  * \                                                               \
1247  * /            Heartbeat Information TLV (Variable-Length)        /
1248  * \                                                               \
1249  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1250  */
1251 typedef struct
1252 {
1253   sctp_header_t sctp_hdr;
1254   sctp_chunks_common_hdr_t chunk_hdr;
1255   sctp_hb_info_param_t hb_info;
1256
1257 } sctp_hb_req_chunk_t;
1258
1259 always_inline void
1260 vnet_sctp_set_hb_request_info (sctp_hb_req_chunk_t * h,
1261                                sctp_hb_info_param_t * hb_info)
1262 {
1263   vnet_sctp_set_chunk_type (&h->chunk_hdr, HEARTBEAT);
1264   memcpy (&h->hb_info, hb_info, sizeof (h->hb_info));
1265 }
1266
1267 /*
1268  * Heartbeat Acknowledgement
1269  *
1270  * An endpoint should send this chunk to its peer endpoint as a response
1271  * to a HEARTBEAT chunk.
1272  * A HEARTBEAT ACK is always sent to the source IP address of the IP datagram
1273  * containing the HEARTBEAT chunk to which this ack is responding.
1274  */
1275 /*
1276  *
1277  * 0                   1                   2                   3
1278  * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
1279  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1280  * |   Type = 5    | Chunk  Flags  |    Heartbeat Ack Length       |
1281  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1282  * \                                                               \
1283  * /            Heartbeat Information TLV (Variable-Length)        /
1284  * \                                                               \
1285  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1286  */
1287 typedef sctp_hb_req_chunk_t sctp_hb_ack_chunk_t;
1288
1289 always_inline void
1290 vnet_sctp_set_hb_ack_info (sctp_hb_ack_chunk_t * h,
1291                            sctp_hb_info_param_t * hb_info)
1292 {
1293   vnet_sctp_set_chunk_type (&h->chunk_hdr, HEARTBEAT_ACK);
1294   memcpy (&h->hb_info, hb_info, sizeof (h->hb_info));
1295 }
1296
1297 /*
1298  * Error cause
1299  */
1300 /*
1301  * 0                   1                   2                   3
1302  * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
1303  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1304  * |           Cause Code          |       Cause Length            |
1305  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1306  * /                    Cause-Specific Information                 /
1307  * \                                                               \
1308  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1309 */
1310 typedef struct
1311 {
1312
1313   sctp_opt_params_hdr_t param_hdr;
1314   u64 cause_info;
1315
1316 } sctp_err_cause_param_t;
1317
1318
1319 /*
1320  * An end-point sends this chunk to its peer end-point to notify it of
1321  * certain error conditions.  It contains one or more error causes.
1322  * An Operation Error is not considered fatal in and of itself, but may be
1323  * used with an ABORT chunk to report a fatal condition.  It has the
1324  * following parameters:
1325  *
1326  * 0                   1                   2                   3
1327  * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
1328  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1329  * |   Type = 9    | Chunk  Flags  |           Length              |
1330  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1331  * \                                                               \
1332  * /                    one or more Error Causes                   /
1333  * \                                                               \
1334  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1335  */
1336 typedef struct
1337 {
1338   sctp_header_t sctp_hdr;
1339   sctp_chunks_common_hdr_t chunk_hdr;
1340   sctp_err_cause_param_t err_causes[];
1341
1342 } sctp_operation_error_t;
1343
1344 /*
1345  * Abort Association (ABORT)
1346  *
1347  * The ABORT chunk is sent to the peer of an association to close the
1348  * association.  The ABORT chunk may contain Cause Parameters to inform
1349  * the receiver about the reason of the abort.  DATA chunks MUST NOT be
1350  * bundled with ABORT.  Control chunks (except for INIT, INIT ACK, and
1351  * SHUTDOWN COMPLETE) MAY be bundled with an ABORT, but they MUST be
1352  * placed before the ABORT in the SCTP packet or they will be ignored by
1353  * the receiver.
1354  *
1355  * If an endpoint receives an ABORT with a format error or no TCB is
1356  * found, it MUST silently discard it.  Moreover, under any
1357  * circumstances, an endpoint that receives an ABORT MUST NOT respond to
1358  * that ABORT by sending an ABORT of its own.
1359  */
1360 /*
1361  * 0                   1                   2                   3
1362  * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
1363  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1364  * |   Type = 6    |Reserved     |T|           Length              |
1365  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1366  * \                                                               \
1367  * /                   zero or more Error Causes                   /
1368  * \                                                               \
1369  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1370  */
1371 typedef struct
1372 {
1373   sctp_header_t sctp_hdr;
1374   sctp_chunks_common_hdr_t chunk_hdr;
1375   sctp_err_cause_param_t err_causes[];
1376
1377 } sctp_abort_chunk_t;
1378
1379 always_inline void
1380 vnet_sctp_set_tbit (sctp_abort_chunk_t * a)
1381 {
1382   vnet_sctp_set_chunk_type (&a->chunk_hdr, ABORT);
1383   // a->chunk_hdr.flags = clib_host_to_net_u16 (1);
1384 }
1385
1386 always_inline void
1387 vnet_sctp_unset_tbit (sctp_abort_chunk_t * a)
1388 {
1389   vnet_sctp_set_chunk_type (&a->chunk_hdr, ABORT);
1390   // a->chunk_hdr.flags = clib_host_to_net_u16 (0);
1391 }
1392
1393 /*
1394  * Shutdown Association (SHUTDOWN)
1395  *
1396  * An endpoint in an association MUST use this chunk to initiate a
1397  * graceful close of the association with its peer.
1398  */
1399 /*
1400  * 0                   1                   2                   3
1401  * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
1402  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1403  * |   Type = 7    | Chunk  Flags  |      Length = 8               |
1404  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1405  * |                      Cumulative TSN Ack                       |
1406  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1407  */
1408 typedef struct
1409 {
1410   sctp_header_t sctp_hdr;
1411   sctp_chunks_common_hdr_t chunk_hdr;
1412   /*
1413    * This parameter contains the TSN of the last chunk received in
1414    * sequence before any gaps.
1415    *
1416    * Note: Since the SHUTDOWN message does not contain Gap Ack Blocks,
1417    * it cannot be used to acknowledge TSNs received out of order. In a
1418    * SACK, lack of Gap Ack Blocks that were previously included
1419    * indicates that the data receiver reneged on the associated DATA
1420    * chunks. Since SHUTDOWN does not contain Gap Ack Blocks, the
1421    * receiver of the SHUTDOWN shouldn't interpret the lack of a Gap Ack
1422    * Block as a renege.
1423    */
1424   u32 cumulative_tsn_ack;
1425
1426 } sctp_shutdown_association_chunk_t;
1427
1428 always_inline void
1429 vnet_sctp_set_tsn_last_received_chunk (sctp_shutdown_association_chunk_t * s,
1430                                        u32 tsn_last_chunk)
1431 {
1432   vnet_sctp_set_chunk_type (&s->chunk_hdr, SHUTDOWN);
1433   s->cumulative_tsn_ack = clib_host_to_net_u32 (tsn_last_chunk);
1434 }
1435
1436 /*
1437  * Shutdown Acknowledgement (SHUTDOWN ACK)
1438  *
1439  * This chunk MUST be used to acknowledge the receipt of the SHUTDOWN
1440  * chunk at the completion of the shutdown process.
1441  */
1442 /*
1443  * 0                   1                   2                   3
1444  * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
1445  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1446  * |   Type = 8    |Chunk  Flags   |      Length = 4               |
1447  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1448  */
1449 typedef struct
1450 {
1451   sctp_header_t sctp_hdr;
1452   sctp_chunks_common_hdr_t chunk_hdr;
1453 } sctp_shutdown_ack_chunk_t;
1454
1455 always_inline void
1456 vnet_sctp_fill_shutdown_ack (sctp_shutdown_ack_chunk_t * s)
1457 {
1458   vnet_sctp_set_chunk_type (&s->chunk_hdr, SHUTDOWN_ACK);
1459   vnet_sctp_set_chunk_length (&s->chunk_hdr, 4);
1460 }
1461
1462 #endif /* included_vnet_sctp_packet_h */
1463
1464 /*
1465  * fd.io coding-style-patch-verification: ON
1466  *
1467  * Local Variables:
1468  * eval: (c-set-style "gnu")
1469  * End:
1470  */