示例#1
0
  /**
   * Push routes from back to front
   *
   * @param route Route to push
   * @param match OpenFlow fields to match on
   * @param srcSwPort Source switch port for the first hop
   * @param dstSwPort Destination switch port for final hop
   * @param cookie The cookie to set in each flow_mod
   * @param cntx The floodlight context
   * @param reqeustFlowRemovedNotifn if set to true then the switch would send a flow mod removal
   *     notification when the flow mod expires
   * @param doFlush if set to true then the flow mod would be immediately written to the switch
   * @param flowModCommand flow mod. command to use, e.g. OFFlowMod.OFPFC_ADD,
   *     OFFlowMod.OFPFC_MODIFY etc.
   * @return srcSwitchIincluded True if the source switch is included in this route
   */
  @LogMessageDocs({
    @LogMessageDoc(
        level = "WARN",
        message = "Unable to push route, switch at DPID {dpid} not available",
        explanation = "A switch along the calculated path for the " + "flow has disconnected.",
        recommendation = LogMessageDoc.CHECK_SWITCH),
    @LogMessageDoc(
        level = "ERROR",
        message = "Failure writing flow mod",
        explanation = "An I/O error occurred while writing a " + "flow modification to a switch",
        recommendation = LogMessageDoc.CHECK_SWITCH)
  })
  public boolean pushRoute(
      Route route,
      OFMatch match,
      Integer wildcard_hints,
      OFPacketIn pi,
      long pinSwitch,
      long cookie,
      FloodlightContext cntx,
      boolean reqeustFlowRemovedNotifn,
      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 - TODO generalize check
        if ((reqeustFlowRemovedNotifn) && (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) {
          // TODO: Instead of doing a packetOut here we could also
          // send a flowMod with bufferId set....
          pushPacket(sw, pi, false, 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;
  }