Lines Matching full:conn
63 #define TCP_RTO_MS (conn->rto)
82 static enum net_verdict tcp_in(struct tcp *conn, struct net_pkt *pkt);
84 static void tcp_out(struct tcp *conn, uint8_t flags);
88 size_t (*tcp_recv_cb)(struct tcp *conn, struct net_pkt *pkt) = NULL;
248 const struct tcp *conn = ctx->tcp; in net_tcp_endpoint_copy() local
258 if (conn->state < TCP_ESTABLISHED) { in net_tcp_endpoint_copy()
277 memcpy(local, &conn->src.sa, newlen); in net_tcp_endpoint_copy()
282 memcpy(peer, &conn->dst.sa, newlen); in net_tcp_endpoint_copy()
422 static void tcp_derive_rto(struct tcp *conn) in tcp_derive_rto() argument
438 conn->rto = (uint16_t)rto; in tcp_derive_rto()
440 ARG_UNUSED(conn); in tcp_derive_rto()
448 static void tcp_new_reno_log(struct tcp *conn, char *step) in tcp_new_reno_log() argument
450 NET_DBG("conn: %p, ca %s, cwnd=%d, ssthres=%d, fast_pend=%i", in tcp_new_reno_log()
451 conn, step, conn->ca.cwnd, conn->ca.ssthresh, in tcp_new_reno_log()
452 conn->ca.pending_fast_retransmit_bytes); in tcp_new_reno_log()
455 static void tcp_new_reno_init(struct tcp *conn) in tcp_new_reno_init() argument
457 conn->ca.cwnd = conn_mss(conn) * TCP_CONGESTION_INITIAL_WIN; in tcp_new_reno_init()
458 conn->ca.ssthresh = conn_mss(conn) * TCP_CONGESTION_INITIAL_SSTHRESH; in tcp_new_reno_init()
459 conn->ca.pending_fast_retransmit_bytes = 0; in tcp_new_reno_init()
460 tcp_new_reno_log(conn, "init"); in tcp_new_reno_init()
463 static void tcp_new_reno_fast_retransmit(struct tcp *conn) in tcp_new_reno_fast_retransmit() argument
465 if (conn->ca.pending_fast_retransmit_bytes == 0) { in tcp_new_reno_fast_retransmit()
466 conn->ca.ssthresh = MAX(conn_mss(conn) * 2, conn->unacked_len / 2); in tcp_new_reno_fast_retransmit()
468 conn->ca.cwnd = conn_mss(conn) * 3 + conn->ca.ssthresh; in tcp_new_reno_fast_retransmit()
469 conn->ca.pending_fast_retransmit_bytes = conn->unacked_len; in tcp_new_reno_fast_retransmit()
470 tcp_new_reno_log(conn, "fast_retransmit"); in tcp_new_reno_fast_retransmit()
474 static void tcp_new_reno_timeout(struct tcp *conn) in tcp_new_reno_timeout() argument
476 conn->ca.ssthresh = MAX(conn_mss(conn) * 2, conn->unacked_len / 2); in tcp_new_reno_timeout()
477 conn->ca.cwnd = conn_mss(conn); in tcp_new_reno_timeout()
478 tcp_new_reno_log(conn, "timeout"); in tcp_new_reno_timeout()
482 static void tcp_new_reno_dup_ack(struct tcp *conn) in tcp_new_reno_dup_ack() argument
484 int32_t new_win = conn->ca.cwnd; in tcp_new_reno_dup_ack()
486 new_win += conn_mss(conn); in tcp_new_reno_dup_ack()
487 conn->ca.cwnd = MIN(new_win, UINT16_MAX); in tcp_new_reno_dup_ack()
488 tcp_new_reno_log(conn, "dup_ack"); in tcp_new_reno_dup_ack()
491 static void tcp_new_reno_pkts_acked(struct tcp *conn, uint32_t acked_len) in tcp_new_reno_pkts_acked() argument
493 int32_t new_win = conn->ca.cwnd; in tcp_new_reno_pkts_acked()
494 int32_t win_inc = MIN(acked_len, conn_mss(conn)); in tcp_new_reno_pkts_acked()
496 if (conn->ca.pending_fast_retransmit_bytes == 0) { in tcp_new_reno_pkts_acked()
497 if (conn->ca.cwnd < conn->ca.ssthresh) { in tcp_new_reno_pkts_acked()
501 new_win += ((win_inc * win_inc) + conn->ca.cwnd - 1) / conn->ca.cwnd; in tcp_new_reno_pkts_acked()
503 conn->ca.cwnd = MIN(new_win, UINT16_MAX); in tcp_new_reno_pkts_acked()
506 if (conn->ca.pending_fast_retransmit_bytes <= acked_len) { in tcp_new_reno_pkts_acked()
507 conn->ca.pending_fast_retransmit_bytes = 0; in tcp_new_reno_pkts_acked()
508 conn->ca.cwnd = conn->ca.ssthresh; in tcp_new_reno_pkts_acked()
510 conn->ca.pending_fast_retransmit_bytes -= acked_len; in tcp_new_reno_pkts_acked()
511 conn->ca.cwnd -= acked_len; in tcp_new_reno_pkts_acked()
514 tcp_new_reno_log(conn, "pkts_acked"); in tcp_new_reno_pkts_acked()
517 static void tcp_ca_init(struct tcp *conn) in tcp_ca_init() argument
519 tcp_new_reno_init(conn); in tcp_ca_init()
522 static void tcp_ca_fast_retransmit(struct tcp *conn) in tcp_ca_fast_retransmit() argument
524 tcp_new_reno_fast_retransmit(conn); in tcp_ca_fast_retransmit()
527 static void tcp_ca_timeout(struct tcp *conn) in tcp_ca_timeout() argument
529 tcp_new_reno_timeout(conn); in tcp_ca_timeout()
532 static void tcp_ca_dup_ack(struct tcp *conn) in tcp_ca_dup_ack() argument
534 tcp_new_reno_dup_ack(conn); in tcp_ca_dup_ack()
537 static void tcp_ca_pkts_acked(struct tcp *conn, uint32_t acked_len) in tcp_ca_pkts_acked() argument
539 tcp_new_reno_pkts_acked(conn, acked_len); in tcp_ca_pkts_acked()
543 static void tcp_ca_init(struct tcp *conn) { } in tcp_ca_init() argument
545 static void tcp_ca_fast_retransmit(struct tcp *conn) { } in tcp_ca_fast_retransmit() argument
547 static void tcp_ca_timeout(struct tcp *conn) { } in tcp_ca_timeout() argument
549 static void tcp_ca_dup_ack(struct tcp *conn) { } in tcp_ca_dup_ack() argument
551 static void tcp_ca_pkts_acked(struct tcp *conn, uint32_t acked_len) { } in tcp_ca_pkts_acked() argument
559 static void keep_alive_timer_init(struct tcp *conn) in keep_alive_timer_init() argument
561 conn->keep_alive = false; in keep_alive_timer_init()
562 conn->keep_idle = CONFIG_NET_TCP_KEEPIDLE_DEFAULT; in keep_alive_timer_init()
563 conn->keep_intvl = CONFIG_NET_TCP_KEEPINTVL_DEFAULT; in keep_alive_timer_init()
564 conn->keep_cnt = CONFIG_NET_TCP_KEEPCNT_DEFAULT; in keep_alive_timer_init()
566 conn->keep_idle, conn->keep_intvl, conn->keep_cnt); in keep_alive_timer_init()
567 k_work_init_delayable(&conn->keepalive_timer, tcp_send_keepalive_probe); in keep_alive_timer_init()
578 static void keep_alive_timer_restart(struct tcp *conn) in keep_alive_timer_restart() argument
580 if (!conn->keep_alive || conn->state != TCP_ESTABLISHED) { in keep_alive_timer_restart()
584 conn->keep_cur = 0; in keep_alive_timer_restart()
585 k_work_reschedule_for_queue(&tcp_work_q, &conn->keepalive_timer, in keep_alive_timer_restart()
586 K_SECONDS(conn->keep_idle)); in keep_alive_timer_restart()
589 static void keep_alive_timer_stop(struct tcp *conn) in keep_alive_timer_stop() argument
591 k_work_cancel_delayable(&conn->keepalive_timer); in keep_alive_timer_stop()
594 static int set_tcp_keep_alive(struct tcp *conn, const void *value, size_t len) in set_tcp_keep_alive() argument
598 if (conn == NULL || value == NULL || len != sizeof(int)) { in set_tcp_keep_alive()
607 conn->keep_alive = (bool)keep_alive; in set_tcp_keep_alive()
610 keep_alive_timer_restart(conn); in set_tcp_keep_alive()
612 keep_alive_timer_stop(conn); in set_tcp_keep_alive()
618 static int set_tcp_keep_idle(struct tcp *conn, const void *value, size_t len) in set_tcp_keep_idle() argument
622 if (conn == NULL || value == NULL || len != sizeof(int)) { in set_tcp_keep_idle()
631 conn->keep_idle = keep_idle; in set_tcp_keep_idle()
633 keep_alive_timer_restart(conn); in set_tcp_keep_idle()
638 static int set_tcp_keep_intvl(struct tcp *conn, const void *value, size_t len) in set_tcp_keep_intvl() argument
642 if (conn == NULL || value == NULL || len != sizeof(int)) { in set_tcp_keep_intvl()
651 conn->keep_intvl = keep_intvl; in set_tcp_keep_intvl()
653 keep_alive_timer_restart(conn); in set_tcp_keep_intvl()
658 static int set_tcp_keep_cnt(struct tcp *conn, const void *value, size_t len) in set_tcp_keep_cnt() argument
662 if (conn == NULL || value == NULL || len != sizeof(int)) { in set_tcp_keep_cnt()
671 conn->keep_cnt = keep_cnt; in set_tcp_keep_cnt()
673 keep_alive_timer_restart(conn); in set_tcp_keep_cnt()
678 static int get_tcp_keep_alive(struct tcp *conn, void *value, size_t *len) in get_tcp_keep_alive() argument
680 if (conn == NULL || value == NULL || len == NULL || in get_tcp_keep_alive()
685 *((int *)value) = (int)conn->keep_alive; in get_tcp_keep_alive()
690 static int get_tcp_keep_idle(struct tcp *conn, void *value, size_t *len) in get_tcp_keep_idle() argument
692 if (conn == NULL || value == NULL || len == NULL || in get_tcp_keep_idle()
697 *((int *)value) = (int)conn->keep_idle; in get_tcp_keep_idle()
702 static int get_tcp_keep_intvl(struct tcp *conn, void *value, size_t *len) in get_tcp_keep_intvl() argument
704 if (conn == NULL || value == NULL || len == NULL || in get_tcp_keep_intvl()
709 *((int *)value) = (int)conn->keep_intvl; in get_tcp_keep_intvl()
714 static int get_tcp_keep_cnt(struct tcp *conn, void *value, size_t *len) in get_tcp_keep_cnt() argument
716 if (conn == NULL || value == NULL || len == NULL || in get_tcp_keep_cnt()
721 *((int *)value) = (int)conn->keep_cnt; in get_tcp_keep_cnt()
743 static void tcp_send_queue_flush(struct tcp *conn) in tcp_send_queue_flush() argument
747 k_work_cancel_delayable(&conn->send_timer); in tcp_send_queue_flush()
749 while ((pkt = tcp_slist(conn, &conn->send_queue, get, in tcp_send_queue_flush()
757 struct tcp *conn = CONTAINER_OF(work, struct tcp, conn_release); in tcp_conn_release() local
761 if (conn->test_closed_cb != NULL) { in tcp_conn_release()
762 conn->test_closed_cb(conn, conn->test_user_data); in tcp_conn_release()
769 while ((pkt = k_fifo_get(&conn->recv_data, K_NO_WAIT)) != NULL) { in tcp_conn_release()
773 k_mutex_lock(&conn->lock, K_FOREVER); in tcp_conn_release()
775 if (conn->context->conn_handler) { in tcp_conn_release()
776 net_conn_unregister(conn->context->conn_handler); in tcp_conn_release()
777 conn->context->conn_handler = NULL; in tcp_conn_release()
783 if (conn->iface != NULL && conn->addr_ref_done) { in tcp_conn_release()
784 net_if_addr_unref(conn->iface, conn->src.sa.sa_family, in tcp_conn_release()
785 conn->src.sa.sa_family == AF_INET ? in tcp_conn_release()
786 (const void *)&conn->src.sin.sin_addr : in tcp_conn_release()
787 (const void *)&conn->src.sin6.sin6_addr); in tcp_conn_release()
790 conn->context->tcp = NULL; in tcp_conn_release()
791 conn->state = TCP_UNUSED; in tcp_conn_release()
793 tcp_send_queue_flush(conn); in tcp_conn_release()
795 (void)k_work_cancel_delayable(&conn->send_data_timer); in tcp_conn_release()
796 tcp_pkt_unref(conn->send_data); in tcp_conn_release()
799 tcp_pkt_unref(conn->queue_recv_data); in tcp_conn_release()
802 (void)k_work_cancel_delayable(&conn->timewait_timer); in tcp_conn_release()
803 (void)k_work_cancel_delayable(&conn->fin_timer); in tcp_conn_release()
804 (void)k_work_cancel_delayable(&conn->persist_timer); in tcp_conn_release()
805 (void)k_work_cancel_delayable(&conn->ack_timer); in tcp_conn_release()
806 (void)k_work_cancel_delayable(&conn->send_timer); in tcp_conn_release()
807 (void)k_work_cancel_delayable(&conn->recv_queue_timer); in tcp_conn_release()
808 keep_alive_timer_stop(conn); in tcp_conn_release()
810 k_mutex_unlock(&conn->lock); in tcp_conn_release()
812 net_context_unref(conn->context); in tcp_conn_release()
813 conn->context = NULL; in tcp_conn_release()
816 sys_slist_find_and_remove(&tcp_conns, &conn->next); in tcp_conn_release()
819 k_mem_slab_free(&tcp_conns_slab, (void *)conn); in tcp_conn_release()
834 static int tcp_conn_unref(struct tcp *conn) in tcp_conn_unref() argument
836 int ref_count = atomic_get(&conn->ref_count); in tcp_conn_unref()
838 NET_DBG("conn: %p, ref_count=%d", conn, ref_count); in tcp_conn_unref()
840 ref_count = atomic_dec(&conn->ref_count) - 1; in tcp_conn_unref()
842 tp_out(net_context_get_family(conn->context), conn->iface, in tcp_conn_unref()
851 k_work_submit_to_queue(&tcp_work_q, &conn->conn_release); in tcp_conn_unref()
857 #define tcp_conn_close(conn, status) \ argument
858 tcp_conn_close_debug(conn, status, __func__, __LINE__)
860 static int tcp_conn_close_debug(struct tcp *conn, int status, in tcp_conn_close_debug() argument
863 static int tcp_conn_close(struct tcp *conn, int status) in tcp_conn_close_debug()
867 NET_DBG("conn: %p closed by TCP stack (%s():%d)", conn, caller, line); in tcp_conn_close_debug()
869 k_mutex_lock(&conn->lock, K_FOREVER); in tcp_conn_close_debug()
870 conn_state(conn, TCP_CLOSED); in tcp_conn_close_debug()
871 keep_alive_timer_stop(conn); in tcp_conn_close_debug()
872 k_mutex_unlock(&conn->lock); in tcp_conn_close_debug()
874 if (conn->in_connect) { in tcp_conn_close_debug()
875 if (conn->connect_cb) { in tcp_conn_close_debug()
876 conn->connect_cb(conn->context, status, conn->context->user_data); in tcp_conn_close_debug()
879 conn->connect_cb = NULL; in tcp_conn_close_debug()
882 conn->in_connect = false; in tcp_conn_close_debug()
883 k_sem_reset(&conn->connect_sem); in tcp_conn_close_debug()
884 } else if (conn->context->recv_cb) { in tcp_conn_close_debug()
885 conn->context->recv_cb(conn->context, NULL, NULL, NULL, in tcp_conn_close_debug()
886 status, conn->recv_user_data); in tcp_conn_close_debug()
889 k_sem_give(&conn->tx_sem); in tcp_conn_close_debug()
891 return tcp_conn_unref(conn); in tcp_conn_close_debug()
894 static bool tcp_send_process_no_lock(struct tcp *conn) in tcp_send_process_no_lock() argument
900 pkt = tcp_slist(conn, &conn->send_queue, peek_head, in tcp_send_process_no_lock()
906 NET_DBG("%s %s", tcp_th(pkt), conn->in_retransmission ? in tcp_send_process_no_lock()
909 if (conn->in_retransmission) { in tcp_send_process_no_lock()
910 if (conn->send_retries > 0) { in tcp_send_process_no_lock()
915 conn->send_retries--; in tcp_send_process_no_lock()
928 pkt = forget ? tcp_slist(conn, &conn->send_queue, get, in tcp_send_process_no_lock()
943 !k_work_delayable_remaining_get(&conn->send_timer)) { in tcp_send_process_no_lock()
944 conn->send_retries = tcp_retries; in tcp_send_process_no_lock()
945 conn->in_retransmission = true; in tcp_send_process_no_lock()
949 if (conn->in_retransmission) { in tcp_send_process_no_lock()
950 k_work_reschedule_for_queue(&tcp_work_q, &conn->send_timer, in tcp_send_process_no_lock()
952 } else if (local && !sys_slist_is_empty(&conn->send_queue)) { in tcp_send_process_no_lock()
953 k_work_reschedule_for_queue(&tcp_work_q, &conn->send_timer, in tcp_send_process_no_lock()
964 struct tcp *conn = CONTAINER_OF(dwork, struct tcp, send_timer); in tcp_send_process() local
967 k_mutex_lock(&conn->lock, K_FOREVER); in tcp_send_process()
969 unref = tcp_send_process_no_lock(conn); in tcp_send_process()
971 k_mutex_unlock(&conn->lock); in tcp_send_process()
974 tcp_conn_close(conn, -ETIMEDOUT); in tcp_send_process()
978 static void tcp_send_timer_cancel(struct tcp *conn) in tcp_send_timer_cancel() argument
980 if (conn->in_retransmission == false) { in tcp_send_timer_cancel()
984 k_work_cancel_delayable(&conn->send_timer); in tcp_send_timer_cancel()
987 struct net_pkt *pkt = tcp_slist(conn, &conn->send_queue, get, in tcp_send_timer_cancel()
995 if (sys_slist_is_empty(&conn->send_queue)) { in tcp_send_timer_cancel()
996 conn->in_retransmission = false; in tcp_send_timer_cancel()
998 conn->send_retries = tcp_retries; in tcp_send_timer_cancel()
999 k_work_reschedule_for_queue(&tcp_work_q, &conn->send_timer, in tcp_send_timer_cancel()
1006 static void tcp_nbr_reachability_hint(struct tcp *conn) in tcp_nbr_reachability_hint() argument
1011 if (net_context_get_family(conn->context) != AF_INET6) { in tcp_nbr_reachability_hint()
1016 iface = net_context_get_iface(conn->context); in tcp_nbr_reachability_hint()
1021 if ((now - conn->last_nd_hint_time) > (net_if_ipv6_get_reachable_time(iface) / 2)) { in tcp_nbr_reachability_hint()
1022 net_ipv6_nbr_reachability_hint(iface, &conn->dst.sin6.sin6_addr); in tcp_nbr_reachability_hint()
1023 conn->last_nd_hint_time = now; in tcp_nbr_reachability_hint()
1057 static const char *tcp_conn_state(struct tcp *conn, struct net_pkt *pkt) in tcp_conn_state() argument
1063 tcp_state_to_str(conn->state, false), in tcp_conn_state()
1064 conn->seq, conn->ack); in tcp_conn_state()
1162 static bool tcp_short_window(struct tcp *conn) in tcp_short_window() argument
1164 int32_t threshold = MIN(conn_mss(conn), conn->recv_win_max / 2); in tcp_short_window()
1166 if (conn->recv_win > threshold) { in tcp_short_window()
1173 static bool tcp_need_window_update(struct tcp *conn) in tcp_need_window_update() argument
1175 int32_t threshold = MAX(conn_mss(conn), conn->recv_win_max / 2); in tcp_need_window_update()
1180 return (conn->recv_win == conn->recv_win_max && in tcp_need_window_update()
1181 conn->recv_win_sent <= threshold); in tcp_need_window_update()
1187 * @param conn TCP network connection
1193 static int tcp_update_recv_wnd(struct tcp *conn, int32_t delta) in tcp_update_recv_wnd() argument
1199 new_win = conn->recv_win + delta; in tcp_update_recv_wnd()
1202 } else if (new_win > conn->recv_win_max) { in tcp_update_recv_wnd()
1203 new_win = conn->recv_win_max; in tcp_update_recv_wnd()
1206 short_win_before = tcp_short_window(conn); in tcp_update_recv_wnd()
1208 conn->recv_win = new_win; in tcp_update_recv_wnd()
1210 short_win_after = tcp_short_window(conn); in tcp_update_recv_wnd()
1213 tcp_need_window_update(conn)) && in tcp_update_recv_wnd()
1214 conn->state == TCP_ESTABLISHED) { in tcp_update_recv_wnd()
1215 k_work_cancel_delayable(&conn->ack_timer); in tcp_update_recv_wnd()
1216 tcp_out(conn, ACK); in tcp_update_recv_wnd()
1222 static size_t tcp_check_pending_data(struct tcp *conn, struct net_pkt *pkt, in tcp_check_pending_data() argument
1228 !net_pkt_is_empty(conn->queue_recv_data)) { in tcp_check_pending_data()
1250 pending_seq = tcp_get_seq(conn->queue_recv_data->buffer); in tcp_check_pending_data()
1253 pending_len = net_pkt_get_len(conn->queue_recv_data); in tcp_check_pending_data()
1264 conn->queue_recv_data->buffer); in tcp_check_pending_data()
1265 conn->queue_recv_data->buffer = NULL; in tcp_check_pending_data()
1267 k_work_cancel_delayable(&conn->recv_queue_timer); in tcp_check_pending_data()
1271 net_buf_unref(conn->queue_recv_data->buffer); in tcp_check_pending_data()
1272 conn->queue_recv_data->buffer = NULL; in tcp_check_pending_data()
1274 k_work_cancel_delayable(&conn->recv_queue_timer); in tcp_check_pending_data()
1284 static enum net_verdict tcp_data_get(struct tcp *conn, struct net_pkt *pkt, size_t *len) in tcp_data_get() argument
1289 tcp_recv_cb(conn, pkt); in tcp_data_get()
1293 if (conn->context->recv_cb) { in tcp_data_get()
1297 *len += tcp_check_pending_data(conn, pkt, *len); in tcp_data_get()
1304 tcp_update_recv_wnd(conn, -*len); in tcp_data_get()
1305 if (*len > conn->recv_win_sent) { in tcp_data_get()
1306 conn->recv_win_sent = 0; in tcp_data_get()
1308 conn->recv_win_sent -= *len; in tcp_data_get()
1311 /* Do not pass data to application with TCP conn in tcp_data_get()
1313 * to send the data and the conn is locked. So the recv in tcp_data_get()
1315 * after unlocking the conn in tcp_data_get()
1317 k_fifo_put(&conn->recv_data, pkt); in tcp_data_get()
1340 static int tcp_header_add(struct tcp *conn, struct net_pkt *pkt, uint8_t flags, in tcp_header_add() argument
1353 UNALIGNED_PUT(conn->src.sin.sin_port, &th->th_sport); in tcp_header_add()
1354 UNALIGNED_PUT(conn->dst.sin.sin_port, &th->th_dport); in tcp_header_add()
1357 if (conn->send_options.mss_found) { in tcp_header_add()
1362 UNALIGNED_PUT(htons(conn->recv_win), &th->th_win); in tcp_header_add()
1366 UNALIGNED_PUT(htonl(conn->ack), &th->th_ack); in tcp_header_add()
1372 static int ip_header_add(struct tcp *conn, struct net_pkt *pkt) in ip_header_add() argument
1375 return net_context_create_ipv4_new(conn->context, pkt, in ip_header_add()
1376 &conn->src.sin.sin_addr, in ip_header_add()
1377 &conn->dst.sin.sin_addr); in ip_header_add()
1381 return net_context_create_ipv6_new(conn->context, pkt, in ip_header_add()
1382 &conn->src.sin6.sin6_addr, in ip_header_add()
1383 &conn->dst.sin6.sin6_addr); in ip_header_add()
1389 static int set_tcp_nodelay(struct tcp *conn, const void *value, size_t len) in set_tcp_nodelay() argument
1403 conn->tcp_nodelay = (bool)no_delay_int; in set_tcp_nodelay()
1408 static int get_tcp_nodelay(struct tcp *conn, void *value, size_t *len) in get_tcp_nodelay() argument
1410 int no_delay_int = (int)conn->tcp_nodelay; in get_tcp_nodelay()
1420 static int net_tcp_set_mss_opt(struct tcp *conn, struct net_pkt *pkt) in net_tcp_set_mss_opt() argument
1431 recv_mss = net_tcp_get_supported_mss(conn); in net_tcp_set_mss_opt()
1540 static int tcp_out_ext(struct tcp *conn, uint8_t flags, struct net_pkt *data, in tcp_out_ext() argument
1547 if (conn->send_options.mss_found) { in tcp_out_ext()
1551 pkt = tcp_pkt_alloc(conn, alloc_len); in tcp_out_ext()
1563 ret = ip_header_add(conn, pkt); in tcp_out_ext()
1569 ret = tcp_header_add(conn, pkt, flags, seq); in tcp_out_ext()
1575 if (conn->send_options.mss_found) { in tcp_out_ext()
1576 ret = net_tcp_set_mss_opt(conn, pkt); in tcp_out_ext()
1594 sys_slist_append(&conn->send_queue, &pkt->next); in tcp_out_ext()
1597 conn->recv_win_sent = conn->recv_win; in tcp_out_ext()
1606 &conn->send_timer, K_NO_WAIT); in tcp_out_ext()
1607 } else if (tcp_send_process_no_lock(conn)) { in tcp_out_ext()
1608 tcp_conn_close(conn, -ETIMEDOUT); in tcp_out_ext()
1614 static void tcp_out(struct tcp *conn, uint8_t flags) in tcp_out() argument
1616 (void)tcp_out_ext(conn, flags, NULL /* no data */, conn->seq); in tcp_out()
1694 static bool tcp_window_full(struct tcp *conn) in tcp_window_full() argument
1696 bool window_full = (conn->send_data_total >= conn->send_win); in tcp_window_full()
1699 window_full = window_full || (conn->send_data_total >= conn->ca.cwnd); in tcp_window_full()
1703 NET_DBG("conn: %p TX window_full", conn); in tcp_window_full()
1709 static int tcp_unsent_len(struct tcp *conn) in tcp_unsent_len() argument
1713 if (conn->unacked_len > conn->send_data_total) { in tcp_unsent_len()
1715 conn->send_data_total, conn->unacked_len); in tcp_unsent_len()
1720 unsent_len = conn->send_data_total - conn->unacked_len; in tcp_unsent_len()
1721 if (conn->unacked_len >= conn->send_win) { in tcp_unsent_len()
1724 unsent_len = MIN(unsent_len, conn->send_win - conn->unacked_len); in tcp_unsent_len()
1727 if (conn->unacked_len >= conn->ca.cwnd) { in tcp_unsent_len()
1730 unsent_len = MIN(unsent_len, conn->ca.cwnd - conn->unacked_len); in tcp_unsent_len()
1738 static int tcp_send_data(struct tcp *conn) in tcp_send_data() argument
1744 len = MIN(tcp_unsent_len(conn), conn_mss(conn)); in tcp_send_data()
1750 NET_DBG("conn: %p no data to send", conn); in tcp_send_data()
1755 pkt = tcp_pkt_alloc(conn, len); in tcp_send_data()
1757 NET_ERR("conn: %p packet allocation failed, len=%d", conn, len); in tcp_send_data()
1762 ret = tcp_pkt_peek(pkt, conn->send_data, conn->unacked_len, len); in tcp_send_data()
1769 ret = tcp_out_ext(conn, PSH | ACK, pkt, conn->seq + conn->unacked_len); in tcp_send_data()
1771 conn->unacked_len += len; in tcp_send_data()
1773 if (conn->data_mode == TCP_DATA_MODE_RESEND) { in tcp_send_data()
1774 net_stats_update_tcp_resent(conn->iface, len); in tcp_send_data()
1775 net_stats_update_tcp_seg_rexmit(conn->iface); in tcp_send_data()
1777 net_stats_update_tcp_sent(conn->iface, len); in tcp_send_data()
1778 net_stats_update_tcp_seg_sent(conn->iface); in tcp_send_data()
1788 conn_send_data_dump(conn); in tcp_send_data()
1796 static int tcp_send_queued_data(struct tcp *conn) in tcp_send_queued_data() argument
1801 if (conn->data_mode == TCP_DATA_MODE_RESEND) { in tcp_send_queued_data()
1805 while (tcp_unsent_len(conn) > 0) { in tcp_send_queued_data()
1807 if ((conn->tcp_nodelay == false) && (conn->unacked_len > 0)) { in tcp_send_queued_data()
1809 if (tcp_unsent_len(conn) < conn_mss(conn)) { in tcp_send_queued_data()
1819 ret = tcp_send_data(conn); in tcp_send_queued_data()
1825 if (conn->send_data_total) { in tcp_send_queued_data()
1829 if (k_work_delayable_remaining_get(&conn->send_data_timer)) { in tcp_send_queued_data()
1834 conn->send_data_retries = 0; in tcp_send_queued_data()
1835 k_work_reschedule_for_queue(&tcp_work_q, &conn->send_data_timer, in tcp_send_queued_data()
1845 struct tcp *conn = CONTAINER_OF(dwork, struct tcp, recv_queue_timer); in tcp_cleanup_recv_queue() local
1847 k_mutex_lock(&conn->lock, K_FOREVER); in tcp_cleanup_recv_queue()
1849 NET_DBG("Cleanup recv queue conn %p len %zd seq %u", conn, in tcp_cleanup_recv_queue()
1850 net_pkt_get_len(conn->queue_recv_data), in tcp_cleanup_recv_queue()
1851 tcp_get_seq(conn->queue_recv_data->buffer)); in tcp_cleanup_recv_queue()
1853 net_buf_unref(conn->queue_recv_data->buffer); in tcp_cleanup_recv_queue()
1854 conn->queue_recv_data->buffer = NULL; in tcp_cleanup_recv_queue()
1856 k_mutex_unlock(&conn->lock); in tcp_cleanup_recv_queue()
1862 struct tcp *conn = CONTAINER_OF(dwork, struct tcp, send_data_timer); in tcp_resend_data() local
1867 k_mutex_lock(&conn->lock, K_FOREVER); in tcp_resend_data()
1869 NET_DBG("send_data_retries=%hu", conn->send_data_retries); in tcp_resend_data()
1871 if (conn->send_data_retries >= tcp_retries) { in tcp_resend_data()
1872 NET_DBG("conn: %p close, data retransmissions exceeded", conn); in tcp_resend_data()
1878 (conn->send_data_retries == 0)) { in tcp_resend_data()
1879 tcp_ca_timeout(conn); in tcp_resend_data()
1880 if (tcp_window_full(conn)) { in tcp_resend_data()
1881 (void)k_sem_take(&conn->tx_sem, K_NO_WAIT); in tcp_resend_data()
1885 conn->data_mode = TCP_DATA_MODE_RESEND; in tcp_resend_data()
1886 conn->unacked_len = 0; in tcp_resend_data()
1888 ret = tcp_send_data(conn); in tcp_resend_data()
1889 conn->send_data_retries++; in tcp_resend_data()
1891 if (conn->in_close && conn->send_data_total == 0) { in tcp_resend_data()
1896 &conn->fin_timer, in tcp_resend_data()
1899 conn_state(conn, TCP_FIN_WAIT_1); in tcp_resend_data()
1901 ret = tcp_out_ext(conn, FIN | ACK, NULL, in tcp_resend_data()
1902 conn->seq + conn->unacked_len); in tcp_resend_data()
1904 conn_seq(conn, + 1); in tcp_resend_data()
1907 keep_alive_timer_stop(conn); in tcp_resend_data()
1912 conn->data_mode = TCP_DATA_MODE_SEND; in tcp_resend_data()
1921 if (conn->send_data_retries < tcp_retries) { in tcp_resend_data()
1923 for (int i = 0; i < conn->send_data_retries; i++) { in tcp_resend_data()
1928 k_work_reschedule_for_queue(&tcp_work_q, &conn->send_data_timer, in tcp_resend_data()
1932 k_mutex_unlock(&conn->lock); in tcp_resend_data()
1935 tcp_conn_close(conn, -ETIMEDOUT); in tcp_resend_data()
1942 struct tcp *conn = CONTAINER_OF(dwork, struct tcp, timewait_timer); in tcp_timewait_timeout() local
1944 /* no need to acquire the conn->lock as there is nothing scheduled here */ in tcp_timewait_timeout()
1945 NET_DBG("conn: %p %s", conn, tcp_conn_state(conn, NULL)); in tcp_timewait_timeout()
1947 (void)tcp_conn_close(conn, -ETIMEDOUT); in tcp_timewait_timeout()
1950 static void tcp_establish_timeout(struct tcp *conn) in tcp_establish_timeout() argument
1953 NET_DBG("conn: %p %s", conn, tcp_conn_state(conn, NULL)); in tcp_establish_timeout()
1955 (void)tcp_conn_close(conn, -ETIMEDOUT); in tcp_establish_timeout()
1961 struct tcp *conn = CONTAINER_OF(dwork, struct tcp, fin_timer); in tcp_fin_timeout() local
1963 /* no need to acquire the conn->lock as there is nothing scheduled here */ in tcp_fin_timeout()
1964 if (conn->state == TCP_SYN_RECEIVED) { in tcp_fin_timeout()
1965 tcp_establish_timeout(conn); in tcp_fin_timeout()
1970 NET_DBG("conn: %p %s", conn, tcp_conn_state(conn, NULL)); in tcp_fin_timeout()
1972 (void)tcp_conn_close(conn, -ETIMEDOUT); in tcp_fin_timeout()
1978 struct tcp *conn = CONTAINER_OF(dwork, struct tcp, fin_timer); in tcp_last_ack_timeout() local
1981 NET_DBG("conn: %p %s", conn, tcp_conn_state(conn, NULL)); in tcp_last_ack_timeout()
1983 (void)tcp_conn_close(conn, -ETIMEDOUT); in tcp_last_ack_timeout()
1986 static void tcp_setup_last_ack_timer(struct tcp *conn) in tcp_setup_last_ack_timer() argument
1994 k_work_init_delayable(&conn->fin_timer, tcp_last_ack_timeout); in tcp_setup_last_ack_timer()
2000 &conn->fin_timer, in tcp_setup_last_ack_timer()
2004 static void tcp_cancel_last_ack_timer(struct tcp *conn) in tcp_cancel_last_ack_timer() argument
2006 k_work_cancel_delayable(&conn->fin_timer); in tcp_cancel_last_ack_timer()
2013 struct tcp *conn = CONTAINER_OF(dwork, struct tcp, keepalive_timer); in tcp_send_keepalive_probe() local
2015 if (conn->state != TCP_ESTABLISHED) { in tcp_send_keepalive_probe()
2016 NET_DBG("conn: %p TCP connection not established", conn); in tcp_send_keepalive_probe()
2020 if (!conn->keep_alive) { in tcp_send_keepalive_probe()
2021 NET_DBG("conn: %p keepalive is not enabled", conn); in tcp_send_keepalive_probe()
2025 conn->keep_cur++; in tcp_send_keepalive_probe()
2026 if (conn->keep_cur > conn->keep_cnt) { in tcp_send_keepalive_probe()
2027 NET_DBG("conn: %p keepalive probe failed multiple times", in tcp_send_keepalive_probe()
2028 conn); in tcp_send_keepalive_probe()
2029 tcp_conn_close(conn, -ETIMEDOUT); in tcp_send_keepalive_probe()
2033 NET_DBG("conn: %p keepalive probe", conn); in tcp_send_keepalive_probe()
2034 k_work_reschedule_for_queue(&tcp_work_q, &conn->keepalive_timer, in tcp_send_keepalive_probe()
2035 K_SECONDS(conn->keep_intvl)); in tcp_send_keepalive_probe()
2038 (void)tcp_out_ext(conn, ACK, NULL, conn->seq - 1); in tcp_send_keepalive_probe()
2045 struct tcp *conn = CONTAINER_OF(dwork, struct tcp, persist_timer); in tcp_send_zwp() local
2047 k_mutex_lock(&conn->lock, K_FOREVER); in tcp_send_zwp()
2049 (void)tcp_out_ext(conn, ACK, NULL, conn->seq - 1); in tcp_send_zwp()
2051 tcp_derive_rto(conn); in tcp_send_zwp()
2053 if (conn->send_win == 0) { in tcp_send_zwp()
2057 if (conn->zwp_retries < 63) { in tcp_send_zwp()
2058 conn->zwp_retries++; in tcp_send_zwp()
2061 timeout <<= conn->zwp_retries; in tcp_send_zwp()
2067 &tcp_work_q, &conn->persist_timer, K_MSEC(timeout)); in tcp_send_zwp()
2070 k_mutex_unlock(&conn->lock); in tcp_send_zwp()
2076 struct tcp *conn = CONTAINER_OF(dwork, struct tcp, ack_timer); in tcp_send_ack() local
2078 k_mutex_lock(&conn->lock, K_FOREVER); in tcp_send_ack()
2080 tcp_out(conn, ACK); in tcp_send_ack()
2082 k_mutex_unlock(&conn->lock); in tcp_send_ack()
2085 static void tcp_conn_ref(struct tcp *conn) in tcp_conn_ref() argument
2087 int ref_count = atomic_inc(&conn->ref_count) + 1; in tcp_conn_ref()
2089 NET_DBG("conn: %p, ref_count: %d", conn, ref_count); in tcp_conn_ref()
2094 struct tcp *conn = NULL; in tcp_conn_alloc() local
2097 ret = k_mem_slab_alloc(&tcp_conns_slab, (void **)&conn, K_NO_WAIT); in tcp_conn_alloc()
2103 memset(conn, 0, sizeof(*conn)); in tcp_conn_alloc()
2106 conn->queue_recv_data = tcp_rx_pkt_alloc(conn, 0); in tcp_conn_alloc()
2107 if (conn->queue_recv_data == NULL) { in tcp_conn_alloc()
2108 NET_ERR("Cannot allocate %s queue for conn %p", "recv", in tcp_conn_alloc()
2109 conn); in tcp_conn_alloc()
2114 conn->send_data = tcp_pkt_alloc(conn, 0); in tcp_conn_alloc()
2115 if (conn->send_data == NULL) { in tcp_conn_alloc()
2116 NET_ERR("Cannot allocate %s queue for conn %p", "send", conn); in tcp_conn_alloc()
2120 k_mutex_init(&conn->lock); in tcp_conn_alloc()
2121 k_fifo_init(&conn->recv_data); in tcp_conn_alloc()
2122 k_sem_init(&conn->connect_sem, 0, K_SEM_MAX_LIMIT); in tcp_conn_alloc()
2123 k_sem_init(&conn->tx_sem, 1, 1); in tcp_conn_alloc()
2125 conn->in_connect = false; in tcp_conn_alloc()
2126 conn->state = TCP_LISTEN; in tcp_conn_alloc()
2127 conn->recv_win_max = tcp_rx_window; in tcp_conn_alloc()
2128 conn->recv_win = conn->recv_win_max; in tcp_conn_alloc()
2129 conn->recv_win_sent = conn->recv_win_max; in tcp_conn_alloc()
2130 conn->send_win_max = MAX(tcp_tx_window, NET_IPV6_MTU); in tcp_conn_alloc()
2131 conn->send_win = conn->send_win_max; in tcp_conn_alloc()
2132 conn->tcp_nodelay = false; in tcp_conn_alloc()
2133 conn->addr_ref_done = false; in tcp_conn_alloc()
2135 conn->dup_ack_cnt = 0; in tcp_conn_alloc()
2141 conn->ca.cwnd = UINT16_MAX; in tcp_conn_alloc()
2147 conn->seq = 0U; in tcp_conn_alloc()
2149 sys_slist_init(&conn->send_queue); in tcp_conn_alloc()
2151 k_work_init_delayable(&conn->send_timer, tcp_send_process); in tcp_conn_alloc()
2152 k_work_init_delayable(&conn->timewait_timer, tcp_timewait_timeout); in tcp_conn_alloc()
2153 k_work_init_delayable(&conn->fin_timer, tcp_fin_timeout); in tcp_conn_alloc()
2154 k_work_init_delayable(&conn->send_data_timer, tcp_resend_data); in tcp_conn_alloc()
2155 k_work_init_delayable(&conn->recv_queue_timer, tcp_cleanup_recv_queue); in tcp_conn_alloc()
2156 k_work_init_delayable(&conn->persist_timer, tcp_send_zwp); in tcp_conn_alloc()
2157 k_work_init_delayable(&conn->ack_timer, tcp_send_ack); in tcp_conn_alloc()
2158 k_work_init(&conn->conn_release, tcp_conn_release); in tcp_conn_alloc()
2159 keep_alive_timer_init(conn); in tcp_conn_alloc()
2161 tcp_conn_ref(conn); in tcp_conn_alloc()
2164 sys_slist_append(&tcp_conns, &conn->next); in tcp_conn_alloc()
2167 NET_DBG("conn: %p", conn); in tcp_conn_alloc()
2169 return conn; in tcp_conn_alloc()
2172 if (CONFIG_NET_TCP_RECV_QUEUE_TIMEOUT && conn->queue_recv_data) { in tcp_conn_alloc()
2173 tcp_pkt_unref(conn->queue_recv_data); in tcp_conn_alloc()
2174 conn->queue_recv_data = NULL; in tcp_conn_alloc()
2177 k_mem_slab_free(&tcp_conns_slab, (void *)conn); in tcp_conn_alloc()
2184 struct tcp *conn; in net_tcp_get() local
2186 conn = tcp_conn_alloc(); in net_tcp_get()
2187 if (conn == NULL) { in net_tcp_get()
2193 conn->context = context; in net_tcp_get()
2194 context->tcp = conn; in net_tcp_get()
2211 static bool tcp_conn_cmp(struct tcp *conn, struct net_pkt *pkt) in tcp_conn_cmp() argument
2213 return tcp_endpoint_cmp(&conn->src, pkt, TCP_EP_DST) && in tcp_conn_cmp()
2214 tcp_endpoint_cmp(&conn->dst, pkt, TCP_EP_SRC); in tcp_conn_cmp()
2220 struct tcp *conn; in tcp_conn_search() local
2225 SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&tcp_conns, conn, tmp, next) { in tcp_conn_search()
2226 found = tcp_conn_cmp(conn, pkt); in tcp_conn_search()
2234 return found ? conn : NULL; in tcp_conn_search()
2245 struct tcp *conn; in tcp_recv() local
2252 conn = tcp_conn_search(pkt); in tcp_recv()
2253 if (conn) { in tcp_recv()
2262 conn = tcp_conn_new(pkt); in tcp_recv()
2263 if (!conn) { in tcp_recv()
2268 conn->accepted_conn = conn_old; in tcp_recv()
2271 if (conn) { in tcp_recv()
2272 verdict = tcp_in(conn, pkt); in tcp_recv()
2393 struct tcp *conn = NULL; in tcp_conn_new() local
2405 conn = context->tcp; in tcp_conn_new()
2406 conn->iface = pkt->iface; in tcp_conn_new()
2407 tcp_derive_rto(conn); in tcp_conn_new()
2409 net_context_set_family(conn->context, net_pkt_family(pkt)); in tcp_conn_new()
2411 if (tcp_endpoint_set(&conn->dst, pkt, TCP_EP_SRC) < 0) { in tcp_conn_new()
2413 conn = NULL; in tcp_conn_new()
2417 if (tcp_endpoint_set(&conn->src, pkt, TCP_EP_DST) < 0) { in tcp_conn_new()
2419 conn = NULL; in tcp_conn_new()
2423 NET_DBG("conn: src: %s, dst: %s", in tcp_conn_new()
2424 net_sprint_addr(conn->src.sa.sa_family, in tcp_conn_new()
2425 (const void *)&conn->src.sin.sin_addr), in tcp_conn_new()
2426 net_sprint_addr(conn->dst.sa.sa_family, in tcp_conn_new()
2427 (const void *)&conn->dst.sin.sin_addr)); in tcp_conn_new()
2429 memcpy(&context->remote, &conn->dst, sizeof(context->remote)); in tcp_conn_new()
2439 &conn->src.sin6.sin6_addr); in tcp_conn_new()
2443 &conn->src.sin.sin_addr); in tcp_conn_new()
2450 conn = NULL; in tcp_conn_new()
2457 * are already copied above from conn->dst. The call to net_context_bind in tcp_conn_new()
2468 net_sin6_ptr(&context->local)->sin6_port = conn->src.sin6.sin6_port; in tcp_conn_new()
2471 net_sin_ptr(&context->local)->sin_port = conn->src.sin.sin_port; in tcp_conn_new()
2476 conn->seq = tcp_init_isn(&local_addr, &context->remote); in tcp_conn_new()
2487 ntohs(conn->dst.sin.sin_port),/* local port */ in tcp_conn_new()
2488 ntohs(conn->src.sin.sin_port),/* remote port */ in tcp_conn_new()
2494 conn = NULL; in tcp_conn_new()
2498 net_if_addr_ref(conn->iface, conn->dst.sa.sa_family, in tcp_conn_new()
2499 conn->src.sa.sa_family == AF_INET ? in tcp_conn_new()
2500 (const void *)&conn->src.sin.sin_addr : in tcp_conn_new()
2501 (const void *)&conn->src.sin6.sin6_addr); in tcp_conn_new()
2502 conn->addr_ref_done = true; in tcp_conn_new()
2505 if (!conn) { in tcp_conn_new()
2509 return conn; in tcp_conn_new()
2512 static bool tcp_validate_seq(struct tcp *conn, struct tcphdr *hdr) in tcp_validate_seq() argument
2514 return (net_tcp_seq_cmp(th_seq(hdr), conn->ack) >= 0) && in tcp_validate_seq()
2515 (net_tcp_seq_cmp(th_seq(hdr), conn->ack + conn->recv_win) < 0); in tcp_validate_seq()
2518 static int32_t tcp_compute_new_length(struct tcp *conn, struct tcphdr *hdr, size_t len, in tcp_compute_new_length() argument
2530 new_len = (int32_t)(len) - net_tcp_seq_cmp(conn->ack, th_seq(hdr)); in tcp_compute_new_length()
2539 static enum tcp_state tcp_enter_time_wait(struct tcp *conn) in tcp_enter_time_wait() argument
2541 tcp_send_timer_cancel(conn); in tcp_enter_time_wait()
2543 k_work_cancel_delayable(&conn->fin_timer); in tcp_enter_time_wait()
2545 &tcp_work_q, &conn->timewait_timer, in tcp_enter_time_wait()
2576 static void tcp_queue_recv_data(struct tcp *conn, struct net_pkt *pkt, in tcp_queue_recv_data() argument
2583 NET_DBG("conn: %p len %zd seq %u ack %u", conn, len, seq, conn->ack); in tcp_queue_recv_data()
2598 NET_DBG("Queuing data: conn %p", conn); in tcp_queue_recv_data()
2601 if (!net_pkt_is_empty(conn->queue_recv_data)) { in tcp_queue_recv_data()
2631 pending_seq = tcp_get_seq(conn->queue_recv_data->buffer); in tcp_queue_recv_data()
2633 pending_len = net_pkt_get_len(conn->queue_recv_data); in tcp_queue_recv_data()
2642 conn->queue_recv_data->buffer); in tcp_queue_recv_data()
2645 conn->queue_recv_data->buffer = pkt->buffer; in tcp_queue_recv_data()
2651 last = net_buf_frag_last(conn->queue_recv_data->buffer); in tcp_queue_recv_data()
2663 net_buf_unref(conn->queue_recv_data->buffer); in tcp_queue_recv_data()
2664 conn->queue_recv_data->buffer = pkt->buffer; in tcp_queue_recv_data()
2669 net_pkt_remove_tail(conn->queue_recv_data, in tcp_queue_recv_data()
2676 net_buf_frag_add(conn->queue_recv_data->buffer, in tcp_queue_recv_data()
2684 NET_DBG("All pending data: conn %p", conn); in tcp_queue_recv_data()
2685 if (check_seq_list(conn->queue_recv_data->buffer) == false) { in tcp_queue_recv_data()
2686 NET_ERR("Incorrect order in out of order sequence for conn %p", in tcp_queue_recv_data()
2687 conn); in tcp_queue_recv_data()
2689 net_buf_unref(conn->queue_recv_data->buffer); in tcp_queue_recv_data()
2690 conn->queue_recv_data->buffer = NULL; in tcp_queue_recv_data()
2696 net_pkt_append_buffer(conn->queue_recv_data, pkt->buffer); in tcp_queue_recv_data()
2704 if (!k_work_delayable_is_pending(&conn->recv_queue_timer)) { in tcp_queue_recv_data()
2706 &tcp_work_q, &conn->recv_queue_timer, in tcp_queue_recv_data()
2712 static enum net_verdict tcp_data_received(struct tcp *conn, struct net_pkt *pkt, in tcp_data_received() argument
2721 ret = tcp_data_get(conn, pkt, len); in tcp_data_received()
2723 net_stats_update_tcp_seg_recv(conn->iface); in tcp_data_received()
2724 conn_ack(conn, *len); in tcp_data_received()
2729 if (tcp_short_window(conn) || !psh) { in tcp_data_received()
2730 k_work_schedule_for_queue(&tcp_work_q, &conn->ack_timer, in tcp_data_received()
2733 k_work_cancel_delayable(&conn->ack_timer); in tcp_data_received()
2734 tcp_out(conn, ACK); in tcp_data_received()
2740 static void tcp_out_of_order_data(struct tcp *conn, struct net_pkt *pkt, in tcp_out_of_order_data() argument
2758 tcp_queue_recv_data(conn, pkt, data_len, seq); in tcp_out_of_order_data()
2761 static void tcp_check_sock_options(struct tcp *conn) in tcp_check_sock_options() argument
2767 (void)net_context_get_option(conn->context, NET_OPT_SNDBUF, in tcp_check_sock_options()
2772 (void)net_context_get_option(conn->context, NET_OPT_RCVBUF, in tcp_check_sock_options()
2776 if (sndbuf_opt > 0 && sndbuf_opt != conn->send_win_max) { in tcp_check_sock_options()
2777 k_mutex_lock(&conn->lock, K_FOREVER); in tcp_check_sock_options()
2779 conn->send_win_max = sndbuf_opt; in tcp_check_sock_options()
2780 if (conn->send_win > conn->send_win_max) { in tcp_check_sock_options()
2781 conn->send_win = conn->send_win_max; in tcp_check_sock_options()
2784 k_mutex_unlock(&conn->lock); in tcp_check_sock_options()
2787 if (rcvbuf_opt > 0 && rcvbuf_opt != conn->recv_win_max) { in tcp_check_sock_options()
2790 k_mutex_lock(&conn->lock, K_FOREVER); in tcp_check_sock_options()
2792 diff = rcvbuf_opt - conn->recv_win_max; in tcp_check_sock_options()
2793 conn->recv_win_max = rcvbuf_opt; in tcp_check_sock_options()
2794 tcp_update_recv_wnd(conn, diff); in tcp_check_sock_options()
2796 k_mutex_unlock(&conn->lock); in tcp_check_sock_options()
2801 static enum net_verdict tcp_in(struct tcp *conn, struct net_pkt *pkt) in tcp_in() argument
2822 if (conn->state != TCP_SYN_SENT) { in tcp_in()
2823 tcp_check_sock_options(conn); in tcp_in()
2826 k_mutex_lock(&conn->lock, K_FOREVER); in tcp_in()
2829 if (conn->state == TCP_UNUSED) { in tcp_in()
2830 k_mutex_unlock(&conn->lock); in tcp_in()
2834 NET_DBG("%s", tcp_conn_state(conn, pkt)); in tcp_in()
2837 tcp_out(conn, RST); in tcp_in()
2845 if (!tcp_validate_seq(conn, th)) { in tcp_in()
2847 k_mutex_unlock(&conn->lock); in tcp_in()
2861 if (conn->in_connect) { in tcp_in()
2871 if (tcp_options_len && !tcp_options_check(&conn->recv_options, pkt, in tcp_in()
2874 tcp_out(conn, RST); in tcp_in()
2880 if (th && (conn->state != TCP_LISTEN) && (conn->state != TCP_SYN_SENT) && in tcp_in()
2881 tcp_validate_seq(conn, th) && FL(&fl, &, SYN)) { in tcp_in()
2886 NET_DBG("conn: %p, SYN received in %s state, dropping connection", in tcp_in()
2887 conn, tcp_state_to_str(conn->state, false)); in tcp_in()
2888 net_stats_update_tcp_seg_drop(conn->iface); in tcp_in()
2889 tcp_out(conn, RST); in tcp_in()
2896 conn->send_win = ntohs(th_win(th)); in tcp_in()
2897 if (conn->send_win > conn->send_win_max) { in tcp_in()
2899 conn->send_win, conn->send_win_max); in tcp_in()
2901 conn->send_win = conn->send_win_max; in tcp_in()
2904 if (conn->send_win == 0) { in tcp_in()
2905 if (!k_work_delayable_is_pending(&conn->persist_timer)) { in tcp_in()
2906 conn->zwp_retries = 0; in tcp_in()
2908 &tcp_work_q, &conn->persist_timer, in tcp_in()
2912 (void)k_work_cancel_delayable(&conn->persist_timer); in tcp_in()
2915 if (tcp_window_full(conn)) { in tcp_in()
2916 (void)k_sem_take(&conn->tx_sem, K_NO_WAIT); in tcp_in()
2918 k_sem_give(&conn->tx_sem); in tcp_in()
2925 switch (conn->state) { in tcp_in()
2929 conn->send_options.mss_found = true; in tcp_in()
2930 conn_ack(conn, th_seq(th) + 1); /* capture peer's isn */ in tcp_in()
2931 tcp_out(conn, SYN | ACK); in tcp_in()
2932 conn->send_options.mss_found = false; in tcp_in()
2933 conn_seq(conn, + 1); in tcp_in()
2939 &conn->establish_timer, in tcp_in()
2943 conn->send_options.mss_found = true; in tcp_in()
2944 ret = tcp_out_ext(conn, SYN, NULL /* no data */, conn->seq); in tcp_in()
2949 conn->send_options.mss_found = false; in tcp_in()
2950 conn_seq(conn, + 1); in tcp_in()
2952 tcp_conn_ref(conn); in tcp_in()
2957 if (FL(&fl, &, ACK, th_ack(th) == conn->seq && in tcp_in()
2958 th_seq(th) == conn->ack)) { in tcp_in()
2962 if (conn->accepted_conn != NULL) { in tcp_in()
2963 accept_cb = conn->accepted_conn->accept_cb; in tcp_in()
2964 context = conn->accepted_conn->context; in tcp_in()
2965 keep_alive_param_copy(conn, conn->accepted_conn); in tcp_in()
2968 k_work_cancel_delayable(&conn->establish_timer); in tcp_in()
2969 tcp_send_timer_cancel(conn); in tcp_in()
2970 tcp_conn_ref(conn); in tcp_in()
2971 net_context_set_state(conn->context, in tcp_in()
2975 conn->accepted_conn = NULL; in tcp_in()
2984 net_tcp_put(conn->context); in tcp_in()
2988 keep_alive_timer_restart(conn); in tcp_in()
2990 net_ipaddr_copy(&conn->context->remote, &conn->dst.sa); in tcp_in()
2996 net_context_get_family(conn->context) == AF_INET && in tcp_in()
3002 &net_sin(&conn->context->remote)->sin_addr, in tcp_in()
3004 net_ipaddr_copy(&net_sin6(&conn->context->remote)->sin6_addr, in tcp_in()
3007 net_sin6(&conn->context->remote)->sin6_family = AF_INET6; in tcp_in()
3015 * passing it to accept() and printing it by "net conn" in tcp_in()
3020 accept_cb(conn->context, &conn->context->remote, in tcp_in()
3027 tcp_ca_init(conn); in tcp_in()
3030 verdict = tcp_data_get(conn, pkt, &len); in tcp_in()
3036 conn_ack(conn, + len); in tcp_in()
3037 tcp_out(conn, ACK); in tcp_in()
3045 tcp_nbr_reachability_hint(conn); in tcp_in()
3053 if (FL(&fl, &, SYN | ACK, th && th_ack(th) == conn->seq)) { in tcp_in()
3054 tcp_send_timer_cancel(conn); in tcp_in()
3055 conn_ack(conn, th_seq(th) + 1); in tcp_in()
3057 verdict = tcp_data_get(conn, pkt, &len); in tcp_in()
3063 conn_ack(conn, + len); in tcp_in()
3069 net_context_set_state(conn->context, in tcp_in()
3071 tcp_ca_init(conn); in tcp_in()
3072 tcp_out(conn, ACK); in tcp_in()
3073 keep_alive_timer_restart(conn); in tcp_in()
3086 tcp_nbr_reachability_hint(conn); in tcp_in()
3094 if (th && FL(&fl, &, FIN, th_seq(th) == conn->ack)) { in tcp_in()
3098 verdict = tcp_data_get(conn, pkt, &len); in tcp_in()
3107 conn_ack(conn, + len + 1); in tcp_in()
3108 keep_alive_timer_stop(conn); in tcp_in()
3113 if (net_tcp_seq_cmp(th_ack(th), conn->seq) > 0) { in tcp_in()
3114 uint32_t len_acked = th_ack(th) - conn->seq; in tcp_in()
3116 conn_seq(conn, + len_acked); in tcp_in()
3121 tcp_out(conn, FIN | ACK); in tcp_in()
3122 conn_seq(conn, + 1); in tcp_in()
3123 tcp_setup_last_ack_timer(conn); in tcp_in()
3126 tcp_out(conn, ACK); in tcp_in()
3136 keep_alive_timer_restart(conn); in tcp_in()
3139 if (th && (net_tcp_seq_cmp(th_ack(th), conn->seq) == 0)) { in tcp_in()
3141 if (conn->send_data_total > 0) { in tcp_in()
3147 conn->dup_ack_cnt = MIN(conn->dup_ack_cnt + 1, in tcp_in()
3149 tcp_ca_dup_ack(conn); in tcp_in()
3152 conn->dup_ack_cnt = 0; in tcp_in()
3156 if ((conn->data_mode == TCP_DATA_MODE_SEND) && in tcp_in()
3157 (conn->dup_ack_cnt == DUPLICATE_ACK_RETRANSMIT_TRHESHOLD)) { in tcp_in()
3159 int temp_unacked_len = conn->unacked_len; in tcp_in()
3161 conn->unacked_len = 0; in tcp_in()
3163 (void)tcp_send_data(conn); in tcp_in()
3166 conn->unacked_len = temp_unacked_len; in tcp_in()
3168 tcp_ca_fast_retransmit(conn); in tcp_in()
3169 if (tcp_window_full(conn)) { in tcp_in()
3170 (void)k_sem_take(&conn->tx_sem, K_NO_WAIT); in tcp_in()
3175 NET_ASSERT((conn->send_data_total == 0) || in tcp_in()
3176 k_work_delayable_is_pending(&conn->send_data_timer), in tcp_in()
3177 "conn: %p, Missing a subscription " in tcp_in()
3178 "of the send_data queue timer", conn); in tcp_in()
3180 if (th && (net_tcp_seq_cmp(th_ack(th), conn->seq) > 0)) { in tcp_in()
3181 uint32_t len_acked = th_ack(th) - conn->seq; in tcp_in()
3183 NET_DBG("conn: %p len_acked=%u", conn, len_acked); in tcp_in()
3185 if ((conn->send_data_total < len_acked) || in tcp_in()
3186 (tcp_pkt_pull(conn->send_data, in tcp_in()
3188 NET_ERR("conn: %p, Invalid len_acked=%u " in tcp_in()
3189 "(total=%zu)", conn, len_acked, in tcp_in()
3190 conn->send_data_total); in tcp_in()
3191 net_stats_update_tcp_seg_drop(conn->iface); in tcp_in()
3192 tcp_out(conn, RST); in tcp_in()
3200 conn->dup_ack_cnt = 0; in tcp_in()
3202 tcp_ca_pkts_acked(conn, len_acked); in tcp_in()
3204 conn->send_data_total -= len_acked; in tcp_in()
3205 if (conn->unacked_len < len_acked) { in tcp_in()
3206 conn->unacked_len = 0; in tcp_in()
3208 conn->unacked_len -= len_acked; in tcp_in()
3211 if (!tcp_window_full(conn)) { in tcp_in()
3212 k_sem_give(&conn->tx_sem); in tcp_in()
3215 conn_seq(conn, + len_acked); in tcp_in()
3216 net_stats_update_tcp_seg_recv(conn->iface); in tcp_in()
3222 tcp_nbr_reachability_hint(conn); in tcp_in()
3224 conn_send_data_dump(conn); in tcp_in()
3226 conn->send_data_retries = 0; in tcp_in()
3227 if (conn->data_mode == TCP_DATA_MODE_RESEND) { in tcp_in()
3228 conn->unacked_len = 0; in tcp_in()
3229 tcp_derive_rto(conn); in tcp_in()
3231 conn->data_mode = TCP_DATA_MODE_SEND; in tcp_in()
3232 if (conn->send_data_total > 0) { in tcp_in()
3233 k_work_reschedule_for_queue(&tcp_work_q, &conn->send_data_timer, in tcp_in()
3238 if (conn->in_close && conn->send_data_total == 0) { in tcp_in()
3239 tcp_send_timer_cancel(conn); in tcp_in()
3243 &conn->fin_timer, in tcp_in()
3246 tcp_out(conn, FIN | ACK); in tcp_in()
3247 conn_seq(conn, + 1); in tcp_in()
3249 keep_alive_timer_stop(conn); in tcp_in()
3253 ret = tcp_send_queued_data(conn); in tcp_in()
3255 tcp_out(conn, RST); in tcp_in()
3262 if (tcp_window_full(conn)) { in tcp_in()
3263 (void)k_sem_take(&conn->tx_sem, K_NO_WAIT); in tcp_in()
3268 if (th_seq(th) == conn->ack) { in tcp_in()
3272 verdict = tcp_data_received(conn, pkt, &len, psh); in tcp_in()
3281 } else if (net_tcp_seq_greater(conn->ack, th_seq(th))) { in tcp_in()
3289 tcp_out(conn, ACK); /* peer has resent */ in tcp_in()
3291 net_stats_update_tcp_seg_ackerr(conn->iface); in tcp_in()
3294 tcp_out_of_order_data(conn, pkt, len, in tcp_in()
3298 tcp_out(conn, ACK); in tcp_in()
3306 if (conn->send_data_total == 0) { in tcp_in()
3307 conn->send_data_retries = 0; in tcp_in()
3308 k_work_cancel_delayable(&conn->send_data_timer); in tcp_in()
3312 if (tcp_window_full(conn)) { in tcp_in()
3313 (void)k_sem_take(&conn->tx_sem, K_NO_WAIT); in tcp_in()
3315 k_sem_give(&conn->tx_sem); in tcp_in()
3320 tcp_out(conn, FIN); in tcp_in()
3321 conn_seq(conn, + 1); in tcp_in()
3323 tcp_setup_last_ack_timer(conn); in tcp_in()
3326 if (th && FL(&fl, ==, ACK, th_ack(th) == conn->seq)) { in tcp_in()
3327 tcp_send_timer_cancel(conn); in tcp_in()
3333 tcp_cancel_last_ack_timer(conn); in tcp_in()
3351 if (tcp_compute_new_length(conn, th, len, false) > 0) { in tcp_in()
3356 net_stats_update_tcp_seg_drop(conn->iface); in tcp_in()
3358 next = tcp_enter_time_wait(conn); in tcp_in()
3360 tcp_out(conn, RST); in tcp_in()
3363 if (FL(&fl, &, ACK, th_ack(th) == conn->seq)) { in tcp_in()
3364 NET_DBG("conn %p: FIN acknowledged, going to FIN_WAIT_2 " in tcp_in()
3366 , conn, conn->seq, conn->ack); in tcp_in()
3367 tcp_send_timer_cancel(conn); in tcp_in()
3377 if (FL(&fl, &, FIN, net_tcp_seq_cmp(th_seq(th) + len, conn->ack) == 0)) { in tcp_in()
3378 conn_ack(conn, + 1); in tcp_in()
3383 NET_DBG("conn %p: FIN received, going to TIME WAIT", conn); in tcp_in()
3385 next = tcp_enter_time_wait(conn); in tcp_in()
3387 tcp_out(conn, ACK); in tcp_in()
3391 NET_DBG("conn %p: FIN received, going to CLOSING as no " in tcp_in()
3392 "ACK has been received", conn); in tcp_in()
3393 tcp_send_timer_cancel(conn); in tcp_in()
3394 tcp_out_ext(conn, FIN | ACK, NULL, conn->seq - 1); in tcp_in()
3402 tcp_send_timer_cancel(conn); in tcp_in()
3403 tcp_out(conn, ACK); in tcp_in()
3409 tcp_send_timer_cancel(conn); in tcp_in()
3410 tcp_out_ext(conn, FIN | ACK, NULL, conn->seq - 1); in tcp_in()
3431 if (tcp_compute_new_length(conn, th, len, false) > 0) { in tcp_in()
3436 net_stats_update_tcp_seg_drop(conn->iface); in tcp_in()
3438 next = tcp_enter_time_wait(conn); in tcp_in()
3440 tcp_out(conn, RST); in tcp_in()
3447 if (FL(&fl, &, FIN, net_tcp_seq_cmp(th_seq(th) + len, conn->ack) == 0)) { in tcp_in()
3448 conn_ack(conn, + 1); in tcp_in()
3449 NET_DBG("conn %p: FIN received, going to TIME WAIT", conn); in tcp_in()
3451 next = tcp_enter_time_wait(conn); in tcp_in()
3454 tcp_out(conn, ACK); in tcp_in()
3458 tcp_out(conn, ACK); in tcp_in()
3474 int32_t new_len = tcp_compute_new_length(conn, th, len, true); in tcp_in()
3480 NET_ERR("conn: %p, new bytes %u during CLOSING state " in tcp_in()
3481 "sending reset", conn, new_len); in tcp_in()
3482 net_stats_update_tcp_seg_drop(conn->iface); in tcp_in()
3484 next = tcp_enter_time_wait(conn); in tcp_in()
3486 tcp_out(conn, RST); in tcp_in()
3490 if (FL(&fl, &, ACK, th_ack(th) == conn->seq)) { in tcp_in()
3491 NET_DBG("conn %p: FIN acknowledged, going to TIME WAIT " in tcp_in()
3493 , conn, conn->seq, conn->ack); in tcp_in()
3495 next = tcp_enter_time_wait(conn); in tcp_in()
3504 * Since the conn->ack was already incremented in TCP_FIN_WAIT_1 in tcp_in()
3508 net_tcp_seq_cmp(th_seq(th) + len + 1, conn->ack) == 0)) || in tcp_in()
3510 tcp_send_timer_cancel(conn); in tcp_in()
3513 tcp_out(conn, ACK); in tcp_in()
3518 tcp_out_ext(conn, FIN | ACK, NULL, conn->seq - 1); in tcp_in()
3526 int32_t new_len = tcp_compute_new_length(conn, th, len, true); in tcp_in()
3537 NET_ERR("conn: %p, new bytes %u during TIME-WAIT state " in tcp_in()
3538 "sending reset", conn, new_len); in tcp_in()
3539 net_stats_update_tcp_seg_drop(conn->iface); in tcp_in()
3541 tcp_out(conn, RST); in tcp_in()
3547 net_tcp_seq_cmp(th_seq(th) + 1, conn->ack) == 0)) || in tcp_in()
3549 tcp_out(conn, ACK); in tcp_in()
3557 tcp_state_to_str(conn->state, true)); in tcp_in()
3571 conn_state(conn, next); in tcp_in()
3575 conn->in_connect = false; in tcp_in()
3576 if (conn->connect_cb) { in tcp_in()
3577 conn->connect_cb(conn->context, 0, conn->context->user_data); in tcp_in()
3580 conn->connect_cb = NULL; in tcp_in()
3583 k_sem_give(&conn->connect_sem); in tcp_in()
3589 if (conn->context) { in tcp_in()
3590 /* If the conn->context is not set, then the connection was in tcp_in()
3593 conn_handler = (struct net_conn *)conn->context->conn_handler; in tcp_in()
3596 recv_user_data = conn->recv_user_data; in tcp_in()
3597 recv_data_fifo = &conn->recv_data; in tcp_in()
3599 k_mutex_unlock(&conn->lock); in tcp_in()
3605 while (conn_handler && atomic_get(&conn->ref_count) > 0 && in tcp_in()
3618 if (do_close && conn->state != TCP_UNUSED && conn->state != TCP_CLOSED) { in tcp_in()
3619 tcp_conn_close(conn, close_status); in tcp_in()
3628 struct tcp *conn = context->tcp; in net_tcp_put() local
3630 if (!conn) { in net_tcp_put()
3634 k_mutex_lock(&conn->lock, K_FOREVER); in net_tcp_put()
3636 NET_DBG("%s", conn ? tcp_conn_state(conn, NULL) : ""); in net_tcp_put()
3641 if (conn->state == TCP_ESTABLISHED || in net_tcp_put()
3642 conn->state == TCP_SYN_RECEIVED) { in net_tcp_put()
3644 if (conn->send_data_total > 0) { in net_tcp_put()
3645 NET_DBG("conn %p pending %zu bytes", conn, in net_tcp_put()
3646 conn->send_data_total); in net_tcp_put()
3647 conn->in_close = true; in net_tcp_put()
3652 &conn->send_data_timer, in net_tcp_put()
3661 &conn->fin_timer, in net_tcp_put()
3664 ret = tcp_out_ext(conn, FIN | ACK, NULL, in net_tcp_put()
3665 conn->seq + conn->unacked_len); in net_tcp_put()
3667 conn_seq(conn, + 1); in net_tcp_put()
3670 conn_state(conn, TCP_FIN_WAIT_1); in net_tcp_put()
3672 keep_alive_timer_stop(conn); in net_tcp_put()
3674 } else if (conn->in_connect) { in net_tcp_put()
3675 conn->in_connect = false; in net_tcp_put()
3676 k_sem_reset(&conn->connect_sem); in net_tcp_put()
3679 k_mutex_unlock(&conn->lock); in net_tcp_put()
3681 tcp_conn_unref(conn); in net_tcp_put()
3696 struct tcp *conn = context->tcp; in net_tcp_update_recv_wnd() local
3699 if (!conn) { in net_tcp_update_recv_wnd()
3704 k_mutex_lock(&conn->lock, K_FOREVER); in net_tcp_update_recv_wnd()
3708 k_mutex_unlock(&conn->lock); in net_tcp_update_recv_wnd()
3716 struct tcp *conn = context->tcp; in net_tcp_queue() local
3720 if (!conn || conn->state != TCP_ESTABLISHED) { in net_tcp_queue()
3724 k_mutex_lock(&conn->lock, K_FOREVER); in net_tcp_queue()
3730 if (tcp_window_full(conn)) { in net_tcp_queue()
3744 * that conn->send_data_total is less than conn->send_win, as it was in net_tcp_queue()
3748 len = MIN(conn->send_win - conn->send_data_total, len); in net_tcp_queue()
3754 ret = tcp_pkt_append(conn->send_data, in net_tcp_queue()
3773 ret = tcp_pkt_append(conn->send_data, data, len); in net_tcp_queue()
3781 conn->send_data_total += queued_len; in net_tcp_queue()
3787 ret = tcp_send_queued_data(conn); in net_tcp_queue()
3789 tcp_conn_close(conn, ret); in net_tcp_queue()
3793 if (tcp_window_full(conn)) { in net_tcp_queue()
3794 (void)k_sem_take(&conn->tx_sem, K_NO_WAIT); in net_tcp_queue()
3799 k_mutex_unlock(&conn->lock); in net_tcp_queue()
3826 struct tcp *conn; in net_tcp_connect() local
3835 conn = context->tcp; in net_tcp_connect()
3836 conn->iface = net_context_get_iface(context); in net_tcp_connect()
3837 tcp_derive_rto(conn); in net_tcp_connect()
3849 memset(&conn->src, 0, sizeof(struct sockaddr_in)); in net_tcp_connect()
3850 memset(&conn->dst, 0, sizeof(struct sockaddr_in)); in net_tcp_connect()
3852 conn->src.sa.sa_family = AF_INET; in net_tcp_connect()
3853 conn->dst.sa.sa_family = AF_INET; in net_tcp_connect()
3855 conn->dst.sin.sin_port = remote_port; in net_tcp_connect()
3856 conn->src.sin.sin_port = local_port; in net_tcp_connect()
3867 net_ipaddr_copy(&conn->src.sin.sin_addr, ip4); in net_tcp_connect()
3869 net_ipaddr_copy(&conn->src.sin.sin_addr, in net_tcp_connect()
3872 net_ipaddr_copy(&conn->dst.sin.sin_addr, in net_tcp_connect()
3882 memset(&conn->src, 0, sizeof(struct sockaddr_in6)); in net_tcp_connect()
3883 memset(&conn->dst, 0, sizeof(struct sockaddr_in6)); in net_tcp_connect()
3885 conn->src.sin6.sin6_family = AF_INET6; in net_tcp_connect()
3886 conn->dst.sin6.sin6_family = AF_INET6; in net_tcp_connect()
3888 conn->dst.sin6.sin6_port = remote_port; in net_tcp_connect()
3889 conn->src.sin6.sin6_port = local_port; in net_tcp_connect()
3896 net_ipaddr_copy(&conn->src.sin6.sin6_addr, ip6); in net_tcp_connect()
3898 net_ipaddr_copy(&conn->src.sin6.sin6_addr, in net_tcp_connect()
3901 net_ipaddr_copy(&conn->dst.sin6.sin6_addr, in net_tcp_connect()
3911 conn->seq = tcp_init_isn(&conn->src.sa, &conn->dst.sa); in net_tcp_connect()
3914 NET_DBG("conn: %p src: %s, dst: %s", conn, in net_tcp_connect()
3915 net_sprint_addr(conn->src.sa.sa_family, in net_tcp_connect()
3916 (const void *)&conn->src.sin.sin_addr), in net_tcp_connect()
3917 net_sprint_addr(conn->dst.sa.sa_family, in net_tcp_connect()
3918 (const void *)&conn->dst.sin.sin_addr)); in net_tcp_connect()
3932 net_if_addr_ref(conn->iface, conn->src.sa.sa_family, in net_tcp_connect()
3933 conn->src.sa.sa_family == AF_INET ? in net_tcp_connect()
3934 (const void *)&conn->src.sin.sin_addr : in net_tcp_connect()
3935 (const void *)&conn->src.sin6.sin6_addr); in net_tcp_connect()
3936 conn->addr_ref_done = true; in net_tcp_connect()
3938 conn->connect_cb = cb; in net_tcp_connect()
3944 conn->in_connect = !IS_ENABLED(CONFIG_NET_TEST_PROTOCOL); in net_tcp_connect()
3949 tcp_conn_ref(conn); in net_tcp_connect()
3950 (void)tcp_in(conn, NULL); in net_tcp_connect()
3953 if (conn->state == TCP_UNUSED || conn->state == TCP_CLOSED) { in net_tcp_connect()
3957 conn->state != TCP_ESTABLISHED) { in net_tcp_connect()
3960 } else if (k_sem_take(&conn->connect_sem, timeout) != 0 && in net_tcp_connect()
3961 conn->state != TCP_ESTABLISHED) { in net_tcp_connect()
3962 if (conn->in_connect) { in net_tcp_connect()
3963 conn->in_connect = false; in net_tcp_connect()
3964 tcp_conn_close(conn, -ETIMEDOUT); in net_tcp_connect()
3970 conn->in_connect = false; in net_tcp_connect()
3974 tcp_conn_unref(conn); in net_tcp_connect()
3977 NET_DBG("conn: %p, ret=%d", conn, ret); in net_tcp_connect()
3985 struct tcp *conn = context->tcp; in net_tcp_accept() local
3989 if (!conn) { in net_tcp_accept()
3993 NET_DBG("context: %p, tcp: %p, cb: %p", context, conn, cb); in net_tcp_accept()
3995 if (conn->state != TCP_LISTEN) { in net_tcp_accept()
3999 conn->accept_cb = cb; in net_tcp_accept()
4068 struct tcp *conn = context->tcp; in net_tcp_recv() local
4074 if (conn) { in net_tcp_recv()
4075 conn->recv_user_data = user_data; in net_tcp_recv()
4139 struct tcp *conn = tcp_conn_search(pkt); in tcp_input() local
4141 if (conn == NULL && SYN == th_flags(th)) { in tcp_input()
4146 conn = context->tcp; in tcp_input()
4147 tcp_endpoint_set(&conn->dst, pkt, TCP_EP_SRC); in tcp_input()
4148 tcp_endpoint_set(&conn->src, pkt, TCP_EP_DST); in tcp_input()
4152 tcp_conn_ref(conn); in tcp_input()
4155 if (conn) { in tcp_input()
4156 conn->iface = pkt->iface; in tcp_input()
4157 verdict = tcp_in(conn, pkt); in tcp_input()
4164 static size_t tp_tcp_recv_cb(struct tcp *conn, struct net_pkt *pkt) in tp_tcp_recv_cb() argument
4177 net_tcp_queue(conn->context, buf->data, buf->len); in tp_tcp_recv_cb()
4188 static void tp_init(struct tcp *conn, struct tp *tp) in tp_init() argument
4193 .state = tcp_state_to_str(conn->state, true), in tp_init()
4194 .seq = conn->seq, in tp_init()
4195 .ack = conn->ack, in tp_init()
4204 static void tcp_to_json(struct tcp *conn, void *data, size_t *data_len) in tcp_to_json() argument
4208 tp_init(conn, &tp); in tcp_to_json()
4221 struct tcp *conn = tcp_conn_search(pkt); in tp_input() local
4270 conn = context->tcp; in tp_input()
4271 tcp_endpoint_set(&conn->dst, pkt, TCP_EP_SRC); in tp_input()
4272 tcp_endpoint_set(&conn->src, pkt, TCP_EP_DST); in tp_input()
4273 conn->iface = pkt->iface; in tp_input()
4274 tcp_conn_ref(conn); in tp_input()
4276 conn->seq = tp->seq; in tp_input()
4277 verdict = tcp_in(conn, NULL); in tp_input()
4284 conn = (void *)sys_slist_peek_head(&tcp_conns); in tp_input()
4285 context = conn->context; in tp_input()
4286 while (tcp_conn_close(conn, 0)) in tp_input()
4296 struct tcp *conn = in tp_input() local
4298 net_tcp_put(conn->context); in tp_input()
4305 tp_init(conn, tp); in tp_input()
4314 struct tcp *conn = in tp_input() local
4321 net_tcp_queue(conn->context, buf, len); in tp_input()
4335 conn = (void *)sys_slist_peek_head(&tcp_conns); in tp_input()
4336 tcp_to_json(conn, buf, &json_len); in tp_input()
4380 struct tcp *conn; in net_tcp_foreach() local
4385 SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&tcp_conns, conn, tmp, next) { in net_tcp_foreach()
4386 if (atomic_get(&conn->ref_count) > 0) { in net_tcp_foreach()
4388 cb(conn, user_data); in net_tcp_foreach()
4448 uint16_t net_tcp_get_supported_mss(const struct tcp *conn) in net_tcp_get_supported_mss() argument
4450 sa_family_t family = net_context_get_family(conn->context); in net_tcp_get_supported_mss()
4453 struct net_if *iface = net_context_get_iface(conn->context); in net_tcp_get_supported_mss()
4456 dest_mtu = get_ipv4_destination_mtu(iface, &conn->dst.sin.sin_addr); in net_tcp_get_supported_mss()
4462 struct net_if *iface = net_context_get_iface(conn->context); in net_tcp_get_supported_mss()
4465 dest_mtu = get_ipv6_destination_mtu(iface, &conn->dst.sin6.sin6_addr); in net_tcp_get_supported_mss()
4480 static void testing_find_conn(struct tcp *conn, void *user_data) in testing_find_conn() argument
4485 net_ipv6_addr_cmp(&conn->dst.sin6.sin6_addr, in testing_find_conn()
4492 NET_DBG("Found connection %p mtu %u", conn, in testing_find_conn()
4493 net_tcp_get_supported_mss(conn) + NET_IPV6TCPH_LEN); in testing_find_conn()
4494 data->mtu = net_tcp_get_supported_mss(conn) + NET_IPV6TCPH_LEN; in testing_find_conn()
4499 net_ipv4_addr_cmp(&conn->dst.sin.sin_addr, in testing_find_conn()
4506 NET_DBG("Found connection %p mtu %u", conn, in testing_find_conn()
4507 net_tcp_get_supported_mss(conn) + NET_IPV4TCPH_LEN); in testing_find_conn()
4508 data->mtu = net_tcp_get_supported_mss(conn) + NET_IPV4TCPH_LEN; in testing_find_conn()
4534 struct tcp *conn = context->tcp; in net_tcp_set_option() local
4536 NET_ASSERT(conn); in net_tcp_set_option()
4538 k_mutex_lock(&conn->lock, K_FOREVER); in net_tcp_set_option()
4542 ret = set_tcp_nodelay(conn, value, len); in net_tcp_set_option()
4545 ret = set_tcp_keep_alive(conn, value, len); in net_tcp_set_option()
4548 ret = set_tcp_keep_idle(conn, value, len); in net_tcp_set_option()
4551 ret = set_tcp_keep_intvl(conn, value, len); in net_tcp_set_option()
4554 ret = set_tcp_keep_cnt(conn, value, len); in net_tcp_set_option()
4558 k_mutex_unlock(&conn->lock); in net_tcp_set_option()
4571 struct tcp *conn = context->tcp; in net_tcp_get_option() local
4573 NET_ASSERT(conn); in net_tcp_get_option()
4575 k_mutex_lock(&conn->lock, K_FOREVER); in net_tcp_get_option()
4579 ret = get_tcp_nodelay(conn, value, len); in net_tcp_get_option()
4582 ret = get_tcp_keep_alive(conn, value, len); in net_tcp_get_option()
4585 ret = get_tcp_keep_idle(conn, value, len); in net_tcp_get_option()
4588 ret = get_tcp_keep_intvl(conn, value, len); in net_tcp_get_option()
4591 ret = get_tcp_keep_cnt(conn, value, len); in net_tcp_get_option()
4595 k_mutex_unlock(&conn->lock); in net_tcp_get_option()
4607 struct tcp *conn = context->tcp; in net_tcp_tx_sem_get() local
4609 return &conn->tx_sem; in net_tcp_tx_sem_get()
4614 struct tcp *conn = context->tcp; in net_tcp_conn_sem_get() local
4616 return &conn->connect_sem; in net_tcp_conn_sem_get()