Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 | /* * Copyright (c) 2018-2019 Intel Corporation * * SPDX-License-Identifier: Apache-2.0 */ #include "tp.h" #define is(_a, _b) (strcmp((_a), (_b)) == 0) #define is_timer_subscribed(_t) (k_timer_remaining_get(_t)) #define th_seq(_x) ntohl((_x)->th_seq) #define th_ack(_x) ntohl((_x)->th_ack) #define ip_get(_x) ((struct net_ipv4_hdr *) net_pkt_ip_data((_x))) #define ip6_get(_x) ((struct net_ipv6_hdr *) net_pkt_ip_data((_x))) #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_nbuf_alloc(_pool, _len) \ tp_nbuf_alloc(_pool, _len, tp_basename(__FILE__), __LINE__, __func__) #define tcp_nbuf_unref(_nbuf) \ tp_nbuf_unref(_nbuf, tp_basename(__FILE__), __LINE__, __func__) #else #define tcp_nbuf_alloc(_pool, _len) net_buf_alloc_len(_pool, _len, K_NO_WAIT) #define tcp_nbuf_unref(_nbuf) net_buf_unref(_nbuf) #endif #if IS_ENABLED(CONFIG_NET_TEST_PROTOCOL) #define tcp_pkt_alloc(_len) tp_pkt_alloc(_len, tp_basename(__FILE__), __LINE__) #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 #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_PAD 0 #define TCPOPT_NOP 1 #define TCPOPT_MAXSEG 2 #define TCPOPT_WINDOW 3 enum pkt_addr { SRC = 1, 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_WAIT1, TCP_FIN_WAIT2, TCP_CLOSE_WAIT, TCP_CLOSING, TCP_LAST_ACK, TCP_TIME_WAIT, TCP_CLOSED }; struct tcp_win { /* TCP window */ size_t len; sys_slist_t bufs; }; union tcp_endpoint { struct sockaddr sa; struct sockaddr_in sin; struct sockaddr_in6 sin6; }; struct tcp { /* TCP connection */ sys_snode_t next; struct net_context *context; 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_win *rcv; struct tcp_win *snd; struct k_timer send_timer; sys_slist_t send_queue; bool in_retransmission; size_t send_retries; 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) |