ONU4024i硬件接口,2GE、1EPON、24LAN/VOIP,就是一个24口交换机+VOIP,可以GE上行,或者EPON上行,LAN口和VOIP共用接用户
1. VOIP硬件参数
MPC8247 64MSDRAM 4MFLASH,这样的硬件设计成本太高,临时加班出来的产品,简单的由switch+VOIP板合并而成,switch部分是NMS可见的,VOIP和switch之间用内部IP来管理,中间有FE来连接,管理包和业务包都经过这里
VOIP板原来是iFXS产品,为单独一个盒子,24PORT的VOIP,不支持NMS,只可以命令行配置,配置文件保存在板子FLASH上
在MPC8247的MII,必须配置几个IP,一个192.168.1.*内部管理用,另外是VOIP协议用的两个IP
协议栈收到包后,会判断是到哪个IP的,这样互相不冲突
if(edp == &fcc1Device)
{
if(source_ip == (u_long)(ip_config.primary_ip))
....
}
原来的VOIP单板是早期的,VCP是没有的,采用一个51来采集摘挂机和铃声控制,在VOIP一侧需要做的工作有:去掉51代码,移植vcp代码;增加loop_test测试模块;增加VOIP的MIB管理模块
2. VCP代替51模块
VCP和51是最底层的任务了,它们上一层的任务是HIP,也只有HIP任务和它们通信,所以需要删除51的任务,添加VCP的任务
VCP(或者51)检测摘机,发包到HIP
-->HIP收到包,发包到VOIP协议栈
-->协议栈收到包,处理
下面代码就是VCP的所有消息送到HIP去的,封装数据格式一定要和hip的API一样,有些繁琐
bool VcpSendFixMessageToHip(int8 lineNum, uint8 byte1, uint8 byte2){
uint8 msgLen=2, i;
//qbuf_t *qbuf;
OS_STATUS rc;
uint8 rx_buf[4];//slot,len,byte1,byte2
vcp_debug_printf_notice("VCP module sending out message to 51 ctrl with message 0x%x 0x%x ",byte1,byte2);
/*Convert content to sbus format, and send it to M8051_MSG_Q */
rx_buf[0] = get_hip_id(0, 2); /* Add old slot id for HIP */
rx_buf[1] = 2;/*length of content*/
rx_buf[2] = byte1;
rx_buf[3] = byte2;
rc = forward_msg(&rx_buf[0], rx_buf[1] + 2, POLL_TO_HIP_RX_DATA);
return rc;
}
协议栈有阵铃消息,送包到HIP
-->HIP收到包,发包到VCP
-->VCP收到包
UserBdTxProc是HIP发送包的接口,所以在这里做操作封装函数fill_tx_buf为send_to_vcp,还是繁琐的调试,还好消息格式没有改变
void
UserBdTxProc (qbuf_t * DownMsgQ)
{
......
cadence_type = DownMsgQ->digit;
if (DownMsgQ->option == 0) /* normal ring_on */
{
// fill_tx_buf (6,0x00,0x03,0x04,port,cadence_type,board_i);
send_to_vcp(6,0x00,0x03,0x04,port,cadence_type,board_i);
if( ( is_fx_debug_on() == TRUE ) || (is_fx_port_trace_on(port) == TRUE ) )
{
printf("UserBdTxProc(): Sent FXS port %d RING-ON Pattern %d message!/n", port, cadence_type);
}
}
......
}
这些接口都可以用测试命令先测试线程间通信是否正常
3. 添加loop_test的任务
NMS操作,switch发包到VOIP
-->MIB任务收到,发测试命令到loop_test
-->loop_test收到测试命令,判断一下转发包到VCP
-->VCP收到开始测试,测试结果发到loop_test
-->loop_test收到测试结果,发给MIB任务
-->MIB收到,更新MIB表项
(这里并没有发给NMS,只是等待NMS来取的;因为VOIP测每次做的操作都是跟新MIB表,管理这一块都是NMS发消息到MIB任务,MIB任务去MIB表中取)
这个真的挺繁琐的
4. MIB任务以及N多的MIB添加
和switch之间通信起socket用内部管理IP,同步操作,不管是SET还是GET配置项都是去更新MIB表,另外再掉底层API使配置生效;所以有N多的MIB表要去更新,这是收到NMS的消息后解析MIB命令,定义了一个枚举来操作的,有SET项有GET项
......
/* Command dispatch */
switch (pCmdReq->cmd)
{
case COMM_CMD_MG_IPADDR_CFG_GET:
memcpy(&commMsgBuf, &(pCmdReq->buffer), 4);
result = mml_utsMgIpAddressCfgEntry_get(commMsgBuf, &msgLen);
break;
case COMM_CMD_MG_IPADDR_CFG_SET:
result = mml_utsMgIpAddressCfgEntry(pCmdReq->buffer);
break;
case COMM_CMD_MG_CALL_SERVER_CFG_GET:
result = mml_utsMgCallServerCfgScalars_get(commMsgBuf, &msgLen);
break;
case COMM_CMD_MG_CALL_SERVER_CFG_SET:
result = mml_utsMgCallServerCfgScalars(pCmdReq->buffer);
break;
......
下面是代码接口,还有N多的MIB*.cc表项,那些表项是实现底层的程序接口,比如媒体IP,信令IP,涉及到系统和VOIP协议相关
/*
* Function: by hyg 4024i 080410
* Purpose:
* Arguments:
* Returns:
*/
int mml_utsMgIpAddressCfgEntry_get(char* buf, int* length)
{
mtbl_sel_t sel;
int error_flag = 1;
udl_utsMgIpAddressCfgEntry_t* udl_utsMgIpAddressCfgEntry_t_p_tmp = (udl_utsMgIpAddressCfgEntry_t*)buf;
unsigned utsMgIpAddressCfgIpIndex_s = 1;
sel.set(0,0);
*length = sizeof (udl_utsMgIpAddressCfgEntry_t);
if ((error_flag = CMmlTbl::get_mtbl(UDL_UTSMGIPADDRESSCFGENTRY_T)->get_row(sel, &(udl_utsMgIpAddressCfgEntry_t_p_tmp->utsMgIpAddressCfgIpIndex), udl_utsMgIpAddressCfgEntry_t_p_tmp))
== RV_OK)
{
hprintf("mml_utsMgIpAddressCfgEntry_get ok/n");
return RV_OK;
}
else
{
hprintf("error:%d/n",error_flag);
return error_flag;
}
}
int mml_utsMgIpAddressCfgEntry(char* buf)
{
mtbl_sel_t sel;
int error_flag = 1;
udl_utsMgIpAddressCfgEntry_t* udl_utsMgIpAddressCfgEntry_p = (udl_utsMgIpAddressCfgEntry_t*)(buf);
int mask = *(int*)(buf+sizeof(udl_utsMgIpAddressCfgEntry_t));
udl_utsMgIpAddressCfgEntry_t udl_utsMgIpAddressCfgEntry_p_tmp;
sel.set(0,0);
hprintf("mask-----:%x----/n",mask);
if (CMmlTbl::get_mtbl(UDL_UTSMGIPADDRESSCFGENTRY_T)->get_row(sel, &(udl_utsMgIpAddressCfgEntry_p->utsMgIpAddressCfgIpIndex),&udl_utsMgIpAddressCfgEntry_p_tmp)
== RV_OK)
{
memcpy(&udl_utsMgIpAddressCfgEntry_p_tmp, udl_utsMgIpAddressCfgEntry_p, sizeof(udl_utsMgIpAddressCfgEntry_t));
if ((error_flag = CMmlTbl::get_mtbl(UDL_UTSMGIPADDRESSCFGENTRY_T)->set_row(sel,
&(udl_utsMgIpAddressCfgEntry_p->utsMgIpAddressCfgIpIndex), &udl_utsMgIpAddressCfgEntry_p_tmp, mask)) == RV_OK)
{
hprintf("mml_utsMgIpAddressCfgEntry ok /n");
return RV_OK;
}
else
{
hprintf("error:%d/n",error_flag);
return error_flag;
}
}
else
return error_flag;
}
写了N多这样的代码,N多的MIB表,时间紧急下的编码质量也不高
5. 其它更新
还有一个问题就是MIB配置项的保存,之前iFXS是基于命令行配置,现在需要所有的MIB表项全部保存,实现方法是起一个大的struct,直接保存,系统启动的时候直接读这个大的struct,解析出来对照每一个MIB表项即可
6. 小结
移植vcp代码,去掉了一些宏控制以及looptest没有移植,导致很多地方编译不通过,修改了很多,如果一按开始就按照原样子以及looptest移植过来,很少需要改动的,教训
ss_send_test定义char buf[]过大,而任务的分配内存太小,直接crash
task中起task,没有删除已经的clienttask,起了n多的task,不重启才怪
rtems_task_create中参数拷贝过来的,taskname没对上,导致task的name不是define的name
get_task_id_from_task_name这个函数太烂了,只可以找m4中定义的函数的,导致无法取到自己起的task的id号
update_signal_ip((inaddr_t)utsMgIpAddressCfgEntry_p_tmp.utsMgIpAddressCfgIpAddress, inaddr_t)utsMgIpAddressCfgEntry_p_tmp.utsMgIpAddressCfgNetmask);少了强制转换定义,肯定报错
extern "C" void update_signal_ip(inaddr_t signal_ip, inaddr_t signal_ip_mask);C++调用一定切记加这个
../../vpm/nmgt/oam/oaminit.cc:2186: passing `void (*)()' as argument 3 of `rtems
_timer_fire_after(unsigned int, unsigned int, rtems_timer_service_routine (*)(un
signed int, void *), void *)'这个意思是子函数的参数不匹配
memcpy(&(udl_utsVoiceBandTestinEntry_t_mask_p->utsVoiceBandTestinVBat), &RcvBuf[i+5], 2);
0x4400
udl_utsVoiceBandTestinEntry_t_mask_p->utsVoiceBandTestinVBat = *((short *)&RcvBuf[i+5]);
0x0044取值刚好相反
尽量定义数组,只要不太大,指针出了问题找起来太麻烦了
malloc后没释放,导致大呼后crash,小问题大麻烦
BSP提供的I2C驱动有问题,导致读出的MAC出错,这个时候代码中会采用一个默认的MAC,这个时候多台ONU4024i连接OLT的时候就会出错了,导致内部IP不通了,这个问题害死我了