def test_fgnhg_more_nhs_nondiv_bucket_size(self, dvs, testlog): ''' Test Fine Grained ECMP with a greater number of FG members and bigger bucket size, such that the no. of nhs are not divisible by bucket size. Use a different physical interface type for dynamicitiy. ''' app_db = dvs.get_app_db() asic_db = dvs.get_asic_db() config_db = dvs.get_config_db() state_db = dvs.get_state_db() fg_nhg_name = "fgnhg_v4" fg_nhg_prefix = "3.3.3.0/24" # Test with non-divisible bucket size bucket_size = 128 NUM_NHs = 10 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) asic_nh_count = len(asic_db.get_keys(ASIC_NH_TB)) ip_to_if_map = create_interface_n_fg_ecmp_config( dvs, 0, NUM_NHs, fg_nhg_name) asic_db.wait_for_n_keys(ASIC_NH_TB, asic_nh_count + NUM_NHs) # Program the route ps = swsscommon.ProducerStateTable(app_db.db_connection, 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 asic_db.wait_for_n_keys(ASIC_NHG_MEMB, bucket_size) nhgid = validate_asic_nhg_fine_grained_ecmp(asic_db, fg_nhg_prefix, bucket_size) nh_oid_map = get_nh_oid_map(asic_db) # The route had been created 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, fg_nhg_prefix, 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) asic_db.wait_for_n_keys(ASIC_NHG, 0) # cleanup all config remove_interface_n_fg_ecmp_config(dvs, 0, NUM_NHs, fg_nhg_name) remove_entry(config_db, FG_NHG_PREFIX, fg_nhg_prefix)
def create_entry(tbl, key, pairs): fvs = swsscommon.FieldValuePairs(pairs) tbl.set(key, fvs) # FIXME: better to wait until DB create them time.sleep(1)
def create_acl_table(self, dvs, table_name, ports): tbl = swsscommon.Table(self.cdb, "ACL_TABLE") fvs = swsscommon.FieldValuePairs([("POLICY_DESC", "LAG_ACL_TEST"), ("TYPE", "L3"), ("PORTS", ports)]) tbl.set(table_name, fvs) time.sleep(1)
def test_V6AclRuleL4DstPortRange(self, dvs, testlog): """ hmset ACL_RULE|test-aclv6|test_rule10 priority 1010 PACKET_ACTION DROP L4_DST_PORT_RANGE 101-200 """ self.setup_db(dvs) db = swsscommon.DBConnector(4, dvs.redis_sock, 0) adb = swsscommon.DBConnector(1, dvs.redis_sock, 0) # create acl rule tbl = swsscommon.Table(db, "ACL_RULE") fvs = swsscommon.FieldValuePairs([("priority", "1010"), ("PACKET_ACTION", "DROP"), ("L4_DST_PORT_RANGE", "101-200")]) tbl.set("test-aclv6|test_rule10", fvs) time.sleep(1) test_acl_table_id = self.get_acl_table_id(dvs) # check acl table in asic db atbl = swsscommon.Table(adb, "ASIC_STATE:SAI_OBJECT_TYPE_ACL_ENTRY") keys = atbl.getKeys() acl_entry = [ k for k in keys if k not in dvs.asicdb.default_acl_entries ] assert len(acl_entry) == 1 (status, fvs) = atbl.get(acl_entry[0]) assert status == True assert len(fvs) == 6 for fv in fvs: if fv[0] == "SAI_ACL_ENTRY_ATTR_TABLE_ID": assert fv[1] == test_acl_table_id elif fv[0] == "SAI_ACL_ENTRY_ATTR_ADMIN_STATE": assert fv[1] == "true" elif fv[0] == "SAI_ACL_ENTRY_ATTR_PRIORITY": assert fv[1] == "1010" elif fv[0] == "SAI_ACL_ENTRY_ATTR_ACTION_COUNTER": assert True elif fv[0] == "SAI_ACL_ENTRY_ATTR_FIELD_ACL_RANGE_TYPE": aclrange = fv[1] elif fv[0] == "SAI_ACL_ENTRY_ATTR_ACTION_PACKET_ACTION": assert fv[1] == "SAI_PACKET_ACTION_DROP" else: assert False atbl = swsscommon.Table(adb, "ASIC_STATE:SAI_OBJECT_TYPE_ACL_RANGE") aclrange_obj = aclrange.split(":", 1)[1] (status, fvs) = atbl.get(aclrange_obj) assert status == True assert len(fvs) == 2 for fv in fvs: if fv[0] == "SAI_ACL_RANGE_ATTR_TYPE": assert fv[1] == "SAI_ACL_RANGE_TYPE_L4_DST_PORT_RANGE" elif fv[0] == "SAI_ACL_RANGE_ATTR_LIMIT": assert fv[1] == "101,200" else: assert False # remove acl rule tbl._del("test-aclv6|test_rule10") time.sleep(1) (status, fvs) = atbl.get(acl_entry[0]) assert status == False
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 test_InsertAclRuleBetweenPriorities(self, dvs, testlog): self.setup_db(dvs) db = swsscommon.DBConnector(4, dvs.redis_sock, 0) adb = swsscommon.DBConnector(1, dvs.redis_sock, 0) bind_ports = ["Ethernet0", "Ethernet4"] # create ACL_TABLE in config db tbl = swsscommon.Table(db, "ACL_TABLE") fvs = swsscommon.FieldValuePairs([("policy_desc", "test"), ("type", "L3"), ("ports", ",".join(bind_ports))]) tbl.set("test_insert", fvs) time.sleep(2) num_rules = 0 #create ACL rules tbl = swsscommon.Table(db, "ACL_RULE") rules = [[("PRIORITY", "10"), ("PACKET_ACTION", "DROP"), ("SRC_IP", "10.0.0.0/32")], [("PRIORITY", "20"), ("PACKET_ACTION", "DROP"), ("DST_IP", "104.44.94.0/23")], [("PRIORITY", "30"), ("PACKET_ACTION", "DROP"), ("DST_IP", "192.168.0.16/32")], [("PRIORITY", "40"), ("PACKET_ACTION", "FORWARD"), ("DST_IP", "100.64.0.0/10")]] #used to verify how ACL rules are programmed in ASICDB verifs = [{ 'SAI_ACL_ENTRY_ATTR_PRIORITY': '10', 'SAI_ACL_ENTRY_ATTR_FIELD_SRC_IP': '10.0.0.0&mask:255.255.255.255', 'SAI_ACL_ENTRY_ATTR_ACTION_PACKET_ACTION': 'SAI_PACKET_ACTION_DROP' }, { 'SAI_ACL_ENTRY_ATTR_PRIORITY': '20', 'SAI_ACL_ENTRY_ATTR_FIELD_DST_IP': '104.44.94.0&mask:255.255.254.0', 'SAI_ACL_ENTRY_ATTR_ACTION_PACKET_ACTION': 'SAI_PACKET_ACTION_DROP' }, { 'SAI_ACL_ENTRY_ATTR_PRIORITY': '30', 'SAI_ACL_ENTRY_ATTR_FIELD_DST_IP': '192.168.0.16&mask:255.255.255.255', 'SAI_ACL_ENTRY_ATTR_ACTION_PACKET_ACTION': 'SAI_PACKET_ACTION_DROP' }, { 'SAI_ACL_ENTRY_ATTR_PRIORITY': '40', 'SAI_ACL_ENTRY_ATTR_FIELD_DST_IP': '100.64.0.0&mask:255.192.0.0', 'SAI_ACL_ENTRY_ATTR_ACTION_PACKET_ACTION': 'SAI_PACKET_ACTION_FORWARD' }] #insert rules for rule in rules: fvs = swsscommon.FieldValuePairs(rule) num_rules += 1 tbl.set("test_insert|acl_test_rule%s" % num_rules, fvs) time.sleep(1) atbl = swsscommon.Table(adb, "ASIC_STATE:SAI_OBJECT_TYPE_ACL_ENTRY") keys = atbl.getKeys() #assert that first set of rules are programmed acl_entry = [ k for k in keys if k not in dvs.asicdb.default_acl_entries ] assert len(acl_entry) == num_rules #insert new rule with odd priority tbl = swsscommon.Table(db, "ACL_RULE") insertrule = [("PRIORITY", "21"), ("PACKET_ACTION", "DROP"), ("ETHER_TYPE", "4660")] #create verification for that rule verifs.append({ 'SAI_ACL_ENTRY_ATTR_PRIORITY': '21', 'SAI_ACL_ENTRY_ATTR_FIELD_ETHER_TYPE': '4660&mask:0xffff', 'SAI_ACL_ENTRY_ATTR_ACTION_PACKET_ACTION': 'SAI_PACKET_ACTION_DROP' }) rules.append(insertrule) fvs = swsscommon.FieldValuePairs(insertrule) num_rules += 1 tbl.set("test_insert|acl_test_rule%s" % num_rules, fvs) time.sleep(1) #assert all rules are programmed keys = atbl.getKeys() acl_entry = [ k for k in keys if k not in dvs.asicdb.default_acl_entries ] assert len(acl_entry) == num_rules #match each entry to its corresponding verification matched_rules = 0 for entry in acl_entry: (status, fvs) = atbl.get(entry) assert status == True assert len(fvs) == 6 #helper function if self.check_rule_existence(dict(fvs), rules, verifs): matched_rules += 1 assert num_rules == matched_rules #cleanup while num_rules > 0: tbl._del("test_insert|acl_test_rule%s" % num_rules) num_rules -= 1 time.sleep(1) (status, fvs) = atbl.get(acl_entry[0]) assert status == False tbl = swsscommon.Table(db, "ACL_TABLE") tbl._del("test_insert") time.sleep(1) atbl = swsscommon.Table(adb, "ASIC_STATE:SAI_OBJECT_TYPE_ACL_TABLE") keys = atbl.getKeys() # only the default table was left assert len(keys) >= 1
def test_AclRuleInOutPorts(self, dvs, testlog): """ hmset ACL_RULE|test|acl_test_rule priority 55 PACKET_ACTION FORWARD IN_PORTS Ethernet0,Ethernet4 OUT_PORTS Ethernet8,Ethernet12 """ self.setup_db(dvs) db = swsscommon.DBConnector(4, dvs.redis_sock, 0) adb = swsscommon.DBConnector(1, dvs.redis_sock, 0) # create acl rule tbl = swsscommon.Table(db, "ACL_RULE") fvs = swsscommon.FieldValuePairs([("priority", "55"), ("PACKET_ACTION", "FORWARD"), ("IN_PORTS", "Ethernet0,Ethernet4"), ("OUT_PORTS", "Ethernet8,Ethernet12") ]) tbl.set("test|acl_test_rule", fvs) time.sleep(1) test_acl_table_id = self.get_acl_table_id(dvs) # check acl table in asic db atbl = swsscommon.Table(adb, "ASIC_STATE:SAI_OBJECT_TYPE_ACL_ENTRY") keys = atbl.getKeys() acl_entry = [ k for k in keys if k not in dvs.asicdb.default_acl_entries ] assert len(acl_entry) == 1 (status, fvs) = atbl.get(acl_entry[0]) assert status == True assert len(fvs) == 7 for fv in fvs: if fv[0] == "SAI_ACL_ENTRY_ATTR_TABLE_ID": assert fv[1] == test_acl_table_id elif fv[0] == "SAI_ACL_ENTRY_ATTR_ADMIN_STATE": assert fv[1] == "true" elif fv[0] == "SAI_ACL_ENTRY_ATTR_PRIORITY": assert fv[1] == "55" elif fv[0] == "SAI_ACL_ENTRY_ATTR_ACTION_COUNTER": assert True elif fv[0] == "SAI_ACL_ENTRY_ATTR_FIELD_IN_PORTS": assert fv[1].startswith("2:") assert dvs.asicdb.portnamemap["Ethernet0"] in fv[1] assert dvs.asicdb.portnamemap["Ethernet4"] in fv[1] elif fv[0] == "SAI_ACL_ENTRY_ATTR_FIELD_OUT_PORTS": assert fv[1].startswith("2:") assert dvs.asicdb.portnamemap["Ethernet8"] in fv[1] assert dvs.asicdb.portnamemap["Ethernet12"] in fv[1] elif fv[0] == "SAI_ACL_ENTRY_ATTR_ACTION_PACKET_ACTION": assert fv[1] == "SAI_PACKET_ACTION_FORWARD" else: assert False # remove acl rule tbl._del("test|acl_test_rule") time.sleep(1) (status, fvs) = atbl.get(acl_entry[0]) assert status == False
def test_CrmIpv6Neighbor(self, dvs, testlog): # Enable IPv6 routing dvs.runcmd("sysctl net.ipv6.conf.all.disable_ipv6=0") time.sleep(2) 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("Ethernet0|fc00::1/126", fvs) dvs.runcmd("config interface startup Ethernet0") dvs.runcmd("crm config polling interval 1") dvs.setReadOnlyAttr('SAI_OBJECT_TYPE_SWITCH', 'SAI_SWITCH_ATTR_AVAILABLE_IPV6_NEIGHBOR_ENTRY', '1000') time.sleep(2) # get counters used_counter = getCrmCounterValue(dvs, 'STATS', 'crm_stats_ipv6_neighbor_used') avail_counter = getCrmCounterValue( dvs, 'STATS', 'crm_stats_ipv6_neighbor_available') # add neighbor and update available counter dvs.runcmd( "ip -6 neigh replace fc00::2 lladdr 11:22:33:44:55:66 dev Ethernet0" ) dvs.setReadOnlyAttr('SAI_OBJECT_TYPE_SWITCH', 'SAI_SWITCH_ATTR_AVAILABLE_IPV6_NEIGHBOR_ENTRY', '999') time.sleep(2) # get counters new_used_counter = getCrmCounterValue(dvs, 'STATS', 'crm_stats_ipv6_neighbor_used') new_avail_counter = getCrmCounterValue( dvs, 'STATS', 'crm_stats_ipv6_neighbor_available') assert new_used_counter - used_counter == 1 assert avail_counter - new_avail_counter == 1 # remove neighbor and update available counter dvs.runcmd( "ip -6 neigh del fc00::2 lladdr 11:22:33:44:55:66 dev Ethernet0") dvs.setReadOnlyAttr('SAI_OBJECT_TYPE_SWITCH', 'SAI_SWITCH_ATTR_AVAILABLE_IPV6_NEIGHBOR_ENTRY', '1000') time.sleep(2) # get counters new_used_counter = getCrmCounterValue(dvs, 'STATS', 'crm_stats_ipv6_neighbor_used') new_avail_counter = getCrmCounterValue( dvs, 'STATS', 'crm_stats_ipv6_neighbor_available') assert new_used_counter == used_counter assert new_avail_counter == avail_counter marker = dvs.add_log_marker() dvs.runcmd("crm config polling interval 2") dvs.runcmd("crm config thresholds ipv6 neighbor high 90") dvs.runcmd("crm config thresholds ipv6 neighbor type free") time.sleep(2) check_syslog(dvs, marker, "IPV6_NEIGHBOR THRESHOLD_EXCEEDED for TH_FREE", 1) intf_tbl._del("Ethernet0|fc00::1/126") time.sleep(2)
def test_CrmFdbEntry(self, dvs, testlog): # disable ipv6 on Ethernet8 neighbor as once ipv6 link-local address is # configured, server 2 will send packet which can switch to learn another # mac and fail the test. dvs.servers[2].runcmd("sysctl -w net.ipv6.conf.eth0.disable_ipv6=1") dvs.runcmd("crm config polling interval 1") dvs.setReadOnlyAttr('SAI_OBJECT_TYPE_SWITCH', 'SAI_SWITCH_ATTR_AVAILABLE_FDB_ENTRY', '1000') time.sleep(2) # get counters used_counter = getCrmCounterValue(dvs, 'STATS', 'crm_stats_fdb_entry_used') avail_counter = getCrmCounterValue(dvs, 'STATS', 'crm_stats_fdb_entry_available') app_db = swsscommon.DBConnector(swsscommon.APPL_DB, dvs.redis_sock, 0) cfg_db = swsscommon.DBConnector(swsscommon.CONFIG_DB, dvs.redis_sock, 0) # create a FDB entry tbl = swsscommon.ProducerStateTable(app_db, "FDB_TABLE") fvs = swsscommon.FieldValuePairs([("port", "Ethernet8"), ("type", "dynamic")]) tbl.set("Vlan2:52-54-00-25-06-E9", fvs) # create vlan tbl = swsscommon.Table(cfg_db, "VLAN") fvs = swsscommon.FieldValuePairs([("vlanid", "2")]) tbl.set("Vlan2", fvs) # create vlan member tbl = swsscommon.Table(cfg_db, "VLAN_MEMBER") fvs = swsscommon.FieldValuePairs([("tagging_mode", "untagged")]) tbl.set("Vlan2|Ethernet8", fvs) # update available counter dvs.setReadOnlyAttr('SAI_OBJECT_TYPE_SWITCH', 'SAI_SWITCH_ATTR_AVAILABLE_FDB_ENTRY', '999') time.sleep(2) # get counters new_used_counter = getCrmCounterValue(dvs, 'STATS', 'crm_stats_fdb_entry_used') new_avail_counter = getCrmCounterValue( dvs, 'STATS', 'crm_stats_fdb_entry_available') assert new_used_counter - used_counter == 1 assert avail_counter - new_avail_counter == 1 # update available counter dvs.setReadOnlyAttr('SAI_OBJECT_TYPE_SWITCH', 'SAI_SWITCH_ATTR_AVAILABLE_FDB_ENTRY', '1000') time.sleep(2) # get counters new_avail_counter = getCrmCounterValue( dvs, 'STATS', 'crm_stats_fdb_entry_available') assert new_avail_counter == avail_counter marker = dvs.add_log_marker() dvs.runcmd("crm config polling interval 2") dvs.runcmd("crm config thresholds fdb high 90") dvs.runcmd("crm config thresholds fdb type free") time.sleep(2) check_syslog(dvs, marker, "FDB_ENTRY THRESHOLD_EXCEEDED for TH_FREE", 1) # enable ipv6 on server 2 dvs.servers[2].runcmd("sysctl -w net.ipv6.conf.eth0.disable_ipv6=0")
def test_CrmIpv6Route(self, dvs, testlog): # Enable IPv6 routing dvs.runcmd("sysctl net.ipv6.conf.all.disable_ipv6=0") time.sleep(2) 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("Ethernet0|fc00::1/126", fvs) dvs.runcmd("config interface startup Ethernet0") dvs.servers[0].runcmd("ifconfig eth0 inet6 add fc00::2/126") dvs.servers[0].runcmd("ip -6 route add default via fc00::1") dvs.runcmd("crm config polling interval 1") dvs.setReadOnlyAttr('SAI_OBJECT_TYPE_SWITCH', 'SAI_SWITCH_ATTR_AVAILABLE_IPV6_ROUTE_ENTRY', '1000') # get neighbor and arp entry dvs.servers[0].runcmd("ping6 -c 4 fc00::1") db = swsscommon.DBConnector(0, dvs.redis_sock, 0) ps = swsscommon.ProducerStateTable(db, "ROUTE_TABLE") fvs = swsscommon.FieldValuePairs([("nexthop", "fc00::2"), ("ifname", "Ethernet0")]) time.sleep(2) # get counters used_counter = getCrmCounterValue(dvs, 'STATS', 'crm_stats_ipv6_route_used') avail_counter = getCrmCounterValue(dvs, 'STATS', 'crm_stats_ipv6_route_available') # add route and update available counter ps.set("2001::/64", fvs) dvs.setReadOnlyAttr('SAI_OBJECT_TYPE_SWITCH', 'SAI_SWITCH_ATTR_AVAILABLE_IPV6_ROUTE_ENTRY', '999') time.sleep(2) # get counters new_used_counter = getCrmCounterValue(dvs, 'STATS', 'crm_stats_ipv6_route_used') new_avail_counter = getCrmCounterValue( dvs, 'STATS', 'crm_stats_ipv6_route_available') assert new_used_counter - used_counter == 1 assert avail_counter - new_avail_counter == 1 # remove route and update available counter ps._del("2001::/64") dvs.runcmd( "ip -6 neigh del fc00::2 lladdr 11:22:33:44:55:66 dev Ethernet0") dvs.setReadOnlyAttr('SAI_OBJECT_TYPE_SWITCH', 'SAI_SWITCH_ATTR_AVAILABLE_IPV6_ROUTE_ENTRY', '1000') time.sleep(2) # get counters new_used_counter = getCrmCounterValue(dvs, 'STATS', 'crm_stats_ipv6_route_used') new_avail_counter = getCrmCounterValue( dvs, 'STATS', 'crm_stats_ipv6_route_available') assert new_used_counter == used_counter assert new_avail_counter == avail_counter marker = dvs.add_log_marker() dvs.runcmd("crm config polling interval 2") dvs.runcmd("crm config thresholds ipv6 route high 90") dvs.runcmd("crm config thresholds ipv6 route type free") time.sleep(2) check_syslog(dvs, marker, "IPV6_ROUTE THRESHOLD_EXCEEDED for TH_FREE", 1) intf_tbl._del("Ethernet0|fc00::1/126") time.sleep(2)
def test_CrmIpv4Nexthop(self, 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|10.0.0.0/31", fvs) intf_tbl.set("Ethernet0", fvs) dvs.runcmd("config interface startup Ethernet0") dvs.runcmd("crm config polling interval 1") dvs.setReadOnlyAttr('SAI_OBJECT_TYPE_SWITCH', 'SAI_SWITCH_ATTR_AVAILABLE_IPV4_NEXTHOP_ENTRY', '1000') time.sleep(2) # get counters used_counter = getCrmCounterValue(dvs, 'STATS', 'crm_stats_ipv4_nexthop_used') avail_counter = getCrmCounterValue(dvs, 'STATS', 'crm_stats_ipv4_nexthop_available') # add nexthop and update available counter dvs.runcmd( "ip neigh replace 10.0.0.1 lladdr 11:22:33:44:55:66 dev Ethernet0") dvs.setReadOnlyAttr('SAI_OBJECT_TYPE_SWITCH', 'SAI_SWITCH_ATTR_AVAILABLE_IPV4_NEXTHOP_ENTRY', '999') time.sleep(2) # get counters new_used_counter = getCrmCounterValue(dvs, 'STATS', 'crm_stats_ipv4_nexthop_used') new_avail_counter = getCrmCounterValue( dvs, 'STATS', 'crm_stats_ipv4_nexthop_available') assert new_used_counter - used_counter == 1 assert avail_counter - new_avail_counter == 1 # remove nexthop and update available counter dvs.runcmd( "ip neigh del 10.0.0.1 lladdr 11:22:33:44:55:66 dev Ethernet0") dvs.setReadOnlyAttr('SAI_OBJECT_TYPE_SWITCH', 'SAI_SWITCH_ATTR_AVAILABLE_IPV4_NEXTHOP_ENTRY', '1000') time.sleep(2) # get counters new_used_counter = getCrmCounterValue(dvs, 'STATS', 'crm_stats_ipv4_nexthop_used') new_avail_counter = getCrmCounterValue( dvs, 'STATS', 'crm_stats_ipv4_nexthop_available') assert new_used_counter == used_counter assert new_avail_counter == avail_counter marker = dvs.add_log_marker() dvs.runcmd("crm config polling interval 2") dvs.runcmd("crm config thresholds ipv4 nexthop high 90") dvs.runcmd("crm config thresholds ipv4 nexthop type free") time.sleep(2) check_syslog(dvs, marker, "IPV4_NEXTHOP THRESHOLD_EXCEEDED for TH_FREE", 1) intf_tbl._del("Ethernet0|10.0.0.0/31") time.sleep(2)
def set_statedb_nat_restore_done(): statedb = swsscommon.DBConnector("STATE_DB", 0) tbl = swsscommon.Table(statedb, "NAT_RESTORE_TABLE") fvs = swsscommon.FieldValuePairs([("restored", "true")]) tbl.set("Flags", fvs) return
def test_route_nhg(self, dvs, testlog): config_db = dvs.get_config_db() fvs = {"NULL": "NULL"} config_db.create_entry("INTERFACE", "Ethernet0", fvs) config_db.create_entry("INTERFACE", "Ethernet4", fvs) config_db.create_entry("INTERFACE", "Ethernet8", fvs) config_db.create_entry("INTERFACE", "Ethernet0|10.0.0.0/31", fvs) config_db.create_entry("INTERFACE", "Ethernet4|10.0.0.2/31", fvs) config_db.create_entry("INTERFACE", "Ethernet8|10.0.0.4/31", fvs) dvs.runcmd("config interface startup Ethernet0") dvs.runcmd("config interface startup Ethernet4") dvs.runcmd("config interface startup Ethernet8") 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") assert dvs.servers[0].runcmd("ip link set down dev eth0") == 0 assert dvs.servers[1].runcmd("ip link set down dev eth0") == 0 assert dvs.servers[2].runcmd("ip link set down dev eth0") == 0 assert dvs.servers[0].runcmd("ip link set up dev eth0") == 0 assert dvs.servers[1].runcmd("ip link set up dev eth0") == 0 assert dvs.servers[2].runcmd("ip link set up dev eth0") == 0 app_db = dvs.get_app_db() ps = swsscommon.ProducerStateTable(app_db.db_connection, "ROUTE_TABLE") asic_db = dvs.get_asic_db() asic_routes_count = len( asic_db.get_keys("ASIC_STATE:SAI_OBJECT_TYPE_ROUTE_ENTRY")) 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) # check if route was propagated to ASIC DB asic_db.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_ROUTE_ENTRY", asic_routes_count + 1) keys = asic_db.get_keys("ASIC_STATE:SAI_OBJECT_TYPE_ROUTE_ENTRY") 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 fvs = asic_db.get_entry("ASIC_STATE:SAI_OBJECT_TYPE_ROUTE_ENTRY", k) nhgid = fvs["SAI_ROUTE_ENTRY_ATTR_NEXT_HOP_ID"] fvs = asic_db.get_entry("ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP_GROUP", nhgid) assert bool(fvs) keys = asic_db.get_keys( "ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP_GROUP_MEMBER") assert len(keys) == 3 for k in keys: fvs = asic_db.get_entry( "ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP_GROUP_MEMBER", k) assert fvs[ "SAI_NEXT_HOP_GROUP_MEMBER_ATTR_NEXT_HOP_GROUP_ID"] == 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) fvs = app_db.get_entry("PORT_TABLE", "Ethernet%d" % (i * 4)) assert bool(fvs) assert fvs["oper_status"] == "down" keys = asic_db.get_keys( "ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP_GROUP_MEMBER") 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) fvs = app_db.get_entry("PORT_TABLE", "Ethernet%d" % (i * 4)) assert bool(fvs) assert fvs["oper_status"] == "up" keys = asic_db.get_keys( "ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP_GROUP_MEMBER") assert len(keys) == i + 1 for k in keys: fvs = asic_db.get_entry( "ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP_GROUP_MEMBER", k) assert fvs[ "SAI_NEXT_HOP_GROUP_MEMBER_ATTR_NEXT_HOP_GROUP_ID"] == nhgid # Remove route 2.2.2.0/24 ps._del("2.2.2.0/24") # Wait for route 2.2.2.0/24 to be removed asic_db.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_ROUTE_ENTRY", asic_routes_count)
def test_fgnhg_matchmode_nexthop_multi_route(self, dvs, testlog): ''' Test route/nh transitions to/from Fine Grained ECMP and Regular ECMP. Create multiple prefixes pointing to the Fine Grained nhs and ensure fine grained ECMP ASIC objects were created for this scenario as expected. ''' 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"} fg_nhg_name = "fgnhg_v4" fg_nhg_prefix = "3.3.3.0/24" # Test with non-divisible bucket size bucket_size = 128 NUM_NHs = 4 NUM_NHs_non_fgnhg = 2 nh_oid_map = {} # Initialize base config fvs = {"bucket_size": str(bucket_size), "match_mode": "nexthop-based"} create_entry(config_db, FG_NHG, fg_nhg_name, fvs) asic_nh_count = len(asic_db.get_keys(ASIC_NH_TB)) ip_to_if_map = create_interface_n_fg_ecmp_config( dvs, 0, NUM_NHs, fg_nhg_name) # Create 2 more interface + IPs for non-fine grained ECMP validation for i in range(NUM_NHs, NUM_NHs + NUM_NHs_non_fgnhg): 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) dvs.runcmd("arp -s 10.0.0." + str(1 + i * 2) + " 00:00:00:00:00:" + str(1 + i * 2)) asic_db.wait_for_n_keys(ASIC_NH_TB, asic_nh_count + NUM_NHs + NUM_NHs_non_fgnhg) # Program the route ps = swsscommon.ProducerStateTable(app_db.db_connection, ROUTE_TB) fvs = swsscommon.FieldValuePairs([("nexthop", "10.0.0.1,10.0.0.5"), ("ifname", "Ethernet0,Ethernet8")]) ps.set(fg_nhg_prefix, fvs) # Validate that the correct ASIC DB elements were setup per Fine Grained ECMP asic_db.wait_for_n_keys(ASIC_NHG_MEMB, bucket_size) nhgid = validate_asic_nhg_fine_grained_ecmp(asic_db, fg_nhg_prefix, bucket_size) nh_oid_map = get_nh_oid_map(asic_db) # The route had been created with 0 members in bank nh_memb_exp_count = {"10.0.0.1": 64, "10.0.0.5": 64} validate_fine_grained_asic_n_state_db_entries( asic_db, state_db, ip_to_if_map, fg_nhg_prefix, nh_memb_exp_count, nh_oid_map, nhgid, bucket_size) # Add a 2nd prefix associated with the same set of next-hops fg_nhg_prefix_2 = "5.5.5.0/16" fvs = swsscommon.FieldValuePairs([("nexthop", "10.0.0.1,10.0.0.5"), ("ifname", "Ethernet0,Ethernet8")]) ps.set(fg_nhg_prefix_2, fvs) asic_db.wait_for_n_keys(ASIC_NHG_MEMB, bucket_size * 2) nhgid_2 = validate_asic_nhg_fine_grained_ecmp(asic_db, fg_nhg_prefix_2, bucket_size) nh_memb_exp_count = {"10.0.0.1": 64, "10.0.0.5": 64} validate_fine_grained_asic_n_state_db_entries( asic_db, state_db, ip_to_if_map, fg_nhg_prefix_2, nh_memb_exp_count, nh_oid_map, nhgid_2, bucket_size) # Add a 3rd prefix with a next-hop(10.0.0.9) not defined for FG ECMP # Should end up as regular ECMP fg_nhg_prefix_3 = "6.6.6.0/16" fvs = swsscommon.FieldValuePairs([ ("nexthop", "10.0.0.1,10.0.0.5,10.0.0.9"), ("ifname", "Ethernet0,Ethernet8,Ethernet16") ]) ps.set(fg_nhg_prefix_3, fvs) validate_asic_nhg_regular_ecmp(asic_db, fg_nhg_prefix_3) asic_db.wait_for_n_keys(ASIC_NHG_MEMB, bucket_size * 2 + 3) # Remove the 10.0.0.9 next-hop, it should now transition to Fine Grained ECMP fvs = swsscommon.FieldValuePairs([("nexthop", "10.0.0.1,10.0.0.5"), ("ifname", "Ethernet0,Ethernet8")]) ps.set(fg_nhg_prefix_3, fvs) nhgid_3 = validate_asic_nhg_fine_grained_ecmp(asic_db, fg_nhg_prefix_3, bucket_size) asic_db.wait_for_n_keys(ASIC_NHG_MEMB, bucket_size * 3) nh_memb_exp_count = {"10.0.0.1": 64, "10.0.0.5": 64} validate_fine_grained_asic_n_state_db_entries( asic_db, state_db, ip_to_if_map, fg_nhg_prefix_3, nh_memb_exp_count, nh_oid_map, nhgid_3, bucket_size) # Add the 10.0.0.9 next-hop again, it should transition back to regular ECMP fvs = swsscommon.FieldValuePairs([ ("nexthop", "10.0.0.1,10.0.0.5,10.0.0.9"), ("ifname", "Ethernet0,Ethernet8,Ethernet16") ]) ps.set(fg_nhg_prefix_3, fvs) validate_asic_nhg_regular_ecmp(asic_db, fg_nhg_prefix_3) asic_db.wait_for_n_keys(ASIC_NHG_MEMB, bucket_size * 2 + 3) # Delete the prefix asic_rt_key = get_asic_route_key(asic_db, fg_nhg_prefix_3) ps._del(fg_nhg_prefix_3) asic_db.wait_for_deleted_entry(ASIC_ROUTE_TB, asic_rt_key) asic_db.wait_for_n_keys(ASIC_NHG_MEMB, bucket_size * 2) # Change FG nhs for one route, ensure that the other route nh is unaffected nh_memb_exp_count = { "10.0.0.1": 32, "10.0.0.3": 32, "10.0.0.5": 32, "10.0.0.7": 32 } 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) nh_memb_exp_count = {"10.0.0.1": 64, "10.0.0.5": 64} validate_fine_grained_asic_n_state_db_entries( asic_db, state_db, ip_to_if_map, fg_nhg_prefix_2, nh_memb_exp_count, nh_oid_map, nhgid_2, 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, bucket_size) # Ensure that 2nd route is still here and then delete it nh_memb_exp_count = {"10.0.0.1": 64, "10.0.0.5": 64} validate_fine_grained_asic_n_state_db_entries( asic_db, state_db, ip_to_if_map, fg_nhg_prefix_2, nh_memb_exp_count, nh_oid_map, nhgid_2, bucket_size) # Delete the 2nd route as well asic_rt_key = get_asic_route_key(asic_db, fg_nhg_prefix_2) ps._del(fg_nhg_prefix_2) asic_db.wait_for_deleted_entry(ASIC_ROUTE_TB, asic_rt_key) asic_db.wait_for_n_keys(ASIC_NHG_MEMB, 0) asic_db.wait_for_n_keys(ASIC_NHG, 0) # cleanup all entries remove_interface_n_fg_ecmp_config(dvs, 0, NUM_NHs + NUM_NHs_non_fgnhg, fg_nhg_name)
def test_evpnFdb(dvs, testlog): vxlan_obj = VxlanTunnel() helper = VxlanEvpnHelper() dvs.setup_db() dvs.clear_fdb() time.sleep(2) #Find switch_id switch_id = dvs.getSwitchOid() print("Switch_id=" + str(switch_id)) vlan_before = helper.how_many_entries_exist( dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_VLAN") # create vlan print("Creating Vlan3") dvs.create_vlan("3") time.sleep(2) vlan_after = helper.how_many_entries_exist( dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_VLAN") assert vlan_after - vlan_before == 1, "The Vlan3 wasn't created" print("Vlan3 is created") # Find the vlan_oid to be used in DB communications vlan_oid_3 = dvs.getVlanOid("3") assert vlan_oid_3 is not None, "Could not find Vlan_oid" print("Vlan-3 vlan_oid=" + str(vlan_oid_3)) bp_before = helper.how_many_entries_exist( dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_BRIDGE_PORT") vm_before = helper.how_many_entries_exist( dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_VLAN_MEMBER") print("Making Ethernet0 as a member of Vlan3") dvs.create_vlan_member("3", "Ethernet0") time.sleep(2) # check that the vlan information was propagated bp_after = helper.how_many_entries_exist( dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_BRIDGE_PORT") vm_after = helper.how_many_entries_exist( dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_VLAN_MEMBER") assert bp_after - bp_before == 1, "The bridge port wasn't created" assert vm_after - vm_before == 1, "The vlan member wasn't added" print("Ethernet0 is a member of Vlan3") # Get mapping between interface name and its bridge port_id iface_2_bridge_port_id = dvs.get_map_iface_bridge_port_id(dvs.adb) #create SIP side of tunnel source_tnl_name = "source_vtep_name" source_tnl_ip = "7.7.7.7" vxlan_obj.create_vxlan_tunnel(dvs, source_tnl_name, source_tnl_ip) time.sleep(1) nvo_name = "evpn_nvo" vxlan_obj.create_evpn_nvo(dvs, nvo_name, source_tnl_name) time.sleep(1) map_name_vlan_3 = "map_3_3" vxlan_obj.create_vxlan_tunnel_map(dvs, source_tnl_name, map_name_vlan_3, "3", "Vlan3") time.sleep(1) remote_ip_6 = "6.6.6.6" vxlan_obj.create_evpn_remote_vni(dvs, "Vlan3", remote_ip_6, "3") remote_ip_8 = "8.8.8.8" vxlan_obj.create_evpn_remote_vni(dvs, "Vlan3", remote_ip_8, "3") time.sleep(1) #UT-1 Evpn Mac add from remote when tunnels are already created mac = "52:54:00:25:06:E9" print("Creating Evpn FDB Vlan3:" + mac.lower() + ":6.6.6.6 in APP-DB") helper.create_entry_pst(dvs.pdb, "VXLAN_FDB_TABLE", "Vlan3:" + mac.lower(), [("remote_vtep", remote_ip_6), ("type", "dynamic"), ("vni", "3")]) time.sleep(1) tnl_bp_oid_6 = get_vxlan_p2p_tunnel_bp(dvs.adb, remote_ip_6) # check that the FDB entry is inserted into ASIC DB ok, extra = dvs.is_fdb_entry_exists( dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_FDB_ENTRY", [("mac", mac), ("bvid", vlan_oid_3)], [ ("SAI_FDB_ENTRY_ATTR_TYPE", "SAI_FDB_ENTRY_TYPE_STATIC"), ("SAI_FDB_ENTRY_ATTR_ALLOW_MAC_MOVE", "true"), ("SAI_FDB_ENTRY_ATTR_ENDPOINT_IP", remote_ip_6), ("SAI_FDB_ENTRY_ATTR_BRIDGE_PORT_ID", str(tnl_bp_oid_6)), ]) assert ok == True, str(extra) print("EVPN FDB Vlan3:" + mac.lower() + ":" + remote_ip_6 + " is created in ASIC-DB") time.sleep(1) #UT-2 Evpn Mac del from remote mac = "52:54:00:25:06:E9" print("Deleting Evpn FDB Vlan3:" + mac.lower() + ":6.6.6.6 in APP-DB") helper.delete_entry_pst(dvs.pdb, "VXLAN_FDB_TABLE", "Vlan3:" + mac.lower()) time.sleep(1) # check that the FDB entry is deleted from ASIC DB ok, extra = dvs.is_fdb_entry_exists( dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_FDB_ENTRY", [("mac", mac), ("bvid", vlan_oid_3)], [ ("SAI_FDB_ENTRY_ATTR_TYPE", "SAI_FDB_ENTRY_TYPE_STATIC"), ("SAI_FDB_ENTRY_ATTR_ALLOW_MAC_MOVE", "true"), ("SAI_FDB_ENTRY_ATTR_ENDPOINT_IP", remote_ip_6), ("SAI_FDB_ENTRY_ATTR_BRIDGE_PORT_ID", str(tnl_bp_oid_6)), ]) assert ok == False, str(extra) print("EVPN FDB Vlan3:" + mac.lower() + ":" + remote_ip_6 + " is deleted from ASIC-DB") time.sleep(1) #UT-3 Evpn Mac add from remote when local mac is already present mac = "52:54:00:25:06:E9" print("Creating Local dynamic FDB Vlan3:" + mac.lower() + ":Ethernet0 in APP-DB") # Create Dynamic MAC entry in APP DB helper.create_entry_pst(dvs.pdb, "FDB_TABLE", "Vlan3:" + mac.lower(), [ ("port", "Ethernet0"), ("type", "dynamic"), ]) time.sleep(1) #raw_input("Check ASIC_DB.........") # check that the FDB entry was added in ASIC DB ok, extra = dvs.is_fdb_entry_exists( dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_FDB_ENTRY", [("mac", mac), ("bvid", vlan_oid_3)], [("SAI_FDB_ENTRY_ATTR_TYPE", "SAI_FDB_ENTRY_TYPE_DYNAMIC"), ("SAI_FDB_ENTRY_ATTR_BRIDGE_PORT_ID", iface_2_bridge_port_id["Ethernet0"])]) assert ok, str(extra) print("Dynamic FDB Vlan3:" + mac.lower() + ":Ethernet0 is created in Asic-DB") # check that the FDB entry was added in STATE DB mac1_found, extra = dvs.is_table_entry_exists(dvs.sdb, "FDB_TABLE", "Vlan3:" + mac.lower(), [ ("port", "Ethernet0"), ("type", "dynamic"), ]) assert mac1_found, str(extra) print("FDB Vlan3:" + mac + ":Ethernet0 is created in STATE-DB") print("Creating Evpn FDB Vlan3:" + mac.lower() + ":6.6.6.6 in APP-DB") helper.create_entry_pst(dvs.pdb, "VXLAN_FDB_TABLE", "Vlan3:" + mac.lower(), [("remote_vtep", remote_ip_6), ("type", "dynamic"), ("vni", "3")]) time.sleep(1) # check that the FDB entry is inserted into ASIC DB ok, extra = dvs.is_fdb_entry_exists( dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_FDB_ENTRY", [("mac", mac), ("bvid", str(dvs.getVlanOid("3")))], [ ("SAI_FDB_ENTRY_ATTR_TYPE", "SAI_FDB_ENTRY_TYPE_STATIC"), ("SAI_FDB_ENTRY_ATTR_ALLOW_MAC_MOVE", "true"), ("SAI_FDB_ENTRY_ATTR_ENDPOINT_IP", remote_ip_6), ("SAI_FDB_ENTRY_ATTR_BRIDGE_PORT_ID", str(tnl_bp_oid_6)), ]) assert ok, str(extra) print("EVPN FDB Vlan3:" + mac.lower() + ":" + remote_ip_6 + " is created in ASIC-DB") # check that the Local FDB entry is deleted from STATE DB mac1_found, extra = dvs.is_table_entry_exists(dvs.sdb, "FDB_TABLE", "Vlan3:" + mac.lower(), [ ("port", "Ethernet0"), ("type", "dynamic"), ]) assert mac1_found == False, str(extra) print("FDB Vlan3:" + mac + ":Ethernet0 is deleted from STATE-DB") time.sleep(1) #UT-4 Evpn Sticky Mac add from remote mac = "52:54:00:25:06:E9" print("Creating Evpn Sticky FDB Vlan3:" + mac.lower() + ":6.6.6.6 in APP-DB") helper.create_entry_pst(dvs.pdb, "VXLAN_FDB_TABLE", "Vlan3:" + mac.lower(), [("remote_vtep", remote_ip_6), ("type", "static"), ("vni", "3")]) time.sleep(1) # check that the FDB entry is inserted into ASIC DB ok, extra = dvs.is_fdb_entry_exists( dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_FDB_ENTRY", [("mac", mac), ("bvid", str(dvs.getVlanOid("3")))], [ ("SAI_FDB_ENTRY_ATTR_TYPE", "SAI_FDB_ENTRY_TYPE_STATIC"), ("SAI_FDB_ENTRY_ATTR_ENDPOINT_IP", remote_ip_6), ("SAI_FDB_ENTRY_ATTR_BRIDGE_PORT_ID", str(tnl_bp_oid_6)), ]) assert ok, str(extra) print("EVPN Sticky FDB Vlan3:" + mac.lower() + ":" + remote_ip_6 + " is created in ASIC-DB") #raw_input("Check ASIC_DB.........") #UT-8 Evpn Mac add from remote when tunnels are already created mac = "52:54:00:25:06:E9" print("Creating Evpn FDB Vlan3:" + mac.lower() + ":6.6.6.6 in APP-DB") helper.create_entry_pst(dvs.pdb, "VXLAN_FDB_TABLE", "Vlan3:" + mac.lower(), [("remote_vtep", remote_ip_6), ("type", "dynamic"), ("vni", "3")]) time.sleep(1) #raw_input("Check ASIC_DB.........") # check that the FDB entry is inserted into ASIC DB ok, extra = dvs.is_fdb_entry_exists( dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_FDB_ENTRY", [("mac", mac), ("bvid", vlan_oid_3)], [ ("SAI_FDB_ENTRY_ATTR_TYPE", "SAI_FDB_ENTRY_TYPE_STATIC"), ("SAI_FDB_ENTRY_ATTR_ALLOW_MAC_MOVE", "true"), ("SAI_FDB_ENTRY_ATTR_ENDPOINT_IP", remote_ip_6), ("SAI_FDB_ENTRY_ATTR_BRIDGE_PORT_ID", str(tnl_bp_oid_6)), ]) assert ok == True, str(extra) print("EVPN FDB Vlan3:" + mac.lower() + ":" + remote_ip_6 + " is created in ASIC-DB") time.sleep(1) tnl_bp_oid_8 = get_vxlan_p2p_tunnel_bp(dvs.adb, remote_ip_8) print("Creating Evpn FDB Vlan3:" + mac.lower() + ":8.8.8.8 in APP-DB") helper.create_entry_pst(dvs.pdb, "VXLAN_FDB_TABLE", "Vlan3:" + mac.lower(), [("remote_vtep", remote_ip_8), ("type", "dynamic"), ("vni", "3")]) time.sleep(1) #raw_input("Check ASIC_DB.........") # check that the FDB entry is inserted into ASIC DB ok, extra = dvs.is_fdb_entry_exists( dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_FDB_ENTRY", [("mac", mac), ("bvid", vlan_oid_3)], [ ("SAI_FDB_ENTRY_ATTR_TYPE", "SAI_FDB_ENTRY_TYPE_STATIC"), ("SAI_FDB_ENTRY_ATTR_ALLOW_MAC_MOVE", "true"), ("SAI_FDB_ENTRY_ATTR_ENDPOINT_IP", remote_ip_8), ("SAI_FDB_ENTRY_ATTR_BRIDGE_PORT_ID", str(tnl_bp_oid_8)), ]) assert ok == True, str(extra) print("EVPN FDB Vlan3:" + mac.lower() + ":" + remote_ip_8 + " is created in ASIC-DB") time.sleep(1) #UT-9 Local mac move (delete and learn) when remote is already added mac = "52:54:00:25:06:E9" print("Deleting FDB Vlan3:52-54-00-25-06-E9:8.8.8.8 in ASIC-DB") helper.delete_entry_tbl( dvs.adb, "ASIC_STATE", "SAI_OBJECT_TYPE_FDB_ENTRY:{\"bvid\":\"" + vlan_oid_3 + "\",\"mac\":\"" + mac + "\",\"switch_id\":\"" + switch_id + "\"}") ntf = swsscommon.NotificationProducer(dvs.adb, "NOTIFICATIONS") fvp = swsscommon.FieldValuePairs() ntf_data = "[{\"fdb_entry\":\"{\\\"bvid\\\":\\\"" + vlan_oid_3 + "\\\",\\\"mac\\\":\\\"" + mac + "\\\",\\\"switch_id\\\":\\\"" + switch_id + "\\\"}\",\"fdb_event\":\"SAI_FDB_EVENT_AGED\",\"list\":[{\"id\":\"SAI_FDB_ENTRY_ATTR_BRIDGE_PORT_ID\",\"value\":\"" + str( tnl_bp_oid_8) + "\"}]}]" ntf.send("fdb_event", ntf_data, fvp) time.sleep(2) #raw_input("Check ASIC_DB.........") print("Creating FDB Vlan3:52-54-00-25-06-E9:Ethernet0 in ASIC-DB") helper.create_entry_tbl( dvs.adb, "ASIC_STATE", "SAI_OBJECT_TYPE_FDB_ENTRY:{\"bvid\":\"" + vlan_oid_3 + "\",\"mac\":\"52:54:00:25:06:E9\",\"switch_id\":\"" + switch_id + "\"}", [ ("SAI_FDB_ENTRY_ATTR_TYPE", "SAI_FDB_ENTRY_TYPE_DYNAMIC"), ("SAI_FDB_ENTRY_ATTR_BRIDGE_PORT_ID", iface_2_bridge_port_id["Ethernet0"]), ]) ntf = swsscommon.NotificationProducer(dvs.adb, "NOTIFICATIONS") fvp = swsscommon.FieldValuePairs() ntf_data = "[{\"fdb_entry\":\"{\\\"bvid\\\":\\\"" + vlan_oid_3 + "\\\",\\\"mac\\\":\\\"52:54:00:25:06:E9\\\",\\\"switch_id\\\":\\\"" + switch_id + "\\\"}\",\"fdb_event\":\"SAI_FDB_EVENT_LEARNED\",\"list\":[{\"id\":\"SAI_FDB_ENTRY_ATTR_BRIDGE_PORT_ID\",\"value\":\"" + iface_2_bridge_port_id[ "Ethernet0"] + "\"}]}]" ntf.send("fdb_event", ntf_data, fvp) time.sleep(2) #raw_input("Check ASIC_DB.........") # check that the FDB entry was added in ASIC DB ok, extra = dvs.is_fdb_entry_exists( dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_FDB_ENTRY", [("mac", "52:54:00:25:06:E9"), ("bvid", vlan_oid_3)], [("SAI_FDB_ENTRY_ATTR_TYPE", "SAI_FDB_ENTRY_TYPE_DYNAMIC"), ("SAI_FDB_ENTRY_ATTR_BRIDGE_PORT_ID", iface_2_bridge_port_id["Ethernet0"])]) assert ok, str(extra) print("FDB Vlan3:52-54-00-25-06-E9:Ethernet0 is created in ASIC-DB") # check that the FDB entry was added in STATE DB mac1_found, extra = dvs.is_table_entry_exists(dvs.sdb, "FDB_TABLE", "Vlan3:52:54:00:25:06:e9", [ ("port", "Ethernet0"), ("type", "dynamic"), ]) assert mac1_found, str(extra) print("FDB Vlan3:52-54-00-25-06-E9:Ethernet0 is created in STATE-DB") dvs.remove_vlan_member("3", "Ethernet0") dvs.remove_vlan("3")
def test_CrmNexthopGroupMember(self, dvs, testlog): # down, then up to generate port up signal dvs.servers[0].runcmd("ip link set down dev eth0") == 0 dvs.servers[1].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 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("Ethernet0|10.0.0.0/31", fvs) intf_tbl.set("Ethernet4|10.0.0.2/31", fvs) dvs.runcmd("config interface startup Ethernet0") dvs.runcmd("config interface startup Ethernet4") dvs.runcmd("crm config polling interval 1") dvs.setReadOnlyAttr( 'SAI_OBJECT_TYPE_SWITCH', 'SAI_SWITCH_ATTR_AVAILABLE_NEXT_HOP_GROUP_MEMBER_ENTRY', '1000') # add neighbors dvs.runcmd( "ip neigh replace 10.0.0.1 lladdr 11:22:33:44:55:66 dev Ethernet0") dvs.runcmd( "ip neigh replace 10.0.0.3 lladdr 11:22:33:44:55:66 dev Ethernet4") 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"), ("ifname", "Ethernet0,Ethernet4")]) time.sleep(2) # get counters used_counter = getCrmCounterValue( dvs, 'STATS', 'crm_stats_nexthop_group_member_used') avail_counter = getCrmCounterValue( dvs, 'STATS', 'crm_stats_nexthop_group_member_available') # add route and update available counter ps.set("2.2.2.0/24", fvs) dvs.setReadOnlyAttr( 'SAI_OBJECT_TYPE_SWITCH', 'SAI_SWITCH_ATTR_AVAILABLE_NEXT_HOP_GROUP_MEMBER_ENTRY', '998') time.sleep(2) # get counters new_used_counter = getCrmCounterValue( dvs, 'STATS', 'crm_stats_nexthop_group_member_used') new_avail_counter = getCrmCounterValue( dvs, 'STATS', 'crm_stats_nexthop_group_member_available') assert new_used_counter - used_counter == 2 assert avail_counter - new_avail_counter == 2 # remove route and update available counter ps._del("2.2.2.0/24") dvs.runcmd( "ip neigh del 10.0.0.1 lladdr 11:22:33:44:55:66 dev Ethernet0") dvs.runcmd( "ip neigh del 10.0.0.3 lladdr 11:22:33:44:55:66 dev Ethernet4") dvs.setReadOnlyAttr( 'SAI_OBJECT_TYPE_SWITCH', 'SAI_SWITCH_ATTR_AVAILABLE_NEXT_HOP_GROUP_MEMBER_ENTRY', '1000') time.sleep(2) # get counters new_used_counter = getCrmCounterValue( dvs, 'STATS', 'crm_stats_nexthop_group_member_used') new_avail_counter = getCrmCounterValue( dvs, 'STATS', 'crm_stats_nexthop_group_member_available') assert new_used_counter == used_counter assert new_avail_counter == avail_counter marker = dvs.add_log_marker() dvs.runcmd("crm config polling interval 2") dvs.runcmd("crm config thresholds nexthop group member high 90") dvs.runcmd("crm config thresholds nexthop group member type free") time.sleep(2) check_syslog(dvs, marker, "NEXTHOP_GROUP_MEMBER THRESHOLD_EXCEEDED for TH_FREE", 1) intf_tbl._del("Ethernet0|10.0.0.0/31") intf_tbl._del("Ethernet4|10.0.0.2/31") time.sleep(2)
def create_dot1p_profile(self): tbl = swsscommon.Table(self.config_db, CFG_DOT1P_TO_TC_MAP_TABLE_NAME) fvs = swsscommon.FieldValuePairs(DOT1P_TO_TC_MAP.items()) tbl.set(CFG_DOT1P_TO_TC_MAP_KEY, fvs) time.sleep(1)
def test_CrmAcl(self, dvs, testlog): db = swsscommon.DBConnector(4, dvs.redis_sock, 0) adb = swsscommon.DBConnector(1, dvs.redis_sock, 0) dvs.runcmd("crm config polling interval 1") time.sleep(1) bind_ports = ["Ethernet0", "Ethernet4"] old_table_used_counter = getCrmCounterValue( dvs, 'ACL_STATS:INGRESS:PORT', 'crm_stats_acl_table_used') # create ACL table ttbl = swsscommon.Table(db, "ACL_TABLE") fvs = swsscommon.FieldValuePairs([("policy_desc", "test"), ("type", "L3"), ("ports", ",".join(bind_ports))]) ttbl.set("test", fvs) # create ACL rule rtbl = swsscommon.Table(db, "ACL_RULE") fvs = swsscommon.FieldValuePairs([("priority", "55"), ("PACKET_ACTION", "FORWARD"), ("L4_SRC_PORT", "65000")]) rtbl.set("test|acl_test_rule", fvs) time.sleep(2) new_table_used_counter = getCrmCounterValue( dvs, 'ACL_STATS:INGRESS:PORT', 'crm_stats_acl_table_used') table_used_counter = new_table_used_counter - old_table_used_counter assert table_used_counter == 1 # get ACL table key atbl = swsscommon.Table(adb, "ASIC_STATE:SAI_OBJECT_TYPE_ACL_TABLE") acl_tables = [ k for k in atbl.getKeys() if k not in dvs.asicdb.default_acl_tables ] key = "ACL_TABLE_STATS:{0}".format(acl_tables[0].replace('oid:', '')) entry_used_counter = getCrmCounterValue(dvs, key, 'crm_stats_acl_entry_used') assert entry_used_counter == 1 cnt_used_counter = getCrmCounterValue(dvs, key, 'crm_stats_acl_counter_used') assert entry_used_counter == 1 # remove ACL rule rtbl._del("test|acl_test_rule") time.sleep(2) entry_used_counter = getCrmCounterValue(dvs, key, 'crm_stats_acl_entry_used') assert entry_used_counter == 0 cnt_used_counter = getCrmCounterValue(dvs, key, 'crm_stats_acl_counter_used') assert cnt_used_counter == 0 # remove ACL table ttbl._del("test") time.sleep(2) new_table_used_counter = getCrmCounterValue( dvs, 'ACL_STATS:INGRESS:PORT', 'crm_stats_acl_table_used') table_used_counter = new_table_used_counter - old_table_used_counter assert table_used_counter == 0 counters_db = swsscommon.DBConnector(swsscommon.COUNTERS_DB, dvs.redis_sock, 0) crm_stats_table = swsscommon.Table(counters_db, 'CRM') keys = crm_stats_table.getKeys() assert key not in keys
def test_RulesWithDiffMaskLengths(self, dvs, testlog): self.setup_db(dvs) db = swsscommon.DBConnector(4, dvs.redis_sock, 0) adb = swsscommon.DBConnector(1, dvs.redis_sock, 0) bind_ports = ["Ethernet0", "Ethernet4"] # create ACL_TABLE in config db tbl = swsscommon.Table(db, "ACL_TABLE") fvs = swsscommon.FieldValuePairs([("policy_desc", "test"), ("type", "L3"), ("ports", ",".join(bind_ports))]) tbl.set("test_subnet", fvs) time.sleep(2) subnet_mask_rules = 0 #create ACL rules tbl = swsscommon.Table(db, "ACL_RULE") rules = [[("PRIORITY", "10"), ("PACKET_ACTION", "FORWARD"), ("SRC_IP", "23.103.0.0/18")], [("PRIORITY", "20"), ("PACKET_ACTION", "FORWARD"), ("SRC_IP", "104.44.94.0/23")], [("PRIORITY", "30"), ("PACKET_ACTION", "FORWARD"), ("DST_IP", "172.16.0.0/12")], [("PRIORITY", "40"), ("PACKET_ACTION", "FORWARD"), ("DST_IP", "100.64.0.0/10")], [("PRIORITY", "50"), ("PACKET_ACTION", "FORWARD"), ("DST_IP", "104.146.32.0/19")], [("PRIORITY", "60"), ("PACKET_ACTION", "FORWARD"), ("SRC_IP", "21.0.0.0/8")]] #used to verify how ACL rules are programmed in ASICDB #order must match the list of rules verifs = [{ 'SAI_ACL_ENTRY_ATTR_PRIORITY': '10', 'SAI_ACL_ENTRY_ATTR_FIELD_SRC_IP': '23.103.0.0&mask:255.255.192.0', 'SAI_ACL_ENTRY_ATTR_ACTION_PACKET_ACTION': 'SAI_PACKET_ACTION_FORWARD' }, { 'SAI_ACL_ENTRY_ATTR_PRIORITY': '20', 'SAI_ACL_ENTRY_ATTR_FIELD_SRC_IP': '104.44.94.0&mask:255.255.254.0', 'SAI_ACL_ENTRY_ATTR_ACTION_PACKET_ACTION': 'SAI_PACKET_ACTION_FORWARD' }, { 'SAI_ACL_ENTRY_ATTR_PRIORITY': '30', 'SAI_ACL_ENTRY_ATTR_FIELD_DST_IP': '172.16.0.0&mask:255.240.0.0', 'SAI_ACL_ENTRY_ATTR_ACTION_PACKET_ACTION': 'SAI_PACKET_ACTION_FORWARD' }, { 'SAI_ACL_ENTRY_ATTR_PRIORITY': '40', 'SAI_ACL_ENTRY_ATTR_FIELD_DST_IP': '100.64.0.0&mask:255.192.0.0', 'SAI_ACL_ENTRY_ATTR_ACTION_PACKET_ACTION': 'SAI_PACKET_ACTION_FORWARD' }, { 'SAI_ACL_ENTRY_ATTR_PRIORITY': '50', 'SAI_ACL_ENTRY_ATTR_FIELD_DST_IP': '104.146.32.0&mask:255.255.224.0', 'SAI_ACL_ENTRY_ATTR_ACTION_PACKET_ACTION': 'SAI_PACKET_ACTION_FORWARD' }, { 'SAI_ACL_ENTRY_ATTR_PRIORITY': '60', 'SAI_ACL_ENTRY_ATTR_FIELD_SRC_IP': '21.0.0.0&mask:255.0.0.0', 'SAI_ACL_ENTRY_ATTR_ACTION_PACKET_ACTION': 'SAI_PACKET_ACTION_FORWARD' }] #insert rules for rule in rules: fvs = swsscommon.FieldValuePairs(rule) subnet_mask_rules += 1 tbl.set("test_subnet|acl_test_rule%s" % subnet_mask_rules, fvs) time.sleep(1) atbl = swsscommon.Table(adb, "ASIC_STATE:SAI_OBJECT_TYPE_ACL_ENTRY") keys = atbl.getKeys() acl_entry = [ k for k in keys if k not in dvs.asicdb.default_acl_entries ] assert len(acl_entry) == subnet_mask_rules #match each entry to its corresponding verification matched_masks = 0 for entry in acl_entry: (status, fvs) = atbl.get(entry) assert status == True assert len(fvs) == 6 #helper function if self.check_rule_existence(dict(fvs), rules, verifs): matched_masks += 1 assert matched_masks == subnet_mask_rules while subnet_mask_rules > 0: tbl._del("test_subnet|acl_test_rule%s" % subnet_mask_rules) subnet_mask_rules -= 1 time.sleep(1) (status, fvs) = atbl.get(acl_entry[0]) assert status == False tbl = swsscommon.Table(db, "ACL_TABLE") tbl._del("test_subnet") time.sleep(1) atbl = swsscommon.Table(adb, "ASIC_STATE:SAI_OBJECT_TYPE_ACL_TABLE") keys = atbl.getKeys() assert len(keys) >= 1
def test_Portchannel_oper_down(self, dvs, testlog): self.adb = swsscommon.DBConnector(1, dvs.redis_sock, 0) self.cdb = swsscommon.DBConnector(4, dvs.redis_sock, 0) self.pdb = swsscommon.DBConnector(0, dvs.redis_sock, 0) # Create 4 PortChannels tbl = swsscommon.Table(self.cdb, "PORTCHANNEL") fvs = swsscommon.FieldValuePairs([("admin_status", "up"),("mtu", "9100"),("oper_status", "up")]) tbl.set("PortChannel001", fvs) time.sleep(1) tbl.set("PortChannel002", fvs) time.sleep(1) tbl.set("PortChannel003", fvs) time.sleep(1) tbl.set("PortChannel004", fvs) time.sleep(1) tbl = swsscommon.Table(self.cdb, "PORTCHANNEL_MEMBER") fvs = swsscommon.FieldValuePairs([("NULL", "NULL")]) tbl.set("PortChannel001|Ethernet0", fvs) time.sleep(1) tbl.set("PortChannel002|Ethernet4", fvs) time.sleep(1) tbl.set("PortChannel003|Ethernet8", fvs) time.sleep(1) tbl.set("PortChannel004|Ethernet12", fvs) time.sleep(1) tbl = swsscommon.Table(self.cdb, "PORTCHANNEL_INTERFACE") fvs = swsscommon.FieldValuePairs([("NULL", "NULL")]) tbl.set("PortChannel001", fvs) tbl.set("PortChannel001|40.0.0.0/31", fvs) time.sleep(1) tbl.set("PortChannel002", fvs) tbl.set("PortChannel002|40.0.0.2/31", fvs) time.sleep(1) tbl.set("PortChannel003", fvs) tbl.set("PortChannel003|40.0.0.4/31", fvs) time.sleep(1) tbl.set("PortChannel004", fvs) tbl.set("PortChannel004|40.0.0.6/31", fvs) time.sleep(1) # check application database tbl = swsscommon.Table(self.pdb, "INTF_TABLE:PortChannel001") intf_entries = tbl.getKeys() assert len(intf_entries) == 1 assert intf_entries[0] == "40.0.0.0/31" tbl = swsscommon.Table(self.pdb, "INTF_TABLE:PortChannel002") intf_entries = tbl.getKeys() assert len(intf_entries) == 1 assert intf_entries[0] == "40.0.0.2/31" tbl = swsscommon.Table(self.pdb, "INTF_TABLE:PortChannel003") intf_entries = tbl.getKeys() assert len(intf_entries) == 1 assert intf_entries[0] == "40.0.0.4/31" tbl = swsscommon.Table(self.pdb, "INTF_TABLE:PortChannel004") intf_entries = tbl.getKeys() assert len(intf_entries) == 1 assert intf_entries[0] == "40.0.0.6/31" # set oper_status for PortChannels ps = swsscommon.ProducerStateTable(self.pdb, "LAG_TABLE") fvs = swsscommon.FieldValuePairs([("admin_status", "up"),("mtu", "9100"),("oper_status", "up")]) ps.set("PortChannel001", fvs) ps.set("PortChannel002", fvs) ps.set("PortChannel003", fvs) ps.set("PortChannel004", fvs) time.sleep(1) dvs.runcmd("arp -s 40.0.0.1 00:00:00:00:00:01") time.sleep(1) dvs.runcmd("arp -s 40.0.0.3 00:00:00:00:00:03") time.sleep(1) dvs.runcmd("arp -s 40.0.0.5 00:00:00:00:00:05") time.sleep(1) dvs.runcmd("arp -s 40.0.0.7 00:00:00:00:00:07") time.sleep(1) ps = swsscommon.ProducerStateTable(self.pdb, "ROUTE_TABLE") fvs = swsscommon.FieldValuePairs([("nexthop","40.0.0.1,40.0.0.3,40.0.0.5,40.0.0.7"), ("ifname", "PortChannel001,PortChannel002,PortChannel003,PortChannel004")]) ps.set("2.2.2.0/24", fvs) time.sleep(1) # check if route has propagated to ASIC DB re_tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_ROUTE_ENTRY") found_route = False for key in re_tbl.getKeys(): route = json.loads(key) if route["dest"] == "2.2.2.0/24": found_route = True break assert found_route # check if route points to next hop group nhg_tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP_GROUP") (status, fvs) = re_tbl.get(key) for v in fvs: if v[0] == "SAI_ROUTE_ENTRY_ATTR_NEXT_HOP_ID": nhg_id = v[1] (status, fvs) = nhg_tbl.get(nhg_id) assert status # check if next hop group consists of 4 members nhg_member_tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP_GROUP_MEMBER") keys = nhg_member_tbl.getKeys() assert len(keys) == 4 for key in keys: (status, fvs) = nhg_member_tbl.get(key) for v in fvs: if v[0] == "SAI_NEXT_HOP_GROUP_MEMBER_ATTR_NEXT_HOP_GROUP_ID": assert v[1] == nhg_id # bring PortChannel down dvs.servers[0].runcmd("ip link set down dev eth0") time.sleep(1) ps = swsscommon.ProducerStateTable(self.pdb, "LAG_TABLE") fvs = swsscommon.FieldValuePairs([("admin_status", "up"),("mtu", "9100"),("oper_status", "down")]) ps.set("PortChannel001", fvs) time.sleep(1) # check if next hop group consists of 3 member keys = nhg_member_tbl.getKeys() assert len(keys) == 3 # remove route entry ps = swsscommon.ProducerStateTable(self.pdb, "ROUTE_TABLE") ps._del("2.2.2.0/24") time.sleep(1) # remove IP address tbl = swsscommon.Table(self.cdb, "PORTCHANNEL_INTERFACE") tbl._del("PortChannel001|40.0.0.0/31") tbl._del("PortChannel002|40.0.0.2/31") tbl._del("PortChannel003|40.0.0.4/31") tbl._del("PortChannel004|40.0.0.6/31") time.sleep(1) # check application database tbl = swsscommon.Table(self.pdb, "INTF_TABLE:PortChannel001") intf_entries = tbl.getKeys() assert len(intf_entries) == 0 tbl = swsscommon.Table(self.pdb, "INTF_TABLE:PortChannel002") intf_entries = tbl.getKeys() assert len(intf_entries) == 0 tbl = swsscommon.Table(self.pdb, "INTF_TABLE:PortChannel003") intf_entries = tbl.getKeys() assert len(intf_entries) == 0 tbl = swsscommon.Table(self.pdb, "INTF_TABLE:PortChannel004") intf_entries = tbl.getKeys() assert len(intf_entries) == 0 # remove router interfaces tbl = swsscommon.Table(self.cdb, "PORTCHANNEL_INTERFACE") tbl._del("PortChannel001") tbl._del("PortChannel002") tbl._del("PortChannel003") tbl._del("PortChannel004") time.sleep(1) # check application database tbl = swsscommon.Table(self.pdb, "INTF_TABLE") intf_entries = tbl.getKeys() assert len(intf_entries) == 0 # remove PortChannel members tbl = swsscommon.Table(self.cdb, "PORTCHANNEL_MEMBER") tbl._del("PortChannel001|Ethernet0") tbl._del("PortChannel002|Ethernet4") tbl._del("PortChannel003|Ethernet8") tbl._del("PortChannel004|Ethernet12") time.sleep(1) # remove PortChannel tbl = swsscommon.Table(self.cdb, "PORTCHANNEL") tbl._del("PortChannel001") tbl._del("PortChannel002") tbl._del("PortChannel003") tbl._del("PortChannel004") time.sleep(1) # Restore eth0 up dvs.servers[0].runcmd("ip link set up dev eth0") time.sleep(1)
def test_V6AclTableCreation(self, dvs, testlog): self.setup_db(dvs) db = swsscommon.DBConnector(4, dvs.redis_sock, 0) adb = swsscommon.DBConnector(1, dvs.redis_sock, 0) bind_ports = ["Ethernet0", "Ethernet4", "Ethernet8"] # create ACL_TABLE in config db tbl = swsscommon.Table(db, "ACL_TABLE") fvs = swsscommon.FieldValuePairs([("policy_desc", "testv6"), ("type", "L3V6"), ("ports", ",".join(bind_ports))]) tbl.set("test-aclv6", fvs) time.sleep(1) # check acl table in asic db test_acl_table_id = self.get_acl_table_id(dvs) # check acl table group in asic db atbl = swsscommon.Table(adb, "ASIC_STATE:SAI_OBJECT_TYPE_ACL_TABLE_GROUP") acl_table_groups = atbl.getKeys() assert len(acl_table_groups) == 3 for k in acl_table_groups: (status, fvs) = atbl.get(k) assert status == True for fv in fvs: if fv[0] == "SAI_ACL_TABLE_GROUP_ATTR_ACL_STAGE": assert fv[1] == "SAI_ACL_STAGE_INGRESS" elif fv[0] == "SAI_ACL_TABLE_GROUP_ATTR_ACL_BIND_POINT_TYPE_LIST": assert fv[1] == "1:SAI_ACL_BIND_POINT_TYPE_PORT" elif fv[0] == "SAI_ACL_TABLE_GROUP_ATTR_TYPE": assert fv[1] == "SAI_ACL_TABLE_GROUP_TYPE_PARALLEL" else: assert False # check acl table group member atbl = swsscommon.Table( adb, "ASIC_STATE:SAI_OBJECT_TYPE_ACL_TABLE_GROUP_MEMBER") keys = atbl.getKeys() # three ports assert len(keys) == 3 member_groups = [] for k in keys: (status, fvs) = atbl.get(k) assert status == True assert len(fvs) == 3 for fv in fvs: if fv[0] == "SAI_ACL_TABLE_GROUP_MEMBER_ATTR_ACL_TABLE_GROUP_ID": assert fv[1] in acl_table_groups member_groups.append(fv[1]) elif fv[0] == "SAI_ACL_TABLE_GROUP_MEMBER_ATTR_ACL_TABLE_ID": assert fv[1] == test_acl_table_id elif fv[0] == "SAI_ACL_TABLE_GROUP_MEMBER_ATTR_PRIORITY": assert True else: assert False assert set(member_groups) == set(acl_table_groups) # check port binding atbl = swsscommon.Table(adb, "ASIC_STATE:SAI_OBJECT_TYPE_PORT") port_groups = [] for p in [dvs.asicdb.portnamemap[portname] for portname in bind_ports]: (status, fvs) = atbl.get(p) for fv in fvs: if fv[0] == "SAI_PORT_ATTR_INGRESS_ACL": assert fv[1] in acl_table_groups port_groups.append(fv[1]) assert set(port_groups) == set(acl_table_groups)
def test_Portchannel(self, dvs, testlog): # create port channel db = swsscommon.DBConnector(0, dvs.redis_sock, 0) ps = swsscommon.ProducerStateTable(db, "LAG_TABLE") fvs = swsscommon.FieldValuePairs([("admin", "up"), ("mtu", "1500")]) ps.set("PortChannel0001", fvs) # create port channel member ps = swsscommon.ProducerStateTable(db, "LAG_MEMBER_TABLE") fvs = swsscommon.FieldValuePairs([("status", "enabled")]) ps.set("PortChannel0001:Ethernet0", fvs) time.sleep(1) # check asic db asicdb = swsscommon.DBConnector(1, dvs.redis_sock, 0) lagtbl = swsscommon.Table(asicdb, "ASIC_STATE:SAI_OBJECT_TYPE_LAG") lags = lagtbl.getKeys() assert len(lags) == 1 lagmtbl = swsscommon.Table(asicdb, "ASIC_STATE:SAI_OBJECT_TYPE_LAG_MEMBER") lagms = lagmtbl.getKeys() assert len(lagms) == 1 (status, fvs) = lagmtbl.get(lagms[0]) fvs = dict(fvs) assert status assert "SAI_LAG_MEMBER_ATTR_LAG_ID" in fvs assert fvs.pop("SAI_LAG_MEMBER_ATTR_LAG_ID") == lags[0] assert "SAI_LAG_MEMBER_ATTR_PORT_ID" in fvs assert dvs.asicdb.portoidmap[fvs.pop("SAI_LAG_MEMBER_ATTR_PORT_ID")] == "Ethernet0" assert "SAI_LAG_MEMBER_ATTR_INGRESS_DISABLE" in fvs assert fvs.pop("SAI_LAG_MEMBER_ATTR_INGRESS_DISABLE") == "false" assert "SAI_LAG_MEMBER_ATTR_EGRESS_DISABLE" in fvs assert fvs.pop("SAI_LAG_MEMBER_ATTR_EGRESS_DISABLE") == "false" assert not fvs ps = swsscommon.ProducerStateTable(db, "LAG_MEMBER_TABLE") fvs = swsscommon.FieldValuePairs([("status", "disabled")]) ps.set("PortChannel0001:Ethernet0", fvs) time.sleep(1) lagmtbl = swsscommon.Table(asicdb, "ASIC_STATE:SAI_OBJECT_TYPE_LAG_MEMBER") lagms = lagmtbl.getKeys() assert len(lagms) == 1 (status, fvs) = lagmtbl.get(lagms[0]) fvs = dict(fvs) assert status assert "SAI_LAG_MEMBER_ATTR_LAG_ID" in fvs assert fvs.pop("SAI_LAG_MEMBER_ATTR_LAG_ID") == lags[0] assert "SAI_LAG_MEMBER_ATTR_PORT_ID" in fvs assert dvs.asicdb.portoidmap[fvs.pop("SAI_LAG_MEMBER_ATTR_PORT_ID")] == "Ethernet0" assert "SAI_LAG_MEMBER_ATTR_INGRESS_DISABLE" in fvs assert fvs.pop("SAI_LAG_MEMBER_ATTR_INGRESS_DISABLE") == "true" assert "SAI_LAG_MEMBER_ATTR_EGRESS_DISABLE" in fvs assert fvs.pop("SAI_LAG_MEMBER_ATTR_EGRESS_DISABLE") == "true" assert not fvs # remove port channel member ps = swsscommon.ProducerStateTable(db, "LAG_MEMBER_TABLE") ps._del("PortChannel0001:Ethernet0") # remove port channel ps = swsscommon.ProducerStateTable(db, "LAG_TABLE") ps._del("PortChannel0001") time.sleep(1) # check asic db lags = lagtbl.getKeys() assert len(lags) == 0 lagms = lagmtbl.getKeys() assert len(lagms) == 0
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 create_entry(tbl, key, pairs): fvs = swsscommon.FieldValuePairs(pairs) tbl.set(key, fvs) time.sleep(1)
def add_neighbor(self, interface, ip, mac): tbl = swsscommon.ProducerStateTable(self.pdb, "NEIGH_TABLE") fvs = swsscommon.FieldValuePairs([("neigh", mac), ("family", "IPv4")]) tbl.set(interface + ":" + ip, 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 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 table_set(t, state): fvs = swsscommon.FieldValuePairs([("status", state)]) t.set("123", fvs)
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 fine_grained_ecmp_base_test(dvs, match_mode): 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), "match_mode": match_mode} create_entry(config_db, FG_NHG, fg_nhg_name, fvs) if match_mode == 'route-based': 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) vlan_name_key = "Vlan" + str((i + 1) * 4) ip_pref_key = vlan_name_key + "|10.0.0." + str(i * 2) + "/31" fvs = {"vlanid": str((i + 1) * 4)} create_entry(config_db, VLAN_TB, vlan_name_key, fvs) fvs = {"tagging_mode": "untagged"} create_entry(config_db, VLAN_MEMB_TB, vlan_name_key + "|" + if_name_key, fvs) create_entry(config_db, VLAN_IF_TB, vlan_name_key, fvs_nul) create_entry(config_db, VLAN_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), "link": if_name_key} 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)] = vlan_name_key # Wait for the software to receive the entries time.sleep(1) 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", "Vlan16,Vlan20,Vlan24")]) 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) asic_nh_count = len(asic_db.get_keys(ASIC_NH_TB)) 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") asic_db.wait_for_n_keys(ASIC_NH_TB, asic_nh_count + 5) asic_db.wait_for_n_keys(ASIC_NHG_MEMB, bucket_size) nhgid = validate_asic_nhg_fine_grained_ecmp(asic_db, fg_nhg_prefix, bucket_size) nh_oid_map = get_nh_oid_map(asic_db) ### Test scenarios with bank 0 having 0 members up and only bank 1 having members # 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, fg_nhg_prefix, 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_NH_TB)) dvs.runcmd("arp -s 10.0.0.7 00:00:00:00:00:04") asic_db.wait_for_n_keys(ASIC_NH_TB, 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, fg_nhg_prefix, nh_memb_exp_count, nh_oid_map, nhgid, bucket_size) # Test warm reboot run_warm_reboot(dvs) asic_db.wait_for_n_keys(ASIC_NHG_MEMB, bucket_size) nhgid = validate_asic_nhg_fine_grained_ecmp(asic_db, fg_nhg_prefix, bucket_size) 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, fg_nhg_prefix, 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 down 2 next hop and bring up 1 next hop in bank 1 nh_memb_exp_count = {"10.0.0.9": 60} 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) # Test warm reboot run_warm_reboot(dvs) asic_db.wait_for_n_keys(ASIC_NHG_MEMB, bucket_size) nhgid = validate_asic_nhg_fine_grained_ecmp(asic_db, fg_nhg_prefix, bucket_size) nh_oid_map = get_nh_oid_map(asic_db) 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 } validate_fine_grained_asic_n_state_db_entries(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) shutdown_link(dvs, app_db, 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, fg_nhg_prefix, 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, fg_nhg_prefix, 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, fg_nhg_prefix, 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, fg_nhg_prefix, 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) nh_memb_exp_count = {"10.0.0.7": 30, "10.0.0.9": 30} validate_fine_grained_asic_n_state_db_entries(asic_db, state_db, ip_to_if_map, fg_nhg_prefix, nh_memb_exp_count, nh_oid_map, nhgid, bucket_size) startup_link(dvs, app_db, 5) # Perform a route table update, Update the route to contain 10.0.0.3 as well, since Ethernet4 associated with it # is link down, it should make no difference fvs = swsscommon.FieldValuePairs([ ("nexthop", "10.0.0.1,10.0.0.3,10.0.0.5,10.0.0.7,10.0.0.9,10.0.0.11"), ("ifname", "Vlan4,Vlan8,Vlan12,Vlan16,Vlan20,Vlan24") ]) ps.set(fg_nhg_prefix, fvs) # 10.0.0.11 associated with newly brought up link 5 should be updated in FG ecmp # 10.0.0.3 addition per above route table change should have no effect 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, fg_nhg_prefix, 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, fg_nhg_prefix, 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, fg_nhg_prefix, 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, fg_nhg_prefix, 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, fg_nhg_prefix, 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) if match_mode == 'route-based': 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 fvs = swsscommon.FieldValuePairs([("nexthop", "10.0.0.7,10.0.0.9,10.0.0.11"), ("ifname", "Vlan16,Vlan20,Vlan24")]) ps.set(fg_nhg_prefix, fvs) validate_asic_nhg_regular_ecmp(asic_db, fg_nhg_prefix) 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) nhgid = validate_asic_nhg_fine_grained_ecmp(asic_db, fg_nhg_prefix, 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, fg_nhg_prefix, 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) vlan_name_key = "Vlan" + str((i + 1) * 4) ip_pref_key = vlan_name_key + "|10.0.0." + str(i * 2) + "/31" remove_entry(config_db, VLAN_IF_TB, ip_pref_key) remove_entry(config_db, VLAN_IF_TB, vlan_name_key) remove_entry(config_db, VLAN_MEMB_TB, vlan_name_key + "|" + if_name_key) remove_entry(config_db, VLAN_TB, vlan_name_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))