From 679d6b0c0d58b893ab73abd9052379e3c071c96e Mon Sep 17 00:00:00 2001 From: ansao-aci Date: Fri, 13 Aug 2021 10:02:11 +0000 Subject: [PATCH] System security group changes --- agent-ovs/ovs/AccessFlowManager.cpp | 227 ++++++++++++++---- agent-ovs/ovs/FlowUtils.cpp | 27 ++- agent-ovs/ovs/IntFlowManager.cpp | 4 + agent-ovs/ovs/include/AccessFlowManager.h | 13 +- agent-ovs/ovs/include/FlowUtils.h | 2 + agent-ovs/ovs/test/AccessFlowManager_test.cpp | 124 +++++++++- .../ovs/test/TableDropStatsManager_test.cpp | 3 +- 7 files changed, 341 insertions(+), 59 deletions(-) diff --git a/agent-ovs/ovs/AccessFlowManager.cpp b/agent-ovs/ovs/AccessFlowManager.cpp index a1a32af5a..f3d3fa712 100644 --- a/agent-ovs/ovs/AccessFlowManager.cpp +++ b/agent-ovs/ovs/AccessFlowManager.cpp @@ -20,6 +20,7 @@ #include #include #include +#include #include #include "ovs-ofputil.h" #include @@ -46,6 +47,7 @@ using boost::optional; static const char* ID_NAMESPACES[] = {"secGroup", "secGroupSet"}; +static const int VMM_DOMAIN_DN_PARTS = 4; static const char* ID_NMSPC_SECGROUP = ID_NAMESPACES[0]; static const char* ID_NMSPC_SECGROUP_SET = ID_NAMESPACES[1]; @@ -59,8 +61,12 @@ void AccessFlowManager::populateTableDescriptionMap( TABLE_DESC(SERVICE_BYPASS_TABLE_ID, "SERVICE_BYPASS_TABLE", "Skip security-group checks for Service loopback traffic") TABLE_DESC(GROUP_MAP_TABLE_ID, "GROUP_MAP_TABLE", "Access port incorrect") + TABLE_DESC(SYS_SEC_GRP_IN_TABLE_ID, "SYS_SEC_GRP_IN_TABLE_ID", + "Ingress System Security group derivation missing/incorrect") TABLE_DESC(SEC_GROUP_IN_TABLE_ID, "SEC_GROUP_IN_TABLE", "Ingress Security group derivation missing/incorrect") + TABLE_DESC(SYS_SEC_GRP_OUT_TABLE_ID, "SYS_SEC_GRP_OUT_TABLE_ID", + "Egress System Security group derivation missing/incorrect") TABLE_DESC(SEC_GROUP_OUT_TABLE_ID, "SEC_GROUP_OUT_TABLE", "Egress security group missing/incorrect") TABLE_DESC(TAP_TABLE_ID, "TAP_TABLE", @@ -472,6 +478,23 @@ void AccessFlowManager::createStaticFlows() { .parent().build(tapFlows); switchManager.writeFlow("static", TAP_TABLE_ID, tapFlows); } + { + FlowEntryList defaultSysIngressFlow; + FlowBuilder().priority(1) + .action().go(SEC_GROUP_IN_TABLE_ID) + .parent().build(defaultSysIngressFlow); + switchManager.writeFlow("static", SYS_SEC_GRP_IN_TABLE_ID, defaultSysIngressFlow); + + } + { + FlowEntryList defaultSysEgressFlow; + FlowBuilder().priority(1) + .action().go(SEC_GROUP_OUT_TABLE_ID) + .parent().build(defaultSysEgressFlow); + switchManager.writeFlow("static", SYS_SEC_GRP_OUT_TABLE_ID, defaultSysEgressFlow); + + } + // everything is allowed for endpoints with no security group set uint32_t emptySecGrpSetId = idGen.getId(ID_NMSPC_SECGROUP_SET, ""); switchManager.writeFlow("static", SEC_GROUP_OUT_TABLE_ID, @@ -533,6 +556,7 @@ void AccessFlowManager::handleEndpointUpdate(const string& uuid) { FlowEntryList el; FlowEntryList skipServiceFlows; + if (accessPort != OFPP_NONE && uplinkPort != OFPP_NONE) { { FlowBuilder in; @@ -558,7 +582,7 @@ void AccessFlowManager::handleEndpointUpdate(const string& uuid) { flow::meta::access_meta::MASK); } - in.action().go(SEC_GROUP_OUT_TABLE_ID); + in.action().go(SYS_SEC_GRP_OUT_TABLE_ID); in.build(el); } @@ -588,7 +612,7 @@ void AccessFlowManager::handleEndpointUpdate(const string& uuid) { .reg(MFF_REG7, uplinkPort) .metadata(flow::meta::access_meta::EGRESS_DIR, flow::meta::access_meta::MASK) - .go(SEC_GROUP_OUT_TABLE_ID); + .go(SYS_SEC_GRP_OUT_TABLE_ID); inSkipVlan.build(el); } @@ -636,7 +660,7 @@ void AccessFlowManager::handleEndpointUpdate(const string& uuid) { .metadata(flow::meta::access_meta::INGRESS_DIR, flow::meta::access_meta::MASK); } - out.action().go(SEC_GROUP_IN_TABLE_ID); + out.action().go(SYS_SEC_GRP_IN_TABLE_ID); out.build(el); } @@ -774,6 +798,30 @@ void AccessFlowManager::handleSecGrpUpdate(const opflex::modb::URI& uri) { secGroupSetUpdated(secGrpSet); } +bool AccessFlowManager::checkIfSystemSecurityGroup(const string& uri){ + const string& opflex_domain = agent.getPolicyManager().getOpflexDomain(); + std::vector parts; + std::string domain_name; + + std::string systemSgName = "_SystemSecurityGroup"; + + split(parts, opflex_domain, boost::is_any_of("/")); + if (parts.size() == VMM_DOMAIN_DN_PARTS){ + const string& ctrlr = parts[2]; + std::vector ctrlr_parts; + split(ctrlr_parts, ctrlr, boost::is_any_of("-")); + if (ctrlr_parts.size() == 3){ + domain_name = ctrlr_parts[2]; + // eg: SG010197146194_SystemSecurityGroup + systemSgName = domain_name + "_SystemSecurityGroup"; + } + } + if (uri.find(systemSgName) != std::string::npos){ + return true; + } + return false; +} + void AccessFlowManager::handleSecGrpSetUpdate(const uri_set_t& secGrps, const string& secGrpsIdStr) { using modelgbp::gbpe::L24Classifier; @@ -792,6 +840,8 @@ void AccessFlowManager::handleSecGrpSetUpdate(const uri_set_t& secGrps, if (agent.getEndpointManager().secGrpSetEmpty(secGrps)) { switchManager.clearFlows(secGrpsIdStr, SEC_GROUP_IN_TABLE_ID); switchManager.clearFlows(secGrpsIdStr, SEC_GROUP_OUT_TABLE_ID); + switchManager.clearFlows(secGrpsIdStr, SYS_SEC_GRP_IN_TABLE_ID); + switchManager.clearFlows(secGrpsIdStr, SYS_SEC_GRP_OUT_TABLE_ID); return; } @@ -799,12 +849,46 @@ void AccessFlowManager::handleSecGrpSetUpdate(const uri_set_t& secGrps, FlowEntryList secGrpIn; FlowEntryList secGrpOut; + FlowEntryList sysSecGrpIn; + FlowEntryList sysSecGrpOut; + + bool any_system_sec_rule_configured = false; for (const opflex::modb::URI& secGrp : secGrps) { PolicyManager::rule_list_t rules; agent.getPolicyManager().getSecGroupRules(secGrp, rules); + bool isSystemRule = false; + int ingress_table = SEC_GROUP_IN_TABLE_ID; + int egress_table = SEC_GROUP_OUT_TABLE_ID; + int after_ingress_table = TAP_TABLE_ID; + int after_egress_table = TAP_TABLE_ID; + + FlowEntryList *secGrpInRef = &secGrpIn; + FlowEntryList *secGrpOutRef = &secGrpOut; + + bool system_sec_group = false; + std::string uri (secGrp.toString()); + + if (checkIfSystemSecurityGroup(secGrp.toString())){ + system_sec_group = true; + + ingress_table = SYS_SEC_GRP_IN_TABLE_ID; + egress_table = SYS_SEC_GRP_OUT_TABLE_ID; + + after_ingress_table = SEC_GROUP_IN_TABLE_ID; + after_egress_table = SEC_GROUP_OUT_TABLE_ID; + + secGrpInRef = &sysSecGrpIn; + secGrpOutRef = &sysSecGrpOut; + } + for (shared_ptr& pc : rules) { + if (system_sec_group){ + any_system_sec_rule_configured = true; + isSystemRule = true; + } + uint8_t dir = pc->getDirection(); bool skipL34 = false; const shared_ptr& cls = pc->getL24Classifier(); @@ -821,10 +905,10 @@ void AccessFlowManager::handleSecGrpSetUpdate(const uri_set_t& secGrps, LOG(DEBUG) << "skipL34 flows: " << skipL34 << " for rule: " << ruleURI; } - + bool log = false; flowutils::ClassAction act = flowutils::CA_DENY; - + if (pc->getAllow()) { if (cls->getConnectionTracking(ConnTrackEnumT::CONST_NORMAL) == ConnTrackEnumT::CONST_REFLEXIVE) { @@ -847,44 +931,49 @@ void AccessFlowManager::handleSecGrpSetUpdate(const uri_set_t& secGrps, dir == DirectionEnumT::CONST_IN) { if (act == flowutils::CA_DENY) { flowutils::add_l2classifier_entries(*cls, act, log, - EXP_DROP_TABLE_ID, SEC_GROUP_IN_TABLE_ID, + EXP_DROP_TABLE_ID, ingress_table, EXP_DROP_TABLE_ID, pc->getPriority(), OFPUTIL_FF_SEND_FLOW_REM, secGrpCookie, secGrpSetId, 0, - secGrpIn); - } else { + isSystemRule, + *secGrpInRef); + } else { flowutils::add_l2classifier_entries(*cls, act, log, - TAP_TABLE_ID, SEC_GROUP_IN_TABLE_ID, + after_ingress_table, ingress_table, EXP_DROP_TABLE_ID, pc->getPriority(), OFPUTIL_FF_SEND_FLOW_REM, secGrpCookie, secGrpSetId, 0, - secGrpIn); + isSystemRule, + *secGrpInRef); } } if (dir == DirectionEnumT::CONST_BIDIRECTIONAL || dir == DirectionEnumT::CONST_OUT) { if (act == flowutils::CA_DENY) { flowutils::add_l2classifier_entries(*cls, act, log, - EXP_DROP_TABLE_ID, SEC_GROUP_OUT_TABLE_ID, + EXP_DROP_TABLE_ID, egress_table, EXP_DROP_TABLE_ID, pc->getPriority(), OFPUTIL_FF_SEND_FLOW_REM, secGrpCookie, secGrpSetId, 0, - secGrpOut); + isSystemRule, + *secGrpOutRef); } else { flowutils::add_l2classifier_entries(*cls, act, log, - TAP_TABLE_ID, SEC_GROUP_OUT_TABLE_ID, + after_egress_table, egress_table, EXP_DROP_TABLE_ID, pc->getPriority(), OFPUTIL_FF_SEND_FLOW_REM, secGrpCookie, - secGrpSetId, 0, secGrpOut); - } + secGrpSetId, 0, + isSystemRule, + *secGrpOutRef); + } } continue; } @@ -896,83 +985,90 @@ void AccessFlowManager::handleSecGrpSetUpdate(const uri_set_t& secGrps, remoteSubs, boost::none, boost::none, - EXP_DROP_TABLE_ID, SEC_GROUP_IN_TABLE_ID, + EXP_DROP_TABLE_ID, ingress_table, EXP_DROP_TABLE_ID, pc->getPriority(), OFPUTIL_FF_SEND_FLOW_REM, secGrpCookie, secGrpSetId, 0, - secGrpIn); + isSystemRule, + *secGrpInRef); } else { flowutils::add_classifier_entries(*cls, act, log, remoteSubs, boost::none, boost::none, - TAP_TABLE_ID, SEC_GROUP_IN_TABLE_ID, + after_ingress_table, ingress_table, EXP_DROP_TABLE_ID, pc->getPriority(), OFPUTIL_FF_SEND_FLOW_REM, secGrpCookie, secGrpSetId, 0, - secGrpIn); + isSystemRule, + *secGrpInRef); } if (act == CA_REFLEX_FWD) { flowutils::add_classifier_entries(*cls, CA_REFLEX_FWD_TRACK, log, remoteSubs, boost::none, boost::none, - GROUP_MAP_TABLE_ID, SEC_GROUP_IN_TABLE_ID, + GROUP_MAP_TABLE_ID, ingress_table, EXP_DROP_TABLE_ID, pc->getPriority(), OFPUTIL_FF_SEND_FLOW_REM, secGrpCookie, secGrpSetId, 0, - secGrpIn); + isSystemRule, + *secGrpInRef); flowutils::add_classifier_entries(*cls, CA_REFLEX_FWD_EST, log, remoteSubs, boost::none, boost::none, - TAP_TABLE_ID, SEC_GROUP_IN_TABLE_ID, + after_ingress_table, ingress_table, EXP_DROP_TABLE_ID, pc->getPriority(), OFPUTIL_FF_SEND_FLOW_REM, secGrpCookie, secGrpSetId, 0, - secGrpIn); + isSystemRule, + *secGrpInRef); // add reverse entries for reflexive classifier flowutils::add_classifier_entries(*cls, CA_REFLEX_REV_TRACK, log, boost::none, remoteSubs, namedSvcPorts, - GROUP_MAP_TABLE_ID, SEC_GROUP_OUT_TABLE_ID, + GROUP_MAP_TABLE_ID, egress_table, EXP_DROP_TABLE_ID, pc->getPriority(), OFPUTIL_FF_SEND_FLOW_REM, 0, secGrpSetId, 0, - secGrpOut); + isSystemRule, + *secGrpOutRef); flowutils::add_classifier_entries(*cls, CA_REFLEX_REV_ALLOW, log, boost::none, remoteSubs, namedSvcPorts, - TAP_TABLE_ID, SEC_GROUP_OUT_TABLE_ID, + after_egress_table, egress_table, EXP_DROP_TABLE_ID, pc->getPriority(), OFPUTIL_FF_SEND_FLOW_REM, secGrpCookie, secGrpSetId, 0, - secGrpOut); + isSystemRule, + *secGrpOutRef); flowutils::add_classifier_entries(*cls, CA_REFLEX_REV_RELATED, log, boost::none, remoteSubs, namedSvcPorts, - TAP_TABLE_ID, SEC_GROUP_OUT_TABLE_ID, + after_egress_table, egress_table, EXP_DROP_TABLE_ID, pc->getPriority(), OFPUTIL_FF_SEND_FLOW_REM, secGrpCookie, secGrpSetId, 0, - secGrpOut); + isSystemRule, + *secGrpOutRef); } } if (dir == DirectionEnumT::CONST_BIDIRECTIONAL || @@ -982,83 +1078,90 @@ void AccessFlowManager::handleSecGrpSetUpdate(const uri_set_t& secGrps, boost::none, remoteSubs, namedSvcPorts, - EXP_DROP_TABLE_ID, SEC_GROUP_OUT_TABLE_ID, + EXP_DROP_TABLE_ID, egress_table, EXP_DROP_TABLE_ID, pc->getPriority(), OFPUTIL_FF_SEND_FLOW_REM, secGrpCookie, secGrpSetId, 0, - secGrpOut); + isSystemRule, + *secGrpOutRef); } else { flowutils::add_classifier_entries(*cls, act, log, boost::none, remoteSubs, namedSvcPorts, - TAP_TABLE_ID, SEC_GROUP_OUT_TABLE_ID, + after_egress_table, egress_table, EXP_DROP_TABLE_ID, pc->getPriority(), OFPUTIL_FF_SEND_FLOW_REM, secGrpCookie, secGrpSetId, 0, - secGrpOut); + isSystemRule, + *secGrpOutRef); } if (act == CA_REFLEX_FWD) { flowutils::add_classifier_entries(*cls, CA_REFLEX_FWD_TRACK, log, boost::none, remoteSubs, namedSvcPorts, - GROUP_MAP_TABLE_ID, SEC_GROUP_OUT_TABLE_ID, + GROUP_MAP_TABLE_ID, egress_table, EXP_DROP_TABLE_ID, pc->getPriority(), OFPUTIL_FF_SEND_FLOW_REM, secGrpCookie, secGrpSetId, 0, - secGrpOut); + isSystemRule, + *secGrpOutRef); flowutils::add_classifier_entries(*cls, CA_REFLEX_FWD_EST, log, boost::none, remoteSubs, namedSvcPorts, - TAP_TABLE_ID, SEC_GROUP_OUT_TABLE_ID, + after_egress_table, egress_table, EXP_DROP_TABLE_ID, pc->getPriority(), OFPUTIL_FF_SEND_FLOW_REM, secGrpCookie, secGrpSetId, 0, - secGrpOut); + isSystemRule, + *secGrpOutRef); // add reverse entries for reflexive classifier flowutils::add_classifier_entries(*cls, CA_REFLEX_REV_TRACK, log, remoteSubs, boost::none, boost::none, - GROUP_MAP_TABLE_ID, SEC_GROUP_IN_TABLE_ID, + GROUP_MAP_TABLE_ID, ingress_table, EXP_DROP_TABLE_ID, pc->getPriority(), OFPUTIL_FF_SEND_FLOW_REM, 0, secGrpSetId, 0, - secGrpIn); + isSystemRule, + *secGrpInRef); flowutils::add_classifier_entries(*cls, CA_REFLEX_REV_ALLOW, log, remoteSubs, boost::none, boost::none, - TAP_TABLE_ID, SEC_GROUP_IN_TABLE_ID, + after_ingress_table, ingress_table, EXP_DROP_TABLE_ID, pc->getPriority(), OFPUTIL_FF_SEND_FLOW_REM, secGrpCookie, secGrpSetId, 0, - secGrpIn); + isSystemRule, + *secGrpInRef); flowutils::add_classifier_entries(*cls, CA_REFLEX_REV_RELATED, log, remoteSubs, boost::none, boost::none, - TAP_TABLE_ID, SEC_GROUP_IN_TABLE_ID, + after_ingress_table, ingress_table, EXP_DROP_TABLE_ID, pc->getPriority(), OFPUTIL_FF_SEND_FLOW_REM, secGrpCookie, secGrpSetId, 0, - secGrpIn); + isSystemRule, + *secGrpInRef); } } } @@ -1066,6 +1169,44 @@ void AccessFlowManager::handleSecGrpSetUpdate(const uri_set_t& secGrps, switchManager.writeFlow(secGrpsIdStr, SEC_GROUP_IN_TABLE_ID, secGrpIn); switchManager.writeFlow(secGrpsIdStr, SEC_GROUP_OUT_TABLE_ID, secGrpOut); + + if (any_system_sec_rule_configured){ + /* + * Configure drop flows to drop packets not matching any system + * security group rules. + * */ + FlowEntryList dropLogFlowIn; + FlowBuilder().priority(2).cookie(flow::cookie::TABLE_DROP_FLOW) + .flags(OFPUTIL_FF_SEND_FLOW_REM) + .action().dropLog(SYS_SEC_GRP_IN_TABLE_ID) + .go(EXP_DROP_TABLE_ID) + .parent().build(dropLogFlowIn); + switchManager.writeFlow("SystemDropLogFlow", SYS_SEC_GRP_IN_TABLE_ID, dropLogFlowIn); + + FlowEntryList dropLogFlowOut; + FlowBuilder().priority(2).cookie(flow::cookie::TABLE_DROP_FLOW) + .flags(OFPUTIL_FF_SEND_FLOW_REM) + .action().dropLog(SYS_SEC_GRP_OUT_TABLE_ID) + .go(EXP_DROP_TABLE_ID) + .parent().build(dropLogFlowOut); + switchManager.writeFlow("SystemDropLogFlow", SYS_SEC_GRP_OUT_TABLE_ID, dropLogFlowOut); + + /* + * Configure system security group rules. + * */ + switchManager.writeFlow(secGrpsIdStr, SYS_SEC_GRP_IN_TABLE_ID, sysSecGrpIn); + switchManager.writeFlow(secGrpsIdStr, SYS_SEC_GRP_OUT_TABLE_ID, sysSecGrpOut); + } else{ + + /* Delete all flows in System security group tables except static flows. + * Static flows will simply forward packets to usual security group tables. + * */ + switchManager.clearFlows(secGrpsIdStr, SYS_SEC_GRP_IN_TABLE_ID); + switchManager.clearFlows(secGrpsIdStr, SYS_SEC_GRP_OUT_TABLE_ID); + + switchManager.clearFlows("SystemDropLogFlow", SYS_SEC_GRP_IN_TABLE_ID); + switchManager.clearFlows("SystemDropLogFlow", SYS_SEC_GRP_OUT_TABLE_ID); + } } void AccessFlowManager::lbIfaceUpdated(const std::string& uuid) { diff --git a/agent-ovs/ovs/FlowUtils.cpp b/agent-ovs/ovs/FlowUtils.cpp index 61a8e182f..5880cd751 100644 --- a/agent-ovs/ovs/FlowUtils.cpp +++ b/agent-ovs/ovs/FlowUtils.cpp @@ -168,13 +168,17 @@ void add_l2classifier_entries(L24Classifier& clsfr, ClassAction act, bool log, uint16_t priority, uint32_t flags, uint64_t cookie, uint32_t svnid, uint32_t dvnid, + bool isSystemRule, /* out */ FlowEntryList& entries) { if (clsfr.isProtSet()) return; ovs_be64 ckbe = ovs_htonll(cookie); + if (isSystemRule){ + svnid = 0; + dvnid = 0; + } FlowBuilder f; - f.cookie(ckbe) .flags(flags); flowutils::match_group(f, priority, svnid, dvnid); @@ -203,12 +207,18 @@ void add_classifier_entries(L24Classifier& clsfr, ClassAction act, bool log, uint16_t priority, uint32_t flags, uint64_t cookie, uint32_t svnid, uint32_t dvnid, + bool isSystemRule, /* out */ FlowEntryList& entries) { using modelgbp::l2::EtherTypeEnumT; using modelgbp::l4::TcpFlagsEnumT; ovs_be64 ckbe = ovs_htonll(cookie); MaskList srcPorts; MaskList dstPorts; + + if (isSystemRule){ + svnid = 0; + dvnid = 0; + } if (clsfr.getProt(0) == 1 && (clsfr.isIcmpTypeSet() || clsfr.isIcmpCodeSet())) { if (clsfr.isIcmpTypeSet()) { @@ -287,6 +297,7 @@ void add_classifier_entries(L24Classifier& clsfr, ClassAction act, bool log, for (const Mask& dm : dstPorts) { for (uint32_t flagMask : tcpFlagsVec) { FlowBuilder f; + f.cookie(ckbe); f.flags(flags); @@ -320,7 +331,7 @@ void add_classifier_entries(L24Classifier& clsfr, ClassAction act, bool log, f.action().dropLog(currentTable,ActionBuilder::CaptureReason::POLICY_DENY,cookie).go(nextTable); } else { - f.action().metadata(0, flow::meta::DROP_LOG).go(nextTable); + f.action().metadata(0, flow::meta::DROP_LOG).go(nextTable); } break; case flowutils::CA_ALLOW: @@ -354,11 +365,13 @@ void add_classifier_entries(L24Classifier& clsfr, ClassAction act, bool log, FlowBuilder::CT_NEW, FlowBuilder::CT_TRACKED | FlowBuilder::CT_NEW); - f.action().conntrack(ActionBuilder::CT_COMMIT, - MFF_REG6); - if(log) { - f.action().permitLog(currentTable, dropTable, cookie); - } + if (!isSystemRule) { + f.action().conntrack(ActionBuilder::CT_COMMIT, + MFF_REG6); + if(log) { + f.action().permitLog(currentTable, dropTable, cookie); + } + } f.action().go(nextTable); break; case CA_REFLEX_FWD_EST: diff --git a/agent-ovs/ovs/IntFlowManager.cpp b/agent-ovs/ovs/IntFlowManager.cpp index 4a91807f0..7dd0c4116 100644 --- a/agent-ovs/ovs/IntFlowManager.cpp +++ b/agent-ovs/ovs/IntFlowManager.cpp @@ -5938,6 +5938,7 @@ void IntFlowManager::addContractRules(FlowEntryList& entryList, OFPUTIL_FF_SEND_FLOW_REM, cookie, cvnid, pvnid, + false, entryList); } else { flowutils::add_classifier_entries(*cls, act, log, @@ -5950,6 +5951,7 @@ void IntFlowManager::addContractRules(FlowEntryList& entryList, OFPUTIL_FF_SEND_FLOW_REM, cookie, cvnid, pvnid, + false, entryList); } } @@ -5966,6 +5968,7 @@ void IntFlowManager::addContractRules(FlowEntryList& entryList, OFPUTIL_FF_SEND_FLOW_REM, cookie, pvnid, cvnid, + false, entryList); } else { flowutils::add_classifier_entries(*cls, act, log, @@ -5978,6 +5981,7 @@ void IntFlowManager::addContractRules(FlowEntryList& entryList, OFPUTIL_FF_SEND_FLOW_REM, cookie, pvnid, cvnid, + false, entryList); } } diff --git a/agent-ovs/ovs/include/AccessFlowManager.h b/agent-ovs/ovs/include/AccessFlowManager.h index 6c0732c48..c03378e75 100644 --- a/agent-ovs/ovs/include/AccessFlowManager.h +++ b/agent-ovs/ovs/include/AccessFlowManager.h @@ -139,11 +139,21 @@ class AccessFlowManager : public EndpointListener, * port after applying policy */ GROUP_MAP_TABLE_ID, + /** + * Enforece system security group policy on packets coming into + * the endpoint from switch. + */ + SYS_SEC_GRP_IN_TABLE_ID, /** * Enforce security group policy on packets coming in to the * endpoint from the switch */ SEC_GROUP_IN_TABLE_ID, + /** + * Enforce system security group policy on packets coming out of + * the endpoints to the switch. + */ + SYS_SEC_GRP_OUT_TABLE_ID, /** * Enforce security group policy on packets coming out from * the endpoint to the switch @@ -177,7 +187,8 @@ class AccessFlowManager : public EndpointListener, void handleSecGrpSetUpdate(const EndpointListener::uri_set_t& secGrps, const std::string& secGrpsId); void handleDscpQosUpdate(const string& interface, uint8_t dscp); - + bool checkIfSystemSecurityGroup(const string& uri); + Agent& agent; SwitchManager& switchManager; IdGenerator& idGen; diff --git a/agent-ovs/ovs/include/FlowUtils.h b/agent-ovs/ovs/include/FlowUtils.h index 4a0b996bb..73963ede3 100644 --- a/agent-ovs/ovs/include/FlowUtils.h +++ b/agent-ovs/ovs/include/FlowUtils.h @@ -121,6 +121,7 @@ void add_classifier_entries(modelgbp::gbpe::L24Classifier& clsfr, uint16_t priority, uint32_t flags, uint64_t cookie, uint32_t svnid, uint32_t dvnid, + bool isSystemRule, /* out */ FlowEntryList& entries); /** @@ -145,6 +146,7 @@ void add_l2classifier_entries(modelgbp::gbpe::L24Classifier& clsfr, uint16_t priority, uint32_t flags, uint64_t cookie, uint32_t svnid, uint32_t dvnid, + bool isSystemRule, /* out */ FlowEntryList& entries); /** * Add a match entry for the DHCP v4 and v6 request diff --git a/agent-ovs/ovs/test/AccessFlowManager_test.cpp b/agent-ovs/ovs/test/AccessFlowManager_test.cpp index 8d605abe3..5e3905b52 100644 --- a/agent-ovs/ovs/test/AccessFlowManager_test.cpp +++ b/agent-ovs/ovs/test/AccessFlowManager_test.cpp @@ -68,6 +68,9 @@ class AccessFlowManagerFixture : public FlowManagerFixture { void initExpSecGrp5(std::vector>& namedAddressSet); void initExpSecGrp6(); + /** Initialize system security group flow entries */ + void initExpSysSecGrpSet1(); + /** Initialize dscp flow entries */ void addDscpFlows(shared_ptr& ep); @@ -76,6 +79,8 @@ class AccessFlowManagerFixture : public FlowManagerFixture { shared_ptr secGrp1; shared_ptr secGrp2; shared_ptr secGrp3; + shared_ptr sysSecGrp1; + shared_ptr classifier100,classifier101; shared_ptr pSpace; @@ -235,7 +240,7 @@ BOOST_FIXTURE_TEST_CASE(learningBridge, AccessFlowManagerFixture) { #define ADDF(flow) addExpFlowEntry(expTables, flow) enum TABLE { - DROP_LOG=0, SVC_BYPASS = 1, GRP = 2, IN_POL = 3, OUT_POL = 4, TAP=5, OUT = 6, EXP_DROP=7 + DROP_LOG=0, SVC_BYPASS = 1, GRP = 2, SYS_IN_POL = 3, IN_POL = 4, SYS_OUT_POL = 5, OUT_POL = 6, TAP=7, OUT = 8, EXP_DROP=9 }; enum CaptureReason { @@ -397,6 +402,58 @@ BOOST_FIXTURE_TEST_CASE(secGrp, AccessFlowManagerFixture) { WAIT_FOR_TABLES("remote-addsubnets", 500); } +BOOST_FIXTURE_TEST_CASE(syssecgrp, AccessFlowManagerFixture) { + createObjects(); + createPolicyObjects(); + shared_ptr rs; + { + Mutator mutator(framework, "policyreg"); + rs = space->addGbpSubnets("subnets_rule0"); + + rs->addGbpSubnet("subnets_rule0_1") + ->setAddress("0.0.0.0") + .setPrefixLen(0); + rs->addGbpSubnet("subnets_rule0_2") + ->setAddress("0::") + .setPrefixLen(0); + + shared_ptr r1, r2, r3, r4, r5 ; + sysSecGrp1 = space->addGbpSecGroup("ostack_SystemSecurityGroup"); + + r1 = sysSecGrp1->addGbpSecGroupSubject("2_subject1") + ->addGbpSecGroupRule("2_1_rule1"); + r1->addGbpRuleToClassifierRSrc(classifier0->getURI().toString()); + r1->addGbpSecGroupRuleToRemoteAddressRSrc(rs->getURI().toString()); + + r2 = sysSecGrp1->addGbpSecGroupSubject("2_subject1") + ->addGbpSecGroupRule("2_1_rule2"); + r2->setDirection(DirectionEnumT::CONST_BIDIRECTIONAL).setOrder(20) + .addGbpRuleToClassifierRSrc(classifier5->getURI().toString()); + + r3 = sysSecGrp1->addGbpSecGroupSubject("2_subject1") + ->addGbpSecGroupRule("2_1_rule3"); + r3->setDirection(DirectionEnumT::CONST_OUT).setOrder(30) + .addGbpRuleToClassifierRSrc(classifier9->getURI().toString()); + r3->addGbpSecGroupRuleToRemoteAddressRSrc(rs->getURI().toString()); + mutator.commit(); + + } + + ep0.reset(new Endpoint("0-0-0-0")); + epSrc.updateEndpoint(*ep0); + + initExpStatic(); + WAIT_FOR_TABLES("empty-secgrp", 500); + + ep0->addSecurityGroup(sysSecGrp1->getURI()); + epSrc.updateEndpoint(*ep0); + + clearExpFlowTables(); + initExpStatic(); + initExpSysSecGrpSet1(); + WAIT_FOR_TABLES("syssecgrp", 500); +} + BOOST_FIXTURE_TEST_CASE(denyrule, AccessFlowManagerFixture) { createObjects(); createPolicyObjects(); @@ -676,6 +733,8 @@ void AccessFlowManagerFixture::initExpStatic() { .actions().go(SVC_BYPASS).done()); ADDF(Bldr().table(SVC_BYPASS).priority(1) .actions().go(GRP).done()); + ADDF(Bldr().table(SYS_IN_POL).priority(1).actions().go(IN_POL).done()); + ADDF(Bldr().table(SYS_OUT_POL).priority(1).actions().go(OUT_POL).done()); for(int i=SVC_BYPASS; i<=OUT; i++) { ADDF(Bldr().table(i).priority(0) .cookie(ovs_ntohll(opflexagent::flow::cookie::TABLE_DROP_FLOW)) @@ -755,7 +814,7 @@ void AccessFlowManagerFixture::initExpEp(shared_ptr& ep) { .meta((opflexagent::flow::meta::access_out::POP_VLAN| opflexagent::flow::meta::access_meta::EGRESS_DIR), opflexagent::flow::meta::ACCESS_MASK) - .go(OUT_POL).done()); + .go(SYS_OUT_POL).done()); if (ep->isAccessAllowUntagged()) { ADDF(Bldr().table(GRP).priority(99).in(access) .isVlanTci("0x0000/0x1fff") @@ -764,7 +823,7 @@ void AccessFlowManagerFixture::initExpEp(shared_ptr& ep) { .load(OUTPORT, uplink) .meta(opflexagent::flow::meta::access_meta::EGRESS_DIR, opflexagent::flow::meta::access_meta::MASK) - .go(OUT_POL).done()); + .go(SYS_OUT_POL).done()); } ADDF(Bldr().table(GRP).priority(100).in(uplink) .actions().load(RD, zoneId).load(SEPG, 1).load(OUTPORT, access) @@ -772,7 +831,7 @@ void AccessFlowManagerFixture::initExpEp(shared_ptr& ep) { .meta((opflexagent::flow::meta::access_out::PUSH_VLAN| opflexagent::flow::meta::access_meta::INGRESS_DIR), opflexagent::flow::meta::ACCESS_MASK) - .go(IN_POL).done()); + .go(SYS_IN_POL).done()); } else { ADDF(Bldr().table(GRP).priority(100).in(access) .noVlan() @@ -780,13 +839,13 @@ void AccessFlowManagerFixture::initExpEp(shared_ptr& ep) { .load(OUTPORT, uplink) .meta(opflexagent::flow::meta::access_meta::EGRESS_DIR, opflexagent::flow::meta::access_meta::MASK) - .go(OUT_POL).done()); + .go(SYS_OUT_POL).done()); ADDF(Bldr().table(GRP).priority(100).in(uplink) .actions().load(RD, zoneId).load(SEPG, 1) .load(OUTPORT, access) .meta(opflexagent::flow::meta::access_meta::INGRESS_DIR, opflexagent::flow::meta::access_meta::MASK) - .go(IN_POL).done()); + .go(SYS_IN_POL).done()); } } @@ -815,6 +874,57 @@ void AccessFlowManagerFixture::initExpSecGrpSet12(bool second, initExpSecGrp2(setId); } +void AccessFlowManagerFixture::initExpSysSecGrpSet1(){ + uint16_t prio = PolicyManager::MAX_POLICY_RULE_PRIORITY; + PolicyManager::rule_list_t rules; + agent.getPolicyManager().getSecGroupRules(sysSecGrp1->getURI(), rules); + uint32_t ruleId; + + ADDF(Bldr().table(SYS_IN_POL).cookie(ovs_ntohll(opflexagent::flow::cookie::TABLE_DROP_FLOW)) + .flags(OFPUTIL_FF_SEND_FLOW_REM).priority(2) + .actions().dropLog(SYS_IN_POL).go(EXP_DROP).done()); + + ADDF(Bldr().table(SYS_OUT_POL).cookie(ovs_ntohll(opflexagent::flow::cookie::TABLE_DROP_FLOW)) + .flags(OFPUTIL_FF_SEND_FLOW_REM).priority(2) + .actions().dropLog(SYS_OUT_POL).go(EXP_DROP).done()); + + /* classifier 5 */ + ruleId = idGen.getId("l24classifierRule", + classifier5->getURI().toString()); + ADDF(Bldr(SEND_FLOW_REM).table(SYS_IN_POL).priority(prio).cookie(ruleId) + .isEth(0x8906).actions().go(IN_POL).done()); + ADDF(Bldr(SEND_FLOW_REM).table(SYS_OUT_POL).priority(prio).cookie(ruleId) + .isEth(0x8906).actions().go(OUT_POL).done()); + + /* classifier 9 */ + ruleId = idGen.getId("l24classifierRule", + classifier9->getURI().toString()); + ADDF(Bldr(SEND_FLOW_REM).table(SYS_IN_POL).priority(prio - 128).cookie(ruleId) + .isCtState("-new+est-rel+rpl-inv+trk").tcp() + .actions().go(IN_POL).done()); + ADDF(Bldr(SEND_FLOW_REM).table(SYS_IN_POL).priority(prio - 128).cookie(ruleId) + .isCtState("-new-est+rel+rpl-inv+trk").ip() + .actions().go(IN_POL).done()); + ADDF(Bldr(SEND_FLOW_REM).table(SYS_IN_POL).priority(prio - 128) + .isCtState("-trk").tcp() + .actions().ct("table=2,zone=NXM_NX_REG6[0..15]").done()); + ADDF(Bldr(SEND_FLOW_REM).table(SYS_OUT_POL).priority(prio - 128).cookie(ruleId) + .isCtState("-trk") + .tcp().isTpDst(22) + .actions().ct("table=2,zone=NXM_NX_REG6[0..15]").done()); + ADDF(Bldr(SEND_FLOW_REM).table(SYS_OUT_POL).priority(prio - 128).cookie(ruleId) + .isCtState("+est+trk") + .tcp().isTpDst(22) + .actions() + .go(OUT_POL).done()); + ADDF(Bldr(SEND_FLOW_REM).table(SYS_OUT_POL).priority(prio - 128).cookie(ruleId) + .isCtState("+new+trk") + .tcp().isTpDst(22) + .actions() + .go(OUT_POL).done()); + +} + uint16_t AccessFlowManagerFixture::initExpSecGrp1(uint32_t setId, int remoteAddress) { uint16_t prio = PolicyManager::MAX_POLICY_RULE_PRIORITY; @@ -886,6 +996,7 @@ uint16_t AccessFlowManagerFixture::initExpSecGrp1(uint32_t setId, return 512; } + uint16_t AccessFlowManagerFixture::initExpSecGrp2(uint32_t setId) { uint16_t prio = PolicyManager::MAX_POLICY_RULE_PRIORITY; PolicyManager::rule_list_t rules; @@ -1010,6 +1121,5 @@ void AccessFlowManagerFixture::initExpSecGrp6() { ADDF(Bldr(SEND_FLOW_REM).table(OUT_POL).priority(prio).cookie(ruleId) .tcp().reg(SEPG, setId).isIpDst("10.0.0.0/16").isTpDst(80).actions() .permitLog(OUT_POL,EXP_DROP,ruleId).go(TAP).done()); - } BOOST_AUTO_TEST_SUITE_END() diff --git a/agent-ovs/ovs/test/TableDropStatsManager_test.cpp b/agent-ovs/ovs/test/TableDropStatsManager_test.cpp index 1167d00b8..6fa7523e8 100644 --- a/agent-ovs/ovs/test/TableDropStatsManager_test.cpp +++ b/agent-ovs/ovs/test/TableDropStatsManager_test.cpp @@ -290,6 +290,7 @@ void TableDropStatsManagerFixture::testOneStaticDropFlow ( { uint64_t expected_pkt_count = INITIAL_PACKET_COUNT, expected_byte_count = INITIAL_PACKET_COUNT * PACKET_SIZE; + int ctr = 1; FlowEntryList dropLogFlows; if(portConn.getSwitchName()=="int_conn") { createIntBridgeDropFlowList(table_id, @@ -299,10 +300,10 @@ void TableDropStatsManagerFixture::testOneStaticDropFlow ( expected_byte_count *=4; } } else { + ctr = 2; createAccBridgeDropFlowList(table_id, dropLogFlows); } - int ctr = 1; if(refresh_aged_flow) { ctr++; }