Skip to content

Commit

Permalink
[dash-p4] Add tunnel member table and tunnel next hop table. (#622)
Browse files Browse the repository at this point in the history
To support the ECMP group in the tunnel, this change adds the tunnel
member and tunnel next hop tables using the same way as how next hop
group works today in SAI.

The detailed design is following the HLD defined here:
https://github.com/sonic-net/DASH/blob/main/documentation/private-link-service/private-link-service.md.
  • Loading branch information
r12f authored Oct 22, 2024
1 parent 3caced3 commit 8dd75ce
Show file tree
Hide file tree
Showing 10 changed files with 273 additions and 34 deletions.
101 changes: 100 additions & 1 deletion dash-pipeline/SAI/specs/dash_tunnel.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ sai_apis:
attr_value_field: s32
default: SAI_DASH_ENCAPSULATION_VXLAN
isresourcetype: false
flags: CREATE_AND_SET
flags: CREATE_ONLY
object_name: null
allow_null: false
valid_only: null
Expand All @@ -43,6 +43,32 @@ sai_apis:
attr_value_field: u32
default: '0'
isresourcetype: false
flags: CREATE_ONLY
object_name: null
allow_null: false
valid_only: null
is_vlan: false
deprecated: false
- !!python/object:utils.sai_spec.sai_attribute.SaiAttribute
name: SAI_DASH_TUNNEL_ATTR_MAX_MEMBER_SIZE
description: Action parameter max member size
type: sai_uint32_t
attr_value_field: u32
default: '1'
isresourcetype: false
flags: CREATE_ONLY
object_name: null
allow_null: false
valid_only: null
is_vlan: false
deprecated: false
- !!python/object:utils.sai_spec.sai_attribute.SaiAttribute
name: SAI_DASH_TUNNEL_ATTR_SIP
description: Action parameter sip
type: sai_ip_address_t
attr_value_field: ipaddr
default: 0.0.0.0
isresourcetype: false
flags: CREATE_AND_SET
object_name: null
allow_null: false
Expand All @@ -59,3 +85,76 @@ sai_apis:
name: default
id: 27891720
attr_param_id: {}
- !!python/object:utils.sai_spec.sai_api.SaiApi
name: dash_tunnel_member
description: DASH tunnel member
is_object: true
enums: []
structs: []
attributes:
- !!python/object:utils.sai_spec.sai_attribute.SaiAttribute
name: SAI_DASH_TUNNEL_MEMBER_ATTR_DASH_TUNNEL_ID
description: Action parameter DASH tunnel id
type: sai_object_id_t
attr_value_field: u16
default: null
isresourcetype: false
flags: MANDATORY_ON_CREATE | CREATE_ONLY
object_name: SAI_OBJECT_TYPE_DASH_TUNNEL
allow_null: false
valid_only: null
is_vlan: false
deprecated: false
- !!python/object:utils.sai_spec.sai_attribute.SaiAttribute
name: SAI_DASH_TUNNEL_MEMBER_ATTR_DASH_TUNNEL_NEXT_HOP_ID
description: Action parameter DASH tunnel next hop id
type: sai_object_id_t
attr_value_field: u16
default: null
isresourcetype: false
flags: MANDATORY_ON_CREATE | CREATE_AND_SET
object_name: SAI_OBJECT_TYPE_DASH_TUNNEL_NEXT_HOP
allow_null: false
valid_only: null
is_vlan: false
deprecated: false
stats: []
p4_meta: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4Meta
tables:
- !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaTable
id: 40012474
actions:
default: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaAction
name: default
id: 23738116
attr_param_id: {}
- !!python/object:utils.sai_spec.sai_api.SaiApi
name: dash_tunnel_next_hop
description: DASH tunnel next hop
is_object: true
enums: []
structs: []
attributes:
- !!python/object:utils.sai_spec.sai_attribute.SaiAttribute
name: SAI_DASH_TUNNEL_NEXT_HOP_ATTR_DIP
description: Action parameter dip
type: sai_ip_address_t
attr_value_field: ipaddr
default: 0.0.0.0
isresourcetype: false
flags: CREATE_AND_SET
object_name: null
allow_null: false
valid_only: null
is_vlan: false
deprecated: false
stats: []
p4_meta: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4Meta
tables:
- !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaTable
id: 34229686
actions:
default: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaAction
name: default
id: 31749609
attr_param_id: {}
2 changes: 2 additions & 0 deletions dash-pipeline/SAI/specs/sai_spec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ object_types:
- SAI_OBJECT_TYPE_FLOW_ENTRY_BULK_GET_SESSION
- SAI_OBJECT_TYPE_METER_BUCKET_ENTRY
- SAI_OBJECT_TYPE_DASH_APPLIANCE
- SAI_OBJECT_TYPE_DASH_TUNNEL_MEMBER
- SAI_OBJECT_TYPE_DASH_TUNNEL_NEXT_HOP
object_entries:
- !!python/object:utils.sai_spec.sai_struct_entry.SaiStructEntry
name: direction_lookup_entry
Expand Down
22 changes: 12 additions & 10 deletions dash-pipeline/SAI/templates/saiapi.cpp.j2
Original file line number Diff line number Diff line change
Expand Up @@ -59,15 +59,16 @@ static sai_status_t dash_sai_create_{{ table.name }}(

matchActionEntry->set_table_id(tableId);

{% if table['keys'] | length== 1 %}
// SAI object table with single P4 key - object ID itself is the P4 table key
// Generate a SAI object ID and fill it as the P4 table key
auto mf = matchActionEntry->add_match();
mf->set_field_id({{table['keys'][0].id}});
auto mf_exact = mf->mutable_exact();
//{{table['keys'][0].field}}SetVal(objId, mf_exact, {{table['keys'][0].bitwidth}});
{{table['keys'][0].field}}SetVal(static_cast<uint{{ table['keys'][0].bitwidth }}_t>(objId), mf_exact, {{ table['keys'][0].bitwidth }});
{% else %}
{% for key in table['keys'] %}
{% if key.is_object_key %}
auto key_mf = matchActionEntry->add_match();
key_mf->set_field_id({{key.id}});
auto key_mf_exact = key_mf->mutable_exact();
// {{key.field}}SetVal(objId, key_mf_exact, {{key.bitwidth}});
{{key.field}}SetVal(static_cast<uint{{ key.bitwidth }}_t>(objId), key_mf_exact, {{ key.bitwidth }});
{% endif %}
{% endfor %}

// SAI object table with multiple P4 table keys
// Copy P4 table keys from appropriate SAI attributes
for (uint32_t i = 0; i < attr_count; i++)
Expand All @@ -79,6 +80,7 @@ static sai_status_t dash_sai_create_{{ table.name }}(
switch(attr_list[i].id)
{
{% for key in table['keys'] %}
{% if not key.is_object_key %}
case SAI_{{ table.name | upper }}_ATTR_{{ key.name | upper }}:
{
auto mf = matchActionEntry->add_match();
Expand Down Expand Up @@ -138,6 +140,7 @@ static sai_status_t dash_sai_create_{{ table.name }}(
{% endif %}
break;
}
{% endif%}
{% endfor %}
{% if table['keys'] | selectattr('match_type', 'ne', 'exact') | list | length > 0 %}
{% if table['keys'] | selectattr('match_type', 'eq', 'lpm') | list | length == 0 %}
Expand All @@ -154,7 +157,6 @@ static sai_status_t dash_sai_create_{{ table.name }}(
break;
}
}
{% endif %}

// If there is only one action, simply set it.
// Else, search in the attrs.
Expand Down
2 changes: 2 additions & 0 deletions dash-pipeline/SAI/templates/saiapi.h.j2
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,8 @@ typedef enum _sai_{{ table.name }}_attr_t
* @type {{ sai_attr.type }}
{% if sai_attr.isreadonly == 'true' %}
* @flags READ_ONLY
{% else if sai_attr.is_create_only == 'true' %}
* @flags CREATE_ONLY
{% else %}
* @flags CREATE_AND_SET
{% endif %}
Expand Down
12 changes: 8 additions & 4 deletions dash-pipeline/SAI/utils/dash_p4/dash_p4_table.py
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ def __table_with_counters(self, program: Dict[str, Any]) -> None:
def __parse_table_keys(self, p4rt_table: Dict[str, Any]) -> None:
for p4rt_table_key in p4rt_table[MATCH_FIELDS_TAG]:
table_key = DashP4TableKey.from_p4rt(p4rt_table_key)

if self.is_object != "false":
table_key.is_entry_key = False

Expand Down Expand Up @@ -372,9 +372,13 @@ def create_sai_stats(self, sai_api: SaiApi) -> None:

def create_sai_attributes(self, sai_api: SaiApi) -> None:
# If the table is an object with more one key (table entry id), we need to add all the keys into the attributes.
if self.is_object == "true" and len(self.keys) > 1:
for key in self.keys:
sai_api.attributes.extend(key.to_sai_attribute(self.name, create_only=True))
if self.is_object == "true":
if len(self.keys) == 1:
self.keys[0].is_object_key = True
elif len(self.keys) > 1:
for key in self.keys:
if not key.is_object_key:
sai_api.attributes.extend(key.to_sai_attribute(self.name))

# Add all the action parameters into the attributes.
for attr in self.sai_attributes:
Expand Down
32 changes: 26 additions & 6 deletions dash-pipeline/SAI/utils/dash_p4/dash_p4_table_attribute.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,13 @@ def __init__(self):
self.bitwidth: int = 0
self.isresourcetype: Optional[str] = None
self.isreadonly: Optional[str] = None
self.is_create_only: Optional[str] = None
self.is_mandatory: Optional[str] = None
self.object_name: Optional[str] = None
self.skipattr: Optional[str] = None
self.match_type: str = ""
self.validonly: Optional[str] = None
self.is_object_key: bool = False

def _parse_sai_table_attribute_annotation(
self, p4rt_anno_list: Dict[str, Any]
Expand Down Expand Up @@ -58,6 +61,10 @@ def _parse_sai_table_attribute_annotation(
self.isresourcetype = str(kv["value"]["stringValue"])
elif kv["key"] == "isreadonly":
self.isreadonly = str(kv["value"]["stringValue"])
elif kv["key"] == "create_only":
self.is_create_only = str(kv["value"]["stringValue"])
elif kv["key"] == "mandatory":
self.is_mandatory = str(kv["value"]["stringValue"])
elif kv["key"] == "objects":
self.object_name = str(kv["value"]["stringValue"])
elif kv["key"] == "skipattr":
Expand All @@ -66,6 +73,8 @@ def _parse_sai_table_attribute_annotation(
self.match_type = str(kv["value"]["stringValue"])
elif kv["key"] == "validonly":
self.validonly = str(kv["value"]["stringValue"])
elif kv["key"] == "is_object_key":
self.is_object_key = kv["value"]["stringValue"] == "true"
else:
raise ValueError("Unknown attr annotation " + kv["key"])

Expand Down Expand Up @@ -122,7 +131,7 @@ def to_sai_struct_entry(self, table_name: str) -> List[SaiStructEntry]:

return entries

def to_sai_attribute(self, table_name: str, create_only: bool = False, add_action_valid_only_check: bool = False) -> List[SaiAttribute]:
def to_sai_attribute(self, table_name: str, add_action_valid_only_check: bool = False) -> List[SaiAttribute]:
name = self.get_sai_name(table_name)
description = self.get_sai_description(table_name)

Expand All @@ -133,13 +142,24 @@ def to_sai_attribute(self, table_name: str, create_only: bool = False, add_actio
if self.isreadonly == "true":
sai_flags = "READ_ONLY"
default_value = None
elif create_only:
sai_flags = "MANDATORY_ON_CREATE | CREATE_ONLY"
default_value = None
elif self.is_create_only == "true":
if self.default == None or self.is_mandatory == "true":
sai_flags = "MANDATORY_ON_CREATE | CREATE_ONLY"
default_value = None
allow_null = False
else:
sai_flags = "CREATE_ONLY"
default_value = self.default

allow_null = False
else:
sai_flags = "CREATE_AND_SET"
default_value = self.default
if self.is_mandatory == "true":
sai_flags = "MANDATORY_ON_CREATE | CREATE_AND_SET"
default_value = None
allow_null = False
else:
sai_flags = "CREATE_AND_SET"
default_value = self.default

valid_only_checks = []
if add_action_valid_only_check:
Expand Down
5 changes: 5 additions & 0 deletions dash-pipeline/SAI/utils/dash_p4/dash_p4_table_key.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ class DashP4TableKey(DashP4TableAttribute):

def __init__(self):
super().__init__()
self.is_create_only: str = "true"
self.is_mandatory: str = "true"
self.ip_is_v6_field_id: int = 0

def parse_p4rt(self, p4rt_table_key: Dict[str, Any]) -> None:
Expand Down Expand Up @@ -55,6 +57,9 @@ def parse_p4rt(self, p4rt_table_key: Dict[str, Any]) -> None:

self.set_sai_type(sai_type_info)

# For table keys, we currently require the values to be explicitly set.
self.default = None

return

#
Expand Down
4 changes: 3 additions & 1 deletion dash-pipeline/bmv2/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,9 @@ Available tags are:
- `default_value`: Override the default value for this key or action parameter.
- `isresourcetype`: When set to "true", we generate a corresponding SAI tag in SAI APIs: `@isresourcetype true`.
- `objects`: Space separated list of SAI object type this value accepts. When set, we force this value to be a SAI object id, and generate a corresponding SAI tag in SAI APIs: `@objects <list>`.
- `isreadonly`: When set to "true", we generate force this value to be read-only in SAI API using: `@flags READ_ONLY`, otherwise, we generate `@flags CREATE_AND_SET`.
- `isreadonly`: When set to "true", we generate force this value to be read-only in SAI API using: `@flags READ_ONLY`, otherwise, we generate `@flags CREATE_AND_SET`. It cannot be used with `iscreateonly`.
- `iscreateonly`: When set to "true", we generate force this value to be create-only in SAI API using: `@flags CREATE_ONLY`, otherwise, we generate `@flags CREATE_AND_SET`. It cannot be used with `isreadonly`.
- `ismandatory`: When set to "true", we generate force this value to be mandatory in SAI API using: `@flags MANDATORY_ON_CREATE`. It cannot be used with `isreadonly`.
- `skipattr`: When set to "true", we skip this attribute in SAI API generation.

#### `@SaiCounter`: Counters
Expand Down
4 changes: 4 additions & 0 deletions dash-pipeline/bmv2/dash_metadata.p4
Original file line number Diff line number Diff line change
Expand Up @@ -326,6 +326,10 @@ struct metadata_t {
IPv4Address reverse_tunnel_sip;
overlay_rewrite_data_t overlay_data;
bit<16> dash_tunnel_id;
bit<32> dash_tunnel_max_member_size;
bit<16> dash_tunnel_member_index;
bit<16> dash_tunnel_member_id;
bit<16> dash_tunnel_next_hop_id;
bit<32> meter_class;
bit<8> local_region_id;
}
Expand Down
Loading

0 comments on commit 8dd75ce

Please sign in to comment.