Revert "l4p/tcp: introduce tle_tcp_stream_establish() API"
[tldk.git] / lib / libtle_l4p / syncookie.h
1 /*
2  * Copyright (c) 2016-2017  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 _SYNCOOKIE_H_
17 #define _SYNCOOKIE_H_
18
19 #include <rte_jhash.h>
20
21 #include "tcp_misc.h"
22 #include <tle_ctx.h>
23 #include <halfsiphash.h>
24
25 #ifdef __cplusplus
26 extern "C" {
27 #endif
28
29 struct sync_in4 {
30         uint32_t seq;
31         union l4_ports port;
32         union ipv4_addrs addr;
33 };
34
35 static const rte_xmm_t mss4len = {
36         .u32 = {
37                 TCP4_MIN_MSS, /* 536 */
38                 1300,
39                 TCP4_OP_MSS,  /* 1440 */
40                 TCP4_NOP_MSS, /* 1460 */
41         },
42 };
43
44 static const rte_xmm_t mss6len = {
45         .u32 = {
46                 TCP6_MIN_MSS, /* 1220 */
47                 TCP6_OP_MSS,  /* 1420 */
48                 TCP6_NOP_MSS, /* 1440 */
49                 8940,
50         },
51 };
52
53 #define SYNC_MSS_BITS   2
54 #define SYNC_MSS_MASK   ((1 << SYNC_MSS_BITS) - 1)
55
56 #define SYNC_TMS_WSCALE_BITS    4
57 #define SYNC_TMS_WSCALE_MASK    ((1 << SYNC_TMS_WSCALE_BITS) - 1)
58
59 #define SYNC_TMS_RESERVE_BITS   2
60
61 #define SYNC_TMS_OPT_BITS       (SYNC_TMS_WSCALE_BITS + SYNC_TMS_RESERVE_BITS)
62 #define SYNC_TMS_OPT_MASK       ((1 << SYNC_TMS_OPT_BITS) - 1)
63
64 /* allow around 2 minutes for 3-way handshake. */
65 #define SYNC_MAX_TMO    0x20000
66
67 /* ??? use SipHash as FreeBSD does. ??? */
68 static inline uint32_t
69 sync_hash4(const union pkt_info *pi, uint32_t seq, rte_xmm_t *secret_key,
70                 uint32_t hash_alg)
71 {
72         struct sync_in4 in4;
73         rte_xmm_t state;
74         uint32_t v0, v1;
75
76         in4.seq = seq;
77         in4.port = pi->port;
78         in4.addr = pi->addr4;
79
80         if (hash_alg == TLE_JHASH) {
81                 v0 = secret_key->u32[0];
82                 v1 = secret_key->u32[1];
83                 rte_jhash_32b_2hashes(&in4.seq, sizeof(in4) / sizeof(uint32_t),
84                                 &v0, &v1);
85                 return v0 + v1;
86         } else {
87                 state = *secret_key;
88                 siphash_compression(&in4.seq, sizeof(in4) / sizeof(uint32_t),
89                                 &state);
90                 siphash_finalization(&state);
91                 return (state.u32[0] ^ state.u32[1] ^
92                         state.u32[2] ^ state.u32[3]);
93         }
94 }
95
96 static inline uint32_t
97 sync_hash6(const union pkt_info *pi, uint32_t seq, rte_xmm_t *secret_key,
98                 uint32_t hash_alg)
99 {
100         uint32_t port_seq[2];
101         rte_xmm_t state;
102         uint32_t v0, v1;
103
104         if (hash_alg == TLE_JHASH) {
105                 v0 = secret_key->u32[0];
106                 v1 = secret_key->u32[1];
107                 rte_jhash_32b_2hashes(pi->addr6->raw.u32,
108                                 sizeof(*pi->addr6) / sizeof(uint32_t),
109                                 &v0, &v1);
110                 return rte_jhash_3words(v0, seq, pi->port.raw, v1);
111         } else {
112                 state = *secret_key;
113                 siphash_compression(pi->addr6->raw.u32,
114                                 sizeof(*pi->addr6) / sizeof(uint32_t), &state);
115                 port_seq[0] = pi->port.raw;
116                 port_seq[1] = seq;
117                 siphash_compression(port_seq, RTE_DIM(port_seq), &state);
118                 siphash_finalization(&state);
119                 return (state.u32[0] ^ state.u32[1] ^
120                         state.u32[2] ^ state.u32[3]);
121         }
122 }
123
124 static inline uint32_t
125 sync_mss2idx(uint16_t mss, const rte_xmm_t *msl)
126 {
127         if (mss >= msl->u32[2])
128                 return (mss >= msl->u32[3]) ? 3 : 2;
129         else
130                 return (mss >= msl->u32[1]) ? 1 : 0;
131 }
132
133 static inline uint32_t
134 sync_gen_seq(const union pkt_info *pi, uint32_t seq, uint32_t ts, uint16_t mss,
135                 uint32_t hash_alg, rte_xmm_t *secret_key)
136 {
137         uint32_t h, mi;
138
139         if (pi->tf.type == TLE_V4) {
140                 h = sync_hash4(pi, seq, secret_key, hash_alg);
141                 mi = sync_mss2idx(mss, &mss4len);
142         } else {
143                 h = sync_hash6(pi, seq, secret_key, hash_alg);
144                 mi = sync_mss2idx(mss, &mss6len);
145         }
146
147         h += (ts & ~SYNC_MSS_MASK) | mi;
148         return h;
149 }
150
151 static inline uint32_t
152 sync_gen_ts(uint32_t ts, uint32_t wscale)
153 {
154         ts = (ts - (SYNC_TMS_OPT_MASK + 1)) & ~SYNC_TMS_OPT_MASK;
155         ts |= wscale;
156         return ts;
157 }
158
159 static inline int
160 sync_check_ack(const union pkt_info *pi, uint32_t seq, uint32_t ack,
161         uint32_t ts, uint32_t hash_alg, rte_xmm_t *secret_key)
162 {
163         uint32_t h, mi, pts;
164
165         if (pi->tf.type == TLE_V4)
166                 h = sync_hash4(pi, seq, secret_key, hash_alg);
167         else
168                 h = sync_hash6(pi, seq, secret_key, hash_alg);
169
170         h = ack - h;
171         pts = h & ~SYNC_MSS_MASK;
172         mi = h & SYNC_MSS_MASK;
173
174         if (ts - pts > SYNC_MAX_TMO)
175                 return -ERANGE;
176
177         return (pi->tf.type == TLE_V4) ? mss4len.u32[mi] : mss6len.u32[mi];
178 }
179
180 static inline void
181 sync_fill_tcb(struct tcb *tcb, const union seg_info *si, const union tsopt *to)
182 {
183         uint32_t ack, mss, seq, wscale;
184
185         seq = si->seq;
186
187         tcb->rcv.nxt = seq;
188         tcb->rcv.irs = seq - 1;
189         tcb->snd.wu.wl1 = seq;
190
191         ack = si->ack;
192
193         tcb->snd.nxt = ack;
194         tcb->snd.una = ack;
195         tcb->snd.iss = ack - 1;
196         tcb->snd.rcvr = ack - 1;
197         tcb->snd.wu.wl2 = ack;
198
199         mss = si->mss;
200
201         tcb->snd.mss = mss;
202         tcb->so.mss = mss;
203
204         tcb->snd.ts = to->ecr;
205         tcb->rcv.ts = to->val;
206         tcb->so.ts.raw = to->raw;
207
208         wscale = to->ecr & SYNC_TMS_WSCALE_MASK;
209
210         tcb->snd.wscale = wscale;
211         tcb->snd.wnd = si->wnd << wscale;
212         tcb->so.wscale = wscale;
213
214         tcb->rcv.wscale = (wscale == TCP_WSCALE_NONE) ?
215                 TCP_WSCALE_NONE : TCP_WSCALE_DEFAULT;
216 }
217
218 #ifdef __cplusplus
219 }
220 #endif
221
222 #endif /* _STREAM_TABLE_H_ */