diff options
Diffstat (limited to 'lib/libtle_l4p/syncookie.h')
-rw-r--r-- | lib/libtle_l4p/syncookie.h | 194 |
1 files changed, 194 insertions, 0 deletions
diff --git a/lib/libtle_l4p/syncookie.h b/lib/libtle_l4p/syncookie.h new file mode 100644 index 0000000..276d45a --- /dev/null +++ b/lib/libtle_l4p/syncookie.h @@ -0,0 +1,194 @@ +/* + * Copyright (c) 2016 Intel Corporation. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _SYNCOOKIE_H_ +#define _SYNCOOKIE_H_ + +#include "tcp_misc.h" +#include <rte_jhash.h> + +#ifdef __cplusplus +extern "C" { +#endif + +#define SYNC_SEED0 0x736f6d65 +#define SYNC_SEED1 0x646f7261 + +struct sync_in4 { + uint32_t seq; + union l4_ports port; + union ipv4_addrs addr; +}; + +static const rte_xmm_t mss4len = { + .u32 = { + TCP4_MIN_MSS, /* 536 */ + 1300, + TCP4_OP_MSS, /* 1440 */ + TCP4_NOP_MSS, /* 1460 */ + }, +}; + +static const rte_xmm_t mss6len = { + .u32 = { + TCP6_MIN_MSS, /* 1220 */ + TCP6_OP_MSS, /* 1420 */ + TCP6_NOP_MSS, /* 1440 */ + 8940, + }, +}; + +#define SYNC_MSS_BITS 2 +#define SYNC_MSS_MASK ((1 << SYNC_MSS_BITS) - 1) + +#define SYNC_TMS_WSCALE_BITS 4 +#define SYNC_TMS_WSCALE_MASK ((1 << SYNC_TMS_WSCALE_BITS) - 1) + +#define SYNC_TMS_RESERVE_BITS 2 + +#define SYNC_TMS_OPT_BITS (SYNC_TMS_WSCALE_BITS + SYNC_TMS_RESERVE_BITS) +#define SYNC_TMS_OPT_MASK ((1 << SYNC_TMS_OPT_BITS) - 1) + +/* allow around 2 minutes for 3-way handshake. */ +#define SYNC_MAX_TMO 0x20000 + + +/* ??? use SipHash as FreeBSD does. ??? */ +static inline uint32_t +sync_hash4(const union pkt_info *pi, uint32_t seq) +{ + uint32_t v0, v1; + struct sync_in4 in4; + + in4.seq = seq; + in4.port = pi->port; + in4.addr = pi->addr4; + + v0 = SYNC_SEED0; + v1 = SYNC_SEED1; + rte_jhash_32b_2hashes(&in4.seq, sizeof(in4) / sizeof(uint32_t), + &v0, &v1); + return v0 + v1; +} + +static inline uint32_t +sync_hash6(const union pkt_info *pi, uint32_t seq) +{ + uint32_t v0, v1; + + v0 = SYNC_SEED0; + v1 = SYNC_SEED1; + rte_jhash_32b_2hashes(pi->addr6->raw.u32, + sizeof(*pi->addr6) / sizeof(uint32_t), &v0, &v1); + return rte_jhash_3words(v0, seq, pi->port.raw, v1); +} + +static inline uint32_t +sync_mss2idx(uint16_t mss, const rte_xmm_t *msl) +{ + if (mss >= msl->u32[2]) + return (mss >= msl->u32[3]) ? 3 : 2; + else + return (mss >= msl->u32[1]) ? 1 : 0; +} + +static inline uint32_t +sync_gen_seq(const union pkt_info *pi, uint32_t seq, uint32_t ts, uint16_t mss) +{ + uint32_t h, mi; + + if (pi->tf.type == TLE_V4) { + h = sync_hash4(pi, seq); + mi = sync_mss2idx(mss, &mss4len); + } else { + h = sync_hash6(pi, seq); + mi = sync_mss2idx(mss, &mss6len); + } + + h += (ts & ~SYNC_MSS_MASK) | mi; + return h; +} + +static inline uint32_t +sync_gen_ts(uint32_t ts, uint32_t wscale) +{ + ts = (ts - (SYNC_TMS_OPT_MASK + 1)) & ~SYNC_TMS_OPT_MASK; + ts |= wscale; + return ts; +} + +static inline int +sync_check_ack(const union pkt_info *pi, uint32_t seq, uint32_t ack, + uint32_t ts) +{ + uint32_t h, mi, pts; + + h = (pi->tf.type == TLE_V4) ? sync_hash4(pi, seq) : sync_hash6(pi, seq); + + h = ack - h; + pts = h & ~SYNC_MSS_MASK; + mi = h & SYNC_MSS_MASK; + + if (ts - pts > SYNC_MAX_TMO) + return -ERANGE; + + return (pi->tf.type == TLE_V4) ? mss4len.u32[mi] : mss6len.u32[mi]; +} + +static inline void +sync_get_opts(struct syn_opts *so, uintptr_t p, uint32_t len) +{ + so->ts = get_tms_opts(p, len); + so->wscale = so->ts.ecr & SYNC_TMS_WSCALE_MASK; +} + +static inline void +sync_fill_tcb(struct tcb *tcb, const union seg_info *si, + const struct rte_mbuf *mb) +{ + const struct tcp_hdr *th; + + th = rte_pktmbuf_mtod_offset(mb, const struct tcp_hdr *, + mb->l2_len + mb->l3_len); + + tcb->rcv.nxt = si->seq; + tcb->rcv.irs = si->seq - 1; + + tcb->snd.nxt = si->ack; + tcb->snd.una = si->ack; + tcb->snd.iss = si->ack - 1; + tcb->snd.rcvr = tcb->snd.iss; + + tcb->snd.wu.wl1 = si->seq; + tcb->snd.wu.wl2 = si->ack; + + get_syn_opts(&tcb->so, (uintptr_t)(th + 1), mb->l4_len - sizeof(*th)); + + tcb->snd.wscale = tcb->so.wscale; + tcb->snd.mss = tcb->so.mss; + tcb->snd.wnd = si->wnd << tcb->snd.wscale; + + tcb->snd.ts = tcb->so.ts.ecr; + tcb->rcv.ts = tcb->so.ts.val; + + tcb->rcv.wscale = (tcb->so.wscale == TCP_WSCALE_NONE) ? + TCP_WSCALE_NONE : TCP_WSCALE_DEFAULT; +} + +#ifdef __cplusplus +} +#endif + +#endif /* _STREAM_TABLE_H_ */ |