[ONOS-7653] ACL app enhancements for including more matching criteria in rules
Change-Id: Ic29bab0c0752d6280a5feff992a69a2e10084414
diff --git a/apps/acl/src/main/java/org/onosproject/acl/AclRule.java b/apps/acl/src/main/java/org/onosproject/acl/AclRule.java
index 02b7025..8587d7c 100644
--- a/apps/acl/src/main/java/org/onosproject/acl/AclRule.java
+++ b/apps/acl/src/main/java/org/onosproject/acl/AclRule.java
@@ -23,6 +23,7 @@
import com.google.common.base.MoreObjects;
import org.onlab.packet.IPv4;
import org.onlab.packet.Ip4Prefix;
+import org.onlab.packet.MacAddress;
import org.onosproject.core.IdGenerator;
import java.util.Objects;
@@ -37,10 +38,14 @@
private final RuleId id;
+ private final MacAddress srcMac;
+ private final MacAddress dstMac;
private final Ip4Prefix srcIp;
private final Ip4Prefix dstIp;
private final byte ipProto;
+ private final short srcTpPort;
private final short dstTpPort;
+ private final byte dscp;
private final Action action;
protected static IdGenerator idGenerator;
@@ -58,10 +63,14 @@
*/
private AclRule() {
this.id = null;
+ this.srcMac = null;
+ this.dstMac = null;
this.srcIp = null;
this.dstIp = null;
+ this.dscp = 0;
this.ipProto = 0;
this.dstTpPort = 0;
+ this.srcTpPort = 0;
this.action = null;
}
@@ -69,21 +78,29 @@
* Create a new ACL rule.
*
* @param srcIp source IP address
+ * @param srcMac source Mac address
+ * @param dstMac destination Mac address
* @param dstIp destination IP address
* @param ipProto IP protocol
+ * @param dscp IP dscp
* @param dstTpPort destination transport layer port
+ * @param srcTpPort source transport layer port
* @param action ACL rule's action
*/
- private AclRule(Ip4Prefix srcIp, Ip4Prefix dstIp, byte ipProto,
- short dstTpPort, Action action) {
+ private AclRule(MacAddress srcMac, MacAddress dstMac, Ip4Prefix srcIp, Ip4Prefix dstIp, byte ipProto,
+ byte dscp, short dstTpPort, short srcTpPort, Action action) {
synchronized (ID_GENERATOR_LOCK) {
checkState(idGenerator != null, "Id generator is not bound.");
this.id = RuleId.valueOf(idGenerator.getNewId());
}
+ this.srcMac = srcMac;
+ this.dstMac = dstMac;
this.srcIp = srcIp;
this.dstIp = dstIp;
this.ipProto = ipProto;
+ this.dscp = dscp;
this.dstTpPort = dstTpPort;
+ this.srcTpPort = srcTpPort;
this.action = action;
}
@@ -119,7 +136,11 @@
*/
public boolean checkMatch(AclRule r) {
return (this.dstTpPort == r.dstTpPort || r.dstTpPort == 0)
+ && (this.srcTpPort == r.srcTpPort || r.srcTpPort == 0)
&& (this.ipProto == r.ipProto || r.ipProto == 0)
+ && (this.dscp == r.dscp || r.dscp == 0)
+ && (this.srcMac == r.srcMac || r.srcMac == null)
+ && (this.dstMac == r.dstMac || r.dstMac == null)
&& (checkCidrInCidr(this.srcIp(), r.srcIp()))
&& (checkCidrInCidr(this.dstIp(), r.dstIp()));
}
@@ -140,8 +161,12 @@
private Ip4Prefix srcIp = null;
private Ip4Prefix dstIp = null;
+ private MacAddress srcMac = null;
+ private MacAddress dstMac = null;
private byte ipProto = 0;
+ private byte dscp = 0;
private short dstTpPort = 0;
+ private short srcTpPort = 0;
private Action action = Action.DENY;
private Builder() {
@@ -149,6 +174,28 @@
}
/**
+ * Sets the source Mac address for the ACL rule that will be built.
+ *
+ * @param srcMac source Mac address to use for built ACL rule
+ * @return this builder
+ */
+ public Builder srcMac(MacAddress srcMac) {
+ this.srcMac = srcMac;
+ return this;
+ }
+
+ /**
+ * Sets the destination Mac address for the ACL rule that will be built.
+ *
+ * @param dstMac destination Mac address to use for built ACL rule
+ * @return this builder
+ */
+ public Builder dstMac(MacAddress dstMac) {
+ this.dstMac = dstMac;
+ return this;
+ }
+
+ /**
* Sets the source IP address for the ACL rule that will be built.
*
* @param srcIp source IP address to use for built ACL rule
@@ -181,6 +228,18 @@
return this;
}
+
+ /**
+ * Sets the IP dscp for the ACL rule that will be built.
+ *
+ * @param dscp IP dscp to use for built ACL rule
+ * @return this builder
+ */
+ public Builder dscp(byte dscp) {
+ this.dscp = dscp;
+ return this;
+ }
+
/**
* Sets the destination transport layer port for the ACL rule that will be built.
*
@@ -195,6 +254,19 @@
}
/**
+ * Sets the source transport layer port for the ACL rule that will be built.
+ *
+ * @param srcTpPort destination transport layer port to use for built ACL rule
+ * @return this builder
+ */
+ public Builder srcTpPort(short srcTpPort) {
+ if ((ipProto == IPv4.PROTOCOL_TCP || ipProto == IPv4.PROTOCOL_UDP)) {
+ this.srcTpPort = srcTpPort;
+ }
+ return this;
+ }
+
+ /**
* Sets the action for the ACL rule that will be built.
*
* @param action action to use for built ACL rule
@@ -215,7 +287,7 @@
checkState(ipProto == 0 || ipProto == IPv4.PROTOCOL_ICMP
|| ipProto == IPv4.PROTOCOL_TCP || ipProto == IPv4.PROTOCOL_UDP,
"ipProto must be assigned to TCP, UDP, or ICMP.");
- return new AclRule(srcIp, dstIp, ipProto, dstTpPort, action);
+ return new AclRule(srcMac, dstMac, srcIp, dstIp, ipProto, dscp, dstTpPort, srcTpPort, action);
}
}
@@ -238,6 +310,14 @@
return id;
}
+ public MacAddress srcMac() {
+ return srcMac;
+ }
+
+ public MacAddress dstMac() {
+ return dstMac;
+ }
+
public Ip4Prefix srcIp() {
return srcIp;
}
@@ -250,17 +330,26 @@
return ipProto;
}
+ public byte dscp() {
+ return dscp;
+ }
+
public short dstTpPort() {
return dstTpPort;
}
+ public short srcTpPort() {
+ return srcTpPort;
+ }
+
public Action action() {
return action;
}
@Override
public int hashCode() {
- return Objects.hash(action, id.fingerprint(), ipProto, srcIp, dstIp, dstTpPort);
+ return Objects.hash(action, id.fingerprint(), srcMac, dstMac, ipProto, dscp,
+ srcIp, dstIp, dstTpPort, srcTpPort);
}
@Override
@@ -271,10 +360,14 @@
if (obj instanceof AclRule) {
AclRule that = (AclRule) obj;
return Objects.equals(id, that.id) &&
+ Objects.equals(srcMac, that.srcMac) &&
+ Objects.equals(dstMac, that.dstMac) &&
Objects.equals(srcIp, that.srcIp) &&
Objects.equals(dstIp, that.dstIp) &&
Objects.equals(ipProto, that.ipProto) &&
+ Objects.equals(dscp, that.dscp) &&
Objects.equals(dstTpPort, that.dstTpPort) &&
+ Objects.equals(srcTpPort, that.srcTpPort) &&
Objects.equals(action, that.action);
}
return false;
@@ -285,10 +378,14 @@
return MoreObjects.toStringHelper(this)
.omitNullValues()
.add("id", id)
+ .add("srcMac", srcMac)
+ .add("dstMac", dstMac)
.add("srcIp", srcIp)
.add("dstIp", dstIp)
.add("ipProto", ipProto)
+ .add("dscp", dscp)
.add("dstTpPort", dstTpPort)
+ .add("srcTpPort", srcTpPort)
.add("action", action)
.toString();
}
diff --git a/apps/acl/src/main/java/org/onosproject/acl/AclWebResource.java b/apps/acl/src/main/java/org/onosproject/acl/AclWebResource.java
index 0cda20b..74b572c 100644
--- a/apps/acl/src/main/java/org/onosproject/acl/AclWebResource.java
+++ b/apps/acl/src/main/java/org/onosproject/acl/AclWebResource.java
@@ -26,6 +26,7 @@
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.onlab.packet.IPv4;
import org.onlab.packet.Ip4Prefix;
+import org.onlab.packet.MacAddress;
import org.onosproject.rest.AbstractWebResource;
import javax.ws.rs.Consumes;
@@ -65,12 +66,21 @@
for (AclRule rule : rules) {
ObjectNode node = mapper.createObjectNode();
node.put("id", rule.id().toString());
+ if (rule.srcMac() != null) {
+ node.put("srcMac", rule.srcMac().toString());
+ }
+ if (rule.dstMac() != null) {
+ node.put("dstMac", rule.dstMac().toString());
+ }
if (rule.srcIp() != null) {
node.put("srcIp", rule.srcIp().toString());
}
if (rule.dstIp() != null) {
node.put("dstIp", rule.dstIp().toString());
}
+ if (rule.dscp() != 0) {
+ node.put("dscp", rule.dscp());
+ }
if (rule.ipProto() != 0) {
switch (rule.ipProto()) {
case IPv4.PROTOCOL_ICMP:
@@ -89,6 +99,9 @@
if (rule.dstTpPort() != 0) {
node.put("dstTpPort", rule.dstTpPort());
}
+ if (rule.srcTpPort() != 0) {
+ node.put("srcTpPort", rule.srcTpPort());
+ }
node.put("action", rule.action().toString());
arrayNode.add(node);
}
@@ -160,6 +173,21 @@
rule.dstIp(Ip4Prefix.valueOf(s));
}
+ s = node.path("srcMac").asText(null);
+ if (s != null) {
+ rule.srcMac(MacAddress.valueOf(s));
+ }
+
+ s = node.path("dstMac").asText(null);
+ if (s != null) {
+ rule.dstMac(MacAddress.valueOf(s));
+ }
+
+ s = node.path("dscp").asText(null);
+ if (s != null) {
+ rule.dscp(Byte.valueOf(s));
+ }
+
s = node.path("ipProto").asText(null);
if (s != null) {
if ("TCP".equalsIgnoreCase(s)) {
@@ -178,6 +206,11 @@
rule.dstTpPort((short) port);
}
+ port = node.path("srcTpPort").asInt(0);
+ if (port > 0) {
+ rule.srcTpPort((short) port);
+ }
+
s = node.path("action").asText(null);
if (s != null) {
if ("allow".equalsIgnoreCase(s)) {
diff --git a/apps/acl/src/main/java/org/onosproject/acl/impl/AclManager.java b/apps/acl/src/main/java/org/onosproject/acl/impl/AclManager.java
index 2c735f2..3b8617e 100644
--- a/apps/acl/src/main/java/org/onosproject/acl/impl/AclManager.java
+++ b/apps/acl/src/main/java/org/onosproject/acl/impl/AclManager.java
@@ -265,6 +265,14 @@
TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
FlowEntry.Builder flowEntry = DefaultFlowEntry.builder();
+ if (rule.srcMac() != null) {
+ selectorBuilder.matchEthSrc(rule.srcMac());
+
+ }
+ if (rule.dstMac() != null) {
+ selectorBuilder.matchEthDst(rule.dstMac());
+ }
+
selectorBuilder.matchEthType(Ethernet.TYPE_IPV4);
if (rule.srcIp() != null) {
selectorBuilder.matchIPSrc(rule.srcIp());
@@ -277,6 +285,9 @@
if (rule.ipProto() != 0) {
selectorBuilder.matchIPProtocol(Integer.valueOf(rule.ipProto()).byteValue());
}
+ if (rule.dscp() != 0) {
+ selectorBuilder.matchIPDscp(Byte.valueOf(rule.dscp()));
+ }
if (rule.dstTpPort() != 0) {
switch (rule.ipProto()) {
case IPv4.PROTOCOL_TCP:
@@ -289,6 +300,20 @@
break;
}
}
+
+ if (rule.srcTpPort() != 0) {
+ switch (rule.ipProto()) {
+ case IPv4.PROTOCOL_TCP:
+ selectorBuilder.matchTcpSrc(TpPort.tpPort(rule.srcTpPort()));
+ break;
+ case IPv4.PROTOCOL_UDP:
+ selectorBuilder.matchUdpSrc(TpPort.tpPort(rule.srcTpPort()));
+ break;
+ default:
+ break;
+ }
+ }
+
if (rule.action() == AclRule.Action.ALLOW) {
treatment.add(Instructions.createOutput(PortNumber.CONTROLLER));
}