aboutgitcodebugslistschat
diff options
context:
space:
mode:
-rw-r--r--flow.c30
-rw-r--r--flow.h2
-rw-r--r--tcp.c33
3 files changed, 36 insertions, 29 deletions
diff --git a/flow.c b/flow.c
index b291f25..8eea861 100644
--- a/flow.c
+++ b/flow.c
@@ -455,16 +455,16 @@ static uint64_t flow_sidx_hash(const struct ctx *c, flow_sidx_t sidx)
}
/**
- * flow_hash_probe() - Find hash bucket for a flow
- * @c: Execution context
+ * flow_hash_probe_() - Find hash bucket for a flow, given hash
+ * @hash: Raw hash value for flow & side
* @sidx: Flow and side to find bucket for
*
* Return: If @sidx is in the hash table, its current bucket, otherwise a
* suitable free bucket for it.
*/
-static inline unsigned flow_hash_probe(const struct ctx *c, flow_sidx_t sidx)
+static inline unsigned flow_hash_probe_(uint64_t hash, flow_sidx_t sidx)
{
- unsigned b = flow_sidx_hash(c, sidx) % FLOW_HASH_SIZE;
+ unsigned b = hash % FLOW_HASH_SIZE;
/* Linear probing */
while (flow_sidx_valid(flow_hashtab[b]) &&
@@ -475,17 +475,35 @@ static inline unsigned flow_hash_probe(const struct ctx *c, flow_sidx_t sidx)
}
/**
+ * flow_hash_probe() - Find hash bucket for a flow
+ * @c: Execution context
+ * @sidx: Flow and side to find bucket for
+ *
+ * Return: If @sidx is in the hash table, its current bucket, otherwise a
+ * suitable free bucket for it.
+ */
+static inline unsigned flow_hash_probe(const struct ctx *c, flow_sidx_t sidx)
+{
+ return flow_hash_probe_(flow_sidx_hash(c, sidx), sidx);
+}
+
+/**
* flow_hash_insert() - Insert side of a flow into into hash table
* @c: Execution context
* @sidx: Flow & side index
+ *
+ * Return: raw (un-modded) hash value of side of flow
*/
-void flow_hash_insert(const struct ctx *c, flow_sidx_t sidx)
+uint64_t flow_hash_insert(const struct ctx *c, flow_sidx_t sidx)
{
- unsigned b = flow_hash_probe(c, sidx);
+ uint64_t hash = flow_sidx_hash(c, sidx);
+ unsigned b = flow_hash_probe_(hash, sidx);
flow_hashtab[b] = sidx;
flow_dbg(flow_at_sidx(sidx), "Side %u hash table insert: bucket: %u",
sidx.sidei, b);
+
+ return hash;
}
/**
diff --git a/flow.h b/flow.h
index fcb4121..e3a778a 100644
--- a/flow.h
+++ b/flow.h
@@ -229,7 +229,7 @@ static inline bool flow_sidx_eq(flow_sidx_t a, flow_sidx_t b)
return (a.flowi == b.flowi) && (a.sidei == b.sidei);
}
-void flow_hash_insert(const struct ctx *c, flow_sidx_t sidx);
+uint64_t flow_hash_insert(const struct ctx *c, flow_sidx_t sidx);
void flow_hash_remove(const struct ctx *c, flow_sidx_t sidx);
flow_sidx_t flow_lookup_af(const struct ctx *c,
uint8_t proto, uint8_t pif, sa_family_t af,
diff --git a/tcp.c b/tcp.c
index 0964855..b6eca5d 100644
--- a/tcp.c
+++ b/tcp.c
@@ -1294,28 +1294,16 @@ static void tcp_tap_window_update(struct tcp_tap_conn *conn, unsigned wnd)
}
/**
- * tcp_seq_init() - Calculate initial sequence number according to RFC 6528
- * @c: Execution context
- * @conn: TCP connection, with faddr, fport and eport populated
+ * tcp_init_seq() - Calculate initial sequence number according to RFC 6528
+ * @hash: Hash of connection details
* @now: Current timestamp
*/
-static void tcp_seq_init(const struct ctx *c, struct tcp_tap_conn *conn,
- const struct timespec *now)
+static uint32_t tcp_init_seq(uint64_t hash, const struct timespec *now)
{
- struct siphash_state state = SIPHASH_INIT(c->hash_secret);
- const struct flowside *tapside = TAPFLOW(conn);
- uint64_t hash;
- uint32_t ns;
-
- inany_siphash_feed(&state, &tapside->faddr);
- inany_siphash_feed(&state, &tapside->eaddr);
- hash = siphash_final(&state, 36,
- (uint64_t)tapside->fport << 16 | tapside->eport);
-
/* 32ns ticks, overflows 32 bits every 137s */
- ns = (now->tv_sec * 1000000000 + now->tv_nsec) >> 5;
+ uint32_t ns = (now->tv_sec * 1000000000 + now->tv_nsec) >> 5;
- conn->seq_to_tap = ((uint32_t)(hash >> 32) ^ (uint32_t)hash) + ns;
+ return ((uint32_t)(hash >> 32) ^ (uint32_t)hash) + ns;
}
/**
@@ -1488,6 +1476,7 @@ static void tcp_conn_from_tap(struct ctx *c, sa_family_t af,
union sockaddr_inany sa;
union flow *flow;
int s = -1, mss;
+ uint64_t hash;
socklen_t sl;
if (!(flow = flow_alloc()))
@@ -1584,11 +1573,10 @@ static void tcp_conn_from_tap(struct ctx *c, sa_family_t af,
conn->seq_from_tap = conn->seq_init_from_tap + 1;
conn->seq_ack_to_tap = conn->seq_from_tap;
- tcp_seq_init(c, conn, now);
+ hash = flow_hash_insert(c, TAP_SIDX(conn));
+ conn->seq_to_tap = tcp_init_seq(hash, now);
conn->seq_ack_from_tap = conn->seq_to_tap;
- flow_hash_insert(c, TAP_SIDX(conn));
-
tcp_bind_outbound(c, conn, s);
if (connect(s, &sa.sa, sl)) {
@@ -2110,6 +2098,7 @@ static void tcp_tap_conn_from_sock(struct ctx *c, in_port_t dstport,
union inany_addr saddr, daddr; /* FIXME: avoid bulky temporaries */
struct tcp_tap_conn *conn;
in_port_t srcport;
+ uint64_t hash;
inany_from_sockaddr(&saddr, &srcport, sa);
tcp_snat_inbound(c, &saddr);
@@ -2133,8 +2122,8 @@ static void tcp_tap_conn_from_sock(struct ctx *c, in_port_t dstport,
conn->ws_to_tap = conn->ws_from_tap = 0;
conn_event(c, conn, SOCK_ACCEPTED);
- tcp_seq_init(c, conn, now);
- flow_hash_insert(c, TAP_SIDX(conn));
+ hash = flow_hash_insert(c, TAP_SIDX(conn));
+ conn->seq_to_tap = tcp_init_seq(hash, now);
conn->seq_ack_from_tap = conn->seq_to_tap;