blob: ecfb71c635dff5708557953fc1cb4815b9006e52 [file] [log] [blame]
Thomas Vachuska4f1a60c2014-10-28 13:39:07 -07001/*
Ray Milkey34c95902015-04-15 09:47:53 -07002 * Copyright 2014-2015 Open Networking Laboratory
Thomas Vachuska4f1a60c2014-10-28 13:39:07 -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 */
Brian O'Connorabafb502014-12-02 22:26:20 -080016package org.onosproject.net.proxyarp.impl;
alshabibb5522ff2014-09-29 19:20:00 -070017
alshabibb5522ff2014-09-29 19:20:00 -070018import org.apache.felix.scr.annotations.Activate;
19import org.apache.felix.scr.annotations.Component;
20import org.apache.felix.scr.annotations.Deactivate;
21import org.apache.felix.scr.annotations.Reference;
22import org.apache.felix.scr.annotations.ReferenceCardinality;
23import org.apache.felix.scr.annotations.Service;
Jonathan Harte8600eb2015-01-12 10:30:45 -080024import org.onlab.packet.ARP;
25import org.onlab.packet.Ethernet;
Kunihiro Ishigurof1bff502015-01-30 15:47:06 -080026import org.onlab.packet.ICMP6;
27import org.onlab.packet.IPv6;
Jonathan Harte8600eb2015-01-12 10:30:45 -080028import org.onlab.packet.Ip4Address;
Kunihiro Ishigurof1bff502015-01-30 15:47:06 -080029import org.onlab.packet.Ip6Address;
Jonathan Harte8600eb2015-01-12 10:30:45 -080030import org.onlab.packet.IpAddress;
31import org.onlab.packet.MacAddress;
32import org.onlab.packet.VlanId;
Kunihiro Ishigurof1bff502015-01-30 15:47:06 -080033import org.onlab.packet.ndp.NeighborAdvertisement;
Pavlin Radoslavova2626ef2015-02-18 18:33:25 -080034import org.onlab.packet.ndp.NeighborDiscoveryOptions;
Kunihiro Ishigurof1bff502015-01-30 15:47:06 -080035import org.onlab.packet.ndp.NeighborSolicitation;
Changhoon Yoon541ef712015-05-23 17:18:34 +090036import org.onosproject.core.Permission;
Brian O'Connorabafb502014-12-02 22:26:20 -080037import org.onosproject.net.ConnectPoint;
Brian O'Connorabafb502014-12-02 22:26:20 -080038import org.onosproject.net.Host;
39import org.onosproject.net.HostId;
Brian O'Connorabafb502014-12-02 22:26:20 -080040import org.onosproject.net.device.DeviceService;
Aaron Kruglikovd8123832015-07-06 14:20:25 -070041import org.onosproject.net.edge.EdgePortService;
Brian O'Connorabafb502014-12-02 22:26:20 -080042import org.onosproject.net.flow.DefaultTrafficTreatment;
43import org.onosproject.net.flow.TrafficTreatment;
44import org.onosproject.net.host.HostService;
45import org.onosproject.net.host.InterfaceIpAddress;
46import org.onosproject.net.host.PortAddresses;
Brian O'Connorabafb502014-12-02 22:26:20 -080047import org.onosproject.net.link.LinkService;
48import org.onosproject.net.packet.DefaultOutboundPacket;
49import org.onosproject.net.packet.InboundPacket;
50import org.onosproject.net.packet.PacketContext;
51import org.onosproject.net.packet.PacketService;
52import org.onosproject.net.proxyarp.ProxyArpService;
alshabibb5522ff2014-09-29 19:20:00 -070053import org.slf4j.Logger;
54
Jonathan Hart6cd2f352015-01-13 17:44:45 -080055import java.nio.ByteBuffer;
56import java.util.HashSet;
Jonathan Hart6cd2f352015-01-13 17:44:45 -080057import java.util.Set;
Aaron Kruglikovd8123832015-07-06 14:20:25 -070058import java.util.stream.Collectors;
Jonathan Hart6cd2f352015-01-13 17:44:45 -080059
60import static com.google.common.base.Preconditions.checkArgument;
61import static com.google.common.base.Preconditions.checkNotNull;
Changhoon Yoon541ef712015-05-23 17:18:34 +090062import static org.onosproject.security.AppGuard.checkPermission;
Aaron Kruglikovd8123832015-07-06 14:20:25 -070063import static org.slf4j.LoggerFactory.getLogger;
Changhoon Yoon541ef712015-05-23 17:18:34 +090064
alshabibb5522ff2014-09-29 19:20:00 -070065
alshabibb5522ff2014-09-29 19:20:00 -070066@Component(immediate = true)
67@Service
68public class ProxyArpManager implements ProxyArpService {
69
70 private final Logger log = getLogger(getClass());
71
72 private static final String MAC_ADDR_NULL = "Mac address cannot be null.";
Kunihiro Ishigurof1bff502015-01-30 15:47:06 -080073 private static final String REQUEST_NULL = "ARP or NDP request cannot be null.";
alshabibb5522ff2014-09-29 19:20:00 -070074 private static final String REQUEST_NOT_ARP = "Ethernet frame does not contain ARP request.";
75 private static final String NOT_ARP_REQUEST = "ARP is not a request.";
Jonathan Hart704ca142014-10-09 09:34:39 -070076 private static final String NOT_ARP_REPLY = "ARP is not a reply.";
alshabibb5522ff2014-09-29 19:20:00 -070077
78 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Aaron Kruglikovd8123832015-07-06 14:20:25 -070079 protected EdgePortService edgeService;
80
81 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
alshabibb5522ff2014-09-29 19:20:00 -070082 protected HostService hostService;
83
84 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
85 protected PacketService packetService;
86
87 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
88 protected LinkService linkService;
89
90 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
91 protected DeviceService deviceService;
92
alshabibb5522ff2014-09-29 19:20:00 -070093 /**
94 * Listens to both device service and link service to determine
95 * whether a port is internal or external.
96 */
97 @Activate
98 public void activate() {
alshabibb5522ff2014-09-29 19:20:00 -070099 log.info("Started");
100 }
101
102
103 @Deactivate
104 public void deactivate() {
105 log.info("Stopped");
106 }
107
108 @Override
Kunihiro Ishigurof1bff502015-01-30 15:47:06 -0800109 public boolean isKnown(IpAddress addr) {
Changhoon Yoon541ef712015-05-23 17:18:34 +0900110 checkPermission(Permission.PACKET_READ);
111
Yuta HIGUCHI59718042014-10-04 22:04:56 -0700112 checkNotNull(addr, MAC_ADDR_NULL);
alshabibb5522ff2014-09-29 19:20:00 -0700113 Set<Host> hosts = hostService.getHostsByIp(addr);
114 return !hosts.isEmpty();
115 }
116
117 @Override
Jonathan Hartdbdbdbb2014-10-06 18:35:30 -0700118 public void reply(Ethernet eth, ConnectPoint inPort) {
Changhoon Yoon541ef712015-05-23 17:18:34 +0900119 checkPermission(Permission.PACKET_WRITE);
120
Yuta HIGUCHI59718042014-10-04 22:04:56 -0700121 checkNotNull(eth, REQUEST_NULL);
Kunihiro Ishigurof1bff502015-01-30 15:47:06 -0800122
123 if (eth.getEtherType() == Ethernet.TYPE_ARP) {
124 replyArp(eth, inPort);
125 } else if (eth.getEtherType() == Ethernet.TYPE_IPV6) {
126 replyNdp(eth, inPort);
127 }
128 }
129
130 private void replyArp(Ethernet eth, ConnectPoint inPort) {
alshabibb5522ff2014-09-29 19:20:00 -0700131 ARP arp = (ARP) eth.getPayload();
132 checkArgument(arp.getOpCode() == ARP.OP_REQUEST, NOT_ARP_REQUEST);
Jonathan Hartdbdbdbb2014-10-06 18:35:30 -0700133 checkNotNull(inPort);
Dusan Pajina22b9702015-02-12 16:25:23 +0100134 Ip4Address targetAddress = Ip4Address.valueOf(arp.getTargetProtocolAddress());
Jonathan Hartdbdbdbb2014-10-06 18:35:30 -0700135
Jonathan Hart6cd2f352015-01-13 17:44:45 -0800136 VlanId vlan = VlanId.vlanId(eth.getVlanID());
137
Jonathan Hartdbdbdbb2014-10-06 18:35:30 -0700138 if (isOutsidePort(inPort)) {
Jonathan Hart7d1496b2015-03-10 22:00:48 -0700139 // If the request came from outside the network, only reply if it was
140 // for one of our external addresses.
Jonathan Harta887ba82014-11-03 15:20:52 -0800141 Set<PortAddresses> addressSet =
Jonathan Hart7d1496b2015-03-10 22:00:48 -0700142 hostService.getAddressBindingsForPort(inPort);
Jonathan Hartdbdbdbb2014-10-06 18:35:30 -0700143
Jonathan Harta887ba82014-11-03 15:20:52 -0800144 for (PortAddresses addresses : addressSet) {
145 for (InterfaceIpAddress ia : addresses.ipAddresses()) {
Dusan Pajina22b9702015-02-12 16:25:23 +0100146 if (ia.ipAddress().equals(targetAddress)) {
Jonathan Harta887ba82014-11-03 15:20:52 -0800147 Ethernet arpReply =
Pingping Linc9e16bf2015-04-10 14:42:41 -0700148 ARP.buildArpReply(targetAddress, addresses.mac(), eth);
Jonathan Harta887ba82014-11-03 15:20:52 -0800149 sendTo(arpReply, inPort);
150 }
Jonathan Hartdbdbdbb2014-10-06 18:35:30 -0700151 }
152 }
Jonathan Hartdbdbdbb2014-10-06 18:35:30 -0700153 return;
154 }
155
Jonathan Hart7d1496b2015-03-10 22:00:48 -0700156 // See if we have the target host in the host store
alshabibb5522ff2014-09-29 19:20:00 -0700157
Dusan Pajina22b9702015-02-12 16:25:23 +0100158 Set<Host> hosts = hostService.getHostsByIp(targetAddress);
alshabibb5522ff2014-09-29 19:20:00 -0700159
160 Host dst = null;
161 Host src = hostService.getHost(HostId.hostId(eth.getSourceMAC(),
162 VlanId.vlanId(eth.getVlanID())));
163
164 for (Host host : hosts) {
165 if (host.vlan().equals(vlan)) {
166 dst = host;
167 break;
168 }
169 }
170
Jonathan Hart7d1496b2015-03-10 22:00:48 -0700171 if (src != null && dst != null) {
172 // We know the target host so we can respond
Pingping Linc9e16bf2015-04-10 14:42:41 -0700173 Ethernet arpReply = ARP.buildArpReply(targetAddress, dst.mac(), eth);
Jonathan Hart7d1496b2015-03-10 22:00:48 -0700174 sendTo(arpReply, inPort);
175 return;
176 }
177
178 // If the source address matches one of our external addresses
179 // it could be a request from an internal host to an external
180 // address. Forward it over to the correct port.
181 Ip4Address source =
182 Ip4Address.valueOf(arp.getSenderProtocolAddress());
183 Set<PortAddresses> sourceAddresses = findPortsInSubnet(source);
184 boolean matched = false;
185 for (PortAddresses pa : sourceAddresses) {
186 for (InterfaceIpAddress ia : pa.ipAddresses()) {
187 if (ia.ipAddress().equals(source) &&
188 pa.vlan().equals(vlan)) {
189 matched = true;
190 sendTo(eth, pa.connectPoint());
191 break;
192 }
193 }
194 }
195
196 if (matched) {
alshabibb5522ff2014-09-29 19:20:00 -0700197 return;
198 }
199
Pavlin Radoslavov5b5dc482014-11-05 14:48:08 -0800200 //
Jonathan Hart7d1496b2015-03-10 22:00:48 -0700201 // The request couldn't be resolved.
202 // Flood the request on all ports except the incoming port.
Pavlin Radoslavov5b5dc482014-11-05 14:48:08 -0800203 //
Jonathan Hart7d1496b2015-03-10 22:00:48 -0700204 flood(eth, inPort);
205 return;
Jonathan Hartdbdbdbb2014-10-06 18:35:30 -0700206 }
207
Kunihiro Ishigurof1bff502015-01-30 15:47:06 -0800208 private void replyNdp(Ethernet eth, ConnectPoint inPort) {
209
210 IPv6 ipv6 = (IPv6) eth.getPayload();
211 ICMP6 icmpv6 = (ICMP6) ipv6.getPayload();
212 NeighborSolicitation nsol = (NeighborSolicitation) icmpv6.getPayload();
Dusan Pajina22b9702015-02-12 16:25:23 +0100213 Ip6Address targetAddress = Ip6Address.valueOf(nsol.getTargetAddress());
Kunihiro Ishigurof1bff502015-01-30 15:47:06 -0800214
215 VlanId vlan = VlanId.vlanId(eth.getVlanID());
216
217 // If the request came from outside the network, only reply if it was
218 // for one of our external addresses.
219 if (isOutsidePort(inPort)) {
Kunihiro Ishigurof1bff502015-01-30 15:47:06 -0800220 Set<PortAddresses> addressSet =
221 hostService.getAddressBindingsForPort(inPort);
222
223 for (PortAddresses addresses : addressSet) {
224 for (InterfaceIpAddress ia : addresses.ipAddresses()) {
Dusan Pajina22b9702015-02-12 16:25:23 +0100225 if (ia.ipAddress().equals(targetAddress)) {
Kunihiro Ishigurof1bff502015-01-30 15:47:06 -0800226 Ethernet ndpReply =
Aaron Kruglikovd8123832015-07-06 14:20:25 -0700227 buildNdpReply(targetAddress, addresses.mac(), eth);
Kunihiro Ishigurof1bff502015-01-30 15:47:06 -0800228 sendTo(ndpReply, inPort);
229 }
230 }
231 }
232 return;
233 } else {
234 // If the source address matches one of our external addresses
235 // it could be a request from an internal host to an external
236 // address. Forward it over to the correct ports.
237 Ip6Address source =
Pavlin Radoslavovcef52062015-02-12 16:57:17 -0800238 Ip6Address.valueOf(ipv6.getSourceAddress());
Kunihiro Ishigurof1bff502015-01-30 15:47:06 -0800239 Set<PortAddresses> sourceAddresses = findPortsInSubnet(source);
240 boolean matched = false;
241 for (PortAddresses pa : sourceAddresses) {
242 for (InterfaceIpAddress ia : pa.ipAddresses()) {
243 if (ia.ipAddress().equals(source) &&
244 pa.vlan().equals(vlan)) {
245 matched = true;
246 sendTo(eth, pa.connectPoint());
Pavlin Radoslavovcef52062015-02-12 16:57:17 -0800247 break;
Kunihiro Ishigurof1bff502015-01-30 15:47:06 -0800248 }
249 }
250 }
251
252 if (matched) {
253 return;
254 }
255 }
256
257 // Continue with normal proxy ARP case
258
Dusan Pajina22b9702015-02-12 16:25:23 +0100259 Set<Host> hosts = hostService.getHostsByIp(targetAddress);
Kunihiro Ishigurof1bff502015-01-30 15:47:06 -0800260
261 Host dst = null;
262 Host src = hostService.getHost(HostId.hostId(eth.getSourceMAC(),
263 VlanId.vlanId(eth.getVlanID())));
264
265 for (Host host : hosts) {
266 if (host.vlan().equals(vlan)) {
267 dst = host;
268 break;
269 }
270 }
271
272 if (src == null || dst == null) {
Dusan Pajina22b9702015-02-12 16:25:23 +0100273 //
274 // The request couldn't be resolved.
275 // Flood the request on all ports except the incoming ports.
276 //
Kunihiro Ishigurof1bff502015-01-30 15:47:06 -0800277 flood(eth, inPort);
278 return;
279 }
280
281 //
Dusan Pajina22b9702015-02-12 16:25:23 +0100282 // Reply on the port the request was received on
Kunihiro Ishigurof1bff502015-01-30 15:47:06 -0800283 //
Dusan Pajina22b9702015-02-12 16:25:23 +0100284 Ethernet ndpReply = buildNdpReply(targetAddress, dst.mac(), eth);
285 sendTo(ndpReply, inPort);
Kunihiro Ishigurof1bff502015-01-30 15:47:06 -0800286 }
Aaron Kruglikovd8123832015-07-06 14:20:25 -0700287 //TODO checkpoint
Kunihiro Ishigurof1bff502015-01-30 15:47:06 -0800288
Jonathan Hartdbdbdbb2014-10-06 18:35:30 -0700289 /**
290 * Outputs the given packet out the given port.
291 *
Aaron Kruglikovd8123832015-07-06 14:20:25 -0700292 * @param packet the packet to send
Jonathan Hartdbdbdbb2014-10-06 18:35:30 -0700293 * @param outPort the port to send it out
294 */
295 private void sendTo(Ethernet packet, ConnectPoint outPort) {
Aaron Kruglikovd8123832015-07-06 14:20:25 -0700296 if (!edgeService.isEdgePoint(outPort)) {
Jonathan Hartdbdbdbb2014-10-06 18:35:30 -0700297 // Sanity check to make sure we don't send the packet out an
298 // internal port and create a loop (could happen due to
299 // misconfiguration).
300 return;
301 }
302
tom9a693fd2014-10-03 11:32:19 -0700303 TrafficTreatment.Builder builder = DefaultTrafficTreatment.builder();
Jonathan Hartdbdbdbb2014-10-06 18:35:30 -0700304 builder.setOutput(outPort.port());
305 packetService.emit(new DefaultOutboundPacket(outPort.deviceId(),
306 builder.build(), ByteBuffer.wrap(packet.serialize())));
307 }
308
309 /**
Jonathan Hart1f793a72014-11-12 23:22:02 -0800310 * Finds ports with an address in the subnet of the target address.
Jonathan Hartdbdbdbb2014-10-06 18:35:30 -0700311 *
Pavlin Radoslavov76b0ae22014-10-27 15:33:19 -0700312 * @param target the target address to find a matching port for
Jonathan Hart1f793a72014-11-12 23:22:02 -0800313 * @return a set of PortAddresses describing ports in the subnet
Jonathan Hartdbdbdbb2014-10-06 18:35:30 -0700314 */
Kunihiro Ishigurof1bff502015-01-30 15:47:06 -0800315 private Set<PortAddresses> findPortsInSubnet(IpAddress target) {
Aaron Kruglikovd8123832015-07-06 14:20:25 -0700316 Set<PortAddresses> result = new HashSet<>();
Jonathan Hartdbdbdbb2014-10-06 18:35:30 -0700317 for (PortAddresses addresses : hostService.getAddressBindings()) {
Aaron Kruglikovd8123832015-07-06 14:20:25 -0700318 result.addAll(addresses.ipAddresses().stream().filter(ia -> ia.subnetAddress().contains(target)).
319 map(ia -> addresses).collect(Collectors.toList()));
Jonathan Hartdbdbdbb2014-10-06 18:35:30 -0700320 }
Jonathan Hart1f793a72014-11-12 23:22:02 -0800321 return result;
Jonathan Hartdbdbdbb2014-10-06 18:35:30 -0700322 }
323
324 /**
325 * Returns whether the given port is an outside-facing port with an IP
326 * address configured.
327 *
328 * @param port the port to check
329 * @return true if the port is an outside-facing port, otherwise false
330 */
331 private boolean isOutsidePort(ConnectPoint port) {
Pavlin Radoslavov76b0ae22014-10-27 15:33:19 -0700332 //
333 // TODO: Is this sufficient to identify outside-facing ports: just
334 // having IP addresses on a port?
335 //
Jonathan Harta887ba82014-11-03 15:20:52 -0800336 return !hostService.getAddressBindingsForPort(port).isEmpty();
alshabibb5522ff2014-09-29 19:20:00 -0700337 }
338
339 @Override
Jonathan Hartf84591d2015-01-16 14:33:43 -0800340 public void forward(Ethernet eth, ConnectPoint inPort) {
Changhoon Yoon541ef712015-05-23 17:18:34 +0900341 checkPermission(Permission.PACKET_WRITE);
342
Yuta HIGUCHI59718042014-10-04 22:04:56 -0700343 checkNotNull(eth, REQUEST_NULL);
alshabibb5522ff2014-09-29 19:20:00 -0700344
345 Host h = hostService.getHost(HostId.hostId(eth.getDestinationMAC(),
346 VlanId.vlanId(eth.getVlanID())));
347
348 if (h == null) {
Jonathan Hartf84591d2015-01-16 14:33:43 -0800349 flood(eth, inPort);
alshabibb5522ff2014-09-29 19:20:00 -0700350 } else {
tom9a693fd2014-10-03 11:32:19 -0700351 TrafficTreatment.Builder builder = DefaultTrafficTreatment.builder();
alshabibb5522ff2014-09-29 19:20:00 -0700352 builder.setOutput(h.location().port());
353 packetService.emit(new DefaultOutboundPacket(h.location().deviceId(),
354 builder.build(), ByteBuffer.wrap(eth.serialize())));
355 }
356
357 }
358
alshabibc274c902014-10-03 14:58:27 -0700359 @Override
Kunihiro Ishigurof1bff502015-01-30 15:47:06 -0800360 public boolean handlePacket(PacketContext context) {
Changhoon Yoon541ef712015-05-23 17:18:34 +0900361 checkPermission(Permission.PACKET_WRITE);
362
alshabibc274c902014-10-03 14:58:27 -0700363 InboundPacket pkt = context.inPacket();
364 Ethernet ethPkt = pkt.parsed();
Kunihiro Ishigurof1bff502015-01-30 15:47:06 -0800365
366 if (ethPkt == null) {
367 return false;
368 }
369 if (ethPkt.getEtherType() == Ethernet.TYPE_ARP) {
370 return handleArp(context, ethPkt);
371 } else if (ethPkt.getEtherType() == Ethernet.TYPE_IPV6) {
372 return handleNdp(context, ethPkt);
alshabibc274c902014-10-03 14:58:27 -0700373 }
374 return false;
375 }
376
Kunihiro Ishigurof1bff502015-01-30 15:47:06 -0800377 private boolean handleArp(PacketContext context, Ethernet ethPkt) {
378 ARP arp = (ARP) ethPkt.getPayload();
379
380 if (arp.getOpCode() == ARP.OP_REPLY) {
381 forward(ethPkt, context.inPacket().receivedFrom());
382 } else if (arp.getOpCode() == ARP.OP_REQUEST) {
383 reply(ethPkt, context.inPacket().receivedFrom());
384 } else {
385 return false;
386 }
387 context.block();
388 return true;
389 }
390
391 private boolean handleNdp(PacketContext context, Ethernet ethPkt) {
392 IPv6 ipv6 = (IPv6) ethPkt.getPayload();
393
394 if (ipv6.getNextHeader() != IPv6.PROTOCOL_ICMP6) {
395 return false;
396 }
397 ICMP6 icmpv6 = (ICMP6) ipv6.getPayload();
398 if (icmpv6.getIcmpType() == ICMP6.NEIGHBOR_ADVERTISEMENT) {
399 forward(ethPkt, context.inPacket().receivedFrom());
400 } else if (icmpv6.getIcmpType() == ICMP6.NEIGHBOR_SOLICITATION) {
401 reply(ethPkt, context.inPacket().receivedFrom());
402 } else {
403 return false;
404 }
405 context.block();
406 return true;
407 }
408
alshabibb5522ff2014-09-29 19:20:00 -0700409 /**
410 * Flood the arp request at all edges in the network.
Dusan Pajina22b9702015-02-12 16:25:23 +0100411 *
412 * @param request the arp request
Aaron Kruglikovd8123832015-07-06 14:20:25 -0700413 * @param inPort the connect point the arp request was received on
alshabibb5522ff2014-09-29 19:20:00 -0700414 */
Jonathan Hartf84591d2015-01-16 14:33:43 -0800415 private void flood(Ethernet request, ConnectPoint inPort) {
alshabibb5522ff2014-09-29 19:20:00 -0700416 TrafficTreatment.Builder builder = null;
417 ByteBuffer buf = ByteBuffer.wrap(request.serialize());
418
Aaron Kruglikovd8123832015-07-06 14:20:25 -0700419 for (ConnectPoint connectPoint : edgeService.getEdgePoints()) {
420 if (isOutsidePort(connectPoint) || connectPoint.equals(inPort)) {
421 continue;
422 }
Jonathan Hartdbdbdbb2014-10-06 18:35:30 -0700423
Aaron Kruglikovd8123832015-07-06 14:20:25 -0700424 builder = DefaultTrafficTreatment.builder();
425 builder.setOutput(connectPoint.port());
426 packetService.emit(new DefaultOutboundPacket(connectPoint.deviceId(),
427 builder.build(), buf));
alshabibb5522ff2014-09-29 19:20:00 -0700428 }
429
430 }
431
alshabibb5522ff2014-09-29 19:20:00 -0700432 /**
Kunihiro Ishigurof1bff502015-01-30 15:47:06 -0800433 * Builds an Neighbor Discovery reply based on a request.
434 *
Aaron Kruglikovd8123832015-07-06 14:20:25 -0700435 * @param srcIp the IP address to use as the reply source
436 * @param srcMac the MAC address to use as the reply source
Kunihiro Ishigurof1bff502015-01-30 15:47:06 -0800437 * @param request the Neighbor Solicitation request we got
438 * @return an Ethernet frame containing the Neighbor Advertisement reply
439 */
440 private Ethernet buildNdpReply(Ip6Address srcIp, MacAddress srcMac,
441 Ethernet request) {
442
443 Ethernet eth = new Ethernet();
444 eth.setDestinationMACAddress(request.getSourceMAC());
445 eth.setSourceMACAddress(srcMac);
446 eth.setEtherType(Ethernet.TYPE_IPV6);
447 eth.setVlanID(request.getVlanID());
448
449 IPv6 requestIp = (IPv6) request.getPayload();
450 IPv6 ipv6 = new IPv6();
451 ipv6.setSourceAddress(srcIp.toOctets());
452 ipv6.setDestinationAddress(requestIp.getSourceAddress());
453 ipv6.setHopLimit((byte) 255);
Kunihiro Ishigurof1bff502015-01-30 15:47:06 -0800454
455 ICMP6 icmp6 = new ICMP6();
456 icmp6.setIcmpType(ICMP6.NEIGHBOR_ADVERTISEMENT);
457 icmp6.setIcmpCode((byte) 0);
Kunihiro Ishigurof1bff502015-01-30 15:47:06 -0800458
459 NeighborAdvertisement nadv = new NeighborAdvertisement();
Dusan Pajina22b9702015-02-12 16:25:23 +0100460 nadv.setTargetAddress(srcIp.toOctets());
Kunihiro Ishigurof1bff502015-01-30 15:47:06 -0800461 nadv.setSolicitedFlag((byte) 1);
462 nadv.setOverrideFlag((byte) 1);
Pavlin Radoslavova2626ef2015-02-18 18:33:25 -0800463 nadv.addOption(NeighborDiscoveryOptions.TYPE_TARGET_LL_ADDRESS,
Aaron Kruglikovd8123832015-07-06 14:20:25 -0700464 srcMac.toBytes());
Kunihiro Ishigurof1bff502015-01-30 15:47:06 -0800465
Pavlin Radoslavova2626ef2015-02-18 18:33:25 -0800466 icmp6.setPayload(nadv);
Dusan Pajina22b9702015-02-12 16:25:23 +0100467 ipv6.setPayload(icmp6);
468 eth.setPayload(ipv6);
Kunihiro Ishigurof1bff502015-01-30 15:47:06 -0800469 return eth;
470 }
alshabibb5522ff2014-09-29 19:20:00 -0700471}