diff --git a/cfgmgr/portmgr.cpp b/cfgmgr/portmgr.cpp index 94a1994310f7..21d0893668f3 100644 --- a/cfgmgr/portmgr.cpp +++ b/cfgmgr/portmgr.cpp @@ -151,6 +151,11 @@ void PortMgr::doTask(Consumer &consumer) SWSS_LOG_NOTICE("Configure %s MAC learn mode to %s", alias.c_str(), learn_mode.c_str()); } } + else if (op == DEL_COMMAND) + { + SWSS_LOG_NOTICE("Delete Port: %s", alias.c_str()); + m_appPortTable.del(alias); + } it = consumer.m_toSync.erase(it); } diff --git a/orchagent/portsorch.cpp b/orchagent/portsorch.cpp index 66750c59e82b..f190df110fa1 100644 --- a/orchagent/portsorch.cpp +++ b/orchagent/portsorch.cpp @@ -24,6 +24,7 @@ #include "crmorch.h" #include "countercheckorch.h" #include "notifier.h" +#include "redisclient.h" extern sai_switch_api_t *sai_switch_api; extern sai_bridge_api_t *sai_bridge_api; @@ -1427,6 +1428,7 @@ bool PortsOrch::addPort(const set &lane_set, uint32_t speed, int an, string } m_portListLaneMap[lane_set] = port_id; + m_portCount++; SWSS_LOG_NOTICE("Create port %" PRIx64 " with the speed %u", port_id, speed); @@ -1450,7 +1452,10 @@ bool PortsOrch::removePort(sai_object_id_t port_id) SWSS_LOG_ERROR("Failed to remove port %" PRIx64 ", rv:%d", port_id, status); return false; } + removeAclTableGroup(p); + + m_portCount--; SWSS_LOG_NOTICE("Remove port %" PRIx64, port_id); return true; @@ -1528,6 +1533,24 @@ bool PortsOrch::initPort(const string &alias, const set &lane_set) return true; } +void PortsOrch::deInitPort(string alias, sai_object_id_t port_id) +{ + SWSS_LOG_ENTER(); + + Port p(alias, Port::PHY); + p.m_port_id = port_id; + + /* remove port from flex_counter_table for updating counters */ + port_stat_manager.clearCounterIdList(p.m_port_id); + + /* remove port name map from counter table */ + RedisClient redisClient(m_counter_db.get()); + redisClient.hdel(COUNTERS_PORT_NAME_MAP, alias); + + SWSS_LOG_NOTICE("De-Initialized port %s", alias.c_str()); +} + + bool PortsOrch::bake() { SWSS_LOG_ENTER(); @@ -1594,6 +1617,35 @@ void PortsOrch::cleanPortTable(const vector& keys) } } +void PortsOrch::removePortFromLanesMap(string alias) +{ + + for (auto it = m_lanesAliasSpeedMap.begin(); it != m_lanesAliasSpeedMap.end(); it++) + { + if (get<0>(it->second) == alias) + { + SWSS_LOG_NOTICE("Removing port %s from lanes map", alias.c_str()); + it = m_lanesAliasSpeedMap.erase(it); + break; + } + } +} + +void PortsOrch::removePortFromPortListMap(sai_object_id_t port_id) +{ + + for (auto it = m_portListLaneMap.begin(); it != m_portListLaneMap.end(); it++) + { + if (it->second == port_id) + { + SWSS_LOG_NOTICE("Removing port-id %lx from port list map", port_id); + it = m_portListLaneMap.erase(it); + break; + } + } +} + + void PortsOrch::doPortTask(Consumer &consumer) { SWSS_LOG_ENTER(); @@ -1754,7 +1806,7 @@ void PortsOrch::doPortTask(Consumer &consumer) * 2. Create new ports * 3. Initialize all ports */ - if (m_portConfigState == PORT_CONFIG_RECEIVED && (m_lanesAliasSpeedMap.size() == m_portCount)) + if (m_portConfigState == PORT_CONFIG_RECEIVED || m_portConfigState == PORT_CONFIG_DONE) { for (auto it = m_portListLaneMap.begin(); it != m_portListLaneMap.end();) { @@ -1797,7 +1849,7 @@ void PortsOrch::doPortTask(Consumer &consumer) } } - it = m_lanesAliasSpeedMap.erase(it); + it++; } m_portConfigState = PORT_CONFIG_DONE; @@ -2086,6 +2138,31 @@ void PortsOrch::doPortTask(Consumer &consumer) } } } + else if (op == DEL_COMMAND) + { + SWSS_LOG_NOTICE("Deleting Port %s", alias.c_str()); + auto port_id = m_portList[alias].m_port_id; + auto hif_id = m_portList[alias].m_hif_id; + + deInitPort(alias, port_id); + + SWSS_LOG_NOTICE("Removing hostif %lx for Port %s", hif_id, alias.c_str()); + sai_status_t status = sai_hostif_api->remove_hostif(hif_id); + if (status != SAI_STATUS_SUCCESS) + { + throw runtime_error("Remove hostif for the port failed"); + } + + if (!removePort(port_id)) + { + throw runtime_error("Delete port failed"); + } + removePortFromLanesMap(alias); + removePortFromPortListMap(port_id); + + /* Delete port from port list */ + m_portList.erase(alias); + } else { SWSS_LOG_ERROR("Unknown operation type %s", op.c_str()); diff --git a/orchagent/portsorch.h b/orchagent/portsorch.h index b35c050bfc43..72444c549ace 100644 --- a/orchagent/portsorch.h +++ b/orchagent/portsorch.h @@ -149,6 +149,8 @@ class PortsOrch : public Orch, public Subject void doTask(NotificationConsumer &consumer); + void removePortFromLanesMap(string alias); + void removePortFromPortListMap(sai_object_id_t port_id); void removeDefaultVlanMembers(); void removeDefaultBridgePorts(); @@ -179,6 +181,7 @@ class PortsOrch : public Orch, public Subject bool addPort(const set &lane_set, uint32_t speed, int an=0, string fec=""); bool removePort(sai_object_id_t port_id); bool initPort(const string &alias, const set &lane_set); + void deInitPort(string alias, sai_object_id_t port_id); bool setPortAdminStatus(sai_object_id_t id, bool up); bool getPortAdminStatus(sai_object_id_t id, bool& up); diff --git a/portsyncd/linksync.cpp b/portsyncd/linksync.cpp index bf39f8f0012c..d12410c91c7a 100644 --- a/portsyncd/linksync.cpp +++ b/portsyncd/linksync.cpp @@ -155,6 +155,8 @@ LinkSync::LinkSync(DBConnector *appl_db, DBConnector *state_db) : void LinkSync::onMsg(int nlmsg_type, struct nl_object *obj) { + SWSS_LOG_ENTER(); + if ((nlmsg_type != RTM_NEWLINK) && (nlmsg_type != RTM_DELLINK)) { return; @@ -209,6 +211,14 @@ void LinkSync::onMsg(int nlmsg_type, struct nl_object *obj) return; } + /* If netlink for this port has master, we ignore that for now + * This could be the case where the port was removed from VLAN bridge + */ + if (master) + { + return; + } + /* In the event of swss restart, it is possible to get netlink messages during bridge * delete, interface delete etc which are part of cleanup. These netlink messages for * the front-panel interface must not be published or it will update the statedb with @@ -226,27 +236,24 @@ void LinkSync::onMsg(int nlmsg_type, struct nl_object *obj) /* Insert or update the ifindex to key map */ m_ifindexNameMap[ifindex] = key; + if (nlmsg_type == RTM_DELLINK) + { + m_statePortTable.del(key); + SWSS_LOG_NOTICE("Delete %s(ok) from state db", key.c_str()); + return; + } + /* front panel interfaces: Check if the port is in the PORT_TABLE * non-front panel interfaces such as eth0, lo which are not in the * PORT_TABLE are ignored. */ vector temp; if (m_portTable.get(key, temp)) { - /* TODO: When port is removed from the kernel */ - if (nlmsg_type == RTM_DELLINK) - { - return; - } - - /* Host interface is created */ - if (!g_init && g_portSet.find(key) != g_portSet.end()) - { - g_portSet.erase(key); - FieldValueTuple tuple("state", "ok"); - vector vector; - vector.push_back(tuple); - m_statePortTable.set(key, vector); - SWSS_LOG_INFO("Publish %s(ok) to state db", key.c_str()); - } + g_portSet.erase(key); + FieldValueTuple tuple("state", "ok"); + vector vector; + vector.push_back(tuple); + m_statePortTable.set(key, vector); + SWSS_LOG_NOTICE("Publish %s(ok) to state db", key.c_str()); } } diff --git a/tests/conftest.py b/tests/conftest.py index 65d954a9a768..a06de3cecf8b 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -77,8 +77,8 @@ def __init__(self, dvs): class ApplDbValidator(object): def __init__(self, dvs): - appl_db = swsscommon.DBConnector(swsscommon.APPL_DB, dvs.redis_sock, 0) - self.neighTbl = swsscommon.Table(appl_db, "NEIGH_TABLE") + self.appl_db = swsscommon.DBConnector(swsscommon.APPL_DB, dvs.redis_sock, 0) + self.neighTbl = swsscommon.Table(self.appl_db, "NEIGH_TABLE") def __del__(self): # Make sure no neighbors on physical interfaces @@ -155,13 +155,14 @@ def __init__(self, name=None, imgname=None, keeptb=False, fakeplatform=None): 'vrfmgrd', 'portmgrd'] self.syncd = ['syncd'] - self.rtd = ['fpmsyncd', 'zebra'] + self.rtd = ['fpmsyncd', 'zebra', 'staticd'] self.teamd = ['teamsyncd', 'teammgrd'] # FIXME: We need to verify that NAT processes are running, once the # appropriate changes are merged into sonic-buildimage # self.natd = ['natsyncd', 'natmgrd'] self.alld = self.basicd + self.swssd + self.syncd + self.rtd + self.teamd # + self.natd self.client = docker.from_env() + self.appldb = None if subprocess.check_call(["/sbin/modprobe", "team"]) != 0: raise NameError("cannot install kernel team module") @@ -199,7 +200,7 @@ def __init__(self, name=None, imgname=None, keeptb=False, fakeplatform=None): self.mount = "/var/run/redis-vs/{}".format(ctn_sw_name) self.net_cleanup() - self.restart() + self.ctn_restart() else: self.ctn_sw = self.client.containers.run('debian:jessie', privileged=True, detach=True, command="bash", stdin_open=True) @@ -224,8 +225,20 @@ def __init__(self, name=None, imgname=None, keeptb=False, fakeplatform=None): network_mode="container:%s" % self.ctn_sw.name, volumes={ self.mount: { 'bind': '/var/run/redis', 'mode': 'rw' } }) - self.appldb = None self.redis_sock = self.mount + '/' + "redis.sock" + self.check_ctn_status_and_db_connect() + + def destroy(self): + if self.appldb: + del self.appldb + if self.cleanup: + self.ctn.remove(force=True) + self.ctn_sw.remove(force=True) + os.system("rm -rf {}".format(self.mount)) + for s in self.servers: + s.destroy() + + def check_ctn_status_and_db_connect(self): try: # temp fix: remove them once they are moved to vs start.sh self.ctn.exec_run("sysctl -w net.ipv6.conf.default.disable_ipv6=0") @@ -239,15 +252,6 @@ def __init__(self, name=None, imgname=None, keeptb=False, fakeplatform=None): self.destroy() raise - def destroy(self): - if self.appldb: - del self.appldb - if self.cleanup: - self.ctn.remove(force=True) - self.ctn_sw.remove(force=True) - os.system("rm -rf {}".format(self.mount)) - for s in self.servers: - s.destroy() def check_ready(self, timeout=30): '''check if all processes in the dvs is ready''' @@ -314,15 +318,22 @@ def net_cleanup(self): print "remove extra link {}".format(pname) return - def restart(self): + def ctn_restart(self): self.ctn.restart() + def restart(self): + if self.appldb: + del self.appldb + self.ctn_restart() + self.check_ctn_status_and_db_connect() + # start processes in SWSS def start_swss(self): cmd = "" for pname in self.swssd: cmd += "supervisorctl start {}; ".format(pname) self.runcmd(['sh', '-c', cmd]) + time.sleep(5) # stop processes in SWSS def stop_swss(self): @@ -839,3 +850,25 @@ def testlog(request, dvs): dvs.runcmd("logger === start test %s ===" % request.node.name) yield testlog dvs.runcmd("logger === finish test %s ===" % request.node.name) + +##################### DPB fixtures ########################################### +@pytest.yield_fixture(scope="module") +def create_dpb_config_file(dvs): + cmd = "sonic-cfggen -j /etc/sonic/init_cfg.json -j /tmp/ports.json --print-data > /tmp/dpb_config_db.json" + dvs.runcmd(['sh', '-c', cmd]) + cmd = "mv /etc/sonic/config_db.json /etc/sonic/config_db.json.bak" + dvs.runcmd(cmd) + cmd = "cp /tmp/dpb_config_db.json /etc/sonic/config_db.json" + dvs.runcmd(cmd) + +@pytest.yield_fixture(scope="module") +def remove_dpb_config_file(dvs): + cmd = "mv /etc/sonic/config_db.json.bak /etc/sonic/config_db.json" + dvs.runcmd(cmd) + +@pytest.yield_fixture(scope="module") +def dpb_setup_fixture(dvs): + create_dpb_config_file(dvs) + dvs.restart() + yield + remove_dpb_config_file(dvs) diff --git a/tests/port_dpb.py b/tests/port_dpb.py new file mode 100644 index 000000000000..97abdf975a25 --- /dev/null +++ b/tests/port_dpb.py @@ -0,0 +1,302 @@ +from swsscommon import swsscommon +import redis +import time +import os +import pytest +from pytest import * +import json +import re + +class Port(): + def __init__(self, dvs, name = None): + self._name = name + if name != None: + self._port_num = int(re.compile(r'(\d+)$').search(self._name).group(1)) + self._alias = None + self._speed = None + self._lanes = [] + self._index = None + self._lanes_db_str = None + self._lanes_asic_db_str = None + self._oid = None + self._dvs = dvs + self._cfg_db = swsscommon.DBConnector(swsscommon.CONFIG_DB, dvs.redis_sock, 0) + self._cfg_db_ptbl = swsscommon.Table(self._cfg_db, "PORT") + self._app_db = swsscommon.DBConnector(swsscommon.APPL_DB, dvs.redis_sock, 0) + self._app_db_ptbl = swsscommon.Table(self._app_db, swsscommon.APP_PORT_TABLE_NAME) + self._asic_db = swsscommon.DBConnector(swsscommon.ASIC_DB, dvs.redis_sock, 0) + self._asic_db_ptbl = swsscommon.Table(self._asic_db, "ASIC_STATE:SAI_OBJECT_TYPE_PORT") + self._counters_db = redis.Redis(unix_socket_path=self._dvs.redis_sock, db=swsscommon.COUNTERS_DB) + + def set_name(self, name): + self._name = name + self._port_num = int(re.compile(r'(\d+)$').search(self._name).group(1)) + + def set_speed(self, speed): + self._speed = speed + + def set_alias(self, alias): + self._alias = alias + + def set_lanes(self, lanes): + self._lanes = lanes + lanes_list = [] + for lane in lanes: + lanes_list.append(int(lane)) + lanes_list.sort() + self._lanes_db_str = str(lanes_list)[1:-1] + self._lanes_db_str = self._lanes_db_str.replace(" ","") + self._lanes_asic_db_str = str(len(lanes)) + ":" + self._lanes_db_str + self._lanes_asic_db_str = self._lanes_asic_db_str.replace(" ", "") + + def set_index(self, index): + self._index = index + + def set_oid(self, oid = None): + self._oid = oid + + def get_speed(self): + return self._speed + + def get_alias(self): + return self._alias + + def get_lanes(self): + return self._lanes + + def get_num_lanes(self): + return len(self._lanes) + + def get_index(self): + return self._index + + def get_name(self): + return self._name + + def get_port_num(self): + return self._port_num + + def get_lanes_db_str(self): + return self._lanes_db_str + + def get_lanes_asic_db_str(self): + return self._lanes_asic_db_str + + def get_oid(self): + return self._oid + + def print_port(self): + print "Port: %s Lanes: %s Speed: %d, Index: %d"%(self._name, self._lanes, self._speed, self._index) + + def port_merge(self, child_ports): + child_ports.sort(key=lambda x: x.get_port_num()) + self.set_name(child_ports[0].get_name()) + speed = 0 + for cp in child_ports: + speed = speed + cp.get_speed() + self.set_speed(speed) + self.set_alias(child_ports[0].get_alias().rsplit(',',1)[0]) + self.set_index(child_ports[0].get_index()) + lanes =[] + for cp in child_ports: + for l in cp.get_lanes(): + lanes.append(l) + self.set_lanes(lanes) + + + def port_split(self, child_ports): + if child_ports == 1: + return self + child_port_list = [] + port_num = self.get_port_num() + num_lanes = len(self._lanes) + offset = num_lanes/child_ports; + lanes_per_child = offset + for i in range(child_ports): + child_port_num = port_num + (i * offset) + child_port_name = "Ethernet%d"%(child_port_num) + child_port_alias = "Eth%d/%d"%(port_num, child_port_num) + child_port_lanes = [] + for j in range(lanes_per_child): + child_port_lanes.append(self._lanes[(i*offset)+j]) + child_port_speed = self._speed/child_ports + child_port_index = self._index + + child_port = Port(self._dvs, child_port_name) + child_port.set_alias(child_port_alias) + child_port.set_speed(child_port_speed) + child_port.set_lanes(child_port_lanes) + child_port.set_index(child_port_index) + child_port_list.append(child_port) + return child_port_list + + def delete_from_config_db(self): + self._cfg_db_ptbl._del(self.get_name()) + self._oid = None + time.sleep(2) + + def sync_from_config_db(self): + (status, fvs) = self._cfg_db_ptbl.get(self.get_name()) + assert status == True + fvs_dict = self.get_fvs_dict(fvs) + self.set_alias(fvs_dict['alias']) + self.set_speed(int(fvs_dict['speed'])) + self.set_lanes(list(fvs_dict['lanes'].split(","))) + self.set_index(int(fvs_dict['index'])) + + def write_to_config_db(self): + lanes_str = self.get_lanes_db_str() + index_str = str(self.get_index()) + alias_str = self.get_alias() + speed_str = str(self.get_speed()) + fvs = swsscommon.FieldValuePairs([("alias", alias_str), + ("lanes", lanes_str), + ("speed", speed_str), + ("index", index_str)]) + self._cfg_db_ptbl.set(self.get_name(), fvs) + time.sleep(1) + + def get_fvs_dict(self, fvs): + fvs_dict = {} + for fv in fvs: + fvs_dict.update({fv[0]:fv[1]}) + return fvs_dict + + def exists_in_config_db(self): + (status, _) = self._cfg_db_ptbl.get(self.get_name()) + return status + + def exists_in_app_db(self): + (status, _) = self._app_db_ptbl.get(self.get_name()) + return status + + def sync_oid(self): + self._oid = self._counters_db.hget("COUNTERS_PORT_NAME_MAP", self.get_name()) + + def exists_in_asic_db(self): + self.sync_oid() + if self._oid is None: + return False + (status, _) = self._asic_db_ptbl.get(self._oid) + return status + + def verify_config_db(self): + (status, fvs) = self._cfg_db_ptbl.get(self.get_name()) + assert(status == True) + fvs_dict = self.get_fvs_dict(fvs) + assert(fvs_dict['alias'] == self.get_alias()) + assert(fvs_dict['lanes'] == self.get_lanes_db_str()) + assert(fvs_dict['speed'] == str(self.get_speed())) + assert(fvs_dict['index'] == str(self.get_index())) + + def verify_app_db(self): + (status, fvs) = self._app_db_ptbl.get(self.get_name()) + assert(status == True) + fvs_dict = self.get_fvs_dict(fvs) + assert(fvs_dict['alias'] == self.get_alias()) + assert(fvs_dict['lanes'] == self.get_lanes_db_str()) + assert(fvs_dict['speed'] == str(self.get_speed())) + assert(fvs_dict['index'] == str(self.get_index())) + + def verify_asic_db(self): + self.sync_oid() + (status, fvs) = self._asic_db_ptbl.get(self.get_oid()) + assert(status == True) + fvs_dict = self.get_fvs_dict(fvs) + if (fvs_dict.has_key("SAI_PORT_ATTR_HW_LANE_LIST")): + assert(fvs_dict['SAI_PORT_ATTR_HW_LANE_LIST'] == self.get_lanes_asic_db_str()) + assert(fvs_dict['SAI_PORT_ATTR_SPEED'] == str(self.get_speed())) + +class DPB(): + def breakin(self, dvs, port_names): + child_ports = [] + for pname in port_names: + cp = Port(dvs, pname) + cp.sync_from_config_db() + child_ports.append(cp) + + for cp in child_ports: + cp.delete_from_config_db() + # TBD, need vs lib to support removing hostif + #dvs.runcmd("ip link delete " + cp.get_name()) + #print "Deleted child ports:%s from config DB"%port_names + + time.sleep(6) + + for cp in child_ports: + assert(cp.exists_in_config_db() == False) + for cp in child_ports: + assert(cp.exists_in_app_db() == False) + for cp in child_ports: + assert(cp.exists_in_asic_db() == False) + #print "Verified child ports are deleted from all DBs" + + p = Port(dvs) + p.port_merge(child_ports) + p.write_to_config_db() + #print "Added port:%s to config DB"%p.get_name() + time.sleep(2) + + p.verify_config_db() + #print "Config DB verification passed!" + + p.verify_app_db() + #print "Application DB verification passed!" + + p.verify_asic_db() + #print "ASIC DB verification passed!" + + def create_child_ports(self, dvs, p, num_child_ports): + # Create child ports and write to config DB + child_ports = p.port_split(num_child_ports) + child_port_names = [] + for cp in child_ports: + cp.write_to_config_db() + child_port_names.append(cp.get_name()) + #print "Added child ports:%s to config DB"%child_port_names + time.sleep(6) + + for cp in child_ports: + assert(cp.exists_in_config_db() == True) + cp.verify_config_db() + #print "Config DB verification passed" + for cp in child_ports: + assert(cp.exists_in_app_db() == True) + cp.verify_app_db() + #print "APP DB verification passed" + for cp in child_ports: + assert(cp.exists_in_asic_db() == True) + cp.verify_asic_db() + #print "ASIC DB verification passed" + + def breakout(self, dvs, port_name, num_child_ports): + + p = Port(dvs, port_name) + p.sync_from_config_db() + + # Delete port from config DB and kernel + p.delete_from_config_db() + # TBD, need vs lib to support hostif removal + #dvs.runcmd("ip link delete " + p.get_name()) + #print "Deleted port:%s from config DB"%port_name + time.sleep(6) + + # Verify port is deleted from all DBs + assert(p.exists_in_config_db() == False) + assert(p.exists_in_app_db() == False) + assert(p.exists_in_asic_db() == False) + + self.create_child_ports(dvs, p, num_child_ports) + + + def change_speed_and_verify(self, dvs, port_names, speed = 100000): + for port_name in port_names: + p = Port(dvs, port_name) + p.sync_from_config_db() + p.set_speed(speed) + p.write_to_config_db() + p.verify_config_db() + time.sleep(1) + p.verify_app_db() + time.sleep(1) + p.verify_asic_db() diff --git a/tests/test_acl.py b/tests/test_acl.py index 86ebb3f36ec1..fa571aed115c 100644 --- a/tests/test_acl.py +++ b/tests/test_acl.py @@ -5,7 +5,6 @@ from swsscommon import swsscommon - class BaseTestAcl(object): """ base class with helpers for Test classes """ def setup_db(self, dvs): diff --git a/tests/test_port_config.py b/tests/test_port_config.py index da07abd73c14..4698fde93c77 100644 --- a/tests/test_port_config.py +++ b/tests/test_port_config.py @@ -36,25 +36,25 @@ def getVIDfromRID(self, dvs, port_rid): asic_r = redis.Redis(unix_socket_path=dvs.redis_sock, db=swsscommon.ASIC_DB) return asic_r.hget("RIDTOVID", port_rid); - def test_port_hw_lane(self, dvs): app_db = swsscommon.DBConnector(swsscommon.APPL_DB, dvs.redis_sock, 0) - port_tbl = swsscommon.Table(app_db, "PORT_TABLE") + app_db_ptbl = swsscommon.Table(app_db, "PORT_TABLE") + asic_db = swsscommon.DBConnector(swsscommon.ASIC_DB, dvs.redis_sock, 0) + asic_db_lanes_tbl = swsscommon.Table(asic_db, "LANES") - asic_r = redis.Redis(unix_socket_path=dvs.redis_sock, db=swsscommon.ASIC_DB) - num_lanes = asic_r.hlen("LANES") - for i in range(1, num_lanes+1): - port_rid = asic_r.hget("LANES", i) + lanes = asic_db_lanes_tbl.get('')[1] + num_lanes = len(lanes) + for lane in lanes: + lane_num = lane[0]; + port_rid = lane[1]; port_vid = self.getVIDfromRID(dvs, port_rid) port_name = self.getPortName(dvs, port_vid) - - (status, fvs) = port_tbl.get(port_name) + (status, fvs) = app_db_ptbl.get(port_name) assert status == True for fv in fvs: if fv[0] == "lanes": - assert str(i) in list(fv[1].split(",")) - + assert str(lane_num) in list(fv[1].split(",")) def test_port_breakout(self, dvs, port_config): diff --git a/tests/test_port_dpb.py b/tests/test_port_dpb.py new file mode 100644 index 000000000000..316f83ab4841 --- /dev/null +++ b/tests/test_port_dpb.py @@ -0,0 +1,96 @@ +from swsscommon import swsscommon +import redis +import time +import os +import pytest +from pytest import * +import json +import re +from port_dpb import DPB + +@pytest.mark.usefixtures('dpb_setup_fixture') +class TestPortDPB(object): + + ''' + |-------------------------------------------------- + | | 1X100G | 1X40G | 4X10G | 4X25G | 2X50G | + |-------------------------------------------------- + | 1X100G | NA | P | P | P | P | + |-------------------------------------------------- + | 1X40G | P | NA | P | P | | + |-------------------------------------------------- + | 4X10G | P | P | NA | P | | + |-------------------------------------------------- + | 4X25G | P | P | P | NA | | + |-------------------------------------------------- + | 2X50G | P | | | | NA | + |-------------------------------------------------- + NA --> Not Applicable + P --> Pass + F --> Fail + Empty --> Not Tested + ''' + + ''' + @pytest.mark.skip() + ''' + def test_port_breakout_one(self, dvs): + dpb = DPB() + dpb.breakout(dvs, "Ethernet0", 4) + #print "**** 1X40G --> 4X10G passed ****" + dpb.change_speed_and_verify(dvs, ["Ethernet0", "Ethernet1", "Ethernet2", "Ethernet3"], 25000) + #print "**** 4X10G --> 4X25G passed ****" + dpb.change_speed_and_verify(dvs, ["Ethernet0", "Ethernet1", "Ethernet2", "Ethernet3"], 10000) + #print "**** 4X25G --> 4X10G passed ****" + dpb.breakin(dvs, ["Ethernet0", "Ethernet1", "Ethernet2", "Ethernet3"]) + #print "**** 4X10G --> 1X40G passed ****" + dpb.change_speed_and_verify(dvs, ["Ethernet0"], 100000) + #print "**** 1X40G --> 1X100G passed ****" + dpb.breakout(dvs, "Ethernet0", 4) + #print "**** 1X100G --> 4X25G passed ****" + dpb.change_speed_and_verify(dvs, ["Ethernet0", "Ethernet1", "Ethernet2", "Ethernet3"], 10000) + #print "**** 4X25G --> 4X10G passed ****" + dpb.change_speed_and_verify(dvs, ["Ethernet0", "Ethernet1", "Ethernet2", "Ethernet3"], 25000) + #print "**** 4X10G --> 4X25G passed ****" + dpb.breakin(dvs, ["Ethernet0", "Ethernet1", "Ethernet2", "Ethernet3"]) + #print "**** 4X25G --> 1X100G passed ****" + dpb.breakout(dvs, "Ethernet0", 2) + #print "**** 1X100G --> 2X50G passed ****" + dpb.breakin(dvs, ["Ethernet0", "Ethernet2"]) + #print "**** 2X50G --> 1X100G passed ****" + dpb.change_speed_and_verify(dvs, ["Ethernet0"], 40000) + #print "**** 1X100G --> 1X40G passed ****" + + ''' + @pytest.mark.skip() + ''' + def test_port_breakout_multiple(self, dvs): + dpb = DPB() + port_names = ["Ethernet0", "Ethernet12", "Ethernet64", "Ethernet112"] + for pname in port_names: + dpb.breakout(dvs, pname, 4) + dpb.breakin(dvs, ["Ethernet0", "Ethernet1", "Ethernet2", "Ethernet3"]) + dpb.breakin(dvs, ["Ethernet12", "Ethernet13", "Ethernet14", "Ethernet15"]) + dpb.breakin(dvs, ["Ethernet64", "Ethernet65", "Ethernet66", "Ethernet67"]) + dpb.breakin(dvs, ["Ethernet112", "Ethernet113", "Ethernet114", "Ethernet115"]) + + @pytest.mark.skip() + def test_port_breakout_all(self, dvs): + dpb = DPB() + port_names = [] + for i in range(32): + pname = "Ethernet" + str(i*4) + port_names.append(pname) + + for pname in port_names: + dpb.breakout(dvs, pname, 4) + + child_port_names = [] + for i in range(128): + cpname = "Ethernet" + str(i) + child_port_names.append(cpname) + + for i in range(32): + start = i*4 + end = start+4 + dpb.breakin(dvs, child_port_names[start:end])