From c4f681c776c0acc566ff1af0692df13b81870c19 Mon Sep 17 00:00:00 2001 From: Jonathan Hart Date: Fri, 9 Sep 2016 07:14:25 -0700 Subject: [PATCH] Reimplemented the ProxyArp app on top of the NeighbourResolutionService. Also some small API changes to track app ID of handler registrations, and improved interface matching in NeighbourPacketManager. Added CLI to view handler registrations. Change-Id: I8cd0b91a16d9ec60287b65f9d8fc5e3cd87560e8 --- apps/proxyarp/BUCK | 1 + apps/proxyarp/pom.xml | 4 + .../onosproject/proxyarp/DefaultProxyArp.java | 97 +++++++++++++ .../org/onosproject/proxyarp/ProxyArp.java | 5 +- .../onosproject/proxyarp/package-info.java | 2 +- .../cli/net/NeighbourHandlersListCommand.java | 46 ++++++ .../OSGI-INF/blueprint/shell-config.xml | 3 + .../net/proxyarp/ProxyArpService.java | 3 + .../net/proxyarp/ProxyArpStore.java | 4 + .../net/proxyarp/impl/ProxyArpManager.java | 7 +- .../impl/DistributedProxyArpStore.java | 4 + .../NeighbourHandlerRegistration.java | 47 ++++++ .../neighbour/NeighbourMessageContext.java | 10 ++ .../neighbour/NeighbourResolutionService.java | 36 ++++- .../impl/DefaultNeighbourMessageContext.java | 7 +- .../impl/NeighbourPacketManager.java | 135 +++++++++++++----- 16 files changed, 370 insertions(+), 41 deletions(-) create mode 100644 apps/proxyarp/src/main/java/org/onosproject/proxyarp/DefaultProxyArp.java create mode 100644 cli/src/main/java/org/onosproject/cli/net/NeighbourHandlersListCommand.java create mode 100644 incubator/api/src/main/java/org/onosproject/incubator/net/neighbour/NeighbourHandlerRegistration.java diff --git a/apps/proxyarp/BUCK b/apps/proxyarp/BUCK index 5406f4e62c..70e3c9df09 100644 --- a/apps/proxyarp/BUCK +++ b/apps/proxyarp/BUCK @@ -1,5 +1,6 @@ COMPILE_DEPS = [ '//lib:CORE_DEPS', + '//incubator/api:onos-incubator-api', ] osgi_jar ( diff --git a/apps/proxyarp/pom.xml b/apps/proxyarp/pom.xml index 86664f4c54..0d2b3a9721 100644 --- a/apps/proxyarp/pom.xml +++ b/apps/proxyarp/pom.xml @@ -43,6 +43,10 @@ org.osgi org.osgi.compendium + + org.onosproject + onos-incubator-api + diff --git a/apps/proxyarp/src/main/java/org/onosproject/proxyarp/DefaultProxyArp.java b/apps/proxyarp/src/main/java/org/onosproject/proxyarp/DefaultProxyArp.java new file mode 100644 index 0000000000..175989ff97 --- /dev/null +++ b/apps/proxyarp/src/main/java/org/onosproject/proxyarp/DefaultProxyArp.java @@ -0,0 +1,97 @@ +/* + * Copyright 2016-present Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onosproject.proxyarp; + +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.onosproject.core.ApplicationId; +import org.onosproject.core.CoreService; +import org.onosproject.incubator.net.neighbour.DefaultNeighbourMessageHandler; +import org.onosproject.incubator.net.neighbour.NeighbourResolutionService; +import org.onosproject.net.ConnectPoint; +import org.onosproject.net.edge.EdgePortEvent; +import org.onosproject.net.edge.EdgePortListener; +import org.onosproject.net.edge.EdgePortService; + +/** + * Implements proxy ARP and NDP functionality by considering the entire network + * as a single L2 broadcast domain. + *

+ * This application maintains a DefaultNeighbourMessageHandler on all edge ports + * in the network, and the handler implements the desired proxying functionality. + *

+ */ +@Component(immediate = true) +public class DefaultProxyArp { + + private static final String APP_NAME = "org.onosproject.proxyarp"; + + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) + protected EdgePortService edgeService; + + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) + protected NeighbourResolutionService neighbourResolutionService; + + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) + protected CoreService coreService; + + private ApplicationId appId; + + private InternalEdgeListener edgeListener = new InternalEdgeListener(); + private DefaultNeighbourMessageHandler defaultHandler = new DefaultNeighbourMessageHandler(); + + @Activate + protected void activate() { + appId = coreService.registerApplication(APP_NAME); + + edgeService.addListener(edgeListener); + edgeService.getEdgePoints().forEach(this::addDefault); + } + + @Deactivate + protected void deactivate() { + edgeService.removeListener(edgeListener); + neighbourResolutionService.unregisterNeighbourHandlers(appId); + } + + private void addDefault(ConnectPoint port) { + neighbourResolutionService.registerNeighbourHandler(port, defaultHandler, appId); + } + + private void removeDefault(ConnectPoint port) { + neighbourResolutionService.unregisterNeighbourHandler(port, defaultHandler, appId); + } + + private class InternalEdgeListener implements EdgePortListener { + @Override + public void event(EdgePortEvent event) { + switch (event.type()) { + case EDGE_PORT_ADDED: + addDefault(event.subject()); + break; + case EDGE_PORT_REMOVED: + removeDefault(event.subject()); + break; + default: + break; + } + } + } +} diff --git a/apps/proxyarp/src/main/java/org/onosproject/proxyarp/ProxyArp.java b/apps/proxyarp/src/main/java/org/onosproject/proxyarp/ProxyArp.java index 612301e099..d441aeed58 100644 --- a/apps/proxyarp/src/main/java/org/onosproject/proxyarp/ProxyArp.java +++ b/apps/proxyarp/src/main/java/org/onosproject/proxyarp/ProxyArp.java @@ -51,8 +51,11 @@ import static org.slf4j.LoggerFactory.getLogger; /** * Sample reactive proxy arp application. + * + * @deprecated in Hummingbird release */ -@Component(immediate = true) +@Deprecated +@Component(enabled = false) public class ProxyArp { private final Logger log = getLogger(getClass()); diff --git a/apps/proxyarp/src/main/java/org/onosproject/proxyarp/package-info.java b/apps/proxyarp/src/main/java/org/onosproject/proxyarp/package-info.java index d8ed846308..960382ff9c 100644 --- a/apps/proxyarp/src/main/java/org/onosproject/proxyarp/package-info.java +++ b/apps/proxyarp/src/main/java/org/onosproject/proxyarp/package-info.java @@ -15,6 +15,6 @@ */ /** - * Proxy Arp application that handles arp resolution for you. + * Application that handles ARP and NDP resolution on a single L2 broadcast domain. */ package org.onosproject.proxyarp; diff --git a/cli/src/main/java/org/onosproject/cli/net/NeighbourHandlersListCommand.java b/cli/src/main/java/org/onosproject/cli/net/NeighbourHandlersListCommand.java new file mode 100644 index 0000000000..1fd618eedd --- /dev/null +++ b/cli/src/main/java/org/onosproject/cli/net/NeighbourHandlersListCommand.java @@ -0,0 +1,46 @@ +/* + * Copyright 2016-present Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onosproject.cli.net; + +import org.apache.karaf.shell.commands.Command; +import org.onosproject.cli.AbstractShellCommand; +import org.onosproject.incubator.net.intf.Interface; +import org.onosproject.incubator.net.neighbour.NeighbourResolutionService; + +/** + * Lists neighbour message handlers. + */ +@Command(scope = "onos", name = "neighbour-handlers", + description = "Lists neighbour message handlers") +public class NeighbourHandlersListCommand extends AbstractShellCommand { + + private static final String FORMAT = "%20s: interface=%s, class=%s"; + + @Override + protected void execute() { + NeighbourResolutionService service = get(NeighbourResolutionService.class); + + service.getHandlerRegistrations().forEach((cp, list) -> { + list.forEach(hr -> print(FORMAT, cp, intfToName(hr.intf()), + hr.handler().getClass().getCanonicalName())); + }); + } + + private String intfToName(Interface intf) { + return (intf == null) ? "(None)" : intf.name(); + } +} diff --git a/cli/src/main/resources/OSGI-INF/blueprint/shell-config.xml b/cli/src/main/resources/OSGI-INF/blueprint/shell-config.xml index 5664cc3816..4da1d8bd2c 100644 --- a/cli/src/main/resources/OSGI-INF/blueprint/shell-config.xml +++ b/cli/src/main/resources/OSGI-INF/blueprint/shell-config.xml @@ -485,6 +485,9 @@ + + + diff --git a/core/api/src/main/java/org/onosproject/net/proxyarp/ProxyArpService.java b/core/api/src/main/java/org/onosproject/net/proxyarp/ProxyArpService.java index 37d91a833c..015a26354b 100644 --- a/core/api/src/main/java/org/onosproject/net/proxyarp/ProxyArpService.java +++ b/core/api/src/main/java/org/onosproject/net/proxyarp/ProxyArpService.java @@ -22,8 +22,11 @@ import org.onosproject.net.packet.PacketContext; /** * Service for processing ARP or NDP requests on behalf of applications. + * + * @deprecated in Hummingbird release. Use NeighbourResolutionService instead. */ // TODO: move to the peer host package +@Deprecated public interface ProxyArpService { /** diff --git a/core/api/src/main/java/org/onosproject/net/proxyarp/ProxyArpStore.java b/core/api/src/main/java/org/onosproject/net/proxyarp/ProxyArpStore.java index e386fb1460..708f92fa72 100644 --- a/core/api/src/main/java/org/onosproject/net/proxyarp/ProxyArpStore.java +++ b/core/api/src/main/java/org/onosproject/net/proxyarp/ProxyArpStore.java @@ -22,7 +22,11 @@ import java.nio.ByteBuffer; /** * State distribution mechanism for the proxy ARP service. + * + * @deprecated in Hummingbird release. This is no longer necessary as there are + * other solutions for the problem this was solving. */ +@Deprecated public interface ProxyArpStore { /** diff --git a/core/net/src/main/java/org/onosproject/net/proxyarp/impl/ProxyArpManager.java b/core/net/src/main/java/org/onosproject/net/proxyarp/impl/ProxyArpManager.java index 0c84651a37..3937e9c256 100644 --- a/core/net/src/main/java/org/onosproject/net/proxyarp/impl/ProxyArpManager.java +++ b/core/net/src/main/java/org/onosproject/net/proxyarp/impl/ProxyArpManager.java @@ -63,7 +63,12 @@ import static org.onosproject.security.AppGuard.checkPermission; import static org.slf4j.LoggerFactory.getLogger; import static org.onosproject.security.AppPermission.Type.*; - +/** + * Implementation of the proxy ARP service. + * + * @deprecated in Hummingbird release + */ +@Deprecated @Component(immediate = true) @Service public class ProxyArpManager implements ProxyArpService { diff --git a/core/store/dist/src/main/java/org/onosproject/store/proxyarp/impl/DistributedProxyArpStore.java b/core/store/dist/src/main/java/org/onosproject/store/proxyarp/impl/DistributedProxyArpStore.java index f388aa9eb0..00768dcfce 100644 --- a/core/store/dist/src/main/java/org/onosproject/store/proxyarp/impl/DistributedProxyArpStore.java +++ b/core/store/dist/src/main/java/org/onosproject/store/proxyarp/impl/DistributedProxyArpStore.java @@ -50,7 +50,11 @@ import static org.onlab.util.Tools.groupedThreads; /** * Implementation of proxy ARP distribution mechanism. + * + * @deprecated in Hummingbird release. This is no longer necessary as there are + * other solutions for the problem this was solving. */ +@Deprecated @Component(immediate = true) @Service public class DistributedProxyArpStore implements ProxyArpStore { diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/neighbour/NeighbourHandlerRegistration.java b/incubator/api/src/main/java/org/onosproject/incubator/net/neighbour/NeighbourHandlerRegistration.java new file mode 100644 index 0000000000..cc800a3c56 --- /dev/null +++ b/incubator/api/src/main/java/org/onosproject/incubator/net/neighbour/NeighbourHandlerRegistration.java @@ -0,0 +1,47 @@ +/* + * Copyright 2016-present Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onosproject.incubator.net.neighbour; + +import org.onosproject.core.ApplicationId; +import org.onosproject.incubator.net.intf.Interface; + +/** + * Information about the registration of a neighbour message handler. + */ +public interface NeighbourHandlerRegistration { + + /** + * Gets the interface of the registration. + * + * @return interface + */ + Interface intf(); + + /** + * Gets the neighbour message handler. + * + * @return message handler + */ + NeighbourMessageHandler handler(); + + /** + * Gets the ID of the application that registered the handler. + * + * @return application ID + */ + ApplicationId appId(); +} diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/neighbour/NeighbourMessageContext.java b/incubator/api/src/main/java/org/onosproject/incubator/net/neighbour/NeighbourMessageContext.java index f498f17e8d..0c609ae05a 100644 --- a/incubator/api/src/main/java/org/onosproject/incubator/net/neighbour/NeighbourMessageContext.java +++ b/incubator/api/src/main/java/org/onosproject/incubator/net/neighbour/NeighbourMessageContext.java @@ -75,6 +75,16 @@ public interface NeighbourMessageContext { */ MacAddress srcMac(); + /** + * Gets the destination MAC address of the message. + *

+ * Only valid for reply packets, will be null for request packets. + *

+ * + * @return target MAC address + */ + MacAddress dstMac(); + /** * Gets the target IP address of the message. * diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/neighbour/NeighbourResolutionService.java b/incubator/api/src/main/java/org/onosproject/incubator/net/neighbour/NeighbourResolutionService.java index 94401ccf6a..4e4adb94ad 100644 --- a/incubator/api/src/main/java/org/onosproject/incubator/net/neighbour/NeighbourResolutionService.java +++ b/incubator/api/src/main/java/org/onosproject/incubator/net/neighbour/NeighbourResolutionService.java @@ -17,9 +17,13 @@ package org.onosproject.incubator.net.neighbour; import com.google.common.annotations.Beta; +import org.onosproject.core.ApplicationId; import org.onosproject.incubator.net.intf.Interface; import org.onosproject.net.ConnectPoint; +import java.util.Collection; +import java.util.Map; + /** * Provides a means of registering logic for handling neighbour messages. */ @@ -32,8 +36,10 @@ public interface NeighbourResolutionService { * * @param connectPoint connect point * @param handler neighbour message handler + * @param appId application ID */ - void registerNeighbourHandler(ConnectPoint connectPoint, NeighbourMessageHandler handler); + void registerNeighbourHandler(ConnectPoint connectPoint, NeighbourMessageHandler handler, + ApplicationId appId); /** * Registers a neighbour message handler for all neighbour messages incoming @@ -42,8 +48,10 @@ public interface NeighbourResolutionService { * * @param intf interface * @param handler neighbour message handler + * @param appId application ID */ - void registerNeighbourHandler(Interface intf, NeighbourMessageHandler handler); + void registerNeighbourHandler(Interface intf, NeighbourMessageHandler handler, + ApplicationId appId); /** * Unregisters a neighbour message handler that was assigned to a connect @@ -51,14 +59,34 @@ public interface NeighbourResolutionService { * * @param connectPoint connect point * @param handler neighbour message handler + * @param appId application ID */ - void unregisterNeighbourHandler(ConnectPoint connectPoint, NeighbourMessageHandler handler); + void unregisterNeighbourHandler(ConnectPoint connectPoint, NeighbourMessageHandler handler, + ApplicationId appId); /** * Unregisters a neighbour message handler that was assigned to an interface. * * @param intf interface * @param handler neighbour message handler + * @param appId application ID */ - void unregisterNeighbourHandler(Interface intf, NeighbourMessageHandler handler); + void unregisterNeighbourHandler(Interface intf, NeighbourMessageHandler handler, + ApplicationId appId); + + /** + * Unregisters all neighbour handlers that were registered by the given + * application. + * + * @param appId application ID + */ + void unregisterNeighbourHandlers(ApplicationId appId); + + /** + * Gets the neighbour message handlers that have been registered with the + * service. + * + * @return neighbour message handlers indexed by connect point + */ + Map> getHandlerRegistrations(); } diff --git a/incubator/net/src/main/java/org/onosproject/incubator/net/neighbour/impl/DefaultNeighbourMessageContext.java b/incubator/net/src/main/java/org/onosproject/incubator/net/neighbour/impl/DefaultNeighbourMessageContext.java index e056f79449..44e97f9cad 100644 --- a/incubator/net/src/main/java/org/onosproject/incubator/net/neighbour/impl/DefaultNeighbourMessageContext.java +++ b/incubator/net/src/main/java/org/onosproject/incubator/net/neighbour/impl/DefaultNeighbourMessageContext.java @@ -105,7 +105,12 @@ public class DefaultNeighbourMessageContext implements NeighbourMessageContext { @Override public MacAddress srcMac() { - return MacAddress.valueOf(eth.getSourceMACAddress()); + return eth.getSourceMAC(); + } + + @Override + public MacAddress dstMac() { + return eth.getDestinationMAC(); } @Override diff --git a/incubator/net/src/main/java/org/onosproject/incubator/net/neighbour/impl/NeighbourPacketManager.java b/incubator/net/src/main/java/org/onosproject/incubator/net/neighbour/impl/NeighbourPacketManager.java index 2292ecbb2e..e0e9c98b36 100644 --- a/incubator/net/src/main/java/org/onosproject/incubator/net/neighbour/impl/NeighbourPacketManager.java +++ b/incubator/net/src/main/java/org/onosproject/incubator/net/neighbour/impl/NeighbourPacketManager.java @@ -16,9 +16,10 @@ package org.onosproject.incubator.net.neighbour.impl; -import com.google.common.collect.LinkedListMultimap; -import com.google.common.collect.ListMultimap; +import com.google.common.collect.HashMultimap; +import com.google.common.collect.ImmutableMap; import com.google.common.collect.Multimaps; +import com.google.common.collect.SetMultimap; import org.apache.felix.scr.annotations.Activate; import org.apache.felix.scr.annotations.Component; import org.apache.felix.scr.annotations.Deactivate; @@ -33,6 +34,7 @@ import org.onlab.packet.ICMP6; import org.onlab.packet.IPv6; import org.onlab.packet.Ip4Address; import org.onlab.packet.Ip6Address; +import org.onlab.packet.IpAddress; import org.onlab.packet.MacAddress; import org.onlab.packet.VlanId; import org.onlab.packet.ndp.NeighborAdvertisement; @@ -42,6 +44,7 @@ import org.onosproject.cfg.ComponentConfigService; import org.onosproject.core.ApplicationId; import org.onosproject.core.CoreService; import org.onosproject.incubator.net.intf.Interface; +import org.onosproject.incubator.net.neighbour.NeighbourHandlerRegistration; import org.onosproject.incubator.net.neighbour.NeighbourMessageActions; import org.onosproject.incubator.net.neighbour.NeighbourMessageContext; import org.onosproject.incubator.net.neighbour.NeighbourMessageHandler; @@ -63,8 +66,10 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.nio.ByteBuffer; +import java.util.Collection; import java.util.Dictionary; -import java.util.List; +import java.util.Iterator; +import java.util.Map; import java.util.Objects; import static com.google.common.base.Preconditions.checkNotNull; @@ -79,7 +84,7 @@ import static org.onosproject.net.packet.PacketPriority.CONTROL; * Manages handlers for neighbour messages. */ @Service -@Component(immediate = true, enabled = false) +@Component(immediate = true) public class NeighbourPacketManager implements NeighbourResolutionService { private final Logger log = LoggerFactory.getLogger(getClass()); @@ -106,8 +111,8 @@ public class NeighbourPacketManager implements NeighbourResolutionService { private static final String APP_NAME = "org.onosproject.neighbour"; private ApplicationId appId; - private ListMultimap packetHandlers = - Multimaps.synchronizedListMultimap(LinkedListMultimap.create()); + private SetMultimap packetHandlers = + Multimaps.synchronizedSetMultimap(HashMultimap.create()); private final InternalPacketProcessor processor = new InternalPacketProcessor(); private final InternalNeighbourMessageActions actions = new InternalNeighbourMessageActions(); @@ -191,23 +196,52 @@ public class NeighbourPacketManager implements NeighbourResolutionService { } @Override - public void registerNeighbourHandler(ConnectPoint connectPoint, NeighbourMessageHandler handler) { - packetHandlers.put(connectPoint, new HandlerRegistration(handler)); + public void registerNeighbourHandler(ConnectPoint connectPoint, + NeighbourMessageHandler handler, + ApplicationId appId) { + packetHandlers.put(connectPoint, new HandlerRegistration(handler, appId)); } @Override - public void registerNeighbourHandler(Interface intf, NeighbourMessageHandler handler) { - packetHandlers.put(intf.connectPoint(), new HandlerRegistration(handler, intf)); + public void registerNeighbourHandler(Interface intf, + NeighbourMessageHandler handler, + ApplicationId appId) { + packetHandlers.put(intf.connectPoint(), + new HandlerRegistration(handler, intf, appId)); } @Override - public void unregisterNeighbourHandler(ConnectPoint connectPoint, NeighbourMessageHandler handler) { - packetHandlers.remove(connectPoint, handler); + public void unregisterNeighbourHandler(ConnectPoint connectPoint, + NeighbourMessageHandler handler, + ApplicationId appId) { + packetHandlers.remove(connectPoint, new HandlerRegistration(handler, appId)); } @Override - public void unregisterNeighbourHandler(Interface intf, NeighbourMessageHandler handler) { - packetHandlers.remove(intf.connectPoint(), handler); + public void unregisterNeighbourHandler(Interface intf, + NeighbourMessageHandler handler, + ApplicationId appId) { + packetHandlers.remove(intf.connectPoint(), + new HandlerRegistration(handler, intf, appId)); + } + + @Override + public void unregisterNeighbourHandlers(ApplicationId appId) { + synchronized (packetHandlers) { + Iterator it = packetHandlers.values().iterator(); + + while (it.hasNext()) { + NeighbourHandlerRegistration registration = it.next(); + if (registration.appId().equals(appId)) { + it.remove(); + } + } + } + } + + @Override + public Map> getHandlerRegistrations() { + return ImmutableMap.copyOf(Multimaps.asMap(packetHandlers)); } public void handlePacket(PacketContext context) { @@ -227,7 +261,7 @@ public class NeighbourPacketManager implements NeighbourResolutionService { } private void handleMessage(NeighbourMessageContext context) { - List handlers = packetHandlers.get(context.inPort()); + Collection handlers = packetHandlers.get(context.inPort()); handlers.forEach(registration -> { if (registration.intf() == null || matches(context, registration.intf())) { @@ -236,18 +270,53 @@ public class NeighbourPacketManager implements NeighbourResolutionService { }); } + /** + * Checks that incoming packet matches the parameters of the interface. + * This means that if the interface specifies a particular parameter + * (VLAN, IP address, etc.) then the incoming packet should match those + * parameters. + * + * @param context incoming message context + * @param intf interface to check + * @return true if the incoming message matches the interface, otherwise false + */ private boolean matches(NeighbourMessageContext context, Interface intf) { checkNotNull(context); checkNotNull(intf); boolean matches = true; + // For non-broadcast packets, if the interface has a MAC address check that + // the destination MAC address of the packet matches the interface MAC + if (!context.dstMac().isBroadcast() && + !intf.mac().equals(MacAddress.NONE) && + !intf.mac().equals(context.dstMac())) { + matches = false; + } + // If the interface has a VLAN, check that the packet's VLAN matches if (!intf.vlan().equals(VlanId.NONE) && !intf.vlan().equals(context.vlan())) { matches = false; } + // If the interface has IP addresses, check that the packet's target IP + // address matches one of the interface IP addresses + if (!intf.ipAddressesList().isEmpty() && !hasIp(intf, context.target())) { + matches = false; + } return matches; } + /** + * Returns true if the interface has the given IP address. + * + * @param intf interface to check + * @param ip IP address + * @return true if the IP is configured on the interface, otherwise false + */ + private boolean hasIp(Interface intf, IpAddress ip) { + return intf.ipAddressesList().stream() + .anyMatch(intfAddress -> intfAddress.ipAddress().equals(ip)); + } + private void reply(NeighbourMessageContext context, MacAddress targetMac) { switch (context.protocol()) { @@ -295,7 +364,7 @@ public class NeighbourPacketManager implements NeighbourResolutionService { } /** - * Builds an Neighbor Discovery reply based on a request. + * Builds an NDP reply based on a request. * * @param srcIp the IP address to use as the reply source * @param srcMac the MAC address to use as the reply source @@ -336,17 +405,18 @@ public class NeighbourPacketManager implements NeighbourResolutionService { /** * Stores a neighbour message handler registration. */ - private class HandlerRegistration { + private class HandlerRegistration implements NeighbourHandlerRegistration { private final Interface intf; private final NeighbourMessageHandler handler; + private final ApplicationId appId; /** * Creates a new handler registration. * * @param handler neighbour message handler */ - public HandlerRegistration(NeighbourMessageHandler handler) { - this(handler, null); + public HandlerRegistration(NeighbourMessageHandler handler, ApplicationId appId) { + this(handler, null, appId); } /** @@ -355,29 +425,27 @@ public class NeighbourPacketManager implements NeighbourResolutionService { * @param handler neighbour message handler * @param intf interface */ - public HandlerRegistration(NeighbourMessageHandler handler, Interface intf) { + public HandlerRegistration(NeighbourMessageHandler handler, Interface intf, ApplicationId appId) { this.intf = intf; this.handler = handler; + this.appId = appId; } - /** - * Gets the interface of the registration. - * - * @return interface - */ + @Override public Interface intf() { return intf; } - /** - * Gets the neighbour message handler. - * - * @return message handler - */ + @Override public NeighbourMessageHandler handler() { return handler; } + @Override + public ApplicationId appId() { + return appId; + } + @Override public boolean equals(Object other) { if (this == other) { @@ -391,12 +459,13 @@ public class NeighbourPacketManager implements NeighbourResolutionService { HandlerRegistration that = (HandlerRegistration) other; return Objects.equals(intf, that.intf) && - Objects.equals(handler, that.handler); + Objects.equals(handler, that.handler) && + Objects.equals(appId, that.appId); } @Override public int hashCode() { - return Objects.hash(intf, handler); + return Objects.hash(intf, handler, appId); } } @@ -450,7 +519,7 @@ public class NeighbourPacketManager implements NeighbourResolutionService { @Override public void proxy(NeighbourMessageContext context, Interface outIntf) { - + // TODO implement } @Override