/**
     * Add the typed flow entry into table, and calculates and set the flow live type, and then add
     * it into a corresponding typed flow table.
     *
     * @param rule the flow rule
     */
    public synchronized void addWithCalAndSetFlowLiveType(TypedStoredFlowEntry rule) {
      checkNotNull(rule);

      // rule have to be new DefaultTypedFlowEntry
      boolean result = getFlowEntriesInternal(rule.id()).add(rule);
      if (result) {
        calAndSetFlowLiveTypeInternal(rule);
        addWithSetFlowLiveTypeCount++;
      } else {
        log.debug(
            "addWithCalAndSetFlowLiveType, FlowId="
                + Long.toHexString(rule.id().value())
                + " ADD Failed, cause it may already exists in table !!!,"
                + " AdaptiveStats collection thread for {}",
            sw.getStringId());
      }
    }
    /**
     * Add typed flow entry into table only.
     *
     * @param rule the flow rule
     */
    public synchronized void add(TypedStoredFlowEntry rule) {
      checkNotNull(rule);

      // rule have to be new DefaultTypedFlowEntry
      boolean result = getFlowEntriesInternal(rule.id()).add(rule);

      if (result) {
        addCount++;
      }
    }
Example #3
0
  /**
   * Returns current typed flow entry's polling interval.
   *
   * @param tfe typed flow entry
   */
  public static long typedPollInterval(TypedStoredFlowEntry tfe) {
    checkNotNull(tfe, "TypedStoredFlowEntry cannot be null");

    switch (tfe.flowLiveType()) {
      case LONG_FLOW:
        return LONG_POLL_INTERVAL;
      case MID_FLOW:
        return MID_POLL_INTERVAL;
      case SHORT_FLOW:
      case IMMEDIATE_FLOW:
      default:
        return CAL_AND_POLL_INTERVAL;
    }
  }
 // Remove the typed flow entry from corresponding table
 private void removeLiveFlowsInternal(TypedStoredFlowEntry fe) {
   switch (fe.flowLiveType()) {
     case IMMEDIATE_FLOW:
       // do nothing
       break;
     case SHORT_FLOW:
       shortFlows.remove(fe);
       break;
     case MID_FLOW:
       midFlows.remove(fe);
       break;
     case LONG_FLOW:
       longFlows.remove(fe);
       break;
     default: // error in Flow Live Type
       log.error("removeLiveFlowsInternal, Unknown Live Type error!");
       break;
   }
 }
    // In real, calculates and set the flow live type at the first time,
    // and then add it into a corresponding typed flow table
    private void calAndSetFlowLiveTypeInternal(TypedStoredFlowEntry rule) {
      long life = rule.life();
      FlowLiveType prevFlowLiveType = rule.flowLiveType();

      if (life >= longPollInterval) {
        rule.setFlowLiveType(FlowLiveType.LONG_FLOW);
        longFlows.add(rule);
      } else if (life >= midPollInterval) {
        rule.setFlowLiveType(FlowLiveType.MID_FLOW);
        midFlows.add(rule);
      } else if (life >= calAndPollInterval) {
        rule.setFlowLiveType(FlowLiveType.SHORT_FLOW);
        shortFlows.add(rule);
      } else if (life >= 0) {
        rule.setFlowLiveType(FlowLiveType.IMMEDIATE_FLOW);
      } else { // life < 0
        rule.setFlowLiveType(FlowLiveType.UNKNOWN_FLOW);
      }

      if (rule.flowLiveType() != prevFlowLiveType) {
        switch (prevFlowLiveType) {
            // delete it from previous flow table
          case SHORT_FLOW:
            shortFlows.remove(rule);
            break;
          case MID_FLOW:
            midFlows.remove(rule);
            break;
          case LONG_FLOW:
            longFlows.remove(rule);
            break;
          default:
            break;
        }
      }
    }
    // check the flow live type based on current time, then set and add it into corresponding table
    private boolean checkAndMoveLiveFlowInternal(TypedStoredFlowEntry fe, long cTime) {
      long curTime = (cTime > 0 ? cTime : System.currentTimeMillis());
      // For latency adjustment(default=500 millisecond) between FlowStatsRequest and Reply
      long fromLastSeen =
          ((curTime - fe.lastSeen() + latencyFlowStatsRequestAndReplyMillis) / 1000);
      // fe.life() unit is SECOND!
      long liveTime = fe.life() + fromLastSeen;

      switch (fe.flowLiveType()) {
        case IMMEDIATE_FLOW:
          if (liveTime >= longPollInterval) {
            fe.setFlowLiveType(FlowLiveType.LONG_FLOW);
            longFlows.add(fe);
          } else if (liveTime >= midPollInterval) {
            fe.setFlowLiveType(FlowLiveType.MID_FLOW);
            midFlows.add(fe);
          } else if (liveTime >= calAndPollInterval) {
            fe.setFlowLiveType(FlowLiveType.SHORT_FLOW);
            shortFlows.add(fe);
          }
          break;
        case SHORT_FLOW:
          if (liveTime >= longPollInterval) {
            fe.setFlowLiveType(FlowLiveType.LONG_FLOW);
            shortFlows.remove(fe);
            longFlows.add(fe);
          } else if (liveTime >= midPollInterval) {
            fe.setFlowLiveType(FlowLiveType.MID_FLOW);
            shortFlows.remove(fe);
            midFlows.add(fe);
          }
          break;
        case MID_FLOW:
          if (liveTime >= longPollInterval) {
            fe.setFlowLiveType(FlowLiveType.LONG_FLOW);
            midFlows.remove(fe);
            longFlows.add(fe);
          }
          break;
        case LONG_FLOW:
          if (fromLastSeen > entirePollInterval) {
            log.trace("checkAndMoveLiveFlowInternal, flow is already removed at switch.");
            return false;
          }
          break;
        case UNKNOWN_FLOW: // Unknown flow is an internal error flow type, just fall through
        default:
          // Error Unknown Live Type
          log.error(
              "checkAndMoveLiveFlowInternal, Unknown Live Type error!"
                  + "AdaptiveStats collection thread for {}",
              sw.getStringId());
          return false;
      }

      log.debug(
          "checkAndMoveLiveFlowInternal, FlowId="
              + Long.toHexString(fe.id().value())
              + ", state="
              + fe.state()
              + ", After liveType="
              + fe.flowLiveType()
              + ", liveTime="
              + liveTime
              + ", life="
              + fe.life()
              + ", bytes="
              + fe.bytes()
              + ", packets="
              + fe.packets()
              + ", fromLastSeen="
              + fromLastSeen
              + ", priority="
              + fe.priority()
              + ", selector="
              + fe.selector().criteria()
              + ", treatment="
              + fe.treatment()
              + " AdaptiveStats collection thread for {}",
          sw.getStringId());

      return true;
    }
  /**
   * add or update typed flow entry from flow entry into the internal flow table.
   *
   * @param flowEntries the flow entries
   */
  public synchronized void addOrUpdateFlows(FlowEntry... flowEntries) {
    for (FlowEntry fe : flowEntries) {
      // check if this new rule is an update to an existing entry
      TypedStoredFlowEntry stored = deviceFlowTable.getFlowEntry(fe);

      if (stored != null) {
        // duplicated flow entry is collected!, just skip
        if (fe.bytes() == stored.bytes()
            && fe.packets() == stored.packets()
            && fe.life() == stored.life()) {
          log.debug(
              "addOrUpdateFlows:, FlowId="
                  + Long.toHexString(fe.id().value())
                  + ",is DUPLICATED stats collection, just skip."
                  + " AdaptiveStats collection thread for {}",
              sw.getStringId());

          // FIXME modification of "stored" flow entry outside of store
          stored.setLastSeen();
          continue;
        } else if (fe.life() < stored.life()) {
          // Invalid updates the stats values, i.e., bytes, packets, durations ...
          log.debug(
              "addOrUpdateFlows():"
                  + " Invalid Flow Update! The new life is SMALLER than the previous one, jus skip."
                  + " new flowId="
                  + Long.toHexString(fe.id().value())
                  + ", old flowId="
                  + Long.toHexString(stored.id().value())
                  + ", new bytes="
                  + fe.bytes()
                  + ", old bytes="
                  + stored.bytes()
                  + ", new life="
                  + fe.life()
                  + ", old life="
                  + stored.life()
                  + ", new lastSeen="
                  + fe.lastSeen()
                  + ", old lastSeen="
                  + stored.lastSeen());
          // go next
          // FIXME modification of "stored" flow entry outside of store
          stored.setLastSeen();
          continue;
        }

        // update now
        // FIXME modification of "stored" flow entry outside of store
        stored.setLife(fe.life());
        stored.setPackets(fe.packets());
        stored.setBytes(fe.bytes());
        stored.setLastSeen();
        if (stored.state() == FlowEntry.FlowEntryState.PENDING_ADD) {
          // flow is really RULE_ADDED
          stored.setState(FlowEntry.FlowEntryState.ADDED);
        }
        // flow is RULE_UPDATED, skip adding and just updating flow live table
        // deviceFlowTable.calAndSetFlowLiveType(stored);
        continue;
      }

      // add new flow entry, we suppose IMMEDIATE_FLOW
      TypedStoredFlowEntry newFlowEntry =
          new DefaultTypedFlowEntry(fe, FlowLiveType.IMMEDIATE_FLOW);
      deviceFlowTable.addWithCalAndSetFlowLiveType(newFlowEntry);
    }
  }
Example #8
0
 public TypedFlowEntryWithLoad(ConnectPoint cp, TypedStoredFlowEntry tfe) {
   this.cp = cp;
   this.tfe = tfe;
   this.load = new DefaultLoad(tfe.bytes(), 0, typedPollInterval(tfe));
 }