}
_public_
-int knot_xdp_tcp_relay(knot_xdp_socket_t *socket, knot_xdp_msg_t msgs[], uint32_t msg_count,
- knot_tcp_table_t *tcp_table, knot_tcp_table_t *syn_table,
- knot_tcp_relay_dynarray_t *relays)
+int knot_tcp_relay(knot_xdp_socket_t *socket, knot_xdp_msg_t msgs[], uint32_t msg_count,
+ knot_tcp_table_t *tcp_table, knot_tcp_table_t *syn_table,
+ knot_tcp_relay_dynarray_t *relays)
{
if (msg_count == 0) {
return KNOT_EOK;
}
_public_
-int knot_xdp_tcp_send_data(knot_tcp_relay_dynarray_t *relays, const knot_tcp_relay_t *relay,
- void *data, size_t data_len)
+int knot_tcp_send_data(knot_tcp_relay_dynarray_t *relays, const knot_tcp_relay_t *relay,
+ void *data, size_t data_len)
{
if (relays == NULL || relay == NULL || data == NULL) {
return KNOT_EINVAL;
}
_public_
-void knot_xdp_tcp_relay_free(knot_tcp_relay_dynarray_t *relays)
+void knot_tcp_relay_free(knot_tcp_relay_dynarray_t *relays)
{
if (relays == NULL) {
return;
}
_public_
-int knot_xdp_tcp_send(knot_xdp_socket_t *socket, knot_tcp_relay_t relays[],
- uint32_t relay_count)
+int knot_tcp_send(knot_xdp_socket_t *socket, knot_tcp_relay_t relays[], uint32_t relay_count)
{
if (relay_count == 0) {
return KNOT_EOK;
}
_public_
-int knot_xdp_tcp_timeout(knot_tcp_table_t *tcp_table, knot_xdp_socket_t *socket,
- uint32_t max_at_once,
- uint32_t close_timeout, uint32_t reset_timeout,
- uint32_t reset_at_least, size_t reset_inbufs,
- uint32_t *close_count, uint32_t *reset_count)
+int knot_tcp_sweep(knot_tcp_table_t *tcp_table, knot_xdp_socket_t *socket,
+ uint32_t max_at_once, uint32_t close_timeout, uint32_t reset_timeout,
+ uint32_t reset_at_least, size_t reset_buf_size,
+ uint32_t *close_count, uint32_t *reset_count)
{
if (tcp_table == NULL) {
return KNOT_EINVAL;
WALK_LIST_DELSAFE(conn, next, *tcp_table_timeout(tcp_table)) {
if (i++ < reset_at_least ||
now - conn->last_active >= reset_timeout ||
- (reset_inbufs > 0 && conn->inbuf.iov_len > 0)) {
+ (reset_buf_size > 0 && conn->inbuf.iov_len > 0)) {
rl.answer = XDP_TCP_RESET;
// move this conn into to-remove list
rem_node((node_t *)conn);
add_tail(&to_remove, (node_t *)conn);
- reset_inbufs -= MIN(reset_inbufs, conn->inbuf.iov_len);
+ reset_buf_size -= MIN(reset_buf_size, conn->inbuf.iov_len);
} else if (now - conn->last_active >= close_timeout) {
if (conn->state != XDP_TCP_CLOSING) {
rl.answer = XDP_TCP_CLOSE;
(*close_count)++;
}
}
- } else if (reset_inbufs == 0) {
+ } else if (reset_buf_size == 0) {
break;
}
}
if (ret == KNOT_EOK) {
- ret = knot_xdp_tcp_send(socket, knot_tcp_relay_dynarray_arr(&relays), relays.size);
+ ret = knot_tcp_send(socket, knot_tcp_relay_dynarray_arr(&relays), relays.size);
}
// immediately remove resetted connections
}
}
- knot_xdp_tcp_relay_free(&relays);
+ knot_tcp_relay_free(&relays);
return ret;
}
XDP_TCP_FREE_PREFIX,
} knot_tcp_relay_free_t;
-typedef struct knot_xdp_tcp_conn {
+typedef struct knot_tcp_conn {
struct {
void *list_node_placeholder1;
void *list_node_placeholder2;
uint32_t last_active;
knot_tcp_state_t state;
struct iovec inbuf;
- struct knot_xdp_tcp_conn *next;
+ struct knot_tcp_conn *next;
} knot_tcp_conn_t;
typedef struct {
*
* \return KNOT_E*
*/
-int knot_xdp_tcp_relay(knot_xdp_socket_t *socket, knot_xdp_msg_t msgs[], uint32_t msg_count,
- knot_tcp_table_t *tcp_table, knot_tcp_table_t *syn_table,
- knot_tcp_relay_dynarray_t *relays);
+int knot_tcp_relay(knot_xdp_socket_t *socket, knot_xdp_msg_t msgs[], uint32_t msg_count,
+ knot_tcp_table_t *tcp_table, knot_tcp_table_t *syn_table,
+ knot_tcp_relay_dynarray_t *relays);
/*!
* \brief Answer one relay with one or more relays with data payload.
*
* \return KNOT_EOK, KNOT_ENOMEM
*/
-int knot_xdp_tcp_send_data(knot_tcp_relay_dynarray_t *relays, const knot_tcp_relay_t *relay,
- void *data, size_t data_len);
+int knot_tcp_send_data(knot_tcp_relay_dynarray_t *relays, const knot_tcp_relay_t *relay,
+ void *data, size_t data_len);
/*!
* \brief Free resources in 'relays'.
*/
-void knot_xdp_tcp_relay_free(knot_tcp_relay_dynarray_t *relays);
+void knot_tcp_relay_free(knot_tcp_relay_dynarray_t *relays);
/*!
* \brief Send TCP packets.
*
* \return KNOT_E*
*/
-int knot_xdp_tcp_send(knot_xdp_socket_t *socket, knot_tcp_relay_t relays[],
- uint32_t relay_count);
+int knot_tcp_send(knot_xdp_socket_t *socket, knot_tcp_relay_t relays[], uint32_t relay_count);
/*!
* \brief Cleanup old TCP connections, perform timeout checks.
* \param reset_timeout Reset connections older than this (usecs).
* \param reset_at_least Reset at least this number of oldest conecctions, even
* when not yet timeouted.
- * \param reset_inbufs Reset oldest connection with buffered partial DNS messages
+ * \param reset_buf_size Reset oldest connection with buffered partial DNS messages
* to free up this amount of space.
* \param close_count Optional: Out: number of closed connections.
* \param reset_count Optional: Out: number of reset connections.
*
* \return KNOT_E*
*/
-int knot_xdp_tcp_timeout(knot_tcp_table_t *tcp_table, knot_xdp_socket_t *socket,
- uint32_t max_at_once,
- uint32_t close_timeout, uint32_t reset_timeout,
- uint32_t reset_at_least, size_t reset_inbufs,
- uint32_t *close_count, uint32_t *reset_count);
+int knot_tcp_sweep(knot_tcp_table_t *tcp_table, knot_xdp_socket_t *socket,
+ uint32_t max_at_once, uint32_t close_timeout, uint32_t reset_timeout,
+ uint32_t reset_at_least, size_t reset_buf_size,
+ uint32_t *close_count, uint32_t *reset_count);
/*! @} */
knot_xdp_msg_t msg;
knot_tcp_relay_dynarray_t relays = { 0 };
prepare_msg(&msg, KNOT_XDP_MSG_SYN, 1, 2);
- int ret = knot_xdp_tcp_relay(test_sock, &msg, 1, test_table, NULL, &relays);
+ int ret = knot_tcp_relay(test_sock, &msg, 1, test_table, NULL, &relays);
is_int(KNOT_EOK, ret, "SYN: relay OK");
is_int(msg.seqno + 1, sent_ackno, "SYN: ackno");
check_sent(0, 0, 1, 0);
ok(memcmp(&conn->ip_rem, &msg.ip_from, sizeof(msg.ip_from)) == 0, "SYN: conn IP from");
ok(memcmp(&conn->ip_loc, &msg.ip_to, sizeof(msg.ip_to)) == 0, "SYN: conn IP to");
- knot_xdp_tcp_relay_free(&relays);
+ knot_tcp_relay_free(&relays);
test_conn = conn;
}
knot_tcp_relay_dynarray_t relays = { 0 };
prepare_msg(&msg, KNOT_XDP_MSG_ACK, 1, 2);
prepare_seqack(&msg, 0, 1);
- int ret = knot_xdp_tcp_relay(test_sock, &msg, 1, test_table, NULL, &relays);
+ int ret = knot_tcp_relay(test_sock, &msg, 1, test_table, NULL, &relays);
is_int(KNOT_EOK, ret, "establish: relay OK");
check_sent(0, 0, 0, 0);
is_int(0, relays.size, "establish: no relay");
ok(rl->conn == test_conn, "establish: same connection");
is_int(XDP_TCP_NORMAL, rl->conn->state, "establish: connection state");*/
- knot_xdp_tcp_relay_free(&relays);
+ knot_tcp_relay_free(&relays);
clean_table();
}
knot_xdp_msg_t msg;
knot_tcp_relay_dynarray_t relays = { 0 };
prepare_msg(&msg, KNOT_XDP_MSG_SYN | KNOT_XDP_MSG_ACK, 1000, 2000);
- int ret = knot_xdp_tcp_relay(test_sock, &msg, 1, test_table, NULL, &relays);
+ int ret = knot_tcp_relay(test_sock, &msg, 1, test_table, NULL, &relays);
is_int(KNOT_EOK, ret, "SYN+ACK: relay OK");
is_int(msg.seqno + 1, sent_ackno, "SYN+ACK: ackno");
check_sent(1, 0, 0, 0);
ok(rl->conn != NULL, "SYN+ACK: connection present");
test_conn = rl->conn;
- knot_xdp_tcp_relay_free(&relays);
+ knot_tcp_relay_free(&relays);
}
void test_data_fragments(void)
prepare_seqack(&msgs[3], 15, 0);
prepare_data(&msgs[3], "\x02""AB""\xff\xff""abcdefghijklmnopqrstuvwxyz...", 34);
- int ret = knot_xdp_tcp_relay(test_sock, msgs, sizeof(msgs) / sizeof(msgs[0]), test_table, NULL, &relays);
+ int ret = knot_tcp_relay(test_sock, msgs, sizeof(msgs) / sizeof(msgs[0]), test_table, NULL, &relays);
is_int(KNOT_EOK, ret, "fragments: relay OK");
is_int(msgs[3].ackno, sent_seqno, "fragments: seqno");
is_int(msgs[3].seqno + msgs[3].payload.iov_len, sent_ackno, "fragments: ackno");
ok(memcmp("AB", rls[3].data.iov_base, rls[3].data.iov_len) == 0, "fragments3: data");
ok(rls[3].conn == test_conn, "fragments3: same connection");
- knot_xdp_tcp_relay_free(&relays);
+ knot_tcp_relay_free(&relays);
}
void test_close(void)
knot_tcp_relay_dynarray_t relays = { 0 };
prepare_msg(&msg, KNOT_XDP_MSG_FIN | KNOT_XDP_MSG_ACK, be16toh(test_conn->ip_rem.sin6_port), be16toh(test_conn->ip_loc.sin6_port));
prepare_seqack(&msg, 0, 0);
- int ret = knot_xdp_tcp_relay(test_sock, &msg, 1, test_table, NULL, &relays);
+ int ret = knot_tcp_relay(test_sock, &msg, 1, test_table, NULL, &relays);
is_int(KNOT_EOK, ret, "close: relay 1 OK");
check_sent(0, 0, 0, 1);
is_int(1, relays.size, "close: one relay");
is_int(XDP_TCP_CLOSE, rl->action, "close: relay action");
ok(rl->conn == test_conn, "close: same connection");
is_int(XDP_TCP_CLOSING, rl->conn->state, "close: conn state");
- knot_xdp_tcp_relay_free(&relays);
+ knot_tcp_relay_free(&relays);
msg.flags &= ~KNOT_XDP_MSG_FIN;
prepare_seqack(&msg, 0, 0);
- ret = knot_xdp_tcp_relay(test_sock, &msg, 1, test_table, NULL, &relays);
+ ret = knot_tcp_relay(test_sock, &msg, 1, test_table, NULL, &relays);
is_int(KNOT_EOK, ret, "close: relay 2 OK");
check_sent(0, 0, 0, 0);
is_int(conns_pre - 1, test_table->usage, "close: connection removed");
}
knot_tcp_relay_dynarray_t relays = { 0 };
- int ret = knot_xdp_tcp_relay(test_sock, msgs, CONNS, test_table, NULL, &relays);
+ int ret = knot_tcp_relay(test_sock, msgs, CONNS, test_table, NULL, &relays);
is_int(KNOT_EOK, ret, "many: relay OK");
check_sent(0, 0, CONNS, 0);
is_int(CONNS, relays.size, "many: relays count");
is_int(CONNS, test_table->usage, "many: table usage");
- knot_xdp_tcp_relay_free(&relays);
+ knot_tcp_relay_free(&relays);
usleep(timeout_time);
knot_xdp_msg_t *survive = &msgs[i_survive];
survive->flags = (KNOT_XDP_MSG_TCP | KNOT_XDP_MSG_ACK);
knot_tcp_conn_t *surv_conn = tcp_table_find(test_table, survive);
fix_seqack(survive);
prepare_data(survive, "\x00\x00", 2);
- (void)knot_xdp_tcp_relay(test_sock, survive, 1, test_table, NULL, &relays);
+ (void)knot_tcp_relay(test_sock, survive, 1, test_table, NULL, &relays);
is_int(1, relays.size, "many/survivor: one relay");
knot_tcp_relay_t *rl = &knot_tcp_relay_dynarray_arr(&relays)[0];
clean_sent();
uint32_t reset_count = 0, close_count = 0;
- ret = knot_xdp_tcp_timeout(test_table, test_sock, UINT32_MAX, timeout_time, UINT32_MAX, 0, 0, &close_count, &reset_count);
+ ret = knot_tcp_sweep(test_table, test_sock, UINT32_MAX, timeout_time, UINT32_MAX, 0, 0, &close_count, &reset_count);
is_int(KNOT_EOK, ret, "many/timeout1: OK");
is_int(CONNS - 1, close_count, "many/timeout1: close count");
is_int(0, reset_count, "may/timeout1: reset count");
check_sent(0, 0, 0, CONNS - 1);
close_count = 0;
- ret = knot_xdp_tcp_timeout(test_table, test_sock, UINT32_MAX, UINT32_MAX, timeout_time, 0, 0, &close_count, &reset_count);
+ ret = knot_tcp_sweep(test_table, test_sock, UINT32_MAX, UINT32_MAX, timeout_time, 0, 0, &close_count, &reset_count);
is_int(KNOT_EOK, ret, "many/timeout2: OK");
is_int(0, close_count, "many/timeout2: close count");
is_int(CONNS - 1, reset_count, "may/timeout2: reset count");
for (int i = 0; i < CONNS; i++) {
prepare_msg(&msgs[i], KNOT_XDP_MSG_SYN, i + 2000, 1);
}
- int ret = knot_xdp_tcp_relay(test_sock, msgs, CONNS, test_table, NULL, &relays);
+ int ret = knot_tcp_relay(test_sock, msgs, CONNS, test_table, NULL, &relays);
is_int(KNOT_EOK, ret, "ibufs: open OK");
check_sent(0, 0, CONNS, 0);
for (int i = 0; i < CONNS; i++) {
// first connection will start a fragment buf then finish it
fix_seqack(&msgs[0]);
prepare_data(&msgs[0], "\x00\x0a""lorem", 7);
- ret = knot_xdp_tcp_relay(test_sock, &msgs[0], 1, test_table, NULL, &relays);
+ ret = knot_tcp_relay(test_sock, &msgs[0], 1, test_table, NULL, &relays);
is_int(KNOT_EOK, ret, "ibufs: must be OK");
check_sent(1, 0, 0, 0);
is_int(7, test_table->inbufs_total, "inbufs: first inbuf");
- knot_xdp_tcp_relay_free(&relays);
+ knot_tcp_relay_free(&relays);
// other connection will just store fragments
fix_seqacks(msgs, CONNS);
prepare_data(&msgs[1], "\x00\xff""12345", 7);
prepare_data(&msgs[2], "\xff\xff""abcde", 7);
prepare_data(&msgs[3], "\xff\xff""abcde", 7);
- ret = knot_xdp_tcp_relay(test_sock, msgs, CONNS, test_table, NULL, &relays);
+ ret = knot_tcp_relay(test_sock, msgs, CONNS, test_table, NULL, &relays);
is_int(KNOT_EOK, ret, "inbufs: relay OK");
check_sent(CONNS, 0, 0, 0);
is_int(21, test_table->inbufs_total, "inbufs: after change");
is_int(1, relays.size, "inbufs: one relay");
is_int(10, knot_tcp_relay_dynarray_arr(&relays)[0].data.iov_len, "inbufs: data length");
- knot_xdp_tcp_relay_free(&relays);
+ knot_tcp_relay_free(&relays);
// now free some
uint32_t reset_count = 0, close_count = 0;
- ret = knot_xdp_tcp_timeout(test_table, test_sock, UINT32_MAX, UINT32_MAX, UINT32_MAX, 0, 8, &close_count, &reset_count);
+ ret = knot_tcp_sweep(test_table, test_sock, UINT32_MAX, UINT32_MAX, UINT32_MAX, 0, 8, &close_count, &reset_count);
is_int(KNOT_EOK, ret, "inbufs: timeout OK");
check_sent(0, 2, 0, 0);
is_int(0, close_count, "inbufs: close count");