一、功能需求 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 != ‘