add a traffic engineering use case and samples of NetworkGraph classes as test codes
Change-Id: Id655106309d032a2e99e26887db1836d2f598ef8
diff --git a/src/test/java/net/onrc/onos/ofcontroller/app/BaseApplication.java b/src/test/java/net/onrc/onos/ofcontroller/app/BaseApplication.java
new file mode 100644
index 0000000..6aa435c
--- /dev/null
+++ b/src/test/java/net/onrc/onos/ofcontroller/app/BaseApplication.java
@@ -0,0 +1,8 @@
+package net.onrc.onos.ofcontroller.app;
+
+/**
+ * This code is valid for the architectural study purpose only.
+ * @author Toshio Koide (t-koide@onlab.us)
+ */
+public interface BaseApplication {
+}
diff --git a/src/test/java/net/onrc/onos/ofcontroller/app/ConstrainedFlow.java b/src/test/java/net/onrc/onos/ofcontroller/app/ConstrainedFlow.java
new file mode 100644
index 0000000..7b18c34
--- /dev/null
+++ b/src/test/java/net/onrc/onos/ofcontroller/app/ConstrainedFlow.java
@@ -0,0 +1,88 @@
+package net.onrc.onos.ofcontroller.app;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedList;
+
+/**
+ * This code is valid for the architectural study purpose only.
+ * @author Toshio Koide (t-koide@onlab.us)
+ */
+public class ConstrainedFlow extends Flow {
+ public double bandwidth;
+
+ /**
+ *
+ * @param srcPort
+ * @param dstPort
+ * @param bandwidth
+ */
+ public ConstrainedFlow(NetworkGraph graph, String name, SwitchPort srcPort, SwitchPort dstPort, double bandwidth) {
+ super(graph, name, srcPort, dstPort);
+ this.bandwidth = bandwidth;
+ }
+
+ /**
+ * calculate available bandwidth of specified link
+ * @param link
+ * @return
+ */
+ protected Double getAvailableBandwidth(Link link) {
+ Double capacity = link.getCapacity();
+ if (capacity.isInfinite()) {
+ return capacity;
+ }
+ Double bandwidth = capacity;
+ for (Flow flow: link.getFlows()) {
+ if (flow instanceof ConstrainedFlow) {
+ bandwidth -= ((ConstrainedFlow)flow).getBandwidth();
+ }
+ }
+ return bandwidth;
+ }
+
+ public Double getBandwidth() {
+ return bandwidth;
+ }
+
+ /**
+ * calculate path by creating BFS tree satisfying the bandwidth condition
+ */
+ @Override
+ public boolean calcPath() {
+ LinkedList<Switch> switchQueue = new LinkedList<Switch>();
+ HashSet<Switch> switchSearched = new HashSet<Switch>();
+ HashMap<Switch, Link> upstreamLinks = new HashMap<Switch, Link>();
+
+ Switch srcSwitch = srcPort.getSwitch();
+ Switch dstSwitch = dstPort.getSwitch();
+
+ switchQueue.add(srcSwitch);
+ switchSearched.add(srcSwitch);
+
+ while (!switchQueue.isEmpty()) {
+ Switch sw = switchQueue.poll();
+ if (sw == dstSwitch) {
+ // path has been searched.
+ // store path into itself
+ path.clear();
+ while (sw != srcSwitch) {
+ Link upstreamLink = upstreamLinks.get(sw);
+ path.add(0, upstreamLink);
+ sw = upstreamLink.getSrcPort().getSwitch();
+ }
+ return super.calcPath();
+ }
+ for (Link link: sw.getAdjLinks()) {
+ Switch reachedSwitch = link.getDstPort().getSwitch();
+ Double availableBandwidth = getAvailableBandwidth(link);
+ if (availableBandwidth < bandwidth || switchSearched.contains(reachedSwitch)) continue;
+ switchQueue.add(reachedSwitch);
+ switchSearched.add(reachedSwitch);
+ upstreamLinks.put(reachedSwitch, link);
+ }
+ }
+ state = FlowState.PathCalcurationFailed;
+ return false;
+ }
+}
diff --git a/src/test/java/net/onrc/onos/ofcontroller/app/Flow.java b/src/test/java/net/onrc/onos/ofcontroller/app/Flow.java
new file mode 100644
index 0000000..071d89f
--- /dev/null
+++ b/src/test/java/net/onrc/onos/ofcontroller/app/Flow.java
@@ -0,0 +1,106 @@
+package net.onrc.onos.ofcontroller.app;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Base class for Flow representation
+ * This code is valid for the architectural study purpose only.
+ * @author Toshio Koide (t-koide@onlab.us)
+ */
+public class Flow extends NetworkGraphEntity {
+ public enum FlowState {
+ Created,
+ Configuring,
+ Configured,
+ PathCalcurating,
+ PathCalcurated,
+ PathCalcurationFailed,
+ PathInstalled,
+ PathInstlationFailed,
+ FlowEntriesCalcurating,
+ FlowEntriesCalcurated,
+ FlowEntriesCalcuratinFailed,
+ FlowEntriesInstalling,
+ FlowEntriesInstalled,
+ FlowEntriesInstallationFailed,
+ FlowEntriesRemoving,
+ FlowEntriesRemoved,
+ FlowEntriesRemovalFailed,
+ PathRemoved,
+ PathRemovalFailed,
+ }
+
+ protected FlowState state = FlowState.Created;
+
+ // configurations
+ protected SwitchPort srcPort = null;
+ protected SwitchPort dstPort = null;
+
+ // path
+ protected Path path = new Path();
+
+ // flow entries
+ protected Map<SwitchPort, FlowEntry> flowEntries = null;
+
+ public Flow(NetworkGraph graph, String name, SwitchPort srcPort, SwitchPort dstPort) {
+ super(graph);
+ this.srcPort = srcPort;
+ this.dstPort = dstPort;
+ state = FlowState.Created;
+ }
+
+ FlowState getState() {
+ return state;
+ }
+
+ boolean isState(FlowState state) {
+ return this.state == state;
+ }
+
+ boolean calcPath() {
+ state = FlowState.PathCalcurated;
+ return true;
+ }
+
+ public Path getPath() {
+ return path;
+ }
+
+ public boolean installPath() {
+ for (Link link: path) {
+ link.addFlow(this);
+ }
+ state = FlowState.PathInstalled;
+ return true;
+ }
+
+ public boolean uninstallPath() {
+ for (Link link: path) {
+ link.removeFlow(this);
+ }
+ state = FlowState.PathRemoved;
+ return true;
+ }
+
+ public void calcFlowEntries() {
+ flowEntries = new HashMap<SwitchPort, FlowEntry>();
+ state = FlowState.FlowEntriesCalcurated;
+ }
+
+ public void installFlowEntries() {
+ state = FlowState.FlowEntriesInstalled;
+ }
+
+ public void uninstallFlowEntries() {
+ state = FlowState.FlowEntriesRemoved;
+ }
+
+ @Override
+ public String toString() {
+ return String.format("srcPort:%s, dstPort:%s, Path: %s",
+ srcPort.toString(),
+ dstPort.toString(),
+ path.toString());
+ }
+}
diff --git a/src/test/java/net/onrc/onos/ofcontroller/app/FlowEntry.java b/src/test/java/net/onrc/onos/ofcontroller/app/FlowEntry.java
new file mode 100644
index 0000000..76e90ed
--- /dev/null
+++ b/src/test/java/net/onrc/onos/ofcontroller/app/FlowEntry.java
@@ -0,0 +1,12 @@
+package net.onrc.onos.ofcontroller.app;
+
+/**
+ * Base class for Link representation
+ * This code is valid for the architectural study purpose only.
+ *
+ * @author Toshio Koide (t-koide@onlab.us)
+ *
+ */
+public class FlowEntry {
+
+}
diff --git a/src/test/java/net/onrc/onos/ofcontroller/app/Link.java b/src/test/java/net/onrc/onos/ofcontroller/app/Link.java
new file mode 100644
index 0000000..dc3c0dd
--- /dev/null
+++ b/src/test/java/net/onrc/onos/ofcontroller/app/Link.java
@@ -0,0 +1,74 @@
+package net.onrc.onos.ofcontroller.app;
+
+import java.util.Collection;
+import java.util.HashSet;
+
+/**
+ * This code is valid for the architectural study purpose only.
+ * Base class for Link representation
+ *
+ * @author Toshio Koide (t-koide@onlab.us)
+ *
+ */
+public class Link extends NetworkGraphEntity {
+ protected SwitchPort srcPort;
+ protected SwitchPort dstPort;
+ protected HashSet<Flow> flows;
+ protected Double capacity;
+
+ public Link(SwitchPort srcPort, SwitchPort dstPort) {
+ super(srcPort.getNetworkGraph());
+ this.srcPort = srcPort;
+ this.dstPort = dstPort;
+ this.flows = new HashSet<Flow>();
+ this.capacity = Double.POSITIVE_INFINITY;
+ setToPorts();
+ }
+
+ public void setToPorts() {
+ srcPort.setOutgoingLink(this);
+ dstPort.setIncomingLink(this);
+ }
+
+ public void unsetFromPorts() {
+ srcPort.setOutgoingLink(null);
+ dstPort.setIncomingLink(null);
+ }
+
+ public void setCapacity(Double capacity) {
+ this.capacity = capacity;
+ }
+
+ public Double getCapacity() {
+ return capacity;
+ }
+
+ public boolean addFlow(Flow flow) {
+ return flows.add(flow);
+ }
+
+ public boolean removeFlow(Flow flow) {
+ return flows.remove(flow);
+ }
+
+ public Collection<Flow> getFlows() {
+ return flows;
+ }
+
+ public SwitchPort getSrcPort() {
+ return srcPort;
+ }
+
+ public SwitchPort getDstPort() {
+ return dstPort;
+ }
+
+ @Override
+ public String toString() {
+ return String.format("%s --(%f Mbps, %d flows)--> %s",
+ getSrcPort().toString(),
+ getCapacity(),
+ getFlows().size(),
+ getDstPort().toString());
+ }
+}
diff --git a/src/test/java/net/onrc/onos/ofcontroller/app/NamedNode.java b/src/test/java/net/onrc/onos/ofcontroller/app/NamedNode.java
new file mode 100644
index 0000000..c900d53
--- /dev/null
+++ b/src/test/java/net/onrc/onos/ofcontroller/app/NamedNode.java
@@ -0,0 +1,19 @@
+package net.onrc.onos.ofcontroller.app;
+
+public class NamedNode {
+ protected String name;
+ protected NetworkGraph graph;
+
+ public NamedNode(NetworkGraph graph, String name) {
+ this.graph = graph;
+ this.name = name;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public NetworkGraph getNetworkGraph() {
+ return graph;
+ }
+}
diff --git a/src/test/java/net/onrc/onos/ofcontroller/app/NetworkGraph.java b/src/test/java/net/onrc/onos/ofcontroller/app/NetworkGraph.java
new file mode 100644
index 0000000..a062b61
--- /dev/null
+++ b/src/test/java/net/onrc/onos/ofcontroller/app/NetworkGraph.java
@@ -0,0 +1,71 @@
+package net.onrc.onos.ofcontroller.app;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedList;
+
+/**
+ * This code is valid for the architectural study purpose only.
+ * @author Toshio Koide (t-koide@onlab.us)
+ */
+public class NetworkGraph {
+ protected HashSet<Flow> flows;
+ protected HashMap<String, Switch> switches;
+
+ public NetworkGraph() {
+ flows = new HashSet<Flow>();
+ switches = new HashMap<String, Switch>();
+ }
+
+ // Switch operations
+
+ public Switch addSwitch(String name) {
+ if (switches.containsKey(name)) {
+ return null; // should throw exception
+ }
+ Switch sw = new Switch(this, name);
+ switches.put(sw.getName(), sw);
+ return sw;
+
+ }
+
+ public Switch getSwitch(String switchName) {
+ return switches.get(switchName);
+ }
+
+ // Link operations
+
+ public Link addLink(String srcSwitchName, Integer srcPortNo, String dstSwitchName, Integer dstPortNo) {
+ return new Link(
+ getSwitch(srcSwitchName).getPort(srcPortNo),
+ getSwitch(dstSwitchName).getPort(dstPortNo));
+ }
+
+ public Link[] addBidirectionalLinks(String srcSwitchName, Integer srcPortNo, String dstSwitchName, Integer dstPortNo) {
+ Link[] links = new Link[2];
+ links[0] = addLink(srcSwitchName, srcPortNo, dstSwitchName, dstPortNo);
+ links[1] = addLink(dstSwitchName, dstPortNo, srcSwitchName, srcPortNo);
+
+ return links;
+ }
+
+ public Collection<Link> getLinks() {
+ LinkedList<Link> links = new LinkedList<Link>();
+ for (Switch sw: switches.values()) {
+ for (SwitchPort port: sw.getPorts()) {
+ Link link = port.outgoingLink;
+ if (link != null) {
+ links.add(link);
+ }
+ }
+ }
+ return links;
+ }
+
+ // Flow operations
+
+ public boolean addFlow(Flow flow) {
+ return flows.add(flow);
+ }
+}
diff --git a/src/test/java/net/onrc/onos/ofcontroller/app/NetworkGraphEntity.java b/src/test/java/net/onrc/onos/ofcontroller/app/NetworkGraphEntity.java
new file mode 100644
index 0000000..9a26b31
--- /dev/null
+++ b/src/test/java/net/onrc/onos/ofcontroller/app/NetworkGraphEntity.java
@@ -0,0 +1,17 @@
+package net.onrc.onos.ofcontroller.app;
+
+/**
+ * This code is valid for the architectural study purpose only.
+ * @author Toshio Koide (t-koide@onlab.us)
+ */
+public class NetworkGraphEntity {
+ protected NetworkGraph graph;
+
+ public NetworkGraphEntity(NetworkGraph graph) {
+ this.graph = graph;
+ }
+
+ public NetworkGraph getNetworkGraph() {
+ return graph;
+ }
+}
diff --git a/src/test/java/net/onrc/onos/ofcontroller/app/Path.java b/src/test/java/net/onrc/onos/ofcontroller/app/Path.java
new file mode 100644
index 0000000..318dbda
--- /dev/null
+++ b/src/test/java/net/onrc/onos/ofcontroller/app/Path.java
@@ -0,0 +1,25 @@
+package net.onrc.onos.ofcontroller.app;
+
+import java.util.Iterator;
+import java.util.LinkedList;
+
+/**
+ * Base class for Path representation
+ * This code is valid for the architectural study purpose only.
+ * @author Toshio Koide (t-koide@onlab.us)
+ */
+public class Path extends LinkedList<Link> {
+ private static final long serialVersionUID = 7127274096495173415L;
+
+ @Override
+ public String toString() {
+ StringBuilder builder = new StringBuilder();
+ Iterator<Link> i = this.iterator();
+ while (i.hasNext()) {
+ builder.append(i.next().toString());
+ if (i.hasNext())
+ builder.append(", ");
+ }
+ return builder.toString();
+ }
+}
diff --git a/src/test/java/net/onrc/onos/ofcontroller/app/ShortestPath.java b/src/test/java/net/onrc/onos/ofcontroller/app/ShortestPath.java
new file mode 100644
index 0000000..4789c6e
--- /dev/null
+++ b/src/test/java/net/onrc/onos/ofcontroller/app/ShortestPath.java
@@ -0,0 +1,9 @@
+package net.onrc.onos.ofcontroller.app;
+
+/**
+ * @author Toshio Koide (t-koide@onlab.us)
+ * This code is valid for the architectural study purpose only.
+ */
+public class ShortestPath implements BaseApplication {
+
+}
diff --git a/src/test/java/net/onrc/onos/ofcontroller/app/ShortestPathTest.java b/src/test/java/net/onrc/onos/ofcontroller/app/ShortestPathTest.java
new file mode 100644
index 0000000..4bf1d4c
--- /dev/null
+++ b/src/test/java/net/onrc/onos/ofcontroller/app/ShortestPathTest.java
@@ -0,0 +1,18 @@
+package net.onrc.onos.ofcontroller.app;
+
+import static org.junit.Assert.*;
+
+import org.junit.Test;
+
+/**
+ * This code is valid for the architectural study purpose only.
+ * @author Toshio Koide (t-koide@onlab.us)
+ */
+public class ShortestPathTest {
+
+ @Test
+ public void test() {
+ fail("Not yet implemented");
+ }
+
+}
diff --git a/src/test/java/net/onrc/onos/ofcontroller/app/SimpleTrafficEngineering.java b/src/test/java/net/onrc/onos/ofcontroller/app/SimpleTrafficEngineering.java
new file mode 100644
index 0000000..3714da0
--- /dev/null
+++ b/src/test/java/net/onrc/onos/ofcontroller/app/SimpleTrafficEngineering.java
@@ -0,0 +1,77 @@
+package net.onrc.onos.ofcontroller.app;
+
+/**
+ * This code is valid for the architectural study purpose only.
+ * @author Toshio Koide (t-koide@onlab.us)
+ */
+public class SimpleTrafficEngineering implements BaseApplication {
+ NetworkGraph graph;
+
+ /**
+ * Instantiate SimpleTrafficEngineering application
+ *
+ * 1. store NetworkGraph as a cache
+ *
+ * @param graph
+ */
+ public SimpleTrafficEngineering(NetworkGraph graph) {
+ this.graph = graph;
+ }
+
+ /**
+ * Allocate specified bandwidth between specified switch ports
+ *
+ * @param srcPort
+ * @param dstPort
+ * @param bandWidth
+ * @return
+ */
+ public ConstrainedFlow allocate(SwitchPort srcPort, SwitchPort dstPort, double bandWidth) {
+ ConstrainedFlow flow = new ConstrainedFlow(this.graph, null, srcPort, dstPort, bandWidth);
+
+ // 1. store Flow object to NetworkGraph
+ if (!graph.addFlow(flow)) {
+ return flow;
+ }
+
+ // 2. calculate path from srcPort to dstPort under condition of bandWidth
+ if (!flow.calcPath()) {
+ return flow;
+ }
+
+ // debug (show path)
+ System.out.println("path was calculated:");
+ System.out.println("[Flow] " + flow.toString());
+
+ // 3. allocate bandwidth in NetworkGraph
+ if (!flow.installPath()) {
+ return flow;
+ }
+
+ // debug (show path)
+ System.out.println("bandwidth was allocated.");
+ System.out.println("[Flow] " + flow.toString());
+
+ // (then, flow entries are created and installed from stored path information in the Flow object by another processes)
+ return flow;
+ }
+
+ /**
+ * Release specified Flow object
+ *
+ * @param flow
+ */
+ public void release(ConstrainedFlow flow) {
+ // 1. release bandwidth (remove property of links) in NetworkGraph
+ flow.uninstallPath();
+
+ // debug (show path)
+ System.out.println("bandwidth was released.");
+ System.out.println("[Flow] " + flow.toString());
+
+ // 2. deactivate Flow object
+
+ // (then, flow entries are removed by another processes)
+ // (retain flow object in NetworkGraph as a removed flow object)
+ }
+}
diff --git a/src/test/java/net/onrc/onos/ofcontroller/app/SimpleTrafficEngineeringTest.java b/src/test/java/net/onrc/onos/ofcontroller/app/SimpleTrafficEngineeringTest.java
new file mode 100644
index 0000000..ceb9135
--- /dev/null
+++ b/src/test/java/net/onrc/onos/ofcontroller/app/SimpleTrafficEngineeringTest.java
@@ -0,0 +1,80 @@
+package net.onrc.onos.ofcontroller.app;
+
+import static org.junit.Assert.*;
+
+import net.onrc.onos.ofcontroller.app.Flow.FlowState;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * This code is valid for the architectural study purpose only.
+ * @author Toshio Koide (t-koide@onlab.us)
+ */
+public class SimpleTrafficEngineeringTest {
+ NetworkGraph g;
+
+ @Before
+ public void setUp() {
+ g = new NetworkGraph();
+
+ // add 10 switches (24 ports switch)
+ for (Integer i=1; i<10; i++) {
+ Switch sw = g.addSwitch("v" + i.toString());
+ for (Integer j=1; j<=24; j++) {
+ sw.addPort(j);
+ }
+ }
+
+ // add loop path
+ g.addBidirectionalLinks("v1", 1, "v2", 2);
+ g.addBidirectionalLinks("v2", 1, "v3", 2);
+ g.addBidirectionalLinks("v3", 1, "v4", 2);
+ g.addBidirectionalLinks("v4", 1, "v5", 2);
+ g.addBidirectionalLinks("v5", 1, "v6", 2);
+ g.addBidirectionalLinks("v6", 1, "v7", 2);
+ g.addBidirectionalLinks("v7", 1, "v8", 2);
+ g.addBidirectionalLinks("v8", 1, "v9", 2);
+ g.addBidirectionalLinks("v9", 1, "v1", 2);
+
+ // add other links
+ g.addBidirectionalLinks("v1", 3, "v2", 3);
+ g.addBidirectionalLinks("v2", 4, "v3", 4);
+ g.addBidirectionalLinks("v4", 5, "v3", 5);
+ g.addBidirectionalLinks("v5", 6, "v6", 6);
+ g.addBidirectionalLinks("v7", 7, "v6", 7);
+ g.addBidirectionalLinks("v8", 8, "v1", 8);
+ g.addBidirectionalLinks("v9", 9, "v1", 9);
+
+ // set capacity of all links to 1000Mbps
+ for (Link link: g.getLinks()) {
+ link.setCapacity(1000.0);
+ }
+ }
+
+ @After
+ public void tearDown() {
+ }
+
+ @Test
+ public void useCase1() {
+ // load TE algorithm
+ SimpleTrafficEngineering te = new SimpleTrafficEngineering(g);
+
+ // get edge ports
+ SwitchPort srcPort = g.getSwitch("v1").getPort(20);
+ SwitchPort dstPort = g.getSwitch("v6").getPort(20);
+
+ // specify bandwidth (Mbps)
+ double bandWidth = 1000.0;
+
+ // allocate flow
+ ConstrainedFlow flow = te.allocate(srcPort, dstPort, bandWidth);
+ assertTrue(flow.isState(FlowState.PathInstalled));
+
+ // release flow
+ te.release(flow);
+ assertTrue(flow.isState(FlowState.PathRemoved));
+ }
+}
diff --git a/src/test/java/net/onrc/onos/ofcontroller/app/Switch.java b/src/test/java/net/onrc/onos/ofcontroller/app/Switch.java
new file mode 100644
index 0000000..6b7b75c
--- /dev/null
+++ b/src/test/java/net/onrc/onos/ofcontroller/app/Switch.java
@@ -0,0 +1,50 @@
+package net.onrc.onos.ofcontroller.app;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.LinkedList;
+
+/**
+ * This code is valid for the architectural study purpose only.
+ * @author Toshio Koide (t-koide@onlab.us)
+ */
+public class Switch extends NetworkGraphEntity {
+ protected HashMap<Integer, SwitchPort> ports;
+ protected String name;
+
+ public Switch(NetworkGraph graph, String name) {
+ super(graph);
+ this.name = name;
+ ports = new HashMap<Integer, SwitchPort>();
+ }
+
+ public SwitchPort addPort(Integer i) {
+ SwitchPort port = new SwitchPort(this, i);
+ ports.put(port.getPortNumber(), port);
+ return port;
+ }
+
+ public SwitchPort getPort(Integer i) {
+ return ports.get(i);
+ }
+
+ public Collection<SwitchPort> getPorts() {
+ return ports.values();
+ }
+
+ public Collection<Link> getAdjLinks() {
+ LinkedList<Link> links = new LinkedList<Link>();
+ for (SwitchPort port: getPorts()) {
+ Link link = port.getOutgointLink();
+ if (link != null) {
+ links.add(link);
+ }
+ }
+ return links;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+}
diff --git a/src/test/java/net/onrc/onos/ofcontroller/app/SwitchPort.java b/src/test/java/net/onrc/onos/ofcontroller/app/SwitchPort.java
new file mode 100644
index 0000000..7bea465
--- /dev/null
+++ b/src/test/java/net/onrc/onos/ofcontroller/app/SwitchPort.java
@@ -0,0 +1,49 @@
+package net.onrc.onos.ofcontroller.app;
+
+/**
+ * This code is valid for the architectural study purpose only.
+ * @author Toshio Koide (t-koide@onlab.us)
+ */
+public class SwitchPort extends NetworkGraphEntity {
+ protected Switch parentSwitch;
+ protected Integer portNumber;
+ protected Link outgoingLink;
+ protected Link incomingLink;
+
+ public SwitchPort(Switch parentSwitch, Integer portNumber) {
+ super(parentSwitch.getNetworkGraph());
+ this.parentSwitch = parentSwitch;
+ this.portNumber = portNumber;
+ }
+
+ public Switch getSwitch() {
+ return parentSwitch;
+ }
+
+ public void setOutgoingLink(Link link) {
+ outgoingLink = link;
+ }
+
+ public Link getOutgointLink() {
+ return outgoingLink;
+ }
+
+ public void setIncomingLink(Link link) {
+ incomingLink = link;
+ }
+
+ public Link getIncomingLink() {
+ return incomingLink;
+ }
+
+ public Integer getPortNumber() {
+ return portNumber;
+ }
+
+ @Override
+ public String toString() {
+ return String.format("%s:%d",
+ getSwitch().getName(),
+ getPortNumber());
+ }
+}