Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Changes for local network policies #572

Merged
merged 1 commit into from
Jul 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions agent-ovs/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ libopflex_agent_la_include_HEADERS = \
lib/include/opflexagent/Snat.h \
lib/include/opflexagent/SnatSource.h \
lib/include/opflexagent/SnatListener.h \
lib/include/opflexagent/FSNetpolSource.h \
lib/include/opflexagent/FSPacketDropLogConfigSource.h \
lib/include/opflexagent/PacketDropLogConfig.h \
lib/include/opflexagent/Faults.h \
Expand Down Expand Up @@ -228,6 +229,7 @@ libopflex_agent_la_SOURCES = \
lib/Snat.cpp \
lib/SnatManager.cpp \
lib/SnatSource.cpp \
lib/FSNetpolSource.cpp \
lib/FSPacketDropLogConfigSource.cpp \
lib/AgentPrometheusManager.cpp

Expand Down
30 changes: 29 additions & 1 deletion agent-ovs/lib/Agent.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#include <opflexagent/FSLearningBridgeSource.h>
#include <opflexagent/FSExternalEndpointSource.h>
#include <opflexagent/FSSnatSource.h>
#include <opflexagent/FSNetpolSource.h>
#include <opflexagent/FSPacketDropLogConfigSource.h>
#include <opflexagent/logging.h>

Expand Down Expand Up @@ -78,7 +79,8 @@ Agent::Agent(OFFramework& framework_, const LogParams& _logParams)
prometheusExposeEpSvcNan(false),
behaviorL34FlowsWithoutSubnet(true),
logParams(_logParams),
startupPolicyEnabled(false) {
startupPolicyEnabled(false),
localNetpolEnabled(false) {
std::random_device rng;
std::mt19937 urng(rng());
uuid = to_string(basic_random_generator<std::mt19937>(urng)());
Expand Down Expand Up @@ -149,6 +151,7 @@ void Agent::setProperties(const boost::property_tree::ptree& properties) {
static const std::string ENDPOINT_SOURCE_MODEL_LOCAL("endpoint-sources.model-local");
static const std::string SERVICE_SOURCE_PATH("service-sources.filesystem");
static const std::string SNAT_SOURCE_PATH("snat-sources.filesystem");
static const std::string NETPOL_SOURCE_PATH("netpol-sources.filesystem");
static const std::string DROP_LOG_CFG_SOURCE_FSPATH("drop-log-config-sources.filesystem");
static const std::string FAULT_SOURCE_FSPATH("host-agent-fault-sources.filesystem");
static const std::string PACKET_EVENT_NOTIF_SOCK("packet-event-notif.socket-name");
Expand Down Expand Up @@ -194,6 +197,7 @@ void Agent::setProperties(const boost::property_tree::ptree& properties) {
static const std::string OPFLEX_POLICY_FILE("opflex.startup.policy-file");
static const std::string OPFLEX_LOCAL_RESOLVE_AFTER_CONNECTION("opflex.startup.resolve-aft-conn");
static const std::string OPFLEX_STARTUP_POLICY_DURATION("opflex.startup.policy-duration");
static const std::string OPFLEX_ENABLE_LOCAL_NETPOL("opflex.enable-local-netpol");

// set feature flags to true
clearFeatureFlags();
Expand Down Expand Up @@ -327,6 +331,13 @@ void Agent::setProperties(const boost::property_tree::ptree& properties) {
snatSourcePaths.insert(v.second.data());
}

optional<const ptree&> netpolSource =
properties.get_child_optional(NETPOL_SOURCE_PATH);
if (netpolSource) {
for (const ptree::value_type &v : netpolSource.get())
netpolSourcePaths.insert(v.second.data());
}

optional<const ptree&> dropLogCfgSrc =
properties.get_child_optional(DROP_LOG_CFG_SOURCE_FSPATH);

Expand Down Expand Up @@ -556,6 +567,13 @@ void Agent::setProperties(const boost::property_tree::ptree& properties) {
localResolveAftConn = lResolveAftConn.get();
LOG(INFO) << "Startup policy resolve after connection set to " << localResolveAftConn;
}

optional<bool> enableLocalNetpol =
properties.get_optional<bool>(OPFLEX_ENABLE_LOCAL_NETPOL);
if (enableLocalNetpol && enableLocalNetpol.get()) {
localNetpolEnabled = true;
LOG(INFO) << "Local Network Policy is enabled";
}
}

void Agent::applyProperties() {
Expand All @@ -568,13 +586,16 @@ void Agent::applyProperties() {
policyManager.setOpflexDomain(opflexDomain.get());
}

policyManager.configLocalNetpol(localNetpolEnabled);
if (endpointSourceFSPaths.empty() &&
endpointSourceModelLocalNames.empty())
LOG(ERROR) << "No endpoint sources found in configuration.";
if (serviceSourcePaths.empty())
LOG(INFO) << "No service sources found in configuration.";
if (snatSourcePaths.empty())
LOG(INFO) << "No SNAT sources found in configuration.";
if (netpolSourcePaths.empty())
LOG(INFO) << "No Local Network Policy sources found in configuration.";
if (opflexPeers.empty())
LOG(ERROR) << "No Opflex peers found in configuration";
if (renderers.empty())
Expand Down Expand Up @@ -696,6 +717,13 @@ void Agent::start() {
new FSSnatSource(&snatManager, fsWatcher, path);
snatSources.emplace_back(source);
}
if (localNetpolEnabled) {
for (const std::string& path : netpolSourcePaths) {
FSNetpolSource* source =
new FSNetpolSource(framework, fsWatcher, path);
netpolSources.emplace_back(source);
}
}
if(!dropLogCfgSourcePath.empty()) {
opflex::modb::URI uri = (opflex::modb::URIBuilder()
.addElement("PolicyUniverse").addElement("ObserverDropLogConfig")
Expand Down
80 changes: 61 additions & 19 deletions agent-ovs/lib/EndpointManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -883,17 +883,32 @@ bool EndpointManager::updateEndpointLocal(const string& uuid,
}
newlocall2eps.insert(l2e->getURI());

vector<shared_ptr<EndPointToSecGroupRSrc> > oldSecGrps;
l2e->resolveEpdrEndPointToSecGroupRSrc(oldSecGrps);
const set<URI>& secGrps = es.endpoint->getSecurityGroups();
for (const shared_ptr<EndPointToSecGroupRSrc>& og :
oldSecGrps) {
optional<URI> targ = og->getTargetURI();
if (!targ || secGrps.find(targ.get()) == secGrps.end())
og->remove();
}
for (const URI& sg : secGrps) {
l2e->addEpdrEndPointToSecGroupRSrc(sg.toString());
if (policyManager.useLocalNetpol()) {
vector<shared_ptr<EndPointToLocalSecGroupRSrc> > oldSecGrps;
l2e->resolveEpdrEndPointToLocalSecGroupRSrc(oldSecGrps);
const set<URI>& secGrps = es.endpoint->getSecurityGroups();
for (const shared_ptr<EndPointToLocalSecGroupRSrc>& og :
oldSecGrps) {
optional<URI> targ = og->getTargetURI();
if (!targ || secGrps.find(targ.get()) == secGrps.end())
og->remove();
}
for (const URI& sg : secGrps) {
l2e->addEpdrEndPointToLocalSecGroupRSrc(sg.toString());
}
} else {
vector<shared_ptr<EndPointToSecGroupRSrc> > oldSecGrps;
l2e->resolveEpdrEndPointToSecGroupRSrc(oldSecGrps);
const set<URI>& secGrps = es.endpoint->getSecurityGroups();
for (const shared_ptr<EndPointToSecGroupRSrc>& og :
oldSecGrps) {
optional<URI> targ = og->getTargetURI();
if (!targ || secGrps.find(targ.get()) == secGrps.end())
og->remove();
}
for (const URI& sg : secGrps) {
l2e->addEpdrEndPointToSecGroupRSrc(sg.toString());
}
}

const optional<URI>& qosPol =
Expand Down Expand Up @@ -1007,13 +1022,33 @@ static URI formSecGroupURI (SecurityGroupContext& sgc) {
.build();
}

/* Form the URI of local secGroup from the given security group.
* This is needed since we want to generate URI without the EPR prefixes of the EP */
static URI formLocalSecGroupURI (SecurityGroupContext& sgc) {
optional<const string&> sgOpt = sgc.getSecGroup();
if (!sgOpt)
return URIBuilder().build();
const auto& sg = sgOpt.get();
size_t spaceStart = sg.find("PolicySpace") + 12;
size_t gsgStart = sg.rfind("GbpLocalSecGroup");
size_t nameStart = gsgStart + 17;
return URIBuilder()
.addElement("PolicyUniverse")
.addElement("PolicySpace")
.addElement(sg.substr(spaceStart, gsgStart-spaceStart-1))
.addElement("GbpLocalSecGroup")
.addElement(sg.substr(nameStart, sg.size()-nameStart-1))
.build();
}

static shared_ptr<modelgbp::epr::L2Ep>
populateL2E(shared_ptr<modelgbp::epr::L2Universe>& l2u,
shared_ptr<const Endpoint>& ep,
const string& uuid,
shared_ptr<modelgbp::gbp::BridgeDomain>& bd,
const URI& egURI,
const set<URI>& secGroups) {
const set<URI>& secGroups,
bool localNetpolEnabled) {
using namespace modelgbp::gbp;
using namespace modelgbp::gbpe;
using namespace modelgbp::epr;
Expand All @@ -1028,7 +1063,8 @@ populateL2E(shared_ptr<modelgbp::epr::L2Universe>& l2u,
vector<shared_ptr<SecurityGroupContext> > outSGC;
l2e->resolveEprSecurityGroupContext(outSGC);
for (auto &sgc : outSGC) {
auto sgURI = formSecGroupURI(*sgc);
auto sgURI = localNetpolEnabled ? formLocalSecGroupURI(*sgc)
: formSecGroupURI(*sgc);
if (secGroups.find(sgURI) == secGroups.end())
sgc->remove();
}
Expand Down Expand Up @@ -1073,7 +1109,8 @@ populateL3E(shared_ptr<modelgbp::epr::L3Universe>& l3u,
shared_ptr<modelgbp::gbp::RoutingDomain>& rd,
const string& ip,
const URI& egURI,
const set<URI>& secGroups) {
const set<URI>& secGroups,
bool localNetpolEnabled) {
using namespace modelgbp::gbp;
using namespace modelgbp::epr;

Expand All @@ -1087,7 +1124,8 @@ populateL3E(shared_ptr<modelgbp::epr::L3Universe>& l3u,
vector<shared_ptr<SecurityGroupContext> > outSGC;
l3e->resolveEprSecurityGroupContext(outSGC);
for (auto &sgc : outSGC) {
auto sgURI = formSecGroupURI(*sgc);
auto sgURI = localNetpolEnabled ? formLocalSecGroupURI(*sgc)
: formSecGroupURI(*sgc);
if (secGroups.find(sgURI) == secGroups.end())
sgc->remove();
}
Expand Down Expand Up @@ -1132,7 +1170,8 @@ bool EndpointManager::updateEndpointReg(const string& uuid) {
{
shared_ptr<L2Ep> l2e =
populateL2E(l2u.get(), es.endpoint, uuid,
bd.get(), egURI.get(), secGroups);
bd.get(), egURI.get(), secGroups,
policyManager.useLocalNetpol());

newl2eps.insert(l2e->getURI());
}
Expand All @@ -1152,7 +1191,8 @@ bool EndpointManager::updateEndpointReg(const string& uuid) {
shared_ptr<L2Ep> fl2e =
populateL2E(l2u.get(), es.endpoint, ipm.getUUID(), fbd.get(),
ipm.getEgURI().get(),
secGroups);
secGroups,
policyManager.useLocalNetpol());
newl2eps.insert(fl2e->getURI());
}
}
Expand All @@ -1171,7 +1211,8 @@ bool EndpointManager::updateEndpointReg(const string& uuid) {
shared_ptr<L3Ep> l3e =
populateL3E(l3u.get(), es.endpoint, uuid,
rd.get(), ip, egURI.get(),
secGroups);
secGroups,
policyManager.useLocalNetpol());
newl3eps.insert(l3e->getURI());
}

Expand All @@ -1192,7 +1233,8 @@ bool EndpointManager::updateEndpointReg(const string& uuid) {
populateL3E(l3u.get(), es.endpoint, ipm.getUUID(),
frd.get(), ipm.getFloatingIP().get(),
ipm.getEgURI().get(),
secGroups);
secGroups,
policyManager.useLocalNetpol());
newl3eps.insert(fl3e->getURI());
}
}
Expand Down
24 changes: 17 additions & 7 deletions agent-ovs/lib/FSEndpointSource.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -205,13 +205,23 @@ void FSEndpointSource::updated(const fs::path& filePath) {
optional<string> secGrpName =
v.second.get_optional<string>(SEC_GROUP_NAME);
if (secGrpName && secGrpPS) {
newep.addSecurityGroup(opflex::modb::URIBuilder()
.addElement("PolicyUniverse")
.addElement("PolicySpace")
.addElement(secGrpPS.get())
.addElement("GbpSecGroup")
.addElement(secGrpName.get())
.build());
if (manager->getAgent().getPolicyManager().useLocalNetpol()) {
newep.addSecurityGroup(opflex::modb::URIBuilder()
.addElement("PolicyUniverse")
.addElement("PolicySpace")
.addElement(secGrpPS.get())
.addElement("GbpLocalSecGroup")
.addElement(secGrpName.get())
.build());
} else {
newep.addSecurityGroup(opflex::modb::URIBuilder()
.addElement("PolicyUniverse")
.addElement("PolicySpace")
.addElement(secGrpPS.get())
.addElement("GbpSecGroup")
.addElement(secGrpName.get())
.build());
}
}
}
}
Expand Down
98 changes: 98 additions & 0 deletions agent-ovs/lib/FSNetpolSource.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
/* -*- C++ -*-; c-basic-offset: 4; indent-tabs-mode: nil */
/*
* Implementation for FSNetpolSource class.
*
* Copyright (c) 2024 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
*/

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#if defined(HAVE_SYS_INOTIFY_H) && defined(HAVE_SYS_EVENTFD_H)
#define USE_INOTIFY
#endif

#include <stdexcept>
#include <sstream>
#include <boost/algorithm/string/predicate.hpp>

#include <opflexagent/FSNetpolSource.h>
#include <opflexagent/logging.h>

namespace opflexagent {

using boost::optional;
namespace fs = boost::filesystem;
using std::string;
using std::runtime_error;

FSNetpolSource::FSNetpolSource(opflex::ofcore::OFFramework& framework_,
FSWatcher& listener,
const std::string& netpolDir)
: framework(framework_) {
LOG(INFO) << "Watching " << netpolDir << " for netpol data";
listener.addWatch(netpolDir, *this);
}

static bool isnetpol(fs::path filePath) {
string fstr = filePath.filename().string();
return (boost::algorithm::ends_with(fstr, ".netpol") &&
!boost::algorithm::starts_with(fstr, "."));
}

void FSNetpolSource::updated(const fs::path& filePath) {
if (!isnetpol(filePath)) return;

try {
string pathstr = filePath.string();
netpol_map_t::const_iterator it = knownNetpols.find(pathstr);
if (it != knownNetpols.end()) {
deleted(filePath);
}
opflex::modb::mointernal::StoreClient::notif_t notifs;
size_t n =
framework.updateMOs(pathstr, opflex::gbp::PolicyUpdateOp::REPLACE, &notifs);
knownNetpols[pathstr] = notifs;

LOG(INFO) << "Updated Netpol " << filePath.stem()
<< " from " << filePath
<< " ( " << n << " Objects )";
} catch (const std::exception& ex) {
LOG(ERROR) << "Could not load netpol from: "
<< filePath << ": "
<< ex.what();
} catch (...) {
LOG(ERROR) << "Unknown error while loading netpol "
<< "information from "
<< filePath;
}
}

void FSNetpolSource::deleted(const fs::path& filePath) {
try {
string pathstr = filePath.string();
netpol_map_t::iterator it = knownNetpols.find(pathstr);
if (it != knownNetpols.end()) {

framework.deleteMOs(it->second);
LOG(INFO) << "Removed netpol-uuid "
<< filePath.stem()
<< " at " << filePath
<< " ( " << it->second.size() << " Objects )";
knownNetpols.erase(it);
}
} catch (const std::exception& ex) {
LOG(ERROR) << "Could not delete netpol for "
<< filePath << ": "
<< ex.what();
} catch (...) {
LOG(ERROR) << "Unknown error while deleting netpol information for "
<< filePath;
}
}

} /* namespace opflexagent */
Loading