久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 3988|回復: 1
打印 上一主題 下一主題
收起左側

TCP的OOS 隊列之胡猜亂猜胡師傅

[復制鏈接]
跳轉到指定樓層
樓主
ID:82781 發表于 2015-6-13 00:41 | 只看該作者 回帖獎勵 |倒序瀏覽 |閱讀模式


        最近忙于手頭工作,而沒有太多時間搞那懸而未決的OOS隊列斷言失敗的問題。今晚猜測一下。
在測試中發現去掉這個隊列也是可以工作的,而且局域網內也是不會丟包,所以這個OOS隊列的作用就有待審視。

要想搞清楚這個OOS對列斷言失敗的情況下這個隊列的作用首先要從他的誕生之地說起。

IP層把數據交給tcp_input(struct pbuf *p, struct netif *inp),這就是開始了。
接著‘
iphdr = p->payload;
  tcphdr = (struct tcp_hdr *)((u8_t *)p->payload + IPH_HL(iphdr) * 4);
取出指向PBUF的載荷指針,就找到了那個所有的IP層運輸的TCP數據包。于是乎又取走了TCP的首部,按照TCPIP協議加載到對應的結構中,這樣一個TCP頭的句柄就產生了。
接下來是縮減PBUF有效指針,移動指針到拋去TCP首部的后邊TCP載荷數據上,這就是所謂的
pbuf_header(p, -((s16_t)(IPH_HL(iphdr) * 4))) || (p->tot_len < sizeof(struct tcp_hdr))
下一步是拋卻多播和廣播如果有,因為在TCP中這些完全是操蛋的玩意。邊去!
下一步校驗這個TCP段是否正確。正確就繼續。

/* Convert fields in TCP header to host byte order. */
  tcphdr->src = ntohs(tcphdr->src);
  tcphdr->dest = ntohs(tcphdr->dest);
  seqno = tcphdr->seqno = ntohl(tcphdr->seqno);
  ackno = tcphdr->ackno = ntohl(tcphdr->ackno);
  tcphdr->wnd = ntohs(tcphdr->wnd);
顯然.........  那么。。。。
flags = TCPH_FLAGS(tcphdr);  tcplen = p->tot_len + ((flags & (TCP_FIN | TCP_SYN)) ? 1 : 0);
以上是取出來TCP的標志,就是所謂的RST FIN....等等所在的字段,然后保存在一個全局變量flags中,這很重要。
for(pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next)
開始遍歷所有的活躍連接表。
如果活躍鏈表沒有,好開始遍歷另一個
for(pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next)
就是所謂的等待隊列。
如果等待隊列也沒有再去遍歷另一個
for(lpcb = tcp_listen_pcbs.listen_pcbs; lpcb != NULL; lpcb = lpcb->next)
所謂的監聽列表,這就沒了。
如果當前列表中有,那好(pcb != NULL)必定成立,則
inseg.next = NULL;
    inseg.len = p->tot_len;
    inseg.dataptr = p->payload;
    inseg.p = p;
    inseg.tcphdr = tcphdr;

    recv_data = NULL;
    recv_flags = 0;
開始構建TCP段準備交付上層的結構準備工作。可見這個結構繼承PBUF
緊接著執行tcp_process(struct tcp_pcb *pcb)
開始處理TCP事務,其實是主要處理TCP的那狀態圖,根據
enum tcp_state {
  CLOSED      = 0,
  LISTEN      = 1,
  SYN_SENT    = 2,
  SYN_RCVD    = 3,
  ESTABLISHED = 4,
  FIN_WAIT_1  = 5,
  FIN_WAIT_2  = 6,
  CLOSE_WAIT  = 7,
  CLOSING     = 8,
  LAST_ACK    = 9,
  TIME_WAIT   = 10
};
這個狀態處理各個分支的枝枝叉叉。最后鎖定這個函數
tcp_receive(struct tcp_pcb *pcb)
這個函數開始處理我兩件事3,一件事是TCP的ACK一件事是含有數據包的TCP報文。把它交給上層。但是他是如何交上去的,還得猜
if (flags & TCP_ACK) 這個就是處理TCP的ACK包,我們忽略這不是重點,因為我想看看底層數據如何向上的。向下換個選項
/* If the incoming segment contains data, we must process it
     further. */
  if (tcplen > 0) {。。。}
按照解釋上說的是只做三件事:
/* This code basically does three things:

    +) If the incoming segment contains data that is the next
    in-sequence data, this data is passed to the application. This
    might involve trimming the first edge of the data. The rcv_nxt
    variable and the advertised window are adjusted.

    +) If the incoming segment has data that is above the next
    sequence number expected (->rcv_nxt), the segment is placed on
    the ->ooseq queue. This is done by finding the appropriate
    place in the ->ooseq queue (which is ordered by sequence
    number) and trim the segment in both ends if needed. An
    immediate ACK is sent to indicate that we received an
    out-of-sequence segment.

    +) Finally, we check if the first segment on the ->ooseq queue
    now is in sequence (i.e., if rcv_nxt >= ooseq->seqno). If
    rcv_nxt > ooseq->seqno, we must trim the first edge of the
    segment on ->ooseq before we adjust rcv_nxt. The data in the
    segments that are now on sequence are chained onto the
    incoming segment so that we only need to call the application
    once.
    */
終于出來OOS對列了,這個稱之為:out-of-sequence 隊列。如上文所述
這個OOS是用來存儲失序的SEQ號所排的隊,并且按照序號鏈接起來一并交付應用層處理,這種失序在局域網中小數據根本沒有。只有
在廣域網中或或者在局域網高速數據吞吐的情況下才會發生,尤其是廣域網中這種情況完全可能,
TCP的失序問題是這樣產生的
HOST端發送的數據經過若干道路由,有可能有的去天津饒了一圈,有的去海南轉了圈,再回來肯定有時間差,時間差很可能會發生序號小的后到達,而序號大的先到達,這是完全有可能的,這是OOS隊列起作用了,他會緩存住失序的TCP段,并發出失序應答。然后重新連接PBUF把序號鏈接的BUF連接重新分配后一并交付應用層。

而現在回到我最初的問題,那就是斷言失敗,在哪里斷言失敗呢,恰巧是在OOS對列的更新WIN處,也就是說這個OOS還要關心一個TCP的滑動窗口,而應用層遲遲沒能從更新WIN,也就是沒有及時的取走應用層的數據,而導致了WIN數據的推遲更新,更在搞的是還有的正確的數據包擠壓在OOS中,最要命的是WIN值并不多了,然后
pcb->rcv_nxt += TCP_TCPLEN(cseg);
          ASSERT("tcp_receive: ooseq tcplen > rcv_wnd\n",
                      pcb->rcv_wnd >= TCP_TCPLEN(cseg));
          pcb->rcv_wnd -= TCP_TCPLEN(cseg);

          tcp_update_rcv_ann_wnd(pcb);
事故就不可避免的發生了,WIN值減到了負的!那是絕對不允許的。所以這里斷言失敗了。輸入了一個非法的值。這個值是TCP的滑動窗口不能為負造成的。W其實根源在于WIN值不大,大的話就不會出現負值鳥!!!!也就不會斷言失敗。

這種情況發生在網卡驅動速度慢,然后HOST快速發送的時候,出現。同樣的程序倘若放到一臺網卡快的就沒有這個問題。
現在只能猜到這里。表面上是WIN的值為負,實際上還有一些深層的背靜因素所左右。也從側面看到同樣的情況軟件情況下好的硬件就很重要了。

現在的用法是去掉OOS,這樣一來他就不會緩存失序的隊列,也就不會重新組裝底層的失序數據。肯定會丟失一些數據的。如果快速廣域網通信。

也許這是協議棧的BUG也許是我沒用精細。總之去掉OOS在網卡不是那么優秀的情況下會帶來一些意外收獲哦!!!!總比斷言失敗好吧。這只是個開始~~~~~~

最近面對伙計們關于未來的質問我確實心下慚愧,確實沒有什么成就,哎!狗屁一樣!簡直是槽糕透了,不過好在胡猜亂猜胡師傅 表示只要他那啥。。一定那啥...即使不那啥..胡猜亂猜胡師傅也自己認為很那啥了!

胡猜亂猜胡師傅老王頭!!!


20150129
日照比特





分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏 分享淘帖 頂 踩
回復

使用道具 舉報

沙發
ID:82781 發表于 2015-6-13 00:41 | 只看該作者
        Send


1、對載荷進行填充,填充目標地址。校驗等
2、SndState = STATE_M_TX_XMIT;激活發送,打開發送接口驅動PortEnable( FALSE, TRUE );
3、發送 /* check if we are finished. */
        if( SndBufferCount != 0 )
        {
            PortPutByte( ( CHAR )*pucMasterSndBufferCur );
            pucMasterSndBufferCur++;  /* next byte in sendbuffer. */
            SndBufferCount--;
        }
4、發送完畢,開始判斷當前是否廣播然后區別對待(打開接受關閉發送,打開接收就是要接受回應的。)

/* If the frame is broadcast ,master will enable timer of convert delay,
             * else master will enable timer of respond timeout. */
            if ( xFrameIsBroadcast == TRUE )
            {
            vMBMasterPortTimersConvertDelayEnable( );
            }
            else
            {
            vMBMasterPortTimersRespondTimeoutEnable( );
            }

兩種情況都是開啟定時器計時開始,但是時間長短不一樣而已。
5、關閉POLL。
6、開始等待延時結束
7、延時完成回調函數激活
/* A frame was send finish and convert delay or respond timeout expired.
* If the frame is broadcast,The master will idle,and if the frame is not
* broadcast.Notify the listener process error.*/
向應用程序報告當前的情況,是廣播的話就是當前延時結束,是發送的話就是沒有回應應該報錯誤。這樣一個超時錯誤響應的就產生了
于是通過一個隊列接口通知應用即可】】
PortEventPost(EV_MASTER_ERROR_PROCESS);
8、  關閉定時器,發送狀態重新回到        eSndState = STATE_M_TX_IDLE;


值得注意的是這是非正常情況,正常是
如果收到從機的回應主機會立即關閉發送等待定時器,并重新標定發送狀態為空閑
case STATE_M_RX_IDLE:
     PortTimersDisable( );
            eSndState = STATE_M_TX_IDLE;
這個是在接受文件中定義的!
就是這些
2015年3月15日
比特
回復

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規則

手機版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術交流QQ群281945664

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 中文字幕在线三区 | 亚洲天堂中文字幕 | 亚洲三区在线观看 | 成人免费在线小视频 | 在线免费黄色小视频 | 欧美亚洲国产一区二区三区 | 91久久精品一区二区二区 | 欧美一区二区大片 | 国产精品海角社区在线观看 | 久久免费看 | 97精品国产97久久久久久免费 | 天天草狠狠干 | 欧美成视频 | 久久小视频| 亚洲 欧美 综合 | 欧美成人在线免费 | 精品欧美色视频网站在线观看 | 91性高湖久久久久久久久_久久99 | 日韩和的一区二区 | 亚洲精品一区二区三区免 | 国产98色在线 | 日韩 | 欧美午夜一区二区三区免费大片 | 久久精品黄色 | 欧美极品少妇xxxxⅹ免费视频 | 99久久精品免费看国产四区 | 久久精品中文字幕 | 日本一二三区电影 | 在线免费观看黄视频 | 一级a爱片久久毛片 | 中文字幕亚洲一区二区三区 | 国产成人精品一区二区三 | 91高清视频在线 | 伊人久久伊人 | 精品亚洲一区二区三区四区五区 | 久久精品中文 | 97伦理电影网 | 久久久精品国产 | 91偷拍精品一区二区三区 | 久精品久久| 午夜合集 | 亚洲欧美一区二区三区国产精品 |