Jonathan Hart
Committed by Gerrit Code Review

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
1 COMPILE_DEPS = [ 1 COMPILE_DEPS = [
2 '//lib:CORE_DEPS', 2 '//lib:CORE_DEPS',
3 + '//incubator/api:onos-incubator-api',
3 ] 4 ]
4 5
5 osgi_jar ( 6 osgi_jar (
......
...@@ -43,6 +43,10 @@ ...@@ -43,6 +43,10 @@
43 <groupId>org.osgi</groupId> 43 <groupId>org.osgi</groupId>
44 <artifactId>org.osgi.compendium</artifactId> 44 <artifactId>org.osgi.compendium</artifactId>
45 </dependency> 45 </dependency>
46 + <dependency>
47 + <groupId>org.onosproject</groupId>
48 + <artifactId>onos-incubator-api</artifactId>
49 + </dependency>
46 </dependencies> 50 </dependencies>
47 51
48 </project> 52 </project>
......
1 +/*
2 + * Copyright 2016-present Open Networking Laboratory
3 + *
4 + * Licensed under the Apache License, Version 2.0 (the "License");
5 + * you may not use this file except in compliance with the License.
6 + * You may obtain a copy of the License at
7 + *
8 + * http://www.apache.org/licenses/LICENSE-2.0
9 + *
10 + * Unless required by applicable law or agreed to in writing, software
11 + * distributed under the License is distributed on an "AS IS" BASIS,
12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 + * See the License for the specific language governing permissions and
14 + * limitations under the License.
15 + */
16 +
17 +package org.onosproject.proxyarp;
18 +
19 +import org.apache.felix.scr.annotations.Activate;
20 +import org.apache.felix.scr.annotations.Component;
21 +import org.apache.felix.scr.annotations.Deactivate;
22 +import org.apache.felix.scr.annotations.Reference;
23 +import org.apache.felix.scr.annotations.ReferenceCardinality;
24 +import org.onosproject.core.ApplicationId;
25 +import org.onosproject.core.CoreService;
26 +import org.onosproject.incubator.net.neighbour.DefaultNeighbourMessageHandler;
27 +import org.onosproject.incubator.net.neighbour.NeighbourResolutionService;
28 +import org.onosproject.net.ConnectPoint;
29 +import org.onosproject.net.edge.EdgePortEvent;
30 +import org.onosproject.net.edge.EdgePortListener;
31 +import org.onosproject.net.edge.EdgePortService;
32 +
33 +/**
34 + * Implements proxy ARP and NDP functionality by considering the entire network
35 + * as a single L2 broadcast domain.
36 + * <p>
37 + * This application maintains a DefaultNeighbourMessageHandler on all edge ports
38 + * in the network, and the handler implements the desired proxying functionality.
39 + * </p>
40 + */
41 +@Component(immediate = true)
42 +public class DefaultProxyArp {
43 +
44 + private static final String APP_NAME = "org.onosproject.proxyarp";
45 +
46 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
47 + protected EdgePortService edgeService;
48 +
49 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
50 + protected NeighbourResolutionService neighbourResolutionService;
51 +
52 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
53 + protected CoreService coreService;
54 +
55 + private ApplicationId appId;
56 +
57 + private InternalEdgeListener edgeListener = new InternalEdgeListener();
58 + private DefaultNeighbourMessageHandler defaultHandler = new DefaultNeighbourMessageHandler();
59 +
60 + @Activate
61 + protected void activate() {
62 + appId = coreService.registerApplication(APP_NAME);
63 +
64 + edgeService.addListener(edgeListener);
65 + edgeService.getEdgePoints().forEach(this::addDefault);
66 + }
67 +
68 + @Deactivate
69 + protected void deactivate() {
70 + edgeService.removeListener(edgeListener);
71 + neighbourResolutionService.unregisterNeighbourHandlers(appId);
72 + }
73 +
74 + private void addDefault(ConnectPoint port) {
75 + neighbourResolutionService.registerNeighbourHandler(port, defaultHandler, appId);
76 + }
77 +
78 + private void removeDefault(ConnectPoint port) {
79 + neighbourResolutionService.unregisterNeighbourHandler(port, defaultHandler, appId);
80 + }
81 +
82 + private class InternalEdgeListener implements EdgePortListener {
83 + @Override
84 + public void event(EdgePortEvent event) {
85 + switch (event.type()) {
86 + case EDGE_PORT_ADDED:
87 + addDefault(event.subject());
88 + break;
89 + case EDGE_PORT_REMOVED:
90 + removeDefault(event.subject());
91 + break;
92 + default:
93 + break;
94 + }
95 + }
96 + }
97 +}
...@@ -51,8 +51,11 @@ import static org.slf4j.LoggerFactory.getLogger; ...@@ -51,8 +51,11 @@ import static org.slf4j.LoggerFactory.getLogger;
51 51
52 /** 52 /**
53 * Sample reactive proxy arp application. 53 * Sample reactive proxy arp application.
54 + *
55 + * @deprecated in Hummingbird release
54 */ 56 */
55 -@Component(immediate = true) 57 +@Deprecated
58 +@Component(enabled = false)
56 public class ProxyArp { 59 public class ProxyArp {
57 60
58 private final Logger log = getLogger(getClass()); 61 private final Logger log = getLogger(getClass());
......
...@@ -15,6 +15,6 @@ ...@@ -15,6 +15,6 @@
15 */ 15 */
16 16
17 /** 17 /**
18 - * Proxy Arp application that handles arp resolution for you. 18 + * Application that handles ARP and NDP resolution on a single L2 broadcast domain.
19 */ 19 */
20 package org.onosproject.proxyarp; 20 package org.onosproject.proxyarp;
......
1 +/*
2 + * Copyright 2016-present Open Networking Laboratory
3 + *
4 + * Licensed under the Apache License, Version 2.0 (the "License");
5 + * you may not use this file except in compliance with the License.
6 + * You may obtain a copy of the License at
7 + *
8 + * http://www.apache.org/licenses/LICENSE-2.0
9 + *
10 + * Unless required by applicable law or agreed to in writing, software
11 + * distributed under the License is distributed on an "AS IS" BASIS,
12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 + * See the License for the specific language governing permissions and
14 + * limitations under the License.
15 + */
16 +
17 +package org.onosproject.cli.net;
18 +
19 +import org.apache.karaf.shell.commands.Command;
20 +import org.onosproject.cli.AbstractShellCommand;
21 +import org.onosproject.incubator.net.intf.Interface;
22 +import org.onosproject.incubator.net.neighbour.NeighbourResolutionService;
23 +
24 +/**
25 + * Lists neighbour message handlers.
26 + */
27 +@Command(scope = "onos", name = "neighbour-handlers",
28 + description = "Lists neighbour message handlers")
29 +public class NeighbourHandlersListCommand extends AbstractShellCommand {
30 +
31 + private static final String FORMAT = "%20s: interface=%s, class=%s";
32 +
33 + @Override
34 + protected void execute() {
35 + NeighbourResolutionService service = get(NeighbourResolutionService.class);
36 +
37 + service.getHandlerRegistrations().forEach((cp, list) -> {
38 + list.forEach(hr -> print(FORMAT, cp, intfToName(hr.intf()),
39 + hr.handler().getClass().getCanonicalName()));
40 + });
41 + }
42 +
43 + private String intfToName(Interface intf) {
44 + return (intf == null) ? "(None)" : intf.name();
45 + }
46 +}
...@@ -485,6 +485,9 @@ ...@@ -485,6 +485,9 @@
485 <command> 485 <command>
486 <action class="org.onosproject.cli.net.PacketProcessorsListCommand"/> 486 <action class="org.onosproject.cli.net.PacketProcessorsListCommand"/>
487 </command> 487 </command>
488 + <command>
489 + <action class="org.onosproject.cli.net.NeighbourHandlersListCommand"/>
490 + </command>
488 491
489 <command> 492 <command>
490 <action class="org.onosproject.cli.net.AddTestFlowsCommand"/> 493 <action class="org.onosproject.cli.net.AddTestFlowsCommand"/>
......
...@@ -22,8 +22,11 @@ import org.onosproject.net.packet.PacketContext; ...@@ -22,8 +22,11 @@ import org.onosproject.net.packet.PacketContext;
22 22
23 /** 23 /**
24 * Service for processing ARP or NDP requests on behalf of applications. 24 * Service for processing ARP or NDP requests on behalf of applications.
25 + *
26 + * @deprecated in Hummingbird release. Use NeighbourResolutionService instead.
25 */ 27 */
26 // TODO: move to the peer host package 28 // TODO: move to the peer host package
29 +@Deprecated
27 public interface ProxyArpService { 30 public interface ProxyArpService {
28 31
29 /** 32 /**
......
...@@ -22,7 +22,11 @@ import java.nio.ByteBuffer; ...@@ -22,7 +22,11 @@ import java.nio.ByteBuffer;
22 22
23 /** 23 /**
24 * State distribution mechanism for the proxy ARP service. 24 * State distribution mechanism for the proxy ARP service.
25 + *
26 + * @deprecated in Hummingbird release. This is no longer necessary as there are
27 + * other solutions for the problem this was solving.
25 */ 28 */
29 +@Deprecated
26 public interface ProxyArpStore { 30 public interface ProxyArpStore {
27 31
28 /** 32 /**
......
...@@ -63,7 +63,12 @@ import static org.onosproject.security.AppGuard.checkPermission; ...@@ -63,7 +63,12 @@ import static org.onosproject.security.AppGuard.checkPermission;
63 import static org.slf4j.LoggerFactory.getLogger; 63 import static org.slf4j.LoggerFactory.getLogger;
64 import static org.onosproject.security.AppPermission.Type.*; 64 import static org.onosproject.security.AppPermission.Type.*;
65 65
66 - 66 +/**
67 + * Implementation of the proxy ARP service.
68 + *
69 + * @deprecated in Hummingbird release
70 + */
71 +@Deprecated
67 @Component(immediate = true) 72 @Component(immediate = true)
68 @Service 73 @Service
69 public class ProxyArpManager implements ProxyArpService { 74 public class ProxyArpManager implements ProxyArpService {
......
...@@ -50,7 +50,11 @@ import static org.onlab.util.Tools.groupedThreads; ...@@ -50,7 +50,11 @@ import static org.onlab.util.Tools.groupedThreads;
50 50
51 /** 51 /**
52 * Implementation of proxy ARP distribution mechanism. 52 * Implementation of proxy ARP distribution mechanism.
53 + *
54 + * @deprecated in Hummingbird release. This is no longer necessary as there are
55 + * other solutions for the problem this was solving.
53 */ 56 */
57 +@Deprecated
54 @Component(immediate = true) 58 @Component(immediate = true)
55 @Service 59 @Service
56 public class DistributedProxyArpStore implements ProxyArpStore { 60 public class DistributedProxyArpStore implements ProxyArpStore {
......
1 +/*
2 + * Copyright 2016-present Open Networking Laboratory
3 + *
4 + * Licensed under the Apache License, Version 2.0 (the "License");
5 + * you may not use this file except in compliance with the License.
6 + * You may obtain a copy of the License at
7 + *
8 + * http://www.apache.org/licenses/LICENSE-2.0
9 + *
10 + * Unless required by applicable law or agreed to in writing, software
11 + * distributed under the License is distributed on an "AS IS" BASIS,
12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 + * See the License for the specific language governing permissions and
14 + * limitations under the License.
15 + */
16 +
17 +package org.onosproject.incubator.net.neighbour;
18 +
19 +import org.onosproject.core.ApplicationId;
20 +import org.onosproject.incubator.net.intf.Interface;
21 +
22 +/**
23 + * Information about the registration of a neighbour message handler.
24 + */
25 +public interface NeighbourHandlerRegistration {
26 +
27 + /**
28 + * Gets the interface of the registration.
29 + *
30 + * @return interface
31 + */
32 + Interface intf();
33 +
34 + /**
35 + * Gets the neighbour message handler.
36 + *
37 + * @return message handler
38 + */
39 + NeighbourMessageHandler handler();
40 +
41 + /**
42 + * Gets the ID of the application that registered the handler.
43 + *
44 + * @return application ID
45 + */
46 + ApplicationId appId();
47 +}
...@@ -76,6 +76,16 @@ public interface NeighbourMessageContext { ...@@ -76,6 +76,16 @@ public interface NeighbourMessageContext {
76 MacAddress srcMac(); 76 MacAddress srcMac();
77 77
78 /** 78 /**
79 + * Gets the destination MAC address of the message.
80 + * <p>
81 + * Only valid for reply packets, will be null for request packets.
82 + * </p>
83 + *
84 + * @return target MAC address
85 + */
86 + MacAddress dstMac();
87 +
88 + /**
79 * Gets the target IP address of the message. 89 * Gets the target IP address of the message.
80 * 90 *
81 * @return target IP address 91 * @return target IP address
......
...@@ -17,9 +17,13 @@ ...@@ -17,9 +17,13 @@
17 package org.onosproject.incubator.net.neighbour; 17 package org.onosproject.incubator.net.neighbour;
18 18
19 import com.google.common.annotations.Beta; 19 import com.google.common.annotations.Beta;
20 +import org.onosproject.core.ApplicationId;
20 import org.onosproject.incubator.net.intf.Interface; 21 import org.onosproject.incubator.net.intf.Interface;
21 import org.onosproject.net.ConnectPoint; 22 import org.onosproject.net.ConnectPoint;
22 23
24 +import java.util.Collection;
25 +import java.util.Map;
26 +
23 /** 27 /**
24 * Provides a means of registering logic for handling neighbour messages. 28 * Provides a means of registering logic for handling neighbour messages.
25 */ 29 */
...@@ -32,8 +36,10 @@ public interface NeighbourResolutionService { ...@@ -32,8 +36,10 @@ public interface NeighbourResolutionService {
32 * 36 *
33 * @param connectPoint connect point 37 * @param connectPoint connect point
34 * @param handler neighbour message handler 38 * @param handler neighbour message handler
39 + * @param appId application ID
35 */ 40 */
36 - void registerNeighbourHandler(ConnectPoint connectPoint, NeighbourMessageHandler handler); 41 + void registerNeighbourHandler(ConnectPoint connectPoint, NeighbourMessageHandler handler,
42 + ApplicationId appId);
37 43
38 /** 44 /**
39 * Registers a neighbour message handler for all neighbour messages incoming 45 * Registers a neighbour message handler for all neighbour messages incoming
...@@ -42,8 +48,10 @@ public interface NeighbourResolutionService { ...@@ -42,8 +48,10 @@ public interface NeighbourResolutionService {
42 * 48 *
43 * @param intf interface 49 * @param intf interface
44 * @param handler neighbour message handler 50 * @param handler neighbour message handler
51 + * @param appId application ID
45 */ 52 */
46 - void registerNeighbourHandler(Interface intf, NeighbourMessageHandler handler); 53 + void registerNeighbourHandler(Interface intf, NeighbourMessageHandler handler,
54 + ApplicationId appId);
47 55
48 /** 56 /**
49 * Unregisters a neighbour message handler that was assigned to a connect 57 * Unregisters a neighbour message handler that was assigned to a connect
...@@ -51,14 +59,34 @@ public interface NeighbourResolutionService { ...@@ -51,14 +59,34 @@ public interface NeighbourResolutionService {
51 * 59 *
52 * @param connectPoint connect point 60 * @param connectPoint connect point
53 * @param handler neighbour message handler 61 * @param handler neighbour message handler
62 + * @param appId application ID
54 */ 63 */
55 - void unregisterNeighbourHandler(ConnectPoint connectPoint, NeighbourMessageHandler handler); 64 + void unregisterNeighbourHandler(ConnectPoint connectPoint, NeighbourMessageHandler handler,
65 + ApplicationId appId);
56 66
57 /** 67 /**
58 * Unregisters a neighbour message handler that was assigned to an interface. 68 * Unregisters a neighbour message handler that was assigned to an interface.
59 * 69 *
60 * @param intf interface 70 * @param intf interface
61 * @param handler neighbour message handler 71 * @param handler neighbour message handler
72 + * @param appId application ID
73 + */
74 + void unregisterNeighbourHandler(Interface intf, NeighbourMessageHandler handler,
75 + ApplicationId appId);
76 +
77 + /**
78 + * Unregisters all neighbour handlers that were registered by the given
79 + * application.
80 + *
81 + * @param appId application ID
82 + */
83 + void unregisterNeighbourHandlers(ApplicationId appId);
84 +
85 + /**
86 + * Gets the neighbour message handlers that have been registered with the
87 + * service.
88 + *
89 + * @return neighbour message handlers indexed by connect point
62 */ 90 */
63 - void unregisterNeighbourHandler(Interface intf, NeighbourMessageHandler handler); 91 + Map<ConnectPoint, Collection<NeighbourHandlerRegistration>> getHandlerRegistrations();
64 } 92 }
......
...@@ -105,7 +105,12 @@ public class DefaultNeighbourMessageContext implements NeighbourMessageContext { ...@@ -105,7 +105,12 @@ public class DefaultNeighbourMessageContext implements NeighbourMessageContext {
105 105
106 @Override 106 @Override
107 public MacAddress srcMac() { 107 public MacAddress srcMac() {
108 - return MacAddress.valueOf(eth.getSourceMACAddress()); 108 + return eth.getSourceMAC();
109 + }
110 +
111 + @Override
112 + public MacAddress dstMac() {
113 + return eth.getDestinationMAC();
109 } 114 }
110 115
111 @Override 116 @Override
......
...@@ -16,9 +16,10 @@ ...@@ -16,9 +16,10 @@
16 16
17 package org.onosproject.incubator.net.neighbour.impl; 17 package org.onosproject.incubator.net.neighbour.impl;
18 18
19 -import com.google.common.collect.LinkedListMultimap; 19 +import com.google.common.collect.HashMultimap;
20 -import com.google.common.collect.ListMultimap; 20 +import com.google.common.collect.ImmutableMap;
21 import com.google.common.collect.Multimaps; 21 import com.google.common.collect.Multimaps;
22 +import com.google.common.collect.SetMultimap;
22 import org.apache.felix.scr.annotations.Activate; 23 import org.apache.felix.scr.annotations.Activate;
23 import org.apache.felix.scr.annotations.Component; 24 import org.apache.felix.scr.annotations.Component;
24 import org.apache.felix.scr.annotations.Deactivate; 25 import org.apache.felix.scr.annotations.Deactivate;
...@@ -33,6 +34,7 @@ import org.onlab.packet.ICMP6; ...@@ -33,6 +34,7 @@ import org.onlab.packet.ICMP6;
33 import org.onlab.packet.IPv6; 34 import org.onlab.packet.IPv6;
34 import org.onlab.packet.Ip4Address; 35 import org.onlab.packet.Ip4Address;
35 import org.onlab.packet.Ip6Address; 36 import org.onlab.packet.Ip6Address;
37 +import org.onlab.packet.IpAddress;
36 import org.onlab.packet.MacAddress; 38 import org.onlab.packet.MacAddress;
37 import org.onlab.packet.VlanId; 39 import org.onlab.packet.VlanId;
38 import org.onlab.packet.ndp.NeighborAdvertisement; 40 import org.onlab.packet.ndp.NeighborAdvertisement;
...@@ -42,6 +44,7 @@ import org.onosproject.cfg.ComponentConfigService; ...@@ -42,6 +44,7 @@ import org.onosproject.cfg.ComponentConfigService;
42 import org.onosproject.core.ApplicationId; 44 import org.onosproject.core.ApplicationId;
43 import org.onosproject.core.CoreService; 45 import org.onosproject.core.CoreService;
44 import org.onosproject.incubator.net.intf.Interface; 46 import org.onosproject.incubator.net.intf.Interface;
47 +import org.onosproject.incubator.net.neighbour.NeighbourHandlerRegistration;
45 import org.onosproject.incubator.net.neighbour.NeighbourMessageActions; 48 import org.onosproject.incubator.net.neighbour.NeighbourMessageActions;
46 import org.onosproject.incubator.net.neighbour.NeighbourMessageContext; 49 import org.onosproject.incubator.net.neighbour.NeighbourMessageContext;
47 import org.onosproject.incubator.net.neighbour.NeighbourMessageHandler; 50 import org.onosproject.incubator.net.neighbour.NeighbourMessageHandler;
...@@ -63,8 +66,10 @@ import org.slf4j.Logger; ...@@ -63,8 +66,10 @@ import org.slf4j.Logger;
63 import org.slf4j.LoggerFactory; 66 import org.slf4j.LoggerFactory;
64 67
65 import java.nio.ByteBuffer; 68 import java.nio.ByteBuffer;
69 +import java.util.Collection;
66 import java.util.Dictionary; 70 import java.util.Dictionary;
67 -import java.util.List; 71 +import java.util.Iterator;
72 +import java.util.Map;
68 import java.util.Objects; 73 import java.util.Objects;
69 74
70 import static com.google.common.base.Preconditions.checkNotNull; 75 import static com.google.common.base.Preconditions.checkNotNull;
...@@ -79,7 +84,7 @@ import static org.onosproject.net.packet.PacketPriority.CONTROL; ...@@ -79,7 +84,7 @@ import static org.onosproject.net.packet.PacketPriority.CONTROL;
79 * Manages handlers for neighbour messages. 84 * Manages handlers for neighbour messages.
80 */ 85 */
81 @Service 86 @Service
82 -@Component(immediate = true, enabled = false) 87 +@Component(immediate = true)
83 public class NeighbourPacketManager implements NeighbourResolutionService { 88 public class NeighbourPacketManager implements NeighbourResolutionService {
84 89
85 private final Logger log = LoggerFactory.getLogger(getClass()); 90 private final Logger log = LoggerFactory.getLogger(getClass());
...@@ -106,8 +111,8 @@ public class NeighbourPacketManager implements NeighbourResolutionService { ...@@ -106,8 +111,8 @@ public class NeighbourPacketManager implements NeighbourResolutionService {
106 private static final String APP_NAME = "org.onosproject.neighbour"; 111 private static final String APP_NAME = "org.onosproject.neighbour";
107 private ApplicationId appId; 112 private ApplicationId appId;
108 113
109 - private ListMultimap<ConnectPoint, HandlerRegistration> packetHandlers = 114 + private SetMultimap<ConnectPoint, NeighbourHandlerRegistration> packetHandlers =
110 - Multimaps.synchronizedListMultimap(LinkedListMultimap.create()); 115 + Multimaps.synchronizedSetMultimap(HashMultimap.create());
111 116
112 private final InternalPacketProcessor processor = new InternalPacketProcessor(); 117 private final InternalPacketProcessor processor = new InternalPacketProcessor();
113 private final InternalNeighbourMessageActions actions = new InternalNeighbourMessageActions(); 118 private final InternalNeighbourMessageActions actions = new InternalNeighbourMessageActions();
...@@ -191,23 +196,52 @@ public class NeighbourPacketManager implements NeighbourResolutionService { ...@@ -191,23 +196,52 @@ public class NeighbourPacketManager implements NeighbourResolutionService {
191 } 196 }
192 197
193 @Override 198 @Override
194 - public void registerNeighbourHandler(ConnectPoint connectPoint, NeighbourMessageHandler handler) { 199 + public void registerNeighbourHandler(ConnectPoint connectPoint,
195 - packetHandlers.put(connectPoint, new HandlerRegistration(handler)); 200 + NeighbourMessageHandler handler,
201 + ApplicationId appId) {
202 + packetHandlers.put(connectPoint, new HandlerRegistration(handler, appId));
196 } 203 }
197 204
198 @Override 205 @Override
199 - public void registerNeighbourHandler(Interface intf, NeighbourMessageHandler handler) { 206 + public void registerNeighbourHandler(Interface intf,
200 - packetHandlers.put(intf.connectPoint(), new HandlerRegistration(handler, intf)); 207 + NeighbourMessageHandler handler,
208 + ApplicationId appId) {
209 + packetHandlers.put(intf.connectPoint(),
210 + new HandlerRegistration(handler, intf, appId));
201 } 211 }
202 212
203 @Override 213 @Override
204 - public void unregisterNeighbourHandler(ConnectPoint connectPoint, NeighbourMessageHandler handler) { 214 + public void unregisterNeighbourHandler(ConnectPoint connectPoint,
205 - packetHandlers.remove(connectPoint, handler); 215 + NeighbourMessageHandler handler,
216 + ApplicationId appId) {
217 + packetHandlers.remove(connectPoint, new HandlerRegistration(handler, appId));
206 } 218 }
207 219
208 @Override 220 @Override
209 - public void unregisterNeighbourHandler(Interface intf, NeighbourMessageHandler handler) { 221 + public void unregisterNeighbourHandler(Interface intf,
210 - packetHandlers.remove(intf.connectPoint(), handler); 222 + NeighbourMessageHandler handler,
223 + ApplicationId appId) {
224 + packetHandlers.remove(intf.connectPoint(),
225 + new HandlerRegistration(handler, intf, appId));
226 + }
227 +
228 + @Override
229 + public void unregisterNeighbourHandlers(ApplicationId appId) {
230 + synchronized (packetHandlers) {
231 + Iterator<NeighbourHandlerRegistration> it = packetHandlers.values().iterator();
232 +
233 + while (it.hasNext()) {
234 + NeighbourHandlerRegistration registration = it.next();
235 + if (registration.appId().equals(appId)) {
236 + it.remove();
237 + }
238 + }
239 + }
240 + }
241 +
242 + @Override
243 + public Map<ConnectPoint, Collection<NeighbourHandlerRegistration>> getHandlerRegistrations() {
244 + return ImmutableMap.copyOf(Multimaps.asMap(packetHandlers));
211 } 245 }
212 246
213 public void handlePacket(PacketContext context) { 247 public void handlePacket(PacketContext context) {
...@@ -227,7 +261,7 @@ public class NeighbourPacketManager implements NeighbourResolutionService { ...@@ -227,7 +261,7 @@ public class NeighbourPacketManager implements NeighbourResolutionService {
227 } 261 }
228 262
229 private void handleMessage(NeighbourMessageContext context) { 263 private void handleMessage(NeighbourMessageContext context) {
230 - List<HandlerRegistration> handlers = packetHandlers.get(context.inPort()); 264 + Collection<NeighbourHandlerRegistration> handlers = packetHandlers.get(context.inPort());
231 265
232 handlers.forEach(registration -> { 266 handlers.forEach(registration -> {
233 if (registration.intf() == null || matches(context, registration.intf())) { 267 if (registration.intf() == null || matches(context, registration.intf())) {
...@@ -236,18 +270,53 @@ public class NeighbourPacketManager implements NeighbourResolutionService { ...@@ -236,18 +270,53 @@ public class NeighbourPacketManager implements NeighbourResolutionService {
236 }); 270 });
237 } 271 }
238 272
273 + /**
274 + * Checks that incoming packet matches the parameters of the interface.
275 + * This means that if the interface specifies a particular parameter
276 + * (VLAN, IP address, etc.) then the incoming packet should match those
277 + * parameters.
278 + *
279 + * @param context incoming message context
280 + * @param intf interface to check
281 + * @return true if the incoming message matches the interface, otherwise false
282 + */
239 private boolean matches(NeighbourMessageContext context, Interface intf) { 283 private boolean matches(NeighbourMessageContext context, Interface intf) {
240 checkNotNull(context); 284 checkNotNull(context);
241 checkNotNull(intf); 285 checkNotNull(intf);
242 286
243 boolean matches = true; 287 boolean matches = true;
288 + // For non-broadcast packets, if the interface has a MAC address check that
289 + // the destination MAC address of the packet matches the interface MAC
290 + if (!context.dstMac().isBroadcast() &&
291 + !intf.mac().equals(MacAddress.NONE) &&
292 + !intf.mac().equals(context.dstMac())) {
293 + matches = false;
294 + }
295 + // If the interface has a VLAN, check that the packet's VLAN matches
244 if (!intf.vlan().equals(VlanId.NONE) && !intf.vlan().equals(context.vlan())) { 296 if (!intf.vlan().equals(VlanId.NONE) && !intf.vlan().equals(context.vlan())) {
245 matches = false; 297 matches = false;
246 } 298 }
299 + // If the interface has IP addresses, check that the packet's target IP
300 + // address matches one of the interface IP addresses
301 + if (!intf.ipAddressesList().isEmpty() && !hasIp(intf, context.target())) {
302 + matches = false;
303 + }
247 304
248 return matches; 305 return matches;
249 } 306 }
250 307
308 + /**
309 + * Returns true if the interface has the given IP address.
310 + *
311 + * @param intf interface to check
312 + * @param ip IP address
313 + * @return true if the IP is configured on the interface, otherwise false
314 + */
315 + private boolean hasIp(Interface intf, IpAddress ip) {
316 + return intf.ipAddressesList().stream()
317 + .anyMatch(intfAddress -> intfAddress.ipAddress().equals(ip));
318 + }
319 +
251 320
252 private void reply(NeighbourMessageContext context, MacAddress targetMac) { 321 private void reply(NeighbourMessageContext context, MacAddress targetMac) {
253 switch (context.protocol()) { 322 switch (context.protocol()) {
...@@ -295,7 +364,7 @@ public class NeighbourPacketManager implements NeighbourResolutionService { ...@@ -295,7 +364,7 @@ public class NeighbourPacketManager implements NeighbourResolutionService {
295 } 364 }
296 365
297 /** 366 /**
298 - * Builds an Neighbor Discovery reply based on a request. 367 + * Builds an NDP reply based on a request.
299 * 368 *
300 * @param srcIp the IP address to use as the reply source 369 * @param srcIp the IP address to use as the reply source
301 * @param srcMac the MAC address to use as the reply source 370 * @param srcMac the MAC address to use as the reply source
...@@ -336,17 +405,18 @@ public class NeighbourPacketManager implements NeighbourResolutionService { ...@@ -336,17 +405,18 @@ public class NeighbourPacketManager implements NeighbourResolutionService {
336 /** 405 /**
337 * Stores a neighbour message handler registration. 406 * Stores a neighbour message handler registration.
338 */ 407 */
339 - private class HandlerRegistration { 408 + private class HandlerRegistration implements NeighbourHandlerRegistration {
340 private final Interface intf; 409 private final Interface intf;
341 private final NeighbourMessageHandler handler; 410 private final NeighbourMessageHandler handler;
411 + private final ApplicationId appId;
342 412
343 /** 413 /**
344 * Creates a new handler registration. 414 * Creates a new handler registration.
345 * 415 *
346 * @param handler neighbour message handler 416 * @param handler neighbour message handler
347 */ 417 */
348 - public HandlerRegistration(NeighbourMessageHandler handler) { 418 + public HandlerRegistration(NeighbourMessageHandler handler, ApplicationId appId) {
349 - this(handler, null); 419 + this(handler, null, appId);
350 } 420 }
351 421
352 /** 422 /**
...@@ -355,30 +425,28 @@ public class NeighbourPacketManager implements NeighbourResolutionService { ...@@ -355,30 +425,28 @@ public class NeighbourPacketManager implements NeighbourResolutionService {
355 * @param handler neighbour message handler 425 * @param handler neighbour message handler
356 * @param intf interface 426 * @param intf interface
357 */ 427 */
358 - public HandlerRegistration(NeighbourMessageHandler handler, Interface intf) { 428 + public HandlerRegistration(NeighbourMessageHandler handler, Interface intf, ApplicationId appId) {
359 this.intf = intf; 429 this.intf = intf;
360 this.handler = handler; 430 this.handler = handler;
431 + this.appId = appId;
361 } 432 }
362 433
363 - /** 434 + @Override
364 - * Gets the interface of the registration.
365 - *
366 - * @return interface
367 - */
368 public Interface intf() { 435 public Interface intf() {
369 return intf; 436 return intf;
370 } 437 }
371 438
372 - /** 439 + @Override
373 - * Gets the neighbour message handler.
374 - *
375 - * @return message handler
376 - */
377 public NeighbourMessageHandler handler() { 440 public NeighbourMessageHandler handler() {
378 return handler; 441 return handler;
379 } 442 }
380 443
381 @Override 444 @Override
445 + public ApplicationId appId() {
446 + return appId;
447 + }
448 +
449 + @Override
382 public boolean equals(Object other) { 450 public boolean equals(Object other) {
383 if (this == other) { 451 if (this == other) {
384 return true; 452 return true;
...@@ -391,12 +459,13 @@ public class NeighbourPacketManager implements NeighbourResolutionService { ...@@ -391,12 +459,13 @@ public class NeighbourPacketManager implements NeighbourResolutionService {
391 HandlerRegistration that = (HandlerRegistration) other; 459 HandlerRegistration that = (HandlerRegistration) other;
392 460
393 return Objects.equals(intf, that.intf) && 461 return Objects.equals(intf, that.intf) &&
394 - Objects.equals(handler, that.handler); 462 + Objects.equals(handler, that.handler) &&
463 + Objects.equals(appId, that.appId);
395 } 464 }
396 465
397 @Override 466 @Override
398 public int hashCode() { 467 public int hashCode() {
399 - return Objects.hash(intf, handler); 468 + return Objects.hash(intf, handler, appId);
400 } 469 }
401 } 470 }
402 471
...@@ -450,7 +519,7 @@ public class NeighbourPacketManager implements NeighbourResolutionService { ...@@ -450,7 +519,7 @@ public class NeighbourPacketManager implements NeighbourResolutionService {
450 519
451 @Override 520 @Override
452 public void proxy(NeighbourMessageContext context, Interface outIntf) { 521 public void proxy(NeighbourMessageContext context, Interface outIntf) {
453 - 522 + // TODO implement
454 } 523 }
455 524
456 @Override 525 @Override
......