+ /**
+ * Programs the port specific fixed rules.
+ *
+ * @param dpId the dp id
+ * @param allowedAddresses the allowed addresses
+ * @param lportTag the lport tag
+ * @param portId the portId
+ * @param action the action
+ * @param write whether to add or remove the flow.
+ */
+ protected void programAclPortSpecificFixedRules(BigInteger dpId, List<AllowedAddressPairs> allowedAddresses,
+ int lportTag, String portId, Action action, int write) {
+ programGotoClassifierTableRules(dpId, allowedAddresses, lportTag, write);
+ if (action == Action.ADD || action == Action.REMOVE) {
+ programConntrackRecircRules(dpId, allowedAddresses, lportTag, portId, write);
+ programPortSpecificDropRules(dpId, lportTag, write);
+ programAclCommitRules(dpId, lportTag, portId, write);
+ }
+ LOG.info("programAclPortSpecificFixedRules: flows for dpId={}, lportId={}, action={}, write={}", dpId, lportTag,
+ action, write);
+ }
+
+ protected abstract void programGotoClassifierTableRules(BigInteger dpId, List<AllowedAddressPairs> aaps,
+ int lportTag, int addOrRemove);
+
+ /**
+ * Adds the rule to send the packet to the netfilter to check whether it is a known packet.
+ *
+ * @param dpId the dpId
+ * @param aaps the allowed address pairs
+ * @param lportTag the lport tag
+ * @param portId the portId
+ * @param addOrRemove whether to add or remove the flow
+ */
+ protected void programConntrackRecircRules(BigInteger dpId, List<AllowedAddressPairs> aaps, int lportTag,
+ String portId, int addOrRemove) {
+ if (AclServiceUtils.doesIpv4AddressExists(aaps)) {
+ programConntrackRecircRule(dpId, lportTag, portId, MatchEthernetType.IPV4, addOrRemove);
+ }
+ if (AclServiceUtils.doesIpv6AddressExists(aaps)) {
+ programConntrackRecircRule(dpId, lportTag, portId, MatchEthernetType.IPV6, addOrRemove);
+ }
+ }
+
+ protected void programConntrackRecircRule(BigInteger dpId, int lportTag, String portId,
+ MatchEthernetType matchEtherType, int addOrRemove) {
+ List<MatchInfoBase> matches = new ArrayList<>();
+ matches.add(matchEtherType);
+ matches.add(AclServiceUtils.buildLPortTagMatch(lportTag, serviceMode));
+
+ List<InstructionInfo> instructions = new ArrayList<>();
+ if (addOrRemove == NwConstants.ADD_FLOW) {
+ Long elanTag = getElanIdFromAclInterface(portId);
+ if (elanTag == null) {
+ LOG.error("ElanId not found for portId={}; Context: dpId={}, lportTag={}, addOrRemove={},", portId,
+ dpId, lportTag, addOrRemove);
+ return;
+ }
+ List<ActionInfo> actionsInfos = new ArrayList<>();
+ actionsInfos.add(new ActionNxConntrack(2, 0, 0, elanTag.intValue(), getAclForExistingTrafficTable()));
+ instructions.add(new InstructionApplyActions(actionsInfos));
+ }
+
+ String flowName =
+ this.directionString + "_Fixed_Conntrk_" + dpId + "_" + lportTag + "_" + matchEtherType + "_Recirc";
+ syncFlow(dpId, getAclConntrackSenderTable(), flowName, AclConstants.ACL_DEFAULT_PRIORITY, "ACL", 0, 0,
+ AclConstants.COOKIE_ACL_BASE, matches, instructions, addOrRemove);
+ }
+
+ /**
+ * Adds the rules to drop the unknown/invalid packets .
+ *
+ * @param dpId the dpId
+ * @param lportTag the lport tag
+ * @param addOrRemove whether to add or remove the flow
+ */
+ protected void programPortSpecificDropRules(BigInteger dpId, int lportTag, int addOrRemove) {
+ LOG.debug("Programming Drop Rules: DpId={}, lportTag={}, addOrRemove={}", dpId, lportTag, addOrRemove);
+ programConntrackInvalidDropRule(dpId, lportTag, addOrRemove);
+ programAclRuleMissDropRule(dpId, lportTag, addOrRemove);
+ }
+
+ /**
+ * Adds the rule to drop the conntrack invalid packets .
+ *
+ * @param dpId the dpId
+ * @param lportTag the lport tag
+ * @param addOrRemove whether to add or remove the flow
+ */
+ protected void programConntrackInvalidDropRule(BigInteger dpId, int lportTag, int addOrRemove) {
+ List<MatchInfoBase> matches = AclServiceOFFlowBuilder.addLPortTagMatches(lportTag,
+ AclConstants.TRACKED_INV_CT_STATE, AclConstants.TRACKED_INV_CT_STATE_MASK, serviceMode);
+ List<InstructionInfo> instructions = AclServiceOFFlowBuilder.getDropInstructionInfo();
+
+ String flowId = this.directionString + "_Fixed_Conntrk_Drop" + dpId + "_" + lportTag + "_Tracked_Invalid";
+ syncFlow(dpId, getAclFilterCumDispatcherTable(), flowId, AclConstants.CT_STATE_TRACKED_INVALID_PRIORITY, "ACL",
+ 0, 0, AclConstants.COOKIE_ACL_DROP_FLOW, matches, instructions, addOrRemove);
+ }
+
+ /**
+ * Program ACL rule miss drop rule for a port.
+ *
+ * @param dpId the dp id
+ * @param lportTag the lport tag
+ * @param addOrRemove the add or remove
+ */
+ protected void programAclRuleMissDropRule(BigInteger dpId, int lportTag, int addOrRemove) {
+ List<MatchInfoBase> matches = new ArrayList<>();
+ matches.add(AclServiceUtils.buildLPortTagMatch(lportTag, serviceMode));
+ List<InstructionInfo> instructions = AclServiceOFFlowBuilder.getDropInstructionInfo();
+
+ String flowId = this.directionString + "_Fixed_Acl_Rule_Miss_Drop_" + dpId + "_" + lportTag;
+ syncFlow(dpId, getAclFilterCumDispatcherTable(), flowId, AclConstants.CT_STATE_TRACKED_NEW_DROP_PRIORITY, "ACL",
+ 0, 0, AclConstants.COOKIE_ACL_DROP_FLOW, matches, instructions, addOrRemove);
+ }
+
+ /**
+ * Program acl commit rules.
+ *
+ * @param dpId the dp id
+ * @param lportTag the lport tag
+ * @param portId the port id
+ * @param addOrRemove the add or remove
+ */
+ protected void programAclCommitRules(BigInteger dpId, int lportTag, String portId, int addOrRemove) {
+ programAclCommitRuleForConntrack(dpId, lportTag, portId, MatchEthernetType.IPV4, addOrRemove);
+ programAclCommitRuleForConntrack(dpId, lportTag, portId, MatchEthernetType.IPV6, addOrRemove);
+ programAclCommitRuleForNonConntrack(dpId, lportTag, addOrRemove);
+ }
+
+ /**
+ * Program acl commit rule for conntrack.
+ *
+ * @param dpId the dp id
+ * @param lportTag the lport tag
+ * @param portId the port id
+ * @param matchEtherType the match ether type
+ * @param addOrRemove the add or remove
+ */
+ protected void programAclCommitRuleForConntrack(BigInteger dpId, int lportTag, String portId,
+ MatchEthernetType matchEtherType, int addOrRemove) {
+ List<MatchInfoBase> matches = new ArrayList<>();
+ matches.add(matchEtherType);
+ matches.add(AclServiceUtils.buildLPortTagMatch(lportTag, serviceMode));
+ matches.add(
+ AclServiceUtils.buildAclConntrackClassifierTypeMatch(AclConntrackClassifierType.CONNTRACK_SUPPORTED));
+
+ List<ActionInfo> actionsInfos = new ArrayList<>();
+ if (addOrRemove == NwConstants.ADD_FLOW) {
+ Long elanId = getElanIdFromAclInterface(portId);
+ if (elanId == null) {
+ LOG.error("ElanId not found for portId={}; Context: dpId={}, lportTag={}, addOrRemove={}", portId, dpId,
+ lportTag, addOrRemove);
+ return;
+ }
+ List<NxCtAction> ctActionsList =
+ Lists.newArrayList(new ActionNxConntrack.NxCtMark(AclConstants.CT_MARK_EST_STATE));
+ actionsInfos.add(new ActionNxConntrack(2, 1, 0, elanId.intValue(), (short) 255, ctActionsList));
+ }
+ List<InstructionInfo> instructions = getDispatcherTableResubmitInstructions(actionsInfos);
+
+ String flowName = directionString + "_Acl_Commit_Conntrack_" + dpId + "_" + lportTag + "_" + matchEtherType;
+ // Flow for conntrack traffic to commit and resubmit to dispatcher
+ syncFlow(dpId, getAclCommitterTable(), flowName, AclConstants.ACL_DEFAULT_PRIORITY, "ACL", 0, 0,
+ AclConstants.COOKIE_ACL_BASE, matches, instructions, addOrRemove);
+ }
+
+ /**
+ * Program acl commit rule for non conntrack.
+ *
+ * @param dpId the dp id
+ * @param lportTag the lport tag
+ * @param addOrRemove the add or remove
+ */
+ protected void programAclCommitRuleForNonConntrack(BigInteger dpId, int lportTag, int addOrRemove) {
+ List<MatchInfoBase> matches = new ArrayList<>();
+ matches.add(AclServiceUtils.buildLPortTagMatch(lportTag, serviceMode));
+ matches.add(AclServiceUtils
+ .buildAclConntrackClassifierTypeMatch(AclConntrackClassifierType.NON_CONNTRACK_SUPPORTED));
+
+ List<InstructionInfo> instructions = getDispatcherTableResubmitInstructions();
+ String flowName = this.directionString + "_Acl_Commit_Non_Conntrack_" + dpId + "_" + lportTag;
+ // Flow for non-conntrack traffic to resubmit to dispatcher
+ syncFlow(dpId, getAclCommitterTable(), flowName, AclConstants.ACL_DEFAULT_PRIORITY, "ACL", 0, 0,
+ AclConstants.COOKIE_ACL_BASE, matches, instructions, addOrRemove);
+ }
+
+ protected Long getElanIdFromAclInterface(String elanInterfaceName) {
+ AclInterface aclInterface = aclInterfaceCache.get(elanInterfaceName);
+ if (null != aclInterface) {
+ return aclInterface.getElanId();