Access-B1205

    技术2022-05-20  28

    B1205是在B8k基础上的cost down产品,接入设备,上行GE,下行5框可以混插ASLFXS板,主控板为CSM,设备提供VOIPASL服务,

     

     

    FXS硬件图

    FXS板代码跑RTEMS,对比B8K改动有:

    成本考虑,裁剪51利用SBUSCSM通信,改为HDLC通信

    在链路层和网络层间增加UTMAC层,将普通包数据和IP包数据分开处理

    FXS+ASL结合板,增加ASL控制模块

    FXSCSM是通过背板联系起来的,硬件连接CSMFPGACPLDCSMtimeslot

     

    1.        FXS板插入

    CSM起一个定时器函数,定时去读FPGA,当有板插入时,CSM知道是哪个slot有板插入了;

    接着CSM读取单板的CPLD信息,确定具体板类型,有了这些信息,CSM分配highwayHDLC

    FXS侧代码跑起来后,通过底层驱动得到slot,配置CPLD分配highwayHDLC(事先和CSM都协商好的);

    接着FXSutmacstart,通过send_addr_req请求ip地址,CSM响应,根据slot和板类型,分配一个IPFXS

    (比如FXS+slot1192.168.110.2

    有了这些通信已经建立起来了

     

     

    2.        UTMAC实现

    这是UTMAC的数据类型,有包信息类型,有IP请求类型,有心跳类型

     

    /*

     *Frame type field

     */

    #define UTMAC_DATA_FRAME        0x1

    /* Control frame types */

    #define UTMAC_IPADDR_REQ_FRAME        0x2

    #define UTMAC_IPADDR_FRAME        0x3

    #define UTMAC_IPADDR_ACK_FRAME        0x4

    #define UTMAC_ECHO_REQ_FRAME        0x5

    #define UTMAC_ECHO_RESP_FRAME        0x6

    #define UTMAC_SHUTDOWN_FRAME         0x7

    #define UTMAC_TEST_DATA_FRAME         0xA

    #define UTMAC_51_DATA_FRAME         0x10

     

    这就是心跳的包,00 05 00 06就是UTMAC

    < 0: (1792) 1939276544

    < 49 e1 fe db 00 05 01 c0 a8 6e 02

     

    > 0: (1792) 1939276544

    > 49 e1 fe db 00 06 01 c0 a8 6e 00

     

    < 0: (1792) -946339072

    < 49 e1 fe df 00 05 02 c0 a8 6e 02

     

    > 0: (1792) -946339072

    > 49 e1 fe df 00 06 02 c0 a8 6e 00

     

     

    这是纯数据包,业务部分几乎都是这种包

     

     

    > 0: (3072) -946535680

    > 49 e1 fe d7 00 10 00 06 00 04 03 fe 08 37 44 bb

     

     

    > 0: (6656) -946535680

    > 49 e1 fe d7 00 10 00 14 00 12 16 03 01 c2 ff 92

    > 00 00 00 00 07 07 00 00 00 00 00 00 8d 72

    这是IP包,MIB表项配置几乎都是这种包

     

     

    < 0: (22528) 462816000

    < 49 e1 fe d8 00 01 45 00 00 56 00 01 00 00 40 11

    < 1d 43 c0 a8 6e 02 c0 a8 6e 00 13 8e 13 8d 00 42

    < 25 a9 55 4d 03 01 08 01 00 11 00 00 00 00 02 01

    < a5 00 00 02 06 00 04 00 01 00 00 00 01 01 04 00

    < 01 c0 a8 6e 02 02 01 00 01 00 03 01 00 01 00 04

    < 01 00 06 00 00 00 00 00 00 ff 84 b7

     

    UTMAC必须保证工作正常,所以保持和CSM来交互;

    当超时时,UTMAC会挂掉,报警到NMS

    但是UTMAC必须要自动起来,所以这个时候心跳

    UTMAC从一开始就起定时器函数,超时处理函数为timer_handler

    FXSUTMAC_ECHO_REQ_FRAMECSMCSMUTMAC_ECHO_RESP_FRAMEFXS收到回UTMAC_ECHO_RESP_FRAME,(这里很重要一点,记录当前时钟)stop_echo_timer,并重新定时,这个时候FXS没有请求,timer_handler会超时,处理process_utmac_timeout,重新开始UTMAC_ECHO_REQ_FRAME请求和定时

     

     

    static void start_echo_timer ()

    {

        start_timer((TIMER  **)&echo_timer,

                (U32)0, timer_handler, ECHO_TIMEOUT, 0);

    }

    ......

    static void timer_handler (U32 tm)

    {

        OS_STATUS        rc;

        qbuf_t            *q;

       

        /* echo_timer = 0; Removed by Jacky Liu. */

        rc = alloc_msg_buf( (void **)&q, sizeof(qbuf_t));

        if ( rc == SUCCESS )

        {

          memset((void *)q, 0, sizeof(qbuf_t));

            q->buffer_retain = BUFFER_FREE;

            q->primitive     = UTMAC_TIMEOUT_EVENT;

            q->source        = IP_PROC_ID;

       

            rc = send_msg(UTMAC_QUEUE,(void **)&q, NO_SUSPEND );

     

            if (rc != SUCCESS)

                dealloc_msg_buf( (void *)q );

        }

    }

    ......

    static void process_utmac_timeout ()

    {

       

        int            utmac_idx;

        U32            time_diff;

        utmac_info_t    *info_p=NULL;

        hdlc_ibc_ts_t    ibc;

     

        info_p    = find_utmac_chan(LocalShelf, LocalSlot);

        utmac_idx  = info_p - &UtmacInfo[0];

        switch (info_p->state)

        {

            case    UTMAC_UP:

                 if (!info_p->alarm_state)

                 {

                    time_diff = (Retrieve_Clock() - info_p->last_echo_tm)/100;

            

                    if(time_diff > ECHO_THRESHOLD)

                    {

                        /* Let OAM know this state. */

                        info_p->state = UTMAC_DOWN;

                        info_p->alarm_state = TRUE;           

                          send_oam_status(ECHO_ACK_EXPIRED);

                    }

                    else

                    {

                        send_echo_req(info_p, Tag);

                        Tag++;

                        start_echo_timer();

                    }

                 }

    ......

            case    UTMAC_DOWN:   

                /* add by hyg for UTMAC_DOWN state */

                /* Let OAM know this state. */

                down_up = 1;

                info_p->state = UTMAC_UP;

                info_p->alarm_state = FALSE;           

                //send_oam_status(UTMAC_IS_UP);

                /* should not send UTMAC_IS_UP state, for now it is still down */

     

                info_p->last_echo_tm = Retrieve_Clock()

                send_echo_req(info_p, Tag);

                Tag++;

                start_echo_timer();

                break;

               

            default:

        }

     

    }

     

    出问题的时候,FXS没有收到回UTMAC_ECHO_RESP_FRAME,这个时候,timer_handler会超时,处理process_utmac_timeout,重新开始UTMAC_ECHO_REQ_FRAME请求和定时,重复这几步,等待下面条件符合的时候,就会UTMAC挂掉,报警

     

          time_diff = (Retrieve_Clock() - info_p->last_echo_tm)/100;

          /* 当前时间和最后一次正常心跳的时间差 */

          if(time_diff > ECHO_THRESHOLD)

          /* 大于设定的一个值,比如3分钟 */

     

    如果重新起来,记录当前时间,重新发,如果3分钟内UTMAC通了,就UP起来了,如果3分钟内还没通,又重复这样的工作。

    搞不懂新泽西研发为什么这样写,直接一个定时器函数心跳,不通就DOWN,再起定时器,非常的简单

     

    3.        HDLC代替51通信

    两个数据接口要重新封装,发送数据用sendDatatohdlc代替sendDatato51底层接口

     

    #if 0

    int sendDatato51(int minor, const char *buf, int len){

        if(SPI_SUCCESS==spi_send(buf,len))

        {

            spi_ignore_next_pack=TRUE;

            //record len to trim returned package, get the ACK/NACK byte

            spi_ignore_package_len=len;

            return len;

        }

        else

            return -1;

    }

    #endif

    int sendDatatohdlc(int minor, const char *buf, int len){

        if(SUCCESS == hdlc_utmac_send_51(minor, buf, len))

        {

            //spi_ignore_next_pack=TRUE;

            //record len to trim returned package, get the ACK/NACK byte

            //spi_ignore_package_len=len;

            return len;

        }

        else

            return -1;

    }

     

    接收数据不需要从51收了,直接从UTMAC收到的数据做为接口,增加UTMAC_51_DATA_FRAME数据类型,当然CSM侧同样增加这个类型,所有原来发往51的数据全部走这条路,HDLC消息处理的方式和原来51一样即可

    ......   

        case UTMAC_51_DATA_FRAME:

            if (utmac_dedug_flag) printf("UTMAC_51_DATA_FRAME /n");

            sc->sc_stats.ipackets += 1;

            receiveDatafromhdlc(qb->pdata+UTMAC_HEADER_SIZE, qb->data_size-UTMAC_HEADER_SIZE);

            break;

    ......

     

     

     

     

    4.        ADSL控制任务

    需要增加一个任务adsl_ctrl_main,和ASL通信模块利用SCC接口,收发数据通过中断

    下面是adsl_ctrl_main接收到的事件

    ......

            if(event_out & EVNT_SCC3_TO_ADSL)

                adsl_ctrl_proc_scc3_msg();

            if(event_out & EVNT_OAM_TO_ADSL)

                adsl_ctrl_proc_oam_msg();

            if(event_out & EVNT_ADSL_TIMEROUT)

                adsl_ctrl_proc_timerout_msg();

    ......

     

    收到的EVNT_OAM_TO_ADSL来自OAM控制模块,因为FXS只是做一个控制模块而已,比如升级ASL模块,MIB信息先到FXSOAMFXS通过OAM模块送到adsl_ctrl_main,收到之后,会讲消息转发到ADSL

    收到EVNT_SCC3_TO_ADSL来自底层的SCC的中断,这是来自的ADSL板的消息

    流程是:

    ASL板起来后,会发消息过来,取板卡的shelfslotFXS响应,起心跳函数

     

    void  repeat_HeartBeat()

    {

        snd_heartbeat_req_to_adsl();

      

        //start a timer to monitor the response.

        if(heartBeat_repeat_count >= 10)// repeat 10 timers

        {

            if(sys_info.adsl_st != ADSL_ACTIVE)

              reset_adsl();

            if(sys_info.adsl_st != ADSL_UPSTARTING)

            sys_info.adsl_st = ADSL_INACTIVE;

           

            heartBeat_repeat_count = 0;

            send_fxs_alarm_to_oam (ALARM_FXS_ADSL_COMMUNICATION , 1, 0xff);

        }

        else heartBeat_repeat_count++;

        start_timer(&ADSL_HEARTBEAT_RESPONSE_TIMER, 0, heartBeat_TimerOut, HEARTBEAT_REPEAT_TIMER,0);

       

    }

     

    发送心跳消息到ASL,起定时器

    如果正常情况收到ASL的心跳响应,关定时器,再心跳重复操作

     

    /*when rcv heartbeat cmd from adsl*/

    case 0x00:

    {

        /*response with 0xff*/

        snd_heartbeat_rsp_to_adsl();

       

        if(sys_info.adsl_st == ADSL_UPSTARTING)

        {

            //adsl has been successfully started,then close the timer;

            if(ADSL_STARTUP_TIMER)

            {

                stop_timer(ADSL_STARTUP_TIMER);

                ADSL_STARTUP_TIMER = NULL;

                ADSL_TRACE(adsl_trace_debug,"ADSL has been started......../n");

            }

            //snd the repeated heartbeat

            //repeat_HeartBeat();                      

        }

        else if(sys_info.adsl_st != ADSL_DOWNLOAD) sys_info.adsl_st = ADSL_ACTIVE;

       

        ADSL_TRACE(adsl_trace_debug,"send heartbeat response code 0xff/n");

        heartBeat_repeat_count = 0;

        pmsg++;

    }

        break;

    如果不正常情况会超时,执行定时器超时函数,给adsl_ctrl_main发送EVNT_ADSL_TIMEROUT事件,执行repeat_HeartBeat,上报NMS响应ALARM

     

    5.        小结

    编译FXS出错,是因为编译过IVD了,有些LIB是共用的,应该删除后重编

    出现 bin/sh莫名其妙字符错误,说明是dosunix的问题

    shelf_slot_port = (sys_info.shelf_id<<16)+(sys_info.slot_id<<8)+0xff;找了很久原因居然是这里,应该用或就OK

    ST的大呼没过,调试发现23层间的UTMAC层有数据包丢了,怀疑是HDLC问题,只好写个暴力测试函数,从CSMN多包到FXSHDLC统计数据和CSM测统计对比,数据数量不一致,研究一下HDLC驱动,修改OK

    大呼效率低下,发现VCP串口打印过多,关掉打印,OK

    现场出现了UTMAC挂掉后,电话通信OKFXS管理断掉了,这个问题说明了HDLC底层通信正常,UTMAC层不通了,最后发现是process_utmac_timeout中没对UTMAC_DOWN: 处理,添加处理函数,OK

     


    最新回复(0)