183 lines
4.2 KiB
C
183 lines
4.2 KiB
C
/*
|
|
* Copyright (c) 2018-2019 Intel Corporation
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
#include "tp.h"
|
|
|
|
#define is(_a, _b) (strcmp((_a), (_b)) == 0)
|
|
|
|
#define th_seq(_x) ntohl((_x)->th_seq)
|
|
#define th_ack(_x) ntohl((_x)->th_ack)
|
|
|
|
#define tcp_slist(_slist, _op, _type, _link) \
|
|
({ \
|
|
sys_snode_t *_node = sys_slist_##_op(_slist); \
|
|
\
|
|
_type * _x = _node ? CONTAINER_OF(_node, _type, _link) : NULL; \
|
|
\
|
|
_x; \
|
|
})
|
|
|
|
#if IS_ENABLED(CONFIG_NET_TEST_PROTOCOL)
|
|
#define tcp_malloc(_size) \
|
|
tp_malloc(_size, tp_basename(__FILE__), __LINE__, __func__)
|
|
#define tcp_calloc(_nmemb, _size) \
|
|
tp_calloc(_nmemb, _size, tp_basename(__FILE__), __LINE__, __func__)
|
|
#define tcp_free(_ptr) tp_free(_ptr, tp_basename(__FILE__), __LINE__, __func__)
|
|
#else
|
|
#define tcp_malloc(_size) k_malloc(_size)
|
|
#define tcp_calloc(_nmemb, _size) k_calloc(_nmemb, _size)
|
|
#define tcp_free(_ptr) k_free(_ptr)
|
|
#endif
|
|
|
|
#if IS_ENABLED(CONFIG_NET_TEST_PROTOCOL)
|
|
#define tcp_pkt_alloc(_conn, _len) \
|
|
({ \
|
|
sa_family_t _family = net_context_get_family((_conn)->context); \
|
|
struct net_pkt *_pkt = net_pkt_alloc_with_buffer((_conn)->iface,\
|
|
(_len), \
|
|
_family, \
|
|
IPPROTO_TCP, \
|
|
K_NO_WAIT); \
|
|
\
|
|
tp_pkt_alloc(_pkt, tp_basename(__FILE__), __LINE__); \
|
|
\
|
|
_pkt; \
|
|
})
|
|
#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
|
|
#define tcp_pkt_alloc(_conn, _len) \
|
|
net_pkt_alloc_with_buffer((_conn)->iface, (_len), \
|
|
net_context_get_family((_conn)->context), \
|
|
IPPROTO_TCP, K_NO_WAIT)
|
|
|
|
#define tcp_pkt_clone(_pkt) net_pkt_clone(_pkt, K_NO_WAIT)
|
|
#define tcp_pkt_unref(_pkt) net_pkt_unref(_pkt)
|
|
#endif
|
|
#define tcp_pkt_ref(_pkt) net_pkt_ref(_pkt)
|
|
|
|
#if IS_ENABLED(CONFIG_NET_TEST_PROTOCOL)
|
|
#define conn_seq(_conn, _req) \
|
|
tp_seq_track(TP_SEQ, &(_conn)->seq, (_req), tp_basename(__FILE__), \
|
|
__LINE__, __func__)
|
|
#define conn_ack(_conn, _req) \
|
|
tp_seq_track(TP_ACK, &(_conn)->ack, (_req), tp_basename(__FILE__), \
|
|
__LINE__, __func__)
|
|
#else
|
|
#define conn_seq(_conn, _req) (_conn)->seq += (_req)
|
|
#define conn_ack(_conn, _req) (_conn)->ack += (_req)
|
|
#endif
|
|
|
|
#define conn_state(_conn, _s) \
|
|
({ \
|
|
NET_DBG("%s->%s", \
|
|
tcp_state_to_str((_conn)->state, false), \
|
|
tcp_state_to_str((_s), false)); \
|
|
(_conn)->state = _s; \
|
|
})
|
|
|
|
#define TCPOPT_END 0
|
|
#define TCPOPT_NOP 1
|
|
#define TCPOPT_MAXSEG 2
|
|
#define TCPOPT_WINDOW 3
|
|
|
|
enum pkt_addr {
|
|
TCP_EP_SRC = 1,
|
|
TCP_EP_DST = 0
|
|
};
|
|
|
|
struct tcphdr {
|
|
u16_t th_sport;
|
|
u16_t th_dport;
|
|
u32_t th_seq;
|
|
u32_t th_ack;
|
|
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
|
|
u8_t th_x2:4; /* unused */
|
|
u8_t th_off:4; /* data offset */
|
|
#endif
|
|
#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
|
|
u8_t th_off:4;
|
|
u8_t th_x2:4;
|
|
#endif
|
|
u8_t th_flags;
|
|
u16_t th_win;
|
|
u16_t th_sum;
|
|
u16_t th_urp;
|
|
};
|
|
|
|
enum th_flags {
|
|
FIN = 1,
|
|
SYN = 1 << 1,
|
|
RST = 1 << 2,
|
|
PSH = 1 << 3,
|
|
ACK = 1 << 4,
|
|
URG = 1 << 5,
|
|
};
|
|
|
|
enum tcp_state {
|
|
TCP_LISTEN = 1,
|
|
TCP_SYN_SENT,
|
|
TCP_SYN_RECEIVED,
|
|
TCP_ESTABLISHED,
|
|
TCP_FIN_WAIT_1,
|
|
TCP_FIN_WAIT_2,
|
|
TCP_CLOSE_WAIT,
|
|
TCP_CLOSING,
|
|
TCP_LAST_ACK,
|
|
TCP_TIME_WAIT,
|
|
TCP_CLOSED
|
|
};
|
|
|
|
union tcp_endpoint {
|
|
struct sockaddr sa;
|
|
struct sockaddr_in sin;
|
|
struct sockaddr_in6 sin6;
|
|
};
|
|
|
|
struct tcp_options {
|
|
u16_t mss;
|
|
u16_t window;
|
|
bool mss_found : 1;
|
|
bool wnd_found : 1;
|
|
};
|
|
|
|
struct tcp { /* TCP connection */
|
|
sys_snode_t next;
|
|
struct net_context *context;
|
|
struct k_mutex lock;
|
|
void *recv_user_data;
|
|
enum tcp_state state;
|
|
u32_t seq;
|
|
u32_t ack;
|
|
union tcp_endpoint src;
|
|
union tcp_endpoint dst;
|
|
u16_t win;
|
|
struct tcp_options recv_options;
|
|
struct k_delayed_work send_timer;
|
|
sys_slist_t send_queue;
|
|
bool in_retransmission;
|
|
size_t send_retries;
|
|
struct k_delayed_work timewait_timer;
|
|
struct net_if *iface;
|
|
net_tcp_accept_cb_t accept_cb;
|
|
atomic_t ref_count;
|
|
};
|
|
|
|
#define _flags(_fl, _op, _mask, _cond) \
|
|
({ \
|
|
bool result = false; \
|
|
\
|
|
if (*(_fl) && (_cond) && (*(_fl) _op (_mask))) { \
|
|
*(_fl) &= ~(_mask); \
|
|
result = true; \
|
|
} \
|
|
\
|
|
result; \
|
|
})
|
|
|
|
#define FL(_fl, _op, _mask, _args...) \
|
|
_flags(_fl, _op, _mask, strlen("" #_args) ? _args : true)
|