zoukankan      html  css  js  c++  java
  • MPTCP 源码分析(四) 发送和接收数据


    http://www.cnblogs.com/lxgeek/p/4330119.html


    简述:
         MPTCP在发送数据方面和TCP的区别是可以从多条路径中选择一条
    路径来发送数据。MPTCP在接收数据方面与TCP的区别是子路径对无序包
    进行重排后,MPTCP的mpcb需要多所有子路径的包进行排序。查看图1可知。
                                       +-------------------------------+
                                       |           Application         |
          +---------------+            +-------------------------------+
          |  Application  |            |             MPTCP             |
          +---------------+            + - - - - - - - + - - - - - - - +
          |      TCP      |            | Subflow (TCP) | Subflow (TCP) |
          +---------------+            +-------------------------------+
          |      IP       |            |       IP      |      IP       |
          +---------------+            +-------------------------------+
    
          Figure 1: Comparison of Standard TCP and MPTCP Protocol Stacks
    
     
     
    数据序号映射(Data Sequence Mapping) 
         由于所有的数据会通过不同的子路径发送,在接收端MPTCP需要对数据进行重新排序。
    因此我们需要数据序号映射。数据序号映射定义从子路径序列空间到数据序列空间的映射。
    子路径的序列空间是子路径自身的序列号,而数据序列空间维护着所有需发送的数据。如下图
      红色子路径上的子路径序号分别是1、2,其数据序号是1000、1002。而下面的蓝色的子路径上的子路径序号和
    数据序号分别是200,1001。这说明从下面的蓝色子路径已经发送了199个报文,而上面的红色子路径才开始发送。
    在MPTCP协议定义如下:
                          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)      |
         +-------------------------------+------------------------------+
    
     
     
    内核中的实现:
         函数mptcp_write_dss_mapping对 Data Sequeue Number  和  Subflow Sequence Number进行了赋值。实现如下:
    复制代码
    "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 
    复制代码
    第325行和331行分别对子路径序号和数据序号进行了赋值。
    ###
    data_seq and subseq
    The mapping is identify by the relative subflow seq, the data seq and
    the data len. Basically, it means that isn+sub_seq->isn+sub_seq+len at
    the subflow-level corresponds to data_seq->data_seq+len at the
    connection-level.
    ###
     
    数据接收中的重组
         内核使用三种队列接收数据,分别是:Backlog queue(sk->backlog)、Prequeue queue(tp->ucopy.prequeue)
    和 Receive queue (sk->receeive_queue)。MPTCP的实现增加了一个新的队列out-of-order queue对于各个子路径
    收到的数据进行重组。内核中 tcp_v4_rcv()的关键实现如下:
    复制代码
    "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);
    复制代码
    从第1757和1760可以看出skb只进入meta的backlog和prequeue,而和子路径的sock没有什么关系。因此,我们得出包的入队操作如下:
    1.进入meta_sk的backlog
    2.进入meta_sk的prequeue
    3.进入子路径的receive_queue
    第1和2种入队操作后续操作和正常TCP一致,如果是第3种情况,后续将通过函数mptcp_queue_skb()进入tcp_sk(meta_sk)->out_of_order_queue。
     
    结论:
    1.MPTCP利用自身的Data Sequeue Number  和  Subflow Sequence Number进行了数据在各种子路径间的传输。此实现独立于TCP。
    2.为了实现子路径的数据重组,MPTCP利用了队列out_of_order_queue。
     
       
     
     
    问题:
    1. DATA_ACK作用是?
    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.

  • 相关阅读:
    nginx防盗链配置
    nginx禁止非sever_name指定域名访问
    linux下配置python环境 django创建helloworld项目
    node解析修改ngix配置文件
    ~/.ssh/config文件的使用
    SpringCloud-Feign声明式服务调用
    Hystrix 配置参数全解析
    Eureka 的高级使用
    eureka中显示有服务但是通过ribbon调用显示No instances available for service-hello的问题
    EureKa:服务注册与发现
  • 原文地址:https://www.cnblogs.com/ztguang/p/12645836.html
Copyright © 2011-2022 走看看