16 package org.openkilda.pce.cache;
30 import com.google.common.annotations.VisibleForTesting;
31 import com.google.common.base.MoreObjects;
32 import org.slf4j.Logger;
33 import org.slf4j.LoggerFactory;
35 import java.util.HashMap;
36 import java.util.HashSet;
37 import java.util.LinkedList;
39 import java.util.Objects;
41 import java.util.concurrent.ConcurrentHashMap;
42 import java.util.function.Supplier;
43 import java.util.stream.Collectors;
44 import java.util.stream.Stream;
50 private static final Logger logger = LoggerFactory.getLogger(
FlowCache.class);
61 private final Map<String, ImmutablePair<Flow, Flow>> flowPool =
new ConcurrentHashMap<>();
69 logger.debug(
"Flows: {}", flows);
70 flows.forEach(this::putFlow);
78 resourceCache.clear();
88 return flowPool.put(flow.
getLeft().getFlowId(), flow);
98 return flowPool.remove(flowId);
107 resourceCache.allocateFlow(flow);
118 logger.debug(
"Is flow {} in cache", flowId);
120 return flowPool.containsKey(flowId);
130 return flowPool.values().stream().filter(flow ->
131 flow.getLeft().getFlowPath().getPath().stream()
132 .anyMatch(
node ->
node.getSwitchId().equals(switchId))
133 || flow.getRight().getFlowPath().getPath().stream()
134 .anyMatch(
node ->
node.getSwitchId().equals(switchId))
135 ||
isOneSwitchFlow(flow) && flow.getLeft().getSourceSwitch().equals(switchId))
136 .filter(flow -> flow.getLeft().getState().isActiveOrCached())
137 .collect(Collectors.toSet());
147 return flowPool.values().stream()
148 .filter(flow -> flow.getLeft().getFlowPath().getPath().contains(islData.
getPath().get(0))
149 || flow.getRight().getFlowPath().getPath().contains(islData.
getPath().get(0)))
150 .filter(flow -> flow.getLeft().getState().isActiveOrCached())
151 .collect(Collectors.toSet());
162 return flowPool.values().stream()
163 .filter(flow -> flow.getLeft().getFlowPath().getPath().contains(
node)
164 || flow.getRight().getFlowPath().getPath().contains(
node))
165 .filter(flow -> flow.getLeft().getState().isActiveOrCached())
166 .collect(Collectors.toSet());
176 return flowPool.values().stream().filter(flow ->
177 flow.getLeft().getFlowPath().getPath().stream()
178 .anyMatch(
node ->
node.getSwitchId().equals(switchId))
179 || flow.getRight().getFlowPath().getPath().stream()
180 .anyMatch(
node ->
node.getSwitchId().equals(switchId))
181 ||
isOneSwitchFlow(flow) && flow.getLeft().getSourceSwitch().equals(switchId))
182 .collect(Collectors.toSet());
192 return flowPool.values().stream()
193 .filter(flow -> flow.getLeft().getFlowPath().getPath().contains(islData.
getPath().get(0))
194 || flow.getRight().getFlowPath().getPath().contains(islData.
getPath().get(0)))
195 .collect(Collectors.toSet());
206 return flowPool.values().stream().filter(flow ->
207 flow.getLeft().getFlowPath().getPath().contains(
node)
208 || flow.getRight().getFlowPath().getPath().contains(
node))
209 .collect(Collectors.toSet());
219 Map<String, String> response =
new HashMap<>();
222 SwitchId endpoint = getFlowLinkedEndpoint(flow, switchId);
223 if (endpoint != null) {
224 response.put(flow.getLeft().getFlowId(), endpoint.
toString());
248 logger.debug(
"Get {} flow", flowId);
255 String.format(
"Flow %s not found", flowId));
269 String flowId = flow.getFlowId();
270 logger.debug(
"Create {} flow with {} parameters", flowId, flow);
273 if (oldFlow != null) {
275 String.format(
"Flow %s already exists", flowId));
279 resourceCache.allocateFlow(newFlow);
280 flowPool.put(flowId, newFlow);
292 logger.debug(
"Delete {} flow", flowId);
297 String.format(
"Flow %s not found", flowId));
300 resourceCache.deallocateFlow(flow);
313 String flowId = flow.getFlowId();
314 logger.debug(
"Update {} flow with {} parameters", flowId, flow);
317 if (oldFlow == null) {
319 String.format(
"Flow %s not found", flowId));
324 newFlow = buildFlow(flow,
path);
325 resourceCache.deallocateFlow(oldFlow);
327 resourceCache.allocateFlow(newFlow);
328 flowPool.put(flowId, newFlow);
329 }
catch (Throwable e) {
330 flowPool.put(flowId, oldFlow);
343 logger.debug(
"Get all flows");
344 return new HashSet<>(flowPool.values());
355 logger.debug(
"Get single path intersection between {} and {}", firstPath, secondPath);
356 Set<PathNode> intersection =
new HashSet<>(firstPath.
getPath());
357 intersection.retainAll(secondPath.
getPath());
371 logger.debug(
"Get path intersection between {} and {}", firstPath, secondPath);
379 logger.debug(
"Path intersection is {}", intersection);
390 int cookie = resourceCache.allocateCookie();
398 forwardVlan = resourceCache.allocateVlanId();
399 reverseVlan = resourceCache.allocateVlanId();
401 forwardVlan = reverseVlan = 0;
404 Flow.FlowBuilder forwardBuilder = Flow.builder()
405 .flowId(flow.getFlowId())
406 .cookie(cookie | ResourceCache.FORWARD_FLOW_COOKIE_MASK)
407 .description(flow.getDescription())
408 .lastUpdated(timestamp)
409 .sourceSwitch(flow.getSourceSwitch())
410 .destinationSwitch(flow.getDestinationSwitch())
411 .sourcePort(flow.getSourcePort())
412 .destinationPort(flow.getDestinationPort())
413 .sourceVlan(flow.getSourceVlan())
414 .destinationVlan(flow.getDestinationVlan())
415 .transitVlan(forwardVlan)
416 .flowPath(
path.getLeft())
417 .state(FlowState.ALLOCATED);
418 setBandwidthAndMeter(forwardBuilder, flow.getBandwidth(), flow.isIgnoreBandwidth(),
419 () -> resourceCache.allocateMeterId(flow.getSourceSwitch()));
420 Flow forward = forwardBuilder.build();
422 Flow.FlowBuilder reverseBuilder = Flow.builder()
423 .flowId(flow.getFlowId())
424 .cookie(cookie | ResourceCache.REVERSE_FLOW_COOKIE_MASK)
425 .description(flow.getDescription())
426 .lastUpdated(timestamp)
427 .sourceSwitch(flow.getDestinationSwitch())
428 .destinationSwitch(flow.getSourceSwitch())
429 .sourcePort(flow.getDestinationPort())
430 .destinationPort(flow.getSourcePort())
431 .sourceVlan(flow.getDestinationVlan())
432 .destinationVlan(flow.getSourceVlan())
433 .transitVlan(reverseVlan)
434 .flowPath(
path.getRight())
435 .state(FlowState.ALLOCATED);
436 setBandwidthAndMeter(reverseBuilder, flow.getBandwidth(), flow.isIgnoreBandwidth(),
437 () -> resourceCache.allocateMeterId(flow.getDestinationSwitch()));
438 Flow reverse = reverseBuilder.build();
440 return new ImmutablePair<>(forward, reverse);
443 private void setBandwidthAndMeter(Flow.FlowBuilder builder,
long bandwidth,
boolean isIgnoreBandwidth,
444 Supplier<Integer> meterIdSupplier) {
445 builder.bandwidth(bandwidth);
447 if (bandwidth > 0L) {
448 builder.ignoreBandwidth(isIgnoreBandwidth);
449 builder.meterId(meterIdSupplier.get());
452 builder.ignoreBandwidth(
true);
469 return flow.
getLeft().getSourceSwitch().equals(flow.
getLeft().getDestinationSwitch())
470 && flow.
getRight().getSourceSwitch().equals(flow.
getRight().getDestinationSwitch());
485 if (forward.getSourceSwitch().
equals(switchId) && reverse.getDestinationSwitch().
equals(switchId)) {
486 linkedSwitch = forward.getDestinationSwitch();
487 }
else if (forward.getDestinationSwitch().
equals(switchId) && reverse.getSourceSwitch().
equals(switchId)) {
488 linkedSwitch = forward.getSourceSwitch();
501 return flowPool.values().stream()
502 .flatMap(pair -> Stream.of(pair.getLeft(), pair.getRight()))
503 .filter(flow -> flow.getSourceSwitch().
equals(switchId) && flow.getSourcePort() ==
port 504 || flow.getDestinationSwitch().
equals(switchId) && flow.getDestinationPort() ==
port)
505 .collect(Collectors.toSet());
521 return flowPool.values().stream()
522 .flatMap(pair -> Stream.of(pair.getLeft(), pair.getRight()))
523 .filter(flow -> flow.getSourceSwitch().
equals(switchId) && flow.getSourcePort() ==
port 524 && (flow.getSourceVlan() == vlan || flow.getSourceVlan() == 0)
525 || flow.getDestinationSwitch().
equals(switchId) && flow.getDestinationPort() ==
port 526 && (flow.getDestinationVlan() == vlan || flow.getDestinationVlan() == 0))
527 .collect(Collectors.toSet());
535 return flowPool.values().stream()
536 .filter(flowPair -> Objects.nonNull(getFlowLinkedEndpoint(flowPair, switchId)))
537 .collect(Collectors.toSet());
542 return resourceCache.getAllVlanIds();
546 return resourceCache.getAllCookies();
550 return resourceCache.getAllMeterIds();
558 return MoreObjects.toStringHelper(
this)
559 .add(
"resources", resourceCache)
560 .add(
"flows", flowPool)
void pushFlow(ImmutablePair< Flow, Flow > flow)
Set< ImmutablePair< Flow, Flow > > getActiveFlowsWithAffectedPath(IslInfoData islData)
ImmutablePair< PathInfoData, PathInfoData > getFlowPath(String flowId)
void load(Set< ImmutablePair< Flow, Flow >> flows)
ImmutablePair< Flow, Flow > removeFlow(String flowId)
Set< ImmutablePair< Flow, Flow > > getIngressAndEgressFlows(SwitchId switchId)
Map< String, String > getFlowsWithAffectedEndpoint(SwitchId switchId)
ImmutablePair< Flow, Flow > getFlow(String flowId)
Set< Flow > getFlowsForEndpoint(SwitchId switchId, int port)
boolean equals(Object object)
Set< PathNode > getPathIntersection(PathInfoData firstPath, PathInfoData secondPath)
static String getIsoTimestamp()
Map< SwitchId, Set< Integer > > getAllocatedMeters()
Set< Integer > getAllocatedVlans()
Set< ImmutablePair< Flow, Flow > > dumpFlows()
ImmutablePair< Flow, Flow > updateFlow(Flow flow, ImmutablePair< PathInfoData, PathInfoData > path)
ImmutablePair< Flow, Flow > putFlow(ImmutablePair< Flow, Flow > flow)
Set< Flow > getFlowsForEndpoint(SwitchId switchId, int port, int vlan)
Set< ImmutablePair< Flow, Flow > > getActiveFlowsWithAffectedPath(PortInfoData portData)
Set< ImmutablePair< Flow, Flow > > getFlowsWithAffectedPath(IslInfoData islData)
ImmutablePair< Flow, Flow > deleteFlow(String flowId)
Set< ImmutablePair< Flow, Flow > > getActiveFlowsWithAffectedPath(SwitchId switchId)
List< PathNode > getPath()
boolean isOneSwitchFlow()
Set< ImmutablePair< Flow, Flow > > getFlowsWithAffectedPath(SwitchId switchId)
ImmutablePair< Flow, Flow > createFlow(Flow flow, ImmutablePair< PathInfoData, PathInfoData > path)
Set< Integer > getAllocatedCookies()
boolean isOneSwitchFlow(ImmutablePair< Flow, Flow > flow)
Set< ImmutablePair< Flow, Flow > > getFlowsWithAffectedPath(PortInfoData portData)
boolean cacheContainsFlow(String flowId)
ImmutablePair< Set< PathNode >, Set< PathNode > > getPathIntersection(ImmutablePair< PathInfoData, PathInfoData > firstPath, ImmutablePair< PathInfoData, PathInfoData > secondPath)
boolean equals(Object object)