MPTCP 源碼分析(六) 數據重發

簡述網絡

     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的實現以下:tcp

"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 }
View Code
第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會選擇另一條路徑發送一樣的數據。
相關文章
相關標籤/搜索