Skip to content
Snippets Groups Projects
Commit 6e2621e6 authored by Daniel Salzman's avatar Daniel Salzman
Browse files

xdp-tcp: replace tcp_outbufs_t with struct knot_tcp_outbuf

parent fef9811b
No related branches found
No related tags found
1 merge request!1394xdp-tcp: evolution and bugfixes
......@@ -91,7 +91,7 @@ static void next_ptr_obuf(knot_tcp_conn_t **ptr)
{
do {
next_node_ptr(ptr);
} while (*ptr != NULL && tcp_outbufs_usage(&(*ptr)->outbufs) == 0);
} while (*ptr != NULL && tcp_outbufs_usage((*ptr)->outbufs) == 0);
}
_public_
......@@ -163,7 +163,7 @@ static void del_conn(knot_tcp_conn_t *conn)
{
if (conn != NULL) {
free(conn->inbuf.iov_base);
free(conn->outbufs.bufs);
free(conn->outbufs);
free(conn);
}
}
......@@ -190,7 +190,7 @@ static void tcp_table_remove(knot_tcp_conn_t **todel, knot_tcp_table_t *table)
next_ptr_obuf(&table->next_resend);
}
table->inbufs_total -= (*todel)->inbuf.iov_len;
table->outbufs_total -= tcp_outbufs_usage(&(*todel)->outbufs);
table->outbufs_total -= tcp_outbufs_usage((*todel)->outbufs);
tcp_table_remove_conn(todel);
table->usage--;
}
......@@ -447,10 +447,10 @@ int knot_tcp_reply_data(knot_tcp_relay_t *relay, knot_tcp_table_t *tcp_table,
int ret = tcp_outbufs_add(&relay->conn->outbufs, data, len, ignore_lastbyte,
relay->conn->mss, &tcp_table->outbufs_total);
if (tcp_table->next_obuf == NULL && tcp_outbufs_usage(&relay->conn->outbufs) > 0) {
if (tcp_table->next_obuf == NULL && tcp_outbufs_usage(relay->conn->outbufs) > 0) {
tcp_table->next_obuf = relay->conn;
}
if (tcp_table->next_resend == NULL && tcp_outbufs_usage(&relay->conn->outbufs) > 0) {
if (tcp_table->next_resend == NULL && tcp_outbufs_usage(relay->conn->outbufs) > 0) {
tcp_table->next_resend = relay->conn;
}
return ret;
......@@ -576,9 +576,9 @@ int knot_tcp_send(knot_xdp_socket_t *socket, knot_tcp_relay_t relays[], uint32_t
}
size_t can_data = 0;
struct tcp_outbuf *ob;
knot_tcp_outbuf_t *ob;
if (rl->conn != NULL) {
tcp_outbufs_can_send(&rl->conn->outbufs, rl->conn->window_size,
tcp_outbufs_can_send(rl->conn->outbufs, rl->conn->window_size,
rl->answer == XDP_TCP_RESEND, &ob, &can_data);
}
while (can_data > 0) {
......@@ -619,7 +619,7 @@ void sweep_reset(knot_tcp_table_t *tcp_table, knot_tcp_relay_t *rl,
*free_conns -= 1;
*free_inbuf -= rl->conn->inbuf.iov_len;
*free_outbuf -= tcp_outbufs_usage(&rl->conn->outbufs);
*free_outbuf -= tcp_outbufs_usage(rl->conn->outbufs);
if (reset_count != NULL) {
(*reset_count)++;
......@@ -659,7 +659,7 @@ int knot_tcp_sweep(knot_tcp_table_t *tcp_table,
// reset connections to free obufs
while (free_outbuf > 0 && rl != rl_max) {
if (tcp_outbufs_usage(&tcp_table->next_obuf->outbufs) == 0) {
if (tcp_outbufs_usage(tcp_table->next_obuf->outbufs) == 0) {
next_ptr_obuf(&tcp_table->next_obuf);
}
assert(tcp_table->next_obuf != NULL);
......
......@@ -59,10 +59,6 @@ typedef enum {
XDP_TCP_IGNORE_FIN = (1 << 2),
} knot_tcp_ignore_t;
typedef struct tcp_outbufs {
struct tcp_outbuf *bufs;
} tcp_outbufs_t; // this typedef belongs to tcp_iobuf.h, but is here to avoid issues with symbols
typedef struct knot_tcp_conn {
struct {
struct knot_tcp_conn *list_node_next;
......@@ -82,7 +78,7 @@ typedef struct knot_tcp_conn {
uint32_t establish_rtt;
knot_tcp_state_t state;
struct iovec inbuf;
tcp_outbufs_t outbufs;
struct knot_tcp_outbuf *outbufs;
struct knot_tcp_conn *next;
} knot_tcp_conn_t;
......
......@@ -21,7 +21,6 @@
#include <string.h>
#include "libknot/xdp/tcp_iobuf.h"
#include "libknot/xdp/tcp.h" // just tcp_outbufs_t
#include "libknot/error.h"
#include "contrib/macros.h"
......@@ -176,20 +175,20 @@ int tcp_inbuf_update(struct iovec *buffer, struct iovec data,
return KNOT_EOK;
}
int tcp_outbufs_add(struct tcp_outbufs *ob, uint8_t *data, size_t len,
int tcp_outbufs_add(knot_tcp_outbuf_t **bufs, uint8_t *data, size_t len,
bool ignore_lastbyte, uint32_t mss, size_t *outbufs_total)
{
if (len > UINT16_MAX) {
return KNOT_ELIMIT;
}
struct tcp_outbuf **end = &ob->bufs;
knot_tcp_outbuf_t **end = bufs;
while (*end != NULL) { // NOTE: this can be optimized by adding "end" pointer for the price of larger knot_tcp_conn_t struct
end = &(*end)->next;
}
uint16_t prefix = htobe16(len), prefix_len = sizeof(prefix);
while (len > 0) {
uint16_t newlen = MIN(len + prefix_len, mss);
struct tcp_outbuf *newob = calloc(1, sizeof(*newob) + newlen);
knot_tcp_outbuf_t *newob = calloc(1, sizeof(*newob) + newlen);
if (newob == NULL) {
return KNOT_ENOMEM;
}
......@@ -221,28 +220,28 @@ static bool seqno_lower(uint32_t seqno, uint32_t ackno, uint32_t ackno_min)
}
}
void tcp_outbufs_ack(struct tcp_outbufs *ob, uint32_t ackno, size_t *outbufs_total)
void tcp_outbufs_ack(knot_tcp_outbuf_t **bufs, uint32_t ackno, size_t *outbufs_total)
{
uint32_t ackno_min = ackno - (UINT32_MAX / 2); // FIXME better?
while (ob->bufs != NULL && ob->bufs->sent && seqno_lower(ob->bufs->seqno + ob->bufs->len, ackno, ackno_min)) {
struct tcp_outbuf *tofree = ob->bufs;
ob->bufs = tofree->next;
while (*bufs != NULL && (*bufs)->sent && seqno_lower((*bufs)->seqno + (*bufs)->len, ackno, ackno_min)) {
knot_tcp_outbuf_t *tofree = *bufs;
*bufs = tofree->next;
*outbufs_total -= tofree->len + sizeof(*tofree);
free(tofree);
}
}
void tcp_outbufs_can_send(struct tcp_outbufs *ob, ssize_t window_size, bool resend,
struct tcp_outbuf **send_start, size_t *send_count)
void tcp_outbufs_can_send(knot_tcp_outbuf_t *bufs, ssize_t window_size, bool resend,
knot_tcp_outbuf_t **send_start, size_t *send_count)
{
*send_count = 0;
*send_start = ob->bufs;
*send_start = bufs;
while (*send_start != NULL && (*send_start)->sent && !resend) {
window_size -= (*send_start)->len;
*send_start = (*send_start)->next;
}
struct tcp_outbuf *can_send = *send_start;
knot_tcp_outbuf_t *can_send = *send_start;
while (can_send != NULL && window_size >= can_send->len) {
(*send_count)++;
window_size -= can_send->len;
......@@ -250,10 +249,10 @@ void tcp_outbufs_can_send(struct tcp_outbufs *ob, ssize_t window_size, bool rese
}
}
size_t tcp_outbufs_usage(struct tcp_outbufs *ob)
size_t tcp_outbufs_usage(knot_tcp_outbuf_t *bufs)
{
size_t res = 0;
for (struct tcp_outbuf *i = ob->bufs; i != NULL; i = i->next) {
for (knot_tcp_outbuf_t *i = bufs; i != NULL; i = i->next) {
res += i->len + sizeof(*i);
}
return res;
......
......@@ -31,15 +31,13 @@
#include "libknot/endian.h"
struct tcp_outbuf {
struct tcp_outbuf *next;
typedef struct knot_tcp_outbuf {
struct knot_tcp_outbuf *next;
uint32_t len;
uint32_t seqno;
bool sent;
uint8_t bytes[];
};
struct tcp_outbufs; // see tcp.h
} knot_tcp_outbuf_t;
/*!
* \brief Handle DNS-over-TCP payloads in buffer and message.
......@@ -68,7 +66,7 @@ int tcp_inbuf_update(struct iovec *buffer, struct iovec data,
*
* \return KNOT_E*
*/
int tcp_outbufs_add(struct tcp_outbufs *ob, uint8_t *data, size_t len,
int tcp_outbufs_add(knot_tcp_outbuf_t **bufs, uint8_t *data, size_t len,
bool ignore_lastbyte, uint32_t mss, size_t *outbufs_total);
/*!
......@@ -78,7 +76,7 @@ int tcp_outbufs_add(struct tcp_outbufs *ob, uint8_t *data, size_t len,
* \param ackno Ackno of received ACK.
* \param outbufs_total In/out: total outbuf statistic to be updated.
*/
void tcp_outbufs_ack(struct tcp_outbufs *ob, uint32_t ackno, size_t *outbufs_total);
void tcp_outbufs_ack(knot_tcp_outbuf_t **bufs, uint32_t ackno, size_t *outbufs_total);
/*!
* \brief Prepare output buffers to be sent now.
......@@ -89,12 +87,12 @@ void tcp_outbufs_ack(struct tcp_outbufs *ob, uint32_t ackno, size_t *outbufs_tot
* \param send_start Out: first output buffer to be sent.
* \param send_count Out: number of output buffers to be sent.
*/
void tcp_outbufs_can_send(struct tcp_outbufs *ob, ssize_t window_size, bool resend,
struct tcp_outbuf **send_start, size_t *send_count);
void tcp_outbufs_can_send(knot_tcp_outbuf_t *bufs, ssize_t window_size, bool resend,
knot_tcp_outbuf_t **send_start, size_t *send_count);
/*!
* \brief Compute allocated size of output buffers.
*/
size_t tcp_outbufs_usage(struct tcp_outbufs *ob);
size_t tcp_outbufs_usage(knot_tcp_outbuf_t *bufs);
/*! @} */
......@@ -537,7 +537,7 @@ void test_obufs(void)
int ret = knot_tcp_reply_data(&rl, test_table, false, data, DATA_LEN), i = 0;
is_int(KNOT_EOK, ret, "obufs: fill with data");
for (struct tcp_outbuf *ob = rl.conn->outbufs.bufs; ob != NULL; ob = ob->next, i++) {
for (knot_tcp_outbuf_t *ob = rl.conn->outbufs; ob != NULL; ob = ob->next, i++) {
if (ob->next == NULL) {
ok(ob->len > 0, "init last ob[%d]: non-trivial", i);
ok(ob->len <= TEST_MSS, "init last ob[%d]: fulfills MSS", i);
......@@ -549,7 +549,7 @@ void test_obufs(void)
ret = knot_tcp_send(test_sock, &rl, 1, 20), i = 0;
is_int(KNOT_EOK, ret, "obufs: send OK");
is_int((DATA_LEN + 2) / TEST_MSS * TEST_MSS, sent2_data, "obufs: sent all but one MSS");
for (struct tcp_outbuf *ob = rl.conn->outbufs.bufs; ob != NULL; ob = ob->next, i++) {
for (knot_tcp_outbuf_t *ob = rl.conn->outbufs; ob != NULL; ob = ob->next, i++) {
if (ob->next == NULL) {
ok(!ob->sent, "last ob[%d]: not sent", i);
} else {
......@@ -565,7 +565,7 @@ void test_obufs(void)
ret = knot_tcp_recv(&rl, &msg, 1, test_table, test_syn_table, XDP_TCP_IGNORE_NONE);
is_int(KNOT_EOK, ret, "obufs: ACKed data");
rl.conn->window_size = 65536;
struct tcp_outbuf *surv_ob = rl.conn->outbufs.bufs;
knot_tcp_outbuf_t *surv_ob = rl.conn->outbufs;
ok(surv_ob != NULL, "obufs: unACKed survived");
ok(surv_ob->next == NULL, "obufs: just one survived");
ok(!surv_ob->sent, "obufs: survivor not sent");
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment