net: tcp2: Simplify TCP pkt creation
Use existing network stack calls to create net pkt, ip header and tcp header creation. Also simplify finalize api calls. Signed-off-by: Ravi kumar Veeramally <ravikumar.veeramally@linux.intel.com>
This commit is contained in:
parent
a4d4485c0e
commit
69551b4681
2 changed files with 88 additions and 91 deletions
|
@ -15,6 +15,7 @@ LOG_MODULE_REGISTER(net_tcp, CONFIG_NET_TCP_LOG_LEVEL);
|
|||
#include <net/net_context.h>
|
||||
#include <net/udp.h>
|
||||
#include "ipv4.h"
|
||||
#include "ipv6.h"
|
||||
#include "connection.h"
|
||||
#include "net_stats.h"
|
||||
#include "net_private.h"
|
||||
|
@ -465,113 +466,122 @@ static size_t tcp_data_get(struct tcp *conn, struct net_pkt *pkt)
|
|||
return len;
|
||||
}
|
||||
|
||||
static void tcp_header_add(struct tcp *conn, struct net_pkt *pkt, u8_t flags)
|
||||
static int tcp_finalize_pkt(struct net_pkt *pkt)
|
||||
{
|
||||
struct net_buf *buf = net_pkt_get_frag(pkt, K_NO_WAIT);
|
||||
struct tcphdr th;
|
||||
net_pkt_cursor_init(pkt);
|
||||
|
||||
memset(&th, 0, sizeof(th));
|
||||
|
||||
th.th_sport = conn->src->sin.sin_port;
|
||||
th.th_dport = conn->dst->sin.sin_port;
|
||||
|
||||
th.th_off = 5;
|
||||
th.th_flags = flags;
|
||||
th.th_win = htons(conn->win);
|
||||
th.th_seq = htonl(conn->seq);
|
||||
|
||||
if (ACK & flags) {
|
||||
th.th_ack = htonl(conn->ack);
|
||||
if (IS_ENABLED(CONFIG_NET_IPV4) && net_pkt_family(pkt) == AF_INET) {
|
||||
return net_ipv4_finalize(pkt, IPPROTO_TCP);
|
||||
}
|
||||
|
||||
memcpy(net_buf_add(buf, sizeof(th)), &th, sizeof(th));
|
||||
if (IS_ENABLED(CONFIG_NET_IPV6) && net_pkt_family(pkt) == AF_INET6) {
|
||||
return net_ipv6_finalize(pkt, IPPROTO_TCP);
|
||||
}
|
||||
|
||||
net_pkt_frag_insert(pkt, buf);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static void ip_header_add(struct tcp *conn, struct net_pkt *pkt)
|
||||
static int tcp_header_add(struct tcp *conn, struct net_pkt *pkt, u8_t flags)
|
||||
{
|
||||
struct net_buf *buf = net_pkt_get_frag(pkt, K_NO_WAIT);
|
||||
NET_PKT_DATA_ACCESS_DEFINE(tcp_access, struct tcphdr);
|
||||
struct tcphdr *th;
|
||||
|
||||
pkt->family = net_context_get_family(conn->context);
|
||||
|
||||
switch (pkt->family) {
|
||||
case AF_INET: {
|
||||
struct net_ipv4_hdr ip;
|
||||
|
||||
memset(&ip, 0, sizeof(ip));
|
||||
|
||||
ip.vhl = 0x45;
|
||||
ip.ttl = 64;
|
||||
ip.proto = IPPROTO_TCP;
|
||||
ip.len = htons(net_pkt_get_len(pkt) + sizeof(ip));
|
||||
|
||||
ip.src = conn->src->sin.sin_addr;
|
||||
ip.dst = conn->dst->sin.sin_addr;
|
||||
|
||||
memcpy(net_buf_add(buf, sizeof(ip)), &ip, sizeof(ip));
|
||||
|
||||
net_pkt_frag_insert(pkt, buf);
|
||||
|
||||
net_pkt_set_ip_hdr_len(pkt, buf->len);
|
||||
|
||||
net_pkt_cursor_init(pkt);
|
||||
|
||||
net_ipv4_finalize(pkt, IPPROTO_TCP);
|
||||
break;
|
||||
th = (struct tcphdr *)net_pkt_get_data(pkt, &tcp_access);
|
||||
if (!th) {
|
||||
return -ENOBUFS;
|
||||
}
|
||||
case AF_INET6: {
|
||||
struct net_ipv6_hdr ip6;
|
||||
|
||||
memset(&ip6, 0, sizeof(ip6));
|
||||
memset(th, 0, sizeof(struct tcphdr));
|
||||
|
||||
ip6.vtc = 0x60;
|
||||
ip6.nexthdr = IPPROTO_TCP;
|
||||
ip6.len = htons(net_pkt_get_len(pkt));
|
||||
th->th_sport = conn->src->sin.sin_port;
|
||||
th->th_dport = conn->dst->sin.sin_port;
|
||||
|
||||
ip6.src = conn->src->sin6.sin6_addr;
|
||||
ip6.dst = conn->dst->sin6.sin6_addr;
|
||||
th->th_off = 5;
|
||||
th->th_flags = flags;
|
||||
th->th_win = htons(conn->win);
|
||||
th->th_seq = htonl(conn->seq);
|
||||
|
||||
memcpy(net_buf_add(buf, sizeof(ip6)), &ip6, sizeof(ip6));
|
||||
|
||||
net_pkt_frag_insert(pkt, buf);
|
||||
|
||||
net_pkt_set_ip_hdr_len(pkt, buf->len);
|
||||
|
||||
break;
|
||||
if (ACK & flags) {
|
||||
th->th_ack = htonl(conn->ack);
|
||||
}
|
||||
|
||||
return net_pkt_set_data(pkt, &tcp_access);
|
||||
}
|
||||
|
||||
static int ip_header_add(struct tcp *conn, struct net_pkt *pkt)
|
||||
{
|
||||
if (IS_ENABLED(CONFIG_NET_IPV4) && net_pkt_family(pkt) == AF_INET) {
|
||||
return net_context_create_ipv4_new(conn->context, pkt,
|
||||
&conn->src->sin.sin_addr,
|
||||
&conn->dst->sin.sin_addr);
|
||||
}
|
||||
|
||||
if (IS_ENABLED(CONFIG_NET_IPV6) && net_pkt_family(pkt) == AF_INET6) {
|
||||
return net_context_create_ipv6_new(conn->context, pkt,
|
||||
&conn->src->sin6.sin6_addr,
|
||||
&conn->dst->sin6.sin6_addr);
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static struct net_pkt *tcp_pkt_alloc(struct net_if *iface,
|
||||
sa_family_t family, size_t len)
|
||||
{
|
||||
struct net_pkt *pkt;
|
||||
|
||||
pkt = net_pkt_alloc_with_buffer(iface, len, family,
|
||||
IPPROTO_TCP, K_NO_WAIT);
|
||||
|
||||
#if IS_ENABLED(CONFIG_NET_TEST_PROTOCOL)
|
||||
tp_pkt_alloc(pkt);
|
||||
#endif
|
||||
return pkt;
|
||||
}
|
||||
|
||||
static void tcp_out(struct tcp *conn, u8_t flags, ...)
|
||||
{
|
||||
struct net_pkt *pkt;
|
||||
size_t len = 0;
|
||||
int r;
|
||||
|
||||
pkt = tcp_pkt_alloc(conn->iface, net_context_get_family(conn->context),
|
||||
sizeof(struct tcphdr));
|
||||
if (!pkt) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (PSH & flags) {
|
||||
struct net_pkt *data_pkt;
|
||||
va_list ap;
|
||||
va_start(ap, flags);
|
||||
pkt = va_arg(ap, struct net_pkt *);
|
||||
data_pkt = va_arg(ap, struct net_pkt *);
|
||||
va_end(ap);
|
||||
|
||||
len = net_pkt_get_len(pkt);
|
||||
} else {
|
||||
pkt = tcp_pkt_alloc(0);
|
||||
len = net_pkt_get_len(data_pkt);
|
||||
/* Append the data buffer to pkt */
|
||||
net_pkt_append_buffer(pkt, data_pkt->buffer);
|
||||
|
||||
data_pkt->buffer = NULL;
|
||||
tcp_pkt_unref(data_pkt);
|
||||
}
|
||||
|
||||
pkt->iface = conn->iface;
|
||||
|
||||
tcp_header_add(conn, pkt, flags);
|
||||
r = ip_header_add(conn, pkt);
|
||||
if (r < 0) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ip_header_add(conn, pkt);
|
||||
r = tcp_header_add(conn, pkt, flags);
|
||||
if (r < 0) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
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);
|
||||
r = tcp_finalize_pkt(pkt);
|
||||
if (r < 0) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (len) {
|
||||
conn_seq(conn, + len);
|
||||
|
@ -589,6 +599,11 @@ static void tcp_out(struct tcp *conn, u8_t flags, ...)
|
|||
tcp_send_process((struct k_work *)&conn->send_timer);
|
||||
out:
|
||||
return;
|
||||
|
||||
fail:
|
||||
if (pkt) {
|
||||
tcp_pkt_unref(pkt);
|
||||
}
|
||||
}
|
||||
|
||||
static void tcp_conn_ref(struct tcp *conn)
|
||||
|
|
|
@ -37,24 +37,6 @@
|
|||
#define tcp_pkt_clone(_pkt) tp_pkt_clone(_pkt, tp_basename(__FILE__), __LINE__)
|
||||
#define tcp_pkt_unref(_pkt) tp_pkt_unref(_pkt, tp_basename(__FILE__), __LINE__)
|
||||
#else
|
||||
static struct net_pkt *tcp_pkt_alloc(size_t len)
|
||||
{
|
||||
struct net_pkt *pkt = net_pkt_alloc(K_NO_WAIT);
|
||||
|
||||
pkt->family = AF_INET;
|
||||
|
||||
NET_ASSERT(pkt);
|
||||
|
||||
if (len) {
|
||||
struct net_buf *buf = net_pkt_get_frag(pkt, K_NO_WAIT);
|
||||
|
||||
net_buf_add(buf, len);
|
||||
net_pkt_frag_insert(pkt, buf);
|
||||
NET_ASSERT(buf);
|
||||
}
|
||||
|
||||
return pkt;
|
||||
}
|
||||
#define tcp_pkt_clone(_pkt) net_pkt_clone(_pkt, K_NO_WAIT)
|
||||
#define tcp_pkt_unref(_pkt) net_pkt_unref(_pkt)
|
||||
#endif
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue