@Test public void testMultipath() { Trace forwardTrace1 = new Trace(ACCEPTED, ImmutableList.of()); Trace forwardTrace2 = new Trace(DENIED_IN, ImmutableList.of()); Trace forwardTrace3 = new Trace(DELIVERED_TO_SUBNET, ImmutableList.of()); TraceAndReverseFlow forwardTarf1 = new TraceAndReverseFlow(forwardTrace1, REVERSE_FLOW, ImmutableSet.of()); TraceAndReverseFlow forwardTarf2 = new TraceAndReverseFlow(forwardTrace2, null, ImmutableSet.of()); TraceAndReverseFlow forwardTarf3 = new TraceAndReverseFlow(forwardTrace3, REVERSE_FLOW, ImmutableSet.of()); Trace reverseTrace1 = new Trace(DENIED_IN, ImmutableList.of()); Trace reverseTrace2 = new Trace(EXITS_NETWORK, ImmutableList.of()); TraceAndReverseFlow reverseTarf1 = new TraceAndReverseFlow(reverseTrace1, null, ImmutableSet.of()); TraceAndReverseFlow reverseTarf2 = new TraceAndReverseFlow(reverseTrace2, FORWARD_FLOW, ImmutableSet.of()); TracerouteEngine tracerouteEngine = forFlows( ImmutableMap.of( FORWARD_FLOW, ImmutableList.of(forwardTarf1, forwardTarf2, forwardTarf3), REVERSE_FLOW, ImmutableList.of(reverseTarf1, reverseTarf2))); List<BidirectionalTrace> bidirectionalTraces = computeBidirectionalTraces(ImmutableSet.of(FORWARD_FLOW), tracerouteEngine, false); assertThat( bidirectionalTraces, contains( new BidirectionalTrace( FORWARD_FLOW, forwardTrace1, ImmutableSet.of(), REVERSE_FLOW, reverseTrace1), new BidirectionalTrace( FORWARD_FLOW, forwardTrace1, ImmutableSet.of(), REVERSE_FLOW, reverseTrace2), new BidirectionalTrace(FORWARD_FLOW, forwardTrace2, ImmutableSet.of(), null, null), new BidirectionalTrace( FORWARD_FLOW, forwardTrace3, ImmutableSet.of(), REVERSE_FLOW, reverseTrace1), new BidirectionalTrace( FORWARD_FLOW, forwardTrace3, ImmutableSet.of(), REVERSE_FLOW, reverseTrace2))); }
@VisibleForTesting static List<BidirectionalTrace> computeBidirectionalTraces( Set<Flow> flows, TracerouteEngine tracerouteEngine, boolean ignoreFilters) { SortedMap<Flow, List<TraceAndReverseFlow>> forwardTraces = tracerouteEngine.computeTracesAndReverseFlows(flows, ignoreFilters); Set<FlowAndSessions> reverseFlowsAndSessions = forwardTraces.values().stream() .flatMap(List::stream) .filter(tarf -> tarf.getReverseFlow() != null) .map(tarf -> new FlowAndSessions(tarf.getReverseFlow(), tarf.getNewFirewallSessions())) .collect(ImmutableSet.toImmutableSet()); Map<FlowAndSessions, List<Trace>> reverseTraces = computeReverseTraces(tracerouteEngine, reverseFlowsAndSessions, ignoreFilters); List<BidirectionalTrace> result = new ArrayList<>(); forwardTraces.forEach( (forwardFlow, forwardTraceAndReverseFlows) -> forwardTraceAndReverseFlows.forEach( forwardTraceAndReverseFlow -> { Trace forwardTrace = forwardTraceAndReverseFlow.getTrace(); Flow reverseFlow = forwardTraceAndReverseFlow.getReverseFlow(); Set<FirewallSessionTraceInfo> newSessions = forwardTraceAndReverseFlow.getNewFirewallSessions(); if (reverseFlow == null) { result.add( new BidirectionalTrace(forwardFlow, forwardTrace, newSessions, null, null)); } else { FlowAndSessions fas = new FlowAndSessions(reverseFlow, newSessions); reverseTraces.get(fas).stream() .map( reverseTrace -> new BidirectionalTrace( forwardFlow, forwardTrace, newSessions, reverseFlow, reverseTrace)) .forEach(result::add); } })); return result; }
BidirectionalTracerouteAnswerer extends Answerer { @VisibleForTesting static List<BidirectionalTrace> computeBidirectionalTraces( Set<Flow> flows, TracerouteEngine tracerouteEngine, boolean ignoreFilters) { SortedMap<Flow, List<TraceAndReverseFlow>> forwardTraces = tracerouteEngine.computeTracesAndReverseFlows(flows, ignoreFilters); Set<FlowAndSessions> reverseFlowsAndSessions = forwardTraces.values().stream() .flatMap(List::stream) .filter(tarf -> tarf.getReverseFlow() != null) .map(tarf -> new FlowAndSessions(tarf.getReverseFlow(), tarf.getNewFirewallSessions())) .collect(ImmutableSet.toImmutableSet()); Map<FlowAndSessions, List<Trace>> reverseTraces = computeReverseTraces(tracerouteEngine, reverseFlowsAndSessions, ignoreFilters); List<BidirectionalTrace> result = new ArrayList<>(); forwardTraces.forEach( (forwardFlow, forwardTraceAndReverseFlows) -> forwardTraceAndReverseFlows.forEach( forwardTraceAndReverseFlow -> { Trace forwardTrace = forwardTraceAndReverseFlow.getTrace(); Flow reverseFlow = forwardTraceAndReverseFlow.getReverseFlow(); Set<FirewallSessionTraceInfo> newSessions = forwardTraceAndReverseFlow.getNewFirewallSessions(); if (reverseFlow == null) { result.add( new BidirectionalTrace(forwardFlow, forwardTrace, newSessions, null, null)); } else { FlowAndSessions fas = new FlowAndSessions(reverseFlow, newSessions); reverseTraces.get(fas).stream() .map( reverseTrace -> new BidirectionalTrace( forwardFlow, forwardTrace, newSessions, reverseFlow, reverseTrace)) .forEach(result::add); } })); return result; } }
BidirectionalTracerouteAnswerer extends Answerer { @VisibleForTesting static List<BidirectionalTrace> computeBidirectionalTraces( Set<Flow> flows, TracerouteEngine tracerouteEngine, boolean ignoreFilters) { SortedMap<Flow, List<TraceAndReverseFlow>> forwardTraces = tracerouteEngine.computeTracesAndReverseFlows(flows, ignoreFilters); Set<FlowAndSessions> reverseFlowsAndSessions = forwardTraces.values().stream() .flatMap(List::stream) .filter(tarf -> tarf.getReverseFlow() != null) .map(tarf -> new FlowAndSessions(tarf.getReverseFlow(), tarf.getNewFirewallSessions())) .collect(ImmutableSet.toImmutableSet()); Map<FlowAndSessions, List<Trace>> reverseTraces = computeReverseTraces(tracerouteEngine, reverseFlowsAndSessions, ignoreFilters); List<BidirectionalTrace> result = new ArrayList<>(); forwardTraces.forEach( (forwardFlow, forwardTraceAndReverseFlows) -> forwardTraceAndReverseFlows.forEach( forwardTraceAndReverseFlow -> { Trace forwardTrace = forwardTraceAndReverseFlow.getTrace(); Flow reverseFlow = forwardTraceAndReverseFlow.getReverseFlow(); Set<FirewallSessionTraceInfo> newSessions = forwardTraceAndReverseFlow.getNewFirewallSessions(); if (reverseFlow == null) { result.add( new BidirectionalTrace(forwardFlow, forwardTrace, newSessions, null, null)); } else { FlowAndSessions fas = new FlowAndSessions(reverseFlow, newSessions); reverseTraces.get(fas).stream() .map( reverseTrace -> new BidirectionalTrace( forwardFlow, forwardTrace, newSessions, reverseFlow, reverseTrace)) .forEach(result::add); } })); return result; } BidirectionalTracerouteAnswerer(Question question, IBatfish batfish); }
BidirectionalTracerouteAnswerer extends Answerer { @VisibleForTesting static List<BidirectionalTrace> computeBidirectionalTraces( Set<Flow> flows, TracerouteEngine tracerouteEngine, boolean ignoreFilters) { SortedMap<Flow, List<TraceAndReverseFlow>> forwardTraces = tracerouteEngine.computeTracesAndReverseFlows(flows, ignoreFilters); Set<FlowAndSessions> reverseFlowsAndSessions = forwardTraces.values().stream() .flatMap(List::stream) .filter(tarf -> tarf.getReverseFlow() != null) .map(tarf -> new FlowAndSessions(tarf.getReverseFlow(), tarf.getNewFirewallSessions())) .collect(ImmutableSet.toImmutableSet()); Map<FlowAndSessions, List<Trace>> reverseTraces = computeReverseTraces(tracerouteEngine, reverseFlowsAndSessions, ignoreFilters); List<BidirectionalTrace> result = new ArrayList<>(); forwardTraces.forEach( (forwardFlow, forwardTraceAndReverseFlows) -> forwardTraceAndReverseFlows.forEach( forwardTraceAndReverseFlow -> { Trace forwardTrace = forwardTraceAndReverseFlow.getTrace(); Flow reverseFlow = forwardTraceAndReverseFlow.getReverseFlow(); Set<FirewallSessionTraceInfo> newSessions = forwardTraceAndReverseFlow.getNewFirewallSessions(); if (reverseFlow == null) { result.add( new BidirectionalTrace(forwardFlow, forwardTrace, newSessions, null, null)); } else { FlowAndSessions fas = new FlowAndSessions(reverseFlow, newSessions); reverseTraces.get(fas).stream() .map( reverseTrace -> new BidirectionalTrace( forwardFlow, forwardTrace, newSessions, reverseFlow, reverseTrace)) .forEach(result::add); } })); return result; } BidirectionalTracerouteAnswerer(Question question, IBatfish batfish); @Override AnswerElement answer(NetworkSnapshot snapshot); static AnswerElement bidirectionalTracerouteAnswerElement(
      Question question,
      Set<Flow> flows,
      TracerouteEngine tracerouteEngine,
      boolean ignoreFilters,
      @Nullable Integer maxTraces); static TableMetadata metadata(); }
BidirectionalTracerouteAnswerer extends Answerer { @VisibleForTesting static List<BidirectionalTrace> computeBidirectionalTraces( Set<Flow> flows, TracerouteEngine tracerouteEngine, boolean ignoreFilters) { SortedMap<Flow, List<TraceAndReverseFlow>> forwardTraces = tracerouteEngine.computeTracesAndReverseFlows(flows, ignoreFilters); Set<FlowAndSessions> reverseFlowsAndSessions = forwardTraces.values().stream() .flatMap(List::stream) .filter(tarf -> tarf.getReverseFlow() != null) .map(tarf -> new FlowAndSessions(tarf.getReverseFlow(), tarf.getNewFirewallSessions())) .collect(ImmutableSet.toImmutableSet()); Map<FlowAndSessions, List<Trace>> reverseTraces = computeReverseTraces(tracerouteEngine, reverseFlowsAndSessions, ignoreFilters); List<BidirectionalTrace> result = new ArrayList<>(); forwardTraces.forEach( (forwardFlow, forwardTraceAndReverseFlows) -> forwardTraceAndReverseFlows.forEach( forwardTraceAndReverseFlow -> { Trace forwardTrace = forwardTraceAndReverseFlow.getTrace(); Flow reverseFlow = forwardTraceAndReverseFlow.getReverseFlow(); Set<FirewallSessionTraceInfo> newSessions = forwardTraceAndReverseFlow.getNewFirewallSessions(); if (reverseFlow == null) { result.add( new BidirectionalTrace(forwardFlow, forwardTrace, newSessions, null, null)); } else { FlowAndSessions fas = new FlowAndSessions(reverseFlow, newSessions); reverseTraces.get(fas).stream() .map( reverseTrace -> new BidirectionalTrace( forwardFlow, forwardTrace, newSessions, reverseFlow, reverseTrace)) .forEach(result::add); } })); return result; } BidirectionalTracerouteAnswerer(Question question, IBatfish batfish); @Override AnswerElement answer(NetworkSnapshot snapshot); static AnswerElement bidirectionalTracerouteAnswerElement(
      Question question,
      Set<Flow> flows,
      TracerouteEngine tracerouteEngine,
      boolean ignoreFilters,
      @Nullable Integer maxTraces); static TableMetadata metadata();  }