Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[sai-gen] Deprecate the name annotations in favor of SaiTable #479

Merged
merged 6 commits into from
Dec 13, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .wordlist.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
ABI
ABNF
accessor
accessors
Expand Down
41 changes: 26 additions & 15 deletions dash-pipeline/SAI/sai_api_gen.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
import os
import json
import argparse
import shutil
import copy
from jinja2 import Template, Environment, FileSystemLoader
except ImportError as ie:
Expand Down Expand Up @@ -35,6 +34,7 @@
KV_PAIR_LIST_TAG = 'kvPairList'
SAI_VAL_TAG = 'SaiVal'
SAI_TABLE_TAG = 'SaiTable'
SAI_API_ORDER_TAG = 'api_order'

#
# SAI parser decorators:
Expand Down Expand Up @@ -481,7 +481,7 @@ def parse_p4rt(self, p4rt_table_action, sai_enums):
]
}
'''
#print("Parsing table action: " + self.name)
# print("Parsing table action: " + self.name)
_, self.name, _ = self.parse_sai_annotated_name(self.name)
self.parse_action_params(p4rt_table_action, sai_enums)

Expand Down Expand Up @@ -523,7 +523,7 @@ def parse_p4rt(self, p4rt_table_action_param, sai_enums, ip_is_v6_param_ids):
self.id = p4rt_table_action_param['id']
self.name = p4rt_table_action_param[NAME_TAG]
self.bitwidth = p4rt_table_action_param[BITWIDTH_TAG]
print("Parsing table action param: " + self.name)
# print("Parsing table action param: " + self.name)

if STRUCTURED_ANNOTATIONS_TAG in p4rt_table_action_param:
self._parse_sai_object_annotation(p4rt_table_action_param)
Expand Down Expand Up @@ -559,6 +559,8 @@ def __init__(self):
# Extra properties from annotations
self.stage = None
self.is_object = None
self.api_order = 0
self.api_type = None

def parse_p4rt(self, p4rt_table, program, all_actions, ignore_tables):
'''
Expand Down Expand Up @@ -590,21 +592,16 @@ def parse_p4rt(self, p4rt_table, program, all_actions, ignore_tables):
"size": "1024"
}
'''

# The first part of full name is the top level control block name, which is removed for showing better comments as stage.
self.stage, self.name, self.api_name = self.parse_sai_annotated_name(self.name, full_name_part_start = 1)
self.stage = self.stage.replace('.', '_')
if "stage" not in self.stage:
self.stage = None
self.__parse_sai_table_annotations(p4rt_table[PREAMBLE_TAG])

# If tables are specified as ignored via CLI or annotations, skip them.
if self.name in ignore_tables:
self.ignored = True
return
elif self.ignored:
ignore_tables.append(self.name)

self.__parse_sai_table_annotations(p4rt_table[PREAMBLE_TAG])
if self.ignored:
ignore_tables.append(self.name)
print("Ignoring table: " + self.name)
return

print("Parsing table: " + self.name)
Expand Down Expand Up @@ -632,14 +629,18 @@ def __parse_sai_table_annotations(self, p4rt_table_preamble):
for kv in anno[KV_PAIR_LIST_TAG][KV_PAIRS_TAG]:
if kv['key'] == 'isobject':
self.is_object = kv['value']['stringValue']
if kv['key'] == 'ignoretable':
if kv['key'] == 'ignored':
self.ignored = True
if kv['key'] == 'name':
self.name = kv['value']['stringValue']
if kv['key'] == 'stage':
self.stage = kv['value']['stringValue']
if kv['key'] == 'api':
self.api_name = kv['value']['stringValue']
if kv['key'] == 'api_type':
self.api_type = kv['value']['stringValue']
if kv['key'] == 'api_order':
self.api_order = kv['value']['int64Value']

return

Expand Down Expand Up @@ -709,9 +710,15 @@ class DASHAPISet(SAIObject):
'''
def __init__(self, api_name):
self.app_name = api_name
self.api_type = None
self.tables = []

def add_table(self, table):
if self.api_type == None:
self.api_type = table.api_type
elif self.api_type != table.api_type:
raise ValueError(f'API type mismatch: CurrentType = {self.api_type}, NewTableAPIType = {table.api_type}')

self.tables.append(table)


Expand Down Expand Up @@ -762,6 +769,10 @@ def __parse_sai_apis_from_p4rt(self, program, ignore_tables):
new_api.add_table(sai_api_table_data)
self.sai_apis.append(new_api)

# Sort all parsed tables by API order, so we can always generate the APIs in the same order for keeping ABI compatibility.
for sai_api in self.sai_apis:
sai_api.tables.sort(key=lambda x: x.api_order)

def __update_table_param_object_name_reference(self):
all_table_names = [table.name for api in self.sai_apis for table in api.tables]

Expand Down Expand Up @@ -907,7 +918,7 @@ def generate_sai_api(self, sai_api):

# For new DASH APIs, we need to generate SAI API headers.
unique_sai_api = self.__get_uniq_sai_api(sai_api)
if "dash" in sai_api.app_name:
if sai_api.api_type != 'underlay':
self.generate_dash_sai_definitions_for_api(unique_sai_api)

# Generate SAI API implementation for all APIs.
Expand All @@ -933,7 +944,7 @@ def generate_dash_sai_definitions_for_api(self, sai_api):

def generate_sai_impl_file_for_api(self, sai_api):
sai_impl_file_name = 'sai' + sai_api.app_name.replace('_', '') + '.cpp'
header_prefix = "experimental" if "dash" in sai_api.app_name else ""
header_prefix = "experimental" if sai_api.api_type != "underlay" else ""
SAITemplateRender('templates/saiapi.cpp.j2').render_to_file('lib/' + sai_impl_file_name, tables = sai_api.tables, app_name = sai_api.app_name, header_prefix = header_prefix)
self.generated_impl_file_names.append(sai_impl_file_name)

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 @@ -44,8 +44,10 @@ Available tags are:

- `name`: Specify the preferred table name in SAI API generation, e.g. `dash_acl_rule`.
- `api`: Specify which SAI API should be used in generation, e.g. `dash_acl`.
- `api_type`: The type of the API. DASH contains certain tables for handling underlay actions, such as route table. We should not generate header files for these tables but only the lib files without experimental prefix. To enable this behavior, please set the API type to `underlay`.
- `api_order`: Specify the order of the generated API in the SAI API header file. When multiple tables generates API entries in the same API set, e.g., acl group and acl rules. This explicit attribute helps us keep the order of the generated APIs to keep ABI compatibility.
- `stage`: Specify which stage this table represents for the matching stage type, e.g. `acl.stage1`.
- `isobject`: When set to "true", a top level objects in SAI that attached to switch will be generated. Otherwise, a new type of entry will be generated, if nothing else helps us to determine this table is an object table.
- `ignoretable`: When set to "true", we skip this table in SAI API generation.
- `ignored`: When set to "true", we skip this table in SAI API generation.

For more details, please check the SAI API generation script: [sai_api_gen.py](../SAI/sai_api_gen.py).
2 changes: 1 addition & 1 deletion dash-pipeline/bmv2/dash_acl.p4
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ match_kind {
#ifdef TARGET_BMV2_V1MODEL
#define ACL_STAGE(stage_index) \
direct_counter(CounterType.packets_and_bytes) ## stage ## stage_index ##_counter; \
@SaiTable[name="dash_acl_rule", stage=str(acl.stage ## stage_index), api="dash_acl"] \
@SaiTable[name="dash_acl_rule", stage=str(acl.stage ## stage_index), api="dash_acl", api_order=1] \
table stage ## stage_index { \
key = { \
meta.stage ## stage_index ##_dash_acl_group_id : exact @name("meta.dash_acl_group_id:dash_acl_group_id") \
Expand Down
6 changes: 3 additions & 3 deletions dash-pipeline/bmv2/dash_outbound.p4
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ control outbound(inout headers_t hdr,
#endif // DPDK_SUPPORTS_DIRECT_COUNTER_ON_WILDCARD_KEY_TABLE
#endif // TARGET_DPDK_PNA

@name("outbound_routing|dash_outbound_routing")
@SaiTable[name = "outbound_routing", api = "dash_outbound_routing"]
table routing {
key = {
meta.eni_id : exact @name("meta.eni_id:eni_id");
Expand Down Expand Up @@ -175,7 +175,7 @@ control outbound(inout headers_t hdr,
#endif // DPDK_SUPPORTS_DIRECT_COUNTER_ON_WILDCARD_KEY_TABLE
#endif // TARGET_DPDK_PNA

@name("outbound_ca_to_pa|dash_outbound_ca_to_pa")
@SaiTable[name = "outbound_ca_to_pa", api = "dash_outbound_ca_to_pa"]
table ca_to_pa {
key = {
/* Flow for express route */
Expand Down Expand Up @@ -205,7 +205,7 @@ control outbound(inout headers_t hdr,
meta.encap_data.vni = vni;
}

@name("vnet|dash_vnet")
@SaiTable[name = "vnet", api = "dash_vnet"]
table vnet {
key = {
meta.vnet_id : exact @name("meta.vnet_id:vnet_id");
Expand Down
25 changes: 12 additions & 13 deletions dash-pipeline/bmv2/dash_pipeline.p4
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ control dash_ingress(
action accept() {
}

@name("vip|dash_vip")
@SaiTable[name = "vip", api = "dash_vip"]
table vip {
key = {
hdr.ipv4.dst_addr : exact @name("hdr.ipv4.dst_addr:VIP");
Expand All @@ -61,7 +61,7 @@ control dash_ingress(
meta.direction = dash_direction_t.INBOUND;
}

@name("direction_lookup|dash_direction_lookup")
@SaiTable[name = "direction_lookup", api = "dash_direction_lookup"]
table direction_lookup {
key = {
hdr.vxlan.vni : exact @name("hdr.vxlan.vni:VNI");
Expand All @@ -82,6 +82,7 @@ control dash_ingress(
}

/* This table API should be implemented manually using underlay SAI */
@SaiTable[ignored = "true"]
table appliance {
key = {
meta.appliance_id : ternary @name("meta.appliance_id:appliance_id");
Expand Down Expand Up @@ -153,7 +154,7 @@ control dash_ingress(
}
}

@name("eni|dash_eni")
@SaiTable[name = "eni", api = "dash_eni", api_order=1]
table eni {
key = {
meta.eni_id : exact @name("meta.eni_id:eni_id");
Expand Down Expand Up @@ -185,6 +186,7 @@ control dash_ingress(
#endif // DPDK_SUPPORTS_DIRECT_COUNTER_ON_WILDCARD_KEY_TABLE
#endif // TARGET_DPDK_PNA

@SaiTable[ignored = "true"]
table eni_meter {
key = {
meta.eni_id : exact @name("meta.eni_id:eni_id");
Expand All @@ -211,7 +213,7 @@ control dash_ingress(
meta.vnet_id = src_vnet_id;
}

@name("pa_validation|dash_pa_validation")
@SaiTable[name = "pa_validation", api = "dash_pa_validation"]
table pa_validation {
key = {
meta.vnet_id: exact @name("meta.vnet_id:vnet_id");
Expand All @@ -226,7 +228,7 @@ control dash_ingress(
const default_action = deny;
}

@name("inbound_routing|dash_inbound_routing")
@SaiTable[name = "inbound_routing", api = "dash_inbound_routing"]
table inbound_routing {
key = {
meta.eni_id: exact @name("meta.eni_id:eni_id");
Expand Down Expand Up @@ -254,8 +256,7 @@ control dash_ingress(
}
}

@name("meter_policy|dash_meter")
@SaiTable[isobject="true"]
@SaiTable[name = "meter_policy", api = "dash_meter", api_order = 1, isobject="true"]
table meter_policy {
key = {
meta.meter_policy_id : exact @name("meta.meter_policy_id:meter_policy_id");
Expand All @@ -269,8 +270,7 @@ control dash_ingress(
meta.policy_meter_class = meter_class;
}

@name("meter_rule|dash_meter")
@SaiTable[isobject="true"]
@SaiTable[name = "meter_rule", api = "dash_meter", api_order = 2, isobject="true"]
table meter_rule {
key = {
meta.meter_policy_id: exact @name("meta.meter_policy_id:meter_policy_id") @SaiVal[type="sai_object_id_t", isresourcetype="true", objects="METER_POLICY"];
Expand Down Expand Up @@ -298,8 +298,7 @@ control dash_ingress(
meta.meter_bucket_index = meter_bucket_index;
}

@name("meter_bucket|dash_meter")
@SaiTable[isobject="true"]
@SaiTable[name = "meter_bucket", api = "dash_meter", api_order = 0, isobject="true"]
table meter_bucket {
key = {
meta.eni_id: exact @name("meta.eni_id:eni_id");
Expand All @@ -316,7 +315,7 @@ control dash_ingress(
meta.eni_id = eni_id;
}

@name("eni_ether_address_map|dash_eni")
@SaiTable[name = "eni_ether_address_map", api = "dash_eni", api_order=0]
table eni_ether_address_map {
key = {
meta.eni_addr : exact @name("meta.eni_addr:address");
Expand All @@ -341,7 +340,7 @@ control dash_ingress(
}
}

@name("dash_acl_group|dash_acl")
@SaiTable[name = "dash_acl_group", api = "dash_acl", api_order = 0]
table acl_group {
key = {
meta.stage1_dash_acl_group_id : exact @name("meta.stage1_dash_acl_group_id:dash_acl_group_id");
Expand Down
3 changes: 1 addition & 2 deletions dash-pipeline/bmv2/underlay.p4
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,7 @@ control underlay(
#endif // TARGET_DPDK_PNA
}

@name("route|route")
// TODO: To add structural annotations (example: @SaiTable[skipHeaderGen=true])
@SaiTable[name = "route", api = "route", api_type="underlay"]
table underlay_routing {
key = {
meta.dst_ip_addr : lpm @name("meta.dst_ip_addr:destination");
Expand Down