MPTCP 源碼分析(三) 子路徑選擇

簡述:
     支持MPTCP的鏈路中存在多條子路徑,所以在發送數據的時候須要選擇最優路徑來進行操做。
MPTCP利用內核通知鏈對MPTCP中各子路徑進行增長路徑、刪除路徑、修改路徑優先級的操做。MPTCP根據
相應的策略進行路徑選擇。
 
路徑選擇的代碼實現
     路徑選擇的關鍵在於從多個子路徑中選擇其中一個進行數據的發送。此過程經過下面的函數實現:
"net/mptcp/mptcp_sched.c" line 114 of 496
114 static struct sock *get_available_subflow(struct sock *meta_sk,
115                       struct sk_buff *skb,
116                       bool zero_wnd_test)
117 {
118     struct mptcp_cb *mpcb = tcp_sk(meta_sk)->mpcb;   //MPTCP內核實現的三個組成部分之一:Multi-path control bock(mpcb) 
119     struct sock *sk, *bestsk = NULL, *lowpriosk = NULL, *backupsk = NULL;
120     u32 min_time_to_peer = 0xffffffff, lowprio_min_time_to_peer = 0xffffffff;
121     int cnt_backups = 0;
122
123     /* if there is only one subflow, bypass the scheduling function */    
124     if (mpcb->cnt_subflows == 1) {
125         bestsk = (struct sock *)mpcb->connection_list;
126         if (!mptcp_is_available(bestsk, skb, zero_wnd_test))
127             bestsk = NULL;
128         return bestsk;
129     }
130
131     /* Answer data_fin on same subflow!!! */
132     if (meta_sk->sk_shutdown & RCV_SHUTDOWN &&
133         skb && mptcp_is_data_fin(skb)) {
134         mptcp_for_each_sk(mpcb, sk) {
135             if (tcp_sk(sk)->mptcp->path_index == mpcb->dfin_path_index &&
136                 mptcp_is_available(sk, skb, zero_wnd_test))
137                 return sk;
138         }
139     }
View Code
第124行的代碼是處理只有一個子路徑的特殊狀況。第132行是對關閉操做進行了處理,在
收包過程當中對接收關閉包的子路徑進行記錄,而後回包的時候使用相同的子路徑。
"net/mptcp/mptcp_input.c" line 876 of 2293
875     /* Record it, because we want to send our data_fin on the same path */
876     if (tp->mptcp->map_data_fin) {
877         mpcb->dfin_path_index = tp->mptcp->path_index;
878         mpcb->dfin_combined = !!(sk->sk_shutdown & RCV_SHUTDOWN);
879     }
第876行是對子路徑關閉的處理,關於data_fin能夠參考https://tools.ietf.org/html/rfc6824#section-3.3.3。
 
下面的代碼遍歷mpcb下管理的sk,選擇最合適的sk。
"net/mptcp/mptcp_sched.c" line 142 of 496
141     /* First, find the best subflow */
142     mptcp_for_each_sk(mpcb, sk) {
143         struct tcp_sock *tp = tcp_sk(sk);
144
145         if (tp->mptcp->rcv_low_prio || tp->mptcp->low_prio)
146             cnt_backups++;
147
148         if ((tp->mptcp->rcv_low_prio || tp->mptcp->low_prio) &&
149             tp->srtt < lowprio_min_time_to_peer) {
150             if (!mptcp_is_available(sk, skb, zero_wnd_test))
151                 continue;
152
153             if (mptcp_dont_reinject_skb(tp, skb)) {
154                 backupsk = sk;
155                 continue;
156             }
157
158             lowprio_min_time_to_peer = tp->srtt;
159             lowpriosk = sk;
160         } else if (!(tp->mptcp->rcv_low_prio || tp->mptcp->low_prio) &&
161                tp->srtt < min_time_to_peer) {
162             if (!mptcp_is_available(sk, skb, zero_wnd_test))
163                 continue;
164
165             if (mptcp_dont_reinject_skb(tp, skb)) {
166                 backupsk = sk;
167                 continue;
168             }
169
170             min_time_to_peer = tp->srtt;
171             bestsk = sk;
172         }
173     }
View Code
從上面的代碼能夠看出,選擇sk的依據有5條:
1. 「tp->mptcp->rcv_low_prio 」 which stands for priority level in the remote machine.
2.  "tp->mptcp->low_prio" which stands for priority level in the local machine.
3.   whether the skb has already been enqueued into this subsocket
4.   "tp->srtt" stands for smoothed round trip time.
5.   mptcp_is_available() check the congestion of this subflow.
 
"net/mptcp/mptcp_sched.c" line 175 of 496
175     if (mpcb->cnt_established == cnt_backups && lowpriosk) {
176         sk = lowpriosk;  
177     } else if (bestsk) {
178         sk = bestsk;
179     } else if (backupsk) {
180         /* It has been sent on all subflows once - let's give it a
181          * chance again by restarting its pathmask.
182          */
183         if (skb)
184             TCP_SKB_CB(skb)->path_mask = 0;
185         sk = backupsk;
186     }
187
188     return sk;
189 }
View Code
第176行的狀況說明全部的子路徑都處於backup狀態。而第178行則是存在bestsk。
 
總結:
1.控制路徑選擇的因素有下面四個:
此路徑在對端機器的優先級
此路徑在本地的優先級
這次發送的skb是否已經使用此路徑發送過,不能在同一路徑重複發送。
tp->srtt
 
2.調整 low_prio 和 rcv_low_prio 能夠經過下面命令:
ip link set dev eth0 multipath backup
當通信雙方的一端被設置爲backup後,能夠經過MP_PRIO
通知對端。具體內容能夠參考:https://tools.ietf.org/html/rfc6824#section-3.3.8
 
3.srtt的調整經過函數 tcp_ack_update_rtt 實現。
相關文章
相關標籤/搜索