@Test public void testOriginatingFlowMatchesInboundSession() { NetworkFactory nf = new NetworkFactory(); Configuration c = nf.configurationBuilder().setConfigurationFormat(ConfigurationFormat.CISCO_IOS).build(); Vrf vrf = nf.vrfBuilder().setOwner(c).build(); vrf.setFirewallSessionVrfInfo(new FirewallSessionVrfInfo(true)); String ifaceName = "ifaceName"; nf.interfaceBuilder() .setOwner(c) .setVrf(vrf) .setName(ifaceName) .setFirewallSessionInterfaceInfo( new FirewallSessionInterfaceInfo(false, ImmutableSet.of(ifaceName), null, null)) .build(); Ip srcIp = Ip.parse("1.1.1.1"); Ip dstIp = Ip.parse("2.2.2.2"); int srcPort = 22; int dstPort = 40; Flow returnFlow = Flow.builder() .setSrcIp(dstIp) .setDstIp(srcIp) .setIngressNode(c.getHostname()) .setIngressVrf(vrf.getName()) .setIpProtocol(IpProtocol.TCP) .setSrcPort(dstPort) .setDstPort(srcPort) .build(); SessionMatchExpr flowMatchingNewSession = new SessionMatchExpr(IpProtocol.TCP, dstIp, srcIp, dstPort, srcPort); FirewallSessionTraceInfo inboundSession = new FirewallSessionTraceInfo( c.getHostname(), new ForwardOutInterface(ifaceName, null), new OriginatingSessionScope(vrf.getName()), flowMatchingNewSession, null); ImmutableMap<String, Configuration> configs = ImmutableMap.of(c.getHostname(), c); TracerouteEngineImplContext ctxt = new TracerouteEngineImplContext( MockDataPlane.builder() .setForwardingAnalysis( MockForwardingAnalysis.builder() .setAcceptedIps( ImmutableMap.of( c.getHostname(), ImmutableMap.of(vrf.getName(), ImmutableMap.of()))) .build()) .build(), Topology.EMPTY, ImmutableSet.of(inboundSession), ImmutableSet.of(), ImmutableMap.of( c.getHostname(), ImmutableMap.of(vrf.getName(), MockFib.builder().build())), false, configs); { List<TraceAndReverseFlow> traces = new ArrayList<>(); FlowTracer flowTracer = new FlowTracer( ctxt, c, null, new Node(c.getHostname()), new LegacyTraceRecorder(traces::add), null, new ArrayList<>(), returnFlow, vrf.getName(), new ArrayList<>(), new ArrayList<>(), new Stack<>(), returnFlow, 0, 0); flowTracer.processHop(); TraceAndReverseFlow traceAndReverseFlow = Iterables.getOnlyElement(traces); Trace trace = traceAndReverseFlow.getTrace(); assertThat(trace, hasDisposition(EXITS_NETWORK)); assertThat(trace.getHops().get(0).getSteps(), hasItem(instanceOf(MatchSessionStep.class))); assertThat(traceAndReverseFlow.getNewFirewallSessions(), empty()); } { Flow nonMatchingReturnFlow = returnFlow.toBuilder().setIpProtocol(IpProtocol.UDP).build(); List<TraceAndReverseFlow> traces = new ArrayList<>(); FlowTracer flowTracer = new FlowTracer( ctxt, c, null, new Node(c.getHostname()), new LegacyTraceRecorder(traces::add), null, new ArrayList<>(), nonMatchingReturnFlow, vrf.getName(), new ArrayList<>(), new ArrayList<>(), new Stack<>(), nonMatchingReturnFlow, 0, 0); flowTracer.processHop(); TraceAndReverseFlow traceAndReverseFlow = Iterables.getOnlyElement(traces); Trace trace = traceAndReverseFlow.getTrace(); assertThat(trace, hasDisposition(NO_ROUTE)); assertThat( trace.getHops().get(0).getSteps(), not(hasItem(instanceOf(MatchSessionStep.class)))); assertThat(traceAndReverseFlow.getNewFirewallSessions(), empty()); } }
void processHop() { checkState(_steps.isEmpty(), "Steps must be empty when processHop is called"); checkState( _hops.size() == _breadcrumbs.size(), "Must have equal number of hops and breadcrumbs"); String currentNodeName = _currentNode.getName(); if (_ingressInterface != null) { _steps.add(buildEnterSrcIfaceStep(_currentConfig, _ingressInterface)); } if (processSessions()) { return; } if (_ingressInterface != null) { Interface incomingInterface = _currentConfig.getAllInterfaces().get(_ingressInterface); if (processPBR(incomingInterface)) { return; } IpAccessList inputFilter = incomingInterface.getIncomingFilter(); if (inputFilter != null) { if (applyFilter(inputFilter, INGRESS_FILTER) == DENIED) { return; } } applyTransformation(incomingInterface.getIncomingTransformation()); inputFilter = incomingInterface.getPostTransformationIncomingFilter(); if (applyFilter(inputFilter, POST_TRANSFORMATION_INGRESS_FILTER) == DENIED) { return; } } else { _steps.add(buildOriginateStep()); } Ip dstIp = _currentFlow.getDstIp(); if (_tracerouteContext.vrfAcceptsIp(currentNodeName, _vrfName, dstIp)) { buildAcceptTrace(); return; } Fib fib = _tracerouteContext.getFib(currentNodeName, _vrfName).get(); fibLookup(dstIp, currentNodeName, fib); }
FlowTracer { void processHop() { checkState(_steps.isEmpty(), "Steps must be empty when processHop is called"); checkState( _hops.size() == _breadcrumbs.size(), "Must have equal number of hops and breadcrumbs"); String currentNodeName = _currentNode.getName(); if (_ingressInterface != null) { _steps.add(buildEnterSrcIfaceStep(_currentConfig, _ingressInterface)); } if (processSessions()) { return; } if (_ingressInterface != null) { Interface incomingInterface = _currentConfig.getAllInterfaces().get(_ingressInterface); if (processPBR(incomingInterface)) { return; } IpAccessList inputFilter = incomingInterface.getIncomingFilter(); if (inputFilter != null) { if (applyFilter(inputFilter, INGRESS_FILTER) == DENIED) { return; } } applyTransformation(incomingInterface.getIncomingTransformation()); inputFilter = incomingInterface.getPostTransformationIncomingFilter(); if (applyFilter(inputFilter, POST_TRANSFORMATION_INGRESS_FILTER) == DENIED) { return; } } else { _steps.add(buildOriginateStep()); } Ip dstIp = _currentFlow.getDstIp(); if (_tracerouteContext.vrfAcceptsIp(currentNodeName, _vrfName, dstIp)) { buildAcceptTrace(); return; } Fib fib = _tracerouteContext.getFib(currentNodeName, _vrfName).get(); fibLookup(dstIp, currentNodeName, fib); } }
FlowTracer { void processHop() { checkState(_steps.isEmpty(), "Steps must be empty when processHop is called"); checkState( _hops.size() == _breadcrumbs.size(), "Must have equal number of hops and breadcrumbs"); String currentNodeName = _currentNode.getName(); if (_ingressInterface != null) { _steps.add(buildEnterSrcIfaceStep(_currentConfig, _ingressInterface)); } if (processSessions()) { return; } if (_ingressInterface != null) { Interface incomingInterface = _currentConfig.getAllInterfaces().get(_ingressInterface); if (processPBR(incomingInterface)) { return; } IpAccessList inputFilter = incomingInterface.getIncomingFilter(); if (inputFilter != null) { if (applyFilter(inputFilter, INGRESS_FILTER) == DENIED) { return; } } applyTransformation(incomingInterface.getIncomingTransformation()); inputFilter = incomingInterface.getPostTransformationIncomingFilter(); if (applyFilter(inputFilter, POST_TRANSFORMATION_INGRESS_FILTER) == DENIED) { return; } } else { _steps.add(buildOriginateStep()); } Ip dstIp = _currentFlow.getDstIp(); if (_tracerouteContext.vrfAcceptsIp(currentNodeName, _vrfName, dstIp)) { buildAcceptTrace(); return; } Fib fib = _tracerouteContext.getFib(currentNodeName, _vrfName).get(); fibLookup(dstIp, currentNodeName, fib); } @VisibleForTesting  FlowTracer(
      TracerouteEngineImplContext tracerouteContext,
      Configuration currentConfig,
      @Nullable String ingressInterface,
      Node currentNode,
      TraceRecorder traceRecorder,
      @Nullable NodeInterfacePair lastHopNodeAndOutgoingInterface,
      List<FirewallSessionTraceInfo> newSessions,
      Flow originalFlow,
      @Nonnull String vrfName,
      List<HopInfo> hops,
      List<Step<?>> steps,
      Stack<Breadcrumb> breadcrumbs,
      Flow currentFlow,
      int origNewSessionsSize,
      int origBreadcrumbsSize); }
FlowTracer { void processHop() { checkState(_steps.isEmpty(), "Steps must be empty when processHop is called"); checkState( _hops.size() == _breadcrumbs.size(), "Must have equal number of hops and breadcrumbs"); String currentNodeName = _currentNode.getName(); if (_ingressInterface != null) { _steps.add(buildEnterSrcIfaceStep(_currentConfig, _ingressInterface)); } if (processSessions()) { return; } if (_ingressInterface != null) { Interface incomingInterface = _currentConfig.getAllInterfaces().get(_ingressInterface); if (processPBR(incomingInterface)) { return; } IpAccessList inputFilter = incomingInterface.getIncomingFilter(); if (inputFilter != null) { if (applyFilter(inputFilter, INGRESS_FILTER) == DENIED) { return; } } applyTransformation(incomingInterface.getIncomingTransformation()); inputFilter = incomingInterface.getPostTransformationIncomingFilter(); if (applyFilter(inputFilter, POST_TRANSFORMATION_INGRESS_FILTER) == DENIED) { return; } } else { _steps.add(buildOriginateStep()); } Ip dstIp = _currentFlow.getDstIp(); if (_tracerouteContext.vrfAcceptsIp(currentNodeName, _vrfName, dstIp)) { buildAcceptTrace(); return; } Fib fib = _tracerouteContext.getFib(currentNodeName, _vrfName).get(); fibLookup(dstIp, currentNodeName, fib); } @VisibleForTesting  FlowTracer(
      TracerouteEngineImplContext tracerouteContext,
      Configuration currentConfig,
      @Nullable String ingressInterface,
      Node currentNode,
      TraceRecorder traceRecorder,
      @Nullable NodeInterfacePair lastHopNodeAndOutgoingInterface,
      List<FirewallSessionTraceInfo> newSessions,
      Flow originalFlow,
      @Nonnull String vrfName,
      List<HopInfo> hops,
      List<Step<?>> steps,
      Stack<Breadcrumb> breadcrumbs,
      Flow currentFlow,
      int origNewSessionsSize,
      int origBreadcrumbsSize);  }
FlowTracer { void processHop() { checkState(_steps.isEmpty(), "Steps must be empty when processHop is called"); checkState( _hops.size() == _breadcrumbs.size(), "Must have equal number of hops and breadcrumbs"); String currentNodeName = _currentNode.getName(); if (_ingressInterface != null) { _steps.add(buildEnterSrcIfaceStep(_currentConfig, _ingressInterface)); } if (processSessions()) { return; } if (_ingressInterface != null) { Interface incomingInterface = _currentConfig.getAllInterfaces().get(_ingressInterface); if (processPBR(incomingInterface)) { return; } IpAccessList inputFilter = incomingInterface.getIncomingFilter(); if (inputFilter != null) { if (applyFilter(inputFilter, INGRESS_FILTER) == DENIED) { return; } } applyTransformation(incomingInterface.getIncomingTransformation()); inputFilter = incomingInterface.getPostTransformationIncomingFilter(); if (applyFilter(inputFilter, POST_TRANSFORMATION_INGRESS_FILTER) == DENIED) { return; } } else { _steps.add(buildOriginateStep()); } Ip dstIp = _currentFlow.getDstIp(); if (_tracerouteContext.vrfAcceptsIp(currentNodeName, _vrfName, dstIp)) { buildAcceptTrace(); return; } Fib fib = _tracerouteContext.getFib(currentNodeName, _vrfName).get(); fibLookup(dstIp, currentNodeName, fib); } @VisibleForTesting  FlowTracer(
      TracerouteEngineImplContext tracerouteContext,
      Configuration currentConfig,
      @Nullable String ingressInterface,
      Node currentNode,
      TraceRecorder traceRecorder,
      @Nullable NodeInterfacePair lastHopNodeAndOutgoingInterface,
      List<FirewallSessionTraceInfo> newSessions,
      Flow originalFlow,
      @Nonnull String vrfName,
      List<HopInfo> hops,
      List<Step<?>> steps,
      Stack<Breadcrumb> breadcrumbs,
      Flow currentFlow,
      int origNewSessionsSize,
      int origBreadcrumbsSize);   }