public boolean remove(DeviceId deviceId, FlowEntry rule) { try { return getFlowEntriesInternal(deviceId, rule.id()).remove(rule); } finally { lastUpdateTimes.put(deviceId, System.currentTimeMillis()); } }
private FlowRuleEvent addOrUpdateFlowRuleInternal(FlowEntry rule) { // check if this new rule is an update to an existing entry StoredFlowEntry stored = flowTable.getFlowEntry(rule); if (stored != null) { stored.setBytes(rule.bytes()); stored.setLife(rule.life()); stored.setPackets(rule.packets()); if (stored.state() == FlowEntryState.PENDING_ADD) { stored.setState(FlowEntryState.ADDED); return new FlowRuleEvent(Type.RULE_ADDED, rule); } return new FlowRuleEvent(Type.RULE_UPDATED, rule); } // TODO: Confirm if this behavior is correct. See SimpleFlowRuleStore // TODO: also update backup if the behavior is correct. flowTable.add(rule); return null; }
@Override public FlowRuleEvent addOrUpdateFlowRule(FlowEntry rule) { NodeId master = mastershipService.getMasterFor(rule.deviceId()); if (Objects.equal(local, master)) { return addOrUpdateFlowRuleInternal(rule); } log.warn("Tried to update FlowRule {} state," + " while the Node was not the master.", rule); return null; }
// send openflow flow stats request message with getting the specific flow entry(fe) to a given // switch sw private void ofFlowStatsRequestFlowSend(FlowEntry fe) { // set find match Match match = FlowModBuilder.builder(fe, sw.factory(), Optional.empty(), Optional.of(driverService)) .buildMatch(); // set find tableId TableId tableId = TableId.of(fe.tableId()); // set output port Instruction ins = fe.treatment() .allInstructions() .stream() .filter(i -> (i.type() == Instruction.Type.OUTPUT)) .findFirst() .orElse(null); OFPort ofPort = OFPort.NO_MASK; if (ins != null) { Instructions.OutputInstruction out = (Instructions.OutputInstruction) ins; ofPort = OFPort.of((int) ((out.port().toLong()))); } OFFlowStatsRequest request = sw.factory() .buildFlowStatsRequest() .setMatch(match) .setTableId(tableId) .setOutPort(ofPort) .build(); synchronized (this) { if (getFlowMissingXid() != NO_FLOW_MISSING_XID) { log.debug( "ofFlowStatsRequestFlowSend: previous FlowStatsRequestAll does not be processed yet," + " set no flow missing xid anyway, for {}", sw.getStringId()); setFlowMissingXid(NO_FLOW_MISSING_XID); } sw.sendMsg(request); } }
/** * Creates a new typed flow entry with the given flow entry fe. * * @param fe flow entry */ public static TypedStoredFlowEntry newTypedStoredFlowEntry(FlowEntry fe) { if (fe == null) { return null; } long life = fe.life(); if (life >= LONG_POLL_INTERVAL) { return new DefaultTypedFlowEntry(fe, TypedStoredFlowEntry.FlowLiveType.LONG_FLOW); } else if (life >= MID_POLL_INTERVAL) { return new DefaultTypedFlowEntry(fe, TypedStoredFlowEntry.FlowLiveType.MID_FLOW); } else if (life >= CAL_AND_POLL_INTERVAL) { return new DefaultTypedFlowEntry(fe, TypedStoredFlowEntry.FlowLiveType.SHORT_FLOW); } else if (life >= 0) { return new DefaultTypedFlowEntry(fe, TypedStoredFlowEntry.FlowLiveType.IMMEDIATE_FLOW); } else { // life < 0 return new DefaultTypedFlowEntry(fe, TypedStoredFlowEntry.FlowLiveType.UNKNOWN_FLOW); } }
/** * 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, FlowEntry fe) { this.cp = cp; this.tfe = newTypedStoredFlowEntry(fe); this.load = new DefaultLoad(fe.bytes(), 0, typedPollInterval(this.tfe)); }
@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())); } } }
public void add(FlowEntry rule) { getFlowEntriesInternal(rule.deviceId(), rule.id()).add((StoredFlowEntry) rule); lastUpdateTimes.put(rule.deviceId(), System.currentTimeMillis()); }
private FlowRuleEvent removeFlowRuleInternal(FlowEntry rule) { final DeviceId deviceId = rule.deviceId(); // This is where one could mark a rule as removed and still keep it in the store. final boolean removed = flowTable.remove(deviceId, rule); // flowEntries.remove(deviceId, rule); return removed ? new FlowRuleEvent(RULE_REMOVED, rule) : null; }
@Override public FlowRuleEvent removeFlowRule(FlowEntry rule) { final DeviceId deviceId = rule.deviceId(); NodeId master = mastershipService.getMasterFor(deviceId); if (Objects.equal(local, master)) { // bypass and handle it locally return removeFlowRuleInternal(rule); } if (master == null) { log.warn("Failed to removeFlowRule: No master for {}", deviceId); // TODO: revisit if this should be null (="no-op") or Exception return null; } log.trace( "Forwarding removeFlowRule to {}, which is the master for device {}", master, deviceId); return Futures.get( clusterCommunicator.sendAndReceive( rule, REMOVE_FLOW_ENTRY, SERIALIZER::encode, SERIALIZER::decode, master), FLOW_RULE_STORE_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS, RuntimeException.class); }