博通交換芯片中,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);