diff --git a/orchagent/routeorch.cpp b/orchagent/routeorch.cpp index 05606f2fb65a..e3c27b98182a 100644 --- a/orchagent/routeorch.cpp +++ b/orchagent/routeorch.cpp @@ -376,6 +376,13 @@ bool RouteOrch::validnexthopinNextHopGroup(const NextHopKey &nexthop, uint32_t& nhgm_attrs.push_back(nhgm_attr); } + if (m_switchOrch->checkOrderedEcmpEnable()) + { + nhgm_attr.id = SAI_NEXT_HOP_GROUP_MEMBER_ATTR_SEQUENCE_ID; + nhgm_attr.value.u32 = nhopgroup->second.nhopgroup_members[nexthop].seq_id; + nhgm_attrs.push_back(nhgm_attr); + } + status = sai_next_hop_group_api->create_next_hop_group_member(&nexthop_id, gSwitchId, (uint32_t)nhgm_attrs.size(), nhgm_attrs.data()); @@ -393,7 +400,7 @@ bool RouteOrch::validnexthopinNextHopGroup(const NextHopKey &nexthop, uint32_t& ++count; gCrmOrch->incCrmResUsedCounter(CrmResourceType::CRM_NEXTHOP_GROUP_MEMBER); - nhopgroup->second.nhopgroup_members[nexthop] = nexthop_id; + nhopgroup->second.nhopgroup_members[nexthop].next_hop_id = nexthop_id; } if (!m_fgNhgOrch->validNextHopInNextHopGroup(nexthop)) @@ -421,7 +428,7 @@ bool RouteOrch::invalidnexthopinNextHopGroup(const NextHopKey &nexthop, uint32_t continue; } - nexthop_id = nhopgroup->second.nhopgroup_members[nexthop]; + nexthop_id = nhopgroup->second.nhopgroup_members[nexthop].next_hop_id; status = sai_next_hop_group_api->remove_next_hop_group_member(nexthop_id); if (status != SAI_STATUS_SUCCESS) @@ -1241,7 +1248,7 @@ bool RouteOrch::addNextHopGroup(const NextHopGroupKey &nexthops) vector nhg_attrs; nhg_attr.id = SAI_NEXT_HOP_GROUP_ATTR_TYPE; - nhg_attr.value.s32 = SAI_NEXT_HOP_GROUP_TYPE_ECMP; + nhg_attr.value.s32 = m_switchOrch->checkOrderedEcmpEnable() ? SAI_NEXT_HOP_GROUP_TYPE_DYNAMIC_ORDERED_ECMP : SAI_NEXT_HOP_GROUP_TYPE_ECMP; nhg_attrs.push_back(nhg_attr); sai_object_id_t next_hop_group_id; @@ -1295,6 +1302,13 @@ bool RouteOrch::addNextHopGroup(const NextHopGroupKey &nexthops) nhgm_attrs.push_back(nhgm_attr); } + if (m_switchOrch->checkOrderedEcmpEnable()) + { + nhgm_attr.id = SAI_NEXT_HOP_GROUP_MEMBER_ATTR_SEQUENCE_ID; + nhgm_attr.value.u32 = ((uint32_t)i) + 1; // To make non-zero sequence id + nhgm_attrs.push_back(nhgm_attr); + } + gNextHopGroupMemberBulker.create_entry(&nhgm_ids[i], (uint32_t)nhgm_attrs.size(), nhgm_attrs.data()); @@ -1319,7 +1333,8 @@ bool RouteOrch::addNextHopGroup(const NextHopGroupKey &nexthops) if (nhopgroup_shared_set.find(nhid) != nhopgroup_shared_set.end()) { auto it = nhopgroup_shared_set[nhid].begin(); - next_hop_group_entry.nhopgroup_members[*it] = nhgm_id; + next_hop_group_entry.nhopgroup_members[*it].next_hop_id = nhgm_id; + next_hop_group_entry.nhopgroup_members[*it].seq_id = (uint32_t)i + 1; nhopgroup_shared_set[nhid].erase(it); if (nhopgroup_shared_set[nhid].empty()) { @@ -1328,7 +1343,8 @@ bool RouteOrch::addNextHopGroup(const NextHopGroupKey &nexthops) } else { - next_hop_group_entry.nhopgroup_members[nhopgroup_members_set.find(nhid)->second] = nhgm_id; + next_hop_group_entry.nhopgroup_members[nhopgroup_members_set.find(nhid)->second].next_hop_id = nhgm_id; + next_hop_group_entry.nhopgroup_members[nhopgroup_members_set.find(nhid)->second].seq_id = ((uint32_t)i) + 1; } } @@ -1373,12 +1389,12 @@ bool RouteOrch::removeNextHopGroup(const NextHopGroupKey &nexthops) if (m_neighOrch->isNextHopFlagSet(nhop->first, NHFLAGS_IFDOWN)) { SWSS_LOG_WARN("NHFLAGS_IFDOWN set for next hop group member %s with next_hop_id %" PRIx64, - nhop->first.to_string().c_str(), nhop->second); + nhop->first.to_string().c_str(), nhop->second.next_hop_id); nhop = nhgm.erase(nhop); continue; } - next_hop_ids.push_back(nhop->second); + next_hop_ids.push_back(nhop->second.next_hop_id); nhop = nhgm.erase(nhop); } diff --git a/orchagent/routeorch.h b/orchagent/routeorch.h index 22756ad176f3..2c8826ecf7a3 100644 --- a/orchagent/routeorch.h +++ b/orchagent/routeorch.h @@ -24,7 +24,13 @@ #define LOOPBACK_PREFIX "Loopback" -typedef std::map NextHopGroupMembers; +struct NextHopGroupMemberEntry +{ + sai_object_id_t next_hop_id; // next hop sai oid + uint32_t seq_id; // Sequence Id of nexthop in the group +}; + +typedef std::map NextHopGroupMembers; struct NhgBase; diff --git a/orchagent/switchorch.cpp b/orchagent/switchorch.cpp index 325bf2a3de20..48ecd1fd350f 100644 --- a/orchagent/switchorch.cpp +++ b/orchagent/switchorch.cpp @@ -1,4 +1,5 @@ #include +#include #include #include "switchorch.h" @@ -44,6 +45,9 @@ const map packet_action_map = {"trap", SAI_PACKET_ACTION_TRAP} }; + +const std::set switch_non_sai_attribute_set = {"ordered_ecmp"}; + SwitchOrch::SwitchOrch(DBConnector *db, vector& connectors, TableConnector switchTable): Orch(connectors), m_switchTable(switchTable.first, switchTable.second), @@ -224,7 +228,51 @@ void SwitchOrch::doCfgSensorsTableTask(Consumer &consumer) } } +void SwitchOrch::setSwitchNonSaiAttributes(swss::FieldValueTuple &val) +{ + auto attribute = fvField(val); + auto value = fvValue(val); + if (attribute == "ordered_ecmp") + { + vector fvVector; + if (value == "true") + { + const auto* meta = sai_metadata_get_attr_metadata(SAI_OBJECT_TYPE_NEXT_HOP_GROUP, SAI_NEXT_HOP_GROUP_ATTR_TYPE); + if (meta && meta->isenum) + { + vector values_list(meta->enummetadata->valuescount); + sai_s32_list_t values; + values.count = static_cast(values_list.size()); + values.list = values_list.data(); + + auto status = sai_query_attribute_enum_values_capability(gSwitchId, + SAI_OBJECT_TYPE_NEXT_HOP_GROUP, + SAI_NEXT_HOP_GROUP_ATTR_TYPE, + &values); + if (status == SAI_STATUS_SUCCESS) + { + for (size_t i = 0; i < values.count; i++) + { + if (values.list[i] == SAI_NEXT_HOP_GROUP_TYPE_DYNAMIC_ORDERED_ECMP) + { + m_orderedEcmpEnable = true; + fvVector.emplace_back(SWITCH_CAPABILITY_TABLE_ORDERED_ECMP_CAPABLE, "true"); + set_switch_capability(fvVector); + SWSS_LOG_NOTICE("Ordered ECMP/Nexthop-Group is configured"); + return; + } + } + } + } + } + m_orderedEcmpEnable = false; + fvVector.emplace_back(SWITCH_CAPABILITY_TABLE_ORDERED_ECMP_CAPABLE, "false"); + set_switch_capability(fvVector); + SWSS_LOG_NOTICE("Ordered ECMP/Nexthop-Group is not configured"); + return; + } +} sai_status_t SwitchOrch::setSwitchTunnelVxlanParams(swss::FieldValueTuple &val) { auto attribute = fvField(val); @@ -296,7 +344,12 @@ void SwitchOrch::doAppSwitchTableTask(Consumer &consumer) { auto attribute = fvField(i); - if (switch_attribute_map.find(attribute) == switch_attribute_map.end()) + if (switch_non_sai_attribute_set.find(attribute) != switch_non_sai_attribute_set.end()) + { + setSwitchNonSaiAttributes(i); + continue; + } + else if (switch_attribute_map.find(attribute) == switch_attribute_map.end()) { // Check additionally 'switch_tunnel_attribute_map' for Switch Tunnel if (switch_tunnel_attribute_map.find(attribute) == switch_tunnel_attribute_map.end()) diff --git a/orchagent/switchorch.h b/orchagent/switchorch.h index 8c3789f52350..5b09a6764083 100644 --- a/orchagent/switchorch.h +++ b/orchagent/switchorch.h @@ -10,6 +10,7 @@ #define SWITCH_CAPABILITY_TABLE_PORT_TPID_CAPABLE "PORT_TPID_CAPABLE" #define SWITCH_CAPABILITY_TABLE_LAG_TPID_CAPABLE "LAG_TPID_CAPABLE" +#define SWITCH_CAPABILITY_TABLE_ORDERED_ECMP_CAPABLE "ORDERED_ECMP_CAPABLE" struct WarmRestartCheck { @@ -37,6 +38,8 @@ class SwitchOrch : public Orch // Initialize the ACL groups bind to Switch void initAclGroupsBindToSwitch(); + bool checkOrderedEcmpEnable() { return m_orderedEcmpEnable; } + private: void doTask(Consumer &consumer); void doTask(swss::SelectableTimer &timer); @@ -45,6 +48,8 @@ class SwitchOrch : public Orch void initSensorsTable(); void querySwitchTpidCapability(); sai_status_t setSwitchTunnelVxlanParams(swss::FieldValueTuple &val); + void setSwitchNonSaiAttributes(swss::FieldValueTuple &val); + // Create the default ACL group for the given stage, bind point is // SAI_ACL_BIND_POINT_TYPE_SWITCH and group type is @@ -74,6 +79,7 @@ class SwitchOrch : public Orch bool m_sensorsMaxTempSupported = true; bool m_sensorsAvgTempSupported = true; bool m_vxlanSportUserModeEnabled = false; + bool m_orderedEcmpEnable = false; // Information contained in the request from // external program for orchagent pre-shutdown state check diff --git a/orchagent/vnetorch.cpp b/orchagent/vnetorch.cpp index d1d117f094a0..9640e0ee3ab7 100644 --- a/orchagent/vnetorch.cpp +++ b/orchagent/vnetorch.cpp @@ -40,7 +40,7 @@ extern CrmOrch *gCrmOrch; extern RouteOrch *gRouteOrch; extern MacAddress gVxlanMacAddress; extern BfdOrch *gBfdOrch; - +extern SwitchOrch *gSwitchOrch; /* * VRF Modeling and VNetVrf class definitions */ @@ -680,9 +680,12 @@ bool VNetRouteOrch::addNextHopGroup(const string& vnet, const NextHopGroupKey &n vector next_hop_ids; set next_hop_set = nexthops.getNextHops(); std::map nhopgroup_members_set; + std::map nh_seq_id_in_nhgrp; + uint32_t seq_id = 0; for (auto it : next_hop_set) { + nh_seq_id_in_nhgrp[it] = ++seq_id; if (nexthop_info_[vnet].find(it.ip_address) != nexthop_info_[vnet].end() && nexthop_info_[vnet][it.ip_address].bfd_state != SAI_BFD_SESSION_STATE_UP) { continue; @@ -696,7 +699,7 @@ bool VNetRouteOrch::addNextHopGroup(const string& vnet, const NextHopGroupKey &n vector nhg_attrs; nhg_attr.id = SAI_NEXT_HOP_GROUP_ATTR_TYPE; - nhg_attr.value.s32 = SAI_NEXT_HOP_GROUP_TYPE_ECMP; + nhg_attr.value.s32 = gSwitchOrch->checkOrderedEcmpEnable() ? SAI_NEXT_HOP_GROUP_TYPE_DYNAMIC_ORDERED_ECMP : SAI_NEXT_HOP_GROUP_TYPE_ECMP; nhg_attrs.push_back(nhg_attr); sai_object_id_t next_hop_group_id; @@ -733,6 +736,13 @@ bool VNetRouteOrch::addNextHopGroup(const string& vnet, const NextHopGroupKey &n nhgm_attr.value.oid = nhid; nhgm_attrs.push_back(nhgm_attr); + if (gSwitchOrch->checkOrderedEcmpEnable()) + { + nhgm_attr.id = SAI_NEXT_HOP_GROUP_MEMBER_ATTR_SEQUENCE_ID; + nhgm_attr.value.u32 = nh_seq_id_in_nhgrp[nhopgroup_members_set.find(nhid)->second]; + nhgm_attrs.push_back(nhgm_attr); + } + sai_object_id_t next_hop_group_member_id; status = sai_next_hop_group_api->create_next_hop_group_member(&next_hop_group_member_id, gSwitchId, @@ -865,7 +875,10 @@ bool VNetRouteOrch::doRouteTask(const string& vnet, IpPrefix& ipP NextHopGroupInfo next_hop_group_entry; next_hop_group_entry.next_hop_group_id = vrf_obj->getTunnelNextHop(nexthop); next_hop_group_entry.ref_count = 0; - next_hop_group_entry.active_members[nexthop] = SAI_NULL_OBJECT_ID; + if (nexthop_info_[vnet].find(nexthop.ip_address) == nexthop_info_[vnet].end() || nexthop_info_[vnet][nexthop.ip_address].bfd_state == SAI_BFD_SESSION_STATE_UP) + { + next_hop_group_entry.active_members[nexthop] = SAI_NULL_OBJECT_ID; + } syncd_nexthop_groups_[vnet][nexthops] = next_hop_group_entry; } else @@ -1680,7 +1693,20 @@ void VNetRouteOrch::updateVnetTunnel(const BfdUpdate& update) NextHopGroupKey nexthops = nhg_info_pair.first; NextHopGroupInfo& nhg_info = nhg_info_pair.second; - if (!(nexthops.contains(endpoint))) + std::set next_hop_set = nexthops.getNextHops(); + uint32_t seq_id = 0; + uint32_t nh_seq_id = 0; + for (auto nh: next_hop_set) + { + seq_id++; + if (nh == endpoint) + { + nh_seq_id = seq_id; + break; + } + } + + if (!nh_seq_id) { continue; } @@ -1702,6 +1728,13 @@ void VNetRouteOrch::updateVnetTunnel(const BfdUpdate& update) nhgm_attr.value.oid = vrf_obj->getTunnelNextHop(endpoint); nhgm_attrs.push_back(nhgm_attr); + if (gSwitchOrch->checkOrderedEcmpEnable()) + { + nhgm_attr.id = SAI_NEXT_HOP_GROUP_MEMBER_ATTR_SEQUENCE_ID; + nhgm_attr.value.u32 = nh_seq_id; + nhgm_attrs.push_back(nhgm_attr); + } + sai_status_t status = sai_next_hop_group_api->create_next_hop_group_member(&next_hop_group_member_id, gSwitchId, (uint32_t)nhgm_attrs.size(), diff --git a/tests/test_nhg.py b/tests/test_nhg.py index c8d75fb5e7b7..390a8e0f517c 100644 --- a/tests/test_nhg.py +++ b/tests/test_nhg.py @@ -154,11 +154,13 @@ def init_test(self, dvs, num_intfs): self.app_db = self.dvs.get_app_db() self.asic_db = self.dvs.get_asic_db() self.config_db = self.dvs.get_config_db() + self.state_db = self.dvs.get_state_db() self.nhg_ps = swsscommon.ProducerStateTable(self.app_db.db_connection, swsscommon.APP_NEXTHOP_GROUP_TABLE_NAME) self.rt_ps = swsscommon.ProducerStateTable(self.app_db.db_connection, swsscommon.APP_ROUTE_TABLE_NAME) self.lr_ps = swsscommon.ProducerStateTable(self.app_db.db_connection, swsscommon.APP_LABEL_ROUTE_TABLE_NAME) self.cbf_nhg_ps = swsscommon.ProducerStateTable(self.app_db.db_connection, swsscommon.APP_CLASS_BASED_NEXT_HOP_GROUP_TABLE_NAME) self.fc_to_nhg_ps = swsscommon.ProducerStateTable(self.app_db.db_connection, swsscommon.APP_FC_TO_NHG_INDEX_MAP_TABLE_NAME) + self.switch_ps = swsscommon.ProducerStateTable(self.app_db.db_connection, swsscommon.APP_SWITCH_TABLE_NAME) # Set switch FC capability to 63 self.dvs.setReadOnlyAttr('SAI_OBJECT_TYPE_SWITCH', 'SAI_SWITCH_ATTR_MAX_NUMBER_OF_FORWARDING_CLASSES', '63') @@ -182,6 +184,16 @@ def route_exists(self, rt_prefix): def nhg_map_exists(self, nhg_map_index): return self.get_nhg_map_id(nhg_map_index) is not None + def enable_ordered_ecmp(self): + switch_fvs = swsscommon.FieldValuePairs([('ordered_ecmp', 'true')]) + self.switch_ps.set('switch', switch_fvs) + self.state_db.wait_for_field_match("SWITCH_CAPABILITY", "switch", {"ORDERED_ECMP_CAPABLE": "true"}) + + def disble_ordered_ecmp(self): + switch_fvs = swsscommon.FieldValuePairs([('ordered_ecmp', 'false')]) + self.switch_ps.set('switch', switch_fvs) + self.state_db.wait_for_field_match("SWITCH_CAPABILITY", "switch", {"ORDERED_ECMP_CAPABLE": "false"}) + class TestNhgExhaustBase(TestNextHopGroupBase): MAX_ECMP_COUNT = 512 MAX_PORT_COUNT = 10 @@ -887,8 +899,13 @@ def test_cbf_nhg_exhaust(self, dvs, testlog): class TestNextHopGroup(TestNextHopGroupBase): - def test_route_nhg(self, dvs, dvs_route, testlog): + @pytest.mark.parametrize('ordered_ecmp', ['false', 'true']) + def test_route_nhg(self, ordered_ecmp, dvs, dvs_route, testlog): self.init_test(dvs, 3) + nhip_seqid_map = {"10.0.0.1" : "1", "10.0.0.3" : "2" , "10.0.0.5" : "3" } + + if ordered_ecmp == 'true': + self.enable_ordered_ecmp() rtprefix = "2.2.2.0/24" @@ -911,6 +928,11 @@ def test_route_nhg(self, dvs, dvs_route, testlog): assert bool(fvs) + if ordered_ecmp == 'true': + assert fvs["SAI_NEXT_HOP_GROUP_ATTR_TYPE"] == "SAI_NEXT_HOP_GROUP_TYPE_DYNAMIC_ORDERED_ECMP" + else: + assert fvs["SAI_NEXT_HOP_GROUP_ATTR_TYPE"] == "SAI_NEXT_HOP_GROUP_TYPE_DYNAMIC_UNORDERED_ECMP" + keys = self.asic_db.get_keys(self.ASIC_NHGM_STR) assert len(keys) == 3 @@ -923,6 +945,13 @@ def test_route_nhg(self, dvs, dvs_route, testlog): # verify weight attributes not in asic db assert fvs.get("SAI_NEXT_HOP_GROUP_MEMBER_ATTR_WEIGHT") is None + if ordered_ecmp == "true": + nhid = fvs["SAI_NEXT_HOP_GROUP_MEMBER_ATTR_NEXT_HOP_ID"] + nh_fvs = self.asic_db.get_entry("ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP", nhid) + assert nhip_seqid_map[nh_fvs["SAI_NEXT_HOP_ATTR_IP"]] == fvs["SAI_NEXT_HOP_GROUP_MEMBER_ATTR_SEQUENCE_ID"] + else: + assert fvs.get("SAI_NEXT_HOP_GROUP_MEMBER_ATTR_SEQUENCE_ID") is None + # Remove route 2.2.2.0/24 self.rt_ps._del(rtprefix) @@ -930,8 +959,9 @@ def test_route_nhg(self, dvs, dvs_route, testlog): dvs_route.check_asicdb_deleted_route_entries([rtprefix]) # Negative test with nexthops with incomplete weight info - fvs = swsscommon.FieldValuePairs([("nexthop","10.0.0.1,10.0.0.3,10.0.0.5"), - ("ifname", "Ethernet0,Ethernet4,Ethernet8"), + # To validate Order ECMP change the nexthop order + fvs = swsscommon.FieldValuePairs([("nexthop","10.0.0.5,10.0.0.1,10.0.0.3"), + ("ifname", "Ethernet8,Ethernet0,Ethernet4"), ("weight", "10,30")]) self.rt_ps.set(rtprefix, fvs) @@ -939,25 +969,33 @@ def test_route_nhg(self, dvs, dvs_route, testlog): rtkeys = dvs_route.check_asicdb_route_entries([rtprefix]) # assert the route points to next hop group - fvs = self.asic_db.get_entry("ASIC_STATE:SAI_OBJECT_TYPE_ROUTE_ENTRY", rtkeys[0]) + fvs = self.asic_db.get_entry(self.ASIC_RT_STR, rtkeys[0]) nhgid = fvs["SAI_ROUTE_ENTRY_ATTR_NEXT_HOP_ID"] - fvs = self.asic_db.get_entry("ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP_GROUP", nhgid) + fvs = self.asic_db.get_entry(self.ASIC_NHG_STR, nhgid) assert bool(fvs) - keys = self.asic_db.get_keys("ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP_GROUP_MEMBER") + keys = self.asic_db.get_keys(self.ASIC_NHGM_STR) assert len(keys) == 3 for k in keys: - fvs = self.asic_db.get_entry("ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP_GROUP_MEMBER", k) + fvs = self.asic_db.get_entry(self.ASIC_NHGM_STR, k) assert fvs["SAI_NEXT_HOP_GROUP_MEMBER_ATTR_NEXT_HOP_GROUP_ID"] == nhgid # verify weight attributes not in asic db assert fvs.get("SAI_NEXT_HOP_GROUP_MEMBER_ATTR_WEIGHT") is None + + if ordered_ecmp == "true": + nhid = fvs["SAI_NEXT_HOP_GROUP_MEMBER_ATTR_NEXT_HOP_ID"] + nh_fvs = self.asic_db.get_entry("ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP", nhid) + assert nhip_seqid_map[nh_fvs["SAI_NEXT_HOP_ATTR_IP"]] == fvs["SAI_NEXT_HOP_GROUP_MEMBER_ATTR_SEQUENCE_ID"] + else: + assert fvs.get("SAI_NEXT_HOP_GROUP_MEMBER_ATTR_SEQUENCE_ID") is None + # Remove route 2.2.2.0/24 self.rt_ps._del(rtprefix) @@ -974,20 +1012,20 @@ def test_route_nhg(self, dvs, dvs_route, testlog): rtkeys = dvs_route.check_asicdb_route_entries([rtprefix]) # assert the route points to next hop group - fvs = self.asic_db.get_entry("ASIC_STATE:SAI_OBJECT_TYPE_ROUTE_ENTRY", rtkeys[0]) + fvs = self.asic_db.get_entry(self.ASIC_RT_STR, rtkeys[0]) nhgid = fvs["SAI_ROUTE_ENTRY_ATTR_NEXT_HOP_ID"] - fvs = self.asic_db.get_entry("ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP_GROUP", nhgid) + fvs = self.asic_db.get_entry(self.ASIC_NHG_STR, nhgid) assert bool(fvs) - keys = self.asic_db.get_keys("ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP_GROUP_MEMBER") + keys = self.asic_db.get_keys(self.ASIC_NHGM_STR) assert len(keys) == 3 for k in keys: - fvs = self.asic_db.get_entry("ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP_GROUP_MEMBER", k) + fvs = self.asic_db.get_entry(self.ASIC_NHGM_STR, k) assert fvs["SAI_NEXT_HOP_GROUP_MEMBER_ATTR_NEXT_HOP_GROUP_ID"] == nhgid @@ -995,6 +1033,13 @@ def test_route_nhg(self, dvs, dvs_route, testlog): nhid = fvs["SAI_NEXT_HOP_GROUP_MEMBER_ATTR_NEXT_HOP_ID"] weight = fvs["SAI_NEXT_HOP_GROUP_MEMBER_ATTR_WEIGHT"] + if ordered_ecmp == "true": + nhid = fvs["SAI_NEXT_HOP_GROUP_MEMBER_ATTR_NEXT_HOP_ID"] + nh_fvs = self.asic_db.get_entry("ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP", nhid) + assert nhip_seqid_map[nh_fvs["SAI_NEXT_HOP_ATTR_IP"]] == fvs["SAI_NEXT_HOP_GROUP_MEMBER_ATTR_SEQUENCE_ID"] + else: + assert fvs.get("SAI_NEXT_HOP_GROUP_MEMBER_ATTR_SEQUENCE_ID") is None + fvs = self.asic_db.get_entry("ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP", nhid) nhip = fvs["SAI_NEXT_HOP_ATTR_IP"].split('.') expected_weight = int(nhip[3]) * 10 @@ -1011,11 +1056,11 @@ def test_route_nhg(self, dvs, dvs_route, testlog): # wait for route to be programmed time.sleep(1) - keys = self.asic_db.get_keys("ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP_GROUP") + keys = self.asic_db.get_keys(self.ASIC_NHG_STR) assert len(keys) == 2 - keys = self.asic_db.get_keys("ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP_GROUP_MEMBER") + keys = self.asic_db.get_keys(self.ASIC_NHGM_STR) assert len(keys) == 6 @@ -1035,7 +1080,8 @@ def test_route_nhg(self, dvs, dvs_route, testlog): assert len(keys) == 2 - i # bring links up one-by-one - for i in [0, 1, 2]: + # Bring link up in random order to verify sequence id is as per order + for i, val in enumerate([2,1,0]): self.flap_intf(i, 'up') keys = self.asic_db.get_keys(self.ASIC_NHGM_STR) @@ -1045,13 +1091,23 @@ def test_route_nhg(self, dvs, dvs_route, testlog): for k in keys: fvs = self.asic_db.get_entry(self.ASIC_NHGM_STR, k) assert fvs["SAI_NEXT_HOP_GROUP_MEMBER_ATTR_NEXT_HOP_GROUP_ID"] == nhgid - + if ordered_ecmp == "true": + nhid = fvs["SAI_NEXT_HOP_GROUP_MEMBER_ATTR_NEXT_HOP_ID"] + nh_fvs = self.asic_db.get_entry("ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP", nhid) + assert nhip_seqid_map[nh_fvs["SAI_NEXT_HOP_ATTR_IP"]] == fvs["SAI_NEXT_HOP_GROUP_MEMBER_ATTR_SEQUENCE_ID"] + else: + assert fvs.get("SAI_NEXT_HOP_GROUP_MEMBER_ATTR_SEQUENCE_ID") is None + # Remove route 2.2.2.0/24 self.rt_ps._del(rtprefix) # Wait for route 2.2.2.0/24 to be removed dvs_route.check_asicdb_deleted_route_entries([rtprefix]) + # Cleanup by disabling to get default behaviour + if ordered_ecmp == 'true': + self.disble_ordered_ecmp() + def test_label_route_nhg(self, dvs, testlog): self.init_test(dvs, 3) diff --git a/tests/test_vnet.py b/tests/test_vnet.py index 997d97018c9a..41217de92e32 100644 --- a/tests/test_vnet.py +++ b/tests/test_vnet.py @@ -523,16 +523,17 @@ class VnetVxlanVrfTunnel(object): ASIC_NEXT_HOP_GROUP_MEMBER = "ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP_GROUP_MEMBER" ASIC_BFD_SESSION = "ASIC_STATE:SAI_OBJECT_TYPE_BFD_SESSION" - tunnel_map_ids = set() - tunnel_map_entry_ids = set() - tunnel_ids = set() - tunnel_term_ids = set() - tunnel_map_map = {} - tunnel = {} - vnet_vr_ids = set() - vr_map = {} - nh_ids = {} - nhg_ids = {} + def __init__(self): + self.tunnel_map_ids = set() + self.tunnel_map_entry_ids = set() + self.tunnel_ids = set() + self.tunnel_term_ids = set() + self.tunnel_map_map = {} + self.tunnel = {} + self.vnet_vr_ids = set() + self.vr_map = {} + self.nh_ids = {} + self.nhg_ids = {} def fetch_exist_entries(self, dvs): self.vnet_vr_ids = get_exist_entries(dvs, self.ASIC_VRF_TABLE) @@ -818,7 +819,7 @@ def serialize_endpoint_group(self, endpoints): endpoints.sort() return ",".join(endpoints) - def check_next_hop_group_member(self, dvs, nhg, expected_endpoint, expected_attrs): + def check_next_hop_group_member(self, dvs, nhg, ordered_ecmp, expected_endpoint, expected_attrs): expected_endpoint_str = self.serialize_endpoint_group(expected_endpoint) asic_db = swsscommon.DBConnector(swsscommon.ASIC_DB, dvs.redis_sock, 0) tbl_nhgm = swsscommon.Table(asic_db, self.ASIC_NEXT_HOP_GROUP_MEMBER) @@ -837,11 +838,17 @@ def check_next_hop_group_member(self, dvs, nhg, expected_endpoint, expected_attr endpoint = nh_fvs["SAI_NEXT_HOP_ATTR_IP"] endpoints.append(endpoint) assert endpoint in expected_attrs + if ordered_ecmp == "true": + assert fvs["SAI_NEXT_HOP_GROUP_MEMBER_ATTR_SEQUENCE_ID"] == expected_attrs[endpoint]['SAI_NEXT_HOP_GROUP_MEMBER_ATTR_SEQUENCE_ID'] + del expected_attrs[endpoint]['SAI_NEXT_HOP_GROUP_MEMBER_ATTR_SEQUENCE_ID'] + else: + assert fvs.get("SAI_NEXT_HOP_GROUP_MEMBER_ATTR_SEQUENCE_ID") is None + check_object(asic_db, self.ASIC_NEXT_HOP, nh_key, expected_attrs[endpoint]) assert self.serialize_endpoint_group(endpoints) == expected_endpoint_str - def check_vnet_ecmp_routes(self, dvs, name, endpoints, tunnel, mac=[], vni=[], route_ids=[], nhg=""): + def check_vnet_ecmp_routes(self, dvs, name, endpoints, tunnel, mac=[], vni=[], route_ids=[], nhg="", ordered_ecmp="false", nh_seq_id=None): asic_db = swsscommon.DBConnector(swsscommon.ASIC_DB, dvs.redis_sock, 0) endpoint_str = name + "|" + self.serialize_endpoint_group(endpoints) @@ -859,6 +866,8 @@ def check_vnet_ecmp_routes(self, dvs, name, endpoints, tunnel, mac=[], vni=[], r expected_attr.update({'SAI_NEXT_HOP_ATTR_TUNNEL_VNI': vni[idx]}) if mac and mac[idx]: expected_attr.update({'SAI_NEXT_HOP_ATTR_TUNNEL_MAC': mac[idx]}) + if ordered_ecmp == "true" and nh_seq_id: + expected_attr.update({'SAI_NEXT_HOP_GROUP_MEMBER_ATTR_SEQUENCE_ID': nh_seq_id[idx]}) expected_attrs[endpoint] = expected_attr if nhg: @@ -873,12 +882,12 @@ def check_vnet_ecmp_routes(self, dvs, name, endpoints, tunnel, mac=[], vni=[], r # Check routes in ingress VRF expected_nhg_attr = { - "SAI_NEXT_HOP_GROUP_ATTR_TYPE": "SAI_NEXT_HOP_GROUP_TYPE_DYNAMIC_UNORDERED_ECMP", + "SAI_NEXT_HOP_GROUP_ATTR_TYPE": "SAI_NEXT_HOP_GROUP_TYPE_DYNAMIC_UNORDERED_ECMP" if ordered_ecmp == "false" else "SAI_NEXT_HOP_GROUP_TYPE_DYNAMIC_ORDERED_ECMP", } check_object(asic_db, self.ASIC_NEXT_HOP_GROUP, new_nhg, expected_nhg_attr) # Check nexthop group member - self.check_next_hop_group_member(dvs, new_nhg, endpoints, expected_attrs) + self.check_next_hop_group_member(dvs, new_nhg, ordered_ecmp, endpoints, expected_attrs) if route_ids: new_route = route_ids @@ -921,6 +930,32 @@ class TestVnetOrch(object): def get_vnet_obj(self): return VnetVxlanVrfTunnel() + @pytest.fixture(params=["true", "false"]) + def ordered_ecmp(self, dvs, request): + + app_db = swsscommon.DBConnector(swsscommon.APPL_DB, dvs.redis_sock, 0) + if request.param == "true": + create_entry_pst( + app_db, + "SWITCH_TABLE", ':', "switch", + [ + ('ordered_ecmp', 'true') + ], + ) + dvs.get_state_db().wait_for_field_match("SWITCH_CAPABILITY", "switch", {"ORDERED_ECMP_CAPABLE": "true"}) + + yield request.param + + if request.param == "true": + create_entry_pst( + app_db, + "SWITCH_TABLE", ':', "switch", + [ + ('ordered_ecmp', 'false') + ], + ) + dvs.get_state_db().wait_for_field_match("SWITCH_CAPABILITY", "switch", {"ORDERED_ECMP_CAPABLE": "false"}) + ''' Test 1 - Create Vlan Interface, Tunnel and Vnet ''' @@ -1399,34 +1434,34 @@ def test_vnet_vxlan_multi_map(self, dvs, testlog): ''' Test 7 - Test for vnet tunnel routes with ECMP nexthop group ''' - def test_vnet_orch_7(self, dvs, testlog): + def test_vnet_orch_7(self, dvs, ordered_ecmp, testlog): vnet_obj = self.get_vnet_obj() - tunnel_name = 'tunnel_7' + tunnel_name = 'tunnel_7' + ordered_ecmp + vnet_name = 'Vnet7' + ordered_ecmp vnet_obj.fetch_exist_entries(dvs) create_vxlan_tunnel(dvs, tunnel_name, '7.7.7.7') - create_vnet_entry(dvs, 'Vnet7', tunnel_name, '10007', "") + create_vnet_entry(dvs, vnet_name, tunnel_name, '10007', "") - vnet_obj.check_vnet_entry(dvs, 'Vnet7') - vnet_obj.check_vxlan_tunnel_entry(dvs, tunnel_name, 'Vnet7', '10007') + vnet_obj.check_vnet_entry(dvs, vnet_name) + vnet_obj.check_vxlan_tunnel_entry(dvs, tunnel_name, vnet_name, '10007') vnet_obj.check_vxlan_tunnel(dvs, tunnel_name, '7.7.7.7') # Create an ECMP tunnel route vnet_obj.fetch_exist_entries(dvs) - create_vnet_routes(dvs, "100.100.1.1/32", 'Vnet7', '7.0.0.1,7.0.0.2,7.0.0.3') - route1, nhg1_1 = vnet_obj.check_vnet_ecmp_routes(dvs, 'Vnet7', ['7.0.0.1', '7.0.0.2', '7.0.0.3'], tunnel_name) - check_state_db_routes(dvs, 'Vnet7', "100.100.1.1/32", ['7.0.0.1', '7.0.0.2', '7.0.0.3']) - # The default Vnet setting does not advertise prefix + create_vnet_routes(dvs, "100.100.1.1/32", vnet_name, '7.0.0.3,7.0.0.2,7.0.0.1') + route1, nhg1_1 = vnet_obj.check_vnet_ecmp_routes(dvs, vnet_name, ['7.0.0.1', '7.0.0.2', '7.0.0.3'], tunnel_name, ordered_ecmp=ordered_ecmp, nh_seq_id=['1', '2', '3']) + check_state_db_routes(dvs, vnet_name, "100.100.1.1/32", ['7.0.0.1', '7.0.0.2', '7.0.0.3']) check_remove_routes_advertisement(dvs, "100.100.1.1/32") # Set the tunnel route to another nexthop group - set_vnet_routes(dvs, "100.100.1.1/32", 'Vnet7', '7.0.0.1,7.0.0.2,7.0.0.3,7.0.0.4') - route1, nhg1_2 = vnet_obj.check_vnet_ecmp_routes(dvs, 'Vnet7', ['7.0.0.1', '7.0.0.2', '7.0.0.3', '7.0.0.4'], tunnel_name, route_ids=route1) - check_state_db_routes(dvs, 'Vnet7', "100.100.1.1/32", ['7.0.0.1', '7.0.0.2', '7.0.0.3', '7.0.0.4']) - # The default Vnet setting does not advertise prefix + set_vnet_routes(dvs, "100.100.1.1/32", vnet_name, '7.0.0.1,7.0.0.2,7.0.0.4,7.0.0.3') + route1, nhg1_2 = vnet_obj.check_vnet_ecmp_routes(dvs, vnet_name, ['7.0.0.1', '7.0.0.2', '7.0.0.3', '7.0.0.4'], tunnel_name, route_ids=route1, + ordered_ecmp=ordered_ecmp, nh_seq_id=['1', '2', '3', '4']) + check_state_db_routes(dvs, vnet_name, "100.100.1.1/32", ['7.0.0.1', '7.0.0.2', '7.0.0.3', '7.0.0.4']) check_remove_routes_advertisement(dvs, "100.100.1.1/32") # Check the previous nexthop group is removed @@ -1434,18 +1469,18 @@ def test_vnet_orch_7(self, dvs, testlog): assert nhg1_1 not in vnet_obj.nhgs # Create another tunnel route to the same set of endpoints - create_vnet_routes(dvs, "100.100.2.1/32", 'Vnet7', '7.0.0.1,7.0.0.2,7.0.0.3,7.0.0.4') - route2, nhg2_1 = vnet_obj.check_vnet_ecmp_routes(dvs, 'Vnet7', ['7.0.0.1', '7.0.0.2', '7.0.0.3', '7.0.0.4'], tunnel_name) - check_state_db_routes(dvs, 'Vnet7', "100.100.2.1/32", ['7.0.0.1', '7.0.0.2', '7.0.0.3', '7.0.0.4']) - # The default Vnet setting does not advertise prefix + create_vnet_routes(dvs, "100.100.2.1/32", vnet_name, '7.0.0.1,7.0.0.2,7.0.0.3,7.0.0.4') + route2, nhg2_1 = vnet_obj.check_vnet_ecmp_routes(dvs, vnet_name, ['7.0.0.1', '7.0.0.2', '7.0.0.3', '7.0.0.4'], tunnel_name, + ordered_ecmp=ordered_ecmp, nh_seq_id=['1', '2', '3', '4']) + check_state_db_routes(dvs, vnet_name, "100.100.2.1/32", ['7.0.0.1', '7.0.0.2', '7.0.0.3', '7.0.0.4']) check_remove_routes_advertisement(dvs, "100.100.2.1/32") assert nhg2_1 == nhg1_2 # Remove one of the tunnel routes - delete_vnet_routes(dvs, "100.100.1.1/32", 'Vnet7') - vnet_obj.check_del_vnet_routes(dvs, 'Vnet7', ["100.100.1.1/32"]) - check_remove_state_db_routes(dvs, 'Vnet7', "100.100.1.1/32") + delete_vnet_routes(dvs, "100.100.1.1/32", vnet_name) + vnet_obj.check_del_vnet_routes(dvs, vnet_name, ["100.100.1.1/32"]) + check_remove_state_db_routes(dvs, vnet_name, "100.100.1.1/32") check_remove_routes_advertisement(dvs, "100.100.1.1/32") # Check the nexthop group still exists @@ -1453,49 +1488,51 @@ def test_vnet_orch_7(self, dvs, testlog): assert nhg1_2 in vnet_obj.nhgs # Remove the other tunnel route - delete_vnet_routes(dvs, "100.100.2.1/32", 'Vnet7') - vnet_obj.check_del_vnet_routes(dvs, 'Vnet7', ["100.100.2.1/32"]) - check_remove_state_db_routes(dvs, 'Vnet7', "100.100.2.1/32") + delete_vnet_routes(dvs, "100.100.2.1/32", vnet_name) + vnet_obj.check_del_vnet_routes(dvs, vnet_name, ["100.100.2.1/32"]) + check_remove_state_db_routes(dvs, vnet_name, "100.100.2.1/32") check_remove_routes_advertisement(dvs, "100.100.2.1/32") # Check the nexthop group is removed vnet_obj.fetch_exist_entries(dvs) assert nhg2_1 not in vnet_obj.nhgs - delete_vnet_entry(dvs, 'Vnet7') - vnet_obj.check_del_vnet_entry(dvs, 'Vnet7') + delete_vnet_entry(dvs, vnet_name) + vnet_obj.check_del_vnet_entry(dvs, vnet_name) ''' Test 8 - Test for ipv6 vnet tunnel routes with ECMP nexthop group ''' - def test_vnet_orch_8(self, dvs, testlog): + def test_vnet_orch_8(self, dvs, ordered_ecmp, testlog): + vnet_obj = self.get_vnet_obj() - tunnel_name = 'tunnel_8' + tunnel_name = 'tunnel_8' + ordered_ecmp + vnet_name = 'Vnet8' + ordered_ecmp + vnet_obj.fetch_exist_entries(dvs) create_vxlan_tunnel(dvs, tunnel_name, 'fd:8::32') - create_vnet_entry(dvs, 'Vnet8', tunnel_name, '10008', "") + create_vnet_entry(dvs, vnet_name, tunnel_name, '10008', "") - vnet_obj.check_vnet_entry(dvs, 'Vnet8') - vnet_obj.check_vxlan_tunnel_entry(dvs, tunnel_name, 'Vnet8', '10008') + vnet_obj.check_vnet_entry(dvs, vnet_name) + vnet_obj.check_vxlan_tunnel_entry(dvs, tunnel_name, vnet_name, '10008') vnet_obj.check_vxlan_tunnel(dvs, tunnel_name, 'fd:8::32') # Create an ECMP tunnel route vnet_obj.fetch_exist_entries(dvs) - create_vnet_routes(dvs, "fd:8:10::32/128", 'Vnet8', 'fd:8:1::1,fd:8:1::2,fd:8:1::3') - route1, nhg1_1 = vnet_obj.check_vnet_ecmp_routes(dvs, 'Vnet8', ['fd:8:1::1', 'fd:8:1::2', 'fd:8:1::3'], tunnel_name) - check_state_db_routes(dvs, 'Vnet8', "fd:8:10::32/128", ['fd:8:1::1', 'fd:8:1::2', 'fd:8:1::3']) - # The default Vnet setting does not advertise prefix + create_vnet_routes(dvs, "fd:8:10::32/128", vnet_name, 'fd:8:1::1,fd:8:1::3,fd:8:1::2') + route1, nhg1_1 = vnet_obj.check_vnet_ecmp_routes(dvs, vnet_name, ['fd:8:1::1', 'fd:8:1::2', 'fd:8:1::3'], tunnel_name, ordered_ecmp=ordered_ecmp, nh_seq_id=['1', '2', '3']) + check_state_db_routes(dvs, vnet_name, "fd:8:10::32/128", ['fd:8:1::1', 'fd:8:1::2', 'fd:8:1::3']) check_remove_routes_advertisement(dvs, "fd:8:10::32/128") # Set the tunnel route to another nexthop group - set_vnet_routes(dvs, "fd:8:10::32/128", 'Vnet8', 'fd:8:1::1,fd:8:1::2,fd:8:1::3,fd:8:1::4') - route1, nhg1_2 = vnet_obj.check_vnet_ecmp_routes(dvs, 'Vnet8', ['fd:8:1::1', 'fd:8:1::2', 'fd:8:1::3', 'fd:8:1::4'], tunnel_name, route_ids=route1) - check_state_db_routes(dvs, 'Vnet8', "fd:8:10::32/128", ['fd:8:1::1', 'fd:8:1::2', 'fd:8:1::3', 'fd:8:1::4']) - # The default Vnet setting does not advertise prefix + set_vnet_routes(dvs, "fd:8:10::32/128", vnet_name, 'fd:8:1::2,fd:8:1::3,fd:8:1::1,fd:8:1::4') + route1, nhg1_2 = vnet_obj.check_vnet_ecmp_routes(dvs, vnet_name, ['fd:8:1::1', 'fd:8:1::2', 'fd:8:1::3', 'fd:8:1::4'], tunnel_name, route_ids=route1, + ordered_ecmp=ordered_ecmp, nh_seq_id=['1', '2', '3', '4']) + check_state_db_routes(dvs, vnet_name, "fd:8:10::32/128", ['fd:8:1::1', 'fd:8:1::2', 'fd:8:1::3', 'fd:8:1::4']) check_remove_routes_advertisement(dvs, "fd:8:10::32/128") # Check the previous nexthop group is removed @@ -1503,27 +1540,27 @@ def test_vnet_orch_8(self, dvs, testlog): assert nhg1_1 not in vnet_obj.nhgs # Create another tunnel route to the same set of endpoints - create_vnet_routes(dvs, "fd:8:20::32/128", 'Vnet8', 'fd:8:1::1,fd:8:1::2,fd:8:1::3,fd:8:1::4') - route2, nhg2_1 = vnet_obj.check_vnet_ecmp_routes(dvs, 'Vnet8', ['fd:8:1::1', 'fd:8:1::2', 'fd:8:1::3', 'fd:8:1::4'], tunnel_name) - check_state_db_routes(dvs, 'Vnet8', "fd:8:20::32/128", ['fd:8:1::1', 'fd:8:1::2', 'fd:8:1::3', 'fd:8:1::4']) - # The default Vnet setting does not advertise prefix + create_vnet_routes(dvs, "fd:8:20::32/128", vnet_name, 'fd:8:1::1,fd:8:1::2,fd:8:1::3,fd:8:1::4') + route2, nhg2_1 = vnet_obj.check_vnet_ecmp_routes(dvs, vnet_name, ['fd:8:1::1', 'fd:8:1::2', 'fd:8:1::3', 'fd:8:1::4'], tunnel_name, + ordered_ecmp=ordered_ecmp, nh_seq_id=['1', '2', '3', '4']) + check_state_db_routes(dvs, vnet_name, "fd:8:20::32/128", ['fd:8:1::1', 'fd:8:1::2', 'fd:8:1::3', 'fd:8:1::4']) check_remove_routes_advertisement(dvs, "fd:8:20::32/128") assert nhg2_1 == nhg1_2 # Create another tunnel route with ipv4 prefix to the same set of endpoints - create_vnet_routes(dvs, "8.0.0.0/24", 'Vnet8', 'fd:8:1::1,fd:8:1::2,fd:8:1::3,fd:8:1::4') - route3, nhg3_1 = vnet_obj.check_vnet_ecmp_routes(dvs, 'Vnet8', ['fd:8:1::1', 'fd:8:1::2', 'fd:8:1::3', 'fd:8:1::4'], tunnel_name) - check_state_db_routes(dvs, 'Vnet8', "8.0.0.0/24", ['fd:8:1::1', 'fd:8:1::2', 'fd:8:1::3', 'fd:8:1::4']) - # The default Vnet setting does not advertise prefix + create_vnet_routes(dvs, "8.0.0.0/24", vnet_name, 'fd:8:1::1,fd:8:1::2,fd:8:1::3,fd:8:1::4') + route3, nhg3_1 = vnet_obj.check_vnet_ecmp_routes(dvs, vnet_name, ['fd:8:1::1', 'fd:8:1::2', 'fd:8:1::3', 'fd:8:1::4'], tunnel_name, + ordered_ecmp=ordered_ecmp, nh_seq_id=['1', '2', '3', '4']) + check_state_db_routes(dvs, vnet_name, "8.0.0.0/24", ['fd:8:1::1', 'fd:8:1::2', 'fd:8:1::3', 'fd:8:1::4']) check_remove_routes_advertisement(dvs, "8.0.0.0/24") assert nhg3_1 == nhg1_2 # Remove one of the tunnel routes - delete_vnet_routes(dvs, "fd:8:10::32/128", 'Vnet8') - vnet_obj.check_del_vnet_routes(dvs, 'Vnet8', ["fd:8:10::32/128"]) - check_remove_state_db_routes(dvs, 'Vnet8', "fd:8:10::32/128") + delete_vnet_routes(dvs, "fd:8:10::32/128", vnet_name) + vnet_obj.check_del_vnet_routes(dvs, vnet_name, ["fd:8:10::32/128"]) + check_remove_state_db_routes(dvs, vnet_name, "fd:8:10::32/128") check_remove_routes_advertisement(dvs, "fd:8:10::32/128") # Check the nexthop group still exists @@ -1531,101 +1568,96 @@ def test_vnet_orch_8(self, dvs, testlog): assert nhg1_2 in vnet_obj.nhgs # Remove tunnel route 2 - delete_vnet_routes(dvs, "fd:8:20::32/128", 'Vnet8') - vnet_obj.check_del_vnet_routes(dvs, 'Vnet8', ["fd:8:20::32/128"]) - check_remove_state_db_routes(dvs, 'Vnet8', "fd:8:20::32/128") + delete_vnet_routes(dvs, "fd:8:20::32/128", vnet_name) + vnet_obj.check_del_vnet_routes(dvs, vnet_name, ["fd:8:20::32/128"]) + check_remove_state_db_routes(dvs, vnet_name, "fd:8:20::32/128") check_remove_routes_advertisement(dvs, "fd:8:20::32/128") # Remove tunnel route 3 - delete_vnet_routes(dvs, "8.0.0.0/24", 'Vnet8') - vnet_obj.check_del_vnet_routes(dvs, 'Vnet8', ["8.0.0.0/24"]) - check_remove_state_db_routes(dvs, 'Vnet8', "8.0.0.0/24") + delete_vnet_routes(dvs, "8.0.0.0/24", vnet_name) + vnet_obj.check_del_vnet_routes(dvs, vnet_name, ["8.0.0.0/24"]) + check_remove_state_db_routes(dvs, vnet_name, "8.0.0.0/24") check_remove_routes_advertisement(dvs, "8.0.0.0/24") # Check the nexthop group is removed vnet_obj.fetch_exist_entries(dvs) assert nhg2_1 not in vnet_obj.nhgs - delete_vnet_entry(dvs, 'Vnet8') - vnet_obj.check_del_vnet_entry(dvs, 'Vnet8') + delete_vnet_entry(dvs, vnet_name) + vnet_obj.check_del_vnet_entry(dvs, vnet_name) - ''' + ''' Test 9 - Test for vnet tunnel routes with ECMP nexthop group with endpoint health monitor ''' - def test_vnet_orch_9(self, dvs, testlog): + def test_vnet_orch_9(self, dvs, ordered_ecmp, testlog): vnet_obj = self.get_vnet_obj() - tunnel_name = 'tunnel_9' + tunnel_name = 'tunnel_9' + ordered_ecmp + vnet_name = 'Vnet9' + ordered_ecmp vnet_obj.fetch_exist_entries(dvs) create_vxlan_tunnel(dvs, tunnel_name, '9.9.9.9') - create_vnet_entry(dvs, 'Vnet9', tunnel_name, '10009', "") + create_vnet_entry(dvs, vnet_name, tunnel_name, '10009', "") - vnet_obj.check_vnet_entry(dvs, 'Vnet9') - vnet_obj.check_vxlan_tunnel_entry(dvs, tunnel_name, 'Vnet9', '10009') + vnet_obj.check_vnet_entry(dvs, vnet_name) + vnet_obj.check_vxlan_tunnel_entry(dvs, tunnel_name, vnet_name, '10009') vnet_obj.check_vxlan_tunnel(dvs, tunnel_name, '9.9.9.9') vnet_obj.fetch_exist_entries(dvs) - create_vnet_routes(dvs, "100.100.1.1/32", 'Vnet9', '9.0.0.1,9.0.0.2,9.0.0.3', ep_monitor='9.1.0.1,9.1.0.2,9.1.0.3') + create_vnet_routes(dvs, "100.100.1.1/32", vnet_name, '9.0.0.1,9.0.0.2,9.0.0.3', ep_monitor='9.1.0.1,9.1.0.2,9.1.0.3') # default bfd status is down, route should not be programmed in this status - vnet_obj.check_del_vnet_routes(dvs, 'Vnet9', ["100.100.1.1/32"]) - check_state_db_routes(dvs, 'Vnet9', "100.100.1.1/32", []) + vnet_obj.check_del_vnet_routes(dvs, vnet_name, ["100.100.1.1/32"]) + check_state_db_routes(dvs, vnet_name, "100.100.1.1/32", []) check_remove_routes_advertisement(dvs, "100.100.1.1/32") # Route should be properly configured when all bfd session states go up - update_bfd_session_state(dvs, '9.1.0.1', 'Up') update_bfd_session_state(dvs, '9.1.0.2', 'Up') update_bfd_session_state(dvs, '9.1.0.3', 'Up') + update_bfd_session_state(dvs, '9.1.0.1', 'Up') time.sleep(2) - route1, nhg1_1 = vnet_obj.check_vnet_ecmp_routes(dvs, 'Vnet9', ['9.0.0.1', '9.0.0.2', '9.0.0.3'], tunnel_name) - check_state_db_routes(dvs, 'Vnet9', "100.100.1.1/32", ['9.0.0.1', '9.0.0.2', '9.0.0.3']) - # The default Vnet setting does not advertise prefix + route1, nhg1_1 = vnet_obj.check_vnet_ecmp_routes(dvs, vnet_name, ['9.0.0.1', '9.0.0.2', '9.0.0.3'], tunnel_name, ordered_ecmp=ordered_ecmp, nh_seq_id=['1', '2', '3']) + check_state_db_routes(dvs, vnet_name, "100.100.1.1/32", ['9.0.0.1', '9.0.0.2', '9.0.0.3']) check_remove_routes_advertisement(dvs, "100.100.1.1/32") # Remove endpoint from group if it goes down update_bfd_session_state(dvs, '9.1.0.2', 'Down') time.sleep(2) - route1, nhg1_1 = vnet_obj.check_vnet_ecmp_routes(dvs, 'Vnet9', ['9.0.0.1', '9.0.0.3'], tunnel_name, route_ids=route1, nhg=nhg1_1) - check_state_db_routes(dvs, 'Vnet9', "100.100.1.1/32", ['9.0.0.1', '9.0.0.3']) - # The default Vnet setting does not advertise prefix + route1, nhg1_1 = vnet_obj.check_vnet_ecmp_routes(dvs, vnet_name, ['9.0.0.1', '9.0.0.3'], tunnel_name, route_ids=route1, nhg=nhg1_1, ordered_ecmp=ordered_ecmp, nh_seq_id=['1', '3']) + check_state_db_routes(dvs, vnet_name, "100.100.1.1/32", ['9.0.0.1', '9.0.0.3']) check_remove_routes_advertisement(dvs, "100.100.1.1/32") # Create another tunnel route with endpoint group overlapped with route1 vnet_obj.fetch_exist_entries(dvs) - create_vnet_routes(dvs, "100.100.2.1/32", 'Vnet9', '9.0.0.1,9.0.0.2,9.0.0.5', ep_monitor='9.1.0.1,9.1.0.2,9.1.0.5') - route2, nhg2_1 = vnet_obj.check_vnet_ecmp_routes(dvs, 'Vnet9', ['9.0.0.1'], tunnel_name) - check_state_db_routes(dvs, 'Vnet9', "100.100.2.1/32", ['9.0.0.1']) - # The default Vnet setting does not advertise prefix + create_vnet_routes(dvs, "100.100.2.1/32", vnet_name, '9.0.0.1,9.0.0.2,9.0.0.5', ep_monitor='9.1.0.1,9.1.0.2,9.1.0.5') + route2, nhg2_1 = vnet_obj.check_vnet_ecmp_routes(dvs, vnet_name, ['9.0.0.1'], tunnel_name, ordered_ecmp=ordered_ecmp, nh_seq_id=['1']) + check_state_db_routes(dvs, vnet_name, "100.100.2.1/32", ['9.0.0.1']) check_remove_routes_advertisement(dvs, "100.100.1.1/32") # Update BFD session state and verify route change update_bfd_session_state(dvs, '9.1.0.5', 'Up') time.sleep(2) - route2, nhg2_1 = vnet_obj.check_vnet_ecmp_routes(dvs, 'Vnet9', ['9.0.0.1', '9.0.0.5'], tunnel_name, route_ids=route2, nhg=nhg2_1) - check_state_db_routes(dvs, 'Vnet9', "100.100.2.1/32", ['9.0.0.1', '9.0.0.5']) - # The default Vnet setting does not advertise prefix + route2, nhg2_1 = vnet_obj.check_vnet_ecmp_routes(dvs, vnet_name, ['9.0.0.1', '9.0.0.5'], tunnel_name, route_ids=route2, nhg=nhg2_1, ordered_ecmp=ordered_ecmp, nh_seq_id=['1', '3']) + check_state_db_routes(dvs, vnet_name, "100.100.2.1/32", ['9.0.0.1', '9.0.0.5']) check_remove_routes_advertisement(dvs, "100.100.2.1/32") # Update BFD state and check route nexthop update_bfd_session_state(dvs, '9.1.0.3', 'Down') time.sleep(2) - route1, nhg1_1 = vnet_obj.check_vnet_ecmp_routes(dvs, 'Vnet9', ['9.0.0.1'], tunnel_name, route_ids=route1, nhg=nhg1_1) - check_state_db_routes(dvs, 'Vnet9', "100.100.1.1/32", ['9.0.0.1']) - # The default Vnet setting does not advertise prefix + route1, nhg1_1 = vnet_obj.check_vnet_ecmp_routes(dvs, vnet_name, ['9.0.0.1'], tunnel_name, route_ids=route1, nhg=nhg1_1, ordered_ecmp=ordered_ecmp, nh_seq_id=['1']) + check_state_db_routes(dvs, vnet_name, "100.100.1.1/32", ['9.0.0.1']) check_remove_routes_advertisement(dvs, "100.100.1.1/32") # Set the route1 to a new group - set_vnet_routes(dvs, "100.100.1.1/32", 'Vnet9', '9.0.0.1,9.0.0.2,9.0.0.3,9.0.0.4', ep_monitor='9.1.0.1,9.1.0.2,9.1.0.3,9.1.0.4') + set_vnet_routes(dvs, "100.100.1.1/32", vnet_name, '9.0.0.1,9.0.0.2,9.0.0.3,9.0.0.4', ep_monitor='9.1.0.1,9.1.0.2,9.1.0.3,9.1.0.4') update_bfd_session_state(dvs, '9.1.0.4', 'Up') time.sleep(2) - route1, nhg1_2 = vnet_obj.check_vnet_ecmp_routes(dvs, 'Vnet9', ['9.0.0.1', '9.0.0.4'], tunnel_name, route_ids=route1) - check_state_db_routes(dvs, 'Vnet9', "100.100.1.1/32", ['9.0.0.1', '9.0.0.4']) - # The default Vnet setting does not advertise prefix + route1, nhg1_2 = vnet_obj.check_vnet_ecmp_routes(dvs, vnet_name, ['9.0.0.1', '9.0.0.4'], tunnel_name, route_ids=route1, ordered_ecmp=ordered_ecmp, nh_seq_id=['1', '4']) + check_state_db_routes(dvs, vnet_name, "100.100.1.1/32", ['9.0.0.1', '9.0.0.4']) check_remove_routes_advertisement(dvs, "100.100.1.1/32") # Check the previous nexthop group is removed @@ -1635,9 +1667,8 @@ def test_vnet_orch_9(self, dvs, testlog): # Set BFD session state for a down endpoint to up update_bfd_session_state(dvs, '9.1.0.2', 'Up') time.sleep(2) - route1, nhg1_2 = vnet_obj.check_vnet_ecmp_routes(dvs, 'Vnet9', ['9.0.0.1', '9.0.0.2', '9.0.0.4'], tunnel_name, route_ids=route1, nhg=nhg1_2) - check_state_db_routes(dvs, 'Vnet9', "100.100.1.1/32", ['9.0.0.1', '9.0.0.2', '9.0.0.4']) - # The default Vnet setting does not advertise prefix + route1, nhg1_2 = vnet_obj.check_vnet_ecmp_routes(dvs, vnet_name, ['9.0.0.1', '9.0.0.2', '9.0.0.4'], tunnel_name, route_ids=route1, nhg=nhg1_2, ordered_ecmp=ordered_ecmp, nh_seq_id=['1', '2', '4']) + check_state_db_routes(dvs, vnet_name, "100.100.1.1/32", ['9.0.0.1', '9.0.0.2', '9.0.0.4']) check_remove_routes_advertisement(dvs, "100.100.1.1/32") # Set all endpoint to down state @@ -1648,18 +1679,18 @@ def test_vnet_orch_9(self, dvs, testlog): time.sleep(2) # Confirm the tunnel route is updated in ASIC - vnet_obj.check_del_vnet_routes(dvs, 'Vnet9', ["100.100.1.1/32"]) - route2, nhg2_1 = vnet_obj.check_vnet_ecmp_routes(dvs, 'Vnet9', ['9.0.0.5'], tunnel_name, route_ids=route2, nhg=nhg2_1) - check_state_db_routes(dvs, 'Vnet9', "100.100.2.1/32", ['9.0.0.5']) - check_state_db_routes(dvs, 'Vnet9', "100.100.1.1/32", []) + vnet_obj.check_del_vnet_routes(dvs, vnet_name, ["100.100.1.1/32"]) + route2, nhg2_1 = vnet_obj.check_vnet_ecmp_routes(dvs, vnet_name, ['9.0.0.5'], tunnel_name, route_ids=route2, nhg=nhg2_1, ordered_ecmp=ordered_ecmp, nh_seq_id=['3']) + check_state_db_routes(dvs, vnet_name, "100.100.2.1/32", ['9.0.0.5']) + check_state_db_routes(dvs, vnet_name, "100.100.1.1/32", []) check_remove_routes_advertisement(dvs, "100.100.1.1/32") # The default Vnet setting does not advertise prefix check_remove_routes_advertisement(dvs, "100.100.2.1/32") # Remove tunnel route2 - delete_vnet_routes(dvs, "100.100.2.1/32", 'Vnet9') - vnet_obj.check_del_vnet_routes(dvs, 'Vnet9', ["100.100.2.1/32"]) - check_remove_state_db_routes(dvs, 'Vnet9', "100.100.2.1/32") + delete_vnet_routes(dvs, "100.100.2.1/32", vnet_name) + vnet_obj.check_del_vnet_routes(dvs, vnet_name, ["100.100.2.1/32"]) + check_remove_state_db_routes(dvs, vnet_name, "100.100.2.1/32") check_remove_routes_advertisement(dvs, "100.100.2.1/32") # Check the corresponding nexthop group is removed @@ -1671,9 +1702,9 @@ def test_vnet_orch_9(self, dvs, testlog): check_bfd_session(dvs, ['9.1.0.1', '9.1.0.2', '9.1.0.3', '9.1.0.4']) # Remove tunnel route 1 - delete_vnet_routes(dvs, "100.100.1.1/32", 'Vnet9') - vnet_obj.check_del_vnet_routes(dvs, 'Vnet9', ["100.100.1.1/32"]) - check_remove_state_db_routes(dvs, 'Vnet9', "100.100.1.1/32") + delete_vnet_routes(dvs, "100.100.1.1/32", vnet_name) + vnet_obj.check_del_vnet_routes(dvs, vnet_name, ["100.100.1.1/32"]) + check_remove_state_db_routes(dvs, vnet_name, "100.100.1.1/32") check_remove_routes_advertisement(dvs, "100.100.1.1/32") # Check the previous nexthop group is removed @@ -1683,68 +1714,65 @@ def test_vnet_orch_9(self, dvs, testlog): # Confirm the BFD sessions are removed check_del_bfd_session(dvs, ['9.1.0.1', '9.1.0.2', '9.1.0.3', '9.1.0.4', '9.1.0.5']) - delete_vnet_entry(dvs, 'Vnet9') - vnet_obj.check_del_vnet_entry(dvs, 'Vnet9') + delete_vnet_entry(dvs, vnet_name) + vnet_obj.check_del_vnet_entry(dvs, vnet_name) ''' Test 10 - Test for ipv6 vnet tunnel routes with ECMP nexthop group with endpoint health monitor ''' - def test_vnet_orch_10(self, dvs, testlog): + def test_vnet_orch_10(self, dvs, ordered_ecmp, testlog): vnet_obj = self.get_vnet_obj() - tunnel_name = 'tunnel_10' + tunnel_name = 'tunnel_10' + ordered_ecmp + vnet_name = 'Vnet10' + ordered_ecmp vnet_obj.fetch_exist_entries(dvs) create_vxlan_tunnel(dvs, tunnel_name, 'fd:10::32') - create_vnet_entry(dvs, 'Vnet10', tunnel_name, '10010', "") + create_vnet_entry(dvs, vnet_name, tunnel_name, '10010', "") - vnet_obj.check_vnet_entry(dvs, 'Vnet10') - vnet_obj.check_vxlan_tunnel_entry(dvs, tunnel_name, 'Vnet10', '10010') + vnet_obj.check_vnet_entry(dvs, vnet_name) + vnet_obj.check_vxlan_tunnel_entry(dvs, tunnel_name, vnet_name, '10010') vnet_obj.check_vxlan_tunnel(dvs, tunnel_name, 'fd:10::32') vnet_obj.fetch_exist_entries(dvs) - create_vnet_routes(dvs, "fd:10:10::1/128", 'Vnet10', 'fd:10:1::1,fd:10:1::2,fd:10:1::3', ep_monitor='fd:10:2::1,fd:10:2::2,fd:10:2::3') + create_vnet_routes(dvs, "fd:10:10::1/128", vnet_name, 'fd:10:1::1,fd:10:1::2,fd:10:1::3', ep_monitor='fd:10:2::1,fd:10:2::2,fd:10:2::3') # default bfd status is down, route should not be programmed in this status - vnet_obj.check_del_vnet_routes(dvs, 'Vnet10', ["fd:10:10::1/128"]) - check_state_db_routes(dvs, 'Vnet10', "fd:10:10::1/128", []) + vnet_obj.check_del_vnet_routes(dvs, vnet_name, ["fd:10:10::1/128"]) + check_state_db_routes(dvs, vnet_name, "fd:10:10::1/128", []) check_remove_routes_advertisement(dvs, "fd:10:10::1/128") # Route should be properly configured when all bfd session states go up - update_bfd_session_state(dvs, 'fd:10:2::1', 'Up') update_bfd_session_state(dvs, 'fd:10:2::2', 'Up') update_bfd_session_state(dvs, 'fd:10:2::3', 'Up') + update_bfd_session_state(dvs, 'fd:10:2::1', 'Up') time.sleep(2) - route1, nhg1_1 = vnet_obj.check_vnet_ecmp_routes(dvs, 'Vnet10', ['fd:10:1::1', 'fd:10:1::2', 'fd:10:1::3'], tunnel_name) - check_state_db_routes(dvs, 'Vnet10', "fd:10:10::1/128", ['fd:10:1::1', 'fd:10:1::2', 'fd:10:1::3']) - # The default Vnet setting does not advertise prefix + route1, nhg1_1 = vnet_obj.check_vnet_ecmp_routes(dvs, vnet_name, ['fd:10:1::1', 'fd:10:1::2', 'fd:10:1::3'], tunnel_name, ordered_ecmp=ordered_ecmp, nh_seq_id=['1', '2', '3']) + check_state_db_routes(dvs, vnet_name, "fd:10:10::1/128", ['fd:10:1::1', 'fd:10:1::2', 'fd:10:1::3']) check_remove_routes_advertisement(dvs, "fd:10:10::1/128") # Remove endpoint from group if it goes down update_bfd_session_state(dvs, 'fd:10:2::2', 'Down') time.sleep(2) - route1, nhg1_1 = vnet_obj.check_vnet_ecmp_routes(dvs, 'Vnet10', ['fd:10:1::1', 'fd:10:1::3'], tunnel_name, route_ids=route1, nhg=nhg1_1) - check_state_db_routes(dvs, 'Vnet10', "fd:10:10::1/128", ['fd:10:1::1', 'fd:10:1::3']) - # The default Vnet setting does not advertise prefix + route1, nhg1_1 = vnet_obj.check_vnet_ecmp_routes(dvs, vnet_name, ['fd:10:1::1', 'fd:10:1::3'], tunnel_name, route_ids=route1, nhg=nhg1_1, ordered_ecmp=ordered_ecmp, nh_seq_id=['1', '3']) + check_state_db_routes(dvs, vnet_name, "fd:10:10::1/128", ['fd:10:1::1', 'fd:10:1::3']) check_remove_routes_advertisement(dvs, "fd:10:10::1/128") # Create another tunnel route with endpoint group overlapped with route1 vnet_obj.fetch_exist_entries(dvs) - create_vnet_routes(dvs, "fd:10:20::1/128", 'Vnet10', 'fd:10:1::1,fd:10:1::2,fd:10:1::5', ep_monitor='fd:10:2::1,fd:10:2::2,fd:10:2::5') - route2, nhg2_1 = vnet_obj.check_vnet_ecmp_routes(dvs, 'Vnet10', ['fd:10:1::1'], tunnel_name) - check_state_db_routes(dvs, 'Vnet10', "fd:10:20::1/128", ['fd:10:1::1']) - # The default Vnet setting does not advertise prefix + create_vnet_routes(dvs, "fd:10:20::1/128", vnet_name, 'fd:10:1::1,fd:10:1::2,fd:10:1::5', ep_monitor='fd:10:2::1,fd:10:2::2,fd:10:2::5') + route2, nhg2_1 = vnet_obj.check_vnet_ecmp_routes(dvs, vnet_name, ['fd:10:1::1'], tunnel_name, ordered_ecmp=ordered_ecmp, nh_seq_id=['1']) + check_state_db_routes(dvs, vnet_name, "fd:10:20::1/128", ['fd:10:1::1']) check_remove_routes_advertisement(dvs, "fd:10:20::1/128") # Update BFD session state and verify route change update_bfd_session_state(dvs, 'fd:10:2::5', 'Up') time.sleep(2) - route2, nhg2_1 = vnet_obj.check_vnet_ecmp_routes(dvs, 'Vnet10', ['fd:10:1::1', 'fd:10:1::5'], tunnel_name, route_ids=route2, nhg=nhg2_1) - check_state_db_routes(dvs, 'Vnet10', "fd:10:20::1/128", ['fd:10:1::1', 'fd:10:1::5']) - # The default Vnet setting does not advertise prefix + route2, nhg2_1 = vnet_obj.check_vnet_ecmp_routes(dvs, vnet_name, ['fd:10:1::1', 'fd:10:1::5'], tunnel_name, route_ids=route2, nhg=nhg2_1, ordered_ecmp=ordered_ecmp, nh_seq_id=['1', '3']) + check_state_db_routes(dvs, vnet_name, "fd:10:20::1/128", ['fd:10:1::1', 'fd:10:1::5']) check_remove_routes_advertisement(dvs, "fd:10:20::1/128") # Update BFD state and check route nexthop @@ -1752,20 +1780,17 @@ def test_vnet_orch_10(self, dvs, testlog): update_bfd_session_state(dvs, 'fd:10:2::2', 'Up') time.sleep(2) - route1, nhg1_1 = vnet_obj.check_vnet_ecmp_routes(dvs, 'Vnet10', ['fd:10:1::1', 'fd:10:1::2'], tunnel_name, route_ids=route1, nhg=nhg1_1) - check_state_db_routes(dvs, 'Vnet10', "fd:10:10::1/128", ['fd:10:1::1', 'fd:10:1::2']) - # The default Vnet setting does not advertise prefix + route1, nhg1_1 = vnet_obj.check_vnet_ecmp_routes(dvs, vnet_name, ['fd:10:1::1', 'fd:10:1::2'], tunnel_name, route_ids=route1, nhg=nhg1_1, ordered_ecmp=ordered_ecmp, nh_seq_id=['1', '2']) + check_state_db_routes(dvs, vnet_name, "fd:10:10::1/128", ['fd:10:1::1', 'fd:10:1::2']) check_remove_routes_advertisement(dvs, "fd:10:10::1/128") # Set the route to a new group - set_vnet_routes(dvs, "fd:10:10::1/128", 'Vnet10', 'fd:10:1::1,fd:10:1::2,fd:10:1::3,fd:10:1::4', ep_monitor='fd:10:2::1,fd:10:2::2,fd:10:2::3,fd:10:2::4') + set_vnet_routes(dvs, "fd:10:10::1/128", vnet_name, 'fd:10:1::1,fd:10:1::2,fd:10:1::3,fd:10:1::4', ep_monitor='fd:10:2::1,fd:10:2::2,fd:10:2::3,fd:10:2::4') update_bfd_session_state(dvs, 'fd:10:2::4', 'Up') time.sleep(2) - route1, nhg1_2 = vnet_obj.check_vnet_ecmp_routes(dvs, 'Vnet10', ['fd:10:1::1', 'fd:10:1::2', 'fd:10:1::4'], tunnel_name, route_ids=route1) - check_state_db_routes(dvs, 'Vnet10', "fd:10:10::1/128", ['fd:10:1::1', 'fd:10:1::2', 'fd:10:1::4']) - # The default Vnet setting does not advertise prefix + route1, nhg1_2 = vnet_obj.check_vnet_ecmp_routes(dvs, vnet_name, ['fd:10:1::1', 'fd:10:1::2', 'fd:10:1::4'], tunnel_name, route_ids=route1, ordered_ecmp=ordered_ecmp, nh_seq_id=['1', '2', '4']) + check_state_db_routes(dvs, vnet_name, "fd:10:10::1/128", ['fd:10:1::1', 'fd:10:1::2', 'fd:10:1::4']) check_remove_routes_advertisement(dvs, "fd:10:10::1/128") - # Check the previous nexthop group is removed vnet_obj.fetch_exist_entries(dvs) assert nhg1_1 not in vnet_obj.nhgs @@ -1773,9 +1798,9 @@ def test_vnet_orch_10(self, dvs, testlog): # Set BFD session state for a down endpoint to up update_bfd_session_state(dvs, 'fd:10:2::3', 'Up') time.sleep(2) - route1, nhg1_2 = vnet_obj.check_vnet_ecmp_routes(dvs, 'Vnet10', ['fd:10:1::1', 'fd:10:1::2', 'fd:10:1::3', 'fd:10:1::4'], tunnel_name, route_ids=route1, nhg=nhg1_2) - check_state_db_routes(dvs, 'Vnet10', "fd:10:10::1/128", ['fd:10:1::1', 'fd:10:1::2', 'fd:10:1::3', 'fd:10:1::4']) - # The default Vnet setting does not advertise prefix + route1, nhg1_2 = vnet_obj.check_vnet_ecmp_routes(dvs, vnet_name, ['fd:10:1::1', 'fd:10:1::2', 'fd:10:1::3', 'fd:10:1::4'], tunnel_name, route_ids=route1, nhg=nhg1_2, + ordered_ecmp=ordered_ecmp, nh_seq_id=['1', '2', '3', '4']) + check_state_db_routes(dvs, vnet_name, "fd:10:10::1/128", ['fd:10:1::1', 'fd:10:1::2', 'fd:10:1::3', 'fd:10:1::4']) check_remove_routes_advertisement(dvs, "fd:10:10::1/128") # Set all endpoint to down state @@ -1786,18 +1811,18 @@ def test_vnet_orch_10(self, dvs, testlog): time.sleep(2) # Confirm the tunnel route is updated in ASIC - vnet_obj.check_del_vnet_routes(dvs, 'Vnet10', ["fd:10:10::1/128"]) - route2, nhg2_1 = vnet_obj.check_vnet_ecmp_routes(dvs, 'Vnet10', ['fd:10:1::5'], tunnel_name, route_ids=route2, nhg=nhg2_1) - check_state_db_routes(dvs, 'Vnet10', "fd:10:20::1/128", ['fd:10:1::5']) - check_state_db_routes(dvs, 'Vnet10', "fd:10:10::1/128", []) + vnet_obj.check_del_vnet_routes(dvs, vnet_name, ["fd:10:10::1/128"]) + route2, nhg2_1 = vnet_obj.check_vnet_ecmp_routes(dvs, vnet_name, ['fd:10:1::5'], tunnel_name, route_ids=route2, nhg=nhg2_1, ordered_ecmp=ordered_ecmp, nh_seq_id=['3']) + check_state_db_routes(dvs, vnet_name, "fd:10:20::1/128", ['fd:10:1::5']) + check_state_db_routes(dvs, vnet_name, "fd:10:10::1/128", []) check_remove_routes_advertisement(dvs, "fd:10:10::1/128") # The default Vnet setting does not advertise prefix check_remove_routes_advertisement(dvs, "fd:10:20::1/128") # Remove tunnel route2 - delete_vnet_routes(dvs, "fd:10:20::1/128", 'Vnet10') - vnet_obj.check_del_vnet_routes(dvs, 'Vnet10', ["fd:10:20::1/128"]) - check_remove_state_db_routes(dvs, 'Vnet10', "fd:10:20::1/128") + delete_vnet_routes(dvs, "fd:10:20::1/128", vnet_name) + vnet_obj.check_del_vnet_routes(dvs, vnet_name, ["fd:10:20::1/128"]) + check_remove_state_db_routes(dvs, vnet_name, "fd:10:20::1/128") check_remove_routes_advertisement(dvs, "fd:10:20::1/128") # Check the corresponding nexthop group is removed @@ -1813,9 +1838,9 @@ def test_vnet_orch_10(self, dvs, testlog): check_bfd_session(dvs, ['fd:10:2::1', 'fd:10:2::2', 'fd:10:2::3', 'fd:10:2::4']) # Remove tunnel route 1 - delete_vnet_routes(dvs, "fd:10:10::1/128", 'Vnet10') - vnet_obj.check_del_vnet_routes(dvs, 'Vnet10', ["fd:10:10::1/128"]) - check_remove_state_db_routes(dvs, 'Vnet10', "fd:10:10::1/128") + delete_vnet_routes(dvs, "fd:10:10::1/128", vnet_name) + vnet_obj.check_del_vnet_routes(dvs, vnet_name, ["fd:10:10::1/128"]) + check_remove_state_db_routes(dvs, vnet_name, "fd:10:10::1/128") check_remove_routes_advertisement(dvs, "fd:10:10::1/128") # Confirm the BFD sessions are removed @@ -1825,89 +1850,89 @@ def test_vnet_orch_10(self, dvs, testlog): vnet_obj.fetch_exist_entries(dvs) assert nhg1_2 not in vnet_obj.nhgs - delete_vnet_entry(dvs, 'Vnet10') - vnet_obj.check_del_vnet_entry(dvs, 'Vnet10') + delete_vnet_entry(dvs, vnet_name) + vnet_obj.check_del_vnet_entry(dvs, vnet_name) ''' Test 11 - Test for vnet tunnel routes with both single endpoint and ECMP group with endpoint health monitor ''' - def test_vnet_orch_11(self, dvs, testlog): + def test_vnet_orch_11(self, dvs, ordered_ecmp, testlog): vnet_obj = self.get_vnet_obj() - tunnel_name = 'tunnel_11' + tunnel_name = 'tunnel_11' + ordered_ecmp + vnet_name = 'Vnet11' + ordered_ecmp vnet_obj.fetch_exist_entries(dvs) create_vxlan_tunnel(dvs, tunnel_name, '11.11.11.11') - create_vnet_entry(dvs, 'Vnet11', tunnel_name, '100011', "") + create_vnet_entry(dvs, vnet_name, tunnel_name, '100011', "") - vnet_obj.check_vnet_entry(dvs, 'Vnet11') - vnet_obj.check_vxlan_tunnel_entry(dvs, tunnel_name, 'Vnet11', '100011') + vnet_obj.check_vnet_entry(dvs, vnet_name) + vnet_obj.check_vxlan_tunnel_entry(dvs, tunnel_name, vnet_name, '100011') vnet_obj.check_vxlan_tunnel(dvs, tunnel_name, '11.11.11.11') vnet_obj.fetch_exist_entries(dvs) - create_vnet_routes(dvs, "100.100.1.1/32", 'Vnet11', '11.0.0.1', ep_monitor='11.1.0.1') + create_vnet_routes(dvs, "100.100.1.1/32", vnet_name, '11.0.0.1', ep_monitor='11.1.0.1') # default bfd status is down, route should not be programmed in this status - vnet_obj.check_del_vnet_routes(dvs, 'Vnet11', ["100.100.1.1/32"]) - check_state_db_routes(dvs, 'Vnet11', "100.100.1.1/32", []) + vnet_obj.check_del_vnet_routes(dvs, vnet_name, ["100.100.1.1/32"]) + check_state_db_routes(dvs, vnet_name, "100.100.1.1/32", []) check_remove_routes_advertisement(dvs, "100.100.1.1/32") # Route should be properly configured when bfd session state goes up update_bfd_session_state(dvs, '11.1.0.1', 'Up') time.sleep(2) - vnet_obj.check_vnet_routes(dvs, 'Vnet11', '11.0.0.1', tunnel_name) - check_state_db_routes(dvs, 'Vnet11', "100.100.1.1/32", ['11.0.0.1']) - # The default Vnet setting does not advertise prefix + vnet_obj.check_vnet_routes(dvs, vnet_name, '11.0.0.1', tunnel_name) + check_state_db_routes(dvs, vnet_name, "100.100.1.1/32", ['11.0.0.1']) check_remove_routes_advertisement(dvs, "100.100.1.1/32") # Create another tunnel route with endpoint group overlapped with route1 vnet_obj.fetch_exist_entries(dvs) - create_vnet_routes(dvs, "100.100.2.1/32", 'Vnet11', '11.0.0.1,11.0.0.2', ep_monitor='11.1.0.1,11.1.0.2') - route2, nhg2_1 = vnet_obj.check_vnet_ecmp_routes(dvs, 'Vnet11', ['11.0.0.1'], tunnel_name) - check_state_db_routes(dvs, 'Vnet11', "100.100.2.1/32", ['11.0.0.1']) - # The default Vnet setting does not advertise prefix + create_vnet_routes(dvs, "100.100.2.1/32", vnet_name, '11.0.0.2,11.0.0.1', ep_monitor='11.1.0.2,11.1.0.1') + route2, nhg2_1 = vnet_obj.check_vnet_ecmp_routes(dvs, vnet_name, ['11.0.0.1'], tunnel_name, ordered_ecmp=ordered_ecmp, nh_seq_id=['1']) + check_state_db_routes(dvs, vnet_name, "100.100.2.1/32", ['11.0.0.1']) check_remove_routes_advertisement(dvs, "100.100.2.1/32") # Create a third tunnel route with another endpoint vnet_obj.fetch_exist_entries(dvs) - create_vnet_routes(dvs, "100.100.3.1/32", 'Vnet11', '11.0.0.2', ep_monitor='11.1.0.2') + create_vnet_routes(dvs, "100.100.3.1/32", vnet_name, '11.0.0.2', ep_monitor='11.1.0.2') # Update BFD session state and verify route change update_bfd_session_state(dvs, '11.1.0.2', 'Up') time.sleep(2) - vnet_obj.check_vnet_routes(dvs, 'Vnet11', '11.0.0.2', tunnel_name) - route2, nhg2_1 = vnet_obj.check_vnet_ecmp_routes(dvs, 'Vnet11', ['11.0.0.1', '11.0.0.2'], tunnel_name, route_ids=route2, nhg=nhg2_1) - check_state_db_routes(dvs, 'Vnet11', "100.100.3.1/32", ['11.0.0.2']) - check_state_db_routes(dvs, 'Vnet11', "100.100.2.1/32", ['11.0.0.1', '11.0.0.2']) + vnet_obj.check_vnet_routes(dvs, vnet_name, '11.0.0.2', tunnel_name) + route2, nhg2_1 = vnet_obj.check_vnet_ecmp_routes(dvs, vnet_name, ['11.0.0.1', '11.0.0.2'], tunnel_name, route_ids=route2, nhg=nhg2_1, ordered_ecmp=ordered_ecmp, nh_seq_id=['1', '2']) + check_state_db_routes(dvs, vnet_name, "100.100.3.1/32", ['11.0.0.2']) + check_state_db_routes(dvs, vnet_name, "100.100.2.1/32", ['11.0.0.1', '11.0.0.2']) check_remove_routes_advertisement(dvs, "100.100.2.1/32") # The default Vnet setting does not advertise prefix check_remove_routes_advertisement(dvs, "100.100.3.1/32") + update_bfd_session_state(dvs, '11.1.0.1', 'Down') time.sleep(2) - route2, nhg2_1 = vnet_obj.check_vnet_ecmp_routes(dvs, 'Vnet11', ['11.0.0.2'], tunnel_name, route_ids=route2, nhg=nhg2_1) - vnet_obj.check_del_vnet_routes(dvs, 'Vnet11', ["100.100.1.1/32"]) - check_state_db_routes(dvs, 'Vnet11', "100.100.2.1/32", ['11.0.0.2']) - check_state_db_routes(dvs, 'Vnet11', "100.100.1.1/32", []) + route2, nhg2_1 = vnet_obj.check_vnet_ecmp_routes(dvs, vnet_name, ['11.0.0.2'], tunnel_name, route_ids=route2, nhg=nhg2_1, ordered_ecmp=ordered_ecmp, nh_seq_id=['2']) + vnet_obj.check_del_vnet_routes(dvs, vnet_name, ["100.100.1.1/32"]) + check_state_db_routes(dvs, vnet_name, "100.100.2.1/32", ['11.0.0.2']) + check_state_db_routes(dvs, vnet_name, "100.100.1.1/32", []) check_remove_routes_advertisement(dvs, "100.100.1.1/32") # The default Vnet setting does not advertise prefix check_remove_routes_advertisement(dvs, "100.100.2.1/32") + # Set the route1 to a new endpoint vnet_obj.fetch_exist_entries(dvs) - set_vnet_routes(dvs, "100.100.1.1/32", 'Vnet11', '11.0.0.2', ep_monitor='11.1.0.2') - vnet_obj.check_vnet_routes(dvs, 'Vnet11', '11.0.0.2', tunnel_name) - check_state_db_routes(dvs, 'Vnet11', "100.100.3.1/32", ['11.0.0.2']) - # The default Vnet setting does not advertise prefix + set_vnet_routes(dvs, "100.100.1.1/32", vnet_name, '11.0.0.2', ep_monitor='11.1.0.2') + vnet_obj.check_vnet_routes(dvs, vnet_name, '11.0.0.2', tunnel_name) + check_state_db_routes(dvs, vnet_name, "100.100.3.1/32", ['11.0.0.2']) check_remove_routes_advertisement(dvs, "100.100.3.1/32") # Remove tunnel route2 - delete_vnet_routes(dvs, "100.100.2.1/32", 'Vnet11') - vnet_obj.check_del_vnet_routes(dvs, 'Vnet11', ["100.100.2.1/32"]) - check_remove_state_db_routes(dvs, 'Vnet11', "100.100.2.1/32") + delete_vnet_routes(dvs, "100.100.2.1/32", vnet_name) + vnet_obj.check_del_vnet_routes(dvs, vnet_name, ["100.100.2.1/32"]) + check_remove_state_db_routes(dvs, vnet_name, "100.100.2.1/32") check_remove_routes_advertisement(dvs, "100.100.2.1/32") # Check the corresponding nexthop group is removed @@ -1919,22 +1944,22 @@ def test_vnet_orch_11(self, dvs, testlog): check_bfd_session(dvs, ['11.1.0.2']) # Remove tunnel route 1 - delete_vnet_routes(dvs, "100.100.1.1/32", 'Vnet11') - vnet_obj.check_del_vnet_routes(dvs, 'Vnet11', ["100.100.1.1/32"]) - check_remove_state_db_routes(dvs, 'Vnet11', "100.100.1.1/32") + delete_vnet_routes(dvs, "100.100.1.1/32", vnet_name) + vnet_obj.check_del_vnet_routes(dvs, vnet_name, ["100.100.1.1/32"]) + check_remove_state_db_routes(dvs, vnet_name, "100.100.1.1/32") check_remove_routes_advertisement(dvs, "100.100.1.1/32") # Remove tunnel route 3 - delete_vnet_routes(dvs, "100.100.3.1/32", 'Vnet11') - vnet_obj.check_del_vnet_routes(dvs, 'Vnet11', ["100.100.3.1/32"]) - check_remove_state_db_routes(dvs, 'Vnet11', "100.100.3.1/32") + delete_vnet_routes(dvs, "100.100.3.1/32", vnet_name) + vnet_obj.check_del_vnet_routes(dvs, vnet_name, ["100.100.3.1/32"]) + check_remove_state_db_routes(dvs, vnet_name, "100.100.3.1/32") check_remove_routes_advertisement(dvs, "100.100.3.1/32") # Confirm the BFD sessions are removed check_del_bfd_session(dvs, ['11.1.0.1', '11.1.0.2']) - delete_vnet_entry(dvs, 'Vnet11') - vnet_obj.check_del_vnet_entry(dvs, 'Vnet11') + delete_vnet_entry(dvs, vnet_name) + vnet_obj.check_del_vnet_entry(dvs, vnet_name) '''