diff --git a/src/main/java/net/floodlightcontroller/core/OFMessageFilterManager.java b/src/main/java/net/floodlightcontroller/core/OFMessageFilterManager.java index 5d9a38fc947bae9a079a64f11df579bbe2b652c0..777bfaf44d87997e9a4020f7beec87977e698620 100644 --- a/src/main/java/net/floodlightcontroller/core/OFMessageFilterManager.java +++ b/src/main/java/net/floodlightcontroller/core/OFMessageFilterManager.java @@ -423,11 +423,11 @@ public class OFMessageFilterManager packetClient.pushMessageAsync(sendMsg); } } catch (TTransportException e) { - log.error("Caught TTransportException: {}", e); + log.error("Caught TTransportException: {}", e.getMessage()); disconnectFromPSServer(); connectToPSServer(); } catch (Exception e) { - log.error("Caught exception: {}", e); + log.error("Caught exception: {}", e.getMessage()); disconnectFromPSServer(); connectToPSServer(); } diff --git a/src/main/java/net/floodlightcontroller/core/internal/Controller.java b/src/main/java/net/floodlightcontroller/core/internal/Controller.java index d61231fa66a1e94b44b14e84bf850d3162152b80..a2de33dd27ca5da397c6e77635e44e775d1e0bf4 100644 --- a/src/main/java/net/floodlightcontroller/core/internal/Controller.java +++ b/src/main/java/net/floodlightcontroller/core/internal/Controller.java @@ -656,7 +656,7 @@ public class Controller implements IFloodlightProviderService, // If role is MASTER we will promote switch to active // list when we receive the switch's role reply messages log.debug("This controller's role is {}, " + - "sending initial role request msg to {}", + "sending initial role request msg to {}", role, sw); Collection<OFSwitchImpl> swList = new ArrayList<OFSwitchImpl>(1); swList.add(sw); @@ -666,7 +666,7 @@ public class Controller implements IFloodlightProviderService, // Role supported not enabled on controller (for now) // automatically promote switch to active state. log.debug("This controller's role is null, " + - "not sending role request msg to {}", + "not sending role request msg to {}", role, sw); // Need to clear FlowMods before we add the switch // and dispatch updates otherwise we have a race condition. @@ -773,7 +773,7 @@ public class Controller implements IFloodlightProviderService, state.firstRoleReplyReceived = true; } - protected boolean handleVendorMessage(OFVendor vendorMessage) { + protected boolean handleVendorMessage(OFVendor vendorMessage) { boolean shouldHandleMessage = false; int vendor = vendorMessage.getVendor(); switch (vendor) { @@ -815,7 +815,9 @@ public class Controller implements IFloodlightProviderService, switch (m.getType()) { case HELLO: - log.debug("HELLO from {}", sw); + if (log.isDebugEnabled()) + log.debug("HELLO from {}", sw); + if (state.hsState.equals(HandshakeState.START)) { state.hsState = HandshakeState.HELLO; sendHelloConfiguration(); @@ -833,7 +835,9 @@ public class Controller implements IFloodlightProviderService, case ECHO_REPLY: break; case FEATURES_REPLY: - log.debug("Features Reply from {}", sw); + if (log.isDebugEnabled()) + log.debug("Features Reply from {}", sw); + if (state.hsState.equals(HandshakeState.HELLO)) { sw.setFeaturesReply((OFFeaturesReply) m); sendFeatureReplyConfiguration(); @@ -847,6 +851,9 @@ public class Controller implements IFloodlightProviderService, } break; case GET_CONFIG_REPLY: + if (log.isDebugEnabled()) + log.debug("Get config reply from {}", sw); + if (!state.hsState.equals(HandshakeState.FEATURES_REPLY)) { String em = "Unexpected GET_CONFIG_REPLY from " + sw; throw new SwitchStateException(em); @@ -1288,7 +1295,7 @@ public class Controller implements IFloodlightProviderService, // No need to acquire the listener lock, since // this method is only called after netty has processed all // pending messages - log.debug("removeSwitch: {}", sw); + log.debug("removeSwitch: {}", sw); if (!this.activeSwitches.remove(sw.getId(), sw) || !sw.isConnected()) { log.debug("Not removing switch {}; already removed", sw); return; @@ -1581,7 +1588,7 @@ public class Controller implements IFloodlightProviderService, } protected void updateInactiveSwitchInfo(IOFSwitch sw) { - log.debug("Update DB with inactiveSW {}", sw); + log.debug("Update DB with inactiveSW {}", sw); // Update the controller info in the storage source to be inactive Map<String, Object> switchInfo = new HashMap<String, Object>(); String datapathIdString = sw.getStringId(); @@ -1662,7 +1669,7 @@ public class Controller implements IFloodlightProviderService, //for (Short portNum : oldports.keySet()) { // sw.deletePort(portNum); //} - } + } protected void removePortInfo(IOFSwitch sw, short portNumber) { String datapathIdString = sw.getStringId(); @@ -1702,11 +1709,11 @@ public class Controller implements IFloodlightProviderService, roleString = properties.getProperty("floodlight.role"); } catch (IOException exc) { - // Don't treat it as an error if the file specified by the - // rolepath property doesn't exist. This lets us enable the - // HA mechanism by just creating/setting the floodlight.role - // property in that file without having to modify the - // floodlight properties. + // Don't treat it as an error if the file specified by the + // rolepath property doesn't exist. This lets us enable the + // HA mechanism by just creating/setting the floodlight.role + // property in that file without having to modify the + // floodlight properties. } } } @@ -2016,9 +2023,9 @@ public class Controller implements IFloodlightProviderService, } } - @Override - public long getSystemStartTime() { - return (this.systemStartTime); - } + @Override + public long getSystemStartTime() { + return (this.systemStartTime); + } } diff --git a/src/main/java/net/floodlightcontroller/core/internal/OFSwitchImpl.java b/src/main/java/net/floodlightcontroller/core/internal/OFSwitchImpl.java index 7f06870ca1085fabf50e2eebf3a9beeabd8de5d2..948714f079d8a3806e0bf0377282e58d1bfe1a99 100644 --- a/src/main/java/net/floodlightcontroller/core/internal/OFSwitchImpl.java +++ b/src/main/java/net/floodlightcontroller/core/internal/OFSwitchImpl.java @@ -18,8 +18,10 @@ package net.floodlightcontroller.core.internal; import java.io.IOException; +import java.net.SocketAddress; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collection; import java.util.Date; import java.util.HashMap; import java.util.LinkedList; @@ -37,11 +39,14 @@ import net.floodlightcontroller.core.IFloodlightProviderService; import net.floodlightcontroller.core.IOFMessageListener; import net.floodlightcontroller.core.IFloodlightProviderService.Role; import net.floodlightcontroller.core.IOFSwitch; -import net.floodlightcontroller.core.types.MacVlanPair; +import net.floodlightcontroller.core.web.serializers.DPIDSerializer; import net.floodlightcontroller.threadpool.IThreadPoolService; import net.floodlightcontroller.util.TimedCache; import org.codehaus.jackson.annotate.JsonIgnore; +import org.codehaus.jackson.annotate.JsonProperty; +import org.codehaus.jackson.map.annotate.JsonSerialize; +import org.codehaus.jackson.map.ser.ToStringSerializer; import org.jboss.netty.channel.Channel; import org.openflow.protocol.OFFeaturesReply; import org.openflow.protocol.OFFlowMod; @@ -82,8 +87,6 @@ public class OFSwitchImpl implements IOFSwitch { protected Channel channel; protected AtomicInteger transactionIdSource; protected Map<Short, OFPhysicalPort> ports; - protected Long switchClusterId; - protected Map<MacVlanPair,Short> macVlanToPortMap; protected Map<Integer,OFStatisticsFuture> statsFutureMap; protected Map<Integer, IOFMessageListener> iofMsgListenersMap; protected boolean connected; @@ -132,7 +135,6 @@ public class OFSwitchImpl implements IOFSwitch { this.connectedSince = new Date(); this.transactionIdSource = new AtomicInteger(); this.ports = new ConcurrentHashMap<Short, OFPhysicalPort>(); - this.switchClusterId = null; this.connected = true; this.statsFutureMap = new ConcurrentHashMap<Integer,OFStatisticsFuture>(); this.iofMsgListenersMap = new ConcurrentHashMap<Integer,IOFMessageListener>(); @@ -241,27 +243,20 @@ public class OFSwitchImpl implements IOFSwitch { channel.close(); } + @JsonIgnore public OFFeaturesReply getFeaturesReply() { return this.featuresReply; } - public void setSwitchClusterId(Long id) { - this.switchClusterId = id; - } - - public Long getSwitchClusterId() { - return switchClusterId; - } - public synchronized void setFeaturesReply(OFFeaturesReply featuresReply) { this.featuresReply = featuresReply; for (OFPhysicalPort port : featuresReply.getPorts()) { ports.put(port.getPortNumber(), port); } - this.switchClusterId = featuresReply.getDatapathId(); this.stringId = HexString.toHexString(featuresReply.getDatapathId()); } + @JsonIgnore public synchronized List<OFPhysicalPort> getEnabledPorts() { List<OFPhysicalPort> result = new ArrayList<OFPhysicalPort>(); for (OFPhysicalPort port : ports.values()) { @@ -280,9 +275,15 @@ public class OFSwitchImpl implements IOFSwitch { ports.put(port.getPortNumber(), port); } + @JsonIgnore public Map<Short, OFPhysicalPort> getPorts() { return ports; } + + @JsonProperty("ports") + public Collection<OFPhysicalPort> getPortCollection() { + return ports.values(); + } public synchronized void deletePort(short portNumber) { ports.remove(portNumber); @@ -306,12 +307,15 @@ public class OFSwitchImpl implements IOFSwitch { } @Override + @JsonSerialize(using=DPIDSerializer.class) + @JsonProperty("dpid") public long getId() { if (this.featuresReply == null) throw new RuntimeException("Features reply has not yet been set"); return this.featuresReply.getDatapathId(); } + @JsonIgnore @Override public String getStringId() { return stringId; @@ -335,6 +339,7 @@ public class OFSwitchImpl implements IOFSwitch { return connectedSince; } + @JsonIgnore @Override public int getNextTransactionId() { return this.transactionIdSource.incrementAndGet(); @@ -409,6 +414,7 @@ public class OFSwitchImpl implements IOFSwitch { this.threadPool = tp; } + @JsonIgnore @Override public synchronized boolean isConnected() { return connected; @@ -424,6 +430,7 @@ public class OFSwitchImpl implements IOFSwitch { return role; } + @JsonIgnore @Override public boolean isActive() { return (role != Role.SLAVE); @@ -469,6 +476,7 @@ public class OFSwitchImpl implements IOFSwitch { } @Override + @JsonIgnore public Map<Short, Long> getPortBroadcastHits() { return this.portBroadcastCacheHitMap; } @@ -517,6 +525,15 @@ public class OFSwitchImpl implements IOFSwitch { public Lock getListenerWriteLock() { return listenerLock.writeLock(); } + + /** + * Get the IP Address for the switch + * @return the inet address + */ + @JsonSerialize(using=ToStringSerializer.class) + public SocketAddress getInetAddress() { + return channel.getRemoteAddress(); + } /** * Send NX role request message to the switch requesting the specified role. diff --git a/src/main/java/net/floodlightcontroller/core/web/ControllerSwitchesResource.java b/src/main/java/net/floodlightcontroller/core/web/ControllerSwitchesResource.java index c8f74860e7369ecb789be974bc3343ba86afcf78..454f566cf78fbf5fcf1ec73c705a59e99a0d83d4 100644 --- a/src/main/java/net/floodlightcontroller/core/web/ControllerSwitchesResource.java +++ b/src/main/java/net/floodlightcontroller/core/web/ControllerSwitchesResource.java @@ -17,14 +17,16 @@ package net.floodlightcontroller.core.web; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.Collections; +import java.util.Iterator; import net.floodlightcontroller.core.IFloodlightProviderService; import net.floodlightcontroller.core.IOFSwitch; +import net.floodlightcontroller.util.FilterIterator; +import org.openflow.util.HexString; +import org.restlet.data.Form; +import org.restlet.data.Status; import org.restlet.resource.Get; import org.restlet.resource.ServerResource; @@ -33,19 +35,47 @@ import org.restlet.resource.ServerResource; * @author readams */ public class ControllerSwitchesResource extends ServerResource { + public static final String DPID_ERROR = + "Invalid Switch DPID: must be a 64-bit quantity, expressed in " + + "hex as AA:BB:CC:DD:EE:FF:00:11"; + @Get("json") - public List<Map<String, String>> retrieve() { - List<Map<String, String>> switchIds = new ArrayList<Map<String, String>>(); + public Iterator<IOFSwitch> retrieve() { IFloodlightProviderService floodlightProvider = (IFloodlightProviderService)getContext().getAttributes(). get(IFloodlightProviderService.class.getCanonicalName()); - Map<Long, IOFSwitch> switches = floodlightProvider.getSwitches(); - for (IOFSwitch s: switches.values()) { - Map<String, String> m = new HashMap<String, String>(); - m.put("dpid", s.getStringId()); - switchIds.add(m); + Long switchDPID = null; + + Form form = getQuery(); + String dpid = form.getFirstValue("dpid", true); + if (dpid != null) { + try { + switchDPID = HexString.toLong(dpid); + } catch (Exception e) { + setStatus(Status.CLIENT_ERROR_BAD_REQUEST, DPID_ERROR); + return null; + } } - return switchIds; + if (switchDPID != null) { + IOFSwitch sw = + floodlightProvider.getSwitches().get(switchDPID); + if (sw != null) + return Collections.singleton(sw).iterator(); + return Collections.<IOFSwitch>emptySet().iterator(); + } + final String dpidStartsWith = + form.getFirstValue("dpid__startswith", true); + Iterator<IOFSwitch> switer = + floodlightProvider.getSwitches().values().iterator(); + if (dpidStartsWith != null) { + return new FilterIterator<IOFSwitch>(switer) { + @Override + protected boolean matches(IOFSwitch value) { + return value.getStringId().startsWith(dpidStartsWith); + } + }; + } + return switer; } } diff --git a/src/main/java/net/floodlightcontroller/core/web/serializers/ByteArrayMACSerializer.java b/src/main/java/net/floodlightcontroller/core/web/serializers/ByteArrayMACSerializer.java new file mode 100644 index 0000000000000000000000000000000000000000..66c33f55bfbf5262049c9cf60c2c730fcd69a04a --- /dev/null +++ b/src/main/java/net/floodlightcontroller/core/web/serializers/ByteArrayMACSerializer.java @@ -0,0 +1,40 @@ +/** +* Copyright 2011,2012 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 +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +* License for the specific language governing permissions and limitations +* under the License. +**/ + +package net.floodlightcontroller.core.web.serializers; + +import java.io.IOException; + +import org.codehaus.jackson.JsonGenerator; +import org.codehaus.jackson.JsonProcessingException; +import org.codehaus.jackson.map.JsonSerializer; +import org.codehaus.jackson.map.SerializerProvider; +import org.openflow.util.HexString; + +/** + * Serialize a MAC as colon-separated hexadecimal + */ +public class ByteArrayMACSerializer extends JsonSerializer<byte[]> { + + @Override + public void serialize(byte[] mac, JsonGenerator jGen, + SerializerProvider serializer) + throws IOException, JsonProcessingException { + jGen.writeString(HexString.toHexString(mac)); + } + +} diff --git a/src/main/java/net/floodlightcontroller/core/web/serializers/UShortSerializer.java b/src/main/java/net/floodlightcontroller/core/web/serializers/UShortSerializer.java new file mode 100644 index 0000000000000000000000000000000000000000..c125c76fc6138924f4ac04ceb918ca7dcbe80d90 --- /dev/null +++ b/src/main/java/net/floodlightcontroller/core/web/serializers/UShortSerializer.java @@ -0,0 +1,40 @@ +/** +* Copyright 2011,2012 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 +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +* License for the specific language governing permissions and limitations +* under the License. +**/ + +package net.floodlightcontroller.core.web.serializers; + +import java.io.IOException; + +import org.codehaus.jackson.JsonGenerator; +import org.codehaus.jackson.JsonProcessingException; +import org.codehaus.jackson.map.JsonSerializer; +import org.codehaus.jackson.map.SerializerProvider; + +/** + * Serialize a short value as an unsigned short + */ +public class UShortSerializer extends JsonSerializer<Short> { + + @Override + public void serialize(Short s, JsonGenerator jGen, + SerializerProvider serializer) throws IOException, + JsonProcessingException { + if (s == null) jGen.writeNull(); + else jGen.writeNumber(s.shortValue() & 0xffff); + } + +} diff --git a/src/main/java/net/floodlightcontroller/devicemanager/IDeviceService.java b/src/main/java/net/floodlightcontroller/devicemanager/IDeviceService.java index 5d482c48133e1c09d0945bbc2d2117472523ee54..ad29a947fbed2a3af94e24259fe58701f7c5e778 100755 --- a/src/main/java/net/floodlightcontroller/devicemanager/IDeviceService.java +++ b/src/main/java/net/floodlightcontroller/devicemanager/IDeviceService.java @@ -189,17 +189,6 @@ public interface IDeviceService extends IFloodlightService { */ public void addListener(IDeviceListener listener); - - /** - * Flush and/or reclassify all entities in a class - * - * @param entityClass the class to flush. If null, flush all classes - * @param reclassify if true, begin an asynchronous task to reclassify the - * flushed entities - */ - public void flushEntityCache(IEntityClass entityClass, - boolean reclassify); - /** * Specify points in the network where attachment points are not to * be learned. diff --git a/src/main/java/net/floodlightcontroller/devicemanager/IEntityClassListener.java b/src/main/java/net/floodlightcontroller/devicemanager/IEntityClassListener.java new file mode 100644 index 0000000000000000000000000000000000000000..6029af1b6c855460a45b502e4c4f568761fc648f --- /dev/null +++ b/src/main/java/net/floodlightcontroller/devicemanager/IEntityClassListener.java @@ -0,0 +1,35 @@ +/** +* 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 +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +* License for the specific language governing permissions and limitations +* under the License. +**/ + +package net.floodlightcontroller.devicemanager; + +import java.util.Set; + +/** + * Implementors of this interface can receive updates from DeviceManager about + * the changes entity Classes. + * + * @author Ananth Suryanarayana (Ananth.Suryanarayana@bigswitch.com) + */ +public interface IEntityClassListener { + + /** + * Process entity classes change event. + * @param entityClassNames Set of entity classes changed + */ + public void entityClassChanged(Set<String> entityClassNames); +} diff --git a/src/main/java/net/floodlightcontroller/devicemanager/IEntityClassifierService.java b/src/main/java/net/floodlightcontroller/devicemanager/IEntityClassifierService.java index 8d693ce9220155f92ef2aef5ecfec785eee78c84..2569a7df54ed892464810ca415b12a52d1ea76a7 100644 --- a/src/main/java/net/floodlightcontroller/devicemanager/IEntityClassifierService.java +++ b/src/main/java/net/floodlightcontroller/devicemanager/IEntityClassifierService.java @@ -98,5 +98,11 @@ public interface IEntityClassifierService extends IFloodlightService { void deviceUpdate(IDevice oldDevice, Collection<? extends IDevice> newDevices); + /** + * Adds a listener to listen for IEntityClassifierServices notifications + * + * @param listener The listener that wants the notifications + */ + public void addListener(IEntityClassListener listener); } diff --git a/src/main/java/net/floodlightcontroller/devicemanager/internal/DefaultEntityClassifier.java b/src/main/java/net/floodlightcontroller/devicemanager/internal/DefaultEntityClassifier.java index 353a72d1b5b8a3e382feb895d6ac24e10bc9c8e8..948272a0c10a845edc33cf8b54a526aae5d7e8f6 100644 --- a/src/main/java/net/floodlightcontroller/devicemanager/internal/DefaultEntityClassifier.java +++ b/src/main/java/net/floodlightcontroller/devicemanager/internal/DefaultEntityClassifier.java @@ -31,6 +31,7 @@ import net.floodlightcontroller.devicemanager.IDevice; import net.floodlightcontroller.devicemanager.IDeviceService; import net.floodlightcontroller.devicemanager.IDeviceService.DeviceField; import net.floodlightcontroller.devicemanager.IEntityClass; +import net.floodlightcontroller.devicemanager.IEntityClassListener; import net.floodlightcontroller.devicemanager.IEntityClassifierService; /** @@ -46,6 +47,12 @@ public class DefaultEntityClassifier implements * A default fixed entity class */ protected static class DefaultEntityClass implements IEntityClass { + String name; + + public DefaultEntityClass(String name) { + this.name = name; + } + @Override public EnumSet<IDeviceService.DeviceField> getKeyFields() { return keyFields; @@ -53,7 +60,11 @@ public class DefaultEntityClassifier implements @Override public String getName() { - return "DefaultEntityClass"; + return name; + } + + public void setName(String name) { + this.name = name; } } @@ -61,7 +72,16 @@ public class DefaultEntityClassifier implements static { keyFields = EnumSet.of(DeviceField.MAC, DeviceField.VLAN); } - protected static IEntityClass entityClass = new DefaultEntityClass(); + protected static DefaultEntityClass entityClass = + new DefaultEntityClass("DefaultEntityClass"); + + public void setClassifierName (String name) { + entityClass.setName(name); + } + + public String getClassifierName (String name) { + return entityClass.getName(); + } @Override public IEntityClass classifyEntity(Entity entity) { @@ -121,4 +141,10 @@ public class DefaultEntityClassifier implements public void startUp(FloodlightModuleContext context) { // no-op } + + @Override + public void addListener(IEntityClassListener listener) { + // no-op + + } } diff --git a/src/main/java/net/floodlightcontroller/devicemanager/internal/DeviceManagerImpl.java b/src/main/java/net/floodlightcontroller/devicemanager/internal/DeviceManagerImpl.java index ba859bd9b13a525f8143d3627edc1e04b680d0fd..d5d53e5a9e502a46227a8c08462673cb0b92dfd5 100755 --- a/src/main/java/net/floodlightcontroller/devicemanager/internal/DeviceManagerImpl.java +++ b/src/main/java/net/floodlightcontroller/devicemanager/internal/DeviceManagerImpl.java @@ -49,6 +49,7 @@ import net.floodlightcontroller.core.util.SingletonTask; import net.floodlightcontroller.devicemanager.IDevice; import net.floodlightcontroller.devicemanager.IDeviceService; import net.floodlightcontroller.devicemanager.IEntityClass; +import net.floodlightcontroller.devicemanager.IEntityClassListener; import net.floodlightcontroller.devicemanager.IEntityClassifierService; import net.floodlightcontroller.devicemanager.IDeviceListener; import net.floodlightcontroller.devicemanager.SwitchPort; @@ -86,7 +87,7 @@ import org.slf4j.LoggerFactory; */ public class DeviceManagerImpl implements IDeviceService, IOFMessageListener, -IStorageSourceListener, IFloodlightModule, +IStorageSourceListener, IFloodlightModule, IEntityClassListener, IFlowReconcileListener, IInfoProvider, IHAListener { protected static Logger logger = LoggerFactory.getLogger(DeviceManagerImpl.class); @@ -461,12 +462,6 @@ IFlowReconcileListener, IInfoProvider, IHAListener { deviceListeners.add(listener); } - @Override - public void flushEntityCache(IEntityClass entityClass, - boolean reclassify) { - // TODO Auto-generated method stub - } - // ************* // IInfoProvider // ************* @@ -639,11 +634,12 @@ IFlowReconcileListener, IInfoProvider, IHAListener { floodlightProvider.addOFMessageListener(OFType.PACKET_IN, this); floodlightProvider.addHAListener(this); flowReconcileMgr.addFlowReconcileListener(this); + entityClassifier.addListener(this); Runnable ecr = new Runnable() { @Override public void run() { - cleanupEntities(); + cleanupEntities(null, false); entityCleanupTask.reschedule(ENTITY_CLEANUP_INTERVAL, TimeUnit.SECONDS); } @@ -858,11 +854,18 @@ IFlowReconcileListener, IInfoProvider, IHAListener { if ((dlAddrArr[0] & 0x1) != 0) return null; - long swDpid = ofmWithSwDpid.getSwitchDataPathId(); - short inPort = ofmWithSwDpid.getOfMatch().getInputPort(); + Long swDpid = null; + Short inPort = null; + + if (isSource) { + swDpid = ofmWithSwDpid.getSwitchDataPathId(); + inPort = ofmWithSwDpid.getOfMatch().getInputPort(); + } boolean learnap = true; - if (!isValidAttachmentPoint(swDpid, inPort)) { + if (swDpid == null || + inPort == null || + !isValidAttachmentPoint(swDpid, inPort)) { // If this is an internal port or we otherwise don't want // to learn on these ports. In the future, we should // handle this case by labeling flows with something that @@ -1279,10 +1282,46 @@ IFlowReconcileListener, IInfoProvider, IHAListener { } } + /** + * Flush and/or reclassify all entities in a class + * + * @param entityClass the class to flush. If null, flush all classes + * @param reclassify if true, begin an asynchronous task to reclassify the + * flushed entities + */ + private void flushEntityCache (Set<String> entityClassChangedSet, + boolean reclassify) { + if (reclassify) return; // TODO + + /* + * TODO This can be running at the same time by timer thread. Check + * and make sure that this is thread safe. + */ + cleanupEntities(entityClassChangedSet, true); + } + + // ********************* + // IEntityClassListener + // ********************* + @Override + public void entityClassChanged (Set<String> entityClassNames) { + + /* + * Flush the entire device entity cache for now. + */ + flushEntityCache(entityClassNames, false); + return; + } + /** * Clean up expired entities/devices + * + * @param[in] forceCleanup ForceCleanup of entities irrespective of age + * @param[in] specificEntities Cleanup only a specific set of entities */ - protected void cleanupEntities() { + protected void cleanupEntities (Set<String> specificEntities, + boolean forceCleanup) { + Calendar c = Calendar.getInstance(); c.add(Calendar.MILLISECOND, -ENTITY_TIMEOUT); Date cutoff = c.getTime(); @@ -1297,13 +1336,23 @@ IFlowReconcileListener, IInfoProvider, IHAListener { while (diter.hasNext()) { Device d = diter.next(); + /* + * If we are cleaning entities for a specific set of devices, + * skip if not applicable. + */ + if (specificEntities != null && d.getEntityClass() != null && + !specificEntities.contains(d.getEntityClass().getName())) { + continue; + } + while (true) { deviceUpdates.clear(); toRemove.clear(); toKeep.clear(); for (Entity e : d.getEntities()) { - if (e.getLastSeenTimestamp() != null && - 0 > e.getLastSeenTimestamp().compareTo(cutoff)) { + if (forceCleanup || + (e.getLastSeenTimestamp() != null && + 0 > e.getLastSeenTimestamp().compareTo(cutoff))) { // individual entity needs to be removed toRemove.add(e); } else { diff --git a/src/main/java/net/floodlightcontroller/routing/ForwardingBase.java b/src/main/java/net/floodlightcontroller/routing/ForwardingBase.java index a2eae4a43096dbbb083b3dab5be604ef058b8ced..445956a4d01cc8dd0bd40b1276f5275859f0c01d 100644 --- a/src/main/java/net/floodlightcontroller/routing/ForwardingBase.java +++ b/src/main/java/net/floodlightcontroller/routing/ForwardingBase.java @@ -47,11 +47,9 @@ import org.openflow.protocol.OFMatch; import org.openflow.protocol.OFMessage; import org.openflow.protocol.OFPacketIn; 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.util.U16; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -534,29 +532,6 @@ public abstract class ForwardingBase implements @Override public void deviceMoved(IDevice device) { - // Build flow mod to delete based on destination mac == device mac - OFMatch match = new OFMatch(); - match.setDataLayerDestination(Ethernet.toByteArray(device.getMACAddress())); - match.setWildcards(OFMatch.OFPFW_ALL ^ OFMatch.OFPFW_DL_DST); - long cookie = - AppCookie.makeCookie(FORWARDING_APP_ID, 0); - OFMessage fm = ((OFFlowMod) floodlightProvider.getOFMessageFactory() - .getMessage(OFType.FLOW_MOD)) - .setCommand(OFFlowMod.OFPFC_DELETE) - .setOutPort((short) OFPort.OFPP_NONE.getValue()) - .setMatch(match) - .setCookie(cookie) - .setLength(U16.t(OFFlowMod.MINIMUM_LENGTH)); - - // Flush to all switches - for (IOFSwitch outSw : floodlightProvider.getSwitches().values()) { - try { - outSw.write(fm, null); - } catch (IOException e) { - log.error("Failure sending flow mod delete for moved device", - e); - } - } } @Override diff --git a/src/main/java/net/floodlightcontroller/topology/NodePortTuple.java b/src/main/java/net/floodlightcontroller/topology/NodePortTuple.java index ea2ddca0275071e07b945eac4e415ea29ded50aa..b985bbbcb856f4181fbd5e7a439dd3080bad2c84 100644 --- a/src/main/java/net/floodlightcontroller/topology/NodePortTuple.java +++ b/src/main/java/net/floodlightcontroller/topology/NodePortTuple.java @@ -84,4 +84,8 @@ public class NodePortTuple { return false; return true; } + + public String toKeyString() { + return (HexString.toHexString(nodeId)+ "|" + portId); + } } diff --git a/src/main/java/org/openflow/protocol/OFPhysicalPort.java b/src/main/java/org/openflow/protocol/OFPhysicalPort.java index 009bef529214bb6c82826af778fe860f4835f364..58fdae59f56de9df28358e65f1b9cab038ab676e 100644 --- a/src/main/java/org/openflow/protocol/OFPhysicalPort.java +++ b/src/main/java/org/openflow/protocol/OFPhysicalPort.java @@ -21,16 +21,16 @@ import java.io.UnsupportedEncodingException; import java.nio.charset.Charset; import java.util.Arrays; +import net.floodlightcontroller.core.web.serializers.ByteArrayMACSerializer; +import net.floodlightcontroller.core.web.serializers.UShortSerializer; import org.codehaus.jackson.map.annotate.JsonSerialize; import org.jboss.netty.buffer.ChannelBuffer; -import org.openflow.protocol.serializers.OFPhysicalPortJSONSerializer; /** * Represents ofp_phy_port * @author David Erickson (daviderickson@cs.stanford.edu) - Mar 25, 2010 */ -@JsonSerialize(using=OFPhysicalPortJSONSerializer.class) public class OFPhysicalPort { public static int MINIMUM_LENGTH = 48; public static int OFP_ETH_ALEN = 6; @@ -221,6 +221,7 @@ public class OFPhysicalPort { /** * @return the portNumber */ + @JsonSerialize(using=UShortSerializer.class) public short getPortNumber() { return portNumber; } @@ -235,6 +236,7 @@ public class OFPhysicalPort { /** * @return the hardwareAddress */ + @JsonSerialize(using=ByteArrayMACSerializer.class) public byte[] getHardwareAddress() { return hardwareAddress; } diff --git a/src/main/java/org/openflow/protocol/serializers/OFPhysicalPortJSONSerializer.java b/src/main/java/org/openflow/protocol/serializers/OFPhysicalPortJSONSerializer.java deleted file mode 100644 index b847a72c6c59add03167666ab998a4ecbde26005..0000000000000000000000000000000000000000 --- a/src/main/java/org/openflow/protocol/serializers/OFPhysicalPortJSONSerializer.java +++ /dev/null @@ -1,57 +0,0 @@ -/** -* 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 -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -* License for the specific language governing permissions and limitations -* under the License. -**/ - -package org.openflow.protocol.serializers; - -import java.io.IOException; - -import org.codehaus.jackson.JsonGenerator; -import org.codehaus.jackson.JsonProcessingException; -import org.codehaus.jackson.map.JsonSerializer; -import org.codehaus.jackson.map.SerializerProvider; -import org.openflow.protocol.OFPhysicalPort; -import org.openflow.util.HexString; - -public class OFPhysicalPortJSONSerializer extends JsonSerializer<OFPhysicalPort> { - - /** - * Performs the serialization of a OFPhysicalPort object - */ - @Override - public void serialize(OFPhysicalPort port, JsonGenerator jGen, SerializerProvider serializer) throws IOException, JsonProcessingException { - jGen.writeStartObject(); - jGen.writeNumberField("advertisedFeatures", port.getAdvertisedFeatures()); - jGen.writeNumberField("config", port.getConfig()); - jGen.writeNumberField("currentFeatures", port.getCurrentFeatures()); - jGen.writeStringField("hardwareAddress", HexString.toHexString(port.getHardwareAddress())); - jGen.writeStringField("name", port.getName()); - jGen.writeNumberField("peerFeatures", port.getPeerFeatures()); - jGen.writeNumberField("portNumber", port.getPortNumber()); - jGen.writeNumberField("state", port.getState()); - jGen.writeNumberField("supportedFeatures", port.getSupportedFeatures()); - jGen.writeEndObject(); - } - - /** - * Tells SimpleModule that we are the serializer for OFPhysicalPort - */ - @Override - public Class<OFPhysicalPort> handledType() { - return OFPhysicalPort.class; - } - -}