From 9fa82a63e47e4ee274c54af366e6fce055a0cbab Mon Sep 17 00:00:00 2001 From: Reshma Pattan Date: Fri, 7 Apr 2017 16:51:27 +0100 Subject: * Add siphash file for calculating the sequence number. * l4fwd app changed to include new command line parameters hash and secret key for hash calculation. * Changed l4fwd library to integrate siphash support for calculating the sequence number. Change-Id: I29c60836c8b17a118d76b619fd79398fac200f67 Signed-off-by: Reshma Pattan --- lib/libtle_l4p/ctx.c | 10 +++++ lib/libtle_l4p/halfsiphash.h | 100 +++++++++++++++++++++++++++++++++++++++++++ lib/libtle_l4p/syncookie.h | 76 ++++++++++++++++++++++---------- lib/libtle_l4p/tcp_rxtx.c | 21 ++++++--- lib/libtle_l4p/tle_ctx.h | 11 +++++ 5 files changed, 188 insertions(+), 30 deletions(-) create mode 100644 lib/libtle_l4p/halfsiphash.h (limited to 'lib') diff --git a/lib/libtle_l4p/ctx.c b/lib/libtle_l4p/ctx.c index 7ebef9d..6eb33eb 100644 --- a/lib/libtle_l4p/ctx.c +++ b/lib/libtle_l4p/ctx.c @@ -21,6 +21,7 @@ #include "stream.h" #include "misc.h" +#include #define LPORT_START 0x8000 #define LPORT_END MAX_PORT_NUM @@ -66,6 +67,8 @@ check_ctx_prm(const struct tle_ctx_param *prm) { if (prm->proto >= TLE_PROTO_NUM) return -EINVAL; + if (prm->hash_alg >= TLE_HASH_NUM) + return -EINVAL; return 0; } @@ -108,6 +111,13 @@ tle_ctx_create(const struct tle_ctx_param *ctx_prm) tle_pbm_init(ctx->use + i, LPORT_START_BLK); ctx->streams.nb_free = ctx->prm.max_streams; + + /* Initialization of siphash state is done here to speed up the + * fastpath processing. + */ + if (ctx->prm.hash_alg == TLE_SIPHASH) + siphash_initialization(&ctx->prm.secret_key, + &ctx->prm.secret_key); return ctx; } diff --git a/lib/libtle_l4p/halfsiphash.h b/lib/libtle_l4p/halfsiphash.h new file mode 100644 index 0000000..e8e21e4 --- /dev/null +++ b/lib/libtle_l4p/halfsiphash.h @@ -0,0 +1,100 @@ +/* + * SipHash reference C implementation + + * Copyright (c) 2016 Jean-Philippe Aumasson + + * To the extent possible under law, the author(s) have dedicated all copyright + * and related and neighboring rights to this software to the public domain + * worldwide. This software is distributed without any warranty. + + * You should have received a copy of the CC0 Public Domain Dedication along + * with this software. If not, see + * . + */ + +#ifndef _SIPHASH_ +#define _SIPHASH_ + +#ifdef __cplusplus +extern "C" { +#endif + +/* The below siphash logic is taken from the source + * https://github.com/veorq/SipHash + */ + +#include +#include +#include + +#include + +#define STATE_V2 0x6c796765 +#define STATE_V3 0x74656462 + +#define ROTL(x, b) (uint32_t)(((x) << (b)) | ((x) >> (32 - (b)))) + +/* + * Siphash hash functionality logically divided into different + * phases and the functions are named based on the same. + * SipHash-2-4 is used i.e: 2 compression rounds and 4 finalization rounds. + */ +static inline void +sipround(rte_xmm_t *v) +{ + v->u32[0] += v->u32[1]; + v->u32[1] = ROTL(v->u32[1], 5); + v->u32[1] ^= v->u32[0]; + v->u32[0] = ROTL(v->u32[0], 16); + v->u32[2] += v->u32[3]; + v->u32[3] = ROTL(v->u32[3], 8); + v->u32[3] ^= v->u32[2]; + v->u32[0] += v->u32[3]; + v->u32[3] = ROTL(v->u32[3], 7); + v->u32[3] ^= v->u32[0]; + v->u32[2] += v->u32[1]; + v->u32[1] = ROTL(v->u32[1], 13); + v->u32[1] ^= v->u32[2]; + v->u32[2] = ROTL(v->u32[2], 16); +} + +static inline void +siphash_initialization(rte_xmm_t *v, const rte_xmm_t *k) +{ + uint32_t k0 = k->u32[0]; + uint32_t k1 = k->u32[1]; + + v->u32[0] = k0; + v->u32[1] = k1; + v->u32[2] = STATE_V2 ^ k0; + v->u32[3] = STATE_V3 ^ k1; +} + +static inline void +siphash_compression(const uint32_t *in, size_t len, rte_xmm_t *v) +{ + uint32_t i; + + for (i = 0; i < len; i++) { + v->u32[3] ^= in[i]; + sipround(v); + sipround(v); + v->u32[0] ^= in[i]; + } +} + +static inline void +siphash_finalization(rte_xmm_t *v) +{ + v->u32[2] ^= 0xff; + sipround(v); + sipround(v); + sipround(v); + sipround(v); +} + +#ifdef __cplusplus +} +#endif + +#endif /* __SIPHASH__ */ diff --git a/lib/libtle_l4p/syncookie.h b/lib/libtle_l4p/syncookie.h index ad70b7d..da2e166 100644 --- a/lib/libtle_l4p/syncookie.h +++ b/lib/libtle_l4p/syncookie.h @@ -16,16 +16,16 @@ #ifndef _SYNCOOKIE_H_ #define _SYNCOOKIE_H_ -#include "tcp_misc.h" #include +#include "tcp_misc.h" +#include +#include + #ifdef __cplusplus extern "C" { #endif -#define SYNC_SEED0 0x736f6d65 -#define SYNC_SEED1 0x646f7261 - struct sync_in4 { uint32_t seq; union l4_ports port; @@ -64,35 +64,61 @@ static const rte_xmm_t mss6len = { /* 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) +sync_hash4(const union pkt_info *pi, uint32_t seq, rte_xmm_t *secret_key, + uint32_t hash_alg) { - uint32_t v0, v1; struct sync_in4 in4; + rte_xmm_t state; + uint32_t v0, v1; 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; + if (hash_alg == TLE_JHASH) { + v0 = secret_key->u32[0]; + v1 = secret_key->u32[1]; + rte_jhash_32b_2hashes(&in4.seq, sizeof(in4) / sizeof(uint32_t), + &v0, &v1); + return v0 + v1; + } else { + state = *secret_key; + siphash_compression(&in4.seq, sizeof(in4) / sizeof(uint32_t), + &state); + siphash_finalization(&state); + return (state.u32[0] ^ state.u32[1] ^ + state.u32[2] ^ state.u32[3]); + } } static inline uint32_t -sync_hash6(const union pkt_info *pi, uint32_t seq) +sync_hash6(const union pkt_info *pi, uint32_t seq, rte_xmm_t *secret_key, + uint32_t hash_alg) { + uint32_t port_seq[2]; + rte_xmm_t state; 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); + if (hash_alg == TLE_JHASH) { + v0 = secret_key->u32[0]; + v1 = secret_key->u32[1]; + 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); + } else { + state = *secret_key; + siphash_compression(pi->addr6->raw.u32, + sizeof(*pi->addr6) / sizeof(uint32_t), &state); + port_seq[0] = pi->port.raw; + port_seq[1] = seq; + siphash_compression(port_seq, RTE_DIM(port_seq), &state); + siphash_finalization(&state); + return (state.u32[0] ^ state.u32[1] ^ + state.u32[2] ^ state.u32[3]); + } } static inline uint32_t @@ -105,15 +131,16 @@ sync_mss2idx(uint16_t mss, const rte_xmm_t *msl) } static inline uint32_t -sync_gen_seq(const union pkt_info *pi, uint32_t seq, uint32_t ts, uint16_t mss) +sync_gen_seq(const union pkt_info *pi, uint32_t seq, uint32_t ts, uint16_t mss, + uint32_t hash_alg, rte_xmm_t *secret_key) { uint32_t h, mi; if (pi->tf.type == TLE_V4) { - h = sync_hash4(pi, seq); + h = sync_hash4(pi, seq, secret_key, hash_alg); mi = sync_mss2idx(mss, &mss4len); } else { - h = sync_hash6(pi, seq); + h = sync_hash6(pi, seq, secret_key, hash_alg); mi = sync_mss2idx(mss, &mss6len); } @@ -131,11 +158,14 @@ sync_gen_ts(uint32_t ts, uint32_t wscale) static inline int sync_check_ack(const union pkt_info *pi, uint32_t seq, uint32_t ack, - uint32_t ts) + uint32_t ts, uint32_t hash_alg, rte_xmm_t *secret_key) { uint32_t h, mi, pts; - h = (pi->tf.type == TLE_V4) ? sync_hash4(pi, seq) : sync_hash6(pi, seq); + if (pi->tf.type == TLE_V4) + h = sync_hash4(pi, seq, secret_key, hash_alg); + else + h = sync_hash6(pi, seq, secret_key, hash_alg); h = ack - h; pts = h & ~SYNC_MSS_MASK; diff --git a/lib/libtle_l4p/tcp_rxtx.c b/lib/libtle_l4p/tcp_rxtx.c index b525751..d4b6fdd 100644 --- a/lib/libtle_l4p/tcp_rxtx.c +++ b/lib/libtle_l4p/tcp_rxtx.c @@ -641,7 +641,9 @@ sync_ack(struct tle_tcp_stream *s, const union pkt_info *pi, get_syn_opts(&s->tcb.so, (uintptr_t)(th + 1), m->l4_len - sizeof(*th)); s->tcb.rcv.nxt = si->seq + 1; - seq = sync_gen_seq(pi, s->tcb.rcv.nxt, ts, s->tcb.so.mss); + seq = sync_gen_seq(pi, s->tcb.rcv.nxt, ts, s->tcb.so.mss, + s->s.ctx->prm.hash_alg, + &s->s.ctx->prm.secret_key); s->tcb.so.ts.ecr = s->tcb.so.ts.val; s->tcb.so.ts.val = sync_gen_ts(ts, s->tcb.so.wscale); s->tcb.so.wscale = (s->tcb.so.wscale == TCP_WSCALE_NONE) ? @@ -762,14 +764,17 @@ rx_check_seqack(struct tcb *tcb, uint32_t seq, uint32_t ack, uint32_t len, static inline int restore_syn_opt(struct syn_opts *so, const union pkt_info *pi, - const union seg_info *si, uint32_t ts, const struct rte_mbuf *mb) + const union seg_info *si, uint32_t ts, const struct rte_mbuf *mb, + uint32_t hash_alg, rte_xmm_t *secret_key) { int32_t rc; uint32_t len; const struct tcp_hdr *th; /* check that ACK, etc fields are what we expected. */ - rc = sync_check_ack(pi, si->seq, si->ack - 1, ts); + rc = sync_check_ack(pi, si->seq, si->ack - 1, ts, + hash_alg, + secret_key); if (rc < 0) return rc; @@ -918,12 +923,12 @@ rx_ack_listen(struct tle_tcp_stream *s, struct stbl *st, if (pi->tf.flags != TCP_FLAG_ACK || rx_check_stream(s, pi) != 0) return -EINVAL; - rc = restore_syn_opt(&so, pi, si, tms, mb); + ctx = s->s.ctx; + rc = restore_syn_opt(&so, pi, si, tms, mb, ctx->prm.hash_alg, + &ctx->prm.secret_key); if (rc < 0) return rc; - ctx = s->s.ctx; - /* allocate new stream */ ts = get_stream(ctx); cs = TCP_STREAM(ts); @@ -2059,7 +2064,9 @@ tx_syn(struct tle_tcp_stream *s, const struct sockaddr *addr) s->tcb.so.mss = calc_smss(s->tx.dst.mtu, &s->tx.dst); /* note that rcv.nxt is 0 here for sync_gen_seq.*/ - seq = sync_gen_seq(&pi, s->tcb.rcv.nxt, tms, s->tcb.so.mss); + seq = sync_gen_seq(&pi, s->tcb.rcv.nxt, tms, s->tcb.so.mss, + s->s.ctx->prm.hash_alg, + &s->s.ctx->prm.secret_key); s->tcb.snd.iss = seq; s->tcb.snd.rcvr = seq; s->tcb.snd.una = seq; diff --git a/lib/libtle_l4p/tle_ctx.h b/lib/libtle_l4p/tle_ctx.h index a3516bf..144dbe7 100644 --- a/lib/libtle_l4p/tle_ctx.h +++ b/lib/libtle_l4p/tle_ctx.h @@ -97,6 +97,12 @@ enum { TLE_PROTO_NUM }; +enum { + TLE_JHASH, + TLE_SIPHASH, + TLE_HASH_NUM +}; + struct tle_ctx_param { int32_t socket_id; /**< socket ID to allocate memory for. */ uint32_t proto; /**< L4 proto to handle. */ @@ -116,6 +122,11 @@ struct tle_ctx_param { /**< will be called by send() to get IPv6 packet destination info. */ void *lookup6_data; /**< opaque data pointer for lookup6() callback. */ + + uint32_t hash_alg; + /**< hash algorithm to be used to generate sequence number. */ + rte_xmm_t secret_key; + /**< secret key to be used to calculate the hash. */ }; /** -- cgit 1.2.3-korg