--- zzzz-none-000/linux-4.1.52/net/ipv4/tcp_minisocks.c 2018-05-28 02:26:45.000000000 +0000 +++ bcm63-7530ax-731/linux-4.1.52/net/ipv4/tcp_minisocks.c 2022-03-02 11:37:13.000000000 +0000 @@ -18,11 +18,17 @@ * Jorge Cwik, */ +#if defined(CONFIG_BCM_MPTCP) && defined(CONFIG_BCM_KF_MPTCP) +#include +#endif #include #include #include #include #include +#if defined(CONFIG_BCM_MPTCP) && defined(CONFIG_BCM_KF_MPTCP) +#include +#endif #include #include #include @@ -103,10 +109,19 @@ struct tcp_options_received tmp_opt; struct tcp_timewait_sock *tcptw = tcp_twsk((struct sock *)tw); bool paws_reject = false; +#if defined(CONFIG_BCM_MPTCP) && defined(CONFIG_BCM_KF_MPTCP) + struct mptcp_options_received mopt; +#endif tmp_opt.saw_tstamp = 0; if (th->doff > (sizeof(*th) >> 2) && tcptw->tw_ts_recent_stamp) { +#if !defined(CONFIG_BCM_MPTCP) || !defined(CONFIG_BCM_KF_MPTCP) tcp_parse_options(skb, &tmp_opt, 0, NULL); +#else + mptcp_init_mp_opt(&mopt); + + tcp_parse_options(skb, &tmp_opt, &mopt, 0, NULL, NULL); +#endif if (tmp_opt.saw_tstamp) { tmp_opt.rcv_tsecr -= tcptw->tw_ts_offset; @@ -114,6 +129,13 @@ tmp_opt.ts_recent_stamp = tcptw->tw_ts_recent_stamp; paws_reject = tcp_paws_reject(&tmp_opt, th->rst); } +#if defined(CONFIG_BCM_MPTCP) && defined(CONFIG_BCM_KF_MPTCP) + + if (unlikely(mopt.mp_fclose) && tcptw->mptcp_tw) { + if (mopt.mptcp_sender_key == tcptw->mptcp_tw->loc_key) + goto kill_with_rst; + } +#endif } if (tw->tw_substate == TCP_FIN_WAIT2) { @@ -137,6 +159,18 @@ if (!th->ack || !after(TCP_SKB_CB(skb)->end_seq, tcptw->tw_rcv_nxt) || TCP_SKB_CB(skb)->end_seq == TCP_SKB_CB(skb)->seq) { +#if defined(CONFIG_BCM_MPTCP) && defined(CONFIG_BCM_KF_MPTCP) + /* If mptcp_is_data_fin() returns true, we are sure that + * mopt has been initialized - otherwise it would not + * be a DATA_FIN. + */ + if (tcptw->mptcp_tw && tcptw->mptcp_tw->meta_tw && + mptcp_is_data_fin(skb) && + TCP_SKB_CB(skb)->seq == tcptw->tw_rcv_nxt && + mopt.data_seq + 1 == (u32)tcptw->mptcp_tw->rcv_nxt) + return TCP_TW_ACK; + +#endif inet_twsk_put(tw); return TCP_TW_SUCCESS; } @@ -293,6 +327,17 @@ tcptw->tw_ts_offset = tp->tsoffset; tcptw->tw_last_oow_ack_time = 0; +#if defined(CONFIG_BCM_MPTCP) && defined(CONFIG_BCM_KF_MPTCP) + if (mptcp(tp)) { + if (mptcp_init_tw_sock(sk, tcptw)) { + inet_twsk_free(tw); + goto exit; + } + } else { + tcptw->mptcp_tw = NULL; + } + +#endif #if IS_ENABLED(CONFIG_IPV6) if (tw->tw_family == PF_INET6) { struct ipv6_pinfo *np = inet6_sk(sk); @@ -348,10 +393,27 @@ NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPTIMEWAITOVERFLOW); } +#if defined(CONFIG_BCM_MPTCP) && defined(CONFIG_BCM_KF_MPTCP) +exit: +#endif tcp_update_metrics(sk); tcp_done(sk); } +#if defined(CONFIG_BCM_MPTCP) && defined(CONFIG_BCM_KF_MPTCP) +void tcp_twsk_destructor(struct sock *sk) +{ + struct tcp_timewait_sock *twsk = tcp_twsk(sk); + + if (twsk->mptcp_tw) + mptcp_twsk_destructor(twsk); + +#ifdef CONFIG_TCP_MD5SIG + if (twsk->tw_md5_key) + kfree_rcu(twsk->tw_md5_key, rcu); +#endif +} +#else void tcp_twsk_destructor(struct sock *sk) { #ifdef CONFIG_TCP_MD5SIG @@ -361,6 +423,7 @@ kfree_rcu(twsk->tw_md5_key, rcu); #endif } +#endif EXPORT_SYMBOL_GPL(tcp_twsk_destructor); void tcp_openreq_init_rwin(struct request_sock *req, @@ -383,13 +446,23 @@ req->window_clamp = tcp_full_space(sk); /* tcp_full_space because it is guaranteed to be the first packet */ +#if !defined(CONFIG_BCM_MPTCP) || !defined(CONFIG_BCM_KF_MPTCP) tcp_select_initial_window(tcp_full_space(sk), mss - (ireq->tstamp_ok ? TCPOLEN_TSTAMP_ALIGNED : 0), +#else + tp->ops->select_initial_window(tcp_full_space(sk), + mss - (ireq->tstamp_ok ? TCPOLEN_TSTAMP_ALIGNED : 0) - + (ireq->saw_mpc ? MPTCP_SUB_LEN_DSM_ALIGN : 0), +#endif &req->rcv_wnd, &req->window_clamp, ireq->wscale_ok, &rcv_wscale, +#if !defined(CONFIG_BCM_MPTCP) || !defined(CONFIG_BCM_KF_MPTCP) dst_metric(dst, RTAX_INITRWND)); +#else + dst_metric(dst, RTAX_INITRWND), sk); +#endif ireq->rcv_wscale = rcv_wscale; } EXPORT_SYMBOL(tcp_openreq_init_rwin); @@ -455,7 +528,9 @@ newtp->snd_nxt = newtp->snd_up = treq->snt_isn + 1; tcp_prequeue_init(newtp); +#if !defined(CONFIG_BCM_KF_TCP_NO_TSQ) INIT_LIST_HEAD(&newtp->tsq_node); +#endif tcp_init_wl(newtp, treq->rcv_isn); @@ -526,6 +601,10 @@ newtp->rx_opt.ts_recent_stamp = 0; newtp->tcp_header_len = sizeof(struct tcphdr); } +#if defined(CONFIG_BCM_MPTCP) && defined(CONFIG_BCM_KF_MPTCP) + if (ireq->saw_mpc) + newtp->tcp_header_len += MPTCP_SUB_LEN_DSM_ALIGN; +#endif newtp->tsoffset = 0; #ifdef CONFIG_TCP_MD5SIG newtp->md5sig_info = NULL; /*XXX*/ @@ -561,16 +640,32 @@ bool fastopen) { struct tcp_options_received tmp_opt; +#if defined(CONFIG_BCM_MPTCP) && defined(CONFIG_BCM_KF_MPTCP) + struct mptcp_options_received mopt; +#endif struct sock *child; const struct tcphdr *th = tcp_hdr(skb); __be32 flg = tcp_flag_word(th) & (TCP_FLAG_RST|TCP_FLAG_SYN|TCP_FLAG_ACK); bool paws_reject = false; +#if !defined(CONFIG_BCM_MPTCP) || !defined(CONFIG_BCM_KF_MPTCP) BUG_ON(fastopen == (sk->sk_state == TCP_LISTEN)); +#else + BUG_ON(!mptcp(tcp_sk(sk)) && fastopen == (sk->sk_state == TCP_LISTEN)); +#endif tmp_opt.saw_tstamp = 0; +#if defined(CONFIG_BCM_MPTCP) && defined(CONFIG_BCM_KF_MPTCP) + + mptcp_init_mp_opt(&mopt); + +#endif if (th->doff > (sizeof(struct tcphdr)>>2)) { +#if !defined(CONFIG_BCM_MPTCP) || !defined(CONFIG_BCM_KF_MPTCP) tcp_parse_options(skb, &tmp_opt, 0, NULL); +#else + tcp_parse_options(skb, &tmp_opt, &mopt, 0, NULL, NULL); +#endif if (tmp_opt.saw_tstamp) { tmp_opt.ts_recent = req->ts_recent; @@ -610,6 +705,15 @@ * Reset timer after retransmitting SYNACK, similar to * the idea of fast retransmit in recovery. */ + +#if defined(CONFIG_BCM_MPTCP) && defined(CONFIG_BCM_KF_MPTCP) + /* Fall back to TCP if MP_CAPABLE is not set.i */ + + if (inet_rsk(req)->saw_mpc && !mopt.saw_mpc) + inet_rsk(req)->saw_mpc = false; + + +#endif if (!tcp_oow_rate_limited(sock_net(sk), skb, LINUX_MIB_TCPACKSKIPPEDSYNRECV, &tcp_rsk(req)->last_oow_ack_time) && @@ -758,6 +862,20 @@ if (!child) goto listen_overflow; +#if defined(CONFIG_BCM_MPTCP) && defined(CONFIG_BCM_KF_MPTCP) + if (!is_meta_sk(sk)) { + int ret = mptcp_check_req_master(sk, child, req, 1); + if (ret < 0) + goto listen_overflow; + + /* MPTCP-supported */ + if (!ret) + return tcp_sk(child)->mpcb->master_sk; + } else { + return mptcp_check_req_child(sk, child, req, &mopt); + } + +#endif inet_csk_reqsk_queue_drop(sk, req); inet_csk_reqsk_queue_add(sk, req, child); /* Warning: caller must not call reqsk_put(req); @@ -808,8 +926,15 @@ { int ret = 0; int state = child->sk_state; +#if defined(CONFIG_BCM_MPTCP) && defined(CONFIG_BCM_KF_MPTCP) + struct sock *meta_sk = mptcp(tcp_sk(child)) ? mptcp_meta_sk(child) : child; +#endif +#if !defined(CONFIG_BCM_MPTCP) || !defined(CONFIG_BCM_KF_MPTCP) if (!sock_owned_by_user(child)) { +#else + if (!sock_owned_by_user(meta_sk)) { +#endif ret = tcp_rcv_state_process(child, skb, tcp_hdr(skb), skb->len); /* Wakeup parent, send SIGIO */ @@ -820,10 +945,22 @@ * in main socket hash table and lock on listening * socket does not protect us more. */ +#if !defined(CONFIG_BCM_MPTCP) || !defined(CONFIG_BCM_KF_MPTCP) __sk_add_backlog(child, skb); +#else + if (mptcp(tcp_sk(child))) + skb->sk = child; + __sk_add_backlog(meta_sk, skb); +#endif } +#if !defined(CONFIG_BCM_MPTCP) || !defined(CONFIG_BCM_KF_MPTCP) bh_unlock_sock(child); +#else + if (mptcp(tcp_sk(child))) + bh_unlock_sock(child); + bh_unlock_sock(meta_sk); +#endif sock_put(child); return ret; }