예제 #1
0
  @Override
  public List<String> listDevices() {
    FVLog.log(LogLevel.DEBUG, null, "API listDevices() by: " + APIUserCred.getUserName());
    FlowVisor fv = FlowVisor.getInstance();
    // get list from main flowvisor instance
    List<String> dpids = new ArrayList<String>();
    String dpidStr;

    /*
     * if (TopologyController.isConfigured()) { for (Long dpid :
     * TopologyController.getRunningInstance() .listDevices()) { dpidStr =
     * HexString.toHexString(dpid); if (!dpids.contains(dpidStr))
     * dpids.add(dpidStr); else FVLog.log(LogLevel.WARN, TopologyController
     * .getRunningInstance(), "duplicate dpid detected: " + dpidStr); } }
     * else {
     */
    // only list a device is we have a features reply for it
    for (FVEventHandler handler : fv.getHandlersCopy()) {
      if (handler instanceof FVClassifier) {
        OFFeaturesReply featuresReply = ((FVClassifier) handler).getSwitchInfo();
        if (featuresReply != null) {
          dpidStr = FlowSpaceUtil.dpidToString(featuresReply.getDatapathId());
          if (!dpids.contains(dpidStr)) dpids.add(dpidStr);
          else FVLog.log(LogLevel.WARN, handler, "duplicate dpid detected: " + dpidStr);
        }
      }
    }
    // }
    return dpids;
  }
예제 #2
0
  @Override
  public String getSliceStats(String sliceName) throws SliceNotFound, PermissionDeniedException {

    if (!(doesSliceExist(sliceName))) {
      throw new SliceNotFound("Slice does not exist: " + sliceName);
    }

    FVSlicer fvSlicer = null;
    for (Iterator<FVEventHandler> it = FlowVisor.getInstance().getHandlersCopy().iterator();
        it.hasNext(); ) {
      FVEventHandler eventHandler = it.next();
      if (eventHandler instanceof FVClassifier) {
        FVClassifier classifier = (FVClassifier) eventHandler;
        if (!classifier.isIdentified()) // only print switches have have
          // been identified
          continue;
        fvSlicer = classifier.getSlicerByName(sliceName);
        if (fvSlicer != null) {
          break;
        }
      }
    }

    if (fvSlicer == null) return SendRecvDropStats.NO_STATS_AVAILABLE_MSG;

    return fvSlicer.getStats().combinedString();
  }
예제 #3
0
 private SlicerLimits getSliceLimits() throws DPIDNotFound {
   for (Iterator<FVEventHandler> it = FlowVisor.getInstance().getHandlersCopy().iterator();
       it.hasNext(); ) {
     FVEventHandler eventHandler = it.next();
     if (eventHandler instanceof FVClassifier) {
       FVClassifier classifier = (FVClassifier) eventHandler;
       return classifier.getSlicerLimits();
     }
   }
   throw new DPIDNotFound("No classifier found, therefore no limits accessible");
 }
예제 #4
0
 /**
  * Returns a valid fvClassifier
  *
  * @param dpid
  * @return never null
  * @throws DPIDNotFound
  */
 private FVClassifier lookupClassifier(long dpid) throws DPIDNotFound {
   for (Iterator<FVEventHandler> it = FlowVisor.getInstance().getHandlersCopy().iterator();
       it.hasNext(); ) {
     FVEventHandler eventHandler = it.next();
     if (eventHandler instanceof FVClassifier) {
       FVClassifier classifier = (FVClassifier) eventHandler;
       if (dpid == classifier.getDPID()) return classifier;
     }
   }
   throw new DPIDNotFound("No such switch: " + dpid);
 }
예제 #5
0
  @Override
  public Map<String, String> getSliceInfo(String sliceName)
      throws PermissionDeniedException, SliceNotFound {

    /*
     * relaxed security -- anyone can read slice info for now String user =
     * APIUserCred.getUserName(); if (!FVConfig.isSupervisor(user) &&
     * !APIAuth.transitivelyCreated(user, sliceName)) throw new
     * PermissionDeniedException(
     * "not superuser or transitive slice creator");
     */
    if (!(doesSliceExist(sliceName))) {
      throw new SliceNotFound("Slice does not exist: " + sliceName);
    }

    HashMap<String, String> map = new HashMap<String, String>();

    synchronized (FVConfig.class) {
      try {
        map.put("contact_email", FVConfig.getSliceEmail(sliceName));
        map.put("controller_hostname", FVConfig.getSliceHost(sliceName));
        map.put("controller_port", String.valueOf(FVConfig.getSlicePort(sliceName)));
        map.put("creator", FVConfig.getSliceCreator(sliceName));
        map.put("drop_policy", FVConfig.getSlicePolicy(sliceName));
      } catch (ConfigError e) {
        FVLog.log(LogLevel.CRIT, null, "malformed slice: " + e);
        e.printStackTrace();
      }
    }
    long dpid;
    int connection = 1;

    // TODO: come back an architect this so we can walk the list of slicers,
    // not the list of classifiers, and then slicers
    for (Iterator<FVEventHandler> it = FlowVisor.getInstance().getHandlersCopy().iterator();
        it.hasNext(); ) {
      FVEventHandler eventHandler = it.next();
      if (eventHandler instanceof FVClassifier) {
        FVClassifier classifier = (FVClassifier) eventHandler;
        if (!classifier.isIdentified()) // only print switches have have
          // been identified
          continue;
        dpid = classifier.getDPID();
        FVSlicer fvSlicer = classifier.getSlicerByName(sliceName);
        if (fvSlicer != null) {
          map.put(
              "connection_" + connection++,
              FlowSpaceUtil.dpidToString(dpid) + "-->" + fvSlicer.getConnectionName());
        }
      }
    }

    return map;
  }
예제 #6
0
  @Override
  public Boolean changeSlice(String sliceName, String key, String value)
      throws MalformedURLException, InvalidSliceName, PermissionDeniedException, InvalidUserInfoKey,
          DuplicateControllerException {
    String changerSlice = APIUserCred.getUserName();
    if (!APIAuth.transitivelyCreated(changerSlice, sliceName)
        && !FVConfig.isSupervisor(changerSlice))
      throw new PermissionDeniedException(
          "Slice " + changerSlice + " does not have perms to change the passwd of " + sliceName);
    /**
     * this is the list of things a user is allowed to change about themselves. Critically, it
     * should not include "creator" string as this would allow security issues.
     */
    try {
      if (key.equals("contact_email")) FVConfig.setSliceContactEmail(sliceName, value);
      else if (key.equals("controller_hostname")) {
        // make sure there isn't already a slice with this hostname and port
        // that this slice uses
        if (isSecondSliceSharingController(sliceName, value, FVConfig.getSlicePort(sliceName))) {
          throw new DuplicateControllerException(
              value, FVConfig.getSlicePort(sliceName), sliceName, "changed");
        }
        FVConfig.setSliceHost(sliceName, value);
      } else if (key.equals("controller_port")) {
        // Make sure that there isn't already a slice on this port that uses
        // the same hostname that this slice uses
        if (isSecondSliceSharingController(
            sliceName, FVConfig.getSliceHost(sliceName), Integer.parseInt(value))) {
          throw new DuplicateControllerException(
              FVConfig.getSliceHost(sliceName), Integer.parseInt(value), sliceName, "changed");
        }

        FVConfig.setSlicePort(sliceName, Integer.valueOf(value));
      } else if (key.equals("drop_policy")) {
        // Set the drop policy when the controller is done,
        // either to an exact match of the packet in or to the
        // flow entry.
        FVConfig.setSliceDropPolicy(sliceName, value);
      } else
        throw new InvalidUserInfoKey(
            "invalid key: "
                + key
                + "-- only contact_email, drop_policy and "
                + "controller_{hostname,port} can be changed");
      FlowVisor.getInstance().checkPointConfig();
    } catch (ConfigError e) {
      // this should probably never happen b/c of above checks
      throw new InvalidUserInfoKey(e.toString());
    }

    return true;
  }
예제 #7
0
 @Override
 public String getSwitchStats(String dpidStr) throws DPIDNotFound, PermissionDeniedException {
   long dpid = FlowSpaceUtil.parseDPID(dpidStr);
   for (Iterator<FVEventHandler> it = FlowVisor.getInstance().getHandlersCopy().iterator();
       it.hasNext(); ) {
     FVEventHandler eventHandler = it.next();
     if (eventHandler instanceof FVClassifier) {
       FVClassifier classifier = (FVClassifier) eventHandler;
       if (classifier.getDPID() == dpid) return classifier.getStats().combinedString();
     }
   }
   throw new DPIDNotFound("dpid not found: " + dpidStr);
 }
예제 #8
0
 /**
  * Change the password for this slice
  *
  * <p>A slice is allowed to change its own password and the password of any slice that it has
  * (transitively) created
  *
  * @param sliceName
  * @param newPasswd
  */
 @Override
 public Boolean changePasswd(String sliceName, String newPasswd) throws PermissionDeniedException {
   String changerSlice = APIUserCred.getUserName();
   if (!APIAuth.transitivelyCreated(changerSlice, sliceName)
       && !FVConfig.isSupervisor(changerSlice))
     throw new PermissionDeniedException(
         "Slice " + changerSlice + " does not have perms to change the passwd of " + sliceName);
   String salt = APIAuth.getSalt();
   String crypt = APIAuth.makeCrypt(salt, newPasswd);
   sliceName = FVConfig.sanitize(sliceName);
   // set passwd is synchronized
   FVConfig.setPasswd(sliceName, salt, crypt);
   FlowVisor.getInstance().checkPointConfig();
   return true;
 }
예제 #9
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);
  }
예제 #10
0
  @Override
  public Boolean deleteSlice(String sliceName)
      throws SliceNotFound, PermissionDeniedException, ConfigError {
    String changerSlice = APIUserCred.getUserName();
    if (!APIAuth.transitivelyCreated(changerSlice, sliceName)) {
      FVLog.log(
          LogLevel.WARN,
          null,
          "API deletSlice(" + sliceName + ") failed by: " + APIUserCred.getUserName());
      throw new PermissionDeniedException(
          "Slice " + changerSlice + " does not have perms to change the passwd of " + sliceName);
    }
    synchronized (FVConfig.class) {
      FVLog.log(
          LogLevel.DEBUG,
          null,
          "API removeSlice(" + sliceName + ") by: " + APIUserCred.getUserName());
      FlowMap flowSpace = FlowSpaceUtil.deleteFlowSpaceBySlice(sliceName);
      try {
        // this is also synchronized against FVConfig.class
        FVConfig.deleteSlice(sliceName);
      } catch (Exception e) {
        throw new SliceNotFound("slice does not exist: " + sliceName);
      }

      /*
       * We need to do this because of the linear flowmap, because
       * it wants the slicers and classifiers to update their
       * view of the flowspace.
       * Once linearflowmap is dropped, this should be dropped as
       * well.
       *
       * FIXME
       */
      FlowSpaceImpl.getProxy().notifyChange(flowSpace);
      // FVConfig.sendUpdates(FVConfig.FLOWSPACE);
      // signal that FS has changed
      FlowVisor.getInstance().checkPointConfig();
    }
    return true;
  }
예제 #11
0
 /*
  * (non-Javadoc)
  *
  * @see org.flowvisor.api.FVUserAPI#getDeviceInfo()
  */
 @Override
 public Map<String, String> getDeviceInfo(String dpidStr) throws DPIDNotFound {
   Map<String, String> map = new HashMap<String, String>();
   long dpid = HexString.toLong(dpidStr);
   FVClassifier fvClassifier = null;
   for (FVEventHandler handler : FlowVisor.getInstance().getHandlersCopy()) {
     if (handler instanceof FVClassifier) {
       OFFeaturesReply featuresReply = ((FVClassifier) handler).getSwitchInfo();
       if (featuresReply != null && featuresReply.getDatapathId() == dpid) {
         fvClassifier = (FVClassifier) handler;
         break;
       }
     }
   }
   if (fvClassifier == null)
     throw new DPIDNotFound("dpid does not exist: " + dpidStr + " ::" + String.valueOf(dpid));
   OFFeaturesReply config = fvClassifier.getSwitchInfo();
   map.put("dpid", FlowSpaceUtil.dpidToString(dpid));
   if (config != null) {
     map.put("nPorts", String.valueOf(config.getPorts().size()));
     String portList = "";
     String portNames = "";
     int p;
     for (Iterator<OFPhysicalPort> it = config.getPorts().iterator(); it.hasNext(); ) {
       OFPhysicalPort port = it.next();
       p = U16.f(port.getPortNumber());
       portList += p;
       portNames += port.getName() + "(" + p + ")";
       if (it.hasNext()) {
         portList += ",";
         portNames += ",";
       }
     }
     map.put("portList", portList);
     map.put("portNames", portNames);
   } else {
     FVLog.log(LogLevel.WARN, null, "null config for: " + dpidStr);
   }
   map.put("remote", String.valueOf(fvClassifier.getConnectionName()));
   return map;
 }
예제 #12
0
 @Override
 public Collection<Map<String, String>> getSwitchFlowDB(String dpidStr) throws DPIDNotFound {
   boolean found = false;
   long dpid = FlowSpaceUtil.parseDPID(dpidStr);
   List<Map<String, String>> ret = new LinkedList<Map<String, String>>();
   for (Iterator<FVEventHandler> it = FlowVisor.getInstance().getHandlersCopy().iterator();
       it.hasNext(); ) {
     FVEventHandler eventHandler = it.next();
     if (eventHandler instanceof FVClassifier) {
       FVClassifier classifier = (FVClassifier) eventHandler;
       if (dpid == classifier.getDPID() || dpid == FlowEntry.ALL_DPIDS) {
         synchronized (classifier) {
           for (Iterator<FlowDBEntry> it2 = classifier.getFlowDB().iterator(); it2.hasNext(); ) {
             ret.add(it2.next().toBracketMap());
           }
         }
         found = true;
       }
     }
   }
   if (!found) throw new DPIDNotFound("dpid not found: " + dpidStr);
   return ret;
 }
예제 #13
0
  /**
   * Create a new slice (without flowspace)
   *
   * <p>Slices that contain the field separator are rewritten with underscores
   *
   * @param sliceName Cannot contain FVConfig.FS == '!'
   * @param passwd Cleartext! FIXME
   * @param controller_url Reference controller pseudo-url, e.g., tcp:hostname[:port]
   * @param slice_email As a contract for the slice
   * @return success
   * @throws InvalidSliceName
   * @throws PermissionDeniedException
   * @throws DuplicateControllerException
   */
  @Override
  public Boolean createSlice(
      String sliceName,
      String passwd,
      String controller_url,
      String drop_policy,
      String slice_email)
      throws MalformedControllerURL, InvalidSliceName, InvalidDropPolicy, PermissionDeniedException,
          DuplicateControllerException {
    // FIXME: make sure this user has perms to do this OP
    // for now, all slices can create other slices
    // FIXME: for now, only handle tcp, not ssl controller url
    String[] list = controller_url.split(":");
    if (!FVConfig.isSupervisor(APIUserCred.getUserName()))
      throw new PermissionDeniedException("only superusers can create new slices");
    if (list.length < 2)
      throw new MalformedControllerURL(
          "controller url needs to be of the form "
              + "proto:hostname[:port], e.g., tcp:yourhost.foo.com:6633, not: "
              + controller_url);
    if (!list[0].equals("tcp"))
      throw new MalformedControllerURL(
          "Flowvisor currently only supports 'tcp' proto, not: " + list[0]);
    int controller_port;
    if (list.length >= 3) controller_port = Integer.valueOf(list[2]);
    else controller_port = FVConfig.OFP_TCP_PORT;
    // createSlice is synchronized()

    if (drop_policy.equals("")) drop_policy = "exact";
    else if (!drop_policy.equals("exact") && !drop_policy.equals("rule"))
      throw new InvalidDropPolicy(
          "Flowvisor currently supports an 'exact'" + " or a 'rule' based drop policy");

    // We need to make sure this slice doesn't already exist
    List<String> slices = null;
    synchronized (FVConfig.class) {
      try {
        slices = FVConfig.getAllSlices();
      } catch (ConfigError e) {
        e.printStackTrace();
        throw new RuntimeException("no SLICES subdir found in config");
      }
      for (Iterator<String> sliceIter = slices.iterator(); sliceIter.hasNext(); ) {
        String existingSlice = sliceIter.next();
        if (sliceName.equals(existingSlice)) {
          throw new PermissionDeniedException("Cannot create slice with existing name.");
        }
      }
    }

    FVConfig.createSlice(
        sliceName,
        list[1],
        controller_port,
        drop_policy,
        passwd,
        slice_email,
        APIUserCred.getUserName());
    FlowVisor.getInstance().checkPointConfig();
    return true;
  }