blob: a42a80613364921dcd5408618d8fd418fbffca32 [file] [log] [blame]
sangho80f11cb2015-04-01 13:05:26 -07001/*
Brian O'Connor43b53542016-04-09 01:19:45 -07002 * Copyright 2015-present Open Networking Laboratory
sangho80f11cb2015-04-01 13:05:26 -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 */
16package org.onosproject.segmentrouting;
17
sangho80f11cb2015-04-01 13:05:26 -070018import org.onlab.packet.Ethernet;
19import org.onlab.packet.ICMP;
Pier Ventreb6b81d52016-12-02 08:16:05 -080020import org.onlab.packet.ICMP6;
sangho80f11cb2015-04-01 13:05:26 -070021import org.onlab.packet.IPv4;
Pier Ventreb6b81d52016-12-02 08:16:05 -080022import org.onlab.packet.IPv6;
sangho80f11cb2015-04-01 13:05:26 -070023import org.onlab.packet.Ip4Address;
Pier Ventre1a655962016-11-28 16:48:06 -080024import org.onlab.packet.Ip6Address;
Pier Ventreadb4ae62016-11-23 09:57:42 -080025import org.onlab.packet.IpAddress;
sangho80f11cb2015-04-01 13:05:26 -070026import org.onlab.packet.IpPrefix;
27import org.onlab.packet.MPLS;
Pier Ventre1a655962016-11-28 16:48:06 -080028import org.onlab.packet.MacAddress;
29import org.onlab.packet.VlanId;
Pier Ventreb6b81d52016-12-02 08:16:05 -080030import org.onlab.packet.ndp.NeighborSolicitation;
Pier Ventreb6a7f342016-11-26 21:05:22 -080031import org.onosproject.incubator.net.neighbour.NeighbourMessageContext;
Pier Ventre1a655962016-11-28 16:48:06 -080032import org.onosproject.incubator.net.neighbour.NeighbourMessageType;
sangho80f11cb2015-04-01 13:05:26 -070033import org.onosproject.net.ConnectPoint;
34import org.onosproject.net.DeviceId;
35import org.onosproject.net.flow.DefaultTrafficTreatment;
36import org.onosproject.net.flow.TrafficTreatment;
Pier Ventre1a655962016-11-28 16:48:06 -080037import org.onosproject.net.host.HostService;
sangho80f11cb2015-04-01 13:05:26 -070038import org.onosproject.net.packet.DefaultOutboundPacket;
sangho80f11cb2015-04-01 13:05:26 -070039import org.onosproject.net.packet.OutboundPacket;
Charles Chan319d1a22015-11-03 10:42:14 -080040import org.onosproject.segmentrouting.config.DeviceConfigNotFoundException;
Pier Ventre1a655962016-11-28 16:48:06 -080041import org.onosproject.segmentrouting.config.SegmentRoutingAppConfig;
sangho80f11cb2015-04-01 13:05:26 -070042import org.slf4j.Logger;
43import org.slf4j.LoggerFactory;
44
Jonathan Hartd53ebc42015-04-07 16:46:33 -070045import java.nio.ByteBuffer;
Charles Chand3727b72017-03-13 13:10:30 -070046import java.util.Arrays;
Saurav Dasc28b3432015-10-30 17:45:38 -070047import java.util.Set;
Jonathan Hartd53ebc42015-04-07 16:46:33 -070048
Charles Chanb7f75ac2016-01-11 18:28:54 -080049/**
50 * Handler of ICMP packets that responses or forwards ICMP packets that
51 * are sent to the controller.
52 */
Pier Ventreb6b81d52016-12-02 08:16:05 -080053public class IcmpHandler extends SegmentRoutingNeighbourHandler {
sangho80f11cb2015-04-01 13:05:26 -070054
55 private static Logger log = LoggerFactory.getLogger(IcmpHandler.class);
sangho80f11cb2015-04-01 13:05:26 -070056
57 /**
58 * Creates an IcmpHandler object.
59 *
60 * @param srManager SegmentRoutingManager object
61 */
62 public IcmpHandler(SegmentRoutingManager srManager) {
Pier Ventreb6b81d52016-12-02 08:16:05 -080063 super(srManager);
64 }
65
66 /**
67 * Utility function to send packet out.
68 *
69 * @param outport the output port
70 * @param payload the packet to send
71 * @param sid the segment id
72 * @param destIpAddress the destination ip address
73 * @param allowedHops the hop limit/ttl
74 */
75 private void sendPacketOut(ConnectPoint outport,
76 Ethernet payload,
77 int sid,
78 IpAddress destIpAddress,
79 byte allowedHops) {
80 int destSid;
81 if (destIpAddress.isIp4()) {
82 destSid = config.getIPv4SegmentId(payload.getDestinationMAC());
83 } else {
84 destSid = config.getIPv6SegmentId(payload.getDestinationMAC());
85 }
86
87 if (sid == -1 || destSid == sid ||
88 config.inSameSubnet(outport.deviceId(), destIpAddress)) {
89 TrafficTreatment treatment = DefaultTrafficTreatment.builder().
90 setOutput(outport.port()).build();
91 OutboundPacket packet = new DefaultOutboundPacket(outport.deviceId(),
92 treatment, ByteBuffer.wrap(payload.serialize()));
93 srManager.packetService.emit(packet);
94 } else {
95 log.debug("Send a MPLS packet as a ICMP response");
96 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
97 .setOutput(outport.port())
98 .build();
99
100 payload.setEtherType(Ethernet.MPLS_UNICAST);
101 MPLS mplsPkt = new MPLS();
102 mplsPkt.setLabel(sid);
103 mplsPkt.setTtl(allowedHops);
104 mplsPkt.setPayload(payload.getPayload());
105 payload.setPayload(mplsPkt);
106
107 OutboundPacket packet = new DefaultOutboundPacket(outport.deviceId(),
108 treatment, ByteBuffer.wrap(payload.serialize()));
109
110 srManager.packetService.emit(packet);
111 }
sangho80f11cb2015-04-01 13:05:26 -0700112 }
113
Pier Ventre1a655962016-11-28 16:48:06 -0800114 //////////////////////////////////////
115 // ICMP Echo/Reply Protocol //
116 //////////////////////////////////////
117
sangho80f11cb2015-04-01 13:05:26 -0700118 /**
119 * Process incoming ICMP packet.
120 * If it is an ICMP request to router or known host, then sends an ICMP response.
121 * If it is an ICMP packet to known host and forward the packet to the host.
122 * If it is an ICMP packet to unknown host in a subnet, then sends an ARP request
123 * to the subnet.
124 *
Pier Ventreb6b81d52016-12-02 08:16:05 -0800125 * @param eth inbound ICMP packet
126 * @param inPort the input port
sangho80f11cb2015-04-01 13:05:26 -0700127 */
Pier Ventreb6b81d52016-12-02 08:16:05 -0800128 public void processIcmp(Ethernet eth, ConnectPoint inPort) {
129 DeviceId deviceId = inPort.deviceId();
130 IPv4 ipv4Packet = (IPv4) eth.getPayload();
131 Ip4Address destinationAddress = Ip4Address.valueOf(ipv4Packet.getDestinationAddress());
Pier Ventreb6a7f342016-11-26 21:05:22 -0800132 Set<IpAddress> gatewayIpAddresses = config.getPortIPs(deviceId);
Pier Ventreadb4ae62016-11-23 09:57:42 -0800133 IpAddress routerIp;
Charles Chan319d1a22015-11-03 10:42:14 -0800134 try {
Pier Ventreadb4ae62016-11-23 09:57:42 -0800135 routerIp = config.getRouterIpv4(deviceId);
Charles Chan319d1a22015-11-03 10:42:14 -0800136 } catch (DeviceConfigNotFoundException e) {
137 log.warn(e.getMessage() + " Aborting processPacketIn.");
138 return;
139 }
sangho80f11cb2015-04-01 13:05:26 -0700140 // ICMP to the router IP or gateway IP
Pier Ventreb6b81d52016-12-02 08:16:05 -0800141 if (((ICMP) ipv4Packet.getPayload()).getIcmpType() == ICMP.TYPE_ECHO_REQUEST &&
142 (destinationAddress.equals(routerIp.getIp4Address()) ||
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700143 gatewayIpAddresses.contains(destinationAddress))) {
Pier Ventreb6b81d52016-12-02 08:16:05 -0800144 sendIcmpResponse(eth, inPort);
145 // We remove the packet from the queue
146 srManager.ipHandler.dequeuePacket(ipv4Packet, destinationAddress);
sangho80f11cb2015-04-01 13:05:26 -0700147
148 // ICMP for any known host
149 } else if (!srManager.hostService.getHostsByIp(destinationAddress).isEmpty()) {
Saurav Das2d94d312015-11-24 23:21:05 -0800150 // TODO: known host packet should not be coming to controller - resend flows?
sangho80f11cb2015-04-01 13:05:26 -0700151 srManager.ipHandler.forwardPackets(deviceId, destinationAddress);
152
153 // ICMP for an unknown host in the subnet of the router
154 } else if (config.inSameSubnet(deviceId, destinationAddress)) {
Pier Ventreb6b81d52016-12-02 08:16:05 -0800155 srManager.arpHandler.sendArpRequest(deviceId, destinationAddress, inPort);
sangho80f11cb2015-04-01 13:05:26 -0700156
157 // ICMP for an unknown host
158 } else {
159 log.debug("ICMP request for unknown host {} ", destinationAddress);
Pier Ventreb6b81d52016-12-02 08:16:05 -0800160 // We remove the packet from the queue
161 srManager.ipHandler.dequeuePacket(ipv4Packet, destinationAddress);
sangho80f11cb2015-04-01 13:05:26 -0700162 }
163 }
164
Charles Chanf4586112015-11-09 16:37:23 -0800165 /**
166 * Sends an ICMP reply message.
167 *
168 * Note: we assume that packets sending from the edge switches to the hosts
169 * have untagged VLAN.
170 * @param icmpRequest the original ICMP request
171 * @param outport the output port where the ICMP reply should be sent to
172 */
Pier Ventreadb4ae62016-11-23 09:57:42 -0800173 private void sendIcmpResponse(Ethernet icmpRequest, ConnectPoint outport) {
Charles Chanf4586112015-11-09 16:37:23 -0800174 // Note: We assume that packets arrive at the edge switches have
175 // untagged VLAN.
Pier Ventreb6b81d52016-12-02 08:16:05 -0800176 Ethernet icmpReplyEth = ICMP.buildIcmpReply(icmpRequest);
sangho80f11cb2015-04-01 13:05:26 -0700177 IPv4 icmpRequestIpv4 = (IPv4) icmpRequest.getPayload();
Pier Ventreb6b81d52016-12-02 08:16:05 -0800178 IPv4 icmpReplyIpv4 = (IPv4) icmpReplyEth.getPayload();
179 Ip4Address destIpAddress = Ip4Address.valueOf(icmpRequestIpv4.getSourceAddress());
sangho9b169e32015-04-14 16:27:13 -0700180 Ip4Address destRouterAddress = config.getRouterIpAddressForASubnetHost(destIpAddress);
Pier Ventreadb4ae62016-11-23 09:57:42 -0800181 int destSid = config.getIPv4SegmentId(destRouterAddress);
Charles Chan70661362016-12-09 12:54:49 -0800182 if (destSid < 0) {
Pier Ventreb6b81d52016-12-02 08:16:05 -0800183 log.warn("Cannot find the Segment ID for {}", destIpAddress);
sangho80f11cb2015-04-01 13:05:26 -0700184 return;
185 }
Pier Ventreb6b81d52016-12-02 08:16:05 -0800186 sendPacketOut(outport, icmpReplyEth, destSid, destIpAddress, icmpReplyIpv4.getTtl());
sangho80f11cb2015-04-01 13:05:26 -0700187 }
188
Pier Ventreb6b81d52016-12-02 08:16:05 -0800189 ///////////////////////////////////////////
190 // ICMPv6 Echo/Reply Protocol //
191 ///////////////////////////////////////////
sangho80f11cb2015-04-01 13:05:26 -0700192
Pier Ventreb6b81d52016-12-02 08:16:05 -0800193 /**
194 * Process incoming ICMPv6 packet.
195 * If it is an ICMP request to router or known host, then sends an ICMP response.
196 * If it is an ICMP packet to known host and forward the packet to the host.
197 * If it is an ICMP packet to unknown host in a subnet, then sends an ARP request
198 * to the subnet.
199 *
200 * @param eth the incoming ICMPv6 packet
201 * @param inPort the input port
202 */
203 public void processIcmpv6(Ethernet eth, ConnectPoint inPort) {
204 DeviceId deviceId = inPort.deviceId();
205 IPv6 ipv6Packet = (IPv6) eth.getPayload();
206 Ip6Address destinationAddress = Ip6Address.valueOf(ipv6Packet.getDestinationAddress());
207 Set<IpAddress> gatewayIpAddresses = config.getPortIPs(deviceId);
208 IpAddress routerIp;
209 try {
210 routerIp = config.getRouterIpv6(deviceId);
211 } catch (DeviceConfigNotFoundException e) {
212 log.warn(e.getMessage() + " Aborting processPacketIn.");
213 return;
sangho80f11cb2015-04-01 13:05:26 -0700214 }
Pier Ventreb6b81d52016-12-02 08:16:05 -0800215 ICMP6 icmp6 = (ICMP6) ipv6Packet.getPayload();
216 // ICMP to the router IP or gateway IP
217 if (icmp6.getIcmpType() == ICMP6.ECHO_REQUEST &&
218 (destinationAddress.equals(routerIp.getIp6Address()) ||
219 gatewayIpAddresses.contains(destinationAddress))) {
220 sendIcmpv6Response(eth, inPort);
221 // We remove the packet from the queue
222 srManager.ipHandler.dequeuePacket(ipv6Packet, destinationAddress);
223 // ICMP for any known host
224 } else if (!srManager.hostService.getHostsByIp(destinationAddress).isEmpty()) {
225 // TODO: known host packet should not be coming to controller - resend flows?
226 srManager.ipHandler.forwardPackets(deviceId, destinationAddress);
227 // ICMP for an unknown host in the subnet of the router
228 } else if (config.inSameSubnet(deviceId, destinationAddress)) {
229 sendNdpRequest(deviceId, destinationAddress, inPort);
230 // ICMP for an unknown host or not configured host
231 } else {
232 log.debug("ICMPv6 request for unknown host or not configured host {} ", destinationAddress);
233 // We remove the packet from the queue
234 srManager.ipHandler.dequeuePacket(ipv6Packet, destinationAddress);
235 }
236 }
237
238 /**
239 * Sends an ICMPv6 reply message.
240 *
241 * Note: we assume that packets sending from the edge switches to the hosts
242 * have untagged VLAN.
243 * @param ethRequest the original ICMP request
244 * @param outport the output port where the ICMP reply should be sent to
245 */
246 private void sendIcmpv6Response(Ethernet ethRequest, ConnectPoint outport) {
247 // Note: We assume that packets arrive at the edge switches have
248 // untagged VLAN.
249 Ethernet ethReply = ICMP6.buildIcmp6Reply(ethRequest);
250 IPv6 icmpRequestIpv6 = (IPv6) ethRequest.getPayload();
251 IPv6 icmpReplyIpv6 = (IPv6) ethRequest.getPayload();
252 Ip6Address destIpAddress = Ip6Address.valueOf(icmpRequestIpv6.getSourceAddress());
253 Ip6Address destRouterAddress = config.getRouterIpAddressForASubnetHost(destIpAddress);
254 int sid = config.getIPv6SegmentId(destRouterAddress);
255 if (sid < 0) {
256 log.warn("Cannot find the Segment ID for {}", destIpAddress);
257 return;
258 }
259 sendPacketOut(outport, ethReply, sid, destIpAddress, icmpReplyIpv6.getHopLimit());
sangho80f11cb2015-04-01 13:05:26 -0700260 }
sangho9b169e32015-04-14 16:27:13 -0700261
Pier Ventre1a655962016-11-28 16:48:06 -0800262 ///////////////////////////////////////////
263 // ICMPv6 Neighbour Discovery Protocol //
264 ///////////////////////////////////////////
sangho9b169e32015-04-14 16:27:13 -0700265
Pier Ventre1a655962016-11-28 16:48:06 -0800266 /**
267 * Process incoming NDP packet.
268 *
269 * If it is an NDP request for the router or for the gateway, then sends a NDP reply.
270 * If it is an NDP request to unknown host flood in the subnet.
271 * If it is an NDP packet to known host forward the packet to the host.
272 *
273 * FIXME If the NDP packets use link local addresses we fail.
274 *
275 * @param pkt inbound packet
276 * @param hostService the host service
277 */
278 public void processPacketIn(NeighbourMessageContext pkt, HostService hostService) {
279 /*
280 * First we validate the ndp packet
281 */
282 SegmentRoutingAppConfig appConfig = srManager.cfgService
283 .getConfig(srManager.appId, SegmentRoutingAppConfig.class);
284 if (appConfig != null && appConfig.suppressSubnet().contains(pkt.inPort())) {
285 // Ignore NDP packets come from suppressed ports
286 pkt.drop();
287 return;
288 }
289 if (!validateSrcIp(pkt)) {
290 log.debug("Ignore NDP packet discovered on {} with unexpected src ip address {}.",
291 pkt.inPort(), pkt.sender());
292 pkt.drop();
293 return;
294 }
295
296 if (pkt.type() == NeighbourMessageType.REQUEST) {
297 handleNdpRequest(pkt, hostService);
298 } else {
299 handleNdpReply(pkt, hostService);
300 }
301
302 }
303
304 /**
305 * Utility function to verify if the src ip belongs to the same
306 * subnet configured on the port it is seen.
307 *
308 * @param pkt the ndp packet and context information
309 * @return true if the src ip is a valid address for the subnet configured
310 * for the connect point
311 */
312 private boolean validateSrcIp(NeighbourMessageContext pkt) {
313 ConnectPoint connectPoint = pkt.inPort();
314 IpPrefix subnet = config.getPortIPv6Subnet(
315 connectPoint.deviceId(),
316 connectPoint.port()
Pier Luigi6a2643a2017-01-31 09:35:05 -0800317 );
Pier Ventre1a655962016-11-28 16:48:06 -0800318 return subnet != null && subnet.contains(pkt.sender());
319 }
320
321 /**
322 * Helper method to handle the ndp requests.
323 *
324 * @param pkt the ndp packet request and context information
325 * @param hostService the host service
326 */
327 private void handleNdpRequest(NeighbourMessageContext pkt, HostService hostService) {
Charles Chanb3016ed2017-02-27 15:50:43 -0800328 // ND request for the gateway. We have to reply on behalf of the gateway.
Pier Ventre1a655962016-11-28 16:48:06 -0800329 if (isNdpForGateway(pkt)) {
330 log.debug("Sending NDP reply on behalf of the router");
Pier Ventreb6b81d52016-12-02 08:16:05 -0800331 sendResponse(pkt, config.getRouterMacForAGatewayIp(pkt.target()), hostService);
Pier Ventre1a655962016-11-28 16:48:06 -0800332 } else {
Charles Chanb3016ed2017-02-27 15:50:43 -0800333 // NOTE: Ignore NDP packets except those target for the router
334 // We will reconsider enabling this when we have host learning support
Pier Ventre1a655962016-11-28 16:48:06 -0800335 /*
Charles Chanb3016ed2017-02-27 15:50:43 -0800336 // ND request for an host. We do a search by Ip.
Pier Ventre1a655962016-11-28 16:48:06 -0800337 Set<Host> hosts = hostService.getHostsByIp(pkt.target());
Charles Chanb3016ed2017-02-27 15:50:43 -0800338 // Possible misconfiguration ? In future this case
339 // should be handled we can have same hosts in different VLANs.
Pier Ventre1a655962016-11-28 16:48:06 -0800340 if (hosts.size() > 1) {
341 log.warn("More than one host with IP {}", pkt.target());
342 }
343 Host targetHost = hosts.stream().findFirst().orElse(null);
Charles Chanb3016ed2017-02-27 15:50:43 -0800344 // If we know the host forward to its attachment point.
Pier Ventre1a655962016-11-28 16:48:06 -0800345 if (targetHost != null) {
346 log.debug("Forward NDP request to the target host");
347 pkt.forward(targetHost.location());
348 } else {
Charles Chanb3016ed2017-02-27 15:50:43 -0800349 // Flood otherwise.
Pier Ventre1a655962016-11-28 16:48:06 -0800350 log.debug("Flood NDP request to the target subnet");
351 flood(pkt);
352 }
Charles Chanb3016ed2017-02-27 15:50:43 -0800353 */
Pier Ventre1a655962016-11-28 16:48:06 -0800354 }
355 }
356
357 /**
358 * Helper method to handle the ndp replies.
359 *
360 * @param pkt the ndp packet reply and context information
361 * @param hostService the host service
362 */
363 private void handleNdpReply(NeighbourMessageContext pkt, HostService hostService) {
364 if (isNdpForGateway(pkt)) {
365 log.debug("Forwarding all the ip packets we stored");
366 Ip6Address hostIpAddress = pkt.sender().getIp6Address();
367 srManager.ipHandler.forwardPackets(pkt.inPort().deviceId(), hostIpAddress);
368 } else {
Charles Chanb3016ed2017-02-27 15:50:43 -0800369 // NOTE: Ignore NDP packets except those target for the router
370 // We will reconsider enabling this when we have host learning support
371 /*
Pier Ventre1a655962016-11-28 16:48:06 -0800372 HostId hostId = HostId.hostId(pkt.dstMac(), pkt.vlan());
373 Host targetHost = hostService.getHost(hostId);
374 if (targetHost != null) {
375 log.debug("Forwarding the reply to the host");
376 pkt.forward(targetHost.location());
377 } else {
Charles Chanb3016ed2017-02-27 15:50:43 -0800378 // We don't have to flood towards spine facing ports.
Charles Chan10b0fb72017-02-02 16:20:42 -0800379 if (pkt.vlan().equals(SegmentRoutingManager.INTERNAL_VLAN)) {
Pier Ventre1a655962016-11-28 16:48:06 -0800380 return;
381 }
382 log.debug("Flooding the reply to the subnet");
383 flood(pkt);
384 }
Charles Chanb3016ed2017-02-27 15:50:43 -0800385 */
Pier Ventre1a655962016-11-28 16:48:06 -0800386 }
387 }
388
389 /**
390 * Utility to verify if the ND are for the gateway.
391 *
392 * @param pkt the ndp packet
393 * @return true if the ndp is for the gateway. False otherwise
394 */
395 private boolean isNdpForGateway(NeighbourMessageContext pkt) {
396 DeviceId deviceId = pkt.inPort().deviceId();
397 Set<IpAddress> gatewayIpAddresses = null;
398 try {
399 if (pkt.target().equals(config.getRouterIpv6(deviceId))) {
400 return true;
401 }
402 gatewayIpAddresses = config.getPortIPs(deviceId);
403 } catch (DeviceConfigNotFoundException e) {
404 log.warn(e.getMessage() + " Aborting check for router IP in processing ndp");
405 }
Charles Chand3727b72017-03-13 13:10:30 -0700406
407 return gatewayIpAddresses != null && gatewayIpAddresses.stream()
408 .filter(IpAddress::isIp6)
409 .anyMatch(gatewayIp -> gatewayIp.equals(pkt.target()) ||
410 Arrays.equals(IPv6.getSolicitNodeAddress(gatewayIp.toOctets()),
411 pkt.target().toOctets())
412 );
Pier Ventre1a655962016-11-28 16:48:06 -0800413 }
414
415 /**
Pier Ventreb6b81d52016-12-02 08:16:05 -0800416 * Sends a NDP request for the target IP address to all ports except in-port.
Pier Ventre1a655962016-11-28 16:48:06 -0800417 *
Pier Ventreb6b81d52016-12-02 08:16:05 -0800418 * @param deviceId Switch device ID
419 * @param targetAddress target IP address for ARP
420 * @param inPort in-port
Pier Ventre1a655962016-11-28 16:48:06 -0800421 */
Pier Ventreb6b81d52016-12-02 08:16:05 -0800422 public void sendNdpRequest(DeviceId deviceId, IpAddress targetAddress, ConnectPoint inPort) {
423 byte[] senderMacAddress = new byte[MacAddress.MAC_ADDRESS_LENGTH];
424 byte[] senderIpAddress = new byte[Ip6Address.BYTE_LENGTH];
425 /*
426 * Retrieves device info.
427 */
Pier Luigi6a83c4a2017-01-29 12:38:48 -0800428 if (!getSenderInfo(senderMacAddress, senderIpAddress, deviceId, targetAddress)) {
429 log.warn("Aborting sendNdpRequest, we cannot get all the information needed");
430 return;
431 }
Pier Ventreb6b81d52016-12-02 08:16:05 -0800432 /*
433 * We have to compute the dst mac address and dst
434 * ip address.
435 */
436 byte[] dstIp = IPv6.getSolicitNodeAddress(targetAddress.toOctets());
437 byte[] dstMac = IPv6.getMCastMacAddress(dstIp);
438 /*
439 * Creates the request.
440 */
441 Ethernet ndpRequest = NeighborSolicitation.buildNdpSolicit(
442 targetAddress.toOctets(),
443 senderIpAddress,
444 dstIp,
445 senderMacAddress,
446 dstMac,
447 VlanId.NONE
448 );
449 flood(ndpRequest, inPort, targetAddress);
Pier Ventre1a655962016-11-28 16:48:06 -0800450 }
sangho80f11cb2015-04-01 13:05:26 -0700451}