From 885db1f59b85144d3f2418c26512d37f09370574 Mon Sep 17 00:00:00 2001 From: Riff Date: Mon, 26 Feb 2024 14:16:40 -0800 Subject: [PATCH 01/32] [dash-p4] Fix incorrect service tunnel key assignment. (#521) The service tunnel key is a dead code and never used in building the encapsulation. Assign the tunnel key to VNI will fix this issue. --- dash-pipeline/bmv2/dash_metadata.p4 | 1 - dash-pipeline/bmv2/dash_outbound.p4 | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/dash-pipeline/bmv2/dash_metadata.p4 b/dash-pipeline/bmv2/dash_metadata.p4 index a562d12ca..baba1454d 100644 --- a/dash-pipeline/bmv2/dash_metadata.p4 +++ b/dash-pipeline/bmv2/dash_metadata.p4 @@ -12,7 +12,6 @@ struct encap_data_t { EthernetAddress underlay_dmac; EthernetAddress overlay_dmac; dash_encapsulation_t dash_encapsulation; - bit<24> service_tunnel_key; IPv4Address original_overlay_sip; IPv4Address original_overlay_dip; } diff --git a/dash-pipeline/bmv2/dash_outbound.p4 b/dash-pipeline/bmv2/dash_outbound.p4 index 1b1128651..01cd43461 100644 --- a/dash-pipeline/bmv2/dash_outbound.p4 +++ b/dash-pipeline/bmv2/dash_outbound.p4 @@ -83,7 +83,7 @@ control outbound(inout headers_t hdr, #endif meta.encap_data.overlay_dmac = hdr.u0_ethernet.dst_addr; meta.encap_data.dash_encapsulation = dash_encapsulation; - meta.encap_data.service_tunnel_key = tunnel_key; + meta.encap_data.vni = tunnel_key; set_route_meter_attrs(meter_policy_en, meter_class); } From 3a10145eecbc0b32a70071276044ed3b1d18f14f Mon Sep 17 00:00:00 2001 From: Riff Date: Tue, 27 Feb 2024 09:56:10 -0800 Subject: [PATCH 02/32] [dash-p4] Refactor routing type and routing actions in P4 to make it align more explicitly with the DASH pipeline design. (#522) This commit refactors the table actions in outbound pipeline to make it align more explicitly to how DASH pipeline is modeled today. The change includes: - Extract the table actions related to routing types out of the control block into a separate file. - Split the routing type actions into a list of routing actions. For how routing types and routing actions work, please refer to the [SONiC DASH HLD](https://github.com/sonic-net/DASH/blob/main/documentation/general/dash-sonic-hld.md). This commit doesn't change any SAI header definitions and libsai (except a few action id change, due to moving actions): ![image](https://github.com/sonic-net/DASH/assets/1533278/f6a38224-bb6b-4f00-a2aa-1d755bb9a126) ![image](https://github.com/sonic-net/DASH/assets/1533278/ae376efe-8740-4f42-919c-f31c003b320e) --- dash-pipeline/bmv2/dash_arch_specific.p4 | 7 + dash-pipeline/bmv2/dash_inbound.p4 | 2 +- dash-pipeline/bmv2/dash_metadata.p4 | 48 +++-- dash-pipeline/bmv2/dash_outbound.p4 | 178 ++--------------- dash-pipeline/bmv2/dash_pipeline.p4 | 3 + dash-pipeline/bmv2/dash_routing_types.p4 | 188 ++++++++++++++++++ .../routing_actions/routing_action_nat46.p4 | 51 +++++ .../routing_actions/routing_action_nat64.p4 | 47 +++++ .../routing_action_static_encap.p4 | 80 ++++++++ .../bmv2/routing_actions/routing_actions.p4 | 8 + .../bmv2/stages/routing_action_apply.p4 | 21 ++ 11 files changed, 455 insertions(+), 178 deletions(-) create mode 100644 dash-pipeline/bmv2/dash_routing_types.p4 create mode 100644 dash-pipeline/bmv2/routing_actions/routing_action_nat46.p4 create mode 100644 dash-pipeline/bmv2/routing_actions/routing_action_nat64.p4 create mode 100644 dash-pipeline/bmv2/routing_actions/routing_action_static_encap.p4 create mode 100644 dash-pipeline/bmv2/routing_actions/routing_actions.p4 create mode 100644 dash-pipeline/bmv2/stages/routing_action_apply.p4 diff --git a/dash-pipeline/bmv2/dash_arch_specific.p4 b/dash-pipeline/bmv2/dash_arch_specific.p4 index dbd59b2f8..5127c0498 100644 --- a/dash-pipeline/bmv2/dash_arch_specific.p4 +++ b/dash-pipeline/bmv2/dash_arch_specific.p4 @@ -6,6 +6,9 @@ #include #define DIRECT_COUNTER_TABLE_PROPERTY counters +// DBC (Design By Contract) macros +#define REQUIRES(cond) assert(cond) + #endif // TARGET_BMV2_V1MODEL #ifdef TARGET_DPDK_PNA @@ -13,6 +16,10 @@ #include #define DIRECT_COUNTER_TABLE_PROPERTY pna_direct_counter +// DBC (Design By Contract) macros +// NOTE: PNA doesn't support assert, hence all macros are defined as empty +#define REQUIRES(cond) + #endif // TARGET_DPDK_PNA #endif // __DASH_TARGET_SPECIFIC__ diff --git a/dash-pipeline/bmv2/dash_inbound.p4 b/dash-pipeline/bmv2/dash_inbound.p4 index 15f89d247..d219de5ef 100644 --- a/dash-pipeline/bmv2/dash_inbound.p4 +++ b/dash-pipeline/bmv2/dash_inbound.p4 @@ -37,7 +37,7 @@ control inbound(inout headers_t hdr, tunnel_encap(hdr, meta, - meta.encap_data.overlay_dmac, + meta.overlay_data.dmac, meta.encap_data.underlay_dmac, meta.encap_data.underlay_smac, meta.encap_data.underlay_dip, diff --git a/dash-pipeline/bmv2/dash_metadata.p4 b/dash-pipeline/bmv2/dash_metadata.p4 index baba1454d..5cfed64e8 100644 --- a/dash-pipeline/bmv2/dash_metadata.p4 +++ b/dash-pipeline/bmv2/dash_metadata.p4 @@ -3,17 +3,11 @@ #include "dash_headers.p4" -struct encap_data_t { - bit<24> vni; - bit<24> dest_vnet_vni; - IPv4Address underlay_sip; - IPv4Address underlay_dip; - EthernetAddress underlay_smac; - EthernetAddress underlay_dmac; - EthernetAddress overlay_dmac; - dash_encapsulation_t dash_encapsulation; - IPv4Address original_overlay_sip; - IPv4Address original_overlay_dip; +enum bit<32> dash_routing_actions_t { + NONE = 0, + STATIC_ENCAP = (1 << 0), + NAT46 = (1 << 1), + NAT64 = (1 << 2) } enum bit<16> dash_direction_t { @@ -45,10 +39,30 @@ struct eni_data_t { dash_tunnel_dscp_mode_t dscp_mode; } +struct encap_data_t { + bit<24> vni; + bit<24> dest_vnet_vni; + IPv4Address underlay_sip; + IPv4Address underlay_dip; + EthernetAddress underlay_smac; + EthernetAddress underlay_dmac; + dash_encapsulation_t dash_encapsulation; + IPv4Address original_overlay_sip; + IPv4Address original_overlay_dip; +} + +struct overlay_rewrite_data_t { + bool is_ipv6; + EthernetAddress dmac; + IPv4ORv6Address sip; + IPv4ORv6Address dip; + IPv6Address sip_mask; + IPv6Address dip_mask; +} + struct metadata_t { - bool dropped; + // Lookup context dash_direction_t direction; - encap_data_t encap_data; EthernetAddress eni_addr; bit<16> vnet_id; bit<16> dst_vnet_id; @@ -81,6 +95,14 @@ struct metadata_t { bit<16> tunnel_pointer; bool is_fast_path_icmp_flow_redirection_packet; bit<1> fast_path_icmp_flow_redirection_disabled; + + // Actions + bit<32> routing_actions; + + // Action data + bool dropped; + encap_data_t encap_data; + overlay_rewrite_data_t overlay_data; } #endif /* _SIRIUS_METADATA_P4_ */ diff --git a/dash-pipeline/bmv2/dash_outbound.p4 b/dash-pipeline/bmv2/dash_outbound.p4 index 01cd43461..fdbcd1308 100644 --- a/dash-pipeline/bmv2/dash_outbound.p4 +++ b/dash-pipeline/bmv2/dash_outbound.p4 @@ -3,95 +3,15 @@ #include "dash_headers.p4" #include "dash_acl.p4" +#include "dash_routing_types.p4" #include "dash_conntrack.p4" -#include "dash_service_tunnel.p4" control outbound(inout headers_t hdr, inout metadata_t meta) { - action set_route_meter_attrs(bit<1> meter_policy_en, - bit<16> meter_class) { - meta.meter_policy_en = meter_policy_en; - meta.route_meter_class = meter_class; - } - action route_vnet(@SaiVal[type="sai_object_id_t"] bit<16> dst_vnet_id, - bit<1> meter_policy_en, - bit<16> meter_class) { - meta.dst_vnet_id = dst_vnet_id; - set_route_meter_attrs(meter_policy_en, meter_class); - } - - action route_vnet_direct(bit<16> dst_vnet_id, - bit<1> overlay_ip_is_v6, - @SaiVal[type="sai_ip_address_t"] - IPv4ORv6Address overlay_ip, - bit<1> meter_policy_en, - bit<16> meter_class) { - meta.dst_vnet_id = dst_vnet_id; - meta.lkup_dst_ip_addr = overlay_ip; - meta.is_lkup_dst_ip_v6 = overlay_ip_is_v6; - set_route_meter_attrs(meter_policy_en, meter_class); - } - - action route_direct(bit<1> meter_policy_en, - bit<16> meter_class) { - set_route_meter_attrs(meter_policy_en, meter_class); - /* send to underlay router without any encap */ - } - - action drop() { - meta.dropped = true; - } - - action route_service_tunnel(bit<1> overlay_dip_is_v6, - IPv4ORv6Address overlay_dip, - bit<1> overlay_dip_mask_is_v6, - IPv4ORv6Address overlay_dip_mask, - bit<1> overlay_sip_is_v6, - IPv4ORv6Address overlay_sip, - bit<1> overlay_sip_mask_is_v6, - IPv4ORv6Address overlay_sip_mask, - bit<1> underlay_dip_is_v6, - IPv4ORv6Address underlay_dip, - bit<1> underlay_sip_is_v6, - IPv4ORv6Address underlay_sip, - @SaiVal[type="sai_dash_encapsulation_t", default_value="SAI_DASH_ENCAPSULATION_VXLAN"] - dash_encapsulation_t dash_encapsulation, - bit<24> tunnel_key, - bit<1> meter_policy_en, - bit<16> meter_class) { - /* Assume the overlay addresses provided are always IPv6 and the original are IPv4 */ - /* 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.encap_data.original_overlay_dip = hdr.u0_ipv4.src_addr; - meta.encap_data.original_overlay_sip = hdr.u0_ipv4.dst_addr; - - service_tunnel_encode(hdr, - overlay_dip, - overlay_dip_mask, - overlay_sip, - overlay_sip_mask); - - /* encapsulation will be done in apply block based on dash_encapsulation */ -#ifndef DISABLE_128BIT_ARITHMETIC - // As of 2024-Feb-09, p4c-dpdk does not yet support arithmetic - // on 128-bit operands. This lack of support extends to cast - // operations. - meta.encap_data.underlay_dip = underlay_dip == 0 ? meta.encap_data.original_overlay_dip : (IPv4Address)underlay_dip; - meta.encap_data.underlay_sip = underlay_sip == 0 ? meta.encap_data.original_overlay_sip : (IPv4Address)underlay_sip; -#endif - meta.encap_data.overlay_dmac = hdr.u0_ethernet.dst_addr; - meta.encap_data.dash_encapsulation = dash_encapsulation; - meta.encap_data.vni = tunnel_key; - set_route_meter_attrs(meter_policy_en, meter_class); - } - #ifdef TARGET_BMV2_V1MODEL - direct_counter(CounterType.packets_and_bytes) routing_counter; -#endif // TARGET_BMV2_V1MODEL -#ifdef TARGET_DPDK_PNA +#elif TARGET_DPDK_PNA // TARGET_BMV2_V1MODEL #ifdef DPDK_SUPPORTS_DIRECT_COUNTER_ON_WILDCARD_KEY_TABLE // See the #ifdef with same preprocessor symbol in dash_pipeline.p4 DirectCounter>(PNA_CounterType_t.PACKETS_AND_BYTES) routing_counter; @@ -107,13 +27,13 @@ control outbound(inout headers_t hdr, } actions = { - route_vnet; /* for expressroute - ecmp of overlay */ - route_vnet_direct; - route_direct; - route_service_tunnel; - drop; + 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; + const default_action = drop(meta); #ifdef TARGET_BMV2_V1MODEL counters = routing_counter; @@ -125,55 +45,6 @@ control outbound(inout headers_t hdr, #endif // TARGET_DPDK_PNA } - action set_tunnel(@SaiVal[type="sai_ip_address_t"] IPv4Address underlay_dip, - @SaiVal[type="sai_dash_encapsulation_t"] dash_encapsulation_t dash_encapsulation, - bit<16> meter_class, - bit<1> meter_class_override) { - meta.encap_data.underlay_dip = underlay_dip; - meta.mapping_meter_class = meter_class; - meta.mapping_meter_class_override = meter_class_override; - meta.encap_data.dash_encapsulation = dash_encapsulation; - } - - action set_tunnel_mapping(@SaiVal[type="sai_ip_address_t"] IPv4Address underlay_dip, - EthernetAddress overlay_dmac, - bit<1> use_dst_vnet_vni, - bit<16> meter_class, - bit<1> meter_class_override) { - if (use_dst_vnet_vni == 1) - meta.vnet_id = meta.dst_vnet_id; - meta.encap_data.overlay_dmac = overlay_dmac; - - set_tunnel(underlay_dip, - dash_encapsulation_t.VXLAN, - meter_class, - meter_class_override); - } - - action set_private_link_mapping(@SaiVal[type="sai_ip_address_t"] IPv4Address underlay_dip, - IPv6Address overlay_sip, - IPv6Address overlay_dip, - @SaiVal[type="sai_dash_encapsulation_t"] dash_encapsulation_t dash_encapsulation, - bit<24> tunnel_key, - bit<16> meter_class, - bit<1> meter_class_override) { - meta.encap_data.overlay_dmac = hdr.u0_ethernet.dst_addr; - meta.encap_data.vni = tunnel_key; - // PL has its own underlay SIP, so override - meta.encap_data.underlay_sip = meta.eni_data.pl_underlay_sip; - - service_tunnel_encode(hdr, - overlay_dip, - 0xffffffffffffffffffffffff, - (overlay_sip & ~meta.eni_data.pl_sip_mask) | meta.eni_data.pl_sip | (IPv6Address)hdr.u0_ipv4.src_addr, - 0xffffffffffffffffffffffff); - - set_tunnel(underlay_dip, - dash_encapsulation, - meter_class, - meter_class_override); - } - #ifdef TARGET_BMV2_V1MODEL direct_counter(CounterType.packets_and_bytes) ca_to_pa_counter; #endif // TARGET_BMV2_V1MODEL @@ -193,11 +64,11 @@ control outbound(inout headers_t hdr, } actions = { - set_tunnel_mapping; - set_private_link_mapping; - @defaultonly drop; + set_tunnel_mapping(hdr, meta); + set_private_link_mapping(hdr, meta); + @defaultonly drop(meta); } - const default_action = drop; + const default_action = drop(meta); #ifdef TARGET_BMV2_V1MODEL counters = ca_to_pa_counter; @@ -257,29 +128,8 @@ control outbound(inout headers_t hdr, vnet.apply(); } } - - tunnel_encap(hdr, - meta, - meta.encap_data.overlay_dmac, - meta.encap_data.underlay_dmac, - meta.encap_data.underlay_smac, - meta.encap_data.underlay_dip, - meta.encap_data.underlay_sip, - meta.encap_data.dash_encapsulation, - meta.encap_data.vni); - } - route_service_tunnel: { - tunnel_encap(hdr, - meta, - meta.encap_data.overlay_dmac, - meta.encap_data.underlay_dmac, - meta.encap_data.underlay_smac, - meta.encap_data.underlay_dip, - meta.encap_data.underlay_sip, - meta.encap_data.dash_encapsulation, - meta.encap_data.vni); - } - } + } + } } } diff --git a/dash-pipeline/bmv2/dash_pipeline.p4 b/dash-pipeline/bmv2/dash_pipeline.p4 index 50418b837..76c58158a 100644 --- a/dash-pipeline/bmv2/dash_pipeline.p4 +++ b/dash-pipeline/bmv2/dash_pipeline.p4 @@ -8,6 +8,7 @@ #include "dash_outbound.p4" #include "dash_inbound.p4" #include "dash_conntrack.p4" +#include "stages/routing_action_apply.p4" #include "underlay.p4" #define MAX_ENI 64 @@ -481,6 +482,8 @@ control dash_ingress( inbound.apply(hdr, meta); } + routing_action_apply.apply(hdr, meta); + /* Underlay routing */ meta.dst_ip_addr = (bit<128>)hdr.u0_ipv4.dst_addr; underlay.apply( diff --git a/dash-pipeline/bmv2/dash_routing_types.p4 b/dash-pipeline/bmv2/dash_routing_types.p4 new file mode 100644 index 000000000..7df952b47 --- /dev/null +++ b/dash-pipeline/bmv2/dash_routing_types.p4 @@ -0,0 +1,188 @@ +#ifndef _DASH_ROUTING_TYPES_P4_ +#define _DASH_ROUTING_TYPES_P4_ + +#include "dash_headers.p4" +#include "routing_actions/routing_actions.p4" + +action set_route_meter_attrs( + inout metadata_t meta, + bit<1> meter_policy_en, + bit<16> meter_class) +{ + meta.meter_policy_en = meter_policy_en; + meta.route_meter_class = meter_class; +} + +action set_mapping_meter_attr( + inout metadata_t meta, + in bit<16> meter_class, + in bit<1> meter_class_override) +{ + meta.mapping_meter_class = meter_class; + meta.mapping_meter_class_override = meter_class_override; +} + +// Routing Type - drop: +action drop(inout metadata_t meta) { + meta.dropped = true; +} + +// Routing Type - vnet: +// - Continue to look up in VNET mapping stage with the destination VNET ID. +// - No routing action will be populated in this routing type. +action route_vnet( + inout headers_t hdr, + inout metadata_t meta, + @SaiVal[type="sai_object_id_t"] bit<16> dst_vnet_id, + bit<1> meter_policy_en, + bit<16> meter_class) +{ + meta.dst_vnet_id = dst_vnet_id; + set_route_meter_attrs(meta, meter_policy_en, meter_class); +} + +// Routing Type - vnet_direct: +// - Forward with overrided destination overlay IP. +// - No routing action will be populated in this routing type. +action route_vnet_direct( + inout headers_t hdr, + inout metadata_t meta, + bit<16> dst_vnet_id, + bit<1> overlay_ip_is_v6, + @SaiVal[type="sai_ip_address_t"] + IPv4ORv6Address overlay_ip, + bit<1> meter_policy_en, + bit<16> meter_class) +{ + meta.dst_vnet_id = dst_vnet_id; + meta.lkup_dst_ip_addr = overlay_ip; + meta.is_lkup_dst_ip_v6 = overlay_ip_is_v6; + set_route_meter_attrs(meta, meter_policy_en, meter_class); +} + +// Routing Type - direct: +// - Send to underlay router without any encap +// - No routing action will be populated in this routing type. +action route_direct( + inout headers_t hdr, + inout metadata_t meta, + bit<1> meter_policy_en, + bit<16> meter_class) +{ + set_route_meter_attrs(meta, meter_policy_en, meter_class); +} + +// Routing Type - servicetunnel +// - Encap the packet with the given overlay and underlay addresses. +// - Perform 4-to-6 translation on the overlay addresses. +action route_service_tunnel( + inout headers_t hdr, + inout metadata_t meta, + bit<1> overlay_dip_is_v6, + IPv4ORv6Address overlay_dip, + bit<1> overlay_dip_mask_is_v6, + IPv4ORv6Address overlay_dip_mask, + bit<1> overlay_sip_is_v6, + IPv4ORv6Address overlay_sip, + bit<1> overlay_sip_mask_is_v6, + IPv4ORv6Address overlay_sip_mask, + bit<1> underlay_dip_is_v6, + IPv4ORv6Address underlay_dip, + bit<1> underlay_sip_is_v6, + IPv4ORv6Address underlay_sip, + @SaiVal[type="sai_dash_encapsulation_t", default_value="SAI_DASH_ENCAPSULATION_VXLAN"] + dash_encapsulation_t dash_encapsulation, + bit<24> tunnel_key, + bit<1> meter_policy_en, + bit<16> meter_class) +{ + /* Assume the overlay addresses provided are always IPv6 and the original are IPv4 */ + /* 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.encap_data.original_overlay_dip = hdr.u0_ipv4.src_addr; + meta.encap_data.original_overlay_sip = hdr.u0_ipv4.dst_addr; + + push_action_nat46(hdr = hdr, + meta = meta, + sip = overlay_sip, + sip_mask = overlay_sip_mask, + dip = overlay_dip, + dip_mask = overlay_dip_mask); + +#ifndef DISABLE_128BIT_ARITHMETIC + // As of 2024-Feb-09, p4c-dpdk does not yet support arithmetic on 128-bit operands. + // This lack of support extends to cast operations. + push_action_static_encap(hdr = hdr, + meta = meta, + encap = dash_encapsulation, + vni = tunnel_key, + underlay_sip = underlay_sip == 0 ? meta.encap_data.original_overlay_sip : (IPv4Address)underlay_sip, + underlay_dip = underlay_dip == 0 ? meta.encap_data.original_overlay_dip : (IPv4Address)underlay_dip, + overlay_dmac = hdr.u0_ethernet.dst_addr); + +#endif + + set_route_meter_attrs(meta, meter_policy_en, meter_class); +} + +// Routing type - vnet_encap: +action set_tunnel_mapping( + inout headers_t hdr, + inout metadata_t meta, + @SaiVal[type="sai_ip_address_t"] IPv4Address underlay_dip, + EthernetAddress overlay_dmac, + bit<1> use_dst_vnet_vni, + bit<16> meter_class, + bit<1> meter_class_override) +{ + if (use_dst_vnet_vni == 1) + meta.vnet_id = meta.dst_vnet_id; + + push_action_static_encap(hdr = hdr, + meta = meta, + underlay_dip = underlay_dip, + overlay_dmac = overlay_dmac); + + set_mapping_meter_attr(meta, meter_class, meter_class_override); +} + +// Routing type - privatelink: +action set_private_link_mapping( + inout headers_t hdr, + inout metadata_t meta, + @SaiVal[type="sai_ip_address_t"] IPv4Address underlay_dip, + IPv6Address overlay_sip, + IPv6Address overlay_dip, + @SaiVal[type="sai_dash_encapsulation_t"] dash_encapsulation_t dash_encapsulation, + bit<24> tunnel_key, + bit<16> meter_class, + bit<1> meter_class_override) +{ + push_action_static_encap(hdr = hdr, + meta = meta, + encap = dash_encapsulation, + vni = tunnel_key, + // PL has its own underlay SIP, so override + underlay_sip = meta.eni_data.pl_underlay_sip, + underlay_dip = underlay_dip, + overlay_dmac = hdr.u0_ethernet.dst_addr); + +#ifndef DISABLE_128BIT_ARITHMETIC + // As of 2024-Feb-09, p4c-dpdk does not yet support arithmetic on + // 128-bit operands. + // + // Hence passing IPv6 addresses as arguments is not supported due to error below: + // error: DPDK target supports up-to 64-bit immediate values, 128w0xffffffffffffffffffffffff exceeds the limit. + push_action_nat46(hdr = hdr, + meta = meta, + dip = overlay_dip, + dip_mask = 0xffffffffffffffffffffffff, + sip = (overlay_sip & ~meta.eni_data.pl_sip_mask) | meta.eni_data.pl_sip | (IPv6Address)hdr.u0_ipv4.src_addr, + sip_mask = 0xffffffffffffffffffffffff); +#endif /* DISABLE_128BIT_ARITHMETIC */ + + set_mapping_meter_attr(meta, meter_class, meter_class_override); +} + +#endif /* _DASH_ROUTING_TYPES_P4_ */ \ No newline at end of file diff --git a/dash-pipeline/bmv2/routing_actions/routing_action_nat46.p4 b/dash-pipeline/bmv2/routing_actions/routing_action_nat46.p4 new file mode 100644 index 000000000..06948c45a --- /dev/null +++ b/dash-pipeline/bmv2/routing_actions/routing_action_nat46.p4 @@ -0,0 +1,51 @@ +#ifndef _DASH_ROUTING_ACTION_NAT46_P4_ +#define _DASH_ROUTING_ACTION_NAT46_P4_ + +action push_action_nat46( + in headers_t hdr, + inout metadata_t meta, + in IPv6Address sip, + in IPv6Address sip_mask, + in IPv6Address dip, + in IPv6Address dip_mask) +{ + meta.routing_actions = meta.routing_actions | dash_routing_actions_t.NAT46; + + meta.overlay_data.is_ipv6 = true; + meta.overlay_data.sip = sip; + meta.overlay_data.sip_mask = sip_mask; + meta.overlay_data.dip = dip; + meta.overlay_data.dip_mask = dip_mask; +} + +control do_action_nat46( + inout headers_t hdr, + in metadata_t meta) +{ + apply { + if (meta.routing_actions & dash_routing_actions_t.NAT46 == 0) { + return; + } + + REQUIRES(meta.overlay_data.is_ipv6 == true); + + hdr.u0_ipv6.setValid(); + hdr.u0_ipv6.version = 6; + hdr.u0_ipv6.traffic_class = 0; + hdr.u0_ipv6.flow_label = 0; + hdr.u0_ipv6.payload_length = hdr.u0_ipv4.total_len - IPV4_HDR_SIZE; + hdr.u0_ipv6.next_header = hdr.u0_ipv4.protocol; + hdr.u0_ipv6.hop_limit = hdr.u0_ipv4.ttl; +#ifndef DISABLE_128BIT_ARITHMETIC + // As of 2024-Feb-09, p4c-dpdk does not yet support arithmetic on + // 128-bit operands. + hdr.u0_ipv6.dst_addr = ((IPv6Address)hdr.u0_ipv4.dst_addr & ~meta.overlay_data.dip_mask) | (meta.overlay_data.dip & meta.overlay_data.dip_mask); + hdr.u0_ipv6.src_addr = ((IPv6Address)hdr.u0_ipv4.src_addr & ~meta.overlay_data.sip_mask) | (meta.overlay_data.sip & meta.overlay_data.sip_mask); +#endif + + hdr.u0_ipv4.setInvalid(); + hdr.u0_ethernet.ether_type = IPV6_ETHTYPE; + } +} + +#endif /* _DASH_ROUTING_ACTION_NAT46_P4_ */ \ No newline at end of file diff --git a/dash-pipeline/bmv2/routing_actions/routing_action_nat64.p4 b/dash-pipeline/bmv2/routing_actions/routing_action_nat64.p4 new file mode 100644 index 000000000..1f3bebab7 --- /dev/null +++ b/dash-pipeline/bmv2/routing_actions/routing_action_nat64.p4 @@ -0,0 +1,47 @@ +#ifndef _DASH_ROUTING_ACTION_NAT64_P4_ +#define _DASH_ROUTING_ACTION_NAT64_P4_ + +action push_action_nat64( + in headers_t hdr, + inout metadata_t meta, + in IPv4Address src, + in IPv4Address dst) +{ + meta.routing_actions = meta.routing_actions | dash_routing_actions_t.NAT64; + + meta.overlay_data.is_ipv6 = false; + meta.overlay_data.sip = (IPv4ORv6Address)src; + meta.overlay_data.dip = (IPv4ORv6Address)dst; +} + +control do_action_nat64( + inout headers_t hdr, + in metadata_t meta) +{ + apply { + if (meta.routing_actions & dash_routing_actions_t.NAT64 == 0) { + return; + } + + REQUIRES(meta.overlay_data.is_ipv6 == false); + + hdr.u0_ipv4.setValid(); + hdr.u0_ipv4.version = 4; + hdr.u0_ipv4.ihl = 5; + hdr.u0_ipv4.diffserv = 0; + hdr.u0_ipv4.total_len = hdr.u0_ipv6.payload_length + IPV4_HDR_SIZE; + hdr.u0_ipv4.identification = 1; + hdr.u0_ipv4.flags = 0; + hdr.u0_ipv4.frag_offset = 0; + hdr.u0_ipv4.protocol = hdr.u0_ipv6.next_header; + hdr.u0_ipv4.ttl = hdr.u0_ipv6.hop_limit; + hdr.u0_ipv4.hdr_checksum = 0; + hdr.u0_ipv4.dst_addr = (IPv4Address)meta.overlay_data.dip; + hdr.u0_ipv4.src_addr = (IPv4Address)meta.overlay_data.sip; + + hdr.u0_ipv6.setInvalid(); + hdr.u0_ethernet.ether_type = IPV4_ETHTYPE; + } +} + +#endif /* _DASH_ROUTING_ACTION_NAT64_P4_ */ \ No newline at end of file diff --git a/dash-pipeline/bmv2/routing_actions/routing_action_static_encap.p4 b/dash-pipeline/bmv2/routing_actions/routing_action_static_encap.p4 new file mode 100644 index 000000000..275ec2491 --- /dev/null +++ b/dash-pipeline/bmv2/routing_actions/routing_action_static_encap.p4 @@ -0,0 +1,80 @@ +#ifndef _DASH_ROUTING_ACTION_STATIC_ENCAP_P4_ +#define _DASH_ROUTING_ACTION_STATIC_ENCAP_P4_ + +action push_action_static_encap( + in headers_t hdr, + inout metadata_t meta, + in dash_encapsulation_t encap = dash_encapsulation_t.VXLAN, + in bit<24> vni = 0, + in IPv4Address underlay_sip = 0, + in IPv4Address underlay_dip = 0, + in EthernetAddress underlay_smac = 0, + in EthernetAddress underlay_dmac = 0, + in EthernetAddress overlay_dmac = 0) +{ + meta.routing_actions = meta.routing_actions | dash_routing_actions_t.STATIC_ENCAP; + + meta.encap_data.dash_encapsulation = encap; + meta.encap_data.vni = vni == 0 ? meta.encap_data.vni : vni; + + meta.encap_data.underlay_smac = underlay_smac == 0 ? meta.encap_data.underlay_smac : underlay_smac; + meta.encap_data.underlay_dmac = underlay_dmac == 0 ? meta.encap_data.underlay_dmac : underlay_dmac; + meta.encap_data.underlay_sip = underlay_sip == 0 ? meta.encap_data.underlay_sip : underlay_sip; + meta.encap_data.underlay_dip = underlay_dip == 0 ? meta.encap_data.underlay_dip : underlay_dip; + + meta.overlay_data.dmac = overlay_dmac == 0 ? meta.overlay_data.dmac : overlay_dmac; +} + +control do_action_static_encap( + inout headers_t hdr, + inout metadata_t meta) +{ + apply { + if (meta.routing_actions & dash_routing_actions_t.STATIC_ENCAP == 0) { + return; + } + + if (meta.encap_data.dash_encapsulation == dash_encapsulation_t.VXLAN) { + if (meta.tunnel_pointer == 0) { + push_vxlan_tunnel_u0(hdr, + meta.overlay_data.dmac, + meta.encap_data.underlay_dmac, + meta.encap_data.underlay_smac, + meta.encap_data.underlay_dip, + meta.encap_data.underlay_sip, + meta.encap_data.vni); + } else if (meta.tunnel_pointer == 1) { + push_vxlan_tunnel_u1(hdr, + meta.overlay_data.dmac, + meta.encap_data.underlay_dmac, + meta.encap_data.underlay_smac, + meta.encap_data.underlay_dip, + meta.encap_data.underlay_sip, + meta.encap_data.vni); + } + } + else if (meta.encap_data.dash_encapsulation == dash_encapsulation_t.NVGRE) { + if (meta.tunnel_pointer == 0) { + push_vxlan_tunnel_u0(hdr, + meta.overlay_data.dmac, + meta.encap_data.underlay_dmac, + meta.encap_data.underlay_smac, + meta.encap_data.underlay_dip, + meta.encap_data.underlay_sip, + meta.encap_data.vni); + } else if (meta.tunnel_pointer == 1) { + push_vxlan_tunnel_u1(hdr, + meta.overlay_data.dmac, + meta.encap_data.underlay_dmac, + meta.encap_data.underlay_smac, + meta.encap_data.underlay_dip, + meta.encap_data.underlay_sip, + meta.encap_data.vni); + } + } + + meta.tunnel_pointer = meta.tunnel_pointer + 1; + } +} + +#endif /* _DASH_ROUTING_ACTION_STATIC_ENCAP_P4_ */ \ No newline at end of file diff --git a/dash-pipeline/bmv2/routing_actions/routing_actions.p4 b/dash-pipeline/bmv2/routing_actions/routing_actions.p4 new file mode 100644 index 000000000..3dbaa49c8 --- /dev/null +++ b/dash-pipeline/bmv2/routing_actions/routing_actions.p4 @@ -0,0 +1,8 @@ +#ifndef _DASH_ROUTING_ACTIONS_P4_ +#define _DASH_ROUTING_ACTIONS_P4_ + +#include "routing_action_static_encap.p4" +#include "routing_action_nat46.p4" +#include "routing_action_nat64.p4" + +#endif /* _DASH_ROUTING_ACTIONS_P4_ */ \ No newline at end of file diff --git a/dash-pipeline/bmv2/stages/routing_action_apply.p4 b/dash-pipeline/bmv2/stages/routing_action_apply.p4 new file mode 100644 index 000000000..2db38fc49 --- /dev/null +++ b/dash-pipeline/bmv2/stages/routing_action_apply.p4 @@ -0,0 +1,21 @@ +#ifndef _DASH_STAGE_ACTION_APPLY_P4_ +#define _DASH_STAGE_ACTION_APPLY_P4_ + +#include "../routing_actions/routing_actions.p4" + +control routing_action_apply( + inout headers_t hdr, + inout metadata_t meta) +{ + apply { + do_action_nat46.apply(hdr, meta); + do_action_nat64.apply(hdr, meta); + + // Encaps needs to be added after all other transforms, from inner ones to outer ones, + // because it requires the transforms on the inner packet to be finished in order to + // get the correct inner packet size and other informations. + do_action_static_encap.apply(hdr, meta); + } +} + +#endif /* _DASH_STAGE_ACTION_APPLY_P4_ */ \ No newline at end of file From 7070b515b37e9e2400fbe60a76a1e1b25cf585dd Mon Sep 17 00:00:00 2001 From: Riff Date: Tue, 27 Feb 2024 20:43:10 -0800 Subject: [PATCH 03/32] [dash-p4] Create macro for defining direct counters. (#523) This is to simplify the code for creating and attaching the direct counters. No SAI updates will be introduced with this change. --- dash-pipeline/bmv2/dash_arch_specific.p4 | 24 +++++++++++++++- dash-pipeline/bmv2/dash_outbound.p4 | 36 +++--------------------- dash-pipeline/bmv2/dash_pipeline.p4 | 28 ++---------------- 3 files changed, 29 insertions(+), 59 deletions(-) diff --git a/dash-pipeline/bmv2/dash_arch_specific.p4 b/dash-pipeline/bmv2/dash_arch_specific.p4 index 5127c0498..30a293b68 100644 --- a/dash-pipeline/bmv2/dash_arch_specific.p4 +++ b/dash-pipeline/bmv2/dash_arch_specific.p4 @@ -4,6 +4,10 @@ #ifdef TARGET_BMV2_V1MODEL #include + +// Counters +#define DEFINE_TABLE_COUNTER(counter_name) direct_counter(CounterType.packets_and_bytes) counter_name; +#define ATTACH_TABLE_COUNTER(counter_name) counters = counter_name; #define DIRECT_COUNTER_TABLE_PROPERTY counters // DBC (Design By Contract) macros @@ -14,7 +18,25 @@ #ifdef TARGET_DPDK_PNA #include -#define DIRECT_COUNTER_TABLE_PROPERTY pna_direct_counter + +// Counters +#ifdef DPDK_SUPPORTS_DIRECT_COUNTER_ON_WILDCARD_KEY_TABLE + // Omit all direct counters for tables with ternary match keys, + // because the latest version of p4c-dpdk as of 2023-Jan-26 does + // not support this combination of features. If you try to + // compile it with this code enabled, the error message looks like + // this: + // + // [--Werror=target-error] error: Direct counters and direct meters are unsupported for wildcard match table outbound_acl_stage1:dash_acl_rule|dash_acl + // + // This p4c issue is tracking this feature gap in p4c-dpdk: + // https://github.com/p4lang/p4c/issues/3868 + #define DEFINE_TABLE_COUNTER(counter_name) DirectCounter>(PNA_CounterType_t.PACKETS_AND_BYTES) counter_name; + #define ATTACH_TABLE_COUNTER(counter_name) pna_direct_counter = counter_name; +#else + #define DEFINE_TABLE_COUNTER(counter_name) + #define ATTACH_TABLE_COUNTER(counter_name) +#endif // DBC (Design By Contract) macros // NOTE: PNA doesn't support assert, hence all macros are defined as empty diff --git a/dash-pipeline/bmv2/dash_outbound.p4 b/dash-pipeline/bmv2/dash_outbound.p4 index fdbcd1308..4a4de8cea 100644 --- a/dash-pipeline/bmv2/dash_outbound.p4 +++ b/dash-pipeline/bmv2/dash_outbound.p4 @@ -9,14 +9,7 @@ control outbound(inout headers_t hdr, inout metadata_t meta) { -#ifdef TARGET_BMV2_V1MODEL - direct_counter(CounterType.packets_and_bytes) routing_counter; -#elif TARGET_DPDK_PNA // TARGET_BMV2_V1MODEL -#ifdef DPDK_SUPPORTS_DIRECT_COUNTER_ON_WILDCARD_KEY_TABLE - // See the #ifdef with same preprocessor symbol in dash_pipeline.p4 - DirectCounter>(PNA_CounterType_t.PACKETS_AND_BYTES) routing_counter; -#endif // DPDK_SUPPORTS_DIRECT_COUNTER_ON_WILDCARD_KEY_TABLE -#endif // TARGET_DPDK_PNA + DEFINE_TABLE_COUNTER(routing_counter) @SaiTable[name = "outbound_routing", api = "dash_outbound_routing"] table routing { @@ -35,24 +28,10 @@ control outbound(inout headers_t hdr, } const default_action = drop(meta); -#ifdef TARGET_BMV2_V1MODEL - counters = routing_counter; -#endif // TARGET_BMV2_V1MODEL -#ifdef TARGET_DPDK_PNA -#ifdef DPDK_SUPPORTS_DIRECT_COUNTER_ON_WILDCARD_KEY_TABLE - pna_direct_counter = routing_counter; -#endif // DPDK_SUPPORTS_DIRECT_COUNTER_ON_WILDCARD_KEY_TABLE -#endif // TARGET_DPDK_PNA + ATTACH_TABLE_COUNTER(routing_counter) } -#ifdef TARGET_BMV2_V1MODEL - direct_counter(CounterType.packets_and_bytes) ca_to_pa_counter; -#endif // TARGET_BMV2_V1MODEL -#ifdef TARGET_DPDK_PNA -#ifdef DPDK_SUPPORTS_DIRECT_COUNTER_ON_WILDCARD_KEY_TABLE - DirectCounter>(PNA_CounterType_t.PACKETS_AND_BYTES) ca_to_pa_counter; -#endif // DPDK_SUPPORTS_DIRECT_COUNTER_ON_WILDCARD_KEY_TABLE -#endif // TARGET_DPDK_PNA + DEFINE_TABLE_COUNTER(ca_to_pa_counter) @SaiTable[name = "outbound_ca_to_pa", api = "dash_outbound_ca_to_pa"] table ca_to_pa { @@ -70,14 +49,7 @@ control outbound(inout headers_t hdr, } const default_action = drop(meta); -#ifdef TARGET_BMV2_V1MODEL - counters = ca_to_pa_counter; -#endif // TARGET_BMV2_V1MODEL -#ifdef TARGET_DPDK_PNA -#ifdef DPDK_SUPPORTS_DIRECT_COUNTER_ON_WILDCARD_KEY_TABLE - pna_direct_counter = ca_to_pa_counter; -#endif // DPDK_SUPPORTS_DIRECT_COUNTER_ON_WILDCARD_KEY_TABLE -#endif // TARGET_DPDK_PNA + ATTACH_TABLE_COUNTER(ca_to_pa_counter) } action set_vnet_attrs(bit<24> vni) { diff --git a/dash-pipeline/bmv2/dash_pipeline.p4 b/dash-pipeline/bmv2/dash_pipeline.p4 index 76c58158a..c7b77af0f 100644 --- a/dash-pipeline/bmv2/dash_pipeline.p4 +++ b/dash-pipeline/bmv2/dash_pipeline.p4 @@ -188,24 +188,7 @@ control dash_ingress( const default_action = deny; } -#ifdef TARGET_BMV2_V1MODEL - direct_counter(CounterType.packets_and_bytes) eni_counter; -#endif // TARGET_BMV2_V1MODEL -#ifdef TARGET_DPDK_PNA -#ifdef DPDK_SUPPORTS_DIRECT_COUNTER_ON_WILDCARD_KEY_TABLE - // Omit all direct counters for tables with ternary match keys, - // because the latest version of p4c-dpdk as of 2023-Jan-26 does - // not support this combination of features. If you try to - // compile it with this code enabled, the error message looks like - // this: - // - // [--Werror=target-error] error: Direct counters and direct meters are unsupported for wildcard match table outbound_acl_stage1:dash_acl_rule|dash_acl - // - // This p4c issue is tracking this feature gap in p4c-dpdk: - // https://github.com/p4lang/p4c/issues/3868 - DirectCounter>(PNA_CounterType_t.PACKETS_AND_BYTES) eni_counter; -#endif // DPDK_SUPPORTS_DIRECT_COUNTER_ON_WILDCARD_KEY_TABLE -#endif // TARGET_DPDK_PNA + DEFINE_TABLE_COUNTER(eni_counter) @SaiTable[ignored = "true"] table eni_meter { @@ -217,14 +200,7 @@ control dash_ingress( actions = { NoAction; } -#ifdef TARGET_BMV2_V1MODEL - counters = eni_counter; -#endif // TARGET_BMV2_V1MODEL -#ifdef TARGET_DPDK_PNA -#ifdef DPDK_SUPPORTS_DIRECT_COUNTER_ON_WILDCARD_KEY_TABLE - pna_direct_counter = eni_counter; -#endif // DPDK_SUPPORTS_DIRECT_COUNTER_ON_WILDCARD_KEY_TABLE -#endif // TARGET_DPDK_PNA + ATTACH_TABLE_COUNTER(eni_counter) } action permit() { From 82a3145cec87485e73a6be19503adc24c359aab2 Mon Sep 17 00:00:00 2001 From: Kamil Cudnik Date: Wed, 28 Feb 2024 18:14:11 +0100 Subject: [PATCH 04/32] [SAI] Add dummy buffer and dtel api (#525) Needed to return dummy success object to for new dash-app --- dash-pipeline/SAI/src/sai_dash_buffer.cpp | 22 ++++++++++++++++++++++ dash-pipeline/SAI/src/sai_dash_dtel.cpp | 16 ++++++++++++++++ dash-pipeline/SAI/templates/saiimpl.h.j2 | 2 ++ 3 files changed, 40 insertions(+) create mode 100644 dash-pipeline/SAI/src/sai_dash_buffer.cpp create mode 100644 dash-pipeline/SAI/src/sai_dash_dtel.cpp diff --git a/dash-pipeline/SAI/src/sai_dash_buffer.cpp b/dash-pipeline/SAI/src/sai_dash_buffer.cpp new file mode 100644 index 000000000..5d0b8ae7a --- /dev/null +++ b/dash-pipeline/SAI/src/sai_dash_buffer.cpp @@ -0,0 +1,22 @@ +#include "saiimpl.h" + +DASH_GENERIC_QUAD(BUFFER_POOL,buffer_pool); +DASH_GENERIC_QUAD(INGRESS_PRIORITY_GROUP,ingress_priority_group); +DASH_GENERIC_QUAD(BUFFER_PROFILE,buffer_profile); + +sai_buffer_api_t redis_buffer_api = { + + DASH_GENERIC_QUAD_API(buffer_pool) + + .get_buffer_pool_stats = 0, + .get_buffer_pool_stats_ext = 0, + .clear_buffer_pool_stats = 0, + + DASH_GENERIC_QUAD_API(ingress_priority_group) + + .get_ingress_priority_group_stats = 0, + .get_ingress_priority_group_stats_ext = 0, + .clear_ingress_priority_group_stats = 0, + + DASH_GENERIC_QUAD_API(buffer_profile) +}; diff --git a/dash-pipeline/SAI/src/sai_dash_dtel.cpp b/dash-pipeline/SAI/src/sai_dash_dtel.cpp new file mode 100644 index 000000000..49be60116 --- /dev/null +++ b/dash-pipeline/SAI/src/sai_dash_dtel.cpp @@ -0,0 +1,16 @@ +#include "saiimpl.h" + +DASH_GENERIC_QUAD(DTEL,dtel); +DASH_GENERIC_QUAD(DTEL_QUEUE_REPORT,dtel_queue_report); +DASH_GENERIC_QUAD(DTEL_INT_SESSION,dtel_int_session); +DASH_GENERIC_QUAD(DTEL_REPORT_SESSION,dtel_report_session); +DASH_GENERIC_QUAD(DTEL_EVENT,dtel_event); + +sai_dtel_api_t dash_sai_dtel_api = { + + DASH_GENERIC_QUAD_API(dtel) + DASH_GENERIC_QUAD_API(dtel_queue_report) + DASH_GENERIC_QUAD_API(dtel_int_session) + DASH_GENERIC_QUAD_API(dtel_report_session) + DASH_GENERIC_QUAD_API(dtel_event) +}; diff --git a/dash-pipeline/SAI/templates/saiimpl.h.j2 b/dash-pipeline/SAI/templates/saiimpl.h.j2 index 052a0a3ac..133bda777 100644 --- a/dash-pipeline/SAI/templates/saiimpl.h.j2 +++ b/dash-pipeline/SAI/templates/saiimpl.h.j2 @@ -11,6 +11,8 @@ DASH_PRIVATE extern sai_policer_api_t dash_sai_policer_api_impl; DASH_PRIVATE extern sai_port_api_t dash_sai_port_api_impl; DASH_PRIVATE extern sai_router_interface_api_t dash_sai_router_interface_api_impl; DASH_PRIVATE extern sai_switch_api_t dash_sai_switch_api_impl; +DASH_PRIVATE extern sai_dtel_api_t dash_sai_dtel_api; +DASH_PRIVATE extern sai_buffer_api_t dash_sai_buffer_api; {% for api in api_names %} DASH_PRIVATE extern sai_{{ api }}_api_t dash_sai_{{ api }}_api_impl; From 477ce2dc016203337e8ada227e1dab94dc71bca7 Mon Sep 17 00:00:00 2001 From: Prince Sunny Date: Wed, 28 Feb 2024 11:42:10 -0800 Subject: [PATCH 05/32] [Dash-Sonic] Introduce route group, pa validation tables (#520) 1. Add Route group table for grouping routes and binding to an ENI 2. Introduce PA validation table for special validation for certain scenarios --- documentation/general/dash-sonic-hld.md | 100 ++++++++++++++++++++---- 1 file changed, 85 insertions(+), 15 deletions(-) diff --git a/documentation/general/dash-sonic-hld.md b/documentation/general/dash-sonic-hld.md index 40a5f6482..0033517c9 100644 --- a/documentation/general/dash-sonic-hld.md +++ b/documentation/general/dash-sonic-hld.md @@ -1,6 +1,6 @@ # SONiC-DASH HLD ## High Level Design Document -### Rev 1.6 +### Rev 1.7 # Table of Contents @@ -47,6 +47,7 @@ | 1.4 | 05/03/2023 | Prince Sunny | ACL Tagging, ACL Requirements | | 1.5 | 05/22/2023 | Oleksandr Ivantsiv | Update configuration examples | | 1.6 | 06/01/2023 | Prince Sunny | Added FastPath | +| 1.7 | 02/20/2024 | Prince Sunny | Introduce Route Group Table | # About this Manual This document provides more detailed design of DASH APIs, DASH orchestration agent, Config and APP DB Schemas and other SONiC buildimage changes required to bring up SONiC image on an appliance card. General DASH HLD can be found at [dash_hld](./dash-high-level-design.md). @@ -494,8 +495,25 @@ vm_vni = VM VNI that is used for setting direction. Also used ### 3.2.9 ROUTE LPM TABLE - OUTBOUND +``` +DASH_ENI_ROUTE_TABLE:{{eni}} + "group_id": {{group_id}} +``` + +``` +key = DASH_ENI_ROUTE_TABLE:eni ; ENI name as key; ENI can bind to a route group table atomically (Overwrites any old bindings) +; field = value +group_id = Route Group Table Id (contains both IPv4 and IPv6 routes) +``` + +``` +DASH_ROUTE_GROUP_TABLE:{{group_id}} + "guid": {{string}} + "version": {{string}} +``` + ``` -DASH_ROUTE_TABLE:{{eni}}:{{prefix}} +DASH_ROUTE_TABLE:{{group_id}}:{{prefix}} "action_type": {{routing_type}} "vnet":{{vnet_name}} (OPTIONAL) "appliance":{{appliance_id}} (OPTIONAL) @@ -509,7 +527,7 @@ DASH_ROUTE_TABLE:{{eni}}:{{prefix}} ``` ``` -key = DASH_ROUTE_TABLE:eni:prefix ; ENI route table with CA prefix for packet Outbound +key = DASH_ROUTE_TABLE:group_id:prefix ; Route route table with CA prefix for packet Outbound ; field = value action_type = routing_type ; reference to routing type vnet = vnet name ; destination vnet name if routing_type is {vnet, vnet_direct}, a vnet other than eni's vnet means vnet peering @@ -622,7 +640,20 @@ tx_counter = uint64 ; Number of transmitted bytes (read-only) rx_counter = uint64 ; Number of received bytes (read-only) ``` -### 3.2.13 DASH orchagent (Overlay) +### 3.2.13 Underlay SRC IP (PA) Validation + +``` +DASH_PA_VALIDATION_TABLE:{{vni}} + "addresses": {{list of underlay addresses}} +``` + +``` +key = DASH_PA_VALIDATION_TABLE:vni; ENI and VNI as key; +; field = value +addresses = list of addresses used for validating underlay source ip of incoming packets. +``` + +### 3.2.14 DASH orchagent (Overlay) | APP_DB Table | Key | Field | SAI Attributes/*objects* | Comment | | --------------------- | ------------ | --------------- | ----------------------------------------------- | --------------------------------------------- | @@ -700,7 +731,7 @@ rx_counter = uint64 ; Number of received bytes (read-only) | | | pa_validation | SAI_INBOUND_ROUTING_ENTRY_ATTR_ACTION | use PA_VALIDATE if true | | | | metering_bucket | | | -### 3.2.14 Protobuf encoding +### 3.2.15 Protobuf encoding For saving memory consumption([AppDBMemoryEstimation.xlsx](data/AppDBMemoryEstimation.xlsx)), the DASH table of APP_DB could be encoded as protobuf. @@ -1013,7 +1044,20 @@ Refer DASH documentation for the test plan. "OP": "SET" }, { - "DASH_ROUTE_TABLE:F4939FEFC47E:10.1.0.0/16": { + "DASH_ENI_ROUTE_TABLE:F4939FEFC47E": { + "group_id":"group_id_1" + }, + "OP": "SET" + }, + { + "DASH_ROUTE_GROUP_TABLE:group_id_1": { + "guid":"group_id_1-test", + "version":"1" + }, + "OP": "SET" + }, + { + "DASH_ROUTE_TABLE:group_id_1:10.1.0.0/16": { "prefix":"10.1.0.0/16", "action_type":"vnet", "vnet":"Vnet1" @@ -1021,7 +1065,7 @@ Refer DASH documentation for the test plan. "OP": "SET" }, { - "DASH_ROUTE_TABLE:F4939FEFC47E:10.1.0.0/24": { + "DASH_ROUTE_TABLE:group_id_1:10.1.0.0/24": { "action_type":"vnet_direct", "vnet":"Vnet1", "overlay_ip":"10.0.0.6" @@ -1029,7 +1073,7 @@ Refer DASH documentation for the test plan. "OP": "SET" }, { - "DASH_ROUTE_TABLE:F4939FEFC47E:30.0.0.0/16": { + "DASH_ROUTE_TABLE:group_id_1:30.0.0.0/16": { "action_type":"direct", "metering_policy_en":"false", "metering_class":"1000" @@ -1037,7 +1081,7 @@ Refer DASH documentation for the test plan. "OP": "SET" }, { - "DASH_ROUTE_TABLE:F4939FEFC47E:40.0.0.0/16": { + "DASH_ROUTE_TABLE:group_id_1:40.0.0.0/16": { "action_type":"direct", "metering_policy_en":"true", "metering_class":"1000" @@ -1045,7 +1089,7 @@ Refer DASH documentation for the test plan. "OP": "SET" }, { - "DASH_ROUTE_TABLE:F4939FEFC47E:10.2.5.0/24": { + "DASH_ROUTE_TABLE:group_id_1:10.2.5.0/24": { "action_type":"drop" }, "OP": "SET" @@ -1213,7 +1257,20 @@ For the inbound direction, after Route/ACL lookup, pipeline shall use the "under "OP": "SET" }, { - "DASH_ROUTE_TABLE:F4939FEFC47E:50.1.2.0/24": { + "DASH_ENI_ROUTE_TABLE:F4939FEFC47E": { + "group_id":"group_id_2" + }, + "OP": "SET" + }, + { + "DASH_ROUTE_GROUP_TABLE:group_id_2": { + "guid":"group_id_2-test", + "version":"1.1" + }, + "OP": "SET" + }, + { + "DASH_ROUTE_TABLE:group_id_2:50.1.2.0/24": { "action_type":"servicetunnel", "overlay_sip":"fd00:108:0:d204:0:200::0", "overlay_dip":"2603:10e1:100:2::0", @@ -1224,7 +1281,7 @@ For the inbound direction, after Route/ACL lookup, pipeline shall use the "under "OP": "SET" }, { - "DASH_ROUTE_TABLE:F4939FEFC47E:60.1.2.1/32": { + "DASH_ROUTE_TABLE:group_id_2:60.1.2.1/32": { "action_type":"servicetunnel", "overlay_sip":"fd00:108:0:d204:0:200::0", "overlay_dip":"2603:10e1:100:2::0", @@ -1234,7 +1291,7 @@ For the inbound direction, after Route/ACL lookup, pipeline shall use the "under "OP": "SET" }, { - "DASH_ROUTE_TABLE:F4939FEFC47E:70.1.2.0/24": { + "DASH_ROUTE_TABLE:group_id_2:70.1.2.0/24": { "action_type":"servicetunnel", "overlay_sip":"fd00:108:0:d204:0:200::0", "overlay_dip":"2603:10e1:100:2::4601:203", @@ -1349,7 +1406,20 @@ For the example configuration above, the following is a brief explanation of loo "OP": "SET" }, { - "DASH_ROUTE_TABLE:F4939FEFC47E:10.1.0.8/32": { + "DASH_ENI_ROUTE_TABLE:F4939FEFC47E": { + "group_id":"group_id_3" + }, + "OP": "SET" + }, + { + "DASH_ROUTE_GROUP_TABLE:group_id_3": { + "guid":"group_id_3-test", + "version":"1" + }, + "OP": "SET" + }, + { + "DASH_ROUTE_TABLE:group_id_3:10.1.0.8/32": { "action_type":"vnet", "vnet":"Vnet1", "metering_policy_en":"false", @@ -1370,7 +1440,7 @@ For the example configuration above, the following is a brief explanation of loo "OP": "SET" }, { - "DASH_ROUTE_TABLE:F4939FEFC47E:10.2.0.6/24": { + "DASH_ROUTE_TABLE:group_id_3:10.2.0.6/24": { "action_type":"vnet", "vnet":"Vnet1" }, From 1d1c89dffb99c27f4cdd9e72fa2f9d76c3d8dc8c Mon Sep 17 00:00:00 2001 From: Riff Date: Wed, 28 Feb 2024 13:58:33 -0800 Subject: [PATCH 06/32] [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 From 57daf3170977dcb6d2a1a62a8812bed6350ae3cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Br=C3=B8ms=C3=B8?= Date: Fri, 1 Mar 2024 18:17:11 +0100 Subject: [PATCH 07/32] Bumped GitHub spellcheck action to latest version: 0.35.0 (#476) --- .github/workflows/dash-md-spellcheck.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/dash-md-spellcheck.yml b/.github/workflows/dash-md-spellcheck.yml index 9b73265f8..a583d5a21 100644 --- a/.github/workflows/dash-md-spellcheck.yml +++ b/.github/workflows/dash-md-spellcheck.yml @@ -16,4 +16,4 @@ jobs: steps: - uses: actions/checkout@master - name: Spellcheck - uses: rojopolis/spellcheck-github-actions@0.26.0 + uses: rojopolis/spellcheck-github-actions@0.35.0 From c5f713f03c435438564102ac2941273486fdf67d Mon Sep 17 00:00:00 2001 From: Riff Date: Fri, 1 Mar 2024 09:26:17 -0800 Subject: [PATCH 08/32] [dash-p4] Modularize direction lookup, eni lookup and metering update stages. (#528) * Extract metering update stage into dedicated file. * Extract direction lookup stage and eni lookup stage. * Move VIP miss counters to TODO. --- dash-pipeline/bmv2/dash_pipeline.p4 | 179 +----------------- dash-pipeline/bmv2/stages/direction_lookup.p4 | 36 ++++ dash-pipeline/bmv2/stages/eni_lookup.p4 | 50 +++++ dash-pipeline/bmv2/stages/metering_update.p4 | 120 ++++++++++++ 4 files changed, 216 insertions(+), 169 deletions(-) create mode 100644 dash-pipeline/bmv2/stages/direction_lookup.p4 create mode 100644 dash-pipeline/bmv2/stages/eni_lookup.p4 create mode 100644 dash-pipeline/bmv2/stages/metering_update.p4 diff --git a/dash-pipeline/bmv2/dash_pipeline.p4 b/dash-pipeline/bmv2/dash_pipeline.p4 index ad0917861..47ee55b74 100644 --- a/dash-pipeline/bmv2/dash_pipeline.p4 +++ b/dash-pipeline/bmv2/dash_pipeline.p4 @@ -8,7 +8,10 @@ #include "dash_outbound.p4" #include "dash_inbound.p4" #include "dash_conntrack.p4" +#include "stages/direction_lookup.p4" +#include "stages/eni_lookup.p4" #include "stages/routing_action_apply.p4" +#include "stages/metering_update.p4" #include "underlay.p4" #define MAX_ENI 64 @@ -44,8 +47,6 @@ control dash_ingress( #ifdef TARGET_BMV2_V1MODEL @SaiCounter[name="lb_fast_path_icmp_in", attr_type="stats"] counter(1, CounterType.packets_and_bytes) port_lb_fast_path_icmp_in_counter; - @SaiCounter[name="lb_fast_path_eni_miss", attr_type="stats"] - counter(1, CounterType.packets_and_bytes) port_lb_fast_path_eni_miss_counter; #endif @SaiTable[name = "vip", api = "dash_vip"] @@ -62,28 +63,6 @@ control dash_ingress( const default_action = deny; } - action set_outbound_direction() { - meta.direction = dash_direction_t.OUTBOUND; - } - - action set_inbound_direction() { - meta.direction = dash_direction_t.INBOUND; - } - - @SaiTable[name = "direction_lookup", api = "dash_direction_lookup"] - table direction_lookup { - key = { - hdr.u0_vxlan.vni : exact @SaiVal[name = "VNI"]; - } - - actions = { - set_outbound_direction; - @defaultonly set_inbound_direction; - } - - const default_action = set_inbound_direction; - } - action set_appliance(EthernetAddress neighbor_mac, EthernetAddress mac) { meta.encap_data.underlay_dmac = neighbor_mac; @@ -188,21 +167,6 @@ control dash_ingress( const default_action = deny; } - DEFINE_TABLE_COUNTER(eni_counter) - - @SaiTable[ignored = "true"] - table eni_meter { - key = { - meta.eni_id : exact @SaiVal[type="sai_object_id_t"]; - meta.direction : exact; - meta.dropped : exact; - } - - actions = { NoAction; } - - ATTACH_TABLE_COUNTER(eni_counter) - } - action permit() { } @@ -241,88 +205,6 @@ control dash_ingress( const default_action = deny; } - action check_ip_addr_family(@SaiVal[type="sai_ip_addr_family_t", isresourcetype="true"] bit<32> ip_addr_family) { - if (ip_addr_family == 0) /* SAI_IP_ADDR_FAMILY_IPV4 */ { - if (meta.is_overlay_ip_v6 == 1) { - meta.dropped = true; - } - } else { - if (meta.is_overlay_ip_v6 == 0) { - meta.dropped = true; - } - } - } - - @SaiTable[name = "meter_policy", api = "dash_meter", order = 1, isobject="true"] - table meter_policy { - key = { - meta.meter_policy_id : exact; - } - actions = { - check_ip_addr_family; - } - } - - action set_policy_meter_class(bit<16> meter_class) { - meta.policy_meter_class = meter_class; - } - - @SaiTable[name = "meter_rule", api = "dash_meter", order = 2, isobject="true"] - table meter_rule { - key = { - meta.meter_policy_id: exact @SaiVal[type="sai_object_id_t", isresourcetype="true", objects="METER_POLICY"]; - hdr.u0_ipv4.dst_addr : ternary @SaiVal[name = "dip", type="sai_ip_address_t"]; - } - - actions = { - set_policy_meter_class; - @defaultonly NoAction; - } - const default_action = NoAction(); - } - - // MAX_METER_BUCKET = MAX_ENI(64) * NUM_BUCKETS_PER_ENI(4096) - #define MAX_METER_BUCKETS 262144 -#ifdef TARGET_BMV2_V1MODEL - @SaiCounter[name="outbound", action_names="meter_bucket_action", attr_type="counter_attr"] - counter(MAX_METER_BUCKETS, CounterType.bytes) meter_bucket_outbound; - @SaiCounter[name="inbound", action_names="meter_bucket_action", attr_type="counter_attr"] - counter(MAX_METER_BUCKETS, CounterType.bytes) meter_bucket_inbound; -#endif // TARGET_BMV2_V1MODEL - action meter_bucket_action(@SaiVal[type="sai_uint32_t", skipattr="true"] bit<32> meter_bucket_index) { - meta.meter_bucket_index = meter_bucket_index; - } - - @SaiTable[name = "meter_bucket", api = "dash_meter", order = 0, isobject="true"] - table meter_bucket { - key = { - meta.eni_id: exact @SaiVal[type="sai_object_id_t"]; - meta.meter_class: exact; - } - actions = { - meter_bucket_action; - @defaultonly NoAction; - } - const default_action = NoAction(); - } - - action set_eni(@SaiVal[type="sai_object_id_t"] bit<16> eni_id) { - meta.eni_id = eni_id; - } - - @SaiTable[name = "eni_ether_address_map", api = "dash_eni", order=0] - table eni_ether_address_map { - key = { - meta.eni_addr : exact @SaiVal[name = "address", type = "sai_mac_t"]; - } - - actions = { - set_eni; - @defaultonly deny; - } - const default_action = deny; - } - action set_acl_group_attrs(@SaiVal[type="sai_ip_addr_family_t", isresourcetype="true"] bit<32> ip_addr_family) { if (ip_addr_family == 0) /* SAI_IP_ADDR_FAMILY_IPV4 */ { if (meta.is_overlay_ip_v6 == 1) { @@ -372,35 +254,20 @@ control dash_ingress( present in the VIP table */ meta.encap_data.underlay_sip = hdr.u0_ipv4.dst_addr; } else { + // TODO: Count the packet drops due to VIP miss if (meta.is_fast_path_icmp_flow_redirection_packet) { -#ifdef TARGET_BMV2_V1MODEL - port_lb_fast_path_eni_miss_counter.count(0); -#endif } } - /* If Outer VNI matches with a reserved VNI, then the direction is Outbound - */ - direction_lookup.apply(); + direction_lookup_stage.apply(hdr, meta); appliance.apply(); - // Save the original DSCP value - meta.eni_data.dscp = (bit<6>)hdr.u0_ipv4.diffserv; - /* Outer header processing */ + eni_lookup_stage.apply(hdr, meta); - /* Put VM's MAC in the direction agnostic metadata field */ - meta.eni_addr = meta.direction == dash_direction_t.OUTBOUND ? - hdr.customer_ethernet.src_addr : - hdr.customer_ethernet.dst_addr; - - if (!eni_ether_address_map.apply().hit) { - if (meta.is_fast_path_icmp_flow_redirection_packet) { -#ifdef TARGET_BMV2_V1MODEL - port_lb_fast_path_eni_miss_counter.count(0); -#endif - } - } + // Save the original DSCP value + meta.eni_data.dscp = (bit<6>)hdr.u0_ipv4.diffserv; if (meta.direction == dash_direction_t.OUTBOUND) { tunnel_decap(hdr, meta); @@ -462,6 +329,7 @@ control dash_ingress( /* Underlay routing */ meta.dst_ip_addr = (bit<128>)hdr.u0_ipv4.dst_addr; + underlay.apply( hdr , meta @@ -473,38 +341,11 @@ control dash_ingress( #endif // TARGET_DPDK_PNA ); - if (meta.meter_policy_en == 1) { - meter_policy.apply(); - meter_rule.apply(); - } - - { - if (meta.meter_policy_en == 1) { - meta.meter_class = meta.policy_meter_class; - } else { - meta.meter_class = meta.route_meter_class; - } - if ((meta.meter_class == 0) || (meta.mapping_meter_class_override == 1)) { - meta.meter_class = meta.mapping_meter_class; - } - } - - meter_bucket.apply(); - if (meta.direction == dash_direction_t.OUTBOUND) { -#ifdef TARGET_BMV2_V1MODEL - meter_bucket_outbound.count(meta.meter_bucket_index); -#endif - } else if (meta.direction == dash_direction_t.INBOUND) { -#ifdef TARGET_BMV2_V1MODEL - meter_bucket_inbound.count(meta.meter_bucket_index); -#endif - } - if (meta.eni_data.dscp_mode == dash_tunnel_dscp_mode_t.PIPE_MODEL) { hdr.u0_ipv4.diffserv = (bit<8>)meta.eni_data.dscp; } - eni_meter.apply(); + metering_update_stage.apply(hdr, meta); if (meta.dropped) { drop_action(); diff --git a/dash-pipeline/bmv2/stages/direction_lookup.p4 b/dash-pipeline/bmv2/stages/direction_lookup.p4 new file mode 100644 index 000000000..2bae56667 --- /dev/null +++ b/dash-pipeline/bmv2/stages/direction_lookup.p4 @@ -0,0 +1,36 @@ +#ifndef _DASH_STAGE_DIRECTION_LOOKUP_P4_ +#define _DASH_STAGE_DIRECTION_LOOKUP_P4_ + +control direction_lookup_stage( + inout headers_t hdr, + inout metadata_t meta) +{ + action set_outbound_direction() { + meta.direction = dash_direction_t.OUTBOUND; + } + + action set_inbound_direction() { + meta.direction = dash_direction_t.INBOUND; + } + + @SaiTable[name = "direction_lookup", api = "dash_direction_lookup"] + table direction_lookup { + key = { + hdr.u0_vxlan.vni : exact @SaiVal[name = "VNI"]; + } + + actions = { + set_outbound_direction; + @defaultonly set_inbound_direction; + } + + const default_action = set_inbound_direction; + } + + apply { + /* If Outer VNI matches with a reserved VNI, then the direction is Outbound - */ + direction_lookup.apply(); + } +} + +#endif /* _DASH_STAGE_DIRECTION_LOOKUP_P4_ */ \ No newline at end of file diff --git a/dash-pipeline/bmv2/stages/eni_lookup.p4 b/dash-pipeline/bmv2/stages/eni_lookup.p4 new file mode 100644 index 000000000..57d3605f2 --- /dev/null +++ b/dash-pipeline/bmv2/stages/eni_lookup.p4 @@ -0,0 +1,50 @@ +#ifndef _DASH_STAGE_ENI_LOOKUP_P4_ +#define _DASH_STAGE_ENI_LOOKUP_P4_ + +control eni_lookup_stage( + inout headers_t hdr, + inout metadata_t meta) +{ +#ifdef TARGET_BMV2_V1MODEL + @SaiCounter[name="lb_fast_path_eni_miss", attr_type="stats"] + counter(1, CounterType.packets_and_bytes) port_lb_fast_path_eni_miss_counter; +#endif + + action set_eni(@SaiVal[type="sai_object_id_t"] bit<16> eni_id) { + meta.eni_id = eni_id; + } + + action deny() { + meta.dropped = true; + } + + @SaiTable[name = "eni_ether_address_map", api = "dash_eni", order=0] + table eni_ether_address_map { + key = { + meta.eni_addr : exact @SaiVal[name = "address", type = "sai_mac_t"]; + } + + actions = { + set_eni; + @defaultonly deny; + } + const default_action = deny; + } + + apply { + /* Put VM's MAC in the direction agnostic metadata field */ + meta.eni_addr = meta.direction == dash_direction_t.OUTBOUND ? + hdr.customer_ethernet.src_addr : + hdr.customer_ethernet.dst_addr; + + if (!eni_ether_address_map.apply().hit) { + if (meta.is_fast_path_icmp_flow_redirection_packet) { +#ifdef TARGET_BMV2_V1MODEL + port_lb_fast_path_eni_miss_counter.count(0); +#endif + } + } + } +} + +#endif /* _DASH_STAGE_ENI_LOOKUP_P4_ */ \ No newline at end of file diff --git a/dash-pipeline/bmv2/stages/metering_update.p4 b/dash-pipeline/bmv2/stages/metering_update.p4 new file mode 100644 index 000000000..48269d6f6 --- /dev/null +++ b/dash-pipeline/bmv2/stages/metering_update.p4 @@ -0,0 +1,120 @@ +#ifndef _DASH_STAGE_METERING_UPDATE_P4_ +#define _DASH_STAGE_METERING_UPDATE_P4_ + +control metering_update_stage( + inout headers_t hdr, + inout metadata_t meta) +{ + action check_ip_addr_family(@SaiVal[type="sai_ip_addr_family_t", isresourcetype="true"] bit<32> ip_addr_family) { + if (ip_addr_family == 0) /* SAI_IP_ADDR_FAMILY_IPV4 */ { + if (meta.is_overlay_ip_v6 == 1) { + meta.dropped = true; + } + } else { + if (meta.is_overlay_ip_v6 == 0) { + meta.dropped = true; + } + } + } + + @SaiTable[name = "meter_policy", api = "dash_meter", order = 1, isobject="true"] + table meter_policy { + key = { + meta.meter_policy_id : exact; + } + actions = { + check_ip_addr_family; + } + } + + action set_policy_meter_class(bit<16> meter_class) { + meta.policy_meter_class = meter_class; + } + + @SaiTable[name = "meter_rule", api = "dash_meter", order = 2, isobject="true"] + table meter_rule { + key = { + meta.meter_policy_id: exact @SaiVal[type="sai_object_id_t", isresourcetype="true", objects="METER_POLICY"]; + hdr.u0_ipv4.dst_addr : ternary @SaiVal[name = "dip", type="sai_ip_address_t"]; + } + + actions = { + set_policy_meter_class; + @defaultonly NoAction; + } + const default_action = NoAction(); + } + + // MAX_METER_BUCKET = MAX_ENI(64) * NUM_BUCKETS_PER_ENI(4096) + #define MAX_METER_BUCKETS 262144 +#ifdef TARGET_BMV2_V1MODEL + @SaiCounter[name="outbound", action_names="meter_bucket_action", attr_type="counter_attr"] + counter(MAX_METER_BUCKETS, CounterType.bytes) meter_bucket_outbound; + @SaiCounter[name="inbound", action_names="meter_bucket_action", attr_type="counter_attr"] + counter(MAX_METER_BUCKETS, CounterType.bytes) meter_bucket_inbound; +#endif // TARGET_BMV2_V1MODEL + action meter_bucket_action(@SaiVal[type="sai_uint32_t", skipattr="true"] bit<32> meter_bucket_index) { + meta.meter_bucket_index = meter_bucket_index; + } + + @SaiTable[name = "meter_bucket", api = "dash_meter", order = 0, isobject="true"] + table meter_bucket { + key = { + meta.eni_id: exact @SaiVal[type="sai_object_id_t"]; + meta.meter_class: exact; + } + actions = { + meter_bucket_action; + @defaultonly NoAction; + } + const default_action = NoAction(); + } + + DEFINE_TABLE_COUNTER(eni_counter) + + @SaiTable[ignored = "true"] + table eni_meter { + key = { + meta.eni_id : exact @SaiVal[type="sai_object_id_t"]; + meta.direction : exact; + meta.dropped : exact; + } + + actions = { NoAction; } + + ATTACH_TABLE_COUNTER(eni_counter) + } + + apply { + if (meta.meter_policy_en == 1) { + meter_policy.apply(); + meter_rule.apply(); + } + + { + if (meta.meter_policy_en == 1) { + meta.meter_class = meta.policy_meter_class; + } else { + meta.meter_class = meta.route_meter_class; + } + if ((meta.meter_class == 0) || (meta.mapping_meter_class_override == 1)) { + meta.meter_class = meta.mapping_meter_class; + } + } + + meter_bucket.apply(); + if (meta.direction == dash_direction_t.OUTBOUND) { +#ifdef TARGET_BMV2_V1MODEL + meter_bucket_outbound.count(meta.meter_bucket_index); +#endif + } else if (meta.direction == dash_direction_t.INBOUND) { +#ifdef TARGET_BMV2_V1MODEL + meter_bucket_inbound.count(meta.meter_bucket_index); +#endif + } + + eni_meter.apply(); + } +} + +#endif /* _DASH_STAGE_METERING_UPDATE_P4_ */ \ No newline at end of file From 04e861784c4c403ce0b519fb6a4b58b0cb978786 Mon Sep 17 00:00:00 2001 From: Riff Date: Mon, 4 Mar 2024 13:11:18 -0800 Subject: [PATCH 09/32] [dash-p4] Add macro for defining and update regular counters. (#530) --- dash-pipeline/bmv2/dash_arch_specific.p4 | 97 +++++++++++++------- dash-pipeline/bmv2/dash_pipeline.p4 | 18 +--- dash-pipeline/bmv2/stages/eni_lookup.p4 | 9 +- dash-pipeline/bmv2/stages/metering_update.p4 | 16 +--- 4 files changed, 75 insertions(+), 65 deletions(-) diff --git a/dash-pipeline/bmv2/dash_arch_specific.p4 b/dash-pipeline/bmv2/dash_arch_specific.p4 index 30a293b68..ca7bb75e1 100644 --- a/dash-pipeline/bmv2/dash_arch_specific.p4 +++ b/dash-pipeline/bmv2/dash_arch_specific.p4 @@ -1,47 +1,80 @@ #ifndef __DASH_TARGET_SPECIFIC__ #define __DASH_TARGET_SPECIFIC__ -#ifdef TARGET_BMV2_V1MODEL - -#include +// +// P4 arch/target includes +// +#if defined(TARGET_BMV2_V1MODEL) + #include +#elif defined(TARGET_DPDK_PNA) // TARGET_BMV2_V1MODEL + #include +#endif // TARGET_DPDK_PNA +// // Counters -#define DEFINE_TABLE_COUNTER(counter_name) direct_counter(CounterType.packets_and_bytes) counter_name; -#define ATTACH_TABLE_COUNTER(counter_name) counters = counter_name; -#define DIRECT_COUNTER_TABLE_PROPERTY counters +// - The counters are defined differently for different arch. +// +#if defined(TARGET_BMV2_V1MODEL) + + #define DEFINE_COUNTER(name, count, ...) \ + @SaiCounter[__VA_ARGS__] \ + counter(count, CounterType.packets_and_bytes) name; -// DBC (Design By Contract) macros -#define REQUIRES(cond) assert(cond) + #define DEFINE_PACKET_COUNTER(name, count, ...) \ + @SaiCounter[__VA_ARGS__] \ + counter(count, CounterType.packets) name; -#endif // TARGET_BMV2_V1MODEL + #define DEFINE_BYTE_COUNTER(name, count, ...) \ + @SaiCounter[__VA_ARGS__] \ + counter(count, CounterType.bytes) name; -#ifdef TARGET_DPDK_PNA + #define UPDATE_COUNTER(name, index) \ + name.count((bit<32>)index) + + #define DEFINE_TABLE_COUNTER(counter_name) direct_counter(CounterType.packets_and_bytes) counter_name; + #define ATTACH_TABLE_COUNTER(counter_name) counters = counter_name; + +#elif defined(TARGET_DPDK_PNA) // TARGET_BMV2_V1MODEL + + // Counters are not supported yet for PNA arch in DASH + #define DEFINE_COUNTER(name, count, ...) + #define DEFINE_PACKET_COUNTER(name, count, ...) + #define DEFINE_BYTE_COUNTER(name, count, ...) + #define UPDATE_COUNTER(name, index) -#include + #ifdef DPDK_SUPPORTS_DIRECT_COUNTER_ON_WILDCARD_KEY_TABLE + // Omit all direct counters for tables with ternary match keys, + // because the latest version of p4c-dpdk as of 2023-Jan-26 does + // not support this combination of features. If you try to + // compile it with this code enabled, the error message looks like + // this: + // + // [--Werror=target-error] error: Direct counters and direct meters are unsupported for wildcard match table outbound_acl_stage1:dash_acl_rule|dash_acl + // + // This p4c issue is tracking this feature gap in p4c-dpdk: + // https://github.com/p4lang/p4c/issues/3868 + #define DEFINE_TABLE_COUNTER(counter_name) DirectCounter>(PNA_CounterType_t.PACKETS_AND_BYTES) counter_name; + #define ATTACH_TABLE_COUNTER(counter_name) pna_direct_counter = counter_name; + #else + #define DEFINE_TABLE_COUNTER(counter_name) + #define ATTACH_TABLE_COUNTER(counter_name) + #endif -// Counters -#ifdef DPDK_SUPPORTS_DIRECT_COUNTER_ON_WILDCARD_KEY_TABLE - // Omit all direct counters for tables with ternary match keys, - // because the latest version of p4c-dpdk as of 2023-Jan-26 does - // not support this combination of features. If you try to - // compile it with this code enabled, the error message looks like - // this: - // - // [--Werror=target-error] error: Direct counters and direct meters are unsupported for wildcard match table outbound_acl_stage1:dash_acl_rule|dash_acl - // - // This p4c issue is tracking this feature gap in p4c-dpdk: - // https://github.com/p4lang/p4c/issues/3868 - #define DEFINE_TABLE_COUNTER(counter_name) DirectCounter>(PNA_CounterType_t.PACKETS_AND_BYTES) counter_name; - #define ATTACH_TABLE_COUNTER(counter_name) pna_direct_counter = counter_name; -#else - #define DEFINE_TABLE_COUNTER(counter_name) - #define ATTACH_TABLE_COUNTER(counter_name) -#endif +#endif // TARGET_DPDK_PNA +// // DBC (Design By Contract) macros -// NOTE: PNA doesn't support assert, hence all macros are defined as empty -#define REQUIRES(cond) - +// - These macros will be used as a replacement for asserts, which makes the precondition and postcondition checks more explicit. +// +#if defined(TARGET_BMV2_V1MODEL) + + #define REQUIRES(cond) assert(cond) + +#elif defined(TARGET_DPDK_PNA) // TARGET_BMV2_V1MODEL + + // NOTE: PNA doesn't support assert, hence all macros are defined as empty + #define REQUIRES(cond) + #endif // TARGET_DPDK_PNA #endif // __DASH_TARGET_SPECIFIC__ diff --git a/dash-pipeline/bmv2/dash_pipeline.p4 b/dash-pipeline/bmv2/dash_pipeline.p4 index 47ee55b74..da4d6f7a7 100644 --- a/dash-pipeline/bmv2/dash_pipeline.p4 +++ b/dash-pipeline/bmv2/dash_pipeline.p4 @@ -44,10 +44,7 @@ control dash_ingress( action accept() { } -#ifdef TARGET_BMV2_V1MODEL - @SaiCounter[name="lb_fast_path_icmp_in", attr_type="stats"] - counter(1, CounterType.packets_and_bytes) port_lb_fast_path_icmp_in_counter; -#endif + DEFINE_COUNTER(port_lb_fast_path_icmp_in_counter, 1, name="lb_fast_path_icmp_in", attr_type="stats") @SaiTable[name = "vip", api = "dash_vip"] table vip { @@ -95,10 +92,7 @@ control dash_ingress( meta.stage4_dash_acl_group_id = ## prefix ##_stage4_dash_acl_group_id; \ meta.stage5_dash_acl_group_id = ## prefix ##_stage5_dash_acl_group_id; -#ifdef TARGET_BMV2_V1MODEL - @SaiCounter[name="lb_fast_path_icmp_in", attr_type="stats", action_names="set_eni_attrs"] - counter(MAX_ENI, CounterType.packets_and_bytes) eni_lb_fast_path_icmp_in_counter; -#endif + DEFINE_COUNTER(eni_lb_fast_path_icmp_in_counter, MAX_ENI, name="lb_fast_path_icmp_in", attr_type="stats", action_names="set_eni_attrs") action set_eni_attrs(bit<32> cps, bit<32> pps, @@ -244,9 +238,7 @@ control dash_ingress( #endif // TARGET_DPDK_PNA if (meta.is_fast_path_icmp_flow_redirection_packet) { -#ifdef TARGET_BMV2_V1MODEL - port_lb_fast_path_icmp_in_counter.count(0); -#endif + UPDATE_COUNTER(port_lb_fast_path_icmp_in_counter, 0); } if (vip.apply().hit) { @@ -311,9 +303,7 @@ control dash_ingress( } if (meta.is_fast_path_icmp_flow_redirection_packet) { -#ifdef TARGET_BMV2_V1MODEL - eni_lb_fast_path_icmp_in_counter.count((bit<32>)meta.eni_id); -#endif + UPDATE_COUNTER(eni_lb_fast_path_icmp_in_counter, meta.eni_id); } acl_group.apply(); diff --git a/dash-pipeline/bmv2/stages/eni_lookup.p4 b/dash-pipeline/bmv2/stages/eni_lookup.p4 index 57d3605f2..fc94965df 100644 --- a/dash-pipeline/bmv2/stages/eni_lookup.p4 +++ b/dash-pipeline/bmv2/stages/eni_lookup.p4 @@ -5,10 +5,7 @@ control eni_lookup_stage( inout headers_t hdr, inout metadata_t meta) { -#ifdef TARGET_BMV2_V1MODEL - @SaiCounter[name="lb_fast_path_eni_miss", attr_type="stats"] - counter(1, CounterType.packets_and_bytes) port_lb_fast_path_eni_miss_counter; -#endif + DEFINE_COUNTER(port_lb_fast_path_eni_miss_counter, 1, name="lb_fast_path_eni_miss", attr_type="stats") action set_eni(@SaiVal[type="sai_object_id_t"] bit<16> eni_id) { meta.eni_id = eni_id; @@ -39,9 +36,7 @@ control eni_lookup_stage( if (!eni_ether_address_map.apply().hit) { if (meta.is_fast_path_icmp_flow_redirection_packet) { -#ifdef TARGET_BMV2_V1MODEL - port_lb_fast_path_eni_miss_counter.count(0); -#endif + UPDATE_COUNTER(port_lb_fast_path_eni_miss_counter, 0); } } } diff --git a/dash-pipeline/bmv2/stages/metering_update.p4 b/dash-pipeline/bmv2/stages/metering_update.p4 index 48269d6f6..24877739f 100644 --- a/dash-pipeline/bmv2/stages/metering_update.p4 +++ b/dash-pipeline/bmv2/stages/metering_update.p4 @@ -47,12 +47,8 @@ control metering_update_stage( // MAX_METER_BUCKET = MAX_ENI(64) * NUM_BUCKETS_PER_ENI(4096) #define MAX_METER_BUCKETS 262144 -#ifdef TARGET_BMV2_V1MODEL - @SaiCounter[name="outbound", action_names="meter_bucket_action", attr_type="counter_attr"] - counter(MAX_METER_BUCKETS, CounterType.bytes) meter_bucket_outbound; - @SaiCounter[name="inbound", action_names="meter_bucket_action", attr_type="counter_attr"] - counter(MAX_METER_BUCKETS, CounterType.bytes) meter_bucket_inbound; -#endif // TARGET_BMV2_V1MODEL + DEFINE_BYTE_COUNTER(meter_bucket_outbound, MAX_METER_BUCKETS, name="outbound", action_names="meter_bucket_action", attr_type="counter_attr") + DEFINE_BYTE_COUNTER(meter_bucket_inbound, MAX_METER_BUCKETS, name="inbound", action_names="meter_bucket_action", attr_type="counter_attr") action meter_bucket_action(@SaiVal[type="sai_uint32_t", skipattr="true"] bit<32> meter_bucket_index) { meta.meter_bucket_index = meter_bucket_index; } @@ -104,13 +100,9 @@ control metering_update_stage( meter_bucket.apply(); if (meta.direction == dash_direction_t.OUTBOUND) { -#ifdef TARGET_BMV2_V1MODEL - meter_bucket_outbound.count(meta.meter_bucket_index); -#endif + UPDATE_COUNTER(meter_bucket_outbound, meta.meter_bucket_index); } else if (meta.direction == dash_direction_t.INBOUND) { -#ifdef TARGET_BMV2_V1MODEL - meter_bucket_inbound.count(meta.meter_bucket_index); -#endif + UPDATE_COUNTER(meter_bucket_inbound, meta.meter_bucket_index); } eni_meter.apply(); From 5c160720a8e79c3d58fd9e6219f702c9a4597aa0 Mon Sep 17 00:00:00 2001 From: Riff Date: Tue, 5 Mar 2024 16:21:37 -0800 Subject: [PATCH 10/32] [sai-gen] Add support of generating hit count counters (#531) ## Problem In today's DASH SAI generator, we support 3 type of counters: SAI counter ID, SAI Attributes and SAI stats. Due to the nature of P4 counters, the counters are used as packet counters or byte counters, hence all counters will either have _PACKET or _BYTES suffix. However, we have many counters that doesn't work as packet counters, for example - how many flows is created or deleted. ## What we are doing in this change This change updates the SAI generator to support the counters without suffix. This allows us to support generating hit-count type counters. For example, if we have these counters defined in P4: ![image](https://github.com/sonic-net/DASH/assets/1533278/bd5cd15a-5156-48ea-8199-274642c796eb) The following stats will be generated on the ENI: ![image](https://github.com/sonic-net/DASH/assets/1533278/512a5f0b-ce47-438b-b41b-e340e7adc9b8) --- dash-pipeline/SAI/sai_api_gen.py | 8 ++++++-- dash-pipeline/bmv2/dash_arch_specific.p4 | 5 +++++ 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/dash-pipeline/SAI/sai_api_gen.py b/dash-pipeline/SAI/sai_api_gen.py index 3b94645eb..20e5c4ec7 100755 --- a/dash-pipeline/SAI/sai_api_gen.py +++ b/dash-pipeline/SAI/sai_api_gen.py @@ -516,6 +516,7 @@ def __init__(self): self.isreadonly: str = "true" self.counter_type: str = "bytes" self.attr_type: str = "stats" + self.no_suffix: bool = "" self.param_actions: List[str] = [] def parse_p4rt(self, p4rt_counter: Dict[str, Any], var_ref_graph: P4VarRefGraph) -> None: @@ -597,6 +598,8 @@ def __parse_sai_counter_annotation(self, p4rt_counter: Dict[str, Any]) -> None: self.attr_type = str(kv['value']['stringValue']) if self.attr_type not in ["counter_attr", "counter_id", "stats"]: raise ValueError(f'Unknown counter attribute type: attr_type={self.attr_type}') + elif kv['key'] == 'no_suffix': + self.no_suffix = str(kv['value']['stringValue']) == "true" else: raise ValueError("Unknown attr annotation " + kv['key']) @@ -613,10 +616,11 @@ def generate_counter_sai_attributes(self) -> 'Iterator[SAICounter]': counter = copy.deepcopy(self) counter.counter_type = counter_type + if counter.attr_type == "counter_attr": - counter.name = f"{counter.name}_{counter.counter_type}_counter" + counter.name = f"{counter.name}_{counter.counter_type}_counter" if not self.no_suffix else f"{counter.name}_counter" else: - counter.name = f"{counter.name}_{counter.counter_type}" + counter.name = f"{counter.name}_{counter.counter_type}" if not self.no_suffix else counter.name yield counter diff --git a/dash-pipeline/bmv2/dash_arch_specific.p4 b/dash-pipeline/bmv2/dash_arch_specific.p4 index ca7bb75e1..17b8c60e8 100644 --- a/dash-pipeline/bmv2/dash_arch_specific.p4 +++ b/dash-pipeline/bmv2/dash_arch_specific.p4 @@ -28,6 +28,10 @@ @SaiCounter[__VA_ARGS__] \ counter(count, CounterType.bytes) name; + #define DEFINE_HIT_COUNTER(name, count, ...) \ + @SaiCounter[__VA_ARGS__, no_suffix="true"] \ + counter(count, CounterType.packets) name; + #define UPDATE_COUNTER(name, index) \ name.count((bit<32>)index) @@ -40,6 +44,7 @@ #define DEFINE_COUNTER(name, count, ...) #define DEFINE_PACKET_COUNTER(name, count, ...) #define DEFINE_BYTE_COUNTER(name, count, ...) + #define DEFINE_HIT_COUNTER(name, count, ...) #define UPDATE_COUNTER(name, index) #ifdef DPDK_SUPPORTS_DIRECT_COUNTER_ON_WILDCARD_KEY_TABLE From 28e2ab579f038ef94b16266402b746355f6fb4fd Mon Sep 17 00:00:00 2001 From: KrisNey-MSFT Date: Wed, 6 Mar 2024 12:16:53 -0700 Subject: [PATCH 11/32] Add files via upload --- ...la In Network Transformations for AI_ML.pdf | Bin 0 -> 640113 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 slides/Srikanth Kandula In Network Transformations for AI_ML.pdf diff --git a/slides/Srikanth Kandula In Network Transformations for AI_ML.pdf b/slides/Srikanth Kandula In Network Transformations for AI_ML.pdf new file mode 100644 index 0000000000000000000000000000000000000000..ab25150f6ae1736d72880876ff42b0d7346dcb76 GIT binary patch literal 640113 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

w+O1dAIJa`>s5? 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�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 z%0D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 |cJV?vXI0vK{W;1X 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 z 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

7tEH#)yyA zylt$N3Y0-5I-zcnsMmS(ek@vAmKxmqp4Bg90R#M|}^Hz-LL?Jk#vCc$UawUx<)X9Z=bRzS$#34CBQ<94TW#Zyc;+V8u9 zSsv#@HMParelMwC$;rvFl_jqCG;*eAF^@ieNDG*rDq3+uB;}7UyGfD+O@k=5U=1hL zLoN^U_A-Y=Be?6cM=C2w^4v9uruVFjw_iHo)pW_ar|5wW@@$P=3vcf=c)duy{jAh} z2c-g7sfRx2DW9iQ1HF$oOarqjI|m~(PNFFQ-n6^$9~91tq%~)bIdhiwjZwlN*Cm_~ zTcIuJ8UG8UW=7$^%E9cWC87wABx6j+)C(F`R1Nm&)2qH#mFJEa7#MGt?%lz$*Xwf% zNikOqZC5f1{2z%+A1}(H!Ro~59U23fqWDJ^k`|w35F+r_IuKe$IShxMUPX|>p-fUYE2)u_6zqL^N zu0W=B0V#QapTU3~8!2H90%Ma0&HLr+1}5velCPv-CIIa(NEOx7 zxl_#ET8x-0-jZlU&ot(P|7dgX;s!p)=@cKYf_r8znso^7TWr2TChhXniQSX*r@WrN zfCek?z@xs6)jzXzR@=%mwyXPqhRN>l@7ry(@!$MG_kUYRgoXKBX?r^>iCKA&)66l= zdJN>U7vxWe#WB|tpnaW7HF%k*-|Ko8N3ed0=w=1AA`0c&rgpTxCcz|+KnC9*sEX03 zZ6@+UQpk>G`e?+`C7(EN)~A?%zAtEOlfCU?bxTT1zszNS{B1tU=HY#-&M~)4Ztniu z;X7tZ(RyPJuIBh%IFv?hxnmMg(KYU^jk~uBYq!stc!kxqtD^e_#Kz!fZ$EjLGTX`G zwen)eBV?ri>4T}rjrU9xI~3qx{eju^Kg}PAHzl+-D?O_P+krF>_9S*wsM$_L<3JX= zRlx6X*hLWME)fqCHZ|bQQaQ(?WCz>}?2DXVn4~Yz(JI-VW04676+OH`!f|RT)E2~A z{l4~6@fnJ%&1xEOBb2s{u>CZIprzo(NHPnD!hQ#02UEi>>qOy3Z(z&iNu5I@{(wG5R>e>hQzDDV(+q;foYoYg zr;b1t{`yte(5u>gbnPf>Y@O}c`?F^8^~@(VGI<^7d$i8x%^+}IKjwfzOtDz;y}i-c zEc^DLvk`j5e3u10Hc*^aZx{H*WWRT3pmh%6#K@+i4@aqcF&OMWB830t>jwp6^hY9}d5FRBFw_u< zJpos^^tG#?pkM$UnB-q?|3~|lkeHdD`Ialo-k%YmBJVk+`GE`&$fGm%hfBjYYck_)##X} zj+J(g!2jfxk0#BX-J=o-AQ3L!rxH#SJ^pMmIU!oX`2?2r`F;!Lq%t)=?r93IhgE%Z zzg0EfP3N!%gWI7no2AtKpcljqc+E2j&~5k`pJqExru`XwI4Ok>iyki4ABybkSb@&b zhS&~7M7BZ579-{MemIXI;QhEh-(Fg}7*4v1WF%y+ca+SO$NKh-)B2}<%h6|gD^%14 z;?&bACQ-gOPAj?FxJEgQOB%1Q$j_fYt*pvaBO>hBn-wIBe(Z(US6V@Jk22Zcng(-C})0JpU2lLc+62%M!>jZN{SauV2g>#x&E%Pth7HlBUZzxrz>9u*I z@O9zb6N&T#<@P@-_N#Tq4M|rxM0?zX8#s`tz|n}mNy0E@aXS~uq%wlWC0}fIzAo9x z5uDAt*`Ikmf^`Qd<%@GKloIf^)myBEUK2f?XgB<<^?tOQXMS6zZCQKw^zG=jgXB6{ zuFVGk0QL3G8I<>&$d;%=q}p5%TT~Pjh1N?|_ooYIt3{sZ7OOrX6e;l^;qcb(KZ*~XT-7dUt*d@Z)BsHE_8$-Boz;SON#4-kt!}U|Y?JtL$i2~H4iB45B<>QSbEuojd62B>J@sdyx;u+ zU50u7Zjj#sz;6}Tg-vEuej$8hm3I3sHPuE|S6?MkDS&lG@wndhecjMzKVGYv$!Jh% zaf1OvBP^Dyr|cE&9@SYc{{sT=S4EU^=`C$-w8_$%0nEmSKGjWClPI5JHY_EW4%xfA zyYXZaoNjKi+4ua~&H?V?>rF*+8E&Ap^?Y|k8A=nYmBwBAfXC+{CiY9aGV}nPg%SGzlDfmsL1JEX1c}bLuD*UJOYrej z6?gh-?shYw)0v*9QIh(Pnq+iO?a=lisL^p4%h$;o*ieY(z&J7^YgQSRKA zSbM0#fj3|yP}qgw7}+{;fPo^^K&Rnxs`&HbU{@1X;A;~F9o?9D9$&j09OZ}p?69Ci zh^nw~V0X7az|A)BqTBA2wLv9u2lCbRxy(6}#}#ZIYcl)sW7$h}e(#E6lQVGKkbQp( z-4=J^qjuXYMeSA!(LC``9b#41pULQ0@zrx>%5&=N@8BdGk$yufP|vv-VUta8U8WFB z>c>B!hQ6X^^mx5!`ulK3K7YEqD-!RqRut^{XRMTVRa*_>P|Pq5$+u4NPaeb}l0p{e z#>Z#4WGxb9y%jnnQ|Gk=_gl&+@Gm0c>b;Wr=GJyp4q%?gaas%-#ROj}KnGkDd6x#G zV~7MN3mOZ zM9W==RK8?@%hjxa349r1%K1yO%{JtG<@e67g~4_>-iDLM+StS^?I(3idz`|%*EEz` z2bsL?t4+3us&5Z=w439X6ME_2c_k@)M7H~7!fQSZx@=LdO^n-bz(o2%hrS3I6;=SE zR=4@!&#Ou#(8|F*VfvTp;5TJ+?Bpm< zfKH2S0Eet+_Gqs7r1Avrsrdq;k8w67d{#l9Z_tvo|3q1Oi8hfWJAlz8E%{48_L~^B zKpi=vB}0_b>outW3zQ)nx^L?QE%0{T?cr@^={g29Kb3>!1*@3_H2@xn0^s2)IybvI zWb+?($0n`~&m*=lpE{g42SGdbL70=r$w8YnR#{U7tgVXLmJ9H7;N1;m2XvQ zb^b1Ydu|^nVH)m0SY8=v%nIU{835zcYt!h@KTyoT|K>CpX2G=ya|J~IK#dm#OP?^x?Em%7|!z_Ae&_vF~ z`4DB;af*Mn45l0-*l}b;UuETpim&fxq)`Jxrvu?5`K{{cS_X{YuF>50fJ@E37ut>A z0~)lU3kS$LyI#91{q3$&z#{72@BFTXR=l2{f3kDp#-=%zIgNRAciDl(31vK~_e9jb znyh!994fZE?F~i)kZ{m&akVuy!*))U-eT-|n$PCigf}N!_X90Y)|U9&-Ru^6PWqcH zdjvtBxU4W((F9Lqq}(>u%ItJS!Z7-xVZd+RHlh_LiB#XOLzlb7k8ZZ}hJTM|AOZvQ z>f8Q4y?`DyN-vl5t#1EjyN%Um`>VsyMZq?MtFo_CbA)=l8i`cEG6fS_82qn9fOYHskyiJl*ix)&`YA z`-Wy_W_qgrnfe$0>sOJS-j1kuqa_sOI8~RxfMQyHTMI1k7mBY7kNH-YFPHtM7@`T% zi^Wnc6Mu~EOunxS^VMdjx2Gq!&)DfaWZKK$){|cuIQO2w^_J@bIn!9jC$aIkVYd2m z&qK)d9$4hwhP!dpZLpTbqSa$tlbOVh>DvEPIcYn-`S<5>G$~@Y|3XFQpc50*$ulKLBM;im+q|78H66VPmaW+*FGHApD z#y88gCV^X3Z>#So>si-V8yAQaY6+@IC(CHbMwz%vWe}2=Do_+~#MVn~PpPrC39S9h zq=DOuh0c+k>+2h*TvZy)8rAyLc9xA@UiW1dQ(2wsr$^%_G^_058XP*s4Gn)Y?7JMT zxBvQ;0(!RY-tvfS!7R;CUmWRNL7F~&jmkrH&N^mLyg%W?#hylCT}YtoM|s&Yk5Q|; z^$<^ED#LHUm@}B&Q0)6iqj0B^LHi~4CW-Tem`5A0`z6?M-yWpCbe?%{@%ryGwQ>aF z$`+R&+BZK3YWyy6n_O&>I^5r$9G9VLLXayosyC&xIrFBCgg&6$SwPA)+>2Tb5fXxv z4lM|L_!GEVt~NKgxw$E{)Y{rARM5DbyF7L1i`o;)i&&~k>jo}<@a%xE5`vlF9;^`m zx#w^H;Lfj|r-V?{@4Z-9-=rf{M?45K^b{BxQUY>y6EQaP-W zug9!AKp)lmb6=AGFY#h>s(h&XzB9)>{A5d%3}x?{8klgv2tPZ|w>J;-4Wu~Zv=vC1FFw{I|}dM#E%RarM?cmqYn#OZ7!CP zl*sl!s`?=FXQ0q4rD>BlK~@pOiKAL%aXIiHP3?@yKTo_WKmW3T#f_-6kHo%|Lz%6t ztZ;K5OKwyo4I5*1Xw6&4Ta?2v%4cxpI|9J;-e2y|X4{^lJxh+F&bQGLp&CmAL2uFd zYE#Y6gIibd?(A^_kE;QkTrx2}Ou?q`^^iIF%66$$AnuYOM2D)Z`hqGyT_N`Be6>Tr zzYWFW-H$Vc)MsLJG>8k5E`>m6EEHTKSn6X=qN=LOVJ1S`#~`qHI4z`TP4>m}clb^_ z!KIb}9wQ^pQ{%o!K_#7slamwZEkTO=3{jfKuwn3#XYfOu<=K0x2|i(n2OOda_`S8{ zGL4lrW=w8ng>bnC z=Gu68H%`^Zc9m6oH=bAQVOK=z*m=POy~rk`Idwkdb!e1fF-vRnKN~LYX{4WQv|l!xve@mB>24T!n$vBY$;u)T>nbY7@qK>11dy$AviS8oad9<+oZ~!; zF3F4IF|o&QZ)d(Q`gPXk*ybQ3g-zUhdT^?g@9oQPv&`)HolT6Po%2SdV0{-x128@cQT+xK$+$tbmI_4=1VrzzkfE1uwn zrTIoLMvV0N^{U%wB{z`nCd{_yKKAt;tks}f+_`EeGC-mCfb%*{;gcUJ39cLg8QFHJ zDzjenLN0hM6&5vqfFbl1vZwz&@U%DvC%*e&$-CY=%H95Rqj?L=c^6s}8?p*g#Bo?s z00sWfcfThv=JVBYZrds*E!B|SI7?VZd}TCF;5myOS_<`)-GFtIE#(mq=a&Tvz zN}kpfe#9X0s^_5^BT6`5ebT>Pd*c2_fGO=}t}(1z1AvDihR;mgQL-sXtOdXaV$>6%j{`zAk)4PS^qs;jzDhkOaB=To~Ef@ey3qGL2*S0;I+~-t6Fc!LV zLl=)ryViK1Qm1*d%lCCFITF3gdSkkDatBAiDh04ZDr9+gI6+4FAP<~la_n2`?S7kX zuvBq(cdtSuHIYPlMhA29xne9y%GfrVsN8G%UT~=tflTb{>$`+v)$L~3elO@(Ph&W; zKa!}^WCNeZV=@@kY>{UQi?uW1Y{7KAC+<#mSh#@}A15*Va=E_I~PI z4RUxr#lMimD1L0TyE8E`PW%WOtzuh~7YALihJej{M?)jo0 zgokoDi?4ogy6a$iNgW!U=@g^%r0FSuM8##rCJ!vcgb6l!yxaim0s90D*1pf~r7U-u znJV9+WeeoX4y;iH;Mp>Puk}mpO*D)F=&AVFHa6KJv(!Bg?O!x-vON!p!LwYSSYrSE z=0TK2e76Flco9+KxsS>EhX}LQXj!MXxLd$LRv1n?Z@B3>TpB{A8SLL=qI)W;jN>|{ zvDk_~LU5GdApOTHi0RHU9 z_ps`WCaYDb?SD4#>w3AfMZ`f=CjCA!xjmboi&v@7!-F_-`k! z?eqf%jM+V)1ElNFlTqMBLMt*jy5urA4Ser0uTMYQTr<8``0qAkZDcHDe6NYMeF7=b zR)$A>CAC|^W3XChwN!=5hX-|v zV&nDkFqgm(nQ-d^HT6PsMcQg%U?ZnBKH&@=43c!Pm$N3NLQ>11e3z=OGDbe@4 z54dIHEmFwVuh!@9k<3|_zgP{8eXp|dwD0KYm95Rx9=D%-*+UcJ4&_IOdpHjA#vp-e--`MFJva+1H0 zP~YUVl77VK)D-CTwBj7DFGeFVr68j=iG=HJxDquyJWM7L(}RcYCXbxzp4x!(MXpe} zu%JLJm=l(Y>9h6E6l4u7ET%A+#?ssz8=3m{5L6qbHBZCi=Rl&@w#ClMG2O3^jZ1%D zzfUS>Z)sEpF6*Z%iMHR?9&B{|MdlZJ&QIHcpk>=biH!ua6H*fC3{x<5&bZbcU}LA^ zbhY{%Cx}kv_s(NV--Bu8RI&t8+^;=>kj3u5_~7y3W1lHqWKU0?f`Wo*TRIKAsF^L5 zm%L?QgW-X|oDrVat2d($fyyP+&zG&1;W8kv4W6v-EE-?Q-`T)?C0@|0`uh735fNQu zt9#7rhPF(A%3Tg4Pb>2OL>p0;Ak7CvDRwdbf^))z@k)j~f2GMM@(f6}U81bvrlJ90M_ zS(p3Pj1eo7G6btV@z%<02wAoM)t(?$HjMSlz)0iyc&b2MTI;?NYY)6OTZAZzxm*~S z<*htP2B?0^9bIv6IEp|Hy2kZXNUwJ!_~h^Rx3n50R)Ik{0T912L7z`r`?DqI%oToy zinA~CZ8B$N>lMpTnKflU9#JS`M1<*$Y-X||WdxO>U#&&Hkej+5Z7GFzM)1lj2D3RdpF|_3uVJ!~>k&F?)u?Tcfl3l#{ZK1zn zeFRiczR{qJ)p-G0e4tP^p#F!p3kBk`21UAFxva+Ch;fSJO6O1$7Z^e5?W>1jn}=T_ z7Yh(fuZ8q1>1TpkS_J9C+t-`q82Zwhw0kDIaIQScwb45x5CioHjZYy%cRLR|926uM zS&oU?K@MHgdYfQ(Y6+^RQ^R@$0rcIY1P2VBL?UEj>k$S@7}-A=Lr&{5U?eK~)Zu9~ zPd3N!aGT+CyqNIT^j>)>y0`Fq6mRqVT_R}lr^Zlrxn#T@>s77=+LY12A+w0QK2yTC z`O?~!)gRy3rexWrgNFXRlNhZG|B_@Af(M>ISDQZC?@!}I%9l#6h9%Lgk%*)~I$grrj z;HxH`r)gjCTqXufp2Qh6rZT&PFMcXswC&Er*pNoQ<*&+s_yV*|vU}rMQy=opVs<&x z_A;#iij-tOC+LE63kME#K4;hgl98^E9uw4r8`md^P(?9Cd|wH<0J;o#psNnIZPeFDUboytpvxJXbyB@4ms(bGUqJR0a`dMf=Q_4LR z^*PSA@{{c~weQl3Y3GUD(6jOEd8eL6NLlHhSP)x?_!$)vdm!=7tv=FiPXgiCX2I3M zynRpB);Y8PyW*<~7jiCm&H-4FNrujHm8>OuhaUxU9hxwiHUDd4{CXcO zW_TYCU0%BfqtN3ugy+WfVeUi$?*C!$o!{dOySCBE#A+Jbc4H^g*lyIAjcqq-Y^$+t zr?G7|w(W2F9^d;s``G`%K8`&<-7|A@U2B~S=en}?nur6Q6$!EG*eHdZ-)f8PlNZkLJyyVkX|AVJD!YG2g~qgJi|ffsgJmQEk22lf zEO$`Zb8^*T#|&(T@kxuZ$&1}e?l@L%9A04CRkdZ~2?s*-7?1dE_Pjv6m?ea~P&GDF zM(pP-ssFXk;Aca8Vi6y#De~jNTGQX8A6XUUke`JgXrN6pp*=>UVNyi-Hvml}@!#G8 zEnyBFs#byaSb3jP5Z=&G4(Y?ck9ci6u7Y9G7<{nZ9bi4cxURf*MAX(Rol)x{fTUZd z)mKnTw73Z=B@hV$ef(^PYM6Q=kOfC*KS$Zdm-#nht>f?h-_YpOD_i=x@{tXM?B8+7 z|Kj3V?_7j>XrcXub&V&|pwSXS`zw*!K1xBeult3?v;fCUCs($=sHAZP`Ah5|EbyuO z6OFv}UzNwP2(c>Eou7NwJK#1;s|Gf#cqMy}0Jl+YgBWHjDq>!?JkrG(Z%1e=MDnvY zN3V|1P$k_ZFiCMB3aM?*Mt~a(PRlp92iAqu(GtqM*u}gZ0PrJtfFQVT(?$xq{KjoF#qY z0?|@w6P5q?Bq{O*_4;hK%rQMl-r1s8CK{!3&ykxEYkk&9)fRIK+pGI=s{pxr%e^7B zD25sOx!ZK5(}do0Xu{L+k6&h42&(j+r0Csz8fAf>48KCBFzR za)w+(2!KsD7R8K^hu$5qDXgL}gfTay(cg)A&+7U6)woP5T)x874#Jk|3lU0~Rj&&t zLWnH5_TrA-5j zeNIuE958*8b~qS^c6_Jq%vC4uFPv=E_2Uc6=p*Eh!dke$5UGIP-Ss_4C#^&w;elDE(yE^Q$3`ApvfRPgFBp(;I~I4E{{JYA)16*;)uTLN zZC>JQKkTM`afAE*h9}C|!2&Nt6VK`R zIA2&!mL7%x7})(3Qwteh|1fcds2KJw*=5HrUZ=luIe$`aP^Sd!*M3j=H$W$>qXKdR@6k-hycS0D?2noDDnqV`;>fzdj)jwgWV3h z&~E_xVnFxEonLcEyCDn4+~7qogJvo1(l%crSm8f`v=s2Yu$PC+oFI(u#6i)-X^HxSh!@HqD6E*=sU=#xO8 zvo;~W<74;y<)*MToI2Js(GLWfm6*Ivq1Oo)x3&^zv&QF#Dbs*^o+JkJg&Px~$o78G z45@o^g>o4n$(pdZCbfE#EzhDY$v%LY$~rJe?aRrE$LAAp)k87Np$2_1jRfjr5`$Ln zl2}-%%!5)Y5F{YmY$;>X&1t*>u>s!)(^KS3H7S#YTg)S#k9{1>BE%HzeB}Xb8-0c_ z6uojJV)){;lOfAzvi3~DH0HNf^rYZ|Ug)hTO^c}?$o|pT#f)kxm8PHO(=cm(hEOiX;2(CV$0iqeFryjb${I!Y_Wp_Ss$v&&|X{ z62^ACGnmG2-RYpNMoQRwkn@~OQP4r7uXRf}?!ZYAf;^gwvR@x9)>X)a3qJe9FMc}A z)xnmY!_2U*2*}M`ehoAUmxrcm#*Zem&m?sA@*s~)3;Ip(;?H@4^prA0k#Tm0PW*$i z#}8aS$Z)2OOp{a2P9)qNk93RrZb%wd?muW8@;O?{MP6M`NLZZ1nz0jX9dUaHrWI(e zIT*J1C{)IV0E;W{&zN;Gt{>t_A>BrF;A-h_II3MZ{B`hqieEA-1RG^?<}6idr-vwv zzp#>S$2_l{gavXitVK}{ssT$ZY;r~A41RN^TvCeB2&aeAFKn&W$l!cAwzmEm44UEqrAJQ!rf~ zr>Rv75rzM4dDsKBqNo-PZVlxaPugNZ67w0-ZEQs?=Q<0;@cUg--LOXy{DjBl1I{QG zoc8C)h-{J1h(1tY4wC-qqxfqi0g_1j*j~1q)xYjr8<9WXK`_35HGS<~G)bq(2BU}p z2`MgGMawP6zQGrk-OV~3u2DLBS3-lBXe#npa8@C6Rc|BJha>=BBh9jC%-1cGiDhO+ zR?*EELBUrTTOeZEfb@tZl0fHQilJLi0IBP!hCjY0DrP>keHcZdHgY)q0={2urWoUvL zg$PM?L4iImizx<>bkk>f9ic*ukGyaMlLo>Nx%qN1xy!$$l%r&qWW}6UzB(|legRB` zK*f+i=5!nB_c%ikHVnj> zZNCFR`d2VOpCRRv&I{pt%gP*`gQ9cn-4vr5(v3aIq`bPrRrq6u^ ziZ-|*vO`CKsYO?$;CO|q8rMAcl`CVf2322}wVm^YOr9^0QEWX1?oy?IsITZlUpN;} zzwTAzb25tNV@d`^ifraR3Z*y)Xy+0KP_jD;4$Con=t~<$+0H)eWu>;WI?stnd59*lLY^7(r9iGWviU+ zXrpU*m}(%pibrkvlAPr8@RybHIvmOTY2R2-kC#VYD_TIW+_7cNE<2XaxiiG7lNjC` zwWjg7D%KX&YER4`uzgU_<827`3`hF;4v=-OLE_ZXeOlH_ZI5T5^XEe>H6;WdUsA;> zaDS$QyH(3tm!3#5h3Zc+pg?7F;#ss>+!6?GZ{sd4;cv(?7JIbyGLGJk(KK^MPwZ1n z2_Qx2j>urKj#HCdLU*)ZqHth?aQY)UB+dcWOPsSAK{2!>&;IX&@#EI|;oYL`&IB^~ zzOkrUO9Ck>wympM~|HN07?xBiLhqnrr zQ5QY&E#?fK(YVEUaKN_3ucGEe=ZBa~2&9JQBA3_zoY2V!Z%rVnBWE{%~|4)lO0lqaf|NICy%5 zPxg#=v}M{)KghTtfa-}AA;Hjmxv1WyRV2yYVDHp8%R@! zl-fb|l!@*T53$=wtT!>O6g#ZU+72eK^;mD`Hx?HrAQUznc95_fJkTP#lE+96F}`bk z`bMJ?w?vxM@X6g$sz|80KQhGYOTI{De=-}}l5)WQ(PT9CYY$gJM4v=?42R~R-@E)HJPK$JmvMpqVBIkv7rw`=l*(W%TZ1lGF-+ z0DY;{hag`~kguege3gQL@{jjYdIeX;zc9vv1XrZ^v?KI3y@`J!UOKS^{vOE3qf`zZ zOB2l{RU8hYU+2rsw$ubUu^a)l8teFX$81~vL^{1a>5+|XVwBor$7hGg3N*c3tqIm> zI;Jh$py$v^EI5>*&-Cwhjh0MH97!40VV~|-G2NcdHNNaaap=gttDcwh%`)r`d%jCX zkK&@Hd9b`pPy|JdxF^?LjJ59bIbyA+ewGACqd(u~cd`D@03>O>pw#TrHpeul2Br$^ zbXE2N@-!jWgUGa)%Gn`I-v!VDH-YtNLcV*mt_D%gvq%%p}o78Mk z-%@CJ7pS?pH=jkD?O4L*0@uanI?7Nv)Y3A_E#avwZxxk&#gRN`_$l5q)U5J&G|xWs z$r7(HYjboS2TUbU5yn}D9*|ouTX4(H3%dEFH}za6?nEEljn8BSls&qGBTA5w?Cf8ojS<9zEDri#%6LEm&RI>t=JnV>U&(Xm5(Y zB5>67;m{8Rab!?N@9&Ers|l}YMG!?MR- zd*^8%$4)aeLTXI*(wJ{!Ag;i&b&|8$wU^tClT9!Ne9P0sZpGVp8=LK*Xeen6AOR}_ z#QXFuUx*8;XS#>>QZD54khJqmW%l@!Rdn0?ZuGnMIZf5Qw&2*_IgN6jV>vlF>HY9F zL`G>1KZWfQz5v_z;T3+C`{j}hEBsVabI<|~=M0fr`yordz zbxeD{p@*=Q*RGj%di-NuJ6O?{cSxTchuKu(wy9kw@m!l6FgAJPIAymzQqfKCMjG^; zOsQJvUDFh>P{uf#?O(Jj^|*bMxqNs?wy)NRn~yl*yFMhDEta#|ZE;;$G^t;P8DGoy z<0%7pLgiBKzg0>tNGv*rPQmu_PLsac7lm35IFgH*!}@gb4_hb2d@RHf#%0WYyf~dO zOn6EyJql-e*b60xM7)$h5XMOi)$Kzd+e~IBXJR@2OdpZ6W&ihMi`2PQBcg8~aQUuB zPts=GeQ5sGe1C4gJSfa#al+e7*T~iM{_nt=>ptmdX6nJfm(5h!p}gb>e-Kd7!VXC5 zfLQG!0;mSczb6uYC280z70~Ub7yc1khq`an;wWw96X@>wdRui(aBcVavR3sd1~)EP z9WdHc(;(?^GnA1X!LfL`WlJ5hwZ9TmyvsvD@A!jhsCP5VW$)43u|$OT%Ot7xH2zI- z7s}J>KQJqRpnZH7r>ICDvZmG>cOL2h&$ukO>(kFgzg^M-N4l6kwwd*QDZilQDX_Wi zde!w;M;5_HIx?R{u-3Bi6X6bVoQF^J-e;R1#IS@Dav3b)9!vppZ7u^2a9snB;bTaZ zKR@5ptf_>}Tx`}8^jwS_=#B9keLBMT--}5wI(h1n9_vgAZ7Hio*REox4usYn)81nl zwUZVxy^*)v}2?UKCNlbUF{b&Dt#Uw=a4y6#{k?P}-Y72&u zgXhFr;qmgbJqwJd7_H?H)k#mu7CdOd?-Qg3zDF_TFuMZzUT*%#ik(U?;2DiEJ>Uc; zye01whu^GDV;q7Al(#5DjI&LHw1Tu#y(aIQK9!_iu$N)JS|!n|2riQDXZwJC5nYO98r1Ab{`$sjLh!008(4B=`$190hn=5$WH>!B+uq z_XGa_pZ`B169=d`L6HL1HiVX;2jmb0e{FI*m*zSj9fNC35D6iEjwA_2-Djyl`3Yg_ zRK-&=v{6mTd3lV9O2fn^wjio*F}<$_ZsfLZfn@>~n4g2Cr9~*k{JV1P%1TE*R9mkR z&Kq`Zl+WiWN6H7P8+j1Llu0cs;z2YRS}!9I08kVtZ0+^PpAdREVSZI{rKo%k-dMVf zE6*x$h+Goj?}Q_Y29b&bpR-1x^u%o$VB8As-QsVuphK8k!Mk|Yx`5H@qT>D7XAtH~ z>)~yA%Y^fOuoZyhAgON1;wVg=D9WMdm@JD5wyekj7rPaTK-6Te$*njPXwdPp5bbCH z#jsseNvWrmnXo%+{#vUMhL{;?WT%SpNfROLP({TWn#Y3N3o zpqdDqhH6memKENY7u;Kx-`JKS{-{K;GJ&(OhO;q4I?|{3gJ^D>4`*YG zWMLV_3A5raCIfjU`&BSCkRxS=DmnjZEQrtV}915ifBrBvLOUd zd>qkcG;L&MjH5FkRzA>@?d)_@R-x!fMejsc$GW_HE@&iiV*MSiQ(*eN6Ew16Wq3!mZ2M!yDG0Q}kspp$ z5HCwjB{2ijibF>$&@(TH+~Ci6M@kqOWPF44KJL^RsVz16!^{Yik|&)?vG7w&$(xBo ze1dRc^3-gtRhFzVV(uOVrjij&vB4aFPM zM`rE=+_ec1)v1o2WohY5VtoAV$T|h9I?Gd|qVZWg6kv(*vt%0_oH0BM)Qrt%(*mr1 zgxEC-(oHrsHIMn}$Ii3kO;w3joV5u_2g&U|w9vCL&AtVgE?4c2V+&c^TKnKMKx&VO zbSdpTZ!AHWj^wBDmS$FnHg4r4C(7Z3(iEl9NVIE_Ma7nqun{)xvu_IMQ`*FH1KqXB z3>Ov%9D4Mv(i9mCM$1$46|K^Gx|P?7(_3p_WRj+XG=KnIXs8(`AW-usgnzw>2@MK9^H26eJx9=}VLxs;aH( z>Yj_U&z*UQRwg6`yLwA8pTyDRqqXov#1{B23=^jO^Gg7L7-G159Vn<;C`h0=J=}OI z6KeWK?seP|J&h!srb|t#U^Al(W37`WEay@*!Aw!?LPwewHkG;ui+X}Z<{?e&(n^tj z^skfx84OL8Fi8w4YynFPN!k{OB+|9SiyvgYx3;A>Hou)cW%ls4g_CtC`c(-5Aguq2 zJ}t#LR#o(jnN3Y8F5?nCBIhFQP~xM|qpH=46)qktJ|R*Psvv+zz2w?{p)2RIxa7+G z5DzTLwT&TsISZs8mE^1J?Kz5Wl9>(Vi>oVPo#DSQl+KyvVcMEI3Uaxa@!6d(IsWLQ^>SCv-$5G!+H!j68s^fJFbY7$0e{en7>GpX z3rS2B3U!I%5h=$vuqMtwa?O56Q`^OPmvcJjNYNRRL#qM8i?>Noph`Cw78I$f%b$Of zKp(;n18riz;+^nYlpgW@9Q(%5jROT3A^VS@Ybj9E4&*HREB`oDwXXc;ET7>}r>6qn zL{n_pkzB#Zpl0sp8ZV6e8d);qxAon4*33Q*(TQ(1W-9IDJO_VW2K{q^UP*Gh@?oT09s{DZ1{8-L7M((yS7MT?m)V5#R5op$*@p*8;gO;YV zzTSmfhMJEU-*!kTDFf8M0Fj)Lk;G8qd>%6FjkHpI8RoY%2WlD5UwyI}rBZR5pKcCr zHZDl{3*#r!C(bc+YiMLrpg?Y|F9S)BKKBP>E*KLoH&Pmfc2s^R90uS52Q^dJQ*qPn zpchqszux?NQsS~nG9+;F-69%hN>%xCBKa<}Vfnz%s78ysMpp=Tvm|$>_6YC4h_QG=iFy-=Y^LdDj%*oI@77R45gpuy^ zXhwFPM*1=xt^$naesu%GQo+XLkE3=EiQ!6y<;Az&A@fd#O=^5egPh;KjmV)JP`>RlRs+ja=2Bf}VMq{X-m~ZFg?Uka>D@i!@{UZabO3F)*;q`|cvfYi3Nr2pF>{!4i6Bf&@{K8BmTDL_E+v2(~ASrUMlYqzTX@Xpd z>qtt^I6gMkeM@bvyI{5S9?xLMpZ-Yj5U(;SiA&>Ey;Qrtu_kT1!rw;)+2=hZ`ig^Mi)}G5-V}f{N8U@;aftoyDq^X zEI4ygZ{5-L0-JeNE0#Yl`!yEUk+;K@$aV&nWJbU7+^o5I5Hof9gTtghsCZp2Qcr@O zJ1b_@6?rX{l+gg+`%Iz18c?md8Z{;HaTXGtT_C{R3v78Fda6G-q8J`7F{ek#Zo_*i z1_#JbL?zdeu<(PGYlY|^gNH${n?7G0eAagQ0`n6d$o3C}7It>N8mV36^txtK_Y%l` z2eu+_`cS219c))L+o&Y9IS&ti_wZqDUY)~S+$Nf~bN94KmqA#w|@b82b9hZAHS|!Jv_ib9QU4&*rdM)h7KaP|EiFugU80p{bR? z>uBzHYHDiuLl*0mM_F%Y1UH&W@;XKm=Q~AY98_&t1#Bh88J6ykTLD5`ZA@A>?EKJ)|eXuWKQ#J0-Ugl;8 zlm|(YsQtnqQhvZY{@YldZ!GDV=Zn73z&M-B$^+o^w??3FSH10k-Hp^COZH(mkXptX z@{QC{?Yh9QY2Qrm7)W&YFQ0K7i#<$7$>R5BHuUNBQ86+k){XR>yF8$M^*;O#3BTLW z>^7+YbHLNyTfLbr;7gPqv-G%lBz}`JY@}{uX4;uje+4qA!nu9A6hg`1@jkPu;yH=< zEa_<5AiB4UM@Ox*yO96MIDD!kVPoR)2TWtI2Ga~o+atTv9*oq?BEj=W-mL?c)DgnjW=bj0akJ!?w_D{$J?IA`~;C?Th&)nC$K4$MQ12T$-TJT zYx$tno-4#FXBW*n{}6C<$?7HNI;Cz}^F3-k7#w5di%fB4{U|}h4P_ZaT4FWCj_uJo*8EO5v$0mSK5?j{PxtV(Kfh~HyR?e2maqXs#O zHfA@(I5dl6`M~zDtvs&I%sO&r7WYos&zsZ%>v&{zoSb5ri{t~#LnkHU8(DuQ66mN0 zdx$H|Ijz-Ublbb=k;Uw#X2qLK?>$ueZnehImB3Q}JP7GjFoWp(r=meUdA-Cg^4jVj zOSZ@0fn^mR?L&aeulelH?o9MJ$r5gABcROHCR}(1i>nWYnN0nP)AUk@Nfvu}DTTP~ z`3t_~TKvqF=o`){8;M+-Yx>Jq&r{<1gUk?xX3rV0&)LMXr6gSU7Tk}llEAD%{zMbQ zs$S!X?5s~OklbotR;b)8!%~K~L@&HhRRQm0fM>32zgkrj#f}E)3QqSQfw*hMXMW40 zROPEp+f&P6>u-=?p4!=>cUd@m3tN*1>*t}-TR<%0p?y%5`1DRiQSRZ=rYq5^J=ODd z<_m0|4LkmqUR6m=AsMiqjP1uK$E(Z+Gj0BnOX290CgGS*7qeON{ji_8d%4oq4)?sh z>5-$PoWoe&+QqEN=SS&Qy+xY!!AmcV=E zZ>cs6h91yE8~QsbQO@J=t}DEKxyRS?zV`YxnZ*~0}y8pz@H=#@WuqXMx#qlC~&hNP=c`N5r&g)gVkAhApK@ubn#Lnxh zYYZ+6N1IZ%EiX5Qb{BojfHncfg7(hFEF>FET;25PA((_vv;rH9*7a5>t*<>Fg*Umu2y6fMWJFYJL;-#j=jizdb}lfCoV)Y#gn6cBS| zH78`nUcIeppPV{@x8+l9;=0d!8S$mO)d~1VnM{hSE+Ru9$NC&4cj9 zw#oHA9C6&iXS}*+o+Y9d@{Gl|(9QEvArvJku%MnzFa5m$qn1=u5j&@33YtJo_zDhv zXNNpiz&QmIehIvjeVm~n4xlPI7tVN{n3}M|;Uo_}ye0aMu_#Zxa%EgkV3!g&+z(5B z5D(=;&=NtUe#T+5dQ_a_d;a(0?}EGji-DtgcH5PLB==JnT^PuQ*PW+pL-onU>JbH9 zDm(2yTmI`$vyu02pe6$fv~k$6{DWPyF)u;FnZF0L^_lkvr5fL%;?mY{!RvrDPBD`` zR>et>JRN+y2?@=2xp5_Qz353g$aCR*HnEU`r^uAacE{%==n^dyJr-LTJHy@ZBO8(|jpxzvqs<@$XmExN4#XMBW~VX0 z!Pb4Dbm<>B7R3S7FlYpYk|y_B7fDZY^ZXf=u+$YmyI>euj4m+>mC>4`;6T?&b)`yD z_OBKlYS*xfM4*(K%Z|_MB_?0X+*EJhF6E2-jcf7qS+mZ8p=5>{0q;xnG$NnaSX1Ax z#J0Gsf(`H6-L{sK!$G_bYUy4JEHM&^iVZnA9p}f_LiFSzf&~Je$-Ql08%lc3-B1hu z!vbNO8~^@&1Y^i(y4gt#G_r2v+sxTZx`M7CfwN<8sLXs9@g)52pHVK(?64KL?dv^0 zl>IYanjAr!0xpyH^Brw!zRaGV z>(ohSLMj~(feQhq@$@t4!pM1Sxn*A!-Z$;TqeVAMH@T86-@e!iWZoUjs&(F+)azkc zQ>pLL?Y0xM2+>j|%4f^Q5yj`rX?Jy1ZAa$ zEA}b(Gb=0GQN^xnRXo>#fIO=@o>>#tI{vNOLL>R>qBV=%e&h>0IQV?CeU0m>r0YP{ zo6t_oNNfC+a!oiXPLK~y^Bn-NCJ zhV=0Ps)EQ|4B|av17F?$j+I!tf|Cb|$?8^h1mlK_!R&~Z-fzd`vBmFif&AnPTAwnU zx!$Er_YqmKW@LOQ3iBN-H>PK2q63nx9hs8VNu)@Vi1|nRa|Nj1T0iYU#g!-SA$f|j zzgfe$D|LybNAC9#y341N)&&R>U#V5un^kV+F*=D8M`^iTxvUMw%7}F0d_8Eh`Z&s} zQ+x5^4MaKyyCY}c42);7z7HyfmZvZNLNvFOKy&%N3Mwwk>k}t5rB=AkDm*U@Cx0*7 zzV zw;%t3Dd1kGUC`sshUrA(d{n7zQjgF;&D+Ca=CoDF#9Q;x{LjD}cGZ<>_d3Qn6kRt(ph6ymp635vTreqn0<>O`ogd!Zf4kB2W8+=qRa;4$Q=cPeQ)^d*#k8 z=FWS3e*JBPi^%@I&ruG3v|g?^XJ)guMi)QNJvicEWo0e2<`HeuOU01nT$?7jGXITi zV{42le{8u&B^wX%DKuvObsDAxihZ%pKXyN-%a8{~9H`iX;f=H#l7|)3e@5?l% zHv+=KxqFe<^gZ47msz|S>|cGDWn)#I$%=2Ai54)c7-o){ejtj{?Fb1s7J+llotvxC|a%FgQ@gur${opxR6g1 zRkM=w7FUG@UCJa<8+g0tI&Uw)5@g%2Me(-`9M9*FVd)P$M=UyyGk>4j5u4kWD;U|c{%cs)3+B7VqJ%<dqbCFkpGC-3d-!g`!; zhSpPf3UBSS(o%3*FTBa|#5G;=W~?Xy$fu)LmZ*Gf)-%dnQ4i*Q0wj=#VMxwYU!B~q zd!&F`h2w72p|6Sau&Yf>sF)bXnD~WoWns0%%dd9QH7yT^s|NeyC#Rwz)`PL_ktp;? zhVdmTR~o?Sqer#d#ZlCp z;h_^}?DI$5gW&cFPNp!8Xl&IzgTS`8CLCIRfXkT(gq`ZLq zAnl$N`*ri{V}Na)O;$AQw6nZV(mf4Js&0W&SIJ%%o>;ETg{0d>sMAoUM6{G3II}*m z@!4mkj3M)%Q8}Ldg~Ti1#76IMTCVyE>`(4zT4Xoe?7$vbn`*q{22?vZjE@qNZDg@D`Xoum=N271JX1=Eu85?dw<422c9;3C? zf9<06-nae@V|Ve13&sIlMW}$Cd_PDD0s|v{hX+bWPL2Rs(kY)9HaHAs2s!;?b)FQj z6#1f1$A937dNZv4{Zq#9o22^bNC&L>(NVVCdtJ5T1-l{9ncc^g%6o0Far&*GX&S8j zhRsOdn*Db16g&$43bM^EOL^ICKZuCq?nsnAVXW+sB{HVN660U!Kv@omq zvoX@i?!KnPj$xmj1ONd%R}Z`Ide>*Qrs9?uYi92KWR9*`uB2O)@p@nr*JU z;aZOgtzKf7)UHpvp(%W$C|Nm6-c0*o6n|mTwFIjz7kuloAFh3Lyc(gPI{0mcb5YZD zO#J%~qd8%Dl8XT$&H4k?Djv&ZLT<+`7wy?iQ@e@+6^;6b-JS(zk`lDwFHO0N-OUaNoF-CGLmlX2aqIUk@t=k_ePs+v7K zYr7-yZ&cj5=%=pac3SB3y#9UO`@*;;ySTfQ_-cPz3~UXv%VF&sVVDJOJFPuA?# zIN9E&CYKEEc;y;0 zxf3nO2nnRcK*(q?ByPkBVJU9-qo@>$HUelz0vBwsJr~VR7NHt)gm8o6k$hPJuZ##7 zL(kqt5qeD*XQydw7h+@hb*2ghrw%_e$@U|4>q0h>wZPS~x<NO`?Zyhq)Nw55Z$K5jP>#L(=xNf*XR$n za}*;N?E6JF^~qItujBoIai8=*Qp_zX6~ttNmCGW05;ol3ldj)hJ#K#`@?oC}vRIGi z6n5354iV{SZ1pkMnklH@A1Ysts?KOCXmmw0$%7+y$RwLO_5j^0FxqN8f2V&S5GhhT z_y$dPbnMMzbXVnTWgeT^Mz2VM_3fy*>`m=TaQ{-;djMANUg9bZjioA3C;zDyNswVqO37r0!#nXnLGc2jh_VvC_ef?9>dhbfs_ z)>q_Dzib3T?C22*tKwIDOWc6pL;qX7ccF?A_Ftob|B++X;9+4& zfq>)z^&3p0^1`NcWx6lSa2uRi0m6{}FR5jq2Q0ZQRNxYkgw6AG2EPpiP`rkNW+i-y z!djW${f6x>2?#^@-+d*3N4eOr^~Nm{OXPqm%oeHR#gs@EFbRq(b=d^dUG~4U$*CBL z32)6NU-@~BL^Gaq4}@DsO85;d`(lU_drLsSD*1b*O=_LFro z9-}pXAL%?JkQTno{O&$MSaM`>3z1^`A_N(M0zMD?4EdRVxn5nRm` zEk*QY0_y1BsUU`AqCmjEZcAW>K9TIhv^Ay?rUhOP9Z-$AwxK+`$gA=#u>l|GHxA(s z6%}y?m(Qt)HM4Q}O)p%`3{Xv&q0*0Udz5eXAxj7T3(~!GXP%%{}gTJ z&!MJF0CX+HU!$(NYSdp{=$zjM2Iu*`!S=q=It~ErN)%#(^-G1@k|hzwj{qz&nQ_k2 zfe&$#5xXJFraBJ)+tM;hf6)&P0Ov17ip$Euk(aXe8eUES&(e-GJ6zvpsJ0C5^Eb2? z^+p?SidfOZO))X>fx8+2rS(xe=qC0xf%e z`VL=}Oi_P`7{C&lg&r<^zB*y#KM^5A_=|FD?V?FOs~hjdULl~E+kGeZ<_yg*MhE&a zl6?!8A_2z&75_PH&jOV4-U-3l#35?s0FWK9L?zEk3U93VJ>b7*TS^02{M3NAZ{qp} zyw!))kB7^IA|;H-A(VS0hwcVKp>6$$l_6OVfD)z$*IdUer&3Cbp$`ARbaSG@|6IWX z_ez9PJkmpxApUy}vL+CW){DXy@Btgjp)qTKZYoq>cyLRFB*}m8itK{H3cH}Yv_&XU zVF5>yf(uYB*XMw`Y@|;wn+rh#UYiztB3r^C0R5uBs+(lM3Qqfpd8V=CSD=14x8-UR5#W%RC9H|cyG-T4S)wkf*OU@NEHK&?d}R? z$`4T5591XC3%0P74oy-gWo-o+qC40RL`J}9B~JnkoV4Tc<~I+hXs7xFAQ2*~nQF^P z>fEMXt9T`b25>_ElLxq3UUFrISm4ezrPYKB@Oy1Oqy(#%kDQZoVxr{$P+#SLuE|Lg zgBCb`t<3k0RKC#-O?CmLgeTvdy`Aw6v-7p(tMyF*$B8wi zV0NUquu>B#UHPi`)&|BZIalk}aPTZ_vI@6S}FtW}`0e zw*8fjjs$5Ir+m!LTzY?z2&*55p+9Y1_lM~aGrDl3nS7vB!7(~%?IIwjeR#TF86>y} zy(5rEOW^yM95G*4N+Uu^##HjG$ges1W##fZJ1QzQV3^k{HR4U4d>I3MO?~gp&yAa2 zg_Z0M^**rO^vaM@^D%GYyVqP$zNqUmGU1#&n$$CSz0YGtkhT$WhoAas=|>%}w_9-= z{w3?C>}5F}bG|_{h*D7(Gg)9{MDN(KaYteGW7zvn(-pwv$}C`ZJn`EVQL;;gm%+|w z^wqS%F2r&vvOUhhprN?6@Z7}U=-DqEOQ@~A_v?>Tz_3yh7jCf`M^>42;qyNsi3Rm3 zC0K5%FRmn+U9yaK73Nx0VgX~$4tQ6ruAZGrUhw7I*qY>=g|INgCL*he?`=$N)Q z;%&w7hSyP5s@Gy5^kY{|Mx}#u$5>e2FT>$de6L%d*YG+mv+1uE zi3%S!o$T@hCTT**cQW2gPkH>A1*Z3CG9ZJyJ5m-ROjjQ^4_l__F-9scQ@%&*ML1t` zWbJ&>kEdpD=zBTEcrf|`2Xd{u&vHvhB*sbx?q_0=8bjMp|l6!|p2Q%j%iLmV^~2gFaE}BgR0aglf;(i*84Mrmq}oE;}F#PXFF|R#m-F3p*yby|Cw3=t5uD3lBR+wjc#8yO+E~&dGvE z9`R$SNO$J9in+TiA9iMH2l-y)Tu>r>5=cL*5w;R=IUlg(QTajr{8^~%_~_4t#!SKA z^1zQz0!zmQEmpXP1!N+Mh&XHSdz%DMkf^9B9R;4f>#dx@^uUKJtmFFJY}^nevn{4i z@B9ofBQiP2j#NO7l9C?ZhgA9chSC;2$UnhAQ*qgjf#^odI_O46U1N*iqF- zZL$ws78dwy>ZR3q(eUCqx#>YkqjT(yHL#mb=pUNe0xqxv1Wd2Pi_VZ((=Sdv&o+9K z-D#I!e|bi)jx~l@{$Ygb=jXPk#|{1wCj+Qo@QtUwMGrpd?q98fGPx0u??sNPet_wn zbtP^MUiZseoz(s?4qa_TS6UXM{E|-;>uSefIFuRUn$>yRf``)N#d|+}FzN~v@HxSA z6B3}_bzzP82pH2QP@i%f?|eMqv3uXRX+meytq@$v0CZ{8Aj0`NPEn$fY&B`@VJm5A zB6qB#;;lRH5jD?#uzW4TAlW2w=V4^~Hp;U0sTWE0Zewo|6Ff1wAAW_k`+mS3rs`oB z0COIH4hVtvP0L>I9_*`!_wluGhRUtGs=nk=k&zRwhn-C zG+W2-d(q=j|v-^CgMe{`-;DNm2P<&<;VlUqr!aUfJJ?gRgY|9I$ zuI+`xf@zCI)|$ZJgWa~?tuy6drG>RzINw9q?L3b`yO)F!{j6;axK`eNWrWPS!uAqE;NVZ%H{bqUX8x1hBCG0` zdC`(ylIp!c=m!IK3;~FYLTI1zpd{h<72%;_h?x*XYUZe4bv@*}kcmM3b`o}^JBt}H zwhU9LEks33)CCZ_oWJ_}F~3C>Rl2-KY6LBOig7qBW4CV2wbf1eG#6hKZVEOM$+Sbn zJ8if0*&nNh@00#vr9maoz+JGpf@LdOWbCFJMtF8;$vX-E6Vxd9i` ztpm~qnY=J>@Hiik*8A>lIU>bCOv5vP#QXoGCd2vhy97W>UKG2ntw3RaXn$R-v|8=C3{_Q+s31I33upaW6+zb|%WEl^_lChN%KD_+L%dfz|d&f*Lfs5WYcR z`t-ejn>so6li+Ckq^_(RU1`NCDjuW2oOvvL1d0#hZvedVg7V>)o^B7ILRCDk&QM{l z$BVM!PRgwWu5~+e!=Wbu=DaOffE1tep1clhbs*oWr~y=Ocn+AdK8Pg#zWD$iPv4=P zjGt8tAB29|ZZxWj;7M-AeG<+EHd`)WP!3cU&x;N~LVOJR@tOdV*&9tig6d^-!1c@e z;3izmKY)QjY{}#|nhf2#-=MaomY^*9`W90Wave4bMvjZ9W@t&yjVBt__fyO?9o1tj zmtH=)b5jc#fb~lYD}ZNVn3=Ju_~p2R%8@X~tGy3-#g=W=CnH|Z#y-_-SLg3cV1zpP zX@`L^Ke^G)Y_0lp7JmEPRB(5A>g%>C0REskc%2*lW$4-rdrdz%(Nj=scg1>sBZ1+a ziw|g5aMwd^s=z z2pQzGj+je~l!Gdu@g&EKO5IKLrYz7Uvy~0*^XQ{QLbl<_DQq#DetgmGn18xJ_8ykc zfe#WJjy}p?EYKo8ghPIS0!&x)qE-SfR0bANwg*^m4-dc*%~vjBhC4w-liMnZ--N~d zIJj*eJ(+tFJ^m$rL@lzcsPHjwoF4rDhpBIjuB;2TjnT2$aZYU8wr$()*z7ocVq2Z0 z11*Xk7TQ+cUUm8XseRyb)a2KO`d91-f{jqr2eS@Mv1}@~2`{@pR z%PC_rSz)>MKgUNU%J>F{h!K^?347DF5*&0slNu1%B8HTXo zak44JgdjV_P1MWh0Af^QbTqIDhpZ+kZ%iAXx5Co4oS+_MG{{m@I~ehb81cLb%<8j6 zM5wftEffib+1-CK7rh;alOk;O@gwCW9{qf^z($#BT9e-iaq=@kB%y?8gkhLzP-q%v z3Or6`#2dO5TAaQ2@Z`Re3=~`KTi#^m*};A%=y!Puk;8IBMWHDY?VpUBxpIA?k|2!J z-Yy2e&fP#IDA2i)R=Oxy1p1?QV>`2spJwnyV{T^ky z*JR6nk_@`|?Ylj>FfooYr$4>L?ZXF@L6jnr&S0B8)F>nr(NR>PK|QLy$;zX5L5P*3 zsVE;qOBJOATRh4K)!}v|gTZIO0DfdoK6eCs%^a?zR=*z#?()NAmDKdcw`R8?i{qf? zfN^!a=}*j_!-Lg=h!Yrv^F9bzXjWg8w{2#T=U)_YF!Fj&E)oCwa55e)rQigOIZs{q zQxSJhpme8o@{t|w#&#O)vN)%~Gk!96ZfWhc5dKB{oBH+mR(elJ)dqu!P?cY$56F-r zsSbM@Wmq-Q4ze-fe<|rJYYV^mmS{v4=bz5;Ba6#Y@fYHaDj2sccthL4;o8$obHgEU z^`vTsLA<Tl!TrmWkY6~NWTu7C>oWNqay3dPx4%-o%)BLs{?KIW(pTTnen!xYpurOV zCgjB5RkZq3?SqIO>DHJ9RNdTTml*z(;Z`IrD8n#2a8{&EUtGuGAHj_vhSQTW{xgi} zo~MI``p!ZGUfEh*b!~UtW&DRSCF*ze1m_#@S{PSyCISCvmsWN}WJI($nMmmMP)EU_ z5WTm$~}?1+VQqe=?K<7Q=;^X3Eac*toxrcZZ^#G z8^`|BzyhpT;Kk$``zMQDYilGAJaw+dZ5=deihZU`3myuNe$%Jg~Kkb{5{ zz6Tyj@ZLZJ7PS5#Dgu5Nud06BbY2#lKGzKz`c_s@_^L!XowRK3=`U`C`A0LQ>}#jI z{8RctZ^fzYNB0ja5T)oLn!)Lzm{AACpK;*%Pq%NS*T^tLFaW|s=Y!etcMzNhuHgUL zR+`pvr^aMPv3G&mj}z$a3@oa0DpL-6{|?TTiNaFfeE8?Otg5=?rnW;&;;~nDUH{KM zHDuLq{i`y3_J^dHv*{>^13gB`#>))fJpV+XAApmR`>6L(>h#LW=|{8u@zhNgJYHRh zS+e4mV)qlZznU`W77lUql4bJ;{ujc`+G)qn9&BAV%k=u~7l+RmQSiIxlFBk`%OVs+ z8&+X0oh()gti`_!K0F70gl2GGV~Biq&X_a;swy8eDnUQqpv&uq&-@`deMDbuKfqIb ztkF6@^oI>W6niY!?y2juB4eA@;h4MUWo~H=!|wK4q5$kA5)@RKzn9xtjI&+VRaMqe zDCIe+tAC|)yZSDjVHY9R47vE^*|}P`vS2Odfm++^ZaMTCAvc(G>%4f5`N1Z-B8oL% zSJ^p?pEGX=HyX%YGhi+HkwRPe^eb`H47t?|-98AZmeDP%s|U(plGxZd9QuPYwnCWU z)|P}chPr)e$Q)!__dqk+%0Mz`4aN1VHO+nHDNudNW>a3w8B;6-1w&0uXBikgg!Mr{ ztqo7Q9Y?O+f`pt(yx=|Plp79sT=6BxEID7Ts}^@*@Ey`@wBfK8w^2bW)z$L}1XoQk zkruG?pfi@%GkmLaS3l+4|8FUGuDstDc@u=Q2taI1jY~DX=s{ZIu|*s_IekfU%Pwd@ zl}(-Xv~Jm^5bbk=G=8(N@Rdz_S@3U5>fK*b3Z!D3T<@?!DQs@=!n6DLsHp! z9Q@99q)gU{)?zB%c|h^AWiV-;U6ZA8wz2t8CxLU}kFuI_X`KORf2IH5Ui5=WQ+NZK z)mVsQu=hdBnHER(2dJua0W25}yqhFfm-P3y+Q)d^g)~6>Bl7?M2V7c`);DIT%cGj= zrh4dp?P)=UEuTO_RYitkI%)ooDjPvu^Ii*Xd_xUS5(&8E1*;WMWTaKaJtksKS>0<5*-rXM|!{4Fa=xKbxwPxi~h^JJtT*J0YQ@CBfo5 zzif2kB#q432&(I>B)B9?ZPSva9DV+^81qD|gLdj&Z|1UG_F18%@O60+kt9vCYet{c0*~1i51d2{-Vh* z@Mkv#XsomNGLUO8Ad=V=l%%DiV36Q}v)E=;WFiZ{y=$-DtvxQy+Lw_jLni6Mgagnk&m`BG-N8dQX?Cj+jkC?caMlZLIUD;Es^6%0X&$eIc4HyyjY8Y4A`KWcHKNdV~}Oc zsWZQ;&;KX~zmrUms({i3(B8S@U{s0I)<@~PS1 z%504$`ds@erM4jBJ=3S;d4(&r?NwDyT4vGWIIW9is|Mk~y8FB;mug`aqOwXC9S7t{ z_x40~n`>i}JRS?EyOBYG{M%4^b>!VZa}2FyQ28vtmfK);s6 zqSGqR$^uZb6=Z?&Olf-RM`5jDFkoN-ayPe)CJLgbRHRtQUvSC-hFZ}ksfMCHlb5=4 zZq_C)Zij$8789uUb1hcq(9)U{R;cSw3#Z&;s8n_!RpeBss_KMVIl0)D$5cN-7UV>_ z%#2dM%0bC?Tb^yXHJ$P_57uIb23ycZhk0ddd*N>xj%m~J1cxK0YgKch(xcH$Nl~l} z6fytZ2=Ed?Poxs)x!1J^sNIUolNqLd2^lSdLDSQM%5_p@qxvH{=8EZQa|J^|Ovwug z00FGVcC591c?JOm%B_`lXvLXkO`7$%2){ zWux{I1yk3VB{QqeX2+dxP^;zu(U>fa_96munl}TsKqsK4j%lJY0YR#!=0p?CM_ONP zF!Ml=Zi5{T=uKaqAT*qbc^sWww}%YZ?-^4?r-Kn-nbfac&a}l>Mhno^-Bvb)0zlin z^%gYb*X+@fu4j@+?Yw?xUFGOvJ%h7T)qw#p_f0sgMbnM1h?V@XCO(6%RSQFVD}J2u zVWx4-4SMZ#aty5xBh-Y$XnRpGM5rN9M@sWKuF0eyLt#og~hOt>K`oLhiws zl=EfcW<}<&WBv}+xo2;tcgA3K!Bx9g_p~(R9hjP6T?OLpAx0uAU5SFD%ZWr6S(Xoc zh|Zg0`ts`a&-+9LWL>S{JJ=K=E%ITnN%qLr7#Iy5atB*EjE8#>8n|g#IPh|S;3O;) z{9r2j<_EFH8yWBi8P0WXbaXkru~|{|w?MoIqNOaDMgCawb2${IegI`|Y$g!SQ+^1S zMz&34DFfP}7ch9W&BaE;!<<*pT3a|EXD)z>&j}u5ZK-bX6S2YdXE-@DIB6A`a~pE9=1W1V*jrfr!uvl@CFG- zMLU*gCfN3#Z}2*Mki(sFZv?nPsL!wJ$YqS^==*_ot?3c5p2Fl_#56qlg|)F zHm}JcRd(TH-pZtSFRvJ}dymW#8{4;Fq$U*j(zVsO;$Ew_?0; zXc28mii0t9QN!OfA0d>%vyBzz_Qog!MobQ^JQKS+DmxH=u6n@IQ^-_s-Ur`o5DlU5 z)W1JGMZ}n%lFs(qp%bn>n>kn}H+3`8Vf};hFm~9!Q=57mY_o^W-9D~68Txl+xxnAn z4|0aOKDd?!DW52_@4IA>+%($H98a6k$+gnw=LijzR}r$plq=ngd}$60$1-U9Fi?b* z2`E+yG53}G(BZn2ec+D1|&c|F1Nyj}^#AkHcQ% z6%RxwJPH&@j|?K6XxPTR5ZG1x05$La3Hf*$gaJ0UYUYJ__KGMnt0TIl10DSxBCBtS zPN|(C*_j2&xoPb*7^Kle+xxA6kH=Oc>q`7N5}C>`WkL%dLbYH|2rEMq zFyL#7NGzg*sDnT@Cr`JAR)S+)5~pB*IdFhDS;dk%`M<4qJFur16)wN1p_` zUy$v;@s2*XzhuderyS~9LGYejz3?|&e&yAuqysUI&{cjJ7=i*W{tVeL)FHT*U!7wo z!b`;s)%3>XGseAVhLao0!v2GPmTW6*DG#CGlj%9mU`@jAF4h%@PaA)g_u3L&DipAC z*T;#htxLbj4ghm|ICvn!lsl+Bhnc(o~9se`$Rx=+a=lH%Xhu)CJsi?iI8a{ zg?0_IMe?xEEBc95eLmcB4pXjalscKoAJ1TwZiJQyyB=FLwkkLriBo+&Z8WQ~!&!2* zsAl8u;9JO?4St6N*;^c}9fU0q19M=uRQa`7OJBi>lG z&d)UHyQZ=8;0Xc|F6LnDl_f(8ES?0Z?<>6eFe3;?vN`P*!_5o)e}|jXKcFOYeWL40 zgF6ejQRHWgyL~J_sewQiDs7C>3Bow77YX>JIWa0SMwOsdt+IHTNJgb6v!d54hfX@C#In+8LH#SS zn_O6-*Yg0D&b6s#+((pTz>I`z0P_4TG&)X=1RfqAu;{6uQy6*cH&lXO?$DJ z+M9b35s{V7v*x?5dUk7va7;D)|Cwe?`XS%+ljb!C)~0bxT|V?kxQRdADX0y5Q;o>`Ch zu%O!5XI9~Ezw|irCQS;&ZH8z#fmT#wJzwe6A6O^=2v;%^3<~~0uwiHH>nu9ZAZ7e{ zr~`~}5G(;EK>f`-(d4NhA!jBK?IB!$0mHN!&ot*JHdyci-1TL^@1|pmVmuXg14?ZK zp&TRW?g)J}3?vNb{xl2xnUze~_x7$>JFqhlkmJx0lfVy@ zlXx^d@d&b~W}+ABMq>I4!3M_t8|8Vph1nyYyNlkFvZbJsP#BFbs?t<(0q3{fYER-w zSZ{9TaEnDb`9znoKuFaXb>3?T&YT#SRu4fk@&?~DM3^=rY6y-``0>*MT0UHUth_U< zBh;w!FqY8;34_oJ9iBT?Z3V4oR>X#X)G$B6ApMj2rl3Zv2e+qZ62ekE^@*b;DaNK2 z(HU*6**VjPNT0I?(F4M1dsy#)yJ?0`UY4$-O-7O8t5uzeshn$@Kfdn^+^nD&Q$|-rgRo7?=|WLMd&9(`RrV-tSeaysO;t234oC?%-~f-|7pAo* zD(*frn(%07zr*)3ZL`gh>c0WZ-7O~PwX<;z>rF^bBkilPqOXj04NNlgAZ zUMyl#qKyI`{}dk3q33PMNU@4Qww931A+$&iVRLdWM5~%HKNn)HOH~u2w<08hZg$bt z!J-3@W?W~RlcGpJmSWK1h0I+TSxq`KvC!UhFn;5{(mUry$s;pW#UPmxV0`O=!mxRP zAC?pi8ishbiSiQ&s3iMdP$(OLHOz|Ip*ut&)a6a=dWL-sL~>SqXd{wm-cI*r0PJFG ztDHqr_?P96*?n@Om70HbM#QK#|Gp!$;it&7gfh??%pQ=@80;ubL5#Mv+>sm-6T}Bb zjR1YHBfUhQ&;Eg?^?pTTF7n_zq#_BbIDx*7yH=BW%I%?`-gnO|*w#T%ji@2!_w9}J zj)yBs{o&kf3MO!ICO0hOyeg=&t0=XU7SaWMiS9mY0Yew403pgNsmvKdq_@mzlM8%*X=BYmo zGAz2QMlP-KflUvhfQb6{CWJQQZ>X_ad2;;NB(OBQi}bg;aUY3bJkI#5_)n+s8>PX~ zt-0}$AVR=&D@J4}8Nw^wBdi5t@8+Vfq+;0!EeSpDQUIeOWM+a#;g+Q6D37pj)7QfR z(!Ebk(#w=*V20*Kvq(VHgqblrsoMbY@V{{+1{vj$CXVli2D1Yr^0wvX!S%0Gc%37L z^-pxHj1XbvdVBfZ677st#Nt>i{D|T2X(Ae2Arx$EyM+@IKk&z=CNdh>*aQoW6^JiL zg@|y4!S9H_p(Yhk)K%96xwgEWxZ_$H^T0sYgUfgln#^3$8GI<7+3H&a$#BO9P!?lF zlMkyTY0Vv2G|n7yX?=XKTWd-&|E@a=yd6hzN7z*N;C* zD~VDMJFF3UyKMrKABhEyBLlU3V<=?WzX6YcAw^?pJR$R`l$fZGR!EH&r6l*rJ7rEb z$DaN55%xq7;2MW?Wn!ra9r&;?mnxf2Uc3=aC-4Yu5HeZq3K z=%jC8vLP|zGG@Th;YxJ2Mo?tz7a;8s0l4q7{#q&C@Eh8l*HY2M=)ZaCcAPuCETWf_ zVen8)!YM>XJ!GNLL{~>HYA7DXmhM-LVO+%gD}H{@#8qsz&O{3xotiMHo0PW{q8^=~ zAi)N}CKbW=7AJ^UAvvgNXb5BufAq?VNEpUf z70;{0KbNG-1PZ+8i0Jbob1`4l6j@2+#H*_lXBut~!NP^bT|pN1s90gCbRUqJIY^q$ zE+zfoJGiV+P)c0=NqLL@M5q~dP1^YL{BAx8KGe4Gz>d}V@d4S>AU%>hsn-LH);MHS zLBmT-X8Zfv2Z2-f_xj+t_OM(MjEG^{x|bwp=rWl(F=Qqx5oq-TcJK~HI9Yo60Z`YjH%zC^0;qfOSRPoCfO%L>cKVdhZUpuF-gPIO(FMIc7E1kF_7 zh)*LCSAx27C}D9};iTMyKvy$2xXZ6BzVUqa&9DD%!Kg=ld4MBfdNiB@^HJI{zf%zL z?uG2oD}Y221&2R49Bwfsf>8v(HnQ?6H!SZ(fP>EJ7udWhS3WgOrA{KGV)ky`NeqAF zfI}fW^$?1V$1yw4uR^I=>nY(8V{e7h|Wg`*zV!I~$*E?yv|A87*Sl)z(lj#Euz?!YKq3hLco6BM=PIQ44NpZJ|g#4xpUsQ#K;XF*1>^ zzHqqZc8ir+(43LS9bKMTLd)=x{B5HC6%GcjY?0ptBk4>Ip$BTet?FD#x{%zI+odBeyk=+#Y0f6zkV713xB)<9h$Aj@e+V_S#~JVF%? zVbXHyhuhege-%e!Z{gphCrkWAtctr!>YY;N3PwOK&{t3KjkT{C*r$R?Gs*(u1b~G9 z*BVMo01Hbk(W4$;7R14NQbTiLdIjw>f&xeg{vLs+9e*s7ow7e$D(uj10}>l+7Y!vQ zg`)xPEzSiD-G49_d}Mi#DmSJ%)*olVWmDVn7>1lD?H}U&tRa0%KZa~-5U_d}; zp!T}sfP3ybUrZ$WPi*h<_c^0;1LdZ25Jpt~MSG~s<-MP38TPLzbn>L*nOeW3eQuz) zbO69?4w6*=j)Mjz>fF{gcS8iOrBE-a|AhD8%1i_r6vx1kAdY1CNNTHU{D2|Z@x~1f z<_?x*2(%s?&;$<3d0LN^ou2BMs-(4bRZJ6-+0BJ?uPdf!3UkFHF8pWrW4Tzz&vGCx z7V@5G_ePd7DK?|)Ij?!P_qw)cz^0rx+kBu{eO_H)NMA|2!3vUo>cJyY+rbO|pid7{ z6HV9poz8lM$w2;sYgQ5kod1=~a+2Ex4X&676xdR2IM@+258)$`1X$-4Vi|zaNoapd ze_y0W>Nnh1L?PhY^9U55=%6XH$Tm`#k&i~*of>1clG28<%P!bfc*BSZy&2gl*e|e1 z^0K{3L$DOkGy2+2q9D~%Eq6NoZDJsM7fsJ}jOSPLIdZ5@-@!sp+WFZTYX4BK1!rxT z%~DxGD$`|9YiavlGMB4z-393iN6G`|GJl*S>#0Eo6(5_KVm(`m{)dv1xs~OszpEuo zWKI#-OZuRSBzTIgKIO;H#dZG@JC;nl(Sbo7rNl6WOr*I;->WZnaBh&3QYNKfif*NG zTWk49Xdu6vgTCHKZvK&nIRU@-BBXR->kHhCJZE0$DX(f)gndY%sZdiQ$I>{TJC|Xn zK1tA#7w5CV7_aM_`Mx5gdG_a*%W1t`MM%!JnUmfNeB_YtQkgp1X*7m;P(va-P<^ir zway~rwHEM^k~SO6-Bfq7d^-}hu>te);LDoidOzwR)8sSU^w<{fSik9zH*G41)Ehp=| zh|hPxO^^Qs!`=j^TVu^lenkMi80?Hv1WrD&ffGfTG7xVfMw-dhq`ja4(~Rm2Ea_u& z#QbWfmtJV!SKw^!Xfn&q4aiUP8@J|j|KZ;5^I(7)VIvF{(R+fyvPGw7WzW@87Z?+JalJgFG(+k^fWVMfP3ofoJ z&)w;wWk~}-f+uY`fsARUy-o#@6!g?TDQu}#%bj6^z4b{aI~Dd!?ymAGTM}T`4S_L- zqLY!OdGR~w_7q9@JWT@F0$-1 zy~V3ukRZXj7rDKXU|1(*tYIxq{Ihav#C*E??5ojh%SFRratozP+6h}&;$pTu-}G9N za;ZFe=$EM+`|n^f&)>#kzfCgosX6Nro+7$PSFj|MY091hkgu!%a9Y*H3%+bTKTdW% z`)u5=22#8+zg0I*{o5U{2EM3NZdlqx@6CLJGMHsZI*8|RDbv9FMwAa}=PW~5(d9BS z#%bAx>Hs)mKb#d`8q5!WEb2}xccy@d+Ntc5pw!6O?7h)m`>`}=E}Yfo3&pR{`Gfk5 zvIQXhN7h?ZV)YpFKsBiysyWsE9m&Em16lOGy@nBn9Vr^D&HR$78sW%9#}#u5LhNqS%Fhy-MxfkAd83Nd4vY&3r%bpYyp1_bRw zwKL7AR2IAm=a=1S>9$StK+?;13}7FbqdCBzpEYl@UJ`(R8g1Ym^loGk6ppN6pVN5> zjtLBDHxzt?fd*4r`r-`gF^8+oLp(dsD2k7~&T!2AlVk8sc#-4M9joN~v7L#eiGNpL zrMfxWky{n$HgRLnW%qmoKL{_m^7QKcCHD5x{}F_JW$0lL#E{c@aS4w9f^;0uwN?L7 z#Ui+5Pf$}F7oZaxDM6a=B{wcj9OHdhFUwfWkm3HvS^t2nFaq-L zGhJK$>HG>bb;5pOY7|BQ$zXh%erlv9I!+MfYqtagRmiOKEU@2|RS#wx7O>lTqFx+^ z4r+6nmhH-(cLUajf-^jrFLC^LBF=6~+jXD|i_x8E&Xhgz$|*In*d21*g>2zW^q3U9 zY?UVUxxpG||Ls^4hZiM!DSL9{Rz0)ZF+EMkz#WChNBYv=(zTQ}mTh*{bV1LciR?7!feO3fP3NW(I{7RRKFY8&kYLrx;)(Sf4P&r-ys6k4>#vi+ zn%14F)%c#{e+eERB<=9s!Cq(|5zjt9r!hV>D<`Gw`$e>0eu|esMkT{WD6jY8=UU{J z*c_7))m)3G(zdbiLvwCGyvj0vo$w@qQ|Cw52VD@9J;@r`o<->C3r}mag9l!29=TGE zMFBG2qf(t7WiC=GK3t^(xoT)5ZzzJ)+R@>6$#Z8BC$Ud~C1?$UQZsyeSjHiAP4^+? z#Bpi<=}X0*sZc?)=tQxO@Qg6Fh$J&nuM?hgsv=b$83ahL$A~{iJ*R@cERATUw2Tz# z`X>ds-Ly?Ci*^_N$#59gS+L?E8zAEHmHp1)Ld71;2^vRl04R%Mrk75aIT#mo$>>1> z;6M^_x(}U+p%x`PkG^6T!f2~-xHeRdY{*y|9E56}5Ix<*1rm-uf>H9VanqsXFOIHk z)|8!i^Zpf9ddW~(>eY|s5CmSl;mcz}92pio8XCjfoa8yWNDlHEG5&a|h9fHckx5t5 zQ&C^8y5}L%T_PePg-rI*Nr`AvVQY{lxy1K6w->3 zg_2>YabW=Qd0Fd5pLb55W8Vn21P;OPw#UJsWn$+3REGN1H#(6o+t%=h@cBh5D-det zR%4uMb(EoiQ6;LzbLQTpbjMeL@wLJ7w83yQyHb6LSen_HU7MaC*cg>Wq)0JXUBfVf zPj2q2!8Sib;8!nh!aAcpg&nx+m<}k&->`vCZgifvx5M&~-#j(6xb0;bdGE)!d{ur- zlH9tcBsCotI>w68QIoMk?j-F=p0>}j8-UTv+y9_S%d}}L4>L~LemizQZq=TM@kfY`rEsD6fM}KGQX)afKd0Ko!WvRsSZHh|J~n~* zK5s5i!y(`f=Mj~yM9SEwlSA8vYD3^$fQ2VQ2uh6dmi9c>=)+)jHYQ?pR zBQLo*fByT@R^6q+Yd5now5zd;K|k%9k2mpc3fYsm)7-=5sB`B)`igILb@88m3M z%lkHjKB%dr$R@9>r2&C0YXYA#^m%ml!Ac~l%^nT|*ks5VEw4{QYhc8~8coX!HS|PG z1_Hq6)z@E-L zzAH)4t^bN1)hmup@XjFU!hY&-OnhI`FRGDp#;M~?>h_jw5t?67b-6NfN({6X67uFa zuycPv@l!3z(Gqs!s%vMwq4wrp73fxo=GyXp!>oczBrqMCSt;^!ZWdK>jM~*e{y+dy zf50CkaNr9ln9E^nx}ogw}Tl4P!i0zA!SUHdeBa5C1trT4yZDcNyRBjuZDe=)kI? z+-=3^Z*ET?P|*ELHb~juf=PgTRyk4b=y*ic)V=LkrwI+yw$>_DL!Pya!zj)v@7wKd zmHiv0B9W>t1S6Cmrj+LF2aRx9SZYuVhZaf$qbxl71wfR?=Ki!d8ZgTjWSa`3FO(^W z6EPfuP^8%EPrI3CnvUQpPq@an&}j92+7PMg`B1mc(ql(ZfBWG=a{C%%Hg)5xJ=cgb zW6R`mR4!?g*F}FV+@tPt_cE>&-s@_ktvqU!xX%&w0;ldZmhY5?g`YwQ_D*PV#936zi!Zy@-Mwn}Kx2KiEVwFAt>vsnMYYz_ z>pF3(JMAu=*ibmv7mjNxFr>u5`7uvjnibsV(H7BI>#k z5SZUSeXR>-L((YXI_9V7`ZCBselz8RIQspp0Mmo(%1ReQJd#u*Y11RbT=^$smc!l> zqf&hUwx|!f>v38~y%85l9FyQAL9O4CB@`irFLO~xX?Y(Q2gL_+R>~@=)OkT!_*uaS z4m&4M)pC%omh(}iDiONA@-^aBv8Iu12~h-KF>xZzS&<82vCctrG*wD7g`?l>w5&HP z`JKWRv8*98$br`N7twtBmOS&vKAn8Cn<7_2a;v0BB^|g+@WiRiS_GF5#VQ=*gS3pX z#OBAmysFnRVr+V!oC)cu7zliz7p%4oijoD}HE*o$L!ueB>b@6I2NYE@m#BwbeXYJv zF2KzW`Y*lFw#h%elDhb0+@y4#K))r+zgqfAUCik^yH-7V&Sr(2ssVUcSDTSs$FtaG zlqWo;!EI71wR$HME9pJig70^$&~_qje~JSb9mSJ?zvH@;$lSL6MolPSfPkPA@i{KP zjr|GBM@R|^$QXd^7@QEK=lsH1ySKf;kl*HK>^HqLwdK5cb_Mwml??3iKkvah#aX*1 z*DA@BKYDGp{iB)N{6yc}8|W9_uKTDH^eXt;#QU#H)R)wG@ZwAXTTP%3GW~daVzMKc zu6l`WpiNd|0jQ{2bkjCtA(b4%Pj@#&;Pj>NL@NBv(lfPes*p{6%})o*XQcP6as9No z@a_OcwSrm>D1zd*aA;s$IfeZw5zS5OCFPCyTfvo`0k$a6SHZ;@zQRN;XRA*|wc9O( zXKaIWRa!#}|L!_DM83CLu~IE-l2x-$^7(}I)CGo+qtg1fnShP<)gEwP;i`2wLApXthl!s1g zvmy_Apb5h$s=Cq2lu!!?oon9yGXrr(e{;IM++qZJnjGT2blD#LFV$gGp~QAM&8F}_ zvc%-aIS~r9%JGg7K?Ty}9g(Y^r;Sfcgx191-Fo0!2k-(xw*)bi*B&A>MGOe=6Y32Z zZCA-W$8(kS|-*LV5az=57*r|30pYmC* z`QfwZ^4skb?7+TT*kJk}EWd5Qfr@j|v+I*<&~vy~%iA>V@&SnPe)eBLGF;e*Ln$Y9 zPYAs@=|J8AjK)424L*+4{kv>4K)640vo4{M6mRn(YLgaoxq1~O*GVf zsRi=d5+U2ptlYs?!o)eC2#N$rW4|m9itQrudM{V2gc)>xH7iBk^|AiF_Q_?FIPy-A^3-p3yi$zsL!_tJ zFn;P~&Cd15GqO#xeLiZV z3_&84H6eL4&R2~f4!|x#o463~XTShztEv9xN=T6Jj*b9@y?xMb3(gAK7lI?AG78Hu z*vxTL#M(R;Cfs@y4Brn?;wO;*0I_F^!Ce)tJ`xcJo$*A1*aG6X zyn!>NU*CBb4o9$qR7WU+hXpiCF-Dw^2dn-4IP;`{U&RY-+fr3sn2#7MxEgJroYDE?3 z7yV2I9dOJZ8T`{PDEhMA=@GAK04rsX&jXVeC}m(5jwt_)SwCaJVhx@sttgY?ALQr> z)-LukYR$eODYbY?dN!i1=q>Nz*`YJlK$(xzmBujN{tt z);7EFy?qsS^qxg(G%Z3PCLNKY2q6tfa5_Pnh%Vz<;O0Z?0t=8K9A!2iV$EzfVS}fZ zO&%h{Nsyn;GoO^^N}Q_$Z>0q4-Hu%+AuRHSH6h<-COMMSaJ-y#!?o=8;J`AvpC^); zRiMUxg6YrFD46Y`RF z5q3az#Q$TwpNqJ}kE@r(QOJj+H0o?shtdg92vOxsrE>;DXXAb&`i?y)DN!Gk$o9ej z8-(L$2poJS4lY(yiTu#nf~J!=i7LzF7&g9O1OZ-Ezn?r`SPW;N;nfrEC+zZpV@*pV z5d=XB1@{*Sy^9Li^J`}-%0pVWa#3>Y56%~Bgjqu;`rmrRDf?lb#YM6jw;X9&H zsYFk3U~xC-T3QgSv(Uhs$6y2+Hf5rH#BI*bZY2N*__HRhBNPrRuWC0}f+tJ2pKNkF zHHyzZbC=~oNEO{7pH-?_u`R8inhNes6~K@9gZ(i2aWAd^7e7T>KIgbBu-jfTA+p5o z5s#O3)y=0-5|lvxLFAgsA1Q9gJd^XIkT?H?lAeI102%6k*6LsQF-a)Bz$4lqpj7L6 zu$yZr!5-o!RXPWe3ERYljCN{rxta37jW4zk|!ju?9Q)0i->5@znzY!05@@F(Z(s($*X&G9Rm{s*i_?Vbu zj>sY)VqN<3WsDkSoEej6cmJO25_$WjS{zbW^`*WpGc#OBQ3LLh!FJ_V+iyx)fbF$h1iL`qj z5do~%7FW~U|7%}kG$2M4uDmOb;3g=`DC=Ap7bp@!uD4)Jn8B#5--F zj0rCL*mb5)kr^LAy^MT$Y5XvlKCr1nBB+a9;v%<#Vr3?B0Y!qTm(-gSap&=w)ihD2 z?VZ8Wb>E9SI#q~Vj}c2-ZwDPR_kuX#D=L|;Si8&4NI_hr>mcMrlNw2ySok>G1bJS` z;ixINa}-kC{4SBF>~wNLUPV zm14ww2ch45*?-c4xEze}RZfxL06=t-7QQtx*X1xtgWU^ne2dv<Vb57q$Y+|#=)JUJ^k2K;dI%{mKh zQ$4ZRH!v|G1eXZbBETc)*{V*$g_%+ga{|kiNsG}x}O>)vy=G3KW?cmly$jfAEctLEB}3n zA7n~I2*7WhXKWwVk`7Syp-&RT<{F1uf$j=h6Dx;75))yR5d*nAyBbt%lQgY<)AGDc zGdujZ=vaOW$&zC1v7fsc3&)-_jFxF}=C#FHR5LSr3HONu5PF4*^vX`A%*`$PC9ef0#}I5|ATA|%xB^7TNcP-H_R6M_9~M z(hVj5a3-xUZp)pru?+Od0&=!J;q=>S>J3vch%mNpN_q%}8#ewvfd`_{7(Rx6u5z6F z$4Y`Tf=DzkQ2hBXq-qTI^Y#K&aZJ(Xug}d?*~7QzYrExIBoR|9vy_!aO`5fdLoY?* zm$Rz6?Ck8QJCD1B=$XNG5_x4+=J?5YU*-g=n z>Tjk5_M`FSqLZIG3E#k!XZN=yj)umPXf~hf$lTmy7o3SmeEuV8-usto7h*x;-^PD` zKk3F|r!F;pZSfxTa>s@Xu)}D=n6OsbPn4(=StVj8s{dpCV%#p&r~Td#7sWbl{gYLF zMVxH5^wI9ui13I1``jXan#i2VjaHzxgo3tOlR zJD>7B;^*HAAe&@YMN<&HaO(+yfL3W(6E38rYlM@T1qMVSC?WP(5Et>z#LXc8Rw|Xx zU%V(U87oN>#Ik-W>2wH5t3kPehKfrQG|L^l(5o|LPKUIS*n*QHaf z?eot#>4(F!$0EsiGM76$wy(WWhAoMf)8%ST;r(f$FMVBI+Kh3pVTE?Cb{QRZ)qa{X z#9s<7%(?aetgL51_NC_i+OIZ2AM(FM%w6?P@oHqyfvLUQ zB=+XrWsqWxUpFlO>m;gOF($VV2bgCW!1)vT^B(_An`)ZVlfSSS<8F|ck%9_u$qhLO zXLa4_D5k9@X>{nvs^g2@#2XwjT}?(X+N8NY6!i}}EPKDYf4nrvWiSR9=U#2qCM0+^ zdwMqK5?uwX*e;YOwcC~1A0xW|BG^=Ie?gIb2d&yAs(2yn-nY=}H)D@ER0LX(oVwiY z8S$wgro)ttt2rWyIO9?oxOmP+5VBjaG|uz!iG@&?qN{JcWlHfc0esG^AQR;?^eAgh zD@Ex2tWK8i1Z!(QR0e0Krq{=(ae(Bn&dt4sQ?m}0LRmA2po(AYOj#rHHrti2@^tDl z+XbC%iRTmaOkYf_PfuI9-f{l;2oa`6eG*+>R0m6SxqLfMaLdMB4`kc#F}Cp6rr!P7 zwuS6FcfA(gR_x1jtLU<^tJ<%X>=7=r0;5}9ek~~}7y~jL%?=3I{sfzhBZIx3)_(=} zlAkqk8b!mpEiOdu&U@tMCNXX-Bj|nt8Z2& zf*e|UO(I|(6GtZ29&SfA&@^~hF@BAxThceez-)(u1pK_VRqxmJMVnru_eUP1W{xxe zv%f_s?e%|Jen#)9V1!w(8uOyq{CJl4p#XPTd#|$q37u$-jL-ZI!uy!KUZ$`Ep%~ntji|P&;hRdv^zw$;YXQ&#`{^i+OpN;_|3q{bcTB!8Fd! zb|p?VOd;j&pKQp|IbBLkQ4>vsl2qkL;V6fG`-$UyPBYrBW86tJhmuFTY3k+;h;`!v zR`K#`gW1&ox!olj7nt4grMTejupoQLm#7 ze%iKZgYo}rTv$Pli95tJz*QKm`z6A1E}1qj$ot2goJPu?Ny&l|Iy|JI+u!%Cb)^iY zmI{=k#G_(&Nj9@Z5dM{Id6(%jhKV5`^yq8bY-7|dJfVuRp@Zox*xIJ|r5fyaFa~!g zXG4X{$L9&aV!#s?nxtn)O4@7x<(b{6US#NRf&=>d#Fc56kVzjDmDF%r(&H$^h)!j% z@yO)lcPZ5IbE-%tMJec=nuNipukiscPODBXYA_d&G>yPwe>Q zYCLM)=N-aJQ}3L9LcHm#zDY6Lh2t+W3m9E`ErZ)9fZC~@>*t%d>iUuh5w)Vd{rks9 zXlSTYX|=iX%Z5=?tPTx8nDN)5gjBRapJm@R&VkL?z8y6Vrlol^dRXMqn4vElQZYNk zv};*6DOo7jS@nds?39Bf23Z@=S<#!h;5ILifVXra&ocv>FNYv zv7qkkU6(?Y!1Q_f247Rjbc+7N^VUi8)+Jgzxyik^KFT-Y$+JsT0K-agqurxQnu4s@ zochN<@2#Gi?XU@A0rR0aJkY|Ya|#PSN{o!i}F}xR>A&S6+D-m{jL#I)L_6SbA}#{m$oRLBoiT6LnNZ)+3ED}uOBkf}rej8LHgLSxi6bGxp1Fg=K z?j)}d!Xq~cz(ic8SRd4)oaF&*2_lL4C8NXaEWe2HHpP?`l3kfbMd%9m{RpgW9dQ|_ ztprH$>t!>GBgL%6{P&F>L+~;a25dk(XmSO!QKoNlmqix$iKgC06!z2khEd?2u1fDxQ=2)P zGcdK^U6ntP$&H1M{yAJpZ$N+yz`C9jV(sD#TTrkL%WXYrJPj!p(~S)70WcrDyd0*q(Yh8@o(9C&-v zLRb`9{Pq@#x8U8oZEU$*^4mQWlkjBW<`JGAj*_f^)Q@F!mxQ2ni0&c7^T9HM`?%D{ zSy){)7%($=vDWO6HX1r8RaC!B$UnZhSt%Y(fJLth*)!Ie#%eKRQ-Rd5!^JYi(`L+w z6A>Qn+qAZ}X0D8wvdVZl72}SD`O0Im#Eyi7)EkVbM4cF%>=N-nPpGiDy1q>8wqR4K z%R@s$!|nab(e^$5I7<{wi|CjmqsqofTR=ddNG@|CoB!i@p`V63N#0Cne0I1)Ymv?d zE+vOuAf?I)(KB-urnMYzipOFH)j~R=`jPy*GHve)*UsQi50uoeg|fUT-xJqto3L63V5j-yUgke5|O{S;%a(XV-hRAl*11L_2*x z2!xZh-P~8B@jC)tPS+Shvog%$(6#!(j&LXJ^9V2-o{H$mlzV!5^y6`kK{qz=?51VU zo5mk?DP&61={yNbbxwJg<8pFwMG^377AP77D#g$GfEd1`l2LmS*3dyl$%SYp#rPmV zgbBCNcYRtM0Hbj7dhSr!kg#f$4A0OTX{_4;WSERM5{NPK+8+QBN7?mn%z#u5>`BV} zIrS~IDh>l|$puVcW1c~8 zunnO$jH(+$gJi2dGGIulNG^3a!>YFU^s$gI?U9R<%MyDd%FzeS_jK_g-EjD-Q6yzM-o~T8!c3ec8&2%jm$n$Q_sL2q1 z_FTHNK((^$P+!g~Bx=aJo`Q=Qj!8>9K0XHdsiKZ3t^zv$p}QE|>C)rXPIo^o&8)UO zeI_njZdi7C`Pq0ndpW$v2Q9miM7xJkTKFHBnHkXfDFx}4@IvvShcPfdvWILQx0wzn z4%kF}!bY0GCG-Lfs_K1W6DsB*JxI;+`+>+Wn?AF%gZb|rM)jW3HZrC5r(#Nqr9kh07X?Co6P`|u*`)w(^GLO-`{t2e%hreiZWGO zn&gkXwXfcsZj7>ZPR2SqNe^6rLq_&_x;Eil;36C68;5B3^z@X#M7jj7)R|30A@K_F zpt&!ObJpq59lIM`ReKTV>-J^E#S-ZSNc;XSU6Y#I=v3O zJ?Se*Vo>diB^pQi`up-hU8r9A6NH=fN|!(Ti12`D-1r)!2M>>FmoM0!dS(>|>D8gU zftt5DEq9IP+c8*Kb5#`sCnt_KMWK$TpHZ+&sODLV{sO4 zo^FE^DxcK3pJsD0?9DMeH~EPesO;W{j1RQW2zgaEJ~t(Cn1_i?l@q66eR;dDo)cC2 zk9L>;)$ZXZkA2r}M;1l-#O5%$b!<3-7(qt=WgQN<(Ktg8qbEdLp3Bpc#*BQh?!bsU zhXx8L!;+{NOY^r#dP17RA*65R)icrKt3FAb9tH063iFuxCX5;r&_&VRH{5wsBH92T;_iNu|y4-#sgdNVd7TlQgySgqP8OhZ6U~l;rf&-J5vNDVN?GGDy zWMs;h&xFa9+#>k}1(IZ_*T?;=)eUTVo;rg{puBio);V|*grEAAT#&6;;vm<(ZjZz#S@h6w7R+b@8*i89x zXRp&*s}|L^&gztUES+oXuPSc4mQ3I)1{dApg)VX8>j}-wO z^C1~uqs93gzb`>vULI(MlgZtiOi~$DMPl#pGIW~mY|G>Dg$~A&gFBg~C=;tUhlPcW zCgh(O8nSh8fJlbjR*}X;hO`7iV!CU4d$sy5PBh!7+U zx80-0YW-Mu!a3T|9hbUl(2|Y6$=zG@boc$P{luM{n}Y)ZpDO{ccB9FzcVVGHo|oS< zWn+FN`R(<|VX1UN_5@R2aH-b)53-&zfJ}qgK!U~T04i}7t&?!EvotSrJp7y$MC*Tn zGb5VBAb;B^jiTf+y%7SgY=c-lQc_aC)@SzH^i3+;$v(fq_&=b00-hfY3k&8~&>o6b z93!8qZ=jA!mbTB`9-Svq?uq1*Yu5kYhsXvsekPovl5Q zTb$<=LE)>?ypu*<%a&SaUZ7Y!d&J;UtS4UI{wf{sENIQf#xGmNcTZZf6a2eBxI|q~DF)YyudwPc2G2kUfXsd6idFRu zJ)%F(;YUb%UU_Z%*=%6-P`@E4`zui_fK$-x&Lz%I)~L4Gt|krX>;k~*wuq|*)^geO z0dP8h5SI>s+py$E2V{=NRdn}QecuBH|LTJGRO+~5hl=(^&G?N!B>5d9^vU!lo&A8@V#s5q*|OwY3gK)OPi!Cr)1*Z5|sp}JzJ{#=z}9= zyccau$Z#}D-ySuW6U}J(C1HF4VM5JKpNYQHm8;6_ls|v-vmv-|cV165Bu?^(7VbOmMTp}FMDvy~!?g5q zp=|m>gVic1J(YDvbz+}~@nm!uTkP^!ZH&j8t5->^?0kj;7-y|&=^Ms!GC|%S%^qZ* zttN)V8V67gcEEMrkF#%bKm+H@nAm8K7IF3s>L*zuenYD}Zgu%Z^S`@FRTcf@?xngu z|Hc*1>VA6&L*S|pN&sv-SI}04VBX+mz#c zrt41EFFcnG1ldfkudylB4XC8Owm1fL*V`ZCC3 z$Eja}j@@HlK2+L2uu}OuW@;T?8g)GzN=B~o00RiwLJ^~Yha_}N1>f7t%c=RK?i;J! zYhm!CWt`%;S2H`DJqnu~TjGPZ#B%IGQMYK~Jro>eik)qyfzicrdntTa8fJ4;7scDs zbk%*_a~3G7bEEGpBm%h#baaps3DTu^Hv%)%fsi33(#!N-z0EQ!@@>2_sDOc6e3lw%5!m9{YGxT8x!4KexXQkw)L1ueTNsps?cIFQ4fD zS#7P|uTsJkNf%r_)JA{;T-*4(toDVW?R0q21Bc)(p!qKz-Udmug=lcW~3|0pEvp?_TdPMfjP& zw=(?YqH}X`@!?q!Tqp8;y-c;Vwe^MfA*SgV37-q${C?yFpTNCty*+*KzM4B?j^?03 zH6y(rf^03~UV`TgCdL{F-gI&)9A3!O!9w9JhqyHYU?RfGE-7j2n4GM1`0t ztMzD~OhVi^UJ`kE46!HTb&uB-9CM`gU}#yL5N!NzLre!6k)u`@Io5ofg1j?33B- zek{y6{$-_)s!73B$jJ|MHUQbWjOpk(HhpH{FmyBT?3$Sp1?RYPI@{Sr=fm**1LEoZ z^FU;jaM-?ui9X5ov7OzDmR|dfeX~Nc&hmU z4J6i4)wJneBjJ&{sGT|DKAwBS_kkl{1y;gHH3esTMsq1^i|Eeq`lP@^(D;pecuEyR z_Zl_EX7>7uzUjO}XaG+~*5>P&jBGSh*Cf}|)e7BxSeyb4aS8ud;hMOF&RQ{ft&riu zEo(ZKoz+a)5BF8DZ>QSToGbD*q)cIb|Og~sbq>HSKOj&7Z zEj6wiT5t0XIXU@M=Z|R;{Wcv&6eu)Zi^nG&6?>x331WF*ic-?jN>cr8VSN05;Z9%3 z$XGw)@_iOfca_6SJ!TWN3B*NP8W`m0RvyStb-&?84*2`~2L=X0!DG_GUvFNECc`Uj zKn6A(;l<8@B4N;J8buu!*tHIBe4o!?s3&;czxqw5UAU7YoYWkg_$>ClurcQx`BHmA zpRF`d(b6J7C&k7RCy$nrP>6e9d+r~qE&bUsujitnu{d+#T|jc%zHS3k4H^R0s;H?^ zl9NM0L6v7cN+zj}t{I2uO#88UXS&J73Yfdm z+H;jKN#LLr$?i;! zcB#^k=@Z=jNF6FIG7JcLdKMi_uAVn!{$c#xI#PQcd3_ii*G9;gvD76*8ayN*jMhE; z$-OyqfvG`5vd8wEC*M`j=Pb-hNRGc$)ImRz%s79jHpFrndEa6$3Jida!%{-#a~uK* z1a#D^(~@O2&6kX?$wc+KIVVFRvg^?7zyK&9CDvNQ_wUK}Bpz9O*=V|;?PA=WZL~SM z6da=Hhd|5vdGRQ(PmzpN&*19qO*ys$KmgXU%fPvMbd@#K+E`pTx8fL##wVAY_%&@c zV$`fT^ezBrR34l+uGH;;E$QGoM8Zm}y+WUm6ZvQvpCW#}j#VWYHNN>GAgtohx8TUq zcRU}akR&XQXCr=a48+f*e5v@1cCkTnf$Z4KeUxI*O3 zNMgv;NeE#6#iS>V3tV-*6Y9;CKR$3wEXOk~`)se-W91L4K$7xxHuu&^g{8k`+_EOr zLh@_7hgyo_Lh&cHQO(D3rDz@mc*}|W>gN+#qlT1ijV^G93}sp_A`y(#$Z*80KjZ-h z(E3c{PRXulia{|BY;5H+XthjOANwOeU&|AlS-b~q|AKAef4~-3fUU&^?djHpSJ~HX z#V8%OnTdSn(ng~wx0)oID*+Hb#!kmXf$K$Z5ORA;tn9M9g{dnGtLPMFv50 z@JK59AwP%o=_|Gnqs(u*%nuOb!V{>TMY&>MNzOd$yod{jumnv}=^P(vmrj!%9 zSuhFk5S-N4KwlilmL@nROA{RZFQqfv^N_ks+C#vK!lJz%Fb{ynlXq*s@%&fcldrv> z6%C<@v^cZm3YqL+jSQjDH0khyw-Yc|EfxF53*(2gD|Yw$!6{}gFL0Y_L*?deB_u{k zCh}Wp?Q^GWYW-lx-x1@BH?W3vWixT*Wb^#R*egrw7X< zuZlB@xcQ;rE!`(g`%idN)hvK(TV_8WWrFm0(=p zXBkXS32+uywECZO3!o!m2_?Wg^&LjBM;&|#VDHB+#1*kw5xYuaE#xf&h9MRGmw|cF zvaAJ$o!tou64z&iVCwZ!Z%1Avm043=eIrx#&D-I9AIvE-LW>8rkT98YRvbS5B8RT` z0JLsF7>7di_$`Z+R5!vHUz3g1vc;|tR5UTT+?ZTG-)hu>26joRtboj}u3{V2e^~PNi8=eZFt3DRPSZ-MQ`i zFN(oS5_{bEiZLVD&JL!=Z`K`5!cB=s+zRmo!yep>q0mA0cEkd?+M4BUSs&;+`wOLpsD^@S&2&lpd=QXSy}&~J zrgm1|)8**0C6;E0)m}U}&zBQrFbHsyRhyjMJqR33aa``=dG2vMo>#Wk=vt8UW29+% zBf z(Qa<~J9HGe*g%>;9RbidheEB#EbC$)!T?BAZa3xR-GC)D#nP?9l|qtC{+JpP^+6*r zg8n5Jkb@STmv1v_c%OF$ogv zFQ4eu#|n>Y`_>_iknr}6bK_>lwe>-8g#ZMoI-I#Jhcia946>pnTFwutwDvRwq!Es& z{xqoscIYC-44g3`*D-_{mT{3YU<|fP94i%*=5Qe6=kF8_L8|H+@O&$H zTvBZ@E$2k1Nl}-hu*lffj$SptgX*-G!3EaTLKs0L%oTFJj*3`Y6zcA z7BL3Zj(URpYVo)og?2sFd;&J7PnNsc*_wV{!Ckp85ninT@(VrO71e%=blUBYYEa?tI;>F?q2RYY!mC@}iB-9M(mY*{$aPPGW-AzcfZM`2NxZ zR+DIyDN~`=6*&vQQ4E%^sy0XJSDegod_sP8 zf`Z0=T636ef17d0cJUf+bUBb_-kiqM9`z0vRYhhWs{W(aqD|~LR1%wBGC2eG+c~6~ z!q~*#W7*h*AQG!^vzp1nZf(`m1e|v!5r_ZH;lE-ZP@;)+X@Jb$(^%WPT5Im#e9rU| zDI@V=psj)VLe=WGc_$srL>rrB~`DKt^x9#%x&j zaW&F+CIF!*SvzoGGDWp%9*Hv_YPv;GFFARu^-XvK$?&JJ-4DMfpM0{Xr=`v4H#^?S zir+Z;WVOF^0c6x2v#4!Y#WA}VS8Dki?)t3(>xYbhaX~0t;k3-a_ie05 z%X!xcWKO@od5PuqzIU`OO+4&J2yy}E03$LP+}Bpb71T=lzmbBJGI zadXDi>4^g6U_HtI%;^2a7d~xDYkLUqiVYgFW#}Kot7RD%pEmSMP+s+Y*^!hlzw`vl z#k>Y4%gyS@nJq0AN*4ts-oLaxAc%PPB5u3R+6+U;^O5`tY-I=FVBo#Xc&nP9I z8v8p^#utByQNA=#SoX|Q%p?%){vt3sV1JQ{aBgdaoFce zpH5(%P>v0nmHHmE`qbR`$s_}Y$>P};RTK%JFO6uFHS^hT`(X}`q+E?pt!tXA(*kE4 z_(=d0Pu{M``fa_%O;#wQ;g{@A3ev)zGkc%n%~Yg^nQn+&H$6>8jtg$*EG|DS2qXQH zmce`-7|~`#`Y#lLj`cI) zhB@!Z$^EELn8fwdgi{KMThw855$ntpKc_2l4spn&05~D6OQ&kBB~mS}R+TKPAgSo- zAh>YNI=k#;;ESnfly+m@qg+KP6p7(RhX0v8RV+AUn^#|`8U8%^uB1DW{9X7+wPU+& zDJs+SVDoz6?Sr?f8mM5atMk@MYy&6M#K_UY@j`OT&Geu zN2EaLaf+6|g&AyQf}5J?#v!MkNIuL&;YB?T z`g7GmpDG(+6o{V43PFECvX#mqZ7y7^@l8-AX2d^P;D@zJq#_gJp7!Gub&jTbDF`_@WQ7P{YdhKC_EOq*f zkUat?3za}DUnq~nzL=AH9ol_rNi8XBmMMyyA6iy-Zwqw zafQ=920)`RQ@i_b=SR?u7d7ItVtA3lem-|WFU#LN=I_b1_Xo~xJK0Q6W0kVa57qR0 z27Z=4h{dP_A1WAtlth!#1+k={NVhLA?0SJpQ?$NQEVo&fFUnNe0OsRTOfY>P56SWfSjl411;VPRSM7@fI6u> zl%)SvDVTX&vSh1`J^g@2g3$hMeT^cdQI3h)+!a(eL^1#dRljAwk4})qB2n zs)gjwA2&~AA89&Nle|ps%RhQq2Qn7VlK7E`Wby9CTKC-33^UTH_IcP*?(u=4z1xze z#9XfK@yEH3Z*Rgr5qFD_f2Vl18{BY5L(7t+1?o7Xa#9^E?xE7mjFZ0K_u^{sqS z#(vbbt!Pvd6;)aD+d#Od{b~Fvj;ZwO5(1a?XcJ+|kLW&l9Hw$rr87tn$erkc*WeHF$*Gs0uh((h(3KUKUjz62FW{J_!yVNHCZbf!&(%^@^&kvcKUDA(u&-MGve`{=Xb z36P~TWTR=y%xL-P!hzxS%)-2_(}#Jb(xB&J-ngZV9v+8w1^ULPp^1JLSQ@3HI;MKc z22RX@|6e&|K&0}ImpEIVT(esTh)0=z^(I5qkC&eWvVoOI9u?PO>;RCS=3+tYlKn5T zOZZrMy?%F>ZQHzl88$Q{pu#CJg)H|LTP##W(ns~=~f3`2| zNyr>tcw(>@DX2Obfi1h{%YxJogg{e~`n2xNs)7NlVpE2>epNnWvKg^|7YFHMW>&U6 z`!gVnf;T*H+x3A>cL)_PN41pBrjgbVq4>+=DCPb$^}B7R3MmW;_$Au-i-4YIj8h

UfRMxvEf^Llo!TP{+rPscKPwnrAMQcDWME8Pg_l`^Ok~RphYX&)fKh`` z23ni|I8Z>;s=knaS^DEhp&G=7aM4gL%q71EcsD5gN*TL=uROMQz8pldf=0aLTsD0; ztdP@LC|e*-0el0E(g=dE86v~7#XXDc_w8Y!)GhNo+%z2nKqKKVDfcG`0>tX|D6t)H zV}WrB9c^F`#Ybk4RE#>+f`x4dD02%37FjZ>qm$rDBk{<@S+R}tYow-olD!Ly-tar> zri#@tH7nnf$tTQ?%#}JrP9-*bTk8E+mI116upNYD!kho#a&C$^V^`h3*&ygK`g!~0 zfk)6odSxjQ^dtsl(?bF|Wc%K8IPKRBJ6BUpt0TIWE+y{HzJPeOPyT z>Xao9pwY5e{BvYJ=#b01^KqH2@kni}OrW>E)Ow`$^8=8A<%#Vx)fYM|O3sa5Jh}cY z`t;PV3!u9#qj3D|+4o#+c6+ixPtcM%vg}nDS1U*5?0Ik>D#m33sbfqt;SLWYkU>K( zpEaJ*PBu2lve!+;aO)XC=d2uSn-h~EixO&X`=?&N05;StyfOY{;%KKTX68n2Wf~q) zi@pvAl0dZsKz5OCRnME_f>HMeY{ZjGXzcM`P3`=Grp-VJ$SpLmH%^jBFfZkU! zX;HzI%Hq5#x3}0|((GtBhN{mP*tu49}0#9z{Sp;+bSFy#g(_ zwvwlvCM!keJZq1$j_e^&KQ22x`?H*G+I@HN;gc==t8@^IqQpo3Ls$M+rIe4jSvM$2 zizcwP?ADpux?6+~#jC4;sqCYL#1uRUl>N@CEyrUDF5fki+DY_GAhc~)V-M&S-^6kj>lv6r@zmwR^HE?U-`p?a?TO{(+@m|3q*$tvM2wi z3Hm=!LukF_uL*qv4G`4GvDW$9Er@0R+fZoyXDt9cXsDpZZ>@i5M9@os8eiwiL67%l zK=~)AfquO3&%1$s7u0}rI{7Cp1^w>d9$K9KU){N|3Gh8Wc)VA}OV_jcw0_7F_Ug>8 ztUUn!9l}R|t8d#u^@J67rzcFk2Z6_P)?l_@cdN3+%@nE6GxmAf!v40;Kjk!ZxI6w( zn4t!F$EVrODVySYuWM1bn6r(y$8Em6^XmnV`~Wu&-?oqX4WIXz^Ihi;3$K5N_?!*8 z8e#R}ueC`OAiM;6(Ju*{ng1|an_4`ig6JU_HAqbtM0!tO!@?N9rfc=Ok?A} zvYJOF7T7>R1iQXx`&R{;Ajsm*1wGve{*S1Yr2_$O;w+FutE>Nx*F5Yq(M4!5z|G^! zzhe4^0=|ns{h7$d2DD4`uSQD9g?!scalv=btp1;asa(iP`FvTYwWWjxu_X8Z>Erzw zumuP5knZs_ajY=2pH=dob2JGoqi{J#H!LS$3yl#2PhpYiF3yv*gt zJUh{UtY9AXtsksr^tQ@s*>p^`blsW|r6tUHqa3ij{B6o(6s%bchCN+Z`Tfr=!+Sw1 zGLeU?_}LI|x{~frZEouT*Gj)X?8ZQkOx=P z!^@=nwsolzQg$(IS&Mf?1A(TTo73s`t1e$@wmrP@_+MuM>A^hgeFU&<*48tr!1X23uL?@^TR;z`hM zo}RauuS|n5!_sR8Yq%POGn)j-t5dV3pyfMsrh9zzb?~F5)!UwX*n)l_LH)#M2ab!q z)a_S{|5X@h1f2SImMQ^re$g&e0^m}J$jf!4543B={pKo1KS>JqD`19-*1?f6)w-;t zly`xHWm1NEL9k}ZKYSs?gKVBuZUm+OU^1{IB|bG<-e1?yq;SN`3;R-KYDZgO07ChU9kM z*zve!Ux8vu-31nCxp5De+D#{5*IwB_x;mkQ+y`2CFGC+Nl6ZNkLVYmaC+JFpC6|(% z_JOOE6p*x==_b|c4m9R^ne7Pf8|h!%ngtE(mm7c>9|uL3>9Ra%Gl^UQ1Ns?t?v!W$ zdQA!W^C-CS)`Ss71XRj#x`~!W|8*+{5qH$X2RRifRgt6n>3QRt8i1t*TmU*BFTi8X zwXEu*ryi>^qU4zT4XeM(M!oHgp>4ZF{Yq#SMZBY(&13oMMg_Cf>Z#+jh$1dNQjjV& zgIVdNVQ@t6tqH3zxNtWMqUR@Pg1GGe)rbFIi{KZ?6UwuRDTR5lIXq~+2iXNuhVsR1@6w;&9EhWV725k@)2}CDpe|GymGFr($9cIJzav zhVj9OY-f1GangH}-q&5#IX?EFd`?`{s_hnKGltY{@j*gDi2p?f_?YO z<@@5z=Yt}aO)<*_-4xvG;*Vz^S;Vt0eElz{oq`MxdYj`GDuev5S z4d0(eM!2q=!g`FWwUfVYU-U>XKGSO7yyy)IgR}j149)>FmcD9ljy309Hh|Q6#KPXP zlzq#1tm6mg6hPl0aXI{1Xo1@A+h1LG(+O^TU=R-x7cEA}(a-K1@8Z3~vGy^go7L?2 zz7W9Mp67EnUqk^N6)p8nWi1b5y~E1%M#hhDF%Hu*8F|d{j>&hD1h{Sk5eO)r!}Z>%Lbe2fGnn3qAUE@u z-Q!=GgITXOi$|Rtg>{7lbbHN=k@6&OdSKU^dXr^k$-BB`>semG4Nf>u>jz>RbOQd| z)E)Lar3IZ?iu=pM-5_k6jiBqfQg{dN08(+?K-v(a2y-Sm)r4aCm0z&O9G&N zhA)KYvpy(xI8A?oj^2vc3N%dtm|_pF63~P|*}U!uKfgiC7j4b3HofV^F(D->Yg@-C z1fQN_K0Z&5+Po*Ep4=~;-oK7mWTxOUk_xd=)jxxP%w{4?Kcr<(gfSCt1>%HZ-?pRQ zob;(Tz3q?nGHy4Z!T8`|_bu!JYi?{YO;%XPA!pw{e+(U6n`L4zSB!d4#PlATe`ZlC>XusiS*ZMp61= zNp8uBdAptF*m=~LhX`D~a>3i24X?$^%+G@JD>H*)${!J&36wjE;{Qfa^Y(8jzL2>b z?)TT%?aN)rgm0*7-znd%pBl8lhYSS2^h7P7zTrSBO`| zao>+);Q2xus(|C$7fpk<&F}Z^gGiu*%R|F(0;e+Ywm#�+r1OAj(8@8BF@=+#I# zK~>3Tw=MNLE#&=hlR7MDn~8>1QbVV`tfat3>q?4%aQ-{L#oEqrV8AGdbC0zv+=g9c z@7>Gyw9Cq8F?<)GFA#jf1Se&2>^}L?egp8qBjRp_D#S{HAtUs1kn01TcTF($UHd4D z@M1O9?PX)tW#gRBwukd)Ew8?jPRg|Dk$xR3)N} zk)-nMe=V*>lq*zBo0C7l#@0*O{7a5#;}CnGGZP~qEU&f`E5Pr0n(cRu?9fEyMH#rm ziRL`lOLHvy#KoP~FNLq*v*FoW>$dQ)Wf-A@d*M1G+>i`l(81z%6`Oy)(f8UBsz|)5gz?bQ}W?zEtv@H*KWX@c12F9g*?~5gyGVrOku3HjoNNf6- z(7-rNS6b%)PQu&v$0guS`W+A&9Cn<}`dHoU@NP&<*jdMJgTiQuRV++r&_iLA=t=X9 zBKeYhPEY1UGxb-IXVdQ8g>`kM8(l<&}he@hw zcM@nRJngC~u>eSSQd3Hu4}a{18d$IGx4f!0N-S@ElKV=NO%?-^K4cE;EXok)h`8t& zsS;U@Ur+G;K||@L^+N=B^KO$xrhp-CtbJ+c1-#=~twkD)n3zpe&NO3?{}XTT_B7)w zduPWP(68(w!SQZn%R5xlZ)sa-pT~++mFOWW(m)L#i_nhB0@Kq1gF$bxqD7}}oHv}8 z#j>PAsb*m8g7{l+Sqbn39w+(-bJT4grjn(*c`22<^4b!Zpdn!hCr(_9y5i`10B9_* z_1xKN-5n15SVn2!PZ#iN1jykw@e*E2aBDjbf5J<+TV8B2^);5~$6qD}{&)&f5D$D* zA-kzfHkUO!)Q7RdU2zr_CVnhfOW-z~UvW*|pFf>pCc~BL(3#eP!>;ZoX*sQt5bM8Y z|J?rbmPdE#DUr6q4)5L8wu*aT?dqsK`EfmtjLDm8rMyDc<+ibd(Mumv4PWqf2R>XR zW*XG~W*-EO|9w>F;xiK$-QZdmyMIVs;pHlpi^jmdTGS|puG;kx?|eW0k>;bu{4!gZ%y=C$cC0a+6-hv(ODT z9YaF>^UJ1qeI(rRYNLk;l^S}`+F7X0X=A_=-gWz@#F0{~Rd%Wj?ceJVZe&~6w@}xD z-vVA+*ajm~Up>#!h0?#}Dozh7<%E^z>L!n>(eJ83nI^O~ zEJDlPwZw%G+jk@cp%+DHOkSFcRaVwJc5`YJdl-b6cuFGDJ_G&Mj&O9QruYg3I%)=i z@i)!lHmiddWe|JzqNdRZdYFZ4-9)EwTu4WI{C796ND*__(4GMjr9T3BFPTqFr!BI&emrj_^=-JYzdS%{Cv-MrVw@3Pj#C9wNT<&^dXSj+?Z?Se06gwZ=C>@ zYsyyP$VJ!_aqF2Oea1)`NT3l_8u&?=YXGG zL~5`3vn0nR+2aPt#yE*-%BqcrF-Df&d(*y6clSA)tB~E1c2h358K_d`)6nP@^_M9SL83%^n zK|7YwIRbaKc7Y$!oysvXSp+eg0zU<^(1VRXLd@I|OWA~f*e4aJl6LHYI4eBVP9uyW z5Vmkt5svzwcD8U`Flui_6x!tN1vMNF4j-G;SCGN>k!1fb!UhhD>?dS5$FYaF9nM#_ z6)2sV8M6BInZCfM@-IOXJG+Sqo2`(~M9LYQW?z_4u2HYHSQ^b-swg< zB9}i&sRnl|sJpjt=q#XITl-_L-wBV*#aBN+#$W%5_xUj4fIB3!EO%Ba9a5fZ)885| z3li&XfJy%f1uLQV3$c(3S;i(kVJi7LsRD#T2}8lb7F;5&6Kj`k zu;|ZHX6y55m@Jj~lD-au_ekJjxHB}k(D0(mca(t;qmRVrb#s>UBZr?X%& zvE>&de%7`1o-k4 z)e%0nzhL$E>6JUb4j7u44k{>(|3lk9MoG4;U7&E6ZQHhOv&%-8vTVDni``}0wyiGP zw$)|3>gGOs@AIDT8{_`G>rajxYh~t&cp{!>&KWCXsw*rIkV+pua-tzc=f{ei47g_Q z#sNe$)Y&u<+nvMPb+#x(5DF(iBf#Vjqrg$i$WHKt@q#*8OVT9N{>ZggXmvWa#AvTC zUk}=DIeg4(s3y0RtJ{h`KH-0~N6dpeJrDXaOMaB26Rp{FOi~_upXR*1H06UNch@6| zYe^O_y31}~wKg*F+Qm{oZ*oF|#ThQ~+Rq_WUk6ZCHzREvqjwFCC%1!-8}u63?soRD z$dA$3%otHU&|tiUZ)`3&A12s*__Y(+1g>P&UEkQ9x-JH+Q+GD3{h?|{R^vW+rCsrm z9@`f4{n`LhH{@?djTkzr+_l*I`E%`q8rACe)rToo#|lL+J?nv~!;dECr=vl0d%vFo zFyz20CSuW>01CtMty;~=zlUg%HDl~G@Z%~n8RhwPO5LFTa43+gi$7+==!K~+q_pnd z;k@;^7=9tDWZiQY^#L+;Idk)BG7#-HD6EXu=Owh<`iq zQj6ICD~oSHL5gCGFe(rm1X0EaZ(@mndb$UK#{q{kF?#^`O&2uka68_=jUkVDlmK3| zK^#C1JP)lv9MHk^1N`O!@}DmSh1vH-A&+tAk|u@$o)<-vCcX>@Uex|?BZNUc4Z&gd zHxT}rG2p1fucW|>?Ec?wK}3Q0(`2Oivr+aan}1rmOZa2W+i>%i@_iMg_6Tl2+tAQ$ zD&56!D0@rmpWk4UR3N_0-v)QmfS`*(cQCE@k2G z8}84{M;-orE*5&boPORS}u3xRJV8ow8mIm zE<$h?|LMmx;4AP$z#)2cOKW^Xo3&-fQjhyTKYTHyWluz!gjm7xn6AzHwl0{Z*} zKzok~+7r2c>+Qa1=8I2xouQf1HJeZ$yo~Uw#G`YJ?o$U1EH&B=>W)d-DXDu ziG`M?>r&BqjWqk+p&)5PqE{%f{u-}89Iq=6Hv8)r9-m?;C2kNUufb@W&W6e=xmI4l zlgK#YlU|9%IS|O2AIM`Q0$bIQ6ws2#@iUTEXI^YFND`Iby(X+Z?R2uA)M? zIA={C*&mTgUBp#1UHNwvSX^F;>a*Ic9+bc5lqi}XLO_S_Z=Z-M3Vr&Dw8M|9+Wk7O zz#6)@1qP0Qh!(HNHSl6uD~ss;#C6Nxx)oE!hQrl9$BUqBW)-XtgBCs|{(<7QZai37 z>JK+|<$Sh-ONV|Xwj(S{G|hr#wm^cHyNAiMXSey#kY?u?`JJ&W(cbar?;8Gm6Uh4D zlg3}(*ZN;re?Iljn}74T^Z51#j~HqIA02sl69I^H?5f&mOqvWUH=D9yYgdP*?5q9F z&Az=iXAW=>|F>criV<(|AIE4ey|}~q`+W5FQyu8|iumH$41I`FX7rQts!z{R5#R%% z<+K~(5nYesl*O6GD*bn%<^BSp_6ht~F^JcY5Wcp;6O2e|BloUIVNrm~I$68dtKpV) z_`4XZoNO96u(M$XIOr6;)~QK~g?JBsTG8pWkEZdN+|X_=n}<7vhNtRx)@^>|0_oUS z%6ISyU2`-orLCx{+yh|UuRa4Tb{$?eBaKjxRN9L0_yDF-Q>dEL7=?BSHPtfpHzJ}m zf#t~!+Sjqz%*BoeH(qq%R%tFjniUms`OYTY6lP%M=J9~%| z_)k3nZUXNPV}~S?w!gE~HQuc?^u8_>L5{(e79@X(8FIYgNo-8}RZgGOOV&W-k8?uh z>hng&@a{B?nWv~MwAogAZZQ+h$CK&)0jZ3ol;_-#_s!a9D?E}%D}``<8_0^2ossgs zW)$guT<2~~`b)`g9w2EzH%l@(j!pGO@05)SSV( zLqDKd!kzYG$7V#Z*K-$jJ#)BE0p{ganSGH(qmWVp~z3Pkl+l@ zJ)9+Z>Q6f~Q^{`HM&{+WmSc)7xzW=?(Lwn52U_3wD?Y@0rylPzfa5Qd$*f$TI@H6O zC#17&D8#TOhNseYOGjbd`|5$DxFs)*rL{w07VgolB_>#G>h}TilzsE>X98?OAYzqe zEEkGTd8}0b?b3jjFxEBxr`#LIdBUICz7!G zRC~WGP+1)U=+RWZj=8~Mqu-rqeZ%+vG(;cPP`=c0?&dh`x(BVbwHc%}vB!VU>{DFt z<9NzBM>p7_5s6=pBeD&oTWd?ob}(l$DqnbRh{8dHq6<8(sz)3zu?Zs0TLFqF(*)4V z>j)7aJWu6V*2zjIrhVl=&o&hMz(Lc3e{#uX@?NU=+Y{;s#oiEC zIz8VBV)sOul@-QgFL`d}x<(1N8}LuNPYD5bAFkaSGrze#_*NGg@R*}zMc&VpHE=zA zjdttb3iyt0|DF(zNYCmJsM&@qCY?ichoU0tV#(y}nX^mIvbs>FqCh0##nMcDqQ?>DL>KXDQjvavIsXXlTsT*oMnoGoe$ zWl3DF&&3ph1XJu*Bi*B(E`}-)ZCOn0ZQJ981ja#{b8#({ziwujl$PT_=N*blpo{ZS zEO2QpRIp>lq1;;B$5FuoP%5YA<|SbgDeO}(oHf>!l$Y?esfp|(nPnb%5?~Z9p$6-o zKtMQi+Yp)KcHHjnB%%;XU0-*?S8gdV4UT7XoFIIAh12(e^cvHx`{G>nl#R%~QiCV9`5*|_e)>UZNJcW$`X%2=Bs#|ydQ3P36+YoP63nb`I*(Pss!%E8l zZhgkGkldahIX-|`niC8Jo7^N5?C}_&SZU7yR<;@hhqzqN(4%GR03D3>=S6S0%1)8q z2=yALv9o5buA|Vp+x={g7w}XqBhFe8jUf&F0IY6JqQ!D6+$dj9QfLUqk%9Xi1ij9p zU2u;UhZtmlh_(@~*}$t0@_6~w!>}W1WN6HU5$5(TJ*@Hf$XYUtKObypoaJ4ddfNiw2KFzWQEz&q`X}D$>4gax@({Di;BI}J!E`A6 zc?02n9~!vcXpPz_nOvi%s(=~4&yq2$BEgu?U?_s@)lq6|%lK{e1Cu3-Vox>NIzcX8 zxxXQLH;cOjF$wD0M*i~hG5W_0%~uWL9eB$F1i_JKx#;#D1E4xkIa%EEBMNFjy%Dav z@yc}4_OJj{hlma=O3?$jvT6YFj z?ZSbDt-kDM`!|75&y5%bV;NvB?!k550;*s;{0~^HL^GUeD#T0LP@%Yc=7c4k;)ueZC;xCjk-`bjD#!;J)8KF*$nT(u4M`$%X+*ULJT|kuy zW4;+Dlq$FQ%Ia*8(%3u#4;)o&$AtzizibaPRehzuO4!)O5&h0LxC=_q-{b@dhZFW| zuU&iRB$tb97yJG57-IPJ_$*za>y{40t}qM*M+~paG$o}#YsCi;mID>4j;ehTjqEkM zk9=F^L951}NNJC$xtfZ$aNy}epcc-OW@I{ip`PrU(B=ij{>X-~ioui_hzb#t2nv^U^nU|L$bXzbt&IANyL1v^0n+I2QMvWlslxrE8zNXVx<=5IoPsv@E4 zCMXo&4@yTlTW89pcBLI)Z3kxCW>>q2*kP3rH&~W!ZsW^ zXKI#Q5+dRbcqt5d#zUWK)=}M<10hR@MC5shk>zpP-?B4>y;q+G=D^#FH*sHUY@>=)l>sqbgnm)|WdaomQ^eUyl+^asg*$8@_K3cxe z94!%=IjYO6Ni(3U-3o^9)L8o{a7l@kjguMN+|Ai3A;b}2I*TxsCvI!x%zNFdD3_k% z;zPG{A^f|><$id3ob43)zp6t4<#j`pHb7lf&F=Y;Q{=P)jDQKC4@4KU^TkDCXUQsI zNJ6WSp{7aVhkD+UM@g6choGo~eF%u1YHN8~~AE z(QSON6>wc7#oEg(Uw2*ogZ6+OYK4r1i@qG)Z!&58{rPUC;B9v>itAx&|K%S4A5H**BoV#w2J0j1CeIHfQsE_P)pVX&KRtm0=#+fd=Nr~uqQGKFP^E$p zxl!8X?`H-RAZY;xFVyZDEc{IgZ5W92{p?(lI==|KYk3T#y!f`3ywI_20Y?lnP?7BR z{M}WT=viaIJCVZrKQ!8}@VoHgQuBMCpy?n7e@l<>)MuPHr`7@`y^Vzwu-(2cqqmh{ zh_|2?;rrF`rEq_n!vWWDo?OrQ2*}96c#H` z84(ume+V@oM3(sTwwvh5|CX8>@bzuy>u31iatPoHRm@`>3AiKE-!1w7lW6+ThM_K8 zb)k2;fXdBZ!qx@;U&6>Dq=2~CUrUl~z*Yj^{iFTBa|F1oz3aCRAWgI%Hse&Emownw z9~0r@0>rRwB5sm=?cL4A@8H&2on)N8h2DEn9`wsvx_;zTM6Z!YIg0b-@lmuGPLC%( zno7AZTe3A0yregRmbg#74E;WF@^50Q#0O7j#xofF{n-0qT!91p7-oRE-eLW<1FhxWj?+cQ?EuY<#lYlLBS7fPsh*>99gWDF36_~xIPE+ zaC0x)HAV4^g;;x44I(~_J)waG%co~HT|=SG7_bQ#*qdcp|byr5pkOVCaI0S2ajkTD>W)j@fM4QCz-e2Nv)2 zQXc?5by|kcqe2ewA1caX^9~)0Yhkznv5XE!9F=$>8k<}*IGV}cUa@^Ai{C9{Q*)4M zG;%3ea%PHm@&RsIhZgJ;vBsK$I(=Resj%^Y7g8m8V;%oOXrvNFe*(v$27h0!Qa5?u za{in0=Rq5Y0hh=Y53rw+I;jw5lOKP!-sHZ)bsDtEb18J;N+T#mM3$`jtRNidx7o|R zM@NRQwcPB)(NPFC{KeXq9 z1Si)D@ulQ59F!%r`DhnFsIK)$fXN8%Z4i_xn9=l#UDgHi=xFBPjwLy1SAfOWxqk@n zuGCghs>`}Y9WOh%F-y^UnrkaX*VC+bBd42UWe%;Dt2c6>hb#J);g4U2$f=uq>a9-} z9CuC?h-*i2COW1Mu9lHg8nTd?yxc1pz-uyI#uH1p?26g+a$l|SZ!QGIbMUYQwmJ=5 zeRl#>83T%l0Dvai!eZyq)K;%KyML!T7u>#UurcwBobd;Oo`g*uq+Jd+PTJe4;3k$4 zBY#ba^=G=uR-aR<>CM*`V`efn<9mU4ryCQ>U^a?pk53BCogVkLht8F~F4avswG*X} z0lW0>UbDk5h-eYdg^k-V$pUi;TXrK^)C!*nl$$(7svk+zxiDbQ=4{_plP`3+%^Wxr zMd{FejRuX$8azd!*W5A`&>d+aN=_O3Jsu=^kuwIc*5u~pj67ujg`&bUA+CH}aB zb4CfLV+5)&nh_g00n+>`1=*%jVURj1Gg7^rw7HU5Q&4&>s8sIM+2a3^qK#k!OexAr z)%sfy>Nh!5s&ycKu({}dQuALS);lHQQWG7k%OupuxY*!){4hcD$ANX>vq2{`UF;!_ zchZiQ4SVqxA4-NZa`!$0#^FlUYw8Sx&|sWiOd@6MmAniAw)OZ4HkUEJ*CJYU(l!<{ z(-f<{;A3cC1*My__8Lo6|6o=-qVoq^;pvjuj7A=rTnYs5FoOy@ta`fbXAd+?JtCk4 zo9JNlbx$D0?jn<^R(GmkSRLWmb!%Yxe)G9=6AHtmPmd=dPG1Er-6t4*pvCH34c8%p zWuf!7J+qlsGPK1hto-Rt)~z*B21k`c7}K%`v8eyXd*F&#Q&7)K!lu8Xw+ALQL0KK_ zWp6zwbj!qw?;Xb<$E|@jtg;B<5lryTv-rcHwNc*`!7!2w(iv^&c{nYYs zv8*1lTNvGWT9!7`Xzs)`k%cTzNs!SDKpHka>n|3~c&#BbmQ5%-BzV*^;X0da& zS<&)NH2!AX3IjPybotYZnAzfs|A|vWEw&d-FfySwua4pGR#+WSXJkBI8veViWrur@ zW??e|+eDS@KnH1{fknvJ9Cv5`4z@a*Hdr`Xrp}0aN^O;781?8*tr$e|zJNX&O(1aH zvj5In3tvSN@0VKM>;?&fVB~vn=qAB9JW;ZIMW!*nq?HqSk+pJELhKEDBF#wKYp((` zJ@>S599Od&EE~RcDukkYe`Okh5HQvZ}Vx*jQ?;ueW0OMNFm5QYu; zachK43>mL&xAB=o-)k(dG$n%tsbPH0poc=`LcHnhgoBK5EQK&yI0iBMJKltVBOc8J zorZgi`!z3~Xs5xc2=-IWi^-Xx{jq|vUU;Avfsq=IG>KIRZp=oYK!WEH-m7wgzJudDvj zmCr*28Zxoj-)O)KCt|+TO=K!8ESMKQDXf>Yx(m9bWwWXzP83Fj>v&}19If)}x$KSG zRH{wLZ+3z&rKaKl2l;dI4Nj-##Q4|E{NkFwRu+v9OJMd>E3;(+6=_1KG!Tu5r@`Em zYu8?e93AnF$ZtLfEw5;1Mxw=EvY9n)S|ReTSqkpF&WwrNzNt_$)r(S@#wINry6pB5 zE}fT!N5Dd;6!=LcBBlHAQkLu`G0vbKK8MX^|B7O`YNNEI5~B>WRuMMy4xnvjo|U~Fm>(q)ly>{7iKm+n-*BbF!Y7< zu+g#V_iMsluyApyWCSd#GP_rNB0RBu*+9(EsDd3mw)*5@+Yw8ZawfPhxf6~1 z7V4CiU_wv(}cKc!_~YhEgSg2t1Y)*5vhK z&+w==DqOKkN}u^@&|SJMbI*J+6lhdH3;#7}SeE$cb)K!Y;4-6Z|9#<6e>AjWVRR+5 zdc_-Zp0if-8Re~=J%D~Oiy_pbypVY+cin}L6kGbiY%CaROWj^LXr-TZ`_ufAFF&uX z?J@s{vWYR%PfE(c{^O~Tyk$C;!5=?4V3U?H@CZO^fBgD^{W~OQIZw2Plor=U>o+K@ z8@eTH=VPybwsVO0RK&!F9>TX;v(;EqiGUfWT z`0Urag6JENmtJchW#xw`zY$8I$CFb333Ag}=W3=ZiQs~T=&e$Gy1lr~UP_+yaLhn%YVvZaio zzA|;%s4C15cochVxP90KlAmP*#v#bh2K(`3n|E|qAZ@CMDe2TM)U?PHRl+136s+iR zs6pWMcmfdvNFG(jtYuRJxrl8J?v`)-^HkboK`cr98icw`SI!vKM3LaQ8Swp9%H|Z| z8qr^}DBn#Gm6WQ=0JPp^yci5ur(`;8Dxce+n)9OThX7iY;~@ADWYfyNV6`qK^9$6c z_MY<9wG%yMIF>>vEM@5{VQ3N8Vcb@PGgKuGBVog3{PRXKjVe`i$MiL7@*1Ha?5snF zMn2*{tGfQVRbx3Ie=2+%T!z&iz=OeCM8ZCHDD2oK;$Sxd;YwCYYu&X%XgC_jP1yPQ{GG&!SYR$j|rjcVX7Q9j1qkwK*bH3)$dD`3T!CpWx*P zTK*Hmhn2UfScO~`HxmE$A;4yyKOS+-uHIQYHcrNoDx*VPI*xzz%tsaj|DWR%=kie) zH*38naq@w_@Sqv9Fs1zA7_Lf9mAT7TZ?2asT9CD>DWwHDN75xsTMba&G~h8)#rI`a zH>^BuahpL`g8eR*ihtMSD1ofC6~Z1MEt=fw%U4p(J)5}R;8J7=X+W)x+_;btTO!B5I7()3vEo4`;b0E-F zBFzD*mS1+L4YEWd`*U3(k*O6~$29Unqu;EEYhouL_9oSm>60soKaVvY>yQnD6YQ^} zFLc`%)KXdI;CI5Co`ezEcfajkl&Xi6h!85C{$1TV+cr+BM9k+=BuFx;p6T3Q3B>3s zb2LySb(!Jdg2P!T?HBVw*e;`cc(pJ)-^lfMM6Y)8`A4u8NXY!v&B(7L1pxJb?%dFS zjQN%bYM=qbjHJu~y~3=KNGRd`TEcW8K@#w;3|FW!-f8Ni`rU=Pt5e)sDmUKom$;>U zmM{s3Z-6POloVr7ioMwIACzBxE&H?{m*)YE0wc#t@?>x)R~Z42d-uLf|y;} zP+1m!g*<&wM%$yMNFC~8(!J5fd?hw8th`t;Xp()PvCut)|JoagBMJKbqG($1XBfKz z2Z=@}q-cL^_qM^0t(i3IEY`%-zQj@#H306@c!VDln`+BA{NZfGf0Im)P+3i++1G_+ zR2d1mE}`!aeJmZr6ehC$D0=}-*W!gY7&B&IJ>QYN8h%~dlJJa*7mo)oQRm%gcpsrx z_1=dd>&RKt`ZKQZgCv6V`4{L?PsGW-_tEPf(2h(+^{I6x*+`*-mVl~6&41xe@7iXy zv;%(;SyG(HW2GT&76>S_{5ULJ*NDUy72hFaIoB>|AA{?gsG}v-!i0PPV;u=S=0G;i z7jSfLTza12#7qQlBqK##`|3&h1BnHXBGL3ZF8Vc3W7w}KyWP8w)M zc34G#+bYBF64k8r5XJHLjRHQb)nIh}X0sD!q&_=gnBID5D-c3Uy$jq3Wdg>T-F*u$!s z8_U#Ui5@#~@tfJyZpzhp=9Qk&5P_z8#*WGZH>1MM31o|RXXH@tB5ylO8y62&k|f5# z{_79~{{-xrD339>V{dyfTGnF!ssh_V`F2nDmUfFTS*&5WP6vju}%kQ#fx_Gi+nZSt&p?JPdX}M0B?u} zF?1I03nEz*eza&_QOW`TDRUAgNU2VvBCk0dLLpEF%IL7C-+DLT- zKt<`T4DyVr+elV82~-bQgwvm6%9j3&jfC}8;KGyKRfy&A&Ms>o+gVG_9&(lt-B6;Y zf1wIO_B)2B1P)3MSkq(X_k0^c@s~+J!u}eZsD(P*?7-ec5LDUN*mf0}+xxM-@hHRB z2R8m4sDl)UYTKjB4_^x*d};XiJ)2noF_@@gW_S94nJHVXi9yNsviEvS2HjTIA;l?}G&j5Fu+Rt@Jp2NR=$=z7T96S~Zphh*nD!aa|Q!)GLs4 zu5<=TYqG2P#@Q5k^l6QsFD+ND(=CJ1%?GWF3b^x^3_4xQGhvoT)@E;I@l?vrtHBfOA0_hq6vP9s| zWJ1W&FKQ&FXZCE^0jA&nI-aH+h-08cu`H?x4tOFYtJEa6@j&cA2sSUhEQ0+61C9ZAr@Orwn>pg?uj)=y;`}*mef_+lv7%r<374x z*_&!6PP40^yXfUj5ri-YjHJVvjIo*2h`UrwB?uWu%|Jk&8$QSZ&GgG)vS(TR+HkDE z#6<;Vr-IGy5}xRj%;NsrqYo%742~$BR0Sm&GP&ZcaSoF6SoSC*1rh$I?NiM|x(1ZQ z!nd)au*h4=D#EveKO(lINfRp_lnLH6v+gr_MBc8p+Mm-*1m8X8qQ|v-vY*68<9+Xu zn0h#Xo`4w{9W)NlZ9l;@kgVX`*U(!cJ`*O=NjuDgknE9`xF)kZXxNb%6;qgvhGR&o z;ckdQpfy8%w}l3*f;sXpWQPlbAkt3N0A;1){6H&BNC%0$G09XJF34kLK-^5^_+V(j zU&oHvRTokLyIWEpu_Y^&1UB#d)1NF~0#=+9Y`dy-i`Z4q_tN1E^zKb$Q98FquCLO@ z{Eq6kRBcXS7fG$*(}aETcH-9Ir8<||VqLGay+D^oHcsKZMnrLz?DsKMJf zTZqmo5fsr9)=Eo-tU&v%1gc*^-%l&(pmt>hu!Sd6y`UpV(7?L%LE~CsXvbl-%&6Kl zptUuHkkBX4E^BvoHy$ojqTL^Z&-R<>Ra__fZj$_p;0%VrD$AI!eJ|1aJ;LeYz1^C{ z)UkcR^{rB4JfWZ;bH4_(0u1OPL-N?%?5y;BR4UoF#+tvY475&zyE(smv&YufPW}vN z(Zg1~@9FM9I21hg)!oS)8kM46%3QlmYq-ZAcLHEO%=SsQ&n>BQuX9`;W)R|!5p__S zSKyzRrtu8ZTK8P?(6b0(R_4DBALx%6X}u=r*pRpY;O@N>jrsWMHA?uXkz_q;3NJ&K zZou6!z=C4>#8(X-T_Ky9C#)8Xvxps8co1sw?Olgz!63l#21n_ox<0#gchL*D6g$zP!=v60qKA z_J!-UX`+>O)E0q>9r+DBHl))K*b4yCVsaa50ms2~K%w%|yA z<`8P&u`Hi$p4~_sTzZzqjw(-U>u}D1Gv;6nf@Nt>B3yIe2iSJ|y_1rWao|S6&=fqN zcvW}aV|B8HXg&s!gwggbo?QR7`<6vRLt~D3k!V&~kIX=*GWb*(|b8>2Ij13z;6p`T1weM>toB-_)NFz)FnWX?Anc6qi zYqE|#9DGgviEE4j707`5L63){76&8iKc1_9QOV6VB%d+P@;SNht1!ohOjfcSr!9^^++~<@B4P47y^k75|n9b=~4E9%S z@3G^Hj68|17bvV@H4Bf0yQ-8TfwXcdX&fcz`q7=t?$Kfeg%G z=-?RM{d=L43HC%GvP7|M6G>TL_${p9Z#ZEuy@XysYUCukW9prRv$cF}#BRlGWOxCJzIt_+q)%|8m%+f6U%WS70Gq4D%m^Pe-eH-Xn*6xN>YN`c24F=& z_%AO&K~N%4;X$|0Dj7Q?><70t?a5OGC!|Y@t%ja;LIzrQrX$&8uTDS1e%kJ?Y{Tpo z9D#{bD#k*B%?{7oc&e}8>3Xxm!xH?CL{~@gh8g%3NHpX%GuJrG=BLA;)9FxH-Fy40 zjo9Ss=1fdXfc{Db+S)Mkx*n$b>n%j2Ax#W?I8x1MDYAr1%(JC0QkuhM#>U30jaF_p z&rG0sV7wR#$+{DX)#Oj~c;=L!!`~bB#@}$v4ykQ8kE#jV&1n3 zO;53~T%dJT8p&#uk9?mDet(62f2EFHE|B!IZY--llcM_BRkeF>q9i@B%?~8{(*9gw zy$1fUjN<9>A(X>U52zvVk|Z4au%h#+?aB&M)m+Sy?fLsq$;br3F<-d8De1K$X@vcW z=>dxoGHRfz{D5={7Jc)Ad*6TudfDQ(GW6SsyAG=d&S3XLBkAnJ6+i?(wTnQbhAdIL zQ~=P*#7O-`HBo#NK(>&8TWcY+2Tyk+O)FQq!IFd|KPm~4v#xxsXo>!;P**`mW&a|| zz7&1as2V<^_JO}ZLPG9Surs2NMU$$qtI$oV-{enpKhW7BR6GDL57VfWhwMJdQ(snQ z)mz$Y1qFeSpU>)iDH<<_Z*9R)&(BP6pM?(RBgJOB4N~{` z^J_`#hto(%EGNZ7OgMgAM{t{>Q|qk{G%ue46lv(#V(>nxRl5_@WwG47CtcKR$*6ylK*VPAz5rB;Uda}Mty2FH!8rjR*iT}6Om+*4;d z2aYbvAnZpSWK(3bMEVk=>HXMXaW1U~+-8SlzDDT4Ph*3Q-~_i*!}s@etV?wk+JD4I#hI2?$d`f9Z(r# z^IA#C7QJRxw2hFQ8X}sI`ad`zQkayBaGP0+n@k}kdcGQ<+c>0luj5CI>=A6SG4+dV z2S2nn4ZiI)Rh*e_AXCWe+)QoLLhX{mJ{VqvJbcDt1cH+RwVq-k zj;WnU`HCFFp2HGXQtIY9948fq{PGxphnux^i1}qp&Yh1S7#t}G*{i?4^rn!0L<)PG z5*7z`D?EP`Gf_O*Uk3ex5gzvo3Hv!q_}BrBNQny$zqI!wx>VxMCwA6`C{TzY4kD~Y zu-5o!MO27^Ijin;OJItzN~{6Q_h3(Bi54_ZxxDOz0^NP2$x*e~(p1s-m9{U7x>}Oe zEW*RX@q8C+tY4Yzy^usnbSd*;1Y4S?tr}@JJAISe64fl!i%qr>bt*ae`8({Z39Ag7 z&t_iYi|#YK-gcdvH>-SER8&;xad~Vgjg}nay}2ycm&eA+J38=ZzqrY?`5w0a{-CfP z>{5)Ztf)Z$DNY#=mp|l}Ku<(C?&FsikG}L(f?x8CK`@%kckBy{RW6$=!vP^GLPOFvMWLpYV+2 z3xqFi+7D51GgzywU)K%`zTrUo68IgrBDbB^;lddWyPCZuS$QJ|S63p+^l0gbSJ5E` za|gw6^5})W1$NnCYQ~&e&^8N%J@Z&r_nEkfdIgqD4w=+5r-ZUN{M7sSh<^SAdw85)cU*8&xbH8eW;+N0I{_tmYeQu8m z3oDsS%I4M#e#*`n<{M@rp^#sPc0B-SC`cKYrCYzbNj;+WkT50hO(TG#N9{31JwkuL z7QgcJ9~2FQ(fH7&H={JeyX}Yli)BmLSz9Ed5Gz#_B~Dt-Z?Hl`H@q z{L~LJPVBUCrlRj11a!+_ci8Z|t5z#;JIgY*S|IbuyCMo0n=!8#+=Uv=w|3xL*HV2} zy|AVB1URYB&0dBsywLq_>3G6lEN1BB@#G|8W3(qMx>FS?j`N` zC6=CNQ&*t(VS~XDgn=qc-)M3g9h8!@!?lv$BtBr6&ghFN+t4G7;oUUN#U=e1o`i15txKZ^81|)(N8hHjfR97cZcB zLvaZS;P(46)k}Erko7AS@>@4YP7*W?~DPR^ZEqWFt2_C0!urc z;}BWkwr)~oYOTM#6*I6^P1zFfi@CnC0QK*e4obIg+-i4 z6g|$R8r*#yZIB+H^V{sSQXWfUXtkfK5ZP$TUOd0^j2|I1nNxjcQ#BbOTUa63@6dAp z<1@|}TCS2#`h~dwwTfO?N z8Ze}z3HT0yHtQF!gTf1@-pS5sl-s}j1nKm3{8@L?r!K}%yo}B}+-%p@JG~#TcKU!` zgRJWOSRo{z8F9xvdtSanDAM%}D%t)kZZH0TQ1#*+=z`Ke9F8f;gHv<@oz_oRJMS;| zx-Aa58ft{ie(Kenkxl^DD5MmovYZUIfded`!MnG&c(mJ4pdP-GDM1zrPQ2&g1L+Sp z(rOe~Y5SWV4O!D+dy{t5XR~Z6XFQ@mwbeP-7a(incOR2V)qF#uB`fs6#q@9VKG-%d z1HfegbeZScvZqS)vMgKcS`NX7`h(5U);dpzjz`@kW{j5E(Q8NhhD%8Z85tRa5jbce zD7)?a1AA+u7>se)O!dQdMI=;Xjd-?!Wofikr_pXA6_TXZNO+w*1gf@3c}tLSCiI^2 zhRM76@*srR=g6WN4FOL$)MXlx@=Yk}o2^ ziC}i>yw;VK{9ft!{wL`-TAP2?aC=_CXGyV!YhcA19;kq0bltvcp=9YGGf_MjhV=?^ zqx1HSsYQoUPA@>TcO&)$fyg8n`2>-D#7lDN@cz$&oP2|4i0(b^TG)Aw(XYUsyXdZq z9*8`#Sn;pTXu~NA`!Sj=R$)F{vUCHy-#KH*Oh%Gq5Y1O)$A^M?z<^2-WlUHkf2(D> zEB4NgFyDf<3@E>qQj_;j?a{AP>>VxT@@wMI`=dWEBpK|bRQ(Q~vSzkiY&52T?z>A% z$yChMM5}*djL7h9MqD9MqMsjrOpFUf!-fD&wHHtCi)Kmh3&lGQMMfJY09Fb0I|~BF zhG4o@9+OLo0g6B%FX?{ku3994OKS*h2^`_Y`|D#Y!CaY$DcgN?-E${;l7)ToTGY)~ z8+K(?d-;Q@Uz)980e6I(63NLuq0)3amay-&UuR;OSJy{?!pibMAHd34rSW40jUc$4^DyW%3yPF zQ|Yt_7;!&2^^WD#7{BsUv@o%dTUC4uTUMR`6L9UNTW?mtTO)bgHUKEl`dsfqoRA0c zfnfx+Z)o$J^|T7P@@C2w($dp+`29IvSk94xYtyJaD}8fj;0i(7RPuOM8_etRS9oEx z7TFp-Ew13`{DFDG2P}I)cycAO)Lhx&;K5Xr{No2`uqa4FD1HQJXT_+z*VC1ewsz`> zsh4_;I|XIVy#JTd=#^*>#_&|WDz{1f^rLTvmq)T#f7f-X(oi zXMIwf?FWmbNh`4t-R6x`5UhfGUOKw{*u843Q7C0}>&)c=b}p(N=Q`f$zO=HT8^-mu z?o|GZo39_$AN2cEhVX1DcTHT_YUdz)nnfCK`TcV+^2Mclot#kJXvUF|5p8X4AmAW4 z6>K0i480N@=dg7v_`K4xcTGl`Rm2 zcRhEfSW|xI>vj71{||d_85KvjZjA;f5Zr=GaCd^cyL)hJEV#P`2(I0@ySs-FoW>iM z;10np!0mT`d!KW@G4B0wzkhd(yZBQq=<2FkwbnDAIcL?AkONo*thG19#wx0*B`VQY z4dJ{5L%ttPxBETwE;ooX=~N#sHCPnM#2GZ(auf!nq-X}cLuXLVbcWc!gJNCdE>DDg zow5a4v8^GDuN@73q&>l1ehVt+v)Erk>x{}&a_-Jnr*Z`Ep=GrrGdjZWvTsf|wzBF5 z1_q#Yb)n;f8tap7PWNwenhIjm0;rX$VQs^*D6$CxIi0)nudV;Hbd7=puGEgptw;(sZf#p@Vs z0%NaXqTtWnSLKz*`v+ps0zh!KU1_f9>hfD@RdYFY(9q@*>Ow<}47k3z(aI2+Ge^pb zy6*a!b+TADh1SR0J4r`^or@kYVxO*4C_r5cD5MOoJBK;=9uor+@BpOHD)$1kymZ>| zyM_Z)7b#g3lFldPIY$g#K2Q7!=PQSom?T|Zg;4UKtgp{mQJ!D>HV2dbp6>Lpw>omu z(jIa|ypd9DkYlgcZF^E_(G==UqpJ=6`s(DG3>;A~mgnKq$pS+qyI;3*t@c z0xfZtwCvY_|HMp@4{rlVvwBx@op3m59-_pXBBe;*$|qmMnbAr(zTB*dX+FBSJ~4kF zgQvu=jBxD_MG(6%5B#e@a*4`dm!6gu_mQJedp!LWCn_gvi!=d za%W(im(@0S{FxRjxHhMpV99gn{MnxXs;H=}8}N8{RU`Q)p3AGugD@%5p){aK(5wG> zMVLJ;n$ygW4vVU(Vk_QQ=ZE}S<1TLdS#Qq-ooI_*`2-Y$Z5~1inFKOp4GpMZ3sb!_ zWg^J^wRRoH;&iFuhXu_Z%~-RtWpM1>f{C>}f5+-%j$nuwEAf>i0%46rbWjcAdJ-BF zG0%gy<+DuMLCQ$@$q3o z_IS(neNteog}Hf5?97<9cFFaVzxHOwU8;&Q8%=f4pWiUu@WrSjyD!ECBOXW}wO01? z5x4-5N(l56Vq#FdWs+^D=D3W0kG48(Xw{X;tgZ=B8VI6rluH)egm~}(ka8%04b*9u zwPm3R6sYNiTt02j{LD{c%W%)2VT~%2k9tQc-GqLr1%!YOLESJi43hp3XM*e=?ve>WtGM4BIA;SJqG4nYBdF~hVL>lSxch@ zCMWbibIA%??=O?KPOOOxh;Zd4P2ko@0Qo2F(f`}jgAUJW6_#+v>b!?0+7DIZqsyg$ zozbP3L$g$~1GK9x;dj_=$Mcw>GDuH1spP-2h(p8{s!qCJ4$u#WUlRC_nUI2`p%vS0 zviO{N51TQmmO1y*yzVPmKHQ-Oa_>XE@FTj)K3-0V%`HZbxn8{4P^6VMc zCi59bi(Au_=-b~RG(!d@HoS+4%->pFI#0<-V(wttxnoEbbh2GsT(I@{t3_&WIPK7RR$CHICmUQ9>zmGF=3 z1FqA9ho>jBWU}K^i({r}U)AR;f_wn9zO6Ed8(LepnW*^}zM!3hpWfSAN4Jf4;E=ja znLwY1lMa?h%n1wp#%gcCbG)OWh{>Ar?@c6;!JBh!TU+{H&?4G|xtoZ0$X;FiT}_+R z_r=B3tFOejc7nV={Cb@YR9!hEX#>kCaq`|^nObqOGQU5Cjvuy@aA^ppc`f5)sV6wI z71JD;@*c%HCGN`%=GmVeCu$G=;g0@_O{0 z#+U|JX|_}GIIh+|l&2jTN%3#)aJPk-Ik1~sPamEexTg42i)^#4f5#J@~7IF{2 z@7^Tl0l@!K{ifc{cQ{(;lr+#+t-Htog_qnM=ww3eX2J)Gijlu}7DMnOFl(oBg^6_n zFE)gK^QMXPysR7WmFq5!k28sinowf{!TVlqoUUO*xPC?0R!2o^1(H#)IOAY&1TmnF z6mQ#Q)JwC_9`b~|M5_Pik*kbo-h=2ZASDKm6^hKBx(;2Zpx}+)4!3f{1dqq#`0Ss&x|a>K1<{$X zJXuXGEqDifWXmI00w{pB=BV_9)fVx)JH3rP_^lZ(4!6O2LfPy3@m&KkpHubF3ZVvK zDv7a8F-T?9Z*7H}*<>p;@>R|12f@9Y)5PhAH&+WC+~u7iSlz4HmjL3!lL(Bfkz2te zHxdcgbc|1IdxJ>)8;+g?xY)d-TTf^Cm(;uG3xm5cMovsDg@?9 z0bg1GX`DRC^C~5m7gn^q$5=IFTbV!}JXh}aX%ViyrT*yuA!a;@jitP}`y8}y8pX=g zPRdb;ZljwcLCsm%JJD6b8!Lw0Z682q$w?IPQf0uaREjDC6=X|u^FnEcm1WWWgYwXDAj5HiC(rtJJ=tHbL%aXb(DY?mb;@I_UD^<>&e;r~fnbXM}MU z#0!cgI0z$?fxzW@vw_j|6-?uL0ef=3QKE=7m5eiEmGUccGp6?;)FDuNNw~2j^0Z>R zDl|J@Utd?`(%eOY#k^QQyga?oj6x?1k6?kydgp5$eRqEm7cMS?YAAm(GwvZ5XZV?H z!4xYI)DT90tUze5C)B$UbFVF-&!sqTzf1cg4K_Ue78X*BV4E*26a!2=BGnx zq<%k{+cOpPWhlYVk6Prk-udzdZo7x6YS~M^A>I9e^;2%H2u_DNEC3xHeMsxE-{NE|1vb&BMT&A@0P7Xygh*!3V4=_nDl{A%%t8EympW%_}H9KuXbKfNxj>@AVzTt{;aePlgS40b-_PFR22_3PiZ zFOtS9ElwN7@+r^-^XcJX#21Z;uuWOzB?#&b`~rr)F=*L@G%`Negb=)F+hBb@cs8o%55 z^Wy~9l#k-Cy1rMGJeP?~j`~*}axKf$>n>9+b+NnC<+-Gkiup2!k9Lz?IhmPyB?@U? zn*nWK)&<~*0`A;y1bak+;M#G9Drh8NBzra5o2k&7Sk=XNoj1C@9Z&;ct7yE=jlXT9 zY#jcKKs`_;6JFxG5?id4jcgU{qT7S*PkLBD^3#pVh*v$r2rBLU`uexvqG;=JAPkhd z-gEo&(XBu?o;JX(UKP#zXlW_;Ac4G8SCBg&tLUcA>#hw$W7FR4I3iVT+|hEvxD{T>qm>)s@-9-qFdef#9-`@29uLYh-ZDs1F) zM^6-WWg0w9{%i({qs(3-^X zot>@rg{OoS~ zuY3*WD*@JmxlK%{?Sa@qUiB-$HHS0}e{%ZFcfSQXb*K(bU;Q$^TP(A|&P_P=t{(d< zjcR;IMUw10y}MXk#=4uPJcdwk(uGrLI$Dvtuj*S~`O6K**N^!B`89$It0DGJ`)&6p zoY6tw95VdgLyR%g+QUZQ#&#V(OuQ}&jP^Zl8Y9lLn5L?x+iJPN3+CjOfWQp2l&+cD zEttQ=8;=-6MUla(O&zsJENDA@ZIuh$JQX%Jhm+YFu7jFNVyf>3cX=Twh_Z*;4*FlZpZMf##0GD-dgwP zBkw%uP?Z0!;o{`{U9-v;Yj(j&twBzn(-dH~+-L>jbv$1c$UgTogH}-aY$hfHQkLZ5N1lPBMaxk2l?!Grb;w(VtnLI?V`#TAuh&BPyuZbQV>_GJJ?LAFpmqVM>9U99%znwS>kW-5z z^C>04WLtpr!596xGD;qY6C8+=v_4{tovWV=q571Edk!d(0l~o@J2gF7F~|(pNGwsE zOyy#u_PAB4+arZ{2A$M??xTXGipD2RWI33BT1Z*{ zMa$*o!58bz`EJR4QB}u}=u|O20sbV>&+|Gf;xzeFgMl*>^PPc(;Xj0`p1s~4{W@%3 zyDj%q6C?TE_LZOuUS;>wS}QvFpMkZ_tLy8&*C+ewz>|dblH}IRBFFHE%rH)&qvy2_Ct8R9`9q>x`Sb{`x$+r=GDfg z|D@57TD!w?BYF4TS}m)#7}1t@FR7qs zDwA$)f0VP;>n~Ohd#R@R8bguC-4vT#pHiqf=MU0C%lmp@1l-&8nA_A}Xf5T5$w^j5 zMp%zCk*-e_qq2WE{G@bw@q|<10++JWm~?yZR_rG-s;)6eoj;J>JhwV;q7(c*@48^N z@gi(5Ypb)@rubM3Zw<7B-UpR`{Fmo&p3ALu z*&j69CWE$NleJG*;*R|8Lvi76A&0Syn~>_+eC(5P<6CFEt7}(0vz<$*P4N19Z>-m( z!6=NalGlFaCJaNQT&>{ee1)cC2Vb_|{>e7L;aIK2zr&^?_-1{Kz3D0cIFduzjH3X7 zIWz48_IcVt?#m)EUS;>&moy9!@8`2N@w!mjYLm9Rf(K6oIDKdGw{@j_y_$uU7JE_M zyX6rt#@1R5j;EZMyzcA$L#zQY>Z0HexVxDIugI?DCM|twK6gN964?!nN>E-Yx#sB< zt|HBZ>23DfiWm}oJYA}-r8N&F?LeuiTD|^{zpPEz+Z?@(Rrhn3`om25#3T;ZNAA{z z(DL?t`=+*loK|DuMA3>vQLVS~Yxz~9zN~4-X3JK$n^WeKjt(B}RvQjH7UG-)%bI2E zGkCfK9$!lU41U?K&&$n833Q*`^ zkP6Im9ls1+^sJql)O|RdO)gba7z!O&7dd{IsTvjaWSsfQ{X*D>I3Z$A7jsNax|j?Sbn(0HG&a;ct3F>vO9H=4)r2f&!;_j3SqFW2q7ZH6=}f`V9QP<&TJbc&WStN2hXGwHlW4 zc@59~S_|%jLS0D07HN)%t3*1p=GpU;tyUyGAik4eD>G5gmZQyjBEwwW_df^hd6sw+ zc7|J6G9#%afjznj_$*`(w!edvGzAr8ZhvqedJOp12cfIk=22~e=Xf{xr$09+|4yn* zHBFj)8DDzuY#xv=mu{Yx>_%n}Sc1><%fQv%arHUX!CdX0FX1i1J&2@-&VaE$mq~H{ zd@2O{Mk?Q9%5luX z)E&01Ku!+M8JLcH|8Vi;mj=N}jNT^1;+W}4Xlj|8`7R{y1EX}hSSv&B#;l1D5Rl+9 zsx`t*{gilws;!`gF4S$7{X;-dAOE!+=wZuMPvzz0wW_Jt_XL#!ulC0KZWprRpLNv- zvJPGYEo%vNBrvDrB3piTRNp8m0i zPsPOpYfGRpUBfa8nwIB#f9p0gpn0p*2; zU9!N6@#fc%g@#Bb?;(YT%lTM#-^K(&1bsV5?G?(Fs zcbt?uomVl#J#jrhLW^!>eNIygWsXi|qS`5^B~nmpbtW2MNXjofLKSOZHrLP>rH*N> zgNfN`(_bU|&aLdAxM_J)p7hlXNxJ8~ZVD;BFUMj*TDHbO;*!|)YhazQ6*jBb?A~m~ znvKRxICFemhsVwnbVhqXpAoYfPtOawQkRJRW+)nfu8Yc5E}Vg3X8L12wYstsQT|k< z6^7t|VenuN$oy?CXC3?7$^7%Pq181_t#kQK&t};NZ>yOT|1-DOCNQ+Fz8En zCvEv6XkXI)bPHB-lGLLflEyZ(%OZOMXaYwcMm^I zIP=(4G!{Q3?ikeL&;5ejSd-S*ewTzC^yMkn?JteqWSVJxP}6Jb$J|?KNW?hm@`$Yb z%-fo<8Z1_j9F zG5M#3_pe5`zwqZjlPR4j9Xk2BXIFs8Ce$@Mmd4W6{^*xU ze=@pOq%jczO+r2(d8V~KAVO@m=id9oUf|xwFUN`Xo4|_>)w^soS%Wodt-Zgw0rV`% z0)#jX&3=k`TTUJ%@f+d*#mRsyf}U9a6)-+2i8-mr-%OCHoU=ytd8oue?!NrqV3$r3( zd20R#+|;qBUr)XEzrLlw-Z|pTL?S4w(2M8mrN4}cS{tjDb^`0)4d?ol%ZYD7&2i3~ zP*Hnjm|TZHW#nujT)>^n45pm&_EMcfr=mSA2VYPW9K|yShObXg4y#%}e|sEw5NJ%P zIH|6#M!{qJPRN0KU^M_bvQDqh4zY+?1H73sD5}2XWLn|&Wa$7A0@E1NAv})6rOQ$*;DD&3FtOHZJ-O~S5RQ_&WPpErZ=_U) z4TYlvHV7g6MNkefE4`FK9$c zgF8u+{7Uix_U1b$;Hx{%L2n5s1EWjcYINgpr$1)Z6>G%XB*Jh!A$>v4QLGiQ{*M-m zrCvl4=3A8)A6*hZg8HgKS;091g`udxzCLJFuj_p}Zr#QD{2h@u#iy*Ghq?XiSJP=f zgv4(jDdxOVw<|9K&d8LjMZ{8sDQKU|3mRHOkQOn>g!G_*4QhaW3p>GNX$R)UQj^bW ze83$*-UqC-eaEm0Z$!Xd=TbfkFRi5|pS2s+`+SvG*LMYZW;kN;V$QMs zhIuD6+|2=4v;YZXgFx0Uhwq&65cj2pxIfn9S_GzyrrW%{5_xJ!mSv27f4}6{BSw#X zJ1{a~75kr5`MO>s8Pp#gqhFEzZRB(vIvhBNu#Gu|0CmB9FpZEXsj09$e-%)3SrbL zerLZ4E+NVgKGv^1Wnblu>+hZ3D%~ChmlAF=HXbyC?(lCq#Vd|+PAoP^!7T21>sVKm z`UhfZIF=SkJ}-41k76t4D{gis6{n92()NJ%if={DEU3?0msM19wPXX7!KDnO+0W@} zx^q6ZG@XEbeqk%OBt|)>95b93?=-%mM9skaikhKlM<3sV#b)$DuZv`~fRQ8)u_Q-C z4=~U#Ro^dV1#yJ3OY{x2Eg5>c)+WU%qP6J1hwN19qNK?<0vEwQc@vTO@g44F(JC4d zcez%DhM5`ViQOpQT%w-I&e72|5M$I>`QY5gER=)~$2_xee<= zp8hbTTv{N+R%$&-t%0(QUqzufQ{}qUd{$_|IzIG9)(-RH1Bz{jQ zm$Xs^Lf>HaV^ACV>RqW<9%j#JjJIU+hi> z>{~}mzcJkES40-s78+acB_Cn(n(dDKg|d3^nlQPbonT;=q#)nV9#h=jcZ-*Cg0r)X zI@O<{jw$(MQ?A<*+0n07zC1hOI!gn?z~1o5HM1<>uk%I^?QTmAFX%IO?s2uVdrfVP zeQ#P^e3*PGn^u^|4qVX~cKY+=q!O!F_QG6Z;p5=J#&*X6R1*FBM>21t=jyIb z)&uE2K5kw8;!4>Yaj)kfbj5>?UU8#J7Oe>MHO#m0qO`J*#+Xb^Oxon-vI&s(whT2# z^n6Jm(Q9(?XG+cKBL=Pns`dI2D6h@8)cQ(TZYLnj49Wh7QuQV#S2LNXfHftM8W@q8 znET|3BZo>u?kc0ZLWg8(+<%kF%8E@7{fB@;a`n6}5KDy$+)_O%RTB*PEJAyNvzTf$ znicJ<<$KR{b^no*`Li3NrMOvGGI4WWSR*9e)Tczk8$j;~UAxCnt&9he;g2InfiL{q zJ2>qcX z;Mwhod_(JLw-}sgTq$Wtr6@LYEx92`TqdJcw^3^>m=k}bJ!%x}L|1OY=nFFxU6Y1z z3RDe{o9^*`u-6ws#&5En`3bc-SXo(x40Z8zAEn==4MU!hPF|H&-e5A*O@XVigCA}w z3EsZzTBObIX24Q7D~;!Udev!}6`dqoXG^KlUyK*)f;2wR8MMRyQ1Bcm|40U8i~x3K zVvG(&*i+5@3}QfrVW9Y@{o(dDCzsp5OWff6bLOzg3B%+@DrlpzjyJuI@tD}`3g6oj zV*ZPy6}-b8GooPx!dTApM7P|0Hl#C8YjZsN>L^H&<)gwD$hxelnE~eBRhr|zp+r)k zy|v_}M_}$|UxR8HIY|n}$~I5t*VPwG5d6PlsN9)4>JC2^#0q{+d057Au30X4g@lrT zL201)kNLmFNZ?0QCMda;k1)NzDr;&rX6gE1RDtQKyOJRVUwsBvVAiJ!*F91vx+32U{u_R-_KFPt}n-U7@hSIN@{Iw;>8D_g@Q=Uf`Cl#!HP zm{bCNQ~U@;_iF<4dR`SG>M@V+j!u}_J;5`$`UJc60?e%D%ht0_(3c~af?!4_6R`ko zt0^+n{zfIP$9!+r2NzK~vnKGbe@~VoxrI2-Xz_tUlna-u)%m(F^4Rpf^~7K7v;FSpb6s48gDQ(b0WRCC3puTxtka;>^?EarF{N_;W&vyQBZ4$ z=0Htz+{cvg$s$rcE)z{!1?Xs0&K`C?>7y*NQBfl|GbkOduD3{fF6rBZkv1YFZgr+h zA6C`iF6EmZU|HijRkq-Cm#X&2eI;F$VLokG_(0j6YCI<#B0e2O&#jT0^o*|urWQ+Qy5z0qP(M4XlaW1mZILrD6-rCIL*`1Bocy>gEn*7pl> ze(xvI91CJCbeo*Xh|eWm?T|t!LsV#=r!@2)VXK)eLbflxX;rfIpy^M*^Btb5?Kln` zD7-|?V3Cd?iNDUv+tS?lZ@mG`3!JiLDGgH+e~E>jWegS3e|YvCY3`7}_L+3nphuRP zCA7}7e7--nOHc%&<)3GpDU^+94q5@?Po%@s$Pj|hO3&sFi$5+~{|MFJDQ?ZZ1|SjB z;^{!&Nzr1Os$BGfQCmfD-8tjH9q)K9(xd$ek2j7(#UacyMO2r|Xh`TX zU3SHtIjEKS_}~+Re@u5j@AoL(87_O9Co0XW#Z!yP3huNpD1gPIc~Dwp6t>E^$LEe6xo&&hrPJQLTx8ReUE{rRgQ2R|K@ z-q%zl(LBc=$#Ezj=}El96|%6hP&lMM$v<7|`#>ssMpF=+Ru7T5{ULDZ*7eAZ zzn&6MTuCgF@wP!@)Z`*z zFL1(sc%2V{u6!v)e@%asDMdiZTaryGhhTI@rX?li>$6~!R^qQP`D5Mg!LgfB(eO_X z^!t*POz1z>rFf7-jpp!0esfKohX`71a;lV!V5@!a4#8%Y3#Ay7>&F*}oH5~0u!Yh1 z(d!|!I?;|i?I5m>5W~PyX?dMxtcoyE zy3ZwNG*HD_)i0+uj4AcXP~ZvZ<7<-^lWdnmDrjAv8k`W< zNxUAuSms`4=bCR?Q?>m_=p{(Z)1nXxC4~NbUxhN_2FKe|UFNHw4Te|Y8e4babKL|R zloMSPWC3u9Wb5z&-vr|9Pm(y8|?V;XPP(wgI<%}kR!fz~ofh_ChG|y!9 zhvQk1G;_uuV9T;8q;!aDS(?0MQ6ytsJVEjqZmk^NOoo;=@xdH@{sN- z3c06`?V@@4;l@mb#URgzp8NqQBsrGYRETv*q078{QFCd3H+;??P8H@Pb)fbSDYa{z zhW+Q!b&@GMv>DY(&04v&Vff(>Th4O^W(@f*p@x_hmI7uf2K|>@Lp@zC4K)-wX|Lb% zH!zYb@dXt{Q1wL!A-*C{Z2jHrgR^%u^`_U@|$7fBBKs1sf=-&~2DheKiC@L?R zSB1Lh0)lwiL1k(`A>3tu1M4gnNwkXdM~@(uZb=?TY~HU-h7boO+6#=jp(clckw~H# zh^et434xf6+E43HkzYT8y9jS=pRktOlz$=A13onZDZ-%SsszMi+EH^sh&l!;<|O&> zX~roj7cxujqtI~5*Qw(JBLJ4XFPsYhTYh1E!&ZHS_BiWBy7>*gAb_g{Mt^}kJxUJ> zpJdS**M9C0rzNN3xujAZxpJt3g}S1ye{f!f!sAw}HZY&7S|wPrHbdFwtT>Y>4^FSV zwZfY_;9}H5&4_1;2bi7o0_9vzv9yIZpFWjrhpTIb3U@kvDPs0>EkALMM7#-P707*rzI$z zMAm%GQxWHf$6XO0@j8H=6yT=j&7Y(!7ja&Ik(MY^DL`X{l1kZr1g;QW)Yr(Wg zc1~9R>(46|LTX=EJ-qRbS*JR3Zqggxa|(4O#}O4bp?mmzt#k?NjCFQ!HAtBZk#m-%yHgcTW9Pv5dT}iW=G7Nra|w`EAU&z(S1wVumh75-F&K zGVbP_Eioze&S0Nn$i9!MR2^st2xvi3J%jY@K|v%;4AkawtGMQPzb+K#nW8CJOC&{6 zi9WDoeUr&^=mLLLn;+?Nnq5)QUR`b`<`ogWBz6R==S&Ez7aW~X#rqvl4Jd}G?z|cqS_V?{Bp;VLY+$o%l-CE$|3CnS z%U?3v=~i&-yQTt%jrctDZsm(HP5K~oH)K3=&W>2F0IZT=C*~ZFB|f$6s$L33y%)#q z`GpRz0_$e*5iSj-n>C*RUp@6ap1*@;{`4|yE^1db({$A7NH~hRi%RvYio-ixkns^% zRlK>P18C@9F~#H90!B&D#{uKz6k41-~OAgDEwvP2Y`wye@Fo2AcNW55QmGa!a zZn-ItM7IA#ZX`)O{keivcrVovv3h-aShfkqr?^~-Q&`J?B--(i8}os96Kyc6xmG?A zTzQ^cBS7MT)HyC$#bTr*`jqH!IAJPZcg(u%^y@Bo$OUXHyHKvtzhn9y*qzn}RTq6< zQA6>G2R{z^?=5kelz6X;iR;cm)kx*%)OFrLL=s4*^7*IGa9zTtF!i}+mDetSC;42@ zXMNfVtgK5?-!CZd27e{!$Ke=+I%t|)`J`g4M&I&8$aRm9PHm!DfB-U8@cwt)(vl!+ z4>n3<+)ds6`R@QFzLdwrXZ!*TJJ4E4jG>NTQ(Dzwailw!Vy4b!@bD&75~}D-|A0Z- z2Oj!|-*0C-)$t!0J)6MJZsT&(oMU_ zz5cBNSng+Qiqc5!58lwpl+qVs{V(Z?Na%~yrz2N=B;qfxN(paz3!An4LzgT*D~8xF zrRmJldM_xI&??S2sUbgCUVlqs{EJ2kts@ zKFcqE?tl|)EaU3sXk!-{>$UsfD7!Pdf`LLf$kJV8Ewp`!M(+o;Cc#m6&3e7Sr;9cX zMbq)lU4F}*5bm5c&-*cu#ke==<2Od_&a+O(JBIHeL}h;oMol+^GVi>`JS4Om)36VW`IQhO?ej=5`b;AJX75iKlYlQ>CZl16zO;q$Y|@n$JNZFCpHpQmwFPfPUtdm?8Bk?(mu? ztNF*lr%(3bnnb+nwRcv+XeD;U5gJ9lXXxuZY=hiP#%`qGYnGKL`j(ZzDxae&9h8z% zYjBH!hYmwcmn}VbrINhq#fz~7%*R+_B@2cacruqrK>(}T0lfijmkm&}$#;)f-G1k^&tXij|Y4o4c!(nd84Uoy`GgC>;Ep6zmlL+7uFE)AIRh z#iplf4zRLtXVdgBcmL;ic}FuFD>hv_OLtp}&wM;=a#nUWw(bF=1eLg#b5D>5{9WVi?3S_>r*d-`O{8*q14qSkXdywL@G8rxuv35gg zWjX%$pESX49aK)*rZiIk99BSXU%Dg^r~Mg8*Nv3R3nD}EGHrx3N~ea#E>X5Z$H0+t zIv5O+ucpNF;!UecOX`4B8?NhTG>4T183#EN zzkp1{#H?1OtMxk^y1#C8Z)#uQvD$d{9Sc$`$?1w|bGY-IPp2Vgb}uMhBtmv0%wI#F%Fvr=GRexl&md z%2>Exw~T#cA7U|tMH;Hxb=($iza0?h-r>fm3I#z&m$GudKI65K3*HCQW2_Lg z^+owk{dn|=bMm#OoERn)a9r$DvtGR3Jynip;`i04h-pk8J=?+ZcrTK3()#P)8X}T| z#`JidgSn?KKI@WY24`WTsADdzCdFrUgD&x(lG${&zt$mEe^hU|8a^Z-mP`!5Mw?LP z$x4}*ZLewEEF@zpFU>6JfBHS47r?@S-JcwWgkZt%U9M_H5+D#iZ{%PTcvo;q(u>;{i$LhZeIC@vNiT7wI+YX z!^DiI2>_8hOKNbNtc1K*b{btaDTLG^YyVo6sJNpcWz1+GHVLWjG!Cd0=vxZi&iU>N z2MLByRakpPwVnusjXXt`ecwXO#-G_TFT<+CDFg)UB%mfNJG>R;nm0S0h)k6l{1v-= z@A1~&)zV>5j48E~E$IzuZ_^ATMzKFvRPjm!Nw0a@t6UxFA}gLyoC}+-KmXmdYfc{3 zw|NJ7_sN~KDRPkRZHo$#yQ_4aO-_5SLn5;ke7WeY-lBtb9}%^7wP|N4y>;yj%24Jx z(-+rmy9M3W8huj0&zTylgn1s1}?LFeHgRd0|F$zIWR>8&YT1dlmGfw>9aY*d@+~2LzJ!Q z1XwKIn`nOqH&vAS6LCMJO=f8&2)bq~B7^O8+IAYdI6?te1q`DmZB8PmmA-LtuUMWx z^ueVlM&l#g-IBKwb)2AQj--lj&=c><8_FA zt-4xq&z~a?S;_0xrIr7tAa~9TvOf2$Aj#4jh;Lc!N(kT79v|g|vWcn-wyM|HAG+-SLTw)f`-Uf#RAkIXVR5_v^%zp>D z|Kl(GUorCkD<7w=^n45Pd9(xma|wvm(CVo&zhr586X^>))51ZAEwm!7q{&nr8gSwN z8xX*2{!W}7r+{8CGXqphd8D|PV8Z{eobdn4!@a2gAf9JpF{r}SiY3Y9dQG3OOV=5vXpvK}X zWB8P3=~9_>AR)n1p3YZvbh$sPB%sBGq;|IVy;M1UGE_P`60rZSvWEnEaVOqs`SC-? z6bMs(=b8^%)_SftIVy4P!cjY;5#wp9&{+uq_*hhfYV3V%h*9?ku``uh&K8+R+>XY{ ztVe~6{04*wW&xvWV7H~I6Hm713dLnAQR|W^5k}ozC>pia1Q+^$s<>+{xrVtCt1|#n zX5ge)eA=1&1jT+}%G`;WeurU)SMDXY0~X%+J8MCO*LrkFZs( zQMcRKpRU?%nS)DlzA)7q0F%RPg-&39$Awk4#pa9dMYge~$>iv;v9}xt0qb9_8#FFL zy(mB|4Mafif1Pn}iQ$*XeBMj-p3k)?J>?X&PQ`XctNGWd__)o*oHq9XPfesJUb2IM z%npJQChJP=WtwNy0dD6D@#}APb=>=l*{^CMD#c~w$CnQqNC z{@#j0_Df#ObkM>@Y=Uo8N&-r!B$l}N=4URUpc6I6lwt!o#RItAkm3~u0Ra7cyFi=9 zu%$YSz)ZALFgH&*bto*UI_P5#u;$ zloDOY(`045aIRmZ#Pq&xo!21-RYjWtEf4)RGIaqGhe5w8N=}Sk{V}Boo5!v$BCIW`oHoGnrzq>SP~z8(GWn!vS(2$ zSrgPY^qNdBCB<7R#vBRpl)tq6U+legR2H3+@nt zdw>AJ-5MH#I|O$K(2cvhyZ)NJ&%O7Yd-ndld&m3hjqye?imutKYJO8zRn65^-^zcW zEdgNS@JmTR#&fyHQNY+Z1)2!IxzD@Lxj7|oMJDKvz~;bU7lTBNB9{v{7bz4EZJXR_ z{XLN(r@CchT_rQA3&F1-iZLf8bVB{z&X>mR4{Ca^>3=}lh^r@ZX#^tuKmjZ8A{FV6 zeA$0PH zWt@ZZhJdS-Lc!$4y~4UP8X%mb`4WNMVLRAR_XXyd<%h3H9dj(OFs`d6=lG+&zXnac0R*v0Ijb z&%G*f%1wmdSf}LlOY7mq%tNhxDz_HkI}X=bkuV)~H3tdA`MKy(7Ui!R%AeuN zK~WgXd3Jabq%;b=-Rw$;EESY*CLy%9JOvgSU0DxdrcnvrvA{bds=onRv6d6X>EHnZ7mi7r*%(Zvh^U?5J4dq$%=U>lQJZy$dsRH?xT)6`iZLFCj@nd zEwG)C%UNEb53TjVF1-xgqEh^eqUNRtQwljVq*ZivhAS`(exbH*%ymFGegcm3gb{9l zCC1w37*jF7AuB^xi@K^@>3_txUC%jYh=>3fln0$7GNudZj{Q3N(TU$|Dkox$j=KSPq46etJ9>P)2#My~XKb3DayqyAHHbhFK#f2DlOy zwszdSQ|mr2)#EkmGNYJ(@v6W-Qa2tEj4cP-)$h|Pna>)Q0+!CZ?G5>vsmQ#vcGm&v z=?$D5=3|h|!rxjvV^LiKxSQk5r!rdqXtJCbLB=2s2vA4g(ZF@CDQ<4yf}B3-XybI=RrRKjBe< z$jXI=)w-K+4U?Q&&*a!>9N6;?(dfUn(r36t;TH~fLfarY37RY}-M{`@he;8*byYwv- zdB&S~uF6;L4e@IcKp2?1qKrY!=y%i%OCY5=XWwb?Nl`N);bh0c;3_*KkjH%jG-W-& zGV`FIQNRh_sEI1QEUrlKvu3u{d_s)?W6VqPI@4MJekPCi4{YN{hLeYBPO0+R6<-V$ zL(E8W4z)-8t?vqb!d`B!n0RL-nW$Inuv*-7zCbJ0?r2?*a<50@)9DHMI!FXN(tQm+U7UNjm8!e^N7w?X^zXZWcbcoD+vg zV%HzV{^A>oABw?#3Y!FLmOb1el6j6~HZ^&Fx=2E2S!hLY<;3GL0&@DeEtgs+j^J0o z8Mq6&(-U=<`ni6IVINalKBX`+0Il(zRNPASB7kA#A=yyx_4(&Dzy1| zJro_Z9xE(RQ!uEpeV(t&-|DOVw%~D-Q03?>%c%@0(1>k0zDj$SRXK*bP^inkV>o0@ zUEEMgzSjg0EBZdbL5m|&MXoWJyN!&TmX|Mpo&+6ec&62A%&gHcRQEPl-m|vSBX@Z! zUhUQwBvGIPS=wo@I(5C9#2-KW)>m>@nT;Z@wSL|~3vGJ>3zY^mytFNTC8OF!bW@O7 zR0XX!j?;nvC|?j+e`Z&h~yRX>B~`V6;vto%^=@ndbgjzS3M) z&u~A=?pVH@`R!`hik+QD(+T$2e9OVLtHw5jcW_Uo68lMksSRv*Td@g}D@B0JzlI07 zSGd32W=m`-_PhLu@Lw;6W!+>M*hf-76?Z%w4+T?{bkn2)T zJ;DaigY`jGeZ{0`+C}Rn6`?oD@bodNI!8XJWUo5k!pIqYK+2;wC&@WK-|nNgdb0h> zdI&o8DjV+0f}}4KE(zGD=I&mW<_0ED)H%{Y$JGSwbWSF=HMipN>e;7J5r`+*(*jHq z=d@Nh4*9R)!&d;I`T|YhO?k{!g;9VAz@cz`)XgR4x|alP_jm%%l#r+SI-rIl6xgP| z;-la9N+>47n-4;aFKzHrog)?$@erElFN|<9rw>$SI{g_~*$|$DBbx#ezz!tVEGYHa zwb_5{2ZMy*Dd-JA?{4>?3u&{0vcS1;#fuzvfp@{Dtx-{=SL0TsS%t=tJAHk9eGkdq zG`!6(h0j_tQDZO3pN~nh9+wFpg-x0*vZ>I7;E(q~{Z&RLwB8Y{EUJ~({Y;Vpm#MJtgqV*wOW3J)e^jKNtK7SoMsgUNEl< zUt)}7j>ppmdKqvXL^+nL=Uae0xK7?HC!I_Kk4u*DmHrsd32NQ+?K$L{nHb&U>gR{{ z8*_XMX+aHIG$P~$`LVrBFT2{p%ok|X)4RN@)vRTfI52_r+-Q(i)z_2=g{qKDuvv?) z1aLSD0h|cdfk~7lEwYucME$^%0hFAhkq;hRix|ODeAdxqS}MKvNV4RiE6ZP4frN2pClP zNOp!MkX3-39mYbOaWBg`eZoUVK45b8B*Tlm!>XFEwEewu?ekBN|@Vv08h5VzPX^2TdY|une84QdMcM0@GHO0JTyh z3zm48cxybW@*pL=XVID4PP7fY%~FeSF!+_AjSG_Vl?21;B^?{$nU8lGS>D%A6@}}P z@=Lv8ior2q2rlW2E>EkR=JYpz{-C{ur84?XUq#D1;Hx^SQv^jLC`ag_#9O)60Fa#6 zcq8?4Vq?nW+GsEJ4V9~&K{VWU<-xp835ipybWuUI(V{Ncs--WuQ&sz8&U6q+)h8or zw^CVwZ7$cu2dEp(p;nsHKrgl_SyU&}#E#U5zoz#$t41dXCJw6pQ+B zlA4LXQ4uxVhqI)~C{}eIlA}LP=f|3rt*X^751#UWON6B(+LuZWdod&!ui9b9YaP5? zf0SM-j%m#bB7%6vZPuxyZ)E7eE{uYQ0CcCkGMBc>puF0|AHmoNu$P58C$ZBsck<>> zSydw}V?}ca2k?rx^)KD&g2|mXs%ol^9c--X1Nwdvm?WVyt~3C`&Qrfo(w}f0;oXfLey}_6;czt&J&m#_|B4B27tf`=E|L%b|(mbD_I|8O0%;MAS__fmK1=ao{Wfm|za=SW$ zdlINOP@*$wbWhtqxEMUwLpxYq9LxLN9bVMK$Ek2+`9aC2C$`1-T6P%GrpaN^Ac|3G zCvzKWYUx}RQy7A)#Q5hFPvpXu)swMfxal1q6@W&cVx6gBwbLr%+cI2u;4@k3HLM2tNm-DY=Ad^- z;J*6Ow!gBynm5dWWkf)ci#dW^+^D|OtVBeUNBp!+Om83)VT)VObzZRbl|G*JbWq{N zg!oD@n=<4z*vVDa@+DxgBX|I8mwuwr^K%>zTqUy@mQ6^YU;Zi!FGZ2f)?V!GX36hr zmh{3bpVU+>ObAvDR}_1tUg+hm99FbtMR3&Jhx;_v=5$_z*^#?EP*4!wXc=*aPOFBc zheX*(KNK}x0&oG-872H7;tr$tKj8*S0%1uJ_^_C3&w+J~oy4+C&u12G-nbEN-NddI<8Sb#MjcHuIwZVujX!2`CxQPg_Y#~m15BE^&jVf- zgYB{}5v1gv!z3AG_-B;sIm4;SdJPKKzo#t^A?!~$qOoy z4DxAn^UcHc0QXsWogr<&kVWCwO%Oi^lx(lNvm5?y*>h#c7x0w40{Y&kKo(^#m>#ZN z_Lw91>e-vlSHI6Noq;8J-!XEspC8j(u}_!Tycp3RErHg-q!fmM%G0cK+0=hL!Svze=SsdD8ZH65si)6)AhKKIZn`Nu3C@#MXurYJAL}6WTNC{&Gi~} zJi(@hPTXd=QOrScp6oD3U3;|%1|Q|Y37NqW&&>v474aD9rY{IdZ4l0glda7+W~vpj z!-NinVxYw-g)S3?3RK#(Ya9OFplGjrA-vsX$^wP>eCsO}AO8)hE5@$g>ybXAmm>D{e;NCnSQF_y!ybu}S#mN|M`1rQ;LP9q^nn+cOMzT!k z%)yN*-IPF7Zg>aB)K?YfsBKI=j;97yODzdHLOmK)3n8?39ft$lG76aOMXOi@tC5~D zpFDhNdMjn+EqxicR;MRfZq#PeJe@zfWv8!hRbmVOM#}B<3u0nS4f^y{yJQyP%hGwmX+(juaTuZF^|u! zP-grBiXxWQ6D~G8fxp&bi`OZue^-B*vK{x?!EuYl=~aGHfwO}$6QA%1=bQdy9(%p? zOGN6Z7fb=1dHl)|exNJW2pWs`mNRc;2!6+Fes0`CQeVl?@z$Vl+S~* ze_+MHn`%ZZSMRCbSp& zmE!Lba~+{Z2eqV)e8r2EIl7M^>rQc^Nyem9gfE+XZBn%6x-l#(ZWlhFkc>PpfFC2F z5a(X4tKnt;tY)R*MS2;2{HUXxS>}f)uw!L~H@9MFE6&@4r@YxdVc1K~?2ww=lSjAl zf=wNw7u>DgMb>{~Y`zP72yq%Y>V-Uy9}+8j0$wYghCut%HG8Ke_4(Ps=zb3&8ipJS zP4oWTLOO4hnap4~N&|)^$~AkTbgtR%t+X!i*CyA>WD%8_HY_~tQUADLb5%%&j@B8&|B``7fC0&7YaeM+Bv1moUgoZ;M5nf$8VQCa* zp}S<&vz75P_*Dr^P4EtzzwZ@G*+bhJ4oPYF^PK`R+DOWfU!~Iyv*5<@(bF3|ORd54v78>mP2Je1>I|2hb`-E1@FSEv;G)^uo1P5 zfh!=(K{yau`(up_+9hI$Q7h)o zv=Nmdi{M_+Gs{R$&NFYObnuk3_Kkq{`y5%<%G$K0H!$DYT1Z;to=adptxV!)Gd;Zf zhB*tTXCx}ArwbF3bKL#s^8}sUWD=g6-1pavGxK3#x|@qoFD3ENuj(O&m>pJ=Ubwip zrE5`G-3~QP7G`GrT;y)dc|okt!Px8igOCT9p1IX>+;BSRoMHv74i@<8H*z`|pZeX- z#x;`+$#k6p`+#&#QUY7j*-cLP+yktoWsED-ylVI&@Ox|vCSmmrY_m`NS(2kY`a$FG z+nDy=IQXp<{Jw3Xr9fz5sFEPsv(WU$;+4v6nr&dj^_D#T$e1Euh%1blNh$a8!Flgx z=;WJebB3EzCra+PcH-n9*^QAz8h>-|Zf-&M?!s#@V&cusuOPoln`_tg&~ zK0?xNWMv(8UM;IcPem6u7kv3@F{zD>fLqFV^JPZAJW9ZyDc0K(mv9&B%n}eN&Gbzv5W2OHasC6TK$8cy3UDb(^D^&a z*hGR6mwvG7kor_x20AYa&O+XD{`sIHx3!XEVgQi68j;d*3u6hT-75|K6isDG(25Hj zRVE2?xFtJf;dYqK%Ec-?(pQf7l(&`U=7dgBucxiU6$D~WM=MlOV>2?<%+Og)q;CF#kS0k8B_H&ZbzWA}B}S_;OUUQS7v|(p9pybu{Qke;u`uB;~9~%B=;?%BCMn zXPuOZeHhm*{y;Fp~ zRM%VGgC*d*7aE+rp$pew^c}H5RZ-RHQrb=Mryaa32$?KagLuCwcuN~utaidXD|xwS z`57#-cC&r$K`O^*+^QagzLH+Za?xSsIOPip(2R(65t1m&etGjmR(bDg{7h0Fr#(WQ z;pAa&&P_ypt*!gW%yjb2>p1ma`d9#$PA?V?j{c^-rZxKt%jK6f^}e~Lb(A5_osi>t zle$$+kPb6hUS?(iZOqF$2L4wA*Nqz~i5$TLzn+*8e_p@13otip_ITA1-eG`OFkx4tD` zYx7xoZk!|q8lm{nPBXb$ zdz)ImDo+>+u2PwgLeEwLbc?gb_hmzR$AGWX+NhzkX29RM56EVKpI8MNk@(SdO8ohQ z1|#*e4QIOVA&P{#+}BvcO0}KzASGbdsq0Z;1FDiaDkzPm8*J|qu(E8$3N@b7G#%@3DI+nb^VP{Mv@25dLSMs5 zNmb6*OIMZ69sf|fc?HNtdb&;x-)kCmW+kaea95>s_;}MS#b`iN;&(Rpyd`2U()k~R+q7RWs-4KL z&A;fEQ5aurGWObcF6NJaBgOPHqJ3PN9wa`0=vTB|e8&Q-yiOf_3%I%=jC&f`-!xj_ z9c!_}B2gQ;jf{#5$&xhCR6Rq$Bus$0yX#K+%(7SEWq+gINvu~Pu6 zm)<&yTt0j6qnt$RxnYu+#9uR%xM#LT_?b>;NM;0{RMwF;N z0oI^Pn_dzrl{$Gn|28O3%{?Q!2=zfOT>#uNs_2>=?KZ@`s_BMykTkABf%#qChevwy zrRsW>s=}74p?yExNA{S*C5CJD8B+ZwGT>Xa6@){LBy2lqTI%vowAk)!Z$o98&%2qi!M_ewgZ2RL1B)obbU) ziToLAVZ@l;tMiO3c-6_3@(PoC)Mmr8bhe2^5p?5fELOca+8*z_^>936=W@l4XWRG55|H}rPj=DL9{WP%rw(h4nw|~%N?4k6dfCIdK$Z9WPX0UQpN!MqpR)mw0H@~c^I3v zx|dyuBeJOT7ZC+}cmkq_H!C?M)I`!+2j{?oqNBKbc_ue!cduN?$s=_4`Vi+Yui*+bn!fw8wrNG{k%75W*Ha5aAg}Wj|WIm1jUWlLFUTQidraNDt6;(43pAZ7IcFUAk5# z*+ACxw7ni%718n(FA~Wxh^Bla$#qOU0@5i~5rOqIslwnr%($0V3wbC=$xKD*>z#)Wh1c&C1O_R zUfbE^WM=D!wi-UIgJFStKT)mDV}gR5Jyeq58V))HfHSmK@3x__iR|iqGcyaoaIoW} z@bGpG-`4it!b&>{%N!GQb(Xiv*sA|{?=Y0{IY_<`h1cm4J|X0U`gd>)*RWd?FnjyN zPD&A^32;Eh z&J9WEWPUwXYrn86fLCimX&?5gAw!0+Km!FJw%?Q|c@WmpYb%$2b8~$-(xh`;ez88A zv9~yZyDz;23^*=bXimLwub{ai__a+?pg{%@TFBVXrZ~?rcXUrmaNpl78Ky=vU(ES7 z;|WusPGFdwX(nvm&R0v=FFND19!mUy=f@AIOo#M=IPagcUGUbDHBV5K6iVsn3nQ+YFu*vo^8IJ*+*K@P1p%0FSzy9Im_tUm=Q4E zBsk$ptz~GeZk)kg!8n+1WWB8-vmPKa+&{ugK$R37%iir~1dphh@++I>-Pnxd5VW*l;Ilz)D}b_xR-@t0fV z9rkOkFtv1a1Dl-W^f@!xuTJM-VPf4a0tF7Q1COSVL9nieqY1-FA8QS*hSO3BxDEq~L6`-CcF+N=cct6|-_}3q zE`sxXlLVDdE-w)6;)l?Sy^}S_g_J9hK^@k!L@PH*LQbc#wGV}e&p^)aBYKcK!#LuE z8YHJKqy`WHHyM(v);_pW6cq`-bO5iQyZ-oOXf307W^xr(+8QnI)X9}A2tYaKNun#B z7Ty+LeS5ZX3Z^gs%jcy*U3gri-6VU{yAk%U&kUvyAnq_DqN=d6#Wc5{jz4*gNz8#8qKm3BY z0fWLf+ChHH0`v(V9A1;6AOe&b66aJY%Ab2^bS0{L?{qtU&IwMMrTN)i;YDyWeSeab zrUI5Ub;zr(cfN10D(s9uWRBiJ#|Q58_#B-Qwt1PJz-`4}|pH(v*(_o_VCXxj}Hjg=O1NfL6y%K*CBpZ%bV;E@h)N4t7^?GE{Sqm%=O1Bk1wF{0t2=|^$fnr6e5S7U+% zBT^&Q+X*Lu1O^QQK8O53Pn_v_*V&VBr#B- zDW58%+YWmd`GdBPp5Zz%@{r=Uoj{gdhXk>{Y) zPZb+>T`4VN3fT8jc&T-BxKOYh`uhmlK*~@KPap6e@{3nc(XDiebTmPiQJ4)*0qkC; z!j^1-J8|Qy8>lFZm_D@RwYR&~IMZup=+4dZ%)xH9C5lDfh|uv=Y&MR&-W{EfapE}i7jR!5C&%qS~p=G9fCatK(c`fvWwaaH;j2rI6WYPOAL(pT;Vt`MbLLf4_J{EgGSF&lOxz zJpXYAlJg46r$6j5=BRPNKeb|vQ*cEzkUrj_oDqfuvMIW9>N2CKUpAhCIi zg<1Ue2Ou?{T;an41n*(*{!7=VLm8U-_U}MB&hlw?X)vj;Rt;;xzB&;7>w`|C#-bm{;R#VxT-hBF`=`=Z@Cj9Jh1J@eTPe?rE2?%|ka`nuP0^?Mpm?oH10e9f9~ z&Nw!f=bp&zW>x1c*xrL)lP3Zh$)vN3+rZ(FZ)W?chc#Qf@h{+6#REU*aN31Q-=z;v zohF9shP@hON&&s|R}n~-$+s7_+*co5M`i@wlPY`A3%R`TIf0KH0q@NYpeGPnWq!h6 z4_2{-gwknzDGZ(!`j!Mr5h;1;haOFRT4N?%Z+g(p9E+Mz62)9zG_(s{e0eAy=Qzu% zLu0jmSCH863s16;nhxI{f_AGb!Pw{|hw$sxtgbX0Vu0C0?p;9lDh`DI?e5Z)saLbe zpjpDT7z;PAg`*hu`u?iAL*ce=>09V`HgDzVZPe1R%+avU#zM-8X3rK3VSNLlv2^F{rhbDlBr#XCnwe zob60|G+K|AP(^nePnpdgmyE-tbZ_DpnZHhu+c#5XuB2#KSt_l-MXG%klDrFgmg6rm^8;-n`)h!Ny5&tH5wM`{E@F;c~O~xbGY0WRt+ame@F-P0!RI+8utFSY+pw zfhauKhRL{n?b6|Rt1-O`%)hitARulLPPri?Nls)lSmIhW_tkV*Y6*-;MAS^9mv0Ny z)=2eJp>X03YcRE};jV_oV(~A&kHG1yvDbtGgjLjl4il0i(l!c}79%4nw@Em2w&S&r5Syh;)KsyKL zE}{Lr%1@Od?H~j(y1t|2Ek@**Bq|U}1!0{)caCI=RBov4o==nZ`CLC{fp*sVCNDLB zoW$K=R(5Aen2NuTm82jsf83)gyZcgr36{U;*Y(~fiG*oQgc2?fB&^9Gf}b@til}DQ z@Sq}Sg7MvE@a?m1KI!v(g z2Nx>j zI|iA(x(mvZ04T->cZdjDTs)jE?5KFE&cUm%*@w;!8lP7DxnEPmv)}F{;@kC8xdUuv zv0U7r?<@1>@joOYFBj|;UBmJ{9tGK zXjr%&%`7(Vj~rb3TO@)4UwrzCl91*7EVl~5{^o`$5j3cBVy|dqNSOS2%F8rE1h{2! zsRJ%SuHn*y)n8tE{o$=~b=xwY&C)pny=deoa2=X!INl4j&`oBS8pr!`)kn4CYkd3F zwX=G7TK7)UkM1%FZADoYG45Km$N0lPma$dBl+3(SDrv`KKl;5+yc-*BC5Q?pok$K-3UxoSDz<%OWGCT-hHJl(R&mT<_u34Mvl90wF zu$s#dhARb&%vW^0_wmwWDaw1a47>LVFvdoH(DZQ-h4axl0rvRjeAxK0g$nnb)V z2^k+#ku4W^_YjNgu~r4wvQjmvZyUaT)RDXG^?uf#(kRe_?&2|b;$+9~{LPsdvcCV3 zTA8xz6&1f~1uR;uKOPx8npuA3W5Fl6IHCcz>j^+3VA6KfQ;fkffjcuJASKEr`Y`blF!8}%a$tfqBf|ARh&F~ zvv_!4vVBrOmVA1e9(AAKT@fMz0Rz?J;N24k5X^LL7~%Z{el)9Z3(pnUEKVJn9s#@A zjC4xf&<(mPbg5WQPTQS4h0B=Lh!Z5YG}HScM1+nEpS_hyZ-fn`7AAr}$xZu}zybF> zzdFU3AxyvN$vQ`ZLn@ak$5*%s+^>r()8O#ZRA{eNh+T+l?cSL=iT=%9_% z(P;6fM}xl3hG*RCSRT+znr?;XpkS4EI8Ol`lyG1F|EvF(KFGm4_3@JAu^E)|#s4%G z4)z8X9*dx{p+Jc<&mYz=GEe@7>V)IJQ=KR|Ia*oRm^i@cN9-LON!fTg;Vo2ID5{UlBXHi7e~_g-e*d3jDHe`aCbVi+7RDx|Y<#3LHcU1qjxM(LmZXmMhBgkS zw)WPBjuy5y4y5ppr0-=|6y!+_ZH!569nDSbNgo?p*%}%<(2=qz8`?keqOkEk0#t=l zsW>?5lKu(hgSHM_2H^aYN=4Dc^|2Y?-+?`f{t6g7AE}nPoABQ$0X&klsIvU47G--A z=l}G@KU8x4yUIt=U#aAHRB2&k{@>m3w;1TUeM_VIX ztG|cxr@eof7k^m)Clq$pKl10Fq5LWOD=6H2q)Ij>Opdlp)`m82q!O-%)}O6R{uToF z|0Om5%$Glsf}NG^zenRw(O*H}`A-ONCL&Uk{|5v-e|E>eaKbG#fLs6Q1vrGiHJ<0sc>ks9f47(IQS_hM9yyzoK7rI6tyvV|>`83@adHE2K7RZ= znk9BFHtv6AS?bhLh??bk+l1WXvuJk#B@as%dHqY9=JWU!s}-Wh;eMu|rm4H&n02Lx z^NLSPY0jr8Neb2Dp5$NexFwFT!!$}mv1G<5VYJyYbzexbE7zs+9e-YSrXTfjsw8%t zy^n@Z3_?3$E@+)$>|IU&t+iC8?7bj>{@Ndy|8^elm>$WyT9(_D6|2t3 zJ68GgEj_I@r-62aXa@u8T8}9HJttLxKXc{TD=C7FjBih8Ir^ULwsJM7h6>gs;s~BBkXMX$W<{H3xK^RVcj+>M9 zT028aycnTN5{H@XDS)d?q;hK)5v`{pDAi0Ui)~hl?B}ln+P2&0RalrUqoHq6!zHJl zpRd>yn|8N<(B!~mePa1)kuBpFh_aHb`rRu-rYNF;vUoIfjbaK;MRX)$5ApzRMr44m z0&4oyFVjMTnq!vmPva0!Pcuk(Ocu%V4WGS3K{}OJ9x5wB`R>$F`eXVT@3VeB z%Smr@D~cA-kLGZMsHP=Rk*8v01{?d*jhXzwlZ5%W`wb=Qo#2 zRV&PIk)KVA*e+-j37k|L0?9NP2?)Th)z5v4=BaGLxdzY>B9;hyT1macjo*U2zPci8 zcr7=7d9{mmsfRS^MV9nY)O$^1QJM6a%0~jsWd>y$n!=B6IWMw48aj!3A_cu5WfgG! zfI9o$m+ASjAN~Nfota6oe!Um%Ame@#Nh%Y< zqxVfF>A5_`GqN^cui%W4h^G`UN+f#iURw;=9CAz8m}%pQXW9Is$iZcH8!|x4#CnYx zKB2HGj~de&*x|IP;DU$bC=n7Hyzbb0D;EF07av`9d7yXI$Zhc{=1cs|C+;zZbiPCw z0>!O+thC<`ZwI-ParI+tq5XqJgBT6{Ge!+=@Fxix+?@F44N{t0Y;3uP7Yf#app#`) zZJW!z8lVph(eM}XrM!~wDdpzu%+C46*i8F@nsi$HZ}WOJhD+So9&E4rPwAhvqkLcn zDb%fVR@dywl$N}LPka_;l}eO++_EAY9xA1r8s`pNZseTm`G{>;N}-ym=nr!bm=9^y zBrK5)82NLCrPVe0?Sto)4U+~yAJv4tW*85k_X1V!-;saZX-_tFbGQS>ll57w4!L1?3GLDlD$B-sam8eK)rxE4w2~J7{6; zR9XeVmRm5Qj!T?6A)DbT66}VKe$yLoCM6xX%zk5Xy8I(-?MD%hlXi7X_?)F6SpnkR z_1pr`#@p-0Hti>WrkdVoxA@DSbHbZDuOI3Vd8`Wq%L)wjiZgE* z(M--AuywS-Lo-cBSUyN+IwhYAA*)MQg?e(~=6K(GeWgtb_Z#0Pr6^FjZF{nQnYHHUhQ-<}X!aa7=+R}#aCW!_Em?qHp8Sq0wktL$b ztcj#wP+Q#%=nz=MFP0#BhyLNT%g9KuX8;SF?ILDdt9%+5>y(t>zhg4;R!`wN3rmM% zS6lSzL@VKVA0niVpT8t?UT7D=M0@t& z<{z)JirZr3)k8q4xY0FvT78K&_D=Z30ijW%xd0>iDNx(3y3xHSLTFpZ5B;6~WmjZx zmE|&u$**=tTn`y5W&XJ#X8vOw{RBy!gOc~}+=lRC$;9uf&0IdI;O)Dq1ivPS$dOUH z58*?8I8`)Lp`3Y&+?kn=*BD19YD6S=4(62&t2aEf?GE|S8xh@^g=GmcQ`tKsm=B-##PH322!TrHr@k@zv@g zU+gR{p?l9Cl`_*4ck*59jSm(=lH**P-nPWpyHjnP%8sIOne`?mEmQ$lE|(%V66`!b zghVkMS$wQj=19?w%Maq81X4?t7&mJ7x^jGMEMgy;1Oz$&lk7}QzH%{eRKmp-F-O#p z6n(8c5csu=eL%(Ui`Ww=?kXBYexx$S<)8nYe>Hp)j-tklOw|t?e>>E45*6)_1blY) zsimQJ;-QbbG@1p8cbht!E$Cc_;6CpS`NsgAMs&OL<&mRX7KgTSfY7%_08UrJ5#ah{yw z_r&ul8;k>H^lNuCf@T3i#pHybo%4;op#A3zMdzP9{B>^Y8~UcHPPnJg8IN!8aaniV zZnpM~_K|yLNEG+haqkaq?iw0`2HJ)~ho|=%&LnOI>cxVX*kB)leD_>B(}A zwJX=@yK0F{kL&KG%lo~h!~3Cly^|xbwNmk##mUL}vgmcj z<{F%TS05k`GDpoMpR}2{)Z1_mA7}W~HC+X>?(ScfA33>n*EmdEDZW}`U<0>Y^ixgD z-K@nN?BChbIbL|zVKsQP=*iACEhyTL>EG_ne&b)5uOwMGjcVsFw(m;2U~EXZ(hQG2 z`Ei3w)16S?g^SdkaM(35bG(-4>9Vm;uQE}G8L_{>ga@2{N0Jj|%NuTs5k6c>Lj2P? zRcdSX-eURkhmGgGhESMcrhNw6JS9o`6M@-?{a?#|Cql+RI%Bs}Rq@00CagD}c68*I z%kT}KYgKWKaJpx_!w@f%Bt;m|=S;Y})V%*MYj1Y;f3CfiSmZ4n9RFA;I$3`*vA3`> zV^M_P5C2Oc!T!%R)&Fc4j{m(Dz&{s||1&LI|9fCO|6DBpkF;>G{_l7Bmpb5orsaE9x z&i2@rlarg2os*N42VR#xN&#$twtn0LK2<3xCl?1P2P@|v-?5T%vvI-qfJ-?z^hy6~ zl!pTj@4w2azpt3sSlQWG|G`qr23O0*!}G5N)UGGW2Z9OMW)sKsYXr()9}%l1aeBfg zUzwi0O&omQ_z_39jlhpmgp|^a()TEa=Lo-ZYMZNeXc?-I0%3WhxIJl6QEPoX$~Ckw zv3Ax}T`H4QZE<~{XFc7rC1Fa&*VIiv7aPPf&^sCHpBSgh{!wwG;q}l$@n&?kN zP8_ZxL@en9HZb6mlL}6x89X0;Ks^LHd+gnw*!mbTiS{3eNT>1*92^(UPTRk$K@j5J zeRU|vU&Zix+XnGNd=QDVkk56H3pw=JvB~Vx$u;7L+KWx6gtwmQi>Gsotlqd}n1@EH zZ$^mB9%fp7_5FiJ^R1p%(?(N z(pF?82+O$-$eFj&bei}?)eFhZa}cp(@=3ehxtSWU3Q?rM-&&v{82h3+<=1m)xWXPm z%fWky*@L{%y2bPCUgoL{n8HW$fV7v2qBIhOPJNuFQk^oqU}k3!a}XT$Lr`t)Q@ZGm zkd4qv9bc443!c-18Tu8+&uw}B$#&`9NYDD&m^B|Eu6x${a!lH|S+f5_*E_}N!Uf&B z-K%Y{wr$(CZQHhOyL+{5+qP}nep~0;7w4S4ll^BV^J*rQROUsc@{BP~l}%Ta_M*Ag zkIIjp5{@<LdItbFL2#qX${h~dtj7UqQ@Nr*e>AuHK}zTmE;A= z^$dfiJwts1{HR_6$s~{`HtEgE1&9UJg}uZ3>@GCJgenHQJE02_aXzi6RT=e&@4f3f zQ%r(4p=K}+eW5fNYZ55&CyghS!9H2OS@ zzN_&AVF-k6m!lu-+PyaSx!VTaBI1Dn{q>6{udp5A;M%|+zOtd+skiI(UfZiQyKL8| z(%RX$SX=DXI_<5^#cng#C7~X*T$Kp&q?MOZud>c^MA`D>f@~d?h@mJzebS#H>}j3# z#sw=2+cq|~V=UNKogzXTs3~Zyi3x6@*YyB6iGG?47!ob+m>TS^8Xe>EaQHvP&XdU; zdbs$>UWTQ;OIUVHL&}3sRsbA-9cJ5hPBxq4!E#zuCmDiPp#8LMC>icYfVNG3j^16^aA7iiGj`bw&6;velt&tNiiYwL(3Po9x)LhUKf)u#SIxTUh;KGJ+X?T(d>c zM|2H)D5uvr=xV4K-doj#!WeHD&LwAV)Ecl)9fZLP{TnuCMd(kEtqVZS7%J?B!{Y36 z8utrvc2{7uB4-P7SDN6=FTAd;kv|uC zMNH87b8hoNgDQ*|Vy{mzkV{c9GAW5*Of!CZWN{is>r4R^BI|xg-UT5wK}fWip5TlL z=`IR9{Zjjw(OPzjnn^TRWTC+Ni1V5OJRt3o7`zn&lpOAVELxTCJ-hvhCX&1Zm8{Yk z-ayC#Z{mjpoPyE>Am1aS+-0riS8RQif&=(^{)pjnMnPkfXS|plnP}KI2fbmD-+MVD zgs^#DhG@-YZ)_m^M^KFMmyx3`SL=*n!NSrg0mq1Yy~4Az67 zXsG+C7o_U5g;3P6b6pQijCFmExm0Bh~C#*qoYl3A-B5iRKs0Zsu;9 z9t5~;7#|HY8|d7H!Y&E)&5RW)9RJj?2iw&k24hd#YX7&$U~E??56rF~m+8(WpMwJ* z|4d*pv9YKpowhg@GK8_e1C9~H77ddDH7H6v!!a;bK&M$V46$=(&s^HDg|oyF3rC`{ zX$bL9;7)JaauR0aZsC}QSWr+b@M+|d9El|4)Hk>bp7Ml$dByM+1)7+>sQg~ePJyBZBAIshes_mPSWZ=N!e*YFC0cn=x; zR>p@ojF&yW2ChPjZa_}UlsMLeI~drm-!h9UxoIm`-`@Wxw`^0{Dz*i9aV{sr7%JALNRFD_t{4YAk$-ieQU{aaS28 z;X-2y7{HNWvVbthvj?G-nL7r?%-J609Ec9a9^|;%poU9U374I)W5KcW8Nim)3^>aF z_8c1_2(pB=3ARqaxD-4is-px|w#Z8NPPN)!2AT#gImzOEzmPvIkF3c|pW~d6x!9@dt zIc!L(XwC$gk02E7tU*;<4)h#|Mjopm>QxM(8JK)YLKluhnOCp4AA3B_i|<UhNLt>RNaL zyC`TBX5lF^DMfjg({TWty+JsuB!QL_90i@a)th+B)+)e;0Vh>%oX=;1hJMR1L?q#Bii7B%Q!YBE-6Q4 zoTif4px~n*HxV1vV3<@(Y_<~9BvdIsDnshYoFg(O!OB#@mxV^nRW9nH4nwSDhjaxh zAp5EikVWfSqd~#@S*$i+0ScViTO#|N8VPWKL3bPC@;s%V9zj z4FLJcU$FH6qRtMH)_E5J5Bzr!pIoM=2rDj@&>&L!vf(>Wijv??z8oF-S9%j$DI#D6 z*q@!ZLKWw8H=+RsR1qacB(CgrJxppSJ!c!cX**w*l9G<4{M=PvAks9i#A*^lSoe+z zfmt0RuF2Tp_B9$?mp7!lU6F|$lT!}#>!wS_>sEsTm&B4N;&mz%S|`Hw`*x3itAqe7 zX6#p`8xwa}dmu5|@bsdS!>I&CuektL0W|~Nf7-^uZ&6PRZBI5v6-EY$;Z4lLj#{{| zq3tdn3y}DQr>UbcsNhxYgCvGXaPWdoQ63^*a41$cK*R~`Os=lAS=}cidi8P{{8kyn zPX$t;?ilWv5tM`3F~;?p`W}NrXBX;%?w3=)?!7 zrvu!Z$3nIo9YoMsK*T-40*ZIomwM8o1tFKq=^E>!YeemDg7MMbS znzG8C5z|%n)8~uzBmIT?nfQw=n4+)ofH45vSVf5XR(e+G2p6Q8jz}^ z(ig;Ct3R81p8j7LV#`w@0LxcJzh=5)HD7fJp~$Y zIEV%)6cX(7Sa9;P4OxReaR_IQ! zUecMy7E-U2wo=-R|L1jeX=I&2mm1q(iDca{{s86!ammv5PhD(Fd#JLN*3gGVXI`-O zei2a(2kt*#HriFF82cvN&KEV7wpvyn@$eU#=zN$@iBi8JSE12evnpXT6SnNcxd&W$E4+W{tV-CWS_}#n~-DI;sO^>HYxMputlV(UKDO(@*;l%hX>3X zQT9SZi=uJh*k^ZQd@MoS@yMX@SOBmwWUU`dgkO}$axCaF6vnp&f&so52!k8M^!npz;8=!Wj!}gX@qQkPo#> zQBN2nMXX7Jy#!6Czvj-IFvlNEuBFnnOIFcmr{*RGVggja&GbvXDy7un(VFT1bd@_z z%4YMaGwdrhv^4e7SgDl>+0S9uRWwyKH5-;qa_TZnV`3@Lph-WCOyvA5E&cp7HBHdE z9v|E4mDQRGTN{0q&*1kiuC1rOzI2vh8ueHs zGa=*8Bk8kE?g7?WvG}{l#|!gLD*ZJnmHzG;#-s_TmJu`4QP2~cF<`12{B2|~Xrt24-`}E`7Sf~3Fkm^4#Nz=&+i0c;Gl`IbyHLubT zj7~E8Ynzidr$Qq;N1uM(Nnp0}0Xab6Z&?G<$w47@HTqqbq6ED>|tt@SH_rPD5+El z3N};^dr(6Sp?uFJ4A#KXOY4O4DRLZe-SF^$&}o48A^M*m(y3*HD5?z;Oj^R!0MTW; z=;R2_0U=;G9%=Ag!Q?r+9d)fI=E`A1`5y7Z>lm~CsfUT1bAVwGqAhUmZ-AkkA_5g5 zmYL@Aghom5xLPU7r9f|tgnBJ?LJ)9OUJNW#S1k@H`NMrA%3~+WaHsBqy9UB1R#y05 zqF~YVqQ5F)##oCcRA9b%QfcECR#xSsu}`ujxldJOC>Ts0c+Aq~I{69#4^>pOW&>QA>y&CCoTAn zT2OoIjpn`9)6eU;16Ey;)?k7y1PM5>xw#gLv+|_Wpg&MfEeQjoBFxIVg0)~$kW{!x z*VaUE z{7ByM`^ra^Fv;EDq`9X<;5ih!jo`_KU19O`yGBksBYcCff6E_w+|H-!LR0A>H@EiT zAP6>(uwZw(_)k+8k~_*PLeR)gNrB#BY`1AlO`gziHuVD2NSzrt@1KK1+HL%NOdjS7 z>hfgiIU097MpW&NW4Aj4&$)d*`-$w|J69RS|A~)x8&6IHSv}sw&PK`x_Yz3j5r~K( zFa?5^w`o$qDJ4K7DiF}fdrEzxK#S9`PZ^Ug*9AfinB=>M?frk^qWOoW(YR}Ojq$Ne z@l8I)i2wNI?c5>YN$@{sZ}mN&{_yuCwo+J*Rp6!f{7PeEZY^-zLEsk$aas)^H}ykQ z$e58;DMM0PX;dz|%m7oLTkJ5arKr>BPNbyI5qZr8Wz+cpo^hsTZ+mN2lh}6+)bT6q z;9BYV`t2(?oId_25eOecdiU6XIE)L2T5xIwZz{x^-U6arYtv2vfT#}54=`#qR5H_o zLL!v{#6<-yn-hsT&z5SQT$9kaZ3#*(QmukYDVAUie}!F3Arn+)6B_MmsSQ;qBxX{L z$iBZSYHBlCb^UYkd0QT5P(5!m_P>CZPk1!&ZE-Ah2(yQOhp)G_l_wvoEto%_TikMB zVs|_9Zg&wY%qC4AZUrRO9JZ zu{Y>m0CcPqKI)X}#ke|>W?us=^j-Y$i}vy>UZ>xg)?$(d zSoAS;VLer;Lud1U$<8ZmM)~pfesoMhd0vc*P*ZE7U*8fdsR;L?GO zIXHqZ>e5vd@_&FLOw0tk50#16(s@*jXsvoy=#=$FwY}n!E+MKex31*}Zo$SaB=gdZ z86sBIA;Bh+z6&UVA@;?X^Lak0=rN3Xz!v8RmKsOMzu&@Vk6GAXa5QPAW_6d=QM6df zE@kd_jjyZRSGf8<6oQg1%F4XvT!TSzqQR+Dd9YB`MTb_LfV7{!yKXss$lP6XpVCHB z7MSB@qQh#>^VZQf){dxql;%gJW|oPlOQx4o^*o>20H1xXPYvl15c+(lI5p)MuD6gW z=@89byX|Ma?Cy7dPrcr|>#p@@)ARE~Jiqnc_c92&#zaTg2>Fweu57~TSv1p$%R&_- zF-BLG;xhD;yO7jz@Z`0O5Oe#D$smK6TdU!rfe%hOjE4w-+;ExFp+rZ|m5Nrp#{Ms> zv(YpOD!=d0`;9aA+GrfxgUDTiA+i&{USb%T&+CD!??gu*&l|UcSO|PSP%BHx)rJ=%$ezNRf1tFvRhR{Npi8`kq<@mNv25&C^sDeD>5|4 zhCGJx3IjFvKPE%U57jZpJy-n>TZb{cyPCm?7u8qct2JCq4L2`&_qIBl;akpKt*cJf zk#@hjnYA9TqbzXa+sgxZn7+w`J+95$Yc0*T{6!va^Vs>FLpv4;Z|+jj*FAzHLtVw< zQZjNls$?{wPSh#WQ>Vt-h)Ai`G^ftu2&m8GeK^uGdH&}!{&WopLQBk<#5Fx`rxPYg zourqAz6S9EtVqtnzl$aUYPk9>Bdprfew~sDYPMhdzHK}?TZ`u$-RA{$azR=wE>;?s0wA?Qzl9UDkk<75$fr~J*HydAN`+j(duG)eqS|v z`tL*bco9DChq?Shsy^YeeP7~g?j13?&L6Z9!lcKqZ~~f8nB$sENvKwwa!8^nh#{3&!ev? zfA_|3C#mn|ahZm{?Dk8DSLKyR$f?nSgy2%yR4YmDCxJNC1+SG!?GjQeVj8N9MW?od z#%T?C(5dlbbLd#?o?S&oh1Y5tf`sfFo$1q|wzfx%SUt0Q^d~F-NSkG8%~OP2<8+2k zPDb1n=7%g!HRr0V$Z%Ku((#yVJxcVu7AAP^-xiaSuW`lGXgHL!W89lZN48X)yq`24 zS+|9QYv0>R)I>JTEq?KVCVj!qh?9=nOw1}n!~CV6&8 zn~>qaRFfi=Gvh);KDZ|Qxa8o8wu~4s?SOhW`vdXKok4U8;t@P0Ojd4BxxL*1u9{`V zmL1H3Szi3bZMsn(U)aTAiJ*$<-^UOM<_@?LmEM^R1G&rD?KQLAb9^1V$+o}y&p_{a zHL3LqZqL6klTvH5&&|SuP`RVS@Fi^ipHbh{r1uatmYZGsty-(Av2891N>@~`>S@7p zowe$CYRw-_WHzTIHuDCIcX$<#Elk7X1=}q=+>JAu>l;`u92unF<=$`oyMsQzq299h zhR?Chx3=v*_iMihm&YmTQMx?gH?kNtfs4c4knVR;x<*cM`d=}=v+uSDna@K1A#a1W z1W<2Xk3A8s8m&_$Wgo3*E*aPwtQaOo?PsaYYX>(kN7w%}nj=}P@4G;B9CE!a9C#m@ z{6^NbT-@2s-h z7zrWD?ML4Cr?s&)KMnf_;^F_cy6(E2C)A{88f{uj8ap}~D?2drlu9YX?<_PfESta) zVs1Tsq{q_3H^tvcL#?@~h_cB~hK}EIr@t59kRcI9X-*)dO^^2SqD&&A$joH&nvn- z=GoAbH~asVX&)b9&&pW5EN#Z-33t6Iw@ByJ_i!s4)BHMgA#FNC(Q<991N_TBOs-Q} zLt5!H{kw1eHTa5J&B?QMXzB6RK;>2Pg5B_n{#))=Z}C37`OIto=3Px0nZ(6kzxmztO(+!D4600H)&Ao7Dem ze+TrbFAWlKVYk+w7|c2)fQ%6ff)Pz*6WIf@X8soMu6w$1-3G)ojY+0 ziW>%h;x5K~LRTb%C%+>TBQb6uv_p;AhXe07_zBo=M8OITFmZ>#6$x9f-(tN^;!t>s z@&hdtHK^M3+V@f zrc21a(7TIBt|aPQIf4r)E(9I^>6I*#68-_k6S;GhdPNpak)IbM*!~8- z?}Cv*s1VqYU2F76rQd&XhNJ77n~87X{tUL$%V&UUhFT`GNk>gzrP)%@(Ktuc0-U*{lj^N@a1cR5h06Io8IUaw9CLJzLgp0ug}zV zcpP?wS43SP<{JPjGUx{y#vLv^#z&4tJQsnUn7}EXVPFkezCZyvrPA~bT0?4v=+{-i zFt8)cL@@?Z!^L&jfGAZB%UB^VdGp#f-WFOTn&sTSav{kF35`!mD_ruBmjL-iZ5y?u zE&8i*{)Z0ujDgZV2&SE@y9lo>-Cd>yk3MUX64AB0AG&rR009|#5(|p3AJd`JSD6;N z1^F^CLJmhLNd6wa-Ak9i*|FM3aQ8Dh-1u*?DGkHvlThXZTuiC}3j|1ZE=dx57fxUx z93P}6zzDw*}DX*YgCFJGnu8|B4_Zx8X9>+lNI&oJal`Fkie^;2%uFZAcR!3nVJv z6qo~kXbsRqAReIwIAT7jOb{Ie9p3;#g>3=@WDWjjPmXUOxId>D&)yfVXfa$spSI`h z0~xp+080P(;XDaq1-=k`1PAY+5XKK<9Y}k00m#_UWpLnt4@Fw4z*Pj}5HrMfbP!y6 zEN}|?iG2}K0cJAc36@P!sAlQ%+-?V2U}&C|=>4?(mU2v<<%rcH`1Zd;Zu4Dvaht%&>Bq!KA_Ri- zGm<6$V$6s-qP=vUjS2ATaF;x$A+F@Cgp88PIQO%V`IpQSDgF`_osgW7yp>~@wn zK~N9#eHAbDsG=h-;*B>eY>m4`{8Q#P2NcUS7)3C3l6uI$xsq?7QNE}y52M8`475;X zFS(^^SichaB2}~UQ(XO`I48yg>p~ujz{P*2%{=8LiR*W|S(; zrWPR82C3yn&=3o9JgE`ORD}-=CHyX_)yy@%-_M+osN~dGkyQ9C!4^eE^GpOavLVp& zYd~eFi4ACiItXHx)TMmclh#hIkO67KwMMQlz@dx*qpQMw&3{N9+r7XGZsV77B$@eF zCdHlAVuCOr8o}4gS8+~Q{?_3!*UcH>tylPec!)a4JZKrge_F&uJKrFql|4_(M_&na zyG2vWO{*(Y!;#m74M8Dsqb;(R{PFAF^L^eBTpI~U`96#jJJ!ZHW7Y*>Ocx`?hxLh= zG4js3=-^1cnZRMcp#}XCbs%Tl#;#LQS4KB|Z*I*k=Ii*G?$(+q7Ce;VP^~qEViaIO za)naxYuG6fP(NU-c#Tt<>0z`R0&($u z^fifz`qYa*&Xl}tfQ?i&L*@r@Np+EQqwBSDr??gW%B#eSu!dMLWmbr6M8Ijrn{@w}Lkg;yh;9uM$jN29dseO!rNV`3@=W6PqYZJb_b86@PcKF50LGx?) z1;0pk|0h?s23NNv9X(YQl}>jQO+fvkLvVd9MqMdP0Nuh9J(D*B@y!aiXI8#CwK`OZgHk8Tc|c5A^KY;N!CLr8nbq` z7i*1#6{=102+qVJh#Y~^q*6Qa>mX49qAs^prl_(5MkZ8dvQyGHAaodao2x(YLuAP z{Hudb{6u?>_@c3W07oa#nti_eK7jn0PUko31k#vPF36f`wVxG@KBx-QKHy5sCcFye zF8B(L19Z*!-Lai7a4yK^?4I*HZ)~prMf2<0-_7ASzg^rBXKe1nr%!%yMtF_@rY%P3 zZ?KS^yjXAqh6%%t5?j@TMSbSD)WlFpyKAaH>BPSNV_6wBtWXl{;O84nU2iVe(AnFk zTbQ#P1pA?$Qx^f=z9G+GvPV?<1M(AN{BQEk{xJ)d{tyG85K>lVbXI{Ppc zLpRCA_}*LXJvJcjyZg7%m5qu#uu8lG_o%P z-U%JZv?TQRyTB4*|35c>3zH&_={5k5xJU0ikF;KwwK$(Y-=hPs83xbC80qzm zq8JX3#d2sI_Dj2|TeDzoU|n{k6*oP4bj3h6)3*rVX#(ky>B=0hqginT2M z6>Eha|6Fjh#=K6|x6j4@XX~WutH1r}efs!jS8zQ^<2ea0m4GvVvb%~ZJgvgV4+mn; z{y%iAx$Z3M8v9q{s@{sLDG|2I1sL==|~RCntcC_RSr7*isp`A z`Mw`{pS#kQ)LfVPXP>`*{(BSNce~DWyl310U2ofEV1^+Ha5z@T5_)8M8}_q^TjH(`jxCc=b!8$WQYKBEA7jyGy7K+ z!s9nQh8=~q=E~O}-}F`@7DnI#M{V>~jjETUEn5L@Aopz{0Sbt9=6-7MOG23J^je!_ zS;zo@KjHDW($XQ7_3P_1I--<66k&&WldEa8O(L{K1Lk?l46AevT1_P;9!Y7|f5EYs3oP3Ajo#osFqhJ4f#ujtVa((10(?A1i zGFb1xKpVP3fh3&b(Zg z#~kgv)dKUluYfd%we_hi8zcLRU*AZ}|xa#!Fpe5$v`4vzmj z2X4Y?26r0iWnH4@+`9aA@1@L5zyxo`nRN5R_(GhYqI=^k@zC1V?fBH{x6Nm@AmzZ- zY)0Pr$o~0d4UC)dLjtDpgQ*7tZN8^`zij^K?CSqJ*6$<51x)SK2S2l%$MIy`m}vdE z-*+a=X3LXT7Gli3skhv5VDHQR=zc2vQK8)MxBI{77e6TIe&??qR3NxPT}!IzHesEZ zyl&iD01B#4vY%y6m6urCKEYVxOS5LA+v&Q6)co45gT6V@ZxmZV-^FiUw@KgcoS*&s z2Vk%Le&p8{uGjCNiXX}NaV62``zet8bPx95pSuYMCZhxhtavg(PViY9ObT=~LYPW% z+j9)A$bTYphujtwtNFT>JLOMZlAO5_KDapngNmqGp^FNCCn3D3hm(xYhamwk0`Z<+ zM0(7{vQYeLoHO~^vzoJS4M&@GwIw=Bdf5by0dC2G_Bev!KVhy^h2!e0PcIOZY1{u+tO(Wx0~&So(k)uu$L>Ywb}~{{hd~; zlcgM8gqksH$<@E&g?Bw3JIn~oK8yA)+ zEL0uZ9Jk8j$uASEj}Z>b4OE@=ckvxZI# z1r^7wYFkx0aDNSed-Cb)$EoJcPtdYkDqf*`kr+aWt%SS>6|yy)6edE=#IumBhAuCB ze9O7KRsPe4Y1X;s>vZ*WA}kaHu!FrA_V$z6xAsfWc!`%N)-7dQ2eitErF0HPnNU#b zl2*$?#BKVaRfcp~_4eXNml!n(Yb#o3!YxNYyWaQxS?_+K4s{9@)-GA$A}Ih&>NM$| z^`ij@8vfaXM;lrv=$5Tn(x&;HH4TJl)q&`tN?k4;{p;pKxuv9F%To^Ie?!fZSICg6 zm1ukp70CX``AdirUjms%ASo(MMFBH3os)0E<2%oZB9!YxJw*KOg%%SuHlf22Qwg91 zE<*;z^bjP|$W{H0nKyD$WDZD%YL^T23X-4={)=YmiL6+k_91rghk9T-nNXZKXb0=)6qOHoAMlIj#9t)8dNIi3TH6zG{gpjIDs6t z`+OBLDr$y274rQ_K3{@JUBtr*Kh<`5&*_SXd0Nj3f0j)xz&e=(n?%`F3ZI;52d z(g&}bo0KTWBYm~H4r);w;Nx>mTj5Kk>XgQdiG%4A>t4@SHLPIR3_~Z5BU_gRZ6_6O zrgE`F6(E8z1@4C#P?=R$=%m}x<_E?ej_{=zB= zAIfK0ej?{mHcv!ItK^#m@(HCTzfxv3w!BsKoVp)as^hGyP%{GEjZ4upy42h4En+%h3K4oq{23-BxDtDHAiGWlH*jid*g7wO%YQ*#LW$SlPlY zvswwAFVS*8T#pQ#S=nY)H89DbQ?C<<7d0|cEN|GbQCq#Lel;*imb?Q!1iz@J8FZaS zwR<>^uOf_ea9wjw0!|)P{V`vu;*l$>X@#T%3C05e)rx9oLz-5-PmH;-nt1 zLI%@&XaGC>G|eS0oKQ4jghSN8#YO$!mQspeRUXgh%*9EaLxaLaO;ge#32_fZgp8p1 zRO;T;AVba2-4n;f7*;q5Cpv~$Lr7vIlpqV5bjZ==)QXyBGYYzY@Nxmn5|^gCrA6&f zhvfPc`e-6_9f7{82M9pa7!ZV`v<_@l!|H`AVhy3$9P|2#X{8#1*~5gAvX%rgXAR8YP=o6fZVxbp_uCVF4C$0w~ zK4Gy9+FB{cofS~dzgjUXLiCXs11*S(gih)w4;x}o)!;pH(2lTS2vt&76byr8gYh-m z^;V^bxDo1yEWA=6_{cEh2yvc(jSL<{8rp9g2(Xocq#w}GdYL={Jv%@MAG9>#X0k!C zle$oTo4TqB3^uCac|~GKo&~#~U3&7oiiKG)2Fx83_!xB2`N*Jihhw=fm}at4 zI;m;#4BztjnQIG zx^xeseo4Oaf3Eu^!q=WEm6i$?RL~ms8 zK!V7CecEyqjN$a*Vw`5+iJ}=fSZ5r5RZ^GGuyJ{D-Ka^^Uo_fNTo-bNFo-OnOUNA# zJea|9Iff@HJt{%M*SA4M*@0*3y7F|piq*2^J=UDSXrx`IxSCKaAzfwy!9TuExL?+; z@xeKaXEY{ApCsR4%mI3)qWu?F3KLG)<1rh+8vw;Bk090D-%+^tp;#{psfudz=zzZ2 zqLqr3b*)9uVZqVq@f2n2g$L2qK1`sLh~zSGh&{lXM1rQDWd0`K-LNhUL(-UF4qi{o(R$gs_Jo zk1;~%rsUO#1OF1oIMP57q1+2p+XFs-g02vXiF2xqgB9l1!D^DoHfwQQPgb&6S(#^} zqCuv&m@%B2^@%tq%M&S`MO3V;)WN8<)Syr~nSY{UBHKkLnOm`HA~T_K;-7;KvwM&- zGx>DI1QQ2qCU_AUaj_gT_i+*#?{I}AjH{KBaJ;qBvz+XsM;V!Z-<7^}M# zy``B|ZWiXI-i(WFvDqd^w%H{|8JXhIGKmEj>w~dvR(pe-?De{IR>r<`*116$8P$9H zX&fcn%<(;DR)j;g+2Sx*mO=s=G6t$bCBFS)Oc@A>lxrX}%jSi`d`#6+Og6`8olA9} zGRpPYGUy1n3@s+g8G8%Ke2VPkPw_Q2!;HOQgL|QRBA24-v8kfwHcG0f4UuwjGsE9G zj(8%`!fuHy3d+a&aav@U#&*)lsB@7@39|wkDv@j%8ouy5!O+oazY1plDZ(jQ$9+6; z3t-Q|f&sz{$Na)WWM}+QZCYLJ*8B!Z%{Xu9X>tot(Q)F6V;*OGVfz*mLSiPYSP9UE zbFV|gfPFH46I5uSF2!?_v~Vgh^oj`l1txGpwn(5yqwhrYZ_w-I6kxRCpcUY>!m<=_6<7wHp{xY_MbuPcY|0TSF6XWCcSHUP#h={U zgaX7=0{?=Ptys`Kvp?Zf3v7VaOa*#F%tg+h3D@9hu>;K!?Q6nmU{4A^DPk%#3;oB= z8R!}?BgOJ0vPTIdmi9~jZ1yv-g(QA1PhqB7J+33#+skYuOoJE2EA=3j#D#?`-kjud zoW!ZM$l-GBB4VSU3=k6<`J?@gf2&5kH#6V-gq$tN=PdrRac~cr8j&^!2h z)kAHiBt;}JM0V!N7D6kcb!@NH4nf=!(+WnwE(lg9l90#67ZMfw03FDA|FkAwY9K|@ z%jf4uz{9s0Tv*#T`d!k79`8N#GZ&0kmKu$ahU?MM{ColuPFFcw?)D4fme?MR?if^b zI2e}&SNhqz-ElN^1Mzz2ZA++uf8FmDfO|ZSUNH+8yhp1&fB`Y@_VJ|D&Lg=X%=^_q}VQ``CYoUoZCEzUuqreFFq@Yx7?^`xpc#0^0+m_ix0+Mkh@o zI!=OyTf2euas9c^n+HTy4)%*|7UAjo-0%Gsn3(&S3Wn)fv}zz8|7?MF+7!vjsE8x9 z&2m_!xE>z5HgFa4y?k74cNq}PT*1uU)hgvArQ_RhIyee`j09`TX;avNrM3rlUA%C_ z^|@e@^WbfH7%XhNa`x!oZhp*pTglP)_5DEI;&Uf55QW7^1pbkc(xMYb#z?ej?@M45 z9rB7&yE?ew5Y^>%G*Xx%gXKz zwt$);atmScyGf#}XQ;&Fu$jP)Dd+>aDyXLB8NDOa(*ClFisr9+!u=0 z5pne`xMO0wC^d~Q$L-3~$Hq#Ia&synWdgHN;ZNI;Nv(@po z%W`_I^4nrz1RKQCJ$Vb!aw4D!x7Ync}Y2NEo^$7r{+ zmEQFH)%fDAu>AVIIDNqaRlgij8NpfJbK&l} zbX&Sw%_R&Mfv#Qu=yXvncu8E{%%=2rA%2NMHbOzW$|Ed?G+Nx z^JNe2wm3J3tIQ*A_gxyI@7IC%-2lJceg1zmrpX9z_!vm)jC3no`~Q)L)3kw zT6oj|iuk|7sPgaNlVh?4<25=qOZ10j@H1Bc5&#-2oQxn>5|^TF;@L~S_&ITtWk7Zq|?Lv8C3FT~gD zK74r0`r*a)UTs~o&qG~3QcVCRbh&@(K&w%Y$MIWpTU(OP@hT-v@1kCUep=c8it)>A zgTJP~4ZIDMAWh!<0z3HH#m3|`N#!tnV{PBwX!#Jc>25E6NxfZNl6@XZdL6BCpVMi| zcSQMS*zu9;d7oS;x@$Gtwb!11&N1E?_=v_%|0UXDrMKV1>I&aJjk5`aPPnbX%1Was zatv|tM@AZnROou{U;7|*r`g8!JQi%r5O&6H3zNUDytvf6GVO9ZzR%N^ZlpYkebQc{ zbzdnyLi>n4%j59XTiz#%;YGZVh=F<({)Z?P`KR_kIOahr2Co1Zilx&rg~O%#C^i4^ zwMR+wXFCr4S4c59(?iSLcM1!`?}c(!>SLa_YLm^|_1kspdyR|Vf6cj2`=d7sP}%wU zL?J!LyJZ01Y!Jt30HxnJrO3zEtYze!E*wOCh7PA8I3up?YvW=wEknh%nI5x+u6KC` zj|bb{)Y4wMj_i4ZmAjjp(7`j;UQkF<>%EVYl&?~o?H4#9h)01DT6AH-HYple+OW~! ze8tS1lx#c(2o0IdK)O8*Cn8d)1`VnzquzU#>c#XwkmAk`q`(_;|MpuRg| zN44kMANh=q6#rs~$2_Pu=^Z4Xe!!(4`1QC~58ZONQup`!NS2SYjnnD6?oF9yy*-&p zc8-EEG7r;oa-oi&&i<9q9y|C7D#}H}ovJy(y>c*&a(pUmHr08%PPG)p4nACSv-L4i z6$KPy9<6*hE=fBS`e=>5bDu(td5FcmEO^*cY+2H6sp@oBReP96+A1nrJ4-(mn)&?9 zf>A!FHIP8xhM#|6t?xm&F_lE6N!VftLQ|Z{4%GFM)`mhD3eegVD!u#+A&IZyZ@QV- zxQRXaBGnJ~=BWKH7X`a3n_5QSR%fw|dw=W@3%Ie|+LTlUa2mW1PSz2Z~G zkighossJ7ZP?ym7EtPmWz;GXI0F4Q>9UhQ4ulR(^2~W|DB;eNwq?FES-dKs%_{<3} zeS{|8gBJW~&Q$VA%7kh{;55!~9xie%zmT_m{WGKL{!^HQnVx_921#Le``Q1?7)j_u z>({^c3>d@wI{;3E?o4%6^G&>oo~PYl_IMy6EwY+MCB_vXP30x=EG)s4>xX@f7xhe5 z=NQP9Yv3D6t3tSmAH*~b)E!d2_-oyi@0>a~T>6b5856#RV8aXjq|~-DK8>5r>wT~~ z0j&H9B&om4So8D6m{GjwVwm(E_7*^qHOsmv?(PnQ5AN>n zIt=daHn_XHyAST}&fxCuGPpb3=HF+ZyU&gLUc7h#E6A0V^;LFe_6j<>@+-{a(m;iX zG~`x)^3yt_)#BZCf!f-9y*=)C+_dZ9c znmS$fclg&v56?R6k-L>s!cq=dc8Ur49d%OG%R;W-As2uGJJf`+9uA~>#WaEb0 zBQ@0$JUnPN@Jc}ghh#4fiHzxI)O|u^9?~q`MNqI0?+2E|hy*-u&qr~|5NZvHb+4mI z7rlNcmh3wnbI;)K;-O-FIB{z{*m~52tBpatnriQ!@kAG^Plz#R99&flrZZm1;*a%l ze|U4;Q!NPB6B_I+Mt=Pr5SWiHjglDtb^__w9=PxI7B|HzyKe@D1A9WEGr96wgK-*T z|0n?V2Fhzr1mjMCLopXaa zP`MlgSkko!A%0jsXTg?p-CQGC4EBTyUF)xs>uCv}QbSRRTm-heZw9SAZz6CXftKxt zS0tMdH3p&Z^KT=n`3e$bY+-o24Ix+|uF`0+G4$8h{=9_*iCujBj1R# zm;2X_num_<=ghMc47rwf%YG#Xx46V%foND0aIrl;X|Z}D{diK^hDdU`wW)Y`HIwY% zKOTzY;JV}oU6kmZtFba?C&cUJPh5`qZ_Byn_xHXxe2>pycES;!8jiSz#^Sf08Fp!K<|KKx>_`le2CJnEFz_BZ@c*1VA~ zUU~MW7!>lOp~dy$9aI_jf;vm$JIR?*Fv(i~GI8Q; zZ$DYWzSoUD=E45sC@@3}%3R`-3_B%wF^JHbi`7~~Cnot7EH0$)or*?xw~8OJBiC+) zse^-qF;6uo>}S6Hw(K0trL4yN_n@#QQ>Ev;_0}Iv`LwgCv~jJLzp8oS1VsntC(Nxf z1qLVNC8uhuvpWjCuXHDvl{6eL)`d(DWMxrU@=dRGDg5L9m?yz4yp9PZ=!fl>>`xzn zPOTwm(u7!##Uv%+Yi=r{>ZrF=w55mFWdA+p(bnhfY}!k7S`aS3;btbZ(7i{x-e;;= z@Hity6PaX)heTopb+#sI_U?SoEqz%w|fjc1O%`MIipRSF&d+BJ*>gySqCB0WdHD zT-4i8ZB69*pu#rdidJFzr<@@1?zCL)QbdldxH*ZpPEnta$KEg~uVoW|gPV=cpP_qr zYIXwiCu0w3pWByUl~;`JC_24!D^p%!F7pt4Au)U#w+tv4QMfLpcjH#{!j{xY=5IeU=0!(Ppk+V! zkP3e0e%cPZ`HwWyx$GZ;ui5BrD>!2wkcp(HCF(_ebG&jSS$J;ReHW#LZX6qzb>Y!+ zZhC!-z<#8E54F$DUOTLN0a z7{J}{I^(ln37q!39hU@a0G_pF#2V>I0)_}HAf~)tY_-7U3QNWHEXD`V6D#L%a(f*A zuEMX_J?{>o5pF;11CnHNZ>i)MS7AzAw;pQ#6q@&)POaj+eCI{#c)_#1gm!+-4L1H$ zWLh@hU621)|HlW+l&^alg}QWD--unIDPp}gjhqZy(SCaU;%2vTf3%47e7$Q3I&;|V z-Yyf&rB3G|%p9a(q&)-n_K8`4c!&)A{Y>byAyYSq$&+si+w}RKbrLB~ zL}&i@U^%Ayb*kD6e3|A=+H{0>z+FDzi#VP`U}RJo-QN#VAH;Y5omd6Jll0g9$F{M9 z!}3x{pS98qt(H2q-@Y+3fAfB@auc)iba(f(g1Gy;&v)oi8n>h#SnIDJG-cG`ffl>h z^vQq`ZjmjQ zMZS4Yz(gQMnT{L@_$=z;1i#aE?{C8P`q6Ss_h>&Gk0ktx7mPCalVHK^q`mx;z6%T z9~}ihv?kt}9cd+l!v0#js%Hb3k_WxddQ!8|&>h*c3vF{{`QF1iy!lRQ0OF3qS@Q|I z*4zD-{UK_gDtR;Hr_R18#KzyX zD?XoR-{d>u<4$i#OLI$1yPtB(T+EFTedIiqQ^U^;hZGo%M(0H@8p=jQT(BZOj{r(= zF3xv>VptNV^iNtYFHh;B>XsORBKFo8cI2ED5q8B0x18%>Pl3r?2*jZzL;)_KV#FI` z>ykizCHIR*yQ8|KGSF<8w$k+(g`bO0W<{sx`=42eEACCPj8{GjNWt<6KDOY}C-ln! zlU!)7;Rp#zC4^HZPweFD|xXV`60H+WA0Z=`+j5~P$9Z<2!kxb>4u_2edq7eVWYzI8?M);F{h@9aLT_hh!0$y&tR` z++deJn0AK1`N4X5YoN`36ry(CF0m;H0YO002U$S$W34$mrcc;i^pq%Qyy0{FSl&e~ zxh*Uxi6}+I4u_Ny$|lrDQU2hg8VC7`HM-AX?T?gD&WKJqJTSW(vKQC|L|dH$oiE}+ zjThpsfd3kLX|JI0fQOJ7v;(DLF21?W?=|{>vU|f^;oW}Xi+q~Je(ZtfAmUsZFLg^x zP!L^Hv-7Bz=wH)E6#Xh!`yH~Arf-ZICZYVatD92 zL>ws^Eb_W>Jw7OvdkxZ(y``DhAeKQDCkP{Uqrw9VN-j?P`P_Dc@5ZIz@X;}v;HKWv zDKXMOA3-!(jz)$NE;JnUMPq37yKiLql<^)>giAw z-H%OP=hwe8+>6m%wcUUGY*#2LT(<8v`(<(Q+=@r{6f9e4ccgM1z^NfyGtfpahrO$o zY3S{4{r(OUC)qH?r;V~=6n6H(CyWXsat$Hpg(7Td`K_c>EtX=o#ZtV_QyV6s;hC%; zl7JI_hq$#g8GIx7xl7HSPc*B=OBMnpq=5mIN_R6&f{oAMrg)M7fBy?@C~u}`r}73W zuP7MO$W(l&lk&hkiLKrRQt+OnA5nh z1`~{#zR-Ysh#-!E>LryX5)rggHb8*s~S5IjObU14-xBW(lwN2E~`j}Sb zqj^%2nViKF8;970%{sJN6AAaJBGwhrpJ)&nBRJ40=@T<0LDBL5rd2SvCNASMzFLNQ zt6-))#~zgGx`WsGzsEGo1;YSU)aU`u$O;^ca~_0ZycXA z-Y9YAP3o+zK#%UZK+=FgSH>I@26U3?qZC!~$LVk7dMFn8QYa|0 z;VU+XSiOd4p$M@i7Yi=K>enl~e7CYaA8-O|)kH6#5oI6oSHu+6#4triKU{}K9OPza@+fniJz&~a_G9Rbvn2fmPN$`!|F0LL7bq#KqkpNOBEt=Ah_(alT*$s#x z6-ymas{^wI8SjZ>wuP3%!S!{%p2wo?k{|qCVs?o3G$!d>Kj4ypQF> z+|%jrTm8_0Jwag1f2NkCga99EP{YvXfk-7uBWvJ}O$f&-sHznV10SxiKDLSNoQ~Z% z;3(>$BW*duymlUBwC85}^<(|pqA!ApS8a%4*Qh;?U-_h5(n;s;737fL;>Jk4;bZ{Y zN-{Y$@YHwIF<@1ZzNV-Ae)WPC$p#6k0~6m`gg@*Dky1dU*F2y7D0_RUTj(HGe zmgPj1mxPx~N#u1ipo^)GyZu>k{uN1z$Rz!7kVS=nt19kFc&j!SB6-jDXlQIc;!!sj zN-@J|Hakn$tr}%ztksMx&b^JCb29puU`@&XFJtka+Da#t=VOPbVntZ^w~46iA+>pJ`&07Cs#xco<+^;`Pouk(GKyD zy$Uz0gem9Xp{@fl_QH!42l))6qE=1RNObbw6Ik>2{9(e5#d6iN9iZhUkC96WFBZ;< zkDv|-FffaEDK{+Bv2ircb&c`iM)6mYm} zfNI(EX3M1(U1!}6;Kb)RK2BLSeh;?WT(>IOwZ_>J;G4pmB0aDBMuSPyzr(*~zjEp8pJuC$KtDB%RH+p#s8|^=F~{j##bJndym`slBNC!EDN?@wzU-F9goJN2%nW`$Ra#etZ}Y$p?a_Gn_5NhO+s@IO@M_ ze)R;bVRt4SIFA&@cbQKb10g0*>`VIhM`sRsGEWSf{)4@+*6|i+Ecm%-t$j7a&qI~su=&O z!34-r1#i!kI)yIJLppr`1vCDVtdc0#wF~S&5EY)+L@)V@a;kNvlxG&~e4k%$gAt;|dKd|R$u*YhY-)HR>NSAfL@~if%PtW7oW8i{+c@Hh^KnLqmI_QPj zInag0If%|$8-}a)Dc3f9C9dynCHS_1C9j&6eU8`=Wm!t>W+|QX0ieq+Dla?yYH|(ZuTb$oHw>F0N zm#b6FJ~0}W`uEC04L%#*a^qKj&ws?67q4}{^TYg2i28r%Jos-4a7`ixz`ub>&cFeX*a0By4D4SL zvnF6Z13=;c%w=W!8s+>#X86)^vIFcm0X)%=iV$`mbPpz2biyU}gaX1Rw&4#J}*FSpc8_#_%tZ^=oA&01-D4^FJ|V z{aT8d12C24Unm@asq9Q&zA%3UlZA!p-y>g6urPncmV@OhM9ct!?|)qY6(07Qm`^`D3{FaSW9{|O_2;u{b=CIII+;L;}gpDf}3 z%>w@qKA_d-KY#vf&KD*?|FtLp@t?o{vic7v|Hr)l!~oRaSLJ=x+*h>$>;RSaRbyY( z^%eFn4SN$!8F2&j^OQo_mv;A#h? z22ctAE`hIHekC1X56JgFEB;r8zf$`z>whKlD~n(01Ly%9?SL^rrv9Cxf92*s`PIJw z|9|yG^;+~Zzy)7=!{Dz8+oz8?L;1}x4eM{HH9^{0kulTMDP{_9de>ocrS?EPfAU{z zzRYTK-$38tLarJ5&mY%IrH;{wpaaaYk7PeKe*fw2CydHB;qF$ar#qqRDTanE%o#Uf_$^3_`g4$01t@& zFVSLT2ed-{cV84MCnMAU$wu!5>-uA%@oM!oliBgm%VgLvKFw&-h^gNY%8zHbeq;po z+f8t+APDp~6eLn4g)7cQVverPaI;Qgca`}v3d9p6tGuMu7lD?A)y1EpgJqpj3jA9_ zhq|xhqym;c@1NC=r|;c9izBNZ=bcNN9_NiqIv!ahVFExs;n0XXE4R0>N+w#*SU@Lz zt4-03=NtUzo7xb$R)5-bU9{>Hy?1*w*+FTlz^1i5^&dwYix7*zfh|&iQs}oc?lC`#=|1kYB1e zHM?wjv;sfwb>4btJkMyK^B6}oe03Y9uRdR2p4^~s0DU748ga3IU7ZYApuT`y_Pdp} zIMZ3GXJi9*2Euy@ymqlYKHJ=Q?9Bl-Ndq2#?pZ7=Zq96=KS)`j;z!peW^mo!s6|!# z5Ze-8^17ctNkR#AtTmf{!q%&*#>obELh-zxS51**Sd9l7>#P|1pg{v&prVw>?QsGU z;+h=u-D^tF6a-Ri5vLpg*1FDom2ZjV67fs_#bew<7$8|2Q1c8T3la#QqphGk`h8F@v(u9erI9uALYhRRYWZxTXC%a z=s%JKh}bBJrDE?g{>$t?X8ga2eV;LUslbSz%zyT_K3}(*Uo?@tpC5VN2)jCUzgGL# z+&&jDI=_p7>N?v26s3Kp?L6=?gxH#3A%yvUnN&z>y#Tp5$K}i3fJfU?gUf6;xzaye zpAYO0djh{qy_0ejV8XUG`6GbiFuPRlYDor+lF>f3UmF~yV7r|j(-o?p%`;Hx+X>TLFIiNE_plVgUkW4h5Tpu<$!xlBW zjJ?2O`=dTkaz7&)B5xF*NosbtpEaqjupW&Vzi2oZiFjFB+mE|WigmtGw9w(_)JwU) z?#)P?JTPq!`(28oB6m(L#gv9gKj|hjTqP4< zJU8MavC9w-b8Xgy51vcBt5dA6;1$7>4F%z+tiw`_)h_;mlJR3Hnd4e=a?HlJ#Wn_t zYlyWsKTpR)HuPtgh5OAAW+bxx&MVgIpv5#g4nu2_^tcxz$NU#vu`~2%=>k%#V$$klMDe$RrB{4z zQ9}xKdRp!|+Hb!#2zZ*c?B$;EuE&uPzz;zi%zJkw23+NE(=|N%PQu`52{0O554g}V zc1P~^L2V?i}!` z--tfUm&ad>w z%4-wcxp~oMwIpvkFnC}#EPNBqYg!U-nmSh*et3@1e2@gXc>t&NN}O(MT2-*6Yic}8 zSRuqRXiQwFllmE}4xA2E_B$pVr`s|I1Zh#jtx|~EMFiT+X;%W@FPbuHN%A@jWK{%a z(-vQmZ!e#4Spu{=SjZ&J0&#W^EQL(j=ztQy(+6T1!h& zH;kPpt!T6c#Q0o3l4;Jj2}VY4T{J7kIf*&X27yI08Yk>2i)3~2q^Eh~t_htcuEv$- z!H6V26*1c=nNEfY{BRK?PtTI1=)+{!(ez;v_GmPv{xNY^ZJUNLW>IG6g|o7)3D4nU ztCX1WCSX%T5hEk6#ywn9;S&`HVChCe*|*Ko?TD$E=3kz(!|}rg4dT`5gXD6i!>uM4w6&@u~K62 zaZH{*W5Y5B2k20&uR?z?DiMb%y*-J|Cmmt5i$z4iF^XNwhqps(MK~LE{?Ih3wEe<%!bA)#09-w-e_M4}F}tLm>P)-UHKW?4}iPmLFX+Tv~wN&PYpP zqC}67%}n|N=1&I$X)vbP@3`L-yB^FJI4)}3Zluzq)rHhgq04=X>$rQG7BERz|1j)% z25YsZRYvf>5_F!$cc`Uea%q3gjO~_)aM)b39WLT&CQO;%jhtrx9tU7Th`OIu>+rp`l;Qk@czLn^B&(Y)T0SkJ*^|EV916p`|7gt9}dzv4c7oqG$QQ zN5@ZbN8A@y^>|!k>+&^iH6bz?(;_4UG*gx*Y?6m1Z;-#MdbZ`8KEK6Y)iEQPBUVc^ zkn$$6^=B;kB`OfhSUS;gS9V7_23I?MaR(DAo{9_H(Hp2RPos*>1b0_MA9E(#+Qiss zHsLLWNHBp`J*so8avYl|wDP&q54E?21`qG)mNg7_$?HN61u$G&h}eOt7;~nJ$8JPg z?cafmkB*twT{(g!TCcr&X{PvWXi^qbcNFt8tGD7b^vXx}jDGb#Yfu@sAzXhS01f4# z*{iG7>AM5a1?(z^LL$Ww@4{mLu22!v3Tc78#Ne1=D6qfe#fEdmT4`e*x{~Z%|pn|n9cnLuAhuc3l3>H+rpw{gafk~^*t}7 zM-0k!+nWykhsfv&3M0LLh@=i|))fR0NpjzF0=?fZ}61nQ-|ah7_JxS z4RSeh%C`$49$!}wMft6sANf8;g4xMTZ8&kW{03Ar{M&UOzNJxJ(etNwPH5*zUGa7P zUO33(@<;?e{t_-^P~sYbi63p3W7lSi!0YA>CGT1YKLo#}%pK+UA0C~RYaN8my1X9b z9(|;b+^HxauV}uObKI5_kxU9&37?70f4j#~susk${yFf9tRm9DBts^W*5&(zvTMnJ zttgloKsj6B#UYzWZ~{B;ZZUg2c9#+xjl(bFQ*=N-bJXxA`T|SqLvU*~uA4h`Z|spf z6nO6IMLJG4ep{=Z%YQoM<;8~)XPFxi(}8W%QT>g6)!CT0%LUswGKvuJ7LsLg;cY7{TOL`T68)qQ7U1u3< zAgMP&2GGYw(v_lk7Lq#dLMPk1gc*lUdwR#s}QG(gPF&&s2;8^ptmFOQPx`I>$6 zh6HSXH#02B+RE-X-+6^qWt^SCo;}VN#wvNBN2IzOXrDGV+Lp%xgocl?4@Gf zwPw_2RMIodFiTWaEa^<8T3r(kV4l$RAWJ9>g3}tw}+`cH4e=158zOw&Wfo`~*L0Yuw_v#rGWq5c8bZPKOe&>V@&(ZSUuI( z&+rgYF%*&2%@oafUF__tdy*-6;(I5ODN~1Ty)iuA-9rf&!I&)Bn6rJ6;+3;%>o!Is z&XzQ!sOvZp8AcW~6Q*i6s5DD4bz0RE198ke7aTDM%TO@~ST|tZ)V~%X0t&l{=W7GK zhAeJbe-Ss8vTMyA7$LW=uOUl$ZoxFrULG584i$dWHSJv8DNpgBPWBYOMOoC^DZdON zg9k({g)-|NKx`-)P~FKl&u=ZKIKt_u&CjJelWB`(g@9WTI>B1GkDD&7cFV%13Y}3N zIKe8L_Im<6y>!a_1U--KM>A>mqjCcBL=*hp(<)18yHx!SO!Y0*5>YUnM-LiYsfli- zg`knF8><^@1#}FCWnG3cAh`(Mp0@e9h`bdC>NdEN@27N=+Hx$6SD~3NAZi z(4RTIDSi+uONFF|m+UAY*}s9$vKFjeZx4U()z*fR3zK8!(`4XhmU~?fNGoVelknI_ zhyPNkXZ6PFy}iC~B@Ul1e}|fTe-{}c$IYV{C|!|-rF0Jj4~r2Bz*4Ji&!-54J^Lm& z%giJubf$;2YpiEU&>NM3@S|3SlFJuoik_X{6 zXfk4TxL41ry4+`^4s*JIFYgtYI=Flf@DnFzSZB7s7XuJYSy_n34onMZ(~fK_mSt6l z+Y^+U59CNFya3m@Ybtceh#=0u4EK)LE~%=W6US%(Bdar1>-sc| zwjCl|ya7{`dk|S|T5W%9u%p$G;$<-3a)dmZH%K*Vy&cm7VQoSzFseRRl_`)8Ib`e3 z+!CB>!4TN|tSe=IveT9F6B!;E-wkt{90M%4Kd}~u2fC6T42_66VQ;n%an4-%RcpFO zv~A>qKl;4`?i|}2$R>FjY0fzL#4jFg@yk6n-%w_`UQ_T2A+O7UnJp2+b?J#as7Int zj?YFq%O|z*aBdV|!oKeQsZelLssw@?uNxeW9X^~&8hdm>OoV!t$tl$G13A#T=R1T{DBVIlLowHi_btPh*cKEqhm>gYZ)V`J8a4$li^Q)ur9Oqa_h(!2JXdHBsalbm z5sFraHo~Xo*4I4AeF9_hvS9=9`{?vzu3D}fcM2yfKKUTv=(F6f?gHm*5&EwlcJTYX z`ax@(zo9=OT@rbQl#86KU8_gEc7oDge0L2>Rdh)+0x2avDlkcoTQK5XiA;Y3ZVlln z9Qh!1gJ`_dbO14KQfMZ>CDo9zJhAdjo|S7OFl=8t0rHCS9z5YhHQiHcg1& zq01;zHaj&lwb1<6cII-So2n_#i4Ru3KW6H~)_ot#1%9cA7oL4ih!1otTu0192ZFjK z4UIPG;@jFul9BHrOokJBga0_-C>9{6cf1Wz{sQ!MnOTv;ehV%#zI3`EAGms{4|S~F zoZiOHND|w{v=NoNz)3hS5deGCKIXa+-*6{XwWBREZ#V8o53VE^c7BYV<1~zSpDHx% z_Q6FEMeF^(lxsR05LP#atq6CvD1mTyjW1d(eG66>(v%Q2)y`&+y z^;41^Gg>_LwwEiG{GjWO!3LN%m0NbzF3B%AY@kv8(U0F;BV?JeApAs?>%48KcaJsD z(N|)w39rafK7o8A6Z`Tow-T7yzSKKhYJ}|&O;EIN)gw~d63kD}hQ}LK+c2*5hpGjt z>i&Gz^w}4Jcc856G8Oju2bnR>wMe`JyiaE${JjO>m3_=zP@T(T47r*D1vN@FD0f^y zZxQ{sdiH1fE!<5gbkQ3KZpVmCgH=7qk3AlCfXAO^2z`i+C-*yV_W5m)n7fEscj#4j(6a*IW7q?3!-f5^{$=n1);qx;74Jai%s=>n zeLLz6?2E%rd+uBQt+nC?1O|as%Q&gxM~hI7=R!zh>QPqqL5$sOI}= zOTZtRZ`kubTeEeibjN(4*>}^n{5}r7dDvriM)XYy8)B}G;lLj*!R{2e1xD<%_@pj> z4*B*F9`%$Q#h?x&IrZ6(@&<^R2&6DWX9}LwkIp647s^waW>*DT6c#C`%A}n&dYpU9 zFbsz%Gr3$P689_--9oN(gDEIt0^XkFzQE2UngO((T<5U-;NPTjlw=HwCe0|1sGSZ1 z_X+vE@XF*rOIH_87d1ear36h`I)|}GgOs{Zq~c=A3xALYc9^lGS6yFhhWT+xEog8m z@tMCyPO8~i4sSGaYw~X@++X*^;my2(G8`rI!;K%;=JjTq< z=}G&+pwi2f4wbuYA!2 zww<0Q;)Kc2wE%iQ|6FD-BP7x2f?Q1MC^q3`0eGwv%2Eu?xE!d_V3=iZHhH9UI z5fMbDD5>Ir%A|CIw3=dS#&6Ez>e&6?6C@dqmBs^?a0RD#EPr|e&*t4RSp!pYtCkcs zW8h7C7>@3YXz@$(yE#1dyN){V@~z(ww!q*T#i?7NhYLT%a?NBV$wD_uudpG_Sr#rc zr1r|7nFZf1|7kH$_Wyu8r4>=+nK%Jn5#R|Q6vD(YlI)u|tJnWKZ;@Xsk5<1@p=maJ zXC(PE;k#6#pUH?>?Etiuuuv_VG}8>9O&u~3&a0I#d_J-j9%&a2Lk8>aEifAagYh1N zM5Bo+jXnf+Oum9`>QD0UN?{rn!w2=sG}8?XW2&RsJ=ii|K*u&+f7(eQSHg@{0~V*Y zg@)8>DvR9F?ri6P{@}p(wocLsvqyu_5Q`jNJHSScdw;Y87|2CmiMrThO<_tK!5Xem zTm`d7jKbogVooLHlBAcnP5)9d@F57#&DY_S82T=%hFa4_<7WI#u65~A8xJ$7 z{_*z3ad(3!GJOWt)3<|uaRgo_o;Nd(UR32`7SE@v9KM{`iOpD-eB0)oXvuZFCf)a4 zFlDU}v@kC#P51BIGOq%WUcXaQ>qN>2&I*9Va=p9@BMlQ*degx((wKqr@_UWI zX9S|i@#nfE4RF}=h8~&d5(3LU<^&9MyRcSLl&`%;#P10fQFx3Y5v9aq2pYI&$NU8+ zqyo0XbL<8SQe??DgtC$yG)65;bBhdE9%^?D(O501Y{qd{s)mcQYj ziTvGG$JCX&_+&BZ9%T1j6|^zz`#jlAN@_LpCya`DwoSIp-q5Z0n205;3$Ra^alKQ9 zD2t*XO}$Lx?9F7@2+{sN-)gG}m3acC2_ zR=1%-l<1-XGe&i46+gqyl`}}ra-#*?Amz6c`2;Zvj7H~7K)HIJPMC1^LPn>p647rL z$PI7?j5Wic-OSOLas6;e2zKK3;8yL23_tcvVy!n&;_@4w|I|&B2ZAGbU1ocGhz?_q z3v`EPFSw=SSLcnxnL|mZnWD!uGx7f@eXfY3P{zSoC6|G*X}_6nl9Wr9O^dYkCilD@ z8)EOy@#TDA)i|>hFsx2WP7anxuo!Bxcf>4jkW)FN5esM<=sIr1Q7?EvF$?Q#ThcVi zI;O1`iKF>mkCAA$Kj)^Fp_=TPv0BrGzStbUh}4C!>#Z(>r2}&Yir#2m+^FDDwnvd% zSR_yTO{aY-njYjK3oA*Bfs?iXYfn=D)9zNepSEv%iEzt#Gn3GvxXWT+_pL3J|DiF` z`xpDm48_$Cu5TeamCuUR{YGTbr5A(Qu!D^Rn?&Y^Wkv3^6QZBh&rE2~s8I|tNWYQ$ zkfS>1E{AFQ-i&-Emx;NlO`~YzQCex^3|}u_>OroZ_ft?fEmeP$>@-i>O~oE%B)2R9 zNVeHDo0pq#n%6Gscq}4T`D(gs6Rtu>oHfHYZ0gs>At1%>(#*xO`svii{pa)~q^HJ* z&PBhlYvXr? z^ImJZ?BAqfck^mAo|5dfFx&euD4Vc{7Qo?yZB8W_KObX<@^)HfI4LQ#C<)b*R~~ti z>P6?H!~bLq53d|2Pg=u27^fR?p9rt4WltK9Wb%*`O9P!LYZ)udL=!B;Ua*ONitdjCC_YSYwKTj=^Xw`T*_~nhSe~va} zNkVkm&Vp1;qBUK;&k}OzJ6sjBn@_CkJWiw4U3fWo)Uh((%V{6Gk`Jb`8qHmK({2KA zrDb2{GFtlLY3JIige`3&y?Q!>7HvXkxWwuos3Q}bpJ+vs-6Iq-mCkfTFtLt`#$Bol zsRQMN#icS{bB|PZ*bO&_U2VrbzEjM8Qtx$E7-pwZOzc6M{QRwA!e;F3VRL^>F{3qB z*x;aHWu6b8Jd}8HAv$C-CN<{K_Bhu?oTEk-KdLSp53gmDu!%7AgWc32AN3W4X1r#4 zI8(xMC={41-L2Q6-#+GUV%W5ArnAS`FS{a*? z7;uI*s8ATi3518H@m@n8YhsQ!`SLy5bAVt+iuy`LDOP;KV|OU=`j;@9+(`6e3{2PH z-$J=12L!B|{Z>TMC)jXgLenkN4pNkqDdI$=S zn$;WIYn?!cQurZAX0SQ3zK_bDYZlDaC+H}|wp73<7w5ar-OCiaYnOSQf~u64(W_~w zXlmB7kYymA>GXm5#Wa@pW|G=a;z=om?V{^L7-TrgK?WnAZ`(&*AqQww>R=^d2fr8YXezzzk-}ep>(Hf1?Ev_IfuAs;a zHLf_iyErkzv}8#f=5%JWfCMYnSZR18Jl#=c)jT+0H@sz;I&gC1_D-F4I_{|YS$h+t zyqD>3EHQn3Z++k5KmX)`oWuyvD)c6fRGRi!(x;1fasEsXXOz~r&_`EQinRwny(ia877tU-(;E5Cn&6IKS`avu zWK|cnYIRcTjbt1bK9p-F122@A(US>RRpta$UAg$pTGp_GX_@TGT^a_q%#0Cry*YtL z(jnC4>3s(=IH_0u=T7@$CIalwYb=r_`*IL z_UIWV03q~;jXU~%N+yeS^jUZ&#(Tggtr6{alG$z zap`q)l0!%?{iU+&oy9+|PUVZyX;XNqsZTPXH~3?y<-~m!^7o4h8MjiX%|Dk0wCtp9 zRwi0EhVY7yAq%VuhvpN}OckoxhXtEL`3&@=_2i()nlX2&-^Rv^o+w0QHo|F@?W#`WEa1xBf1&VI; zytvwI;9$x`bZ~4?$@M!%PXp80M)#(g=_%V}Ot8t!@g=+THT!Bkf46!g1G^(LyW?xM zx%NjQIV(V7w@UlDrKysd(VF&u{ayRqFggD~WLq&kFUwm2`%k0ya`^t5sxxh@ciLL4 zcI=lU3%t81xTX?FeYV4%>aPZ~$gIT%13YVhH&1Q)2Cu09EbrIy6wIfNm{%vN>;-5jH!y?O$ znu$SfXBjBJRuAf*1oa@qP*>a-_O?jgaV9f#4%bHW$8H>xgnQ6d(#ypbhoF_;}MQpy@C&5PI0Y^*xzG!;tJ!@_ODt7M5q=20Wyo z(3D2NT6kAvz=RUQ!Nv?NUIO&+k$o#xL}j$59>$p5Ys3&aszH?~d!%S<{DJgmaj+YR;$#>=_CrY$IYG@+ zZsbMfwa2R(Tl%o1z#kNd`8XC4wy9$wEDAPO4X=lPY83GK`O-xm;Yh^^)O~JnG>h^d zs(s3b-B0c14oT-xqBsCo!7PKmFoLsy7bIZTb>a*c2;k*U%iv)7EzT2fi4;i8=3;}7 ze*5lPIfK6%8ROK;1sdZ`u%mEkMI?9J{BSkNIK+jyUd6*q&LUOtHAK* zbX@+k73p9J=+ts`SkzQyLePstjTpoW54oHkpr6}KjL(TRmp3`$j8r)7mMr6dDV<6| z?z`dx7E@={`3?@5|0?j?L!-g{*t|LRhx%H&iT^h~R>}wXYm?A-dUL()k5;V>83P~- zq0@ZfH@HT{fI14q!5ADh$sj6-XBF9#WfDtK^sHx#!=%OVV14*e11jXi#cf$o{7~rA zjb?+ys#U5XX4ZLl?0mh73c*H2KL@oxPZ)gVSk7T+i4#(VMZKeq1?eF?!o+Hm1Ar5b zDs9Lcgp=_9uAtunM+u>0-wX>lMF{DT^z2hV+kp=P@6ku0v{OeT~&qfqJuTb zy2ik^TOoa06xm+zz0*I)Ro^N(VqzUlz9fSBBu5@dsUwd@?`PW~cec~?gdDCu*rz#}4-jt{+mr`^8jZCy)zMed4 zTLArN_?8THNxEER{GH_5iz0&xdo|g=TnqYiI$tHU@~!^URBjW!`mP-g{6QBmrmgWT z%H2w7NBM)d;A!(ozn!iixnHHTQ; z@M99v&l(a(`U^_~@b}Xb-QC=HpM_m@6s?!{e8q13!iWcHp4|Mly#j+jptn5aJY*)! z5qllc(2UGc*RFR>+>10$)UK&HbVy0Imo+-&F3(|kZINR}l3LOnw+?#ly?R`E z*pTZ>O3lg{*|oid!S3mFsb^d5qLWU2dHqe*6C1BJHuOnJPat1nU#+Kud2*trK+T&` z7H8gUB!~D(cll#aw&Wo%9S!m}3_ouWd;F>{Q@z-@h~r+Tn=7B>Icbhe1bj=_Xfj>X@dNJ|j`JLjL7K5|dna6K`mFIy&!O)2GL$kC zcbS; zhATE@k5Vn(X1DK9r?19uYkHK)D68DAPq@crBZTyxF%L;jzu&a9)Y?KY<=#*to!iQi zuHA9F0_iRopF|h4JxL=<-N7)Zxuv$^RK=5XgiKw=J*k(~MGP>A>Q6^98Ms3~ICKbm zob#{m$elhu$azQi!d0%*$pTMLA2Tz5d+#o4CQ{X%<>R()4vXqH9z4Zpyc3s;{K4LY zg%JB^TdNN>@wc_LFz~o4Y0+awhGHCwL>bDA>V-`{DTz4m)jq8xOW;44#mkN~*ot1D z3v)cApGe0r;aIC}!F^xXr{a$8-r6?J&|b9X7>*ole>=l~&Qd~EDU*@7yWx&*136?% z+I8!l>+THNuQSP^cN-@6y|ppkvdEFV;||k7lT$iR;YQtPF1!23JKmbNsT#1^WOW3c zyL@%`0a)C`0CG!XfvboN&ySlrJ2is~HN!NHRewv;x0LvL==S9@aSpwmH6h`jt=uk& zaH`fE93Jj36h6#3D;dTzI#hMBl`HW?Sh!fB1XA|s0eb7Cl-r?&`UWTX1b2K?yIwiA ze`^eLXl&U3X|jro8N z`OyJWDW0uMiI<%2NxUeacjZ)Pd16&cXABQv{jAIs9l|Oqx>Hhl-|e%PM_4&E#I;o| zhjM%h@uDY~8LwPbLMpok-?nAA$8vpVsHm?`im>6%gQ{uOm%`{15p80@tgSl-#kT~i zSg8$5q^O7D51-mvET8b~z{f(g@&TTC*C5pcR~f%Zb8ee&d2|kxS#(oL!Dt>khu2XW zTUe&+w60=ugIO3jFGX?7VAYlw-(wue>X*lPcx1y5So=!(xejYGZLCe?+dPOyj`I^_ z@75FY2#y3fLP_QOQ_a}sx2BKjH%uNY#>{p%dC!cMER}C&#%;d-;6JeW*mpqJ@4f%H zOPL35py=Uj@6;)e@1=e-e%@C+8@*@8O1!`Kt(AZ3D{0ssrRo=)7`Q9WF4a`r{KdyT zym3}VU(FQ@V7MDS0jqTGh=`8Falj8CN4lSf0<-Luwx2(Iw^_&=& zMvq91l?tpoyA&DTe_IiekM7;J?!%0ZIV>o6=efcB9GvZb<(vJQaoPzYcYT+~J?3n0 z)+#NSgfcDLZ(n1x_mVbZ4tQsC>>+#2P)*j1$*F1gfMbXFxbjS-%Jy55>`{gIM`~_` zPEic%J96@8>>7r17lNF43(VDT)4#W=_6+h1lH?7J<>N8KAP@9D@~cpvo7y=tOt*@7 zet0~B<6@wJ$*Gk?KGj!h^y+TClHR_quyJ;-CPvcZ-Qwb<;NAgdg>iqvwI-{)xDEIX z{_ht`Y=<8Fki5;?%cmLDdg&xbJ>ibUt?ZnUYB%Y)Pi}@~sMalB>2c1xG@WCQ-hW|~ zw!FBV32!&*B$hZ5<8c4ctZrcyr`h@F*eTDudP2)Hp|4!yKlfIV&*}~tsvRzti(u!h zxaG}URhm-@dpvP;d0uXfacckY9AKE^aU^G+XVcXz)P%Trhj;xYN9E1U@{e zFR|uH-k}KHh-2JHOgU%k&LmTO&)VvW*SFcW93!Q3&nt9QSv7Nb3bwbVBn-v<(0cRA z@7#uqeG<0JF4b|=Z@fWUR8Ta3FzmW!5~(OfKK*pPzpY5SL@A2RsgyW*{BimYhJA~c zipaLrEvZWDmnRs49@1~?3};>t-TIo2t92j&6J8S`DjKR7qF5>OwKBWDscD0YHKC)x zZi-n>A`cb5c>UeMY}ulBL6Lazh|Zst#k@(YrCayfj9C<%Q5YZJ*%#8cYv5EwNF~NAttl)`IKSS=;O&=k8g%2eZNdK1r(cTs-MsL z5%|QMtIu)bsb|n`y~mu4jhmKJw=X`-iRJD0$wQ|?{@6Ns|GB=Glc-%=!>!65x12(LU&=dekaSFSa?_&Cz5V_hqp&4Kw=UdL zPF2v6FR^dkn#)q3EXl;W`5qhP@ae&MM3>vW=o-)YX3%NbzNt@d@mX+y|A?(e)UNne z_&FQBAgss9=5qzM-XSxeNM=qJb1L<=ogz{04kxcVkIi3`+g?iKO}Vf!5qADqx0dKc zV7F003(w6Bqr=x>$}RVw1~k1^&0y55CZ*45o*=^UiSS0OI z?vxKKp5iD8^wrt)>zFOOA}Cxxow?vl?)<+_6pcQ2g0E{Zfy&y15TB|TcZ z{iP0jbF#$p-Xo;@%^6N-(D#Q^{sTJN)0{gQEE-|6nOof$60TBrEY{xKx2yC z+k7Cyd$GMgsWigKilgW&S#D?aqlA_Ho{s#l+g}D9q)>Cb8>XsrwUdDC)maA#*vH8AtV$q}vUlR2&z$rk5z6K~L6rN8kaNG)^MqO|jafWE6W3`e2Qhp6PYR3)k_pH9|3DQst$Q ze51bSdYfOXzJ1bRUr*yOe97=^T@YWeXxtpYh0k<9GRrBCUo(g!@NrB|ZD?i;pKoyAd8vjC>6*N&Lxy z=20j(nD{gNUKw4(HibhTIF&u5l-F(r?;T`ZT~U2^>D|^WnfCIq^>GE%elBf#eSbA3 zki7aK2$%Qa%Th+4xR+kqi?8|X+Cx!kU%N8fHzzv^G)C`__1iuUSehHok@zt-ayekb z4C5zjY2tnZ-cek9{`Ok_khS7Y$~Y5!ZUcCAoLWCku4k@5^9j^_4kOR2Qj# zW7VgaEk5<&d-DQWZ>=lexN8V~)|paYxGqZEZp>d*>t3jD`#w_ESAKJ|;hTExqqgt+ zyKB<-bc)-yIuSd@cmrYy5>Xa~#oi-_3_gbG1omWZzl*t8GO~VItmal!2S?ogo_t+I z^Za;!&5F*2{xq_quS*xdmt>Z9Wn`ZV=gElp^fu;Z3Xh;F^O6z+vcaxm= zsWjW z+7TO%Jv~3--<3Xp`D}R+_t??{Kb7vMCi!OLZG^9fE;h%X*~_t^IOy|X^QkASSos7z|vnSnuu2V5-d?e>NWH;y*Uu|7BN3$jd!kt9Oa3 zad}Kx1+fbIOYUTOf6<#bGhBJ)2wl|@Os3N!pb@cW9`CIymv66nW~zPmhe*b)_c4*(!^+=F7CR55Z(v%_6doCO(9&%99_vruOyB8)Xx#oLi;<=~f74;)TvpYub z-yQq@5WjYLm%#Ea=6L({%DnW)j{^fQn^oABO2FicQs(#!e3tbZVzH`{tNVsbQLy@_ z=s`l`h~A-j{Nu zlG*fq={HKtR6b>Y_fTs)L@;KT4foGFHTbbreAnk@K|8|Bvm3ifECh%MKXDq)}TP{5jEI!=yVDec_^DD=Ls=*<{N1Q_0 zxA(gSxK=)oItjZeV|K6C_mOME(@QdXQoPp{d+*_9uge*}Z%8cYH18c4IqBy8^)rVK z?)?B_u;sSr$JMCo;`Hv%YytMk(o2m$)`Z22?`WX8T^Z!7>63YwIHU4~jfn|ebrg(fBW^Q*n@XMTl5vc=KDrZ)>T<<+ACGd@&qsaHO!_VMjbY*9Z zeKTdh532nrKp2l_=svtV8MkW3PnZ}@Hgars%FEtsLF!|!iBqYI!ua^i>Rhv4yv&7G zP+$0|%AhCs+Oku%e8q9#V$0#I{+|zA3SjfoUvKvI92-cVeE4CaF>g(>4YRrFgX@!w z{_*_anzUbl+(hZ-sgllkKi#P6)ib`|O6;0X@?eKLN-+I;+%R0E^Vgp(-y3XaUlzD4 zm=!kpD}4K`mFZd3zGnDx`1#645B9@Unl{c>p-V2&rf)s(Y(e}iz8E=VWH#wKHGAr3 zZ$rO~owZg~HoL&0+7+xt<=!KW0vp8*Ih)JgVvb=#O^0{sNY0$t%08f?G;|ETugsZ6 zu4N$Sn~>`=XzzEN`Xc-);6 zd?icO`Jt(P98!CH!pNsy%5_caxK%DqjjZ+iDfF2>m$i?5DP_`UtSBSvJ5#|?Bwc(& zr~YhF-T{2BapR%7q9_GJjnduRuz+3N5M|8dceXM1hCTdZfjrwQD$uKG`kq*!w_o+cXh(ebVB3V(d@l=cF__YwPJi1)nGB=ZALc{_tg$G=0%|#N2&BEUG z9(Z^veb(F7zr$hL;-hR?)>kdpjTapy8Up(kO#%I1iKe`wrT6xOb%W1t$JnMFG zzQ1*C#^YP%vX5@1u5l%1C|uT+ACrnl9Lm|asUuW~%e%NR^La(Y<>mW2odWSyXFc86 z0I|f*jq`QqpB;~%JEY+I0d_xNQpbMHFQysdQbf`wwsM*6Fadb3G*X4&%__!;M-WREfB$WGEKgfPj7hVnAF!H_qeY* zb70g=I`-oth6lUQFZ8Y|@IrtN>Q1BnxC~4__k%4ldgd0pU{T6I0%2^)>KNy{(!n#| z-2|*k($~Ja-w)_bU!Q&1mp*&XS7CW5SJbJE}p> zAUL_3_zSiMWfPezwAr=UYi-S#P)b+m7M!x?Me+RSa--O0wQqRy&P}|PDG*B^Lf$;d zaMtpYNzJI|$S60j760V-{e=DO;YTheuy1hxXqG9LdN%&d80WVMN7VJ)4Lm>oDfjtZ zOkj`DOf>mm+bomNmzKzD0=rL)jtv~U0M-sdne zY4CG5w{MzyUtH{UxN!d|lSpY)UX z&C2VBGOh>A%Y{k~?A~>iq{EyYuzZyxw5mjPNIJJ<;S<)sCyYI;Wyp-&Vg1ZW)~_=Xl`Qo0X44Hb zCSwJ;(iGo^&pSM^c%OHku5ZlJSKEuts*-%d#$PCOt<0T^eh}OcAU85`(>BHIn)jzZ zBRNlx#hz%+Bd>h(6sp|}Ya%8D(jL|J`m3|=ZJo8A`eIp7U41FaY}eY1TlbH_tAjQx zy-#^Q9~p&R=pr-u-5ThMUKxHd964K?l`Xq}$4bW!7tJ?M-iWh(T5MTuEy7N{S_?S+ zt)N-VI>f2eXjGvvp|aX!gP+h`*3)7nFn`-qgZK?E@~zBUU9YeD;{dET3AP>F%HMaB zWu|fUM@WG}eoB8>b-it~hD(;2X(TslU1>9a_4(W7GT!&jA2+%6%D%|XZq7QcMTGU2 zEq=VqJARFAr0IzF=ei2(a^tMQLv3r^y{nM{KI;;?b$)zHKeyN+3jZfJLlG#~=KQ*; z=GV$M%c&M$;Cs~M?uumhGa#Q1@9?jn5ghC7P6y)C`tw)je{dZ z6VWnnOHZ*LiIlnlxJJPbh~5MXd542hHm9MT@XE@Vp| zX%~E5N&Y=h z9!3%1Zvy=Z@^6&iMf^iuU=Ec)YZg4FVxew6elu2m}lqiMO^;bFs8?BHAdD-93rFr2WsQ_@$+PJ{*{z9mz(~ zh-~R%W9e@59}4m3EdQYlM)qW)mW?6~X-mN4t!$<7SX+cN8ewTGO+Z*$Nh57=);4ei z!o~`X`w!*&a|M=vYyy8;sg3o&EWp*%-RYO<+gQVhPDE#-3)ur00pgdT+E~ky?a59= z#a~a4vJ?4_H%|7Hd1Rd|UCt|r`bgUlZ7n^W$fAl`F48VUvNy@yQJCy*>EZz_*x8cu zsCfJ`W@Rmy&T(O|F~TIW9noEw!stY@wDI@@hLgSGA8&rG1N-;d;GMNQ(UMGZ|6_S0 zqT63`C>pujJ6gJs?Szkkc|DyhsiykHN}1|k6a3SM=1+|Qm-8=`{r1rKSh@mr!GEa> zFv+U?A?XPc$>|?G+SFs^|3x6GT9S#1NH`KL4M$1Cu_q8nSp)|BlZNAD;c$5v73Z&! zIwTu=Ti^eak$>a-Pt6GkpriA@R*$puUmDWUkyRyGdr}NdOI6X+)80lFkHxB>RS-C7 z6j~J{jmE1gOB1k1)ugdFRRWTLR)(t()PBMIeJlkiplG>xfT!J>_@B)7x3M(93;#cO zvHU++L-@ao{39*@S6%;A*FVz0KVtr`b^TXe|40M>i21+P_0QDxN7x62AxJ*|Raq+j zyD}xZfO6Cu)Sds6i%L;{D}Yt)JzSkEeL;G2f|50ZB-oQksdvE~zv^ie0sS}bU*+;? zL!vFr$o>LR82l1uY$gnDkQD|O2*V6XBr^B`E^G+Xat) z*XgP%qw$nf>F=46;{Tol%&%_mL?*h!)SW^`M}NS;z-YjGf=u+{o_#m6%QTA2v02wc zZH8QUYK^VzSYKOxKHGBO@Yp zthtB8vzLdZ_6(_T4zQkAlEx;N3Ug_SC9;=sUKjDvJ3y?+6D2URS6GN%tv6KMoqBaH z>Onk+i$OC-2DZzA(rUS(od3ZRkb)d&brHEH>vxEv9Y*B`b!PNpKE_1T*?V-j+}3 zu&y0y-3{tFbPor28yr0>wjrunSZS;lYI==1^+T|<(&)Rr%H#DCkC{G*9Y0egt~6d* zm{jKHRU7^)!7fm1dc~A{7@^mBI7iQ~#ly6u`MX>4@`!+&LF$8?!*Maok(#Rp^!rsc zozchg2GRcFZ(mhDPcrAP*U=IuzNznHJotP>SZaGznh7ekmCSssxYH^!w_HPR1Un9z77D6Ydcqm~;d`wt zxm4fi!0D_8Z67dyf-?*!Fy#(n<#fw;jZ4FMhDA7&mA5utKJZ}smn9p=xCTR!J%;BP zk6%OA2k$84v3)b6&wjB!=&t_Onx)Co=E;@YtiJlp9tm5*2HBaF_Rx#aKg;GDJIZ&# zlJi7Q&LdANlPx^1xLzV#5wdp=QfRC)PM_g^_Rh(3+dn7?eW-ep%{@89jjll21s^=k zE_qHY{jzN#)2TP5*^D2n0z`lvdYuGl^aF)zo7`p!2)bjJ${}Wv#R~g4tBfhyo$_!(!FoLkxbKT`M48p*;wGfnf4snL;lfx9 z289u({OZpa0^F%hc?rAxi-y1hPeesS!ND;g6%9`S7heBPLm*M$K5r@-0RiPB;Hc(9 zA_!;#l`MdUM__)Rk3u6rX#^bAx=17(PPwD}@3H_I0tK!&r=o!=Av6@w2sIzLwH-o3 zW2td~E9%iy`UC4?!42os^WossIFN80LLi9tf=!y+MiLE_L5J%fwu zAvll(sC+0IIz=HM_J>3vq4oz(QX%W2(3Io!-}e`V#X3%)W~g;G-1ATEb0{$@`2|FA|D!j2tthmjfKjGreXI0E>u1OR6YzG^rWED6$Ut22n}>KfzZ&3Gd;wNz!JQObmPwB%!dHt0$0Otn+KZJ&a_;wr?I3fri4ZVPcA-c!Iq0b;5 zw1c3Y508YzG7z<(z7CIq`Y=2i1CbAi2VDaT@y|H$NJDG`kAwObJU9!7$PA6=po0!1 z=HUnk1Y`}6UO{{q0UD2R1QZ5>gMbFzTd4MufPwl>0;OLIHQ%q^Ex+3V0Voy1M*tmL zejkemc^LJ&fClmH!1^F|iicw%`-X?(Ap3@g<7v>KF%%E-CTg7mvx3+V9&|6F)*l{$ zhS(&?Sh3W)!XvPdm<*yI4H_Ow1Bom|S0DyJWI;l5ZzLXx!a!s}q9M6A9*Lo}WBF|_ z@sy|xp#iNzY0$AKI3yUacbkhlP7cxwL)GEoE#8l{iZ zZ+1obS^=m)f2W}kNa|b)4N?p0cm!zRTL@HR(ZKCe>lsv%)czU#(K%4+?_)u9Lr}Uv z{oU><5s$hq12l;51T+xjA!D(igBA6BIMC9Ing+@LFu)JNA+mtnmI^Q60}tl!^MT2c zlzv)NwLJv~l!m22!_lDOY0yB&E$TJEa|ER!XwX2fFUVNvc?1$c0|z(*fR3es1LQtX zJ{mYcz6Rj~_5!8RzyV?-l#fbg3?7uzRJK9cBTx@Q$I`$7o&_i$mCTeisC_484G>o$ zV?iztrP06vn#=vh2iAZ*3%}N&fdlyL-^Tvpqk#kXKPVp+Hp*CF_Ygi1Q=l{&IDr3y z@=;;?wFV6wAf7|V(!c@EU!Z(6Z~%V=;RE#%ltu#ws28AoG;n~r8_Gum2Z$BF@lp1d zI_6RI0(#y3#z&!n+zd*ifdkZ`P(B(sK#m0Eqk#kD%1}NU`vGdY-}nGFP_RP%B=DWT z@lmjWx)w^Kfdlw^C?5?RI2t%W{DqFCfdfaiN5ABw!bYLtY2W~P1Y`}6PeN%laDX}m z%0~kSs7-(4qv)AB2l*u*4IGrdkJK>$o`dY{ z_py{UsB1OK8lYB#tU)85gUpTwA9O!ZG~zi5)IHEOXyBj`&rzUvCuA&*cuwi}3FV`) zA2i}Q3gn{Du~d6R(G{p?pnNoN(1_-!h)j=>N5{O1E)|_V^MG{^;s#F@-f8U>S^#TbbBYFI~$9<{9j+P z!TjI;X3Zae;9}`c{^L`2@L35Shh$?B6I0VuXJh&6qjxwP%l{AIVEXPvFX2CAf>FME UWJGobKT@;?ksIs`;!nB%2aLM_GXMYp literal 0 HcmV?d00001 From cc1c9ffd20e923acb1a2331b4785f632c79eedc0 Mon Sep 17 00:00:00 2001 From: Ashutosh Agrawal Date: Wed, 13 Mar 2024 09:13:04 -0700 Subject: [PATCH 12/32] * Fixed inbound routing table action name to match with the latest P4 code (#534) * Fixes to CreateDeleteEniTest and EniScaleTest * Added IPv4 checksum calculation for tunnel encapsulation * Set "I" bit in Flags field of VXLAN header * Hardcoded underlay mac address to 0 since P4 behavioral code doesn't support underlay routing completely. * Disabled UDP checksum for behavioral model (applies to both bmv2 and p4dpdk) --- dash-pipeline/SAI/templates/saiapi.cpp.j2 | 10 +++ dash-pipeline/bmv2/dash_bmv2_v1model.p4 | 22 ++++++- dash-pipeline/bmv2/dash_tunnel.p4 | 2 +- test/SAI-Challenger | 2 +- test/docs/testplans/vnet.md | 4 +- .../functional/ptf/sai_dash_utils.py | 66 ++++++++++++------- test/test-cases/functional/ptf/saidashacl.py | 2 - test/test-cases/functional/ptf/saidasheni.py | 23 +++---- test/test-cases/functional/ptf/saidashvnet.py | 24 +++---- .../functional/ptf/saidashvnet_sanity.py | 8 --- .../saic/config_bidir_setup_commands.py | 6 +- .../saic/config_inbound_setup_commands.py | 4 +- .../sai-api/test_sai_api_vnet_in_route.py | 4 +- .../saic/test_vm_to_vm_commn_acl_inbound.py | 3 +- .../saic/test_vm_to_vm_commn_acl_outbound.py | 1 - .../saic/test_vm_to_vm_commn_udp_bidir.py | 4 -- .../saic/test_vm_to_vm_commn_udp_inbound.py | 2 - .../saic/test_vm_to_vm_commn_udp_outbound.py | 2 - .../scale/saic/test_sai_vnet_inbound.py | 1 - .../saic/test_sai_vnet_outbound_simple.py | 3 +- .../saic/test_sai_vnet_route_bidirectional.py | 15 ++--- .../test_sai_vnet_route_unidirectional.py | 4 +- .../saic/vnet_inbound_setup_commands.json | 2 +- 23 files changed, 114 insertions(+), 100 deletions(-) diff --git a/dash-pipeline/SAI/templates/saiapi.cpp.j2 b/dash-pipeline/SAI/templates/saiapi.cpp.j2 index 6f650f4d9..f342ba1f1 100644 --- a/dash-pipeline/SAI/templates/saiapi.cpp.j2 +++ b/dash-pipeline/SAI/templates/saiapi.cpp.j2 @@ -395,6 +395,11 @@ static sai_status_t dash_sai_create_{{ table.name }}( {% elif key.match_type == 'lpm' %} auto mf_lpm = mf->mutable_lpm(); {{key.field}}SetVal(tableEntry->{{ key.name | lower }}, mf_lpm, {{key.bitwidth}}); + {% elif key.match_type == 'ternary' %} + auto mf_ternary = mf->mutable_ternary(); + {{key.field}}SetVal(tableEntry->{{ key.name | lower }}, mf_ternary, {{key.bitwidth}}); + {{key.field}}SetMask(tableEntry->{{ key.name | lower }}_mask, mf_ternary, {{key.bitwidth}}); + matchActionEntry->set_priority(tableEntry->priority); {% elif key.match_type == 'list' %} // BMv2 doesn't support "list" match type, and we are using "optional" match in v1model as our implementation. // Hence, here we only take the first item from the list and program it as optional match. @@ -568,6 +573,11 @@ static sai_status_t dash_sai_remove_{{ table.name }}( {% elif key.match_type == 'lpm' %} auto mf_lpm = mf->mutable_lpm(); {{key.field}}SetVal(tableEntry->{{ key.name | lower }}, mf_lpm, {{key.bitwidth}}); + {% elif key.match_type == 'ternary' %} + auto mf_ternary = mf->mutable_ternary(); + {{key.field}}SetVal(tableEntry->{{ key.name | lower }}, mf_ternary, {{key.bitwidth}}); + {{key.field}}SetMask(tableEntry->{{ key.name | lower }}_mask, mf_ternary, {{key.bitwidth}}); + matchActionEntry->set_priority(tableEntry->priority); {% elif key.match_type == 'list' %} // BMv2 doesn't support "list" match type, and we are using "optional" match in v1model as our implementation. // Hence, here we only take the first item from the list and program it as optional match. diff --git a/dash-pipeline/bmv2/dash_bmv2_v1model.p4 b/dash-pipeline/bmv2/dash_bmv2_v1model.p4 index 49f877645..6a93f962a 100644 --- a/dash-pipeline/bmv2/dash_bmv2_v1model.p4 +++ b/dash-pipeline/bmv2/dash_bmv2_v1model.p4 @@ -8,7 +8,27 @@ control dash_verify_checksum(inout headers_t hdr, control dash_compute_checksum(inout headers_t hdr, inout metadata_t meta) { - apply { } + apply { +#ifdef TARGET_BMV2_V1MODEL + update_checksum( + hdr.u0_ipv4.isValid(), + { + hdr.u0_ipv4.version, + hdr.u0_ipv4.ihl, + hdr.u0_ipv4.diffserv, + hdr.u0_ipv4.total_len, + hdr.u0_ipv4.identification, + hdr.u0_ipv4.frag_offset, + hdr.u0_ipv4.flags, + hdr.u0_ipv4.ttl, + hdr.u0_ipv4.protocol, + hdr.u0_ipv4.src_addr, + hdr.u0_ipv4.dst_addr + }, + hdr.u0_ipv4.hdr_checksum, + HashAlgorithm.csum16); +#endif // TARGET_BMV2_V1MODEL + } } control dash_egress(inout headers_t hdr, diff --git a/dash-pipeline/bmv2/dash_tunnel.p4 b/dash-pipeline/bmv2/dash_tunnel.p4 index 125b43516..9ba8df82c 100644 --- a/dash-pipeline/bmv2/dash_tunnel.p4 +++ b/dash-pipeline/bmv2/dash_tunnel.p4 @@ -52,7 +52,7 @@ action push_vxlan_tunnel_ ## underlay_id ## (inout headers_t hdr, \ hdr. ## underlay_id ## _vxlan.setValid(); \ hdr. ## underlay_id ## _vxlan.reserved = 0; \ hdr. ## underlay_id ## _vxlan.reserved_2 = 0; \ - hdr. ## underlay_id ## _vxlan.flags = 0; \ + hdr. ## underlay_id ## _vxlan.flags = 0x8; \ hdr. ## underlay_id ## _vxlan.vni = tunnel_key; \ } #endif diff --git a/test/SAI-Challenger b/test/SAI-Challenger index 95edf36d1..ccff50f4a 160000 --- a/test/SAI-Challenger +++ b/test/SAI-Challenger @@ -1 +1 @@ -Subproject commit 95edf36d124f098d04b9f3ed984fe404959c9662 +Subproject commit ccff50f4ae7371b7ece63ecab9866ee0f617ea45 diff --git a/test/docs/testplans/vnet.md b/test/docs/testplans/vnet.md index fa487a097..53322c175 100644 --- a/test/docs/testplans/vnet.md +++ b/test/docs/testplans/vnet.md @@ -103,8 +103,8 @@ Original table [link](https://github.com/sonic-net/DASH/blob/main/documentation/ | # | Test case purpose | Test Class.Method | Test description | |:------:|:-----------|:---|:------| -| 1-2 | Verify VNET2VNET routing with PA validation entry PERMIT.
SAI_INBOUND_ROUTING_ENTRY_ACTION_VXLAN_DECAP_PA_VALIDATE
SAI_PA_VALIDATION_ENTRY_ACTION_PERMIT | `Vnet2VnetInboundDecapPaValidateSinglePortTest.`
`vnet2VnetInboundRoutingTest`

`Vnet2VnetInboundDecapPaValidateTwoPortsTest.`
`vnet2VnetInboundRoutingTest` | Creates single ENI inbound (SAI_INBOUND_ROUTING_ENTRY_ACTION_VXLAN_DECAP_PA_VALIDATE) overlay configuration.
Verifies configuration with mono/bidirectional VXLAN TCP traffic.
1. With underlay route
2. Without underlay route | -| 3-4 | Verify VNET2VNET routing without PA validation entry
SAI_INBOUND_ROUTING_ENTRY_ACTION_VXLAN_DECAP | `Vnet2VnetInboundDecapSinglePortTest.`
`vnet2VnetInboundRoutingTest`

`Vnet2VnetInboundDecapTwoPortsTest.`
`vnet2VnetInboundRoutingTest` | Creates single ENI inbound (SAI_INBOUND_ROUTING_ENTRY_ACTION_VXLAN_DECAP) overlay configuration.
Verifies configuration with mono/bidirectional VXLAN TCP traffic.
1. With underlay route
2. Without underlay route | +| 1-2 | Verify VNET2VNET routing with PA validation entry PERMIT.
SAI_INBOUND_ROUTING_ENTRY_ACTION_TUNNEL_DECAP_PA_VALIDATE
SAI_PA_VALIDATION_ENTRY_ACTION_PERMIT | `Vnet2VnetInboundDecapPaValidateSinglePortTest.`
`vnet2VnetInboundRoutingTest`

`Vnet2VnetInboundDecapPaValidateTwoPortsTest.`
`vnet2VnetInboundRoutingTest` | Creates single ENI inbound (SAI_INBOUND_ROUTING_ENTRY_ACTION_TUNNEL_DECAP_PA_VALIDATE) overlay configuration.
Verifies configuration with mono/bidirectional VXLAN TCP traffic.
1. With underlay route
2. Without underlay route | +| 3-4 | Verify VNET2VNET routing without PA validation entry
SAI_INBOUND_ROUTING_ENTRY_ACTION_TUNNEL_DECAP | `Vnet2VnetInboundDecapSinglePortTest.`
`vnet2VnetInboundRoutingTest`

`Vnet2VnetInboundDecapTwoPortsTest.`
`vnet2VnetInboundRoutingTest` | Creates single ENI inbound (SAI_INBOUND_ROUTING_ENTRY_ACTION_TUNNEL_DECAP) overlay configuration.
Verifies configuration with mono/bidirectional VXLAN TCP traffic.
1. With underlay route
2. Without underlay route | | 5-6 | Verify VNET2VNET routing when multiple Inbound routing entries and multiple PA validate exist with single ENI | `Vnet2VnetInboundMultiplePaValidatesSingleEniSinglePortTest.`
`vnet2VnetInboundRoutingPositiveTest`

`Vnet2VnetInboundMultiplePaValidatesSingleEniTwoPortsTest.`
`vnet2VnetInboundRoutingPositiveTest` | Creates single ENI with multiple Inbound routing entries.
Verifies configuration with mono/bidirectional VXLAN TCP traffic.
1. With underlay route
2. Without underlay route | | 7-8 | Verify VNET2VNET routing when multiple Inbound routing entries and multiple PA validate exist with multiple ENI | `Vnet2VnetInboundMultiplePaValidatesMultipleEniSinglePortTest.`
`vnet2VnetInboundRoutingPositiveTest`

`Vnet2VnetInboundMultiplePaValidatesMultipleEniTwoPortsTest.`
`vnet2VnetInboundRoutingPositiveTest` | Creates 2 ENI: 1st ENI with 2 Inbound routes (with and without PA Validate), 2nd ENI with 1 Inbound route and 1 PA validation.
Verifies configuration with mono/bidirectional VXLAN TCP traffic.
1. With underlay route
2. Without underlay route | | 9-10 | Verify VNET2VNET routing when single ENI and single Inbound routing entry exist with multiple PA validation entries | `Vnet2VnetSingleInboundRouteMultiplePaValidateSinglePortTest.`
`vnet2VnetInboundRoutingTest`

`Vnet2VnetSingleInboundRouteMultiplePaValidateTwoPortsTest.`
`vnet2VnetInboundRoutingTest` | Creates single ENI with single Inbound routing entry and with multiple PA validation entries.
Verifies configuration with mono/bidirectional VXLAN TCP traffic.
1. With underlay route
2. Without underlay route | diff --git a/test/test-cases/functional/ptf/sai_dash_utils.py b/test/test-cases/functional/ptf/sai_dash_utils.py index cc34ce22d..d4758fe3c 100644 --- a/test/test-cases/functional/ptf/sai_dash_utils.py +++ b/test/test-cases/functional/ptf/sai_dash_utils.py @@ -239,15 +239,15 @@ def vnet_remove(self, vnet_id): def inbound_routing_decap_validate_create(self, eni_id, vni, sip, sip_mask, src_vnet_id): """ Create inbound routing entry with - SAI_INBOUND_ROUTING_ENTRY_ACTION_VXLAN_DECAP_PA_VALIDATE action + SAI_INBOUND_ROUTING_ENTRY_ACTION_TUNNEL_DECAP_PA_VALIDATE action """ inbound_routing_entry = sai_thrift_inbound_routing_entry_t( switch_id=self.switch_id, vni=vni, eni_id=eni_id, sip=sai_ipaddress(sip), - sip_mask=sai_ipaddress(sip_mask), priority=0) + sip_mask=sai_ipaddress(sip_mask), priority=1) sai_thrift_create_inbound_routing_entry(self.client, inbound_routing_entry, - action=SAI_INBOUND_ROUTING_ENTRY_ACTION_VXLAN_DECAP_PA_VALIDATE, + action=SAI_INBOUND_ROUTING_ENTRY_ACTION_TUNNEL_DECAP_PA_VALIDATE, src_vnet_id=src_vnet_id) self.assertEqual(self.status(), SAI_STATUS_SUCCESS) self.add_teardown_obj(self.inbound_routing_remove, inbound_routing_entry) @@ -256,15 +256,15 @@ def inbound_routing_decap_validate_create(self, eni_id, vni, sip, sip_mask, src_ def inbound_routing_decap_create(self, eni_id, vni, sip, sip_mask): """ Create inbound routing entry with - SAI_INBOUND_ROUTING_ENTRY_ACTION_VXLAN_DECAP action + SAI_INBOUND_ROUTING_ENTRY_ACTION_TUNNEL_DECAP action """ inbound_routing_entry = sai_thrift_inbound_routing_entry_t( switch_id=self.switch_id, vni=vni, eni_id=eni_id, sip=sai_ipaddress(sip), - sip_mask=sai_ipaddress(sip_mask), priority=0) + sip_mask=sai_ipaddress(sip_mask), priority=1) sai_thrift_create_inbound_routing_entry(self.client, inbound_routing_entry, - action=SAI_INBOUND_ROUTING_ENTRY_ACTION_VXLAN_DECAP) + action=SAI_INBOUND_ROUTING_ENTRY_ACTION_TUNNEL_DECAP) self.assertEqual(self.status(), SAI_STATUS_SUCCESS) self.add_teardown_obj(self.inbound_routing_remove, inbound_routing_entry) return inbound_routing_entry @@ -547,10 +547,14 @@ def update_configuration_for_tx_equal_to_rx(self): """ self.rx_host.port = self.tx_host.port - self.rx_host.mac = self.tx_host.mac + # MAC address is hardcoded to 0 since underlay routing is not completely implemented. + self.rx_host.mac = "00:00:00:00:00:00" + #self.rx_host.mac = self.tx_host.mac self.rx_host.peer.port = self.tx_host.peer.port - self.rx_host.peer.mac = self.tx_host.peer.mac + # MAC address is hardcoded to 0 since underlay routing is not completely implemented. + self.rx_host.peer.mac = "00:00:00:00:00:00" + #self.rx_host.peer.mac = self.tx_host.peer.mac self.rx_host.peer.ip = self.tx_host.peer.ip @staticmethod @@ -599,6 +603,12 @@ class VnetTrafficMixin: Mixin class with methods dedicated for Vnet use cases traffic verification """ + # Disable UDP checksum for behavioral model + if test_param_get('target') == 'bmv2': + with_udp_chksum = False + else: + with_udp_chksum = True + # TCP flags SYN = "S" SYN_ACK = "SA" @@ -958,7 +968,7 @@ def create_vxlan_tcp_session_packets(self, eth_src=client.mac, **{self.ip_dst_outer_pkt: client.peer.ip}, # VIP **{self.ip_src_outer_pkt: client.ip}, - with_udp_chksum=True, + with_udp_chksum=self.with_udp_chksum, vxlan_vni=client.client.vni, inner_frame=client_inner_pkt) @@ -966,7 +976,8 @@ def create_vxlan_tcp_session_packets(self, eth_src=server.peer.mac, **{self.ip_dst_outer_pkt: server.ip}, **{self.ip_src_outer_pkt: server.peer.ip}, # VIP - with_udp_chksum=True, + with_udp_chksum=self.with_udp_chksum, + udp_sport=0, vxlan_vni=server.client.vni, inner_frame=exp_client_inner_pkt) @@ -1010,7 +1021,7 @@ def create_vxlan_tcp_session_packets(self, eth_src=server.mac, **{self.ip_dst_outer_pkt: server.peer.ip}, # VIP **{self.ip_src_outer_pkt: server.ip}, - with_udp_chksum=True, + with_udp_chksum=self.with_udp_chksum, vxlan_vni=server.client.vni, inner_frame=server_inner_pkt) @@ -1018,7 +1029,8 @@ def create_vxlan_tcp_session_packets(self, eth_src=client.peer.mac, **{self.ip_dst_outer_pkt: client.ip}, **{self.ip_src_outer_pkt: client.peer.ip}, # VIP - with_udp_chksum=True, + with_udp_chksum=self.with_udp_chksum, + udp_sport=0, vxlan_vni=client.client.vni, inner_frame=server_inner_pkt) @@ -1105,7 +1117,7 @@ def create_vxlan_tcp_session_route_direct_packets(self, eth_src=client.mac, **{self.ip_dst_outer_pkt: client.peer.ip}, # VIP **{self.ip_src_outer_pkt: client.ip}, - with_udp_chksum=True, + with_udp_chksum=self.with_udp_chksum, vxlan_vni=client.client.vni, inner_frame=client_inner_pkt) @@ -1167,7 +1179,8 @@ def create_vxlan_tcp_session_route_direct_packets(self, eth_src=client.peer.mac, **{self.ip_dst_inner_pkt: client.ip}, **{self.ip_src_inner_pkt: client.peer.ip}, # VIP - with_udp_chksum=True, + with_udp_chksum=self.with_udp_chksum, + udp_sport=0, vxlan_vni=client.client.vni, inner_frame=exp_server_inner_pkt) @@ -1261,7 +1274,7 @@ def create_vxlan_udp_session_packets(self, eth_src=client.mac, **{self.ip_dst_outer_pkt: client.peer.ip}, # VIP **{self.ip_src_outer_pkt: client.ip}, - with_udp_chksum=True, + with_udp_chksum=self.with_udp_chksum, vxlan_vni=client.client.vni, inner_frame=client_inner_pkt) @@ -1269,7 +1282,8 @@ def create_vxlan_udp_session_packets(self, eth_src=server.peer.mac, **{self.ip_dst_outer_pkt: server.ip}, **{self.ip_src_outer_pkt: server.peer.ip}, # VIP - with_udp_chksum=True, + with_udp_chksum=self.with_udp_chksum, + udp_sport=0, vxlan_vni=server.client.vni, inner_frame=exp_client_inner_pkt) @@ -1277,7 +1291,7 @@ def create_vxlan_udp_session_packets(self, eth_src=server.mac, **{self.ip_dst_outer_pkt: server.peer.ip}, # VIP **{self.ip_src_outer_pkt: server.ip}, - with_udp_chksum=True, + with_udp_chksum=self.with_udp_chksum, vxlan_vni=server.client.vni, inner_frame=server_inner_pkt) @@ -1285,7 +1299,8 @@ def create_vxlan_udp_session_packets(self, eth_src=client.peer.mac, **{self.ip_dst_outer_pkt: client.ip}, **{self.ip_src_outer_pkt: client.peer.ip}, # VIP - with_udp_chksum=True, + with_udp_chksum=self.with_udp_chksum, + udp_sport=0, vxlan_vni=client.client.vni, inner_frame=server_inner_pkt) send_packets = OrderedDict() @@ -1339,7 +1354,7 @@ def create_vxlan_icmp_session_packets(self, eth_src=client.mac, **{self.ip_dst_outer_pkt: client.peer.ip}, # VIP **{self.ip_src_outer_pkt: client.ip}, - with_udp_chksum=True, + with_udp_chksum=self.with_udp_chksum, vxlan_vni=client.client.vni, inner_frame=client_inner_pkt) @@ -1347,7 +1362,8 @@ def create_vxlan_icmp_session_packets(self, eth_src=server.peer.mac, **{self.ip_dst_outer_pkt: server.ip}, **{self.ip_src_outer_pkt: server.peer.ip}, # VIP - with_udp_chksum=True, + with_udp_chksum=self.with_udp_chksum, + udp_sport=0, vxlan_vni=server.client.vni, inner_frame=exp_client_inner_pkt) @@ -1355,7 +1371,7 @@ def create_vxlan_icmp_session_packets(self, eth_src=server.mac, **{self.ip_dst_outer_pkt: server.peer.ip}, # VIP **{self.ip_src_outer_pkt: server.ip}, - with_udp_chksum=True, + with_udp_chksum=self.with_udp_chksum, vxlan_vni=server.client.vni, inner_frame=server_inner_pkt) @@ -1363,7 +1379,8 @@ def create_vxlan_icmp_session_packets(self, eth_src=client.peer.mac, **{self.ip_dst_outer_pkt: client.ip}, **{self.ip_src_outer_pkt: client.peer.ip}, - with_udp_chksum=True, + with_udp_chksum=self.with_udp_chksum, + udp_sport=0, vxlan_vni=client.client.vni, inner_frame=server_inner_pkt) send_packets = OrderedDict() @@ -1452,7 +1469,7 @@ def create_vxlan_oneway_pkts(self, eth_src=client.mac, **{self.ip_dst_outer_pkt: client.peer.ip}, # VIP **{self.ip_src_outer_pkt: client.ip}, - with_udp_chksum=True, + with_udp_chksum=self.with_udp_chksum, vxlan_vni=client.client.vni, inner_frame=inner_pkt) @@ -1460,7 +1477,8 @@ def create_vxlan_oneway_pkts(self, eth_src=server.peer.mac, **{self.ip_dst_outer_pkt: server.ip}, **{self.ip_src_outer_pkt: server.peer.ip}, # VIP - with_udp_chksum=True, + with_udp_chksum=self.with_udp_chksum, + udp_sport=0, vxlan_vni=server.client.vni, inner_frame=exp_inner_pkt) diff --git a/test/test-cases/functional/ptf/saidashacl.py b/test/test-cases/functional/ptf/saidashacl.py index 5f295d1c2..794eb0c9f 100644 --- a/test/test-cases/functional/ptf/saidashacl.py +++ b/test/test-cases/functional/ptf/saidashacl.py @@ -95,8 +95,6 @@ def runTest(self): with_udp_chksum=False, vxlan_vni=self.saithrift.vnet_vni, inner_frame=inner_exp_pkt) - vxlan_exp_pkt[IP].chksum = 0 - vxlan_exp_pkt[IP][UDP][VXLAN].flags = 0 pkt_exp = vxlan_exp_pkt print("Sending packet...\n", vxlan_pkt.__repr__()) diff --git a/test/test-cases/functional/ptf/saidasheni.py b/test/test-cases/functional/ptf/saidasheni.py index 6446f65e9..62cd75de4 100644 --- a/test/test-cases/functional/ptf/saidasheni.py +++ b/test/test-cases/functional/ptf/saidasheni.py @@ -41,7 +41,8 @@ def setUp(self): self.eni_mac = '00:11:22:33:44:55' # ENI MAC address self.vm_underlay_dip = sai_ipaddress('192.168.1.5') # ENI VM underlay DIP - self.sip = '10.0.1.2' # PA validation entry SIP address + self.sip = '10.0.1.0' # PA validation entry SIP address + self.sip_mask = '255.255.255.0' def runTest(self): # Not all tests are interdependent, @@ -53,10 +54,8 @@ def runTest(self): self.createDirectionLookupTest() self.createEniTest() self.createEniEtherAddressMapTest() - if not test_param_get('target') == 'bmv2': - # Issue #233 - self.createInboundRoutingEntryTest() - self.createPaValidationTest() + self.createInboundRoutingEntryTest() + self.createPaValidationTest() self.createOutboundRoutingEntryTest() self.createCa2PaEntryTest() @@ -172,7 +171,7 @@ def createInboundRoutingEntryTest(self): self.inbound_routing_entry = self.inbound_routing_decap_validate_create( eni_id=self.eni, vni=self.vm_vni, - sip=self.sip, sip_mask="255.255.255.0", + sip=self.sip, sip_mask=self.sip_mask, src_vnet_id=self.outbound_vnet ) @@ -786,20 +785,20 @@ def inboundRoutingEntryAttributesTest(self): action=True, src_vnet_id=True) self.assertEqual(self.status(), SAI_STATUS_SUCCESS) - self.assertEqual(attr['action'], SAI_INBOUND_ROUTING_ENTRY_ACTION_VXLAN_DECAP_PA_VALIDATE) + self.assertEqual(attr['action'], SAI_INBOUND_ROUTING_ENTRY_ACTION_TUNNEL_DECAP_PA_VALIDATE) self.assertEqual(attr['src_vnet_id'], self.outbound_vnet) try: # set and verify new action sai_thrift_set_inbound_routing_entry_attribute(self.client, inbound_routing_entry=self.inbound_routing_entry, - action=SAI_INBOUND_ROUTING_ENTRY_ACTION_VXLAN_DECAP) + action=SAI_INBOUND_ROUTING_ENTRY_ACTION_TUNNEL_DECAP) self.assertEqual(self.status(), SAI_STATUS_SUCCESS) attr = sai_thrift_get_inbound_routing_entry_attribute(self.client, inbound_routing_entry=self.inbound_routing_entry, action=True) - self.assertEqual(attr['action'], SAI_INBOUND_ROUTING_ENTRY_ACTION_VXLAN_DECAP) + self.assertEqual(attr['action'], SAI_INBOUND_ROUTING_ENTRY_ACTION_TUNNEL_DECAP) # set and verify new src_vnet_id value test_vnet = self.vnet_create(vni=500) @@ -818,7 +817,7 @@ def inboundRoutingEntryAttributesTest(self): sai_thrift_set_inbound_routing_entry_attribute( self.client, inbound_routing_entry=self.inbound_routing_entry, - action=SAI_INBOUND_ROUTING_ENTRY_ACTION_VXLAN_DECAP_PA_VALIDATE) + action=SAI_INBOUND_ROUTING_ENTRY_ACTION_TUNNEL_DECAP_PA_VALIDATE) sai_thrift_set_inbound_routing_entry_attribute(self.client, inbound_routing_entry=self.inbound_routing_entry, src_vnet_id=self.outbound_vnet) @@ -827,7 +826,7 @@ def inboundRoutingEntryAttributesTest(self): inbound_routing_entry=self.inbound_routing_entry, action=True, src_vnet_id=True) - self.assertEqual(attr['action'], SAI_INBOUND_ROUTING_ENTRY_ACTION_VXLAN_DECAP_PA_VALIDATE) + self.assertEqual(attr['action'], SAI_INBOUND_ROUTING_ENTRY_ACTION_TUNNEL_DECAP_PA_VALIDATE) self.assertEqual(attr['src_vnet_id'], self.outbound_vnet) def outboundRoutingEntryAttributesTest(self): @@ -977,7 +976,6 @@ def deleteEniWhenMapExistTest(self): self.assertEqual(self.status(), SAI_STATUS_SUCCESS) -@skipIf(test_param_get('target') == 'bmv2', "Blocked by Issue #233. Inbound Routing is not supported in BMv2.") class EniScaleTest(VnetAPI): """ Verifies ENI scaling: @@ -1083,7 +1081,6 @@ def eniScaleTest(self): print("PASS") -@skipIf(test_param_get('target') == 'bmv2', "Blocked by Issue #233. Inbound Routing is not supported in BMv2.") class CreateTwoSameEnisNegativeTest(VnetAPI): """ Verifies failure in case of creation the same ENIs in one VNET diff --git a/test/test-cases/functional/ptf/saidashvnet.py b/test/test-cases/functional/ptf/saidashvnet.py index 57062866a..6c25d1afa 100644 --- a/test/test-cases/functional/ptf/saidashvnet.py +++ b/test/test-cases/functional/ptf/saidashvnet.py @@ -120,7 +120,7 @@ def l3UnderlayHost2toHost1RoutingTest(self): class Vnet2VnetInboundDecapPaValidateSinglePortTest(VnetApiEndpoints, VnetTrafficMixin): """ Inbound Vnet to Vnet scenario test case with - VXLAN_DECAP_PA_VALIDATE inbound routing entry action + TUNNEL_DECAP_PA_VALIDATE inbound routing entry action with underlay config (neighbour + next hop) but without underlay routes Verifies positive and negative scenarios @@ -208,7 +208,7 @@ class Vnet2VnetInboundDecapPaValidateSinglePortOverlayIpv6Test(Vnet2VnetInboundD """ Underlay IPv4 and Overlay IPv6 configs Inbound Vnet to Vnet scenario test case with - VXLAN_DECAP_PA_VALIDATE inbound routing entry action + TUNNEL_DECAP_PA_VALIDATE inbound routing entry action with underlay config (neighbour + next hop) but without underlay routes Verifies positive and negative scenarios @@ -223,7 +223,7 @@ def setUp(self): class Vnet2VnetInboundDecapPaValidateTwoPortsTest(Vnet2VnetInboundDecapPaValidateSinglePortTest): """ Inbound Vnet to Vnet scenario test case with - VXLAN_DECAP_PA_VALIDATE inbound routing entry action + TUNNEL_DECAP_PA_VALIDATE inbound routing entry action with full underlay config (2 neighbours, 2 next-hops, 2 routes) Verifies positive scenario @@ -243,7 +243,7 @@ class Vnet2VnetInboundDecapPaValidateTwoPortsOverlayIpv6Test(Vnet2VnetInboundDec """ Underlay IPv4 and Overlay IPv6 configs Inbound Vnet to Vnet scenario test case with - VXLAN_DECAP_PA_VALIDATE inbound routing entry action + TUNNEL_DECAP_PA_VALIDATE inbound routing entry action with full underlay config (2 neighbours, 2 next-hops, 2 routes) Verifies positive scenario @@ -261,7 +261,7 @@ def runTest(self): class Vnet2VnetInboundDecapSinglePortTest(Vnet2VnetInboundDecapPaValidateSinglePortTest): """ Inbound Vnet to Vnet scenario test case with - VXLAN_DECAP inbound routing entry action + TUNNEL_DECAP inbound routing entry action with underlay config (neighbour + next hop) but without underlay routes Verifies positive and negative scenarios @@ -319,7 +319,7 @@ class Vnet2VnetInboundDecapSinglePortOverlayIpv6Test(Vnet2VnetInboundDecapSingle """ Underlay IPv4 and Overlay IPv6 configs Inbound Vnet to Vnet scenario test case with - VXLAN_DECAP inbound routing entry action + TUNNEL_DECAP inbound routing entry action with underlay config (neighbour + next hop) but without underlay routes Verifies positive and negative scenarios @@ -334,7 +334,7 @@ def setUp(self): class Vnet2VnetInboundDecapTwoPortsTest(Vnet2VnetInboundDecapSinglePortTest): """ Inbound Vnet to Vnet scenario test case with - VXLAN_DECAP inbound routing entry action + TUNNEL_DECAP inbound routing entry action with full underlay config (2 neighbours, 2 next-hops, 2 routes) Verifies positive scenario @@ -354,7 +354,7 @@ class Vnet2VnetInboundDecapTwoPortsOverlayIpv6Test(Vnet2VnetInboundDecapSinglePo """ Underlay IPv4 and Overlay IPv6 configs Inbound Vnet to Vnet scenario test case with - VXLAN_DECAP inbound routing entry action + TUNNEL_DECAP inbound routing entry action with full underlay config (2 neighbours, 2 next-hops, 2 routes) Verifies positive scenario @@ -1104,7 +1104,7 @@ def configure_underlay(self): class Vnet2VnetSingleInboundRouteMultiplePaValidateSinglePortTest(VnetApiEndpoints, VnetTrafficMixin): """ Inbound Vnet to Vnet scenario test case with - VXLAN_DECAP_PA_VALIDATE inbound routing entry action with multiple PA validate entries + TUNNEL_DECAP_PA_VALIDATE inbound routing entry action with multiple PA validate entries with underlay config (neighbour + next hop) but without underlay routes Verifies positive and negative scenarios @@ -1224,7 +1224,7 @@ class Vnet2VnetSingleInboundRouteMultiplePaValidateSinglePortIpv6Test(Vnet2VnetS """ Underlay IPv4 and Overlay IPv6 configs Inbound Vnet to Vnet scenario test case with - VXLAN_DECAP_PA_VALIDATE inbound routing entry action with multiple PA validate entries + TUNNEL_DECAP_PA_VALIDATE inbound routing entry action with multiple PA validate entries with underlay config (neighbour + next hop) but without underlay routes Verifies positive and negative scenarios @@ -1320,7 +1320,7 @@ def configureTest(self): class Vnet2VnetSingleInboundRouteMultiplePaValidateTwoPortsTest(Vnet2VnetSingleInboundRouteMultiplePaValidateSinglePortTest): """ Inbound Vnet to Vnet scenario test case with - VXLAN_DECAP_PA_VALIDATE inbound routing entry action with multiple PA validate entries + TUNNEL_DECAP_PA_VALIDATE inbound routing entry action with multiple PA validate entries with full underlay config (2 neighbours + 2 next hops + 2 routes) Verifies positive and negative scenarios @@ -1339,7 +1339,7 @@ class Vnet2VnetSingleInboundRouteMultiplePaValidateTwoPortsIpv6Test(Vnet2VnetSin """ Underlay IPv4 and Overlay IPv6 configs Inbound Vnet to Vnet scenario test case with - VXLAN_DECAP_PA_VALIDATE inbound routing entry action with multiple PA validate entries + TUNNEL_DECAP_PA_VALIDATE inbound routing entry action with multiple PA validate entries with underlay config (2 neighbours + 2 next hops + 2 routes) Verifies positive and negative scenarios diff --git a/test/test-cases/functional/ptf/saidashvnet_sanity.py b/test/test-cases/functional/ptf/saidashvnet_sanity.py index 6deeb4f9b..33ea531f9 100644 --- a/test/test-cases/functional/ptf/saidashvnet_sanity.py +++ b/test/test-cases/functional/ptf/saidashvnet_sanity.py @@ -232,10 +232,6 @@ def trafficTest(self): with_udp_chksum=False, vxlan_vni=self.vnet_vni, inner_frame=inner_exp_pkt) - # TODO: Fix IP chksum - vxlan_exp_pkt[IP].chksum = 0 - # TODO: Fix UDP length - vxlan_exp_pkt[IP][UDP][VXLAN].flags = 0 self.pkt_exp = vxlan_exp_pkt print("\tSending outbound packet...") @@ -390,10 +386,6 @@ def trafficTest(self): with_udp_chksum=False, vxlan_vni=self.vnet_vni, inner_frame=inner_exp_pkt) - # TODO: Fix IP chksum - vxlan_exp_pkt[IP].chksum = 0 - # TODO: Fix UDP length - vxlan_exp_pkt[IP][UDP][VXLAN].flags = 0 self.pkt_exp = vxlan_exp_pkt print("\tSending outbound packet...") diff --git a/test/test-cases/functional/saic/config_bidir_setup_commands.py b/test/test-cases/functional/saic/config_bidir_setup_commands.py index cd558797f..7b4ebfd46 100644 --- a/test/test-cases/functional/saic/config_bidir_setup_commands.py +++ b/test/test-cases/functional/saic/config_bidir_setup_commands.py @@ -311,7 +311,7 @@ }, "attributes": [ "SAI_INBOUND_ROUTING_ENTRY_ATTR_ACTION", - "SAI_INBOUND_ROUTING_ENTRY_ACTION_VXLAN_DECAP_PA_VALIDATE", + "SAI_INBOUND_ROUTING_ENTRY_ACTION_TUNNEL_DECAP_PA_VALIDATE", "SAI_INBOUND_ROUTING_ENTRY_ATTR_SRC_VNET_ID", "$vnet" ] @@ -330,7 +330,7 @@ }, "attributes": [ "SAI_INBOUND_ROUTING_ENTRY_ATTR_ACTION", - "SAI_INBOUND_ROUTING_ENTRY_ACTION_VXLAN_DECAP_PA_VALIDATE", + "SAI_INBOUND_ROUTING_ENTRY_ACTION_TUNNEL_DECAP_PA_VALIDATE", "SAI_INBOUND_ROUTING_ENTRY_ATTR_SRC_VNET_ID", "$vnet" ] @@ -349,7 +349,7 @@ }, "attributes": [ "SAI_INBOUND_ROUTING_ENTRY_ATTR_ACTION", - "SAI_INBOUND_ROUTING_ENTRY_ACTION_VXLAN_DECAP_PA_VALIDATE", + "SAI_INBOUND_ROUTING_ENTRY_ACTION_TUNNEL_DECAP_PA_VALIDATE", "SAI_INBOUND_ROUTING_ENTRY_ATTR_SRC_VNET_ID", "$vnet" ] diff --git a/test/test-cases/functional/saic/config_inbound_setup_commands.py b/test/test-cases/functional/saic/config_inbound_setup_commands.py index 8ba05f2bc..2ce4a593b 100644 --- a/test/test-cases/functional/saic/config_inbound_setup_commands.py +++ b/test/test-cases/functional/saic/config_inbound_setup_commands.py @@ -285,7 +285,7 @@ }, "attributes": [ "SAI_INBOUND_ROUTING_ENTRY_ATTR_ACTION", - "SAI_INBOUND_ROUTING_ENTRY_ACTION_VXLAN_DECAP_PA_VALIDATE", + "SAI_INBOUND_ROUTING_ENTRY_ACTION_TUNNEL_DECAP_PA_VALIDATE", "SAI_INBOUND_ROUTING_ENTRY_ATTR_SRC_VNET_ID", "$vnet_#1" ] @@ -304,7 +304,7 @@ }, "attributes": [ "SAI_INBOUND_ROUTING_ENTRY_ATTR_ACTION", - "SAI_INBOUND_ROUTING_ENTRY_ACTION_VXLAN_DECAP_PA_VALIDATE", + "SAI_INBOUND_ROUTING_ENTRY_ACTION_TUNNEL_DECAP_PA_VALIDATE", "SAI_INBOUND_ROUTING_ENTRY_ATTR_SRC_VNET_ID", "$vnet_#1" ] diff --git a/test/test-cases/functional/saic/sai-api/test_sai_api_vnet_in_route.py b/test/test-cases/functional/saic/sai-api/test_sai_api_vnet_in_route.py index 73bc878fa..e2d86f062 100644 --- a/test/test-cases/functional/saic/sai-api/test_sai_api_vnet_in_route.py +++ b/test/test-cases/functional/saic/sai-api/test_sai_api_vnet_in_route.py @@ -132,7 +132,7 @@ def test_vnet_inbound_routing_entry_create(self, dpu): }, "attributes": [ "SAI_INBOUND_ROUTING_ENTRY_ATTR_ACTION", - "SAI_INBOUND_ROUTING_ENTRY_ACTION_VXLAN_DECAP_PA_VALIDATE", + "SAI_INBOUND_ROUTING_ENTRY_ACTION_TUNNEL_DECAP_PA_VALIDATE", "SAI_INBOUND_ROUTING_ENTRY_ATTR_SRC_VNET_ID", "$vnet" ] @@ -175,7 +175,7 @@ def test_vnet_inbound_routing_entry_set(self, dpu): }, "attribute": [ "SAI_INBOUND_ROUTING_ENTRY_ATTR_ACTION", - "SAI_INBOUND_ROUTING_ENTRY_ACTION_VXLAN_DECAP_CA_VALIDATE", + "SAI_INBOUND_ROUTING_ENTRY_ACTION_TUNNEL_DECAP_CA_VALIDATE", ] }, ] diff --git a/test/test-cases/functional/saic/test_vm_to_vm_commn_acl_inbound.py b/test/test-cases/functional/saic/test_vm_to_vm_commn_acl_inbound.py index be68da357..227b29d9e 100644 --- a/test/test-cases/functional/saic/test_vm_to_vm_commn_acl_inbound.py +++ b/test/test-cases/functional/saic/test_vm_to_vm_commn_acl_inbound.py @@ -84,7 +84,6 @@ def test_vm_to_vm_commn_acl_inbound(self, dataplane): udp.src_port.value = 11638 udp.dst_port.value = 4789 - #vxlan.flags.value = vxlan.vni.value = 101 vxlan.reserved0.value = 0 vxlan.reserved1.value = 0 @@ -129,7 +128,7 @@ def test_vm_to_vm_commn_acl_inbound(self, dataplane): print("\n======= Verify traffic with denied packets failing =======") print("\n======= Start traffic =======") su.start_traffic(dataplane, f2.name) - flow_names=[f1.name, f2.name, f3.name, f4.name] + flow_names=[f2.name, f3.name, f4.name] while(True): if (dataplane.is_traffic_stopped(flow_names)): break diff --git a/test/test-cases/functional/saic/test_vm_to_vm_commn_acl_outbound.py b/test/test-cases/functional/saic/test_vm_to_vm_commn_acl_outbound.py index dc091713e..9a57a4f48 100644 --- a/test/test-cases/functional/saic/test_vm_to_vm_commn_acl_outbound.py +++ b/test/test-cases/functional/saic/test_vm_to_vm_commn_acl_outbound.py @@ -104,7 +104,6 @@ def test_vm_to_vm_commn_acl_outbound(self, dataplane): udp1.src_port.value = 11638 udp1.dst_port.value = 4789 - #vxlan.flags.value = vxlan1.vni.value = 11 vxlan1.reserved0.value = 0 vxlan1.reserved1.value = 0 diff --git a/test/test-cases/functional/saic/test_vm_to_vm_commn_udp_bidir.py b/test/test-cases/functional/saic/test_vm_to_vm_commn_udp_bidir.py index be167367d..3161bc11d 100644 --- a/test/test-cases/functional/saic/test_vm_to_vm_commn_udp_bidir.py +++ b/test/test-cases/functional/saic/test_vm_to_vm_commn_udp_bidir.py @@ -88,7 +88,6 @@ def test_vm_to_vm_commn_udp_bidir(self, dataplane): udp1.src_port.value = 11638 udp1.dst_port.value = 4789 - #vxlan.flags.value = vxlan1.vni.value = 11 vxlan1.reserved0.value = 0 vxlan1.reserved1.value = 0 @@ -128,7 +127,6 @@ def test_vm_to_vm_commn_udp_bidir(self, dataplane): udp.src_port.value = 11638 udp.dst_port.value = 4789 - #vxlan.flags.value = vxlan.vni.value = 101 vxlan.reserved0.value = 0 vxlan.reserved1.value = 0 @@ -169,7 +167,6 @@ def test_vm_to_vm_commn_udp_bidir(self, dataplane): udp.src_port.value = 11638 udp.dst_port.value = 4789 - #vxlan.flags.value = vxlan.vni.value = 11 vxlan.reserved0.value = 0 vxlan.reserved1.value = 0 @@ -210,7 +207,6 @@ def test_vm_to_vm_commn_udp_bidir(self, dataplane): udp.src_port.value = 11638 udp.dst_port.value = 4789 - #vxlan.flags.value = vxlan.vni.value = 101 vxlan.reserved0.value = 0 vxlan.reserved1.value = 0 diff --git a/test/test-cases/functional/saic/test_vm_to_vm_commn_udp_inbound.py b/test/test-cases/functional/saic/test_vm_to_vm_commn_udp_inbound.py index dfb571126..695b38f03 100644 --- a/test/test-cases/functional/saic/test_vm_to_vm_commn_udp_inbound.py +++ b/test/test-cases/functional/saic/test_vm_to_vm_commn_udp_inbound.py @@ -80,7 +80,6 @@ def test_vm_to_vm_commn_udp_inbound(self, dataplane): udp1.src_port.value = 11638 udp1.dst_port.value = 4789 - #vxlan.flags.value = vxlan1.vni.value = 11 vxlan1.reserved0.value = 0 vxlan1.reserved1.value = 0 @@ -119,7 +118,6 @@ def test_vm_to_vm_commn_udp_inbound(self, dataplane): udp.src_port.value = 11638 udp.dst_port.value = 4789 - #vxlan.flags.value = vxlan.vni.value = 101 vxlan.reserved0.value = 0 vxlan.reserved1.value = 0 diff --git a/test/test-cases/functional/saic/test_vm_to_vm_commn_udp_outbound.py b/test/test-cases/functional/saic/test_vm_to_vm_commn_udp_outbound.py index d6b943b92..bac296144 100644 --- a/test/test-cases/functional/saic/test_vm_to_vm_commn_udp_outbound.py +++ b/test/test-cases/functional/saic/test_vm_to_vm_commn_udp_outbound.py @@ -106,7 +106,6 @@ def test_vm_to_vm_commn_udp_outbound(self, dataplane): udp1.src_port.value = 11638 udp1.dst_port.value = 4789 - #vxlan.flags.value = vxlan1.vni.value = 11 vxlan1.reserved0.value = 0 vxlan1.reserved1.value = 0 @@ -145,7 +144,6 @@ def test_vm_to_vm_commn_udp_outbound(self, dataplane): udp.src_port.value = 11638 udp.dst_port.value = 4789 - #vxlan.flags.value = vxlan.vni.value = 101 vxlan.reserved0.value = 0 vxlan.reserved1.value = 0 diff --git a/test/test-cases/scale/saic/test_sai_vnet_inbound.py b/test/test-cases/scale/saic/test_sai_vnet_inbound.py index 02f553ff3..5162c7898 100644 --- a/test/test-cases/scale/saic/test_sai_vnet_inbound.py +++ b/test/test-cases/scale/saic/test_sai_vnet_inbound.py @@ -130,7 +130,6 @@ def test_vnet_inbound_create(self, dpu): pprint(result) @pytest.mark.ptf - @pytest.mark.xfail(reason="https://github.com/sonic-net/DASH/issues/233") def test_vnet_inbound_traffic_check(self, dpu, dataplane): """Verify traffic forwarding in PTF style""" diff --git a/test/test-cases/scale/saic/test_sai_vnet_outbound_simple.py b/test/test-cases/scale/saic/test_sai_vnet_outbound_simple.py index 1a77ef25b..97de3f043 100644 --- a/test/test-cases/scale/saic/test_sai_vnet_outbound_simple.py +++ b/test/test-cases/scale/saic/test_sai_vnet_outbound_simple.py @@ -234,9 +234,8 @@ def test_vnet_inbound_simple_packet_modification(self, dpu, dataplane): udp_sport = 0, # TODO: Fix sport in pipeline with_udp_chksum = False, vxlan_vni = VNET_VNI, - vxlan_flags = 0, + vxlan_flags = 0x8, inner_frame = inner_exp_pkt) - vxlan_exp_pkt['IP'].chksum = 0 print("\nSending outbound packet...\n\n", vxlan_pkt.__repr__()) send_packet(dataplane, 0, vxlan_pkt) diff --git a/test/test-cases/scale/saic/test_sai_vnet_route_bidirectional.py b/test/test-cases/scale/saic/test_sai_vnet_route_bidirectional.py index eb81f43ac..5c31843a2 100644 --- a/test/test-cases/scale/saic/test_sai_vnet_route_bidirectional.py +++ b/test/test-cases/scale/saic/test_sai_vnet_route_bidirectional.py @@ -77,10 +77,8 @@ def test_vnet_route_packet_bidirectional_forwarding_with_route_match(self, dpu, udp_sport = 0, with_udp_chksum = False, vxlan_vni = 100, - vxlan_flags = 0, + vxlan_flags = 0x8, inner_frame = inner_exp_pkt_one) - vxlan_exp_pkt_one['IP'].chksum = 0 - # Send packet two inner_pkt_two = simple_udp_packet(eth_dst = "00:00:00:09:03:14", eth_src = "00:0a:04:06:06:06", @@ -107,9 +105,8 @@ def test_vnet_route_packet_bidirectional_forwarding_with_route_match(self, dpu, udp_sport = 0, with_udp_chksum = False, vxlan_vni = 100, - vxlan_flags = 0, + vxlan_flags = 0x8, inner_frame = inner_exp_pkt_two) - vxlan_exp_pkt_two['IP'].chksum = 0 # Send packets from both ports send_packet(dataplane, 0, vxlan_pkt_one, 10) @@ -147,10 +144,8 @@ def test_vnet_route_packet_bidirectional_forwarding_with_route_match(self, dpu, udp_sport = 0, with_udp_chksum = False, vxlan_vni = 100, - vxlan_flags = 0, + vxlan_flags = 0x8, inner_frame = inner_exp_pkt_one) - vxlan_exp_pkt_one['IP'].chksum = 0 - # Send packet two inner_pkt_two = simple_udp_packet(eth_dst = "00:00:00:09:03:14", eth_src = "00:0a:04:06:06:06", @@ -177,10 +172,8 @@ def test_vnet_route_packet_bidirectional_forwarding_with_route_match(self, dpu, udp_sport = 0, with_udp_chksum = False, vxlan_vni = 100, - vxlan_flags = 0, + vxlan_flags = 0x8, inner_frame = inner_exp_pkt_two) - vxlan_exp_pkt_two['IP'].chksum = 0 - # Send packets from both ports send_packet(dataplane, 0, vxlan_pkt_one, 10) time.sleep(0.5) diff --git a/test/test-cases/scale/saic/test_sai_vnet_route_unidirectional.py b/test/test-cases/scale/saic/test_sai_vnet_route_unidirectional.py index f4407abcb..fd5d50bc2 100644 --- a/test/test-cases/scale/saic/test_sai_vnet_route_unidirectional.py +++ b/test/test-cases/scale/saic/test_sai_vnet_route_unidirectional.py @@ -197,10 +197,8 @@ def test_vnet_route_packet_unidirectional_forwarding_with_route_match(self, dpu, udp_sport = 0, with_udp_chksum = False, vxlan_vni = VNET_VNI, - vxlan_flags = 0, + vxlan_flags = 0x8, inner_frame = inner_exp_pkt) - vxlan_exp_pkt['IP'].chksum = 0 - # Send packets from port 0 send_packet(dataplane, 0, vxlan_pkt, 10) time.sleep(0.5) diff --git a/test/test-cases/scale/saic/vnet_inbound_setup_commands.json b/test/test-cases/scale/saic/vnet_inbound_setup_commands.json index 98659ddba..38695fa81 100644 --- a/test/test-cases/scale/saic/vnet_inbound_setup_commands.json +++ b/test/test-cases/scale/saic/vnet_inbound_setup_commands.json @@ -156,7 +156,7 @@ }, "attributes": [ "SAI_INBOUND_ROUTING_ENTRY_ATTR_ACTION", - "SAI_INBOUND_ROUTING_ENTRY_ACTION_VXLAN_DECAP_PA_VALIDATE", + "SAI_INBOUND_ROUTING_ENTRY_ACTION_TUNNEL_DECAP_PA_VALIDATE", "SAI_INBOUND_ROUTING_ENTRY_ATTR_SRC_VNET_ID", "$vnet_1" ] From e5b729187c0be861657ca358f5bb9df27c5fe18e Mon Sep 17 00:00:00 2001 From: Ashutosh Agrawal Date: Wed, 13 Mar 2024 09:13:43 -0700 Subject: [PATCH 13/32] Fixed typo (#536) --- dash-pipeline/bmv2/dash_tunnel.p4 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dash-pipeline/bmv2/dash_tunnel.p4 b/dash-pipeline/bmv2/dash_tunnel.p4 index 9ba8df82c..f486a399e 100644 --- a/dash-pipeline/bmv2/dash_tunnel.p4 +++ b/dash-pipeline/bmv2/dash_tunnel.p4 @@ -240,7 +240,7 @@ PUSH_NVGRE_TUNNEL_DEF(u1, u0) } \ } else if (dash_encapsulation == dash_encapsulation_t.NVGRE) { \ if (meta.tunnel_pointer == 0) { \ - push_vxlan_tunnel_u0(hdr, \ + push_nvgre_tunnel_u0(hdr, \ overlay_dmac, \ underlay_dmac, \ underlay_smac, \ @@ -248,7 +248,7 @@ PUSH_NVGRE_TUNNEL_DEF(u1, u0) underlay_sip, \ tunnel_key); \ } else if (meta.tunnel_pointer == 1) { \ - push_vxlan_tunnel_u1(hdr, \ + push_nvgre_tunnel_u1(hdr, \ overlay_dmac, \ underlay_dmac, \ underlay_smac, \ From 924dde93e11678fdbfe758e351466aeded247474 Mon Sep 17 00:00:00 2001 From: Riff Date: Wed, 13 Mar 2024 09:23:30 -0700 Subject: [PATCH 14/32] Remove encap data original overlay IP and reuse the existing fields. (#529) --- dash-pipeline/bmv2/dash_conntrack.p4 | 17 ++++++++++------- dash-pipeline/bmv2/dash_inbound.p4 | 9 ++++----- dash-pipeline/bmv2/dash_metadata.p4 | 2 -- dash-pipeline/bmv2/dash_routing_types.p4 | 7 ++----- 4 files changed, 16 insertions(+), 19 deletions(-) diff --git a/dash-pipeline/bmv2/dash_conntrack.p4 b/dash-pipeline/bmv2/dash_conntrack.p4 index 101018af9..d4e1cb582 100644 --- a/dash-pipeline/bmv2/dash_conntrack.p4 +++ b/dash-pipeline/bmv2/dash_conntrack.p4 @@ -48,19 +48,22 @@ control ConntrackIn(inout headers_t hdr, } restart_expire_timer(); // reset expiration timer for entry meta.conntrack_data.allow_in = true; - meta.encap_data.original_overlay_sip = original_overlay_sip; - meta.encap_data.original_overlay_dip = original_overlay_dip; + meta.overlay_data.is_ipv6 = false; + meta.overlay_data.sip = (IPv4ORv6Address)original_overlay_sip; + meta.overlay_data.dip = (IPv4ORv6Address)original_overlay_dip; } action conntrackIn_miss() { // TODO: Should this be ((hdr.tcp.flags & 0x2) != 0) instead? if (hdr.customer_tcp.flags == 0x2 /* SYN */) { if (meta.direction == dash_direction_t.OUTBOUND) { - // New PNA Extern - add_entry("conntrackIn_allow", - {meta.encap_data.original_overlay_sip, meta.encap_data.original_overlay_dip}, - EXPIRE_TIME_PROFILE_LONG); - //adding failure to be eventually handled + if (meta.routing_actions & dash_routing_actions_t.NAT46 != 0) { + // New PNA Extern + add_entry("conntrackIn_allow", + {(IPv4Address)meta.src_ip_addr, (IPv4Address)meta.dst_ip_addr}, + EXPIRE_TIME_PROFILE_LONG); + } + //adding failure to be eventually handled } } } diff --git a/dash-pipeline/bmv2/dash_inbound.p4 b/dash-pipeline/bmv2/dash_inbound.p4 index d219de5ef..6e8de6939 100644 --- a/dash-pipeline/bmv2/dash_inbound.p4 +++ b/dash-pipeline/bmv2/dash_inbound.p4 @@ -4,6 +4,7 @@ #include "dash_headers.p4" #include "dash_service_tunnel.p4" #include "dash_acl.p4" +#include "routing_actions/routing_actions.p4" #include "dash_conntrack.p4" control inbound(inout headers_t hdr, @@ -11,15 +12,13 @@ control inbound(inout headers_t hdr, { apply { #ifdef STATEFUL_P4 - ConntrackIn.apply(0); + ConntrackIn.apply(0); #endif /* STATEFUL_P4 */ #ifdef PNA_CONNTRACK ConntrackIn.apply(hdr, meta); - if (meta.encap_data.original_overlay_sip != 0) { - service_tunnel_decode(hdr, - meta.encap_data.original_overlay_sip, - meta.encap_data.original_overlay_dip); + if ((IPv4Address)meta.overlay_data.sip != 0) { + do_action_nat64.apply(hdr, meta); } #endif // PNA_CONNTRACK diff --git a/dash-pipeline/bmv2/dash_metadata.p4 b/dash-pipeline/bmv2/dash_metadata.p4 index 900ab79bf..49b1080cb 100644 --- a/dash-pipeline/bmv2/dash_metadata.p4 +++ b/dash-pipeline/bmv2/dash_metadata.p4 @@ -63,8 +63,6 @@ struct encap_data_t { EthernetAddress underlay_smac; EthernetAddress underlay_dmac; dash_encapsulation_t dash_encapsulation; - IPv4Address original_overlay_sip; - IPv4Address original_overlay_dip; } struct overlay_rewrite_data_t { diff --git a/dash-pipeline/bmv2/dash_routing_types.p4 b/dash-pipeline/bmv2/dash_routing_types.p4 index 1531fa916..ab31d5d84 100644 --- a/dash-pipeline/bmv2/dash_routing_types.p4 +++ b/dash-pipeline/bmv2/dash_routing_types.p4 @@ -107,9 +107,6 @@ action route_service_tunnel( 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; - push_action_nat46(hdr = hdr, meta = meta, sip = overlay_sip, @@ -124,8 +121,8 @@ action route_service_tunnel( meta = meta, encap = dash_encapsulation, vni = tunnel_key, - underlay_sip = underlay_sip == 0 ? meta.encap_data.original_overlay_sip : (IPv4Address)underlay_sip, - underlay_dip = underlay_dip == 0 ? meta.encap_data.original_overlay_dip : (IPv4Address)underlay_dip, + underlay_sip = underlay_sip == 0 ? hdr.u0_ipv4.src_addr : (IPv4Address)underlay_sip, + underlay_dip = underlay_dip == 0 ? hdr.u0_ipv4.dst_addr : (IPv4Address)underlay_dip, overlay_dmac = hdr.u0_ethernet.dst_addr); #endif From bf20715458c69a1f8869e579a7c84f1354eeccfb Mon Sep 17 00:00:00 2001 From: Marian Pritsak Date: Wed, 13 Mar 2024 09:37:27 -0700 Subject: [PATCH 15/32] Add ability to provide @validonly tag (#535) * Add ability to provide @validonly tag * Update saiapi.h.j2 * Update saiapi.h.j2 * Update saiapi.h.j2 * Update dash_pipeline.p4 * Update dash_pipeline.p4 --- dash-pipeline/SAI/sai_api_gen.py | 2 ++ dash-pipeline/SAI/templates/saiapi.h.j2 | 3 +++ dash-pipeline/bmv2/dash_pipeline.p4 | 2 +- 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/dash-pipeline/SAI/sai_api_gen.py b/dash-pipeline/SAI/sai_api_gen.py index 20e5c4ec7..b0ab76e0e 100755 --- a/dash-pipeline/SAI/sai_api_gen.py +++ b/dash-pipeline/SAI/sai_api_gen.py @@ -484,6 +484,8 @@ def _parse_sai_table_attribute_annotation(self, p4rt_anno_list: Dict[str, Any]) self.skipattr = str(kv['value']['stringValue']) elif kv['key'] == 'match_type': self.match_type = str(kv['value']['stringValue']) + elif kv['key'] == 'validonly': + self.validonly = str(kv['value']['stringValue']) else: raise ValueError("Unknown attr annotation " + kv['key']) diff --git a/dash-pipeline/SAI/templates/saiapi.h.j2 b/dash-pipeline/SAI/templates/saiapi.h.j2 index 7f5443df7..e6e909577 100644 --- a/dash-pipeline/SAI/templates/saiapi.h.j2 +++ b/dash-pipeline/SAI/templates/saiapi.h.j2 @@ -183,6 +183,9 @@ typedef enum _sai_{{ table.name }}_attr_t {% endif %} {% endif %} +{% if sai_attr.validonly | length > 0 %} + * @validonly {{ sai_attr.validonly }} +{% endif %} {% if sai_attr.isresourcetype == 'true' %} * @isresourcetype true {% endif %} diff --git a/dash-pipeline/bmv2/dash_pipeline.p4 b/dash-pipeline/bmv2/dash_pipeline.p4 index da4d6f7a7..cff4e1baf 100644 --- a/dash-pipeline/bmv2/dash_pipeline.p4 +++ b/dash-pipeline/bmv2/dash_pipeline.p4 @@ -107,7 +107,7 @@ control dash_ingress( @SaiVal[type="sai_object_id_t"] bit<16> v4_meter_policy_id, @SaiVal[type="sai_object_id_t"] bit<16> v6_meter_policy_id, @SaiVal[type="sai_dash_tunnel_dscp_mode_t"] dash_tunnel_dscp_mode_t dash_tunnel_dscp_mode, - @SaiVal[type="sai_uint8_t"] bit<6> dscp, + @SaiVal[type="sai_uint8_t",validonly="SAI_ENI_ATTR_DASH_TUNNEL_DSCP_MODE == SAI_DASH_TUNNEL_DSCP_MODE_PIPE_MODEL"] bit<6> dscp, ACL_GROUPS_PARAM(inbound_v4), ACL_GROUPS_PARAM(inbound_v6), ACL_GROUPS_PARAM(outbound_v4), From a8c5dc913eb685d56e3a0b368690df664c11ea69 Mon Sep 17 00:00:00 2001 From: Marian Pritsak Date: Wed, 13 Mar 2024 09:38:25 -0700 Subject: [PATCH 16/32] Remove INVALID mode from DSCP modes (#533) * Remove INVALID mode from DSCP modes Preserve is the default, there is no condition under which INVALID can be set. * Update dash_pipeline.p4 --- dash-pipeline/bmv2/dash_metadata.p4 | 5 ++--- dash-pipeline/bmv2/dash_pipeline.p4 | 1 + 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/dash-pipeline/bmv2/dash_metadata.p4 b/dash-pipeline/bmv2/dash_metadata.p4 index 49b1080cb..8e6e7c11d 100644 --- a/dash-pipeline/bmv2/dash_metadata.p4 +++ b/dash-pipeline/bmv2/dash_metadata.p4 @@ -38,9 +38,8 @@ struct conntrack_data_t { } enum bit<16> dash_tunnel_dscp_mode_t { - INVALID = 0, - PRESERVE_MODEL = 1, - PIPE_MODEL = 2 + PRESERVE_MODEL = 0, + PIPE_MODEL = 1 } struct eni_data_t { diff --git a/dash-pipeline/bmv2/dash_pipeline.p4 b/dash-pipeline/bmv2/dash_pipeline.p4 index cff4e1baf..dc7405ed9 100644 --- a/dash-pipeline/bmv2/dash_pipeline.p4 +++ b/dash-pipeline/bmv2/dash_pipeline.p4 @@ -259,6 +259,7 @@ control dash_ingress( eni_lookup_stage.apply(hdr, meta); // Save the original DSCP value + meta.eni_data.dscp_mode = dash_tunnel_dscp_mode_t.PRESERVE_MODEL; meta.eni_data.dscp = (bit<6>)hdr.u0_ipv4.diffserv; if (meta.direction == dash_direction_t.OUTBOUND) { From 9eff6d74d75228ffebc167510a860bc51f1908d8 Mon Sep 17 00:00:00 2001 From: Ze Gan Date: Fri, 22 Mar 2024 09:36:54 +0800 Subject: [PATCH 17/32] misc: Fix compiling issue in local environment (#538) Disable the unused-result warning and add the string header to the target file. Signed-off-by: Ze Gan --- dash-pipeline/SAI/src/Makefile | 1 + dash-pipeline/SAI/src/objectidmanager.h | 1 + 2 files changed, 2 insertions(+) diff --git a/dash-pipeline/SAI/src/Makefile b/dash-pipeline/SAI/src/Makefile index 5bcabb278..6216b6420 100644 --- a/dash-pipeline/SAI/src/Makefile +++ b/dash-pipeline/SAI/src/Makefile @@ -43,6 +43,7 @@ CXXFLAGS_COMMON+= -Wno-switch-default CXXFLAGS_COMMON+= -Wconversion CXXFLAGS_COMMON+= -Wno-psabi CXXFLAGS_COMMON+= -Wno-unused-label +CXXFLAGS_COMMON+= -Wno-unused-result # Sources from OCP SAI Repo: SAI_DIR=../SAI/meta/ diff --git a/dash-pipeline/SAI/src/objectidmanager.h b/dash-pipeline/SAI/src/objectidmanager.h index d824f6832..d28f001ab 100644 --- a/dash-pipeline/SAI/src/objectidmanager.h +++ b/dash-pipeline/SAI/src/objectidmanager.h @@ -7,6 +7,7 @@ extern "C" { #include #include +#include namespace dash { From cc281333e24ade258773ea843f669251a44d7c9a Mon Sep 17 00:00:00 2001 From: Ze Gan Date: Wed, 27 Mar 2024 01:57:39 +0800 Subject: [PATCH 18/32] [debian]: Add p4 pipeline json to debian package (#541) We want to install the libsai debian package into SONiC. The libsai with p4 pipeline configuration is one to one mapping. So this configuration should also be added to the package. Signed-off-by: Ze Gan --- dash-pipeline/SAI/debian/Makefile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/dash-pipeline/SAI/debian/Makefile b/dash-pipeline/SAI/debian/Makefile index 87ace1d3a..4d982f12e 100644 --- a/dash-pipeline/SAI/debian/Makefile +++ b/dash-pipeline/SAI/debian/Makefile @@ -16,6 +16,8 @@ libsai-dev_$(VERSION)_amd64.deb: ../SAI/inc/*.h ../SAI/experimental/*.h dpkg-deb --build --root-owner-group libsai-dev_$(VERSION)_amd64 libsai_$(VERSION)_amd64.deb: ../lib/libsai.so + mkdir -p -m 755 libsai_$(VERSION)_amd64/etc/dash + install -vCD ../../bmv2/dash_pipeline.bmv2/* libsai_$(VERSION)_amd64/etc/dash/ mkdir -p -m 755 libsai_$(VERSION)_amd64/usr/lib/x86_64-linux-gnu/ find -type d |xargs chmod go-w install -vCD ../lib/libsai.so libsai_$(VERSION)_amd64/usr/lib/x86_64-linux-gnu/libsai.so From 7d695909e449b21a3cb9f5c2e3e38206a0f6f996 Mon Sep 17 00:00:00 2001 From: Ashutosh Agrawal Date: Wed, 27 Mar 2024 16:23:07 -0700 Subject: [PATCH 19/32] Check for valid overlay dmac value before overwriting the field in header (#540) We found this issue while running one of the inbound routing PTF tests in saidashvnet.py. Most likely the bug was introduced during refactoring of tunnel encapsulation code. In case of inbound routing, overlay_dmac is not supposed to be modified. But, in inbound_routing.p4, when tunnel_encap action is called, the value of meta.overlay_data.dmac is zero and tunnel_encap action ends up incorrectly setting the overlay_dmac to zero. ` tunnel_encap(hdr, meta, meta.overlay_data.dmac, meta.encap_data.underlay_dmac, meta.encap_data.underlay_smac, meta.encap_data.underlay_dip, meta.encap_data.underlay_sip, dash_encapsulation_t.VXLAN, meta.encap_data.vni); ` This fix will check for a non-zero overlay_dmac value before overwriting the customer dmac field in the packet header. --- dash-pipeline/bmv2/dash_tunnel.p4 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dash-pipeline/bmv2/dash_tunnel.p4 b/dash-pipeline/bmv2/dash_tunnel.p4 index f486a399e..a83b05ae7 100644 --- a/dash-pipeline/bmv2/dash_tunnel.p4 +++ b/dash-pipeline/bmv2/dash_tunnel.p4 @@ -12,7 +12,7 @@ action push_vxlan_tunnel_ ## underlay_id ## (inout headers_t hdr, \ in IPv4Address underlay_dip, \ in IPv4Address underlay_sip, \ in bit<24> tunnel_key) { \ - hdr. ## overlay_id ## _ethernet.dst_addr = overlay_dmac; \ + hdr. ## overlay_id ## _ethernet.dst_addr = (overlay_dmac == 0) ? hdr. ## overlay_id ## _ethernet.dst_addr : overlay_dmac; \ hdr. ## underlay_id ## _ethernet.setValid(); \ hdr. ## underlay_id ## _ethernet.dst_addr = underlay_dmac; \ hdr. ## underlay_id ## _ethernet.src_addr = underlay_smac; \ From f2200ff4421b3f470ab33af4d780836d640b42f2 Mon Sep 17 00:00:00 2001 From: Riff Date: Mon, 1 Apr 2024 13:32:41 -0700 Subject: [PATCH 20/32] [sai] Update SAI to latest master with DSCP change. (#539) --- dash-pipeline/SAI/SAI | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dash-pipeline/SAI/SAI b/dash-pipeline/SAI/SAI index 6198db544..3fe490d83 160000 --- a/dash-pipeline/SAI/SAI +++ b/dash-pipeline/SAI/SAI @@ -1 +1 @@ -Subproject commit 6198db544f1d03163c8f8cac1fbf607ce81b4149 +Subproject commit 3fe490d836be6ed1d7c4a8763d5e33053f9e957a From 31b94c80b9a3ddbbae74c8cedba7d45be24b0d8d Mon Sep 17 00:00:00 2001 From: Riff Date: Thu, 4 Apr 2024 13:09:01 -0700 Subject: [PATCH 21/32] Add DASH HA session API design. (#532) This change is made to add HA session API HLD and P4 changes for SAI API generation. To describe how the HA session API works, the HLD in this change contains: - The key fundamental components that used to form the HA set topology and their SAI API design. - How we could implement HA in DASH behavior model and how each components works with each other. - The life of the packet for inline flow sync. - The SAI API call sequence of several typical HA related work flows. The change also contains the P4 code that generates the SAI APIs. --- .wordlist.txt | 6 + dash-pipeline/Makefile | 2 +- dash-pipeline/bmv2/dash_arch_specific.p4 | 8 + dash-pipeline/bmv2/dash_metadata.p4 | 72 ++- dash-pipeline/bmv2/dash_pipeline.p4 | 31 +- dash-pipeline/bmv2/stages/ha.p4 | 133 ++++ .../tests/libsai/vnet_out/vnet_out.cpp | 4 + .../pytest/vnet/test_saithrift_vnet.py | 1 + documentation/high-avail/ha-api-hld.md | 609 ++++++++++++++++++ .../high-avail/images/ha-bm-packet-flow.svg | 4 + .../images/ha-components-complex.svg | 4 + .../images/ha-components-dpu-level-ha.svg | 4 + .../images/ha-components-eni-level-ha.svg | 4 + .../functional/ptf/sai_dash_utils.py | 1 + test/test-cases/functional/ptf/saidashacl.py | 1 + .../functional/ptf/saidashvnet_sanity.py | 1 + .../saic/config_bidir_setup_commands.py | 3 + .../saic/config_inbound_setup_commands.py | 4 + .../saic/config_outbound_setup_commands.json | 2 + .../saic/sai-api/test_sai_api_vnet_eni.py | 2 + .../sai-api/test_sai_api_vnet_in_route.py | 2 + .../sai-api/test_sai_api_vnet_out_route.py | 2 + ..._outbound_small_scale_config_via_dpugen.py | 2 +- ..._small_scale_config_via_dpugen_create.json | 4 + .../saic/test_sai_vnet_outbound_scale.py | 2 +- .../saic/vnet_inbound_setup_commands.json | 2 + .../vnet_outbound_setup_commands_scale.json | 2 + .../vnet_outbound_setup_commands_simple.json | 1 + ...et_route_setup_commands_bidirectional.json | 8 + ...t_route_setup_commands_unidirectional.json | 2 + 30 files changed, 913 insertions(+), 10 deletions(-) create mode 100644 dash-pipeline/bmv2/stages/ha.p4 create mode 100644 documentation/high-avail/ha-api-hld.md create mode 100644 documentation/high-avail/images/ha-bm-packet-flow.svg create mode 100644 documentation/high-avail/images/ha-components-complex.svg create mode 100644 documentation/high-avail/images/ha-components-dpu-level-ha.svg create mode 100644 documentation/high-avail/images/ha-components-eni-level-ha.svg diff --git a/.wordlist.txt b/.wordlist.txt index 1b0b6257f..463b1a777 100644 --- a/.wordlist.txt +++ b/.wordlist.txt @@ -6,6 +6,7 @@ Accton ACK Ack ack +ack'ed acl ACL ACLs @@ -304,6 +305,7 @@ IxLoad ixload IxNetwork IxNetworkWeb +Jiang Jinja jitter journaled @@ -372,6 +374,7 @@ NonSynStateful NorthBound Novus NPL +NPU NPUS NSG NSGs @@ -471,11 +474,13 @@ README READMEs README's reconvergence +RECV RedirectRuleResimulatedUf redis renderer repo repos +REQ resimulated resimulation responder @@ -534,6 +539,7 @@ SmartAppliances SmartNIC SmartNic SmartNICs +SmartSwitch SmartSwitches snappi SNAT diff --git a/dash-pipeline/Makefile b/dash-pipeline/Makefile index 5929fc840..43bde771d 100644 --- a/dash-pipeline/Makefile +++ b/dash-pipeline/Makefile @@ -92,7 +92,7 @@ sai-submodule: # P4 Source code compile TARGETS ###################################### -P4_SRC=$(wildcard bmv2/*.p4) +P4_SRC=$(wildcard bmv2/**/*.p4) P4_MAIN=bmv2/dash_pipeline.p4 P4_OUTDIR=bmv2/dash_pipeline.bmv2 P4_ARTIFACTS=$(P4_OUTDIR)/dash_pipeline.json $(P4_OUTDIR)/dash_pipeline_p4rt.txt diff --git a/dash-pipeline/bmv2/dash_arch_specific.p4 b/dash-pipeline/bmv2/dash_arch_specific.p4 index 17b8c60e8..978a6ef07 100644 --- a/dash-pipeline/bmv2/dash_arch_specific.p4 +++ b/dash-pipeline/bmv2/dash_arch_specific.p4 @@ -82,4 +82,12 @@ #endif // TARGET_DPDK_PNA +// +// Utility macros +// + +// The second macro will have the value of x expanded before stringification. +#define PP_STR_RAW(x) #x +#define PP_STR(x) PP_STR_RAW(x) + #endif // __DASH_TARGET_SPECIFIC__ diff --git a/dash-pipeline/bmv2/dash_metadata.p4 b/dash-pipeline/bmv2/dash_metadata.p4 index 8e6e7c11d..005068e1e 100644 --- a/dash-pipeline/bmv2/dash_metadata.p4 +++ b/dash-pipeline/bmv2/dash_metadata.p4 @@ -3,6 +3,9 @@ #include "dash_headers.p4" +#define MAX_ENI 64 +#define MAX_HA_SET 1 + enum bit<32> dash_routing_actions_t { NONE = 0, STATIC_ENCAP = (1 << 0), @@ -14,7 +17,21 @@ enum bit<16> dash_direction_t { INVALID = 0, OUTBOUND = 1, INBOUND = 2 -} +}; + +enum bit<8> dash_packet_source_t { + EXTERNAL = 0, // Packets from external sources. + DPAPP = 1, // Packets from data plane app. + PEER = 2 // Packets from the paired DPU. +}; + +enum bit<8> dash_packet_type_t { + REGULAR = 0, // Regular packets from external sources. + FLOW_SYNC_REQ = 1, // Flow sync request packet. + FLOW_SYNC_ACK = 2, // Flow sync ack packet. + DP_PROBE_REQ = 3, // Data plane probe packet. + DP_PROBE_ACK = 4 // Data plane probe ack packet. +}; // Pipeline stages: enum bit<16> dash_pipeline_stage_t { @@ -30,7 +47,7 @@ enum bit<16> dash_pipeline_stage_t { // Common stages ROUTING_ACTION_APPLY = 300 -} +}; struct conntrack_data_t { bool allow_in; @@ -73,7 +90,55 @@ struct overlay_rewrite_data_t { IPv6Address dip_mask; } +// HA roles +enum bit<8> dash_ha_role_t { + DEAD = 0, + ACTIVE = 1, + STANDBY = 2, + STANDALONE = 3, + SWITCHING_TO_ACTIVE = 4 +}; + +// Flow sync state +enum bit<8> dash_ha_flow_sync_state_t { + FLOW_MISS = 0, // Flow not created yet + FLOW_CREATED = 1, // Flow is created but not synched or waiting for ack + FLOW_SYNCED = 2, // Flow has been synched to its peer + FLOW_PENDING_DELETE = 3, // Flow is pending deletion, waiting for ack + FLOW_PENDING_RESIMULATION = 4 // Flow is marked as pending resimulation +}; + +// HA flow sync operations +enum bit<8> dash_ha_flow_sync_op_t { + FLOW_CREATE = 0, // New flow creation. + FLOW_UPDATE = 1, // Flow resimulation or any other reason causing existing flow to be updated. + FLOW_DELETE = 2 // Flow deletion. +}; + +struct ha_data_t { + // HA scope settings + bit<16> ha_scope_id; + bit<16> ha_set_id; + dash_ha_role_t ha_role; + + // HA set settings + bit<1> local_ip_is_v6; + IPv4ORv6Address local_ip; + bit<1> peer_ip_is_v6; + IPv4ORv6Address peer_ip; + bit<16> dp_channel_dst_port; + bit<16> dp_channel_src_port_min; + bit<16> dp_channel_src_port_max; + + // HA packet/flow state + dash_ha_flow_sync_state_t flow_sync_state; +} + struct metadata_t { + // Packet type + dash_packet_source_t packet_source; // TODO: Parse packet source in parser. + dash_packet_type_t packet_type; // TODO: Parse packet type in parser. + // Lookup context dash_direction_t direction; EthernetAddress eni_addr; @@ -109,6 +174,9 @@ struct metadata_t { bool is_fast_path_icmp_flow_redirection_packet; bit<1> fast_path_icmp_flow_redirection_disabled; + // HA + ha_data_t ha; + // Stage transition control dash_pipeline_stage_t target_stage; diff --git a/dash-pipeline/bmv2/dash_pipeline.p4 b/dash-pipeline/bmv2/dash_pipeline.p4 index dc7405ed9..2961f3d5c 100644 --- a/dash-pipeline/bmv2/dash_pipeline.p4 +++ b/dash-pipeline/bmv2/dash_pipeline.p4 @@ -10,12 +10,11 @@ #include "dash_conntrack.p4" #include "stages/direction_lookup.p4" #include "stages/eni_lookup.p4" +#include "stages/ha.p4" #include "stages/routing_action_apply.p4" #include "stages/metering_update.p4" #include "underlay.p4" -#define MAX_ENI 64 - control dash_ingress( inout headers_t hdr , inout metadata_t meta @@ -92,12 +91,19 @@ control dash_ingress( meta.stage4_dash_acl_group_id = ## prefix ##_stage4_dash_acl_group_id; \ meta.stage5_dash_acl_group_id = ## prefix ##_stage5_dash_acl_group_id; - DEFINE_COUNTER(eni_lb_fast_path_icmp_in_counter, MAX_ENI, name="lb_fast_path_icmp_in", attr_type="stats", action_names="set_eni_attrs") + DEFINE_COUNTER(eni_rx_counter, MAX_ENI, name="rx", attr_type="stats", action_names="set_eni_attrs", order=0) + DEFINE_COUNTER(eni_tx_counter, MAX_ENI, name="tx", attr_type="stats", action_names="set_eni_attrs", order=0) + DEFINE_COUNTER(eni_outbound_rx_counter, MAX_ENI, name="outbound_rx", attr_type="stats", action_names="set_eni_attrs", order=0) + DEFINE_COUNTER(eni_outbound_tx_counter, MAX_ENI, name="outbound_tx", attr_type="stats", action_names="set_eni_attrs", order=0) + DEFINE_COUNTER(eni_inbound_rx_counter, MAX_ENI, name="inbound_rx", attr_type="stats", action_names="set_eni_attrs", order=0) + DEFINE_COUNTER(eni_inbound_tx_counter, MAX_ENI, name="inbound_tx", attr_type="stats", action_names="set_eni_attrs", order=0) + DEFINE_COUNTER(eni_lb_fast_path_icmp_in_counter, MAX_ENI, name="lb_fast_path_icmp_in", attr_type="stats", action_names="set_eni_attrs", order=0) action set_eni_attrs(bit<32> cps, bit<32> pps, bit<32> flows, bit<1> admin_state, + @SaiVal[type="sai_object_id_t"] bit<16> ha_scope_id, @SaiVal[type="sai_ip_address_t"] IPv4Address vm_underlay_dip, @SaiVal[type="sai_uint32_t"] bit<24> vm_vni, @SaiVal[type="sai_object_id_t"] bit<16> vnet_id, @@ -144,7 +150,8 @@ control dash_ingress( } meta.meter_policy_id = v4_meter_policy_id; } - + + meta.ha.ha_scope_id = ha_scope_id; meta.fast_path_icmp_flow_redirection_disabled = disable_fast_path_icmp_flow_redirection; } @@ -302,17 +309,23 @@ control dash_ingress( if (meta.eni_data.admin_state == 0) { deny(); } - + + UPDATE_COUNTER(eni_rx_counter, meta.eni_id); if (meta.is_fast_path_icmp_flow_redirection_packet) { UPDATE_COUNTER(eni_lb_fast_path_icmp_in_counter, meta.eni_id); } + ha_stage.apply(hdr, meta); + acl_group.apply(); if (meta.direction == dash_direction_t.OUTBOUND) { + UPDATE_COUNTER(eni_outbound_rx_counter, meta.eni_id); + meta.target_stage = dash_pipeline_stage_t.OUTBOUND_ROUTING; outbound.apply(hdr, meta); } else if (meta.direction == dash_direction_t.INBOUND) { + UPDATE_COUNTER(eni_inbound_rx_counter, meta.eni_id); inbound.apply(hdr, meta); } @@ -340,6 +353,14 @@ control dash_ingress( if (meta.dropped) { drop_action(); + } else { + UPDATE_COUNTER(eni_tx_counter, meta.eni_id); + + if (meta.direction == dash_direction_t.OUTBOUND) { + UPDATE_COUNTER(eni_outbound_tx_counter, meta.eni_id); + } else if (meta.direction == dash_direction_t.INBOUND) { + UPDATE_COUNTER(eni_inbound_tx_counter, meta.eni_id); + } } } } diff --git a/dash-pipeline/bmv2/stages/ha.p4 b/dash-pipeline/bmv2/stages/ha.p4 new file mode 100644 index 000000000..dcfeb901b --- /dev/null +++ b/dash-pipeline/bmv2/stages/ha.p4 @@ -0,0 +1,133 @@ +#ifndef _DASH_STAGE_HA_P4_ +#define _DASH_STAGE_HA_P4_ + +control ha_stage(inout headers_t hdr, + inout metadata_t meta) +{ + // + // ENI-level flow operation counters: + // + DEFINE_HIT_COUNTER(flow_created_counter, MAX_ENI, name="flow_created", attr_type="stats", action_names="set_eni_attrs", order=1) + DEFINE_HIT_COUNTER(flow_create_failed_counter, MAX_ENI, name="flow_create_failed", attr_type="stats", action_names="set_eni_attrs", order=1) + DEFINE_HIT_COUNTER(flow_updated_counter, MAX_ENI, name="flow_updated", attr_type="stats", action_names="set_eni_attrs", order=1) + DEFINE_HIT_COUNTER(flow_update_failed_counter, MAX_ENI, name="flow_update_failed", attr_type="stats", action_names="set_eni_attrs", order=1) + DEFINE_HIT_COUNTER(flow_deleted_counter, MAX_ENI, name="flow_deleted", attr_type="stats", action_names="set_eni_attrs", order=1) + DEFINE_HIT_COUNTER(flow_delete_failed_counter, MAX_ENI, name="flow_delete_failed", attr_type="stats", action_names="set_eni_attrs", order=1) + DEFINE_HIT_COUNTER(flow_aged_counter, MAX_ENI, name="flow_aged", attr_type="stats", action_names="set_eni_attrs", order=1) + + // + // ENI-level flow sync packet counters: + // + DEFINE_COUNTER(inline_sync_packet_rx_counter, MAX_ENI, name="inline_sync_packet_rx", attr_type="stats", action_names="set_eni_attrs", order=2) + DEFINE_COUNTER(inline_sync_packet_tx_counter, MAX_ENI, name="inline_sync_packet_tx", attr_type="stats", action_names="set_eni_attrs", order=2) + DEFINE_COUNTER(timed_sync_packet_rx_counter, MAX_ENI, name="timed_sync_packet_rx", attr_type="stats", action_names="set_eni_attrs", order=2) + DEFINE_COUNTER(timed_sync_packet_tx_counter, MAX_ENI, name="timed_sync_packet_tx", attr_type="stats", action_names="set_eni_attrs", order=2) + + // + // ENI-level flow sync request counters: + // - Depends on implementations, the flow sync request could be batched, hence they need to tracked separately. + // - The counters are defined as combination of following things: + // - 3 flow sync operations: create, update, delete. + // - 2 ways of sync: Inline sync and timed sync. + // - Request result: succeeded, failed (unexpected) and ignored (expected and ok to ignore, e.g., more packets arrives before flow sync is acked). + // + #define DEFINE_ENI_FLOW_SYNC_COUNTERS(counter_name) \ + DEFINE_HIT_COUNTER(inline_ ## counter_name ## _req_sent_counter, MAX_ENI, name=PP_STR(inline_ ## counter_name ## _req_sent), attr_type="stats", action_names="set_eni_attrs", order=2) \ + DEFINE_HIT_COUNTER(inline_ ## counter_name ## _req_recv_counter, MAX_ENI, name=PP_STR(inline_ ## counter_name ## _req_recv), attr_type="stats", action_names="set_eni_attrs", order=2) \ + DEFINE_HIT_COUNTER(inline_ ## counter_name ## _req_failed_counter, MAX_ENI, name=PP_STR(inline_ ## counter_name ## _req_failed), attr_type="stats", action_names="set_eni_attrs", order=2) \ + DEFINE_HIT_COUNTER(inline_ ## counter_name ## _req_ignored_counter, MAX_ENI, name=PP_STR(inline_ ## counter_name ## _req_failed), attr_type="stats", action_names="set_eni_attrs", order=2) \ + DEFINE_HIT_COUNTER(inline_ ## counter_name ## _ack_recv_counter, MAX_ENI, name=PP_STR(inline_ ## counter_name ## _ack_recv), attr_type="stats", action_names="set_eni_attrs", order=2) \ + DEFINE_HIT_COUNTER(inline_ ## counter_name ## _ack_failed_counter, MAX_ENI, name=PP_STR(inline_ ## counter_name ## _ack_failed_recv), attr_type="stats", action_names="set_eni_attrs", order=2) \ + DEFINE_HIT_COUNTER(inline_ ## counter_name ## _ack_ignored_counter, MAX_ENI, name=PP_STR(inline_ ## counter_name ## _ack_ignored_recv), attr_type="stats", action_names="set_eni_attrs", order=2) \ + \ + DEFINE_HIT_COUNTER(timed_ ## counter_name ## _req_sent_counter, MAX_ENI, name=PP_STR(timed_ ## counter_name ## _req_sent), attr_type="stats", action_names="set_eni_attrs", order=2) \ + DEFINE_HIT_COUNTER(timed_ ## counter_name ## _req_recv_counter, MAX_ENI, name=PP_STR(timed_ ## counter_name ## _req_recv), attr_type="stats", action_names="set_eni_attrs", order=2) \ + DEFINE_HIT_COUNTER(timed_ ## counter_name ## _req_failed_counter, MAX_ENI, name=PP_STR(timed_ ## counter_name ## _req_failed), attr_type="stats", action_names="set_eni_attrs", order=2) \ + DEFINE_HIT_COUNTER(timed_ ## counter_name ## _req_ignored_counter, MAX_ENI, name=PP_STR(timed_ ## counter_name ## _req_failed), attr_type="stats", action_names="set_eni_attrs", order=2) \ + DEFINE_HIT_COUNTER(timed_ ## counter_name ## _ack_recv_counter, MAX_ENI, name=PP_STR(timed_ ## counter_name ## _ack_recv), attr_type="stats", action_names="set_eni_attrs", order=2) \ + DEFINE_HIT_COUNTER(timed_ ## counter_name ## _ack_failed_counter, MAX_ENI, name=PP_STR(timed_ ## counter_name ## _ack_failed_recv), attr_type="stats", action_names="set_eni_attrs", order=2) \ + DEFINE_HIT_COUNTER(timed_ ## counter_name ## _ack_ignored_counter, MAX_ENI, name=PP_STR(timed_ ## counter_name ## _ack_ignored_recv), attr_type="stats", action_names="set_eni_attrs", order=2) + + DEFINE_ENI_FLOW_SYNC_COUNTERS(flow_create) + DEFINE_ENI_FLOW_SYNC_COUNTERS(flow_update) + DEFINE_ENI_FLOW_SYNC_COUNTERS(flow_delete) + + // + // HA scope: + // + action set_ha_scope_attr( + @SalVal[type="sai_object_id_t"] bit<16> ha_set_id, + @SaiVal[type="sai_dash_ha_role_t"] dash_ha_role_t dash_ha_role, + @SaiVal[isreadonly="true"] bit<32> flow_version + ) { + meta.ha.ha_set_id = ha_set_id; + meta.ha.ha_role = dash_ha_role; + } + + @SaiTable[api = "dash_ha", order=1, isobject="true"] + table ha_scope { + key = { + meta.ha.ha_scope_id : exact; + } + actions = { + set_ha_scope_attr; + } + } + + // + // HA set: + // + DEFINE_COUNTER(dp_probe_req_rx, MAX_HA_SET, name="dp_probe_req_rx", attr_type="stats", action_names="set_ha_set_attr") + DEFINE_COUNTER(dp_probe_req_tx, MAX_HA_SET, name="dp_probe_req_tx", attr_type="stats", action_names="set_ha_set_attr") + DEFINE_COUNTER(dp_probe_ack_rx, MAX_HA_SET, name="dp_probe_ack_rx", attr_type="stats", action_names="set_ha_set_attr") + DEFINE_COUNTER(dp_probe_ack_tx, MAX_HA_SET, name="dp_probe_ack_tx", attr_type="stats", action_names="set_ha_set_attr") + DEFINE_HIT_COUNTER(dp_probe_failed, MAX_HA_SET, name="dp_probe_failed", attr_type="stats", action_names="set_ha_set_attr") + + action set_ha_set_attr( + bit<1> local_ip_is_v6, + @SaiVal[type="sai_ip_address_t"] IPv4ORv6Address local_ip, + bit<1> peer_ip_is_v6, + @SaiVal[type="sai_ip_address_t"] IPv4ORv6Address peer_ip, + bit<16> dp_channel_dst_port, + bit<16> dp_channel_min_src_port, + bit<16> dp_channel_max_src_port, + bit<32> dp_channel_probe_interval_ms, + bit<32> dp_channel_probe_fail_threshold, + @SaiVal[isreadonly="true"] bit<1> dp_channel_is_alive + ) { + meta.ha.peer_ip_is_v6 = peer_ip_is_v6; + meta.ha.peer_ip = peer_ip; + + meta.ha.dp_channel_dst_port = dp_channel_dst_port; + meta.ha.dp_channel_src_port_min = dp_channel_min_src_port; + meta.ha.dp_channel_src_port_max = dp_channel_max_src_port; + } + + @SaiTable[api = "dash_ha", order=0, isobject="true"] + table ha_set { + key = { + meta.ha.ha_set_id : exact @SaiVal[type="sai_object_id_t"]; + } + actions = { + set_ha_set_attr; + } + } + + apply { + // If HA scope id is not set, then HA is not enabled. + if (meta.ha.ha_scope_id == 0) { + return; + } + ha_scope.apply(); + + // If HA set id is not set, then HA is not enabled. + if (meta.ha.ha_set_id == 0) { + return; + } + ha_set.apply(); + + // TODO: HA state machine handling. + } +} + +#endif /* _DASH_STAGE_HA_P4_ */ diff --git a/dash-pipeline/tests/libsai/vnet_out/vnet_out.cpp b/dash-pipeline/tests/libsai/vnet_out/vnet_out.cpp index d386c1db5..c032c32e5 100644 --- a/dash-pipeline/tests/libsai/vnet_out/vnet_out.cpp +++ b/dash-pipeline/tests/libsai/vnet_out/vnet_out.cpp @@ -126,6 +126,10 @@ int main(int argc, char **argv) attr.value.booldata = true; attrs.push_back(attr); + attr.id = SAI_ENI_ATTR_HA_SCOPE_ID; + attr.value.oid = SAI_NULL_OBJECT_ID; + attrs.push_back(attr); + attr.id = SAI_ENI_ATTR_VM_UNDERLAY_DIP; sai_ip_addr_t u_dip_addr = {.ip4 = 0x010310ac}; sai_ip_address_t u_dip = {.addr_family = SAI_IP_ADDR_FAMILY_IPV4, diff --git a/dash-pipeline/tests/saithrift/pytest/vnet/test_saithrift_vnet.py b/dash-pipeline/tests/saithrift/pytest/vnet/test_saithrift_vnet.py index ffdc26568..7a8552aaf 100644 --- a/dash-pipeline/tests/saithrift/pytest/vnet/test_saithrift_vnet.py +++ b/dash-pipeline/tests/saithrift/pytest/vnet/test_saithrift_vnet.py @@ -44,6 +44,7 @@ def test_sai_thrift_create_eni(saithrift_client): eni = sai_thrift_create_eni(saithrift_client, cps=10000, pps=100000, flows=100000, admin_state=True, + ha_scope_id=0, vm_underlay_dip=vm_underlay_dip, vm_vni=9, vnet_id=vnet, diff --git a/documentation/high-avail/ha-api-hld.md b/documentation/high-avail/ha-api-hld.md new file mode 100644 index 000000000..043fff32b --- /dev/null +++ b/documentation/high-avail/ha-api-hld.md @@ -0,0 +1,609 @@ +# DASH High Availability API + +| Rev | Date | Author | Change Description | +| --- | ---- | ------ | ------------------ | +| 0.1 | 03/02/2024 | Riff Jiang | Initial version. | +| 0.2 | 03/15/2024 | Riff Jiang | Added HA set notification. | +| 0.3 | 03/21/2024 | Riff Jiang | Added capabilities for HA topology and stats. | +| 0.4 | 04/01/2024 | Riff Jiang | Added capabilities for HA owner, simplified capabilities for HA topology. | + +1. [1. Terminology](#1-terminology) +2. [2. Background](#2-background) +3. [3. Overview](#3-overview) +4. [4. SAI APIs](#4-sai-apis) + 1. [4.1. HA Set](#41-ha-set) + 2. [4.2. HA Scope](#42-ha-scope) + 3. [4.3. Flow table](#43-flow-table) + 4. [4.4. Flow](#44-flow) + 5. [4.5. ENI](#45-eni) + 6. [4.6. Event notifications](#46-event-notifications) + 1. [4.6.1. HA set event notifications](#461-ha-set-event-notifications) + 2. [4.6.2. HA scope event notifications](#462-ha-scope-event-notifications) + 7. [4.7. Counters](#47-counters) + 1. [4.7.1. HA set stats](#471-ha-set-stats) + 2. [4.7.2. ENI stats](#472-eni-stats) + 1. [4.7.2.1. ENI-level traffic counters](#4721-eni-level-traffic-counters) + 2. [4.7.2.2. ENI-level flow operation counters](#4722-eni-level-flow-operation-counters) + 3. [4.7.2.3. ENI-level flow sync packet counters](#4723-eni-level-flow-sync-packet-counters) + 4. [4.7.2.4. ENI-level flow sync operations counters](#4724-eni-level-flow-sync-operations-counters) + 8. [4.8. Capability](#48-capability) + 1. [4.8.1. Topology related capabilities](#481-topology-related-capabilities) + 2. [4.8.2. Stats related capabilities](#482-stats-related-capabilities) +5. [5. HA in DASH behavior model](#5-ha-in-dash-behavior-model) + 1. [5.1. HA stage](#51-ha-stage) + 2. [5.2. Packet type and flow operations](#52-packet-type-and-flow-operations) + 3. [5.3. Life of the packet](#53-life-of-the-packet) +6. [6. Workflows](#6-workflows) + 1. [6.1. ENI level HA](#61-eni-level-ha) + 1. [6.1.1. HA set and ENI creation](#611-ha-set-and-eni-creation) + 2. [6.1.2. Switchover](#612-switchover) + 3. [6.1.3. Unplanned failover](#613-unplanned-failover) + 4. [6.1.4. Recover from unplanned failover](#614-recover-from-unplanned-failover) + +## 1. Terminology + +| Term | Explanation | +| ---- | ----------- | +| HA | High Availability. | +| NPU | Network Processing Unit. | +| DPU | Data Processing Unit. | +| ENI | Elastic Network Interface. | +| VIP | Virtual IP address. | + +## 2. Background + +The DASH high availability APIs are a set of APIs to support flow HA feature for DASH. It follows the [SmartSwitch high availability design](https://github.com/sonic-net/SONiC/blob/master/doc/smart-switch/high-availability/smart-switch-ha-hld.md) and used to ensure the flow created on the active DPU can be correctly synchronized to the peered DPU. + +For how the network topology is setup and how flow HA works, such as lifetime management, inline sync, bulk sync, and packet format, please refer to the [SmartSwitch high availability design](https://github.com/sonic-net/SONiC/blob/master/doc/smart-switch/high-availability/smart-switch-ha-hld.md). In this doc, we will only focus on the design from SAI API perspective. + +## 3. Overview + +To support the [SmartSwitch HA workflows](https://github.com/sonic-net/SONiC/blob/master/doc/smart-switch/high-availability/smart-switch-ha-hld.md), from SAI perspective, there are a few key components involved: + +- **HA set**: It defines the peer DPU and data plane channel that used for inline flow sync. +- **HA scope**: It controls the failover scope, such as HA role, such as active, standby or standalone, and expected flow version for new flows. Depends on the HA role of the ENI, the packet will be processed differently to get the flow synched. +- **Flow table**: It is the container of all flow entries. It can be attached to all ENIs in a DPU or being attached to a single DPU, depends on at which level we like to provide the flow HA, i.e. HA scope. +- **Flow**: It is used to represent a network connection, which contains match conditions and packet transformations. In HA, each flow will have it own HA-related states, such flow version, flow sync state and etc. +- **ENI**: In ENI-level HA, each ENI will be connected to a HA scope. + +The components is designed to be conceptually simple and reusable, hence we can use these components to support different HA setup. For example, to support the current ENI-level HA design, these components can be put together as below: + +![](./images/ha-components-eni-level-ha.svg) + +If more complex scenario support is needed, we can reuse the same components to represent them easily. For example, here is the topology that can be used to represent DPU-level HA: + +![](./images/ha-components-dpu-level-ha.svg) + +Or, with even more complicated topology, such as each ENI owns 2 dedicated flow tables and a single DPU can pair with multiple DPUs: + +![](./images/ha-components-complex.svg) + +> Note: The graphs here is to show the flexibiilty of these concepts, but not require all the possible topology to be supported by the DASH providers. + +## 4. SAI APIs + +To illustrate how these concepts look, their SAI API design is shown as below. + +### 4.1. HA Set + +HA set is defined as a SAI object and contains the following SAI attributes: + +| Attribute name | Type | Description | +| -------------- | ---- | ----------- | +| SAI_HA_SET_ATTR_LOCAL_IP | `sai_ip_address_t` | The IP address of the local DPU. | +| SAI_HA_SET_ATTR_PEER_IP | `sai_ip_address_t` | The IP address of the peer DPU. | +| SAI_HA_SET_ATTR_DP_CHANNEL_DST_PORT | `sai_uint16_t` | The destination port of the data plane channel. | +| SAI_HA_SET_ATTR_DP_CHANNEL_SRC_PORT_MIN | `sai_uint16_t` | The minimum source port of the data plane channel. | +| SAI_HA_SET_ATTR_DP_CHANNEL_SRC_PORT_MAX | `sai_uint16_t` | The maximum source port of the data plane channel. | +| SAI_HA_SET_ATTR_DP_CHANNEL_PROBE_INTERVAL_MS | `sai_uint32_t` | The interval of the data plane channel probe. | +| SAI_HA_SET_ATTR_DP_CHANNEL_PROBE_FAIL_THRESHOLD | `sai_uint32_t` | The threshold of the data plane channel probe fail. | +| SAI_HA_SET_ATTR_DP_CHANNEL_IS_ALIVE | `bool` | (Read-only) Is data plane channel alive. | + +### 4.2. HA Scope + +HA scope is also defined as a SAI object and contains the following SAI attributes: + +| Attribute name | Type | Description | +| -------------- | ---- | ----------- | +| SAI_HA_SCOPE_ATTR_HA_SET_ID | `sai_object_id_t` | The HA set ID for this scope. | +| SAI_HA_SCOPE_ATTR_HA_ROLE | `sai_dash_ha_role_t` | The HA role. | +| SAI_HA_SCOPE_ATTR_FLOW_VERSION | `sai_uint32_t` | The flow version for new flows. | + +The HA role is defined as below: + +```c +typedef enum _sai_dash_ha_role_t +{ + SAI_DASH_HA_ROLE_DEAD, + SAI_DASH_HA_ROLE_ACTIVE, + SAI_DASH_HA_ROLE_STANDBY, + SAI_DASH_HA_ROLE_STANDALONE, + SAI_DASH_HA_ROLE_SWITCHING_TO_ACTIVE, +} sai_dash_ha_role_t; +``` + +### 4.3. Flow table + +HA uses the DASH flow table to achieve the flow state manipulation. Since the flow table already provides the CRUD operations, we don't need any extra APIs from flow table. + +For more information, please refer to DASH flow API documentation. + +### 4.4. Flow + +To support HA, each flow contains the following SAI attributes: + +| Attribute name | Type | Description | +| -------------- | ---- | ----------- | +| SAI_FLOW_ATTR_FLOW_VERSION | `sai_uint32_t` | The flow version. | +| SAI_FLOW_ATTR_FLOW_SYNC_STATE | `sai_dash_ha_flow_sync_state_t` | The flow sync state. | + +The flow sync state is defined as below: + +```c +typedef enum _sai_dash_ha_flow_sync_state_t +{ + SAI_DASH_HA_FLOW_SYNC_STATE_FLOW_MISS, + SAI_DASH_HA_FLOW_SYNC_STATE_FLOW_CREATED, + SAI_DASH_HA_FLOW_SYNC_STATE_FLOW_SYNCED, + SAI_DASH_HA_FLOW_SYNC_STATE_FLOW_PENDING_DELETE, + SAI_DASH_HA_FLOW_SYNC_STATE_FLOW_PENDING_RESIMULATION +} sai_dash_ha_flow_sync_state_t; +``` + +The flow sync state is a small state machine that represents if the flow is synched or not, so we can make the packet processing decision accordingly to achieve HA. + +```mermaid +stateDiagram-v2 + M: FLOW_MISS + C: FLOW_CREATED + S: FLOW_SYNCED + D: FLOW_PENDING_DELETE + R: FLOW_PENDING_RESIMULATION + + M --> C: Flow created + M --> S: Flow sync request
received on
standby node + + C --> S: Flow sync ack received + S --> R: Flow resimulation requested + R --> C: Flow updated + + C --> D: Flow deleted + S --> D: Flow deleted + R --> D: Flow deleted + + D --> M: Flow sync ack received +``` + +For more information, please refer to DASH flow API documentation. + +### 4.5. ENI + +To provide the ENI-level HA control, each ENI will have the following SAI attributes: + +| Attribute name | Type | Description | +| -------------- | ---- | ----------- | +| SAI_ENI_ATTR_HA_SCOPE_ID | `sai_object_id_t` | The HA scope ID of the ENI. | + +### 4.6. Event notifications + +To receive the HA related updates from the DASH implementation, the following SAI notification attributes are added on the switch object: + +| Attribute name | Type | Description | +| -------------- | ---- | ----------- | +| SAI_SWITCH_ATTR_HA_SET_EVENT_NOTIFY | `sai_ha_set_event_notification_fn` | The callback function for receiving events on the HA set. | +| SAI_SWITCH_ATTR_HA_SCOPE_EVENT_NOTIFY | `sai_ha_scope_event_notification_fn` | The callback function for receiving events on the HA scope. | + +#### 4.6.1. HA set event notifications + +Whenever a HA set state is changed, it will be reported back via HA set event notification, such as data plane channel goes down. The detailed definition is shown as below: + +```c +/** + * @brief HA set event type + */ +typedef enum _sai_ha_set_event_t +{ + /** Data plane channel goes up. */ + SAI_HA_SET_DP_CHANNEL_UP, + + /** Data plane channel goes down. */ + SAI_HA_SET_DP_CHANNEL_DOWN, + +} sai_ha_set_event_t; + +/** + * @brief Notification data format received from SAI HA set callback + */ +typedef struct _sai_ha_set_event_data_t +{ + /** Event type */ + sai_ha_set_event_t event_type; + + /** HA set id */ + sai_object_id_t ha_set_id; + +} sai_ha_set_event_data_t; + +/** + * @brief HA set event notification + * + * Passed as a parameter into sai_initialize_switch() + * + * @count data[count] + * + * @param[in] count Number of notifications + * @param[in] data Array of HA set events + */ +typedef void (*sai_ha_set_event_notification_fn)( + _In_ uint32_t count, + _In_ const sai_ha_set_event_data_t *ha_set_event_data); +``` + +#### 4.6.2. HA scope event notifications + +Similar to HA set, whenever any HA scope state is changed, it will be reported back via HA scope event notification. The detailed definition is shown as below: + +```c +/** + * @brief Notification data format received from SAI HA scope callback + */ +typedef struct _sai_ha_scope_event_data_t +{ + /** HA scope id */ + sai_object_id_t ha_scope_id; + + /** HA role */ + sai_dash_ha_role_t ha_role; + + /** Flow version */ + sai_uint32_t flow_version; + +} sai_ha_scope_event_data_t; + +/** + * @brief HA scope event notification + * + * Passed as a parameter into sai_initialize_switch() + * + * @count data[count] + * + * @param[in] count Number of notifications + * @param[in] data Array of HA scope events + */ +typedef void (*sai_ha_scope_event_notification_fn)( + _In_ uint32_t count, + _In_ const sai_ha_scope_event_data_t *ha_scope_event_data); +``` + +### 4.7. Counters + +To check how HA works, we will provide the following counters, which follows the [SmartSwitch HA detailed design doc](https://github.com/sonic-net/SONiC/blob/master/doc/smart-switch/high-availability/smart-switch-ha-detailed-design.md). + +#### 4.7.1. HA set stats + +Here are the new stats we added for monitoring HA on HA set (DPU pair): + +| SAI stats name | Description | +| -------------- | ----------- | +| SAI_HA_SET_STAT_DP_PROBE_(REQ/ACK)_RX_BYTES | The bytes of data plane probes that this HA set received. | +| SAI_HA_SET_STAT_DP_PROBE_(REQ/ACK)_RX_PACKETS | The number of packets of data plane probes that this HA set received. | +| SAI_HA_SET_STAT_DP_PROBE_(REQ/ACK)_TX_BYTES | The bytes of data plane probes that this HA set sent. | +| SAI_HA_SET_STAT_DP_PROBE_(REQ/ACK)_TX_PACKETS | The number of packets of data plane probes that this HA set sent. | +| SAI_HA_SET_STAT_DP_PROBE_FAILED | The number of probes that failed. The failure rate = the number of failed probes / the number of tx packets. | + +#### 4.7.2. ENI stats + +##### 4.7.2.1. ENI-level traffic counters + +To monitor the traffic on ENI level, the following stats are added: + +| SAI stats name | Description | +| -------------- | ----------- | +| SAI_ENI_STAT_(/OUTBOUND_/INBOUND_)RX_BYTES | Total bytes received on ENI (overall/outbound/inbound) pipeline. | +| SAI_ENI_STAT_(/OUTBOUND_/INBOUND_)RX_PACKETS | Total number of packets received on ENI (overall/outbound/inbound) pipeline. | +| SAI_ENI_STAT_(/OUTBOUND_/INBOUND_)TX_BYTES | Total bytes sent by ENI (overall/outbound/inbound) pipeline. | +| SAI_ENI_STAT_(/OUTBOUND_/INBOUND_)TX_PACKETS | Total number of packets sent by ENI (overall/outbound/inbound) pipeline. | + +The packet size of all the counters should contain the size of both the customer packet and the encap, to reflect the real traffic size. For the traffic volume of the customer packet only, they are counted using metering buckets. + +##### 4.7.2.2. ENI-level flow operation counters + +Here are the new stats added for monitoring flow operations on each ENI: + +| SAI stats name | Description | +| -------------- | ----------- | +| SAI_ENI_STAT_FLOW_CREATED | Total flow created on ENI. | +| SAI_ENI_STAT_FLOW_CREATE_FAILED | Total flow failed to create on ENI. | +| SAI_ENI_STAT_FLOW_UPDATED | Total flow updated on ENI. | +| SAI_ENI_STAT_FLOW_UPDATE_FAILED | Total flow failed to update on ENI. | +| SAI_ENI_STAT_FLOW_DELETED | Total flow deleted on ENI. | +| SAI_ENI_STAT_FLOW_DELETE_FAILED | Total flow failed to delete on ENI. | +| SAI_ENI_STAT_FLOW_AGED | Total flow aged out on ENI. A flow is aged out doesn't mean the flow entry is deleted. It could be marked as pending deletion and get deleted later. | + +##### 4.7.2.3. ENI-level flow sync packet counters + +Here are the new stats added for monitoring flow sync packets on each ENI: + +- The flow can be synched inline with the packet, or on a timer such as idle timeout. + +| SAI stats name | Description | +| -------------- | ----------- | +| SAI_ENI_STAT_(INLINE/TIMED)_FLOW_SYNC_PACKET_RX_BYTES | The bytes of inline/timed flow sync packet received by the ENI. | +| SAI_ENI_STAT_(INLINE/TIMED)_FLOW_SYNC_PACKET_RX_PACKETS | The number of inline/timed flow sync packets received by the ENI. | +| SAI_ENI_STAT_(INLINE/TIMED)_FLOW_SYNC_PACKET_TX_BYTES | The bytes of inline/timed flow sync packet that this ENI sent. | +| SAI_ENI_STAT_(INLINE/TIMED)_FLOW_SYNC_PACKET_TX_PACKETS | The number of inline/timed flow sync packets that this ENI sent. | + +##### 4.7.2.4. ENI-level flow sync operations counters + +Here are the new stats added for monitoring flow sync operations on each ENI: + +- The number of flow operations can be different from the number of flow sync packets. Depending on implementation, a single flow sync packet can carry multiple flow operations. +- The flow operation could fail or be ignored by ENI. + - Failed means it is unexpected to receive packet, and we failed to process it. + - Ignored means packet is expected be received, but we should ignore the flow operation inside and move on without dropping the packet. E.g., more packet arrives before flow sync is ack'ed. + +| SAI stats name | Description | +| -------------- | ----------- | +| SAI_ENI_STAT_(INLINE/TIMED)\_FLOW\_(CREATE/UPDATE/DELETE)_REQ_SENT | The number of inline/timed flow create/update/delete request that the ENI sent. | +| SAI_ENI_STAT_(INLINE/TIMED)\_FLOW\_(CREATE/UPDATE/DELETE)_REQ_RECV | The number of inline/timed flow create/update/delete request that the ENI received. | +| SAI_ENI_STAT_(INLINE/TIMED)\_FLOW\_(CREATE/UPDATE/DELETE)_REQ_FAILED | The number of inline/timed flow create/update/delete request that the ENI received but failed to process. | +| SAI_ENI_STAT_(INLINE/TIMED)\_FLOW\_(CREATE/UPDATE/DELETE)_REQ_IGNORED | The number of inline/timed flow create/update/delete request that the ENI received but its flow operation is processed as ignored. | +| SAI_ENI_STAT_(INLINE/TIMED)\_FLOW\_(CREATE/UPDATE/DELETE)_ACK_RECV | The number of inline/timed flow create/update/delete ack that the ENI is received. | +| SAI_ENI_STAT_(INLINE/TIMED)\_FLOW\_(CREATE/UPDATE/DELETE)_ACK_FAILED | The number of inline/timed flow create/update/delete ack that the ENI is received but failed to process. | +| SAI_ENI_STAT_(INLINE/TIMED)\_FLOW\_(CREATE/UPDATE/DELETE)_ACK_IGNORED | The number of inline/timed flow create/update/delete ack that the ENI is received but its flow operation is processed as ignored. | + +### 4.8. Capability + +To check which type of topology is supported in the DASH implementation, the following read only attributes is added on the switch level for capability queries: + +#### 4.8.1. Topology related capabilities + +To describe how the topology looks like, we need to use at least 4 different attributes: + +- \# of HA set that can be created +- \# of HA scope per HA set that can be created +- \# of ENI per HA scope that can be created +- \# of flow table that can be created + +However, since we only support DPU level pairing with a single flow table and the topology we supported at this moment is limited, the topology related capability is added as high level modes, instead of individual attributes: + +| Attribute name | Type | Description | +| -------------- | ---- | ----------- | +| SAI_SWITCH_ATTR_DASH_CAPS_HA_OWNER_NEEDED | `bool` | If `true`, the DASH host will own driving the HA state machine. | +| SAI_SWITCH_ATTR_DASH_CAPS_HA_SCOPE_LEVEL | `sai_dash_caps_ha_scope_level_t` | HA scope that supported by the DASH implementation. | + +The HA scope capability enum is defined as below: + +```c++ +typedef enum _sai_dash_caps_ha_scope_level_t +{ + Card, + ENI, +} sai_dash_caps_ha_scope_level_t; +``` + +And here is how the topology looks like for type of HA scope: + +| HA scope | DPU | ENI | +| --- | --- | --- | +| \# of HA set | 1 | 1 | +| \# of HA scope per HA set | 1 | (Max \# of ENI) | +| \# of ENI per HA scope | (Max \# of ENI) | 1 | +| \# of flow table | 1 | 1 | + +#### 4.8.2. Stats related capabilities + +Stats related capabilities can help with 2 things: + +1. Specify which stats is supported now, so we can start pulling to avoid errors. +2. Return internal debug stats to help with troubleshooting. + +To query the HA stats related capabilities, we will use the existing SAI stats capabilities. For more details on the API, please refer to the [SAI object APIs](https://github.com/opencomputeproject/SAI/blob/master/inc/saiobject.h). + +## 5. HA in DASH behavior model + +With these concepts, we can now use them to build a pipeline with flow HA supported. + +To illustrate how HA works in DASH, we implements HA in our behavior model. However it should only be treated as a logical example, but doesn't require the DASH providers to follow the exact same implementation. The goal is still to satisfy the requirements that defined in [our HA HLD](https://github.com/sonic-net/SONiC/blob/master/doc/smart-switch/high-availability/smart-switch-ha-hld.md). + +> NOTE: This work is currently in progress, but how it will work is described here. + +### 5.1. HA stage + +In the DASH pipeline, the HA can be considered as a sub-stage of the Conntrack Lookup stage or a stage that follows the Conntrack Lookup stage. + +When a packet arrives, it will: + +1. From ENI, pick up the flow table id and HA scope id. +2. From flow table, pick up the current flow info, such as if flow exists and synched. +3. From HA scope, pick up the HA set id, HA role and expected flow version if it will create a new flow. +4. From HA set, pick up the peer DPU information. + +Then, based on these information, the HA stage will make a decision on whether this packet should be forwarded directly, or going through slow path to get flow created or updated, or tunneled to its peer for flow sync or sending to active. + +### 5.2. Packet type and flow operations + +To support the flow HA, due to the nature of having different type of packets, such as regular packets vs flow sync packets, and different type of flow operations, such as flow creations vs flow updates, we have these things defined: + +```c +// Packet source +enum bit<8> dash_packet_source_t { + EXTERNAL = 0, // Packets from external sources. + DPAPP = 1, // Packets from data plane app. + PEER = 2 // Packets from the paired DPU. +}; + +// Packet type +enum bit<8> dash_packet_type_t { + REGULAR = 0, // Regular packets from external sources. + FLOW_SYNC_REQ = 1, // Flow sync request packet. + FLOW_SYNC_ACK = 2, // Flow sync ack packet. + DP_PROBE_REQ = 3, // Data plane probe packet. + DP_PROBE_ACK = 4 // Data plane probe ack packet. +}; + +// HA flow sync operations +enum bit<8> dash_ha_flow_sync_op_t { + FLOW_CREATE = 0, // New flow creation. + FLOW_UPDATE = 1, // Flow resimulation or any other reason causing existing flow to be updated. + FLOW_DELETE = 2 // Flow deletion. +}; +``` + +### 5.3. Life of the packet + +With these ingredients, we can enhance our current DASH behavior model to support flow HA. + +To simplify the scenario, let's say a packet arrives at the active DPU in active-standby steady state. At a high level, the packet will transverse our pipeline as below, which syncs the flow inline: + +![](./images/ha-bm-packet-flow.svg) + +1. (Green Lines) First, the packet for a new flow arrives to the active DPU. After ENI lookup, it will try to find the flow in the flow table. Due to flow being missing, the packet will go through the rest of the pipeline and eventually trapped into the data plane app. +2. (Black Lines in Active DPU) The data plane app will get the lookup result from the packet and insert the flow entry in not synched state to flow table using the DASH SAI flow APIs. +3. (Red Line in Active DPU) The data plane app recirculate the packet back to the pipeline and hit the flow table again, because the flow is not synched and this ENI is active side, HA stage will kick in and change this packet to a flow sync request packet, then forward it to its peer DPU. +4. (Yellow Lines) The flow sync packet goes to the standby side, which will also hit the flow miss, skip the HA stage and trapped into data plane app. +5. (Black Line in Standby DPU) The data plane app takes the flow decision from the flow sync packet, inserts the flow entry in synched state. +6. (Red Lines in Standby DPU) The data plane app recirculate the packet back to the pipeline and hit the flow table again, because the packet is a flow sync request and flow is in synched state, HA stage will transform this packet into flow sync ack and sending it back to its active side. +7. (Blue Lines) The packet goes back to the active side, which will hit the flow again. Since it is flow sync ack and flow is in not-synched state, the packet will be trapped into data plane app again. +8. (Black Line in Active DPU) The data plane app will update the flow sync state into synched state and recirculate the packet again. +9. (Purple Lines) The final packet will be sent to the pipeline again, hit the flow entry in synched state, applying all the transformation and send out to the network. + +## 6. Workflows + +### 6.1. ENI level HA + +In ENI-level HA, the HA SAI APIs is designed to act passively according to the HA control plane decision. + +To explain how HA API works from SAI API perspective, here are the examples of the common HA workflows. + +> NOTE: The following workflow only shows the sequence of how each SAI API being called. But to achieve HA, besides this, we have HA control plane services that drives the HA state machine which ensures the APIs are called in the expected sequence. For more information, please refer to the planned operations and unplanned operations in [our HA HLD](https://github.com/sonic-net/SONiC/blob/master/doc/smart-switch/high-availability/smart-switch-ha-hld.md). + +#### 6.1.1. HA set and ENI creation + +The first step to start using HA is to create the HA set to form the DPU pair. + +> The full workflow can be found in the ["Clean launch on both sides" section in SmartSwitch HA HLD](https://github.com/sonic-net/SONiC/blob/master/doc/smart-switch/high-availability/smart-switch-ha-hld.md#811-clean-launch-on-both-sides). + +```mermaid +sequenceDiagram + autonumber + + participant SDN as SDN Controller + participant S0D as Switch 0 DPU
(Desired Active) + participant S0N as Switch 0 NPU + participant S1N as Switch 1 NPU + participant S1D as Switch 1 DPU
(Desired Standby) + + SDN->>S0N: Create HA set on all switches + SDN->>S1N: Create HA set on all switches + + S0N->>S0D: Create HA set on DPU
(sai: create_ha_set) + S1N->>S1D: Create HA set on DPU
(sai: create_ha_set) + Note over S0D,S1D: DPU starts data path probe to peer DPU.
After this, ENIs can be created. + + SDN->>S0N: Create ENI with HA set ID as dead state + SDN->>S1N: Create ENI with HA set ID as dead state + + S0N->>S0D: Create ENI with HA set ID as dead role
(sai: create_ha_scope / create_eni) + S1N->>S1D: Create ENI with HA set ID as dead role
(sai: create_ha_scope / create_eni) + Note over SDN,S1D: SDN controller programs the SDN policy for both ENI. + + SDN->>S0N: Update ENI with desired state as active. + SDN->>S1N: Update ENI with desired state as empty. + Note over S0N,S1N: hamgrd driving HA state machine + + S1N->>S1D: Update ENI HA scope with standby role.
(sai: set_ha_scope_attribute) + Note over S0N,S1N: hamgrd continue to drive
HA state machine + S0N->>S0D: Update ENI HA scope with active role.
(sai: set_ha_scope_attribute) + + Note over S0N,S1N: hamgrd continue to drive HA
state machine and update
nexthop on all switches. +``` + +#### 6.1.2. Switchover + +After the DPU goes into steady state, we can start initiating the switchover process. + +In the ENI-level HA, the switchover starts from the standby side, so we can make sure the standby is ready to pick up the traffic before switching over. + +> The full workflow can be found in the ["Planned switchover" section in SmartSwitch HA HLD](https://github.com/sonic-net/SONiC/blob/master/doc/smart-switch/high-availability/smart-switch-ha-hld.md#82-planned-switchover). + +```mermaid +sequenceDiagram + autonumber + + participant SDN as SDN Controller + participant S0D as Switch 0 DPU
(Active->Standby) + participant S0N as Switch 0 NPU + participant S1N as Switch 1 NPU + participant S1D as Switch 1 DPU
(Standby->Active) + + SDN->>S0N: Update ENI with desired state as empty. + SDN->>S1N: Update ENI with desired state as active. + Note over S0N,S1N: hamgrd gets approval from
upstream service and drives
HA state machine + + S1N->>S1D: Update ENI HA scope with SwitchingToActive role.
(sai: set_ha_scope_attribute) + Note over S0N,S1N: hamgrd continue to drive
HA state machine + S0N->>S0D: Update ENI HA scope with standby role.
(sai: set_ha_scope_attribute) + Note over S0N,S1N: hamgrd continue to drive
HA state machine + S1N->>S1D: Update ENI HA scope with active role.
(sai: set_ha_scope_attribute) + + Note over S0N,S1N: hamgrd continue to drive
HA state machine and
update nexthop on all switches. +``` + +#### 6.1.3. Unplanned failover + +Whenever the network or one DPU having problem, unplanned failover will be triggered. + +In ENI-level HA, the unplanned events are monitored by the HA control plane via various of different event sources, such as PMON, counters and etc. Once any event is triggered, we will trigger the unplanned failover as below: + +> The full workflow can be found in the ["Working as standalone setup" section in SmartSwitch HA HLD](https://github.com/sonic-net/SONiC/blob/master/doc/smart-switch/high-availability/smart-switch-ha-hld.md#101-working-as-standalone-setup). + +```mermaid +sequenceDiagram + autonumber + + participant S0D as Switch 0 DPU
(Active->Dead) + participant S0N as Switch 0 NPU + participant S1N as Switch 1 NPU + participant S1D as Switch 1 DPU
(Standby->Standalone) + + S0N->>S0N: PMON detects DPU0 is dead. + Note over S0N,S1N: hamgrd receives the health
signal and drives HA state
machine + + S1N->>S1D: Update ENI HA scope with Standalone role.
(sai: set_ha_scope_attribute) + + Note over S0N,S1N: hamgrd continue to drive
HA state machine and
update nexthop on all switches. +``` + +#### 6.1.4. Recover from unplanned failover + +During recovery, bulk sync will be used to ensure both sides contains the same set of flows. + +In ENI-level HA today, perfect sync will be used as the default mechanism to sync the flows. It is done via the DASH flow APIs as below. For more information, please refer to the DASH flow API design doc. + +> The full workflow can be found in the ["Launch with standalone peer" section in SmartSwitch HA HLD](https://github.com/sonic-net/SONiC/blob/master/doc/smart-switch/high-availability/smart-switch-ha-hld.md#812-launch-with-standalone-peer). + +```mermaid +sequenceDiagram + autonumber + + participant SDN as SDN Controller + participant S0D as Switch 0 DPU
(Standalone->Active) + participant S0N as Switch 0 NPU + participant S1N as Switch 1 NPU + participant S1D as Switch 1 DPU
(Empty->Standby) + + S1D->>S1D: Coming back from dead. + S1N->>S1D: Create HA set on DPU
(sai: create_ha_set) + Note over S0D,S1D: DPU starts data path probe to peer DPU. + + SDN->>S1N: Reconcile SDN policy for the new DPU. + S1N->>S1D: Create ENI with HA set ID as dead role
(sai: create_ha_scope / create_eni) + Note over S0N,S1N: hamgrd driving HA state machine. + + S1N->>S1D: Update ENI HA scope with standby role.
(sai: set_ha_scope_attribute) + Note over S0N,S1N: hamgrd continue to drive
HA state machine + S0N->>S0D: Update ENI HA scope with active role.
(sai: set_ha_scope_attribute) + + Note over S0N,S1N: hamgrd continue to drive HA
state machine and update
nexthop on all switches. +``` diff --git a/documentation/high-avail/images/ha-bm-packet-flow.svg b/documentation/high-avail/images/ha-bm-packet-flow.svg new file mode 100644 index 000000000..1d6165402 --- /dev/null +++ b/documentation/high-avail/images/ha-bm-packet-flow.svg @@ -0,0 +1,4 @@ + + + +
Active
Data Plane App
P4 Pipeline
Parser
ENI Pipeline
ConnTrack
Lookup
Match
Stages
Action
Apply
Trap
Forward
HA
Flow Sync Req
Direction/ENI Lookup
In
Recirculate Initial Packet
Call Flow API to create flow
in not-sync'ed state or update
flow to sync'ed state
Recirculate Flow Sync Ack Packet
Legends
Packet circulated
by data plane app
Initial Packet
SAI API Call
Flow Sync Req
Flow Sync Ack
Final Packet
Standby
Data Plane App
P4 Pipeline
Parser
ENI Pipeline
ConnTrack
Lookup
Flow Sync Ack
Match
Stages
Action
Apply
Trap
Forward
HA
Direction/ENI Lookup
Recirculate Flow Sync Req Packet
Call Flow API to
create flow in
sync'ed state
Out
\ No newline at end of file diff --git a/documentation/high-avail/images/ha-components-complex.svg b/documentation/high-avail/images/ha-components-complex.svg new file mode 100644 index 000000000..fc050af3e --- /dev/null +++ b/documentation/high-avail/images/ha-components-complex.svg @@ -0,0 +1,4 @@ + + + +
DPU 2
DPU 1
HA Set 1
HA Scope 1
ENI 3
3-tuple Flow Table
5-tuple
Flow Table
ENI 3
3-tuple Flow Table
5-tuple
Flow Table
HA Scope 2
ENI 4
3-tuple Flow Table
5-tuple
Flow Table
ENI 4
3-tuple Flow Table
5-tuple
Flow Table
DPU 0
HA Set 0
HA Scope 0
ENI 0
3-tuple Flow Table
5-tuple
Flow Table
ENI 0
3-tuple Flow Table
5-tuple
Flow Table
ENI 1
3-tuple Flow Table
5-tuple
Flow Table
ENI 1
3-tuple Flow Table
5-tuple
Flow Table
\ No newline at end of file diff --git a/documentation/high-avail/images/ha-components-dpu-level-ha.svg b/documentation/high-avail/images/ha-components-dpu-level-ha.svg new file mode 100644 index 000000000..9f8748ba4 --- /dev/null +++ b/documentation/high-avail/images/ha-components-dpu-level-ha.svg @@ -0,0 +1,4 @@ + + + +
DPU 1
DPU 0
HA Set 0
HA Scope 0
ENI 0
ENI 1
Flow Table
ENI 0
ENI 1
Flow Table
\ No newline at end of file diff --git a/documentation/high-avail/images/ha-components-eni-level-ha.svg b/documentation/high-avail/images/ha-components-eni-level-ha.svg new file mode 100644 index 000000000..db0147eb1 --- /dev/null +++ b/documentation/high-avail/images/ha-components-eni-level-ha.svg @@ -0,0 +1,4 @@ + + + +
DPU 1
DPU 0
HA Set 0
HA Scope 0
ENI 0
HA Scope 1
ENI 1
Flow Table
HA Scope 0
ENI 0
HA Scope 1
ENI 1
Flow Table
\ No newline at end of file diff --git a/test/test-cases/functional/ptf/sai_dash_utils.py b/test/test-cases/functional/ptf/sai_dash_utils.py index d4758fe3c..ff4acd9a7 100644 --- a/test/test-cases/functional/ptf/sai_dash_utils.py +++ b/test/test-cases/functional/ptf/sai_dash_utils.py @@ -140,6 +140,7 @@ def eni_create(self, **kwargs): "pps": 100000, "flows": 100000, "admin_state": True, + "ha_scope_id": 0, "vm_underlay_dip": sai_ipaddress("0.0.0.0"), "vm_vni": 1, "vnet_id": 1, diff --git a/test/test-cases/functional/ptf/saidashacl.py b/test/test-cases/functional/ptf/saidashacl.py index 794eb0c9f..1cd4ac4c3 100644 --- a/test/test-cases/functional/ptf/saidashacl.py +++ b/test/test-cases/functional/ptf/saidashacl.py @@ -192,6 +192,7 @@ def setUpSwitch(self): self.eni = self.create_obj(sai_thrift_create_eni, sai_thrift_remove_eni, cps=10000, pps=100000, flows=100000, admin_state=True, + ha_scope_id=0, vm_underlay_dip=vm_underlay_dip, vm_vni=9, vnet_id=self.vnet, diff --git a/test/test-cases/functional/ptf/saidashvnet_sanity.py b/test/test-cases/functional/ptf/saidashvnet_sanity.py index 33ea531f9..e1a435954 100644 --- a/test/test-cases/functional/ptf/saidashvnet_sanity.py +++ b/test/test-cases/functional/ptf/saidashvnet_sanity.py @@ -65,6 +65,7 @@ def configureVnet(self): self.eni = sai_thrift_create_eni(self.client, cps=10000, pps=100000, flows=100000, admin_state=True, + ha_scope_id=0, vm_underlay_dip=vm_underlay_dip, vm_vni=9, vnet_id=self.vnet, diff --git a/test/test-cases/functional/saic/config_bidir_setup_commands.py b/test/test-cases/functional/saic/config_bidir_setup_commands.py index 7b4ebfd46..0125361d6 100644 --- a/test/test-cases/functional/saic/config_bidir_setup_commands.py +++ b/test/test-cases/functional/saic/config_bidir_setup_commands.py @@ -95,6 +95,7 @@ "SAI_ENI_ATTR_PPS", "100000", "SAI_ENI_ATTR_FLOWS", "100000", "SAI_ENI_ATTR_ADMIN_STATE", "True", + "SAI_ENI_ATTR_HA_SCOPE_ID", "0", "SAI_ENI_ATTR_VM_UNDERLAY_DIP", ENI_VTEP_IP, "SAI_ENI_ATTR_VM_VNI", "9", "SAI_ENI_ATTR_VNET_ID", "$vnet", @@ -137,6 +138,7 @@ "SAI_ENI_ATTR_PPS", "100000", "SAI_ENI_ATTR_FLOWS", "100000", "SAI_ENI_ATTR_ADMIN_STATE", "True", + "SAI_ENI_ATTR_HA_SCOPE_ID", "0", "SAI_ENI_ATTR_VM_UNDERLAY_DIP", NETWORK_VTEP_IP, "SAI_ENI_ATTR_VM_VNI", "9", "SAI_ENI_ATTR_VNET_ID", "$vnet", @@ -179,6 +181,7 @@ "SAI_ENI_ATTR_PPS", "100000", "SAI_ENI_ATTR_FLOWS", "100000", "SAI_ENI_ATTR_ADMIN_STATE", "True", + "SAI_ENI_ATTR_HA_SCOPE_ID", "0", "SAI_ENI_ATTR_VM_UNDERLAY_DIP", NETWORK_VTEP_IP, "SAI_ENI_ATTR_VM_VNI", "9", "SAI_ENI_ATTR_VNET_ID", "$vnet", diff --git a/test/test-cases/functional/saic/config_inbound_setup_commands.py b/test/test-cases/functional/saic/config_inbound_setup_commands.py index 2ce4a593b..8eeac1460 100644 --- a/test/test-cases/functional/saic/config_inbound_setup_commands.py +++ b/test/test-cases/functional/saic/config_inbound_setup_commands.py @@ -103,6 +103,8 @@ "100000", "SAI_ENI_ATTR_ADMIN_STATE", "True", + "SAI_ENI_ATTR_HA_SCOPE_ID", + "0", "SAI_ENI_ATTR_VM_UNDERLAY_DIP", ENI_VTEP_IP, "SAI_ENI_ATTR_VM_VNI", @@ -180,6 +182,8 @@ "100000", "SAI_ENI_ATTR_ADMIN_STATE", "True", + "SAI_ENI_ATTR_HA_SCOPE_ID", + "0", "SAI_ENI_ATTR_VM_UNDERLAY_DIP", NETWORK_VTEP_IP, "SAI_ENI_ATTR_VM_VNI", diff --git a/test/test-cases/functional/saic/config_outbound_setup_commands.json b/test/test-cases/functional/saic/config_outbound_setup_commands.json index 4c6b7f0c0..2ee4275fb 100644 --- a/test/test-cases/functional/saic/config_outbound_setup_commands.json +++ b/test/test-cases/functional/saic/config_outbound_setup_commands.json @@ -69,6 +69,7 @@ "SAI_ENI_ATTR_PPS", "100000", "SAI_ENI_ATTR_FLOWS", "100000", "SAI_ENI_ATTR_ADMIN_STATE", "True", + "SAI_ENI_ATTR_HA_SCOPE_ID", "0", "SAI_ENI_ATTR_VM_UNDERLAY_DIP", "221.0.1.11", "SAI_ENI_ATTR_VM_VNI", "9", "SAI_ENI_ATTR_VNET_ID", "$vnet", @@ -111,6 +112,7 @@ "SAI_ENI_ATTR_PPS", "100000", "SAI_ENI_ATTR_FLOWS", "100000", "SAI_ENI_ATTR_ADMIN_STATE", "True", + "SAI_ENI_ATTR_HA_SCOPE_ID", "0", "SAI_ENI_ATTR_VM_UNDERLAY_DIP", "221.0.2.101", "SAI_ENI_ATTR_VM_VNI", "9", "SAI_ENI_ATTR_VNET_ID", "$vnet", diff --git a/test/test-cases/functional/saic/sai-api/test_sai_api_vnet_eni.py b/test/test-cases/functional/saic/sai-api/test_sai_api_vnet_eni.py index 30798c09e..e733f05a4 100644 --- a/test/test-cases/functional/saic/sai-api/test_sai_api_vnet_eni.py +++ b/test/test-cases/functional/saic/sai-api/test_sai_api_vnet_eni.py @@ -38,6 +38,8 @@ def test_vnet_eni_create(self, dpu): "100000", "SAI_ENI_ATTR_ADMIN_STATE", "True", + "SAI_ENI_ATTR_HA_SCOPE_ID", + "0", "SAI_ENI_ATTR_VM_UNDERLAY_DIP", "10.10.1.10", "SAI_ENI_ATTR_VM_VNI", diff --git a/test/test-cases/functional/saic/sai-api/test_sai_api_vnet_in_route.py b/test/test-cases/functional/saic/sai-api/test_sai_api_vnet_in_route.py index e2d86f062..be0a57f1b 100644 --- a/test/test-cases/functional/saic/sai-api/test_sai_api_vnet_in_route.py +++ b/test/test-cases/functional/saic/sai-api/test_sai_api_vnet_in_route.py @@ -45,6 +45,8 @@ def test_vnet_inbound_routing_entry_create_setup(self, dpu): "100000", "SAI_ENI_ATTR_ADMIN_STATE", "True", + "SAI_ENI_ATTR_HA_SCOPE_ID", + "0", "SAI_ENI_ATTR_VM_UNDERLAY_DIP", "10.10.2.10", "SAI_ENI_ATTR_VM_VNI", diff --git a/test/test-cases/functional/saic/sai-api/test_sai_api_vnet_out_route.py b/test/test-cases/functional/saic/sai-api/test_sai_api_vnet_out_route.py index 2c07e1d8d..ecf73212e 100644 --- a/test/test-cases/functional/saic/sai-api/test_sai_api_vnet_out_route.py +++ b/test/test-cases/functional/saic/sai-api/test_sai_api_vnet_out_route.py @@ -44,6 +44,8 @@ def test_vnet_outbound_routing_entry_create(self, dpu): "100000", "SAI_ENI_ATTR_ADMIN_STATE", "True", + "SAI_ENI_ATTR_HA_SCOPE_ID", + "0", "SAI_ENI_ATTR_VM_UNDERLAY_DIP", "10.10.9.10", "SAI_ENI_ATTR_VM_VNI", diff --git a/test/test-cases/functional/saic/tutorial/test_sai_vnet_outbound_small_scale_config_via_dpugen.py b/test/test-cases/functional/saic/tutorial/test_sai_vnet_outbound_small_scale_config_via_dpugen.py index a0c33ade6..5376fa3d1 100755 --- a/test/test-cases/functional/saic/tutorial/test_sai_vnet_outbound_small_scale_config_via_dpugen.py +++ b/test/test-cases/functional/saic/tutorial/test_sai_vnet_outbound_small_scale_config_via_dpugen.py @@ -63,7 +63,7 @@ def make_create_commands(self): 'SAI_ENI_ATTR_PL_SIP', '2001:0db8:85a3:0000:0000:8a2e:0370:7334', 'SAI_ENI_ATTR_PL_SIP_MASK', '2001:0db8:85a3:0000:0000:0000:0000:0000', 'SAI_ENI_ATTR_PL_UNDERLAY_SIP', '10.0.0.18', "SAI_ENI_ATTR_DASH_TUNNEL_DSCP_MODE", "SAI_DASH_TUNNEL_DSCP_MODE_PRESERVE_MODEL", "SAI_ENI_ATTR_DSCP", "0", - "SAI_ENI_ATTR_DISABLE_FAST_PATH_ICMP_FLOW_REDIRECTION", "False"]) + "SAI_ENI_ATTR_DISABLE_FAST_PATH_ICMP_FLOW_REDIRECTION", "False", "SAI_ENI_ATTR_HA_SCOPE_ID", "0"]) ret = add_extra_attrs('SAI_OBJECT_TYPE_OUTBOUND_CA_TO_PA_ENTRY', ret, [ 'SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_METER_CLASS', '0', 'SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_METER_CLASS_OVERRIDE', 'True' ]) diff --git a/test/test-cases/functional/saic/tutorial/test_sai_vnet_outbound_small_scale_config_via_dpugen_create.json b/test/test-cases/functional/saic/tutorial/test_sai_vnet_outbound_small_scale_config_via_dpugen_create.json index 93529a361..225113553 100644 --- a/test/test-cases/functional/saic/tutorial/test_sai_vnet_outbound_small_scale_config_via_dpugen_create.json +++ b/test/test-cases/functional/saic/tutorial/test_sai_vnet_outbound_small_scale_config_via_dpugen_create.json @@ -87,6 +87,8 @@ "100000", "SAI_ENI_ATTR_ADMIN_STATE", "True", + "SAI_ENI_ATTR_HA_SCOPE_ID", + "0", "SAI_ENI_ATTR_VM_UNDERLAY_DIP", "221.0.1.1", "SAI_ENI_ATTR_VM_VNI", @@ -164,6 +166,8 @@ "100000", "SAI_ENI_ATTR_ADMIN_STATE", "True", + "SAI_ENI_ATTR_HA_SCOPE_ID", + "0", "SAI_ENI_ATTR_VM_UNDERLAY_DIP", "221.0.1.2", "SAI_ENI_ATTR_VM_VNI", diff --git a/test/test-cases/scale/saic/test_sai_vnet_outbound_scale.py b/test/test-cases/scale/saic/test_sai_vnet_outbound_scale.py index cbabf50d2..e14bf8aaa 100755 --- a/test/test-cases/scale/saic/test_sai_vnet_outbound_scale.py +++ b/test/test-cases/scale/saic/test_sai_vnet_outbound_scale.py @@ -116,7 +116,7 @@ def make_create_vnet_config(self): 'SAI_ENI_ATTR_PL_SIP', '2001:0db8:85a3:0000:0000:8a2e:0370:7334', 'SAI_ENI_ATTR_PL_SIP_MASK', '2001:0db8:85a3:0000:0000:0000:0000:0000', 'SAI_ENI_ATTR_PL_UNDERLAY_SIP', '10.0.0.18', "SAI_ENI_ATTR_DASH_TUNNEL_DSCP_MODE", "SAI_DASH_TUNNEL_DSCP_MODE_PRESERVE_MODEL", "SAI_ENI_ATTR_DSCP", "0", - "SAI_ENI_ATTR_DISABLE_FAST_PATH_ICMP_FLOW_REDIRECTION", "False"]) + "SAI_ENI_ATTR_DISABLE_FAST_PATH_ICMP_FLOW_REDIRECTION", "False", "SAI_ENI_ATTR_HA_SCOPE_ID", "0"]) ret = add_extra_attrs('SAI_OBJECT_TYPE_OUTBOUND_CA_TO_PA_ENTRY', ret, [ 'SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_METER_CLASS', '0', 'SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_METER_CLASS_OVERRIDE', 'True' ]) diff --git a/test/test-cases/scale/saic/vnet_inbound_setup_commands.json b/test/test-cases/scale/saic/vnet_inbound_setup_commands.json index 38695fa81..597c49692 100644 --- a/test/test-cases/scale/saic/vnet_inbound_setup_commands.json +++ b/test/test-cases/scale/saic/vnet_inbound_setup_commands.json @@ -65,6 +65,8 @@ "100000", "SAI_ENI_ATTR_ADMIN_STATE", "True", + "SAI_ENI_ATTR_HA_SCOPE_ID", + "True", "SAI_ENI_ATTR_VM_UNDERLAY_DIP", "10.10.2.10", "SAI_ENI_ATTR_VM_VNI", diff --git a/test/test-cases/scale/saic/vnet_outbound_setup_commands_scale.json b/test/test-cases/scale/saic/vnet_outbound_setup_commands_scale.json index 967061a6e..8013b9ca7 100644 --- a/test/test-cases/scale/saic/vnet_outbound_setup_commands_scale.json +++ b/test/test-cases/scale/saic/vnet_outbound_setup_commands_scale.json @@ -104,6 +104,7 @@ "SAI_ENI_ATTR_PPS", "100000", "SAI_ENI_ATTR_FLOWS", "100000", "SAI_ENI_ATTR_ADMIN_STATE", "True", + "SAI_ENI_ATTR_HA_SCOPE_ID", "0", "SAI_ENI_ATTR_VM_UNDERLAY_DIP", "172.16.1.1", "SAI_ENI_ATTR_VM_VNI", "9", "SAI_ENI_ATTR_VNET_ID", "$vnet_#4", @@ -148,6 +149,7 @@ "SAI_ENI_ATTR_PPS", "100000", "SAI_ENI_ATTR_FLOWS", "100000", "SAI_ENI_ATTR_ADMIN_STATE", "True", + "SAI_ENI_ATTR_HA_SCOPE_ID", "0", "SAI_ENI_ATTR_VM_UNDERLAY_DIP", "172.16.2.1", "SAI_ENI_ATTR_VM_VNI", "10", "SAI_ENI_ATTR_VNET_ID", "$vnet_#5", diff --git a/test/test-cases/scale/saic/vnet_outbound_setup_commands_simple.json b/test/test-cases/scale/saic/vnet_outbound_setup_commands_simple.json index d21474e5c..96b942a0e 100644 --- a/test/test-cases/scale/saic/vnet_outbound_setup_commands_simple.json +++ b/test/test-cases/scale/saic/vnet_outbound_setup_commands_simple.json @@ -56,6 +56,7 @@ "SAI_ENI_ATTR_PPS", "100000", "SAI_ENI_ATTR_FLOWS", "100000", "SAI_ENI_ATTR_ADMIN_STATE", "True", + "SAI_ENI_ATTR_HA_SCOPE_ID", "0", "SAI_ENI_ATTR_VM_UNDERLAY_DIP", "172.16.1.1", "SAI_ENI_ATTR_VM_VNI", "9", "SAI_ENI_ATTR_VNET_ID", "$vnet", diff --git a/test/test-cases/scale/saic/vnet_route_setup_commands_bidirectional.json b/test/test-cases/scale/saic/vnet_route_setup_commands_bidirectional.json index 4d951d3b4..a7be524e9 100644 --- a/test/test-cases/scale/saic/vnet_route_setup_commands_bidirectional.json +++ b/test/test-cases/scale/saic/vnet_route_setup_commands_bidirectional.json @@ -126,6 +126,8 @@ "100000", "SAI_ENI_ATTR_ADMIN_STATE", "True", + "SAI_ENI_ATTR_HA_SCOPE_ID", + "0", "SAI_ENI_ATTR_VM_UNDERLAY_DIP", "172.16.1.1", "SAI_ENI_ATTR_VM_VNI", @@ -203,6 +205,8 @@ "100000", "SAI_ENI_ATTR_ADMIN_STATE", "True", + "SAI_ENI_ATTR_HA_SCOPE_ID", + "0", "SAI_ENI_ATTR_VM_UNDERLAY_DIP", "10.10.2.10", "SAI_ENI_ATTR_VM_VNI", @@ -280,6 +284,8 @@ "100000", "SAI_ENI_ATTR_ADMIN_STATE", "True", + "SAI_ENI_ATTR_HA_SCOPE_ID", + "0", "SAI_ENI_ATTR_VM_UNDERLAY_DIP", "10.11.1.10", "SAI_ENI_ATTR_VM_VNI", @@ -357,6 +363,8 @@ "100000", "SAI_ENI_ATTR_ADMIN_STATE", "True", + "SAI_ENI_ATTR_HA_SCOPE_ID", + "0", "SAI_ENI_ATTR_VM_UNDERLAY_DIP", "170.16.1.1", "SAI_ENI_ATTR_VM_VNI", diff --git a/test/test-cases/scale/saic/vnet_route_setup_commands_unidirectional.json b/test/test-cases/scale/saic/vnet_route_setup_commands_unidirectional.json index fd8a093bb..1d76e1551 100644 --- a/test/test-cases/scale/saic/vnet_route_setup_commands_unidirectional.json +++ b/test/test-cases/scale/saic/vnet_route_setup_commands_unidirectional.json @@ -65,6 +65,8 @@ "100000", "SAI_ENI_ATTR_ADMIN_STATE", "True", + "SAI_ENI_ATTR_HA_SCOPE_ID", + "0", "SAI_ENI_ATTR_VM_UNDERLAY_DIP", "172.16.1.1", "SAI_ENI_ATTR_VM_VNI", From 54973eb25d4e5406033889e611eaebc7fcb0b006 Mon Sep 17 00:00:00 2001 From: Ashutosh Agrawal Date: Thu, 4 Apr 2024 14:35:21 -0700 Subject: [PATCH 22/32] VNET test fixes (#545) - Run tests in "monodir" mode since bidirectional testing requires stateful connection tracking and learning of new flows in both directions. - Fixed IP address mask in more tests - Comment out underlay programming since dash.p4 doesn't have a complete implementation of underlay. Co-authored-by: Shrivastava, Shweta --- test/test-cases/functional/ptf/run-tests.sh | 2 +- .../functional/ptf/sai_dash_utils.py | 4 +- test/test-cases/functional/ptf/saidashvnet.py | 201 +++++++++--------- 3 files changed, 103 insertions(+), 104 deletions(-) diff --git a/test/test-cases/functional/ptf/run-tests.sh b/test/test-cases/functional/ptf/run-tests.sh index ae0dd0b7f..edcc65622 100755 --- a/test/test-cases/functional/ptf/run-tests.sh +++ b/test/test-cases/functional/ptf/run-tests.sh @@ -3,7 +3,7 @@ SCRIPT=$(basename $0) TARGET="bmv2" # TODO: add no target by default and remove -H -TRAFFIC="bidir" +TRAFFIC="monodir" CONNECTION="tcp" TEST_DIR="$(dirname $0)" EXTRA_PARAMETERS="" diff --git a/test/test-cases/functional/ptf/sai_dash_utils.py b/test/test-cases/functional/ptf/sai_dash_utils.py index ff4acd9a7..a5339e837 100644 --- a/test/test-cases/functional/ptf/sai_dash_utils.py +++ b/test/test-cases/functional/ptf/sai_dash_utils.py @@ -443,8 +443,8 @@ def configure_underlay(self, *neighbors, add_routes=True): src_mac=neighbor.peer.mac) nhop = self.nexthop_create(rif, neighbor.ip) self.neighbor_create(rif, neighbor.ip, neighbor.mac) - if add_routes is True: - self.route_create(neighbor.ip_prefix, nhop) + #if add_routes is True: + # self.route_create(neighbor.ip_prefix, nhop) class VnetApiEndpoints(VnetAPI): diff --git a/test/test-cases/functional/ptf/saidashvnet.py b/test/test-cases/functional/ptf/saidashvnet.py index 6c25d1afa..2e04ea389 100644 --- a/test/test-cases/functional/ptf/saidashvnet.py +++ b/test/test-cases/functional/ptf/saidashvnet.py @@ -70,7 +70,7 @@ def configureTest(self): self.host_1 = self.tx_host self.host_2 = self.rx_host - self.configure_underlay(self.host_1, self.host_2) + #self.configure_underlay(self.host_1, self.host_2) def verifyOverlayOutboundConfigTest(self): @@ -116,7 +116,6 @@ def l3UnderlayHost2toHost1RoutingTest(self): @group("draft") -@skipIf(test_param_get('target') == 'bmv2', "Blocked on BMv2 by Issue #236") class Vnet2VnetInboundDecapPaValidateSinglePortTest(VnetApiEndpoints, VnetTrafficMixin): """ Inbound Vnet to Vnet scenario test case with @@ -130,7 +129,7 @@ def runTest(self): # Reconfigure configuration for tx equal to rx self.update_configuration_for_tx_equal_to_rx() self.configureTest() - self.configure_underlay(self.tx_host, add_routes=False) + #self.configure_underlay(self.tx_host, add_routes=False) self.vnet2VnetInboundRoutingTest(tx_equal_to_rx=True) self.vnet2VnetInboundNegativeTest() @@ -155,8 +154,9 @@ def configureTest(self): self.eni_mac_map_create(eni_id, self.rx_host.client.mac) # ENI MAC # Inbound routing PA Validate + addr_mask = self.tx_host.ip_prefix.split('/') self.inbound_routing_decap_validate_create(eni_id, vni=self.tx_host.client.vni, - sip=self.tx_host.ip, sip_mask="255.255.255.0", + sip=addr_mask[0], sip_mask=num_to_dotted_quad(addr_mask[1]), src_vnet_id=src_vnet) # PA validation entry with Permit action self.pa_validation_create(self.tx_host.ip, src_vnet) @@ -203,7 +203,6 @@ def vnet2VnetInboundNegativeTest(self): @group("draft") -@skipIf(test_param_get('target') == 'bmv2', "Blocked on BMv2 by Issue #236") class Vnet2VnetInboundDecapPaValidateSinglePortOverlayIpv6Test(Vnet2VnetInboundDecapPaValidateSinglePortTest): """ Underlay IPv4 and Overlay IPv6 configs @@ -231,7 +230,7 @@ class Vnet2VnetInboundDecapPaValidateTwoPortsTest(Vnet2VnetInboundDecapPaValidat def runTest(self): self.configureTest() - self.configure_underlay(self.tx_host, self.rx_host) + # self.configure_underlay(self.tx_host, self.rx_host) self.vnet2VnetInboundRoutingTest(tx_equal_to_rx=False) self.vnet2VnetInboundNegativeTest() @@ -251,13 +250,12 @@ class Vnet2VnetInboundDecapPaValidateTwoPortsOverlayIpv6Test(Vnet2VnetInboundDec def runTest(self): self.configureTest() - self.configure_underlay(self.tx_host, self.rx_host) + # self.configure_underlay(self.tx_host, self.rx_host) self.vnet2VnetInboundRoutingTest(tx_equal_to_rx=False) @group("draft") -@skipIf(test_param_get('target') == 'bmv2', "Blocked on BMv2 by Issue #236") class Vnet2VnetInboundDecapSinglePortTest(Vnet2VnetInboundDecapPaValidateSinglePortTest): """ Inbound Vnet to Vnet scenario test case with @@ -286,8 +284,9 @@ def configureTest(self): self.eni_mac_map_create(eni_id, self.rx_host.client.mac) # ENI MAC # Inbound routing PA Validate + addr_mask = self.tx_host.ip_prefix.split('/') self.inbound_routing_decap_create(eni_id, vni=self.tx_host.client.vni, - sip=self.tx_host.ip, sip_mask="255.255.255.0") + sip=addr_mask[0], sip_mask=num_to_dotted_quad(addr_mask[1])) def vnet2VnetInboundNegativeTest(self): """ @@ -314,7 +313,6 @@ def vnet2VnetInboundNegativeTest(self): @group("draft") -@skipIf(test_param_get('target') == 'bmv2', "Blocked on BMv2 by Issue #236") class Vnet2VnetInboundDecapSinglePortOverlayIpv6Test(Vnet2VnetInboundDecapSinglePortTest): """ Underlay IPv4 and Overlay IPv6 configs @@ -342,7 +340,7 @@ class Vnet2VnetInboundDecapTwoPortsTest(Vnet2VnetInboundDecapSinglePortTest): def runTest(self): self.configureTest() - self.configure_underlay(self.tx_host, self.rx_host) + # self.configure_underlay(self.tx_host, self.rx_host) self.vnet2VnetInboundRoutingTest(tx_equal_to_rx=False) self.vnet2VnetInboundNegativeTest() @@ -362,13 +360,12 @@ class Vnet2VnetInboundDecapTwoPortsOverlayIpv6Test(Vnet2VnetInboundDecapSinglePo def runTest(self): self.configureTest() - self.configure_underlay(self.tx_host, self.rx_host) + # self.configure_underlay(self.tx_host, self.rx_host) self.vnet2VnetInboundRoutingTest(tx_equal_to_rx=False) @group("draft") -@skipIf(test_param_get('target') == 'bmv2', "Blocked on BMv2 by Issue #236") class Vnet2VnetInboundMultiplePaValidatesSingleEniSinglePortTest(VnetApiEndpoints, VnetTrafficMixin): """ Inbound Vnet to Vnet scenario test case with single eni and @@ -392,7 +389,7 @@ def runTest(self): # Reconfigure configuration for tx equal to rx self.update_configuration_for_tx_equal_to_rx() self.configureTest() - self.configure_underlay(self.tx_host, add_routes=False) + # self.configure_underlay(self.tx_host, add_routes=False) self.vnet2VnetInboundRoutingPositiveTest(tx_equal_to_rx=True) self.vnet2VnetInboundRoutingNegativeTest() @@ -428,7 +425,7 @@ def configureTest(self): self.tx_host_3 = self.define_neighbor_network(port=self.tx_host_0.port, mac=self.tx_host_0.mac, ip="11.0.0.1", - ip_prefix="11.0.0.1/24", + ip_prefix="11.0.0.0/24", peer_port=self.tx_host_0.peer.port, peer_mac=self.tx_host_0.peer.mac, peer_ip=self.tx_host_0.peer.ip, @@ -454,26 +451,30 @@ def configureTest(self): self.eni_mac_map_create(eni_id, self.rx_host.client.mac) # ENI MAC # Inbound routing decap + addr_mask = self.tx_host_3.ip_prefix.split('/') self.inbound_routing_decap_create(eni_id, vni=self.tx_host_3.client.vni, - sip=self.tx_host_3.ip, sip_mask="255.255.255.0") + sip=addr_mask[0], sip_mask=num_to_dotted_quad(addr_mask[1])) # Inbound routing decap PA Validate tx_host_0 + addr_mask = self.tx_host_0.ip_prefix.split('/') self.inbound_routing_decap_validate_create(eni_id, vni=self.tx_host_0.client.vni, - sip=self.tx_host_0.ip, sip_mask="255.255.255.0", + sip=addr_mask[0], sip_mask=num_to_dotted_quad(addr_mask[1]), src_vnet_id=src_vnet_0) # PA validation entry with Permit action tx_host_0 self.pa_validation_create(self.tx_host_0.ip, src_vnet_0) # Inbound routing decap PA Validate tx_host_1 + addr_mask = self.tx_host_1.ip_prefix.split('/') self.inbound_routing_decap_validate_create(eni_id, vni=self.tx_host_1.client.vni, - sip=self.tx_host_1.ip, sip_mask="255.255.255.0", + sip=addr_mask[0], sip_mask=num_to_dotted_quad(addr_mask[1]), src_vnet_id=src_vnet_1) # PA validation entry with Permit action tx_host_1 self.pa_validation_create(self.tx_host_1.ip, src_vnet_1) # Inbound routing decap PA Validate tx_host_2 + addr_mask = self.tx_host_2.ip_prefix.split('/') self.inbound_routing_decap_validate_create(eni_id, vni=self.tx_host_2.client.vni, - sip=self.tx_host_2.ip, sip_mask="255.255.255.0", + sip=addr_mask[0], sip_mask=num_to_dotted_quad(addr_mask[1]), src_vnet_id=src_vnet_2) # PA validation entry with Permit action tx_host_2 self.pa_validation_create(self.tx_host_2.ip, src_vnet_2) @@ -552,7 +553,6 @@ def vnet2VnetInboundRoutingNegativeTest(self): @group("draft") -@skipIf(test_param_get('target') == 'bmv2', "Blocked on BMv2 by Issue #236") class Vnet2VnetInboundMultiplePaValidatesSingleEniSinglePortOverlayIpv6Test(Vnet2VnetInboundMultiplePaValidatesSingleEniSinglePortTest): """ Underlay IPv4 and Overlay IPv6 configs @@ -575,7 +575,7 @@ def runTest(self): # Reconfigure configuration for tx equal to rx self.update_configuration_for_tx_equal_to_rx() self.configureTest() - self.configure_underlay(self.tx_host, add_routes=False) + # self.configure_underlay(self.tx_host, add_routes=False) self.vnet2VnetInboundRoutingPositiveTest(tx_equal_to_rx=True) @@ -610,7 +610,7 @@ def configureTest(self): self.tx_host_3 = self.define_neighbor_network(port=self.tx_host_0.port, mac=self.tx_host_0.mac, ip="11.0.0.1", - ip_prefix="11.0.0.1/24", + ip_prefix="11.0.0.0/24", peer_port=self.tx_host_0.peer.port, peer_mac=self.tx_host_0.peer.mac, peer_ip=self.tx_host_0.peer.ip, @@ -636,26 +636,30 @@ def configureTest(self): self.eni_mac_map_create(eni_id, self.rx_host.client.mac) # ENI MAC # Inbound routing decap + addr_mask = self.tx_host_3.ip_prefix.split('/') self.inbound_routing_decap_create(eni_id, vni=self.tx_host_3.client.vni, - sip=self.tx_host_3.ip, sip_mask="255.255.255.0") + sip=addr_mask[0], sip_mask=num_to_dotted_quad(addr_mask[1])) # Inbound routing decap PA Validate tx_host_0 + addr_mask = self.tx_host_0.ip_prefix.split('/') self.inbound_routing_decap_validate_create(eni_id, vni=self.tx_host_0.client.vni, - sip=self.tx_host_0.ip, sip_mask="255.255.255.0", + sip=addr_mask[0], sip_mask=num_to_dotted_quad(addr_mask[1]), src_vnet_id=src_vnet_0) # PA validation entry with Permit action tx_host_0 self.pa_validation_create(self.tx_host_0.ip, src_vnet_0) # Inbound routing decap PA Validate tx_host_1 + addr_mask = self.tx_host_1.ip_prefix.split('/') self.inbound_routing_decap_validate_create(eni_id, vni=self.tx_host_1.client.vni, - sip=self.tx_host_1.ip, sip_mask="255.255.255.0", + sip=addr_mask[0], sip_mask=num_to_dotted_quad(addr_mask[1]), src_vnet_id=src_vnet_1) # PA validation entry with Permit action tx_host_1 self.pa_validation_create(self.tx_host_1.ip, src_vnet_1) # Inbound routing decap PA Validate tx_host_2 + addr_mask = self.tx_host_2.ip_prefix.split('/') self.inbound_routing_decap_validate_create(eni_id, vni=self.tx_host_2.client.vni, - sip=self.tx_host_2.ip, sip_mask="255.255.255.0", + sip=addr_mask[0], sip_mask=num_to_dotted_quad(addr_mask[1]), src_vnet_id=src_vnet_2) # PA validation entry with Permit action tx_host_2 self.pa_validation_create(self.tx_host_2.ip, src_vnet_2) @@ -678,7 +682,7 @@ class Vnet2VnetInboundMultiplePaValidatesSingleEniTwoPortsTest(Vnet2VnetInboundM def runTest(self): self.configureTest() - self.configure_underlay() + #self.configure_underlay() self.vnet2VnetInboundRoutingPositiveTest(tx_equal_to_rx=False) @@ -720,7 +724,7 @@ class Vnet2VnetInboundMultiplePaValidatesSingleEniTwoPortsOverlayIpv6Test(Vnet2V def runTest(self): self.configureTest() - self.configure_underlay() + #self.configure_underlay() self.vnet2VnetInboundRoutingPositiveTest(tx_equal_to_rx=False) @@ -744,7 +748,6 @@ def configure_underlay(self): @group("draft") -@skipIf(test_param_get('target') == 'bmv2', "Blocked on BMv2 by Issue #236") class Vnet2VnetInboundMultiplePaValidatesMultipleEniSinglePortTest(VnetApiEndpoints, VnetTrafficMixin): """ Inbound Vnet to Vnet scenario test case with @@ -766,7 +769,7 @@ def runTest(self): # Reconfigure configuration for tx equal to rx self.update_configuration_for_tx_equal_to_rx() self.configureTest() - self.configure_underlay(self.tx_host, add_routes=False) + # self.configure_underlay(self.tx_host, add_routes=False) self.vnet2VnetInboundRoutingPositiveTest(tx_equal_to_rx=True) self.vnet2VnetInboundRoutingNegativeTest() @@ -832,12 +835,14 @@ def configureTest(self): self.eni_mac_map_create(eni_id_0, self.rx_host_0.client.mac) # ENI MAC # Inbound routing decap + addr_mask = self.tx_host_2.ip_prefix.split('/') self.inbound_routing_decap_create(eni_id_0, vni=self.tx_host_2.client.vni, - sip=self.tx_host_2.ip, sip_mask="255.255.255.0") + sip=addr_mask[0], sip_mask=num_to_dotted_quad(addr_mask[1])) # Inbound routing decap PA Validate + addr_mask = self.tx_host_0.ip_prefix.split('/') self.inbound_routing_decap_validate_create(eni_id_0, vni=self.tx_host_0.client.vni, - sip=self.tx_host_0.ip, sip_mask="255.255.255.0", + sip=addr_mask[0], sip_mask=num_to_dotted_quad(addr_mask[1]), src_vnet_id=src_vnet_0) # PA validation entry with Permit action self.pa_validation_create(self.tx_host_0.ip, src_vnet_0) @@ -850,8 +855,9 @@ def configureTest(self): self.eni_mac_map_create(eni_id_1, self.rx_host_1.client.mac) # ENI MAC # Inbound routing PA Validate + addr_mask = self.tx_host_1.ip_prefix.split('/') self.inbound_routing_decap_validate_create(eni_id_1, vni=self.tx_host_1.client.vni, - sip=self.tx_host_1.ip, sip_mask="255.255.255.0", + sip=addr_mask[0], sip_mask=num_to_dotted_quad(addr_mask[1]), src_vnet_id=src_vnet_1) # PA validation entry with Permit action self.pa_validation_create(self.tx_host_1.ip, src_vnet_1) @@ -936,7 +942,7 @@ def runTest(self): # Reconfigure configuration for tx equal to rx self.update_configuration_for_tx_equal_to_rx() self.configureTest() - self.configure_underlay(self.tx_host, add_routes=False) + # self.configure_underlay(self.tx_host, add_routes=False) self.vnet2VnetInboundRoutingPositiveTest(tx_equal_to_rx=True) @@ -1001,12 +1007,13 @@ def configureTest(self): self.eni_mac_map_create(eni_id_0, self.rx_host_0.client.mac) # ENI MAC # Inbound routing decap + addr_mask = self.tx_host_2.ip_prefix.split('/') self.inbound_routing_decap_create(eni_id_0, vni=self.tx_host_2.client.vni, - sip=self.tx_host_2.ip, sip_mask="255.255.255.0") + sip=addr_mask[0], sip_mask=num_to_dotted_quad(addr_mask[1])) # Inbound routing decap PA Validate self.inbound_routing_decap_validate_create(eni_id_0, vni=self.tx_host_0.client.vni, - sip=self.tx_host_0.ip, sip_mask="255.255.255.0", + sip=addr_mask[0], sip_mask=num_to_dotted_quad(addr_mask[1]), src_vnet_id=src_vnet_0) # PA validation entry with Permit action self.pa_validation_create(self.tx_host_0.ip, src_vnet_0) @@ -1019,8 +1026,9 @@ def configureTest(self): self.eni_mac_map_create(eni_id_1, self.rx_host_1.client.mac) # ENI MAC # Inbound routing PA Validate + addr_mask = self.tx_host_1.ip_prefix.split('/') self.inbound_routing_decap_validate_create(eni_id_1, vni=self.tx_host_1.client.vni, - sip=self.tx_host_1.ip, sip_mask="255.255.255.0", + sip=addr_mask[0], sip_mask=num_to_dotted_quad(addr_mask[1]), src_vnet_id=src_vnet_1) # PA validation entry with Permit action self.pa_validation_create(self.tx_host_1.ip, src_vnet_1) @@ -1043,7 +1051,7 @@ class Vnet2VnetInboundMultiplePaValidatesMultipleEniTwoPortsTest(Vnet2VnetInboun def runTest(self): self.configureTest() - self.configure_underlay() + # self.configure_underlay() self.vnet2VnetInboundRoutingPositiveTest(tx_equal_to_rx=False) @@ -1080,7 +1088,7 @@ class Vnet2VnetInboundMultiplePaValidatesMultipleEniTwoPortsOverlayIpv6Test(Vnet def runTest(self): self.configureTest() - self.configure_underlay() + # self.configure_underlay() self.vnet2VnetInboundRoutingPositiveTest(tx_equal_to_rx=False) @@ -1100,7 +1108,6 @@ def configure_underlay(self): @group("draft") -@skipIf(test_param_get('target') == 'bmv2', "Blocked on BMv2 by Issue #236") class Vnet2VnetSingleInboundRouteMultiplePaValidateSinglePortTest(VnetApiEndpoints, VnetTrafficMixin): """ Inbound Vnet to Vnet scenario test case with @@ -1114,7 +1121,7 @@ def runTest(self): # Reconfigure configuration for tx equal to rx self.update_configuration_for_tx_equal_to_rx() self.configureTest() - self.configure_underlay(self.tx_host_0, add_routes=False) + # self.configure_underlay(self.tx_host_0, add_routes=False) self.vnet2VnetInboundRoutingTest(tx_equal_to_rx=True) @@ -1183,8 +1190,9 @@ def configureTest(self): self.eni_mac_map_create(eni_id, self.rx_host.client.mac) # ENI MAC # Inbound routing PA Validate + addr_mask = self.tx_host_0.ip_prefix.split('/') self.inbound_routing_decap_validate_create(eni_id, vni=self.tx_host_0.client.vni, - sip=self.tx_host_0.ip, sip_mask="255.255.255.0", + sip=addr_mask[0], sip_mask=num_to_dotted_quad(addr_mask[1]), src_vnet_id=src_vnet) # PA validation entries with Permit action self.pa_validation_create(self.tx_host_0.ip, src_vnet) @@ -1219,7 +1227,6 @@ def vnet2VnetInboundRoutingTest(self, tx_equal_to_rx): @group("draft") -@skipIf(test_param_get('target') == 'bmv2', "Blocked on BMv2 by Issue #236") class Vnet2VnetSingleInboundRouteMultiplePaValidateSinglePortIpv6Test(Vnet2VnetSingleInboundRouteMultiplePaValidateSinglePortTest): """ Underlay IPv4 and Overlay IPv6 configs @@ -1237,7 +1244,7 @@ def runTest(self): # Reconfigure configuration for tx equal to rx self.update_configuration_for_tx_equal_to_rx() self.configureTest() - self.configure_underlay(self.tx_host_0, add_routes=False) + # self.configure_underlay(self.tx_host_0, add_routes=False) self.vnet2VnetInboundRoutingTest(tx_equal_to_rx=True) @@ -1306,8 +1313,9 @@ def configureTest(self): self.eni_mac_map_create(eni_id, self.rx_host.client.mac) # ENI MAC # Inbound routing PA Validate + addr_mask = self.tx_host_0.ip_prefix.split('/') self.inbound_routing_decap_validate_create(eni_id, vni=self.tx_host_0.client.vni, - sip=self.tx_host_0.ip, sip_mask="255.255.255.0", + sip=addr_mask[0], sip_mask=num_to_dotted_quad(addr_mask[1]), src_vnet_id=src_vnet) # PA validation entries with Permit action self.pa_validation_create(self.tx_host_0.ip, src_vnet) @@ -1328,7 +1336,7 @@ class Vnet2VnetSingleInboundRouteMultiplePaValidateTwoPortsTest(Vnet2VnetSingleI def runTest(self): self.configureTest() - self.configure_underlay(self.tx_host_0, self.rx_host) + # self.configure_underlay(self.tx_host_0, self.rx_host) self.vnet2VnetInboundRoutingTest(tx_equal_to_rx=False) @@ -1347,7 +1355,7 @@ class Vnet2VnetSingleInboundRouteMultiplePaValidateTwoPortsIpv6Test(Vnet2VnetSin def runTest(self): self.configureTest() - self.configure_underlay(self.tx_host_0, self.rx_host) + # self.configure_underlay(self.tx_host_0, self.rx_host) self.vnet2VnetInboundRoutingTest(tx_equal_to_rx=False) @@ -1364,7 +1372,7 @@ def runTest(self): # Reconfigure configuration for tx equal to rx self.update_configuration_for_tx_equal_to_rx() self.configureTest() - self.configure_underlay(self.tx_host, add_routes=False) + # self.configure_underlay(self.tx_host, add_routes=False) self.vnet2VnetEniUpTrafficTest(tx_equal_to_rx=True) self.eni_set_admin_state(self.eni_id, "down") @@ -1391,8 +1399,9 @@ def configureTest(self): self.eni_mac_map_create(self.eni_id, self.rx_host.client.mac) # ENI MAC # Inbound routing PA Validate + addr_mask = self.tx_host.ip_prefix.split('/') self.inbound_routing_decap_create(self.eni_id, vni=self.tx_host.client.vni, - sip=self.tx_host.ip, sip_mask="255.255.255.0") + sip=addr_mask[0], sip_mask=num_to_dotted_quad(addr_mask[1])) def vnet2VnetEniUpTrafficTest(self, tx_equal_to_rx): """ @@ -1425,7 +1434,7 @@ class Vnet2VnetInboundEniSetUpDownTwoPortsTest(Vnet2VnetInboundEniSetUpDownSingl def runTest(self): self.configureTest() - self.configure_underlay(self.tx_host, self.rx_host) + # self.configure_underlay(self.tx_host, self.rx_host) self.vnet2VnetEniUpTrafficTest(tx_equal_to_rx=True) self.eni_set_admin_state(self.eni_id, "down") @@ -1435,7 +1444,6 @@ def runTest(self): @group("draft") -@skipIf(test_param_get('target') == 'bmv2', "Blocked on BMv2 by Issue #236") class Vnet2VnetOutboundRouteVnetDirectSinglePortTest(VnetApiEndpoints, VnetTrafficMixin): """ Outbound Vnet to Vnet test scenario with Outbound routing entry @@ -1447,7 +1455,7 @@ def runTest(self): # Reconfigure configuration for tx equal to rx self.update_configuration_for_tx_equal_to_rx() self.configureTest() - self.configure_underlay(self.tx_host, add_routes=False) + # self.configure_underlay(self.tx_host, add_routes=False) self.vnet2VnetOutboundRoutingTest(tx_equal_to_rx=True) self.vnet2VnetOutboundNegativeTest() @@ -1510,7 +1518,6 @@ def vnet2VnetOutboundNegativeTest(self): @group("draft") -@skipIf(test_param_get('target') == 'bmv2', "Blocked on BMv2 by Issue #236") class Vnet2VnetOutboundRouteVnetDirectSinglePortOverlayIpv6Test(Vnet2VnetOutboundRouteVnetDirectSinglePortTest): """ Underlay IPv4 and Overlay IPv6 configs @@ -1579,7 +1586,7 @@ class Vnet2VnetOutboundRouteVnetDirectTwoPortsTest(Vnet2VnetOutboundRouteVnetDir def runTest(self): self.configureTest() - self.configure_underlay(self.tx_host, self.rx_host) + # self.configure_underlay(self.tx_host, self.rx_host) self.vnet2VnetOutboundRoutingTest(tx_equal_to_rx=False) self.vnet2VnetOutboundNegativeTest() @@ -1597,13 +1604,12 @@ class Vnet2VnetOutboundRouteVnetDirectTwoPortsOverlayIpv6Test(Vnet2VnetOutboundR def runTest(self): self.configureTest() - self.configure_underlay(self.tx_host, self.rx_host) + # self.configure_underlay(self.tx_host, self.rx_host) self.vnet2VnetOutboundRoutingTest(tx_equal_to_rx=False) @group("draft") -@skipIf(test_param_get('target') == 'bmv2', "Blocked on BMv2 by Issue #236") class Vnet2VnetOutboundRouteVnetSinglePortTest(VnetApiEndpoints, VnetTrafficMixin): """ Outbound Vnet to Vnet test scenario with outbound routing entry @@ -1615,7 +1621,7 @@ def runTest(self): # Reconfigure configuration for tx equal to rx self.update_configuration_for_tx_equal_to_rx() self.configureTest() - self.configure_underlay(self.tx_host, add_routes=False) + # self.configure_underlay(self.tx_host, add_routes=False) self.vnet2VnetOutboundRoutingTest(tx_equal_to_rx=True) self.vnet2VnetOutboundNegativeTest() @@ -1685,7 +1691,6 @@ def vnet2VnetOutboundNegativeTest(self): @group("draft") -@skipIf(test_param_get('target') == 'bmv2', "Blocked on BMv2 by Issue #236") class Vnet2VnetOutboundRouteVnetSinglePortOverlayIpv6Test(Vnet2VnetOutboundRouteVnetSinglePortTest): """ Underlay IPv4 and Overlay IPv6 configs @@ -1760,7 +1765,7 @@ class Vnet2VnetOutboundRouteVnetTwoPortsTest(Vnet2VnetOutboundRouteVnetSinglePor def runTest(self): self.configureTest() - self.configure_underlay(self.tx_host, self.rx_host) + # self.configure_underlay(self.tx_host, self.rx_host) self.vnet2VnetOutboundRoutingTest(tx_equal_to_rx=False) self.vnet2VnetOutboundNegativeTest() @@ -1778,7 +1783,7 @@ class Vnet2VnetOutboundRouteVnetTwoPortsOverlayIpv6Test(Vnet2VnetOutboundRouteVn def runTest(self): self.configureTest() - self.configure_underlay(self.tx_host, self.rx_host) + # self.configure_underlay(self.tx_host, self.rx_host) self.vnet2VnetOutboundRoutingTest(tx_equal_to_rx=False) @@ -1795,7 +1800,7 @@ def runTest(self): # Reconfigure configuration for tx equal to rx self.update_configuration_for_tx_equal_to_rx() self.configureTest() - self.configure_underlay(self.tx_host, add_routes=False) + # self.configure_underlay(self.tx_host, add_routes=False) self.vnet2VnetEniUpTrafficTest(tx_equal_to_rx=True) self.eni_set_admin_state(self.eni_id, "down") @@ -1861,7 +1866,7 @@ class Vnet2VnetOutboundEniSetUpDownTwoPortsTest(Vnet2VnetOutboundEniSetUpDownSin def runTest(self): self.configureTest() - self.configure_underlay(self.tx_host, self.rx_host) + # self.configure_underlay(self.tx_host, self.rx_host) self.vnet2VnetEniUpTrafficTest(tx_equal_to_rx=True) self.eni_set_admin_state(self.eni_id, "down") @@ -1882,7 +1887,7 @@ class Vnet2VnetOutboundRouteDirectSinglePortTest(VnetApiEndpoints, VnetTrafficMi def runTest(self): self.update_configuration_for_tx_equal_to_rx() self.configureTest() - self.configure_underlay(self.tx_host, add_routes=False) + # self.configure_underlay(self.tx_host, add_routes=False) self.outboundRouteDirectTest(tx_equal_to_rx=True) self.outboundRouteDirectNegativeTest() @@ -2014,7 +2019,7 @@ class Vnet2VnetOutboundRouteDirectTwoPortsTest(Vnet2VnetOutboundRouteDirectSingl def runTest(self): self.configureTest() - self.configure_underlay(self.tx_host, self.rx_host) + # self.configure_underlay(self.tx_host, self.rx_host) self.outboundRouteDirectTest(tx_equal_to_rx=False) @@ -2031,13 +2036,12 @@ class Vnet2VnetOutboundRouteDirectTwoPortsOverlayIpv6Test(Vnet2VnetOutboundRoute def runTest(self): self.configureTest() - self.configure_underlay(self.tx_host, self.rx_host) + # self.configure_underlay(self.tx_host, self.rx_host) self.outboundRouteDirectTest(tx_equal_to_rx=False) @group("draft") -@skipIf(test_param_get('target') == 'bmv2', "Blocked on BMv2 by Issue #236") class Vnet2VnetSingleOutboundRouteMultipleCa2PaSinglePortTest(VnetApiEndpoints, VnetTrafficMixin): """ Outbound Vnet to Vnet test scenario with outbound routing entry @@ -2049,7 +2053,7 @@ def runTest(self): # Reconfigure configuration for tx equal to rx self.update_configuration_for_tx_equal_to_rx() self.configureTest() - self.configure_underlay(self.tx_host, add_routes=False) + # self.configure_underlay(self.tx_host, add_routes=False) self.vnet2VnetOutboundRoutingTest(tx_equal_to_rx=True) self.vnet2VnetOutboundNegativeTest() @@ -2305,7 +2309,7 @@ class Vnet2VnetSingleOutboundRouteMultipleCa2PaTwoPortsTest(Vnet2VnetSingleOutbo def runTest(self): self.configureTest() - self.configure_underlay(self.tx_host, self.rx_host_0) + # self.configure_underlay(self.tx_host, self.rx_host_0) self.vnet2VnetOutboundRoutingTest(tx_equal_to_rx=False) @@ -2322,13 +2326,12 @@ class Vnet2VnetSingleOutboundRouteMultipleCa2PaTwoPortsIpv6Test(Vnet2VnetSingleO def runTest(self): self.configureTest() - self.configure_underlay(self.tx_host, self.rx_host_0) + # self.configure_underlay(self.tx_host, self.rx_host_0) self.vnet2VnetOutboundRoutingTest(tx_equal_to_rx=False) @group("draft") -@skipIf(test_param_get('target') == 'bmv2', "Blocked on BMv2 by Issue #236") class Vnet2VnetOutboundDstVnetIdRouteVnetSinglePortTest(VnetApiEndpoints, VnetTrafficMixin): """ Outbound Vnet to Vnet test scenario that verifies @@ -2340,7 +2343,7 @@ class Vnet2VnetOutboundDstVnetIdRouteVnetSinglePortTest(VnetApiEndpoints, VnetTr def runTest(self): self.update_configuration_for_tx_equal_to_rx() self.configureTest() - self.configure_underlay(self.tx_host, add_routes=False) + # self.configure_underlay(self.tx_host, add_routes=False) self.vnet2VnetOutboundDstVnetIdTrueTest(tx_equal_to_rx=True) self.vnet2VnetOutboundDstVnetIdFalseTest(tx_equal_to_rx=True) @@ -2417,7 +2420,6 @@ def vnet2VnetOutboundDstVnetIdFalseTest(self, tx_equal_to_rx): @group("draft") -@skipIf(test_param_get('target') == 'bmv2', "Blocked on BMv2 by Issue #236") class Vnet2VnetOutboundDstVnetIdRouteVnetSinglePortOverlayIpv6Test(Vnet2VnetOutboundDstVnetIdRouteVnetSinglePortTest): """ Underlay IPv4 and Overlay IPv6 configs @@ -2496,7 +2498,7 @@ class Vnet2VnetOutboundDstVnetIdRouteVnetTwoPortsTest(Vnet2VnetOutboundDstVnetId def runTest(self): self.configureTest() - self.configure_underlay(self.tx_host, self.rx_host_0) + # self.configure_underlay(self.tx_host, self.rx_host_0) self.vnet2VnetOutboundDstVnetIdTrueTest(tx_equal_to_rx=False) self.vnet2VnetOutboundDstVnetIdFalseTest(tx_equal_to_rx=False) @@ -2515,14 +2517,13 @@ class Vnet2VnetOutboundDstVnetIdRouteVnetTwoPortsOverlayIpv6Test(Vnet2VnetOutbou def runTest(self): self.configureTest() - self.configure_underlay(self.tx_host, self.rx_host_0) + # self.configure_underlay(self.tx_host, self.rx_host_0) self.vnet2VnetOutboundDstVnetIdTrueTest(tx_equal_to_rx=False) self.vnet2VnetOutboundDstVnetIdFalseTest(tx_equal_to_rx=False) @group("draft") -@skipIf(test_param_get('target') == 'bmv2', "Blocked on BMv2 by Issue #236") class Vnet2VnetOutboundDstVnetIdRouteVnetDirectSinglePortTest(Vnet2VnetOutboundDstVnetIdRouteVnetSinglePortTest): """ Outbound Vnet to Vnet test scenario that verifies @@ -2534,7 +2535,7 @@ class Vnet2VnetOutboundDstVnetIdRouteVnetDirectSinglePortTest(Vnet2VnetOutboundD def runTest(self): self.update_configuration_for_tx_equal_to_rx() self.configureTest() - self.configure_underlay(self.tx_host, add_routes=False) + # self.configure_underlay(self.tx_host, add_routes=False) self.vnet2VnetOutboundDstVnetIdTrueTest(tx_equal_to_rx=True) self.vnet2VnetOutboundDstVnetIdFalseTest(tx_equal_to_rx=True) @@ -2596,7 +2597,6 @@ def configureTest(self): @group("draft") -@skipIf(test_param_get('target') == 'bmv2', "Blocked on BMv2 by Issue #236") class Vnet2VnetOutboundDstVnetIdRouteVnetDirectSinglePortOverlayIpv6Test(Vnet2VnetOutboundDstVnetIdRouteVnetDirectSinglePortTest): """ Underlay IPv4 and Overlay IPv6 configs @@ -2677,7 +2677,7 @@ class Vnet2VnetOutboundDstVnetIdRouteVnetDirectTwoPortsTest(Vnet2VnetOutboundDst def runTest(self): self.configureTest() - self.configure_underlay(self.tx_host, self.rx_host_0) + # self.configure_underlay(self.tx_host, self.rx_host_0) self.vnet2VnetOutboundDstVnetIdTrueTest(tx_equal_to_rx=False) self.vnet2VnetOutboundDstVnetIdFalseTest(tx_equal_to_rx=False) @@ -2696,7 +2696,7 @@ class Vnet2VnetOutboundDstVnetIdRouteVnetDirectTwoPortstOverlayIpv6Test(Vnet2Vne def runTest(self): self.configureTest() - self.configure_underlay(self.tx_host, self.rx_host_0) + # self.configure_underlay(self.tx_host, self.rx_host_0) self.vnet2VnetOutboundDstVnetIdTrueTest(tx_equal_to_rx=False) self.vnet2VnetOutboundDstVnetIdFalseTest(tx_equal_to_rx=False) @@ -2714,7 +2714,7 @@ class Vnet2VnetInboundOutboundMultipleConfigsSinglePortTest(VnetApiEndpoints, Vn def runTest(self): self.update_configuration_for_tx_equal_to_rx() self.configureTest() - self.configure_underlay(self.host_0, self.host_2, add_routes=False) + # self.configure_underlay(self.host_0, self.host_2, add_routes=False) self.outboundHost0toHost2Test(tx_equal_to_rx=True) self.inboundHost2toHost0Test(tx_equal_to_rx=True) @@ -2780,8 +2780,9 @@ def configureTest(self): self.eni_mac_map_create(eni_id_3, self.host_3.client.mac) # ENI 0 inbound/outbound routing + addr_mask = self.host_2.ip_prefix.split('/') self.inbound_routing_decap_validate_create(eni_id=eni_id_0, vni=self.host_2.client.vni, - sip=self.host_2.ip, sip_mask="255.255.255.0", + sip=addr_mask[0], sip_mask=num_to_dotted_quad(addr_mask[1]), src_vnet_id=host_2_vnet) self.pa_validation_create(sip=self.host_2.ip, vnet_id=host_2_vnet) @@ -2794,8 +2795,9 @@ def configureTest(self): overlay_dmac=self.host_2.client.mac) # ENI 3 inbound/outbound routing + addr_mask = self.host_1.ip_prefix.split('/') self.inbound_routing_decap_validate_create(eni_id=eni_id_3, vni=self.host_1.client.vni, - sip=self.host_1.ip, sip_mask="255.255.255.0", + sip=addr_mask[0], sip_mask=num_to_dotted_quad(addr_mask[1]), src_vnet_id=host_1_vnet) self.pa_validation_create(sip=self.host_1.ip, vnet_id=host_1_vnet) @@ -2916,8 +2918,9 @@ def configureTest(self): self.eni_mac_map_create(eni_id_3, self.host_3.client.mac) # ENI 0 inbound/outbound routing + addr_mask = self.host_2.ip_prefix.split('/') self.inbound_routing_decap_validate_create(eni_id=eni_id_0, vni=self.host_2.client.vni, - sip=self.host_2.ip, sip_mask="255.255.255.0", + sip=addr_mask[0], sip_mask=num_to_dotted_quad(addr_mask[1]), src_vnet_id=host_2_vnet) self.pa_validation_create(sip=self.host_2.ip, vnet_id=host_2_vnet) @@ -2930,8 +2933,9 @@ def configureTest(self): overlay_dmac=self.host_2.client.mac) # ENI 3 inbound/outbound routing + addr_mask = self.host_1.ip_prefix.split('/') self.inbound_routing_decap_validate_create(eni_id=eni_id_3, vni=self.host_1.client.vni, - sip=self.host_1.ip, sip_mask="255.255.255.0", + sip=addr_mask[0], sip_mask=num_to_dotted_quad(addr_mask[1]), src_vnet_id=host_1_vnet) self.pa_validation_create(sip=self.host_1.ip, vnet_id=host_1_vnet) @@ -2955,8 +2959,8 @@ class Vnet2VnetInboundOutboundMultipleConfigsTwoPortsTest(Vnet2VnetInboundOutbou def runTest(self): self.configureTest() - self.configure_underlay(self.host_0, self.host_2, - add_routes=True) + # self.configure_underlay(self.host_0, self.host_2, + # add_routes=True) self.outboundHost0toHost2Test(tx_equal_to_rx=False) self.inboundHost2toHost0Test(tx_equal_to_rx=False) @@ -2977,8 +2981,8 @@ class Vnet2VnetInboundOutboundMultipleConfigsTwoPortsOverlayIpv6Test(Vnet2VnetIn def runTest(self): self.configureTest() - self.configure_underlay(self.host_0, self.host_2, - add_routes=True) + # self.configure_underlay(self.host_0, self.host_2, + # add_routes=True) self.outboundHost0toHost2Test(tx_equal_to_rx=False) self.inboundHost2toHost0Test(tx_equal_to_rx=False) @@ -2988,7 +2992,6 @@ def runTest(self): @group("draft") -@skipIf(test_param_get('target') == 'bmv2', "Blocked on BMv2 by Issue #236") class Vnet2VnetOutboundMultipleEniSameIpPrefixSinglePortTest(VnetApiEndpoints, VnetTrafficMixin): """ Outbound Vnet to Vnet test scenario when multiple ENI and @@ -2999,7 +3002,7 @@ class Vnet2VnetOutboundMultipleEniSameIpPrefixSinglePortTest(VnetApiEndpoints, V def runTest(self): self.update_configuration_for_tx_equal_to_rx() self.configureTest() - self.configure_underlay(self.tx_host_0, add_routes=False) + # self.configure_underlay(self.tx_host_0, add_routes=False) self.outboundEni0Test(tx_equal_to_rx=True) self.outboundEni1Test(tx_equal_to_rx=True) @@ -3160,7 +3163,6 @@ def outboundEni2Test(self, tx_equal_to_rx): @group("draft") -@skipIf(test_param_get('target') == 'bmv2', "Blocked on BMv2 by Issue #236") class Vnet2VnetOutboundMultipleEniSameIpPrefixSinglePortOverlayIpv6Test(Vnet2VnetOutboundMultipleEniSameIpPrefixSinglePortTest): """ Underlay IPv4 and Overlay IPv6 configs @@ -3304,7 +3306,7 @@ class Vnet2VnetOutboundMultipleEniSameIpPrefixTwoPortsTest(Vnet2VnetOutboundMult def runTest(self): self.configureTest() - self.configure_underlay(self.tx_host_0, self.rx_host_0) + # self.configure_underlay(self.tx_host_0, self.rx_host_0) self.outboundEni0Test(tx_equal_to_rx=False) self.outboundEni1Test(tx_equal_to_rx=False) @@ -3323,7 +3325,7 @@ class Vnet2VnetOutboundMultipleEniSameIpPrefixTwoPortsOverlayIpv6Test(Vnet2VnetO def runTest(self): self.configureTest() - self.configure_underlay(self.tx_host_0, self.rx_host_0) + # self.configure_underlay(self.tx_host_0, self.rx_host_0) self.outboundEni0Test(tx_equal_to_rx=False) self.outboundEni1Test(tx_equal_to_rx=False) @@ -3331,7 +3333,6 @@ def runTest(self): @group("draft") -@skipIf(test_param_get('target') == 'bmv2', "Blocked on BMv2 by Issue #236") class Vnet2VnetOutboundSingleEniMultipleIpPrefixSinglePortTest(VnetApiEndpoints, VnetTrafficMixin): """ Outbound Vnet to Vnet test scenario with single ENI and @@ -3342,7 +3343,7 @@ class Vnet2VnetOutboundSingleEniMultipleIpPrefixSinglePortTest(VnetApiEndpoints, def runTest(self): self.update_configuration_for_tx_equal_to_rx() self.configureTest() - self.configure_underlay(self.tx_host, add_routes=False) + # self.configure_underlay(self.tx_host, add_routes=False) self.singleEniToOutboundVm1Test(tx_equal_to_rx=True) self.singleEniToOutboundVm2Test(tx_equal_to_rx=True) @@ -3489,7 +3490,6 @@ def singleEniToOutboundVm3Test(self, tx_equal_to_rx): @group("draft") -@skipIf(test_param_get('target') == 'bmv2', "Blocked on BMv2 by Issue #236") class Vnet2VnetOutboundSingleEniMultipleIpPrefixSinglePortOverlayIpv6Test(Vnet2VnetOutboundSingleEniMultipleIpPrefixSinglePortTest): """ Underlay IPv4 and Overlay IPv6 configs @@ -3601,7 +3601,7 @@ class Vnet2VnetOutboundSingleEniMultipleIpPrefixTwoPortsTest(Vnet2VnetOutboundSi def runTest(self): self.configureTest() - self.configure_underlay(self.tx_host, self.rx_host_0) + # self.configure_underlay(self.tx_host, self.rx_host_0) self.singleEniToOutboundVm1Test(tx_equal_to_rx=False) self.singleEniToOutboundVm2Test(tx_equal_to_rx=False) @@ -3620,7 +3620,7 @@ class Vnet2VnetOutboundSingleEniMultipleIpPrefixTwoPortsOverlayIpv6Test(Vnet2Vne def runTest(self): self.configureTest() - self.configure_underlay(self.tx_host, self.rx_host_0) + # self.configure_underlay(self.tx_host, self.rx_host_0) self.singleEniToOutboundVm1Test(tx_equal_to_rx=False) self.singleEniToOutboundVm2Test(tx_equal_to_rx=False) @@ -3628,7 +3628,6 @@ def runTest(self): @group("draft") -@skipIf(test_param_get('target') == 'bmv2', "Blocked on BMv2 by Issue #236") class Vnet2VnetOutboundSameCaPaIpPrefixesSinglePortTest(VnetApiEndpoints, VnetTrafficMixin): """ Outbound Vnet to Vnet test scenario with the same @@ -3638,7 +3637,7 @@ class Vnet2VnetOutboundSameCaPaIpPrefixesSinglePortTest(VnetApiEndpoints, VnetTr def runTest(self): self.update_configuration_for_tx_equal_to_rx() self.configureTest() - self.configure_underlay(self.tx_host, add_routes=False) + # self.configure_underlay(self.tx_host, add_routes=False) self.vnet2VnetOutboundRouteVnetTest(tx_equal_to_rx=True) @@ -3702,6 +3701,6 @@ class Vnet2VnetOutboundSameCaPaIpPrefixesTwoPortsTest(Vnet2VnetOutboundSameCaPaI def runTest(self): self.configureTest() - self.configure_underlay(self.tx_host, self.rx_host) + # self.configure_underlay(self.tx_host, self.rx_host) self.vnet2VnetOutboundRouteVnetTest(tx_equal_to_rx=False) From d3725ffd99a47059fa0e4463f416f318aebee49c Mon Sep 17 00:00:00 2001 From: Riff Date: Tue, 9 Apr 2024 17:51:50 -0700 Subject: [PATCH 23/32] [build] Fix SAI challenger build break. (#551) --- test/SAI-Challenger | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/SAI-Challenger b/test/SAI-Challenger index ccff50f4a..46b4c330f 160000 --- a/test/SAI-Challenger +++ b/test/SAI-Challenger @@ -1 +1 @@ -Subproject commit ccff50f4ae7371b7ece63ecab9866ee0f617ea45 +Subproject commit 46b4c330fcf5cc8422043b9186a1a10f9d66a74b From 57763e9297989d0a2aef039690b78556fda30c7a Mon Sep 17 00:00:00 2001 From: Riff Date: Wed, 10 Apr 2024 08:56:51 -0700 Subject: [PATCH 24/32] [dash-p4] Add VXLAN tunnel to avoid build break in swss. (#552) ## Problems With recent tunnel update, the SAI API generated by current P4 code will have the VXLAN_DECAP_* attributes on inbound routing table renamed to TUNNEL_DECAP_*. However, these 2 attributes are already used by SWSS, hence renaming then will cause build break in SWSS. ## What we are doing in this change This change adds the vxlan decap actions back as dummy actions, so the old attributes will be generated as before and buy us time for swss to update the code. ![image](https://github.com/sonic-net/DASH/assets/1533278/09f65623-0d28-422d-91a8-dcf901d5e927) --- dash-pipeline/bmv2/dash_inbound.p4 | 2 +- dash-pipeline/bmv2/dash_pipeline.p4 | 19 +++++++++++++++---- dash-pipeline/bmv2/dash_tunnel.p4 | 4 ++-- 3 files changed, 18 insertions(+), 7 deletions(-) diff --git a/dash-pipeline/bmv2/dash_inbound.p4 b/dash-pipeline/bmv2/dash_inbound.p4 index 6e8de6939..40148d3c6 100644 --- a/dash-pipeline/bmv2/dash_inbound.p4 +++ b/dash-pipeline/bmv2/dash_inbound.p4 @@ -34,7 +34,7 @@ control inbound(inout headers_t hdr, ConntrackOut.apply(hdr, meta); #endif //PNA_CONNTRACK - tunnel_encap(hdr, + do_tunnel_encap(hdr, meta, meta.overlay_data.dmac, meta.encap_data.underlay_dmac, diff --git a/dash-pipeline/bmv2/dash_pipeline.p4 b/dash-pipeline/bmv2/dash_pipeline.p4 index 2961f3d5c..78f7b5e00 100644 --- a/dash-pipeline/bmv2/dash_pipeline.p4 +++ b/dash-pipeline/bmv2/dash_pipeline.p4 @@ -171,7 +171,16 @@ control dash_ingress( action permit() { } - action tunnel_decap_pa_validate(@SaiVal[type="sai_object_id_t"] bit<16> src_vnet_id) { + action vxlan_decap() {} + action vxlan_decap_pa_validate() {} + + action tunnel_decap(inout headers_t hdr, + inout metadata_t meta) { + } + + action tunnel_decap_pa_validate(inout headers_t hdr, + inout metadata_t meta, + @SaiVal[type="sai_object_id_t"] bit<16> src_vnet_id) { meta.vnet_id = src_vnet_id; } @@ -198,8 +207,10 @@ control dash_ingress( hdr.u0_ipv4.src_addr : ternary @SaiVal[name = "sip", type="sai_ip_address_t"]; } actions = { + vxlan_decap; // Deprecated, but cannot be removed until SWSS is updated. + vxlan_decap_pa_validate; // Deprecated, but cannot be removed until SWSS is updated. tunnel_decap(hdr, meta); - tunnel_decap_pa_validate; + tunnel_decap_pa_validate(hdr, meta); @defaultonly deny; } @@ -270,12 +281,12 @@ control dash_ingress( meta.eni_data.dscp = (bit<6>)hdr.u0_ipv4.diffserv; if (meta.direction == dash_direction_t.OUTBOUND) { - tunnel_decap(hdr, meta); + do_tunnel_decap(hdr, meta); } else if (meta.direction == dash_direction_t.INBOUND) { switch (inbound_routing.apply().action_run) { tunnel_decap_pa_validate: { pa_validation.apply(); - tunnel_decap(hdr, meta); + do_tunnel_decap(hdr, meta); } } } diff --git a/dash-pipeline/bmv2/dash_tunnel.p4 b/dash-pipeline/bmv2/dash_tunnel.p4 index a83b05ae7..4d39f5e65 100644 --- a/dash-pipeline/bmv2/dash_tunnel.p4 +++ b/dash-pipeline/bmv2/dash_tunnel.p4 @@ -211,7 +211,7 @@ PUSH_VXLAN_TUNNEL_DEF(u1, u0) PUSH_NVGRE_TUNNEL_DEF(u0, customer) PUSH_NVGRE_TUNNEL_DEF(u1, u0) -#define tunnel_encap(hdr, \ +#define do_tunnel_encap(hdr, \ meta, \ overlay_dmac, \ underlay_dmac, \ @@ -266,7 +266,7 @@ PUSH_NVGRE_TUNNEL_DEF(u1, u0) reparse it. It is also assumed, that if DASH pushes more than one tunnel, they won't need to pop them */ -action tunnel_decap(inout headers_t hdr, inout metadata_t meta) { +action do_tunnel_decap(inout headers_t hdr, inout metadata_t meta) { hdr.u0_ethernet.setInvalid(); hdr.u0_ipv4.setInvalid(); hdr.u0_ipv6.setInvalid(); From 2f9594d422dfc8782eab988e3f492e359c25b58a Mon Sep 17 00:00:00 2001 From: Riff Date: Wed, 17 Apr 2024 16:39:21 -0700 Subject: [PATCH 25/32] [dash-p4] Update DASH p4 for support the latest metering design. (#550) To support the latest metering design, we are updating the DASH p4 code to generate the SAI header file as well as updating how the metering pipeline works. The latest metering HLD is shown here: https://github.com/sonic-net/DASH/pull/544 --- dash-pipeline/SAI/sai_api_gen.py | 4 +- dash-pipeline/bmv2/dash_metadata.p4 | 19 +++---- dash-pipeline/bmv2/dash_pipeline.p4 | 27 +++++++--- dash-pipeline/bmv2/dash_routing_types.p4 | 53 ++++++++----------- dash-pipeline/bmv2/stages/metering_update.p4 | 44 +++++++-------- .../functional/ptf/sai_dash_utils.py | 14 ++--- test/test-cases/functional/ptf/saidashacl.py | 4 +- .../functional/ptf/saidashvnet_sanity.py | 4 +- .../saic/config_bidir_setup_commands.py | 39 ++++++++------ .../saic/config_inbound_setup_commands.py | 12 ++++- .../saic/config_outbound_setup_commands.json | 14 +++-- .../sai-api/test_sai_api_vnet_in_route.py | 6 ++- .../sai-api/test_sai_api_vnet_out_route.py | 8 +-- ..._outbound_small_scale_config_via_dpugen.py | 7 ++- ..._small_scale_config_via_dpugen_create.json | 28 +++++----- .../saic/test_sai_vnet_outbound_scale.py | 8 +-- .../saic/vnet_inbound_setup_commands.json | 6 ++- .../vnet_outbound_setup_commands_scale.json | 40 ++++++-------- .../vnet_outbound_setup_commands_simple.json | 7 ++- ...et_route_setup_commands_bidirectional.json | 40 ++++++-------- ...t_route_setup_commands_unidirectional.json | 14 +++-- 21 files changed, 196 insertions(+), 202 deletions(-) diff --git a/dash-pipeline/SAI/sai_api_gen.py b/dash-pipeline/SAI/sai_api_gen.py index b0ab76e0e..8166bd05b 100755 --- a/dash-pipeline/SAI/sai_api_gen.py +++ b/dash-pipeline/SAI/sai_api_gen.py @@ -701,8 +701,8 @@ def parse_p4rt(self, p4rt_table_action: Dict[str, Any], sai_enums: List[SAIEnum] }, "params": [ { "id": 1, "name": "dst_vnet_id", "bitwidth": 16 }, - { "id": 2, "name": "meter_policy_en", "bitwidth": 1 }, - { "id": 3, "name": "meter_class", "bitwidth": 16 } + { "id": 2, "name": "meter_class_or", "bitwidth": 32 }, + { "id": 3, "name": "meter_class_and", "bitwidth": 32 } ] } ''' diff --git a/dash-pipeline/bmv2/dash_metadata.p4 b/dash-pipeline/bmv2/dash_metadata.p4 index 005068e1e..94fa9e40a 100644 --- a/dash-pipeline/bmv2/dash_metadata.p4 +++ b/dash-pipeline/bmv2/dash_metadata.p4 @@ -67,10 +67,17 @@ struct eni_data_t { IPv6Address pl_sip; IPv6Address pl_sip_mask; IPv4Address pl_underlay_sip; - bit<6> dscp; + bit<6> dscp; dash_tunnel_dscp_mode_t dscp_mode; } +struct meter_context_t { + bit<32> meter_class_or; + bit<32> meter_class_and; + bit<16> meter_policy_id; + IPv4ORv6Address meter_policy_lookup_ip; +} + struct encap_data_t { bit<24> vni; bit<24> dest_vnet_vni; @@ -162,17 +169,10 @@ struct metadata_t { bit<16> stage3_dash_acl_group_id; bit<16> stage4_dash_acl_group_id; bit<16> stage5_dash_acl_group_id; - bit<1> meter_policy_en; - bit<1> mapping_meter_class_override; - bit<16> meter_policy_id; - bit<16> policy_meter_class; - bit<16> route_meter_class; - bit<16> mapping_meter_class; - bit<16> meter_class; - bit<32> meter_bucket_index; bit<16> tunnel_pointer; bool is_fast_path_icmp_flow_redirection_packet; bit<1> fast_path_icmp_flow_redirection_disabled; + meter_context_t meter_context; // HA ha_data_t ha; @@ -187,6 +187,7 @@ struct metadata_t { bool dropped; encap_data_t encap_data; overlay_rewrite_data_t overlay_data; + bit<32> meter_class; } #endif /* _SIRIUS_METADATA_P4_ */ diff --git a/dash-pipeline/bmv2/dash_pipeline.p4 b/dash-pipeline/bmv2/dash_pipeline.p4 index 78f7b5e00..fd48195ac 100644 --- a/dash-pipeline/bmv2/dash_pipeline.p4 +++ b/dash-pipeline/bmv2/dash_pipeline.p4 @@ -138,17 +138,23 @@ control dash_ingress( if (meta.is_overlay_ip_v6 == 1) { if (meta.direction == dash_direction_t.OUTBOUND) { ACL_GROUPS_COPY_TO_META(outbound_v6); + meta.meter_context.meter_policy_lookup_ip = meta.dst_ip_addr; } else { ACL_GROUPS_COPY_TO_META(inbound_v6); + meta.meter_context.meter_policy_lookup_ip = meta.src_ip_addr; } - meta.meter_policy_id = v6_meter_policy_id; + + meta.meter_context.meter_policy_id = v6_meter_policy_id; } else { if (meta.direction == dash_direction_t.OUTBOUND) { ACL_GROUPS_COPY_TO_META(outbound_v4); + meta.meter_context.meter_policy_lookup_ip = meta.dst_ip_addr; } else { ACL_GROUPS_COPY_TO_META(inbound_v4); + meta.meter_context.meter_policy_lookup_ip = meta.src_ip_addr; } - meta.meter_policy_id = v4_meter_policy_id; + + meta.meter_context.meter_policy_id = v4_meter_policy_id; } meta.ha.ha_scope_id = ha_scope_id; @@ -175,13 +181,19 @@ control dash_ingress( action vxlan_decap_pa_validate() {} action tunnel_decap(inout headers_t hdr, - inout metadata_t meta) { + inout metadata_t meta, + bit<32> meter_class_or, + @SaiVal[default_value="4294967295"] bit<32> meter_class_and) { + set_meter_attrs(meta, meter_class_or, meter_class_and); } action tunnel_decap_pa_validate(inout headers_t hdr, inout metadata_t meta, - @SaiVal[type="sai_object_id_t"] bit<16> src_vnet_id) { + @SaiVal[type="sai_object_id_t"] bit<16> src_vnet_id, + bit<32> meter_class_or, + @SaiVal[default_value="4294967295"] bit<32> meter_class_and) { meta.vnet_id = src_vnet_id; + set_meter_attrs(meta, meter_class_or, meter_class_and); } @SaiTable[name = "pa_validation", api = "dash_pa_validation"] @@ -280,17 +292,16 @@ control dash_ingress( meta.eni_data.dscp_mode = dash_tunnel_dscp_mode_t.PRESERVE_MODEL; meta.eni_data.dscp = (bit<6>)hdr.u0_ipv4.diffserv; - if (meta.direction == dash_direction_t.OUTBOUND) { - do_tunnel_decap(hdr, meta); - } else if (meta.direction == dash_direction_t.INBOUND) { + if (meta.direction == dash_direction_t.INBOUND) { switch (inbound_routing.apply().action_run) { tunnel_decap_pa_validate: { pa_validation.apply(); - do_tunnel_decap(hdr, meta); } } } + do_tunnel_decap(hdr, meta); + /* At this point the processing is done on customer headers */ meta.is_overlay_ip_v6 = 0; diff --git a/dash-pipeline/bmv2/dash_routing_types.p4 b/dash-pipeline/bmv2/dash_routing_types.p4 index ab31d5d84..9009e1995 100644 --- a/dash-pipeline/bmv2/dash_routing_types.p4 +++ b/dash-pipeline/bmv2/dash_routing_types.p4 @@ -4,22 +4,13 @@ #include "dash_headers.p4" #include "routing_actions/routing_actions.p4" -action set_route_meter_attrs( +action set_meter_attrs( inout metadata_t meta, - bit<1> meter_policy_en, - bit<16> meter_class) + bit<32> meter_class_or, + bit<32> meter_class_and) { - meta.meter_policy_en = meter_policy_en; - meta.route_meter_class = meter_class; -} - -action set_mapping_meter_attr( - inout metadata_t meta, - in bit<16> meter_class, - in bit<1> meter_class_override) -{ - meta.mapping_meter_class = meter_class; - meta.mapping_meter_class_override = meter_class_override; + meta.meter_context.meter_class_or = meta.meter_context.meter_class_or | meter_class_or; + meta.meter_context.meter_class_and = meta.meter_context.meter_class_and & meter_class_and; } // Routing Type - drop: @@ -35,12 +26,12 @@ action route_vnet( inout headers_t hdr, inout metadata_t meta, @SaiVal[type="sai_object_id_t"] bit<16> dst_vnet_id, - bit<1> meter_policy_en, - bit<16> meter_class) + bit<32> meter_class_or, + @SaiVal[default_value="4294967295"] bit<32> meter_class_and) { 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); + set_meter_attrs(meta, meter_class_or, meter_class_and); } // Routing Type - vnet_direct: @@ -53,14 +44,14 @@ action route_vnet_direct( bit<1> overlay_ip_is_v6, @SaiVal[type="sai_ip_address_t"] IPv4ORv6Address overlay_ip, - bit<1> meter_policy_en, - bit<16> meter_class) + bit<32> meter_class_or, + @SaiVal[default_value="4294967295"] bit<32> meter_class_and) { 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; - set_route_meter_attrs(meta, meter_policy_en, meter_class); + set_meter_attrs(meta, meter_class_or, meter_class_and); } // Routing Type - direct: @@ -69,11 +60,11 @@ action route_vnet_direct( action route_direct( inout headers_t hdr, inout metadata_t meta, - bit<1> meter_policy_en, - bit<16> meter_class) + bit<32> meter_class_or, + @SaiVal[default_value="4294967295"] bit<32> meter_class_and) { meta.target_stage = dash_pipeline_stage_t.ROUTING_ACTION_APPLY; - set_route_meter_attrs(meta, meter_policy_en, meter_class); + set_meter_attrs(meta, meter_class_or, meter_class_and); } // Routing Type - servicetunnel @@ -97,8 +88,8 @@ action route_service_tunnel( @SaiVal[type="sai_dash_encapsulation_t", default_value="SAI_DASH_ENCAPSULATION_VXLAN"] dash_encapsulation_t dash_encapsulation, bit<24> tunnel_key, - bit<1> meter_policy_en, - bit<16> meter_class) + bit<32> meter_class_or, + @SaiVal[default_value="4294967295"] bit<32> meter_class_and) { /* Assume the overlay addresses provided are always IPv6 and the original are IPv4 */ /* assert(overlay_dip_is_v6 == 1 && overlay_sip_is_v6 == 1); @@ -127,7 +118,7 @@ action route_service_tunnel( #endif - set_route_meter_attrs(meta, meter_policy_en, meter_class); + set_meter_attrs(meta, meter_class_or, meter_class_and); } // Routing type - vnet_encap: @@ -137,8 +128,7 @@ action set_tunnel_mapping( @SaiVal[type="sai_ip_address_t"] IPv4Address underlay_dip, EthernetAddress overlay_dmac, bit<1> use_dst_vnet_vni, - bit<16> meter_class, - bit<1> meter_class_override) + bit<32> meter_class_or) { meta.target_stage = dash_pipeline_stage_t.ROUTING_ACTION_APPLY; @@ -150,7 +140,7 @@ action set_tunnel_mapping( underlay_dip = underlay_dip, overlay_dmac = overlay_dmac); - set_mapping_meter_attr(meta, meter_class, meter_class_override); + set_meter_attrs(meta, meter_class_or, 0xffffffff); } // Routing type - privatelink: @@ -162,8 +152,7 @@ action set_private_link_mapping( IPv6Address overlay_dip, @SaiVal[type="sai_dash_encapsulation_t"] dash_encapsulation_t dash_encapsulation, bit<24> tunnel_key, - bit<16> meter_class, - bit<1> meter_class_override) + bit<32> meter_class_or) { meta.target_stage = dash_pipeline_stage_t.ROUTING_ACTION_APPLY; @@ -190,7 +179,7 @@ action set_private_link_mapping( sip_mask = 0xffffffffffffffffffffffff); #endif /* DISABLE_128BIT_ARITHMETIC */ - set_mapping_meter_attr(meta, meter_class, meter_class_override); + set_meter_attrs(meta, meter_class_or, 0xffffffff); } #endif /* _DASH_ROUTING_TYPES_P4_ */ \ No newline at end of file diff --git a/dash-pipeline/bmv2/stages/metering_update.p4 b/dash-pipeline/bmv2/stages/metering_update.p4 index 24877739f..83439fa6b 100644 --- a/dash-pipeline/bmv2/stages/metering_update.p4 +++ b/dash-pipeline/bmv2/stages/metering_update.p4 @@ -20,22 +20,22 @@ control metering_update_stage( @SaiTable[name = "meter_policy", api = "dash_meter", order = 1, isobject="true"] table meter_policy { key = { - meta.meter_policy_id : exact; + meta.meter_context.meter_policy_id : exact; } actions = { check_ip_addr_family; } } - action set_policy_meter_class(bit<16> meter_class) { - meta.policy_meter_class = meter_class; + action set_policy_meter_class(bit<32> meter_class) { + meta.meter_class = meter_class; } @SaiTable[name = "meter_rule", api = "dash_meter", order = 2, isobject="true"] table meter_rule { key = { - meta.meter_policy_id: exact @SaiVal[type="sai_object_id_t", isresourcetype="true", objects="METER_POLICY"]; - hdr.u0_ipv4.dst_addr : ternary @SaiVal[name = "dip", type="sai_ip_address_t"]; + meta.meter_context.meter_policy_id: exact @SaiVal[type="sai_object_id_t", isresourcetype="true", objects="METER_POLICY"]; + meta.meter_context.meter_policy_lookup_ip: ternary @SaiVal[name = "dip", type="sai_ip_address_t"]; } actions = { @@ -47,11 +47,9 @@ control metering_update_stage( // MAX_METER_BUCKET = MAX_ENI(64) * NUM_BUCKETS_PER_ENI(4096) #define MAX_METER_BUCKETS 262144 - DEFINE_BYTE_COUNTER(meter_bucket_outbound, MAX_METER_BUCKETS, name="outbound", action_names="meter_bucket_action", attr_type="counter_attr") - DEFINE_BYTE_COUNTER(meter_bucket_inbound, MAX_METER_BUCKETS, name="inbound", action_names="meter_bucket_action", attr_type="counter_attr") - action meter_bucket_action(@SaiVal[type="sai_uint32_t", skipattr="true"] bit<32> meter_bucket_index) { - meta.meter_bucket_index = meter_bucket_index; - } + DEFINE_BYTE_COUNTER(meter_bucket_outbound, MAX_METER_BUCKETS, name="outbound", action_names="meter_bucket_action", attr_type="stats") + DEFINE_BYTE_COUNTER(meter_bucket_inbound, MAX_METER_BUCKETS, name="inbound", action_names="meter_bucket_action", attr_type="stats") + action meter_bucket_action() {} @SaiTable[name = "meter_bucket", api = "dash_meter", order = 0, isobject="true"] table meter_bucket { @@ -82,29 +80,23 @@ control metering_update_stage( } apply { - if (meta.meter_policy_en == 1) { + meta.meter_class = meta.meter_context.meter_class_or & meta.meter_context.meter_class_and; + + // If the meter class is 0 from the SDN policies, we go through the metering policy. + if (meta.meter_class == 0) { meter_policy.apply(); meter_rule.apply(); } + meter_bucket.apply(); - { - if (meta.meter_policy_en == 1) { - meta.meter_class = meta.policy_meter_class; - } else { - meta.meter_class = meta.route_meter_class; - } - if ((meta.meter_class == 0) || (meta.mapping_meter_class_override == 1)) { - meta.meter_class = meta.mapping_meter_class; + if (meta.meter_class != 0) { + if (meta.direction == dash_direction_t.OUTBOUND) { + UPDATE_COUNTER(meter_bucket_outbound, meta.meter_class); + } else if (meta.direction == dash_direction_t.INBOUND) { + UPDATE_COUNTER(meter_bucket_inbound, meta.meter_class); } } - meter_bucket.apply(); - if (meta.direction == dash_direction_t.OUTBOUND) { - UPDATE_COUNTER(meter_bucket_outbound, meta.meter_bucket_index); - } else if (meta.direction == dash_direction_t.INBOUND) { - UPDATE_COUNTER(meter_bucket_inbound, meta.meter_bucket_index); - } - eni_meter.apply(); } } diff --git a/test/test-cases/functional/ptf/sai_dash_utils.py b/test/test-cases/functional/ptf/sai_dash_utils.py index a5339e837..2a449287a 100644 --- a/test/test-cases/functional/ptf/sai_dash_utils.py +++ b/test/test-cases/functional/ptf/sai_dash_utils.py @@ -249,7 +249,8 @@ def inbound_routing_decap_validate_create(self, eni_id, vni, sip, sip_mask, src_ sip_mask=sai_ipaddress(sip_mask), priority=1) sai_thrift_create_inbound_routing_entry(self.client, inbound_routing_entry, action=SAI_INBOUND_ROUTING_ENTRY_ACTION_TUNNEL_DECAP_PA_VALIDATE, - src_vnet_id=src_vnet_id) + src_vnet_id=src_vnet_id, + meter_class_or=0, meter_class_and=-1) self.assertEqual(self.status(), SAI_STATUS_SUCCESS) self.add_teardown_obj(self.inbound_routing_remove, inbound_routing_entry) return inbound_routing_entry @@ -265,7 +266,8 @@ def inbound_routing_decap_create(self, eni_id, vni, sip, sip_mask): eni_id=eni_id, sip=sai_ipaddress(sip), sip_mask=sai_ipaddress(sip_mask), priority=1) sai_thrift_create_inbound_routing_entry(self.client, inbound_routing_entry, - action=SAI_INBOUND_ROUTING_ENTRY_ACTION_TUNNEL_DECAP) + action=SAI_INBOUND_ROUTING_ENTRY_ACTION_TUNNEL_DECAP, + meter_class_or=0, meter_class_and=-1) self.assertEqual(self.status(), SAI_STATUS_SUCCESS) self.add_teardown_obj(self.inbound_routing_remove, inbound_routing_entry) return inbound_routing_entry @@ -305,7 +307,7 @@ def outbound_routing_vnet_direct_create(self, eni_id, lpm, dst_vnet_id, outbound_routing_entry, dst_vnet_id=dst_vnet_id, action=SAI_OUTBOUND_ROUTING_ENTRY_ACTION_ROUTE_VNET_DIRECT, overlay_ip=sai_ipaddress(overlay_ip), counter_id=counter_id, - meter_policy_en=False, meter_class=0) + meter_class_or=0, meter_class_and=-1) self.assertEqual(self.status(), SAI_STATUS_SUCCESS) self.add_teardown_obj(self.outbound_routing_vnet_direct_remove, outbound_routing_entry) @@ -321,7 +323,7 @@ def outbound_routing_direct_create(self, eni_id, lpm, counter_id=None): destination=sai_ipprefix(lpm)) sai_thrift_create_outbound_routing_entry(self.client, outbound_routing_entry, counter_id=counter_id, action=SAI_OUTBOUND_ROUTING_ENTRY_ACTION_ROUTE_DIRECT, - meter_policy_en=False, meter_class=0) + meter_class_or=0, meter_class_and=-1) self.assertEqual(self.status(), SAI_STATUS_SUCCESS) self.add_teardown_obj(self.outbound_routing_vnet_direct_remove, outbound_routing_entry) @@ -339,7 +341,7 @@ def outbound_routing_vnet_create(self, eni_id, lpm, dst_vnet_id, counter_id=None outbound_routing_entry, dst_vnet_id=dst_vnet_id, counter_id=counter_id, action=SAI_OUTBOUND_ROUTING_ENTRY_ACTION_ROUTE_VNET, - meter_policy_en=False, meter_class=0) + meter_class_or=0, meter_class_and=-1) self.assertEqual(self.status(), SAI_STATUS_SUCCESS) self.add_teardown_obj(self.outbound_routing_vnet_direct_remove, outbound_routing_entry) @@ -359,7 +361,7 @@ def outbound_ca_to_pa_create(self, dst_vnet_id, dip, underlay_dip, underlay_dip=sai_ipaddress(underlay_dip), use_dst_vnet_vni=use_dst_vnet_vni, overlay_dmac=overlay_dmac, - meter_class=0, meter_class_override=False) + meter_class_or=0) self.assertEqual(self.status(), SAI_STATUS_SUCCESS) self.add_teardown_obj(self.outbound_ca_to_pa_remove, ca_to_pa_entry) diff --git a/test/test-cases/functional/ptf/saidashacl.py b/test/test-cases/functional/ptf/saidashacl.py index 1cd4ac4c3..b715d0df7 100644 --- a/test/test-cases/functional/ptf/saidashacl.py +++ b/test/test-cases/functional/ptf/saidashacl.py @@ -243,7 +243,7 @@ def setUpSwitch(self): self.create_entry(sai_thrift_create_outbound_routing_entry, sai_thrift_remove_outbound_routing_entry, self.ore, action=SAI_OUTBOUND_ROUTING_ENTRY_ACTION_ROUTE_VNET, dst_vnet_id=self.vnet, - meter_policy_en=False, meter_class=0) + meter_class_or=0, meter_class_and=-1) underlay_dip = sai_thrift_ip_address_t(addr_family=SAI_IP_ADDR_FAMILY_IPV4, addr=sai_thrift_ip_addr_t(ip4=self.dst_pa_ip)) @@ -252,7 +252,7 @@ def setUpSwitch(self): self.create_entry(sai_thrift_create_outbound_ca_to_pa_entry, sai_thrift_remove_outbound_ca_to_pa_entry, self.ocpe, underlay_dip=underlay_dip, overlay_dmac=self.dst_ca_mac, use_dst_vnet_vni=True, - meter_class=0, meter_class_override=False) + meter_class_or=0) def setupTest(self): self.tests.append(AclRuleTest(self, diff --git a/test/test-cases/functional/ptf/saidashvnet_sanity.py b/test/test-cases/functional/ptf/saidashvnet_sanity.py index e1a435954..91cf1c0c5 100644 --- a/test/test-cases/functional/ptf/saidashvnet_sanity.py +++ b/test/test-cases/functional/ptf/saidashvnet_sanity.py @@ -131,7 +131,7 @@ def configureVnet(self): status = sai_thrift_create_outbound_routing_entry(self.client, self.ore, action=SAI_OUTBOUND_ROUTING_ENTRY_ACTION_ROUTE_VNET, dst_vnet_id=self.vnet, - meter_policy_en=False, meter_class=0) + meter_class_or=0, meter_class_and=-1) assert(status == SAI_STATUS_SUCCESS) underlay_dip = sai_thrift_ip_address_t(addr_family=SAI_IP_ADDR_FAMILY_IPV4, @@ -139,7 +139,7 @@ def configureVnet(self): self.ocpe = sai_thrift_outbound_ca_to_pa_entry_t(switch_id=self.switch_id, dst_vnet_id=self.vnet, dip=dip) status = sai_thrift_create_outbound_ca_to_pa_entry(self.client, self.ocpe, underlay_dip = underlay_dip, overlay_dmac=self.dst_ca_mac, use_dst_vnet_vni = True, - meter_class=0, meter_class_override=False) + meter_class_or=0) assert(status == SAI_STATUS_SUCCESS) print(f"\n{self.__class__.__name__} configureVnet OK") diff --git a/test/test-cases/functional/saic/config_bidir_setup_commands.py b/test/test-cases/functional/saic/config_bidir_setup_commands.py index 0125361d6..eb81c7740 100644 --- a/test/test-cases/functional/saic/config_bidir_setup_commands.py +++ b/test/test-cases/functional/saic/config_bidir_setup_commands.py @@ -264,8 +264,8 @@ "attributes": [ "SAI_OUTBOUND_ROUTING_ENTRY_ATTR_ACTION", "SAI_OUTBOUND_ROUTING_ENTRY_ACTION_ROUTE_VNET", "SAI_OUTBOUND_ROUTING_ENTRY_ATTR_DST_VNET_ID", "$vnet", - "SAI_OUTBOUND_ROUTING_ENTRY_ATTR_METER_POLICY_EN", "False", - "SAI_OUTBOUND_ROUTING_ENTRY_ATTR_METER_CLASS", "0" + "SAI_OUTBOUND_ROUTING_ENTRY_ATTR_METER_CLASS_OR", "0", + "SAI_OUTBOUND_ROUTING_ENTRY_ATTR_METER_CLASS_AND", "-1" ] }, { @@ -280,8 +280,8 @@ "attributes": [ "SAI_OUTBOUND_ROUTING_ENTRY_ATTR_ACTION", "SAI_OUTBOUND_ROUTING_ENTRY_ACTION_ROUTE_VNET", "SAI_OUTBOUND_ROUTING_ENTRY_ATTR_DST_VNET_ID", "$vnet", - "SAI_OUTBOUND_ROUTING_ENTRY_ATTR_METER_POLICY_EN", "False", - "SAI_OUTBOUND_ROUTING_ENTRY_ATTR_METER_CLASS", "0" + "SAI_OUTBOUND_ROUTING_ENTRY_ATTR_METER_CLASS_OR", "0", + "SAI_OUTBOUND_ROUTING_ENTRY_ATTR_METER_CLASS_AND", "-1" ] }, { @@ -296,8 +296,8 @@ "attributes": [ "SAI_OUTBOUND_ROUTING_ENTRY_ATTR_ACTION", "SAI_OUTBOUND_ROUTING_ENTRY_ACTION_ROUTE_VNET", "SAI_OUTBOUND_ROUTING_ENTRY_ATTR_DST_VNET_ID", "$vnet", - "SAI_OUTBOUND_ROUTING_ENTRY_ATTR_METER_POLICY_EN", "False", - "SAI_OUTBOUND_ROUTING_ENTRY_ATTR_METER_CLASS", "0" + "SAI_OUTBOUND_ROUTING_ENTRY_ATTR_METER_CLASS_OR", "0", + "SAI_OUTBOUND_ROUTING_ENTRY_ATTR_METER_CLASS_AND", "-1" ] }, { @@ -316,7 +316,11 @@ "SAI_INBOUND_ROUTING_ENTRY_ATTR_ACTION", "SAI_INBOUND_ROUTING_ENTRY_ACTION_TUNNEL_DECAP_PA_VALIDATE", "SAI_INBOUND_ROUTING_ENTRY_ATTR_SRC_VNET_ID", - "$vnet" + "$vnet", + "SAI_INBOUND_ROUTING_ENTRY_ATTR_METER_CLASS_OR", + "0", + "SAI_INBOUND_ROUTING_ENTRY_ATTR_METER_CLASS_AND", + "-1" ] }, { @@ -335,7 +339,11 @@ "SAI_INBOUND_ROUTING_ENTRY_ATTR_ACTION", "SAI_INBOUND_ROUTING_ENTRY_ACTION_TUNNEL_DECAP_PA_VALIDATE", "SAI_INBOUND_ROUTING_ENTRY_ATTR_SRC_VNET_ID", - "$vnet" + "$vnet", + "SAI_INBOUND_ROUTING_ENTRY_ATTR_METER_CLASS_OR", + "0", + "SAI_INBOUND_ROUTING_ENTRY_ATTR_METER_CLASS_AND", + "-1" ] }, { @@ -354,7 +362,11 @@ "SAI_INBOUND_ROUTING_ENTRY_ATTR_ACTION", "SAI_INBOUND_ROUTING_ENTRY_ACTION_TUNNEL_DECAP_PA_VALIDATE", "SAI_INBOUND_ROUTING_ENTRY_ATTR_SRC_VNET_ID", - "$vnet" + "$vnet", + "SAI_INBOUND_ROUTING_ENTRY_ATTR_METER_CLASS_OR", + "0", + "SAI_INBOUND_ROUTING_ENTRY_ATTR_METER_CLASS_AND", + "-1" ] }, { @@ -370,8 +382,7 @@ "SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_UNDERLAY_DIP", NETWORK_VTEP_IP, "SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_OVERLAY_DMAC", INNER_DST_MAC, "SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_USE_DST_VNET_VNI", "True", - "SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_METER_CLASS", "0", - "SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_METER_CLASS_OVERRIDE", "False" + "SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_METER_CLASS_OR", "0" ] }, { @@ -387,8 +398,7 @@ "SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_UNDERLAY_DIP", NETWORK_VTEP_IP, "SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_OVERLAY_DMAC", INNER_DST_MAC2, "SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_USE_DST_VNET_VNI", "True", - "SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_METER_CLASS", "0", - "SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_METER_CLASS_OVERRIDE", "False" + "SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_METER_CLASS_OR", "0" ] }, { @@ -404,8 +414,7 @@ "SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_UNDERLAY_DIP", ENI_VTEP_IP, "SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_OVERLAY_DMAC", INNER_SRC_MAC, "SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_USE_DST_VNET_VNI", "True", - "SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_METER_CLASS", "0", - "SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_METER_CLASS_OVERRIDE", "False" + "SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_METER_CLASS_OR", "0" ] } ] diff --git a/test/test-cases/functional/saic/config_inbound_setup_commands.py b/test/test-cases/functional/saic/config_inbound_setup_commands.py index 8eeac1460..787e32bdb 100644 --- a/test/test-cases/functional/saic/config_inbound_setup_commands.py +++ b/test/test-cases/functional/saic/config_inbound_setup_commands.py @@ -291,7 +291,11 @@ "SAI_INBOUND_ROUTING_ENTRY_ATTR_ACTION", "SAI_INBOUND_ROUTING_ENTRY_ACTION_TUNNEL_DECAP_PA_VALIDATE", "SAI_INBOUND_ROUTING_ENTRY_ATTR_SRC_VNET_ID", - "$vnet_#1" + "$vnet_#1", + "SAI_INBOUND_ROUTING_ENTRY_ATTR_METER_CLASS_OR", + "0", + "SAI_INBOUND_ROUTING_ENTRY_ATTR_METER_CLASS_AND", + "-1" ] }, { @@ -310,7 +314,11 @@ "SAI_INBOUND_ROUTING_ENTRY_ATTR_ACTION", "SAI_INBOUND_ROUTING_ENTRY_ACTION_TUNNEL_DECAP_PA_VALIDATE", "SAI_INBOUND_ROUTING_ENTRY_ATTR_SRC_VNET_ID", - "$vnet_#1" + "$vnet_#1", + "SAI_INBOUND_ROUTING_ENTRY_ATTR_METER_CLASS_OR", + "0", + "SAI_INBOUND_ROUTING_ENTRY_ATTR_METER_CLASS_AND", + "-1" ] }, { diff --git a/test/test-cases/functional/saic/config_outbound_setup_commands.json b/test/test-cases/functional/saic/config_outbound_setup_commands.json index 2ee4275fb..848946b6b 100644 --- a/test/test-cases/functional/saic/config_outbound_setup_commands.json +++ b/test/test-cases/functional/saic/config_outbound_setup_commands.json @@ -183,8 +183,8 @@ "attributes": [ "SAI_OUTBOUND_ROUTING_ENTRY_ATTR_ACTION", "SAI_OUTBOUND_ROUTING_ENTRY_ACTION_ROUTE_VNET", "SAI_OUTBOUND_ROUTING_ENTRY_ATTR_DST_VNET_ID", "$vnet", - "SAI_OUTBOUND_ROUTING_ENTRY_ATTR_METER_POLICY_EN", "False", - "SAI_OUTBOUND_ROUTING_ENTRY_ATTR_METER_CLASS", "0" + "SAI_OUTBOUND_ROUTING_ENTRY_ATTR_METER_CLASS_OR", "0", + "SAI_OUTBOUND_ROUTING_ENTRY_ATTR_METER_CLASS_AND", "-1" ] }, { @@ -199,8 +199,8 @@ "attributes": [ "SAI_OUTBOUND_ROUTING_ENTRY_ATTR_ACTION", "SAI_OUTBOUND_ROUTING_ENTRY_ACTION_ROUTE_VNET", "SAI_OUTBOUND_ROUTING_ENTRY_ATTR_DST_VNET_ID", "$vnet", - "SAI_OUTBOUND_ROUTING_ENTRY_ATTR_METER_POLICY_EN", "False", - "SAI_OUTBOUND_ROUTING_ENTRY_ATTR_METER_CLASS", "0" + "SAI_OUTBOUND_ROUTING_ENTRY_ATTR_METER_CLASS_OR", "0", + "SAI_OUTBOUND_ROUTING_ENTRY_ATTR_METER_CLASS_AND", "-1" ] }, @@ -217,8 +217,7 @@ "SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_UNDERLAY_DIP", "221.0.2.101", "SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_OVERLAY_DMAC", "00:1b:6e:00:00:01", "SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_USE_DST_VNET_VNI", "True", - "SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_METER_CLASS", "0", - "SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_METER_CLASS_OVERRIDE", "False" + "SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_METER_CLASS_OR", "0" ] }, { @@ -234,8 +233,7 @@ "SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_UNDERLAY_DIP", "221.0.1.11", "SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_OVERLAY_DMAC", "00:1A:C5:00:00:01", "SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_USE_DST_VNET_VNI", "True", - "SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_METER_CLASS", "0", - "SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_METER_CLASS_OVERRIDE", "False" + "SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_METER_CLASS_OR", "0" ] } ] diff --git a/test/test-cases/functional/saic/sai-api/test_sai_api_vnet_in_route.py b/test/test-cases/functional/saic/sai-api/test_sai_api_vnet_in_route.py index be0a57f1b..29e16903b 100644 --- a/test/test-cases/functional/saic/sai-api/test_sai_api_vnet_in_route.py +++ b/test/test-cases/functional/saic/sai-api/test_sai_api_vnet_in_route.py @@ -136,7 +136,11 @@ def test_vnet_inbound_routing_entry_create(self, dpu): "SAI_INBOUND_ROUTING_ENTRY_ATTR_ACTION", "SAI_INBOUND_ROUTING_ENTRY_ACTION_TUNNEL_DECAP_PA_VALIDATE", "SAI_INBOUND_ROUTING_ENTRY_ATTR_SRC_VNET_ID", - "$vnet" + "$vnet", + "SAI_INBOUND_ROUTING_ENTRY_ATTR_METER_CLASS_OR", + "0", + "SAI_INBOUND_ROUTING_ENTRY_ATTR_METER_CLASS_AND", + "-1" ] }, ] diff --git a/test/test-cases/functional/saic/sai-api/test_sai_api_vnet_out_route.py b/test/test-cases/functional/saic/sai-api/test_sai_api_vnet_out_route.py index ecf73212e..5b1134869 100644 --- a/test/test-cases/functional/saic/sai-api/test_sai_api_vnet_out_route.py +++ b/test/test-cases/functional/saic/sai-api/test_sai_api_vnet_out_route.py @@ -128,8 +128,8 @@ def test_vnet_outbound_routing_entry_create(self, dpu): "attributes": [ "SAI_OUTBOUND_ROUTING_ENTRY_ATTR_ACTION", "SAI_OUTBOUND_ROUTING_ENTRY_ACTION_ROUTE_VNET", "SAI_OUTBOUND_ROUTING_ENTRY_ATTR_DST_VNET_ID", "$vnet", - "SAI_OUTBOUND_ROUTING_ENTRY_ATTR_METER_POLICY_EN", "False", - "SAI_OUTBOUND_ROUTING_ENTRY_ATTR_METER_CLASS", "0" + "SAI_OUTBOUND_ROUTING_ENTRY_ATTR_METER_CLASS_OR", "0", + "SAI_OUTBOUND_ROUTING_ENTRY_ATTR_METER_CLASS_AND", "-1" ] }, ] @@ -167,8 +167,8 @@ def test_vnet_outbound_routing_entry_set(self, dpu): "attributes": [ "SAI_OUTBOUND_ROUTING_ENTRY_ATTR_ACTION", "SAI_OUTBOUND_ROUTING_ENTRY_ACTION_ROUTE_VNET", "SAI_OUTBOUND_ROUTING_ENTRY_ATTR_DST_VNET_ID", "$vnet", - "SAI_OUTBOUND_ROUTING_ENTRY_ATTR_METER_POLICY_EN", "False", - "SAI_OUTBOUND_ROUTING_ENTRY_ATTR_METER_CLASS", "0" + "SAI_OUTBOUND_ROUTING_ENTRY_ATTR_METER_CLASS_OR", "0", + "SAI_OUTBOUND_ROUTING_ENTRY_ATTR_METER_CLASS_AND", "-1" ] }, ] diff --git a/test/test-cases/functional/saic/tutorial/test_sai_vnet_outbound_small_scale_config_via_dpugen.py b/test/test-cases/functional/saic/tutorial/test_sai_vnet_outbound_small_scale_config_via_dpugen.py index 5376fa3d1..35b18398d 100755 --- a/test/test-cases/functional/saic/tutorial/test_sai_vnet_outbound_small_scale_config_via_dpugen.py +++ b/test/test-cases/functional/saic/tutorial/test_sai_vnet_outbound_small_scale_config_via_dpugen.py @@ -65,11 +65,10 @@ def make_create_commands(self): "SAI_ENI_ATTR_DASH_TUNNEL_DSCP_MODE", "SAI_DASH_TUNNEL_DSCP_MODE_PRESERVE_MODEL", "SAI_ENI_ATTR_DSCP", "0", "SAI_ENI_ATTR_DISABLE_FAST_PATH_ICMP_FLOW_REDIRECTION", "False", "SAI_ENI_ATTR_HA_SCOPE_ID", "0"]) - ret = add_extra_attrs('SAI_OBJECT_TYPE_OUTBOUND_CA_TO_PA_ENTRY', ret, [ 'SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_METER_CLASS', '0', - 'SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_METER_CLASS_OVERRIDE', 'True' ]) + ret = add_extra_attrs('SAI_OBJECT_TYPE_OUTBOUND_CA_TO_PA_ENTRY', ret, [ 'SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_METER_CLASS_OR', '0' ]) - ret = add_extra_attrs('SAI_OBJECT_TYPE_OUTBOUND_ROUTING_ENTRY', ret, [ 'SAI_OUTBOUND_ROUTING_ENTRY_ATTR_METER_POLICY_EN', 'True', - 'SAI_OUTBOUND_ROUTING_ENTRY_ATTR_METER_CLASS', '0' ]) + ret = add_extra_attrs('SAI_OBJECT_TYPE_OUTBOUND_ROUTING_ENTRY', ret, [ 'SAI_OUTBOUND_ROUTING_ENTRY_ATTR_METER_CLASS_OR', '0', + 'SAI_OUTBOUND_ROUTING_ENTRY_ATTR_METER_CLASS_AND', '-1' ]) return ret def make_remove_commands(self): diff --git a/test/test-cases/functional/saic/tutorial/test_sai_vnet_outbound_small_scale_config_via_dpugen_create.json b/test/test-cases/functional/saic/tutorial/test_sai_vnet_outbound_small_scale_config_via_dpugen_create.json index 225113553..230b4ffca 100644 --- a/test/test-cases/functional/saic/tutorial/test_sai_vnet_outbound_small_scale_config_via_dpugen_create.json +++ b/test/test-cases/functional/saic/tutorial/test_sai_vnet_outbound_small_scale_config_via_dpugen_create.json @@ -272,10 +272,10 @@ "SAI_OUTBOUND_ROUTING_ENTRY_ACTION_ROUTE_VNET", "SAI_OUTBOUND_ROUTING_ENTRY_ATTR_DST_VNET_ID", "$vnet_#5000", - "SAI_OUTBOUND_ROUTING_ENTRY_ATTR_METER_POLICY_EN", - "False", - "SAI_OUTBOUND_ROUTING_ENTRY_ATTR_METER_CLASS", - "0" + "SAI_OUTBOUND_ROUTING_ENTRY_ATTR_METER_CLASS_OR", + "0", + "SAI_OUTBOUND_ROUTING_ENTRY_ATTR_METER_CLASS_AND", + "-1" ] }, { @@ -292,10 +292,10 @@ "SAI_OUTBOUND_ROUTING_ENTRY_ACTION_ROUTE_VNET", "SAI_OUTBOUND_ROUTING_ENTRY_ATTR_DST_VNET_ID", "$vnet_#6000", - "SAI_OUTBOUND_ROUTING_ENTRY_ATTR_METER_POLICY_EN", - "False", - "SAI_OUTBOUND_ROUTING_ENTRY_ATTR_METER_CLASS", - "0" + "SAI_OUTBOUND_ROUTING_ENTRY_ATTR_METER_CLASS_OR", + "0", + "SAI_OUTBOUND_ROUTING_ENTRY_ATTR_METER_CLASS_AND", + "-1" ] }, { @@ -314,10 +314,8 @@ "00:1B:6E:00:00:01", "SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_USE_DST_VNET_VNI", "True", - "SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_METER_CLASS", - "0", - "SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_METER_CLASS_OVERRIDE", - "False" + "SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_METER_CLASS_OR", + "0" ] }, { @@ -336,10 +334,8 @@ "00:1B:6E:18:00:01", "SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_USE_DST_VNET_VNI", "True", - "SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_METER_CLASS", - "0", - "SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_METER_CLASS_OVERRIDE", - "False" + "SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_METER_CLASS_OR", + "0" ] } ] diff --git a/test/test-cases/scale/saic/test_sai_vnet_outbound_scale.py b/test/test-cases/scale/saic/test_sai_vnet_outbound_scale.py index e14bf8aaa..2ac9a1663 100755 --- a/test/test-cases/scale/saic/test_sai_vnet_outbound_scale.py +++ b/test/test-cases/scale/saic/test_sai_vnet_outbound_scale.py @@ -118,11 +118,11 @@ def make_create_vnet_config(self): "SAI_ENI_ATTR_DASH_TUNNEL_DSCP_MODE", "SAI_DASH_TUNNEL_DSCP_MODE_PRESERVE_MODEL", "SAI_ENI_ATTR_DSCP", "0", "SAI_ENI_ATTR_DISABLE_FAST_PATH_ICMP_FLOW_REDIRECTION", "False", "SAI_ENI_ATTR_HA_SCOPE_ID", "0"]) - ret = add_extra_attrs('SAI_OBJECT_TYPE_OUTBOUND_CA_TO_PA_ENTRY', ret, [ 'SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_METER_CLASS', '0', - 'SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_METER_CLASS_OVERRIDE', 'True' ]) + ret = add_extra_attrs('SAI_OBJECT_TYPE_OUTBOUND_CA_TO_PA_ENTRY', ret, [ 'SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_METER_CLASS_OR', '0' ]) + + ret = add_extra_attrs('SAI_OBJECT_TYPE_OUTBOUND_ROUTING_ENTRY', ret, [ 'SAI_OUTBOUND_ROUTING_ENTRY_ATTR_METER_CLASS_OR', '0', + 'SAI_OUTBOUND_ROUTING_ENTRY_ATTR_METER_CLASS_AND', '-1' ]) - ret = add_extra_attrs('SAI_OBJECT_TYPE_OUTBOUND_ROUTING_ENTRY', ret, [ 'SAI_OUTBOUND_ROUTING_ENTRY_ATTR_METER_POLICY_EN', 'True', - 'SAI_OUTBOUND_ROUTING_ENTRY_ATTR_METER_CLASS', '0' ]) return ret def make_remove_vnet_config(self): diff --git a/test/test-cases/scale/saic/vnet_inbound_setup_commands.json b/test/test-cases/scale/saic/vnet_inbound_setup_commands.json index 597c49692..25cbd1364 100644 --- a/test/test-cases/scale/saic/vnet_inbound_setup_commands.json +++ b/test/test-cases/scale/saic/vnet_inbound_setup_commands.json @@ -160,7 +160,11 @@ "SAI_INBOUND_ROUTING_ENTRY_ATTR_ACTION", "SAI_INBOUND_ROUTING_ENTRY_ACTION_TUNNEL_DECAP_PA_VALIDATE", "SAI_INBOUND_ROUTING_ENTRY_ATTR_SRC_VNET_ID", - "$vnet_1" + "$vnet_1", + "SAI_INBOUND_ROUTING_ENTRY_ATTR_METER_CLASS_OR", + "0", + "SAI_INBOUND_ROUTING_ENTRY_ATTR_METER_CLASS_AND", + "-1" ] }, { diff --git a/test/test-cases/scale/saic/vnet_outbound_setup_commands_scale.json b/test/test-cases/scale/saic/vnet_outbound_setup_commands_scale.json index 8013b9ca7..46d85a0b8 100644 --- a/test/test-cases/scale/saic/vnet_outbound_setup_commands_scale.json +++ b/test/test-cases/scale/saic/vnet_outbound_setup_commands_scale.json @@ -221,8 +221,8 @@ "attributes": [ "SAI_OUTBOUND_ROUTING_ENTRY_ATTR_ACTION", "SAI_OUTBOUND_ROUTING_ENTRY_ACTION_ROUTE_VNET", "SAI_OUTBOUND_ROUTING_ENTRY_ATTR_DST_VNET_ID", "$vnet_#0", - "SAI_OUTBOUND_ROUTING_ENTRY_ATTR_METER_POLICY_EN", "False", - "SAI_OUTBOUND_ROUTING_ENTRY_ATTR_METER_CLASS", "0" + "SAI_OUTBOUND_ROUTING_ENTRY_ATTR_METER_CLASS_OR", "0", + "SAI_OUTBOUND_ROUTING_ENTRY_ATTR_METER_CLASS_AND", "-1" ] }, { @@ -237,8 +237,8 @@ "attributes": [ "SAI_OUTBOUND_ROUTING_ENTRY_ATTR_ACTION", "SAI_OUTBOUND_ROUTING_ENTRY_ACTION_ROUTE_VNET", "SAI_OUTBOUND_ROUTING_ENTRY_ATTR_DST_VNET_ID", "$vnet_#1", - "SAI_OUTBOUND_ROUTING_ENTRY_ATTR_METER_POLICY_EN", "False", - "SAI_OUTBOUND_ROUTING_ENTRY_ATTR_METER_CLASS", "0" + "SAI_OUTBOUND_ROUTING_ENTRY_ATTR_METER_CLASS_OR", "0", + "SAI_OUTBOUND_ROUTING_ENTRY_ATTR_METER_CLASS_AND", "-1" ] }, { @@ -253,8 +253,8 @@ "attributes": [ "SAI_OUTBOUND_ROUTING_ENTRY_ATTR_ACTION", "SAI_OUTBOUND_ROUTING_ENTRY_ACTION_ROUTE_VNET", "SAI_OUTBOUND_ROUTING_ENTRY_ATTR_DST_VNET_ID", "$vnet_#2", - "SAI_OUTBOUND_ROUTING_ENTRY_ATTR_METER_POLICY_EN", "False", - "SAI_OUTBOUND_ROUTING_ENTRY_ATTR_METER_CLASS", "0" + "SAI_OUTBOUND_ROUTING_ENTRY_ATTR_METER_CLASS_OR", "0", + "SAI_OUTBOUND_ROUTING_ENTRY_ATTR_METER_CLASS_AND", "-1" ] }, { @@ -269,8 +269,8 @@ "attributes": [ "SAI_OUTBOUND_ROUTING_ENTRY_ATTR_ACTION", "SAI_OUTBOUND_ROUTING_ENTRY_ACTION_ROUTE_VNET", "SAI_OUTBOUND_ROUTING_ENTRY_ATTR_DST_VNET_ID", "$vnet_#3", - "SAI_OUTBOUND_ROUTING_ENTRY_ATTR_METER_POLICY_EN", "False", - "SAI_OUTBOUND_ROUTING_ENTRY_ATTR_METER_CLASS", "0" + "SAI_OUTBOUND_ROUTING_ENTRY_ATTR_METER_CLASS_OR", "0", + "SAI_OUTBOUND_ROUTING_ENTRY_ATTR_METER_CLASS_AND", "-1" ] }, { @@ -286,8 +286,7 @@ "SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_UNDERLAY_DIP", "172.16.1.20", "SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_OVERLAY_DMAC", "00:DD:DD:DD:DD:00", "SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_USE_DST_VNET_VNI", "True", - "SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_METER_CLASS", "0", - "SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_METER_CLASS_OVERRIDE", "False" + "SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_METER_CLASS_OR", "0" ] }, { @@ -303,8 +302,7 @@ "SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_UNDERLAY_DIP", "172.16.2.20", "SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_OVERLAY_DMAC", "00:DD:DD:DD:DD:01", "SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_USE_DST_VNET_VNI", "True", - "SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_METER_CLASS", "0", - "SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_METER_CLASS_OVERRIDE", "False" + "SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_METER_CLASS_OR", "0" ] }, { @@ -320,8 +318,7 @@ "SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_UNDERLAY_DIP", "172.16.3.20", "SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_OVERLAY_DMAC", "00:DD:DD:DD:DD:02", "SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_USE_DST_VNET_VNI", "True", - "SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_METER_CLASS", "0", - "SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_METER_CLASS_OVERRIDE", "False" + "SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_METER_CLASS_OR", "0" ] }, { @@ -337,8 +334,7 @@ "SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_UNDERLAY_DIP", "172.16.4.20", "SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_OVERLAY_DMAC", "00:DD:DD:DD:DD:03", "SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_USE_DST_VNET_VNI", "True", - "SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_METER_CLASS", "0", - "SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_METER_CLASS_OVERRIDE", "False" + "SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_METER_CLASS_OR", "0" ] }, { @@ -354,8 +350,7 @@ "SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_UNDERLAY_DIP", "172.16.5.20", "SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_OVERLAY_DMAC", "00:DD:DD:DD:DD:04", "SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_USE_DST_VNET_VNI", "True", - "SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_METER_CLASS", "0", - "SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_METER_CLASS_OVERRIDE", "False" + "SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_METER_CLASS_OR", "0" ] }, { @@ -371,8 +366,7 @@ "SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_UNDERLAY_DIP", "172.16.6.20", "SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_OVERLAY_DMAC", "00:DD:DD:DD:DD:05", "SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_USE_DST_VNET_VNI", "True", - "SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_METER_CLASS", "0", - "SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_METER_CLASS_OVERRIDE", "False" + "SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_METER_CLASS_OR", "0" ] }, { @@ -388,8 +382,7 @@ "SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_UNDERLAY_DIP", "172.16.7.20", "SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_OVERLAY_DMAC", "00:DD:DD:DD:DD:06", "SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_USE_DST_VNET_VNI", "True", - "SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_METER_CLASS", "0", - "SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_METER_CLASS_OVERRIDE", "False" + "SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_METER_CLASS_OR", "0" ] }, { @@ -405,8 +398,7 @@ "SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_UNDERLAY_DIP", "172.16.8.20", "SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_OVERLAY_DMAC", "00:DD:DD:DD:DD:07", "SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_USE_DST_VNET_VNI", "True", - "SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_METER_CLASS", "0", - "SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_METER_CLASS_OVERRIDE", "False" + "SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_METER_CLASS_OR", "0" ] } ] diff --git a/test/test-cases/scale/saic/vnet_outbound_setup_commands_simple.json b/test/test-cases/scale/saic/vnet_outbound_setup_commands_simple.json index 96b942a0e..dc39a2ee7 100644 --- a/test/test-cases/scale/saic/vnet_outbound_setup_commands_simple.json +++ b/test/test-cases/scale/saic/vnet_outbound_setup_commands_simple.json @@ -114,8 +114,8 @@ "attributes": [ "SAI_OUTBOUND_ROUTING_ENTRY_ATTR_ACTION", "SAI_OUTBOUND_ROUTING_ENTRY_ACTION_ROUTE_VNET", "SAI_OUTBOUND_ROUTING_ENTRY_ATTR_DST_VNET_ID", "$vnet", - "SAI_OUTBOUND_ROUTING_ENTRY_ATTR_METER_POLICY_EN", "False", - "SAI_OUTBOUND_ROUTING_ENTRY_ATTR_METER_CLASS", "0" + "SAI_OUTBOUND_ROUTING_ENTRY_ATTR_METER_CLASS_OR", "0", + "SAI_OUTBOUND_ROUTING_ENTRY_ATTR_METER_CLASS_AND", "-1" ] }, { @@ -131,8 +131,7 @@ "SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_UNDERLAY_DIP", "172.16.1.20", "SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_OVERLAY_DMAC", "00:DD:DD:DD:00:00", "SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_USE_DST_VNET_VNI", "True", - "SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_METER_CLASS", "0", - "SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_METER_CLASS_OVERRIDE", "False" + "SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_METER_CLASS_OR", "0" ] } ] diff --git a/test/test-cases/scale/saic/vnet_route_setup_commands_bidirectional.json b/test/test-cases/scale/saic/vnet_route_setup_commands_bidirectional.json index a7be524e9..6630859c0 100644 --- a/test/test-cases/scale/saic/vnet_route_setup_commands_bidirectional.json +++ b/test/test-cases/scale/saic/vnet_route_setup_commands_bidirectional.json @@ -469,10 +469,10 @@ "SAI_OUTBOUND_ROUTING_ENTRY_ACTION_ROUTE_VNET", "SAI_OUTBOUND_ROUTING_ENTRY_ATTR_DST_VNET_ID", "$vnet", - "SAI_OUTBOUND_ROUTING_ENTRY_ATTR_METER_POLICY_EN", - "False", - "SAI_OUTBOUND_ROUTING_ENTRY_ATTR_METER_CLASS", - "0" + "SAI_OUTBOUND_ROUTING_ENTRY_ATTR_METER_CLASS_OR", + "0", + "SAI_OUTBOUND_ROUTING_ENTRY_ATTR_METER_CLASS_AND", + "-1" ] }, { @@ -489,10 +489,10 @@ "SAI_OUTBOUND_ROUTING_ENTRY_ACTION_ROUTE_VNET", "SAI_OUTBOUND_ROUTING_ENTRY_ATTR_DST_VNET_ID", "$vnet", - "SAI_OUTBOUND_ROUTING_ENTRY_ATTR_METER_POLICY_EN", - "False", - "SAI_OUTBOUND_ROUTING_ENTRY_ATTR_METER_CLASS", - "0" + "SAI_OUTBOUND_ROUTING_ENTRY_ATTR_METER_CLASS_OR", + "0", + "SAI_OUTBOUND_ROUTING_ENTRY_ATTR_METER_CLASS_AND", + "-1" ] }, { @@ -511,10 +511,8 @@ "00:DD:DD:DD:00:00", "SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_USE_DST_VNET_VNI", "True", - "SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_METER_CLASS", - "0", - "SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_METER_CLASS_OVERRIDE", - "False" + "SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_METER_CLASS_OR", + "0" ] }, { @@ -533,10 +531,8 @@ "00:BB:BB:BB:00:00", "SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_USE_DST_VNET_VNI", "True", - "SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_METER_CLASS", - "0", - "SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_METER_CLASS_OVERRIDE", - "False" + "SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_METER_CLASS_OR", + "0" ] }, { @@ -555,10 +551,8 @@ "00:BB:BB:BB:00:00", "SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_USE_DST_VNET_VNI", "True", - "SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_METER_CLASS", - "0", - "SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_METER_CLASS_OVERRIDE", - "False" + "SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_METER_CLASS_OR", + "0" ] }, { @@ -577,10 +571,8 @@ "00:DD:DD:DD:00:00", "SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_USE_DST_VNET_VNI", "True", - "SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_METER_CLASS", - "0", - "SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_METER_CLASS_OVERRIDE", - "False" + "SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_METER_CLASS_OR", + "0" ] }, { diff --git a/test/test-cases/scale/saic/vnet_route_setup_commands_unidirectional.json b/test/test-cases/scale/saic/vnet_route_setup_commands_unidirectional.json index 1d76e1551..b9d93745a 100644 --- a/test/test-cases/scale/saic/vnet_route_setup_commands_unidirectional.json +++ b/test/test-cases/scale/saic/vnet_route_setup_commands_unidirectional.json @@ -158,10 +158,10 @@ "SAI_OUTBOUND_ROUTING_ENTRY_ACTION_ROUTE_VNET", "SAI_OUTBOUND_ROUTING_ENTRY_ATTR_DST_VNET_ID", "$vnet", - "SAI_OUTBOUND_ROUTING_ENTRY_ATTR_METER_POLICY_EN", - "False", - "SAI_OUTBOUND_ROUTING_ENTRY_ATTR_METER_CLASS", - "0" + "SAI_OUTBOUND_ROUTING_ENTRY_ATTR_METER_CLASS_OR", + "0", + "SAI_OUTBOUND_ROUTING_ENTRY_ATTR_METER_CLASS_AND", + "-1" ] }, { @@ -180,10 +180,8 @@ "00:DD:DD:DD:00:00", "SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_USE_DST_VNET_VNI", "True", - "SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_METER_CLASS", - "0", - "SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_METER_CLASS_OVERRIDE", - "False" + "SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_METER_CLASS_OR", + "0" ] } ] From 0b3d5592b827d47cd3cccc8bdcdf500125de578b Mon Sep 17 00:00:00 2001 From: Riff Date: Fri, 19 Apr 2024 15:35:54 -0700 Subject: [PATCH 26/32] [sai-gen] Simplify condition for table action generation. (#554) ## Problem Currently, we have a very complicated check for when a table action should be generated, for example: ![image](https://github.com/sonic-net/DASH/assets/1533278/9fbd5ee4-a3fb-4680-833d-c12bc3104518) The reason of this check being introduced is to enable us ignore the `SAI_VIP_ENTRY_ACTION_DENY` and `SAI_PA_VALIDATION_ENTRY_ACTION_DENY` action while still keep the action generated for them, as these entries only has 1 action which will be ignored. However, this check is too narrowed, and also create some issues, for example - an object (not entry) with 1 action will also have the action type generated, which is not ideal. ## What are we doing in this change Ideally, the condition to generate the action type should be really straightforward: 1. If the table entry has more than 2 valid actions (not deny), the action type should be generated. 2. If the table entry is an entry, not object, the action type should be generated. 3. Otherwise, the action type should not be generated. This simple logic simplify the mind model a lot, and the only case it didn't cover is the eni_eth_address_map_entry, which IMO, should follow the same pattern as many other similar tables (direction lookup, VIP, PA validation) and have the action type created too. ![image](https://github.com/sonic-net/DASH/assets/1533278/22292468-11d0-4b54-8fc7-7478ebd4a356) Hence, proposing the change to make our life easier. --- dash-pipeline/SAI/templates/saiapi.h.j2 | 4 ++-- dash-pipeline/tests/libsai/vnet_out/vnet_out.cpp | 4 ++++ .../test-cases/functional/saic/config_bidir_setup_commands.py | 3 +++ .../functional/saic/config_inbound_setup_commands.py | 4 ++++ .../functional/saic/config_outbound_setup_commands.json | 2 ++ .../functional/saic/sai-api/test_sai_api_vnet_eni_addr.py | 4 ++++ ...ai_vnet_outbound_small_scale_config_via_dpugen_create.json | 4 ++++ test/test-cases/scale/saic/vnet_inbound_setup_commands.json | 2 ++ .../scale/saic/vnet_outbound_setup_commands_scale.json | 2 ++ .../scale/saic/vnet_outbound_setup_commands_simple.json | 1 + .../scale/saic/vnet_route_setup_commands_bidirectional.json | 4 ++++ .../scale/saic/vnet_route_setup_commands_unidirectional.json | 2 ++ 12 files changed, 34 insertions(+), 2 deletions(-) diff --git a/dash-pipeline/SAI/templates/saiapi.h.j2 b/dash-pipeline/SAI/templates/saiapi.h.j2 index e6e909577..c7d76026d 100644 --- a/dash-pipeline/SAI/templates/saiapi.h.j2 +++ b/dash-pipeline/SAI/templates/saiapi.h.j2 @@ -34,7 +34,7 @@ */ {% for table in sai_api.tables %} -{% if table.actions | length > 1 or ((table.actions | length == 1) and (((table.is_object == 'false') or (table['keys'] | length <= 1)) and ((table['action_params'] | length == 0)))) %} +{% if table.actions | length > 1 or table.is_object == 'false' %} /** * @brief Attribute data for #SAI_{{ table.name | upper }}_ATTR_ACTION */ @@ -103,7 +103,7 @@ typedef enum _sai_{{ table.name }}_attr_t SAI_{{ table.name | upper }}_ATTR_START, {% set ns = namespace(firstattr=false) %} -{% if table.actions | length > 1 or ((table.actions | length == 1) and (((table.is_object == 'false') or (table['keys'] | length <= 1)) and ((table['action_params'] | length == 0)))) %} +{% if table.actions | length > 1 or table.is_object == 'false' %} /** * @brief Action * diff --git a/dash-pipeline/tests/libsai/vnet_out/vnet_out.cpp b/dash-pipeline/tests/libsai/vnet_out/vnet_out.cpp index c032c32e5..a9f5e9f11 100644 --- a/dash-pipeline/tests/libsai/vnet_out/vnet_out.cpp +++ b/dash-pipeline/tests/libsai/vnet_out/vnet_out.cpp @@ -224,6 +224,10 @@ int main(int argc, char **argv) eam.address[4] = 0xcc; eam.address[5] = 0xcc; + attr.id = SAI_ENI_ETHER_ADDRESS_MAP_ENTRY_ATTR_ACTION; + attr.value.u32 = SAI_ENI_ETHER_ADDRESS_MAP_ENTRY_ACTION_SET_ENI; + attrs.push_back(attr); + attr.id = SAI_ENI_ETHER_ADDRESS_MAP_ENTRY_ATTR_ENI_ID; attr.value.u16 = eni_id; attrs.push_back(attr); diff --git a/test/test-cases/functional/saic/config_bidir_setup_commands.py b/test/test-cases/functional/saic/config_bidir_setup_commands.py index eb81c7740..0c9282898 100644 --- a/test/test-cases/functional/saic/config_bidir_setup_commands.py +++ b/test/test-cases/functional/saic/config_bidir_setup_commands.py @@ -225,6 +225,7 @@ "address": INNER_SRC_MAC }, "attributes": [ + "SAI_ENI_ETHER_ADDRESS_MAP_ENTRY_ATTR_ACTION","SAI_ENI_ETHER_ADDRESS_MAP_ENTRY_ACTION_SET_ENI", "SAI_ENI_ETHER_ADDRESS_MAP_ENTRY_ATTR_ENI_ID", "$eni_#1" ] }, @@ -237,6 +238,7 @@ "address": INNER_DST_MAC }, "attributes": [ + "SAI_ENI_ETHER_ADDRESS_MAP_ENTRY_ATTR_ACTION","SAI_ENI_ETHER_ADDRESS_MAP_ENTRY_ACTION_SET_ENI", "SAI_ENI_ETHER_ADDRESS_MAP_ENTRY_ATTR_ENI_ID", "$eni_#2" ] }, @@ -249,6 +251,7 @@ "address": INNER_DST_MAC2 }, "attributes": [ + "SAI_ENI_ETHER_ADDRESS_MAP_ENTRY_ATTR_ACTION","SAI_ENI_ETHER_ADDRESS_MAP_ENTRY_ACTION_SET_ENI", "SAI_ENI_ETHER_ADDRESS_MAP_ENTRY_ATTR_ENI_ID", "$eni_#3" ] }, diff --git a/test/test-cases/functional/saic/config_inbound_setup_commands.py b/test/test-cases/functional/saic/config_inbound_setup_commands.py index 787e32bdb..7305883c8 100644 --- a/test/test-cases/functional/saic/config_inbound_setup_commands.py +++ b/test/test-cases/functional/saic/config_inbound_setup_commands.py @@ -258,6 +258,8 @@ "address": INNER_SRC_MAC }, "attributes": [ + "SAI_ENI_ETHER_ADDRESS_MAP_ENTRY_ATTR_ACTION", + "SAI_ENI_ETHER_ADDRESS_MAP_ENTRY_ACTION_SET_ENI", "SAI_ENI_ETHER_ADDRESS_MAP_ENTRY_ATTR_ENI_ID", "$eni_#1" ] @@ -271,6 +273,8 @@ "address": INNER_DST_MAC }, "attributes": [ + "SAI_ENI_ETHER_ADDRESS_MAP_ENTRY_ATTR_ACTION", + "SAI_ENI_ETHER_ADDRESS_MAP_ENTRY_ACTION_SET_ENI", "SAI_ENI_ETHER_ADDRESS_MAP_ENTRY_ATTR_ENI_ID", "$eni_#2" ] diff --git a/test/test-cases/functional/saic/config_outbound_setup_commands.json b/test/test-cases/functional/saic/config_outbound_setup_commands.json index 848946b6b..66585411d 100644 --- a/test/test-cases/functional/saic/config_outbound_setup_commands.json +++ b/test/test-cases/functional/saic/config_outbound_setup_commands.json @@ -156,6 +156,7 @@ "address": "00:1A:C5:00:00:01" }, "attributes": [ + "SAI_ENI_ETHER_ADDRESS_MAP_ENTRY_ATTR_ACTION", "SAI_ENI_ETHER_ADDRESS_MAP_ENTRY_ACTION_SET_ENI", "SAI_ENI_ETHER_ADDRESS_MAP_ENTRY_ATTR_ENI_ID", "$eni_#1" ] }, @@ -168,6 +169,7 @@ "address": "00:1b:6e:00:00:01" }, "attributes": [ + "SAI_ENI_ETHER_ADDRESS_MAP_ENTRY_ATTR_ACTION", "SAI_ENI_ETHER_ADDRESS_MAP_ENTRY_ACTION_SET_ENI", "SAI_ENI_ETHER_ADDRESS_MAP_ENTRY_ATTR_ENI_ID", "$eni_#2" ] }, diff --git a/test/test-cases/functional/saic/sai-api/test_sai_api_vnet_eni_addr.py b/test/test-cases/functional/saic/sai-api/test_sai_api_vnet_eni_addr.py index 4618311bd..7ed2293ba 100644 --- a/test/test-cases/functional/saic/sai-api/test_sai_api_vnet_eni_addr.py +++ b/test/test-cases/functional/saic/sai-api/test_sai_api_vnet_eni_addr.py @@ -23,6 +23,8 @@ def test_vnet_eni_ether_address_create(self, dpu): "address": "00:AA:AA:AA:AB:00" }, "attributes": [ + "SAI_ENI_ETHER_ADDRESS_MAP_ENTRY_ATTR_ACTION", + "SAI_ENI_ETHER_ADDRESS_MAP_ENTRY_ACTION_SET_ENI", "SAI_ENI_ETHER_ADDRESS_MAP_ENTRY_ATTR_ENI_ID", "1" ] @@ -59,6 +61,8 @@ def test_vnet_eni_ether_address_set(self, dpu): "address": "00:AA:AA:AA:BB:00" }, "attributes": [ + "SAI_ENI_ETHER_ADDRESS_MAP_ENTRY_ATTR_ACTION", + "SAI_ENI_ETHER_ADDRESS_MAP_ENTRY_ACTION_SET_ENI", "SAI_ENI_ETHER_ADDRESS_MAP_ENTRY_ATTR_ENI_ID", "$eni_id" ] diff --git a/test/test-cases/functional/saic/tutorial/test_sai_vnet_outbound_small_scale_config_via_dpugen_create.json b/test/test-cases/functional/saic/tutorial/test_sai_vnet_outbound_small_scale_config_via_dpugen_create.json index 230b4ffca..ba59d8f29 100644 --- a/test/test-cases/functional/saic/tutorial/test_sai_vnet_outbound_small_scale_config_via_dpugen_create.json +++ b/test/test-cases/functional/saic/tutorial/test_sai_vnet_outbound_small_scale_config_via_dpugen_create.json @@ -241,6 +241,8 @@ "address": "00:1A:C5:00:00:01" }, "attributes": [ + "SAI_ENI_ETHER_ADDRESS_MAP_ENTRY_ATTR_ACTION", + "SAI_ENI_ETHER_ADDRESS_MAP_ENTRY_ACTION_SET_ENI", "SAI_ENI_ETHER_ADDRESS_MAP_ENTRY_ATTR_ENI_ID", "$eni_#5000" ] @@ -254,6 +256,8 @@ "address": "00:1A:C5:18:00:01" }, "attributes": [ + "SAI_ENI_ETHER_ADDRESS_MAP_ENTRY_ATTR_ACTION", + "SAI_ENI_ETHER_ADDRESS_MAP_ENTRY_ACTION_SET_ENI", "SAI_ENI_ETHER_ADDRESS_MAP_ENTRY_ATTR_ENI_ID", "$eni_#6000" ] diff --git a/test/test-cases/scale/saic/vnet_inbound_setup_commands.json b/test/test-cases/scale/saic/vnet_inbound_setup_commands.json index 25cbd1364..95220fd19 100644 --- a/test/test-cases/scale/saic/vnet_inbound_setup_commands.json +++ b/test/test-cases/scale/saic/vnet_inbound_setup_commands.json @@ -140,6 +140,8 @@ "address": "00:AA:AA:AA:AA:00" }, "attributes": [ + "SAI_ENI_ETHER_ADDRESS_MAP_ENTRY_ATTR_ACTION", + "SAI_ENI_ETHER_ADDRESS_MAP_ENTRY_ACTION_SET_ENI", "SAI_ENI_ETHER_ADDRESS_MAP_ENTRY_ATTR_ENI_ID", "$eni_id" ] diff --git a/test/test-cases/scale/saic/vnet_outbound_setup_commands_scale.json b/test/test-cases/scale/saic/vnet_outbound_setup_commands_scale.json index 46d85a0b8..7318ce778 100644 --- a/test/test-cases/scale/saic/vnet_outbound_setup_commands_scale.json +++ b/test/test-cases/scale/saic/vnet_outbound_setup_commands_scale.json @@ -194,6 +194,7 @@ "address": "00:CC:CC:CC:00:00" }, "attributes": [ + "SAI_ENI_ETHER_ADDRESS_MAP_ENTRY_ATTR_ACTION", "SAI_ENI_ETHER_ADDRESS_MAP_ENTRY_ACTION_SET_ENI", "SAI_ENI_ETHER_ADDRESS_MAP_ENTRY_ATTR_ENI_ID", "$eni_#0" ] }, @@ -206,6 +207,7 @@ "address": "00:CC:CC:CC:00:01" }, "attributes": [ + "SAI_ENI_ETHER_ADDRESS_MAP_ENTRY_ATTR_ACTION", "SAI_ENI_ETHER_ADDRESS_MAP_ENTRY_ACTION_SET_ENI", "SAI_ENI_ETHER_ADDRESS_MAP_ENTRY_ATTR_ENI_ID", "$eni_#1" ] }, diff --git a/test/test-cases/scale/saic/vnet_outbound_setup_commands_simple.json b/test/test-cases/scale/saic/vnet_outbound_setup_commands_simple.json index dc39a2ee7..2f8e021f2 100644 --- a/test/test-cases/scale/saic/vnet_outbound_setup_commands_simple.json +++ b/test/test-cases/scale/saic/vnet_outbound_setup_commands_simple.json @@ -99,6 +99,7 @@ "address": "00:CC:CC:CC:00:00" }, "attributes": [ + "SAI_ENI_ETHER_ADDRESS_MAP_ENTRY_ATTR_ACTION", "SAI_ENI_ETHER_ADDRESS_MAP_ENTRY_ACTION_SET_ENI", "SAI_ENI_ETHER_ADDRESS_MAP_ENTRY_ATTR_ENI_ID", "$eni" ] }, diff --git a/test/test-cases/scale/saic/vnet_route_setup_commands_bidirectional.json b/test/test-cases/scale/saic/vnet_route_setup_commands_bidirectional.json index 6630859c0..3d90d683e 100644 --- a/test/test-cases/scale/saic/vnet_route_setup_commands_bidirectional.json +++ b/test/test-cases/scale/saic/vnet_route_setup_commands_bidirectional.json @@ -438,6 +438,8 @@ "address": "00:CC:CC:CC:00:00" }, "attributes": [ + "SAI_ENI_ETHER_ADDRESS_MAP_ENTRY_ATTR_ACTION", + "SAI_ENI_ETHER_ADDRESS_MAP_ENTRY_ACTION_SET_ENI", "SAI_ENI_ETHER_ADDRESS_MAP_ENTRY_ATTR_ENI_ID", "$eni" ] @@ -451,6 +453,8 @@ "address": "00:0a:04:06:06:06" }, "attributes": [ + "SAI_ENI_ETHER_ADDRESS_MAP_ENTRY_ATTR_ACTION", + "SAI_ENI_ETHER_ADDRESS_MAP_ENTRY_ACTION_SET_ENI", "SAI_ENI_ETHER_ADDRESS_MAP_ENTRY_ATTR_ENI_ID", "$eni" ] diff --git a/test/test-cases/scale/saic/vnet_route_setup_commands_unidirectional.json b/test/test-cases/scale/saic/vnet_route_setup_commands_unidirectional.json index b9d93745a..05956037b 100644 --- a/test/test-cases/scale/saic/vnet_route_setup_commands_unidirectional.json +++ b/test/test-cases/scale/saic/vnet_route_setup_commands_unidirectional.json @@ -140,6 +140,8 @@ "address": "00:CC:CC:CC:00:00" }, "attributes": [ + "SAI_ENI_ETHER_ADDRESS_MAP_ENTRY_ATTR_ACTION", + "SAI_ENI_ETHER_ADDRESS_MAP_ENTRY_ACTION_SET_ENI", "SAI_ENI_ETHER_ADDRESS_MAP_ENTRY_ATTR_ENI_ID", "$eni" ] From 2ba84b69291d60aabef2e0c0f81766dbeebc4896 Mon Sep 17 00:00:00 2001 From: Riff Date: Sat, 20 Apr 2024 00:30:03 -0700 Subject: [PATCH 27/32] [dash-p4] Add pre-routing action apply stage. (#555) This change adds a pre routing action apply stage, which serves as a pivot for doing any post processing after routing and mapping stages before the final action being applied. --- dash-pipeline/bmv2/dash_metadata.p4 | 9 ++++++--- dash-pipeline/bmv2/dash_outbound.p4 | 7 +++++-- dash-pipeline/bmv2/dash_routing_types.p4 | 10 +++++----- .../outbound_pre_routing_action_apply.p4 | 19 +++++++++++++++++++ 4 files changed, 35 insertions(+), 10 deletions(-) create mode 100644 dash-pipeline/bmv2/stages/outbound_pre_routing_action_apply.p4 diff --git a/dash-pipeline/bmv2/dash_metadata.p4 b/dash-pipeline/bmv2/dash_metadata.p4 index 94fa9e40a..8c73fb7b4 100644 --- a/dash-pipeline/bmv2/dash_metadata.p4 +++ b/dash-pipeline/bmv2/dash_metadata.p4 @@ -9,9 +9,11 @@ enum bit<32> dash_routing_actions_t { NONE = 0, STATIC_ENCAP = (1 << 0), - NAT46 = (1 << 1), - NAT64 = (1 << 2) -} + NAT = (1 << 1), + NAT46 = (1 << 2), + NAT64 = (1 << 3), + NAT_PORT = (1 << 4) +}; enum bit<16> dash_direction_t { INVALID = 0, @@ -44,6 +46,7 @@ enum bit<16> dash_pipeline_stage_t { OUTBOUND_STAGE_START = 200, OUTBOUND_ROUTING = 200, // OUTBOUND_STAGE_START OUTBOUND_MAPPING = 201, + OUTBOUND_PRE_ROUTING_ACTION_APPLY = 280, // Common stages ROUTING_ACTION_APPLY = 300 diff --git a/dash-pipeline/bmv2/dash_outbound.p4 b/dash-pipeline/bmv2/dash_outbound.p4 index fa780027d..8440b7a84 100644 --- a/dash-pipeline/bmv2/dash_outbound.p4 +++ b/dash-pipeline/bmv2/dash_outbound.p4 @@ -6,13 +6,14 @@ #include "dash_conntrack.p4" #include "stages/outbound_routing.p4" #include "stages/outbound_mapping.p4" +#include "stages/outbound_pre_routing_action_apply.p4" control outbound(inout headers_t hdr, inout metadata_t meta) { apply { #ifdef STATEFUL_P4 - ConntrackOut.apply(0); + ConntrackOut.apply(0); #endif /* STATEFUL_P4 */ #ifdef PNA_CONNTRACK @@ -25,7 +26,7 @@ control outbound(inout headers_t hdr, } #ifdef STATEFUL_P4 - ConntrackIn.apply(1); + ConntrackIn.apply(1); #endif /* STATEFUL_P4 */ #ifdef PNA_CONNTRACK @@ -37,6 +38,8 @@ control outbound(inout headers_t hdr, outbound_routing_stage.apply(hdr, meta); outbound_mapping_stage.apply(hdr, meta); + + outbound_pre_routing_action_apply_stage.apply(hdr, meta); } } diff --git a/dash-pipeline/bmv2/dash_routing_types.p4 b/dash-pipeline/bmv2/dash_routing_types.p4 index 9009e1995..a29053dbf 100644 --- a/dash-pipeline/bmv2/dash_routing_types.p4 +++ b/dash-pipeline/bmv2/dash_routing_types.p4 @@ -15,7 +15,7 @@ action set_meter_attrs( // Routing Type - drop: action drop(inout metadata_t meta) { - meta.target_stage = dash_pipeline_stage_t.ROUTING_ACTION_APPLY; + meta.target_stage = dash_pipeline_stage_t.OUTBOUND_PRE_ROUTING_ACTION_APPLY; meta.dropped = true; } @@ -63,7 +63,7 @@ action route_direct( bit<32> meter_class_or, @SaiVal[default_value="4294967295"] bit<32> meter_class_and) { - meta.target_stage = dash_pipeline_stage_t.ROUTING_ACTION_APPLY; + meta.target_stage = dash_pipeline_stage_t.OUTBOUND_PRE_ROUTING_ACTION_APPLY; set_meter_attrs(meta, meter_class_or, meter_class_and); } @@ -96,7 +96,7 @@ action route_service_tunnel( 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.target_stage = dash_pipeline_stage_t.OUTBOUND_PRE_ROUTING_ACTION_APPLY; push_action_nat46(hdr = hdr, meta = meta, @@ -130,7 +130,7 @@ action set_tunnel_mapping( bit<1> use_dst_vnet_vni, bit<32> meter_class_or) { - meta.target_stage = dash_pipeline_stage_t.ROUTING_ACTION_APPLY; + meta.target_stage = dash_pipeline_stage_t.OUTBOUND_PRE_ROUTING_ACTION_APPLY; if (use_dst_vnet_vni == 1) meta.vnet_id = meta.dst_vnet_id; @@ -154,7 +154,7 @@ action set_private_link_mapping( bit<24> tunnel_key, bit<32> meter_class_or) { - meta.target_stage = dash_pipeline_stage_t.ROUTING_ACTION_APPLY; + meta.target_stage = dash_pipeline_stage_t.OUTBOUND_PRE_ROUTING_ACTION_APPLY; push_action_static_encap(hdr = hdr, meta = meta, diff --git a/dash-pipeline/bmv2/stages/outbound_pre_routing_action_apply.p4 b/dash-pipeline/bmv2/stages/outbound_pre_routing_action_apply.p4 new file mode 100644 index 000000000..74329f13d --- /dev/null +++ b/dash-pipeline/bmv2/stages/outbound_pre_routing_action_apply.p4 @@ -0,0 +1,19 @@ +#ifndef _DASH_STAGE_OUTBOUND_PRE_ROUTING_ACTION_APPLY_P4_ +#define _DASH_STAGE_OUTBOUND_PRE_ROUTING_ACTION_APPLY_P4_ + +control outbound_pre_routing_action_apply_stage( + inout headers_t hdr, + inout metadata_t meta) +{ + apply { + // Outbound pre-routing action apply stage is added here for certain pre processing before applying the final actions. + if (meta.target_stage != dash_pipeline_stage_t.OUTBOUND_PRE_ROUTING_ACTION_APPLY) { + return; + } + + // Once it is done, move to routing action apply stage. + meta.target_stage = dash_pipeline_stage_t.ROUTING_ACTION_APPLY; + } +} + +#endif /* _DASH_STAGE_OUTBOUND_PRE_ROUTING_ACTION_APPLY_P4_ */ \ No newline at end of file From 827b51ff6b1190b1e6b9f93a115ca741e11b0221 Mon Sep 17 00:00:00 2001 From: Riff Date: Tue, 23 Apr 2024 07:27:57 -0700 Subject: [PATCH 28/32] [sai-gen] Fix SAI generation if the coutners is the firs attribute. (#557) ## Problem When we create a new SAI object (table) without any attribute and with the counter attached, the counter id will be generated as the first attribute, however the format is not right, as it doesn't have the ` = SAI_TABLE_NAME_ATTR_START` part after it. This will cause SAI checkers to fail. ## What we are doing in this change This change fixes the template, so we can have the counter attribute correctly generated as below in this case. ```c typedef enum _sai_some_table_attr_t { /** * @brief Start of attributes */ SAI_SOME_TABLE_ATTR_START, /** * @brief Attach a counter * * When it is empty, then packet hits won't be counted * * @type sai_object_id_t * @flags CREATE_AND_SET * @objects SAI_OBJECT_TYPE_COUNTER * @allownull true * @default SAI_NULL_OBJECT_ID */ SAI_SOME_TABLE_ATTR_COUNTER_ID = SAI_SOME_TABLE_ATTR_START, /** * @brief End of attributes */ SAI_SOME_TABLE_ATTR_END, /** Custom range base value */ SAI_SOME_TABLE_ATTR_CUSTOM_RANGE_START = 0x10000000, /** End of custom range base */ SAI_SOME_TABLE_ATTR_CUSTOM_RANGE_END, } sai_some_table_attr_t; ``` --- dash-pipeline/SAI/templates/saiapi.h.j2 | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/dash-pipeline/SAI/templates/saiapi.h.j2 b/dash-pipeline/SAI/templates/saiapi.h.j2 index c7d76026d..c6eeb178d 100644 --- a/dash-pipeline/SAI/templates/saiapi.h.j2 +++ b/dash-pipeline/SAI/templates/saiapi.h.j2 @@ -211,7 +211,12 @@ typedef enum _sai_{{ table.name }}_attr_t * @allownull true * @default SAI_NULL_OBJECT_ID */ +{% if not ns.firstattr %} + SAI_{{ table.name | upper }}_ATTR_COUNTER_ID = SAI_{{ table.name | upper }}_ATTR_START, +{% set ns.firstattr = true %} +{% else %} SAI_{{ table.name | upper }}_ATTR_COUNTER_ID, +{% endif %} {% endif %} {% if table.is_object == 'true' %} From f3c8019d9a8d45bd34f2eec75f1d01ea1537fb33 Mon Sep 17 00:00:00 2001 From: Riff Date: Wed, 24 Apr 2024 15:35:38 -0700 Subject: [PATCH 29/32] [sai-gen] Update the default action of inbound routing type to use the latest one instead of deprecating one. (#559) The SAI action type generation follows the order of the actions defined in P4 and the first one will be the default action. The newly added tunnel decap actions in inbound routing table are not used as default value, as they are put in the end of the action list. This change fixes the action order, which produces the right default action in the SAI header: ![image](https://github.com/sonic-net/DASH/assets/1533278/291a474c-3f8c-4e84-95cb-79c6f74f16ac) --- dash-pipeline/bmv2/dash_pipeline.p4 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dash-pipeline/bmv2/dash_pipeline.p4 b/dash-pipeline/bmv2/dash_pipeline.p4 index fd48195ac..1653dea34 100644 --- a/dash-pipeline/bmv2/dash_pipeline.p4 +++ b/dash-pipeline/bmv2/dash_pipeline.p4 @@ -219,10 +219,10 @@ control dash_ingress( hdr.u0_ipv4.src_addr : ternary @SaiVal[name = "sip", type="sai_ip_address_t"]; } actions = { - vxlan_decap; // Deprecated, but cannot be removed until SWSS is updated. - vxlan_decap_pa_validate; // Deprecated, but cannot be removed until SWSS is updated. tunnel_decap(hdr, meta); tunnel_decap_pa_validate(hdr, meta); + vxlan_decap; // Deprecated, but cannot be removed until SWSS is updated. + vxlan_decap_pa_validate; // Deprecated, but cannot be removed until SWSS is updated. @defaultonly deny; } From c00def3aea9e716b208713a83cebe280f2e22124 Mon Sep 17 00:00:00 2001 From: Riff Date: Wed, 24 Apr 2024 16:00:28 -0700 Subject: [PATCH 30/32] [sai-gen] Fix template for generating the SAI stats. (#560) SAI has a style checker that forces the certain words to be upper cases in the comment, such as acronyms like ENI. However, currently we are generating the comments using lower cases, which breaks this checker. ![image](https://github.com/sonic-net/DASH/assets/1533278/8bbc6995-a8e4-435e-b546-ddbd869ff533) This issue will be gone after moving everything to upper case, hence making this change to fix this issue. --- dash-pipeline/SAI/templates/headers/sai_stats_enum.j2 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dash-pipeline/SAI/templates/headers/sai_stats_enum.j2 b/dash-pipeline/SAI/templates/headers/sai_stats_enum.j2 index 89ae86fa7..e5bc0370f 100644 --- a/dash-pipeline/SAI/templates/headers/sai_stats_enum.j2 +++ b/dash-pipeline/SAI/templates/headers/sai_stats_enum.j2 @@ -5,7 +5,7 @@ typedef enum _sai_{{ table.name }}_stat_t { {% for stat in table.sai_stats %} - /** DASH {{ table.name | lower }} {{ stat.name | upper }} stat count */ + /** DASH {{ table.name | upper }} {{ stat.name | upper }} stat count */ SAI_{{ table.name | upper }}_STAT_{{ stat.name | upper }}, {% endfor %} From 8b7a0d5c5da4bbe595e34ec7dff05171b78ef6ff Mon Sep 17 00:00:00 2001 From: Riff Date: Fri, 26 Apr 2024 11:27:57 -0700 Subject: [PATCH 31/32] [doc] Add HLD for Private link and Private Link NSG (#542) --- .wordlist.txt | 3 + documentation/private-link-service/README.md | 9 + .../images/private-link-nsg-vm-to-pls.svg | 4 + .../images/private-link-pls-to-vm.svg | 4 + .../images/private-link-vm-to-pls.svg | 4 + .../private-link-service.md | 275 ++++++++++++++++++ 6 files changed, 299 insertions(+) create mode 100644 documentation/private-link-service/README.md create mode 100644 documentation/private-link-service/images/private-link-nsg-vm-to-pls.svg create mode 100644 documentation/private-link-service/images/private-link-pls-to-vm.svg create mode 100644 documentation/private-link-service/images/private-link-vm-to-pls.svg create mode 100644 documentation/private-link-service/private-link-service.md diff --git a/.wordlist.txt b/.wordlist.txt index 463b1a777..b204d5f33 100644 --- a/.wordlist.txt +++ b/.wordlist.txt @@ -38,6 +38,7 @@ AspNet assignees asyncE atlassian +attr ATTR auditability autogenerate @@ -424,6 +425,7 @@ performant pingmesh PIR pluggable +PLS PLVision's PKTS pmon @@ -533,6 +535,7 @@ sharding SInce SKU SKUs +SLA SLB SMAC SmartAppliances diff --git a/documentation/private-link-service/README.md b/documentation/private-link-service/README.md new file mode 100644 index 000000000..aa2954f88 --- /dev/null +++ b/documentation/private-link-service/README.md @@ -0,0 +1,9 @@ +# DASH Private Link Service Documents + +This folder contains DASH Private Link Service design and requirements documents. + +## Design + +| Document | Description | +| --- | --- | +| [Private Link scenario](private-link-service.md) | Private Link | diff --git a/documentation/private-link-service/images/private-link-nsg-vm-to-pls.svg b/documentation/private-link-service/images/private-link-nsg-vm-to-pls.svg new file mode 100644 index 000000000..574b88580 --- /dev/null +++ b/documentation/private-link-service/images/private-link-nsg-vm-to-pls.svg @@ -0,0 +1,4 @@ + + + +
Initial Packet (Before Pipeline)
Eth
SRC, DST=...
VxLan
SRC=100.1.0.1, DST=2.2.2.1,
VNI=<Outbound VNI>
Eth
SRC=<DASH ENI MAC>
IPv4
SRC=10.0.0.1, DST=10.0.1.1
SmartSwitch
(SS DP VIP: 2.2.2.1)
(DPU IP: 100.0.0.1)
NPU uses VIP (+ Inner SRC MAC) to forward the packet to the corresponding ENI pipeline.
Initial Packet (After Pipeline)
Eth
SRC, DST=...
VxLan
SRC=100.0.0.1, DST=100.0.1.1,
VNI=<NSG Appliance VNI>
Eth
SRC, DST=...
NvGRE
SRC=2.2.2.1, DST=3.3.3.1,
Key=<Private Link Key>
Eth
SRC=<DASH ENI MAC>
IPv6
SRC=9988::a00:1,
DST=1122:3344:5566:7788::303:301
\ No newline at end of file diff --git a/documentation/private-link-service/images/private-link-pls-to-vm.svg b/documentation/private-link-service/images/private-link-pls-to-vm.svg new file mode 100644 index 000000000..e96b43e0f --- /dev/null +++ b/documentation/private-link-service/images/private-link-pls-to-vm.svg @@ -0,0 +1,4 @@ + + + +
Return Packet (From PrivateLink Endpoint)
Eth
SRC, DST = ...
NvGRE
SRC=3.3.3.1, DST=2.2.2.1,
Key=<Private Link Key>
Eth
DST=<DASH ENI MAC>
IPv6
SRC=1122:3344:5566:7788::303:301,
DST=9988::a00:1
1
Return Packet (After pipeline)
Eth
SRC, DST = ...
VxLan
SRC=5.5.5.1, DST=100.1.0.1,
VNI=<Outbound VNI>
Eth
DST=<DASH ENI MAC>
IPv4
SRC=10.0.1.1, DST=10.0.0.1
SmartSwitch
(SS DP VIP: 2.2.2.1)
(DPU IP: 100.0.0.1)
NPU uses DST VIP (+ Inner DST MAC) to forward the traffic to ENI pipeline.
2
\ No newline at end of file diff --git a/documentation/private-link-service/images/private-link-vm-to-pls.svg b/documentation/private-link-service/images/private-link-vm-to-pls.svg new file mode 100644 index 000000000..35a29fd3b --- /dev/null +++ b/documentation/private-link-service/images/private-link-vm-to-pls.svg @@ -0,0 +1,4 @@ + + + +
Initial Packet (After Pipeline)
Eth
SRC, DST = ...
NvGRE
SRC=2.2.2.1, DST=3.3.3.1,
Key=<Private Link Key>
Eth
SRC=<DASH ENI MAC>
IPv6
SRC=9988::a00:1,
DST=1122:3344:5566:7788::303:301
Initial Packet (Before Pipeline)
Eth
SRC, DST = ...
VxLan
SRC=100.1.0.1, DST=2.2.2.1,
VNI=<Outbound VNI>
Eth
SRC=<DASH ENI MAC>
IPv4
SRC=10.0.0.1, DST=10.0.1.1
SmartSwitch
(SS DP VIP: 2.2.2.1)
(DPU IP: 100.0.0.1)
NPU uses DST VIP (+ Inner SRC MAC) to forward the packet to the corresponding ENI pipeline.
\ No newline at end of file diff --git a/documentation/private-link-service/private-link-service.md b/documentation/private-link-service/private-link-service.md new file mode 100644 index 000000000..259a518c8 --- /dev/null +++ b/documentation/private-link-service/private-link-service.md @@ -0,0 +1,275 @@ +# DASH Private Link and Private Link NSG HLD + +| Rev | Date | Author | Change Description | +| --- | ---- | ------ | ------------------ | +| 0.1 | 03/29/2024 | Riff Jiang | Initial version | + +1. [1. Terminology](#1-terminology) +2. [2. Background](#2-background) +3. [3. SDN transformation](#3-sdn-transformation) + 1. [3.1. Private Link](#31-private-link) + 1. [3.1.1. VM-to-PLS direction](#311-vm-to-pls-direction) + 2. [3.1.2. PLS-to-VM direction](#312-pls-to-vm-direction) + 2. [3.2. Private Link NSG](#32-private-link-nsg) + 1. [3.2.1. VM-to-PLS direction](#321-vm-to-pls-direction) + 2. [3.2.2. PLS-to-VM direction](#322-pls-to-vm-direction) + 3. [3.3. Load balancer fast path support](#33-load-balancer-fast-path-support) + 4. [3.4. Non-required features](#34-non-required-features) +4. [4. Resource modeling, requirement, and SLA](#4-resource-modeling-requirement-and-sla) + 1. [4.1. Scaling requirements](#41-scaling-requirements) + 2. [4.2. Reliability requirements](#42-reliability-requirements) +5. [5. SAI API design](#5-sai-api-design) + 1. [5.1. DASH ENI attributes](#51-dash-eni-attributes) + 2. [5.2. DASH CA-PA mapping attributes](#52-dash-ca-pa-mapping-attributes) + 3. [5.3. DASH tunnel table and attributes](#53-dash-tunnel-table-and-attributes) +6. [6. DASH pipeline behavior](#6-dash-pipeline-behavior) + 1. [6.1. VM-to-PLS direction (Outbound)](#61-vm-to-pls-direction-outbound) + 1. [6.1.1. Private Link](#611-private-link) + 2. [6.1.2. Private Link NSG](#612-private-link-nsg) + 2. [6.2. PLS-to-VM direction](#62-pls-to-vm-direction) +7. [7. DASH database schema](#7-dash-database-schema) + +## 1. Terminology + +| Term | Explanation | +| --- | --- | +| PL | Private Link: . | +| NSG | Network Security Group. | +| PE | Private endpoint. | +| PLS | Private Link Service. This is the term for private endpoint from server side. Customer can create their private link service, then expose them to their VNETs as a private endpoint. | + +## 2. Background + +Azure Private Link provides private connectivity from a virtual network to Azure platform as a service, by providing an 1-to-1 VNET mapping to the service. + +This doc is used to capture the requirements for implementing the Private Link and Private Link NSG in the context of DASH APIs. + +## 3. SDN transformation + +### 3.1. Private Link + +#### 3.1.1. VM-to-PLS direction + +When a packet coming from the VM and being sent to PLS, it will be transformed as below: + +![PL VM-to-PLS direction](./images/private-link-vm-to-pls.svg) + +#### 3.1.2. PLS-to-VM direction + +And the return packet from PLS to VM, will be transformed as below: + +![PL PLS-to-VM direction](./images/private-link-pls-to-vm.svg) + +### 3.2. Private Link NSG + +#### 3.2.1. VM-to-PLS direction + +When NSG appliance is enabled, the VM-to-PLS packet will have an additional outer encap that tunnels the packet to NSG appliance as below: + +![PL NSG VM-to-PLS direction](./images/private-link-nsg-vm-to-pls.svg) + +#### 3.2.2. PLS-to-VM direction + +The return packet will be the same as Private Link, coming directly from PLS bypassing the NSG appliance. + +### 3.3. Load balancer fast path support + +The fast path here is not the DASH hardware fast path, but the [load balancer fast path ICMP flow redirection](../load-bal-service/fast-path-icmp-flow-redirection.md). + +1. If PL NSG is not used, it changes the flow just like regular PL case. +2. If PL NSG is used, it updates the PL encap, and **removes** the outer NSG encap. + +For more information on how Fast Path works, please refer to [Fast Path design doc](../load-bal-service/fast-path-icmp-flow-redirection.md). + +### 3.4. Non-required features + +- RST on connection idle timeout. + +## 4. Resource modeling, requirement, and SLA + +### 4.1. Scaling requirements + +| Metric | Requirement | +| --- | --- | +| # of ENIs per DPU | 32 | +| # of VNET mapping per ENI | 64K | +| # of PPS | 64M | +| VNET mapping change rate (CRUD) | (TBD) | +| # of fast path packets | Same as CPS. 3M per card. | +| # of tunnels | (TBD) | +| # of next hop in each tunnel | (TBD) | + +### 4.2. Reliability requirements + +The flows replication follows the SmartSwitch HA design. + +For more information, please refer to [SmartSwitch HA design doc](https://github.com/sonic-net/SONiC/blob/master/doc/smart-switch/high-availability/smart-switch-ha-hld.md). + +## 5. SAI API design + +The following SAI API only includes the SAI updates that used for setting up the PL / PL NSG scenarios. + +### 5.1. DASH ENI attributes + +The following attributes will be added on ENI: + +| Attribute name | Type | Description | +| --- | --- | --- | +| SAI_ENI_ATTR_PL_UNDERLAY_SIP | sai_ip_address_t | Underlay IP that will be used for private link routing type. | + +### 5.2. DASH CA-PA mapping attributes + +The following attributes will be added to CA-to-PA entry, for supporting service rewrites for PL/PL NSG: + +| Attribute name | Type | Description | +| --- | --- | --- | +| SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_OVERLAY_SIP_MASK | sai_ip_address_t | Used with overlay sip to support src prefix rewrite. | +| SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_OVERLAY_DIP_MASK | sai_ip_address_t | Used with overlay dip to support dst prefix rewrite. | +| SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_TUNNEL_ID | sai_object_id_t | Used to specify the tunnel. It can be a tunnel next hop id or the tunnel id, depending on if multiple dips as ECMP group is required. | + +The PL and PL NSG will share the same routing type on the CA-PA mapping entry: + +```c +typedef enum _sai_outbound_ca_to_pa_entry_action_t +{ + // ... + + SAI_OUTBOUND_CA_TO_PA_ENTRY_ACTION_SET_PRIVATE_LINK_MAPPING, + + // ... +} sai_outbound_ca_to_pa_entry_action_t; +``` + +### 5.3. DASH tunnel table and attributes + +A new tunnel next hop table needs to be added with the following attributes: + +| Attribute name | Type | Description | +| --- | --- | --- | +| SAI_DASH_TUNNEL_ENTRY_ATTR_DASH_ENCAPSULATION | sai_dash_encapsulation_t | Encapsulation type, such as VxLan, NvGRE. Optional. If not specified, the encap from tunnel will be used. | +| SAI_DASH_TUNNEL_ENTRY_ATTR_VNI | sai_uint32_t | VNI used in the encap. Optional. If not specified, the VNI from tunnel will be used. | +| SAI_DASH_TUNNEL_NEXT_HOP_ENTRY_ATTR_DIP | sai_ip_address_t | Destination IP of the next hop. | + +When multiple destination IPs are required as ECMP group, the tunnel table and tunnel member will be used to specify the tunnel with multiple next hop information: + +- A new tunnel table needs to be added with the following attributes: + + | Attribute name | Type | Description | + | --- | --- | --- | + | SAI_DASH_TUNNEL_ENTRY_ATTR_DASH_ENCAPSULATION | sai_dash_encapsulation_t | Encapsulation type, such as VxLan, NvGRE. | + | SAI_DASH_TUNNEL_ENTRY_ATTR_VNI | sai_uint32_t | VNI used in the encap. | + +- A new tunnel member table needs to be added to create the bindings between tunnel and next hop: + + | Attribute name | Type | Description | + | --- | --- | --- | + | SAI_DASH_TUNNEL_MEMBER_ENTRY_ATTR_TUNNEL_ID | sai_object_id_t | Tunnel Id | + | SAI_DASH_TUNNEL_MEMBER_ENTRY_ATTR_TUNNEL_NEXT_HOP_ID | sai_object_id_t | Tunnel next hop id | + +## 6. DASH pipeline behavior + +### 6.1. VM-to-PLS direction (Outbound) + +The VM-to-PLS direction is modeled as outbound pipeline in DASH. + +To demonstrate how the DASH pipeline works, let's say, we have a VM in with IP 10.0.0.1, trying to reach the Private Endpoint in their VNET with IP 10.0.1.1, and the VM Outbound VNI is 1000000. + +#### 6.1.1. Private Link + +For private link, the packet will go through the pipeline with following setup: + +1. **Direction Lookup**: First, we will look up the VNI to determine the packet direction. In this case, we consider all the packets from on-premises network as outbound direction from the floating NIC perspective. + + | SAI field name | Type | Value | + | --- | --- | --- | + | entry.vni | `sai_uint32_t` | `1000000` | + | entry_attr.SAI_DIRECTION_LOOKUP_ENTRY_ATTR_ACTION | `sai_direction_lookup_entry_action_t` | `SAI_DIRECTION_LOOKUP_ENTRY_ACTION_SET_OUTBOUND_DIRECTION` | + +2. **ENI Lookup**: Then, we will use the inner MAC address to find the ENI pipeline. Then, the outer encap will be decap’ed, leaving inner packet going through the rest of pipeline. + + First, we use ENI ether address map table to find the ENI id: + + | SAI field name | Type | Value | + | --- | --- | --- | + | entry.address | `sai_mac_t` | `11-22-33-44-55-66` | + | entry_attr.SAI_ENI_ETHER_ADDRESS_MAP_ENTRY_ATTR_ENI_ID | `sai_object_id_t` | (SAI object ID of the ENI) | + + Then, we use the ENI id to find the ENI, which contains the PL underlay source IP as below: + + | SAI field name | Type | Value | + | --- | --- | --- | + | entry_attr.SAI_ENI_ATTR_PL_UNDERLAY_SIP | `sai_ip_address_t` | 2.2.2.1 | + +3. **Conntrack Lookup**: If flow already exists, we directly apply the transformation from the flow, otherwise, move on. +4. **ACL**: No changes in the ACL stage, it will work just like the other cases. +5. **Routing**: The inner destination IP (a.k.a. overlay dip) will be used for finding the route entry. This will trigger the maprouting action to run, which makes the packet entering Mapping stage. + + The routing stage could also have underlay source ip defined, but the `PL_UNDERLAY_SIP` will be used first, whenever the routing type is set to `privatelink`. + + The outbound routing entry will look like as below: + + | SAI field name | Type | Value | + | --- | --- | --- | + | entry.eni_id | `sai_object_id_t` | (SAI object ID of the ENI) | + | entry.destination | `sai_ip_prefix_t` | `10.0.1.0/24` | + | entry_attr.SAI_OUTBOUND_ROUTING_ENTRY_ATTR_ACTION | `sai_outbound_routing_entry_action_t` | `SAI_OUTBOUND_ROUTING_ENTRY_ACTION_ROUTE_VNET` | + | entry_attr.SAI_OUTBOUND_ROUTING_ENTRY_ATTR_DST_VNET_ID | `sai_object_id_t` | (SAI object ID of the destination VNET) | + | entry_attr.SAI_OUTBOUND_ROUTING_ENTRY_ATTR_METER_CLASS | `sai_uint16_t` | `60000` | + +6. **Mapping - VNET**: The inner destination IP will be used for finding the outbound CA-PA mapping entry, of which the routing type will be set to private link. + + | SAI field name | Type | Value | + | --- | --- | --- | + | entry.dst_vnet_id | `sai_object_id_t` | (SAI object ID of the destination VNET) | + | entry.dip | `sai_ip_address_t` | `10.0.1.1` | + | entry_attr.SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_ACTION | `sai_outbound_ca_to_pa_entry_action_t` | `SAI_OUTBOUND_CA_TO_PA_ENTRY_ACTION_SET_PRIVATE_LINK_MAPPING` | + | entry_attr.SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_UNDERLAY_DIP | `sai_ip_address_t` | `3.3.3.1` | + | entry_attr.SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_OVERLAY_DMAC | `sai_mac_t` | `99-88-77-66-55-44` | + | entry_attr.SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_OVERLAY_SIP | `sai_ip_address_t` | `9988::` | + | entry_attr.SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_OVERLAY_SIP_MASK | `sai_ip_address_t` | `FFFF:FFFF:FFFF:FFFF:FFFF:FFFF::` | + | entry_attr.SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_OVERLAY_DIP | `sai_ip_address_t` | `1122:3344:5566:7788::303:301/128` | + | entry_attr.SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_OVERLAY_DIP_MASK | `sai_ip_address_t` | `FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF` | + | entry_attr.SAI_OUTBOUND_ROUTING_ENTRY_ATTR_METER_CLASS | `sai_uint16_t` | `60001` | + +7. **Metering**: The last action we need to do is to find the corresponding metering rule. +8. **Conntrack Update**: Both forwarding and reverse flows will be created by this stage. +9. **Metering Update**: Metering update will update the metering counter based on the rules that we found before. +10. **Underlay routing**: Underlay routing will move the packet to the right port and forward it out. + +#### 6.1.2. Private Link NSG + +The changes needed for PL NSG is mostly the same as PL. In addition, on the VNET mapping, we need to provide the extra tunnel info. + +| SAI field name | Type | Value | +| --- | --- | --- | +| entry_attr.SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_TUNNEL_ID | `sai_object_id_t` | (SAI object ID of the NSG tunnel) | + +And we can use the tunnel next hop table to specify the tunnel information: + +| SAI field name | Type | Value | +| --- | --- | --- | +| entry_attr.SAI_DASH_TUNNEL_ENTRY_ATTR_DASH_ENCAPSULATION | `sai_dash_encapsulation_t` | `SAI_DASH_ENCAPSULATION_VXLAN` | +| entry_attr.SAI_DASH_TUNNEL_ENTRY_ATTR_VNI | `sai_uint32_t` | `2000000` | +| entry_attr.SAI_DASH_TUNNEL_NEXT_HOP_ENTRY_ATTR_DIP | `sai_ip_address_t` | `100.0.1.1` | + +### 6.2. PLS-to-VM direction + +On the return path, we will leverage the reverse flow that is created by the outbound side to process the packet and forward it back to the original source. + +Since the packet that being sent back to the VM in PL NSG scenario will be exactly the same as regular PL, and the reverse flow that being created in the PL NSG scenario will also be the same, there is nothing we need to change for the PL NSG case. + +The packet will go through the DASH pipeline as below: + +1. **Direction Lookup**: First, we will use the VNI to determine the packet direction. In this case, since Private Link Key is not in the outbound VNI list, we consider all the packets from PLS side as inbound direction. + +2. **ENI Lookup**: We will use the inner destination MAC address to find the ENI pipeline. Once found, the outer encap will be decap'ed, exposing the inner packet for later processing. + + The ENI entry that we are using will be the same as before. Hence, omitted here. + +3. **Conntrack Lookup**: The return packet transformation will be handled by reverse flow. +4. **Metering Update**: Metering update will update the metering counter based on the rules that we saved in the reverse flow. +5. **Underlay routing**: Underlay routing will move the packet to the right port and forward it out. + +## 7. DASH database schema + +For the DASH database schema, please refer to the [SONIC-DASH HLD](https://github.com/sonic-net/SONiC/blob/master/doc/dash/dash-sonic-hld.md). From 51df51331d4e64353bbc45faf246d515009263bd Mon Sep 17 00:00:00 2001 From: Riff Date: Fri, 26 Apr 2024 12:11:16 -0700 Subject: [PATCH 32/32] [doc] Add metering HLD (#544) --- documentation/metering/README.md | 9 ++ documentation/metering/metering.md | 154 +++++++++++++++++++++++++++++ 2 files changed, 163 insertions(+) create mode 100644 documentation/metering/README.md create mode 100644 documentation/metering/metering.md diff --git a/documentation/metering/README.md b/documentation/metering/README.md new file mode 100644 index 000000000..b6a028a54 --- /dev/null +++ b/documentation/metering/README.md @@ -0,0 +1,9 @@ +# DASH Metering Documents + +This folder contains DASH Metering design and requirements documents. + +## Design + +| Document | Description | +| --- | --- | +| [Metering](metering.md) | Metering design | diff --git a/documentation/metering/metering.md b/documentation/metering/metering.md new file mode 100644 index 000000000..de7c5db3a --- /dev/null +++ b/documentation/metering/metering.md @@ -0,0 +1,154 @@ +# DASH Metering HLD + +| Rev | Date | Author | Change Description | +| --- | ---- | ------ | ------------------ | +| 0.1 | 03/30/2024 | Riff Jiang | Initial version | +| 0.2 | 04/03/2024 | Riff Jiang | Updated meter class from 16 bits to 32 bits. Added capability for meter bucket. | + +1. [1. Background](#1-background) +2. [2. Resource modeling, requirement, and SLA](#2-resource-modeling-requirement-and-sla) + 1. [2.1. Resource modeling](#21-resource-modeling) + 2. [2.2. Scaling requirement](#22-scaling-requirement) + 3. [2.3. Reliability requirements](#23-reliability-requirements) +3. [3. SAI API design](#3-sai-api-design) + 1. [3.1. Meter bucket](#31-meter-bucket) + 2. [3.2. Policy-based meter attributes](#32-policy-based-meter-attributes) + 1. [3.2.1. Route attributes](#321-route-attributes) + 2. [3.2.2. Mapping attributes](#322-mapping-attributes) + 3. [3.2.3. Tunnel attributes](#323-tunnel-attributes) + 4. [3.2.4. Inbound route rule attributes](#324-inbound-route-rule-attributes) + 3. [3.3. Global meter policy](#33-global-meter-policy) + 1. [3.3.1. ENI](#331-eni) + 2. [3.3.2. Meter policy](#332-meter-policy) + 3. [3.3.3. Meter rule](#333-meter-rule) + 4. [3.4. Capability](#34-capability) +4. [4. Metering bucket selection in DASH pipeline](#4-metering-bucket-selection-in-dash-pipeline) + +## 1. Background + +To support billing, DASH introduced metering related objects as traffic counters. These counters are only used for billing purposes and not related to traffic policer or shaping. + +## 2. Resource modeling, requirement, and SLA + +### 2.1. Resource modeling + +- Each ENI will allocates a set of metering bucket for billing purposes. +- Metering bucket is indexed by a UINT32 number called metering class, which starts from 1. Meter class 0 will be reversed and considered as not set. +- Each metering bucket will contain 1 inbound counter and 1 outbound counter for at least counting bytes. +- Metering bucket shall reflect the traffic volume of the customer. This means: + - It shall only count the size of the overlay packet. + - On the outbound direction, it shall count the packets before the SDN transformation. + - On the inbound direction, it shall count the packets after the SDN transformation. + +### 2.2. Scaling requirement + +The scaling requirement for metering are listed as below: + +| Metric | Requirement | +| --- | --- | +| # of meter buckets per ENI | 4095 (2^12 – 1, 0 is considered as not set) | +| # of meter rules per meter policy | (TBD) | + +### 2.3. Reliability requirements + +In HA setup, the metering info should be stored as part of flow and replicated to the standby side. Whenever the primary failover, the metering class id should be still the same for each flow. + +The high level flow replication follows the same approach as the SmartSwitch HA design, hence omitted here. + +## 3. SAI API design + +The following attributes will be involved in determining the final metering buckets in DASH. + +### 3.1. Meter bucket + +| Attribute | Type | Default Value | Description | +| --- | --- | --- | --- | +| SAI_METER_BUCKET_ATTR_ENI_ID | `sai_object_id_t` | SAI_NULL_OBJECT_ID | ENI ID of this metering class. | +| SAI_METER_BUCKET_ATTR_METER_CLASS | `sai_uint32_t` | 0 | Meter class of this meter bucket. | + +To fetch the metering data from each meter bucket, we are going to leverage the SAI stats APIs, which provides get, get and clear and other frequently used semantics. It will also reduce the work in SONiC stack, as SONiC already have good support over the stats APIs. + +| Attribute | Description | +| --- | --- | +| SAI_METER_BUCKET_STAT_OUTBOUND_BYTES | Total outbound traffic in bytes. | +| SAI_METER_BUCKET_STAT_INBOUND_BYTES | Total inbound traffic in bytes. | + +### 3.2. Policy-based meter attributes + +#### 3.2.1. Route attributes + +| Attribute | Type | Default Value | Description | +| --- | --- | --- | --- | +| SAI_OUTBOUND_ROUTING_ENTRY_ATTR_METER_CLASS_OR | `sai_uint32_t` | 0 | Meter class OR bits. | +| SAI_OUTBOUND_ROUTING_ENTRY_ATTR_METER_CLASS_AND | `sai_uint32_t` | UINT32_MAX | Meter class AND bits. | + +#### 3.2.2. Mapping attributes + +| Attribute | Type | Default Value | Description | +| --- | --- | --- | --- | +| SAI_OUTBOUND_CA_TO_PA_ENTRY_ATTR_METER_CLASS_OR | `sai_uint32_t` | 0 | Meter class OR bits. | + +#### 3.2.3. Tunnel attributes + +| Attribute | Type | Default Value | Description | +| --- | --- | --- | --- | +| SAI_DASH_TUNNEL_ATTR_METER_CLASS_OR | `sai_uint32_t` | 0 | Meter class OR bits. | + +#### 3.2.4. Inbound route rule attributes + +| Attribute | Type | Default Value | Description | +| --- | --- | --- | --- | +| SAI_INBOUND_ROUTING_ENTRY_ATTR_METER_CLASS_OR | `sai_uint32_t` | 0 | Meter class OR bits. | +| SAI_INBOUND_ROUTING_ENTRY_ATTR_METER_CLASS_AND | `sai_uint32_t` | UINT32_MAX | Meter class AND bits. | + +### 3.3. Global meter policy + +#### 3.3.1. ENI + +| Attribute | Type | Default Value | Description | +| --- | --- | --- | --- | +| SAI_ENI_ATTR_V4_METER_POLICY_ID | `sai_object_id_t` | SAI_NULL_OBJECT_ID | Global IPv4 meter policy ID for this ENI. | +| SAI_ENI_ATTR_V6_METER_POLICY_ID | `sai_object_id_t` | SAI_NULL_OBJECT_ID | Global IPv6 meter policy ID for this ENI. | + +#### 3.3.2. Meter policy + +| Attribute | Type | Default Value | Description | +| --- | --- | --- | --- | +| SAI_METER_POLICY_ATTR_IP_ADDR_FAMILY | `sai_ip_addr_family_t` | SAI_IP_ADDR_FAMILY_IPV4 | IP address family of the metering policy | + +#### 3.3.3. Meter rule + +| Attribute | Type | Default Value | Description | +| --- | --- | --- | --- | +| SAI_METER_RULE_ATTR_METER_POLICY_ID | `sai_object_id_t` | SAI_NULL_OBJECT_ID | Meter policy ID of this meter rule. | +| SAI_METER_RULE_ATTR_METER_CLASS | `sai_uint32_t` | UINT32_MAX | Meter class when this meter rule is hit. | +| SAI_METER_RULE_ATTR_DIP | `sai_ip_address_t` | NA | Destination IP for ternary match. | +| SAI_METER_RULE_ATTR_DIP_MASK | `sai_ip_address_t` | NA | Destination IP mask for ternary match. | +| SAI_METER_RULE_ATTR_PRIORITY | `sai_uint32_t` | NA | Priority required for ternary match. | + +### 3.4. Capability + +To enable the DASH providers be able to tell the host how much metering buckets are supported, we are going to introduce a new capability attributes: + +| Attribute | Type | Description | +| --- | --- | --- | +| SAI_SWITCH_ATTR_DASH_CAPS_MAX_METER_BUCKET_COUNT_PER_ENI | `sai_uint32_t` | Max number of meter buckets per ENI supported by the DASH implementation. | + +## 4. Metering bucket selection in DASH pipeline + +In DASH, the packet shall be metered following the approach below. + +When a packet arrives at an ENI, it will go through the steps below to find its metering bucket: + +1. **Init**: `AggregatedMeterClassOR` = 0, `AggregatedMeterClassAND` = UINT32_MAX. +2. **Conntrack Lookup**: In Conntrack Lookup stage, if a valid flow is hit, the meter class stored in that flow shall be used for locating the metering bucket. +3. **Policy match stages (Routing/Mapping)**: When flow is missing, the packet will go to slow path and walk through all the policy match stages. Depends on the stage it goes through, it will pick up the meter class OR bits and AND bits, and these 2 bits shall be aggregated separately: + 1. `AggregatedMeterClassOR` = `AggregatedMeterClassOR` | `MeterClassOR` + 2. `AggregatedMeterClassAND` = `AggregatedMeterClassAND` & `MeterClassAND` +4. **After policy match stages**: Now we calculates the meter class as below: + 1. `MeterClass` = `AggregatedMeterClassOR` & `AggregatedMeterClassAND` + 2. This allows us to use the info from routing entry to override the some meter class bits set in the mapping. +5. **Metering**: If `MeterClass` is 0 at this moment, meter policy will be used for determining which meter class shall be used: + 1. Meter policy v4 or v6 will be selected based on the IP family of the original overlay packet. + 2. The overlay destination (outbound pipeline) / source (inbound pipeline) IP will be used for ternary match against the meter rules in the meter policy to find the meter class. +6. **Meter Update**: The final meter class will be used for update the counters in meter bucket. If final meter class is 0, no meter bucket will be updated.