一、功能需求       vlan-mapping,比如A公司想蹭腾讯的服务,为了成本以及A公司和腾讯的服务都不受影响,有了vlan-mapping,映射对应的vlan,比如将A公司的网络接入B公司,但由于A和B的配置不同,不可能将其改为一样的配置,所以有了此需求,vlan映射,相当于网络映射。 二、 大致流程 三、详细需求 1、支持如下四种配置,单个,多个,连续,混合模式 CLI配置示例: interface gigabitethernet 1/1     vlan-mapping vlan 100 map-vlan 500                       //上行:将vlan 100映射为vlan 500  下行:将vlan 500映射为vlan 100     vlan-mapping vlan 200,300 map-vlan 600,700     vlan-mapping vlan 3-6 map-vlan 13-16     vlan-mapping vlan 3-6,100,200 map-vlan 13-16,500,600 2、交换机接口支持配置80条vlan-maping配置,每条配置支持满配(4096个vlan)2048对vlan映射 3、CLI下发如上示列所示配置,data plane最后以映射关系存在shared_memory中,在报文转发时替换vlan tag。而CLI show配置时,是从control plane中的结构体中将配置恢复为如上示列所示(所以数据结构用——双链表,这样保证配置删除和恢复可靠性),比如配置是这样的vlan-mapping vlan 3-10 map-vlan 13-20,中途删除了vlan 4和vlan14的映射关系, 最后配置需要显示为, vlan-mapping vlan 3,5-10 map-vlan 13,15-20 4、在报文到来,有vlan-mapping配置时,需要查找映射的vlanid并对应替换vlan tag,查找速度快用——数组 + bitmap 额外:转发层的表项结构——都是hash桶的结构,求hash值,再对应的槽位,添加节点(节点是从统一的一个单链表pool拿过来的),当删除释放时,又将此节点放回单链表pool  四、数据结构设计 #ifndef _VLAN_MAPPING_H /* node of per config */ /* double-list head */ /* init head */   五、将配置从结构体恢复为CLI示列所示——代码
 #define _VLAN_MAPPING_H
     
 #include “./policyroute/policy_routemap_list.h”
     
 /* Vlan-mapping */
     
 #define VLAN_MAP_MAX_NUM            (4096)    
 #define VLAN_MAP_BITMAP             (64)
 #define VLAN_MAP_MAX_INDEX          (2048)    
 #define VLAN_MAP_CONFIG_MAX         (80)
struct nsm_vlan_mapping {    
     u_int16_t cnt;                                                                 /* count pair */    
     u_int16_t coming_vlan[VLAN_MAP_MAX_NUM];        /* save all vlan-map, index: coming_vlan, value: mapped_vlan*/    
     u_int16_t coming_index[VLAN_MAP_MAX_INDEX];   /* for show config, record coming_vlan order. index id 0,1,2…*/
     u_int64_t coming_bitmap[VLAN_MAP_BITMAP];        /* use search; bitmap of coming_vlan*/
     u_int64_t mapped_bitmap[VLAN_MAP_BITMAP];       /* use search; bitmap of mapped_vlan*/
     struct list_head lists;    
 }; //从访问速度、省内存,还有配置恢复考虑,用双向链表+数组+bitmap实现 
 struct vlan_mapping_head {
     u_int8_t length;
     struct list_head lists;
 }; 
 void init_vlan_mapping_head(struct vlan_mapping_head *h);
 /* create node */
 struct nsm_vlan_mapping *vlan_mapping_create_node();    
 /* Delete node */
 void vlan_mapping_del_node(struct nsm_vlan_mapping *node);    
 /* Delete all */
 void nsm_unset_vlan_mapping_all(struct vlan_mapping_head *h);    
 /* insert node */
 int vlan_mapping_insert_node(struct vlan_mapping_head *h, u_int16_t cnt, u_int64_t coming_bitmap[], u_int64_t mapped_bitmap[], u_int16_t coming_index[], u_int16_t coming_vlan[]);
 /* search node */
 void vlan_mapping_search_list(struct vlan_mapping_head *h, u_int16_t coming_v[], u_int16_t mapped_v[], u_int16_t cnt);
 /* convert bitmap */
 void convert_vlan_mapping2bitmap(u_int16_t vlan_v[], u_int16_t cnt, u_int64_t vlan_bitmap[]);
 /* check vlan characters len*/
 int check_vlan_mapping_characters_len(char *vlan_coming, char *vlan_mapped);     
 /* check illegal characters */
 int check_illegal_characters(char *vlan_coming, char *vlan_mapped); 
 /* check vlan id repetiton */    
 int check_vlan_id_repetition(u_int16_t vlan_coming[], u_int16_t vlan_mapped[], u_int16_t vlan_num);
 /* convert coming vlan */
 void record_coming_vlan_map(u_int16_t coming_vlan[], u_int16_t vlan_num, u_int16_t coming_v[], u_int16_t mapped_v[]);
 /* set configs */
 int nsm_set_vlan_mapping_config(struct vlan_mapping_head *h, u_int16_t coming_v[], u_int16_t mapped_v[], u_int16_t vlan_num);
 /* end Vlan-mapping */    
 #endif
 void show_vlan_mapping_config(char *vlan_v, uint16_t vlan_id, uint16_t *base, uint16_t *continuous, uint16_t *first)    
 {    
     char *p = vlan_v;    
     
     /* vlan-mapping vlan %d map-vlan %d */    
     if ((*continuous) == 1) {    
         if ((*first) == 1) {    
             *base = vlan_id;    
             *first = 0;    
             *continuous = 0;    
             sprintf(p, “%d”, vlan_id);    
         } else {
             if ((vlan_id – (*base)) == 1) {    
                 *base = vlan_id;
             } else {
                 while (*p != ‘