Merge branch 'master' of https://github.com/OPENNETWORKINGLAB/ONOS
diff --git a/README.md b/README.md
index 495a2ed..516091e 100644
--- a/README.md
+++ b/README.md
@@ -1,10 +1,12 @@
-ONOS
-====
+ONOS (Open Networking Operating System)
+=======================================
-Open Networking Operating System
+ONOS (Open Network Operating System) is an experimental distributed SDN OS. ONOS is under development. ONOS was announced and demonstrated at ONS'13.
-BELOW TO BE WRITTEN IN DETAIL
+Steps to download and setup development VM
+==========================================
+http://wiki.onlab.us/display/Eng/ONOS+Development+VM
Building ONOS
-------------
diff --git a/pom.xml b/pom.xml
index 52fe30a..44b7f07 100644
--- a/pom.xml
+++ b/pom.xml
@@ -121,6 +121,30 @@
<locale>en</locale>
</configuration>
</plugin>
+ <plugin>
+ <groupId>org.jacoco</groupId>
+ <artifactId>jacoco-maven-plugin</artifactId>
+ <version>0.6.3.201306030806</version>
+ <configuration>
+ <destfile>${basedir}/target/jacoco/jacoco.exec</destfile>
+ <datafile>${basedir}/target/jacoco/jacoco.exec</datafile>
+ </configuration>
+ <executions>
+ <execution>
+ <id>jacoco-initialize</id>
+ <goals>
+ <goal>prepare-agent</goal>
+ </goals>
+ </execution>
+ <execution>
+ <id>jacoco-site</id>
+ <phase>package</phase>
+ <goals>
+ <goal>report</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
</plugins>
</build>
<!-- for getting visualization reporting -->
@@ -145,6 +169,7 @@
<reportSet>
<reports>
<report>dependencies</report>
+ <report>maven-emma-plugin</report>
<report>scm</report>
</reports>
</reportSet>
diff --git a/src/main/java/net/onrc/onos/flow/FlowManagerImpl.java b/src/main/java/net/onrc/onos/flow/FlowManagerImpl.java
index 1f041e6..2e2706c 100644
--- a/src/main/java/net/onrc/onos/flow/FlowManagerImpl.java
+++ b/src/main/java/net/onrc/onos/flow/FlowManagerImpl.java
@@ -28,6 +28,7 @@
import net.onrc.onos.ofcontroller.util.Dpid;
import net.onrc.onos.ofcontroller.util.FlowEntry;
import net.onrc.onos.ofcontroller.util.FlowEntryAction;
+import net.onrc.onos.ofcontroller.util.FlowEntryActions;
import net.onrc.onos.ofcontroller.util.FlowEntryMatch;
import net.onrc.onos.ofcontroller.util.FlowPath;
import net.onrc.onos.ofcontroller.util.Port;
@@ -132,16 +133,12 @@
flowEntry.setOutPort(new Port(src_port.getNumber()));
flowEntry.setFlowEntryMatch(new FlowEntryMatch());
flowEntry.flowEntryMatch().enableInPort(flowEntry.inPort());
-
+
// Set the outgoing port output action
- ArrayList<FlowEntryAction> flowEntryActions = flowEntry.flowEntryActions();
- if (flowEntryActions == null) {
- flowEntryActions = new ArrayList<FlowEntryAction>();
- flowEntry.setFlowEntryActions(flowEntryActions);
- }
+ FlowEntryActions flowEntryActions = flowEntry.flowEntryActions();
FlowEntryAction flowEntryAction = new FlowEntryAction();
flowEntryAction.setActionOutput(flowEntry.outPort());
- flowEntryActions.add(flowEntryAction);
+ flowEntryActions.addAction(flowEntryAction);
dataPath.flowEntries().add(flowEntry);
FlowPath flowPath = new FlowPath();
@@ -254,14 +251,10 @@
flowEntry.flowEntryMatch().enableInPort(flowEntry.inPort());
// Set the outgoing port output action
- ArrayList<FlowEntryAction> flowEntryActions = flowEntry.flowEntryActions();
- if (flowEntryActions == null) {
- flowEntryActions = new ArrayList<FlowEntryAction>();
- flowEntry.setFlowEntryActions(flowEntryActions);
- }
+ FlowEntryActions flowEntryActions = flowEntry.flowEntryActions();
FlowEntryAction flowEntryAction = new FlowEntryAction();
flowEntryAction.setActionOutput(flowEntry.outPort());
- flowEntryActions.add(flowEntryAction);
+ flowEntryActions.addAction(flowEntryAction);
dataPath.flowEntries().add(flowEntry);
continue;
}
@@ -276,14 +269,10 @@
flowEntry.flowEntryMatch().enableInPort(flowEntry.inPort());
// Set the outgoing port output action
- ArrayList<FlowEntryAction> flowEntryActions = flowEntry.flowEntryActions();
- if (flowEntryActions == null) {
- flowEntryActions = new ArrayList<FlowEntryAction>();
- flowEntry.setFlowEntryActions(flowEntryActions);
- }
+ FlowEntryActions flowEntryActions = flowEntry.flowEntryActions();
FlowEntryAction flowEntryAction = new FlowEntryAction();
flowEntryAction.setActionOutput(flowEntry.outPort());
- flowEntryActions.add(flowEntryAction);
+ flowEntryActions.addAction(flowEntryAction);
dataPath.flowEntries().add(flowEntry);
dataPath.flowEntries().add(flowEntry);
}
diff --git a/src/main/java/net/onrc/onos/ofcontroller/bgproute/BgpRoute.java b/src/main/java/net/onrc/onos/ofcontroller/bgproute/BgpRoute.java
index 2034118..acdf185 100644
--- a/src/main/java/net/onrc/onos/ofcontroller/bgproute/BgpRoute.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/bgproute/BgpRoute.java
@@ -10,7 +10,10 @@
import java.util.Iterator;
import java.util.List;
import java.util.Map;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
+import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
@@ -61,6 +64,8 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import com.google.common.util.concurrent.ThreadFactoryBuilder;
+
public class BgpRoute implements IFloodlightModule, IBgpRouteService,
ITopologyListener, IOFSwitchListener {
@@ -75,6 +80,8 @@
protected ProxyArpManager proxyArp;
protected static Ptree ptree;
+ protected BlockingQueue<RibUpdate> ribUpdates;
+
protected String bgpdRestIp;
protected String routerId;
protected String configFilename = "config.json";
@@ -119,9 +126,9 @@
ITopoLinkService topoLinkService = new TopoLinkServiceImpl();
List<Link> activeLinks = topoLinkService.getActiveLinks();
- for (Link l : activeLinks){
- log.debug("active link: {}", l);
- }
+ //for (Link l : activeLinks){
+ //log.debug("active link: {}", l);
+ //}
Iterator<LDUpdate> it = linkUpdates.iterator();
while (it.hasNext()){
@@ -139,12 +146,12 @@
if (linkUpdates.isEmpty()){
//All updates have been seen in network map.
//We can check if topology is ready
- log.debug("No know changes outstanding. Checking topology now");
+ log.debug("No known changes outstanding. Checking topology now");
checkStatus();
}
else {
//We know of some link updates that haven't propagated to the database yet
- log.debug("Some changes not found in network map- size {}", linkUpdates.size());
+ log.debug("Some changes not found in network map - {} links missing", linkUpdates.size());
topologyChangeDetectorTask.reschedule(TOPO_DETECTION_WAIT, TimeUnit.SECONDS);
}
}
@@ -215,6 +222,8 @@
throws FloodlightModuleException {
ptree = new Ptree(32);
+
+ ribUpdates = new LinkedBlockingQueue<RibUpdate>();
// Register floodlight provider and REST handler.
floodlightProvider = context.getServiceImpl(IFloodlightProviderService.class);
@@ -224,7 +233,7 @@
//TODO We'll initialise this here for now, but it should really be done as
//part of the controller core
- proxyArp = new ProxyArpManager(floodlightProvider, topology);
+ proxyArp = new ProxyArpManager(floodlightProvider, topology, devices);
linkUpdates = new ArrayList<LDUpdate>();
ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);
@@ -311,23 +320,23 @@
Prefix r = new Prefix("10.0.0.0", 24);
Prefix a = new Prefix("10.0.0.1", 32);
- ptree.acquire(p.getAddress(), p.masklen);
- ptree.acquire(q.getAddress(), q.masklen);
- ptree.acquire(r.getAddress(), r.masklen);
+ ptree.acquire(p.getAddress(), p.getPrefixLength());
+ ptree.acquire(q.getAddress(), q.getPrefixLength());
+ ptree.acquire(r.getAddress(), r.getPrefixLength());
System.out.println("Traverse start");
for (PtreeNode node = ptree.begin(); node != null; node = ptree.next(node)) {
Prefix p_result = new Prefix(node.key, node.keyBits);
}
- PtreeNode n = ptree.match(a.getAddress(), a.masklen);
+ PtreeNode n = ptree.match(a.getAddress(), a.getPrefixLength());
if (n != null) {
System.out.println("Matched prefix for 10.0.0.1:");
Prefix x = new Prefix(n.key, n.keyBits);
ptree.delReference(n);
}
- n = ptree.lookup(p.getAddress(), p.masklen);
+ n = ptree.lookup(p.getAddress(), p.getPrefixLength());
if (n != null) {
ptree.delReference(n);
ptree.delReference(n);
@@ -337,7 +346,7 @@
Prefix p_result = new Prefix(node.key, node.keyBits);
}
- n = ptree.lookup(q.getAddress(), q.masklen);
+ n = ptree.lookup(q.getAddress(), q.getPrefixLength());
if (n != null) {
ptree.delReference(n);
ptree.delReference(n);
@@ -347,7 +356,7 @@
Prefix p_result = new Prefix(node.key, node.keyBits);
}
- n = ptree.lookup(r.getAddress(), r.masklen);
+ n = ptree.lookup(r.getAddress(), r.getPrefixLength());
if (n != null) {
ptree.delReference(n);
ptree.delReference(n);
@@ -409,8 +418,8 @@
continue;
}
- PtreeNode node = ptree.acquire(p.getAddress(), p.masklen);
- Rib rib = new Rib(router_id, nexthop, p.masklen);
+ PtreeNode node = ptree.acquire(p.getAddress(), p.getPrefixLength());
+ Rib rib = new Rib(router_id, nexthop, p.getPrefixLength());
if (node.rib != null) {
node.rib = null;
@@ -423,6 +432,53 @@
}
}
+ @Override
+ public void newRibUpdate(RibUpdate update) {
+ ribUpdates.add(update);
+ }
+
+ //TODO temporary
+ public void wrapPrefixAdded(RibUpdate update) {
+ Prefix prefix = update.getPrefix();
+
+ PtreeNode node = ptree.acquire(prefix.getAddress(), prefix.getPrefixLength());
+
+ if (node.rib != null) {
+ node.rib = null;
+ ptree.delReference(node);
+ }
+ node.rib = update.getRibEntry();
+
+ prefixAdded(node);
+ }
+
+ //TODO temporary
+ public void wrapPrefixDeleted(RibUpdate update) {
+ Prefix prefix = update.getPrefix();
+
+ PtreeNode node = ptree.lookup(prefix.getAddress(), prefix.getPrefixLength());
+
+ /*
+ * Remove the flows from the switches before the rib is lost
+ * Theory: we could get a delete for a prefix not in the Ptree.
+ * This would result in a null node being returned. We could get a delete for
+ * a node that's not actually there, but is a aggregate node. This would result
+ * in a non-null node with a null rib. Only a non-null node with a non-null
+ * rib is an actual prefix in the Ptree.
+ */
+ if (node != null && node.rib != null){
+ prefixDeleted(node);
+ }
+
+ if (node != null && node.rib != null) {
+ if (update.getRibEntry().equals(node.rib)) {
+ node.rib = null;
+ ptree.delReference(node);
+ }
+ }
+ }
+
+ @Override
public void prefixAdded(PtreeNode node) {
if (!topologyReady){
return;
@@ -435,7 +491,7 @@
node.rib.routerId.getHostAddress()});
//TODO this is wrong, we shouldn't be dealing with BGP peers here.
- //We need to figure out where the device is attached and what it's
+ //We need to figure out where the device is attached and what its
//mac address is by learning.
//The next hop is not necessarily the peer, and the peer's attachment
//point is not necessarily the next hop's attachment point.
@@ -549,6 +605,7 @@
}
//TODO this is largely untested
+ @Override
public void prefixDeleted(PtreeNode node) {
if (!topologyReady) {
return;
@@ -915,9 +972,45 @@
floodlightProvider.addOFMessageListener(OFType.PACKET_IN, proxyArp);
+ ExecutorService e = Executors.newSingleThreadExecutor(
+ new ThreadFactoryBuilder().setNameFormat("bgp-updates-%d").build());
+
+
+ e.execute(new Runnable() {
+ @Override
+ public void run() {
+ doUpdatesThread();
+ }
+ });
+
//Retrieve the RIB from BGPd during startup
retrieveRib();
}
+
+ private void doUpdatesThread() {
+ boolean interrupted = false;
+ try {
+ while (true) {
+ try {
+ RibUpdate update = ribUpdates.take();
+ switch (update.getOperation()){
+ case UPDATE:
+ wrapPrefixAdded(update);
+ break;
+ case DELETE:
+ wrapPrefixDeleted(update);
+ break;
+ }
+ } catch (InterruptedException e) {
+ interrupted = true;
+ }
+ }
+ } finally {
+ if (interrupted) {
+ Thread.currentThread().interrupt();
+ }
+ }
+ }
@Override
public void topologyChanged() {
diff --git a/src/main/java/net/onrc/onos/ofcontroller/bgproute/BgpRouteResource.java b/src/main/java/net/onrc/onos/ofcontroller/bgproute/BgpRouteResource.java
index 8355308..19b44c8 100644
--- a/src/main/java/net/onrc/onos/ofcontroller/bgproute/BgpRouteResource.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/bgproute/BgpRouteResource.java
@@ -2,6 +2,8 @@
import java.net.UnknownHostException;
+import net.onrc.onos.ofcontroller.bgproute.RibUpdate.Operation;
+
import org.restlet.resource.Delete;
import org.restlet.resource.Get;
import org.restlet.resource.Post;
@@ -100,7 +102,7 @@
IBgpRouteService bgpRoute = (IBgpRouteService) getContext().getAttributes().
get(IBgpRouteService.class.getCanonicalName());
- Ptree ptree = bgpRoute.getPtree();
+ //Ptree ptree = bgpRoute.getPtree();
String routerId = (String) getRequestAttributes().get("routerid");
String prefix = (String) getRequestAttributes().get("prefix");
@@ -125,9 +127,13 @@
return reply + "\n";
}
- PtreeNode node = ptree.acquire(p.getAddress(), p.masklen);
- Rib rib = new Rib(routerId, nexthop, p.masklen);
+ Rib rib = new Rib(routerId, nexthop, p.getPrefixLength());
+ bgpRoute.newRibUpdate(new RibUpdate(Operation.UPDATE, p, rib));
+
+ /*
+ PtreeNode node = ptree.acquire(p.getAddress(), p.getPrefixLength());
+
if (node.rib != null) {
node.rib = null;
ptree.delReference(node);
@@ -135,6 +141,7 @@
node.rib = rib;
bgpRoute.prefixAdded(node);
+ */
reply = "[POST: " + prefix + "/" + mask + ":" + nexthop + "]";
log.info(reply);
@@ -158,7 +165,7 @@
IBgpRouteService bgpRoute = (IBgpRouteService)getContext().getAttributes().
get(IBgpRouteService.class.getCanonicalName());
- Ptree ptree = bgpRoute.getPtree();
+ //Ptree ptree = bgpRoute.getPtree();
String routerId = (String) getRequestAttributes().get("routerid");
String prefix = (String) getRequestAttributes().get("prefix");
@@ -182,8 +189,13 @@
log.info(reply);
return reply + "\n";
}
-
- PtreeNode node = ptree.lookup(p.getAddress(), p.masklen);
+
+ Rib r = new Rib(routerId, nextHop, p.getPrefixLength());
+
+ bgpRoute.newRibUpdate(new RibUpdate(Operation.DELETE, p, r));
+
+ /*
+ PtreeNode node = ptree.lookup(p.getAddress(), p.getPrefixLength());
//Remove the flows from the switches before the rib is lost
//Theory: we could get a delete for a prefix not in the Ptree.
@@ -195,7 +207,7 @@
bgpRoute.prefixDeleted(node);
}
- Rib r = new Rib(routerId, nextHop, p.masklen);
+
if (node != null && node.rib != null) {
if (r.equals(node.rib)) {
@@ -203,6 +215,7 @@
ptree.delReference(node);
}
}
+ */
reply =reply + "[DELE: " + prefix + "/" + mask + ":" + nextHop + "]";
}
diff --git a/src/main/java/net/onrc/onos/ofcontroller/bgproute/IBgpRouteService.java b/src/main/java/net/onrc/onos/ofcontroller/bgproute/IBgpRouteService.java
index c84a415..3dbc940 100644
--- a/src/main/java/net/onrc/onos/ofcontroller/bgproute/IBgpRouteService.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/bgproute/IBgpRouteService.java
@@ -14,6 +14,12 @@
public void clearPtree();
+ /**
+ * Pass a RIB update to the {@link IBgpRouteService}
+ * @param update
+ */
+ public void newRibUpdate(RibUpdate update);
+
//TODO This functionality should be provided by some sort of Ptree listener framework
public void prefixAdded(PtreeNode node);
public void prefixDeleted(PtreeNode node);
diff --git a/src/main/java/net/onrc/onos/ofcontroller/bgproute/Prefix.java b/src/main/java/net/onrc/onos/ofcontroller/bgproute/Prefix.java
index c3baa37..4d7c53a 100644
--- a/src/main/java/net/onrc/onos/ofcontroller/bgproute/Prefix.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/bgproute/Prefix.java
@@ -4,31 +4,40 @@
import java.net.UnknownHostException;
public class Prefix {
- public int masklen;
- protected InetAddress address;
+ private int prefixLength;
+ private InetAddress address;
- public Prefix(byte[] addr, int masklen) throws UnknownHostException {
+ public Prefix(byte[] addr, int prefixLength) throws UnknownHostException {
//try {
address = InetAddress.getByAddress(addr);
//} catch (UnknownHostException e) {
// System.out.println("InetAddress exception");
// return;
//}
- this.masklen = masklen;
- //System.out.println(address.toString() + "/" + masklen);
+ this.prefixLength = prefixLength;
+ //System.out.println(address.toString() + "/" + prefixLength);
}
- public Prefix(String str, int masklen) throws UnknownHostException {
+ public Prefix(String str, int prefixLength) throws UnknownHostException {
//try {
address = InetAddress.getByName(str);
//} catch (UnknownHostException e) {
// System.out.println("InetAddress exception");
// return;
//}
- this.masklen = masklen;
+ this.prefixLength = prefixLength;
}
- public byte [] getAddress() {
+ public int getPrefixLength() {
+ return prefixLength;
+ }
+
+ public byte[] getAddress() {
return address.getAddress();
}
+
+ @Override
+ public String toString() {
+ return address.getHostAddress() + "/" + prefixLength;
+ }
}
diff --git a/src/main/java/net/onrc/onos/ofcontroller/bgproute/Ptree.java b/src/main/java/net/onrc/onos/ofcontroller/bgproute/Ptree.java
index 6741a41..041061c 100644
--- a/src/main/java/net/onrc/onos/ofcontroller/bgproute/Ptree.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/bgproute/Ptree.java
@@ -1,24 +1,33 @@
package net.onrc.onos.ofcontroller.bgproute;
+/*
+ * TODO This Ptree needs to be refactored if we're going to use it permenantly.
+ *
+ * The biggest problem is it leaks PTreeNode references - these need to stay within
+ * the Ptree as they contain data fundamental to the structure of the tree.
+ * You should put RIB entries in and get RIB entries out.
+ * Also we need to get rid of the referencing scheme to determine when to delete nodes.
+ * Deletes should be explicit, and there's no need to keep track of references if
+ * we don't leak them out the the Ptree.
+ */
public class Ptree {
- int maxKeyBits;
- int maxKeyOctets;
- int refCount;
- PtreeNode top;
- byte maskBits[] = { (byte)0x00, (byte)0x80, (byte)0xc0, (byte)0xe0, (byte)0xf0, (byte)0xf8, (byte)0xfc, (byte)0xfe, (byte)0xff };
+ private int maxKeyBits;
+ private int maxKeyOctets;
+ //private int refCount;
+ private PtreeNode top;
+ private byte maskBits[] = { (byte)0x00, (byte)0x80, (byte)0xc0, (byte)0xe0, (byte)0xf0, (byte)0xf8, (byte)0xfc, (byte)0xfe, (byte)0xff };
- // Constructor.
- Ptree(int max_key_bits) {
+ public Ptree(int max_key_bits) {
maxKeyBits = max_key_bits;
maxKeyOctets = bit_to_octet(max_key_bits);
- refCount = 0;
+ //refCount = 0;
}
- public PtreeNode acquire(byte [] key) {
+ public synchronized PtreeNode acquire(byte [] key) {
return acquire(key, maxKeyBits);
}
- public PtreeNode acquire(byte [] key, int key_bits) {
+ public synchronized PtreeNode acquire(byte [] key, int key_bits) {
if (key_bits > maxKeyBits) {
return null;
}
@@ -76,7 +85,7 @@
return addReference(add);
}
- public PtreeNode lookup(byte [] key, int key_bits) {
+ public synchronized PtreeNode lookup(byte [] key, int key_bits) {
if (key_bits > maxKeyBits) {
return null;
}
@@ -99,7 +108,7 @@
return null;
}
- public PtreeNode match(byte [] key, int key_bits) {
+ public synchronized PtreeNode match(byte [] key, int key_bits) {
if (key_bits > maxKeyBits) {
return null;
}
@@ -127,14 +136,14 @@
return null;
}
- public PtreeNode begin() {
+ public synchronized PtreeNode begin() {
if (top == null) {
return null;
}
return addReference(top);
}
- public PtreeNode next(PtreeNode node) {
+ public synchronized PtreeNode next(PtreeNode node) {
PtreeNode next;
if (node.left != null) {
@@ -175,7 +184,7 @@
return node;
}
- public void delReference(PtreeNode node) {
+ public synchronized void delReference(PtreeNode node) {
if (node.refCount > 0) {
node.refCount--;
}
@@ -278,10 +287,6 @@
return add;
}
- //add by linpp
- private void clear() {
-
- }
private void node_remove(PtreeNode node) {
PtreeNode child;
diff --git a/src/main/java/net/onrc/onos/ofcontroller/bgproute/RibUpdate.java b/src/main/java/net/onrc/onos/ofcontroller/bgproute/RibUpdate.java
new file mode 100644
index 0000000..c7272bd
--- /dev/null
+++ b/src/main/java/net/onrc/onos/ofcontroller/bgproute/RibUpdate.java
@@ -0,0 +1,27 @@
+package net.onrc.onos.ofcontroller.bgproute;
+
+public class RibUpdate {
+ public enum Operation {UPDATE, DELETE};
+
+ private Operation operation;
+ private Prefix prefix;
+ private Rib ribEntry;
+
+ public RibUpdate(Operation operation, Prefix prefix, Rib ribEntry) {
+ this.operation = operation;
+ this.prefix = prefix;
+ this.ribEntry = ribEntry;
+ }
+
+ public Operation getOperation() {
+ return operation;
+ }
+
+ public Prefix getPrefix() {
+ return prefix;
+ }
+
+ public Rib getRibEntry() {
+ return ribEntry;
+ }
+}
diff --git a/src/main/java/net/onrc/onos/ofcontroller/core/INetMapTopologyObjects.java b/src/main/java/net/onrc/onos/ofcontroller/core/INetMapTopologyObjects.java
index 2672a6b..9a96638 100644
--- a/src/main/java/net/onrc/onos/ofcontroller/core/INetMapTopologyObjects.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/core/INetMapTopologyObjects.java
@@ -253,6 +253,9 @@
@Adjacency(label="flow", direction=Direction.IN)
public void removeFlowEntry(final IFlowEntry flowEntry);
+ //
+ // Matching fields
+ //
@JsonIgnore
@Property("matchSrcMac")
public String getMatchSrcMac();
@@ -330,6 +333,18 @@
@Property("matchDstTcpUdpPort")
public void setMatchDstTcpUdpPort(Short matchDstTcpUdpPort);
+ //
+ // Action-related fields
+ //
+ @Property("actions")
+ public String getActions();
+
+ @Property("actions")
+ public void setActions(String actionsStr);
+
+ //
+ // Other fields
+ //
@JsonIgnore
@GremlinGroovy("it.in('flow').out('switch')")
public Iterable<ISwitchObject> getSwitches();
@@ -383,6 +398,9 @@
@Property("error_state_code")
public void setErrorStateCode(String errorStateCode);
+ //
+ // Matching fields
+ //
@Property("matchInPort")
public Short getMatchInPort();
@@ -455,12 +473,24 @@
@Property("matchDstTcpUdpPort")
public void setMatchDstTcpUdpPort(Short matchDstTcpUdpPort);
- @Property("actionOutput")
- public Short getActionOutput();
+ //
+ // Action-related fields
+ //
+ @Property("actionOutputPort")
+ public Short getActionOutputPort();
- @Property("actionOutput")
- public void setActionOutput(Short actionOutput);
+ @Property("actionOutputPort")
+ public void setActionOutputPort(Short actionOutputPort);
+ @Property("actions")
+ public String getActions();
+
+ @Property("actions")
+ public void setActions(String actionsStr);
+
+ //
+ // Other fields
+ //
@Adjacency(label="flow")
public IFlowPath getFlow();
diff --git a/src/main/java/net/onrc/onos/ofcontroller/floodlightlistener/NetworkGraphPublisher.java b/src/main/java/net/onrc/onos/ofcontroller/floodlightlistener/NetworkGraphPublisher.java
index 8c83a7c..e0ac4e1 100644
--- a/src/main/java/net/onrc/onos/ofcontroller/floodlightlistener/NetworkGraphPublisher.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/floodlightlistener/NetworkGraphPublisher.java
@@ -127,19 +127,22 @@
public void linkDiscoveryUpdate(LDUpdate update) {
// TODO Auto-generated method stub
Link lt = new Link(update.getSrc(),update.getSrcPort(),update.getDst(),update.getDstPort());
- log.debug("{}:LinkDicoveryUpdate(): Updating Link {}",this.getClass(), lt);
- switch (update.getOperation()) {
+ //log.debug("{}:LinkDicoveryUpdate(): Updating Link {}",this.getClass(), lt);
+ switch (update.getOperation()) {
case LINK_REMOVED:
+ log.debug("LinkDiscoveryUpdate(): Removing link {}", lt);
linkStore.update(lt, DM_OPERATION.DELETE);
// TODO: Move network map link removal here
// reconcile paths here
// IPortObject srcPort = conn.utils().searchPort(conn, HexString.toHexString(update.getSrc()), update.getSrcPort());
break;
case LINK_UPDATED:
+ log.debug("LinkDiscoveryUpdate(): Updating link {}", lt);
linkStore.update(lt, DM_OPERATION.UPDATE);
break;
case LINK_ADDED:
+ log.debug("LinkDiscoveryUpdate(): Adding link {}", lt);
linkStore.update(lt, DM_OPERATION.INSERT);
break;
diff --git a/src/main/java/net/onrc/onos/ofcontroller/flowmanager/FlowManager.java b/src/main/java/net/onrc/onos/ofcontroller/flowmanager/FlowManager.java
index 969d41e..a072882 100644
--- a/src/main/java/net/onrc/onos/ofcontroller/flowmanager/FlowManager.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/flowmanager/FlowManager.java
@@ -42,6 +42,8 @@
import net.onrc.onos.ofcontroller.util.Dpid;
import net.onrc.onos.ofcontroller.util.FlowEntry;
import net.onrc.onos.ofcontroller.util.FlowEntryAction;
+import net.onrc.onos.ofcontroller.util.FlowEntryAction.*;
+import net.onrc.onos.ofcontroller.util.FlowEntryActions;
import net.onrc.onos.ofcontroller.util.FlowEntryId;
import net.onrc.onos.ofcontroller.util.FlowEntryMatch;
import net.onrc.onos.ofcontroller.util.FlowEntrySwitchState;
@@ -58,8 +60,7 @@
import org.openflow.protocol.OFPacketOut;
import org.openflow.protocol.OFPort;
import org.openflow.protocol.OFType;
-import org.openflow.protocol.action.OFAction;
-import org.openflow.protocol.action.OFActionOutput;
+import org.openflow.protocol.action.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -587,6 +588,7 @@
// - flowPath.matchIpToS()
// - flowPath.matchSrcTcpUdpPort()
// - flowPath.matchDstTcpUdpPort()
+ // - flowPath.flowEntryActions()
//
flowObj.setInstallerId(flowPath.installerId().toString());
flowObj.setFlowPathFlags(flowPath.flowPathFlags().flags());
@@ -627,6 +629,9 @@
if (flowPath.flowEntryMatch().matchDstTcpUdpPort()) {
flowObj.setMatchDstTcpUdpPort(flowPath.flowEntryMatch().dstTcpUdpPort());
}
+ if (! flowPath.flowEntryActions().actions().isEmpty()) {
+ flowObj.setActions(flowPath.flowEntryActions().toString());
+ }
if (dataPathSummaryStr != null) {
flowObj.setDataPathSummary(dataPathSummaryStr);
@@ -720,8 +725,6 @@
// - InPort edge
// - OutPort edge
//
- // - flowEntry.flowEntryMatch()
- // - flowEntry.flowEntryActions()
// - flowEntry.dpid()
// - flowEntry.flowEntryUserState()
// - flowEntry.flowEntrySwitchState()
@@ -738,7 +741,8 @@
// - flowEntry.matchIpToS()
// - flowEntry.matchSrcTcpUdpPort()
// - flowEntry.matchDstTcpUdpPort()
- // - flowEntry.actionOutput()
+ // - flowEntry.actionOutputPort()
+ // - flowEntry.actions()
//
ISwitchObject sw =
op.searchSwitch(flowEntry.dpid().toString());
@@ -785,15 +789,19 @@
flowEntryObj.setMatchDstTcpUdpPort(flowEntry.flowEntryMatch().dstTcpUdpPort());
}
- for (FlowEntryAction fa : flowEntry.flowEntryActions()) {
+ for (FlowEntryAction fa : flowEntry.flowEntryActions().actions()) {
if (fa.actionOutput() != null) {
IPortObject outport =
op.searchPort(flowEntry.dpid().toString(),
fa.actionOutput().port().value());
- flowEntryObj.setActionOutput(fa.actionOutput().port().value());
+ flowEntryObj.setActionOutputPort(fa.actionOutput().port().value());
flowEntryObj.setOutPort(outport);
}
}
+ if (! flowEntry.flowEntryActions().isEmpty()) {
+ flowEntryObj.setActions(flowEntry.flowEntryActions().toString());
+ }
+
// TODO: Hacks with hard-coded state names!
if (found)
flowEntryObj.setUserState("FE_USER_MODIFY");
@@ -1387,6 +1395,16 @@
flowPath.setFlowEntryMatch(match);
}
+ //
+ // Extract the actions for the first Flow Entry
+ //
+ {
+ String actionsStr = flowObj.getActions();
+ if (actionsStr != null) {
+ FlowEntryActions flowEntryActions = new FlowEntryActions(actionsStr);
+ flowPath.setFlowEntryActions(flowEntryActions);
+ }
+ }
//
// Extract all Flow Entries
@@ -1471,19 +1489,15 @@
//
// Extract the actions
//
- ArrayList<FlowEntryAction> actions = new ArrayList<FlowEntryAction>();
- Short actionOutputPort = flowEntryObj.getActionOutput();
- if (actionOutputPort != null) {
- FlowEntryAction action = new FlowEntryAction();
- action.setActionOutput(new Port(actionOutputPort));
- actions.add(action);
- }
+ FlowEntryActions actions = new FlowEntryActions();
+ String actionsStr = flowEntryObj.getActions();
+ if (actionsStr != null)
+ actions = new FlowEntryActions(actionsStr);
flowEntry.setFlowEntryActions(actions);
flowEntry.setFlowEntryUserState(FlowEntryUserState.valueOf(userState));
flowEntry.setFlowEntrySwitchState(FlowEntrySwitchState.valueOf(switchState));
//
- // TODO: Take care of the FlowEntryMatch, FlowEntryAction set,
- // and FlowEntryErrorState.
+ // TODO: Take care of FlowEntryErrorState.
//
return flowEntry;
}
@@ -1518,6 +1532,7 @@
computedFlowPath.setFlowPathFlags(new FlowPathFlags(flowPath.flowPathFlags().flags()));
computedFlowPath.setDataPath(dataPath);
computedFlowPath.setFlowEntryMatch(new FlowEntryMatch(flowPath.flowEntryMatch()));
+ computedFlowPath.setFlowEntryActions(new FlowEntryActions(flowPath.flowEntryActions()));
FlowId flowId = new FlowId();
String dataPathSummaryStr = dataPath.dataPathSummary();
@@ -1543,21 +1558,35 @@
// Set the incoming port matching and the outgoing port output
// actions for each flow entry.
//
+ int idx = 0;
for (FlowEntry flowEntry : newDataPath.flowEntries()) {
// Set the incoming port matching
FlowEntryMatch flowEntryMatch = new FlowEntryMatch();
flowEntry.setFlowEntryMatch(flowEntryMatch);
flowEntryMatch.enableInPort(flowEntry.inPort());
- // Set the outgoing port output action
- ArrayList<FlowEntryAction> flowEntryActions = flowEntry.flowEntryActions();
- if (flowEntryActions == null) {
- flowEntryActions = new ArrayList<FlowEntryAction>();
- flowEntry.setFlowEntryActions(flowEntryActions);
+ //
+ // Set the actions
+ //
+ FlowEntryActions flowEntryActions = flowEntry.flowEntryActions();
+ //
+ // If the first Flow Entry, copy the Flow Path actions to it
+ //
+ if (idx == 0) {
+ String actionsStr = flowObj.getActions();
+ if (actionsStr != null) {
+ FlowEntryActions flowActions = new FlowEntryActions(actionsStr);
+ for (FlowEntryAction action : flowActions.actions())
+ flowEntryActions.addAction(action);
+ }
}
+ idx++;
+ //
+ // Add the outgoing port output action
+ //
FlowEntryAction flowEntryAction = new FlowEntryAction();
flowEntryAction.setActionOutput(flowEntry.outPort());
- flowEntryActions.add(flowEntryAction);
+ flowEntryActions.addAction(flowEntryAction);
}
//
@@ -1749,16 +1778,115 @@
//
// Fetch the actions
//
- // TODO: For now we support only the "OUTPUT" actions.
- //
- List<OFAction> actions = new ArrayList<OFAction>();
- Short actionOutputPort = flowEntryObj.getActionOutput();
- if (actionOutputPort != null) {
- OFActionOutput action = new OFActionOutput();
- // XXX: The max length is hard-coded for now
- action.setMaxLength((short)0xffff);
- action.setPort(actionOutputPort);
- actions.add(action);
+ Short actionOutputPort = null;
+ List<OFAction> openFlowActions = new ArrayList<OFAction>();
+ int actionsLen = 0;
+ FlowEntryActions flowEntryActions = null;
+ String actionsStr = flowEntryObj.getActions();
+ if (actionsStr != null)
+ flowEntryActions = new FlowEntryActions(actionsStr);
+ for (FlowEntryAction action : flowEntryActions.actions()) {
+ ActionOutput actionOutput = action.actionOutput();
+ ActionSetVlanId actionSetVlanId = action.actionSetVlanId();
+ ActionSetVlanPriority actionSetVlanPriority = action.actionSetVlanPriority();
+ ActionStripVlan actionStripVlan = action.actionStripVlan();
+ ActionSetEthernetAddr actionSetEthernetSrcAddr = action.actionSetEthernetSrcAddr();
+ ActionSetEthernetAddr actionSetEthernetDstAddr = action.actionSetEthernetDstAddr();
+ ActionSetIPv4Addr actionSetIPv4SrcAddr = action.actionSetIPv4SrcAddr();
+ ActionSetIPv4Addr actionSetIPv4DstAddr = action.actionSetIPv4DstAddr();
+ ActionSetIpToS actionSetIpToS = action.actionSetIpToS();
+ ActionSetTcpUdpPort actionSetTcpUdpSrcPort = action.actionSetTcpUdpSrcPort();
+ ActionSetTcpUdpPort actionSetTcpUdpDstPort = action.actionSetTcpUdpDstPort();
+ ActionEnqueue actionEnqueue = action.actionEnqueue();
+
+ if (actionOutput != null) {
+ actionOutputPort = actionOutput.port().value();
+ // XXX: The max length is hard-coded for now
+ OFActionOutput ofa =
+ new OFActionOutput(actionOutput.port().value(),
+ (short)0xffff);
+ openFlowActions.add(ofa);
+ actionsLen += ofa.getLength();
+ }
+
+ if (actionSetVlanId != null) {
+ OFActionVirtualLanIdentifier ofa =
+ new OFActionVirtualLanIdentifier(actionSetVlanId.vlanId());
+ openFlowActions.add(ofa);
+ actionsLen += ofa.getLength();
+ }
+
+ if (actionSetVlanPriority != null) {
+ OFActionVirtualLanPriorityCodePoint ofa =
+ new OFActionVirtualLanPriorityCodePoint(actionSetVlanPriority.vlanPriority());
+ openFlowActions.add(ofa);
+ actionsLen += ofa.getLength();
+ }
+
+ if (actionStripVlan != null) {
+ if (actionStripVlan.stripVlan() == true) {
+ OFActionStripVirtualLan ofa = new OFActionStripVirtualLan();
+ openFlowActions.add(ofa);
+ actionsLen += ofa.getLength();
+ }
+ }
+
+ if (actionSetEthernetSrcAddr != null) {
+ OFActionDataLayerSource ofa =
+ new OFActionDataLayerSource(actionSetEthernetSrcAddr.addr().toBytes());
+ openFlowActions.add(ofa);
+ actionsLen += ofa.getLength();
+ }
+
+ if (actionSetEthernetDstAddr != null) {
+ OFActionDataLayerDestination ofa =
+ new OFActionDataLayerDestination(actionSetEthernetDstAddr.addr().toBytes());
+ openFlowActions.add(ofa);
+ actionsLen += ofa.getLength();
+ }
+
+ if (actionSetIPv4SrcAddr != null) {
+ OFActionNetworkLayerSource ofa =
+ new OFActionNetworkLayerSource(actionSetIPv4SrcAddr.addr().value());
+ openFlowActions.add(ofa);
+ actionsLen += ofa.getLength();
+ }
+
+ if (actionSetIPv4DstAddr != null) {
+ OFActionNetworkLayerDestination ofa =
+ new OFActionNetworkLayerDestination(actionSetIPv4DstAddr.addr().value());
+ openFlowActions.add(ofa);
+ actionsLen += ofa.getLength();
+ }
+
+ if (actionSetIpToS != null) {
+ OFActionNetworkTypeOfService ofa =
+ new OFActionNetworkTypeOfService(actionSetIpToS.ipToS());
+ openFlowActions.add(ofa);
+ actionsLen += ofa.getLength();
+ }
+
+ if (actionSetTcpUdpSrcPort != null) {
+ OFActionTransportLayerSource ofa =
+ new OFActionTransportLayerSource(actionSetTcpUdpSrcPort.port());
+ openFlowActions.add(ofa);
+ actionsLen += ofa.getLength();
+ }
+
+ if (actionSetTcpUdpDstPort != null) {
+ OFActionTransportLayerDestination ofa =
+ new OFActionTransportLayerDestination(actionSetTcpUdpDstPort.port());
+ openFlowActions.add(ofa);
+ actionsLen += ofa.getLength();
+ }
+
+ if (actionEnqueue != null) {
+ OFActionEnqueue ofa =
+ new OFActionEnqueue(actionEnqueue.port().value(),
+ actionEnqueue.queueId());
+ openFlowActions.add(ofa);
+ actionsLen += ofa.getLength();
+ }
}
fm.setIdleTimeout(FLOWMOD_DEFAULT_IDLE_TIMEOUT)
@@ -1768,8 +1896,8 @@
.setCookie(cookie)
.setCommand(flowModCommand)
.setMatch(match)
- .setActions(actions)
- .setLengthU(OFFlowMod.MINIMUM_LENGTH+OFActionOutput.MINIMUM_LENGTH);
+ .setActions(openFlowActions)
+ .setLengthU(OFFlowMod.MINIMUM_LENGTH + actionsLen);
fm.setOutPort(OFPort.OFPP_NONE.getValue());
if ((flowModCommand == OFFlowMod.OFPFC_DELETE) ||
(flowModCommand == OFFlowMod.OFPFC_DELETE_STRICT)) {
@@ -1973,27 +2101,113 @@
//
// Fetch the actions
//
- // TODO: For now we support only the "OUTPUT" actions.
+ Short actionOutputPort = null;
+ List<OFAction> openFlowActions = new ArrayList<OFAction>();
+ int actionsLen = 0;
+ FlowEntryActions flowEntryActions = flowEntry.flowEntryActions();
//
- fm.setOutPort(OFPort.OFPP_NONE.getValue());
- List<OFAction> actions = new ArrayList<OFAction>();
- ArrayList<FlowEntryAction> flowEntryActions =
- flowEntry.flowEntryActions();
- for (FlowEntryAction flowEntryAction : flowEntryActions) {
- FlowEntryAction.ActionOutput actionOutput =
- flowEntryAction.actionOutput();
+ for (FlowEntryAction action : flowEntryActions.actions()) {
+ ActionOutput actionOutput = action.actionOutput();
+ ActionSetVlanId actionSetVlanId = action.actionSetVlanId();
+ ActionSetVlanPriority actionSetVlanPriority = action.actionSetVlanPriority();
+ ActionStripVlan actionStripVlan = action.actionStripVlan();
+ ActionSetEthernetAddr actionSetEthernetSrcAddr = action.actionSetEthernetSrcAddr();
+ ActionSetEthernetAddr actionSetEthernetDstAddr = action.actionSetEthernetDstAddr();
+ ActionSetIPv4Addr actionSetIPv4SrcAddr = action.actionSetIPv4SrcAddr();
+ ActionSetIPv4Addr actionSetIPv4DstAddr = action.actionSetIPv4DstAddr();
+ ActionSetIpToS actionSetIpToS = action.actionSetIpToS();
+ ActionSetTcpUdpPort actionSetTcpUdpSrcPort = action.actionSetTcpUdpSrcPort();
+ ActionSetTcpUdpPort actionSetTcpUdpDstPort = action.actionSetTcpUdpDstPort();
+ ActionEnqueue actionEnqueue = action.actionEnqueue();
+
if (actionOutput != null) {
- short actionOutputPort = actionOutput.port().value();
- OFActionOutput action = new OFActionOutput();
+ actionOutputPort = actionOutput.port().value();
// XXX: The max length is hard-coded for now
- action.setMaxLength((short)0xffff);
- action.setPort(actionOutputPort);
- actions.add(action);
- if ((flowModCommand == OFFlowMod.OFPFC_DELETE) ||
- (flowModCommand == OFFlowMod.OFPFC_DELETE_STRICT)) {
- fm.setOutPort(actionOutputPort);
+ OFActionOutput ofa =
+ new OFActionOutput(actionOutput.port().value(),
+ (short)0xffff);
+ openFlowActions.add(ofa);
+ actionsLen += ofa.getLength();
+ }
+
+ if (actionSetVlanId != null) {
+ OFActionVirtualLanIdentifier ofa =
+ new OFActionVirtualLanIdentifier(actionSetVlanId.vlanId());
+ openFlowActions.add(ofa);
+ actionsLen += ofa.getLength();
+ }
+
+ if (actionSetVlanPriority != null) {
+ OFActionVirtualLanPriorityCodePoint ofa =
+ new OFActionVirtualLanPriorityCodePoint(actionSetVlanPriority.vlanPriority());
+ openFlowActions.add(ofa);
+ actionsLen += ofa.getLength();
+ }
+
+ if (actionStripVlan != null) {
+ if (actionStripVlan.stripVlan() == true) {
+ OFActionStripVirtualLan ofa = new OFActionStripVirtualLan();
+ openFlowActions.add(ofa);
+ actionsLen += ofa.getLength();
}
}
+
+ if (actionSetEthernetSrcAddr != null) {
+ OFActionDataLayerSource ofa =
+ new OFActionDataLayerSource(actionSetEthernetSrcAddr.addr().toBytes());
+ openFlowActions.add(ofa);
+ actionsLen += ofa.getLength();
+ }
+
+ if (actionSetEthernetDstAddr != null) {
+ OFActionDataLayerDestination ofa =
+ new OFActionDataLayerDestination(actionSetEthernetDstAddr.addr().toBytes());
+ openFlowActions.add(ofa);
+ actionsLen += ofa.getLength();
+ }
+
+ if (actionSetIPv4SrcAddr != null) {
+ OFActionNetworkLayerSource ofa =
+ new OFActionNetworkLayerSource(actionSetIPv4SrcAddr.addr().value());
+ openFlowActions.add(ofa);
+ actionsLen += ofa.getLength();
+ }
+
+ if (actionSetIPv4DstAddr != null) {
+ OFActionNetworkLayerDestination ofa =
+ new OFActionNetworkLayerDestination(actionSetIPv4DstAddr.addr().value());
+ openFlowActions.add(ofa);
+ actionsLen += ofa.getLength();
+ }
+
+ if (actionSetIpToS != null) {
+ OFActionNetworkTypeOfService ofa =
+ new OFActionNetworkTypeOfService(actionSetIpToS.ipToS());
+ openFlowActions.add(ofa);
+ actionsLen += ofa.getLength();
+ }
+
+ if (actionSetTcpUdpSrcPort != null) {
+ OFActionTransportLayerSource ofa =
+ new OFActionTransportLayerSource(actionSetTcpUdpSrcPort.port());
+ openFlowActions.add(ofa);
+ actionsLen += ofa.getLength();
+ }
+
+ if (actionSetTcpUdpDstPort != null) {
+ OFActionTransportLayerDestination ofa =
+ new OFActionTransportLayerDestination(actionSetTcpUdpDstPort.port());
+ openFlowActions.add(ofa);
+ actionsLen += ofa.getLength();
+ }
+
+ if (actionEnqueue != null) {
+ OFActionEnqueue ofa =
+ new OFActionEnqueue(actionEnqueue.port().value(),
+ actionEnqueue.queueId());
+ openFlowActions.add(ofa);
+ actionsLen += ofa.getLength();
+ }
}
fm.setIdleTimeout(FLOWMOD_DEFAULT_IDLE_TIMEOUT)
@@ -2003,8 +2217,14 @@
.setCookie(cookie)
.setCommand(flowModCommand)
.setMatch(match)
- .setActions(actions)
- .setLengthU(OFFlowMod.MINIMUM_LENGTH+OFActionOutput.MINIMUM_LENGTH);
+ .setActions(openFlowActions)
+ .setLengthU(OFFlowMod.MINIMUM_LENGTH + actionsLen);
+ fm.setOutPort(OFPort.OFPP_NONE.getValue());
+ if ((flowModCommand == OFFlowMod.OFPFC_DELETE) ||
+ (flowModCommand == OFFlowMod.OFPFC_DELETE_STRICT)) {
+ if (actionOutputPort != null)
+ fm.setOutPort(actionOutputPort);
+ }
//
// TODO: Set the following flag
@@ -2131,14 +2351,10 @@
flowEntryMatch.enableInPort(flowEntry.inPort());
// Set the outgoing port output action
- ArrayList<FlowEntryAction> flowEntryActions = flowEntry.flowEntryActions();
- if (flowEntryActions == null) {
- flowEntryActions = new ArrayList<FlowEntryAction>();
- flowEntry.setFlowEntryActions(flowEntryActions);
- }
+ FlowEntryActions flowEntryActions = flowEntry.flowEntryActions();
FlowEntryAction flowEntryAction = new FlowEntryAction();
flowEntryAction.setActionOutput(flowEntry.outPort());
- flowEntryActions.add(flowEntryAction);
+ flowEntryActions.addAction(flowEntryAction);
}
//
diff --git a/src/main/java/net/onrc/onos/ofcontroller/proxyarp/HostArpRequester.java b/src/main/java/net/onrc/onos/ofcontroller/proxyarp/HostArpRequester.java
new file mode 100644
index 0000000..20c6a28
--- /dev/null
+++ b/src/main/java/net/onrc/onos/ofcontroller/proxyarp/HostArpRequester.java
@@ -0,0 +1,28 @@
+package net.onrc.onos.ofcontroller.proxyarp;
+
+import net.floodlightcontroller.packet.ARP;
+
+public class HostArpRequester implements IArpRequester {
+
+ private IProxyArpService arpService;
+ private ARP arpRequest;
+ private long dpid;
+ private short port;
+ //private long requestTime; //in ms
+
+ public HostArpRequester(IProxyArpService arpService, ARP arpRequest,
+ long dpid, short port) {
+
+ this.arpService = arpService;
+ this.arpRequest = arpRequest;
+ this.dpid = dpid;
+ this.port = port;
+ //this.requestTime = System.currentTimeMillis();
+ }
+
+ @Override
+ public void arpResponse(byte[] mac) {
+ arpService.sendArpReply(arpRequest, dpid, port, mac);
+ }
+
+}
diff --git a/src/main/java/net/onrc/onos/ofcontroller/proxyarp/IArpRequester.java b/src/main/java/net/onrc/onos/ofcontroller/proxyarp/IArpRequester.java
new file mode 100644
index 0000000..2a74944
--- /dev/null
+++ b/src/main/java/net/onrc/onos/ofcontroller/proxyarp/IArpRequester.java
@@ -0,0 +1,5 @@
+package net.onrc.onos.ofcontroller.proxyarp;
+
+public interface IArpRequester {
+ public void arpResponse(byte[] mac);
+}
diff --git a/src/main/java/net/onrc/onos/ofcontroller/proxyarp/IProxyArpService.java b/src/main/java/net/onrc/onos/ofcontroller/proxyarp/IProxyArpService.java
new file mode 100644
index 0000000..4632aba
--- /dev/null
+++ b/src/main/java/net/onrc/onos/ofcontroller/proxyarp/IProxyArpService.java
@@ -0,0 +1,41 @@
+package net.onrc.onos.ofcontroller.proxyarp;
+
+import java.net.InetAddress;
+
+import net.floodlightcontroller.packet.ARP;
+
+public interface IProxyArpService {
+
+ public final int ARP_REQUEST_TIMEOUT = 2000; //ms
+
+ /**
+ * Tell the IProxyArpService to send an ARP reply with the targetMac to
+ * the host on the specified switchport.
+ * @param arpRequest
+ * @param dpid
+ * @param port
+ * @param targetMac
+ */
+ public void sendArpReply(ARP arpRequest, long dpid, short port, byte[] targetMac);
+
+ /**
+ * Returns the mac address if there is a valid entry in the cache.
+ * Otherwise returns null.
+ * @param ipAddress
+ * @return
+ */
+ public byte[] getMacAddress(InetAddress ipAddress);
+
+ /**
+ * Tell the IProxyArpService to send an ARP request for the IP address.
+ * The request will be broadcast out all edge ports in the network.
+ * As an optimization, the IProxyArpService will first check its cache and
+ * return the MAC address if it is already known. If not, the request will be
+ * sent and the callback will be called when the MAC address is known
+ * (or if the request times out).
+ * @param ipAddress
+ * @param requester
+ * @return
+ */
+ public byte[] sendArpRequest(InetAddress ipAddress, IArpRequester requester);
+}
diff --git a/src/main/java/net/onrc/onos/ofcontroller/proxyarp/ProxyArpManager.java b/src/main/java/net/onrc/onos/ofcontroller/proxyarp/ProxyArpManager.java
index a5246c0..5c2a2b9 100644
--- a/src/main/java/net/onrc/onos/ofcontroller/proxyarp/ProxyArpManager.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/proxyarp/ProxyArpManager.java
@@ -6,18 +6,23 @@
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
+import java.util.Timer;
+import java.util.TimerTask;
+import java.util.concurrent.ConcurrentHashMap;
import net.floodlightcontroller.core.FloodlightContext;
import net.floodlightcontroller.core.IFloodlightProviderService;
import net.floodlightcontroller.core.IOFMessageListener;
import net.floodlightcontroller.core.IOFSwitch;
+import net.floodlightcontroller.devicemanager.IDeviceService;
import net.floodlightcontroller.packet.ARP;
import net.floodlightcontroller.packet.Ethernet;
import net.floodlightcontroller.topology.ITopologyService;
-import net.floodlightcontroller.topology.NodePortTuple;
import net.floodlightcontroller.util.MACAddress;
import org.openflow.protocol.OFMessage;
@@ -31,27 +36,98 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-public class ProxyArpManager implements IOFMessageListener {
+public class ProxyArpManager implements IProxyArpService, IOFMessageListener {
private static Logger log = LoggerFactory.getLogger(ProxyArpManager.class);
- private final long ARP_ENTRY_TIMEOUT = 600000; //ms (== 5 mins)
+ private final long ARP_ENTRY_TIMEOUT = 600000; //ms (== 10 mins)
+ private final long ARP_REQUEST_TIMEOUT_THREAD_PERIOD = 60000; //ms (== 1 min)
+
protected IFloodlightProviderService floodlightProvider;
protected ITopologyService topology;
+ protected IDeviceService devices;
protected Map<InetAddress, ArpTableEntry> arpTable;
+ //protected ConcurrentHashMap<InetAddress, Set<ArpRequest>> arpRequests;
+ protected ConcurrentHashMap<InetAddress, ArpRequest> arpRequests;
+
+ private class ArpRequest {
+ private Set<IArpRequester> requesters;
+ private long requestTime;
+
+ public ArpRequest(){
+ this.requesters = new HashSet<IArpRequester>();
+ this.requestTime = System.currentTimeMillis();
+ }
+
+ public synchronized void addRequester(IArpRequester requester){
+ requestTime = System.currentTimeMillis();
+ requesters.add(requester);
+ }
+
+ public boolean isExpired(){
+ return (System.currentTimeMillis() - requestTime)
+ > IProxyArpService.ARP_REQUEST_TIMEOUT;
+ }
+
+ public synchronized void dispatchReply(byte[] replyMacAddress){
+ for (IArpRequester requester : requesters){
+ requester.arpResponse(replyMacAddress);
+ }
+ }
+ }
+
public ProxyArpManager(IFloodlightProviderService floodlightProvider,
- ITopologyService topology){
+ ITopologyService topology, IDeviceService devices){
this.floodlightProvider = floodlightProvider;
this.topology = topology;
+ this.devices = devices;
arpTable = new HashMap<InetAddress, ArpTableEntry>();
+ //arpRequests = new ConcurrentHashMap<InetAddress, Set<ArpRequest>>();
+ arpRequests = new ConcurrentHashMap<InetAddress, ArpRequest>();
+
+ Timer arpRequestTimeoutTimer = new Timer();
+ arpRequestTimeoutTimer.scheduleAtFixedRate(new TimerTask() {
+ @Override
+ public void run() {
+ synchronized (arpRequests) {
+ log.debug("Current have {} outstanding requests",
+ arpRequests.size());
+
+ Iterator<Map.Entry<InetAddress, ArpRequest>> it
+ = arpRequests.entrySet().iterator();
+
+ while (it.hasNext()){
+ Map.Entry<InetAddress, ArpRequest> entry
+ = it.next();
+
+ if (entry.getValue().isExpired()){
+ log.debug("Cleaning expired ARP request for {}",
+ entry.getKey().getHostAddress());
+ it.remove();
+ }
+ }
+ }
+ }
+ }, 0, ARP_REQUEST_TIMEOUT_THREAD_PERIOD);
+ }
+
+ private void storeRequester(InetAddress address, IArpRequester requester) {
+ synchronized (arpRequests) {
+ if (arpRequests.get(address) == null) {
+ arpRequests.put(address, new ArpRequest());
+ }
+ ArpRequest request = arpRequests.get(address);
+
+ request.addRequester(requester);
+ }
}
@Override
public String getName() {
- return "ProxyArpManager";
+ return "ProxyArpManager";
}
@Override
@@ -78,42 +154,95 @@
IFloodlightProviderService.CONTEXT_PI_PAYLOAD);
if (eth.getEtherType() == Ethernet.TYPE_ARP){
-
-
ARP arp = (ARP) eth.getPayload();
if (arp.getOpCode() == ARP.OP_REQUEST) {
- log.debug("ARP request received for {}", bytesToStringAddr(arp.getTargetProtocolAddress()));
-
- byte[] mac = lookupArpTable(arp.getTargetProtocolAddress());
-
- if (mac == null){
- //Mac address is not in our arp table.
- //We need to flood the request out edge ports
- Set<NodePortTuple> broadcastPorts = topology.getBroadcastDomainPorts();
- log.debug("size {}", broadcastPorts.size());
- for (NodePortTuple nodePort : broadcastPorts){
- log.debug("Port {}", nodePort);
- }
- broadcastArpRequestOutEdge(pi, sw.getId(), pi.getInPort());
- }
- else {
- //We know the address, so send a reply
- log.debug("Sending reply of {}", MACAddress.valueOf(mac).toString());
- sendArpReply(arp, pi, mac, sw);
- }
+ handleArpRequest(sw, pi, arp);
}
else if (arp.getOpCode() == ARP.OP_REPLY) {
- log.debug("ARP reply recieved for {}", bytesToStringAddr(arp.getSenderProtocolAddress()));
-
- log.debug("arp table {}", arpTable.keySet());
-
- updateArpTable(arp);
+ handleArpReply(sw, pi, arp);
}
}
+ //TODO should we propagate ARP or swallow it?
+ //Always propagate for now so DeviceManager can learn the host location
return Command.CONTINUE;
}
+
+ protected void handleArpRequest(IOFSwitch sw, OFPacketIn pi, ARP arp) {
+ log.debug("ARP request received for {}",
+ bytesToStringAddr(arp.getTargetProtocolAddress()));
+
+ byte[] mac = lookupArpTable(arp.getTargetProtocolAddress());
+
+ if (mac == null){
+ //Mac address is not in our arp table.
+
+ //TODO check what the DeviceManager thinks
+
+ //Record where the request came from so we know where to send the reply
+ InetAddress target;
+ try {
+ target = InetAddress.getByAddress(arp.getTargetProtocolAddress());
+ } catch (UnknownHostException e) {
+ log.debug("Invalid address in ARP request", e);
+ //return Command.CONTINUE; //Continue or stop?
+ return;
+ }
+
+ storeRequester(target, new HostArpRequester(this, arp, sw.getId(),
+ pi.getInPort()));
+
+ //Flood the request out edge ports
+ broadcastArpRequestOutEdge(pi.getPacketData(), sw.getId(), pi.getInPort());
+ }
+ else {
+ //We know the address, so send a reply
+ log.debug("Sending reply of {}", MACAddress.valueOf(mac).toString());
+ //sendArpReply(arp, pi, mac, sw);
+ sendArpReply(arp, sw.getId(), pi.getInPort(), mac);
+ }
+ }
+
+ protected void handleArpReply(IOFSwitch sw, OFPacketIn pi, ARP arp){
+ log.debug("ARP reply recieved for {}",
+ bytesToStringAddr(arp.getSenderProtocolAddress()));
+
+ updateArpTable(arp);
+
+ //See if anyone's waiting for this ARP reply
+ InetAddress addr;
+ try {
+ addr = InetAddress.getByAddress(arp.getSenderProtocolAddress());
+ } catch (UnknownHostException e) {
+ return;
+ }
+
+ ArpRequest request = null;
+ synchronized (arpRequests) {
+ request = arpRequests.get(addr);
+ if (request != null) {
+ arpRequests.remove(addr);
+ }
+ }
+ if (request != null && !request.isExpired()) {
+ request.dispatchReply(arp.getSenderHardwareAddress());
+ }
+
+ /*
+ Set<ArpRequest> requests = arpRequests.get(addr);
+ if (requests != null){
+
+ synchronized (requests) {
+ for (ArpRequest request : requests) {
+ if (!request.isExpired()){
+ request.getRequester().arpResponse(
+ arp.getSenderHardwareAddress());
+ }
+ }
+ }
+ }*/
+ }
private synchronized byte[] lookupArpTable(byte[] ipAddress){
InetAddress addr;
@@ -162,7 +291,35 @@
}
}
- private void broadcastArpRequestOutEdge(OFPacketIn pi, long inSwitch, short inPort){
+ private void sendArpRequestForAddress(InetAddress ipAddress) {
+ byte[] zeroIpv4 = {0x0, 0x0, 0x0, 0x0};
+ byte[] zeroMac = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0};
+ byte[] broadcastMac = {(byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff,
+ (byte)0xff, (byte)0xff, (byte)0xff};
+
+ ARP arpRequest = new ARP();
+
+ arpRequest.setHardwareType(ARP.HW_TYPE_ETHERNET)
+ .setProtocolType(ARP.PROTO_TYPE_IP)
+ .setHardwareAddressLength((byte)Ethernet.DATALAYER_ADDRESS_LENGTH)
+ .setProtocolAddressLength((byte)4) //can't find the constant anywhere
+ .setOpCode(ARP.OP_REQUEST)
+ .setSenderHardwareAddress(zeroMac)
+ .setSenderProtocolAddress(zeroIpv4)
+ .setTargetHardwareAddress(zeroMac)
+ .setTargetProtocolAddress(ipAddress.getAddress());
+
+ Ethernet eth = new Ethernet();
+ eth.setDestinationMACAddress(arpRequest.getSenderHardwareAddress())
+ .setSourceMACAddress(broadcastMac)
+ .setEtherType(Ethernet.TYPE_ARP)
+ .setPayload(arpRequest);
+
+ broadcastArpRequestOutEdge(eth.serialize(), 0, OFPort.OFPP_NONE.getValue());
+ }
+
+ //private void broadcastArpRequestOutEdge(OFPacketIn pi, long inSwitch, short inPort){
+ private void broadcastArpRequestOutEdge(byte[] arpRequest, long inSwitch, short inPort) {
for (IOFSwitch sw : floodlightProvider.getSwitches().values()){
Collection<Short> enabledPorts = sw.getEnabledPortNumbers();
Set<Short> linkPorts = topology.getPortsWithLinks(sw.getId());
@@ -176,7 +333,7 @@
OFPacketOut po = new OFPacketOut();
po.setInPort(OFPort.OFPP_NONE)
.setBufferId(-1)
- .setPacketData(pi.getPacketData());
+ .setPacketData(arpRequest);
List<OFAction> actions = new ArrayList<OFAction>();
@@ -196,7 +353,7 @@
short actionsLength = (short) (actions.size() * OFActionOutput.MINIMUM_LENGTH);
po.setActionsLength(actionsLength);
po.setLengthU(OFPacketOut.MINIMUM_LENGTH + actionsLength
- + pi.getPacketData().length);
+ + arpRequest.length);
List<OFMessage> msgList = new ArrayList<OFMessage>();
msgList.add(po);
@@ -210,26 +367,30 @@
}
}
- private void sendArpReply(ARP arpRequest, OFPacketIn pi, byte[] macRequested, IOFSwitch sw){
+ public void sendArpReply(ARP arpRequest, long dpid, short port, byte[] targetMac) {
+ //private void sendArpReply(ARP arpRequest, OFPacketIn pi, byte[] macRequested, IOFSwitch sw){
ARP arpReply = new ARP();
arpReply.setHardwareType(ARP.HW_TYPE_ETHERNET)
.setProtocolType(ARP.PROTO_TYPE_IP)
.setHardwareAddressLength((byte)Ethernet.DATALAYER_ADDRESS_LENGTH)
.setProtocolAddressLength((byte)4) //can't find the constant anywhere
.setOpCode(ARP.OP_REPLY)
- .setSenderHardwareAddress(macRequested)
+ //.setSenderHardwareAddress(macRequested)
+ .setSenderHardwareAddress(targetMac)
.setSenderProtocolAddress(arpRequest.getTargetProtocolAddress())
.setTargetHardwareAddress(arpRequest.getSenderHardwareAddress())
.setTargetProtocolAddress(arpRequest.getSenderProtocolAddress());
Ethernet eth = new Ethernet();
eth.setDestinationMACAddress(arpRequest.getSenderHardwareAddress())
- .setSourceMACAddress(macRequested)
+ //.setSourceMACAddress(macRequested)
+ .setSourceMACAddress(targetMac)
.setEtherType(Ethernet.TYPE_ARP)
.setPayload(arpReply);
List<OFAction> actions = new ArrayList<OFAction>();
- actions.add(new OFActionOutput(pi.getInPort()));
+ //actions.add(new OFActionOutput(pi.getInPort()));
+ actions.add(new OFActionOutput(port));
OFPacketOut po = new OFPacketOut();
po.setInPort(OFPort.OFPP_NONE)
@@ -242,9 +403,15 @@
List<OFMessage> msgList = new ArrayList<OFMessage>();
msgList.add(po);
+
+ IOFSwitch sw = floodlightProvider.getSwitches().get(dpid);
+
+ if (sw == null) {
+ return;
+ }
try {
- log.debug("Sending ARP reply to {}/{}", HexString.toHexString(sw.getId()), pi.getInPort());
+ log.debug("Sending ARP reply to {}/{}", HexString.toHexString(sw.getId()), port);
sw.write(msgList, null);
sw.flush();
} catch (IOException e) {
@@ -254,7 +421,7 @@
//TODO this should be put somewhere more central. I use it in BgpRoute as well.
//We need a HexString.toHexString() equivalent.
- private String bytesToStringAddr(byte[] bytes){
+ private String bytesToStringAddr(byte[] bytes) {
InetAddress addr;
try {
addr = InetAddress.getByAddress(bytes);
@@ -265,4 +432,22 @@
if (addr == null) return "";
else return addr.getHostAddress();
}
+
+
+ public byte[] getMacAddress(InetAddress ipAddress) {
+ return lookupArpTable(ipAddress.getAddress());
+ }
+
+ public byte[] sendArpRequest(InetAddress ipAddress, IArpRequester requester) {
+ byte[] lookupMac;
+ if ((lookupMac = lookupArpTable(ipAddress.getAddress())) == null) {
+ return lookupMac;
+ }
+
+ sendArpRequestForAddress(ipAddress);
+
+ storeRequester(ipAddress, requester);
+
+ return null;
+ }
}
diff --git a/src/main/java/net/onrc/onos/ofcontroller/util/DataPath.java b/src/main/java/net/onrc/onos/ofcontroller/util/DataPath.java
index 9b06743..dec70e3 100644
--- a/src/main/java/net/onrc/onos/ofcontroller/util/DataPath.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/util/DataPath.java
@@ -5,7 +5,7 @@
import org.codehaus.jackson.annotate.JsonProperty;
/**
- * The class representing the Data Path.
+ * The data forwarding path state from a source to a destination.
*/
public class DataPath {
private SwitchPort srcPort; // The source port
diff --git a/src/main/java/net/onrc/onos/ofcontroller/util/FlowEntry.java b/src/main/java/net/onrc/onos/ofcontroller/util/FlowEntry.java
index 7dd0699..049e783 100644
--- a/src/main/java/net/onrc/onos/ofcontroller/util/FlowEntry.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/util/FlowEntry.java
@@ -12,10 +12,10 @@
* support multiple in-ports and multiple out-ports.
*/
public class FlowEntry {
- private FlowId flowId; // FlowID of flowEntry
+ private FlowId flowId; // FlowID of the Flow Entry
private FlowEntryId flowEntryId; // The Flow Entry ID
private FlowEntryMatch flowEntryMatch; // The Flow Entry Match
- private ArrayList<FlowEntryAction> flowEntryActions; // The Flow Entry Actions
+ private FlowEntryActions flowEntryActions; // The Flow Entry Actions
private Dpid dpid; // The Switch DPID
private Port inPort; // The Switch incoming port. Used only
// when the entry is used to return
@@ -53,64 +53,64 @@
flowEntryMatch.enableDstTcpUdpPort((short)80);
FlowEntryAction action = null;
- ArrayList<FlowEntryAction> actions = new ArrayList<FlowEntryAction>();
+ FlowEntryActions actions = new FlowEntryActions();
action = new FlowEntryAction();
action.setActionOutput(new Port((short)12));
- actions.add(action);
+ actions.addAction(action);
action = new FlowEntryAction();
action.setActionOutputToController((short)13);
- actions.add(action);
+ actions.addAction(action);
action = new FlowEntryAction();
action.setActionSetVlanId((short)14);
- actions.add(action);
+ actions.addAction(action);
action = new FlowEntryAction();
action.setActionSetVlanPriority((byte)15);
- actions.add(action);
+ actions.addAction(action);
action = new FlowEntryAction();
action.setActionStripVlan(true);
- actions.add(action);
+ actions.addAction(action);
action = new FlowEntryAction();
action.setActionSetEthernetSrcAddr(mac);
- actions.add(action);
+ actions.addAction(action);
action = new FlowEntryAction();
action.setActionSetEthernetDstAddr(mac);
- actions.add(action);
+ actions.addAction(action);
action = new FlowEntryAction();
action.setActionSetIPv4SrcAddr(ipv4);
- actions.add(action);
+ actions.addAction(action);
action = new FlowEntryAction();
action.setActionSetIPv4DstAddr(ipv4);
- actions.add(action);
+ actions.addAction(action);
action = new FlowEntryAction();
action.setActionSetIpToS((byte)16);
- actions.add(action);
+ actions.addAction(action);
action = new FlowEntryAction();
action.setActionSetTcpUdpSrcPort((short)17);
- actions.add(action);
+ actions.addAction(action);
action = new FlowEntryAction();
action.setActionSetTcpUdpDstPort((short)18);
- actions.add(action);
+ actions.addAction(action);
action = new FlowEntryAction();
action.setActionEnqueue(new Port((short)19), 20);
- actions.add(action);
+ actions.addAction(action);
setFlowEntryActions(actions);
*/
-
+ flowEntryActions = new FlowEntryActions();
flowEntryUserState = FlowEntryUserState.FE_USER_UNKNOWN;
flowEntrySwitchState = FlowEntrySwitchState.FE_SWITCH_UNKNOWN;
}
@@ -173,7 +173,7 @@
* @return the Flow Entry Actions.
*/
@JsonProperty("flowEntryActions")
- public ArrayList<FlowEntryAction> flowEntryActions() {
+ public FlowEntryActions flowEntryActions() {
return flowEntryActions;
}
@@ -183,7 +183,7 @@
* @param flowEntryActions the Flow Entry Actions to set.
*/
@JsonProperty("flowEntryActions")
- public void setFlowEntryActions(ArrayList<FlowEntryAction> flowEntryActions) {
+ public void setFlowEntryActions(FlowEntryActions flowEntryActions) {
this.flowEntryActions = flowEntryActions;
}
@@ -319,8 +319,7 @@
* Convert the flow entry to a string.
*
* The string has the following form:
- * [flowEntryId=XXX flowEntryMatch=XXX flowEntryAction=XXX
- * flowEntryAction=XXX flowEntryAction=XXX dpid=XXX
+ * [flowEntryId=XXX flowEntryMatch=XXX flowEntryActions=XXX dpid=XXX
* inPort=XXX outPort=XXX flowEntryUserState=XXX flowEntrySwitchState=XXX
* flowEntryErrorState=XXX]
* @return the flow entry as a string.
@@ -329,9 +328,7 @@
public String toString() {
String ret = "[flowEntryId=" + this.flowEntryId.toString();
ret += " flowEntryMatch=" + this.flowEntryMatch.toString();
- for (FlowEntryAction fa : flowEntryActions) {
- ret += " flowEntryAction=" + fa.toString();
- }
+ ret += " flowEntryActions=" + this.flowEntryActions.toString();
ret += " dpid=" + this.dpid.toString();
ret += " inPort=" + this.inPort.toString();
ret += " outPort=" + this.outPort.toString();
diff --git a/src/main/java/net/onrc/onos/ofcontroller/util/FlowEntryAction.java b/src/main/java/net/onrc/onos/ofcontroller/util/FlowEntryAction.java
index 22aef98..f150983 100644
--- a/src/main/java/net/onrc/onos/ofcontroller/util/FlowEntryAction.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/util/FlowEntryAction.java
@@ -7,7 +7,9 @@
/**
* The class representing a single Flow Entry action.
*
- * A set of Flow Entry actions need to be applied to each packet.
+ * A Flow Entry action that needs to be applied to each packet.
+ * Note that it contains only a single action. Multiple actions are
+ * listed in a list inside @ref FlowEntryActions.
*/
public class FlowEntryAction {
/**
@@ -59,6 +61,28 @@
this.maxLen = 0;
}
+ /**
+ * Copy constructor.
+ *
+ * @param other the object to copy from.
+ */
+ public ActionOutput(ActionOutput other) {
+ if (other.port != null)
+ this.port = new Port(other.port);
+ this.maxLen = other.maxLen;
+ }
+
+ /**
+ * Constructor from a string.
+ *
+ * The string has the following form:
+ * [port=XXX maxLen=XXX]
+ *
+ * @param actionStr the action as a string.
+ */
+ public ActionOutput(String actionStr) {
+ this.fromString(actionStr);
+ }
/**
* Constructor for a given output port and maximum length.
@@ -121,6 +145,54 @@
return ret;
}
+
+ /**
+ * Convert a string to an action.
+ *
+ * The string has the following form:
+ * [port=XXX maxLen=XXX]
+ *
+ * @param actionStr the action as a string.
+ */
+ public void fromString(String actionStr) {
+ String[] parts = actionStr.split(" ");
+ String decode = null;
+
+ // Decode the "port=XXX" part
+ if (parts.length > 0)
+ decode = parts[0];
+ if (decode != null) {
+ String[] tokens = decode.split("port=");
+ if (tokens.length > 1 && tokens[1] != null) {
+ try {
+ Short valueShort = Short.valueOf(tokens[1]);
+ port = new Port(valueShort);
+ } catch (NumberFormatException e) {
+ throw new IllegalArgumentException("Invalid action string");
+ }
+ }
+ } else {
+ throw new IllegalArgumentException("Invalid action string");
+ }
+
+ // Decode the "maxLen=XXX" part
+ decode = null;
+ if (parts.length > 1)
+ decode = parts[1];
+ if (decode != null) {
+ decode = decode.replace("]", "");
+ String[] tokens = decode.split("maxLen=");
+ if (tokens.length > 1 && tokens[1] != null) {
+ try {
+ maxLen = Short.valueOf(tokens[1]);
+ } catch (NumberFormatException e) {
+ throw new IllegalArgumentException("Invalid action string");
+ }
+ }
+ } else {
+ throw new IllegalArgumentException("Invalid action string");
+ }
+ }
}
/**
@@ -137,6 +209,27 @@
}
/**
+ * Copy constructor.
+ *
+ * @param other the object to copy from.
+ */
+ public ActionSetVlanId(ActionSetVlanId other) {
+ this.vlanId = other.vlanId;
+ }
+
+ /**
+ * Constructor from a string.
+ *
+ * The string has the following form:
+ * [vlanId=XXX]
+ *
+ * @param actionStr the action as a string.
+ */
+ public ActionSetVlanId(String actionStr) {
+ this.fromString(actionStr);
+ }
+
+ /**
* Constructor for a given VLAN ID.
*
* @param vlanId the VLAN ID to set.
@@ -171,6 +264,33 @@
return ret;
}
+
+ /**
+ * Convert a string to an action.
+ *
+ * The string has the following form:
+ * [vlanId=XXX]
+ *
+ * @param actionStr the action as a string.
+ */
+ public void fromString(String actionStr) {
+ String[] parts = actionStr.split("vlanId=");
+ String decode = null;
+
+ // Decode the value
+ if (parts.length > 1)
+ decode = parts[1];
+ if (decode != null) {
+ decode = decode.replace("]", "");
+ try {
+ vlanId = Short.valueOf(decode);
+ } catch (NumberFormatException e) {
+ throw new IllegalArgumentException("Invalid action string");
+ }
+ } else {
+ throw new IllegalArgumentException("Invalid action string");
+ }
+ }
}
/**
@@ -187,6 +307,27 @@
}
/**
+ * Copy constructor.
+ *
+ * @param other the object to copy from.
+ */
+ public ActionSetVlanPriority(ActionSetVlanPriority other) {
+ this.vlanPriority = other.vlanPriority;
+ }
+
+ /**
+ * Constructor from a string.
+ *
+ * The string has the following form:
+ * [vlanPriority=XXX]
+ *
+ * @param actionStr the action as a string.
+ */
+ public ActionSetVlanPriority(String actionStr) {
+ this.fromString(actionStr);
+ }
+
+ /**
* Constructor for a given VLAN priority.
*
* @param vlanPriority the VLAN priority to set.
@@ -221,6 +362,33 @@
return ret;
}
+
+ /**
+ * Convert a string to an action.
+ *
+ * The string has the following form:
+ * [vlanPriority=XXX]
+ *
+ * @param actionStr the action as a string.
+ */
+ public void fromString(String actionStr) {
+ String[] parts = actionStr.split("vlanPriority=");
+ String decode = null;
+
+ // Decode the value
+ if (parts.length > 1)
+ decode = parts[1];
+ if (decode != null) {
+ decode = decode.replace("]", "");
+ try {
+ vlanPriority = Byte.valueOf(decode);
+ } catch (NumberFormatException e) {
+ throw new IllegalArgumentException("Invalid action string");
+ }
+ } else {
+ throw new IllegalArgumentException("Invalid action string");
+ }
+ }
}
/**
@@ -237,6 +405,27 @@
}
/**
+ * Copy constructor.
+ *
+ * @param other the object to copy from.
+ */
+ public ActionStripVlan(ActionStripVlan other) {
+ this.stripVlan = other.stripVlan;
+ }
+
+ /**
+ * Constructor from a string.
+ *
+ * The string has the following form:
+ * [stripVlan=XXX]
+ *
+ * @param actionStr the action as a string.
+ */
+ public ActionStripVlan(String actionStr) {
+ this.fromString(actionStr);
+ }
+
+ /**
* Constructor for a given boolean flag.
*
* @param stripVlan if true, strip the VLAN header.
@@ -271,6 +460,29 @@
return ret;
}
+
+ /**
+ * Convert a string to an action.
+ *
+ * The string has the following form:
+ * [stripVlan=XXX]
+ *
+ * @param actionStr the action as a string.
+ */
+ public void fromString(String actionStr) {
+ String[] parts = actionStr.split("stripVlan=");
+ String decode = null;
+
+ // Decode the value
+ if (parts.length > 1)
+ decode = parts[1];
+ if (decode != null) {
+ decode = decode.replace("]", "");
+ stripVlan = Boolean.valueOf(decode);
+ } else {
+ throw new IllegalArgumentException("Invalid action string");
+ }
+ }
}
/**
@@ -288,6 +500,28 @@
}
/**
+ * Copy constructor.
+ *
+ * @param other the object to copy from.
+ */
+ public ActionSetEthernetAddr(ActionSetEthernetAddr other) {
+ if (other.addr != null)
+ this.addr = MACAddress.valueOf(other.addr.toLong());
+ }
+
+ /**
+ * Constructor from a string.
+ *
+ * The string has the following form:
+ * [addr=XXX]
+ *
+ * @param actionStr the action as a string.
+ */
+ public ActionSetEthernetAddr(String actionStr) {
+ this.fromString(actionStr);
+ }
+
+ /**
* Constructor for a given MAC address.
*
* @param addr the MAC address to set.
@@ -322,6 +556,33 @@
return ret;
}
+
+ /**
+ * Convert a string to an action.
+ *
+ * The string has the following form:
+ * [addr=XXX]
+ *
+ * @param actionStr the action as a string.
+ */
+ public void fromString(String actionStr) {
+ String[] parts = actionStr.split("addr=");
+ String decode = null;
+
+ // Decode the value
+ if (parts.length > 1)
+ decode = parts[1];
+ if (decode != null) {
+ decode = decode.replace("]", "");
+ try {
+ addr = MACAddress.valueOf(decode);
+ } catch (IllegalArgumentException e) {
+ throw new IllegalArgumentException("Invalid action string");
+ }
+ } else {
+ throw new IllegalArgumentException("Invalid action string");
+ }
+ }
}
/**
@@ -339,6 +600,28 @@
}
/**
+ * Copy constructor.
+ *
+ * @param other the object to copy from.
+ */
+ public ActionSetIPv4Addr(ActionSetIPv4Addr other) {
+ if (other.addr != null)
+ this.addr = new IPv4(other.addr);
+ }
+
+ /**
+ * Constructor from a string.
+ *
+ * The string has the following form:
+ * [addr=XXX]
+ *
+ * @param actionStr the action as a string.
+ */
+ public ActionSetIPv4Addr(String actionStr) {
+ this.fromString(actionStr);
+ }
+
+ /**
* Constructor for a given IPv4 address.
*
* @param addr the IPv4 address to set.
@@ -373,6 +656,33 @@
return ret;
}
+
+ /**
+ * Convert a string to an action.
+ *
+ * The string has the following form:
+ * [addr=XXX]
+ *
+ * @param actionStr the action as a string.
+ */
+ public void fromString(String actionStr) {
+ String[] parts = actionStr.split("addr=");
+ String decode = null;
+
+ // Decode the value
+ if (parts.length > 1)
+ decode = parts[1];
+ if (decode != null) {
+ decode = decode.replace("]", "");
+ try {
+ addr = new IPv4(decode);
+ } catch (IllegalArgumentException e) {
+ throw new IllegalArgumentException("Invalid action string");
+ }
+ } else {
+ throw new IllegalArgumentException("Invalid action string");
+ }
+ }
}
/**
@@ -390,6 +700,27 @@
}
/**
+ * Copy constructor.
+ *
+ * @param other the object to copy from.
+ */
+ public ActionSetIpToS(ActionSetIpToS other) {
+ this.ipToS = other.ipToS;
+ }
+
+ /**
+ * Constructor from a string.
+ *
+ * The string has the following form:
+ * [ipToS=XXX]
+ *
+ * @param actionStr the action as a string.
+ */
+ public ActionSetIpToS(String actionStr) {
+ this.fromString(actionStr);
+ }
+
+ /**
* Constructor for a given IP ToS (DSCP field, 6 bits).
*
* @param ipToS the IP ToS (DSCP field, 6 bits) to set.
@@ -424,6 +755,33 @@
return ret;
}
+
+ /**
+ * Convert a string to an action.
+ *
+ * The string has the following form:
+ * [ipToS=XXX]
+ *
+ * @param actionStr the action as a string.
+ */
+ public void fromString(String actionStr) {
+ String[] parts = actionStr.split("ipToS=");
+ String decode = null;
+
+ // Decode the value
+ if (parts.length > 1)
+ decode = parts[1];
+ if (decode != null) {
+ decode = decode.replace("]", "");
+ try {
+ ipToS = Byte.valueOf(decode);
+ } catch (NumberFormatException e) {
+ throw new IllegalArgumentException("Invalid action string");
+ }
+ } else {
+ throw new IllegalArgumentException("Invalid action string");
+ }
+ }
}
/**
@@ -441,6 +799,27 @@
}
/**
+ * Copy constructor.
+ *
+ * @param other the object to copy from.
+ */
+ public ActionSetTcpUdpPort(ActionSetTcpUdpPort other) {
+ this.port = other.port;
+ }
+
+ /**
+ * Constructor from a string.
+ *
+ * The string has the following form:
+ * [port=XXX]
+ *
+ * @param actionStr the action as a string.
+ */
+ public ActionSetTcpUdpPort(String actionStr) {
+ this.fromString(actionStr);
+ }
+
+ /**
* Constructor for a given TCP/UDP port.
*
* @param port the TCP/UDP port to set.
@@ -475,6 +854,33 @@
return ret;
}
+
+ /**
+ * Convert a string to an action.
+ *
+ * The string has the following form:
+ * [port=XXX]
+ *
+ * @param actionStr the action as a string.
+ */
+ public void fromString(String actionStr) {
+ String[] parts = actionStr.split("port=");
+ String decode = null;
+
+ // Decode the value
+ if (parts.length > 1)
+ decode = parts[1];
+ if (decode != null) {
+ decode = decode.replace("]", "");
+ try {
+ port = Short.valueOf(decode);
+ } catch (NumberFormatException e) {
+ throw new IllegalArgumentException("Invalid action string");
+ }
+ } else {
+ throw new IllegalArgumentException("Invalid action string");
+ }
+ }
}
/**
@@ -495,6 +901,29 @@
}
/**
+ * Copy constructor.
+ *
+ * @param other the object to copy from.
+ */
+ public ActionEnqueue(ActionEnqueue other) {
+ if (other.port != null)
+ this.port = new Port(other.port);
+ this.queueId = other.queueId;
+ }
+
+ /**
+ * Constructor from a string.
+ *
+ * The string has the following form:
+ * [port=XXX queueId=XXX]
+ *
+ * @param actionStr the action as a string.
+ */
+ public ActionEnqueue(String actionStr) {
+ this.fromString(actionStr);
+ }
+
+ /**
* Constructor for a given port and queue ID.
*
* @param port the port to set.
@@ -542,6 +971,54 @@
return ret;
}
+
+ /**
+ * Convert a string to an action.
+ *
+ * The string has the following form:
+ * [port=XXX queueId=XXX]
+ *
+ * @param actionStr the action as a string.
+ */
+ public void fromString(String actionStr) {
+ String[] parts = actionStr.split(" ");
+ String decode = null;
+
+ // Decode the "port=XXX" part
+ if (parts.length > 0)
+ decode = parts[0];
+ if (decode != null) {
+ String[] tokens = decode.split("port=");
+ if (tokens.length > 1 && tokens[1] != null) {
+ try {
+ Short valueShort = Short.valueOf(tokens[1]);
+ port = new Port(valueShort);
+ } catch (NumberFormatException e) {
+ throw new IllegalArgumentException("Invalid action string");
+ }
+ }
+ } else {
+ throw new IllegalArgumentException("Invalid action string");
+ }
+
+ // Decode the "queueId=XXX" part
+ decode = null;
+ if (parts.length > 1)
+ decode = parts[1];
+ if (decode != null) {
+ decode = decode.replace("]", "");
+ String[] tokens = decode.split("queueId=");
+ if (tokens.length > 1 && tokens[1] != null) {
+ try {
+ queueId = Short.valueOf(tokens[1]);
+ } catch (NumberFormatException e) {
+ throw new IllegalArgumentException("Invalid action string");
+ }
+ }
+ } else {
+ throw new IllegalArgumentException("Invalid action string");
+ }
+ }
}
private ActionValues actionType; // The action type
@@ -571,6 +1048,88 @@
}
/**
+ * Copy constructor.
+ *
+ * @param other the object to copy from.
+ */
+ public FlowEntryAction(FlowEntryAction other) {
+ this.actionType = other.actionType;
+
+ //
+ if (other.actionOutput != null)
+ this.actionOutput = new ActionOutput(other.actionOutput);
+ else
+ this.actionOutput = null;
+ //
+ if (other.actionSetVlanId != null)
+ this.actionSetVlanId = new ActionSetVlanId(other.actionSetVlanId);
+ else
+ this.actionSetVlanId = null;
+ //
+ if (other.actionSetVlanPriority != null)
+ this.actionSetVlanPriority = new ActionSetVlanPriority(other.actionSetVlanPriority);
+ else
+ this.actionSetVlanPriority = null;
+ //
+ if (other.actionStripVlan != null)
+ this.actionStripVlan = new ActionStripVlan(other.actionStripVlan);
+ else
+ this.actionStripVlan = null;
+ //
+ if (other.actionSetEthernetSrcAddr != null)
+ this.actionSetEthernetSrcAddr = new ActionSetEthernetAddr(other.actionSetEthernetSrcAddr);
+ else
+ this.actionSetEthernetSrcAddr = null;
+ //
+ if (other.actionSetEthernetDstAddr != null)
+ this.actionSetEthernetDstAddr = new ActionSetEthernetAddr(other.actionSetEthernetDstAddr);
+ else
+ this.actionSetEthernetDstAddr = null;
+ //
+ if (other.actionSetIPv4SrcAddr != null)
+ this.actionSetIPv4SrcAddr = new ActionSetIPv4Addr(other.actionSetIPv4SrcAddr);
+ else
+ this.actionSetIPv4SrcAddr = null;
+ //
+ if (other.actionSetIPv4DstAddr != null)
+ this.actionSetIPv4DstAddr = new ActionSetIPv4Addr(other.actionSetIPv4DstAddr);
+ else
+ this.actionSetIPv4DstAddr = null;
+ //
+ if (other.actionSetIpToS != null)
+ this.actionSetIpToS = new ActionSetIpToS(other.actionSetIpToS);
+ else
+ this.actionSetIpToS = null;
+ //
+ if (other.actionSetTcpUdpSrcPort != null)
+ this.actionSetTcpUdpSrcPort = new ActionSetTcpUdpPort(other.actionSetTcpUdpSrcPort);
+ else
+ this.actionSetTcpUdpSrcPort = null;
+ //
+ if (other.actionSetTcpUdpDstPort != null)
+ this.actionSetTcpUdpDstPort = new ActionSetTcpUdpPort(other.actionSetTcpUdpDstPort);
+ else
+ this.actionSetTcpUdpDstPort = null;
+ //
+ if (other.actionEnqueue != null)
+ this.actionEnqueue = new ActionEnqueue(other.actionEnqueue);
+ else
+ this.actionEnqueue = null;
+ }
+
+ /**
+ * Constructor from a string.
+ *
+ * The string has the following form:
+ * [type=XXX action=XXX]
+ *
+ * @param actionStr the action as a string.
+ */
+ public FlowEntryAction(String actionStr) {
+ this.fromString(actionStr);
+ }
+
+ /**
* Get the action type.
*
* @return the action type.
@@ -957,12 +1516,12 @@
}
/**
- * Convert the set of actions to a string.
+ * Convert the action to a string.
*
* The string has the following form:
* [type=XXX action=XXX]
*
- * @return the set of actions as a string.
+ * @return the action as a string.
*/
@Override
public String toString() {
@@ -1010,4 +1569,96 @@
return ret;
}
+
+ /**
+ * Convert a string to an action.
+ *
+ * The string has the following form:
+ * [type=XXX action=XXX]
+ *
+ * @param actionStr the action as a string.
+ */
+ public void fromString(String actionStr) {
+ String[] parts = actionStr.split("type=");
+ String decode = null;
+
+ // Extract the string after the "type="
+ if (parts.length > 1)
+ decode = parts[1];
+ if (decode == null)
+ throw new IllegalArgumentException("Invalid action string");
+
+ // Remove the trailing ']'
+ if ((decode.length() > 0) && (decode.charAt(decode.length() - 1) == ']')) {
+ decode = decode.substring(0, decode.length() - 1);
+ } else {
+ throw new IllegalArgumentException("Invalid action string");
+ }
+
+ // Extract the type value and the action value
+ parts = decode.split(" action=");
+
+ // Decode the "type=XXX" payload
+ if (parts.length > 0)
+ decode = parts[0];
+ if (decode != null) {
+ try {
+ actionType = Enum.valueOf(ActionValues.class, decode);
+ } catch (IllegalArgumentException e) {
+ throw new IllegalArgumentException("Invalid action string");
+ }
+ } else {
+ throw new IllegalArgumentException("Invalid action string");
+ }
+
+ // Decode the "action=XXX" payload
+ decode = null;
+ if (parts.length > 1)
+ decode = parts[1];
+ if (decode == null)
+ throw new IllegalArgumentException("Invalid action string");
+ //
+ try {
+ switch (actionType) {
+ case ACTION_OUTPUT:
+ actionOutput = new ActionOutput(decode);
+ break;
+ case ACTION_SET_VLAN_VID:
+ actionSetVlanId = new ActionSetVlanId(decode);
+ break;
+ case ACTION_SET_VLAN_PCP:
+ actionSetVlanPriority = new ActionSetVlanPriority(decode);
+ break;
+ case ACTION_STRIP_VLAN:
+ actionStripVlan = new ActionStripVlan(decode);
+ break;
+ case ACTION_SET_DL_SRC:
+ actionSetEthernetSrcAddr = new ActionSetEthernetAddr(decode);
+ break;
+ case ACTION_SET_DL_DST:
+ actionSetEthernetDstAddr = new ActionSetEthernetAddr(decode);
+ break;
+ case ACTION_SET_NW_SRC:
+ actionSetIPv4SrcAddr = new ActionSetIPv4Addr(decode);
+ break;
+ case ACTION_SET_NW_DST:
+ actionSetIPv4DstAddr = new ActionSetIPv4Addr(decode);
+ break;
+ case ACTION_SET_NW_TOS:
+ actionSetIpToS = new ActionSetIpToS(decode);
+ break;
+ case ACTION_SET_TP_SRC:
+ actionSetTcpUdpSrcPort = new ActionSetTcpUdpPort(decode);
+ break;
+ case ACTION_SET_TP_DST:
+ actionSetTcpUdpDstPort = new ActionSetTcpUdpPort(decode);
+ break;
+ case ACTION_ENQUEUE:
+ actionEnqueue = new ActionEnqueue(decode);
+ break;
+ }
+ } catch (IllegalArgumentException e) {
+ throw new IllegalArgumentException("Invalid action string");
+ }
+ }
}
diff --git a/src/main/java/net/onrc/onos/ofcontroller/util/FlowEntryActions.java b/src/main/java/net/onrc/onos/ofcontroller/util/FlowEntryActions.java
new file mode 100644
index 0000000..46f638d
--- /dev/null
+++ b/src/main/java/net/onrc/onos/ofcontroller/util/FlowEntryActions.java
@@ -0,0 +1,146 @@
+package net.onrc.onos.ofcontroller.util;
+
+import java.util.ArrayList;
+
+import org.codehaus.jackson.annotate.JsonProperty;
+
+/**
+ * The class representing multiple Flow Entry actions.
+ *
+ * A set of Flow Entry actions need to be applied to each packet.
+ */
+public class FlowEntryActions {
+ private ArrayList<FlowEntryAction> actions; // The Flow Entry Actions
+
+ /**
+ * Default constructor.
+ */
+ public FlowEntryActions() {
+ actions = new ArrayList<FlowEntryAction>();
+ }
+
+ /**
+ * Constructor from a string.
+ *
+ * The string has the following form:
+ * [[type=XXX action=XXX];[type=XXX action=XXX];...;]
+ *
+ * @param actionsStr the set of actions as a string.
+ */
+ public FlowEntryActions(String actionsStr) {
+ this.fromString(actionsStr);
+ }
+
+ /**
+ * Copy constructor.
+ *
+ * @param other the object to copy from.
+ */
+ public FlowEntryActions(FlowEntryActions other) {
+ actions = new ArrayList<FlowEntryAction>();
+
+ for (FlowEntryAction action : other.actions) {
+ FlowEntryAction newAction = new FlowEntryAction(action);
+ actions.add(newAction);
+ }
+ }
+
+ /**
+ * Get the Flow Entry Actions.
+ *
+ * @return the Flow Entry Actions.
+ */
+ @JsonProperty("actions")
+ public ArrayList<FlowEntryAction> actions() {
+ return actions;
+ }
+
+ /**
+ * Set the Flow Entry Actions.
+ *
+ * @param actions the Flow Entry Actions to set.
+ */
+ @JsonProperty("actions")
+ public void setActions(ArrayList<FlowEntryAction> actions) {
+ this.actions = actions;
+ }
+
+ /**
+ * Add a Flow Entry Action.
+ *
+ * @param FlowEntryAction the Flow Entry Action to add.
+ */
+ public void addAction(FlowEntryAction flowEntryAction) {
+ actions.add(flowEntryAction);
+ }
+
+ /**
+ * Test whether the set of actions is empty.
+ *
+ * @return true if the set of actions is empty, otherwise false.
+ */
+ public Boolean isEmpty() {
+ return actions.isEmpty();
+ }
+
+ /**
+ * Convert the set of actions to a string.
+ *
+ * The string has the following form:
+ * [[type=XXX action=XXX];[type=XXX action=XXX];...;]
+ *
+ * @return the set of actions as a string.
+ */
+ @Override
+ public String toString() {
+ String ret = "[";
+ for (FlowEntryAction action : actions) {
+ ret += action.toString() + ";";
+ }
+ ret += "]";
+
+ return ret;
+ }
+
+ /**
+ * Convert a string to a set of actions.
+ *
+ * The string has the following form:
+ * [[type=XXX action=XXX];[type=XXX action=XXX];...;]
+ *
+ * @param actionsStr the set of actions as a string.
+ */
+ public void fromString(String actionsStr) {
+ String decode = actionsStr;
+
+ actions = new ArrayList<FlowEntryAction>();
+
+ if (decode.isEmpty())
+ return; // Nothing to do
+
+ // Remove the '[' and ']' in the beginning and the end of the string
+ if ((decode.length() > 1) && (decode.charAt(0) == '[') &&
+ (decode.charAt(decode.length() - 1) == ']')) {
+ decode = decode.substring(1, decode.length() - 1);
+ } else {
+ throw new IllegalArgumentException("Invalid action string");
+ }
+
+ // Split the string, and decode each action
+ String[] parts = decode.split(";");
+ for (int i = 0; i < parts.length; i++) {
+ decode = parts[i];
+ if ((decode == null) || decode.isEmpty())
+ continue;
+ FlowEntryAction flowEntryAction = null;
+ try {
+ flowEntryAction = new FlowEntryAction(decode);
+ } catch (IllegalArgumentException e) {
+ // TODO: Ignore invalid actions for now
+ continue;
+ }
+ if (flowEntryAction != null)
+ actions.add(flowEntryAction);
+ }
+ }
+}
diff --git a/src/main/java/net/onrc/onos/ofcontroller/util/FlowPath.java b/src/main/java/net/onrc/onos/ofcontroller/util/FlowPath.java
index 2f4d421..153e184 100644
--- a/src/main/java/net/onrc/onos/ofcontroller/util/FlowPath.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/util/FlowPath.java
@@ -19,6 +19,8 @@
private DataPath dataPath; // The data path
private FlowEntryMatch flowEntryMatch; // Common Flow Entry Match for all
// Flow Entries
+ private FlowEntryActions flowEntryActions; // The Flow Entry Actions for
+ // the first Flow Entry
/**
* Default constructor.
@@ -26,6 +28,7 @@
public FlowPath() {
flowPathFlags = new FlowPathFlags();
dataPath = new DataPath();
+ flowEntryActions = new FlowEntryActions();
}
/**
@@ -82,6 +85,19 @@
this.setFlowEntryMatch(match);
}
+ //
+ // Extract the actions for the first Flow Entry
+ //
+ {
+ FlowEntryActions actions = new FlowEntryActions();
+
+ String actionsStr = flowObj.getActions();
+ if (actions != null)
+ actions = new FlowEntryActions(actionsStr);
+
+ this.setFlowEntryActions(actions);
+ }
+
//
// Extract all Flow Entries
//
@@ -95,64 +111,77 @@
// Extract the match conditions
//
FlowEntryMatch match = new FlowEntryMatch();
+ //
Short matchInPort = flowEntryObj.getMatchInPort();
if (matchInPort != null)
match.enableInPort(new Port(matchInPort));
+ //
String matchSrcMac = flowEntryObj.getMatchSrcMac();
if (matchSrcMac != null)
match.enableSrcMac(MACAddress.valueOf(matchSrcMac));
+ //
String matchDstMac = flowEntryObj.getMatchDstMac();
if (matchDstMac != null)
match.enableDstMac(MACAddress.valueOf(matchDstMac));
+ //
Short matchEthernetFrameType = flowEntryObj.getMatchEthernetFrameType();
if (matchEthernetFrameType != null)
match.enableEthernetFrameType(matchEthernetFrameType);
+ //
Short matchVlanId = flowEntryObj.getMatchVlanId();
if (matchVlanId != null)
match.enableVlanId(matchVlanId);
+ //
Byte matchVlanPriority = flowEntryObj.getMatchVlanPriority();
if (matchVlanPriority != null)
match.enableVlanPriority(matchVlanPriority);
+ //
String matchSrcIPv4Net = flowEntryObj.getMatchSrcIPv4Net();
if (matchSrcIPv4Net != null)
match.enableSrcIPv4Net(new IPv4Net(matchSrcIPv4Net));
+ //
String matchDstIPv4Net = flowEntryObj.getMatchDstIPv4Net();
if (matchDstIPv4Net != null)
match.enableDstIPv4Net(new IPv4Net(matchDstIPv4Net));
+ //
Byte matchIpProto = flowEntryObj.getMatchIpProto();
if (matchIpProto != null)
match.enableIpProto(matchIpProto);
+ //
Byte matchIpToS = flowEntryObj.getMatchIpToS();
if (matchIpToS != null)
match.enableIpToS(matchIpToS);
+ //
Short matchSrcTcpUdpPort = flowEntryObj.getMatchSrcTcpUdpPort();
if (matchSrcTcpUdpPort != null)
match.enableSrcTcpUdpPort(matchSrcTcpUdpPort);
+ //
Short matchDstTcpUdpPort = flowEntryObj.getMatchDstTcpUdpPort();
if (matchDstTcpUdpPort != null)
match.enableDstTcpUdpPort(matchDstTcpUdpPort);
+ //
flowEntry.setFlowEntryMatch(match);
- //
- // Extract the actions
- //
- ArrayList<FlowEntryAction> actions = new ArrayList<FlowEntryAction>();
- Short actionOutputPort = flowEntryObj.getActionOutput();
- if (actionOutputPort != null) {
- FlowEntryAction action = new FlowEntryAction();
- action.setActionOutput(new Port(actionOutputPort));
- actions.add(action);
- }
- flowEntry.setFlowEntryActions(actions);
+ //
+ // Extract the actions
+ //
+ {
+ FlowEntryActions actions = new FlowEntryActions();
+
+ String actionsStr = flowObj.getActions();
+ if (actions != null)
+ actions = new FlowEntryActions(actionsStr);
+
+ flowEntry.setFlowEntryActions(actions);
+ }
String userState = flowEntryObj.getUserState();
flowEntry.setFlowEntryUserState(FlowEntryUserState.valueOf(userState));
String switchState = flowEntryObj.getSwitchState();
flowEntry.setFlowEntrySwitchState(FlowEntrySwitchState.valueOf(switchState));
- //
- // TODO: Take care of the FlowEntryMatch, FlowEntryAction set,
- // and FlowEntryErrorState.
- //
+ //
+ // TODO: Take care of the FlowEntryErrorState.
+ //
this.dataPath().flowEntries().add(flowEntry);
}
}
@@ -249,10 +278,32 @@
}
/**
+ * Get the flow path's flow entry actions for the first Flow Entry.
+ *
+ * @return the flow path's flow entry actions for the first Flow Entry.
+ */
+ @JsonProperty("flowEntryActions")
+ public FlowEntryActions flowEntryActions() {
+ return flowEntryActions;
+ }
+
+ /**
+ * Set the flow path's flow entry actions for the first Flow Entry.
+ *
+ * @param flowEntryActions the flow path's flow entry actions for the first
+ * Flow Entry.
+ */
+ @JsonProperty("flowEntryActions")
+ public void setFlowEntryActions(FlowEntryActions flowEntryActions) {
+ this.flowEntryActions = flowEntryActions;
+ }
+
+ /**
* Convert the flow path to a string.
*
* The string has the following form:
- * [flowId=XXX installerId=XXX flowPathFlags=XXX dataPath=XXX]
+ * [flowId=XXX installerId=XXX flowPathFlags=XXX dataPath=XXX
+ * flowEntryMatch=XXX flowEntryActions=XXX]
*
* @return the flow path as a string.
*/
@@ -265,6 +316,8 @@
ret += " dataPath=" + this.dataPath.toString();
if (flowEntryMatch != null)
ret += " flowEntryMatch=" + this.flowEntryMatch.toString();
+ if (flowEntryActions != null)
+ ret += " flowEntryActions=" + this.flowEntryActions.toString();
ret += "]";
return ret;
}
@@ -276,5 +329,4 @@
public int compareTo(FlowPath f) {
return (int) (this.flowId.value() - f.flowId.value());
}
-
}
diff --git a/src/main/java/net/onrc/onos/ofcontroller/util/IPv4.java b/src/main/java/net/onrc/onos/ofcontroller/util/IPv4.java
index 2081bbe..119165c 100644
--- a/src/main/java/net/onrc/onos/ofcontroller/util/IPv4.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/util/IPv4.java
@@ -22,6 +22,15 @@
}
/**
+ * Copy constructor.
+ *
+ * @param other the object to copy from.
+ */
+ public IPv4(IPv4 other) {
+ this.value = other.value;
+ }
+
+ /**
* Constructor from an integer value.
*
* @param value the value to use.
diff --git a/src/main/java/net/onrc/onos/ofcontroller/util/IPv4Net.java b/src/main/java/net/onrc/onos/ofcontroller/util/IPv4Net.java
index 52e6535..9ce247c 100644
--- a/src/main/java/net/onrc/onos/ofcontroller/util/IPv4Net.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/util/IPv4Net.java
@@ -23,6 +23,17 @@
}
/**
+ * Copy constructor.
+ *
+ * @param other the object to copy from.
+ */
+ public IPv4Net(IPv4Net other) {
+ if (other.address != null)
+ this.address = new IPv4(other.address);
+ this.prefixLen = other.prefixLen;
+ }
+
+ /**
* Constructor for a given address and prefix length.
*
* @param address the address to use.
diff --git a/src/main/java/net/onrc/onos/ofcontroller/util/IPv6.java b/src/main/java/net/onrc/onos/ofcontroller/util/IPv6.java
index 2d28db8..f5dae11 100644
--- a/src/main/java/net/onrc/onos/ofcontroller/util/IPv6.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/util/IPv6.java
@@ -25,6 +25,16 @@
}
/**
+ * Copy constructor.
+ *
+ * @param other the object to copy from.
+ */
+ public IPv6(IPv6 other) {
+ this.valueHigh = other.valueHigh;
+ this.valueLow = other.valueLow;
+ }
+
+ /**
* Constructor from integer values.
*
* @param valueHigh the higher (more significant) 64 bits of the address.
diff --git a/src/main/java/net/onrc/onos/ofcontroller/util/IPv6Net.java b/src/main/java/net/onrc/onos/ofcontroller/util/IPv6Net.java
index bafff24..65ffe54 100644
--- a/src/main/java/net/onrc/onos/ofcontroller/util/IPv6Net.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/util/IPv6Net.java
@@ -23,6 +23,17 @@
}
/**
+ * Copy constructor.
+ *
+ * @param other the object to copy from.
+ */
+ public IPv6Net(IPv6Net other) {
+ if (other.address != null)
+ this.address = new IPv6(other.address);
+ this.prefixLen = other.prefixLen;
+ }
+
+ /**
* Constructor for a given address and prefix length.
*
* @param address the address to use.
diff --git a/src/main/java/net/onrc/onos/ofcontroller/util/Port.java b/src/main/java/net/onrc/onos/ofcontroller/util/Port.java
index 34c807d..bb4851c 100644
--- a/src/main/java/net/onrc/onos/ofcontroller/util/Port.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/util/Port.java
@@ -78,9 +78,9 @@
}
/**
- * Constructor from another entry.
+ * Copy constructor.
*
- * @param other the other entry to use.
+ * @param other the object to copy from.
*/
public Port(Port other) {
this.value = other.value();
diff --git a/src/test/java/net/onrc/onos/ofcontroller/core/INetMapTopologyObjectsIFlowEntryTest.java b/src/test/java/net/onrc/onos/ofcontroller/core/INetMapTopologyObjectsIFlowEntryTest.java
index 717d688..06d8522 100644
--- a/src/test/java/net/onrc/onos/ofcontroller/core/INetMapTopologyObjectsIFlowEntryTest.java
+++ b/src/test/java/net/onrc/onos/ofcontroller/core/INetMapTopologyObjectsIFlowEntryTest.java
@@ -353,18 +353,18 @@
/**
* Desc:
- * Test method for set and get ActionOutput.
+ * Test method for set and get ActionOutputPort.
* Condition:
* N/A
* Expect:
- * 1. Should set ActionOutput.
- * 2. Should get ActionOutput.
+ * 1. Should set ActionOutputPort.
+ * 2. Should get ActionOutputPort.
*/
@Test
- public void testSetGetActionOutput() {
- Short actionOutput = 1;
- flowEntry.setActionOutput(actionOutput);
- assertEquals(flowEntry.getActionOutput(), actionOutput);
+ public void testSetGetActionOutputPort() {
+ Short actionOutputPort = 1;
+ flowEntry.setActionOutputPort(actionOutputPort);
+ assertEquals(flowEntry.getActionOutputPort(), actionOutputPort);
}
/**
diff --git a/src/test/java/net/onrc/onos/ofcontroller/core/internal/TestableGraphDBOperation.java b/src/test/java/net/onrc/onos/ofcontroller/core/internal/TestableGraphDBOperation.java
index f746060..bcff36a 100644
--- a/src/test/java/net/onrc/onos/ofcontroller/core/internal/TestableGraphDBOperation.java
+++ b/src/test/java/net/onrc/onos/ofcontroller/core/internal/TestableGraphDBOperation.java
@@ -425,6 +425,7 @@
private String matchSrcIpaddr,matchDstIpaddr;
private Byte matchIpProto, matchIpToS;
private Short matchSrcTcpUdpPort, matchDstTcpUdpPort;
+ private String actions;
private List<IFlowEntry> entries;
private List<ISwitchObject> switches;
@@ -440,6 +441,7 @@
private String matchSrcIpaddrToUpdate,matchDstIpaddrToUpdate;
private Byte matchIpProtoToUpdate, matchIpToSToUpdate;
private Short matchSrcTcpUdpPortToUpdate, matchDstTcpUdpPortToUpdate;
+ private String actionsToUpdate;
private List<IFlowEntry> flowsToAdd;
private List<IFlowEntry> flowsToRemove;
@@ -485,6 +487,7 @@
if(matchIpToSToUpdate != null) { matchIpToS = matchIpToSToUpdate; }
if(matchSrcTcpUdpPortToUpdate != null) { matchSrcTcpUdpPort = matchSrcTcpUdpPortToUpdate; }
if(matchDstTcpUdpPortToUpdate != null) { matchDstTcpUdpPort = matchDstTcpUdpPortToUpdate; }
+ if(actionsToUpdate != null) { actions = actionsToUpdate; }
}
public void rollback() {
@@ -506,6 +509,7 @@
matchSrcIpaddrToUpdate = matchDstIpaddrToUpdate = null;
matchIpProtoToUpdate = matchIpToSToUpdate = null;
matchSrcTcpUdpPortToUpdate = matchDstTcpUdpPortToUpdate = null;
+ actionsToUpdate = null;
}
// Setter methods for test
@@ -531,6 +535,7 @@
public void setMatchIpToSForTest(Byte matchIpToS) { this.matchIpToS = matchIpToS; }
public void setMatchSrcTcpUdpPortForTest(Short matchSrcTcpUdpPort) { this.matchSrcTcpUdpPort = matchSrcTcpUdpPort; }
public void setMatchDstTcpUdpPortForTest(Short matchDstTcpUdpPort) { this.matchDstTcpUdpPort = matchDstTcpUdpPort; }
+ public void setActionsForTest(String actions) { this.actions = actions; }
public void addFlowEntryForTest(IFlowEntry entry) { entries.add(entry); }
public void addSwitchForTest(ISwitchObject sw) { switches.add(sw); }
@@ -693,6 +698,13 @@
matchDstTcpUdpPortToUpdate = matchDstTcpUdpPort; }
@Override
+ public String getActions() { return actions; }
+
+ @Override
+ public void setActions(String actions) {
+ actionsToUpdate = actions; }
+
+ @Override
public Iterable<ISwitchObject> getSwitches() { return switches; }
@Override
@@ -712,7 +724,8 @@
private String matchSrcIpaddr,matchDstIpaddr;
private Byte matchIpProto, matchIpToS;
private Short matchSrcTcpUdpPort, matchDstTcpUdpPort;
- private Short actionOutput;
+ private Short actionOutputPort;
+ private String actions;
private IFlowPath flowPath;
private ISwitchObject sw;
@@ -728,7 +741,8 @@
private String matchSrcIpaddrToUpdate,matchDstIpaddrToUpdate;
private Byte matchIpProtoToUpdate, matchIpToSToUpdate;
private Short matchSrcTcpUdpPortToUpdate, matchDstTcpUdpPortToUpdate;
- private Short actionOutputToUpdate;
+ private Short actionOutputPortToUpdate;
+ private String actionsToUpdate;
private IFlowPath flowPathToUpdate;
private ISwitchObject swToUpdate;
@@ -761,7 +775,8 @@
if(matchIpToSToUpdate != null) { matchIpToS = matchIpToSToUpdate; }
if(matchSrcTcpUdpPortToUpdate != null) { matchSrcTcpUdpPort = matchSrcTcpUdpPortToUpdate; }
if(matchDstTcpUdpPortToUpdate != null) { matchDstTcpUdpPort = matchDstTcpUdpPortToUpdate; }
- if(actionOutputToUpdate != null) { actionOutput = actionOutputToUpdate; }
+ if(actionOutputPortToUpdate != null) { actionOutputPort = actionOutputPortToUpdate; }
+ if(actionsToUpdate != null) { actions = actionsToUpdate; }
if(flowPathToUpdate != null) { flowPath = flowPathToUpdate; }
if(swToUpdate != null) { sw = swToUpdate; }
@@ -786,7 +801,8 @@
matchSrcIpaddrToUpdate = matchDstIpaddrToUpdate = null;
matchIpProtoToUpdate = matchIpToSToUpdate = null;
matchSrcTcpUdpPortToUpdate = matchDstTcpUdpPortToUpdate = null;
- actionOutputToUpdate = null;
+ actionOutputPortToUpdate = null;
+ actionsToUpdate = null;
flowPathToUpdate = null;
swToUpdate = null;
inportToUpdate = outportToUpdate = null;
@@ -813,7 +829,8 @@
public void setMatchIpToSForTest(Byte matchIpToS) { this.matchIpToS = matchIpToS; }
public void setMatchSrcTcpUdpPortForTest(Short matchSrcTcpUdpPort) { this.matchSrcTcpUdpPort = matchSrcTcpUdpPort; }
public void setMatchDstTcpUdpPortForTest(Short matchDstTcpUdpPort) { this.matchDstTcpUdpPort = matchDstTcpUdpPort; }
- public void setActionOutputForTest(Short actionOutput) { this.actionOutput = actionOutput; }
+ public void setActionOutputPortForTest(Short actionOutputPort) { this.actionOutputPort = actionOutputPort; }
+ public void setActionsForTest(String actions) { this.actions = actions; }
public void setFlowPathForTest(IFlowPath flowPath) { this.flowPath = flowPath; }
public void setSwitchForTest(ISwitchObject sw) { this.sw = sw; }
public void setInportForTest(IPortObject inport) { this.inport = inport; }
@@ -946,10 +963,16 @@
public void setMatchDstTcpUdpPort(Short matchDstTcpUdpPort) { matchDstTcpUdpPortToUpdate = matchDstTcpUdpPort; }
@Override
- public Short getActionOutput() { return actionOutput; }
+ public Short getActionOutputPort() { return actionOutputPort; }
@Override
- public void setActionOutput(Short actionOutput) { actionOutputToUpdate = actionOutput; }
+ public void setActionOutputPort(Short actionOutputPort) { actionOutputPortToUpdate = actionOutputPort; }
+
+ @Override
+ public String getActions() { return actions; }
+
+ @Override
+ public void setActions(String actions) { actionsToUpdate = actions; }
@Override
public IFlowPath getFlow() { return flowPath; }
diff --git a/src/test/java/net/onrc/onos/ofcontroller/flowmanager/FlowManagerTest.java b/src/test/java/net/onrc/onos/ofcontroller/flowmanager/FlowManagerTest.java
index cacedd2..7bc0aac 100644
--- a/src/test/java/net/onrc/onos/ofcontroller/flowmanager/FlowManagerTest.java
+++ b/src/test/java/net/onrc/onos/ofcontroller/flowmanager/FlowManagerTest.java
@@ -1086,7 +1086,7 @@
flowEntry1.setOutPort(new Port((short) 11));
flowEntry1.setFlowEntryId(new FlowEntryId(1));
flowEntry1.setFlowEntryMatch(new FlowEntryMatch());
- flowEntry1.setFlowEntryActions(new ArrayList<FlowEntryAction>());
+ flowEntry1.setFlowEntryActions(new FlowEntryActions());
flowEntry1.setFlowEntryErrorState(new FlowEntryErrorState());
FlowEntry flowEntry2 = new FlowEntry();
@@ -1096,7 +1096,7 @@
flowEntry2.setOutPort(new Port((short) 2));
flowEntry2.setFlowEntryId(new FlowEntryId(2));
flowEntry2.setFlowEntryMatch(new FlowEntryMatch());
- flowEntry2.setFlowEntryActions(new ArrayList<FlowEntryAction>());
+ flowEntry2.setFlowEntryActions(new FlowEntryActions());
flowEntry2.setFlowEntryErrorState(new FlowEntryErrorState());
DataPath dataPath = new DataPath();
@@ -1147,6 +1147,11 @@
// instantiate required objects
FlowManager fm = new FlowManager();
+ FlowEntryAction action = new FlowEntryAction();
+ action.setActionOutput(new Port((short)2));
+ FlowEntryActions actions = new FlowEntryActions();
+ actions.addAction(action);
+
// setup expectations
expectInitWithContext();
expect(iFlowEntry.getFlowEntryId()).andReturn(new FlowEntryId(123).toString());
@@ -1164,7 +1169,7 @@
expect(iFlowEntry.getMatchIpToS()).andReturn(new Byte((byte)0x3));
expect(iFlowEntry.getMatchSrcTcpUdpPort()).andReturn(new Short((short)40000));
expect(iFlowEntry.getMatchDstTcpUdpPort()).andReturn(new Short((short)80));
- expect(iFlowEntry.getActionOutput()).andReturn(new Short((short) 2));
+ expect(iFlowEntry.getActions()).andReturn(actions.toString());
expect(floodlightProvider.getOFMessageFactory()).andReturn(basicFactory);
expect(basicFactory.getMessage(OFType.FLOW_MOD)).andReturn(new OFFlowMod());
expect(iofSwitch.getStringId()).andReturn(new Dpid(100).toString());
diff --git a/src/test/java/net/onrc/onos/ofcontroller/routing/TopoRouteServiceTest.java b/src/test/java/net/onrc/onos/ofcontroller/routing/TopoRouteServiceTest.java
index ba23a01..a33df98 100644
--- a/src/test/java/net/onrc/onos/ofcontroller/routing/TopoRouteServiceTest.java
+++ b/src/test/java/net/onrc/onos/ofcontroller/routing/TopoRouteServiceTest.java
@@ -48,7 +48,6 @@
/**
* A class for testing the TopoRouteService class.
* @see net.onrc.onos.ofcontroller.routing.TopoRouteService
- * @author Pavlin Radoslavov (pavlin@onlab.us)
*/
@RunWith(PowerMockRunner.class)
@PrepareForTest({TitanFactory.class, GraphDBConnection.class, GraphDBOperation.class, TopoRouteService.class})
diff --git a/start-onos.sh b/start-onos.sh
index 13ea0ac..a35d181 100755
--- a/start-onos.sh
+++ b/start-onos.sh
@@ -16,6 +16,8 @@
# Set JVM options
JVM_OPTS=""
+## If you want JaCoCo Code Coverage reports... uncomment line below
+JVM_OPTS="$JVM_OPTS -javaagent:${ONOS_HOME}/lib/jacocoagent.jar=dumponexit=true,output=file,destfile=${LOGDIR}/jacoco.exec"
JVM_OPTS="$JVM_OPTS -server -d64"
#JVM_OPTS="$JVM_OPTS -Xmx2g -Xms2g -Xmn800m"
JVM_OPTS="$JVM_OPTS -Xmx1g -Xms1g -Xmn800m"
@@ -134,7 +136,7 @@
pids="$flpid $tdpid"
for p in ${pids}; do
if [ x$p != "x" ]; then
- kill -KILL $p
+ kill -TERM $p
echo "Killed existing process (pid: $p)"
fi
done
diff --git a/web/add_flow.py b/web/add_flow.py
index f61e926..8100f22 100755
--- a/web/add_flow.py
+++ b/web/add_flow.py
@@ -204,18 +204,19 @@
match['dstTcpUdpPort'] = int(arg2, 0)
# match['matchDstTcpUdpPort'] = True
elif arg1 == "actionOutput":
- # Just mark whether ACTION_OUTPUT action is enabled
+ # Mark whether ACTION_OUTPUT action is enabled
actionOutputEnabled = arg2 in ['True', 'true']
- #
- # TODO: Complete the implementation for ACTION_OUTPUT
- # actionOutput = {}
- # outPort = {}
- # outPort['value'] = int(arg2, 0)
- # actionOutput['port'] = outPort
- # actionOutput['maxLen'] = int(arg3, 0)
- # action['actionOutput'] = actionOutput
- # # action['actionType'] = 'ACTION_OUTPUT'
- # actions.append(action)
+ # If ACTION_OUTPUT is explicitly enabled, add an entry with a fake
+ # port number. We need this entry to preserve the action ordering.
+ if actionOutputEnabled == True:
+ actionOutput = {}
+ outPort = {}
+ outPort['value'] = 0xffff
+ actionOutput['port'] = outPort
+ actionOutput['maxLen'] = 0
+ action['actionOutput'] = actionOutput
+ # action['actionType'] = 'ACTION_OUTPUT'
+ actions.append(action)
#
elif arg1 == "actionSetVlanId":
vlanId = {}
@@ -346,6 +347,8 @@
flowPathFlags = {}
flowPathFlags['flags'] = myFlowPathFlags
+ flowEntryActions = {}
+
flow_path = {}
flow_path['flowId'] = flow_id
flow_path['installerId'] = installer_id
@@ -367,6 +370,11 @@
my_data_path['flowEntries'][idx]['flowEntryMatch'] = copy.deepcopy(match)
idx = idx + 1
+
+ if (len(actions) > 0):
+ flowEntryActions['actions'] = copy.deepcopy(actions)
+ flow_path['flowEntryActions'] = flowEntryActions
+
#
# Set the actions for each flow entry
# NOTE: The actions from the command line are aplied
@@ -388,11 +396,12 @@
action['actionOutput'] = copy.deepcopy(actionOutput)
# action['actionType'] = 'ACTION_OUTPUT'
actions.append(copy.deepcopy(action))
+ flowEntryActions = {}
+ flowEntryActions['actions'] = copy.deepcopy(actions)
- my_data_path['flowEntries'][idx]['flowEntryActions'] = copy.deepcopy(actions)
+ my_data_path['flowEntries'][idx]['flowEntryActions'] = flowEntryActions
idx = idx + 1
-
flow_path['dataPath'] = my_data_path
debug("Flow Path: %s" % flow_path)
return flow_path
@@ -506,18 +515,17 @@
usage_msg = usage_msg + "\n"
usage_msg = usage_msg + " Actions:\n"
usage_msg = usage_msg + " actionOutput <True|False> (default to True)\n"
+ usage_msg = usage_msg + " actionSetVlanId <VLAN ID>\n"
+ usage_msg = usage_msg + " actionSetVlanPriority <VLAN priority>\n"
+ usage_msg = usage_msg + " actionStripVlan <True|False>\n"
usage_msg = usage_msg + " actionSetEthernetSrcAddr <source MAC address>\n"
usage_msg = usage_msg + " actionSetEthernetDstAddr <destination MAC address>\n"
usage_msg = usage_msg + " actionSetIPv4SrcAddr <source IPv4 address>\n"
usage_msg = usage_msg + " actionSetIPv4DstAddr <destination IPv4 address>\n"
- usage_msg = usage_msg + "\n"
- usage_msg = usage_msg + " Actions (not implemented yet):\n"
- usage_msg = usage_msg + " actionSetVlanId <VLAN ID>\n"
- usage_msg = usage_msg + " actionSetVlanPriority <VLAN priority>\n"
usage_msg = usage_msg + " actionSetIpToS <IP ToS (DSCP field, 6 bits)>\n"
usage_msg = usage_msg + " actionSetTcpUdpSrcPort <source TCP/UDP port>\n"
usage_msg = usage_msg + " actionSetTcpUdpDstPort <destination TCP/UDP port>\n"
- usage_msg = usage_msg + " actionStripVlan <True|False>\n"
+ usage_msg = usage_msg + " Actions (not implemented yet):\n"
usage_msg = usage_msg + " actionEnqueue <dummy argument>\n"
# app.debug = False;
diff --git a/web/get_flow.py b/web/get_flow.py
index 6599360..9ab55da 100755
--- a/web/get_flow.py
+++ b/web/get_flow.py
@@ -33,6 +33,131 @@
# Sample output:
# {"flowId":{"value":"0x5"},"installerId":{"value":"FOOBAR"},"dataPath":{"srcPort":{"dpid":{"value":"00:00:00:00:00:00:00:01"},"port":{"value":0}},"dstPort":{"dpid":{"value":"00:00:00:00:00:00:00:02"},"port":{"value":0}},"flowEntries":[{"flowEntryId":"0x1389","flowEntryMatch":null,"flowEntryActions":null,"dpid":{"value":"00:00:00:00:00:00:00:01"},"inPort":{"value":0},"outPort":{"value":1},"flowEntryUserState":"FE_USER_DELETE","flowEntrySwitchState":"FE_SWITCH_NOT_UPDATED","flowEntryErrorState":null},{"flowEntryId":"0x138a","flowEntryMatch":null,"flowEntryActions":null,"dpid":{"value":"00:00:00:00:00:00:00:02"},"inPort":{"value":9},"outPort":{"value":0},"flowEntryUserState":"FE_USER_DELETE","flowEntrySwitchState":"FE_SWITCH_NOT_UPDATED","flowEntryErrorState":null}]}}
+def parse_match(match):
+ result = []
+
+ inPort = match['inPort']
+ matchInPort = match['matchInPort']
+ srcMac = match['srcMac']
+ matchSrcMac = match['matchSrcMac']
+ dstMac = match['dstMac']
+ matchDstMac = match['matchDstMac']
+ ethernetFrameType = match['ethernetFrameType']
+ matchEthernetFrameType = match['matchEthernetFrameType']
+ vlanId = match['vlanId']
+ matchVlanId = match['matchVlanId']
+ vlanPriority = match['vlanPriority']
+ matchVlanPriority = match['matchVlanPriority']
+ srcIPv4Net = match['srcIPv4Net']
+ matchSrcIPv4Net = match['matchSrcIPv4Net']
+ dstIPv4Net = match['dstIPv4Net']
+ matchDstIPv4Net = match['matchDstIPv4Net']
+ ipProto = match['ipProto']
+ matchIpProto = match['matchIpProto']
+ ipToS = match['ipToS']
+ matchIpToS = match['matchIpToS']
+ srcTcpUdpPort = match['srcTcpUdpPort']
+ matchSrcTcpUdpPort = match['matchSrcTcpUdpPort']
+ dstTcpUdpPort = match['dstTcpUdpPort']
+ matchDstTcpUdpPort = match['matchDstTcpUdpPort']
+ if matchInPort == True:
+ r = "inPort: %s" % inPort['value']
+ result.append(r)
+ if matchSrcMac == True:
+ r = "srcMac: %s" % srcMac['value']
+ result.append(r)
+ if matchDstMac == True:
+ r = "dstMac: %s" % dstMac['value']
+ result.append(r)
+ if matchEthernetFrameType == True:
+ r = "ethernetFrameType: %s" % hex(ethernetFrameType)
+ result.append(r)
+ if matchVlanId == True:
+ r = "vlanId: %s" % vlanId
+ result.append(r)
+ if matchVlanPriority == True:
+ r = "vlanPriority: %s" % vlanPriority
+ result.append(r)
+ if matchSrcIPv4Net == True:
+ r = "srcIPv4Net: %s" % srcIPv4Net['value']
+ result.append(r)
+ if matchDstIPv4Net == True:
+ r = "dstIPv4Net: %s" % dstIPv4Net['value']
+ result.append(r)
+ if matchIpProto == True:
+ r = "ipProto: %s" % ipProto
+ result.append(r)
+ if matchIpToS == True:
+ r = "ipToS: %s" % ipToS
+ result.append(r)
+ if matchSrcTcpUdpPort == True:
+ r = "srcTcpUdpPort: %s" % srcTcpUdpPort
+ result.append(r)
+ if matchDstTcpUdpPort == True:
+ r = "dstTcpUdpPort: %s" % dstTcpUdpPort
+ result.append(r)
+
+ return result
+
+
+def parse_actions(actions):
+ result = []
+ for a in actions:
+ actionType = a['actionType']
+ if actionType == "ACTION_OUTPUT":
+ port = a['actionOutput']['port']['value']
+ maxLen = a['actionOutput']['maxLen']
+ r = "actionType: %s port: %s maxLen: %s" % (actionType, port, maxLen)
+ result.append(r)
+ if actionType == "ACTION_SET_VLAN_VID":
+ vlanId = a['actionSetVlanId']['vlanId']
+ r = "actionType: %s vlanId: %s" % (actionType, vlanId)
+ result.append(r)
+ if actionType == "ACTION_SET_VLAN_PCP":
+ vlanPriority = a['actionSetVlanPriority']['vlanPriority']
+ r = "actionType: %s vlanPriority: %s" % (actionType, vlanPriority)
+ result.append(r)
+ if actionType == "ACTION_STRIP_VLAN":
+ stripVlan = a['actionStripVlan']['stripVlan']
+ r = "actionType: %s stripVlan: %s" % (actionType, stripVlan)
+ result.append(r)
+ if actionType == "ACTION_SET_DL_SRC":
+ setEthernetSrcAddr = a['actionSetEthernetSrcAddr']['addr']['value']
+ r = "actionType: %s setEthernetSrcAddr: %s" % (actionType, setEthernetSrcAddr)
+ result.append(r)
+ if actionType == "ACTION_SET_DL_DST":
+ setEthernetDstAddr = a['actionSetEthernetDstAddr']['addr']['value']
+ r = "actionType: %s setEthernetDstAddr: %s" % (actionType, setEthernetDstAddr)
+ result.append(r)
+ if actionType == "ACTION_SET_NW_SRC":
+ setIPv4SrcAddr = a['actionSetIPv4SrcAddr']['addr']['value']
+ r = "actionType: %s setIPv4SrcAddr: %s" % (actionType, setIPv4SrcAddr)
+ result.append(r)
+ if actionType == "ACTION_SET_NW_DST":
+ setIPv4DstAddr = a['actionSetIPv4DstAddr']['addr']['value']
+ r = "actionType: %s setIPv4DstAddr: %s" % (actionType, setIPv4DstAddr)
+ result.append(r)
+ if actionType == "ACTION_SET_NW_TOS":
+ setIpToS = a['actionSetIpToS']['ipToS']
+ r = "actionType: %s setIpToS: %s" % (actionType, setIpToS)
+ result.append(r)
+ if actionType == "ACTION_SET_TP_SRC":
+ setTcpUdpSrcPort = a['actionSetTcpUdpSrcPort']['port']
+ r = "actionType: %s setTcpUdpSrcPort: %s" % (actionType, setTcpUdpSrcPort)
+ result.append(r)
+ if actionType == "ACTION_SET_TP_DST":
+ setTcpUdpDstPort = a['actionSetTcpUdpDstPort']['port']
+ r = "actionType: %s setTcpUdpDstPort: %s" % (actionType, setTcpUdpDstPort)
+ result.append(r)
+ if actionType == "ACTION_ENQUEUE":
+ port = a['actionEnqueue']['port']['value']
+ queueId = a['actionEnqueue']['queueId']
+ r = "actionType: %s port: %s queueId: %s" % (actionType, port, queueId)
+ result.append(r)
+
+ return result
+
+
def print_flow_path(parsedResult):
flowId = parsedResult['flowId']['value']
installerId = parsedResult['installerId']['value']
@@ -41,6 +166,8 @@
srcPort = parsedResult['dataPath']['srcPort']['port']['value']
dstSwitch = parsedResult['dataPath']['dstPort']['dpid']['value']
dstPort = parsedResult['dataPath']['dstPort']['port']['value']
+ match = parsedResult['flowEntryMatch'];
+ actions = parsedResult['flowEntryActions']['actions']
flowPathFlagsStr = ""
if (flowPathFlags & 0x1):
@@ -53,69 +180,35 @@
flowPathFlagsStr += "KEEP_ONLY_FIRST_HOP_ENTRY"
print "FlowPath: (flowId = %s installerId = %s flowPathFlags = 0x%x(%s) src = %s/%s dst = %s/%s)" % (flowId, installerId, flowPathFlags, flowPathFlagsStr, srcSwitch, srcPort, dstSwitch, dstPort)
- match = parsedResult['flowEntryMatch'];
+
#
- # Print the common conditions
+ # Print the common match conditions
#
if match == None:
print " Match: %s" % (match)
else:
- # inPort = match['inPort']
- # matchInPort = match['matchInPort']
- srcMac = match['srcMac']
- matchSrcMac = match['matchSrcMac']
- dstMac = match['dstMac']
- matchDstMac = match['matchDstMac']
- ethernetFrameType = match['ethernetFrameType']
- matchEthernetFrameType = match['matchEthernetFrameType']
- vlanId = match['vlanId']
- matchVlanId = match['matchVlanId']
- vlanPriority = match['vlanPriority']
- matchVlanPriority = match['matchVlanPriority']
- srcIPv4Net = match['srcIPv4Net']
- matchSrcIPv4Net = match['matchSrcIPv4Net']
- dstIPv4Net = match['dstIPv4Net']
- matchDstIPv4Net = match['matchDstIPv4Net']
- ipProto = match['ipProto']
- matchIpProto = match['matchIpProto']
- ipToS = match['ipToS']
- matchIpToS = match['matchIpToS']
- srcTcpUdpPort = match['srcTcpUdpPort']
- matchSrcTcpUdpPort = match['matchSrcTcpUdpPort']
- dstTcpUdpPort = match['dstTcpUdpPort']
- matchDstTcpUdpPort = match['matchDstTcpUdpPort']
- # if matchInPort == True:
- # print " inPort: %s" % inPort['value']
- if matchSrcMac == True:
- print " srcMac: %s" % srcMac['value']
- if matchDstMac == True:
- print " dstMac: %s" % dstMac['value']
- if matchEthernetFrameType == True:
- print " ethernetFrameType: %s" % hex(ethernetFrameType)
- if matchVlanId == True:
- print " vlanId: %s" % vlanId
- if matchVlanPriority == True:
- print " vlanPriority: %s" % vlanPriority
- if matchSrcIPv4Net == True:
- print " srcIPv4Net: %s" % srcIPv4Net['value']
- if matchDstIPv4Net == True:
- print " dstIPv4Net: %s" % dstIPv4Net['value']
- if matchIpProto == True:
- print " ipProto: %s" % ipProto
- if matchIpToS == True:
- print " ipToS: %s" % ipToS
- if matchSrcTcpUdpPort == True:
- print " srcTcpUdpPort: %s" % srcTcpUdpPort
- if matchDstTcpUdpPort == True:
- print " dstTcpUdpPort: %s" % dstTcpUdpPort
+ parsedMatch = parse_match(match)
+ for l in parsedMatch:
+ print " %s" % l
+ #
+ # Print the actions
+ #
+ parsedActions = parse_actions(actions)
+ for l in parsedActions:
+ print " %s" % l
+
+ #
+ # Print each Flow Entry
+ #
for f in parsedResult['dataPath']['flowEntries']:
flowEntryId = f['flowEntryId']
dpid = f['dpid']['value']
userState = f['flowEntryUserState']
switchState = f['flowEntrySwitchState']
match = f['flowEntryMatch'];
- actions = f['flowEntryActions']
+ actions = f['flowEntryActions']['actions']
+
print " FlowEntry: (%s, %s, %s, %s)" % (flowEntryId, dpid, userState, switchState)
#
@@ -124,101 +217,16 @@
if match == None:
print " Match: %s" % (match)
else:
- inPort = match['inPort']
- matchInPort = match['matchInPort']
- srcMac = match['srcMac']
- matchSrcMac = match['matchSrcMac']
- dstMac = match['dstMac']
- matchDstMac = match['matchDstMac']
- ethernetFrameType = match['ethernetFrameType']
- matchEthernetFrameType = match['matchEthernetFrameType']
- vlanId = match['vlanId']
- matchVlanId = match['matchVlanId']
- vlanPriority = match['vlanPriority']
- matchVlanPriority = match['matchVlanPriority']
- srcIPv4Net = match['srcIPv4Net']
- matchSrcIPv4Net = match['matchSrcIPv4Net']
- dstIPv4Net = match['dstIPv4Net']
- matchDstIPv4Net = match['matchDstIPv4Net']
- ipProto = match['ipProto']
- matchIpProto = match['matchIpProto']
- ipToS = match['ipToS']
- matchIpToS = match['matchIpToS']
- srcTcpUdpPort = match['srcTcpUdpPort']
- matchSrcTcpUdpPort = match['matchSrcTcpUdpPort']
- dstTcpUdpPort = match['dstTcpUdpPort']
- matchDstTcpUdpPort = match['matchDstTcpUdpPort']
- if matchInPort == True:
- print " inPort: %s" % inPort['value']
- if matchSrcMac == True:
- print " srcMac: %s" % srcMac['value']
- if matchDstMac == True:
- print " dstMac: %s" % dstMac['value']
- if matchEthernetFrameType == True:
- print " ethernetFrameType: %s" % hex(ethernetFrameType)
- if matchVlanId == True:
- print " vlanId: %s" % vlanId
- if matchVlanPriority == True:
- print " vlanPriority: %s" % vlanPriority
- if matchSrcIPv4Net == True:
- print " srcIPv4Net: %s" % srcIPv4Net['value']
- if matchDstIPv4Net == True:
- print " dstIPv4Net: %s" % dstIPv4Net['value']
- if matchIpProto == True:
- print " ipProto: %s" % ipProto
- if matchIpToS == True:
- print " ipToS: %s" % ipToS
- if matchSrcTcpUdpPort == True:
- print " srcTcpUdpPort: %s" % srcTcpUdpPort
- if matchDstTcpUdpPort == True:
- print " dstTcpUdpPort: %s" % dstTcpUdpPort
-
+ parsedMatch = parse_match(match)
+ for l in parsedMatch:
+ print " %s" % l
#
# Print the actions
#
- if actions == None:
- print " Actions: %s" % (actions)
- else:
- for a in actions:
- actionType = a['actionType']
- if actionType == "ACTION_OUTPUT":
- port = a['actionOutput']['port']['value']
- maxLen = a['actionOutput']['maxLen']
- print " actionType: %s port: %s maxLen: %s" % (actionType, port, maxLen)
- if actionType == "ACTION_SET_VLAN_VID":
- vlanId = a['actionSetVlanId']['vlanId']
- print " actionType: %s vlanId: %s" % (actionType, vlanId)
- if actionType == "ACTION_SET_VLAN_PCP":
- vlanPriority = a['actionSetVlanPriority']['vlanPriority']
- print " actionType: %s vlanPriority: %s" % (actionType, vlanPriority)
- if actionType == "ACTION_STRIP_VLAN":
- stripVlan = a['actionStripVlan']['stripVlan']
- print " actionType: %s stripVlan: %s" % (actionType, stripVlan)
- if actionType == "ACTION_SET_DL_SRC":
- setEthernetSrcAddr = a['actionSetEthernetSrcAddr']['addr']['value']
- print " actionType: %s setEthernetSrcAddr: %s" % (actionType, setEthernetSrcAddr)
- if actionType == "ACTION_SET_DL_DST":
- setEthernetDstAddr = a['actionSetEthernetDstAddr']['addr']['value']
- print " actionType: %s setEthernetDstAddr: %s" % (actionType, setEthernetDstAddr)
- if actionType == "ACTION_SET_NW_SRC":
- setIPv4SrcAddr = a['actionSetIPv4SrcAddr']['addr']['value']
- print " actionType: %s setIPv4SrcAddr: %s" % (actionType, setIPv4SrcAddr)
- if actionType == "ACTION_SET_NW_DST":
- setIPv4DstAddr = a['actionSetIPv4DstAddr']['addr']['value']
- print " actionType: %s setIPv4DstAddr: %s" % (actionType, setIPv4DstAddr)
- if actionType == "ACTION_SET_NW_TOS":
- setIpToS = a['actionSetIpToS']['ipToS']
- print " actionType: %s setIpToS: %s" % (actionType, setIpToS)
- if actionType == "ACTION_SET_TP_SRC":
- setTcpUdpSrcPort = a['actionSetTcpUdpSrcPort']['port']
- print " actionType: %s setTcpUdpSrcPort: %s" % (actionType, setTcpUdpSrcPort)
- if actionType == "ACTION_SET_TP_DST":
- setTcpUdpDstPort = a['actionSetTcpUdpDstPort']['port']
- print " actionType: %s setTcpUdpDstPort: %s" % (actionType, setTcpUdpDstPort)
- if actionType == "ACTION_ENQUEUE":
- port = a['actionEnqueue']['port']['value']
- queueId = a['actionEnqueue']['queueId']
- print " actionType: %s port: %s queueId: %s" % (actionType, port, queueId)
+ parsedActions = parse_actions(actions)
+ for l in parsedActions:
+ print " %s" % l
+
def get_flow_path(flow_id):
try:
diff --git a/web/measurement_store_flow.py b/web/measurement_store_flow.py
index 8f6bd73..0e39465 100755
--- a/web/measurement_store_flow.py
+++ b/web/measurement_store_flow.py
@@ -87,7 +87,7 @@
if "KEEP_ONLY_FIRST_HOP_ENTRY" in arg2:
flowPathFlags = flowPathFlags + 0x2
elif arg1 == "matchInPort":
- # Just mark whether inPort matching is enabled
+ # Mark whether ACTION_OUTPUT action is enabled
matchInPortEnabled = arg2 in ['True', 'true']
# inPort = {}
# inPort['value'] = int(arg2, 0)
@@ -135,18 +135,19 @@
match['dstTcpUdpPort'] = int(arg2, 0)
# match['matchDstTcpUdpPort'] = True
elif arg1 == "actionOutput":
- # Just mark whether ACTION_OUTPUT action is enabled
+ # Mark whether ACTION_OUTPUT action is enabled
actionOutputEnabled = arg2 in ['True', 'true']
- #
- # TODO: Complete the implementation for ACTION_OUTPUT
- # actionOutput = {}
- # outPort = {}
- # outPort['value'] = int(arg2, 0)
- # actionOutput['port'] = outPort
- # actionOutput['maxLen'] = int(arg3, 0)
- # action['actionOutput'] = actionOutput
- # # action['actionType'] = 'ACTION_OUTPUT'
- # actions.append(action)
+ # If ACTION_OUTPUT is explicitly enabled, add an entry with a fake
+ # port number. We need this entry to preserve the action ordering.
+ if actionOutputEnabled == True:
+ actionOutput = {}
+ outPort = {}
+ outPort['value'] = 0xffff
+ actionOutput['port'] = outPort
+ actionOutput['maxLen'] = 0
+ action['actionOutput'] = actionOutput
+ # action['actionType'] = 'ACTION_OUTPUT'
+ actions.append(action)
#
elif arg1 == "actionSetVlanId":
vlanId = {}
@@ -264,6 +265,8 @@
flowPathFlags = {}
flowPathFlags['flags'] = myFlowPathFlags
+ flowEntryActions = {}
+
flow_path = {}
flow_path['flowId'] = flow_id
flow_path['installerId'] = installer_id
@@ -285,6 +288,11 @@
my_data_path['flowEntries'][idx]['flowEntryMatch'] = copy.deepcopy(match)
idx = idx + 1
+
+ if (len(actions) > 0):
+ flowEntryActions['actions'] = copy.deepcopy(actions)
+ flow_path['flowEntryActions'] = flowEntryActions
+
#
# Set the actions for each flow entry
# NOTE: The actions from the command line are aplied
@@ -306,11 +314,12 @@
action['actionOutput'] = copy.deepcopy(actionOutput)
# action['actionType'] = 'ACTION_OUTPUT'
actions.append(copy.deepcopy(action))
+ flowEntryActions = {}
+ flowEntryActions['actions'] = copy.deepcopy(actions)
- my_data_path['flowEntries'][idx]['flowEntryActions'] = copy.deepcopy(actions)
+ my_data_path['flowEntries'][idx]['flowEntryActions'] = flowEntryActions
idx = idx + 1
-
flow_path['dataPath'] = my_data_path
debug("Flow Path: %s" % flow_path)
return flow_path
@@ -386,18 +395,17 @@
usage_msg = usage_msg + "\n"
usage_msg = usage_msg + " Actions:\n"
usage_msg = usage_msg + " actionOutput <True|False> (default to True)\n"
+ usage_msg = usage_msg + " actionSetVlanId <VLAN ID>\n"
+ usage_msg = usage_msg + " actionSetVlanPriority <VLAN priority>\n"
+ usage_msg = usage_msg + " actionStripVlan <True|False>\n"
usage_msg = usage_msg + " actionSetEthernetSrcAddr <source MAC address>\n"
usage_msg = usage_msg + " actionSetEthernetDstAddr <destination MAC address>\n"
usage_msg = usage_msg + " actionSetIPv4SrcAddr <source IPv4 address>\n"
usage_msg = usage_msg + " actionSetIPv4DstAddr <destination IPv4 address>\n"
- usage_msg = usage_msg + "\n"
- usage_msg = usage_msg + " Actions (not implemented yet):\n"
- usage_msg = usage_msg + " actionSetVlanId <VLAN ID>\n"
- usage_msg = usage_msg + " actionSetVlanPriority <VLAN priority>\n"
usage_msg = usage_msg + " actionSetIpToS <IP ToS (DSCP field, 6 bits)>\n"
usage_msg = usage_msg + " actionSetTcpUdpSrcPort <source TCP/UDP port>\n"
usage_msg = usage_msg + " actionSetTcpUdpDstPort <destination TCP/UDP port>\n"
- usage_msg = usage_msg + " actionStripVlan <True|False>\n"
+ usage_msg = usage_msg + " Actions (not implemented yet):\n"
usage_msg = usage_msg + " actionEnqueue <dummy argument>\n"
# app.debug = False;
diff --git a/web/topology_rest.py b/web/topology_rest.py
index 53f46bc..ea33a00 100755
--- a/web/topology_rest.py
+++ b/web/topology_rest.py
@@ -216,19 +216,6 @@
resp = Response(result, status=200, mimetype='application/json')
return resp
-@app.route("/proxy/gui/switchctrl/<cmd>")
-def proxy_switch_controller_setting(cmd):
- try:
- command = "curl -s %s/gui/switchctrl/%s" % (ONOS_GUI3_CONTROL_HOST, cmd)
- print command
- result = os.popen(command).read()
- except:
- print "REST IF has issue"
- exit
-
- resp = Response(result, status=200, mimetype='application/json')
- return resp
-
@app.route("/proxy/gui/reset")
def proxy_gui_reset():
result = ""