blob: 116b0637326f51fc041c1e542ac119fc4151fede [file] [log] [blame]
Jonathan Hart9bdaaec2016-08-22 13:33:45 -07001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2016-present Open Networking Foundation
Jonathan Hart9bdaaec2016-08-22 13:33:45 -07003 *
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
Ray Milkeyb65d7842017-08-03 16:28:24 -070017package org.onosproject.net.neighbour.impl;
Jonathan Hart9bdaaec2016-08-22 13:33:45 -070018
Jonathan Hartc4f681c2016-09-09 07:14:25 -070019import com.google.common.collect.HashMultimap;
20import com.google.common.collect.ImmutableMap;
Jonathan Hart9bdaaec2016-08-22 13:33:45 -070021import com.google.common.collect.Multimaps;
Jonathan Hartc4f681c2016-09-09 07:14:25 -070022import com.google.common.collect.SetMultimap;
Jonathan Hart9bdaaec2016-08-22 13:33:45 -070023import org.onlab.packet.Ethernet;
24import org.onlab.packet.ICMP6;
25import org.onlab.packet.IPv6;
Jonathan Hartc4f681c2016-09-09 07:14:25 -070026import org.onlab.packet.IpAddress;
Jonathan Hart9bdaaec2016-08-22 13:33:45 -070027import org.onlab.packet.MacAddress;
28import org.onlab.packet.VlanId;
Jonathan Hart9bdaaec2016-08-22 13:33:45 -070029import org.onlab.util.Tools;
30import org.onosproject.cfg.ComponentConfigService;
31import org.onosproject.core.ApplicationId;
32import org.onosproject.core.CoreService;
Ray Milkeyd84f89b2018-08-17 14:54:17 -070033import org.onosproject.net.ConnectPoint;
34import org.onosproject.net.edge.EdgePortService;
35import org.onosproject.net.flow.DefaultTrafficSelector;
36import org.onosproject.net.flow.TrafficSelector;
37import org.onosproject.net.host.HostService;
Ray Milkeyfacf2862017-08-03 11:58:29 -070038import org.onosproject.net.intf.Interface;
Ray Milkeyb65d7842017-08-03 16:28:24 -070039import org.onosproject.net.neighbour.NeighbourHandlerRegistration;
40import org.onosproject.net.neighbour.NeighbourMessageActions;
41import org.onosproject.net.neighbour.NeighbourMessageContext;
42import org.onosproject.net.neighbour.NeighbourMessageHandler;
43import org.onosproject.net.neighbour.NeighbourResolutionService;
Jonathan Hart9bdaaec2016-08-22 13:33:45 -070044import org.onosproject.net.packet.InboundPacket;
45import org.onosproject.net.packet.PacketContext;
46import org.onosproject.net.packet.PacketProcessor;
47import org.onosproject.net.packet.PacketService;
48import org.osgi.service.component.ComponentContext;
Ray Milkeyd84f89b2018-08-17 14:54:17 -070049import org.osgi.service.component.annotations.Activate;
50import org.osgi.service.component.annotations.Component;
51import org.osgi.service.component.annotations.Deactivate;
52import org.osgi.service.component.annotations.Modified;
53import org.osgi.service.component.annotations.Reference;
54import org.osgi.service.component.annotations.ReferenceCardinality;
Jonathan Hart9bdaaec2016-08-22 13:33:45 -070055import org.slf4j.Logger;
56import org.slf4j.LoggerFactory;
57
Jonathan Hartc4f681c2016-09-09 07:14:25 -070058import java.util.Collection;
Jonathan Hart9bdaaec2016-08-22 13:33:45 -070059import java.util.Dictionary;
Jonathan Hartc4f681c2016-09-09 07:14:25 -070060import java.util.Iterator;
61import java.util.Map;
Jonathan Hart9bdaaec2016-08-22 13:33:45 -070062import java.util.Objects;
Pier Ventre0ba98522016-09-19 15:49:14 -070063import java.util.stream.Collectors;
Jonathan Hart9bdaaec2016-08-22 13:33:45 -070064
65import static com.google.common.base.Preconditions.checkNotNull;
66import static org.onlab.packet.Ethernet.TYPE_ARP;
67import static org.onlab.packet.Ethernet.TYPE_IPV6;
68import static org.onlab.packet.ICMP6.NEIGHBOR_ADVERTISEMENT;
69import static org.onlab.packet.ICMP6.NEIGHBOR_SOLICITATION;
70import static org.onlab.packet.IPv6.PROTOCOL_ICMP6;
Ray Milkeyd04e2272018-10-16 18:20:18 -070071import static org.onosproject.net.OsgiPropertyConstants.NRM_ARP_ENABLED;
72import static org.onosproject.net.OsgiPropertyConstants.NRM_ARP_ENABLED_DEFAULT;
73import static org.onosproject.net.OsgiPropertyConstants.NRM_NDP_ENABLED;
74import static org.onosproject.net.OsgiPropertyConstants.NRM_NDP_ENABLED_DEFAULT;
75import static org.onosproject.net.OsgiPropertyConstants.NRM_REQUEST_INTERCEPTS_ENABLED;
76import static org.onosproject.net.OsgiPropertyConstants.NRM_REQUEST_INTERCEPTS_ENABLED_DEFAULT;
Jonathan Hart9bdaaec2016-08-22 13:33:45 -070077import static org.onosproject.net.packet.PacketPriority.CONTROL;
78
79/**
80 * Manages handlers for neighbour messages.
81 */
Ray Milkeyd04e2272018-10-16 18:20:18 -070082@Component(
83 immediate = true,
84 service = NeighbourResolutionService.class,
85 property = {
Ray Milkey2d7bca12018-10-17 14:51:52 -070086 NRM_ARP_ENABLED + ":Boolean=" + NRM_ARP_ENABLED_DEFAULT,
87 NRM_NDP_ENABLED + ":Boolean=" + NRM_NDP_ENABLED,
88 NRM_REQUEST_INTERCEPTS_ENABLED + ":Boolean=" + NRM_REQUEST_INTERCEPTS_ENABLED_DEFAULT
Ray Milkeyd04e2272018-10-16 18:20:18 -070089 }
90)
Jonathan Hart1e393bb2016-09-14 08:51:09 -070091public class NeighbourResolutionManager implements NeighbourResolutionService {
Jonathan Hart9bdaaec2016-08-22 13:33:45 -070092
93 private final Logger log = LoggerFactory.getLogger(getClass());
94
Ray Milkeyd84f89b2018-08-17 14:54:17 -070095 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Jonathan Hart9bdaaec2016-08-22 13:33:45 -070096 protected CoreService coreService;
97
Ray Milkeyd84f89b2018-08-17 14:54:17 -070098 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Jonathan Hart9bdaaec2016-08-22 13:33:45 -070099 protected HostService hostService;
100
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700101 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Jonathan Hart9bdaaec2016-08-22 13:33:45 -0700102 protected EdgePortService edgeService;
103
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700104 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Jonathan Hart9bdaaec2016-08-22 13:33:45 -0700105 protected PacketService packetService;
106
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700107 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Jonathan Hart9bdaaec2016-08-22 13:33:45 -0700108 protected ComponentConfigService componentConfigService;
109
Thomas Vachuskaf566fa22018-10-30 14:03:36 -0700110 /** Enable Address resolution protocol. */
Ray Milkeyd04e2272018-10-16 18:20:18 -0700111 protected boolean arpEnabled = NRM_ARP_ENABLED_DEFAULT;
Pier Luigi65a0ab32017-01-12 20:52:38 -0800112
Thomas Vachuskaf566fa22018-10-30 14:03:36 -0700113 /** Enable IPv6 neighbour discovery. */
Ray Milkeyd04e2272018-10-16 18:20:18 -0700114 protected boolean ndpEnabled = NRM_NDP_ENABLED_DEFAULT;
Jonathan Hart9bdaaec2016-08-22 13:33:45 -0700115
Thomas Vachuskaf566fa22018-10-30 14:03:36 -0700116 /** Enable requesting packet intercepts. */
Ray Milkeyd04e2272018-10-16 18:20:18 -0700117 private boolean requestInterceptsEnabled = NRM_REQUEST_INTERCEPTS_ENABLED_DEFAULT;
Pier Luigi65a0ab32017-01-12 20:52:38 -0800118
Jonathan Hart9bdaaec2016-08-22 13:33:45 -0700119 private static final String APP_NAME = "org.onosproject.neighbour";
120 private ApplicationId appId;
121
Jonathan Hartc004adf2016-09-15 16:50:04 -0700122 private final SetMultimap<ConnectPoint, NeighbourHandlerRegistration> packetHandlers =
Jonathan Hartc4f681c2016-09-09 07:14:25 -0700123 Multimaps.synchronizedSetMultimap(HashMultimap.create());
Jonathan Hart9bdaaec2016-08-22 13:33:45 -0700124
125 private final InternalPacketProcessor processor = new InternalPacketProcessor();
Jonathan Hart584ea2d2016-10-11 10:49:16 +0200126 private NeighbourMessageActions actions;
Jonathan Hart9bdaaec2016-08-22 13:33:45 -0700127
128 @Activate
129 protected void activate(ComponentContext context) {
130 appId = coreService.registerApplication(APP_NAME);
131
132 componentConfigService.registerProperties(getClass());
133 modified(context);
134
Jonathan Hart584ea2d2016-10-11 10:49:16 +0200135 actions = new DefaultNeighbourMessageActions(packetService, edgeService);
136
Jonathan Hart9bdaaec2016-08-22 13:33:45 -0700137 packetService.addProcessor(processor, PacketProcessor.director(1));
138 }
139
140 @Deactivate
141 protected void deactivate() {
142 cancelPackets();
143 packetService.removeProcessor(processor);
144 componentConfigService.unregisterProperties(getClass(), false);
145 }
146
147 @Modified
148 protected void modified(ComponentContext context) {
149 Dictionary<?, ?> properties = context.getProperties();
150 Boolean flag;
151
Thomas Vachuskaf566fa22018-10-30 14:03:36 -0700152 flag = Tools.isPropertyEnabled(properties, NRM_NDP_ENABLED);
Jonathan Hart9bdaaec2016-08-22 13:33:45 -0700153 if (flag != null) {
154 ndpEnabled = flag;
155 log.info("IPv6 neighbor discovery is {}",
156 ndpEnabled ? "enabled" : "disabled");
157 }
158
Thomas Vachuskaf566fa22018-10-30 14:03:36 -0700159 flag = Tools.isPropertyEnabled(properties, NRM_ARP_ENABLED);
Pier Luigi65a0ab32017-01-12 20:52:38 -0800160 if (flag != null) {
161 arpEnabled = flag;
162 log.info("Address resolution protocol is {}",
163 arpEnabled ? "enabled" : "disabled");
164 }
165
Thomas Vachuskaf566fa22018-10-30 14:03:36 -0700166 flag = Tools.isPropertyEnabled(properties, NRM_REQUEST_INTERCEPTS_ENABLED);
Pier Luigi65a0ab32017-01-12 20:52:38 -0800167 if (flag == null) {
168 log.info("Request intercepts is not configured, " +
169 "using current value of {}", requestInterceptsEnabled);
170 } else {
171 requestInterceptsEnabled = flag;
172 log.info("Configured. Request intercepts is {}",
173 requestInterceptsEnabled ? "enabled" : "disabled");
174 }
175
Jonathan Hartc004adf2016-09-15 16:50:04 -0700176 synchronized (packetHandlers) {
Pier Luigi65a0ab32017-01-12 20:52:38 -0800177 if (!packetHandlers.isEmpty() && requestInterceptsEnabled) {
Jonathan Hartc004adf2016-09-15 16:50:04 -0700178 requestPackets();
Pier Luigi65a0ab32017-01-12 20:52:38 -0800179 } else {
180 cancelPackets();
Jonathan Hartc004adf2016-09-15 16:50:04 -0700181 }
182 }
Jonathan Hart9bdaaec2016-08-22 13:33:45 -0700183 }
184
185 private void requestPackets() {
Pier Luigi65a0ab32017-01-12 20:52:38 -0800186 if (arpEnabled) {
187 packetService.requestPackets(buildArpSelector(), CONTROL, appId);
188 } else {
189 packetService.cancelPackets(buildArpSelector(), CONTROL, appId);
190 }
Jonathan Hart9bdaaec2016-08-22 13:33:45 -0700191
192 if (ndpEnabled) {
193 packetService.requestPackets(buildNeighborSolicitationSelector(),
194 CONTROL, appId);
195 packetService.requestPackets(buildNeighborAdvertisementSelector(),
196 CONTROL, appId);
197 } else {
198 packetService.cancelPackets(buildNeighborSolicitationSelector(),
199 CONTROL, appId);
200 packetService.cancelPackets(buildNeighborAdvertisementSelector(),
201 CONTROL, appId);
202 }
203 }
204
205 private void cancelPackets() {
206 packetService.cancelPackets(buildArpSelector(), CONTROL, appId);
207 packetService.cancelPackets(buildNeighborSolicitationSelector(),
208 CONTROL, appId);
209 packetService.cancelPackets(buildNeighborAdvertisementSelector(),
210 CONTROL, appId);
211 }
212
213 private TrafficSelector buildArpSelector() {
214 return DefaultTrafficSelector.builder()
215 .matchEthType(TYPE_ARP)
216 .build();
217 }
218
219 private TrafficSelector buildNeighborSolicitationSelector() {
220 return DefaultTrafficSelector.builder()
221 .matchEthType(TYPE_IPV6)
222 .matchIPProtocol(PROTOCOL_ICMP6)
223 .matchIcmpv6Type(NEIGHBOR_SOLICITATION)
224 .build();
225 }
226
227 private TrafficSelector buildNeighborAdvertisementSelector() {
228 return DefaultTrafficSelector.builder()
229 .matchEthType(TYPE_IPV6)
230 .matchIPProtocol(PROTOCOL_ICMP6)
231 .matchIcmpv6Type(NEIGHBOR_ADVERTISEMENT)
232 .build();
233 }
234
235 @Override
Jonathan Hartc4f681c2016-09-09 07:14:25 -0700236 public void registerNeighbourHandler(ConnectPoint connectPoint,
237 NeighbourMessageHandler handler,
238 ApplicationId appId) {
Jonathan Hartc004adf2016-09-15 16:50:04 -0700239 register(connectPoint, new HandlerRegistration(handler, appId));
Jonathan Hart9bdaaec2016-08-22 13:33:45 -0700240 }
241
242 @Override
Jonathan Hartc4f681c2016-09-09 07:14:25 -0700243 public void registerNeighbourHandler(Interface intf,
244 NeighbourMessageHandler handler,
245 ApplicationId appId) {
Jonathan Hartc004adf2016-09-15 16:50:04 -0700246 register(intf.connectPoint(), new HandlerRegistration(handler, intf, appId));
247 }
248
249 private void register(ConnectPoint connectPoint, HandlerRegistration registration) {
250 synchronized (packetHandlers) {
Pier Ventre09f88b82017-01-09 23:01:05 -0800251 if (packetHandlers.isEmpty() && requestInterceptsEnabled) {
Jonathan Hartc004adf2016-09-15 16:50:04 -0700252 requestPackets();
253 }
254 packetHandlers.put(connectPoint, registration);
255 }
Jonathan Hart9bdaaec2016-08-22 13:33:45 -0700256 }
257
258 @Override
Jonathan Hartc4f681c2016-09-09 07:14:25 -0700259 public void unregisterNeighbourHandler(ConnectPoint connectPoint,
260 NeighbourMessageHandler handler,
261 ApplicationId appId) {
Jonathan Hartc004adf2016-09-15 16:50:04 -0700262 unregister(connectPoint, new HandlerRegistration(handler, appId));
Jonathan Hart9bdaaec2016-08-22 13:33:45 -0700263 }
264
265 @Override
Jonathan Hartc4f681c2016-09-09 07:14:25 -0700266 public void unregisterNeighbourHandler(Interface intf,
267 NeighbourMessageHandler handler,
268 ApplicationId appId) {
Jonathan Hartc004adf2016-09-15 16:50:04 -0700269 unregister(intf.connectPoint(), new HandlerRegistration(handler, intf, appId));
270 }
271
272 private void unregister(ConnectPoint connectPoint, HandlerRegistration registration) {
273 synchronized (packetHandlers) {
274 packetHandlers.remove(connectPoint, registration);
275
276 if (packetHandlers.isEmpty()) {
277 cancelPackets();
278 }
279 }
Jonathan Hartc4f681c2016-09-09 07:14:25 -0700280 }
281
282 @Override
283 public void unregisterNeighbourHandlers(ApplicationId appId) {
284 synchronized (packetHandlers) {
285 Iterator<NeighbourHandlerRegistration> it = packetHandlers.values().iterator();
286
287 while (it.hasNext()) {
288 NeighbourHandlerRegistration registration = it.next();
289 if (registration.appId().equals(appId)) {
290 it.remove();
291 }
292 }
Jonathan Hartc004adf2016-09-15 16:50:04 -0700293
294 if (packetHandlers.isEmpty()) {
295 cancelPackets();
296 }
Jonathan Hartc4f681c2016-09-09 07:14:25 -0700297 }
298 }
299
300 @Override
301 public Map<ConnectPoint, Collection<NeighbourHandlerRegistration>> getHandlerRegistrations() {
Ray Milkeyfb1c7622018-05-18 10:16:53 -0700302 synchronized (packetHandlers) {
303 return ImmutableMap.copyOf(Multimaps.asMap(packetHandlers));
304 }
Jonathan Hart9bdaaec2016-08-22 13:33:45 -0700305 }
306
Jonathan Hart584ea2d2016-10-11 10:49:16 +0200307 private void handlePacket(PacketContext context) {
Jonathan Hart9bdaaec2016-08-22 13:33:45 -0700308 InboundPacket pkt = context.inPacket();
309 Ethernet ethPkt = pkt.parsed();
310
311 NeighbourMessageContext msgContext =
312 DefaultNeighbourMessageContext.createContext(ethPkt, pkt.receivedFrom(), actions);
313
314 if (msgContext == null) {
315 return;
316 }
317
Pier Ventre0ba98522016-09-19 15:49:14 -0700318 if (handleMessage(msgContext)) {
319 context.block();
320 }
Jonathan Hart9bdaaec2016-08-22 13:33:45 -0700321
Jonathan Hart9bdaaec2016-08-22 13:33:45 -0700322 }
323
Pier Ventre0ba98522016-09-19 15:49:14 -0700324 private boolean handleMessage(NeighbourMessageContext context) {
Ray Milkeyfb1c7622018-05-18 10:16:53 -0700325 Collection<NeighbourHandlerRegistration> handled;
326 synchronized (packetHandlers) {
327 handled = packetHandlers.get(context.inPort())
328 .stream()
329 .filter(registration -> registration.intf() == null || matches(context, registration.intf()))
330 .collect(Collectors.toSet());
331 }
Pier Ventre0ba98522016-09-19 15:49:14 -0700332 handled.forEach(registration -> registration.handler().handleMessage(context, hostService));
333
334 return !handled.isEmpty();
Jonathan Hart9bdaaec2016-08-22 13:33:45 -0700335 }
336
Jonathan Hartc4f681c2016-09-09 07:14:25 -0700337 /**
338 * Checks that incoming packet matches the parameters of the interface.
339 * This means that if the interface specifies a particular parameter
340 * (VLAN, IP address, etc.) then the incoming packet should match those
341 * parameters.
342 *
343 * @param context incoming message context
344 * @param intf interface to check
345 * @return true if the incoming message matches the interface, otherwise false
346 */
Jonathan Hart9bdaaec2016-08-22 13:33:45 -0700347 private boolean matches(NeighbourMessageContext context, Interface intf) {
348 checkNotNull(context);
349 checkNotNull(intf);
350
351 boolean matches = true;
Jonathan Hartc4f681c2016-09-09 07:14:25 -0700352 // For non-broadcast packets, if the interface has a MAC address check that
353 // the destination MAC address of the packet matches the interface MAC
354 if (!context.dstMac().isBroadcast() &&
355 !intf.mac().equals(MacAddress.NONE) &&
356 !intf.mac().equals(context.dstMac())) {
357 matches = false;
358 }
359 // If the interface has a VLAN, check that the packet's VLAN matches
Jonathan Hart9bdaaec2016-08-22 13:33:45 -0700360 if (!intf.vlan().equals(VlanId.NONE) && !intf.vlan().equals(context.vlan())) {
361 matches = false;
362 }
Jonathan Hartc4f681c2016-09-09 07:14:25 -0700363 // If the interface has IP addresses, check that the packet's target IP
364 // address matches one of the interface IP addresses
365 if (!intf.ipAddressesList().isEmpty() && !hasIp(intf, context.target())) {
366 matches = false;
367 }
Jonathan Hart9bdaaec2016-08-22 13:33:45 -0700368
369 return matches;
370 }
371
Jonathan Hartc4f681c2016-09-09 07:14:25 -0700372 /**
373 * Returns true if the interface has the given IP address.
374 *
375 * @param intf interface to check
376 * @param ip IP address
377 * @return true if the IP is configured on the interface, otherwise false
378 */
379 private boolean hasIp(Interface intf, IpAddress ip) {
380 return intf.ipAddressesList().stream()
381 .anyMatch(intfAddress -> intfAddress.ipAddress().equals(ip));
382 }
383
Jonathan Hart9bdaaec2016-08-22 13:33:45 -0700384 /**
385 * Stores a neighbour message handler registration.
386 */
Jonathan Hartc4f681c2016-09-09 07:14:25 -0700387 private class HandlerRegistration implements NeighbourHandlerRegistration {
Jonathan Hart9bdaaec2016-08-22 13:33:45 -0700388 private final Interface intf;
389 private final NeighbourMessageHandler handler;
Jonathan Hartc4f681c2016-09-09 07:14:25 -0700390 private final ApplicationId appId;
Jonathan Hart9bdaaec2016-08-22 13:33:45 -0700391
392 /**
393 * Creates a new handler registration.
394 *
395 * @param handler neighbour message handler
396 */
Jonathan Hartc4f681c2016-09-09 07:14:25 -0700397 public HandlerRegistration(NeighbourMessageHandler handler, ApplicationId appId) {
398 this(handler, null, appId);
Jonathan Hart9bdaaec2016-08-22 13:33:45 -0700399 }
400
401 /**
402 * Creates a new handler registration.
403 *
404 * @param handler neighbour message handler
405 * @param intf interface
406 */
Jonathan Hartc4f681c2016-09-09 07:14:25 -0700407 public HandlerRegistration(NeighbourMessageHandler handler, Interface intf, ApplicationId appId) {
Jonathan Hart9bdaaec2016-08-22 13:33:45 -0700408 this.intf = intf;
409 this.handler = handler;
Jonathan Hartc4f681c2016-09-09 07:14:25 -0700410 this.appId = appId;
Jonathan Hart9bdaaec2016-08-22 13:33:45 -0700411 }
412
Jonathan Hartc4f681c2016-09-09 07:14:25 -0700413 @Override
Jonathan Hart9bdaaec2016-08-22 13:33:45 -0700414 public Interface intf() {
415 return intf;
416 }
417
Jonathan Hartc4f681c2016-09-09 07:14:25 -0700418 @Override
Jonathan Hart9bdaaec2016-08-22 13:33:45 -0700419 public NeighbourMessageHandler handler() {
420 return handler;
421 }
422
423 @Override
Jonathan Hartc4f681c2016-09-09 07:14:25 -0700424 public ApplicationId appId() {
425 return appId;
426 }
427
428 @Override
Jonathan Hart9bdaaec2016-08-22 13:33:45 -0700429 public boolean equals(Object other) {
430 if (this == other) {
431 return true;
432 }
433
434 if (!(other instanceof HandlerRegistration)) {
435 return false;
436 }
437
438 HandlerRegistration that = (HandlerRegistration) other;
439
440 return Objects.equals(intf, that.intf) &&
Jonathan Hartc4f681c2016-09-09 07:14:25 -0700441 Objects.equals(handler, that.handler) &&
442 Objects.equals(appId, that.appId);
Jonathan Hart9bdaaec2016-08-22 13:33:45 -0700443 }
444
445 @Override
446 public int hashCode() {
Jonathan Hartc4f681c2016-09-09 07:14:25 -0700447 return Objects.hash(intf, handler, appId);
Jonathan Hart9bdaaec2016-08-22 13:33:45 -0700448 }
449 }
450
451 /**
452 * Packet processor for incoming packets.
453 */
454 private class InternalPacketProcessor implements PacketProcessor {
455
456 @Override
457 public void process(PacketContext context) {
458 // Stop processing if the packet has been handled, since we
459 // can't do any more to it.
460 if (context.isHandled()) {
461 return;
462 }
463
464 InboundPacket pkt = context.inPacket();
465 Ethernet ethPkt = pkt.parsed();
466 if (ethPkt == null) {
467 return;
468 }
469
470 if (ethPkt.getEtherType() == TYPE_ARP) {
471 // handle ARP packets
472 handlePacket(context);
473 } else if (ethPkt.getEtherType() == TYPE_IPV6) {
474 IPv6 ipv6 = (IPv6) ethPkt.getPayload();
475 if (ipv6.getNextHeader() == IPv6.PROTOCOL_ICMP6) {
476 ICMP6 icmp6 = (ICMP6) ipv6.getPayload();
477 if (icmp6.getIcmpType() == NEIGHBOR_SOLICITATION ||
478 icmp6.getIcmpType() == NEIGHBOR_ADVERTISEMENT) {
479 // handle ICMPv6 solicitations and advertisements (NDP)
480 handlePacket(context);
481 }
482 }
483 }
484 }
485 }
Jonathan Hart9bdaaec2016-08-22 13:33:45 -0700486}