5.4 ACK发送与接收

  TCP在发送数据的时候会携带ACK标记,但这里我们要研究的是TCP在收到数据时发送不带数据的ACK报文的情况,这时ACK的发送是通过tcp_send_ack函数完成的:

3027 void tcp_send_ack(struct sock *sk)                                                                                                         
3028 {
3029     struct sk_buff *buff;
3030 
3031     /* If we have been reset, we may not send again. */
3032     if (sk->sk_state == TCP_CLOSE)     
3033         return;          
3034 
3035     /* We are not putting this on the write queue, so
3036      * tcp_transmit_skb() will set the ownership to this                                                                                   
3037      * sock.
3038      */
3039     buff = alloc_skb(MAX_TCP_HEADER, sk_gfp_atomic(sk, GFP_ATOMIC));    //申请一个只能容纳TCP首部的skb                                                                   
3040     if (buff == NULL) {   //申请失败
3041         inet_csk_schedule_ack(sk);     
3042         inet_csk(sk)->icsk_ack.ato = TCP_ATO_MIN; //记录用来计算延时确认的估值
3043         inet_csk_reset_xmit_timer(sk, ICSK_TIME_DACK,
3044                       TCP_DELACK_MAX, TCP_RTO_MAX); //使用延迟ACK定时器发送ACK                                                                                        
3045         return;
3046     }
3047 
3048     /* Reserve space for headers and prepare control bits. */
3049     skb_reserve(buff, MAX_TCP_HEADER);
3050     tcp_init_nondata_skb(buff, tcp_acceptable_seq(sk), TCPHDR_ACK);            //设置ACK标记                                                            
3051 
3052     /* Send it off, this clears delayed acks for us. */
3053     TCP_SKB_CB(buff)->when = tcp_time_stamp;  //记录发送时间,用于计算RTT
3054     tcp_transmit_skb(sk, buff, 0, sk_gfp_atomic(sk, GFP_ATOMIC));        //发送无数据的ACK                                                                  
3055 }

  tcp_transmit_skb函数会将ACK标记写如TCP报头,并设置ack_seq:

 828 static int tcp_transmit_skb(struct sock *sk, struct sk_buff *skb, int clone_it,
 829                 gfp_t gfp_mask)                
 830 {
 831     const struct inet_connection_sock *icsk = inet_csk(sk);
...
 899     th->ack_seq     = htonl(tp->rcv_nxt);
 900     *(((__be16 *)th) + 6)   = htons(((tcp_header_size >> 2) << 12) |
 901                     tcb->tcp_flags);
...
  899:tp->rcv_nxt是“下次希望接收的数据的序列号”,tp->rcv_nxt - 1则是“已经接收到的数据的序列号”。

  发送ACK的时机有:

(1)进程将TCP收到的数据读取(通过tcp_recvmsg、tcp_splice、DMA等等)完毕,会调用tcp_cleanup_rbuf函数发送ACK来通过数据发送端更新窗口:

1323 void tcp_cleanup_rbuf(struct sock *sk, int copied)
1324 {
1325     struct tcp_sock *tp = tcp_sk(sk);
1326     bool time_to_ack = false;
1327 
1328     struct sk_buff *skb = skb_peek(&sk->sk_receive_queue);
1329 
1330     WARN(skb && !before(tp->copied_seq, TCP_SKB_CB(skb)->end_seq),
1331          "cleanup rbuf bug: copied %X seq %X rcvnxt %X\n",
1332          tp->copied_seq, TCP_SKB_CB(skb)->end_seq, tp->rcv_nxt);
1333 
1334     if (inet_csk_ack_scheduled(sk)) { //需要发送ACK
1335         const struct inet_connection_sock *icsk = inet_csk(sk);
1336            /* Delayed ACKs frequently hit locked sockets during bulk
1337             * receive. */
1338         if (icsk->icsk_ack.blocked || //延迟ACK定时器超时时进程锁定了socket,导致ACK无法发送
1339             /* Once-per-two-segments ACK was not sent by tcp_input.c */
1340             tp->rcv_nxt - tp->rcv_wup > icsk->icsk_ack.rcv_mss || //接收了多于2个数据段但还未发送ACK
1341             /*
1342              * If this read emptied read buffer, we send ACK, if
1343              * connection is not bidirectional, user drained
1344              * receive buffer and there was a small segment
1345              * in queue.
1346              */
1347             (copied > 0 && //进程至少copy了1字节数据
1348              ((icsk->icsk_ack.pending & ICSK_ACK_PUSHED2) ||
1349               ((icsk->icsk_ack.pending & ICSK_ACK_PUSHED) &&
1350                !icsk->icsk_ack.pingpong)) && //非socket是交互模式(交互模式允许延迟发送ACK)
1351               !atomic_read(&sk->sk_rmem_alloc)))  //接收缓存为空
1352             time_to_ack = true;
1353     }
1354 
1355     /* We send an ACK if we can now advertise a non-zero window
1356      * which has been raised "significantly".
1357      *
1358      * Even if window raised up to infinity, do not send window open ACK
1359      * in states, where we will not receive more. It is useless.
1360      */
1361     if (copied > 0 && !time_to_ack && !(sk->sk_shutdown & RCV_SHUTDOWN)) {
1362         __u32 rcv_window_now = tcp_receive_window(tp); //得到当前接收窗口的值,即对端计算的发送窗口
1363 
1364         /* Optimize, __tcp_select_window() is not cheap. */
1365         if (2*rcv_window_now <= tp->window_clamp) { //当前接收窗口小于最大接收窗口的一半
1366             __u32 new_window = __tcp_select_window(sk); //根据当前缓存情况得出真正的通告窗口
1367 
1368             /* Send ACK now, if this read freed lots of space
1369              * in our buffer. Certainly, new_window is new window.
1370              * We can advertise it now, if it is not less than current one.
1371              * "Lots" means "at least twice" here.
1372              */
1373             if (new_window && new_window >= 2 * rcv_window_now) //真正的通告窗口是现在对端计算的发送窗口的2倍以上
1374                 time_to_ack = true;
1375         }
1376     }
1377     if (time_to_ack)  //决定发送ACK
1378         tcp_send_ack(sk);
1379 }
  1348-1349:看一下icsk->icsk_ack.pend
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
LTE空中接口技术与性能 第1 章 LTE 系统概述 1 1.1 LTE 技术特点 5 1.2 LTE 网络架构 6 1.2.1 网元设置 6 1.2.2 网络内部接口及网元功能 9 1.3 LTE 网络协议栈 11 1.4 LTE 组网的技术应用 15 1.4.1 终端移动性 15 1.4.2 RRM 16 1.4.3 无线自组织网络 16 1.4.4 家庭型基站 17 1.4.5 增强型MBMS(eMBMS) 19 1.4.6 中继(Relay)技术 22 1.5 FDD LTE 与TDD LTE 26 1.6 LTE 终端类别 28 1.7 LTE 频段划分 30 第 2 章 LTE 物理层技术 32 2.1 概述 32 2.1.1 eNode B 发送接收技术 32 2.1.2 UE 发送接收技术 35 2.1.3 物理层主要性能指标 42 2.2 帧结构与资源块 48 2.2.1 FDD 帧结构 48 2.2.2 TDD 帧结构 54 2.2.3 资源块及其映射 60 2.3 下行链路 66 2.3.1 概述 66 2.3.2 下行信道的一般结构 68 2.3.3 物理下行共享信道 70 2.3.4 物理广播信道 70 2.3.5 物理控制格式指示信道(PCFICH) 74 2.3.6 物理下行控制信道 75 2.3.7 物理HARQ 指示信道 89 2.3.8 参考信号 92 2.3.9 同步信号 98 2.4 上行链路 101 2.4.1 上行物理信道概述 102 2.4.2 时隙结构和物理资源 103 2.4.3 物理上行共享信道 106 2.4.4 参考信号 107 2.4.5 物理上行控制信道 114 2.4.6 物理层随机接入信道 123 2.5 调制和上变频 132 2.6 定时 133 2.7 物理层过程 133 2.7.1 随机接入 133 2.7.2 功率控制 136 2.7.3 小区搜索过程 143 2.7.4 UE 上报CQI、PMI 和RI 的过程 145 2.7.5 HARQ 相关进程 151 2.7.6 频率复用与干扰协调 156 2.7.7 信道定时控制 163 2.7.8 RRC 连接状态下的DRX 167 2.8 LTE 地址标识 169 第 3 章 LTE 的MIMO 技术 172 3.1 MIMO 技术简介 177 3.1.1 天线的种类与应用 178 3.1.2 SDMA 179 3.1.3 码字与层映射 180 3.1.4 预编码 184 3.1.5 下行MIMO 193 3.1.6 SU-MIMO 与MU-MIMO 194 3.2 上行MU-MIMO 的调度与解码过程 196 3.2.1 上行MU-MIMO 的调度 196 3.2.2 上行MU-MIMO 的解码 198 3.3 MIMO 性能 199 3.4 波束赋形技术 200 3.4.1 基于波束赋形的非码本反馈方式 201 3.4.2 基于波束赋形的码本反馈方式 202 3.4.3 BF 和MIMO 的结合 203 第 4 章 空中接口和RRC 技术 206 4.1 概述 206 4.2 PDCP 子层 208 4.2.1 PDCP PDU 208 4.2.2 头压缩 209 4.2.3 数据传输流程 210 4.3 RLC 子层 212 4.3.1 透明模式 213 4.3.2 非确认模式 213 4.3.3 确认模式 217 4.4 MAC 子层 225 4.4.1 MAC 结构和功能 225 4.4.2 MAC PDU 227 4.4.3 MAC 涉及的过程 229 4.4.4 无线资源调度 237 4.5 RRC 技术 240 4.5.1 RRC 功能 240 4.5.2 RRC 状态 243 4.5.3 信令无线承载 244 4.5.4 系统信息广播 245 4.5.5 RRC 连接控制 248 4.5.6 E-UTRAN 内移动性管理 256 4.6 LTE 的QoS 机制 260 4.6.1 简介 260 4.6.2 EPS 承载业务架构 260 4.6.3 QoS 参数 262 第 5 章 LTE 网络性能 265 5.1 3GPP 评估的LTE 网络性能 265 5.1.1 系统峰值速率分析 265 5.1.2 系统频谱效率分析 267 5.2 影响接收灵敏度的因素 268 5.2.1 子载波频率偏差对接收灵敏度的影响 268 5.2.2 振荡器相位噪声对接收灵敏度的影响 270 5.2.3 符号/抽样定时误差对接收灵敏度的影响 270 5.3 开销分析 271 5.3.1 FDD 开销分析 271 5.3.2 TDD 开销分析 278 5.4 时延分析 278 5.4.1 用户面时延 278 5.4.2 控制面时延 280 5.4.3 实际网络主要时延分析 282 5.5 SC-FDMA 性能 286 5.6 LTE 覆盖性能 289 5.6.1 下行信道覆盖 289 5.6.2 上行链路覆盖 290 5.6.3 DL PDCCH 覆盖性能 291 5.6.4 UL PUCCH 覆盖性能 292 5.6.5 DL RS 覆盖性能 294 5.7 MCS 的选择 295 5.8 VoIP 性能 297 5.9 固定带宽探测参考信号的链路性能分析 300 5.10 上行ACK/NACK 性能分析 303 5.11 MIMO 信道反馈性能分析 305 5.12 不同频率分集方式对吞吐量的影响 309 。。。。。。。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值