HLD Policy-Based Routing (PBR)
=====
###### tags: `SONiC`
# Revision
|Revision| Author| Date |
|----|----|----|
|Initial version|Dung-Ru Tsai |13/05/2021|
|First Review, add test case|Dung-Ru Tsai |26/05/2021|
|Add PBR CLI command usage |Dung-Ru Tsai |01/06/2021|
# About this manual
Policy-based routing (PBR) is a process whereby the device puts packets through a Access Control List before routing them. With policy-based routing, you can configure a defined policy for IPv4 and IPv6 traffic flows that lessens the reliance on routes derived from routing protocols.
# Scope
This document describes the overall design of SONiC Policy-based Routing which include sonic CLI configuration flow, SAI implemetation.
The document assumes that you have basic access control list (ACL) knowledge.
PBR table and PBR rule are subset ACL table and ACL rule. Hence, this document can be used ACL table and PBR table alternately.
# Definitions/Abbreviations
This section covers the abbreviation if any, used in this high-level design document and its definitions.
| Abbreviation | Meaning |
|---------------------|----------------------------|
| ACL | Access Control List |
| LAG | Link Aggregation Group |
| PBR | Policy-based Routing |
# 1. Requirements
- Support binding PBR rules to each port.
- Support redirected packet to physical port.
- Support redirected packet to next-hop address.
- Support redirected packet to LAG port.
- Support redirected packet to next-hop group.
- Support rules' priority.
Policy-based routing ACLs support the following additional matching options:
- Layer 3 source and/or destination ipv4/ipv6 address.
- TCP/UDP source port or detination port.
- TCP/UDP source port range or detination port range.
- IP protocol, IP Identification, IP Explicit Congestion Notification, IP Time To Live, IP TOS, IP Flags, IP Type, IP Fragment Offset, IPv6 Flow Label.
# 2. Architecture Design
Policy-based routing is a more flexible mechanism for routing packets than destination routing. Policy-based routing could describe more detail on matching rule for ingress packet. Each policy-based routing rule could assign a action method, such as net-hop IP, physical port or LAG port.
All packets received on an interface with Policy-based Routing enabled are passed through enhanced packet filters which implement by matching ACL.
To enable policy-based routing, please check Switch capability `REDIRECT_ACTION` before using the policy-based routing.
```bash
127.0.0.1:6379[6]> hgetall "SWITCH_CAPABILITY|switch"
1) "MIRROR"
2) "true"
3) "MIRRORV6"
4) "true"
5) "ACL_ACTIONS|INGRESS"
6) "PACKET_ACTION,REDIRECT_ACTION,MIRROR_INGRESS_ACTION"
7) "ACL_ACTIONS|EGRESS"
8) "PACKET_ACTION,MIRROR_EGRESS_ACTION"
9) "ACL_ACTION|PACKET_ACTION"
10) "DROP,FORWARD"
```
In order to not mix up with original ACL table type `L3` and `L3V6`, we create two table types which are `PBR` and `PBRV6`. Because not all the `L3/L3V6` type matching rule support policy-based routing. PBR table type only support `REDIRECT_ACTION`.
## 2.1 SWSS Container
### 2.1.1 Introduce PBR Tables and Rules
The main loop `AclOrch::doTask` handle changing from ACL table or ACL rule which store in CONFIG_DB or APPL_DB.
`doAclTableTask` process ACL table change/create request.
`doAclRuleTask` process ACL rule change/create request.
On the other hand, `class AclRulePBRV6` and `class AclRulePBR` also two classes need to be implemant. These two class are resposible to validate the PBR rules attribute and value before send to ASCI_DB.
Following entry need to be create:
```clike
static acl_table_type_lookup_t aclTableTypeLookUp =
{
...
{ TABLE_TYPE_PBR, ACL_TABLE_PBR },
{ TABLE_TYPE_PBRV6, ACL_TABLE_PBRV6 }
};
```
#### 2.1.1.1 PBR Table
To use Policy-based routing table, it is equivalent to create the ACL table with `TABLE_TYPE_PBR="PBR"` or `TABLE_TYPE_PBRV6="PBRV6"` type.
To identify the PBR table, table name should be named with `PBR-` prefix. And naming should be unique. PBR table could bind the specific port or port range. The usage is same as ACL table.
- ACL table class
```clike=
class AclTable {
sai_object_id_t m_oid;
AclOrch *m_pAclOrch;
public:
string id;
string description;
acl_table_type_t type;
acl_stage_type_t stage;
// Map port oid to group member oid
std::map<sai_object_id_t, sai_object_id_t> ports;
// Map rule name to rule data
map<string, shared_ptr<AclRule>> rules;
// Set to store the ACL table port alias
set<string> portSet;
// Set to store the not configured ACL table port alias
set<string> pendingPortSet;
AclTable()
: m_pAclOrch(NULL)
, type(ACL_TABLE_UNKNOWN)
, m_oid(SAI_NULL_OBJECT_ID)
, stage(ACL_STAGE_INGRESS)
{}
AclTable(AclOrch *aclOrch)
: m_pAclOrch(aclOrch)
, type(ACL_TABLE_UNKNOWN)
, m_oid(SAI_NULL_OBJECT_ID)
, stage(ACL_STAGE_INGRESS)
{}
sai_object_id_t getOid() { return m_oid; }
string getId() { return id; }
bool validate();
bool create();
// Bind the ACL table to a port which is already linked
bool bind(sai_object_id_t portOid);
// Unbind the ACL table to a port which is already linked
bool unbind(sai_object_id_t portOid);
// Bind the ACL table to all ports linked
bool bind();
// Unbind the ACL table to all ports linked
bool unbind();
// Link the ACL table with a port, for future bind or unbind
void link(sai_object_id_t portOid);
// Unlink the ACL table from a port after unbind
void unlink(sai_object_id_t portOid);
// Add or overwrite a rule into the ACL table
bool add(shared_ptr<AclRule> newRule);
// Remove a rule from the ACL table
bool remove(string rule_id);
// Remove all rules from the ACL table
bool clear();
// Update table subject to changes
void update(SubjectType, void *);
};
```
#### 2.1.1.2 PBR Rules
PBR rule is a rule entry which is under the PBR table. The name of rule should be unique in the same PBR table. One PBR table could have multiple PBR rules. The same PBR rule could be belong to multiple PBR tables.
The PBR rules have two main attribuate types: Action and Matching. Action attribute type only provide `REDIRECT_ACTION` attribute. `REDIRECT_ACTION` field value could be `next-hop`, `next-hop group`, `physical port`, `physical port group`, `LAG port` or `bridge port`. Matching attribute type have a lot of matching attribute options. Such as L4 port number, IP src address, IP protocol and other IP packet fields.
SONiC original ACL support many matching attributes which could find define in `aclMatchLookup`. In our PBR matching attributes, matching capbility will be depen on the ASIC capbility.
SWSS `AclOrch` need to create two PBR classes which are `AclRulePBR` and `AclRulePBRV6`.
The following are capability of PRB attributes.
##### IPv4 Match Attribuates (AclRulePBR)
```clike
MATCH_SRC_IP
MATCH_DST_IP
MATCH_L4_SRC_PORT
MATCH_L4_DST_PORT
MATCH_L4_SRC_PORT_RANGE
MATCH_L4_DST_PORT_RANGE
MATCH_TCP_FLAGS
MATCH_IP_PROTOCOL
MATCH_IP_TYPE
MATCH_ICMP_TYPE
MATCH_ICMP_CODE
```
##### IPv6 Match Attribuates (AclRulePBRV6)
```clike
MATCH_SRC_IPV6
MATCH_DST_IPV6
MATCH_L4_SRC_PORT
MATCH_L4_DST_PORT
MATCH_L4_SRC_PORT_RANGE
MATCH_L4_DST_PORT_RANGE
MATCH_IP_PROTOCOL
MATCH_TCP_FLAGS
MATCH_IP_TYPE
MATCH_ICMPV6_TYPE
MATCH_ICMPV6_CODE
```
- Define the new PBR rules class
The PBR rules class define is reference `AclRuleL3` and `AclRuleL3V6`.
```clike
class AclRulePBR: public AclRule
{
public:
AclRulePBR(AclOrch *m_pAclOrch, string rule, string table, acl_table_type_t type, bool createCounter = true);
bool validateAddAction(string attr_name, string attr_value);
bool validateAddMatch(string attr_name, string attr_value);
bool validate();
void update(SubjectType, void *);
protected:
sai_object_id_t getRedirectObjectId(const string& redirect_param);
};
class AclRulePBRV6: public AclRulePBR
{
public:
AclRulePBRV6(AclOrch *m_pAclOrch, string rule, string table, acl_table_type_t type);
bool validateAddMatch(string attr_name, string attr_value);
};
```
### 2.1.2 Create/Remove PBR table
`AclTable::create()` resposible to create the ACL table by table type. According to the table type, user could enable `SAI_ACL_TABLE_ATTR_FIELD_*` .
Remove PBR table flow is same as remove ACL table. Executor function is `AclOrch::removeAclTable`.
### 2.1.3 Add/Remove PBR rule
`doAclRuleTask` handle the rule add/delete operation.
After get the PBR table ID, `AclRulePBR::validateAddAction` and `AclRulePBR::validateAddMatch` should be able add the arttribute and value. You could refence the matching and action function in table type L3 (`AclRuleL3`).
In the end of addd PBR rule, `AclRule::create()` execuate `sai_acl_api->create_acl_entry` and the new rule will be add.
## 2.2 Syncd Container
No Changes
## 2.3 Database
Because of CONFIG_DB and APPL_DB share the same PBR table/rule schema.
### 2.3.1 Schema
#### 2.3.1.1 PBR Table Schema
```bash
key = ACL_TABLE:name ; PBR table name must be unique
;field = value
policy_desc = 1*255VCHAR ; name of the ACL policy table description
type = "PBR"/"PBRV6" ; type of PBR table
ports = [0-max_ports]*port_name ; the ports which bind to this PBR table.
port_name = 1*64VCHAR ; name of the port, must be unique
max_ports = 1*5DIGIT ; number of ports supported on the chip
```
#### 2.3.1.2 PBR Rule Schema
```bash
key: ACL_RULE_TABLE:table_name:rule_name ; key of the rule entry in the table,
; seq is the order of the rules
; when the packet is filtered by the
; ACL "policy_name".
; A rule is always assocaited with a
; policy.
;field = value
priority = 1*3DIGIT ; rule priority. Valid values range
; could be platform dependent
packet_action = "redirect:" redirect_parameter
; an action when the fields are matched
; we have a parameter in case of packet_action="redirect"
; This parameter defines a destination for redirected packets
; it could be:
: name of physical port. Example: "Ethernet10"
: name of LAG port Example: "PortChannel5"
: next-hop ip address Example: "10.0.0.1"
: next-hop group set of addresses Example: "10.0.0.1,10.0.0.3"
redirect_action = string ; It could be:
: name of physical port. Example: "Ethernet10"
: name of LAG port Example: "PortChannel5"
: next-hop ip address Example: "10.0.0.1"
: next-hop group set of addresses Example: "10.0.0.1,10.0.0.3"
ether_type = h16 ; Ethernet type field
ip_type = ip_types ; options of the l2_protocol_type
; field. Only v4 is support for
; this stage.
ip_protocol = h8 ; options of the l3_protocol_type field
src_ip = ipv4_prefix ; options of the source ipv4
; address (and mask) field
dst_ip = ipv4_prefix ; options of the destination ipv4
; address (and mask) field
l4_src_port = port_num ; source L4 port or the
l4_dst_port = port_num ; destination L4 port
l4_src_port_range = port_num_L-port_num_H ; source ports range of L4 ports field
l4_dst_port_range = port_num_L-port_num_H ; destination ports range of L4 ports field
tcp_flags = h8/h8 ; TCP flags field and mask
dscp = h8 ; DSCP field (only available for mirror
; table type)
;value annotations
ip_types = any | ip | ipv4 | ipv4any | non_ipv4 | ipv6any | non_ipv6
port_num = 1*5DIGIT ; a number between 0 and 65535
port_num_L = 1*5DIGIT ; a number between 0 and 65535,
; port_num_L < port_num_H
port_num_H = 1*5DIGIT ; a number between 0 and 65535,
; port_num_L < port_num_H
ipv6_prefix = 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 ] "::"
h8 = 1*2HEXDIG
h16 = 1*4HEXDIG
ls32 = ( h16 ":" h16 ) / IPv4address
ipv4_prefix = dec-octet "." dec-octet "." dec-octet "." dec-octet “/” %d1-32
dec-octet = DIGIT ; 0-9
/ %x31-39 DIGIT ; 10-99
/ "1" 2DIGIT ; 100-199
/ "2" %x30-34 DIGIT ; 200-249
```
The following 2.3.2 and 2.3.3 section show a example of PBR table/rules.
`ACL_TABLE` and `ACL_RULE` are database identity schema key, don't mix up them with acl table type `ACL_TABLE_PBR` or `ACL_TABLE_PBRV6`.
Here is the key identity in Redis-DB.
```clike
schema.h
#define CFG_ACL_TABLE_TABLE_NAME "ACL_TABLE"
#define CFG_ACL_RULE_TABLE_NAME "ACL_RULE"
#define APP_ACL_TABLE_TABLE_NAME "ACL_TABLE_TABLE"
#define APP_ACL_RULE_TABLE_NAME "ACL_RULE_TABLE"
```
### 2.3.2 APPL_DB
#### 2.3.2.1 JSON file PBR table/rules:
```json
[
{
"ACL_TABLE:PBR-PERMIT": {
"policy_desc" : "Redirect to nexthop",
"type" : "PBR",
"ports" : "Ethernet0,Ethernet4"
},
"OP": "SET"
},
{
"ACL_RULE_TABLE:PBR-PERMIT:ThePBRRuleName": {
"priority" : "55",
"SRC_IP" : "20.0.0.0/25",
"DST_IP" : "20.0.0.0/23",
"L4_SRC_PORT" : "80",
"PACKET_ACTION" : "REDIRECT:192.168.112.1"
},
"OP": "SET"
}
]
```
#### 2.3.2.2 Equivalent RedisDB entry:
```bash
127.0.0.1:6379> HGETALL ACL_TABLE:PBR-PERMIT
1) "policy_desc"
2) "Redirect to nexthop"
3) "ports"
4) "Ethernet0,Ethernet4"
5) "type"
6) "PBR"
127.0.0.1:6379> KEYS *ACL*
1) "ACL_TABLE:PBR-PERMIT"
2) "ACL_RULE_TABLE:PBR-PERMIT:ThePBRRuleName"
127.0.0.1:6379> HGETALL ACL_RULE_TABLE:PBR-PERMIT:ThePBRRuleName
1) "DST_IP"
2) "20.0.0.0/23"
3) "L4_SRC_PORT"
4) "80"
5) "PACKET_ACTION"
6) "REDIRECT:192.168.112.1"
7) "SRC_IP"
8) "20.0.0.0/25"
9) "priority"
10) "55"
```
### 2.3.3 CONFIG_DB
Basically, PBR CONFIG_DB and APPL_DB share the same database schema and AclOrch process flow.
The only different is CONFIG_DB keys' seperator is `|` instead of `:`.
#### 2.3.3.1 JSON file PBR table/rules:
```json=
{
"ACL_TABLE":{
"PBR-PERMIT": {
"policy_desc" : "Policy_Base_Routing",
"type" : "PBR",
"ports" : "Ethernet0,Ethernet4"
}
},
"ACL_RULE":{
"PBR-PERMIT|ThePBRRuleName": {
"priority" : "55",
"SRC_IP" : "20.0.0.0/25",
"DST_IP" : "20.0.0.0/23",
"L4_SRC_PORT" : "80",
"PACKET_ACTION" : "REDIRECT:192.168.112.1"
},
"PBR-PERMIT|ThePBRRuleName2": {
"priority" : "55",
"SRC_IP" : "20.0.0.0/25",
"DST_IP" : "20.0.0.0/23",
"L4_SRC_PORT" : "80",
"REDIRECT_ACTION": "Ethernet8"
}
}
}
```
#### 2.3.3.2 Equivalent RedisDB entry:
Same as APPL_DB.
# 3. Flows
Add PBR tables or PBR rules flow diagram.
```mermaid
graph TD
subgraph database[database Container]
CONFIG_DB[(CONFIG_DB)]
APPL_DB[(APPL_DB)]
ASIC_DB[(ASIC_DB)]
end
CONFIG_DB-->orchagent
APPL_DB-->orchagent
subgraph swss[swss Container]
orchagent-->AclOrch
AclOrch-->doAclTableTask
doAclTableTask-->addAclTable
addAclTable-->createBindAclTable
createBindAclTable-->PortsOrch
PortsOrch-->bindAclTable
bindAclTable-->create_acl_table_group_member
AclOrch-->doAclRuleTask
doAclRuleTask-->addAclRule
addAclRule-->AclTable::add
AclTable::add-->AclRule::create
AclRule::create-->sai_create_acl_entry
end
sai_create_acl_entry-->ASIC_DB
create_acl_table_group_member-->ASIC_DB
ASIC_DB-->syncd
subgraph Syncd[Syncd Container]
syncd-->ASIC-SDK
end
```
# 4. SAI API
## 4.1 Methods
We leverage ACL methods, only the following need to be check.
```clike
/**
* @brief Port methods table retrieved with sai_api_query()
*/
typedef struct _sai_acl_api_t
{
sai_create_acl_table_fn create_acl_table;
sai_remove_acl_table_fn remove_acl_table;
sai_set_acl_table_attribute_fn set_acl_table_attribute;
sai_get_acl_table_attribute_fn get_acl_table_attribute;
sai_create_acl_entry_fn create_acl_entry;
sai_remove_acl_entry_fn remove_acl_entry;
sai_set_acl_entry_attribute_fn set_acl_entry_attribute;
sai_get_acl_entry_attribute_fn get_acl_entry_attribute;
sai_create_acl_range_fn create_acl_range;
sai_remove_acl_range_fn remove_acl_range;
sai_set_acl_range_attribute_fn set_acl_range_attribute;
sai_get_acl_range_attribute_fn get_acl_range_attribute;
} sai_acl_api_t;
```
## 4.2 ACL Table Attribuates
This section list the SAI ACL table attribuates for PBR type table.
- SAI_OBJECT_TYPE_ACL_TABLE
### 4.2.1 IPV4 PBR table
This section list the SAI ACL table attribuates for `ACL_TABLE_PBR` type table.
SAI ACL table attribuate:
```clike=
SAI_ACL_TABLE_ATTR_ACL_BIND_POINT_TYPE_LIST
SAI_ACL_TABLE_ATTR_FIELD_ACL_IP_TYPE
SAI_ACL_TABLE_ATTR_FIELD_SRC_IP
SAI_ACL_TABLE_ATTR_FIELD_DST_IP
SAI_ACL_TABLE_ATTR_FIELD_ICMP_TYPE
SAI_ACL_TABLE_ATTR_FIELD_ICMP_CODE
SAI_ACL_TABLE_ATTR_FIELD_IP_PROTOCOL
SAI_ACL_TABLE_ATTR_FIELD_L4_SRC_PORT
SAI_ACL_TABLE_ATTR_FIELD_L4_DST_PORT
SAI_ACL_TABLE_ATTR_FIELD_TCP_FLAGS
SAI_ACL_TABLE_ATTR_FIELD_ACL_RANGE_TYPE
```
For `SAI_ACL_TABLE_ATTR_FIELD_ACL_RANGE_TYPE` usage, implementation will looks like following:
```cpp
int32_t range_types_list[] = { SAI_ACL_RANGE_TYPE_L4_DST_PORT_RANGE, SAI_ACL_RANGE_TYPE_L4_SRC_PORT_RANGE };
attr.id = SAI_ACL_TABLE_ATTR_FIELD_ACL_RANGE_TYPE;
attr.value.s32list.count = (uint32_t)(sizeof(range_types_list) / sizeof(range_types_list[0]));
attr.value.s32list.list = range_types_list;
table_attrs.push_back(attr);
```
### 4.2.2 IPV6 PBR table
This section list the SAI ACL table attribuates for `ACL_TABLE_PBRV6` type table.
SAI ACL table attribuate:
```clike=
SAI_ACL_TABLE_ATTR_ACL_BIND_POINT_TYPE_LIST
SAI_ACL_TABLE_ATTR_FIELD_ACL_IP_TYPE
SAI_ACL_TABLE_ATTR_FIELD_SRC_IPV6
SAI_ACL_TABLE_ATTR_FIELD_DST_IPV6
SAI_ACL_TABLE_ATTR_FIELD_ICMPV6_TYPE
SAI_ACL_TABLE_ATTR_FIELD_ICMPV6_CODE
SAI_ACL_TABLE_ATTR_FIELD_IP_PROTOCOL
SAI_ACL_TABLE_ATTR_FIELD_L4_SRC_PORT
SAI_ACL_TABLE_ATTR_FIELD_L4_DST_PORT
SAI_ACL_TABLE_ATTR_FIELD_TCP_FLAGS
SAI_ACL_TABLE_ATTR_FIELD_ACL_RANGE_TYPE
```
## 4.3 ACL Entry Attribuates
This section list the SAI ACL entry attribuates for PBR rules.
- SAI_OBJECT_TYPE_ACL_ENTRY
### 4.3.1 Action Attribuate
In PBR/PBRV6, only support REDIRECT_ACTION ACL entry.
| String in config.json | sai_acl_entry_attr_t|
| --------------------------| --------------------|
|ACTION_REDIRECT_ACTION|SAI_ACL_ENTRY_ATTR_ACTION_REDIRECT|
### 4.3.2 Matching Attribuate
Here is the map table between SAI attrbutes and matching rule.
| String in config.json | sai_acl_entry_attr_t |
| ------------------------- | --------------------------------------|
| MATCH_SRC_IP | SAI_ACL_ENTRY_ATTR_FIELD_SRC_IP |
| MATCH_DST_IP | SAI_ACL_ENTRY_ATTR_FIELD_DST_IP |
| MATCH_SRC_IPV6 | SAI_ACL_ENTRY_ATTR_FIELD_SRC_IPV6 |
| MATCH_DST_IPV6 | SAI_ACL_ENTRY_ATTR_FIELD_DST_IPV6 |
| MATCH_L4_SRC_PORT | SAI_ACL_ENTRY_ATTR_FIELD_L4_SRC_PORT |
| MATCH_L4_DST_PORT | SAI_ACL_ENTRY_ATTR_FIELD_L4_DST_PORT |
| MATCH_IP_PROTOCOL | SAI_ACL_ENTRY_ATTR_FIELD_IP_PROTOCOL |
| MATCH_TCP_FLAGS | SAI_ACL_ENTRY_ATTR_FIELD_TCP_FLAGS |
| MATCH_IP_TYPE | SAI_ACL_ENTRY_ATTR_FIELD_ACL_IP_TYPE |
| MATCH_ICMP_TYPE | SAI_ACL_ENTRY_ATTR_FIELD_ICMP_TYPE |
| MATCH_ICMP_CODE | SAI_ACL_ENTRY_ATTR_FIELD_ICMP_CODE |
| MATCH_ICMPV6_TYPE | SAI_ACL_ENTRY_ATTR_FIELD_ICMPV6_TYPE |
| MATCH_ICMPV6_CODE | SAI_ACL_ENTRY_ATTR_FIELD_ICMPV6_CODE |
| MATCH_L4_SRC_PORT_RANGE | SAI_ACL_RANGE_TYPE_L4_SRC_PORT_RANGE |
| MATCH_L4_DST_PORT_RANGE | SAI_ACL_RANGE_TYPE_L4_DST_PORT_RANGE |
# 5. Configuration and Management
## 5.1 JSON file config
The PBR rule/table setting are config in the JSON file.
For JSON file configuration, please check section 2.3.3.1 in CONFIG_DB.
After prepare the JSON file done, you could use command
`config load pbr-example.json` to aplly the new PBR table setting.
## 5.2 CLI command
Using the ACL CLI command format, please reference the ACL CLI command section.
### 5.2.1 PBR table add/remove
#### config acl add table
- Usage:
```
config acl add table [OPTIONS] <PBR-table_name> <(PBR|PBRV6)> [-d <description>] [-p <ports>] [-s (ingress)]
```
- Example:
```
config acl add table PBR-PERMIT PBR -d Policy_Base_Routing -p Ethernet0,Ethernet4 -s ingress
```
#### config acl remove table
- Usage:
```
config acl remove table [OPTIONS] <table_name>
```
- Example:
```
config acl remove table PBR-PERMIT
```
### 5.2.2 PBR rule create/add/remove/enable/disable/add whole-rule
Use following json file as example.
```json
{
"ACL_TABLE":{
"PBR-PERMIT": {
"policy_desc" : "Policy_Base_Routing",
"type" : "PBR",
"ports" : "Ethernet0,Ethernet4"
}
},
"ACL_RULE":{
"PBR-PERMIT|ThePBRRuleName": {
"priority" : "55",
"SRC_IP" : "20.0.0.0/25",
"DST_IP" : "20.0.0.0/23",
"L4_SRC_PORT" : "80",
"PACKET_ACTION" : "REDIRECT:192.168.112.1"
},
"PBR-PERMIT|ThePBRRuleName2": {
"priority" : "55",
"SRC_IP" : "20.0.0.0/25",
"DST_IP" : "20.0.0.0/23",
"L4_SRC_PORT" : "80",
"REDIRECT_ACTION": "Ethernet8"
}
}
}
```
#### config acl create rule
- Usage:
```
config acl create rule <PBR-table_name> <rule_name>
```
- Example:
```
config acl create rule PBR-PERMIT ThePBRRuleName
```
#### config acl add matching rule attribute
The PBR table only have one rule action which is `redirect-action`
- Usage:
```
config acl add rule <match-attr> <PBR-tablename> <rulename> <match-attr value>
```
- Example:
```
config acl add rule src-ip PBR-PERMIT ThePBRRuleName 20.0.0.0/25
config acl add rule packet-action PBR-PERMIT ThePBRRuleName REDIRECT:192.168.112.1
```
#### config acl remove matching rule attribute
- Usage:
```
config acl remove rule <match-attr> <PBR-table_name> <rulename>
```
- Example:
```
config acl remove rule src-ip PBR-PERMIT ThePBRRuleName
```
#### config acl enable rule
- Usage:
```
config acl enable rule <PBR-table_name> <rule_name>
```
- Example:
```
config acl enable rule PBR-PERMIT ThePBRRuleName
```
#### config acl disable rule
- Usage:
```
config acl disable rule <PBR-table_name> <rule_name>
```
- Example:
```
config acl disable rule PBR-PERMIT ThePBRRuleName
```
#### config acl add whole-rule
- Usage:
```
config acl add whole-rule <PBR-table_name> <rule_name> <pri> <match_info> <action_info>
```
- Example:
```
config acl add whole-rule PBR-PERMIT ThePBRRuleName 100 src-ip20.0.0.0/25,l4-src-port:80 packet-action:REDIRECT:192.168.112.1
```
# 6. Restrictions/Limitations
N/A
# 7. Test cases
## 7.1 Unit test
To test PBR, the ACL test test_acl.py must be ready.
- Set PBR action to nexthop.
- Set PBR action to nexthop group.
- Set PBR action to interface.
- Set PBR action to interface group.
- Set PBR action to LAG port.
## 7.2 System test
Test Scenario
```mermaid
graph LR
sw1((switch1))
sw2((switch2))
sw3((switch3))
PC-- 192.168.116/24 ---sw1
sw1-- 10.12.0.0/24 -->sw2
sw1-- 10.13.0.0/24 -->sw3
sw2-. 10.23.0.0/24 .-sw3
```
| Config | Verify | Step |
| ------ | ------ | ---------------------------------|
| V | | Set up the Topology, Let default route is sw1-->sw2 |
| | V | check trace route is sw1-->sw2|
| V | | config policy route on sw1 and let it direct to sw2 |
| | V | check trace route is pc-->sw1-->sw2|
[Reference video](https://www.youtube.com/watch?v=3Ie5MBmmg48)
# 8. Open/Action items - if any
Need to implement the following:
- PBR table and PBRV6 tables
- `AclRulePBR` and `AclRulePBRV6` classes.
- PBR CLI command: need to reference ACL command.
# 9. Summary
Policy-based routing provide more flexible control the routing than destination-based routing. PBR inhrentence the ACL table/rules benefit and easy to use.
------
**Don't COPY BELOW THIS LINE.**
# 10. Appendix Policy Based Route (PBR)
[FRR policy base routing](https://docs.frrouting.org/en/latest/pbr.html)
[N9K policy based routing](https://www.cisco.com/c/en/us/td/docs/switches/datacenter/nexus9000/sw/6-x/unicast/configuration/guide/l3_cli_nxos/l3pbr.html)
### Config management port ip
```bash
config terminal
N9300(config-if)# interface mgmt 0
show interface mgmt0
ip addrss dhcp
```
```bash
config terminal
feature pbr
show feature | grep pbr
copy running-config startup-config
```
[swss-schema.md](https://github.com/Azure/sonic-swss/blob/4c56d23b9ff4940bdf576cf7c9e5aa77adcbbdcc/doc/swss-schema.md)
[ACL-Configuration-Requirement-Description](https://github.com/Azure/SONiC/wiki/ACL-Configuration-Requirement-Description)
[ACL HLD](https://github.com/Azure/SONiC/blob/master/doc/acl/ACL-High-Level-Design.md)
Move ACL_TABLE_TABLE, ACL_RULE_TABLE, and PORT_MIRROR_TABLE to config DB, rename to ACL_TABLE, ACL_RULE and MIRROR_SESSION correspondingly.
[`config acl update` command reference](https://github.com/Azure/sonic-utilities/blob/9fc630c552d5f4cfa89fb9f84f40c975e1de9168/doc/Command-Reference.md#acl)
`config acl update` is using the openconfig acl format.
[openconfig json example](https://github.com/Azure/sonic-mgmt/blob/master/ansible/roles/test/tasks/acl/acltb_test_rules_part_1.json)