三层交换机之VLAN_XLATE
博通交换芯片中,QinQ域功能实现主要依赖于VLAN_XLATE和VCAP(VFP)资源实现。其中,VLAN_XLATE实现常规QinQ域;VCAP实现灵活QinQ域,因为灵活QinQ域需要匹配除VLAN和MAC之外的其他字段,比如EtherType、IpProtocol、UDP Src/Dst Port等,这种方式又称为基于流(Based on Flow)。
VLAN_XLATE和EGR_VLAN_XLATE表均包含多个表项资源,使用Hash算法查找。
VLAN_XLATE
VLAN_XLATE表查找有两种相互独立的方式,首先使用PORT_TAB.VT_KEY_TYPE作为Key值进行Hash查找,查找失败的情况下,继续使用PORT_TAB.VT_KEY_TYPE2作为Key值进行Hash查找。
/* Key types for vlan translation lookup. */ typedef enum bcm_vlan_translate_key_e { bcmVlanTranslateKeyInvalid, /* Invalid Key Type. */ bcmVlanTranslateKeyDouble, /* Use O-VID[11:0] and I-VID[11:0]. */ bcmVlanTranslateKeyOuter, /* Use O-VID[11:0] */ bcmVlanTranslateKeyInner, /* Use I-VID[11:0] */ bcmVlanTranslateKeyOuterTag, /* Use O-TAG[15:0] */ bcmVlanTranslateKeyInnerTag, /* Use I-TAG[15:0] */ bcmVlanTranslateKeyOuterPri, /* Use (VLAN-PRI, VLAN-CFI => O-TAG[15:12]) */ bcmVlanTranslateKeyPortDouble, /* Use Port, O-VID[11:0] and I-VID[11:0]. */ bcmVlanTranslateKeyPortOuter, /* Use Port, O-VID[11:0] */ bcmVlanTranslateKeyPortInner, /* Use Port, I-VID[11:0] */ bcmVlanTranslateKeyPortOuterTag, /* Use Port, O-TAG[15:0] */ bcmVlanTranslateKeyPortInnerTag, /* Use Port, I-TAG[15:0] */ bcmVlanTranslateKeyPortOuterPri /* Use Port, (VLAN-PRI, VLAN-CFI =>O-TAG[15:12]) */ } bcm_vlan_translate_key_t;
EGR_VLAN_XLATE
首先进行DT查找,然后进行OVID查找。
VLAN RANGE CHECKING
允许将CVID(Customer VLAN ID)或者IVID(Inner VLAN ID)范围段映射到相同的PVID/SVID/OVID,这样可以使用一条VLAN_XLATE表项和VLAN_PROFILE表项实现,从而节省VLAN_XLATE资源:
1) 最多支持128个VLAN RANGE profiles
2) 每个VLAN RANGE profile最多支持8个VLAN RANGEs
3) 同一个VLAN RANGE profile内的8个VLAN RANGEs不能重叠
4) CVID和PVID/SVID不能重叠
过程如下:
1) 入端口报文CVID进入VLAN range checking逻辑,通过(MODID, port)索引VLAN_RANGE_IDX表,返回指向IGR_VLAN_RANGE_TBL的索引号;
2) IGR_VLAN_RANGE_TBL的每个表项包含6个VLAN对(MIN,MAX)支持6个VLAN范围段;如果CVID与任意VLAN对匹配,则命中,该报文的CVID被替换为VLAN_MIN值;如果未命中,则CVID用来进行VLAN_XLATE查找;
BCM SDK API
Ingress
/* Add an entry to the VLAN Translation table. */ extern int bcm_vlan_translate_add( int unit, int port, bcm_vlan_t old_vid, bcm_vlan_t new_vid, int prio);
将指定端口入端口old_vid的报文转换为new_vid的报文。
对于StrataXGS III系列交换芯片,支持优先级替换,prio为-1表示转换后不更改报文优先级,prio为0~7表示转换后的报文优先级。
对于支持VLAN action API的交换芯片,prio表示内部优先级,不支持-1。
/* Add an entry to the VLAN Translation table. */ extern int bcm_vlan_translate_get( int unit, int port, bcm_vlan_t old_vid, bcm_vlan_t *new_vid, int *prio);
/* Delete an entry or entries from the VLAN Translation table. */ extern int bcm_vlan_translate_delete( int unit, int port, bcm_vlan_t old_vid);
删除old_vid相关的所有VLAN_XLATE表项
/* Remove all entries from the VLAN Translation table. */ extern int bcm_vlan_translate_delete_all( int unit);
/* Add an entry to the VLAN Translation table and assign VLAN actions. */ extern int bcm_vlan_translate_action_add( int unit, bcm_gport_t port, bcm_vlan_translate_key_t key_type, bcm_vlan_t outer_vlan, bcm_vlan_t inner_vlan, bcm_vlan_action_set_t *action);
key_type必须为bcmVlanPortTranslateKeyFirst或者bcmVlanPortTranslateKeySecond之一,它们由bcm_vlan_control_port_set配置,可以通过bcm_vlan_control_port_get获取。
使用bcm_vlan_translate_action_add创建VLAN_XLATE表项转换的报文必须是tagged。
/* Get an entry to the VLAN Translation table and assign VLAN actions. */ extern int bcm_vlan_translate_action_get( int unit, bcm_gport_t port, bcm_vlan_translate_key_t key_type, bcm_vlan_t outer_vlan, bcm_vlan_t inner_vlan, bcm_vlan_action_set_t *action);
/* Delete an entry from the VLAN Translation table. */ extern int bcm_vlan_translate_action_delete( int unit, bcm_gport_t port, bcm_vlan_translate_key_t key_type, bcm_vlan_t outer_vlan, bcm_vlan_t inner_vlan);
获取指定端口、key_type和VLAN的VLAN_XLATE动作。
Egress
/* Add an entry to the egress VLAN Translation table. */ extern int bcm_vlan_translate_egress_add( int unit, int port, bcm_vlan_t old_vid, bcm_vlan_t new_vid, int prio);
/* Get an entry to the egress VLAN Translation table. */ extern int bcm_vlan_translate_egress_get( int unit, int port, bcm_vlan_t old_vid, bcm_vlan_t *new_vid, int *prio);
/* Remove an entry or entries from the VLAN egress Translation table. */ extern int bcm_vlan_translate_egress_delete( int unit, int port, bcm_vlan_t old_vid);
/* Remove all entries from the egress VLAN Translation table. */ extern int bcm_vlan_translate_egress_delete_all( int unit);
/* * Add an entry to the egress VLAN Translation table and assign VLAN * actions. */ extern int bcm_vlan_translate_egress_action_add( int unit, int port_class, bcm_vlan_t outer_vlan, bcm_vlan_t inner_vlan, bcm_vlan_action_set_t *action);
/* * Get an entry to the egress VLAN Translation table and assign VLAN * actions. */ extern int bcm_vlan_translate_egress_action_get( int unit, int port_class, bcm_vlan_t outer_vlan, bcm_vlan_t inner_vlan, bcm_vlan_action_set_t *action);
/* Delete an entry from the egress VLAN Translation table. */ extern int bcm_vlan_translate_egress_action_delete( int unit, int port_class, bcm_vlan_t outer_vlan, bcm_vlan_t inner_vlan);
Dtag & Vlan Range
/* Add an entry to the VLAN Translation table for double-tagging. */ extern int bcm_vlan_dtag_add( int unit, int port, bcm_vlan_t old_vid, bcm_vlan_t new_vid, int prio);
对入端口VLAN为old_vid的single inner-tagged的报文添加new_vid的外层VLAN。
/* Get an entry to the VLAN Translation table for double-tagging. */ extern int bcm_vlan_dtag_get( int unit, int port, bcm_vlan_t old_vid, bcm_vlan_t *new_vid, int *prio);
/* Remove an entry from the VLAN Translation table for double-tagging. */ extern int bcm_vlan_dtag_delete( int unit, int port, bcm_vlan_t old_vid);
/* Remove all entries from the VLAN Translation table for double-tagging. */ extern int bcm_vlan_dtag_delete_all( int unit);
/* Add a VLAN range to the VLAN Translation table. */ extern int bcm_vlan_translate_range_add( int unit, int port, bcm_vlan_t old_vid_low, bcm_vlan_t old_vid_high, bcm_vlan_t new_vid, int int_prio);
将入端口VLAN在old_vid_low~old_vid_high范围以内的报文,转换为new_vid的报文。
/* Get a VLAN range to the VLAN Translation table. */ extern int bcm_vlan_translate_range_get( int unit, int port, bcm_vlan_t old_vid_low, bcm_vlan_t old_vid_high, bcm_vlan_t *new_vid, int *int_prio);
/* Delete a VLAN range from the VLAN Translation table. */ extern int bcm_vlan_translate_range_delete( int unit, int port, bcm_vlan_t old_vid_low, bcm_vlan_t old_vid_high);
/* Remove all VLAN ranges from the VLAN Translation table. */ extern int bcm_vlan_translate_range_delete_all( int unit);
/* Add VLAN range to the VLAN Translation table for double-tagging. */ extern int bcm_vlan_dtag_range_add( int unit, int port, bcm_vlan_t old_vid_low, bcm_vlan_t old_vid_high, bcm_vlan_t new_vid, int int_prio);
对于入端口VLAN在old_vid_low~old_vid_high范围内的single inner-tagged的报文,添加new_vid的外层VLAN。
/* Get VLAN range to the VLAN Translation table for double-tagging. */ extern int bcm_vlan_dtag_range_get( int unit, int port, bcm_vlan_t old_vid_low, bcm_vlan_t old_vid_high, bcm_vlan_t *new_vid, int *prio);
/* * Remove a VLAN range from the VLAN Translation table for * double-tagging. */ extern int bcm_vlan_dtag_range_delete( int unit, int port, bcm_vlan_t old_vid_low, bcm_vlan_t old_vid_high);
/* * Remove all VLAN ranges from the VLAN Translation table for * double-tagging. */ extern int bcm_vlan_dtag_range_delete_all( int unit);
/* bcm_vlan_translate_action_range_add */ extern int bcm_vlan_translate_action_range_add( int unit, bcm_gport_t port, bcm_vlan_t outer_vlan_low, bcm_vlan_t outer_vlan_high, bcm_vlan_t inner_vlan_low, bcm_vlan_t inner_vlan_high, bcm_vlan_action_set_t *action);
如果要转换double-tagged或者single outer-tagged报文,那么outer_vlan_low/high用来指定入端口报文外层VLAN的范围,inner_vlan_low/high必须指定为BCM_VLAN_INVALID。同时,入端口必须通过bcm_vlan_control_port_set配置为bcmVlanPortTranslateKeyOuter。
如果要转换single inner-tagged报文,那么inner_vlan_low/high指定VLAN范围,outer_vlan_low/high必须指定为BCM_VLAN_INVALID。同时,入端口必须通过bcm_vlan_control_port_set配置为bcmVlanPortTranslateKeyInner。
对于untagged报文,该VLAN_XLATE表项无效。
/* bcm_vlan_translate_action_range_get */ extern int bcm_vlan_translate_action_range_get( int unit, bcm_gport_t port, bcm_vlan_t outer_vlan_low, bcm_vlan_t outer_vlan_high, bcm_vlan_t inner_vlan_low, bcm_vlan_t inner_vlan_high, bcm_vlan_action_set_t *action);
/* bcm_vlan_translate_action_range_delete */ extern int bcm_vlan_translate_action_range_delete( int unit, bcm_gport_t port, bcm_vlan_t outer_vlan_low, bcm_vlan_t outer_vlan_high, bcm_vlan_t inner_vlan_low, bcm_vlan_t inner_vlan_high);
/* bcm_vlan_translate_action_range_delete_all */ extern int bcm_vlan_translate_action_range_delete_all( int unit);