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:
7 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 #include <rte_jhash.h>
23 #include <halfsiphash.h>
32 union ipv4_addrs addr;
35 static const rte_xmm_t mss4len = {
37 TCP4_MIN_MSS, /* 536 */
39 TCP4_OP_MSS, /* 1440 */
40 TCP4_NOP_MSS, /* 1460 */
44 static const rte_xmm_t mss6len = {
46 TCP6_MIN_MSS, /* 1220 */
47 TCP6_OP_MSS, /* 1420 */
48 TCP6_NOP_MSS, /* 1440 */
53 #define SYNC_MSS_BITS 2
54 #define SYNC_MSS_MASK ((1 << SYNC_MSS_BITS) - 1)
56 #define SYNC_TMS_WSCALE_BITS 4
57 #define SYNC_TMS_WSCALE_MASK ((1 << SYNC_TMS_WSCALE_BITS) - 1)
59 #define SYNC_TMS_RESERVE_BITS 2
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)
64 /* allow around 2 minutes for 3-way handshake. */
65 #define SYNC_MAX_TMO 0x20000
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,
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),
88 siphash_compression(&in4.seq, sizeof(in4) / sizeof(uint32_t),
90 siphash_finalization(&state);
91 return (state.u32[0] ^ state.u32[1] ^
92 state.u32[2] ^ state.u32[3]);
96 static inline uint32_t
97 sync_hash6(const union pkt_info *pi, uint32_t seq, rte_xmm_t *secret_key,
100 uint32_t port_seq[2];
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),
110 return rte_jhash_3words(v0, seq, pi->port.raw, v1);
113 siphash_compression(pi->addr6->raw.u32,
114 sizeof(*pi->addr6) / sizeof(uint32_t), &state);
115 port_seq[0] = pi->port.raw;
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]);
124 static inline uint32_t
125 sync_mss2idx(uint16_t mss, const rte_xmm_t *msl)
127 if (mss >= msl->u32[2])
128 return (mss >= msl->u32[3]) ? 3 : 2;
130 return (mss >= msl->u32[1]) ? 1 : 0;
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)
139 if (pi->tf.type == TLE_V4) {
140 h = sync_hash4(pi, seq, secret_key, hash_alg);
141 mi = sync_mss2idx(mss, &mss4len);
143 h = sync_hash6(pi, seq, secret_key, hash_alg);
144 mi = sync_mss2idx(mss, &mss6len);
147 h += (ts & ~SYNC_MSS_MASK) | mi;
151 static inline uint32_t
152 sync_gen_ts(uint32_t ts, uint32_t wscale)
154 ts = (ts - (SYNC_TMS_OPT_MASK + 1)) & ~SYNC_TMS_OPT_MASK;
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)
165 if (pi->tf.type == TLE_V4)
166 h = sync_hash4(pi, seq, secret_key, hash_alg);
168 h = sync_hash6(pi, seq, secret_key, hash_alg);
171 pts = h & ~SYNC_MSS_MASK;
172 mi = h & SYNC_MSS_MASK;
174 if (ts - pts > SYNC_MAX_TMO)
177 return (pi->tf.type == TLE_V4) ? mss4len.u32[mi] : mss6len.u32[mi];
181 sync_fill_tcb(struct tcb *tcb, const union seg_info *si, const union tsopt *to)
183 uint32_t ack, mss, seq, wscale;
188 tcb->rcv.irs = seq - 1;
189 tcb->snd.wu.wl1 = seq;
195 tcb->snd.iss = ack - 1;
196 tcb->snd.rcvr = ack - 1;
197 tcb->snd.wu.wl2 = ack;
204 tcb->snd.ts = to->ecr;
205 tcb->rcv.ts = to->val;
206 tcb->so.ts.raw = to->raw;
208 wscale = to->ecr & SYNC_TMS_WSCALE_MASK;
210 tcb->snd.wscale = wscale;
211 tcb->snd.wnd = si->wnd << wscale;
212 tcb->so.wscale = wscale;
214 tcb->rcv.wscale = (wscale == TCP_WSCALE_NONE) ?
215 TCP_WSCALE_NONE : TCP_WSCALE_DEFAULT;
222 #endif /* _STREAM_TABLE_H_ */