Ejemplo n.º 1
0
  /**
   * Step through all of the partially computed results, compute the intersections and remove the
   * intersections by priority.
   *
   * <p>Could be O(n^2) in worst case, but we expect that intersections are rare (?)
   *
   * <p>Uses the fact that the order of the list is also the priority order
   *
   * <p>FIXME :: come back and make this faster
   *
   * @param mergeList List of all FlowEntry's from matches(), including overlaps.
   * @return A pruned list of just the non-completely-overlapping matches
   */
  List<FlowIntersect> priorityMerge(List<FlowIntersect> mergeList) {
    List<FlowIntersect> results = new ArrayList<FlowIntersect>();
    boolean eclipsed;
    MatchType matchType;
    results.add(mergeList.get(0));
    mergeList.remove(0);

    for (FlowIntersect merge : mergeList) {
      eclipsed = false;
      for (FlowIntersect result : results) {
        /*
         * is this new match eclipsed by previous entries?
         *
         * with each successive matches() call, the part that over laps
         * result is removed, so that if a merge rule is not fully
         * eclipsed by any one result, but is fully eclipsed by a sum of
         * results, we will catch that to
         */
        FlowIntersect tmpIntersect =
            merge.getFlowEntry().matches(result.getDpid(), result.getMatch());
        matchType = tmpIntersect.getMatchType();

        if ((matchType == MatchType.EQUAL) || (matchType == MatchType.SUPERSET)) {
          eclipsed = true;
          break;
        } else if (matchType == MatchType.SUBSET) {
          merge = tmpIntersect; // then update with the intersection
        }
        // note: if matchtype == NONE, then tmpIntersect.getMatch() is
        // undefined
      }
      if (!eclipsed) // add this match to the list iff it's
      results.add(merge); // not complete eclipsed by something before
      // it
    }
    return results;
  }
Ejemplo n.º 2
0
  /**
   * This is called when a controller issues a FlowMod. The goal here is to rewrite flowmods so that
   * they guarantee traffic isolation between slices. A flowmod is rewritten following these rules:
   *
   * <p>1. Its field is wildcarded, then for every potentially matching rule we rewrite the field
   * with the value in the rule.
   *
   * <p>2. Its field is specified, then leave it untouched, but use it for matching purposes.
   *
   * <p>3. We have a potential partial match: 3.1. The field and the flowrule field do not overlap,
   * return no match. 3.2. The fields overlap, return the smallest possible intersection of the two.
   *
   * <p>Currently rule 3 only applies to IP addresses, but this could change in the future.
   *
   * @param dpid - The dpid this flowmod is directed to, could be wildcarded.
   * @param match - The set of field modifications issued by this flowmod.
   * @return a list of intersections (ie. flowmod rewrites) created by the flowmod issued from the
   *     controller.
   */
  public List<FlowIntersect> intersect(long dpid, FVMatch match) {
    FVLog.log(LogLevel.DEBUG, null, "dpid: ", dpid, " match: ", match.toString());
    BitSet set = new BitSet();
    normalize(match);
    int wildcards = match.getWildcards();
    TreeSet<FlowIntersect> ret = new TreeSet<FlowIntersect>();
    HashMap<Integer, FlowIntersect> intersections = new HashMap<Integer, FlowIntersect>();
    HashMap<Integer, Pair<Boolean, BitSet>> rewrites =
        new HashMap<Integer, Pair<Boolean, BitSet>>();

    set.or(allRules);

    try {

      testEmpty(set, dpids, dpid, FlowEntry.ALL_DPIDS, wildcards, 0);

      rewrites.put(
          FVMatch.OFPFW_IN_PORT,
          new Pair<Boolean, BitSet>(
              testEmpty(
                  set, port, match.getInputPort(), ANY_IN_PORT, wildcards, FVMatch.OFPFW_IN_PORT),
              set));

      rewrites.put(
          FVMatch.OFPFW_DL_SRC,
          new Pair<Boolean, BitSet>(
              testEmpty(
                  set,
                  dl_src,
                  FVMatch.toLong(match.getDataLayerSource()),
                  ANY_MAC,
                  wildcards,
                  FVMatch.OFPFW_DL_SRC),
              set));

      rewrites.put(
          FVMatch.OFPFW_DL_DST,
          new Pair<Boolean, BitSet>(
              testEmpty(
                  set,
                  dl_dst,
                  FVMatch.toLong(match.getDataLayerDestination()),
                  ANY_MAC,
                  wildcards,
                  FVMatch.OFPFW_DL_DST),
              set));

      rewrites.put(
          FVMatch.OFPFW_DL_VLAN,
          new Pair<Boolean, BitSet>(
              testEmpty(
                  set,
                  vlan,
                  (int) match.getDataLayerVirtualLan(),
                  (int) ANY_VLAN_ID,
                  wildcards,
                  FVMatch.OFPFW_DL_VLAN),
              set));

      rewrites.put(
          FVMatch.OFPFW_DL_VLAN_PCP,
          new Pair<Boolean, BitSet>(
              testEmpty(
                  set,
                  vlan,
                  match.getDataLayerVirtualLanPriorityCodePoint() << 16,
                  ANY_VLAN_PCP << 16,
                  wildcards,
                  FVMatch.OFPFW_DL_VLAN_PCP),
              set));
      rewrites.put(
          FVMatch.OFPFW_DL_TYPE,
          new Pair<Boolean, BitSet>(
              testEmpty(
                  set,
                  dl_type,
                  match.getDataLayerType(),
                  ANY_ETHER,
                  wildcards,
                  FVMatch.OFPFW_DL_TYPE),
              set));

      rewrites.put(
          FVMatch.OFPFW_NW_PROTO,
          new Pair<Boolean, BitSet>(
              testEmpty(
                  set,
                  nw,
                  (short) match.getNetworkProtocol(),
                  (short) ANY_NW_PROTO_TOS,
                  wildcards,
                  FVMatch.OFPFW_NW_PROTO),
              set));

      rewrites.put(
          FVMatch.OFPFW_NW_TOS,
          new Pair<Boolean, BitSet>(
              testEmpty(
                  set,
                  nw,
                  (short) (match.getNetworkTypeOfService() << 8),
                  (short) (ANY_NW_PROTO_TOS << 8),
                  wildcards,
                  FVMatch.OFPFW_NW_TOS),
              set));

      rewrites.put(
          FVMatch.OFPFW_TP_SRC,
          new Pair<Boolean, BitSet>(
              testEmpty(
                  set,
                  tp,
                  (int) match.getTransportSource(),
                  (int) ANY_TP,
                  wildcards,
                  FVMatch.OFPFW_TP_SRC),
              set));

      rewrites.put(
          FVMatch.OFPFW_TP_DST,
          new Pair<Boolean, BitSet>(
              testEmpty(
                  set,
                  tp,
                  match.getTransportDestination() << 16,
                  ANY_TP << 16,
                  wildcards,
                  FVMatch.OFPFW_TP_DST),
              set));

      int field = 0;
      boolean rewrite = false;
      BitSet inters = null;
      FlowIntersect flow = null;
      FlowEntry rule = null;

      for (Entry<Integer, Pair<Boolean, BitSet>> entry : rewrites.entrySet()) {
        field = entry.getKey();
        rewrite = entry.getValue().getFirst();
        inters = entry.getValue().getSecond();
        FVLog.log(LogLevel.DEBUG, null, "Rule ids which intersect: ", inters.toString());
        for (int i = inters.nextSetBit(0); i >= 0; i = inters.nextSetBit(i + 1)) {
          rule = rules.get(i).clone();
          flow = getIntersect(rule, intersections);

          if (!rewrite) {
            rule.setRuleMatch(match);
            setField(flow, rule.getRuleMatch(), field);
          }

          FVMatch ruleMatch = rules.get(i).getRuleMatch();
          FlowIntersect inter = flow;
          FVMatch interMatch = inter.getMatch();
          interMatch.setNetworkDestination(
              testIP(
                  inter,
                  FVMatch.OFPFW_NW_DST_SHIFT,
                  match.getNetworkDestinationMaskLen(),
                  ruleMatch.getNetworkDestinationMaskLen(),
                  match.getNetworkDestination(),
                  ruleMatch.getNetworkDestination()));
          if (inter.getMatchType() == MatchType.NONE) continue;

          interMatch.setNetworkSource(
              testIP(
                  inter,
                  FVMatch.OFPFW_NW_SRC_SHIFT,
                  match.getNetworkSourceMaskLen(),
                  ruleMatch.getNetworkSourceMaskLen(),
                  match.getNetworkSource(),
                  ruleMatch.getNetworkSource()));
          if (inter.getMatchType() == MatchType.NONE) continue;
          intersections.put(flow.getFlowEntry().getId(), flow);
        }
      }

      /*
       * Need to resolve intersection by priority.
       *
       * In the worst case this will be O(n) where n is the number of
       * rules. But in average we will only have a small subset of the
       * rules. Right??
       */
      ret.addAll(intersections.values());
      FVLog.log(LogLevel.DEBUG, null, "Intersections: ", intersections);

    } catch (NoMatch e) {
      FVLog.log(LogLevel.FATAL, null, "Failed to intersect flow mod " + match);
      return new ArrayList<FlowIntersect>(ret);
    } catch (UnknownMatchField umf) {
      FVLog.log(LogLevel.FATAL, null, umf.getMessage());
    }

    return new ArrayList<FlowIntersect>(ret);
  }