@Override public Iterable<FlowEntry> getFlowEntries(DeviceId deviceId) { NodeId master = mastershipService.getMasterFor(deviceId); if (master == null) { log.debug("Failed to getFlowEntries: No master for {}", deviceId); return Collections.emptyList(); } if (Objects.equal(local, master)) { return flowTable.getFlowEntries(deviceId); } log.trace( "Forwarding getFlowEntries to {}, which is the primary (master) for device {}", master, deviceId); return Tools.futureGetOrElse( clusterCommunicator.sendAndReceive( deviceId, FlowStoreMessageSubjects.GET_DEVICE_FLOW_ENTRIES, SERIALIZER::encode, SERIALIZER::decode, master), FLOW_RULE_STORE_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS, Collections.emptyList()); }
@Override public FlowEntry getFlowEntry(FlowRule rule) { NodeId master = mastershipService.getMasterFor(rule.deviceId()); if (master == null) { log.debug("Failed to getFlowEntry: No master for {}", rule.deviceId()); return null; } if (Objects.equal(local, master)) { return flowTable.getFlowEntry(rule); } log.trace( "Forwarding getFlowEntry to {}, which is the primary (master) for device {}", master, rule.deviceId()); return Tools.futureGetOrElse( clusterCommunicator.sendAndReceive( rule, FlowStoreMessageSubjects.GET_FLOW_ENTRY, SERIALIZER::encode, SERIALIZER::decode, master), FLOW_RULE_STORE_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS, null); }
@Override public void storeBatch(FlowRuleBatchOperation operation) { if (operation.getOperations().isEmpty()) { notifyDelegate( FlowRuleBatchEvent.completed( new FlowRuleBatchRequest(operation.id(), Collections.emptySet()), new CompletedBatchOperation(true, Collections.emptySet(), operation.deviceId()))); return; } DeviceId deviceId = operation.deviceId(); NodeId master = mastershipService.getMasterFor(deviceId); if (master == null) { log.warn("No master for {} : flows will be marked for removal", deviceId); updateStoreInternal(operation); notifyDelegate( FlowRuleBatchEvent.completed( new FlowRuleBatchRequest(operation.id(), Collections.emptySet()), new CompletedBatchOperation(true, Collections.emptySet(), operation.deviceId()))); return; } if (Objects.equal(local, master)) { storeBatchInternal(operation); return; } log.trace( "Forwarding storeBatch to {}, which is the primary (master) for device {}", master, deviceId); clusterCommunicator .unicast(operation, APPLY_BATCH_FLOWS, SERIALIZER::encode, master) .whenComplete( (result, error) -> { if (error != null) { log.warn("Failed to storeBatch: {} to {}", operation, master, error); Set<FlowRule> allFailures = operation .getOperations() .stream() .map(op -> op.target()) .collect(Collectors.toSet()); notifyDelegate( FlowRuleBatchEvent.completed( new FlowRuleBatchRequest(operation.id(), Collections.emptySet()), new CompletedBatchOperation(false, allFailures, deviceId))); } }); }
@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; }
@Override public Iterable<TableStatisticsEntry> getTableStatistics(DeviceId deviceId) { NodeId master = mastershipService.getMasterFor(deviceId); if (master == null) { log.debug("Failed to getTableStats: No master for {}", deviceId); return Collections.emptyList(); } List<TableStatisticsEntry> tableStats = deviceTableStats.get(deviceId); if (tableStats == null) { return Collections.emptyList(); } return ImmutableList.copyOf(tableStats); }
@Override public Set<FlowEntry> getPreviousFlowStatistic(ConnectPoint connectPoint) { final DeviceId deviceId = connectPoint.deviceId(); NodeId master = mastershipService.getMasterFor(deviceId); if (master == null) { log.warn("No master for {}", deviceId); return Collections.emptySet(); } if (Objects.equal(local, master)) { return getPreviousStatisticInternal(connectPoint); } else { return Tools.futureGetOrElse( clusterCommunicator.sendAndReceive( connectPoint, GET_PREVIOUS, SERIALIZER::encode, SERIALIZER::decode, master), STATISTIC_STORE_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS, Collections.emptySet()); } }
@Override public void emit(OutboundPacket packet) { NodeId myId = clusterService.getLocalNode().id(); NodeId master = mastershipService.getMasterFor(packet.sendThrough()); if (master == null) { return; } if (myId.equals(master)) { notifyDelegate(new PacketEvent(Type.EMIT, packet)); return; } communicationService .unicast(packet, PACKET_OUT_SUBJECT, SERIALIZER::encode, master) .whenComplete( (r, error) -> { if (error != null) { log.warn("Failed to send packet-out to {}", master, error); } }); }
@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); }