--- zzzz-none-000/linux-4.1.38/net/ipv6/tcp_ipv6.c 2017-01-18 18:48:06.000000000 +0000 +++ bcm63-7582-715/linux-4.1.38/net/ipv6/tcp_ipv6.c 2020-11-25 10:06:48.000000000 +0000 @@ -62,6 +62,10 @@ #include #include #include +#if defined(CONFIG_BCM_MPTCP) && defined(CONFIG_BCM_KF_MPTCP) +#include +#include +#endif #include #include @@ -70,6 +74,7 @@ #include #include +#if !defined(CONFIG_BCM_MPTCP) || !defined(CONFIG_BCM_KF_MPTCP) static void tcp_v6_send_reset(struct sock *sk, struct sk_buff *skb); static void tcp_v6_reqsk_send_ack(struct sock *sk, struct sk_buff *skb, struct request_sock *req); @@ -78,6 +83,7 @@ static const struct inet_connection_sock_af_ops ipv6_mapped; static const struct inet_connection_sock_af_ops ipv6_specific; +#endif #ifdef CONFIG_TCP_MD5SIG static const struct tcp_sock_af_ops tcp_sock_ipv6_specific; static const struct tcp_sock_af_ops tcp_sock_ipv6_mapped_specific; @@ -89,7 +95,11 @@ } #endif +#if !defined(CONFIG_BCM_MPTCP) || !defined(CONFIG_BCM_KF_MPTCP) static void inet6_sk_rx_dst_set(struct sock *sk, const struct sk_buff *skb) +#else +void inet6_sk_rx_dst_set(struct sock *sk, const struct sk_buff *skb) +#endif { struct dst_entry *dst = skb_dst(skb); @@ -111,7 +121,11 @@ tcp_hdr(skb)->source); } +#if !defined(CONFIG_BCM_MPTCP) || !defined(CONFIG_BCM_KF_MPTCP) static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr, +#else +int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr, +#endif int addr_len) { struct sockaddr_in6 *usin = (struct sockaddr_in6 *) uaddr; @@ -204,7 +218,16 @@ sin.sin_port = usin->sin6_port; sin.sin_addr.s_addr = usin->sin6_addr.s6_addr32[3]; +#if !defined(CONFIG_BCM_MPTCP) || !defined(CONFIG_BCM_KF_MPTCP) icsk->icsk_af_ops = &ipv6_mapped; +#else +#ifdef CONFIG_MPTCP + if (sock_flag(sk, SOCK_MPTCP)) + icsk->icsk_af_ops = &mptcp_v6_mapped; + else +#endif + icsk->icsk_af_ops = &ipv6_mapped; +#endif sk->sk_backlog_rcv = tcp_v4_do_rcv; #ifdef CONFIG_TCP_MD5SIG tp->af_specific = &tcp_sock_ipv6_mapped_specific; @@ -214,7 +237,16 @@ if (err) { icsk->icsk_ext_hdr_len = exthdrlen; +#if !defined(CONFIG_BCM_MPTCP) || !defined(CONFIG_BCM_KF_MPTCP) icsk->icsk_af_ops = &ipv6_specific; +#else +#ifdef CONFIG_MPTCP + if (sock_flag(sk, SOCK_MPTCP)) + icsk->icsk_af_ops = &mptcp_v6_specific; + else +#endif + icsk->icsk_af_ops = &ipv6_specific; +#endif sk->sk_backlog_rcv = tcp_v6_do_rcv; #ifdef CONFIG_TCP_MD5SIG tp->af_specific = &tcp_sock_ipv6_specific; @@ -303,7 +335,11 @@ return err; } +#if !defined(CONFIG_BCM_MPTCP) || !defined(CONFIG_BCM_KF_MPTCP) static void tcp_v6_mtu_reduced(struct sock *sk) +#else +void tcp_v6_mtu_reduced(struct sock *sk) +#endif { struct dst_entry *dst; @@ -330,7 +366,11 @@ struct ipv6_pinfo *np; struct tcp_sock *tp; __u32 seq, snd_una; +#if !defined(CONFIG_BCM_MPTCP) || !defined(CONFIG_BCM_KF_MPTCP) struct sock *sk; +#else + struct sock *sk, *meta_sk; +#endif int err; sk = __inet6_lookup_established(net, &tcp_hashinfo, @@ -352,8 +392,19 @@ if (sk->sk_state == TCP_NEW_SYN_RECV) return tcp_req_err(sk, seq); +#if !defined(CONFIG_BCM_MPTCP) || !defined(CONFIG_BCM_KF_MPTCP) bh_lock_sock(sk); if (sock_owned_by_user(sk) && type != ICMPV6_PKT_TOOBIG) +#else + tp = tcp_sk(sk); + if (mptcp(tp)) + meta_sk = mptcp_meta_sk(sk); + else + meta_sk = sk; + + bh_lock_sock(meta_sk); + if (sock_owned_by_user(meta_sk) && type != ICMPV6_PKT_TOOBIG) +#endif NET_INC_STATS_BH(net, LINUX_MIB_LOCKDROPPEDICMPS); if (sk->sk_state == TCP_CLOSE) @@ -364,7 +415,9 @@ goto out; } +#if !defined(CONFIG_BCM_MPTCP) || !defined(CONFIG_BCM_KF_MPTCP) tp = tcp_sk(sk); +#endif /* XXX (TFO) - tp->snd_una should be ISN (tcp_create_openreq_child() */ fastopen = tp->fastopen_rsk; snd_una = fastopen ? tcp_rsk(fastopen)->snt_isn : tp->snd_una; @@ -396,11 +449,27 @@ goto out; tp->mtu_info = ntohl(info); +#if !defined(CONFIG_BCM_MPTCP) || !defined(CONFIG_BCM_KF_MPTCP) if (!sock_owned_by_user(sk)) +#else + if (!sock_owned_by_user(meta_sk)) +#endif tcp_v6_mtu_reduced(sk); +#if !defined(CONFIG_BCM_MPTCP) || !defined(CONFIG_BCM_KF_MPTCP) else if (!test_and_set_bit(TCP_MTU_REDUCED_DEFERRED, +#else + else { + if (!test_and_set_bit(TCP_MTU_REDUCED_DEFERRED, +#endif &tp->tsq_flags)) +#if !defined(CONFIG_BCM_MPTCP) || !defined(CONFIG_BCM_KF_MPTCP) sock_hold(sk); +#else + sock_hold(sk); + if (mptcp(tp)) + mptcp_tsq_flags(sk); + } +#endif goto out; } @@ -416,7 +485,11 @@ if (fastopen && !fastopen->sk) break; +#if !defined(CONFIG_BCM_MPTCP) || !defined(CONFIG_BCM_KF_MPTCP) if (!sock_owned_by_user(sk)) { +#else + if (!sock_owned_by_user(meta_sk)) { +#endif sk->sk_err = err; sk->sk_error_report(sk); /* Wake people up to see the error (see connect in sock.c) */ @@ -426,23 +499,39 @@ goto out; } +#if !defined(CONFIG_BCM_MPTCP) || !defined(CONFIG_BCM_KF_MPTCP) if (!sock_owned_by_user(sk) && np->recverr) { +#else + if (!sock_owned_by_user(meta_sk) && np->recverr) { +#endif sk->sk_err = err; sk->sk_error_report(sk); } else sk->sk_err_soft = err; out: +#if !defined(CONFIG_BCM_MPTCP) || !defined(CONFIG_BCM_KF_MPTCP) bh_unlock_sock(sk); +#else + bh_unlock_sock(meta_sk); +#endif sock_put(sk); } +#if !defined(CONFIG_BCM_MPTCP) || !defined(CONFIG_BCM_KF_MPTCP) static int tcp_v6_send_synack(struct sock *sk, struct dst_entry *dst, struct flowi *fl, struct request_sock *req, u16 queue_mapping, struct tcp_fastopen_cookie *foc) +#else +int tcp_v6_send_synack(struct sock *sk, struct dst_entry *dst, + struct flowi *fl, + struct request_sock *req, + u16 queue_mapping, + struct tcp_fastopen_cookie *foc) +#endif { struct inet_request_sock *ireq = inet_rsk(req); struct ipv6_pinfo *np = inet6_sk(sk); @@ -470,14 +559,22 @@ np->tclass); rcu_read_unlock(); err = net_xmit_eval(err); +#if defined(CONFIG_BCM_MPTCP) && defined(CONFIG_BCM_KF_MPTCP) + if (!tcp_rsk(req)->snt_synack && !err) + tcp_rsk(req)->snt_synack = tcp_time_stamp; +#endif } done: return err; } +#if !defined(CONFIG_BCM_MPTCP) || !defined(CONFIG_BCM_KF_MPTCP) static void tcp_v6_reqsk_destructor(struct request_sock *req) +#else +void tcp_v6_reqsk_destructor(struct request_sock *req) +#endif { kfree_skb(inet_rsk(req)->pktopts); } @@ -670,8 +767,13 @@ } #endif +#if !defined(CONFIG_BCM_MPTCP) || !defined(CONFIG_BCM_KF_MPTCP) static void tcp_v6_init_req(struct request_sock *req, struct sock *sk, struct sk_buff *skb) +#else +static int tcp_v6_init_req(struct request_sock *req, struct sock *sk, + struct sk_buff *skb, bool want_cookie) +#endif { struct inet_request_sock *ireq = inet_rsk(req); struct ipv6_pinfo *np = inet6_sk(sk); @@ -692,6 +794,10 @@ atomic_inc(&skb->users); ireq->pktopts = skb; } +#if defined(CONFIG_BCM_MPTCP) && defined(CONFIG_BCM_KF_MPTCP) + + return 0; +#endif } static struct dst_entry *tcp_v6_route_req(struct sock *sk, struct flowi *fl, @@ -713,7 +819,11 @@ .syn_ack_timeout = tcp_syn_ack_timeout, }; +#if !defined(CONFIG_BCM_MPTCP) || !defined(CONFIG_BCM_KF_MPTCP) static const struct tcp_request_sock_ops tcp_request_sock_ipv6_ops = { +#else +const struct tcp_request_sock_ops tcp_request_sock_ipv6_ops = { +#endif .mss_clamp = IPV6_MIN_MTU - sizeof(struct tcphdr) - sizeof(struct ipv6hdr), #ifdef CONFIG_TCP_MD5SIG @@ -731,9 +841,17 @@ }; static void tcp_v6_send_response(struct sock *sk, struct sk_buff *skb, u32 seq, +#if !defined(CONFIG_BCM_MPTCP) || !defined(CONFIG_BCM_KF_MPTCP) u32 ack, u32 win, u32 tsval, u32 tsecr, +#else + u32 ack, u32 data_ack, u32 win, u32 tsval, u32 tsecr, +#endif int oif, struct tcp_md5sig_key *key, int rst, +#if !defined(CONFIG_BCM_MPTCP) || !defined(CONFIG_BCM_KF_MPTCP) u8 tclass, u32 label) +#else + u8 tclass, u32 label, int mptcp) +#endif { const struct tcphdr *th = tcp_hdr(skb); struct tcphdr *t1; @@ -751,7 +869,12 @@ if (key) tot_len += TCPOLEN_MD5SIG_ALIGNED; #endif - +#if defined(CONFIG_BCM_MPTCP) && defined(CONFIG_BCM_KF_MPTCP) +#ifdef CONFIG_MPTCP + if (mptcp) + tot_len += MPTCP_SUB_LEN_DSS + MPTCP_SUB_LEN_ACK; +#endif +#endif buff = alloc_skb(MAX_HEADER + sizeof(struct ipv6hdr) + tot_len, GFP_ATOMIC); if (!buff) @@ -789,9 +912,24 @@ tcp_v6_md5_hash_hdr((__u8 *)topt, key, &ipv6_hdr(skb)->saddr, &ipv6_hdr(skb)->daddr, t1); +#if defined(CONFIG_BCM_MPTCP) && defined(CONFIG_BCM_KF_MPTCP) + topt += 4; +#endif } #endif +#if defined(CONFIG_BCM_MPTCP) && defined(CONFIG_BCM_KF_MPTCP) +#ifdef CONFIG_MPTCP + if (mptcp) { + /* Construction of 32-bit data_ack */ + *topt++ = htonl((TCPOPT_MPTCP << 24) | + ((MPTCP_SUB_LEN_DSS + MPTCP_SUB_LEN_ACK) << 16) | + (0x20 << 8) | + (0x01)); + *topt++ = htonl(data_ack); + } +#endif +#endif memset(&fl6, 0, sizeof(fl6)); fl6.daddr = ipv6_hdr(skb)->saddr; fl6.saddr = ipv6_hdr(skb)->daddr; @@ -829,7 +967,11 @@ kfree_skb(buff); } +#if !defined(CONFIG_BCM_MPTCP) || !defined(CONFIG_BCM_KF_MPTCP) static void tcp_v6_send_reset(struct sock *sk, struct sk_buff *skb) +#else +void tcp_v6_send_reset(struct sock *sk, struct sk_buff *skb) +#endif { const struct tcphdr *th = tcp_hdr(skb); u32 seq = 0, ack_seq = 0; @@ -889,7 +1031,11 @@ (th->doff << 2); oif = sk ? sk->sk_bound_dev_if : 0; +#if !defined(CONFIG_BCM_MPTCP) || !defined(CONFIG_BCM_KF_MPTCP) tcp_v6_send_response(sk, skb, seq, ack_seq, 0, 0, 0, oif, key, 1, 0, 0); +#else + tcp_v6_send_response(sk, skb, seq, ack_seq, 0, 0, 0, 0, oif, key, 1, 0, 0, 0); +#endif #ifdef CONFIG_TCP_MD5SIG release_sk1: @@ -901,44 +1047,91 @@ } static void tcp_v6_send_ack(struct sock *sk, struct sk_buff *skb, u32 seq, +#if !defined(CONFIG_BCM_MPTCP) || !defined(CONFIG_BCM_KF_MPTCP) u32 ack, u32 win, u32 tsval, u32 tsecr, int oif, +#else + u32 ack, u32 data_ack, u32 win, u32 tsval, u32 tsecr, int oif, +#endif struct tcp_md5sig_key *key, u8 tclass, +#if !defined(CONFIG_BCM_MPTCP) || !defined(CONFIG_BCM_KF_MPTCP) u32 label) +#else + u32 label, int mptcp) +#endif { +#if !defined(CONFIG_BCM_MPTCP) || !defined(CONFIG_BCM_KF_MPTCP) tcp_v6_send_response(sk, skb, seq, ack, win, tsval, tsecr, oif, key, 0, tclass, label); +#else + tcp_v6_send_response(sk, skb, seq, ack, data_ack, win, tsval, tsecr, oif, + key, 0, tclass, label, mptcp); +#endif } static void tcp_v6_timewait_ack(struct sock *sk, struct sk_buff *skb) { struct inet_timewait_sock *tw = inet_twsk(sk); struct tcp_timewait_sock *tcptw = tcp_twsk(sk); +#if defined(CONFIG_BCM_MPTCP) && defined(CONFIG_BCM_KF_MPTCP) + u32 data_ack = 0; + int mptcp = 0; +#endif +#if defined(CONFIG_BCM_MPTCP) && defined(CONFIG_BCM_KF_MPTCP) + if (tcptw->mptcp_tw && tcptw->mptcp_tw->meta_tw) { + data_ack = (u32)tcptw->mptcp_tw->rcv_nxt; + mptcp = 1; + } +#endif tcp_v6_send_ack(sk, skb, tcptw->tw_snd_nxt, tcptw->tw_rcv_nxt, +#if defined(CONFIG_BCM_MPTCP) && defined(CONFIG_BCM_KF_MPTCP) + data_ack, +#endif tcptw->tw_rcv_wnd >> tw->tw_rcv_wscale, tcp_time_stamp + tcptw->tw_ts_offset, tcptw->tw_ts_recent, tw->tw_bound_dev_if, tcp_twsk_md5_key(tcptw), +#if !defined(CONFIG_BCM_MPTCP) || !defined(CONFIG_BCM_KF_MPTCP) tw->tw_tclass, cpu_to_be32(tw->tw_flowlabel)); +#else + tw->tw_tclass, cpu_to_be32(tw->tw_flowlabel), mptcp); +#endif inet_twsk_put(tw); } +#if !defined(CONFIG_BCM_MPTCP) || !defined(CONFIG_BCM_KF_MPTCP) static void tcp_v6_reqsk_send_ack(struct sock *sk, struct sk_buff *skb, struct request_sock *req) +#else +void tcp_v6_reqsk_send_ack(struct sock *sk, struct sk_buff *skb, + struct request_sock *req) +#endif { /* sk->sk_state == TCP_LISTEN -> for regular TCP_SYN_RECV * sk->sk_state == TCP_SYN_RECV -> for Fast Open. */ tcp_v6_send_ack(sk, skb, (sk->sk_state == TCP_LISTEN) ? tcp_rsk(req)->snt_isn + 1 : tcp_sk(sk)->snd_nxt, +#if !defined(CONFIG_BCM_MPTCP) || !defined(CONFIG_BCM_KF_MPTCP) tcp_rsk(req)->rcv_nxt, req->rcv_wnd, +#else + tcp_rsk(req)->rcv_nxt, 0, req->rcv_wnd, +#endif tcp_time_stamp, req->ts_recent, sk->sk_bound_dev_if, tcp_v6_md5_do_lookup(sk, &ipv6_hdr(skb)->daddr), +#if !defined(CONFIG_BCM_MPTCP) || !defined(CONFIG_BCM_KF_MPTCP) 0, 0); +#else + 0, 0, 0); +#endif } +#if !defined(CONFIG_BCM_MPTCP) || !defined(CONFIG_BCM_KF_MPTCP) static struct sock *tcp_v6_hnd_req(struct sock *sk, struct sk_buff *skb) +#else +struct sock *tcp_v6_hnd_req(struct sock *sk, struct sk_buff *skb) +#endif { const struct tcphdr *th = tcp_hdr(skb); struct request_sock *req; @@ -961,6 +1154,13 @@ if (nsk) { if (nsk->sk_state != TCP_TIME_WAIT) { +#if defined(CONFIG_BCM_MPTCP) && defined(CONFIG_BCM_KF_MPTCP) + /* Don't lock again the meta-sk. It has been locked + * before mptcp_v6_do_rcv. + */ + if (mptcp(tcp_sk(nsk)) && !is_meta_sk(sk)) + bh_lock_sock(mptcp_meta_sk(nsk)); +#endif bh_lock_sock(nsk); return nsk; } @@ -975,7 +1175,11 @@ return sk; } +#if !defined(CONFIG_BCM_MPTCP) || !defined(CONFIG_BCM_KF_MPTCP) static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb) +#else +int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb) +#endif { if (skb->protocol == htons(ETH_P_IP)) return tcp_v4_conn_request(sk, skb); @@ -991,9 +1195,15 @@ return 0; /* don't send reset */ } +#if !defined(CONFIG_BCM_MPTCP) || !defined(CONFIG_BCM_KF_MPTCP) static struct sock *tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb, struct request_sock *req, struct dst_entry *dst) +#else +struct sock *tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb, + struct request_sock *req, + struct dst_entry *dst) +#endif { struct inet_request_sock *ireq; struct ipv6_pinfo *newnp, *np = inet6_sk(sk); @@ -1028,7 +1238,19 @@ newnp->saddr = newsk->sk_v6_rcv_saddr; +#if !defined(CONFIG_BCM_MPTCP) || !defined(CONFIG_BCM_KF_MPTCP) inet_csk(newsk)->icsk_af_ops = &ipv6_mapped; +#else +#ifdef CONFIG_MPTCP + /* We must check on the request-socket because the listener + * socket's flag may have been changed halfway through. + */ + if (!inet_rsk(req)->saw_mpc) + inet_csk(newsk)->icsk_af_ops = &mptcp_v6_mapped; + else +#endif + inet_csk(newsk)->icsk_af_ops = &ipv6_mapped; +#endif newsk->sk_backlog_rcv = tcp_v4_do_rcv; #ifdef CONFIG_TCP_MD5SIG newtp->af_specific = &tcp_sock_ipv6_mapped_specific; @@ -1074,6 +1296,16 @@ if (!newsk) goto out_nonewsk; +#if defined(CONFIG_BCM_MPTCP) && defined(CONFIG_BCM_KF_MPTCP) +#ifdef CONFIG_MPTCP + /* If the meta_sk is v6-mapped we can end up here with the wrong af_ops. + * Just make sure that this subflow is v6. + */ + if (is_meta_sk(sk)) + inet_csk(newsk)->icsk_af_ops = &mptcp_v6_specific; +#endif + +#endif /* * No need to charge this sock to the relevant IPv6 refcnt debug socks * count here, tcp_create_openreq_child now does this for us, see the @@ -1198,7 +1430,11 @@ * This is because we cannot sleep with the original spinlock * held. */ +#if !defined(CONFIG_BCM_MPTCP) || !defined(CONFIG_BCM_KF_MPTCP) static int tcp_v6_do_rcv(struct sock *sk, struct sk_buff *skb) +#else +int tcp_v6_do_rcv(struct sock *sk, struct sk_buff *skb) +#endif { struct ipv6_pinfo *np = inet6_sk(sk); struct tcp_sock *tp; @@ -1215,6 +1451,11 @@ if (skb->protocol == htons(ETH_P_IP)) return tcp_v4_do_rcv(sk, skb); +#if defined(CONFIG_BCM_MPTCP) && defined(CONFIG_BCM_KF_MPTCP) + if (is_meta_sk(sk)) + return mptcp_v6_do_rcv(sk, skb); + +#endif if (sk_filter(sk, skb)) goto discard; @@ -1350,6 +1591,12 @@ TCP_SKB_CB(skb)->end_seq = (TCP_SKB_CB(skb)->seq + th->syn + th->fin + skb->len - th->doff*4); TCP_SKB_CB(skb)->ack_seq = ntohl(th->ack_seq); +#if defined(CONFIG_BCM_MPTCP) && defined(CONFIG_BCM_KF_MPTCP) +#ifdef CONFIG_MPTCP + TCP_SKB_CB(skb)->mptcp_flags = 0; + TCP_SKB_CB(skb)->dss_off = 0; +#endif +#endif TCP_SKB_CB(skb)->tcp_flags = tcp_flag_byte(th); TCP_SKB_CB(skb)->tcp_tw_isn = 0; TCP_SKB_CB(skb)->ip_dsfield = ipv6_get_dsfield(hdr); @@ -1369,7 +1616,11 @@ { const struct tcphdr *th; const struct ipv6hdr *hdr; +#if !defined(CONFIG_BCM_MPTCP) || !defined(CONFIG_BCM_KF_MPTCP) struct sock *sk; +#else + struct sock *sk, *meta_sk = NULL; +#endif int ret; struct net *net = dev_net(skb->dev); @@ -1403,9 +1654,18 @@ goto no_tcp_socket; process: +#if !defined(CONFIG_BCM_MPTCP) || !defined(CONFIG_BCM_KF_MPTCP) if (sk->sk_state == TCP_TIME_WAIT) +#else + if (sk && sk->sk_state == TCP_TIME_WAIT) +#endif goto do_time_wait; +#if defined(CONFIG_BCM_MPTCP) && defined(CONFIG_BCM_KF_MPTCP) + if (!sk) + goto no_tcp_socket; + +#endif if (hdr->hop_limit < inet6_sk(sk)->min_hopcount) { NET_INC_STATS_BH(net, LINUX_MIB_TCPMINTTLDROP); goto discard_and_relse; @@ -1416,6 +1676,17 @@ tcp_v6_fill_cb(skb, hdr, th); +#if defined(CONFIG_BCM_MPTCP) && defined(CONFIG_BCM_KF_MPTCP) +#ifdef CONFIG_MPTCP + /* Is there a pending request sock for this segment ? */ + if (sk->sk_state == TCP_LISTEN && mptcp_check_req(skb, net)) { + if (sk) + sock_put(sk); + return 0; + } +#endif + +#endif #ifdef CONFIG_TCP_MD5SIG if (tcp_v6_inbound_md5_hash(sk, skb)) goto discard_and_relse; @@ -1427,18 +1698,48 @@ sk_incoming_cpu_update(sk); skb->dev = NULL; +#if !defined(CONFIG_BCM_MPTCP) || !defined(CONFIG_BCM_KF_MPTCP) bh_lock_sock_nested(sk); +#else + if (mptcp(tcp_sk(sk))) { + meta_sk = mptcp_meta_sk(sk); + + bh_lock_sock_nested(meta_sk); + if (sock_owned_by_user(meta_sk)) + skb->sk = sk; + } else { + meta_sk = sk; + bh_lock_sock_nested(sk); + } + +#endif ret = 0; +#if !defined(CONFIG_BCM_MPTCP) || !defined(CONFIG_BCM_KF_MPTCP) if (!sock_owned_by_user(sk)) { if (!tcp_prequeue(sk, skb)) +#else + if (!sock_owned_by_user(meta_sk)) { + if (!tcp_prequeue(meta_sk, skb)) +#endif ret = tcp_v6_do_rcv(sk, skb); +#if !defined(CONFIG_BCM_MPTCP) || !defined(CONFIG_BCM_KF_MPTCP) } else if (unlikely(sk_add_backlog(sk, skb, sk->sk_rcvbuf + sk->sk_sndbuf))) { bh_unlock_sock(sk); +#else + } else if (unlikely(sk_add_backlog(meta_sk, skb, + meta_sk->sk_rcvbuf + meta_sk->sk_sndbuf))) { + bh_unlock_sock(meta_sk); +#endif NET_INC_STATS_BH(net, LINUX_MIB_TCPBACKLOGDROP); goto discard_and_relse; } +#if !defined(CONFIG_BCM_MPTCP) || !defined(CONFIG_BCM_KF_MPTCP) bh_unlock_sock(sk); +#else + + bh_unlock_sock(meta_sk); +#endif sock_put(sk); return ret ? -1 : 0; @@ -1449,6 +1750,28 @@ tcp_v6_fill_cb(skb, hdr, th); +#if defined(CONFIG_BCM_MPTCP) && defined(CONFIG_BCM_KF_MPTCP) +#ifdef CONFIG_MPTCP + if (!sk && th->syn && !th->ack) { + int ret = mptcp_lookup_join(skb, NULL); + + if (ret < 0) { + tcp_v6_send_reset(NULL, skb); + goto discard_it; + } else if (ret > 0) { + return 0; + } + } + + /* Is there a pending request sock for this segment ? */ + if (!sk && mptcp_check_req(skb, net)) { + if (sk) + sock_put(sk); + return 0; + } +#endif + +#endif if (skb->len < (th->doff<<2) || tcp_checksum_complete(skb)) { csum_error: TCP_INC_STATS_BH(net, TCP_MIB_CSUMERRORS); @@ -1500,6 +1823,20 @@ tcp_v6_restore_cb(skb); goto process; } +#if defined(CONFIG_BCM_MPTCP) && defined(CONFIG_BCM_KF_MPTCP) +#ifdef CONFIG_MPTCP + if (th->syn && !th->ack) { + int ret = mptcp_lookup_join(skb, inet_twsk(sk)); + + if (ret < 0) { + tcp_v6_send_reset(NULL, skb); + goto discard_it; + } else if (ret > 0) { + return 0; + } + } +#endif +#endif /* Fall through to ACK */ } case TCP_TW_ACK: @@ -1552,13 +1889,21 @@ } } +#if !defined(CONFIG_BCM_MPTCP) || !defined(CONFIG_BCM_KF_MPTCP) static struct timewait_sock_ops tcp6_timewait_sock_ops = { +#else +struct timewait_sock_ops tcp6_timewait_sock_ops = { +#endif .twsk_obj_size = sizeof(struct tcp6_timewait_sock), .twsk_unique = tcp_twsk_unique, .twsk_destructor = tcp_twsk_destructor, }; +#if !defined(CONFIG_BCM_MPTCP) || !defined(CONFIG_BCM_KF_MPTCP) static const struct inet_connection_sock_af_ops ipv6_specific = { +#else +const struct inet_connection_sock_af_ops ipv6_specific = { +#endif .queue_xmit = inet6_csk_xmit, .send_check = tcp_v6_send_check, .rebuild_header = inet6_sk_rebuild_header, @@ -1590,7 +1935,11 @@ /* * TCP over IPv4 via INET6 API */ +#if !defined(CONFIG_BCM_MPTCP) || !defined(CONFIG_BCM_KF_MPTCP) static const struct inet_connection_sock_af_ops ipv6_mapped = { +#else +const struct inet_connection_sock_af_ops ipv6_mapped = { +#endif .queue_xmit = ip_queue_xmit, .send_check = tcp_v4_send_check, .rebuild_header = inet_sk_rebuild_header, @@ -1627,7 +1976,16 @@ tcp_init_sock(sk); +#if !defined(CONFIG_BCM_MPTCP) || !defined(CONFIG_BCM_KF_MPTCP) icsk->icsk_af_ops = &ipv6_specific; +#else +#ifdef CONFIG_MPTCP + if (sock_flag(sk, SOCK_MPTCP)) + icsk->icsk_af_ops = &mptcp_v6_specific; + else +#endif + icsk->icsk_af_ops = &ipv6_specific; +#endif #ifdef CONFIG_TCP_MD5SIG tcp_sk(sk)->af_specific = &tcp_sock_ipv6_specific; @@ -1636,7 +1994,11 @@ return 0; } +#if !defined(CONFIG_BCM_MPTCP) || !defined(CONFIG_BCM_KF_MPTCP) static void tcp_v6_destroy_sock(struct sock *sk) +#else +void tcp_v6_destroy_sock(struct sock *sk) +#endif { tcp_v4_destroy_sock(sk); inet6_destroy_sock(sk); @@ -1823,12 +2185,34 @@ static void tcp_v6_clear_sk(struct sock *sk, int size) { struct inet_sock *inet = inet_sk(sk); +#if defined(CONFIG_BCM_MPTCP) && defined(CONFIG_BCM_KF_MPTCP) +#ifdef CONFIG_MPTCP + struct tcp_sock *tp = tcp_sk(sk); + /* size_tk_table goes from the end of tk_table to the end of sk */ + int size_tk_table = size - offsetof(struct tcp_sock, tk_table) - + sizeof(tp->tk_table); +#endif +#endif /* we do not want to clear pinet6 field, because of RCU lookups */ sk_prot_clear_nulls(sk, offsetof(struct inet_sock, pinet6)); size -= offsetof(struct inet_sock, pinet6) + sizeof(inet->pinet6); +#if defined(CONFIG_BCM_MPTCP) && defined(CONFIG_BCM_KF_MPTCP) + +#ifdef CONFIG_MPTCP + /* We zero out only from pinet6 to tk_table */ + size -= size_tk_table + sizeof(tp->tk_table); +#endif +#endif memset(&inet->pinet6 + 1, 0, size); +#if defined(CONFIG_BCM_MPTCP) && defined(CONFIG_BCM_KF_MPTCP) + +#ifdef CONFIG_MPTCP + memset((char *)&tp->tk_table + sizeof(tp->tk_table), 0, size_tk_table); +#endif + +#endif } struct proto tcpv6_prot = {