Access-B1205

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

 

你可能感兴趣的:(Access-B1205)