Introduce first version of TCP code.
[tldk.git] / lib / libtle_l4p / tcp_timer.h
1 /*
2  * Copyright (c) 2016  Intel Corporation.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at:
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15
16 #ifndef _TCP_TIMER_H_
17 #define _TCP_TIMER_H_
18
19 #include <tle_timer.h>
20
21 #ifdef __cplusplus
22 extern "C" {
23 #endif
24
25 /*
26  * internal defines.
27  * all RTO values are in ms.
28  */
29 #define TCP_RTO_MAX     60000U        /* RFC 6298 (2.5) */
30 #define TCP_RTO_MIN     1000U         /* RFC 6298 (2.4) */
31 #define TCP_RTO_2MSL    (2 * TCP_RTO_MAX)
32 #define TCP_RTO_DEFAULT TCP_RTO_MIN   /* RFC 6298 (2.1)*/
33 #define TCP_RTO_GRANULARITY     100U
34
35
36 static inline void
37 timer_stop(struct tle_tcp_stream *s)
38 {
39         struct tle_timer_wheel *tw;
40
41         if (s->timer.handle != NULL) {
42                 tw = CTX_TCP_TMWHL(s->s.ctx);
43                 tle_timer_stop(tw, s->timer.handle);
44                 s->timer.handle = NULL;
45         }
46 }
47
48 static inline void
49 timer_start(struct tle_tcp_stream *s)
50 {
51         struct tle_timer_wheel *tw;
52
53         if (s->timer.handle == NULL) {
54                 tw = CTX_TCP_TMWHL(s->s.ctx);
55                 s->timer.handle = tle_timer_start(tw, s, s->tcb.snd.rto);
56                 s->tcb.snd.nb_retx = 0;
57         }
58 }
59
60 static inline void
61 timer_restart(struct tle_tcp_stream *s)
62 {
63         struct tle_timer_wheel *tw;
64
65         tw = CTX_TCP_TMWHL(s->s.ctx);
66         s->timer.handle = tle_timer_start(tw, s, s->tcb.snd.rto);
67 }
68
69
70 /*
71  * reset number of retransmissions and restart RTO timer.
72  */
73 static inline void
74 timer_reset(struct tle_tcp_stream *s)
75 {
76         timer_stop(s);
77         timer_start(s);
78 }
79
80 static inline uint32_t
81 rto_roundup(uint32_t rto)
82 {
83         rto = RTE_MAX(rto, TCP_RTO_MIN);
84         rto = RTE_MIN(rto, TCP_RTO_MAX);
85         return rto;
86 }
87
88 /*
89  * RFC6298: Computing TCP's Retransmission Timer
90  * RTTVAR <- (1 - beta) * RTTVAR + beta * |SRTT - R'|
91  * SRTT <- (1 - alpha) * SRTT + alpha * R'
92  * RTO <- SRTT + max (G, K*RTTVAR)
93  * the following computation is based on Jacobson'88 paper referenced
94  * in the RFC6298
95 */
96 static inline void
97 rto_estimate(struct tcb *tcb, int32_t rtt)
98 {
99         uint32_t rto;
100
101         if (!rtt)
102                 rtt = 1;
103         if (tcb->rcv.srtt) {
104                 rtt -= (tcb->rcv.srtt >> 3); /* alpha = 1/8 */
105                 tcb->rcv.srtt += rtt;
106
107                 if (rtt < 0)
108                         rtt = -rtt;
109                 rtt -= (tcb->rcv.rttvar >> 2); /* beta = 1/4 */
110                 tcb->rcv.rttvar += rtt;
111
112         } else {
113                 tcb->rcv.srtt = rtt << 3;
114                 tcb->rcv.rttvar = rtt << 1;
115         }
116
117         rto = (tcb->rcv.srtt >> 3) +
118                 RTE_MAX(TCP_RTO_GRANULARITY, tcb->rcv.rttvar);
119         tcb->snd.rto = rto_roundup(rto);
120 }
121
122 #ifdef __cplusplus
123 }
124 #endif
125
126 #endif /* _TCP_TIMER_H_ */