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 diff --git a/.wordlist.txt b/.wordlist.txt index 1b0b6257f..b204d5f33 100644 --- a/.wordlist.txt +++ b/.wordlist.txt @@ -6,6 +6,7 @@ Accton ACK Ack ack +ack'ed acl ACL ACLs @@ -37,6 +38,7 @@ AspNet assignees asyncE atlassian +attr ATTR auditability autogenerate @@ -304,6 +306,7 @@ IxLoad ixload IxNetwork IxNetworkWeb +Jiang Jinja jitter journaled @@ -372,6 +375,7 @@ NonSynStateful NorthBound Novus NPL +NPU NPUS NSG NSGs @@ -421,6 +425,7 @@ performant pingmesh PIR pluggable +PLS PLVision's PKTS pmon @@ -471,11 +476,13 @@ README READMEs README's reconvergence +RECV RedirectRuleResimulatedUf redis renderer repo repos +REQ resimulated resimulation responder @@ -528,12 +535,14 @@ sharding SInce SKU SKUs +SLA SLB SMAC 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/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 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 diff --git a/dash-pipeline/SAI/sai_api_gen.py b/dash-pipeline/SAI/sai_api_gen.py index 3b94645eb..8166bd05b 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']) @@ -516,6 +518,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 +600,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 +618,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 @@ -695,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/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 { 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/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 %} 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/SAI/templates/saiapi.h.j2 b/dash-pipeline/SAI/templates/saiapi.h.j2 index 7f5443df7..c6eeb178d 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 * @@ -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 %} @@ -208,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' %} 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; diff --git a/dash-pipeline/bmv2/dash_arch_specific.p4 b/dash-pipeline/bmv2/dash_arch_specific.p4 index dbd59b2f8..978a6ef07 100644 --- a/dash-pipeline/bmv2/dash_arch_specific.p4 +++ b/dash-pipeline/bmv2/dash_arch_specific.p4 @@ -1,18 +1,93 @@ #ifndef __DASH_TARGET_SPECIFIC__ #define __DASH_TARGET_SPECIFIC__ -#ifdef TARGET_BMV2_V1MODEL +// +// P4 arch/target includes +// +#if defined(TARGET_BMV2_V1MODEL) + #include +#elif defined(TARGET_DPDK_PNA) // TARGET_BMV2_V1MODEL + #include +#endif // TARGET_DPDK_PNA + +// +// 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; -#include -#define DIRECT_COUNTER_TABLE_PROPERTY counters + #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 DEFINE_HIT_COUNTER(name, count, ...) \ + @SaiCounter[__VA_ARGS__, no_suffix="true"] \ + counter(count, CounterType.packets) name; -#include -#define DIRECT_COUNTER_TABLE_PROPERTY pna_direct_counter + #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 DEFINE_HIT_COUNTER(name, count, ...) + #define UPDATE_COUNTER(name, index) + + #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 +// - 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 + +// +// 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_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_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 15f89d247..40148d3c6 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 @@ -35,9 +34,9 @@ control inbound(inout headers_t hdr, ConntrackOut.apply(hdr, meta); #endif //PNA_CONNTRACK - tunnel_encap(hdr, + do_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 f0c2c6311..8279561f5 100644 --- a/dash-pipeline/bmv2/dash_metadata.p4 +++ b/dash-pipeline/bmv2/dash_metadata.p4 @@ -3,25 +3,54 @@ #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; - bit<24> service_tunnel_key; - IPv4Address original_overlay_sip; - IPv4Address original_overlay_dip; -} +#define MAX_ENI 64 +#define MAX_HA_SET 1 + +enum bit<32> dash_routing_actions_t { + NONE = 0, + STATIC_ENCAP = (1 << 0), + NAT = (1 << 1), + NAT46 = (1 << 2), + NAT64 = (1 << 3), + NAT_PORT = (1 << 4) +}; 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 { + INVALID = 0, + + // Inbound stages + INBOUND_STAGE_START = 100, + + // Outbound stages + 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 +}; struct conntrack_data_t { bool allow_in; @@ -29,9 +58,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 { @@ -42,14 +70,87 @@ 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; + IPv4Address underlay_sip; + IPv4Address underlay_dip; + EthernetAddress underlay_smac; + EthernetAddress underlay_dmac; + dash_encapsulation_t dash_encapsulation; +} + +struct overlay_rewrite_data_t { + bool is_ipv6; + EthernetAddress dmac; + IPv4ORv6Address sip; + IPv4ORv6Address dip; + IPv6Address sip_mask; + 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 { - bool dropped; + // 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; - encap_data_t encap_data; EthernetAddress eni_addr; bit<16> vnet_id; bit<16> dst_vnet_id; @@ -71,17 +172,25 @@ 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; + + // Stage transition control + dash_pipeline_stage_t target_stage; + + // Actions + bit<32> routing_actions; + + // Action data + 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_outbound.p4 b/dash-pipeline/bmv2/dash_outbound.p4 index 1b1128651..8440b7a84 100644 --- a/dash-pipeline/bmv2/dash_outbound.p4 +++ b/dash-pipeline/bmv2/dash_outbound.p4 @@ -1,232 +1,19 @@ -#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_conntrack.p4" -#include "dash_service_tunnel.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) { - 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.service_tunnel_key = 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 -#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 - - @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; /* for expressroute - ecmp of overlay */ - route_vnet_direct; - route_direct; - route_service_tunnel; - drop; - } - const default_action = drop; - -#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 - } - - 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 -#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 - - @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; - set_private_link_mapping; - @defaultonly drop; - } - const default_action = drop; - -#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 - } - - 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); + ConntrackOut.apply(0); #endif /* STATEFUL_P4 */ #ifdef PNA_CONNTRACK @@ -239,7 +26,7 @@ control outbound(inout headers_t hdr, } #ifdef STATEFUL_P4 - ConntrackIn.apply(1); + ConntrackIn.apply(1); #endif /* STATEFUL_P4 */ #ifdef PNA_CONNTRACK @@ -249,38 +36,11 @@ 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); - 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); - } - } + outbound_pre_routing_action_apply_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 af8ce46ce..0b84b8570 100644 --- a/dash-pipeline/bmv2/dash_pipeline.p4 +++ b/dash-pipeline/bmv2/dash_pipeline.p4 @@ -8,10 +8,13 @@ #include "dash_outbound.p4" #include "dash_inbound.p4" #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 @@ -40,12 +43,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; - @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_icmp_in_counter, 1, name="lb_fast_path_icmp_in", attr_type="stats") @SaiTable[name = "vip", api = "dash_vip"] table vip { @@ -61,28 +59,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; @@ -115,15 +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; -#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_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> bw, 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, @@ -133,7 +113,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), @@ -158,19 +138,26 @@ 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; meta.fast_path_icmp_flow_redirection_disabled = disable_fast_path_icmp_flow_redirection; } @@ -187,50 +174,26 @@ 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 - - @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; } - -#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 + action permit() { } - action permit() { + action vxlan_decap() {} + action vxlan_decap_pa_validate() {} + + action tunnel_decap(inout headers_t hdr, + 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(@SaiVal[type="sai_object_id_t"] bit<16> src_vnet_id) { + action tunnel_decap_pa_validate(inout headers_t hdr, + inout metadata_t meta, + @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"] @@ -257,95 +220,15 @@ control dash_ingress( } actions = { tunnel_decap(hdr, meta); - tunnel_decap_pa_validate; + 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; } 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) { @@ -385,9 +268,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) { @@ -395,47 +276,32 @@ 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_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) { - 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(); - 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; @@ -465,24 +331,31 @@ 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) { -#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(); + 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); } + routing_action_apply.apply(hdr, meta); + /* Underlay routing */ meta.dst_ip_addr = (bit<128>)hdr.u0_ipv4.dst_addr; + underlay.apply( hdr , meta @@ -494,41 +367,22 @@ 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(); + } 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/dash_routing_types.p4 b/dash-pipeline/bmv2/dash_routing_types.p4 new file mode 100644 index 000000000..a29053dbf --- /dev/null +++ b/dash-pipeline/bmv2/dash_routing_types.p4 @@ -0,0 +1,185 @@ +#ifndef _DASH_ROUTING_TYPES_P4_ +#define _DASH_ROUTING_TYPES_P4_ + +#include "dash_headers.p4" +#include "routing_actions/routing_actions.p4" + +action set_meter_attrs( + inout metadata_t meta, + bit<32> meter_class_or, + bit<32> meter_class_and) +{ + 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: +action drop(inout metadata_t meta) { + meta.target_stage = dash_pipeline_stage_t.OUTBOUND_PRE_ROUTING_ACTION_APPLY; + 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<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_meter_attrs(meta, meter_class_or, meter_class_and); +} + +// 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<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_meter_attrs(meta, meter_class_or, meter_class_and); +} + +// 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<32> meter_class_or, + @SaiVal[default_value="4294967295"] bit<32> meter_class_and) +{ + meta.target_stage = dash_pipeline_stage_t.OUTBOUND_PRE_ROUTING_ACTION_APPLY; + set_meter_attrs(meta, meter_class_or, meter_class_and); +} + +// 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<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); + 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.OUTBOUND_PRE_ROUTING_ACTION_APPLY; + + 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 ? 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 + + set_meter_attrs(meta, meter_class_or, meter_class_and); +} + +// 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<32> meter_class_or) +{ + 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; + + push_action_static_encap(hdr = hdr, + meta = meta, + underlay_dip = underlay_dip, + overlay_dmac = overlay_dmac); + + set_meter_attrs(meta, meter_class_or, 0xffffffff); +} + +// 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<32> meter_class_or) +{ + meta.target_stage = dash_pipeline_stage_t.OUTBOUND_PRE_ROUTING_ACTION_APPLY; + + 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_meter_attrs(meta, meter_class_or, 0xffffffff); +} + +#endif /* _DASH_ROUTING_TYPES_P4_ */ \ No newline at end of file diff --git a/dash-pipeline/bmv2/dash_tunnel.p4 b/dash-pipeline/bmv2/dash_tunnel.p4 index 125b43516..4d39f5e65 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; \ @@ -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 @@ -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, \ @@ -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, \ @@ -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(); 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/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..fc94965df --- /dev/null +++ b/dash-pipeline/bmv2/stages/eni_lookup.p4 @@ -0,0 +1,45 @@ +#ifndef _DASH_STAGE_ENI_LOOKUP_P4_ +#define _DASH_STAGE_ENI_LOOKUP_P4_ + +control eni_lookup_stage( + inout headers_t hdr, + inout metadata_t meta) +{ + 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; + } + + 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) { + UPDATE_COUNTER(port_lb_fast_path_eni_miss_counter, 0); + } + } + } +} + +#endif /* _DASH_STAGE_ENI_LOOKUP_P4_ */ \ No newline at end of file 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/bmv2/stages/metering_update.p4 b/dash-pipeline/bmv2/stages/metering_update.p4 new file mode 100644 index 000000000..83439fa6b --- /dev/null +++ b/dash-pipeline/bmv2/stages/metering_update.p4 @@ -0,0 +1,104 @@ +#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_context.meter_policy_id : exact; + } + actions = { + check_ip_addr_family; + } + } + + 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_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 = { + 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 + 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 { + 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 { + 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_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); + } + } + + eni_meter.apply(); + } +} + +#endif /* _DASH_STAGE_METERING_UPDATE_P4_ */ \ No newline at end of file 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_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 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 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 diff --git a/dash-pipeline/tests/libsai/vnet_out/vnet_out.cpp b/dash-pipeline/tests/libsai/vnet_out/vnet_out.cpp index 3d636cf95..e98c8d960 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, @@ -220,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/dash-pipeline/tests/saithrift/pytest/vnet/test_saithrift_vnet.py b/dash-pipeline/tests/saithrift/pytest/vnet/test_saithrift_vnet.py index 3ff91f8d8..15ad3d256 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, bw=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/general/dash-sonic-hld.md b/documentation/general/dash-sonic-hld.md index 988b12685..ca4e52388 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" }, 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/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. 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). 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 000000000..ab25150f6 Binary files /dev/null and b/slides/Srikanth Kandula In Network Transformations for AI_ML.pdf differ diff --git a/test/SAI-Challenger b/test/SAI-Challenger index 95edf36d1..46b4c330f 160000 --- a/test/SAI-Challenger +++ b/test/SAI-Challenger @@ -1 +1 @@ -Subproject commit 95edf36d124f098d04b9f3ed984fe404959c9662 +Subproject commit 46b4c330fcf5cc8422043b9186a1a10f9d66a74b 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/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 3639c6e46..a15d69215 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): "bw": 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, @@ -239,16 +240,17 @@ 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, - src_vnet_id=src_vnet_id) + action=SAI_INBOUND_ROUTING_ENTRY_ACTION_TUNNEL_DECAP_PA_VALIDATE, + 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 @@ -256,15 +258,16 @@ 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, + 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 @@ -304,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) @@ -320,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) @@ -338,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) @@ -358,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) @@ -442,8 +445,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): @@ -547,10 +550,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 +606,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 +971,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 +979,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 +1024,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 +1032,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 +1120,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 +1182,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 +1277,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 +1285,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 +1294,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 +1302,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 +1357,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 +1365,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 +1374,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 +1382,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 +1472,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 +1480,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 bc19f887f..c3f11c232 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__()) @@ -194,6 +192,7 @@ def setUpSwitch(self): self.eni = self.create_obj(sai_thrift_create_eni, sai_thrift_remove_eni, cps=10000, bw=100000, flows=100000, admin_state=True, + ha_scope_id=0, vm_underlay_dip=vm_underlay_dip, vm_vni=9, vnet_id=self.vnet, @@ -244,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)) @@ -253,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/saidasheni.py b/test/test-cases/functional/ptf/saidasheni.py index 5c5af2408..b3cb8a0b4 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..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,11 +116,10 @@ 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 - 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 @@ -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,12 +203,11 @@ 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 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 +222,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 @@ -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() @@ -243,7 +242,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 @@ -251,17 +250,16 @@ 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 - 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 @@ -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,12 +313,11 @@ 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 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 +332,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 @@ -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() @@ -354,7 +352,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 @@ -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,11 +1108,10 @@ 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 - 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 @@ -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,12 +1227,11 @@ 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 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 @@ -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) @@ -1320,7 +1328,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 @@ -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) @@ -1339,7 +1347,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 @@ -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) diff --git a/test/test-cases/functional/ptf/saidashvnet_sanity.py b/test/test-cases/functional/ptf/saidashvnet_sanity.py index 8cceffeaf..73b2c4189 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, bw=100000, flows=100000, admin_state=True, + ha_scope_id=0, vm_underlay_dip=vm_underlay_dip, vm_vni=9, vnet_id=self.vnet, @@ -130,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, @@ -138,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") @@ -232,10 +233,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 +387,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 adf98d823..a47167c02 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_BW", "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_BW", "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_BW", "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", @@ -222,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" ] }, @@ -234,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" ] }, @@ -246,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" ] }, @@ -261,8 +267,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" ] }, { @@ -277,8 +283,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" ] }, { @@ -293,8 +299,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" ] }, { @@ -311,9 +317,13 @@ }, "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" + "$vnet", + "SAI_INBOUND_ROUTING_ENTRY_ATTR_METER_CLASS_OR", + "0", + "SAI_INBOUND_ROUTING_ENTRY_ATTR_METER_CLASS_AND", + "-1" ] }, { @@ -330,9 +340,13 @@ }, "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" + "$vnet", + "SAI_INBOUND_ROUTING_ENTRY_ATTR_METER_CLASS_OR", + "0", + "SAI_INBOUND_ROUTING_ENTRY_ATTR_METER_CLASS_AND", + "-1" ] }, { @@ -349,9 +363,13 @@ }, "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" + "$vnet", + "SAI_INBOUND_ROUTING_ENTRY_ATTR_METER_CLASS_OR", + "0", + "SAI_INBOUND_ROUTING_ENTRY_ATTR_METER_CLASS_AND", + "-1" ] }, { @@ -367,8 +385,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" ] }, { @@ -384,8 +401,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" ] }, { @@ -401,8 +417,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 695601758..3e72b311f 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", @@ -254,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" ] @@ -267,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" ] @@ -285,9 +293,13 @@ }, "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" + "$vnet_#1", + "SAI_INBOUND_ROUTING_ENTRY_ATTR_METER_CLASS_OR", + "0", + "SAI_INBOUND_ROUTING_ENTRY_ATTR_METER_CLASS_AND", + "-1" ] }, { @@ -304,9 +316,13 @@ }, "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" + "$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 b4fd14735..544c7dade 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_BW", "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_BW", "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", @@ -154,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" ] }, @@ -166,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" ] }, @@ -181,8 +185,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" ] }, { @@ -197,8 +201,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" ] }, @@ -215,8 +219,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" ] }, { @@ -232,8 +235,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_eni.py b/test/test-cases/functional/saic/sai-api/test_sai_api_vnet_eni.py index 1aa2e93bd..850e6464c 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_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/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 695fdb5ec..2fb31ca17 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", @@ -132,9 +134,13 @@ 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" + "$vnet", + "SAI_INBOUND_ROUTING_ENTRY_ATTR_METER_CLASS_OR", + "0", + "SAI_INBOUND_ROUTING_ENTRY_ATTR_METER_CLASS_AND", + "-1" ] }, ] @@ -175,7 +181,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/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 da15c78f2..59399d055 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", @@ -126,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" ] }, ] @@ -165,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/test_vm_to_vm_commn_acl_inbound.py b/test/test-cases/functional/saic/test_vm_to_vm_commn_acl_inbound.py index 3d25c0bc9..757dc8c33 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 d2228613f..2a38fc8f9 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 7e652b456..75d0490f7 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 c1c2ac18b..72a0cfb21 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 580554957..fba95dddc 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/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..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 @@ -63,13 +63,12 @@ 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' ]) + 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 4dce1f917..d4928bd56 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", @@ -237,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" ] @@ -250,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" ] @@ -268,10 +276,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" ] }, { @@ -288,10 +296,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" ] }, { @@ -310,10 +318,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" ] }, { @@ -332,10 +338,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_inbound.py b/test/test-cases/scale/saic/test_sai_vnet_inbound.py index 367b4a1b0..9764bb0ac 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_scale.py b/test/test-cases/scale/saic/test_sai_vnet_outbound_scale.py index cbabf50d2..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 @@ -116,13 +116,13 @@ 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' ]) + 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/test_sai_vnet_outbound_simple.py b/test/test-cases/scale/saic/test_sai_vnet_outbound_simple.py index 65f4dd8f1..1f7006103 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 d27f24b74..2fbcaca22 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 7231676c6..bbd1022a4 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", @@ -138,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" ] @@ -156,9 +160,13 @@ }, "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" + "$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 d1af58bc3..777833af6 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_BW", "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_BW", "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", @@ -192,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" ] }, @@ -204,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" ] }, @@ -219,8 +223,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" ] }, { @@ -235,8 +239,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" ] }, { @@ -251,8 +255,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" ] }, { @@ -267,8 +271,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" ] }, { @@ -284,8 +288,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" ] }, { @@ -301,8 +304,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" ] }, { @@ -318,8 +320,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" ] }, { @@ -335,8 +336,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" ] }, { @@ -352,8 +352,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" ] }, { @@ -369,8 +368,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" ] }, { @@ -386,8 +384,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" ] }, { @@ -403,8 +400,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 eaabaca00..ff15603a5 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_BW", "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", @@ -98,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" ] }, @@ -113,8 +115,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" ] }, { @@ -130,8 +132,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 b22c84c80..8fc2d4282 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", @@ -430,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" ] @@ -443,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" ] @@ -461,10 +473,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" ] }, { @@ -481,10 +493,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" ] }, { @@ -503,10 +515,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" ] }, { @@ -525,10 +535,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" ] }, { @@ -547,10 +555,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" ] }, { @@ -569,10 +575,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 21add0082..d1caf856e 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", @@ -138,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" ] @@ -156,10 +160,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" ] }, { @@ -178,10 +182,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" ] } ]