Example #1
0
  /**
   * Creates the interface configuration. On devices 1, 2 and 3 is configured an interface on port 1
   * with vlan 1. On devices 4, 5 and 6 is configured an interface on port 1 with vlan 2. On device
   * 5 no interfaces are configured.
   */
  private void addIntfConfig() {
    Set<Interface> interfaces = Sets.newHashSet();
    Set<Interface> vlanOneSet = Sets.newHashSet();
    Set<Interface> vlanTwoSet = Sets.newHashSet();

    for (int i = 1; i <= NUM_DEVICES - 1; i++) {
      ConnectPoint cp = new ConnectPoint(getDeviceId(i), P1);

      Interface intf = new Interface("intfOne", cp, Collections.emptyList(), null, VlanId.NONE);

      if (i <= 3) {
        intf = new Interface("intfTwo", cp, Collections.emptyList(), null, VLAN1);
        interfaces.add(intf);
        vlanOneSet.add(intf);
      } else if (i > 3 && i <= 6) {
        intf = new Interface("intfThree", cp, Collections.emptyList(), null, VLAN2);
        interfaces.add(intf);
        vlanTwoSet.add(intf);
      }
      expect(interfaceService.getInterfacesByPort(cp)).andReturn(Sets.newHashSet(intf)).anyTimes();
    }
    expect(interfaceService.getInterfacesByVlan(VLAN1)).andReturn(vlanOneSet).anyTimes();
    expect(interfaceService.getInterfacesByVlan(VLAN2)).andReturn(vlanTwoSet).anyTimes();
    expect(interfaceService.getInterfaces()).andReturn(interfaces).anyTimes();

    replay(interfaceService);
  }
Example #2
0
  @Before
  public void setUp() throws Exception {
    idGenerator = new TestIdGenerator();
    Intent.bindIdGenerator(idGenerator);

    applicationService = createMock(ApplicationService.class);

    coreService = createMock(CoreService.class);
    expect(coreService.registerApplication(APP_NAME)).andReturn(APPID);
    replay(coreService);

    hostsAvailable = Sets.newHashSet();
    hostService = new TestHostService(hostsAvailable);

    intentService = new TestIntentService();

    TestIntentSynchronizer intentSynchronizer = new TestIntentSynchronizer(intentService);

    interfaceService = createMock(InterfaceService.class);
    interfaceService.addListener(anyObject(InterfaceListener.class));
    expectLastCall().anyTimes();
    addIntfConfig();

    vpls = new Vpls();
    vpls.applicationService = applicationService;
    vpls.coreService = coreService;
    vpls.hostService = hostService;
    vpls.intentService = intentService;
    vpls.interfaceService = interfaceService;
    vpls.intentSynchronizer = intentSynchronizer;
  }
  /** Tests a corner case, when there is no Interface configured for one BGP peer. */
  @Test
  public void testNoPeerInterface() {
    IpAddress ip = IpAddress.valueOf("1.1.1.1");
    bgpSpeakers.clear();
    bgpSpeakers.add(
        new BgpConfig.BgpSpeakerConfig(
            Optional.of("foo"), VlanId.NONE, s1Eth100, Collections.singleton(ip)));
    reset(interfaceService);
    interfaceService.addListener(anyObject(InterfaceListener.class));
    expect(interfaceService.getMatchingInterface(ip)).andReturn(null).anyTimes();
    replay(interfaceService);

    // We don't expect any intents in this case
    reset(intentSynchronizer);
    replay(intentSynchronizer);
    peerConnectivityManager.start();
    verify(intentSynchronizer);
  }
Example #4
0
  /**
   * Sends an ARP or Neighbor Discovery Protocol request for the given IP address.
   *
   * @param targetIp IP address to send the request for
   */
  private void sendArpNdpRequest(IpAddress targetIp) {
    Interface intf = interfaceService.getMatchingInterface(targetIp);

    if (intf == null) {
      return;
    }

    for (InterfaceIpAddress ia : intf.ipAddresses()) {
      if (ia.subnetAddress().contains(targetIp)) {
        sendArpNdpProbe(intf.connectPoint(), targetIp, ia.ipAddress(), intf.mac(), intf.vlan());
      }
    }
  }
  private void handle(Ethernet eth) {
    checkNotNull(eth);

    if (!(eth.getEtherType() == EthType.EtherType.IPV4.ethType().toShort())) {
      return;
    }

    IPv4 ipv4 = (IPv4) eth.getPayload().clone();

    Ip4Address dstIp = Ip4Address.valueOf(ipv4.getDestinationAddress());

    Interface egressInterface = interfaceService.getMatchingInterface(dstIp);

    if (egressInterface == null) {
      log.info("No egress interface found for {}", dstIp);
      return;
    }

    Optional<Host> host =
        hostService
            .getHostsByIp(dstIp)
            .stream()
            .filter(h -> h.location().equals(egressInterface.connectPoint()))
            .filter(h -> h.vlan().equals(egressInterface.vlan()))
            .findAny();

    if (host.isPresent()) {
      transformAndSend(ipv4, egressInterface, host.get().mac());
    } else {
      hostService.startMonitoringIp(dstIp);
      ipPacketCache
          .asMap()
          .compute(
              dstIp,
              (ip, queue) -> {
                if (queue == null) {
                  queue = new ConcurrentLinkedQueue();
                }
                queue.add(ipv4);
                return queue;
              });
    }
  }
  @Before
  public void setUp() throws Exception {
    super.setUp();

    interfaceService = createMock(InterfaceService.class);
    interfaceService.addListener(anyObject(InterfaceListener.class));
    expectLastCall().anyTimes();
    networkConfigService = createMock(NetworkConfigService.class);
    networkConfigService.addListener(anyObject(NetworkConfigListener.class));
    expectLastCall().anyTimes();
    bgpConfig = createMock(BgpConfig.class);

    // These will set expectations on routingConfig and interfaceService
    bgpSpeakers = setUpBgpSpeakers();
    interfaces = Collections.unmodifiableMap(setUpInterfaces());

    initPeerConnectivity();
    intentList = setUpIntentList();
  }
  private void sendQueued(IpAddress ipAddress, MacAddress macAddress) {
    log.debug("Sending queued packets for {} ({})", ipAddress, macAddress);
    ipPacketCache
        .asMap()
        .computeIfPresent(
            ipAddress,
            (ip, packets) -> {
              packets.forEach(
                  ipv4 -> {
                    Interface egressInterface = interfaceService.getMatchingInterface(ipAddress);

                    if (egressInterface == null) {
                      log.info("No egress interface found for {}", ipAddress);
                      return;
                    }

                    transformAndSend(ipv4, egressInterface, macAddress);
                  });
              return null;
            });
  }
Example #8
0
  /**
   * Generates a route intent for a prefix, the next hop IP address, and the next hop MAC address.
   *
   * <p>This method will find the egress interface for the intent. Intent will match dst IP prefix
   * and rewrite dst MAC address at all other border switches, then forward packets according to dst
   * MAC address.
   *
   * @param prefix IP prefix of the route to add
   * @param nextHopIpAddress IP address of the next hop
   * @param nextHopMacAddress MAC address of the next hop
   * @return the generated intent, or null if no intent should be submitted
   */
  private MultiPointToSinglePointIntent generateRouteIntent(
      IpPrefix prefix, IpAddress nextHopIpAddress, MacAddress nextHopMacAddress) {

    // Find the attachment point (egress interface) of the next hop
    Interface egressInterface = interfaceService.getMatchingInterface(nextHopIpAddress);
    if (egressInterface == null) {
      log.warn("No outgoing interface found for {}", nextHopIpAddress);
      return null;
    }

    // Generate the intent itself
    Set<ConnectPoint> ingressPorts = new HashSet<>();
    ConnectPoint egressPort = egressInterface.connectPoint();
    log.debug("Generating intent for prefix {}, next hop mac {}", prefix, nextHopMacAddress);

    for (Interface intf : interfaceService.getInterfaces()) {
      // TODO this should be only peering interfaces
      if (!intf.connectPoint().equals(egressInterface.connectPoint())) {
        ConnectPoint srcPort = intf.connectPoint();
        ingressPorts.add(srcPort);
      }
    }

    // Match the destination IP prefix at the first hop
    TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
    if (prefix.isIp4()) {
      selector.matchEthType(Ethernet.TYPE_IPV4);
      // if it is default route, then we do not need match destination
      // IP address
      if (prefix.prefixLength() != 0) {
        selector.matchIPDst(prefix);
      }
    } else {
      selector.matchEthType(Ethernet.TYPE_IPV6);
      // if it is default route, then we do not need match destination
      // IP address
      if (prefix.prefixLength() != 0) {
        selector.matchIPv6Dst(prefix);
      }
    }

    // Rewrite the destination MAC address
    TrafficTreatment.Builder treatment =
        DefaultTrafficTreatment.builder().setEthDst(nextHopMacAddress);
    if (!egressInterface.vlan().equals(VlanId.NONE)) {
      treatment.setVlanId(egressInterface.vlan());
      // If we set VLAN ID, we have to make sure a VLAN tag exists.
      // TODO support no VLAN -> VLAN routing
      selector.matchVlanId(VlanId.ANY);
    }

    int priority = prefix.prefixLength() * PRIORITY_MULTIPLIER + PRIORITY_OFFSET;
    Key key = Key.of(prefix.toString(), appId);
    return MultiPointToSinglePointIntent.builder()
        .appId(appId)
        .key(key)
        .selector(selector.build())
        .treatment(treatment.build())
        .ingressPoints(ingressPorts)
        .egressPoint(egressPort)
        .priority(priority)
        .constraints(CONSTRAINTS)
        .build();
  }
  /** Tests a corner case, when there are no interfaces in the configuration. */
  @Test
  public void testNullInterfaces() {
    reset(interfaceService);
    interfaceService.addListener(anyObject(InterfaceListener.class));
    expectLastCall().anyTimes();

    expect(interfaceService.getInterfaces()).andReturn(Sets.newHashSet()).anyTimes();
    expect(interfaceService.getInterfacesByPort(s2Eth1))
        .andReturn(Collections.emptySet())
        .anyTimes();
    expect(interfaceService.getInterfacesByPort(s1Eth1))
        .andReturn(Collections.emptySet())
        .anyTimes();
    expect(interfaceService.getInterfacesByIp(IpAddress.valueOf("192.168.10.101")))
        .andReturn(Collections.emptySet())
        .anyTimes();
    expect(interfaceService.getMatchingInterface(IpAddress.valueOf("192.168.10.1")))
        .andReturn(null)
        .anyTimes();
    expect(interfaceService.getInterfacesByIp(IpAddress.valueOf("192.168.20.101")))
        .andReturn(Collections.emptySet())
        .anyTimes();
    expect(interfaceService.getMatchingInterface(IpAddress.valueOf("192.168.20.1")))
        .andReturn(null)
        .anyTimes();
    expect(interfaceService.getInterfacesByIp(IpAddress.valueOf("192.168.30.101")))
        .andReturn(Collections.emptySet())
        .anyTimes();
    expect(interfaceService.getMatchingInterface(IpAddress.valueOf("192.168.30.1")))
        .andReturn(null)
        .anyTimes();
    expect(interfaceService.getInterfacesByIp(IpAddress.valueOf("192.168.40.101")))
        .andReturn(Collections.emptySet())
        .anyTimes();
    expect(interfaceService.getMatchingInterface(IpAddress.valueOf("192.168.40.1")))
        .andReturn(null)
        .anyTimes();
    expect(interfaceService.getInterfacesByIp(IpAddress.valueOf("192.168.50.101")))
        .andReturn(Collections.emptySet())
        .anyTimes();
    expect(interfaceService.getMatchingInterface(IpAddress.valueOf("192.168.50.1")))
        .andReturn(null)
        .anyTimes();

    replay(interfaceService);

    reset(intentSynchronizer);
    replay(intentSynchronizer);
    peerConnectivityManager.start();
    verify(intentSynchronizer);
  }
  /**
   * Sets up logical interfaces, which emulate the configured interfaces in SDN-IP application.
   *
   * @return configured interfaces as a map from interface name to Interface
   */
  private Map<String, Interface> setUpInterfaces() {

    Map<String, Interface> configuredInterfaces = new HashMap<>();

    String interfaceSw1Eth1 = "s1-eth1";
    InterfaceIpAddress ia1 =
        new InterfaceIpAddress(
            IpAddress.valueOf("192.168.10.101"), IpPrefix.valueOf("192.168.10.0/24"));
    Interface intfsw1eth1 =
        new Interface(
            interfaceSw1Eth1,
            s1Eth1,
            Collections.singletonList(ia1),
            MacAddress.valueOf("00:00:00:00:00:01"),
            VlanId.NONE);

    configuredInterfaces.put(interfaceSw1Eth1, intfsw1eth1);

    String interfaceSw2Eth1 = "s2-eth1";
    InterfaceIpAddress ia2 =
        new InterfaceIpAddress(
            IpAddress.valueOf("192.168.20.101"), IpPrefix.valueOf("192.168.20.0/24"));
    Interface intfsw2eth1 =
        new Interface(
            interfaceSw2Eth1,
            s2Eth1,
            Collections.singletonList(ia2),
            MacAddress.valueOf("00:00:00:00:00:02"),
            VlanId.NONE);

    configuredInterfaces.put(interfaceSw2Eth1, intfsw2eth1);

    String interfaceSw2Eth1intf2 = "s2-eth1_2";
    InterfaceIpAddress ia3 =
        new InterfaceIpAddress(
            IpAddress.valueOf("192.168.30.101"), IpPrefix.valueOf("192.168.30.0/24"));
    Interface intfsw2eth1intf2 =
        new Interface(
            interfaceSw2Eth1intf2,
            s2Eth1,
            Collections.singletonList(ia3),
            MacAddress.valueOf("00:00:00:00:00:03"),
            VlanId.NONE);

    configuredInterfaces.put(interfaceSw2Eth1intf2, intfsw2eth1intf2);

    String interfaceSw3Eth1 = "s3-eth1";
    InterfaceIpAddress ia4 =
        new InterfaceIpAddress(
            IpAddress.valueOf("192.168.40.101"), IpPrefix.valueOf("192.168.40.0/24"));
    Interface intfsw3eth1 =
        new Interface(
            Interface.NO_INTERFACE_NAME,
            s3Eth1,
            ImmutableList.of(ia4),
            MacAddress.valueOf("00:00:00:00:00:04"),
            VLAN10);

    configuredInterfaces.put(interfaceSw3Eth1, intfsw3eth1);

    String interfaceSw3Eth1intf2 = "s3-eth1_2";
    InterfaceIpAddress ia5 =
        new InterfaceIpAddress(
            IpAddress.valueOf("192.168.50.101"), IpPrefix.valueOf("192.168.50.0/24"));
    Interface intfsw3eth1intf2 =
        new Interface(
            Interface.NO_INTERFACE_NAME,
            s3Eth1,
            ImmutableList.of(ia5),
            MacAddress.valueOf("00:00:00:00:00:05"),
            VLAN20);

    configuredInterfaces.put(interfaceSw3Eth1intf2, intfsw3eth1intf2);

    expect(interfaceService.getInterfacesByPort(s1Eth1))
        .andReturn(Collections.singleton(intfsw1eth1))
        .anyTimes();
    expect(interfaceService.getInterfacesByIp(IpAddress.valueOf("192.168.10.101")))
        .andReturn(Collections.singleton(intfsw1eth1))
        .anyTimes();
    expect(interfaceService.getMatchingInterface(IpAddress.valueOf("192.168.10.1")))
        .andReturn(intfsw1eth1)
        .anyTimes();

    expect(interfaceService.getInterfacesByPort(s2Eth1))
        .andReturn(Collections.singleton(intfsw2eth1))
        .anyTimes();
    expect(interfaceService.getInterfacesByIp(IpAddress.valueOf("192.168.20.101")))
        .andReturn(Collections.singleton(intfsw2eth1))
        .anyTimes();
    expect(interfaceService.getMatchingInterface(IpAddress.valueOf("192.168.20.1")))
        .andReturn(intfsw2eth1)
        .anyTimes();

    expect(interfaceService.getInterfacesByIp(IpAddress.valueOf("192.168.30.101")))
        .andReturn(Collections.singleton(intfsw2eth1intf2))
        .anyTimes();
    expect(interfaceService.getMatchingInterface(IpAddress.valueOf("192.168.30.1")))
        .andReturn(intfsw2eth1intf2)
        .anyTimes();

    expect(interfaceService.getInterfacesByIp(IpAddress.valueOf("192.168.40.101")))
        .andReturn(Collections.singleton(intfsw3eth1))
        .anyTimes();
    expect(interfaceService.getMatchingInterface(IpAddress.valueOf("192.168.40.1")))
        .andReturn(intfsw3eth1)
        .anyTimes();

    expect(interfaceService.getInterfacesByIp(IpAddress.valueOf("192.168.50.101")))
        .andReturn(Collections.singleton(intfsw3eth1intf2))
        .anyTimes();
    expect(interfaceService.getMatchingInterface(IpAddress.valueOf("192.168.50.1")))
        .andReturn(intfsw3eth1intf2)
        .anyTimes();

    // Non-existent interface used during one of the tests
    expect(
            interfaceService.getInterfacesByPort(
                new ConnectPoint(
                    DeviceId.deviceId("of:0000000000000100"), PortNumber.portNumber(1))))
        .andReturn(null)
        .anyTimes();

    expect(interfaceService.getInterfaces())
        .andReturn(Sets.newHashSet(configuredInterfaces.values()))
        .anyTimes();

    return configuredInterfaces;
  }