/** * 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); } }
@Override public synchronized void updateFlowStatistic(FlowEntry rule) { ConnectPoint cp = buildConnectPoint(rule); if (cp == null) { return; } Set<FlowEntry> curr = current.get(cp); if (curr == null) { addFlowStatistic(rule); } else { Optional<FlowEntry> f = curr.stream().filter(c -> rule.equals(c)).findAny(); if (f.isPresent() && rule.bytes() < f.get().bytes()) { log.debug( "DistributedFlowStatisticStore:updateFlowStatistic():" + " Invalid Flow Update! Will be removed!!" + " curr flowId=" + Long.toHexString(rule.id().value()) + ", prev flowId=" + Long.toHexString(f.get().id().value()) + ", curr bytes=" + rule.bytes() + ", prev bytes=" + f.get().bytes() + ", curr life=" + rule.life() + ", prev life=" + f.get().life() + ", curr lastSeen=" + rule.lastSeen() + ", prev lastSeen=" + f.get().lastSeen()); // something is wrong! invalid flow entry, so delete it removeFlowStatistic(rule); return; } Set<FlowEntry> prev = previous.get(cp); if (prev == null) { prev = new HashSet<>(); previous.put(cp, prev); } // previous one is exist if (f.isPresent()) { // remove old one and add new one prev.remove(rule); if (!prev.add(f.get())) { log.debug( "DistributedFlowStatisticStore:updateFlowStatistic():" + " flowId={}, add failed into previous.", Long.toHexString(rule.id().value())); } } // remove old one and add new one curr.remove(rule); if (!curr.add(rule)) { log.debug( "DistributedFlowStatisticStore:updateFlowStatistic():" + " flowId={}, add failed into current.", Long.toHexString(rule.id().value())); } } }