Exemple #1
0
 /**
  * Returns ordered intent key from network and two hosts.
  *
  * @param network network name
  * @param one host one
  * @param two host two
  * @return canonical intent string key
  */
 protected Key generateKey(String network, HostId one, HostId two) {
   String hosts =
       one.toString().compareTo(two.toString()) < 0
           ? format(HOST_FORMAT, one, two)
           : format(HOST_FORMAT, two, one);
   return Key.of(format(KEY_FORMAT, network, hosts), appId);
 }
Exemple #2
0
  private void sendArpResponse(ARP arpRequest, MacAddress targetMac, VlanId vlanId) {
    ARP arpReply = new ARP();
    arpReply
        .setHardwareType(ARP.HW_TYPE_ETHERNET)
        .setProtocolType(ARP.PROTO_TYPE_IP)
        .setHardwareAddressLength((byte) Ethernet.DATALAYER_ADDRESS_LENGTH)
        .setProtocolAddressLength((byte) Ip4Address.BYTE_LENGTH)
        .setOpCode(ARP.OP_REPLY)
        .setSenderHardwareAddress(targetMac.toBytes())
        .setSenderProtocolAddress(arpRequest.getTargetProtocolAddress())
        .setTargetHardwareAddress(arpRequest.getSenderHardwareAddress())
        .setTargetProtocolAddress(arpRequest.getSenderProtocolAddress());

    Ethernet eth = new Ethernet();
    eth.setDestinationMACAddress(arpRequest.getSenderHardwareAddress())
        .setSourceMACAddress(targetMac.toBytes())
        .setEtherType(Ethernet.TYPE_ARP)
        .setPayload(arpReply);

    MacAddress hostMac = MacAddress.valueOf(arpReply.getTargetHardwareAddress());
    HostId dstId = HostId.hostId(hostMac, vlanId);
    Host dst = srManager.hostService.getHost(dstId);
    if (dst == null) {
      log.warn("Cannot send ARP response to host {}", dstId);
      return;
    }

    TrafficTreatment treatment =
        DefaultTrafficTreatment.builder().setOutput(dst.location().port()).build();
    OutboundPacket packet =
        new DefaultOutboundPacket(
            dst.location().deviceId(), treatment, ByteBuffer.wrap(eth.serialize()));

    srManager.packetService.emit(packet);
  }
Exemple #3
0
  private void handleArpReply(DeviceId deviceId, ConnectPoint inPort, Ethernet payload) {
    ARP arpReply = (ARP) payload.getPayload();
    VlanId vlanId = VlanId.vlanId(payload.getVlanID());
    HostId targetHostId =
        HostId.hostId(MacAddress.valueOf(arpReply.getTargetHardwareAddress()), vlanId);

    // ARP reply for router. Process all pending IP packets.
    if (isArpForRouter(deviceId, arpReply)) {
      Ip4Address hostIpAddress = Ip4Address.valueOf(arpReply.getSenderProtocolAddress());
      srManager.ipHandler.forwardPackets(deviceId, hostIpAddress);
    } else {
      Host targetHost = srManager.hostService.getHost(targetHostId);
      // ARP reply for known hosts. Forward to the host.
      if (targetHost != null) {
        removeVlanAndForward(payload, targetHost.location());
        // ARP reply for unknown host, Flood in the subnet.
      } else {
        // Don't flood to non-edge ports
        if (vlanId.equals(VlanId.vlanId(SegmentRoutingManager.ASSIGNED_VLAN_NO_SUBNET))) {
          return;
        }
        removeVlanAndFlood(payload, inPort);
      }
    }
  }
Exemple #4
0
 private Set<Host> constructHostIds(Iterator<JsonNode> elements) {
   Set<Host> hostIds = Sets.newHashSet();
   JsonNode n;
   while (elements.hasNext()) {
     n = elements.next();
     hostIds.add(hostService.getHost(HostId.hostId(n.textValue())));
   }
   return hostIds;
 }
Exemple #5
0
  /**
   * Matches an intent to a network and optional host.
   *
   * @param network network name
   * @param id optional host id, wildcard if missing
   * @param intent intent to match
   * @return true if intent matches, false otherwise
   */
  protected boolean matches(String network, Optional<HostId> id, Intent intent) {
    if (!Objects.equals(appId, intent.appId())) {
      // different app ids
      return false;
    }

    String key = intent.key().toString();
    if (!key.startsWith(network)) {
      // different network
      return false;
    }

    if (!id.isPresent()) {
      // no host id specified; wildcard match
      return true;
    }

    HostId hostId = id.get();
    String[] fields = key.split(",");
    // return result of id match in host portion of key
    return fields.length > 1 && fields[1].contains(hostId.toString());
  }
Exemple #6
0
  // Parses the given node with host data and supplies the host.
  private void parseHost(JsonNode node) {
    MacAddress mac = MacAddress.valueOf(get(node, "mac"));
    VlanId vlanId = VlanId.vlanId((short) node.get("vlan").asInt(VlanId.UNTAGGED));
    HostId hostId = HostId.hostId(mac, vlanId);
    SparseAnnotations annotations = annotations(node.get("annotations"));
    HostLocation location = new HostLocation(connectPoint(get(node, "location")), 0);

    String[] ipStrings = get(node, "ip", "").split(",");
    Set<IpAddress> ips = new HashSet<>();
    for (String ip : ipStrings) {
      ips.add(IpAddress.valueOf(ip.trim()));
    }

    DefaultHostDescription desc =
        new DefaultHostDescription(mac, vlanId, location, ips, annotations);
    hostProviderService.hostDetected(hostId, desc);

    connectPoints.add(location);
  }
Exemple #7
0
  private void handleArpRequest(DeviceId deviceId, ConnectPoint inPort, Ethernet payload) {
    ARP arpRequest = (ARP) payload.getPayload();
    VlanId vlanId = VlanId.vlanId(payload.getVlanID());
    HostId targetHostId =
        HostId.hostId(MacAddress.valueOf(arpRequest.getTargetHardwareAddress()), vlanId);

    // ARP request for router. Send ARP reply.
    if (isArpForRouter(deviceId, arpRequest)) {
      Ip4Address targetAddress = Ip4Address.valueOf(arpRequest.getTargetProtocolAddress());
      sendArpResponse(arpRequest, config.getRouterMacForAGatewayIp(targetAddress), vlanId);
    } else {
      Host targetHost = srManager.hostService.getHost(targetHostId);
      // ARP request for known hosts. Send proxy ARP reply on behalf of the target.
      if (targetHost != null) {
        removeVlanAndForward(payload, targetHost.location());
        // ARP request for unknown host in the subnet. Flood in the subnet.
      } else {
        removeVlanAndFlood(payload, inPort);
      }
    }
  }
Exemple #8
0
  @Override
  public void addServiceVm(CordVtnNode node, ConnectPoint connectPoint) {
    Port port = deviceService.getPort(connectPoint.deviceId(), connectPoint.port());
    OpenstackPort vPort = openstackService.port(port);
    if (vPort == null) {
      log.warn("Failed to get OpenstackPort for {}", getPortName(port));
      return;
    }

    MacAddress mac = vPort.macAddress();
    HostId hostId = HostId.hostId(mac);

    Host host = hostService.getHost(hostId);
    if (host != null) {
      // Host is already known to the system, no HOST_ADDED event is triggered in this case.
      // It happens when the application is restarted.
      // TODO check host description if it has all the information
      serviceVmAdded(host);
      return;
    }

    Set<IpAddress> ip = Sets.newHashSet(vPort.fixedIps().values());
    SparseAnnotations annotations =
        DefaultAnnotations.builder()
            .set(OPENSTACK_VM_ID, vPort.deviceId())
            .set(SERVICE_ID, vPort.networkId())
            .set(LOCATION_IP, node.localIp().toString())
            .build();

    HostDescription hostDesc =
        new DefaultHostDescription(
            mac,
            VlanId.NONE,
            new HostLocation(connectPoint, System.currentTimeMillis()),
            ip,
            annotations);

    hostProvider.hostDetected(hostId, hostDesc, false);
  }
  private void updateForMode(String id) {
    log.debug("host service: {}", hostService);
    log.debug("device service: {}", deviceService);

    try {
      HostId hid = HostId.hostId(id);
      log.debug("host id {}", hid);
      elementOfNote = hostService.getHost(hid);
      log.debug("host element {}", elementOfNote);

    } catch (Exception e) {
      try {
        DeviceId did = DeviceId.deviceId(id);
        log.debug("device id {}", did);
        elementOfNote = deviceService.getDevice(did);
        log.debug("device element {}", elementOfNote);

      } catch (Exception e2) {
        log.debug("Unable to process ID [{}]", id);
        elementOfNote = null;
      }
    }

    switch (currentMode) {
      case MOUSE:
        sendMouseData();
        break;

      case LINK:
        sendLinkData();
        break;

      default:
        break;
    }
  }
    @Override
    public void process(PacketContext context) {
      // Stop processing if the packet has been handled, since we
      // can't do any more to it.
      if (context.isHandled()) {
        return;
      }

      InboundPacket pkt = context.inPacket();
      Ethernet ethPkt = pkt.parsed();

      if (ethPkt == null) {
        return;
      }

      // Bail if this is deemed to be a control packet.
      if (isControlPacket(ethPkt)) {
        return;
      }

      // Skip IPv6 multicast packet when IPv6 forward is disabled.
      if (!ipv6Forwarding && isIpv6Multicast(ethPkt)) {
        return;
      }

      HostId id = HostId.hostId(ethPkt.getDestinationMAC());

      // Do not process link-local addresses in any way.
      if (id.mac().isLinkLocal()) {
        return;
      }

      // Do we know who this is for? If not, flood and bail.
      Host dst = hostService.getHost(id);
      if (dst == null) {
        flood(context);
        return;
      }

      // Are we on an edge switch that our destination is on? If so,
      // simply forward out to the destination and bail.
      if (pkt.receivedFrom().deviceId().equals(dst.location().deviceId())) {
        if (!context.inPacket().receivedFrom().port().equals(dst.location().port())) {
          installRule(context, dst.location().port());
        }
        return;
      }

      // Otherwise, get a set of paths that lead from here to the
      // destination edge switch.
      Set<Path> paths =
          topologyService.getPaths(
              topologyService.currentTopology(),
              pkt.receivedFrom().deviceId(),
              dst.location().deviceId());
      if (paths.isEmpty()) {
        // If there are no paths, flood and bail.
        flood(context);
        return;
      }

      // Otherwise, pick a path that does not lead back to where we
      // came from; if no such path, flood and bail.
      Path path = pickForwardPath(paths, pkt.receivedFrom().port());
      if (path == null) {
        log.warn(
            "Doh... don't know where to go... {} -> {} received on {}",
            ethPkt.getSourceMAC(),
            ethPkt.getDestinationMAC(),
            pkt.receivedFrom());
        flood(context);
        return;
      }

      // Otherwise forward and be done with it.
      installRule(context, path.src().port());
    }
Exemple #11
0
/** Tests for the {@link Vpls} class. */
public class VplsTest {

  private static final int NUM_DEVICES = 7;

  private static final MacAddress MAC1 = MacAddress.valueOf("00:00:00:00:00:01");
  private static final MacAddress MAC2 = MacAddress.valueOf("00:00:00:00:00:02");
  private static final MacAddress MAC3 = MacAddress.valueOf("00:00:00:00:00:03");
  private static final MacAddress MAC4 = MacAddress.valueOf("00:00:00:00:00:04");
  private static final MacAddress MAC5 = MacAddress.valueOf("00:00:00:00:00:05");
  private static final MacAddress MAC6 = MacAddress.valueOf("00:00:00:00:00:06");
  private static final MacAddress MAC7 = MacAddress.valueOf("00:00:00:00:00:07");

  private static final Ip4Address IP1 = Ip4Address.valueOf("192.168.1.1");
  private static final Ip4Address IP2 = Ip4Address.valueOf("192.168.1.2");

  private static final PortNumber P1 = PortNumber.portNumber(1);

  private static final VlanId VLAN1 = VlanId.vlanId((short) 1);
  private static final VlanId VLAN2 = VlanId.vlanId((short) 2);

  private static final int PRIORITY_OFFSET = 1000;
  private static final String PREFIX_BROADCAST = "brc";
  private static final String PREFIX_UNICAST = "uni";

  private static final DeviceId DID1 = getDeviceId(1);
  private static final DeviceId DID2 = getDeviceId(2);
  private static final DeviceId DID3 = getDeviceId(3);
  private static final DeviceId DID4 = getDeviceId(4);
  private static final DeviceId DID5 = getDeviceId(5);
  private static final DeviceId DID6 = getDeviceId(6);

  private static final ConnectPoint C1 = new ConnectPoint(DID1, P1);
  private static final ConnectPoint C2 = new ConnectPoint(DID2, P1);
  private static final ConnectPoint C3 = new ConnectPoint(DID3, P1);
  private static final ConnectPoint C4 = new ConnectPoint(DID4, P1);
  private static final ConnectPoint C5 = new ConnectPoint(DID5, P1);
  private static final ConnectPoint C6 = new ConnectPoint(DID6, P1);

  private static final HostId HID1 = HostId.hostId(MAC1, VLAN1);
  private static final HostId HID2 = HostId.hostId(MAC2, VLAN1);
  private static final HostId HID3 = HostId.hostId(MAC3, VLAN1);
  private static final HostId HID4 = HostId.hostId(MAC4, VLAN2);
  private static final HostId HID5 = HostId.hostId(MAC5, VLAN2);
  private static final HostId HID6 = HostId.hostId(MAC6, VLAN2);
  private static final HostId HID7 = HostId.hostId(MAC7, VlanId.NONE);

  private ApplicationService applicationService;
  private CoreService coreService;
  private HostListener hostListener;
  private Set<Host> hostsAvailable;
  private HostService hostService;
  private IntentService intentService;
  private InterfaceService interfaceService;
  private Vpls vpls;

  private static final String APP_NAME = "org.onosproject.vpls";
  private static final ApplicationId APPID = TestApplicationId.create(APP_NAME);

  private static final ProviderId PID = new ProviderId("of", "foo");

  private static IdGenerator idGenerator;

  @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;
  }

  @After
  public void tearDown() {
    Intent.unbindIdGenerator(idGenerator);
  }

  /**
   * 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);
  }

  /**
   * Checks the case in which six ports are configured with VLANs but no hosts are registered by the
   * HostService. The first three ports have an interface configured on VLAN1, the other three on
   * VLAN2. The number of intents expected is six: three for VLAN1, three for VLAN2. three sp2mp
   * intents, three mp2sp intents.
   */
  @Test
  public void testActivateNoHosts() {
    vpls.activate();

    List<Intent> expectedIntents = Lists.newArrayList();
    expectedIntents.addAll(generateVlanOneBrc());
    expectedIntents.addAll(generateVlanTwoBrc());

    checkIntents(expectedIntents);
  }

  /**
   * Checks the case in which six ports are configured with VLANs and four hosts are registered by
   * the HostService. The first three ports have an interface configured on VLAN1, the other three
   * on VLAN2. The number of intents expected is twelve: six for VLAN1, six for VLAN2. six sp2mp
   * intents, six mp2sp intents. For VLAN1 IPs are added to demonstrate it doesn't influence the
   * number of intents created.
   */
  @Test
  public void testFourInterfacesConfiguredHostsPresent() {
    Host h1 = new DefaultHost(PID, HID1, MAC1, VLAN1, getLocation(1), Collections.singleton(IP1));
    Host h2 = new DefaultHost(PID, HID2, MAC2, VLAN1, getLocation(2), Collections.singleton(IP2));
    Host h3 = new DefaultHost(PID, HID3, MAC3, VLAN1, getLocation(3), Collections.EMPTY_SET);
    Host h4 = new DefaultHost(PID, HID4, MAC4, VLAN2, getLocation(4), Collections.EMPTY_SET);
    Host h5 = new DefaultHost(PID, HID5, MAC5, VLAN2, getLocation(5), Collections.EMPTY_SET);
    Host h6 = new DefaultHost(PID, HID6, MAC6, VLAN2, getLocation(6), Collections.EMPTY_SET);
    hostsAvailable.addAll(Sets.newHashSet(h1, h2, h3, h4, h5, h6));

    vpls.activate();

    List<Intent> expectedIntents = Lists.newArrayList();
    expectedIntents.addAll(generateVlanOneBrc());
    expectedIntents.addAll(generateVlanOneUni());
    expectedIntents.addAll(generateVlanTwoBrc());
    expectedIntents.addAll(generateVlanTwoUni());

    checkIntents(expectedIntents);
  }

  /**
   * Checks the case in which six ports are configured with VLANs and initially no hosts are
   * registered by the HostService. The first three ports have an interface configured on VLAN1, the
   * other three have an interface configured on VLAN2. When the module starts up, three hosts - on
   * device one, two and three - port 1 (both on VLAN1), are registered by the HostService and
   * events are sent to the application. sp2mp intents are created for all interfaces configured and
   * mp2sp intents are created only for the hosts attached. The number of intents expected is nine:
   * six for VLAN1, three for VLAN2. Six sp2mp intents, three mp2sp intents. IPs are added on the
   * first two hosts only to demonstrate it doesn't influence the number of intents created. An
   * additional host is added on device seven, port one to demonstrate that, even if it's on the
   * same VLAN of other interfaces configured in the system, it doesn't let the application generate
   * intents, since it's not connected to the interface configured.
   */
  @Test
  public void testFourInterfacesThreeHostEventsSameVlan() {
    vpls.activate();

    Host h1 = new DefaultHost(PID, HID1, MAC1, VLAN1, getLocation(1), Collections.singleton(IP1));
    Host h2 = new DefaultHost(PID, HID2, MAC2, VLAN1, getLocation(2), Collections.singleton(IP2));
    Host h3 = new DefaultHost(PID, HID3, MAC3, VLAN1, getLocation(3), Collections.EMPTY_SET);
    Host h7 = new DefaultHost(PID, HID7, MAC7, VLAN1, getLocation(7), Collections.EMPTY_SET);
    hostsAvailable.addAll(Sets.newHashSet(h1, h2, h3, h7));

    hostsAvailable.forEach(
        host -> hostListener.event(new HostEvent(HostEvent.Type.HOST_ADDED, host)));

    List<Intent> expectedIntents = Lists.newArrayList();
    expectedIntents.addAll(generateVlanOneBrc());
    expectedIntents.addAll(generateVlanOneUni());
    expectedIntents.addAll(generateVlanTwoBrc());

    checkIntents(expectedIntents);
  }

  /**
   * Checks the case in which six ports are configured with VLANs and initially no hosts are
   * registered by the HostService. The first three ports have an interface configured on VLAN1, the
   * other three have an interface configured on VLAN2. When the module starts up, two hosts - on
   * device one and four - port 1 (VLAN 1 and VLAN 2), are registered by the HostService and events
   * are sent to the application. sp2mp intents are created for all interfaces configured and no
   * mp2sp intents are created at all, since the minimum number of hosts needed on the same vlan to
   * create mp2sp intents is 2. The number of intents expected is six: three for VLAN1, three for
   * VLAN2. six sp2mp intents, zero mp2sp intents. IPs are added on the first host only to
   * demonstrate it doesn't influence the number of intents created.
   */
  @Test
  public void testFourInterfacesTwoHostEventsDifferentVlan() {
    vpls.activate();

    Host h1 = new DefaultHost(PID, HID1, MAC1, VLAN1, getLocation(1), Collections.singleton(IP1));
    Host h4 = new DefaultHost(PID, HID4, MAC4, VLAN2, getLocation(4), Collections.EMPTY_SET);
    hostsAvailable.addAll(Sets.newHashSet(h1, h4));

    hostsAvailable.forEach(
        host -> {
          hostListener.event(new HostEvent(HostEvent.Type.HOST_ADDED, host));
        });

    List<Intent> expectedIntents = Lists.newArrayList();
    expectedIntents.addAll(generateVlanOneBrc());
    expectedIntents.addAll(generateVlanTwoBrc());

    checkIntents(expectedIntents);
  }

  /**
   * Checks both that the number of intents in submitted in the intent framework it's equal to the
   * number of intents expected and that all intents are equivalent.
   *
   * @param intents the list of intents expected
   */
  private void checkIntents(List<Intent> intents) {
    assertEquals(intents.size(), intentService.getIntentCount());

    for (Intent intentOne : intents) {
      boolean found = false;
      for (Intent intentTwo : intentService.getIntents()) {
        if (intentOne.key().equals(intentTwo.key())) {
          found = true;
          assertTrue(
              format("Comparing %s and %s", intentOne, intentTwo),
              IntentUtils.intentsAreEqual(intentOne, intentTwo));
          break;
        }
      }
      assertTrue(found);
    }
  }

  /**
   * Generates the list of the expected sp2mp intents for VLAN 1.
   *
   * @return the list of expected sp2mp intents for VLAN 1
   */
  private List<SinglePointToMultiPointIntent> generateVlanOneBrc() {
    Key key = null;

    List<SinglePointToMultiPointIntent> intents = Lists.newArrayList();

    // Building sp2mp intent for H1 - VLAN1
    key = Key.of((PREFIX_BROADCAST + "-" + DID1 + "-" + P1 + "-" + VLAN1), APPID);
    intents.add(buildBrcIntent(key, C1, Sets.newHashSet(C2, C3), VLAN1));

    // Building sp2mp intent for H2 - VLAN1
    key = Key.of((PREFIX_BROADCAST + "-" + DID2 + "-" + P1 + "-" + VLAN1), APPID);
    intents.add(buildBrcIntent(key, C2, Sets.newHashSet(C1, C3), VLAN1));

    // Building sp2mp intent for H3 - VLAN1
    key = Key.of((PREFIX_BROADCAST + "-" + DID3 + "-" + P1 + "-" + VLAN1), APPID);
    intents.add(buildBrcIntent(key, C3, Sets.newHashSet(C1, C2), VLAN1));

    return intents;
  }

  /**
   * Generates the list of the expected mp2sp intents for VLAN 1.
   *
   * @return the list of expected mp2sp intents for VLAN 1
   */
  private List<MultiPointToSinglePointIntent> generateVlanOneUni() {
    Key key = null;

    List<MultiPointToSinglePointIntent> intents = Lists.newArrayList();

    // Building mp2sp intent for H1 - VLAN1
    key = Key.of((PREFIX_UNICAST + "-" + DID1 + "-" + P1 + "-" + VLAN1), APPID);
    intents.add(buildUniIntent(key, Sets.newHashSet(C2, C3), C1, VLAN1, MAC1));

    // Building mp2sp intent for H2 - VLAN1
    key = Key.of((PREFIX_UNICAST + "-" + DID2 + "-" + P1 + "-" + VLAN1), APPID);
    intents.add(buildUniIntent(key, Sets.newHashSet(C1, C3), C2, VLAN1, MAC2));

    // Building mp2sp intent for H3 - VLAN1
    key = Key.of((PREFIX_UNICAST + "-" + DID3 + "-" + P1 + "-" + VLAN1), APPID);
    intents.add(buildUniIntent(key, Sets.newHashSet(C1, C2), C3, VLAN1, MAC3));

    return intents;
  }

  /**
   * Generates the list of the expected sp2mp intents for VLAN 2.
   *
   * @return the list of expected sp2mp intents for VLAN 2
   */
  private List<SinglePointToMultiPointIntent> generateVlanTwoBrc() {
    Key key = null;

    List<SinglePointToMultiPointIntent> intents = Lists.newArrayList();

    // Building sp2mp intent for H4 - VLAN2
    key = Key.of((PREFIX_BROADCAST + "-" + DID4 + "-" + P1 + "-" + VLAN2), APPID);
    intents.add(buildBrcIntent(key, C4, Sets.newHashSet(C5, C6), VLAN2));

    // Building sp2mp intent for H5 - VLAN2
    key = Key.of((PREFIX_BROADCAST + "-" + DID5 + "-" + P1 + "-" + VLAN2), APPID);
    intents.add(buildBrcIntent(key, C5, Sets.newHashSet(C4, C6), VLAN2));

    // Building sp2mp intent for H6 - VLAN2
    key = Key.of((PREFIX_BROADCAST + "-" + DID6 + "-" + P1 + "-" + VLAN2), APPID);
    intents.add(buildBrcIntent(key, C6, Sets.newHashSet(C4, C5), VLAN2));

    return intents;
  }

  /**
   * Generates the list of the expected mp2sp intents for VLAN 2.
   *
   * @return the list of expected mp2sp intents for VLAN 2
   */
  private List<MultiPointToSinglePointIntent> generateVlanTwoUni() {
    Key key = null;

    List<MultiPointToSinglePointIntent> intents = Lists.newArrayList();

    // Building mp2sp intent for H4 - VLAN2
    key = Key.of((PREFIX_UNICAST + "-" + DID4 + "-" + P1 + "-" + VLAN2), APPID);
    intents.add(buildUniIntent(key, Sets.newHashSet(C5, C6), C4, VLAN2, MAC4));

    // Building mp2sp intent for H5 - VLAN2
    key = Key.of((PREFIX_UNICAST + "-" + DID5 + "-" + P1 + "-" + VLAN2), APPID);
    intents.add(buildUniIntent(key, Sets.newHashSet(C4, C6), C5, VLAN2, MAC5));

    // Building mp2sp intent for H6 - VLAN2
    key = Key.of((PREFIX_UNICAST + "-" + DID6 + "-" + P1 + "-" + VLAN2), APPID);
    intents.add(buildUniIntent(key, Sets.newHashSet(C4, C5), C6, VLAN2, MAC6));

    return intents;
  }

  /**
   * Builds a Single Point to Multi Point intent.
   *
   * @param key The intent key
   * @param src The source Connect Point
   * @param dsts The destination Connect Points
   * @return Single Point to Multi Point intent generated.
   */
  private SinglePointToMultiPointIntent buildBrcIntent(
      Key key, ConnectPoint src, Set<ConnectPoint> dsts, VlanId vlanId) {
    SinglePointToMultiPointIntent intent;

    TrafficTreatment treatment = DefaultTrafficTreatment.emptyTreatment();

    TrafficSelector selector =
        DefaultTrafficSelector.builder()
            .matchEthDst(MacAddress.BROADCAST)
            .matchVlanId(vlanId)
            .build();

    intent =
        SinglePointToMultiPointIntent.builder()
            .appId(APPID)
            .key(key)
            .selector(selector)
            .treatment(treatment)
            .ingressPoint(src)
            .egressPoints(dsts)
            .priority(PRIORITY_OFFSET)
            .build();
    return intent;
  }

  /**
   * Builds a Multi Point to Single Point intent.
   *
   * @param key The intent key
   * @param srcs The source Connect Points
   * @param dst The destination Connect Point
   * @return Multi Point to Single Point intent generated.
   */
  private MultiPointToSinglePointIntent buildUniIntent(
      Key key, Set<ConnectPoint> srcs, ConnectPoint dst, VlanId vlanId, MacAddress mac) {
    MultiPointToSinglePointIntent intent;

    TrafficTreatment treatment = DefaultTrafficTreatment.emptyTreatment();

    TrafficSelector.Builder builder =
        DefaultTrafficSelector.builder().matchEthDst(mac).matchVlanId(vlanId);

    TrafficSelector selector = builder.build();

    intent =
        MultiPointToSinglePointIntent.builder()
            .appId(APPID)
            .key(key)
            .selector(selector)
            .treatment(treatment)
            .ingressPoints(srcs)
            .egressPoint(dst)
            .priority(PRIORITY_OFFSET)
            .build();
    return intent;
  }

  /**
   * Returns the device ID of the ith device.
   *
   * @param i device to get the ID of
   * @return the device ID
   */
  private static DeviceId getDeviceId(int i) {
    return DeviceId.deviceId("" + i);
  }

  private static HostLocation getLocation(int i) {
    return new HostLocation(new ConnectPoint(getDeviceId(i), P1), 123L);
  }

  /**
   * Represents a fake IntentService class that easily allows to store and retrieve intents without
   * implementing the IntentService logic.
   */
  private class TestIntentService extends IntentServiceAdapter {

    private Set<Intent> intents;

    public TestIntentService() {
      intents = Sets.newHashSet();
    }

    @Override
    public void submit(Intent intent) {
      intents.add(intent);
    }

    @Override
    public long getIntentCount() {
      return intents.size();
    }

    @Override
    public Iterable<Intent> getIntents() {
      return intents;
    }

    @Override
    public Intent getIntent(Key intentKey) {
      for (Intent intent : intents) {
        if (intent.key().equals(intentKey)) {
          return intent;
        }
      }
      return null;
    }
  }

  /**
   * Represents a fake HostService class which allows to add hosts manually in each test, when
   * needed.
   */
  private class TestHostService extends HostServiceAdapter {

    private Set<Host> hosts;

    public TestHostService(Set<Host> hosts) {
      this.hosts = hosts;
    }

    @Override
    public void addListener(HostListener listener) {
      VplsTest.this.hostListener = listener;
    }

    @Override
    public Set<Host> getConnectedHosts(ConnectPoint connectPoint) {
      return hosts
          .stream()
          .filter(
              h ->
                  h.location().elementId().equals(connectPoint.elementId())
                      && h.location().port().equals(connectPoint.port()))
          .collect(Collectors.toSet());
    }
  }

  private static class TestIdGenerator implements IdGenerator {

    private final AtomicLong id = new AtomicLong(0);

    @Override
    public long getNewId() {
      return id.getAndIncrement();
    }
  }

  /** Test IntentSynchronizer that passes all intents straight through to the intent service. */
  private class TestIntentSynchronizer
      implements IntentSynchronizationService, IntentSynchronizationAdminService {

    private final IntentService intentService;

    /**
     * Creates a new test intent synchronizer.
     *
     * @param intentService intent service
     */
    public TestIntentSynchronizer(IntentService intentService) {
      this.intentService = intentService;
    }

    @Override
    public void submit(Intent intent) {
      intentService.submit(intent);
    }

    @Override
    public void withdraw(Intent intent) {
      intentService.withdraw(intent);
    }

    @Override
    public void modifyPrimary(boolean isPrimary) {}

    @Override
    public void removeIntents() {}

    @Override
    public void removeIntentsByAppId(ApplicationId applicationId) {}
  }
}
Exemple #12
0
 @Override
 public HostId createSubject(String key) {
   return HostId.hostId(key);
 }
    @Override
    public void process(PacketContext context) {
      if (context == null) {
        return;
      }
      Ethernet eth = context.inPacket().parsed();

      if (eth == null) {
        return;
      }

      VlanId vlan = VlanId.vlanId(eth.getVlanID());
      ConnectPoint heardOn = context.inPacket().receivedFrom();

      // If this is not an edge port, bail out.
      Topology topology = topologyService.currentTopology();
      if (topologyService.isInfrastructure(topology, heardOn)) {
        return;
      }

      HostLocation hloc = new HostLocation(heardOn, System.currentTimeMillis());

      HostId hid = HostId.hostId(eth.getSourceMAC(), vlan);

      // ARP: possible new hosts, update both location and IP
      if (eth.getEtherType() == Ethernet.TYPE_ARP) {
        ARP arp = (ARP) eth.getPayload();
        IpAddress ip = IpAddress.valueOf(IpAddress.Version.INET, arp.getSenderProtocolAddress());
        HostDescription hdescr = new DefaultHostDescription(eth.getSourceMAC(), vlan, hloc, ip);
        providerService.hostDetected(hid, hdescr);

        // IPv4: update location only
      } else if (eth.getEtherType() == Ethernet.TYPE_IPV4) {
        HostDescription hdescr = new DefaultHostDescription(eth.getSourceMAC(), vlan, hloc);
        providerService.hostDetected(hid, hdescr);

        // NeighborAdvertisement and NeighborSolicitation: possible new hosts, update both location
        // and IP
        // IPv6: update location only
      } else if (eth.getEtherType() == Ethernet.TYPE_IPV6) {
        IpAddress ip = null;
        IPv6 ipv6 = (IPv6) eth.getPayload();

        IPacket iPkt = ipv6;
        while (iPkt != null) {
          if (iPkt instanceof NeighborAdvertisement || iPkt instanceof NeighborSolicitation) {
            IpAddress sourceAddress =
                IpAddress.valueOf(IpAddress.Version.INET6, ipv6.getSourceAddress());
            // Ignore DAD packets, in which source address is all zeros.
            if (!sourceAddress.isZero()) {
              ip = sourceAddress;
              break;
            }
          }
          iPkt = iPkt.getPayload();
        }
        HostDescription hdescr =
            (ip == null)
                ? new DefaultHostDescription(eth.getSourceMAC(), vlan, hloc)
                : new DefaultHostDescription(eth.getSourceMAC(), vlan, hloc, ip);
        providerService.hostDetected(hid, hdescr);
      }
    }