Adding ability to synchronize topology clusters' broadcast trees.
Proxy ARP now supports deferred ARP replies until instance learns of the subject host location.
Change-Id: Ib3ee97c0812858b5b4972d945e9e6d2bd397d4c5
diff --git a/core/net/src/main/java/org/onosproject/net/proxyarp/impl/ProxyArpManager.java b/core/net/src/main/java/org/onosproject/net/proxyarp/impl/ProxyArpManager.java
index ecfb71c..b5acde6 100644
--- a/core/net/src/main/java/org/onosproject/net/proxyarp/impl/ProxyArpManager.java
+++ b/core/net/src/main/java/org/onosproject/net/proxyarp/impl/ProxyArpManager.java
@@ -36,7 +36,6 @@
import org.onosproject.core.Permission;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.Host;
-import org.onosproject.net.HostId;
import org.onosproject.net.device.DeviceService;
import org.onosproject.net.edge.EdgePortService;
import org.onosproject.net.flow.DefaultTrafficTreatment;
@@ -50,6 +49,7 @@
import org.onosproject.net.packet.PacketContext;
import org.onosproject.net.packet.PacketService;
import org.onosproject.net.proxyarp.ProxyArpService;
+import org.onosproject.net.proxyarp.ProxyArpStore;
import org.slf4j.Logger;
import java.nio.ByteBuffer;
@@ -59,6 +59,8 @@
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
+import static org.onlab.packet.VlanId.vlanId;
+import static org.onosproject.net.HostId.hostId;
import static org.onosproject.security.AppGuard.checkPermission;
import static org.slf4j.LoggerFactory.getLogger;
@@ -90,25 +92,29 @@
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected DeviceService deviceService;
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected ProxyArpStore store;
+
/**
* Listens to both device service and link service to determine
* whether a port is internal or external.
*/
@Activate
public void activate() {
+ store.setDelegate(this::sendTo);
log.info("Started");
}
@Deactivate
public void deactivate() {
+ store.setDelegate(null);
log.info("Stopped");
}
@Override
public boolean isKnown(IpAddress addr) {
checkPermission(Permission.PACKET_READ);
-
checkNotNull(addr, MAC_ADDR_NULL);
Set<Host> hosts = hostService.getHostsByIp(addr);
return !hosts.isEmpty();
@@ -117,7 +123,6 @@
@Override
public void reply(Ethernet eth, ConnectPoint inPort) {
checkPermission(Permission.PACKET_WRITE);
-
checkNotNull(eth, REQUEST_NULL);
if (eth.getEtherType() == Ethernet.TYPE_ARP) {
@@ -133,7 +138,7 @@
checkNotNull(inPort);
Ip4Address targetAddress = Ip4Address.valueOf(arp.getTargetProtocolAddress());
- VlanId vlan = VlanId.vlanId(eth.getVlanID());
+ VlanId vlan = vlanId(eth.getVlanID());
if (isOutsidePort(inPort)) {
// If the request came from outside the network, only reply if it was
@@ -158,8 +163,8 @@
Set<Host> hosts = hostService.getHostsByIp(targetAddress);
Host dst = null;
- Host src = hostService.getHost(HostId.hostId(eth.getSourceMAC(),
- VlanId.vlanId(eth.getVlanID())));
+ Host src = hostService.getHost(hostId(eth.getSourceMAC(),
+ vlanId(eth.getVlanID())));
for (Host host : hosts) {
if (host.vlan().equals(vlan)) {
@@ -202,17 +207,15 @@
// Flood the request on all ports except the incoming port.
//
flood(eth, inPort);
- return;
}
private void replyNdp(Ethernet eth, ConnectPoint inPort) {
-
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());
+ VlanId vlan = vlanId(eth.getVlanID());
// If the request came from outside the network, only reply if it was
// for one of our external addresses.
@@ -259,8 +262,8 @@
Set<Host> hosts = hostService.getHostsByIp(targetAddress);
Host dst = null;
- Host src = hostService.getHost(HostId.hostId(eth.getSourceMAC(),
- VlanId.vlanId(eth.getVlanID())));
+ Host src = hostService.getHost(hostId(eth.getSourceMAC(),
+ vlanId(eth.getVlanID())));
for (Host host : hosts) {
if (host.vlan().equals(vlan)) {
@@ -293,6 +296,10 @@
* @param outPort the port to send it out
*/
private void sendTo(Ethernet packet, ConnectPoint outPort) {
+ sendTo(outPort, ByteBuffer.wrap(packet.serialize()));
+ }
+
+ private void sendTo(ConnectPoint outPort, ByteBuffer packet) {
if (!edgeService.isEdgePoint(outPort)) {
// Sanity check to make sure we don't send the packet out an
// internal port and create a loop (could happen due to
@@ -303,7 +310,7 @@
TrafficTreatment.Builder builder = DefaultTrafficTreatment.builder();
builder.setOutput(outPort.port());
packetService.emit(new DefaultOutboundPacket(outPort.deviceId(),
- builder.build(), ByteBuffer.wrap(packet.serialize())));
+ builder.build(), packet));
}
/**
@@ -329,31 +336,25 @@
* @return true if the port is an outside-facing port, otherwise false
*/
private boolean isOutsidePort(ConnectPoint port) {
- //
- // TODO: Is this sufficient to identify outside-facing ports: just
- // having IP addresses on a port?
- //
+ // TODO: Is this sufficient to identify outside-facing ports: just having IP addresses on a port?
return !hostService.getAddressBindingsForPort(port).isEmpty();
}
@Override
public void forward(Ethernet eth, ConnectPoint inPort) {
checkPermission(Permission.PACKET_WRITE);
-
checkNotNull(eth, REQUEST_NULL);
- Host h = hostService.getHost(HostId.hostId(eth.getDestinationMAC(),
- VlanId.vlanId(eth.getVlanID())));
+ Host h = hostService.getHost(hostId(eth.getDestinationMAC(),
+ vlanId(eth.getVlanID())));
if (h == null) {
flood(eth, inPort);
} else {
- TrafficTreatment.Builder builder = DefaultTrafficTreatment.builder();
- builder.setOutput(h.location().port());
- packetService.emit(new DefaultOutboundPacket(h.location().deviceId(),
- builder.build(), ByteBuffer.wrap(eth.serialize())));
+ Host subject = hostService.getHost(hostId(eth.getSourceMAC(),
+ vlanId(eth.getVlanID())));
+ store.forward(h.location(), subject, ByteBuffer.wrap(eth.serialize()));
}
-
}
@Override
@@ -424,7 +425,7 @@
builder = DefaultTrafficTreatment.builder();
builder.setOutput(connectPoint.port());
packetService.emit(new DefaultOutboundPacket(connectPoint.deviceId(),
- builder.build(), buf));
+ builder.build(), buf));
}
}
@@ -439,7 +440,6 @@
*/
private Ethernet buildNdpReply(Ip6Address srcIp, MacAddress srcMac,
Ethernet request) {
-
Ethernet eth = new Ethernet();
eth.setDestinationMACAddress(request.getSourceMAC());
eth.setSourceMACAddress(srcMac);
@@ -461,7 +461,7 @@
nadv.setSolicitedFlag((byte) 1);
nadv.setOverrideFlag((byte) 1);
nadv.addOption(NeighborDiscoveryOptions.TYPE_TARGET_LL_ADDRESS,
- srcMac.toBytes());
+ srcMac.toBytes());
icmp6.setPayload(nadv);
ipv6.setPayload(icmp6);
diff --git a/core/net/src/test/java/org/onosproject/net/proxyarp/impl/ProxyArpManagerTest.java b/core/net/src/test/java/org/onosproject/net/proxyarp/impl/ProxyArpManagerTest.java
index 4a1c446..e96602b 100644
--- a/core/net/src/test/java/org/onosproject/net/proxyarp/impl/ProxyArpManagerTest.java
+++ b/core/net/src/test/java/org/onosproject/net/proxyarp/impl/ProxyArpManagerTest.java
@@ -38,6 +38,8 @@
import org.onosproject.net.device.DeviceListener;
import org.onosproject.net.device.DeviceService;
import org.onosproject.net.edgeservice.impl.EdgeManager;
+import org.onosproject.net.flow.DefaultTrafficTreatment;
+import org.onosproject.net.flow.TrafficTreatment;
import org.onosproject.net.flow.instructions.Instruction;
import org.onosproject.net.flow.instructions.Instructions.OutputInstruction;
import org.onosproject.net.host.HostService;
@@ -45,24 +47,22 @@
import org.onosproject.net.host.PortAddresses;
import org.onosproject.net.link.LinkListener;
import org.onosproject.net.link.LinkService;
+import org.onosproject.net.packet.DefaultOutboundPacket;
import org.onosproject.net.packet.OutboundPacket;
import org.onosproject.net.packet.PacketServiceAdapter;
import org.onosproject.net.provider.ProviderId;
+import org.onosproject.net.proxyarp.ProxyArpStore;
+import org.onosproject.net.proxyarp.ProxyArpStoreDelegate;
+import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Set;
-import static org.easymock.EasyMock.anyObject;
-import static org.easymock.EasyMock.createMock;
-import static org.easymock.EasyMock.expect;
-import static org.easymock.EasyMock.replay;
-import static org.junit.Assert.assertArrayEquals;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
+import static org.easymock.EasyMock.*;
+import static org.junit.Assert.*;
/**
* Tests for the {@link ProxyArpManager} class.
@@ -110,6 +110,7 @@
proxyArp = new ProxyArpManager();
packetService = new TestPacketService();
proxyArp.packetService = packetService;
+ proxyArp.store = new TestProxyArpStoreAdapter();
proxyArp.edgeService = new TestEdgePortService();
@@ -455,8 +456,11 @@
public void testForwardToHost() {
Host host1 = new DefaultHost(PID, HID1, MAC1, VLAN1, LOC1,
Collections.singleton(IP1));
+ Host host2 = new DefaultHost(PID, HID2, MAC2, VLAN1, LOC2,
+ Collections.singleton(IP2));
expect(hostService.getHost(HID1)).andReturn(host1);
+ expect(hostService.getHost(HID2)).andReturn(host2);
replay(hostService);
Ethernet arpRequest = buildArp(ARP.OP_REPLY, MAC2, MAC1, IP2, IP1);
@@ -625,4 +629,16 @@
return getEdgePointsNoArg;
}
}
+
+ private class TestProxyArpStoreAdapter implements ProxyArpStore {
+ @Override
+ public void forward(ConnectPoint outPort, Host subject, ByteBuffer packet) {
+ TrafficTreatment tt = DefaultTrafficTreatment.builder().setOutput(outPort.port()).build();
+ packetService.emit(new DefaultOutboundPacket(outPort.deviceId(), tt, packet));
+ }
+
+ @Override
+ public void setDelegate(ProxyArpStoreDelegate delegate) {
+ }
+ }
}