簡述
TCP使用定時器函式tcp_retransmit_timer進行資料重發,MPTCP需要重發資料的時候,
不僅僅在原路徑傳送資料,而且會在另外一條子路徑進行重發。這樣考慮的原因是:
考慮網路中介軟體裝置的影響, 保證子路徑上資料序列號的完整性。目前的版本0.89依然如此實現,
以後應該會優化。
核心實現
MPTCP的結構如下圖所示:
如上圖所示:每一個slave subsock 和 master subsock實際上維持著一個正常的TCP鏈路,因此,他們都具有
重發定時器tcp_write_timer。MPTCP實現的思路就是:每個子鏈路傳送失敗的時候,將傳送失敗的SKB拷貝一份
到meta sock。然後讓meta sock 再次選擇另外一條子路徑傳送。
如下是對tcp_retransmit_timer的修改:
"net/ipv4/tcp_timer.c" line 488 of 691 487 488 out:; 489 if (mptcp(tp)) { 490 mptcp_reinject_data(sk, 1); 491 mptcp_set_rto(sk); 492 } 493 }
函式mptcp_reinject_data的實現如下:
"net/mptcp/mptcp_output.c" line 237 of 1667 236 /* Inserts data into the reinject queue */ 237 void mptcp_reinject_data(struct sock *sk, int clone_it) 238 { 239 struct sk_buff *skb_it, *tmp; 240 struct tcp_sock *tp = tcp_sk(sk); 241 struct sock *meta_sk = tp->meta_sk; 242 243 /* It has already been closed - there is really no point in reinjecting */ 244 if (meta_sk->sk_state == TCP_CLOSE) 245 return; 246 247 skb_queue_walk_safe(&sk->sk_write_queue, skb_it, tmp) { 248 struct tcp_skb_cb *tcb = TCP_SKB_CB(skb_it); 249 /* Subflow syn's and fin's are not reinjected. 250 * 251 * As well as empty subflow-fins with a data-fin. 252 * They are reinjected below (without the subflow-fin-flag) 253 */ 254 if (tcb->tcp_flags & TCPHDR_SYN || 255 (tcb->tcp_flags & TCPHDR_FIN && !mptcp_is_data_fin(skb_it)) || 256 (tcb->tcp_flags & TCPHDR_FIN && mptcp_is_data_fin(skb_it) && !skb_it->len)) 257 continue; 258 259 __mptcp_reinject_data(skb_it, meta_sk, sk, clone_it); 260 } 261 262 skb_it = tcp_write_queue_tail(meta_sk); 263 /* If sk has sent the empty data-fin, we have to reinject it too. */ 264 if (skb_it && mptcp_is_data_fin(skb_it) && skb_it->len == 0 && 265 TCP_SKB_CB(skb_it)->path_mask & mptcp_pi_to_flag(tp->mptcp->path_index)) { 266 __mptcp_reinject_data(skb_it, meta_sk, NULL, 1); 267 } 268 269 mptcp_push_pending_frames(meta_sk); 270 271 tp->pf = 1; 272 }
第259行的__mptcp_reinject_data函式將出現超時的sk->sk_write_queue的資料拷貝到 meta_sk 的reinject queue。
而269行的函式mptcp_push_pending_frames將會對reinject queue中的資料進行傳送,其呼叫關係如下:
mptcp_push_pending_frames
=》__tcp_push_pending_frames
=》tcp_sk(sk)->write_xmit
=》mptcp_write_xmit
=》mptcp_next_segment
=》__mptcp_next_segment
=》get_available_subflow
結論 :
1.子路徑出現重發資料的情況下,MPTCP會選擇另外一條路徑傳送同樣的資料。