vlan-mapping映射功能设计

一、功能需求

      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下发如上示列所示配置,最后以映射关系存在shared_memory中,但show配置时,又要将配置恢复为如上示列所示(所以数据结构用——双链表,这样保证配置删除和恢复可靠性),比如配置是这样的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,所以考虑查找速度快用——数组 + bitmap

额外:转发层的表项结构——都是hash桶的结构,求hash值,再对应的槽位,添加节点(节点是从统一的一个单链表pool拿过来的),当删除释放时,又将此节点放回单链表pool 

四、数据结构设计

#ifndef _VLAN_MAPPING_H
#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)

/* node of per config */
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实现 

/* double-list head */
struct vlan_mapping_head {
    u_int8_t length;
    struct list_head lists;
}; 

/* init head */
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

五、将配置从结构体恢复为CLI示列所示——代码
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 != '\0') {    
                    p++;
                }
                sprintf(p, "-%d", *base);    
                *base = vlan_id;    
                *continuous = 0;    
                while (*p != '\0') {
                    p++;    
                }    
                sprintf(p, ",%d", vlan_id);    
            }    
        }    
    } else {    
        if ((vlan_id - (*base)) == 1) {    
            *base = vlan_id;    
            *continuous = 1;    
        } else {    
            *base = vlan_id;    
            while (*p != '\0') {    
                p++;    
            }    
            sprintf(p, ",%d", vlan_id);    
        }    
    }    
}

void vlan_mapping_config_write(struct cli *cli, struct vlan_mapping_head *h)
{    
    struct nsm_vlan_mapping *node;    
    struct list_head *pos, *n;    
    u_int16_t i;
    
    list_for_each_safe(pos, n, &h->lists) {    
        if (!(node = list_entry(pos, struct nsm_vlan_mapping, lists))) {
            break;    
        }    
        u_int16_t base = 0, continuous = 1, first  = 1;
        u_int16_t end = 0, continuouss = 1, firsts = 1;
        u_int16_t coming_vlan, mapped_vlan;
        char coming_v[256] = {0};    
        char mapped_v[256] = {0};
        
        i = 0;
        while (i < node->cnt) {    
            coming_vlan = node->coming_index[i];    
            if (VLAN_MAP_BITMAP_EXISTED(node->coming_bitmap, coming_vlan)) {    
                show_vlan_mapping_config(coming_v, coming_vlan, &base, &continuous, &first);
            }
            
            mapped_vlan = node->coming_vlan[coming_vlan];
            if (VLAN_MAP_BITMAP_EXISTED(node->mapped_bitmap, mapped_vlan)) {    
                show_vlan_mapping_config(mapped_v, mapped_vlan, &end, &continuouss, &firsts);    
            }    
            i++;    
        }    
    
        if (continuous == 1 && base != 0) {     
            char *p = coming_v;    
            while (*p != '\0') {    
                p++;    
            }    
            sprintf(p, "-%d", base);
        }
    
        if (continuouss == 1 && end != 0) {     
            char *p = mapped_v;    
            while (*p != '\0') {    
                p++;    
            }
            sprintf(p, "-%d", end);    
        }    
        
        cli_out (cli, "    vlan-mapping vlan %s map-vlan %s\n", coming_v, mapped_v);
    }    
}

 六、需要注意bitmap——64位系统一定要用 0X1LL,之前就是被这里坑了 

#define VLAN_MAP_BITMAP_WIDTH       (64)
#define VLAN_MAP_BITMAP_SET(bitmap, vlan_id)                                    \
    do {                                                                        \
        int _word = (vlan_id) / VLAN_MAP_BITMAP_WIDTH;                          \
        bitmap[_word] |= (0x1LL << ((vlan_id) % VLAN_MAP_BITMAP_WIDTH));        \
    } while (0)

猜你喜欢

转载自blog.csdn.net/BBOYWISH/article/details/106258414