FD.io VPP  v18.04-17-g3a0d853
Vector Packet Processing
sctp_packet.h
Go to the documentation of this file.
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  */
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  */
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  */
74 
75  /*
76  * This field contains the checksum of this SCTP packet.
77  * SCTP uses the CRC32c algorithm.
78  */
80 
82 
83 always_inline void
85 {
86  h->src_port = clib_host_to_net_u16 (src_port);
87 }
88 
91 {
92  return (clib_net_to_host_u16 (h->src_port));
93 }
94 
95 always_inline void
97 {
98  h->dst_port = clib_host_to_net_u16 (dst_port);
99 }
100 
103 {
104  return (clib_net_to_host_u16 (h->dst_port));
105 }
106 
107 always_inline void
109 {
110  h->verification_tag = clib_host_to_net_u32 (verification_tag);
111 }
112 
115 {
116  return (clib_net_to_host_u32 (h->verification_tag));
117 }
118 
119 always_inline void
121 {
122  h->checksum = clib_host_to_net_u32 (checksum);
123 }
124 
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,
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 
255 
257 
258 typedef struct
259 {
262 
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
285 {
286  h->params = clib_host_to_net_u32 (h->params);
287 }
288 
289 always_inline void
291 {
292  h->params = clib_net_to_host_u32 (h->params);
293 }
294 
295 always_inline void
297 {
298  h->params &= ~(CHUNK_UBIT_MASK);
299  h->params |= (1 << CHUNK_UBIT_SHIFT) & CHUNK_UBIT_MASK;
300 }
301 
304 {
305  return ((h->params & CHUNK_UBIT_MASK) >> CHUNK_UBIT_SHIFT);
306 }
307 
308 always_inline void
310 {
311  h->params &= ~(CHUNK_BBIT_MASK);
312  h->params |= (1 << CHUNK_BBIT_SHIFT) & CHUNK_BBIT_MASK;
313 }
314 
317 {
318  return ((h->params & CHUNK_BBIT_MASK) >> CHUNK_BBIT_SHIFT);
319 }
320 
321 always_inline void
323 {
324  h->params &= ~(CHUNK_EBIT_MASK);
325  h->params |= (1 << CHUNK_EBIT_SHIFT) & CHUNK_EBIT_MASK;
326 }
327 
330 {
331  return ((h->params & CHUNK_EBIT_MASK) >> CHUNK_EBIT_SHIFT);
332 }
333 
334 always_inline void
336 {
337  h->params &= ~(CHUNK_TYPE_MASK);
338  h->params |= (t << CHUNK_TYPE_SHIFT) & CHUNK_TYPE_MASK;
339 }
340 
343 {
344  return ((h->params & CHUNK_TYPE_MASK) >> CHUNK_TYPE_SHIFT);
345 }
346 
347 always_inline void
349 {
350  h->params &= ~(CHUNK_LENGTH_MASK);
351  h->params |= (length << CHUNK_LENGTH_SHIFT) & CHUNK_LENGTH_MASK;
352 }
353 
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 {
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  */
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  */
420 
421  /*
422  * Identifies the stream to which the following user data belongs.
423  */
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  */
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  */
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 
458 
459 always_inline void
461 {
462  p->tsn = clib_host_to_net_u32 (tsn);
463 }
464 
467 {
468  return (clib_net_to_host_u32 (p->tsn));
469 }
470 
471 always_inline void
473 {
474  p->stream_id = clib_host_to_net_u16 (stream_id);
475 }
476 
479 {
480  return (clib_net_to_host_u16 (p->stream_id));
481 }
482 
483 always_inline void
485 {
486  p->stream_seq = clib_host_to_net_u16 (stream_seq);
487 }
488 
491 {
492  return (clib_net_to_host_u16 (p->stream_seq));
493 }
494 
495 always_inline void
497 {
498  p->payload_id = clib_host_to_net_u32 (payload_id);
499 }
500 
503 {
504  return (clib_net_to_host_u32 (p->payload_id));
505 }
506 
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 {
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  */
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  */
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  */
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  */
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  */
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 
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  */
691 
692 typedef struct
693 {
696 
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 {
714 
715  unsigned char mac[SHA1_OUTPUT_LENGTH]; /* RFC 2104 */
718 
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 {
741 
743 
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 {
758 
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 {
772 
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 {
799 
800  /*
801  * Contains an IPv4 address of the sending endpoint.
802  * It is binary encoded.
803  */
805 
807 
808 always_inline void
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 
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 {
837 
838  /*
839  * Contains an IPv6 address of the sending endpoint.
840  * It is binary encoded.
841  */
843 
845 
846 always_inline void
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 
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 {
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  */
896 
898 
899 always_inline void
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 
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 {
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 
948 
949 always_inline void
951 {
953  h->param_hdr.type = clib_host_to_net_u16 (SCTP_HOSTNAME_ADDRESS_TYPE);
954  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 {
978 
980 
982 
983 always_inline void
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
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 {
1023 
1024  u32 value[];
1025 
1027 
1028 always_inline void
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 {
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  */
1082 
1083  /*
1084  * This field indicates the updated receive buffer space in bytes of
1085  * the sender of this SACK.
1086  */
1088 
1089  /*
1090  * Indicates the number of Gap Ack Blocks included in this SACK.
1091  */
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  */
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  */
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  */
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  */
1124 
1126 
1127 always_inline void
1129  u32 cumulative_tsn_ack)
1130 {
1132  s->cumulative_tsn_ack = clib_host_to_net_u32 (cumulative_tsn_ack);
1133 }
1134 
1137 {
1138  return clib_net_to_host_u32 (s->cumulative_tsn_ack);
1139 }
1140 
1141 always_inline void
1143 {
1145  s->a_rwnd = clib_host_to_net_u32 (a_rwnd);
1146 }
1147 
1150 {
1151  return clib_net_to_host_u32 (s->a_rwnd);
1152 }
1153 
1154 always_inline void
1156  u16 gap_ack_blocks_count)
1157 {
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 
1171 {
1172  return clib_net_to_host_u32 (s->gap_ack_blocks_count);
1173 }
1174 
1175 always_inline void
1177  u16 duplicate_tsn_count)
1178 {
1180  s->duplicate_tsn_count = clib_host_to_net_u16 (duplicate_tsn_count);
1181 }
1182 
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 {
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  */
1219 
1221 
1222 always_inline void
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 {
1256 
1258 
1259 always_inline void
1261  sctp_hb_info_param_t * hb_info)
1262 {
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  */
1288 
1289 always_inline void
1291  sctp_hb_info_param_t * hb_info)
1292 {
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 
1315 
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 {
1341 
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 {
1376 
1378 
1379 always_inline void
1381 {
1383  // a->chunk_hdr.flags = clib_host_to_net_u16 (1);
1384 }
1385 
1386 always_inline void
1388 {
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 {
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  */
1425 
1427 
1428 always_inline void
1430  u32 tsn_last_chunk)
1431 {
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 {
1454 
1455 always_inline void
1457 {
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  */
static u32 vnet_sctp_get_cumulative_tsn_ack(sctp_selective_ack_chunk_t *s)
Definition: sctp_packet.h:1136
static u16 vnet_sctp_get_stream_id(sctp_payload_data_chunk_t *p)
Definition: sctp_packet.h:478
#define CHUNK_BBIT_MASK
Definition: sctp_packet.h:274
static void vnet_sctp_set_stream_id(sctp_payload_data_chunk_t *p, u16 stream_id)
Definition: sctp_packet.h:472
static void vnet_sctp_set_ebit(sctp_chunks_common_hdr_t *h)
Definition: sctp_packet.h:322
static void vnet_sctp_set_stream_seq(sctp_payload_data_chunk_t *p, u16 stream_seq)
Definition: sctp_packet.h:484
static void vnet_sctp_set_gap_ack_blocks_count(sctp_selective_ack_chunk_t *s, u16 gap_ack_blocks_count)
Definition: sctp_packet.h:1155
a
Definition: bitmap.h:516
static void vnet_sctp_set_hb_ack_info(sctp_hb_ack_chunk_t *h, sctp_hb_info_param_t *hb_info)
Definition: sctp_packet.h:1290
sctp_opt_params_hdr_t param_hdr
Definition: sctp_packet.h:935
u64 as_u64[2]
Definition: ip6_packet.h:51
#define NULL
Definition: clib.h:55
sctp_chunks_common_hdr_t chunk_hdr
Definition: sctp_packet.h:591
static u8 vnet_sctp_get_ebit(sctp_chunks_common_hdr_t *h)
Definition: sctp_packet.h:329
#define CHUNK_EBIT_SHIFT
Definition: sctp_packet.h:278
sctp_chunks_common_hdr_t chunk_hdr
Definition: sctp_packet.h:412
#define MAX_SUPPORTED_ADDRESS_TYPES
Definition: sctp_packet.h:958
#define SCTP_HOSTNAME_ADDRESS_TYPE
Definition: sctp_packet.h:784
static void vnet_sctp_set_hb_request_info(sctp_hb_req_chunk_t *h, sctp_hb_info_param_t *hb_info)
Definition: sctp_packet.h:1260
static void vnet_sctp_set_tsn_last_received_chunk(sctp_shutdown_association_chunk_t *s, u32 tsn_last_chunk)
Definition: sctp_packet.h:1429
#define SHA1_OUTPUT_LENGTH
Definition: sctp_packet.h:699
sctp_chunks_common_hdr_t chunk_hdr
Definition: sctp_packet.h:1254
static u16 vnet_get_sctp_dst_port(sctp_header_t *h)
Definition: sctp_packet.h:102
static u32 vnet_sctp_get_tsn(sctp_payload_data_chunk_t *p)
Definition: sctp_packet.h:466
static u32 vnet_get_sctp_checksum(sctp_header_t *h)
Definition: sctp_packet.h:126
sctp_chunks_common_hdr_t chunk_hdr
Definition: sctp_packet.h:1339
sctp_chunk_type
Definition: sctp_packet.h:150
static void vnet_sctp_common_hdr_params_host_to_net(sctp_chunks_common_hdr_t *h)
Definition: sctp_packet.h:284
sctp_chunks_common_hdr_t chunk_hdr
Definition: sctp_packet.h:1411
static void vnet_sctp_set_arwnd(sctp_selective_ack_chunk_t *s, u32 a_rwnd)
Definition: sctp_packet.h:1142
static void vnet_sctp_set_tbit(sctp_abort_chunk_t *a)
Definition: sctp_packet.h:1380
static void vnet_sctp_set_cumulative_tsn_ack(sctp_selective_ack_chunk_t *s, u32 cumulative_tsn_ack)
Definition: sctp_packet.h:1128
static u16 vnet_sctp_get_duplicate_tsn_count(sctp_selective_ack_chunk_t *s)
Definition: sctp_packet.h:1184
#define always_inline
Definition: clib.h:92
static void vnet_sctp_set_chunk_type(sctp_chunks_common_hdr_t *h, sctp_chunk_type t)
Definition: sctp_packet.h:335
static void vnet_sctp_set_duplicate_tsn_count(sctp_selective_ack_chunk_t *s, u16 duplicate_tsn_count)
Definition: sctp_packet.h:1176
#define FQDN_MAX_LENGTH
Definition: sctp_packet.h:914
static void vnet_sctp_common_hdr_params_net_to_host(sctp_chunks_common_hdr_t *h)
Definition: sctp_packet.h:290
sctp_header_t sctp_hdr
Definition: sctp_packet.h:1338
unsigned long u64
Definition: types.h:89
#define SCTP_STATE_COOKIE_TYPE
Definition: sctp_packet.h:780
static u32 vnet_sctp_get_cookie_preservative(sctp_cookie_preservative_param_t *c)
Definition: sctp_packet.h:909
static void vnet_sctp_set_ipv4_address(sctp_ipv4_addr_param_t *a, ip4_address_t address)
Definition: sctp_packet.h:809
static void vnet_sctp_set_state_cookie(sctp_state_cookie_param_t *s)
Definition: sctp_packet.h:1013
ip6_address_t address
Definition: sctp_packet.h:842
static u8 vnet_sctp_get_ubit(sctp_chunks_common_hdr_t *h)
Definition: sctp_packet.h:303
sctp_init_chunk_t sctp_init_ack_chunk_t
Definition: sctp_packet.h:690
static u16 vnet_get_sctp_src_port(sctp_header_t *h)
Definition: sctp_packet.h:90
static u8 vnet_sctp_get_bbit(sctp_chunks_common_hdr_t *h)
Definition: sctp_packet.h:316
sctp_opt_params_hdr_t param_hdr
Definition: sctp_packet.h:1203
#define CHUNK_UBIT_SHIFT
Definition: sctp_packet.h:272
sctp_header_t sctp_hdr
Definition: sctp_packet.h:1253
#define SCTP_IPV6_ADDRESS_TYPE
Definition: sctp_packet.h:778
static void vnet_sctp_set_tsn(sctp_payload_data_chunk_t *p, u32 tsn)
Definition: sctp_packet.h:460
u32 verification_tag
Definition: sctp_packet.h:73
static void vnet_set_sctp_dst_port(sctp_header_t *h, u16 dst_port)
Definition: sctp_packet.h:96
static u8 vnet_sctp_get_chunk_type(sctp_chunks_common_hdr_t *h)
Definition: sctp_packet.h:342
static u32 vnet_sctp_get_ipv4_address(sctp_ipv4_addr_param_t *a)
Definition: sctp_packet.h:817
sctp_hb_req_chunk_t sctp_hb_ack_chunk_t
Definition: sctp_packet.h:1287
sctp_chunks_common_hdr_t common_hdr
Definition: sctp_packet.h:261
ip4_address_t address
Definition: sctp_packet.h:804
#define CHUNK_UBIT_MASK
Definition: sctp_packet.h:271
svmdb_client_t * c
#define UNRECOGNIZED_PARAMETER
Definition: sctp_packet.h:1005
static void vnet_sctp_set_heartbeat_info(sctp_hb_info_param_t *h, u64 hb_info, u16 hb_info_length)
Definition: sctp_packet.h:1223
sctp_opt_params_hdr_t param_hdr
Definition: sctp_packet.h:836
static u16 vnet_sctp_get_gap_ack_blocks_count(sctp_selective_ack_chunk_t *s)
Definition: sctp_packet.h:1170
char hostname[FQDN_MAX_LENGTH]
Definition: sctp_packet.h:945
static void vnet_sctp_fill_shutdown_ack(sctp_shutdown_ack_chunk_t *s)
Definition: sctp_packet.h:1456
sctp_header_t sctp_hdr
Definition: sctp_packet.h:590
sctp_opt_params_hdr_t param_hdr
Definition: sctp_packet.h:1313
unsigned int u32
Definition: types.h:88
#define CHUNK_LENGTH_SHIFT
Definition: sctp_packet.h:281
static u16 vnet_sctp_calculate_padding(u16 base_length)
Definition: sctp_packet.h:508
#define CHUNK_TYPE_MASK
Definition: sctp_packet.h:265
static void vnet_sctp_set_ubit(sctp_chunks_common_hdr_t *h)
Definition: sctp_packet.h:296
static void vnet_sctp_set_ipv6_address(sctp_ipv6_addr_param_t *a, ip6_address_t address)
Definition: sctp_packet.h:847
sctp_chunks_common_hdr_t chunk_hdr
Definition: sctp_packet.h:1452
sctp_header_t sctp_hdr
Definition: sctp_packet.h:1373
static void * clib_mem_alloc(uword size)
Definition: mem.h:112
static void vnet_sctp_set_unrecognized_param(sctp_unrecognized_param_t *u)
Definition: sctp_packet.h:1029
sctp_hb_info_param_t hb_info
Definition: sctp_packet.h:1255
static void vnet_sctp_set_cookie_preservative(sctp_cookie_preservative_param_t *c, u32 life_span_inc)
Definition: sctp_packet.h:900
sctp_opt_params_hdr_t param_hdr
Definition: sctp_packet.h:1022
static void vnet_set_sctp_verification_tag(sctp_header_t *h, u32 verification_tag)
Definition: sctp_packet.h:108
unsigned short u16
Definition: types.h:57
#define SCTP_IPV4_ADDRESS_TYPE
Definition: sctp_packet.h:776
static void vnet_sctp_set_payload_id(sctp_payload_data_chunk_t *p, u32 payload_id)
Definition: sctp_packet.h:496
unsigned char u8
Definition: types.h:56
static u32 vnet_sctp_get_payload_id(sctp_payload_data_chunk_t *p)
Definition: sctp_packet.h:502
sctp_chunks_common_hdr_t chunk_hdr
Definition: sctp_packet.h:771
u16 address_type[MAX_SUPPORTED_ADDRESS_TYPES]
Definition: sctp_packet.h:979
static u16 vnet_sctp_get_chunk_length(sctp_chunks_common_hdr_t *h)
Definition: sctp_packet.h:355
static void vnet_sctp_unset_tbit(sctp_abort_chunk_t *a)
Definition: sctp_packet.h:1387
static u32 vnet_get_sctp_verification_tag(sctp_header_t *h)
Definition: sctp_packet.h:114
sctp_opt_params_hdr_t param_hdr
Definition: sctp_packet.h:977
#define CHUNK_TYPE_SHIFT
Definition: sctp_packet.h:266
static u16 vnet_sctp_get_stream_seq(sctp_payload_data_chunk_t *p)
Definition: sctp_packet.h:490
#define SCTP_COOKIE_PRESERVATIVE_TYPE
Definition: sctp_packet.h:782
static void vnet_sctp_set_bbit(sctp_chunks_common_hdr_t *h)
Definition: sctp_packet.h:309
#define CHUNK_EBIT_MASK
Definition: sctp_packet.h:277
sctp_header_t hdr
Definition: sctp_packet.h:260
static void vnet_set_sctp_src_port(sctp_header_t *h, u16 src_port)
Definition: sctp_packet.h:84
static ip6_address_t vnet_sctp_get_ipv6_address(sctp_ipv6_addr_param_t *a)
Definition: sctp_packet.h:856
sctp_chunks_common_hdr_t chunk_hdr
Definition: sctp_packet.h:1075
static void vnet_sctp_set_supported_address_types(sctp_supported_addr_types_param_t *s)
Definition: sctp_packet.h:984
sctp_opt_params_hdr_t param_hdr
Definition: sctp_packet.h:798
static void vnet_sctp_set_chunk_length(sctp_chunks_common_hdr_t *h, u16 length)
Definition: sctp_packet.h:348
static void vnet_sctp_set_hostname_address(sctp_hostname_param_t *h, char *hostname)
Definition: sctp_packet.h:950
#define CHUNK_BBIT_SHIFT
Definition: sctp_packet.h:275
#define CHUNK_LENGTH_MASK
Definition: sctp_packet.h:280
static u32 vnet_sctp_get_arwnd(sctp_selective_ack_chunk_t *s)
Definition: sctp_packet.h:1149
sctp_chunks_common_hdr_t chunk_hdr
Definition: sctp_packet.h:1374
static void vnet_set_sctp_checksum(sctp_header_t *h, u32 checksum)
Definition: sctp_packet.h:120
#define SCTP_SUPPORTED_ADDRESS_TYPES
Definition: sctp_packet.h:785