diff --git a/orchagent/mirrororch.cpp b/orchagent/mirrororch.cpp index 4d01c88c30..03fb853c1c 100644 --- a/orchagent/mirrororch.cpp +++ b/orchagent/mirrororch.cpp @@ -265,6 +265,76 @@ bool MirrorOrch::decreaseRefCount(const string& name) return true; } +bool MirrorOrch::validateDstPort(const string& dstPort) +{ + Port port; + if (!m_portsOrch->getPort(dstPort, port) && port.m_type != Port::PHY) + { + SWSS_LOG_ERROR("Failed to locate port %s", dstPort.c_str()); + return false; + } + return true; +} + +bool MirrorOrch::checkPortExistsInSrcPortList(const string& port, const string& srcPort) +{ + auto ports = tokenize(srcPort, ','); + if (ports.size() != 0) + { + for (auto alias : ports) + { + if(port == alias) + { + return true; + } + } + } + + return false; +} + +bool MirrorOrch::validateSrcPort(const string& srcPort) +{ + auto ports = tokenize(srcPort, ','); + + if (ports.size() != 0) + { + for (auto alias : ports) + { + Port port; + if (!gPortsOrch->getPort(alias, port)) + { + SWSS_LOG_ERROR("Failed to locate Port/LAG %s", alias.c_str()); + return false; + } + + if(!(port.m_type == Port::PHY || port.m_type == Port::LAG)) + { + SWSS_LOG_ERROR("Not supported port %s", alias.c_str()); + return false; + } + + // Check if the ports in LAG are part of source port list + if (port.m_type == Port::LAG) + { + vector portv; + m_portsOrch->getLagMember(port, portv); + for (const auto p : portv) + { + if (checkPortExistsInSrcPortList(p.m_alias, srcPort)) + { + SWSS_LOG_ERROR("Port %s in LAG %s is also part of src_port config %s", + p.m_alias.c_str(), port.m_alias.c_str(), srcPort.c_str()); + return false; + } + } + } + } + } + + return true; +} + void MirrorOrch::createEntry(const string& key, const vector& data) { SWSS_LOG_ENTER(); @@ -331,36 +401,26 @@ void MirrorOrch::createEntry(const string& key, const vector& d } else if (fvField(i) == MIRROR_SESSION_SRC_PORT) { - auto ports = tokenize(fvValue(i), ','); - if (ports.size() != 0) + if (!validateSrcPort(fvValue(i))) { - for (auto alias : ports) - { - Port port; - if (!gPortsOrch->getPort(alias, port)) - { - SWSS_LOG_ERROR("Failed to locate port/LAG %s", alias.c_str()); - return; - } - } + SWSS_LOG_ERROR("Failed to get valid source port list %s", fvValue(i).c_str()); + return; } entry.src_port = fvValue(i); } else if (fvField(i) == MIRROR_SESSION_DST_PORT) { - Port dst_port; - if (!m_portsOrch->getPort(fvValue(i), dst_port)) + if (!validateDstPort(fvValue(i))) { - SWSS_LOG_ERROR("Failed to locate port %s", fvValue(i).c_str()); + SWSS_LOG_ERROR("Failed to get valid destination port %s", fvValue(i).c_str()); return; } entry.dst_port = fvValue(i); - } else if (fvField(i) == MIRROR_SESSION_DIRECTION) { - if (!(fvValue(i) == mirror_rx_direction || fvValue(i) == mirror_tx_direction - || fvValue(i) == mirror_both_direction)) + if (!(fvValue(i) == MIRROR_RX_DIRECTION || fvValue(i) == MIRROR_TX_DIRECTION + || fvValue(i) == MIRROR_BOTH_DIRECTION)) { SWSS_LOG_ERROR("Failed to get valid direction %s", fvValue(i).c_str()); return; @@ -395,7 +455,7 @@ void MirrorOrch::createEntry(const string& key, const vector& d setSessionState(key, entry); - if (entry.type == mirror_session_span && !entry.dst_port.empty()) + if (entry.type == MIRROR_SESSION_SPAN && !entry.dst_port.empty()) { auto &session1 = m_syncdMirrors.find(key)->second; activateSession(key, session1); @@ -430,7 +490,7 @@ task_process_status MirrorOrch::deleteEntry(const string& name) if (session.status) { - if (session.type != mirror_session_span) + if (session.type != MIRROR_SESSION_SPAN) { m_routeOrch->detach(this, session.dstIp); } @@ -700,8 +760,9 @@ bool MirrorOrch::setUnsetPortMirror(Port port, status = sai_port_api->set_port_attribute(p.m_port_id, &port_attr); if (status != SAI_STATUS_SUCCESS) { - SWSS_LOG_ERROR("Failed to configure mirror session port %s: %s, status %d, sessionId %x\n", - port.m_alias.c_str(), p.m_alias.c_str(), status, sessionId); + SWSS_LOG_ERROR("Failed to configure %s session on port %s: %s, status %d, sessionId %x\n", + ingress ? "RX" : "TX", port.m_alias.c_str(), + p.m_alias.c_str(), status, sessionId); return false; } } @@ -711,8 +772,8 @@ bool MirrorOrch::setUnsetPortMirror(Port port, status = sai_port_api->set_port_attribute(port.m_port_id, &port_attr); if (status != SAI_STATUS_SUCCESS) { - SWSS_LOG_ERROR("Failed to configure mirror session to port %s, status %d, sessionId %x\n", - port.m_alias.c_str(), status, sessionId); + SWSS_LOG_ERROR("Failed to configure %s session on port %s, status %d, sessionId %x\n", + ingress ? "RX" : "TX", port.m_alias.c_str(), status, sessionId); return false; } } @@ -732,15 +793,23 @@ bool MirrorOrch::configurePortMirrorSession(const string& name, MirrorEntry& ses SWSS_LOG_ERROR("Failed to locate port/LAG %s", alias.c_str()); return false; } - if (session.direction == mirror_rx_direction || session.direction == mirror_both_direction) + if (session.direction == MIRROR_RX_DIRECTION || session.direction == MIRROR_BOTH_DIRECTION) { if (!setUnsetPortMirror(port, true, set, session.sessionId)) + { + SWSS_LOG_ERROR("Failed to configure mirror session %s port %s\n", + name.c_str(), port.m_alias.c_str()); return false; + } } - if (session.direction == mirror_tx_direction || session.direction == mirror_both_direction) + if (session.direction == MIRROR_TX_DIRECTION || session.direction == MIRROR_BOTH_DIRECTION) { if (!setUnsetPortMirror(port, false, set, session.sessionId)) + { + SWSS_LOG_ERROR("Failed to configure mirror session %s port %s \n", + name.c_str(), port.m_alias.c_str()); return false; + } } } } @@ -767,7 +836,7 @@ bool MirrorOrch::activateSession(const string& name, MirrorEntry& session) attrs.push_back(attr); } - if (session.type == mirror_session_span) + if (session.type == MIRROR_SESSION_SPAN) { Port dst_port; if (!m_portsOrch->getPort(session.dst_port, dst_port)) @@ -1225,16 +1294,18 @@ void MirrorOrch::updateLagMember(const LagMemberUpdate& update) // Check the following conditions: // 1) Session is active // 2) LAG is part of mirror session source ports. + // 3) Member port is not part of session source ports. // if the above condition matches then set/unset mirror configuration to new member port. if (session.status && !session.src_port.empty() && - session.src_port.find(update.lag.m_alias.c_str()) != std::string::npos) + session.src_port.find(update.lag.m_alias.c_str()) != std::string::npos && + !checkPortExistsInSrcPortList(update.member.m_alias, session.src_port)) { - if (session.direction == mirror_rx_direction || session.direction == mirror_both_direction) + if (session.direction == MIRROR_RX_DIRECTION || session.direction == MIRROR_BOTH_DIRECTION) { setUnsetPortMirror(update.member, true, update.add, session.sessionId); } - if (session.direction == mirror_tx_direction || session.direction == mirror_both_direction) + if (session.direction == MIRROR_TX_DIRECTION || session.direction == MIRROR_BOTH_DIRECTION) { setUnsetPortMirror(update.member, false, update.add, session.sessionId); } diff --git a/orchagent/mirrororch.h b/orchagent/mirrororch.h index a4e9c73fe7..73eaafde35 100644 --- a/orchagent/mirrororch.h +++ b/orchagent/mirrororch.h @@ -18,11 +18,11 @@ #include #include -const string mirror_rx_direction = "RX"; -const string mirror_tx_direction = "TX"; -const string mirror_both_direction = "BOTH"; -const string mirror_session_span = "SPAN"; -const string mirror_session_erspan = "ERSPAN"; +#define MIRROR_RX_DIRECTION "RX" +#define MIRROR_TX_DIRECTION "TX" +#define MIRROR_BOTH_DIRECTION "BOTH" +#define MIRROR_SESSION_SPAN "SPAN" +#define MIRROR_SESSION_ERSPAN "ERSPAN" /* * Contains session data specified by user in config file @@ -128,6 +128,9 @@ class MirrorOrch : public Orch, public Observer, public Subject void updateLagMember(const LagMemberUpdate&); void updateVlanMember(const VlanMemberUpdate&); + bool checkPortExistsInSrcPortList(const string& port, const string& srcPort); + bool validateSrcPort(const string& srcPort); + bool validateDstPort(const string& dstPort); bool setUnsetPortMirror(Port port, bool ingress, bool set, sai_object_id_t sessionId); bool configurePortMirrorSession(const string&, MirrorEntry&, bool enable); diff --git a/tests/conftest.py b/tests/conftest.py index fac32b3217..a62dcc2a96 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -17,6 +17,8 @@ from dvslib import dvs_acl from dvslib import dvs_vlan from dvslib import dvs_lag +from dvslib import dvs_mirror +from dvslib import dvs_policer def ensure_system(cmd): (rc, output) = commands.getstatusoutput(cmd) @@ -816,6 +818,26 @@ def remove_neighbor(self, interface, ip): tbl._del(interface + ":" + ip) time.sleep(1) + def add_route(self, prefix, nexthop): + self.runcmd("ip route add " + prefix + " via " + nexthop) + time.sleep(1) + + def remove_route(self, prefix): + self.runcmd("ip route del " + prefix) + 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 remove_fdb(self, vlan, mac): + tbl = swsscommon.ProducerStateTable(self.pdb, "FDB_TABLE") + tbl._del("Vlan" + vlan + ":" + mac) + time.sleep(1) + def setup_db(self): self.pdb = swsscommon.DBConnector(0, self.redis_sock, 0) self.adb = swsscommon.DBConnector(1, self.redis_sock, 0) @@ -1023,6 +1045,17 @@ def dvs_vlan_manager(request, dvs): dvs.get_state_db(), dvs.get_counters_db(), dvs.get_app_db()) +@pytest.yield_fixture(scope="class") +def dvs_mirror_manager(request, dvs): + request.cls.dvs_mirror = dvs_mirror.DVSMirror(dvs.get_asic_db(), + dvs.get_config_db(), + dvs.get_state_db(), + dvs.get_counters_db(), + dvs.get_app_db()) +@pytest.yield_fixture(scope="class") +def dvs_policer_manager(request, dvs): + request.cls.dvs_policer = dvs_policer.DVSPolicer(dvs.get_asic_db(), + dvs.get_config_db()) ##################### DPB fixtures ########################################### 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" diff --git a/tests/dvslib/dvs_acl.py b/tests/dvslib/dvs_acl.py index e859b23aae..d21add4149 100644 --- a/tests/dvslib/dvs_acl.py +++ b/tests/dvslib/dvs_acl.py @@ -136,6 +136,16 @@ def create_acl_rule(self, table_name, rule_name, qualifiers, action="FORWARD", p self.config_db.create_entry("ACL_RULE", "{}|{}".format(table_name, rule_name), fvs) + def create_mirror_acl_rule(self, table_name, rule_name, qualifiers, priority="2020"): + fvs = { + "priority": priority + } + + for k, v in qualifiers.items(): + fvs[k] = v + + self.config_db.create_entry("ACL_RULE", "{}|{}".format(table_name, rule_name), fvs) + def remove_acl_rule(self, table_name, rule_name): self.config_db.delete_entry("ACL_RULE", "{}|{}".format(table_name, rule_name)) diff --git a/tests/dvslib/dvs_mirror.py b/tests/dvslib/dvs_mirror.py new file mode 100644 index 0000000000..c90e5da201 --- /dev/null +++ b/tests/dvslib/dvs_mirror.py @@ -0,0 +1,107 @@ +from dvs_database import DVSDatabase + +class DVSMirror(object): + def __init__(self, adb, cdb, sdb, cntrdb, appdb): + self.asic_db = adb + self.config_db = cdb + self.state_db = sdb + self.counters_db = cntrdb + self.app_db = appdb + + def src_ports_to_list(): + src_port_list = [] + for port in src_ports.split(","): + src_port_list.append(port) + src_port=",".join(src_port_list) + + def create_span_session(self, name, dst_port, src_ports=None, direction="BOTH", queue=None, policer=None): + mirror_entry = {"type": "SPAN"} + if dst_port: + mirror_entry["dst_port"] = dst_port + + if src_ports: + mirror_entry["src_port"] = src_ports + # set direction without source port to uncover any swss issues. + mirror_entry["direction"] = direction + + if queue: + mirror_entry["queue"] = queue + if policer: + mirror_entry["policer"] = policer + self.config_db.create_entry("MIRROR_SESSION", name, mirror_entry) + + def create_erspan_session(self, name, src, dst, gre, dscp, ttl, queue, policer=None, src_ports=None, direction="BOTH"): + mirror_entry = {"type": "ERSPAN"} + mirror_entry["src_ip"] = src + mirror_entry["dst_ip"] = dst + mirror_entry["gre_type"] = gre + mirror_entry["dscp"] = dscp + mirror_entry["ttl"] = ttl + mirror_entry["queue"] = queue + if policer: + mirror_entry["policer"] = policer + if src_ports: + mirror_entry["src_port"] = src_ports + mirror_entry["direction"] = direction + + self.config_db.create_entry("MIRROR_SESSION", name, mirror_entry) + + def remove_mirror_session(self, name): + self.config_db.delete_entry("MIRROR_SESSION", name) + + def verify_no_mirror(self): + self.config_db.wait_for_n_keys("MIRROR_SESSION", 0) + self.state_db.wait_for_n_keys("MIRROR_SESSION_TABLE", 0) + + def verify_session_status(self, name, status="active", expected=1): + self.state_db.wait_for_n_keys("MIRROR_SESSION_TABLE", expected) + if expected: + self.state_db.wait_for_field_match("MIRROR_SESSION_TABLE", name, {"status": status}) + + def verify_port_mirror_config(self, dvs, ports, direction, session_oid="null"): + fvs = dvs.counters_db.get_entry("COUNTERS_PORT_NAME_MAP", "") + fvs = dict(fvs) + for p in ports: + port_oid = fvs.get(p) + member = dvs.asic_db.get_entry("ASIC_STATE:SAI_OBJECT_TYPE_PORT", port_oid) + if direction in {"RX", "BOTH"}: + assert member["SAI_PORT_ATTR_INGRESS_MIRROR_SESSION"] == "1:"+session_oid + else: + assert "SAI_PORT_ATTR_INGRESS_MIRROR_SESSION" not in member.keys() or member["SAI_PORT_ATTR_INGRESS_MIRROR_SESSION"] == "0:null" + if direction in {"TX", "BOTH"}: + assert member["SAI_PORT_ATTR_EGRESS_MIRROR_SESSION"] == "1:"+session_oid + else: + assert "SAI_PORT_ATTR_EGRESS_MIRROR_SESSION" not in member.keys() or member["SAI_PORT_ATTR_EGRESS_MIRROR_SESSION"] == "0:null" + + def verify_session_db(self, dvs, name, asic_table=None, asic=None, state=None, asic_size=None): + if asic: + fv_pairs = dvs.asic_db.get_entry("ASIC_STATE:SAI_OBJECT_TYPE_MIRROR_SESSION", asic_table) + assert all(fv_pairs.get(k) == v for k, v in asic.items()) + if asic_size: + assert asic_size == len(fv_pairs) + if state: + fv_pairs = dvs.state_db.get_entry("MIRROR_SESSION_TABLE", name) + assert all(fv_pairs.get(k) == v for k, v in state.items()) + + def verify_session_policer(self, dvs, policer_oid, cir): + if cir: + entry = dvs.asic_db.get_entry("ASIC_STATE:SAI_OBJECT_TYPE_POLICER", policer_oid) + assert entry["SAI_POLICER_ATTR_CIR"] == cir + + def verify_session(self, dvs, name, asic_db=None, state_db=None, dst_oid=None, src_ports=None, direction="BOTH", policer=None, expected = 1, asic_size=None): + member_ids = self.asic_db.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_MIRROR_SESSION", expected) + session_oid=member_ids[0] + # with multiple sessions, match on dst_oid to get session_oid + if dst_oid: + for member in member_ids: + entry=dvs.asic_db.get_entry("ASIC_STATE:SAI_OBJECT_TYPE_MIRROR_SESSION", member) + if entry["SAI_MIRROR_SESSION_ATTR_MONITOR_PORT"] == dst_oid: + session_oid = member + + self.verify_session_db(dvs, name, session_oid, asic=asic_db, state=state_db, asic_size=asic_size) + if policer: + cir = dvs.config_db.get_entry("POLICER", policer)["cir"] + entry=dvs.asic_db.get_entry("ASIC_STATE:SAI_OBJECT_TYPE_MIRROR_SESSION", session_oid) + self.verify_session_policer(dvs, entry["SAI_MIRROR_SESSION_ATTR_POLICER"], cir) + if src_ports: + self.verify_port_mirror_config(dvs, src_ports, direction, session_oid=session_oid) diff --git a/tests/dvslib/dvs_policer.py b/tests/dvslib/dvs_policer.py new file mode 100644 index 0000000000..217e0fe8ea --- /dev/null +++ b/tests/dvslib/dvs_policer.py @@ -0,0 +1,18 @@ +class DVSPolicer(object): + def __init__(self, adb, cdb): + self.asic_db = adb + self.config_db = cdb + + def create_policer(self, name, type="packets", cir="600", cbs="600", mode="sr_tcm", red_action="drop" ): + policer_entry = {"meter_type": type, "mode": mode, + "cir": cir, "cbs": cbs, "red_packet_action": red_action} + self.config_db.create_entry("POLICER", name, policer_entry) + + def remove_policer(self, name): + self.config_db.delete_entry("POLICER", name) + + def verify_policer(self, name, expected=1): + self.asic_db.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_POLICER", expected) + + def verify_no_policer(self): + self.asic_db.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_ACL_ENTRY", 0) diff --git a/tests/test_mirror_port_erspan.py b/tests/test_mirror_port_erspan.py index 3a59f594e0..3f1ac8dc46 100644 --- a/tests/test_mirror_port_erspan.py +++ b/tests/test_mirror_port_erspan.py @@ -6,449 +6,179 @@ from swsscommon import swsscommon from distutils.version import StrictVersion +@pytest.mark.usefixtures("testlog") +@pytest.mark.usefixtures('dvs_vlan_manager') +@pytest.mark.usefixtures('dvs_lag_manager') +@pytest.mark.usefixtures('dvs_mirror_manager') class TestMirror(object): - def setup_db(self, dvs): - self.pdb = swsscommon.DBConnector(0, dvs.redis_sock, 0) - self.adb = swsscommon.DBConnector(1, dvs.redis_sock, 0) - self.cdb = swsscommon.DBConnector(4, dvs.redis_sock, 0) - self.sdb = swsscommon.DBConnector(6, dvs.redis_sock, 0) - - def set_interface_status(self, dvs, interface, admin_status): - if interface.startswith("PortChannel"): - tbl_name = "PORTCHANNEL" - elif interface.startswith("Vlan"): - tbl_name = "VLAN" - else: - tbl_name = "PORT" - tbl = swsscommon.Table(self.cdb, tbl_name) - fvs = swsscommon.FieldValuePairs([("admin_status", "up")]) - tbl.set(interface, fvs) - time.sleep(1) - - # when using FRR, route cannot be inserted if the neighbor is not - # connected. thus it is mandatory to force the interface up manually - if interface.startswith("PortChannel"): - dvs.runcmd("bash -c 'echo " + ("1" if admin_status == "up" else "0") +\ - " > /sys/class/net/" + interface + "/carrier'") - - def add_ip_address(self, interface, ip): - if interface.startswith("PortChannel"): - tbl_name = "PORTCHANNEL_INTERFACE" - elif interface.startswith("Vlan"): - tbl_name = "VLAN_INTERFACE" - else: - tbl_name = "INTERFACE" - tbl = swsscommon.Table(self.cdb, tbl_name) - fvs = swsscommon.FieldValuePairs([("NULL", "NULL")]) - tbl.set(interface + "|" + ip, fvs) - tbl.set(interface, fvs) - time.sleep(1) - - def remove_ip_address(self, interface, ip): - if interface.startswith("PortChannel"): - tbl_name = "PORTCHANNEL_INTERFACE" - elif interface.startswith("Vlan"): - tbl_name = "VLAN_INTERFACE" - else: - tbl_name = "INTERFACE" - tbl = swsscommon.Table(self.cdb, tbl_name) - tbl._del(interface + "|" + ip) - tbl._del(interface) - time.sleep(1) - - def add_neighbor(self, interface, ip, mac): - tbl = swsscommon.ProducerStateTable(self.pdb, "NEIGH_TABLE") - fvs = swsscommon.FieldValuePairs([("neigh", mac), - ("family", "IPv4")]) - tbl.set(interface + ":" + ip, fvs) - time.sleep(1) - - def remove_neighbor(self, interface, ip): - tbl = swsscommon.ProducerStateTable(self.pdb, "NEIGH_TABLE") - tbl._del(interface + ":" + ip) - time.sleep(1) - - def add_route(self, dvs, prefix, nexthop): - dvs.runcmd("ip route add " + prefix + " via " + nexthop) - time.sleep(1) - - def remove_route(self, dvs, prefix): - dvs.runcmd("ip route del " + prefix) - time.sleep(1) - - def create_policer(self, name): - tbl = swsscommon.Table(self.cdb, "POLICER") - fvs = swsscommon.FieldValuePairs([("meter_type", "packets"), - ("mode", "sr_tcm"), - ("cir", "600"), - ("cbs", "600"), - ("red_packet_action", "drop")]) - tbl.set(name, fvs) - time.sleep(1) - - def remove_policer(self, name): - tbl = swsscommon.Table(self.cdb, "POLICER") - tbl._del(name) - time.sleep(1) - - def getPortOid(self, dvs, port_name): - - cnt_db = swsscommon.DBConnector(swsscommon.COUNTERS_DB, dvs.redis_sock, 0) - port_map_tbl = swsscommon.Table(cnt_db, 'COUNTERS_PORT_NAME_MAP') - - for k in port_map_tbl.get('')[1]: - if k[0] == port_name: - return k[1] - - - def getPortAttr(self, dvs, port_oid, port_attr): - - asic_db = swsscommon.DBConnector(swsscommon.ASIC_DB, dvs.redis_sock, 0) - port_tbl = swsscommon.Table(asic_db, 'ASIC_STATE:SAI_OBJECT_TYPE_PORT:{0}'.format(port_oid)) - - for k in port_tbl.get('')[1]: - if k[0] == port_attr: - return k[1] - - def create_mirror_erspan_session(self, name, src, dst, gre, dscp, ttl, queue, policer=None, src_port=None, direction=None): - tbl = swsscommon.Table(self.cdb, "MIRROR_SESSION") - if src_port is None and policer is None and direction is None: - fvs = swsscommon.FieldValuePairs([("src_ip", src), - ("dst_ip", dst), - ("gre_type", gre), - ("dscp", dscp), - ("ttl", ttl), - ("queue", queue)]) - elif policer is None: - fvs = swsscommon.FieldValuePairs([("src_ip", src), - ("dst_ip", dst), - ("gre_type", gre), - ("dscp", dscp), - ("ttl", ttl), - ("queue", queue), - ("src_port", src_port), - ("direction", direction)]) - else: - fvs = swsscommon.FieldValuePairs([("src_ip", src), - ("dst_ip", dst), - ("gre_type", gre), - ("dscp", dscp), - ("ttl", ttl), - ("queue", queue), - ("src_port", src_port), - ("direction", direction), - ("policer", policer)]) - tbl.set(name, fvs) - time.sleep(3) - - def remove_mirror_session(self, name): - tbl = swsscommon.Table(self.cdb, "MIRROR_SESSION") - tbl._del(name) - time.sleep(2) - - def get_mirror_session_status(self, name): - return self.get_mirror_session_state(name)["status"] - - def get_mirror_session_state(self, name): - tbl = swsscommon.Table(self.sdb, "MIRROR_SESSION_TABLE") - (status, fvs) = tbl.get(name) - assert status == True - assert len(fvs) > 0 - return { fv[0]: fv[1] for fv in fvs } - - def check_mirror_session_state(self, name, status): - tbl = swsscommon.Table(self.sdb, "MIRROR_SESSION_TABLE") - (session_status, fvs) = tbl.get(name) - assert session_status == status - def test_PortMirrorERSpanAddRemove(self, dvs, testlog): """ - This test covers the basic mirror session creation and removal operations + This test covers the basic ERSPANmirror session creation and removal operations Operation flow: - 1. Create mirror session with only dst_port - The session becomes active. - 2. Create mirror session with invalid dst_port, session becomes inactive. - 2. Create mirror session with invalid source port, the session becomes inactive, - 3. Create mirror session with multiple source ports, the session becomes active - 4. Create mirror session with valid and invalid source ports, the session becomes inactive - 5. Remove miror session + 1. Create mirror session with source ports. + The session remains inactive because no nexthop/neighbor exists + 2. Bring up port; assign IP; create neighbor; create route + The session remains inactive until the route is created + 3. Verify that port mirror config is proper. + 4. Remove route; remove neighbor; remove IP; bring down port + The session becomes inactive again till the end """ - self.setup_db(dvs) + dvs.setup_db() + pmap = dvs.counters_db.get_entry("COUNTERS_PORT_NAME_MAP", "") + pmap = dict(pmap) session = "TEST_SESSION" - src_port = "Ethernet0" - src_oid = self.getPortOid(dvs, src_port) + src_ports = "Ethernet12" + src_asic_ports = ["Ethernet12"] # create mirror session - self.create_mirror_erspan_session(session, "1.1.1.1", "2.2.2.2", "0x6558", "8", "100", "0", None, src_port, "BOTH") - assert self.get_mirror_session_state(session)["status"] == "inactive" + self.dvs_mirror.create_erspan_session(session, "1.1.1.1", "2.2.2.2", "0x6558", "8", "100", "0", None, src_ports) + self.dvs_mirror.verify_session_status(session, status="inactive") # bring up Ethernet16 - self.set_interface_status(dvs, "Ethernet16", "up") - assert self.get_mirror_session_state(session)["status"] == "inactive" + dvs.set_interface_status("Ethernet16", "up") + self.dvs_mirror.verify_session_status(session, status="inactive") # add IP address to Ethernet16 - self.add_ip_address("Ethernet16", "10.0.0.0/31") - assert self.get_mirror_session_state(session)["status"] == "inactive" + dvs.add_ip_address("Ethernet16", "10.0.0.0/31") + self.dvs_mirror.verify_session_status(session, status="inactive") # add neighbor to Ethernet16 - self.add_neighbor("Ethernet16", "10.0.0.1", "02:04:06:08:10:12") - assert self.get_mirror_session_state(session)["status"] == "inactive" + dvs.add_neighbor("Ethernet16", "10.0.0.1", "02:04:06:08:10:12") + self.dvs_mirror.verify_session_status(session, status="inactive") # add route to mirror destination via 10.0.0.1 - self.add_route(dvs, "2.2.2.2", "10.0.0.1") - assert self.get_mirror_session_state(session)["status"] == "active" - assert self.get_mirror_session_state(session)["monitor_port"] == "Ethernet16" - assert self.get_mirror_session_state(session)["dst_mac"] == "02:04:06:08:10:12" - assert self.get_mirror_session_state(session)["route_prefix"] == "2.2.2.2/32" - - # check asic database - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_MIRROR_SESSION") - mirror_entries = tbl.getKeys() - assert len(mirror_entries) == 1 - - (status, fvs) = tbl.get(mirror_entries[0]) - assert status == True - assert len(fvs) == 11 - for fv in fvs: - if fv[0] == "SAI_MIRROR_SESSION_ATTR_MONITOR_PORT": - assert dvs.asicdb.portoidmap[fv[1]] == "Ethernet16" - elif fv[0] == "SAI_MIRROR_SESSION_ATTR_TYPE": - assert fv[1] == "SAI_MIRROR_SESSION_TYPE_ENHANCED_REMOTE" - elif fv[0] == "SAI_MIRROR_SESSION_ATTR_ERSPAN_ENCAPSULATION_TYPE": - assert fv[1] == "SAI_ERSPAN_ENCAPSULATION_TYPE_MIRROR_L3_GRE_TUNNEL" - elif fv[0] == "SAI_MIRROR_SESSION_ATTR_IPHDR_VERSION": - assert fv[1] == "4" - elif fv[0] == "SAI_MIRROR_SESSION_ATTR_TOS": - assert fv[1] == "32" - elif fv[0] == "SAI_MIRROR_SESSION_ATTR_TTL": - assert fv[1] == "100" - elif fv[0] == "SAI_MIRROR_SESSION_ATTR_SRC_IP_ADDRESS": - assert fv[1] == "1.1.1.1" - elif fv[0] == "SAI_MIRROR_SESSION_ATTR_DST_IP_ADDRESS": - assert fv[1] == "2.2.2.2" - elif fv[0] == "SAI_MIRROR_SESSION_ATTR_SRC_MAC_ADDRESS": - assert fv[1] == dvs.runcmd("bash -c \"ip link show eth0 | grep ether | awk '{print $2}'\"")[1].strip().upper() - elif fv[0] == "SAI_MIRROR_SESSION_ATTR_DST_MAC_ADDRESS": - assert fv[1] == "02:04:06:08:10:12" - elif fv[0] == "SAI_MIRROR_SESSION_ATTR_GRE_PROTOCOL_TYPE": - assert fv[1] == "25944" # 0x6558 - else: - assert False - - # Check src_port state. - session_status= "1:"+format(mirror_entries[0]) - # Verify port has mirror session enabled with session oid. - status = self.getPortAttr(dvs, src_oid, 'SAI_PORT_ATTR_INGRESS_MIRROR_SESSION') - assert status == session_status - # Verify port has egress mirror session enabled with session oid. - session_status = self.getPortAttr(dvs, src_oid, 'SAI_PORT_ATTR_EGRESS_MIRROR_SESSION') - assert status == session_status + dvs.add_route("2.2.2.2", "10.0.0.1") + src_mac = dvs.runcmd("bash -c \"ip link show eth0 | grep ether | awk '{print $2}'\"")[1].strip().upper() + expected_asic_db = {"SAI_MIRROR_SESSION_ATTR_MONITOR_PORT": pmap.get("Ethernet16"), + "SAI_MIRROR_SESSION_ATTR_TYPE": "SAI_MIRROR_SESSION_TYPE_ENHANCED_REMOTE", + "SAI_MIRROR_SESSION_ATTR_ERSPAN_ENCAPSULATION_TYPE": "SAI_ERSPAN_ENCAPSULATION_TYPE_MIRROR_L3_GRE_TUNNEL", + "SAI_MIRROR_SESSION_ATTR_IPHDR_VERSION": "4", + "SAI_MIRROR_SESSION_ATTR_TOS": "32", + "SAI_MIRROR_SESSION_ATTR_TTL": "100", + "SAI_MIRROR_SESSION_ATTR_SRC_IP_ADDRESS": "1.1.1.1", + "SAI_MIRROR_SESSION_ATTR_DST_IP_ADDRESS": "2.2.2.2", + "SAI_MIRROR_SESSION_ATTR_DST_MAC_ADDRESS": "02:04:06:08:10:12", + "SAI_MIRROR_SESSION_ATTR_SRC_MAC_ADDRESS": src_mac, + "SAI_MIRROR_SESSION_ATTR_GRE_PROTOCOL_TYPE": "25944"} + expected_state_db = {"status": "active", + "monitor_port": "Ethernet16", + "dst_mac": "02:04:06:08:10:12", + "route_prefix": "2.2.2.2/32"} + self.dvs_mirror.verify_session_status(session) + self.dvs_mirror.verify_session(dvs, session, asic_db=expected_asic_db, state_db=expected_state_db, src_ports=src_asic_ports, asic_size=11) # remove route - self.remove_route(dvs, "2.2.2.2") - assert self.get_mirror_session_state(session)["status"] == "inactive" + dvs.remove_route("2.2.2.2") + self.dvs_mirror.verify_session_status(session, status="inactive") # remove neighbor - self.remove_neighbor("Ethernet16", "10.0.0.1") - assert self.get_mirror_session_state(session)["status"] == "inactive" + dvs.remove_neighbor("Ethernet16", "10.0.0.1") + self.dvs_mirror.verify_session_status(session, status="inactive") # remove IP address - self.remove_ip_address("Ethernet16", "10.0.0.0/31") - assert self.get_mirror_session_state(session)["status"] == "inactive" + dvs.remove_ip_address("Ethernet16", "10.0.0.0/31") + self.dvs_mirror.verify_session_status(session, status="inactive") # bring down Ethernet16 - self.set_interface_status(dvs, "Ethernet16", "down") - assert self.get_mirror_session_state(session)["status"] == "inactive" + dvs.set_interface_status("Ethernet16", "down") + self.dvs_mirror.verify_session_status(session, status="inactive") # remove mirror session - self.remove_mirror_session(session) - def create_vlan(self, dvs, vlan): - #dvs.runcmd("ip link del Bridge") - #dvs.runcmd("ip link add Bridge up type bridge") - tbl = swsscommon.Table(self.cdb, "VLAN") - fvs = swsscommon.FieldValuePairs([("vlanid", vlan)]) - tbl.set("Vlan" + vlan, fvs) - time.sleep(1) - - def remove_vlan(self, vlan): - tbl = swsscommon.Table(self.cdb, "VLAN") - tbl._del("Vlan" + vlan) - time.sleep(1) - - def create_vlan_member(self, vlan, interface): - tbl = swsscommon.Table(self.cdb, "VLAN_MEMBER") - fvs = swsscommon.FieldValuePairs([("tagging_mode", "untagged")]) - tbl.set("Vlan" + vlan + "|" + interface, fvs) - time.sleep(1) - - def remove_vlan_member(self, vlan, interface): - tbl = swsscommon.Table(self.cdb, "VLAN_MEMBER") - tbl._del("Vlan" + vlan + "|" + interface) - time.sleep(1) - - def 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 remove_fdb(self, vlan, mac): - tbl = swsscommon.ProducerStateTable(self.pdb, "FDB_TABLE") - tbl._del("Vlan" + vlan + ":" + mac) - time.sleep(1) - - - # Ignore testcase in Debian Jessie - # TODO: Remove this skip if Jessie support is no longer needed - @pytest.mark.skipif(StrictVersion(platform.linux_distribution()[1]) <= StrictVersion('8.9'), reason="Debian 8.9 or before has no support") + self.dvs_mirror.remove_mirror_session(session) + self.dvs_mirror.verify_no_mirror() + def test_PortMirrorToVlanAddRemove(self, dvs, testlog): """ This test covers basic mirror session creation and removal operation with destination port sits in a VLAN Opeartion flow: - 1. Create mirror session + 1. Create mirror session with source ports. 2. Create VLAN; assign IP; create neighbor; create FDB The session should be up only at this time. + verify source port mirror config. 3. Remove FDB; remove neighbor; remove IP; remove VLAN 4. Remove mirror session """ - self.setup_db(dvs) + dvs.setup_db() + pmap = dvs.counters_db.get_entry("COUNTERS_PORT_NAME_MAP", "") + pmap = dict(pmap) session = "TEST_SESSION" - src_port = "Ethernet0" - src_oid = self.getPortOid(dvs, src_port) + src_ports = "Ethernet12,Ethernet16" + src_asic_ports = ["Ethernet12", "Ethernet16"] + vlan_id = "10" + vlan = "Vlan10" # create mirror session - self.create_mirror_erspan_session(session, "5.5.5.5", "6.6.6.6", "0x6558", "8", "100", "0", None, src_port, "BOTH") - assert self.get_mirror_session_state(session)["status"] == "inactive" + self.dvs_mirror.create_erspan_session(session, "5.5.5.5", "6.6.6.6", "0x6558", "8", "100", "0", None, src_ports, direction="TX") + self.dvs_mirror.verify_session_status(session, status="inactive") # create vlan; create vlan member - self.create_vlan(dvs, "6") - self.create_vlan_member("6", "Ethernet4") + self.dvs_vlan.create_vlan(vlan_id) + self.dvs_vlan.create_vlan_member(vlan_id, "Ethernet4") # bring up vlan and member - self.set_interface_status(dvs, "Vlan6", "up") - self.set_interface_status(dvs, "Ethernet4", "up") + dvs.set_interface_status(vlan, "up") + dvs.set_interface_status("Ethernet4", "up") # add ip address to vlan 6 - self.add_ip_address("Vlan6", "6.6.6.0/24") - assert self.get_mirror_session_state(session)["status"] == "inactive" + dvs.add_ip_address(vlan, "6.6.6.0/24") + self.dvs_mirror.verify_session_status(session, status="inactive") # create neighbor to vlan 6 - self.add_neighbor("Vlan6", "6.6.6.6", "66:66:66:66:66:66") - assert self.get_mirror_session_state(session)["status"] == "inactive" + dvs.add_neighbor(vlan, "6.6.6.6", "66:66:66:66:66:66") + self.dvs_mirror.verify_session_status(session, status="inactive") # create fdb entry to ethernet4 - self.create_fdb("6", "66-66-66-66-66-66", "Ethernet4") - assert self.get_mirror_session_state(session)["status"] == "active" - - # check asic database - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_MIRROR_SESSION") - mirror_entries = tbl.getKeys() - assert len(mirror_entries) == 1 - - (status, fvs) = tbl.get(mirror_entries[0]) - assert status == True - assert len(fvs) == 16 - for fv in fvs: - if fv[0] == "SAI_MIRROR_SESSION_ATTR_MONITOR_PORT": - assert dvs.asicdb.portoidmap[fv[1]] == "Ethernet4" - elif fv[0] == "SAI_MIRROR_SESSION_ATTR_TYPE": - assert fv[1] == "SAI_MIRROR_SESSION_TYPE_ENHANCED_REMOTE" - elif fv[0] == "SAI_MIRROR_SESSION_ATTR_ERSPAN_ENCAPSULATION_TYPE": - assert fv[1] == "SAI_ERSPAN_ENCAPSULATION_TYPE_MIRROR_L3_GRE_TUNNEL" - elif fv[0] == "SAI_MIRROR_SESSION_ATTR_IPHDR_VERSION": - assert fv[1] == "4" - elif fv[0] == "SAI_MIRROR_SESSION_ATTR_TOS": - assert fv[1] == "32" - elif fv[0] == "SAI_MIRROR_SESSION_ATTR_TTL": - assert fv[1] == "100" - elif fv[0] == "SAI_MIRROR_SESSION_ATTR_SRC_IP_ADDRESS": - assert fv[1] == "5.5.5.5" - elif fv[0] == "SAI_MIRROR_SESSION_ATTR_DST_IP_ADDRESS": - assert fv[1] == "6.6.6.6" - elif fv[0] == "SAI_MIRROR_SESSION_ATTR_SRC_MAC_ADDRESS": - assert fv[1] == dvs.runcmd("bash -c \"ip link show eth0 | grep ether | awk '{print $2}'\"")[1].strip().upper() - elif fv[0] == "SAI_MIRROR_SESSION_ATTR_DST_MAC_ADDRESS": - assert fv[1] == "66:66:66:66:66:66" - elif fv[0] == "SAI_MIRROR_SESSION_ATTR_GRE_PROTOCOL_TYPE": - assert fv[1] == "25944" # 0x6558 - elif fv[0] == "SAI_MIRROR_SESSION_ATTR_VLAN_HEADER_VALID": - assert fv[1] == "true" - elif fv[0] == "SAI_MIRROR_SESSION_ATTR_VLAN_TPID": - assert fv[1] == "33024" - elif fv[0] == "SAI_MIRROR_SESSION_ATTR_VLAN_ID": - assert fv[1] == "6" - elif fv[0] == "SAI_MIRROR_SESSION_ATTR_VLAN_PRI": - assert fv[1] == "0" - elif fv[0] == "SAI_MIRROR_SESSION_ATTR_VLAN_CFI": - assert fv[1] == "0" - else: - assert False - - # Check src_port state. - session_status= "1:"+format(mirror_entries[0]) - # Verify port has mirror session enabled with session oid. - status = self.getPortAttr(dvs, src_oid, 'SAI_PORT_ATTR_INGRESS_MIRROR_SESSION') - assert status == session_status - # Verify port has egress mirror session enabled with session oid. - session_status = self.getPortAttr(dvs, src_oid, 'SAI_PORT_ATTR_EGRESS_MIRROR_SESSION') - assert status == session_status + dvs.create_fdb(vlan_id, "66-66-66-66-66-66", "Ethernet4") + self.dvs_mirror.verify_session_status(session) + + src_mac = dvs.runcmd("bash -c \"ip link show eth0 | grep ether | awk '{print $2}'\"")[1].strip().upper() + expected_asic_db = {"SAI_MIRROR_SESSION_ATTR_MONITOR_PORT": pmap.get("Ethernet4"), + "SAI_MIRROR_SESSION_ATTR_TYPE": "SAI_MIRROR_SESSION_TYPE_ENHANCED_REMOTE", + "SAI_MIRROR_SESSION_ATTR_ERSPAN_ENCAPSULATION_TYPE": "SAI_ERSPAN_ENCAPSULATION_TYPE_MIRROR_L3_GRE_TUNNEL", + "SAI_MIRROR_SESSION_ATTR_IPHDR_VERSION": "4", + "SAI_MIRROR_SESSION_ATTR_TOS": "32", + "SAI_MIRROR_SESSION_ATTR_TTL": "100", + "SAI_MIRROR_SESSION_ATTR_SRC_IP_ADDRESS": "5.5.5.5", + "SAI_MIRROR_SESSION_ATTR_DST_IP_ADDRESS": "6.6.6.6", + "SAI_MIRROR_SESSION_ATTR_DST_MAC_ADDRESS": "66:66:66:66:66:66", + "SAI_MIRROR_SESSION_ATTR_SRC_MAC_ADDRESS": src_mac, + "SAI_MIRROR_SESSION_ATTR_GRE_PROTOCOL_TYPE": "25944", + "SAI_MIRROR_SESSION_ATTR_VLAN_HEADER_VALID": "true", + "SAI_MIRROR_SESSION_ATTR_VLAN_TPID": "33024", + "SAI_MIRROR_SESSION_ATTR_VLAN_ID": vlan_id, + "SAI_MIRROR_SESSION_ATTR_VLAN_PRI": "0", + "SAI_MIRROR_SESSION_ATTR_VLAN_CFI": "0"} + self.dvs_mirror.verify_session(dvs, session, asic_db=expected_asic_db, src_ports=src_asic_ports, asic_size=16, direction="TX") + + dvs.set_interface_status("Ethernet4", "down") # remove fdb entry - self.remove_fdb("6", "66-66-66-66-66-66") - assert self.get_mirror_session_state(session)["status"] == "inactive" + dvs.remove_fdb(vlan_id, "66-66-66-66-66-66") + self.dvs_mirror.verify_session_status(session, status="inactive") # remove neighbor - self.remove_neighbor("Vlan6", "6.6.6.6") - assert self.get_mirror_session_state(session)["status"] == "inactive" + dvs.remove_neighbor(vlan, "6.6.6.6") + self.dvs_mirror.verify_session_status(session, status="inactive") # remove ip address - self.remove_ip_address("Vlan6", "6.6.6.0/24") - assert self.get_mirror_session_state(session)["status"] == "inactive" + dvs.remove_ip_address(vlan, "6.6.6.0/24") + self.dvs_mirror.verify_session_status(session, status="inactive") # bring down vlan and member - self.set_interface_status(dvs, "Ethernet4", "down") - self.set_interface_status(dvs, "Vlan6", "down") - - # remove vlan member; remove vlan - self.remove_vlan_member("6", "Ethernet4") - self.remove_vlan("6") + dvs.set_interface_status("Ethernet4", "down") + dvs.set_interface_status(vlan, "down") # remove mirror session - self.remove_mirror_session(session) - - def create_port_channel(self, dvs, channel): - tbl = swsscommon.ProducerStateTable(self.pdb, "LAG_TABLE") - fvs = swsscommon.FieldValuePairs([("admin", "up"), ("mtu", "9100")]) - tbl.set("PortChannel" + channel, fvs) - dvs.runcmd("ip link add PortChannel" + channel + " type bond") - tbl = swsscommon.Table(self.sdb, "LAG_TABLE") - fvs = swsscommon.FieldValuePairs([("state", "ok")]) - tbl.set("PortChannel" + channel, fvs) - time.sleep(1) - - def remove_port_channel(self, dvs, channel): - tbl = swsscommon.ProducerStateTable(self.pdb, "LAG_TABLE") - tbl._del("PortChannel" + channel) - dvs.runcmd("ip link del PortChannel" + channel) - tbl = swsscommon.Table(self.sdb, "LAG_TABLE") - tbl._del("PortChannel" + channel) - time.sleep(1) - - 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 remove_port_channel_member(self, channel, interface): - tbl = swsscommon.ProducerStateTable(self.pdb, "LAG_MEMBER_TABLE") - tbl._del("PortChannel" + channel + ":" + interface) - time.sleep(1) + self.dvs_mirror.remove_mirror_session(session) + self.dvs_mirror.verify_no_mirror() + + # remove vlan member; remove vlan + self.dvs_vlan.remove_vlan_member(vlan_id, "Ethernet4") + self.dvs_vlan.remove_vlan(vlan_id) def test_PortMirrorToLagAddRemove(self, dvs, testlog): @@ -456,84 +186,77 @@ def test_PortMirrorToLagAddRemove(self, dvs, testlog): This test covers basic mirror session creation and removal operations with destination port sits in a LAG Operation flow: - 1. Create mirror sesion + 1. Create mirror sesion with source ports, direction 2. Create LAG; assign IP; create directly connected neighbor The session shoudl be up only at this time. 3. Remove neighbor; remove IP; remove LAG 4. Remove mirror session """ - self.setup_db(dvs) + dvs.setup_db() + pmap = dvs.counters_db.get_entry("COUNTERS_PORT_NAME_MAP", "") + pmap = dict(pmap) session = "TEST_SESSION" - src_port = "Ethernet0" - src_oid = self.getPortOid(dvs, src_port) + src_ports = "Ethernet0,Ethernet4" + src_asic_ports = ["Ethernet0", "Ethernet4"] # create mirror session - self.create_mirror_erspan_session(session, "10.10.10.10", "11.11.11.11", "0x6558", "8", "100", "0", None, src_port, "TX") - assert self.get_mirror_session_state(session)["status"] == "inactive" + self.dvs_mirror.create_erspan_session(session, "10.10.10.10", "11.11.11.11", "0x6558", + "8", "100", "0", None, src_ports, "TX") + self.dvs_mirror.verify_session_status(session, status="inactive") # create port channel; create port channel member - self.create_port_channel(dvs, "008") - self.create_port_channel_member("008", "Ethernet88") + self.dvs_lag.create_port_channel("008") + lag_entries = self.dvs_vlan.asic_db.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_LAG", 1) + self.dvs_lag.create_port_channel_member("008", "Ethernet88") + + # Verify the LAG has been initialized properly + lag_member_entries = self.dvs_vlan.asic_db.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_LAG_MEMBER", 1) + fvs = self.dvs_vlan.asic_db.wait_for_entry("ASIC_STATE:SAI_OBJECT_TYPE_LAG_MEMBER", lag_member_entries[0]) + assert len(fvs) == 4 + assert fvs.get("SAI_LAG_MEMBER_ATTR_LAG_ID") == lag_entries[0] + assert self.dvs_vlan.asic_db.port_to_id_map[fvs.get("SAI_LAG_MEMBER_ATTR_PORT_ID")] == "Ethernet88" # bring up port channel and port channel member - self.set_interface_status(dvs, "PortChannel008", "up") - self.set_interface_status(dvs, "Ethernet88", "up") + dvs.set_interface_status("PortChannel008", "up") + dvs.set_interface_status("Ethernet88", "up") # add ip address to port channel 008 - self.add_ip_address("PortChannel008", "11.11.11.0/24") - assert self.get_mirror_session_state(session)["status"] == "inactive" + dvs.add_ip_address("PortChannel008", "11.11.11.0/24") + self.dvs_mirror.verify_session_status(session, status="inactive") # create neighbor to port channel 008 - self.add_neighbor("PortChannel008", "11.11.11.11", "88:88:88:88:88:88") - assert self.get_mirror_session_state(session)["status"] == "active" + dvs.add_neighbor("PortChannel008", "11.11.11.11", "88:88:88:88:88:88") + self.dvs_mirror.verify_session_status(session) # Check src_port state. - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_MIRROR_SESSION") - mirror_entries = tbl.getKeys() - assert len(mirror_entries) == 1 - (status, fvs) = tbl.get(tbl.getKeys()[0]) - assert status == True - for fv in fvs: - if fv[0] == "SAI_MIRROR_SESSION_ATTR_MONITOR_PORT": - assert dvs.asicdb.portoidmap[fv[1]] == "Ethernet88" - elif fv[0] == "SAI_MIRROR_SESSION_ATTR_DST_MAC_ADDRESS": - assert fv[1] == "88:88:88:88:88:88" - - session_status= "1:"+format(mirror_entries[0]) - print src_oid - print session_status - # Verify port has mirror session enabled with session oid. - status = self.getPortAttr(dvs, src_oid, 'SAI_PORT_ATTR_INGRESS_MIRROR_SESSION') - assert status == None or status == "0:null" - # Verify port has egress mirror session enabled with session oid. - status = self.getPortAttr(dvs, src_oid, 'SAI_PORT_ATTR_EGRESS_MIRROR_SESSION') - assert status == session_status + expected_asic_db = {"SAI_MIRROR_SESSION_ATTR_MONITOR_PORT": pmap.get("Ethernet88"), + "SAI_MIRROR_SESSION_ATTR_DST_MAC_ADDRESS": "88:88:88:88:88:88"} + + self.dvs_mirror.verify_session(dvs, session, asic_db=expected_asic_db, src_ports=src_asic_ports, direction="TX") # remove neighbor - self.remove_neighbor("PortChannel008", "11.11.11.11") - assert self.get_mirror_session_state(session)["status"] == "inactive" + dvs.remove_neighbor("PortChannel008", "11.11.11.11") + self.dvs_mirror.verify_session_status(session, status="inactive") # remove ip address - self.remove_ip_address("PortChannel008", "11.11.11.0/24") - assert self.get_mirror_session_state(session)["status"] == "inactive" + dvs.remove_ip_address("PortChannel008", "11.11.11.0/24") + self.dvs_mirror.verify_session_status(session, status="inactive") # bring down port channel and port channel member - self.set_interface_status(dvs, "PortChannel008", "down") - self.set_interface_status(dvs, "Ethernet88", "down") + dvs.set_interface_status("PortChannel008", "down") + dvs.set_interface_status("Ethernet88", "down") # remove port channel member; remove port channel - self.remove_port_channel_member("008", "Ethernet88") - self.remove_port_channel(dvs, "008") - # remove mirror session - self.remove_mirror_session(session) + self.dvs_lag.remove_port_channel_member("008", "Ethernet88") + self.dvs_lag.remove_port_channel("008") + # remove mirror session + self.dvs_mirror.remove_mirror_session(session) + self.dvs_mirror.verify_no_mirror() - # Ignore testcase in Debian Jessie - # TODO: Remove this skip if Jessie support is no longer needed - @pytest.mark.skipif(StrictVersion(platform.linux_distribution()[1]) <= StrictVersion('8.9'), reason="Debian 8.9 or before has no support") def test_PortMirrorDestMoveVlan(self, dvs, testlog): """ This test tests mirror session destination move from non-VLAN to VLAN @@ -547,120 +270,92 @@ def test_PortMirrorDestMoveVlan(self, dvs, testlog): 7. Disable non-VLAN monitor port 8. Remove mirror session """ - self.setup_db(dvs) + dvs.setup_db() + pmap = dvs.counters_db.get_entry("COUNTERS_PORT_NAME_MAP", "") + pmap = dict(pmap) session = "TEST_SESSION" - src_port = "Ethernet0" - src_oid = self.getPortOid(dvs, src_port) + src_ports = "Ethernet0" + src_asic_ports = ["Ethernet0"] # create mirror session - self.create_mirror_erspan_session(session, "7.7.7.7", "8.8.8.8", "0x6558", "8", "100", "0", None, src_port, "BOTH") - assert self.get_mirror_session_state(session)["status"] == "inactive" + self.dvs_mirror.create_erspan_session(session, "7.7.7.7", "8.8.8.8", "0x6558", "8", "100", "0", None, src_ports) + self.dvs_mirror.verify_session_status(session, status="inactive") # bring up port; add ip; add neighbor; add route - self.set_interface_status(dvs, "Ethernet32", "up") - self.add_ip_address("Ethernet32", "80.0.0.0/31") - self.add_neighbor("Ethernet32", "80.0.0.1", "02:04:06:08:10:12") - self.add_route(dvs, "8.8.0.0/16", "80.0.0.1") - assert self.get_mirror_session_state(session)["status"] == "active" + dvs.set_interface_status("Ethernet32", "up") + dvs.add_ip_address("Ethernet32", "80.0.0.0/31") + dvs.add_neighbor("Ethernet32", "80.0.0.1", "02:04:06:08:10:12") + dvs.add_route("8.8.0.0/16", "80.0.0.1") + + self.dvs_mirror.verify_session_status(session) # check monitor port - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_MIRROR_SESSION") - assert len(tbl.getKeys()) == 1 - (status, fvs) = tbl.get(tbl.getKeys()[0]) - assert status == True - for fv in fvs: - if fv[0] == "SAI_MIRROR_SESSION_ATTR_MONITOR_PORT": - assert dvs.asicdb.portoidmap[fv[1]] == "Ethernet32" - elif fv[0] == "SAI_MIRROR_SESSION_ATTR_VLAN_HEADER_VALID": - assert fv[1] == "false" + expected_asic_db = {"SAI_MIRROR_SESSION_ATTR_MONITOR_PORT": pmap.get("Ethernet32")} + self.dvs_mirror.verify_session(dvs, session, asic_db=expected_asic_db) # mirror session move round 1 # create vlan; create vlan member; bring up vlan and member - self.create_vlan(dvs, "9") - self.create_vlan_member("9", "Ethernet48") - self.set_interface_status(dvs, "Vlan9", "up") - self.set_interface_status(dvs, "Ethernet48", "up") - assert self.get_mirror_session_state(session)["status"] == "active" + self.dvs_vlan.create_vlan("9") + self.dvs_vlan.create_vlan_member("9", "Ethernet48") + dvs.set_interface_status("Vlan9", "up") + dvs.set_interface_status("Ethernet48", "up") + + self.dvs_mirror.verify_session_status(session) # add ip address to vlan 9 - self.add_ip_address("Vlan9", "8.8.8.0/24") - assert self.get_mirror_session_state(session)["status"] == "inactive" + dvs.add_ip_address("Vlan9", "8.8.8.0/24") + self.dvs_mirror.verify_session_status(session, status="inactive") # create neighbor to vlan 9 - self.add_neighbor("Vlan9", "8.8.8.8", "88:88:88:88:88:88") - assert self.get_mirror_session_state(session)["status"] == "inactive" + dvs.add_neighbor("Vlan9", "8.8.8.8", "88:88:88:88:88:88") + self.dvs_mirror.verify_session_status(session, status="inactive") # create fdb entry to ethernet48 - self.create_fdb("9", "88-88-88-88-88-88", "Ethernet48") - assert self.get_mirror_session_state(session)["status"] == "active" + dvs.create_fdb("9", "88-88-88-88-88-88", "Ethernet48") + self.dvs_mirror.verify_session_status(session) # check monitor port - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_MIRROR_SESSION") - mirror_entries = tbl.getKeys() - assert len(mirror_entries) == 1 - (status, fvs) = tbl.get(mirror_entries[0]) - assert status == True - for fv in fvs: - if fv[0] == "SAI_MIRROR_SESSION_ATTR_MONITOR_PORT": - assert dvs.asicdb.portoidmap[fv[1]] == "Ethernet48" - elif fv[0] == "SAI_MIRROR_SESSION_ATTR_VLAN_HEADER_VALID": - assert fv[1] == "true" - elif fv[0] == "SAI_MIRROR_SESSION_ATTR_VLAN_TPID": - assert fv[1] == "33024" - elif fv[0] == "SAI_MIRROR_SESSION_ATTR_VLAN_ID": - assert fv[1] == "9" - elif fv[0] == "SAI_MIRROR_SESSION_ATTR_VLAN_PRI": - assert fv[1] == "0" - elif fv[0] == "SAI_MIRROR_SESSION_ATTR_VLAN_CFI": - assert fv[1] == "0" - - session_status= "1:"+format(mirror_entries[0]) - # Verify port has mirror session enabled with session oid. - status = self.getPortAttr(dvs, src_oid, 'SAI_PORT_ATTR_INGRESS_MIRROR_SESSION') - assert status == session_status - # Verify port has egress mirror session enabled with session oid. - status = self.getPortAttr(dvs, src_oid, 'SAI_PORT_ATTR_EGRESS_MIRROR_SESSION') - assert status == session_status + expected_asic_db = {"SAI_MIRROR_SESSION_ATTR_MONITOR_PORT": pmap.get("Ethernet48"), + "SAI_MIRROR_SESSION_ATTR_VLAN_HEADER_VALID": "true", + "SAI_MIRROR_SESSION_ATTR_VLAN_TPID": "33024", + "SAI_MIRROR_SESSION_ATTR_VLAN_ID": "9", + "SAI_MIRROR_SESSION_ATTR_VLAN_PRI": "0", + "SAI_MIRROR_SESSION_ATTR_VLAN_CFI": "0"} + + self.dvs_mirror.verify_session(dvs, session, asic_db=expected_asic_db, src_ports=src_asic_ports) # mirror session move round 2 # remove fdb entry - self.remove_fdb("9", "88-88-88-88-88-88") - assert self.get_mirror_session_state(session)["status"] == "inactive" + dvs.remove_fdb("9", "88-88-88-88-88-88") + self.dvs_mirror.verify_session_status(session, status="inactive") # remove neighbor - self.remove_neighbor("Vlan9", "8.8.8.8") - assert self.get_mirror_session_state(session)["status"] == "inactive" + dvs.remove_neighbor("Vlan9", "8.8.8.8") + self.dvs_mirror.verify_session_status(session, status="inactive") # remove ip address - self.remove_ip_address("Vlan9", "8.8.8.0/24") - assert self.get_mirror_session_state(session)["status"] == "active" + dvs.remove_ip_address("Vlan9", "8.8.8.0/24") + self.dvs_mirror.verify_session_status(session) - # check monitor port - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_MIRROR_SESSION") - assert len(tbl.getKeys()) == 1 - (status, fvs) = tbl.get(tbl.getKeys()[0]) - assert status == True - for fv in fvs: - if fv[0] == "SAI_MIRROR_SESSION_ATTR_MONITOR_PORT": - assert dvs.asicdb.portoidmap[fv[1]] == "Ethernet32" - elif fv[0] == "SAI_MIRROR_SESSION_ATTR_VLAN_HEADER_VALID": - assert fv[1] == "false" + expected_asic_db = {"SAI_MIRROR_SESSION_ATTR_MONITOR_PORT": pmap.get("Ethernet32")} + self.dvs_mirror.verify_session(dvs, session, asic_db=expected_asic_db) # bring down vlan and member; remove vlan member; remove vlan - self.set_interface_status(dvs, "Ethernet48", "down") - self.set_interface_status(dvs, "Vlan9", "down") - self.remove_vlan_member("9", "Ethernet48") - self.remove_vlan("9") + dvs.set_interface_status("Ethernet48", "down") + dvs.set_interface_status("Vlan9", "down") + dvs.remove_vlan_member("9", "Ethernet48") + dvs.remove_vlan("9") # remove route; remove neighbor; remove ip; bring down port - self.remove_route(dvs, "8.8.8.0/24") - self.remove_neighbor("Ethernet32", "80.0.0.1") - self.remove_ip_address("Ethernet32", "80.0.0.0/31") - self.set_interface_status(dvs, "Ethernet32", "down") + dvs.remove_route("8.8.8.0/24") + dvs.remove_neighbor("Ethernet32", "80.0.0.1") + dvs.remove_ip_address("Ethernet32", "80.0.0.0/31") + dvs.set_interface_status("Ethernet32", "down") # remove mirror session - self.remove_mirror_session(session) + self.dvs_mirror.remove_mirror_session(session) + self.dvs_mirror.verify_no_mirror() def test_PortMirrorDestMoveLag(self, dvs, testlog): @@ -676,163 +371,98 @@ def test_PortMirrorDestMoveLag(self, dvs, testlog): 7. Disable non-LAG monitor port 8. Remove mirror session """ - self.setup_db(dvs) + dvs.setup_db() + pmap = dvs.counters_db.get_entry("COUNTERS_PORT_NAME_MAP", "") + pmap = dict(pmap) session = "TEST_SESSION" - src_port = "Ethernet0" - src_oid = self.getPortOid(dvs, src_port) - + src_ports = "Ethernet0,Ethernet4" + src_asic_ports = ["Ethernet0", "Ethernet4"] # create mirror session - self.create_mirror_erspan_session(session, "12.12.12.12", "13.13.13.13", "0x6558", "8", "100", "0", None, src_port, "RX") - assert self.get_mirror_session_state(session)["status"] == "inactive" + self.dvs_mirror.create_erspan_session(session, "12.12.12.12", "13.13.13.13", "0x6558", "8", "100", "0", None, src_ports, direction="RX") + self.dvs_mirror.verify_session_status(session, status="inactive") # bring up port; add ip; add neighbor; add route - self.set_interface_status(dvs, "Ethernet64", "up") - self.add_ip_address("Ethernet64", "100.0.0.0/31") - self.add_neighbor("Ethernet64", "100.0.0.1", "02:04:06:08:10:12") - self.add_route(dvs, "13.13.0.0/16", "100.0.0.1") - assert self.get_mirror_session_state(session)["status"] == "active" + dvs.set_interface_status("Ethernet64", "up") + dvs.add_ip_address("Ethernet64", "100.0.0.0/31") + dvs.add_neighbor("Ethernet64", "100.0.0.1", "02:04:06:08:10:12") + dvs.add_route("13.13.0.0/16", "100.0.0.1") + self.dvs_mirror.verify_session_status(session) # check monitor port - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_MIRROR_SESSION") - mirror_entries = tbl.getKeys() - assert len(mirror_entries) == 1 - (status, fvs) = tbl.get(mirror_entries[0]) - assert status == True - for fv in fvs: - if fv[0] == "SAI_MIRROR_SESSION_ATTR_MONITOR_PORT": - assert dvs.asicdb.portoidmap[fv[1]] == "Ethernet64" - if fv[0] == "SAI_MIRROR_SESSION_ATTR_DST_MAC_ADDRESS": - assert fv[1] == "02:04:06:08:10:12" - - session_status= "1:"+format(mirror_entries[0]) - # Verify port has mirror session enabled with session oid. - status = self.getPortAttr(dvs, src_oid, 'SAI_PORT_ATTR_INGRESS_MIRROR_SESSION') - assert status == session_status - # Verify port has egress mirror session enabled with session oid. - status = self.getPortAttr(dvs, src_oid, 'SAI_PORT_ATTR_EGRESS_MIRROR_SESSION') - assert status == None or status == "0:null" + expected_asic_db = {"SAI_MIRROR_SESSION_ATTR_MONITOR_PORT": pmap.get("Ethernet64"), + "SAI_MIRROR_SESSION_ATTR_DST_MAC_ADDRESS": "02:04:06:08:10:12"} + self.dvs_mirror.verify_session(dvs, session, asic_db=expected_asic_db, src_ports=src_asic_ports, direction="RX") # mirror session move round 1 # create port channel; create port channel member; bring up - self.create_port_channel(dvs, "080") - self.create_port_channel_member("080", "Ethernet32") - self.set_interface_status(dvs, "PortChannel080", "up") - self.set_interface_status(dvs, "Ethernet32", "up") + self.dvs_lag.create_port_channel("080") + lag_entries = self.dvs_vlan.asic_db.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_LAG", 1) + self.dvs_lag.create_port_channel_member("080", "Ethernet32") + dvs.set_interface_status("PortChannel080", "up") + dvs.set_interface_status("Ethernet32", "up") # add ip address to port channel 080; create neighbor to port channel 080 - self.add_ip_address("PortChannel080", "200.0.0.0/31") - self.add_neighbor("PortChannel080", "200.0.0.1", "12:10:08:06:04:02") - assert self.get_mirror_session_state(session)["status"] == "active" + dvs.add_ip_address("PortChannel080", "200.0.0.0/31") + dvs.add_neighbor("PortChannel080", "200.0.0.1", "12:10:08:06:04:02") + self.dvs_mirror.verify_session_status(session) # add route - self.add_route(dvs, "13.13.13.0/24", "200.0.0.1") - assert self.get_mirror_session_state(session)["status"] == "active" + dvs.add_route("13.13.13.0/24", "200.0.0.1") + self.dvs_mirror.verify_session_status(session) - # check monitor port - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_MIRROR_SESSION") - mirror_entries = tbl.getKeys() - assert len(mirror_entries) == 1 - (status, fvs) = tbl.get(mirror_entries[0]) - assert status == True - for fv in fvs: - if fv[0] == "SAI_MIRROR_SESSION_ATTR_MONITOR_PORT": - assert dvs.asicdb.portoidmap[fv[1]] == "Ethernet32" - if fv[0] == "SAI_MIRROR_SESSION_ATTR_DST_MAC_ADDRESS": - assert fv[1] == "12:10:08:06:04:02" - - session_status= "1:"+format(mirror_entries[0]) - # Verify port has mirror session enabled with session oid. - status = self.getPortAttr(dvs, src_oid, 'SAI_PORT_ATTR_INGRESS_MIRROR_SESSION') - assert status == session_status - # Verify port has egress mirror session enabled with session oid. - status = self.getPortAttr(dvs, src_oid, 'SAI_PORT_ATTR_EGRESS_MIRROR_SESSION') - assert status == None or status == "0:null" + expected_asic_db = {"SAI_MIRROR_SESSION_ATTR_MONITOR_PORT": pmap.get("Ethernet32"), + "SAI_MIRROR_SESSION_ATTR_DST_MAC_ADDRESS": "12:10:08:06:04:02"} + self.dvs_mirror.verify_session(dvs, session, asic_db=expected_asic_db, src_ports=src_asic_ports, direction="RX") # mirror session move round 2 # remove port channel member - self.remove_port_channel_member("080", "Ethernet32") - assert self.get_mirror_session_state(session)["status"] == "inactive" + self.dvs_lag.remove_port_channel_member("080", "Ethernet32") + self.dvs_mirror.verify_session_status(session, status="inactive") # mirror session move round 3 # create port channel member - self.create_port_channel_member("080", "Ethernet32") - assert self.get_mirror_session_state(session)["status"] == "active" + self.dvs_lag.create_port_channel_member("080", "Ethernet32") + self.dvs_mirror.verify_session_status(session) # check monitor port - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_MIRROR_SESSION") - mirror_entries = tbl.getKeys() - assert len(mirror_entries) == 1 - (status, fvs) = tbl.get(mirror_entries[0]) - assert status == True - for fv in fvs: - if fv[0] == "SAI_MIRROR_SESSION_ATTR_MONITOR_PORT": - assert dvs.asicdb.portoidmap[fv[1]] == "Ethernet32" - if fv[0] == "SAI_MIRROR_SESSION_ATTR_DST_MAC_ADDRESS": - assert fv[1] == "12:10:08:06:04:02" - - session_status= "1:"+format(mirror_entries[0]) - # Verify port has mirror session enabled with session oid. - status = self.getPortAttr(dvs, src_oid, 'SAI_PORT_ATTR_INGRESS_MIRROR_SESSION') - assert status == session_status - # Verify port has egress mirror session enabled with session oid. - status = self.getPortAttr(dvs, src_oid, 'SAI_PORT_ATTR_EGRESS_MIRROR_SESSION') - assert status == None or status == "0:null" + expected_asic_db = {"SAI_MIRROR_SESSION_ATTR_MONITOR_PORT": pmap.get("Ethernet32"), + "SAI_MIRROR_SESSION_ATTR_DST_MAC_ADDRESS": "12:10:08:06:04:02"} + self.dvs_mirror.verify_session(dvs, session, asic_db=expected_asic_db, src_ports=src_asic_ports, direction="RX") # mirror session move round 4 # remove route - self.remove_route(dvs, "13.13.13.0/24") - assert self.get_mirror_session_state(session)["status"] == "active" + dvs.remove_route("13.13.13.0/24") + self.dvs_mirror.verify_session_status(session) - port_oid = "" # check monitor port - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_MIRROR_SESSION") - mirror_entries = tbl.getKeys() - assert len(mirror_entries) == 1 - - (status, fvs) = tbl.get(mirror_entries[0]) - assert status == True - for fv in fvs: - if fv[0] == "SAI_MIRROR_SESSION_ATTR_MONITOR_PORT": - assert dvs.asicdb.portoidmap[fv[1]] == "Ethernet64" - if fv[0] == "SAI_MIRROR_SESSION_ATTR_DST_MAC_ADDRESS": - assert fv[1] == "02:04:06:08:10:12" - - session_status= "1:"+format(mirror_entries[0]) - # Verify port has mirror session enabled with session oid. - status = self.getPortAttr(dvs, src_oid, 'SAI_PORT_ATTR_INGRESS_MIRROR_SESSION') - assert status == session_status - # Verify port has egress mirror session enabled with session oid. - status = self.getPortAttr(dvs, src_oid, 'SAI_PORT_ATTR_EGRESS_MIRROR_SESSION') - assert status == None or status == "0:null" + expected_asic_db = {"SAI_MIRROR_SESSION_ATTR_MONITOR_PORT": pmap.get("Ethernet64"), + "SAI_MIRROR_SESSION_ATTR_DST_MAC_ADDRESS": "02:04:06:08:10:12"} + self.dvs_mirror.verify_session(dvs, session, asic_db=expected_asic_db, src_ports=src_asic_ports, direction="RX") # remove neighbor; remove ip address to port channel 080 - self.remove_neighbor("PortChannel080", "200.0.0.1") - self.remove_ip_address("PortChannel080", "200.0.0.0/31") + dvs.remove_neighbor("PortChannel080", "200.0.0.1") + dvs.remove_ip_address("PortChannel080", "200.0.0.0/31") # bring down; remove port channel member; remove port channel - self.set_interface_status(dvs, "Ethernet32", "down") - self.set_interface_status(dvs, "PortChannel080", "down") - self.remove_port_channel_member("080", "Ethernet32") - self.remove_port_channel(dvs, "080") - assert self.get_mirror_session_state(session)["status"] == "active" + dvs.set_interface_status("Ethernet32", "down") + dvs.set_interface_status("PortChannel080", "down") + self.dvs_lag.remove_port_channel_member("080", "Ethernet32") + self.dvs_lag.remove_port_channel("080") + self.dvs_mirror.verify_session_status(session) + # remove route; remove neighbor; remove ip; bring down port - self.remove_route(dvs, "13.13.0.0/16") - self.remove_neighbor("Ethernet64", "100.0.0.1") - self.remove_ip_address("Ethernet64", "100.0.0.0/31") - self.set_interface_status(dvs, "Ethernet64", "down") - assert self.get_mirror_session_state(session)["status"] == "inactive" - - # Verify port has mirror session enabled with session oid. - status = self.getPortAttr(dvs, src_oid, 'SAI_PORT_ATTR_INGRESS_MIRROR_SESSION') - assert status == None or status == "0:null" - # Verify port has egress mirror session enabled with session oid. - status = self.getPortAttr(dvs, src_oid, 'SAI_PORT_ATTR_EGRESS_MIRROR_SESSION') - assert status == None or status == "0:null" + dvs.remove_route("13.13.0.0/16") + dvs.remove_neighbor("Ethernet64", "100.0.0.1") + dvs.remove_ip_address("Ethernet64", "100.0.0.0/31") + dvs.set_interface_status("Ethernet64", "down") + self.dvs_mirror.verify_session_status(session, status="inactive") + # remove mirror session - self.remove_mirror_session(session) + self.dvs_mirror.remove_mirror_session(session) + self.dvs_mirror.verify_no_mirror() def test_LAGMirrorToERSPANLagAddRemove(self, dvs, testlog): """ @@ -847,105 +477,73 @@ def test_LAGMirrorToERSPANLagAddRemove(self, dvs, testlog): 5. Remove mirror session """ - self.setup_db(dvs) + dvs.setup_db() + pmap = dvs.counters_db.get_entry("COUNTERS_PORT_NAME_MAP", "") + pmap = dict(pmap) session = "TEST_SESSION" - po_src_port = "PortChannel001" - src_port1 = "Ethernet0" - src_port2 = "Ethernet4" - src_oid1 = self.getPortOid(dvs, src_port1) - src_oid2 = self.getPortOid(dvs, src_port2) + src_port1="Ethernet0" + po_src_port="PortChannel001" + src_port2="Ethernet4" + src_ports = "PortChannel001,Ethernet8" + src_asic_ports = ["Ethernet0", "Ethernet4", "Ethernet8"] # create port channel; create port channel member - self.create_port_channel(dvs, "001") - self.create_port_channel_member("001", src_port1) - self.create_port_channel_member("001", src_port2) + self.dvs_lag.create_port_channel("001") + self.dvs_vlan.asic_db.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_LAG", 1) + self.dvs_lag.create_port_channel_member("001", src_port1) + self.dvs_lag.create_port_channel_member("001", src_port2) # bring up port channel and port channel member - self.set_interface_status(dvs, po_src_port, "up") - self.set_interface_status(dvs, src_port1, "up") - self.set_interface_status(dvs, src_port2, "up") + dvs.set_interface_status(po_src_port, "up") + dvs.set_interface_status(src_port1, "up") + dvs.set_interface_status(src_port2, "up") # create mirror session - self.create_mirror_erspan_session(session, "10.10.10.10", "11.11.11.11", "0x6558", "8", "100", "0", None, po_src_port, "BOTH") - assert self.get_mirror_session_state(session)["status"] == "inactive" - + self.dvs_mirror.create_erspan_session(session, "10.10.10.10", "11.11.11.11", "0x6558", "8", "100", "0", None, src_ports) + self.dvs_mirror.verify_session_status(session, status="inactive") + # create port channel; create port channel member - self.create_port_channel(dvs, "008") - self.create_port_channel_member("008", "Ethernet88") + self.dvs_lag.create_port_channel("008") + lag_entries = self.dvs_vlan.asic_db.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_LAG", 2) + self.dvs_lag.create_port_channel_member("008", "Ethernet88") # bring up port channel and port channel member - self.set_interface_status(dvs, "PortChannel008", "up") - self.set_interface_status(dvs, "Ethernet88", "up") + dvs.set_interface_status("PortChannel008", "up") + dvs.set_interface_status("Ethernet88", "up") # add ip address to port channel 008 - self.add_ip_address("PortChannel008", "11.11.11.0/24") - assert self.get_mirror_session_state(session)["status"] == "inactive" + dvs.add_ip_address("PortChannel008", "11.11.11.0/24") + self.dvs_mirror.verify_session_status(session, status="inactive") # create neighbor to port channel 008 - self.add_neighbor("PortChannel008", "11.11.11.11", "88:88:88:88:88:88") - assert self.get_mirror_session_state(session)["status"] == "active" + dvs.add_neighbor("PortChannel008", "11.11.11.11", "88:88:88:88:88:88") + self.dvs_mirror.verify_session_status(session) # Check src_port state. - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_MIRROR_SESSION") - mirror_entries = tbl.getKeys() - assert len(mirror_entries) == 1 - (status, fvs) = tbl.get(tbl.getKeys()[0]) - assert status == True - for fv in fvs: - if fv[0] == "SAI_MIRROR_SESSION_ATTR_MONITOR_PORT": - assert dvs.asicdb.portoidmap[fv[1]] == "Ethernet88" - elif fv[0] == "SAI_MIRROR_SESSION_ATTR_DST_MAC_ADDRESS": - assert fv[1] == "88:88:88:88:88:88" - - session_status= "1:"+format(mirror_entries[0]) - # Verify port has mirror session enabled with session oid. - status = self.getPortAttr(dvs, src_oid1, 'SAI_PORT_ATTR_INGRESS_MIRROR_SESSION') - assert status == session_status - # Verify port has egress mirror session enabled with session oid. - session_status = self.getPortAttr(dvs, src_oid1, 'SAI_PORT_ATTR_EGRESS_MIRROR_SESSION') - assert status == session_status - - # Verify port has mirror session enabled with session oid. - status = self.getPortAttr(dvs, src_oid2, 'SAI_PORT_ATTR_INGRESS_MIRROR_SESSION') - assert status == session_status - # Verify port has egress mirror session enabled with session oid. - session_status = self.getPortAttr(dvs, src_oid2, 'SAI_PORT_ATTR_EGRESS_MIRROR_SESSION') - assert status == session_status + expected_asic_db = {"SAI_MIRROR_SESSION_ATTR_MONITOR_PORT": pmap.get("Ethernet88"), + "SAI_MIRROR_SESSION_ATTR_DST_MAC_ADDRESS": "88:88:88:88:88:88"} + + self.dvs_mirror.verify_session(dvs, session, asic_db=expected_asic_db, src_ports=src_asic_ports) + # remove neighbor - self.remove_neighbor("PortChannel008", "11.11.11.11") - assert self.get_mirror_session_state(session)["status"] == "inactive" + dvs.remove_neighbor("PortChannel008", "11.11.11.11") + self.dvs_mirror.verify_session_status(session, status="inactive") # remove ip address - self.remove_ip_address("PortChannel008", "11.11.11.0/24") - assert self.get_mirror_session_state(session)["status"] == "inactive" - - #verify mirror config is removed from LAG source ports. - session_status= "1:"+format(mirror_entries[0]) - # Verify port has mirror session enabled with session oid. - status = self.getPortAttr(dvs, src_oid1, 'SAI_PORT_ATTR_INGRESS_MIRROR_SESSION') - assert status == None or status == "0:null" - # Verify port has egress mirror session enabled with session oid. - status = self.getPortAttr(dvs, src_oid1, 'SAI_PORT_ATTR_EGRESS_MIRROR_SESSION') - assert status == None or status == "0:null" - - # Verify port has mirror session enabled with session oid. - status = self.getPortAttr(dvs, src_oid2, 'SAI_PORT_ATTR_INGRESS_MIRROR_SESSION') - assert status == None or status == "0:null" - # Verify port has egress mirror session enabled with session oid. - session_status = self.getPortAttr(dvs, src_oid2, 'SAI_PORT_ATTR_EGRESS_MIRROR_SESSION') - assert status == None or status == "0:null" - + dvs.remove_ip_address("PortChannel008", "11.11.11.0/24") + self.dvs_mirror.verify_session_status(session, status="inactive") # bring down port channel and port channel member - self.set_interface_status(dvs, "PortChannel008", "down") - self.set_interface_status(dvs, "Ethernet88", "down") + dvs.set_interface_status("PortChannel008", "down") + dvs.set_interface_status("Ethernet88", "down") # remove port channel member; remove port channel - self.remove_port_channel_member("008", "Ethernet88") - self.remove_port_channel(dvs, "008") - self.remove_port_channel_member("001", src_port1) - self.remove_port_channel_member("001", src_port2) - self.remove_port_channel(dvs, "001") + self.dvs_lag.remove_port_channel_member("008", "Ethernet88") + self.dvs_lag.remove_port_channel("008") + self.dvs_lag.remove_port_channel_member("001", src_port1) + self.dvs_lag.remove_port_channel_member("001", src_port2) + self.dvs_lag.remove_port_channel("001") # remove mirror session - self.remove_mirror_session(session) \ No newline at end of file + self.dvs_mirror.remove_mirror_session(session) + self.dvs_mirror.verify_no_mirror() diff --git a/tests/test_mirror_port_span.py b/tests/test_mirror_port_span.py index 77fbce5864..e2dc18a438 100644 --- a/tests/test_mirror_port_span.py +++ b/tests/test_mirror_port_span.py @@ -6,112 +6,14 @@ from swsscommon import swsscommon from distutils.version import StrictVersion +@pytest.mark.usefixtures("testlog") +@pytest.mark.usefixtures('dvs_vlan_manager') +@pytest.mark.usefixtures('dvs_lag_manager') +@pytest.mark.usefixtures('dvs_mirror_manager') +@pytest.mark.usefixtures('dvs_acl_manager') +@pytest.mark.usefixtures('dvs_policer_manager') class TestMirror(object): - def setup_db(self, dvs): - self.pdb = swsscommon.DBConnector(0, dvs.redis_sock, 0) - self.adb = swsscommon.DBConnector(1, dvs.redis_sock, 0) - self.cdb = swsscommon.DBConnector(4, dvs.redis_sock, 0) - self.sdb = swsscommon.DBConnector(6, dvs.redis_sock, 0) - - def set_interface_status(self, dvs, interface, admin_status): - if interface.startswith("PortChannel"): - tbl_name = "PORTCHANNEL" - elif interface.startswith("Vlan"): - tbl_name = "VLAN" - else: - tbl_name = "PORT" - tbl = swsscommon.Table(self.cdb, tbl_name) - fvs = swsscommon.FieldValuePairs([("admin_status", "up")]) - tbl.set(interface, fvs) - time.sleep(1) - - # when using FRR, route cannot be inserted if the neighbor is not - # connected. thus it is mandatory to force the interface up manually - if interface.startswith("PortChannel"): - dvs.runcmd("bash -c 'echo " + ("1" if admin_status == "up" else "0") +\ - " > /sys/class/net/" + interface + "/carrier'") - - def getPortOid(self, dvs, port_name): - - cnt_db = swsscommon.DBConnector(swsscommon.COUNTERS_DB, dvs.redis_sock, 0) - port_map_tbl = swsscommon.Table(cnt_db, 'COUNTERS_PORT_NAME_MAP') - - for k in port_map_tbl.get('')[1]: - if k[0] == port_name: - return k[1] - - - def getPortAttr(self, dvs, port_oid, port_attr): - - asic_db = swsscommon.DBConnector(swsscommon.ASIC_DB, dvs.redis_sock, 0) - port_tbl = swsscommon.Table(asic_db, 'ASIC_STATE:SAI_OBJECT_TYPE_PORT:{0}'.format(port_oid)) - - for k in port_tbl.get('')[1]: - if k[0] == port_attr: - return k[1] - - def create_mirror_span_session(self, name, dst_port, src_port=None, direction=None, queue=None, policer=None): - tbl = swsscommon.Table(self.cdb, "MIRROR_SESSION") - if src_port is None and direction is None: - if queue is None and policer is None: - fvs = swsscommon.FieldValuePairs([("type", "SPAN"), - ("dst_port", dst_port)]) - elif queue is None: - fvs = swsscommon.FieldValuePairs([("type", "SPAN"), - ("dst_port", dst_port), - ("policer", policer)]) - elif policer is None: - fvs = swsscommon.FieldValuePairs([("type", "SPAN"), - ("dst_port", dst_port), - ("queue", queue)]) - else: - fvs = swsscommon.FieldValuePairs([("type", "SPAN"), - ("dst_port", dst_port), - ("queue", queue), - ("policer", policer)]) - else: - if queue is None and policer is None: - fvs = swsscommon.FieldValuePairs([("type", "SPAN"), - ("dst_port", dst_port), - ("src_port", src_port), - ("direction", direction)]) - elif queue is None: - fvs = swsscommon.FieldValuePairs([("type", "SPAN"), - ("dst_port", dst_port), - ("src_port", src_port), - ("direction", direction), - ("policer", policer)]) - elif policer is None: - fvs = swsscommon.FieldValuePairs([("type", "SPAN"), - ("dst_port", dst_port), - ("src_port", src_port), - ("direction", direction), - ("queue", queue)]) - tbl.set(name, fvs) - time.sleep(2) - - def remove_mirror_session(self, name): - tbl = swsscommon.Table(self.cdb, "MIRROR_SESSION") - tbl._del(name) - time.sleep(1) - - def get_mirror_session_status(self, name): - return self.get_mirror_session_state(name)["status"] - - def get_mirror_session_state(self, name): - tbl = swsscommon.Table(self.sdb, "MIRROR_SESSION_TABLE") - (status, fvs) = tbl.get(name) - assert status == True - assert len(fvs) > 0 - return { fv[0]: fv[1] for fv in fvs } - - def check_mirror_session_state(self, name, status): - tbl = swsscommon.Table(self.sdb, "MIRROR_SESSION_TABLE") - (session_status, fvs) = tbl.get(name) - assert session_status == status - - @pytest.mark.skipif(StrictVersion(platform.linux_distribution()[1]) <= StrictVersion('8.9'), reason="Debian 8.9 or before has no support") def test_PortMirrorAddRemove(self, dvs, testlog): """ This test covers the basic SPAN mirror session creation and removal operations @@ -120,466 +22,264 @@ def test_PortMirrorAddRemove(self, dvs, testlog): 2. Create mirror session with invalid dst_port, verify session doesnt get created. 3. Create mirror session with invalid source port, verify session doesnt get created. 4. Create mirror session with source port, verify session becomes active + 5. Create mirror session with Vlan as dst_port, verify session doesnt get created. + 6. Create mirror session with Vlan as source port, verify session doesnt get created. """ - self.setup_db(dvs) + + pmap = dvs.counters_db.get_entry("COUNTERS_PORT_NAME_MAP", "") + pmap = dict(pmap) session = "TEST_SESSION" - src_port = "Ethernet12" dst_port = "Ethernet16" - invld_port = "Invalid" - src_oid = self.getPortOid(dvs, src_port) - + # Sub Test 1 - # create mirror session - self.create_mirror_span_session(session, "Ethernet16") - assert self.get_mirror_session_state(session)["status"] == "active" - - # check asic database - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_MIRROR_SESSION") - mirror_entries = tbl.getKeys() - assert len(mirror_entries) == 1 - - # verify asicdb - (status, fvs) = tbl.get(mirror_entries[0]) - assert status == True - assert len(fvs) == 2 - for fv in fvs: - if fv[0] == "SAI_MIRROR_SESSION_ATTR_MONITOR_PORT": - assert dvs.asicdb.portoidmap[fv[1]] == "Ethernet16" - elif fv[0] == "SAI_MIRROR_SESSION_ATTR_TYPE": - assert fv[1] == "SAI_MIRROR_SESSION_TYPE_LOCAL" - - # remove mirror session - self.remove_mirror_session(session) + self.dvs_mirror.create_span_session(session, dst_port) + self.dvs_mirror.verify_session_status(session) + a = {"SAI_MIRROR_SESSION_ATTR_MONITOR_PORT": pmap.get("Ethernet16"), + "SAI_MIRROR_SESSION_ATTR_TYPE": "SAI_MIRROR_SESSION_TYPE_LOCAL"} + self.dvs_mirror.verify_session(dvs, session, asic_db=a) + self.dvs_mirror.remove_mirror_session(session) # Sub Test 2 - # create mirror session with invalid dst_port - self.create_mirror_span_session(session, invld_port) - self.check_mirror_session_state(session, False) + self.dvs_mirror.create_span_session(session, "Invalid") + self.dvs_mirror.verify_session_status(session, expected=0) # Sub Test 3 - # create mirror session with invalid src_port - self.create_mirror_span_session(session, dst_port, invld_port, "RX") - self.check_mirror_session_state(session, False) + self.dvs_mirror.create_span_session(session, dst_port, "Invalid", "RX") + self.dvs_mirror.verify_session_status(session, expected=0) # Sub Test 4 # create mirror session with dst_port, src_port, direction - self.create_mirror_span_session(session, dst_port, src_port, "RX") - assert self.get_mirror_session_state(session)["status"] == "active" - - #verify asicdb - mirror_entries = tbl.getKeys() - (status, fvs) = tbl.get(mirror_entries[0]) - assert status == True - assert len(fvs) == 2 - for fv in fvs: - if fv[0] == "SAI_MIRROR_SESSION_ATTR_MONITOR_PORT": - assert dvs.asicdb.portoidmap[fv[1]] == "Ethernet16" - elif fv[0] == "SAI_MIRROR_SESSION_ATTR_TYPE": - assert fv[1] == "SAI_MIRROR_SESSION_TYPE_LOCAL" - - session_status= "1:"+format(mirror_entries[0]) - # Verify port has mirror session enabled with session oid. - status = self.getPortAttr(dvs, src_oid, 'SAI_PORT_ATTR_INGRESS_MIRROR_SESSION') - assert status == session_status - # Verify port has egress mirror session enabled with session oid. - status = self.getPortAttr(dvs, src_oid, 'SAI_PORT_ATTR_EGRESS_MIRROR_SESSION') - assert status == None or status == "0:null" - - # remove mirror session - self.remove_mirror_session(session) + src_ports = "Ethernet12" + src_asic_ports = ["Ethernet12"] + self.dvs_mirror.create_span_session(session, dst_port, src_ports, "RX") + self.dvs_mirror.verify_session_status(session) + self.dvs_mirror.verify_session(dvs, session, asic_db=a, src_ports=src_asic_ports, direction = "RX") + self.dvs_mirror.remove_mirror_session(session) + self.dvs_mirror.verify_no_mirror() + + ## Sub Test 5 + self.dvs_vlan.create_vlan("10") + self.dvs_mirror.create_span_session(session, dst_port="Vlan10") + self.dvs_mirror.verify_session_status(session, expected=0) + + ## Sub Test 6 + self.dvs_mirror.create_span_session(session, dst_port, src_ports="Vlan10") + self.dvs_mirror.verify_session_status(session, expected=0) + self.dvs_mirror.remove_mirror_session(session) + self.dvs_mirror.verify_no_mirror() + self.dvs_vlan.remove_vlan("10") + def test_PortMirrorMultiSpanAddRemove(self, dvs, testlog): """ This test covers the Multiple SPAN mirror session creation and removal operations Operation flow: 1. Create mirror session with multiple source ports, verify that session is active - 2. Create mirror session with multiple source with valid,invalid ports, session becomes inactive. - 3. Create multiple mirror sessions with multiple source ports. - 4. Create mirror session with invalid source port, the session becomes inactive, - 5. Create mirror session with multiple source ports, the session becomes active - 6. Create mirror session with valid and invalid source ports, the session becomes inactive - 5. Remove mirror session + 2. Create mirror session with multiple source with valid,invalid ports, session doesnt get created. + 3. Create mirror session with multiple source with invalid destination, session doesnt get created. + 4. Create two mirror sessions with multiple source ports. + 5. Verify session config in both sessions. """ - self.setup_db(dvs) + + pmap = dvs.counters_db.get_entry("COUNTERS_PORT_NAME_MAP", "") + pmap = dict(pmap) session1 = "TEST_SESSION1" session2 = "TEST_SESSION2" - src_port1 = "Ethernet0" - src_port2 = "Ethernet4" - src_port3 = "Ethernet8" - src_port4 = "Ethernet12" dst_port1 = "Ethernet16" + dst_oid1 = pmap.get(dst_port1) dst_port2 = "Ethernet20" - invld_port = "Ethernet" - src_oid1 = self.getPortOid(dvs, src_port1) - src_oid2 = self.getPortOid(dvs, src_port2) - src_oid3 = self.getPortOid(dvs, src_port3) - src_oid4 = self.getPortOid(dvs, src_port4) - queue = 1 + dst_oid2 = pmap.get(dst_port2) # Sub test 1 - # Create mirror session with multiple source ports, verify that session is active - self.create_mirror_span_session(session1, dst_port1, src_port1+","+src_port2+","+src_port3, "BOTH") - assert self.get_mirror_session_state(session1)["status"] == "active" - - # check asic database - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_MIRROR_SESSION") - mirror_entries = tbl.getKeys() - assert len(mirror_entries) == 1 + src_ports = "Ethernet0,Ethernet4,Ethernet8" + src_asic_ports = ["Ethernet0","Ethernet4","Ethernet8"] + self.dvs_mirror.create_span_session(session1, dst_port1, src_ports) + a = {"SAI_MIRROR_SESSION_ATTR_MONITOR_PORT": dst_oid1, + "SAI_MIRROR_SESSION_ATTR_TYPE": "SAI_MIRROR_SESSION_TYPE_LOCAL"} + self.dvs_mirror.verify_session_status(session1) + self.dvs_mirror.verify_session(dvs, session1, asic_db=a, src_ports=src_asic_ports) + self.dvs_mirror.remove_mirror_session(session1) + self.dvs_mirror.verify_no_mirror() - # verify asicdb - (status, fvs) = tbl.get(mirror_entries[0]) - assert status == True - assert len(fvs) == 2 - for fv in fvs: - if fv[0] == "SAI_MIRROR_SESSION_ATTR_MONITOR_PORT": - assert dvs.asicdb.portoidmap[fv[1]] == dst_port1 - elif fv[0] == "SAI_MIRROR_SESSION_ATTR_TYPE": - assert fv[1] == "SAI_MIRROR_SESSION_TYPE_LOCAL" - - session_status= "1:"+format(mirror_entries[0]) - # Verify port has mirror session enabled with session oid. - status = self.getPortAttr(dvs, src_oid1, 'SAI_PORT_ATTR_INGRESS_MIRROR_SESSION') - assert status == session_status - # Verify port has egress mirror session enabled with session oid. - session_status = self.getPortAttr(dvs, src_oid1, 'SAI_PORT_ATTR_EGRESS_MIRROR_SESSION') - assert status == session_status - - # Verify port has mirror session enabled with session oid. - status = self.getPortAttr(dvs, src_oid2, 'SAI_PORT_ATTR_INGRESS_MIRROR_SESSION') - assert status == session_status - # Verify port has egress mirror session enabled with session oid. - session_status = self.getPortAttr(dvs, src_oid2, 'SAI_PORT_ATTR_EGRESS_MIRROR_SESSION') - assert status == session_status - - # Verify port has mirror session enabled with session oid. - status = self.getPortAttr(dvs, src_oid3, 'SAI_PORT_ATTR_INGRESS_MIRROR_SESSION') - assert status == session_status - # Verify port has egress mirror session enabled with session oid. - session_status = self.getPortAttr(dvs, src_oid3, 'SAI_PORT_ATTR_EGRESS_MIRROR_SESSION') - assert status == session_status - - # remove mirror session - self.remove_mirror_session(session1) - #Subtest 2 + # create mirror session with valid and invalid ports. - self.create_mirror_span_session(session1, dst_port1, src_port1+','+invld_port+','+src_port2, "BOTH") - self.check_mirror_session_state(session1, False) + src_ports = "Ethernet0,Invalid,Ethernet8" + self.dvs_mirror.create_span_session(session1, dst_port1, src_ports) + self.dvs_mirror.verify_session_status(session1, expected=0) # Subtest 3 - # create mirror session with multiple source ports. - self.create_mirror_span_session(session1, invld_port, src_port1+','+src_port2+','+src_port3, "BOTH") - self.check_mirror_session_state(session1, False) + src_ports = "Ethernet0,Ethernet4,Ethernet8" + self.dvs_mirror.create_span_session(session1, "Invalid", src_ports) + self.dvs_mirror.verify_session_status(session1, expected=0) # create mirror session - self.create_mirror_span_session(session1, dst_port1, src_port1+","+src_port2, "BOTH") - assert self.get_mirror_session_state(session1)["status"] == "active" - self.create_mirror_span_session(session2, dst_port2, src_port3+","+src_port4, "BOTH") - assert self.get_mirror_session_state(session2)["status"] == "active" - - # check asic database - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_MIRROR_SESSION") - mirror_entries = tbl.getKeys() - assert len(mirror_entries) == 2 - - # verify asicdb - (status1, fvs1) = tbl.get(mirror_entries[0]) - (status2, fvs2) = tbl.get(mirror_entries[1]) - assert status1 == True and status2 == True - assert len(fvs1) == 2 and len(fvs2) == 2 - for fv in fvs1: - if fv[0] == "SAI_MIRROR_SESSION_ATTR_MONITOR_PORT": - if dvs.asicdb.portoidmap[fv[1]] == dst_port1: - session_oid1 = mirror_entries[0] - if dvs.asicdb.portoidmap[fv[1]] == dst_port2: - session_oid2 = mirror_entries[0] - - for fv in fvs2: - if fv[0] == "SAI_MIRROR_SESSION_ATTR_MONITOR_PORT": - if dvs.asicdb.portoidmap[fv[1]] == dst_port1: - session_oid1 = mirror_entries[1] - if dvs.asicdb.portoidmap[fv[1]] == dst_port2: - session_oid2 = mirror_entries[1] - assert session_oid1 is not None or session_oid2 is not None - - (status1, fvs1) = tbl.get(session_oid1) - for fv in fvs1: - if fv[0] == "SAI_MIRROR_SESSION_ATTR_MONITOR_PORT": - assert dvs.asicdb.portoidmap[fv[1]] == dst_port1 - elif fv[0] == "SAI_MIRROR_SESSION_ATTR_TYPE": - assert fv[1] == "SAI_MIRROR_SESSION_TYPE_LOCAL" - elif fv[0] == "SAI_MIRROR_SESSION_ATTR_POLICER": - assert fv[1] == policer_oid1 - - (status1, fvs2) = tbl.get(session_oid2) - for fv in fvs2: - if fv[0] == "SAI_MIRROR_SESSION_ATTR_MONITOR_PORT": - assert dvs.asicdb.portoidmap[fv[1]] == dst_port2 - elif fv[0] == "SAI_MIRROR_SESSION_ATTR_TYPE": - assert fv[1] == "SAI_MIRROR_SESSION_TYPE_LOCAL" - elif fv[0] == "SAI_MIRROR_SESSION_ATTR_POLICER": - assert fv[1] == policer_oid2 - - # check asic database - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_MIRROR_SESSION") - mirror_entries = tbl.getKeys() - assert len(mirror_entries) == 2 - - session_status1= "1:"+format(session_oid1) - session_status2="1:"+format(session_oid2) - # Verify port has mirror session enabled with session oid. - status = self.getPortAttr(dvs, src_oid1, 'SAI_PORT_ATTR_INGRESS_MIRROR_SESSION') - assert status == session_status1 - # Verify port has egress mirror session enabled with session oid. - status = self.getPortAttr(dvs, src_oid1, 'SAI_PORT_ATTR_EGRESS_MIRROR_SESSION') - assert status == session_status1 - - # Verify port has mirror session enabled with session oid. - status = self.getPortAttr(dvs, src_oid2, 'SAI_PORT_ATTR_INGRESS_MIRROR_SESSION') - assert status == session_status1 - # Verify port has egress mirror session enabled with session oid. - status = self.getPortAttr(dvs, src_oid2, 'SAI_PORT_ATTR_EGRESS_MIRROR_SESSION') - assert status == session_status1 - - # Verify port has mirror session enabled with session oid. - status = self.getPortAttr(dvs, src_oid3, 'SAI_PORT_ATTR_INGRESS_MIRROR_SESSION') - assert status == session_status2 - # Verify port has egress mirror session enabled with session oid. - status = self.getPortAttr(dvs, src_oid3, 'SAI_PORT_ATTR_EGRESS_MIRROR_SESSION') - assert status == session_status2 - - # Verify port has mirror session enabled with session oid. - status = self.getPortAttr(dvs, src_oid4, 'SAI_PORT_ATTR_INGRESS_MIRROR_SESSION') - assert status == session_status2 - # Verify port has egress mirror session enabled with session oid. - status = self.getPortAttr(dvs, src_oid4, 'SAI_PORT_ATTR_EGRESS_MIRROR_SESSION') - assert status == session_status2 - - # remove mirror session - self.remove_mirror_session(session1) - self.remove_mirror_session(session2) - - def create_policer(self, name): - tbl = swsscommon.Table(self.cdb, "POLICER") - fvs = swsscommon.FieldValuePairs([("meter_type", "packets"), - ("mode", "sr_tcm"), - ("cir", "600"), - ("cbs", "600"), - ("red_packet_action", "drop")]) - tbl.set(name, fvs) - time.sleep(1) - - def remove_policer(self, name): - tbl = swsscommon.Table(self.cdb, "POLICER") - tbl._del(name) - time.sleep(1) + src_ports1 = "Ethernet0,Ethernet4" + src_asic_ports1 = ["Ethernet0","Ethernet4"] + self.dvs_mirror.create_span_session(session1, dst_port1, src_ports1) + src_ports2 = "Ethernet8,Ethernet12" + src_asic_ports2 = ["Ethernet8","Ethernet12"] + self.dvs_mirror.create_span_session(session2, dst_port2, src_ports2) + + a1 = {"SAI_MIRROR_SESSION_ATTR_MONITOR_PORT": dst_oid1, + "SAI_MIRROR_SESSION_ATTR_TYPE": "SAI_MIRROR_SESSION_TYPE_LOCAL"} + a2 = {"SAI_MIRROR_SESSION_ATTR_MONITOR_PORT": dst_oid2, + "SAI_MIRROR_SESSION_ATTR_TYPE": "SAI_MIRROR_SESSION_TYPE_LOCAL"} + self.dvs_mirror.verify_session_status(session1, expected = 2) + self.dvs_mirror.verify_session_status(session2, expected = 2) + self.dvs_mirror.verify_session(dvs, session1, dst_oid=dst_oid1, asic_db=a1, src_ports=src_asic_ports1, expected = 2) + self.dvs_mirror.verify_session(dvs, session2, dst_oid=dst_oid2, asic_db=a2, src_ports=src_asic_ports2, expected = 2) + self.dvs_mirror.remove_mirror_session(session1) + self.dvs_mirror.remove_mirror_session(session2) + self.dvs_mirror.verify_no_mirror() def test_PortMirrorPolicerAddRemove(self, dvs, testlog): """ This test covers the basic SPAN mirror session creation and removal operations Operation flow: 1. Create mirror session with only dst_port and policer , verify session becomes active - 2. Verify policer config is proper. + 2. Create session with invalid policer, verify session doesnt get created. + 2. Create mirror with policer and multiple source ports, verify session config on all ports. """ - self.setup_db(dvs) - + pmap = dvs.counters_db.get_entry("COUNTERS_PORT_NAME_MAP", "") + pmap = dict(pmap) session = "TEST_SESSION" - src_port = "Ethernet12" dst_port = "Ethernet16" - invld_port = "Invalid" - policer= "POLICER" - src_oid = self.getPortOid(dvs, src_port) - - # create policer - self.create_policer(policer) - - # Sub Test 1 - # create mirror session - self.create_mirror_span_session(session, "Ethernet16", None, None, None, policer) - assert self.get_mirror_session_state(session)["status"] == "active" - - # check asic database - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_POLICER") - policer_entries = tbl.getKeys() - assert len(policer_entries) == 1 - policer_oid = policer_entries[0] - - # check asic database - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_MIRROR_SESSION") - mirror_entries = tbl.getKeys() - assert len(mirror_entries) == 1 - - # verify asicdb - (status, fvs) = tbl.get(mirror_entries[0]) - assert status == True - assert len(fvs) == 3 - for fv in fvs: - if fv[0] == "SAI_MIRROR_SESSION_ATTR_MONITOR_PORT": - assert dvs.asicdb.portoidmap[fv[1]] == "Ethernet16" - elif fv[0] == "SAI_MIRROR_SESSION_ATTR_TYPE": - assert fv[1] == "SAI_MIRROR_SESSION_TYPE_LOCAL" - elif fv[0] == "SAI_MIRROR_SESSION_ATTR_POLICER": - assert fv[1] == policer_oid - - # remove mirror session - self.remove_mirror_session(session) - self.remove_policer(policer) - - def test_PortMirrorPolicerMultiAddRemove(self, dvs, testlog): + policer="POLICER" + + #Sub Test 1 + self.dvs_policer.create_policer(policer) + self.dvs_policer.verify_policer(policer) + self.dvs_mirror.create_span_session(session, dst_port, policer="POLICER") + self.dvs_mirror.verify_session_status(session) + a = {"SAI_MIRROR_SESSION_ATTR_MONITOR_PORT": pmap.get("Ethernet16"), + "SAI_MIRROR_SESSION_ATTR_TYPE": "SAI_MIRROR_SESSION_TYPE_LOCAL"} + self.dvs_mirror.verify_session(dvs, session, asic_db=a, policer="POLICER") + self.dvs_mirror.remove_mirror_session(session) + self.dvs_policer.remove_policer("POLICER") + self.dvs_policer.verify_no_policer() + self.dvs_mirror.verify_no_mirror() + + # Sub test 2 + src_ports = "Ethernet0,Ethernet4,Ethernet8" + src_asic_ports = ["Ethernet0","Ethernet4","Ethernet8"] + self.dvs_mirror.create_span_session(session, dst_port, src_ports, policer="POLICER") + self.dvs_mirror.verify_session_status(session, expected=0) + + # Sub test 3 + self.dvs_policer.create_policer(policer) + self.dvs_policer.verify_policer(policer) + self.dvs_mirror.create_span_session(session, dst_port, src_ports, policer="POLICER") + self.dvs_mirror.verify_session_status(session) + self.dvs_mirror.verify_session(dvs, session, asic_db=a, src_ports=src_asic_ports, policer="POLICER") + self.dvs_mirror.remove_mirror_session(session) + self.dvs_policer.remove_policer("POLICER") + self.dvs_policer.verify_no_policer() + self.dvs_mirror.verify_no_mirror() + + + def test_PortMultiMirrorPolicerAddRemove(self, dvs, testlog): """ - This test covers the SPAN mirror session with multiple source ports and multiple policers. + This test covers the basic SPAN mirror session creation and removal operations Operation flow: - 1. Create mirror session with multiple source ports and policers. - 2. Verify mirror and policer config is proper. + 1. Create mirror session with multiple source with multiple policer. + 2. Verify port/policer/session config on all. """ - self.setup_db(dvs) + pmap = dvs.counters_db.get_entry("COUNTERS_PORT_NAME_MAP", "") + pmap = dict(pmap) session1 = "TEST_SESSION1" session2 = "TEST_SESSION2" - src_port1 = "Ethernet0" - src_port2 = "Ethernet4" - src_port3 = "Ethernet8" - src_port4 = "Ethernet12" dst_port1 = "Ethernet16" + dst_oid1 = pmap.get(dst_port1) dst_port2 = "Ethernet20" - policer1= "POLICER1" - policer2= "POLICER2" - src_oid1 = self.getPortOid(dvs, src_port1) - src_oid2 = self.getPortOid(dvs, src_port2) - src_oid3 = self.getPortOid(dvs, src_port3) - src_oid4 = self.getPortOid(dvs, src_port4) + dst_oid2 = pmap.get(dst_port2) + policer1 = "POLICER1" + policer2 = "POLICER2" + + #Sub Test 1 + self.dvs_policer.create_policer(policer1, cir="600") + self.dvs_policer.verify_policer(policer1) + self.dvs_policer.create_policer(policer2, cir="800") + self.dvs_policer.verify_policer(policer2, expected = 2) + + src_ports1 = "Ethernet0,Ethernet4" + src_asic_ports1 = ["Ethernet0","Ethernet4"] + self.dvs_mirror.create_span_session(session1, dst_port1, src_ports1, policer=policer1) + src_ports2 = "Ethernet8,Ethernet12" + src_asic_ports2 = ["Ethernet8","Ethernet12"] + self.dvs_mirror.create_span_session(session2, dst_port2, src_ports2, policer=policer2) + + a1 = {"SAI_MIRROR_SESSION_ATTR_MONITOR_PORT": dst_oid1, + "SAI_MIRROR_SESSION_ATTR_TYPE": "SAI_MIRROR_SESSION_TYPE_LOCAL"} + a2 = {"SAI_MIRROR_SESSION_ATTR_MONITOR_PORT": dst_oid2, + "SAI_MIRROR_SESSION_ATTR_TYPE": "SAI_MIRROR_SESSION_TYPE_LOCAL"} + self.dvs_mirror.verify_session_status(session1, expected = 2) + self.dvs_mirror.verify_session_status(session2, expected = 2) + self.dvs_mirror.verify_session(dvs, session1, dst_oid=dst_oid1, asic_db=a1, src_ports=src_asic_ports1, expected = 2, policer=policer1) + self.dvs_mirror.verify_session(dvs, session2, dst_oid=dst_oid2, asic_db=a2, src_ports=src_asic_ports2, expected = 2, policer=policer2) + self.dvs_mirror.remove_mirror_session(session1) + self.dvs_mirror.remove_mirror_session(session2) + self.dvs_policer.remove_policer(policer1) + self.dvs_policer.remove_policer(policer2) + self.dvs_policer.verify_no_policer() + self.dvs_mirror.verify_no_mirror() - # create policer - self.create_policer(policer1) - # create policer - self.create_policer(policer2) - - # create mirror session - source=src_port1+","+src_port2 - self.create_mirror_span_session(session1, dst_port1, source, "BOTH", None, policer1) - assert self.get_mirror_session_state(session1)["status"] == "active" - # create mirror session - source=src_port3+","+src_port4 - self.create_mirror_span_session(session2, dst_port2, source, "BOTH", None, policer2) - assert self.get_mirror_session_state(session2)["status"] == "active" + def test_LAGMirorrSpanAddRemove(self, dvs, testlog): + """ + This test covers the LAG mirror session creation and removal operations + Operation flow: + 1. Create port channel with 2 members. + 2. Create mirror session with LAG as source port. + 3. Verify that source ports have proper mirror config. + 4. Remove port from port-channel and verify mirror config is removed from the port. + 5. Remove second port and verify mirror config is removed. + """ + dvs.setup_db() + pmap = dvs.counters_db.get_entry("COUNTERS_PORT_NAME_MAP", "") + pmap = dict(pmap) + session = "TEST_SESSION" + dst_port = "Ethernet16" + src_port1="Ethernet8" + src_port2="Ethernet4" + po_src_port="PortChannel008" + src_ports = "PortChannel008,Ethernet12" + src_asic_ports = ["Ethernet8", "Ethernet4", "Ethernet12"] - # check asic database - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_POLICER") - policer_entries = tbl.getKeys() - assert len(policer_entries) == 2 - policer_oid1 = policer_entries[1] - policer_oid2 = policer_entries[0] - - # check asic database - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_MIRROR_SESSION") - mirror_entries = tbl.getKeys() - assert len(mirror_entries) == 2 + # create port channel; create port channel member + self.dvs_lag.create_port_channel("008") + self.dvs_vlan.asic_db.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_LAG", 1) + self.dvs_lag.create_port_channel_member("008", src_port1) + self.dvs_lag.create_port_channel_member("008", src_port2) + + # bring up port channel and port channel member + dvs.set_interface_status(po_src_port, "up") + dvs.set_interface_status(src_port1, "up") + dvs.set_interface_status(src_port2, "up") + + # Sub Test 1 + self.dvs_mirror.create_span_session(session, dst_port, src_ports) + self.dvs_mirror.verify_session_status(session) # verify asicdb - (status1, fvs1) = tbl.get(mirror_entries[0]) - (status2, fvs2) = tbl.get(mirror_entries[1]) - assert status1 == True and status2 == True - assert len(fvs1) == 3 and len(fvs2) == 3 - for fv in fvs1: - if fv[0] == "SAI_MIRROR_SESSION_ATTR_MONITOR_PORT": - if dvs.asicdb.portoidmap[fv[1]] == dst_port1: - session_oid1 = mirror_entries[0] - if dvs.asicdb.portoidmap[fv[1]] == dst_port2: - session_oid2 = mirror_entries[0] - - for fv in fvs2: - if fv[0] == "SAI_MIRROR_SESSION_ATTR_MONITOR_PORT": - if dvs.asicdb.portoidmap[fv[1]] == dst_port1: - session_oid1 = mirror_entries[1] - if dvs.asicdb.portoidmap[fv[1]] == dst_port2: - session_oid2 = mirror_entries[1] - assert session_oid1 is not None or session_oid2 is not None - - (status1, fvs1) = tbl.get(session_oid1) - for fv in fvs1: - if fv[0] == "SAI_MIRROR_SESSION_ATTR_MONITOR_PORT": - assert dvs.asicdb.portoidmap[fv[1]] == dst_port1 - elif fv[0] == "SAI_MIRROR_SESSION_ATTR_TYPE": - assert fv[1] == "SAI_MIRROR_SESSION_TYPE_LOCAL" - elif fv[0] == "SAI_MIRROR_SESSION_ATTR_POLICER": - assert fv[1] == policer_oid1 or fv[1] == policer_oid2 - - (status1, fvs2) = tbl.get(session_oid2) - for fv in fvs2: - if fv[0] == "SAI_MIRROR_SESSION_ATTR_MONITOR_PORT": - assert dvs.asicdb.portoidmap[fv[1]] == dst_port2 - elif fv[0] == "SAI_MIRROR_SESSION_ATTR_TYPE": - assert fv[1] == "SAI_MIRROR_SESSION_TYPE_LOCAL" - elif fv[0] == "SAI_MIRROR_SESSION_ATTR_POLICER": - assert fv[1] == policer_oid2 or fv[1] == policer_oid1 - - # check asic database - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_MIRROR_SESSION") - mirror_entries = tbl.getKeys() - assert len(mirror_entries) == 2 - - session_status1= "1:"+format(session_oid1) - session_status2="1:"+format(session_oid2) - # Verify port has mirror session enabled with session oid. - status = self.getPortAttr(dvs, src_oid1, 'SAI_PORT_ATTR_INGRESS_MIRROR_SESSION') - assert status == session_status1 - # Verify port has egress mirror session enabled with session oid. - status = self.getPortAttr(dvs, src_oid1, 'SAI_PORT_ATTR_EGRESS_MIRROR_SESSION') - assert status == session_status1 - - # Verify port has mirror session enabled with session oid. - status = self.getPortAttr(dvs, src_oid2, 'SAI_PORT_ATTR_INGRESS_MIRROR_SESSION') - assert status == session_status1 - # Verify port has egress mirror session enabled with session oid. - status = self.getPortAttr(dvs, src_oid2, 'SAI_PORT_ATTR_EGRESS_MIRROR_SESSION') - assert status == session_status1 - - # Verify port has mirror session enabled with session oid. - status = self.getPortAttr(dvs, src_oid3, 'SAI_PORT_ATTR_INGRESS_MIRROR_SESSION') - assert status == session_status2 - # Verify port has egress mirror session enabled with session oid. - status = self.getPortAttr(dvs, src_oid3, 'SAI_PORT_ATTR_EGRESS_MIRROR_SESSION') - assert status == session_status2 - - # Verify port has mirror session enabled with session oid. - status = self.getPortAttr(dvs, src_oid4, 'SAI_PORT_ATTR_INGRESS_MIRROR_SESSION') - assert status == session_status2 - # Verify port has egress mirror session enabled with session oid. - status = self.getPortAttr(dvs, src_oid4, 'SAI_PORT_ATTR_EGRESS_MIRROR_SESSION') - assert status == session_status2 - - # remove mirror session - self.remove_mirror_session(session1) - self.remove_mirror_session(session2) - - def create_acl_table(self, table, interfaces): - tbl = swsscommon.Table(self.cdb, "ACL_TABLE") - fvs = swsscommon.FieldValuePairs([("policy_desc", "mirror_test"), - ("type", "mirror"), - ("ports", ",".join(interfaces))]) - tbl.set(table, fvs) - time.sleep(1) - - def remove_acl_table(self, table): - tbl = swsscommon.Table(self.cdb, "ACL_TABLE") - tbl._del(table) - time.sleep(1) - - def create_mirror_acl_dscp_rule(self, table, rule, dscp, session): - tbl = swsscommon.Table(self.cdb, "ACL_RULE") - fvs = swsscommon.FieldValuePairs([("priority", "1000"), - ("mirror_action", session), - ("DSCP", dscp)]) - tbl.set(table + "|" + rule, fvs) - time.sleep(1) - - def remove_mirror_acl_dscp_rule(self, table, rule): - tbl = swsscommon.Table(self.cdb, "ACL_RULE") - tbl._del(table + "|" + rule) - time.sleep(1) + # Check src_port state. + expected_asic_db = {"SAI_MIRROR_SESSION_ATTR_MONITOR_PORT": pmap.get(dst_port), + "SAI_MIRROR_SESSION_ATTR_TYPE": "SAI_MIRROR_SESSION_TYPE_LOCAL"} + self.dvs_mirror.verify_session(dvs, session, asic_db=expected_asic_db, src_ports=src_asic_ports, asic_size=2) + + # Sub Test 2 + # remove port channel member; remove port channel + self.dvs_lag.remove_port_channel_member("008", src_port1) + src_asic_ports = ["Ethernet4", "Ethernet12"] + self.dvs_mirror.verify_session(dvs, session, asic_db=expected_asic_db, src_ports=src_asic_ports, asic_size=2) + self.dvs_lag.remove_port_channel_member("008", src_port2) + + self.dvs_lag.remove_port_channel("008") + self.dvs_mirror.remove_mirror_session(session) + self.dvs_mirror.verify_no_mirror() def test_PortMirrorPolicerWithAcl(self, dvs, testlog): """ @@ -589,7 +289,9 @@ def test_PortMirrorPolicerWithAcl(self, dvs, testlog): 2. Create ACL and configure mirror 2. Verify mirror and ACL config is proper. """ - self.setup_db(dvs) + dvs.setup_db() + pmap = dvs.counters_db.get_entry("COUNTERS_PORT_NAME_MAP", "") + pmap = dict(pmap) session = "MIRROR_SESSION" policer= "POLICER" @@ -598,165 +300,178 @@ def test_PortMirrorPolicerWithAcl(self, dvs, testlog): dst_port = "Ethernet16" # create policer - self.create_policer(policer) + self.dvs_policer.create_policer(policer) + self.dvs_policer.verify_policer(policer) # create mirror session - self.create_mirror_span_session(session, dst_port, None, None, None, policer=policer) - - # check asic database - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_MIRROR_SESSION") - mirror_entries = tbl.getKeys() - assert len(mirror_entries) == 1 - mirror_oid = mirror_entries[0] + self.dvs_mirror.create_span_session(session, dst_port, policer=policer) + self.dvs_mirror.verify_session_status(session) + member_ids = dvs.asic_db.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_MIRROR_SESSION", 1) + # create acl table - self.create_acl_table(acl_table, ["Ethernet0", "Ethernet4"]) - - # create acl rule with dscp value and mask - self.create_mirror_acl_dscp_rule(acl_table, acl_rule, "8/56", session) - - # assert acl rule is created - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_ACL_ENTRY") - rule_entries = [k for k in tbl.getKeys() if k not in dvs.asicdb.default_acl_entries] - assert len(rule_entries) == 1 - - (status, fvs) = tbl.get(rule_entries[0]) - assert status == True - for fv in fvs: - if fv[0] == "SAI_ACL_ENTRY_ATTR_FIELD_DSCP": - assert fv[1] == "8&mask:0x38" - if fv[0] == "SAI_ACL_ENTRY_ATTR_ACTION_MIRROR_INGRESS": - assert fv[1] == "1:" + mirror_oid - - # remove acl rule - self.remove_mirror_acl_dscp_rule(acl_table, acl_rule) - # remove acl table - self.remove_acl_table(acl_table) - self.remove_mirror_session(session) - - # remove policer - self.remove_policer(policer) + bind_ports = ["Ethernet0", "Ethernet4"] + self.dvs_acl.create_acl_table("test", "mirror", bind_ports) + self.dvs_acl.verify_acl_group_num(len(bind_ports)) + + config_qualifiers = {"mirror_action": session, + "DSCP": "8/56"} + mirror_oid="1:" + member_ids[0] + expected_sai_qualifiers = {"SAI_ACL_ENTRY_ATTR_FIELD_DSCP": "8&mask:0x38", + "SAI_ACL_ENTRY_ATTR_ACTION_MIRROR_INGRESS": mirror_oid} + self.dvs_acl.create_mirror_acl_rule("test", "mirror_rule", config_qualifiers) + self.dvs_acl.remove_acl_rule("test", "mirror_rule") + self.dvs_acl.verify_no_acl_rules() + + self.dvs_acl.remove_acl_table("test") + self.dvs_acl.verify_acl_table_count(0) + self.dvs_mirror.remove_mirror_session(session) - def create_port_channel(self, dvs, channel): - tbl = swsscommon.ProducerStateTable(self.pdb, "LAG_TABLE") - fvs = swsscommon.FieldValuePairs([("admin", "up"), ("mtu", "9100")]) - tbl.set("PortChannel" + channel, fvs) - dvs.runcmd("ip link add PortChannel" + channel + " type bond") - tbl = swsscommon.Table(self.sdb, "LAG_TABLE") - fvs = swsscommon.FieldValuePairs([("state", "ok")]) - tbl.set("PortChannel" + channel, fvs) - time.sleep(1) - - def remove_port_channel(self, dvs, channel): - tbl = swsscommon.ProducerStateTable(self.pdb, "LAG_TABLE") - tbl._del("PortChannel" + channel) - dvs.runcmd("ip link del PortChannel" + channel) - tbl = swsscommon.Table(self.sdb, "LAG_TABLE") - tbl._del("PortChannel" + channel) - time.sleep(1) - - 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 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_LAGMirorrSpanAddRemove(self, dvs, testlog): + self.dvs_policer.remove_policer(policer) + self.dvs_policer.verify_no_policer() + self.dvs_mirror.verify_no_mirror() + + def test_PortMirrorLAGPortSpanAddRemove(self, dvs, testlog): """ This test covers the LAG mirror session creation and removal operations Operation flow: 1. Create port channel with 2 members. - 2. Create mirror session with LAG as source port. - 3. Verify that source ports have proper mirror config. - 4. Remove port from port-channel and verify mirror config is removed from the port. - 5. Remove second port and verify mirror config is removed. + 2. Create mirror session with LAG and LAG port. session creation has to fail. + 3. Create mirror session with LAG and other LAG port. session creation has to fail + 4. Create mirror session with LAG and new port, session will become active. + 5. Verify all LAG and new port has session config. + 6. Remove one LAG member and verify that failing session works fine. """ - self.setup_db(dvs) + dvs.setup_db() + pmap = dvs.counters_db.get_entry("COUNTERS_PORT_NAME_MAP", "") + pmap = dict(pmap) session = "TEST_SESSION" dst_port = "Ethernet16" - po_src_port = "PortChannel008" - src_port1 = "Ethernet0" - src_port2 = "Ethernet4" - src_oid1 = self.getPortOid(dvs, src_port1) - src_oid2 = self.getPortOid(dvs, src_port2) + + session = "TEST_SESSION" + src_port1="Ethernet8" + src_port2="Ethernet4" + po_src_port="PortChannel008" # create port channel; create port channel member - self.create_port_channel(dvs, "008") - self.create_port_channel_member("008", src_port1) - self.create_port_channel_member("008", src_port2) + self.dvs_lag.create_port_channel("008") + self.dvs_vlan.asic_db.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_LAG", 1) + self.dvs_lag.create_port_channel_member("008", src_port1) + self.dvs_lag.create_port_channel_member("008", src_port2) + lag_member_entries = self.dvs_vlan.asic_db.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_LAG_MEMBER", 2) # bring up port channel and port channel member - self.set_interface_status(dvs, po_src_port, "up") - self.set_interface_status(dvs, src_port1, "up") - self.set_interface_status(dvs, src_port2, "up") + dvs.set_interface_status(po_src_port, "up") + dvs.set_interface_status(src_port1, "up") + dvs.set_interface_status(src_port2, "up") # Sub Test 1 - self.create_mirror_span_session(session, dst_port, po_src_port, "BOTH") - assert self.get_mirror_session_state(session)["status"] == "active" + src_ports = "PortChannel008,Ethernet8" + self.dvs_mirror.create_span_session(session, dst_port, src_ports) + self.dvs_mirror.verify_session_status(session, expected=0) + self.dvs_mirror.verify_session_status(session, status="inactive", expected = 0) - # check asic database - tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_MIRROR_SESSION") - mirror_entries = tbl.getKeys() - assert len(mirror_entries) == 1 + # Sub Test 2 + src_ports = "PortChannel008,Ethernet4" + self.dvs_mirror.create_span_session(session, dst_port, src_ports) + self.dvs_mirror.verify_session_status(session, expected=0) + self.dvs_mirror.verify_session_status(session, status="inactive", expected=0) - # verify asicdb - (status, fvs) = tbl.get(mirror_entries[0]) - assert status == True - assert len(fvs) == 2 - for fv in fvs: - if fv[0] == "SAI_MIRROR_SESSION_ATTR_MONITOR_PORT": - assert dvs.asicdb.portoidmap[fv[1]] == dst_port - elif fv[0] == "SAI_MIRROR_SESSION_ATTR_TYPE": - assert fv[1] == "SAI_MIRROR_SESSION_TYPE_LOCAL" - - session_status= "1:"+format(mirror_entries[0]) - # Verify port has mirror session enabled with session oid. - status = self.getPortAttr(dvs, src_oid1, 'SAI_PORT_ATTR_INGRESS_MIRROR_SESSION') - assert status == session_status - # Verify port has egress mirror session enabled with session oid. - session_status = self.getPortAttr(dvs, src_oid1, 'SAI_PORT_ATTR_EGRESS_MIRROR_SESSION') - assert status == session_status - - # Verify port has mirror session enabled with session oid. - status = self.getPortAttr(dvs, src_oid2, 'SAI_PORT_ATTR_INGRESS_MIRROR_SESSION') - assert status == session_status - # Verify port has egress mirror session enabled with session oid. - session_status = self.getPortAttr(dvs, src_oid2, 'SAI_PORT_ATTR_EGRESS_MIRROR_SESSION') - assert status == session_status + # Sub Test 3 + src_ports = "PortChannel008,Ethernet40" + src_asic_ports = ["Ethernet8", "Ethernet40", "Ethernet4"] + self.dvs_mirror.create_span_session(session, dst_port, src_ports) + self.dvs_mirror.verify_session_status(session, status="active") - # Sub Test 2 - # remove port channel member; remove port channel - self.remove_port_channel_member("008", src_port1) + expected_asic_db = {"SAI_MIRROR_SESSION_ATTR_MONITOR_PORT": pmap.get(dst_port), + "SAI_MIRROR_SESSION_ATTR_TYPE": "SAI_MIRROR_SESSION_TYPE_LOCAL"} + self.dvs_mirror.verify_session(dvs, session, asic_db=expected_asic_db, src_ports=src_asic_ports, asic_size=2) + self.dvs_mirror.remove_mirror_session(session) + self.dvs_mirror.verify_no_mirror() + + # Sub Test 4 + self.dvs_lag.remove_port_channel_member("008", "Ethernet4") + lag_member_entries = self.dvs_vlan.asic_db.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_LAG_MEMBER", 1) + src_ports = "PortChannel008,Ethernet40" + src_asic_ports = ["Ethernet8", "Ethernet40"] + self.dvs_mirror.create_span_session(session, dst_port, src_ports) + self.dvs_mirror.verify_session_status(session) + self.dvs_mirror.verify_session(dvs, session, src_ports=src_asic_ports) + + self.dvs_mirror.remove_mirror_session(session) + self.dvs_mirror.verify_no_mirror() + self.dvs_lag.remove_port_channel_member("008", "Ethernet8") + lag_member_entries = self.dvs_vlan.asic_db.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_LAG_MEMBER", 0) + self.dvs_lag.remove_port_channel("008") + self.dvs_vlan.asic_db.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_LAG", 0) + + + def test_PortLAGMirrorUpdateLAG(self, dvs, testlog): + """ + This test covers the LAG mirror session creation and removal operations + Operation flow: + 1. Create port channel with 2 members. + 2. Create mirror session with LAG and other port P1 + 3. Verify mirror session is active and ports have proper config + 4. Add port P1 to LAG and verify mirror config on all ports. + 5. Remove port P1 from LAG and verify mirror config on P1 is intact. + 6. Remove port from LAG and verify mirror config on other ports in intact. + """ + dvs.setup_db() + pmap = dvs.counters_db.get_entry("COUNTERS_PORT_NAME_MAP", "") + pmap = dict(pmap) - session_status= "1:"+format(mirror_entries[0]) + session = "TEST_SESSION" + dst_port = "Ethernet16" + src_port1="Ethernet8" + src_port2="Ethernet4" + po_src_port="PortChannel008" - # Verify first port doesnt have any mirror config - status = self.getPortAttr(dvs, src_oid1, 'SAI_PORT_ATTR_INGRESS_MIRROR_SESSION') - assert status == None or status == "0:null" - status = self.getPortAttr(dvs, src_oid1, 'SAI_PORT_ATTR_EGRESS_MIRROR_SESSION') - assert status == None or status == "0:null" + # create port channel; create port channel member + self.dvs_lag.create_port_channel("008") + self.dvs_vlan.asic_db.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_LAG", 1) + self.dvs_lag.create_port_channel_member("008", src_port1) + self.dvs_lag.create_port_channel_member("008", src_port2) + self.dvs_vlan.asic_db.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_LAG_MEMBER", 2) - # Verify second port has mirror config - status = self.getPortAttr(dvs, src_oid2, 'SAI_PORT_ATTR_INGRESS_MIRROR_SESSION') - assert status == session_status - # Verify port has egress mirror session enabled with session oid. - status = self.getPortAttr(dvs, src_oid2, 'SAI_PORT_ATTR_EGRESS_MIRROR_SESSION') - assert status == session_status + # bring up port channel and port channel member + dvs.set_interface_status(po_src_port, "up") + dvs.set_interface_status(src_port1, "up") + dvs.set_interface_status(src_port2, "up") + + # Sub Test 1 + src_ports = "PortChannel008,Ethernet40" + src_asic_ports = ["Ethernet8", "Ethernet40", "Ethernet4"] + self.dvs_mirror.create_span_session(session, dst_port, src_ports) + self.dvs_mirror.verify_session_status(session, status="active") + + expected_asic_db = {"SAI_MIRROR_SESSION_ATTR_MONITOR_PORT": pmap.get(dst_port), + "SAI_MIRROR_SESSION_ATTR_TYPE": "SAI_MIRROR_SESSION_TYPE_LOCAL"} + self.dvs_mirror.verify_session(dvs, session, asic_db=expected_asic_db, src_ports=src_asic_ports, asic_size=2) - self.remove_port_channel_member("008", src_port2) - # Verify second port doesnt have any mirror config - status = self.getPortAttr(dvs, src_oid2, 'SAI_PORT_ATTR_INGRESS_MIRROR_SESSION') - assert status == None or status == "0:null" - status = self.getPortAttr(dvs, src_oid2, 'SAI_PORT_ATTR_EGRESS_MIRROR_SESSION') - assert status == None or status == "0:null" + # Add source port Ethernet40 to LAG + self.dvs_lag.create_port_channel_member("008", "Ethernet40") + self.dvs_vlan.asic_db.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_LAG_MEMBER", 3) + self.dvs_mirror.verify_session(dvs, session, src_ports=src_asic_ports) - self.remove_port_channel(dvs, "008") - self.remove_mirror_session(session) + # Remove source port Ethernet40 from LAG + self.dvs_lag.remove_port_channel_member("008", "Ethernet40") + self.dvs_vlan.asic_db.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_LAG_MEMBER", 2) + self.dvs_mirror.verify_session(dvs, session, src_ports=src_asic_ports) + + # Remove one port from LAG + self.dvs_lag.remove_port_channel_member("008", "Ethernet4") + self.dvs_vlan.asic_db.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_LAG_MEMBER", 1) + src_asic_ports = ["Ethernet8"] + self.dvs_mirror.verify_session(dvs, session, src_ports=src_asic_ports) + + #cleanup + self.dvs_mirror.remove_mirror_session(session) + self.dvs_mirror.verify_no_mirror() + self.dvs_lag.remove_port_channel_member("008", "Ethernet8") + self.dvs_vlan.asic_db.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_LAG_MEMBER", 0) + self.dvs_lag.remove_port_channel("008") + self.dvs_vlan.asic_db.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_LAG", 0)