From 284e6814445604b4830ca2a2c44a449df0a3cdd0 Mon Sep 17 00:00:00 2001 From: MirceaDan Date: Wed, 13 Nov 2024 09:30:51 -0800 Subject: [PATCH 1/8] clarification for Calculation error in program scale testing requirements? (#645) clarification for https://github.com/sonic-net/DASH/issues/397 --- .../general/program-scale-testing-requirements/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/documentation/general/program-scale-testing-requirements/README.md b/documentation/general/program-scale-testing-requirements/README.md index 24a83e78d..6453eb94f 100644 --- a/documentation/general/program-scale-testing-requirements/README.md +++ b/documentation/general/program-scale-testing-requirements/README.md @@ -189,6 +189,7 @@ integrators to track and test the designs in a common manner. - 6 packets: SYN, SYN-ACK, ACK, FIN, FIN-ACK, ACK - Flow Table Size: (2 \* CPS) + 15M + 15M //For 5M CPS, Flow Table Size: (2 \* 1000) + 15M + 15M = ~30M + - CPS test is opening and closing so fast that concurrent connections number added is very small (hundreds to thousands) - Effective PPS: Sustained CPS \* 6 + PPS for background flows. - CPS and flow results will be measured while channel bandwidth is From 0726ca74863823d3ba29d8f6e760c84230171341 Mon Sep 17 00:00:00 2001 From: Shaofeng Wu <69145577+ShaofengWu123@users.noreply.github.com> Date: Thu, 14 Nov 2024 13:06:24 +0800 Subject: [PATCH 2/8] [DASH Flow] Add SaiVal derivative before some arguments of set_flow_entry_attr to make configuration easier (#643) This PR adds `@SaiVal[type="sai_ip_address_t"]` before the following arguments of action `set_flow_entry_attr` in dash flow: - underlay0_sip - underlay0_dip - underlay1_sip - underlay1_dip There are mainly two reasons for doing this: - Other parts of the dash pipeline do so. For example, in action `set_eni_attrs`, every argument of type `IPv4Address` is added a `@SaiVal[type="sai_ip_address_t"]` before it. - Generated saithrift rpc can use IP address-related helper functions to assign a value to corresponding arguments instead of directly using a u32 type value, making the code more readable. --- dash-pipeline/SAI/specs/dash_flow.yaml | 24 +++++++++---------- dash-pipeline/bmv2/stages/conntrack_lookup.p4 | 8 +++---- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/dash-pipeline/SAI/specs/dash_flow.yaml b/dash-pipeline/SAI/specs/dash_flow.yaml index fdbdd73a6..b7ea10e0a 100644 --- a/dash-pipeline/SAI/specs/dash_flow.yaml +++ b/dash-pipeline/SAI/specs/dash_flow.yaml @@ -311,9 +311,9 @@ sai_apis: - !!python/object:utils.sai_spec.sai_attribute.SaiAttribute name: SAI_FLOW_ENTRY_ATTR_UNDERLAY0_SIP description: Action parameter underlay0 sip - type: sai_uint32_t - attr_value_field: u32 - default: '0' + type: sai_ip_address_t + attr_value_field: ipaddr + default: 0.0.0.0 isresourcetype: false flags: CREATE_AND_SET object_name: null @@ -324,9 +324,9 @@ sai_apis: - !!python/object:utils.sai_spec.sai_attribute.SaiAttribute name: SAI_FLOW_ENTRY_ATTR_UNDERLAY0_DIP description: Action parameter underlay0 dip - type: sai_uint32_t - attr_value_field: u32 - default: '0' + type: sai_ip_address_t + attr_value_field: ipaddr + default: 0.0.0.0 isresourcetype: false flags: CREATE_AND_SET object_name: null @@ -363,9 +363,9 @@ sai_apis: - !!python/object:utils.sai_spec.sai_attribute.SaiAttribute name: SAI_FLOW_ENTRY_ATTR_UNDERLAY1_SIP description: Action parameter underlay1 sip - type: sai_uint32_t - attr_value_field: u32 - default: '0' + type: sai_ip_address_t + attr_value_field: ipaddr + default: 0.0.0.0 isresourcetype: false flags: CREATE_AND_SET object_name: null @@ -376,9 +376,9 @@ sai_apis: - !!python/object:utils.sai_spec.sai_attribute.SaiAttribute name: SAI_FLOW_ENTRY_ATTR_UNDERLAY1_DIP description: Action parameter underlay1 dip - type: sai_uint32_t - attr_value_field: u32 - default: '0' + type: sai_ip_address_t + attr_value_field: ipaddr + default: 0.0.0.0 isresourcetype: false flags: CREATE_AND_SET object_name: null diff --git a/dash-pipeline/bmv2/stages/conntrack_lookup.p4 b/dash-pipeline/bmv2/stages/conntrack_lookup.p4 index c55f17da1..90ec911a2 100644 --- a/dash-pipeline/bmv2/stages/conntrack_lookup.p4 +++ b/dash-pipeline/bmv2/stages/conntrack_lookup.p4 @@ -239,15 +239,15 @@ control conntrack_lookup_stage(inout headers_t hdr, inout metadata_t meta) { /* Flow encap related attributes */ bit<24> underlay0_vnet_id, - IPv4Address underlay0_sip, - IPv4Address underlay0_dip, + @SaiVal[type="sai_ip_address_t"] IPv4Address underlay0_sip, + @SaiVal[type="sai_ip_address_t"] IPv4Address underlay0_dip, EthernetAddress underlay0_smac, EthernetAddress underlay0_dmac, @SaiVal[type="sai_dash_encapsulation_t"] dash_encapsulation_t underlay0_dash_encapsulation, bit<24> underlay1_vnet_id, - IPv4Address underlay1_sip, - IPv4Address underlay1_dip, + @SaiVal[type="sai_ip_address_t"] IPv4Address underlay1_sip, + @SaiVal[type="sai_ip_address_t"] IPv4Address underlay1_dip, EthernetAddress underlay1_smac, EthernetAddress underlay1_dmac, @SaiVal[type="sai_dash_encapsulation_t"] dash_encapsulation_t underlay1_dash_encapsulation, From aa2cde56de7ecef1426cf96e5ba83c960f281a5c Mon Sep 17 00:00:00 2001 From: Junhua Zhai Date: Wed, 20 Nov 2024 10:12:37 +0800 Subject: [PATCH 3/8] Define table size per scaling test (#644) This pull request adds a new header file `defines.h` for constants definitions. It defines different table sizes for outbound routing and ca_to_pa mapping according to [hero-implementation-details](https://github.com/sonic-net/DASH/blob/main/documentation/general/program-scale-testing-requirements/hero-implementation-details.md). The hardcoded table sizes of outbound routing and ca_to_pa mapping, whose size 4M and 8M respectively (from https://github.com/sonic-net/DASH/pull/592) take up too much memory by default. This memory pressure could make low-RAM KVM DPU crash and be unusable with sonic mgmt test. The below shows the dash pipeline memory usage of the container `simple_switch` with different scale number of routing and mapping. ``` 1. 4M/8M junhuazhai@junhuazhai-dev-vm:~/workspace/DASH/dash-pipeline$ docker stats --no-stream simple_switch-junhuazhai CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS 00016dc28662 simple_switch-junhuazhai 0.08% 1.799GiB / 62.78GiB 2.87% 0B / 0B 0B / 0B 20 2. 4K/8K junhuazhai@junhuazhai-dev-vm:~/workspace/DASH/dash-pipeline$ docker stats --no-stream simple_switch-junhuazhai CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS bcb858280193 simple_switch-junhuazhai 0.08% 46.63MiB / 62.78GiB 0.07% 0B / 0B 0B / 0B 20 ``` --- dash-pipeline/Makefile | 2 +- dash-pipeline/bmv2/defines.h | 19 +++++++++++++++++++ dash-pipeline/bmv2/stages/outbound_mapping.p4 | 3 ++- dash-pipeline/bmv2/stages/outbound_routing.p4 | 3 ++- 4 files changed, 24 insertions(+), 3 deletions(-) create mode 100644 dash-pipeline/bmv2/defines.h diff --git a/dash-pipeline/Makefile b/dash-pipeline/Makefile index 40cf83f46..99bd1a99a 100644 --- a/dash-pipeline/Makefile +++ b/dash-pipeline/Makefile @@ -103,7 +103,7 @@ sai-submodule: # P4 Source code compile TARGETS ###################################### -P4_SRC=$(wildcard bmv2/**/*.p4) +P4_SRC=$(wildcard bmv2/**/*.p4) $(wildcard bmv2/*.h) P4_MAIN=bmv2/dash_pipeline.p4 P4_OUTDIR=bmv2/dash_pipeline.bmv2 P4_ARTIFACTS=$(P4_OUTDIR)/dash_pipeline.json $(P4_OUTDIR)/dash_pipeline_p4rt.txt diff --git a/dash-pipeline/bmv2/defines.h b/dash-pipeline/bmv2/defines.h new file mode 100644 index 000000000..19bc1d8c4 --- /dev/null +++ b/dash-pipeline/bmv2/defines.h @@ -0,0 +1,19 @@ +#ifndef _DASH_DEFINES_H_ +#define _DASH_DEFINES_H_ + +#if defined(TABLE_HERO_SCALE) +#define TABLE_CA_TO_PA_SIZE (8 * 1024 * 1024) +#define TABLE_ROUTING_SIZE (4 * 1024 * 1024) + +#elif defined(TABLE_BABY_HERO_SCALE) +#define TABLE_CA_TO_PA_SIZE (8 * 1024 * 10) +#define TABLE_ROUTING_SIZE (4 * 1024 * 10) + +#else /* default/minimum size */ +#define TABLE_CA_TO_PA_SIZE 1024 +#define TABLE_ROUTING_SIZE 1024 + +#endif + + +#endif /* _DASH_DEFINES_H_ */ diff --git a/dash-pipeline/bmv2/stages/outbound_mapping.p4 b/dash-pipeline/bmv2/stages/outbound_mapping.p4 index e44624d16..5f9038091 100644 --- a/dash-pipeline/bmv2/stages/outbound_mapping.p4 +++ b/dash-pipeline/bmv2/stages/outbound_mapping.p4 @@ -2,6 +2,7 @@ #define _DASH_STAGE_OUTBOUND_MAPPING_P4_ #include "../dash_routing_types.p4" +#include "../defines.h" control outbound_mapping_stage( inout headers_t hdr, @@ -23,7 +24,7 @@ control outbound_mapping_stage( set_private_link_mapping(hdr, meta); @defaultonly drop(meta); } - size = 8 * 1024 * 1024; + size = TABLE_CA_TO_PA_SIZE; const default_action = drop(meta); ATTACH_TABLE_COUNTER(ca_to_pa_counter) diff --git a/dash-pipeline/bmv2/stages/outbound_routing.p4 b/dash-pipeline/bmv2/stages/outbound_routing.p4 index 25362814e..d9be31189 100644 --- a/dash-pipeline/bmv2/stages/outbound_routing.p4 +++ b/dash-pipeline/bmv2/stages/outbound_routing.p4 @@ -2,6 +2,7 @@ #define _DASH_STAGE_OUTBOUND_ROUTING_P4_ #include "../dash_routing_types.p4" +#include "../defines.h" control outbound_routing_stage( inout headers_t hdr, @@ -40,7 +41,7 @@ control outbound_routing_stage( route_service_tunnel(hdr, meta); drop(meta); } - size = 4 * 1024 * 1024; + size = TABLE_ROUTING_SIZE; const default_action = drop(meta); ATTACH_TABLE_COUNTER(routing_counter) From 62c99079462ad16bc743c2567a51a9253303c3be Mon Sep 17 00:00:00 2001 From: Junhua Zhai Date: Wed, 20 Nov 2024 10:40:21 +0800 Subject: [PATCH 4/8] [ptftest] Add p4_dash_utils (#640) This PR adds a module p4_dash_utils to include helper functions for p4 pipeline. * Function `set_internal_config` aims to update pipeline internal configuration, neighbor mac, data port mac, cpu port mac, etc. * Decorator `use_flow` aims to enable flow lookup stage in p4 pipeline. It wrappers method setUp/tearDown of test class. --- dash-pipeline/bmv2/dash_headers.p4 | 1 - dash-pipeline/bmv2/dash_metadata.p4 | 1 + dash-pipeline/bmv2/stages/conntrack_lookup.p4 | 2 +- dash-pipeline/bmv2/stages/pre_pipeline.p4 | 2 + .../Dockerfile.saithrift-client-bldr | 2 +- .../functional/ptf/p4_dash_utils.py | 177 ++++++++++++++++++ .../functional/ptf/saidashvnet_sanity.py | 54 +++--- 7 files changed, 212 insertions(+), 27 deletions(-) create mode 100644 test/test-cases/functional/ptf/p4_dash_utils.py diff --git a/dash-pipeline/bmv2/dash_headers.p4 b/dash-pipeline/bmv2/dash_headers.p4 index 1b3b6085e..02c0a9001 100644 --- a/dash-pipeline/bmv2/dash_headers.p4 +++ b/dash-pipeline/bmv2/dash_headers.p4 @@ -254,7 +254,6 @@ header dash_packet_meta_t { const bit<16> PACKET_META_HDR_SIZE=dash_packet_meta_t.minSizeInBytes(); #define DASH_ETHTYPE 0x876d -#define DPAPP_MAC 0x02fe23f0e413 /* FIXME temp hardcode */ struct headers_t { /* packet metadata headers */ diff --git a/dash-pipeline/bmv2/dash_metadata.p4 b/dash-pipeline/bmv2/dash_metadata.p4 index e7415f59d..bcbbe8ba6 100644 --- a/dash-pipeline/bmv2/dash_metadata.p4 +++ b/dash-pipeline/bmv2/dash_metadata.p4 @@ -243,6 +243,7 @@ struct metadata_t { bit<16> dash_tunnel_next_hop_id; bit<32> meter_class; bit<8> local_region_id; + EthernetAddress cpu_mac; } #endif /* _SIRIUS_METADATA_P4_ */ diff --git a/dash-pipeline/bmv2/stages/conntrack_lookup.p4 b/dash-pipeline/bmv2/stages/conntrack_lookup.p4 index 90ec911a2..a8e9dfdc9 100644 --- a/dash-pipeline/bmv2/stages/conntrack_lookup.p4 +++ b/dash-pipeline/bmv2/stages/conntrack_lookup.p4 @@ -127,7 +127,7 @@ control conntrack_build_dash_header(inout headers_t hdr, in metadata_t meta, hdr.packet_meta.length = length + PACKET_META_HDR_SIZE; hdr.dp_ethernet.setValid(); - hdr.dp_ethernet.dst_addr = DPAPP_MAC; + hdr.dp_ethernet.dst_addr = meta.cpu_mac; hdr.dp_ethernet.src_addr = meta.u0_encap_data.underlay_smac; hdr.dp_ethernet.ether_type = DASH_ETHTYPE; } diff --git a/dash-pipeline/bmv2/stages/pre_pipeline.p4 b/dash-pipeline/bmv2/stages/pre_pipeline.p4 index 55728abcd..a3b6f3610 100644 --- a/dash-pipeline/bmv2/stages/pre_pipeline.p4 +++ b/dash-pipeline/bmv2/stages/pre_pipeline.p4 @@ -27,9 +27,11 @@ control pre_pipeline_stage(inout headers_t hdr, action set_internal_config(EthernetAddress neighbor_mac, EthernetAddress mac, + EthernetAddress cpu_mac, bit<1> flow_enabled) { meta.u0_encap_data.underlay_dmac = neighbor_mac; meta.u0_encap_data.underlay_smac = mac; + meta.cpu_mac = cpu_mac; meta.flow_enabled = (bool)flow_enabled; } diff --git a/dash-pipeline/dockerfiles/Dockerfile.saithrift-client-bldr b/dash-pipeline/dockerfiles/Dockerfile.saithrift-client-bldr index faceb0f0b..df46d12ff 100644 --- a/dash-pipeline/dockerfiles/Dockerfile.saithrift-client-bldr +++ b/dash-pipeline/dockerfiles/Dockerfile.saithrift-client-bldr @@ -15,7 +15,7 @@ ADD requirements.txt /tests/ RUN apt update && apt install -y python3 python3-pip sudo && \ sudo update-alternatives --install /usr/bin/python python /usr/bin/python3.8 1 && \ sudo python3 -m pip install -r /tests/requirements.txt && \ - sudo pip3 install scapy pysubnettree + sudo pip3 install scapy pysubnettree p4runtime WORKDIR / diff --git a/test/test-cases/functional/ptf/p4_dash_utils.py b/test/test-cases/functional/ptf/p4_dash_utils.py new file mode 100644 index 000000000..bc93b7c79 --- /dev/null +++ b/test/test-cases/functional/ptf/p4_dash_utils.py @@ -0,0 +1,177 @@ +import grpc +from p4.v1 import p4runtime_pb2 +from p4.v1 import p4runtime_pb2_grpc + + +def get_mac(interface): + try: + mac = open('/sys/class/net/'+interface+'/address').readline().strip() + except: + mac = "00:00:00:00:00:00" + return mac + + +def mac_in_bytes(mac): + return bytes(int(b, 16) for b in mac.split(":")) + + +class P4info(): + def __init__(self, stub): + self.config = P4info.get_pipeline_config(stub) + + @staticmethod + def get_pipeline_config(stub): + try: + req = p4runtime_pb2.GetForwardingPipelineConfigRequest() + req.device_id = 0 + req.response_type = p4runtime_pb2.GetForwardingPipelineConfigRequest.ResponseType.P4INFO_AND_COOKIE + return stub.GetForwardingPipelineConfig(req).config.p4info + except Exception as e: + print(f'gRPC error: str({e})') + return None + + def get_table(self, name): + for table in self.config.tables: + if table.preamble.name == name: + return table + + return None + + def get_action(self, name): + for action in self.config.actions: + if action.preamble.name == name: + return action + + return None + + +def set_internal_config(neighbor_mac :bytes = None, + mac :bytes = None, + cpu_mac :bytes = None, + flow_enabled :bytes = None): + ''' + Set dash pipeline internal config by updating table entry of internal_config. + + if one argument is not specifed, the action param is not changed in the + existing table entry, otherwise set default value in new table entry. + ''' + channel = grpc.insecure_channel('localhost:9559') + stub = p4runtime_pb2_grpc.P4RuntimeStub(channel) + + p4info = P4info(stub) + internal_config = p4info.get_table("dash_ingress.dash_lookup_stage.pre_pipeline_stage.internal_config") + + entry = p4runtime_pb2.TableEntry() + entry.table_id = internal_config.preamble.id + entry.priority = 1 + + match = entry.match.add() + match.field_id = 1 + match.ternary.value = b'\x00' + match.ternary.mask = b'\xff' + + req = p4runtime_pb2.ReadRequest() + req.device_id = 0 + entity = req.entities.add() + entity.table_entry.CopyFrom(entry) + for response in stub.Read(req): + if not response.entities: + continue + entry = response.entities[0].table_entry + changed = 0 + + param = entry.action.action.params[0] + if neighbor_mac and neighbor_mac != param.value: + param.value = neighbor_mac + changed += 1 + + param = entry.action.action.params[1] + if mac and mac != param.value: + param.value = mac + changed += 1 + + param = entry.action.action.params[2] + if cpu_mac and cpu_mac != param.value: + param.value = cpu_mac + changed += 1 + + param = entry.action.action.params[3] + if flow_enabled and flow_enabled != param.value: + param.value = flow_enabled + changed += 1 + + if not changed: + return # none of change + + req = p4runtime_pb2.WriteRequest() + req.device_id = 0 + update = req.updates.add() + update.type = p4runtime_pb2.Update.MODIFY + update.entity.table_entry.CopyFrom(entry) + stub.Write(req) + return + + # Add one entry + set_internal_config = p4info.get_action("dash_ingress.dash_lookup_stage.pre_pipeline_stage.set_internal_config") + entry.action.action.action_id = set_internal_config.preamble.id + action = entry.action.action + + param = action.params.add() + param.param_id = 1 + if neighbor_mac: + param.value = neighbor_mac + else: # default value + param.value = b'\x00\x00\x00\x00\x00\x00' + + param = action.params.add() + param.param_id = 2 + if mac: + param.value = mac + else: # default value + param.value = b'\x00\x00\x00\x00\x00\x00' + + param = action.params.add() + param.param_id = 3 + if cpu_mac: + param.value = cpu_mac + else: # default value + param.value = b'\x00\x00\x00\x00\x00\x00' + + param = action.params.add() + param.param_id = 4 + if flow_enabled: + param.value = flow_enabled + else: # default value + param.value = b'\x00' + + req = p4runtime_pb2.WriteRequest() + req.device_id = 0 + update = req.updates.add() + update.type = p4runtime_pb2.Update.INSERT + update.entity.table_entry.CopyFrom(entry) + stub.Write(req) + + +def use_flow(cls): + _setUp = getattr(cls, "setUp", None) + _tearDown = getattr(cls, "tearDown", None) + + def setUp(self, *args, **kwargs): + if _setUp is not None: + _setUp(self, *args, **kwargs) + print(f'*** Enable Flow lookup') + set_internal_config(cpu_mac = mac_in_bytes(get_mac("veth5")), + flow_enabled = b'\x01') + return + + def tearDown(self, *args, **kwargs): + print(f'*** Disable Flow lookup') + set_internal_config(flow_enabled = b'\x00') + if _tearDown is not None: + _tearDown(self, *args, **kwargs) + return + + setattr(cls, "setUp", setUp) + setattr(cls, "tearDown", tearDown) + return cls + diff --git a/test/test-cases/functional/ptf/saidashvnet_sanity.py b/test/test-cases/functional/ptf/saidashvnet_sanity.py index 045eb0d85..5080b5baa 100644 --- a/test/test-cases/functional/ptf/saidashvnet_sanity.py +++ b/test/test-cases/functional/ptf/saidashvnet_sanity.py @@ -1,5 +1,6 @@ from sai_thrift.sai_headers import * from sai_base_test import * +from p4_dash_utils import * class SaiThriftVnetOutboundUdpPktTest(SaiHelperSimplified): """ Test saithrift vnet outbound""" @@ -10,7 +11,6 @@ def setUp(self): self.outbound_vni = 60 self.vnet_vni = 100 self.eni_mac = "00:cc:cc:cc:cc:cc" - self.our_mac = "00:00:02:03:04:05" self.dst_ca_mac = "00:dd:dd:dd:dd:dd" self.vip = "172.16.1.100" self.outbound_vni = 100 @@ -25,6 +25,11 @@ def setUp(self): # SAI address family self.sai_ip_addr_family = SAI_IP_ADDR_FAMILY_IPV4 + self.dut_mac = get_mac("veth0") + self.neighbor_mac = get_mac("veth1") + set_internal_config(neighbor_mac = mac_in_bytes(self.neighbor_mac), + mac = mac_in_bytes(self.dut_mac)) + # Flag to indicate whether configureVnet were successful or not. self.configured = False @@ -157,7 +162,6 @@ def configureVnet(self): def trafficTest(self): src_vm_ip = "10.1.1.10" - outer_smac = "00:00:05:06:06:06" # check VIP drop wrong_vip = "172.16.100.100" @@ -165,8 +169,8 @@ def trafficTest(self): eth_src=self.eni_mac, ip_dst=self.dst_ca_ip, ip_src=src_vm_ip) - vxlan_pkt = simple_vxlan_packet(eth_dst=self.our_mac, - eth_src=outer_smac, + vxlan_pkt = simple_vxlan_packet(eth_dst=self.dut_mac, + eth_src=self.neighbor_mac, ip_dst=wrong_vip, ip_src=self.src_vm_pa_ip, udp_sport=11638, @@ -184,8 +188,8 @@ def trafficTest(self): eth_src=self.eni_mac, ip_dst=wrong_dst_ca, ip_src=src_vm_ip) - vxlan_pkt = simple_vxlan_packet(eth_dst=self.our_mac, - eth_src=outer_smac, + vxlan_pkt = simple_vxlan_packet(eth_dst=self.dut_mac, + eth_src=self.neighbor_mac, ip_dst=self.vip, ip_src=self.src_vm_pa_ip, udp_sport=11638, @@ -203,8 +207,8 @@ def trafficTest(self): eth_src=self.eni_mac, ip_dst=wrong_dst_ca, ip_src=src_vm_ip) - vxlan_pkt = simple_vxlan_packet(eth_dst=self.our_mac, - eth_src=outer_smac, + vxlan_pkt = simple_vxlan_packet(eth_dst=self.dut_mac, + eth_src=self.neighbor_mac, ip_dst=self.vip, ip_src=self.src_vm_pa_ip, udp_sport=11638, @@ -221,8 +225,8 @@ def trafficTest(self): eth_src=self.eni_mac, ip_dst=self.dst_ca_ip, ip_src=src_vm_ip) - vxlan_pkt = simple_vxlan_packet(eth_dst=self.our_mac, - eth_src=outer_smac, + vxlan_pkt = simple_vxlan_packet(eth_dst=self.dut_mac, + eth_src=self.neighbor_mac, ip_dst=self.vip, ip_src=self.src_vm_pa_ip, udp_sport=11638, @@ -234,8 +238,8 @@ def trafficTest(self): eth_src=self.eni_mac, ip_dst=self.dst_ca_ip, ip_src=src_vm_ip) - vxlan_exp_pkt = simple_vxlan_packet(eth_dst="00:00:00:00:00:00", - eth_src="00:00:00:00:00:00", + vxlan_exp_pkt = simple_vxlan_packet(eth_dst=self.neighbor_mac, + eth_src=self.dut_mac, ip_dst=self.dst_pa_ip, ip_src=self.vip, udp_sport=0, # TODO: Fix sport in pipeline @@ -283,6 +287,10 @@ def tearDown(self): # Run standard PTF teardown super(SaiThriftVnetOutboundUdpPktTest, self).tearDown() + # restore default internal_config + set_internal_config(neighbor_mac = b'\x00\x00\x00\x00\x00\x00', + mac = b'\x00\x00\x00\x00\x00\x00') + class SaiThriftVnetOutboundUdpV6PktTest(SaiThriftVnetOutboundUdpPktTest): """ Test saithrift vnet outbound ipv6""" @@ -293,7 +301,6 @@ def setUp(self): self.outbound_vni = 60 self.vnet_vni = 50 self.eni_mac = "00:aa:aa:aa:aa:aa" - self.our_mac = "00:00:06:07:08:09" self.dst_ca_mac = "00:bb:bb:bb:bb:bb" self.vip = "172.16.1.200" self.outbound_vni = 50 @@ -311,7 +318,6 @@ def setUp(self): def trafficTest(self): src_vm_ip = "2000:aaaa::10a" - outer_smac = "00:00:03:06:06:06" # check VIP drop wrong_vip = "172.16.100.100" @@ -319,8 +325,8 @@ def trafficTest(self): eth_src=self.eni_mac, ipv6_dst=self.dst_ca_ip, ipv6_src=src_vm_ip) - vxlan_pkt = simple_vxlan_packet(eth_dst=self.our_mac, - eth_src=outer_smac, + vxlan_pkt = simple_vxlan_packet(eth_dst=self.dut_mac, + eth_src=self.neighbor_mac, ip_dst=wrong_vip, ip_src=self.src_vm_pa_ip, udp_sport=11638, @@ -338,8 +344,8 @@ def trafficTest(self): eth_src=self.eni_mac, ipv6_dst=wrong_dst_ca, ipv6_src=src_vm_ip) - vxlan_pkt = simple_vxlan_packet(eth_dst=self.our_mac, - eth_src=outer_smac, + vxlan_pkt = simple_vxlan_packet(eth_dst=self.dut_mac, + eth_src=self.neighbor_mac, ip_dst=self.vip, ip_src=self.src_vm_pa_ip, udp_sport=11638, @@ -357,8 +363,8 @@ def trafficTest(self): eth_src=self.eni_mac, ipv6_dst=wrong_dst_ca, ipv6_src=src_vm_ip) - vxlan_pkt = simple_vxlan_packet(eth_dst=self.our_mac, - eth_src=outer_smac, + vxlan_pkt = simple_vxlan_packet(eth_dst=self.dut_mac, + eth_src=self.neighbor_mac, ip_dst=self.vip, ip_src=self.src_vm_pa_ip, udp_sport=11638, @@ -375,8 +381,8 @@ def trafficTest(self): eth_src=self.eni_mac, ipv6_dst=self.dst_ca_ip, ipv6_src=src_vm_ip) - vxlan_pkt = simple_vxlan_packet(eth_dst=self.our_mac, - eth_src=outer_smac, + vxlan_pkt = simple_vxlan_packet(eth_dst=self.dut_mac, + eth_src=self.neighbor_mac, ip_dst=self.vip, ip_src=self.src_vm_pa_ip, udp_sport=11638, @@ -388,8 +394,8 @@ def trafficTest(self): eth_src=self.eni_mac, ipv6_dst=self.dst_ca_ip, ipv6_src=src_vm_ip) - vxlan_exp_pkt = simple_vxlan_packet(eth_dst="00:00:00:00:00:00", - eth_src="00:00:00:00:00:00", + vxlan_exp_pkt = simple_vxlan_packet(eth_dst=self.neighbor_mac, + eth_src=self.dut_mac, ip_dst=self.dst_pa_ip, ip_src=self.vip, udp_sport=0, # TODO: Fix sport in pipeline From abdd94643c6e8c16642440918b66d150b0faa44b Mon Sep 17 00:00:00 2001 From: Junhua Zhai Date: Thu, 5 Dec 2024 01:10:19 +0800 Subject: [PATCH 5/8] [dpapp] Initial dpapp implementation being a vpp plugin (#609) Following dpapp HLD - https://github.com/sonic-net/DASH/pull/606, this is the 3th part implementation. It implements the basic logic of inline flow creation, deletion and ageout. - Build with command `make dpapp` - Run with command `make run-dpapp` --- .github/workflows/dash-bmv2-ci.yml | 10 +- .wordlist.txt | 1 + dash-pipeline/dpapp/CMakeLists.txt | 11 + dash-pipeline/dpapp/Makefile | 24 ++ dash-pipeline/dpapp/README.md | 84 ++++ dash-pipeline/dpapp/dash/CMakeLists.txt | 36 ++ dash-pipeline/dpapp/dash/dash.api | 18 + dash-pipeline/dpapp/dash/dash.c | 194 +++++++++ dash-pipeline/dpapp/dash/dash.h | 65 +++ dash-pipeline/dpapp/dash/dash_node.c | 194 +++++++++ dash-pipeline/dpapp/dash/dash_test.c | 71 +++ dash-pipeline/dpapp/dash/flow.c | 404 ++++++++++++++++++ dash-pipeline/dpapp/dash/flow.h | 193 +++++++++ dash-pipeline/dpapp/dash/saiapi.c | 245 +++++++++++ dash-pipeline/dpapp/dpapp.sh | 18 + dash-pipeline/dpapp/startup.conf | 37 ++ dash-pipeline/dpapp/tools/send_p2a_pkt.py | 127 ++++++ .../functional/ptf/p4_dash_utils.py | 109 +++++ .../functional/ptf/saidashdpapp_sanity.py | 327 ++++++++++++++ .../functional/ptf/saidashvnet_sanity.py | 1 + 20 files changed, 2167 insertions(+), 2 deletions(-) create mode 100644 dash-pipeline/dpapp/CMakeLists.txt create mode 100644 dash-pipeline/dpapp/Makefile create mode 100644 dash-pipeline/dpapp/README.md create mode 100644 dash-pipeline/dpapp/dash/CMakeLists.txt create mode 100644 dash-pipeline/dpapp/dash/dash.api create mode 100644 dash-pipeline/dpapp/dash/dash.c create mode 100644 dash-pipeline/dpapp/dash/dash.h create mode 100644 dash-pipeline/dpapp/dash/dash_node.c create mode 100644 dash-pipeline/dpapp/dash/dash_test.c create mode 100644 dash-pipeline/dpapp/dash/flow.c create mode 100644 dash-pipeline/dpapp/dash/flow.h create mode 100644 dash-pipeline/dpapp/dash/saiapi.c create mode 100755 dash-pipeline/dpapp/dpapp.sh create mode 100644 dash-pipeline/dpapp/startup.conf create mode 100755 dash-pipeline/dpapp/tools/send_p2a_pkt.py create mode 100644 test/test-cases/functional/ptf/saidashdpapp_sanity.py diff --git a/.github/workflows/dash-bmv2-ci.yml b/.github/workflows/dash-bmv2-ci.yml index be19deeb1..3db115e23 100644 --- a/.github/workflows/dash-bmv2-ci.yml +++ b/.github/workflows/dash-bmv2-ci.yml @@ -62,18 +62,24 @@ jobs: run: make docker-bmv2-bldr - name: Generate SAI API run: DOCKER_FLAGS=$docker_fg_flags make sai + - name: Pull/Build docker dpapp image + run: make docker-dash-dpapp + - name: Build bmv2 dpapp + run: DOCKER_FLAGS=$docker_fg_flags make dpapp - name: Check if SAI spec is updated run: DOCKER_FLAGS=$docker_fg_flags make check-sai-spec - name: Build libsai c++ tests run: DOCKER_FLAGS=$docker_fg_flags make test - name: Prepare network - run: DOCKER_FLAGS=$docker_fg_flags make network + run: DOCKER_FLAGS=$docker_fg_flags make network HAVE_DPAPP=y - name: Run P4 software switch (bmv2) with P4Runtime - run: DOCKER_FLAGS=$docker_bg_flags make run-switch + run: DOCKER_FLAGS=$docker_bg_flags make run-switch HAVE_DPAPP=y - name: Force bmv2 to load forwarding pipeline config via dummy libsai call run: DOCKER_FLAGS=$docker_fg_flags make init-switch - name: Test SAI library over P4RT to switch run: DOCKER_FLAGS=$docker_fg_flags make run-libsai-test + - name: Run dpapp + run: DOCKER_FLAGS=$docker_bg_flags make run-dpapp HAVE_DPAPP=y - name: Generate saithrift-server run: DOCKER_FLAGS=$docker_fg_flags make saithrift-server - name: Generate saithrift-client local docker diff --git a/.wordlist.txt b/.wordlist.txt index 087b60021..85f447754 100644 --- a/.wordlist.txt +++ b/.wordlist.txt @@ -559,6 +559,7 @@ sai saic SAIC saichallenger +saidashdpapp saigen sairedis SAIRPC diff --git a/dash-pipeline/dpapp/CMakeLists.txt b/dash-pipeline/dpapp/CMakeLists.txt new file mode 100644 index 000000000..82f6ab3a1 --- /dev/null +++ b/dash-pipeline/dpapp/CMakeLists.txt @@ -0,0 +1,11 @@ +cmake_minimum_required(VERSION 3.5) + +project(dash-plugin) + +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) +set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -I /SAI/SAI/inc -I /SAI/SAI/experimental") + +find_package(VPP) + +add_subdirectory(dash) diff --git a/dash-pipeline/dpapp/Makefile b/dash-pipeline/dpapp/Makefile new file mode 100644 index 000000000..ca966ef5b --- /dev/null +++ b/dash-pipeline/dpapp/Makefile @@ -0,0 +1,24 @@ +SHELL=/bin/bash +BUILD_DIR=build +CMAKE_ARGS= + +ifeq ($(V),1) +CMAKE_ARGS += --verbose +endif + +all: dpapp + +.PHONY:configure install clean + +configure: + @cmake $(CMAKE_ARGS) -G Ninja -S . -B $(BUILD_DIR) + +dpapp: configure + @cmake --build $(BUILD_DIR) $(CMAKE_ARGS) + +clean: + @cmake --build $(BUILD_DIR) $(CMAKE_ARGS) -- clean + +install: + @sudo cmake --build $(BUILD_DIR) $(CMAKE_ARGS) -- install + diff --git a/dash-pipeline/dpapp/README.md b/dash-pipeline/dpapp/README.md new file mode 100644 index 000000000..fd2719a37 --- /dev/null +++ b/dash-pipeline/dpapp/README.md @@ -0,0 +1,84 @@ +# DPAPP - Data Plane Application +## Overview +DPAPP fulfills [VPP](https://fd.io/) plugin mechanism to implement the slow (exception) path of +packet processing. It works with [DASH pipeline BMv2](https://github.com/sonic-net/DASH/tree/main/dash-pipeline/bmv2), +serving fast path, to consist of a complete DASH data plane. Refer to the doc +[bmv2 data plane app](https://github.com/sonic-net/DASH/blob/main/documentation/dataplane/dash-bmv2-data-plane-app.md) +for design details. + +## Usage +1. build dpapp +``` +DASH/dash-pipeline$ make dpapp +``` +2. Run dpapp +``` +DASH/dash-pipeline$ make run-dpapp +``` + +## Debug +VPP CLI `vppctl` provides lots of commands for debugging. Use the command `docker exec -it dash-dpapp-${USER} vppctl` +to launch it. + +- Check dpapp interfaces and the counters +``` +vpp# show interface + Name Idx State MTU (L3/IP4/IP6/MPLS) Counter Count +host-veth5 1 up 9000/0/0/0 rx packets 39 + rx bytes 10764 + tx packets 39 + tx bytes 7628 +local0 0 down 0/0/0/0 + +vpp# show hardware-interfaces + Name Idx Link Hardware +host-veth5 1 up host-veth5 + Link speed: unknown + RX Queues: + queue thread mode + 0 vpp_wk_0 (1) interrupt + TX Queues: + TX Hash: [name: hash-eth-l34 priority: 50 description: Hash ethernet L34 headers] + queue shared thread(s) + 0 yes 0-1 + Ethernet address 02:fe:23:f0:88:99 + Linux PACKET socket interface v3 + FEATURES: + qdisc-bpass-enabled + cksum-gso-enabled + RX Queue 0: + block size:65536 nr:160 frame size:2048 nr:5120 next block:39 + TX Queue 0: + block size:69206016 nr:1 frame size:67584 nr:1024 next frame:39 + available:1024 request:0 sending:0 wrong:0 total:1024 +local0 0 down local0 + Link speed: unknown + local + +``` + +- Check flow table in dpapp +``` +vpp# show dash flow + 1: eni 00:cc:cc:cc:cc:cc, vnet_id 343, proto 17, 10.1.1.10 1234 -> 10.1.2.50 80 + common data - version 0, direction 1, actions 0x9, timeout 28 + +vpp# clear dash flow 1 +``` + +- Check packet processing trace in dpapp +``` +vpp# trace add af-packet-input 100 +vpp# show trace +``` + +On behalf of BMv2 switch, script `tools/send_p2a_pkt.py` can send packet with dash header to verify basic flow +functionality of dpapp. + +## Test +By default, flow lookup is not enabled in DASH pipeline. The decorator `@use_flow` will enable it and then involve dpapp +for slow path. If test cases are verified to support flow, aka stateful packet processing, use the decorator to mark +the test class. + +PTF test script [saidashdpapp_sanity.py](https://github.com/sonic-net/DASH/blob/main/test/test-cases/functional/ptf/saidashdpapp_sanity.py) +provides sanity check for dpapp. Refer to it as a sample for new flow tests. diff --git a/dash-pipeline/dpapp/dash/CMakeLists.txt b/dash-pipeline/dpapp/dash/CMakeLists.txt new file mode 100644 index 000000000..a56c568ef --- /dev/null +++ b/dash-pipeline/dpapp/dash/CMakeLists.txt @@ -0,0 +1,36 @@ +# Copyright (c) 2018 Cisco and/or its affiliates. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +include_directories(${CMAKE_SOURCE_DIR}) + +# for generated API headers: +include_directories(${CMAKE_BINARY_DIR}) + +add_vpp_plugin(dash + SOURCES + dash.c + dash_node.c + flow.c + saiapi.c + + MULTIARCH_SOURCES + dash_node.c + + API_FILES + dash.api + + API_TEST_SOURCES + dash_test.c + + COMPONENT vpp-plugin-dash +) diff --git a/dash-pipeline/dpapp/dash/dash.api b/dash-pipeline/dpapp/dash/dash.api new file mode 100644 index 000000000..426fec369 --- /dev/null +++ b/dash-pipeline/dpapp/dash/dash.api @@ -0,0 +1,18 @@ +/* Define a simple binary API to control the feature */ + +option version = "0.1.0"; +import "vnet/interface_types.api"; + +autoreply define dash_enable_disable { + /* Client identifier, set from api_main.my_client_index */ + u32 client_index; + + /* Arbitrary context, so client can match reply to request */ + u32 context; + + /* Enable / disable the feature */ + bool enable_disable; + + /* Interface handle */ + vl_api_interface_index_t sw_if_index; +}; diff --git a/dash-pipeline/dpapp/dash/dash.c b/dash-pipeline/dpapp/dash/dash.c new file mode 100644 index 000000000..c796f1d81 --- /dev/null +++ b/dash-pipeline/dpapp/dash/dash.c @@ -0,0 +1,194 @@ +/** + * @file + * @brief Dash Plugin, plugin API / trace / CLI handling. + */ + +#include +#include +#include + +#include +#include + +#include +#include + +#define REPLY_MSG_ID_BASE sm->msg_id_base +#include + +/* *INDENT-OFF* */ +VLIB_PLUGIN_REGISTER () = { + .version = DASH_PLUGIN_BUILD_VER, + .description = "Dash of VPP Plugin", +}; +/* *INDENT-ON* */ + +VLIB_REGISTER_LOG_CLASS (dash_log) = { + .class_name = "dash", +}; + +dash_main_t dash_main; + +/** + * @brief Enable/disable the dash plugin. + * + * Action function shared between message handler and debug CLI. + */ + +int dash_enable_disable (dash_main_t * sm, u32 sw_if_index, + int enable_disable) +{ + vnet_sw_interface_t * sw; + int rv = 0; + + /* Utterly wrong? */ + if (pool_is_free_index (sm->vnet_main->interface_main.sw_interfaces, + sw_if_index)) + return VNET_API_ERROR_INVALID_SW_IF_INDEX; + + /* Not a physical port? */ + sw = vnet_get_sw_interface (sm->vnet_main, sw_if_index); + if (sw->type != VNET_SW_INTERFACE_TYPE_HARDWARE) + return VNET_API_ERROR_INVALID_SW_IF_INDEX; + + vnet_feature_enable_disable ("dash-pipeline", "dash-pipeline-input", + sw_if_index, enable_disable, 0, 0); + + return rv; +} + +static clib_error_t * +dash_cmd_set_enable_disable_fn (vlib_main_t * vm, + unformat_input_t * input, + vlib_cli_command_t * cmd) +{ + dash_main_t * sm = &dash_main; + u32 sw_if_index = ~0; + int enable_disable = 1; + int rv; + + while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) { + if (unformat (input, "disable")) + enable_disable = 0; + else if (unformat (input, "%U", unformat_vnet_sw_interface, + sm->vnet_main, &sw_if_index)) + ; + else + break; + } + + if (sw_if_index == ~0) + return clib_error_return (0, "Please specify an interface..."); + + rv = dash_enable_disable (sm, sw_if_index, enable_disable); + + switch(rv) { + case 0: + break; + + case VNET_API_ERROR_INVALID_SW_IF_INDEX: + return clib_error_return + (0, "Invalid interface, only works on physical ports"); + break; + + case VNET_API_ERROR_UNIMPLEMENTED: + return clib_error_return (0, "Device driver doesn't support redirection"); + break; + + default: + return clib_error_return (0, "dash_enable_disable returned %d", + rv); + } + return 0; +} + +/** + * @brief CLI command to enable/disable the dash plugin. + */ +VLIB_CLI_COMMAND (dash_set_command, static) = { + .path = "set dash", + .short_help = + "set dash [disable]", + .function = dash_cmd_set_enable_disable_fn, +}; + +/** + * @brief Plugin API message handler. + */ +static void vl_api_dash_enable_disable_t_handler +(vl_api_dash_enable_disable_t * mp) +{ + vl_api_dash_enable_disable_reply_t * rmp; + dash_main_t * sm = &dash_main; + int rv; + + rv = dash_enable_disable (sm, ntohl(mp->sw_if_index), + (int) (mp->enable_disable)); + + REPLY_MACRO(VL_API_DASH_ENABLE_DISABLE_REPLY); +} + +/* API definitions */ +#include + +/** + * @brief Initialize the dash plugin. + */ +static clib_error_t * dash_init (vlib_main_t * vm) +{ + dash_main_t * sm = &dash_main; + + sm->vnet_main = vnet_get_main (); + + /* Add our API messages to the global name_crc hash table */ + sm->msg_id_base = setup_message_id_table (); + + /* Reuse SECURE_DATA (0x876D) for dash metadata */ + ethernet_register_input_type (vm, ETHERNET_TYPE_SECURE_DATA, dash_node.index); + + dash_flow_table_init(dash_flow_table_get()); + + dash_sai_init(); + + return 0; +} + +VLIB_INIT_FUNCTION (dash_init); + +/** + * @brief Hook the dash plugin into the VPP graph hierarchy. + */ +VNET_FEATURE_ARC_INIT (dash_pipeline, static) = +{ + .arc_name = "dash-pipeline", + .start_nodes = VNET_FEATURES ("dash-pipeline-input"), + .last_in_arc = "error-drop", + .arc_index_ptr = &dash_main.feature_arc_index, +}; + +static uword +dash_timer_process (vlib_main_t * vm, vlib_node_runtime_t * rt, vlib_frame_t * f) +{ + f64 sleep_duration = 1.0; + + while (1) + { + /* + * Notify the first worker thread to scan flow table + */ + vlib_node_set_interrupt_pending (vlib_get_main_by_index(1), + dash_flow_scan_node.index); + + vlib_process_suspend (vm, sleep_duration); + } + return 0; +} + +/* *INDENT-OFF* */ +VLIB_REGISTER_NODE (dash_timer_node,static) = { + .function = dash_timer_process, + .name = "dash-timer-process", + .type = VLIB_NODE_TYPE_PROCESS, +}; +/* *INDENT-ON* */ + diff --git a/dash-pipeline/dpapp/dash/dash.h b/dash-pipeline/dpapp/dash/dash.h new file mode 100644 index 000000000..d14ee65e7 --- /dev/null +++ b/dash-pipeline/dpapp/dash/dash.h @@ -0,0 +1,65 @@ +#ifndef __included_dash_h__ +#define __included_dash_h__ + +#include +#include +#include + +#include +#include +#include + +#include + +#include +#include + +typedef struct { + /* API message ID base */ + u16 msg_id_base; + + /* convenience */ + vnet_main_t * vnet_main; + + /* dash pipeline arc index */ + u8 feature_arc_index; +} dash_main_t; + +extern dash_main_t dash_main; + +extern vlib_node_registration_t dash_node; + +extern vlib_log_class_registration_t dash_log; + +#define dash_log_err(fmt, ...) \ + vlib_log_err (dash_log.class, fmt, ##__VA_ARGS__) + +#define dash_log_warn(fmt, ...) \ + vlib_log_warn (dash_log.class, fmt, ##__VA_ARGS__) + +#define dash_log_notice(fmt, ...) \ + vlib_log_notice (dash_log.class, fmt, ##__VA_ARGS__) + +#define dash_log_info(fmt, ...) \ + vlib_log_info (dash_log.class, fmt, ##__VA_ARGS__) + +#define dash_log_debug(fmt, ...) \ + vlib_log_debug (dash_log.class, fmt, ##__VA_ARGS__) + + +#define ASSERT_MSG(expr, message) \ + do { \ + if (!(expr)) { \ + dash_log_err("Assertion failed: (%s), %s:%d %s", \ + #expr, __FILE__, __LINE__, message);\ + abort(); \ + } \ + } while (0) + +void dash_sai_init (); +sai_status_t dash_sai_create_flow_entry (const dash_flow_entry_t *flow); +sai_status_t dash_sai_remove_flow_entry (const dash_flow_entry_t *flow); + +#define DASH_PLUGIN_BUILD_VER "1.0" + +#endif /* __included_dash_h__ */ diff --git a/dash-pipeline/dpapp/dash/dash_node.c b/dash-pipeline/dpapp/dash/dash_node.c new file mode 100644 index 000000000..e574ecad3 --- /dev/null +++ b/dash-pipeline/dpapp/dash/dash_node.c @@ -0,0 +1,194 @@ +#include + +#include +#include +#include +#include +#include +#include + + +extern vlib_node_registration_t dash_node; + +#define foreach_dash_error \ +_(OK, "packets process OK") \ +_(FAILED, "packets process FAILED") + +typedef enum +{ +#define _(sym,str) DASH_ERROR_##sym, + foreach_dash_error +#undef _ + DASH_N_ERROR, +} dash_error_t; + +static char *dash_error_strings[] = { +#define _(sym,string) string, + foreach_dash_error +#undef _ +}; + +typedef struct +{ + u32 next_index; + dash_error_t error; +} dash_trace_t; + + +/* packet trace format function */ +static u8 * +format_dash_trace (u8 * s, va_list * args) +{ + CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *); + CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *); + dash_trace_t *t = va_arg (*args, dash_trace_t *); + + s = format (s, "DASH: next index %d, error %d\n", + t->next_index, t->error); + + return s; +} + +typedef enum +{ + DASH_NEXT_INTERFACE_OUTPUT, + DASH_NEXT_DROP, + DASH_N_NEXT, +} dash_next_t; + +static inline void swap_ether_mac(ethernet_header_t *ether) +{ + u8 tmp[6]; + + clib_memcpy_fast (tmp, ether->src_address, sizeof (tmp)); + clib_memcpy_fast (ether->src_address, ether->dst_address, sizeof (tmp)); + clib_memcpy_fast (ether->dst_address, tmp, sizeof (tmp)); +} + +static inline dash_error_t process_one_buffer(vlib_buffer_t *buffer) +{ + u32 if_index; + ethernet_header_t *ether; + dash_header_t *dh = vlib_buffer_get_current (buffer); + + if (dash_flow_process(dash_flow_table_get(), dh) != 0) { + return DASH_ERROR_FAILED; + } + + /* Update dash header */ + dh->packet_meta.packet_source = DPAPP; + if (dh->packet_meta.packet_subtype != FLOW_DELETE) { + /* Only keep packet_meta and flow_key in dash_header_t */ + u16 length0 = ntohs(dh->packet_meta.length); + dh->packet_meta.length = htons(offsetof(dash_header_t, flow_data)); + /* Move customer packet after dash header */ + clib_memmove((u8*)&dh->flow_data, (u8*)dh + length0, + vlib_buffer_get_tail(buffer) - (u8*)dh - length0); + buffer->current_length -= length0 - offsetof(dash_header_t, flow_data); + } + + vlib_buffer_reset (buffer); + + /* Update ethernet header via swap src and dst mac */ + ether = vlib_buffer_get_current (buffer); + swap_ether_mac(ether); + + /* Send pkt back out the RX interface */ + if_index = vnet_buffer (buffer)->sw_if_index[VLIB_RX]; + vnet_buffer (buffer)->sw_if_index[VLIB_TX] = if_index; + + return DASH_ERROR_OK; +} + +VLIB_NODE_FN (dash_node) (vlib_main_t * vm, vlib_node_runtime_t * node, + vlib_frame_t * frame) +{ + u32 current_pkt_vector_size, *current_pkt_vector, *next_pkt_vector; + dash_next_t next_index; + dash_error_t error; + u32 pkts_counter[DASH_N_ERROR] = { 0 }; + + current_pkt_vector = vlib_frame_vector_args (frame); + current_pkt_vector_size = frame->n_vectors; + next_index = node->cached_next_index; + + while (current_pkt_vector_size > 0) + { + u32 next_pkt_vector_left_size; + + vlib_get_next_frame (vm, node, next_index, next_pkt_vector, next_pkt_vector_left_size); + + while (current_pkt_vector_size > 0 && next_pkt_vector_left_size > 0) + { + u32 buffer_index; + vlib_buffer_t *buffer; + u32 dst_next_index = DASH_NEXT_INTERFACE_OUTPUT; + + /* speculatively enqueue buffer to the current next frame */ + buffer_index = current_pkt_vector[0]; + next_pkt_vector[0] = buffer_index; + current_pkt_vector += 1; + next_pkt_vector += 1; + current_pkt_vector_size -= 1; + next_pkt_vector_left_size -= 1; + + buffer = vlib_get_buffer (vm, buffer_index); + error = process_one_buffer (buffer); + if (error != DASH_ERROR_OK) { + dst_next_index = DASH_NEXT_DROP; + } + + pkts_counter[error] += 1; + + if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE) && + (buffer->flags & VLIB_BUFFER_IS_TRACED))) + { + dash_trace_t *t = vlib_add_trace (vm, node, buffer, sizeof (*t)); + t->next_index = dst_next_index; + t->error = error; + } + + /* verify speculative enqueue, maybe switch current next frame */ + vlib_validate_buffer_enqueue_x1 (vm, node, next_index, + next_pkt_vector, next_pkt_vector_left_size, + buffer_index, dst_next_index); + } + + vlib_put_next_frame (vm, node, next_index, next_pkt_vector_left_size); + } + + for (error = 0; error < DASH_N_ERROR; error++) { + vlib_node_increment_counter (vm, dash_node.index, + error, pkts_counter[error]); + } + return frame->n_vectors; +} + +/* *INDENT-OFF* */ +VLIB_REGISTER_NODE (dash_node) = +{ + .name = "dash-pipeline-input", + .vector_size = sizeof (u32), + .format_trace = format_dash_trace, + .type = VLIB_NODE_TYPE_INTERNAL, + + .n_errors = ARRAY_LEN(dash_error_strings), + .error_strings = dash_error_strings, + + .n_next_nodes = DASH_N_NEXT, + + /* edit / add dispositions here */ + .next_nodes = { + [DASH_NEXT_INTERFACE_OUTPUT] = "interface-output", + [DASH_NEXT_DROP] = "error-drop" + }, +}; +/* *INDENT-ON* */ + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: + * eval: (c-set-style "gnu") + * End: + */ diff --git a/dash-pipeline/dpapp/dash/dash_test.c b/dash-pipeline/dpapp/dash/dash_test.c new file mode 100644 index 000000000..04466b0bc --- /dev/null +++ b/dash-pipeline/dpapp/dash/dash_test.c @@ -0,0 +1,71 @@ +/* + *------------------------------------------------------------------ + * dash_test.c - test harness plugin + *------------------------------------------------------------------ + */ + +#include +#include +#include +#include + +#define __plugin_msg_base dash_test_main.msg_id_base +#include + +uword unformat_sw_if_index (unformat_input_t * input, va_list * args); + +/* Declare message IDs */ +#include +#include + +typedef struct { + /* API message ID base */ + u16 msg_id_base; + vat_main_t *vat_main; +} dash_test_main_t; + +dash_test_main_t dash_test_main; + +static int api_dash_enable_disable (vat_main_t * vam) +{ + unformat_input_t * i = vam->input; + int enable_disable = 1; + u32 sw_if_index = ~0; + vl_api_dash_enable_disable_t * mp; + int ret; + + /* Parse args required to build the message */ + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) { + if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index)) + ; + else if (unformat (i, "sw_if_index %d", &sw_if_index)) + ; + else if (unformat (i, "disable")) + enable_disable = 0; + else + break; + } + + if (sw_if_index == ~0) { + errmsg ("missing interface name / explicit sw_if_index number \n"); + return -99; + } + + /* Construct the API message */ + M(DASH_ENABLE_DISABLE, mp); + mp->sw_if_index = ntohl (sw_if_index); + mp->enable_disable = enable_disable; + + /* send it... */ + S(mp); + + /* Wait for a reply... */ + W (ret); + return ret; +} + +/* + * List of messages that the api test plugin sends, + * and that the data plane plugin processes + */ +#include diff --git a/dash-pipeline/dpapp/dash/flow.c b/dash-pipeline/dpapp/dash/flow.c new file mode 100644 index 000000000..f51a0e5cc --- /dev/null +++ b/dash-pipeline/dpapp/dash/flow.c @@ -0,0 +1,404 @@ + +#include + +#include +#include + +#define DASH_FLOW_NUM (1 << 12) /* 4K */ +#define DASH_FLOW_NUM_BUCKETS (DASH_FLOW_NUM / BIHASH_KVP_PER_PAGE) +#define DASH_FLOW_MEMORY_SIZE (DASH_FLOW_NUM * 32) + +static dash_flow_table_t dash_flow_table; + +dash_flow_table_t* +dash_flow_table_get (void) +{ + return &dash_flow_table; +} + +dash_flow_entry_t* +dash_flow_alloc() +{ + dash_flow_entry_t *flow; + dash_flow_table_t *flow_table = dash_flow_table_get(); + + pool_get (flow_table->flow_pool, flow); + clib_memset (flow, 0, sizeof (*flow)); + flow->index = flow - flow_table->flow_pool; + flow->timeout = DASH_FLOW_TIMEOUT; + flow->access_time = (u64)unix_time_now(); + return flow; +} + +void +dash_flow_free(dash_flow_entry_t *flow) +{ + dash_flow_table_t *flow_table = dash_flow_table_get(); + + if (flow != NULL) + pool_put(flow_table->flow_pool, flow); +} + +dash_flow_entry_t* +dash_flow_get_by_index (u32 index) +{ + dash_flow_table_t *flow_table = dash_flow_table_get(); + dash_flow_entry_t *flow = pool_elt_at_index(flow_table->flow_pool, index); + + return flow; +} + +static int +dash_flow_create (dash_flow_table_t *flow_table, const dash_header_t *dh) +{ + int r; + sai_status_t status; + + ASSERT(flow_table && dh); + + u16 length = ntohs(dh->packet_meta.length); + ASSERT_MSG(length >= offsetof(dash_header_t, flow_overlay_data), "dash header not enough"); + + dash_flow_entry_t* flow = dash_flow_alloc(); + + clib_memcpy_fast(&flow->key, &dh->flow_key, sizeof(dh->flow_key)); + + clib_memcpy_fast(&flow->flow_data, &dh->flow_data, sizeof(dh->flow_data)); + + /* FIXME + * Assume overlay_data, u0_encap_data, u1_encap_data in order if exists + * Need to add their offset in generic. + */ + if (flow->flow_data.actions != 0) { + ASSERT_MSG(length >= offsetof(dash_header_t, flow_u0_encap_data), + "dash header not enough"); + clib_memcpy_fast(&flow->flow_overlay_data, &dh->flow_overlay_data, sizeof(dh->flow_overlay_data)); + } + + if (flow->flow_data.actions & htonl(SAI_DASH_FLOW_ACTION_ENCAP_U0)) { + ASSERT_MSG(length >= offsetof(dash_header_t, flow_u1_encap_data), + "dash header not enough"); + clib_memcpy_fast(&flow->flow_u0_encap_data, &dh->flow_u0_encap_data, sizeof(dh->flow_u0_encap_data)); + } + + if (flow->flow_data.actions & htonl(SAI_DASH_FLOW_ACTION_ENCAP_U1)) { + ASSERT_MSG((u8*)(&dh->flow_u1_encap_data + 1) <= (u8*)dh + length, + "dash header not enough"); + clib_memcpy_fast(&flow->flow_u1_encap_data, &dh->flow_u1_encap_data, sizeof(dh->flow_u1_encap_data)); + } + + r = dash_flow_table_add_entry (flow_table, flow); + if (r != 0) goto table_add_entry_fail; + + status = dash_sai_create_flow_entry(flow); + if (status != SAI_STATUS_SUCCESS) goto sai_create_flow_fail; + + flow_table->flow_stats.create_ok++; + flow->timer_handle = TW (tw_timer_start) (&flow_table->flow_tw, flow->index, 0, flow->timeout); + return 0; + +sai_create_flow_fail: + flow_table->flow_stats.create_fail++; + dash_flow_table_delete_entry (flow_table, flow); + dash_flow_free(flow); + return -1; + +table_add_entry_fail: + dash_flow_free(flow); + return r; +} + +static int +dash_flow_update (dash_flow_table_t *flow_table, const dash_header_t *dh) +{ + return -1; /* TODO later */ +} + +static int +dash_flow_remove (dash_flow_table_t *flow_table, const dash_header_t *dh) +{ + int r = -1; + sai_status_t status; + dash_flow_hash_key_t flow_hash_key; + dash_flow_entry_t* flow; + + ASSERT(flow_table && dh); + + u16 length = ntohs(dh->packet_meta.length); + ASSERT(length >= offsetof(dash_header_t, flow_key)); + + bzero(&flow_hash_key, sizeof(flow_hash_key)); + clib_memcpy_fast(&flow_hash_key, &dh->flow_key, sizeof(dh->flow_key)); + + flow = dash_flow_table_lookup_entry(flow_table, &flow_hash_key.key); + if (!flow) goto flow_not_found; + + status = dash_sai_remove_flow_entry(flow); + if (status != SAI_STATUS_SUCCESS) goto sai_remove_flow_fail; + + TW (tw_timer_stop) (&flow_table->flow_tw, flow->timer_handle); + + r = dash_flow_table_delete_entry (flow_table, flow); + ASSERT(r == 0); + dash_flow_free(flow); + + flow_table->flow_stats.remove_ok++; + return 0; + +sai_remove_flow_fail: + flow_table->flow_stats.remove_fail++; + +flow_not_found: + return -1; +} + +typedef int (*dash_flow_cmd_handler) (dash_flow_table_t *flow_table, const dash_header_t *dh); + +static dash_flow_cmd_handler flow_cmd_funs[] = { + [FLOW_CREATE] = dash_flow_create, + [FLOW_UPDATE] = dash_flow_update, + [FLOW_DELETE] = dash_flow_remove, +}; + + +int +dash_flow_process (dash_flow_table_t *flow_table, const dash_header_t *dh) +{ + ASSERT(dh->packet_meta.packet_type == REGULAR); + ASSERT(dh->packet_meta.packet_subtype >= FLOW_CREATE); + ASSERT(dh->packet_meta.packet_subtype <= FLOW_DELETE); + + return flow_cmd_funs[dh->packet_meta.packet_subtype](flow_table, dh); +} + +static void +dash_flow_expired_timer_callback (u32 * expired_timers) +{ + int i; + u32 index; + sai_status_t status; + dash_flow_table_t *flow_table = dash_flow_table_get(); + + for (i = 0; i < vec_len (expired_timers); i++) + { + index = expired_timers[i] & 0x7FFFFFFF; + dash_flow_entry_t *flow = dash_flow_get_by_index(index); + status = dash_sai_remove_flow_entry(flow); + if (status != SAI_STATUS_SUCCESS) { + dash_log_err("dash_sai_remove_flow_entry fail: %d", status); + continue; + } + + if (dash_flow_table_delete_entry (flow_table, flow) == 0) { + dash_flow_free(flow); + } else { + ASSERT(0); + } + } +} + +void +dash_flow_table_init (dash_flow_table_t *flow_table) +{ + BV(clib_bihash_init) (&flow_table->hash_table, "flow hash table", + DASH_FLOW_NUM_BUCKETS, DASH_FLOW_MEMORY_SIZE); + + pool_init_fixed (flow_table->flow_pool, DASH_FLOW_NUM); + + bzero(&flow_table->flow_stats, sizeof(flow_table->flow_stats)); + + TW (tw_timer_wheel_init) (&flow_table->flow_tw, + dash_flow_expired_timer_callback, + 1.0 /* timer interval */, 1024); +} + +int +dash_flow_table_add_entry (dash_flow_table_t *flow_table, dash_flow_entry_t *flow) +{ + BVT (clib_bihash_kv) kv; + + clib_memcpy_fast (kv.key, &flow->key, sizeof(kv.key)); + kv.value = (u64)(uintptr_t)&flow->flow_data; + return BV (clib_bihash_add_del) (&flow_table->hash_table, &kv, 1 /* is_add */ ); +} + +int +dash_flow_table_delete_entry (dash_flow_table_t *flow_table, dash_flow_entry_t *flow) +{ + BVT (clib_bihash_kv) kv; + + clib_memcpy_fast (kv.key, &flow->key, sizeof(kv.key)); + return BV (clib_bihash_add_del) (&flow_table->hash_table, &kv, 0 /* is_del */ ); +} + +dash_flow_entry_t* +dash_flow_table_lookup_entry (dash_flow_table_t *flow_table, flow_key_t *flow_key) +{ + BVT (clib_bihash_kv) kv; + flow_data_t *flow_data; + + clib_memcpy_fast (kv.key, flow_key, sizeof(kv.key)); + if (BV (clib_bihash_search) (&flow_table->hash_table, &kv, &kv)) + return NULL; + + flow_data = (flow_data_t *)(uintptr_t)kv.value; + return (dash_flow_entry_t*)((u8*)flow_data - offsetof(dash_flow_entry_t, flow_data)); +} + +static uword +dash_flow_scan (vlib_main_t * vm, vlib_node_runtime_t * rt, vlib_frame_t * f) +{ + dash_flow_table_t *flow_table = dash_flow_table_get(); + TW (tw_timer_expire_timers) (&flow_table->flow_tw, vlib_time_now(vm)); + return 0; +} + +/* *INDENT-OFF* */ +VLIB_REGISTER_NODE (dash_flow_scan_node) = { + .function = dash_flow_scan, + .name = "dash-flow-scan", + .type = VLIB_NODE_TYPE_INPUT, + .state = VLIB_NODE_STATE_INTERRUPT, +}; +/* *INDENT-ON* */ + +static u8 * +dash_flow_format (u8 * s, va_list * args) +{ + dash_flow_entry_t *flow = va_arg(*args, dash_flow_entry_t*); + + s = format (s, "eni %U, vnet_id %d, proto %d, ", + format_mac_address, flow->key.eni_mac, + clib_net_to_host_u16 (flow->key.vnet_id), + flow->key.ip_proto); + + if (flow->key.is_ip_v6) { + s = format (s, "%U %d -> %U %d\n", + format_ip6_address, &flow->key.src_ip.ip6, + clib_net_to_host_u16 (flow->key.src_port), + format_ip6_address, &flow->key.dst_ip.ip6, + clib_net_to_host_u16 (flow->key.dst_port)); + } else { + s = format (s, "%U %d -> %U %d\n", + format_ip4_address, &flow->key.src_ip.ip4, + clib_net_to_host_u16 (flow->key.src_port), + format_ip4_address, &flow->key.dst_ip.ip4, + clib_net_to_host_u16 (flow->key.dst_port)); + } + + s = format (s, " common data - version %u, direction %u, actions 0x%x", + clib_net_to_host_u32 (flow->flow_data.version), + clib_net_to_host_u16 (flow->flow_data.direction), + clib_net_to_host_u32 (flow->flow_data.actions)); + s = format (s, ", timeout %lu\n", + flow->access_time + flow->timeout - (u64)unix_time_now()); + + return s; +} + +typedef struct dash_flow_show_walk_ctx_t_ +{ + u8 verbose; + vlib_main_t *vm; +} dash_flow_show_walk_ctx_t; + +static int +dash_flow_show_walk_cb (BVT (clib_bihash_kv) * kvp, void *arg) +{ + dash_flow_show_walk_ctx_t *ctx = arg; + flow_data_t *flow_data = (flow_data_t *)(uintptr_t)kvp->value; + dash_flow_entry_t *flow = (dash_flow_entry_t*)((u8*)flow_data - + offsetof(dash_flow_entry_t, flow_data)); + + vlib_cli_output (ctx->vm, "%6u: %U", flow->index, dash_flow_format, flow); + + return BIHASH_WALK_CONTINUE; +} + +static clib_error_t * +dash_cmd_show_flow_fn (vlib_main_t * vm, + unformat_input_t * input, vlib_cli_command_t * cmd) +{ + clib_error_t *error = 0; + dash_flow_show_walk_ctx_t ctx = { + .vm = vm, + }; + dash_flow_table_t *flow_table = dash_flow_table_get(); + + BV (clib_bihash_foreach_key_value_pair) + (&flow_table->hash_table, dash_flow_show_walk_cb, &ctx); + + return error; +} + +VLIB_CLI_COMMAND (dash_show_flow_command, static) = { + .path = "show dash flow", + .short_help = "show dash flow [src-addr IP]", + .function = dash_cmd_show_flow_fn, +}; + +static clib_error_t * +dash_cmd_clear_flow_fn (vlib_main_t * vm, + unformat_input_t * input, vlib_cli_command_t * cmd) +{ + clib_error_t *error = 0; + dash_flow_table_t *flow_table = dash_flow_table_get(); + u32 index; + + if (!unformat (input, "%u", &index)) + { + error = clib_error_return (0, "expected flow index"); + goto done; + } + + + dash_flow_entry_t *flow = dash_flow_get_by_index(index); + sai_status_t status = dash_sai_remove_flow_entry(flow); + if (status != SAI_STATUS_SUCCESS) { + error = clib_error_return (0, "dash_sai_remove_flow_entry fail: %d", status); + } + + TW (tw_timer_stop) (&flow_table->flow_tw, flow->timer_handle); + + if (dash_flow_table_delete_entry (flow_table, flow) == 0) { + dash_flow_free(flow); + } else { + ASSERT(0); + } + +done: + return error; +} + +VLIB_CLI_COMMAND (dash_clear_flow_command, static) = { + .path = "clear dash flow", + .short_help = "clear dash flow ", + .function = dash_cmd_clear_flow_fn, +}; + + +static clib_error_t * +dash_cmd_show_flow_stats_fn (vlib_main_t * vm, + unformat_input_t * input, vlib_cli_command_t * cmd) +{ + clib_error_t *error = 0; + dash_flow_table_t *flow_table = dash_flow_table_get(); + + vlib_cli_output (vm, "%12s: %u", "create_ok", + flow_table->flow_stats.create_ok); + vlib_cli_output (vm, "%12s: %u", "create_fail", + flow_table->flow_stats.create_fail); + vlib_cli_output (vm, "%12s: %u", "remove_ok", + flow_table->flow_stats.remove_ok); + vlib_cli_output (vm, "%12s: %u", "remove_fail", + flow_table->flow_stats.remove_fail); + + return error; +} + +VLIB_CLI_COMMAND (dash_show_flow_stats_command, static) = { + .path = "show dash flow stats", + .short_help = "show dash flow [src-addr IP]", + .function = dash_cmd_show_flow_stats_fn, +}; + diff --git a/dash-pipeline/dpapp/dash/flow.h b/dash-pipeline/dpapp/dash/flow.h new file mode 100644 index 000000000..752564cce --- /dev/null +++ b/dash-pipeline/dpapp/dash/flow.h @@ -0,0 +1,193 @@ +#ifndef __included_flow_h__ +#define __included_flow_h__ + +#include + +#include +#include +#include + +#include + +/* Default timeout in seconds */ +#define DASH_FLOW_TIMEOUT 30 + +typedef enum _dash_packet_source_t { + EXTERNAL = 0, // Packets from external sources. + PIPELINE = 1, // Packets from P4 pipeline. + DPAPP = 2, // Packets from data plane app. + PEER = 3 // Packets from the paired DPU. +} dash_packet_source_t; + +typedef enum _dash_packet_type_t { + REGULAR = 0, // Regular packets from external sources. + FLOW_SYNC_REQ = 1, // Flow sync request packet. + FLOW_SYNC_ACK = 2, // Flow sync ack packet. + DP_PROBE_REQ = 3, // Data plane probe packet. + DP_PROBE_ACK = 4 // Data plane probe ack packet. +} dash_packet_type_t; + +typedef enum _dash_packet_subtype_t { + NONE = 0, // no op + FLOW_CREATE = 1, // New flow creation. + FLOW_UPDATE = 2, // Flow resimulation or any other reason causing existing flow to be updated. + FLOW_DELETE = 3 // Flow deletion. +} dash_packet_subtype_t; + +typedef struct dash_packet_meta { + u8 packet_source; +#if defined(__LITTLE_ENDIAN_BITFIELD) + u8 packet_subtype :4; + u8 packet_type :4; +#elif defined (__BIG_ENDIAN_BITFIELD) + u8 packet_type :4; + u8 packet_subtype :4; +#else +#error "Please fix " +#endif + u16 length; +} __clib_packed dash_packet_meta_t; + +/* + * If sizeof flow_key_t > 48, update the use of bihash_xx + */ +typedef struct flow_key { + u8 eni_mac[6]; + u16 vnet_id; + ip46_address_t src_ip; + ip46_address_t dst_ip; + u16 src_port; + u16 dst_port; + u8 ip_proto; +#if defined(__LITTLE_ENDIAN_BITFIELD) + u8 is_ip_v6 :1; + u8 reserved :7; +#elif defined (__BIG_ENDIAN_BITFIELD) + u8 reserved :7; + u8 is_ip_v6 :1; +#else +#error "Please fix " +#endif +} __clib_packed flow_key_t; + +typedef union { + flow_key_t key; + u64 bihash_key[6]; /* bihash_48_8 */ +} dash_flow_hash_key_t; + +typedef struct flow_data { +#if defined(__LITTLE_ENDIAN_BITFIELD) + u8 is_unidirectional :1; + u8 reserved :7; +#elif defined (__BIG_ENDIAN_BITFIELD) + u8 reserved :7; + u8 is_unidirectional :1; +#else +#error "Please fix " +#endif + u16 direction; + u32 version; + u32 actions; + u32 meter_class; +} __clib_packed flow_data_t; + +typedef struct encap_data { + u16 vni_high; + u8 vni_low; + u8 reserved; + ip4_address_t underlay_sip; + ip4_address_t underlay_dip; + u8 underlay_smac[6]; + u8 underlay_dmac[6]; + u16 dash_encapsulation; +} __clib_packed encap_data_t; + +typedef struct overlay_rewrite_data { + u8 dmac[6]; + ip46_address_t sip; + ip46_address_t dip; + ip6_address_t sip_mask; + ip6_address_t dip_mask; +#if defined(__LITTLE_ENDIAN_BITFIELD) + u8 is_ipv6 :1; + u8 reserved :7; +#elif defined (__BIG_ENDIAN_BITFIELD) + u8 reserved :7; + u8 is_ipv6 :1; +#else +#error "Please fix " +#endif +} __clib_packed overlay_rewrite_data_t; + + +typedef struct dash_header { + dash_packet_meta_t packet_meta; + union { + struct { + flow_key_t flow_key; + flow_data_t flow_data; // flow common data + overlay_rewrite_data_t flow_overlay_data; + encap_data_t flow_u0_encap_data; + encap_data_t flow_u1_encap_data; + }; + u8 data[0]; + }; +} +__clib_packed dash_header_t; + + +typedef struct dash_flow_entry { + union { + flow_key_t key; + u64 bihash_key[6]; /* bihash_48_8 */ + }; + + struct { + flow_data_t flow_data; + overlay_rewrite_data_t flow_overlay_data; + encap_data_t flow_u0_encap_data; + encap_data_t flow_u1_encap_data; + }; + + u32 index; + + /* timers */ + u32 timer_handle; /* index in the timer pool */ + u32 timeout; /* in seconds */ + u64 access_time; /* in seconds */ +} dash_flow_entry_t; + +typedef struct dash_flow_stats { + u32 create_ok; + u32 create_fail; + + u32 remove_ok; + u32 remove_fail; +} dash_flow_stats_t; + +typedef struct dash_flow_table { + /* hashtable */ + BVT(clib_bihash) hash_table; + + dash_flow_entry_t *flow_pool; + dash_flow_stats_t flow_stats; + + TWT (tw_timer_wheel) flow_tw; +} dash_flow_table_t; + +dash_flow_table_t* dash_flow_table_get (void); +dash_flow_entry_t* dash_flow_alloc(); +void dash_flow_free(dash_flow_entry_t *flow); +dash_flow_entry_t* dash_flow_get_by_index (u32 index); + +void dash_flow_table_init (dash_flow_table_t *flow_table); +int dash_flow_table_add_entry (dash_flow_table_t *flow_table, dash_flow_entry_t *flow); +int dash_flow_table_delete_entry (dash_flow_table_t *flow_table, dash_flow_entry_t *flow); +dash_flow_entry_t* dash_flow_table_lookup_entry (dash_flow_table_t *flow_table, flow_key_t *flow_key); + + +int dash_flow_process (dash_flow_table_t *flow_table, const dash_header_t *dh); + +extern vlib_node_registration_t dash_flow_scan_node; + +#endif /* __included_flow_h__ */ diff --git a/dash-pipeline/dpapp/dash/saiapi.c b/dash-pipeline/dpapp/dash/saiapi.c new file mode 100644 index 000000000..00963b11d --- /dev/null +++ b/dash-pipeline/dpapp/dash/saiapi.c @@ -0,0 +1,245 @@ + +#include + +#include +#include + +#include +#include + +static sai_object_id_t dash_switch_id = SAI_NULL_OBJECT_ID; +static sai_dash_flow_api_t *dash_flow_api = NULL; + +void +dash_sai_init () +{ + sai_status_t status; + + status = sai_api_initialize(0, NULL); + ASSERT_MSG(status == SAI_STATUS_SUCCESS, "Failed to initialize SAI api"); + + sai_switch_api_t *switch_api; + status = sai_api_query((sai_api_t)SAI_API_SWITCH, (void**)&switch_api); + ASSERT_MSG(status == SAI_STATUS_SUCCESS, "Failed to query SAI_API_SWITCH"); + + status = switch_api->create_switch(&dash_switch_id, 0, NULL); + ASSERT_MSG(status == SAI_STATUS_SUCCESS, "Failed to create switch"); + + status = sai_api_query((sai_api_t)SAI_API_DASH_FLOW, (void**)&dash_flow_api); + ASSERT_MSG(status == SAI_STATUS_SUCCESS, "Failed to query SAI_API_DASH_FLOW"); + + dash_log_info("Succeeded to init dash sai api"); +} + +sai_status_t +dash_sai_create_flow_entry (const dash_flow_entry_t *flow) +{ + sai_flow_entry_t flow_entry; + u32 count = 0; + sai_attribute_t attrs[SAI_FLOW_ENTRY_ATTR_END]; + const flow_key_t *flow_key = &flow->key; + const flow_data_t *flow_data = &flow->flow_data; + const overlay_rewrite_data_t *flow_overlay_data = &flow->flow_overlay_data; + const encap_data_t *flow_u0_encap_data = &flow->flow_u0_encap_data; + const encap_data_t *flow_u1_encap_data = &flow->flow_u1_encap_data; + + /* + * Fill sai_flow_entry_t, sai_attribute_t, whose values need host order + * ip4/6 address in network order + */ + flow_entry.switch_id = dash_switch_id; + clib_memcpy_fast(flow_entry.eni_mac, flow_key->eni_mac, sizeof(flow_entry.eni_mac)); + flow_entry.vnet_id = ntohs(flow_key->vnet_id); + if (flow_key->is_ip_v6) { + flow_entry.src_ip.addr_family = SAI_IP_ADDR_FAMILY_IPV6; + clib_memcpy_fast(flow_entry.src_ip.addr.ip6, &flow_key->src_ip.ip6, sizeof(sai_ip6_t)); + flow_entry.dst_ip.addr_family = SAI_IP_ADDR_FAMILY_IPV6; + clib_memcpy_fast(flow_entry.dst_ip.addr.ip6, &flow_key->dst_ip.ip6, sizeof(sai_ip6_t)); + } else { + flow_entry.src_ip.addr_family = SAI_IP_ADDR_FAMILY_IPV4; + flow_entry.src_ip.addr.ip4 = flow_key->src_ip.ip4.as_u32; + flow_entry.dst_ip.addr_family = SAI_IP_ADDR_FAMILY_IPV4; + flow_entry.dst_ip.addr.ip4 = flow_key->dst_ip.ip4.as_u32; + } + flow_entry.src_port = ntohs(flow_key->src_port); + flow_entry.dst_port = ntohs(flow_key->dst_port); + flow_entry.ip_proto = flow_key->ip_proto; + + attrs[count].id = SAI_FLOW_ENTRY_ATTR_ACTION; + attrs[count++].value.u32 = SAI_FLOW_ENTRY_ACTION_SET_FLOW_ENTRY_ATTR; + + attrs[count].id = SAI_FLOW_ENTRY_ATTR_VERSION; + attrs[count++].value.u32 = ntohl(flow_data->version); + + attrs[count].id = SAI_FLOW_ENTRY_ATTR_DASH_DIRECTION; + attrs[count++].value.u16 = ntohs(flow_data->direction); + + attrs[count].id = SAI_FLOW_ENTRY_ATTR_DASH_FLOW_ACTION; + attrs[count++].value.u32 = ntohl(flow_data->actions); + + attrs[count].id = SAI_FLOW_ENTRY_ATTR_METER_CLASS; + attrs[count++].value.u32 = ntohl(flow_data->meter_class); + + attrs[count].id = SAI_FLOW_ENTRY_ATTR_IS_UNIDIRECTIONAL_FLOW; + attrs[count++].value.booldata = flow_data->is_unidirectional; + + attrs[count].id = SAI_FLOW_ENTRY_ATTR_DASH_FLOW_SYNC_STATE; + attrs[count++].value.u8 = SAI_DASH_FLOW_SYNC_STATE_FLOW_CREATED; + + /* FIXME: Attrs for reverse flow key */ + { + u8 mac[6] = {0}; + attrs[count].id = SAI_FLOW_ENTRY_ATTR_REVERSE_FLOW_ENI_MAC; + clib_memcpy_fast(attrs[count].value.mac, mac, sizeof(ethernet_header_t)); + count++; + } + + /* Attrs for overlay rewrite data */ + if (flow_data->actions != 0) { + attrs[count].id = SAI_FLOW_ENTRY_ATTR_DST_MAC; + clib_memcpy_fast(attrs[count].value.mac, flow_overlay_data->dmac, sizeof(ethernet_header_t)); + count++; + + if (flow_overlay_data->is_ipv6) { + attrs[count].id = SAI_FLOW_ENTRY_ATTR_SIP; + attrs[count].value.ipaddr.addr_family = SAI_IP_ADDR_FAMILY_IPV6; + clib_memcpy_fast(attrs[count].value.ipaddr.addr.ip6, + &flow_overlay_data->sip.ip6, sizeof(sai_ip6_t)); + count++; + + attrs[count].id = SAI_FLOW_ENTRY_ATTR_DIP; + attrs[count].value.ipaddr.addr_family = SAI_IP_ADDR_FAMILY_IPV6; + clib_memcpy_fast(attrs[count].value.ipaddr.addr.ip6, + &flow_overlay_data->dip.ip6, sizeof(sai_ip6_t)); + count++; + } else { + attrs[count].id = SAI_FLOW_ENTRY_ATTR_SIP; + attrs[count].value.ipaddr.addr_family = SAI_IP_ADDR_FAMILY_IPV4; + attrs[count++].value.ipaddr.addr.ip4 = flow_overlay_data->sip.ip4.as_u32; + + attrs[count].id = SAI_FLOW_ENTRY_ATTR_DIP; + attrs[count].value.ipaddr.addr_family = SAI_IP_ADDR_FAMILY_IPV4; + attrs[count++].value.ipaddr.addr.ip4 = flow_overlay_data->dip.ip4.as_u32; + } + + attrs[count].id = SAI_FLOW_ENTRY_ATTR_SIP_MASK; + attrs[count].value.ipaddr.addr_family = SAI_IP_ADDR_FAMILY_IPV6; + clib_memcpy_fast(attrs[count].value.ipaddr.addr.ip6, + &flow_overlay_data->sip_mask, sizeof(sai_ip6_t)); + count++; + + attrs[count].id = SAI_FLOW_ENTRY_ATTR_DIP_MASK; + attrs[count].value.ipaddr.addr_family = SAI_IP_ADDR_FAMILY_IPV6; + clib_memcpy_fast(attrs[count].value.ipaddr.addr.ip6, + &flow_overlay_data->dip_mask, sizeof(sai_ip6_t)); + count++; + } else { + u8 mac[6] = {0}; + /* set default value for bmv2 table */ + attrs[count].id = SAI_FLOW_ENTRY_ATTR_DST_MAC; + clib_memcpy_fast(attrs[count].value.mac, mac, sizeof(ethernet_header_t)); + count++; + } + + /* Attrs for encap data of underlay 0 */ + if (flow_data->actions & htonl(SAI_DASH_FLOW_ACTION_ENCAP_U0)) { + attrs[count].id = SAI_FLOW_ENTRY_ATTR_UNDERLAY0_VNET_ID; + attrs[count++].value.u32 = ntohs(flow_u0_encap_data->vni_high) << 8 | flow_u0_encap_data->vni_low; + + attrs[count].id = SAI_FLOW_ENTRY_ATTR_UNDERLAY0_SIP; + attrs[count].value.ipaddr.addr_family = SAI_IP_ADDR_FAMILY_IPV4; + attrs[count++].value.ipaddr.addr.ip4 = flow_u0_encap_data->underlay_sip.as_u32; + + attrs[count].id = SAI_FLOW_ENTRY_ATTR_UNDERLAY0_DIP; + attrs[count].value.ipaddr.addr_family = SAI_IP_ADDR_FAMILY_IPV4; + attrs[count++].value.ipaddr.addr.ip4 = flow_u0_encap_data->underlay_dip.as_u32; + + attrs[count].id = SAI_FLOW_ENTRY_ATTR_UNDERLAY0_SMAC; + clib_memcpy_fast(attrs[count].value.mac, flow_u0_encap_data->underlay_smac, sizeof(ethernet_header_t)); + count++; + + attrs[count].id = SAI_FLOW_ENTRY_ATTR_UNDERLAY0_DMAC; + clib_memcpy_fast(attrs[count].value.mac, flow_u0_encap_data->underlay_dmac, sizeof(ethernet_header_t)); + count++; + + attrs[count].id = SAI_FLOW_ENTRY_ATTR_UNDERLAY0_DASH_ENCAPSULATION; + attrs[count++].value.s32 = ntohs(flow_u0_encap_data->dash_encapsulation); + } else { + u8 mac[6] = {0}; + /* set default value for bmv2 table */ + attrs[count].id = SAI_FLOW_ENTRY_ATTR_UNDERLAY0_SMAC; + clib_memcpy_fast(attrs[count].value.mac, mac, sizeof(ethernet_header_t)); + count++; + + attrs[count].id = SAI_FLOW_ENTRY_ATTR_UNDERLAY0_DMAC; + clib_memcpy_fast(attrs[count].value.mac, mac, sizeof(ethernet_header_t)); + count++; + } + + /* Attrs for encap data of underlay 1 */ + if (flow_data->actions & htonl(SAI_DASH_FLOW_ACTION_ENCAP_U1)) { + attrs[count].id = SAI_FLOW_ENTRY_ATTR_UNDERLAY1_VNET_ID; + attrs[count++].value.u32 = ntohs(flow_u1_encap_data->vni_high) << 8 | flow_u1_encap_data->vni_low; + + attrs[count].id = SAI_FLOW_ENTRY_ATTR_UNDERLAY1_SIP; + attrs[count].value.ipaddr.addr_family = SAI_IP_ADDR_FAMILY_IPV4; + attrs[count++].value.ipaddr.addr.ip4 = flow_u1_encap_data->underlay_sip.as_u32; + + attrs[count].id = SAI_FLOW_ENTRY_ATTR_UNDERLAY1_DIP; + attrs[count].value.ipaddr.addr_family = SAI_IP_ADDR_FAMILY_IPV4; + attrs[count++].value.ipaddr.addr.ip4 = flow_u1_encap_data->underlay_dip.as_u32; + + attrs[count].id = SAI_FLOW_ENTRY_ATTR_UNDERLAY1_SMAC; + clib_memcpy_fast(attrs[count].value.mac, flow_u1_encap_data->underlay_smac, sizeof(ethernet_header_t)); + count++; + + attrs[count].id = SAI_FLOW_ENTRY_ATTR_UNDERLAY1_DMAC; + clib_memcpy_fast(attrs[count].value.mac, flow_u1_encap_data->underlay_dmac, sizeof(ethernet_header_t)); + count++; + + attrs[count].id = SAI_FLOW_ENTRY_ATTR_UNDERLAY1_DASH_ENCAPSULATION; + attrs[count++].value.s32 = ntohs(flow_u1_encap_data->dash_encapsulation); + } else { + u8 mac[6] = {0}; + /* set default value for bmv2 table */ + attrs[count].id = SAI_FLOW_ENTRY_ATTR_UNDERLAY1_SMAC; + clib_memcpy_fast(attrs[count].value.mac, mac, sizeof(ethernet_header_t)); + count++; + + attrs[count].id = SAI_FLOW_ENTRY_ATTR_UNDERLAY1_DMAC; + clib_memcpy_fast(attrs[count].value.mac, mac, sizeof(ethernet_header_t)); + count++; + } + + return dash_flow_api->create_flow_entry(&flow_entry, count, attrs); +} + +sai_status_t +dash_sai_remove_flow_entry (const dash_flow_entry_t *flow) +{ + sai_flow_entry_t flow_entry; + const flow_key_t *flow_key = &flow->key; + + flow_entry.switch_id = dash_switch_id; + clib_memcpy_fast(flow_entry.eni_mac, flow_key->eni_mac, sizeof(flow_entry.eni_mac)); + flow_entry.vnet_id = ntohs(flow_key->vnet_id); + + if (flow_key->is_ip_v6) { + flow_entry.src_ip.addr_family = SAI_IP_ADDR_FAMILY_IPV6; + clib_memcpy_fast(flow_entry.src_ip.addr.ip6, &flow_key->src_ip.ip6, sizeof(sai_ip6_t)); + flow_entry.dst_ip.addr_family = SAI_IP_ADDR_FAMILY_IPV6; + clib_memcpy_fast(flow_entry.dst_ip.addr.ip6, &flow_key->dst_ip.ip6, sizeof(sai_ip6_t)); + } else { + flow_entry.src_ip.addr_family = SAI_IP_ADDR_FAMILY_IPV4; + flow_entry.src_ip.addr.ip4 = flow_key->src_ip.ip4.as_u32; + flow_entry.dst_ip.addr_family = SAI_IP_ADDR_FAMILY_IPV4; + flow_entry.dst_ip.addr.ip4 = flow_key->dst_ip.ip4.as_u32; + } + + flow_entry.src_port = ntohs(flow_key->src_port); + flow_entry.dst_port = ntohs(flow_key->dst_port); + flow_entry.ip_proto = flow_key->ip_proto; + + return dash_flow_api->remove_flow_entry(&flow_entry); +} + diff --git a/dash-pipeline/dpapp/dpapp.sh b/dash-pipeline/dpapp/dpapp.sh new file mode 100755 index 000000000..5e6514c84 --- /dev/null +++ b/dash-pipeline/dpapp/dpapp.sh @@ -0,0 +1,18 @@ +#!/bin/bash +set -m + +[ -d /var/log/vpp ] || mkdir -p /var/log/vpp + +sysctl vm.nr_hugepages=32 + +/usr/bin/vpp -c ${1:-/etc/vpp/startup.conf} & +sleep 5 + +# Create a host interface which connects p4 bmv2 simple_switch +HOST_INTERFACE=${HOST_INTERFACE:-veth5} +HOST_INTERFACE_MAC=`cat /sys/class/net/$HOST_INTERFACE/address` +vppctl create host-interface name $HOST_INTERFACE hw-addr $HOST_INTERFACE_MAC +vppctl set interface state host-$HOST_INTERFACE up + +# Move vpp to foreground +fg %1 diff --git a/dash-pipeline/dpapp/startup.conf b/dash-pipeline/dpapp/startup.conf new file mode 100644 index 000000000..248442fb3 --- /dev/null +++ b/dash-pipeline/dpapp/startup.conf @@ -0,0 +1,37 @@ +unix { + nodaemon + log /var/log/vpp/vpp.log + full-coredump + cli-listen /run/vpp/cli.sock + gid vpp +} + +api-trace { + on +} + +api-segment { + gid vpp +} + +socksvr { + default +} + +logging { + default-log-level info + default-syslog-log-level info +} + +cpu { + main-core 1 + corelist-workers 2 +} + +plugins { + add-path /dash/dash-pipeline/dpapp/build/lib/vpp_plugins + plugin default {disable} + plugin af_packet_plugin.so {enable} + plugin dash_plugin.so {enable} +} + diff --git a/dash-pipeline/dpapp/tools/send_p2a_pkt.py b/dash-pipeline/dpapp/tools/send_p2a_pkt.py new file mode 100755 index 000000000..49a31c691 --- /dev/null +++ b/dash-pipeline/dpapp/tools/send_p2a_pkt.py @@ -0,0 +1,127 @@ +#!/usr/bin/python3 +# -*- coding: utf-8 -*- +import re +import sys +from scapy.all import * +import argparse + +class DASH_PACKET_META(Packet): + name = "DASH_PACKET_META" + fields_desc = [ ByteField("packet_source", 0), + BitField("packet_type", 0, 4), + BitField("packet_subtype", 1, 4), + ShortField("length", 4), + ] + +class DASH_FLOW_KEY(Packet): + name = "DASH_FLOW_KEY" + fields_desc = [ MACField("eni_mac", "0:0:0:0:0:0"), + ShortField("vnet_id", 2), + IP6Field("src_ip", "::1.1.1.1"), + IP6Field("dst_ip", "::2.2.2.2"), + XShortField("src_port", 0x5566), + XShortField("dst_port", 0x6677), + ByteEnumField("ip_proto", IP_PROTOS.udp, IP_PROTOS), + BitField("reserved", 0, 7), + BitField("is_ip_v6", 0, 1), + ] + +class DASH_FLOW_DATA(Packet): + name = "DASH_FLOW_DATA" + fields_desc = [ + BitField("reserved", 0, 7), + BitField("is_unidirectional", 0, 1), + ShortEnumField("direction", 1, { 1: "OUTBOUND", 2: "INBOUND" }), + IntField("version", 0), + IntField("actions", 0), + IntField("meter_class", 0), + ] + +class DASH_OVERLAY_DATA(Packet): + name = "DASH_OVERLAY_DATA" + fields_desc = [ MACField("dmac", 0), + IP6Field("sip", "::"), + IP6Field("dip", "::"), + IP6Field("sip_mask", "::"), + IP6Field("dip_mask", "::"), + BitField("reserved", 0, 7), + BitField("is_ipv6", 0, 1), + ] + +class DASH_ENCAP_DATA(Packet): + name = "DASH_ENCAP_DATA" + fields_desc = [ BitField("vni", 1, 24), + BitField("reserved", 0, 8), + IPField("underlay_sip", "1.1.1.1"), + IPField("underlay_dip", "2.2.2.2"), + MACField("underlay_smac", "0:0:0:0:0:0"), + MACField("underlay_dmac", "0:0:0:0:0:0"), + ShortField("dash_encapsulation", 1), + ] + + +def get_mac(interface): + try: + mac = open('/sys/class/net/'+interface+'/address').readline().strip() + except: + mac = "00:00:00:00:00:00" + return mac + +if __name__ == "__main__": + parser = argparse.ArgumentParser(description="Packet generator on behalf of DASH pipeline") + parser.add_argument("--flow-action", type=str, default="CREATE", + help="Flow action, CREATE|UPDATE|DELETE") + parser.add_argument("--flow-key", type=str, + help="Flow key, string style eni_mac=,vnet_id=,src_ip=,dst_ip=,...") + parser.add_argument("--from-port", type=str, default="veth4", + help="DASH pipeline port name") + parser.add_argument("--to-port", type=str, default="veth5", + help="cpu port name") + args = parser.parse_args() + + dpappEther = Ether(dst=get_mac(args.to_port), + src=get_mac(args.from_port), type=0x876D) + + action_dic = { "CREATE":1, "UPDATE":2, "DELETE":3 } + try: + flow_action = action_dic[args.flow_action] + except KeyError: + print(f"Invalid flow action name: {args.flow_action}") + exit(1) + + if args.flow_key: + flow_key = dict(kv.split("=") for kv in args.flow_key.split(",")) + if "vnet_id" in flow_key: + flow_key["vnet_id"] = int(flow_key["vnet_id"]) + if "src_port" in flow_key: + flow_key["src_port"] = int(flow_key["src_port"]) + if "dst_port" in flow_key: + flow_key["dst_port"] = int(flow_key["dst_port"]) + if "ip_proto" in flow_key: + flow_key["ip_proto"] = int(flow_key["ip_proto"]) + if "is_ip_v6" in flow_key: + flow_key["is_ip_v6"] = int(flow_key["is_ip_v6"]) + else: + flow_key = {} + + packetMeta = DASH_PACKET_META(packet_subtype = flow_action) + flowKey = DASH_FLOW_KEY(**flow_key) + flowData = DASH_FLOW_DATA() + packetMeta.length = len(packetMeta) + len(flowKey) + len(flowData) + dashMeta = packetMeta/flowKey/flowData + + if flowKey.is_ip_v6: + L3 = IPv6(src = flowKey.src_ip, dst = flowKey.dst_ip) + else: + L3 = IP(src = flowKey.src_ip.lstrip("::"), dst = flowKey.dst_ip.lstrip("::")) + + if flowKey.ip_proto == IP_PROTOS.tcp: + L4 = TCP(sport=flowKey.src_port, dport=flowKey.dst_port) + else: + L4 = UDP(sport=flowKey.src_port, dport=flowKey.dst_port) + + customerPacket = Ether(dst="00:02:02:02:02:02") / L3 / L4 / ("a"*16) + + pkt = dpappEther/dashMeta/customerPacket + sendp(pkt, iface=args.from_port, count=1) + diff --git a/test/test-cases/functional/ptf/p4_dash_utils.py b/test/test-cases/functional/ptf/p4_dash_utils.py index bc93b7c79..1e87da321 100644 --- a/test/test-cases/functional/ptf/p4_dash_utils.py +++ b/test/test-cases/functional/ptf/p4_dash_utils.py @@ -1,6 +1,8 @@ import grpc from p4.v1 import p4runtime_pb2 from p4.v1 import p4runtime_pb2_grpc +from ipaddress import ip_address +from scapy.all import * def get_mac(interface): @@ -175,3 +177,110 @@ def tearDown(self, *args, **kwargs): setattr(cls, "tearDown", tearDown) return cls + +class P4Table(): + def __init__(self): + channel = grpc.insecure_channel('localhost:9559') + self.stub = p4runtime_pb2_grpc.P4RuntimeStub(channel) + self.p4info = P4info(self.stub) + + def read(self, table_id, match_list = None): + entry = p4runtime_pb2.TableEntry() + entry.table_id = table_id + if match_list: + entry.match.extend(match_list) + + req = p4runtime_pb2.ReadRequest() + req.device_id = 0 + entity = req.entities.add() + entity.table_entry.CopyFrom(entry) + for response in self.stub.Read(req): + for entity in response.entities: + yield entity.table_entry + + +class P4FlowTable(P4Table): + def __init__(self): + super(P4FlowTable, self).__init__() + self.p4info_table_flow = self.p4info.get_table("dash_ingress.conntrack_lookup_stage.flow_entry") + + def print_flow_table(self): + for entry in self.read(self.p4info_table_flow.preamble.id): + print(entry) + + def get_flow_entry(self, eni_mac, vnet_id, + src_ip, dst_ip, + src_port, dst_port, ip_proto): + match_list = [] + + match = p4runtime_pb2.FieldMatch() + match.field_id = 1 + match.exact.value = mac_in_bytes(eni_mac) + match_list.append(match) + + match = p4runtime_pb2.FieldMatch() + match.field_id = 2 + match.exact.value = vnet_id.to_bytes(2, byteorder='big') + match_list.append(match) + + match = p4runtime_pb2.FieldMatch() + match.field_id = 3 + match.exact.value = ip_address(src_ip).packed + match_list.append(match) + + match = p4runtime_pb2.FieldMatch() + match.field_id = 4 + match.exact.value = ip_address(dst_ip).packed + match_list.append(match) + + match = p4runtime_pb2.FieldMatch() + match.field_id = 5 + match.exact.value = src_port.to_bytes(2, byteorder='big') + match_list.append(match) + + match = p4runtime_pb2.FieldMatch() + match.field_id = 6 + match.exact.value = dst_port.to_bytes(2, byteorder='big') + match_list.append(match) + + match = p4runtime_pb2.FieldMatch() + match.field_id = 7 + match.exact.value = ip_proto.to_bytes(1, byteorder='big') + match_list.append(match) + + match = p4runtime_pb2.FieldMatch() + match.field_id = 8 + match.exact.value = b'\x00' if ip_address(src_ip).version == 4 else b'\x01' + match_list.append(match) + + for entry in self.read(self.p4info_table_flow.preamble.id, match_list): + return entry + + return None + + +def verify_flow(eni_mac, vnet_id, packet, existed = True): + if packet.haslayer(TCP): + sport = packet['TCP'].sport + dport = packet['TCP'].dport + elif packet.haslayer(UDP): + sport = packet['UDP'].sport + dport = packet['UDP'].dport + else: # TODO: later for other ip proto + assert False, "Not TCP/UDP packet" + + flow_table = P4FlowTable() + flow = flow_table.get_flow_entry(eni_mac, vnet_id, + packet['IP'].src, + packet['IP'].dst, + sport, + dport, + packet['IP'].proto) + if existed: + assert flow, "flow not found" + else: + assert not flow, "flow still found" + + +def verify_no_flow(eni_mac, vnet_id, packet): + verify_flow(eni_mac, vnet_id, packet, existed = False) diff --git a/test/test-cases/functional/ptf/saidashdpapp_sanity.py b/test/test-cases/functional/ptf/saidashdpapp_sanity.py new file mode 100644 index 000000000..f03b59af7 --- /dev/null +++ b/test/test-cases/functional/ptf/saidashdpapp_sanity.py @@ -0,0 +1,327 @@ +from sai_thrift.sai_headers import * +from sai_base_test import * +from p4_dash_utils import * + +@use_flow +class SaiThriftDpappPktTest(SaiHelperSimplified): + """ Test saithrift vnet outbound towards dpapp""" + + def setUp(self): + super(SaiThriftDpappPktTest, self).setUp() + self.switch_id = 5 + self.outbound_vni = 60 + self.vnet_vni = 100 + self.eni_mac = "00:cc:cc:cc:cc:cc" + self.our_mac = "00:00:02:03:04:05" + self.dst_ca_mac = "00:dd:dd:dd:dd:dd" + self.vip = "172.16.1.100" + self.ca_prefix_addr = "10.1.0.0" + self.ca_prefix_mask = "255.255.0.0" + self.dst_ca_ip = "10.1.2.50" + self.dst_pa_ip = "172.16.1.20" + self.src_vm_pa_ip = "172.16.1.1" + self.dpapp_port = 2 + + # SAI attribute name + self.ip_addr_family_attr = 'ip4' + # SAI address family + self.sai_ip_addr_family = SAI_IP_ADDR_FAMILY_IPV4 + + # Flag to indicate whether configureVnet were successful or not. + self.configured = False + + def configureVnet(self): + """Create VNET configuration""" + + vip = sai_thrift_ip_address_t(addr_family=SAI_IP_ADDR_FAMILY_IPV4, + addr=sai_thrift_ip_addr_t(ip4=self.vip)) + self.vpe = sai_thrift_vip_entry_t(switch_id=self.switch_id, vip=vip) + + status = sai_thrift_create_vip_entry(self.client, self.vpe, + action=SAI_VIP_ENTRY_ACTION_ACCEPT) + assert(status == SAI_STATUS_SUCCESS) + + self.dle = sai_thrift_direction_lookup_entry_t(switch_id=self.switch_id, vni=self.outbound_vni) + status = sai_thrift_create_direction_lookup_entry(self.client, self.dle, + action=SAI_DIRECTION_LOOKUP_ENTRY_ACTION_SET_OUTBOUND_DIRECTION) + assert(status == SAI_STATUS_SUCCESS) + + self.in_acl_group_id = sai_thrift_create_dash_acl_group(self.client, + ip_addr_family=self.sai_ip_addr_family) + assert (self.in_acl_group_id != SAI_NULL_OBJECT_ID) + self.out_acl_group_id = sai_thrift_create_dash_acl_group(self.client, + ip_addr_family=self.sai_ip_addr_family) + assert (self.out_acl_group_id != SAI_NULL_OBJECT_ID) + + self.vnet = sai_thrift_create_vnet(self.client, vni=self.vnet_vni) + assert (self.vnet != SAI_NULL_OBJECT_ID) + + self.outbound_routing_group = sai_thrift_create_outbound_routing_group(self.client, disabled=False) + assert (self.outbound_routing_group != SAI_NULL_OBJECT_ID) + + vm_underlay_dip = sai_thrift_ip_address_t(addr_family=SAI_IP_ADDR_FAMILY_IPV4, + addr=sai_thrift_ip_addr_t(ip4=self.src_vm_pa_ip)) + pl_sip_mask = sai_thrift_ip_address_t(addr_family=SAI_IP_ADDR_FAMILY_IPV6, + addr=sai_thrift_ip_addr_t(ip6="2001:0db8:85a3:0000:0000:0000:0000:0000")) + pl_sip = sai_thrift_ip_address_t(addr_family=SAI_IP_ADDR_FAMILY_IPV6, + addr=sai_thrift_ip_addr_t(ip6="2001:0db8:85a3:0000:0000:8a2e:0370:7334")) + pl_underlay_sip = sai_thrift_ip_address_t(addr_family=SAI_IP_ADDR_FAMILY_IPV4, + addr=sai_thrift_ip_addr_t(ip4="10.0.0.18")) + self.eni = sai_thrift_create_eni(self.client, cps=10000, + pps=100000, flows=100000, + admin_state=True, + ha_scope_id=0, + vm_underlay_dip=vm_underlay_dip, + vm_vni=9, + vnet_id=self.vnet, + pl_sip = pl_sip, + pl_sip_mask = pl_sip_mask, + pl_underlay_sip = pl_underlay_sip, + v4_meter_policy_id = 0, + v6_meter_policy_id = 0, + dash_tunnel_dscp_mode=SAI_DASH_TUNNEL_DSCP_MODE_PRESERVE_MODEL, + dscp=0, + # TODO: Enable ACL rule + #inbound_v4_stage1_dash_acl_group_id = self.in_acl_group_id, + #inbound_v4_stage2_dash_acl_group_id = self.in_acl_group_id, + #inbound_v4_stage3_dash_acl_group_id = self.in_acl_group_id, + #inbound_v4_stage4_dash_acl_group_id = self.in_acl_group_id, + #inbound_v4_stage5_dash_acl_group_id = self.in_acl_group_id, + #outbound_v4_stage1_dash_acl_group_id = self.out_acl_group_id, + #outbound_v4_stage2_dash_acl_group_id = self.out_acl_group_id, + #outbound_v4_stage3_dash_acl_group_id = self.out_acl_group_id, + #outbound_v4_stage4_dash_acl_group_id = self.out_acl_group_id, + #outbound_v4_stage5_dash_acl_group_id = self.out_acl_group_id, + inbound_v4_stage1_dash_acl_group_id = 0, + inbound_v4_stage2_dash_acl_group_id = 0, + inbound_v4_stage3_dash_acl_group_id = 0, + inbound_v4_stage4_dash_acl_group_id = 0, + inbound_v4_stage5_dash_acl_group_id = 0, + outbound_v4_stage1_dash_acl_group_id = 0, + outbound_v4_stage2_dash_acl_group_id = 0, + outbound_v4_stage3_dash_acl_group_id = 0, + outbound_v4_stage4_dash_acl_group_id = 0, + outbound_v4_stage5_dash_acl_group_id = 0, + inbound_v6_stage1_dash_acl_group_id = 0, + inbound_v6_stage2_dash_acl_group_id = 0, + inbound_v6_stage3_dash_acl_group_id = 0, + inbound_v6_stage4_dash_acl_group_id = 0, + inbound_v6_stage5_dash_acl_group_id = 0, + outbound_v6_stage1_dash_acl_group_id = 0, + outbound_v6_stage2_dash_acl_group_id = 0, + outbound_v6_stage3_dash_acl_group_id = 0, + outbound_v6_stage4_dash_acl_group_id = 0, + outbound_v6_stage5_dash_acl_group_id = 0, + disable_fast_path_icmp_flow_redirection = 0, + full_flow_resimulation_requested=False, + max_resimulated_flow_per_second=0, + outbound_routing_group_id=self.outbound_routing_group) + + self.eam = sai_thrift_eni_ether_address_map_entry_t(switch_id=self.switch_id, address = self.eni_mac) + status = sai_thrift_create_eni_ether_address_map_entry(self.client, + eni_ether_address_map_entry=self.eam, + eni_id=self.eni) + assert(status == SAI_STATUS_SUCCESS) + + dip = sai_thrift_ip_address_t(addr_family=self.sai_ip_addr_family, + addr=sai_thrift_ip_addr_t(**{self.ip_addr_family_attr: self.dst_ca_ip})) + + # TODO: Enable ACL rule for IPv6 + if self.sai_ip_addr_family == SAI_IP_ADDR_FAMILY_IPV4: + self.out_acl_rule_id = sai_thrift_create_dash_acl_rule(self.client, dash_acl_group_id=self.out_acl_group_id, priority=10, + action=SAI_DASH_ACL_RULE_ACTION_PERMIT) + assert(status == SAI_STATUS_SUCCESS) + + ca_prefix = sai_thrift_ip_prefix_t(addr_family=self.sai_ip_addr_family, + addr=sai_thrift_ip_addr_t(**{self.ip_addr_family_attr: self.ca_prefix_addr}), + mask=sai_thrift_ip_addr_t(**{self.ip_addr_family_attr: self.ca_prefix_mask})) + self.ore = sai_thrift_outbound_routing_entry_t(switch_id=self.switch_id, outbound_routing_group_id=self.outbound_routing_group, destination=ca_prefix) + status = sai_thrift_create_outbound_routing_entry(self.client, self.ore, + action=SAI_OUTBOUND_ROUTING_ENTRY_ACTION_ROUTE_VNET, + dst_vnet_id=self.vnet, + meter_class_or=0, meter_class_and=-1, + dash_tunnel_id=0, routing_actions_disabled_in_flow_resimulation = 0) + assert(status == SAI_STATUS_SUCCESS) + + underlay_dip = sai_thrift_ip_address_t(addr_family=SAI_IP_ADDR_FAMILY_IPV4, + addr=sai_thrift_ip_addr_t(ip4=self.dst_pa_ip)) + self.ocpe = sai_thrift_outbound_ca_to_pa_entry_t(switch_id=self.switch_id, dst_vnet_id=self.vnet, dip=dip) + status = sai_thrift_create_outbound_ca_to_pa_entry(self.client, self.ocpe, action=SAI_OUTBOUND_CA_TO_PA_ENTRY_ACTION_SET_TUNNEL_MAPPING, + underlay_dip = underlay_dip, + overlay_dmac=self.dst_ca_mac, use_dst_vnet_vni = True, + meter_class_or=0, flow_resimulation_requested = False, dash_tunnel_id=0, + routing_actions_disabled_in_flow_resimulation = 0) + assert(status == SAI_STATUS_SUCCESS) + + + print(f"\n{self.__class__.__name__} configureVnet OK\n") + self.configured = True + + def trafficUdpTest(self): + + src_vm_ip = "10.1.1.10" + outer_smac = "00:00:05:06:06:06" + + # check forwarding + inner_pkt = simple_udp_packet(eth_dst="02:02:02:02:02:02", + eth_src=self.eni_mac, + ip_dst=self.dst_ca_ip, + ip_src=src_vm_ip) + vxlan_pkt = simple_vxlan_packet(eth_dst=self.our_mac, + eth_src=outer_smac, + ip_dst=self.vip, + ip_src=self.src_vm_pa_ip, + udp_sport=11638, + with_udp_chksum=False, + vxlan_vni=self.outbound_vni, + inner_frame=inner_pkt) + + inner_exp_pkt = simple_udp_packet(eth_dst=self.dst_ca_mac, + eth_src=self.eni_mac, + ip_dst=self.dst_ca_ip, + ip_src=src_vm_ip) + vxlan_exp_pkt = simple_vxlan_packet(eth_dst="00:00:00:00:00:00", + eth_src="00:00:00:00:00:00", + ip_dst=self.dst_pa_ip, + ip_src=self.vip, + udp_sport=0, # TODO: Fix sport in pipeline + with_udp_chksum=False, + vxlan_vni=self.vnet_vni, + inner_frame=inner_exp_pkt) + + self.pkt_exp = vxlan_exp_pkt + print("\tSending outbound udp packet...") + send_packet(self, 0, vxlan_pkt) + print("\tVerifying packet...") + verify_packet(self, self.pkt_exp, 0) + print("\tVerifying flow created...") + verify_flow(self.eni_mac, self.vnet & 0xffff, inner_pkt) + print(f"{self.__class__.__name__} trafficUdpTest OK\n") + + def trafficTcpTest(self): + + src_vm_ip = "10.1.1.10" + outer_smac = "00:00:05:06:06:06" + tcp_src_port = 0x1234 + tcp_dst_port = 0x50 + + # customer packet: tcp SYN + inner_pkt = simple_tcp_packet(eth_dst="02:02:02:02:02:02", + eth_src=self.eni_mac, + ip_dst=self.dst_ca_ip, + ip_src=src_vm_ip, + tcp_sport=tcp_src_port, + tcp_dport=tcp_dst_port, + tcp_flags="S") + vxlan_pkt = simple_vxlan_packet(eth_dst=self.our_mac, + eth_src=outer_smac, + ip_dst=self.vip, + ip_src=self.src_vm_pa_ip, + udp_sport=11638, + with_udp_chksum=False, + vxlan_vni=self.outbound_vni, + inner_frame=inner_pkt) + + inner_exp_pkt = simple_tcp_packet(eth_dst=self.dst_ca_mac, + eth_src=self.eni_mac, + ip_dst=self.dst_ca_ip, + ip_src=src_vm_ip, + tcp_sport=tcp_src_port, + tcp_dport=tcp_dst_port, + tcp_flags="S") + vxlan_exp_pkt = simple_vxlan_packet(eth_dst="00:00:00:00:00:00", + eth_src="00:00:00:00:00:00", + ip_dst=self.dst_pa_ip, + ip_src=self.vip, + udp_sport=0, # TODO: Fix sport in pipeline + with_udp_chksum=False, + vxlan_vni=self.vnet_vni, + inner_frame=inner_exp_pkt) + + self.pkt_exp = vxlan_exp_pkt + print("\tSending outbound packet TCP SYN ...") + send_packet(self, 0, vxlan_pkt) + print("\tVerifying packet...") + verify_packet(self, self.pkt_exp, 0) + print("\tVerifying flow created...") + verify_flow(self.eni_mac, self.vnet & 0xffff, inner_pkt) + + # customer packet: tcp FIN + inner_pkt = simple_tcp_packet(eth_dst="02:02:02:02:02:02", + eth_src=self.eni_mac, + ip_dst=self.dst_ca_ip, + ip_src=src_vm_ip, + tcp_sport=tcp_src_port, + tcp_dport=tcp_dst_port, + tcp_flags="F") + vxlan_pkt = simple_vxlan_packet(eth_dst=self.our_mac, + eth_src=outer_smac, + ip_dst=self.vip, + ip_src=self.src_vm_pa_ip, + udp_sport=11638, + with_udp_chksum=False, + vxlan_vni=self.outbound_vni, + inner_frame=inner_pkt) + + inner_exp_pkt = simple_tcp_packet(eth_dst=self.dst_ca_mac, + eth_src=self.eni_mac, + ip_dst=self.dst_ca_ip, + ip_src=src_vm_ip, + tcp_sport=tcp_src_port, + tcp_dport=tcp_dst_port, + tcp_flags="F") + vxlan_exp_pkt = simple_vxlan_packet(eth_dst="00:00:00:00:00:00", + eth_src="00:00:00:00:00:00", + ip_dst=self.dst_pa_ip, + ip_src=self.vip, + udp_sport=0, # TODO: Fix sport in pipeline + with_udp_chksum=False, + vxlan_vni=self.vnet_vni, + inner_frame=inner_exp_pkt) + + self.pkt_exp = vxlan_exp_pkt + print("\tSending outbound packet TCP FIN ...") + send_packet(self, 0, vxlan_pkt) + print("\tVerifying packet...") + verify_packet(self, self.pkt_exp, 0) + print("\tVerifying flow deleted...") + verify_no_flow(self.eni_mac, self.vnet & 0xffff, inner_pkt) + + print(f"{self.__class__.__name__} trafficTcpTest OK\n") + + def runTest(self): + + self.configureVnet() + self.trafficUdpTest() + self.trafficTcpTest() + + def tearDown(self): + + status = True + try: + # Delete entries in the reverse order + status &= sai_thrift_remove_outbound_ca_to_pa_entry(self.client, self.ocpe) + status &= sai_thrift_remove_outbound_routing_entry(self.client, self.ore) + if self.sai_ip_addr_family == SAI_IP_ADDR_FAMILY_IPV4: + status &= sai_thrift_remove_dash_acl_rule(self.client, self.out_acl_rule_id) + status &= sai_thrift_remove_eni_ether_address_map_entry(self.client, self.eam) + status &= sai_thrift_remove_eni(self.client, self.eni) + status &= sai_thrift_remove_vnet(self.client, self.vnet) + status &= sai_thrift_remove_dash_acl_group(self.client, self.out_acl_group_id) + status &= sai_thrift_remove_dash_acl_group(self.client, self.in_acl_group_id) + status &= sai_thrift_remove_direction_lookup_entry(self.client, self.dle) + status &= sai_thrift_remove_vip_entry(self.client, self.vpe) + status &= sai_thrift_remove_route_entry(self.client, self.pa_route_entry) + if self.configured: + # Skip remove status verification if the configuration creation failed + self.assertEqual(status, SAI_STATUS_SUCCESS) + print(f"{self.__class__.__name__} tearDown OK") + except: + # Ignore errors if configuration were unsuccessful + if self.configured: + raise + finally: + # Run standard PTF teardown + super(SaiThriftDpappPktTest, self).tearDown() + + diff --git a/test/test-cases/functional/ptf/saidashvnet_sanity.py b/test/test-cases/functional/ptf/saidashvnet_sanity.py index 5080b5baa..c001e1702 100644 --- a/test/test-cases/functional/ptf/saidashvnet_sanity.py +++ b/test/test-cases/functional/ptf/saidashvnet_sanity.py @@ -2,6 +2,7 @@ from sai_base_test import * from p4_dash_utils import * +@use_flow class SaiThriftVnetOutboundUdpPktTest(SaiHelperSimplified): """ Test saithrift vnet outbound""" From 69d76b57d47e8879fd641fda38d33cdc8fb8227a Mon Sep 17 00:00:00 2001 From: Junhua Zhai Date: Fri, 6 Dec 2024 10:14:38 +0800 Subject: [PATCH 6/8] [libsai] Tidy up saiapi.cpp.j2 (#646) Adjust the api locations, remove white spaces at the line end and remove blank lines, as to generate neat code. Taking generated file SAI/lib/saidashoutboundrouting.cpp as an example, the side effect of this change is as below: - Remove the useless comment and align the statement ![image](https://github.com/user-attachments/assets/62c567be-38d9-4924-bdeb-70851bb7474d) - Move bulk APIs (create|remove)_outbound_routing_entries after quad APIs (create|remove|set|get)_outbound_routing_group_attribute ![image](https://github.com/user-attachments/assets/ed802023-6cb4-47fa-95d7-e82013b6668e) ![image](https://github.com/user-attachments/assets/0e7d901d-aba0-499c-9574-7d8176a11241) - Remove white space between function name and '(' ![image](https://github.com/user-attachments/assets/652eb3ec-719a-4456-a075-cd8d79a70659) --- dash-pipeline/SAI/templates/saiapi.cpp.j2 | 186 +++++++++++----------- 1 file changed, 91 insertions(+), 95 deletions(-) diff --git a/dash-pipeline/SAI/templates/saiapi.cpp.j2 b/dash-pipeline/SAI/templates/saiapi.cpp.j2 index 93f4dd508..37f0df927 100644 --- a/dash-pipeline/SAI/templates/saiapi.cpp.j2 +++ b/dash-pipeline/SAI/templates/saiapi.cpp.j2 @@ -65,7 +65,7 @@ static sai_status_t dash_sai_create_{{ table.name }}( 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(objId), key_mf_exact, {{ key.bitwidth }}); + {{key.field}}SetVal(static_cast(objId), key_mf_exact, {{ key.bitwidth }}); {% endif %} {% endfor %} @@ -115,7 +115,7 @@ static sai_status_t dash_sai_create_{{ table.name }}( {% endif %} {% elif key.match_type == 'range_list' %} // BMv2 doesn't support "range_list" match type, and we are using "optional" match in v1model as our implementation. - // Hence, here we only take the first item from the list and program it as optional match. + // Hence, here we only take the first item from the list and program the range start as optional match. assert(attr_list[i].value.{{key.field}}.count == 1 && "BMv2 only supports one item in list match type"); auto mf_optional = mf->mutable_optional(); {{ key.field | replace('rangelist', '') }}SetVal(attr_list[i].value.{{key.field}}.list[0].min, mf_optional, {{key.bitwidth}}); @@ -190,7 +190,6 @@ static sai_status_t dash_sai_create_{{ table.name }}( } } {% endif %} - action->set_action_id(actionId); for (uint32_t i = 0; i < attr_count; i++) @@ -247,19 +246,6 @@ ErrRet: return SAI_STATUS_FAILURE; } -static sai_status_t dash_sai_create_{{ table.name }}s( - _In_ sai_object_id_t switch_id, - _In_ uint32_t object_count, - _In_ const uint32_t *attr_count, - _In_ const sai_attribute_t **attr_list, - _In_ sai_bulk_op_error_mode_t mode, - _Out_ sai_object_id_t *object_id, - _Out_ sai_status_t *object_statuses) -{ - DASH_LOG_ENTER(); - return dash::DashSai::bulk_create_objects(dash_sai_create_{{ table.name }}, switch_id, object_count, attr_count, attr_list, mode, object_id, object_statuses); -} - static sai_status_t dash_sai_remove_{{ table.name }}( _In_ sai_object_id_t {{ table.name }}_id) { @@ -273,17 +259,7 @@ static sai_status_t dash_sai_remove_{{ table.name }}( return SAI_STATUS_FAILURE; } -static sai_status_t dash_sai_remove_{{ table.name }}s( - _In_ uint32_t object_count, - _In_ const sai_object_id_t *object_id, - _In_ sai_bulk_op_error_mode_t mode, - _Out_ sai_status_t *object_statuses) -{ - DASH_LOG_ENTER(); - return dash::DashSai::bulk_remove_objects(dash_sai_remove_{{ table.name }}, object_count, object_id, mode, object_statuses); -} - -static sai_status_t dash_sai_set_{{ table.name }}_attribute ( +static sai_status_t dash_sai_set_{{ table.name }}_attribute( _In_ sai_object_id_t {{ table.name }}_id, _In_ const sai_attribute_t *attr) { @@ -335,7 +311,30 @@ static sai_status_t dash_sai_clear_{{ table.name }}_stats( assert(0 && "sai_clear_{{ table.name }}_stats NYI"); return SAI_STATUS_FAILURE; } + {% endif %} +static sai_status_t dash_sai_create_{{ table.name }}s( + _In_ sai_object_id_t switch_id, + _In_ uint32_t object_count, + _In_ const uint32_t *attr_count, + _In_ const sai_attribute_t **attr_list, + _In_ sai_bulk_op_error_mode_t mode, + _Out_ sai_object_id_t *object_id, + _Out_ sai_status_t *object_statuses) +{ + DASH_LOG_ENTER(); + return dash::DashSai::bulk_create_objects(dash_sai_create_{{ table.name }}, switch_id, object_count, attr_count, attr_list, mode, object_id, object_statuses); +} + +static sai_status_t dash_sai_remove_{{ table.name }}s( + _In_ uint32_t object_count, + _In_ const sai_object_id_t *object_id, + _In_ sai_bulk_op_error_mode_t mode, + _Out_ sai_status_t *object_statuses) +{ + DASH_LOG_ENTER(); + return dash::DashSai::bulk_remove_objects(dash_sai_remove_{{ table.name }}, object_count, object_id, mode, object_statuses); +} {% else %} static sai_status_t dash_sai_create_{{ table.name }}( _In_ const sai_{{ table.name }}_t *{{ table.name }}, @@ -366,13 +365,12 @@ static sai_status_t dash_sai_create_{{ table.name }}( mf->set_field_id({{key.id}}); {% if key.match_type == 'exact' %} auto mf_exact = mf->mutable_exact(); - //{{key.field}}SetVal(tableEntry->{{ key.name | lower }}, mf_exact, {{key.bitwidth}}); {% set keyfield = key.field %} {% set bitwidth = key.bitwidth %} - {% if keyfield in ['ipaddr','mac'] or bitwidth in [24] %} - {{key.field}}SetVal(tableEntry->{{ key.name | lower }}, mf_exact, {{key.bitwidth}}); - {% else %} - {{key.field}}SetVal(static_cast(tableEntry->{{ key.name | lower }}), mf_exact, {{key.bitwidth}}); + {% if keyfield in ['ipaddr','mac'] or bitwidth in [24] %} + {{key.field}}SetVal(tableEntry->{{ key.name | lower }}, mf_exact, {{key.bitwidth}}); + {% else %} + {{key.field}}SetVal(static_cast(tableEntry->{{ key.name | lower }}), mf_exact, {{key.bitwidth}}); {% endif %} {% elif key.match_type == 'lpm' %} {% if key.field == 'ipPrefix' %} @@ -508,36 +506,6 @@ ErrRet: return SAI_STATUS_FAILURE; } -static sai_status_t dash_sai_create_{{ table.name | replace("entry", "entries") }}( - _In_ uint32_t object_count, - _In_ const sai_{{ table.name }}_t *{{ table.name }}, - _In_ const uint32_t *attr_count, - _In_ const sai_attribute_t **attr_list, - _In_ sai_bulk_op_error_mode_t mode, - _Out_ sai_status_t *object_statuses) -{ - DASH_LOG_ENTER(); - - sai_status_t agg_status = SAI_STATUS_SUCCESS; - - for (uint32_t i = 0; i < object_count; i++) - { - object_statuses[i] = dash_sai_create_{{ table.name }}(&{{ table.name }}[i], attr_count[i], attr_list[i]); - - if (object_statuses[i] != SAI_STATUS_SUCCESS) - { - agg_status = SAI_STATUS_FAILURE; - } - - if (agg_status == SAI_STATUS_FAILURE && mode == SAI_BULK_OP_ERROR_MODE_STOP_ON_ERROR) - { - return agg_status; - } - } - - return agg_status; -} - static sai_status_t dash_sai_remove_{{ table.name }}( _In_ const sai_{{ table.name }}_t *{{ table.name }}) { @@ -558,11 +526,10 @@ static sai_status_t dash_sai_remove_{{ table.name }}( {% set keyfield = key.field %} {% set bitwidth = key.bitwidth %} {% if keyfield in ['ipaddr','mac'] or bitwidth in [24] %} - {{key.field}}SetVal(tableEntry->{{ key.name | lower }}, mf_exact, {{key.bitwidth}}); + {{key.field}}SetVal(tableEntry->{{ key.name | lower }}, mf_exact, {{key.bitwidth}}); {% else %} - {{key.field}}SetVal(static_cast(tableEntry->{{ key.name | lower }}), mf_exact, {{key.bitwidth}}); - {% endif %} - //{{key.field}}SetVal(tableEntry->{{ key.name | lower }}, mf_exact, {{key.bitwidth}}); + {{key.field}}SetVal(static_cast(tableEntry->{{ key.name | lower }}), mf_exact, {{key.bitwidth}}); + {% endif %} {% elif key.match_type == 'lpm' %} {% if key.field == 'ipPrefix' %} if (getPrefixLength(tableEntry->{{ key.name | lower }}) == 0) @@ -624,34 +591,6 @@ ErrRet: return SAI_STATUS_FAILURE; } -static sai_status_t dash_sai_remove_{{ table.name | replace("entry", "entries") }}( - _In_ uint32_t object_count, - _In_ const sai_{{ table.name }}_t *{{ table.name }}, - _In_ sai_bulk_op_error_mode_t mode, - _Out_ sai_status_t *object_statuses) -{ - DASH_LOG_ENTER(); - - sai_status_t agg_status = SAI_STATUS_SUCCESS; - - for (uint32_t i = 0; i < object_count; i++) - { - object_statuses[i] = dash_sai_remove_{{ table.name }}(&{{ table.name }}[i]); - - if (object_statuses[i] != SAI_STATUS_SUCCESS) - { - agg_status = SAI_STATUS_FAILURE; - } - - if (agg_status == SAI_STATUS_FAILURE && mode == SAI_BULK_OP_ERROR_MODE_STOP_ON_ERROR) - { - return agg_status; - } - } - - return agg_status; -} - static sai_status_t dash_sai_set_{{ table.name }}_attribute( _In_ const sai_{{ table.name }}_t *{{ table.name }}, _In_ const sai_attribute_t *attr) @@ -704,7 +643,65 @@ static sai_status_t dash_sai_clear_{{ table.name }}_stats( assert(0 && "sai_clear_{{ table.name }}_stats NYI"); return SAI_STATUS_FAILURE; } + {% endif %} +static sai_status_t dash_sai_create_{{ table.name | replace("entry", "entries") }}( + _In_ uint32_t object_count, + _In_ const sai_{{ table.name }}_t *{{ table.name }}, + _In_ const uint32_t *attr_count, + _In_ const sai_attribute_t **attr_list, + _In_ sai_bulk_op_error_mode_t mode, + _Out_ sai_status_t *object_statuses) +{ + DASH_LOG_ENTER(); + + sai_status_t agg_status = SAI_STATUS_SUCCESS; + + for (uint32_t i = 0; i < object_count; i++) + { + object_statuses[i] = dash_sai_create_{{ table.name }}(&{{ table.name }}[i], attr_count[i], attr_list[i]); + + if (object_statuses[i] != SAI_STATUS_SUCCESS) + { + agg_status = SAI_STATUS_FAILURE; + } + + if (agg_status == SAI_STATUS_FAILURE && mode == SAI_BULK_OP_ERROR_MODE_STOP_ON_ERROR) + { + return agg_status; + } + } + + return agg_status; +} + +static sai_status_t dash_sai_remove_{{ table.name | replace("entry", "entries") }}( + _In_ uint32_t object_count, + _In_ const sai_{{ table.name }}_t *{{ table.name }}, + _In_ sai_bulk_op_error_mode_t mode, + _Out_ sai_status_t *object_statuses) +{ + DASH_LOG_ENTER(); + + sai_status_t agg_status = SAI_STATUS_SUCCESS; + + for (uint32_t i = 0; i < object_count; i++) + { + object_statuses[i] = dash_sai_remove_{{ table.name }}(&{{ table.name }}[i]); + + if (object_statuses[i] != SAI_STATUS_SUCCESS) + { + agg_status = SAI_STATUS_FAILURE; + } + + if (agg_status == SAI_STATUS_FAILURE && mode == SAI_BULK_OP_ERROR_MODE_STOP_ON_ERROR) + { + return agg_status; + } + } + + return agg_status; +} {% if table.name == 'route_entry' %} static sai_status_t dash_sai_set_{{ table.name | replace("entry", "entries") }}_attribute( @@ -731,7 +728,6 @@ static sai_status_t dash_sai_get_{{ table.name | replace("entry", "entries") }}_ assert(0 && "sai_get_{{ table.name | replace("entry", "entries") }}_attribute NYI"); return SAI_STATUS_FAILURE; } - {% endif %} {% endif %} {% endfor %} From 3013f3371df26db5ab563d3b4dc9ccc4ea5d21f5 Mon Sep 17 00:00:00 2001 From: Junhua Zhai Date: Fri, 6 Dec 2024 10:14:55 +0800 Subject: [PATCH 7/8] [sai-gen] Update SAI specs to have more p4 meta info (#647) This PR updates p4 meta of sai api to include table keys and action params in detail. It will be the single truth to generate sai api implementation later. --- dash-pipeline/SAI/specs/dash_acl.yaml | 370 +++++++++++++-- dash-pipeline/SAI/specs/dash_appliance.yaml | 22 +- .../SAI/specs/dash_direction_lookup.yaml | 19 +- dash-pipeline/SAI/specs/dash_eni.yaml | 287 +++++++++++- dash-pipeline/SAI/specs/dash_flow.yaml | 434 ++++++++++++++++-- dash-pipeline/SAI/specs/dash_ha.yaml | 152 +++++- .../SAI/specs/dash_inbound_routing.yaml | 69 ++- dash-pipeline/SAI/specs/dash_meter.yaml | 72 ++- .../SAI/specs/dash_outbound_ca_to_pa.yaml | 148 +++++- .../SAI/specs/dash_outbound_routing.yaml | 239 ++++++++-- .../SAI/specs/dash_pa_validation.yaml | 20 +- dash-pipeline/SAI/specs/dash_tunnel.yaml | 96 +++- dash-pipeline/SAI/specs/dash_vip.yaml | 12 +- dash-pipeline/SAI/specs/dash_vnet.yaml | 22 +- dash-pipeline/SAI/specs/route.yaml | 26 +- .../SAI/utils/dash_p4/dash_p4_table.py | 42 +- dash-pipeline/SAI/utils/sai_spec/__init__.py | 3 +- .../SAI/utils/sai_spec/sai_api_p4_meta.py | 28 +- 18 files changed, 1873 insertions(+), 188 deletions(-) diff --git a/dash-pipeline/SAI/specs/dash_acl.yaml b/dash-pipeline/SAI/specs/dash_acl.yaml index 879eca6f7..fabda4103 100644 --- a/dash-pipeline/SAI/specs/dash_acl.yaml +++ b/dash-pipeline/SAI/specs/dash_acl.yaml @@ -28,11 +28,27 @@ sai_apis: tables: - !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaTable id: 37949057 + stage: null + keys: + - !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaKey + name: dash_acl_group_id + id: 1 + match_type: exact + field: u16 + bitwidth: 16 + ip_is_v6_field_id: 0 + is_object_key: true actions: - default: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaAction - name: default + SAI_DASH_ACL_GROUP_ACTION_SET_ACL_GROUP_ATTRS: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaAction + name: SAI_DASH_ACL_GROUP_ACTION_SET_ACL_GROUP_ATTRS id: 21989040 - attr_param_id: {} + attr_params: + SAI_DASH_ACL_GROUP_ATTR_IP_ADDR_FAMILY: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 1 + field: u32 + bitwidth: 32 + ip_is_v6_field_id: 0 + skipattr: null - !!python/object:utils.sai_spec.sai_api.SaiApi name: dash_acl_rule description: DASH ACL rule @@ -195,115 +211,415 @@ sai_apis: tables: - !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaTable id: 43936368 + stage: acl.stage1 + keys: + - !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaKey + name: dash_acl_group_id + id: 1 + match_type: exact + field: u16 + bitwidth: 16 + ip_is_v6_field_id: 0 + is_object_key: false + - !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaKey + name: dip + id: 2 + match_type: list + field: ipprefixlist + bitwidth: 128 + ip_is_v6_field_id: 0 + is_object_key: false + - !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaKey + name: sip + id: 3 + match_type: list + field: ipprefixlist + bitwidth: 128 + ip_is_v6_field_id: 0 + is_object_key: false + - !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaKey + name: protocol + id: 4 + match_type: list + field: u8list + bitwidth: 8 + ip_is_v6_field_id: 0 + is_object_key: false + - !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaKey + name: src_port + id: 5 + match_type: range_list + field: u16rangelist + bitwidth: 16 + ip_is_v6_field_id: 0 + is_object_key: false + - !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaKey + name: dst_port + id: 6 + match_type: range_list + field: u16rangelist + bitwidth: 16 + ip_is_v6_field_id: 0 + is_object_key: false actions: SAI_DASH_ACL_RULE_ACTION_PERMIT: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaAction name: SAI_DASH_ACL_RULE_ACTION_PERMIT id: 24892843 - attr_param_id: {} + attr_params: {} SAI_DASH_ACL_RULE_ACTION_PERMIT_AND_CONTINUE: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaAction name: SAI_DASH_ACL_RULE_ACTION_PERMIT_AND_CONTINUE id: 26577723 - attr_param_id: {} + attr_params: {} SAI_DASH_ACL_RULE_ACTION_DENY: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaAction name: SAI_DASH_ACL_RULE_ACTION_DENY id: 31332881 - attr_param_id: {} + attr_params: {} SAI_DASH_ACL_RULE_ACTION_DENY_AND_CONTINUE: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaAction name: SAI_DASH_ACL_RULE_ACTION_DENY_AND_CONTINUE id: 24146215 - attr_param_id: {} + attr_params: {} - !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaTable id: 48549629 + stage: acl.stage2 + keys: + - !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaKey + name: dash_acl_group_id + id: 1 + match_type: exact + field: u16 + bitwidth: 16 + ip_is_v6_field_id: 0 + is_object_key: false + - !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaKey + name: dip + id: 2 + match_type: list + field: ipprefixlist + bitwidth: 128 + ip_is_v6_field_id: 0 + is_object_key: false + - !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaKey + name: sip + id: 3 + match_type: list + field: ipprefixlist + bitwidth: 128 + ip_is_v6_field_id: 0 + is_object_key: false + - !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaKey + name: protocol + id: 4 + match_type: list + field: u8list + bitwidth: 8 + ip_is_v6_field_id: 0 + is_object_key: false + - !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaKey + name: src_port + id: 5 + match_type: range_list + field: u16rangelist + bitwidth: 16 + ip_is_v6_field_id: 0 + is_object_key: false + - !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaKey + name: dst_port + id: 6 + match_type: range_list + field: u16rangelist + bitwidth: 16 + ip_is_v6_field_id: 0 + is_object_key: false actions: SAI_DASH_ACL_RULE_ACTION_PERMIT: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaAction name: SAI_DASH_ACL_RULE_ACTION_PERMIT id: 24892843 - attr_param_id: {} + attr_params: {} SAI_DASH_ACL_RULE_ACTION_PERMIT_AND_CONTINUE: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaAction name: SAI_DASH_ACL_RULE_ACTION_PERMIT_AND_CONTINUE id: 26577723 - attr_param_id: {} + attr_params: {} SAI_DASH_ACL_RULE_ACTION_DENY: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaAction name: SAI_DASH_ACL_RULE_ACTION_DENY id: 31332881 - attr_param_id: {} + attr_params: {} SAI_DASH_ACL_RULE_ACTION_DENY_AND_CONTINUE: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaAction name: SAI_DASH_ACL_RULE_ACTION_DENY_AND_CONTINUE id: 24146215 - attr_param_id: {} + attr_params: {} - !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaTable id: 40869404 + stage: acl.stage3 + keys: + - !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaKey + name: dash_acl_group_id + id: 1 + match_type: exact + field: u16 + bitwidth: 16 + ip_is_v6_field_id: 0 + is_object_key: false + - !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaKey + name: dip + id: 2 + match_type: list + field: ipprefixlist + bitwidth: 128 + ip_is_v6_field_id: 0 + is_object_key: false + - !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaKey + name: sip + id: 3 + match_type: list + field: ipprefixlist + bitwidth: 128 + ip_is_v6_field_id: 0 + is_object_key: false + - !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaKey + name: protocol + id: 4 + match_type: list + field: u8list + bitwidth: 8 + ip_is_v6_field_id: 0 + is_object_key: false + - !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaKey + name: src_port + id: 5 + match_type: range_list + field: u16rangelist + bitwidth: 16 + ip_is_v6_field_id: 0 + is_object_key: false + - !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaKey + name: dst_port + id: 6 + match_type: range_list + field: u16rangelist + bitwidth: 16 + ip_is_v6_field_id: 0 + is_object_key: false actions: SAI_DASH_ACL_RULE_ACTION_PERMIT: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaAction name: SAI_DASH_ACL_RULE_ACTION_PERMIT id: 24892843 - attr_param_id: {} + attr_params: {} SAI_DASH_ACL_RULE_ACTION_PERMIT_AND_CONTINUE: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaAction name: SAI_DASH_ACL_RULE_ACTION_PERMIT_AND_CONTINUE id: 26577723 - attr_param_id: {} + attr_params: {} SAI_DASH_ACL_RULE_ACTION_DENY: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaAction name: SAI_DASH_ACL_RULE_ACTION_DENY id: 31332881 - attr_param_id: {} + attr_params: {} SAI_DASH_ACL_RULE_ACTION_DENY_AND_CONTINUE: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaAction name: SAI_DASH_ACL_RULE_ACTION_DENY_AND_CONTINUE id: 24146215 - attr_param_id: {} + attr_params: {} - !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaTable id: 49672642 + stage: acl.stage1 + keys: + - !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaKey + name: dash_acl_group_id + id: 1 + match_type: exact + field: u16 + bitwidth: 16 + ip_is_v6_field_id: 0 + is_object_key: false + - !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaKey + name: dip + id: 2 + match_type: list + field: ipprefixlist + bitwidth: 128 + ip_is_v6_field_id: 0 + is_object_key: false + - !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaKey + name: sip + id: 3 + match_type: list + field: ipprefixlist + bitwidth: 128 + ip_is_v6_field_id: 0 + is_object_key: false + - !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaKey + name: protocol + id: 4 + match_type: list + field: u8list + bitwidth: 8 + ip_is_v6_field_id: 0 + is_object_key: false + - !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaKey + name: src_port + id: 5 + match_type: range_list + field: u16rangelist + bitwidth: 16 + ip_is_v6_field_id: 0 + is_object_key: false + - !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaKey + name: dst_port + id: 6 + match_type: range_list + field: u16rangelist + bitwidth: 16 + ip_is_v6_field_id: 0 + is_object_key: false actions: SAI_DASH_ACL_RULE_ACTION_PERMIT: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaAction name: SAI_DASH_ACL_RULE_ACTION_PERMIT id: 22622424 - attr_param_id: {} + attr_params: {} SAI_DASH_ACL_RULE_ACTION_PERMIT_AND_CONTINUE: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaAction name: SAI_DASH_ACL_RULE_ACTION_PERMIT_AND_CONTINUE id: 27458076 - attr_param_id: {} + attr_params: {} SAI_DASH_ACL_RULE_ACTION_DENY: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaAction name: SAI_DASH_ACL_RULE_ACTION_DENY id: 27228779 - attr_param_id: {} + attr_params: {} SAI_DASH_ACL_RULE_ACTION_DENY_AND_CONTINUE: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaAction name: SAI_DASH_ACL_RULE_ACTION_DENY_AND_CONTINUE id: 29275145 - attr_param_id: {} + attr_params: {} - !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaTable id: 37932124 + stage: acl.stage2 + keys: + - !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaKey + name: dash_acl_group_id + id: 1 + match_type: exact + field: u16 + bitwidth: 16 + ip_is_v6_field_id: 0 + is_object_key: false + - !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaKey + name: dip + id: 2 + match_type: list + field: ipprefixlist + bitwidth: 128 + ip_is_v6_field_id: 0 + is_object_key: false + - !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaKey + name: sip + id: 3 + match_type: list + field: ipprefixlist + bitwidth: 128 + ip_is_v6_field_id: 0 + is_object_key: false + - !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaKey + name: protocol + id: 4 + match_type: list + field: u8list + bitwidth: 8 + ip_is_v6_field_id: 0 + is_object_key: false + - !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaKey + name: src_port + id: 5 + match_type: range_list + field: u16rangelist + bitwidth: 16 + ip_is_v6_field_id: 0 + is_object_key: false + - !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaKey + name: dst_port + id: 6 + match_type: range_list + field: u16rangelist + bitwidth: 16 + ip_is_v6_field_id: 0 + is_object_key: false actions: SAI_DASH_ACL_RULE_ACTION_PERMIT: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaAction name: SAI_DASH_ACL_RULE_ACTION_PERMIT id: 22622424 - attr_param_id: {} + attr_params: {} SAI_DASH_ACL_RULE_ACTION_PERMIT_AND_CONTINUE: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaAction name: SAI_DASH_ACL_RULE_ACTION_PERMIT_AND_CONTINUE id: 27458076 - attr_param_id: {} + attr_params: {} SAI_DASH_ACL_RULE_ACTION_DENY: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaAction name: SAI_DASH_ACL_RULE_ACTION_DENY id: 27228779 - attr_param_id: {} + attr_params: {} SAI_DASH_ACL_RULE_ACTION_DENY_AND_CONTINUE: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaAction name: SAI_DASH_ACL_RULE_ACTION_DENY_AND_CONTINUE id: 29275145 - attr_param_id: {} + attr_params: {} - !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaTable id: 46113118 + stage: acl.stage3 + keys: + - !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaKey + name: dash_acl_group_id + id: 1 + match_type: exact + field: u16 + bitwidth: 16 + ip_is_v6_field_id: 0 + is_object_key: false + - !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaKey + name: dip + id: 2 + match_type: list + field: ipprefixlist + bitwidth: 128 + ip_is_v6_field_id: 0 + is_object_key: false + - !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaKey + name: sip + id: 3 + match_type: list + field: ipprefixlist + bitwidth: 128 + ip_is_v6_field_id: 0 + is_object_key: false + - !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaKey + name: protocol + id: 4 + match_type: list + field: u8list + bitwidth: 8 + ip_is_v6_field_id: 0 + is_object_key: false + - !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaKey + name: src_port + id: 5 + match_type: range_list + field: u16rangelist + bitwidth: 16 + ip_is_v6_field_id: 0 + is_object_key: false + - !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaKey + name: dst_port + id: 6 + match_type: range_list + field: u16rangelist + bitwidth: 16 + ip_is_v6_field_id: 0 + is_object_key: false actions: SAI_DASH_ACL_RULE_ACTION_PERMIT: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaAction name: SAI_DASH_ACL_RULE_ACTION_PERMIT id: 22622424 - attr_param_id: {} + attr_params: {} SAI_DASH_ACL_RULE_ACTION_PERMIT_AND_CONTINUE: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaAction name: SAI_DASH_ACL_RULE_ACTION_PERMIT_AND_CONTINUE id: 27458076 - attr_param_id: {} + attr_params: {} SAI_DASH_ACL_RULE_ACTION_DENY: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaAction name: SAI_DASH_ACL_RULE_ACTION_DENY id: 27228779 - attr_param_id: {} + attr_params: {} SAI_DASH_ACL_RULE_ACTION_DENY_AND_CONTINUE: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaAction name: SAI_DASH_ACL_RULE_ACTION_DENY_AND_CONTINUE id: 29275145 - attr_param_id: {} + attr_params: {} diff --git a/dash-pipeline/SAI/specs/dash_appliance.yaml b/dash-pipeline/SAI/specs/dash_appliance.yaml index f8bbf8b1f..7c3b1820a 100644 --- a/dash-pipeline/SAI/specs/dash_appliance.yaml +++ b/dash-pipeline/SAI/specs/dash_appliance.yaml @@ -28,8 +28,24 @@ sai_apis: tables: - !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaTable id: 45177948 + stage: null + keys: + - !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaKey + name: appliance_id + id: 1 + match_type: exact + field: u16 + bitwidth: 8 + ip_is_v6_field_id: 0 + is_object_key: true actions: - default: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaAction - name: default + SAI_DASH_APPLIANCE_ACTION_SET_APPLIANCE: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaAction + name: SAI_DASH_APPLIANCE_ACTION_SET_APPLIANCE id: 17143042 - attr_param_id: {} + attr_params: + SAI_DASH_APPLIANCE_ATTR_LOCAL_REGION_ID: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 1 + field: u8 + bitwidth: 8 + ip_is_v6_field_id: 0 + skipattr: null diff --git a/dash-pipeline/SAI/specs/dash_direction_lookup.yaml b/dash-pipeline/SAI/specs/dash_direction_lookup.yaml index 14cd33034..7ae162c22 100644 --- a/dash-pipeline/SAI/specs/dash_direction_lookup.yaml +++ b/dash-pipeline/SAI/specs/dash_direction_lookup.yaml @@ -65,9 +65,24 @@ sai_apis: tables: - !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaTable id: 49875338 + stage: null + keys: + - !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaKey + name: VNI + id: 1 + match_type: exact + field: u32 + bitwidth: 24 + ip_is_v6_field_id: 0 + is_object_key: false actions: SAI_DIRECTION_LOOKUP_ENTRY_ACTION_SET_OUTBOUND_DIRECTION: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaAction name: SAI_DIRECTION_LOOKUP_ENTRY_ACTION_SET_OUTBOUND_DIRECTION id: 32588257 - attr_param_id: - SAI_DIRECTION_LOOKUP_ENTRY_ATTR_DASH_ENI_MAC_OVERRIDE_TYPE: 1 + attr_params: + SAI_DIRECTION_LOOKUP_ENTRY_ATTR_DASH_ENI_MAC_OVERRIDE_TYPE: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 1 + field: s32 + bitwidth: 8 + ip_is_v6_field_id: 0 + skipattr: null diff --git a/dash-pipeline/SAI/specs/dash_eni.yaml b/dash-pipeline/SAI/specs/dash_eni.yaml index 0651f9011..d7bafd7fb 100644 --- a/dash-pipeline/SAI/specs/dash_eni.yaml +++ b/dash-pipeline/SAI/specs/dash_eni.yaml @@ -65,12 +65,27 @@ sai_apis: tables: - !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaTable id: 39883185 + stage: null + keys: + - !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaKey + name: address + id: 1 + match_type: exact + field: mac + bitwidth: 48 + ip_is_v6_field_id: 0 + is_object_key: false actions: SAI_ENI_ETHER_ADDRESS_MAP_ENTRY_ACTION_SET_ENI: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaAction name: SAI_ENI_ETHER_ADDRESS_MAP_ENTRY_ACTION_SET_ENI id: 19019152 - attr_param_id: - SAI_ENI_ETHER_ADDRESS_MAP_ENTRY_ATTR_ENI_ID: 1 + attr_params: + SAI_ENI_ETHER_ADDRESS_MAP_ENTRY_ATTR_ENI_ID: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 1 + field: u16 + bitwidth: 16 + ip_is_v6_field_id: 0 + skipattr: null - !!python/object:utils.sai_spec.sai_api.SaiApi name: eni description: ENI @@ -1643,8 +1658,270 @@ sai_apis: tables: - !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaTable id: 38483381 + stage: null + keys: + - !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaKey + name: eni_id + id: 1 + match_type: exact + field: u16 + bitwidth: 16 + ip_is_v6_field_id: 0 + is_object_key: true actions: - default: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaAction - name: default + SAI_ENI_ACTION_SET_ENI_ATTRS: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaAction + name: SAI_ENI_ACTION_SET_ENI_ATTRS id: 30359009 - attr_param_id: {} + attr_params: + SAI_ENI_ATTR_CPS: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 1 + field: u32 + bitwidth: 32 + ip_is_v6_field_id: 0 + skipattr: null + SAI_ENI_ATTR_PPS: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 2 + field: u32 + bitwidth: 32 + ip_is_v6_field_id: 0 + skipattr: null + SAI_ENI_ATTR_FLOWS: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 3 + field: u32 + bitwidth: 32 + ip_is_v6_field_id: 0 + skipattr: null + SAI_ENI_ATTR_ADMIN_STATE: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 4 + field: booldata + bitwidth: 1 + ip_is_v6_field_id: 0 + skipattr: null + SAI_ENI_ATTR_HA_SCOPE_ID: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 5 + field: u16 + bitwidth: 16 + ip_is_v6_field_id: 0 + skipattr: null + SAI_ENI_ATTR_VM_UNDERLAY_DIP: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 6 + field: ipaddr + bitwidth: 32 + ip_is_v6_field_id: 0 + skipattr: null + SAI_ENI_ATTR_VM_VNI: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 7 + field: u32 + bitwidth: 24 + ip_is_v6_field_id: 0 + skipattr: null + SAI_ENI_ATTR_VNET_ID: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 8 + field: u16 + bitwidth: 16 + ip_is_v6_field_id: 0 + skipattr: null + SAI_ENI_ATTR_PL_SIP: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 9 + field: ipaddr + bitwidth: 128 + ip_is_v6_field_id: 0 + skipattr: null + SAI_ENI_ATTR_PL_SIP_MASK: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 10 + field: ipaddr + bitwidth: 128 + ip_is_v6_field_id: 0 + skipattr: null + SAI_ENI_ATTR_PL_UNDERLAY_SIP: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 11 + field: ipaddr + bitwidth: 32 + ip_is_v6_field_id: 0 + skipattr: null + SAI_ENI_ATTR_V4_METER_POLICY_ID: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 12 + field: u16 + bitwidth: 16 + ip_is_v6_field_id: 0 + skipattr: null + SAI_ENI_ATTR_V6_METER_POLICY_ID: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 13 + field: u16 + bitwidth: 16 + ip_is_v6_field_id: 0 + skipattr: null + SAI_ENI_ATTR_DASH_TUNNEL_DSCP_MODE: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 14 + field: s32 + bitwidth: 16 + ip_is_v6_field_id: 0 + skipattr: null + SAI_ENI_ATTR_DSCP: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 15 + field: u8 + bitwidth: 6 + ip_is_v6_field_id: 0 + skipattr: null + SAI_ENI_ATTR_INBOUND_V4_STAGE1_DASH_ACL_GROUP_ID: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 16 + field: u16 + bitwidth: 16 + ip_is_v6_field_id: 0 + skipattr: null + SAI_ENI_ATTR_INBOUND_V4_STAGE2_DASH_ACL_GROUP_ID: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 17 + field: u16 + bitwidth: 16 + ip_is_v6_field_id: 0 + skipattr: null + SAI_ENI_ATTR_INBOUND_V4_STAGE3_DASH_ACL_GROUP_ID: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 18 + field: u16 + bitwidth: 16 + ip_is_v6_field_id: 0 + skipattr: null + SAI_ENI_ATTR_INBOUND_V4_STAGE4_DASH_ACL_GROUP_ID: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 19 + field: u16 + bitwidth: 16 + ip_is_v6_field_id: 0 + skipattr: null + SAI_ENI_ATTR_INBOUND_V4_STAGE5_DASH_ACL_GROUP_ID: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 20 + field: u16 + bitwidth: 16 + ip_is_v6_field_id: 0 + skipattr: null + SAI_ENI_ATTR_INBOUND_V6_STAGE1_DASH_ACL_GROUP_ID: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 21 + field: u16 + bitwidth: 16 + ip_is_v6_field_id: 0 + skipattr: null + SAI_ENI_ATTR_INBOUND_V6_STAGE2_DASH_ACL_GROUP_ID: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 22 + field: u16 + bitwidth: 16 + ip_is_v6_field_id: 0 + skipattr: null + SAI_ENI_ATTR_INBOUND_V6_STAGE3_DASH_ACL_GROUP_ID: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 23 + field: u16 + bitwidth: 16 + ip_is_v6_field_id: 0 + skipattr: null + SAI_ENI_ATTR_INBOUND_V6_STAGE4_DASH_ACL_GROUP_ID: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 24 + field: u16 + bitwidth: 16 + ip_is_v6_field_id: 0 + skipattr: null + SAI_ENI_ATTR_INBOUND_V6_STAGE5_DASH_ACL_GROUP_ID: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 25 + field: u16 + bitwidth: 16 + ip_is_v6_field_id: 0 + skipattr: null + SAI_ENI_ATTR_OUTBOUND_V4_STAGE1_DASH_ACL_GROUP_ID: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 26 + field: u16 + bitwidth: 16 + ip_is_v6_field_id: 0 + skipattr: null + SAI_ENI_ATTR_OUTBOUND_V4_STAGE2_DASH_ACL_GROUP_ID: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 27 + field: u16 + bitwidth: 16 + ip_is_v6_field_id: 0 + skipattr: null + SAI_ENI_ATTR_OUTBOUND_V4_STAGE3_DASH_ACL_GROUP_ID: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 28 + field: u16 + bitwidth: 16 + ip_is_v6_field_id: 0 + skipattr: null + SAI_ENI_ATTR_OUTBOUND_V4_STAGE4_DASH_ACL_GROUP_ID: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 29 + field: u16 + bitwidth: 16 + ip_is_v6_field_id: 0 + skipattr: null + SAI_ENI_ATTR_OUTBOUND_V4_STAGE5_DASH_ACL_GROUP_ID: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 30 + field: u16 + bitwidth: 16 + ip_is_v6_field_id: 0 + skipattr: null + SAI_ENI_ATTR_OUTBOUND_V6_STAGE1_DASH_ACL_GROUP_ID: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 31 + field: u16 + bitwidth: 16 + ip_is_v6_field_id: 0 + skipattr: null + SAI_ENI_ATTR_OUTBOUND_V6_STAGE2_DASH_ACL_GROUP_ID: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 32 + field: u16 + bitwidth: 16 + ip_is_v6_field_id: 0 + skipattr: null + SAI_ENI_ATTR_OUTBOUND_V6_STAGE3_DASH_ACL_GROUP_ID: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 33 + field: u16 + bitwidth: 16 + ip_is_v6_field_id: 0 + skipattr: null + SAI_ENI_ATTR_OUTBOUND_V6_STAGE4_DASH_ACL_GROUP_ID: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 34 + field: u16 + bitwidth: 16 + ip_is_v6_field_id: 0 + skipattr: null + SAI_ENI_ATTR_OUTBOUND_V6_STAGE5_DASH_ACL_GROUP_ID: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 35 + field: u16 + bitwidth: 16 + ip_is_v6_field_id: 0 + skipattr: null + SAI_ENI_ATTR_DISABLE_FAST_PATH_ICMP_FLOW_REDIRECTION: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 36 + field: booldata + bitwidth: 1 + ip_is_v6_field_id: 0 + skipattr: null + SAI_ENI_ATTR_FULL_FLOW_RESIMULATION_REQUESTED: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 37 + field: booldata + bitwidth: 1 + ip_is_v6_field_id: 0 + skipattr: null + SAI_ENI_ATTR_MAX_RESIMULATED_FLOW_PER_SECOND: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 38 + field: u64 + bitwidth: 64 + ip_is_v6_field_id: 0 + skipattr: null + SAI_ENI_ATTR_OUTBOUND_ROUTING_GROUP_ID: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 39 + field: u16 + bitwidth: 16 + ip_is_v6_field_id: 0 + skipattr: null + SAI_ENI_ATTR_ENABLE_REVERSE_TUNNEL_LEARNING: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 40 + field: booldata + bitwidth: 1 + ip_is_v6_field_id: 0 + skipattr: null + SAI_ENI_ATTR_REVERSE_TUNNEL_SIP: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 41 + field: ipaddr + bitwidth: 32 + ip_is_v6_field_id: 0 + skipattr: null + SAI_ENI_ATTR_IS_HA_FLOW_OWNER: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 42 + field: booldata + bitwidth: 1 + ip_is_v6_field_id: 0 + skipattr: null diff --git a/dash-pipeline/SAI/specs/dash_flow.yaml b/dash-pipeline/SAI/specs/dash_flow.yaml index b7ea10e0a..e8641d62d 100644 --- a/dash-pipeline/SAI/specs/dash_flow.yaml +++ b/dash-pipeline/SAI/specs/dash_flow.yaml @@ -54,11 +54,39 @@ sai_apis: tables: - !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaTable id: 38557285 + stage: null + keys: + - !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaKey + name: id + id: 1 + match_type: exact + field: u16 + bitwidth: 16 + ip_is_v6_field_id: 0 + is_object_key: true actions: - default: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaAction - name: default + SAI_FLOW_TABLE_ACTION_SET_FLOW_TABLE_ATTR: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaAction + name: SAI_FLOW_TABLE_ACTION_SET_FLOW_TABLE_ATTR id: 33071001 - attr_param_id: {} + attr_params: + SAI_FLOW_TABLE_ATTR_MAX_FLOW_COUNT: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 1 + field: u32 + bitwidth: 32 + ip_is_v6_field_id: 0 + skipattr: null + SAI_FLOW_TABLE_ATTR_DASH_FLOW_ENABLED_KEY: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 2 + field: s32 + bitwidth: 16 + ip_is_v6_field_id: 0 + skipattr: null + SAI_FLOW_TABLE_ATTR_FLOW_TTL_IN_MILLISECONDS: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 3 + field: u32 + bitwidth: 32 + ip_is_v6_field_id: 0 + skipattr: null - !!python/object:utils.sai_spec.sai_api.SaiApi name: flow_entry description: flow entry @@ -573,43 +601,261 @@ sai_apis: tables: - !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaTable id: 49035675 + stage: null + keys: + - !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaKey + name: eni_mac + id: 1 + match_type: exact + field: mac + bitwidth: 48 + ip_is_v6_field_id: 0 + is_object_key: false + - !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaKey + name: vnet_id + id: 2 + match_type: exact + field: u16 + bitwidth: 16 + ip_is_v6_field_id: 0 + is_object_key: false + - !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaKey + name: src_ip + id: 3 + match_type: exact + field: ipaddr + bitwidth: 128 + ip_is_v6_field_id: 8 + is_object_key: false + - !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaKey + name: dst_ip + id: 4 + match_type: exact + field: ipaddr + bitwidth: 128 + ip_is_v6_field_id: 0 + is_object_key: false + - !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaKey + name: src_port + id: 5 + match_type: exact + field: u16 + bitwidth: 16 + ip_is_v6_field_id: 0 + is_object_key: false + - !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaKey + name: dst_port + id: 6 + match_type: exact + field: u16 + bitwidth: 16 + ip_is_v6_field_id: 0 + is_object_key: false + - !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaKey + name: ip_proto + id: 7 + match_type: exact + field: u8 + bitwidth: 8 + ip_is_v6_field_id: 0 + is_object_key: false actions: SAI_FLOW_ENTRY_ACTION_SET_FLOW_ENTRY_ATTR: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaAction name: SAI_FLOW_ENTRY_ACTION_SET_FLOW_ENTRY_ATTR id: 26241621 - attr_param_id: - SAI_FLOW_ENTRY_ATTR_VERSION: 1 - SAI_FLOW_ENTRY_ATTR_DASH_DIRECTION: 2 - SAI_FLOW_ENTRY_ATTR_DASH_FLOW_ACTION: 3 - SAI_FLOW_ENTRY_ATTR_METER_CLASS: 4 - SAI_FLOW_ENTRY_ATTR_IS_UNIDIRECTIONAL_FLOW: 5 - SAI_FLOW_ENTRY_ATTR_DASH_FLOW_SYNC_STATE: 6 - SAI_FLOW_ENTRY_ATTR_REVERSE_FLOW_ENI_MAC: 7 - SAI_FLOW_ENTRY_ATTR_REVERSE_FLOW_VNET_ID: 8 - SAI_FLOW_ENTRY_ATTR_REVERSE_FLOW_IP_PROTO: 9 - SAI_FLOW_ENTRY_ATTR_REVERSE_FLOW_SRC_IP: 10 - SAI_FLOW_ENTRY_ATTR_REVERSE_FLOW_DST_IP: 11 - SAI_FLOW_ENTRY_ATTR_REVERSE_FLOW_SRC_PORT: 12 - SAI_FLOW_ENTRY_ATTR_REVERSE_FLOW_DST_PORT: 13 - SAI_FLOW_ENTRY_ATTR_UNDERLAY0_VNET_ID: 15 - SAI_FLOW_ENTRY_ATTR_UNDERLAY0_SIP: 16 - SAI_FLOW_ENTRY_ATTR_UNDERLAY0_DIP: 17 - SAI_FLOW_ENTRY_ATTR_UNDERLAY0_SMAC: 18 - SAI_FLOW_ENTRY_ATTR_UNDERLAY0_DMAC: 19 - SAI_FLOW_ENTRY_ATTR_UNDERLAY0_DASH_ENCAPSULATION: 20 - SAI_FLOW_ENTRY_ATTR_UNDERLAY1_VNET_ID: 21 - SAI_FLOW_ENTRY_ATTR_UNDERLAY1_SIP: 22 - SAI_FLOW_ENTRY_ATTR_UNDERLAY1_DIP: 23 - SAI_FLOW_ENTRY_ATTR_UNDERLAY1_SMAC: 24 - SAI_FLOW_ENTRY_ATTR_UNDERLAY1_DMAC: 25 - SAI_FLOW_ENTRY_ATTR_UNDERLAY1_DASH_ENCAPSULATION: 26 - SAI_FLOW_ENTRY_ATTR_DST_MAC: 27 - SAI_FLOW_ENTRY_ATTR_SIP: 28 - SAI_FLOW_ENTRY_ATTR_DIP: 29 - SAI_FLOW_ENTRY_ATTR_SIP_MASK: 30 - SAI_FLOW_ENTRY_ATTR_DIP_MASK: 31 - SAI_FLOW_ENTRY_ATTR_VENDOR_METADATA: 33 - SAI_FLOW_ENTRY_ATTR_FLOW_DATA_PB: 34 + attr_params: + SAI_FLOW_ENTRY_ATTR_VERSION: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 1 + field: u32 + bitwidth: 32 + ip_is_v6_field_id: 0 + skipattr: null + SAI_FLOW_ENTRY_ATTR_DASH_DIRECTION: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 2 + field: s32 + bitwidth: 16 + ip_is_v6_field_id: 0 + skipattr: null + SAI_FLOW_ENTRY_ATTR_DASH_FLOW_ACTION: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 3 + field: s32 + bitwidth: 32 + ip_is_v6_field_id: 0 + skipattr: null + SAI_FLOW_ENTRY_ATTR_METER_CLASS: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 4 + field: u32 + bitwidth: 32 + ip_is_v6_field_id: 0 + skipattr: null + SAI_FLOW_ENTRY_ATTR_IS_UNIDIRECTIONAL_FLOW: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 5 + field: booldata + bitwidth: 1 + ip_is_v6_field_id: 0 + skipattr: null + SAI_FLOW_ENTRY_ATTR_DASH_FLOW_SYNC_STATE: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 6 + field: s32 + bitwidth: 8 + ip_is_v6_field_id: 0 + skipattr: null + SAI_FLOW_ENTRY_ATTR_REVERSE_FLOW_ENI_MAC: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 7 + field: mac + bitwidth: 48 + ip_is_v6_field_id: 0 + skipattr: null + SAI_FLOW_ENTRY_ATTR_REVERSE_FLOW_VNET_ID: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 8 + field: u16 + bitwidth: 16 + ip_is_v6_field_id: 0 + skipattr: null + SAI_FLOW_ENTRY_ATTR_REVERSE_FLOW_IP_PROTO: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 9 + field: u8 + bitwidth: 8 + ip_is_v6_field_id: 0 + skipattr: null + SAI_FLOW_ENTRY_ATTR_REVERSE_FLOW_SRC_IP: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 10 + field: ipaddr + bitwidth: 128 + ip_is_v6_field_id: 0 + skipattr: null + SAI_FLOW_ENTRY_ATTR_REVERSE_FLOW_DST_IP: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 11 + field: ipaddr + bitwidth: 128 + ip_is_v6_field_id: 14 + skipattr: null + SAI_FLOW_ENTRY_ATTR_REVERSE_FLOW_SRC_PORT: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 12 + field: u16 + bitwidth: 16 + ip_is_v6_field_id: 0 + skipattr: null + SAI_FLOW_ENTRY_ATTR_REVERSE_FLOW_DST_PORT: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 13 + field: u16 + bitwidth: 16 + ip_is_v6_field_id: 0 + skipattr: null + SAI_FLOW_ENTRY_ATTR_UNDERLAY0_VNET_ID: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 15 + field: u32 + bitwidth: 24 + ip_is_v6_field_id: 0 + skipattr: null + SAI_FLOW_ENTRY_ATTR_UNDERLAY0_SIP: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 16 + field: ipaddr + bitwidth: 32 + ip_is_v6_field_id: 0 + skipattr: null + SAI_FLOW_ENTRY_ATTR_UNDERLAY0_DIP: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 17 + field: ipaddr + bitwidth: 32 + ip_is_v6_field_id: 0 + skipattr: null + SAI_FLOW_ENTRY_ATTR_UNDERLAY0_SMAC: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 18 + field: mac + bitwidth: 48 + ip_is_v6_field_id: 0 + skipattr: null + SAI_FLOW_ENTRY_ATTR_UNDERLAY0_DMAC: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 19 + field: mac + bitwidth: 48 + ip_is_v6_field_id: 0 + skipattr: null + SAI_FLOW_ENTRY_ATTR_UNDERLAY0_DASH_ENCAPSULATION: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 20 + field: s32 + bitwidth: 16 + ip_is_v6_field_id: 0 + skipattr: null + SAI_FLOW_ENTRY_ATTR_UNDERLAY1_VNET_ID: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 21 + field: u32 + bitwidth: 24 + ip_is_v6_field_id: 0 + skipattr: null + SAI_FLOW_ENTRY_ATTR_UNDERLAY1_SIP: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 22 + field: ipaddr + bitwidth: 32 + ip_is_v6_field_id: 0 + skipattr: null + SAI_FLOW_ENTRY_ATTR_UNDERLAY1_DIP: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 23 + field: ipaddr + bitwidth: 32 + ip_is_v6_field_id: 0 + skipattr: null + SAI_FLOW_ENTRY_ATTR_UNDERLAY1_SMAC: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 24 + field: mac + bitwidth: 48 + ip_is_v6_field_id: 0 + skipattr: null + SAI_FLOW_ENTRY_ATTR_UNDERLAY1_DMAC: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 25 + field: mac + bitwidth: 48 + ip_is_v6_field_id: 0 + skipattr: null + SAI_FLOW_ENTRY_ATTR_UNDERLAY1_DASH_ENCAPSULATION: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 26 + field: s32 + bitwidth: 16 + ip_is_v6_field_id: 0 + skipattr: null + SAI_FLOW_ENTRY_ATTR_DST_MAC: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 27 + field: mac + bitwidth: 48 + ip_is_v6_field_id: 0 + skipattr: null + SAI_FLOW_ENTRY_ATTR_SIP: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 28 + field: ipaddr + bitwidth: 128 + ip_is_v6_field_id: 0 + skipattr: null + SAI_FLOW_ENTRY_ATTR_DIP: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 29 + field: ipaddr + bitwidth: 128 + ip_is_v6_field_id: 32 + skipattr: null + SAI_FLOW_ENTRY_ATTR_SIP_MASK: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 30 + field: ipaddr + bitwidth: 128 + ip_is_v6_field_id: 0 + skipattr: null + SAI_FLOW_ENTRY_ATTR_DIP_MASK: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 31 + field: ipaddr + bitwidth: 128 + ip_is_v6_field_id: 0 + skipattr: null + SAI_FLOW_ENTRY_ATTR_VENDOR_METADATA: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 33 + field: u8list + bitwidth: 16 + ip_is_v6_field_id: 0 + skipattr: null + SAI_FLOW_ENTRY_ATTR_FLOW_DATA_PB: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 34 + field: u8list + bitwidth: 16 + ip_is_v6_field_id: 0 + skipattr: null - !!python/object:utils.sai_spec.sai_api.SaiApi name: flow_entry_bulk_get_session_filter description: flow entry bulk get session filter @@ -687,11 +933,51 @@ sai_apis: tables: - !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaTable id: 38861669 + stage: null + keys: + - !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaKey + name: bulk_get_session_filter_id + id: 1 + match_type: exact + field: u16 + bitwidth: 16 + ip_is_v6_field_id: 0 + is_object_key: true actions: - default: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaAction - name: default + SAI_FLOW_ENTRY_BULK_GET_SESSION_FILTER_ACTION_SET_FLOW_ENTRY_BULK_GET_SESSION_FILTER_ATTR: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaAction + name: SAI_FLOW_ENTRY_BULK_GET_SESSION_FILTER_ACTION_SET_FLOW_ENTRY_BULK_GET_SESSION_FILTER_ATTR id: 19436677 - attr_param_id: {} + attr_params: + SAI_FLOW_ENTRY_BULK_GET_SESSION_FILTER_ATTR_DASH_FLOW_ENTRY_BULK_GET_SESSION_FILTER_KEY: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 1 + field: s32 + bitwidth: 16 + ip_is_v6_field_id: 0 + skipattr: null + SAI_FLOW_ENTRY_BULK_GET_SESSION_FILTER_ATTR_DASH_FLOW_ENTRY_BULK_GET_SESSION_OP_KEY: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 2 + field: s32 + bitwidth: 8 + ip_is_v6_field_id: 0 + skipattr: null + SAI_FLOW_ENTRY_BULK_GET_SESSION_FILTER_ATTR_INT_VALUE: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 3 + field: u64 + bitwidth: 64 + ip_is_v6_field_id: 0 + skipattr: null + SAI_FLOW_ENTRY_BULK_GET_SESSION_FILTER_ATTR_IP_VALUE: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 4 + field: ipaddr + bitwidth: 128 + ip_is_v6_field_id: 0 + skipattr: null + SAI_FLOW_ENTRY_BULK_GET_SESSION_FILTER_ATTR_MAC_VALUE: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 5 + field: mac + bitwidth: 48 + ip_is_v6_field_id: 0 + skipattr: null - !!python/object:utils.sai_spec.sai_api.SaiApi name: flow_entry_bulk_get_session description: flow entry bulk get session @@ -821,8 +1107,72 @@ sai_apis: tables: - !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaTable id: 38230977 + stage: null + keys: + - !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaKey + name: bulk_get_session_id + id: 1 + match_type: exact + field: u16 + bitwidth: 16 + ip_is_v6_field_id: 0 + is_object_key: true actions: - default: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaAction - name: default + SAI_FLOW_ENTRY_BULK_GET_SESSION_ACTION_SET_FLOW_ENTRY_BULK_GET_SESSION_ATTR: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaAction + name: SAI_FLOW_ENTRY_BULK_GET_SESSION_ACTION_SET_FLOW_ENTRY_BULK_GET_SESSION_ATTR id: 24218189 - attr_param_id: {} + attr_params: + SAI_FLOW_ENTRY_BULK_GET_SESSION_ATTR_DASH_FLOW_ENTRY_BULK_GET_SESSION_MODE: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 1 + field: s32 + bitwidth: 16 + ip_is_v6_field_id: 0 + skipattr: null + SAI_FLOW_ENTRY_BULK_GET_SESSION_ATTR_BULK_GET_ENTRY_LIMITATION: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 2 + field: u32 + bitwidth: 32 + ip_is_v6_field_id: 0 + skipattr: null + SAI_FLOW_ENTRY_BULK_GET_SESSION_ATTR_BULK_GET_SESSION_SERVER_IP: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 3 + field: ipaddr + bitwidth: 128 + ip_is_v6_field_id: 0 + skipattr: null + SAI_FLOW_ENTRY_BULK_GET_SESSION_ATTR_BULK_GET_SESSION_SERVER_PORT: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 4 + field: u16 + bitwidth: 16 + ip_is_v6_field_id: 0 + skipattr: null + SAI_FLOW_ENTRY_BULK_GET_SESSION_ATTR_FIRST_FLOW_ENTRY_BULK_GET_SESSION_FILTER_ID: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 5 + field: u16 + bitwidth: 16 + ip_is_v6_field_id: 0 + skipattr: null + SAI_FLOW_ENTRY_BULK_GET_SESSION_ATTR_SECOND_FLOW_ENTRY_BULK_GET_SESSION_FILTER_ID: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 6 + field: u16 + bitwidth: 16 + ip_is_v6_field_id: 0 + skipattr: null + SAI_FLOW_ENTRY_BULK_GET_SESSION_ATTR_THIRD_FLOW_ENTRY_BULK_GET_SESSION_FILTER_ID: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 7 + field: u16 + bitwidth: 16 + ip_is_v6_field_id: 0 + skipattr: null + SAI_FLOW_ENTRY_BULK_GET_SESSION_ATTR_FOURTH_FLOW_ENTRY_BULK_GET_SESSION_FILTER_ID: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 8 + field: u16 + bitwidth: 16 + ip_is_v6_field_id: 0 + skipattr: null + SAI_FLOW_ENTRY_BULK_GET_SESSION_ATTR_FIFTH_FLOW_ENTRY_BULK_GET_SESSION_FILTER_ID: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 9 + field: u16 + bitwidth: 16 + ip_is_v6_field_id: 0 + skipattr: null diff --git a/dash-pipeline/SAI/specs/dash_ha.yaml b/dash-pipeline/SAI/specs/dash_ha.yaml index e428fe64b..676211ac3 100644 --- a/dash-pipeline/SAI/specs/dash_ha.yaml +++ b/dash-pipeline/SAI/specs/dash_ha.yaml @@ -405,11 +405,81 @@ sai_apis: tables: - !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaTable id: 45319666 + stage: null + keys: + - !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaKey + name: ha_set_id + id: 1 + match_type: exact + field: u16 + bitwidth: 16 + ip_is_v6_field_id: 0 + is_object_key: true actions: - default: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaAction - name: default + SAI_HA_SET_ACTION_SET_HA_SET_ATTR: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaAction + name: SAI_HA_SET_ACTION_SET_HA_SET_ATTR id: 21324178 - attr_param_id: {} + attr_params: + SAI_HA_SET_ATTR_LOCAL_IP: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 2 + field: ipaddr + bitwidth: 128 + ip_is_v6_field_id: 1 + skipattr: null + SAI_HA_SET_ATTR_PEER_IP: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 4 + field: ipaddr + bitwidth: 128 + ip_is_v6_field_id: 3 + skipattr: null + SAI_HA_SET_ATTR_CP_DATA_CHANNEL_PORT: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 5 + field: u16 + bitwidth: 16 + ip_is_v6_field_id: 0 + skipattr: null + SAI_HA_SET_ATTR_DP_CHANNEL_DST_PORT: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 6 + field: u16 + bitwidth: 16 + ip_is_v6_field_id: 0 + skipattr: null + SAI_HA_SET_ATTR_DP_CHANNEL_MIN_SRC_PORT: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 7 + field: u16 + bitwidth: 16 + ip_is_v6_field_id: 0 + skipattr: null + SAI_HA_SET_ATTR_DP_CHANNEL_MAX_SRC_PORT: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 8 + field: u16 + bitwidth: 16 + ip_is_v6_field_id: 0 + skipattr: null + SAI_HA_SET_ATTR_DP_CHANNEL_PROBE_INTERVAL_MS: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 9 + field: u32 + bitwidth: 32 + ip_is_v6_field_id: 0 + skipattr: null + SAI_HA_SET_ATTR_DP_CHANNEL_PROBE_FAIL_THRESHOLD: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 10 + field: u32 + bitwidth: 32 + ip_is_v6_field_id: 0 + skipattr: null + SAI_HA_SET_ATTR_DP_CHANNEL_IS_ALIVE: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 11 + field: booldata + bitwidth: 1 + ip_is_v6_field_id: 0 + skipattr: null + SAI_HA_SET_ATTR_DPU_DRIVEN_HA_SWITCHOVER_WAIT_TIME_MS: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 12 + field: u32 + bitwidth: 32 + ip_is_v6_field_id: 0 + skipattr: null - !!python/object:utils.sai_spec.sai_api.SaiApi name: ha_scope description: HA scope @@ -552,8 +622,78 @@ sai_apis: tables: - !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaTable id: 49681752 + stage: null + keys: + - !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaKey + name: ha_scope_id + id: 1 + match_type: exact + field: u16 + bitwidth: 16 + ip_is_v6_field_id: 0 + is_object_key: true actions: - default: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaAction - name: default + SAI_HA_SCOPE_ACTION_SET_HA_SCOPE_ATTR: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaAction + name: SAI_HA_SCOPE_ACTION_SET_HA_SCOPE_ATTR id: 25507507 - attr_param_id: {} + attr_params: + SAI_HA_SCOPE_ATTR_HA_SET_ID: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 1 + field: u16 + bitwidth: 16 + ip_is_v6_field_id: 0 + skipattr: null + SAI_HA_SCOPE_ATTR_DASH_HA_ROLE: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 2 + field: s32 + bitwidth: 8 + ip_is_v6_field_id: 0 + skipattr: null + SAI_HA_SCOPE_ATTR_FLOW_VERSION: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 3 + field: u32 + bitwidth: 32 + ip_is_v6_field_id: 0 + skipattr: null + SAI_HA_SCOPE_ATTR_FLOW_RECONCILE_REQUESTED: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 4 + field: booldata + bitwidth: 1 + ip_is_v6_field_id: 0 + skipattr: null + SAI_HA_SCOPE_ATTR_FLOW_RECONCILE_NEEDED: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 5 + field: booldata + bitwidth: 1 + ip_is_v6_field_id: 0 + skipattr: null + SAI_HA_SCOPE_ATTR_VIP_V4: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 6 + field: ipaddr + bitwidth: 32 + ip_is_v6_field_id: 0 + skipattr: null + SAI_HA_SCOPE_ATTR_VIP_V6: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 7 + field: ipaddr + bitwidth: 128 + ip_is_v6_field_id: 0 + skipattr: null + SAI_HA_SCOPE_ATTR_ADMIN_STATE: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 8 + field: booldata + bitwidth: 1 + ip_is_v6_field_id: 0 + skipattr: null + SAI_HA_SCOPE_ATTR_ACTIVATE_ROLE: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 9 + field: booldata + bitwidth: 1 + ip_is_v6_field_id: 0 + skipattr: null + SAI_HA_SCOPE_ATTR_DASH_HA_STATE: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 10 + field: s32 + bitwidth: 8 + ip_is_v6_field_id: 0 + skipattr: null diff --git a/dash-pipeline/SAI/specs/dash_inbound_routing.yaml b/dash-pipeline/SAI/specs/dash_inbound_routing.yaml index 228223821..6c59fb0b2 100644 --- a/dash-pipeline/SAI/specs/dash_inbound_routing.yaml +++ b/dash-pipeline/SAI/specs/dash_inbound_routing.yaml @@ -142,25 +142,76 @@ sai_apis: tables: - !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaTable id: 35881437 + stage: null + keys: + - !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaKey + name: eni_id + id: 1 + match_type: exact + field: u16 + bitwidth: 16 + ip_is_v6_field_id: 0 + is_object_key: false + - !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaKey + name: VNI + id: 2 + match_type: exact + field: u32 + bitwidth: 24 + ip_is_v6_field_id: 0 + is_object_key: false + - !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaKey + name: sip + id: 3 + match_type: ternary + field: ipaddr + bitwidth: 32 + ip_is_v6_field_id: 0 + is_object_key: false actions: SAI_INBOUND_ROUTING_ENTRY_ACTION_TUNNEL_DECAP: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaAction name: SAI_INBOUND_ROUTING_ENTRY_ACTION_TUNNEL_DECAP id: 26741158 - attr_param_id: - SAI_INBOUND_ROUTING_ENTRY_ATTR_METER_CLASS_OR: 1 - SAI_INBOUND_ROUTING_ENTRY_ATTR_METER_CLASS_AND: 2 + attr_params: + SAI_INBOUND_ROUTING_ENTRY_ATTR_METER_CLASS_OR: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 1 + field: u32 + bitwidth: 32 + ip_is_v6_field_id: 0 + skipattr: null + SAI_INBOUND_ROUTING_ENTRY_ATTR_METER_CLASS_AND: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 2 + field: u32 + bitwidth: 32 + ip_is_v6_field_id: 0 + skipattr: null SAI_INBOUND_ROUTING_ENTRY_ACTION_TUNNEL_DECAP_PA_VALIDATE: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaAction name: SAI_INBOUND_ROUTING_ENTRY_ACTION_TUNNEL_DECAP_PA_VALIDATE id: 26064107 - attr_param_id: - SAI_INBOUND_ROUTING_ENTRY_ATTR_SRC_VNET_ID: 1 - SAI_INBOUND_ROUTING_ENTRY_ATTR_METER_CLASS_OR: 2 - SAI_INBOUND_ROUTING_ENTRY_ATTR_METER_CLASS_AND: 3 + attr_params: + SAI_INBOUND_ROUTING_ENTRY_ATTR_SRC_VNET_ID: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 1 + field: u16 + bitwidth: 16 + ip_is_v6_field_id: 0 + skipattr: null + SAI_INBOUND_ROUTING_ENTRY_ATTR_METER_CLASS_OR: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 2 + field: u32 + bitwidth: 32 + ip_is_v6_field_id: 0 + skipattr: null + SAI_INBOUND_ROUTING_ENTRY_ATTR_METER_CLASS_AND: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 3 + field: u32 + bitwidth: 32 + ip_is_v6_field_id: 0 + skipattr: null SAI_INBOUND_ROUTING_ENTRY_ACTION_VXLAN_DECAP: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaAction name: SAI_INBOUND_ROUTING_ENTRY_ACTION_VXLAN_DECAP id: 24482615 - attr_param_id: {} + attr_params: {} SAI_INBOUND_ROUTING_ENTRY_ACTION_VXLAN_DECAP_PA_VALIDATE: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaAction name: SAI_INBOUND_ROUTING_ENTRY_ACTION_VXLAN_DECAP_PA_VALIDATE id: 24695752 - attr_param_id: {} + attr_params: {} diff --git a/dash-pipeline/SAI/specs/dash_meter.yaml b/dash-pipeline/SAI/specs/dash_meter.yaml index dadc1ab35..90efd0d71 100644 --- a/dash-pipeline/SAI/specs/dash_meter.yaml +++ b/dash-pipeline/SAI/specs/dash_meter.yaml @@ -84,11 +84,29 @@ sai_apis: tables: - !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaTable id: 45482818 + stage: null + keys: + - !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaKey + name: eni_id + id: 1 + match_type: exact + field: u16 + bitwidth: 16 + ip_is_v6_field_id: 0 + is_object_key: false + - !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaKey + name: meter_class + id: 2 + match_type: exact + field: u32 + bitwidth: 32 + ip_is_v6_field_id: 0 + is_object_key: false actions: SAI_METER_BUCKET_ENTRY_ACTION_UPDATE_METER_BUCKET: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaAction name: SAI_METER_BUCKET_ENTRY_ACTION_UPDATE_METER_BUCKET id: 23515737 - attr_param_id: {} + attr_params: {} - !!python/object:utils.sai_spec.sai_api.SaiApi name: meter_policy description: meter policy @@ -114,11 +132,27 @@ sai_apis: tables: - !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaTable id: 40733610 + stage: null + keys: + - !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaKey + name: meter_policy_id + id: 1 + match_type: exact + field: u16 + bitwidth: 16 + ip_is_v6_field_id: 0 + is_object_key: true actions: - default: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaAction - name: default + SAI_METER_POLICY_ACTION_CHECK_IP_ADDR_FAMILY: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaAction + name: SAI_METER_POLICY_ACTION_CHECK_IP_ADDR_FAMILY id: 20564717 - attr_param_id: {} + attr_params: + SAI_METER_POLICY_ATTR_IP_ADDR_FAMILY: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 1 + field: u32 + bitwidth: 32 + ip_is_v6_field_id: 0 + skipattr: null - !!python/object:utils.sai_spec.sai_api.SaiApi name: meter_rule description: meter rule @@ -209,8 +243,32 @@ sai_apis: tables: - !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaTable id: 44484556 + stage: null + keys: + - !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaKey + name: meter_policy_id + id: 1 + match_type: exact + field: u16 + bitwidth: 16 + ip_is_v6_field_id: 0 + is_object_key: false + - !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaKey + name: dip + id: 2 + match_type: ternary + field: ipaddr + bitwidth: 128 + ip_is_v6_field_id: 0 + is_object_key: false actions: - default: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaAction - name: default + SAI_METER_RULE_ACTION_SET_POLICY_METER_CLASS: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaAction + name: SAI_METER_RULE_ACTION_SET_POLICY_METER_CLASS id: 19652160 - attr_param_id: {} + attr_params: + SAI_METER_RULE_ATTR_METER_CLASS: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 1 + field: u32 + bitwidth: 32 + ip_is_v6_field_id: 0 + skipattr: null diff --git a/dash-pipeline/SAI/specs/dash_outbound_ca_to_pa.yaml b/dash-pipeline/SAI/specs/dash_outbound_ca_to_pa.yaml index 7c594d82e..945fecfc8 100644 --- a/dash-pipeline/SAI/specs/dash_outbound_ca_to_pa.yaml +++ b/dash-pipeline/SAI/specs/dash_outbound_ca_to_pa.yaml @@ -262,30 +262,138 @@ sai_apis: tables: - !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaTable id: 48765007 + stage: null + keys: + - !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaKey + name: dst_vnet_id + id: 1 + match_type: exact + field: u16 + bitwidth: 16 + ip_is_v6_field_id: 0 + is_object_key: false + - !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaKey + name: dip + id: 3 + match_type: exact + field: ipaddr + bitwidth: 128 + ip_is_v6_field_id: 2 + is_object_key: false actions: SAI_OUTBOUND_CA_TO_PA_ENTRY_ACTION_SET_TUNNEL_MAPPING: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaAction name: SAI_OUTBOUND_CA_TO_PA_ENTRY_ACTION_SET_TUNNEL_MAPPING id: 25614729 - attr_param_id: - SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_UNDERLAY_DIP: 1 - SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_OVERLAY_DMAC: 2 - SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_USE_DST_VNET_VNI: 3 - SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_METER_CLASS_OR: 4 - SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_DASH_TUNNEL_ID: 5 - SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_FLOW_RESIMULATION_REQUESTED: 6 - SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_ROUTING_ACTIONS_DISABLED_IN_FLOW_RESIMULATION: 7 + attr_params: + SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_UNDERLAY_DIP: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 1 + field: ipaddr + bitwidth: 32 + ip_is_v6_field_id: 0 + skipattr: null + SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_OVERLAY_DMAC: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 2 + field: mac + bitwidth: 48 + ip_is_v6_field_id: 0 + skipattr: null + SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_USE_DST_VNET_VNI: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 3 + field: booldata + bitwidth: 1 + ip_is_v6_field_id: 0 + skipattr: null + SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_METER_CLASS_OR: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 4 + field: u32 + bitwidth: 32 + ip_is_v6_field_id: 0 + skipattr: null + SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_DASH_TUNNEL_ID: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 5 + field: u16 + bitwidth: 16 + ip_is_v6_field_id: 0 + skipattr: null + SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_FLOW_RESIMULATION_REQUESTED: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 6 + field: booldata + bitwidth: 1 + ip_is_v6_field_id: 0 + skipattr: null + SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_ROUTING_ACTIONS_DISABLED_IN_FLOW_RESIMULATION: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 7 + field: u32 + bitwidth: 32 + ip_is_v6_field_id: 0 + skipattr: null SAI_OUTBOUND_CA_TO_PA_ENTRY_ACTION_SET_PRIVATE_LINK_MAPPING: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaAction name: SAI_OUTBOUND_CA_TO_PA_ENTRY_ACTION_SET_PRIVATE_LINK_MAPPING id: 31441909 - attr_param_id: - SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_UNDERLAY_DIP: 1 - SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_OVERLAY_SIP: 2 - SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_OVERLAY_SIP_MASK: 3 - SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_OVERLAY_DIP: 4 - SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_OVERLAY_DIP_MASK: 5 - SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_DASH_ENCAPSULATION: 6 - SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_TUNNEL_KEY: 7 - SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_METER_CLASS_OR: 8 - SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_DASH_TUNNEL_ID: 9 - SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_FLOW_RESIMULATION_REQUESTED: 10 - SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_ROUTING_ACTIONS_DISABLED_IN_FLOW_RESIMULATION: 11 + attr_params: + SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_UNDERLAY_DIP: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 1 + field: ipaddr + bitwidth: 32 + ip_is_v6_field_id: 0 + skipattr: null + SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_OVERLAY_SIP: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 2 + field: ipaddr + bitwidth: 128 + ip_is_v6_field_id: 0 + skipattr: null + SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_OVERLAY_SIP_MASK: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 3 + field: ipaddr + bitwidth: 128 + ip_is_v6_field_id: 0 + skipattr: null + SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_OVERLAY_DIP: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 4 + field: ipaddr + bitwidth: 128 + ip_is_v6_field_id: 0 + skipattr: null + SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_OVERLAY_DIP_MASK: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 5 + field: ipaddr + bitwidth: 128 + ip_is_v6_field_id: 0 + skipattr: null + SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_DASH_ENCAPSULATION: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 6 + field: s32 + bitwidth: 16 + ip_is_v6_field_id: 0 + skipattr: null + SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_TUNNEL_KEY: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 7 + field: u32 + bitwidth: 24 + ip_is_v6_field_id: 0 + skipattr: null + SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_METER_CLASS_OR: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 8 + field: u32 + bitwidth: 32 + ip_is_v6_field_id: 0 + skipattr: null + SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_DASH_TUNNEL_ID: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 9 + field: u16 + bitwidth: 16 + ip_is_v6_field_id: 0 + skipattr: null + SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_FLOW_RESIMULATION_REQUESTED: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 10 + field: booldata + bitwidth: 1 + ip_is_v6_field_id: 0 + skipattr: null + SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_ROUTING_ACTIONS_DISABLED_IN_FLOW_RESIMULATION: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 11 + field: u32 + bitwidth: 32 + ip_is_v6_field_id: 0 + skipattr: null diff --git a/dash-pipeline/SAI/specs/dash_outbound_routing.yaml b/dash-pipeline/SAI/specs/dash_outbound_routing.yaml index 05effc7b2..ad6533117 100644 --- a/dash-pipeline/SAI/specs/dash_outbound_routing.yaml +++ b/dash-pipeline/SAI/specs/dash_outbound_routing.yaml @@ -295,54 +295,207 @@ sai_apis: tables: - !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaTable id: 38546097 + stage: null + keys: + - !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaKey + name: outbound_routing_group_id + id: 1 + match_type: exact + field: u16 + bitwidth: 16 + ip_is_v6_field_id: 0 + is_object_key: false + - !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaKey + name: destination + id: 3 + match_type: lpm + field: ipPrefix + bitwidth: 128 + ip_is_v6_field_id: 2 + is_object_key: false actions: SAI_OUTBOUND_ROUTING_ENTRY_ACTION_ROUTE_VNET: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaAction name: SAI_OUTBOUND_ROUTING_ENTRY_ACTION_ROUTE_VNET id: 21392322 - attr_param_id: - SAI_OUTBOUND_ROUTING_ENTRY_ATTR_DST_VNET_ID: 1 - SAI_OUTBOUND_ROUTING_ENTRY_ATTR_DASH_TUNNEL_ID: 2 - SAI_OUTBOUND_ROUTING_ENTRY_ATTR_METER_CLASS_OR: 3 - SAI_OUTBOUND_ROUTING_ENTRY_ATTR_METER_CLASS_AND: 4 - SAI_OUTBOUND_ROUTING_ENTRY_ATTR_ROUTING_ACTIONS_DISABLED_IN_FLOW_RESIMULATION: 5 + attr_params: + SAI_OUTBOUND_ROUTING_ENTRY_ATTR_DST_VNET_ID: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 1 + field: u16 + bitwidth: 16 + ip_is_v6_field_id: 0 + skipattr: null + SAI_OUTBOUND_ROUTING_ENTRY_ATTR_DASH_TUNNEL_ID: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 2 + field: u16 + bitwidth: 16 + ip_is_v6_field_id: 0 + skipattr: null + SAI_OUTBOUND_ROUTING_ENTRY_ATTR_METER_CLASS_OR: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 3 + field: u32 + bitwidth: 32 + ip_is_v6_field_id: 0 + skipattr: null + SAI_OUTBOUND_ROUTING_ENTRY_ATTR_METER_CLASS_AND: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 4 + field: u32 + bitwidth: 32 + ip_is_v6_field_id: 0 + skipattr: null + SAI_OUTBOUND_ROUTING_ENTRY_ATTR_ROUTING_ACTIONS_DISABLED_IN_FLOW_RESIMULATION: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 5 + field: u32 + bitwidth: 32 + ip_is_v6_field_id: 0 + skipattr: null SAI_OUTBOUND_ROUTING_ENTRY_ACTION_ROUTE_VNET_DIRECT: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaAction name: SAI_OUTBOUND_ROUTING_ENTRY_ACTION_ROUTE_VNET_DIRECT id: 24813914 - attr_param_id: - SAI_OUTBOUND_ROUTING_ENTRY_ATTR_DST_VNET_ID: 1 - SAI_OUTBOUND_ROUTING_ENTRY_ATTR_DASH_TUNNEL_ID: 2 - SAI_OUTBOUND_ROUTING_ENTRY_ATTR_OVERLAY_IP: 4 - SAI_OUTBOUND_ROUTING_ENTRY_ATTR_METER_CLASS_OR: 5 - SAI_OUTBOUND_ROUTING_ENTRY_ATTR_METER_CLASS_AND: 6 - SAI_OUTBOUND_ROUTING_ENTRY_ATTR_ROUTING_ACTIONS_DISABLED_IN_FLOW_RESIMULATION: 7 + attr_params: + SAI_OUTBOUND_ROUTING_ENTRY_ATTR_DST_VNET_ID: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 1 + field: u16 + bitwidth: 16 + ip_is_v6_field_id: 0 + skipattr: null + SAI_OUTBOUND_ROUTING_ENTRY_ATTR_DASH_TUNNEL_ID: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 2 + field: u16 + bitwidth: 16 + ip_is_v6_field_id: 0 + skipattr: null + SAI_OUTBOUND_ROUTING_ENTRY_ATTR_OVERLAY_IP: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 4 + field: ipaddr + bitwidth: 128 + ip_is_v6_field_id: 3 + skipattr: null + SAI_OUTBOUND_ROUTING_ENTRY_ATTR_METER_CLASS_OR: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 5 + field: u32 + bitwidth: 32 + ip_is_v6_field_id: 0 + skipattr: null + SAI_OUTBOUND_ROUTING_ENTRY_ATTR_METER_CLASS_AND: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 6 + field: u32 + bitwidth: 32 + ip_is_v6_field_id: 0 + skipattr: null + SAI_OUTBOUND_ROUTING_ENTRY_ATTR_ROUTING_ACTIONS_DISABLED_IN_FLOW_RESIMULATION: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 7 + field: u32 + bitwidth: 32 + ip_is_v6_field_id: 0 + skipattr: null SAI_OUTBOUND_ROUTING_ENTRY_ACTION_ROUTE_DIRECT: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaAction name: SAI_OUTBOUND_ROUTING_ENTRY_ACTION_ROUTE_DIRECT id: 31102279 - attr_param_id: - SAI_OUTBOUND_ROUTING_ENTRY_ATTR_DASH_TUNNEL_ID: 1 - SAI_OUTBOUND_ROUTING_ENTRY_ATTR_METER_CLASS_OR: 2 - SAI_OUTBOUND_ROUTING_ENTRY_ATTR_METER_CLASS_AND: 3 - SAI_OUTBOUND_ROUTING_ENTRY_ATTR_ROUTING_ACTIONS_DISABLED_IN_FLOW_RESIMULATION: 4 + attr_params: + SAI_OUTBOUND_ROUTING_ENTRY_ATTR_DASH_TUNNEL_ID: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 1 + field: u16 + bitwidth: 16 + ip_is_v6_field_id: 0 + skipattr: null + SAI_OUTBOUND_ROUTING_ENTRY_ATTR_METER_CLASS_OR: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 2 + field: u32 + bitwidth: 32 + ip_is_v6_field_id: 0 + skipattr: null + SAI_OUTBOUND_ROUTING_ENTRY_ATTR_METER_CLASS_AND: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 3 + field: u32 + bitwidth: 32 + ip_is_v6_field_id: 0 + skipattr: null + SAI_OUTBOUND_ROUTING_ENTRY_ATTR_ROUTING_ACTIONS_DISABLED_IN_FLOW_RESIMULATION: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 4 + field: u32 + bitwidth: 32 + ip_is_v6_field_id: 0 + skipattr: null SAI_OUTBOUND_ROUTING_ENTRY_ACTION_ROUTE_SERVICE_TUNNEL: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaAction name: SAI_OUTBOUND_ROUTING_ENTRY_ACTION_ROUTE_SERVICE_TUNNEL id: 26982790 - attr_param_id: - SAI_OUTBOUND_ROUTING_ENTRY_ATTR_OVERLAY_DIP: 2 - SAI_OUTBOUND_ROUTING_ENTRY_ATTR_OVERLAY_DIP_MASK: 4 - SAI_OUTBOUND_ROUTING_ENTRY_ATTR_OVERLAY_SIP: 6 - SAI_OUTBOUND_ROUTING_ENTRY_ATTR_OVERLAY_SIP_MASK: 8 - SAI_OUTBOUND_ROUTING_ENTRY_ATTR_UNDERLAY_DIP: 10 - SAI_OUTBOUND_ROUTING_ENTRY_ATTR_UNDERLAY_SIP: 12 - SAI_OUTBOUND_ROUTING_ENTRY_ATTR_DASH_ENCAPSULATION: 13 - SAI_OUTBOUND_ROUTING_ENTRY_ATTR_TUNNEL_KEY: 14 - SAI_OUTBOUND_ROUTING_ENTRY_ATTR_DASH_TUNNEL_ID: 15 - SAI_OUTBOUND_ROUTING_ENTRY_ATTR_METER_CLASS_OR: 16 - SAI_OUTBOUND_ROUTING_ENTRY_ATTR_METER_CLASS_AND: 17 - SAI_OUTBOUND_ROUTING_ENTRY_ATTR_ROUTING_ACTIONS_DISABLED_IN_FLOW_RESIMULATION: 18 + attr_params: + SAI_OUTBOUND_ROUTING_ENTRY_ATTR_OVERLAY_DIP: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 2 + field: ipaddr + bitwidth: 128 + ip_is_v6_field_id: 1 + skipattr: null + SAI_OUTBOUND_ROUTING_ENTRY_ATTR_OVERLAY_DIP_MASK: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 4 + field: ipaddr + bitwidth: 128 + ip_is_v6_field_id: 3 + skipattr: null + SAI_OUTBOUND_ROUTING_ENTRY_ATTR_OVERLAY_SIP: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 6 + field: ipaddr + bitwidth: 128 + ip_is_v6_field_id: 5 + skipattr: null + SAI_OUTBOUND_ROUTING_ENTRY_ATTR_OVERLAY_SIP_MASK: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 8 + field: ipaddr + bitwidth: 128 + ip_is_v6_field_id: 7 + skipattr: null + SAI_OUTBOUND_ROUTING_ENTRY_ATTR_UNDERLAY_DIP: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 10 + field: ipaddr + bitwidth: 128 + ip_is_v6_field_id: 9 + skipattr: null + SAI_OUTBOUND_ROUTING_ENTRY_ATTR_UNDERLAY_SIP: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 12 + field: ipaddr + bitwidth: 128 + ip_is_v6_field_id: 11 + skipattr: null + SAI_OUTBOUND_ROUTING_ENTRY_ATTR_DASH_ENCAPSULATION: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 13 + field: s32 + bitwidth: 16 + ip_is_v6_field_id: 0 + skipattr: null + SAI_OUTBOUND_ROUTING_ENTRY_ATTR_TUNNEL_KEY: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 14 + field: u32 + bitwidth: 24 + ip_is_v6_field_id: 0 + skipattr: null + SAI_OUTBOUND_ROUTING_ENTRY_ATTR_DASH_TUNNEL_ID: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 15 + field: u16 + bitwidth: 16 + ip_is_v6_field_id: 0 + skipattr: null + SAI_OUTBOUND_ROUTING_ENTRY_ATTR_METER_CLASS_OR: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 16 + field: u32 + bitwidth: 32 + ip_is_v6_field_id: 0 + skipattr: null + SAI_OUTBOUND_ROUTING_ENTRY_ATTR_METER_CLASS_AND: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 17 + field: u32 + bitwidth: 32 + ip_is_v6_field_id: 0 + skipattr: null + SAI_OUTBOUND_ROUTING_ENTRY_ATTR_ROUTING_ACTIONS_DISABLED_IN_FLOW_RESIMULATION: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 18 + field: u32 + bitwidth: 32 + ip_is_v6_field_id: 0 + skipattr: null SAI_OUTBOUND_ROUTING_ENTRY_ACTION_DROP: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaAction name: SAI_OUTBOUND_ROUTING_ENTRY_ACTION_DROP id: 18759588 - attr_param_id: {} + attr_params: {} - !!python/object:utils.sai_spec.sai_api.SaiApi name: outbound_routing_group description: outbound routing group @@ -368,8 +521,24 @@ sai_apis: tables: - !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaTable id: 40572680 + stage: null + keys: + - !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaKey + name: outbound_routing_group_id + id: 1 + match_type: exact + field: u16 + bitwidth: 16 + ip_is_v6_field_id: 0 + is_object_key: true actions: - default: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaAction - name: default + SAI_OUTBOUND_ROUTING_GROUP_ACTION_SET_OUTBOUND_ROUTING_GROUP_ATTR: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaAction + name: SAI_OUTBOUND_ROUTING_GROUP_ACTION_SET_OUTBOUND_ROUTING_GROUP_ATTR id: 30077100 - attr_param_id: {} + attr_params: + SAI_OUTBOUND_ROUTING_GROUP_ATTR_DISABLED: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 1 + field: booldata + bitwidth: 1 + ip_is_v6_field_id: 0 + skipattr: null diff --git a/dash-pipeline/SAI/specs/dash_pa_validation.yaml b/dash-pipeline/SAI/specs/dash_pa_validation.yaml index 7a80e2d53..9b115e6a4 100644 --- a/dash-pipeline/SAI/specs/dash_pa_validation.yaml +++ b/dash-pipeline/SAI/specs/dash_pa_validation.yaml @@ -71,8 +71,26 @@ sai_apis: tables: - !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaTable id: 49415809 + stage: null + keys: + - !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaKey + name: vnet_id + id: 1 + match_type: exact + field: u16 + bitwidth: 16 + ip_is_v6_field_id: 0 + is_object_key: false + - !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaKey + name: sip + id: 2 + match_type: exact + field: ipaddr + bitwidth: 32 + ip_is_v6_field_id: 0 + is_object_key: false actions: SAI_PA_VALIDATION_ENTRY_ACTION_PERMIT: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaAction name: SAI_PA_VALIDATION_ENTRY_ACTION_PERMIT id: 17521061 - attr_param_id: {} + attr_params: {} diff --git a/dash-pipeline/SAI/specs/dash_tunnel.yaml b/dash-pipeline/SAI/specs/dash_tunnel.yaml index 688357744..6cb76b8e1 100644 --- a/dash-pipeline/SAI/specs/dash_tunnel.yaml +++ b/dash-pipeline/SAI/specs/dash_tunnel.yaml @@ -80,11 +80,51 @@ sai_apis: tables: - !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaTable id: 49206552 + stage: null + keys: + - !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaKey + name: dash_tunnel_id + id: 1 + match_type: exact + field: u16 + bitwidth: 16 + ip_is_v6_field_id: 0 + is_object_key: true actions: - default: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaAction - name: default + SAI_DASH_TUNNEL_ACTION_SET_TUNNEL_ATTRS: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaAction + name: SAI_DASH_TUNNEL_ACTION_SET_TUNNEL_ATTRS id: 27084508 - attr_param_id: {} + attr_params: + SAI_DASH_TUNNEL_ATTR_DASH_ENCAPSULATION: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 1 + field: s32 + bitwidth: 16 + ip_is_v6_field_id: 0 + skipattr: null + SAI_DASH_TUNNEL_ATTR_TUNNEL_KEY: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 2 + field: u32 + bitwidth: 24 + ip_is_v6_field_id: 0 + skipattr: null + SAI_DASH_TUNNEL_ATTR_MAX_MEMBER_SIZE: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 3 + field: u32 + bitwidth: 32 + ip_is_v6_field_id: 0 + skipattr: null + SAI_DASH_TUNNEL_ATTR_DIP: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 4 + field: ipaddr + bitwidth: 32 + ip_is_v6_field_id: 0 + skipattr: null + SAI_DASH_TUNNEL_ATTR_SIP: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 5 + field: ipaddr + bitwidth: 32 + ip_is_v6_field_id: 0 + skipattr: null - !!python/object:utils.sai_spec.sai_api.SaiApi name: dash_tunnel_member description: DASH tunnel member @@ -123,11 +163,33 @@ sai_apis: tables: - !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaTable id: 41269458 + stage: null + keys: + - !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaKey + name: dash_tunnel_member_id + id: 1 + match_type: exact + field: u16 + bitwidth: 16 + ip_is_v6_field_id: 0 + is_object_key: true actions: - default: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaAction - name: default + SAI_DASH_TUNNEL_MEMBER_ACTION_SET_TUNNEL_MEMBER_ATTRS: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaAction + name: SAI_DASH_TUNNEL_MEMBER_ACTION_SET_TUNNEL_MEMBER_ATTRS id: 19698973 - attr_param_id: {} + attr_params: + SAI_DASH_TUNNEL_MEMBER_ATTR_DASH_TUNNEL_ID: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 1 + field: u16 + bitwidth: 16 + ip_is_v6_field_id: 0 + skipattr: null + SAI_DASH_TUNNEL_MEMBER_ATTR_DASH_TUNNEL_NEXT_HOP_ID: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 2 + field: u16 + bitwidth: 16 + ip_is_v6_field_id: 0 + skipattr: null - !!python/object:utils.sai_spec.sai_api.SaiApi name: dash_tunnel_next_hop description: DASH tunnel next hop @@ -153,8 +215,24 @@ sai_apis: tables: - !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaTable id: 37329198 + stage: null + keys: + - !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaKey + name: dash_tunnel_next_hop_id + id: 1 + match_type: exact + field: u16 + bitwidth: 16 + ip_is_v6_field_id: 0 + is_object_key: true actions: - default: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaAction - name: default + SAI_DASH_TUNNEL_NEXT_HOP_ACTION_SET_TUNNEL_NEXT_HOP_ATTRS: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaAction + name: SAI_DASH_TUNNEL_NEXT_HOP_ACTION_SET_TUNNEL_NEXT_HOP_ATTRS id: 17571304 - attr_param_id: {} + attr_params: + SAI_DASH_TUNNEL_NEXT_HOP_ATTR_DIP: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 1 + field: ipaddr + bitwidth: 32 + ip_is_v6_field_id: 0 + skipattr: null diff --git a/dash-pipeline/SAI/specs/dash_vip.yaml b/dash-pipeline/SAI/specs/dash_vip.yaml index ff280333f..58458e3ee 100644 --- a/dash-pipeline/SAI/specs/dash_vip.yaml +++ b/dash-pipeline/SAI/specs/dash_vip.yaml @@ -65,8 +65,18 @@ sai_apis: tables: - !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaTable id: 36083221 + stage: null + keys: + - !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaKey + name: VIP + id: 1 + match_type: exact + field: ipaddr + bitwidth: 32 + ip_is_v6_field_id: 0 + is_object_key: false actions: SAI_VIP_ENTRY_ACTION_ACCEPT: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaAction name: SAI_VIP_ENTRY_ACTION_ACCEPT id: 21715559 - attr_param_id: {} + attr_params: {} diff --git a/dash-pipeline/SAI/specs/dash_vnet.yaml b/dash-pipeline/SAI/specs/dash_vnet.yaml index 8240bcab4..609d70462 100644 --- a/dash-pipeline/SAI/specs/dash_vnet.yaml +++ b/dash-pipeline/SAI/specs/dash_vnet.yaml @@ -28,8 +28,24 @@ sai_apis: tables: - !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaTable id: 39583935 + stage: null + keys: + - !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaKey + name: vnet_id + id: 1 + match_type: exact + field: u16 + bitwidth: 16 + ip_is_v6_field_id: 0 + is_object_key: true actions: - default: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaAction - name: default + SAI_VNET_ACTION_SET_VNET_ATTRS: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaAction + name: SAI_VNET_ACTION_SET_VNET_ATTRS id: 28116018 - attr_param_id: {} + attr_params: + SAI_VNET_ATTR_VNI: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 1 + field: u32 + bitwidth: 24 + ip_is_v6_field_id: 0 + skipattr: null diff --git a/dash-pipeline/SAI/specs/route.yaml b/dash-pipeline/SAI/specs/route.yaml index 1b5921c09..bfef31e74 100644 --- a/dash-pipeline/SAI/specs/route.yaml +++ b/dash-pipeline/SAI/specs/route.yaml @@ -91,10 +91,30 @@ sai_apis: tables: - !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaTable id: 49279256 + stage: null + keys: + - !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaKey + name: destination + id: 1 + match_type: lpm + field: ipPrefix + bitwidth: 128 + ip_is_v6_field_id: 0 + is_object_key: false actions: SAI_ROUTE_ENTRY_ACTION_PKT_ACT: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaAction name: SAI_ROUTE_ENTRY_ACTION_PKT_ACT id: 32404057 - attr_param_id: - SAI_ROUTE_ENTRY_ATTR_PACKET_ACTION: 1 - SAI_ROUTE_ENTRY_ATTR_NEXT_HOP_ID: 2 + attr_params: + SAI_ROUTE_ENTRY_ATTR_PACKET_ACTION: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 1 + field: u16 + bitwidth: 9 + ip_is_v6_field_id: 0 + skipattr: null + SAI_ROUTE_ENTRY_ATTR_NEXT_HOP_ID: !!python/object:utils.sai_spec.sai_api_p4_meta.SaiApiP4MetaActionParam + id: 2 + field: u16 + bitwidth: 9 + ip_is_v6_field_id: 0 + skipattr: null diff --git a/dash-pipeline/SAI/utils/dash_p4/dash_p4_table.py b/dash-pipeline/SAI/utils/dash_p4/dash_p4_table.py index f931d57cb..a2c01f5a9 100644 --- a/dash-pipeline/SAI/utils/dash_p4/dash_p4_table.py +++ b/dash-pipeline/SAI/utils/dash_p4/dash_p4_table.py @@ -5,7 +5,8 @@ from .dash_p4_table_action_param import * from .dash_p4_table_key import * from .dash_p4_table_action import * -from ..sai_spec import SaiApi, SaiStruct, SaiEnum, SaiEnumMember, SaiAttribute, SaiApiP4MetaAction, SaiApiP4MetaTable +from ..sai_spec import SaiApi, SaiStruct, SaiEnum, SaiEnumMember, SaiAttribute, \ + SaiApiP4MetaAction, SaiApiP4MetaActionParam, SaiApiP4MetaKey, SaiApiP4MetaTable @dash_p4rt_parser @@ -264,24 +265,31 @@ def __build_sai_attributes_after_parsing(self): # def to_sai(self) -> SaiApi: sai_api = SaiApi(self.name, self.name.replace('_', ' '), self.is_object != "false") - sai_api.p4_meta.tables.append(SaiApiP4MetaTable(self.id)) + sai_api.p4_meta.tables.append(SaiApiP4MetaTable(self.id, self.stage)) self.create_sai_action_enum(sai_api) self.create_sai_structs(sai_api) self.create_sai_attributes(sai_api) self.create_sai_stats(sai_api) + self.create_p4_meta_keys(sai_api) return sai_api - def create_sai_action_enum(self, sai_api: SaiApi) -> None: - # If the table represents an SAI object, it should not have an action enum. - # If the table has only 1 action, we don't need to create the action enum. - if len(self.actions) <= 1 and self.is_object != "false": - # We still need to create the p4 meta action here for generating default action code in libsai. - if len(self.actions) == 1: - sai_api.p4_meta.tables[0].actions["default"] = SaiApiP4MetaAction("default", self.actions[0].id) - return + def create_p4_meta_keys(self, sai_api: SaiApi) -> None: + for key in self.keys: + sai_api.p4_meta.tables[0].keys.append( + SaiApiP4MetaKey( + name=key.name, + id=key.id, + match_type=key.match_type, + field=key.field, + bitwidth=key.bitwidth, + ip_is_v6_field_id=key.ip_is_v6_field_id, + is_object_key=key.is_object_key, + ) + ) + def create_sai_action_enum(self, sai_api: SaiApi) -> None: action_enum_member_value = 0 action_enum_members: List[SaiEnumMember] = [] for action in self.actions: @@ -301,12 +309,24 @@ def create_sai_action_enum(self, sai_api: SaiApi) -> None: ) for action_param in action.params: - p4_meta_action.attr_param_id[action_param.get_sai_name(self.name)] = action_param.id + p4_meta_action.attr_params[action_param.get_sai_name(self.name)] = \ + SaiApiP4MetaActionParam( + id=action_param.id, + field=action_param.field, + bitwidth=action_param.bitwidth, + ip_is_v6_field_id=action_param.ip_is_v6_field_id, + skipattr=action_param.skipattr, + ) sai_api.p4_meta.tables[0].actions[action_enum_member_name] = p4_meta_action action_enum_member_value += 1 + # If the table represents an SAI object, it should not have an action enum. + # If the table has only 1 action, we don't need to create the action enum. + if len(self.actions) <= 1 and self.is_object != "false": + return + action_enum_type_name = f"sai_{self.name.lower()}_action_t" action_enum = SaiEnum( diff --git a/dash-pipeline/SAI/utils/sai_spec/__init__.py b/dash-pipeline/SAI/utils/sai_spec/__init__.py index 3542b4756..d29a2c30f 100644 --- a/dash-pipeline/SAI/utils/sai_spec/__init__.py +++ b/dash-pipeline/SAI/utils/sai_spec/__init__.py @@ -7,4 +7,5 @@ from .sai_struct import SaiStruct from .sai_struct_entry import SaiStructEntry from .sai_attribute import SaiAttribute -from .sai_api_p4_meta import SaiApiP4Meta, SaiApiP4MetaTable, SaiApiP4MetaAction \ No newline at end of file +from .sai_api_p4_meta import SaiApiP4Meta, SaiApiP4MetaTable, \ + SaiApiP4MetaAction, SaiApiP4MetaActionParam, SaiApiP4MetaKey diff --git a/dash-pipeline/SAI/utils/sai_spec/sai_api_p4_meta.py b/dash-pipeline/SAI/utils/sai_spec/sai_api_p4_meta.py index e1279faeb..cfe9fe4cd 100644 --- a/dash-pipeline/SAI/utils/sai_spec/sai_api_p4_meta.py +++ b/dash-pipeline/SAI/utils/sai_spec/sai_api_p4_meta.py @@ -1,16 +1,38 @@ -from typing import Dict, List +from typing import Dict, List, Optional +class SaiApiP4MetaActionParam: + def __init__(self, id: int, field: str, bitwidth: int, + ip_is_v6_field_id: int, skipattr: str): + self.id: int = id + self.field: str = field + self.bitwidth: int = bitwidth + self.ip_is_v6_field_id: int = ip_is_v6_field_id + self.skipattr: str = skipattr + class SaiApiP4MetaAction: def __init__(self, name: str, id: int): self.name: str = name self.id: int = id - self.attr_param_id: Dict[str, int] = {} + self.attr_params: Dict[str, SaiApiP4MetaActionParam] = {} +class SaiApiP4MetaKey: + def __init__(self, name: str, id: int, match_type: str, + field: str, bitwidth: int, ip_is_v6_field_id: int, + is_object_key: bool): + self.name: str = name + self.id: int = id + self.match_type: int = match_type + self.field: str = field + self.bitwidth: int = bitwidth + self.ip_is_v6_field_id: int = ip_is_v6_field_id + self.is_object_key: bool = is_object_key class SaiApiP4MetaTable: - def __init__(self, id: int): + def __init__(self, id: int, stage: Optional[str] = None): self.id: int = id + self.stage: Optional[str] = stage + self.keys: List[SaiApiP4MetaKey] = [] self.actions: Dict[str, SaiApiP4MetaAction] = {} From e16ceb457c9453557f584468c6ed789a8b5a1bfa Mon Sep 17 00:00:00 2001 From: Junhua Zhai Date: Thu, 12 Dec 2024 01:15:00 +0800 Subject: [PATCH 8/8] [sai-gen] Refactor the templates of libsai implementation (#648) Base on https://github.com/sonic-net/DASH/pull/647, refactor the templates of libsai implementation to make it more readable and maintainable. It replaces one single template `saiapi.cpp.j2` with several small templates under directory `SAI/templates/impls`. The changes will not change any generated cpp code for sai api implementation: ``` junhuazhai@junhuazhai-dev-vm:~/workspace/DASH/dash-pipeline$ diff -Nur -x '*.[od]' ~/DASH/dash-pipeline/SAI/lib/ SAI/lib junhuazhai@junhuazhai-dev-vm:~/workspace/DASH/dash-pipeline$ ``` --- dash-pipeline/SAI/sai_api_gen.py | 3 +- .../templates/impls/p4_table_action.cpp.j2 | 73 ++++++++ .../impls/p4_table_entry_match.cpp.j2 | 24 +++ .../impls/p4_table_object_match.cpp.j2 | 66 +++++++ .../SAI/templates/impls/p4_table_util.cpp.j2 | 70 ++++++++ .../templates/impls/sai_api_func_bulk.cpp.j2 | 110 ++++++++++++ .../templates/impls/sai_api_func_quad.cpp.j2 | 161 ++++++++++++++++++ .../templates/impls/sai_api_func_stats.cpp.j2 | 33 ++++ .../SAI/templates/impls/sai_api_group.cpp.j2 | 46 +++++ dash-pipeline/SAI/utils/sai_gen/__init__.py | 3 +- .../SAI/utils/sai_gen/sai_generator.py | 3 - .../SAI/utils/sai_gen/sai_impl_generator.py | 22 +++ 12 files changed, 609 insertions(+), 5 deletions(-) create mode 100644 dash-pipeline/SAI/templates/impls/p4_table_action.cpp.j2 create mode 100644 dash-pipeline/SAI/templates/impls/p4_table_entry_match.cpp.j2 create mode 100644 dash-pipeline/SAI/templates/impls/p4_table_object_match.cpp.j2 create mode 100644 dash-pipeline/SAI/templates/impls/p4_table_util.cpp.j2 create mode 100644 dash-pipeline/SAI/templates/impls/sai_api_func_bulk.cpp.j2 create mode 100644 dash-pipeline/SAI/templates/impls/sai_api_func_quad.cpp.j2 create mode 100644 dash-pipeline/SAI/templates/impls/sai_api_func_stats.cpp.j2 create mode 100644 dash-pipeline/SAI/templates/impls/sai_api_group.cpp.j2 create mode 100644 dash-pipeline/SAI/utils/sai_gen/sai_impl_generator.py diff --git a/dash-pipeline/SAI/sai_api_gen.py b/dash-pipeline/SAI/sai_api_gen.py index b91d05f7f..ac930af78 100755 --- a/dash-pipeline/SAI/sai_api_gen.py +++ b/dash-pipeline/SAI/sai_api_gen.py @@ -16,7 +16,7 @@ from utils.dash_p4 import DashP4SAIExtensions from utils.p4ir import P4IRTree, P4VarRefGraph from utils.sai_spec import SaiSpec - from utils.sai_gen import SAIGenerator, SaiHeaderGenerator + from utils.sai_gen import SAIGenerator, SaiHeaderGenerator, SaiImplGenerator except ImportError as ie: print("Import failed for " + ie.name) exit(1) @@ -75,3 +75,4 @@ # Generate and update all SAI files SAIGenerator(dash_sai_exts).generate() SaiHeaderGenerator(sai_spec).generate() + SaiImplGenerator(sai_spec).generate() diff --git a/dash-pipeline/SAI/templates/impls/p4_table_action.cpp.j2 b/dash-pipeline/SAI/templates/impls/p4_table_action.cpp.j2 new file mode 100644 index 000000000..d0cbfec47 --- /dev/null +++ b/dash-pipeline/SAI/templates/impls/p4_table_action.cpp.j2 @@ -0,0 +1,73 @@ + {% if table.actions|length == 1 %} + {% for name, action in table.actions.items() %} + actionId = {{action.id}}; // {{name}} + //expectedParams = {{ action.attr_params|length }}; + {% endfor %} + {% else %} + // Search the action + for (uint32_t i = 0; i < attr_count; i++) + { + if (SAI_{{ api.name | upper }}_ATTR_ACTION == attr_list[i].id) + { + switch(attr_list[i].value.s32) + { + {% for name, action in table.actions.items() %} + case {{ name }}: + { + actionId = {{action.id}}; + //expectedParams = {{ action.attr_params|length }}; + break; + } + {% endfor %} + default: + DASH_LOG_ERROR("attribute value [%d] %d not supported yet", i, attr_list[i].value.s32); + break; + } + // only one action + break; + } + } + {% endif %} + action->set_action_id(actionId); + + for (uint32_t i = 0; i < attr_count; i++) + { + auto *md = sai_metadata_get_attr_metadata((sai_object_type_t)SAI_OBJECT_TYPE_{{ api.name | upper }}, attr_list[i].id); + + const char* attrName = md ? md->attridname : "unknown"; + + switch(attr_list[i].id) + { + {% set attr_id_list = [] %} + {% for name, action in table.actions.items() %} + {% for param_name, param in action.attr_params.items() %} + {% if param_name in attr_id_list %}{% continue %}{% endif %} + {% do attr_id_list.append( param_name ) %} + {% if param.skipattr == 'true' %} + {% else %} + case {{ param_name }}: + { + auto param = action->add_params(); + param->set_param_id({{param.id}}); + {{param.field}}SetVal(attr_list[i].value, param, {{param.bitwidth}}); + //matchedParams++; + {% if param.ip_is_v6_field_id != 0 %} + { + // set ip_is_v6_field_id field + auto param2 = action->add_params(); + param2->set_param_id({{param.ip_is_v6_field_id}}); + booldataSetVal((attr_list[i].value.ipaddr.addr_family == SAI_IP_ADDR_FAMILY_IPV4) ? 0 : 1, param2, 1); + //matchedParams++; + } + {% endif %} + break; + } + {% endif %} + {% endfor %} + {% endfor %} + default: + DASH_LOG_ERROR("attribute [%d] %d %s not supported yet", i, attr_list[i].id, attrName); + break; + } + } + diff --git a/dash-pipeline/SAI/templates/impls/p4_table_entry_match.cpp.j2 b/dash-pipeline/SAI/templates/impls/p4_table_entry_match.cpp.j2 new file mode 100644 index 000000000..ba5ff7c08 --- /dev/null +++ b/dash-pipeline/SAI/templates/impls/p4_table_entry_match.cpp.j2 @@ -0,0 +1,24 @@ + {% import 'templates/impls/p4_table_util.cpp.j2' as util %} + {% for key in table['keys'] %} + {% set value = 'tableEntry->' ~ key.name|lower %} + { + auto mf = matchActionEntry->add_match(); + mf->set_field_id({{key.id}}); + {% if key.match_type == 'exact' %}{{ util.set_key_exact(key, value) }} + {% elif key.match_type == 'lpm' %}{{ util.set_key_lpm(key, value) }} + {% elif key.match_type == 'ternary' %}{{ util.set_key_ternary(key, value) }} + {% elif key.match_type == 'optional' %}{{ util.set_key_optional(key, value) }} + {% elif key.match_type == 'list' %}{{ util.set_key_list(key, value) }} + {% elif key.match_type == 'range_list' %}{{ util.set_key_range_list(key, value) }} + {% endif %} + } + {% if key.ip_is_v6_field_id != 0 %} + { + // set ip_is_v6_field_id field + auto mf = matchActionEntry->add_match(); + mf->set_field_id({{key.ip_is_v6_field_id}}); + auto mf_exact = mf->mutable_exact(); + booldataSetVal(({{value}}.addr_family == SAI_IP_ADDR_FAMILY_IPV4) ? 0 : 1, mf_exact, 1); + } + {% endif %} + {% endfor %} diff --git a/dash-pipeline/SAI/templates/impls/p4_table_object_match.cpp.j2 b/dash-pipeline/SAI/templates/impls/p4_table_object_match.cpp.j2 new file mode 100644 index 000000000..d6419e5f3 --- /dev/null +++ b/dash-pipeline/SAI/templates/impls/p4_table_object_match.cpp.j2 @@ -0,0 +1,66 @@ + {% import 'templates/impls/p4_table_util.cpp.j2' as util %} + {% 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(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++) + { + auto *md = sai_metadata_get_attr_metadata((sai_object_type_t)SAI_OBJECT_TYPE_{{ api.name | upper }}, attr_list[i].id); + + const char* attrName = md ? md->attridname : "unknown"; + + switch(attr_list[i].id) + { + {% for key in table['keys'] %} + {% if not key.is_object_key %} + {% set value = 'attr_list[i].value' %} + case SAI_{{ api.name | upper }}_ATTR_{{ key.name | upper }}: + { + auto mf = matchActionEntry->add_match(); + mf->set_field_id({{key.id}}); + {% filter indent(8, True) %} + {% if key.match_type == 'exact' %}{{ util.set_key_in_attr_exact(key, value) }} + {% elif key.match_type == 'lpm' %}{{ util.set_key_lpm(key, value) }} + {% elif key.match_type == 'ternary' %}{{ util.set_key_in_attr_ternary(api, key, value) }} + {% elif key.match_type == 'optional' %}{{ util.set_key_optional(key, value) }} + {% elif key.match_type == 'list' %}{{ util.set_key_list(key, value) }} + {% elif key.match_type == 'range_list' %}{{ util.set_key_range_list(key, value) }} + {% endif %} + {% endfilter %} + {% if key.ip_is_v6_field_id != 0 %} + { + // set ip_is_v6_field_id field + auto mf = matchActionEntry->add_match(); + mf->set_field_id({{key.ip_is_v6_field_id}}); + auto mf_exact = mf->mutable_exact(); + booldataSetVal(({{value}}.ipaddr.addr_family == SAI_IP_ADDR_FAMILY_IPV4) ? 0 : 1, mf_exact, 1); + } + {% 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 %} + // Table has non lpm ternary keys - add priority field + case SAI_{{ api.name | upper }}_ATTR_PRIORITY: + { + matchActionEntry->set_priority(attr_list[i].value.u32); + break; + } + {% endif %} + {% endif %} + default: + DASH_LOG_ERROR("attribute [%d] %d %s not supported yet", i, attr_list[i].id, attrName); + break; + } + } + diff --git a/dash-pipeline/SAI/templates/impls/p4_table_util.cpp.j2 b/dash-pipeline/SAI/templates/impls/p4_table_util.cpp.j2 new file mode 100644 index 000000000..a610d7f13 --- /dev/null +++ b/dash-pipeline/SAI/templates/impls/p4_table_util.cpp.j2 @@ -0,0 +1,70 @@ +{% macro set_key_exact(key, value) %} + auto mf_exact = mf->mutable_exact(); + {% if key.field in ['ipaddr','mac'] or key.bitwidth in [24] %} + {{key.field}}SetVal({{value}}, mf_exact, {{key.bitwidth}}); + {%- else %} + {{key.field}}SetVal(static_cast({{value}}), mf_exact, {{key.bitwidth}}); + {%- endif %} +{%- endmacro -%} + +{% macro set_key_in_attr_exact(key, value) %} + auto mf_exact = mf->mutable_exact(); + {{key.field}}SetVal({{value}}, mf_exact, {{key.bitwidth}}); +{%- endmacro -%} + +{% macro set_key_lpm(key, value) %} + {% if key.field == 'ipPrefix' %} + if (getPrefixLength({{value}}) == 0) + { + // https://github.com/p4lang/PI/blob/24e0a3c08c964e36d235973556b90e0ae922b894/proto/frontend/src/device_mgr.cpp#L2242-L2246 + DASH_LOG_WARN("Invalid reprsentation of 'don't care' LPM match, omit match field instead of using a prefix length of 0"); + return SAI_STATUS_SUCCESS; + } + {% endif %} + auto mf_lpm = mf->mutable_lpm(); + {{key.field}}SetVal({{value}}, mf_lpm, {{key.bitwidth}}); +{%- endmacro -%} + +{% macro set_key_in_attr_ternary(api, key, value) %} + auto mf_ternary = mf->mutable_ternary(); + {{key.field}}SetVal({{value}}, mf_ternary, {{key.bitwidth}}); + auto mask = getMaskAttr(SAI_{{ api.name | upper }}_ATTR_{{ key.name | upper }}_MASK, attr_count, attr_list); + assert(mask && "SAI_{{ api.name | upper }}_ATTR_{{ key.name | upper }}_MASK isn't provided"); + {{key.field}}SetMask(mask->value, mf_ternary, {{key.bitwidth}}); +{%- endmacro -%} + +{% macro set_key_ternary(key, value) %} + auto mf_ternary = mf->mutable_ternary(); + {{key.field}}SetVal({{value}}, mf_ternary, {{key.bitwidth}}); + {{key.field}}SetMask({{value}}_mask, mf_ternary, {{key.bitwidth}}); + matchActionEntry->set_priority(tableEntry->priority); +{%- endmacro -%} + +{% macro set_key_optional(key, value) %} + auto mf_optional = mf->mutable_optional(); + {{key.field}}SetVal({{value}}, mf_optional, {{key.bitwidth}}); +{%- endmacro -%} + +{% macro set_key_list(key, value) %} + // BMv2 doesn't support "list" match type, and we are using "optional" match in v1model as our implementation. + // Hence, here we only take the first item from the list and program it as optional match. + assert({{value}}.{{key.field}}.count == 1 && "BMv2 only supports one item in list match type"); + auto mf_optional = mf->mutable_optional(); + sai_attribute_value_t attr_val; + {% if key.field == 'ipprefixlist' %} + attr_val.ipaddr.addr_family = {{value}}.ipprefixlist.list[0].addr_family; + attr_val.ipaddr.addr = {{value}}.ipprefixlist.list[0].addr; + ipaddrSetVal(attr_val, mf_optional, {{key.bitwidth}}); + {%- else %} + attr_val.{{ key.field | replace('list', '') }} = {{value}}.{{key.field}}.list[0]; + {{ key.field | replace('list', '') }}SetVal(attr_val, mf_optional, {{key.bitwidth}}); + {%- endif %} +{%- endmacro -%} + +{% macro set_key_range_list(key, value) %} + // BMv2 doesn't support "range_list" match type, and we are using "optional" match in v1model as our implementation. + // Hence, here we only take the first item from the list and program the range start as optional match. + assert(attr_list[i].value.{{key.field}}.count == 1 && "BMv2 only supports one item in list match type"); + auto mf_optional = mf->mutable_optional(); + {{ key.field | replace('rangelist', '') }}SetVal(attr_list[i].value.{{key.field}}.list[0].min, mf_optional, {{key.bitwidth}}); +{%- endmacro -%} diff --git a/dash-pipeline/SAI/templates/impls/sai_api_func_bulk.cpp.j2 b/dash-pipeline/SAI/templates/impls/sai_api_func_bulk.cpp.j2 new file mode 100644 index 000000000..3f42a54af --- /dev/null +++ b/dash-pipeline/SAI/templates/impls/sai_api_func_bulk.cpp.j2 @@ -0,0 +1,110 @@ +{% if api.is_object == True %} +static sai_status_t dash_sai_create_{{ api.name }}s( + _In_ sai_object_id_t switch_id, + _In_ uint32_t object_count, + _In_ const uint32_t *attr_count, + _In_ const sai_attribute_t **attr_list, + _In_ sai_bulk_op_error_mode_t mode, + _Out_ sai_object_id_t *object_id, + _Out_ sai_status_t *object_statuses) +{ + DASH_LOG_ENTER(); + return dash::DashSai::bulk_create_objects(dash_sai_create_{{ api.name }}, switch_id, object_count, attr_count, attr_list, mode, object_id, object_statuses); +} + +static sai_status_t dash_sai_remove_{{ api.name }}s( + _In_ uint32_t object_count, + _In_ const sai_object_id_t *object_id, + _In_ sai_bulk_op_error_mode_t mode, + _Out_ sai_status_t *object_statuses) +{ + DASH_LOG_ENTER(); + return dash::DashSai::bulk_remove_objects(dash_sai_remove_{{ api.name }}, object_count, object_id, mode, object_statuses); +} +{% else %} +static sai_status_t dash_sai_create_{{ api.name | replace("entry", "entries") }}( + _In_ uint32_t object_count, + _In_ const sai_{{ api.name }}_t *{{ api.name }}, + _In_ const uint32_t *attr_count, + _In_ const sai_attribute_t **attr_list, + _In_ sai_bulk_op_error_mode_t mode, + _Out_ sai_status_t *object_statuses) +{ + DASH_LOG_ENTER(); + + sai_status_t agg_status = SAI_STATUS_SUCCESS; + + for (uint32_t i = 0; i < object_count; i++) + { + object_statuses[i] = dash_sai_create_{{ api.name }}(&{{ api.name }}[i], attr_count[i], attr_list[i]); + + if (object_statuses[i] != SAI_STATUS_SUCCESS) + { + agg_status = SAI_STATUS_FAILURE; + } + + if (agg_status == SAI_STATUS_FAILURE && mode == SAI_BULK_OP_ERROR_MODE_STOP_ON_ERROR) + { + return agg_status; + } + } + + return agg_status; +} + +static sai_status_t dash_sai_remove_{{ api.name | replace("entry", "entries") }}( + _In_ uint32_t object_count, + _In_ const sai_{{ api.name }}_t *{{ api.name }}, + _In_ sai_bulk_op_error_mode_t mode, + _Out_ sai_status_t *object_statuses) +{ + DASH_LOG_ENTER(); + + sai_status_t agg_status = SAI_STATUS_SUCCESS; + + for (uint32_t i = 0; i < object_count; i++) + { + object_statuses[i] = dash_sai_remove_{{ api.name }}(&{{ api.name }}[i]); + + if (object_statuses[i] != SAI_STATUS_SUCCESS) + { + agg_status = SAI_STATUS_FAILURE; + } + + if (agg_status == SAI_STATUS_FAILURE && mode == SAI_BULK_OP_ERROR_MODE_STOP_ON_ERROR) + { + return agg_status; + } + } + + return agg_status; +} +{% if api.name == 'route_entry' %} + +static sai_status_t dash_sai_set_{{ api.name | replace("entry", "entries") }}_attribute( + _In_ uint32_t object_count, + _In_ const sai_route_entry_t *route_entry, + _In_ const sai_attribute_t *attr_list, + _In_ sai_bulk_op_error_mode_t mode, + _Out_ sai_status_t *object_statuses) +{ + DASH_LOG_ENTER(); + assert(0 && "sai_set_{{ api.name | replace("entry", "entries") }}_attribute NYI"); + return SAI_STATUS_FAILURE; +} + +static sai_status_t dash_sai_get_{{ api.name | replace("entry", "entries") }}_attribute( + _In_ uint32_t object_count, + _In_ const sai_route_entry_t *route_entry, + _In_ const uint32_t *attr_count, + _Inout_ sai_attribute_t **attr_list, + _In_ sai_bulk_op_error_mode_t mode, + _Out_ sai_status_t *object_statuses) +{ + DASH_LOG_ENTER(); + assert(0 && "sai_get_{{ api.name | replace("entry", "entries") }}_attribute NYI"); + return SAI_STATUS_FAILURE; +} +{% endif %} +{% endif %} + diff --git a/dash-pipeline/SAI/templates/impls/sai_api_func_quad.cpp.j2 b/dash-pipeline/SAI/templates/impls/sai_api_func_quad.cpp.j2 new file mode 100644 index 000000000..249d0209b --- /dev/null +++ b/dash-pipeline/SAI/templates/impls/sai_api_func_quad.cpp.j2 @@ -0,0 +1,161 @@ +static sai_status_t dash_sai_create_{{ api.name }}( +{% if api.is_object %} + _Out_ sai_object_id_t *{{ api.name }}_id, + _In_ sai_object_id_t switch_id, +{% else %} + _In_ const sai_{{ api.name }}_t *{{ api.name }}, +{% endif %} + _In_ uint32_t attr_count, + _In_ const sai_attribute_t *attr_list) +{ + DASH_LOG_ENTER(); + + auto attrs = dash::DashSai::populateDefaultAttributes((sai_object_type_t)SAI_OBJECT_TYPE_{{ api.name | upper }}, attr_count, attr_list); + attr_count = (uint32_t)attrs.size(); + attr_list = attrs.data(); + +{% if api.is_object %} + std::shared_ptr matchActionEntry; + pi_p4_id_t tableId = 0; + // There shall be one and only one action_type + p4::v1::TableAction* entry = nullptr; + p4::v1::Action* action = nullptr; + //auto expectedParams = 0; + //auto matchedParams = 0; + sai_object_id_t objId = 0; + // Search the action + pi_p4_id_t actionId = 0; + + {% for table in api.p4_meta.tables %} + {% if table.stage != None %} + // For stage {{ table.stage }} + {% endif %} + matchActionEntry = std::make_shared(); + tableId = {{table.id}}; + entry = matchActionEntry->mutable_action(); + action = entry->mutable_action(); + //expectedParams = 0; + //matchedParams = 0; + objId = dashSai->getNextObjectId((sai_object_type_t)SAI_OBJECT_TYPE_{{ api.name | upper }}); + + if (objId == SAI_NULL_OBJECT_ID) + { + DASH_LOG_ERROR("getNextObjectId failed for SAI_OBJECT_TYPE_{{ api.name | upper }}"); + // TODO clean resources + return SAI_STATUS_FAILURE; + } + + matchActionEntry->set_table_id(tableId); + + {% include 'templates/impls/p4_table_object_match.cpp.j2' %} + + // If there is only one action, simply set it. + // Else, search in the attrs. + {% include 'templates/impls/p4_table_action.cpp.j2' %} + + //assert((matchedParams == expectedParams)); + + //if (matchedParams != expectedParams) { + // goto ErrRet; + //} + if (false == dashSai->insertInTable(matchActionEntry, objId)) { + goto ErrRet; + } + + {% endfor %} + + *{{ api.name }}_id = objId; + return SAI_STATUS_SUCCESS; +ErrRet: + dashSai->removeFromTable(*{{ api.name }}_id); + return SAI_STATUS_FAILURE; +{% else %} + std::shared_ptr matchActionEntry = std::make_shared(); + pi_p4_id_t tableId = {{table.id}}; + matchActionEntry->set_table_id(tableId); + auto tableEntry = {{ api.name }}; + // There shall be one and only one action_type + auto entry = matchActionEntry->mutable_action(); + auto action = entry->mutable_action(); + //auto expectedParams = 0; + //auto matchedParams = 0; + pi_p4_id_t actionId; + grpc::StatusCode retCode; + + {% include 'templates/impls/p4_table_entry_match.cpp.j2' %} + + + {% include 'templates/impls/p4_table_action.cpp.j2' %} + + //assert((matchedParams == expectedParams)); + + //if (matchedParams != expectedParams) { + // goto ErrRet; + //} + // TODO: ternaly needs to set priority + retCode = dashSai->mutateTableEntry(matchActionEntry, p4::v1::Update_Type_INSERT); + + if (grpc::StatusCode::OK == retCode) + { + return SAI_STATUS_SUCCESS; + } +ErrRet: + return SAI_STATUS_FAILURE; +{% endif %} +} + +static sai_status_t dash_sai_remove_{{ api.name }}( + {% include 'templates/headers/sai_api_param_object_id.j2' %}) +{ +{% if api.is_object %} + DASH_LOG_ENTER(); + + if (dashSai->removeFromTable({{ api.name }}_id)) + { + return SAI_STATUS_SUCCESS; + } + + return SAI_STATUS_FAILURE; +{% else %} + DASH_LOG_ENTER(); + + std::shared_ptr matchActionEntry = std::make_shared(); + pi_p4_id_t tableId = {{table.id}}; + matchActionEntry->set_table_id(tableId); + auto tableEntry = {{ api.name }}; + grpc::StatusCode retCode; + + {% include 'templates/impls/p4_table_entry_match.cpp.j2' %} + + retCode = dashSai->mutateTableEntry(matchActionEntry, p4::v1::Update_Type_DELETE); + + if (grpc::StatusCode::OK == retCode) + { + return SAI_STATUS_SUCCESS; + } + +ErrRet: + + return SAI_STATUS_FAILURE; +{% endif %} +} + +static sai_status_t dash_sai_set_{{ api.name }}_attribute( + {% include 'templates/headers/sai_api_param_object_id.j2' %}, + _In_ const sai_attribute_t *attr) +{ + DASH_LOG_ENTER(); + assert(0 && "sai_set_{{ api.name }}_attribute NYI"); + return SAI_STATUS_FAILURE; +} + +static sai_status_t dash_sai_get_{{ api.name }}_attribute( + {% include 'templates/headers/sai_api_param_object_id.j2' %}, + _In_ uint32_t attr_count, + _Inout_ sai_attribute_t *attr_list) +{ + DASH_LOG_ENTER(); + assert(0 && "sai_get_{{ api.name }}_attribute NYI"); + return SAI_STATUS_FAILURE; +} + diff --git a/dash-pipeline/SAI/templates/impls/sai_api_func_stats.cpp.j2 b/dash-pipeline/SAI/templates/impls/sai_api_func_stats.cpp.j2 new file mode 100644 index 000000000..8645d3e1c --- /dev/null +++ b/dash-pipeline/SAI/templates/impls/sai_api_func_stats.cpp.j2 @@ -0,0 +1,33 @@ +static sai_status_t dash_sai_get_{{ api.name }}_stats( + {% include 'templates/headers/sai_api_param_object_id.j2' %}, + _In_ uint32_t number_of_counters, + _In_ const sai_stat_id_t *counter_ids, + _Out_ uint64_t *counters) +{ + DASH_LOG_ENTER(); + assert(0 && "sai_get_{{ api.name }}_stats NYI"); + return SAI_STATUS_FAILURE; +} + +static sai_status_t dash_sai_get_{{ api.name }}_stats_ext( + {% include 'templates/headers/sai_api_param_object_id.j2' %}, + _In_ uint32_t number_of_counters, + _In_ const sai_stat_id_t *counter_ids, + _In_ sai_stats_mode_t mode, + _Out_ uint64_t *counters) +{ + DASH_LOG_ENTER(); + assert(0 && "sai_get_{{ api.name }}_stats_ext NYI"); + return SAI_STATUS_FAILURE; +} + +static sai_status_t dash_sai_clear_{{ api.name }}_stats( + {% include 'templates/headers/sai_api_param_object_id.j2' %}, + _In_ uint32_t number_of_counters, + _In_ const sai_stat_id_t *counter_ids) +{ + DASH_LOG_ENTER(); + assert(0 && "sai_clear_{{ api.name }}_stats NYI"); + return SAI_STATUS_FAILURE; +} + diff --git a/dash-pipeline/SAI/templates/impls/sai_api_group.cpp.j2 b/dash-pipeline/SAI/templates/impls/sai_api_group.cpp.j2 new file mode 100644 index 000000000..42ab5ba24 --- /dev/null +++ b/dash-pipeline/SAI/templates/impls/sai_api_group.cpp.j2 @@ -0,0 +1,46 @@ +#include "utils.h" +#include "saiimpl.h" + +extern "C" { +#include "saimetadata.h" +} + +using namespace dash::utils; + + +{% for api in api_group.sai_apis %} +{% set table = api.p4_meta.tables[0] -%} +{% include 'templates/impls/sai_api_func_quad.cpp.j2' %} + +{% if api.stats | length > 0 %} +{% include 'templates/impls/sai_api_func_stats.cpp.j2' %} + +{% endif %} +{% include 'templates/impls/sai_api_func_bulk.cpp.j2' %} + +{% endfor %} +/* TODO [cs] Generate .h file for _impl to use within sai_api_query() */ +sai_{{ api_group.name }}_api_t dash_sai_{{ api_group.name }}_api_impl = { +{% for api in api_group.sai_apis %} + .create_{{ api.name }} = dash_sai_create_{{ api.name }}, + .remove_{{ api.name }} = dash_sai_remove_{{ api.name }}, + .set_{{ api.name }}_attribute = dash_sai_set_{{ api.name }}_attribute, + .get_{{ api.name }}_attribute = dash_sai_get_{{ api.name }}_attribute, +{% if api.stats | length > 0 %} + .get_{{ api.name }}_stats = dash_sai_get_{{ api.name }}_stats, + .get_{{ api.name }}_stats_ext = dash_sai_get_{{ api.name }}_stats_ext, + .clear_{{ api.name }}_stats = dash_sai_clear_{{ api.name }}_stats, +{% endif %} +{% if api.is_object %} + .create_{{ api.name }}s = dash_sai_create_{{ api.name }}s, + .remove_{{ api.name }}s = dash_sai_remove_{{ api.name }}s, +{% else %} + .create_{{ api.name | replace("entry", "entries") }} = dash_sai_create_{{ api.name | replace("entry", "entries") }}, + .remove_{{ api.name | replace("entry", "entries") }} = dash_sai_remove_{{ api.name | replace("entry", "entries") }}, +{% endif %} +{% if api.name == 'route_entry' %} + .set_{{ api.name | replace("entry", "entries") }}_attribute = dash_sai_set_{{ api.name | replace("entry", "entries") }}_attribute, + .get_{{ api.name | replace("entry", "entries") }}_attribute = dash_sai_get_{{ api.name | replace("entry", "entries") }}_attribute, +{% endif %} +{% endfor %} +}; diff --git a/dash-pipeline/SAI/utils/sai_gen/__init__.py b/dash-pipeline/SAI/utils/sai_gen/__init__.py index 71d9e9a12..00b2a56a0 100644 --- a/dash-pipeline/SAI/utils/sai_gen/__init__.py +++ b/dash-pipeline/SAI/utils/sai_gen/__init__.py @@ -1,4 +1,5 @@ from .sai_file_updater import SAIFileUpdater from .sai_template_renderer import SAITemplateRenderer from .sai_generator import SAIGenerator -from .sai_header_generator import SaiHeaderGenerator \ No newline at end of file +from .sai_header_generator import SaiHeaderGenerator +from .sai_impl_generator import SaiImplGenerator diff --git a/dash-pipeline/SAI/utils/sai_gen/sai_generator.py b/dash-pipeline/SAI/utils/sai_gen/sai_generator.py index 455cad4e7..d3b072e69 100644 --- a/dash-pipeline/SAI/utils/sai_gen/sai_generator.py +++ b/dash-pipeline/SAI/utils/sai_gen/sai_generator.py @@ -44,9 +44,6 @@ def generate_sai_api_extensions(self, sai_api: DashP4TableGroup) -> None: if sai_api.api_type != "underlay": self.generate_dash_sai_definitions_for_api(unique_sai_api) - # Generate SAI API implementation for all APIs. - self.generate_sai_impl_file_for_api(sai_api) - def generate_dash_sai_definitions_for_api(self, sai_api: DashP4TableGroup) -> None: # SAI header file sai_header_file_name = ( diff --git a/dash-pipeline/SAI/utils/sai_gen/sai_impl_generator.py b/dash-pipeline/SAI/utils/sai_gen/sai_impl_generator.py new file mode 100644 index 000000000..5cd1d1680 --- /dev/null +++ b/dash-pipeline/SAI/utils/sai_gen/sai_impl_generator.py @@ -0,0 +1,22 @@ +from utils.sai_spec import SaiSpec, SaiApiGroup +from .sai_template_renderer import SAITemplateRenderer + + +class SaiImplGenerator: + def __init__(self, sai_spec: SaiSpec): + self.sai_spec: SaiSpec = sai_spec + + def generate(self) -> None: + print("\nGenerating SAI API implementation for all APIs ...") + + for api_group in self.sai_spec.api_groups: + self._generate_sai_api_group(api_group) + + def _generate_sai_api_group(self, api_group: SaiApiGroup) -> None: + print(f"Generating SAI API implementation for API group: {api_group.name} ...") + + # SAI implementation file + sai_impl_file_name = f"sai{api_group.name.replace('_', '')}.cpp" + SAITemplateRenderer("templates/impls/sai_api_group.cpp.j2").render_to_file( + f"lib/{sai_impl_file_name}", api_group = api_group + )