Prep-work patch for congestion-control
[vpp.git] / src / vnet / sctp / sctp.h
index 7c4df30..3e3750e 100644 (file)
@@ -28,6 +28,7 @@
   _(T1_COOKIE, "T1_COOKIE")                            \
   _(T2_SHUTDOWN, "T2_SHUTDOWN")                \
   _(T3_RXTX, "T3_RXTX")                                        \
+  _(T4_HEARTBEAT, "T4_HB")                                     \
   _(T5_SHUTDOWN_GUARD, "T5_SHUTDOWN_GUARD")
 
 typedef enum _sctp_timers
@@ -71,58 +72,125 @@ typedef struct _sctp_sub_connection
 {
   transport_connection_t connection;         /**< Common transport data. First! */
   void *parent;                                                                /**< Link to the parent-super connection */
-  u32 timers[SCTP_N_TIMERS];           /**< Timer handles into timer wheel */
+
+  u32 error_count; /**< The current error count for this destination. */
+  u32 error_threshold; /**< Current error threshold for this destination,
+                               i.e. what value marks the destination down if error count reaches this value. */
+  u32 cwnd; /**< The current congestion window. */
+  u32 ssthresh;        /**< The current ssthresh value. */
+
+  u32 RTO; /**< The current retransmission timeout value. */
+  u32 SRTT; /**< The current smoothed round-trip time. */
+  u32 RTTVAR; /**< The current RTT variation. */
+
+  u32 partially_acked_bytes; /**< The tracking method for increase of cwnd when in
+                                 congestion avoidance mode (see Section 7.2.2).*/
+
+  u8 state; /**< The current state of this destination, i.e., DOWN, UP, ALLOW-HB, NO-HEARTBEAT, etc. */
+
+  u16 PMTU; /**< The current known path MTU. */
+
+  u32 timers[SCTP_N_TIMERS]; /**< A timer used by each destination. */
+
+  u8 RTO_pending; /**< A flag used to track if one of the DATA chunks sent to
+                                 this address is currently being used to compute an RTT.
+                                 If this flag is 0, the next DATA chunk sent to this destination
+                                 should be used to compute an RTT and this flag should be set.
+                                 Every time the RTT calculation completes (i.e., the DATA chunk is SACK'd),
+                                 clear this flag. */
+
+  u32 last_time; /**< The time to which this destination was last sent a packet to.
+                                 This can be used to determine if a HEARTBEAT is needed. */
 
 } sctp_sub_connection_t;
 
 typedef struct
 {
-  u32 a_rwnd;          /**< Maximum segment size advertised */
+  u32 a_rwnd; /**< Maximum segment size advertised */
 
 } sctp_options_t;
 
+#define SetBit(A,k)     ( A[(k/32)] |= (1 << (k%32)) )
+#define ClearBit(A,k)   ( A[(k/32)] &= ~(1 << (k%32)) )
+#define TestBit(A,k)    ( A[(k/32)] & (1 << (k%32)) )
+
+#define MAX_INFLIGHT_PACKETS   128
+#define MAX_ENQUEABLE_SACKS 2
+
+/* This parameter indicates to the receiver how much increment in
+ * milliseconds the sender wishes the receiver to add to its default
+ * cookie life-span.
+ */
+#define SUGGESTED_COOKIE_LIFE_SPAN_INCREMENT 1000
+
 typedef struct _sctp_connection
 {
-  sctp_sub_connection_t sub_conn[MAX_SCTP_CONNECTIONS];               /**< Common transport data. First! */
+  sctp_sub_connection_t sub_conn[MAX_SCTP_CONNECTIONS];        /**< Common transport data. First! */
 
   u8 state;                    /**< SCTP state as per sctp_state_t */
   u16 flags;           /**< Chunk flag (see sctp_chunks_common_hdr_t) */
+
   u32 local_tag;       /**< INIT_TAG generated locally */
   u32 remote_tag;      /**< INIT_TAG generated by the remote peer */
-  u16 life_span_inc;
-
-  /** Send sequence variables RFC4960 */
-  u32 snd_una;         /**< oldest unacknowledged sequence number */
-  u32 snd_una_max;     /**< newest unacknowledged sequence number + 1*/
-  u32 snd_wl1;         /**< seq number used for last snd.wnd update */
-  u32 snd_wl2;         /**< ack number used for last snd.wnd update */
-  u32 snd_nxt;         /**< next seq number to be sent */
-
-  /** Receive sequence variables RFC4960 */
-  u32 rcv_nxt;         /**< next sequence number expected */
-  u32 rcv_las;         /**< rcv_nxt at last ack sent/rcv_wnd update */
-  u32 iss;             /**< initial sent sequence */
-  u32 irs;             /**< initial remote sequence */
-
-  /* RTT and RTO */
-  u32 rto;             /**< Retransmission timeout */
-  u32 rto_boff;                /**< Index for RTO backoff */
-  u32 srtt;            /**< Smoothed RTT */
-  u32 rttvar;          /**< Smoothed mean RTT difference. Approximates variance */
-  u32 rtt_ts;          /**< Timestamp for tracked ACK */
-  u32 rtt_seq;         /**< Sequence number for tracked ACK */
-
-  u32 a_rwnd;                  /** Constrained by medium / IP / etc. */
+
+  u32 local_initial_tsn; /**< Initial TSN generated locally */
+  u32 remote_initial_tsn; /**< Initial TSN generated by the remote-peer */
+
+  u32 peer_cookie_life_span_increment;
+
+  u32 overall_err_count; /**< The overall association error count. */
+  u32 overall_err_treshold; /**< The threshold for this association that if the Overall Error Count
+                                 reaches will cause this association to be torn down. */
+
+  u32 peer_rwnd; /**< Current calculated value of the peer's rwnd. */
+
+  u32 next_tsn;        /**< The next TSN number to be assigned to a new DATA chunk.
+                 This is sent in the INIT or INIT ACK chunk to the peer
+                 and incremented each time a DATA chunk is assigned a
+                 TSN (normally just prior to transmit or during
+                 fragmentation). */
+
+  u32 next_tsn_expected; /**< The next TSN number expected to be received. */
+
+  u32 last_rcvd_tsn; /**< This is the last TSN received in sequence. This value
+                        is set initially by taking the peer's initial TSN,
+                 received in the INIT or INIT ACK chunk, and
+                 subtracting one from it. */
+
+  u32 out_of_order_map[MAX_INFLIGHT_PACKETS]; /**< An array of bits or bytes indicating which out-of-order
+                               TSNs have been received (relative to the Last Rcvd TSN).
+                               If no gaps exist, i.e., no out-of-order packets have been received,
+                               this array will be set to all zero. */
+
+  u8 ack_state;        /**< This flag indicates if the next received packet is set to be responded to with a SACK.
+                               This is initialized to 0. When a packet is received it is incremented.
+                               If this value reaches 2 or more, a SACK is sent and the value is reset to 0.
+                               Note: This is used only when no DATA chunks are received out-of-order.
+                               When DATA chunks are out-of-order, SACKs are not delayed (see Section 6). */
+
+  u32 a_rwnd; /** This value represents the dedicated buffer space, in number of bytes,
+                               the sender of the INIT has reserved in association with this window.
+                               During the life of the association, this buffer space SHOULD NOT be lessened
+                               (i.e., dedicated buffers taken away from this association);
+                               however, an endpoint MAY change the value of a_rwnd it sends in SACK chunks. */
+
+  u32 smallest_PMTU; /** The smallest PMTU discovered for all of the peer's transport addresses. */
+
   u32 rcv_a_rwnd;              /**< LOCAL max seg size that includes options. To be updated by congestion algos, etc. */
   u32 snd_a_rwnd;              /**< REMOTE max seg size that includes options. To be updated if peer pushes back on window, etc.*/
+
+  u32 rtt_ts;
+  u32 rtt_seq;
+
   sctp_options_t rcv_opts;
   sctp_options_t snd_opts;
-  u32 snd_hdr_length;  /**< BASE HEADER LENGTH for the DATA chunk when sending */
 
+  u32 snd_hdr_length;  /**< BASE HEADER LENGTH for the DATA chunk when sending */
   u8 next_avail_sub_conn; /**< Represent the index of the next free slot in sub_conn */
+
 } sctp_connection_t;
 
-typedef void (timer_expiration_handler) (u32 index);
+typedef void (sctp_timer_expiration_handler) (u32 conn_index, u32 timer_id);
 
 sctp_connection_t *sctp_connection_new (u8 thread_index);
 void sctp_sub_connection_add_ip4 (u8 thread_index,
@@ -155,7 +223,7 @@ clib_error_t *sctp_init (vlib_main_t * vm);
 void sctp_connection_timers_init (sctp_connection_t * tc);
 void sctp_connection_timers_reset (sctp_connection_t * tc);
 void sctp_init_snd_vars (sctp_connection_t * tc);
-void sctp_connection_init_vars (sctp_connection_t * tc);
+void sctp_init_mss (sctp_connection_t * tc);
 
 void sctp_prepare_initack_chunk (sctp_connection_t * ts, vlib_buffer_t * b,
                                 ip4_address_t * ip4_addr,
@@ -522,6 +590,7 @@ sctp_timer_update (sctp_connection_t * tc, u8 conn_idx, u8 timer_id,
   if (tc->sub_conn[conn_idx].timers[timer_id] != SCTP_TIMER_HANDLE_INVALID)
     tw_timer_stop_16t_2w_512sl (&sctp_main.timer_wheels[sub->c_thread_index],
                                sub->timers[timer_id]);
+
   tc->sub_conn[conn_idx].timers[timer_id] =
     tw_timer_start_16t_2w_512sl (&sctp_main.timer_wheels[sub->c_thread_index],
                                 sub->c_c_index, timer_id, interval);