青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

大龍的博客

常用鏈接

統(tǒng)計

最新評論

關(guān)于半連接隊列的釋疑 --- 轉(zhuǎn)

1、到底那個是半連接隊列
/** struct listen_sock – listen state
*
* @max_qlen_log – log_2 of maximal queued SYNs/REQUESTs
*/
struct listen_sock {
u8 max_qlen_log; /*2^max_qlen_log is the length of the accpet queue, max of max_qlen_log is 10. (2^10=1024)*/
/* 3 bytes hole, try to use */
int qlen; /* qlen is the current length of the accpet queue*/
int qlen_young;
int clock_hand;
u32 hash_rnd;
u32 nr_table_entries; /*nr_table_entries is the number of the syn_table,max is 512*/
struct request_sock *syn_table[0];
};
里面有幾個關(guān)鍵的成員變量:max_qlen_log、qlen和syn_table。注意syn_table是一個零數(shù)組。

跟蹤listen系統(tǒng)調(diào)用:
inet_listen
inet_csk_listen_start
reqsk_queue_alloc

在reqsk_queue_alloc中:
const int lopt_size = sizeof(struct listen_sock) +
nr_table_entries * sizeof(struct request_sock *);
struct listen_sock *lopt = kzalloc(lopt_size, GFP_KERNEL);
我們發(fā)現(xiàn)這里進行了分配內(nèi)存,分配了nr_table_entries個struct request_sock *。
對于nr_table_entries,我們可以往回追蹤:
err = inet_csk_listen_start(sk, TCP_SYNQ_HSIZE);
#define TCP_SYNQ_HSIZE 512 /* Size of SYNACK hash table */

跟蹤SYN數(shù)據(jù)包的處理,在tcp_v4_conn_request中,最后調(diào)用了inet_csk_reqsk_queue_hash_add函數(shù):
void inet_csk_reqsk_queue_hash_add(struct sock *sk, struct request_sock *req,
unsigned long timeout)
{
struct inet_connection_sock *icsk = inet_csk(sk);
struct listen_sock *lopt = icsk->icsk_accept_queue.listen_opt;
const u32 h = inet_synq_hash(inet_rsk(req)->rmt_addr, inet_rsk(req)->rmt_port,
lopt->hash_rnd, lopt->nr_table_entries);

reqsk_queue_hash_req(&icsk->icsk_accept_queue, h, req, timeout);
inet_csk_reqsk_queue_added(sk, timeout);
}

reqsk_queue_hash_req將新建的request_sock添加到reqsk_queue中:
static inline void reqsk_queue_hash_req(struct request_sock_queue *queue,
u32 hash, struct request_sock *req,
unsigned long timeout)
{
struct listen_sock *lopt = queue->listen_opt;

req->expires = jiffies + timeout;
req->retrans = 0;
req->sk = NULL;
req->dl_next = lopt->syn_table[hash];

write_lock(&queue->syn_wait_lock);
lopt->syn_table[hash] = req;
write_unlock(&queue->syn_wait_lock);
}

inet_csk_reqsk_queue_added增加連接請求隊列的計數(shù),必要是設(shè)置計數(shù)器:
static inline void inet_csk_reqsk_queue_added(struct sock *sk,
const unsigned long timeout)
{
if (reqsk_queue_added(&inet_csk(sk)->icsk_accept_queue) == 0)
inet_csk_reset_keepalive_timer(sk, timeout);
}
static inline int reqsk_queue_added(struct request_sock_queue *queue)
{
struct listen_sock *lopt = queue->listen_opt;
const int prev_qlen = lopt->qlen;

lopt->qlen_young++;
lopt->qlen++;
return prev_qlen;
}

其他的幾個數(shù)據(jù)結(jié)構(gòu):
struct inet_connection_sock {
/* inet_sock has to be the first member! */
struct inet_sock icsk_inet;
struct request_sock_queue icsk_accept_queue;
struct inet_bind_bucket *icsk_bind_hash;
unsigned long icsk_timeout;
struct timer_list icsk_retransmit_timer;
struct timer_list icsk_delack_timer;
__u32 icsk_rto;
__u32 icsk_pmtu_cookie;
const struct tcp_congestion_ops *icsk_ca_ops;
const struct inet_connection_sock_af_ops *icsk_af_ops;
unsigned int (*icsk_sync_mss)(struct sock *sk, u32 pmtu);
__u8 icsk_ca_state;
__u8 icsk_retransmits;
__u8 icsk_pending;
__u8 icsk_backoff;
__u8 icsk_syn_retries;
__u8 icsk_probes_out;
__u16 icsk_ext_hdr_len;
struct {
__u8 pending; /* ACK is pending */
__u8 quick; /* Scheduled number of quick acks */
__u8 pingpong; /* The session is interactive */
__u8 blocked; /* Delayed ACK was blocked by socket lock */
__u32 ato; /* Predicted tick of soft clock */
unsigned long timeout; /* Currently scheduled timeout */
__u32 lrcvtime; /* timestamp of last received data packet */
__u16 last_seg_size; /* Size of last incoming segment */
__u16 rcv_mss; /* MSS used for delayed ACK decisions */
} icsk_ack;
struct {
int enabled;

/* Range of MTUs to search */
int search_high;
int search_low;

/* Information on the current probe. */
int probe_size;
} icsk_mtup;
u32 icsk_ca_priv[16];
#define ICSK_CA_PRIV_SIZE (16 * sizeof(u32))
};

struct request_sock_queue {
/*Points to the request_sock accept queue, when after 3 handshake will add the request_sock from syn_table to here*/
struct request_sock *rskq_accept_head;
struct request_sock *rskq_accept_tail;
rwlock_t syn_wait_lock;
u8 rskq_defer_accept;
/* 3 bytes hole, try to pack */
struct listen_sock *listen_opt;
};

因此,半連接隊列在這里可以認(rèn)為是icsk_accept_queue,叫做連接請求隊列。

2、半連接隊列的長度
跟蹤inet_csk_reqsk_queue_is_full,發(fā)現(xiàn)會比較queue->listen_opt->qlen >> queue->listen_opt->max_qlen_log,看來關(guān)鍵在于max_qlen_log。
發(fā)現(xiàn)reqsk_queue_alloc中:
for (lopt->max_qlen_log = 6; /*64*/
(1 << lopt->max_qlen_log) < sysctl_max_syn_backlog;
lopt->max_qlen_log++);

我們在/proc/sys/net/ipv4/tcp_max_syn_backlog中會可以設(shè)置max_syn_backlog,這個就是我們可以設(shè)置的半連接隊列的長度。
默認(rèn)是1024,那么max_qlen_log就是10了;加入我們設(shè)置成64,那么max_qlen_log就是6了,我們設(shè)置成128,就是7了;其他的依次類推。

3、連接請求的數(shù)據(jù)流向
在前面的分析中,SYN數(shù)據(jù)包的處理中,接收到SYN數(shù)據(jù)包,將會建立一個reqest_sock結(jié)構(gòu),添加到syn_table哈希表相應(yīng)的表中。
接收到ACK數(shù)據(jù)包后,跟蹤tcp_v4_do_rcv,發(fā)現(xiàn)會調(diào)用tcp_v4_hnd_req。
在tcp_v4_hnd_req中:
/* Check the request_sock is in the syn_table or not.
If the request_sock have been in the syn_table, then call tcp_check_req*/
/*If ACK in 3 handsharks, will find a request_sock in syn_table, then call tcp_check_req().*/
struct request_sock *req = inet_csk_search_req(sk, &prev, th->source,
iph->saddr, iph->daddr);
/*Normal: Call syn_recv_sock function(tcp_v4_syn_recv_sock)*/
if (req)
return tcp_check_req(sk, skb, req, prev);

在tcp_check_req中:
/*ipv4_specific.syn_recv_sock = tcp_v4_syn_recv_sock*/
child = inet_csk(sk)->icsk_af_ops->syn_recv_sock(sk, skb,
req, NULL);
if (child == NULL)
goto listen_overflow;

/*Move the request_sock from the syn_table to accept_queue
Notes: syn_table isn’t A hlist_header structure.*/
inet_csk_reqsk_queue_unlink(sk, req, prev);
inet_csk_reqsk_queue_removed(sk, req);

inet_csk_reqsk_queue_add(sk, req, child);
return child;

tcp_v4_syn_recv_sock會根據(jù)request_sock新建一個sock結(jié)構(gòu),并且進行一定的初始化,返回新建的sock結(jié)構(gòu)。
將request_sock從syn_table中移到accept_queue中。

static inline void inet_csk_reqsk_queue_add(struct sock *sk,
struct request_sock *req,
struct sock *child)
{
reqsk_queue_add(&inet_csk(sk)->icsk_accept_queue, req, sk, child);
}
static inline void reqsk_queue_add(struct request_sock_queue *queue,
struct request_sock *req,
struct sock *parent,
struct sock *child)
{
req->sk = child;
/*Add the number of backlog, that not completed 3 handsharks but have connected the server.*/*/
sk_acceptq_added(parent);

if (queue->rskq_accept_head == NULL)
queue->rskq_accept_head = req;
else
queue->rskq_accept_tail->dl_next = req;

queue->rskq_accept_tail = req;
req->dl_next = NULL;
}

4、accept系統(tǒng)調(diào)用的處理

三次握手之后,request_sock已經(jīng)在rskq_accept隊列中了,等待accept系統(tǒng)調(diào)用取走。
static inline void sk_acceptq_removed(struct sock *sk)
{
sk->sk_ack_backlog–;
}

static inline void sk_acceptq_added(struct sock *sk)
{
sk->sk_ack_backlog++;
}
這個時候,我們關(guān)注一個struct sock中的兩個變量:
unsigned short sk_ack_backlog; /*sk_ack_backlog is the socket number that not completed 3 handsharks but have connected the server.*/
unsigned short sk_max_ack_backlog; /*sk_max_ack_backlog is the Max sk_ack_backlog, is assigned in the listen()*/
其中,sk_ack_backlog是已經(jīng)完成了三次握手,但是還沒有被accept系統(tǒng)調(diào)用處理的連接請求數(shù)量;sk_max_ack_backlog就是我們經(jīng)常熟悉的listen的參數(shù)。

跟蹤accept系統(tǒng)調(diào)用:
inet_csk_accept:
newsk = reqsk_queue_get_child(&icsk->icsk_accept_queue, sk);

static inline struct sock *reqsk_queue_get_child(struct request_sock_queue *queue,
struct sock *parent)
{
struct request_sock *req = reqsk_queue_remove(queue);
struct sock *child = req->sk;

BUG_TRAP(child != NULL);

sk_acceptq_removed(parent);
__reqsk_free(req);
return child;
}

注意這里free掉了在三次握手中建立的request_sock結(jié)構(gòu)。

5、防止溢出的兩個鏈表檢查
在tcp_v4_conn_request中,對SYN包的處理過程中:

if (inet_csk_reqsk_queue_is_full(sk) && !isn) {
#ifdef CONFIG_SYN_COOKIES
if (sysctl_tcp_syncookies) {
want_cookie = 1;
} else
#endif
goto drop;
}

/* Accept backlog is full. If we have already queued enough
* of warm entries in syn queue, drop request. It is better than
* clogging syn queue with openreqs with exponentially increasing
* timeout.
*/
/*If Accept Queue is full, Drop the packet*/
if (sk_acceptq_is_full(sk) && inet_csk_reqsk_queue_young(sk) > 1)
goto drop;

這里面有兩個隊列的檢查:request_sock隊列和accept隊列。
request_sock隊列:
static inline int inet_csk_reqsk_queue_is_full(const struct sock *sk)
{
return reqsk_queue_is_full(&inet_csk(sk)->icsk_accept_queue);
}
static inline int reqsk_queue_is_full(const struct request_sock_queue *queue)
{
return queue->listen_opt->qlen >> queue->listen_opt->max_qlen_log;
}

accept隊列:
static inline int sk_acceptq_is_full(struct sock *sk)
{
return sk->sk_ack_backlog > sk->sk_max_ack_backlog;
}

其中關(guān)系到4個變量,其中兩個是sock的成員變量,兩個是request_sock_queue中l(wèi)isten_opt的變量。

max_qlen_log的初始化:
在reqsk_queue_alloc中:
for (lopt->max_qlen_log = 6; /*64*/
(1 << lopt->max_qlen_log) < sysctl_max_syn_backlog;
lopt->max_qlen_log++);

sk_max_ack_backlog的初始化:
在inet_listen中:
sk->sk_max_ack_backlog = backlog;
注:sk_max_ack_backlog就是我們經(jīng)常熟悉的listen的參數(shù)。

qlen的增加:
tcp_v4_conn_request
inet_csk_reqsk_queue_hash_add
inet_csk_reqsk_queue_added
reqsk_queue_added

注:跟蹤SYN數(shù)據(jù)包的處理,在tcp_v4_conn_request中,最后調(diào)用了inet_csk_reqsk_queue_hash_add函數(shù):
inet_csk_reqsk_queue_added(sk, timeout);
inet_csk_reqsk_queue_added增加連接請求隊列的計數(shù),必要時候設(shè)置計數(shù)器。
reqsk_queue_added:
lopt->qlen++;

qlen的減少:
tcp_v4_hnd_req
tcp_check_req
inet_csk_reqsk_queue_removed
reqsk_queue_removed

注:
在inet_csk_listen_stop中:
/* Following specs, it would be better either to send FIN
* (and enter FIN-WAIT-1, it is normal close)
* or to send active reset (abort).
* Certainly, it is pretty dangerous while synflood, but it is
* bad justification for our negligence 8)
* To be honest, we are not able to make either
* of the variants now. –ANK
*/
reqsk_queue_destroy(&icsk->icsk_accept_queue);

sk_ack_backlog的增加:
tcp_check_req
inet_csk_reqsk_queue_add
reqsk_queue_add
sk_acceptq_added

sk_ack_backlog的減少:
inet_csk_accept
reqsk_queue_get_child
sk_acceptq_removed

posted on 2013-02-16 00:04 大龍 閱讀(938) 評論(0)  編輯 收藏 引用


只有注冊用戶登錄后才能發(fā)表評論。
網(wǎng)站導(dǎo)航: 博客園   IT新聞   BlogJava   博問   Chat2DB   管理


青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            亚洲视频每日更新| 午夜精品免费在线| 亚洲国产福利在线| 西瓜成人精品人成网站| 亚洲色无码播放| 欧美精品免费在线| 亚洲第一狼人社区| 激情成人综合网| 欧美一级片在线播放| 香蕉av福利精品导航| 欧美日韩一区二区三区免费看 | 亚洲三级免费电影| 久久久综合免费视频| 久久手机免费观看| 韩国成人理伦片免费播放| 欧美一区二区精品| 久久爱另类一区二区小说| 国产精品国产三级国产aⅴ无密码 国产精品国产三级国产aⅴ入口 | 久久综合给合| 狠狠爱www人成狠狠爱综合网| 亚洲自拍都市欧美小说| 亚洲综合日韩在线| 国产精品久久久久久久久婷婷| 一二三四社区欧美黄| 亚洲一级在线观看| 国产精品一二三| 午夜精品三级视频福利| 久久久精品一品道一区| 激情成人亚洲| 免费日韩视频| 亚洲精品综合久久中文字幕| 亚洲天堂久久| 国产精品视频第一区| 欧美一区二区三区视频免费| 久久人人爽爽爽人久久久| 在线观看欧美精品| 欧美极品在线播放| 亚洲一区网站| 久久婷婷国产麻豆91天堂| 亚洲国产日本| 欧美日韩一区二区在线观看视频| 亚洲色图自拍| 裸体素人女欧美日韩| 亚洲国产精品精华液网站| 欧美日韩国产综合久久| 亚洲欧美国产视频| 欧美国产综合| 亚洲欧美日韩成人高清在线一区| 国产视频在线观看一区二区三区| 久久久久久精| 艳妇臀荡乳欲伦亚洲一区| 欧美影院久久久| 亚洲日本aⅴ片在线观看香蕉| 欧美色精品天天在线观看视频 | 国产精品视频不卡| 久久婷婷麻豆| 在线视频精品一| 美女尤物久久精品| 国产精品99久久久久久久久| 国产亚洲欧美日韩一区二区| 欧美高清视频在线 | 亚洲欧美在线一区| 男女精品视频| 欧美一区二区三区日韩视频| 亚洲精品国产精品国产自| 国产精品久久久久久久久果冻传媒| 久久精品国产69国产精品亚洲| 亚洲日本免费| 猛干欧美女孩| 欧美中在线观看| 中国成人在线视频| 亚洲电影免费观看高清完整版| 欧美午夜不卡在线观看免费 | 亚洲少妇自拍| 亚洲第一主播视频| 国产亚洲va综合人人澡精品| 欧美日韩高清免费| 久久中文久久字幕| 欧美一区二区三区啪啪| 一区二区高清| 亚洲精品免费一二三区| 久久永久免费| 久久九九有精品国产23| 亚洲先锋成人| 制服丝袜激情欧洲亚洲| 亚洲黄色小视频| 在线看片一区| 激情婷婷亚洲| 国产资源精品在线观看| 国产精品一区二区a| 国产精品久久久久9999吃药| 欧美激情1区2区3区| 猛干欧美女孩| 欧美xx69| 欧美激情一区二区三区蜜桃视频| 久久综合网hezyo| 久久久久高清| 久久久久久9999| 久久婷婷人人澡人人喊人人爽| 性亚洲最疯狂xxxx高清| 午夜精品久久久久久久99热浪潮| 一区二区欧美日韩视频| 在线亚洲观看| 亚洲一二三区在线| 亚洲一区二区精品| 亚洲一区二区三区四区在线观看 | 亚洲精品一区二区三区蜜桃久| 欧美激情中文字幕乱码免费| 你懂的亚洲视频| 欧美大秀在线观看| 亚洲福利专区| 日韩视频免费| aa级大片欧美| 亚洲欧美日本日韩| 久久久www成人免费无遮挡大片| 久久久久女教师免费一区| 久久人人九九| 欧美精品一区二区视频 | 久久精品国产免费| 久久久亚洲高清| 免费在线观看日韩欧美| 欧美激情亚洲另类| 亚洲美女色禁图| 亚洲欧美国产一区二区三区| 久久xxxx| 欧美国产在线观看| 国产精品欧美久久| 狠狠色香婷婷久久亚洲精品| 91久久国产综合久久| 一区二区三区精品国产| 欧美一区二区三区在| 免费观看日韩| 一区二区久久久久| 久久精品国产亚洲精品| 欧美成人午夜剧场免费观看| 欧美四级在线| 韩国在线视频一区| 亚洲精品一区二区网址| 午夜精品福利在线| 男女av一区三区二区色多| 日韩一区二区精品视频| 欧美中文字幕视频| 欧美精品久久久久久久免费观看 | 男男成人高潮片免费网站| 亚洲国产日韩欧美在线99| 宅男噜噜噜66一区二区| 久久精品国产亚洲5555| 欧美日韩一区在线播放| 一区二区三区在线视频观看| 一区二区冒白浆视频| 久久一区二区精品| 一本色道精品久久一区二区三区| 久久精品国产77777蜜臀| 欧美日韩精品是欧美日韩精品| 国产在线精品自拍| 亚洲午夜精品一区二区| 免费高清在线一区| 亚洲男人第一网站| 欧美日韩精品久久久| 激情综合色综合久久综合| 亚洲素人一区二区| 亚洲成色777777女色窝| 欧美一区二区三区日韩| 欧美色视频日本高清在线观看| 亚洲国产成人不卡| 久久久久久久网| 亚洲在线第一页| 欧美午夜久久| 一本一本久久a久久精品综合妖精| 久色婷婷小香蕉久久| 亚洲一区二区三区高清| 欧美日韩免费一区二区三区| 亚洲高清自拍| 免费观看在线综合色| 欧美一区二区福利在线| 国产精品一区免费观看| 亚洲性色视频| 欧美伊人久久久久久午夜久久久久 | 亚洲三级视频在线观看| 久久久噜噜噜久久| 香蕉精品999视频一区二区| 国产精品美女www爽爽爽| 一区二区三区视频观看| 亚洲激情一区| 欧美二区在线播放| 91久久视频| 亚洲高清免费在线| 欧美成人午夜免费视在线看片| 亚洲第一页自拍| 欧美大成色www永久网站婷| 久久天堂精品| 亚洲国产日本| 亚洲欧洲日产国产网站| 欧美精品网站| 亚洲一区二区动漫| 亚洲男人的天堂在线观看| 国产麻豆精品视频| 久久久久久成人| 久久久亚洲国产天美传媒修理工| 在线播放精品|