def test_route_nhg_exhaust(self, dvs, testlog): """ Test the situation of exhausting ECMP group, assume SAI_SWITCH_ATTR_NUMBER_OF_ECMP_GROUPS is 512 In order to achieve that, we will config 1. 9 ports 2. 512 routes with different nexthop group See Also -------- SwitchStateBase::set_number_of_ecmp_groups() https://github.com/Azure/sonic-sairedis/blob/master/vslib/src/SwitchStateBase.cpp """ # TODO: check ECMP 512 def port_name(i): return "Ethernet" + str(i * 4) def port_ip(i): return "10.0.0." + str(i * 2) def peer_ip(i): return "10.0.0." + str(i * 2 + 1) def port_ipprefix(i): return port_ip(i) + "/31" def port_mac(i): return "00:00:00:00:00:0" + str(i) def gen_ipprefix(r): """ Construct route like 2.X.X.0/24 """ ip = ipaddress.IPv4Address(IP_INTEGER_BASE + r * 256) ip = str(ip) ipprefix = ip + "/24" return ipprefix def gen_nhg_fvs(binary): nexthop = [] ifname = [] for i in range(MAX_PORT_COUNT): if binary[i] == '1': nexthop.append(peer_ip(i)) ifname.append(port_name(i)) nexthop = ','.join(nexthop) ifname = ','.join(ifname) fvs = swsscommon.FieldValuePairs([("nexthop", nexthop), ("ifname", ifname)]) return fvs def asic_route_exists(keys, ipprefix): for k in keys: rt_key = json.loads(k) if rt_key['dest'] == ipprefix: return k else: return None def asic_route_nhg_fvs(k): fvs = asic_db.get_entry("ASIC_STATE:SAI_OBJECT_TYPE_ROUTE_ENTRY", k) if not fvs: return None print(fvs) nhgid = fvs.get("SAI_ROUTE_ENTRY_ATTR_NEXT_HOP_ID") if nhgid is None: return None fvs = asic_db.get_entry( "ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP_GROUP", nhgid) return fvs MAX_ECMP_COUNT = 512 MAX_PORT_COUNT = 10 if sys.version_info < (3, 0): IP_INTEGER_BASE = int(ipaddress.IPv4Address(unicode("2.2.2.0"))) else: IP_INTEGER_BASE = int(ipaddress.IPv4Address(str("2.2.2.0"))) config_db = dvs.get_config_db() fvs = {"NULL": "NULL"} for i in range(MAX_PORT_COUNT): config_db.create_entry("INTERFACE", port_name(i), fvs) config_db.create_entry( "INTERFACE", "{}|{}".format(port_name(i), port_ipprefix(i)), fvs) dvs.runcmd("config interface startup " + port_name(i)) dvs.runcmd("arp -s {} {}".format(peer_ip(i), port_mac(i))) assert dvs.servers[i].runcmd("ip link set down dev eth0") == 0 assert dvs.servers[i].runcmd("ip link set up dev eth0") == 0 app_db = dvs.get_app_db() asic_db = dvs.get_asic_db() ps = swsscommon.ProducerStateTable(app_db.db_connection, "ROUTE_TABLE") # Add first batch of routes with unique nexthop groups in AppDB route_count = 0 r = 0 asic_routes_count = len( asic_db.get_keys("ASIC_STATE:SAI_OBJECT_TYPE_ROUTE_ENTRY")) while route_count < MAX_ECMP_COUNT: r += 1 fmt = '{{0:0{}b}}'.format(MAX_PORT_COUNT) binary = fmt.format(r) # We need at least 2 ports for a nexthop group if binary.count('1') <= 1: continue fvs = gen_nhg_fvs(binary) route_ipprefix = gen_ipprefix(route_count) ps.set(route_ipprefix, fvs) route_count += 1 # Wait and check ASIC DB the count of nexthop groups used asic_db.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP_GROUP", MAX_ECMP_COUNT) # Wait and check ASIC DB the count of routes asic_db.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_ROUTE_ENTRY", asic_routes_count + MAX_ECMP_COUNT) asic_routes_count += MAX_ECMP_COUNT # Add second batch of routes with unique nexthop groups in AppDB # Add more routes with new nexthop group in AppDBdd route_ipprefix = gen_ipprefix(route_count) base_ipprefix = route_ipprefix base = route_count route_count = 0 while route_count < 10: r += 1 fmt = '{{0:0{}b}}'.format(MAX_PORT_COUNT) binary = fmt.format(r) # We need at least 2 ports for a nexthop group if binary.count('1') <= 1: continue fvs = gen_nhg_fvs(binary) route_ipprefix = gen_ipprefix(base + route_count) ps.set(route_ipprefix, fvs) route_count += 1 last_ipprefix = route_ipprefix # Wait until we get expected routes and check ASIC DB on the count of nexthop groups used, and it should not increase keys = asic_db.wait_for_n_keys( "ASIC_STATE:SAI_OBJECT_TYPE_ROUTE_ENTRY", asic_routes_count + 10) asic_db.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP_GROUP", MAX_ECMP_COUNT) # Check the route points to next hop group # Note: no need to wait here k = asic_route_exists(keys, "2.2.2.0/24") assert k is not None fvs = asic_route_nhg_fvs(k) assert fvs is not None # Check the second batch does not point to next hop group k = asic_route_exists(keys, base_ipprefix) assert k is not None fvs = asic_route_nhg_fvs(k) assert not (fvs) # Remove first batch of routes with unique nexthop groups in AppDB route_count = 0 r = 0 while route_count < MAX_ECMP_COUNT: r += 1 fmt = '{{0:0{}b}}'.format(MAX_PORT_COUNT) binary = fmt.format(r) # We need at least 2 ports for a nexthop group if binary.count('1') <= 1: continue route_ipprefix = gen_ipprefix(route_count) ps._del(route_ipprefix) route_count += 1 # Wait and check the second batch points to next hop group # Check ASIC DB on the count of nexthop groups used, and it should not increase or decrease asic_db.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP_GROUP", 10) keys = asic_db.get_keys("ASIC_STATE:SAI_OBJECT_TYPE_ROUTE_ENTRY") k = asic_route_exists(keys, base_ipprefix) assert k is not None fvs = asic_route_nhg_fvs(k) assert fvs is not None k = asic_route_exists(keys, last_ipprefix) assert k is not None fvs = asic_route_nhg_fvs(k) assert fvs is not None
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 create_entry_pst(db, table, separator, key, pairs): tbl = swsscommon.ProducerStateTable(db, table) create_entry(tbl, key, pairs)
def _test_sub_port_intf_oper_down_with_pending_neigh_route_tasks( self, dvs, sub_port_intf_name, nhop_num=3, create_intf_on_parent_port=False): substrs = sub_port_intf_name.split(VLAN_SUB_INTERFACE_SEPARATOR) parent_port = substrs[0] vlan_id = substrs[1] assert len(vlan_id) == 2 if parent_port.startswith(ETHERNET_PREFIX): parent_port_prefix = ETHERNET_PREFIX else: assert parent_port.startswith(LAG_PREFIX) parent_port_prefix = LAG_PREFIX parent_port_idx_base = self.get_parent_port_index(parent_port) # Set parent ports admin status up parent_port_idx = parent_port_idx_base for i in range(0, nhop_num): port_name = "{}{}".format(parent_port_prefix, parent_port_idx) self.set_parent_port_admin_status(dvs, port_name, "up") parent_port_idx += (4 if parent_port_prefix == ETHERNET_PREFIX else 1) ifnames = [] # Create sub port interfaces ifnames.extend( self.create_nhg_router_intfs(dvs, parent_port_prefix, parent_port_idx_base, int(vlan_id), nhop_num)) # Create router interfaces on parent ports if create_intf_on_parent_port == True: ifnames.extend( self.create_nhg_router_intfs(dvs, parent_port_prefix, parent_port_idx_base, 0, nhop_num)) # Bring parent port oper status down one at a time # Verify next hop group members created after processing pending tasks parent_port_idx = parent_port_idx_base for i in range(0, nhop_num): port_name = "{}{}".format(parent_port_prefix, parent_port_idx) self.set_parent_port_oper_status(dvs, port_name, "down") # Verify parent port oper status down fv_dict = { "oper_status": "down", } if parent_port_prefix == ETHERNET_PREFIX: self.check_sub_port_intf_fvs(self.app_db, APP_PORT_TABLE_NAME, port_name, fv_dict) else: self.check_sub_port_intf_fvs(self.app_db, APP_LAG_TABLE_NAME, port_name, fv_dict) # Mimic pending neighbor task nhop_ips = [] nhop_cnt = len(self.asic_db.get_keys(ASIC_NEXT_HOP_TABLE)) # Create next hop objects on sub port interfaces nhop_ips.extend( self.create_nhg_next_hop_objs(dvs, parent_port_prefix, parent_port_idx_base, int(vlan_id), nhop_num)) # Create next hop objects on router interfaces if create_intf_on_parent_port == True: nhop_ips.extend( self.create_nhg_next_hop_objs(dvs, parent_port_prefix, parent_port_idx_base, 0, nhop_num)) self.asic_db.wait_for_n_keys( ASIC_NEXT_HOP_TABLE, nhop_cnt + nhop_num if create_intf_on_parent_port == False else nhop_cnt + nhop_num * 2) # Mimic pending multi-next-hop route entry task rt_tbl = swsscommon.ProducerStateTable(self.app_db.db_connection, APP_ROUTE_TABLE_NAME) fvs = swsscommon.FieldValuePairs([("nexthop", ",".join(nhop_ips)), ("ifname", ",".join(ifnames))]) ip_prefix = "2.2.2.0/24" rt_tbl.set(ip_prefix, fvs) # Verify route entry created in ASIC_DB and get next hop group oid nhg_oid = self.get_ip_prefix_nhg_oid(ip_prefix) # Verify next hop group of the specified oid created in ASIC_DB self.check_sub_port_intf_key_existence(self.asic_db, ASIC_NEXT_HOP_GROUP_TABLE, nhg_oid) # Verify next hop group member # created in ASIC_DB nhg_member_oids = self.asic_db.wait_for_n_keys(ASIC_NEXT_HOP_GROUP_MEMBER_TABLE, \ (nhop_num - 1) - i if create_intf_on_parent_port == False else ((nhop_num - 1) - i) * 2) # Verify that next hop group members all belong to the next hop group of the specified oid fv_dict = { "SAI_NEXT_HOP_GROUP_MEMBER_ATTR_NEXT_HOP_GROUP_ID": nhg_oid, } for nhg_member_oid in nhg_member_oids: self.check_sub_port_intf_fvs(self.asic_db, ASIC_NEXT_HOP_GROUP_MEMBER_TABLE, nhg_member_oid, fv_dict) nhop_cnt = len(self.asic_db.get_keys(ASIC_NEXT_HOP_TABLE)) # Remove next hop objects on sub port interfaces self.remove_nhg_next_hop_objs(dvs, parent_port_prefix, parent_port_idx_base, int(vlan_id), nhop_num) # Remove next hop objects on router interfaces if create_intf_on_parent_port == True: self.remove_nhg_next_hop_objs(dvs, parent_port_prefix, parent_port_idx_base, 0, nhop_num) # Remove ecmp route entry rt_tbl._del(ip_prefix) # Removal of next hop objects indicates the proper removal of route entry, nhg, and nhg members self.asic_db.wait_for_n_keys( ASIC_NEXT_HOP_TABLE, nhop_cnt - nhop_num if create_intf_on_parent_port == False else nhop_cnt - nhop_num * 2) parent_port_idx += (4 if parent_port_prefix == ETHERNET_PREFIX else 1) # Clean up rif_cnt = len(self.asic_db.get_keys(ASIC_RIF_TABLE)) # Remove sub port interfaces self.remove_nhg_router_intfs(dvs, parent_port_prefix, parent_port_idx_base, int(vlan_id), nhop_num) # Remove router interfaces on parent ports if create_intf_on_parent_port == True: self.remove_nhg_router_intfs(dvs, parent_port_prefix, parent_port_idx_base, 0, nhop_num) self.asic_db.wait_for_n_keys( ASIC_RIF_TABLE, rif_cnt - nhop_num if create_intf_on_parent_port == False else rif_cnt - nhop_num * 2) # Make sure parent port oper status is up parent_port_idx = parent_port_idx_base for i in range(0, nhop_num): port_name = "{}{}".format(parent_port_prefix, parent_port_idx) self.set_parent_port_oper_status(dvs, port_name, "up") parent_port_idx += (4 if parent_port_prefix == ETHERNET_PREFIX else 1)
def test_route_fgnhg_warm_reboot(self, dvs, testlog): dvs.runcmd("swssloglevel -l INFO -c orchagent") 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) 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) 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.7 00:00:00:00:00:04") 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 + 6) 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) # 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) 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, 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) 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} 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)
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.port_admin_set("Ethernet0", "up") dvs.servers[0].runcmd("ifconfig eth0 inet6 add fc00::2/126") dvs.servers[0].runcmd("ip -6 route add default via fc00::1") crm_update(dvs, "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() crm_update(dvs, "polling_interval", "2") crm_update(dvs, "ipv6_route_high_threshold", "90") crm_update(dvs, "ipv6_route_threshold_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_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.port_admin_set("Ethernet0", "up") dvs.port_admin_set("Ethernet4", "up") crm_update(dvs, "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() crm_update(dvs, "polling_interval", "2") crm_update(dvs, "nexthop_group_member_high_threshold", "90") crm_update(dvs, "nexthop_group_member_threshold_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 test_PortAutoNegWarm(self, dvs, testlog): db = swsscommon.DBConnector(0, dvs.redis_sock, 0) cdb = swsscommon.DBConnector(4, dvs.redis_sock, 0) sdb = swsscommon.DBConnector(6, dvs.redis_sock, 0) tbl = swsscommon.ProducerStateTable(db, "PORT_TABLE") ctbl = swsscommon.Table(cdb, "PORT") stbl = swsscommon.Table(sdb, "PORT_TABLE") # set autoneg = true and speed = 1000 fvs = swsscommon.FieldValuePairs([("autoneg", "on"), ("speed", "1000")]) ctbl.set("Ethernet0", fvs) time.sleep(1) adb = swsscommon.DBConnector(1, dvs.redis_sock, 0) atbl = swsscommon.Table(adb, "ASIC_STATE:SAI_OBJECT_TYPE_PORT") (status, fvs) = atbl.get(dvs.asicdb.portnamemap["Ethernet0"]) assert status == True assert "SAI_PORT_ATTR_AUTO_NEG_MODE" in [fv[0] for fv in fvs] assert "SAI_PORT_ATTR_ADVERTISED_SPEED" in [fv[0] for fv in fvs] for fv in fvs: if fv[0] == "SAI_PORT_ATTR_AUTO_NEG_MODE": assert fv[1] == "true" elif fv[0] == "SAI_PORT_ATTR_ADVERTISED_SPEED": assert fv[1] == "1:1000" # set speed = 100 fvs = swsscommon.FieldValuePairs([("speed", "100")]) ctbl.set("Ethernet0", fvs) time.sleep(1) (status, fvs) = atbl.get(dvs.asicdb.portnamemap["Ethernet0"]) assert status == True for fv in fvs: if fv[0] == "SAI_PORT_ATTR_AUTO_NEG_MODE": assert fv[1] == "true" elif fv[0] == "SAI_PORT_ATTR_ADVERTISED_SPEED": assert fv[1] == "1:100" # set admin up cfvs = swsscommon.FieldValuePairs([("admin_status", "up")]) ctbl.set("Ethernet0", cfvs) # enable warm restart (exitcode, result) = dvs.runcmd("config warm_restart enable swss") assert exitcode == 0 # freeze orchagent for warm restart (exitcode, result) = dvs.runcmd("/usr/bin/orchagent_restart_check") assert result == "RESTARTCHECK succeeded\n" time.sleep(2) try: # restart orchagent # clean port state dvs.stop_swss() ports = stbl.getKeys() for port in ports: stbl._del(port) dvs.start_swss() time.sleep(2) # check ASIC DB after warm restart (status, fvs) = atbl.get(dvs.asicdb.portnamemap["Ethernet0"]) assert status == True assert "SAI_PORT_ATTR_AUTO_NEG_MODE" in [fv[0] for fv in fvs] assert "SAI_PORT_ATTR_ADVERTISED_SPEED" in [fv[0] for fv in fvs] for fv in fvs: if fv[0] == "SAI_PORT_ATTR_AUTO_NEG_MODE": assert fv[1] == "true" elif fv[0] == "SAI_PORT_ATTR_ADVERTISED_SPEED": assert fv[1] == "1:100" finally: # disable warm restart dvs.runcmd("config warm_restart disable swss") # slow down crm polling dvs.runcmd("crm config polling interval 10000")
def test_PortAutoNegCold(self, dvs, testlog): db = swsscommon.DBConnector(0, dvs.redis_sock, 0) tbl = swsscommon.ProducerStateTable(db, "PORT_TABLE") # set autoneg = true and speed = 1000 fvs = swsscommon.FieldValuePairs([("autoneg", "on"), ("speed", "1000")]) tbl.set("Ethernet0", fvs) time.sleep(1) adb = swsscommon.DBConnector(1, dvs.redis_sock, 0) atbl = swsscommon.Table(adb, "ASIC_STATE:SAI_OBJECT_TYPE_PORT") (status, fvs) = atbl.get(dvs.asicdb.portnamemap["Ethernet0"]) assert status == True assert "SAI_PORT_ATTR_AUTO_NEG_MODE" in [fv[0] for fv in fvs] assert "SAI_PORT_ATTR_ADVERTISED_SPEED" in [fv[0] for fv in fvs] for fv in fvs: if fv[0] == "SAI_PORT_ATTR_AUTO_NEG_MODE": assert fv[1] == "true" elif fv[0] == "SAI_PORT_ATTR_ADVERTISED_SPEED": assert fv[1] == "1:1000" # set speed = 100 fvs = swsscommon.FieldValuePairs([("speed", "100")]) tbl.set("Ethernet0", fvs) time.sleep(1) (status, fvs) = atbl.get(dvs.asicdb.portnamemap["Ethernet0"]) assert status == True for fv in fvs: if fv[0] == "SAI_PORT_ATTR_AUTO_NEG_MODE": assert fv[1] == "true" elif fv[0] == "SAI_PORT_ATTR_ADVERTISED_SPEED": assert fv[1] == "1:100" # change autoneg to false fvs = swsscommon.FieldValuePairs([("autoneg", "off")]) tbl.set("Ethernet0", fvs) time.sleep(1) (status, fvs) = atbl.get(dvs.asicdb.portnamemap["Ethernet0"]) assert status == True assert "SAI_PORT_ATTR_AUTO_NEG_MODE" in [fv[0] for fv in fvs] assert "SAI_PORT_ATTR_ADVERTISED_SPEED" in [fv[0] for fv in fvs] assert "SAI_PORT_ATTR_SPEED" in [fv[0] for fv in fvs] for fv in fvs: if fv[0] == "SAI_PORT_ATTR_AUTO_NEG_MODE": assert fv[1] == "false" elif fv[0] == "SAI_PORT_ATTR_ADVERTISED_SPEED": assert fv[1] == "1:100" elif fv[0] == "SAI_PORT_ATTR_SPEED": assert fv[1] == "100" # set speed = 1000 fvs = swsscommon.FieldValuePairs([("speed", "1000")]) tbl.set("Ethernet0", fvs) time.sleep(1) (status, fvs) = atbl.get(dvs.asicdb.portnamemap["Ethernet0"]) assert status == True for fv in fvs: if fv[0] == "SAI_PORT_ATTR_AUTO_NEG_MODE": assert fv[1] == "false" elif fv[0] == "SAI_PORT_ATTR_ADVERTISED_SPEED": assert fv[1] == "1:100" elif fv[0] == "SAI_PORT_ATTR_SPEED": assert fv[1] == "1000"
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 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 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_AclTableCreationBeforeLAG(self, dvs): # prepare db and tables self.clean_up_left_over(dvs) db = swsscommon.DBConnector(4, dvs.redis_sock, 0) adb = swsscommon.DBConnector(1, dvs.redis_sock, 0) apldb = swsscommon.DBConnector(0, dvs.redis_sock, 0) # create acl table tbl = swsscommon.Table(db, "ACL_TABLE") bind_ports = ["PortChannel0003"] fvs = swsscommon.FieldValuePairs([("policy_desc", "test_negative"), ("type", "L3"), ("ports", ",".join(bind_ports))]) tbl.set("test_LAG_2", fvs) time.sleep(1) # check acl table in asic db test_acl_table_id = self.get_acl_table_id(dvs, adb) # check acl table group in asic db self.verify_acl_group_num(adb, 0) # get acl table group ids and verify the id numbers atbl = swsscommon.Table(adb, "ASIC_STATE:SAI_OBJECT_TYPE_ACL_TABLE_GROUP") acl_group_ids = atbl.getKeys() assert len(acl_group_ids) == 0 # check acl table group member self.verify_acl_group_member(adb, acl_group_ids, test_acl_table_id) # get lad ids atbl_lag = swsscommon.Table(adb, "ASIC_STATE:SAI_OBJECT_TYPE_LAG") lag_ids = atbl_lag.getKeys() assert len(lag_ids) == 0 # check port binding self.verify_acl_lag_binding(adb, lag_ids) # create port channel ps = swsscommon.ProducerStateTable(apldb, "LAG_TABLE") fvs = swsscommon.FieldValuePairs([("admin", "up"), ("mtu", "1500")]) ps.set("PortChannel0003", fvs) # create port channel member ps = swsscommon.ProducerStateTable(apldb, "LAG_MEMBER_TABLE") fvs = swsscommon.FieldValuePairs([("status", "enabled")]) ps.set("PortChannel0003:Ethernet20", fvs) time.sleep(1) # notify aclorch that port channel configured stdb = swsscommon.DBConnector(6, dvs.redis_sock, 0) ps = swsscommon.ProducerStateTable(stdb, "LAG_TABLE") fvs = swsscommon.FieldValuePairs([("state", "ok")]) ps.set("PortChannel0003", fvs) time.sleep(1) # check acl table in asic db test_acl_table_id = self.get_acl_table_id(dvs, adb) # check acl table group in asic db self.verify_acl_group_num(adb, 1) # get acl table group ids and verify the id numbers atbl = swsscommon.Table(adb, "ASIC_STATE:SAI_OBJECT_TYPE_ACL_TABLE_GROUP") acl_group_ids = atbl.getKeys() assert len(acl_group_ids) == 1 # check acl table group member self.verify_acl_group_member(adb, acl_group_ids, test_acl_table_id) # get lad ids atbl_lag = swsscommon.Table(adb, "ASIC_STATE:SAI_OBJECT_TYPE_LAG") lag_ids = atbl_lag.getKeys() assert len(lag_ids) == 1 # check port binding self.verify_acl_lag_binding(adb, lag_ids) tbl = swsscommon.Table(db, "ACL_TABLE") tbl._del("test_LAG_2")
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 test_CrmNexthopGroupMember(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 dvs.runcmd("ifconfig Ethernet0 10.0.0.0/31 up") dvs.runcmd("ifconfig Ethernet4 10.0.0.2/31 up") dvs.runcmd("crm config polling interval 1") setReadOnlyAttr(dvs, '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) setReadOnlyAttr(dvs, '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") setReadOnlyAttr(dvs, '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
def test_CrmIpv6Route(dvs, testlog): # Enable IPv6 routing dvs.runcmd("sysctl net.ipv6.conf.all.disable_ipv6=0") time.sleep(2) dvs.runcmd("ifconfig Ethernet0 inet6 add fc00::1/126 up") 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") setReadOnlyAttr(dvs, '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) setReadOnlyAttr(dvs, '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") setReadOnlyAttr(dvs, '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
def delete_entry_pst(db, table, key): tbl = swsscommon.ProducerStateTable(db, table) tbl._del(key) time.sleep(1)
def create_fdb(self, vlan, mac, interface): tbl = swsscommon.ProducerStateTable(self.pdb, "FDB_TABLE") fvs = swsscommon.FieldValuePairs([("port", interface), ("type", "dynamic")]) tbl.set("Vlan" + vlan + ":" + mac, fvs) time.sleep(1)
def __init__(self, database: conftest.DVSDatabase, table_name: str): self.table = swsscommon.ProducerStateTable(database.db_connection, table_name)
def remove_fdb(self, vlan, mac): tbl = swsscommon.ProducerStateTable(self.pdb, "FDB_TABLE") tbl._del("Vlan" + vlan + ":" + mac) time.sleep(1)
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") crm_update(dvs, "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() crm_update(dvs, "polling_interval", "2") crm_update(dvs, "fdb_entry_high_threshold", "90") crm_update(dvs, "fdb_entry_threshold_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 create_port_channel_member(self, channel, interface): tbl = swsscommon.ProducerStateTable(self.pdb, "LAG_MEMBER_TABLE") fvs = swsscommon.FieldValuePairs([("status", "enabled")]) tbl.set("PortChannel" + channel + ":" + interface, fvs) time.sleep(1)
def test_CrmResetThresholdExceedCount(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", fvs) intf_tbl.set("Ethernet0|10.0.0.0/31", fvs) dvs.port_admin_set("Ethernet0", "up") crm_update(dvs, "polling_interval", "1") # add static neighbor dvs.runcmd( "ip neigh replace 10.0.0.1 lladdr 11:22:33:44:55:66 dev Ethernet0") db = swsscommon.DBConnector(0, dvs.redis_sock, 0) ps = swsscommon.ProducerStateTable(db, "ROUTE_TABLE") fvs = swsscommon.FieldValuePairs([("nexthop", "10.0.0.1"), ("ifname", "Ethernet0")]) # add route to make sure used count at least 1 and update available counter ps.set("2.2.2.0/24", fvs) dvs.setReadOnlyAttr('SAI_OBJECT_TYPE_SWITCH', 'SAI_SWITCH_ATTR_AVAILABLE_IPV4_ROUTE_ENTRY', '1000') time.sleep(2) # get counters used_counter = getCrmCounterValue(dvs, 'STATS', 'crm_stats_ipv4_route_used') avail_counter = getCrmCounterValue(dvs, 'STATS', 'crm_stats_ipv4_route_available') crm_update(dvs, "ipv4_route_low_threshold", "0") # for changing to free type will rest crm threshold exceed count, previous type can not be same free type crm_update(dvs, "ipv4_route_threshold_type", "percentage") # trigger exceed high threshold of free type marker = dvs.add_log_marker() crm_update(dvs, "ipv4_route_high_threshold", str(avail_counter)) crm_update(dvs, "ipv4_route_threshold_type", "free") time.sleep(20) check_syslog(dvs, marker, "IPV4_ROUTE THRESHOLD_EXCEEDED for TH_FREE", 1) # crm threshold exceed count will be reset when threshold type changed marker = dvs.add_log_marker() crm_update(dvs, "ipv4_route_high_threshold", str(used_counter)) crm_update(dvs, "ipv4_route_threshold_type", "used") time.sleep(2) check_syslog(dvs, marker, "IPV4_ROUTE THRESHOLD_EXCEEDED for TH_USED", 1) # remove route 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") intf_tbl._del("Ethernet0|10.0.0.0/31") time.sleep(2)
def remove_port_channel_member(self, channel, interface): tbl = swsscommon.ProducerStateTable(self.pdb, "LAG_MEMBER_TABLE") tbl._del("PortChannel" + channel + ":" + interface) time.sleep(1)
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) 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, 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, 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) # 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, 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) 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, 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, 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 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, nh_memb_exp_count, nh_oid_map, nhgid, bucket_size) fgnhg_clean_up(config_db, asic_db, app_db, state_db, fg_nhg_name, fg_nhg_prefix, 3) # clean up nh entries 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)) ### 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. Different physical interface type for dynamicitiy. 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) asic_nh_count = len(asic_db.get_keys(ASIC_NH_TB)) 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)) asic_db.wait_for_n_keys(ASIC_NH_TB, asic_nh_count + NUM_NHs) # Program the route 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) # 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) fgnhg_clean_up(config_db, asic_db, app_db, state_db, fg_nhg_name, fg_nhg_prefix, 6) # clean up nh entries 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, ip_pref_key) remove_entry(config_db, IF_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))
def test_add_remove_trap(self, dvs): """Test steps: 1. Enable trap_flow_counter 2. Remove a COPP trap 3. Verify counter is automatically unbind 4. Add the COPP trap back 5. Verify counter is added back Args: dvs (object): virtual switch object """ self.setup_dbs(dvs) meta_data = counter_group_meta['trap_flow_counter'] self.set_flex_counter_group_status(meta_data['key'], meta_data['name_map']) removed_trap = None changed_group = None trap_ids = None copp_groups = self.app_db.db_connection.keys('COPP_TABLE:*') for copp_group in copp_groups: trap_ids = self.app_db.db_connection.hget(copp_group, 'trap_ids') if trap_ids and ',' in trap_ids: trap_ids = [x.strip() for x in trap_ids.split(',')] removed_trap = trap_ids.pop() changed_group = copp_group.split(':')[1] break if not removed_trap: pytest.skip( 'There is not copp group with more than 1 traps, skip rest of the test' ) oid = None for _ in range(NUMBER_OF_RETRIES): counters_keys = self.counters_db.db_connection.hgetall( meta_data['name_map']) if removed_trap in counters_keys: oid = counters_keys[removed_trap] break else: time.sleep(1) assert oid, 'trap counter is not created for {}'.format(removed_trap) self.wait_for_id_list(meta_data['group_name'], removed_trap, oid) app_copp_table = swsscommon.ProducerStateTable( self.app_db.db_connection, 'COPP_TABLE') app_copp_table.set(changed_group, [('trap_ids', ','.join(trap_ids))]) self.wait_for_id_list_remove(meta_data['group_name'], removed_trap, oid) counters_keys = self.counters_db.db_connection.hgetall( meta_data['name_map']) assert removed_trap not in counters_keys trap_ids.append(removed_trap) app_copp_table.set(changed_group, [('trap_ids', ','.join(trap_ids))]) oid = None for _ in range(NUMBER_OF_RETRIES): counters_keys = self.counters_db.db_connection.hgetall( meta_data['name_map']) if removed_trap in counters_keys: oid = counters_keys[removed_trap] break else: time.sleep(1) assert oid, 'Add trap {}, but trap counter is not created'.format( removed_trap) self.wait_for_id_list(meta_data['group_name'], removed_trap, oid) self.set_flex_counter_group_status(meta_data['key'], meta_data['name_map'], 'disable')
def create_and_test_tunnel(self, db, asicdb, tunnel_name, **kwargs): """ Create tunnel and verify all needed enties in ASIC DB exists """ is_symmetric_tunnel = "src_ip" in kwargs decap_dscp_to_tc_map_oid = None decap_tc_to_pg_map_oid = None skip_tunnel_creation = False if "decap_dscp_to_tc_map_oid" in kwargs: decap_dscp_to_tc_map_oid = kwargs.pop("decap_dscp_to_tc_map_oid") if "decap_tc_to_pg_map_oid" in kwargs: decap_tc_to_pg_map_oid = kwargs.pop("decap_tc_to_pg_map_oid") if "skip_tunnel_creation" in kwargs: skip_tunnel_creation = kwargs.pop("skip_tunnel_creation") if not skip_tunnel_creation: fvs = create_fvs(**kwargs) # create tunnel entry in DB ps = swsscommon.ProducerStateTable( db, self.APP_TUNNEL_DECAP_TABLE_NAME) ps.set(tunnel_name, fvs) # wait till config will be applied time.sleep(1) # check asic db table tunnel_table = swsscommon.Table(asicdb, self.ASIC_TUNNEL_TABLE) tunnels = tunnel_table.getKeys() assert len(tunnels) == 1 tunnel_sai_obj = tunnels[0] status, fvs = tunnel_table.get(tunnel_sai_obj) assert status == True # 6 parameters to check in case of decap tunnel # + 1 (SAI_TUNNEL_ATTR_ENCAP_SRC_IP) in case of symmetric tunnel expected_len = 7 if is_symmetric_tunnel else 6 expected_ecn_mode = self.ecn_modes_map[kwargs["ecn_mode"]] expected_dscp_mode = self.dscp_modes_map[kwargs["dscp_mode"]] expected_ttl_mode = self.ttl_modes_map[kwargs["ttl_mode"]] if decap_dscp_to_tc_map_oid: expected_len += 1 if decap_tc_to_pg_map_oid: expected_len += 1 assert len(fvs) == expected_len for field, value in fvs: if field == "SAI_TUNNEL_ATTR_TYPE": assert value == "SAI_TUNNEL_TYPE_IPINIP" elif field == "SAI_TUNNEL_ATTR_ENCAP_SRC_IP": assert value == kwargs["src_ip"] elif field == "SAI_TUNNEL_ATTR_DECAP_ECN_MODE": assert value == expected_ecn_mode elif field == "SAI_TUNNEL_ATTR_DECAP_TTL_MODE": assert value == expected_ttl_mode elif field == "SAI_TUNNEL_ATTR_DECAP_DSCP_MODE": assert value == expected_dscp_mode elif field == "SAI_TUNNEL_ATTR_OVERLAY_INTERFACE": assert self.check_interface_exists_in_asicdb(asicdb, value) elif field == "SAI_TUNNEL_ATTR_UNDERLAY_INTERFACE": assert self.check_interface_exists_in_asicdb(asicdb, value) elif field == "SAI_TUNNEL_ATTR_DECAP_QOS_DSCP_TO_TC_MAP": assert value == decap_dscp_to_tc_map_oid elif field == "SAI_TUNNEL_ATTR_DECAP_QOS_TC_TO_PRIORITY_GROUP_MAP": assert value == decap_tc_to_pg_map_oid else: assert False, "Field %s is not tested" % field src_ip = kwargs["src_ip"] if "src_ip" in kwargs else None self.check_tunnel_termination_entry_exists_in_asicdb( asicdb, tunnel_sai_obj, kwargs["dst_ip"].split(","), src_ip)
def create_entry_pst(self, db, table, key, pairs): tbl = swsscommon.ProducerStateTable(db, table) self.create_entry(tbl, key, pairs)
def remove_neighbor(self, interface, ip): tbl = swsscommon.ProducerStateTable(self.pdb, "NEIGH_TABLE") tbl._del(interface + ":" + ip) time.sleep(1)
def remove_entry_pst(self, db, table, key): tbl = swsscommon.ProducerStateTable(db, table) self.remove_entry(tbl, key)
def test_CrmIpv4Route(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", fvs) intf_tbl.set("Ethernet0|10.0.0.0/31", fvs) dvs.runcmd("ifconfig Ethernet0 up") dvs.runcmd("crm config polling interval 1") setReadOnlyAttr(dvs, 'SAI_OBJECT_TYPE_SWITCH', 'SAI_SWITCH_ATTR_AVAILABLE_IPV4_ROUTE_ENTRY', '1000') # add static neighbor dvs.runcmd( "ip neigh replace 10.0.0.1 lladdr 11:22:33:44:55:66 dev Ethernet0") db = swsscommon.DBConnector(0, dvs.redis_sock, 0) ps = swsscommon.ProducerStateTable(db, "ROUTE_TABLE") fvs = swsscommon.FieldValuePairs([("nexthop", "10.0.0.1"), ("ifname", "Ethernet0")]) time.sleep(2) # get counters used_counter = getCrmCounterValue(dvs, 'STATS', 'crm_stats_ipv4_route_used') avail_counter = getCrmCounterValue(dvs, 'STATS', 'crm_stats_ipv4_route_available') # add route and update available counter ps.set("2.2.2.0/24", fvs) setReadOnlyAttr(dvs, 'SAI_OBJECT_TYPE_SWITCH', 'SAI_SWITCH_ATTR_AVAILABLE_IPV4_ROUTE_ENTRY', '999') time.sleep(2) # get counters new_used_counter = getCrmCounterValue(dvs, 'STATS', 'crm_stats_ipv4_route_used') new_avail_counter = getCrmCounterValue( dvs, 'STATS', 'crm_stats_ipv4_route_available') assert new_used_counter - used_counter == 1 assert avail_counter - new_avail_counter == 1 # 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") setReadOnlyAttr(dvs, 'SAI_OBJECT_TYPE_SWITCH', 'SAI_SWITCH_ATTR_AVAILABLE_IPV4_ROUTE_ENTRY', '1000') time.sleep(2) # get counters new_used_counter = getCrmCounterValue(dvs, 'STATS', 'crm_stats_ipv4_route_used') new_avail_counter = getCrmCounterValue( dvs, 'STATS', 'crm_stats_ipv4_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 ipv4 route high 90") dvs.runcmd("crm config thresholds ipv4 route type free") time.sleep(2) check_syslog(dvs, marker, "IPV4_ROUTE THRESHOLD_EXCEEDED for TH_FREE", 1) intf_tbl._del("Ethernet0|10.0.0.0/31") time.sleep(2)
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)