+-------------------------------+ | Application | +---------------+ +-------------------------------+ | Application | | MPTCP | +---------------+ + - - - - - - - + - - - - - - - + | TCP | | Subflow (TCP) | Subflow (TCP) | +---------------+ +-------------------------------+ | IP | | IP | IP | +---------------+ +-------------------------------+ Figure 1: Comparison of Standard TCP and MPTCP Protocol Stacks
1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +--------------------------------------------------------------+ | | | Data Sequence Number (8 octets) | | | +--------------------------------------------------------------+ | Subflow Sequence Number (4 octets) | +-------------------------------+------------------------------+ | Data-Level Length (2 octets) | Zeros (2 octets) | +-------------------------------+------------------------------+
"net/mptcp/mptcp_output.c" line 318 of 1667 318 static int mptcp_write_dss_mapping(struct tcp_sock *tp, struct sk_buff *skb, 319 __be32 *ptr) 320 { 321 struct tcp_skb_cb *tcb = TCP_SKB_CB(skb); 322 __be32 *start = ptr; 323 __u16 data_len; 324 325 *ptr++ = htonl(tcb->seq); /* data_seq */ 326 327 /* If it's a non-data DATA_FIN, we set subseq to 0 (draft v7) */ 328 if (mptcp_is_data_fin(skb) && skb->len == 0) 329 *ptr++ = 0; /* subseq */ 330 else 331 *ptr++ = htonl(tp->write_seq - tp->mptcp->snt_isn); /* subseq */ 332
"net/ipv4/tcp_ipv4.c" line 1735 of 2581 1735 if (mptcp(tcp_sk(sk))) { 1736 meta_sk = mptcp_meta_sk(sk); 1737 1738 bh_lock_sock_nested(meta_sk); 1739 if (sock_owned_by_user(meta_sk)) 1740 skb->sk = sk; 1741 } else { 1742 meta_sk = sk; 1743 bh_lock_sock_nested(sk); 1744 } 1745 1746 ret = 0; 1747 if (!sock_owned_by_user(meta_sk)) { 1748 #ifdef CONFIG_NET_DMA 1749 struct tcp_sock *tp = tcp_sk(meta_sk); 1750 if (!tp->ucopy.dma_chan && tp->ucopy.pinned_list) 1751 tp->ucopy.dma_chan = net_dma_find_channel(); 1752 if (tp->ucopy.dma_chan) 1753 ret = tcp_v4_do_rcv(sk, skb); 1754 else 1755 #endif 1756 { 1757 if (!tcp_prequeue(meta_sk, skb)) 1758 ret = tcp_v4_do_rcv(sk, skb); 1759 } 1760 } else if (unlikely(sk_add_backlog(meta_sk, skb, 1761 meta_sk->sk_rcvbuf + meta_sk->sk_sndbuf))) { 1762 bh_unlock_sock(meta_sk); 1763 NET_INC_STATS_BH(net, LINUX_MIB_TCPBACKLOGDROP); 1764 goto discard_and_relse; 1765 } 1766 bh_unlock_sock(meta_sk);
The Data ACK is analogous to the behavior of the standard TCP
cumulative ACK -- indicating how much data has been successfully received (with no holes). The Data ACK specifies the next data sequence number it expects to
receive.