diff --git a/src/main/java/net/floodlightcontroller/core/IFloodlightProviderService.java b/src/main/java/net/floodlightcontroller/core/IFloodlightProviderService.java index d61f753ef634f3750ff6936dc5ddbc43606d4fad..00adb103f0877ae3de6947da9c591433e01f3c0c 100644 --- a/src/main/java/net/floodlightcontroller/core/IFloodlightProviderService.java +++ b/src/main/java/net/floodlightcontroller/core/IFloodlightProviderService.java @@ -141,6 +141,8 @@ public interface IFloodlightProviderService extends */ public Map<Long,IOFSwitch> getAllSwitchMap(); + public IOFSwitch getSwitchByDpid(String dpid); + /** * Get the current role of the controller */ diff --git a/src/main/java/net/floodlightcontroller/core/internal/Controller.java b/src/main/java/net/floodlightcontroller/core/internal/Controller.java index e574cc711514b115cc2195d237bbba956b9ae9aa..3bdfdc21554276451193e0cce3afe14013e5e03e 100644 --- a/src/main/java/net/floodlightcontroller/core/internal/Controller.java +++ b/src/main/java/net/floodlightcontroller/core/internal/Controller.java @@ -1580,6 +1580,25 @@ public class Controller implements IFloodlightProviderService, messageListeners.remove(type); } + @Override + @Override + public IOFSwitch getSwitchByDpid(String dpid) { + Map<Long, IOFSwitch> switches = getSwitches(); + if (switches == null) return null; + Long switchid = HexString.toLong(dpid); + + if (switchid != null && switches.containsKey(switchid)) { + return switches.get(switchid); + } + + // TODO: This is a hack for the demo, which only has one switch + for (IOFSwitch sw : switches.values()) { + return sw; + } + + return null; + } + @Override public Map<OFType, List<IOFMessageListener>> getListeners() { Map<OFType, List<IOFMessageListener>> lers = diff --git a/src/main/java/net/floodlightcontroller/devicemanager/IDeviceService.java b/src/main/java/net/floodlightcontroller/devicemanager/IDeviceService.java index 5e8f221a9829bdcf25d0f37a41fd33047db3affe..eb3801344f73d68ab0c35e6db556c09edfa1ba68 100755 --- a/src/main/java/net/floodlightcontroller/devicemanager/IDeviceService.java +++ b/src/main/java/net/floodlightcontroller/devicemanager/IDeviceService.java @@ -20,6 +20,7 @@ package net.floodlightcontroller.devicemanager; import java.util.Collection; import java.util.EnumSet; import java.util.Iterator; +import java.util.Set; import net.floodlightcontroller.core.FloodlightContextStore; import net.floodlightcontroller.core.module.IFloodlightService; @@ -210,4 +211,6 @@ public interface IDeviceService extends IFloodlightService { public void removeSuppressAPs(long swId, short port); + public Set<SwitchPort> getSuppressAPs(); + } diff --git a/src/main/java/net/floodlightcontroller/devicemanager/internal/DeviceManagerImpl.java b/src/main/java/net/floodlightcontroller/devicemanager/internal/DeviceManagerImpl.java index 4d2868396c435472a56f0e93658f07ef008eb4bd..044829ac98022bfa9e6cfe9b92d493239a3fa8bc 100755 --- a/src/main/java/net/floodlightcontroller/devicemanager/internal/DeviceManagerImpl.java +++ b/src/main/java/net/floodlightcontroller/devicemanager/internal/DeviceManagerImpl.java @@ -603,6 +603,11 @@ IFlowReconcileListener, IInfoProvider { suppressAPs.remove(new SwitchPort(swId, port)); } + @Override + public Set<SwitchPort> getSuppressAPs() { + return Collections.unmodifiableSet(suppressAPs); + } + private void logListeners() { List<IDeviceListener> listeners = deviceListeners.getOrderedListeners(); if (listeners != null) { diff --git a/src/main/java/net/floodlightcontroller/routing/IRoutingService.java b/src/main/java/net/floodlightcontroller/routing/IRoutingService.java index 63b5d1856b00820f5558315d068655b4f3fb459f..a3d77a83ba6309c02c6f99c19d2523eab2ecfa3b 100644 --- a/src/main/java/net/floodlightcontroller/routing/IRoutingService.java +++ b/src/main/java/net/floodlightcontroller/routing/IRoutingService.java @@ -1,7 +1,7 @@ /** -* Copyright 2011, Big Switch Networks, Inc. +* Copyright 2011, Big Switch Networks, Inc. * Originally created by David Erickson, Stanford University -* +* * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. You may obtain * a copy of the License at @@ -35,8 +35,8 @@ public interface IRoutingService extends IFloodlightService { */ public Route getRoute(long src, long dst, long cookie); - /** - * Provides a route between src and dst, with option to allow or + /** + * Provides a route between src and dst, with option to allow or * not allow tunnels in the path. * @param src Source switch DPID. * @param dst Destination switch DPID. @@ -45,7 +45,7 @@ public interface IRoutingService extends IFloodlightService { */ public Route getRoute(long src, long dst, long cookie, boolean tunnelEnabled); - /** + /** * Provides a route between srcPort on src and dstPort on dst. * @param src Source switch DPID. * @param srcPort Source port on source switch. @@ -53,10 +53,10 @@ public interface IRoutingService extends IFloodlightService { * @param dstPort dstPort on Destination switch. * @param cookie cookie (usage determined by implementation; ignored by topology instance now). */ - public Route getRoute(long srcId, short srcPort, + public Route getRoute(long srcId, short srcPort, long dstId, short dstPort, long cookie); - /** + /** * Provides a route between srcPort on src and dstPort on dst. * @param src Source switch DPID. * @param srcPort Source port on source switch. @@ -65,7 +65,7 @@ public interface IRoutingService extends IFloodlightService { * @param cookie cookie (usage determined by implementation; ignored by topology instance now). * @param tunnelEnabled boolean option. */ - public Route getRoute(long srcId, short srcPort, + public Route getRoute(long srcId, short srcPort, long dstId, short dstPort, long cookie, boolean tunnelEnabled); @@ -82,4 +82,4 @@ public interface IRoutingService extends IFloodlightService { */ public boolean routeExists(long src, long dst, boolean tunnelEnabled); -} \ No newline at end of file +} diff --git a/src/main/java/net/floodlightcontroller/servicechaining/BITWServiceNode.java b/src/main/java/net/floodlightcontroller/servicechaining/BITWServiceNode.java new file mode 100644 index 0000000000000000000000000000000000000000..38752f0651b771a5662c7e91e26d9e538b16d9e1 --- /dev/null +++ b/src/main/java/net/floodlightcontroller/servicechaining/BITWServiceNode.java @@ -0,0 +1,28 @@ +package net.floodlightcontroller.servicechaining; + +import net.floodlightcontroller.topology.NodePortTuple; + +public class BITWServiceNode extends ServiceNode { + protected NodePortTuple ingressPort; + protected NodePortTuple egressPort; + + public BITWServiceNode(String tenant, String name) { + super(tenant, name, InsertionType.BUMPINTHEWIRE); + } + + public NodePortTuple getIngressPort() { + return ingressPort; + } + + public void setIngressPort(NodePortTuple ingressPort) { + this.ingressPort = ingressPort; + } + + public NodePortTuple getEgressPort() { + return egressPort; + } + + public void setEgressPort(NodePortTuple egressPort) { + this.egressPort = egressPort; + } +} diff --git a/src/main/java/net/floodlightcontroller/servicechaining/IServiceChainingService.java b/src/main/java/net/floodlightcontroller/servicechaining/IServiceChainingService.java new file mode 100644 index 0000000000000000000000000000000000000000..e72a5c84a7c78f861b0b2c1e81ed312b884d23fb --- /dev/null +++ b/src/main/java/net/floodlightcontroller/servicechaining/IServiceChainingService.java @@ -0,0 +1,27 @@ +package net.floodlightcontroller.servicechaining; + +import net.floodlightcontroller.core.FloodlightContextStore; +import net.floodlightcontroller.core.module.IFloodlightService; + +public interface IServiceChainingService extends IFloodlightService { + /** + * A FloodlightContextStore object that can be used to interact with the + * FloodlightContext information created by ServiceInsertion. + */ + public static final FloodlightContextStore<String> scStore = + new FloodlightContextStore<String>(); + + /** + * Returns the service chain by source BVS. + * @param bvsName + * @return the ServiceChain, null is the requested service is not found. + */ + public ServiceChain getServiceChainBySrcBVS(String bvsName); + + /** + * Returns the service chain by destination BVS. + * @param bvsName + * @return the ServiceChain, null is the requested service is not found. + */ + public ServiceChain getServiceChainByDstBVS(String bvsName); +} diff --git a/src/main/java/net/floodlightcontroller/servicechaining/ServiceChain.java b/src/main/java/net/floodlightcontroller/servicechaining/ServiceChain.java new file mode 100644 index 0000000000000000000000000000000000000000..7e2a6d4bc2ca811646318e0aace05b01a66ec647 --- /dev/null +++ b/src/main/java/net/floodlightcontroller/servicechaining/ServiceChain.java @@ -0,0 +1,123 @@ +package net.floodlightcontroller.servicechaining; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +/** + * ServiceChaining module encapsulates properties of service chains and their member nodes + * + * @author kjiang + * + */ +public class ServiceChain { + // Tenant + private String tenant; + + // Service Chain name + private String name; + + // Source network + private String srcBvsName; + + // Destination network + private String dstBvsName; + + // Service Description + private String description; + + // Ordered list of service Nodes + private List<ServiceNode> nodes; + + /** + * Constructor to create a NetworkService + * + * @param name + * @param vMac + * @param vIp + */ + public ServiceChain(String tenant, String name, String description, + String srcBvsName, String dstBvsName) { + this.tenant = tenant; + this.name = name; + this.description = description; + this.srcBvsName = srcBvsName; + this.dstBvsName = dstBvsName; + this.nodes = new ArrayList<ServiceNode>(); + } + + /** + * A getter for service tenant + * @return + */ + public String getTenant() { + return tenant; + } + + /** + * A getter for service name + * @return + */ + public String getName() { + return name; + } + + /** + * A getter for service description + * @return + */ + public String getDescription() { + return description; + } + + /** + * A getter for source BVS + */ + public String getSourceBvs() { + return srcBvsName; + } + + /** + * A getter for destination BVS + */ + public String getDestinationBvs() { + return dstBvsName; + } + + /** + * A getter returns an unmodifiable map of service nodes. + * @return + */ + public List<ServiceNode> getServiceNodes() { + return Collections.unmodifiableList(nodes); + } + + /** + * Add a service node to the end of the node list + */ + public boolean addNode(ServiceNode node) { + try { + return nodes.add(node); + } catch (Exception e) { + return false; + } + } + + /** + * Remove a service node from the node list + */ + public boolean removeNode(ServiceNode node) { + try { + return nodes.remove(node); + } catch (Exception e) { + return false; + } + } + + @Override + public String toString() { + return "ServiceChain [tenant=" + tenant + ", name=" + name + + ", srcBvsName=" + srcBvsName + ", dstBvsName=" + dstBvsName + + ", description=" + description + "]"; + } +} diff --git a/src/main/java/net/floodlightcontroller/servicechaining/ServiceNode.java b/src/main/java/net/floodlightcontroller/servicechaining/ServiceNode.java new file mode 100644 index 0000000000000000000000000000000000000000..dfceead4439b51c59c7bb3a0142797817cdbf7f8 --- /dev/null +++ b/src/main/java/net/floodlightcontroller/servicechaining/ServiceNode.java @@ -0,0 +1,67 @@ +package net.floodlightcontroller.servicechaining; + +public class ServiceNode { + public enum InsertionType { + L3, L2, BUMPINTHEWIRE, TAP, UNKNOWN + } + + public enum Direction { + INGRESS, EGRESS, ANY + } + + protected String name; + protected String tenant; + protected InsertionType type; + + public ServiceNode(String tenant, String name, InsertionType type) { + this.tenant = tenant; + this.name = name; + this.type = type; + } + + public String getTenant() { + return tenant; + } + + public String getName() { + return name; + } + + public InsertionType getServiceType() { + return this.type; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((name == null) ? 0 : name.hashCode()); + result = prime * result + ((tenant == null) ? 0 : tenant.hashCode()); + result = prime * result + ((type == null) ? 0 : type.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + ServiceNode other = (ServiceNode) obj; + if (name == null) { + if (other.name != null) + return false; + } else if (!name.equals(other.name)) + return false; + if (tenant == null) { + if (other.tenant != null) + return false; + } else if (!tenant.equals(other.tenant)) + return false; + if (type != other.type) + return false; + return true; + } +} diff --git a/src/main/java/net/floodlightcontroller/topology/TopologyInstance.java b/src/main/java/net/floodlightcontroller/topology/TopologyInstance.java index af49de70bbb6ca8f29426bc370d5b343fdc30442..893ab74e4d1e105fb3aa02b5bdf1fef2ac409716 100644 --- a/src/main/java/net/floodlightcontroller/topology/TopologyInstance.java +++ b/src/main/java/net/floodlightcontroller/topology/TopologyInstance.java @@ -36,6 +36,8 @@ import net.floodlightcontroller.routing.BroadcastTree; import net.floodlightcontroller.routing.Link; import net.floodlightcontroller.routing.Route; import net.floodlightcontroller.routing.RouteId; +import net.floodlightcontroller.servicechaining.ServiceChain; + import com.google.common.cache.*; /** @@ -659,7 +661,7 @@ public class TopologyInstance { return true; } - protected Route getRoute(long srcId, short srcPort, + protected Route getRoute(ServiceChain sc, long srcId, short srcPort, long dstId, short dstPort, long cookie) { diff --git a/src/main/java/net/floodlightcontroller/topology/TopologyManager.java b/src/main/java/net/floodlightcontroller/topology/TopologyManager.java index 9941e23c743592123ba9ea67c8ff93821f73df0a..523c63714894615f093430de8189f461bc5dc0f4 100644 --- a/src/main/java/net/floodlightcontroller/topology/TopologyManager.java +++ b/src/main/java/net/floodlightcontroller/topology/TopologyManager.java @@ -608,7 +608,7 @@ public class TopologyManager implements public Route getRoute(long src, short srcPort, long dst, short dstPort, long cookie, boolean tunnelEnabled) { TopologyInstance ti = getCurrentInstance(tunnelEnabled); - return ti.getRoute(src, srcPort, dst, dstPort, cookie); + return ti.getRoute(null, src, srcPort, dst, dstPort, cookie); } @Override diff --git a/src/test/java/net/floodlightcontroller/core/test/MockFloodlightProvider.java b/src/test/java/net/floodlightcontroller/core/test/MockFloodlightProvider.java index c18340efbf6775748a9b576cc3658ac5d609509c..181bf9a4bc5b7197b642afcd46a8bf7c2040b648 100644 --- a/src/test/java/net/floodlightcontroller/core/test/MockFloodlightProvider.java +++ b/src/test/java/net/floodlightcontroller/core/test/MockFloodlightProvider.java @@ -55,6 +55,7 @@ import org.openflow.protocol.OFMessage; import org.openflow.protocol.OFPacketIn; import org.openflow.protocol.OFType; import org.openflow.protocol.factory.BasicFactory; +import org.openflow.util.HexString; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -142,6 +143,19 @@ public class MockFloodlightProvider implements IFloodlightModule, IFloodlightPro return this.switches.get(dpid); } + @Override + public IOFSwitch getSwitchByDpid(String dpid) { + Map<Long, IOFSwitch> switches = getSwitches(); + if (switches == null) return null; + Long switchid = HexString.toLong(dpid); + + if (switchid != null && switches.containsKey(switchid)) { + return switches.get(switchid); + } + + return null; + } + public void setSwitches(Map<Long, IOFSwitch> switches) { this.switches = switches; }