blob: ed6c8560629bd8828a7b9b391c92a93444d81175 [file] [log] [blame]
Jonathan Hart9bdaaec2016-08-22 13:33:45 -07001/*
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
17package org.onosproject.incubator.net.neighbour.impl;
18
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.apache.felix.scr.annotations.Activate;
24import org.apache.felix.scr.annotations.Component;
25import org.apache.felix.scr.annotations.Deactivate;
26import org.apache.felix.scr.annotations.Modified;
27import org.apache.felix.scr.annotations.Property;
28import org.apache.felix.scr.annotations.Reference;
29import org.apache.felix.scr.annotations.ReferenceCardinality;
30import org.apache.felix.scr.annotations.Service;
31import org.onlab.packet.ARP;
32import org.onlab.packet.Ethernet;
33import org.onlab.packet.ICMP6;
34import org.onlab.packet.IPv6;
35import org.onlab.packet.Ip4Address;
36import org.onlab.packet.Ip6Address;
Jonathan Hartc4f681c2016-09-09 07:14:25 -070037import org.onlab.packet.IpAddress;
Jonathan Hart9bdaaec2016-08-22 13:33:45 -070038import org.onlab.packet.MacAddress;
39import org.onlab.packet.VlanId;
40import org.onlab.packet.ndp.NeighborAdvertisement;
41import org.onlab.packet.ndp.NeighborDiscoveryOptions;
42import org.onlab.util.Tools;
43import org.onosproject.cfg.ComponentConfigService;
44import org.onosproject.core.ApplicationId;
45import org.onosproject.core.CoreService;
46import org.onosproject.incubator.net.intf.Interface;
Jonathan Hartc4f681c2016-09-09 07:14:25 -070047import org.onosproject.incubator.net.neighbour.NeighbourHandlerRegistration;
Jonathan Hart9bdaaec2016-08-22 13:33:45 -070048import org.onosproject.incubator.net.neighbour.NeighbourMessageActions;
49import org.onosproject.incubator.net.neighbour.NeighbourMessageContext;
50import org.onosproject.incubator.net.neighbour.NeighbourMessageHandler;
51import org.onosproject.incubator.net.neighbour.NeighbourResolutionService;
52import org.onosproject.net.ConnectPoint;
53import org.onosproject.net.edge.EdgePortService;
54import org.onosproject.net.flow.DefaultTrafficSelector;
55import org.onosproject.net.flow.DefaultTrafficTreatment;
56import org.onosproject.net.flow.TrafficSelector;
57import org.onosproject.net.flow.TrafficTreatment;
58import org.onosproject.net.host.HostService;
59import org.onosproject.net.packet.DefaultOutboundPacket;
60import org.onosproject.net.packet.InboundPacket;
61import org.onosproject.net.packet.PacketContext;
62import org.onosproject.net.packet.PacketProcessor;
63import org.onosproject.net.packet.PacketService;
64import org.osgi.service.component.ComponentContext;
65import org.slf4j.Logger;
66import org.slf4j.LoggerFactory;
67
68import java.nio.ByteBuffer;
Jonathan Hartc4f681c2016-09-09 07:14:25 -070069import java.util.Collection;
Jonathan Hart9bdaaec2016-08-22 13:33:45 -070070import java.util.Dictionary;
Jonathan Hartc4f681c2016-09-09 07:14:25 -070071import java.util.Iterator;
72import java.util.Map;
Jonathan Hart9bdaaec2016-08-22 13:33:45 -070073import java.util.Objects;
Pier Ventre0ba98522016-09-19 15:49:14 -070074import java.util.stream.Collectors;
Jonathan Hart9bdaaec2016-08-22 13:33:45 -070075
76import static com.google.common.base.Preconditions.checkNotNull;
77import static org.onlab.packet.Ethernet.TYPE_ARP;
78import static org.onlab.packet.Ethernet.TYPE_IPV6;
79import static org.onlab.packet.ICMP6.NEIGHBOR_ADVERTISEMENT;
80import static org.onlab.packet.ICMP6.NEIGHBOR_SOLICITATION;
81import static org.onlab.packet.IPv6.PROTOCOL_ICMP6;
82import static org.onosproject.net.packet.PacketPriority.CONTROL;
83
84/**
85 * Manages handlers for neighbour messages.
86 */
87@Service
Jonathan Hartc4f681c2016-09-09 07:14:25 -070088@Component(immediate = true)
Jonathan Hart1e393bb2016-09-14 08:51:09 -070089public class NeighbourResolutionManager implements NeighbourResolutionService {
Jonathan Hart9bdaaec2016-08-22 13:33:45 -070090
91 private final Logger log = LoggerFactory.getLogger(getClass());
92
93 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
94 protected CoreService coreService;
95
96 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
97 protected HostService hostService;
98
99 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
100 protected EdgePortService edgeService;
101
102 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
103 protected PacketService packetService;
104
105 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
106 protected ComponentConfigService componentConfigService;
107
108 @Property(name = "ndpEnabled", boolValue = false,
109 label = "Enable IPv6 neighbour discovery")
110 protected boolean ndpEnabled = false;
111
112 private static final String APP_NAME = "org.onosproject.neighbour";
113 private ApplicationId appId;
114
Jonathan Hartc004adf2016-09-15 16:50:04 -0700115 private final SetMultimap<ConnectPoint, NeighbourHandlerRegistration> packetHandlers =
Jonathan Hartc4f681c2016-09-09 07:14:25 -0700116 Multimaps.synchronizedSetMultimap(HashMultimap.create());
Jonathan Hart9bdaaec2016-08-22 13:33:45 -0700117
118 private final InternalPacketProcessor processor = new InternalPacketProcessor();
119 private final InternalNeighbourMessageActions actions = new InternalNeighbourMessageActions();
120
121 @Activate
122 protected void activate(ComponentContext context) {
123 appId = coreService.registerApplication(APP_NAME);
124
125 componentConfigService.registerProperties(getClass());
126 modified(context);
127
128 packetService.addProcessor(processor, PacketProcessor.director(1));
129 }
130
131 @Deactivate
132 protected void deactivate() {
133 cancelPackets();
134 packetService.removeProcessor(processor);
135 componentConfigService.unregisterProperties(getClass(), false);
136 }
137
138 @Modified
139 protected void modified(ComponentContext context) {
140 Dictionary<?, ?> properties = context.getProperties();
141 Boolean flag;
142
143 flag = Tools.isPropertyEnabled(properties, "ndpEnabled");
144 if (flag != null) {
145 ndpEnabled = flag;
146 log.info("IPv6 neighbor discovery is {}",
147 ndpEnabled ? "enabled" : "disabled");
148 }
149
Jonathan Hartc004adf2016-09-15 16:50:04 -0700150 synchronized (packetHandlers) {
151 if (!packetHandlers.isEmpty()) {
152 requestPackets();
153 }
154 }
Jonathan Hart9bdaaec2016-08-22 13:33:45 -0700155 }
156
157 private void requestPackets() {
158 packetService.requestPackets(buildArpSelector(), CONTROL, appId);
159
160 if (ndpEnabled) {
161 packetService.requestPackets(buildNeighborSolicitationSelector(),
162 CONTROL, appId);
163 packetService.requestPackets(buildNeighborAdvertisementSelector(),
164 CONTROL, appId);
165 } else {
166 packetService.cancelPackets(buildNeighborSolicitationSelector(),
167 CONTROL, appId);
168 packetService.cancelPackets(buildNeighborAdvertisementSelector(),
169 CONTROL, appId);
170 }
171 }
172
173 private void cancelPackets() {
174 packetService.cancelPackets(buildArpSelector(), CONTROL, appId);
175 packetService.cancelPackets(buildNeighborSolicitationSelector(),
176 CONTROL, appId);
177 packetService.cancelPackets(buildNeighborAdvertisementSelector(),
178 CONTROL, appId);
179 }
180
181 private TrafficSelector buildArpSelector() {
182 return DefaultTrafficSelector.builder()
183 .matchEthType(TYPE_ARP)
184 .build();
185 }
186
187 private TrafficSelector buildNeighborSolicitationSelector() {
188 return DefaultTrafficSelector.builder()
189 .matchEthType(TYPE_IPV6)
190 .matchIPProtocol(PROTOCOL_ICMP6)
191 .matchIcmpv6Type(NEIGHBOR_SOLICITATION)
192 .build();
193 }
194
195 private TrafficSelector buildNeighborAdvertisementSelector() {
196 return DefaultTrafficSelector.builder()
197 .matchEthType(TYPE_IPV6)
198 .matchIPProtocol(PROTOCOL_ICMP6)
199 .matchIcmpv6Type(NEIGHBOR_ADVERTISEMENT)
200 .build();
201 }
202
203 @Override
Jonathan Hartc4f681c2016-09-09 07:14:25 -0700204 public void registerNeighbourHandler(ConnectPoint connectPoint,
205 NeighbourMessageHandler handler,
206 ApplicationId appId) {
Jonathan Hartc004adf2016-09-15 16:50:04 -0700207 register(connectPoint, new HandlerRegistration(handler, appId));
Jonathan Hart9bdaaec2016-08-22 13:33:45 -0700208 }
209
210 @Override
Jonathan Hartc4f681c2016-09-09 07:14:25 -0700211 public void registerNeighbourHandler(Interface intf,
212 NeighbourMessageHandler handler,
213 ApplicationId appId) {
Jonathan Hartc004adf2016-09-15 16:50:04 -0700214 register(intf.connectPoint(), new HandlerRegistration(handler, intf, appId));
215 }
216
217 private void register(ConnectPoint connectPoint, HandlerRegistration registration) {
218 synchronized (packetHandlers) {
219 if (packetHandlers.isEmpty()) {
220 requestPackets();
221 }
222 packetHandlers.put(connectPoint, registration);
223 }
Jonathan Hart9bdaaec2016-08-22 13:33:45 -0700224 }
225
226 @Override
Jonathan Hartc4f681c2016-09-09 07:14:25 -0700227 public void unregisterNeighbourHandler(ConnectPoint connectPoint,
228 NeighbourMessageHandler handler,
229 ApplicationId appId) {
Jonathan Hartc004adf2016-09-15 16:50:04 -0700230 unregister(connectPoint, new HandlerRegistration(handler, appId));
Jonathan Hart9bdaaec2016-08-22 13:33:45 -0700231 }
232
233 @Override
Jonathan Hartc4f681c2016-09-09 07:14:25 -0700234 public void unregisterNeighbourHandler(Interface intf,
235 NeighbourMessageHandler handler,
236 ApplicationId appId) {
Jonathan Hartc004adf2016-09-15 16:50:04 -0700237 unregister(intf.connectPoint(), new HandlerRegistration(handler, intf, appId));
238 }
239
240 private void unregister(ConnectPoint connectPoint, HandlerRegistration registration) {
241 synchronized (packetHandlers) {
242 packetHandlers.remove(connectPoint, registration);
243
244 if (packetHandlers.isEmpty()) {
245 cancelPackets();
246 }
247 }
Jonathan Hartc4f681c2016-09-09 07:14:25 -0700248 }
249
250 @Override
251 public void unregisterNeighbourHandlers(ApplicationId appId) {
252 synchronized (packetHandlers) {
253 Iterator<NeighbourHandlerRegistration> it = packetHandlers.values().iterator();
254
255 while (it.hasNext()) {
256 NeighbourHandlerRegistration registration = it.next();
257 if (registration.appId().equals(appId)) {
258 it.remove();
259 }
260 }
Jonathan Hartc004adf2016-09-15 16:50:04 -0700261
262 if (packetHandlers.isEmpty()) {
263 cancelPackets();
264 }
Jonathan Hartc4f681c2016-09-09 07:14:25 -0700265 }
266 }
267
268 @Override
269 public Map<ConnectPoint, Collection<NeighbourHandlerRegistration>> getHandlerRegistrations() {
270 return ImmutableMap.copyOf(Multimaps.asMap(packetHandlers));
Jonathan Hart9bdaaec2016-08-22 13:33:45 -0700271 }
272
273 public void handlePacket(PacketContext context) {
274 InboundPacket pkt = context.inPacket();
275 Ethernet ethPkt = pkt.parsed();
276
277 NeighbourMessageContext msgContext =
278 DefaultNeighbourMessageContext.createContext(ethPkt, pkt.receivedFrom(), actions);
279
280 if (msgContext == null) {
281 return;
282 }
283
Pier Ventre0ba98522016-09-19 15:49:14 -0700284 if (handleMessage(msgContext)) {
285 context.block();
286 }
Jonathan Hart9bdaaec2016-08-22 13:33:45 -0700287
Jonathan Hart9bdaaec2016-08-22 13:33:45 -0700288 }
289
Pier Ventre0ba98522016-09-19 15:49:14 -0700290 private boolean handleMessage(NeighbourMessageContext context) {
Jonathan Hartc4f681c2016-09-09 07:14:25 -0700291 Collection<NeighbourHandlerRegistration> handlers = packetHandlers.get(context.inPort());
Jonathan Hart9bdaaec2016-08-22 13:33:45 -0700292
Pier Ventre0ba98522016-09-19 15:49:14 -0700293 Collection<NeighbourHandlerRegistration> handled = handlers
294 .stream()
295 .filter(registration -> registration.intf() == null || matches(context, registration.intf()))
296 .collect(Collectors.toSet());
297
298 handled.forEach(registration -> registration.handler().handleMessage(context, hostService));
299
300 return !handled.isEmpty();
301
Jonathan Hart9bdaaec2016-08-22 13:33:45 -0700302 }
303
Jonathan Hartc4f681c2016-09-09 07:14:25 -0700304 /**
305 * Checks that incoming packet matches the parameters of the interface.
306 * This means that if the interface specifies a particular parameter
307 * (VLAN, IP address, etc.) then the incoming packet should match those
308 * parameters.
309 *
310 * @param context incoming message context
311 * @param intf interface to check
312 * @return true if the incoming message matches the interface, otherwise false
313 */
Jonathan Hart9bdaaec2016-08-22 13:33:45 -0700314 private boolean matches(NeighbourMessageContext context, Interface intf) {
315 checkNotNull(context);
316 checkNotNull(intf);
317
318 boolean matches = true;
Jonathan Hartc4f681c2016-09-09 07:14:25 -0700319 // For non-broadcast packets, if the interface has a MAC address check that
320 // the destination MAC address of the packet matches the interface MAC
321 if (!context.dstMac().isBroadcast() &&
322 !intf.mac().equals(MacAddress.NONE) &&
323 !intf.mac().equals(context.dstMac())) {
324 matches = false;
325 }
326 // If the interface has a VLAN, check that the packet's VLAN matches
Jonathan Hart9bdaaec2016-08-22 13:33:45 -0700327 if (!intf.vlan().equals(VlanId.NONE) && !intf.vlan().equals(context.vlan())) {
328 matches = false;
329 }
Jonathan Hartc4f681c2016-09-09 07:14:25 -0700330 // If the interface has IP addresses, check that the packet's target IP
331 // address matches one of the interface IP addresses
332 if (!intf.ipAddressesList().isEmpty() && !hasIp(intf, context.target())) {
333 matches = false;
334 }
Jonathan Hart9bdaaec2016-08-22 13:33:45 -0700335
336 return matches;
337 }
338
Jonathan Hartc4f681c2016-09-09 07:14:25 -0700339 /**
340 * Returns true if the interface has the given IP address.
341 *
342 * @param intf interface to check
343 * @param ip IP address
344 * @return true if the IP is configured on the interface, otherwise false
345 */
346 private boolean hasIp(Interface intf, IpAddress ip) {
347 return intf.ipAddressesList().stream()
348 .anyMatch(intfAddress -> intfAddress.ipAddress().equals(ip));
349 }
350
Jonathan Hart9bdaaec2016-08-22 13:33:45 -0700351 private void reply(NeighbourMessageContext context, MacAddress targetMac) {
352 switch (context.protocol()) {
353 case ARP:
354 sendTo(ARP.buildArpReply((Ip4Address) context.target(),
355 targetMac, context.packet()), context.inPort());
356 break;
357 case NDP:
358 sendTo(buildNdpReply((Ip6Address) context.target(), targetMac,
359 context.packet()), context.inPort());
360 break;
361 default:
362 break;
363 }
364 }
365
366 /**
367 * Outputs a packet out a specific port.
368 *
369 * @param packet the packet to send
370 * @param outPort the port to send it out
371 */
372 private void sendTo(Ethernet packet, ConnectPoint outPort) {
373 sendTo(ByteBuffer.wrap(packet.serialize()), outPort);
374 }
375
376 /**
377 * Outputs a packet out a specific port.
378 *
379 * @param packet packet to send
380 * @param outPort port to send it out
381 */
382 private void sendTo(ByteBuffer packet, ConnectPoint outPort) {
383 if (!edgeService.isEdgePoint(outPort)) {
384 // Sanity check to make sure we don't send the packet out an
385 // internal port and create a loop (could happen due to
386 // misconfiguration).
387 return;
388 }
389
390 TrafficTreatment.Builder builder = DefaultTrafficTreatment.builder();
391 builder.setOutput(outPort.port());
392 packetService.emit(new DefaultOutboundPacket(outPort.deviceId(),
393 builder.build(), packet));
394 }
395
396 /**
Jonathan Hartc4f681c2016-09-09 07:14:25 -0700397 * Builds an NDP reply based on a request.
Jonathan Hart9bdaaec2016-08-22 13:33:45 -0700398 *
399 * @param srcIp the IP address to use as the reply source
400 * @param srcMac the MAC address to use as the reply source
401 * @param request the Neighbor Solicitation request we got
402 * @return an Ethernet frame containing the Neighbor Advertisement reply
403 */
404 private Ethernet buildNdpReply(Ip6Address srcIp, MacAddress srcMac,
405 Ethernet request) {
406 Ethernet eth = new Ethernet();
407 eth.setDestinationMACAddress(request.getSourceMAC());
408 eth.setSourceMACAddress(srcMac);
409 eth.setEtherType(Ethernet.TYPE_IPV6);
410 eth.setVlanID(request.getVlanID());
411
412 IPv6 requestIp = (IPv6) request.getPayload();
413 IPv6 ipv6 = new IPv6();
414 ipv6.setSourceAddress(srcIp.toOctets());
415 ipv6.setDestinationAddress(requestIp.getSourceAddress());
416 ipv6.setHopLimit((byte) 255);
417
418 ICMP6 icmp6 = new ICMP6();
419 icmp6.setIcmpType(ICMP6.NEIGHBOR_ADVERTISEMENT);
420 icmp6.setIcmpCode((byte) 0);
421
422 NeighborAdvertisement nadv = new NeighborAdvertisement();
423 nadv.setTargetAddress(srcIp.toOctets());
424 nadv.setSolicitedFlag((byte) 1);
425 nadv.setOverrideFlag((byte) 1);
426 nadv.addOption(NeighborDiscoveryOptions.TYPE_TARGET_LL_ADDRESS,
427 srcMac.toBytes());
428
429 icmp6.setPayload(nadv);
430 ipv6.setPayload(icmp6);
431 eth.setPayload(ipv6);
432 return eth;
433 }
434
435 /**
436 * Stores a neighbour message handler registration.
437 */
Jonathan Hartc4f681c2016-09-09 07:14:25 -0700438 private class HandlerRegistration implements NeighbourHandlerRegistration {
Jonathan Hart9bdaaec2016-08-22 13:33:45 -0700439 private final Interface intf;
440 private final NeighbourMessageHandler handler;
Jonathan Hartc4f681c2016-09-09 07:14:25 -0700441 private final ApplicationId appId;
Jonathan Hart9bdaaec2016-08-22 13:33:45 -0700442
443 /**
444 * Creates a new handler registration.
445 *
446 * @param handler neighbour message handler
447 */
Jonathan Hartc4f681c2016-09-09 07:14:25 -0700448 public HandlerRegistration(NeighbourMessageHandler handler, ApplicationId appId) {
449 this(handler, null, appId);
Jonathan Hart9bdaaec2016-08-22 13:33:45 -0700450 }
451
452 /**
453 * Creates a new handler registration.
454 *
455 * @param handler neighbour message handler
456 * @param intf interface
457 */
Jonathan Hartc4f681c2016-09-09 07:14:25 -0700458 public HandlerRegistration(NeighbourMessageHandler handler, Interface intf, ApplicationId appId) {
Jonathan Hart9bdaaec2016-08-22 13:33:45 -0700459 this.intf = intf;
460 this.handler = handler;
Jonathan Hartc4f681c2016-09-09 07:14:25 -0700461 this.appId = appId;
Jonathan Hart9bdaaec2016-08-22 13:33:45 -0700462 }
463
Jonathan Hartc4f681c2016-09-09 07:14:25 -0700464 @Override
Jonathan Hart9bdaaec2016-08-22 13:33:45 -0700465 public Interface intf() {
466 return intf;
467 }
468
Jonathan Hartc4f681c2016-09-09 07:14:25 -0700469 @Override
Jonathan Hart9bdaaec2016-08-22 13:33:45 -0700470 public NeighbourMessageHandler handler() {
471 return handler;
472 }
473
474 @Override
Jonathan Hartc4f681c2016-09-09 07:14:25 -0700475 public ApplicationId appId() {
476 return appId;
477 }
478
479 @Override
Jonathan Hart9bdaaec2016-08-22 13:33:45 -0700480 public boolean equals(Object other) {
481 if (this == other) {
482 return true;
483 }
484
485 if (!(other instanceof HandlerRegistration)) {
486 return false;
487 }
488
489 HandlerRegistration that = (HandlerRegistration) other;
490
491 return Objects.equals(intf, that.intf) &&
Jonathan Hartc4f681c2016-09-09 07:14:25 -0700492 Objects.equals(handler, that.handler) &&
493 Objects.equals(appId, that.appId);
Jonathan Hart9bdaaec2016-08-22 13:33:45 -0700494 }
495
496 @Override
497 public int hashCode() {
Jonathan Hartc4f681c2016-09-09 07:14:25 -0700498 return Objects.hash(intf, handler, appId);
Jonathan Hart9bdaaec2016-08-22 13:33:45 -0700499 }
500 }
501
502 /**
503 * Packet processor for incoming packets.
504 */
505 private class InternalPacketProcessor implements PacketProcessor {
506
507 @Override
508 public void process(PacketContext context) {
509 // Stop processing if the packet has been handled, since we
510 // can't do any more to it.
511 if (context.isHandled()) {
512 return;
513 }
514
515 InboundPacket pkt = context.inPacket();
516 Ethernet ethPkt = pkt.parsed();
517 if (ethPkt == null) {
518 return;
519 }
520
521 if (ethPkt.getEtherType() == TYPE_ARP) {
522 // handle ARP packets
523 handlePacket(context);
524 } else if (ethPkt.getEtherType() == TYPE_IPV6) {
525 IPv6 ipv6 = (IPv6) ethPkt.getPayload();
526 if (ipv6.getNextHeader() == IPv6.PROTOCOL_ICMP6) {
527 ICMP6 icmp6 = (ICMP6) ipv6.getPayload();
528 if (icmp6.getIcmpType() == NEIGHBOR_SOLICITATION ||
529 icmp6.getIcmpType() == NEIGHBOR_ADVERTISEMENT) {
530 // handle ICMPv6 solicitations and advertisements (NDP)
531 handlePacket(context);
532 }
533 }
534 }
535 }
536 }
537
538 private class InternalNeighbourMessageActions implements NeighbourMessageActions {
539
540 @Override
541 public void reply(NeighbourMessageContext context, MacAddress targetMac) {
Jonathan Hart1e393bb2016-09-14 08:51:09 -0700542 NeighbourResolutionManager.this.reply(context, targetMac);
Jonathan Hart9bdaaec2016-08-22 13:33:45 -0700543 }
544
545 @Override
Jonathan Hart1e393bb2016-09-14 08:51:09 -0700546 public void forward(NeighbourMessageContext context, ConnectPoint outPort) {
Jonathan Hart9bdaaec2016-08-22 13:33:45 -0700547 sendTo(context.packet(), outPort);
548 }
549
550 @Override
Jonathan Hart1e393bb2016-09-14 08:51:09 -0700551 public void forward(NeighbourMessageContext context, Interface outIntf) {
Jonathan Hartc4f681c2016-09-09 07:14:25 -0700552 // TODO implement
Jonathan Hart9bdaaec2016-08-22 13:33:45 -0700553 }
554
555 @Override
556 public void flood(NeighbourMessageContext context) {
557 edgeService.getEdgePoints().forEach(connectPoint -> {
558 if (!connectPoint.equals(context.inPort())) {
559 sendTo(context.packet(), connectPoint);
560 }
561 });
562 }
563
564 @Override
565 public void drop(NeighbourMessageContext context) {
566
567 }
568 }
569
570}