From b8750ef2c0f5578e21734c13526f61a5fe213dde Mon Sep 17 00:00:00 2001 From: Riff Date: Mon, 11 Dec 2023 14:21:19 -0800 Subject: [PATCH] [sai-gen] Update Sai attribute doc to include the latest support values, also split it into SaiVal and SaiTable for better clarity. (#477) --- dash-pipeline/SAI/sai_api_gen.py | 9 ++++-- dash-pipeline/bmv2/README.md | 48 +++++++++++++++++++++++++---- dash-pipeline/bmv2/dash_acl.p4 | 2 +- dash-pipeline/bmv2/dash_pipeline.p4 | 20 ++++++------ dash-pipeline/bmv2/underlay.p4 | 2 +- 5 files changed, 60 insertions(+), 21 deletions(-) diff --git a/dash-pipeline/SAI/sai_api_gen.py b/dash-pipeline/SAI/sai_api_gen.py index 9e056ed63..0eda8fd5a 100755 --- a/dash-pipeline/SAI/sai_api_gen.py +++ b/dash-pipeline/SAI/sai_api_gen.py @@ -33,7 +33,8 @@ STRUCTURED_ANNOTATIONS_TAG = 'structuredAnnotations' KV_PAIRS_TAG = 'kvPairs' KV_PAIR_LIST_TAG = 'kvPairList' -SAI_TAG = 'Sai' +SAI_VAL_TAG = 'SaiVal' +SAI_TABLE_TAG = 'SaiTable' # # SAI parser decorators: @@ -252,9 +253,11 @@ def _parse_sai_object_annotation(self, p4rt_anno_list): ] } } + + Whenever a new attribute is introduced, please update the doc here to get it captured: dash-pipeline/bmv2/README.md. ''' for anno in p4rt_anno_list[STRUCTURED_ANNOTATIONS_TAG]: - if anno[NAME_TAG] == SAI_TAG: + if anno[NAME_TAG] == SAI_VAL_TAG: for kv in anno[KV_PAIR_LIST_TAG][KV_PAIRS_TAG]: if kv['key'] == 'type': self.type = kv['value']['stringValue'] @@ -568,7 +571,7 @@ def __parse_sai_table_annotations(self, p4rt_table_preamble): return for anno in p4rt_table_preamble[STRUCTURED_ANNOTATIONS_TAG]: - if anno[NAME_TAG] == SAI_TAG: + if anno[NAME_TAG] == SAI_TABLE_TAG: for kv in anno[KV_PAIR_LIST_TAG][KV_PAIRS_TAG]: if kv['key'] == 'isobject': self.is_object = kv['value']['stringValue'] diff --git a/dash-pipeline/bmv2/README.md b/dash-pipeline/bmv2/README.md index 8ecf246f4..b7d75e56d 100644 --- a/dash-pipeline/bmv2/README.md +++ b/dash-pipeline/bmv2/README.md @@ -1,12 +1,48 @@ +# DASH Pipeline BM + +This directory contains the P4/BMv2-based behavior model implementation of the DASH Pipeline. + +At a high level, the DASH pipeline BM serves 2 purposes: + +1. It provides a behavior model for DASH pipeline, which can be used for testing in a simulated environment. +2. It provides a generated P4 runtime definition, which can be used to generate the SAI API and SAI adapter code to the behavior model. + +## Writing P4/BMv2 code + +The workflow of developing the DASH pipeline BM is described in the [DASH workflows doc](../README-dash-workflows.md). + +The DASH pipeline BM is written in P416 with BMv2 v1model. For specs, please find the referenced docs here: + +- P416, P4Runtime, PNA specs: +- V1Model: + ### P4 annotations for SAI code generation -SAI API generation now supports P4 annotations for documenting/providing necessary metadata to keys and action parameters. +Currently, some of the SAI generation behavior is either controlled by using the `@name` attribute with a non-formalized format, or simplifying guessing in the `sai_api_gen.py`. This is hard to maintain and extend and highly not recommended. + +To deprecate the complicated `@name` attribute, we are moving towards using structured annotations in P4. This annotation can apply on keys, action parameters and tables to document and provide necessary metadata for SAI API generation. -Use `@Sai["tag"="value", ...]` format for annotating attributes. Old mode, where `sai_api_gen.py` is guessing this information, is still supported. +The old mode is still supported, but no more new features will be added to it and it will be deprecated in the future. + +#### `@SaiVal`: Keys and action parameters + +Use `@SaiVal["tag"="value", ...]` format for annotating keys and action parameters. + +Available tags are: + +- `type`: Specify which SAI object type should be used in generation, e.g. `sai_uint32_t`. +- `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 `. +- `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`. +- `skipattr`: When set to "true", we skip this attribute in SAI API generation. + +#### `@SaiTable`: Tables + +Use `@SaiTable["tag"="value", ...]` format for annotating tables. Available tags are: -* type - SAI type -* isresourcetype - generates a corresponding SAI tag -* objects - space separated list of SAI object types this attribute accepts -More annotations may be added in the future. The infrastructure is extendable. +- `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. + +For more details, please check the SAI API generation script: [sai_api_gen.py](../SAI/sai_api_gen.py). \ No newline at end of file diff --git a/dash-pipeline/bmv2/dash_acl.p4 b/dash-pipeline/bmv2/dash_acl.p4 index 481f2ea1e..9e96e1e4f 100644 --- a/dash-pipeline/bmv2/dash_acl.p4 +++ b/dash-pipeline/bmv2/dash_acl.p4 @@ -37,7 +37,7 @@ match_kind { table table_name { \ key = { \ meta. ## table_name ##_dash_acl_group_id : exact @name("meta.dash_acl_group_id:dash_acl_group_id") \ - @Sai[type="sai_object_id_t", isresourcetype="true", objects="SAI_OBJECT_TYPE_DASH_ACL_GROUP"]; \ + @SaiVal[type="sai_object_id_t", isresourcetype="true", objects="SAI_OBJECT_TYPE_DASH_ACL_GROUP"]; \ meta.dst_ip_addr : LIST_MATCH @name("meta.dst_ip_addr:dip"); \ meta.src_ip_addr : LIST_MATCH @name("meta.src_ip_addr:sip"); \ meta.ip_protocol : LIST_MATCH @name("meta.ip_protocol:protocol"); \ diff --git a/dash-pipeline/bmv2/dash_pipeline.p4 b/dash-pipeline/bmv2/dash_pipeline.p4 index a39641ea0..ab21a345e 100644 --- a/dash-pipeline/bmv2/dash_pipeline.p4 +++ b/dash-pipeline/bmv2/dash_pipeline.p4 @@ -111,7 +111,7 @@ control dash_ingress( bit<32> flows, bit<1> admin_state, IPv4Address vm_underlay_dip, - @Sai[type="sai_uint32_t"] + @SaiVal[type="sai_uint32_t"] bit<24> vm_vni, bit<16> vnet_id, IPv6Address pl_sip, @@ -242,7 +242,7 @@ control dash_ingress( const default_action = deny; } - action check_ip_addr_family(@Sai[type="sai_ip_addr_family_t", isresourcetype="true"] bit<32> ip_addr_family) { + action check_ip_addr_family(@SaiVal[type="sai_ip_addr_family_t", isresourcetype="true"] bit<32> ip_addr_family) { if (ip_addr_family == 0) /* SAI_IP_ADDR_FAMILY_IPV4 */ { if (meta.is_overlay_ip_v6 == 1) { meta.dropped = true; @@ -255,7 +255,7 @@ control dash_ingress( } @name("meter_policy|dash_meter") - @Sai[isobject="true"] + @SaiTable[isobject="true"] table meter_policy { key = { meta.meter_policy_id : exact @name("meta.meter_policy_id:meter_policy_id"); @@ -270,10 +270,10 @@ control dash_ingress( } @name("meter_rule|dash_meter") - @Sai[isobject="true"] + @SaiTable[isobject="true"] table meter_rule { key = { - meta.meter_policy_id: exact @name("meta.meter_policy_id:meter_policy_id") @Sai[type="sai_object_id_t", isresourcetype="true", objects="METER_POLICY"]; + meta.meter_policy_id: exact @name("meta.meter_policy_id:meter_policy_id") @SaiVal[type="sai_object_id_t", isresourcetype="true", objects="METER_POLICY"]; hdr.ipv4.dst_addr : ternary @name("hdr.ipv4.dst_addr:dip"); } @@ -291,15 +291,15 @@ control dash_ingress( counter(MAX_METER_BUCKETS, CounterType.bytes) meter_bucket_outbound; #endif // TARGET_BMV2_V1MODEL action meter_bucket_action( - @Sai[type="sai_uint64_t", isreadonly="true"] bit<64> outbound_bytes_counter, - @Sai[type="sai_uint64_t", isreadonly="true"] bit<64> inbound_bytes_counter, - @Sai[type="sai_uint32_t", skipattr="true"] bit<32> meter_bucket_index) { + @SaiVal[type="sai_uint64_t", isreadonly="true"] bit<64> outbound_bytes_counter, + @SaiVal[type="sai_uint64_t", isreadonly="true"] bit<64> inbound_bytes_counter, + @SaiVal[type="sai_uint32_t", skipattr="true"] bit<32> meter_bucket_index) { // read only counters for SAI api generation only meta.meter_bucket_index = meter_bucket_index; } @name("meter_bucket|dash_meter") - @Sai[isobject="true"] + @SaiTable[isobject="true"] table meter_bucket { key = { meta.eni_id: exact @name("meta.eni_id:eni_id"); @@ -329,7 +329,7 @@ control dash_ingress( const default_action = deny; } - action set_acl_group_attrs(@Sai[type="sai_ip_addr_family_t", isresourcetype="true"] bit<32> ip_addr_family) { + action set_acl_group_attrs(@SaiVal[type="sai_ip_addr_family_t", isresourcetype="true"] bit<32> ip_addr_family) { if (ip_addr_family == 0) /* SAI_IP_ADDR_FAMILY_IPV4 */ { if (meta.is_overlay_ip_v6 == 1) { meta.dropped = true; diff --git a/dash-pipeline/bmv2/underlay.p4 b/dash-pipeline/bmv2/underlay.p4 index f00d4e7ba..de23a87e9 100644 --- a/dash-pipeline/bmv2/underlay.p4 +++ b/dash-pipeline/bmv2/underlay.p4 @@ -69,7 +69,7 @@ control underlay( } @name("route|route") - // TODO: To add structural annotations (example: @Sai[skipHeaderGen=true]) + // TODO: To add structural annotations (example: @SaiTable[skipHeaderGen=true]) table underlay_routing { key = { meta.dst_ip_addr : lpm @name("meta.dst_ip_addr:destination");