diff --git a/build.xml b/build.xml index 385c82399e3ab696865d3ce64eafbf642c21ce0c..3acd1ecf9e03b716194b449a40844da847343bdc 100644 --- a/build.xml +++ b/build.xml @@ -67,9 +67,6 @@ <include name="jython-2.5.2.jar"/> <include name="libthrift-0.7.0.jar"/> <include name="guava-13.0.1.jar" /> - <include name="httpclient-4.2.2.jar" /> - <include name="httpcore-4.2.2.jar" /> - <include name="json-simple-1.1.1.jar" /> </patternset> <path id="classpath"> diff --git a/lib/httpclient-4.2.2.jar b/lib/httpclient-4.2.2.jar deleted file mode 100644 index 5f768c46407a6506d46766d1011f2fac342ec333..0000000000000000000000000000000000000000 Binary files a/lib/httpclient-4.2.2.jar and /dev/null differ diff --git a/lib/httpcore-4.2.2.jar b/lib/httpcore-4.2.2.jar deleted file mode 100644 index a64cd2f5e3eff5ea0ff91a545ba2da4dc3fd612b..0000000000000000000000000000000000000000 Binary files a/lib/httpcore-4.2.2.jar and /dev/null differ diff --git a/lib/json-simple-1.1.1.jar b/lib/json-simple-1.1.1.jar deleted file mode 100644 index 66347a6c86b7d6442358ca7643e4dc484fb01866..0000000000000000000000000000000000000000 Binary files a/lib/json-simple-1.1.1.jar and /dev/null differ diff --git a/src/main/java/net/floodlightcontroller/core/IOFSwitch.java b/src/main/java/net/floodlightcontroller/core/IOFSwitch.java index bf897567280040891f82cf0997dd793a33b1af6b..fb7cd7d44d2167386a78534725956737adffdaad 100644 --- a/src/main/java/net/floodlightcontroller/core/IOFSwitch.java +++ b/src/main/java/net/floodlightcontroller/core/IOFSwitch.java @@ -374,6 +374,16 @@ public interface IOFSwitch { * @return value for name */ Object getAttribute(String name); + + /** + * Check if the given attribute is present and if so whether it is equal + * to "other" + * @param name the name of the attribute to check + * @param other the object to compare the attribute against. + * @return true iff the specified attribute is set and equals() the given + * other object. + */ + boolean attributeEquals(String name, Object other); /** * Set properties for switch specific behavior diff --git a/src/main/java/net/floodlightcontroller/core/OFSwitchBase.java b/src/main/java/net/floodlightcontroller/core/OFSwitchBase.java index 39c017724eb632a2355e190c82635b018ecf9eb8..17bbcf07e292b25b7ad2dae2c675a80389aa199e 100644 --- a/src/main/java/net/floodlightcontroller/core/OFSwitchBase.java +++ b/src/main/java/net/floodlightcontroller/core/OFSwitchBase.java @@ -147,13 +147,20 @@ public abstract class OFSwitchBase implements IOFSwitch { this.setAttribute(PROP_SUPPORTS_OFPP_TABLE, new Boolean(true)); } + + @Override + public boolean attributeEquals(String name, Object other) { + Object attr = this.attributes.get(name); + if (attr == null) + return false; + return attr.equals(other); + } + @Override public Object getAttribute(String name) { - if (this.attributes.containsKey(name)) { - return this.attributes.get(name); - } - return null; + // returns null if key doesn't exist + return this.attributes.get(name); } @Override @@ -172,6 +179,7 @@ public abstract class OFSwitchBase implements IOFSwitch { return this.attributes.containsKey(name); } + @Override @JsonIgnore public void setChannel(Channel channel) { this.channel = channel; @@ -452,6 +460,7 @@ public abstract class OFSwitchBase implements IOFSwitch { this.floodlightProvider = floodlightProvider; } + @Override @JsonIgnore public void setThreadPoolService(IThreadPoolService tp) { this.threadPool = tp; @@ -560,6 +569,7 @@ public abstract class OFSwitchBase implements IOFSwitch { * switch list from being modified out from under the listeners. * @return */ + @Override @JsonIgnore public Lock getListenerReadLock() { return listenerLock.readLock(); @@ -572,6 +582,7 @@ public abstract class OFSwitchBase implements IOFSwitch { * message from the switch. * @return */ + @Override @JsonIgnore public Lock getListenerWriteLock() { return listenerLock.writeLock(); @@ -581,6 +592,7 @@ public abstract class OFSwitchBase implements IOFSwitch { * Get the IP Address for the switch * @return the inet address */ + @Override @JsonSerialize(using=ToStringSerializer.class) public SocketAddress getInetAddress() { return channel.getRemoteAddress(); diff --git a/src/main/java/net/floodlightcontroller/core/internal/Controller.java b/src/main/java/net/floodlightcontroller/core/internal/Controller.java index c4f502236253db5c3463ab6ae66be4f66dd26b9e..5f9cbd81d9153ef73ecc302094e10a7f2e513a10 100644 --- a/src/main/java/net/floodlightcontroller/core/internal/Controller.java +++ b/src/main/java/net/floodlightcontroller/core/internal/Controller.java @@ -1446,6 +1446,7 @@ public class Controller implements IFloodlightProviderService, @Override public Map<Long, IOFSwitch> getSwitches() { + if (activeSwitches == null) return null; return Collections.unmodifiableMap(this.activeSwitches); } diff --git a/src/main/java/net/floodlightcontroller/core/internal/RoleChanger.java b/src/main/java/net/floodlightcontroller/core/internal/RoleChanger.java index f9ec793b3ba9797ec06912dc5579772fccd15fb1..a65b28f6c1788ee351726038193b11999d045dcc 100644 --- a/src/main/java/net/floodlightcontroller/core/internal/RoleChanger.java +++ b/src/main/java/net/floodlightcontroller/core/internal/RoleChanger.java @@ -187,7 +187,7 @@ public class RoleChanger { @LogMessageDoc(level="ERROR", message="RoleRequestWorker task had an uncaught exception.", explanation="An unknown occured while processing an HA " + - "role change event.", + "role change event.", recommendation=LogMessageDoc.GENERIC_ACTION) protected class RoleRequestWorker extends Thread { @Override @@ -278,7 +278,7 @@ public class RoleChanger { message="Failed to send role request message " + "to switch {switch}: {message}. Disconnecting", explanation="An I/O error occurred while attempting to change " + - "the switch HA role.", + "the switch HA role.", recommendation=LogMessageDoc.CHECK_SWITCH) protected void sendRoleRequest(Collection<IOFSwitch> switches, Role role, long cookie) { @@ -331,7 +331,7 @@ public class RoleChanger { message="Timeout while waiting for role reply from switch {switch}." + " Disconnecting", explanation="Timed out waiting for the switch to respond to " + - "a request to change the HA role.", + "a request to change the HA role.", recommendation=LogMessageDoc.CHECK_SWITCH) protected void verifyRoleReplyReceived(Collection<IOFSwitch> switches, long cookie) { @@ -425,8 +425,11 @@ public class RoleChanger { * @return */ public boolean checkFirstPendingRoleRequestXid (IOFSwitch sw, int xid) { - LinkedList<PendingRoleRequestEntry> pendingRoleRequests = - pendingRequestMap.get(sw); + LinkedList<PendingRoleRequestEntry> pendingRoleRequests; + if (sw == null) { + return false; + } + pendingRoleRequests = pendingRequestMap.get(sw); if (pendingRoleRequests == null) { return false; } diff --git a/src/main/java/net/floodlightcontroller/firewall/FirewallRule.java b/src/main/java/net/floodlightcontroller/firewall/FirewallRule.java index 127b9658d31cfb6a9d19b6cdabcee0f249e0c08a..f5036f0917f7afec074a97be208b55284edc509f 100644 --- a/src/main/java/net/floodlightcontroller/firewall/FirewallRule.java +++ b/src/main/java/net/floodlightcontroller/firewall/FirewallRule.java @@ -115,7 +115,7 @@ public class FirewallRule implements Comparable<FirewallRule> { public boolean isSameAs(FirewallRule r) { if (this.action != r.action || this.wildcard_dl_type != r.wildcard_dl_type - || (this.wildcard_dl_type == false && this.dl_type == r.dl_type) + || (this.wildcard_dl_type == false && this.dl_type != r.dl_type) || this.wildcard_tp_src != r.wildcard_tp_src || (this.wildcard_tp_src == false && this.tp_src != r.tp_src) || this.wildcard_tp_dst != r.wildcard_tp_dst diff --git a/src/main/java/net/floodlightcontroller/linkdiscovery/ILinkDiscovery.java b/src/main/java/net/floodlightcontroller/linkdiscovery/ILinkDiscovery.java index f172f63be26459ce241e0c4400a3e63885b5bed4..17ad46a7a067c827605d64df3a4acb9443349233 100644 --- a/src/main/java/net/floodlightcontroller/linkdiscovery/ILinkDiscovery.java +++ b/src/main/java/net/floodlightcontroller/linkdiscovery/ILinkDiscovery.java @@ -13,13 +13,15 @@ public interface ILinkDiscovery { SWITCH_UPDATED("Switch Updated"), SWITCH_REMOVED("Switch Removed"), PORT_UP("Port Up"), - PORT_DOWN("Port Down"); - + PORT_DOWN("Port Down"), + TUNNEL_PORT_ADDED("Tunnel Port Added"), + TUNNEL_PORT_REMOVED("Tunnel Port Removed"); + private String value; UpdateOperation(String v) { value = v; } - + @Override public String toString() { return value; @@ -64,7 +66,7 @@ public interface ILinkDiscovery { this.srcType = stype; } - // For port up or port down. + // For port up or port down; and tunnel port added and removed. public LDUpdate(long sw, short port, UpdateOperation operation) { this.src = sw; this.srcPort = port; diff --git a/src/main/java/net/floodlightcontroller/linkdiscovery/internal/LinkDiscoveryManager.java b/src/main/java/net/floodlightcontroller/linkdiscovery/internal/LinkDiscoveryManager.java index 0cc268cde8e6a14ebaf8e06ec6d881f3ee0497f6..1e324d32737d1d12fdbfd0bc7c4a1285a9224888 100644 --- a/src/main/java/net/floodlightcontroller/linkdiscovery/internal/LinkDiscoveryManager.java +++ b/src/main/java/net/floodlightcontroller/linkdiscovery/internal/LinkDiscoveryManager.java @@ -188,7 +188,7 @@ public class LinkDiscoveryManager implements IOFMessageListener, * to false -- Initialized in the init method as well. */ public final boolean AUTOPORTFAST_DEFAULT = false; - boolean autoPortFastFeature = AUTOPORTFAST_DEFAULT; + protected boolean autoPortFastFeature = AUTOPORTFAST_DEFAULT; /** * Map from link to the most recent time it was verified functioning diff --git a/src/main/java/net/floodlightcontroller/loadbalancer/LoadBalancer.java b/src/main/java/net/floodlightcontroller/loadbalancer/LoadBalancer.java index 2ff0dabfa59c7f6ae7d8e78ffe1c70304e8082c4..3893ed5708d29acf52e80c78b922ee261cee1d88 100644 --- a/src/main/java/net/floodlightcontroller/loadbalancer/LoadBalancer.java +++ b/src/main/java/net/floodlightcontroller/loadbalancer/LoadBalancer.java @@ -1,9 +1,6 @@ package net.floodlightcontroller.loadbalancer; -import java.io.BufferedReader; import java.io.IOException; -import java.io.InputStreamReader; -import java.io.UnsupportedEncodingException; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; @@ -14,15 +11,8 @@ import java.util.HashSet; import java.util.List; import java.util.Map; -import org.apache.http.HttpResponse; -import org.apache.http.client.ClientProtocolException; -import org.apache.http.client.HttpClient; -import org.apache.http.client.methods.HttpPost; -import org.apache.http.entity.StringEntity; -import org.apache.http.impl.client.DefaultHttpClient; -import org.apache.http.message.BasicHeader; -import org.apache.http.protocol.HTTP; -import org.json.simple.JSONObject; +import org.openflow.protocol.OFFlowMod; +import org.openflow.protocol.OFMatch; import org.openflow.protocol.OFMessage; import org.openflow.protocol.OFPacketIn; import org.openflow.protocol.OFPacketOut; @@ -31,6 +21,7 @@ import org.openflow.protocol.OFType; import org.openflow.protocol.action.OFAction; import org.openflow.protocol.action.OFActionOutput; import org.openflow.util.HexString; +import org.openflow.util.U16; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -55,6 +46,8 @@ import net.floodlightcontroller.packet.UDP; import net.floodlightcontroller.restserver.IRestApiService; import net.floodlightcontroller.routing.IRoutingService; import net.floodlightcontroller.routing.Route; +import net.floodlightcontroller.staticflowentry.IStaticFlowEntryPusherService; +import net.floodlightcontroller.staticflowentry.StaticFlowEntries; import net.floodlightcontroller.topology.ITopologyService; import net.floodlightcontroller.topology.NodePortTuple; import net.floodlightcontroller.util.MACAddress; @@ -87,6 +80,7 @@ public class LoadBalancer implements IFloodlightModule, protected IDeviceService deviceManager; protected IRoutingService routingEngine; protected ITopologyService topology; + protected IStaticFlowEntryPusherService sfp; protected HashMap<String, LBVip> vips; protected HashMap<String, LBPool> pools; @@ -99,6 +93,9 @@ public class LoadBalancer implements IFloodlightModule, //Copied from Forwarding with message damper routine for pushing proxy Arp protected static int OFMESSAGE_DAMPER_CAPACITY = 10000; // ms. protected static int OFMESSAGE_DAMPER_TIMEOUT = 250; // ms + protected static String LB_ETHER_TYPE = "0x800"; + protected static int LB_PRIORITY = 32768; + // Comparator for sorting by SwitchCluster public Comparator<SwitchPort> clusterIdComparator = new Comparator<SwitchPort>() { @@ -483,97 +480,84 @@ public class LoadBalancer implements IFloodlightModule, * @param LBMember member * @param long pinSwitch */ - @SuppressWarnings("unchecked") public void pushStaticVipRoute(boolean inBound, Route route, IPClient client, LBMember member, long pinSwitch) { List<NodePortTuple> path = route.getPath(); if (path.size()>0) { - for (int i = 0; i < path.size(); i+=2) { - JSONObject json = new JSONObject(); + long sw = path.get(i).getNodeId(); - - json.put("switch", HexString.toHexString(sw)); + String swString = HexString.toHexString(path.get(i).getNodeId()); + String entryName; + String matchString = null; + String actionString = null; + + OFFlowMod fm = (OFFlowMod) floodlightProvider.getOFMessageFactory() + .getMessage(OFType.FLOW_MOD); + + fm.setIdleTimeout((short) 0); // infinite + fm.setHardTimeout((short) 0); // infinite + fm.setBufferId(OFPacketOut.BUFFER_ID_NONE); + fm.setCommand((short) 0); + fm.setFlags((short) 0); + fm.setOutPort(OFPort.OFPP_NONE.getValue()); + fm.setCookie((long) 0); + fm.setPriority(Short.MAX_VALUE); + if (inBound) { - json.put("name","inbound-vip-"+ member.vipId+"client-"+client.ipAddress+"-port-"+client.targetPort - +"srcswitch-"+path.get(0).getNodeId()+"sw-"+sw); - json.put("src-ip",IPv4.fromIPv4Address(client.ipAddress)); - json.put("protocol",String.valueOf(client.nw_proto)); - json.put("src-port",String.valueOf(client.srcPort & 0xffff)); - json.put("ether-type","0x800"); - json.put("priority","32768"); - json.put("ingress-port",String.valueOf(path.get(i).getPortId())); - json.put("active","true"); + entryName = "inbound-vip-"+ member.vipId+"client-"+client.ipAddress+"-port-"+client.targetPort + +"srcswitch-"+path.get(0).getNodeId()+"sw-"+sw; + matchString = "nw_src="+IPv4.fromIPv4Address(client.ipAddress)+"," + + "nw_proto="+String.valueOf(client.nw_proto)+"," + + "tp_src="+String.valueOf(client.srcPort & 0xffff)+"," + + "dl_type="+LB_ETHER_TYPE+"," + + "in_port="+String.valueOf(path.get(i).getPortId()); + if (sw == pinSwitch) { - json.put("actions","set-dst-ip="+IPv4.fromIPv4Address(member.address)+"," + actionString = "set-dst-ip="+IPv4.fromIPv4Address(member.address)+"," + "set-dst-mac="+member.macString+"," - + "output="+path.get(i+1).getPortId()); + + "output="+path.get(i+1).getPortId(); } else { - json.put("actions", - "output="+path.get(i+1).getPortId()); + actionString = + "output="+path.get(i+1).getPortId(); } } else { - json.put("name","outbound-vip-"+ member.vipId+"client-"+client.ipAddress+"-port-"+client.targetPort - +"srcswitch-"+path.get(0).getNodeId()+"sw-"+sw); - json.put("dst-ip",IPv4.fromIPv4Address(client.ipAddress)); - json.put("protocol",String.valueOf(client.nw_proto)); - json.put("dst-port",String.valueOf(client.srcPort & 0xffff)); - json.put("ether-type","0x800"); - json.put("priority","32768"); - json.put("ingress-port",String.valueOf(path.get(i).getPortId())); - json.put("active","true"); + entryName = "outbound-vip-"+ member.vipId+"client-"+client.ipAddress+"-port-"+client.targetPort + +"srcswitch-"+path.get(0).getNodeId()+"sw-"+sw; + matchString = "nw_dst="+IPv4.fromIPv4Address(client.ipAddress)+"," + + "nw_proto="+String.valueOf(client.nw_proto)+"," + + "tp_dst="+String.valueOf(client.srcPort & 0xffff)+"," + + "dl_type="+LB_ETHER_TYPE+"," + + "in_port="+String.valueOf(path.get(i).getPortId()); + if (sw == pinSwitch) { - json.put("actions","set-src-ip="+IPv4.fromIPv4Address(vips.get(member.vipId).address)+"," + actionString = "set-src-ip="+IPv4.fromIPv4Address(vips.get(member.vipId).address)+"," + "set-src-mac="+vips.get(member.vipId).proxyMac.toString()+"," - + "output="+path.get(i+1).getPortId()); + + "output="+path.get(i+1).getPortId(); } else { - json.put("actions", - "output="+path.get(i+1).getPortId()); + actionString = "output="+path.get(i+1).getPortId(); } } + + StaticFlowEntries.parseActionString(fm, actionString, log); + + fm.setPriority(U16.t(LB_PRIORITY)); + + OFMatch ofMatch = new OFMatch(); try { - HttpClient httpclient = new DefaultHttpClient(); - HttpPost httpPost = new HttpPost("http://127.0.0.1:8080/wm/staticflowentrypusher/json"); - StringEntity se = new StringEntity(json.toString()); - se.setContentEncoding(new BasicHeader(HTTP.CONTENT_TYPE, "application/json")); - httpPost.setEntity(se); - - HttpResponse response = null; - - try { - response = httpclient.execute(httpPost); - } catch (ClientProtocolException cliente) { - cliente.printStackTrace(); - } catch (IOException ioe) { - ioe.printStackTrace(); - } - - BufferedReader rd = null; - try { - if (response !=null) - rd = new BufferedReader(new InputStreamReader(response.getEntity().getContent())); - } catch (IllegalStateException statee) { - statee.printStackTrace(); - } catch (IOException ioe) { - ioe.printStackTrace(); - } - - String line = ""; - try { - if (rd!= null) { - while ((line = rd.readLine()) != null) { - System.out.println(line); - } - } - } catch (IOException e) { - e.printStackTrace(); - } - } catch (UnsupportedEncodingException e) { - e.printStackTrace(); - } + ofMatch.fromString(matchString); + } catch (IllegalArgumentException e) { + log.debug( + "ignoring flow entry {} on switch {} with illegal OFMatch() key: " + + matchString, entryName, swString); + } + + fm.setMatch(ofMatch); + sfp.addFlow(entryName, fm, swString); + } } - + return; } @@ -775,6 +759,7 @@ public class LoadBalancer implements IFloodlightModule, l.add(IDeviceService.class); l.add(ITopologyService.class); l.add(IRoutingService.class); + l.add(IStaticFlowEntryPusherService.class); return l; } @@ -788,6 +773,7 @@ public class LoadBalancer implements IFloodlightModule, deviceManager = context.getServiceImpl(IDeviceService.class); routingEngine = context.getServiceImpl(IRoutingService.class); topology = context.getServiceImpl(ITopologyService.class); + sfp = context.getServiceImpl(IStaticFlowEntryPusherService.class); messageDamper = new OFMessageDamper(OFMESSAGE_DAMPER_CAPACITY, EnumSet.of(OFType.FLOW_MOD), diff --git a/src/main/java/net/floodlightcontroller/routing/ForwardingBase.java b/src/main/java/net/floodlightcontroller/routing/ForwardingBase.java index 8b498af5c5d11f7b9edc6ab2b816cde076a1ff76..cd0cd36925bea52c881ab497b7f35a93a39b5168 100644 --- a/src/main/java/net/floodlightcontroller/routing/ForwardingBase.java +++ b/src/main/java/net/floodlightcontroller/routing/ForwardingBase.java @@ -336,60 +336,6 @@ public abstract class ForwardingBase "packet out to a switch", recommendation=LogMessageDoc.CHECK_SWITCH) }) - public void pushPacket(IPacket packet, - IOFSwitch sw, - int bufferId, - short inPort, - short outPort, - FloodlightContext cntx, - boolean flush) { - - - if (log.isTraceEnabled()) { - log.trace("PacketOut srcSwitch={} inPort={} outPort={}", - new Object[] {sw, inPort, outPort}); - } - - OFPacketOut po = - (OFPacketOut) floodlightProvider.getOFMessageFactory() - .getMessage(OFType.PACKET_OUT); - - // set actions - List<OFAction> actions = new ArrayList<OFAction>(); - actions.add(new OFActionOutput(outPort, (short) 0xffff)); - - po.setActions(actions) - .setActionsLength((short) OFActionOutput.MINIMUM_LENGTH); - short poLength = - (short) (po.getActionsLength() + OFPacketOut.MINIMUM_LENGTH); - - // set buffer_id, in_port - po.setBufferId(bufferId); - po.setInPort(inPort); - - // set data - only if buffer_id == -1 - if (po.getBufferId() == OFPacketOut.BUFFER_ID_NONE) { - if (packet == null) { - log.error("BufferId is not set and packet data is null. " + - "Cannot send packetOut. " + - "srcSwitch={} inPort={} outPort={}", - new Object[] {sw, inPort, outPort}); - return; - } - byte[] packetData = packet.serialize(); - poLength += packetData.length; - po.setPacketData(packetData); - } - - po.setLength(poLength); - - try { - counterStore.updatePktOutFMCounterStoreLocal(sw, po); - messageDamper.write(sw, po, cntx, flush); - } catch (IOException e) { - log.error("Failure writing packet out", e); - } - } /** * Pushes a packet-out to a switch. The assumption here is that diff --git a/src/main/java/net/floodlightcontroller/staticflowentry/StaticFlowEntryPusher.java b/src/main/java/net/floodlightcontroller/staticflowentry/StaticFlowEntryPusher.java index 4f8ad79aac14af53901b0debe3d7f165f9119428..490c50ecb7d6d971368bc50d319e075d679f7faf 100644 --- a/src/main/java/net/floodlightcontroller/staticflowentry/StaticFlowEntryPusher.java +++ b/src/main/java/net/floodlightcontroller/staticflowentry/StaticFlowEntryPusher.java @@ -5,11 +5,11 @@ import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.Comparator; -import java.util.HashSet; -import java.util.Iterator; import java.util.HashMap; +import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.Map.Entry; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; @@ -29,18 +29,15 @@ import net.floodlightcontroller.core.module.IFloodlightService; import net.floodlightcontroller.core.util.AppCookie; import net.floodlightcontroller.restserver.IRestApiService; import net.floodlightcontroller.staticflowentry.web.StaticFlowEntryWebRoutable; -import net.floodlightcontroller.staticflowentry.IStaticFlowEntryPusherService; import net.floodlightcontroller.storage.IResultSet; -import net.floodlightcontroller.storage.IStorageSourceService; import net.floodlightcontroller.storage.IStorageSourceListener; - +import net.floodlightcontroller.storage.IStorageSourceService; import net.floodlightcontroller.storage.StorageException; import org.openflow.protocol.OFFlowMod; import org.openflow.protocol.OFFlowRemoved; import org.openflow.protocol.OFMatch; import org.openflow.protocol.OFMessage; -import org.openflow.protocol.OFPort; import org.openflow.protocol.OFType; import org.openflow.util.HexString; import org.openflow.util.U16; @@ -653,6 +650,16 @@ public class StaticFlowEntryPusher @Override public void deleteAllFlows() { + for (String entry : entry2dpid.keySet()) { + deleteFlow(entry); + } + + /* + FIXME: Since the OF spec 1.0 is not clear on how + to match on cookies. Once all switches come to a + common implementation we can possibly re-enable this + fix. + // Send a delete for each switch Set<String> swSet = new HashSet<String>(); for (String dpid : entry2dpid.values()) { @@ -673,11 +680,24 @@ public class StaticFlowEntryPusher // Reset our DB storageSource.deleteMatchingRowsAsync(TABLE_NAME, null); + */ } @Override public void deleteFlowsForSwitch(long dpid) { - sendDeleteByCookie(dpid); + String sDpid = HexString.toHexString(dpid); + + for (Entry<String, String> e : entry2dpid.entrySet()) { + if (e.getValue().equals(sDpid)) + deleteFlow(e.getKey()); + } + + /* + FIXME: Since the OF spec 1.0 is not clear on how + to match on cookies. Once all switches come to a + common implementation we can possibly re-enable this + fix. + //sendDeleteByCookie(dpid); String sDpid = HexString.toHexString(dpid); // Clear all internal flows for this switch @@ -692,6 +712,7 @@ public class StaticFlowEntryPusher } else { log.warn("Map of storage entries for switch {} was null", sDpid); } + */ } /** @@ -701,6 +722,11 @@ public class StaticFlowEntryPusher * disable having flow specific cookies. * @param dpid The DPID of the switch to clear all it's flows. */ + /* + FIXME: Since the OF spec 1.0 is not clear on how + to match on cookies. Once all switches come to a + common implementation we can possibly re-enable this + fix. private void sendDeleteByCookie(long dpid) { if (log.isDebugEnabled()) log.debug("Deleting all static flows on switch {}", HexString.toHexString(dpid)); @@ -729,6 +755,7 @@ public class StaticFlowEntryPusher return; } } + */ @Override public Map<String, Map<String, OFFlowMod>> getFlows() { diff --git a/src/main/java/net/floodlightcontroller/topology/TopologyManager.java b/src/main/java/net/floodlightcontroller/topology/TopologyManager.java index 81a497cde444f0cab42a934a9c62eb61ed702291..e0496a4e54530193e2c307540d8f191c26710efb 100644 --- a/src/main/java/net/floodlightcontroller/topology/TopologyManager.java +++ b/src/main/java/net/floodlightcontroller/topology/TopologyManager.java @@ -89,7 +89,7 @@ public class TopologyManager implements /** * set of tunnel links */ - protected Map<NodePortTuple, Set<Link>> tunnelLinks; + protected Set<NodePortTuple> tunnelPorts; protected ILinkDiscoveryService linkDiscovery; protected IThreadPoolService threadPool; @@ -120,6 +120,10 @@ public class TopologyManager implements */ protected boolean dtLinksUpdated; + /** Flag that indicates if tunnel ports were updated or not + */ + protected boolean tunnelPortsUpdated; + protected final int TOPOLOGY_COMPUTE_INTERVAL_MS = 500; /** @@ -152,6 +156,7 @@ public class TopologyManager implements boolean newInstanceFlag; linksUpdated = false; dtLinksUpdated = false; + tunnelPortsUpdated = false; applyUpdates(); newInstanceFlag = createNewInstance(); lastUpdateTime = new Date(); @@ -492,10 +497,9 @@ public class TopologyManager implements @Override public Set<NodePortTuple> getTunnelPorts() { - return tunnelLinks.keySet(); + return tunnelPorts; } - @Override public Set<NodePortTuple> getBlockedPorts() { Set<NodePortTuple> bp; Set<NodePortTuple> blockedPorts = @@ -679,7 +683,7 @@ public class TopologyManager implements switchPortLinks = new HashMap<NodePortTuple, Set<Link>>(); directLinks = new HashMap<NodePortTuple, Set<Link>>(); portBroadcastDomainLinks = new HashMap<NodePortTuple, Set<Link>>(); - tunnelLinks = new HashMap<NodePortTuple, Set<Link>>(); + tunnelPorts = new HashSet<NodePortTuple>(); topologyAware = new ArrayList<ITopologyListener>(); ldUpdates = new LinkedBlockingQueue<LDUpdate>(); appliedUpdates = new ArrayList<LDUpdate>(); @@ -800,6 +804,27 @@ public class TopologyManager implements } } + /** + * Get the set of ports to eliminate for sending out BDDP. The method + * returns all the ports that are suppressed for link discovery on the + * switch. + * packets. + * @param sid + * @return + */ + protected Set<Short> getPortsToEliminateForBDDP(long sid) { + Set<NodePortTuple> suppressedNptList = linkDiscovery.getSuppressLLDPsInfo(); + if (suppressedNptList == null) return null; + + Set<Short> resultPorts = new HashSet<Short>(); + for(NodePortTuple npt: suppressedNptList) { + if (npt.getNodeId() == sid) { + resultPorts.add(npt.getPortId()); + } + } + + return resultPorts; + } /** * The BDDP packets are forwarded out of all the ports out of an @@ -848,6 +873,11 @@ public class TopologyManager implements } } + Set<Short> portsToEliminate = getPortsToEliminateForBDDP(sid); + if (portsToEliminate != null) { + ports.removeAll(portsToEliminate); + } + // remove the incoming switch port if (pinSwitch == sid) { ports.remove(pi.getInPort()); @@ -914,12 +944,28 @@ public class TopologyManager implements } else if (update.getOperation() == UpdateOperation.LINK_REMOVED){ removeLink(update.getSrc(), update.getSrcPort(), update.getDst(), update.getDstPort()); + } else if (update.getOperation() == UpdateOperation.TUNNEL_PORT_ADDED) { + addTunnelPort(update.getSrc(), update.getSrcPort()); + } else if (update.getOperation() == UpdateOperation.TUNNEL_PORT_REMOVED) { + removeTunnelPort(update.getSrc(), update.getSrcPort()); } // Add to the list of applied updates. appliedUpdates.add(update); } } + public void addTunnelPort(long sw, short port) { + NodePortTuple npt = new NodePortTuple(sw, port); + tunnelPorts.add(npt); + tunnelPortsUpdated = true; + } + + public void removeTunnelPort(long sw, short port) { + NodePortTuple npt = new NodePortTuple(sw, port); + tunnelPorts.remove(npt); + tunnelPortsUpdated = true; + } + /** * This function computes a new topology. */ @@ -962,7 +1008,7 @@ public class TopologyManager implements } // Remove all tunnel links. - for(NodePortTuple npt: tunnelLinks.keySet()) { + for(NodePortTuple npt: tunnelPorts) { if (switchPortLinks.get(npt) == null) continue; for(Link link: switchPortLinks.get(npt)) { removeLinkFromStructure(openflowLinks, link); @@ -973,7 +1019,7 @@ public class TopologyManager implements blockedPorts, openflowLinks, broadcastDomainPorts, - tunnelLinks.keySet()); + tunnelPorts); nt.compute(); // We set the instances with and without tunnels to be identical. // If needed, we may compute them differently. @@ -1146,8 +1192,6 @@ public class TopologyManager implements public void addOrUpdateLink(long srcId, short srcPort, long dstId, short dstPort, LinkType type) { - boolean flag1 = false, flag2 = false; - Link link = new Link(srcId, srcPort, dstId, dstPort); addPortToSwitch(srcId, srcPort); addPortToSwitch(dstId, dstPort); @@ -1156,17 +1200,9 @@ public class TopologyManager implements if (type.equals(LinkType.MULTIHOP_LINK)) { addLinkToStructure(portBroadcastDomainLinks, link); - flag1 = removeLinkFromStructure(tunnelLinks, link); - flag2 = removeLinkFromStructure(directLinks, link); - dtLinksUpdated = flag1 || flag2; - } else if (type.equals(LinkType.TUNNEL)) { - addLinkToStructure(tunnelLinks, link); - removeLinkFromStructure(portBroadcastDomainLinks, link); - removeLinkFromStructure(directLinks, link); - dtLinksUpdated = true; + dtLinksUpdated = removeLinkFromStructure(directLinks, link); } else if (type.equals(LinkType.DIRECT_LINK)) { addLinkToStructure(directLinks, link); - removeLinkFromStructure(tunnelLinks, link); removeLinkFromStructure(portBroadcastDomainLinks, link); dtLinksUpdated = true; } @@ -1174,14 +1210,8 @@ public class TopologyManager implements } public void removeLink(Link link) { - boolean flag1 = false, flag2 = false; - - flag1 = removeLinkFromStructure(directLinks, link); - flag2 = removeLinkFromStructure(tunnelLinks, link); - linksUpdated = true; - dtLinksUpdated = flag1 || flag2; - + dtLinksUpdated = removeLinkFromStructure(directLinks, link); removeLinkFromStructure(portBroadcastDomainLinks, link); removeLinkFromStructure(switchPortLinks, link); @@ -1219,9 +1249,9 @@ public class TopologyManager implements public void clear() { switchPorts.clear(); + tunnelPorts.clear(); switchPortLinks.clear(); portBroadcastDomainLinks.clear(); - tunnelLinks.clear(); directLinks.clear(); appliedUpdates.clear(); } @@ -1234,6 +1264,7 @@ public class TopologyManager implements this.clear(); linksUpdated = true; dtLinksUpdated = true; + tunnelPortsUpdated = true; createNewInstance(); lastUpdateTime = new Date(); } diff --git a/src/main/java/org/openflow/util/IProducer.java b/src/main/java/org/openflow/util/IProducer.java new file mode 100644 index 0000000000000000000000000000000000000000..52ae79a52b5dc47af63f71d0aceeb3ee26105727 --- /dev/null +++ b/src/main/java/org/openflow/util/IProducer.java @@ -0,0 +1,9 @@ +package org.openflow.util; + +public interface IProducer { + + public void registerConsumer(Class<?> iface, Object anObj); + + public void deregisterConsumer(Class<?> iface, Object anObj); + +} diff --git a/src/main/java/org/openflow/util/ProducerConsumer.java b/src/main/java/org/openflow/util/ProducerConsumer.java new file mode 100644 index 0000000000000000000000000000000000000000..f2244ef3524483b0a2fc70e8f2ba433efd363c01 --- /dev/null +++ b/src/main/java/org/openflow/util/ProducerConsumer.java @@ -0,0 +1,223 @@ +package org.openflow.util; + +import java.util.HashSet; +import java.util.Hashtable; +import java.util.Map; +import java.util.Set; + +/** + * The following implement a producer/consumer design pattern in which both + * producers and consumers explicitly employ a centralized registration + * mechanism, and java Interfaces are used as contracts.<br> + */ +public class ProducerConsumer { + + /* + * Class variables + */ + protected static ProducerConsumer singleton; + + /* + * Default constructor + */ + protected ProducerConsumer() { + producerMap = new Hashtable<Class<?>, Set<IProducer>>(); + } + + /* + * Instance variables + */ + + // Interface/IProducer map + protected Map<Class<?>, Set<IProducer>> producerMap; + + /* + * Protected methods + */ + + protected void _registerConsumer(Object consumer, Class<?>[] interfaces, + Set<Class<?>> iSet, + Set<Class<?>> iUniqueSet) { + // *...Process all interfaces...*/ + for (Class<?> iface : interfaces) { + + // *...Protect against repeated interfaces...*/ + if (!iUniqueSet.contains(iface)) { + iUniqueSet.add(iface); + + Set<IProducer> producers = producerMap.get(iface); + + if (producers != null) { + for (IProducer producer : producers) + producer.registerConsumer(iface, consumer); + iSet.add(iface); + } + + // *...Recurse...*/ + _registerConsumer(consumer, iface.getInterfaces(), iSet, + iUniqueSet); + } + } + } + + protected void _registerConsumer(Object consumer, Class<?> clazz, + Set<Class<?>> iSet, + Set<Class<?>> iUniqueSet) { + if (clazz != null) { + // *...Process all interfaces...*/ + _registerConsumer(consumer, clazz.getInterfaces(), iSet, + iUniqueSet); + + // *...Recurse the class hierarchy...*/ + _registerConsumer(consumer, clazz.getSuperclass(), iSet, + iUniqueSet); + } + } + + protected int _deregisterConsumer(Object consumer, + Class<?>[] interfaces, + Set<Class<?>> iUniqueSet) { + int count = 0; + + // *...Process all interfaces...*/ + for (Class<?> iface : interfaces) { + + // *...Protect against repeated interfaces...*/ + if (!iUniqueSet.contains(iface)) { + iUniqueSet.add(iface); + + Set<IProducer> producers = producerMap.get(iface); + + if (producers != null) { + for (IProducer producer : producers) + producer.deregisterConsumer(iface, consumer); + + count++; + } + + // *...Recurse...*/ + count += _deregisterConsumer(consumer, + iface.getInterfaces(), + iUniqueSet); + } + } + + return count; + } + + protected int _deregisterConsumer(Object consumer, Class<?> clazz, + Set<Class<?>> iUniqueSet) { + int count = 0; + + if (clazz != null) { + // *...Process all interfaces...*/ + count += _deregisterConsumer(consumer, clazz.getInterfaces(), + iUniqueSet); + + // *...Recurse the class hierarchy...*/ + count += _deregisterConsumer(consumer, clazz.getSuperclass(), + iUniqueSet); + } + + return count; + } + + /* + * Singleton API + */ + + /** + * @return singleton ProducerConsumer + */ + public static synchronized ProducerConsumer getSingleton() { + if (singleton == null) singleton = new ProducerConsumer(); + + return singleton; + } + + /* + * Producer APIs + */ + + /** + * Producer registration + * + * @param producer + * object that implements IProducer + * @param iface + * interface supported by the producer + * @return whether there was a previously registered producer, or true if + * one or more the arguments were invalid + */ + public boolean registerProducer(IProducer producer, Class<?> iface) { + if (producer != null && iface != null && iface.isInterface()) { + Set<IProducer> producers = producerMap.get(iface); + + if (producers == null) { + producers = new HashSet<IProducer>(); + producerMap.put(iface, producers); + } + + return producers.add(producer); + } else + return true; + } + + /** + * Producer deregistration + * + * @param producer + * object that implements IProducer + * @param iface + * interface supported by the producer + * @return whether the interface/producer pair was removed, or false if one + * or more the arguments were invalid + */ + public boolean deregisterProducer(IProducer producer, Class<?> iface) { + if (producer != null && iface != null && iface.isInterface()) { + Set<IProducer> producers = producerMap.get(iface); + + if (producers != null) return producers.remove(producer); + } + + return false; + } + + /* + * Consumer APIs + */ + + /** + * Consumer registration + * + * @param consumer + * object that implements producer-specific interfaces + * @return set of supported interfaces + */ + public Set<Class<?>> registerConsumer(Object consumer) { + Set<Class<?>> iSet = new HashSet<Class<?>>(); + + if (consumer != null) + _registerConsumer(consumer, + consumer.getClass(), iSet, + new HashSet<Class<?>>()); + + return iSet; + } + + /** + * Consumer deregistration + * + * @param consumer + * object to deregister + * @return number of unregistered interfaces + */ + public int deregisterConsumer(Object consumer) { + if (consumer != null) + return _deregisterConsumer(consumer, consumer.getClass(), + new HashSet<Class<?>>()); + else + return 0; + } + +} diff --git a/src/test/java/net/floodlightcontroller/core/internal/RoleChangerTest.java b/src/test/java/net/floodlightcontroller/core/internal/RoleChangerTest.java index cb446b2a9ec19cd46d59620e8b160e5e1ef3f4a7..037e816897b7a080212a89803cadf6485d4da659 100644 --- a/src/test/java/net/floodlightcontroller/core/internal/RoleChangerTest.java +++ b/src/test/java/net/floodlightcontroller/core/internal/RoleChangerTest.java @@ -390,6 +390,19 @@ public class RoleChangerTest { roleChanger.checkFirstPendingRoleRequestXid(sw, xid)); } + @Test + public void testCheckFirstPendingRoleRequestNullSw() { + int xid = 54321; + long cookie = 232323; + Role role = Role.MASTER; + OFSwitchImpl sw = new OFSwitchImpl(); + setupPendingRoleRequest(sw, xid, role, cookie); + // pass null as sw object, which is true during handshake + assertEquals(false, + roleChanger.checkFirstPendingRoleRequestXid(null, xid)); + roleChanger.pendingRequestMap.get(sw).clear(); + } + @Test public void testCheckFirstPendingRoleRequestCookie() { int xid = 54321; diff --git a/src/test/java/net/floodlightcontroller/topology/TopologyInstanceTest.java b/src/test/java/net/floodlightcontroller/topology/TopologyInstanceTest.java index aaeea904f0b9fff519e9a60fd7920c0400d528a9..59f3090457561b8e51eea89ce0006801eed43e73 100644 --- a/src/test/java/net/floodlightcontroller/topology/TopologyInstanceTest.java +++ b/src/test/java/net/floodlightcontroller/topology/TopologyInstanceTest.java @@ -108,6 +108,7 @@ public class TopologyInstanceTest { } TopologyInstance ti = topologyManager.getCurrentInstance(tunnelsEnabled); Set<NodePortTuple> computed = ti.getBroadcastNodePortsInCluster(npt.nodeId); + log.info("computed: {}", computed); if (computed != null) assertTrue(computed.equals(expected)); else if (computed == null) @@ -295,120 +296,6 @@ public class TopologyInstanceTest { verifyExpectedBroadcastPortsInClusters(expectedBroadcastPorts); } - @Test - public void testTunnelLinkDeletion() throws Exception { - - // +-------+ +-------+ - // | | | | - // | 1 1|-------------|1 2 | - // | 2 | | 2 | - // +-------+ +-------+ - // | | - // | | - // +-------+ | - // | 1 | | - // | 3 2|-----------------+ - // | 3 | - // +-------+ - // - // - // +-------+ - // | 1 | - // | 4 2|----------------+ - // | 3 | | - // +-------+ | - // | | - // | | - // +-------+ +-------+ - // | 1 | | 2 | - // | 5 2|-------------|1 6 | - // | | | | - // +-------+ +-------+ - { - int [][] linkArray = { - {1, 1, 2, 1, DIRECT_LINK}, - {2, 1, 1, 1, DIRECT_LINK}, - {1, 2, 3, 1, TUNNEL_LINK}, - {3, 1, 1, 2, TUNNEL_LINK}, - {2, 2, 3, 2, TUNNEL_LINK}, - {3, 2, 2, 2, TUNNEL_LINK}, - - {4, 2, 6, 2, DIRECT_LINK}, - {6, 2, 4, 2, DIRECT_LINK}, - {4, 3, 5, 1, TUNNEL_LINK}, - {5, 1, 4, 3, TUNNEL_LINK}, - {5, 2, 6, 1, TUNNEL_LINK}, - {6, 1, 5, 2, TUNNEL_LINK}, - - }; - - int [][] expectedClusters = { - {1, 2}, - {4, 6}, - }; - int [][][] expectedBroadcastPorts = { - {{1,1}, {2,1}}, - {{4,2}, {6,2}} - }; - - createTopologyFromLinks(linkArray); - topologyManager.createNewInstance(); - verifyClusters(expectedClusters, false); - verifyExpectedBroadcastPortsInClusters(expectedBroadcastPorts, false); - } - - // +-------+ +-------+ - // | | TUNNEL | | - // | 1 1|-------------|1 2 | - // | 2 | | 2 | - // +-------+ +-------+ - // | | - // | | - // +-------+ | - // | 1 | | - // | 3 2|-----------------+ - // | 3 | - // +-------+ - // | - // | TUNNEL - // | - // +-------+ - // | 1 | TUNNEL - // | 4 2|----------------+ - // | 3 | | - // +-------+ | - // | | - // | | - // +-------+ +-------+ - // | 1 | | 2 | - // | 5 2|-------------|1 6 | - // | | | | - // +-------+ +-------+ - - { - int [][] linkArray = { - {3, 3, 4, 1, TUNNEL_LINK}, - {4, 1, 3, 3, TUNNEL_LINK}, - - }; - int [][] expectedClusters = { - {1, 2}, - {4, 6}, - {3}, - {5}, - }; - int [][][] expectedBroadcastPorts = { - {{1,1}, {2,1}}, - {{4,2}, {6,2}} - }; - - createTopologyFromLinks(linkArray); - topologyManager.createNewInstance(); - verifyClusters(expectedClusters, false); - verifyExpectedBroadcastPortsInClusters(expectedBroadcastPorts, false); - } - } - @Test public void testLoopDetectionWithIslands() throws Exception { @@ -440,15 +327,15 @@ public class TopologyInstanceTest { // +-------+ +-------+ { int [][] linkArray = { - {1, 1, 2, 1, TUNNEL_LINK}, - {2, 1, 1, 1, TUNNEL_LINK}, + {1, 1, 2, 1, DIRECT_LINK}, + {2, 1, 1, 1, DIRECT_LINK}, {1, 2, 3, 1, DIRECT_LINK}, {3, 1, 1, 2, DIRECT_LINK}, {2, 2, 3, 2, DIRECT_LINK}, {3, 2, 2, 2, DIRECT_LINK}, - {4, 2, 6, 2, TUNNEL_LINK}, - {6, 2, 4, 2, TUNNEL_LINK}, + {4, 2, 6, 2, DIRECT_LINK}, + {6, 2, 4, 2, DIRECT_LINK}, {4, 3, 5, 1, DIRECT_LINK}, {5, 1, 4, 3, DIRECT_LINK}, {5, 2, 6, 1, DIRECT_LINK}, @@ -461,8 +348,8 @@ public class TopologyInstanceTest { {4, 5, 6} }; int [][][] expectedBroadcastPorts = { - {{1,2}, {3,1}, {2,2}, {3,2}}, - {{4,3}, {5,1}, {5,2}, {6,1}}, + {{1,1}, {2,1}, {1,2}, {3,1}}, + {{4,3}, {5,1}, {4,2}, {6,2}}, }; createTopologyFromLinks(linkArray); @@ -501,17 +388,17 @@ public class TopologyInstanceTest { { int [][] linkArray = { - {3, 3, 4, 1, TUNNEL_LINK}, - {4, 1, 3, 3, TUNNEL_LINK}, + {3, 3, 4, 1, DIRECT_LINK}, + {4, 1, 3, 3, DIRECT_LINK}, }; int [][] expectedClusters = { - {1, 2, 3}, - {4, 5, 6} + {1, 2, 3, 4, 5, 6} }; int [][][] expectedBroadcastPorts = { - {{1,2}, {3,1}, {2,2}, {3,2}}, - {{4,3}, {5,1}, {5,2}, {6,1}}, + {{1,1}, {2,1}, {1,2}, {3,1}, + {3,3}, {4,1}, {4,3}, {5,1}, + {4,2}, {6,2}}, }; createTopologyFromLinks(linkArray); diff --git a/src/test/java/net/floodlightcontroller/topology/TopologyManagerTest.java b/src/test/java/net/floodlightcontroller/topology/TopologyManagerTest.java index 113cecbaea0492d36831d1221ad9c1e904c59891..913bf83a96fa0c6a8613572624da2a8ec1a55fec 100644 --- a/src/test/java/net/floodlightcontroller/topology/TopologyManagerTest.java +++ b/src/test/java/net/floodlightcontroller/topology/TopologyManagerTest.java @@ -50,78 +50,54 @@ public class TopologyManagerTest extends FloodlightTestCase { assertTrue(tm.getPortBroadcastDomainLinks().size()==2); assertTrue(tm.getTunnelPorts().size()==0); - tm.addOrUpdateLink((long)1, (short)3, (long)2, (short)3, ILinkDiscovery.LinkType.TUNNEL); - assertTrue(tm.getSwitchPorts().size() == 2); // for two nodes. - assertTrue(tm.getSwitchPorts().get((long)1).size()==3); - assertTrue(tm.getSwitchPorts().get((long)2).size()==3); - assertTrue(tm.getSwitchPortLinks().size()==6); - assertTrue(tm.getPortBroadcastDomainLinks().size()==2); - assertTrue(tm.getTunnelPorts().size()==2); - tm.removeLink((long)1, (short)2, (long)2, (short)2); - log.info("# of switchports. {}", tm.getSwitchPorts().get((long)1).size()); - assertTrue(tm.getSwitchPorts().get((long)1).size()==2); - assertTrue(tm.getSwitchPorts().get((long)2).size()==2); - assertTrue(tm.getSwitchPorts().size() == 2); // for two nodes. - assertTrue(tm.getSwitchPortLinks().size()==4); - assertTrue(tm.getPortBroadcastDomainLinks().size()==0); - assertTrue(tm.getTunnelPorts().size()==2); - - tm.removeLink((long)1, (short)1, (long)2, (short)1); - assertTrue(tm.getSwitchPorts().size() == 2); // for two nodes. assertTrue(tm.getSwitchPorts().get((long)1).size()==1); assertTrue(tm.getSwitchPorts().get((long)2).size()==1); + assertTrue(tm.getSwitchPorts().size() == 2); assertTrue(tm.getSwitchPortLinks().size()==2); assertTrue(tm.getPortBroadcastDomainLinks().size()==0); - assertTrue(tm.getTunnelPorts().size()==2); - tm.removeLink((long)1, (short)3, (long)2, (short)3); + tm.removeLink((long)1, (short)1, (long)2, (short)1); assertTrue(tm.getSwitchPorts().size() == 0); assertTrue(tm.getSwitchPortLinks().size()==0); assertTrue(tm.getPortBroadcastDomainLinks().size()==0); - assertTrue(tm.getTunnelPorts().size()==0); } @Test public void testBasic2() throws Exception { tm.addOrUpdateLink((long)1, (short)1, (long)2, (short)1, ILinkDiscovery.LinkType.DIRECT_LINK); tm.addOrUpdateLink((long)2, (short)2, (long)3, (short)1, ILinkDiscovery.LinkType.MULTIHOP_LINK); - tm.addOrUpdateLink((long)3, (short)2, (long)1, (short)2, ILinkDiscovery.LinkType.TUNNEL); assertTrue(tm.getSwitchPorts().size() == 3); // for two nodes. - assertTrue(tm.getSwitchPorts().get((long)1).size()==2); + assertTrue(tm.getSwitchPorts().get((long)1).size()==1); assertTrue(tm.getSwitchPorts().get((long)2).size()==2); - assertTrue(tm.getSwitchPorts().get((long)3).size()==2); - assertTrue(tm.getSwitchPortLinks().size()==6); + assertTrue(tm.getSwitchPorts().get((long)3).size()==1); + assertTrue(tm.getSwitchPortLinks().size()==4); assertTrue(tm.getPortBroadcastDomainLinks().size()==2); - assertTrue(tm.getTunnelPorts().size()==2); tm.removeLink((long)1, (short)1, (long)2, (short)1); - assertTrue(tm.getSwitchPorts().size() == 3); // for two nodes. - assertTrue(tm.getSwitchPorts().get((long)1).size()==1); + assertTrue(tm.getSwitchPorts().size() == 2); + assertTrue(tm.getSwitchPorts().get((long)1) == null); assertTrue(tm.getSwitchPorts().get((long)2).size()==1); - assertTrue(tm.getSwitchPorts().get((long)3).size()==2); - assertTrue(tm.getSwitchPortLinks().size()==4); + assertTrue(tm.getSwitchPorts().get((long)3).size()==1); + assertTrue(tm.getSwitchPortLinks().size()==2); assertTrue(tm.getPortBroadcastDomainLinks().size()==2); - assertTrue(tm.getTunnelPorts().size()==2); // nonexistent link // no null pointer exceptions. tm.removeLink((long)3, (short)1, (long)2, (short)2); - assertTrue(tm.getSwitchPorts().size() == 3); // for two nodes. - assertTrue(tm.getSwitchPorts().get((long)1).size()==1); + assertTrue(tm.getSwitchPorts().size() == 2); + assertTrue(tm.getSwitchPorts().get((long)1) == null); assertTrue(tm.getSwitchPorts().get((long)2).size()==1); - assertTrue(tm.getSwitchPorts().get((long)3).size()==2); - assertTrue(tm.getSwitchPortLinks().size()==4); + assertTrue(tm.getSwitchPorts().get((long)3).size()==1); + assertTrue(tm.getSwitchPortLinks().size()==2); assertTrue(tm.getPortBroadcastDomainLinks().size()==2); - assertTrue(tm.getTunnelPorts().size()==2); tm.removeLink((long)3, (short)2, (long)1, (short)2); - assertTrue(tm.getSwitchPorts().size() == 2); // for two nodes. + assertTrue(tm.getSwitchPorts().size() == 2); assertTrue(tm.getSwitchPorts().get((long)1)==null); assertTrue(tm.getSwitchPorts().get((long)2).size()==1); assertTrue(tm.getSwitchPorts().get((long)3).size()==1); assertTrue(tm.getSwitchPortLinks().size()==2); assertTrue(tm.getPortBroadcastDomainLinks().size()==2); - assertTrue(tm.getTunnelPorts().size()==0); tm.removeLink((long)2, (short)2, (long)3, (short)1); assertTrue(tm.getSwitchPorts().size() == 0); // for two nodes. @@ -137,6 +113,6 @@ public class TopologyManagerTest extends FloodlightTestCase { assert(tm.switchPorts.isEmpty()); assert(tm.switchPortLinks.isEmpty()); assert(tm.portBroadcastDomainLinks.isEmpty()); - assert(tm.tunnelLinks.isEmpty()); + assert(tm.tunnelPorts.isEmpty()); } } diff --git a/src/test/java/net/floodlightcontroller/util/OFMessageDamperMockSwitch.java b/src/test/java/net/floodlightcontroller/util/OFMessageDamperMockSwitch.java index 95fc5acedea46df21d8c9b0476dbbc3ee33a7ce3..6fd8e092226b8cebd4988bc0073b4ed9a912d2e6 100644 --- a/src/test/java/net/floodlightcontroller/util/OFMessageDamperMockSwitch.java +++ b/src/test/java/net/floodlightcontroller/util/OFMessageDamperMockSwitch.java @@ -398,4 +398,10 @@ public class OFMessageDamperMockSwitch implements IOFSwitch { return null; } + @Override + public boolean attributeEquals(String name, Object other) { + fail("Unexpected method call"); + return false; + } + } \ No newline at end of file