From 1d1c89dffb99c27f4cdd9e72fa2f9d76c3d8dc8c Mon Sep 17 00:00:00 2001 From: Riff Date: Wed, 28 Feb 2024 13:58:33 -0800 Subject: [PATCH] [dash-p4] Add skeleton for matching stage transition control and extract the matching stages in outbound pipeline into dedicated file. (#527) ## Problem Currently, the routing types in DASH is used to define 2 things: - Stage transition: which stage we need to run as the next stage - Routing actions: what SDN transformations are required if this stage is the last stage used to match the packets. Although the concepts are there, in DASH P4 code, these concepts are not reflected in a modularized way, and sometimes not that obvious as the transition cannot be found in the definitions of the routing types (P4 table actions). ## What this change is doing This commit contains 2 changes inside: - Add skeleton for matching stage transition control - Extract the matching stages in outbound pipeline into dedicated file These changes are intended to help with: - Modularization and readability of the pipeline. - Make the stage transition control more explicit and obvious. This commit will not change any generated SAI APIs. --- dash-pipeline/bmv2/dash_metadata.p4 | 19 +++++ dash-pipeline/bmv2/dash_outbound.p4 | 79 ++----------------- dash-pipeline/bmv2/dash_pipeline.p4 | 2 +- dash-pipeline/bmv2/dash_routing_types.p4 | 11 +++ dash-pipeline/bmv2/stages/outbound_mapping.p4 | 58 ++++++++++++++ dash-pipeline/bmv2/stages/outbound_routing.p4 | 40 ++++++++++ 6 files changed, 136 insertions(+), 73 deletions(-) create mode 100644 dash-pipeline/bmv2/stages/outbound_mapping.p4 create mode 100644 dash-pipeline/bmv2/stages/outbound_routing.p4 diff --git a/dash-pipeline/bmv2/dash_metadata.p4 b/dash-pipeline/bmv2/dash_metadata.p4 index 5cfed64e8..900ab79bf 100644 --- a/dash-pipeline/bmv2/dash_metadata.p4 +++ b/dash-pipeline/bmv2/dash_metadata.p4 @@ -16,6 +16,22 @@ enum bit<16> dash_direction_t { INBOUND = 2 } +// Pipeline stages: +enum bit<16> dash_pipeline_stage_t { + INVALID = 0, + + // Inbound stages + INBOUND_STAGE_START = 100, + + // Outbound stages + OUTBOUND_STAGE_START = 200, + OUTBOUND_ROUTING = 200, // OUTBOUND_STAGE_START + OUTBOUND_MAPPING = 201, + + // Common stages + ROUTING_ACTION_APPLY = 300 +} + struct conntrack_data_t { bool allow_in; bool allow_out; @@ -96,6 +112,9 @@ struct metadata_t { bool is_fast_path_icmp_flow_redirection_packet; bit<1> fast_path_icmp_flow_redirection_disabled; + // Stage transition control + dash_pipeline_stage_t target_stage; + // Actions bit<32> routing_actions; diff --git a/dash-pipeline/bmv2/dash_outbound.p4 b/dash-pipeline/bmv2/dash_outbound.p4 index 4a4de8cea..fa780027d 100644 --- a/dash-pipeline/bmv2/dash_outbound.p4 +++ b/dash-pipeline/bmv2/dash_outbound.p4 @@ -1,72 +1,15 @@ -#ifndef _SIRIUS_OUTBOUND_P4_ -#define _SIRIUS_OUTBOUND_P4_ +#ifndef _DASH_OUTBOUND_P4_ +#define _DASH_OUTBOUND_P4_ #include "dash_headers.p4" #include "dash_acl.p4" -#include "dash_routing_types.p4" #include "dash_conntrack.p4" +#include "stages/outbound_routing.p4" +#include "stages/outbound_mapping.p4" control outbound(inout headers_t hdr, inout metadata_t meta) { - DEFINE_TABLE_COUNTER(routing_counter) - - @SaiTable[name = "outbound_routing", api = "dash_outbound_routing"] - table routing { - key = { - meta.eni_id : exact @SaiVal[type="sai_object_id_t"]; - meta.is_overlay_ip_v6 : exact @SaiVal[name = "destination_is_v6"]; - meta.dst_ip_addr : lpm @SaiVal[name = "destination"]; - } - - actions = { - route_vnet(hdr, meta); /* for expressroute - ecmp of overlay */ - route_vnet_direct(hdr, meta); - route_direct(hdr, meta); - route_service_tunnel(hdr, meta); - drop(meta); - } - const default_action = drop(meta); - - ATTACH_TABLE_COUNTER(routing_counter) - } - - DEFINE_TABLE_COUNTER(ca_to_pa_counter) - - @SaiTable[name = "outbound_ca_to_pa", api = "dash_outbound_ca_to_pa"] - table ca_to_pa { - key = { - /* Flow for express route */ - meta.dst_vnet_id: exact @SaiVal[type="sai_object_id_t"]; - meta.is_lkup_dst_ip_v6 : exact @SaiVal[name = "dip_is_v6"]; - meta.lkup_dst_ip_addr : exact @SaiVal[name = "dip"]; - } - - actions = { - set_tunnel_mapping(hdr, meta); - set_private_link_mapping(hdr, meta); - @defaultonly drop(meta); - } - const default_action = drop(meta); - - ATTACH_TABLE_COUNTER(ca_to_pa_counter) - } - - action set_vnet_attrs(bit<24> vni) { - meta.encap_data.vni = vni; - } - - @SaiTable[name = "vnet", api = "dash_vnet", isobject="true"] - table vnet { - key = { - meta.vnet_id : exact @SaiVal[type="sai_object_id_t"]; - } - - actions = { - set_vnet_attrs; - } - } - apply { #ifdef STATEFUL_P4 ConntrackOut.apply(0); @@ -92,17 +35,9 @@ control outbound(inout headers_t hdr, meta.lkup_dst_ip_addr = meta.dst_ip_addr; meta.is_lkup_dst_ip_v6 = meta.is_overlay_ip_v6; - switch (routing.apply().action_run) { - route_vnet_direct: - route_vnet: { - switch (ca_to_pa.apply().action_run) { - set_tunnel_mapping: { - vnet.apply(); - } - } - } - } + outbound_routing_stage.apply(hdr, meta); + outbound_mapping_stage.apply(hdr, meta); } } -#endif /* _SIRIUS_OUTBOUND_P4_ */ +#endif /* _DASH_OUTBOUND_P4_ */ diff --git a/dash-pipeline/bmv2/dash_pipeline.p4 b/dash-pipeline/bmv2/dash_pipeline.p4 index c7b77af0f..ad0917861 100644 --- a/dash-pipeline/bmv2/dash_pipeline.p4 +++ b/dash-pipeline/bmv2/dash_pipeline.p4 @@ -451,8 +451,8 @@ control dash_ingress( acl_group.apply(); - if (meta.direction == dash_direction_t.OUTBOUND) { + meta.target_stage = dash_pipeline_stage_t.OUTBOUND_ROUTING; outbound.apply(hdr, meta); } else if (meta.direction == dash_direction_t.INBOUND) { inbound.apply(hdr, meta); diff --git a/dash-pipeline/bmv2/dash_routing_types.p4 b/dash-pipeline/bmv2/dash_routing_types.p4 index 7df952b47..1531fa916 100644 --- a/dash-pipeline/bmv2/dash_routing_types.p4 +++ b/dash-pipeline/bmv2/dash_routing_types.p4 @@ -24,6 +24,7 @@ action set_mapping_meter_attr( // Routing Type - drop: action drop(inout metadata_t meta) { + meta.target_stage = dash_pipeline_stage_t.ROUTING_ACTION_APPLY; meta.dropped = true; } @@ -37,6 +38,7 @@ action route_vnet( bit<1> meter_policy_en, bit<16> meter_class) { + meta.target_stage = dash_pipeline_stage_t.OUTBOUND_MAPPING; meta.dst_vnet_id = dst_vnet_id; set_route_meter_attrs(meta, meter_policy_en, meter_class); } @@ -54,6 +56,7 @@ action route_vnet_direct( bit<1> meter_policy_en, bit<16> meter_class) { + meta.target_stage = dash_pipeline_stage_t.OUTBOUND_MAPPING; meta.dst_vnet_id = dst_vnet_id; meta.lkup_dst_ip_addr = overlay_ip; meta.is_lkup_dst_ip_v6 = overlay_ip_is_v6; @@ -69,6 +72,7 @@ action route_direct( bit<1> meter_policy_en, bit<16> meter_class) { + meta.target_stage = dash_pipeline_stage_t.ROUTING_ACTION_APPLY; set_route_meter_attrs(meta, meter_policy_en, meter_class); } @@ -100,6 +104,9 @@ action route_service_tunnel( /* assert(overlay_dip_is_v6 == 1 && overlay_sip_is_v6 == 1); assert(overlay_dip_mask_is_v6 == 1 && overlay_sip_mask_is_v6 == 1); assert(underlay_dip_is_v6 != 1 && underlay_sip_is_v6 != 1); */ + + meta.target_stage = dash_pipeline_stage_t.ROUTING_ACTION_APPLY; + meta.encap_data.original_overlay_dip = hdr.u0_ipv4.src_addr; meta.encap_data.original_overlay_sip = hdr.u0_ipv4.dst_addr; @@ -136,6 +143,8 @@ action set_tunnel_mapping( bit<16> meter_class, bit<1> meter_class_override) { + meta.target_stage = dash_pipeline_stage_t.ROUTING_ACTION_APPLY; + if (use_dst_vnet_vni == 1) meta.vnet_id = meta.dst_vnet_id; @@ -159,6 +168,8 @@ action set_private_link_mapping( bit<16> meter_class, bit<1> meter_class_override) { + meta.target_stage = dash_pipeline_stage_t.ROUTING_ACTION_APPLY; + push_action_static_encap(hdr = hdr, meta = meta, encap = dash_encapsulation, diff --git a/dash-pipeline/bmv2/stages/outbound_mapping.p4 b/dash-pipeline/bmv2/stages/outbound_mapping.p4 new file mode 100644 index 000000000..0cb9af5b3 --- /dev/null +++ b/dash-pipeline/bmv2/stages/outbound_mapping.p4 @@ -0,0 +1,58 @@ +#ifndef _DASH_STAGE_OUTBOUND_MAPPING_P4_ +#define _DASH_STAGE_OUTBOUND_MAPPING_P4_ + +#include "../dash_routing_types.p4" + +control outbound_mapping_stage(inout headers_t hdr, + inout metadata_t meta) +{ + DEFINE_TABLE_COUNTER(ca_to_pa_counter) + + @SaiTable[name = "outbound_ca_to_pa", api = "dash_outbound_ca_to_pa"] + table ca_to_pa { + key = { + /* Flow for express route */ + meta.dst_vnet_id: exact @SaiVal[type="sai_object_id_t"]; + meta.is_lkup_dst_ip_v6 : exact @SaiVal[name = "dip_is_v6"]; + meta.lkup_dst_ip_addr : exact @SaiVal[name = "dip"]; + } + + actions = { + set_tunnel_mapping(hdr, meta); + set_private_link_mapping(hdr, meta); + @defaultonly drop(meta); + } + const default_action = drop(meta); + + ATTACH_TABLE_COUNTER(ca_to_pa_counter) + } + + action set_vnet_attrs(bit<24> vni) { + meta.encap_data.vni = vni; + } + + @SaiTable[name = "vnet", api = "dash_vnet", isobject="true"] + table vnet { + key = { + meta.vnet_id : exact @SaiVal[type="sai_object_id_t"]; + } + + actions = { + set_vnet_attrs; + } + } + + apply { + if (meta.target_stage != dash_pipeline_stage_t.OUTBOUND_MAPPING) { + return; + } + + switch (ca_to_pa.apply().action_run) { + set_tunnel_mapping: { + vnet.apply(); + } + } + } +} + +#endif /* _DASH_STAGE_OUTBOUND_MAPPING_P4_ */ \ No newline at end of file diff --git a/dash-pipeline/bmv2/stages/outbound_routing.p4 b/dash-pipeline/bmv2/stages/outbound_routing.p4 new file mode 100644 index 000000000..95d515f56 --- /dev/null +++ b/dash-pipeline/bmv2/stages/outbound_routing.p4 @@ -0,0 +1,40 @@ +#ifndef _DASH_STAGE_OUTBOUND_ROUTING_P4_ +#define _DASH_STAGE_OUTBOUND_ROUTING_P4_ + +#include "../dash_routing_types.p4" + +control outbound_routing_stage(inout headers_t hdr, + inout metadata_t meta) +{ + DEFINE_TABLE_COUNTER(routing_counter) + + @SaiTable[name = "outbound_routing", api = "dash_outbound_routing"] + table routing { + key = { + meta.eni_id : exact @SaiVal[type="sai_object_id_t"]; + meta.is_overlay_ip_v6 : exact @SaiVal[name = "destination_is_v6"]; + meta.dst_ip_addr : lpm @SaiVal[name = "destination"]; + } + + actions = { + route_vnet(hdr, meta); /* for expressroute - ecmp of overlay */ + route_vnet_direct(hdr, meta); + route_direct(hdr, meta); + route_service_tunnel(hdr, meta); + drop(meta); + } + const default_action = drop(meta); + + ATTACH_TABLE_COUNTER(routing_counter) + } + + apply { + if (meta.target_stage != dash_pipeline_stage_t.OUTBOUND_ROUTING) { + return; + } + + routing.apply(); + } +} + +#endif /* _DASH_STAGE_OUTBOUND_ROUTING_P4_ */ \ No newline at end of file