diff options
Diffstat (limited to 'framework/src/onos/core/net')
21 files changed, 620 insertions, 332 deletions
diff --git a/framework/src/onos/core/net/src/main/java/org/onosproject/app/impl/ApplicationManager.java b/framework/src/onos/core/net/src/main/java/org/onosproject/app/impl/ApplicationManager.java index 161659f9..d09eb1f1 100644 --- a/framework/src/onos/core/net/src/main/java/org/onosproject/app/impl/ApplicationManager.java +++ b/framework/src/onos/core/net/src/main/java/org/onosproject/app/impl/ApplicationManager.java @@ -15,6 +15,7 @@ */ package org.onosproject.app.impl; +import com.google.common.collect.Maps; import org.apache.felix.scr.annotations.Activate; import org.apache.felix.scr.annotations.Component; import org.apache.felix.scr.annotations.Deactivate; @@ -30,20 +31,21 @@ import org.onosproject.app.ApplicationService; import org.onosproject.app.ApplicationState; import org.onosproject.app.ApplicationStore; import org.onosproject.app.ApplicationStoreDelegate; -import org.onosproject.event.AbstractListenerManager; import org.onosproject.core.Application; import org.onosproject.core.ApplicationId; +import org.onosproject.event.AbstractListenerManager; import org.onosproject.security.Permission; import org.onosproject.security.SecurityUtil; import org.slf4j.Logger; import java.io.InputStream; +import java.util.Map; import java.util.Set; import static com.google.common.base.Preconditions.checkNotNull; import static org.onosproject.app.ApplicationEvent.Type.*; -import static org.onosproject.security.AppPermission.Type.*; import static org.onosproject.security.AppGuard.checkPermission; +import static org.onosproject.security.AppPermission.Type.APP_READ; import static org.slf4j.LoggerFactory.getLogger; /** @@ -69,6 +71,9 @@ public class ApplicationManager private boolean initializing; + // Application supplied hooks for pre-activation processing. + private final Map<String, Runnable> deactivateHooks = Maps.newConcurrentMap(); + @Activate public void activate() { eventDispatcher.addSink(ApplicationEvent.class, listenerRegistry); @@ -122,6 +127,14 @@ public class ApplicationManager } @Override + public void registerDeactivateHook(ApplicationId appId, Runnable hook) { + checkPermission(APP_READ); + checkNotNull(appId, APP_ID_NULL); + checkNotNull(hook, "Hook cannot be null"); + deactivateHooks.put(appId.name(), hook); + } + + @Override public Application install(InputStream appDescStream) { checkNotNull(appDescStream, "Application archive stream cannot be null"); Application app = store.create(appDescStream); @@ -199,6 +212,7 @@ public class ApplicationManager // The following methods are fully synchronized to guard against remote vs. // locally induced feature service interactions. + // Installs all feature repositories required by the specified app. private synchronized boolean installAppArtifacts(Application app) throws Exception { if (app.featuresRepo().isPresent() && featuresService.getRepository(app.featuresRepo().get()) == null) { @@ -208,6 +222,7 @@ public class ApplicationManager return false; } + // Uninstalls all the feature repositories required by the specified app. private synchronized boolean uninstallAppArtifacts(Application app) throws Exception { if (app.featuresRepo().isPresent() && featuresService.getRepository(app.featuresRepo().get()) != null) { @@ -217,6 +232,7 @@ public class ApplicationManager return false; } + // Installs all features that define the specified app. private synchronized boolean installAppFeatures(Application app) throws Exception { boolean changed = false; for (String name : app.features()) { @@ -233,8 +249,10 @@ public class ApplicationManager return changed; } + // Uninstalls all features that define the specified app. private synchronized boolean uninstallAppFeatures(Application app) throws Exception { boolean changed = false; + invokeHook(deactivateHooks.get(app.id().name()), app.id()); for (String name : app.features()) { Feature feature = featuresService.getFeature(name); if (feature != null && featuresService.isInstalled(feature)) { @@ -247,4 +265,16 @@ public class ApplicationManager return changed; } + // Invokes the specified function, if not null. + private void invokeHook(Runnable hook, ApplicationId appId) { + if (hook != null) { + try { + hook.run(); + } catch (Exception e) { + log.warn("Deactivate hook for application {} encountered an error", + appId.name(), e); + } + } + } + } diff --git a/framework/src/onos/core/net/src/main/java/org/onosproject/core/impl/CoreManager.java b/framework/src/onos/core/net/src/main/java/org/onosproject/core/impl/CoreManager.java index f4d560a4..ec99c18b 100644 --- a/framework/src/onos/core/net/src/main/java/org/onosproject/core/impl/CoreManager.java +++ b/framework/src/onos/core/net/src/main/java/org/onosproject/core/impl/CoreManager.java @@ -24,6 +24,7 @@ import org.apache.felix.scr.annotations.Reference; import org.apache.felix.scr.annotations.ReferenceCardinality; import org.apache.felix.scr.annotations.Service; import org.onlab.util.SharedExecutors; +import org.onosproject.app.ApplicationService; import org.onosproject.cfg.ComponentConfigService; import org.onosproject.core.ApplicationId; import org.onosproject.core.ApplicationIdStore; @@ -48,7 +49,7 @@ import java.util.Set; import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Strings.isNullOrEmpty; import static org.onosproject.security.AppGuard.checkPermission; -import static org.onosproject.security.AppPermission.Type.*; +import static org.onosproject.security.AppPermission.Type.APP_READ; @@ -71,6 +72,9 @@ public class CoreManager implements CoreService { protected IdBlockStore idBlockStore; @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) + protected ApplicationService appService; + + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) protected ComponentConfigService cfgService; @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) @@ -111,28 +115,24 @@ public class CoreManager implements CoreService { @Override public Version version() { checkPermission(APP_READ); - return version; } @Override public Set<ApplicationId> getAppIds() { checkPermission(APP_READ); - return applicationIdStore.getAppIds(); } @Override public ApplicationId getAppId(Short id) { checkPermission(APP_READ); - return applicationIdStore.getAppId(id); } @Override public ApplicationId getAppId(String name) { checkPermission(APP_READ); - return applicationIdStore.getAppId(name); } @@ -144,6 +144,13 @@ public class CoreManager implements CoreService { } @Override + public ApplicationId registerApplication(String name, Runnable preDeactivate) { + ApplicationId id = registerApplication(name); + appService.registerDeactivateHook(id, preDeactivate); + return id; + } + + @Override public IdGenerator getIdGenerator(String topic) { IdBlockAllocator allocator = new StoreBasedIdBlockAllocator(topic, idBlockStore); return new BlockAllocatorBasedIdGenerator(allocator); @@ -185,10 +192,10 @@ public class CoreManager implements CoreService { */ private static Integer getIntegerProperty(Dictionary<?, ?> properties, String propertyName) { - Integer value = null; + Integer value; try { String s = (String) properties.get(propertyName); - value = isNullOrEmpty(s) ? value : Integer.parseInt(s.trim()); + value = isNullOrEmpty(s) ? null : Integer.parseInt(s.trim()); } catch (NumberFormatException | ClassCastException e) { value = null; } diff --git a/framework/src/onos/core/net/src/main/java/org/onosproject/net/device/impl/BasicDeviceOperator.java b/framework/src/onos/core/net/src/main/java/org/onosproject/net/device/impl/BasicDeviceOperator.java index fa90eb65..a498b3f4 100644 --- a/framework/src/onos/core/net/src/main/java/org/onosproject/net/device/impl/BasicDeviceOperator.java +++ b/framework/src/onos/core/net/src/main/java/org/onosproject/net/device/impl/BasicDeviceOperator.java @@ -51,7 +51,7 @@ public final class BasicDeviceOperator implements ConfigOperator { * @return DeviceDescription based on both sources */ public static DeviceDescription combine(BasicDeviceConfig bdc, DeviceDescription descr) { - if (bdc == null) { + if (bdc == null || descr == null) { return descr; } @@ -61,7 +61,7 @@ public final class BasicDeviceOperator implements ConfigOperator { } SparseAnnotations sa = combine(bdc, descr.annotations()); - return new DefaultDeviceDescription(descr.deviceURI(), type, descr.manufacturer(), + return new DefaultDeviceDescription(descr.deviceUri(), type, descr.manufacturer(), descr.hwVersion(), descr.swVersion(), descr.serialNumber(), descr.chassisId(), sa); } diff --git a/framework/src/onos/core/net/src/main/java/org/onosproject/net/device/impl/DeviceManager.java b/framework/src/onos/core/net/src/main/java/org/onosproject/net/device/impl/DeviceManager.java index 9215d3a0..03281bef 100644 --- a/framework/src/onos/core/net/src/main/java/org/onosproject/net/device/impl/DeviceManager.java +++ b/framework/src/onos/core/net/src/main/java/org/onosproject/net/device/impl/DeviceManager.java @@ -740,7 +740,7 @@ public class DeviceManager Device dev = getDevice(did); DeviceDescription desc = (dev == null) ? null : BasicDeviceOperator.descriptionOf(dev); desc = BasicDeviceOperator.combine(cfg, desc); - if (getProvider(did) != null) { + if (desc != null && getProvider(did) != null) { de = store.createOrUpdateDevice(getProvider(did).id(), did, desc); } } @@ -754,7 +754,7 @@ public class DeviceManager OpticalPortConfig opc = networkConfigService.getConfig(cpt, OpticalPortConfig.class); PortDescription desc = OpticalPortOperator.descriptionOf(dpt); desc = OpticalPortOperator.combine(opc, desc); - if (getProvider(did) != null) { + if (desc != null && getProvider(did) != null) { de = store.updatePortStatus(getProvider(did).id(), did, desc); } } diff --git a/framework/src/onos/core/net/src/main/java/org/onosproject/net/host/impl/HostManager.java b/framework/src/onos/core/net/src/main/java/org/onosproject/net/host/impl/HostManager.java index 1473f33f..f48b8366 100644 --- a/framework/src/onos/core/net/src/main/java/org/onosproject/net/host/impl/HostManager.java +++ b/framework/src/onos/core/net/src/main/java/org/onosproject/net/host/impl/HostManager.java @@ -192,10 +192,7 @@ public class HostManager @Override public void removeHost(HostId hostId) { checkNotNull(hostId, HOST_ID_NULL); - HostEvent event = store.removeHost(hostId); - if (event != null) { - post(event); - } + store.removeHost(hostId); } // Personalized host provider service issued to the supplied provider. @@ -211,11 +208,8 @@ public class HostManager checkNotNull(hostId, HOST_ID_NULL); checkValidity(); hostDescription = validateHost(hostDescription, hostId); - HostEvent event = store.createOrUpdateHost(provider().id(), hostId, + store.createOrUpdateHost(provider().id(), hostId, hostDescription, replaceIps); - if (event != null) { - post(event); - } } // returns a HostDescription made from the union of the BasicHostConfig @@ -231,20 +225,14 @@ public class HostManager public void hostVanished(HostId hostId) { checkNotNull(hostId, HOST_ID_NULL); checkValidity(); - HostEvent event = store.removeHost(hostId); - if (event != null) { - post(event); - } + store.removeHost(hostId); } @Override public void removeIpFromHost(HostId hostId, IpAddress ipAddress) { checkNotNull(hostId, HOST_ID_NULL); checkValidity(); - HostEvent event = store.removeIp(hostId, ipAddress); - if (event != null) { - post(event); - } + store.removeIp(hostId, ipAddress); } } diff --git a/framework/src/onos/core/net/src/main/java/org/onosproject/net/intent/impl/ObjectiveTracker.java b/framework/src/onos/core/net/src/main/java/org/onosproject/net/intent/impl/ObjectiveTracker.java index 5ebc812e..ebf681a2 100644 --- a/framework/src/onos/core/net/src/main/java/org/onosproject/net/intent/impl/ObjectiveTracker.java +++ b/framework/src/onos/core/net/src/main/java/org/onosproject/net/intent/impl/ObjectiveTracker.java @@ -48,9 +48,9 @@ import org.onosproject.net.intent.PartitionEvent; import org.onosproject.net.intent.PartitionEventListener; import org.onosproject.net.intent.PartitionService; import org.onosproject.net.link.LinkEvent; -import org.onosproject.net.resource.link.LinkResourceEvent; -import org.onosproject.net.resource.link.LinkResourceListener; -import org.onosproject.net.resource.link.LinkResourceService; +import org.onosproject.net.newresource.ResourceEvent; +import org.onosproject.net.newresource.ResourceListener; +import org.onosproject.net.newresource.ResourceService; import org.onosproject.net.topology.TopologyEvent; import org.onosproject.net.topology.TopologyListener; import org.onosproject.net.topology.TopologyService; @@ -60,6 +60,7 @@ import java.util.Collection; import java.util.Collections; import java.util.HashSet; import java.util.List; +import java.util.Optional; import java.util.Set; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; @@ -101,7 +102,7 @@ public class ObjectiveTracker implements ObjectiveTrackerService { protected TopologyService topologyService; @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) - protected LinkResourceService resourceManager; + protected ResourceService resourceService; @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) protected DeviceService deviceService; @@ -122,8 +123,7 @@ public class ObjectiveTracker implements ObjectiveTrackerService { .newScheduledThreadPool(1); private TopologyListener listener = new InternalTopologyListener(); - private LinkResourceListener linkResourceListener = - new InternalLinkResourceListener(); + private ResourceListener resourceListener = new InternalResourceListener(); private DeviceListener deviceListener = new InternalDeviceListener(); private HostListener hostListener = new InternalHostListener(); private PartitionEventListener partitionListener = new InternalPartitionListener(); @@ -134,7 +134,7 @@ public class ObjectiveTracker implements ObjectiveTrackerService { @Activate public void activate() { topologyService.addListener(listener); - resourceManager.addListener(linkResourceListener); + resourceService.addListener(resourceListener); deviceService.addListener(deviceListener); hostService.addListener(hostListener); partitionService.addListener(partitionListener); @@ -144,7 +144,7 @@ public class ObjectiveTracker implements ObjectiveTrackerService { @Deactivate public void deactivate() { topologyService.removeListener(listener); - resourceManager.removeListener(linkResourceListener); + resourceService.removeListener(resourceListener); deviceService.removeListener(deviceListener); hostService.removeListener(hostListener); partitionService.removeListener(partitionListener); @@ -299,35 +299,22 @@ public class ObjectiveTracker implements ObjectiveTrackerService { } } - /** - * Internal re-actor to resource available events. - */ - private class InternalLinkResourceListener implements LinkResourceListener { + private class InternalResourceListener implements ResourceListener { @Override - public void event(LinkResourceEvent event) { - executorService.execute(new ResourceAvailableHandler(event)); - } - } - - /* - * Re-dispatcher of resource available events. - */ - private class ResourceAvailableHandler implements Runnable { - - private final LinkResourceEvent event; - - ResourceAvailableHandler(LinkResourceEvent event) { - this.event = event; - } + public void event(ResourceEvent event) { + Optional<Class<?>> linkEvent = event.subject().components().stream() + .map(Object::getClass) + .filter(x -> x == LinkKey.class) + .findFirst(); + if (linkEvent.isPresent()) { + executorService.execute(() -> { + if (delegate == null) { + return; + } - @Override - public void run() { - // If there is no delegate, why bother? Just bail. - if (delegate == null) { - return; + delegate.triggerCompile(Collections.emptySet(), true); + }); } - - delegate.triggerCompile(Collections.emptySet(), true); } } diff --git a/framework/src/onos/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/MplsPathIntentCompiler.java b/framework/src/onos/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/MplsPathIntentCompiler.java index acc5a5d5..718c7bbf 100644 --- a/framework/src/onos/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/MplsPathIntentCompiler.java +++ b/framework/src/onos/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/MplsPathIntentCompiler.java @@ -121,7 +121,7 @@ public class MplsPathIntentCompiler implements IntentCompiler<MplsPathIntent> { } List<ResourcePath> resources = labels.entrySet().stream() - .map(x -> new ResourcePath(linkKey(x.getKey().src(), x.getKey().src()), x.getValue())) + .map(x -> ResourcePath.discrete(linkKey(x.getKey().src(), x.getKey().src()), x.getValue())) .collect(Collectors.toList()); List<org.onosproject.net.newresource.ResourceAllocation> allocations = resourceService.allocate(intent.id(), resources); @@ -145,9 +145,9 @@ public class MplsPathIntentCompiler implements IntentCompiler<MplsPathIntent> { } private Optional<MplsLabel> findMplsLabel(LinkKey link) { - return resourceService.getAvailableResources(new ResourcePath(link)).stream() - .filter(x -> x.lastComponent() instanceof MplsLabel) - .map(x -> (MplsLabel) x.lastComponent()) + return resourceService.getAvailableResources(ResourcePath.discrete(link)).stream() + .filter(x -> x.last() instanceof MplsLabel) + .map(x -> (MplsLabel) x.last()) .findFirst(); } diff --git a/framework/src/onos/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/OpticalCircuitIntentCompiler.java b/framework/src/onos/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/OpticalCircuitIntentCompiler.java index fce8498c..ee04aab5 100644 --- a/framework/src/onos/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/OpticalCircuitIntentCompiler.java +++ b/framework/src/onos/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/OpticalCircuitIntentCompiler.java @@ -160,8 +160,8 @@ public class OpticalCircuitIntentCompiler implements IntentCompiler<OpticalCircu log.debug("Compiling optical circuit intent between {} and {}", src, dst); // Reserve OduClt ports - ResourcePath srcPortPath = new ResourcePath(src.deviceId(), src.port()); - ResourcePath dstPortPath = new ResourcePath(dst.deviceId(), dst.port()); + ResourcePath srcPortPath = ResourcePath.discrete(src.deviceId(), src.port()); + ResourcePath dstPortPath = ResourcePath.discrete(dst.deviceId(), dst.port()); List<ResourceAllocation> allocation = resourceService.allocate(intent.id(), srcPortPath, dstPortPath); if (allocation.isEmpty()) { throw new IntentCompilationException("Unable to reserve ports for intent " + intent); @@ -312,7 +312,7 @@ public class OpticalCircuitIntentCompiler implements IntentCompiler<OpticalCircu if (ochCP != null) { OchPort ochPort = (OchPort) deviceService.getPort(ochCP.deviceId(), ochCP.port()); Optional<IntentId> intentId = - resourceService.getResourceAllocation(new ResourcePath(ochCP.deviceId(), ochCP.port())) + resourceService.getResourceAllocation(ResourcePath.discrete(ochCP.deviceId(), ochCP.port())) .map(ResourceAllocation::consumer) .filter(x -> x instanceof IntentId) .map(x -> (IntentId) x); @@ -331,7 +331,7 @@ public class OpticalCircuitIntentCompiler implements IntentCompiler<OpticalCircu } Optional<IntentId> intentId = - resourceService.getResourceAllocation(new ResourcePath(oduPort.deviceId(), port.number())) + resourceService.getResourceAllocation(ResourcePath.discrete(oduPort.deviceId(), port.number())) .map(ResourceAllocation::consumer) .filter(x -> x instanceof IntentId) .map(x -> (IntentId) x); diff --git a/framework/src/onos/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/OpticalConnectivityIntentCompiler.java b/framework/src/onos/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/OpticalConnectivityIntentCompiler.java index d6725b7c..a4ed551a 100644 --- a/framework/src/onos/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/OpticalConnectivityIntentCompiler.java +++ b/framework/src/onos/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/OpticalConnectivityIntentCompiler.java @@ -107,8 +107,8 @@ public class OpticalConnectivityIntentCompiler implements IntentCompiler<Optical log.debug("Compiling optical connectivity intent between {} and {}", src, dst); // Reserve OCh ports - ResourcePath srcPortPath = new ResourcePath(src.deviceId(), src.port()); - ResourcePath dstPortPath = new ResourcePath(dst.deviceId(), dst.port()); + ResourcePath srcPortPath = ResourcePath.discrete(src.deviceId(), src.port()); + ResourcePath dstPortPath = ResourcePath.discrete(dst.deviceId(), dst.port()); List<org.onosproject.net.newresource.ResourceAllocation> allocation = resourceService.allocate(intent.id(), srcPortPath, dstPortPath); if (allocation.isEmpty()) { @@ -182,8 +182,8 @@ public class OpticalConnectivityIntentCompiler implements IntentCompiler<Optical IndexedLambda minLambda = findFirstLambda(lambdas); List<ResourcePath> lambdaResources = path.links().stream() - .map(x -> new ResourcePath(linkKey(x.src(), x.dst()))) - .map(x -> ResourcePath.child(x, minLambda)) + .map(x -> ResourcePath.discrete(linkKey(x.src(), x.dst()))) + .map(x -> x.child(minLambda)) .collect(Collectors.toList()); List<ResourceAllocation> allocations = resourceService.allocate(intent.id(), lambdaResources); @@ -196,10 +196,10 @@ public class OpticalConnectivityIntentCompiler implements IntentCompiler<Optical private Set<IndexedLambda> findCommonLambdasOverLinks(List<Link> links) { return links.stream() - .map(x -> new ResourcePath(linkKey(x.src(), x.dst()))) + .map(x -> ResourcePath.discrete(linkKey(x.src(), x.dst()))) .map(resourceService::getAvailableResources) - .map(x -> Iterables.filter(x, r -> r.lastComponent() instanceof IndexedLambda)) - .map(x -> Iterables.transform(x, r -> (IndexedLambda) r.lastComponent())) + .map(x -> Iterables.filter(x, r -> r.last() instanceof IndexedLambda)) + .map(x -> Iterables.transform(x, r -> (IndexedLambda) r.last())) .map(x -> (Set<IndexedLambda>) ImmutableSet.copyOf(x)) .reduce(Sets::intersection) .orElse(Collections.emptySet()); diff --git a/framework/src/onos/core/net/src/main/java/org/onosproject/net/newresource/impl/ResourceDeviceListener.java b/framework/src/onos/core/net/src/main/java/org/onosproject/net/newresource/impl/ResourceDeviceListener.java index e6d92253..066dd33e 100644 --- a/framework/src/onos/core/net/src/main/java/org/onosproject/net/newresource/impl/ResourceDeviceListener.java +++ b/framework/src/onos/core/net/src/main/java/org/onosproject/net/newresource/impl/ResourceDeviceListener.java @@ -75,12 +75,12 @@ final class ResourceDeviceListener implements DeviceListener { } private void registerPortResource(Device device, Port port) { - ResourcePath parent = new ResourcePath(device.id()); + ResourcePath parent = ResourcePath.discrete(device.id()); executor.submit(() -> adminService.registerResources(parent, port.number())); } private void unregisterPortResource(Device device, Port port) { - ResourcePath parent = new ResourcePath(device.id()); + ResourcePath parent = ResourcePath.discrete(device.id()); executor.submit(() -> adminService.unregisterResources(parent, port.number())); } } diff --git a/framework/src/onos/core/net/src/main/java/org/onosproject/net/newresource/impl/ResourceLinkListener.java b/framework/src/onos/core/net/src/main/java/org/onosproject/net/newresource/impl/ResourceLinkListener.java index f04c78b9..68fd6612 100644 --- a/framework/src/onos/core/net/src/main/java/org/onosproject/net/newresource/impl/ResourceLinkListener.java +++ b/framework/src/onos/core/net/src/main/java/org/onosproject/net/newresource/impl/ResourceLinkListener.java @@ -87,7 +87,7 @@ final class ResourceLinkListener implements LinkListener { LinkKey linkKey = LinkKey.linkKey(link); adminService.registerResources(ResourcePath.ROOT, linkKey); - ResourcePath linkPath = new ResourcePath(linkKey); + ResourcePath linkPath = ResourcePath.discrete(linkKey); // register VLAN IDs against the link if (isEnabled(link, this::isVlanEnabled)) { adminService.registerResources(linkPath, ENTIRE_VLAN_IDS); diff --git a/framework/src/onos/core/net/src/main/java/org/onosproject/net/newresource/impl/ResourceManager.java b/framework/src/onos/core/net/src/main/java/org/onosproject/net/newresource/impl/ResourceManager.java index 10fe75ea..1c6930bb 100644 --- a/framework/src/onos/core/net/src/main/java/org/onosproject/net/newresource/impl/ResourceManager.java +++ b/framework/src/onos/core/net/src/main/java/org/onosproject/net/newresource/impl/ResourceManager.java @@ -18,16 +18,22 @@ package org.onosproject.net.newresource.impl; import com.google.common.annotations.Beta; import com.google.common.collect.ImmutableList; import com.google.common.collect.Lists; +import org.apache.felix.scr.annotations.Activate; import org.apache.felix.scr.annotations.Component; +import org.apache.felix.scr.annotations.Deactivate; import org.apache.felix.scr.annotations.Reference; import org.apache.felix.scr.annotations.ReferenceCardinality; import org.apache.felix.scr.annotations.Service; +import org.onosproject.event.AbstractListenerManager; import org.onosproject.net.newresource.ResourceAdminService; import org.onosproject.net.newresource.ResourceAllocation; import org.onosproject.net.newresource.ResourceConsumer; +import org.onosproject.net.newresource.ResourceEvent; +import org.onosproject.net.newresource.ResourceListener; import org.onosproject.net.newresource.ResourceService; import org.onosproject.net.newresource.ResourcePath; import org.onosproject.net.newresource.ResourceStore; +import org.onosproject.net.newresource.ResourceStoreDelegate; import java.util.ArrayList; import java.util.Collection; @@ -44,20 +50,32 @@ import static com.google.common.base.Preconditions.checkNotNull; @Component(immediate = true) @Service @Beta -public final class ResourceManager implements ResourceService, ResourceAdminService { +public final class ResourceManager extends AbstractListenerManager<ResourceEvent, ResourceListener> + implements ResourceService, ResourceAdminService { @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) protected ResourceStore store; + private final ResourceStoreDelegate delegate = new InternalStoreDelegate(); + + @Activate + public void activate() { + store.setDelegate(delegate); + eventDispatcher.addSink(ResourceEvent.class, listenerRegistry); + } + + @Deactivate + public void deactivate() { + store.unsetDelegate(delegate); + eventDispatcher.removeSink(ResourceEvent.class); + } + @Override public List<ResourceAllocation> allocate(ResourceConsumer consumer, List<ResourcePath> resources) { checkNotNull(consumer); checkNotNull(resources); - // TODO: implement support of resource hierarchy - // allocation for a particular resource implies allocations for all of the sub-resources need to be done - boolean success = store.allocate(resources, consumer); if (!success) { return ImmutableList.of(); @@ -151,7 +169,7 @@ public final class ResourceManager implements ResourceService, ResourceAdminServ checkNotNull(children); checkArgument(!children.isEmpty()); - List<ResourcePath> resources = Lists.transform(children, x -> ResourcePath.child(parent, x)); + List<ResourcePath> resources = Lists.transform(children, parent::child); return store.register(resources); } @@ -161,7 +179,14 @@ public final class ResourceManager implements ResourceService, ResourceAdminServ checkNotNull(children); checkArgument(!children.isEmpty()); - List<ResourcePath> resources = Lists.transform(children, x -> ResourcePath.child(parent, x)); + List<ResourcePath> resources = Lists.transform(children, parent::child); return store.unregister(resources); } + + private class InternalStoreDelegate implements ResourceStoreDelegate { + @Override + public void notify(ResourceEvent event) { + post(event); + } + } } diff --git a/framework/src/onos/core/net/src/main/java/org/onosproject/net/newresource/impl/ResourceRegistrar.java b/framework/src/onos/core/net/src/main/java/org/onosproject/net/newresource/impl/ResourceRegistrar.java index 4067d017..143f8c2b 100644 --- a/framework/src/onos/core/net/src/main/java/org/onosproject/net/newresource/impl/ResourceRegistrar.java +++ b/framework/src/onos/core/net/src/main/java/org/onosproject/net/newresource/impl/ResourceRegistrar.java @@ -36,7 +36,7 @@ import static org.onlab.util.Tools.groupedThreads; /** * A class registering resources when they are detected. */ -@Component(immediate = true, enabled = false) +@Component(immediate = true) @Beta public final class ResourceRegistrar { diff --git a/framework/src/onos/core/net/src/main/java/org/onosproject/net/packet/impl/PacketManager.java b/framework/src/onos/core/net/src/main/java/org/onosproject/net/packet/impl/PacketManager.java index 8e87a07d..793030f2 100644 --- a/framework/src/onos/core/net/src/main/java/org/onosproject/net/packet/impl/PacketManager.java +++ b/framework/src/onos/core/net/src/main/java/org/onosproject/net/packet/impl/PacketManager.java @@ -312,9 +312,13 @@ public class PacketManager public void processPacket(PacketContext context) { // TODO filter packets sent to processors based on registrations for (ProcessorEntry entry : processors) { - long start = System.nanoTime(); - entry.processor().process(context); - entry.addNanos(System.nanoTime() - start); + try { + long start = System.nanoTime(); + entry.processor().process(context); + entry.addNanos(System.nanoTime() - start); + } catch (Exception e) { + log.warn("Packet processor {} threw an exception", entry.processor(), e); + } } } diff --git a/framework/src/onos/core/net/src/main/java/org/onosproject/net/proxyarp/impl/ProxyArpManager.java b/framework/src/onos/core/net/src/main/java/org/onosproject/net/proxyarp/impl/ProxyArpManager.java index 25a2640d..5ecf2806 100644 --- a/framework/src/onos/core/net/src/main/java/org/onosproject/net/proxyarp/impl/ProxyArpManager.java +++ b/framework/src/onos/core/net/src/main/java/org/onosproject/net/proxyarp/impl/ProxyArpManager.java @@ -53,6 +53,7 @@ import org.slf4j.Logger; import java.nio.ByteBuffer; import java.util.Set; +import java.util.stream.Collectors; import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkNotNull; @@ -199,11 +200,49 @@ public class ProxyArpManager implements ProxyArpService { return; } + // If the packets has a vlanId look if there are some other + // interfaces in the configuration on the same vlan and broadcast + // the packet out just of through those interfaces. + VlanId vlanId = context.vlan(); + + Set<Interface> filteredVlanInterfaces = + filterVlanInterfacesNoIp(interfaceService.getInterfacesByVlan(vlanId)); + + if (vlanId != null + && !vlanId.equals(VlanId.NONE) + && confContainsVlans(vlanId, context.inPort())) { + vlanFlood(context.packet(), filteredVlanInterfaces, context.inPort); + return; + } + // The request couldn't be resolved. // Flood the request on all ports except the incoming port. flood(context.packet(), context.inPort()); } + private Set<Interface> filterVlanInterfacesNoIp(Set<Interface> vlanInterfaces) { + return vlanInterfaces + .stream() + .filter(intf -> intf.ipAddresses().isEmpty()) + .collect(Collectors.toSet()); + } + + /** + * States if the interface configuration contains more than one interface configured + * on a specific vlan, including the interface passed as argument. + * + * @param vlanId the vlanid to look for in the interface configuration + * @param connectPoint the connect point to exclude from the search + * @return true if interfaces are found. False otherwise + */ + private boolean confContainsVlans(VlanId vlanId, ConnectPoint connectPoint) { + Set<Interface> vlanInterfaces = interfaceService.getInterfacesByVlan(vlanId); + return interfaceService.getInterfacesByVlan(vlanId) + .stream() + .anyMatch(intf -> intf.connectPoint().equals(connectPoint) && intf.ipAddresses().isEmpty()) + && vlanInterfaces.size() > 1; + } + /** * Builds and sends a reply message given a request context and the resolved * MAC address to answer with. @@ -259,14 +298,29 @@ public class ProxyArpManager implements ProxyArpService { /** * Returns whether the given port has any IP addresses configured or not. * - * @param port the port to check + * @param connectPoint the port to check * @return true if the port has at least one IP address configured, - * otherwise false + * false otherwise + */ + private boolean hasIpAddress(ConnectPoint connectPoint) { + return interfaceService.getInterfacesByPort(connectPoint) + .stream() + .flatMap(intf -> intf.ipAddresses().stream()) + .findAny() + .isPresent(); + } + + /** + * Returns whether the given port has any VLAN configured or not. + * + * @param connectPoint the port to check + * @return true if the port has at least one VLAN configured, + * false otherwise */ - private boolean hasIpAddress(ConnectPoint port) { - return interfaceService.getInterfacesByPort(port) + private boolean hasVlan(ConnectPoint connectPoint) { + return interfaceService.getInterfacesByPort(connectPoint) .stream() - .map(intf -> intf.ipAddresses()) + .filter(intf -> !intf.vlan().equals(VlanId.NONE)) .findAny() .isPresent(); } @@ -322,6 +376,30 @@ public class ProxyArpManager implements ProxyArpService { } /** + * Flood the arp request at all edges on a specifc VLAN. + * + * @param request the arp request + * @param dsts the destination interfaces + * @param inPort the connect point the arp request was received on + */ + private void vlanFlood(Ethernet request, Set<Interface> dsts, ConnectPoint inPort) { + TrafficTreatment.Builder builder = null; + ByteBuffer buf = ByteBuffer.wrap(request.serialize()); + + for (Interface intf : dsts) { + ConnectPoint cPoint = intf.connectPoint(); + if (cPoint.equals(inPort)) { + continue; + } + + builder = DefaultTrafficTreatment.builder(); + builder.setOutput(cPoint.port()); + packetService.emit(new DefaultOutboundPacket(cPoint.deviceId(), + builder.build(), buf)); + } + } + + /** * Flood the arp request at all edges in the network. * * @param request the arp request @@ -332,7 +410,9 @@ public class ProxyArpManager implements ProxyArpService { ByteBuffer buf = ByteBuffer.wrap(request.serialize()); for (ConnectPoint connectPoint : edgeService.getEdgePoints()) { - if (hasIpAddress(connectPoint) || connectPoint.equals(inPort)) { + if (hasIpAddress(connectPoint) + || hasVlan(connectPoint) + || connectPoint.equals(inPort)) { continue; } diff --git a/framework/src/onos/core/net/src/main/java/org/onosproject/net/statistic/impl/FlowStatisticManager.java b/framework/src/onos/core/net/src/main/java/org/onosproject/net/statistic/impl/FlowStatisticManager.java index 6515ef31..f18c56dc 100644 --- a/framework/src/onos/core/net/src/main/java/org/onosproject/net/statistic/impl/FlowStatisticManager.java +++ b/framework/src/onos/core/net/src/main/java/org/onosproject/net/statistic/impl/FlowStatisticManager.java @@ -255,7 +255,7 @@ public class FlowStatisticManager implements FlowStatisticService { Instruction.Type instType) {
checkPermission(STATISTIC_READ);
- List<TypedFlowEntryWithLoad> retTFEL = new ArrayList<>();
+ List<TypedFlowEntryWithLoad> retTfel = new ArrayList<>();
Set<FlowEntry> currentStats;
Set<FlowEntry> previousStats;
@@ -264,11 +264,11 @@ public class FlowStatisticManager implements FlowStatisticService { synchronized (flowStatisticStore) {
currentStats = flowStatisticStore.getCurrentFlowStatistic(cp);
if (currentStats == null) {
- return retTFEL;
+ return retTfel;
}
previousStats = flowStatisticStore.getPreviousFlowStatistic(cp);
if (previousStats == null) {
- return retTFEL;
+ return retTfel;
}
// copy to local flow entry set
typedStatistics = new TypedStatistics(currentStats, previousStats);
@@ -291,7 +291,7 @@ public class FlowStatisticManager implements FlowStatisticService { List<TypedFlowEntryWithLoad> fel = typedFlowEntryLoadByInstInternal(cp, currentMap, previousMap,
isAllInstType, instType, TypedFlowEntryWithLoad.shortPollInterval());
if (fel.size() > 0) {
- retTFEL.addAll(fel);
+ retTfel.addAll(fel);
}
}
@@ -302,7 +302,7 @@ public class FlowStatisticManager implements FlowStatisticService { List<TypedFlowEntryWithLoad> fel = typedFlowEntryLoadByInstInternal(cp, currentMap, previousMap,
isAllInstType, instType, TypedFlowEntryWithLoad.shortPollInterval());
if (fel.size() > 0) {
- retTFEL.addAll(fel);
+ retTfel.addAll(fel);
}
}
@@ -313,7 +313,7 @@ public class FlowStatisticManager implements FlowStatisticService { List<TypedFlowEntryWithLoad> fel = typedFlowEntryLoadByInstInternal(cp, currentMap, previousMap,
isAllInstType, instType, TypedFlowEntryWithLoad.midPollInterval());
if (fel.size() > 0) {
- retTFEL.addAll(fel);
+ retTfel.addAll(fel);
}
}
@@ -324,7 +324,7 @@ public class FlowStatisticManager implements FlowStatisticService { List<TypedFlowEntryWithLoad> fel = typedFlowEntryLoadByInstInternal(cp, currentMap, previousMap,
isAllInstType, instType, TypedFlowEntryWithLoad.longPollInterval());
if (fel.size() > 0) {
- retTFEL.addAll(fel);
+ retTfel.addAll(fel);
}
}
@@ -335,11 +335,11 @@ public class FlowStatisticManager implements FlowStatisticService { List<TypedFlowEntryWithLoad> fel = typedFlowEntryLoadByInstInternal(cp, currentMap, previousMap,
isAllInstType, instType, TypedFlowEntryWithLoad.avgPollInterval());
if (fel.size() > 0) {
- retTFEL.addAll(fel);
+ retTfel.addAll(fel);
}
}
- return retTFEL;
+ return retTfel;
}
private List<TypedFlowEntryWithLoad> typedFlowEntryLoadByInstInternal(ConnectPoint cp,
diff --git a/framework/src/onos/core/net/src/test/java/org/onosproject/app/impl/ApplicationManagerTest.java b/framework/src/onos/core/net/src/test/java/org/onosproject/app/impl/ApplicationManagerTest.java index 1ce31ac3..a99fd216 100644 --- a/framework/src/onos/core/net/src/test/java/org/onosproject/app/impl/ApplicationManagerTest.java +++ b/framework/src/onos/core/net/src/test/java/org/onosproject/app/impl/ApplicationManagerTest.java @@ -15,6 +15,7 @@ */ package org.onosproject.app.impl; +import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; import org.junit.After; import org.junit.Before; @@ -24,11 +25,11 @@ import org.onosproject.app.ApplicationListener; import org.onosproject.app.ApplicationState; import org.onosproject.app.ApplicationStoreAdapter; import org.onosproject.common.app.ApplicationArchive; +import org.onosproject.common.event.impl.TestEventDispatcher; import org.onosproject.core.Application; import org.onosproject.core.ApplicationId; import org.onosproject.core.DefaultApplication; import org.onosproject.core.DefaultApplicationId; -import org.onosproject.common.event.impl.TestEventDispatcher; import java.io.InputStream; import java.net.URI; @@ -36,7 +37,7 @@ import java.util.HashSet; import java.util.Optional; import java.util.Set; -import static org.junit.Assert.assertEquals; +import static org.junit.Assert.*; import static org.onosproject.app.ApplicationEvent.Type.*; import static org.onosproject.app.ApplicationState.ACTIVE; import static org.onosproject.app.ApplicationState.INSTALLED; @@ -53,6 +54,8 @@ public class ApplicationManagerTest { private ApplicationManager mgr = new ApplicationManager(); private ApplicationListener listener = new TestListener(); + private boolean deactivated = false; + @Before public void setUp() { injectEventDispatcher(mgr, new TestEventDispatcher()); @@ -88,6 +91,11 @@ public class ApplicationManagerTest { assertEquals("incorrect app count", 1, mgr.getApplications().size()); assertEquals("incorrect app", app, mgr.getApplication(APP_ID)); assertEquals("incorrect app state", INSTALLED, mgr.getState(APP_ID)); + mgr.registerDeactivateHook(app.id(), this::deactivateHook); + } + + private void deactivateHook() { + deactivated = true; } @Test @@ -102,6 +110,7 @@ public class ApplicationManagerTest { install(); mgr.activate(APP_ID); assertEquals("incorrect app state", ACTIVE, mgr.getState(APP_ID)); + assertFalse("preDeactivate hook wrongly called", deactivated); } @Test @@ -109,6 +118,7 @@ public class ApplicationManagerTest { activate(); mgr.deactivate(APP_ID); assertEquals("incorrect app state", INSTALLED, mgr.getState(APP_ID)); + assertTrue("preDeactivate hook not called", deactivated); } @@ -129,7 +139,7 @@ public class ApplicationManagerTest { @Override public Application create(InputStream appDescStream) { app = new DefaultApplication(APP_ID, VER, DESC, ORIGIN, ROLE, PERMS, - Optional.of(FURL), FEATURES); + Optional.of(FURL), FEATURES, ImmutableList.of()); state = INSTALLED; delegate.notify(new ApplicationEvent(APP_INSTALLED, app)); return app; @@ -168,6 +178,11 @@ public class ApplicationManagerTest { state = INSTALLED; delegate.notify(new ApplicationEvent(APP_DEACTIVATED, app)); } + + @Override + public ApplicationId getId(String name) { + return new DefaultApplicationId(0, name); + } } private class TestFeaturesService extends FeaturesServiceAdapter { diff --git a/framework/src/onos/core/net/src/test/java/org/onosproject/net/host/impl/HostManagerTest.java b/framework/src/onos/core/net/src/test/java/org/onosproject/net/host/impl/HostManagerTest.java index 92c6c931..c5a6cabd 100644 --- a/framework/src/onos/core/net/src/test/java/org/onosproject/net/host/impl/HostManagerTest.java +++ b/framework/src/onos/core/net/src/test/java/org/onosproject/net/host/impl/HostManagerTest.java @@ -20,6 +20,7 @@ import com.google.common.collect.Sets; import org.junit.After; import org.junit.Before; import org.junit.Test; +import org.onlab.junit.TestTools; import org.onlab.packet.IpAddress; import org.onlab.packet.MacAddress; import org.onlab.packet.VlanId; @@ -129,13 +130,15 @@ public class HostManagerTest { } private void validateEvents(Enum... types) { - int i = 0; - assertEquals("wrong events received", types.length, listener.events.size()); - for (Event event : listener.events) { - assertEquals("incorrect event type", types[i], event.type()); - i++; - } - listener.events.clear(); + TestTools.assertAfter(100, () -> { + int i = 0; + assertEquals("wrong events received", types.length, listener.events.size()); + for (Event event : listener.events) { + assertEquals("incorrect event type", types[i], event.type()); + i++; + } + listener.events.clear(); + }); } @Test diff --git a/framework/src/onos/core/net/src/test/java/org/onosproject/net/intent/impl/ObjectiveTrackerTest.java b/framework/src/onos/core/net/src/test/java/org/onosproject/net/intent/impl/ObjectiveTrackerTest.java index 58fa1292..eb7f2ccd 100644 --- a/framework/src/onos/core/net/src/test/java/org/onosproject/net/intent/impl/ObjectiveTrackerTest.java +++ b/framework/src/onos/core/net/src/test/java/org/onosproject/net/intent/impl/ObjectiveTrackerTest.java @@ -16,7 +16,6 @@ package org.onosproject.net.intent.impl; import java.util.Collection; -import java.util.HashSet; import java.util.LinkedList; import java.util.List; import java.util.concurrent.CountDownLatch; @@ -38,8 +37,9 @@ import org.onosproject.net.intent.Intent; import org.onosproject.net.intent.Key; import org.onosproject.net.intent.MockIdGenerator; import org.onosproject.net.link.LinkEvent; -import org.onosproject.net.resource.link.LinkResourceEvent; -import org.onosproject.net.resource.link.LinkResourceListener; +import org.onosproject.net.newresource.ResourceEvent; +import org.onosproject.net.newresource.ResourceListener; +import org.onosproject.net.newresource.ResourcePath; import org.onosproject.net.topology.Topology; import org.onosproject.net.topology.TopologyEvent; import org.onosproject.net.topology.TopologyListener; @@ -52,6 +52,8 @@ import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.hasSize; import static org.hamcrest.Matchers.is; +import static org.onosproject.net.LinkKey.linkKey; +import static org.onosproject.net.newresource.ResourceEvent.Type.*; import static org.onosproject.net.NetTestTools.APP_ID; import static org.onosproject.net.NetTestTools.device; import static org.onosproject.net.NetTestTools.link; @@ -67,7 +69,7 @@ public class ObjectiveTrackerTest { private List<Event> reasons; private TopologyListener listener; private DeviceListener deviceListener; - private LinkResourceListener linkResourceListener; + private ResourceListener resourceListener; private IdGenerator mockGenerator; /** @@ -84,7 +86,7 @@ public class ObjectiveTrackerTest { reasons = new LinkedList<>(); listener = TestUtils.getField(tracker, "listener"); deviceListener = TestUtils.getField(tracker, "deviceListener"); - linkResourceListener = TestUtils.getField(tracker, "linkResourceListener"); + resourceListener = TestUtils.getField(tracker, "resourceListener"); mockGenerator = new MockIdGenerator(); Intent.bindIdGenerator(mockGenerator); } @@ -228,10 +230,9 @@ public class ObjectiveTrackerTest { */ @Test public void testResourceEvent() throws Exception { - LinkResourceEvent event = new LinkResourceEvent( - LinkResourceEvent.Type.ADDITIONAL_RESOURCES_AVAILABLE, - new HashSet<>()); - linkResourceListener.event(event); + ResourceEvent event = new ResourceEvent(RESOURCE_ADDED, + ResourcePath.discrete(linkKey(link("a", 1, "b", 1)))); + resourceListener.event(event); assertThat( delegate.latch.await(WAIT_TIMEOUT_SECONDS, TimeUnit.SECONDS), diff --git a/framework/src/onos/core/net/src/test/java/org/onosproject/net/intent/impl/compiler/MockResourceService.java b/framework/src/onos/core/net/src/test/java/org/onosproject/net/intent/impl/compiler/MockResourceService.java index 06b2c81e..f5d3d0f3 100644 --- a/framework/src/onos/core/net/src/test/java/org/onosproject/net/intent/impl/compiler/MockResourceService.java +++ b/framework/src/onos/core/net/src/test/java/org/onosproject/net/intent/impl/compiler/MockResourceService.java @@ -19,6 +19,7 @@ import com.google.common.collect.ImmutableList; import org.onlab.packet.MplsLabel; import org.onosproject.net.newresource.ResourceAllocation; import org.onosproject.net.newresource.ResourceConsumer; +import org.onosproject.net.newresource.ResourceListener; import org.onosproject.net.newresource.ResourcePath; import org.onosproject.net.newresource.ResourceService; @@ -89,7 +90,7 @@ class MockResourceService implements ResourceService { @Override public Collection<ResourcePath> getAvailableResources(ResourcePath parent) { - ResourcePath resource = ResourcePath.child(parent, MplsLabel.mplsLabel(10)); + ResourcePath resource = parent.child(MplsLabel.mplsLabel(10)); return ImmutableList.of(resource); } @@ -97,4 +98,10 @@ class MockResourceService implements ResourceService { public boolean isAvailable(ResourcePath resource) { return true; } + + @Override + public void addListener(ResourceListener listener) {} + + @Override + public void removeListener(ResourceListener listener) {} } diff --git a/framework/src/onos/core/net/src/test/java/org/onosproject/net/proxyarp/impl/ProxyArpManagerTest.java b/framework/src/onos/core/net/src/test/java/org/onosproject/net/proxyarp/impl/ProxyArpManagerTest.java index 3e806a73..70fdb406 100644 --- a/framework/src/onos/core/net/src/test/java/org/onosproject/net/proxyarp/impl/ProxyArpManagerTest.java +++ b/framework/src/onos/core/net/src/test/java/org/onosproject/net/proxyarp/impl/ProxyArpManagerTest.java @@ -15,7 +15,6 @@ */ package org.onosproject.net.proxyarp.impl; -import com.google.common.collect.Lists; import com.google.common.collect.Sets; import org.junit.Before; import org.junit.Test; @@ -48,7 +47,7 @@ import org.onosproject.net.Port; import org.onosproject.net.PortNumber; import org.onosproject.net.device.DeviceListener; import org.onosproject.net.device.DeviceService; -import org.onosproject.net.edgeservice.impl.EdgeManager; +import org.onosproject.net.edge.EdgePortService; import org.onosproject.net.flow.DefaultTrafficTreatment; import org.onosproject.net.flow.TrafficTreatment; import org.onosproject.net.flow.instructions.Instruction; @@ -67,6 +66,7 @@ import org.onosproject.net.proxyarp.ProxyArpStoreDelegate; import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.Collections; +import java.util.HashSet; import java.util.List; import java.util.Set; @@ -88,47 +88,65 @@ import static org.junit.Assert.assertTrue; */ public class ProxyArpManagerTest { - private static final int NUM_DEVICES = 6; + private static final int NUM_DEVICES = 10; private static final int NUM_PORTS_PER_DEVICE = 3; - private static final int NUM_ADDRESS_PORTS = NUM_DEVICES / 2; - private static final int NUM_FLOOD_PORTS = 3; + private static final int LAST_CONF_DEVICE_INTF_VLAN_IP = 3; + private static final int LAST_CONF_DEVICE_INTF_VLAN = 6; 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 Ip6Address IP3 = Ip6Address.valueOf("1000::1"); - private static final Ip6Address IP4 = Ip6Address.valueOf("1000::2"); + private static final Ip6Address IP3 = Ip6Address.valueOf("1000:ffff::1"); + private static final Ip6Address IP4 = Ip6Address.valueOf("1000:ffff::2"); private static final ProviderId PID = new ProviderId("of", "foo"); private static final VlanId VLAN1 = VlanId.vlanId((short) 1); private static final VlanId VLAN2 = VlanId.vlanId((short) 2); - private static final MacAddress MAC1 = MacAddress.valueOf("00:00:11:00:00:01"); - private static final MacAddress MAC2 = MacAddress.valueOf("00:00:22:00:00:02"); - private static final MacAddress MAC3 = MacAddress.valueOf("00:00:33:00:00:03"); - private static final MacAddress MAC4 = MacAddress.valueOf("00:00:44:00:00:04"); + private static final VlanId VLAN10 = VlanId.vlanId((short) 10); + + 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 MAC10 = MacAddress.valueOf("00:00:00:00:00:0A"); + private static final MacAddress SOLICITED_MAC3 = MacAddress.valueOf("33:33:FF:00:00:01"); + 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, VLAN1); + private static final HostId HID10 = HostId.hostId(MAC10, VLAN10); + private static final HostId SOLICITED_HID3 = HostId.hostId(SOLICITED_MAC3, VLAN1); private static final DeviceId DID1 = getDeviceId(1); private static final DeviceId DID2 = getDeviceId(2); + private static final PortNumber P1 = PortNumber.portNumber(1); + private static final HostLocation LOC1 = new HostLocation(DID1, P1, 123L); private static final HostLocation LOC2 = new HostLocation(DID2, P1, 123L); - private static final byte[] ZERO_MAC_ADDRESS = MacAddress.ZERO.toBytes(); - //Return values used for various functions of the TestPacketService inner class. - private boolean isEdgePointReturn; - private List<ConnectPoint> getEdgePointsNoArg; + private final byte[] zeroMacAddress = MacAddress.ZERO.toBytes(); + + // The first three devices in the topology have interfaces configured + // with VLANs and IPs + private final List<ConnectPoint> configIpCPoints = new ArrayList<>(); + // Other three devices in the topology (from 4 to 6) have interfaces + // configured only with VLANs + private final List<ConnectPoint> configVlanCPoints = new ArrayList<>(); + + // Remaining devices in the network (id > 6) don't have any interface + // configured. + private final List<ConnectPoint> noConfigCPoints = new ArrayList<>(); private ProxyArpManager proxyArp; private TestPacketService packetService; private DeviceService deviceService; + private EdgePortService edgePortService; private LinkService linkService; private HostService hostService; private InterfaceService interfaceService; @@ -140,20 +158,27 @@ public class ProxyArpManagerTest { proxyArp.packetService = packetService; proxyArp.store = new TestProxyArpStoreAdapter(); - proxyArp.edgeService = new TestEdgePortService(); - - // Create a host service mock here. Must be replayed by tests once the - // expectations have been set up + // Create a host service mock here. hostService = createMock(HostService.class); proxyArp.hostService = hostService; + // Create an edge port service. + edgePortService = createMock(EdgePortService.class); + proxyArp.edgeService = edgePortService; + + // Create interface service interfaceService = createMock(InterfaceService.class); proxyArp.interfaceService = interfaceService; + // Create the topology createTopology(); proxyArp.deviceService = deviceService; proxyArp.linkService = linkService; + setupNoConfigCPoints(); + setupconfigIpCPoints(); + setupconfigVlanCPoints(); + proxyArp.activate(); } @@ -176,7 +201,8 @@ public class ProxyArpManagerTest { createDevices(NUM_DEVICES, NUM_PORTS_PER_DEVICE); createLinks(NUM_DEVICES); - addAddressBindings(); + addIntfConfig(); + popluateEdgePortService(); } /** @@ -237,13 +263,22 @@ public class ProxyArpManagerTest { replay(linkService); } - private void addAddressBindings() { + /** + * On the first three devices two config interfaces are binded on port 1. + * The first one with VLAN1, the second one with VLAN equals to none. + * Both interfaces have an IP. + * On devices 4, 5 and 6 it's binded a config interface on port 1. + * The interface is configured with VLAN 1 and no IP. + */ + private void addIntfConfig() { Set<Interface> interfaces = Sets.newHashSet(); - for (int i = 1; i <= NUM_ADDRESS_PORTS; i++) { + Set<Interface> vlanOneSet = new HashSet<>(); + + for (int i = 1; i <= LAST_CONF_DEVICE_INTF_VLAN_IP; i++) { ConnectPoint cp = new ConnectPoint(getDeviceId(i), P1); - // Interface address for IPv4 + // Interface addresses for IPv4 Ip4Prefix prefix1 = Ip4Prefix.valueOf("10.0." + (2 * i - 1) + ".0/24"); Ip4Address addr1 = Ip4Address.valueOf("10.0." + (2 * i - 1) + ".1"); Ip4Prefix prefix2 = Ip4Prefix.valueOf("10.0." + (2 * i) + ".0/24"); @@ -251,39 +286,131 @@ public class ProxyArpManagerTest { InterfaceIpAddress ia1 = new InterfaceIpAddress(addr1, prefix1); InterfaceIpAddress ia2 = new InterfaceIpAddress(addr2, prefix2); - // Interface address for IPv6 + // Interface addresses for IPv6 Ip6Prefix prefix3 = Ip6Prefix.valueOf((2 * i - 1) + "000::0/64"); Ip6Address addr3 = Ip6Address.valueOf((2 * i - 1) + "000::1"); Ip6Prefix prefix4 = Ip6Prefix.valueOf((2 * i) + "000::0/64"); - Ip6Address addr4 = Ip6Address.valueOf((2 * i) + "000::1"); + Ip6Address addr4 = Ip6Address.valueOf((2 * i) + "000::2"); InterfaceIpAddress ia3 = new InterfaceIpAddress(addr3, prefix3); InterfaceIpAddress ia4 = new InterfaceIpAddress(addr4, prefix4); + // Setting up interfaces Interface intf1 = new Interface(cp, Sets.newHashSet(ia1, ia3), MacAddress.valueOf(2 * i - 1), VlanId.vlanId((short) 1)); Interface intf2 = new Interface(cp, Sets.newHashSet(ia2, ia4), MacAddress.valueOf(2 * i), VlanId.NONE); + interfaces.add(intf1); interfaces.add(intf2); + vlanOneSet.add(intf1); + expect(interfaceService.getInterfacesByPort(cp)) .andReturn(Sets.newHashSet(intf1, intf2)).anyTimes(); } + for (int i = LAST_CONF_DEVICE_INTF_VLAN_IP + 1; i <= LAST_CONF_DEVICE_INTF_VLAN; i++) { + ConnectPoint cp = new ConnectPoint(getDeviceId(i), P1); + Interface intf1 = new Interface(cp, null, + MacAddress.NONE, + VlanId.vlanId((short) 1)); + + interfaces.add(intf1); + vlanOneSet.add(intf1); + expect(interfaceService.getInterfacesByPort(cp)) + .andReturn(Sets.newHashSet(intf1)).anyTimes(); + } + expect(interfaceService.getInterfacesByVlan(VLAN1)) + .andReturn(vlanOneSet).anyTimes(); + expect(interfaceService.getInterfacesByVlan(VLAN10)) + .andReturn(Collections.emptySet()).anyTimes(); expect(interfaceService.getInterfaces()).andReturn(interfaces).anyTimes(); - for (int i = 1; i <= NUM_FLOOD_PORTS; i++) { - ConnectPoint cp = new ConnectPoint(getDeviceId(i + NUM_ADDRESS_PORTS), + for (int i = LAST_CONF_DEVICE_INTF_VLAN + 1; i <= NUM_DEVICES; i++) { + ConnectPoint cp = new ConnectPoint(getDeviceId(i), P1); - expect(interfaceService.getInterfacesByPort(cp)) .andReturn(Collections.emptySet()).anyTimes(); } } /** + * Populates edge ports in the EdgePortService to return all port 1 + * as edge ports. + */ + private void popluateEdgePortService() { + Set<ConnectPoint> edgeConnectPoints = new HashSet<>(); + + for (int i = 1; i <= NUM_DEVICES; i++) { + for (int j = 1; j <= NUM_PORTS_PER_DEVICE; j++) { + ConnectPoint edgeConnectPoint = new ConnectPoint( + getDeviceId(i), + PortNumber.portNumber(1)); + ConnectPoint noEdgeConnectPointOne = new ConnectPoint( + getDeviceId(i), + PortNumber.portNumber(2)); + ConnectPoint noEdgeConnectPointTwo = new ConnectPoint( + getDeviceId(i), + PortNumber.portNumber(3)); + + edgeConnectPoints.add(edgeConnectPoint); + + expect(edgePortService.isEdgePoint(edgeConnectPoint)) + .andReturn(true).anyTimes(); + expect(edgePortService.isEdgePoint(noEdgeConnectPointOne)) + .andReturn(false).anyTimes(); + expect(edgePortService.isEdgePoint(noEdgeConnectPointTwo)) + .andReturn(false).anyTimes(); + } + } + expect(edgePortService.getEdgePoints()) + .andReturn(edgeConnectPoints).anyTimes(); + + replay(edgePortService); + } + + /** + * Creates a list of connect points used to verify floodling on ports + * with no interfaces configured (all ports without interface config). + */ + private void setupNoConfigCPoints() { + for (int i = NUM_DEVICES / 2 + 2; i <= NUM_DEVICES; i++) { + ConnectPoint connectPoint = new ConnectPoint( + getDeviceId(i), + PortNumber.portNumber(1)); + noConfigCPoints.add(connectPoint); + } + } + + /** + * Creates a list of connect points used to verify floodling on ports + * with interfaces configured (both VLAN and IP). + */ + private void setupconfigIpCPoints() { + for (int i = 1; i <= 3; i++) { + ConnectPoint connectPoint = new ConnectPoint( + getDeviceId(i), + PortNumber.portNumber(1)); + configIpCPoints.add(connectPoint); + } + } + + /** + * Creates a list of connect points used to verify floodling on ports + * with interfaces configured (both VLAN and IP). + */ + private void setupconfigVlanCPoints() { + for (int i = LAST_CONF_DEVICE_INTF_VLAN_IP + 1; i <= LAST_CONF_DEVICE_INTF_VLAN; i++) { + ConnectPoint connectPoint = new ConnectPoint( + getDeviceId(i), + PortNumber.portNumber(1)); + configVlanCPoints.add(connectPoint); + } + } + + /** * Tests {@link ProxyArpManager#isKnown(org.onlab.packet.IpAddress)} in the * case where the IP address is not known. * Verifies the method returns false. @@ -318,33 +445,34 @@ public class ProxyArpManagerTest { /** * Tests {@link ProxyArpManager#reply(Ethernet, ConnectPoint)} in the case where the * destination host is known. - * Verifies the correct ARP reply is sent out the correct port. + * Two host using the same VLAN are registered on the host service on devices 5 and 6. + * Host on port 6 asks for the MAC of the device on port 5. + * Since the destination mac address is known, the request is not flooded to anywhere + * and ONOS directly builds an ARP reply, sended back to the requester on device 6. + * It's verified that a proper ARP reply is received on port 1 of device 6. */ @Test public void testReplyKnown() { - //Set the return value of isEdgePoint from the edgemanager. - isEdgePointReturn = true; - - Host replyer = new DefaultHost(PID, HID1, MAC1, VLAN1, getLocation(4), + Host requestor = new DefaultHost(PID, HID1, MAC1, VLAN1, getLocation(NUM_DEVICES), Collections.singleton(IP1)); - Host requestor = new DefaultHost(PID, HID2, MAC2, VLAN1, getLocation(5), + Host replyer = new DefaultHost(PID, HID2, MAC2, VLAN1, getLocation(NUM_DEVICES - 1), Collections.singleton(IP2)); - expect(hostService.getHostsByIp(IP1)) + expect(hostService.getHostsByIp(IP2)) .andReturn(Collections.singleton(replyer)); - expect(hostService.getHost(HID2)).andReturn(requestor); + expect(hostService.getHost(HID1)).andReturn(requestor); replay(hostService); replay(interfaceService); - Ethernet arpRequest = buildArp(ARP.OP_REQUEST, MAC2, null, IP2, IP1); + Ethernet arpRequest = buildArp(ARP.OP_REQUEST, VLAN1, MAC1, null, IP1, IP2); - proxyArp.reply(arpRequest, getLocation(5)); + proxyArp.reply(arpRequest, getLocation(NUM_DEVICES)); assertEquals(1, packetService.packets.size()); - Ethernet arpReply = buildArp(ARP.OP_REPLY, MAC1, MAC2, IP1, IP2); - verifyPacketOut(arpReply, getLocation(5), packetService.packets.get(0)); + Ethernet arpReply = buildArp(ARP.OP_REPLY, VLAN1, MAC2, MAC1, IP2, IP1); + verifyPacketOut(arpReply, getLocation(NUM_DEVICES), packetService.packets.get(0)); } /** @@ -354,9 +482,6 @@ public class ProxyArpManagerTest { */ @Test public void testReplyKnownIpv6() { - //Set the return value of isEdgePoint from the edgemanager. - isEdgePointReturn = true; - Host replyer = new DefaultHost(PID, HID3, MAC3, VLAN1, getLocation(4), Collections.singleton(IP3)); @@ -370,49 +495,46 @@ public class ProxyArpManagerTest { replay(hostService); replay(interfaceService); - Ethernet ndpRequest = buildNDP(ICMP6.NEIGHBOR_SOLICITATION, - MAC4, SOLICITED_MAC3, - IP4, IP3); + Ethernet ndpRequest = buildNdp(ICMP6.NEIGHBOR_SOLICITATION, + MAC4, SOLICITED_MAC3, + IP4, IP3); proxyArp.reply(ndpRequest, getLocation(5)); assertEquals(1, packetService.packets.size()); - Ethernet ndpReply = buildNDP(ICMP6.NEIGHBOR_ADVERTISEMENT, - MAC3, MAC4, IP3, IP4); + Ethernet ndpReply = buildNdp(ICMP6.NEIGHBOR_ADVERTISEMENT, + MAC3, MAC4, IP3, IP4); verifyPacketOut(ndpReply, getLocation(5), packetService.packets.get(0)); } /** * Tests {@link ProxyArpManager#reply(Ethernet, ConnectPoint)} in the case where the * destination host is not known. + * Only a requestor is present (on device 6, port 1). The device has a VLAN configured + * which is not configured anywhere in the system. + * Since the destination is not known, and since the ARP request can't be sent out of + * interfaces configured, the ARP request is flooded out of ports 4 and 5. * Verifies the ARP request is flooded out the correct edge ports. */ @Test public void testReplyUnknown() { - isEdgePointReturn = true; - - Host requestor = new DefaultHost(PID, HID2, MAC2, VLAN1, getLocation(5), - Collections.singleton(IP2)); + Host requestor = new DefaultHost(PID, HID10, MAC10, VLAN10, getLocation(NUM_DEVICES), + Collections.singleton(IP1)); - expect(hostService.getHostsByIp(IP1)) + expect(hostService.getHostsByIp(IP2)) .andReturn(Collections.emptySet()); - expect(interfaceService.getInterfacesByIp(IP2)) + expect(interfaceService.getInterfacesByIp(IP1)) .andReturn(Collections.emptySet()); - expect(hostService.getHost(HID2)).andReturn(requestor); + expect(hostService.getHost(HID10)).andReturn(requestor); replay(hostService); replay(interfaceService); - Ethernet arpRequest = buildArp(ARP.OP_REQUEST, MAC2, null, IP2, IP1); - - //Setup the set of edge ports to be used in the reply method - getEdgePointsNoArg = Lists.newLinkedList(); - getEdgePointsNoArg.add(new ConnectPoint(DeviceId.deviceId("5"), PortNumber.portNumber(1))); - getEdgePointsNoArg.add(new ConnectPoint(DeviceId.deviceId("4"), PortNumber.portNumber(1))); + Ethernet arpRequest = buildArp(ARP.OP_REQUEST, VLAN10, MAC10, null, IP1, IP2); - proxyArp.reply(arpRequest, getLocation(6)); + proxyArp.reply(arpRequest, getLocation(NUM_DEVICES)); - verifyFlood(arpRequest); + verifyFlood(arpRequest, noConfigCPoints); } /** @@ -422,9 +544,7 @@ public class ProxyArpManagerTest { */ @Test public void testReplyUnknownIpv6() { - isEdgePointReturn = true; - - Host requestor = new DefaultHost(PID, HID4, MAC4, VLAN1, getLocation(5), + Host requestor = new DefaultHost(PID, HID4, MAC4, VLAN1, getLocation(NUM_DEVICES), Collections.singleton(IP4)); expect(hostService.getHostsByIp(IP3)) @@ -436,53 +556,111 @@ public class ProxyArpManagerTest { replay(hostService); replay(interfaceService); - Ethernet ndpRequest = buildNDP(ICMP6.NEIGHBOR_SOLICITATION, - MAC4, SOLICITED_MAC3, - IP4, IP3); - - //Setup the set of edge ports to be used in the reply method - getEdgePointsNoArg = Lists.newLinkedList(); - getEdgePointsNoArg.add(new ConnectPoint(DeviceId.deviceId("5"), PortNumber.portNumber(1))); - getEdgePointsNoArg.add(new ConnectPoint(DeviceId.deviceId("4"), PortNumber.portNumber(1))); + Ethernet ndpRequest = buildNdp(ICMP6.NEIGHBOR_SOLICITATION, + MAC4, SOLICITED_MAC3, + IP4, IP3); - proxyArp.reply(ndpRequest, getLocation(6)); + proxyArp.reply(ndpRequest, getLocation(NUM_DEVICES)); - verifyFlood(ndpRequest); + verifyFlood(ndpRequest, noConfigCPoints); } /** * Tests {@link ProxyArpManager#reply(Ethernet, ConnectPoint)} in the case where the * destination host is known for that IP address, but is not on the same * VLAN as the source host. + * An host is connected on device 6, port 1 where no interfaces are defined. It sends + * ARP requests from VLAN10, not configured anywhere in the network. Another host with + * the IP address requested lives on device 5, port 1 in the network. Anyway, since the + * host uses another VLAN it's not found and the ARP packet is flooded out of port + * 4 and 5. + * * Verifies the ARP request is flooded out the correct edge ports. */ @Test public void testReplyDifferentVlan() { - - Host replyer = new DefaultHost(PID, HID1, MAC1, VLAN2, getLocation(4), + Host requestor = new DefaultHost(PID, HID10, MAC10, VLAN10, getLocation(NUM_DEVICES), Collections.singleton(IP1)); - Host requestor = new DefaultHost(PID, HID2, MAC2, VLAN1, getLocation(5), + Host replyer = new DefaultHost(PID, HID2, MAC2, VLAN2, getLocation(NUM_DEVICES - 1), Collections.singleton(IP2)); - expect(hostService.getHostsByIp(IP1)) + expect(hostService.getHostsByIp(IP2)) .andReturn(Collections.singleton(replyer)); - expect(interfaceService.getInterfacesByIp(IP2)) + expect(interfaceService.getInterfacesByIp(IP1)) .andReturn(Collections.emptySet()); - expect(hostService.getHost(HID2)).andReturn(requestor); + expect(hostService.getHost(HID10)).andReturn(requestor); + + replay(hostService); + replay(interfaceService); + + Ethernet arpRequest = buildArp(ARP.OP_REQUEST, VLAN10, MAC10, null, IP1, IP2); + + proxyArp.reply(arpRequest, getLocation(NUM_DEVICES)); + + verifyFlood(arpRequest, noConfigCPoints); + } + + /** + * Tests {@link ProxyArpManager#reply(Ethernet, ConnectPoint)} in the case where the + * a vlan packet comes in from a port without interfaces configured. The destination + * host is unknown for that IP address and there are some interfaces configured on + * the same vlan. + * It's expected to see the ARP request going out through ports with no interfaces + * configured, devices 4 and 5, port 1. + * + * Verifies the ARP request is flooded out the correct edge ports. + */ + @Test + public void testConfiguredVlan() { + Host requestor = new DefaultHost(PID, HID1, MAC1, VLAN1, getLocation(NUM_DEVICES), + Collections.singleton(IP1)); + + expect(hostService.getHostsByIp(IP2)) + .andReturn(Collections.emptySet()); + expect(interfaceService.getInterfacesByIp(IP1)) + .andReturn(Collections.emptySet()); + expect(hostService.getHost(HID1)).andReturn(requestor); + + replay(hostService); + replay(interfaceService); + + Ethernet arpRequest = buildArp(ARP.OP_REQUEST, VLAN1, MAC1, null, IP1, IP2); + + proxyArp.reply(arpRequest, getLocation(NUM_DEVICES)); + + verifyFlood(arpRequest, noConfigCPoints); + } + + /** + * Tests {@link ProxyArpManager#reply(Ethernet, ConnectPoint)} in the case where the + * a vlan packet comes in from a port without interfaces configured. The destination + * host is not known for that IP address and there are some interfaces configured on + * the same vlan. + * It's expected to see the ARP request going out through ports with no interfaces + * configured, devices 4 and 5, port 1. + * + * Verifies the ARP request is flooded out the correct edge ports. + */ + @Test + public void testConfiguredVlanOnInterfaces() { + Host requestor = new DefaultHost(PID, HID1, MAC1, VLAN1, getLocation(6), + Collections.singleton(IP1)); + + expect(hostService.getHostsByIp(IP2)) + .andReturn(Collections.emptySet()); + expect(interfaceService.getInterfacesByIp(IP1)) + .andReturn(Collections.emptySet()); + expect(hostService.getHost(HID1)).andReturn(requestor); replay(hostService); replay(interfaceService); - Ethernet arpRequest = buildArp(ARP.OP_REQUEST, MAC2, null, IP2, IP1); + Ethernet arpRequest = buildArp(ARP.OP_REQUEST, VLAN1, MAC1, null, IP1, IP2); - //Setup for flood test - getEdgePointsNoArg = Lists.newLinkedList(); - getEdgePointsNoArg.add(new ConnectPoint(DeviceId.deviceId("5"), PortNumber.portNumber(1))); - getEdgePointsNoArg.add(new ConnectPoint(DeviceId.deviceId("4"), PortNumber.portNumber(1))); proxyArp.reply(arpRequest, getLocation(6)); - verifyFlood(arpRequest); + verifyFlood(arpRequest, configVlanCPoints); } /** @@ -493,13 +671,12 @@ public class ProxyArpManagerTest { */ @Test public void testReplyDifferentVlanIpv6() { - - Host replyer = new DefaultHost(PID, HID3, MAC3, VLAN2, getLocation(4), - Collections.singleton(IP3)); - - Host requestor = new DefaultHost(PID, HID4, MAC4, VLAN1, getLocation(5), + Host requestor = new DefaultHost(PID, HID4, MAC4, VLAN1, getLocation(NUM_DEVICES), Collections.singleton(IP4)); + Host replyer = new DefaultHost(PID, HID3, MAC3, VLAN2, getLocation(NUM_DEVICES - 1), + Collections.singleton(IP3)); + expect(hostService.getHostsByIp(IP3)) .andReturn(Collections.singleton(replyer)); expect(interfaceService.getInterfacesByIp(IP4)) @@ -509,17 +686,13 @@ public class ProxyArpManagerTest { replay(hostService); replay(interfaceService); - Ethernet ndpRequest = buildNDP(ICMP6.NEIGHBOR_SOLICITATION, - MAC4, SOLICITED_MAC3, - IP4, IP3); + Ethernet ndpRequest = buildNdp(ICMP6.NEIGHBOR_SOLICITATION, + MAC4, SOLICITED_MAC3, + IP4, IP3); - //Setup for flood test - getEdgePointsNoArg = Lists.newLinkedList(); - getEdgePointsNoArg.add(new ConnectPoint(DeviceId.deviceId("5"), PortNumber.portNumber(1))); - getEdgePointsNoArg.add(new ConnectPoint(DeviceId.deviceId("4"), PortNumber.portNumber(1))); - proxyArp.reply(ndpRequest, getLocation(6)); + proxyArp.reply(ndpRequest, getLocation(NUM_DEVICES)); - verifyFlood(ndpRequest); + verifyFlood(ndpRequest, noConfigCPoints); } /** @@ -533,29 +706,29 @@ public class ProxyArpManagerTest { MacAddress firstMac = MacAddress.valueOf(1L); MacAddress secondMac = MacAddress.valueOf(2L); - Host requestor = new DefaultHost(PID, HID2, MAC2, VLAN1, LOC1, + Host requestor = new DefaultHost(PID, HID1, MAC1, VLAN1, LOC1, Collections.singleton(theirIp)); - expect(hostService.getHost(HID2)).andReturn(requestor); + expect(hostService.getHost(HID1)).andReturn(requestor); replay(hostService); replay(interfaceService); - Ethernet arpRequest = buildArp(ARP.OP_REQUEST, MAC2, null, theirIp, ourFirstIp); - isEdgePointReturn = true; + Ethernet arpRequest = buildArp(ARP.OP_REQUEST, VLAN1, MAC1, null, theirIp, ourFirstIp); + proxyArp.reply(arpRequest, LOC1); assertEquals(1, packetService.packets.size()); - Ethernet arpReply = buildArp(ARP.OP_REPLY, firstMac, MAC2, ourFirstIp, theirIp); + Ethernet arpReply = buildArp(ARP.OP_REPLY, VLAN1, firstMac, MAC1, ourFirstIp, theirIp); verifyPacketOut(arpReply, LOC1, packetService.packets.get(0)); // Test a request for the second address on that port packetService.packets.clear(); - arpRequest = buildArp(ARP.OP_REQUEST, MAC2, null, theirIp, ourSecondIp); + arpRequest = buildArp(ARP.OP_REQUEST, VLAN1, MAC1, null, theirIp, ourSecondIp); proxyArp.reply(arpRequest, LOC1); assertEquals(1, packetService.packets.size()); - arpReply = buildArp(ARP.OP_REPLY, secondMac, MAC2, ourSecondIp, theirIp); + arpReply = buildArp(ARP.OP_REPLY, VLAN1, secondMac, MAC1, ourSecondIp, theirIp); verifyPacketOut(arpReply, LOC1, packetService.packets.get(0)); } @@ -566,7 +739,7 @@ public class ProxyArpManagerTest { public void testReplyToRequestForUsIpv6() { Ip6Address theirIp = Ip6Address.valueOf("1000::ffff"); Ip6Address ourFirstIp = Ip6Address.valueOf("1000::1"); - Ip6Address ourSecondIp = Ip6Address.valueOf("2000::1"); + Ip6Address ourSecondIp = Ip6Address.valueOf("2000::2"); MacAddress firstMac = MacAddress.valueOf(1L); MacAddress secondMac = MacAddress.valueOf(2L); @@ -579,37 +752,37 @@ public class ProxyArpManagerTest { replay(hostService); replay(interfaceService); - Ethernet ndpRequest = buildNDP(ICMP6.NEIGHBOR_SOLICITATION, - MAC2, - MacAddress.valueOf("33:33:ff:00:00:01"), - theirIp, - ourFirstIp); - isEdgePointReturn = true; + Ethernet ndpRequest = buildNdp(ICMP6.NEIGHBOR_SOLICITATION, + MAC2, + MacAddress.valueOf("33:33:ff:00:00:01"), + theirIp, + ourFirstIp); + proxyArp.reply(ndpRequest, LOC1); assertEquals(1, packetService.packets.size()); - Ethernet ndpReply = buildNDP(ICMP6.NEIGHBOR_ADVERTISEMENT, - firstMac, - MAC2, - ourFirstIp, - theirIp); + Ethernet ndpReply = buildNdp(ICMP6.NEIGHBOR_ADVERTISEMENT, + firstMac, + MAC2, + ourFirstIp, + theirIp); verifyPacketOut(ndpReply, LOC1, packetService.packets.get(0)); // Test a request for the second address on that port packetService.packets.clear(); - ndpRequest = buildNDP(ICMP6.NEIGHBOR_SOLICITATION, - MAC2, - MacAddress.valueOf("33:33:ff:00:00:01"), - theirIp, - ourSecondIp); + ndpRequest = buildNdp(ICMP6.NEIGHBOR_SOLICITATION, + MAC2, + MacAddress.valueOf("33:33:ff:00:00:01"), + theirIp, + ourSecondIp); proxyArp.reply(ndpRequest, LOC1); assertEquals(1, packetService.packets.size()); - ndpReply = buildNDP(ICMP6.NEIGHBOR_ADVERTISEMENT, - secondMac, - MAC2, - ourSecondIp, - theirIp); + ndpReply = buildNdp(ICMP6.NEIGHBOR_ADVERTISEMENT, + secondMac, + MAC2, + ourSecondIp, + theirIp); verifyPacketOut(ndpReply, LOC1, packetService.packets.get(0)); } @@ -624,14 +797,14 @@ public class ProxyArpManagerTest { Ip4Address theirIp = Ip4Address.valueOf("10.0.1.254"); // Request for a valid external IP address but coming in the wrong port - Ethernet arpRequest = buildArp(ARP.OP_REQUEST, MAC1, null, theirIp, + Ethernet arpRequest = buildArp(ARP.OP_REQUEST, VLAN1, MAC1, null, theirIp, Ip4Address.valueOf("10.0.3.1")); proxyArp.reply(arpRequest, LOC1); assertEquals(0, packetService.packets.size()); // Request for a valid internal IP address but coming in an external port packetService.packets.clear(); - arpRequest = buildArp(ARP.OP_REQUEST, MAC1, null, theirIp, IP1); + arpRequest = buildArp(ARP.OP_REQUEST, VLAN1, MAC1, null, theirIp, IP1); proxyArp.reply(arpRequest, LOC1); assertEquals(0, packetService.packets.size()); } @@ -646,21 +819,21 @@ public class ProxyArpManagerTest { Ip6Address theirIp = Ip6Address.valueOf("1000::ffff"); - Ethernet ndpRequest = buildNDP(ICMP6.NEIGHBOR_SOLICITATION, - MAC1, - MacAddress.valueOf("33:33:ff:00:00:01"), - theirIp, - Ip6Address.valueOf("3000::1")); + Ethernet ndpRequest = buildNdp(ICMP6.NEIGHBOR_SOLICITATION, + MAC1, + MacAddress.valueOf("33:33:ff:00:00:01"), + theirIp, + Ip6Address.valueOf("3000::1")); proxyArp.reply(ndpRequest, LOC1); assertEquals(0, packetService.packets.size()); // Request for a valid internal IP address but coming in an external port packetService.packets.clear(); - ndpRequest = buildNDP(ICMP6.NEIGHBOR_SOLICITATION, - MAC1, - MacAddress.valueOf("33:33:ff:00:00:01"), - theirIp, - IP3); + ndpRequest = buildNdp(ICMP6.NEIGHBOR_SOLICITATION, + MAC1, + MacAddress.valueOf("33:33:ff:00:00:01"), + theirIp, + IP3); proxyArp.reply(ndpRequest, LOC1); assertEquals(0, packetService.packets.size()); } @@ -685,9 +858,8 @@ public class ProxyArpManagerTest { // This is a request from something inside our network (like a BGP // daemon) to an external host. - Ethernet arpRequest = buildArp(ARP.OP_REQUEST, ourMac, null, ourIp, theirIp); + Ethernet arpRequest = buildArp(ARP.OP_REQUEST, VLAN1, ourMac, null, ourIp, theirIp); //Ensure the packet is allowed through (it is not to an internal port) - isEdgePointReturn = true; proxyArp.reply(arpRequest, getLocation(5)); assertEquals(1, packetService.packets.size()); @@ -722,14 +894,11 @@ public class ProxyArpManagerTest { // This is a request from something inside our network (like a BGP // daemon) to an external host. - Ethernet ndpRequest = buildNDP(ICMP6.NEIGHBOR_SOLICITATION, - ourMac, - MacAddress.valueOf("33:33:ff:00:00:01"), - ourIp, - theirIp); - - //Ensure the packet is allowed through (it is not to an internal port) - isEdgePointReturn = true; + Ethernet ndpRequest = buildNdp(ICMP6.NEIGHBOR_SOLICITATION, + ourMac, + MacAddress.valueOf("33:33:ff:00:00:01"), + ourIp, + theirIp); proxyArp.reply(ndpRequest, getLocation(5)); assertEquals(1, packetService.packets.size()); @@ -758,7 +927,7 @@ public class ProxyArpManagerTest { replay(hostService); replay(interfaceService); - Ethernet arpRequest = buildArp(ARP.OP_REPLY, MAC2, MAC1, IP2, IP1); + Ethernet arpRequest = buildArp(ARP.OP_REPLY, VLAN1, MAC2, MAC1, IP2, IP1); proxyArp.forward(arpRequest, LOC2); @@ -785,9 +954,9 @@ public class ProxyArpManagerTest { replay(hostService); replay(interfaceService); - Ethernet ndpRequest = buildNDP(ICMP6.NEIGHBOR_SOLICITATION, - MAC4, SOLICITED_MAC3, - IP4, IP3); + Ethernet ndpRequest = buildNdp(ICMP6.NEIGHBOR_SOLICITATION, + MAC4, SOLICITED_MAC3, + IP4, IP3); proxyArp.forward(ndpRequest, LOC2); @@ -804,22 +973,15 @@ public class ProxyArpManagerTest { */ @Test public void testForwardFlood() { - expect(hostService.getHost(HID1)).andReturn(null); + expect(hostService.getHost(HID2)).andReturn(null); replay(hostService); replay(interfaceService); - Ethernet arpRequest = buildArp(ARP.OP_REPLY, MAC2, MAC1, IP2, IP1); - - //populate the list of edges when so that when forward hits flood in the manager it contains the values - //that should continue on - getEdgePointsNoArg = Lists.newLinkedList(); - getEdgePointsNoArg.add(new ConnectPoint(DeviceId.deviceId("3"), PortNumber.portNumber(1))); - getEdgePointsNoArg.add(new ConnectPoint(DeviceId.deviceId("5"), PortNumber.portNumber(1))); - getEdgePointsNoArg.add(new ConnectPoint(DeviceId.deviceId("4"), PortNumber.portNumber(1))); + Ethernet arpRequest = buildArp(ARP.OP_REPLY, VLAN1, MAC1, MAC2, IP1, IP2); - proxyArp.forward(arpRequest, getLocation(6)); + proxyArp.forward(arpRequest, getLocation(NUM_DEVICES)); - verifyFlood(arpRequest); + verifyFlood(arpRequest, noConfigCPoints); } /** @@ -833,20 +995,13 @@ public class ProxyArpManagerTest { replay(hostService); replay(interfaceService); - Ethernet ndpRequest = buildNDP(ICMP6.NEIGHBOR_SOLICITATION, - MAC4, SOLICITED_MAC3, - IP4, IP3); + Ethernet ndpRequest = buildNdp(ICMP6.NEIGHBOR_SOLICITATION, + MAC4, SOLICITED_MAC3, + IP4, IP3); - //populate the list of edges when so that when forward hits flood in the manager it contains the values - //that should continue on - getEdgePointsNoArg = Lists.newLinkedList(); - getEdgePointsNoArg.add(new ConnectPoint(DeviceId.deviceId("3"), PortNumber.portNumber(1))); - getEdgePointsNoArg.add(new ConnectPoint(DeviceId.deviceId("5"), PortNumber.portNumber(1))); - getEdgePointsNoArg.add(new ConnectPoint(DeviceId.deviceId("4"), PortNumber.portNumber(1))); + proxyArp.forward(ndpRequest, getLocation(NUM_DEVICES)); - proxyArp.forward(ndpRequest, getLocation(6)); - - verifyFlood(ndpRequest); + verifyFlood(ndpRequest, noConfigCPoints); } /** @@ -854,21 +1009,20 @@ public class ProxyArpManagerTest { * except for the input port. * * @param packet the packet that was expected to be flooded + * @param connectPoints the connectPoints where the outpacket should be + * observed */ - private void verifyFlood(Ethernet packet) { + private void verifyFlood(Ethernet packet, List<ConnectPoint> connectPoints) { + // There should be 1 less than NUM_FLOOD_PORTS; the inPort should be excluded. - assertEquals(NUM_FLOOD_PORTS - 1, packetService.packets.size()); + assertEquals(connectPoints.size() - 1, packetService.packets.size()); Collections.sort(packetService.packets, (o1, o2) -> o1.sendThrough().uri().compareTo(o2.sendThrough().uri())); - - for (int i = 0; i < NUM_FLOOD_PORTS - 1; i++) { - ConnectPoint cp = new ConnectPoint(getDeviceId(NUM_ADDRESS_PORTS + i + 1), - PortNumber.portNumber(1)); - + for (int i = 0; i < connectPoints.size() - 1; i++) { OutboundPacket outboundPacket = packetService.packets.get(i); - verifyPacketOut(packet, cp, outboundPacket); + verifyPacketOut(packet, connectPoints.get(i), outboundPacket); } } @@ -913,8 +1067,8 @@ public class ProxyArpManagerTest { * @param dstIp destination IP address * @return the ARP packet */ - private Ethernet buildArp(short opcode, MacAddress srcMac, MacAddress dstMac, - Ip4Address srcIp, Ip4Address dstIp) { + private Ethernet buildArp(short opcode, VlanId vlanId, MacAddress srcMac, + MacAddress dstMac, Ip4Address srcIp, Ip4Address dstIp) { Ethernet eth = new Ethernet(); if (dstMac == null) { @@ -925,7 +1079,7 @@ public class ProxyArpManagerTest { eth.setSourceMACAddress(srcMac); eth.setEtherType(Ethernet.TYPE_ARP); - eth.setVlanID(VLAN1.toShort()); + eth.setVlanID(vlanId.toShort()); ARP arp = new ARP(); arp.setOpCode(opcode); @@ -937,7 +1091,7 @@ public class ProxyArpManagerTest { arp.setSenderHardwareAddress(srcMac.toBytes()); if (dstMac == null) { - arp.setTargetHardwareAddress(ZERO_MAC_ADDRESS); + arp.setTargetHardwareAddress(zeroMacAddress); } else { arp.setTargetHardwareAddress(dstMac.toBytes()); } @@ -959,7 +1113,7 @@ public class ProxyArpManagerTest { * @param dstIp destination IP address * @return the NDP packet */ - private Ethernet buildNDP(byte type, MacAddress srcMac, MacAddress dstMac, + private Ethernet buildNdp(byte type, MacAddress srcMac, MacAddress dstMac, Ip6Address srcIp, Ip6Address dstIp) { assertThat(type, anyOf( is(ICMP6.NEIGHBOR_SOLICITATION), @@ -1019,19 +1173,6 @@ public class ProxyArpManagerTest { } - class TestEdgePortService extends EdgeManager { - - @Override - public boolean isEdgePoint(ConnectPoint connectPoint) { - return isEdgePointReturn; - } - - @Override - public Iterable<ConnectPoint> getEdgePoints() { - return getEdgePointsNoArg; - } - } - private class TestProxyArpStoreAdapter implements ProxyArpStore { @Override public void forward(ConnectPoint outPort, Host subject, ByteBuffer packet) { |