Skip to content

Commit 0e19e13

Browse files
mchallatomflynn
authored andcommitted
Do not add L34 flows if remotesub missing
This bug was reported by Cisco IT where a secgrp with no remote subnets basically allows all ingress traffic due to how we program the rules. Since this is a day 0 issue we decided to fix the behavior while at the same time providing an option for someone to revert to the old behavior. - If remote subnet is missing do not add L3 and L4 flows - A new function add_l2classifier_entries takes care of adding l2 only flows - Add : "behavior": { "l34flows-without-subnet" : true } to opflex config to override this behavior with old, default is false. - verified make check passes with / without this option since I added default 0.0.0.0/0 ::/0 subnet to relevant secgroups. Signed-off-by: Madhu Challa <challa@gmail.com> Change-Id: Iffa03301c24bd576034f5f5858ebb8c75fa72f5e
1 parent fa36c11 commit 0e19e13

File tree

6 files changed

+154
-31
lines changed

6 files changed

+154
-31
lines changed

agent-ovs/lib/Agent.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ Agent::Agent(OFFramework& framework_, const LogParams& _logParams)
7171
prometheusEnabled(true),
7272
prometheusExposeLocalHostOnly(false),
7373
prometheusExposeEpSvcNan(false),
74+
behaviorL34FlowsWithoutSubnet(false),
7475
logParams(_logParams) {
7576
#else
7677
Agent::Agent(OFFramework& framework_, const LogParams& _logParams)
@@ -84,6 +85,7 @@ Agent::Agent(OFFramework& framework_, const LogParams& _logParams)
8485
contractInterval(0), securityGroupInterval(0), interfaceInterval(0),
8586
spanManager(framework, agent_io),
8687
netflowManager(framework,agent_io),
88+
behaviorL34FlowsWithoutSubnet(false),
8789
logParams(_logParams) {
8890
#endif
8991
std::random_device rng;
@@ -194,6 +196,7 @@ void Agent::setProperties(const boost::property_tree::ptree& properties) {
194196
static const std::string OPFLEX_PRR_INTERVAL("opflex.timers.prr");
195197
static const std::string OPFLEX_HANDSHAKE("opflex.timers.handshake-timeout");
196198
static const std::string DISABLED_FEATURES("feature.disabled");
199+
static const std::string BEHAVIOR_L34FLOWS_WITHOUT_SUBNET("behavior.l34flows-without-subnet");
197200

198201
// set feature flags to true
199202
clearFeatureFlags();
@@ -254,6 +257,12 @@ void Agent::setProperties(const boost::property_tree::ptree& properties) {
254257
disabledFeaturesSet.insert(v.second.data());
255258
}
256259

260+
optional<bool> behaviorAddL34FlowsWithoutSubnet =
261+
properties.get_optional<bool>(BEHAVIOR_L34FLOWS_WITHOUT_SUBNET);
262+
if (behaviorAddL34FlowsWithoutSubnet) {
263+
behaviorL34FlowsWithoutSubnet = behaviorAddL34FlowsWithoutSubnet.get();
264+
}
265+
257266
#ifdef HAVE_PROMETHEUS_SUPPORT
258267
boost::optional<bool> prometheusIsEnabled =
259268
properties.get_optional<bool>(PROMETHEUS_ENABLED);

agent-ovs/lib/include/opflexagent/Agent.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -289,6 +289,21 @@ typedef opflex::ofcore::OFConstants::OpflexElementMode opflex_elem_t;
289289
*/
290290
bool isFeatureEnabled(FeatureList feature) { return featureFlag[feature];}
291291

292+
/**
293+
* get behavior for adding l34flows without subnet
294+
* @return true if l34flows should be added without subnet,
295+
* false otherwise, defaults to false
296+
*/
297+
bool addL34FlowsWithoutSubnet() { return behaviorL34FlowsWithoutSubnet; }
298+
299+
/**
300+
* set behavior for adding l34flows without subnet
301+
* @param value the new value for behaviorL34FlowsWithoutSubnet
302+
*/
303+
void setAddL34FlowsWithoutSubnet(bool value) {
304+
behaviorL34FlowsWithoutSubnet = value;
305+
}
306+
292307
/**
293308
* clear feature flags. set them to true.
294309
*/
@@ -411,6 +426,7 @@ typedef opflex::ofcore::OFConstants::OpflexElementMode opflex_elem_t;
411426
bool prometheusExposeEpSvcNan;
412427
std::unordered_set<std::string> prometheusEpAttributes;
413428
#endif
429+
bool behaviorL34FlowsWithoutSubnet;
414430
LogParams logParams;
415431
};
416432

agent-ovs/ovs/AccessFlowManager.cpp

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -591,13 +591,18 @@ void AccessFlowManager::handleSecGrpSetUpdate(const uri_set_t& secGrps,
591591

592592
for (shared_ptr<PolicyRule>& pc : rules) {
593593
uint8_t dir = pc->getDirection();
594+
bool skipL34 = false;
594595
const shared_ptr<L24Classifier>& cls = pc->getL24Classifier();
595596
const URI& ruleURI = cls.get()->getURI();
596597
uint64_t secGrpCookie =
597598
idGen.getId("l24classifierRule", ruleURI.toString());
598599
boost::optional<const network::subnets_t&> remoteSubs;
599600
if (!pc->getRemoteSubnets().empty())
600601
remoteSubs = pc->getRemoteSubnets();
602+
else
603+
skipL34 = !agent.addL34FlowsWithoutSubnet();
604+
605+
LOG(DEBUG) << "skipL34 flows: " << skipL34;
601606

602607
flowutils::ClassAction act = flowutils::CA_DENY;
603608
if (pc->getAllow()) {
@@ -609,6 +614,35 @@ void AccessFlowManager::handleSecGrpSetUpdate(const uri_set_t& secGrps,
609614
}
610615
}
611616

617+
/*
618+
* Do not program higher level protocols
619+
* when remote subnet is missing
620+
* except when agent.addL34FlowsWithoutSubnet() == true
621+
*/
622+
if (skipL34) {
623+
if (dir == DirectionEnumT::CONST_BIDIRECTIONAL ||
624+
dir == DirectionEnumT::CONST_IN) {
625+
flowutils::add_l2classifier_entries(*cls, act,
626+
OUT_TABLE_ID,
627+
pc->getPriority(),
628+
OFPUTIL_FF_SEND_FLOW_REM,
629+
secGrpCookie,
630+
secGrpSetId, 0,
631+
secGrpIn);
632+
}
633+
if (dir == DirectionEnumT::CONST_BIDIRECTIONAL ||
634+
dir == DirectionEnumT::CONST_OUT) {
635+
flowutils::add_l2classifier_entries(*cls, act,
636+
OUT_TABLE_ID,
637+
pc->getPriority(),
638+
OFPUTIL_FF_SEND_FLOW_REM,
639+
secGrpCookie,
640+
secGrpSetId, 0,
641+
secGrpOut);
642+
}
643+
continue;
644+
}
645+
612646
if (dir == DirectionEnumT::CONST_BIDIRECTIONAL ||
613647
dir == DirectionEnumT::CONST_IN) {
614648
flowutils::add_classifier_entries(*cls, act,

agent-ovs/ovs/FlowUtils.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,27 @@ static flow_func make_flow_functor(const network::subnet_t& ss,
123123
return std::bind(applyRemoteSub, _1, func, addr, ss.second, _2);
124124
}
125125

126+
void add_l2classifier_entries(L24Classifier& clsfr, ClassAction act,
127+
uint8_t nextTable, uint16_t priority,
128+
uint32_t flags, uint64_t cookie,
129+
uint32_t svnid, uint32_t dvnid,
130+
/* out */ FlowEntryList& entries) {
131+
if (clsfr.isProtSet())
132+
return;
133+
134+
ovs_be64 ckbe = ovs_htonll(cookie);
135+
FlowBuilder f;
136+
137+
f.cookie(ckbe)
138+
.flags(flags);
139+
flowutils::match_group(f, priority, svnid, dvnid);
140+
match_protocol(f, clsfr);
141+
if (act != flowutils::CA_DENY)
142+
f.action().go(nextTable);
143+
144+
entries.push_back(f.build());
145+
}
146+
126147
void add_classifier_entries(L24Classifier& clsfr, ClassAction act,
127148
boost::optional<const network::subnets_t&> sourceSub,
128149
boost::optional<const network::subnets_t&> destSub,

agent-ovs/ovs/include/FlowUtils.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,26 @@ void add_classifier_entries(modelgbp::gbpe::L24Classifier& clsfr,
118118
uint32_t svnid, uint32_t dvnid,
119119
/* out */ FlowEntryList& entries);
120120

121+
/**
122+
* Create L2 flow entries for the classifier specified and append them
123+
* to the provided list.
124+
*
125+
* @param classifier Classifier object to get matching rules from
126+
* @param act an action to take for the flows
127+
* @param nextTable the table to send to if the traffic is allowed
128+
* @param priority Priority of the entry created
129+
* @param flags the flow flags to use
130+
* @param cookie Cookie of the entry created
131+
* @param svnid VNID of the source endpoint group for the entry
132+
* @param dvnid VNID of the destination endpoint group for the entry
133+
* @param entries List to append entry to
134+
*/
135+
void add_l2classifier_entries(modelgbp::gbpe::L24Classifier& clsfr,
136+
ClassAction act,
137+
uint8_t nextTable, uint16_t priority,
138+
uint32_t flags, uint64_t cookie,
139+
uint32_t svnid, uint32_t dvnid,
140+
/* out */ FlowEntryList& entries);
121141
/**
122142
* Add a match entry for the DHCP v4 and v6 request
123143
*

agent-ovs/ovs/test/AccessFlowManager_test.cpp

Lines changed: 54 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -187,29 +187,49 @@ BOOST_FIXTURE_TEST_CASE(learningBridge, AccessFlowManagerFixture) {
187187
BOOST_FIXTURE_TEST_CASE(secGrp, AccessFlowManagerFixture) {
188188
createObjects();
189189
createPolicyObjects();
190+
shared_ptr<modelgbp::gbp::Subnets> rs;
190191
{
191192
Mutator mutator(framework, "policyreg");
193+
rs = space->addGbpSubnets("subnets_rule0");
194+
195+
rs->addGbpSubnet("subnets_rule0_1")
196+
->setAddress("0.0.0.0")
197+
.setPrefixLen(0);
198+
rs->addGbpSubnet("subnets_rule0_2")
199+
->setAddress("0::")
200+
.setPrefixLen(0);
201+
202+
shared_ptr<modelgbp::gbp::SecGroupRule> r1, r2, r3, r4, r5;
192203
secGrp1 = space->addGbpSecGroup("secgrp1");
193-
secGrp1->addGbpSecGroupSubject("1_subject1")
194-
->addGbpSecGroupRule("1_1_rule1")
195-
->setDirection(DirectionEnumT::CONST_IN).setOrder(100)
204+
205+
r1 = secGrp1->addGbpSecGroupSubject("1_subject1")
206+
->addGbpSecGroupRule("1_1_rule1");
207+
r1->setDirection(DirectionEnumT::CONST_IN).setOrder(100)
196208
.addGbpRuleToClassifierRSrc(classifier1->getURI().toString());
197-
secGrp1->addGbpSecGroupSubject("1_subject1")
198-
->addGbpSecGroupRule("1_1_rule2")
199-
->setDirection(DirectionEnumT::CONST_IN).setOrder(150)
209+
r1->addGbpSecGroupRuleToRemoteAddressRSrc(rs->getURI().toString());
210+
211+
r2 = secGrp1->addGbpSecGroupSubject("1_subject1")
212+
->addGbpSecGroupRule("1_1_rule2");
213+
r2->setDirection(DirectionEnumT::CONST_IN).setOrder(150)
200214
.addGbpRuleToClassifierRSrc(classifier8->getURI().toString());
201-
secGrp1->addGbpSecGroupSubject("1_subject1")
202-
->addGbpSecGroupRule("1_1_rule3")
203-
->setDirection(DirectionEnumT::CONST_OUT).setOrder(200)
215+
r2->addGbpSecGroupRuleToRemoteAddressRSrc(rs->getURI().toString());
216+
217+
r3 = secGrp1->addGbpSecGroupSubject("1_subject1")
218+
->addGbpSecGroupRule("1_1_rule3");
219+
r3->setDirection(DirectionEnumT::CONST_OUT).setOrder(200)
204220
.addGbpRuleToClassifierRSrc(classifier2->getURI().toString());
205-
secGrp1->addGbpSecGroupSubject("1_subject1")
206-
->addGbpSecGroupRule("1_1_rule4")
207-
->setDirection(DirectionEnumT::CONST_IN).setOrder(300)
221+
222+
r4 = secGrp1->addGbpSecGroupSubject("1_subject1")
223+
->addGbpSecGroupRule("1_1_rule4");
224+
r4->setDirection(DirectionEnumT::CONST_IN).setOrder(300)
208225
.addGbpRuleToClassifierRSrc(classifier6->getURI().toString());
209-
secGrp1->addGbpSecGroupSubject("1_subject1")
210-
->addGbpSecGroupRule("1_1_rule5")
211-
->setDirection(DirectionEnumT::CONST_IN).setOrder(400)
226+
r4->addGbpSecGroupRuleToRemoteAddressRSrc(rs->getURI().toString());
227+
228+
r5 = secGrp1->addGbpSecGroupSubject("1_subject1")
229+
->addGbpSecGroupRule("1_1_rule5");
230+
r5->setDirection(DirectionEnumT::CONST_IN).setOrder(400)
212231
.addGbpRuleToClassifierRSrc(classifier7->getURI().toString());
232+
r5->addGbpSecGroupRuleToRemoteAddressRSrc(rs->getURI().toString());
213233
mutator.commit();
214234
}
215235

@@ -238,19 +258,25 @@ BOOST_FIXTURE_TEST_CASE(secGrp, AccessFlowManagerFixture) {
238258
WAIT_FOR_TABLES("two-secgrp-nocon", 500);
239259

240260
{
261+
shared_ptr<modelgbp::gbp::SecGroupRule> r1, r2, r3;
262+
241263
Mutator mutator(framework, "policyreg");
242264
secGrp2 = space->addGbpSecGroup("secgrp2");
243-
secGrp2->addGbpSecGroupSubject("2_subject1")
244-
->addGbpSecGroupRule("2_1_rule1")
245-
->addGbpRuleToClassifierRSrc(classifier0->getURI().toString());
246-
secGrp2->addGbpSecGroupSubject("2_subject1")
247-
->addGbpSecGroupRule("2_1_rule2")
248-
->setDirection(DirectionEnumT::CONST_BIDIRECTIONAL).setOrder(20)
265+
r1 = secGrp2->addGbpSecGroupSubject("2_subject1")
266+
->addGbpSecGroupRule("2_1_rule1");
267+
r1->addGbpRuleToClassifierRSrc(classifier0->getURI().toString());
268+
r1->addGbpSecGroupRuleToRemoteAddressRSrc(rs->getURI().toString());
269+
270+
r2 = secGrp2->addGbpSecGroupSubject("2_subject1")
271+
->addGbpSecGroupRule("2_1_rule2");
272+
r2->setDirection(DirectionEnumT::CONST_BIDIRECTIONAL).setOrder(20)
249273
.addGbpRuleToClassifierRSrc(classifier5->getURI().toString());
250-
secGrp2->addGbpSecGroupSubject("2_subject1")
251-
->addGbpSecGroupRule("2_1_rule3")
252-
->setDirection(DirectionEnumT::CONST_OUT).setOrder(30)
274+
275+
r3 = secGrp2->addGbpSecGroupSubject("2_subject1")
276+
->addGbpSecGroupRule("2_1_rule3");
277+
r3->setDirection(DirectionEnumT::CONST_OUT).setOrder(30)
253278
.addGbpRuleToClassifierRSrc(classifier9->getURI().toString());
279+
r3->addGbpSecGroupRuleToRemoteAddressRSrc(rs->getURI().toString());
254280
mutator.commit();
255281
}
256282

@@ -259,7 +285,6 @@ BOOST_FIXTURE_TEST_CASE(secGrp, AccessFlowManagerFixture) {
259285
initExpSecGrpSet12(true);
260286
WAIT_FOR_TABLES("two-secgrp", 500);
261287

262-
shared_ptr<modelgbp::gbp::Subnets> rs;
263288
{
264289
Mutator mutator(framework, "policyreg");
265290
rs = space->addGbpSubnets("subnets_rule1");
@@ -470,10 +495,9 @@ uint16_t AccessFlowManagerFixture::initExpSecGrp1(uint32_t setId,
470495
ADDF(Bldr(SEND_FLOW_REM).table(IN_POL).priority(prio).cookie(ruleId)
471496
.tcp().reg(SEPG, setId).isIpSrc("10.0.0.0/8").isTpDst(80)
472497
.actions().go(OUT).done());
473-
} else {
474-
ADDF(Bldr(SEND_FLOW_REM).table(IN_POL).priority(prio).cookie(ruleId)
475-
.tcp().reg(SEPG, setId).isTpDst(80).actions().go(OUT).done());
476498
}
499+
ADDF(Bldr(SEND_FLOW_REM).table(IN_POL).priority(prio).cookie(ruleId)
500+
.tcp().reg(SEPG, setId).isTpDst(80).actions().go(OUT).done());
477501
/* classifer 8 */
478502
ruleId = idGen.getId("l24classifierRule",
479503
classifier8->getURI().toString());
@@ -486,10 +510,9 @@ uint16_t AccessFlowManagerFixture::initExpSecGrp1(uint32_t setId,
486510
.tcp6().reg(SEPG, setId)
487511
.isIpv6Src("fd34:9c39:1374:358c::/64")
488512
.isTpDst(80).actions().go(OUT).done());
489-
} else {
490-
ADDF(Bldr(SEND_FLOW_REM).table(IN_POL).priority(prio-128).cookie(ruleId)
491-
.tcp6().reg(SEPG, setId).isTpDst(80).actions().go(OUT).done());
492513
}
514+
ADDF(Bldr(SEND_FLOW_REM).table(IN_POL).priority(prio-128).cookie(ruleId)
515+
.tcp6().reg(SEPG, setId).isTpDst(80).actions().go(OUT).done());
493516
/* classifier 2 */
494517
ruleId = idGen.getId("l24classifierRule",
495518
classifier2->getURI().toString());

0 commit comments

Comments
 (0)