Beispiel #1
0
 @Override
 public FlowEntry matches(long dpid, short inputPort, byte[] packetData) {
   OFMatch m = new OFMatch();
   m.loadFromPacket(packetData, inputPort);
   List<FlowEntry> list = matches(dpid, m);
   // if we match more than one thing, return the highest priority
   if (list.size() > 0) return list.get(0);
   return null;
 }
Beispiel #2
0
  @LogMessageDocs({
    @LogMessageDoc(
        level = "ERROR",
        message = "Failure writing deny flow mod",
        explanation = "An I/O error occurred while writing a " + "deny flow mod to a switch",
        recommendation = LogMessageDoc.CHECK_SWITCH)
  })
  public static boolean blockHost(
      IFloodlightProviderService floodlightProvider,
      SwitchPort sw_tup,
      long host_mac,
      short hardTimeout,
      long cookie) {

    if (sw_tup == null) {
      return false;
    }

    IOFSwitch sw = floodlightProvider.getSwitches().get(sw_tup.getSwitchDPID());
    if (sw == null) return false;
    int inputPort = sw_tup.getPort();
    log.debug(
        "blockHost sw={} port={} mac={}", new Object[] {sw, sw_tup.getPort(), new Long(host_mac)});

    // Create flow-mod based on packet-in and src-switch
    OFFlowMod fm = (OFFlowMod) floodlightProvider.getOFMessageFactory().getMessage(OFType.FLOW_MOD);
    OFMatch match = new OFMatch();
    List<OFAction> actions = new ArrayList<OFAction>(); // Set no action to
    // drop
    match
        .setDataLayerSource(Ethernet.toByteArray(host_mac))
        .setInputPort((short) inputPort)
        .setWildcards(OFMatch.OFPFW_ALL & ~OFMatch.OFPFW_DL_SRC & ~OFMatch.OFPFW_IN_PORT);
    fm.setCookie(cookie)
        .setHardTimeout(hardTimeout)
        .setIdleTimeout(FLOWMOD_DEFAULT_IDLE_TIMEOUT)
        .setHardTimeout(FLOWMOD_DEFAULT_HARD_TIMEOUT)
        .setBufferId(OFPacketOut.BUFFER_ID_NONE)
        .setMatch(match)
        .setActions(actions)
        .setLengthU(OFFlowMod.MINIMUM_LENGTH); // +OFActionOutput.MINIMUM_LENGTH);

    try {
      log.debug("write drop flow-mod sw={} match={} flow-mod={}", new Object[] {sw, match, fm});
      // TODO: can't use the message damper sine this method is static
      sw.write(fm, null);
    } catch (IOException e) {
      log.error("Failure writing deny flow mod", e);
      return false;
    }
    return true;
  }
Beispiel #3
0
  /**
   * Tell the classifier to drop packets that look like this
   *
   * @param fvClassifier
   * @param flowEntry
   * @param hardTimeout
   * @param idleTimeout
   */
  private void sendDropRule(
      FVClassifier fvClassifier,
      FlowEntry flowEntry,
      String sliceName,
      short hardTimeout,
      short idleTimeout) {
    FVFlowMod flowMod =
        (FVFlowMod) FlowVisor.getInstance().getFactory().getMessage(OFType.FLOW_MOD);
    // block this exact flow
    OFMatch match = new OFMatch();
    match.loadFromPacket(this.packetData, this.inPort);
    // different from previous policty of block by rule
    // flowMod.setMatch(flowEntry.getRuleMatch());

    String drop_policy = null;
    try {
      drop_policy = FVConfig.getDropPolicy(sliceName);
    } catch (ConfigError e) {
      FVLog.log(
          LogLevel.ALERT,
          fvClassifier,
          "Failed to retrieve drop policy from config." + "\nDefauting to exact drop_policy");
      drop_policy = "exact";
    }
    if (drop_policy.equals("exact")) flowMod.setMatch(match);
    else if (drop_policy.equals("rule")) flowMod.setMatch(flowEntry.getRuleMatch());
    else
      // Should never happen
      FVLog.log(LogLevel.CRIT, fvClassifier, "Error in configuration!");
    flowMod.setCommand(FVFlowMod.OFPFC_ADD);
    flowMod.setActions(new LinkedList<OFAction>()); // send to zero-length
    // list, i.e., DROP
    flowMod.setLengthU(OFFlowMod.MINIMUM_LENGTH);
    flowMod.setHardTimeout(hardTimeout);
    flowMod.setIdleTimeout(idleTimeout);
    flowMod.setPriority((short) 0); // set to lowest priority
    flowMod.setFlags((short) 1);
    // send removed msg (1), not the check overlap (2), or
    // emergency flow cache (4)

    FVLog.log(
        LogLevel.WARN,
        fvClassifier,
        "inserting drop (hard=" + hardTimeout + ",idle=" + idleTimeout + ") rule for " + flowEntry);
    fvClassifier.sendMsg(flowMod, fvClassifier);
  }
  /**
   * Event handler called when a switch leaves the network.
   *
   * @param DPID for the switch
   */
  @Override
  public void switchRemoved(long switchId) {
    IOFSwitch sw = this.floodlightProv.getSwitch(switchId);
    log.info(String.format("Switch s%d removed", switchId));

    /** ****************************************************************** */
    /* TODO: Update routing: change routing rules for all hosts */
    // check
    for (Host host : this.getHosts()) {
      OFMatch matchCriteria = new OFMatch();

      matchCriteria.setDataLayerType(OFMatch.ETH_TYPE_IPV4);
      matchCriteria.setNetworkDestination(host.getIPv4Address());

      for (IOFSwitch currSw : this.getSwitches().values()) {
        SwitchCommands.removeRules(currSw, this.table, matchCriteria);
      }
      updateAllRouting();
    }
    /** ****************************************************************** */
  }
 static {
   FlowMod2 = new OFFlowMod();
   TestRule2 = new HashMap<String, Object>();
   TestRule2.put(COLUMN_NAME, "TestRule2");
   TestRule2.put(COLUMN_SWITCH, TestSwitch1DPID);
   // setup match
   OFMatch match = new OFMatch();
   TestRule2.put(COLUMN_NW_DST, "192.168.1.0/24");
   match.fromString("nw_dst=192.168.1.0/24");
   // setup actions
   List<OFAction> actions = new LinkedList<OFAction>();
   TestRule2.put(COLUMN_ACTIONS, "output=1");
   actions.add(new OFActionOutput((short) 1, (short) Short.MAX_VALUE));
   // done
   FlowMod2.setMatch(match);
   FlowMod2.setActions(actions);
   FlowMod2.setBufferId(-1);
   FlowMod2.setOutPort(OFPort.OFPP_NONE.getValue());
   FlowMod2.setPriority(Short.MAX_VALUE);
   FlowMod2.setLengthU(OFFlowMod.MINIMUM_LENGTH + 8); // 8 bytes of actions
 }
  /**
   * Test to check whether the IPs given overlap or not at all
   *
   * @param flowIntersect - the current potential intersection
   * @param maskShift - the shift value (ie. either for a src_ip or a dst_ip).
   * @param masklenX - the netmask for the first ip.
   * @param masklenY - the netmask for the second ip.
   * @param x - the first ip
   * @param y - the second ip.
   * @return the smallest intersection of this ip space.
   */
  private int testIP(
      FlowIntersect flowIntersect, int maskShift, int masklenX, int masklenY, int x, int y) {
    int min = Math.min(masklenX, masklenY); // get the less specific address
    int max = Math.max(masklenX, masklenY); // get the more specific address
    int min_encoded = 32 - min; // because OpenFlow does it backwards... grr
    int max_encoded = 32 - max; // because OpenFlow does it backwards... grr
    if (max_encoded >= 32) // set all the bits if this is in fact fully
    max_encoded = 63; // wildcarded; if only for wireshark's sake

    int mask;
    if (min == 0) mask = 0; // nasty work around for stupid signed ints
    else mask = ~((1 << min_encoded) - 1); // min < 32, so no signed issues
    // int mask = (1 << min) - 1;

    if ((x & mask) != (y & mask)) // if these are not in the same CIDR block
    flowIntersect.setMatchType(MatchType.NONE);
    // else there is some overlap
    OFMatch interMatch = flowIntersect.getMatch();
    int wildCards = interMatch.getWildcards();
    // turn off all bits for this match and then turn on the used ones
    // use MAX not MIN, because we want the most specific intersection
    // split into two ops, so we can see intermediate step in debugger
    // assumes SRC mask == DST mask
    // turn off all bits for this match (making it an exact match)
    wildCards = wildCards & ~(((1 << OFMatch.OFPFW_NW_SRC_BITS) - 1) << maskShift);
    // turn on the bits for the intersection
    wildCards = wildCards | max_encoded << maskShift;
    interMatch.setWildcards(wildCards);
    if (masklenX < masklenY) {
      flowIntersect.maybeSubset = false;
      return y;
    } else if (masklenX > masklenY) {
      flowIntersect.maybeSuperset = false;
      return x;
    }

    // note that b/c of how CIDR addressing works, there is no overlap that
    // is not a SUB or SUPERSET
    return x; // x == y; doesn't matter
  }
  private void installL3FwdRule(IOFSwitch currSw, Host host, int opPortTowardsSrc) {
    if (debug_level < 2)
      System.out.println(
          "L3 Install Rule :  sw - "
              + String.valueOf(currSw.getId())
              + " port "
              + opPortTowardsSrc);
    OFMatch matchCriteria = new OFMatch();
    matchCriteria.setDataLayerType(OFMatch.ETH_TYPE_IPV4);
    matchCriteria.setNetworkDestination(host.getIPv4Address());

    List<OFAction> actionOps = new LinkedList<OFAction>();
    OFActionOutput actOp = new OFActionOutput(opPortTowardsSrc);
    actionOps.add(0, actOp);
    OFInstructionApplyActions applyActions = new OFInstructionApplyActions(actionOps);
    List<OFInstruction> instructionList = new ArrayList<OFInstruction>();
    instructionList.add(applyActions);

    SwitchCommands.removeRules(currSw, this.table, matchCriteria);
    if (SwitchCommands.installRule(
            currSw, this.table, SwitchCommands.DEFAULT_PRIORITY, matchCriteria, instructionList)
        == false) {
      System.out.println(
          "L3 Rule not installed: sw "
              + String.valueOf(currSw.getId())
              + " port: "
              + opPortTowardsSrc
              + " table: "
              + this.table);
    } else {
      if (debug_level < 2)
        System.out.println(
            "L3 Rule installed : sw "
                + String.valueOf(currSw.getId())
                + " port: "
                + opPortTowardsSrc
                + " table: "
                + this.table);
    }
  }
  /**
   * Event handler called when a host is no longer attached to a switch.
   *
   * @param device information about the host
   */
  @Override
  public void deviceRemoved(IDevice device) {
    Host host = this.knownHosts.get(device);
    if (null == host) {
      return;
    }
    this.knownHosts.remove(host);

    log.info(String.format("Host %s is no longer attached to a switch", host.getName()));

    /** ****************************************************************** */
    /* TODO: Update routing: remove rules to route to host */

    OFMatch matchCriteria = new OFMatch();
    matchCriteria.setDataLayerType(OFMatch.ETH_TYPE_IPV4);
    matchCriteria.setNetworkDestination(host.getIPv4Address());

    for (IOFSwitch currSw : this.getSwitches().values()) {
      SwitchCommands.removeRules(currSw, this.table, matchCriteria);
    }
    /** ****************************************************************** */
  }
Beispiel #9
0
 @Override
 protected OFMatch wildcard(OFMatch match, IOFSwitch sw, Integer hints) {
   // use same wilcarding as the learning switch
   int wildcards =
       ((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;
   return match.clone().setWildcards(wildcards);
 }
 static {
   FlowMod3 = new OFFlowMod();
   TestRule3 = new HashMap<String, Object>();
   TestRule3.put(COLUMN_NAME, "TestRule3");
   TestRule3.put(COLUMN_SWITCH, TestSwitch1DPID);
   // setup match
   OFMatch match = new OFMatch();
   TestRule3.put(COLUMN_DL_DST, "00:20:30:40:50:60");
   TestRule3.put(COLUMN_DL_VLAN, 4096);
   match.fromString("dl_dst=00:20:30:40:50:60,dl_vlan=4096");
   // setup actions
   TestRule3.put(COLUMN_ACTIONS, "output=controller");
   List<OFAction> actions = new LinkedList<OFAction>();
   actions.add(new OFActionOutput(OFPort.OFPP_CONTROLLER.getValue(), (short) Short.MAX_VALUE));
   // done
   FlowMod3.setMatch(match);
   FlowMod3.setActions(actions);
   FlowMod3.setBufferId(-1);
   FlowMod3.setOutPort(OFPort.OFPP_NONE.getValue());
   FlowMod3.setPriority(Short.MAX_VALUE);
   FlowMod3.setLengthU(OFFlowMod.MINIMUM_LENGTH + 8); // 8 bytes of actions
 }
Beispiel #11
0
  @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 using the packet
    OFMatch match = new OFMatch();
    match.loadFromPacket(pi.getPacketData(), pi.getInPort());
    if (decision.getWildcards() != null) {
      match.setWildcards(decision.getWildcards());
    }

    // 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);
    }
  }
Beispiel #12
0
 public FVMatch(OFMatch match) {
   super();
   this.wildcards = match.getWildcards();
   inputPort = match.getInputPort();
   dataLayerSource = match.getDataLayerSource();
   dataLayerDestination = match.getDataLayerDestination();
   ;
   dataLayerVirtualLan = match.getDataLayerVirtualLan();
   dataLayerVirtualLanPriorityCodePoint = match.getDataLayerVirtualLanPriorityCodePoint();
   dataLayerType = match.getDataLayerType();
   networkTypeOfService = match.getNetworkTypeOfService();
   networkProtocol = match.getNetworkProtocol();
   networkSource = match.getNetworkSource();
   networkDestination = match.getNetworkDestination();
   transportSource = match.getTransportSource();
   transportDestination = match.getTransportDestination();
 }
Beispiel #13
0
  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];
        Long srcCluster = topology.getL2DomainId(srcDap.getSwitchDPID());
        Long dstCluster = topology.getL2DomainId(dstDap.getSwitchDPID());

        int srcVsDest = srcCluster.compareTo(dstCluster);
        if (srcVsDest == 0) {
          if (!srcDap.equals(dstDap) && (srcCluster != null) && (dstCluster != null)) {
            Route route =
                routingEngine.getRoute(
                    srcDap.getSwitchDPID(),
                    (short) srcDap.getPort(),
                    dstDap.getSwitchDPID(),
                    (short) dstDap.getPort());
            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);

              pushRoute(
                  route,
                  match,
                  0,
                  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);
    }
  }
Beispiel #14
0
 protected OFMatch wildcard(OFMatch match, IOFSwitch sw, Integer wildcard_hints) {
   if (wildcard_hints != null) {
     return match.clone().setWildcards(wildcard_hints.intValue());
   }
   return match.clone();
 }
Beispiel #15
0
  public boolean pushRoute(
      Route route,
      OFMatch match,
      Integer wildcard_hints,
      OFPacketIn pi,
      long pinSwitch,
      long cookie,
      FloodlightContext cntx,
      boolean requestFlowRemovedNotifn,
      boolean doFlush,
      short flowModCommand) {

    boolean srcSwitchIncluded = false;
    OFFlowMod fm = (OFFlowMod) floodlightProvider.getOFMessageFactory().getMessage(OFType.FLOW_MOD);
    OFActionOutput action = new OFActionOutput();
    action.setMaxLength((short) 0xffff);
    List<OFAction> actions = new ArrayList<OFAction>();
    actions.add(action);

    fm.setIdleTimeout(FLOWMOD_DEFAULT_IDLE_TIMEOUT)
        .setHardTimeout(FLOWMOD_DEFAULT_HARD_TIMEOUT)
        .setBufferId(OFPacketOut.BUFFER_ID_NONE)
        .setCookie(cookie)
        .setCommand(flowModCommand)
        .setMatch(match)
        .setActions(actions)
        .setLengthU(OFFlowMod.MINIMUM_LENGTH + OFActionOutput.MINIMUM_LENGTH);

    List<NodePortTuple> switchPortList = route.getPath();

    for (int indx = switchPortList.size() - 1; indx > 0; indx -= 2) {
      // indx and indx-1 will always have the same switch DPID.
      long switchDPID = switchPortList.get(indx).getNodeId();
      IOFSwitch sw = floodlightProvider.getSwitches().get(switchDPID);
      if (sw == null) {
        if (log.isWarnEnabled()) {
          log.warn("Unable to push route, switch at DPID {} " + "not available", switchDPID);
        }
        return srcSwitchIncluded;
      }

      // set the match.
      fm.setMatch(wildcard(match, sw, wildcard_hints));

      // set buffer id if it is the source switch
      if (1 == indx) {
        // Set the flag to request flow-mod removal notifications only
        // for the
        // source switch. The removal message is used to maintain the
        // flow
        // cache. Don't set the flag for ARP messages
        if ((requestFlowRemovedNotifn) && (match.getDataLayerType() != Ethernet.TYPE_ARP)) {
          fm.setFlags(OFFlowMod.OFPFF_SEND_FLOW_REM);
          match.setWildcards(fm.getMatch().getWildcards());
        }
      }

      short outPort = switchPortList.get(indx).getPortId();
      short inPort = switchPortList.get(indx - 1).getPortId();
      // set input and output ports on the switch
      fm.getMatch().setInputPort(inPort);
      ((OFActionOutput) fm.getActions().get(0)).setPort(outPort);

      try {
        counterStore.updatePktOutFMCounterStoreLocal(sw, fm);
        if (log.isTraceEnabled()) {
          log.trace(
              "Pushing Route flowmod routeIndx={} " + "sw={} inPort={} outPort={}",
              new Object[] {indx, sw, fm.getMatch().getInputPort(), outPort});
        }
        messageDamper.write(sw, fm, cntx);
        if (doFlush) {
          sw.flush();
          counterStore.updateFlush();
        }

        // Push the packet out the source switch
        if (sw.getId() == pinSwitch) {
          pushPacket(sw, match, pi, outPort, cntx);
          srcSwitchIncluded = true;
        }
      } catch (IOException e) {
        log.error("Failure writing flow mod", e);
      }

      try {
        fm = fm.clone();
      } catch (CloneNotSupportedException e) {
        log.error("Failure cloning flow mod", e);
      }
    }

    return srcSwitchIncluded;
  }
Beispiel #16
0
  protected void doForwardFlow(IOFSwitch sw, OFPacketIn pi, FloodlightContext cntx) {

    // Setup fields for our packets
    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];
        Long srcCluster = topology.getL2DomainId(srcDap.getSwitchDPID());
        Long dstCluster = topology.getL2DomainId(dstDap.getSwitchDPID());

        int srcVsDest = srcCluster.compareTo(dstCluster);
        if (srcVsDest == 0) {
          if (!srcDap.equals(dstDap) && (srcCluster != null) && (dstCluster != null)) {

            // TODO: INSERT DIJKSTRA HERE FOR OUR VIDEO FLOWS
            // AND CALCULATE FLOWS
            // Call getroute also with weights!!

            Route route =
                getRoute(
                    srcDap.getSwitchDPID(),
                    (short) srcDap.getPort(),
                    dstDap.getSwitchDPID(),
                    (short) dstDap.getPort());

            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,
                  false,
                  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);
    }
  }
  @Override
  public void addedSwitch(IOFSwitch sw) {
    /**
     * Insert static flows on all ports of the switch to redirect DHCP client --> DHCP DHCPServer
     * traffic to the controller. DHCP client's operate on UDP port 67
     */
    OFFlowMod flow = new OFFlowMod();
    OFMatch match = new OFMatch();
    ArrayList<OFAction> actionList = new ArrayList<OFAction>();
    OFActionOutput action = new OFActionOutput();
    String flowName;

    if (sw.getStringId().equals(ROOT_NODE_WIFI_OVS_DPID)) {
      // root node, WiFi bridge, patch to tunnel port
      flow = new OFFlowMod();
      match = new OFMatch();
      match.setInputPort(ROOT_NODE_WIFI_OVS_PATCH);
      action.setType(OFActionType.OUTPUT);
      action.setPort(ROOT_NODE_WIFI_OVS_TUNNEL);
      action.setLength((short) OFActionOutput.MINIMUM_LENGTH);
      actionList.add(action);
      flow.setCookie(0);
      flow.setBufferId(-1);
      flow.setOutPort(ROOT_NODE_WIFI_OVS_TUNNEL);
      flow.setActions(actionList);
      flow.setMatch(match);
      flow.setPriority(PRIORITY_HIGH);
      flow.setLengthU(OFFlowMod.MINIMUM_LENGTH + action.getLengthU());
      flowName = "root-node-wifi-br-patch-tun";
      sfp.addFlow(flowName, flow, sw.getStringId());
      log.info("added flow on SW " + sw.getStringId() + flowName);
      actionList.clear();
      // root node, WiFi bridge, physical to patch
      flow = new OFFlowMod();
      match = new OFMatch();
      match.setInputPort(ROOT_NODE_WIFI_OVS_TUNNEL);
      action.setType(OFActionType.OUTPUT);
      action.setPort(ROOT_NODE_WIFI_OVS_PATCH);
      action.setLength((short) OFActionOutput.MINIMUM_LENGTH);
      actionList.add(action);
      flow.setCookie(0);
      flow.setBufferId(-1);
      flow.setOutPort(ROOT_NODE_WIFI_OVS_PATCH);
      flow.setActions(actionList);
      flow.setMatch(match);
      flow.setPriority(PRIORITY_HIGH);
      flow.setLengthU(OFFlowMod.MINIMUM_LENGTH + action.getLengthU());
      flowName = "root-node-wifi-br-tun-patch";
      sfp.addFlow(flowName, flow, sw.getStringId());
      log.info("added flow on SW " + sw.getStringId() + flowName);
      actionList.clear();
    } else if (sw.getStringId().equals(ROOT_NODE_WIMAX_OVS_DPID)) {
      // root node, WiMAX bridge, patch to physical
      flow = new OFFlowMod();
      match = new OFMatch();
      match.setInputPort(ROOT_NODE_WIMAX_OVS_PATCH);
      action.setType(OFActionType.OUTPUT);
      action.setPort(ROOT_NODE_WIMAX_OVS_VLAN);
      action.setLength((short) OFActionOutput.MINIMUM_LENGTH);
      actionList.add(action);
      flow.setCookie(0);
      flow.setBufferId(-1);
      flow.setOutPort(ROOT_NODE_WIMAX_OVS_VLAN);
      flow.setActions(actionList);
      flow.setMatch(match);
      flow.setPriority(PRIORITY_HIGH);
      flow.setLengthU(OFFlowMod.MINIMUM_LENGTH + action.getLengthU());
      flowName = "root-node-wimax-br-patch-phys";
      sfp.addFlow(flowName, flow, sw.getStringId());
      log.info("added flow on SW " + sw.getStringId() + flowName);
      actionList.clear();
      // root node, WiMAX bridge, interface to patch
      flow = new OFFlowMod();
      match = new OFMatch();
      match.setInputPort(ROOT_NODE_WIMAX_OVS_VLAN);
      action.setType(OFActionType.OUTPUT);
      action.setPort(ROOT_NODE_WIMAX_OVS_PATCH);
      action.setLength((short) OFActionOutput.MINIMUM_LENGTH);
      actionList.add(action);
      flow.setCookie(0);
      flow.setBufferId(-1);
      flow.setOutPort(ROOT_NODE_WIMAX_OVS_PATCH);
      flow.setActions(actionList);
      flow.setMatch(match);
      flow.setPriority(PRIORITY_HIGH);
      flow.setLengthU(OFFlowMod.MINIMUM_LENGTH + action.getLengthU());
      flowName = "root-node-wimax-br-phys-patch";
      sfp.addFlow(flowName, flow, sw.getStringId());
      log.info("added flow on SW " + sw.getStringId() + flowName);
      actionList.clear();
      // root node, WiMAX bridge, DHCP on physical
      match.setInputPort(ROOT_NODE_WIMAX_OVS_VLAN);
      match.setDataLayerType(Ethernet.TYPE_IPv4);
      match.setNetworkProtocol(IPv4.PROTOCOL_UDP);
      match.setTransportSource(UDP.DHCP_CLIENT_PORT);
      action.setType(OFActionType.OUTPUT);
      action.setLength((short) OFActionOutput.MINIMUM_LENGTH);
      action.setPort(OFPort.OFPP_CONTROLLER.getValue());
      actionList.add(action);
      flow.setCookie(0);
      flow.setBufferId(-1);
      flow.setOutPort(OFPort.OFPP_CONTROLLER.getValue());
      flow.setActions(actionList);
      flow.setMatch(match);
      flow.setPriority(PRIORITY_MAX);
      flow.setLengthU(OFFlowMod.MINIMUM_LENGTH + action.getLengthU());
      flowName = "root-node-wimax-br-DHCP-phys";
      sfp.addFlow(flowName, flow, sw.getStringId());
      log.info("added flow on SW " + sw.getStringId() + flowName);
      actionList.clear();
    } else if (sw.getStringId().equals(ROOT_NODE_ROOT_OVS_DPID)) {
      // root node, root bridge, patch AP3 (WiFi) to Linux
      flow = new OFFlowMod();
      match = new OFMatch();
      match.setInputPort(ROOT_NODE_ROOT_OVS_WIFI_PATCH);
      action.setType(OFActionType.OUTPUT);
      action.setPort(OFPort.OFPP_LOCAL.getValue());
      action.setLength((short) OFActionOutput.MINIMUM_LENGTH);
      actionList.add(action);
      flow.setCookie(0);
      flow.setBufferId(-1);
      flow.setOutPort(OFPort.OFPP_LOCAL.getValue());
      flow.setActions(actionList);
      flow.setMatch(match);
      flow.setPriority(PRIORITY_HIGH);
      flow.setLengthU(OFFlowMod.MINIMUM_LENGTH + action.getLengthU());
      flowName = "root-node-root-br-patchWiFi-linux";
      sfp.addFlow(flowName, flow, sw.getStringId());
      log.info("added flow on SW " + sw.getStringId() + flowName);
      actionList.clear();
      // root node, root bridge, patch WiMAX to Linux
      flow = new OFFlowMod();
      match = new OFMatch();
      match.setInputPort(ROOT_NODE_ROOT_OVS_WIMAX_PATCH);
      action.setType(OFActionType.OUTPUT);
      action.setPort(OFPort.OFPP_LOCAL.getValue());
      action.setLength((short) OFActionOutput.MINIMUM_LENGTH);
      actionList.add(action);
      flow.setCookie(0);
      flow.setBufferId(-1);
      flow.setOutPort(OFPort.OFPP_LOCAL.getValue());
      flow.setActions(actionList);
      flow.setMatch(match);
      flow.setPriority(PRIORITY_HIGH);
      flow.setLengthU(OFFlowMod.MINIMUM_LENGTH + action.getLengthU());
      flowName = "root-node-root-br-patchWiMAX-linux";
      sfp.addFlow(flowName, flow, sw.getStringId());
      log.info("added flow on SW " + sw.getStringId() + flowName);
      actionList.clear();
      // root node, root bridge, physical to Linux
      // flow = new OFFlowMod();
      // match = new OFMatch();
      // match.setInputPort((short) 1);
      // action.setType(OFActionType.OUTPUT);
      // action.setPort(OFPort.OFPP_LOCAL.getValue());
      // action.setLength((short) OFActionOutput.MINIMUM_LENGTH);
      // actionList.add(action);
      // flow.setCookie(0);
      // flow.setBufferId(-1);
      // flow.setOutPort(OFPort.OFPP_LOCAL.getValue());
      // flow.setActions(actionList);
      // flow.setMatch(match);
      // flow.setPriority(PRIORITY_HIGH);
      // flow.setLengthU(OFFlowMod.MINIMUM_LENGTH + action.getLengthU());
      // flowName = "root-ovs-root-br-phys-linux";
      // sfp.addFlow(flowName, flow, sw.getStringId());
      // log.info("added flow on SW " + sw.getStringId() + flowName);
      // actionList.clear();
      // root node, root bridge, Linux to physical (match extra: src-ip of root node...i.e. it's
      // outbound)
      // flow = new OFFlowMod();
      // match = new OFMatch();
      // match.setInputPort(OFPort.OFPP_LOCAL.getValue());
      // match.setDataLayerType(Ethernet.TYPE_IPv4); // ... IP packets ... required for a match on
      // an IP address
      // match.setNetworkSource(ROOT_NODE_ROOT_OVS_IP);
      // action.setType(OFActionType.OUTPUT);
      // action.setPort((short) 1);
      // action.setLength((short) OFActionOutput.MINIMUM_LENGTH);
      // actionList.add(action);
      // flow.setCookie(0);
      // flow.setBufferId(-1);
      // flow.setOutPort((short) 1);
      // flow.setActions(actionList);
      // flow.setMatch(match);
      // flow.setPriority(PRIORITY_HIGH);
      // flow.setLengthU(OFFlowMod.MINIMUM_LENGTH + action.getLengthU());
      // flowName = "root-ovs-root-br-linux-phys-egress";
      // sfp.addFlow(flowName, flow, sw.getStringId());
      // log.info("added flow on SW " + sw.getStringId() + flowName);
      // actionList.clear();
    } else if (sw.getStringId().equals(WIFI_NODE_WIFI_OVS_DPID)) {
      // WiFi node, WiFi bridge, physical to patch
      flow = new OFFlowMod();
      match = new OFMatch();
      match.setInputPort((short) 1);
      action.setType(OFActionType.OUTPUT);
      action.setPort(WIFI_NODE_WIFI_OVS_PATCH);
      action.setLength((short) OFActionOutput.MINIMUM_LENGTH);
      actionList.add(action);
      flow.setCookie(0);
      flow.setBufferId(-1);
      flow.setOutPort(WIFI_NODE_WIFI_OVS_PATCH);
      flow.setActions(actionList);
      flow.setMatch(match);
      flow.setPriority(PRIORITY_HIGH);
      flow.setLengthU(OFFlowMod.MINIMUM_LENGTH + action.getLengthU());
      flowName = "wifi-node-wifi-br-phys-patch";
      sfp.addFlow(flowName, flow, sw.getStringId());
      log.info("added flow on SW " + sw.getStringId() + flowName);
      actionList.clear();
      // WiFi node, WiFi bridge, patch to physical
      flow = new OFFlowMod();
      match = new OFMatch();
      match.setInputPort(WIFI_NODE_WIFI_OVS_PATCH);
      action.setType(OFActionType.OUTPUT);
      action.setPort((short) 1);
      action.setLength((short) OFActionOutput.MINIMUM_LENGTH);
      actionList.add(action);
      flow.setCookie(0);
      flow.setBufferId(-1);
      flow.setOutPort((short) 1);
      flow.setActions(actionList);
      flow.setMatch(match);
      flow.setPriority(PRIORITY_HIGH);
      flow.setLengthU(OFFlowMod.MINIMUM_LENGTH + action.getLengthU());
      flowName = "wifi-node-wifi-br-patch-phys";
      sfp.addFlow(flowName, flow, sw.getStringId());
      log.info("added flow on SW " + sw.getStringId() + flowName);
      actionList.clear();
      // root node, WiMAX bridge, DHCP on physical
      match.setInputPort((short) 1);
      match.setDataLayerType(Ethernet.TYPE_IPv4);
      match.setNetworkProtocol(IPv4.PROTOCOL_UDP);
      match.setTransportSource(UDP.DHCP_CLIENT_PORT);
      action.setType(OFActionType.OUTPUT);
      action.setLength((short) OFActionOutput.MINIMUM_LENGTH);
      action.setPort(OFPort.OFPP_CONTROLLER.getValue());
      actionList.add(action);
      flow.setCookie(0);
      flow.setBufferId(-1);
      flow.setOutPort(OFPort.OFPP_CONTROLLER.getValue());
      flow.setActions(actionList);
      flow.setMatch(match);
      flow.setPriority(PRIORITY_MAX);
      flow.setLengthU(OFFlowMod.MINIMUM_LENGTH + action.getLengthU());
      flowName = "wifi-node-wifi-br-DHCP-phys";
      sfp.addFlow(flowName, flow, sw.getStringId());
      log.info("added flow on SW " + sw.getStringId() + flowName);
      actionList.clear();
    } else if (sw.getStringId().equals(WIFI_NODE_TUNNEL_OVS_DPID)) {
      // WiFi node, tunnel bridge, tunnel to patch
      flow = new OFFlowMod();
      match = new OFMatch();
      match.setInputPort(WIFI_NODE_TUNNEL_OVS_TUNNEL);
      action.setType(OFActionType.OUTPUT);
      action.setPort(WIFI_NODE_TUNNEL_OVS_PATCH);
      action.setLength((short) OFActionOutput.MINIMUM_LENGTH);
      actionList.add(action);
      flow.setCookie(0);
      flow.setBufferId(-1);
      flow.setOutPort(WIFI_NODE_TUNNEL_OVS_PATCH);
      flow.setActions(actionList);
      flow.setMatch(match);
      flow.setPriority(PRIORITY_HIGH);
      flow.setLengthU(OFFlowMod.MINIMUM_LENGTH + action.getLengthU());
      flowName = "wifi-node-tunnel-br-tun-patch";
      sfp.addFlow(flowName, flow, sw.getStringId());
      log.info("added flow on SW " + sw.getStringId() + flowName);
      actionList.clear();
      // WiFi node, tunnel bridge, patch to tunnel
      flow = new OFFlowMod();
      match = new OFMatch();
      match.setInputPort(WIFI_NODE_TUNNEL_OVS_PATCH);
      action.setType(OFActionType.OUTPUT);
      action.setPort(WIFI_NODE_TUNNEL_OVS_TUNNEL);
      action.setLength((short) OFActionOutput.MINIMUM_LENGTH);
      actionList.add(action);
      flow.setCookie(0);
      flow.setBufferId(-1);
      flow.setOutPort(WIFI_NODE_TUNNEL_OVS_TUNNEL);
      flow.setActions(actionList);
      flow.setMatch(match);
      flow.setPriority(PRIORITY_HIGH);
      flow.setLengthU(OFFlowMod.MINIMUM_LENGTH + action.getLengthU());
      flowName = "wifi-node-tunnel-br-patch-tun";
      sfp.addFlow(flowName, flow, sw.getStringId());
      log.info("added flow on SW " + sw.getStringId() + flowName);
      actionList.clear();
    }
  }