首页 > 代码库 > OpenLTE开源代码结构解析(二)

OpenLTE开源代码结构解析(二)

对eNodeB的一些配置以及代码结构进行说明,如下:

一,eNodeB配置结构

|| 控制进程(传递eNB配置命令)|| ---》  || eNB按照配置进程的配置命令工作 ||

1,  在一个Tab窗口运行LTE_fdd_eNodeB进程(启动eNodeB工作进程)

2,  在另一个Tab窗口运行控制进程,可使用连接工具(Telent,nc等)连接LTE_fdd_eNodeB进程(端口固定为30000,以Telnet连接本机示例,使用命令为Telnet 127.0.0.1 30000)来完成配置操作,包括启动,终止LTE_fdd_eNodeB进程中的基站操作,读取,设置基站操作中需要的参数;


 二,代码重要实体层说明

2.1 Interface层

eNB提供的接口,处理来自外部的配置命令;

2.2 MsgQ实体

提供统一的消息管理实体,对于各个协议层的消息进行处理,接收,存储,发送;

2.3 Radio层

1,  Radio的Start函数创建线程(radio_thread)来处理数据帧收发;在线程函数中会调用Phy层实体的radio_interface接口来处理上,下行数据,在radio_interface中会进一步地包含上,下行处理,在处理上下行数据中,当对user data进行处理时,会用到dl_sched_mutx锁:

Dl_sched_mutex_lock()

Dl_sched_mutex_unlock()

2.4 Phy层

Start函数中会定义对于Mac数据处理的接口,在进而处理下行调度类型数据时,会应用线程锁:

boost::mutex::scoped_lock lock(dl_sched_mutex)

2.5 Rb协议实体

1,Msg会包含Rb的指针,指向特定的Rb

1,  一个UE只会定义一定数据的RB实体(最多3个SRB,8个DRB),每个RB中会为每个协子层定义一个消息队列(如,RRC,PDCP,RLC,MAC);

Rb_Id的填写在gw协议实体中完成,目前代码中作了简化处理,在gw层只会填写id=1:gw将rb_id会被填写进消息中,并一直在包含在后续pdb流中各个的协议实体间传递:

Gw->pdcp->rlc->mac

2,  当前处理协议子层m从传递的消息中查询到RB后,从RB中取出对应当前处理协议子层m队列中的消息数据,按照当前处理协议子层m的处理机制进行处理,然后再次处理完成后的消息数据单元(下一相邻子层的SDU)存储到RB定义的对应到下一协议子层n的消息数据队列中;并构造消息头传递到协议子层定义的与下一相邻子层n通信的m_n_olmq中下一相邻协议子层n接收到来m的消息后,会触发hand_m_msg的操作,也是处理消息头,取SDU,处理完后再构造下一层的SDU,再向下一协议层发送消息触发下一层的处理,例如,rlc处理完本协议层的操作后向mac层发送消息操作:

LTE_fdd_enb_msg::send(rlc_mac_olmq, **)

3,  直到消息到了mac层,处理方式有不同:

1,  rb_id需要转换为mac_id,处理方式有不同:

sdb_ready->rb->get_rb_id()

2,  上层发下来的SDB数据处理后,只是会存储在scheduler队列中,如下:

Add_to_dl_sched_queue

         不会主动向phy层发送消息,phy层会基于phy层的机制来触发mac层的调度机制,进而从调度队列中依次取出PDU进行发送;

2.6 User实体

管理用户的参数属性;例如标识,能力,承载等;

2.7  安全机制

Eia算法

33220中KDF算法如下:

         Derivedkey = HAMC-SHA-256(Key,S)

在Security中使用sha2_hmac实现:

在代码中好像没有对up面生成的key使用,而且只是保存在Hss中,有些疑问:

用户面的key使用终点是基站,应该保存基站侧才合适;



 三,实体之间交互

3.1 Radio与Phy实体之间交互

Radio_thread->radio_thread_func->radio_interface(此函数是由Phy层提供,并且此处是通过while(循环一直调用))->process_dl/process_ul

其中,UL发送到MAC的帧;DL调用radio中的send(调用uhd的tx-stream)进行发送

Phy类中定义的成员boost::interprocess:message_queue*phy_mac_olmq用来承载Phy给MAC层传递的消息(包括各种类型物理信道(PRACH,PUSCH,PUCCH)的解码后的内容以及一种全称为read_to_send的消息),此处重点说明一下ready_to_send消息,即Phy层处理完了上行或者下行子帧的发送,需要告知MAC层其已经等待好处理下一子帧;MAC层通过读取phy_mac_olmq进行获取发送的消息;当获取到消息类型为read_to_send时,则会执行调度操作,主要为配置子帧资源;

3.2 MessageQueue举例

上层通过send函数向该queue中发送message,主要操作过程如下:

a)      Phy层实例化对象:mac_comm_msgq=newLTE_fdd_end_msgq(“mac_phy_olmq”,cb);

b)      Mac层定义了boost对象mac_phy_olmq,再向该对象队列中发送消息:

1)  mac_phy_olmq->send(&msg_sizeof(msg),0)

2)  LTE_fdd_enb_msg::send(mac_phy_olmq;

 

Phy层在实例化mac_comm_msgq对象时,会调用回调函数:

Messageq->receive_thread->callback(即handle_mac_message,并且callback直到接收到Interface发送的Stop参数的消息才终止处理)->handle_dl_schedulehandle_ul_schedule 其中:

Handle_dl_schedule处理下行调度相关操作,主要是将MAC中Scheduler函数中已经组装好的帧拷贝到具体的位置;并提供给后续process_dl函数中封装user_data时使用,有以下代码操作:

memcpy(&pdcch.alloc[pdcch.N_alloc],&dl_schedule[subfn].ul_allocations.alloc[i],

handle_ul_schedule的目的是为了封装phich。因为phich的封装需要基于MAC层的调度信息。有以下Comment:

           for(i=0; i<ul_schedule[ul_subframe.num].decodes.N_alloc; i++)

           {

                // Determine PHICH indecies

 3.3 LTE_fdd_enb_msgq对象Msgq与boost对象olmq

层m为与相邻n层交互,需要定义一个m_n_olmq,并向m_n_olmq发送消息数据;n层会定义一个相应的m_comm_mesq(实例化的时候,其string名称即为m_n_olmq),这样n层在m_comm_mesq中即可获取来自m层的消息数据:

具体操作如下实例:

在协议层mac层中实例化boost对象:

Mac_phy_olmq = newboost::interprocess::message_queue(boost::interprocess:open_only *

 

在Phy层中msgq定义如下:

         Mac_comm_msgq= new LTE_fdd_enb_msgq(“mac_phy_olmq”,cb);

在后续msgq(专用类)的处理操作receive_thread中,通过msgq的string name对应到”mac_phy_olmq”这个boost:

Boost::interprocess::message_queue mq(boost::interprocess::open_only,msgq->msgq_name.c_str());

 


未完待续。。。欢迎各位也在关注这个项目的朋友指点交流~

 


OpenLTE开源代码结构解析(二)