def test_route_nhg(dvs, testlog): config_db = swsscommon.DBConnector(swsscommon.CONFIG_DB, dvs.redis_sock, 0) intf_tbl = swsscommon.Table(config_db, "INTERFACE") fvs = swsscommon.FieldValuePairs([("NULL", "NULL")]) intf_tbl.set("Ethernet0", fvs) intf_tbl.set("Ethernet4", fvs) intf_tbl.set("Ethernet8", fvs) intf_tbl.set("Ethernet0|10.0.0.0/31", fvs) intf_tbl.set("Ethernet4|10.0.0.2/31", fvs) intf_tbl.set("Ethernet8|10.0.0.4/31", fvs) dvs.runcmd("ifconfig Ethernet0 up") dvs.runcmd("ifconfig Ethernet4 up") dvs.runcmd("ifconfig Ethernet8 up") dvs.runcmd("arp -s 10.0.0.1 00:00:00:00:00:01") dvs.runcmd("arp -s 10.0.0.3 00:00:00:00:00:02") dvs.runcmd("arp -s 10.0.0.5 00:00:00:00:00:03") dvs.servers[0].runcmd("ip link set down dev eth0") == 0 dvs.servers[1].runcmd("ip link set down dev eth0") == 0 dvs.servers[2].runcmd("ip link set down dev eth0") == 0 dvs.servers[0].runcmd("ip link set up dev eth0") == 0 dvs.servers[1].runcmd("ip link set up dev eth0") == 0 dvs.servers[2].runcmd("ip link set up dev eth0") == 0 db = swsscommon.DBConnector(0, dvs.redis_sock, 0) ps = swsscommon.ProducerStateTable(db, "ROUTE_TABLE") fvs = swsscommon.FieldValuePairs([ ("nexthop", "10.0.0.1,10.0.0.3,10.0.0.5"), ("ifname", "Ethernet0,Ethernet4,Ethernet8") ]) ps.set("2.2.2.0/24", fvs) time.sleep(1) # check if route was propagated to ASIC DB adb = swsscommon.DBConnector(1, dvs.redis_sock, 0) rtbl = swsscommon.Table(adb, "ASIC_STATE:SAI_OBJECT_TYPE_ROUTE_ENTRY") nhgtbl = swsscommon.Table(adb, "ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP_GROUP") nhg_member_tbl = swsscommon.Table( adb, "ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP_GROUP_MEMBER") keys = rtbl.getKeys() found_route = False for k in keys: rt_key = json.loads(k) if rt_key['dest'] == "2.2.2.0/24": found_route = True break assert found_route # assert the route points to next hop group (status, fvs) = rtbl.get(k) for v in fvs: if v[0] == "SAI_ROUTE_ENTRY_ATTR_NEXT_HOP_ID": nhgid = v[1] (status, fvs) = nhgtbl.get(nhgid) assert status keys = nhg_member_tbl.getKeys() assert len(keys) == 3 for k in keys: (status, fvs) = nhg_member_tbl.get(k) for v in fvs: if v[0] == "SAI_NEXT_HOP_GROUP_MEMBER_ATTR_NEXT_HOP_GROUP_ID": assert v[1] == nhgid # bring links down one-by-one for i in [0, 1, 2]: dvs.servers[i].runcmd("ip link set down dev eth0") == 0 time.sleep(1) tbl = swsscommon.Table(db, "PORT_TABLE") (status, fvs) = tbl.get("Ethernet%d" % (i * 4)) assert status == True oper_status = "unknown" for v in fvs: if v[0] == "oper_status": oper_status = v[1] break assert oper_status == "down" keys = nhg_member_tbl.getKeys() assert len(keys) == 2 - i # bring links up one-by-one for i in [0, 1, 2]: dvs.servers[i].runcmd("ip link set up dev eth0") == 0 time.sleep(1) tbl = swsscommon.Table(db, "PORT_TABLE") (status, fvs) = tbl.get("Ethernet%d" % (i * 4)) assert status == True oper_status = "unknown" for v in fvs: if v[0] == "oper_status": oper_status = v[1] break assert oper_status == "up" keys = nhg_member_tbl.getKeys() assert len(keys) == i + 1 for k in keys: (status, fvs) = nhg_member_tbl.get(k) for v in fvs: if v[0] == "SAI_NEXT_HOP_GROUP_MEMBER_ATTR_NEXT_HOP_GROUP_ID": assert v[1] == nhgid
def test_AclBindMirrorV6Combined(self, dvs, testlog): """ This test verifies IPv6 rules cannot be inserted into MIRROR table """ self.setup_db(dvs) self.setup_mirrorv6_mode("combined") session = "MIRROR_SESSION" acl_table = "MIRROR_TABLE" acl_table_v6 = "MIRROR_TABLE_V6" acl_rule_1 = "MIRROR_RULE_1" acl_rule_2 = "MIRROR_RULE_2" # bring up port; assign ip; create neighbor; create route self.set_interface_status("Ethernet32", "up") self.add_ip_address("Ethernet32", "20.0.0.0/31") self.add_neighbor("Ethernet32", "20.0.0.1", "02:04:06:08:10:12") self.add_route(dvs, "4.4.4.4", "20.0.0.1") # create mirror session self.create_mirror_session(session, "3.3.3.3", "4.4.4.4", "0x6558", "8", "100", "0") assert self.get_mirror_session_state(session)["status"] == "active" # assert mirror session in asic database tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_MIRROR_SESSION") assert len(tbl.getKeys()) == 1 mirror_session_oid = tbl.getKeys()[0] # create acl table ipv4 self.create_acl_table(acl_table, ["Ethernet0", "Ethernet4"], "MIRROR") # assert acl table is created tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_ACL_TABLE") table_entries = [ k for k in tbl.getKeys() if k not in dvs.asicdb.default_acl_tables ] assert len(table_entries) == 1 # create acl table ipv6 self.create_acl_table(acl_table_v6, ["Ethernet0", "Ethernet4"], "MIRRORV6") # assert acl table is created tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_ACL_TABLE") table_entries = [ k for k in tbl.getKeys() if k not in dvs.asicdb.default_acl_tables ] assert len(table_entries) == 1 table_id = table_entries[0] # create acl rule with IPv4 addresses self.create_mirror_acl_ipv4_rule(acl_table, acl_rule_1, session) # assert acl rule ipv4 is created tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_ACL_ENTRY") rule_entries = [ k for k in tbl.getKeys() if k not in dvs.asicdb.default_acl_entries ] assert len(rule_entries) == 1 rule_id_v4 = rule_entries[0] # assert acl rule is assocaited with table ipv4 (status, fvs) = tbl.get(rule_id_v4) assert status == True for fv in fvs: if fv[0] == "SAI_ACL_ENTRY_ATTR_TABLE_ID": assert fv[1] == table_id # create acl rule with IPv6 addresses self.create_mirror_acl_ipv6_rule(acl_table_v6, acl_rule_2, session) # assert acl rule ipv6 is created tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_ACL_ENTRY") rule_entries = [ k for k in tbl.getKeys() if k not in dvs.asicdb.default_acl_entries ] assert len(rule_entries) == 2 rule_id_v6 = rule_entries[1] if rule_entries[ 0] == rule_id_v4 else rule_entries[0] # assert acl rule is associated with table ipv6 (status, fvs) = tbl.get(rule_id_v6) assert status == True for fv in fvs: if fv[0] == "SAI_ACL_ENTRY_ATTR_TABLE_ID": assert fv[1] == table_id # remove acl rule self.remove_mirror_acl_rule(acl_table, acl_rule_1) self.remove_mirror_acl_rule(acl_table_v6, acl_rule_2) # remove acl table self.remove_acl_table(acl_table) self.remove_acl_table(acl_table_v6) # remove mirror session self.remove_mirror_session(session) # assert no mirror session in asic database tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_MIRROR_SESSION") assert len(tbl.getKeys()) == 0 # remove route; remove neighbor; remove ip; bring down port self.remove_route(dvs, "4.4.4.4") self.remove_neighbor("Ethernet32", "20.0.0.1") self.remove_ip_address("Ethernet32", "20.0.0.0/31") self.set_interface_status("Ethernet32", "down")
def test_AclBindMirrorV6WrongConfig(self, dvs, testlog): """ This test verifies IPv6 rules cannot be inserted into MIRROR table """ self.setup_db(dvs) session = "MIRROR_SESSION" acl_table = "MIRROR_TABLE" acl_table_v6 = "MIRROR_TABLE_V6" acl_rule_1 = "MIRROR_RULE_1" acl_rule_2 = "MIRROR_RULE_2" # bring up port; assign ip; create neighbor; create route self.set_interface_status("Ethernet32", "up") self.add_ip_address("Ethernet32", "20.0.0.0/31") self.add_neighbor("Ethernet32", "20.0.0.1", "02:04:06:08:10:12") self.add_route(dvs, "4.4.4.4", "20.0.0.1") # create mirror session self.create_mirror_session(session, "3.3.3.3", "4.4.4.4", "0x6558", "8", "100", "0") assert self.get_mirror_session_state(session)["status"] == "active" # assert mirror session in asic database tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_MIRROR_SESSION") assert len(tbl.getKeys()) == 1 mirror_session_oid = tbl.getKeys()[0] # create acl table ipv4 self.create_acl_table(acl_table, ["Ethernet0", "Ethernet4"], "MIRROR") # create WRONG acl rule with IPv6 addresses self.create_mirror_acl_ipv6_rule(acl_table, acl_rule_2, session) # assert acl rule is not created tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_ACL_ENTRY") rule_entries = [ k for k in tbl.getKeys() if k not in dvs.asicdb.default_acl_entries ] assert len(rule_entries) == 0 # create acl table ipv6 self.create_acl_table(acl_table_v6, ["Ethernet0", "Ethernet4"], "MIRRORV6") # create WRONG acl rule with IPv4 addresses self.create_mirror_acl_ipv4_rule(acl_table_v6, acl_rule_1, session) # assert acl rules are created tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_ACL_ENTRY") rule_entries = [ k for k in tbl.getKeys() if k not in dvs.asicdb.default_acl_entries ] assert len(rule_entries) == 0 # remove acl rule self.remove_mirror_acl_rule(acl_table, acl_rule_1) self.remove_mirror_acl_rule(acl_table_v6, acl_rule_2) # remove acl table self.remove_acl_table(acl_table) self.remove_acl_table(acl_table_v6) # remove mirror session self.remove_mirror_session(session) # assert no mirror session in asic database tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_MIRROR_SESSION") assert len(tbl.getKeys()) == 0 # remove route; remove neighbor; remove ip; bring down port self.remove_route(dvs, "4.4.4.4") self.remove_neighbor("Ethernet32", "20.0.0.1") self.remove_ip_address("Ethernet32", "20.0.0.0/31") self.set_interface_status("Ethernet32", "down")
def get_created_entry(db, table, existed_entries): tbl = swsscommon.Table(db, table) entries = set(tbl.getKeys()) new_entries = list(entries - existed_entries) assert len(new_entries) == 1, "Wrong number of created entries." return new_entries[0]
def remove_acl_table(self, table): tbl = swsscommon.Table(self.cdb, "ACL_TABLE") tbl._del(table) time.sleep(1)
def remove_acl_rule(self, dvs, table_name, rule_name): tbl = swsscommon.Table(self.cdb, "ACL_RULE") tbl._del(table_name + "|" + rule_name, fvs) time.sleep(1)
def delete_entry_tbl(db, table, key): tbl = swsscommon.Table(db, table) tbl._del(key) time.sleep(1)
def __init__(self, dvs): self.appl_db = swsscommon.DBConnector(swsscommon.APPL_DB, dvs.redis_sock, 0) self.neighTbl = swsscommon.Table(self.appl_db, "NEIGH_TABLE")
def update_acl_table(self, table, fvs): tbl = swsscommon.Table(self.cdb, "ACL_TABLE") tbl.set(table, fvs) time.sleep(1)
def remove_vlan_member(self, vlan, interface): tbl = swsscommon.Table(self.cdb, "VLAN_MEMBER") tbl._del("Vlan" + vlan + "|" + interface) time.sleep(1)
def remove_vlan(self, vlan): tbl = swsscommon.Table(self.cdb, "VLAN") tbl._del("Vlan" + vlan) time.sleep(1)
def create_vlan_member_tagged(self, vlan, interface): tbl = swsscommon.Table(self.cdb, "VLAN_MEMBER") fvs = swsscommon.FieldValuePairs([("tagging_mode", "tagged")]) tbl.set("Vlan" + vlan + "|" + interface, fvs) time.sleep(1)
def create_vlan(self, vlan): tbl = swsscommon.Table(self.cdb, "VLAN") fvs = swsscommon.FieldValuePairs([("vlanid", vlan)]) tbl.set("Vlan" + vlan, fvs) time.sleep(1)
def test_PolicerBasic(self, dvs, testlog): dvs.setup_db() policer = "POLICER" # create policer tbl = swsscommon.Table(dvs.cdb, "POLICER") fvs = swsscommon.FieldValuePairs([("meter_type", "packets"), ("mode", "sr_tcm"), ("cir", "600"), ("cbs", "600"), ("red_packet_action", "drop")]) tbl.set(policer, fvs) time.sleep(1) # check asic database tbl = swsscommon.Table(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_POLICER") policer_entries = [ p for p in tbl.getKeys() if p not in dvs.asicdb.default_copp_policers ] assert len(policer_entries) == 1 (status, fvs) = tbl.get(policer_entries[0]) assert status == True assert len(fvs) == 5 for fv in fvs: if fv[0] == "SAI_POLICER_ATTR_CBS": assert fv[1] == "600" if fv[0] == "SAI_POLICER_ATTR_CIR": assert fv[1] == "600" if fv[0] == "SAI_POLICER_ATTR_RED_PACKET_ACTION": assert fv[1] == "SAI_PACKET_ACTION_DROP" if fv[0] == "SAI_POLICER_ATTR_MODE": assert fv[1] == "SAI_POLICER_MODE_SR_TCM" if fv[0] == "SAI_POLICER_ATTR_METER_TYPE": assert fv[1] == "SAI_METER_TYPE_PACKETS" # update cir tbl = swsscommon.Table(dvs.cdb, "POLICER") fvs = swsscommon.FieldValuePairs([("cir", "800")]) tbl.set(policer, fvs) time.sleep(1) # check asic database tbl = swsscommon.Table(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_POLICER") (status, fvs) = tbl.get(policer_entries[0]) assert status == True assert len(fvs) == 5 for fv in fvs: if fv[0] == "SAI_POLICER_ATTR_CBS": assert fv[1] == "600" if fv[0] == "SAI_POLICER_ATTR_CIR": assert fv[1] == "800" # updated if fv[0] == "SAI_POLICER_ATTR_RED_PACKET_ACTION": assert fv[1] == "SAI_PACKET_ACTION_DROP" if fv[0] == "SAI_POLICER_ATTR_MODE": assert fv[1] == "SAI_POLICER_MODE_SR_TCM" if fv[0] == "SAI_POLICER_ATTR_METER_TYPE": assert fv[1] == "SAI_METER_TYPE_PACKETS" # remove policer tbl = swsscommon.Table(dvs.cdb, "POLICER") tbl._del(policer) time.sleep(1) # check asic database tbl = swsscommon.Table(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_POLICER") policer_entries = [ p for p in tbl.getKeys() if p not in dvs.asicdb.default_copp_policers ] assert len(policer_entries) == 0
def add_port_channel_members(self, dvs, lag, members): tbl = swsscommon.Table(self.cdb, "PORTCHANNEL_MEMBER") fvs = swsscommon.FieldValuePairs([("NULL", "NULL")]) for member in members: tbl.set(lag + "|" + member, fvs) time.sleep(1)
def get_acl_group_ids(self): atbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_ACL_TABLE_GROUP") acl_table_groups = atbl.getKeys() return acl_table_groups
def remove_port_channel_members(self, dvs, lag, members): tbl = swsscommon.Table(self.cdb, "PORTCHANNEL_MEMBER") for member in members: tbl._del(lag + "|" + member) time.sleep(1)
def verify_acl_port_binding(self, bind_ports): atbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_ACL_TABLE_GROUP") acl_table_groups = atbl.getKeys() assert len(acl_table_groups) == len(bind_ports)
def create_entry_tbl(db, table, separator, key, pairs): tbl = swsscommon.Table(db, table) create_entry(tbl, key, pairs)
def generator_SelectMemoryLeak(): app_db = swsscommon.DBConnector("APPL_DB", 0, True) t = swsscommon.Table(app_db, "TABLE") for i in range(int(N / 2)): table_set(t, "up") table_set(t, "down")
def get_exist_entries(dvs, table): db = swsscommon.DBConnector(swsscommon.ASIC_DB, dvs.redis_sock, 0) tbl = swsscommon.Table(db, table) return set(tbl.getKeys())
def test_route_fgnhg(self, dvs, testlog): app_db = dvs.get_app_db() asic_db = dvs.get_asic_db() config_db = dvs.get_config_db() state_db = dvs.get_state_db() fvs_nul = {"NULL": "NULL"} NUM_NHs = 6 fg_nhg_name = "fgnhg_v4" fg_nhg_prefix = "2.2.2.0/24" bucket_size = 60 ip_to_if_map = {} fvs = {"bucket_size": str(bucket_size)} create_entry(config_db, FG_NHG, fg_nhg_name, fvs) fvs = {"FG_NHG": fg_nhg_name} create_entry(config_db, FG_NHG_PREFIX, fg_nhg_prefix, fvs) for i in range(0, NUM_NHs): if_name_key = "Ethernet" + str(i * 4) ip_pref_key = "Ethernet" + str(i * 4) + "|10.0.0." + str( i * 2) + "/31" create_entry(config_db, IF_TB, if_name_key, fvs_nul) create_entry(config_db, IF_TB, ip_pref_key, fvs_nul) dvs.runcmd("config interface startup " + if_name_key) dvs.servers[i].runcmd("ip link set down dev eth0") == 0 dvs.servers[i].runcmd("ip link set up dev eth0") == 0 bank = 0 if i >= NUM_NHs / 2: bank = 1 fvs = {"FG_NHG": fg_nhg_name, "bank": str(bank)} create_entry(config_db, FG_NHG_MEMBER, "10.0.0." + str(1 + i * 2), fvs) ip_to_if_map["10.0.0." + str(1 + i * 2)] = if_name_key # Wait for the software to receive the entries time.sleep(1) asic_routes_count = len(asic_db.get_keys(ASIC_ROUTE_TB)) ps = swsscommon.ProducerStateTable(app_db.db_connection, ROUTE_TB) fvs = swsscommon.FieldValuePairs([ ("nexthop", "10.0.0.7,10.0.0.9,10.0.0.11"), ("ifname", "Ethernet12,Ethernet16,Ethernet20") ]) ps.set(fg_nhg_prefix, fvs) # No ASIC_DB entry we can wait for since ARP is not resolved yet, # We just use sleep so that the sw receives this entry time.sleep(1) adb = swsscommon.DBConnector(1, dvs.redis_sock, 0) rtbl = swsscommon.Table(adb, ASIC_ROUTE_TB) keys = rtbl.getKeys() found_route = False for k in keys: rt_key = json.loads(k) if rt_key['dest'] == fg_nhg_prefix: found_route = True break # Since we didn't populate ARP yet, the route shouldn't be programmed assert (found_route == False) dvs.runcmd("arp -s 10.0.0.1 00:00:00:00:00:01") dvs.runcmd("arp -s 10.0.0.3 00:00:00:00:00:02") dvs.runcmd("arp -s 10.0.0.5 00:00:00:00:00:03") dvs.runcmd("arp -s 10.0.0.9 00:00:00:00:00:05") dvs.runcmd("arp -s 10.0.0.11 00:00:00:00:00:06") keys = asic_db.wait_for_n_keys(ASIC_ROUTE_TB, asic_routes_count + 1) nhgid = asic_route_exists_and_is_nhg(asic_db, keys, fg_nhg_prefix) assert nhgid is not None validate_asic_nhg(asic_db, nhgid, bucket_size) nh_oid_map = get_nh_oid_map(asic_db) ### Test scenarios with bank 0 having 0 members up # ARP is not resolved for 10.0.0.7, so fg nhg should be created without 10.0.0.7 nh_memb_exp_count = {"10.0.0.9": 30, "10.0.0.11": 30} validate_fine_grained_asic_n_state_db_entries(asic_db, state_db, ip_to_if_map, nh_memb_exp_count, nh_oid_map, nhgid, bucket_size) # Resolve ARP for 10.0.0.7 asic_nh_count = len( asic_db.get_keys("ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP")) dvs.runcmd("arp -s 10.0.0.7 00:00:00:00:00:04") asic_db.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP", asic_nh_count + 1) nh_oid_map = get_nh_oid_map(asic_db) # Now that ARP was resolved, 10.0.0.7 should be added as a valid fg nhg member nh_memb_exp_count = {"10.0.0.7": 20, "10.0.0.9": 20, "10.0.0.11": 20} validate_fine_grained_asic_n_state_db_entries(asic_db, state_db, ip_to_if_map, nh_memb_exp_count, nh_oid_map, nhgid, bucket_size) # Bring down 1 next hop in bank 1 nh_memb_exp_count = {"10.0.0.7": 30, "10.0.0.11": 30} program_route_and_validate_fine_grained_ecmp( app_db.db_connection, asic_db, state_db, ip_to_if_map, fg_nhg_prefix, nh_memb_exp_count, nh_oid_map, nhgid, bucket_size) # Bring up 1 next hop in bank 1 nh_memb_exp_count = {"10.0.0.7": 20, "10.0.0.9": 20, "10.0.0.11": 20} program_route_and_validate_fine_grained_ecmp( app_db.db_connection, asic_db, state_db, ip_to_if_map, fg_nhg_prefix, nh_memb_exp_count, nh_oid_map, nhgid, bucket_size) # Bring up some next-hops in bank 0 for the 1st time nh_memb_exp_count = { "10.0.0.1": 10, "10.0.0.3": 10, "10.0.0.5": 10, "10.0.0.7": 10, "10.0.0.9": 10, "10.0.0.11": 10 } program_route_and_validate_fine_grained_ecmp( app_db.db_connection, asic_db, state_db, ip_to_if_map, fg_nhg_prefix, nh_memb_exp_count, nh_oid_map, nhgid, bucket_size) # Bring down 1 next-hop from bank 0, and 2 next-hops from bank 1 nh_memb_exp_count = {"10.0.0.1": 15, "10.0.0.5": 15, "10.0.0.11": 30} program_route_and_validate_fine_grained_ecmp( app_db.db_connection, asic_db, state_db, ip_to_if_map, fg_nhg_prefix, nh_memb_exp_count, nh_oid_map, nhgid, bucket_size) # Bring down 1 member and bring up 1 member in bank 0 at the same time nh_memb_exp_count = {"10.0.0.1": 15, "10.0.0.3": 15, "10.0.0.11": 30} program_route_and_validate_fine_grained_ecmp( app_db.db_connection, asic_db, state_db, ip_to_if_map, fg_nhg_prefix, nh_memb_exp_count, nh_oid_map, nhgid, bucket_size) # Bring down 2 members and bring up 1 member in bank 0 at the same time nh_memb_exp_count = {"10.0.0.5": 30, "10.0.0.11": 30} program_route_and_validate_fine_grained_ecmp( app_db.db_connection, asic_db, state_db, ip_to_if_map, fg_nhg_prefix, nh_memb_exp_count, nh_oid_map, nhgid, bucket_size) # Bring up 2 members and bring down 1 member in bank 0 at the same time nh_memb_exp_count = {"10.0.0.1": 15, "10.0.0.3": 15, "10.0.0.11": 30} program_route_and_validate_fine_grained_ecmp( app_db.db_connection, asic_db, state_db, ip_to_if_map, fg_nhg_prefix, nh_memb_exp_count, nh_oid_map, nhgid, bucket_size) # Bringup arbitrary # of next-hops from both banks at the same time nh_memb_exp_count = { "10.0.0.1": 10, "10.0.0.3": 10, "10.0.0.5": 10, "10.0.0.7": 10, "10.0.0.9": 10, "10.0.0.11": 10 } program_route_and_validate_fine_grained_ecmp( app_db.db_connection, asic_db, state_db, ip_to_if_map, fg_nhg_prefix, nh_memb_exp_count, nh_oid_map, nhgid, bucket_size) # Bring all next-hops in bank 1 down nh_memb_exp_count = {"10.0.0.1": 20, "10.0.0.3": 20, "10.0.0.5": 20} program_route_and_validate_fine_grained_ecmp( app_db.db_connection, asic_db, state_db, ip_to_if_map, fg_nhg_prefix, nh_memb_exp_count, nh_oid_map, nhgid, bucket_size) # Make next-hop changes to bank 0 members, given bank 1 is still down nh_memb_exp_count = {"10.0.0.1": 30, "10.0.0.5": 30} program_route_and_validate_fine_grained_ecmp( app_db.db_connection, asic_db, state_db, ip_to_if_map, fg_nhg_prefix, nh_memb_exp_count, nh_oid_map, nhgid, bucket_size) # Bringup 1 member in bank 1 again nh_memb_exp_count = {"10.0.0.1": 15, "10.0.0.5": 15, "10.0.0.11": 30} program_route_and_validate_fine_grained_ecmp( app_db.db_connection, asic_db, state_db, ip_to_if_map, fg_nhg_prefix, nh_memb_exp_count, nh_oid_map, nhgid, bucket_size) # Test 2nd,3rd memb up in bank nh_memb_exp_count = { "10.0.0.1": 15, "10.0.0.5": 15, "10.0.0.7": 10, "10.0.0.9": 10, "10.0.0.11": 10 } program_route_and_validate_fine_grained_ecmp( app_db.db_connection, asic_db, state_db, ip_to_if_map, fg_nhg_prefix, nh_memb_exp_count, nh_oid_map, nhgid, bucket_size) # bring all links down one by one shutdown_link(dvs, app_db, 0) nh_memb_exp_count = { "10.0.0.5": 30, "10.0.0.7": 10, "10.0.0.9": 10, "10.0.0.11": 10 } validate_fine_grained_asic_n_state_db_entries(asic_db, state_db, ip_to_if_map, nh_memb_exp_count, nh_oid_map, nhgid, bucket_size) shutdown_link(dvs, app_db, 2) nh_memb_exp_count = {"10.0.0.7": 20, "10.0.0.9": 20, "10.0.0.11": 20} validate_fine_grained_asic_n_state_db_entries(asic_db, state_db, ip_to_if_map, nh_memb_exp_count, nh_oid_map, nhgid, bucket_size) shutdown_link(dvs, app_db, 3) nh_memb_exp_count = {"10.0.0.9": 30, "10.0.0.11": 30} validate_fine_grained_asic_n_state_db_entries(asic_db, state_db, ip_to_if_map, nh_memb_exp_count, nh_oid_map, nhgid, bucket_size) shutdown_link(dvs, app_db, 4) nh_memb_exp_count = {"10.0.0.11": 60} validate_fine_grained_asic_n_state_db_entries(asic_db, state_db, ip_to_if_map, nh_memb_exp_count, nh_oid_map, nhgid, bucket_size) # Bring down last link, there shouldn't be a crash or other bad orchagent state because of this shutdown_link(dvs, app_db, 5) # Nothing to check for in this case, sleep 1s for the shutdown to reach sw time.sleep(1) # bring all links up one by one startup_link(dvs, app_db, 3) startup_link(dvs, app_db, 4) startup_link(dvs, app_db, 5) nh_memb_exp_count = {"10.0.0.7": 20, "10.0.0.9": 20, "10.0.0.11": 20} validate_fine_grained_asic_n_state_db_entries(asic_db, state_db, ip_to_if_map, nh_memb_exp_count, nh_oid_map, nhgid, bucket_size) startup_link(dvs, app_db, 2) nh_memb_exp_count = { "10.0.0.5": 30, "10.0.0.7": 10, "10.0.0.9": 10, "10.0.0.11": 10 } validate_fine_grained_asic_n_state_db_entries(asic_db, state_db, ip_to_if_map, nh_memb_exp_count, nh_oid_map, nhgid, bucket_size) startup_link(dvs, app_db, 0) nh_memb_exp_count = { "10.0.0.1": 15, "10.0.0.5": 15, "10.0.0.7": 10, "10.0.0.9": 10, "10.0.0.11": 10 } validate_fine_grained_asic_n_state_db_entries(asic_db, state_db, ip_to_if_map, nh_memb_exp_count, nh_oid_map, nhgid, bucket_size) # remove fgnhg member remove_entry(config_db, "FG_NHG_MEMBER", "10.0.0.1") nh_memb_exp_count = { "10.0.0.5": 30, "10.0.0.7": 10, "10.0.0.9": 10, "10.0.0.11": 10 } validate_fine_grained_asic_n_state_db_entries(asic_db, state_db, ip_to_if_map, nh_memb_exp_count, nh_oid_map, nhgid, bucket_size) # add fgnhg member fvs = {"FG_NHG": fg_nhg_name, "bank": "0"} create_entry(config_db, FG_NHG_MEMBER, "10.0.0.1", fvs) nh_memb_exp_count = { "10.0.0.1": 15, "10.0.0.5": 15, "10.0.0.7": 10, "10.0.0.9": 10, "10.0.0.11": 10 } validate_fine_grained_asic_n_state_db_entries(asic_db, state_db, ip_to_if_map, nh_memb_exp_count, nh_oid_map, nhgid, bucket_size) # Remove route asic_rt_key = get_asic_route_key(asic_db, fg_nhg_prefix) ps._del(fg_nhg_prefix) # validate routes and nhg member in asic db, route entry in state db are removed asic_db.wait_for_deleted_entry(ASIC_ROUTE_TB, asic_rt_key) asic_db.wait_for_n_keys(ASIC_NHG_MEMB, 0) state_db.wait_for_n_keys("FG_ROUTE_TABLE", 0) remove_entry(config_db, "FG_NHG_PREFIX", fg_nhg_prefix) # Nothing we can wait for in terms of db entries, we sleep here # to give the sw enough time to delete the entry time.sleep(1) # Add an ECMP route, since we deleted the FG_NHG_PREFIX it should see # standard(non-Fine grained) ECMP behavior asic_routes_count = len(asic_db.get_keys(ASIC_ROUTE_TB)) fvs = swsscommon.FieldValuePairs([ ("nexthop", "10.0.0.7,10.0.0.9,10.0.0.11"), ("ifname", "Ethernet12,Ethernet16,Ethernet20") ]) ps.set(fg_nhg_prefix, fvs) keys = asic_db.wait_for_n_keys(ASIC_ROUTE_TB, asic_routes_count + 1) nhgid = asic_route_exists_and_is_nhg(asic_db, keys, fg_nhg_prefix) assert nhgid is not None asic_db.wait_for_n_keys(ASIC_NHG_MEMB, 3) # add fgnhg prefix: The regular route should transition to fine grained ECMP fvs = {"FG_NHG": fg_nhg_name} create_entry(config_db, FG_NHG_PREFIX, fg_nhg_prefix, fvs) # Validate the transistion to Fine Grained ECMP asic_db.wait_for_n_keys(ASIC_NHG_MEMB, bucket_size) keys = asic_db.wait_for_n_keys(ASIC_ROUTE_TB, asic_routes_count + 1) nhgid = asic_route_exists_and_is_nhg(asic_db, keys, fg_nhg_prefix) validate_asic_nhg(asic_db, nhgid, bucket_size) nh_oid_map = {} nh_oid_map = get_nh_oid_map(asic_db) nh_memb_exp_count = {"10.0.0.7": 20, "10.0.0.9": 20, "10.0.0.11": 20} validate_fine_grained_asic_n_state_db_entries(asic_db, state_db, ip_to_if_map, nh_memb_exp_count, nh_oid_map, nhgid, bucket_size) # remove fgnhg prefix: The fine grained route should transition to regular ECMP/route remove_entry(config_db, "FG_NHG_PREFIX", fg_nhg_prefix) # Validate regular ECMP validate_asic_nhg_regular_ecmp(asic_db, fg_nhg_prefix) asic_db.wait_for_n_keys(ASIC_NHG_MEMB, 3) state_db.wait_for_n_keys("FG_ROUTE_TABLE", 0) # remove prefix entry asic_rt_key = get_asic_route_key(asic_db, fg_nhg_prefix) ps._del(fg_nhg_prefix) asic_db.wait_for_deleted_entry(ASIC_ROUTE_TB, asic_rt_key) asic_db.wait_for_n_keys(ASIC_NHG_MEMB, 0) # Cleanup all FG, arp and interface remove_entry(config_db, "FG_NHG", fg_nhg_name) for i in range(0, NUM_NHs): if_name_key = "Ethernet" + str(i * 4) ip_pref_key = "Ethernet" + str(i * 4) + "|10.0.0." + str( i * 2) + "/31" remove_entry(config_db, IF_TB, if_name_key) remove_entry(config_db, IF_TB, ip_pref_key) dvs.runcmd("config interface shutdown " + if_name_key) dvs.servers[i].runcmd("ip link set down dev eth0") == 0 remove_entry(config_db, "FG_NHG_MEMBER", "10.0.0." + str(1 + i * 2)) ### Create new set of entries with a greater number of FG members and ### bigger bucket size such that the # of nhs are not divisible by ### bucket size. fg_nhg_name = "new_fgnhg_v4" fg_nhg_prefix = "3.3.3.0/24" # Test with non-divisible bucket size bucket_size = 128 NUM_NHs = 10 ip_to_if_map = {} nh_oid_map = {} # Initialize base config fvs = {"bucket_size": str(bucket_size)} create_entry(config_db, FG_NHG, fg_nhg_name, fvs) fvs = {"FG_NHG": fg_nhg_name} create_entry(config_db, FG_NHG_PREFIX, fg_nhg_prefix, fvs) for i in range(0, NUM_NHs): if_name_key = "Ethernet" + str(i * 4) ip_pref_key = "Ethernet" + str(i * 4) + "|10.0.0." + str( i * 2) + "/31" create_entry(config_db, IF_TB, if_name_key, fvs_nul) create_entry(config_db, IF_TB, ip_pref_key, fvs_nul) dvs.runcmd("config interface startup " + if_name_key) shutdown_link(dvs, app_db, i) startup_link(dvs, app_db, i) bank = 1 if i >= NUM_NHs / 2: bank = 0 fvs = {"FG_NHG": fg_nhg_name, "bank": str(bank)} create_entry(config_db, FG_NHG_MEMBER, "10.0.0." + str(1 + i * 2), fvs) ip_to_if_map["10.0.0." + str(1 + i * 2)] = if_name_key dvs.runcmd("arp -s 10.0.0." + str(1 + i * 2) + " 00:00:00:00:00:" + str(1 + i * 2)) # Program the route asic_routes_count = len(asic_db.get_keys(ASIC_ROUTE_TB)) fvs = swsscommon.FieldValuePairs([("nexthop", "10.0.0.1,10.0.0.11"), ("ifname", "Ethernet0,Ethernet20")]) ps.set(fg_nhg_prefix, fvs) # Validate that the correct ASIC DB elements were setup per Fine Grained ECMP keys = asic_db.wait_for_n_keys(ASIC_ROUTE_TB, asic_routes_count + 1) nhgid = asic_route_exists_and_is_nhg(asic_db, keys, fg_nhg_prefix) assert nhgid is not None validate_asic_nhg(asic_db, nhgid, bucket_size) nh_oid_map = get_nh_oid_map(asic_db) # Test addition of route with 0 members in bank nh_memb_exp_count = {"10.0.0.1": 64, "10.0.0.11": 64} validate_fine_grained_asic_n_state_db_entries(asic_db, state_db, ip_to_if_map, nh_memb_exp_count, nh_oid_map, nhgid, bucket_size) # Add 2 nhs to both bank 0 and bank 1 nh_memb_exp_count = { "10.0.0.1": 22, "10.0.0.3": 21, "10.0.0.5": 21, "10.0.0.11": 22, "10.0.0.13": 21, "10.0.0.15": 21 } program_route_and_validate_fine_grained_ecmp( app_db.db_connection, asic_db, state_db, ip_to_if_map, fg_nhg_prefix, nh_memb_exp_count, nh_oid_map, nhgid, bucket_size) # Add 2 more nhs to both bank 0 and bank 1 nh_memb_exp_count = { "10.0.0.1": 13, "10.0.0.3": 13, "10.0.0.5": 13, "10.0.0.7": 12, "10.0.0.9": 13, "10.0.0.11": 13, "10.0.0.13": 13, "10.0.0.15": 13, "10.0.0.17": 12, "10.0.0.19": 13 } program_route_and_validate_fine_grained_ecmp( app_db.db_connection, asic_db, state_db, ip_to_if_map, fg_nhg_prefix, nh_memb_exp_count, nh_oid_map, nhgid, bucket_size) # Remove 1 nh from bank 0 and remove 2 nhs from bank 1 nh_memb_exp_count = { "10.0.0.3": 16, "10.0.0.5": 16, "10.0.0.7": 16, "10.0.0.9": 16, "10.0.0.11": 22, "10.0.0.13": 21, "10.0.0.19": 21 } program_route_and_validate_fine_grained_ecmp( app_db.db_connection, asic_db, state_db, ip_to_if_map, fg_nhg_prefix, nh_memb_exp_count, nh_oid_map, nhgid, bucket_size) # Remove 1 nh from bank 0 and add 1 nh to bank 1 nh_memb_exp_count = { "10.0.0.3": 22, "10.0.0.7": 21, "10.0.0.9": 21, "10.0.0.13": 16, "10.0.0.15": 16, "10.0.0.17": 16, "10.0.0.19": 16 } program_route_and_validate_fine_grained_ecmp( app_db.db_connection, asic_db, state_db, ip_to_if_map, fg_nhg_prefix, nh_memb_exp_count, nh_oid_map, nhgid, bucket_size) # Remove 2 nh from bank 0 and remove 3 nh from bank 1 nh_memb_exp_count = {"10.0.0.7": 64, "10.0.0.11": 64} program_route_and_validate_fine_grained_ecmp( app_db.db_connection, asic_db, state_db, ip_to_if_map, fg_nhg_prefix, nh_memb_exp_count, nh_oid_map, nhgid, bucket_size) # Add 2 nhs to bank 0 and remove all nh from bank 1 nh_memb_exp_count = {"10.0.0.5": 42, "10.0.0.7": 44, "10.0.0.9": 42} program_route_and_validate_fine_grained_ecmp( app_db.db_connection, asic_db, state_db, ip_to_if_map, fg_nhg_prefix, nh_memb_exp_count, nh_oid_map, nhgid, bucket_size) # Add 2 nhs to bank 0 and add 1 nh to bank 1 nh_memb_exp_count = { "10.0.0.1": 12, "10.0.0.3": 13, "10.0.0.5": 13, "10.0.0.7": 13, "10.0.0.9": 13, "10.0.0.11": 64 } program_route_and_validate_fine_grained_ecmp( app_db.db_connection, asic_db, state_db, ip_to_if_map, fg_nhg_prefix, nh_memb_exp_count, nh_oid_map, nhgid, bucket_size) # Remove route # remove prefix entry asic_rt_key = get_asic_route_key(asic_db, fg_nhg_prefix) ps._del(fg_nhg_prefix) asic_db.wait_for_deleted_entry(ASIC_ROUTE_TB, asic_rt_key) asic_db.wait_for_n_keys(ASIC_NHG_MEMB, 0) remove_entry(config_db, "FG_NHG_PREFIX", fg_nhg_prefix)
def how_many_entries_exist(db, table): tbl = swsscommon.Table(db, table) return len(tbl.getKeys())
def entries(db, table): tbl = swsscommon.Table(db, table) return set(tbl.getKeys())
def remove_mirror_acl_rule(self, table, rule): tbl = swsscommon.Table(self.cdb, "ACL_RULE") tbl._del(table + "|" + rule) time.sleep(1)
def create_port_channel(self, dvs, alias): tbl = swsscommon.Table(self.cdb, "PORTCHANNEL") fvs = swsscommon.FieldValuePairs([("admin_status", "up"), ("mtu", "9100")]) tbl.set(alias, fvs) time.sleep(1)
def setup_mirrorv6_mode(self, mode): tbl = swsscommon.Table(self.sdb, "SWITCH_CAPABILITY") fvs = swsscommon.FieldValuePairs([("mirror_v6_table_mode", mode)]) tbl.set("switch", fvs) time.sleep(1)
def remove_port_channel(self, dvs, alias): tbl = swsscommon.Table(self.cdb, "PORTCHANNEL") tbl._del(alias) time.sleep(1)
def remove_mirror_session(self, name): tbl = swsscommon.Table(self.cdb, "MIRROR_SESSION") tbl._del(name) time.sleep(1)
def create_entry_tbl(self, db, table, key, pairs): tbl = swsscommon.Table(db, table) self.create_entry(tbl, key, pairs)