</root>
<!-- Base log level -->
+ <logger name="org.opendaylight" level="INFO"/>
+
+ <!-- Controller log level -->
<logger name="org.opendaylight.controller" level="INFO"/>
<!-- OSGi logging bridge -->
<logger name="audit" level="INFO" additivity="false">
<appender-ref ref="audit-file"/>
</logger>
-</configuration>
\ No newline at end of file
+</configuration>
#!/bin/bash
-[[ -z ${JAVA_HOME} ]] && echo "Need to set JAVA_HOME environment variable" && exit -1;
-[[ ! -x ${JAVA_HOME}/bin/java ]] && echo "Cannot find an executable \
-JVM at path ${JAVA_HOME}/bin/java check your JAVA_HOME" && exit -1;
-
platform='unknown'
unamestr=`uname`
if [[ "$unamestr" == 'Linux' ]]; then
PHYS_DIR=`pwd -P`
RESULT=$PHYS_DIR/$TARGET_FILE
fullpath=$RESULT
+
+ [[ -z ${JAVA_HOME} ]] && [[ -x "/usr/libexec/java_home" ]] && export JAVA_HOME=`/usr/libexec/java_home -v 1.7`;
+
fi
+[[ -z ${JAVA_HOME} ]] && echo "Need to set JAVA_HOME environment variable" && exit -1;
+[[ ! -x ${JAVA_HOME}/bin/java ]] && echo "Cannot find an executable \
+JVM at path ${JAVA_HOME}/bin/java check your JAVA_HOME" && exit -1;
+
basedir=`dirname ${fullpath}`
function usage {
public FlowEntry mergeWith(ContainerFlow containerFlow) {
Match myMatch = flow.getMatch();
- // Based on this flow direction, rearrange the match
- Match match = containerFlow.getMatch();
+ Match filter = containerFlow.getMatch();
// Merge
- myMatch.mergeWithFilter(match);
+ Match merge = myMatch.mergeWithFilter(filter);
// Replace this Flow's match with merged version
- flow.setMatch(myMatch);
+ flow.setMatch(merge);
return this;
}
.append("dstNodeConnector",
nodeConnectorType_2 + "|" + nodeConnectorId_2 + "@" + nodeType_2 + "|" + nodeId_2);
// execute HTTP request and verify response code
- result = getJsonResult(baseURL + "/userLink", "POST", jo.toString());
+ result = getJsonResult(baseURL + "/user-link", "POST", jo.toString());
Assert.assertTrue(httpResponseCode == 201);
// === test GET method for getUserLinks()
- result = getJsonResult(baseURL + "/userLink", "GET");
+ result = getJsonResult(baseURL + "/user-link", "GET");
Assert.assertTrue(httpResponseCode == 200);
if (debugMsg) {
System.out.println("result:" + result);
// === test DELETE method for deleteUserLink()
String userName = "userLink_1";
- result = getJsonResult(baseURL + "/userLink/" + userName, "DELETE");
+ result = getJsonResult(baseURL + "/user-link/" + userName, "DELETE");
Assert.assertTrue(httpResponseCode == 200);
// execute another getUserLinks() request to verify that userLink_1 is
// removed
- result = getJsonResult(baseURL + "/userLink", "GET");
+ result = getJsonResult(baseURL + "/user-link", "GET");
Assert.assertTrue(httpResponseCode == 200);
if (debugMsg) {
System.out.println("result:" + result);
* Retrieve the Topology
*
* @param containerName
- * The container for which we want to retrieve the topology
+ * The container for which we want to retrieve the topology (Eg. 'default')
*
* @return A List of EdgeProps each EdgeProp represent an Edge of the grap
* with the corresponding properties attached to it.
+ *
+ * <pre>
+ *
+ * Example:
+ *
+ * RequestURL:
+ * http://localhost:8080/controller/nb/v2/topology/default
+ *
+ * Response in XML:
+ * <?xml version="1.0" encoding="UTF-8" standalone="yes"?><topology><edgeProperties><edge><tailNodeConnector id="2" type="OF"><node id="00:00:00:00:00:00:00:02" type="OF"/></tailNodeConnector><headNodeConnector id="2" type="OF"><node id="00:00:00:00:00:00:00:51" type="OF"/></headNodeConnector></edge><properties><state><value>1</value></state><config><value>1</value></config><name><value>C1_2-L2_2</value></name><timeStamp><value>1377279422032</value><name>creation</name></timeStamp></properties></edgeProperties><edgeProperties><edge><tailNodeConnector id="2" type="OF"><node id="00:00:00:00:00:00:00:51" type="OF"/></tailNodeConnector><headNodeConnector id="2" type="OF"><node id="00:00:00:00:00:00:00:02" type="OF"/></headNodeConnector></edge><properties><state><value>1</value></state><name><value>L2_2-C1_2</value></name><config><value>1</value></config><timeStamp><value>1377279423564</value><name>creation</name></timeStamp></properties></edgeProperties></topology>
+ *
+ * Response in JSON:
+ * {"edgeProperties":[{"edge":{"tailNodeConnector":{"@id":"2","@type":"OF","node":{"@id":"00:00:00:00:00:00:00:02","@type":"OF"}},"headNodeConnector":{"@id":"2","@type":"OF","node":{"@id":"00:00:00:00:00:00:00:51","@type":"OF"}}},"properties":{"timeStamp":{"value":"1377278961017","name":"creation"}}},{"edge":{"tailNodeConnector":{"@id":"2","@type":"OF","node":{"@id":"00:00:00:00:00:00:00:51","@type":"OF"}},"headNodeConnector":{"@id":"2","@type":"OF","node":{"@id":"00:00:00:00:00:00:00:02","@type":"OF"}}},"properties":{"timeStamp":{"value":"1377278961018","name":"creation"}}}]}
+ *
+ * </pre>
*/
@Path("/{containerName}")
@GET
@Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
@TypeHint(Topology.class)
- @StatusCodes({ @ResponseCode(code = 404, condition = "The Container Name passed was not found") })
+ @StatusCodes({ @ResponseCode(code = 404, condition = "The Container Name was not found") })
public Topology getTopology(@PathParam("containerName") String containerName) {
if (!NorthboundUtils.isAuthorized(
* Retrieve the user configured links
*
* @param containerName
- * The container for which we want to retrieve the user links
+ * The container for which we want to retrieve the user links (Eg. 'default')
*
* @return A List of user configured links
+ *
+ * <pre>
+ *
+ * Example:
+ *
+ * RequestURL:
+ * http://localhost:8080/controller/nb/v2/topology/default/user-link
+ *
+ * Response in XML:
+ * <?xml version="1.0" encoding="UTF-8" standalone="yes"?><topologyUserLinks><userLinks><status>Success</status><name>link1</name><srcNodeConnector>OF|2@OF|00:00:00:00:00:00:00:02</srcNodeConnector><dstNodeConnector>OF|2@OF|00:00:00:00:00:00:00:51</dstNodeConnector></userLinks></topologyUserLinks>
+ *
+ * Response in JSON:
+ * {"userLinks":{"status":"Success","name":"link1","srcNodeConnector":"OF|2@OF|00:00:00:00:00:00:00:02","dstNodeConnector":"OF|2@OF|00:00:00:00:00:00:00:51"}}
+ *
+ * </pre>
*/
- @Path("/{containerName}/userLink")
+ @Path("/{containerName}/user-link")
@GET
@Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
@TypeHint(TopologyUserLinks.class)
- @StatusCodes({ @ResponseCode(code = 404, condition = "The Container Name passed was not found") })
+ @StatusCodes({ @ResponseCode(code = 404, condition = "The Container Name was not found") })
public TopologyUserLinks getUserLinks(
@PathParam("containerName") String containerName) {
* Add an User Link
*
* @param containerName
- * Name of the Container. The base Container is "default".
+ * Name of the Container (Eg. 'default')
* @param TopologyUserLinkConfig
* in JSON or XML format
* @return Response as dictated by the HTTP Response Status code
+ *
+ * <pre>
+ *
+ * Example:
+ *
+ * RequestURL:
+ * http://localhost:8080/controller/nb/v2/topology/default/user-link/config1-content
+ *
+ * Request in XML:
+ * <?xml version="1.0" encoding="UTF-8" standalone="yes"?><topologyUserLinks><status>Success</status><name>link1</name><srcNodeConnector>OF|2@OF|00:00:00:00:00:00:00:02</srcNodeConnector><dstNodeConnector>OF|2@OF|00:00:00:00:00:00:00:51</dstNodeConnector></topologyUserLinks>
+ *
+ * Request in JSON:
+ * {"status":"Success","name":"link1","srcNodeConnector":"OF|2@OF|00:00:00:00:00:00:00:02","dstNodeConnector":"OF|2@OF|00:00:00:00:00:00:00:51"}
+ *
+ * </pre>
*/
-
- @Path("/{containerName}/userLink")
+ @Path("/{containerName}/user-link")
@POST
@Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
+ @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
@StatusCodes({
@ResponseCode(code = 201, condition = "User Link added successfully"),
- @ResponseCode(code = 404, condition = "The Container Name passed was not found"),
+ @ResponseCode(code = 404, condition = "The Container Name was not found"),
@ResponseCode(code = 409, condition = "Failed to add User Link due to Conflicting Name"),
@ResponseCode(code = 500, condition = "Failed to add User Link. Failure Reason included in HTTP Error response"),
@ResponseCode(code = 503, condition = "One or more of Controller services are unavailable") })
* Delete an User Link
*
* @param containerName
- * Name of the Container. The base Container is "default".
+ * Name of the Container (Eg. 'default')
* @param name
- * Name of the Link Configuration
+ * Name of the Link Configuration (Eg. 'config1')
* @return Response as dictated by the HTTP Response Status code
+ *
+ * <pre>
+ *
+ * Example:
+ *
+ * RequestURL:
+ * http://localhost:8080/controller/nb/v2/topology/default/user-link/config1
+ *
+ * </pre>
*/
-
- @Path("/{containerName}/userLink/{name}")
+ @Path("/{containerName}/user-link/{name}")
@DELETE
@Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
+ @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
@StatusCodes({
@ResponseCode(code = 200, condition = "Operation successful"),
@ResponseCode(code = 404, condition = "The Container Name or Link Configuration Name was not found"),
}
throw new ResourceNotFoundException(ret.getDescription());
}
-
}
/**
* Check whether the current match conflicts with the passed filter match
* This match conflicts with the filter if for at least a MatchType defined
- * in the filter match, the respective MatchFields differ or are not compatible
+ * in the filter match, the respective MatchFields differ or are not
+ * compatible
+ *
+ * In other words the function returns true if the set of packets described
+ * by one match and the set of packets described by the other match are
+ * disjoint. Equivalently, if the intersection of the two sets of packets
+ * described by the two matches is an empty.
*
* For example, Let's suppose the filter has the following MatchFields:
* DL_TYPE = 0x800
- * NW_DST = 172.20.30.110/24
+ * NW_DST = 172.20.30.110/24
*
* while this match has the following MatchFields:
+ * DL_TYPE = 0x800
* NW_DST = 172.20.30.45/24
* TP_DST = 80
*
- * Then the function would return false as the two Match are not conflicting
+ * Then the function would return false as the two Match are not
+ * conflicting.
*
- * Note: the mask value is taken into account only for MatchType.NW_SRC and MatchType.NW_DST
+ * Note: the mask value is taken into account only for MatchType.NW_SRC and
+ * MatchType.NW_DST
*
- * @param match the MAtch describing the filter
- * @return true if the match is conflicting with the filter, false otherwise
+ * @param match
+ * the Match describing the filter
+ * @return true if the set of packets described by one match and the set of
+ * packets described by the other match are disjoint, false
+ * otherwise
*/
public boolean conflictWithFilter(Match filter) {
- // Iterate through the MatchType defined in the filter
- for (MatchType type : filter.getMatchesList()) {
+ return !this.intersetcs(filter);
+ }
+
+ /**
+ * Merge the current Match fields with the fields of the filter Match. A
+ * check is first run to see if this Match is compatible with the filter
+ * Match. If it is not, the merge is not attempted.
+ *
+ * The result is the match object representing the intersection of the set
+ * of packets described by this match with the set of packets described by
+ * the filter match. If the intersection of the two sets is empty, the
+ * return match will be null.
+ *
+ * @param filter
+ * the match with which attempting the merge
+ * @return a new Match object describing the set of packets represented by
+ * the intersection of this and the filter matches. null if the
+ * intersection is empty.
+ */
+ public Match mergeWithFilter(Match filter) {
+ return this.getIntersection(filter);
+ }
+
+ /**
+ * Return the match representing the intersection of the set of packets
+ * described by this match with the set of packets described by the other
+ * match. Such as m.getIntersection(m) == m, m.getIntersection(u) == m and
+ * m.getIntersection(o) == o where u is an empty match (universal set, all
+ * packets) and o is the null match (empty set).
+ *
+ * @param other
+ * the match with which computing the intersection
+ * @return a new Match object representing the intersection of the set of
+ * packets described by this match with the set of packets described
+ * by the other match. null when the intersection is the empty set.
+ */
+ public Match getIntersection(Match other) {
+ // If no intersection, return the empty set
+ if (!this.intersetcs(other)) {
+ return null;
+ }
+ // Check if any of the two is the universal match
+ if (this.getMatches() == 0) {
+ return other.clone();
+ }
+ if (other.getMatches() == 0) {
+ return this.clone();
+ }
+ // Derive the intersection
+ Match intersection = new Match();
+ for (MatchType type : MatchType.values()) {
+ if (this.isAny(type) && other.isAny(type)) {
+ continue;
+ }
if (this.isAny(type)) {
+ intersection.setField(other.getField(type).clone());
+ continue;
+ } else if (other.isAny(type)) {
+ intersection.setField(this.getField(type).clone());
+ continue;
+ }
+ // Either they are equal or it is about IP address
+ switch (type) {
+ // When it is about IP address, take the wider prefix address
+ // between the twos
+ case NW_SRC:
+ case NW_DST:
+ MatchField thisField = this.getField(type);
+ MatchField otherField = other.getField(type);
+ InetAddress thisAddress = (InetAddress) thisField.getValue();
+ InetAddress otherAddress = (InetAddress) otherField.getValue();
+ InetAddress thisMask = (InetAddress) thisField.getMask();
+ InetAddress otherMask = (InetAddress) otherField.getMask();
+
+ int thisMaskLen = (thisMask == null) ? ((thisAddress instanceof Inet4Address) ? 32 : 128) : NetUtils
+ .getSubnetMaskLength(thisMask);
+ int otherMaskLen = (otherMask == null) ? ((otherAddress instanceof Inet4Address) ? 32 : 128) : NetUtils
+ .getSubnetMaskLength(otherMask);
+ if (otherMaskLen < thisMaskLen) {
+ intersection.setField(new MatchField(type, NetUtils.getSubnetPrefix(otherAddress, otherMaskLen),
+ otherMask));
+ } else {
+ intersection.setField(new MatchField(type, NetUtils.getSubnetPrefix(thisAddress, thisMaskLen),
+ thisMask));
+ }
+ break;
+ default:
+ // this and other match field are equal for this type, pick this
+ // match field
+ intersection.setField(this.getField(type).clone());
+ }
+ }
+ return intersection;
+ }
+
+ /**
+ * Checks whether the intersection of the set of packets described by this
+ * match with the set of packets described by the other match is non empty
+ *
+ * For example, if this match is: DL_SRC = 00:cc:bb:aa:11:22
+ *
+ * and the other match is: DL_TYPE = 0x800 NW_SRC = 1.2.3.4
+ *
+ * then their respective matching packets set intersection is non empty:
+ * DL_SRC = 00:cc:bb:aa:11:22 DL_TYPE = 0x800 NW_SRC = 1.2.3.4
+ *
+ * @param other
+ * the other match with which testing the intersection
+ * @return true if the intersection of the respective matching packets sets
+ * is non empty
+ */
+ public boolean intersetcs(Match other) {
+ // No intersection with the empty set
+ if (other == null) {
+ return false;
+ }
+ // Always intersection with the universal set
+ if (this.getMatches() == 0 || other.getMatches() == 0) {
+ return true;
+ }
+ // Iterate through the MatchType defined in the filter
+ for (MatchType type : MatchType.values()) {
+ if (this.isAny(type) || other.isAny(type)) {
continue;
}
MatchField thisField = this.getField(type);
- MatchField filterField = filter.getField(type);
+ MatchField otherField = other.getField(type);
switch (type) {
case DL_SRC:
case DL_DST:
- if (Arrays.equals((byte[]) thisField.getValue(),
- (byte[]) filterField.getValue())) {
+ if (!Arrays.equals((byte[]) thisField.getValue(), (byte[]) otherField.getValue())) {
return false;
}
break;
case NW_SRC:
case NW_DST:
InetAddress thisAddress = (InetAddress) thisField.getValue();
- InetAddress filterAddress = (InetAddress) filterField
- .getValue();
+ InetAddress otherAddress = (InetAddress) otherField.getValue();
// Validity check
- if (thisAddress instanceof Inet4Address
- && filterAddress instanceof Inet6Address
- || thisAddress instanceof Inet6Address
- && filterAddress instanceof Inet4Address) {
- return true;
+ if (thisAddress instanceof Inet4Address && otherAddress instanceof Inet6Address
+ || thisAddress instanceof Inet6Address && otherAddress instanceof Inet4Address) {
+ return false;
}
InetAddress thisMask = (InetAddress) thisField.getMask();
- InetAddress filterMask = (InetAddress) filterField.getMask();
- // thisAddress has to be in same subnet of filterAddress
- if (NetUtils.inetAddressConflict(thisAddress, filterAddress,
- thisMask, filterMask)) {
- return true;
+ InetAddress otherMask = (InetAddress) otherField.getMask();
+ if (NetUtils.inetAddressConflict(thisAddress, otherAddress, thisMask, otherMask)
+ && NetUtils.inetAddressConflict(otherAddress, thisAddress, otherMask, thisMask)) {
+ return false;
}
break;
default:
- if (!thisField.getValue().equals(filterField.getValue())) {
- return true;
- }
- }
- //TODO: check v4 v6 incompatibility
- }
- return false;
- }
-
- /**
- * Merge the current Match fields with the fields of the filter Match
- * A check is first run to see if this Match is compatible with the
- * filter Match. If it is not, the merge is not attempted.
- *
- *
- * @param filter
- * @return
- */
- public Match mergeWithFilter(Match filter) {
- if (!this.conflictWithFilter(filter)) {
- /*
- * No conflict with the filter
- * We can copy over the fields which this match does not have
- */
- for (MatchType type : filter.getMatchesList()) {
- if (this.isAny(type)) {
- this.setField(filter.getField(type).clone());
+ if (!thisField.getValue().equals(otherField.getValue())) {
+ return false;
}
}
}
- return this;
+ return true;
}
@Override
@Override
public String toString() {
- return type + "(" + getValueString() + "," + getMaskString() + ")";
+ return (mask == null) ? String.format("%s(%s)", getTypeString(), getValueString()) :
+ String.format("%s(%s,%s)", getTypeString(), getValueString(), getMaskString());
}
@Override
* Checks if the test address and mask conflicts with the filter address and
* mask
*
- * For example: testAddress: 172.28.2.23 testMask: 255.255.255.0
- * filtAddress: 172.28.1.10 testMask: 255.255.255.0 conflict
+ * For example:
+ * testAddress: 172.28.2.23
+ * testMask: 255.255.255.0
+ * filterAddress: 172.28.1.10
+ * testMask: 255.255.255.0
+ * do conflict
*
- * testAddress: 172.28.2.23 testMask: 255.255.255.0 filtAddress: 172.28.1.10
- * testMask: 255.255.0.0 do not conflict
+ * testAddress: 172.28.2.23
+ * testMask: 255.255.255.0
+ * filterAddress: 172.28.1.10
+ * testMask: 255.255.0.0
+ * do not conflict
*
* Null parameters are permitted
*
int testMaskLen = (testMask == null) ? ((testAddress instanceof Inet4Address) ? 32 : 128) : NetUtils
.getSubnetMaskLength(testMask);
- int filterMaskLen = NetUtils.getSubnetMaskLength(filterMask);
+ int filterMaskLen = (filterMask == null) ? ((testAddress instanceof Inet4Address) ? 32 : 128) : NetUtils
+ .getSubnetMaskLength(filterMask);
// Mask length check. Test mask has to be more specific than filter one
if (testMaskLen < filterMaskLen) {
/*
* Following utilities are useful when you need to compare or bit shift java
- * primitive type variable which are inerently signed
+ * primitive type variable which are inherently signed
*/
/**
* Returns the unsigned value of the passed byte variable
Assert.assertTrue(field.getValue().equals(new Short(vlan)));
Assert.assertTrue(field.isValid());
}
+
+ @Test
+ public void testIntersection() throws UnknownHostException {
+ Short ethType = Short.valueOf((short)0x800);
+ InetAddress ip1 = InetAddress.getByName("1.1.1.1");
+ InetAddress ip2 = InetAddress.getByName("1.1.1.0");
+ InetAddress ipm2 = InetAddress.getByName("255.255.255.0");
+ InetAddress ip3 = InetAddress.getByName("1.3.0.0");
+ InetAddress ipm3 = InetAddress.getByName("255.255.0.0");
+
+ Match m1 = new Match();
+ m1.setField(MatchType.DL_TYPE, ethType);
+ m1.setField(MatchType.NW_SRC, ip1);
+
+ Match m2 = new Match();
+ m2.setField(MatchType.DL_TYPE, ethType);
+ m2.setField(MatchType.NW_SRC, ip2, ipm2);
+
+ Match m3 = new Match();
+ m3.setField(MatchType.DL_TYPE, ethType);
+ m3.setField(MatchType.NW_SRC, ip3, ipm3);
+ m3.setField(MatchType.NW_PROTO, IPProtocols.TCP.byteValue());
+
+ Match m3r = m3.reverse();
+ Assert.assertTrue(m3.intersetcs(m3r));
+
+ Assert.assertTrue(m1.intersetcs(m2));
+ Assert.assertTrue(m2.intersetcs(m1));
+ Assert.assertFalse(m1.intersetcs(m3));
+ Assert.assertTrue(m1.intersetcs(m3r));
+ Assert.assertFalse(m3.intersetcs(m1));
+ Assert.assertTrue(m3.intersetcs(m1.reverse()));
+ Assert.assertFalse(m2.intersetcs(m3));
+ Assert.assertFalse(m3.intersetcs(m2));
+ Assert.assertTrue(m2.intersetcs(m3r));
+
+
+ Match i = m1.getIntersection(m2);
+ Assert.assertTrue(((Short)i.getField(MatchType.DL_TYPE).getValue()).equals(ethType));
+ Assert.assertTrue(((InetAddress)i.getField(MatchType.NW_SRC).getValue()).equals(ip2));
+ Assert.assertTrue(((InetAddress)i.getField(MatchType.NW_SRC).getMask()).equals(ipm2));
+
+ // Empty set
+ i = m2.getIntersection(m3);
+ Assert.assertNull(i);
+
+ Match m4 = new Match();
+ m4.setField(MatchType.DL_TYPE, ethType);
+ m4.setField(MatchType.NW_PROTO, IPProtocols.TCP.byteValue());
+ Assert.assertTrue(m4.intersetcs(m3));
+
+ Match m5 = new Match();
+ m5.setField(MatchType.DL_TYPE, ethType);
+ m3.setField(MatchType.NW_SRC, ip3, ipm3);
+ m5.setField(MatchType.NW_PROTO, IPProtocols.UDP.byteValue());
+ Assert.assertFalse(m5.intersetcs(m3));
+ Assert.assertFalse(m5.intersetcs(m4));
+ Assert.assertTrue(m5.intersetcs(m5));
+ Assert.assertFalse(m3.intersetcs(m5));
+ Assert.assertFalse(m4.intersetcs(m5));
+
+
+ Match i2 = m4.getIntersection(m3);
+ Assert.assertFalse(i2.getMatches() == 0);
+ Assert.assertFalse(i2.getMatchesList().isEmpty());
+ Assert.assertTrue(((InetAddress)i2.getField(MatchType.NW_SRC).getValue()).equals(ip3));
+ Assert.assertTrue(((InetAddress)i2.getField(MatchType.NW_SRC).getMask()).equals(ipm3));
+ Assert.assertTrue(((Byte)i2.getField(MatchType.NW_PROTO).getValue()).equals(IPProtocols.TCP.byteValue()));
+
+ byte src[] = {(byte)0, (byte)0xab,(byte)0xbc,(byte)0xcd,(byte)0xde,(byte)0xef};
+ byte dst[] = {(byte)0x10, (byte)0x11,(byte)0x12,(byte)0x13,(byte)0x14,(byte)0x15};
+ Short srcPort = (short)1024;
+ Short dstPort = (short)80;
+
+ // Check identity
+ Match m6 = new Match();
+ m6.setField(MatchType.DL_SRC, src);
+ m6.setField(MatchType.DL_DST, dst);
+ m6.setField(MatchType.NW_SRC, ip2, ipm2);
+ m6.setField(MatchType.NW_DST, ip3, ipm3);
+ m6.setField(MatchType.NW_PROTO, IPProtocols.UDP.byteValue());
+ m6.setField(MatchType.TP_SRC, srcPort);
+ m6.setField(MatchType.TP_DST, dstPort);
+ Assert.assertTrue(m6.intersetcs(m6));
+ Assert.assertTrue(m6.getIntersection(m6).equals(m6));
+
+ // Empty match, represents the universal set (all packets)
+ Match u = new Match();
+ Assert.assertTrue(m6.getIntersection(u).equals(m6));
+ Assert.assertTrue(u.getIntersection(m6).equals(m6));
+
+ // No intersection with null match, empty set
+ Assert.assertNull(m6.getIntersection(null));
+ }
}
package org.opendaylight.controller.flows.web;
+import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
@RequestMapping(value = "/main")
@ResponseBody
- public Map<String, Object> getFlows(HttpServletRequest request, @RequestParam(required = false) String container) {
- String containerName = (container == null) ? GlobalConstants.DEFAULT.toString() : container;
+ public Map<String, Object> getFlows(HttpServletRequest request,
+ @RequestParam(required = false) String container) {
+ String containerName = (container == null) ? GlobalConstants.DEFAULT
+ .toString() : container;
// Derive the privilege this user has on the current container
String userName = request.getUserPrincipal().getName();
- Privilege privilege = DaylightWebUtil.getContainerPrivilege(userName, containerName, this);
- if (privilege == Privilege.NONE) {
+ Privilege privilege = DaylightWebUtil.getContainerPrivilege(userName,
+ containerName, this);
+ if (privilege == Privilege.NONE) {
return null;
}
flowSet.add(entry);
}
- Map <String, Object> output = new HashMap<String, Object>(2);
+ Map<String, Object> output = new HashMap<String, Object>(2);
output.put("flows", flowSet);
output.put("privilege", privilege);
return output;
@RequestMapping(value = "/node-ports")
@ResponseBody
- public Map<String, Object> getNodePorts(HttpServletRequest request, @RequestParam(required = false) String container) {
- String containerName = (container == null) ? GlobalConstants.DEFAULT.toString() : container;
+ public Map<String, Object> getNodePorts(HttpServletRequest request,
+ @RequestParam(required = false) String container) {
+ String containerName = (container == null) ? GlobalConstants.DEFAULT
+ .toString() : container;
// Derive the privilege this user has on the current container
String userName = request.getUserPrincipal().getName();
- if (DaylightWebUtil.getContainerPrivilege(userName, containerName, this) == Privilege.NONE) {
+ if (DaylightWebUtil
+ .getContainerPrivilege(userName, containerName, this) == Privilege.NONE) {
return null;
}
@RequestMapping(value = "/node-flows")
@ResponseBody
- public Map<String, Object> getNodeFlows(HttpServletRequest request, @RequestParam(required = false) String container) {
- String containerName = (container == null) ? GlobalConstants.DEFAULT.toString() : container;
+ public Map<String, Object> getNodeFlows(HttpServletRequest request,
+ @RequestParam(required = false) String container) {
+ String containerName = (container == null) ? GlobalConstants.DEFAULT
+ .toString() : container;
// Derive the privilege this user has on the current container
String userName = request.getUserPrincipal().getName();
- if (DaylightWebUtil.getContainerPrivilege(userName, containerName, this) == Privilege.NONE) {
+ if (DaylightWebUtil
+ .getContainerPrivilege(userName, containerName, this) == Privilege.NONE) {
return null;
}
List<FlowConfig> flows = frm.getStaticFlows(node);
String nodeDesc = node.toString();
- SwitchConfig config = switchManager.getSwitchConfig(node
- .toString());
- if ((config != null) && (config.getProperty(Description.propertyName) != null)) {
- nodeDesc = ((Description) config.getProperty(Description.propertyName)).getValue();
+ SwitchConfig config = switchManager
+ .getSwitchConfig(node.toString());
+ if ((config != null)
+ && (config.getProperty(Description.propertyName) != null)) {
+ nodeDesc = ((Description) config
+ .getProperty(Description.propertyName)).getValue();
}
nodes.put(nodeDesc, flows.size());
public String actionFlow(@RequestParam(required = true) String action,
@RequestParam(required = false) String body,
@RequestParam(required = true) String nodeId,
- HttpServletRequest request, @RequestParam(required = false) String container) {
- String containerName = (container == null) ? GlobalConstants.DEFAULT.toString() : container;
+ HttpServletRequest request,
+ @RequestParam(required = false) String container) {
+ String containerName = (container == null) ? GlobalConstants.DEFAULT
+ .toString() : container;
// Authorization check
String userName = request.getUserPrincipal().getName();
- if (DaylightWebUtil.getContainerPrivilege(userName, containerName, this) != Privilege.WRITE) {
+ if (DaylightWebUtil
+ .getContainerPrivilege(userName, containerName, this) != Privilege.WRITE) {
return "Operation not authorized";
}
Status result = new Status(StatusCode.BADREQUEST, "Invalid request");
if (action.equals("add")) {
result = frm.addStaticFlow(flow);
- DaylightWebUtil.auditlog("Flow", userName, "added", flow.getName(), containerName);
+ DaylightWebUtil.auditlog("Flow", userName, "added", flow.getName(),
+ containerName);
}
return (result.isSuccess()) ? StatusCode.SUCCESS.toString() : result
public String removeFlow(@PathVariable("nodeId") String nodeId,
@PathVariable("name") String name,
@RequestParam(required = true) String action,
- HttpServletRequest request, @RequestParam(required = false) String container) {
- String containerName = (container == null) ? GlobalConstants.DEFAULT.toString() : container;
+ HttpServletRequest request,
+ @RequestParam(required = false) String container) {
+ String containerName = (container == null) ? GlobalConstants.DEFAULT
+ .toString() : container;
// Authorization check
String userName = request.getUserPrincipal().getName();
- if (DaylightWebUtil.getContainerPrivilege(userName, containerName, this) != Privilege.WRITE) {
+ if (DaylightWebUtil
+ .getContainerPrivilege(userName, containerName, this) != Privilege.WRITE) {
return "Operation not authorized";
}
}
if (action.equals("remove")) {
result = frm.removeStaticFlow(name, node);
- if(result.isSuccess()) {
- DaylightWebUtil.auditlog("Flow", userName, "removed", name, containerName);
+ if (result.isSuccess()) {
+ DaylightWebUtil.auditlog("Flow", userName, "removed", name,
+ containerName);
}
} else if (action.equals("toggle")) {
result = frm.toggleStaticFlowStatus(name, node);
- if(result.isSuccess()) {
- DaylightWebUtil.auditlog("Flow", userName, "toggled", name, containerName);
+ if (result.isSuccess()) {
+ DaylightWebUtil.auditlog("Flow", userName, "toggled", name,
+ containerName);
}
} else {
result = new Status(StatusCode.BADREQUEST, "Unknown action");
.getDescription();
}
+ @SuppressWarnings("unchecked")
+ @RequestMapping(value = "/flow/deleteFlows", method = RequestMethod.POST)
+ @ResponseBody
+ public String removeSelectedFlows(
+ @RequestParam(required = false) String body,
+ HttpServletRequest request,
+ @RequestParam(required = false) String container) {
+ String containerName = (container == null) ? GlobalConstants.DEFAULT
+ .toString() : container;
+
+ // Authorization check
+ String userName = request.getUserPrincipal().getName();
+ if (DaylightWebUtil
+ .getContainerPrivilege(userName, containerName, this) != Privilege.WRITE) {
+ return "Operation not authorized";
+ }
+
+ IForwardingRulesManager frm = (IForwardingRulesManager) ServiceHelper
+ .getInstance(IForwardingRulesManager.class, containerName, this);
+ if (frm == null) {
+ return "Forwarding Rules Manager is not available";
+ }
+
+ Gson gson = new Gson();
+ List<Map<String, String>> flowList = new ArrayList<Map<String, String>>();
+ flowList = gson.fromJson(body, flowList.getClass());
+ Status result = new Status(StatusCode.BADREQUEST, "Invalid request");
+ String status = "";
+ for (Map<String, String> flowEntry : flowList) {
+ Node node = Node.fromString(flowEntry.get("node"));
+ result = frm.removeStaticFlow(flowEntry.get("name"), node);
+ if (result.isSuccess()) {
+ DaylightWebUtil.auditlog("Flow", userName, "removed",
+ flowEntry.get("name"), containerName);
+ } else {
+ status = flowEntry.get("name") + ", " + status;
+ }
+ }
+ if (!status.equals("")) {
+ return "Could not remove "
+ + status.substring(0, status.length() - 2) + " Flow(s)";
+ } else {
+ return "Success";
+ }
+ }
+
private String getNodeDesc(Node node, ISwitchManager switchManager) {
- Description desc = (Description) switchManager.getNodeProp(node, Description.propertyName);
+ Description desc = (Description) switchManager.getNodeProp(node,
+ Description.propertyName);
String description = (desc == null) ? "" : desc.getValue();
- return (description.isEmpty() || description.equalsIgnoreCase("none")) ? node.toString() : description;
+ return (description.isEmpty() || description.equalsIgnoreCase("none")) ? node
+ .toString() : description;
}
}
main : "/main",
flows : "/node-flows",
nodes : "/node-ports",
- flow : "/flow"
+ flow : "/flow",
+ deleteFlows:"/flow/deleteFlows"
}
}
id : {
dashlet : {
add : "one_f_flows_id_dashlet_add",
+ removeMultiple : "one_f_flows_id_dashlet_removeMultiple",
remove : "one_f_flows_id_dashlet_remove",
toggle : "one_f_flows_id_dashlet_toggle",
- datagrid: "one_f_flows_id_dashlet_datagrid"
+ datagrid : "one_f_flows_id_dashlet_datagrid",
+ selectAllFlows : "one_f_flows_id_dashlet_selectAllFlows"
},
modal : {
install : "one_f_flows_id_modal_install",
$modal.modal();
});
$dashlet.append($button);
+ var button = one.lib.dashlet.button.single("Remove Flow Entry", one.f.flows.id.dashlet.removeMultiple, "btn-primary", "btn-mini");
+ var $button = one.lib.dashlet.button.button(button);
+
+ $button.click(function() {
+ var checkedCheckBoxes = $('.flowEntry[type=checkbox]:checked');
+
+ var requestData = [];
+
+ var resource = {};
+ checkedCheckBoxes.each(function(index, value) {
+ var flowEntry = {};
+ flowEntry['name'] = checkedCheckBoxes[index].name;
+ flowEntry['node'] = checkedCheckBoxes[index].getAttribute("node");
+ requestData.push(flowEntry);
+ });
+ resource['body'] = JSON.stringify(requestData);
+
+ $.post(one.f.address.root+one.f.address.flows.deleteFlows, resource, function(response) {
+ if(response == "Success") {
+ one.lib.alert("Flow(s) successfully removed");
+ } else {
+ one.lib.alert(response);
+ }
+ one.main.dashlet.right.bottom.empty();
+ one.f.detail.dashlet(one.main.dashlet.right.bottom);
+ one.main.dashlet.left.top.empty();
+ one.f.flows.dashlet(one.main.dashlet.left.top);
+ });
+ });
+ $dashlet.append($button);
}
$dashlet.append($gridHTML);
var dataSource = one.f.flows.data.flowsDataGrid(data);
$("#" + one.f.flows.id.dashlet.datagrid).datagrid({dataSource: dataSource}).on("loaded", function() {
- $("#" + one.f.flows.id.dashlet.datagrid).find("tbody tr").each(function(index, tr) {
+ $("#"+one.f.flows.id.dashlet.datagrid.selectAllFlows).click(function() {
+ $("#" + one.f.flows.id.dashlet.datagrid).find(':checkbox').prop('checked',
+ $("#"+one.f.flows.id.dashlet.datagrid.selectAllFlows).is(':checked'));
+ });
+
+ $("#" + one.f.flows.id.dashlet.datagrid).find("tbody tr").each(function(index, tr) {
$tr = $(tr);
$span = $("td span", $tr);
var flowstatus = $span.data("flowstatus");
});
// attach click event
$tr.click(function() {
- var $td = $($(this).find("td")[0]);
+ var $td = $($(this).find("td")[1]);
var id = $td.text();
var node = $td.find("span").data("nodeid");
- one.f.flows.detail(id, node);
+ one.f.flows.detail(id, node);
+ });
+ $(".flowEntry").click(function(){
+ if (!$('.flowEntry[type=checkbox]:not(:checked)').length) {
+ $("#"+one.f.flows.id.dashlet.datagrid.selectAllFlows)
+ .prop("checked",
+ true);
+ } else {
+ $("#"+one.f.flows.id.dashlet.datagrid.selectAllFlows)
+ .prop("checked",
+ false);
+ }
+ event.stopPropagation();
});
});
});
flowsDataGrid: function(data) {
var source = new StaticDataSource({
columns: [
+ {
+ property: 'selector',
+ label: "<input type='checkbox' id='"+one.f.flows.id.dashlet.datagrid.selectAllFlows+"'/>",
+ sortable: false
+ },
{
property: 'name',
label: 'Flow Name',
data: data.flows,
formatter: function(items) {
$.each(items, function(index, item) {
- item["name"] = '<span data-installInHw=' + item["flow"]["installInHw"] +
+ var $checkbox = document.createElement("input");
+ $checkbox.setAttribute("type", "checkbox");
+ $checkbox.setAttribute("name", item.name);
+ $checkbox.setAttribute("node", item.node);
+ $checkbox.setAttribute('class','flowEntry')
+ item.selector = $checkbox.outerHTML;
+ item["name"] = '<span data-installInHw=' + item["flow"]["installInHw"] +
' data-flowstatus=' + item["flow"]["status"] +
' data-nodeId=' + item["nodeId"] + '>' + item["name"] + '</span>';
});
$(data).each(function(index, value) {
var tr = {};
var entry = [];
+
+
entry.push(value['name']);
entry.push(value['node']);
if (value['flow']['installInHw'] == 'true' && value['flow']['status'] == 'Success')
var $table = one.lib.dashlet.table.table(attributes);
var headers = ['Flow Name', 'Node'];
+
var $thead = one.lib.dashlet.table.header(headers);
$table.append($thead);
var $tbody = one.lib.dashlet.table.body(body);
$table.append($tbody);
-
return $table;
}
}
List<NodeConnectorStatistics> statistics = statisticsManager
.getNodeConnectorStatistics(node);
for (NodeConnectorStatistics stats : statistics) {
- cells.add(this.convertPortsStatistics(stats));
+ cells.add(this.convertPortsStatistics(stats, containerName));
}
}
}
}
private Map<String, String> convertPortsStatistics(
- NodeConnectorStatistics ncStats) {
+ NodeConnectorStatistics ncStats, String containerName) {
Map<String, String> row = new HashMap<String, String>();
+ ISwitchManager switchManager = (ISwitchManager) ServiceHelper
+ .getInstance(ISwitchManager.class, containerName, this);
+ NodeConnector nodeConnector = ncStats.getNodeConnector();
+ Description description = (Description) switchManager.getNodeProp(nodeConnector.getNode(), Description.propertyName);
+ String desc = (description == null) ? "" : description.getValue();
+ String nodeName = desc.equalsIgnoreCase("none") ? nodeConnector.getNode().getNodeIDString() : desc;
+ String nodeConnectorDisplayName = nodeConnector.getType() + "|" + nodeConnector.getID() + "@" + nodeName;
row.put("nodeConnector",
- String.valueOf(ncStats.getNodeConnector().toString()));
+ String.valueOf(nodeConnectorDisplayName));
+
row.put("rxPkts", String.valueOf(ncStats.getReceivePacketCount()));
row.put("txPkts", String.valueOf(ncStats.getTransmitPacketCount()));
row.put("rxBytes", String.valueOf(ncStats.getReceiveByteCount()));