diff --git a/src/main/java/net/floodlightcontroller/core/OFSwitchBase.java b/src/main/java/net/floodlightcontroller/core/OFSwitchBase.java index 1bef0c9c64c81d286d49435717e69e8e468c3c00..6cdcf712cdfb87732907b1c248c9d547de2e653d 100644 --- a/src/main/java/net/floodlightcontroller/core/OFSwitchBase.java +++ b/src/main/java/net/floodlightcontroller/core/OFSwitchBase.java @@ -1108,11 +1108,16 @@ public abstract class OFSwitchBase implements IOFSwitch { this.role = role; } + @LogMessageDoc(level="INFO", + message="Switch {switch} flow cleared", + explanation="The switch flow table has been cleared, " + + "this normally happens on switch connection") @Override public void clearAllFlowMods() { if (channel == null || !isConnected()) return; // Delete all pre-existing flows + log.info("Clearing all flows on switch {}", this); OFMatch match = new OFMatch().setWildcards(OFMatch.OFPFW_ALL); OFMessage fm = ((OFFlowMod) floodlightProvider.getOFMessageFactory() .getMessage(OFType.FLOW_MOD)) diff --git a/src/main/java/net/floodlightcontroller/core/internal/Controller.java b/src/main/java/net/floodlightcontroller/core/internal/Controller.java index 6bfd413d38665ac9397375c9c6db05929e8bad2e..fd6c35865ebb9b24127509b6375d367aeae0f71b 100644 --- a/src/main/java/net/floodlightcontroller/core/internal/Controller.java +++ b/src/main/java/net/floodlightcontroller/core/internal/Controller.java @@ -95,6 +95,8 @@ import net.floodlightcontroller.threadpool.IThreadPoolService; import net.floodlightcontroller.util.EventHistory; import net.floodlightcontroller.util.LoadMonitor; import net.floodlightcontroller.util.EventHistory.EvAction; +import net.floodlightcontroller.util.TimedCache; + import org.jboss.netty.bootstrap.ServerBootstrap; import org.jboss.netty.channel.ChannelPipelineFactory; import org.jboss.netty.channel.group.ChannelGroup; @@ -191,6 +193,7 @@ public class Controller implements IFloodlightProviderService, // Flag to always flush flow table on switch reconnect (HA or otherwise) private boolean alwaysClearFlowsOnSwActivate = false; + private TimedCache<Long> swConnectCache; // Storage table names protected static final String CONTROLLER_TABLE_NAME = "controller_controller"; @@ -1063,9 +1066,8 @@ public class Controller implements IFloodlightProviderService, // The switch isn't known to the controller cluster. We // need to send a switchAdded notification and clear all // flows. - // TODO: if we switch was recently (seconds) connected we - // might decide to not wipe the flow table. - sw.clearAllFlowMods(); + if (!swConnectCache.update(sw.getId())) + sw.clearAllFlowMods(); addUpdateToQueue(new SwitchUpdate(dpid, SwitchUpdateType.ADDED)); addUpdateToQueue(new SwitchUpdate(dpid, @@ -1074,8 +1076,9 @@ public class Controller implements IFloodlightProviderService, } else { // FIXME: switch was in store. check if ports or anything else // has changed and send update. - if (alwaysClearFlowsOnSwActivate) + if (alwaysClearFlowsOnSwActivate) { sw.clearAllFlowMods(); + } if (sw.attributeEquals(IOFSwitch.SWITCH_SUPPORTS_NX_ROLE, true)) { // We have a stored switch and the newly activated switch // supports roles. This indicates that the switch was @@ -1208,6 +1211,7 @@ public class Controller implements IFloodlightProviderService, return; } log.debug("removeSwitch {}", sw); + swConnectCache.update(sw.getId()); this.activeSwitches.remove(sw.getId()); removeSwitchFromStore(sw.getId()); // We cancel all outstanding statistics replies if the switch transition @@ -2308,6 +2312,8 @@ public class Controller implements IFloodlightProviderService, INITIAL_ROLE_CHANGE_DESCRIPTION); this.switchManager = new SwitchManager(this.notifiedRole); this.counters = new Counters(); + this.swConnectCache = + new TimedCache<Long>(100, 5*1000 ); // 5 seconds interval } /** diff --git a/src/main/java/net/floodlightcontroller/core/internal/OFChannelHandler.java b/src/main/java/net/floodlightcontroller/core/internal/OFChannelHandler.java index efdf5577d43770149771dbe0cb4c4411aeb525d9..fcfd6bc9440ddfd1daa6dac945a924a09ac0b146 100644 --- a/src/main/java/net/floodlightcontroller/core/internal/OFChannelHandler.java +++ b/src/main/java/net/floodlightcontroller/core/internal/OFChannelHandler.java @@ -430,6 +430,12 @@ class OFChannelHandler // need to implement since its abstract but it will never // be called } + + @Override + void processOFPortStatus(OFChannelHandler h, OFPortStatus m) + throws IOException { + unhandledMessageReceived(h, m); + } }, /** @@ -460,6 +466,12 @@ class OFChannelHandler void processOFError(OFChannelHandler h, OFError m) { logErrorDisconnect(h, m); } + + @Override + void processOFPortStatus(OFChannelHandler h, OFPortStatus m) + throws IOException { + unhandledMessageReceived(h, m); + } }, /** @@ -497,6 +509,12 @@ class OFChannelHandler void processOFError(OFChannelHandler h, OFError m) { logErrorDisconnect(h, m); } + + @Override + void processOFPortStatus(OFChannelHandler h, OFPortStatus m) + throws IOException { + unhandledMessageReceived(h, m); + } }, WAIT_SET_L2_TABLE_REPLY(false) { @@ -687,6 +705,12 @@ class OFChannelHandler // TODO: we could re-set the features reply illegalMessageReceived(h, m); } + + @Override + void processOFPortStatus(OFChannelHandler h, OFPortStatus m) + throws IOException { + h.pendingPortStatusMsg.add(m); + } }, WAIT_SWITCH_DRIVER_SUB_HANDSHAKE(false) { @@ -755,6 +779,7 @@ class OFChannelHandler void processOFPortStatus(OFChannelHandler h, OFPortStatus m) throws IOException { handlePortStatusMessage(h, m, false); + } }, @@ -1240,10 +1265,9 @@ class OFChannelHandler unhandledMessageReceived(h, m); } - void processOFPortStatus(OFChannelHandler h, OFPortStatus m) - throws IOException { - unhandledMessageReceived(h, m); - } + // bi default implementation. Every state needs to handle it. + abstract void processOFPortStatus(OFChannelHandler h, OFPortStatus m) + throws IOException; void processOFQueueGetConfigReply(OFChannelHandler h, OFQueueGetConfigReply m) diff --git a/src/main/java/net/floodlightcontroller/firewall/FirewallResource.java b/src/main/java/net/floodlightcontroller/firewall/FirewallResource.java index 2f731db49e1911849745b43982ee9d74edba91d2..03f9baef2c2e07c9876f2aebaa6abaf758aa1539 100644 --- a/src/main/java/net/floodlightcontroller/firewall/FirewallResource.java +++ b/src/main/java/net/floodlightcontroller/firewall/FirewallResource.java @@ -1,14 +1,14 @@ /** * Copyright 2011, Big Switch Networks, Inc. * Originally created by Amer Tahir - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may + * + * 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 + * + * 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 @@ -31,10 +31,10 @@ import org.slf4j.LoggerFactory; public class FirewallResource extends ServerResource { protected static Logger log = LoggerFactory.getLogger(FirewallResource.class); - + @Get("json") public Object handleRequest() { - IFirewallService firewall = + IFirewallService firewall = (IFirewallService)getContext().getAttributes(). get(IFirewallService.class.getCanonicalName()); @@ -52,20 +52,20 @@ public class FirewallResource extends ServerResource { if (op.equalsIgnoreCase("enable")) { firewall.enableFirewall(true); return "{\"status\" : \"success\", \"details\" : \"firewall running\"}"; - } - + } + // REST API disable firewall if (op.equalsIgnoreCase("disable")) { firewall.enableFirewall(false); return "{\"status\" : \"success\", \"details\" : \"firewall stopped\"}"; - } - + } + // REST API retrieving rules from storage // currently equivalent to /wm/firewall/rules/json if (op.equalsIgnoreCase("storageRules")) { return firewall.getStorageRules(); - } - + } + // REST API set local subnet mask -- this only makes sense for one subnet // will remove later if (op.equalsIgnoreCase("subnet-mask")) { @@ -75,7 +75,7 @@ public class FirewallResource extends ServerResource { // no known options found return "{\"status\" : \"failure\", \"details\" : \"invalid operation\"}"; } - + /** * Allows setting of subnet mask * @param fmJson The Subnet Mask in JSON format. @@ -83,7 +83,7 @@ public class FirewallResource extends ServerResource { */ @Post public String handlePost(String fmJson) { - IFirewallService firewall = + IFirewallService firewall = (IFirewallService)getContext().getAttributes(). get(IFirewallService.class.getCanonicalName()); @@ -92,13 +92,12 @@ public class FirewallResource extends ServerResource { newMask = jsonExtractSubnetMask(fmJson); } catch (IOException e) { log.error("Error parsing new subnet mask: " + fmJson, e); - e.printStackTrace(); return "{\"status\" : \"Error! Could not parse new subnet mask, see log for details.\"}"; } firewall.setSubnetMask(newMask); return ("{\"status\" : \"subnet mask set\"}"); } - + /** * Extracts subnet mask from a JSON string * @param fmJson The JSON formatted string @@ -128,7 +127,7 @@ public class FirewallResource extends ServerResource { String n = jp.getCurrentName(); jp.nextToken(); - if (jp.getText().equals("")) + if (jp.getText().equals("")) continue; if (n == "subnet-mask") { diff --git a/src/main/java/net/floodlightcontroller/firewall/FirewallRulesResource.java b/src/main/java/net/floodlightcontroller/firewall/FirewallRulesResource.java index b72f983dd3edafe2a92521f7cdd35afd5494e990..db83c4a21391d1be3183a087a886429da9946873 100644 --- a/src/main/java/net/floodlightcontroller/firewall/FirewallRulesResource.java +++ b/src/main/java/net/floodlightcontroller/firewall/FirewallRulesResource.java @@ -1,14 +1,14 @@ /** * Copyright 2011, Big Switch Networks, Inc. * Originally created by Amer Tahir - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may + * + * 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 + * + * 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 @@ -41,7 +41,7 @@ public class FirewallRulesResource extends ServerResource { @Get("json") public List<FirewallRule> retrieve() { - IFirewallService firewall = + IFirewallService firewall = (IFirewallService)getContext().getAttributes(). get(IFirewallService.class.getCanonicalName()); @@ -56,7 +56,7 @@ public class FirewallRulesResource extends ServerResource { */ @Post public String store(String fmJson) { - IFirewallService firewall = + IFirewallService firewall = (IFirewallService)getContext().getAttributes(). get(IFirewallService.class.getCanonicalName()); @@ -65,7 +65,6 @@ public class FirewallRulesResource extends ServerResource { rule = jsonToFirewallRule(fmJson); } catch (IOException e) { log.error("Error parsing firewall rule: " + fmJson, e); - e.printStackTrace(); return "{\"status\" : \"Error! Could not parse firewall rule, see log for details.\"}"; } String status = null; @@ -86,10 +85,10 @@ public class FirewallRulesResource extends ServerResource { * @param fmJson The Firewall rule entry in JSON format. * @return A string status message */ - + @Delete public String remove(String fmJson) { - IFirewallService firewall = + IFirewallService firewall = (IFirewallService)getContext().getAttributes(). get(IFirewallService.class.getCanonicalName()); @@ -98,7 +97,6 @@ public class FirewallRulesResource extends ServerResource { rule = jsonToFirewallRule(fmJson); } catch (IOException e) { log.error("Error parsing firewall rule: " + fmJson, e); - e.printStackTrace(); return "{\"status\" : \"Error! Could not parse firewall rule, see log for details.\"}"; } String status = null; @@ -128,7 +126,7 @@ public class FirewallRulesResource extends ServerResource { * @return The FirewallRule instance * @throws IOException If there was an error parsing the JSON */ - + public static FirewallRule jsonToFirewallRule(String fmJson) throws IOException { FirewallRule rule = new FirewallRule(); MappingJsonFactory f = new MappingJsonFactory(); @@ -152,47 +150,47 @@ public class FirewallRulesResource extends ServerResource { String n = jp.getCurrentName(); jp.nextToken(); - if (jp.getText().equals("")) + if (jp.getText().equals("")) continue; String tmp; - + // This is currently only applicable for remove(). In store(), ruleid takes a random number if (n == "ruleid") { - rule.ruleid = Integer.parseInt((String)jp.getText()); + rule.ruleid = Integer.parseInt(jp.getText()); } - + // This assumes user having dpid info for involved switches else if (n == "switchid") { tmp = jp.getText(); if (tmp.equalsIgnoreCase("-1") == false) { - // user inputs hex format dpid - rule.dpid = HexString.toLong(tmp); + // user inputs hex format dpid + rule.dpid = HexString.toLong(tmp); rule.wildcard_dpid = false; } - } - + } + else if (n == "src-inport") { rule.in_port = Short.parseShort(jp.getText()); rule.wildcard_in_port = false; - } - + } + else if (n == "src-mac") { tmp = jp.getText(); if (tmp.equalsIgnoreCase("ANY") == false) { rule.wildcard_dl_src = false; rule.dl_src = Ethernet.toLong(Ethernet.toMACAddress(tmp)); } - } - + } + else if (n == "dst-mac") { tmp = jp.getText(); if (tmp.equalsIgnoreCase("ANY") == false) { rule.wildcard_dl_dst = false; rule.dl_dst = Ethernet.toLong(Ethernet.toMACAddress(tmp)); } - } - + } + else if (n == "dl-type") { tmp = jp.getText(); if (tmp.equalsIgnoreCase("ARP")) { @@ -203,8 +201,8 @@ public class FirewallRulesResource extends ServerResource { rule.wildcard_dl_type = false; rule.dl_type = Ethernet.TYPE_IPv4; } - } - + } + else if (n == "src-ip") { tmp = jp.getText(); if (tmp.equalsIgnoreCase("ANY") == false) { @@ -215,8 +213,8 @@ public class FirewallRulesResource extends ServerResource { rule.nw_src_prefix = cidr[0]; rule.nw_src_maskbits = cidr[1]; } - } - + } + else if (n == "dst-ip") { tmp = jp.getText(); if (tmp.equalsIgnoreCase("ANY") == false) { @@ -227,8 +225,8 @@ public class FirewallRulesResource extends ServerResource { rule.nw_dst_prefix = cidr[0]; rule.nw_dst_maskbits = cidr[1]; } - } - + } + else if (n == "nw-proto") { tmp = jp.getText(); if (tmp.equalsIgnoreCase("TCP")) { @@ -246,23 +244,23 @@ public class FirewallRulesResource extends ServerResource { rule.nw_proto = IPv4.PROTOCOL_ICMP; rule.wildcard_dl_type = false; rule.dl_type = Ethernet.TYPE_IPv4; - } - } - + } + } + else if (n == "tp-src") { rule.wildcard_tp_src = false; rule.tp_src = Short.parseShort(jp.getText()); - } - + } + else if (n == "tp-dst") { rule.wildcard_tp_dst = false; rule.tp_dst = Short.parseShort(jp.getText()); - } - + } + else if (n == "priority") { rule.priority = Integer.parseInt(jp.getText()); - } - + } + else if (n == "action") { if (jp.getText().equalsIgnoreCase("allow") == true) { rule.action = FirewallRule.FirewallAction.ALLOW; diff --git a/src/main/java/net/floodlightcontroller/linkdiscovery/internal/LinkDiscoveryManager.java b/src/main/java/net/floodlightcontroller/linkdiscovery/internal/LinkDiscoveryManager.java index 8c64bb5f142384430c2b1a53f7f849be219de6a1..9b3cd7b871af7151a77644f6ff2be6ceab0a61ac 100644 --- a/src/main/java/net/floodlightcontroller/linkdiscovery/internal/LinkDiscoveryManager.java +++ b/src/main/java/net/floodlightcontroller/linkdiscovery/internal/LinkDiscoveryManager.java @@ -20,11 +20,13 @@ package net.floodlightcontroller.linkdiscovery.internal; import java.io.IOException; import java.net.InetAddress; import java.net.NetworkInterface; +import java.net.SocketException; import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; +import java.util.Enumeration; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; @@ -1571,36 +1573,39 @@ public class LinkDiscoveryManager implements IOFMessageListener, //****************** // Internal Helper Methods //****************** - + @LogMessageDoc(level="WARN", + message="Could not get list of interfaces of local machine to " + + "encode in TLV: {detail-msg}", + explanation="Outgoing LLDP packets encode a unique hash to " + + "identify the local machine. The list of network " + + "interfaces is used as input and the controller failed " + + "to query this list", + recommendation=LogMessageDoc.REPORT_CONTROLLER_BUG) protected void setControllerTLV() { // Setting the controllerTLVValue based on current nano time, // controller's IP address, and the network interface object hash // the corresponding IP address. final int prime = 7867; - InetAddress localIPAddress = null; - NetworkInterface localInterface = null; byte[] controllerTLVValue = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 }; // 8 // byte // value. ByteBuffer bb = ByteBuffer.allocate(10); - try { - localIPAddress = java.net.InetAddress.getLocalHost(); - localInterface = NetworkInterface.getByInetAddress(localIPAddress); - } catch (Exception e) { - e.printStackTrace(); - } - long result = System.nanoTime(); - if (localIPAddress != null) - result = result - * prime - + IPv4.toIPv4Address(localIPAddress.getHostAddress()); - if (localInterface != null) - result = result * prime - + localInterface.hashCode(); + try{ + // Use some data specific to the machine this controller is + // running on. In this case: the list of network interfaces + Enumeration<NetworkInterface> ifaces = + NetworkInterface.getNetworkInterfaces(); + if (ifaces != null) { + result = result * prime + ifaces.hashCode(); + } + } catch (SocketException e) { + log.warn("Could not get list of interfaces of local machine to " + + "encode in TLV: {}", e.toString()); + } // set the first 4 bits to 0. result = result & (0x0fffffffffffffffL); diff --git a/src/main/java/net/floodlightcontroller/notification/NotificationManagerFactory.java b/src/main/java/net/floodlightcontroller/notification/NotificationManagerFactory.java index 212c37a41fd24ab4ec0b3d1829f5d9da642d8be0..1e596a9d2638b11fb2eaaeecc207a310460cbf5b 100644 --- a/src/main/java/net/floodlightcontroller/notification/NotificationManagerFactory.java +++ b/src/main/java/net/floodlightcontroller/notification/NotificationManagerFactory.java @@ -37,7 +37,7 @@ public class NotificationManagerFactory { notificationfactoryClassName = System.getProperty(NOTIFICATION_FACTORY_NAME); } catch (SecurityException e) { - e.printStackTrace(); + throw new RuntimeException(e); } if (notificationfactoryClassName != null) { Class<?> nfc; @@ -45,11 +45,11 @@ public class NotificationManagerFactory { nfc = Class.forName(notificationfactoryClassName); factory = (INotificationManagerFactory) nfc.newInstance(); } catch (ClassNotFoundException e) { - e.printStackTrace(); + throw new RuntimeException(e); } catch (InstantiationException e) { - e.printStackTrace(); + throw new RuntimeException(e); } catch (IllegalAccessException e) { - e.printStackTrace(); + throw new RuntimeException(e); } } } diff --git a/src/main/java/net/floodlightcontroller/staticflowentry/web/StaticFlowEntryPusherResource.java b/src/main/java/net/floodlightcontroller/staticflowentry/web/StaticFlowEntryPusherResource.java index 3b750ae35df0b42ba7ddfef67ee11a20891fdcd2..8048fe18390eab52d04e9d12e7eab7c1206277ac 100644 --- a/src/main/java/net/floodlightcontroller/staticflowentry/web/StaticFlowEntryPusherResource.java +++ b/src/main/java/net/floodlightcontroller/staticflowentry/web/StaticFlowEntryPusherResource.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 @@ -41,7 +41,7 @@ import net.floodlightcontroller.storage.IStorageSourceService; @LogMessageCategory("Static Flow Pusher") public class StaticFlowEntryPusherResource extends ServerResource { protected static Logger log = LoggerFactory.getLogger(StaticFlowEntryPusherResource.class); - + /** * Checks to see if the user matches IP information without * checking for the correct ether-type (2048). @@ -64,17 +64,17 @@ public class StaticFlowEntryPusherResource extends ServerResource { } if (type == 2048) matchEther = true; } - - if ((rows.containsKey(StaticFlowEntryPusher.COLUMN_NW_DST) || + + if ((rows.containsKey(StaticFlowEntryPusher.COLUMN_NW_DST) || rows.containsKey(StaticFlowEntryPusher.COLUMN_NW_SRC) || rows.containsKey(StaticFlowEntryPusher.COLUMN_NW_PROTO) || rows.containsKey(StaticFlowEntryPusher.COLUMN_NW_TOS)) && (matchEther == false)) return false; - + return true; } - + /** * Takes a Static Flow Pusher string in JSON format and parses it into * our database schema then pushes it to the database. @@ -90,7 +90,7 @@ public class StaticFlowEntryPusherResource extends ServerResource { IStorageSourceService storageSource = (IStorageSourceService)getContext().getAttributes(). get(IStorageSourceService.class.getCanonicalName()); - + Map<String, Object> rowValues; try { rowValues = StaticFlowEntries.jsonToStorageEntry(fmJson); @@ -107,11 +107,10 @@ public class StaticFlowEntryPusherResource extends ServerResource { return ("{\"status\" : \"" + status + "\"}"); } catch (IOException e) { log.error("Error parsing push flow mod request: " + fmJson, e); - e.printStackTrace(); return "{\"status\" : \"Error! Could not parse flod mod, see log for details.\"}"; } } - + @Delete @LogMessageDoc(level="ERROR", message="Error deleting flow mod request: {request}", @@ -132,10 +131,9 @@ public class StaticFlowEntryPusherResource extends ServerResource { } } catch (IOException e) { log.error("Error deleting flow mod request: " + fmJson, e); - e.printStackTrace(); return "{\"status\" : \"Error deleting entry, see log for details\"}"; } - + storageSource.deleteRowAsync(StaticFlowEntryPusher.TABLE_NAME, fmName); return "{\"status\" : \"Entry " + fmName + " deleted\"}"; } diff --git a/src/main/java/org/openflow/protocol/OFMatchBeanInfo.java b/src/main/java/org/openflow/protocol/OFMatchBeanInfo.java index 16a813f1ee41bff74b02f05bc2decb67b0bee24e..97e14a5592b90062153acd0d77b28168250edb38 100644 --- a/src/main/java/org/openflow/protocol/OFMatchBeanInfo.java +++ b/src/main/java/org/openflow/protocol/OFMatchBeanInfo.java @@ -1,7 +1,7 @@ /** * Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior * 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 @@ -28,12 +28,12 @@ import java.util.List; /** * Extra info for how to treat OFMatch as a JavaBean - * + * * For some (inane!) reason, using chained setters in OFMatch breaks a lot of the JavaBean defaults. - * + * * We don't really use OFMatch as a java bean, but there are a lot of nice XML utils that work for * free if OFMatch follows the java bean paradigm. - * + * * @author Rob Sherwood (rob.sherwood@stanford.edu) * */ @@ -47,23 +47,22 @@ public class OFMatchBeanInfo extends SimpleBeanInfo { String name; for (int i=0; i< fields.length; i++) { int mod = fields[i].getModifiers(); - if(Modifier.isFinal(mod) || // don't expose static or final fields + if(Modifier.isFinal(mod) || // don't expose static or final fields Modifier.isStatic(mod)) continue; - + name = fields[i].getName(); Class<?> type = fields[i].getType(); - + try { - descs.add(new PropertyDescriptor(name, - name2getter(OFMatch.class, name), + descs.add(new PropertyDescriptor(name, + name2getter(OFMatch.class, name), name2setter(OFMatch.class, name, type))); } catch (IntrospectionException e) { - e.printStackTrace(); throw new RuntimeException(e); } } - + return descs.toArray(new PropertyDescriptor[0]); } @@ -74,10 +73,8 @@ public class OFMatchBeanInfo extends SimpleBeanInfo { try { m = c.getMethod(mName, new Class[]{ type}); } catch (SecurityException e) { - e.printStackTrace(); throw new RuntimeException(e); } catch (NoSuchMethodException e) { - e.printStackTrace(); throw new RuntimeException(e); } return m; @@ -89,15 +86,13 @@ public class OFMatchBeanInfo extends SimpleBeanInfo { try { m = c.getMethod(mName, new Class[]{}); } catch (SecurityException e) { - e.printStackTrace(); throw new RuntimeException(e); } catch (NoSuchMethodException e) { - e.printStackTrace(); throw new RuntimeException(e); } return m; } - + private String toLeadingCaps(String s) { char[] array = s.toCharArray(); array[0] = Character.toUpperCase(array[0]); diff --git a/src/test/java/net/floodlightcontroller/core/internal/ControllerTest.java b/src/test/java/net/floodlightcontroller/core/internal/ControllerTest.java index cfb828d37933a4c6c61acdc28dc255558f40bca1..14567fdb0561778317c0a1b02a8664ba04fdf429 100644 --- a/src/test/java/net/floodlightcontroller/core/internal/ControllerTest.java +++ b/src/test/java/net/floodlightcontroller/core/internal/ControllerTest.java @@ -1074,15 +1074,14 @@ public class ControllerTest extends FloodlightTestCase { /** - * Create and activate a new switch with the given dpid, features reply - * and description. If description and/or features reply are null we'll - * allocate the default one + * Create and activate a switch, either completely new or reconnected * The mocked switch instance will be returned. It wil be reset. */ - public IOFSwitch doActivateNewSwitch(long dpid, - OFDescriptionStatistics desc, - OFFeaturesReply featuresReply) - throws Exception { + private IOFSwitch doActivateSwitchInt(long dpid, + OFDescriptionStatistics desc, + OFFeaturesReply featuresReply, + boolean clearFlows) + throws Exception { controller.setAlwaysClearFlowsOnSwActivate(true); IOFSwitch sw = createMock(IOFSwitch.class); @@ -1094,8 +1093,10 @@ public class ControllerTest extends FloodlightTestCase { desc = createOFDescriptionStatistics(); } setupSwitchForAddSwitch(sw, dpid, desc, featuresReply); - sw.clearAllFlowMods(); - expectLastCall().once(); + if (clearFlows) { + sw.clearAllFlowMods(); + expectLastCall().once(); + } replay(sw); controller.switchActivated(sw); @@ -1111,6 +1112,30 @@ public class ControllerTest extends FloodlightTestCase { return sw; } + /** + * Create and activate a new switch with the given dpid, features reply + * and description. If description and/or features reply are null we'll + * allocate the default one + * The mocked switch instance will be returned. It wil be reset. + */ + private IOFSwitch doActivateNewSwitch(long dpid, + OFDescriptionStatistics desc, + OFFeaturesReply featuresReply) + throws Exception { + return doActivateSwitchInt(dpid, desc, featuresReply, true); + } + + /** + * Create and activate a switch that's just been disconnected. + * The mocked switch instance will be returned. It wil be reset. + */ + private IOFSwitch doActivateOldSwitch(long dpid, + OFDescriptionStatistics desc, + OFFeaturesReply featuresReply) + throws Exception { + return doActivateSwitchInt(dpid, desc, featuresReply, false); + } + /** * Create a switch sync representation and add it to the store and @@ -1802,7 +1827,8 @@ public class ControllerTest extends FloodlightTestCase { * Disconnect a switch. normal program flow */ @Test - public void testSwitchDisconnected() throws Exception { + private void doTestSwitchConnectReconnect(boolean reconnect) + throws Exception { IOFSwitch sw = doActivateNewSwitch(1L, null, null); expect(sw.getId()).andReturn(1L).anyTimes(); expect(sw.getStringId()).andReturn(HexString.toHexString(1L)).anyTimes(); @@ -1820,6 +1846,23 @@ public class ControllerTest extends FloodlightTestCase { assertNull(controller.getSwitch(1L)); assertNull(storeClient.getValue(1L)); + if (reconnect) { + controller.removeOFSwitchListener(listener); + sw = doActivateOldSwitch(1L, null, null); + } + } + + @Test + public void testSwitchDisconnected() throws Exception { + doTestSwitchConnectReconnect(false); + } + + /** + * Disconnect a switch and reconnect, verify no clearAllFlowmods() + */ + @Test + public void testSwitchReconnect() throws Exception { + doTestSwitchConnectReconnect(true); } /** diff --git a/src/test/java/net/floodlightcontroller/core/internal/OFChannelHandlerTest.java b/src/test/java/net/floodlightcontroller/core/internal/OFChannelHandlerTest.java index 1e450fb7c2dd8316dc29224ea429b611959f5d1a..ed01868b0035eeae062f8f8f17afa2930a3c5ed2 100644 --- a/src/test/java/net/floodlightcontroller/core/internal/OFChannelHandlerTest.java +++ b/src/test/java/net/floodlightcontroller/core/internal/OFChannelHandlerTest.java @@ -164,7 +164,6 @@ public class OFChannelHandlerTest { /* ensure no exception was thrown */ if (exceptionEventCapture.hasCaptured()) { Throwable ex = exceptionEventCapture.getValue().getCause(); - ex.printStackTrace(); throw new AssertionError("Unexpected exception: " + ex.getClass().getName() + "(" + ex + ")"); } diff --git a/src/test/java/net/floodlightcontroller/core/util/SingletonTaskTest.java b/src/test/java/net/floodlightcontroller/core/util/SingletonTaskTest.java index 8203161d91739b541e99e3202adab2147dcdfd87..fa04b741496d801dfb7c3fe417a61083acab3f93 100644 --- a/src/test/java/net/floodlightcontroller/core/util/SingletonTaskTest.java +++ b/src/test/java/net/floodlightcontroller/core/util/SingletonTaskTest.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 @@ -27,25 +27,26 @@ import org.junit.Test; import net.floodlightcontroller.test.FloodlightTestCase; public class SingletonTaskTest extends FloodlightTestCase { - + public int ran = 0; public int finished = 0; public long time = 0; - + + @Override @Before public void setUp() throws Exception { super.setUp(); - + ran = 0; finished = 0; time = 0; } - + @Test public void testBasic() throws InterruptedException { - ScheduledExecutorService ses = + ScheduledExecutorService ses = Executors.newSingleThreadScheduledExecutor(); - + SingletonTask st1 = new SingletonTask(ses, new Runnable() { @Override public void run() { @@ -55,13 +56,13 @@ public class SingletonTaskTest extends FloodlightTestCase { st1.reschedule(0, null); ses.shutdown(); ses.awaitTermination(5, TimeUnit.SECONDS); - + assertEquals("Check that task ran", 1, ran); } @Test public void testDelay() throws InterruptedException { - ScheduledExecutorService ses = + ScheduledExecutorService ses = Executors.newSingleThreadScheduledExecutor(); SingletonTask st1 = new SingletonTask(ses, new Runnable() { @@ -74,10 +75,10 @@ public class SingletonTaskTest extends FloodlightTestCase { long start = System.nanoTime(); st1.reschedule(10, TimeUnit.MILLISECONDS); assertFalse("Check that task hasn't run yet", ran > 0); - + ses.shutdown(); ses.awaitTermination(5, TimeUnit.SECONDS); - + assertEquals("Check that task ran", 1, ran); assertTrue("Check that time passed appropriately", (time - start) >= TimeUnit.NANOSECONDS.convert(10, TimeUnit.MILLISECONDS)); @@ -85,7 +86,7 @@ public class SingletonTaskTest extends FloodlightTestCase { @Test public void testReschedule() throws InterruptedException { - ScheduledExecutorService ses = + ScheduledExecutorService ses = Executors.newSingleThreadScheduledExecutor(); final Object tc = this; @@ -123,10 +124,10 @@ public class SingletonTaskTest extends FloodlightTestCase { st1.reschedule(20, TimeUnit.MILLISECONDS); Thread.sleep(5); assertFalse("Check that task hasn't run yet", ran > 0); - + ses.shutdown(); ses.awaitTermination(5, TimeUnit.SECONDS); - + assertEquals("Check that task ran only once", 1, ran); assertTrue("Check that time passed appropriately: " + (time - start), (time - start) >= TimeUnit.NANOSECONDS.convert(55, TimeUnit.MILLISECONDS)); @@ -134,7 +135,7 @@ public class SingletonTaskTest extends FloodlightTestCase { @Test public void testConcurrentAddDelay() throws InterruptedException { - ScheduledExecutorService ses = + ScheduledExecutorService ses = Executors.newSingleThreadScheduledExecutor(); final Object tc = this; @@ -155,7 +156,7 @@ public class SingletonTaskTest extends FloodlightTestCase { } } }); - + long start = System.nanoTime(); st1.reschedule(5, TimeUnit.MILLISECONDS); Thread.sleep(20); @@ -173,19 +174,19 @@ public class SingletonTaskTest extends FloodlightTestCase { assertTrue("Check task should run state false", !st1.context.taskShouldRun); assertEquals("Check that task ran exactly twice", 2, ran); assertEquals("Check that task finished exactly twice", 2, finished); - + assertTrue("Check that time passed appropriately: " + (time - start), (time - start) >= TimeUnit.NANOSECONDS.convert(130, TimeUnit.MILLISECONDS)); assertTrue("Check that time passed appropriately: " + (time - start), (time - start) <= TimeUnit.NANOSECONDS.convert(160, TimeUnit.MILLISECONDS)); - + ses.shutdown(); ses.awaitTermination(5, TimeUnit.SECONDS); } @Test public void testConcurrentAddDelay2() throws InterruptedException { - ScheduledExecutorService ses = + ScheduledExecutorService ses = Executors.newSingleThreadScheduledExecutor(); final Object tc = this; @@ -225,12 +226,12 @@ public class SingletonTaskTest extends FloodlightTestCase { assertTrue("Check task should run state false", !st1.context.taskShouldRun); assertEquals("Check that task ran exactly twice", 2, ran); assertEquals("Check that task finished exactly twice", 2, finished); - + assertTrue("Check that time passed appropriately: " + (time - start), (time - start) >= TimeUnit.NANOSECONDS.convert(100, TimeUnit.MILLISECONDS)); assertTrue("Check that time passed appropriately: " + (time - start), (time - start) <= TimeUnit.NANOSECONDS.convert(125, TimeUnit.MILLISECONDS)); - + ses.shutdown(); ses.awaitTermination(5, TimeUnit.SECONDS); } @@ -238,7 +239,7 @@ public class SingletonTaskTest extends FloodlightTestCase { @Test public void testConcurrentAddNoDelay() throws InterruptedException { - ScheduledExecutorService ses = + ScheduledExecutorService ses = Executors.newSingleThreadScheduledExecutor(); final Object tc = this; @@ -260,7 +261,7 @@ public class SingletonTaskTest extends FloodlightTestCase { } } }); - + long start = System.nanoTime(); st1.reschedule(0, null); Thread.sleep(20); @@ -278,12 +279,12 @@ public class SingletonTaskTest extends FloodlightTestCase { assertTrue("Check task should run state false", !st1.context.taskShouldRun); assertEquals("Check that task ran exactly twice", 2, ran); assertEquals("Check that task finished exactly twice", 2, finished); - + assertTrue("Check that time passed appropriately: " + (time - start), (time - start) >= TimeUnit.NANOSECONDS.convert(90, TimeUnit.MILLISECONDS)); assertTrue("Check that time passed appropriately: " + (time - start), (time - start) <= TimeUnit.NANOSECONDS.convert(130, TimeUnit.MILLISECONDS)); - + ses.shutdown(); ses.awaitTermination(5, TimeUnit.SECONDS); } diff --git a/src/test/java/net/floodlightcontroller/debugevent/DebugEventTest.java b/src/test/java/net/floodlightcontroller/debugevent/DebugEventTest.java index 175b3d0d1a040a248dcbfdb2a39673eb6fd96e2a..5fbaba9d47ab0031a5792c822d6721f2314d0efe 100644 --- a/src/test/java/net/floodlightcontroller/debugevent/DebugEventTest.java +++ b/src/test/java/net/floodlightcontroller/debugevent/DebugEventTest.java @@ -25,20 +25,16 @@ public class DebugEventTest extends FloodlightTestCase { @Test - public void testRegisterAndUpdateEvent() { + public void testRegisterAndUpdateEvent() throws Exception { assertEquals(0, debugEvent.currentEvents.size()); IEventUpdater<SwitchyEvent> event1 = null; IEventUpdater<PacketyEvent> event2 = null; - try { - event1 = debugEvent.registerEvent("dbgevtest", "switchevent", - "switchtest", EventType.ALWAYS_LOG, - SwitchyEvent.class, 100); - event2 = debugEvent.registerEvent("dbgevtest", "pktinevent", - "pktintest", EventType.ALWAYS_LOG, - PacketyEvent.class, 100); - } catch (MaxEventsRegistered e) { - e.printStackTrace(); - } + event1 = debugEvent.registerEvent("dbgevtest", "switchevent", + "switchtest", EventType.ALWAYS_LOG, + SwitchyEvent.class, 100); + event2 = debugEvent.registerEvent("dbgevtest", "pktinevent", + "pktintest", EventType.ALWAYS_LOG, + PacketyEvent.class, 100); assertEquals(2, debugEvent.currentEvents.size()); assertTrue(null != debugEvent.moduleEvents.get("dbgevtest"). diff --git a/src/test/java/net/floodlightcontroller/firewall/FirewallTest.java b/src/test/java/net/floodlightcontroller/firewall/FirewallTest.java index 5de211420fb9c5dd2a810eed6e31d942404395ca..e10d320d91a305313151d039240a80b4824616c9 100644 --- a/src/test/java/net/floodlightcontroller/firewall/FirewallTest.java +++ b/src/test/java/net/floodlightcontroller/firewall/FirewallTest.java @@ -1,14 +1,14 @@ /** * Copyright 2011, Big Switch Networks, Inc. * Originally created by Amer Tahir - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may + * + * 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 + * + * 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 @@ -29,7 +29,6 @@ import net.floodlightcontroller.core.FloodlightContext; import net.floodlightcontroller.core.IFloodlightProviderService; import net.floodlightcontroller.core.IOFSwitch; import net.floodlightcontroller.core.module.FloodlightModuleContext; -import net.floodlightcontroller.core.module.FloodlightModuleException; import net.floodlightcontroller.packet.ARP; import net.floodlightcontroller.packet.Data; import net.floodlightcontroller.packet.Ethernet; @@ -55,7 +54,7 @@ import org.openflow.util.HexString; /** * Unit test for stateless firewall implemented as a Google Summer of Code project. - * + * * @author Amer Tahir */ public class FirewallTest extends FloodlightTestCase { @@ -71,6 +70,7 @@ public class FirewallTest extends FloodlightTestCase { private Firewall firewall; public static String TestSwitch1DPID = "00:00:00:00:00:00:00:01"; + @Override @Before public void setUp() throws Exception { super.setUp(); @@ -92,17 +92,13 @@ public class FirewallTest extends FloodlightTestCase { mockFloodlightProvider.setSwitches(switches); FloodlightModuleContext fmc = new FloodlightModuleContext(); - fmc.addService(IFloodlightProviderService.class, + fmc.addService(IFloodlightProviderService.class, mockFloodlightProvider); fmc.addService(IFirewallService.class, firewall); fmc.addService(IStorageSourceService.class, storageService); fmc.addService(IRestApiService.class, restApi); - try { - restApi.init(fmc); - } catch (FloodlightModuleException e) { - e.printStackTrace(); - } + restApi.init(fmc); firewall.init(fmc); firewall.startUp(fmc); @@ -122,7 +118,7 @@ public class FirewallTest extends FloodlightTestCase { .setSourcePort((short) 81) .setDestinationPort((short) 80) .setPayload(new Data(new byte[] {0x01})))); - + // Build a broadcast ARP packet this.broadcastARPPacket = new Ethernet() .setDestinationMACAddress("FF:FF:FF:FF:FF:FF") @@ -141,7 +137,7 @@ public class FirewallTest extends FloodlightTestCase { .setTargetHardwareAddress(Ethernet.toMACAddress("00:00:00:00:00:00")) .setTargetProtocolAddress(IPv4.toIPv4Address("192.168.1.2")) .setPayload(new Data(new byte[] {0x01}))); - + // Build a ARP packet this.ARPReplyPacket = new Ethernet() .setDestinationMACAddress("00:44:33:22:11:00") @@ -160,7 +156,7 @@ public class FirewallTest extends FloodlightTestCase { .setTargetHardwareAddress(Ethernet.toMACAddress("00:44:33:22:11:00")) .setTargetProtocolAddress(IPv4.toIPv4Address("192.168.1.1")) .setPayload(new Data(new byte[] {0x01}))); - + // Build a broadcast IP packet this.broadcastIPPacket = new Ethernet() .setDestinationMACAddress("FF:FF:FF:FF:FF:FF") @@ -221,8 +217,8 @@ public class FirewallTest extends FloodlightTestCase { // Add the packet to the context store IFloodlightProviderService.bcStore. - put(cntx, - IFloodlightProviderService.CONTEXT_PI_PAYLOAD, + put(cntx, + IFloodlightProviderService.CONTEXT_PI_PAYLOAD, (Ethernet)packet); } @@ -241,7 +237,7 @@ public class FirewallTest extends FloodlightTestCase { // no rules to match, so firewall should deny assertEquals(decision.getRoutingAction(), IRoutingDecision.RoutingAction.DROP); } - + @Test public void testReadRulesFromStorage() throws Exception { // add 2 rules first @@ -440,10 +436,10 @@ public class FirewallTest extends FloodlightTestCase { // broadcast-ARP traffic should be allowed IRoutingDecision decision = IRoutingDecision.rtStore.get(cntx, IRoutingDecision.CONTEXT_DECISION); assertEquals(IRoutingDecision.RoutingAction.MULTICAST, decision.getRoutingAction()); - + // clear decision IRoutingDecision.rtStore.remove(cntx, IRoutingDecision.CONTEXT_DECISION); - + // simulate an ARP reply packet-in event this.setPacketIn(ARPReplyPacket); @@ -454,12 +450,12 @@ public class FirewallTest extends FloodlightTestCase { decision = IRoutingDecision.rtStore.get(cntx, IRoutingDecision.CONTEXT_DECISION); assertEquals(decision.getRoutingAction(), IRoutingDecision.RoutingAction.DROP); } - + @Test public void testIPBroadcast() throws Exception { // enable firewall first firewall.enableFirewall(true); - + // set subnet mask for IP broadcast firewall.setSubnetMask("255.255.255.0");