--- zzzz-none-000/linux-4.1.52/net/ipv4/tcp.c 2018-05-28 02:26:45.000000000 +0000 +++ bcm63-7530ax-731/linux-4.1.52/net/ipv4/tcp.c 2022-03-02 11:37:13.000000000 +0000 @@ -272,6 +272,9 @@ #include #include +#if defined(CONFIG_BCM_MPTCP) && defined(CONFIG_BCM_KF_MPTCP) +#include +#endif #include #include #include @@ -372,6 +375,27 @@ return period; } +#if defined(CONFIG_BCM_MPTCP) && defined(CONFIG_BCM_KF_MPTCP) +const struct tcp_sock_ops tcp_specific = { + .__select_window = __tcp_select_window, + .select_window = tcp_select_window, + .select_initial_window = tcp_select_initial_window, + .select_size = select_size, + .init_buffer_space = tcp_init_buffer_space, + .set_rto = tcp_set_rto, + .should_expand_sndbuf = tcp_should_expand_sndbuf, + .send_fin = tcp_send_fin, + .write_xmit = tcp_write_xmit, + .send_active_reset = tcp_send_active_reset, + .write_wakeup = tcp_write_wakeup, + .prune_ofo_queue = tcp_prune_ofo_queue, + .retransmit_timer = tcp_retransmit_timer, + .time_wait = tcp_time_wait, + .cleanup_rbuf = tcp_cleanup_rbuf, + .cwnd_validate = tcp_cwnd_validate, +}; + +#endif /* Address-family independent initialization for a tcp_sock. * * NOTE: A lot of things set to zero explicitly by call to @@ -385,7 +409,9 @@ __skb_queue_head_init(&tp->out_of_order_queue); tcp_init_xmit_timers(sk); tcp_prequeue_init(tp); +#if !defined(CONFIG_BCM_KF_TCP_NO_TSQ) INIT_LIST_HEAD(&tp->tsq_node); +#endif icsk->icsk_rto = TCP_TIMEOUT_INIT; tp->mdev_us = jiffies_to_usecs(TCP_TIMEOUT_INIT); @@ -421,6 +447,13 @@ sk->sk_sndbuf = sysctl_tcp_wmem[1]; sk->sk_rcvbuf = sysctl_tcp_rmem[1]; +#if defined(CONFIG_BCM_MPTCP) && defined(CONFIG_BCM_KF_MPTCP) + tp->ops = &tcp_specific; + + /* Initialize MPTCP-specific stuff and function-pointers */ + mptcp_init_tcp_sock(sk); + +#endif local_bh_disable(); sock_update_memcg(sk); sk_sockets_allocated_inc(sk); @@ -646,6 +679,23 @@ * autocorking if we only have an ACK in Qdisc/NIC queues, * or if TX completion was delayed after we processed ACK packet. */ +#if defined(CONFIG_BCM_KF_TCP_NO_TSQ) +static void tcp_push(struct sock *sk, int flags, int mss_now, + int nonagle, int size_goal) +{ + if (tcp_send_head(sk)) { + struct tcp_sock *tp = tcp_sk(sk); + + if (!(flags & MSG_MORE) || forced_push(tp)) + tcp_mark_push(tp, tcp_write_queue_tail(sk)); + + tcp_mark_urg(tp, flags); + __tcp_push_pending_frames(sk, mss_now, + (flags & MSG_MORE) ? TCP_NAGLE_CORK : nonagle); + } +} + +#else static bool tcp_should_autocork(struct sock *sk, struct sk_buff *skb, int size_goal) { @@ -689,6 +739,7 @@ __tcp_push_pending_frames(sk, mss_now, nonagle); } +#endif static int tcp_splice_data_recv(read_descriptor_t *rd_desc, struct sk_buff *skb, unsigned int offset, size_t len) @@ -741,6 +792,16 @@ int ret; sock_rps_record_flow(sk); +#if defined(CONFIG_BCM_MPTCP) && defined(CONFIG_BCM_KF_MPTCP) + +#ifdef CONFIG_MPTCP + if (mptcp(tcp_sk(sk))) { + struct sock *sk_it; + mptcp_for_each_sk(tcp_sk(sk)->mpcb, sk_it) + sock_rps_record_flow(sk_it); + } +#endif +#endif /* * We can't seek on a socket input */ @@ -780,6 +841,15 @@ ret = -EAGAIN; break; } +#if defined(CONFIG_BCM_KF_MISC_BACKPORTS) +/* CVE-2017-6214*/ + /* if __tcp_splice_read() got nothing while we have + * an skb in receive queue, we do not want to loop. + * This might happen with URG data. + */ + if (!skb_queue_empty(&sk->sk_receive_queue)) + break; +#endif sk_wait_data(sk, &timeo); if (signal_pending(current)) { ret = sock_intr_errno(timeo); @@ -836,8 +906,12 @@ return NULL; } +#if !defined(CONFIG_BCM_MPTCP) || !defined(CONFIG_BCM_KF_MPTCP) static unsigned int tcp_xmit_size_goal(struct sock *sk, u32 mss_now, int large_allowed) +#else +unsigned int tcp_xmit_size_goal(struct sock *sk, u32 mss_now, int large_allowed) +#endif { struct tcp_sock *tp = tcp_sk(sk); u32 new_size_goal, size_goal; @@ -865,8 +939,18 @@ { int mss_now; +#if !defined(CONFIG_BCM_MPTCP) || !defined(CONFIG_BCM_KF_MPTCP) mss_now = tcp_current_mss(sk); *size_goal = tcp_xmit_size_goal(sk, mss_now, !(flags & MSG_OOB)); +#else + if (mptcp(tcp_sk(sk))) { + mss_now = mptcp_current_mss(sk); + *size_goal = mptcp_xmit_size_goal(sk, mss_now, !(flags & MSG_OOB)); + } else { + mss_now = tcp_current_mss(sk); + *size_goal = tcp_xmit_size_goal(sk, mss_now, !(flags & MSG_OOB)); + } +#endif return mss_now; } @@ -885,11 +969,38 @@ * is fully established. */ if (((1 << sk->sk_state) & ~(TCPF_ESTABLISHED | TCPF_CLOSE_WAIT)) && +#if !defined(CONFIG_BCM_MPTCP) || !defined(CONFIG_BCM_KF_MPTCP) !tcp_passive_fastopen(sk)) { +#else + !tcp_passive_fastopen(mptcp(tp) && tp->mpcb->master_sk ? + tp->mpcb->master_sk : sk)) { +#endif if ((err = sk_stream_wait_connect(sk, &timeo)) != 0) goto out_err; } +#if defined(CONFIG_BCM_MPTCP) && defined(CONFIG_BCM_KF_MPTCP) + if (mptcp(tp)) { + struct sock *sk_it = sk; + + /* We must check this with socket-lock hold because we iterate + * over the subflows. + */ + if (!mptcp_can_sendpage(sk)) { + ssize_t ret; + + release_sock(sk); + ret = sock_no_sendpage(sk->sk_socket, page, offset, + size, flags); + lock_sock(sk); + return ret; + } + + mptcp_for_each_sk(tp->mpcb, sk_it) + sock_rps_record_flow(sk_it); + } + +#endif clear_bit(SOCK_ASYNC_NOSPACE, &sk->sk_socket->flags); mss_now = tcp_send_mss(sk, &size_goal, flags); @@ -996,8 +1107,14 @@ { ssize_t res; +#if !defined(CONFIG_BCM_MPTCP) || !defined(CONFIG_BCM_KF_MPTCP) if (!(sk->sk_route_caps & NETIF_F_SG) || !(sk->sk_route_caps & NETIF_F_ALL_CSUM)) +#else + /* If MPTCP is enabled, we check it later after establishment */ + if (!mptcp(tcp_sk(sk)) && (!(sk->sk_route_caps & NETIF_F_SG) || + !(sk->sk_route_caps & NETIF_F_ALL_CSUM))) +#endif return sock_no_sendpage(sk->sk_socket, page, offset, size, flags); @@ -1008,7 +1125,11 @@ } EXPORT_SYMBOL(tcp_sendpage); +#if !defined(CONFIG_BCM_MPTCP) || !defined(CONFIG_BCM_KF_MPTCP) static inline int select_size(const struct sock *sk, bool sg) +#else +int select_size(const struct sock *sk, bool sg) +#endif { const struct tcp_sock *tp = tcp_sk(sk); int tmp = tp->mss_cache; @@ -1095,11 +1216,24 @@ * is fully established. */ if (((1 << sk->sk_state) & ~(TCPF_ESTABLISHED | TCPF_CLOSE_WAIT)) && +#if !defined(CONFIG_BCM_MPTCP) || !defined(CONFIG_BCM_KF_MPTCP) !tcp_passive_fastopen(sk)) { +#else + !tcp_passive_fastopen(mptcp(tp) && tp->mpcb->master_sk ? + tp->mpcb->master_sk : sk)) { +#endif if ((err = sk_stream_wait_connect(sk, &timeo)) != 0) goto do_error; } +#if defined(CONFIG_BCM_MPTCP) && defined(CONFIG_BCM_KF_MPTCP) + if (mptcp(tp)) { + struct sock *sk_it = sk; + mptcp_for_each_sk(tp->mpcb, sk_it) + sock_rps_record_flow(sk_it); + } + +#endif if (unlikely(tp->repair)) { if (tp->repair_queue == TCP_RECV_QUEUE) { copied = tcp_send_rcvq(sk, msg, size); @@ -1125,7 +1259,14 @@ if (sk->sk_err || (sk->sk_shutdown & SEND_SHUTDOWN)) goto out_err; +#if !defined(CONFIG_BCM_MPTCP) || !defined(CONFIG_BCM_KF_MPTCP) sg = !!(sk->sk_route_caps & NETIF_F_SG); +#else + if (mptcp(tp)) + sg = mptcp_can_sg(sk); + else + sg = !!(sk->sk_route_caps & NETIF_F_SG); +#endif while (msg_data_left(msg)) { int copy = 0; @@ -1147,15 +1288,33 @@ goto wait_for_sndbuf; skb = sk_stream_alloc_skb(sk, +#if !defined(CONFIG_BCM_MPTCP) || !defined(CONFIG_BCM_KF_MPTCP) select_size(sk, sg), +#else + tp->ops->select_size(sk, sg), +#endif sk->sk_allocation); if (!skb) goto wait_for_memory; +#if !defined(CONFIG_BCM_MPTCP) || !defined(CONFIG_BCM_KF_MPTCP) /* * Check whether we can use HW checksum. */ if (sk->sk_route_caps & NETIF_F_ALL_CSUM) +#else + /* + * Check whether we can use HW checksum. + * + * If dss-csum is enabled, we do not do hw-csum. + * In case of non-mptcp we check the + * device-capabilities. + * In case of mptcp, hw-csum's will be handled + * later in mptcp_write_xmit. + */ + if (((mptcp(tp) && !tp->mpcb->dss_csum) || !mptcp(tp)) && + (mptcp(tp) || sk->sk_route_caps & NETIF_F_ALL_CSUM)) +#endif skb->ip_summed = CHECKSUM_PARTIAL; skb_entail(sk, skb); @@ -1178,9 +1337,19 @@ if (skb_availroom(skb) > 0) { /* We have some space in skb head. Superb! */ copy = min_t(int, copy, skb_availroom(skb)); - err = skb_add_data_nocache(sk, skb, &msg->msg_iter, copy); - if (err) - goto do_fault; +#if defined(CONFIG_BCM_KF_SPEEDYGET) && defined(CONFIG_BCM_SPEEDYGET) + if( unlikely(!tp->tcp_nocopy) ) { +#endif + err = skb_add_data_nocache(sk, skb, &msg->msg_iter, copy); + if (err) + goto do_fault; +#if defined(CONFIG_BCM_KF_SPEEDYGET) && defined(CONFIG_BCM_SPEEDYGET) + } else { + skb->csum=0; + memset(skb_put(skb,copy),0,copy); + iov_iter_advance(&msg->msg_iter, copy); + } +#endif } else { bool merge = true; int i = skb_shinfo(skb)->nr_frags; @@ -1357,7 +1526,11 @@ * calculation of whether or not we must ACK for the sake of * a window update. */ +#if !defined(CONFIG_BCM_MPTCP) || !defined(CONFIG_BCM_KF_MPTCP) static void tcp_cleanup_rbuf(struct sock *sk, int copied) +#else +void tcp_cleanup_rbuf(struct sock *sk, int copied) +#endif { struct tcp_sock *tp = tcp_sk(sk); bool time_to_ack = false; @@ -1400,7 +1573,11 @@ /* Optimize, __tcp_select_window() is not cheap. */ if (2*rcv_window_now <= tp->window_clamp) { +#if !defined(CONFIG_BCM_MPTCP) || !defined(CONFIG_BCM_KF_MPTCP) __u32 new_window = __tcp_select_window(sk); +#else + __u32 new_window = tp->ops->__select_window(sk); +#endif /* Send ACK now, if this read freed lots of space * in our buffer. Certainly, new_window is new window. @@ -1532,7 +1709,11 @@ /* Clean up data we have read: This will do ACK frames. */ if (copied > 0) { tcp_recv_skb(sk, seq, &offset); +#if !defined(CONFIG_BCM_MPTCP) || !defined(CONFIG_BCM_KF_MPTCP) tcp_cleanup_rbuf(sk, copied); +#else + tp->ops->cleanup_rbuf(sk, copied); +#endif } return copied; } @@ -1570,6 +1751,16 @@ lock_sock(sk); +#if defined(CONFIG_BCM_MPTCP) && defined(CONFIG_BCM_KF_MPTCP) +#ifdef CONFIG_MPTCP + if (mptcp(tp)) { + struct sock *sk_it; + mptcp_for_each_sk(tp->mpcb, sk_it) + sock_rps_record_flow(sk_it); + } +#endif + +#endif err = -ENOTCONN; if (sk->sk_state == TCP_LISTEN) goto out; @@ -1686,7 +1877,11 @@ } } +#if !defined(CONFIG_BCM_MPTCP) || !defined(CONFIG_BCM_KF_MPTCP) tcp_cleanup_rbuf(sk, copied); +#else + tp->ops->cleanup_rbuf(sk, copied); +#endif if (!sysctl_tcp_low_latency && tp->ucopy.task == user_recv) { /* Install new reader */ @@ -1796,16 +1991,22 @@ } } - if (!(flags & MSG_TRUNC)) { - err = skb_copy_datagram_msg(skb, offset, msg, used); - if (err) { - /* Exception. Bailout! */ - if (!copied) - copied = -EFAULT; - break; - } - } - + if (!(flags & MSG_TRUNC)) { +#if defined(CONFIG_BCM_KF_SPEEDYGET) && defined(CONFIG_BCM_SPEEDYGET) + if(unlikely(!tp->tcp_nocopy)) + { +#endif + err = skb_copy_datagram_msg(skb, offset, msg, used); + if (err) { + /* Exception. Bailout! */ + if (!copied) + copied = -EFAULT; + break; + } +#if defined(CONFIG_BCM_KF_SPEEDYGET) && defined(CONFIG_BCM_SPEEDYGET) + } +#endif + } *seq += used; copied += used; len -= used; @@ -1858,7 +2059,11 @@ */ /* Clean up data we have read: This will do ACK frames. */ +#if !defined(CONFIG_BCM_MPTCP) || !defined(CONFIG_BCM_KF_MPTCP) tcp_cleanup_rbuf(sk, copied); +#else + tp->ops->cleanup_rbuf(sk, copied); +#endif release_sock(sk); return copied; @@ -1936,7 +2141,11 @@ [TCP_NEW_SYN_RECV] = TCP_CLOSE, /* should not happen ! */ }; +#if !defined(CONFIG_BCM_MPTCP) || !defined(CONFIG_BCM_KF_MPTCP) static int tcp_close_state(struct sock *sk) +#else +int tcp_close_state(struct sock *sk) +#endif { int next = (int)new_state[sk->sk_state]; int ns = next & TCP_STATE_MASK; @@ -1966,7 +2175,11 @@ TCPF_SYN_RECV | TCPF_CLOSE_WAIT)) { /* Clear out any half completed packets. FIN if needed. */ if (tcp_close_state(sk)) +#if !defined(CONFIG_BCM_MPTCP) || !defined(CONFIG_BCM_KF_MPTCP) tcp_send_fin(sk); +#else + tcp_sk(sk)->ops->send_fin(sk); +#endif } } EXPORT_SYMBOL(tcp_shutdown); @@ -1991,6 +2204,13 @@ int data_was_unread = 0; int state; +#if defined(CONFIG_BCM_MPTCP) && defined(CONFIG_BCM_KF_MPTCP) + if (is_meta_sk(sk)) { + mptcp_close(sk, timeout); + return; + } + +#endif lock_sock(sk); sk->sk_shutdown = SHUTDOWN_MASK; @@ -2035,7 +2255,11 @@ /* Unread data was tossed, zap the connection. */ NET_INC_STATS_USER(sock_net(sk), LINUX_MIB_TCPABORTONCLOSE); tcp_set_state(sk, TCP_CLOSE); +#if !defined(CONFIG_BCM_MPTCP) || !defined(CONFIG_BCM_KF_MPTCP) tcp_send_active_reset(sk, sk->sk_allocation); +#else + tcp_sk(sk)->ops->send_active_reset(sk, sk->sk_allocation); +#endif } else if (sock_flag(sk, SOCK_LINGER) && !sk->sk_lingertime) { /* Check zero linger _after_ checking for unread data. */ sk->sk_prot->disconnect(sk, 0); @@ -2115,7 +2339,11 @@ struct tcp_sock *tp = tcp_sk(sk); if (tp->linger2 < 0) { tcp_set_state(sk, TCP_CLOSE); +#if !defined(CONFIG_BCM_MPTCP) || !defined(CONFIG_BCM_KF_MPTCP) tcp_send_active_reset(sk, GFP_ATOMIC); +#else + tp->ops->send_active_reset(sk, GFP_ATOMIC); +#endif NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPABORTONLINGER); } else { @@ -2125,7 +2353,12 @@ inet_csk_reset_keepalive_timer(sk, tmo - TCP_TIMEWAIT_LEN); } else { +#if !defined(CONFIG_BCM_MPTCP) || !defined(CONFIG_BCM_KF_MPTCP) tcp_time_wait(sk, TCP_FIN_WAIT2, tmo); +#else + tcp_sk(sk)->ops->time_wait(sk, TCP_FIN_WAIT2, + tmo); +#endif goto out; } } @@ -2134,7 +2367,11 @@ sk_mem_reclaim(sk); if (tcp_check_oom(sk, 0)) { tcp_set_state(sk, TCP_CLOSE); +#if !defined(CONFIG_BCM_MPTCP) || !defined(CONFIG_BCM_KF_MPTCP) tcp_send_active_reset(sk, GFP_ATOMIC); +#else + tcp_sk(sk)->ops->send_active_reset(sk, GFP_ATOMIC); +#endif NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPABORTONMEMORY); } else if (!check_net(sock_net(sk))) { @@ -2162,6 +2399,7 @@ } EXPORT_SYMBOL(tcp_close); +#if !defined(CONFIG_BCM_MPTCP) || !defined(CONFIG_BCM_KF_MPTCP) /* These states need RST on ABORT according to RFC793 */ static inline bool tcp_need_reset(int state) @@ -2171,6 +2409,7 @@ TCPF_FIN_WAIT2 | TCPF_SYN_RECV); } +#endif int tcp_disconnect(struct sock *sk, int flags) { struct inet_sock *inet = inet_sk(sk); @@ -2193,7 +2432,11 @@ /* The last check adjusts for discrepancy of Linux wrt. RFC * states */ +#if !defined(CONFIG_BCM_MPTCP) || !defined(CONFIG_BCM_KF_MPTCP) tcp_send_active_reset(sk, gfp_any()); +#else + tp->ops->send_active_reset(sk, gfp_any()); +#endif sk->sk_err = ECONNRESET; } else if (old_state == TCP_SYN_SENT) sk->sk_err = ECONNRESET; @@ -2208,6 +2451,15 @@ if (!(sk->sk_userlocks & SOCK_BINDADDR_LOCK)) inet_reset_saddr(sk); +#if defined(CONFIG_BCM_MPTCP) && defined(CONFIG_BCM_KF_MPTCP) + if (is_meta_sk(sk)) { + mptcp_disconnect(sk); + } else { + if (tp->inside_tk_table) + mptcp_hash_remove_bh(tp); + } + +#endif sk->sk_shutdown = 0; sock_reset_flag(sk, SOCK_DONE); tp->srtt_us = 0; @@ -2352,6 +2604,18 @@ lock_sock(sk); switch (optname) { +#if defined(CONFIG_BCM_KF_SPEEDYGET) && defined(CONFIG_BCM_SPEEDYGET) + case TCP_NOCOPY: + { + if(val < 0 || val > 1) + { + err = -EINVAL; + break; + } + tp->tcp_nocopy = val; + break; + } +#endif case TCP_MAXSEG: /* Values greater than interface MTU won't take effect. However * at the point when this call is done we typically don't yet @@ -2512,6 +2776,14 @@ break; case TCP_DEFER_ACCEPT: +#if defined(CONFIG_BCM_MPTCP) && defined(CONFIG_BCM_KF_MPTCP) + /* An established MPTCP-connection (mptcp(tp) only returns true + * if the socket is established) should not use DEFER on new + * subflows. + */ + if (mptcp(tp)) + break; +#endif /* Translate value in seconds to number of retransmits */ icsk->icsk_accept_queue.rskq_defer_accept = secs_to_retrans(val, TCP_TIMEOUT_INIT / HZ, @@ -2539,7 +2811,11 @@ (TCPF_ESTABLISHED | TCPF_CLOSE_WAIT) && inet_csk_ack_scheduled(sk)) { icsk->icsk_ack.pending |= ICSK_ACK_PUSHED; +#if !defined(CONFIG_BCM_MPTCP) || !defined(CONFIG_BCM_KF_MPTCP) tcp_cleanup_rbuf(sk, 1); +#else + tp->ops->cleanup_rbuf(sk, 1); +#endif if (!(val & 1)) icsk->icsk_ack.pingpong = 1; } @@ -2584,6 +2860,22 @@ tp->notsent_lowat = val; sk->sk_write_space(sk); break; +#if defined(CONFIG_BCM_MPTCP) && defined(CONFIG_BCM_KF_MPTCP) +#ifdef CONFIG_MPTCP + case MPTCP_ENABLED: + if (mptcp_init_failed || !sysctl_mptcp_enabled || + sk->sk_state != TCP_CLOSE) { + err = -EPERM; + break; + } + + if (val) + mptcp_enable_sock(sk); + else + mptcp_disable_sock(sk); + break; +#endif +#endif default: err = -ENOPROTOOPT; break; @@ -2848,6 +3140,13 @@ case TCP_NOTSENT_LOWAT: val = tp->notsent_lowat; break; +#if defined(CONFIG_BCM_MPTCP) && defined(CONFIG_BCM_KF_MPTCP) +#ifdef CONFIG_MPTCP + case MPTCP_ENABLED: + val = sock_flag(sk, SOCK_MPTCP) ? 1 : 0; + break; +#endif +#endif default: return -ENOPROTOOPT; } @@ -3018,6 +3317,9 @@ if (sk->sk_state == TCP_SYN_SENT || sk->sk_state == TCP_SYN_RECV) TCP_INC_STATS_BH(sock_net(sk), TCP_MIB_ATTEMPTFAILS); +#if defined(CONFIG_BCM_MPTCP) && defined(CONFIG_BCM_KF_MPTCP) + WARN_ON(sk->sk_state == TCP_CLOSE); +#endif tcp_set_state(sk, TCP_CLOSE); tcp_clear_xmit_timers(sk); if (req) @@ -3065,6 +3367,10 @@ int max_rshare, max_wshare, cnt; unsigned int i; +#if defined(CONFIG_BCM_KF_MISC_BACKPORTS) +/*CVE-2019-11477*/ + BUILD_BUG_ON(TCP_MIN_SND_MSS <= MAX_TCP_OPTION_SPACE); +#endif //#if defined(CONFIG_BCM_KF_MISC_BACKPORTS) sock_skb_cb_check_size(sizeof(struct tcp_skb_cb)); percpu_counter_init(&tcp_sockets_allocated, 0, GFP_KERNEL); @@ -3136,5 +3442,7 @@ tcp_metrics_init(); BUG_ON(tcp_register_congestion_control(&tcp_reno) != 0); +#if !defined(CONFIG_BCM_KF_TCP_NO_TSQ) tcp_tasklet_init(); +#endif }