首页 > 代码库 > 采用掩码方式简化产品国家地区支持能力的表示

采用掩码方式简化产品国家地区支持能力的表示

 

一、背景描述

     某系列产品中,不同产品、国家和地区支持不同的配置项(但差异不大)。各配置项均由其BranchLeaf结点值(BLV)唯一标识。

     作为ONU通用配置媒介之一,某模块对各配置项创建合法性校验函数IsBranchLeafValid(…),其中包含的结点列表表示产品缺省支持的所有配置项,类似“白名单”;此外根据各国家地区的要求创建屏蔽函数IsBranchLeafScreened (…),其中包含的结点列表表示该国家/地区不予支持的配置项,类似“黑名单”。其中,“黑名单”列表为“白名单”列表的子集。两个名单结合起来对接收到的OLT配置帧进行校验,从而表现出不同的支持能力。

     因此,对于M个产品,N个国家地区,在物理上将需要M+N个黑白名单。具体实现上,黑白名单函数内充斥着大量if...else与switch...case结构:

 1 /* 每个产品对应一个Product_Adapter.c文件,内含IsBranchLeafValid实现 */
 2 BOOL IsBranchLeafValid(OAM_BRANCH_LEAF eBranchLeaf)
 3 {
 4     BOOLEAN retcode = 1;
 5     switch(eBranchLeaf)
 6     {
 7         case OnuSn:
 8         case FirmwareVer:
 9         case ChipsetID:
10         case EthDSRateLimit:
11         case QosConfig:
12         case FastLeaveState:
13         case FastLeaveCtrl:
14         case FaxModemConf:
15         case SIPDigitMap:
16         //Dozens of eBranchLeaf... ...
17         {
18             retcode = 1;
19         }
20             break;
21 
22         default:
23         {
24             retcode = 0;
25         }
26             break;
27     }
28 
29     return retcode;
30 }
31 
32 
33 BOOL IsBranchLeafScreened(INT32U dwdwdwRegionVer, OAM_BRANCH_LEAF eBranchLeaf)
34 {
35     if(dwdwRegionVer == DEFAULT_XINJIANG_CFG)
36     {
37         switch(eBranchLeaf)
38         {
39             case VlanConfig:
40                 
41             case FaxModemConf:
42             case SIPDigitMap:
43             //Dozens of eBranchLeaf... ...
44                 return 1;
45             default:
46                 return 0;
47         }
48     }
49     else if(dwdwRegionVer == DEFAULT_JIANGSU_CFG)
50     {
51        switch(eBranchLeaf)
52        {
53             case VlanConfig:
54               return 1;
55            default:
56               return 0;
57        }           
58     }
59     else
60     {
61         return 0;
62     }
63 }
View Code

     后续若增加其他产品、国家和地区,需要不断增加文件或扩展函数。此外,各名单的BLV列表内容互有重叠,代码冗余度很高。

 

二、改进方案

     定义产品、国家、地区掩码,掩码中各比特表示某BLV的相应产品、国家和地区支持情况。这里将国家和地区分开是为了扩展掩码支持范围。

     例如下面的简化格式(前两比特表示产品支持,后两比特表示地区支持): 

     对于某BLV,上面的0b‘1001表示F420V2上海版本支持该配置项,以此类推。

     这样就无需IsBranchLeafScreened和IsBranchLeafValid黑白名单函数,校验时只需根据掩码对应比特(偏移)来判断相应的BLV是否支持。

     对于产品掩码,可在预编译阶段设置掩码偏移值;对于国家和地区,可在ONU启动初始化时通过查询国家地区码来设置掩码偏移值。

 

三、实践情况

     目前已定义的EPON SFU产品有F420V2/F411V2/F420G/F400G/F1420/F460/F460V2/F460M等等,国家地区码(非指本文“掩码”)如下:

 1 /* 国家码 */
 2 #define DEFAULT_CFG              0    /* 基本默认配置文件 */
 3 #define DEFAULT_RUSSIA_CFG       1    /* 俄罗斯默认配置文件 */
 4 #define DEFAULT_LITHUANIA_CFG    2    /* 立陶宛默认配置文件 */
 5 //… …
 6 
 7 /* 地区码 */
 8 #define DEFAULT_JIANGSU_CFG      200   /* 江苏省默认配置文件 */
 9 #define DEFAULT_XINJIANG_CFG     201   /* 新疆默认配置文件 */
10 #define DEFAULT_HAINAN_CFG       202   /* 海南默认配置文件 */
11 #define DEFAULT_TIANJIN_CFG      203   /* 天津默认配置文件 */
12 #define DEFAULT_ANHUI_CFG        204   /* 安徽默认配置文件 */
13 #define DEFAULT_SHANGHAI_CFG     205   /* 上海默认配置文件 */
14 //… …
View Code

     因此,可将产品掩码定义为1字节,掩码偏移比特定义如下: 

 1 /*ONU产品掩码定义(根据新增产品而扩展)*/
 2 #if defined(CONFIG_CSP_PRODUCT_F411) || defined(CONFIG_CSP_PRODUCT_F420) || defined(CONFIG_CSP_PRODUCT_F420G)
 3     #define PRODUCT_SHIFT            0
 4 #elif defined(CONFIG_CSP_PRODUCT_F400G)
 5     #define PRODUCT_SHIFT            1
 6 #elif defined(CONFIG_CSP_PRODUCT_F1420)
 7     #define PRODUCT_SHIFT            2
 8 #else
 9     #define PRODUCT_SHIFT            3
10 #endif
View Code

     国家掩码定义为4字节长整型,从低位到高位依次对应国家码编号,即掩码bit-0表示缺省版本支持情况(恒为1),bit-1表示俄罗斯版本支持情况;地区掩码与国家掩码类似,应注意掩码bit-0恒为1以避免与国家掩码冲突(只能有一个缺省版本),bit-1表示江苏版本支持情况。国家、地区掩码偏移比特定义如下:

1 VOID GetRegionMask(INT32U dwRegionVer, INT8U *pucNatShift, INT8U *pucRegShift)
2 {
3     if(dwRegionVer < DEFAULT_JIANGSU_CFG)
4         *pucNatShift = dwRegionVer;
5     else
6         *pucRegShift = dwRegionVer - 199;
7 }
View Code

    具体掩码结构如下OAM_CMD_MAP结构定义如下图所示: 

 1 typedef FUNC_STATUS(*OAM_GET_CMD_HANDLER)(OAM_HEAD_INFO*, INT8U*, INT32U*, CTC_OAM_ACK*);
 2 typedef FUNC_STATUS(*OAM_SET_CMD_HANDLER)(OAM_HEAD_INFO*, INT8U*, INT32U*, CTC_OAM_ACK*);
 3 typedef struct{
 4     OAM_BRANCH_LEAF  eBranchLeaf;
 5     INT8U   ucProductMask;
 6     INT32U  dwNationMask;
 7     INT32U  dwRegionMask;
 8     OAM_GET_CMD_HANDLER  fnGetCmdHandler;
 9     OAM_SET_CMD_HANDLER  fnSetCmdHandler;
10 }OAM_CMD_MAP;
11 
12 #define DEF_8U     0xFF
13 #define DEF_32U    0xFFFFFFFF
14 #define GC(NAME)   OAM_##NAME##_Get_Cmd
15 #define SC(NAME)   OAM_##NAME##_Set_Cmd
16 
17 /*OAM命令处理函数映射表 */
18 OAM_CMD_MAP gOamCmdFuncMap[] = {
19     {OnuSn,             DEF_8U,   DEF_32U,    DEF_32U,       GC(ONU_SN),            NULL},
20     {FirmwareVer,       DEF_8U,   DEF_32U,    DEF_32U,       GC(FirmwareVer),       NULL},
21     {ChipsetID,         DEF_8U,   DEF_32U,    DEF_32U,       GC(ChipsetID),         NULL},
22     {EthDSRateLimit,    DEF_8U,   DEF_32U,    DEF_32U,       GC(EthDSRateLimit),    SC(EthDSRateLimit)},
23     {QosConfig,         DEF_8U,   DEF_32U,    DEF_32U,       GC(QosConfig),         SC(QosConfig)},
24     {FastLeaveState,    DEF_8U,   DEF_32U,    0xFFFFFFBF,    GC(FastLeaveState),    NULL},
25     {FastLeaveCtrl,     DEF_8U,   DEF_32U,    0xFFFFFFBF,    NULL,                  SC(FastLeaveCtrl)},
26     {FaxModemConf,      0xFD,     DEF_32U,    0xFFFFFFBD,    GC(FaxModemConf),      SC(FaxModemConf)},
27     {SIPDigitMap,       0xFD,     DEF_32U,    0xFFFFFFBB,    NULL,                  SC(SIPDigitMap)},
28     //... ...
29 };
30 const INT32U gOamCmdMapNum = sizeof(gOamCmdFuncMap) / sizeof(OAM_CMD_MAP);
View Code

     其中,第一列为BLV结点值,第2~4列分别为产品、国家、地区掩码,后2列为处理函数指针。 

     例如。BranchLeaf名FaxModemConf对应的地区掩码为0xFFFFFFBD(1...10111101)表示江苏省和上海地区不支持该配置项。产品掩码含义与之类似。校验时黑白名单由下面的函数代替:

 1 BOOL IsBranchLeafSupported(OAM_BRANCH_LEAF eBranchLeaf)
 2 {
 3     INT32U dwMapIdx = 0;
 4     for(dwMapIdx = 0; dwMapIdx < gOamCmdMapNum; dwMapIdx++)
 5     {
 6         if(eBranchLeaf == gOamCmdFuncMap[dwMapIdx].eBranchLeaf)
 7             break;
 8 
 9     }
10     if(dwMapIdx == gOamCmdMapNum)
11     {
12         CtcOamLog(FUNCTION_Oam,"Unknown BranchLeaf(0x%08X)!\n", eBranchLeaf);
13         return FALSE;
14     }
15     
16     if(GET_BIT(gOamCmdFuncMap[dwMapIdx].ucProductMask, PRODUCT_SHIFT)  //也可先&&后GET_BIT
17     && GET_BIT(gOamCmdFuncMap[dwMapIdx].dwNationMask, gdwRegionVer.ucNatShift) 
18     && GET_BIT(gOamCmdFuncMap[dwMapIdx].dwRegionMask, gdwRegionVer.ucRegShift))
19         return TRUE;
20 
21     return FALSE;   
22 }
View Code

 

四、总结说明

     1. 采用掩码的表示方法,可极大地消除冗余度和增强扩展性。

     可支持10个产品、32个国家及31个地区的不同配置能力,已支持5个产品、1个国家(缺省)和两个地区,后续新增产品、国家、地区只需要修改掩码值即可,无需增加代码。

     2. 相比原有做法,掩码方式在可读性和易用性方面稍嫌不足,可编写掩码的生成和解析函数或工具予以弥补。