LTE rlc 子层代码阅读及总结

本文概述了UM模式中PDU处理流程,重点在于build_data_pdu的SDU组装,包括检查残留SDU、添加到PDU、设置头信息和处理接收窗口。read_pdu则涉及状态报告处理、随机重传和数据PDU的重组与交付。

add_bearer:
    //choose mode-->insert entity-->configure and add to array
configure:
    //check timers-->configure timers-->configure timers/status_prohibit_timer
write_sdu:
    //check size-->check if block on write to queue-->write-->in case of fail, the try_write returns back the sdu;
总结:write_sdu的作用:
    可以写就写,不能写就返回?
read_pdu:
    //Tx STATUS if requested-->build_status_pdu
    //if tx_window is full and retx_queue empty-->retransmit random PDU
    // RETX if required--->build_retx_pdu()
build_status_pdu:
    //get_status_pdu
    //reset_status-->run()
    //debug_state-->rlc_am_write_status_pdu
get_status_pdu:
    // start with lower edge of the rx window--->status->ack_sn = vr_r!
    //We don't use segment NACKs - just NACK the full PDU
    // only update ACK_SN if this SN has been received
    // make sure we don't exceed grant size---->if (status->N_nack >= 1 && status->N_nack < RLC_AM_WINDOW_SIZE)--->status->N_nack
    // make sure we don't have the current ACK_SN in the NACK list-->rlc_am_is_valid_status_pdu
retransmit_random_pdu:
    //randomly select PDU in tx window for retransmission(rand)-->retx_queue.push_b
    ack
build_retx_pdu:
    // Check there is at least 1 element before calling front()-->front()应该就是取队首元素;
    //Sanity check - drop any retx SNs not present in tx_window(tx_window.end() == tx_window.find(retx.sn)-->retx-queuepop-front()???为什么发送窗口首位的单元不能重传?
    // Is resegmentation needed?--->required_buffer_size-->build_segment
    // Update & write header
    // Set poll bit
    //rlc_am_write_data_pdu_header
    //max_retx_attempted
    //debug_state
required_buffer_size:
    //Construct new header---->rlc_am_packed_length(&new_header)
    //Need to rebuild the li table & update fi based on so_start and so_en
build_segment:
    //Construct new header--->rlc_am_packed_length(&new_header)
    //Make sure we can fit at least one N_li element if old header contained at least one-->if (old_header.N_li > 0)
    //pdu_space = nof_bytes - head_len
    //Need to rebuild the li table & update fi based on so_start and so_end--->if (retx.so_start == 0 && rlc_am_start_aligned(old_header.fi))
    //Accomodate some extra space for for LIs if old header contained segments too
    //only increment N_li if more SDU (segments) are being added
    //Update retx_queue--->Write header and pdu
build_data_pdu:
    // do not build any more PDU if window is already full
     // Check for SDU segment
     //    if (tx_sdu != NULL--->First byte does not correspond to first byte of SDU
    // Pull SDUs from queue--> load new SDUs--while(loop)--->
   //head_len = rlc_am_packed_length(&header);  --->// fixed part+Extension part--- integer rounding up
   // Make sure, at least one SDU (segment) has been added until this point
   // Set Poll bit
   // Set SN
   // Place PDU in tx_window, write header and TX----将相关数据记录在tx_window中
     // Write header to pointer & move pointer   Segment part+ Extension part + Pad if N_li is odd
  debug_state();
  return total_len;
总结:build_data_pdu做了些什么事:
    检测整个窗口的状态--->检查是否有残留的SDU残留-->加入新的sdu-->头文件的设置--->发送窗口的设置-->合并头文件和SDU,生成pdu
总结:read_pdu做了些什么事情:
    首先检测是否满足触发status的条件,满足则触发build_status_pdu:
        *build_status_pdu调用get_status_pdu确认哪些SN收到了还是没收到,生成status report;
        *如果重传队列为空并且发送窗口满,调用retransmit_random_pdu随机重传一个PDU;//没有插入轮询P?
        *如果重传队列不为空:发送重传队列中的pdu,调用build_retx_pdu生成重传pdu
            *检查是否需要对重传队列进行重分割;
            *调用build segment 进行重分割;
        *如果都没有问题,那就调用build_data_pdu生成新的pdu;
    更新num_tx_bytes;

write_pdu:
    //if (rlc_am_is_control_pdu(payload))--->handle_control_pdu
    //rlc_am_read_data_pdu_header
    //handle_data_pdu_segment/handle_data_pdu
 handle_control_pdu:
     //rlc_am_read_status_pdu--->E1,E2,CPT...
     //stop poll_retx_timer--->reset?
     // flush retx queue to avoid unordered SNs, we expect the Rx to request lost PDUs again
      // Handle ACKs and NACKs
    // sanity check--->print error but try to send original PDU again--->// check for special SO_end value
    //   if (!nack)--->// ACKed SNs get marked and removed from tx_window if possible
rlc_am_read_data_pdu_header:
    // Fixed part---->Extension part---->Account for padding if N_li is odd
handle_data_pdu_segment:
    // Check inside rx window
    // Check if we already have a segment from the same PDU
    // Add segment to PDU list and check for complete--->add_segment_and_check--->Check for first segment--> Check for complete---> We have all segments of the PDU - reconstruct and handle--->Reconstruct fi\Li field-->Copy data--->handle_data_pdu
handle_data_pdu:
    //sanity check for segments not exceeding PDU length-->Len and inside of window?
    // Write to rx window-->check available space for payload-->Update vr_h-->vr_ms
    // Check poll bit
    // Reassemble and deliver SDUs-->  reassemble_rx_sdus
    // Update reordering variables and timers 
reassemble_rx_sdus:
    // reassemble_rx_sdus-->while(vr_r!=end(0) Handle any SDU segments-->sanity check to avoid zero-size SDUs-->进行了几次长度判断(都是哪些方面)-->调用pdcp->write_pdu()
    //ptr msg should point to the length of sdu recieved already;
    //Handle last segment-->// Move the rx_window-->also erase any segments of this SN
总结:write_pdu作用:
    *判断是不是控制pdu,如果是,调用handle_control_pdu进行处理;
        *对状态报告进行解读;rlc_am_rad_status_pdu
        **如果状态报告中包含有NACk的包,则清空重传窗口;???每次都这样吗?
    *如果是数据pdu,
        *调用rlc_am_read_data_pdu_header读取header数据;
        *如果是pdu segment-->pdu
        *调用reasemble_rx_sdus重组sdu;
            *给出了此pdu中有多少的个sdu segment;
            *用len指示当前的分段的长度
            *用rx_sdu标识接收端缓冲区大小;
            *接收窗口好像直接把数据给rx_sdu缓冲区了,到底是怎么重组回来的呢?
        *如果sdu的大小大于单个PDU的时候如何处理?一个sdu放在三个pdu的情况怎么办?

        ==========================TM============================================
总结:TM模式较为简单粗暴:
        *write_sdu和AM模式相差不大;能写就写,写不下丢掉;
        *read_pdu中,直接读取走sdu;
        *write_pdu中,拷贝走了数据,判断是哪种承载,然后交付;
        ==========================UM============================================
总结:UM模式涉及到pdu的组装与拆分:
        *build_data_pdu
            *检测是否sdu segment 残留-->有,压入pdu,并设置fi为非从头开始-->压入其它sdu-->检查是否整个sdu压完或者pdu是否还有空间-->设置标头

        *handle_data_pdu
            *read_data_pdu_header,对相关的值进行判断,是否为正常的sdu,没什么好说的;
            *写入接收窗口,
            *分离pdu标头,
            *如果sn不在接收窗口内,跟新窗口上限值
            *reassemble_rx_sdus:
                *先置位ur;
                *开始处理pdu,
                *丢弃有遗漏的sdu,其它的正常压入接收窗口;
                * 处理最后一个segment,更新接收窗口;
            *然后开始处理UR往上;
                *if (not pdu_belongs_to_rx_sdu())
                *Handle any SDU segments
                *丢弃存在遗漏的sdu;
                *跟新接收窗口指针;
                *检查sdu剩余空间;
                *在sdu缓冲区中设置了一个ur指针,指示提交的最大ur值, 
                *和接收窗口的指针值相比较,
                *符合条件就继续传送这个sn的pdu;
                *不符合的话更新接收缓冲区的sn值,开始传一个新的sn的值
                *提交或者丢弃
                *处理最后一个segment;
 

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值