From 36ee4763bd864c18fe3238c427b1a529c686fb1a Mon Sep 17 00:00:00 2001 From: kishanps Date: Tue, 19 Dec 2023 13:43:20 -0800 Subject: [PATCH 1/6] [SAIP4] Remove yellow actions and add annotations specifying meter type to direct meters, Add multicast reference annotations to p4 programs, Increase the guaranteed size of QoS and mirror & redirect ACL tables, Add match on ipv6_dst in mirror_and_redirect to middleblock as well, Add entry restrictions of mirror_and_redirect to middleblock as well & Add dst_ipv4 match to mirror_and_redirect. --- sai_p4/fixed/packet_rewrites.p4 | 6 +- sai_p4/fixed/routing.p4 | 3 +- sai_p4/instantiations/google/acl_ingress.p4 | 53 +++++------ .../google/fabric_border_router.p4info.pb.txt | 7 +- .../google/middleblock.p4info.pb.txt | 46 ++++++++-- .../google/minimum_guaranteed_sizes.p4 | 6 ++ sai_p4/instantiations/google/sai_pd.proto | 12 ++- .../instantiations/google/tor.p4info.pb.txt | 50 +++++----- .../google/unioned_p4info.pb.txt | 92 ++++++++++--------- 9 files changed, 161 insertions(+), 114 deletions(-) diff --git a/sai_p4/fixed/packet_rewrites.p4 b/sai_p4/fixed/packet_rewrites.p4 index 2bf3dec3..d8dd277b 100644 --- a/sai_p4/fixed/packet_rewrites.p4 +++ b/sai_p4/fixed/packet_rewrites.p4 @@ -64,12 +64,10 @@ control multicast_rewrites(inout local_metadata_t local_metadata, table multicast_router_interface_table { key = { multicast_replica_port : exact - // TODO: Add this once supported by PDPI and its customers. - // @referenced_by(multicast_group_table, replica.port) + @referenced_by(builtin::multicast_group_table, replica.port) @id(1); multicast_replica_instance : exact - // TODO: Add this once supported by PDPI and its customers. - // @referenced_by(multicast_group_table, replica.instance) + @referenced_by(builtin::multicast_group_table, replica.instance) @id(2); } actions = { diff --git a/sai_p4/fixed/routing.p4 b/sai_p4/fixed/routing.p4 index ba04c247..4acae4af 100644 --- a/sai_p4/fixed/routing.p4 +++ b/sai_p4/fixed/routing.p4 @@ -175,8 +175,7 @@ control routing_lookup(in headers_t headers, ") action set_multicast_group_id( @id(1) - // TODO: Add this once supported by PDPI and its customers. - // @refers_to(multicast_group_table, multicast_group_id) + @refers_to(builtin::multicast_group_table, multicast_group_id) multicast_group_id_t multicast_group_id) { standard_metadata.mcast_grp = multicast_group_id; } diff --git a/sai_p4/instantiations/google/acl_ingress.p4 b/sai_p4/instantiations/google/acl_ingress.p4 index f41434f5..91ff70ba 100644 --- a/sai_p4/instantiations/google/acl_ingress.p4 +++ b/sai_p4/instantiations/google/acl_ingress.p4 @@ -24,9 +24,11 @@ control acl_ingress(in headers_t headers, bool cancel_copy = false; @id(ACL_INGRESS_METER_ID) + @mode(single_rate_two_color) direct_meter(MeterType.bytes) acl_ingress_meter; @id(ACL_INGRESS_QOS_METER_ID) + @mode(single_rate_two_color) direct_meter(MeterType.bytes) acl_ingress_qos_meter; @id(ACL_INGRESS_COUNTER_ID) @@ -53,7 +55,6 @@ control acl_ingress(in headers_t headers, } #else @sai_action(SAI_PACKET_ACTION_COPY, SAI_PACKET_COLOR_GREEN) - @sai_action(SAI_PACKET_ACTION_FORWARD, SAI_PACKET_COLOR_YELLOW) @sai_action(SAI_PACKET_ACTION_FORWARD, SAI_PACKET_COLOR_RED) action acl_copy(@sai_action_param(QOS_QUEUE) @id(1) qos_queue_t qos_queue) { acl_ingress_counter.count(); @@ -73,7 +74,6 @@ control acl_ingress(in headers_t headers, @sai_action(SAI_PACKET_ACTION_TRAP) #else @sai_action(SAI_PACKET_ACTION_TRAP, SAI_PACKET_COLOR_GREEN) - @sai_action(SAI_PACKET_ACTION_DROP, SAI_PACKET_COLOR_YELLOW) @sai_action(SAI_PACKET_ACTION_DROP, SAI_PACKET_COLOR_RED) #endif action acl_trap(@sai_action_param(QOS_QUEUE) @id(1) qos_queue_t qos_queue) { @@ -94,7 +94,6 @@ control acl_ingress(in headers_t headers, } #else @sai_action(SAI_PACKET_ACTION_FORWARD, SAI_PACKET_COLOR_GREEN) - @sai_action(SAI_PACKET_ACTION_DROP, SAI_PACKET_COLOR_YELLOW) @sai_action(SAI_PACKET_ACTION_DROP, SAI_PACKET_COLOR_RED) action acl_forward() { acl_ingress_meter.read(local_metadata.color); @@ -124,7 +123,6 @@ control acl_ingress(in headers_t headers, @id(ACL_INGRESS_SET_QOS_QUEUE_AND_CANCEL_COPY_ABOVE_RATE_LIMIT_ACTION_ID) @sai_action(SAI_PACKET_ACTION_FORWARD, SAI_PACKET_COLOR_GREEN) - @sai_action(SAI_PACKET_ACTION_COPY_CANCEL, SAI_PACKET_COLOR_YELLOW) @sai_action(SAI_PACKET_ACTION_COPY_CANCEL, SAI_PACKET_COLOR_RED) // TODO: Rename qos queue to cpu queue, as per action below. action set_qos_queue_and_cancel_copy_above_rate_limit( @@ -143,7 +141,6 @@ control acl_ingress(in headers_t headers, // set depending on packet color. @id(ACL_INGRESS_SET_CPU_AND_MULTICAST_QUEUES_AND_DENY_ABOVE_RATE_LIMIT_ACTION_ID) @sai_action(SAI_PACKET_ACTION_FORWARD, SAI_PACKET_COLOR_GREEN) - @sai_action(SAI_PACKET_ACTION_DENY, SAI_PACKET_COLOR_YELLOW) @sai_action(SAI_PACKET_ACTION_DENY, SAI_PACKET_COLOR_RED) // TODO: Remove @unsupported annotation. @unsupported @@ -151,9 +148,8 @@ control acl_ingress(in headers_t headers, @id(1) @sai_action_param(QOS_QUEUE) qos_queue_t cpu_queue, @id(2) @sai_action_param(MULTICAST_QOS_QUEUE, SAI_PACKET_COLOR_GREEN) qos_queue_t green_multicast_queue, - @id(3) @sai_action_param(MULTICAST_QOS_QUEUE, SAI_PACKET_COLOR_YELLOW) - @sai_action_param(MULTICAST_QOS_QUEUE, SAI_PACKET_COLOR_RED) - qos_queue_t red_and_yellow_multicast_queue) { + @id(3) @sai_action_param(MULTICAST_QOS_QUEUE, SAI_PACKET_COLOR_RED) + qos_queue_t red_multicast_queue) { acl_ingress_qos_meter.read(local_metadata.color); // We model the behavior for GREEN packes only here. // TODO: Branch on color and model behavior for all colors. @@ -163,7 +159,6 @@ control acl_ingress(in headers_t headers, // they are not copied to the CPU. @id(ACL_INGRESS_SET_CPU_QUEUE_AND_DENY_ABOVE_RATE_LIMIT_ACTION_ID) @sai_action(SAI_PACKET_ACTION_FORWARD, SAI_PACKET_COLOR_GREEN) - @sai_action(SAI_PACKET_ACTION_DENY, SAI_PACKET_COLOR_YELLOW) @sai_action(SAI_PACKET_ACTION_DENY, SAI_PACKET_COLOR_RED) action set_cpu_queue_and_deny_above_rate_limit( @id(1) @sai_action_param(QOS_QUEUE) qos_queue_t cpu_queue) { @@ -391,7 +386,7 @@ control acl_ingress(in headers_t headers, const default_action = NoAction; meters = acl_ingress_qos_meter; counters = acl_ingress_qos_counter; - size = ACL_INGRESS_TABLE_MINIMUM_GUARANTEED_SIZE; + size = ACL_INGRESS_QOS_TABLE_MINIMUM_GUARANTEED_SIZE; } @p4runtime_role(P4RUNTIME_ROLE_SDN_CONTROLLER) @@ -471,10 +466,10 @@ control acl_ingress(in headers_t headers, @id(ACL_INGRESS_MIRROR_AND_REDIRECT_TABLE_ID) @sai_acl(INGRESS) @p4runtime_role(P4RUNTIME_ROLE_SDN_CONTROLLER) -#if defined(SAI_INSTANTIATION_TOR) @entry_restriction(" // Only allow IP field matches for IP packets. - is_ipv6::mask != 0 -> is_ipv6 == 1; + dst_ip::mask != 0 -> is_ipv4 == 1; + dst_ipv6::mask != 0 -> is_ipv6 == 1; // Forbid illegal combinations of IP_TYPE fields. is_ip::mask != 0 -> (is_ipv4::mask == 0 && is_ipv6::mask == 0); is_ipv4::mask != 0 -> (is_ip::mask == 0 && is_ipv6::mask == 0); @@ -483,7 +478,6 @@ control acl_ingress(in headers_t headers, is_ipv4::mask != 0 -> (is_ipv4 == 1); is_ipv6::mask != 0 -> (is_ipv6 == 1); ") -#endif table acl_ingress_mirror_and_redirect_table { key = { #if defined(SAI_INSTANTIATION_TOR) @@ -492,6 +486,17 @@ control acl_ingress(in headers_t headers, @sai_field(SAI_ACL_TABLE_ATTR_FIELD_IN_PORT) @id(1); + local_metadata.acl_metadata : ternary + @name("acl_metadata") + @sai_field(SAI_ACL_TABLE_ATTR_FIELD_ACL_USER_META) + @id(6); + + local_metadata.vlan_id : ternary + @name("vlan_id") + @sai_field(SAI_ACL_TABLE_ATTR_FIELD_OUTER_VLAN_ID) + @id(7); +#endif + headers.ipv4.isValid() || headers.ipv6.isValid() : optional @name("is_ip") @sai_field(SAI_ACL_TABLE_ATTR_FIELD_ACL_IP_TYPE/IP) @@ -507,6 +512,12 @@ control acl_ingress(in headers_t headers, @sai_field(SAI_ACL_TABLE_ATTR_FIELD_ACL_IP_TYPE/IPV6ANY) @id(4); + headers.ipv4.dst_addr : ternary + @name("dst_ip") + @sai_field(SAI_ACL_TABLE_ATTR_FIELD_DST_IP) + @format(IPV4_ADDRESS) + @id(10); + headers.ipv6.dst_addr[127:64] : ternary @name("dst_ipv6") @composite_field( @@ -515,22 +526,6 @@ control acl_ingress(in headers_t headers, @format(IPV6_ADDRESS) @id(5); - local_metadata.acl_metadata : ternary - @name("acl_metadata") - @sai_field(SAI_ACL_TABLE_ATTR_FIELD_ACL_USER_META) - @id(6); -#endif - - // This field is technically only needed on ToR and only included - // for middleblock because at least 1 match field without `@unsupported` - // annotation is required. - // TODO: Make this field TOR-only once the - // middleblock match fields are no longer `@unsupported`. - local_metadata.vlan_id : ternary - @name("vlan_id") - @sai_field(SAI_ACL_TABLE_ATTR_FIELD_OUTER_VLAN_ID) - @id(7); - local_metadata.vrf_id : optional @name("vrf_id") @sai_field(SAI_ACL_TABLE_ATTR_FIELD_VRF_ID) diff --git a/sai_p4/instantiations/google/fabric_border_router.p4info.pb.txt b/sai_p4/instantiations/google/fabric_border_router.p4info.pb.txt index da20e1d3..a371bcc9 100644 --- a/sai_p4/instantiations/google/fabric_border_router.p4info.pb.txt +++ b/sai_p4/instantiations/google/fabric_border_router.p4info.pb.txt @@ -857,6 +857,7 @@ tables { match_fields { id: 1 name: "multicast_replica_port" + annotations: "@referenced_by(builtin : : multicast_group_table , replica . port)" match_type: EXACT type_name { name: "port_id_t" @@ -865,6 +866,7 @@ tables { match_fields { id: 2 name: "multicast_replica_instance" + annotations: "@referenced_by(builtin : : multicast_group_table , replica . instance)" bitwidth: 16 match_type: EXACT } @@ -1127,6 +1129,7 @@ actions { params { id: 1 name: "multicast_group_id" + annotations: "@refers_to(builtin : : multicast_group_table , multicast_group_id)" bitwidth: 16 } } @@ -1136,7 +1139,6 @@ actions { name: "ingress.acl_ingress.acl_copy" alias: "acl_copy" annotations: "@sai_action(SAI_PACKET_ACTION_COPY , SAI_PACKET_COLOR_GREEN)" - annotations: "@sai_action(SAI_PACKET_ACTION_FORWARD , SAI_PACKET_COLOR_YELLOW)" annotations: "@sai_action(SAI_PACKET_ACTION_FORWARD , SAI_PACKET_COLOR_RED)" } params { @@ -1154,7 +1156,6 @@ actions { name: "ingress.acl_ingress.acl_trap" alias: "acl_trap" annotations: "@sai_action(SAI_PACKET_ACTION_TRAP , SAI_PACKET_COLOR_GREEN)" - annotations: "@sai_action(SAI_PACKET_ACTION_DROP , SAI_PACKET_COLOR_YELLOW)" annotations: "@sai_action(SAI_PACKET_ACTION_DROP , SAI_PACKET_COLOR_RED)" } params { @@ -1172,7 +1173,6 @@ actions { name: "ingress.acl_ingress.acl_forward" alias: "acl_forward" annotations: "@sai_action(SAI_PACKET_ACTION_FORWARD , SAI_PACKET_COLOR_GREEN)" - annotations: "@sai_action(SAI_PACKET_ACTION_DROP , SAI_PACKET_COLOR_YELLOW)" annotations: "@sai_action(SAI_PACKET_ACTION_DROP , SAI_PACKET_COLOR_RED)" } } @@ -1519,6 +1519,7 @@ direct_meters { id: 352321792 name: "ingress.acl_ingress.acl_ingress_meter" alias: "acl_ingress_meter" + annotations: "@mode(single_rate_two_color)" } spec { unit: BYTES diff --git a/sai_p4/instantiations/google/middleblock.p4info.pb.txt b/sai_p4/instantiations/google/middleblock.p4info.pb.txt index 2d55d77a..26b9a239 100755 --- a/sai_p4/instantiations/google/middleblock.p4info.pb.txt +++ b/sai_p4/instantiations/google/middleblock.p4info.pb.txt @@ -553,12 +553,43 @@ tables { alias: "acl_ingress_mirror_and_redirect_table" annotations: "@sai_acl(INGRESS)" annotations: "@p4runtime_role(\"sdn_controller\")" + annotations: "@entry_restriction(\"\n // Only allow IP field matches for IP packets.\n dst_ip::mask != 0 -> is_ipv4 == 1;\n dst_ipv6::mask != 0 -> is_ipv6 == 1;\n // Forbid illegal combinations of IP_TYPE fields.\n is_ip::mask != 0 -> (is_ipv4::mask == 0 && is_ipv6::mask == 0);\n is_ipv4::mask != 0 -> (is_ip::mask == 0 && is_ipv6::mask == 0);\n is_ipv6::mask != 0 -> (is_ip::mask == 0 && is_ipv4::mask == 0);\n // Forbid unsupported combinations of IP_TYPE fields.\n is_ipv4::mask != 0 -> (is_ipv4 == 1);\n is_ipv6::mask != 0 -> (is_ipv6 == 1);\n \")" } match_fields { - id: 7 - name: "vlan_id" - annotations: "@sai_field(SAI_ACL_TABLE_ATTR_FIELD_OUTER_VLAN_ID)" - bitwidth: 12 + id: 2 + name: "is_ip" + annotations: "@sai_field(SAI_ACL_TABLE_ATTR_FIELD_ACL_IP_TYPE / IP)" + bitwidth: 1 + match_type: OPTIONAL + } + match_fields { + id: 3 + name: "is_ipv4" + annotations: "@sai_field(SAI_ACL_TABLE_ATTR_FIELD_ACL_IP_TYPE / IPV4ANY)" + bitwidth: 1 + match_type: OPTIONAL + } + match_fields { + id: 4 + name: "is_ipv6" + annotations: "@sai_field(SAI_ACL_TABLE_ATTR_FIELD_ACL_IP_TYPE / IPV6ANY)" + bitwidth: 1 + match_type: OPTIONAL + } + match_fields { + id: 10 + name: "dst_ip" + annotations: "@sai_field(SAI_ACL_TABLE_ATTR_FIELD_DST_IP)" + annotations: "@format(IPV4_ADDRESS)" + bitwidth: 32 + match_type: TERNARY + } + match_fields { + id: 5 + name: "dst_ipv6" + annotations: "@composite_field(@ sai_field ( SAI_ACL_TABLE_ATTR_FIELD_DST_IPV6_WORD3 ) , @ sai_field ( SAI_ACL_TABLE_ATTR_FIELD_DST_IPV6_WORD2 ))" + annotations: "@format(IPV6_ADDRESS)" + bitwidth: 64 match_type: TERNARY } match_fields { @@ -920,6 +951,7 @@ tables { match_fields { id: 1 name: "multicast_replica_port" + annotations: "@referenced_by(builtin : : multicast_group_table , replica . port)" match_type: EXACT type_name { name: "port_id_t" @@ -928,6 +960,7 @@ tables { match_fields { id: 2 name: "multicast_replica_instance" + annotations: "@referenced_by(builtin : : multicast_group_table , replica . instance)" bitwidth: 16 match_type: EXACT } @@ -1110,6 +1143,7 @@ actions { params { id: 1 name: "multicast_group_id" + annotations: "@refers_to(builtin : : multicast_group_table , multicast_group_id)" bitwidth: 16 } } @@ -1119,7 +1153,6 @@ actions { name: "ingress.acl_ingress.acl_copy" alias: "acl_copy" annotations: "@sai_action(SAI_PACKET_ACTION_COPY , SAI_PACKET_COLOR_GREEN)" - annotations: "@sai_action(SAI_PACKET_ACTION_FORWARD , SAI_PACKET_COLOR_YELLOW)" annotations: "@sai_action(SAI_PACKET_ACTION_FORWARD , SAI_PACKET_COLOR_RED)" } params { @@ -1137,7 +1170,6 @@ actions { name: "ingress.acl_ingress.acl_trap" alias: "acl_trap" annotations: "@sai_action(SAI_PACKET_ACTION_TRAP , SAI_PACKET_COLOR_GREEN)" - annotations: "@sai_action(SAI_PACKET_ACTION_DROP , SAI_PACKET_COLOR_YELLOW)" annotations: "@sai_action(SAI_PACKET_ACTION_DROP , SAI_PACKET_COLOR_RED)" } params { @@ -1155,7 +1187,6 @@ actions { name: "ingress.acl_ingress.acl_forward" alias: "acl_forward" annotations: "@sai_action(SAI_PACKET_ACTION_FORWARD , SAI_PACKET_COLOR_GREEN)" - annotations: "@sai_action(SAI_PACKET_ACTION_DROP , SAI_PACKET_COLOR_YELLOW)" annotations: "@sai_action(SAI_PACKET_ACTION_DROP , SAI_PACKET_COLOR_RED)" } } @@ -1522,6 +1553,7 @@ direct_meters { id: 352321792 name: "ingress.acl_ingress.acl_ingress_meter" alias: "acl_ingress_meter" + annotations: "@mode(single_rate_two_color)" } spec { unit: BYTES diff --git a/sai_p4/instantiations/google/minimum_guaranteed_sizes.p4 b/sai_p4/instantiations/google/minimum_guaranteed_sizes.p4 index bc6d6156..eba3881e 100644 --- a/sai_p4/instantiations/google/minimum_guaranteed_sizes.p4 +++ b/sai_p4/instantiations/google/minimum_guaranteed_sizes.p4 @@ -89,9 +89,15 @@ #define ACL_TOR_PRE_INGRESS_TABLE_MINIMUM_GUARANTEED_SIZE 127 +#define ACL_INGRESS_QOS_TABLE_MINIMUM_GUARANTEED_SIZE 511 + #define ACL_INGRESS_COUNTING_TABLE_MINIMUM_GUARANTEED_SIZE 255 +#ifdef SAI_INSTANTIATION_EXPERIMENTAL_TOR +#define ACL_INGRESS_MIRROR_AND_REDIRECT_TABLE_MINIMUM_GUARANTEED_SIZE 511 +#else #define ACL_INGRESS_MIRROR_AND_REDIRECT_TABLE_MINIMUM_GUARANTEED_SIZE 255 +#endif #define ACL_EGRESS_TABLE_MINIMUM_GUARANTEED_SIZE 127 diff --git a/sai_p4/instantiations/google/sai_pd.proto b/sai_p4/instantiations/google/sai_pd.proto index 12448963..e1265b39 100755 --- a/sai_p4/instantiations/google/sai_pd.proto +++ b/sai_p4/instantiations/google/sai_pd.proto @@ -724,7 +724,8 @@ message AclIngressSecurityTableEntry { // Table entry restrictions: // ## Only allow IP field matches for IP packets. -// is_ipv6::mask != 0 -> is_ipv6 == 1; +// dst_ip::mask != 0 -> is_ipv4 == 1; +// dst_ipv6::mask != 0 -> is_ipv6 == 1; // ## Forbid illegal combinations of IP_TYPE fields. // is_ip::mask != 0 -> (is_ipv4::mask == 0 && is_ipv6::mask == 0); // is_ipv4::mask != 0 -> (is_ip::mask == 0 && is_ipv6::mask == 0); @@ -745,7 +746,8 @@ message AclIngressMirrorAndRedirectTableEntry { Optional vrf_id = 8; // optional match / Format::STRING // CAUTION: This match field is not (yet) supported. Optional ipmc_table_hit = - 9; // optional match / Format::HEX_STRING / 1 bits + 9; // optional match / Format::HEX_STRING / 1 bits + Ternary dst_ip = 10; // ternary match / Format::IPV4 } Match match = 1; message Action { @@ -948,9 +950,9 @@ message SetCpuQueueAction { // CAUTION: This action is not (yet) supported. message SetCpuAndMulticastQueuesAndDenyAboveRateLimitAction { - string cpu_queue = 1; // Format::STRING - string green_multicast_queue = 2; // Format::STRING - string red_and_yellow_multicast_queue = 3; // Format::STRING + string cpu_queue = 1; // Format::STRING + string green_multicast_queue = 2; // Format::STRING + string red_multicast_queue = 3; // Format::STRING } message RedirectToNexthopAction { diff --git a/sai_p4/instantiations/google/tor.p4info.pb.txt b/sai_p4/instantiations/google/tor.p4info.pb.txt index 060b95d8..4aa316ef 100644 --- a/sai_p4/instantiations/google/tor.p4info.pb.txt +++ b/sai_p4/instantiations/google/tor.p4info.pb.txt @@ -788,7 +788,7 @@ tables { const_default_action_id: 21257015 direct_resource_ids: 318767367 direct_resource_ids: 352321794 - size: 256 + size: 511 } tables { preamble { @@ -797,7 +797,7 @@ tables { alias: "acl_ingress_mirror_and_redirect_table" annotations: "@sai_acl(INGRESS)" annotations: "@p4runtime_role(\"sdn_controller\")" - annotations: "@entry_restriction(\"\n // Only allow IP field matches for IP packets.\n is_ipv6::mask != 0 -> is_ipv6 == 1;\n // Forbid illegal combinations of IP_TYPE fields.\n is_ip::mask != 0 -> (is_ipv4::mask == 0 && is_ipv6::mask == 0);\n is_ipv4::mask != 0 -> (is_ip::mask == 0 && is_ipv6::mask == 0);\n is_ipv6::mask != 0 -> (is_ip::mask == 0 && is_ipv4::mask == 0);\n // Forbid unsupported combinations of IP_TYPE fields.\n is_ipv4::mask != 0 -> (is_ipv4 == 1);\n is_ipv6::mask != 0 -> (is_ipv6 == 1);\n \")" + annotations: "@entry_restriction(\"\n // Only allow IP field matches for IP packets.\n dst_ip::mask != 0 -> is_ipv4 == 1;\n dst_ipv6::mask != 0 -> is_ipv6 == 1;\n // Forbid illegal combinations of IP_TYPE fields.\n is_ip::mask != 0 -> (is_ipv4::mask == 0 && is_ipv6::mask == 0);\n is_ipv4::mask != 0 -> (is_ip::mask == 0 && is_ipv6::mask == 0);\n is_ipv6::mask != 0 -> (is_ip::mask == 0 && is_ipv4::mask == 0);\n // Forbid unsupported combinations of IP_TYPE fields.\n is_ipv4::mask != 0 -> (is_ipv4 == 1);\n is_ipv6::mask != 0 -> (is_ipv6 == 1);\n \")" } match_fields { id: 1 @@ -808,6 +808,20 @@ tables { name: "port_id_t" } } + match_fields { + id: 6 + name: "acl_metadata" + annotations: "@sai_field(SAI_ACL_TABLE_ATTR_FIELD_ACL_USER_META)" + bitwidth: 8 + match_type: TERNARY + } + match_fields { + id: 7 + name: "vlan_id" + annotations: "@sai_field(SAI_ACL_TABLE_ATTR_FIELD_OUTER_VLAN_ID)" + bitwidth: 12 + match_type: TERNARY + } match_fields { id: 2 name: "is_ip" @@ -829,6 +843,14 @@ tables { bitwidth: 1 match_type: OPTIONAL } + match_fields { + id: 10 + name: "dst_ip" + annotations: "@sai_field(SAI_ACL_TABLE_ATTR_FIELD_DST_IP)" + annotations: "@format(IPV4_ADDRESS)" + bitwidth: 32 + match_type: TERNARY + } match_fields { id: 5 name: "dst_ipv6" @@ -837,20 +859,6 @@ tables { bitwidth: 64 match_type: TERNARY } - match_fields { - id: 6 - name: "acl_metadata" - annotations: "@sai_field(SAI_ACL_TABLE_ATTR_FIELD_ACL_USER_META)" - bitwidth: 8 - match_type: TERNARY - } - match_fields { - id: 7 - name: "vlan_id" - annotations: "@sai_field(SAI_ACL_TABLE_ATTR_FIELD_OUTER_VLAN_ID)" - bitwidth: 12 - match_type: TERNARY - } match_fields { id: 8 name: "vrf_id" @@ -1128,6 +1136,7 @@ tables { match_fields { id: 1 name: "multicast_replica_port" + annotations: "@referenced_by(builtin : : multicast_group_table , replica . port)" match_type: EXACT type_name { name: "port_id_t" @@ -1136,6 +1145,7 @@ tables { match_fields { id: 2 name: "multicast_replica_instance" + annotations: "@referenced_by(builtin : : multicast_group_table , replica . instance)" bitwidth: 16 match_type: EXACT } @@ -1477,6 +1487,7 @@ actions { params { id: 1 name: "multicast_group_id" + annotations: "@refers_to(builtin : : multicast_group_table , multicast_group_id)" bitwidth: 16 } } @@ -1543,7 +1554,6 @@ actions { name: "ingress.acl_ingress.set_qos_queue_and_cancel_copy_above_rate_limit" alias: "set_qos_queue_and_cancel_copy_above_rate_limit" annotations: "@sai_action(SAI_PACKET_ACTION_FORWARD , SAI_PACKET_COLOR_GREEN)" - annotations: "@sai_action(SAI_PACKET_ACTION_COPY_CANCEL , SAI_PACKET_COLOR_YELLOW)" annotations: "@sai_action(SAI_PACKET_ACTION_COPY_CANCEL , SAI_PACKET_COLOR_RED)" } params { @@ -1561,7 +1571,6 @@ actions { name: "ingress.acl_ingress.set_cpu_and_multicast_queues_and_deny_above_rate_limit" alias: "set_cpu_and_multicast_queues_and_deny_above_rate_limit" annotations: "@sai_action(SAI_PACKET_ACTION_FORWARD , SAI_PACKET_COLOR_GREEN)" - annotations: "@sai_action(SAI_PACKET_ACTION_DENY , SAI_PACKET_COLOR_YELLOW)" annotations: "@sai_action(SAI_PACKET_ACTION_DENY , SAI_PACKET_COLOR_RED)" annotations: "@unsupported" } @@ -1583,8 +1592,7 @@ actions { } params { id: 3 - name: "red_and_yellow_multicast_queue" - annotations: "@sai_action_param(MULTICAST_QOS_QUEUE , SAI_PACKET_COLOR_YELLOW)" + name: "red_multicast_queue" annotations: "@sai_action_param(MULTICAST_QOS_QUEUE , SAI_PACKET_COLOR_RED)" type_name { name: "qos_queue_t" @@ -1597,7 +1605,6 @@ actions { name: "ingress.acl_ingress.set_cpu_queue_and_deny_above_rate_limit" alias: "set_cpu_queue_and_deny_above_rate_limit" annotations: "@sai_action(SAI_PACKET_ACTION_FORWARD , SAI_PACKET_COLOR_GREEN)" - annotations: "@sai_action(SAI_PACKET_ACTION_DENY , SAI_PACKET_COLOR_YELLOW)" annotations: "@sai_action(SAI_PACKET_ACTION_DENY , SAI_PACKET_COLOR_RED)" } params { @@ -2015,6 +2022,7 @@ direct_meters { id: 352321794 name: "ingress.acl_ingress.acl_ingress_qos_meter" alias: "acl_ingress_qos_meter" + annotations: "@mode(single_rate_two_color)" } spec { unit: BYTES diff --git a/sai_p4/instantiations/google/unioned_p4info.pb.txt b/sai_p4/instantiations/google/unioned_p4info.pb.txt index 10769ef4..d8c81f91 100644 --- a/sai_p4/instantiations/google/unioned_p4info.pb.txt +++ b/sai_p4/instantiations/google/unioned_p4info.pb.txt @@ -867,6 +867,7 @@ tables { match_fields { id: 1 name: "multicast_replica_port" + annotations: "@referenced_by(builtin : : multicast_group_table , replica . port)" match_type: EXACT type_name { name: "port_id_t" @@ -875,6 +876,7 @@ tables { match_fields { id: 2 name: "multicast_replica_instance" + annotations: "@referenced_by(builtin : : multicast_group_table , replica . instance)" bitwidth: 16 match_type: EXACT } @@ -997,13 +999,43 @@ tables { alias: "acl_ingress_mirror_and_redirect_table" annotations: "@sai_acl(INGRESS)" annotations: "@p4runtime_role(\"sdn_controller\")" - annotations: "@entry_restriction(\"\n // Only allow IP field matches for IP packets.\n is_ipv6::mask != 0 -> is_ipv6 == 1;\n // Forbid illegal combinations of IP_TYPE fields.\n is_ip::mask != 0 -> (is_ipv4::mask == 0 && is_ipv6::mask == 0);\n is_ipv4::mask != 0 -> (is_ip::mask == 0 && is_ipv6::mask == 0);\n is_ipv6::mask != 0 -> (is_ip::mask == 0 && is_ipv4::mask == 0);\n // Forbid unsupported combinations of IP_TYPE fields.\n is_ipv4::mask != 0 -> (is_ipv4 == 1);\n is_ipv6::mask != 0 -> (is_ipv6 == 1);\n \")" + annotations: "@entry_restriction(\"\n // Only allow IP field matches for IP packets.\n dst_ip::mask != 0 -> is_ipv4 == 1;\n dst_ipv6::mask != 0 -> is_ipv6 == 1;\n // Forbid illegal combinations of IP_TYPE fields.\n is_ip::mask != 0 -> (is_ipv4::mask == 0 && is_ipv6::mask == 0);\n is_ipv4::mask != 0 -> (is_ip::mask == 0 && is_ipv6::mask == 0);\n is_ipv6::mask != 0 -> (is_ip::mask == 0 && is_ipv4::mask == 0);\n // Forbid unsupported combinations of IP_TYPE fields.\n is_ipv4::mask != 0 -> (is_ipv4 == 1);\n is_ipv6::mask != 0 -> (is_ipv6 == 1);\n \")" } match_fields { - id: 7 - name: "vlan_id" - annotations: "@sai_field(SAI_ACL_TABLE_ATTR_FIELD_OUTER_VLAN_ID)" - bitwidth: 12 + id: 2 + name: "is_ip" + annotations: "@sai_field(SAI_ACL_TABLE_ATTR_FIELD_ACL_IP_TYPE / IP)" + bitwidth: 1 + match_type: OPTIONAL + } + match_fields { + id: 3 + name: "is_ipv4" + annotations: "@sai_field(SAI_ACL_TABLE_ATTR_FIELD_ACL_IP_TYPE / IPV4ANY)" + bitwidth: 1 + match_type: OPTIONAL + } + match_fields { + id: 4 + name: "is_ipv6" + annotations: "@sai_field(SAI_ACL_TABLE_ATTR_FIELD_ACL_IP_TYPE / IPV6ANY)" + bitwidth: 1 + match_type: OPTIONAL + } + match_fields { + id: 10 + name: "dst_ip" + annotations: "@sai_field(SAI_ACL_TABLE_ATTR_FIELD_DST_IP)" + annotations: "@format(IPV4_ADDRESS)" + bitwidth: 32 + match_type: TERNARY + } + match_fields { + id: 5 + name: "dst_ipv6" + annotations: "@composite_field(@ sai_field ( SAI_ACL_TABLE_ATTR_FIELD_DST_IPV6_WORD3 ) , @ sai_field ( SAI_ACL_TABLE_ATTR_FIELD_DST_IPV6_WORD2 ))" + annotations: "@format(IPV6_ADDRESS)" + bitwidth: 64 match_type: TERNARY } match_fields { @@ -1033,35 +1065,6 @@ tables { name: "port_id_t" } } - match_fields { - id: 2 - name: "is_ip" - annotations: "@sai_field(SAI_ACL_TABLE_ATTR_FIELD_ACL_IP_TYPE / IP)" - bitwidth: 1 - match_type: OPTIONAL - } - match_fields { - id: 3 - name: "is_ipv4" - annotations: "@sai_field(SAI_ACL_TABLE_ATTR_FIELD_ACL_IP_TYPE / IPV4ANY)" - bitwidth: 1 - match_type: OPTIONAL - } - match_fields { - id: 4 - name: "is_ipv6" - annotations: "@sai_field(SAI_ACL_TABLE_ATTR_FIELD_ACL_IP_TYPE / IPV6ANY)" - bitwidth: 1 - match_type: OPTIONAL - } - match_fields { - id: 5 - name: "dst_ipv6" - annotations: "@composite_field(@ sai_field ( SAI_ACL_TABLE_ATTR_FIELD_DST_IPV6_WORD3 ) , @ sai_field ( SAI_ACL_TABLE_ATTR_FIELD_DST_IPV6_WORD2 ))" - annotations: "@format(IPV6_ADDRESS)" - bitwidth: 64 - match_type: TERNARY - } match_fields { id: 6 name: "acl_metadata" @@ -1069,6 +1072,13 @@ tables { bitwidth: 8 match_type: TERNARY } + match_fields { + id: 7 + name: "vlan_id" + annotations: "@sai_field(SAI_ACL_TABLE_ATTR_FIELD_OUTER_VLAN_ID)" + bitwidth: 12 + match_type: TERNARY + } action_refs { id: 16777476 annotations: "@proto_id(1)" @@ -1431,7 +1441,7 @@ tables { const_default_action_id: 21257015 direct_resource_ids: 318767367 direct_resource_ids: 352321794 - size: 256 + size: 511 } tables { preamble { @@ -1729,6 +1739,7 @@ actions { params { id: 1 name: "multicast_group_id" + annotations: "@refers_to(builtin : : multicast_group_table , multicast_group_id)" bitwidth: 16 } } @@ -1738,7 +1749,6 @@ actions { name: "ingress.acl_ingress.acl_copy" alias: "acl_copy" annotations: "@sai_action(SAI_PACKET_ACTION_COPY , SAI_PACKET_COLOR_GREEN)" - annotations: "@sai_action(SAI_PACKET_ACTION_FORWARD , SAI_PACKET_COLOR_YELLOW)" annotations: "@sai_action(SAI_PACKET_ACTION_FORWARD , SAI_PACKET_COLOR_RED)" annotations: "@sai_action(SAI_PACKET_ACTION_COPY)" } @@ -1757,7 +1767,6 @@ actions { name: "ingress.acl_ingress.acl_trap" alias: "acl_trap" annotations: "@sai_action(SAI_PACKET_ACTION_TRAP , SAI_PACKET_COLOR_GREEN)" - annotations: "@sai_action(SAI_PACKET_ACTION_DROP , SAI_PACKET_COLOR_YELLOW)" annotations: "@sai_action(SAI_PACKET_ACTION_DROP , SAI_PACKET_COLOR_RED)" annotations: "@sai_action(SAI_PACKET_ACTION_TRAP)" } @@ -1776,7 +1785,6 @@ actions { name: "ingress.acl_ingress.acl_forward" alias: "acl_forward" annotations: "@sai_action(SAI_PACKET_ACTION_FORWARD , SAI_PACKET_COLOR_GREEN)" - annotations: "@sai_action(SAI_PACKET_ACTION_DROP , SAI_PACKET_COLOR_YELLOW)" annotations: "@sai_action(SAI_PACKET_ACTION_DROP , SAI_PACKET_COLOR_RED)" annotations: "@sai_action(SAI_PACKET_ACTION_FORWARD)" } @@ -2137,7 +2145,6 @@ actions { name: "ingress.acl_ingress.set_qos_queue_and_cancel_copy_above_rate_limit" alias: "set_qos_queue_and_cancel_copy_above_rate_limit" annotations: "@sai_action(SAI_PACKET_ACTION_FORWARD , SAI_PACKET_COLOR_GREEN)" - annotations: "@sai_action(SAI_PACKET_ACTION_COPY_CANCEL , SAI_PACKET_COLOR_YELLOW)" annotations: "@sai_action(SAI_PACKET_ACTION_COPY_CANCEL , SAI_PACKET_COLOR_RED)" } params { @@ -2155,7 +2162,6 @@ actions { name: "ingress.acl_ingress.set_cpu_and_multicast_queues_and_deny_above_rate_limit" alias: "set_cpu_and_multicast_queues_and_deny_above_rate_limit" annotations: "@sai_action(SAI_PACKET_ACTION_FORWARD , SAI_PACKET_COLOR_GREEN)" - annotations: "@sai_action(SAI_PACKET_ACTION_DENY , SAI_PACKET_COLOR_YELLOW)" annotations: "@sai_action(SAI_PACKET_ACTION_DENY , SAI_PACKET_COLOR_RED)" annotations: "@unsupported" } @@ -2177,8 +2183,7 @@ actions { } params { id: 3 - name: "red_and_yellow_multicast_queue" - annotations: "@sai_action_param(MULTICAST_QOS_QUEUE , SAI_PACKET_COLOR_YELLOW)" + name: "red_multicast_queue" annotations: "@sai_action_param(MULTICAST_QOS_QUEUE , SAI_PACKET_COLOR_RED)" type_name { name: "qos_queue_t" @@ -2191,7 +2196,6 @@ actions { name: "ingress.acl_ingress.set_cpu_queue_and_deny_above_rate_limit" alias: "set_cpu_queue_and_deny_above_rate_limit" annotations: "@sai_action(SAI_PACKET_ACTION_FORWARD , SAI_PACKET_COLOR_GREEN)" - annotations: "@sai_action(SAI_PACKET_ACTION_DENY , SAI_PACKET_COLOR_YELLOW)" annotations: "@sai_action(SAI_PACKET_ACTION_DENY , SAI_PACKET_COLOR_RED)" } params { @@ -2369,6 +2373,7 @@ direct_meters { id: 352321792 name: "ingress.acl_ingress.acl_ingress_meter" alias: "acl_ingress_meter" + annotations: "@mode(single_rate_two_color)" } spec { unit: BYTES @@ -2380,6 +2385,7 @@ direct_meters { id: 352321794 name: "ingress.acl_ingress.acl_ingress_qos_meter" alias: "acl_ingress_qos_meter" + annotations: "@mode(single_rate_two_color)" } spec { unit: BYTES From 89e3d533e40ba023b2a52eeb661197225fc806e9 Mon Sep 17 00:00:00 2001 From: kishanps Date: Tue, 2 Jan 2024 15:28:50 -0800 Subject: [PATCH 2/6] [SAIP4] Rename mirror_with_psamp_encapsulation to mirror_with_ipfix_encapsulation to reflect change in SAI mirror session type to IPFIX. --- sai_p4/fixed/ids.h | 2 +- sai_p4/fixed/mirroring.p4 | 14 +++++++------- .../google/fabric_border_router.p4info.pb.txt | 4 ++-- .../google/middleblock.p4info.pb.txt | 4 ++-- .../google/minimum_guaranteed_sizes.p4 | 6 +++--- sai_p4/instantiations/google/sai_pd.proto | 4 ++-- .../google/test_tools/test_entries.cc | 6 +++--- .../google/test_tools/test_entries.h | 2 +- .../google/tests/sai_p4_bmv2_vlan_test.cc | 4 ++-- sai_p4/instantiations/google/tor.p4info.pb.txt | 6 +++--- sai_p4/instantiations/google/unioned_p4info.pb.txt | 6 +++--- 11 files changed, 29 insertions(+), 29 deletions(-) diff --git a/sai_p4/fixed/ids.h b/sai_p4/fixed/ids.h index c8825c41..80c6b392 100644 --- a/sai_p4/fixed/ids.h +++ b/sai_p4/fixed/ids.h @@ -55,7 +55,7 @@ #define ROUTING_SET_MULTICAST_SRC_MAC_ACTION_ID 0x01000019 // 16777241 #define MIRRORING_MIRROR_AS_IPV4_ERSPAN_ACTION_ID 0x01000007 // 16777223 #define CLONING_INGRESS_CLONE_ACTION_ID 0x0100001C // 16777244 -#define CLONING_MIRROR_WITH_PSAMP_ENCAPSULATION_ACTION_ID \ +#define CLONING_MIRROR_WITH_IPFIX_ENCAPSULATION_ACTION_ID \ 0x0100001D // 16777245 #define L3_ADMIT_ACTION_ID 0x01000008 // 16777224 #define MIRRORING_SET_PRE_SESSION_ACTION_ID 0x01000009 // 16777225 diff --git a/sai_p4/fixed/mirroring.p4 b/sai_p4/fixed/mirroring.p4 index beb57057..af564128 100644 --- a/sai_p4/fixed/mirroring.p4 +++ b/sai_p4/fixed/mirroring.p4 @@ -39,16 +39,16 @@ control mirror_session_lookup(inout headers_t headers, } // Sets - // * SAI_MIRROR_SESSION_ATTR_TYPE to SAI_MIRROR_SESSION_TYPE_PSAMP - // * SAI_MIRROR_SESSION_ATTR_PSAMP_ENCAPSULATION_TYPE to - // SAI_PSAMP_ENCAPSULATION_TYPE_EXTENDED + // * SAI_MIRROR_SESSION_ATTR_TYPE to SAI_MIRROR_SESSION_TYPE_IPFIX + // * SAI_MIRROR_SESSION_ATTR_IPFIX_ENCAPSULATION_TYPE to + // SAI_IPFIX_ENCAPSULATION_TYPE_EXTENDED // * SAI_MIRROR_SESSION_ATTR_MONITOR_PORT to `monitor_port` - @id(CLONING_MIRROR_WITH_PSAMP_ENCAPSULATION_ACTION_ID) - // TODO: Add params needed for PSAMP mirroring. + @id(CLONING_MIRROR_WITH_IPFIX_ENCAPSULATION_ACTION_ID) + // TODO: Add params needed for IPFIX mirroring. // TODO: Remove unsupported annotation once the switch stack // supports this table. @unsupported - action mirror_with_psamp_encapsulation(@id(1) port_id_t monitor_port) { + action mirror_with_ipfix_encapsulation(@id(1) port_id_t monitor_port) { local_metadata.mirror_egress_port = monitor_port; } @@ -63,7 +63,7 @@ control mirror_session_lookup(inout headers_t headers, } actions = { @proto_id(1) mirror_as_ipv4_erspan; - @proto_id(2) mirror_with_psamp_encapsulation; + @proto_id(2) mirror_with_ipfix_encapsulation; @defaultonly NoAction; } diff --git a/sai_p4/instantiations/google/fabric_border_router.p4info.pb.txt b/sai_p4/instantiations/google/fabric_border_router.p4info.pb.txt index a371bcc9..6f2eb7d2 100644 --- a/sai_p4/instantiations/google/fabric_border_router.p4info.pb.txt +++ b/sai_p4/instantiations/google/fabric_border_router.p4info.pb.txt @@ -1422,8 +1422,8 @@ actions { actions { preamble { id: 16777245 - name: "ingress.mirror_session_lookup.mirror_with_psamp_encapsulation" - alias: "mirror_with_psamp_encapsulation" + name: "ingress.mirror_session_lookup.mirror_with_ipfix_encapsulation" + alias: "mirror_with_ipfix_encapsulation" annotations: "@unsupported" } params { diff --git a/sai_p4/instantiations/google/middleblock.p4info.pb.txt b/sai_p4/instantiations/google/middleblock.p4info.pb.txt index 26b9a239..1ffc0403 100755 --- a/sai_p4/instantiations/google/middleblock.p4info.pb.txt +++ b/sai_p4/instantiations/google/middleblock.p4info.pb.txt @@ -1467,8 +1467,8 @@ actions { actions { preamble { id: 16777245 - name: "ingress.mirror_session_lookup.mirror_with_psamp_encapsulation" - alias: "mirror_with_psamp_encapsulation" + name: "ingress.mirror_session_lookup.mirror_with_ipfix_encapsulation" + alias: "mirror_with_ipfix_encapsulation" annotations: "@unsupported" } params { diff --git a/sai_p4/instantiations/google/minimum_guaranteed_sizes.p4 b/sai_p4/instantiations/google/minimum_guaranteed_sizes.p4 index eba3881e..4f10e692 100644 --- a/sai_p4/instantiations/google/minimum_guaranteed_sizes.p4 +++ b/sai_p4/instantiations/google/minimum_guaranteed_sizes.p4 @@ -54,6 +54,8 @@ #define ROUTING_IPV4_MULTICAST_TABLE_MINIMUM_GUARANTEED_SIZE 1600 #define ROUTING_IPV6_MULTICAST_TABLE_MINIMUM_GUARANTEED_SIZE 1600 +#define ROUTING_MULTICAST_ROUTER_INTERFACE_TABLE_MINIMUM_GUARANTEED_SIZE 128 + // The maximum number of wcmp groups. #define WCMP_GROUP_TABLE_MINIMUM_GUARANTEED_SIZE 3968 #define WCMP_GROUP_TABLE_MINIMUM_GUARANTEED_SIZE_TOR 960 @@ -85,15 +87,13 @@ #define ACL_DEFAULT_PRE_INGRESS_TABLE_MINIMUM_GUARANTEED_SIZE 254 - #define ACL_TOR_PRE_INGRESS_TABLE_MINIMUM_GUARANTEED_SIZE 127 - #define ACL_INGRESS_QOS_TABLE_MINIMUM_GUARANTEED_SIZE 511 #define ACL_INGRESS_COUNTING_TABLE_MINIMUM_GUARANTEED_SIZE 255 -#ifdef SAI_INSTANTIATION_EXPERIMENTAL_TOR +#ifdef SAI_INSTANTIATION_TOR #define ACL_INGRESS_MIRROR_AND_REDIRECT_TABLE_MINIMUM_GUARANTEED_SIZE 511 #else #define ACL_INGRESS_MIRROR_AND_REDIRECT_TABLE_MINIMUM_GUARANTEED_SIZE 255 diff --git a/sai_p4/instantiations/google/sai_pd.proto b/sai_p4/instantiations/google/sai_pd.proto index e1265b39..9a264df1 100755 --- a/sai_p4/instantiations/google/sai_pd.proto +++ b/sai_p4/instantiations/google/sai_pd.proto @@ -161,7 +161,7 @@ message MirrorSessionTableEntry { oneof action { MirrorAsIpv4ErspanAction mirror_as_ipv4_erspan = 1; // CAUTION: This action is not (yet) supported. - MirrorWithPsampEncapsulationAction mirror_with_psamp_encapsulation = 2; + MirrorWithIpfixEncapsulationAction mirror_with_ipfix_encapsulation = 2; } } Action action = 2; @@ -892,7 +892,7 @@ message SetPortAndSrcMacAndVlanIdAction { } // CAUTION: This action is not (yet) supported. -message MirrorWithPsampEncapsulationAction { +message MirrorWithIpfixEncapsulationAction { string monitor_port = 1; // Format::STRING } diff --git a/sai_p4/instantiations/google/test_tools/test_entries.cc b/sai_p4/instantiations/google/test_tools/test_entries.cc index 5a7b15b9..3e17ccca 100644 --- a/sai_p4/instantiations/google/test_tools/test_entries.cc +++ b/sai_p4/instantiations/google/test_tools/test_entries.cc @@ -567,11 +567,11 @@ EntryBuilder& EntryBuilder::AddMirrorSessionTableEntry( *pd_entry.mutable_mirror_session_table_entry(); mirror_session_entry.mutable_match()->set_mirror_session_id( params.mirror_session_id); - sai::MirrorWithPsampEncapsulationAction& action = + sai::MirrorWithIpfixEncapsulationAction& action = *mirror_session_entry.mutable_action() - ->mutable_mirror_with_psamp_encapsulation(); + ->mutable_mirror_with_ipfix_encapsulation(); action.set_monitor_port(params.mirror_egress_port); - // TODO: Fill in PSAMP params in table entry's action. + // TODO: Fill in IPFIX params in table entry's action. *entries_.add_entries() = std::move(pd_entry); return *this; diff --git a/sai_p4/instantiations/google/test_tools/test_entries.h b/sai_p4/instantiations/google/test_tools/test_entries.h index 52595b63..f453729b 100644 --- a/sai_p4/instantiations/google/test_tools/test_entries.h +++ b/sai_p4/instantiations/google/test_tools/test_entries.h @@ -82,7 +82,7 @@ void AbslStringify(Sink& sink, const IpVersion& ip_version) { } } -// Parameters for generating a mirror session table entry with PSAMP +// Parameters for generating a mirror session table entry with IPFIX // encapsulation. // TODO: Adds data members with parameters needed for mirror // encap. diff --git a/sai_p4/instantiations/google/tests/sai_p4_bmv2_vlan_test.cc b/sai_p4/instantiations/google/tests/sai_p4_bmv2_vlan_test.cc index ca4170e0..f4d760fd 100644 --- a/sai_p4/instantiations/google/tests/sai_p4_bmv2_vlan_test.cc +++ b/sai_p4/instantiations/google/tests/sai_p4_bmv2_vlan_test.cc @@ -563,7 +563,7 @@ sai::TableEntries EntriesForwardingAndRewritingVlanInRifTable( TEST(VlanTest, SettingNonReservedVidInRifWithoutVlanChecksResultsInPacketWithThatId) { - const sai::Instantiation kInstantiation = sai::Instantiation::kExperimentalTor; + const sai::Instantiation kInstantiation = sai::Instantiation::kTor; const pdpi::IrP4Info kIrP4Info = sai::GetIrP4Info(kInstantiation); ASSERT_OK_AND_ASSIGN(Bmv2 bmv2, sai::SetUpBmv2ForSaiP4(kInstantiation)); @@ -624,7 +624,7 @@ TEST(VlanTest, } TEST(VlanTest, SettingNonReservedVidInRifWithVlanChecksResultsInDrop) { - const sai::Instantiation kInstantiation = sai::Instantiation::kExperimentalTor; + const sai::Instantiation kInstantiation = sai::Instantiation::kTor; const pdpi::IrP4Info kIrP4Info = sai::GetIrP4Info(kInstantiation); ASSERT_OK_AND_ASSIGN(Bmv2 bmv2, sai::SetUpBmv2ForSaiP4(kInstantiation)); diff --git a/sai_p4/instantiations/google/tor.p4info.pb.txt b/sai_p4/instantiations/google/tor.p4info.pb.txt index 4aa316ef..c517243f 100644 --- a/sai_p4/instantiations/google/tor.p4info.pb.txt +++ b/sai_p4/instantiations/google/tor.p4info.pb.txt @@ -895,7 +895,7 @@ tables { scope: DEFAULT_ONLY } const_default_action_id: 21257015 - size: 255 + size: 511 } tables { preamble { @@ -1884,8 +1884,8 @@ actions { actions { preamble { id: 16777245 - name: "ingress.mirror_session_lookup.mirror_with_psamp_encapsulation" - alias: "mirror_with_psamp_encapsulation" + name: "ingress.mirror_session_lookup.mirror_with_ipfix_encapsulation" + alias: "mirror_with_ipfix_encapsulation" annotations: "@unsupported" } params { diff --git a/sai_p4/instantiations/google/unioned_p4info.pb.txt b/sai_p4/instantiations/google/unioned_p4info.pb.txt index d8c81f91..11fe4078 100644 --- a/sai_p4/instantiations/google/unioned_p4info.pb.txt +++ b/sai_p4/instantiations/google/unioned_p4info.pb.txt @@ -1097,7 +1097,7 @@ tables { scope: DEFAULT_ONLY } const_default_action_id: 21257015 - size: 255 + size: 511 } tables { preamble { @@ -2035,8 +2035,8 @@ actions { actions { preamble { id: 16777245 - name: "ingress.mirror_session_lookup.mirror_with_psamp_encapsulation" - alias: "mirror_with_psamp_encapsulation" + name: "ingress.mirror_session_lookup.mirror_with_ipfix_encapsulation" + alias: "mirror_with_ipfix_encapsulation" annotations: "@unsupported" } params { From bde6d38f743ca31f33ba091cf4720da3eee4c906 Mon Sep 17 00:00:00 2001 From: kishanps Date: Tue, 16 Jan 2024 11:38:56 -0800 Subject: [PATCH 3/6] [SAI-P4] Models IPFIX mirroring encap. --- sai_p4/fixed/headers.p4 | 5 + sai_p4/fixed/ids.h | 2 +- sai_p4/fixed/metadata.p4 | 26 +- sai_p4/fixed/mirroring.p4 | 90 ++++++- sai_p4/fixed/parser.p4 | 6 + sai_p4/fixed/vlan.p4 | 28 ++- .../google/fabric_border_router.p4info.pb.txt | 50 +++- .../google/middleblock.p4info.pb.txt | 50 +++- sai_p4/instantiations/google/sai_pd.proto | 15 +- .../google/test_tools/test_entries.cc | 18 +- .../google/test_tools/test_entries.h | 11 +- .../google/test_tools/test_entries_test.cc | 13 +- .../tests/sai_p4_bmv2_mirroring_test.cc | 236 ++++++++++++++---- .../google/tests/sai_p4_bmv2_vlan_test.cc | 139 ++++++++++- .../instantiations/google/tor.p4info.pb.txt | 50 +++- .../google/unioned_p4info.pb.txt | 50 +++- 16 files changed, 702 insertions(+), 87 deletions(-) diff --git a/sai_p4/fixed/headers.p4 b/sai_p4/fixed/headers.p4 index b115f60a..dfd92e5f 100644 --- a/sai_p4/fixed/headers.p4 +++ b/sai_p4/fixed/headers.p4 @@ -89,6 +89,8 @@ header ipv6_t { ipv6_addr_t dst_addr; } +#define UDP_HEADER_BYTES 8 + header udp_t { bit<16> src_port; bit<16> dst_port; @@ -143,6 +145,8 @@ header gre_t { bit<16> protocol; } +#define IPFIX_HEADER_BYTES 16 + // IP Flow Information Export (IPFIX) header, pursuant to RFC 7011 section 3.1. header ipfix_t { // Version of IPFIX to which this Message conforms. @@ -161,6 +165,7 @@ header ipfix_t { bit<32> observation_domain_id; } +#define PSAMP_EXTENDED_BYTES 28 // PSAMP extended header, pursuant to RFC5476. header psamp_extended_t { bit<16> template_id; diff --git a/sai_p4/fixed/ids.h b/sai_p4/fixed/ids.h index 80c6b392..b169f602 100644 --- a/sai_p4/fixed/ids.h +++ b/sai_p4/fixed/ids.h @@ -55,7 +55,7 @@ #define ROUTING_SET_MULTICAST_SRC_MAC_ACTION_ID 0x01000019 // 16777241 #define MIRRORING_MIRROR_AS_IPV4_ERSPAN_ACTION_ID 0x01000007 // 16777223 #define CLONING_INGRESS_CLONE_ACTION_ID 0x0100001C // 16777244 -#define CLONING_MIRROR_WITH_IPFIX_ENCAPSULATION_ACTION_ID \ +#define CLONING_MIRROR_WITH_VLAN_TAG_AND_IPFIX_ENCAPSULATION_ACTION_ID \ 0x0100001D // 16777245 #define L3_ADMIT_ACTION_ID 0x01000008 // 16777224 #define MIRRORING_SET_PRE_SESSION_ACTION_ID 0x01000009 // 16777225 diff --git a/sai_p4/fixed/metadata.p4 b/sai_p4/fixed/metadata.p4 index aa47df03..39461a2a 100644 --- a/sai_p4/fixed/metadata.p4 +++ b/sai_p4/fixed/metadata.p4 @@ -141,6 +141,15 @@ struct headers_t { // PacketOut header; extracted only for packets received from the controller. packet_out_header_t packet_out_header; + // -- mirroring encap headers ------------------------------------------------ + ethernet_t mirror_encap_ethernet; + vlan_t mirror_encap_vlan; + ipv6_t mirror_encap_ipv6; + udp_t mirror_encap_udp; + ipfix_t ipfix; + psamp_extended_t psamp_extended; + // -- end of mirroring encap headers ----------------------------------------- + ethernet_t ethernet; vlan_t vlan; @@ -214,7 +223,7 @@ struct local_metadata_t { // pipeline. bool marked_to_copy; - // Mirroring related fields. + // -- Mirroring related fields ----------------------------------------------- // We can't group them into a struct as BMv2 doesn't support passing structs // into clone3. // If true, the packet needs to be mirrored at the end of the ingress @@ -224,6 +233,21 @@ struct local_metadata_t { // Valid iff marked_to_mirror is true. mirror_session_id_t mirror_session_id; port_id_t mirror_egress_port; + @field_list(PreservedFieldList.MIRROR_AND_PACKET_IN_COPY) + ethernet_addr_t mirror_encap_src_mac; + @field_list(PreservedFieldList.MIRROR_AND_PACKET_IN_COPY) + ethernet_addr_t mirror_encap_dst_mac; + @field_list(PreservedFieldList.MIRROR_AND_PACKET_IN_COPY) + vlan_id_t mirror_encap_vlan_id; + @field_list(PreservedFieldList.MIRROR_AND_PACKET_IN_COPY) + ipv6_addr_t mirror_encap_src_ip; + @field_list(PreservedFieldList.MIRROR_AND_PACKET_IN_COPY) + ipv6_addr_t mirror_encap_dst_ip; + @field_list(PreservedFieldList.MIRROR_AND_PACKET_IN_COPY) + bit<16> mirror_encap_udp_src_port; + @field_list(PreservedFieldList.MIRROR_AND_PACKET_IN_COPY) + bit<16> mirror_encap_udp_dst_port; + // -- end of mirroring related fields ---------------------------------------- // Packet-in related fields, which we can't group into a struct, because BMv2 // doesn't support passing structs in clone3. diff --git a/sai_p4/fixed/mirroring.p4 b/sai_p4/fixed/mirroring.p4 index af564128..a5d7769d 100644 --- a/sai_p4/fixed/mirroring.p4 +++ b/sai_p4/fixed/mirroring.p4 @@ -24,7 +24,7 @@ control mirror_session_lookup(inout headers_t headers, // SAI_MIRROR_SESSION_ATTR_TTL // SAI_MIRROR_SESSION_ATTR_TOS // TODO: Remove mirror_as_ipv4_erspan once the the switch - // supports mirror_with_psamp_encapsulation. This action is currently needed + // supports mirror_with_ipfix_encapsulation. This action is currently needed // for mirror_session_table since it is the only action by the switch in this // table. @id(MIRRORING_MIRROR_AS_IPV4_ERSPAN_ACTION_ID) @@ -43,13 +43,39 @@ control mirror_session_lookup(inout headers_t headers, // * SAI_MIRROR_SESSION_ATTR_IPFIX_ENCAPSULATION_TYPE to // SAI_IPFIX_ENCAPSULATION_TYPE_EXTENDED // * SAI_MIRROR_SESSION_ATTR_MONITOR_PORT to `monitor_port` - @id(CLONING_MIRROR_WITH_IPFIX_ENCAPSULATION_ACTION_ID) - // TODO: Add params needed for IPFIX mirroring. + // * SAI_MIRROR_SESSION_ATTR_MONITOR_FAILOVER_PORT to + // `monitor_failover_port + // * SAI_MIRROR_SESSION_ATTR_SRC_MAC_ADDRESS + // * SAI_MIRROR_SESSION_ATTR_DST_MAC_ADDRESS + // * SAI_MIRROR_SESSION_ATTR_VLAN_TPID + // * SAI_MIRROR_SESSION_ATTR_VLAN_ID + // * SAI_MIRROR_SESSION_ATTR_SRC_IP_ADDRESS + // * SAI_MIRROR_SESSION_ATTR_DST_IP_ADDRESS + // * SAI_MIRROR_SESSION_ATTR_UDP_SRC_PORT + // * SAI_MIRROR_SESSION_ATTR_UDP_DST_PORT + @id(CLONING_MIRROR_WITH_VLAN_TAG_AND_IPFIX_ENCAPSULATION_ACTION_ID) // TODO: Remove unsupported annotation once the switch stack // supports this table. @unsupported - action mirror_with_ipfix_encapsulation(@id(1) port_id_t monitor_port) { + action mirror_with_vlan_tag_and_ipfix_encapsulation( + @id(1) port_id_t monitor_port, + @id(2) port_id_t monitor_failover_port, + @id(3) @format(MAC_ADDRESS) ethernet_addr_t mirror_encap_src_mac, + @id(4) @format(MAC_ADDRESS) ethernet_addr_t mirror_encap_dst_mac, + @id(6) vlan_id_t mirror_encap_vlan_id, + @id(7) @format(IPV6_ADDRESS) ipv6_addr_t mirror_encap_dst_ip, + @id(8) @format(IPV6_ADDRESS) ipv6_addr_t mirror_encap_src_ip, + @id(9) bit<16> mirror_encap_udp_src_port, + @id(10) bit<16> mirror_encap_udp_dst_port) { local_metadata.mirror_egress_port = monitor_port; + // monitor_failover_port's effect is not modeled. + local_metadata.mirror_encap_src_mac = mirror_encap_src_mac; + local_metadata.mirror_encap_dst_mac = mirror_encap_dst_mac; + local_metadata.mirror_encap_vlan_id = mirror_encap_vlan_id; + local_metadata.mirror_encap_src_ip = mirror_encap_src_ip; + local_metadata.mirror_encap_dst_ip = mirror_encap_dst_ip; + local_metadata.mirror_encap_udp_src_port = mirror_encap_udp_src_port; + local_metadata.mirror_encap_udp_dst_port = mirror_encap_udp_dst_port; } // Corresponding SAI object: SAI_OBJECT_TYPE_MIRROR_SESSION @@ -63,7 +89,7 @@ control mirror_session_lookup(inout headers_t headers, } actions = { @proto_id(1) mirror_as_ipv4_erspan; - @proto_id(2) mirror_with_ipfix_encapsulation; + @proto_id(2) mirror_with_vlan_tag_and_ipfix_encapsulation; @defaultonly NoAction; } @@ -83,8 +109,60 @@ control mirroring_encap(inout headers_t headers, inout local_metadata_t local_metadata, inout standard_metadata_t standard_metadata) { apply { + // All mirrored packets are encapped with + // ================================================================== + // | Ethernet + vlan | IPv6 | UDP | IPFIX + PSAMP extended| payload | + // ================================================================== + // headers. Fields for headers mostly come from mirror-related + // local_metadata. if (IS_MIRROR_COPY(standard_metadata)) { - // TODO: Implements mirroring encap. + headers.mirror_encap_ethernet.setValid(); + headers.mirror_encap_ethernet.src_addr = + local_metadata.mirror_encap_src_mac; + headers.mirror_encap_ethernet.dst_addr = + local_metadata.mirror_encap_dst_mac; + headers.mirror_encap_ethernet.ether_type = ETHERTYPE_8021Q; // VLAN + + headers.mirror_encap_vlan.setValid(); + headers.mirror_encap_vlan.ether_type = ETHERTYPE_IPV6; + headers.mirror_encap_vlan.vlan_id = local_metadata.mirror_encap_vlan_id; + + headers.mirror_encap_ipv6.setValid(); + headers.mirror_encap_ipv6.version = 4w6; + // Mirrored packets' traffic class is 0. + headers.mirror_encap_ipv6.dscp = 0; + headers.mirror_encap_ipv6.ecn = 0; + // Mirrored packets' hop_limit is 16. + headers.mirror_encap_ipv6.hop_limit = 16; + headers.mirror_encap_ipv6.flow_label = 0; + // payload_lentgh for ipv6 packets is the byte length of headers after + // ipv6 + payload. in our case, that's the UDP, IPFIX and PSAMP headers. + // The mirror replicated packet becomes the new payload during mirror + // encap, so standard_metadata.packet_length becomes the payload length. + // contains the length of payload + all headers. + headers.mirror_encap_ipv6.payload_length = + (bit<16>)standard_metadata.packet_length + + UDP_HEADER_BYTES + + IPFIX_HEADER_BYTES + + PSAMP_EXTENDED_BYTES; + headers.mirror_encap_ipv6.next_header = IP_PROTOCOL_UDP; + headers.mirror_encap_ipv6.src_addr = local_metadata.mirror_encap_src_ip; + headers.mirror_encap_ipv6.dst_addr = local_metadata.mirror_encap_dst_ip; + + headers.mirror_encap_udp.setValid(); + headers.mirror_encap_udp.src_port = + local_metadata.mirror_encap_udp_src_port; + headers.mirror_encap_udp.dst_port = + local_metadata.mirror_encap_udp_dst_port; + headers.mirror_encap_udp.hdr_length = + headers.mirror_encap_ipv6.payload_length; + // Mirrored packets' UDP checksum is 0. + headers.mirror_encap_udp.checksum = 0; + + // IPFIX and PSAMP fields are opaque to P4 so we only set their headers + // as valid. + headers.ipfix.setValid(); + headers.psamp_extended.setValid(); } } } // control mirroring_encap diff --git a/sai_p4/fixed/parser.p4 b/sai_p4/fixed/parser.p4 index 02bc09a5..d96ff8e3 100644 --- a/sai_p4/fixed/parser.p4 +++ b/sai_p4/fixed/parser.p4 @@ -146,6 +146,12 @@ control packet_deparser(packet_out packet, in headers_t headers) { #if defined(PLATFORM_BMV2) || defined(PLATFORM_P4SYMBOLIC) packet.emit(headers.packet_in_header); #endif + packet.emit(headers.mirror_encap_ethernet); + packet.emit(headers.mirror_encap_vlan); + packet.emit(headers.mirror_encap_ipv6); + packet.emit(headers.mirror_encap_udp); + packet.emit(headers.ipfix); + packet.emit(headers.psamp_extended); packet.emit(headers.ethernet); packet.emit(headers.tunnel_encap_ipv6); packet.emit(headers.tunnel_encap_gre); diff --git a/sai_p4/fixed/vlan.p4 b/sai_p4/fixed/vlan.p4 index d6bea5fd..30dfe8ad 100644 --- a/sai_p4/fixed/vlan.p4 +++ b/sai_p4/fixed/vlan.p4 @@ -66,6 +66,9 @@ control vlan_untag(inout headers_t headers, } } // control vlan_untag +// Apply VLAN checks for packets in ingress pipeline. +// This control block assumes vlan_untag control block has been called +// and VLAN-related information is stored in metadata instead of in headers. control ingress_vlan_checks(inout headers_t headers, inout local_metadata_t local_metadata, inout standard_metadata_t standard_metadata) { @@ -77,15 +80,23 @@ control ingress_vlan_checks(inout headers_t headers, } } // control ingress_vlan_checks -// Apply VLAN checks for forwarded packets. -// TODO: Add VLAN checks for mirrored packets. +// Apply VLAN checks for packets in egress pipeline (except for punted packets). +// This control block assumes vlan_tag control block has not been called and +// VLAN-related information is stored in metadata, instead of in headers. control egress_vlan_checks(inout headers_t headers, inout local_metadata_t local_metadata, inout standard_metadata_t standard_metadata) { apply { - if (local_metadata.enable_vlan_checks && - !IS_RESERVED_VLAN_ID(local_metadata.vlan_id)) { - mark_to_drop(standard_metadata); + if (local_metadata.enable_vlan_checks) { + // For mirrored-encapped packets, the encapped VLAN header's VLAN ID + // metadata is different from that of normal VLAN header. + if (IS_MIRROR_COPY(standard_metadata) && + !IS_RESERVED_VLAN_ID(local_metadata.mirror_encap_vlan_id)) { + mark_to_drop(standard_metadata); + } else if (!IS_PACKET_IN_COPY(standard_metadata) && + !IS_RESERVED_VLAN_ID(local_metadata.vlan_id)) { + mark_to_drop(standard_metadata); + } } } } // control egress_vlan_checks @@ -95,9 +106,10 @@ control vlan_tag(inout headers_t headers, inout local_metadata_t local_metadata, inout standard_metadata_t standard_metadata) { apply { - // TODO: Forward and Multicast packets should be vlan tagged - // but not mirrored packets. - if (!IS_RESERVED_VLAN_ID(local_metadata.vlan_id)) { + if (!IS_RESERVED_VLAN_ID(local_metadata.vlan_id) && + !IS_MIRROR_COPY(standard_metadata)) { + // Mirroring encapsulates a series of headers, including a VLAN header. + // To seperate concerns, vlan encapping for mirroring is skipped here. headers.vlan.setValid(); headers.vlan.priority_code_point = 0; headers.vlan.drop_eligible_indicator = 0; diff --git a/sai_p4/instantiations/google/fabric_border_router.p4info.pb.txt b/sai_p4/instantiations/google/fabric_border_router.p4info.pb.txt index 6f2eb7d2..4402123e 100644 --- a/sai_p4/instantiations/google/fabric_border_router.p4info.pb.txt +++ b/sai_p4/instantiations/google/fabric_border_router.p4info.pb.txt @@ -1422,8 +1422,8 @@ actions { actions { preamble { id: 16777245 - name: "ingress.mirror_session_lookup.mirror_with_ipfix_encapsulation" - alias: "mirror_with_ipfix_encapsulation" + name: "ingress.mirror_session_lookup.mirror_with_vlan_tag_and_ipfix_encapsulation" + alias: "mirror_with_vlan_tag_and_ipfix_encapsulation" annotations: "@unsupported" } params { @@ -1433,6 +1433,52 @@ actions { name: "port_id_t" } } + params { + id: 2 + name: "monitor_failover_port" + type_name { + name: "port_id_t" + } + } + params { + id: 3 + name: "mirror_encap_src_mac" + annotations: "@format(MAC_ADDRESS)" + bitwidth: 48 + } + params { + id: 4 + name: "mirror_encap_dst_mac" + annotations: "@format(MAC_ADDRESS)" + bitwidth: 48 + } + params { + id: 6 + name: "mirror_encap_vlan_id" + bitwidth: 12 + } + params { + id: 7 + name: "mirror_encap_dst_ip" + annotations: "@format(IPV6_ADDRESS)" + bitwidth: 128 + } + params { + id: 8 + name: "mirror_encap_src_ip" + annotations: "@format(IPV6_ADDRESS)" + bitwidth: 128 + } + params { + id: 9 + name: "mirror_encap_udp_src_port" + bitwidth: 16 + } + params { + id: 10 + name: "mirror_encap_udp_dst_port" + bitwidth: 16 + } } actions { preamble { diff --git a/sai_p4/instantiations/google/middleblock.p4info.pb.txt b/sai_p4/instantiations/google/middleblock.p4info.pb.txt index 1ffc0403..49144381 100755 --- a/sai_p4/instantiations/google/middleblock.p4info.pb.txt +++ b/sai_p4/instantiations/google/middleblock.p4info.pb.txt @@ -1467,8 +1467,8 @@ actions { actions { preamble { id: 16777245 - name: "ingress.mirror_session_lookup.mirror_with_ipfix_encapsulation" - alias: "mirror_with_ipfix_encapsulation" + name: "ingress.mirror_session_lookup.mirror_with_vlan_tag_and_ipfix_encapsulation" + alias: "mirror_with_vlan_tag_and_ipfix_encapsulation" annotations: "@unsupported" } params { @@ -1478,6 +1478,52 @@ actions { name: "port_id_t" } } + params { + id: 2 + name: "monitor_failover_port" + type_name { + name: "port_id_t" + } + } + params { + id: 3 + name: "mirror_encap_src_mac" + annotations: "@format(MAC_ADDRESS)" + bitwidth: 48 + } + params { + id: 4 + name: "mirror_encap_dst_mac" + annotations: "@format(MAC_ADDRESS)" + bitwidth: 48 + } + params { + id: 6 + name: "mirror_encap_vlan_id" + bitwidth: 12 + } + params { + id: 7 + name: "mirror_encap_dst_ip" + annotations: "@format(IPV6_ADDRESS)" + bitwidth: 128 + } + params { + id: 8 + name: "mirror_encap_src_ip" + annotations: "@format(IPV6_ADDRESS)" + bitwidth: 128 + } + params { + id: 9 + name: "mirror_encap_udp_src_port" + bitwidth: 16 + } + params { + id: 10 + name: "mirror_encap_udp_dst_port" + bitwidth: 16 + } } actions { preamble { diff --git a/sai_p4/instantiations/google/sai_pd.proto b/sai_p4/instantiations/google/sai_pd.proto index 9a264df1..1eeecf62 100755 --- a/sai_p4/instantiations/google/sai_pd.proto +++ b/sai_p4/instantiations/google/sai_pd.proto @@ -161,7 +161,8 @@ message MirrorSessionTableEntry { oneof action { MirrorAsIpv4ErspanAction mirror_as_ipv4_erspan = 1; // CAUTION: This action is not (yet) supported. - MirrorWithIpfixEncapsulationAction mirror_with_ipfix_encapsulation = 2; + MirrorWithVlanTagAndIpfixEncapsulationAction + mirror_with_vlan_tag_and_ipfix_encapsulation = 2; } } Action action = 2; @@ -892,8 +893,16 @@ message SetPortAndSrcMacAndVlanIdAction { } // CAUTION: This action is not (yet) supported. -message MirrorWithIpfixEncapsulationAction { - string monitor_port = 1; // Format::STRING +message MirrorWithVlanTagAndIpfixEncapsulationAction { + string monitor_port = 1; // Format::STRING + string monitor_failover_port = 2; // Format::STRING + string mirror_encap_src_mac = 3; // Format::MAC + string mirror_encap_dst_mac = 4; // Format::MAC + string mirror_encap_vlan_id = 6; // Format::HEX_STRING / 12 bits + string mirror_encap_dst_ip = 7; // Format::IPV6 / 128 bits + string mirror_encap_src_ip = 8; // Format::IPV6 / 128 bits + string mirror_encap_udp_src_port = 9; // Format::HEX_STRING / 16 bits + string mirror_encap_udp_dst_port = 10; // Format::HEX_STRING / 16 bits } message SetVrfAction { diff --git a/sai_p4/instantiations/google/test_tools/test_entries.cc b/sai_p4/instantiations/google/test_tools/test_entries.cc index 3e17ccca..dacb4054 100644 --- a/sai_p4/instantiations/google/test_tools/test_entries.cc +++ b/sai_p4/instantiations/google/test_tools/test_entries.cc @@ -567,13 +567,21 @@ EntryBuilder& EntryBuilder::AddMirrorSessionTableEntry( *pd_entry.mutable_mirror_session_table_entry(); mirror_session_entry.mutable_match()->set_mirror_session_id( params.mirror_session_id); - sai::MirrorWithIpfixEncapsulationAction& action = + sai::MirrorWithVlanTagAndIpfixEncapsulationAction& action = *mirror_session_entry.mutable_action() - ->mutable_mirror_with_ipfix_encapsulation(); - action.set_monitor_port(params.mirror_egress_port); - // TODO: Fill in IPFIX params in table entry's action. + ->mutable_mirror_with_vlan_tag_and_ipfix_encapsulation(); + action.set_monitor_port(params.monitor_port); + // monitor_failover_port's effect is not modeled, so use mirror_egress_port + // as a dummy value to satisfy the action param requirement. + action.set_monitor_failover_port(params.monitor_port); + action.set_mirror_encap_src_mac(params.mirror_encap_src_mac); + action.set_mirror_encap_dst_mac(params.mirror_encap_dst_mac); + action.set_mirror_encap_vlan_id(params.mirror_encap_vlan_id); + action.set_mirror_encap_src_ip(params.mirror_encap_src_ip); + action.set_mirror_encap_dst_ip(params.mirror_encap_dst_ip); + action.set_mirror_encap_udp_src_port(params.mirror_encap_udp_src_port); + action.set_mirror_encap_udp_dst_port(params.mirror_encap_udp_dst_port); *entries_.add_entries() = std::move(pd_entry); - return *this; } diff --git a/sai_p4/instantiations/google/test_tools/test_entries.h b/sai_p4/instantiations/google/test_tools/test_entries.h index f453729b..55875e90 100644 --- a/sai_p4/instantiations/google/test_tools/test_entries.h +++ b/sai_p4/instantiations/google/test_tools/test_entries.h @@ -84,11 +84,16 @@ void AbslStringify(Sink& sink, const IpVersion& ip_version) { // Parameters for generating a mirror session table entry with IPFIX // encapsulation. -// TODO: Adds data members with parameters needed for mirror -// encap. struct MirrorSessionParams { std::string mirror_session_id; - std::string mirror_egress_port; + std::string monitor_port; + std::string mirror_encap_src_mac; + std::string mirror_encap_dst_mac; + std::string mirror_encap_vlan_id; + std::string mirror_encap_src_ip; + std::string mirror_encap_dst_ip; + std::string mirror_encap_udp_src_port; + std::string mirror_encap_udp_dst_port; }; // Parameters for generating an ACL table entry to mark packets to be mirrored. diff --git a/sai_p4/instantiations/google/test_tools/test_entries_test.cc b/sai_p4/instantiations/google/test_tools/test_entries_test.cc index 09c43608..b5aec697 100644 --- a/sai_p4/instantiations/google/test_tools/test_entries_test.cc +++ b/sai_p4/instantiations/google/test_tools/test_entries_test.cc @@ -443,8 +443,17 @@ TEST(EntryBuilder, AddMirrorSessionTableEntry) { pdpi::IrEntities entities, EntryBuilder() .AddMirrorSessionTableEntry(MirrorSessionParams{ - .mirror_session_id = "id", - .mirror_egress_port = "0", + .mirror_session_id = "mirror_session_id", + .monitor_port = "monitor_port", + .mirror_encap_src_mac = + netaddr::MacAddress(1, 1, 1, 1, 1, 1).ToString(), + .mirror_encap_dst_mac = + netaddr::MacAddress(1, 2, 3, 4, 5, 6).ToString(), + .mirror_encap_vlan_id = "0x123", + .mirror_encap_src_ip = "::1", + .mirror_encap_dst_ip = "::2", + .mirror_encap_udp_src_port = "0x1234", + .mirror_encap_udp_dst_port = "0x1235", }) .LogPdEntries() // TODO: Remove unsupported once the diff --git a/sai_p4/instantiations/google/tests/sai_p4_bmv2_mirroring_test.cc b/sai_p4/instantiations/google/tests/sai_p4_bmv2_mirroring_test.cc index 4a767297..d0e90e5d 100644 --- a/sai_p4/instantiations/google/tests/sai_p4_bmv2_mirroring_test.cc +++ b/sai_p4/instantiations/google/tests/sai_p4_bmv2_mirroring_test.cc @@ -17,9 +17,11 @@ #include #include "absl/log/check.h" +#include "absl/strings/str_cat.h" #include "glog/logging.h" #include "gmock/gmock.h" #include "gtest/gtest.h" +#include "gutil/proto_matchers.h" #include "gutil/status_matchers.h" #include "gutil/testing.h" #include "p4/v1/p4runtime.pb.h" @@ -27,6 +29,7 @@ #include "p4_pdpi/p4_runtime_session_extras.h" #include "p4_pdpi/packetlib/packetlib.h" #include "p4_pdpi/packetlib/packetlib.pb.h" +#include "p4_pdpi/packetlib/packetlib_matchers.h" #include "p4_pdpi/string_encodings/byte_string.h" #include "platforms/networking/p4/p4_infra/bmv2/bmv2.h" #include "sai_p4/instantiations/google/instantiations.h" @@ -38,13 +41,13 @@ namespace pins { namespace { using ::gutil::IsOkAndHolds; +using ::gutil::Partially; using ::orion::p4::test::Bmv2; using ::pdpi::HasPacketIn; using ::pdpi::ParsedPayloadIs; using ::testing::ElementsAre; using ::testing::EqualsProto; -using ::testing::Pair; -using ::testing::Property; +using ::testing::Key; using ::testing::SizeIs; using ::testing::UnorderedElementsAre; using ::testing::Values; @@ -52,8 +55,8 @@ using ::testing::Values; constexpr int kV1modelPortBitwidth = 9; // Returns an Ipv4 packet. -packetlib::Packet GetIpv4Packet() { - return gutil::ParseProtoOrDie( +packetlib::Packet GetIpv4PacketOrDie() { + packetlib::Packet packet = gutil::ParseProtoOrDie( R"pb( headers { ethernet_header { @@ -87,11 +90,14 @@ packetlib::Packet GetIpv4Packet() { } payload: "packet" )pb"); + CHECK_OK(packetlib::UpdateMissingComputedFields(packet)); // Crash ok + CHECK_OK(packetlib::PadPacketToMinimumSize(packet)); // Crash ok + return packet; } // Returns an Ipv6 packet. -packetlib::Packet GetIpv6Packet() { - return gutil::ParseProtoOrDie(R"pb( +packetlib::Packet GetIpv6PacketOrDie() { + packetlib::Packet packet = gutil::ParseProtoOrDie(R"pb( headers { ethernet_header { ethernet_destination: "02:03:04:05:06:77" @@ -120,24 +126,24 @@ packetlib::Packet GetIpv6Packet() { } payload: "ipv6 packet" )pb"); + CHECK_OK(packetlib::UpdateMissingComputedFields(packet)); // Crash ok + CHECK_OK(packetlib::PadPacketToMinimumSize(packet)); // Crash ok + return packet; } -packetlib::Packet GetIpPacket(sai::IpVersion ip_version) { +packetlib::Packet GetIpPacketOrDie(sai::IpVersion ip_version) { packetlib::Packet packet; switch (ip_version) { case sai::IpVersion::kIpv4: - packet = GetIpv4Packet(); + packet = GetIpv4PacketOrDie(); break; case sai::IpVersion::kIpv6: - packet = GetIpv6Packet(); + packet = GetIpv6PacketOrDie(); break; default: LOG(FATAL) << " Unsupported ip_version: " // Crash ok << static_cast(ip_version); } - - CHECK_OK(packetlib::UpdateMissingComputedFields(packet)); // Crash ok - CHECK_OK(packetlib::PadPacketToMinimumSize(packet)); // Crash ok return packet; } @@ -146,14 +152,14 @@ std::string BMv2Port(int port) { std::bitset(port)); } -struct MirroringTestParams { +struct MirroringTestConstants { int ingress_port; int mirror_egress_port; sai::MarkToMirrorParams marked_to_mirror_params; sai::MirrorSessionParams mirror_session_params; }; -MirroringTestParams GetDefaultMirroringTestParams() { +MirroringTestConstants GetMirroringTestConstants() { constexpr int kIngressPort = 6; constexpr int kMirrorEgressPort = 5; const std::string kMirrorSessionId = "mirror_session_id"; @@ -168,23 +174,115 @@ MirroringTestParams GetDefaultMirroringTestParams() { .mirror_session_params = { .mirror_session_id = kMirrorSessionId, - .mirror_egress_port = BMv2Port(kMirrorEgressPort), + .monitor_port = BMv2Port(kMirrorEgressPort), + .mirror_encap_src_mac = "00:08:08:08:08:08", + .mirror_encap_dst_mac = "01:09:09:09:09:09", + .mirror_encap_vlan_id = "0x123", + .mirror_encap_src_ip = "::1", + .mirror_encap_dst_ip = "::2", + .mirror_encap_udp_src_port = "0x1234", + .mirror_encap_udp_dst_port = "0x1283", }, }; } -class MirroringTest : public ::testing::TestWithParam {}; +// Asserts headers are IPFIX-extended conformant and verify headers fields are +// populated with values that match with `mirror_session_params` (such as IPV6 +// header's dst ip value should be mirror_session_params.mirror_encap_dst_id) or +// match with hardcoded value in p4 modeling (such as IPV6's hop_limit of 16). +// Fields outside of P4-modeling's control, such as PSAMP header's +// observation_time are not checked. +void AssertPacketIsVlanTaggedAndIpfixEncappedWithMirrorSessionParams( + const packetlib::Packet& packet, + const sai::MirrorSessionParams& mirror_session_params) { + using ::packetlib::HasHeaderCase; + ASSERT_THAT(packet.headers(), + ElementsAre(HasHeaderCase(packetlib::Header::kEthernetHeader), + HasHeaderCase(packetlib::Header::kVlanHeader), + HasHeaderCase(packetlib::Header::kIpv6Header), + HasHeaderCase(packetlib::Header::kUdpHeader), + HasHeaderCase(packetlib::Header::kIpfixHeader), + HasHeaderCase(packetlib::Header::kPsampHeader))); + + packetlib::Header ethernet_header; + ethernet_header.mutable_ethernet_header()->set_ethertype("0x8100"); + ethernet_header.mutable_ethernet_header()->set_ethernet_destination( + mirror_session_params.mirror_encap_dst_mac); + ethernet_header.mutable_ethernet_header()->set_ethernet_source( + mirror_session_params.mirror_encap_src_mac); + + packetlib::Header vlan_header; + vlan_header.mutable_vlan_header()->set_priority_code_point("0x0"); + vlan_header.mutable_vlan_header()->set_drop_eligible_indicator("0x0"); + vlan_header.mutable_vlan_header()->set_vlan_identifier( + mirror_session_params.mirror_encap_vlan_id); + vlan_header.mutable_vlan_header()->set_ethertype("0x86dd"); + + packetlib::Header ipv6_header; + ipv6_header.mutable_ipv6_header()->set_dscp("0x00"); + ipv6_header.mutable_ipv6_header()->set_ecn("0x0"); + ipv6_header.mutable_ipv6_header()->set_flow_label("0x00000"); + ipv6_header.mutable_ipv6_header()->set_hop_limit("0x10"); + ipv6_header.mutable_ipv6_header()->set_version("0x6"); + // IP_PROTOCOL for UDP. + ipv6_header.mutable_ipv6_header()->set_next_header("0x11"); + ipv6_header.mutable_ipv6_header()->set_ipv6_source( + mirror_session_params.mirror_encap_src_ip); + ipv6_header.mutable_ipv6_header()->set_ipv6_destination( + mirror_session_params.mirror_encap_dst_ip); + ASSERT_OK_AND_ASSIGN(const int packet_size, + packetlib::PacketSizeInBytes(packet)); + // Payload length field for both IP and UDP headers is the packet length + // subtracted by the header length of IP header and of headers in front of IP + // header (ETHERNET and VLAN). + const int payload_length = packet_size - /*ETHERNET header bytes*/ 14 - + /*VLAN header bytes*/ 4 - + /*IPV6 header bytes*/ 40; + + ipv6_header.mutable_ipv6_header()->set_payload_length( + packetlib::IpPayloadLength(payload_length)); + + packetlib::Header udp_header; + udp_header.mutable_udp_header()->set_source_port( + mirror_session_params.mirror_encap_udp_src_port); + udp_header.mutable_udp_header()->set_destination_port( + mirror_session_params.mirror_encap_udp_dst_port); + // UDP checksum for mirrored packets is set to 0. + udp_header.mutable_udp_header()->set_checksum("0x0000"); + udp_header.mutable_udp_header()->set_length( + packetlib::IpPayloadLength(payload_length)); + ASSERT_THAT( + packet.headers(), + ElementsAre(EqualsProto(ethernet_header), EqualsProto(vlan_header), + EqualsProto(ipv6_header), EqualsProto(udp_header), + // Use Partially matchers to only check the presence + // of IPFIX and PSAMP headers since P4 modeling + // doesn't populate any of the field within these two + // headers. P4BAR also will not check IPFIX and PSAMP + // headers too. See b/318753700 for details. + Partially(EqualsProto(R"pb(ipfix_header {})pb")), + Partially(EqualsProto(R"pb(psamp_header {})pb")))); +} + +// Test fixture to verify packets are mirrored and encapped. +class MirrorAndEncapTest : public ::testing::TestWithParam {}; -TEST_P(MirroringTest, OnePacketEmittedWhenPacketIsMirroredAndDropped) { - constexpr sai::Instantiation kInstantiation = GetParam(); +TEST_P(MirrorAndEncapTest, OnePacketEmittedWhenPacketIsMirroredAndDropped) { + constexpr sai::Instantiation kInstantiation = sai::Instantiation::kTor; const sai::IpVersion ip_version = GetParam(); - MirroringTestParams mirroring_test_params = GetDefaultMirroringTestParams(); + const MirroringTestConstants mirroring_test_params = + GetMirroringTestConstants(); + SCOPED_TRACE(absl::StrCat( + "MirrorAndEncapTest for OnePacketEmittedWhenPacketIsMirroredAndDropped. " + "IP version: ", + ip_version)); ASSERT_OK_AND_ASSIGN(Bmv2 bmv2, sai::SetUpBmv2ForSaiP4(kInstantiation)); ASSERT_OK_AND_ASSIGN( std::vector pi_entities, sai::EntryBuilder() + .AddDisableVlanChecksEntry() .AddMarkToMirrorAclEntry( mirroring_test_params.marked_to_mirror_params) .AddMirrorSessionTableEntry( @@ -195,26 +293,41 @@ TEST_P(MirroringTest, OnePacketEmittedWhenPacketIsMirroredAndDropped) { /*allow_unsupported=*/true)); ASSERT_OK(pdpi::InstallPiEntities(bmv2.P4RuntimeSession(), pi_entities)); - EXPECT_THAT(bmv2.SendPacket(mirroring_test_params.ingress_port, - GetIpPacket(ip_version)), - IsOkAndHolds(UnorderedElementsAre( - Pair(mirroring_test_params.mirror_egress_port, - Property(&packetlib::Packets::packets, SizeIs(1)))))); + packetlib::Packet input_packet = GetIpPacketOrDie(ip_version); + ASSERT_OK_AND_ASSIGN( + const auto outputs, + bmv2.SendPacket(mirroring_test_params.ingress_port, input_packet)); + ASSERT_THAT(outputs, UnorderedElementsAre( + Key(mirroring_test_params.mirror_egress_port))); + ASSERT_THAT(outputs.at(mirroring_test_params.mirror_egress_port).packets(), + SizeIs(1)); + packetlib::Packet mirrored_packet = + outputs.at(mirroring_test_params.mirror_egress_port).packets(0); + + AssertPacketIsVlanTaggedAndIpfixEncappedWithMirrorSessionParams( + mirrored_packet, mirroring_test_params.mirror_session_params); + ASSERT_THAT(packetlib::ParsePacket(mirrored_packet.payload()), + EqualsProto(input_packet)); } -TEST_P(MirroringTest, +TEST_P(MirrorAndEncapTest, TwoPacketsEmittedWhenAPacketHitsMirroringEntryAndIsForwarded) { constexpr sai::Instantiation kInstantiation = GetParam(); const sai::IpVersion ip_version = GetParam(); - const MirroringTestParams mirroring_test_params = - GetDefaultMirroringTestParams(); + const MirroringTestConstants mirroring_test_params = + GetMirroringTestConstants(); constexpr int kForwardEgressPort = 9; - + SCOPED_TRACE( + absl::StrCat("MirrorAndEncapTest for " + "TwoPacketsEmittedWhenAPacketHitsMirroringEntryAndIsForwarde" + "d. IP version: ", + ip_version)); ASSERT_OK_AND_ASSIGN(Bmv2 bmv2, sai::SetUpBmv2ForSaiP4(kInstantiation)); ASSERT_OK_AND_ASSIGN( std::vector pi_entities, sai::EntryBuilder() + .AddDisableVlanChecksEntry() .AddEntriesForwardingIpPacketsToGivenPort( BMv2Port(kForwardEgressPort)) .AddMarkToMirrorAclEntry( @@ -227,29 +340,47 @@ TEST_P(MirroringTest, /*allow_unsupported=*/true)); ASSERT_OK(pdpi::InstallPiEntities(bmv2.P4RuntimeSession(), pi_entities)); - EXPECT_THAT(bmv2.SendPacket(mirroring_test_params.ingress_port, - GetIpPacket(ip_version)), - IsOkAndHolds(UnorderedElementsAre( - Pair(mirroring_test_params.mirror_egress_port, - Property(&packetlib::Packets::packets, SizeIs(1))), - Pair(kForwardEgressPort, - Property(&packetlib::Packets::packets, SizeIs(1)))))); + + packetlib::Packet input_packet = GetIpPacketOrDie(ip_version); + ASSERT_OK_AND_ASSIGN( + const auto outputs, + bmv2.SendPacket(mirroring_test_params.ingress_port, input_packet)); + + ASSERT_THAT(outputs, UnorderedElementsAre( + Key(mirroring_test_params.mirror_egress_port), + Key(kForwardEgressPort))); + ASSERT_THAT(outputs.at(mirroring_test_params.mirror_egress_port).packets(), + SizeIs(1)); + ASSERT_THAT(outputs.at(kForwardEgressPort).packets(), SizeIs(1)); + + packetlib::Packet mirrored_packet = + outputs.at(mirroring_test_params.mirror_egress_port).packets(0); + AssertPacketIsVlanTaggedAndIpfixEncappedWithMirrorSessionParams( + mirrored_packet, mirroring_test_params.mirror_session_params); + ASSERT_THAT(packetlib::ParsePacket(mirrored_packet.payload()), + EqualsProto(input_packet)); } TEST_P( - MirroringTest, + MirrorAndEncapTest, ThreePacketsEmittedWhenAPacketHitsMirroringEntryAndIsForwardedAndPunted) { constexpr sai::Instantiation kInstantiation = GetParam(); const sai::IpVersion ip_version = GetParam(); - const MirroringTestParams mirroring_test_params = - GetDefaultMirroringTestParams(); + const MirroringTestConstants mirroring_test_params = + GetMirroringTestConstants(); constexpr int kForwardEgressPort = 19; - ASSERT_OK_AND_ASSIGN(Bmv2 bmv2, sai::SetUpBmv2ForSaiP4(kInstantiation)); + SCOPED_TRACE( + absl::StrCat("MirrorAndEncapTest for " + "ThreePacketsEmittedWhenAPacketHitsMirroringEntryAndIsForwar" + "dedAndPunted. IP version: ", + ip_version)); + ASSERT_OK_AND_ASSIGN(Bmv2 bmv2, sai::SetUpBmv2ForSaiP4(kInstantiation)); ASSERT_OK_AND_ASSIGN( std::vector pi_entities, sai::EntryBuilder() + .AddDisableVlanChecksEntry() .AddEntriesForwardingIpPacketsToGivenPort( BMv2Port(kForwardEgressPort)) .AddMarkToMirrorAclEntry( @@ -263,20 +394,31 @@ TEST_P( /*allow_unsupported=*/true)); ASSERT_OK(pdpi::InstallPiEntities(bmv2.P4RuntimeSession(), pi_entities)); - packetlib::Packet input_packet = GetIpPacket(ip_version); - EXPECT_THAT(bmv2.SendPacket(mirroring_test_params.ingress_port, input_packet), - IsOkAndHolds(UnorderedElementsAre( - Pair(mirroring_test_params.mirror_egress_port, - Property(&packetlib::Packets::packets, SizeIs(1))), - Pair(kForwardEgressPort, - Property(&packetlib::Packets::packets, SizeIs(1)))))); + packetlib::Packet input_packet = GetIpPacketOrDie(ip_version); + ASSERT_OK_AND_ASSIGN( + const auto outputs, + bmv2.SendPacket(mirroring_test_params.ingress_port, input_packet)); + ASSERT_THAT(outputs, UnorderedElementsAre( + Key(mirroring_test_params.mirror_egress_port), + Key(kForwardEgressPort))); + ASSERT_THAT(outputs.at(mirroring_test_params.mirror_egress_port).packets(), + SizeIs(1)); + ASSERT_THAT(outputs.at(kForwardEgressPort).packets(), SizeIs(1)); + + const packetlib::Packet mirrored_packet = + outputs.at(mirroring_test_params.mirror_egress_port).packets(0); + + AssertPacketIsVlanTaggedAndIpfixEncappedWithMirrorSessionParams( + mirrored_packet, mirroring_test_params.mirror_session_params); + ASSERT_THAT(packetlib::ParsePacket(mirrored_packet.payload()), + EqualsProto(input_packet)); EXPECT_THAT(bmv2.P4RuntimeSession().ReadStreamChannelResponsesAndFinish(), IsOkAndHolds(ElementsAre( HasPacketIn(ParsedPayloadIs(EqualsProto(input_packet)))))); } -INSTANTIATE_TEST_SUITE_P(DifferentIpVersions, MirroringTest, +INSTANTIATE_TEST_SUITE_P(DifferentIpVersions, MirrorAndEncapTest, Values(sai::IpVersion::kIpv4, sai::IpVersion::kIpv6)); } // namespace diff --git a/sai_p4/instantiations/google/tests/sai_p4_bmv2_vlan_test.cc b/sai_p4/instantiations/google/tests/sai_p4_bmv2_vlan_test.cc index f4d760fd..a9a68f46 100644 --- a/sai_p4/instantiations/google/tests/sai_p4_bmv2_vlan_test.cc +++ b/sai_p4/instantiations/google/tests/sai_p4_bmv2_vlan_test.cc @@ -13,6 +13,7 @@ // limitations under the License. #include +#include #include #include "absl/container/flat_hash_map.h" @@ -48,16 +49,17 @@ using ::orion::p4::test::Bmv2; using ::packetlib::HasHeaderCase; using ::pdpi::HasPacketIn; using ::pdpi::ParsedPayloadIs; -using ::testing::_; using ::testing::ElementsAre; using ::testing::Eq; using ::testing::IsEmpty; using ::testing::Key; +using ::testing::SizeIs; using PacketsByPort = absl::flat_hash_map; using VlanTest = testing::TestWithParam; -constexpr int kIngressPort = 42; +constexpr int kIngressPort = 2; +constexpr absl::string_view kIngressPortProto = "\002"; constexpr int kEgressPort = 1; constexpr absl::string_view kEgressPortProto = "\001"; @@ -661,7 +663,7 @@ TEST(VlanTest, SettingNonReservedVidInRifWithVlanChecksResultsInDrop) { } TEST(VlanTest, SettingVid4095InRifResultsOutputPacketWithNoVlanTag) { - const sai::Instantiation kInstantiation = sai::Instantiation::kExperimentalTor; + const sai::Instantiation kInstantiation = sai::Instantiation::kTor; const pdpi::IrP4Info kIrP4Info = sai::GetIrP4Info(kInstantiation); ASSERT_OK_AND_ASSIGN(Bmv2 bmv2, sai::SetUpBmv2ForSaiP4(kInstantiation)); @@ -712,5 +714,136 @@ INSTANTIATE_TEST_SUITE_P( return InstantiationToString(info.param); }); +sai::MirrorSessionParams GetMirrorSessionParamsForTest() { + return sai::MirrorSessionParams{ + .mirror_session_id = "mirror_session_id", + .monitor_port = std::string(kEgressPortProto), + .mirror_encap_src_mac = "00:08:08:08:08:08", + .mirror_encap_dst_mac = "01:09:09:09:09:09", + .mirror_encap_vlan_id = "0x123", + .mirror_encap_src_ip = "::1", + .mirror_encap_dst_ip = "::2", + .mirror_encap_udp_src_port = "0x1234", + .mirror_encap_udp_dst_port = "0x1283", + }; +} + +// When VLAN checks are enabled, vlan-encapped mirror packets with non-reserved +// vlan id should not be mirrored. +// Only test ToR instantiation since only it supports +// acl_ingress_mirror_and_redirect_table. +TEST(MirrorVlanTest, + IpfixEncappedMirroredPktWithNonReservedVidIsDroppedWhenVlanChecksEnabled) { + const sai::Instantiation kInstantiation = sai::Instantiation::kTor; + ASSERT_OK_AND_ASSIGN(Bmv2 bmv2, sai::SetUpBmv2ForSaiP4(kInstantiation)); + sai::MirrorSessionParams mirror_session_params = + GetMirrorSessionParamsForTest(); + // Encap the mirrored packet with non-reserved vlan id. + mirror_session_params.mirror_encap_vlan_id = "0x123"; + + ASSERT_OK_AND_ASSIGN( + std::vector pi_entities, + sai::EntryBuilder() + .AddMirrorSessionTableEntry(mirror_session_params) + .AddMarkToMirrorAclEntry(sai::MarkToMirrorParams{ + .ingress_port = std::string(kIngressPortProto), + .mirror_session_id = mirror_session_params.mirror_session_id, + }) + .GetDedupedPiEntities(sai::GetIrP4Info(kInstantiation), + /*allow_unsupported=*/true)); + + ASSERT_OK(pdpi::InstallPiEntities(bmv2.P4RuntimeSession(), pi_entities)); + packetlib::Packet input_packet = GetIpv4PacketOrDie(); + + ASSERT_OK_AND_ASSIGN(auto outputs, + bmv2.SendPacket(kIngressPort, input_packet)); + ASSERT_THAT(outputs, IsEmpty()); +} + +// When VLAN checks are enabled, vlan-encapped mirror packets with reserved +// vlan id should be mirrored. +// Only test ToR instantiation since only it supports +// acl_ingress_mirror_and_redirect_table. +TEST( + MirrorVlanTest, + IpfixEncappedMirroredCopyWithVid4095EgressWithoutTagWhenVlanChecksEnabled) { + const sai::Instantiation kInstantiation = sai::Instantiation::kTor; + ASSERT_OK_AND_ASSIGN(Bmv2 bmv2, sai::SetUpBmv2ForSaiP4(kInstantiation)); + sai::MirrorSessionParams mirror_session_params = + GetMirrorSessionParamsForTest(); + // Encap the mirrored packet with reserved vlan id. + mirror_session_params.mirror_encap_vlan_id = "0xfff"; + + ASSERT_OK_AND_ASSIGN( + std::vector pi_entities, + sai::EntryBuilder() + .AddMirrorSessionTableEntry(mirror_session_params) + .AddMarkToMirrorAclEntry(sai::MarkToMirrorParams{ + .ingress_port = std::string(kIngressPortProto), + .mirror_session_id = mirror_session_params.mirror_session_id, + }) + .GetDedupedPiEntities(sai::GetIrP4Info(kInstantiation), + /*allow_unsupported=*/true)); + + ASSERT_OK(pdpi::InstallPiEntities(bmv2.P4RuntimeSession(), pi_entities)); + packetlib::Packet input_packet = GetIpv4PacketOrDie(); + + ASSERT_OK_AND_ASSIGN(auto outputs, + bmv2.SendPacket(kIngressPort, input_packet)); + ASSERT_THAT(outputs, ElementsAre(Key(kEgressPort))); + ASSERT_THAT(outputs[kEgressPort].packets(), SizeIs(1)); + EXPECT_THAT(outputs[kEgressPort] + .packets() + .at(0) + .headers() + .at(1) + .vlan_header() + .vlan_identifier(), + Eq(mirror_session_params.mirror_encap_vlan_id)); +} + +// When VLAN checks are disabled, vlan-encapped mirror packets with VLAN ID are +// mirrored. +// Only test ToR instantiation since only it supports +// acl_ingress_mirror_and_redirect_table. +TEST( + MirrorVlanTest, + EncappedMirroredCopyWithNonReservedVidEgressWithTagWhenVlanChecksDisabled) { + const sai::Instantiation kInstantiation = sai::Instantiation::kTor; + ASSERT_OK_AND_ASSIGN(Bmv2 bmv2, sai::SetUpBmv2ForSaiP4(kInstantiation)); + + sai::MirrorSessionParams mirror_session_params = + GetMirrorSessionParamsForTest(); + // Encap the mirrored packet with non-reserved vlan id. + mirror_session_params.mirror_encap_vlan_id = "0x123"; + + ASSERT_OK_AND_ASSIGN( + std::vector pi_entities, + sai::EntryBuilder() + .AddDisableVlanChecksEntry() + .AddMirrorSessionTableEntry(GetMirrorSessionParamsForTest()) + .AddMarkToMirrorAclEntry(sai::MarkToMirrorParams{ + .ingress_port = std::string(kIngressPortProto), + .mirror_session_id = + GetMirrorSessionParamsForTest().mirror_session_id, + }) + .GetDedupedPiEntities(sai::GetIrP4Info(kInstantiation), + /*allow_unsupported=*/true)); + ASSERT_OK(pdpi::InstallPiEntities(bmv2.P4RuntimeSession(), pi_entities)); + packetlib::Packet input_packet = GetIpv4PacketOrDie(); + + ASSERT_OK_AND_ASSIGN(auto outputs, + bmv2.SendPacket(kIngressPort, input_packet)); + ASSERT_THAT(outputs, ElementsAre(Key(kEgressPort))); + ASSERT_THAT(outputs[kEgressPort].packets(), SizeIs(1)); + EXPECT_THAT(outputs[kEgressPort] + .packets() + .at(0) + .headers() + .at(1) + .vlan_header() + .vlan_identifier(), + Eq(mirror_session_params.mirror_encap_vlan_id)); +} } // namespace } // namespace pins diff --git a/sai_p4/instantiations/google/tor.p4info.pb.txt b/sai_p4/instantiations/google/tor.p4info.pb.txt index c517243f..89ac4245 100644 --- a/sai_p4/instantiations/google/tor.p4info.pb.txt +++ b/sai_p4/instantiations/google/tor.p4info.pb.txt @@ -1884,8 +1884,8 @@ actions { actions { preamble { id: 16777245 - name: "ingress.mirror_session_lookup.mirror_with_ipfix_encapsulation" - alias: "mirror_with_ipfix_encapsulation" + name: "ingress.mirror_session_lookup.mirror_with_vlan_tag_and_ipfix_encapsulation" + alias: "mirror_with_vlan_tag_and_ipfix_encapsulation" annotations: "@unsupported" } params { @@ -1895,6 +1895,52 @@ actions { name: "port_id_t" } } + params { + id: 2 + name: "monitor_failover_port" + type_name { + name: "port_id_t" + } + } + params { + id: 3 + name: "mirror_encap_src_mac" + annotations: "@format(MAC_ADDRESS)" + bitwidth: 48 + } + params { + id: 4 + name: "mirror_encap_dst_mac" + annotations: "@format(MAC_ADDRESS)" + bitwidth: 48 + } + params { + id: 6 + name: "mirror_encap_vlan_id" + bitwidth: 12 + } + params { + id: 7 + name: "mirror_encap_dst_ip" + annotations: "@format(IPV6_ADDRESS)" + bitwidth: 128 + } + params { + id: 8 + name: "mirror_encap_src_ip" + annotations: "@format(IPV6_ADDRESS)" + bitwidth: 128 + } + params { + id: 9 + name: "mirror_encap_udp_src_port" + bitwidth: 16 + } + params { + id: 10 + name: "mirror_encap_udp_dst_port" + bitwidth: 16 + } } actions { preamble { diff --git a/sai_p4/instantiations/google/unioned_p4info.pb.txt b/sai_p4/instantiations/google/unioned_p4info.pb.txt index 11fe4078..12b7e0d2 100644 --- a/sai_p4/instantiations/google/unioned_p4info.pb.txt +++ b/sai_p4/instantiations/google/unioned_p4info.pb.txt @@ -2035,8 +2035,8 @@ actions { actions { preamble { id: 16777245 - name: "ingress.mirror_session_lookup.mirror_with_ipfix_encapsulation" - alias: "mirror_with_ipfix_encapsulation" + name: "ingress.mirror_session_lookup.mirror_with_vlan_tag_and_ipfix_encapsulation" + alias: "mirror_with_vlan_tag_and_ipfix_encapsulation" annotations: "@unsupported" } params { @@ -2046,6 +2046,52 @@ actions { name: "port_id_t" } } + params { + id: 2 + name: "monitor_failover_port" + type_name { + name: "port_id_t" + } + } + params { + id: 3 + name: "mirror_encap_src_mac" + annotations: "@format(MAC_ADDRESS)" + bitwidth: 48 + } + params { + id: 4 + name: "mirror_encap_dst_mac" + annotations: "@format(MAC_ADDRESS)" + bitwidth: 48 + } + params { + id: 6 + name: "mirror_encap_vlan_id" + bitwidth: 12 + } + params { + id: 7 + name: "mirror_encap_dst_ip" + annotations: "@format(IPV6_ADDRESS)" + bitwidth: 128 + } + params { + id: 8 + name: "mirror_encap_src_ip" + annotations: "@format(IPV6_ADDRESS)" + bitwidth: 128 + } + params { + id: 9 + name: "mirror_encap_udp_src_port" + bitwidth: 16 + } + params { + id: 10 + name: "mirror_encap_udp_dst_port" + bitwidth: 16 + } } actions { preamble { From 69d460e9089949b95269bda5f6fa5e09b0630a2b Mon Sep 17 00:00:00 2001 From: kishanps Date: Fri, 21 Jan 2022 09:59:29 -0800 Subject: [PATCH 4/6] [SAIP4] Update P4 PreIngress table to match on DST_MAC, Uncomment refers_to annotation for multicast group ID in redirect action, Assign priorities to ACL Ingress tables, Add tests for multicast programming, Add an ACL egress table with a src_mac match to middleblock & Add acl_forward to mirror_and_redirect. --- sai_p4/fixed/packet_rewrites.p4 | 4 - sai_p4/fixed/routing.p4 | 9 -- sai_p4/instantiations/google/BUILD.bazel | 3 +- sai_p4/instantiations/google/acl_egress.p4 | 2 +- sai_p4/instantiations/google/acl_ingress.p4 | 18 ++-- .../instantiations/google/acl_pre_ingress.p4 | 2 + .../google/fabric_border_router.p4info.pb.txt | 5 +- sai_p4/instantiations/google/middleblock.p4 | 2 + .../google/middleblock.p4info.pb.txt | 97 ++++++++++++++++--- .../google/minimum_guaranteed_sizes.p4 | 3 +- sai_p4/instantiations/google/sai_pd.proto | 10 +- .../instantiations/google/tor.p4info.pb.txt | 18 ++-- .../google/unioned_p4info.pb.txt | 29 +++--- 13 files changed, 130 insertions(+), 72 deletions(-) diff --git a/sai_p4/fixed/packet_rewrites.p4 b/sai_p4/fixed/packet_rewrites.p4 index d8dd277b..c63f7d7a 100644 --- a/sai_p4/fixed/packet_rewrites.p4 +++ b/sai_p4/fixed/packet_rewrites.p4 @@ -55,10 +55,6 @@ control multicast_rewrites(inout local_metadata_t local_metadata, // This will cause the source MAC of packets generated by the group member to // be rewritten to the `src_mac` of the `set_multicast_src_mac` action of the // entry. - // - // TODO: Remove `@unsupported` annotation once the switch stack - // supports this table. - @unsupported @p4runtime_role(P4RUNTIME_ROLE_ROUTING) @id(ROUTING_MULTICAST_ROUTER_INTERFACE_TABLE_ID) table multicast_router_interface_table { diff --git a/sai_p4/fixed/routing.p4 b/sai_p4/fixed/routing.p4 index 4acae4af..0b39acd7 100644 --- a/sai_p4/fixed/routing.p4 +++ b/sai_p4/fixed/routing.p4 @@ -165,9 +165,6 @@ control routing_lookup(in headers_t headers, // Calling this action will override unicast, and can itself be overriden by // `mark_to_drop`. // - // TODO: Remove `@unsupported` annotation once the switch stack - // supports multicast. - @unsupported @id(ROUTING_SET_MULTICAST_GROUP_ID_ACTION_ID) @action_restriction(" // Disallow 0 since it encodes 'no multicast' in V1Model. @@ -226,9 +223,6 @@ control routing_lookup(in headers_t headers, // Models SAI IPMC entries of type (*,G) whose destination is an IPv4 address. @p4runtime_role(P4RUNTIME_ROLE_ROUTING) @id(ROUTING_IPV4_MULTICAST_TABLE_ID) - // TODO: Remove `@unsupported` annotation once the switch stack - // supports multicast. - @unsupported table ipv4_multicast_table { key = { // Sets `vr_id` in `sai_ipmc_entry_t`. @@ -247,9 +241,6 @@ control routing_lookup(in headers_t headers, // Models SAI IPMC entries of type (*,G) whose destination is an IPv6 address. @p4runtime_role(P4RUNTIME_ROLE_ROUTING) @id(ROUTING_IPV6_MULTICAST_TABLE_ID) - // TODO: Remove `@unsupported` annotation once the switch stack - // supports multicast. - @unsupported table ipv6_multicast_table { key = { // Sets `vr_id` in `sai_ipmc_entry_t`. diff --git a/sai_p4/instantiations/google/BUILD.bazel b/sai_p4/instantiations/google/BUILD.bazel index 50ee1794..69da8ab6 100644 --- a/sai_p4/instantiations/google/BUILD.bazel +++ b/sai_p4/instantiations/google/BUILD.bazel @@ -27,6 +27,7 @@ package( SHARED_DEPS = [ "acl_common_actions.p4", + "acl_egress.p4", "acl_ingress.p4", "acl_pre_ingress.p4", "ids.h", @@ -41,12 +42,10 @@ SHARED_DEPS = [ MIDDLEBLOCK_DEPS = SHARED_DEPS + ["middleblock.p4"] FABRIC_BORDER_ROUTER_DEPS = SHARED_DEPS + [ - "acl_egress.p4", "fabric_border_router.p4", ] TOR_DEPS = SHARED_DEPS + [ - "acl_egress.p4", "tor.p4", ] diff --git a/sai_p4/instantiations/google/acl_egress.p4 b/sai_p4/instantiations/google/acl_egress.p4 index 6c08059e..5ecba799 100644 --- a/sai_p4/instantiations/google/acl_egress.p4 +++ b/sai_p4/instantiations/google/acl_egress.p4 @@ -88,7 +88,7 @@ control acl_egress(in headers_t headers, @sai_field(SAI_ACL_TABLE_ATTR_FIELD_DST_IPV6_WORD2) ) @format(IPV6_ADDRESS); #endif -#if defined(SAI_INSTANTIATION_TOR) +#if defined(SAI_INSTANTIATION_TOR) || defined(SAI_INSTANTIATION_MIDDLEBLOCK) headers.ethernet.src_addr : ternary @name("src_mac") @id(10) @sai_field(SAI_ACL_TABLE_ATTR_FIELD_SRC_MAC) @format(MAC_ADDRESS); #endif diff --git a/sai_p4/instantiations/google/acl_ingress.p4 b/sai_p4/instantiations/google/acl_ingress.p4 index 91ff70ba..85079253 100644 --- a/sai_p4/instantiations/google/acl_ingress.p4 +++ b/sai_p4/instantiations/google/acl_ingress.p4 @@ -263,7 +263,8 @@ control acl_ingress(in headers_t headers, @sai_field(SAI_ACL_TABLE_ATTR_FIELD_ECN); #endif // Field for v4 IP protocol and v6 next header. - ip_protocol : ternary @name("ip_protocol") @id(13) + ip_protocol : ternary + @id(13) @name("ip_protocol") @sai_field(SAI_ACL_TABLE_ATTR_FIELD_IP_PROTOCOL); #if defined(SAI_INSTANTIATION_FABRIC_BORDER_ROUTER) || defined(SAI_INSTANTIATION_TOR) headers.icmp.type : ternary @name("icmp_type") @id(19) @@ -391,6 +392,7 @@ control acl_ingress(in headers_t headers, @p4runtime_role(P4RUNTIME_ROLE_SDN_CONTROLLER) @id(ACL_INGRESS_COUNTING_TABLE_ID) + @sai_acl_priority(7) @sai_acl(INGRESS) @entry_restriction(" // Only allow IP field matches for IP packets. @@ -405,9 +407,11 @@ control acl_ingress(in headers_t headers, ") table acl_ingress_counting_table { key = { - headers.ipv4.isValid() || headers.ipv6.isValid() : optional @name("is_ip") - @id(1) @sai_field(SAI_ACL_TABLE_ATTR_FIELD_ACL_IP_TYPE/IP); - headers.ipv4.isValid() : optional @name("is_ipv4") @id(2) + headers.ipv4.isValid() || headers.ipv6.isValid() : optional + @id(1) @name("is_ip") + @sai_field(SAI_ACL_TABLE_ATTR_FIELD_ACL_IP_TYPE/IP); + headers.ipv4.isValid() : optional + @id(2) @name("is_ipv4") @sai_field(SAI_ACL_TABLE_ATTR_FIELD_ACL_IP_TYPE/IPV4ANY); headers.ipv6.isValid() : optional @name("is_ipv6") @id(3) @sai_field(SAI_ACL_TABLE_ATTR_FIELD_ACL_IP_TYPE/IPV6ANY); @@ -451,8 +455,7 @@ control acl_ingress(in headers_t headers, ") action redirect_to_ipmc_group( @sai_action_param(SAI_ACL_ENTRY_ATTR_ACTION_REDIRECT) - // TODO: Add this once supported by PDPI and its customers. - // @refers_to(multicast_group_table, multicast_group_id) + @refers_to(builtin::multicast_group_table, multicast_group_id) multicast_group_id_t multicast_group_id) { standard_metadata.mcast_grp = multicast_group_id; @@ -465,6 +468,7 @@ control acl_ingress(in headers_t headers, // ACL table that mirrors and redirects packets. @id(ACL_INGRESS_MIRROR_AND_REDIRECT_TABLE_ID) @sai_acl(INGRESS) + @sai_acl_priority(15) @p4runtime_role(P4RUNTIME_ROLE_SDN_CONTROLLER) @entry_restriction(" // Only allow IP field matches for IP packets. @@ -541,6 +545,7 @@ control acl_ingress(in headers_t headers, @unsupported; } actions = { + @proto_id(4) acl_forward(); @proto_id(1) acl_mirror(); @proto_id(2) redirect_to_nexthop(); @proto_id(3) redirect_to_ipmc_group(); @@ -553,6 +558,7 @@ control acl_ingress(in headers_t headers, // ACL table that only drops or denies packets, and is otherwise a no-op. @id(ACL_INGRESS_SECURITY_TABLE_ID) @sai_acl(INGRESS) + @sai_acl_priority(20) @p4runtime_role(P4RUNTIME_ROLE_SDN_CONTROLLER) @entry_restriction(" // Forbid using ether_type for IP packets (by convention, use is_ip* instead). diff --git a/sai_p4/instantiations/google/acl_pre_ingress.p4 b/sai_p4/instantiations/google/acl_pre_ingress.p4 index ffccfc56..b3043de0 100644 --- a/sai_p4/instantiations/google/acl_pre_ingress.p4 +++ b/sai_p4/instantiations/google/acl_pre_ingress.p4 @@ -95,8 +95,10 @@ control acl_pre_ingress(in headers_t headers, @sai_field(SAI_ACL_TABLE_ATTR_FIELD_ACL_IP_TYPE/IPV6ANY); headers.ethernet.src_addr : ternary @name("src_mac") @id(4) @sai_field(SAI_ACL_TABLE_ATTR_FIELD_SRC_MAC) @format(MAC_ADDRESS); +#ifdef SAI_INSTANTIATION_FABRIC_BORDER_ROUTER headers.ethernet.dst_addr : ternary @name("dst_mac") @id(9) @sai_field(SAI_ACL_TABLE_ATTR_FIELD_DST_MAC) @format(MAC_ADDRESS); +#endif headers.ipv4.dst_addr : ternary @name("dst_ip") @id(5) @sai_field(SAI_ACL_TABLE_ATTR_FIELD_DST_IP) @format(IPV4_ADDRESS); headers.ipv6.dst_addr[127:64] : ternary @name("dst_ipv6") @id(6) diff --git a/sai_p4/instantiations/google/fabric_border_router.p4info.pb.txt b/sai_p4/instantiations/google/fabric_border_router.p4info.pb.txt index 4402123e..f9d8f6bf 100644 --- a/sai_p4/instantiations/google/fabric_border_router.p4info.pb.txt +++ b/sai_p4/instantiations/google/fabric_border_router.p4info.pb.txt @@ -317,7 +317,6 @@ tables { name: "ingress.routing_lookup.ipv4_multicast_table" alias: "ipv4_multicast_table" annotations: "@p4runtime_role(\"sdn_controller\")" - annotations: "@unsupported" } match_fields { id: 1 @@ -352,7 +351,6 @@ tables { name: "ingress.routing_lookup.ipv6_multicast_table" alias: "ipv6_multicast_table" annotations: "@p4runtime_role(\"sdn_controller\")" - annotations: "@unsupported" } match_fields { id: 1 @@ -567,6 +565,7 @@ tables { name: "ingress.acl_ingress.acl_ingress_counting_table" alias: "acl_ingress_counting_table" annotations: "@p4runtime_role(\"sdn_controller\")" + annotations: "@sai_acl_priority(7)" annotations: "@sai_acl(INGRESS)" annotations: "@entry_restriction(\"\n // Only allow IP field matches for IP packets.\n dscp::mask != 0 -> (is_ip == 1 || is_ipv4 == 1 || is_ipv6 == 1);\n // Forbid illegal combinations of IP_TYPE fields.\n is_ip::mask != 0 -> (is_ipv4::mask == 0 && is_ipv6::mask == 0);\n is_ipv4::mask != 0 -> (is_ip::mask == 0 && is_ipv6::mask == 0);\n is_ipv6::mask != 0 -> (is_ip::mask == 0 && is_ipv4::mask == 0);\n // Forbid unsupported combinations of IP_TYPE fields.\n is_ipv4::mask != 0 -> (is_ipv4 == 1);\n is_ipv6::mask != 0 -> (is_ipv6 == 1);\n \")" } @@ -851,7 +850,6 @@ tables { id: 33554508 name: "egress.packet_rewrites.multicast_rewrites.multicast_router_interface_table" alias: "multicast_router_interface_table" - annotations: "@unsupported" annotations: "@p4runtime_role(\"sdn_controller\")" } match_fields { @@ -1123,7 +1121,6 @@ actions { id: 16777240 name: "ingress.routing_lookup.set_multicast_group_id" alias: "set_multicast_group_id" - annotations: "@unsupported" annotations: "@action_restriction(\"\n // Disallow 0 since it encodes \'no multicast\' in V1Model.\n multicast_group_id != 0;\n \")" } params { diff --git a/sai_p4/instantiations/google/middleblock.p4 b/sai_p4/instantiations/google/middleblock.p4 index de804fa0..254947db 100644 --- a/sai_p4/instantiations/google/middleblock.p4 +++ b/sai_p4/instantiations/google/middleblock.p4 @@ -20,6 +20,7 @@ #include "../../fixed/drop_martians.p4" #include "../../fixed/packet_rewrites.p4" #include "../../fixed/tunnel_termination.p4" +#include "acl_egress.p4" #include "acl_ingress.p4" #include "acl_pre_ingress.p4" #include "admit_google_system_mac.p4" @@ -62,6 +63,7 @@ control egress(inout headers_t headers, mirroring_encap.apply(headers, local_metadata, standard_metadata); egress_vlan_checks.apply(headers, local_metadata, standard_metadata); vlan_tag.apply(headers, local_metadata, standard_metadata); + acl_egress.apply(headers, local_metadata, standard_metadata); } } } // control egress diff --git a/sai_p4/instantiations/google/middleblock.p4info.pb.txt b/sai_p4/instantiations/google/middleblock.p4info.pb.txt index 49144381..8b77d355 100755 --- a/sai_p4/instantiations/google/middleblock.p4info.pb.txt +++ b/sai_p4/instantiations/google/middleblock.p4info.pb.txt @@ -94,14 +94,6 @@ tables { bitwidth: 48 match_type: TERNARY } - match_fields { - id: 9 - name: "dst_mac" - annotations: "@sai_field(SAI_ACL_TABLE_ATTR_FIELD_DST_MAC)" - annotations: "@format(MAC_ADDRESS)" - bitwidth: 48 - match_type: TERNARY - } match_fields { id: 5 name: "dst_ip" @@ -317,7 +309,6 @@ tables { name: "ingress.routing_lookup.ipv4_multicast_table" alias: "ipv4_multicast_table" annotations: "@p4runtime_role(\"sdn_controller\")" - annotations: "@unsupported" } match_fields { id: 1 @@ -352,7 +343,6 @@ tables { name: "ingress.routing_lookup.ipv6_multicast_table" alias: "ipv6_multicast_table" annotations: "@p4runtime_role(\"sdn_controller\")" - annotations: "@unsupported" } match_fields { id: 1 @@ -552,6 +542,7 @@ tables { name: "ingress.acl_ingress.acl_ingress_mirror_and_redirect_table" alias: "acl_ingress_mirror_and_redirect_table" annotations: "@sai_acl(INGRESS)" + annotations: "@sai_acl_priority(15)" annotations: "@p4runtime_role(\"sdn_controller\")" annotations: "@entry_restriction(\"\n // Only allow IP field matches for IP packets.\n dst_ip::mask != 0 -> is_ipv4 == 1;\n dst_ipv6::mask != 0 -> is_ipv6 == 1;\n // Forbid illegal combinations of IP_TYPE fields.\n is_ip::mask != 0 -> (is_ipv4::mask == 0 && is_ipv6::mask == 0);\n is_ipv4::mask != 0 -> (is_ip::mask == 0 && is_ipv6::mask == 0);\n is_ipv6::mask != 0 -> (is_ip::mask == 0 && is_ipv4::mask == 0);\n // Forbid unsupported combinations of IP_TYPE fields.\n is_ipv4::mask != 0 -> (is_ipv4 == 1);\n is_ipv6::mask != 0 -> (is_ipv6 == 1);\n \")" } @@ -610,6 +601,10 @@ tables { bitwidth: 1 match_type: OPTIONAL } + action_refs { + id: 16777475 + annotations: "@proto_id(4)" + } action_refs { id: 16777476 annotations: "@proto_id(1)" @@ -636,6 +631,7 @@ tables { name: "ingress.acl_ingress.acl_ingress_security_table" alias: "acl_ingress_security_table" annotations: "@sai_acl(INGRESS)" + annotations: "@sai_acl_priority(20)" annotations: "@p4runtime_role(\"sdn_controller\")" annotations: "@entry_restriction(\"\n // Forbid using ether_type for IP packets (by convention, use is_ip* instead).\n ether_type != 0x0800 && ether_type != 0x86dd;\n\n // Only allow IP field matches for IP packets.\n dst_ip::mask != 0 -> is_ipv4 == 1;\n src_ip::mask != 0 -> is_ipv4 == 1;\n src_ipv6::mask != 0 -> is_ipv6 == 1;\n\n // TODO: This comment is required for the preprocessor to not\n // spit out nonsense.\n\n\n\n\n\n\n\n // Forbid illegal combinations of IP_TYPE fields.\n is_ip::mask != 0 -> (is_ipv4::mask == 0 && is_ipv6::mask == 0);\n is_ipv4::mask != 0 -> (is_ip::mask == 0 && is_ipv6::mask == 0);\n is_ipv6::mask != 0 -> (is_ip::mask == 0 && is_ipv4::mask == 0);\n // Forbid unsupported combinations of IP_TYPE fields.\n is_ipv4::mask != 0 -> (is_ipv4 == 1);\n is_ipv6::mask != 0 -> (is_ipv6 == 1);\n \")" } @@ -945,7 +941,6 @@ tables { id: 33554508 name: "egress.packet_rewrites.multicast_rewrites.multicast_router_interface_table" alias: "multicast_router_interface_table" - annotations: "@unsupported" annotations: "@p4runtime_role(\"sdn_controller\")" } match_fields { @@ -975,6 +970,73 @@ tables { } size: 128 } +tables { + preamble { + id: 33554692 + name: "egress.acl_egress.acl_egress_table" + alias: "acl_egress_table" + annotations: "@p4runtime_role(\"sdn_controller\")" + annotations: "@sai_acl(EGRESS)" + annotations: "@entry_restriction(\"\n\n\n\n\n\n // Only allow IP field matches for IP packets.\n ip_protocol::mask != 0 -> (is_ip == 1 || is_ipv4 == 1 || is_ipv6 == 1);\n\n\n\n\n\n\n\n // Forbid illegal combinations of IP_TYPE fields.\n is_ip::mask != 0 -> (is_ipv4::mask == 0 && is_ipv6::mask == 0);\n is_ipv4::mask != 0 -> (is_ip::mask == 0 && is_ipv6::mask == 0);\n is_ipv6::mask != 0 -> (is_ip::mask == 0 && is_ipv4::mask == 0);\n // Forbid unsupported combinations of IP_TYPE fields.\n is_ipv4::mask != 0 -> (is_ipv4 == 1);\n is_ipv6::mask != 0 -> (is_ipv6 == 1);\n \")" + } + match_fields { + id: 2 + name: "ip_protocol" + annotations: "@sai_field(SAI_ACL_TABLE_ATTR_FIELD_IP_PROTOCOL)" + bitwidth: 8 + match_type: TERNARY + } + match_fields { + id: 4 + name: "out_port" + annotations: "@sai_field(SAI_ACL_TABLE_ATTR_FIELD_OUT_PORT)" + match_type: OPTIONAL + type_name { + name: "port_id_t" + } + } + match_fields { + id: 5 + name: "is_ip" + annotations: "@sai_field(SAI_ACL_TABLE_ATTR_FIELD_ACL_IP_TYPE / IP)" + bitwidth: 1 + match_type: OPTIONAL + } + match_fields { + id: 6 + name: "is_ipv4" + annotations: "@sai_field(SAI_ACL_TABLE_ATTR_FIELD_ACL_IP_TYPE / IPV4ANY)" + bitwidth: 1 + match_type: OPTIONAL + } + match_fields { + id: 7 + name: "is_ipv6" + annotations: "@sai_field(SAI_ACL_TABLE_ATTR_FIELD_ACL_IP_TYPE / IPV6ANY)" + bitwidth: 1 + match_type: OPTIONAL + } + match_fields { + id: 10 + name: "src_mac" + annotations: "@sai_field(SAI_ACL_TABLE_ATTR_FIELD_SRC_MAC)" + annotations: "@format(MAC_ADDRESS)" + bitwidth: 48 + match_type: TERNARY + } + action_refs { + id: 16777481 + annotations: "@proto_id(1)" + } + action_refs { + id: 21257015 + annotations: "@defaultonly" + scope: DEFAULT_ONLY + } + const_default_action_id: 21257015 + direct_resource_ids: 318767364 + size: 127 +} actions { preamble { id: 21257015 @@ -1137,7 +1199,6 @@ actions { id: 16777240 name: "ingress.routing_lookup.set_multicast_group_id" alias: "set_multicast_group_id" - annotations: "@unsupported" annotations: "@action_restriction(\"\n // Disallow 0 since it encodes \'no multicast\' in V1Model.\n multicast_group_id != 0;\n \")" } params { @@ -1243,6 +1304,7 @@ actions { id: 1 name: "multicast_group_id" annotations: "@sai_action_param(SAI_ACL_ENTRY_ATTR_ACTION_REDIRECT)" + annotations: "@refers_to(builtin : : multicast_group_table , multicast_group_id)" bitwidth: 16 } } @@ -1594,6 +1656,17 @@ direct_counters { } direct_table_id: 33554698 } +direct_counters { + preamble { + id: 318767364 + name: "egress.acl_egress.acl_egress_counter" + alias: "acl_egress_counter" + } + spec { + unit: BOTH + } + direct_table_id: 33554692 +} direct_meters { preamble { id: 352321792 diff --git a/sai_p4/instantiations/google/minimum_guaranteed_sizes.p4 b/sai_p4/instantiations/google/minimum_guaranteed_sizes.p4 index 4f10e692..e84aa64a 100644 --- a/sai_p4/instantiations/google/minimum_guaranteed_sizes.p4 +++ b/sai_p4/instantiations/google/minimum_guaranteed_sizes.p4 @@ -54,7 +54,8 @@ #define ROUTING_IPV4_MULTICAST_TABLE_MINIMUM_GUARANTEED_SIZE 1600 #define ROUTING_IPV6_MULTICAST_TABLE_MINIMUM_GUARANTEED_SIZE 1600 -#define ROUTING_MULTICAST_ROUTER_INTERFACE_TABLE_MINIMUM_GUARANTEED_SIZE 128 +// TODO: b/318522225 - multicast_router_interface_table runs out of space at 110 entries, expected 128 +#define ROUTING_MULTICAST_ROUTER_INTERFACE_TABLE_MINIMUM_GUARANTEED_SIZE 110 // The maximum number of wcmp groups. #define WCMP_GROUP_TABLE_MINIMUM_GUARANTEED_SIZE 3968 diff --git a/sai_p4/instantiations/google/sai_pd.proto b/sai_p4/instantiations/google/sai_pd.proto index 1eeecf62..70fc1f37 100755 --- a/sai_p4/instantiations/google/sai_pd.proto +++ b/sai_p4/instantiations/google/sai_pd.proto @@ -216,7 +216,6 @@ message Ipv6TunnelTerminationTableEntry { bytes controller_metadata = 8; } -// CAUTION: This table is not (yet) supported. message MulticastRouterInterfaceTableEntry { message Match { string multicast_replica_port = 1; // exact match / Format::STRING @@ -247,7 +246,6 @@ message DisableVlanChecksTableEntry { bytes controller_metadata = 8; } -// CAUTION: This table is not (yet) supported. message Ipv4MulticastTableEntry { message Match { // Refers to 'vrf_table.vrf_id'. @@ -256,14 +254,12 @@ message Ipv4MulticastTableEntry { } Match match = 1; message Action { - // CAUTION: This action is not (yet) supported. SetMulticastGroupIdAction set_multicast_group_id = 1; } Action action = 2; bytes controller_metadata = 8; } -// CAUTION: This table is not (yet) supported. message Ipv6MulticastTableEntry { message Match { // Refers to 'vrf_table.vrf_id'. @@ -272,7 +268,6 @@ message Ipv6MulticastTableEntry { } Match match = 1; message Action { - // CAUTION: This action is not (yet) supported. SetMulticastGroupIdAction set_multicast_group_id = 1; } Action action = 2; @@ -753,6 +748,7 @@ message AclIngressMirrorAndRedirectTableEntry { Match match = 1; message Action { oneof action { + AclForwardAction acl_forward = 4; AclMirrorAction acl_mirror = 1; RedirectToNexthopAction redirect_to_nexthop = 2; // CAUTION: This action is not (yet) supported. @@ -875,7 +871,6 @@ message SetIpNexthopAndDisableRewritesAction { string disable_vlan_rewrite = 6; // Format::HEX_STRING / 1 bits } -// CAUTION: This action is not (yet) supported. message SetMulticastGroupIdAction { string multicast_group_id = 1; // Format::HEX_STRING / 16 bits } @@ -1004,13 +999,10 @@ message TableEntry { VrfTableEntry vrf_table_entry = 74; // CAUTION: This table is not (yet) supported. Ipv6TunnelTerminationTableEntry ipv6_tunnel_termination_table_entry = 75; - // CAUTION: This table is not (yet) supported. MulticastRouterInterfaceTableEntry multicast_router_interface_table_entry = 76; DisableVlanChecksTableEntry disable_vlan_checks_table_entry = 77; - // CAUTION: This table is not (yet) supported. Ipv4MulticastTableEntry ipv4_multicast_table_entry = 78; - // CAUTION: This table is not (yet) supported. Ipv6MulticastTableEntry ipv6_multicast_table_entry = 79; TunnelTableEntry tunnel_table_entry = 80; AclIngressTableEntry acl_ingress_table_entry = 256; diff --git a/sai_p4/instantiations/google/tor.p4info.pb.txt b/sai_p4/instantiations/google/tor.p4info.pb.txt index 89ac4245..bd73629c 100644 --- a/sai_p4/instantiations/google/tor.p4info.pb.txt +++ b/sai_p4/instantiations/google/tor.p4info.pb.txt @@ -68,14 +68,6 @@ tables { bitwidth: 48 match_type: TERNARY } - match_fields { - id: 9 - name: "dst_mac" - annotations: "@sai_field(SAI_ACL_TABLE_ATTR_FIELD_DST_MAC)" - annotations: "@format(MAC_ADDRESS)" - bitwidth: 48 - match_type: TERNARY - } match_fields { id: 5 name: "dst_ip" @@ -421,7 +413,6 @@ tables { name: "ingress.routing_lookup.ipv4_multicast_table" alias: "ipv4_multicast_table" annotations: "@p4runtime_role(\"sdn_controller\")" - annotations: "@unsupported" } match_fields { id: 1 @@ -456,7 +447,6 @@ tables { name: "ingress.routing_lookup.ipv6_multicast_table" alias: "ipv6_multicast_table" annotations: "@p4runtime_role(\"sdn_controller\")" - annotations: "@unsupported" } match_fields { id: 1 @@ -796,6 +786,7 @@ tables { name: "ingress.acl_ingress.acl_ingress_mirror_and_redirect_table" alias: "acl_ingress_mirror_and_redirect_table" annotations: "@sai_acl(INGRESS)" + annotations: "@sai_acl_priority(15)" annotations: "@p4runtime_role(\"sdn_controller\")" annotations: "@entry_restriction(\"\n // Only allow IP field matches for IP packets.\n dst_ip::mask != 0 -> is_ipv4 == 1;\n dst_ipv6::mask != 0 -> is_ipv6 == 1;\n // Forbid illegal combinations of IP_TYPE fields.\n is_ip::mask != 0 -> (is_ipv4::mask == 0 && is_ipv6::mask == 0);\n is_ipv4::mask != 0 -> (is_ip::mask == 0 && is_ipv6::mask == 0);\n is_ipv6::mask != 0 -> (is_ip::mask == 0 && is_ipv4::mask == 0);\n // Forbid unsupported combinations of IP_TYPE fields.\n is_ipv4::mask != 0 -> (is_ipv4 == 1);\n is_ipv6::mask != 0 -> (is_ipv6 == 1);\n \")" } @@ -877,6 +868,10 @@ tables { bitwidth: 1 match_type: OPTIONAL } + action_refs { + id: 16777475 + annotations: "@proto_id(4)" + } action_refs { id: 16777476 annotations: "@proto_id(1)" @@ -1130,7 +1125,6 @@ tables { id: 33554508 name: "egress.packet_rewrites.multicast_rewrites.multicast_router_interface_table" alias: "multicast_router_interface_table" - annotations: "@unsupported" annotations: "@p4runtime_role(\"sdn_controller\")" } match_fields { @@ -1481,7 +1475,6 @@ actions { id: 16777240 name: "ingress.routing_lookup.set_multicast_group_id" alias: "set_multicast_group_id" - annotations: "@unsupported" annotations: "@action_restriction(\"\n // Disallow 0 since it encodes \'no multicast\' in V1Model.\n multicast_group_id != 0;\n \")" } params { @@ -1660,6 +1653,7 @@ actions { id: 1 name: "multicast_group_id" annotations: "@sai_action_param(SAI_ACL_ENTRY_ATTR_ACTION_REDIRECT)" + annotations: "@refers_to(builtin : : multicast_group_table , multicast_group_id)" bitwidth: 16 } } diff --git a/sai_p4/instantiations/google/unioned_p4info.pb.txt b/sai_p4/instantiations/google/unioned_p4info.pb.txt index 12b7e0d2..2b6c1fb9 100644 --- a/sai_p4/instantiations/google/unioned_p4info.pb.txt +++ b/sai_p4/instantiations/google/unioned_p4info.pb.txt @@ -317,7 +317,6 @@ tables { name: "ingress.routing_lookup.ipv4_multicast_table" alias: "ipv4_multicast_table" annotations: "@p4runtime_role(\"sdn_controller\")" - annotations: "@unsupported" } match_fields { id: 1 @@ -352,7 +351,6 @@ tables { name: "ingress.routing_lookup.ipv6_multicast_table" alias: "ipv6_multicast_table" annotations: "@p4runtime_role(\"sdn_controller\")" - annotations: "@unsupported" } match_fields { id: 1 @@ -577,6 +575,7 @@ tables { name: "ingress.acl_ingress.acl_ingress_counting_table" alias: "acl_ingress_counting_table" annotations: "@p4runtime_role(\"sdn_controller\")" + annotations: "@sai_acl_priority(7)" annotations: "@sai_acl(INGRESS)" annotations: "@entry_restriction(\"\n // Only allow IP field matches for IP packets.\n dscp::mask != 0 -> (is_ip == 1 || is_ipv4 == 1 || is_ipv6 == 1);\n // Forbid illegal combinations of IP_TYPE fields.\n is_ip::mask != 0 -> (is_ipv4::mask == 0 && is_ipv6::mask == 0);\n is_ipv4::mask != 0 -> (is_ip::mask == 0 && is_ipv6::mask == 0);\n is_ipv6::mask != 0 -> (is_ip::mask == 0 && is_ipv4::mask == 0);\n // Forbid unsupported combinations of IP_TYPE fields.\n is_ipv4::mask != 0 -> (is_ipv4 == 1);\n is_ipv6::mask != 0 -> (is_ipv6 == 1);\n \")" } @@ -861,7 +860,6 @@ tables { id: 33554508 name: "egress.packet_rewrites.multicast_rewrites.multicast_router_interface_table" alias: "multicast_router_interface_table" - annotations: "@unsupported" annotations: "@p4runtime_role(\"sdn_controller\")" } match_fields { @@ -899,6 +897,7 @@ tables { annotations: "@p4runtime_role(\"sdn_controller\")" annotations: "@sai_acl(EGRESS)" annotations: "@entry_restriction(\"\n\n // Forbid using ether_type for IP packets (by convention, use is_ip* instead).\n ether_type != 0x0800 && ether_type != 0x86dd;\n dscp::mask != 0 -> (is_ip == 1 || is_ipv4 == 1 || is_ipv6 == 1);\n\n // Only allow IP field matches for IP packets.\n ip_protocol::mask != 0 -> (is_ip == 1 || is_ipv4 == 1 || is_ipv6 == 1);\n\n\n\n\n // Only allow l4_dst_port matches for TCP/UDP packets.\n l4_dst_port::mask != 0 -> (ip_protocol == 6 || ip_protocol == 17);\n\n // Forbid illegal combinations of IP_TYPE fields.\n is_ip::mask != 0 -> (is_ipv4::mask == 0 && is_ipv6::mask == 0);\n is_ipv4::mask != 0 -> (is_ip::mask == 0 && is_ipv6::mask == 0);\n is_ipv6::mask != 0 -> (is_ip::mask == 0 && is_ipv4::mask == 0);\n // Forbid unsupported combinations of IP_TYPE fields.\n is_ipv4::mask != 0 -> (is_ipv4 == 1);\n is_ipv6::mask != 0 -> (is_ipv6 == 1);\n \")" + annotations: "@entry_restriction(\"\n\n\n\n\n\n // Only allow IP field matches for IP packets.\n ip_protocol::mask != 0 -> (is_ip == 1 || is_ipv4 == 1 || is_ipv6 == 1);\n\n\n\n\n\n\n\n // Forbid illegal combinations of IP_TYPE fields.\n is_ip::mask != 0 -> (is_ipv4::mask == 0 && is_ipv6::mask == 0);\n is_ipv4::mask != 0 -> (is_ip::mask == 0 && is_ipv6::mask == 0);\n is_ipv6::mask != 0 -> (is_ip::mask == 0 && is_ipv4::mask == 0);\n // Forbid unsupported combinations of IP_TYPE fields.\n is_ipv4::mask != 0 -> (is_ipv4 == 1);\n is_ipv6::mask != 0 -> (is_ipv6 == 1);\n \")" annotations: "@entry_restriction(\"\n\n\n\n\n\n // Only allow IP field matches for IP packets.\n ip_protocol::mask != 0 -> (is_ip == 1 || is_ipv4 == 1 || is_ipv6 == 1);\n\n dst_ipv6::mask != 0 -> is_ipv6 == 1;\n\n\n\n\n\n // Forbid illegal combinations of IP_TYPE fields.\n is_ip::mask != 0 -> (is_ipv4::mask == 0 && is_ipv6::mask == 0);\n is_ipv4::mask != 0 -> (is_ip::mask == 0 && is_ipv6::mask == 0);\n is_ipv6::mask != 0 -> (is_ip::mask == 0 && is_ipv4::mask == 0);\n // Forbid unsupported combinations of IP_TYPE fields.\n is_ipv4::mask != 0 -> (is_ipv4 == 1);\n is_ipv6::mask != 0 -> (is_ipv6 == 1);\n \")" } match_fields { @@ -959,14 +958,6 @@ tables { bitwidth: 6 match_type: TERNARY } - match_fields { - id: 9 - name: "dst_ipv6" - annotations: "@composite_field(@ sai_field ( SAI_ACL_TABLE_ATTR_FIELD_DST_IPV6_WORD3 ) , @ sai_field ( SAI_ACL_TABLE_ATTR_FIELD_DST_IPV6_WORD2 ))" - annotations: "@format(IPV6_ADDRESS)" - bitwidth: 64 - match_type: TERNARY - } match_fields { id: 10 name: "src_mac" @@ -975,6 +966,14 @@ tables { bitwidth: 48 match_type: TERNARY } + match_fields { + id: 9 + name: "dst_ipv6" + annotations: "@composite_field(@ sai_field ( SAI_ACL_TABLE_ATTR_FIELD_DST_IPV6_WORD3 ) , @ sai_field ( SAI_ACL_TABLE_ATTR_FIELD_DST_IPV6_WORD2 ))" + annotations: "@format(IPV6_ADDRESS)" + bitwidth: 64 + match_type: TERNARY + } action_refs { id: 16777481 annotations: "@proto_id(1)" @@ -998,6 +997,7 @@ tables { name: "ingress.acl_ingress.acl_ingress_mirror_and_redirect_table" alias: "acl_ingress_mirror_and_redirect_table" annotations: "@sai_acl(INGRESS)" + annotations: "@sai_acl_priority(15)" annotations: "@p4runtime_role(\"sdn_controller\")" annotations: "@entry_restriction(\"\n // Only allow IP field matches for IP packets.\n dst_ip::mask != 0 -> is_ipv4 == 1;\n dst_ipv6::mask != 0 -> is_ipv6 == 1;\n // Forbid illegal combinations of IP_TYPE fields.\n is_ip::mask != 0 -> (is_ipv4::mask == 0 && is_ipv6::mask == 0);\n is_ipv4::mask != 0 -> (is_ip::mask == 0 && is_ipv6::mask == 0);\n is_ipv6::mask != 0 -> (is_ip::mask == 0 && is_ipv4::mask == 0);\n // Forbid unsupported combinations of IP_TYPE fields.\n is_ipv4::mask != 0 -> (is_ipv4 == 1);\n is_ipv6::mask != 0 -> (is_ipv6 == 1);\n \")" } @@ -1079,6 +1079,10 @@ tables { bitwidth: 12 match_type: TERNARY } + action_refs { + id: 16777475 + annotations: "@proto_id(4)" + } action_refs { id: 16777476 annotations: "@proto_id(1)" @@ -1105,6 +1109,7 @@ tables { name: "ingress.acl_ingress.acl_ingress_security_table" alias: "acl_ingress_security_table" annotations: "@sai_acl(INGRESS)" + annotations: "@sai_acl_priority(20)" annotations: "@p4runtime_role(\"sdn_controller\")" annotations: "@entry_restriction(\"\n // Forbid using ether_type for IP packets (by convention, use is_ip* instead).\n ether_type != 0x0800 && ether_type != 0x86dd;\n\n // Only allow IP field matches for IP packets.\n dst_ip::mask != 0 -> is_ipv4 == 1;\n src_ip::mask != 0 -> is_ipv4 == 1;\n src_ipv6::mask != 0 -> is_ipv6 == 1;\n\n // TODO: This comment is required for the preprocessor to not\n // spit out nonsense.\n\n\n\n\n\n\n\n // Forbid illegal combinations of IP_TYPE fields.\n is_ip::mask != 0 -> (is_ipv4::mask == 0 && is_ipv6::mask == 0);\n is_ipv4::mask != 0 -> (is_ip::mask == 0 && is_ipv6::mask == 0);\n is_ipv6::mask != 0 -> (is_ip::mask == 0 && is_ipv4::mask == 0);\n // Forbid unsupported combinations of IP_TYPE fields.\n is_ipv4::mask != 0 -> (is_ipv4 == 1);\n is_ipv6::mask != 0 -> (is_ipv6 == 1);\n \")" } @@ -1733,7 +1738,6 @@ actions { id: 16777240 name: "ingress.routing_lookup.set_multicast_group_id" alias: "set_multicast_group_id" - annotations: "@unsupported" annotations: "@action_restriction(\"\n // Disallow 0 since it encodes \'no multicast\' in V1Model.\n multicast_group_id != 0;\n \")" } params { @@ -2154,6 +2158,7 @@ actions { id: 1 name: "multicast_group_id" annotations: "@sai_action_param(SAI_ACL_ENTRY_ATTR_ACTION_REDIRECT)" + annotations: "@refers_to(builtin : : multicast_group_table , multicast_group_id)" bitwidth: 16 } } From a2b8e045d80b132dd3005e2d51e42deac1dc1ba2 Mon Sep 17 00:00:00 2001 From: rhalstea Date: Wed, 24 Jan 2024 08:39:37 -0800 Subject: [PATCH 5/6] [SAIP4] Add ACL QoS table to FBR instances. --- sai_p4/instantiations/google/acl_ingress.p4 | 42 +- .../google/fabric_border_router.p4info.pb.txt | 228 +++++++++ sai_p4/instantiations/google/sai_pd.proto | 12 +- .../test_tools/table_entry_generator.cc | 9 +- .../instantiations/google/tor.p4info.pb.txt | 34 +- .../google/unioned_p4info.pb.txt | 476 +++++++++--------- 6 files changed, 538 insertions(+), 263 deletions(-) diff --git a/sai_p4/instantiations/google/acl_ingress.p4 b/sai_p4/instantiations/google/acl_ingress.p4 index 85079253..44fe83d5 100644 --- a/sai_p4/instantiations/google/acl_ingress.p4 +++ b/sai_p4/instantiations/google/acl_ingress.p4 @@ -318,7 +318,7 @@ control acl_ingress(in headers_t headers, // Only allow IP field matches for IP packets. ttl::mask != 0 -> (is_ip == 1 || is_ipv4 == 1 || is_ipv6 == 1); ip_protocol::mask != 0 -> (is_ip == 1 || is_ipv4 == 1 || is_ipv6 == 1); - // Only allow l4_dst_port and l4_src_port matches for TCP/UDP packets. + // Only allow l4_dst_port matches for TCP/UDP packets. l4_dst_port::mask != 0 -> (ip_protocol == 6 || ip_protocol == 17); // Forbid illegal combinations of IP_TYPE fields. is_ip::mask != 0 -> (is_ipv4::mask == 0 && is_ipv6::mask == 0); @@ -329,8 +329,16 @@ control acl_ingress(in headers_t headers, is_ipv6::mask != 0 -> (is_ipv6 == 1); // Only allow icmp_type matches for ICMP packets icmpv6_type::mask != 0 -> ip_protocol == 58; +#ifdef SAI_INSTANTIATION_FABRIC_BORDER_ROUTER + // Only allow l4_dst_port matches for TCP/UDP packets. + l4_src_port::mask != 0 -> (ip_protocol == 6 || ip_protocol == 17); + // Only allow icmp_type matches for ICMP packets + icmp_type::mask != 0 -> ip_protocol == 1; +#endif +#if defined(SAI_INSTANTIATION_TOR) // Only allow arp_tpa matches for ARP packets. arp_tpa::mask != 0 -> ether_type == 0x0806; +#endif ") table acl_ingress_qos_table { key = { @@ -346,15 +354,6 @@ control acl_ingress(in headers_t headers, headers.ethernet.ether_type : ternary @id(4) @name("ether_type") @sai_field(SAI_ACL_TABLE_ATTR_FIELD_ETHER_TYPE); - headers.ethernet.dst_addr : ternary - @id(5) @name("dst_mac") - @sai_field(SAI_ACL_TABLE_ATTR_FIELD_DST_MAC) @format(MAC_ADDRESS); - headers.arp.target_proto_addr : ternary - @id(6) @name("arp_tpa") - @composite_field( - @sai_udf(base=SAI_UDF_BASE_L3, offset=24, length=2), - @sai_udf(base=SAI_UDF_BASE_L3, offset=26, length=2) - ) @format(IPV4_ADDRESS); ttl : ternary @id(7) @name("ttl") @sai_field(SAI_ACL_TABLE_ATTR_FIELD_TTL); @@ -367,12 +366,34 @@ control acl_ingress(in headers_t headers, local_metadata.l4_dst_port : ternary @id(10) @name("l4_dst_port") @sai_field(SAI_ACL_TABLE_ATTR_FIELD_L4_DST_PORT); +#ifdef SAI_INSTANTIATION_FABRIC_BORDER_ROUTER + local_metadata.l4_src_port : ternary + @id(12) @name("l4_src_port") + @sai_field(SAI_ACL_TABLE_ATTR_FIELD_L4_SRC_PORT); + headers.icmp.type : ternary + @id(14) @name("icmp_type") + @sai_field(SAI_ACL_TABLE_ATTR_FIELD_ICMP_TYPE); + local_metadata.route_metadata : optional + @id(15) @name("route_metadata") + @sai_field(SAI_ACL_TABLE_ATTR_FIELD_ROUTE_DST_USER_META); +#endif +#if defined(SAI_INSTANTIATION_TOR) + headers.ethernet.dst_addr : ternary + @id(5) @name("dst_mac") + @sai_field(SAI_ACL_TABLE_ATTR_FIELD_DST_MAC) @format(MAC_ADDRESS); + headers.arp.target_proto_addr : ternary + @id(6) @name("arp_tpa") + @composite_field( + @sai_udf(base=SAI_UDF_BASE_L3, offset=24, length=2), + @sai_udf(base=SAI_UDF_BASE_L3, offset=26, length=2) + ) @format(IPV4_ADDRESS); local_metadata.ingress_port : optional @id(11) @name("in_port") @sai_field(SAI_ACL_TABLE_ATTR_FIELD_IN_PORT); local_metadata.acl_metadata : ternary @id(13) @name("acl_metadata") @sai_field(SAI_ACL_TABLE_ATTR_FIELD_ACL_USER_META); +#endif } actions = { @proto_id(1) set_qos_queue_and_cancel_copy_above_rate_limit(); @@ -666,6 +687,7 @@ control acl_ingress(in headers_t headers, #elif defined(SAI_INSTANTIATION_FABRIC_BORDER_ROUTER) acl_ingress_table.apply(); acl_ingress_counting_table.apply(); + acl_ingress_qos_table.apply(); #elif defined(SAI_INSTANTIATION_TOR) // These tables are currently order agnostic, but we should be careful to // ensure that the ordering is correct if we add new actions or model diff --git a/sai_p4/instantiations/google/fabric_border_router.p4info.pb.txt b/sai_p4/instantiations/google/fabric_border_router.p4info.pb.txt index f9d8f6bf..e9e1ec86 100644 --- a/sai_p4/instantiations/google/fabric_border_router.p4info.pb.txt +++ b/sai_p4/instantiations/google/fabric_border_router.p4info.pb.txt @@ -559,6 +559,127 @@ tables { direct_resource_ids: 352321792 size: 256 } +tables { + preamble { + id: 33554695 + name: "ingress.acl_ingress.acl_ingress_qos_table" + alias: "acl_ingress_qos_table" + annotations: "@sai_acl(INGRESS)" + annotations: "@sai_acl_priority(10)" + annotations: "@p4runtime_role(\"sdn_controller\")" + annotations: "@entry_restriction(\"\n // Forbid using ether_type for IP packets (by convention, use is_ip* instead).\n ether_type != 0x0800 && ether_type != 0x86dd;\n // Only allow IP field matches for IP packets.\n ttl::mask != 0 -> (is_ip == 1 || is_ipv4 == 1 || is_ipv6 == 1);\n ip_protocol::mask != 0 -> (is_ip == 1 || is_ipv4 == 1 || is_ipv6 == 1);\n // Only allow l4_dst_port matches for TCP/UDP packets.\n l4_dst_port::mask != 0 -> (ip_protocol == 6 || ip_protocol == 17);\n // Forbid illegal combinations of IP_TYPE fields.\n is_ip::mask != 0 -> (is_ipv4::mask == 0 && is_ipv6::mask == 0);\n is_ipv4::mask != 0 -> (is_ip::mask == 0 && is_ipv6::mask == 0);\n is_ipv6::mask != 0 -> (is_ip::mask == 0 && is_ipv4::mask == 0);\n // Forbid unsupported combinations of IP_TYPE fields.\n is_ipv4::mask != 0 -> (is_ipv4 == 1);\n is_ipv6::mask != 0 -> (is_ipv6 == 1);\n // Only allow icmp_type matches for ICMP packets\n icmpv6_type::mask != 0 -> ip_protocol == 58;\n\n // Only allow l4_dst_port matches for TCP/UDP packets.\n l4_src_port::mask != 0 -> (ip_protocol == 6 || ip_protocol == 17);\n // Only allow icmp_type matches for ICMP packets\n icmp_type::mask != 0 -> ip_protocol == 1;\n\n\n\n\n\n \")" + } + match_fields { + id: 1 + name: "is_ip" + annotations: "@sai_field(SAI_ACL_TABLE_ATTR_FIELD_ACL_IP_TYPE / IP)" + bitwidth: 1 + match_type: OPTIONAL + } + match_fields { + id: 2 + name: "is_ipv4" + annotations: "@sai_field(SAI_ACL_TABLE_ATTR_FIELD_ACL_IP_TYPE / IPV4ANY)" + bitwidth: 1 + match_type: OPTIONAL + } + match_fields { + id: 3 + name: "is_ipv6" + annotations: "@sai_field(SAI_ACL_TABLE_ATTR_FIELD_ACL_IP_TYPE / IPV6ANY)" + bitwidth: 1 + match_type: OPTIONAL + } + match_fields { + id: 4 + name: "ether_type" + annotations: "@sai_field(SAI_ACL_TABLE_ATTR_FIELD_ETHER_TYPE)" + bitwidth: 16 + match_type: TERNARY + } + match_fields { + id: 7 + name: "ttl" + annotations: "@sai_field(SAI_ACL_TABLE_ATTR_FIELD_TTL)" + bitwidth: 8 + match_type: TERNARY + } + match_fields { + id: 8 + name: "ip_protocol" + annotations: "@sai_field(SAI_ACL_TABLE_ATTR_FIELD_IP_PROTOCOL)" + bitwidth: 8 + match_type: TERNARY + } + match_fields { + id: 9 + name: "icmpv6_type" + annotations: "@sai_field(SAI_ACL_TABLE_ATTR_FIELD_ICMPV6_TYPE)" + bitwidth: 8 + match_type: TERNARY + } + match_fields { + id: 10 + name: "l4_dst_port" + annotations: "@sai_field(SAI_ACL_TABLE_ATTR_FIELD_L4_DST_PORT)" + bitwidth: 16 + match_type: TERNARY + } + match_fields { + id: 12 + name: "l4_src_port" + annotations: "@sai_field(SAI_ACL_TABLE_ATTR_FIELD_L4_SRC_PORT)" + bitwidth: 16 + match_type: TERNARY + } + match_fields { + id: 14 + name: "icmp_type" + annotations: "@sai_field(SAI_ACL_TABLE_ATTR_FIELD_ICMP_TYPE)" + bitwidth: 8 + match_type: TERNARY + } + match_fields { + id: 15 + name: "route_metadata" + annotations: "@sai_field(SAI_ACL_TABLE_ATTR_FIELD_ROUTE_DST_USER_META)" + bitwidth: 6 + match_type: OPTIONAL + } + action_refs { + id: 16777484 + annotations: "@proto_id(1)" + } + action_refs { + id: 16777486 + annotations: "@proto_id(2)" + } + action_refs { + id: 16777475 + annotations: "@proto_id(3)" + } + action_refs { + id: 16777481 + annotations: "@proto_id(4)" + } + action_refs { + id: 16777488 + annotations: "@proto_id(5)" + } + action_refs { + id: 16777489 + annotations: "@proto_id(6)" + } + action_refs { + id: 21257015 + annotations: "@defaultonly" + scope: DEFAULT_ONLY + } + const_default_action_id: 21257015 + direct_resource_ids: 318767367 + direct_resource_ids: 352321794 + size: 511 +} tables { preamble { id: 33554697 @@ -1198,6 +1319,90 @@ actions { } } } +actions { + preamble { + id: 16777484 + name: "ingress.acl_ingress.set_qos_queue_and_cancel_copy_above_rate_limit" + alias: "set_qos_queue_and_cancel_copy_above_rate_limit" + annotations: "@sai_action(SAI_PACKET_ACTION_FORWARD , SAI_PACKET_COLOR_GREEN)" + annotations: "@sai_action(SAI_PACKET_ACTION_COPY_CANCEL , SAI_PACKET_COLOR_RED)" + } + params { + id: 1 + name: "qos_queue" + annotations: "@sai_action_param(QOS_QUEUE)" + type_name { + name: "qos_queue_t" + } + } +} +actions { + preamble { + id: 16777489 + name: "ingress.acl_ingress.set_cpu_and_multicast_queues_and_deny_above_rate_limit" + alias: "set_cpu_and_multicast_queues_and_deny_above_rate_limit" + annotations: "@sai_action(SAI_PACKET_ACTION_FORWARD , SAI_PACKET_COLOR_GREEN)" + annotations: "@sai_action(SAI_PACKET_ACTION_DENY , SAI_PACKET_COLOR_RED)" + annotations: "@unsupported" + } + params { + id: 1 + name: "cpu_queue" + annotations: "@sai_action_param(QOS_QUEUE)" + type_name { + name: "qos_queue_t" + } + } + params { + id: 2 + name: "green_multicast_queue" + annotations: "@sai_action_param(MULTICAST_QOS_QUEUE , SAI_PACKET_COLOR_GREEN)" + type_name { + name: "qos_queue_t" + } + } + params { + id: 3 + name: "red_multicast_queue" + annotations: "@sai_action_param(MULTICAST_QOS_QUEUE , SAI_PACKET_COLOR_RED)" + type_name { + name: "qos_queue_t" + } + } +} +actions { + preamble { + id: 16777486 + name: "ingress.acl_ingress.set_cpu_queue_and_deny_above_rate_limit" + alias: "set_cpu_queue_and_deny_above_rate_limit" + annotations: "@sai_action(SAI_PACKET_ACTION_FORWARD , SAI_PACKET_COLOR_GREEN)" + annotations: "@sai_action(SAI_PACKET_ACTION_DENY , SAI_PACKET_COLOR_RED)" + } + params { + id: 1 + name: "cpu_queue" + annotations: "@sai_action_param(QOS_QUEUE)" + type_name { + name: "qos_queue_t" + } + } +} +actions { + preamble { + id: 16777488 + name: "ingress.acl_ingress.set_cpu_queue" + alias: "set_cpu_queue" + annotations: "@sai_action(SAI_PACKET_ACTION_FORWARD)" + } + params { + id: 1 + name: "cpu_queue" + annotations: "@sai_action_param(QOS_QUEUE)" + type_name { + name: "qos_queue_t" + } + } +} actions { preamble { id: 16777217 @@ -1535,6 +1740,17 @@ direct_counters { } direct_table_id: 33554688 } +direct_counters { + preamble { + id: 318767367 + name: "ingress.acl_ingress.acl_ingress_qos_counter" + alias: "acl_ingress_qos_counter" + } + spec { + unit: BOTH + } + direct_table_id: 33554695 +} direct_counters { preamble { id: 318767369 @@ -1569,6 +1785,18 @@ direct_meters { } direct_table_id: 33554688 } +direct_meters { + preamble { + id: 352321794 + name: "ingress.acl_ingress.acl_ingress_qos_meter" + alias: "acl_ingress_qos_meter" + annotations: "@mode(single_rate_two_color)" + } + spec { + unit: BYTES + } + direct_table_id: 33554695 +} controller_packet_metadata { preamble { id: 81826293 diff --git a/sai_p4/instantiations/google/sai_pd.proto b/sai_p4/instantiations/google/sai_pd.proto index 70fc1f37..377a1a63 100755 --- a/sai_p4/instantiations/google/sai_pd.proto +++ b/sai_p4/instantiations/google/sai_pd.proto @@ -561,7 +561,7 @@ message AclPreIngressMetadataTableEntry { // ## Only allow IP field matches for IP packets. // ttl::mask != 0 -> (is_ip == 1 || is_ipv4 == 1 || is_ipv6 == 1); // ip_protocol::mask != 0 -> (is_ip == 1 || is_ipv4 == 1 || is_ipv6 == 1); -// ## Only allow l4_dst_port and l4_src_port matches for TCP/UDP packets. +// ## Only allow l4_dst_port matches for TCP/UDP packets. // l4_dst_port::mask != 0 -> (ip_protocol == 6 || ip_protocol == 17); // ## Forbid illegal combinations of IP_TYPE fields. // is_ip::mask != 0 -> (is_ipv4::mask == 0 && is_ipv6::mask == 0); @@ -572,8 +572,10 @@ message AclPreIngressMetadataTableEntry { // is_ipv6::mask != 0 -> (is_ipv6 == 1); // ## Only allow icmp_type matches for ICMP packets // icmpv6_type::mask != 0 -> ip_protocol == 58; -// ## Only allow arp_tpa matches for ARP packets. -// arp_tpa::mask != 0 -> ether_type == 0x0806; +// ## Only allow l4_dst_port matches for TCP/UDP packets. +// l4_src_port::mask != 0 -> (ip_protocol == 6 || ip_protocol == 17); +// ## Only allow icmp_type matches for ICMP packets +// icmp_type::mask != 0 -> ip_protocol == 1; message AclIngressQosTableEntry { message Match { Optional is_ip = 1; // optional match / Format::HEX_STRING / 1 bits @@ -587,7 +589,11 @@ message AclIngressQosTableEntry { Ternary icmpv6_type = 9; // ternary match / Format::HEX_STRING / 8 bits Ternary l4_dst_port = 10; // ternary match / Format::HEX_STRING / 16 bits Optional in_port = 11; // optional match / Format::STRING + Ternary l4_src_port = 12; // ternary match / Format::HEX_STRING / 16 bits Ternary acl_metadata = 13; // ternary match / Format::HEX_STRING / 8 bits + Ternary icmp_type = 14; // ternary match / Format::HEX_STRING / 8 bits + Optional route_metadata = + 15; // optional match / Format::HEX_STRING / 6 bits } Match match = 1; message Action { diff --git a/sai_p4/instantiations/google/test_tools/table_entry_generator.cc b/sai_p4/instantiations/google/test_tools/table_entry_generator.cc index 2a3abeec..a6028f40 100644 --- a/sai_p4/instantiations/google/test_tools/table_entry_generator.cc +++ b/sai_p4/instantiations/google/test_tools/table_entry_generator.cc @@ -229,11 +229,8 @@ TableEntryGenerator AclIngressQosTableGenerator( auto base_entry = gutil::ParseTextProto( R"pb(table_name: "acl_ingress_qos_table" matches { - name: "ether_type" - ternary { - value { hex_str: "0x0806" } - mask { hex_str: "0xffff" } - } + name: "is_ipv4" + optional { value { hex_str: "0x1" } } } action { name: "set_qos_queue_and_cancel_copy_above_rate_limit" @@ -244,7 +241,7 @@ TableEntryGenerator AclIngressQosTableGenerator( })pb"); if (!base_entry.ok()) LOG(FATAL) << base_entry.status(); // Crash OK generator.generator = IrMatchFieldAndPriorityGenerator( - table_definition, *base_entry, "arp_tpa"); + table_definition, *base_entry, "ip_protocol"); return generator; } diff --git a/sai_p4/instantiations/google/tor.p4info.pb.txt b/sai_p4/instantiations/google/tor.p4info.pb.txt index bd73629c..46d6a7f9 100644 --- a/sai_p4/instantiations/google/tor.p4info.pb.txt +++ b/sai_p4/instantiations/google/tor.p4info.pb.txt @@ -656,7 +656,7 @@ tables { annotations: "@sai_acl(INGRESS)" annotations: "@sai_acl_priority(10)" annotations: "@p4runtime_role(\"sdn_controller\")" - annotations: "@entry_restriction(\"\n // Forbid using ether_type for IP packets (by convention, use is_ip* instead).\n ether_type != 0x0800 && ether_type != 0x86dd;\n // Only allow IP field matches for IP packets.\n ttl::mask != 0 -> (is_ip == 1 || is_ipv4 == 1 || is_ipv6 == 1);\n ip_protocol::mask != 0 -> (is_ip == 1 || is_ipv4 == 1 || is_ipv6 == 1);\n // Only allow l4_dst_port and l4_src_port matches for TCP/UDP packets.\n l4_dst_port::mask != 0 -> (ip_protocol == 6 || ip_protocol == 17);\n // Forbid illegal combinations of IP_TYPE fields.\n is_ip::mask != 0 -> (is_ipv4::mask == 0 && is_ipv6::mask == 0);\n is_ipv4::mask != 0 -> (is_ip::mask == 0 && is_ipv6::mask == 0);\n is_ipv6::mask != 0 -> (is_ip::mask == 0 && is_ipv4::mask == 0);\n // Forbid unsupported combinations of IP_TYPE fields.\n is_ipv4::mask != 0 -> (is_ipv4 == 1);\n is_ipv6::mask != 0 -> (is_ipv6 == 1);\n // Only allow icmp_type matches for ICMP packets\n icmpv6_type::mask != 0 -> ip_protocol == 58;\n // Only allow arp_tpa matches for ARP packets.\n arp_tpa::mask != 0 -> ether_type == 0x0806;\n \")" + annotations: "@entry_restriction(\"\n // Forbid using ether_type for IP packets (by convention, use is_ip* instead).\n ether_type != 0x0800 && ether_type != 0x86dd;\n // Only allow IP field matches for IP packets.\n ttl::mask != 0 -> (is_ip == 1 || is_ipv4 == 1 || is_ipv6 == 1);\n ip_protocol::mask != 0 -> (is_ip == 1 || is_ipv4 == 1 || is_ipv6 == 1);\n // Only allow l4_dst_port matches for TCP/UDP packets.\n l4_dst_port::mask != 0 -> (ip_protocol == 6 || ip_protocol == 17);\n // Forbid illegal combinations of IP_TYPE fields.\n is_ip::mask != 0 -> (is_ipv4::mask == 0 && is_ipv6::mask == 0);\n is_ipv4::mask != 0 -> (is_ip::mask == 0 && is_ipv6::mask == 0);\n is_ipv6::mask != 0 -> (is_ip::mask == 0 && is_ipv4::mask == 0);\n // Forbid unsupported combinations of IP_TYPE fields.\n is_ipv4::mask != 0 -> (is_ipv4 == 1);\n is_ipv6::mask != 0 -> (is_ipv6 == 1);\n // Only allow icmp_type matches for ICMP packets\n icmpv6_type::mask != 0 -> ip_protocol == 58;\n\n\n\n\n\n\n\n // Only allow arp_tpa matches for ARP packets.\n arp_tpa::mask != 0 -> ether_type == 0x0806;\n\n \")" } match_fields { id: 1 @@ -686,22 +686,6 @@ tables { bitwidth: 16 match_type: TERNARY } - match_fields { - id: 5 - name: "dst_mac" - annotations: "@sai_field(SAI_ACL_TABLE_ATTR_FIELD_DST_MAC)" - annotations: "@format(MAC_ADDRESS)" - bitwidth: 48 - match_type: TERNARY - } - match_fields { - id: 6 - name: "arp_tpa" - annotations: "@composite_field(@ sai_udf ( base = SAI_UDF_BASE_L3 , offset = 24 , length = 2 ) , @ sai_udf ( base = SAI_UDF_BASE_L3 , offset = 26 , length = 2 ))" - annotations: "@format(IPV4_ADDRESS)" - bitwidth: 32 - match_type: TERNARY - } match_fields { id: 7 name: "ttl" @@ -730,6 +714,22 @@ tables { bitwidth: 16 match_type: TERNARY } + match_fields { + id: 5 + name: "dst_mac" + annotations: "@sai_field(SAI_ACL_TABLE_ATTR_FIELD_DST_MAC)" + annotations: "@format(MAC_ADDRESS)" + bitwidth: 48 + match_type: TERNARY + } + match_fields { + id: 6 + name: "arp_tpa" + annotations: "@composite_field(@ sai_udf ( base = SAI_UDF_BASE_L3 , offset = 24 , length = 2 ) , @ sai_udf ( base = SAI_UDF_BASE_L3 , offset = 26 , length = 2 ))" + annotations: "@format(IPV4_ADDRESS)" + bitwidth: 32 + match_type: TERNARY + } match_fields { id: 11 name: "in_port" diff --git a/sai_p4/instantiations/google/unioned_p4info.pb.txt b/sai_p4/instantiations/google/unioned_p4info.pb.txt index 2b6c1fb9..97671f6d 100644 --- a/sai_p4/instantiations/google/unioned_p4info.pb.txt +++ b/sai_p4/instantiations/google/unioned_p4info.pb.txt @@ -569,6 +569,160 @@ tables { direct_resource_ids: 352321792 size: 256 } +tables { + preamble { + id: 33554695 + name: "ingress.acl_ingress.acl_ingress_qos_table" + alias: "acl_ingress_qos_table" + annotations: "@sai_acl(INGRESS)" + annotations: "@sai_acl_priority(10)" + annotations: "@p4runtime_role(\"sdn_controller\")" + annotations: "@entry_restriction(\"\n // Forbid using ether_type for IP packets (by convention, use is_ip* instead).\n ether_type != 0x0800 && ether_type != 0x86dd;\n // Only allow IP field matches for IP packets.\n ttl::mask != 0 -> (is_ip == 1 || is_ipv4 == 1 || is_ipv6 == 1);\n ip_protocol::mask != 0 -> (is_ip == 1 || is_ipv4 == 1 || is_ipv6 == 1);\n // Only allow l4_dst_port matches for TCP/UDP packets.\n l4_dst_port::mask != 0 -> (ip_protocol == 6 || ip_protocol == 17);\n // Forbid illegal combinations of IP_TYPE fields.\n is_ip::mask != 0 -> (is_ipv4::mask == 0 && is_ipv6::mask == 0);\n is_ipv4::mask != 0 -> (is_ip::mask == 0 && is_ipv6::mask == 0);\n is_ipv6::mask != 0 -> (is_ip::mask == 0 && is_ipv4::mask == 0);\n // Forbid unsupported combinations of IP_TYPE fields.\n is_ipv4::mask != 0 -> (is_ipv4 == 1);\n is_ipv6::mask != 0 -> (is_ipv6 == 1);\n // Only allow icmp_type matches for ICMP packets\n icmpv6_type::mask != 0 -> ip_protocol == 58;\n\n // Only allow l4_dst_port matches for TCP/UDP packets.\n l4_src_port::mask != 0 -> (ip_protocol == 6 || ip_protocol == 17);\n // Only allow icmp_type matches for ICMP packets\n icmp_type::mask != 0 -> ip_protocol == 1;\n\n\n\n\n\n \")" + annotations: "@entry_restriction(\"\n // Forbid using ether_type for IP packets (by convention, use is_ip* instead).\n ether_type != 0x0800 && ether_type != 0x86dd;\n // Only allow IP field matches for IP packets.\n ttl::mask != 0 -> (is_ip == 1 || is_ipv4 == 1 || is_ipv6 == 1);\n ip_protocol::mask != 0 -> (is_ip == 1 || is_ipv4 == 1 || is_ipv6 == 1);\n // Only allow l4_dst_port matches for TCP/UDP packets.\n l4_dst_port::mask != 0 -> (ip_protocol == 6 || ip_protocol == 17);\n // Forbid illegal combinations of IP_TYPE fields.\n is_ip::mask != 0 -> (is_ipv4::mask == 0 && is_ipv6::mask == 0);\n is_ipv4::mask != 0 -> (is_ip::mask == 0 && is_ipv6::mask == 0);\n is_ipv6::mask != 0 -> (is_ip::mask == 0 && is_ipv4::mask == 0);\n // Forbid unsupported combinations of IP_TYPE fields.\n is_ipv4::mask != 0 -> (is_ipv4 == 1);\n is_ipv6::mask != 0 -> (is_ipv6 == 1);\n // Only allow icmp_type matches for ICMP packets\n icmpv6_type::mask != 0 -> ip_protocol == 58;\n\n\n\n\n\n\n\n // Only allow arp_tpa matches for ARP packets.\n arp_tpa::mask != 0 -> ether_type == 0x0806;\n\n \")" + } + match_fields { + id: 1 + name: "is_ip" + annotations: "@sai_field(SAI_ACL_TABLE_ATTR_FIELD_ACL_IP_TYPE / IP)" + bitwidth: 1 + match_type: OPTIONAL + } + match_fields { + id: 2 + name: "is_ipv4" + annotations: "@sai_field(SAI_ACL_TABLE_ATTR_FIELD_ACL_IP_TYPE / IPV4ANY)" + bitwidth: 1 + match_type: OPTIONAL + } + match_fields { + id: 3 + name: "is_ipv6" + annotations: "@sai_field(SAI_ACL_TABLE_ATTR_FIELD_ACL_IP_TYPE / IPV6ANY)" + bitwidth: 1 + match_type: OPTIONAL + } + match_fields { + id: 4 + name: "ether_type" + annotations: "@sai_field(SAI_ACL_TABLE_ATTR_FIELD_ETHER_TYPE)" + bitwidth: 16 + match_type: TERNARY + } + match_fields { + id: 7 + name: "ttl" + annotations: "@sai_field(SAI_ACL_TABLE_ATTR_FIELD_TTL)" + bitwidth: 8 + match_type: TERNARY + } + match_fields { + id: 8 + name: "ip_protocol" + annotations: "@sai_field(SAI_ACL_TABLE_ATTR_FIELD_IP_PROTOCOL)" + bitwidth: 8 + match_type: TERNARY + } + match_fields { + id: 9 + name: "icmpv6_type" + annotations: "@sai_field(SAI_ACL_TABLE_ATTR_FIELD_ICMPV6_TYPE)" + bitwidth: 8 + match_type: TERNARY + } + match_fields { + id: 10 + name: "l4_dst_port" + annotations: "@sai_field(SAI_ACL_TABLE_ATTR_FIELD_L4_DST_PORT)" + bitwidth: 16 + match_type: TERNARY + } + match_fields { + id: 12 + name: "l4_src_port" + annotations: "@sai_field(SAI_ACL_TABLE_ATTR_FIELD_L4_SRC_PORT)" + bitwidth: 16 + match_type: TERNARY + } + match_fields { + id: 14 + name: "icmp_type" + annotations: "@sai_field(SAI_ACL_TABLE_ATTR_FIELD_ICMP_TYPE)" + bitwidth: 8 + match_type: TERNARY + } + match_fields { + id: 15 + name: "route_metadata" + annotations: "@sai_field(SAI_ACL_TABLE_ATTR_FIELD_ROUTE_DST_USER_META)" + bitwidth: 6 + match_type: OPTIONAL + } + match_fields { + id: 5 + name: "dst_mac" + annotations: "@sai_field(SAI_ACL_TABLE_ATTR_FIELD_DST_MAC)" + annotations: "@format(MAC_ADDRESS)" + bitwidth: 48 + match_type: TERNARY + } + match_fields { + id: 6 + name: "arp_tpa" + annotations: "@composite_field(@ sai_udf ( base = SAI_UDF_BASE_L3 , offset = 24 , length = 2 ) , @ sai_udf ( base = SAI_UDF_BASE_L3 , offset = 26 , length = 2 ))" + annotations: "@format(IPV4_ADDRESS)" + bitwidth: 32 + match_type: TERNARY + } + match_fields { + id: 11 + name: "in_port" + annotations: "@sai_field(SAI_ACL_TABLE_ATTR_FIELD_IN_PORT)" + match_type: OPTIONAL + type_name { + name: "port_id_t" + } + } + match_fields { + id: 13 + name: "acl_metadata" + annotations: "@sai_field(SAI_ACL_TABLE_ATTR_FIELD_ACL_USER_META)" + bitwidth: 8 + match_type: TERNARY + } + action_refs { + id: 16777484 + annotations: "@proto_id(1)" + } + action_refs { + id: 16777486 + annotations: "@proto_id(2)" + } + action_refs { + id: 16777475 + annotations: "@proto_id(3)" + } + action_refs { + id: 16777481 + annotations: "@proto_id(4)" + } + action_refs { + id: 16777488 + annotations: "@proto_id(5)" + } + action_refs { + id: 16777489 + annotations: "@proto_id(6)" + } + action_refs { + id: 21257015 + annotations: "@defaultonly" + scope: DEFAULT_ONLY + } + const_default_action_id: 21257015 + direct_resource_ids: 318767367 + direct_resource_ids: 352321794 + size: 511 +} tables { preamble { id: 33554697 @@ -1316,138 +1470,6 @@ tables { direct_resource_ids: 318767365 size: 127 } -tables { - preamble { - id: 33554695 - name: "ingress.acl_ingress.acl_ingress_qos_table" - alias: "acl_ingress_qos_table" - annotations: "@sai_acl(INGRESS)" - annotations: "@sai_acl_priority(10)" - annotations: "@p4runtime_role(\"sdn_controller\")" - annotations: "@entry_restriction(\"\n // Forbid using ether_type for IP packets (by convention, use is_ip* instead).\n ether_type != 0x0800 && ether_type != 0x86dd;\n // Only allow IP field matches for IP packets.\n ttl::mask != 0 -> (is_ip == 1 || is_ipv4 == 1 || is_ipv6 == 1);\n ip_protocol::mask != 0 -> (is_ip == 1 || is_ipv4 == 1 || is_ipv6 == 1);\n // Only allow l4_dst_port and l4_src_port matches for TCP/UDP packets.\n l4_dst_port::mask != 0 -> (ip_protocol == 6 || ip_protocol == 17);\n // Forbid illegal combinations of IP_TYPE fields.\n is_ip::mask != 0 -> (is_ipv4::mask == 0 && is_ipv6::mask == 0);\n is_ipv4::mask != 0 -> (is_ip::mask == 0 && is_ipv6::mask == 0);\n is_ipv6::mask != 0 -> (is_ip::mask == 0 && is_ipv4::mask == 0);\n // Forbid unsupported combinations of IP_TYPE fields.\n is_ipv4::mask != 0 -> (is_ipv4 == 1);\n is_ipv6::mask != 0 -> (is_ipv6 == 1);\n // Only allow icmp_type matches for ICMP packets\n icmpv6_type::mask != 0 -> ip_protocol == 58;\n // Only allow arp_tpa matches for ARP packets.\n arp_tpa::mask != 0 -> ether_type == 0x0806;\n \")" - } - match_fields { - id: 1 - name: "is_ip" - annotations: "@sai_field(SAI_ACL_TABLE_ATTR_FIELD_ACL_IP_TYPE / IP)" - bitwidth: 1 - match_type: OPTIONAL - } - match_fields { - id: 2 - name: "is_ipv4" - annotations: "@sai_field(SAI_ACL_TABLE_ATTR_FIELD_ACL_IP_TYPE / IPV4ANY)" - bitwidth: 1 - match_type: OPTIONAL - } - match_fields { - id: 3 - name: "is_ipv6" - annotations: "@sai_field(SAI_ACL_TABLE_ATTR_FIELD_ACL_IP_TYPE / IPV6ANY)" - bitwidth: 1 - match_type: OPTIONAL - } - match_fields { - id: 4 - name: "ether_type" - annotations: "@sai_field(SAI_ACL_TABLE_ATTR_FIELD_ETHER_TYPE)" - bitwidth: 16 - match_type: TERNARY - } - match_fields { - id: 5 - name: "dst_mac" - annotations: "@sai_field(SAI_ACL_TABLE_ATTR_FIELD_DST_MAC)" - annotations: "@format(MAC_ADDRESS)" - bitwidth: 48 - match_type: TERNARY - } - match_fields { - id: 6 - name: "arp_tpa" - annotations: "@composite_field(@ sai_udf ( base = SAI_UDF_BASE_L3 , offset = 24 , length = 2 ) , @ sai_udf ( base = SAI_UDF_BASE_L3 , offset = 26 , length = 2 ))" - annotations: "@format(IPV4_ADDRESS)" - bitwidth: 32 - match_type: TERNARY - } - match_fields { - id: 7 - name: "ttl" - annotations: "@sai_field(SAI_ACL_TABLE_ATTR_FIELD_TTL)" - bitwidth: 8 - match_type: TERNARY - } - match_fields { - id: 8 - name: "ip_protocol" - annotations: "@sai_field(SAI_ACL_TABLE_ATTR_FIELD_IP_PROTOCOL)" - bitwidth: 8 - match_type: TERNARY - } - match_fields { - id: 9 - name: "icmpv6_type" - annotations: "@sai_field(SAI_ACL_TABLE_ATTR_FIELD_ICMPV6_TYPE)" - bitwidth: 8 - match_type: TERNARY - } - match_fields { - id: 10 - name: "l4_dst_port" - annotations: "@sai_field(SAI_ACL_TABLE_ATTR_FIELD_L4_DST_PORT)" - bitwidth: 16 - match_type: TERNARY - } - match_fields { - id: 11 - name: "in_port" - annotations: "@sai_field(SAI_ACL_TABLE_ATTR_FIELD_IN_PORT)" - match_type: OPTIONAL - type_name { - name: "port_id_t" - } - } - match_fields { - id: 13 - name: "acl_metadata" - annotations: "@sai_field(SAI_ACL_TABLE_ATTR_FIELD_ACL_USER_META)" - bitwidth: 8 - match_type: TERNARY - } - action_refs { - id: 16777484 - annotations: "@proto_id(1)" - } - action_refs { - id: 16777486 - annotations: "@proto_id(2)" - } - action_refs { - id: 16777475 - annotations: "@proto_id(3)" - } - action_refs { - id: 16777481 - annotations: "@proto_id(4)" - } - action_refs { - id: 16777488 - annotations: "@proto_id(5)" - } - action_refs { - id: 16777489 - annotations: "@proto_id(6)" - } - action_refs { - id: 21257015 - annotations: "@defaultonly" - scope: DEFAULT_ONLY - } - const_default_action_id: 21257015 - direct_resource_ids: 318767367 - direct_resource_ids: 352321794 - size: 511 -} tables { preamble { id: 33554696 @@ -1818,6 +1840,90 @@ actions { } } } +actions { + preamble { + id: 16777484 + name: "ingress.acl_ingress.set_qos_queue_and_cancel_copy_above_rate_limit" + alias: "set_qos_queue_and_cancel_copy_above_rate_limit" + annotations: "@sai_action(SAI_PACKET_ACTION_FORWARD , SAI_PACKET_COLOR_GREEN)" + annotations: "@sai_action(SAI_PACKET_ACTION_COPY_CANCEL , SAI_PACKET_COLOR_RED)" + } + params { + id: 1 + name: "qos_queue" + annotations: "@sai_action_param(QOS_QUEUE)" + type_name { + name: "qos_queue_t" + } + } +} +actions { + preamble { + id: 16777489 + name: "ingress.acl_ingress.set_cpu_and_multicast_queues_and_deny_above_rate_limit" + alias: "set_cpu_and_multicast_queues_and_deny_above_rate_limit" + annotations: "@sai_action(SAI_PACKET_ACTION_FORWARD , SAI_PACKET_COLOR_GREEN)" + annotations: "@sai_action(SAI_PACKET_ACTION_DENY , SAI_PACKET_COLOR_RED)" + annotations: "@unsupported" + } + params { + id: 1 + name: "cpu_queue" + annotations: "@sai_action_param(QOS_QUEUE)" + type_name { + name: "qos_queue_t" + } + } + params { + id: 2 + name: "green_multicast_queue" + annotations: "@sai_action_param(MULTICAST_QOS_QUEUE , SAI_PACKET_COLOR_GREEN)" + type_name { + name: "qos_queue_t" + } + } + params { + id: 3 + name: "red_multicast_queue" + annotations: "@sai_action_param(MULTICAST_QOS_QUEUE , SAI_PACKET_COLOR_RED)" + type_name { + name: "qos_queue_t" + } + } +} +actions { + preamble { + id: 16777486 + name: "ingress.acl_ingress.set_cpu_queue_and_deny_above_rate_limit" + alias: "set_cpu_queue_and_deny_above_rate_limit" + annotations: "@sai_action(SAI_PACKET_ACTION_FORWARD , SAI_PACKET_COLOR_GREEN)" + annotations: "@sai_action(SAI_PACKET_ACTION_DENY , SAI_PACKET_COLOR_RED)" + } + params { + id: 1 + name: "cpu_queue" + annotations: "@sai_action_param(QOS_QUEUE)" + type_name { + name: "qos_queue_t" + } + } +} +actions { + preamble { + id: 16777488 + name: "ingress.acl_ingress.set_cpu_queue" + alias: "set_cpu_queue" + annotations: "@sai_action(SAI_PACKET_ACTION_FORWARD)" + } + params { + id: 1 + name: "cpu_queue" + annotations: "@sai_action_param(QOS_QUEUE)" + type_name { + name: "qos_queue_t" + } + } +} actions { preamble { id: 16777217 @@ -2190,90 +2296,6 @@ actions { bitwidth: 8 } } -actions { - preamble { - id: 16777484 - name: "ingress.acl_ingress.set_qos_queue_and_cancel_copy_above_rate_limit" - alias: "set_qos_queue_and_cancel_copy_above_rate_limit" - annotations: "@sai_action(SAI_PACKET_ACTION_FORWARD , SAI_PACKET_COLOR_GREEN)" - annotations: "@sai_action(SAI_PACKET_ACTION_COPY_CANCEL , SAI_PACKET_COLOR_RED)" - } - params { - id: 1 - name: "qos_queue" - annotations: "@sai_action_param(QOS_QUEUE)" - type_name { - name: "qos_queue_t" - } - } -} -actions { - preamble { - id: 16777489 - name: "ingress.acl_ingress.set_cpu_and_multicast_queues_and_deny_above_rate_limit" - alias: "set_cpu_and_multicast_queues_and_deny_above_rate_limit" - annotations: "@sai_action(SAI_PACKET_ACTION_FORWARD , SAI_PACKET_COLOR_GREEN)" - annotations: "@sai_action(SAI_PACKET_ACTION_DENY , SAI_PACKET_COLOR_RED)" - annotations: "@unsupported" - } - params { - id: 1 - name: "cpu_queue" - annotations: "@sai_action_param(QOS_QUEUE)" - type_name { - name: "qos_queue_t" - } - } - params { - id: 2 - name: "green_multicast_queue" - annotations: "@sai_action_param(MULTICAST_QOS_QUEUE , SAI_PACKET_COLOR_GREEN)" - type_name { - name: "qos_queue_t" - } - } - params { - id: 3 - name: "red_multicast_queue" - annotations: "@sai_action_param(MULTICAST_QOS_QUEUE , SAI_PACKET_COLOR_RED)" - type_name { - name: "qos_queue_t" - } - } -} -actions { - preamble { - id: 16777486 - name: "ingress.acl_ingress.set_cpu_queue_and_deny_above_rate_limit" - alias: "set_cpu_queue_and_deny_above_rate_limit" - annotations: "@sai_action(SAI_PACKET_ACTION_FORWARD , SAI_PACKET_COLOR_GREEN)" - annotations: "@sai_action(SAI_PACKET_ACTION_DENY , SAI_PACKET_COLOR_RED)" - } - params { - id: 1 - name: "cpu_queue" - annotations: "@sai_action_param(QOS_QUEUE)" - type_name { - name: "qos_queue_t" - } - } -} -actions { - preamble { - id: 16777488 - name: "ingress.acl_ingress.set_cpu_queue" - alias: "set_cpu_queue" - annotations: "@sai_action(SAI_PACKET_ACTION_FORWARD)" - } - params { - id: 1 - name: "cpu_queue" - annotations: "@sai_action_param(QOS_QUEUE)" - type_name { - name: "qos_queue_t" - } - } -} actions { preamble { id: 16777485 @@ -2331,6 +2353,17 @@ direct_counters { } direct_table_id: 33554688 } +direct_counters { + preamble { + id: 318767367 + name: "ingress.acl_ingress.acl_ingress_qos_counter" + alias: "acl_ingress_qos_counter" + } + spec { + unit: BOTH + } + direct_table_id: 33554695 +} direct_counters { preamble { id: 318767369 @@ -2386,17 +2419,6 @@ direct_counters { } direct_table_id: 33554694 } -direct_counters { - preamble { - id: 318767367 - name: "ingress.acl_ingress.acl_ingress_qos_counter" - alias: "acl_ingress_qos_counter" - } - spec { - unit: BOTH - } - direct_table_id: 33554695 -} direct_counters { preamble { id: 318767368 From cbf7422df0a8e57407551987d09a6c22164ead27 Mon Sep 17 00:00:00 2001 From: kishanps Date: Wed, 17 Jan 2024 16:22:24 -0800 Subject: [PATCH 6/6] [SAIP4] Change SAI ACL field name for the ipmc table hit, Enable support for multicast ACL qualifiers and redirect action, Change route_metadata to ternary, Adding src_ipv6 match field to ipv6_tunnel_termination table, Make default src_mac_rewrite NOT be multicast, Remove acl_forward from mirror_and_redirect, Add support for multicast RIF table & fix support for ACL QoS table, Reduce resource limits for QoS table, Build an API to convert P4Testgen tests to Arriba test vectors & Clean up test_entries library and fix bug in AddDefaultRouteForwardingAllPacketsToGivenPort. --- .../p4info_verification_schema_test.cc | 2 +- sai_p4/fixed/BUILD.bazel | 1 + sai_p4/fixed/common_actions.p4 | 14 + sai_p4/fixed/ids.h | 2 +- sai_p4/fixed/routing.p4 | 7 +- sai_p4/fixed/tunnel_termination.p4 | 3 + sai_p4/instantiations/google/BUILD.bazel | 4 + sai_p4/instantiations/google/acl_ingress.p4 | 23 +- .../google/fabric_border_router.p4info.pb.txt | 25 +- .../google/middleblock.p4info.pb.txt | 32 +-- .../google/minimum_guaranteed_sizes.p4 | 2 +- sai_p4/instantiations/google/sai_pd.proto | 11 +- .../google/test_tools/BUILD.bazel | 3 +- .../test_tools/table_entry_generator.cc | 26 +- .../google/test_tools/test_entries.cc | 245 ++++++------------ .../google/test_tools/test_entries.h | 50 +++- ...mv2_tunnel_termination_integration_test.cc | 99 ++++--- .../google/tests/sai_p4_bmv2_vlan_test.cc | 56 ++-- .../instantiations/google/tor.p4info.pb.txt | 27 +- .../google/unioned_p4info.pb.txt | 36 +-- 20 files changed, 337 insertions(+), 331 deletions(-) create mode 100644 sai_p4/fixed/common_actions.p4 diff --git a/p4rt_app/p4runtime/p4info_verification_schema_test.cc b/p4rt_app/p4runtime/p4info_verification_schema_test.cc index caaf5480..45c85f8d 100644 --- a/p4rt_app/p4runtime/p4info_verification_schema_test.cc +++ b/p4rt_app/p4runtime/p4info_verification_schema_test.cc @@ -883,7 +883,7 @@ class GoogleInstantiationTest // Tests that P4RT app is always "ahead of" our SAI P4 programs, so we don't // accidentally expose features in the program that are not yet supported by -// P4RT app/GPINS. +// P4RT app/PINS. TEST_P(GoogleInstantiationTest, SchemaSupportsInstantiation) { sai::Instantiation instantiation = GetParam(); pdpi::IrP4Info p4info = sai::GetIrP4Info(instantiation); diff --git a/sai_p4/fixed/BUILD.bazel b/sai_p4/fixed/BUILD.bazel index 23e64752..2b84c4c5 100644 --- a/sai_p4/fixed/BUILD.bazel +++ b/sai_p4/fixed/BUILD.bazel @@ -22,6 +22,7 @@ filegroup( srcs = [ "bitwidths.p4", "bmv2_intrinsics.h", + "common_actions.p4", "drop_martians.p4", "headers.p4", "ids.h", diff --git a/sai_p4/fixed/common_actions.p4 b/sai_p4/fixed/common_actions.p4 new file mode 100644 index 00000000..d8df5532 --- /dev/null +++ b/sai_p4/fixed/common_actions.p4 @@ -0,0 +1,14 @@ +#ifndef SAI_FIXED_COMMON_ACTIONS_P4_ +#define SAI_FIXED_COMMON_ACTIONS_P4_ + +#include "ids.h" + +// This file lists common actions that may be used by multiple control blocks in +// the fixed pipeline. + +// Action that does nothing. Like `NoAction` in `core.p4`, but following +// Google's naming conventions. +@id(SHARED_NO_ACTION_ACTION_ID) +action no_action() {} + +#endif // SAI_FIXED_COMMON_ACTIONS_P4_ diff --git a/sai_p4/fixed/ids.h b/sai_p4/fixed/ids.h index b169f602..a3ec4594 100644 --- a/sai_p4/fixed/ids.h +++ b/sai_p4/fixed/ids.h @@ -35,7 +35,7 @@ // --- Actions ----------------------------------------------------------------- // IDs of fixed SAI actions (8 most significant bits = 0x01). -#define ROUTING_NO_ACTION_ACTION_ID 0x01798B9E // 24742814 +#define SHARED_NO_ACTION_ACTION_ID 0x01798B9E // 24742814 #define ROUTING_SET_DST_MAC_ACTION_ID 0x01000001 // 16777217 #define ROUTING_SET_PORT_AND_SRC_MAC_ACTION_ID 0x01000002 // 16777218 #define ROUTING_SET_PORT_AND_SRC_MAC_AND_VLAN_ID_ACTION_ID \ diff --git a/sai_p4/fixed/routing.p4 b/sai_p4/fixed/routing.p4 index 0b39acd7..236b92b3 100644 --- a/sai_p4/fixed/routing.p4 +++ b/sai_p4/fixed/routing.p4 @@ -2,6 +2,7 @@ #define SAI_ROUTING_P4_ #include +#include "common_actions.p4" #include "headers.p4" #include "metadata.p4" #include "ids.h" @@ -65,12 +66,6 @@ action set_nexthop_id(inout local_metadata_t local_metadata, control routing_lookup(in headers_t headers, inout local_metadata_t local_metadata, inout standard_metadata_t standard_metadata) { - // Action that does nothing. Like `NoAction` in `core.p4`, but following - // Google's naming conventions. - // TODO: Add support for CamlCase actions to the PD generator, - // so we can use `NoAction` throughout. - @id(ROUTING_NO_ACTION_ACTION_ID) - action no_action() {} // Programming this table does not affect packet forwarding directly -- the // table performs no actions -- but results in the creation/deletion of VRFs. // This is a prerequisite to using these VRFs, e.g. in the `ipv4_table` and diff --git a/sai_p4/fixed/tunnel_termination.p4 b/sai_p4/fixed/tunnel_termination.p4 index 63a8e045..57810a06 100644 --- a/sai_p4/fixed/tunnel_termination.p4 +++ b/sai_p4/fixed/tunnel_termination.p4 @@ -41,6 +41,9 @@ control tunnel_termination_lookup(in headers_t headers, // Sets `SAI_TUNNEL_TERM_TABLE_ENTRY_ATTR_DST_IP[_MASK]`. headers.ipv6.dst_addr : ternary @id(1) @name("dst_ipv6") @format(IPV6_ADDRESS); + // Sets `SAI_TUNNEL_TERM_TABLE_ENTRY_ATTR_SRC_IP[_MASK]`. + headers.ipv6.src_addr : ternary + @id(2) @name("src_ipv6") @format(IPV6_ADDRESS); } actions = { @proto_id(1) mark_for_tunnel_decap_and_set_vrf; diff --git a/sai_p4/instantiations/google/BUILD.bazel b/sai_p4/instantiations/google/BUILD.bazel index 69da8ab6..4074db60 100644 --- a/sai_p4/instantiations/google/BUILD.bazel +++ b/sai_p4/instantiations/google/BUILD.bazel @@ -407,3 +407,7 @@ cc_test( ], ) +filegroup( + name = "sai_p4", + srcs = glob(["**/*.p4"]) + glob(["**/*.h"]), +) diff --git a/sai_p4/instantiations/google/acl_ingress.p4 b/sai_p4/instantiations/google/acl_ingress.p4 index 44fe83d5..f12a217b 100644 --- a/sai_p4/instantiations/google/acl_ingress.p4 +++ b/sai_p4/instantiations/google/acl_ingress.p4 @@ -373,7 +373,7 @@ control acl_ingress(in headers_t headers, headers.icmp.type : ternary @id(14) @name("icmp_type") @sai_field(SAI_ACL_TABLE_ATTR_FIELD_ICMP_TYPE); - local_metadata.route_metadata : optional + local_metadata.route_metadata : ternary @id(15) @name("route_metadata") @sai_field(SAI_ACL_TABLE_ATTR_FIELD_ROUTE_DST_USER_META); #endif @@ -454,6 +454,7 @@ control acl_ingress(in headers_t headers, @id(ACL_INGRESS_REDIRECT_TO_NEXTHOP_ACTION_ID) action redirect_to_nexthop( @sai_action_param(SAI_ACL_ENTRY_ATTR_ACTION_REDIRECT) + @sai_action_param_object_type(SAI_OBJECT_TYPE_NEXT_HOP) @refers_to(nexthop_table, nexthop_id) nexthop_id_t nexthop_id) { @@ -466,9 +467,6 @@ control acl_ingress(in headers_t headers, standard_metadata.mcast_grp = 0; } - // TODO: Remove `@unsupported` annotation once the switch stack - // supports multicast. - @unsupported @id(ACL_INGRESS_REDIRECT_TO_IPMC_GROUP_ACTION_ID) @action_restriction(" // Disallow 0 since it encodes 'no multicast' in V1Model. @@ -476,6 +474,7 @@ control acl_ingress(in headers_t headers, ") action redirect_to_ipmc_group( @sai_action_param(SAI_ACL_ENTRY_ATTR_ACTION_REDIRECT) + @sai_action_param_object_type(SAI_OBJECT_TYPE_IPMC_GROUP) @refers_to(builtin::multicast_group_table, multicast_group_id) multicast_group_id_t multicast_group_id) { standard_metadata.mcast_grp = multicast_group_id; @@ -552,21 +551,13 @@ control acl_ingress(in headers_t headers, @id(5); local_metadata.vrf_id : optional - @name("vrf_id") - @sai_field(SAI_ACL_TABLE_ATTR_FIELD_VRF_ID) - @id(8) - // TODO: Remove once the switch supports this field. - @unsupported; - + @id(8) @name("vrf_id") + @sai_field(SAI_ACL_TABLE_ATTR_FIELD_VRF_ID); local_metadata.ipmc_table_hit : optional - @name("ipmc_table_hit") - @sai_field(SAI_ACL_TABLE_ATTR_FIELD_IPMC_TABLE_HIT) - @id(9) - // TODO: Remove once the switch supports this field. - @unsupported; + @id(9) @name("ipmc_table_hit") + @sai_field(SAI_ACL_TABLE_ATTR_FIELD_IPMC_NPU_META_DST_HIT); } actions = { - @proto_id(4) acl_forward(); @proto_id(1) acl_mirror(); @proto_id(2) redirect_to_nexthop(); @proto_id(3) redirect_to_ipmc_group(); diff --git a/sai_p4/instantiations/google/fabric_border_router.p4info.pb.txt b/sai_p4/instantiations/google/fabric_border_router.p4info.pb.txt index e9e1ec86..0c4d8e38 100644 --- a/sai_p4/instantiations/google/fabric_border_router.p4info.pb.txt +++ b/sai_p4/instantiations/google/fabric_border_router.p4info.pb.txt @@ -19,6 +19,13 @@ tables { bitwidth: 128 match_type: TERNARY } + match_fields { + id: 2 + name: "src_ipv6" + annotations: "@format(IPV6_ADDRESS)" + bitwidth: 128 + match_type: TERNARY + } action_refs { id: 16777238 annotations: "@proto_id(1)" @@ -644,7 +651,7 @@ tables { name: "route_metadata" annotations: "@sai_field(SAI_ACL_TABLE_ATTR_FIELD_ROUTE_DST_USER_META)" bitwidth: 6 - match_type: OPTIONAL + match_type: TERNARY } action_refs { id: 16777484 @@ -678,7 +685,7 @@ tables { const_default_action_id: 21257015 direct_resource_ids: 318767367 direct_resource_ids: 352321794 - size: 511 + size: 255 } tables { preamble { @@ -1088,6 +1095,13 @@ actions { annotations: "@noWarn(\"unused\")" } } +actions { + preamble { + id: 24742814 + name: "no_action" + alias: "no_action" + } +} actions { preamble { id: 16777221 @@ -1156,13 +1170,6 @@ actions { alias: "admit_to_l3" } } -actions { - preamble { - id: 24742814 - name: "ingress.routing_lookup.no_action" - alias: "no_action" - } -} actions { preamble { id: 16777222 diff --git a/sai_p4/instantiations/google/middleblock.p4info.pb.txt b/sai_p4/instantiations/google/middleblock.p4info.pb.txt index 8b77d355..695bea8d 100755 --- a/sai_p4/instantiations/google/middleblock.p4info.pb.txt +++ b/sai_p4/instantiations/google/middleblock.p4info.pb.txt @@ -19,6 +19,13 @@ tables { bitwidth: 128 match_type: TERNARY } + match_fields { + id: 2 + name: "src_ipv6" + annotations: "@format(IPV6_ADDRESS)" + bitwidth: 128 + match_type: TERNARY + } action_refs { id: 16777238 annotations: "@proto_id(1)" @@ -587,7 +594,6 @@ tables { id: 8 name: "vrf_id" annotations: "@sai_field(SAI_ACL_TABLE_ATTR_FIELD_VRF_ID)" - annotations: "@unsupported" match_type: OPTIONAL type_name { name: "vrf_id_t" @@ -596,15 +602,10 @@ tables { match_fields { id: 9 name: "ipmc_table_hit" - annotations: "@sai_field(SAI_ACL_TABLE_ATTR_FIELD_IPMC_TABLE_HIT)" - annotations: "@unsupported" + annotations: "@sai_field(SAI_ACL_TABLE_ATTR_FIELD_IPMC_NPU_META_DST_HIT)" bitwidth: 1 match_type: OPTIONAL } - action_refs { - id: 16777475 - annotations: "@proto_id(4)" - } action_refs { id: 16777476 annotations: "@proto_id(1)" @@ -1045,6 +1046,13 @@ actions { annotations: "@noWarn(\"unused\")" } } +actions { + preamble { + id: 24742814 + name: "no_action" + alias: "no_action" + } +} actions { preamble { id: 16777221 @@ -1113,13 +1121,6 @@ actions { alias: "admit_to_l3" } } -actions { - preamble { - id: 24742814 - name: "ingress.routing_lookup.no_action" - alias: "no_action" - } -} actions { preamble { id: 16777222 @@ -1286,6 +1287,7 @@ actions { id: 1 name: "nexthop_id" annotations: "@sai_action_param(SAI_ACL_ENTRY_ATTR_ACTION_REDIRECT)" + annotations: "@sai_action_param_object_type(SAI_OBJECT_TYPE_NEXT_HOP)" annotations: "@refers_to(nexthop_table , nexthop_id)" type_name { name: "nexthop_id_t" @@ -1297,13 +1299,13 @@ actions { id: 16777491 name: "ingress.acl_ingress.redirect_to_ipmc_group" alias: "redirect_to_ipmc_group" - annotations: "@unsupported" annotations: "@action_restriction(\"\n // Disallow 0 since it encodes \'no multicast\' in V1Model.\n multicast_group_id != 0;\n \")" } params { id: 1 name: "multicast_group_id" annotations: "@sai_action_param(SAI_ACL_ENTRY_ATTR_ACTION_REDIRECT)" + annotations: "@sai_action_param_object_type(SAI_OBJECT_TYPE_IPMC_GROUP)" annotations: "@refers_to(builtin : : multicast_group_table , multicast_group_id)" bitwidth: 16 } diff --git a/sai_p4/instantiations/google/minimum_guaranteed_sizes.p4 b/sai_p4/instantiations/google/minimum_guaranteed_sizes.p4 index 7bd7aa92..033c88fe 100644 --- a/sai_p4/instantiations/google/minimum_guaranteed_sizes.p4 +++ b/sai_p4/instantiations/google/minimum_guaranteed_sizes.p4 @@ -90,7 +90,7 @@ #define ACL_TOR_PRE_INGRESS_TABLE_MINIMUM_GUARANTEED_SIZE 127 -#define ACL_INGRESS_QOS_TABLE_MINIMUM_GUARANTEED_SIZE 511 +#define ACL_INGRESS_QOS_TABLE_MINIMUM_GUARANTEED_SIZE 255 #define ACL_INGRESS_COUNTING_TABLE_MINIMUM_GUARANTEED_SIZE 255 diff --git a/sai_p4/instantiations/google/sai_pd.proto b/sai_p4/instantiations/google/sai_pd.proto index 377a1a63..ea705127 100755 --- a/sai_p4/instantiations/google/sai_pd.proto +++ b/sai_p4/instantiations/google/sai_pd.proto @@ -206,6 +206,7 @@ message VrfTableEntry { message Ipv6TunnelTerminationTableEntry { message Match { Ternary dst_ipv6 = 1; // ternary match / Format::IPV6 / 128 bits + Ternary src_ipv6 = 2; // ternary match / Format::IPV6 / 128 bits } Match match = 1; message Action { @@ -592,8 +593,7 @@ message AclIngressQosTableEntry { Ternary l4_src_port = 12; // ternary match / Format::HEX_STRING / 16 bits Ternary acl_metadata = 13; // ternary match / Format::HEX_STRING / 8 bits Ternary icmp_type = 14; // ternary match / Format::HEX_STRING / 8 bits - Optional route_metadata = - 15; // optional match / Format::HEX_STRING / 6 bits + Ternary route_metadata = 15; // ternary match / Format::HEX_STRING / 6 bits } Match match = 1; message Action { @@ -744,9 +744,7 @@ message AclIngressMirrorAndRedirectTableEntry { Ternary dst_ipv6 = 5; // ternary match / Format::IPV6 / upper 64 bits Ternary acl_metadata = 6; // ternary match / Format::HEX_STRING / 8 bits Ternary vlan_id = 7; // ternary match / Format::HEX_STRING / 12 bits - // CAUTION: This match field is not (yet) supported. - Optional vrf_id = 8; // optional match / Format::STRING - // CAUTION: This match field is not (yet) supported. + Optional vrf_id = 8; // optional match / Format::STRING Optional ipmc_table_hit = 9; // optional match / Format::HEX_STRING / 1 bits Ternary dst_ip = 10; // ternary match / Format::IPV4 @@ -754,10 +752,8 @@ message AclIngressMirrorAndRedirectTableEntry { Match match = 1; message Action { oneof action { - AclForwardAction acl_forward = 4; AclMirrorAction acl_mirror = 1; RedirectToNexthopAction redirect_to_nexthop = 2; - // CAUTION: This action is not (yet) supported. RedirectToIpmcGroupAction redirect_to_ipmc_group = 3; } } @@ -970,7 +966,6 @@ message RedirectToNexthopAction { string nexthop_id = 1; // Format::STRING } -// CAUTION: This action is not (yet) supported. message RedirectToIpmcGroupAction { string multicast_group_id = 1; // Format::HEX_STRING / 16 bits } diff --git a/sai_p4/instantiations/google/test_tools/BUILD.bazel b/sai_p4/instantiations/google/test_tools/BUILD.bazel index fcd4effe..2e44c215 100644 --- a/sai_p4/instantiations/google/test_tools/BUILD.bazel +++ b/sai_p4/instantiations/google/test_tools/BUILD.bazel @@ -112,6 +112,7 @@ cc_library( ":table_entry_generator_helper", "//gutil:proto", "//gutil:status", + "//gutil:testing", "//p4_pdpi:ir_cc_proto", "@com_github_google_glog//:glog", "@com_github_p4lang_p4runtime//:p4info_cc_proto", @@ -125,7 +126,7 @@ cc_library( cc_test( name = "table_entry_generator_test", srcs = ["table_entry_generator_test.cc"], - shard_count = 5, + shard_count = 50, deps = [ ":table_entry_generator", "//gutil:status_matchers", diff --git a/sai_p4/instantiations/google/test_tools/table_entry_generator.cc b/sai_p4/instantiations/google/test_tools/table_entry_generator.cc index a6028f40..ceb9bac5 100644 --- a/sai_p4/instantiations/google/test_tools/table_entry_generator.cc +++ b/sai_p4/instantiations/google/test_tools/table_entry_generator.cc @@ -27,6 +27,7 @@ #include "glog/logging.h" #include "gutil/proto.h" #include "gutil/status.h" +#include "gutil/testing.h" #include "p4/config/v1/p4info.pb.h" #include "p4_pdpi/ir.pb.h" #include "sai_p4/instantiations/google/test_tools/table_entry_generator_helper.h" @@ -258,6 +259,28 @@ TableEntryGenerator L3AdmitTableGenerator( return generator; } +TableEntryGenerator MulticastRouterInterfaceTableGenerator( + const pdpi::IrTableDefinition& table_definition) { + auto base_entry = gutil::ParseProtoOrDie(R"pb( + table_name: "multicast_router_interface_table" + matches { + name: "multicast_replica_port" + exact { str: "1" } + } + action { + name: "set_multicast_src_mac" + params { + name: "src_mac" + value { mac: "06:05:04:03:02:01" } + } + } + )pb"); + return TableEntryGenerator{ + .generator = IrMatchFieldGenerator(table_definition, base_entry, + "multicast_replica_instance"), + }; +} + const absl::flat_hash_set& KnownUnsupportedTables() { static const auto* const kUnsupportedTables = new absl::flat_hash_set({ @@ -283,7 +306,6 @@ const absl::flat_hash_set& KnownUnsupportedTables() { "ipv6_tunnel_termination_table", // TODO: Add support for these tables once the switch // supports it. - "multicast_router_interface_table", "ipv4_multicast_table", "ipv6_multicast_table", // TODO: Add support for this table once the switch @@ -314,6 +336,8 @@ absl::StatusOr GetGenerator( {"ipv4_table", Ipv4TableGenerator}, {"ipv6_table", Ipv6TableGenerator}, {"l3_admit_table", L3AdmitTableGenerator}, + {"multicast_router_interface_table", + MulticastRouterInterfaceTableGenerator}, }); const std::string& table_name = table.preamble().alias(); diff --git a/sai_p4/instantiations/google/test_tools/test_entries.cc b/sai_p4/instantiations/google/test_tools/test_entries.cc index dacb4054..be53ba8a 100644 --- a/sai_p4/instantiations/google/test_tools/test_entries.cc +++ b/sai_p4/instantiations/google/test_tools/test_entries.cc @@ -135,129 +135,42 @@ EntryBuilder& EntryBuilder::AddEntryPuntingAllPackets(PuntAction action) { EntryBuilder& EntryBuilder::AddDefaultRouteForwardingAllPacketsToGivenPort( absl::string_view egress_port, IpVersion ip_version, absl::string_view vrf, - const NexthopRewriteOptions& nexthop_rewrite_options, - std::optional vlan_hexstr) { + const NexthopRewriteOptions& rewrite_options) { const std::string kNexthopId = - absl::StrFormat("nexthop(%s, %s)", egress_port, vrf); - - if (ip_version == IpVersion::kIpv4 || ip_version == IpVersion::kIpv4And6) { - sai::TableEntry& entry = *entries_.add_entries(); - entry = gutil::ParseProtoOrDie(R"pb( - ipv4_table_entry { - # IP match field omitted so this entry serves as the default route. - match { vrf_id: "TBD" } - action { set_nexthop_id { nexthop_id: "nexthop" } } - } - )pb"); - entry.mutable_ipv4_table_entry()->mutable_match()->set_vrf_id( - // TODO: Pass string_view directly once proto supports it. - std::string(vrf)); - entry.mutable_ipv4_table_entry() - ->mutable_action() - ->mutable_set_nexthop_id() - ->set_nexthop_id(kNexthopId); - } - if (ip_version == IpVersion::kIpv6 || ip_version == IpVersion::kIpv4And6) { - sai::TableEntry& entry = *entries_.add_entries(); - entry = gutil::ParseProtoOrDie(R"pb( - ipv6_table_entry { - # IP match field omitted so this entry serves as the default route. - match { vrf_id: "TBD" } - action { set_nexthop_id { nexthop_id: "nexthop" } } - } - )pb"); - entry.mutable_ipv6_table_entry()->mutable_match()->set_vrf_id( - // TODO: Pass string_view directly once proto supports it. - std::string(vrf)); - entry.mutable_ipv6_table_entry() - ->mutable_action() - ->mutable_set_nexthop_id() - ->set_nexthop_id(kNexthopId); - } - - return AddNexthopRifNeighborEntries(kNexthopId, egress_port, - nexthop_rewrite_options, vlan_hexstr); -} - -EntryBuilder& EntryBuilder::AddEntriesForwardingIpPacketsToGivenPort( - absl::string_view egress_port, IpVersion ip_version, - NexthopRewriteOptions rewrite_options) { - // Create router interface entry. - sai::RouterInterfaceTableEntry& rif_entry = - *entries_.add_entries()->mutable_router_interface_table_entry(); - const netaddr::MacAddress src_mac = - rewrite_options.src_mac_rewrite.value_or(netaddr::MacAddress::AllZeros()); - const std::string rif_id = absl::StrCat(egress_port, "/", src_mac.ToString()); - rif_entry.mutable_match()->set_router_interface_id(rif_id); - auto& rif_action = - *rif_entry.mutable_action()->mutable_set_port_and_src_mac(); - // TODO: Pass string_view directly once proto supports it. - rif_action.set_port(std::string(egress_port)); - rif_action.set_src_mac(src_mac.ToString()); - - // Create neighbor table entry. - sai::NeighborTableEntry& neighbor_entry = - *entries_.add_entries()->mutable_neighbor_table_entry(); - const netaddr::MacAddress dst_mac = - rewrite_options.dst_mac_rewrite.value_or(netaddr::MacAddress::AllZeros()); - const std::string neighbor_id = dst_mac.ToLinkLocalIpv6Address().ToString(); - neighbor_entry.mutable_match()->set_router_interface_id(rif_id); - neighbor_entry.mutable_match()->set_neighbor_id(neighbor_id); - rif_entry.mutable_match()->set_router_interface_id(rif_id); - neighbor_entry.mutable_action()->mutable_set_dst_mac()->set_dst_mac( - dst_mac.ToString()); - - // Create Nexthop entry based on `rewrite_options` - sai::NexthopTableEntry& nexthop_entry = - *entries_.add_entries()->mutable_nexthop_table_entry(); - // Ideally we would use an ID that is unique for the RIF & neighbor, but - // the ID ends up being longer than BMv2 can support. - const std::string nexthop_id = rif_id; - // const std::string nexthop_id = absl::StrCat(rif_id, "/", neighbor_id); - nexthop_entry.mutable_match()->set_nexthop_id(nexthop_id); - - if (AllRewritesEnabled(rewrite_options)) { - SetIpNexthopAction& action = - *nexthop_entry.mutable_action()->mutable_set_ip_nexthop(); - action.set_router_interface_id(rif_id); - action.set_neighbor_id(neighbor_id); - } else { - SetIpNexthopAndDisableRewritesAction& action = - *nexthop_entry.mutable_action() - ->mutable_set_ip_nexthop_and_disable_rewrites(); - action.set_router_interface_id(rif_id); - action.set_neighbor_id(neighbor_id); - action.set_disable_decrement_ttl( - BoolToHexString(rewrite_options.disable_decrement_ttl)); - action.set_disable_src_mac_rewrite( - BoolToHexString(!rewrite_options.src_mac_rewrite.has_value())); - action.set_disable_dst_mac_rewrite( - BoolToHexString(!rewrite_options.dst_mac_rewrite.has_value())); - action.set_disable_vlan_rewrite( - BoolToHexString(rewrite_options.disable_vlan_rewrite)); - } - - const std::string vrf_id = "vrf"; + absl::StrFormat("nexthop(%s, %s)", egress_port, vrf) + // Ideally we would use the whole ID, but it may be longer than BMv2 + // can support. + .substr(0, 31); // Add IPv4 default route. if (ip_version == IpVersion::kIpv4 || ip_version == IpVersion::kIpv4And6) { auto& ipv4_entry = *entries_.add_entries()->mutable_ipv4_table_entry(); - ipv4_entry.mutable_match()->set_vrf_id(vrf_id); + ipv4_entry.mutable_match()->set_vrf_id(vrf); ipv4_entry.mutable_action()->mutable_set_nexthop_id()->set_nexthop_id( - nexthop_id); + kNexthopId); } // Add IPv6 default route. if (ip_version == IpVersion::kIpv6 || ip_version == IpVersion::kIpv4And6) { auto& ipv6_entry = *entries_.add_entries()->mutable_ipv6_table_entry(); - ipv6_entry.mutable_match()->set_vrf_id(vrf_id); + ipv6_entry.mutable_match()->set_vrf_id(vrf); ipv6_entry.mutable_action()->mutable_set_nexthop_id()->set_nexthop_id( - nexthop_id); + kNexthopId); } + return AddNexthopRifNeighborEntries(kNexthopId, egress_port, rewrite_options); +} + +EntryBuilder& EntryBuilder::AddEntriesForwardingIpPacketsToGivenPort( + absl::string_view egress_port, IpVersion ip_version, + const NexthopRewriteOptions& rewrite_options) { + const std::string vrf_id = "vrf"; + return AddEntryAdmittingAllPacketsToL3() .AddVrfEntry(vrf_id) - .AddPreIngressAclEntryAssigningVrfForGivenIpType(vrf_id, ip_version); + .AddPreIngressAclEntryAssigningVrfForGivenIpType(vrf_id, ip_version) + .AddDefaultRouteForwardingAllPacketsToGivenPort(egress_port, ip_version, + vrf_id, rewrite_options); } EntryBuilder& EntryBuilder::AddEntryPuntingPacketsWithTtlZeroAndOne() { @@ -463,62 +376,70 @@ EntryBuilder& EntryBuilder::AddEntrySettingVlanIdInPreIngress( EntryBuilder& EntryBuilder::AddNexthopRifNeighborEntries( absl::string_view nexthop_id, absl::string_view egress_port, - const NexthopRewriteOptions& nexthop_rewrite_options, - std::optional vlan_hexstr) { - const std::string kRifId = absl::StrFormat( - "rif(port=%s, vlan=%s)", egress_port, vlan_hexstr.value_or("none")); - { - sai::NexthopTableEntry& nexthop_entry = - *entries_.add_entries()->mutable_nexthop_table_entry(); - nexthop_entry.mutable_match()->set_nexthop_id(nexthop_id); - if (AllRewritesEnabled(nexthop_rewrite_options)) { - sai::SetIpNexthopAction& action = - *nexthop_entry.mutable_action()->mutable_set_ip_nexthop(); - action.set_router_interface_id(kRifId); - action.set_neighbor_id("fe80::2"); - } else { - sai::SetIpNexthopAndDisableRewritesAction& action = - *nexthop_entry.mutable_action() - ->mutable_set_ip_nexthop_and_disable_rewrites(); - action.set_router_interface_id(kRifId); - action.set_neighbor_id("fe80::2"); - action.set_disable_decrement_ttl( - BoolToHexString(nexthop_rewrite_options.disable_decrement_ttl)); - action.set_disable_src_mac_rewrite(BoolToHexString( - !nexthop_rewrite_options.src_mac_rewrite.has_value())); - action.set_disable_dst_mac_rewrite(BoolToHexString( - !nexthop_rewrite_options.dst_mac_rewrite.has_value())); - action.set_disable_vlan_rewrite( - BoolToHexString(nexthop_rewrite_options.disable_vlan_rewrite)); - } - } - { - sai::TableEntry& entry = *entries_.add_entries(); - entry = gutil::ParseProtoOrDie(R"pb( - neighbor_table_entry { - match { router_interface_id: "rif" neighbor_id: "fe80::2" } - action { set_dst_mac { dst_mac: "02:03:04:05:06:07" } } - } - )pb"); - entry.mutable_neighbor_table_entry() - ->mutable_match() - ->set_router_interface_id(kRifId); + const NexthopRewriteOptions& rewrite_options) { + // Create router interface entry. + sai::RouterInterfaceTableEntry& rif_entry = + *entries_.add_entries()->mutable_router_interface_table_entry(); + const netaddr::MacAddress src_mac = + rewrite_options.src_mac_rewrite.value_or(netaddr::MacAddress::AllZeros()); + const std::string kRifId = + absl::StrFormat("rif(%s,%s,%s)", egress_port, src_mac.ToString(), + rewrite_options.egress_rif_vlan.value_or("no_vlan")) + // Ideally we would use the whole ID, but it may be longer than BMv2 + // can support. + .substr(0, 32); + rif_entry.mutable_match()->set_router_interface_id(kRifId); + if (rewrite_options.egress_rif_vlan.has_value()) { + auto& rif_action = + *rif_entry.mutable_action()->mutable_set_port_and_src_mac_and_vlan_id(); + rif_action.set_vlan_id(*rewrite_options.egress_rif_vlan); + // TODO: Pass string_view directly once proto supports it. + rif_action.set_port(std::string(egress_port)); + rif_action.set_src_mac(src_mac.ToString()); + } else { + auto& rif_action = + *rif_entry.mutable_action()->mutable_set_port_and_src_mac(); + // TODO: Pass string_view directly once proto supports it. + rif_action.set_port(std::string(egress_port)); + rif_action.set_src_mac(src_mac.ToString()); } - { - sai::RouterInterfaceTableEntry& entry = - *entries_.add_entries()->mutable_router_interface_table_entry(); - entry.mutable_match()->set_router_interface_id(kRifId); - if (vlan_hexstr.has_value()) { - auto& action = - *entry.mutable_action()->mutable_set_port_and_src_mac_and_vlan_id(); - action.set_vlan_id(*vlan_hexstr); - action.set_src_mac("00:01:02:03:04:05"); - action.set_port(egress_port); - } else { - auto& action = *entry.mutable_action()->mutable_set_port_and_src_mac(); - action.set_src_mac("00:01:02:03:04:05"); - action.set_port(egress_port); - } + + // Create neighbor table entry. + sai::NeighborTableEntry& neighbor_entry = + *entries_.add_entries()->mutable_neighbor_table_entry(); + const netaddr::MacAddress dst_mac = + rewrite_options.dst_mac_rewrite.value_or(netaddr::MacAddress::AllZeros()); + const std::string neighbor_id = dst_mac.ToLinkLocalIpv6Address().ToString(); + neighbor_entry.mutable_match()->set_router_interface_id(kRifId); + neighbor_entry.mutable_match()->set_neighbor_id(neighbor_id); + rif_entry.mutable_match()->set_router_interface_id(kRifId); + neighbor_entry.mutable_action()->mutable_set_dst_mac()->set_dst_mac( + dst_mac.ToString()); + + // Create Nexthop entry based on `rewrite_options` + sai::NexthopTableEntry& nexthop_entry = + *entries_.add_entries()->mutable_nexthop_table_entry(); + nexthop_entry.mutable_match()->set_nexthop_id(nexthop_id); + + if (AllRewritesEnabled(rewrite_options)) { + SetIpNexthopAction& action = + *nexthop_entry.mutable_action()->mutable_set_ip_nexthop(); + action.set_router_interface_id(kRifId); + action.set_neighbor_id(neighbor_id); + } else { + SetIpNexthopAndDisableRewritesAction& action = + *nexthop_entry.mutable_action() + ->mutable_set_ip_nexthop_and_disable_rewrites(); + action.set_router_interface_id(kRifId); + action.set_neighbor_id(neighbor_id); + action.set_disable_decrement_ttl( + BoolToHexString(rewrite_options.disable_decrement_ttl)); + action.set_disable_src_mac_rewrite( + BoolToHexString(!rewrite_options.src_mac_rewrite.has_value())); + action.set_disable_dst_mac_rewrite( + BoolToHexString(!rewrite_options.dst_mac_rewrite.has_value())); + action.set_disable_vlan_rewrite( + BoolToHexString(rewrite_options.disable_vlan_rewrite)); } return *this; diff --git a/sai_p4/instantiations/google/test_tools/test_entries.h b/sai_p4/instantiations/google/test_tools/test_entries.h index 55875e90..f511301d 100644 --- a/sai_p4/instantiations/google/test_tools/test_entries.h +++ b/sai_p4/instantiations/google/test_tools/test_entries.h @@ -53,17 +53,26 @@ struct NexthopRewriteOptions { // When present, source MAC will be rewritten to the given address. When // absent, no rewrite occurs. std::optional src_mac_rewrite = - netaddr::MacAddress(1, 2, 3, 4, 5, 6); + netaddr::MacAddress(6, 5, 4, 3, 2, 1); // When present, destination MAC will be rewritten to the given address. When // absent, no rewrite occurs. std::optional dst_mac_rewrite = netaddr::MacAddress(2, 2, 2, 2, 2, 2); + // If true, makes the nexthop use a `set_ip_nexthop_and_disable_rewrites` + // action with `disable_vlan_rewrite` set to true. If false, such an action + // may still be used based on above values (otherwise a `set_ip_nexthop` + // action will be used), but `disable_vlan_rewrite` will be set false. bool disable_vlan_rewrite = false; + // When present, causes the RIF to use a `set_port_and_src_mac_and_vlan_id` + // action with `vlan_id = egress_rif_vlan`. When absent, the RIF will instead + // use the `set_port_and_src_mac` action. + std::optional egress_rif_vlan = std::nullopt; }; enum class IpVersion { kIpv4, kIpv6, + // Targets both IPv4 and IPv6 packets. kIpv4And6, }; @@ -150,23 +159,46 @@ class EntryBuilder { netaddr::MacAddress src_mac; }; + // Adds an entry that matches all packets and punts them according to + // `action`. EntryBuilder& AddEntryPuntingAllPackets(PuntAction action); + + // Constructs all entries required to forward all `ip_version` packets to + // `egress_port` and modify them using `rewrite_options`. // Note: Cannot be combined with other entries that forward *all* IP packets // in a specific way. EntryBuilder& AddEntriesForwardingIpPacketsToGivenPort( absl::string_view egress_port, - IpVersion ip_version = IpVersion::kIpv4And6, NexthopRewriteOptions = {}); + IpVersion ip_version = IpVersion::kIpv4And6, + const NexthopRewriteOptions& rewrite_options = {}); + + // Constructs a default IP route matching packets of `ip_version` with `vrf` + // and sending them to `egress_port`. Matching packets will be modified using + // `rewrite_options`. + // Note: For packets to hit this route, additional entries are required! At a + // minimum an L3 admit entry and entries that assign the given `vrf`. + // Note: Cannot be combined with other entries that forward *all* IP packets + // in a specific way unless they specify a different `vrf`. + EntryBuilder& AddDefaultRouteForwardingAllPacketsToGivenPort( + absl::string_view egress_port, IpVersion ip_version, + absl::string_view vrf, const NexthopRewriteOptions& rewrite_options = {}); + + // Constructs an IpNexthop entry with `nexthop_id` pointing to a neighbor + // entry and RIF entry all characterized by `nexthop_rewrite_options`. The RIF + // will output packets on `egress_port`. + EntryBuilder& AddNexthopRifNeighborEntries( + absl::string_view nexthop_id, absl::string_view egress_port, + const NexthopRewriteOptions& rewrite_options = {}); + + // Warning: If you try to install the result of multiple calls to this + // function (with different `multicast_group_id`s), you will get a runtime + // error. // Note: Cannot be combined with other entries that forward *all* IP packets // in a specific way. EntryBuilder& AddEntriesForwardingIpPacketsToGivenMulticastGroup( int multicast_group_id); EntryBuilder& AddVrfEntry(absl::string_view vrf); EntryBuilder& AddEntryAdmittingAllPacketsToL3(); - EntryBuilder& AddDefaultRouteForwardingAllPacketsToGivenPort( - absl::string_view egress_port, IpVersion ip_version, - absl::string_view vrf, - const NexthopRewriteOptions& nexthop_rewrite_options = {}, - std::optional vlan_hexstr = std::nullopt); EntryBuilder& AddMulticastRoute(absl::string_view vrf, const netaddr::Ipv4Address& dst_ip, int multicast_group_id); @@ -192,10 +224,6 @@ class EntryBuilder { EntryBuilder& AddEntrySettingVlanIdInPreIngress( absl::string_view set_vlan_id_hexstr, std::optional match_vlan_id_hexstr = std::nullopt); - EntryBuilder& AddNexthopRifNeighborEntries( - absl::string_view nexthop_id, absl::string_view egress_port, - const NexthopRewriteOptions& nexthop_rewrite_options = {}, - std::optional vlan_hexstr = std::nullopt); EntryBuilder& AddIngressAclEntryRedirectingToNexthop( absl::string_view nexthop_id, std::optional in_port_match = std::nullopt); diff --git a/sai_p4/instantiations/google/tests/sai_p4_bmv2_tunnel_termination_integration_test.cc b/sai_p4/instantiations/google/tests/sai_p4_bmv2_tunnel_termination_integration_test.cc index cc256b11..619bd6a1 100644 --- a/sai_p4/instantiations/google/tests/sai_p4_bmv2_tunnel_termination_integration_test.cc +++ b/sai_p4/instantiations/google/tests/sai_p4_bmv2_tunnel_termination_integration_test.cc @@ -22,6 +22,7 @@ #include "absl/status/statusor.h" #include "absl/strings/string_view.h" +#include "absl/strings/substitute.h" #include "gmock/gmock.h" #include "gtest/gtest.h" #include "gutil/proto.h" @@ -30,6 +31,7 @@ #include "gutil/status_matchers.h" #include "p4/v1/p4runtime.pb.h" #include "p4_pdpi/ir.pb.h" +#include "p4_pdpi/netaddr/mac_address.h" #include "p4_pdpi/p4_runtime_matchers.h" #include "p4_pdpi/p4_runtime_session.h" #include "p4_pdpi/p4_runtime_session_extras.h" @@ -59,45 +61,52 @@ using ::testing::ElementsAre; using ::testing::IsEmpty; using ::testing::StrEq; +constexpr netaddr::MacAddress kSrcMac = netaddr::MacAddress(0, 1, 2, 3, 4, 5); +constexpr netaddr::MacAddress kDstMac = netaddr::MacAddress(2, 3, 4, 5, 6, 7); +; -absl::StatusOr GetIpv4InIpv6Packet() { - ASSIGN_OR_RETURN(auto packet, gutil::ParseTextProto(R"pb( - headers { - ethernet_header { - ethernet_destination: "02:03:04:05:06:07" - ethernet_source: "00:01:02:03:04:05" - ethertype: "0x86dd" # IPv6 - } - } - headers { - ipv6_header { - version: "0x6" - dscp: "0x00" - ecn: "0x0" - flow_label: "0x12345" - next_header: "0x04" # IPv4 - hop_limit: "0x03" - ipv6_source: "2001::1" - ipv6_destination: "2001::2" - } - } - headers { - ipv4_header { - version: "0x4" - ihl: "0x5" - dscp: "0x1c" - ecn: "0x0" - identification: "0x0000" - flags: "0x0" - fragment_offset: "0x0000" - ttl: "0x20" - protocol: "0xfe" - ipv4_source: "192.168.100.2" - ipv4_destination: "192.168.100.1" - } - } - payload: "A beautiful IPv4-in-IPv6 test packet." - )pb")); +absl::StatusOr GetIpv4InIpv6Packet( + const netaddr::MacAddress& src_mac, const netaddr::MacAddress& dst_mac) { + ASSIGN_OR_RETURN(auto packet, + gutil::ParseTextProto(absl::Substitute( + R"pb( + headers { + ethernet_header { + ethernet_source: "$0" + ethernet_destination: "$1" + ethertype: "0x86dd" # IPv6 + } + } + headers { + ipv6_header { + version: "0x6" + dscp: "0x00" + ecn: "0x0" + flow_label: "0x12345" + next_header: "0x04" # IPv4 + hop_limit: "0x03" + ipv6_source: "2001::1" + ipv6_destination: "2001::2" + } + } + headers { + ipv4_header { + version: "0x4" + ihl: "0x5" + dscp: "0x1c" + ecn: "0x0" + identification: "0x0000" + flags: "0x0" + fragment_offset: "0x0000" + ttl: "0x20" + protocol: "0xfe" + ipv4_source: "192.168.100.2" + ipv4_destination: "192.168.100.1" + } + } + payload: "A beautiful IPv4-in-IPv6 test packet." + )pb", + src_mac.ToString(), dst_mac.ToString()))); RETURN_IF_ERROR(packetlib::UpdateAllComputedFields(packet).status()); return packet; } @@ -118,7 +127,10 @@ TEST_P(TunnelTerminationTest, PacketGetsDecapsulatedAndForwarded) { sai::EntryBuilder() .AddEntryDecappingAllIpInIpv6PacketsAndSettingVrf("vrf") .AddDefaultRouteForwardingAllPacketsToGivenPort( - /*egress_port=*/"\001", sai::IpVersion::kIpv4, "vrf") + /*egress_port=*/"\001", sai::IpVersion::kIpv4, "vrf", + // Rewrites to the same src and dst mac as the input packet. + sai::NexthopRewriteOptions{.src_mac_rewrite = kSrcMac, + .dst_mac_rewrite = kDstMac}) .AddEntryAdmittingAllPacketsToL3() // Needed for forwarding. .LogPdEntries() .GetDedupedPiEntities(kIrP4Info, @@ -128,7 +140,8 @@ TEST_P(TunnelTerminationTest, PacketGetsDecapsulatedAndForwarded) { ASSERT_OK(pdpi::InstallPiEntities(bmv2.P4RuntimeSession(), pi_entities)); // Inject Ipv4-in-IPv6 test packet and expect one output packet. - ASSERT_OK_AND_ASSIGN(packetlib::Packet input_packet, GetIpv4InIpv6Packet()); + ASSERT_OK_AND_ASSIGN(packetlib::Packet input_packet, + GetIpv4InIpv6Packet(kSrcMac, kDstMac)); ASSERT_OK_AND_ASSIGN(std::string raw_input_packet, packetlib::SerializePacket(input_packet)); ASSERT_OK_AND_ASSIGN(std::vector output_packets, @@ -203,7 +216,8 @@ TEST_P(TunnelTerminationTest, ASSERT_OK(pdpi::InstallPiEntities(bmv2.P4RuntimeSession(), pi_entities)); // Inject Ipv4-in-IPv6 test packet and expect one output packet. - ASSERT_OK_AND_ASSIGN(packetlib::Packet input_packet, GetIpv4InIpv6Packet()); + ASSERT_OK_AND_ASSIGN(packetlib::Packet input_packet, + GetIpv4InIpv6Packet(kSrcMac, kDstMac)); ASSERT_OK_AND_ASSIGN(std::string raw_input_packet, packetlib::SerializePacket(input_packet)); ASSERT_OK_AND_ASSIGN(std::vector output_packets, @@ -240,7 +254,8 @@ TEST_P(TunnelTerminationTest, PuntedPacketIsNotDecapsulated) { // Inject Ipv4-in-IPv6 test packet and expect 0 forwarded packets and 1 // punted packet. - ASSERT_OK_AND_ASSIGN(packetlib::Packet input_packet, GetIpv4InIpv6Packet()); + ASSERT_OK_AND_ASSIGN(packetlib::Packet input_packet, + GetIpv4InIpv6Packet(kSrcMac, kDstMac)); ASSERT_OK_AND_ASSIGN(std::string raw_input_packet, packetlib::SerializePacket(input_packet)); ASSERT_THAT(bmv2.SendPacket(pins::PacketAtPort{ diff --git a/sai_p4/instantiations/google/tests/sai_p4_bmv2_vlan_test.cc b/sai_p4/instantiations/google/tests/sai_p4_bmv2_vlan_test.cc index a9a68f46..9ccd1f87 100644 --- a/sai_p4/instantiations/google/tests/sai_p4_bmv2_vlan_test.cc +++ b/sai_p4/instantiations/google/tests/sai_p4_bmv2_vlan_test.cc @@ -30,6 +30,7 @@ #include "p4/v1/p4runtime.pb.h" #include "p4_pdpi/ir.pb.h" #include "p4_pdpi/p4_runtime_matchers.h" +#include "p4_pdpi/p4_runtime_session.h" #include "p4_pdpi/p4_runtime_session_extras.h" #include "p4_pdpi/packetlib/packetlib.h" #include "p4_pdpi/packetlib/packetlib.pb.h" @@ -146,7 +147,8 @@ absl::Status InstallEntries(Bmv2& bmv2, const pdpi::IrP4Info& ir_p4info, ASSIGN_OR_RETURN(std::vector pi_entities, entry_builder.LogPdEntries().GetDedupedPiEntities( ir_p4info, /*allow_unsupported=*/true)); - return pdpi::InstallPiEntities(bmv2.P4RuntimeSession(), pi_entities); + return pdpi::InstallPiEntities(&bmv2.P4RuntimeSession(), ir_p4info, + pi_entities); } TEST_P(VlanTest, VlanPacketWithNonReservedVidGetsDroppedByDefault) { @@ -280,17 +282,19 @@ absl::Status InstallEntriesOnlyForwardingPacketsMatchingVlanIdInAclPreIngress( absl::Status InstallEntriesForwardingAndRewritingVlanInRifTable( Bmv2& bmv2, const pdpi::IrP4Info& ir_p4info, - std::optional vlan_id_hexstr, - absl::string_view egress_port, bool disable_vlan_checks, - bool disable_vlan_rewrite) { - RETURN_IF_ERROR(InstallEntries( - bmv2, ir_p4info, - sai::EntryBuilder() - .AddEntrySettingVrfForAllPackets("vrf-forward") - .AddEntryAdmittingAllPacketsToL3() - .AddDefaultRouteForwardingAllPacketsToGivenPort( - egress_port, sai::IpVersion::kIpv4, "vrf-forward", - {.disable_vlan_rewrite = disable_vlan_rewrite}, vlan_id_hexstr))); + std::optional egress_rif_vlan, absl::string_view egress_port, + bool disable_vlan_checks, bool disable_vlan_rewrite) { + RETURN_IF_ERROR( + InstallEntries(bmv2, ir_p4info, + sai::EntryBuilder() + .AddEntrySettingVrfForAllPackets("vrf-forward") + .AddEntryAdmittingAllPacketsToL3() + .AddDefaultRouteForwardingAllPacketsToGivenPort( + egress_port, sai::IpVersion::kIpv4, "vrf-forward", + sai::NexthopRewriteOptions{ + .disable_vlan_rewrite = disable_vlan_rewrite, + .egress_rif_vlan = egress_rif_vlan, + }))); if (disable_vlan_checks) { return InstallEntries(bmv2, ir_p4info, @@ -305,7 +309,7 @@ TEST_P(VlanTest, const pdpi::IrP4Info kIrP4Info = sai::GetIrP4Info(kInstantiation); ASSERT_OK_AND_ASSIGN(Bmv2 bmv2, sai::SetUpBmv2ForSaiP4(kInstantiation)); - constexpr absl::string_view kEgressVlan = "0x003"; + const std::string kEgressVlan = "0x003"; ASSERT_OK(InstallEntriesForwardingAndRewritingVlanInRifTable( bmv2, kIrP4Info, kEgressVlan, kEgressPortProto, /*disable_vlan_checks=*/true, /*disable_vlan_rewrite=*/false)); @@ -366,7 +370,7 @@ TEST_P(VlanTest, SettingNonReservedVidInRifWithVlanChecksResultsInDrop) { const pdpi::IrP4Info kIrP4Info = sai::GetIrP4Info(kInstantiation); ASSERT_OK_AND_ASSIGN(Bmv2 bmv2, sai::SetUpBmv2ForSaiP4(kInstantiation)); - constexpr absl::string_view kEgressVlan = "0x003"; + const std::string kEgressVlan = "0x003"; ASSERT_OK(InstallEntriesForwardingAndRewritingVlanInRifTable( bmv2, kIrP4Info, kEgressVlan, kEgressPortProto, /*disable_vlan_checks=*/false, /*disable_vlan_rewrite=*/false)); @@ -403,7 +407,7 @@ TEST_P(VlanTest, SettingVid4095InRifResultsOutputPacketWithNoVlanTag) { const pdpi::IrP4Info kIrP4Info = sai::GetIrP4Info(kInstantiation); ASSERT_OK_AND_ASSIGN(Bmv2 bmv2, sai::SetUpBmv2ForSaiP4(kInstantiation)); - constexpr absl::string_view kEgressVlan = "0xfff"; + const std::string kEgressVlan = "0xfff"; ASSERT_OK(InstallEntriesForwardingAndRewritingVlanInRifTable( bmv2, kIrP4Info, kEgressVlan, kEgressPortProto, /*disable_vlan_checks=*/true, /*disable_vlan_rewrite=*/false)); @@ -450,7 +454,8 @@ TEST_P(VlanTest, IngressVidGetCarriedOverToEgressWhenVlanRewriteIsDisabled) { ASSERT_OK_AND_ASSIGN(Bmv2 bmv2, sai::SetUpBmv2ForSaiP4(kInstantiation)); ASSERT_OK(InstallEntriesForwardingAndRewritingVlanInRifTable( - bmv2, kIrP4Info, /*vlan_id_hexstr=*/std::nullopt, kEgressPortProto, + bmv2, kIrP4Info, /*egress_rif_vlan=*/std::nullopt, kEgressPortProto, + /*disable_vlan_checks=*/true, /*disable_vlan_rewrite=*/true)); { // Inject packet without a VLAN tag. ASSERT_OK_AND_ASSIGN(PacketsByPort output_by_port, @@ -499,7 +504,7 @@ TEST_P(VlanTest, ASSERT_OK_AND_ASSIGN(Bmv2 bmv2, sai::SetUpBmv2ForSaiP4(kInstantiation)); ASSERT_OK(InstallEntriesForwardingAndRewritingVlanInRifTable( - bmv2, kIrP4Info, /*vlan_id_hexstr=*/"0x00c", kEgressPortProto, + bmv2, kIrP4Info, /*egress_rif_vlan=*/"0x00c", kEgressPortProto, /*disable_vlan_checks=*/true, /*disable_vlan_rewrite=*/true)); { @@ -565,7 +570,7 @@ sai::TableEntries EntriesForwardingAndRewritingVlanInRifTable( TEST(VlanTest, SettingNonReservedVidInRifWithoutVlanChecksResultsInPacketWithThatId) { - const sai::Instantiation kInstantiation = sai::Instantiation::kTor; + const sai::Instantiation kInstantiation = GetParam(); const pdpi::IrP4Info kIrP4Info = sai::GetIrP4Info(kInstantiation); ASSERT_OK_AND_ASSIGN(Bmv2 bmv2, sai::SetUpBmv2ForSaiP4(kInstantiation)); @@ -573,7 +578,8 @@ TEST(VlanTest, ASSERT_OK(InstallEntries( bmv2, kIrP4Info, EntriesForwardingAndRewritingVlanInRifTable( - kEgressVlan, kEgressPortProto, /*disable_vlan_checks=*/true))); + kEgressVlan, kEgressPortProto, + /*disable_vlan_checks=*/true, /*disable_vlan_rewrite=*/false))); { // Inject packet without a VLAN tag. ASSERT_OK_AND_ASSIGN(PacketsByPort output_by_port, @@ -626,7 +632,7 @@ TEST(VlanTest, } TEST(VlanTest, SettingNonReservedVidInRifWithVlanChecksResultsInDrop) { - const sai::Instantiation kInstantiation = sai::Instantiation::kTor; + const sai::Instantiation kInstantiation = GetParam(); const pdpi::IrP4Info kIrP4Info = sai::GetIrP4Info(kInstantiation); ASSERT_OK_AND_ASSIGN(Bmv2 bmv2, sai::SetUpBmv2ForSaiP4(kInstantiation)); @@ -634,7 +640,8 @@ TEST(VlanTest, SettingNonReservedVidInRifWithVlanChecksResultsInDrop) { ASSERT_OK(InstallEntries( bmv2, kIrP4Info, EntriesForwardingAndRewritingVlanInRifTable( - kEgressVlan, kEgressPortProto, /*disable_vlan_checks=*/false))); + kEgressVlan, kEgressPortProto, + /*disable_vlan_checks=*/false, /*disable_vlan_rewrite=*/false))); { // Inject packet without a VLAN tag. ASSERT_OK_AND_ASSIGN(PacketsByPort output_by_port, @@ -663,15 +670,16 @@ TEST(VlanTest, SettingNonReservedVidInRifWithVlanChecksResultsInDrop) { } TEST(VlanTest, SettingVid4095InRifResultsOutputPacketWithNoVlanTag) { - const sai::Instantiation kInstantiation = sai::Instantiation::kTor; + const sai::Instantiation kInstantiation = GetParam(); const pdpi::IrP4Info kIrP4Info = sai::GetIrP4Info(kInstantiation); ASSERT_OK_AND_ASSIGN(Bmv2 bmv2, sai::SetUpBmv2ForSaiP4(kInstantiation)); - constexpr absl::string_view kEgressVlan = "0xfff"; + const std::string kEgressVlan = "0xfff"; ASSERT_OK(InstallEntries( bmv2, kIrP4Info, EntriesForwardingAndRewritingVlanInRifTable( - kEgressVlan, kEgressPortProto, /*disable_vlan_checks=*/true))); + kEgressVlan, kEgressPortProto, + /*disable_vlan_checks=*/true, /*disable_vlan_rewrite=*/false)); { // Inject packet without a VLAN tag. ASSERT_OK_AND_ASSIGN(PacketsByPort output_by_port, diff --git a/sai_p4/instantiations/google/tor.p4info.pb.txt b/sai_p4/instantiations/google/tor.p4info.pb.txt index 46d6a7f9..43e20d62 100644 --- a/sai_p4/instantiations/google/tor.p4info.pb.txt +++ b/sai_p4/instantiations/google/tor.p4info.pb.txt @@ -778,7 +778,7 @@ tables { const_default_action_id: 21257015 direct_resource_ids: 318767367 direct_resource_ids: 352321794 - size: 511 + size: 255 } tables { preamble { @@ -854,7 +854,6 @@ tables { id: 8 name: "vrf_id" annotations: "@sai_field(SAI_ACL_TABLE_ATTR_FIELD_VRF_ID)" - annotations: "@unsupported" match_type: OPTIONAL type_name { name: "vrf_id_t" @@ -863,15 +862,10 @@ tables { match_fields { id: 9 name: "ipmc_table_hit" - annotations: "@sai_field(SAI_ACL_TABLE_ATTR_FIELD_IPMC_TABLE_HIT)" - annotations: "@unsupported" + annotations: "@sai_field(SAI_ACL_TABLE_ATTR_FIELD_IPMC_NPU_META_DST_HIT)" bitwidth: 1 match_type: OPTIONAL } - action_refs { - id: 16777475 - annotations: "@proto_id(4)" - } action_refs { id: 16777476 annotations: "@proto_id(1)" @@ -1307,6 +1301,13 @@ actions { annotations: "@noWarn(\"unused\")" } } +actions { + preamble { + id: 24742814 + name: "no_action" + alias: "no_action" + } +} actions { preamble { id: 16777221 @@ -1389,13 +1390,6 @@ actions { alias: "admit_to_l3" } } -actions { - preamble { - id: 24742814 - name: "ingress.routing_lookup.no_action" - alias: "no_action" - } -} actions { preamble { id: 16777222 @@ -1635,6 +1629,7 @@ actions { id: 1 name: "nexthop_id" annotations: "@sai_action_param(SAI_ACL_ENTRY_ATTR_ACTION_REDIRECT)" + annotations: "@sai_action_param_object_type(SAI_OBJECT_TYPE_NEXT_HOP)" annotations: "@refers_to(nexthop_table , nexthop_id)" type_name { name: "nexthop_id_t" @@ -1646,13 +1641,13 @@ actions { id: 16777491 name: "ingress.acl_ingress.redirect_to_ipmc_group" alias: "redirect_to_ipmc_group" - annotations: "@unsupported" annotations: "@action_restriction(\"\n // Disallow 0 since it encodes \'no multicast\' in V1Model.\n multicast_group_id != 0;\n \")" } params { id: 1 name: "multicast_group_id" annotations: "@sai_action_param(SAI_ACL_ENTRY_ATTR_ACTION_REDIRECT)" + annotations: "@sai_action_param_object_type(SAI_OBJECT_TYPE_IPMC_GROUP)" annotations: "@refers_to(builtin : : multicast_group_table , multicast_group_id)" bitwidth: 16 } diff --git a/sai_p4/instantiations/google/unioned_p4info.pb.txt b/sai_p4/instantiations/google/unioned_p4info.pb.txt index 97671f6d..29b1a7c7 100644 --- a/sai_p4/instantiations/google/unioned_p4info.pb.txt +++ b/sai_p4/instantiations/google/unioned_p4info.pb.txt @@ -19,6 +19,13 @@ tables { bitwidth: 128 match_type: TERNARY } + match_fields { + id: 2 + name: "src_ipv6" + annotations: "@format(IPV6_ADDRESS)" + bitwidth: 128 + match_type: TERNARY + } action_refs { id: 16777238 annotations: "@proto_id(1)" @@ -655,7 +662,7 @@ tables { name: "route_metadata" annotations: "@sai_field(SAI_ACL_TABLE_ATTR_FIELD_ROUTE_DST_USER_META)" bitwidth: 6 - match_type: OPTIONAL + match_type: TERNARY } match_fields { id: 5 @@ -721,7 +728,7 @@ tables { const_default_action_id: 21257015 direct_resource_ids: 318767367 direct_resource_ids: 352321794 - size: 511 + size: 255 } tables { preamble { @@ -1196,7 +1203,6 @@ tables { id: 8 name: "vrf_id" annotations: "@sai_field(SAI_ACL_TABLE_ATTR_FIELD_VRF_ID)" - annotations: "@unsupported" match_type: OPTIONAL type_name { name: "vrf_id_t" @@ -1205,8 +1211,7 @@ tables { match_fields { id: 9 name: "ipmc_table_hit" - annotations: "@sai_field(SAI_ACL_TABLE_ATTR_FIELD_IPMC_TABLE_HIT)" - annotations: "@unsupported" + annotations: "@sai_field(SAI_ACL_TABLE_ATTR_FIELD_IPMC_NPU_META_DST_HIT)" bitwidth: 1 match_type: OPTIONAL } @@ -1233,10 +1238,6 @@ tables { bitwidth: 12 match_type: TERNARY } - action_refs { - id: 16777475 - annotations: "@proto_id(4)" - } action_refs { id: 16777476 annotations: "@proto_id(1)" @@ -1606,6 +1607,13 @@ actions { annotations: "@noWarn(\"unused\")" } } +actions { + preamble { + id: 24742814 + name: "no_action" + alias: "no_action" + } +} actions { preamble { id: 16777221 @@ -1674,13 +1682,6 @@ actions { alias: "admit_to_l3" } } -actions { - preamble { - id: 24742814 - name: "ingress.routing_lookup.no_action" - alias: "no_action" - } -} actions { preamble { id: 16777222 @@ -2246,6 +2247,7 @@ actions { id: 1 name: "nexthop_id" annotations: "@sai_action_param(SAI_ACL_ENTRY_ATTR_ACTION_REDIRECT)" + annotations: "@sai_action_param_object_type(SAI_OBJECT_TYPE_NEXT_HOP)" annotations: "@refers_to(nexthop_table , nexthop_id)" type_name { name: "nexthop_id_t" @@ -2257,13 +2259,13 @@ actions { id: 16777491 name: "ingress.acl_ingress.redirect_to_ipmc_group" alias: "redirect_to_ipmc_group" - annotations: "@unsupported" annotations: "@action_restriction(\"\n // Disallow 0 since it encodes \'no multicast\' in V1Model.\n multicast_group_id != 0;\n \")" } params { id: 1 name: "multicast_group_id" annotations: "@sai_action_param(SAI_ACL_ENTRY_ATTR_ACTION_REDIRECT)" + annotations: "@sai_action_param_object_type(SAI_OBJECT_TYPE_IPMC_GROUP)" annotations: "@refers_to(builtin : : multicast_group_table , multicast_group_id)" bitwidth: 16 }