syncookie.h revision aa97dd1c
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 _SYNCOOKIE_H_
17#define _SYNCOOKIE_H_
18
19#include "tcp_misc.h"
20#include <rte_jhash.h>
21
22#ifdef __cplusplus
23extern "C" {
24#endif
25
26#define	SYNC_SEED0	0x736f6d65
27#define	SYNC_SEED1	0x646f7261
28
29struct sync_in4 {
30	uint32_t seq;
31	union l4_ports port;
32	union ipv4_addrs addr;
33};
34
35static 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
44static 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
68/* ??? use SipHash as FreeBSD does. ??? */
69static inline uint32_t
70sync_hash4(const union pkt_info *pi, uint32_t seq)
71{
72	uint32_t v0, v1;
73	struct sync_in4 in4;
74
75	in4.seq = seq;
76	in4.port = pi->port;
77	in4.addr = pi->addr4;
78
79	v0 = SYNC_SEED0;
80	v1 = SYNC_SEED1;
81	rte_jhash_32b_2hashes(&in4.seq, sizeof(in4) / sizeof(uint32_t),
82		&v0, &v1);
83	return v0 + v1;
84}
85
86static inline uint32_t
87sync_hash6(const union pkt_info *pi, uint32_t seq)
88{
89	uint32_t v0, v1;
90
91	v0 = SYNC_SEED0;
92	v1 = SYNC_SEED1;
93	rte_jhash_32b_2hashes(pi->addr6->raw.u32,
94		sizeof(*pi->addr6) / sizeof(uint32_t), &v0, &v1);
95	return rte_jhash_3words(v0, seq, pi->port.raw, v1);
96}
97
98static inline uint32_t
99sync_mss2idx(uint16_t mss, const rte_xmm_t *msl)
100{
101	if (mss >= msl->u32[2])
102		return (mss >= msl->u32[3]) ? 3 : 2;
103	else
104		return (mss >= msl->u32[1]) ? 1 : 0;
105}
106
107static inline uint32_t
108sync_gen_seq(const union pkt_info *pi, uint32_t seq, uint32_t ts, uint16_t mss)
109{
110	uint32_t h, mi;
111
112	if (pi->tf.type == TLE_V4) {
113		h = sync_hash4(pi, seq);
114		mi = sync_mss2idx(mss, &mss4len);
115	} else {
116		h = sync_hash6(pi, seq);
117		mi = sync_mss2idx(mss, &mss6len);
118	}
119
120	h += (ts & ~SYNC_MSS_MASK) | mi;
121	return h;
122}
123
124static inline uint32_t
125sync_gen_ts(uint32_t ts, uint32_t wscale)
126{
127	ts = (ts - (SYNC_TMS_OPT_MASK + 1)) & ~SYNC_TMS_OPT_MASK;
128	ts |= wscale;
129	return ts;
130}
131
132static inline int
133sync_check_ack(const union pkt_info *pi, uint32_t seq, uint32_t ack,
134	uint32_t ts)
135{
136	uint32_t h, mi, pts;
137
138	h = (pi->tf.type == TLE_V4) ? sync_hash4(pi, seq) : sync_hash6(pi, seq);
139
140	h = ack - h;
141	pts = h & ~SYNC_MSS_MASK;
142	mi = h & SYNC_MSS_MASK;
143
144	if (ts - pts > SYNC_MAX_TMO)
145		return -ERANGE;
146
147	return (pi->tf.type == TLE_V4) ? mss4len.u32[mi] : mss6len.u32[mi];
148}
149
150static inline void
151sync_get_opts(struct syn_opts *so, uintptr_t p, uint32_t len)
152{
153	so->ts = get_tms_opts(p, len);
154	so->wscale = so->ts.ecr & SYNC_TMS_WSCALE_MASK;
155}
156
157static inline void
158sync_fill_tcb(struct tcb *tcb, const union seg_info *si,
159	const struct rte_mbuf *mb)
160{
161	const struct tcp_hdr *th;
162
163	th = rte_pktmbuf_mtod_offset(mb, const struct tcp_hdr *,
164		mb->l2_len + mb->l3_len);
165
166	tcb->rcv.nxt = si->seq;
167	tcb->rcv.irs = si->seq - 1;
168
169	tcb->snd.nxt = si->ack;
170	tcb->snd.una = si->ack;
171	tcb->snd.iss = si->ack - 1;
172	tcb->snd.rcvr = tcb->snd.iss;
173
174	tcb->snd.wu.wl1 = si->seq;
175	tcb->snd.wu.wl2 = si->ack;
176
177	get_syn_opts(&tcb->so, (uintptr_t)(th + 1), mb->l4_len - sizeof(*th));
178
179	tcb->snd.wscale = tcb->so.wscale;
180	tcb->snd.mss = tcb->so.mss;
181	tcb->snd.wnd = si->wnd << tcb->snd.wscale;
182
183	tcb->snd.ts = tcb->so.ts.ecr;
184	tcb->rcv.ts = tcb->so.ts.val;
185
186	tcb->rcv.wscale = (tcb->so.wscale == TCP_WSCALE_NONE) ?
187		TCP_WSCALE_NONE : TCP_WSCALE_DEFAULT;
188}
189
190#ifdef __cplusplus
191}
192#endif
193
194#endif /* _STREAM_TABLE_H_ */
195