zoukankan      html  css  js  c++  java
  • TCP输入 之 快速路径和慢速路径

    概述

    快速路径:用于处理预期的,理想情况下的数据段,在这种情况下,不会对一些边缘情形进行检测,进而达到快速处理的目的;

    慢速路径:用于处理那些非预期的,非理想情况下的数据段,即不满足快速路径的情况下数据段的处理;

    首部预测字段格式:首页预测字段,实际上是与TCP首部中的【头部长度+保留字段+标记字段+窗口值】这个32位值完全对应的;进行快速路径判断的时候,只需要将该预测值与TCP首部中的对应部分进行比对即可,具体见tcp_rcv_established;

    源码分析

    tcp_fast_path_check完成对是否满足快速路径条件的检查,当没乱序队列中没有乱序数据段,接收窗口不为0,接收缓存足够,且没有紧急数据的情况下,才可以开启快速路径标记;不满足上述情况需要执行慢速路径;

     1 static inline void tcp_fast_path_check(struct sock *sk)
     2 {
     3     struct tcp_sock *tp = tcp_sk(sk);
     4 
     5     if (RB_EMPTY_ROOT(&tp->out_of_order_queue) &&
     6         tp->rcv_wnd &&
     7         atomic_read(&sk->sk_rmem_alloc) < sk->sk_rcvbuf &&
     8         !tp->urg_data)
     9         tcp_fast_path_on(tp);
    10 }

    tcp_fast_path_on对含有扩大因子的窗口值进行还原,之后调用__tcp_fast_path_on;

    1 static inline void tcp_fast_path_on(struct tcp_sock *tp)
    2 {
    3     __tcp_fast_path_on(tp, tp->snd_wnd >> tp->rx_opt.snd_wscale);
    4 }

    __tcp_fast_path_on则是构造与tcp头部【头部长度+保留字段+标记字段+窗口值】对应的字段;其中标记字段为含有ACK标记;

    1 static inline void __tcp_fast_path_on(struct tcp_sock *tp, u32 snd_wnd)
    2 {
    3     tp->pred_flags = htonl((tp->tcp_header_len << 26) |
    4                    ntohl(TCP_FLAG_ACK) |
    5                    snd_wnd);
    6 }

    tcp_rcv_established在处理已连接状态下的数据段接收时,会使用tcp_flag_word(th) & TCP_HP_BITS) == tp->pred_flags将tcp首部中的字段值与预测字段进行比对,若一致,才能进入快速路径进行处理,否则执行慢速路径;

     1 void tcp_rcv_established(struct sock *sk, struct sk_buff *skb,
     2              const struct tcphdr *th, unsigned int len)
     3 {
     4     struct tcp_sock *tp = tcp_sk(sk);
     5 
     6     tp->rx_opt.saw_tstamp = 0;
     7 
     8     /*    pred_flags is 0xS?10 << 16 + snd_wnd
     9      *    if header_prediction is to be made
    10      *    'S' will always be tp->tcp_header_len >> 2
    11      *    '?' will be 0 for the fast path, otherwise pred_flags is 0 to
    12      *  turn it off    (when there are holes in the receive
    13      *     space for instance)
    14      *    PSH flag is ignored.
    15      */
    16 
    17     /* 快路检查&& 序号正确 && ack序号正确 */
    18     if ((tcp_flag_word(th) & TCP_HP_BITS) == tp->pred_flags &&
    19         TCP_SKB_CB(skb)->seq == tp->rcv_nxt &&
    20         !after(TCP_SKB_CB(skb)->ack_seq, tp->snd_nxt)) {
    21 }

    tcp_flag_word则是取TCP首部中的第4个32位字段,实际上就是上面说的【头部长度+保留字段+标记字段+窗口值】;

    1 union tcp_word_hdr { 
    2     struct tcphdr hdr;
    3     __be32           words[5];
    4 }; 
    5 
    6 #define tcp_flag_word(tp) ( ((union tcp_word_hdr *)(tp))->words [3])

    对于保留字段和PSH标记,需要在比对之前屏蔽掉,它们不该影响快慢路的判断;

    1 #define TCP_HP_BITS (~(TCP_RESERVED_BITS|TCP_FLAG_PSH))
  • 相关阅读:
    ZOJ 3278 8G Island 二分+二分
    POJ 2785 4 Values whose Sum is 0 二分
    POJ 3063 Sherlock Holmes 随机化
    UVA 10881 Piortr‘s Ants 思维 模拟
    UVA 1388 Graveyard
    Codeforces Round #410 (Div. 2) B. Mike and strings
    Codeforces 821B
    51nod 1103 N的倍数 抽屉原理
    Codeforces Round #427 (Div. 2) 835D
    Codeforces Round #427 (Div. 2) 835C-Star sky 二维前缀和
  • 原文地址:https://www.cnblogs.com/wanpengcoder/p/11752166.html
Copyright © 2011-2022 走看看