一、引入
4G LTE通信系统由有线和无线两部分组成,当然,在这个层面2G、3G还有5G也是一样,比如从西安拨打上海的电话,手机信号一定是以电磁波的形式先发送到本地基站,这部分是无线网络,然后通过有线网络连接到上海的某个基站,最后再以电磁波的形式发送到上海的电话上。
User Equipment (UE)
Evolved Packet Core(EPC)
Evolved Universal Terrestrial Radio Access Network (E-UTRAN)
Evolved Packet System(EPS)
其中eNB即是所谓的基站,它由BBU和RRU两部分构成。RRU是Remote Radio Unit 远端射频模块,BBU是Building Baseband Unit 室内基带处理单元。
为什么要引入3GPP通信协议?
eNB位于UE和EPC之间,UE在接入(比如主叫主动拨号或者被叫被唤醒)或者切换(开车过程中打电话,从一个蜂窝小区进入到另外一个蜂窝小区)时,UE发送给基站的任一条消息(EPC发送给eNB的消息同此理)都是为了发送给核心网,只有经过核心网才能达到其实现通信的目的。手机可能是苹果公司生产的,eNB可能是中兴/华为的,核心网可能是爱立信的,为了正常通信一定得规范一套协议,只要我发送信令的信元、发送的时机合乎协议,就能保证不同厂家的通信设备组到一起可以正常通信,这就是3GPP通信协议,也是BBU的职责。
二、业务
业务需要描述的场景是完备而复杂的,对于一个具体的业务场景,Figure 2-1所绘的流程图是一种有效的表述形式。
UE和MME之间由控制信息也有数据信息,Figure 2-1描述了一个UE接入过程的控制信息交互的片段。从图中可以看到,eNB首先会起一个定时器等MME的INITIAL CONTEXT SETUP REQUEST,等到之后进行内部各模块的处理,UE也相当于是eNB的一个需要处理的模块,处理完成后给MME回复INITIAL CONTEXT SETUP RESPONSE,不能啥都不回,或者回复的消息不满足INITIAL CONTEXT SETUP RESPONSE的格式要求。
从图中还可以看到,在接入过程中,CONTEXT过程完成后进行UECapabilityEnquiry过程,并且将查询上来的UECapabilityInformation进行处理,按MME接收的格式(UE CAPABILITY INFO INDICATION)发送到MME,这个UE Capability过程的时机不是随时都可以发的。
控制信息的传输即信令,包括消息号和结构体两部分,比如Figure 2-1中INITIAL CONTEXT SETUP REQUEST消息号对应的结构体如图Figure 2-2所示。
Figure 2-2描述了消息体中每个信元的含义,比如MME UE S1AP ID、eNB UE S1AP ID分别代表当前UE在MME和eNB的ID(Identity),这是任意一条S1口消息必带的信元,因为如果一条消息没有发给确定的UE是没有意义的。其它的每个信元也都有各自特定的物理意义,比如E-RAB to Be Setup List代表了UE在接入过程中同时需要建立用于传输数据的承载列表。
3GPP不仅提供了接口和流程描述,还提供了第三方的编解码库,各通信设备商在按照接口的要求填写情况下,直接调用第三方的编解码函数即可转换为协议要求格式的码流,也只有协议确定了才能按协议编解码。
3GPP只是描述了对UE和MME的通信规范,各通信设备商都以此为唯一标准。同时,基站内部内部模块间通信也是通过信令交互完成的,由于模块间的分工、依赖关系和产品需要支持的不同硬件、不同架构等,提出了大量的业务需求。
Figure 2-3中为BBU机框图,机框支持“1~2块CC板”加上“1~6块BPL板”。
数据反传功能会涉及哪些业务场景:
UE切换时,可能MME下发的数据包传输了一半,在原来位置(BPL)的数据传输情况不能直接传到目标侧(BPL),由于背板总线的原因需要采用CC板的、信令传输的方式进行传递。会出现多种数据反传场景。如Figure 2-4到Figure 2-6所示。
业务场景多样而且复杂,要保证特性功能运行正确、代码有利于维护,是一件非常具有挑战性的问题。
三、代码
第一、普遍地,从代码的逻辑梳理出代码的业务功能是一件很麻烦的事情;但是如果大致知道代码的业务需求,再看代码的业务需求,会轻松很多。所以不论是讲解代码还是开发代码,业务是基础。第二、代码的目的是给机器执行的,但是,更重要的是代码是要便于人能够很好的理解,如果一套代码功能无误,但是可读性差或者根本就没有可读性,这套代码肯定是会被废弃的,因为后面的人无法在此基础上新增功能或修改故障。
控制面的代码量大概是20万行的规模,业务的正确理解是前提,它还有这些特点:
代码分层设计:C++面向对象设计,类似Figure 2-4、Figure 2-5、Figure 2-6的整个图的流程都分别是一个类Transaction。既然是流程控制,肯定是一套完备的、能表述C语言流程图的控制逻辑,比如SEQUENTIAL、FORK...JOIN、FINALLY等类,SEQUENTIAL将传给本类的所有事物按顺序逐条执行(Figure 2-4、Figure 2-5、Figure 2-6都属于这类情况),FORK将传入本类的所有事务并发执行,在一个确定的时机去等待所有事务执行完成(JOIN)、FINALLY会在业务流程走完后做一些清理或者其它需要的工作。它们分别被划分为Infra/Sched/traffic等层。
模板和模式:业务中各种的流程图就有超过100张,很多地方需要消除重复,也是形成统一的编码规范和风格,需要大量使用模板。如前文看到的E-RAB to Be Setup List这种List,需要使用访问者模式、对于KPI上报数据搜集需要使用监听者模式,固定的模式利于写也利于读。Figure 2-6中的发送EV_X2_SN_STATUS_TRANSFER这个动作在流程图的每个步骤都会用到,代码中将其设计成一个Action类,对外提供了和Transaction的接口,对内提供了builder(数据构建、编码),sender,waiter等逻辑,这也相当于是一种协议,也是一种模式,省时省力。
多继承:每个UE实例在eNB内是一块儿12k左右的数据,里边存储了大量的UE相关信息,12k大小的数据怎么管理?代码中使用了多继承的数据组织形式。多继承的每一个父类都能根据业务领域做到高内聚低耦合,要找每个特性的时候就能方便找到。
信令:如果一个业务流程失败了,通过信令对照流程图能迅速的找到是在哪个步骤异常了,再检查信令中的信元,将一个流程很清晰的呈现出来,专职的测试人员不用看代码,通过信令就基本能够确定开发人员的特性实现正确与否。
KPI:为了衡量一个系统运行情况的好坏,业务定义了一系列的KPI指标,它相当于一把尺子,对运营商呈现出软件运行情况,当然运营商也有第三方的监测软件。
如此庞大的项目,保证通畅有序的工作是一件很大的工程,管理上由很多有益的实践:
多级CI。在每次代码合入时都需要经过系统CI,CI的意思是持续集成,业务、平台、基带各自在自己的二级CI上保证代码没有问题,然后合入到一级CI,合入每级CI前需要验证通过,合入每级CI后需要回归测试完成,CI本身又设置了很多的校验项保证代码质量。
商用代码监测软件。商用代码监测软件是二级CI的其中的一个校验项,比如我们写的switch...case语句,按规范每个case都需要break,如果待合入代码违反了就会拦截不让合入,再比如代码为业务死代码,永远执行不到等等,各种各样。
大规模FT。每开发的一个业务特性时,需要新增FT,保证业务逻辑,同时,之前别人写的保证业务逻辑的FT已经几千条了,要保证所有FT通过,即既要保证自己的特性软件仿真通过,又要保证不影响之前的代码的逻辑。
RF测试部署。FT的通过基本能保证代码的质量,但是由于模块间的接口、FT不能完全真实构造场景的局限性等,FT不能替代真实环境的测试。RF测试用例通过python自动化脚本自动化的执行一些基本的业务流程,又叫冒烟测试,保证不会让整个大项目瘫痪。
wiki。wiki有些相当于公共的blog,我们在编码、软件安装、脚本学习时有太多不会的地方,比如python的类库如此的多以至于不可能把每个类库都接触到,我们百度一下就都知道了。工作内容纷繁复杂,需要记笔记的及时记笔记,东西太多不能都记得住,记住了也不能保证不忘,每个团队内各成员大家参与、大家受益。
敏捷管理。敏捷管理属于管理制度的范畴,每个公司的管理制度都各不相同,敏捷管理形成了一套方法论,比如任务卡墙、7-13人小团队化、轮值制度、OKR让自己制定自己的目标等,对发挥个人能动性,集思广益,组织有序和民主等都是很好的实践。