/** * 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++; } }
/** * 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); } }
public TypedFlowEntryWithLoad(ConnectPoint cp, TypedStoredFlowEntry tfe) { this.cp = cp; this.tfe = tfe; this.load = new DefaultLoad(tfe.bytes(), 0, typedPollInterval(tfe)); }