Committed by
Ray Milkey
ProxyArpManager - fix IPv6 ND Adv issue with Option fields and ARP/NDP Reply
with first IP address from Host service This fixes ONOS-1010 Also, add protocol-related constants to class NeighborAdvertisement. Change-Id: Iacf9e48a8a03a86e1cc4e89e7e2b2b4ccc4a7e3a
Showing
2 changed files
with
51 additions
and
43 deletions
... | @@ -25,6 +25,7 @@ import org.apache.felix.scr.annotations.Reference; | ... | @@ -25,6 +25,7 @@ import org.apache.felix.scr.annotations.Reference; |
25 | import org.apache.felix.scr.annotations.ReferenceCardinality; | 25 | import org.apache.felix.scr.annotations.ReferenceCardinality; |
26 | import org.apache.felix.scr.annotations.Service; | 26 | import org.apache.felix.scr.annotations.Service; |
27 | import org.onlab.packet.ARP; | 27 | import org.onlab.packet.ARP; |
28 | +import org.onlab.packet.Data; | ||
28 | import org.onlab.packet.Ethernet; | 29 | import org.onlab.packet.Ethernet; |
29 | import org.onlab.packet.ICMP6; | 30 | import org.onlab.packet.ICMP6; |
30 | import org.onlab.packet.IPv6; | 31 | import org.onlab.packet.IPv6; |
... | @@ -141,22 +142,21 @@ public class ProxyArpManager implements ProxyArpService { | ... | @@ -141,22 +142,21 @@ public class ProxyArpManager implements ProxyArpService { |
141 | ARP arp = (ARP) eth.getPayload(); | 142 | ARP arp = (ARP) eth.getPayload(); |
142 | checkArgument(arp.getOpCode() == ARP.OP_REQUEST, NOT_ARP_REQUEST); | 143 | checkArgument(arp.getOpCode() == ARP.OP_REQUEST, NOT_ARP_REQUEST); |
143 | checkNotNull(inPort); | 144 | checkNotNull(inPort); |
145 | + Ip4Address targetAddress = Ip4Address.valueOf(arp.getTargetProtocolAddress()); | ||
144 | 146 | ||
145 | VlanId vlan = VlanId.vlanId(eth.getVlanID()); | 147 | VlanId vlan = VlanId.vlanId(eth.getVlanID()); |
146 | 148 | ||
147 | // If the request came from outside the network, only reply if it was | 149 | // If the request came from outside the network, only reply if it was |
148 | // for one of our external addresses. | 150 | // for one of our external addresses. |
149 | if (isOutsidePort(inPort)) { | 151 | if (isOutsidePort(inPort)) { |
150 | - Ip4Address target = | ||
151 | - Ip4Address.valueOf(arp.getTargetProtocolAddress()); | ||
152 | Set<PortAddresses> addressSet = | 152 | Set<PortAddresses> addressSet = |
153 | hostService.getAddressBindingsForPort(inPort); | 153 | hostService.getAddressBindingsForPort(inPort); |
154 | 154 | ||
155 | for (PortAddresses addresses : addressSet) { | 155 | for (PortAddresses addresses : addressSet) { |
156 | for (InterfaceIpAddress ia : addresses.ipAddresses()) { | 156 | for (InterfaceIpAddress ia : addresses.ipAddresses()) { |
157 | - if (ia.ipAddress().equals(target)) { | 157 | + if (ia.ipAddress().equals(targetAddress)) { |
158 | Ethernet arpReply = | 158 | Ethernet arpReply = |
159 | - buildArpReply(target, addresses.mac(), eth); | 159 | + buildArpReply(targetAddress, addresses.mac(), eth); |
160 | sendTo(arpReply, inPort); | 160 | sendTo(arpReply, inPort); |
161 | } | 161 | } |
162 | } | 162 | } |
... | @@ -187,8 +187,7 @@ public class ProxyArpManager implements ProxyArpService { | ... | @@ -187,8 +187,7 @@ public class ProxyArpManager implements ProxyArpService { |
187 | 187 | ||
188 | // Continue with normal proxy ARP case | 188 | // Continue with normal proxy ARP case |
189 | 189 | ||
190 | - Set<Host> hosts = hostService.getHostsByIp( | 190 | + Set<Host> hosts = hostService.getHostsByIp(targetAddress); |
191 | - Ip4Address.valueOf(arp.getTargetProtocolAddress())); | ||
192 | 191 | ||
193 | Host dst = null; | 192 | Host dst = null; |
194 | Host src = hostService.getHost(HostId.hostId(eth.getSourceMAC(), | 193 | Host src = hostService.getHost(HostId.hostId(eth.getSourceMAC(), |
... | @@ -202,23 +201,19 @@ public class ProxyArpManager implements ProxyArpService { | ... | @@ -202,23 +201,19 @@ public class ProxyArpManager implements ProxyArpService { |
202 | } | 201 | } |
203 | 202 | ||
204 | if (src == null || dst == null) { | 203 | if (src == null || dst == null) { |
204 | + // | ||
205 | + // The request couldn't be resolved. | ||
206 | + // Flood the request on all ports except the incoming ports. | ||
207 | + // | ||
205 | flood(eth, inPort); | 208 | flood(eth, inPort); |
206 | return; | 209 | return; |
207 | } | 210 | } |
208 | 211 | ||
209 | // | 212 | // |
210 | - // TODO find the correct IP address. | 213 | + // Reply on the port the request was received on |
211 | - // Right now we use the first IPv4 address that is found. | ||
212 | // | 214 | // |
213 | - for (IpAddress ipAddress : dst.ipAddresses()) { | 215 | + Ethernet arpReply = buildArpReply(targetAddress, dst.mac(), eth); |
214 | - Ip4Address ip4Address = ipAddress.getIp4Address(); | 216 | + sendTo(arpReply, inPort); |
215 | - if (ip4Address != null) { | ||
216 | - Ethernet arpReply = buildArpReply(ip4Address, dst.mac(), eth); | ||
217 | - // TODO: check send status with host service. | ||
218 | - sendTo(arpReply, src.location()); | ||
219 | - break; | ||
220 | - } | ||
221 | - } | ||
222 | } | 217 | } |
223 | 218 | ||
224 | private void replyNdp(Ethernet eth, ConnectPoint inPort) { | 219 | private void replyNdp(Ethernet eth, ConnectPoint inPort) { |
... | @@ -226,22 +221,21 @@ public class ProxyArpManager implements ProxyArpService { | ... | @@ -226,22 +221,21 @@ public class ProxyArpManager implements ProxyArpService { |
226 | IPv6 ipv6 = (IPv6) eth.getPayload(); | 221 | IPv6 ipv6 = (IPv6) eth.getPayload(); |
227 | ICMP6 icmpv6 = (ICMP6) ipv6.getPayload(); | 222 | ICMP6 icmpv6 = (ICMP6) ipv6.getPayload(); |
228 | NeighborSolicitation nsol = (NeighborSolicitation) icmpv6.getPayload(); | 223 | NeighborSolicitation nsol = (NeighborSolicitation) icmpv6.getPayload(); |
224 | + Ip6Address targetAddress = Ip6Address.valueOf(nsol.getTargetAddress()); | ||
229 | 225 | ||
230 | VlanId vlan = VlanId.vlanId(eth.getVlanID()); | 226 | VlanId vlan = VlanId.vlanId(eth.getVlanID()); |
231 | 227 | ||
232 | // If the request came from outside the network, only reply if it was | 228 | // If the request came from outside the network, only reply if it was |
233 | // for one of our external addresses. | 229 | // for one of our external addresses. |
234 | if (isOutsidePort(inPort)) { | 230 | if (isOutsidePort(inPort)) { |
235 | - Ip6Address target = | ||
236 | - Ip6Address.valueOf(nsol.getTargetAddress()); | ||
237 | Set<PortAddresses> addressSet = | 231 | Set<PortAddresses> addressSet = |
238 | hostService.getAddressBindingsForPort(inPort); | 232 | hostService.getAddressBindingsForPort(inPort); |
239 | 233 | ||
240 | for (PortAddresses addresses : addressSet) { | 234 | for (PortAddresses addresses : addressSet) { |
241 | for (InterfaceIpAddress ia : addresses.ipAddresses()) { | 235 | for (InterfaceIpAddress ia : addresses.ipAddresses()) { |
242 | - if (ia.ipAddress().equals(target)) { | 236 | + if (ia.ipAddress().equals(targetAddress)) { |
243 | Ethernet ndpReply = | 237 | Ethernet ndpReply = |
244 | - buildNdpReply(target, addresses.mac(), eth); | 238 | + buildNdpReply(targetAddress, addresses.mac(), eth); |
245 | sendTo(ndpReply, inPort); | 239 | sendTo(ndpReply, inPort); |
246 | } | 240 | } |
247 | } | 241 | } |
... | @@ -272,8 +266,7 @@ public class ProxyArpManager implements ProxyArpService { | ... | @@ -272,8 +266,7 @@ public class ProxyArpManager implements ProxyArpService { |
272 | 266 | ||
273 | // Continue with normal proxy ARP case | 267 | // Continue with normal proxy ARP case |
274 | 268 | ||
275 | - Set<Host> hosts = hostService.getHostsByIp( | 269 | + Set<Host> hosts = hostService.getHostsByIp(targetAddress); |
276 | - Ip6Address.valueOf(nsol.getTargetAddress())); | ||
277 | 270 | ||
278 | Host dst = null; | 271 | Host dst = null; |
279 | Host src = hostService.getHost(HostId.hostId(eth.getSourceMAC(), | 272 | Host src = hostService.getHost(HostId.hostId(eth.getSourceMAC(), |
... | @@ -287,23 +280,19 @@ public class ProxyArpManager implements ProxyArpService { | ... | @@ -287,23 +280,19 @@ public class ProxyArpManager implements ProxyArpService { |
287 | } | 280 | } |
288 | 281 | ||
289 | if (src == null || dst == null) { | 282 | if (src == null || dst == null) { |
283 | + // | ||
284 | + // The request couldn't be resolved. | ||
285 | + // Flood the request on all ports except the incoming ports. | ||
286 | + // | ||
290 | flood(eth, inPort); | 287 | flood(eth, inPort); |
291 | return; | 288 | return; |
292 | } | 289 | } |
293 | 290 | ||
294 | // | 291 | // |
295 | - // TODO find the correct IP address. | 292 | + // Reply on the port the request was received on |
296 | - // Right now we use the first IPv4 address that is found. | ||
297 | // | 293 | // |
298 | - for (IpAddress ipAddress : dst.ipAddresses()) { | 294 | + Ethernet ndpReply = buildNdpReply(targetAddress, dst.mac(), eth); |
299 | - Ip6Address ip6Address = ipAddress.getIp6Address(); | 295 | + sendTo(ndpReply, inPort); |
300 | - if (ip6Address != null) { | ||
301 | - Ethernet arpReply = buildNdpReply(ip6Address, dst.mac(), eth); | ||
302 | - // TODO: check send status with host service. | ||
303 | - sendTo(arpReply, src.location()); | ||
304 | - break; | ||
305 | - } | ||
306 | - } | ||
307 | } | 296 | } |
308 | 297 | ||
309 | 298 | ||
... | @@ -429,7 +418,9 @@ public class ProxyArpManager implements ProxyArpService { | ... | @@ -429,7 +418,9 @@ public class ProxyArpManager implements ProxyArpService { |
429 | 418 | ||
430 | /** | 419 | /** |
431 | * Flood the arp request at all edges in the network. | 420 | * Flood the arp request at all edges in the network. |
432 | - * @param request the arp request. | 421 | + * |
422 | + * @param request the arp request | ||
423 | + * @param inPort the connect point the arp request was received on | ||
433 | */ | 424 | */ |
434 | private void flood(Ethernet request, ConnectPoint inPort) { | 425 | private void flood(Ethernet request, ConnectPoint inPort) { |
435 | TrafficTreatment.Builder builder = null; | 426 | TrafficTreatment.Builder builder = null; |
... | @@ -519,6 +510,7 @@ public class ProxyArpManager implements ProxyArpService { | ... | @@ -519,6 +510,7 @@ public class ProxyArpManager implements ProxyArpService { |
519 | arp.setTargetProtocolAddress(((ARP) request.getPayload()) | 510 | arp.setTargetProtocolAddress(((ARP) request.getPayload()) |
520 | .getSenderProtocolAddress()); | 511 | .getSenderProtocolAddress()); |
521 | arp.setSenderProtocolAddress(srcIp.toInt()); | 512 | arp.setSenderProtocolAddress(srcIp.toInt()); |
513 | + | ||
522 | eth.setPayload(arp); | 514 | eth.setPayload(arp); |
523 | return eth; | 515 | return eth; |
524 | } | 516 | } |
... | @@ -545,19 +537,32 @@ public class ProxyArpManager implements ProxyArpService { | ... | @@ -545,19 +537,32 @@ public class ProxyArpManager implements ProxyArpService { |
545 | ipv6.setSourceAddress(srcIp.toOctets()); | 537 | ipv6.setSourceAddress(srcIp.toOctets()); |
546 | ipv6.setDestinationAddress(requestIp.getSourceAddress()); | 538 | ipv6.setDestinationAddress(requestIp.getSourceAddress()); |
547 | ipv6.setHopLimit((byte) 255); | 539 | ipv6.setHopLimit((byte) 255); |
548 | - eth.setPayload(ipv6); | ||
549 | 540 | ||
550 | ICMP6 icmp6 = new ICMP6(); | 541 | ICMP6 icmp6 = new ICMP6(); |
551 | icmp6.setIcmpType(ICMP6.NEIGHBOR_ADVERTISEMENT); | 542 | icmp6.setIcmpType(ICMP6.NEIGHBOR_ADVERTISEMENT); |
552 | icmp6.setIcmpCode((byte) 0); | 543 | icmp6.setIcmpCode((byte) 0); |
553 | - ipv6.setPayload(icmp6); | ||
554 | 544 | ||
555 | NeighborAdvertisement nadv = new NeighborAdvertisement(); | 545 | NeighborAdvertisement nadv = new NeighborAdvertisement(); |
556 | - nadv.setTargetAddress(srcMac.toBytes()); | 546 | + nadv.setTargetAddress(srcIp.toOctets()); |
557 | nadv.setSolicitedFlag((byte) 1); | 547 | nadv.setSolicitedFlag((byte) 1); |
558 | nadv.setOverrideFlag((byte) 1); | 548 | nadv.setOverrideFlag((byte) 1); |
549 | + byte[] nadvData = | ||
550 | + new byte[NeighborAdvertisement.OPTION_LENGTH_IEEE802_ADDRESS]; | ||
551 | + ByteBuffer bbNadv = ByteBuffer.wrap(nadvData); | ||
552 | + byte nadvOptionType = | ||
553 | + NeighborAdvertisement.OPTION_TYPE_TARGET_LL_ADDRESS; | ||
554 | + // The Option length in 8-octets units | ||
555 | + byte nadvOptionLength = | ||
556 | + (NeighborAdvertisement.OPTION_LENGTH_IEEE802_ADDRESS + 7) / 8; | ||
557 | + bbNadv.put(nadvOptionType); | ||
558 | + bbNadv.put(nadvOptionLength); | ||
559 | + bbNadv.put(srcMac.toBytes()); | ||
560 | + Data nadvPayload = new Data(); | ||
561 | + nadv.setPayload(nadvPayload.deserialize(nadvData, 0, nadvData.length)); | ||
559 | icmp6.setPayload(nadv); | 562 | icmp6.setPayload(nadv); |
560 | 563 | ||
564 | + ipv6.setPayload(icmp6); | ||
565 | + eth.setPayload(ipv6); | ||
561 | return eth; | 566 | return eth; |
562 | } | 567 | } |
563 | 568 | ... | ... |
1 | /* | 1 | /* |
2 | - * Copyright 2014 Open Networking Laboratory | 2 | + * Copyright 2014-2015 Open Networking Laboratory |
3 | * | 3 | * |
4 | * Licensed under the Apache License, Version 2.0 (the "License"); | 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
5 | * you may not use this file except in compliance with the License. | 5 | * you may not use this file except in compliance with the License. |
... | @@ -13,9 +13,6 @@ | ... | @@ -13,9 +13,6 @@ |
13 | * See the License for the specific language governing permissions and | 13 | * See the License for the specific language governing permissions and |
14 | * limitations under the License. | 14 | * limitations under the License. |
15 | */ | 15 | */ |
16 | - | ||
17 | - | ||
18 | - | ||
19 | package org.onlab.packet.ndp; | 16 | package org.onlab.packet.ndp; |
20 | 17 | ||
21 | import org.onlab.packet.BasePacket; | 18 | import org.onlab.packet.BasePacket; |
... | @@ -27,10 +24,16 @@ import java.nio.ByteBuffer; | ... | @@ -27,10 +24,16 @@ import java.nio.ByteBuffer; |
27 | import java.util.Arrays; | 24 | import java.util.Arrays; |
28 | 25 | ||
29 | /** | 26 | /** |
30 | - * Implements ICMPv6 Neighbor Advertisement packet format. (RFC 4861) | 27 | + * Implements ICMPv6 Neighbor Advertisement packet format (RFC 4861). |
31 | */ | 28 | */ |
32 | public class NeighborAdvertisement extends BasePacket { | 29 | public class NeighborAdvertisement extends BasePacket { |
33 | public static final byte HEADER_LENGTH = 20; // bytes | 30 | public static final byte HEADER_LENGTH = 20; // bytes |
31 | + public static final byte OPTION_TYPE_SOURCE_LL_ADDRESS = 1; | ||
32 | + public static final byte OPTION_TYPE_TARGET_LL_ADDRESS = 2; | ||
33 | + public static final byte OPTION_TYPE_PREFIX_INFORMATION = 3; | ||
34 | + public static final byte OPTION_TYPE_REDIRECTED_HEADER = 4; | ||
35 | + public static final byte OPTION_TYPE_MTU = 5; | ||
36 | + public static final byte OPTION_LENGTH_IEEE802_ADDRESS = 8; | ||
34 | 37 | ||
35 | protected byte routerFlag; | 38 | protected byte routerFlag; |
36 | protected byte solicitedFlag; | 39 | protected byte solicitedFlag; | ... | ... |
-
Please register or login to post a comment