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