mirror of
https://github.com/opennetworkinglab/onos.git
synced 2025-10-16 18:02:05 +02:00
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
This commit is contained in:
parent
9322445f11
commit
a22b970637
@ -25,6 +25,7 @@ import org.apache.felix.scr.annotations.Reference;
|
||||
import org.apache.felix.scr.annotations.ReferenceCardinality;
|
||||
import org.apache.felix.scr.annotations.Service;
|
||||
import org.onlab.packet.ARP;
|
||||
import org.onlab.packet.Data;
|
||||
import org.onlab.packet.Ethernet;
|
||||
import org.onlab.packet.ICMP6;
|
||||
import org.onlab.packet.IPv6;
|
||||
@ -141,22 +142,21 @@ public class ProxyArpManager implements ProxyArpService {
|
||||
ARP arp = (ARP) eth.getPayload();
|
||||
checkArgument(arp.getOpCode() == ARP.OP_REQUEST, NOT_ARP_REQUEST);
|
||||
checkNotNull(inPort);
|
||||
Ip4Address targetAddress = Ip4Address.valueOf(arp.getTargetProtocolAddress());
|
||||
|
||||
VlanId vlan = VlanId.vlanId(eth.getVlanID());
|
||||
|
||||
// If the request came from outside the network, only reply if it was
|
||||
// for one of our external addresses.
|
||||
if (isOutsidePort(inPort)) {
|
||||
Ip4Address target =
|
||||
Ip4Address.valueOf(arp.getTargetProtocolAddress());
|
||||
Set<PortAddresses> addressSet =
|
||||
hostService.getAddressBindingsForPort(inPort);
|
||||
|
||||
for (PortAddresses addresses : addressSet) {
|
||||
for (InterfaceIpAddress ia : addresses.ipAddresses()) {
|
||||
if (ia.ipAddress().equals(target)) {
|
||||
if (ia.ipAddress().equals(targetAddress)) {
|
||||
Ethernet arpReply =
|
||||
buildArpReply(target, addresses.mac(), eth);
|
||||
buildArpReply(targetAddress, addresses.mac(), eth);
|
||||
sendTo(arpReply, inPort);
|
||||
}
|
||||
}
|
||||
@ -187,8 +187,7 @@ public class ProxyArpManager implements ProxyArpService {
|
||||
|
||||
// Continue with normal proxy ARP case
|
||||
|
||||
Set<Host> hosts = hostService.getHostsByIp(
|
||||
Ip4Address.valueOf(arp.getTargetProtocolAddress()));
|
||||
Set<Host> hosts = hostService.getHostsByIp(targetAddress);
|
||||
|
||||
Host dst = null;
|
||||
Host src = hostService.getHost(HostId.hostId(eth.getSourceMAC(),
|
||||
@ -202,23 +201,19 @@ public class ProxyArpManager implements ProxyArpService {
|
||||
}
|
||||
|
||||
if (src == null || dst == null) {
|
||||
//
|
||||
// The request couldn't be resolved.
|
||||
// Flood the request on all ports except the incoming ports.
|
||||
//
|
||||
flood(eth, inPort);
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// TODO find the correct IP address.
|
||||
// Right now we use the first IPv4 address that is found.
|
||||
// Reply on the port the request was received on
|
||||
//
|
||||
for (IpAddress ipAddress : dst.ipAddresses()) {
|
||||
Ip4Address ip4Address = ipAddress.getIp4Address();
|
||||
if (ip4Address != null) {
|
||||
Ethernet arpReply = buildArpReply(ip4Address, dst.mac(), eth);
|
||||
// TODO: check send status with host service.
|
||||
sendTo(arpReply, src.location());
|
||||
break;
|
||||
}
|
||||
}
|
||||
Ethernet arpReply = buildArpReply(targetAddress, dst.mac(), eth);
|
||||
sendTo(arpReply, inPort);
|
||||
}
|
||||
|
||||
private void replyNdp(Ethernet eth, ConnectPoint inPort) {
|
||||
@ -226,22 +221,21 @@ public class ProxyArpManager implements ProxyArpService {
|
||||
IPv6 ipv6 = (IPv6) eth.getPayload();
|
||||
ICMP6 icmpv6 = (ICMP6) ipv6.getPayload();
|
||||
NeighborSolicitation nsol = (NeighborSolicitation) icmpv6.getPayload();
|
||||
Ip6Address targetAddress = Ip6Address.valueOf(nsol.getTargetAddress());
|
||||
|
||||
VlanId vlan = VlanId.vlanId(eth.getVlanID());
|
||||
|
||||
// If the request came from outside the network, only reply if it was
|
||||
// for one of our external addresses.
|
||||
if (isOutsidePort(inPort)) {
|
||||
Ip6Address target =
|
||||
Ip6Address.valueOf(nsol.getTargetAddress());
|
||||
Set<PortAddresses> addressSet =
|
||||
hostService.getAddressBindingsForPort(inPort);
|
||||
|
||||
for (PortAddresses addresses : addressSet) {
|
||||
for (InterfaceIpAddress ia : addresses.ipAddresses()) {
|
||||
if (ia.ipAddress().equals(target)) {
|
||||
if (ia.ipAddress().equals(targetAddress)) {
|
||||
Ethernet ndpReply =
|
||||
buildNdpReply(target, addresses.mac(), eth);
|
||||
buildNdpReply(targetAddress, addresses.mac(), eth);
|
||||
sendTo(ndpReply, inPort);
|
||||
}
|
||||
}
|
||||
@ -272,8 +266,7 @@ public class ProxyArpManager implements ProxyArpService {
|
||||
|
||||
// Continue with normal proxy ARP case
|
||||
|
||||
Set<Host> hosts = hostService.getHostsByIp(
|
||||
Ip6Address.valueOf(nsol.getTargetAddress()));
|
||||
Set<Host> hosts = hostService.getHostsByIp(targetAddress);
|
||||
|
||||
Host dst = null;
|
||||
Host src = hostService.getHost(HostId.hostId(eth.getSourceMAC(),
|
||||
@ -287,23 +280,19 @@ public class ProxyArpManager implements ProxyArpService {
|
||||
}
|
||||
|
||||
if (src == null || dst == null) {
|
||||
//
|
||||
// The request couldn't be resolved.
|
||||
// Flood the request on all ports except the incoming ports.
|
||||
//
|
||||
flood(eth, inPort);
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// TODO find the correct IP address.
|
||||
// Right now we use the first IPv4 address that is found.
|
||||
// Reply on the port the request was received on
|
||||
//
|
||||
for (IpAddress ipAddress : dst.ipAddresses()) {
|
||||
Ip6Address ip6Address = ipAddress.getIp6Address();
|
||||
if (ip6Address != null) {
|
||||
Ethernet arpReply = buildNdpReply(ip6Address, dst.mac(), eth);
|
||||
// TODO: check send status with host service.
|
||||
sendTo(arpReply, src.location());
|
||||
break;
|
||||
}
|
||||
}
|
||||
Ethernet ndpReply = buildNdpReply(targetAddress, dst.mac(), eth);
|
||||
sendTo(ndpReply, inPort);
|
||||
}
|
||||
|
||||
|
||||
@ -429,7 +418,9 @@ public class ProxyArpManager implements ProxyArpService {
|
||||
|
||||
/**
|
||||
* Flood the arp request at all edges in the network.
|
||||
* @param request the arp request.
|
||||
*
|
||||
* @param request the arp request
|
||||
* @param inPort the connect point the arp request was received on
|
||||
*/
|
||||
private void flood(Ethernet request, ConnectPoint inPort) {
|
||||
TrafficTreatment.Builder builder = null;
|
||||
@ -519,6 +510,7 @@ public class ProxyArpManager implements ProxyArpService {
|
||||
arp.setTargetProtocolAddress(((ARP) request.getPayload())
|
||||
.getSenderProtocolAddress());
|
||||
arp.setSenderProtocolAddress(srcIp.toInt());
|
||||
|
||||
eth.setPayload(arp);
|
||||
return eth;
|
||||
}
|
||||
@ -545,19 +537,32 @@ public class ProxyArpManager implements ProxyArpService {
|
||||
ipv6.setSourceAddress(srcIp.toOctets());
|
||||
ipv6.setDestinationAddress(requestIp.getSourceAddress());
|
||||
ipv6.setHopLimit((byte) 255);
|
||||
eth.setPayload(ipv6);
|
||||
|
||||
ICMP6 icmp6 = new ICMP6();
|
||||
icmp6.setIcmpType(ICMP6.NEIGHBOR_ADVERTISEMENT);
|
||||
icmp6.setIcmpCode((byte) 0);
|
||||
ipv6.setPayload(icmp6);
|
||||
|
||||
NeighborAdvertisement nadv = new NeighborAdvertisement();
|
||||
nadv.setTargetAddress(srcMac.toBytes());
|
||||
nadv.setTargetAddress(srcIp.toOctets());
|
||||
nadv.setSolicitedFlag((byte) 1);
|
||||
nadv.setOverrideFlag((byte) 1);
|
||||
byte[] nadvData =
|
||||
new byte[NeighborAdvertisement.OPTION_LENGTH_IEEE802_ADDRESS];
|
||||
ByteBuffer bbNadv = ByteBuffer.wrap(nadvData);
|
||||
byte nadvOptionType =
|
||||
NeighborAdvertisement.OPTION_TYPE_TARGET_LL_ADDRESS;
|
||||
// The Option length in 8-octets units
|
||||
byte nadvOptionLength =
|
||||
(NeighborAdvertisement.OPTION_LENGTH_IEEE802_ADDRESS + 7) / 8;
|
||||
bbNadv.put(nadvOptionType);
|
||||
bbNadv.put(nadvOptionLength);
|
||||
bbNadv.put(srcMac.toBytes());
|
||||
Data nadvPayload = new Data();
|
||||
nadv.setPayload(nadvPayload.deserialize(nadvData, 0, nadvData.length));
|
||||
icmp6.setPayload(nadv);
|
||||
|
||||
ipv6.setPayload(icmp6);
|
||||
eth.setPayload(ipv6);
|
||||
return eth;
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014 Open Networking Laboratory
|
||||
* Copyright 2014-2015 Open Networking Laboratory
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -13,9 +13,6 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
package org.onlab.packet.ndp;
|
||||
|
||||
import org.onlab.packet.BasePacket;
|
||||
@ -27,10 +24,16 @@ import java.nio.ByteBuffer;
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* Implements ICMPv6 Neighbor Advertisement packet format. (RFC 4861)
|
||||
* Implements ICMPv6 Neighbor Advertisement packet format (RFC 4861).
|
||||
*/
|
||||
public class NeighborAdvertisement extends BasePacket {
|
||||
public static final byte HEADER_LENGTH = 20; // bytes
|
||||
public static final byte OPTION_TYPE_SOURCE_LL_ADDRESS = 1;
|
||||
public static final byte OPTION_TYPE_TARGET_LL_ADDRESS = 2;
|
||||
public static final byte OPTION_TYPE_PREFIX_INFORMATION = 3;
|
||||
public static final byte OPTION_TYPE_REDIRECTED_HEADER = 4;
|
||||
public static final byte OPTION_TYPE_MTU = 5;
|
||||
public static final byte OPTION_LENGTH_IEEE802_ADDRESS = 8;
|
||||
|
||||
protected byte routerFlag;
|
||||
protected byte solicitedFlag;
|
||||
|
Loading…
x
Reference in New Issue
Block a user