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不通了,這個問題害死我了