三层交换机之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_XLATEEGR_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) 最多支持128VLAN RANGE profiles

2) 每个VLAN RANGE profile最多支持8VLAN RANGEs

3) 同一个VLAN RANGE profile内的8VLAN RANGEs不能重叠

4) CVIDPVID/SVID不能重叠

过程如下:

1) 入端口报文CVID进入VLAN range checking逻辑,通过(MODID, port)索引VLAN_RANGE_IDX表,返回指向IGR_VLAN_RANGE_TBL的索引号;

2) IGR_VLAN_RANGE_TBL的每个表项包含6VLAN对(MIN,MAX)支持6VLAN范围段;如果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);
原文地址:https://www.cnblogs.com/justin-y-lin/p/14776727.html