- Revision
- About this manual
- Scope
- Abbreviations
- 1 Introduction
- 2 Design
- 3 Test plan
Rev | Date | Author | Description |
---|---|---|---|
0.1 | 15/03/2021 | Nazarii Hnydyn | Initial version |
0.2 | 07/06/2021 | Nazarii Hnydyn | Update DB schema: introduce PBH hash field |
0.3 | 15/11/2021 | Nazarii Hnydyn | PBH modification flows: introduce field set/del |
This document provides general information about PBH implementation in SONiC
This document describes the high level design of PBH feature in SONiC
In scope:
- PBH for NVGRE/VxLAN packets based on inner 5-tuple (IP proto, L4 dst/src port, IPv4/IPv6 dst/src)
Out of scope:
- CRM support for PBH FG hash resources
Term | Meaning |
---|---|
SONiC | Software for Open Networking in the Cloud |
PBH | Policy Based Hashing |
CRM | Critical Resource Monitoring |
ACL | Access Control List |
SAI | Switch Abstraction Interface |
FG | Fine-Grained |
API | Application Programming Interface |
CRC | Cyclic Redundancy Check |
ID | Identifier |
ECMP | Equal-Cost Multi-Path |
LAG | Link Aggregation Group |
NVGRE | Network Virtualization Using Generic Routing Encapsulation |
VxLAN | Virtual eXtensible Local Area Network |
GRE | Generic Routing Encapsulation |
OA | Orchestration agent |
DB | Database |
CLI | Сommand-line Interface |
DPB | Dynamic Port Breakout |
YANG | Yet Another Next Generation |
VS | Virtual Switch |
PTF | Packet Test Framework |
Figure 1: PBH design
Figure 2: PBH OA design
Figure 3: PBH add flow
Figure 4: PBH remove flow
Figure 5: PBH update flow
PBH is a feature which allows user to configure a custom hashing for different packet types.
Under the hood it uses ACL rules to match the specific types of frames and calculates hash
based on user-defined rules.
For flexible hash calculation a new SAI FG Hash API is used.
It allows user not only to configure which fields should be used,
but also to specify a mask for IPv4/IPv6 addresses and sequence ID.
The last one defines in which order the fields are hashed,
and which of them should be associative for CRC with the same sequence ID.
PBH supports hash configuration for ECMP and LAG.
Both Regular ECMP and FG ECMP are eligible.
This feature will support the following functionality:
- NVGRE and VxLAN packets match with inner/outer IPv4/IPv6 frames
- Custom hashing based on inner 5-tuple: IP proto, L4 dst/src port, IPv4/IPv6 dst/src
- Hash configuration for Regular/FG ECMP and LAG
- Warm/Fast reboot
This feature will support the following commands:
- config: add/update/delete PBH table/rule/hash/hash-field configuration
- show: display PBH table/rule/hash/hash-field configuration and statistics
This feature will provide error handling for the next situations:
- Invalid object reference
- Incompatible options/parameters
This feature will provide event logging for the next situations:
- PBH table/rule/hash/hash-field add/update/delete
Event | Severity |
---|---|
PBH table/rule/hash/hash-field add/update/delete: success | NOTICE |
PBH table/rule/hash/hash-field add/update/delete: error | ERROR |
PBH uses ACL engine to match NVGRE/VxLAN packets and calculates hash based on user-defined rules.
Hashing is configured based on inner 5-tuple: IP proto, L4 dst/src port, IPv4/IPv6 dst/src.
A custom hashing can be configured for Regular/FG ECMP and LAG.
SAI attributes which shall be used for PBH:
API | Function | Attribute | Comment |
---|---|---|---|
ACL | create_acl_table | SAI_ACL_TABLE_ATTR_FIELD_GRE_KEY | |
SAI_ACL_TABLE_ATTR_FIELD_ETHER_TYPE | |||
SAI_ACL_TABLE_ATTR_FIELD_IP_PROTOCOL | |||
SAI_ACL_TABLE_ATTR_FIELD_IPV6_NEXT_HEADER | |||
SAI_ACL_TABLE_ATTR_FIELD_L4_DST_PORT | |||
SAI_ACL_TABLE_ATTR_FIELD_INNER_ETHER_TYPE | |||
create_acl_entry | SAI_ACL_ENTRY_ATTR_PRIORITY | PBH_RULE|priority | |
SAI_ACL_ENTRY_ATTR_FIELD_GRE_KEY | PBH_RULE|gre_key | ||
SAI_ACL_ENTRY_ATTR_FIELD_ETHER_TYPE | PBH_RULE|ether_type | ||
SAI_ACL_ENTRY_ATTR_FIELD_IP_PROTOCOL | PBH_RULE|ip_protocol | ||
SAI_ACL_ENTRY_ATTR_FIELD_IPV6_NEXT_HEADER | PBH_RULE|ipv6_next_header | ||
SAI_ACL_ENTRY_ATTR_FIELD_L4_DST_PORT | PBH_RULE|l4_dst_port | ||
SAI_ACL_ENTRY_ATTR_FIELD_INNER_ETHER_TYPE | PBH_RULE|inner_ether_type | ||
SAI_ACL_ENTRY_ATTR_ACTION_SET_LAG_HASH_ID | PBH_RULE|packet_action | ||
SAI_ACL_ENTRY_ATTR_ACTION_SET_ECMP_HASH_ID | PBH_RULE|packet_action | ||
SAI_ACL_ENTRY_ATTR_ACTION_COUNTER | PBH_RULE|flow_counter | ||
HASH | create_hash | SAI_HASH_ATTR_FINE_GRAINED_HASH_FIELD_LIST | PBH_HASH|hash_field_list |
create_fine_grained_hash_field | SAI_FINE_GRAINED_HASH_FIELD_ATTR_NATIVE_HASH_FIELD | PBH_HASH_FIELD|hash_field | |
SAI_FINE_GRAINED_HASH_FIELD_ATTR_IPV4_MASK | PBH_HASH_FIELD|ip_mask | ||
SAI_FINE_GRAINED_HASH_FIELD_ATTR_IPV6_MASK | PBH_HASH_FIELD|ip_mask | ||
SAI_FINE_GRAINED_HASH_FIELD_ATTR_SEQUENCE_ID | PBH_HASH_FIELD|sequence_id |
A PbhOrch
class with a set of data structures will be implemented to handle PBH feature.
OA will be extended with a new PBH Config DB/State DB schema and SAI FG Hash API support.
PBH table/rule/hash/hash-field updates will be processed by OA based on Config DB changes.
Each update operation will be verified against generic/vendor specific capabilities.
Generic/Vendor specific capabilities by default will be stored in State DB by OA.
Some object updates will be handled and some will be considered as invalid.
Class PbhOrch
will hold a set of methods matching generic Orch
class pattern to handle Config DB updates.
For that purpose a producer-consumer mechanism (implemented in sonic-swss-common
) will be used.
Method PbhOrch::doTask()
will be called on PBH table/rule/hash/hash-field update. It will distribute handling
of DB updates between other handlers based on the table key which was updated (Redis Keyspace Notifications).
This class will be responsible for:
- Processing updates of the PBH table/rule/hash/hash-field (add/remove)
- Partial input PBH data validation (including cross-table validation)
- Replicating PBH data from the Config DB to the SAI DB via SAI Redis
- Caching of the PBH objects in order to detect objects update and perform state dump
PBH table objects are stored under PBH_TABLE:*
keys in Config DB. On PBH_TABLE
update,
method PbhOrch::doPbhTableTask()
will be called to process the change.
On table create, PbhOrch
will verify if the table already exists. Creating the table which is already
exists will be treated as an update. Regular table add/remove will update the internal class structures
and appropriate SAI objects will be created/deleted.
PBH rule objects are stored under PBH_RULE:*
keys in Config DB. On PBH_RULE
update,
method PbhOrch::doPbhRuleTask()
will be called to process the change.
On rule create, PbhOrch
will verify if the rule already exists. Creating the rule which is already
exists will be treated as an update. Regular rule add/remove will update the internal class structures
and appropriate SAI objects will be created/deleted.
PBH hash objects are stored under PBH_HASH:*
keys in Config DB. On PBH_HASH
update,
method PbhOrch::doPbhHashTask()
will be called to process the change.
On hash create, PbhOrch
will verify if the hash already exists. Creating the hash which is already
exists will be treated as an update. Regular hash add/remove will update the internal class structures
and appropriate SAI objects will be created or deleted.
PBH hash field objects are stored under PBH_HASH_FIELD:*
keys in Config DB. On PBH_HASH_FIELD
update,
method PbhOrch::doPbhHashFieldTask()
will be called to process the change.
On hash field create, PbhOrch
will verify if the hash field already exists. Creating the hash field which is already
exists will be treated as an update. Regular hash field add/remove will update the internal class structures
and appropriate SAI objects will be created or deleted.
PBH object modification concept allows to do a fine-grained field/value tuple management.
For that purpose a PBH capabilities table will be introduced. Each PBH key will have it's own set of
field capabilities defined in a State DB.
PBH capabilities:
- ADD - field can be set to the redis hash in case it does not exist yet
- UPDATE - field can be set to the redis hash in case it already exists
- REMOVE - field can be deleted from the redis hash in case it does exist
In general, PBH capabilities represent a mix of SAI interface/vendor restrictions.
When special policy is not required, a generic SAI-based implementation will be used by OA.
Platform/Vendor identification will be done via platform
environment variable.
Skeleton code:
class PbhOrch : public Orch
{
public:
PbhOrch(
std::vector<TableConnector> &connectorList,
AclOrch *aclOrch,
PortsOrch *portsOrch
);
~PbhOrch();
using Orch::doTask; // Allow access to the basic doTask
private:
void doPbhTableTask(Consumer &consumer);
void doPbhRuleTask(Consumer &consumer);
void doPbhHashTask(Consumer &consumer);
void doPbhHashFieldTask(Consumer &consumer);
void doTask(Consumer &consumer);
AclOrch *aclOrch;
PortsOrch *portsOrch;
};
This orchestrator provides API for ACL table/rule configuration.
It is already exists in SONiC.
ACL orchestrator will be extended to support PBH table/rule concept.
PBH table will use a dedicated set of keys to allow match of NVGRE and VxLAN packets.
Skeleton code:
class AclOrch : public Orch, public Observer
{
...
bool updateAclTable(string table_id, AclTable &table);
bool updateAclRule(shared_ptr<AclRule> updatedAclRule);
...
};
class AclTable
{
...
bool validateAddType(const acl_table_type_t &value);
bool validateAddStage(const acl_stage_type_t &value);
bool validateAddPorts(const unordered_set<string> &value);
...
};
bool AclTable::create()
{
...
if (type == ACL_TABLE_PBH)
{
attr.id = SAI_ACL_TABLE_ATTR_ACL_STAGE;
attr.value.s32 = SAI_ACL_STAGE_INGRESS;
table_attrs.push_back(attr);
attr.id = SAI_ACL_TABLE_ATTR_FIELD_GRE_KEY;
attr.value.booldata = true;
table_attrs.push_back(attr);
attr.id = SAI_ACL_TABLE_ATTR_FIELD_ETHER_TYPE;
attr.value.booldata = true;
table_attrs.push_back(attr);
attr.id = SAI_ACL_TABLE_ATTR_FIELD_IP_PROTOCOL;
attr.value.booldata = true;
table_attrs.push_back(attr);
attr.id = SAI_ACL_TABLE_ATTR_FIELD_IPV6_NEXT_HEADER;
attr.value.booldata = true;
table_attrs.push_back(attr);
attr.id = SAI_ACL_TABLE_ATTR_FIELD_L4_DST_PORT;
attr.value.booldata = true;
table_attrs.push_back(attr);
attr.id = SAI_ACL_TABLE_ATTR_FIELD_INNER_ETHER_TYPE;
attr.value.booldata = true;
table_attrs.push_back(attr);
sai_status_t status = sai_acl_api->create_acl_table(&m_oid, gSwitchId, (uint32_t)table_attrs.size(), table_attrs.data());
if (status == SAI_STATUS_SUCCESS)
{
gCrmOrch->incCrmAclUsedCounter(CrmResourceType::CRM_ACL_TABLE, SAI_ACL_STAGE_INGRESS, SAI_ACL_BIND_POINT_TYPE_PORT);
gCrmOrch->incCrmAclUsedCounter(CrmResourceType::CRM_ACL_TABLE, SAI_ACL_STAGE_INGRESS, SAI_ACL_BIND_POINT_TYPE_LAG);
}
return status == SAI_STATUS_SUCCESS;
}
...
}
class AclRulePbh: public AclRule
{
public:
AclRulePbh(AclOrch *pAclOrch, string rule, string table, bool createCounter = false);
bool validateAddPriority(const sai_uint32_t &value);
bool validateAddMatch(const sai_attribute_t &attr);
bool validateAddAction(const sai_attribute_t &attr);
bool validate() override;
void onUpdate(SubjectType, void *) override;
};
; defines schema for PBH table configuration attributes
key = PBH_TABLE|table_name ; table name. Must be unique
; field = value
interface_list = interface-list ; interfaces to which this table is applied
description = 1*255VCHAR ; table description
; value annotations
port-name = 1*64VCHAR ; name of the port
lag-name = "PortChannel" 1*4DIGIT ; name of the portchannel
interface-name = port-name / lag-name ; name of the interface
interface-list = interface-name [ 1*( "," interface-name ) ] ; list of the interfaces. Valid values range is platform dependent
Note: at least one member of interface_list is required
; defines schema for PBH rule configuration attributes
key = PBH_RULE|table_name|rule_name ; rule name. Must be unique across the table
; field = value
priority = 1*5DIGIT ; rule priority. Valid values range is platform dependent.
; The evaluation order is descending: the higher priorities shall be evaluated first
gre_key = h32 "/" h32 ; GRE key (32 bits)
ether_type = h16 ; EtherType (16 bits)
ip_protocol = h8 ; IP protocol (8 bits)
ipv6_next_header = h8 ; IPv6 Next Header (8 bits)
l4_dst_port = h16 ; L4 destination port (16 bits)
inner_ether_type = h16 ; Inner EtherType (16 bits)
hash = 1*255VCHAR ; Hash (PBH_HASH|hash_name)
packet_action = packet-action ; Packet action
flow_counter = flow-counter ; Packet/Byte counter
; value annotations
h8 = 1*2HEXDIG
h16 = 1*4HEXDIG
h32 = 1*8HEXDIG
packet-action = "SET_ECMP_HASH" / "SET_LAG_HASH"
flow-counter = "DISABLED" / "ENABLED"
Note: at least one match field (gre_key/ether_type/ip_protocol/etc.) is required
; defines schema for PBH hash configuration attributes
key = PBH_HASH|hash_name ; hash name. Must be unique
; field = value
hash_field_list = hash-field-list ; Hash field list (PBH_HASH_FIELD|hash_field_name)
; value annotations
hash-field-name = 1*255VCHAR
hash-field-list = hash-field-name [ 1*( "," hash-field-name ) ]
Note: at least one member of hash_field_list is required
; defines schema for PBH hash field configuration attributes
key = PBH_HASH_FIELD|hash_field_name ; hash field name. Must be unique
; field = value
hash_field = hash-field ; Hash native field
ip_mask = ip-mask ; Mask for a IPv4/IPv6 address.
; Valid only when hash_field is one of:
; INNER_SRC_IPV4, INNER_DST_IPV4,
; INNER_SRC_IPV6, INNER_DST_IPV6
sequence_id = 1*5DIGIT ; Specifies in which order the fields are hashed,
; and defines which fields should be associative
; for CRC with the same sequence ID
; value annotations
hash-field = "INNER_IP_PROTOCOL"
/ "INNER_L4_DST_PORT"
/ "INNER_L4_SRC_PORT"
/ "INNER_DST_IPV4"
/ "INNER_SRC_IPV4"
/ "INNER_DST_IPV6"
/ "INNER_SRC_IPV6"
h16 = 1*4HEXDIG
ls32 = h16 ":" h16
dec-octet = DIGIT ; 0-9
/ %x31-39 DIGIT ; 10-99
/ "1" 2DIGIT ; 100-199
/ "2" %x30-34 DIGIT ; 200-249
/ "25" %x30-35 ; 250-255
ipv4-addr = dec-octet "." dec-octet "." dec-octet "." dec-octet
ipv6-addr = 6( h16 ":" ) ls32
/ "::" 5( h16 ":" ) ls32
/ [ h16 ] "::" 4( h16 ":" ) ls32
/ [ *1( h16 ":" ) h16 ] "::" 3( h16 ":" ) ls32
/ [ *2( h16 ":" ) h16 ] "::" 2( h16 ":" ) ls32
/ [ *3( h16 ":" ) h16 ] "::" h16 ":" ls32
/ [ *4( h16 ":" ) h16 ] "::" ls32
/ [ *5( h16 ":" ) h16 ] "::" h16
/ [ *6( h16 ":" ) h16 ] "::"
ip-mask = ipv4-addr / ipv6-addr
Note: field ip_mask is only valid when hash_field equals INNER_DST/SRC_IPV4 or INNER_DST/SRC_IPV6
; defines schema for PBH table capabilities
key = PBH_CAPABILITIES|table ; must be unique
; field = value
interface_list = capabilities
description = capabilities
; value annotations
capabilities = "" \ "ADD" \ "UPDATE" \ "REMOVE" \
"ADD" "," "UPDATE" \
"ADD" "," "REMOVE" \
"UPDATE" "," "ADD" \
"UPDATE" "," "REMOVE" \
"REMOVE" "," "ADD" \
"REMOVE" "," "UPDATE" \
"ADD" "," "UPDATE" "," "REMOVE"
; defines schema for PBH rule capabilities
key = PBH_CAPABILITIES|rule ; must be unique
; field = value
priority = capabilities
gre_key = capabilities
ether_type = capabilities
ip_protocol = capabilities
ipv6_next_header = capabilities
l4_dst_port = capabilities
inner_ether_type = capabilities
hash = capabilities
packet_action = capabilities
flow_counter = capabilities
; value annotations
capabilities = "" \ "ADD" \ "UPDATE" \ "REMOVE" \
"ADD" "," "UPDATE" \
"ADD" "," "REMOVE" \
"UPDATE" "," "ADD" \
"UPDATE" "," "REMOVE" \
"REMOVE" "," "ADD" \
"REMOVE" "," "UPDATE" \
"ADD" "," "UPDATE" "," "REMOVE"
; defines schema for PBH hash capabilities
key = PBH_CAPABILITIES|hash ; must be unique
; field = value
hash_field_list = capabilities
; value annotations
capabilities = "" \ "ADD" \ "UPDATE" \ "REMOVE" \
"ADD" "," "UPDATE" \
"ADD" "," "REMOVE" \
"UPDATE" "," "ADD" \
"UPDATE" "," "REMOVE" \
"REMOVE" "," "ADD" \
"REMOVE" "," "UPDATE" \
"ADD" "," "UPDATE" "," "REMOVE"
; defines schema for PBH hash field capabilities
key = PBH_CAPABILITIES|hash-field ; must be unique
; field = value
hash_field = capabilities
ip_mask = capabilities
sequence_id = capabilities
; value annotations
capabilities = "" \ "ADD" \ "UPDATE" \ "REMOVE" \
"ADD" "," "UPDATE" \
"ADD" "," "REMOVE" \
"UPDATE" "," "ADD" \
"UPDATE" "," "REMOVE" \
"REMOVE" "," "ADD" \
"REMOVE" "," "UPDATE" \
"ADD" "," "UPDATE" "," "REMOVE"
Config DB:
redis-cli -n 4 HGETALL 'PBH_HASH_FIELD|inner_ip_proto'
1) "hash_field"
2) "INNER_IP_PROTOCOL"
3) "sequence_id"
4) "1"
redis-cli -n 4 HGETALL 'PBH_HASH_FIELD|inner_l4_dst_port'
1) "hash_field"
2) "INNER_L4_DST_PORT"
3) "sequence_id"
4) "2"
redis-cli -n 4 HGETALL 'PBH_HASH_FIELD|inner_l4_src_port'
1) "hash_field"
2) "INNER_L4_SRC_PORT"
3) "sequence_id"
4) "2"
redis-cli -n 4 HGETALL 'PBH_HASH_FIELD|inner_dst_ipv4'
1) "hash_field"
2) "INNER_DST_IPV4"
3) "ip_mask"
4) "255.0.0.0"
5) "sequence_id"
6) "3"
redis-cli -n 4 HGETALL 'PBH_HASH_FIELD|inner_src_ipv4'
1) "hash_field"
2) "INNER_SRC_IPV4"
3) "ip_mask"
4) "0.0.0.255"
5) "sequence_id"
6) "3"
redis-cli -n 4 HGETALL 'PBH_HASH_FIELD|inner_dst_ipv6'
1) "hash_field"
2) "INNER_DST_IPV6"
3) "ip_mask"
4) "ffff::"
5) "sequence_id"
6) "4"
redis-cli -n 4 HGETALL 'PBH_HASH_FIELD|inner_src_ipv6'
1) "hash_field"
2) "INNER_SRC_IPV6"
3) "ip_mask"
4) "::ffff"
5) "sequence_id"
6) "4"
redis-cli -n 4 HGETALL 'PBH_HASH|inner_v4_hash'
1) "hash_field_list@"
2) "inner_ip_proto,inner_l4_dst_port,inner_l4_src_port,inner_dst_ipv4,inner_src_ipv4"
redis-cli -n 4 HGETALL 'PBH_HASH|inner_v6_hash'
1) "hash_field_list@"
2) "inner_ip_proto,inner_l4_dst_port,inner_l4_src_port,inner_dst_ipv6,inner_src_ipv6"
redis-cli -n 4 HGETALL 'PBH_RULE|pbh_table|nvgre'
1) "ether_type"
2) "0x0800"
3) "flow_counter"
4) "DISABLED"
5) "gre_key"
6) "0x2500/0xffffff00"
7) "hash"
8) "inner_v6_hash"
9) "inner_ether_type"
10) "0x86dd"
11) "ip_protocol"
12) "0x2f"
13) "packet_action"
14) "SET_ECMP_HASH"
15) "priority"
16) "2"
redis-cli -n 4 HGETALL 'PBH_RULE|pbh_table|vxlan'
1) "ether_type"
2) "0x0800"
3) "flow_counter"
4) "ENABLED"
5) "hash"
6) "inner_v4_hash"
7) "inner_ether_type"
8) "0x0800"
9) "ip_protocol"
10) "0x11"
11) "l4_dst_port"
12) "0x12b5"
13) "packet_action"
14) "SET_LAG_HASH"
15) "priority"
16) "1"
redis-cli -n 4 HGETALL 'PBH_TABLE|pbh_table'
1) "description"
2) "NVGRE and VxLAN"
3) "interface_list@"
4) "Ethernet0,Ethernet4,PortChannel0001,PortChannel0002"
State DB:
redis-cli -n 6 HGETALL 'PBH_CAPABILITIES|table'
1) "interface_list"
2) "UPDATE"
3) "description"
4) "UPDATE"
redis-cli -n 6 HGETALL 'PBH_CAPABILITIES|rule'
1) "priority"
2) "UPDATE"
3) "ether_type"
4) "ADD,UPDATE,REMOVE"
5) "ip_protocol"
6) "ADD,UPDATE,REMOVE"
7) "ipv6_next_header"
8) "ADD,UPDATE,REMOVE"
9) "l4_dst_port"
10) "ADD,UPDATE,REMOVE"
11) "gre_key"
12) "ADD,UPDATE,REMOVE"
13) "inner_ether_type"
14) "ADD,UPDATE,REMOVE"
15) "hash"
16) "UPDATE"
17) "packet_action"
18) "ADD,UPDATE,REMOVE"
19) "flow_counter"
20) "ADD,UPDATE,REMOVE"
redis-cli -n 6 HGETALL 'PBH_CAPABILITIES|hash'
1) "hash_field_list"
2) "UPDATE"
redis-cli -n 6 HGETALL 'PBH_CAPABILITIES|hash-field'
1) "hash_field"
2) ""
3) "ip_mask"
4) ""
5) "sequence_id"
6) ""
Inner 5-tuple hashing:
{
"PBH_HASH_FIELD": {
"inner_ip_proto": {
"hash_field": "INNER_IP_PROTOCOL",
"sequence_id": "1"
},
"inner_l4_dst_port": {
"hash_field": "INNER_L4_DST_PORT",
"sequence_id": "2"
},
"inner_l4_src_port": {
"hash_field": "INNER_L4_SRC_PORT",
"sequence_id": "2"
},
"inner_dst_ipv4": {
"hash_field": "INNER_DST_IPV4",
"ip_mask": "255.0.0.0",
"sequence_id": "3"
},
"inner_src_ipv4": {
"hash_field": "INNER_SRC_IPV4",
"ip_mask": "0.0.0.255",
"sequence_id": "3"
},
"inner_dst_ipv6": {
"hash_field": "INNER_DST_IPV6",
"ip_mask": "ffff::",
"sequence_id": "4"
},
"inner_src_ipv6": {
"hash_field": "INNER_SRC_IPV6",
"ip_mask": "::ffff",
"sequence_id": "4"
}
},
"PBH_HASH": {
"inner_v4_hash": {
"hash_field_list": [
"inner_ip_proto",
"inner_l4_dst_port",
"inner_l4_src_port",
"inner_dst_ipv4",
"inner_src_ipv4"
]
},
"inner_v6_hash": {
"hash_field_list": [
"inner_ip_proto",
"inner_l4_dst_port",
"inner_l4_src_port",
"inner_dst_ipv6",
"inner_src_ipv6"
]
}
},
"PBH_RULE": {
"pbh_table|nvgre": {
"priority": "2",
"ether_type": "0x0800",
"ip_protocol": "0x2f",
"gre_key": "0x2500/0xffffff00",
"inner_ether_type": "0x86dd",
"hash": "inner_v6_hash",
"packet_action": "SET_ECMP_HASH",
"flow_counter": "DISABLED"
},
"pbh_table|vxlan": {
"priority": "1",
"ether_type": "0x0800",
"ip_protocol": "0x11",
"l4_dst_port": "0x12b5",
"inner_ether_type": "0x0800",
"hash": "inner_v4_hash",
"packet_action": "SET_LAG_HASH",
"flow_counter": "ENABLED"
}
},
"PBH_TABLE": {
"pbh_table": {
"interface_list": [
"Ethernet0",
"Ethernet4",
"PortChannel0001",
"PortChannel0002"
],
"description": "NVGRE and VxLAN"
}
}
}
User interface:
config
|--- pbh
|--- table
| |--- add <table_name> OPTIONS
| |--- update <table_name> OPTIONS
| |--- delete <table_name>
|
|--- rule
| |--- add <table_name> <rule_name> OPTIONS
| |--- update
| | |--- field
| | |--- set <table_name> <rule_name> OPTIONS
| | |--- del <table_name> <rule_name> OPTIONS
| |--- delete <table_name> <rule_name>
|
|--- hash
| |--- add <hash_name> OPTIONS
| |--- update <hash_name> OPTIONS
| |--- delete <hash_name>
|
|--- hash-field
|--- add <hash_field_name> OPTIONS
|--- update <hash_field_name> OPTIONS
|--- delete <hash_field_name>
show
|--- pbh
|--- table
|--- rule
|--- hash
|--- hash-field
|--- statistics
Options:
config pbh table add/update
- -i|--interface-list - interface list
- -d|--description - table description
config pbh rule add/update
- -p|--priority - rule priority
- -g|--gre-key - GRE key match
- -e|--ether-type - EtherType match
- -r|--ip-protocol - IP protocol match
- -n|--ipv6-next-header - IPv6 Next Header match
- -d|--l4-dst-port - L4 destination port
- -t|--inner-ether-type - inner EtherType match
- -h|--hash - hash
- -a|--packet-action=<SET_ECMP_HASH|SET_LAG_HASH> - packet action
- -c|--flow-counter=<DISABLED|ENABLED> - packet/byte counter
config pbh hash add/update
- -f|--hash-field-list - hash field list
config pbh hash-field add/update
- -f|--hash-field - hash field
- -m|--ip-mask - ip mask
- -s|--sequence-id - sequence id
The following command adds/updates/deletes table:
config pbh table add 'pbh_table' \
--interface-list 'Ethernet0,Ethernet4,PortChannel0001,PortChannel0002' \
--description 'NVGRE and VxLAN'
config pbh table update 'pbh_table' \
--interface-list 'Ethernet0'
config pbh table delete 'pbh_table'
The following command adds/updates/deletes rule:
config pbh rule add 'pbh_table' 'nvgre' \
--priority '2' \
--ether-type '0x0800' \
--ip-protocol '0x2f' \
--gre-key '0x2500/0xffffff00' \
--inner-ether-type '0x86dd' \
--hash 'inner_v6_hash' \
--packet-action 'SET_ECMP_HASH' \
--flow-counter 'DISABLED'
config pbh rule update field del 'pbh_table' 'nvgre' \
--ip-protocol
config pbh rule update field set 'pbh_table' 'nvgre' \
--ether-type '0x86dd' \
--ipv6-next-header '0x2f' \
--flow-counter 'ENABLED'
config pbh rule delete 'pbh_table' 'nvgre'
The following command adds/updates/deletes hash:
config pbh hash add 'inner_v6_hash' \
--hash-field-list 'inner_ip_proto,inner_l4_dst_port,inner_l4_src_port,inner_dst_ipv6,inner_src_ipv6'
config pbh hash update 'inner_v6_hash' \
--hash-field-list 'inner_ip_proto'
config pbh hash delete 'inner_v6_hash'
The following command adds/updates/deletes hash-field:
config pbh hash-field add 'inner_dst_ipv6' \
--hash-field 'INNER_DST_IPV6' \
--ip-mask 'ffff::' \
--sequence-id '4'
config pbh hash-field update 'inner_dst_ipv6' \
--ip-mask 'ffff:ffff::'
config pbh hash-field delete 'inner_dst_ipv6'
The following command shows table configuration:
root@sonic:/home/admin# show pbh table
Name Interface Description
--------- --------------- ---------------
pbh_table Ethernet0 NVGRE and VxLAN
Ethernet4
PortChannel0001
PortChannel0002
The following command shows rule configuration:
root@sonic:/home/admin# show pbh rule
Table Rule Priority Match Hash Action Counter
--------- ------ ---------- ------------------------------------ ------------- ------------- ---------
pbh_table nvgre 2 ether_type: 0x0800 inner_v6_hash SET_ECMP_HASH DISABLED
ip_protocol: 0x2f
gre_key: 0x2500/0xffffff00
inner_ether_type: 0x86dd
pbh_table vxlan 1 ether_type: 0x0800 inner_v4_hash SET_LAG_HASH ENABLED
ip_protocol: 0x11
l4_dst_port: 0x12b5
inner_ether_type: 0x0800
The following command shows hash configuration:
root@sonic:/home/admin# show pbh hash
Name Hash field
------------- -----------------
inner_v4_hash inner_ip_proto
inner_l4_dst_port
inner_l4_src_port
inner_dst_ipv4
inner_src_ipv4
inner_v6_hash inner_ip_proto
inner_l4_dst_port
inner_l4_src_port
inner_dst_ipv6
inner_src_ipv6
The following command shows hash-field configuration:
root@sonic:/home/admin# show pbh hash-field
Name Field Mask Sequence Symmetric
----------------- ----------------- --------- ---------- -----------
inner_ip_proto INNER_IP_PROTOCOL 1 No
inner_l4_dst_port INNER_L4_DST_PORT 2 Yes
inner_l4_src_port INNER_L4_SRC_PORT 2 Yes
inner_dst_ipv4 INNER_DST_IPV4 255.0.0.0 3 Yes
inner_src_ipv4 INNER_SRC_IPV4 0.0.0.255 3 Yes
inner_dst_ipv6 INNER_DST_IPV6 ffff:: 4 Yes
inner_src_ipv6 INNER_SRC_IPV6 ::ffff 4 Yes
The following command shows statistics:
root@sonic:/home/admin# show pbh statistics
Table Rule Packets count (Rx) Bytes count (Rx)
--------- ------ -------------------- ------------------
pbh_table nvgre 0 0
pbh_table vxlan 0 0
A new YANG model sonic-pbh.yang
will be added to sonic-buildimage/src/sonic-yang-models/yang-models
in order to provide support for DPB and management framework.
Skeleton code:
module sonic-pbh {
yang-version 1.1;
namespace "http://github.com/Azure/sonic-pbh";
prefix pbh;
import ietf-inet-types {
prefix inet;
}
import sonic-port {
prefix port;
}
import sonic-portchannel {
prefix lag;
}
description "PBH YANG Module for SONiC OS: hashing for NVGRE & VxLAN with IPv4/IPv6 inner 5-tuple";
revision 2021-04-23 {
description "First Revision";
}
container sonic-pbh {
container PBH_HASH_FIELD {
description "PBH_HASH_FIELD part of config_db.json";
list PBH_HASH_FIELD_LIST {
key "hash_field_name";
leaf hash_field_name {
description "The name of this hash field";
type string {
length 1..255;
}
}
...
}
/* end of PBH_HASH_FIELD_LIST */
}
/* end of container PBH_HASH_FIELD */
container PBH_HASH {
description "PBH_HASH part of config_db.json";
list PBH_HASH_LIST {
key "hash_name";
leaf hash_name {
description "The name of this hash";
type string {
length 1..255;
}
}
...
}
/* end of PBH_HASH_LIST */
}
/* end of container PBH_HASH */
container PBH_RULE {
description "PBH_RULE part of config_db.json";
list PBH_RULE_LIST {
key "table_name rule_name";
leaf table_name {
description "The name of table which holds this rule";
type leafref {
path "/pbh:sonic-pbh/pbh:PBH_TABLE/pbh:PBH_TABLE_LIST/pbh:table_name";
}
}
leaf rule_name {
description "The name of this rule";
type string {
length 1..255;
}
}
...
}
/* end of PBH_RULE_LIST */
}
/* end of container PBH_RULE */
container PBH_TABLE {
description "PBH_TABLE part of config_db.json";
list PBH_TABLE_LIST {
key "table_name";
leaf table_name {
description "The name of this table";
type string {
length 1..255;
}
}
...
}
/* end of PBH_TABLE_LIST */
}
/* end of container PBH_TABLE */
}
/* end of container sonic-pbh */
}
/* end of module sonic-pbh */
No special handling is required
PBH interface binding test:
- Create PBH table with PORT/LAG
- Verify ASIC DB object count
- Verify ACL table group members
- Verify ACL table port binding
- Remove PBH table
- Verify ASIC DB object count
PBH basic configuration test:
- Verify ASIC DB object count after PBH table creation/removal
- Verify ASIC DB object count after PBH rule creation/removal
- Verify ASIC DB object count after PBH hash creation/removal
- Verify ASIC DB object count after PBH hash field creation/removal
PBH basic update test:
- Verify ASIC DB object state after PBH table update
- Verify ASIC DB object state after PBH rule update
- Verify ASIC DB object state after PBH hash update
PBH extended configuration test:
- Create inner 5-tuple PBH hash fields
- Create PBH hash
- Create PBH table
- Create NVGRE/VxLAN PBH rules
- Verify ASIC DB object count
- Remove PBH rules
- Remove PBH table
- Remove PBH hash
- Remove PBH hash fields
- Verify ASIC DB object count
PBH will reuse and extend the existing test plan:
Inner packet hashing test plan #759