From 37a90a364536a041a72442f0a458fbaf995c326e Mon Sep 17 00:00:00 2001 From: Madhu Challa Date: Wed, 31 Jul 2024 22:14:33 -0700 Subject: [PATCH] Add LocalSecGrpClassifierCounter - added as an extension of SecGrpClassifierCounter - added make checks as a copy of SecGrpStatsManager_test.cpp, replacing all the classifiers with Local, and convert the called functions to use template arguments. - The make checks cover the prometheus tests - this would also result in pushing the LocalSecGrpClassifierCounter to the leaf, should we decide to push the local secgrps to the leaf, we can strip the Local before sending it. Signed-off-by: Madhu Challa --- agent-ovs/Makefile.am | 1 + .../include/opflexagent/test/ModbFixture.h | 7 + agent-ovs/ovs/SecGrpStatsManager.cpp | 81 ++-- agent-ovs/ovs/include/SecGrpStatsManager.h | 1 + .../ovs/test/ContractStatsManager_test.cpp | 14 +- .../test/SecGrpStatsManager_LocalSG_test.cpp | 356 ++++++++++++++++++ .../ovs/test/SecGrpStatsManager_test.cpp | 24 +- .../test/include/PolicyStatsManagerFixture.h | 75 +++- genie/MODEL/EXTENSIONS/GBP/extensions.mdl | 10 + 9 files changed, 520 insertions(+), 49 deletions(-) create mode 100644 agent-ovs/ovs/test/SecGrpStatsManager_LocalSG_test.cpp diff --git a/agent-ovs/Makefile.am b/agent-ovs/Makefile.am index d06216d9..e6fd06a6 100644 --- a/agent-ovs/Makefile.am +++ b/agent-ovs/Makefile.am @@ -521,6 +521,7 @@ if RENDERER_OVS ovs/test/IntFlowManager_test.cpp \ ovs/test/AccessFlowManager_test.cpp \ ovs/test/AccessFlowManager_LocalSG_test.cpp \ + ovs/test/SecGrpStatsManager_LocalSG_test.cpp \ ovs/test/PacketInHandler_test.cpp \ ovs/test/AdvertManager_test.cpp \ ovs/test/PortMapper_test.cpp \ diff --git a/agent-ovs/lib/include/opflexagent/test/ModbFixture.h b/agent-ovs/lib/include/opflexagent/test/ModbFixture.h index 5e368052..76bf5655 100644 --- a/agent-ovs/lib/include/opflexagent/test/ModbFixture.h +++ b/agent-ovs/lib/include/opflexagent/test/ModbFixture.h @@ -93,6 +93,7 @@ class ModbFixture : public BaseFixture { std::shared_ptr local_classifier0; std::shared_ptr local_classifier1; std::shared_ptr local_classifier2; + std::shared_ptr local_classifier3; std::shared_ptr local_classifier5; std::shared_ptr local_classifier6; std::shared_ptr local_classifier7; @@ -315,6 +316,12 @@ class ModbFixture : public BaseFixture { local_classifier2 = space->addGbpeLocalL24Classifier("classifier2"); local_classifier2->setEtherT(l2::EtherTypeEnumT::CONST_ARP); + /* classifiers with port ranges */ + local_classifier3 = space->addGbpeLocalL24Classifier("classifier3"); + local_classifier3->setOrder(10) + .setEtherT(l2::EtherTypeEnumT::CONST_IPV4).setProt(6 /* TCP */) + .setDFromPort(80).setDToPort(85); + /* allow bidirectional FCoE */ local_classifier5 = space->addGbpeLocalL24Classifier("classifier5"); local_classifier5->setOrder(20).setEtherT(l2::EtherTypeEnumT::CONST_FCOE); diff --git a/agent-ovs/ovs/SecGrpStatsManager.cpp b/agent-ovs/ovs/SecGrpStatsManager.cpp index ae37753b..e25ebdb3 100644 --- a/agent-ovs/ovs/SecGrpStatsManager.cpp +++ b/agent-ovs/ovs/SecGrpStatsManager.cpp @@ -26,6 +26,7 @@ extern "C" { #include #include #include +#include #include namespace opflexagent { @@ -46,7 +47,8 @@ using boost::system::error_code; SecGrpStatsManager::SecGrpStatsManager(Agent* agent_, IdGenerator& idGen_, SwitchManager& switchManager_, long timer_interval_) - : PolicyStatsManager(agent_,idGen_,switchManager_,timer_interval_) { + : PolicyStatsManager(agent_,idGen_,switchManager_,timer_interval_), + agent(agent_) { } @@ -122,9 +124,15 @@ void SecGrpStatsManager::on_timer(const error_code& ec) { void SecGrpStatsManager::clearCounterObject(const string& key, uint8_t index) { - SecGrpClassifierCounter::remove(agent->getFramework(), - getAgentUUID(), - genIdList_[key]->uidList[index],key); + if (agent->getPolicyManager().useLocalNetpol()) { + LocalSecGrpClassifierCounter::remove(agent->getFramework(), + getAgentUUID(), + genIdList_[key]->uidList[index],key); + } else { + SecGrpClassifierCounter::remove(agent->getFramework(), + getAgentUUID(), + genIdList_[key]->uidList[index],key); + } } void SecGrpStatsManager:: @@ -138,34 +146,60 @@ updatePolicyStatsCounters(const string& l24Classifier, uint64_t nextId = getNextClsfrGenId(); clearOldCounters(l24Classifier,nextId); if (newVals1.byte_count && newVals2.byte_count) { - su.get()->addGbpeSecGrpClassifierCounter(getAgentUUID(), - nextId, - l24Classifier) - ->setTxpackets(newVals2.packet_count.get()) - .setTxbytes(newVals2.byte_count.get()) - .setRxpackets(newVals1.packet_count.get()) - .setRxbytes(newVals1.byte_count.get()); + if (agent->getPolicyManager().useLocalNetpol()) { + su.get()->addGbpeLocalSecGrpClassifierCounter(getAgentUUID(), + nextId, + l24Classifier) + ->setTxpackets(newVals2.packet_count.get()) + .setTxbytes(newVals2.byte_count.get()) + .setRxpackets(newVals1.packet_count.get()) + .setRxbytes(newVals1.byte_count.get()); + } else { + su.get()->addGbpeSecGrpClassifierCounter(getAgentUUID(), + nextId, + l24Classifier) + ->setTxpackets(newVals2.packet_count.get()) + .setTxbytes(newVals2.byte_count.get()) + .setRxpackets(newVals1.packet_count.get()) + .setRxbytes(newVals1.byte_count.get()); + } prometheusManager.addNUpdateSGClassifierCounter(l24Classifier, newVals1.byte_count.get(), newVals1.packet_count.get(), newVals2.byte_count.get(), newVals2.packet_count.get()); } else if (newVals1.byte_count) { - su.get()->addGbpeSecGrpClassifierCounter(getAgentUUID(), - nextId, - l24Classifier) - ->setRxpackets(newVals1.packet_count.get()) - .setRxbytes(newVals1.byte_count.get()); + if (agent->getPolicyManager().useLocalNetpol()) { + su.get()->addGbpeLocalSecGrpClassifierCounter(getAgentUUID(), + nextId, + l24Classifier) + ->setRxpackets(newVals1.packet_count.get()) + .setRxbytes(newVals1.byte_count.get()); + } else { + su.get()->addGbpeSecGrpClassifierCounter(getAgentUUID(), + nextId, + l24Classifier) + ->setRxpackets(newVals1.packet_count.get()) + .setRxbytes(newVals1.byte_count.get()); + } prometheusManager.addNUpdateSGClassifierCounter(l24Classifier, newVals1.byte_count.get(), newVals1.packet_count.get(), 0, 0); } else if (newVals2.byte_count) { - su.get()->addGbpeSecGrpClassifierCounter(getAgentUUID(), - nextId, - l24Classifier) - ->setTxpackets(newVals2.packet_count.get()) - .setTxbytes(newVals2.byte_count.get()); + if (agent->getPolicyManager().useLocalNetpol()) { + su.get()->addGbpeLocalSecGrpClassifierCounter(getAgentUUID(), + nextId, + l24Classifier) + ->setTxpackets(newVals2.packet_count.get()) + .setTxbytes(newVals2.byte_count.get()); + } else { + su.get()->addGbpeSecGrpClassifierCounter(getAgentUUID(), + nextId, + l24Classifier) + ->setTxpackets(newVals2.packet_count.get()) + .setTxbytes(newVals2.byte_count.get()); + } prometheusManager.addNUpdateSGClassifierCounter(l24Classifier, 0, 0, newVals2.byte_count.get(), @@ -182,6 +216,11 @@ void SecGrpStatsManager::objectUpdated(opflex::modb::class_id_t class_id, removeAllCounterObjects(uri.toString()); prometheusManager.removeSGClassifierCounter(uri.toString()); } + } else if (class_id == LocalL24Classifier::CLASS_ID) { + if (!LocalL24Classifier::resolve(agent->getFramework(),uri)) { + removeAllCounterObjects(uri.toString()); + prometheusManager.removeSGClassifierCounter(uri.toString()); + } } } diff --git a/agent-ovs/ovs/include/SecGrpStatsManager.h b/agent-ovs/ovs/include/SecGrpStatsManager.h index 4f43a2df..fe64744d 100644 --- a/agent-ovs/ovs/include/SecGrpStatsManager.h +++ b/agent-ovs/ovs/include/SecGrpStatsManager.h @@ -85,6 +85,7 @@ class SecGrpStatsManager : public PolicyStatsManager { private: flowCounterState_t secGrpInState; flowCounterState_t secGrpOutState; + Agent *agent; }; } /* namespace opflexagent */ diff --git a/agent-ovs/ovs/test/ContractStatsManager_test.cpp b/agent-ovs/ovs/test/ContractStatsManager_test.cpp index ab1305e2..d0c6cd30 100644 --- a/agent-ovs/ovs/test/ContractStatsManager_test.cpp +++ b/agent-ovs/ovs/test/ContractStatsManager_test.cpp @@ -258,7 +258,7 @@ BOOST_FIXTURE_TEST_CASE(testFlowMatchStats, ContractStatsManagerFixture) { contractStatsManager.Handle(&integrationPortConn, OFPTYPE_FLOW_STATS_REPLY, NULL); - testOneFlow(integrationPortConn,classifier3, + testOneFlow(integrationPortConn,classifier3, IntFlowManager::POL_TABLE_ID, 1, false, @@ -314,7 +314,7 @@ BOOST_FIXTURE_TEST_CASE(testFlowRemoved, ContractStatsManagerFixture) { // Add flows in switchManager FlowEntryList entryList; - writeClassifierFlows(entryList, + writeClassifierFlows(entryList, IntFlowManager::POL_TABLE_ID, 1, classifier3, @@ -353,7 +353,7 @@ BOOST_FIXTURE_TEST_CASE(testFlowRemoved, ContractStatsManagerFixture) { // calculate expected packet count and byte count // that we should have in Genie object - verifyFlowStats(classifier3, + verifyFlowStats(classifier3, LAST_PACKET_COUNT, LAST_PACKET_COUNT * PACKET_SIZE, false, @@ -371,7 +371,7 @@ BOOST_FIXTURE_TEST_CASE(testCircularBuffer, ContractStatsManagerFixture) { contractStatsManager.start(); LOG(DEBUG) << "### Contract circbuffer Start"; // Add flows in switchManager - testCircBuffer(intPortConn,classifier3, + testCircBuffer(intPortConn,classifier3, IntFlowManager::POL_TABLE_ID,2,&contractStatsManager, epg1,epg2,&policyManager); LOG(DEBUG) << "### Contract circbuffer End"; @@ -388,7 +388,7 @@ BOOST_FIXTURE_TEST_CASE(testContractDelete, ContractStatsManagerFixture) { contractStatsManager.Handle(&integrationPortConn, OFPTYPE_FLOW_STATS_REPLY, NULL); - testOneFlow(integrationPortConn, + testOneFlow(integrationPortConn, classifier3, IntFlowManager::POL_TABLE_ID, 1, @@ -423,7 +423,7 @@ BOOST_FIXTURE_TEST_CASE(testSEpgDelete, ContractStatsManagerFixture) { contractStatsManager.start(); LOG(DEBUG) << "### Contract SEPG Delete Start"; - testOneFlow(integrationPortConn, + testOneFlow(integrationPortConn, classifier3, IntFlowManager::POL_TABLE_ID, 1, @@ -457,7 +457,7 @@ BOOST_FIXTURE_TEST_CASE(testrDSEpgDelete, ContractStatsManagerFixture) { contractStatsManager.start(); LOG(DEBUG) << "### Contract DSEPG Delete Start"; - testOneFlow(integrationPortConn, + testOneFlow(integrationPortConn, classifier3, IntFlowManager::POL_TABLE_ID, 1, diff --git a/agent-ovs/ovs/test/SecGrpStatsManager_LocalSG_test.cpp b/agent-ovs/ovs/test/SecGrpStatsManager_LocalSG_test.cpp new file mode 100644 index 00000000..e9df82ce --- /dev/null +++ b/agent-ovs/ovs/test/SecGrpStatsManager_LocalSG_test.cpp @@ -0,0 +1,356 @@ +/* + * Test suite for class SecGrpStatsManager. + * + * Copyright (c) 2017 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +#include +#include + +#include +#include "ovs-ofputil.h" +#include "AccessFlowManager.h" +#include "IntFlowManager.h" +#include "SecGrpStatsManager.h" +#include "TableState.h" +#include "ActionBuilder.h" +#include "RangeMask.h" +#include "FlowConstants.h" +#include "PolicyStatsManagerFixture.h" + +#include +#include + +#include + +extern "C" { +#include +#include +} + +using boost::optional; +using std::shared_ptr; +using std::string; +using opflex::modb::URI; +using namespace modelgbp::gbp; +using namespace modelgbp::gbpe; +using modelgbp::observer::PolicyStatUniverse; +using opflex::modb::class_id_t; +using opflex::modb::Mutator; + +typedef opflexagent::EndpointListener::uri_set_t uri_set_t; + +namespace opflexagent { + +static const uint32_t LAST_PACKET_COUNT = 379; // for removed flow entry + +class MockSecGrpStatsManager : public SecGrpStatsManager { +public: + MockSecGrpStatsManager(Agent *agent_, + IdGenerator& idGen_, + SwitchManager& switchManager_, + long timer_interval_) + : SecGrpStatsManager(agent_, idGen_, switchManager_, timer_interval_) {}; + + void testInjectTxnId (uint32_t txn_id) { + std::lock_guard lock(txnMtx); + txns.insert(txn_id); + } +}; + +class SecGrpStatsManagerLocalSGFixture : public PolicyStatsManagerFixture { + +public: + SecGrpStatsManagerLocalSGFixture() : PolicyStatsManagerFixture(), + secGrpStatsManager(&agent, idGen, + switchManager, 100000) { + bool enable = true; + agent.getPolicyManager().configLocalNetpol(enable); + idGen.initNamespace("l24classifierRule"); + idGen.initNamespace("secGroupSet"); + idGen.initNamespace("secGroup"); + createObjects(); + createPolicyObjects(); + switchManager.setMaxFlowTables(IntFlowManager::NUM_FLOW_TABLES); + } + virtual ~SecGrpStatsManagerLocalSGFixture() { + bool enable = false; + agent.getPolicyManager().configLocalNetpol(enable); + stop(); + } + virtual void verifyPromMetrics(shared_ptr classifier, + uint32_t pkts, + uint32_t bytes, + bool isTx=false); + MockSecGrpStatsManager secGrpStatsManager; +}; + +void SecGrpStatsManagerLocalSGFixture:: +verifyPromMetrics (shared_ptr classifier, + uint32_t pkts, + uint32_t bytes, + bool isTx) +{ + std::string s_rx_bytes, s_rx_pkts, s_tx_bytes, s_tx_pkts; + if (classifier == local_classifier1) { + s_tx_bytes = "opflex_sg_tx_bytes{classifier=\"tenant:tenant0,policy:"\ + "classifier1,[etype:2048,proto:6,dport:80]\"} "\ + + std::to_string(bytes); + s_rx_bytes = "opflex_sg_rx_bytes{classifier=\"tenant:tenant0,policy:"\ + "classifier1,[etype:2048,proto:6,dport:80]\"} "\ + + std::to_string(bytes); + s_tx_pkts = "opflex_sg_tx_packets{classifier=\"tenant:tenant0,policy:"\ + "classifier1,[etype:2048,proto:6,dport:80]\"} "\ + + std::to_string(pkts); + s_rx_pkts = "opflex_sg_rx_packets{classifier=\"tenant:tenant0,policy:"\ + "classifier1,[etype:2048,proto:6,dport:80]\"} "\ + + std::to_string(pkts); + } else if (classifier == local_classifier2) { + s_tx_bytes = "opflex_sg_tx_bytes{classifier=\"tenant:tenant0,policy:"\ + "classifier2,[etype:2054,]\"} "\ + + std::to_string(bytes); + s_rx_bytes = "opflex_sg_rx_bytes{classifier=\"tenant:tenant0,policy:"\ + "classifier2,[etype:2054,]\"} "\ + + std::to_string(bytes); + s_tx_pkts = "opflex_sg_tx_packets{classifier=\"tenant:tenant0,policy:"\ + "classifier2,[etype:2054,]\"} "\ + + std::to_string(pkts); + s_rx_pkts = "opflex_sg_rx_packets{classifier=\"tenant:tenant0,policy:"\ + "classifier2,[etype:2054,]\"} "\ + + std::to_string(pkts); + } else { + s_tx_bytes = "opflex_sg_tx_bytes{classifier=\"tenant:tenant0,policy:"\ + "classifier3,[etype:2048,proto:6,dport:80-85,]\"} "\ + + std::to_string(bytes); + s_rx_bytes = "opflex_sg_rx_bytes{classifier=\"tenant:tenant0,policy:"\ + "classifier3,[etype:2048,proto:6,dport:80-85,]\"} "\ + + std::to_string(bytes); + s_tx_pkts = "opflex_sg_tx_packets{classifier=\"tenant:tenant0,policy:"\ + "classifier3,[etype:2048,proto:6,dport:80-85,]\"} "\ + + std::to_string(pkts); + s_rx_pkts = "opflex_sg_rx_packets{classifier=\"tenant:tenant0,policy:"\ + "classifier3,[etype:2048,proto:6,dport:80-85,]\"} "\ + + std::to_string(pkts); + } + + const std::string& output = BaseFixture::getOutputFromCommand(cmd); + size_t pos = std::string::npos; + if (isTx) { + pos = output.find(s_tx_pkts); + BOOST_CHECK_NE(pos, std::string::npos); + pos = output.find(s_tx_bytes); + BOOST_CHECK_NE(pos, std::string::npos); + } else { + pos = output.find(s_rx_pkts); + BOOST_CHECK_NE(pos, std::string::npos); + pos = output.find(s_rx_bytes); + BOOST_CHECK_NE(pos, std::string::npos); + } +} + +BOOST_AUTO_TEST_SUITE(SecGrpStatsManagerLocalSG_test) + +BOOST_FIXTURE_TEST_CASE(testFlowMatchStats, SecGrpStatsManagerLocalSGFixture) { + MockConnection accPortConn(TEST_CONN_TYPE_ACC); + secGrpStatsManager.registerConnection(&accPortConn); + secGrpStatsManager.start(); + LOG(DEBUG) << "### SecGrpClassifierCounter flow stats start"; + secGrpStatsManager.Handle(NULL, OFPTYPE_FLOW_STATS_REPLY, NULL); + secGrpStatsManager.Handle(&accPortConn, + OFPTYPE_FLOW_STATS_REPLY, NULL); + LOG(DEBUG) << "### SecGrpClassifierCounter flow stats in start"; + // testing one flow only + testOneFlow(accPortConn,local_classifier1, + AccessFlowManager::SEC_GROUP_IN_TABLE_ID, + 1, false, &secGrpStatsManager); + // 2 entries in flow table now - testing second flow + testOneFlow(accPortConn,local_classifier2, + AccessFlowManager::SEC_GROUP_IN_TABLE_ID, + 2, false, + &secGrpStatsManager); + // changing flow table entry + // Note: If the portNum is set as 2, then it clashes with classifier2 + // entry. So first classifier1 entry will get deleted. No new counter + // objeects will get generated and verifyflowstats will fail. + testOneFlow(accPortConn,local_classifier1, + AccessFlowManager::SEC_GROUP_IN_TABLE_ID, + 3, true, + &secGrpStatsManager); + LOG(DEBUG) << "### SecGrpClassifierCounter flow stats out start"; + // same 3 steps above for OUT table + testOneFlow(accPortConn,local_classifier1, + AccessFlowManager::SEC_GROUP_OUT_TABLE_ID, + 1, false, + &secGrpStatsManager); + testOneFlow(accPortConn,local_classifier2, + AccessFlowManager::SEC_GROUP_OUT_TABLE_ID, + 2, false, + &secGrpStatsManager); + testOneFlow(accPortConn,local_classifier1, + AccessFlowManager::SEC_GROUP_OUT_TABLE_ID, + 3, true, + &secGrpStatsManager); + LOG(DEBUG) << "### SecGrpClassifierCounter flow stats stop"; + secGrpStatsManager.stop(); + +} + + + +BOOST_FIXTURE_TEST_CASE(testFlowRemoved, SecGrpStatsManagerLocalSGFixture) { + MockConnection accPortConn(TEST_CONN_TYPE_ACC); + secGrpStatsManager.registerConnection(&accPortConn); + secGrpStatsManager.start(); + LOG(DEBUG) << "### SecGrpClassifierCounter flow removed start"; + + // Add flows in switchManager + FlowEntryList entryList; + writeClassifierFlows(entryList, + AccessFlowManager::SEC_GROUP_IN_TABLE_ID, + 1, + local_classifier3); + FlowEntryList entryList1; + writeClassifierFlows(entryList1, + AccessFlowManager::SEC_GROUP_OUT_TABLE_ID, + 1, + local_classifier3); + + boost::system::error_code ec; + ec = make_error_code(boost::system::errc::success); + // Call on_timer function to process the flow entries received from + // switchManager. + secGrpStatsManager.on_timer(ec); + + struct ofpbuf *res_msg = + makeFlowRemovedMessage_2(&accPortConn, + LAST_PACKET_COUNT, + AccessFlowManager::SEC_GROUP_IN_TABLE_ID, + entryList); + BOOST_REQUIRE(res_msg!=0); + struct ofputil_flow_removed fentry; + SwitchConnection::DecodeFlowRemoved(res_msg, &fentry); + + secGrpStatsManager.Handle(&accPortConn, + OFPTYPE_FLOW_REMOVED, res_msg, &fentry); + ofpbuf_delete(res_msg); + + // Collect counts related to Rx + secGrpStatsManager.on_timer(ec); + + // 2nd delete received from ovs for same flow, ideally this is a no-op. + // But since on-timer is called table state's flow would have created + // an entry in newCounterMap. So the flow removed message will lead + // to accumulation of stats to prom metric. + res_msg = makeFlowRemovedMessage_2(&accPortConn, + LAST_PACKET_COUNT, + AccessFlowManager::SEC_GROUP_IN_TABLE_ID, + entryList); + BOOST_REQUIRE(res_msg!=0); + + secGrpStatsManager.Handle(&accPortConn, + OFPTYPE_FLOW_REMOVED, res_msg, &fentry); + ofpbuf_delete(res_msg); + + res_msg = + makeFlowRemovedMessage_2(&accPortConn, + LAST_PACKET_COUNT, + AccessFlowManager::SEC_GROUP_OUT_TABLE_ID, + entryList1); + BOOST_REQUIRE(res_msg!=0); + SwitchConnection::DecodeFlowRemoved(res_msg, &fentry); + + secGrpStatsManager.Handle(&accPortConn, + OFPTYPE_FLOW_REMOVED, res_msg, &fentry); + ofpbuf_delete(res_msg); + res_msg = + makeFlowRemovedMessage_2(&accPortConn, + LAST_PACKET_COUNT, + AccessFlowManager::SEC_GROUP_OUT_TABLE_ID, + entryList1); + BOOST_REQUIRE(res_msg!=0); + SwitchConnection::DecodeFlowRemoved(res_msg, &fentry); + + secGrpStatsManager.Handle(&accPortConn, + OFPTYPE_FLOW_REMOVED, res_msg, &fentry); + ofpbuf_delete(res_msg); + // Call on_timer function to process the stats collected + // and generate Genie objects for stats + + // Collect counts relateed to Tx + secGrpStatsManager.on_timer(ec); + + // calculate expected packet count and byte count + // that we should have in Genie object + + verifyFlowStats(local_classifier3, + LAST_PACKET_COUNT, + LAST_PACKET_COUNT * PACKET_SIZE, + true, + AccessFlowManager::SEC_GROUP_IN_TABLE_ID, + &secGrpStatsManager); + verifyFlowStats(local_classifier3, + LAST_PACKET_COUNT, + LAST_PACKET_COUNT * PACKET_SIZE, + false, + AccessFlowManager::SEC_GROUP_OUT_TABLE_ID, + &secGrpStatsManager); + LOG(DEBUG) << "### SecGrpClassifierCounter flow removed stop"; + secGrpStatsManager.stop(); +} + +BOOST_FIXTURE_TEST_CASE(testCircularBuffer, SecGrpStatsManagerLocalSGFixture) { + MockConnection accPortConn(TEST_CONN_TYPE_ACC); + secGrpStatsManager.registerConnection(&accPortConn); + secGrpStatsManager.start(); + + LOG(DEBUG) << "### SecGrpClassifierCounter circbuffer start"; + // Add flows in switchManager + + testCircBuffer(accPortConn, + local_classifier3, + AccessFlowManager::SEC_GROUP_IN_TABLE_ID, + 2, + &secGrpStatsManager); + LOG(DEBUG) << "### SecGrpClassifierCounter circbuffer stop"; + secGrpStatsManager.stop(); +} + +BOOST_FIXTURE_TEST_CASE(testSecGrpDelete, SecGrpStatsManagerLocalSGFixture) { + MockConnection accPortConn(TEST_CONN_TYPE_ACC); + secGrpStatsManager.registerConnection(&accPortConn); + secGrpStatsManager.start(); + + LOG(DEBUG) << "### SecGrpClassifierCounter Delete Start"; + secGrpStatsManager.Handle(&accPortConn, + OFPTYPE_FLOW_STATS_REPLY, NULL); + // testing one flow only + testOneFlow(accPortConn,local_classifier1, + AccessFlowManager::SEC_GROUP_IN_TABLE_ID, + 1, false, &secGrpStatsManager); + Mutator mutator(agent.getFramework(), "policyreg"); + + // Note: In UTs, deleting the sg doesnt trigger classifier delete + //modelgbp::gbp::SecGroup::remove(agent.getFramework(),"tenant0","secgrp1"); + modelgbp::gbpe::L24Classifier::remove(agent.getFramework(),"tenant0","classifier1"); + mutator.commit(); + optional > su = + PolicyStatUniverse::resolve(agent.getFramework()); + const auto& uuid = secGrpStatsManager.getAgentUUID(); + optional > myCounter; + WAIT_FOR_DO_ONFAIL(!(su.get()->resolveGbpeLocalSecGrpClassifierCounter(uuid, + secGrpStatsManager.getCurrClsfrGenId(), + classifier1->getURI().toString())) + ,500 + , + ,LOG(ERROR) << "Obj still present";); + LOG(DEBUG) << "### SecGrpClassifierCounter Delete End"; + secGrpStatsManager.stop(); +} + +BOOST_AUTO_TEST_SUITE_END() + +} diff --git a/agent-ovs/ovs/test/SecGrpStatsManager_test.cpp b/agent-ovs/ovs/test/SecGrpStatsManager_test.cpp index f86b3f48..9a81c3ff 100644 --- a/agent-ovs/ovs/test/SecGrpStatsManager_test.cpp +++ b/agent-ovs/ovs/test/SecGrpStatsManager_test.cpp @@ -160,11 +160,11 @@ BOOST_FIXTURE_TEST_CASE(testFlowMatchStats, SecGrpStatsManagerFixture) { OFPTYPE_FLOW_STATS_REPLY, NULL); LOG(DEBUG) << "### SecGrpClassifierCounter flow stats in start"; // testing one flow only - testOneFlow(accPortConn,classifier1, + testOneFlow(accPortConn,classifier1, AccessFlowManager::SEC_GROUP_IN_TABLE_ID, 1, false, &secGrpStatsManager); // 2 entries in flow table now - testing second flow - testOneFlow(accPortConn,classifier2, + testOneFlow(accPortConn,classifier2, AccessFlowManager::SEC_GROUP_IN_TABLE_ID, 2, false, &secGrpStatsManager); @@ -172,21 +172,21 @@ BOOST_FIXTURE_TEST_CASE(testFlowMatchStats, SecGrpStatsManagerFixture) { // Note: If the portNum is set as 2, then it clashes with classifier2 // entry. So first classifier1 entry will get deleted. No new counter // objeects will get generated and verifyflowstats will fail. - testOneFlow(accPortConn,classifier1, + testOneFlow(accPortConn,classifier1, AccessFlowManager::SEC_GROUP_IN_TABLE_ID, 3, true, &secGrpStatsManager); LOG(DEBUG) << "### SecGrpClassifierCounter flow stats out start"; // same 3 steps above for OUT table - testOneFlow(accPortConn,classifier1, + testOneFlow(accPortConn,classifier1, AccessFlowManager::SEC_GROUP_OUT_TABLE_ID, 1, false, &secGrpStatsManager); - testOneFlow(accPortConn,classifier2, + testOneFlow(accPortConn,classifier2, AccessFlowManager::SEC_GROUP_OUT_TABLE_ID, 2, false, &secGrpStatsManager); - testOneFlow(accPortConn,classifier1, + testOneFlow(accPortConn,classifier1, AccessFlowManager::SEC_GROUP_OUT_TABLE_ID, 3, true, &secGrpStatsManager); @@ -205,12 +205,12 @@ BOOST_FIXTURE_TEST_CASE(testFlowRemoved, SecGrpStatsManagerFixture) { // Add flows in switchManager FlowEntryList entryList; - writeClassifierFlows(entryList, + writeClassifierFlows(entryList, AccessFlowManager::SEC_GROUP_IN_TABLE_ID, 1, classifier3); FlowEntryList entryList1; - writeClassifierFlows(entryList1, + writeClassifierFlows(entryList1, AccessFlowManager::SEC_GROUP_OUT_TABLE_ID, 1, classifier3); @@ -282,13 +282,13 @@ BOOST_FIXTURE_TEST_CASE(testFlowRemoved, SecGrpStatsManagerFixture) { // calculate expected packet count and byte count // that we should have in Genie object - verifyFlowStats(classifier3, + verifyFlowStats(classifier3, LAST_PACKET_COUNT, LAST_PACKET_COUNT * PACKET_SIZE, true, AccessFlowManager::SEC_GROUP_IN_TABLE_ID, &secGrpStatsManager); - verifyFlowStats(classifier3, + verifyFlowStats(classifier3, LAST_PACKET_COUNT, LAST_PACKET_COUNT * PACKET_SIZE, false, @@ -306,7 +306,7 @@ BOOST_FIXTURE_TEST_CASE(testCircularBuffer, SecGrpStatsManagerFixture) { LOG(DEBUG) << "### SecGrpClassifierCounter circbuffer start"; // Add flows in switchManager - testCircBuffer(accPortConn, + testCircBuffer(accPortConn, classifier3, AccessFlowManager::SEC_GROUP_IN_TABLE_ID, 2, @@ -324,7 +324,7 @@ BOOST_FIXTURE_TEST_CASE(testSecGrpDelete, SecGrpStatsManagerFixture) { secGrpStatsManager.Handle(&accPortConn, OFPTYPE_FLOW_STATS_REPLY, NULL); // testing one flow only - testOneFlow(accPortConn,classifier1, + testOneFlow(accPortConn,classifier1, AccessFlowManager::SEC_GROUP_IN_TABLE_ID, 1, false, &secGrpStatsManager); Mutator mutator(agent.getFramework(), "policyreg"); diff --git a/agent-ovs/ovs/test/include/PolicyStatsManagerFixture.h b/agent-ovs/ovs/test/include/PolicyStatsManagerFixture.h index 96002f0b..dcf4f8ef 100644 --- a/agent-ovs/ovs/test/include/PolicyStatsManagerFixture.h +++ b/agent-ovs/ovs/test/include/PolicyStatsManagerFixture.h @@ -90,7 +90,8 @@ class PolicyStatsManagerFixture : public FlowManagerFixture { // New counter objects get created for every diff in flow. Prometheus // maintains an aggregatiion of all these updates. On the second update // with same values in tests, check for total value in prometheus. - void verifyFlowStats(shared_ptr classifier, + template + void verifyFlowStats(shared_ptr classifier, uint32_t packet_count, // delta uint32_t byte_count, // delta bool isExistingMetric, @@ -132,6 +133,54 @@ class PolicyStatsManagerFixture : public FlowManagerFixture { LOG(DEBUG) << "L24classifiercounter mo isnt present"; }); verifyPromMetrics(std::move(classifier), t_packet_count, t_byte_count); + } else if (agent.getPolicyManager().useLocalNetpol()) { + const auto& uuid = statsManager->getAgentUUID(); + optional > myCounter = + boost::make_optional >(false, nullptr); + LOG(DEBUG) << "verifying stats for" + << " classifier: " << classifier->getURI().toString() + << " delta pkt count: " << packet_count + << " delta byte count: " << byte_count + << " total pkt count: " << t_packet_count + << " total byte count: " << t_byte_count; + WAIT_FOR_DO_ONFAIL( + (myCounter && myCounter.get() + && ( + ((table_id == AccessFlowManager::SEC_GROUP_OUT_TABLE_ID) + && (myCounter.get()->getTxpackets() + && (myCounter.get()->getTxpackets().get() == packet_count)) + && (myCounter.get()->getTxbytes() + && (myCounter.get()->getTxbytes().get() == byte_count))) + || + ((table_id == AccessFlowManager::SEC_GROUP_IN_TABLE_ID) + && (myCounter.get()->getRxpackets().get() == packet_count) + && (myCounter.get()->getRxbytes().get() == byte_count)) + )), + 500, // usleep(1000) * 500 = 500ms + (myCounter = su.get()->resolveGbpeLocalSecGrpClassifierCounter(uuid, + statsManager->getCurrClsfrGenId(), + classifier->getURI().toString())), + if (myCounter && myCounter.get()) { + if (table_id == AccessFlowManager::SEC_GROUP_OUT_TABLE_ID) { + if (myCounter.get()->getTxpackets()) { + BOOST_CHECK_EQUAL(myCounter.get()->getTxpackets().get(), packet_count); + } else { + LOG(DEBUG) << "tx pkts invalid"; + } + if (myCounter.get()->getTxbytes()) { + BOOST_CHECK_EQUAL(myCounter.get()->getTxbytes().get(), byte_count); + } else { + LOG(DEBUG) << "tx bytes invalid"; + } + } else if (table_id == AccessFlowManager::SEC_GROUP_IN_TABLE_ID) { + BOOST_CHECK_EQUAL(myCounter.get()->getRxpackets().get(), packet_count); + BOOST_CHECK_EQUAL(myCounter.get()->getRxbytes().get(), byte_count); + } + } else { + LOG(DEBUG) << "SGclassifiercounter mo isnt present"; + }); + verifyPromMetrics(classifier, t_packet_count, t_byte_count, + table_id == AccessFlowManager::SEC_GROUP_OUT_TABLE_ID); } else { const auto& uuid = statsManager->getAgentUUID(); optional > myCounter = @@ -264,10 +313,11 @@ class PolicyStatsManagerFixture : public FlowManagerFixture { return NULL; } + template void writeClassifierFlows(FlowEntryList& entryList, uint32_t table_id, uint32_t portNum, - shared_ptr& classifier, + shared_ptr& classifier, shared_ptr srcEpg = NULL, shared_ptr dstEpg = NULL, PolicyManager *policyManager = NULL) { @@ -302,9 +352,9 @@ class PolicyStatsManagerFixture : public FlowManagerFixture { entryListCopy); } - template + template void testCircBuffer(MockConnection& portConn, - shared_ptr& classifier, + shared_ptr& classifier, uint32_t table_id, uint32_t portNum, PolicyStatsManager *statsManager, @@ -312,7 +362,7 @@ class PolicyStatsManagerFixture : public FlowManagerFixture { shared_ptr dstEpg = NULL, PolicyManager *policyManager = NULL) { FlowEntryList entryList; - writeClassifierFlows(entryList,table_id,portNum,classifier); + writeClassifierFlows(entryList,table_id,portNum,classifier); boost::system::error_code ec; ec = make_error_code(boost::system::errc::success); // Call on_timer function to process the flow entries received from @@ -373,6 +423,13 @@ class PolicyStatsManagerFixture : public FlowManagerFixture { classifier->getURI() .toString()); WAIT_FOR(!myCounter,500); + } else if (agent.getPolicyManager().useLocalNetpol()) { + optional > myCounter = + su.get()->resolveGbpeLocalSecGrpClassifierCounter(uuid,firstId, + classifier-> + getURI(). + toString()); + WAIT_FOR(!myCounter,500); } else { optional > myCounter = su.get()->resolveGbpeSecGrpClassifierCounter(uuid,firstId, @@ -383,9 +440,9 @@ class PolicyStatsManagerFixture : public FlowManagerFixture { } } - template + template void testOneFlow(MockConnection& portConn, - shared_ptr& classifier,uint32_t table_id, + shared_ptr& classifier,uint32_t table_id, uint32_t portNum, bool isExistingMetric, PolicyStatsManager *statsManager, @@ -394,7 +451,7 @@ class PolicyStatsManagerFixture : public FlowManagerFixture { shared_ptr dstEpg = NULL) { // add flows in switchManager FlowEntryList entryList; - writeClassifierFlows(entryList,table_id,portNum,classifier, + writeClassifierFlows(entryList,table_id,portNum,classifier, srcEpg,dstEpg,policyManager); boost::system::error_code ec; @@ -454,7 +511,7 @@ class PolicyStatsManagerFixture : public FlowManagerFixture { // Verify per classifier/per epg pair packet and byte count - verifyFlowStats(classifier, + verifyFlowStats(classifier, exp_classifier_packet_count, exp_classifier_packet_count * PACKET_SIZE, isExistingMetric, diff --git a/genie/MODEL/EXTENSIONS/GBP/extensions.mdl b/genie/MODEL/EXTENSIONS/GBP/extensions.mdl index c2c3125f..ba9407fe 100644 --- a/genie/MODEL/EXTENSIONS/GBP/extensions.mdl +++ b/genie/MODEL/EXTENSIONS/GBP/extensions.mdl @@ -577,6 +577,16 @@ module[gbpe] member[txbytes; type=scalar/UInt64] } + class[LocalSecGrpClassifierCounter; + super=gbpe/SecGrpClassifierCounter; + concrete] + { + contained + { + parent[class=observer/PolicyStatUniverse] + } + } + class[RoutingDomainDropCounter; super=observer/Observable; concrete;