* @param dpId the dpId
* @param lportTag the lport tag
* @param addOrRemove whether to delete or add flow
+ * @return program succeeded
*/
protected abstract boolean programAclRules(List<Uuid> aclUuidList, BigInteger dpId, int lportTag, int addOrRemove,
String portId);
*/
package org.opendaylight.netvirt.aclservice;
-//import java.util.Map;
import org.opendaylight.controller.md.sal.binding.api.DataBroker;
import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.config.rev160806.AclserviceConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+
public class AclServiceImplFactory implements AutoCloseable {
private static final Logger LOG = LoggerFactory.getLogger(AclServiceImplFactory.class);
public AclServiceImplFactory(DataBroker dataBroker, IMdsalApiManager mdsalManager, AclserviceConfig config) {
this.dataBroker = dataBroker;
this.mdsalManager = mdsalManager;
- this.securityGroupMode = config.getSecurityGroupMode();
+ if (config != null) {
+ this.securityGroupMode = config.getSecurityGroupMode();
+ }
LOG.info("AclserviceConfig: {}", config);
}
- /* alternate use for ConfigAdmin
- public void setSecurityGroupMode(String securityGroupMode) {
- LOG.info("setSecurityGroupMode: {}", securityGroupMode);
- }
-
- public void updateConfigParameter(Map<String, Object> configParameters) {
- LOG.info("Config parameters received : {}", configParameters.entrySet());
- if (configParameters != null && !configParameters.isEmpty()) {
- for (Map.Entry<String, Object> paramEntry : configParameters.entrySet()) {
- if (paramEntry.getKey().equalsIgnoreCase(SECURITY_GROUP_MODE)) {
- LOG.info("setSecurityGroupMode: {}", paramEntry.getValue());
-
- //Please remove the break if you add more config nobs.
- break;
- }
- if (paramEntry.getKey().equalsIgnoreCase("teststring")) {
- LOG.info("testString: {}", paramEntry.getValue());
-
- //Please remove the break if you add more config nobs.
- break;
- }
- if (paramEntry.getKey().equalsIgnoreCase("testint")) {
- LOG.info("testInt: {}", Integer.parseInt((String)paramEntry.getValue()));
-
- //Please remove the break if you add more config nobs.
- break;
- }
- }
- }
- }*/
-
protected InstanceIdentifier<AclserviceConfig> getWildCardPath() {
return InstanceIdentifier
.create(AclserviceConfig.class);
return new IngressAclServiceImpl(dataBroker, mdsalManager);
} else if (securityGroupMode == SecurityGroupMode.Stateless) {
return new StatelessIngressAclServiceImpl(dataBroker, mdsalManager);
- } else {
+ } else if (securityGroupMode == SecurityGroupMode.Transparent) {
return new TransparentIngressAclServiceImpl(dataBroker, mdsalManager);
+ } else {
+ return new LearnIngressAclServiceImpl(dataBroker, mdsalManager);
}
}
return new EgressAclServiceImpl(dataBroker, mdsalManager);
} else if (securityGroupMode == SecurityGroupMode.Stateless) {
return new StatelessEgressAclServiceImpl(dataBroker, mdsalManager);
- } else {
+ } else if (securityGroupMode == SecurityGroupMode.Transparent) {
return new TransparentEgressAclServiceImpl(dataBroker, mdsalManager);
+ } else {
+ return new LearnEgressAclServiceImpl(dataBroker, mdsalManager);
}
}
}
* @param lportTag the lport tag
* @param addOrRemove add/remove the flow.
*/
- private void egressAclDhcpDropServerTraffic(BigInteger dpId, String dhcpMacAddress, int lportTag, int addOrRemove) {
+ protected void egressAclDhcpDropServerTraffic(BigInteger dpId, String dhcpMacAddress, int lportTag,
+ int addOrRemove) {
List<MatchInfoBase> matches = AclServiceUtils.buildDhcpMatches(AclConstants.DHCP_SERVER_PORT_IPV4,
AclConstants.DHCP_CLIENT_PORT_IPV4, lportTag);
* @param lportTag the lport tag
* @param addOrRemove add/remove the flow.
*/
- private void egressAclDhcpv6DropServerTraffic(BigInteger dpId, String dhcpMacAddress, int lportTag,
+ protected void egressAclDhcpv6DropServerTraffic(BigInteger dpId, String dhcpMacAddress, int lportTag,
int addOrRemove) {
List<MatchInfoBase> matches = AclServiceUtils.buildDhcpV6Matches(AclConstants.DHCP_SERVER_PORT_IPV6,
AclConstants.DHCP_CLIENT_PORT_IPV6, lportTag);
* @param lportTag the lport tag
* @param addOrRemove whether to add or remove the flow
*/
- private void programArpRule(BigInteger dpId, List<AllowedAddressPairs> allowedAddresses, int lportTag,
+ protected void programArpRule(BigInteger dpId, List<AllowedAddressPairs> allowedAddresses, int lportTag,
int addOrRemove) {
for (AllowedAddressPairs allowedAddress : allowedAddresses) {
String attachMac = allowedAddress.getMacAddress().getValue();
* @param addOrRemove is write or delete
* @param protoPortMatchPriority the priority
*/
- private void ingressAclDhcpAllowServerTraffic(BigInteger dpId, String dhcpMacAddress, int lportTag, int addOrRemove,
- int protoPortMatchPriority) {
+ protected void ingressAclDhcpAllowServerTraffic(BigInteger dpId, String dhcpMacAddress, int lportTag,
+ int addOrRemove, int protoPortMatchPriority) {
final List<MatchInfoBase> matches = AclServiceUtils.buildDhcpMatches(AclConstants.DHCP_SERVER_PORT_IPV4,
AclConstants.DHCP_CLIENT_PORT_IPV4, lportTag);
* @param addOrRemove is write or delete
* @param protoPortMatchPriority the priority
*/
- private void ingressAclDhcpv6AllowServerTraffic(BigInteger dpId, String dhcpMacAddress, int lportTag,
+ protected void ingressAclDhcpv6AllowServerTraffic(BigInteger dpId, String dhcpMacAddress, int lportTag,
int addOrRemove, Integer protoPortMatchPriority) {
final List<MatchInfoBase> matches = AclServiceUtils.buildDhcpV6Matches(AclConstants.DHCP_SERVER_PORT_IPV6,
AclConstants.DHCP_CLIENT_PORT_IPV6, lportTag);
* @param lportTag the lport tag
* @param addOrRemove whether to add or remove the flow
*/
- private void programArpRule(BigInteger dpId, int lportTag, int addOrRemove) {
+ protected void programArpRule(BigInteger dpId, int lportTag, int addOrRemove) {
List<MatchInfo> matches = new ArrayList<>();
matches.add(new MatchInfo(MatchFieldType.eth_type, new long[] {NwConstants.ETHTYPE_ARP}));
matches.add(AclServiceUtils.buildLPortTagMatch(lportTag));
--- /dev/null
+/*
+ * Copyright (c) 2016 Red Hat, 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
+ */
+package org.opendaylight.netvirt.aclservice;
+
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.genius.mdsalutil.ActionInfo;
+import org.opendaylight.genius.mdsalutil.ActionType;
+import org.opendaylight.genius.mdsalutil.InstructionInfo;
+import org.opendaylight.genius.mdsalutil.InstructionType;
+import org.opendaylight.genius.mdsalutil.MatchInfoBase;
+import org.opendaylight.genius.mdsalutil.NwConstants;
+import org.opendaylight.genius.mdsalutil.NxMatchFieldType;
+import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
+import org.opendaylight.netvirt.aclservice.api.AclServiceManager.Action;
+import org.opendaylight.netvirt.aclservice.utils.AclConstants;
+import org.opendaylight.netvirt.aclservice.utils.AclServiceOFFlowBuilder;
+import org.opendaylight.netvirt.aclservice.utils.AclServiceUtils;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.acl.access.list.entries.Ace;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.acl.access.list.entries.ace.Matches;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.acl.access.list.entries.ace.matches.AceType;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.acl.access.list.entries.ace.matches.ace.type.AceIp;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.DirectionEgress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.SecurityRuleAttr;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.interfaces._interface.AllowedAddressPairs;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class LearnEgressAclServiceImpl extends EgressAclServiceImpl {
+
+ private static final Logger LOG = LoggerFactory.getLogger(LearnEgressAclServiceImpl.class);
+
+ /**
+ * Initialize the member variables.
+ *
+ * @param dataBroker
+ * the data broker instance.
+ * @param mdsalManager
+ * the mdsal manager instance.
+ */
+ public LearnEgressAclServiceImpl(DataBroker dataBroker,
+ IMdsalApiManager mdsalManager) {
+ super(dataBroker, mdsalManager);
+ }
+
+ @Override
+ protected void programFixedRules(BigInteger dpid, String dhcpMacAddress,
+ List<AllowedAddressPairs> allowedAddresses, int lportTag, String portId, Action action, int addOrRemove) {
+ LOG.info("programFixedRules : adding default rules.");
+
+ if (action == Action.ADD || action == Action.REMOVE) {
+ egressAclDhcpDropServerTraffic(dpid, dhcpMacAddress, lportTag, addOrRemove);
+ egressAclDhcpv6DropServerTraffic(dpid, dhcpMacAddress, lportTag, addOrRemove);
+ }
+ programArpRule(dpid, allowedAddresses, lportTag, addOrRemove);
+ }
+
+ @Override
+ protected void programAceRule(BigInteger dpId, int lportTag, int addOrRemove, Ace ace, String portId,
+ List<AllowedAddressPairs> syncAllowedAddresses) {
+ SecurityRuleAttr aceAttr = AclServiceUtils.getAccesssListAttributes(ace);
+ if (!aceAttr.getDirection().equals(DirectionEgress.class)) {
+ return;
+ }
+ Matches matches = ace.getMatches();
+ AceType aceType = matches.getAceType();
+ Map<String, List<MatchInfoBase>> flowMap = null;
+ if (aceType instanceof AceIp) {
+ flowMap = AclServiceOFFlowBuilder.programIpFlow(matches);
+ }
+ if (null == flowMap) {
+ LOG.error("Failed to apply ACL {} lportTag {}", ace.getKey(), lportTag);
+ return;
+ }
+
+ // The flow map contains list of flows if port range is selected.
+ for (Map.Entry<String, List<MatchInfoBase>> flow : flowMap.entrySet()) {
+ List<MatchInfoBase> flowMatches = flow.getValue();
+ flowMatches.add(AclServiceUtils.buildLPortTagMatch(lportTag));
+ List<ActionInfo> actionsInfos = new ArrayList<>();
+ addLearnActions(flowMatches, actionsInfos);
+
+ List<InstructionInfo> instructions = new ArrayList<>();
+ instructions.add(new InstructionInfo(InstructionType.apply_actions, actionsInfos));
+
+ String flowName = flow.getKey() + "Egress" + lportTag + ace.getKey().getRuleName();
+ syncFlow(dpId, NwConstants.INGRESS_LEARN2_TABLE, flowName, AclConstants.PROTO_MATCH_PRIORITY, "ACL", 0, 0,
+ AclConstants.COOKIE_ACL_BASE, flowMatches, instructions, addOrRemove);
+ }
+ }
+
+ /*
+ * learn header
+ *
+ * 0 1 2 3 4 5 6 7 idleTO hardTO prio cook flags table finidle finhrad
+ *
+ * learn flowmod learnFlowModType srcField dstField FlowModNumBits 0 1 2 3
+ */
+ private void addLearnActions(List<MatchInfoBase> flows, List<ActionInfo> actionsInfos) {
+ boolean isTcp = AclServiceUtils.containsMatchFieldType(flows, NxMatchFieldType.nx_tcp_src_with_mask)
+ || AclServiceUtils.containsMatchFieldType(flows, NxMatchFieldType.nx_tcp_dst_with_mask);
+ boolean isUdp = AclServiceUtils.containsMatchFieldType(flows, NxMatchFieldType.nx_udp_src_with_mask)
+ || AclServiceUtils.containsMatchFieldType(flows, NxMatchFieldType.nx_udp_dst_with_mask);
+ if (isTcp) {
+ addTcpLearnActions(actionsInfos);
+ } else if (isUdp) {
+ addUdpLearnActions(actionsInfos);
+ } else if (actionsInfos.isEmpty()) {
+ addAllowAllLearnActions(actionsInfos);
+ } else {
+ addOtherProtocolsLearnActions(actionsInfos);
+ }
+ }
+
+ private void addOtherProtocolsLearnActions(List<ActionInfo> actionsInfos) {
+ String[][] flowMod = new String[5][];
+
+ flowMod[0] = new String[] { NwConstants.LearnFlowModsType.MATCH_FROM_VALUE.name(),
+ Integer.toString(NwConstants.ETHTYPE_IPV4),
+ NwConstants.NxmOfFieldType.NXM_OF_ETH_TYPE.getHexType(),
+ NwConstants.NxmOfFieldType.NXM_OF_ETH_TYPE.getFlowModHeaderLen() };
+ flowMod[1] = new String[] { NwConstants.LearnFlowModsType.MATCH_FROM_FIELD.name(),
+ NwConstants.NxmOfFieldType.NXM_OF_IP_DST.getHexType(),
+ NwConstants.NxmOfFieldType.NXM_OF_IP_SRC.getHexType(),
+ NwConstants.NxmOfFieldType.NXM_OF_IP_SRC.getFlowModHeaderLen() };
+ flowMod[2] = new String[] { NwConstants.LearnFlowModsType.MATCH_FROM_FIELD.name(),
+ NwConstants.NxmOfFieldType.NXM_OF_ETH_DST.getHexType(),
+ NwConstants.NxmOfFieldType.NXM_OF_ETH_SRC.getHexType(),
+ NwConstants.NxmOfFieldType.NXM_OF_ETH_SRC.getFlowModHeaderLen() };
+ flowMod[3] = new String[] { NwConstants.LearnFlowModsType.MATCH_FROM_FIELD.name(),
+ NwConstants.NxmOfFieldType.NXM_OF_IP_PROTO.getHexType(),
+ NwConstants.NxmOfFieldType.NXM_OF_IP_PROTO.getHexType(),
+ NwConstants.NxmOfFieldType.NXM_OF_IP_PROTO.getFlowModHeaderLen() };
+ flowMod[4] = new String[] {
+ NwConstants.LearnFlowModsType.COPY_FROM_VALUE.name(), AclConstants.LEARN_MATCH_REG_VALUE,
+ NwConstants.NxmOfFieldType.NXM_NX_REG0.getHexType(), "8" };
+
+ String[] header = new String[] {
+ AclConstants.getGlobalConf(AclConstants.SECURITY_GROUP_UDP_IDLE_TO_KEY, "60"),
+ AclConstants.getGlobalConf(AclConstants.SECURITY_GROUP_UDP_HARD_TO_KEY, "60"),
+ AclConstants.PROTO_MATCH_PRIORITY.toString(),
+ AclConstants.COOKIE_ACL_BASE.toString(), "0",
+ Short.toString(NwConstants.EGRESS_LEARN_TABLE), "0", "0" };
+ actionsInfos.add(new ActionInfo(ActionType.learn, header, flowMod));
+ }
+
+ private void addAllowAllLearnActions(List<ActionInfo> actionsInfos) {
+ String[][] flowMod = new String[5][];
+
+ flowMod[0] = new String[] { NwConstants.LearnFlowModsType.MATCH_FROM_VALUE.name(),
+ Integer.toString(NwConstants.ETHTYPE_IPV4),
+ NwConstants.NxmOfFieldType.NXM_OF_ETH_TYPE.getHexType(),
+ NwConstants.NxmOfFieldType.NXM_OF_ETH_TYPE.getFlowModHeaderLen() };
+ flowMod[1] = new String[] { NwConstants.LearnFlowModsType.MATCH_FROM_FIELD.name(),
+ NwConstants.NxmOfFieldType.NXM_OF_IP_DST.getHexType(),
+ NwConstants.NxmOfFieldType.NXM_OF_IP_SRC.getHexType(),
+ NwConstants.NxmOfFieldType.NXM_OF_IP_SRC.getFlowModHeaderLen() };
+ flowMod[2] = new String[] { NwConstants.LearnFlowModsType.MATCH_FROM_FIELD.name(),
+ NwConstants.NxmOfFieldType.NXM_OF_ETH_DST.getHexType(),
+ NwConstants.NxmOfFieldType.NXM_OF_ETH_SRC.getHexType(),
+ NwConstants.NxmOfFieldType.NXM_OF_ETH_SRC.getFlowModHeaderLen() };
+ flowMod[3] = new String[] { NwConstants.LearnFlowModsType.MATCH_FROM_FIELD.name(),
+ NwConstants.NxmOfFieldType.NXM_OF_IP_PROTO.getHexType(),
+ NwConstants.NxmOfFieldType.NXM_OF_IP_PROTO.getHexType(),
+ NwConstants.NxmOfFieldType.NXM_OF_IP_PROTO.getFlowModHeaderLen() };
+ flowMod[4] = new String[] {
+ NwConstants.LearnFlowModsType.COPY_FROM_VALUE.name(), AclConstants.LEARN_MATCH_REG_VALUE,
+ NwConstants.NxmOfFieldType.NXM_NX_REG0.getHexType(), "8" };
+
+ String[] header = new String[] {
+ AclConstants.getGlobalConf(AclConstants.SECURITY_GROUP_UDP_IDLE_TO_KEY, "60"),
+ AclConstants.getGlobalConf(AclConstants.SECURITY_GROUP_UDP_HARD_TO_KEY, "60"),
+ AclConstants.PROTO_MATCH_PRIORITY.toString(),
+ AclConstants.COOKIE_ACL_BASE.toString(), "0",
+ Short.toString(NwConstants.EGRESS_LEARN_TABLE), "0", "0" };
+ actionsInfos.add(new ActionInfo(ActionType.learn, header, flowMod));
+ }
+
+ private void addTcpLearnActions(List<ActionInfo> actionsInfos) {
+ String[][] flowMod = new String[6][];
+
+ flowMod[0] = new String[] { NwConstants.LearnFlowModsType.MATCH_FROM_VALUE.name(),
+ Integer.toString(NwConstants.ETHTYPE_IPV4),
+ NwConstants.NxmOfFieldType.NXM_OF_ETH_TYPE.getHexType(),
+ NwConstants.NxmOfFieldType.NXM_OF_ETH_TYPE.getFlowModHeaderLen() };
+ flowMod[1] = new String[] { NwConstants.LearnFlowModsType.MATCH_FROM_VALUE.name(),
+ Integer.toString(NwConstants.IP_PROT_TCP),
+ NwConstants.NxmOfFieldType.NXM_OF_IP_PROTO.getHexType(),
+ NwConstants.NxmOfFieldType.NXM_OF_IP_PROTO.getFlowModHeaderLen() };
+ flowMod[2] = new String[] { NwConstants.LearnFlowModsType.MATCH_FROM_FIELD.name(),
+ NwConstants.NxmOfFieldType.NXM_OF_IP_DST.getHexType(),
+ NwConstants.NxmOfFieldType.NXM_OF_IP_SRC.getHexType(),
+ NwConstants.NxmOfFieldType.NXM_OF_IP_SRC.getFlowModHeaderLen() };
+ flowMod[3] = new String[] { NwConstants.LearnFlowModsType.MATCH_FROM_FIELD.name(),
+ NwConstants.NxmOfFieldType.NXM_OF_TCP_DST.getHexType(),
+ NwConstants.NxmOfFieldType.NXM_OF_TCP_SRC.getHexType(),
+ NwConstants.NxmOfFieldType.NXM_OF_TCP_SRC.getFlowModHeaderLen() };
+ flowMod[4] = new String[] { NwConstants.LearnFlowModsType.MATCH_FROM_FIELD.name(),
+ NwConstants.NxmOfFieldType.NXM_OF_ETH_DST.getHexType(),
+ NwConstants.NxmOfFieldType.NXM_OF_ETH_SRC.getHexType(),
+ NwConstants.NxmOfFieldType.NXM_OF_ETH_SRC.getFlowModHeaderLen() };
+ flowMod[5] = new String[] {
+ NwConstants.LearnFlowModsType.COPY_FROM_VALUE.name(), AclConstants.LEARN_MATCH_REG_VALUE,
+ NwConstants.NxmOfFieldType.NXM_NX_REG0.getHexType(), "8" };
+
+ String[] header = new String[] {
+ AclConstants.getGlobalConf(AclConstants.SECURITY_GROUP_UDP_IDLE_TO_KEY, "3600"),
+ AclConstants.getGlobalConf(AclConstants.SECURITY_GROUP_UDP_HARD_TO_KEY, "3600"),
+ AclConstants.PROTO_MATCH_PRIORITY.toString(),
+ AclConstants.COOKIE_ACL_BASE.toString(), "0",
+ Short.toString(NwConstants.EGRESS_LEARN_TABLE), "60", "60" };
+ actionsInfos.add(new ActionInfo(ActionType.learn, header, flowMod));
+ }
+
+ private void addUdpLearnActions(List<ActionInfo> actionsInfos) {
+ String[][] flowMod = new String[6][];
+
+ flowMod[0] = new String[] { NwConstants.LearnFlowModsType.MATCH_FROM_VALUE.name(),
+ Integer.toString(NwConstants.ETHTYPE_IPV4),
+ NwConstants.NxmOfFieldType.NXM_OF_ETH_TYPE.getHexType(),
+ NwConstants.NxmOfFieldType.NXM_OF_ETH_TYPE.getFlowModHeaderLen() };
+ flowMod[1] = new String[] { NwConstants.LearnFlowModsType.MATCH_FROM_VALUE.name(),
+ Integer.toString(NwConstants.IP_PROT_UDP),
+ NwConstants.NxmOfFieldType.NXM_OF_IP_PROTO.getHexType(),
+ NwConstants.NxmOfFieldType.NXM_OF_IP_PROTO.getFlowModHeaderLen() };
+ flowMod[2] = new String[] { NwConstants.LearnFlowModsType.MATCH_FROM_FIELD.name(),
+ NwConstants.NxmOfFieldType.NXM_OF_IP_DST.getHexType(),
+ NwConstants.NxmOfFieldType.NXM_OF_IP_SRC.getHexType(),
+ NwConstants.NxmOfFieldType.NXM_OF_IP_SRC.getFlowModHeaderLen() };
+ flowMod[3] = new String[] { NwConstants.LearnFlowModsType.MATCH_FROM_FIELD.name(),
+ NwConstants.NxmOfFieldType.NXM_OF_UDP_DST.getHexType(),
+ NwConstants.NxmOfFieldType.NXM_OF_UDP_SRC.getHexType(),
+ NwConstants.NxmOfFieldType.NXM_OF_TCP_SRC.getFlowModHeaderLen() };
+ flowMod[4] = new String[] { NwConstants.LearnFlowModsType.MATCH_FROM_FIELD.name(),
+ NwConstants.NxmOfFieldType.NXM_OF_ETH_DST.getHexType(),
+ NwConstants.NxmOfFieldType.NXM_OF_ETH_SRC.getHexType(),
+ NwConstants.NxmOfFieldType.NXM_OF_ETH_SRC.getFlowModHeaderLen() };
+ flowMod[5] = new String[] {
+ NwConstants.LearnFlowModsType.COPY_FROM_VALUE.name(), AclConstants.LEARN_MATCH_REG_VALUE,
+ NwConstants.NxmOfFieldType.NXM_NX_REG0.getHexType(), "8" };
+
+ String[] header = new String[] {
+ AclConstants.getGlobalConf(AclConstants.SECURITY_GROUP_UDP_IDLE_TO_KEY, "60"),
+ AclConstants.getGlobalConf(AclConstants.SECURITY_GROUP_UDP_HARD_TO_KEY, "60"),
+ AclConstants.PROTO_MATCH_PRIORITY.toString(),
+ AclConstants.COOKIE_ACL_BASE.toString(), "0",
+ Short.toString(NwConstants.EGRESS_LEARN_TABLE), "0", "0" };
+ actionsInfos.add(new ActionInfo(ActionType.learn, header, flowMod));
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2016 Red Hat, 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
+ */
+package org.opendaylight.netvirt.aclservice;
+
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.genius.mdsalutil.ActionInfo;
+import org.opendaylight.genius.mdsalutil.ActionType;
+import org.opendaylight.genius.mdsalutil.InstructionInfo;
+import org.opendaylight.genius.mdsalutil.InstructionType;
+import org.opendaylight.genius.mdsalutil.MatchInfoBase;
+import org.opendaylight.genius.mdsalutil.NwConstants;
+import org.opendaylight.genius.mdsalutil.NxMatchFieldType;
+import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
+import org.opendaylight.netvirt.aclservice.api.AclServiceManager.Action;
+import org.opendaylight.netvirt.aclservice.utils.AclConstants;
+import org.opendaylight.netvirt.aclservice.utils.AclServiceOFFlowBuilder;
+import org.opendaylight.netvirt.aclservice.utils.AclServiceUtils;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.acl.access.list.entries.Ace;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.acl.access.list.entries.ace.Matches;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.acl.access.list.entries.ace.matches.AceType;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.acl.access.list.entries.ace.matches.ace.type.AceIp;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.DirectionIngress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.SecurityRuleAttr;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.interfaces._interface.AllowedAddressPairs;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class LearnIngressAclServiceImpl extends IngressAclServiceImpl {
+
+ private static final Logger LOG = LoggerFactory.getLogger(LearnIngressAclServiceImpl.class);
+
+ public LearnIngressAclServiceImpl(DataBroker dataBroker, IMdsalApiManager mdsalManager) {
+ super(dataBroker, mdsalManager);
+ }
+
+ @Override
+ protected void programFixedRules(BigInteger dpid, String dhcpMacAddress, List<AllowedAddressPairs> allowedAddresses,
+ int lportTag, String portId, Action action, int addOrRemove) {
+ LOG.info("programFixedRules : adding default rules.");
+
+ ingressAclDhcpAllowServerTraffic(dpid, dhcpMacAddress, lportTag, addOrRemove,
+ AclConstants.PROTO_PREFIX_MATCH_PRIORITY);
+ ingressAclDhcpv6AllowServerTraffic(dpid, dhcpMacAddress, lportTag, addOrRemove,
+ AclConstants.PROTO_PREFIX_MATCH_PRIORITY);
+ programArpRule(dpid, lportTag, addOrRemove);
+ }
+
+ @Override
+ protected void programAceRule(BigInteger dpId, int lportTag, int addOrRemove, Ace ace, String portId,
+ List<AllowedAddressPairs> syncAllowedAddresses) {
+ SecurityRuleAttr aceAttr = AclServiceUtils.getAccesssListAttributes(ace);
+ if (!aceAttr.getDirection().equals(DirectionIngress.class)) {
+ return;
+ }
+ Matches matches = ace.getMatches();
+ AceType aceType = matches.getAceType();
+ Map<String, List<MatchInfoBase>> flowMap = null;
+ if (aceType instanceof AceIp) {
+ flowMap = AclServiceOFFlowBuilder.programIpFlow(matches);
+ }
+ if (null == flowMap) {
+ LOG.error("Failed to apply ACL {} lportTag {}", ace.getKey(), lportTag);
+ return;
+ }
+
+ // The flow map contains list of flows if port range is selected.
+ for (Map.Entry<String, List<MatchInfoBase>> flow : flowMap.entrySet()) {
+ List<MatchInfoBase> flowMatches = flow.getValue();
+ flowMatches.add(AclServiceUtils.buildLPortTagMatch(lportTag));
+ List<ActionInfo> actionsInfos = new ArrayList<>();
+ addLearnActions(flowMatches, actionsInfos);
+
+ List<InstructionInfo> instructions = new ArrayList<>();
+ instructions.add(new InstructionInfo(InstructionType.apply_actions, actionsInfos));
+
+ String flowName = flow.getKey() + "Ingress" + lportTag + ace.getKey().getRuleName();
+ syncFlow(dpId, NwConstants.EGRESS_LEARN2_TABLE, flowName, AclConstants.PROTO_MATCH_PRIORITY, "ACL", 0, 0,
+ AclConstants.COOKIE_ACL_BASE, flowMatches, instructions, addOrRemove);
+ }
+ }
+
+ /*
+ * learn header
+ *
+ * 0 1 2 3 4 5 6 7 idleTO hardTO prio cook flags table finidle finhrad
+ *
+ * learn flowmod learnFlowModType srcField dstField FlowModNumBits 0 1 2 3
+ */
+ private void addLearnActions(List<MatchInfoBase> flows, List<ActionInfo> actionsInfos) {
+ boolean isTcp = AclServiceUtils.containsMatchFieldType(flows, NxMatchFieldType.nx_tcp_src_with_mask)
+ || AclServiceUtils.containsMatchFieldType(flows, NxMatchFieldType.nx_tcp_dst_with_mask);
+ boolean isUdp = AclServiceUtils.containsMatchFieldType(flows, NxMatchFieldType.nx_udp_src_with_mask)
+ || AclServiceUtils.containsMatchFieldType(flows, NxMatchFieldType.nx_udp_dst_with_mask);
+ if (isTcp) {
+ addTcpLearnActions(actionsInfos);
+ } else if (isUdp) {
+ addUdpLearnActions(actionsInfos);
+ } else if (actionsInfos.isEmpty()) {
+ addAllowAllLearnActions(actionsInfos);
+ } else {
+ addOtherProtocolsLearnActions(actionsInfos);
+ }
+ }
+
+ private void addOtherProtocolsLearnActions(List<ActionInfo> actionsInfos) {
+ String[][] flowMod = new String[5][];
+
+ flowMod[0] = new String[] { NwConstants.LearnFlowModsType.MATCH_FROM_VALUE.name(),
+ Integer.toString(NwConstants.ETHTYPE_IPV4),
+ NwConstants.NxmOfFieldType.NXM_OF_ETH_TYPE.getHexType(),
+ NwConstants.NxmOfFieldType.NXM_OF_ETH_TYPE.getFlowModHeaderLen() };
+ flowMod[1] = new String[] { NwConstants.LearnFlowModsType.MATCH_FROM_FIELD.name(),
+ NwConstants.NxmOfFieldType.NXM_OF_IP_SRC.getHexType(),
+ NwConstants.NxmOfFieldType.NXM_OF_IP_DST.getHexType(),
+ NwConstants.NxmOfFieldType.NXM_OF_IP_SRC.getFlowModHeaderLen() };
+ flowMod[2] = new String[] { NwConstants.LearnFlowModsType.MATCH_FROM_FIELD.name(),
+ NwConstants.NxmOfFieldType.NXM_OF_ETH_SRC.getHexType(),
+ NwConstants.NxmOfFieldType.NXM_OF_ETH_DST.getHexType(),
+ NwConstants.NxmOfFieldType.NXM_OF_ETH_SRC.getFlowModHeaderLen() };
+ flowMod[3] = new String[] { NwConstants.LearnFlowModsType.MATCH_FROM_FIELD.name(),
+ NwConstants.NxmOfFieldType.NXM_OF_IP_PROTO.getHexType(),
+ NwConstants.NxmOfFieldType.NXM_OF_IP_PROTO.getHexType(),
+ NwConstants.NxmOfFieldType.NXM_OF_IP_PROTO.getFlowModHeaderLen() };
+ flowMod[4] = new String[] {
+ NwConstants.LearnFlowModsType.COPY_FROM_VALUE.name(), AclConstants.LEARN_MATCH_REG_VALUE,
+ NwConstants.NxmOfFieldType.NXM_NX_REG0.getHexType(), "8" };
+
+ String[] header = new String[] {
+ AclConstants.getGlobalConf(AclConstants.SECURITY_GROUP_UDP_IDLE_TO_KEY, "60"),
+ AclConstants.getGlobalConf(AclConstants.SECURITY_GROUP_UDP_HARD_TO_KEY, "60"),
+ AclConstants.PROTO_MATCH_PRIORITY.toString(),
+ AclConstants.COOKIE_ACL_BASE.toString(), "0",
+ Short.toString(NwConstants.INGRESS_LEARN_TABLE), "0", "0" };
+ actionsInfos.add(new ActionInfo(ActionType.learn, header, flowMod));
+ }
+
+ private void addAllowAllLearnActions(List<ActionInfo> actionsInfos) {
+ String[][] flowMod = new String[5][];
+
+ flowMod[0] = new String[] { NwConstants.LearnFlowModsType.MATCH_FROM_VALUE.name(),
+ Integer.toString(NwConstants.ETHTYPE_IPV4),
+ NwConstants.NxmOfFieldType.NXM_OF_ETH_TYPE.getHexType(),
+ NwConstants.NxmOfFieldType.NXM_OF_ETH_TYPE.getFlowModHeaderLen() };
+ flowMod[1] = new String[] { NwConstants.LearnFlowModsType.MATCH_FROM_FIELD.name(),
+ NwConstants.NxmOfFieldType.NXM_OF_IP_SRC.getHexType(),
+ NwConstants.NxmOfFieldType.NXM_OF_IP_DST.getHexType(),
+ NwConstants.NxmOfFieldType.NXM_OF_IP_SRC.getFlowModHeaderLen() };
+ flowMod[2] = new String[] { NwConstants.LearnFlowModsType.MATCH_FROM_FIELD.name(),
+ NwConstants.NxmOfFieldType.NXM_OF_ETH_SRC.getHexType(),
+ NwConstants.NxmOfFieldType.NXM_OF_ETH_DST.getHexType(),
+ NwConstants.NxmOfFieldType.NXM_OF_ETH_SRC.getFlowModHeaderLen() };
+ flowMod[3] = new String[] { NwConstants.LearnFlowModsType.MATCH_FROM_FIELD.name(),
+ NwConstants.NxmOfFieldType.NXM_OF_IP_PROTO.getHexType(),
+ NwConstants.NxmOfFieldType.NXM_OF_IP_PROTO.getHexType(),
+ NwConstants.NxmOfFieldType.NXM_OF_IP_PROTO.getFlowModHeaderLen() };
+ flowMod[4] = new String[] {
+ NwConstants.LearnFlowModsType.COPY_FROM_VALUE.name(), AclConstants.LEARN_MATCH_REG_VALUE,
+ NwConstants.NxmOfFieldType.NXM_NX_REG0.getHexType(), "8" };
+
+ String[] header = new String[] {
+ AclConstants.getGlobalConf(AclConstants.SECURITY_GROUP_UDP_IDLE_TO_KEY, "60"),
+ AclConstants.getGlobalConf(AclConstants.SECURITY_GROUP_UDP_HARD_TO_KEY, "60"),
+ AclConstants.PROTO_MATCH_PRIORITY.toString(),
+ AclConstants.COOKIE_ACL_BASE.toString(), "0",
+ Short.toString(NwConstants.INGRESS_LEARN_TABLE), "0", "0" };
+ actionsInfos.add(new ActionInfo(ActionType.learn, header, flowMod));
+ }
+
+ private void addTcpLearnActions(List<ActionInfo> actionsInfos) {
+ String[][] flowMod = new String[6][];
+
+ flowMod[0] = new String[] { NwConstants.LearnFlowModsType.MATCH_FROM_VALUE.name(),
+ Integer.toString(NwConstants.ETHTYPE_IPV4),
+ NwConstants.NxmOfFieldType.NXM_OF_ETH_TYPE.getHexType(),
+ NwConstants.NxmOfFieldType.NXM_OF_ETH_TYPE.getFlowModHeaderLen() };
+ flowMod[1] = new String[] { NwConstants.LearnFlowModsType.MATCH_FROM_VALUE.name(),
+ Integer.toString(NwConstants.IP_PROT_TCP),
+ NwConstants.NxmOfFieldType.NXM_OF_IP_PROTO.getHexType(),
+ NwConstants.NxmOfFieldType.NXM_OF_IP_PROTO.getFlowModHeaderLen() };
+ flowMod[2] = new String[] { NwConstants.LearnFlowModsType.MATCH_FROM_FIELD.name(),
+ NwConstants.NxmOfFieldType.NXM_OF_IP_SRC.getHexType(),
+ NwConstants.NxmOfFieldType.NXM_OF_IP_DST.getHexType(),
+ NwConstants.NxmOfFieldType.NXM_OF_IP_SRC.getFlowModHeaderLen() };
+ flowMod[3] = new String[] { NwConstants.LearnFlowModsType.MATCH_FROM_FIELD.name(),
+ NwConstants.NxmOfFieldType.NXM_OF_TCP_SRC.getHexType(),
+ NwConstants.NxmOfFieldType.NXM_OF_TCP_DST.getHexType(),
+ NwConstants.NxmOfFieldType.NXM_OF_TCP_SRC.getFlowModHeaderLen() };
+ flowMod[4] = new String[] { NwConstants.LearnFlowModsType.MATCH_FROM_FIELD.name(),
+ NwConstants.NxmOfFieldType.NXM_OF_ETH_SRC.getHexType(),
+ NwConstants.NxmOfFieldType.NXM_OF_ETH_DST.getHexType(),
+ NwConstants.NxmOfFieldType.NXM_OF_ETH_SRC.getFlowModHeaderLen() };
+ flowMod[5] = new String[] {
+ NwConstants.LearnFlowModsType.COPY_FROM_VALUE.name(), AclConstants.LEARN_MATCH_REG_VALUE,
+ NwConstants.NxmOfFieldType.NXM_NX_REG0.getHexType(), "8" };
+
+ String[] header = new String[] {
+ AclConstants.getGlobalConf(AclConstants.SECURITY_GROUP_UDP_IDLE_TO_KEY, "3600"),
+ AclConstants.getGlobalConf(AclConstants.SECURITY_GROUP_UDP_HARD_TO_KEY, "3600"),
+ AclConstants.PROTO_MATCH_PRIORITY.toString(),
+ AclConstants.COOKIE_ACL_BASE.toString(), "0",
+ Short.toString(NwConstants.INGRESS_LEARN_TABLE), "60", "60" };
+ actionsInfos.add(new ActionInfo(ActionType.learn, header, flowMod));
+ }
+
+ private void addUdpLearnActions(List<ActionInfo> actionsInfos) {
+ String[][] flowMod = new String[6][];
+
+ flowMod[0] = new String[] { NwConstants.LearnFlowModsType.MATCH_FROM_VALUE.name(),
+ Integer.toString(NwConstants.ETHTYPE_IPV4),
+ NwConstants.NxmOfFieldType.NXM_OF_ETH_TYPE.getHexType(),
+ NwConstants.NxmOfFieldType.NXM_OF_ETH_TYPE.getFlowModHeaderLen() };
+ flowMod[1] = new String[] { NwConstants.LearnFlowModsType.MATCH_FROM_VALUE.name(),
+ Integer.toString(NwConstants.IP_PROT_UDP),
+ NwConstants.NxmOfFieldType.NXM_OF_IP_PROTO.getHexType(),
+ NwConstants.NxmOfFieldType.NXM_OF_IP_PROTO.getFlowModHeaderLen() };
+ flowMod[2] = new String[] { NwConstants.LearnFlowModsType.MATCH_FROM_FIELD.name(),
+ NwConstants.NxmOfFieldType.NXM_OF_IP_SRC.getHexType(),
+ NwConstants.NxmOfFieldType.NXM_OF_IP_DST.getHexType(),
+ NwConstants.NxmOfFieldType.NXM_OF_IP_SRC.getFlowModHeaderLen() };
+ flowMod[3] = new String[] { NwConstants.LearnFlowModsType.MATCH_FROM_FIELD.name(),
+ NwConstants.NxmOfFieldType.NXM_OF_UDP_SRC.getHexType(),
+ NwConstants.NxmOfFieldType.NXM_OF_UDP_DST.getHexType(),
+ NwConstants.NxmOfFieldType.NXM_OF_TCP_SRC.getFlowModHeaderLen() };
+ flowMod[4] = new String[] { NwConstants.LearnFlowModsType.MATCH_FROM_FIELD.name(),
+ NwConstants.NxmOfFieldType.NXM_OF_ETH_SRC.getHexType(),
+ NwConstants.NxmOfFieldType.NXM_OF_ETH_DST.getHexType(),
+ NwConstants.NxmOfFieldType.NXM_OF_ETH_SRC.getFlowModHeaderLen() };
+ flowMod[5] = new String[] {
+ NwConstants.LearnFlowModsType.COPY_FROM_VALUE.name(), AclConstants.LEARN_MATCH_REG_VALUE,
+ NwConstants.NxmOfFieldType.NXM_NX_REG0.getHexType(), "8" };
+
+ String[] header = new String[] {
+ AclConstants.getGlobalConf(AclConstants.SECURITY_GROUP_UDP_IDLE_TO_KEY, "60"),
+ AclConstants.getGlobalConf(AclConstants.SECURITY_GROUP_UDP_HARD_TO_KEY, "60"),
+ AclConstants.PROTO_MATCH_PRIORITY.toString(),
+ AclConstants.COOKIE_ACL_BASE.toString(), "0",
+ Short.toString(NwConstants.INGRESS_LEARN_TABLE), "0", "0" };
+ actionsInfos.add(new ActionInfo(ActionType.learn, header, flowMod));
+ }
+}
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;
+
import org.opendaylight.controller.md.sal.binding.api.DataBroker;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
import org.opendaylight.genius.datastoreutils.AsyncDataTreeChangeListenerBase;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+
+
/**
* Listener to handle flow capable node updates.
*/
*
* @param mdsalManager the mdsal manager
* @param dataBroker the data broker
- * @param config - acl service configuration
+ * @param config aclservice configuration
*/
public AclNodeListener(final IMdsalApiManager mdsalManager, DataBroker dataBroker, AclserviceConfig config) {
super(FlowCapableNode.class, AclNodeListener.class);
public void start() {
LOG.info("{} start", getClass().getSimpleName());
- this.securityGroupMode = config.getSecurityGroupMode();
+ if (config != null) {
+ this.securityGroupMode = config.getSecurityGroupMode();
+ }
registerListener(LogicalDatastoreType.OPERATIONAL, dataBroker);
- LOG.info("AclserviceConfig: {}", config);
+ LOG.info("AclserviceConfig: {}", this.config);
}
/*
* @param dpnId the dpn id
*/
private void createTableDefaultEntries(BigInteger dpnId) {
- LOG.info("installing security group default rule in mode {}", this.securityGroupMode);
+ LOG.info("Adding default ACL entries for mode: "
+ + (securityGroupMode == null ? SecurityGroupMode.Stateful : securityGroupMode));
if (securityGroupMode == null || securityGroupMode == SecurityGroupMode.Stateful) {
addIngressAclTableMissFlow(dpnId);
addEgressAclTableMissFlow(dpnId);
} else if (securityGroupMode == SecurityGroupMode.Transparent) {
addTransparentIngressAclTableMissFlow(dpnId);
addTransparentEgressAclTableMissFlow(dpnId);
- } else {
+ } else if (securityGroupMode == SecurityGroupMode.Stateless) {
addStatelessIngressAclTableMissFlow(dpnId);
addStatelessEgressAclTableMissFlow(dpnId);
+ } else if (securityGroupMode == SecurityGroupMode.Learn) {
+ addLearnIngressAclTableMissFlow(dpnId);
+ addLearnEgressAclTableMissFlow(dpnId);
}
}
LOG.debug("Added Ingress ACL Table Miss Flows for dpn {}", dpId);
}
+ private void addLearnEgressAclTableMissFlow(BigInteger dpId) {
+ List<InstructionInfo> mkInstructions = new ArrayList<>();
+ List<ActionInfo> actionsInfos = new ArrayList<>();
+ actionsInfos.add(new ActionInfo(ActionType.nx_resubmit,
+ new String[] {Short.toString(NwConstants.EGRESS_LEARN_TABLE) }));
+ actionsInfos.add(new ActionInfo(ActionType.nx_resubmit,
+ new String[] {Short.toString(NwConstants.EGRESS_LEARN2_TABLE) }));
+ mkInstructions.add(new InstructionInfo(InstructionType.apply_actions, actionsInfos));
+
+ List<MatchInfo> mkMatches = new ArrayList<>();
+ FlowEntity doubleResubmitTable = MDSALUtil.buildFlowEntity(dpId, NwConstants.EGRESS_ACL_TABLE,
+ "RESUB-" + getTableMissFlowId(NwConstants.EGRESS_ACL_TABLE),
+ AclConstants.PROTO_MATCH_PRIORITY, "Egress resubmit ACL Table Block", 0, 0,
+ AclConstants.COOKIE_ACL_BASE, mkMatches, mkInstructions);
+ mdsalManager.installFlow(doubleResubmitTable);
+
+ mkMatches = new ArrayList<>();
+ mkInstructions = new ArrayList<>();
+ actionsInfos = new ArrayList<>();
+ actionsInfos.add(new ActionInfo(ActionType.drop_action, new String[] {}));
+ mkInstructions.add(new InstructionInfo(InstructionType.apply_actions, actionsInfos));
+
+ FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.EGRESS_LEARN_TABLE,
+ "LEARN-" + getTableMissFlowId(NwConstants.EGRESS_LEARN_TABLE), 0,
+ "Egress Learn ACL Table Miss Flow", 0, 0,
+ AclConstants.COOKIE_ACL_BASE, mkMatches, mkInstructions);
+ mdsalManager.installFlow(flowEntity);
+
+ flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.EGRESS_LEARN2_TABLE,
+ "LEARN-" + getTableMissFlowId(NwConstants.EGRESS_LEARN2_TABLE), 0,
+ "Egress Learn2 ACL Table Miss Flow", 0, 0,
+ AclConstants.COOKIE_ACL_BASE, mkMatches, mkInstructions);
+ mdsalManager.installFlow(flowEntity);
+
+ List<NxMatchInfo> nxMkMatches = new ArrayList<>();
+ nxMkMatches.add(new NxMatchInfo(NxMatchFieldType.nxm_reg_6,
+ new long[] {Long.valueOf(AclConstants.LEARN_MATCH_REG_VALUE)}));
+
+ short dispatcherTableId = NwConstants.EGRESS_LPORT_DISPATCHER_TABLE;
+ List<InstructionInfo> instructions = new ArrayList<>();
+ actionsInfos.add(new ActionInfo(ActionType.nx_resubmit, new String[] {Short.toString(dispatcherTableId)}));
+ instructions.add(new InstructionInfo(InstructionType.apply_actions, actionsInfos));
+
+ flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.EGRESS_LEARN2_TABLE,
+ "LEARN2-REG-" + getTableMissFlowId(NwConstants.EGRESS_LEARN2_TABLE),
+ AclConstants.PROTO_MATCH_PRIORITY, "Egress Learn2 ACL Table match reg Flow", 0, 0,
+ AclConstants.COOKIE_ACL_BASE, nxMkMatches, instructions);
+ mdsalManager.installFlow(flowEntity);
+ LOG.debug("Added learn ACL Table Miss Flows for dpn {}", dpId);
+ }
+
+ private void addLearnIngressAclTableMissFlow(BigInteger dpId) {
+ List<InstructionInfo> mkInstructions = new ArrayList<>();
+ List<ActionInfo> actionsInfos = new ArrayList<>();
+ actionsInfos.add(new ActionInfo(ActionType.nx_resubmit,
+ new String[] {Short.toString(NwConstants.INGRESS_LEARN_TABLE) }));
+ actionsInfos.add(new ActionInfo(ActionType.nx_resubmit,
+ new String[] {Short.toString(NwConstants.INGRESS_LEARN2_TABLE) }));
+ mkInstructions.add(new InstructionInfo(InstructionType.apply_actions, actionsInfos));
+
+ List<MatchInfo> mkMatches = new ArrayList<>();
+ FlowEntity doubleResubmitTable = MDSALUtil.buildFlowEntity(dpId, NwConstants.INGRESS_ACL_TABLE,
+ "RESUB-" + getTableMissFlowId(NwConstants.INGRESS_ACL_TABLE),
+ AclConstants.PROTO_MATCH_PRIORITY, "Ingress resubmit ACL Table Block", 0, 0,
+ AclConstants.COOKIE_ACL_BASE, mkMatches, mkInstructions);
+ mdsalManager.installFlow(doubleResubmitTable);
+
+ mkMatches = new ArrayList<>();
+ mkInstructions = new ArrayList<>();
+ actionsInfos = new ArrayList<>();
+ actionsInfos.add(new ActionInfo(ActionType.drop_action, new String[] {}));
+ mkInstructions.add(new InstructionInfo(InstructionType.apply_actions, actionsInfos));
+
+ FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.INGRESS_LEARN_TABLE,
+ "LEARN-" + getTableMissFlowId(NwConstants.INGRESS_LEARN_TABLE), 0,
+ "Ingress Learn ACL Table Miss Flow", 0, 0,
+ AclConstants.COOKIE_ACL_BASE, mkMatches, mkInstructions);
+ mdsalManager.installFlow(flowEntity);
+
+ flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.INGRESS_LEARN2_TABLE,
+ "LEARN-" + getTableMissFlowId(NwConstants.INGRESS_LEARN2_TABLE), 0,
+ "Ingress Learn2 ACL Table Miss Flow", 0, 0,
+ AclConstants.COOKIE_ACL_BASE, mkMatches, mkInstructions);
+ mdsalManager.installFlow(flowEntity);
+
+ List<NxMatchInfo> nxMkMatches = new ArrayList<>();
+ nxMkMatches.add(new NxMatchInfo(NxMatchFieldType.nxm_reg_6,
+ new long[] {Long.valueOf(AclConstants.LEARN_MATCH_REG_VALUE)}));
+
+ short dispatcherTableId = NwConstants.LPORT_DISPATCHER_TABLE;
+ List<InstructionInfo> instructions = new ArrayList<>();
+ actionsInfos.add(new ActionInfo(ActionType.nx_resubmit, new String[] {Short.toString(dispatcherTableId)}));
+ instructions.add(new InstructionInfo(InstructionType.apply_actions, actionsInfos));
+
+ flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.INGRESS_LEARN2_TABLE,
+ "LEARN2-REG-" + getTableMissFlowId(NwConstants.INGRESS_LEARN2_TABLE),
+ AclConstants.PROTO_MATCH_PRIORITY, "Egress Learn2 ACL Table match reg Flow", 0, 0,
+ AclConstants.COOKIE_ACL_BASE, nxMkMatches, instructions);
+ mdsalManager.installFlow(flowEntity);
+ LOG.debug("Added learn ACL Table Miss Flows for dpn {}", dpId);
+
+ }
+
/**
* Adds the ingress acl table transparent flow.
*
package org.opendaylight.netvirt.aclservice.utils;
import java.math.BigInteger;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
import org.opendaylight.ovsdb.utils.config.ConfigProperties;
/**
public static final int ICMPV6_TYPE_NA = 136;
public static final int ICMPV6_TYPE_MLD2_REPORT = 143;
+ public static final BigInteger METADATA_MASK_LEARN_FLAG = new BigInteger("FFFFFFFFFFFFFFFE", 16);
+
+ public static final String SECURITY_GROUP_TCP_IDLE_TO_KEY = "security-group-tcp-idle-timeout";
+ public static final String SECURITY_GROUP_TCP_HARD_TO_KEY = "security-group-tcp-hard-timeout";
+ public static final String SECURITY_GROUP_TCP_FIN_IDLE_TO_KEY = "security-group-tcp-fin-idle-timeout";
+ public static final String SECURITY_GROUP_TCP_FIN_HARD_TO_KEY = "security-group-tcp-fin-hard-timeout";
+ public static final String SECURITY_GROUP_UDP_IDLE_TO_KEY = "security-group-udp-idle-timeout";
+ public static final String SECURITY_GROUP_UDP_HARD_TO_KEY = "security-group-udp-hard-timeout";
+
+ public static final String LEARN_MATCH_REG_VALUE = "1";
+
private AclConstants() {
}
- public static boolean isStatelessAcl() {
- final String enabledPropertyStr = ConfigProperties.getProperty(AclConstants.class, "stateless.sg.enabled");
- return enabledPropertyStr != null && enabledPropertyStr.equalsIgnoreCase("yes");
+ private static Map<String, Object> globalConf = Collections.synchronizedMap(new HashMap<>());
+
+ public static String getGlobalConf(String key, String defaultValue) {
+ String ret = defaultValue;
+ String value = (String)globalConf.get(key);
+ if (value == null) {
+ String propertyStr = ConfigProperties.getProperty(AclConstants.class, key);
+ if (propertyStr != null) {
+ ret = propertyStr;
+ }
+ globalConf.put(key, ret);
+ }
+ return ret;
}
+
}
enum "transparent";
enum "stateless";
enum "stateful";
+ enum "learn";
}
}
}
--- /dev/null
+/*
+ * Copyright (c) 2016 Red Hat, 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
+ */
+package org.opendaylight.netvirt.aclservice;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.when;
+
+import com.google.common.base.Optional;
+import com.google.common.util.concurrent.Futures;
+import java.math.BigInteger;
+import java.util.Arrays;
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.runners.MockitoJUnitRunner;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.genius.mdsalutil.ActionType;
+import org.opendaylight.genius.mdsalutil.FlowEntity;
+import org.opendaylight.genius.mdsalutil.MatchFieldType;
+import org.opendaylight.genius.mdsalutil.NwConstants;
+import org.opendaylight.genius.mdsalutil.NxMatchFieldType;
+import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
+import org.opendaylight.netvirt.aclservice.api.utils.AclInterface;
+import org.opendaylight.netvirt.aclservice.utils.AclServiceTestUtils;
+import org.opendaylight.netvirt.aclservice.utils.AclServiceUtils;
+import org.opendaylight.netvirt.aclservice.utils.MethodInvocationParamSaver;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.Ipv4Acl;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.Acl;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.AclBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.AclKey;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.acl.AccessListEntriesBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.acl.access.list.entries.AceBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.acl.access.list.entries.ace.MatchesBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.acl.access.list.entries.ace.matches.ace.type.AceIpBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.acl.access.list.entries.ace.matches.ace.type.ace.ip.ace.ip.version.AceIpv4Builder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Prefix;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.PortNumber;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.packet.fields.rev160218.acl.transport.header.fields.DestinationPortRangeBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.MacAddress;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.DirectionEgress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.IpPrefixOrAddress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.SecurityRuleAttr;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.SecurityRuleAttrBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.interfaces._interface.AllowedAddressPairsBuilder;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+@RunWith(MockitoJUnitRunner.class)
+public class LearnEgressAclServiceImplTest {
+
+ private LearnEgressAclServiceImpl testedService;
+
+ @Mock
+ DataBroker dataBroker;
+ @Mock
+ IMdsalApiManager mdsalManager;
+ @Mock
+ WriteTransaction mockWriteTx;
+ @Mock
+ ReadOnlyTransaction mockReadTx;
+
+ MethodInvocationParamSaver<Void> installFlowValueSaver = null;
+ MethodInvocationParamSaver<Void> removeFlowValueSaver = null;
+
+ @Before
+ public void setUp() {
+ testedService = new LearnEgressAclServiceImpl(dataBroker, mdsalManager);
+ doReturn(Futures.immediateCheckedFuture(null)).when(mockWriteTx).submit();
+ doReturn(mockReadTx).when(dataBroker).newReadOnlyTransaction();
+ doReturn(mockWriteTx).when(dataBroker).newWriteOnlyTransaction();
+ installFlowValueSaver = new MethodInvocationParamSaver<Void>(null);
+ doAnswer(installFlowValueSaver).when(mdsalManager).installFlow(any(FlowEntity.class));
+ removeFlowValueSaver = new MethodInvocationParamSaver<Void>(null);
+ doAnswer(installFlowValueSaver).when(mdsalManager).removeFlow(any(FlowEntity.class));
+
+ }
+
+ @Test
+ public void addAcl__NullInterface() {
+ assertEquals(false, testedService.applyAcl(null));
+ }
+
+ @Test
+ public void addAcl__MissingInterfaceStateShouldFail() throws Exception {
+ AclInterface ai = new AclInterface();
+ ai.setPortSecurityEnabled(true);
+ ai.setDpId(BigInteger.ONE);
+ assertEquals(false, testedService.applyAcl(ai));
+ }
+
+ @Test
+ public void addAcl__SinglePort() throws Exception {
+ Uuid sgUuid = new Uuid("12345678-1234-1234-1234-123456789012");
+ AclInterface ai = stubTcpAclInterface(sgUuid, "if_name", "1.1.1.1/32", 80, 80);
+ assertEquals(true, testedService.applyAcl(ai));
+ assertEquals(4, installFlowValueSaver.getNumOfInvocations());
+
+ FlowEntity flow = (FlowEntity) installFlowValueSaver.getInvocationParams(3).get(0);
+ AclServiceTestUtils.verifyMatchInfo(flow.getMatchInfoList(),
+ NxMatchFieldType.nx_tcp_dst_with_mask, "80", "65535");
+ AclServiceTestUtils.verifyActionTypeExist(flow.getInstructionInfoList().get(0).getActionInfos(),
+ ActionType.learn);
+
+ }
+
+ @Test
+ public void addAcl__AllowAll() throws Exception {
+ Uuid sgUuid = new Uuid("12345678-1234-1234-1234-123456789012");
+ AclInterface ai = stubAllowAllInterface(sgUuid, "if_name");
+ assertEquals(true, testedService.applyAcl(ai));
+ assertEquals(4, installFlowValueSaver.getNumOfInvocations());
+
+ FlowEntity flow = (FlowEntity) installFlowValueSaver.getInvocationParams(3).get(0);
+ AclServiceTestUtils.verifyActionTypeExist(flow.getInstructionInfoList().get(0).getActionInfos(),
+ ActionType.learn);
+ }
+
+ @Test
+ public void addAcl__MultipleRanges() throws Exception {
+ Uuid sgUuid = new Uuid("12345678-1234-1234-1234-123456789012");
+ AclInterface ai = stubTcpAclInterface(sgUuid, "if_name", "1.1.1.1/32", 80, 84);
+ assertEquals(true, testedService.applyAcl(ai));
+ assertEquals(5, installFlowValueSaver.getNumOfInvocations());
+ FlowEntity firstRangeFlow = (FlowEntity) installFlowValueSaver.getInvocationParams(3).get(0);
+ AclServiceTestUtils.verifyMatchInfo(firstRangeFlow.getMatchInfoList(),
+ NxMatchFieldType.nx_tcp_dst_with_mask, "80", "65532");
+
+ FlowEntity secondRangeFlow = (FlowEntity) installFlowValueSaver.getInvocationParams(4).get(0);
+ AclServiceTestUtils.verifyMatchInfo(secondRangeFlow.getMatchInfoList(),
+ NxMatchFieldType.nx_tcp_dst_with_mask, "84", "65535");
+ }
+
+ @Test
+ public void addAcl__UdpSinglePortShouldNotCreateSynRule() throws Exception {
+ Uuid sgUuid = new Uuid("12345678-1234-1234-1234-123456789012");
+ AclInterface ai = stubUdpAclInterface(sgUuid, "if_name", "1.1.1.1/32", 80, 80);
+ assertEquals(true, testedService.applyAcl(ai));
+ assertEquals(4, installFlowValueSaver.getNumOfInvocations());
+ FlowEntity flow = (FlowEntity) installFlowValueSaver.getInvocationParams(3).get(0);
+ AclServiceTestUtils.verifyMatchInfo(flow.getMatchInfoList(),
+ NxMatchFieldType.nx_udp_dst_with_mask, "80", "65535");
+ AclServiceTestUtils.verifyActionTypeExist(flow.getInstructionInfoList().get(0).getActionInfos(),
+ ActionType.learn);
+ }
+
+ @Test
+ @Ignore
+ public void removeAcl__SinglePort() throws Exception {
+ Uuid sgUuid = new Uuid("12345678-1234-1234-1234-123456789012");
+ AclInterface ai = stubTcpAclInterface(sgUuid, "if_name", "1.1.1.1/32", 80, 80);
+ assertEquals(true, testedService.removeAcl(ai));
+ assertEquals(1, removeFlowValueSaver.getNumOfInvocations());
+ FlowEntity firstRangeFlow = (FlowEntity) removeFlowValueSaver.getInvocationParams(0).get(0);
+ AclServiceTestUtils.verifyMatchInfo(firstRangeFlow.getMatchInfoList(), MatchFieldType.tcp_flags, "2");
+ AclServiceTestUtils.verifyMatchInfo(firstRangeFlow.getMatchInfoList(),
+ NxMatchFieldType.nx_tcp_dst_with_mask, "80", "65535");
+
+ }
+
+ private AclInterface stubUdpAclInterface(Uuid sgUuid, String ifName, String ipv4PrefixStr,
+ int tcpPortLower, int tcpPortUpper) {
+ AclInterface ai = new AclInterface();
+ ai.setPortSecurityEnabled(true);
+ ai.setSecurityGroups(Arrays.asList(sgUuid));
+ ai.setDpId(BigInteger.ONE);
+ ai.setLPortTag(new Integer(2));
+ stubInterfaceAcl(ifName, ai);
+
+ stubAccessList(sgUuid, ipv4PrefixStr, tcpPortLower, tcpPortUpper, (short)NwConstants.IP_PROT_UDP);
+ return ai;
+ }
+
+ private AclInterface stubTcpAclInterface(Uuid sgUuid, String ifName, String ipv4PrefixStr,
+ int tcpPortLower, int tcpPortUpper) {
+ AclInterface ai = new AclInterface();
+ ai.setPortSecurityEnabled(true);
+ ai.setDpId(BigInteger.ONE);
+ ai.setLPortTag(Integer.valueOf(2));
+ ai.setSecurityGroups(Arrays.asList(sgUuid));
+ stubInterfaceAcl(ifName, ai);
+
+ stubAccessList(sgUuid, ipv4PrefixStr, tcpPortLower, tcpPortUpper, (short)NwConstants.IP_PROT_TCP);
+ return ai;
+ }
+
+ private void stubInterfaceAcl(String ifName, AclInterface ai) {
+ AllowedAddressPairsBuilder aapb = new AllowedAddressPairsBuilder();
+ aapb.setIpAddress(new IpPrefixOrAddress("1.1.1.1/32".toCharArray()));
+ aapb.setMacAddress(new MacAddress("AA:BB:CC:DD:EE:FF"));
+ ai.setAllowedAddressPairs(Arrays.asList(aapb.build()));
+ }
+
+ private AclInterface stubAllowAllInterface(Uuid sgUuid, String ifName) {
+ AclInterface ai = new AclInterface();
+ ai.setPortSecurityEnabled(true);
+ ai.setSecurityGroups(Arrays.asList(sgUuid));
+ ai.setDpId(BigInteger.ONE);
+ ai.setLPortTag(new Integer(2));
+ stubInterfaceAcl(ifName, ai);
+
+ stubAccessList(sgUuid, null, -1, -1, (short)-1);
+ return ai;
+ }
+
+ private void stubAccessList(Uuid sgUuid, String ipv4PrefixStr, int portLower, int portUpper, short protocol) {
+ AclBuilder ab = new AclBuilder();
+ ab.setAclName("AAA");
+ ab.setKey(new AclKey(sgUuid.getValue(),Ipv4Acl.class));
+
+ AceIpBuilder aceIpBuilder = new AceIpBuilder();
+ if (portLower != -1 && portUpper != -1) {
+ DestinationPortRangeBuilder dprb = new DestinationPortRangeBuilder();
+ dprb.setLowerPort(new PortNumber(portLower));
+ dprb.setUpperPort(new PortNumber(portUpper));
+ aceIpBuilder.setDestinationPortRange(dprb.build());
+ }
+ if (ipv4PrefixStr != null) {
+ AceIpv4Builder aceIpv4Builder = new AceIpv4Builder();
+ Ipv4Prefix ipv4Prefix = new Ipv4Prefix(ipv4PrefixStr);
+ aceIpv4Builder.setSourceIpv4Network(ipv4Prefix);
+ aceIpBuilder.setAceIpVersion(aceIpv4Builder.build());
+ }
+ if (protocol != -1) {
+ aceIpBuilder.setProtocol(protocol);
+ }
+ MatchesBuilder matches = new MatchesBuilder();
+ matches.setAceType(aceIpBuilder.build());
+ AceBuilder aceBuilder = new AceBuilder();
+ aceBuilder.setMatches(matches.build());
+ SecurityRuleAttrBuilder securityRuleAttrBuilder = new SecurityRuleAttrBuilder();
+ securityRuleAttrBuilder.setDirection(DirectionEgress.class);
+ aceBuilder.addAugmentation(SecurityRuleAttr.class, securityRuleAttrBuilder.build());
+ AccessListEntriesBuilder aleb = new AccessListEntriesBuilder();
+ aleb.setAce(Arrays.asList(aceBuilder.build()));
+ ab.setAccessListEntries(aleb.build());
+
+ InstanceIdentifier<Acl> aclKey = AclServiceUtils.getAclInstanceIdentifier(sgUuid.getValue());
+ when(mockReadTx.read(LogicalDatastoreType.CONFIGURATION, aclKey))
+ .thenReturn(Futures.immediateCheckedFuture(Optional.of(ab.build())));
+ }
+}
assertEquals(true, testedService.applyAcl(ai));
assertEquals(2, installFlowValueSaver.getNumOfInvocations());
FlowEntity firstRangeFlow = (FlowEntity) installFlowValueSaver.getInvocationParams(0).get(0);
- // should have been 80-83 will be fixed as part of the port range support
- // https://bugs.opendaylight.org/show_bug.cgi?id=6200
AclServiceTestUtils.verifyMatchInfo(firstRangeFlow.getMatchInfoList(),
NxMatchFieldType.nx_tcp_dst_with_mask, "80", "65532");
AclServiceTestUtils.verifyMatchInfo(firstRangeFlow.getMatchInfoList(), MatchFieldType.tcp_flags, "2");
AclDataUtil.removeAclInterfaceMap(prapreaAclIds(aclNames), inter);
}
+ public static void verifyActionTypeExist(List<ActionInfo> flowActions, ActionType actionType) {
+ Iterable<ActionInfo> actions = filter(flowActions,
+ (item -> ((ActionInfo) item).getActionType().equals(actionType)));
+ assertFalse(Iterables.isEmpty(actions));
+ }
+
public static void verifyActionInfo(List<ActionInfo> flowActions, ActionType actionType, String... params) {
Iterable<ActionInfo> actions = filter(flowActions,
(item -> ((ActionInfo) item).getActionType().equals(actionType)));
}
}
+ public static void verifyLearnActionFlowModInfo(List<ActionInfo> flowActions,
+ NwConstants.LearnFlowModsType type, String... params) {
+ Iterable<ActionInfo> actions = filter(flowActions,
+ (item -> ((ActionInfo) item).getActionType().equals(ActionType.learn)
+ && ((ActionInfo) item).getActionValuesMatrix()[0].equals(type.name())));
+ assertFalse(Iterables.isEmpty(actions));
+ for (ActionInfo action : actions) {
+ verifyActionValues(action, params);
+ }
+ }
+
public static void verifyInstructionInfo(List<InstructionInfo> instructionInfoList, InstructionType type,
String ... params) {
Iterable<InstructionInfo> matches = filter(instructionInfoList,