diff --git a/src/main/java/net/floodlightcontroller/core/internal/Controller.java b/src/main/java/net/floodlightcontroller/core/internal/Controller.java index c28a45e1c6e18d93aeac8c9f009e0f9d34ccf385..a5b2a8a0bd940aa63ce3ff74d4e081369d859ea1 100644 --- a/src/main/java/net/floodlightcontroller/core/internal/Controller.java +++ b/src/main/java/net/floodlightcontroller/core/internal/Controller.java @@ -101,13 +101,10 @@ import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; public class Controller implements IFloodlightProviderService, IStorageSourceListener, IInfoProvider { protected static final Logger log = LoggerFactory.getLogger(Controller.class); - protected static final INotificationManager notifier = - NotificationManagerFactory.getNotificationManager(Controller.class); + protected static final INotificationManager notifier = NotificationManagerFactory.getNotificationManager(Controller.class); - static final String ERROR_DATABASE = - "The controller could not communicate with the system database."; - static final String SWITCH_SYNC_STORE_NAME = - Controller.class.getCanonicalName() + ".stateStore"; + static final String ERROR_DATABASE = "The controller could not communicate with the system database."; + static final String SWITCH_SYNC_STORE_NAME = Controller.class.getCanonicalName() + ".stateStore"; protected ConcurrentMap<OFType, ListenerDispatcher<OFType,IOFMessageListener>> messageListeners; @@ -731,8 +728,6 @@ public class Controller implements IFloodlightProviderService, IStorageSourceLis } } - //TODO @Ryan createServerBootStrap() was here. Implemented how/where? - private void setConfigParams(Map<String, String> configParams) throws FloodlightModuleException { String ofPort = configParams.get("openflowPort"); if (!Strings.isNullOrEmpty(ofPort)) { diff --git a/src/main/java/net/floodlightcontroller/firewall/Firewall.java b/src/main/java/net/floodlightcontroller/firewall/Firewall.java index 052fde940a492b2b12c0e283193ff38dbb09c96b..e95a7d4e47b10fd662b414f62ae2c2d61d0cb843 100644 --- a/src/main/java/net/floodlightcontroller/firewall/Firewall.java +++ b/src/main/java/net/floodlightcontroller/firewall/Firewall.java @@ -173,19 +173,15 @@ public class Firewall implements IFirewallService, IOFMessageListener, Map<String, Object> row; // (..., null, null) for no predicate, no ordering - IResultSet resultSet = storageSource.executeQuery(TABLE_NAME, - ColumnNames, null, null); + IResultSet resultSet = storageSource.executeQuery(TABLE_NAME, ColumnNames, null, null); // put retrieved rows into FirewallRules for (Iterator<IResultSet> it = resultSet.iterator(); it.hasNext();) { row = it.next().getRow(); // now, parse row FirewallRule r = new FirewallRule(); - if (!row.containsKey(COLUMN_RULEID) - || !row.containsKey(COLUMN_DPID)) { - logger.error( - "skipping entry with missing required 'ruleid' or 'switchid' entry: {}", - row); + if (!row.containsKey(COLUMN_RULEID) || !row.containsKey(COLUMN_DPID)) { + logger.error( "skipping entry with missing required 'ruleid' or 'switchid' entry: {}", row); return l; } try { @@ -194,140 +190,69 @@ public class Firewall implements IFirewallService, IOFMessageListener, r.dpid = DatapathId.of((String) row.get(COLUMN_DPID)); for (String key : row.keySet()) { - if (row.get(key) == null) + if (row.get(key) == null) { continue; - if (key.equals(COLUMN_RULEID) - || key.equals(COLUMN_DPID) - || key.equals("id")) { + } + if (key.equals(COLUMN_RULEID) || key.equals(COLUMN_DPID) || key.equals("id")) { continue; // already handled - } - - else if (key.equals(COLUMN_IN_PORT)) { - r.in_port = OFPort.of(Integer.parseInt((String) row - .get(COLUMN_IN_PORT))); - } - - else if (key.equals(COLUMN_DL_SRC)) { - r.dl_src = MacAddress.of(Long.parseLong((String) row - .get(COLUMN_DL_SRC))); - } - - else if (key.equals(COLUMN_DL_DST)) { - r.dl_dst = MacAddress.of(Long.parseLong((String) row - .get(COLUMN_DL_DST))); - } - - else if (key.equals(COLUMN_DL_TYPE)) { - r.dl_type = EthType.of(Integer.parseInt((String) row - .get(COLUMN_DL_TYPE))); - } - - else if (key.equals(COLUMN_NW_SRC_PREFIX)) { - r.nw_src_prefix_and_mask = IPv4AddressWithMask.of(Integer.parseInt((String) row - .get(COLUMN_NW_SRC_PREFIX)), r.nw_src_prefix_and_mask.getMask().getInt()); - } - - else if (key.equals(COLUMN_NW_SRC_MASKBITS)) { - r.nw_src_prefix_and_mask = IPv4AddressWithMask.of(r.nw_src_prefix_and_mask.getValue().getInt(), Integer.parseInt((String) row - .get(COLUMN_NW_SRC_MASKBITS))); - } - - else if (key.equals(COLUMN_NW_DST_PREFIX)) { - r.nw_dst_prefix_and_mask = IPv4AddressWithMask.of(Integer.parseInt((String) row - .get(COLUMN_NW_DST_PREFIX)), r.nw_dst_prefix_and_mask.getMask().getInt()); - } - - else if (key.equals(COLUMN_NW_DST_MASKBITS)) { - r.nw_dst_prefix_and_mask = IPv4AddressWithMask.of(r.nw_dst_prefix_and_mask.getValue().getInt(), Integer.parseInt((String) row - .get(COLUMN_NW_DST_MASKBITS))); - } - - else if (key.equals(COLUMN_NW_PROTO)) { - r.nw_proto = IpProtocol.of(Short.parseShort((String) row - .get(COLUMN_NW_PROTO))); - } - - else if (key.equals(COLUMN_TP_SRC)) { - r.tp_src = TransportPort.of(Integer.parseInt((String) row - .get(COLUMN_TP_SRC))); - } - - else if (key.equals(COLUMN_TP_DST)) { - r.tp_dst = TransportPort.of(Integer.parseInt((String) row - .get(COLUMN_TP_DST))); - } - - else if (key.equals(COLUMN_WILDCARD_DPID)) { - r.any_dpid = Boolean.parseBoolean((String) row - .get(COLUMN_WILDCARD_DPID)); - } - - else if (key.equals(COLUMN_WILDCARD_IN_PORT)) { - r.any_in_port = Boolean - .parseBoolean((String) row - .get(COLUMN_WILDCARD_IN_PORT)); - } - - else if (key.equals(COLUMN_WILDCARD_DL_SRC)) { - r.any_dl_src = Boolean - .parseBoolean((String) row - .get(COLUMN_WILDCARD_DL_SRC)); - } - - else if (key.equals(COLUMN_WILDCARD_DL_DST)) { - r.any_dl_dst = Boolean - .parseBoolean((String) row - .get(COLUMN_WILDCARD_DL_DST)); - } - - else if (key.equals(COLUMN_WILDCARD_DL_TYPE)) { - r.any_dl_type = Boolean - .parseBoolean((String) row - .get(COLUMN_WILDCARD_DL_TYPE)); - } - - else if (key.equals(COLUMN_WILDCARD_NW_SRC)) { - r.any_nw_src = Boolean - .parseBoolean((String) row - .get(COLUMN_WILDCARD_NW_SRC)); - } - - else if (key.equals(COLUMN_WILDCARD_NW_DST)) { - r.any_nw_dst = Boolean - .parseBoolean((String) row - .get(COLUMN_WILDCARD_NW_DST)); - } - - else if (key.equals(COLUMN_WILDCARD_NW_PROTO)) { - r.any_nw_proto = Boolean - .parseBoolean((String) row - .get(COLUMN_WILDCARD_NW_PROTO)); - } - - else if (key.equals(COLUMN_PRIORITY)) { - r.priority = Integer.parseInt((String) row - .get(COLUMN_PRIORITY)); - } - - else if (key.equals(COLUMN_ACTION)) { + } else if (key.equals(COLUMN_IN_PORT)) { + r.in_port = OFPort.of(Integer.parseInt((String) row.get(COLUMN_IN_PORT))); + } else if (key.equals(COLUMN_DL_SRC)) { + r.dl_src = MacAddress.of(Long.parseLong((String) row.get(COLUMN_DL_SRC))); + } else if (key.equals(COLUMN_DL_DST)) { + r.dl_dst = MacAddress.of(Long.parseLong((String) row.get(COLUMN_DL_DST))); + } else if (key.equals(COLUMN_DL_TYPE)) { + r.dl_type = EthType.of(Integer.parseInt((String) row.get(COLUMN_DL_TYPE))); + } else if (key.equals(COLUMN_NW_SRC_PREFIX)) { + r.nw_src_prefix_and_mask = IPv4AddressWithMask.of(Integer.parseInt((String) row.get(COLUMN_NW_SRC_PREFIX)), r.nw_src_prefix_and_mask.getMask().getInt()); + } else if (key.equals(COLUMN_NW_SRC_MASKBITS)) { + r.nw_src_prefix_and_mask = IPv4AddressWithMask.of(r.nw_src_prefix_and_mask.getValue().getInt(), Integer.parseInt((String) row.get(COLUMN_NW_SRC_MASKBITS))); + } else if (key.equals(COLUMN_NW_DST_PREFIX)) { + r.nw_dst_prefix_and_mask = IPv4AddressWithMask.of(Integer.parseInt((String) row.get(COLUMN_NW_DST_PREFIX)), r.nw_dst_prefix_and_mask.getMask().getInt()); + } else if (key.equals(COLUMN_NW_DST_MASKBITS)) { + r.nw_dst_prefix_and_mask = IPv4AddressWithMask.of(r.nw_dst_prefix_and_mask.getValue().getInt(), Integer.parseInt((String) row.get(COLUMN_NW_DST_MASKBITS))); + } else if (key.equals(COLUMN_NW_PROTO)) { + r.nw_proto = IpProtocol.of(Short.parseShort((String) row.get(COLUMN_NW_PROTO))); + } else if (key.equals(COLUMN_TP_SRC)) { + r.tp_src = TransportPort.of(Integer.parseInt((String) row.get(COLUMN_TP_SRC))); + } else if (key.equals(COLUMN_TP_DST)) { + r.tp_dst = TransportPort.of(Integer.parseInt((String) row.get(COLUMN_TP_DST))); + } else if (key.equals(COLUMN_WILDCARD_DPID)) { + r.any_dpid = Boolean.parseBoolean((String) row.get(COLUMN_WILDCARD_DPID)); + } else if (key.equals(COLUMN_WILDCARD_IN_PORT)) { + r.any_in_port = Boolean.parseBoolean((String) row.get(COLUMN_WILDCARD_IN_PORT)); + } else if (key.equals(COLUMN_WILDCARD_DL_SRC)) { + r.any_dl_src = Boolean.parseBoolean((String) row.get(COLUMN_WILDCARD_DL_SRC)); + } else if (key.equals(COLUMN_WILDCARD_DL_DST)) { + r.any_dl_dst = Boolean.parseBoolean((String) row.get(COLUMN_WILDCARD_DL_DST)); + } else if (key.equals(COLUMN_WILDCARD_DL_TYPE)) { + r.any_dl_type = Boolean.parseBoolean((String) row.get(COLUMN_WILDCARD_DL_TYPE)); + } else if (key.equals(COLUMN_WILDCARD_NW_SRC)) { + r.any_nw_src = Boolean.parseBoolean((String) row.get(COLUMN_WILDCARD_NW_SRC)); + } else if (key.equals(COLUMN_WILDCARD_NW_DST)) { + r.any_nw_dst = Boolean.parseBoolean((String) row.get(COLUMN_WILDCARD_NW_DST)); + } else if (key.equals(COLUMN_WILDCARD_NW_PROTO)) { + r.any_nw_proto = Boolean.parseBoolean((String) row.get(COLUMN_WILDCARD_NW_PROTO)); + } else if (key.equals(COLUMN_PRIORITY)) { + r.priority = Integer.parseInt((String) row.get(COLUMN_PRIORITY)); + } else if (key.equals(COLUMN_ACTION)) { int tmp = Integer.parseInt((String) row.get(COLUMN_ACTION)); - if (tmp == FirewallRule.FirewallAction.DENY.ordinal()) - r.action = FirewallRule.FirewallAction.DENY; - else if (tmp == FirewallRule.FirewallAction.ALLOW.ordinal()) + if (tmp == FirewallRule.FirewallAction.DROP.ordinal()) { + r.action = FirewallRule.FirewallAction.DROP; + } else if (tmp == FirewallRule.FirewallAction.ALLOW.ordinal()) { r.action = FirewallRule.FirewallAction.ALLOW; - else { + } else { r.action = null; logger.error("action not recognized"); } } } } catch (ClassCastException e) { - logger.error( - "skipping rule {} with bad data : " - + e.getMessage(), r.ruleid); + logger.error("skipping rule {} with bad data : " + e.getMessage(), r.ruleid); } - if (r.action != null) + if (r.action != null) { l.add(r); + } } } catch (StorageException e) { logger.error("failed to access storage: {}", e.getMessage()); @@ -342,10 +267,8 @@ public class Firewall implements IFirewallService, IOFMessageListener, } @Override - public void init(FloodlightModuleContext context) - throws FloodlightModuleException { - floodlightProvider = context - .getServiceImpl(IFloodlightProviderService.class); + public void init(FloodlightModuleContext context) throws FloodlightModuleException { + floodlightProvider = context.getServiceImpl(IFloodlightProviderService.class); storageSource = context.getServiceImpl(IStorageSourceService.class); restApi = context.getServiceImpl(IRestApiService.class); rules = new ArrayList<FirewallRule>(); @@ -371,15 +294,15 @@ public class Firewall implements IFirewallService, IOFMessageListener, @Override public Command receive(IOFSwitch sw, OFMessage msg, FloodlightContext cntx) { - if (!this.enabled) + if (!this.enabled) { return Command.CONTINUE; + } switch (msg.getType()) { case PACKET_IN: IRoutingDecision decision = null; if (cntx != null) { decision = IRoutingDecision.rtStore.get(cntx, IRoutingDecision.CONTEXT_DECISION); - return this.processPacketInMessage(sw, (OFPacketIn) msg, decision, cntx); } break; @@ -409,8 +332,7 @@ public class Firewall implements IFirewallService, IOFMessageListener, ArrayList<Map<String, Object>> l = new ArrayList<Map<String, Object>>(); try { // null1=no predicate, null2=no ordering - IResultSet resultSet = storageSource.executeQuery(TABLE_NAME, - ColumnNames, null, null); + IResultSet resultSet = storageSource.executeQuery(TABLE_NAME, ColumnNames, null, null); for (Iterator<IResultSet> it = resultSet.iterator(); it.hasNext();) { l.add(it.next().getRow()); } @@ -544,7 +466,9 @@ public class Firewall implements IFirewallService, IOFMessageListener, rule = iter.next(); // check if rule matches - if (rule.matchesFlow(sw.getId(), pi.getInPort(), eth, adp) == true) { + // AllowDropPair adp's allow and drop matches will modified with what matches + // TODO @Ryan might need to re-init adp each time (look into later) + if (rule.matchesThisPacket(sw.getId(), pi.getInPort(), eth, adp) == true) { matched_rule = rule; break; } @@ -554,7 +478,7 @@ public class Firewall implements IFirewallService, IOFMessageListener, // make a pair of rule and wildcards, then return it RuleMatchPair rmp = new RuleMatchPair(); rmp.rule = matched_rule; - if (matched_rule == null || matched_rule.action == FirewallRule.FirewallAction.DENY) { + if (matched_rule == null || matched_rule.action == FirewallRule.FirewallAction.DROP) { rmp.match = adp.drop.build(); } else { rmp.match = adp.allow.build(); @@ -577,16 +501,14 @@ public class Firewall implements IFirewallService, IOFMessageListener, } public Command processPacketInMessage(IOFSwitch sw, OFPacketIn pi, IRoutingDecision decision, FloodlightContext cntx) { - Ethernet eth = IFloodlightProviderService.bcStore.get(cntx, - IFloodlightProviderService.CONTEXT_PI_PAYLOAD); + Ethernet eth = IFloodlightProviderService.bcStore.get(cntx, IFloodlightProviderService.CONTEXT_PI_PAYLOAD); // Allowing L2 broadcast + ARP broadcast request (also deny malformed // broadcasts -> L2 broadcast + L3 unicast) if (eth.isBroadcast() == true) { boolean allowBroadcast = true; // the case to determine if we have L2 broadcast + L3 unicast - // don't allow this broadcast packet if such is the case (malformed - // packet) + // don't allow this broadcast packet if such is the case (malformed packet) if ((eth.getPayload() instanceof IPv4) && (((IPv4) eth.getPayload()).getDestinationAddress().isBroadcast() == false)) { allowBroadcast = false; } @@ -622,13 +544,14 @@ public class Firewall implements IFirewallService, IOFMessageListener, * decision.addToContext(cntx); return Command.CONTINUE; } */ - // check if we have a matching rule for this packet/flow - // and no decision is taken yet + // check if we have a matching rule for this packet/flow and no decision has been made yet if (decision == null) { + // check if the packet we received matches an existing rule RuleMatchPair rmp = this.matchWithRule(sw, pi, cntx); FirewallRule rule = rmp.rule; - if (rule == null || rule.action == FirewallRule.FirewallAction.DENY) { + // Drop the packet if we don't have a rule allowing or dropping it or if we explicitly drop it + if (rule == null || rule.action == FirewallRule.FirewallAction.DROP) { decision = new RoutingDecision(sw.getId(), pi.getInPort(), IDeviceService.fcStore.get(cntx, IDeviceService.CONTEXT_SRC_DEVICE), IRoutingDecision.RoutingAction.DROP); @@ -637,19 +560,20 @@ public class Firewall implements IFirewallService, IOFMessageListener, if (logger.isTraceEnabled()) { if (rule == null) { logger.trace("No firewall rule found for PacketIn={}, blocking flow", pi); - } else if (rule.action == FirewallRule.FirewallAction.DENY) { + } else if (rule.action == FirewallRule.FirewallAction.DROP) { logger.trace("Deny rule={} match for PacketIn={}", rule, pi); } } + // Found a rule and the rule is not a drop, so allow the packet } else { decision = new RoutingDecision(sw.getId(), pi.getInPort(), IDeviceService.fcStore.get(cntx, IDeviceService.CONTEXT_SRC_DEVICE), IRoutingDecision.RoutingAction.FORWARD_OR_FLOOD); decision.setMatch(rmp.match); decision.addToContext(cntx); - if (logger.isTraceEnabled()) - logger.trace("Allow rule={} match for PacketIn={}", rule, - pi); + if (logger.isTraceEnabled()) { + logger.trace("Allow rule={} match for PacketIn={}", rule, pi); + } } } diff --git a/src/main/java/net/floodlightcontroller/firewall/FirewallRule.java b/src/main/java/net/floodlightcontroller/firewall/FirewallRule.java index c5110ad74bd15fc4fb61f76fdc6c3f20303f3bd6..fb99e5612ba921f3dcff4628eea88d142e777e54 100644 --- a/src/main/java/net/floodlightcontroller/firewall/FirewallRule.java +++ b/src/main/java/net/floodlightcontroller/firewall/FirewallRule.java @@ -50,6 +50,10 @@ public class FirewallRule implements Comparable<FirewallRule> { public TransportPort tp_src; public TransportPort tp_dst; + /* Specify whether or not a match field is relevant. + * true = anything goes; don't care what it is + * false = field must match (w or w/o mask depending on field) + */ public boolean any_dpid; public boolean any_in_port; public boolean any_dl_src; @@ -67,10 +71,10 @@ public class FirewallRule implements Comparable<FirewallRule> { public enum FirewallAction { /* - * DENY: Deny rule + * DROP: Drop rule * ALLOW: Allow rule */ - DENY, ALLOW + DROP, ALLOW } /** @@ -167,7 +171,7 @@ public class FirewallRule implements Comparable<FirewallRule> { } /** - * Matches this rule to a given flow - incoming packet + * Checks if this rule is a match for the incoming packet's MatchFields * * @param switchDpid * the Id of the connected switch @@ -176,12 +180,12 @@ public class FirewallRule implements Comparable<FirewallRule> { * @param packet * the Ethernet packet that arrives at the switch * @param allow-drop-pair - * the pair of matches (allow and deny) given by Firewall + * the pair of matches (allow and drop) given by the Firewall * module that is used by the Firewall module's matchWithRule * method to derive the match object for the decision to be taken * @return true if the rule matches the given packet-in, false otherwise */ - public boolean matchesFlow(DatapathId switchDpid, OFPort inPort, Ethernet packet, AllowDropPair adp) { + public boolean matchesThisPacket(DatapathId switchDpid, OFPort inPort, Ethernet packet, AllowDropPair adp) { IPacket pkt = packet.getPayload(); // dl_type type @@ -202,7 +206,7 @@ public class FirewallRule implements Comparable<FirewallRule> { // in_port matches? if (any_in_port == false && !in_port.equals(inPort)) return false; - if (action == FirewallRule.FirewallAction.DENY) { + if (action == FirewallRule.FirewallAction.DROP) { //wildcards.drop &= ~OFMatch.OFPFW_IN_PORT; adp.drop.setExact(MatchField.IN_PORT, this.in_port); } else { @@ -213,7 +217,7 @@ public class FirewallRule implements Comparable<FirewallRule> { // mac address (src and dst) match? if (any_dl_src == false && !dl_src.equals(packet.getSourceMAC())) return false; - if (action == FirewallRule.FirewallAction.DENY) { + if (action == FirewallRule.FirewallAction.DROP) { //wildcards.drop &= ~OFMatch.OFPFW_DL_SRC; adp.drop.setExact(MatchField.ETH_SRC, this.dl_src); } else { @@ -223,7 +227,7 @@ public class FirewallRule implements Comparable<FirewallRule> { if (any_dl_dst == false && !dl_dst.equals(packet.getDestinationMAC())) return false; - if (action == FirewallRule.FirewallAction.DENY) { + if (action == FirewallRule.FirewallAction.DROP) { //wildcards.drop &= ~OFMatch.OFPFW_DL_DST; adp.drop.setExact(MatchField.ETH_DST, this.dl_dst); } else { @@ -240,7 +244,7 @@ public class FirewallRule implements Comparable<FirewallRule> { if (packet.getEtherType() != EthType.ARP.getValue()) return false; else { - if (action == FirewallRule.FirewallAction.DENY) { + if (action == FirewallRule.FirewallAction.DROP) { //wildcards.drop &= ~OFMatch.OFPFW_DL_TYPE; adp.drop.setExact(MatchField.ETH_TYPE, this.dl_type); } else { @@ -252,7 +256,7 @@ public class FirewallRule implements Comparable<FirewallRule> { if (packet.getEtherType() != EthType.IPv4.getValue()) return false; else { - if (action == FirewallRule.FirewallAction.DENY) { + if (action == FirewallRule.FirewallAction.DROP) { //wildcards.drop &= ~OFMatch.OFPFW_NW_PROTO; adp.drop.setExact(MatchField.IP_PROTO, this.nw_proto); } else { @@ -265,7 +269,7 @@ public class FirewallRule implements Comparable<FirewallRule> { // IP addresses (src and dst) match? if (any_nw_src == false && this.matchIPAddress(nw_src_prefix_and_mask.getValue().getInt(), nw_src_prefix_and_mask.getMask().getInt(), pkt_ip.getSourceAddress()) == false) return false; - if (action == FirewallRule.FirewallAction.DENY) { + if (action == FirewallRule.FirewallAction.DROP) { //wildcards.drop &= ~OFMatch.OFPFW_NW_SRC_ALL; //wildcards.drop |= (nw_src_maskbits << OFMatch.OFPFW_NW_SRC_SHIFT); adp.drop.setMasked(MatchField.IPV4_SRC, nw_src_prefix_and_mask); @@ -277,7 +281,7 @@ public class FirewallRule implements Comparable<FirewallRule> { if (any_nw_dst == false && this.matchIPAddress(nw_dst_prefix_and_mask.getValue().getInt(), nw_dst_prefix_and_mask.getMask().getInt(), pkt_ip.getDestinationAddress()) == false) return false; - if (action == FirewallRule.FirewallAction.DENY) { + if (action == FirewallRule.FirewallAction.DROP) { //wildcards.drop &= ~OFMatch.OFPFW_NW_DST_ALL; //wildcards.drop |= (nw_dst_maskbits << OFMatch.OFPFW_NW_DST_SHIFT); adp.drop.setMasked(MatchField.IPV4_DST, nw_dst_prefix_and_mask); @@ -312,7 +316,7 @@ public class FirewallRule implements Comparable<FirewallRule> { // nothing more needed for ICMP } } - if (action == FirewallRule.FirewallAction.DENY) { + if (action == FirewallRule.FirewallAction.DROP) { //wildcards.drop &= ~OFMatch.OFPFW_NW_PROTO; adp.drop.setExact(MatchField.IP_PROTO, this.nw_proto); } else { @@ -326,7 +330,7 @@ public class FirewallRule implements Comparable<FirewallRule> { if (tp_src.getPort() != 0 && tp_src.getPort() != pkt_tp_src.getPort()) { return false; } - if (action == FirewallRule.FirewallAction.DENY) { + if (action == FirewallRule.FirewallAction.DROP) { //wildcards.drop &= ~OFMatch.OFPFW_TP_SRC; if (pkt_tcp != null) { adp.drop.setExact(MatchField.TCP_SRC, this.tp_src); @@ -346,7 +350,7 @@ public class FirewallRule implements Comparable<FirewallRule> { if (tp_dst.getPort() != 0 && tp_dst.getPort() != pkt_tp_dst.getPort()) { return false; } - if (action == FirewallRule.FirewallAction.DENY) { + if (action == FirewallRule.FirewallAction.DROP) { //wildcards.drop &= ~OFMatch.OFPFW_TP_DST; if (pkt_tcp != null) { adp.drop.setExact(MatchField.TCP_DST, this.tp_dst); @@ -370,7 +374,7 @@ public class FirewallRule implements Comparable<FirewallRule> { return false; } } - if (action == FirewallRule.FirewallAction.DENY) { + if (action == FirewallRule.FirewallAction.DROP) { //wildcards.drop &= ~OFMatch.OFPFW_DL_TYPE; adp.drop.setExact(MatchField.ETH_TYPE, this.dl_type); } else { diff --git a/src/main/java/net/floodlightcontroller/firewall/FirewallRulesResource.java b/src/main/java/net/floodlightcontroller/firewall/FirewallRulesResource.java index b1b870907914b0a088321c5c8718a7de3116835a..90c3d13a2d24f9aa128c8480852dd3a15d4baf77 100644 --- a/src/main/java/net/floodlightcontroller/firewall/FirewallRulesResource.java +++ b/src/main/java/net/floodlightcontroller/firewall/FirewallRulesResource.java @@ -268,7 +268,7 @@ public class FirewallRulesResource extends ServerResource { if (jp.getText().equalsIgnoreCase("allow") == true) { rule.action = FirewallRule.FirewallAction.ALLOW; } else if (jp.getText().equalsIgnoreCase("deny") == true) { - rule.action = FirewallRule.FirewallAction.DENY; + rule.action = FirewallRule.FirewallAction.DROP; } } } diff --git a/src/main/java/net/floodlightcontroller/forwarding/Forwarding.java b/src/main/java/net/floodlightcontroller/forwarding/Forwarding.java index 64a663da22a03522a2b15cbbd1571b28c8f4764a..093b9e7d514805ab5db4573e1fbacc0121fdb9a1 100644 --- a/src/main/java/net/floodlightcontroller/forwarding/Forwarding.java +++ b/src/main/java/net/floodlightcontroller/forwarding/Forwarding.java @@ -1,19 +1,19 @@ /** -* 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. -**/ + * 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.forwarding; @@ -45,375 +45,378 @@ import net.floodlightcontroller.routing.IRoutingDecision; import net.floodlightcontroller.routing.IRoutingService; import net.floodlightcontroller.routing.Route; import net.floodlightcontroller.topology.ITopologyService; +import net.floodlightcontroller.util.MatchMaskUtils; import org.projectfloodlight.openflow.protocol.OFFlowMod; import org.projectfloodlight.openflow.protocol.match.Match; +import org.projectfloodlight.openflow.protocol.OFFlowModCommand; import org.projectfloodlight.openflow.protocol.OFPacketIn; import org.projectfloodlight.openflow.protocol.OFPacketOut; +import org.projectfloodlight.openflow.types.DatapathId; +import org.projectfloodlight.openflow.types.OFBufferId; import org.projectfloodlight.openflow.types.OFPort; -import org.projectfloodlight.openflow.protocol.OFType; +import org.projectfloodlight.openflow.types.U64; import org.projectfloodlight.openflow.protocol.action.OFAction; -import org.projectfloodlight.openflow.protocol.action.OFActionOutput; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @LogMessageCategory("Flow Programming") public class Forwarding extends ForwardingBase implements IFloodlightModule { - protected static Logger log = LoggerFactory.getLogger(Forwarding.class); - - @Override - @LogMessageDoc(level="ERROR", - message="Unexpected decision made for this packet-in={}", - explanation="An unsupported PacketIn decision has been " + - "passed to the flow programming component", - recommendation=LogMessageDoc.REPORT_CONTROLLER_BUG) - public Command processPacketInMessage(IOFSwitch sw, OFPacketIn pi, IRoutingDecision decision, FloodlightContext cntx) { - Ethernet eth = IFloodlightProviderService.bcStore.get(cntx, IFloodlightProviderService.CONTEXT_PI_PAYLOAD); - - // If a decision has been made we obey it - // otherwise we just forward - if (decision != null) { - if (log.isTraceEnabled()) { - log.trace("Forwaring decision={} was made for PacketIn={}", decision.getRoutingAction().toString(), pi); - } - - switch(decision.getRoutingAction()) { - case NONE: - // don't do anything - return Command.CONTINUE; - case FORWARD_OR_FLOOD: - case FORWARD: - doForwardFlow(sw, pi, cntx, false); - return Command.CONTINUE; - case MULTICAST: - // treat as broadcast - doFlood(sw, pi, cntx); - return Command.CONTINUE; - case DROP: - doDropFlow(sw, pi, decision, cntx); - return Command.CONTINUE; - default: - log.error("Unexpected decision made for this packet-in={}", pi, decision.getRoutingAction()); - return Command.CONTINUE; - } - } else { - if (log.isTraceEnabled()) { - log.trace("No decision was made for PacketIn={}, forwarding", pi); - } - - if (eth.isBroadcast() || eth.isMulticast()) { - // For now we treat multicast as broadcast - doFlood(sw, pi, cntx); - } else { - doForwardFlow(sw, pi, cntx, false); - } - } - - return Command.CONTINUE; - } - - @LogMessageDoc(level="ERROR", - message="Failure writing drop flow mod", - explanation="An I/O error occured while trying to write a " + - "drop flow mod to a switch", - recommendation=LogMessageDoc.CHECK_SWITCH) - protected void doDropFlow(IOFSwitch sw, OFPacketIn pi, IRoutingDecision decision, FloodlightContext cntx) { - // initialize match structure and populate it based on the packet in's match - Match.Builder mb = pi.getMatch().createBuilder(); - Match m = null; - if (decision.getMatch() != null) { - m = decision.getMatch(); - } - - // Create flow-mod based on packet-in and src-switch - OFFlowMod fm = - (OFFlowMod) floodlightProvider.getOFMessageFactory() - .getMessage(OFType.FLOW_MOD); - List<OFAction> actions = new ArrayList<OFAction>(); // Set no action to - // drop - long cookie = AppCookie.makeCookie(FORWARDING_APP_ID, 0); - - fm.setCookie(cookie) - .setHardTimeout((short) 0) - .setIdleTimeout((short) 5) - .setBufferId(OFPacketOut.BUFFER_ID_NONE) - .setMatch(match) - .setActions(actions) - .setLengthU(OFFlowMod.MINIMUM_LENGTH); // +OFActionOutput.MINIMUM_LENGTH); - - try { - if (log.isDebugEnabled()) { - log.debug("write drop flow-mod sw={} match={} flow-mod={}", - new Object[] { sw, match, fm }); - } - messageDamper.write(sw, fm, cntx); - } catch (IOException e) { - log.error("Failure writing drop flow mod", e); - } - } - - protected void doForwardFlow(IOFSwitch sw, OFPacketIn pi, - FloodlightContext cntx, - boolean requestFlowRemovedNotifn) { - OFMatch match = new OFMatch(); - match.loadFromPacket(pi.getPacketData(), pi.getInPort()); - - // Check if we have the location of the destination - IDevice dstDevice = - IDeviceService.fcStore. - get(cntx, IDeviceService.CONTEXT_DST_DEVICE); - - if (dstDevice != null) { - IDevice srcDevice = - IDeviceService.fcStore. - get(cntx, IDeviceService.CONTEXT_SRC_DEVICE); - Long srcIsland = topology.getL2DomainId(sw.getId()); - - if (srcDevice == null) { - log.debug("No device entry found for source device"); - return; - } - if (srcIsland == null) { - log.debug("No openflow island found for source {}/{}", - sw.getStringId(), pi.getInPort()); - return; - } - - // Validate that we have a destination known on the same island - // Validate that the source and destination are not on the same switchport - boolean on_same_island = false; - boolean on_same_if = false; - for (SwitchPort dstDap : dstDevice.getAttachmentPoints()) { - long dstSwDpid = dstDap.getSwitchDPID(); - Long dstIsland = topology.getL2DomainId(dstSwDpid); - if ((dstIsland != null) && dstIsland.equals(srcIsland)) { - on_same_island = true; - if ((sw.getId() == dstSwDpid) && - (pi.getInPort() == dstDap.getPort())) { - on_same_if = true; - } - break; - } - } - - if (!on_same_island) { - // Flood since we don't know the dst device - if (log.isTraceEnabled()) { - log.trace("No first hop island found for destination " + - "device {}, Action = flooding", dstDevice); - } - doFlood(sw, pi, cntx); - return; - } - - if (on_same_if) { - if (log.isTraceEnabled()) { - log.trace("Both source and destination are on the same " + - "switch/port {}/{}, Action = NOP", - sw.toString(), pi.getInPort()); - } - return; - } - - // Install all the routes where both src and dst have attachment - // points. Since the lists are stored in sorted order we can - // traverse the attachment points in O(m+n) time - SwitchPort[] srcDaps = srcDevice.getAttachmentPoints(); - Arrays.sort(srcDaps, clusterIdComparator); - SwitchPort[] dstDaps = dstDevice.getAttachmentPoints(); - Arrays.sort(dstDaps, clusterIdComparator); - - int iSrcDaps = 0, iDstDaps = 0; - - while ((iSrcDaps < srcDaps.length) && (iDstDaps < dstDaps.length)) { - SwitchPort srcDap = srcDaps[iSrcDaps]; - SwitchPort dstDap = dstDaps[iDstDaps]; - - // srcCluster and dstCluster here cannot be null as - // every switch will be at least in its own L2 domain. - Long srcCluster = - topology.getL2DomainId(srcDap.getSwitchDPID()); - Long dstCluster = - topology.getL2DomainId(dstDap.getSwitchDPID()); - - int srcVsDest = srcCluster.compareTo(dstCluster); - if (srcVsDest == 0) { - if (!srcDap.equals(dstDap)) { - Route route = - routingEngine.getRoute(srcDap.getSwitchDPID(), - (short)srcDap.getPort(), - dstDap.getSwitchDPID(), - (short)dstDap.getPort(), 0); //cookie = 0, i.e., default route - if (route != null) { - if (log.isTraceEnabled()) { - log.trace("pushRoute match={} route={} " + - "destination={}:{}", - new Object[] {match, route, - dstDap.getSwitchDPID(), - dstDap.getPort()}); - } - long cookie = - AppCookie.makeCookie(FORWARDING_APP_ID, 0); - - // if there is prior routing decision use wildcard - Integer wildcard_hints = null; - IRoutingDecision decision = null; - if (cntx != null) { - decision = IRoutingDecision.rtStore - .get(cntx, - IRoutingDecision.CONTEXT_DECISION); - } - if (decision != null) { - wildcard_hints = decision.getWildcards(); - } else { - // L2 only wildcard if there is no prior route decision - wildcard_hints = ((Integer) sw - .getAttribute(IOFSwitch.PROP_FASTWILDCARDS)) - .intValue() - & ~OFMatch.OFPFW_IN_PORT - & ~OFMatch.OFPFW_DL_VLAN - & ~OFMatch.OFPFW_DL_SRC - & ~OFMatch.OFPFW_DL_DST - & ~OFMatch.OFPFW_NW_SRC_MASK - & ~OFMatch.OFPFW_NW_DST_MASK; - } - - pushRoute(route, match, wildcard_hints, pi, sw.getId(), cookie, - cntx, requestFlowRemovedNotifn, false, - OFFlowMod.OFPFC_ADD); - } - } - iSrcDaps++; - iDstDaps++; - } else if (srcVsDest < 0) { - iSrcDaps++; - } else { - iDstDaps++; - } - } - } else { - // Flood since we don't know the dst device - doFlood(sw, pi, cntx); - } - } - - /** - * Creates a OFPacketOut with the OFPacketIn data that is flooded on all ports unless - * the port is blocked, in which case the packet will be dropped. - * @param sw The switch that receives the OFPacketIn - * @param pi The OFPacketIn that came to the switch - * @param cntx The FloodlightContext associated with this OFPacketIn - */ - @LogMessageDoc(level="ERROR", - message="Failure writing PacketOut " + - "switch={switch} packet-in={packet-in} " + - "packet-out={packet-out}", - explanation="An I/O error occured while writing a packet " + - "out message to the switch", - recommendation=LogMessageDoc.CHECK_SWITCH) - protected void doFlood(IOFSwitch sw, OFPacketIn pi, FloodlightContext cntx) { - if (topologyService.isIncomingBroadcastAllowed(sw.getId(), - pi.getInPort()) == false) { - if (log.isTraceEnabled()) { - log.trace("doFlood, drop broadcast packet, pi={}, " + - "from a blocked port, srcSwitch=[{},{}], linkInfo={}", - new Object[] {pi, sw.getId(),pi.getInPort()}); - } - return; - } - - // Set Action to flood - OFPacketOut po = - (OFPacketOut) floodlightProvider.getOFMessageFactory().getMessage(OFType.PACKET_OUT); - List<OFAction> actions = new ArrayList<OFAction>(); - if (sw.hasAttribute(IOFSwitch.PROP_SUPPORTS_OFPP_FLOOD)) { - actions.add(new OFActionOutput(OFPort.OFPP_FLOOD.getValue(), - (short)0xFFFF)); - } else { - actions.add(new OFActionOutput(OFPort.OFPP_ALL.getValue(), - (short)0xFFFF)); - } - po.setActions(actions); - po.setActionsLength((short) OFActionOutput.MINIMUM_LENGTH); - - // set buffer-id, in-port and packet-data based on packet-in - short poLength = (short)(po.getActionsLength() + OFPacketOut.MINIMUM_LENGTH); - po.setBufferId(OFPacketOut.BUFFER_ID_NONE); - po.setInPort(pi.getInPort()); - byte[] packetData = pi.getPacketData(); - poLength += packetData.length; - po.setPacketData(packetData); - po.setLength(poLength); - - try { - if (log.isTraceEnabled()) { - log.trace("Writing flood PacketOut switch={} packet-in={} packet-out={}", - new Object[] {sw, pi, po}); - } - messageDamper.write(sw, po, cntx); - } catch (IOException e) { - log.error("Failure writing PacketOut switch={} packet-in={} packet-out={}", - new Object[] {sw, pi, po}, e); - } - - return; - } - - // IFloodlightModule methods - - @Override - public Collection<Class<? extends IFloodlightService>> getModuleServices() { - // We don't export any services - return null; - } - - @Override - public Map<Class<? extends IFloodlightService>, IFloodlightService> - getServiceImpls() { - // We don't have any services - return null; - } - - @Override - public Collection<Class<? extends IFloodlightService>> getModuleDependencies() { - Collection<Class<? extends IFloodlightService>> l = - new ArrayList<Class<? extends IFloodlightService>>(); - l.add(IFloodlightProviderService.class); - l.add(IDeviceService.class); - l.add(IRoutingService.class); - l.add(ITopologyService.class); - l.add(ICounterStoreService.class); - return l; - } - - @Override - @LogMessageDocs({ - @LogMessageDoc(level="WARN", - message="Error parsing flow idle timeout, " + - "using default of {number} seconds", - explanation="The properties file contains an invalid " + - "flow idle timeout", - recommendation="Correct the idle timeout in the " + - "properties file."), - @LogMessageDoc(level="WARN", - message="Error parsing flow hard timeout, " + - "using default of {number} seconds", - explanation="The properties file contains an invalid " + - "flow hard timeout", - recommendation="Correct the hard timeout in the " + - "properties file.") - }) - public void init(FloodlightModuleContext context) throws FloodlightModuleException { - super.init(); - this.floodlightProvider = context.getServiceImpl(IFloodlightProviderService.class); - this.deviceManager = context.getServiceImpl(IDeviceService.class); - this.routingEngine = context.getServiceImpl(IRoutingService.class); - this.topology = context.getServiceImpl(ITopologyService.class); - this.counterStore = context.getServiceImpl(ICounterStoreService.class); - } - - @Override - public void startUp(FloodlightModuleContext context) { - super.startUp(); - } + protected static Logger log = LoggerFactory.getLogger(Forwarding.class); + + protected static int DEFAULT_HARD_TIMEOUT = 0; // not final b/c could be configured from config file + protected static int DEFAULT_IDLE_TIMEOUT = 5; + + @Override + @LogMessageDoc(level="ERROR", + message="Unexpected decision made for this packet-in={}", + explanation="An unsupported PacketIn decision has been " + + "passed to the flow programming component", + recommendation=LogMessageDoc.REPORT_CONTROLLER_BUG) + public Command processPacketInMessage(IOFSwitch sw, OFPacketIn pi, IRoutingDecision decision, FloodlightContext cntx) { + Ethernet eth = IFloodlightProviderService.bcStore.get(cntx, IFloodlightProviderService.CONTEXT_PI_PAYLOAD); + + // We found a routing decision (i.e. Firewall is enabled... it's the only thing that makes RoutingDecisions) + if (decision != null) { + if (log.isTraceEnabled()) { + log.trace("Forwaring decision={} was made for PacketIn={}", decision.getRoutingAction().toString(), pi); + } + + switch(decision.getRoutingAction()) { + case NONE: + // don't do anything + return Command.CONTINUE; + case FORWARD_OR_FLOOD: + case FORWARD: + doForwardFlow(sw, pi, cntx, false); + return Command.CONTINUE; + case MULTICAST: + // treat as broadcast + doFlood(sw, pi, cntx); + return Command.CONTINUE; + case DROP: + doDropFlow(sw, pi, decision, cntx); + return Command.CONTINUE; + default: + log.error("Unexpected decision made for this packet-in={}", pi, decision.getRoutingAction()); + return Command.CONTINUE; + } + } else { // No routing decision was found. Forward to destination or flood if bcast or mcast. + if (log.isTraceEnabled()) { + log.trace("No decision was made for PacketIn={}, forwarding", pi); + } + + if (eth.isBroadcast() || eth.isMulticast()) { + doFlood(sw, pi, cntx); + } else { + doForwardFlow(sw, pi, cntx, false); + } + } + + return Command.CONTINUE; + } + + @LogMessageDoc(level="ERROR", + message="Failure writing drop flow mod", + explanation="An I/O error occured while trying to write a " + + "drop flow mod to a switch", + recommendation=LogMessageDoc.CHECK_SWITCH) + protected void doDropFlow(IOFSwitch sw, OFPacketIn pi, IRoutingDecision decision, FloodlightContext cntx) { + // initialize match structure and populate it based on the packet in's match + Match.Builder mb = null; + if (decision.getMatch() != null) { + /* TODO @Ryan This routing decision should be a match object with all appropriate fields set, + * not just masked. If it's a decision that matches the packet we received, then simply setting + * the masks to the new match will create the same match in the end. We can just use the routing + * match object instead (right?). + * + * The Firewall is currently the only module/service that sets routing decisions in the context + * store (or instantiates any for that matter). It's disabled by default, so as-is a decision's + * match should always be null, meaning this will never be true. + */ + mb = decision.getMatch().createBuilder(); + } else { + mb = pi.getMatch().createBuilder(); // otherwise no route is known so go based on packet's match object + } + + OFFlowMod.Builder fmb = sw.getOFFactory().buildFlowAdd(); // this will be a drop-flow; a flow that will not output to any ports + List<OFAction> actions = new ArrayList<OFAction>(); // set no action to drop + U64 cookie = AppCookie.makeCookie(FORWARDING_APP_ID, 0); + + fmb.setCookie(cookie) + .setHardTimeout(DEFAULT_HARD_TIMEOUT) + .setIdleTimeout(DEFAULT_IDLE_TIMEOUT) + .setBufferId(OFBufferId.NO_BUFFER) + .setMatch(mb.build()) + .setActions(actions); // empty list + + try { + if (log.isDebugEnabled()) { + log.debug("write drop flow-mod sw={} match={} flow-mod={}", + new Object[] { sw, mb.build(), fmb.build() }); + } + boolean dampened = messageDamper.write(sw, fmb.build(), cntx); + log.debug("OFMessage dampened: {}", dampened); + } catch (IOException e) { + log.error("Failure writing drop flow mod", e); + } + } + + protected void doForwardFlow(IOFSwitch sw, OFPacketIn pi, FloodlightContext cntx, boolean requestFlowRemovedNotifn) { + Match m = pi.getMatch(); + + // Check if we have the location of the destination + IDevice dstDevice = IDeviceService.fcStore.get(cntx, IDeviceService.CONTEXT_DST_DEVICE); + + if (dstDevice != null) { + IDevice srcDevice = IDeviceService.fcStore.get(cntx, IDeviceService.CONTEXT_SRC_DEVICE); + DatapathId srcIsland = topologyService.getL2DomainId(sw.getId()); + + if (srcDevice == null) { + log.debug("No device entry found for source device"); + return; + } + if (srcIsland == null) { + log.debug("No openflow island found for source {}/{}", + sw.getStringId(), pi.getInPort()); + return; + } + + // Validate that we have a destination known on the same island + // Validate that the source and destination are not on the same switchport + boolean on_same_island = false; + boolean on_same_if = false; + for (SwitchPort dstDap : dstDevice.getAttachmentPoints()) { + DatapathId dstSwDpid = dstDap.getSwitchDPID(); + DatapathId dstIsland = topologyService.getL2DomainId(dstSwDpid); + if ((dstIsland != null) && dstIsland.equals(srcIsland)) { + on_same_island = true; + if ((sw.getId().equals(dstSwDpid)) && (pi.getInPort().equals(dstDap.getPort()))) { + on_same_if = true; + } + break; + } + } + + if (!on_same_island) { + // Flood since we don't know the dst device + if (log.isTraceEnabled()) { + log.trace("No first hop island found for destination " + + "device {}, Action = flooding", dstDevice); + } + doFlood(sw, pi, cntx); + return; + } + + if (on_same_if) { + if (log.isTraceEnabled()) { + log.trace("Both source and destination are on the same " + + "switch/port {}/{}, Action = NOP", + sw.toString(), pi.getInPort()); + } + return; + } + + // Install all the routes where both src and dst have attachment + // points. Since the lists are stored in sorted order we can + // traverse the attachment points in O(m+n) time + SwitchPort[] srcDaps = srcDevice.getAttachmentPoints(); + Arrays.sort(srcDaps, clusterIdComparator); + SwitchPort[] dstDaps = dstDevice.getAttachmentPoints(); + Arrays.sort(dstDaps, clusterIdComparator); + + int iSrcDaps = 0, iDstDaps = 0; + + while ((iSrcDaps < srcDaps.length) && (iDstDaps < dstDaps.length)) { + SwitchPort srcDap = srcDaps[iSrcDaps]; + SwitchPort dstDap = dstDaps[iDstDaps]; + + // srcCluster and dstCluster here cannot be null as + // every switch will be at least in its own L2 domain. + DatapathId srcCluster = topologyService.getL2DomainId(srcDap.getSwitchDPID()); + DatapathId dstCluster = topologyService.getL2DomainId(dstDap.getSwitchDPID()); + + int srcVsDest = srcCluster.compareTo(dstCluster); + if (srcVsDest == 0) { + if (!srcDap.equals(dstDap)) { + Route route = + routingEngineService.getRoute(srcDap.getSwitchDPID(), + srcDap.getPort(), + dstDap.getSwitchDPID(), + dstDap.getPort(), U64.of(0)); //cookie = 0, i.e., default route + if (route != null) { + if (log.isTraceEnabled()) { + log.trace("pushRoute match={} route={} " + + "destination={}:{}", + new Object[] { m, route, + dstDap.getSwitchDPID(), + dstDap.getPort()}); + } + U64 cookie = AppCookie.makeCookie(FORWARDING_APP_ID, 0); + + // if there is prior routing decision use route's match + Match routeMatch = null; + IRoutingDecision decision = null; + if (cntx != null) { + decision = IRoutingDecision.rtStore.get(cntx, IRoutingDecision.CONTEXT_DECISION); + } + if (decision != null) { + routeMatch = decision.getMatch(); + } else { + // A Match will contain only what you want to match on. + // Absence of a MatchField --> it can be anything (wildcarded). + // Remove all matches except for L2 and L3 addresses & VLAN + // to allow forwarding on a (V)LAN + routeMatch = MatchMaskUtils.maskL4AndUp(m); + } + + pushRoute(route, routeMatch, pi, sw.getId(), cookie, + cntx, requestFlowRemovedNotifn, false, + OFFlowModCommand.ADD); + } + } + iSrcDaps++; + iDstDaps++; + } else if (srcVsDest < 0) { + iSrcDaps++; + } else { + iDstDaps++; + } + } + } else { + // Flood since we don't know the dst device + doFlood(sw, pi, cntx); + } + } + + /** + * Creates a OFPacketOut with the OFPacketIn data that is flooded on all ports unless + * the port is blocked, in which case the packet will be dropped. + * @param sw The switch that receives the OFPacketIn + * @param pi The OFPacketIn that came to the switch + * @param cntx The FloodlightContext associated with this OFPacketIn + */ + @LogMessageDoc(level="ERROR", + message="Failure writing PacketOut " + + "switch={switch} packet-in={packet-in} " + + "packet-out={packet-out}", + explanation="An I/O error occured while writing a packet " + + "out message to the switch", + recommendation=LogMessageDoc.CHECK_SWITCH) + protected void doFlood(IOFSwitch sw, OFPacketIn pi, FloodlightContext cntx) { + if (topologyService.isIncomingBroadcastAllowed(sw.getId(), + pi.getInPort()) == false) { + if (log.isTraceEnabled()) { + log.trace("doFlood, drop broadcast packet, pi={}, " + + "from a blocked port, srcSwitch=[{},{}], linkInfo={}", + new Object[] {pi, sw.getId(),pi.getInPort()}); + } + return; + } + + // Set Action to flood + OFPacketOut.Builder pob = sw.getOFFactory().buildPacketOut(); + List<OFAction> actions = new ArrayList<OFAction>(); + if (sw.hasAttribute(IOFSwitch.PROP_SUPPORTS_OFPP_FLOOD)) { + actions.add(sw.getOFFactory().actions().output(OFPort.FLOOD, Integer.MAX_VALUE)); // FLOOD is a more selective/efficient version of ALL + } else { + actions.add(sw.getOFFactory().actions().output(OFPort.ALL, Integer.MAX_VALUE)); + } + pob.setActions(actions); + + // set buffer-id, in-port and packet-data based on packet-in + pob.setBufferId(OFBufferId.NO_BUFFER); + pob.setInPort(pi.getInPort()); + pob.setData(pi.getData()); + + try { + if (log.isTraceEnabled()) { + log.trace("Writing flood PacketOut switch={} packet-in={} packet-out={}", + new Object[] {sw, pi, pob.build()}); + } + messageDamper.write(sw, pob.build(), cntx); + } catch (IOException e) { + log.error("Failure writing PacketOut switch={} packet-in={} packet-out={}", + new Object[] {sw, pi, pob.build()}, e); + } + + return; + } + + // IFloodlightModule methods + + @Override + public Collection<Class<? extends IFloodlightService>> getModuleServices() { + // We don't export any services + return null; + } + + @Override + public Map<Class<? extends IFloodlightService>, IFloodlightService> + getServiceImpls() { + // We don't have any services + return null; + } + + @Override + public Collection<Class<? extends IFloodlightService>> getModuleDependencies() { + Collection<Class<? extends IFloodlightService>> l = + new ArrayList<Class<? extends IFloodlightService>>(); + l.add(IFloodlightProviderService.class); + l.add(IDeviceService.class); + l.add(IRoutingService.class); + l.add(ITopologyService.class); + l.add(IDebugCounterService.class); + return l; + } + + @Override + @LogMessageDocs({ + @LogMessageDoc(level="WARN", + message="Error parsing flow idle timeout, " + + "using default of {number} seconds", + explanation="The properties file contains an invalid " + + "flow idle timeout", + recommendation="Correct the idle timeout in the " + + "properties file."), + @LogMessageDoc(level="WARN", + message="Error parsing flow hard timeout, " + + "using default of {number} seconds", + explanation="The properties file contains an invalid " + + "flow hard timeout", + recommendation="Correct the hard timeout in the " + + "properties file.") + }) + public void init(FloodlightModuleContext context) throws FloodlightModuleException { + super.init(); + this.floodlightProviderService = context.getServiceImpl(IFloodlightProviderService.class); + this.deviceManagerService = context.getServiceImpl(IDeviceService.class); + this.routingEngineService = context.getServiceImpl(IRoutingService.class); + this.topologyService = context.getServiceImpl(ITopologyService.class); + this.debugCounterService = context.getServiceImpl(IDebugCounterService.class); + + Map<String, String> configParameters = context.getConfigParams(this); + String tmp = configParameters.get("hard-timeout"); + if (tmp != null) { + DEFAULT_HARD_TIMEOUT = Integer.parseInt(tmp); + log.info("Default hard timeout set to {}.", DEFAULT_HARD_TIMEOUT); + } else { + log.info("Default hard timeout not configured. Using {}.", DEFAULT_HARD_TIMEOUT); + } + tmp = configParameters.get("idle-timeout"); + if (tmp != null) { + DEFAULT_IDLE_TIMEOUT = Integer.parseInt(tmp); + log.info("Default idle timeout set to {}.", DEFAULT_IDLE_TIMEOUT); + } else { + log.info("Default idle timeout not configured. Using {}.", DEFAULT_IDLE_TIMEOUT); + } + + + + } + + @Override + public void startUp(FloodlightModuleContext context) { + super.startUp(); + } } \ No newline at end of file diff --git a/src/main/java/net/floodlightcontroller/learningswitch/LearningSwitch.java b/src/main/java/net/floodlightcontroller/learningswitch/LearningSwitch.java index 8e28c2127e4a16205afbffdb705cee32ebabbc11..7e347294c30dd4822e83e3c3980ea35ac49489f0 100644 --- a/src/main/java/net/floodlightcontroller/learningswitch/LearningSwitch.java +++ b/src/main/java/net/floodlightcontroller/learningswitch/LearningSwitch.java @@ -150,9 +150,11 @@ public class LearningSwitch if (vlan == VlanVid.FULL_MASK) { vlan = VlanVid.ofVlan(0); } + Map<MacVlanPair, OFPort> swMap = macVlanToSwitchPortMap.get(sw); - if (swMap != null) + if (swMap != null) { swMap.remove(new MacVlanPair(mac, vlan)); + } } /** @@ -167,8 +169,9 @@ public class LearningSwitch vlan = VlanVid.FULL_MASK; } Map<MacVlanPair, OFPort> swMap = macVlanToSwitchPortMap.get(sw); - if (swMap != null) + if (swMap != null) { return swMap.get(new MacVlanPair(mac, vlan)); + } // if none found return null; @@ -187,8 +190,9 @@ public class LearningSwitch */ public void clearLearnedTable(IOFSwitch sw) { Map<MacVlanPair, OFPort> swMap = macVlanToSwitchPortMap.get(sw); - if (swMap != null) + if (swMap != null) { swMap.clear(); + } } @Override @@ -342,9 +346,7 @@ public class LearningSwitch * @param packetInMessage The corresponding PacketIn. * @param egressPort The switchport to output the PacketOut. */ - private void writePacketOutForPacketIn(IOFSwitch sw, - OFPacketIn packetInMessage, - OFPort egressPort) { + private void writePacketOutForPacketIn(IOFSwitch sw, OFPacketIn packetInMessage, OFPort egressPort) { // from openflow 1.0 spec - need to set these on a struct ofp_packet_out: // uint32_t buffer_id; /* ID assigned by datapath (-1 if none). */ // uint16_t in_port; /* Packet's input port (OFPP_NONE if none). */ @@ -543,19 +545,15 @@ public class LearningSwitch } @Override - public Map<Class<? extends IFloodlightService>, IFloodlightService> - getServiceImpls() { - Map<Class<? extends IFloodlightService>, - IFloodlightService> m = - new HashMap<Class<? extends IFloodlightService>, - IFloodlightService>(); + public Map<Class<? extends IFloodlightService>, IFloodlightService> getServiceImpls() { + Map<Class<? extends IFloodlightService>, IFloodlightService> m = + new HashMap<Class<? extends IFloodlightService>, IFloodlightService>(); m.put(ILearningSwitchService.class, this); return m; } @Override - public Collection<Class<? extends IFloodlightService>> - getModuleDependencies() { + public Collection<Class<? extends IFloodlightService>> getModuleDependencies() { Collection<Class<? extends IFloodlightService>> l = new ArrayList<Class<? extends IFloodlightService>>(); l.add(IFloodlightProviderService.class); @@ -565,16 +563,11 @@ public class LearningSwitch } @Override - public void init(FloodlightModuleContext context) - throws FloodlightModuleException { - macVlanToSwitchPortMap = - new ConcurrentHashMap<IOFSwitch, Map<MacVlanPair, OFPort>>(); - floodlightProviderService = - context.getServiceImpl(IFloodlightProviderService.class); - debugCounterService = - context.getServiceImpl(IDebugCounterService.class); - restApiService = - context.getServiceImpl(IRestApiService.class); + public void init(FloodlightModuleContext context) throws FloodlightModuleException { + macVlanToSwitchPortMap = new ConcurrentHashMap<IOFSwitch, Map<MacVlanPair, OFPort>>(); + floodlightProviderService = context.getServiceImpl(IFloodlightProviderService.class); + debugCounterService = context.getServiceImpl(IDebugCounterService.class); + restApiService = context.getServiceImpl(IRestApiService.class); } @Override @@ -593,8 +586,7 @@ public class LearningSwitch } } catch (NumberFormatException e) { log.warn("Error parsing flow idle timeout, " + - "using default of {} seconds", - FLOWMOD_DEFAULT_IDLE_TIMEOUT); + "using default of {} seconds", FLOWMOD_DEFAULT_IDLE_TIMEOUT); } try { String hardTimeout = configOptions.get("hardtimeout"); @@ -603,8 +595,7 @@ public class LearningSwitch } } catch (NumberFormatException e) { log.warn("Error parsing flow hard timeout, " + - "using default of {} seconds", - FLOWMOD_DEFAULT_HARD_TIMEOUT); + "using default of {} seconds", FLOWMOD_DEFAULT_HARD_TIMEOUT); } try { String priority = configOptions.get("priority"); @@ -616,11 +607,8 @@ public class LearningSwitch "using default of {}", FLOWMOD_PRIORITY); } - log.debug("FlowMod idle timeout set to {} seconds", - FLOWMOD_DEFAULT_IDLE_TIMEOUT); - log.debug("FlowMod hard timeout set to {} seconds", - FLOWMOD_DEFAULT_HARD_TIMEOUT); - log.debug("FlowMod priority set to {}", - FLOWMOD_PRIORITY); + log.debug("FlowMod idle timeout set to {} seconds", FLOWMOD_DEFAULT_IDLE_TIMEOUT); + log.debug("FlowMod hard timeout set to {} seconds", FLOWMOD_DEFAULT_HARD_TIMEOUT); + log.debug("FlowMod priority set to {}", FLOWMOD_PRIORITY); } } diff --git a/src/main/java/net/floodlightcontroller/routing/ForwardingBase.java b/src/main/java/net/floodlightcontroller/routing/ForwardingBase.java index 7d808973396e15ec085d26304c2bce4590491d80..a339426845d024c242fb8c534122024d20ab8435 100644 --- a/src/main/java/net/floodlightcontroller/routing/ForwardingBase.java +++ b/src/main/java/net/floodlightcontroller/routing/ForwardingBase.java @@ -202,14 +202,9 @@ public abstract class ForwardingBase implements IOFMessageListener { "flow modification to a switch", recommendation=LogMessageDoc.CHECK_SWITCH) }) - public boolean pushRoute(Route route, Match match, - Integer wildcard_hints, - OFPacketIn pi, - DatapathId pinSwitch, - U64 cookie, - FloodlightContext cntx, - boolean reqeustFlowRemovedNotifn, - boolean doFlush, + public boolean pushRoute(Route route, Match match, OFPacketIn pi, + DatapathId pinSwitch, U64 cookie, FloodlightContext cntx, + boolean reqeustFlowRemovedNotifn, boolean doFlush, OFFlowModCommand flowModCommand) { boolean srcSwitchIncluded = false; @@ -228,6 +223,7 @@ public abstract class ForwardingBase implements IOFMessageListener { return srcSwitchIncluded; } + // need to build flow mod based on what type it is. Cannot set command later OFFlowMod.Builder fmb; switch (flowModCommand) { case ADD: @@ -246,15 +242,13 @@ public abstract class ForwardingBase implements IOFMessageListener { log.error("Could not decode OFFlowModCommand. Using MODIFY_STRICT. (Should another be used as the default?)"); case MODIFY_STRICT: fmb = sw.getOFFactory().buildFlowModifyStrict(); - break; } + break; + } OFActionOutput.Builder aob = sw.getOFFactory().actions().buildOutput(); List<OFAction> actions = new ArrayList<OFAction>(); Match.Builder mb = match.createBuilder(); - // set the match. TODO @Ryan look into setting Match's wildcards before hand, then pass in correctly - //fmb.setMatch(wildcard(match, sw, wildcard_hints)); - // set input and output ports on the switch OFPort outPort = switchPortList.get(indx).getPortId(); OFPort inPort = switchPortList.get(indx - 1).getPortId(); @@ -302,15 +296,6 @@ public abstract class ForwardingBase implements IOFMessageListener { return srcSwitchIncluded; } - /* TODO @Ryan get rid of this once wildcard/masked matches are set properly wherever they need to be - * protected Match wildcard(Match match, IOFSwitch sw, Integer wildcard_hints) { - * - if (wildcard_hints != null) { - return match.clone().setWildcards(wildcard_hints.intValue()); - } - return match.clone(); - }*/ - /** * Pushes a packet-out to a switch. If bufferId != BUFFER_ID_NONE we * assume that the packetOut switch is the same as the packetIn switch @@ -352,8 +337,7 @@ public abstract class ForwardingBase implements IOFMessageListener { * @param outport output port * @param cntx context of the packet */ - protected void pushPacket(IOFSwitch sw, OFPacketIn pi, - boolean useBufferId, + protected void pushPacket(IOFSwitch sw, OFPacketIn pi, boolean useBufferId, OFPort outport, FloodlightContext cntx) { if (pi == null) { @@ -381,7 +365,7 @@ public abstract class ForwardingBase implements IOFMessageListener { OFPacketOut.Builder pob = sw.getOFFactory().buildPacketOut(); // set actions List<OFAction> actions = new ArrayList<OFAction>(); - actions.add(sw.getOFFactory().actions().output(outport, Integer.MAX_VALUE)); //TODO @Ryan is MAX_VALUE == 0xffff previously? + actions.add(sw.getOFFactory().actions().output(outport, Integer.MAX_VALUE)); pob.setActions(actions); if (useBufferId) { @@ -415,11 +399,8 @@ public abstract class ForwardingBase implements IOFMessageListener { * @param ports * @param cntx */ - public void packetOutMultiPort(byte[] packetData, - IOFSwitch sw, - OFPort inPort, - Set<OFPort> outPorts, - FloodlightContext cntx) { + public void packetOutMultiPort(byte[] packetData, IOFSwitch sw, + OFPort inPort, Set<OFPort> outPorts, FloodlightContext cntx) { //setting actions List<OFAction> actions = new ArrayList<OFAction>(); @@ -456,11 +437,8 @@ public abstract class ForwardingBase implements IOFMessageListener { * Accepts a PacketIn instead of raw packet data. Note that the inPort * and switch can be different than the packet in switch/port */ - public void packetOutMultiPort(OFPacketIn pi, - IOFSwitch sw, - OFPort inPort, - Set<OFPort> outPorts, - FloodlightContext cntx) { + public void packetOutMultiPort(OFPacketIn pi, IOFSwitch sw, + OFPort inPort, Set<OFPort> outPorts, FloodlightContext cntx) { packetOutMultiPort(pi.getData(), sw, inPort, outPorts, cntx); } @@ -469,52 +447,11 @@ public abstract class ForwardingBase implements IOFMessageListener { * Accepts an IPacket instead of raw packet data. Note that the inPort * and switch can be different than the packet in switch/port */ - public void packetOutMultiPort(IPacket packet, - IOFSwitch sw, - OFPort inPort, - Set<OFPort> outPorts, - FloodlightContext cntx) { + public void packetOutMultiPort(IPacket packet, IOFSwitch sw, + OFPort inPort, Set<OFPort> outPorts, FloodlightContext cntx) { packetOutMultiPort(packet.serialize(), sw, inPort, outPorts, cntx); } - /*TODO @Ryan what are these? outdated? protected boolean isInBroadcastCache(IOFSwitch sw, OFPacketIn pi, FloodlightContext cntx) { - // Get the cluster id of the switch. - // Get the hash of the Ethernet packet. - if (sw == null) return true; - - // If the feature is disabled, always return false; - if (!broadcastCacheFeature) return false; - - Ethernet eth = - IFloodlightProviderService.bcStore.get(cntx, - IFloodlightProviderService.CONTEXT_PI_PAYLOAD); - - Long broadcastHash; - broadcastHash = topology.getL2DomainId(sw.getId()).getLong() * prime1 + - pi.getInPort().getPortNumber() * prime2 + eth.hashCode(); - if (broadcastCache.update(broadcastHash)) { - //TODO @Ryan isn't implemented anymore, nuke it? sw.updateBroadcastCache(broadcastHash, pi.getInPort()); - return true; - } else { - return false; - } - } - - protected boolean isInSwitchBroadcastCache(IOFSwitch sw, OFPacketIn pi, FloodlightContext cntx) { - if (sw == null) return true; - - // If the feature is disabled, always return false; - if (!broadcastCacheFeature) return false; - - // Get the hash of the Ethernet packet. - Ethernet eth = IFloodlightProviderService.bcStore.get(cntx, IFloodlightProviderService.CONTEXT_PI_PAYLOAD); - - long hash = pi.getInPort().getPortNumber() * prime2 + eth.hashCode(); - - // some FORWARD_OR_FLOOD packets are unicast with unknown destination mac - return sw.updateBroadcastCache(hash, pi.getInPort()); - }*/ - @LogMessageDocs({ @LogMessageDoc(level="ERROR", message="Failure writing deny flow mod", @@ -523,8 +460,7 @@ public abstract class ForwardingBase implements IOFMessageListener { recommendation=LogMessageDoc.CHECK_SWITCH) }) public static boolean blockHost(IOFSwitchService switchService, - SwitchPort sw_tup, MacAddress host_mac, - short hardTimeout, U64 cookie) { + SwitchPort sw_tup, MacAddress host_mac, short hardTimeout, U64 cookie) { if (sw_tup == null) { return false; @@ -566,9 +502,7 @@ public abstract class ForwardingBase implements IOFMessageListener { @Override public boolean isCallbackOrderingPrereq(OFType type, String name) { - return (type.equals(OFType.PACKET_IN) && - (name.equals("topology") || - name.equals("devicemanager"))); + return (type.equals(OFType.PACKET_IN) && (name.equals("topology") || name.equals("devicemanager"))); } @Override diff --git a/src/main/java/net/floodlightcontroller/routing/IRoutingDecision.java b/src/main/java/net/floodlightcontroller/routing/IRoutingDecision.java index 02779e0488b8960fea5d5f24eb52d6cc733a4bfc..bc9df880fd08a4a72f98d9104d09f7245edabfc0 100644 --- a/src/main/java/net/floodlightcontroller/routing/IRoutingDecision.java +++ b/src/main/java/net/floodlightcontroller/routing/IRoutingDecision.java @@ -60,7 +60,7 @@ public interface IRoutingDecision { public List<SwitchPort> getMulticastInterfaces(); public void setMulticastInterfaces(List<SwitchPort> lspt); public Match getMatch(); - public void setMatch(Match wildcards); + public void setMatch(Match match); public short getHardTimeout(); public void setHardTimeout(short hardTimeout); } diff --git a/src/main/java/net/floodlightcontroller/util/MatchMaskUtils.java b/src/main/java/net/floodlightcontroller/util/MatchMaskUtils.java new file mode 100644 index 0000000000000000000000000000000000000000..f4620e5aed250128c3d54572a5b215941c141ae7 --- /dev/null +++ b/src/main/java/net/floodlightcontroller/util/MatchMaskUtils.java @@ -0,0 +1,41 @@ +package net.floodlightcontroller.util; + +import org.projectfloodlight.openflow.protocol.OFFactories; +import org.projectfloodlight.openflow.protocol.match.Match; +import org.projectfloodlight.openflow.protocol.match.MatchField; + +/** + * Apply certain, routine masks to existing matches. + * + * @author Ryan Izard <ryan.izard@bigswitch.com, rizard@g.clemson.edu> + */ +public class MatchMaskUtils { + /** + * Create a point-to-point match for two devices at the IP layer. + * Takes an existing match (e.g. from a PACKET_IN), and masks all + * MatchFields leaving behind: + * IN_PORT + * VLAN_VID + * ETH_SRC + * ETH_DST + * IPV4_SRC + * IPV4_DST + * + * @param m The match to remove all L4+ MatchFields from + * @return A new Match object with all MatchFields masked/wildcared + * except for those listed above. + */ + public static Match maskL4AndUp(Match m) { + // cannot create builder from existing match; will retain all MatchFields set + Match.Builder mb = OFFactories.getFactory(m.getVersion()).buildMatch(); + return mb.setExact(MatchField.IN_PORT, m.get(MatchField.IN_PORT)) + .setExact(MatchField.VLAN_VID, m.get(MatchField.VLAN_VID)) + .setExact(MatchField.ETH_SRC, m.get(MatchField.ETH_SRC)) + .setExact(MatchField.ETH_DST, m.get(MatchField.ETH_DST)) + .setExact(MatchField.IPV4_SRC, m.get(MatchField.IPV4_SRC)) + .setExact(MatchField.IPV4_DST, m.get(MatchField.IPV4_DST)) + .build(); + } + + +} diff --git a/src/main/java/net/floodlightcontroller/util/MatchString.java b/src/main/java/net/floodlightcontroller/util/MatchString.java index 26603ce8d18492a5e4b75c1813478bb99069bdc2..fb71e3cd1fb3cf6c108f37c94fe750e471df221f 100644 --- a/src/main/java/net/floodlightcontroller/util/MatchString.java +++ b/src/main/java/net/floodlightcontroller/util/MatchString.java @@ -25,20 +25,19 @@ import org.projectfloodlight.openflow.types.VlanPcp; * */ public class MatchString { - /* List of Strings for marshalling and unmarshalling to human readable forms */ - final public static String STR_IN_PORT = "in_port"; - final public static String STR_DL_DST = "dl_dst"; - final public static String STR_DL_SRC = "dl_src"; - final public static String STR_DL_TYPE = "dl_type"; - final public static String STR_DL_VLAN = "dl_vlan"; - final public static String STR_DL_VLAN_PCP = "dl_vpcp"; - final public static String STR_NW_DST = "nw_dst"; - final public static String STR_NW_SRC = "nw_src"; - final public static String STR_NW_PROTO = "nw_proto"; - final public static String STR_NW_TOS = "nw_tos"; - final public static String STR_TP_DST = "tp_dst"; - final public static String STR_TP_SRC = "tp_src"; + final private static String STR_IN_PORT = "in_port"; + final private static String STR_DL_DST = "dl_dst"; + final private static String STR_DL_SRC = "dl_src"; + final private static String STR_DL_TYPE = "dl_type"; + final private static String STR_DL_VLAN = "dl_vlan"; + final private static String STR_DL_VLAN_PCP = "dl_vpcp"; + final private static String STR_NW_DST = "nw_dst"; + final private static String STR_NW_SRC = "nw_src"; + final private static String STR_NW_PROTO = "nw_proto"; + final private static String STR_NW_TOS = "nw_tos"; + final private static String STR_TP_DST = "tp_dst"; + final private static String STR_TP_SRC = "tp_src"; /** * Output a dpctl-styled string, i.e., only list the elements that are not diff --git a/src/main/java/net/floodlightcontroller/util/OFMessageDamper.java b/src/main/java/net/floodlightcontroller/util/OFMessageDamper.java index eb4c368e80b4131d8eff36879cbb5b86564f2ae9..ba4f01d3ac64a6b96d9856e489ab46e8c521aad2 100644 --- a/src/main/java/net/floodlightcontroller/util/OFMessageDamper.java +++ b/src/main/java/net/floodlightcontroller/util/OFMessageDamper.java @@ -116,8 +116,7 @@ public class OFMessageDamper { * the message was dampened. * @throws IOException */ - public boolean write(IOFSwitch sw, OFMessage msg, FloodlightContext cntx) - throws IOException { + public boolean write(IOFSwitch sw, OFMessage msg, FloodlightContext cntx) throws IOException { return write(sw, msg, cntx, false); } @@ -131,9 +130,7 @@ public class OFMessageDamper { * the message was dampened. * @throws IOException */ - public boolean write(IOFSwitch sw, OFMessage msg, - FloodlightContext cntx, boolean flush) - throws IOException { + public boolean write(IOFSwitch sw, OFMessage msg, FloodlightContext cntx, boolean flush) throws IOException { if (! msgTypesToCache.contains(msg.getType())) { sw.write(msg, LogicalOFMessageCategory.MAIN); if (flush) {