net: tcp2: Eliminate the need for a test send window
In order to drop dependency on a heap, drop the test send window. Use net_tcp_queue_data() to receive the outgoing data from the socket layer. Signed-off-by: Oleg Zhurakivskyy <oleg.zhurakivskyy@intel.com>
This commit is contained in:
parent
b25faa6159
commit
16b8244cf8
3 changed files with 44 additions and 87 deletions
|
@ -1572,14 +1572,7 @@ static int context_sendto(struct net_context *context,
|
||||||
ret = net_send_data(pkt);
|
ret = net_send_data(pkt);
|
||||||
} else if (IS_ENABLED(CONFIG_NET_TCP) &&
|
} else if (IS_ENABLED(CONFIG_NET_TCP) &&
|
||||||
net_context_get_ip_proto(context) == IPPROTO_TCP) {
|
net_context_get_ip_proto(context) == IPPROTO_TCP) {
|
||||||
#if IS_ENABLED(CONFIG_NET_TCP2)
|
|
||||||
ret = net_tcp_queue(context, buf, len, msghdr);
|
|
||||||
if (ret < 0) {
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
net_pkt_unref(pkt);
|
|
||||||
#else
|
|
||||||
ret = context_write_data(pkt, buf, len, msghdr);
|
ret = context_write_data(pkt, buf, len, msghdr);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
goto fail;
|
goto fail;
|
||||||
|
@ -1590,7 +1583,6 @@ static int context_sendto(struct net_context *context,
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
ret = net_tcp_send_data(context, cb, user_data);
|
ret = net_tcp_send_data(context, cb, user_data);
|
||||||
} else if (IS_ENABLED(CONFIG_NET_SOCKETS_PACKET) &&
|
} else if (IS_ENABLED(CONFIG_NET_SOCKETS_PACKET) &&
|
||||||
|
|
|
@ -266,8 +266,6 @@ static int tcp_conn_unref(struct tcp *conn)
|
||||||
|
|
||||||
tcp_send_queue_flush(conn);
|
tcp_send_queue_flush(conn);
|
||||||
|
|
||||||
tcp_win_free(conn->snd, "SND");
|
|
||||||
|
|
||||||
tcp_free(conn->src);
|
tcp_free(conn->src);
|
||||||
tcp_free(conn->dst);
|
tcp_free(conn->dst);
|
||||||
|
|
||||||
|
@ -541,21 +539,26 @@ static size_t tcp_data_get(struct tcp *conn, struct net_pkt *pkt)
|
||||||
|
|
||||||
static void tcp_header_add(struct tcp *conn, struct net_pkt *pkt, u8_t flags)
|
static void tcp_header_add(struct tcp *conn, struct net_pkt *pkt, u8_t flags)
|
||||||
{
|
{
|
||||||
struct tcphdr *th = th_get(pkt);
|
struct net_buf *buf = net_pkt_get_frag(pkt, K_NO_WAIT);
|
||||||
|
struct tcphdr th;
|
||||||
|
|
||||||
memset(th, 0, sizeof(*th));
|
memset(&th, 0, sizeof(th));
|
||||||
|
|
||||||
th->th_sport = conn->src->sin.sin_port;
|
th.th_sport = conn->src->sin.sin_port;
|
||||||
th->th_dport = conn->dst->sin.sin_port;
|
th.th_dport = conn->dst->sin.sin_port;
|
||||||
|
|
||||||
th->th_off = 5;
|
th.th_off = 5;
|
||||||
th->th_flags = flags;
|
th.th_flags = flags;
|
||||||
th->th_win = htons(conn->win);
|
th.th_win = htons(conn->win);
|
||||||
th->th_seq = htonl(conn->seq);
|
th.th_seq = htonl(conn->seq);
|
||||||
|
|
||||||
if (ACK & flags) {
|
if (ACK & flags) {
|
||||||
th->th_ack = htonl(conn->ack);
|
th.th_ack = htonl(conn->ack);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
memcpy(net_buf_add(buf, sizeof(th)), &th, sizeof(th));
|
||||||
|
|
||||||
|
net_pkt_frag_insert(pkt, buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ip_header_add(struct tcp *conn, struct net_pkt *pkt)
|
static void ip_header_add(struct tcp *conn, struct net_pkt *pkt)
|
||||||
|
@ -612,17 +615,6 @@ static void ip_header_add(struct tcp *conn, struct net_pkt *pkt)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct net_pkt *tcp_pkt_make(struct tcp *conn, u8_t flags)
|
|
||||||
{
|
|
||||||
struct net_pkt *pkt = tcp_pkt_alloc(sizeof(struct tcphdr));
|
|
||||||
|
|
||||||
tcp_header_add(conn, pkt, flags);
|
|
||||||
|
|
||||||
pkt->iface = conn->iface;
|
|
||||||
|
|
||||||
return pkt;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void tcp_chain_free(struct net_buf *head)
|
static void tcp_chain_free(struct net_buf *head)
|
||||||
{
|
{
|
||||||
struct net_buf *next;
|
struct net_buf *next;
|
||||||
|
@ -650,31 +642,38 @@ static void tcp_chain(struct net_pkt *pkt, struct net_buf *head)
|
||||||
|
|
||||||
static void tcp_out(struct tcp *conn, u8_t flags, ...)
|
static void tcp_out(struct tcp *conn, u8_t flags, ...)
|
||||||
{
|
{
|
||||||
struct net_pkt *pkt = tcp_pkt_make(conn, flags);
|
struct net_pkt *pkt;
|
||||||
|
size_t len = 0;
|
||||||
|
|
||||||
if (PSH & flags) {
|
if (PSH & flags) {
|
||||||
size_t len = conn->snd->len;
|
va_list ap;
|
||||||
struct net_buf *buf = tcp_win_peek(conn, conn->snd, "SND", len);
|
va_start(ap, flags);
|
||||||
|
pkt = va_arg(ap, struct net_pkt *);
|
||||||
|
va_end(ap);
|
||||||
|
|
||||||
{
|
len = net_pkt_get_len(pkt);
|
||||||
va_list ap;
|
} else {
|
||||||
ssize_t *out_len;
|
pkt = tcp_pkt_alloc(0);
|
||||||
|
|
||||||
va_start(ap, flags);
|
|
||||||
out_len = va_arg(ap, ssize_t *);
|
|
||||||
*out_len = len;
|
|
||||||
va_end(ap);
|
|
||||||
}
|
|
||||||
|
|
||||||
tcp_chain(pkt, buf);
|
|
||||||
|
|
||||||
tcp_chain_free(buf);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pkt->iface = conn->iface;
|
||||||
|
|
||||||
|
tcp_header_add(conn, pkt, flags);
|
||||||
|
|
||||||
ip_header_add(conn, pkt);
|
ip_header_add(conn, pkt);
|
||||||
|
|
||||||
|
net_pkt_cursor_init(pkt);
|
||||||
|
net_pkt_set_overwrite(pkt, true);
|
||||||
|
|
||||||
|
net_pkt_skip(pkt, net_pkt_ip_hdr_len(pkt) +
|
||||||
|
net_pkt_ip_opts_len(pkt));
|
||||||
|
|
||||||
net_tcp_finalize(pkt);
|
net_tcp_finalize(pkt);
|
||||||
|
|
||||||
|
if (len) {
|
||||||
|
conn_seq(conn, + len);
|
||||||
|
}
|
||||||
|
|
||||||
NET_DBG("%s", log_strdup(tcp_th(pkt)));
|
NET_DBG("%s", log_strdup(tcp_th(pkt)));
|
||||||
|
|
||||||
if (tcp_send_cb) {
|
if (tcp_send_cb) {
|
||||||
|
@ -712,8 +711,6 @@ static struct tcp *tcp_conn_alloc(void)
|
||||||
|
|
||||||
conn->win = tcp_window;
|
conn->win = tcp_window;
|
||||||
|
|
||||||
conn->snd = tcp_win_new();
|
|
||||||
|
|
||||||
sys_slist_init(&conn->send_queue);
|
sys_slist_init(&conn->send_queue);
|
||||||
|
|
||||||
k_delayed_work_init(&conn->send_timer, tcp_send_process);
|
k_delayed_work_init(&conn->send_timer, tcp_send_process);
|
||||||
|
@ -987,13 +984,6 @@ next_state:
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case TCP_ESTABLISHED:
|
case TCP_ESTABLISHED:
|
||||||
if (!th && conn->snd->len) { /* TODO: Out of the loop */
|
|
||||||
ssize_t data_len;
|
|
||||||
|
|
||||||
tcp_out(conn, PSH | ACK, &data_len);
|
|
||||||
conn_seq(conn, + data_len);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
/* full-close */
|
/* full-close */
|
||||||
if (FL(&fl, ==, (FIN | ACK), th_seq(th) == conn->ack)) {
|
if (FL(&fl, ==, (FIN | ACK), th_seq(th) == conn->ack)) {
|
||||||
conn_ack(conn, + 1);
|
conn_ack(conn, + 1);
|
||||||
|
@ -1112,48 +1102,24 @@ int net_tcp_update_recv_wnd(struct net_context *context, s32_t delta)
|
||||||
return -EPROTONOSUPPORT;
|
return -EPROTONOSUPPORT;
|
||||||
}
|
}
|
||||||
|
|
||||||
int net_tcp_queue(struct net_context *context, const void *buf, size_t len,
|
/* net context wants to queue data for the TCP connection */
|
||||||
const struct msghdr *msghdr)
|
int net_tcp_queue_data(struct net_context *context, struct net_pkt *pkt)
|
||||||
{
|
{
|
||||||
struct tcp *conn = context->tcp;
|
struct tcp *conn = context->tcp;
|
||||||
ssize_t ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
NET_DBG("conn: %p, buf: %p, len: %zu", conn, buf, len);
|
NET_DBG("conn: %p, len: %zu", conn, net_pkt_get_len(pkt));
|
||||||
|
|
||||||
if (conn == NULL) {
|
if (!conn || conn->state != TCP_ESTABLISHED) {
|
||||||
ret = -ESHUTDOWN;
|
ret = -ENOTCONN;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (msghdr && msghdr->msg_iovlen > 0) {
|
tcp_out(conn, PSH | ACK, pkt);
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 0; i < msghdr->msg_iovlen; i++) {
|
|
||||||
ret = _tcp_send(conn, msghdr->msg_iov[i].iov_base,
|
|
||||||
msghdr->msg_iov[i].iov_len, 0);
|
|
||||||
|
|
||||||
if (ret < 0) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
ret = _tcp_send(conn, buf, len, 0);
|
|
||||||
}
|
|
||||||
out:
|
out:
|
||||||
NET_DBG("conn: %p, ret: %zd", conn, ret);
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* net context wants to queue data for the TCP connection - not used */
|
|
||||||
int net_tcp_queue_data(struct net_context *context, struct net_pkt *pkt)
|
|
||||||
{
|
|
||||||
ARG_UNUSED(context);
|
|
||||||
ARG_UNUSED(pkt);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* net context is about to send out queued data - inform caller only */
|
/* net context is about to send out queued data - inform caller only */
|
||||||
int net_tcp_send_data(struct net_context *context, net_context_send_cb_t cb,
|
int net_tcp_send_data(struct net_context *context, net_context_send_cb_t cb,
|
||||||
void *user_data)
|
void *user_data)
|
||||||
|
|
|
@ -153,7 +153,6 @@ struct tcp { /* TCP connection */
|
||||||
union tcp_endpoint *src;
|
union tcp_endpoint *src;
|
||||||
union tcp_endpoint *dst;
|
union tcp_endpoint *dst;
|
||||||
u16_t win;
|
u16_t win;
|
||||||
struct tcp_win *snd;
|
|
||||||
struct k_delayed_work send_timer;
|
struct k_delayed_work send_timer;
|
||||||
sys_slist_t send_queue;
|
sys_slist_t send_queue;
|
||||||
bool in_retransmission;
|
bool in_retransmission;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue