Refactored packet broadcasting framework. Previously only ARP packets were being broadcasted, but as part of reactive forwarding we need to broadcast all packets that we don't know where to send. This commit refactors the Hazelcast notification system used to tell other instances to send packet-outs.
diff --git a/src/main/java/net/onrc/onos/datagrid/HazelcastDatagrid.java b/src/main/java/net/onrc/onos/datagrid/HazelcastDatagrid.java
index 6483121..4a48acf 100644
--- a/src/main/java/net/onrc/onos/datagrid/HazelcastDatagrid.java
+++ b/src/main/java/net/onrc/onos/datagrid/HazelcastDatagrid.java
@@ -18,8 +18,10 @@
import net.floodlightcontroller.restserver.IRestApiService;
import net.onrc.onos.datagrid.web.DatagridWebRoutable;
import net.onrc.onos.ofcontroller.flowmanager.IFlowEventHandlerService;
-import net.onrc.onos.ofcontroller.proxyarp.ArpMessage;
-import net.onrc.onos.ofcontroller.proxyarp.IArpEventHandler;
+import net.onrc.onos.ofcontroller.proxyarp.ArpReplyNotification;
+import net.onrc.onos.ofcontroller.proxyarp.IArpReplyEventHandler;
+import net.onrc.onos.ofcontroller.proxyarp.IPacketOutEventHandler;
+import net.onrc.onos.ofcontroller.proxyarp.PacketOutNotification;
import net.onrc.onos.ofcontroller.topology.TopologyElement;
import net.onrc.onos.ofcontroller.util.FlowEntry;
import net.onrc.onos.ofcontroller.util.FlowEntryId;
@@ -79,11 +81,16 @@
private MapTopologyListener mapTopologyListener = null;
private String mapTopologyListenerId = null;
- // State related to the ARP map
- protected static final String arpMapName = "arpMap";
- private IMap<ArpMessage, byte[]> arpMap = null;
- private List<IArpEventHandler> arpEventHandlers = new ArrayList<IArpEventHandler>();
+ // State related to the packet out map
+ protected static final String packetOutMapName = "packetOutMap";
+ private IMap<PacketOutNotification, byte[]> packetOutMap = null;
+ private List<IPacketOutEventHandler> packetOutEventHandlers = new ArrayList<IPacketOutEventHandler>();
private final byte[] dummyByte = {0};
+
+ // State related to the ARP reply map
+ protected static final String arpReplyMapName = "arpReplyMap";
+ private IMap<ArpReplyNotification, byte[]> arpReplyMap = null;
+ private List<IArpReplyEventHandler> arpReplyEventHandlers = new ArrayList<IArpReplyEventHandler>();
/**
* Class for receiving notifications for Flow state.
@@ -305,34 +312,22 @@
}
/**
- * Class for receiving notifications for ARP requests.
+ * Class for receiving notifications for sending packet-outs.
*
* The datagrid map is:
- * - Key: Request ID (String)
- * - Value: ARP request packet (byte[])
+ * - Key: Packet-out to send (PacketOutNotification)
+ * - Value: dummy value (we only need the key) (byte[])
*/
- class ArpMapListener implements EntryListener<ArpMessage, byte[]> {
+ class PacketOutMapListener implements EntryListener<PacketOutNotification, byte[]> {
/**
* Receive a notification that an entry is added.
*
* @param event the notification event for the entry.
*/
- public void entryAdded(EntryEvent<ArpMessage, byte[]> event) {
- for (IArpEventHandler arpEventHandler : arpEventHandlers) {
- arpEventHandler.arpRequestNotification(event.getKey());
+ public void entryAdded(EntryEvent<PacketOutNotification, byte[]> event) {
+ for (IPacketOutEventHandler packetOutEventHandler : packetOutEventHandlers) {
+ packetOutEventHandler.packetOutNotification(event.getKey());
}
-
- //
- // Decode the value and deliver the notification
- //
- /*
- Kryo kryo = kryoFactory.newKryo();
- Input input = new Input(valueBytes);
- TopologyElement topologyElement =
- kryo.readObject(input, TopologyElement.class);
- kryoFactory.deleteKryo(kryo);
- flowEventHandlerService.notificationRecvTopologyElementAdded(topologyElement);
- */
}
/**
@@ -340,7 +335,7 @@
*
* @param event the notification event for the entry.
*/
- public void entryRemoved(EntryEvent<ArpMessage, byte[]> event) {
+ public void entryRemoved(EntryEvent<PacketOutNotification, byte[]> event) {
// Not used
}
@@ -349,7 +344,7 @@
*
* @param event the notification event for the entry.
*/
- public void entryUpdated(EntryEvent<ArpMessage, byte[]> event) {
+ public void entryUpdated(EntryEvent<PacketOutNotification, byte[]> event) {
// Not used
}
@@ -358,10 +353,35 @@
*
* @param event the notification event for the entry.
*/
- public void entryEvicted(EntryEvent<ArpMessage, byte[]> event) {
+ public void entryEvicted(EntryEvent<PacketOutNotification, byte[]> event) {
// Not used
}
}
+
+ /**
+ * Class for receiving notifications for sending packet-outs.
+ *
+ * The datagrid map is:
+ * - Key: Packet-out to send (PacketOutNotification)
+ * - Value: dummy value (we only need the key) (byte[])
+ */
+ class ArpReplyMapListener implements EntryListener<ArpReplyNotification, byte[]> {
+ /**
+ * Receive a notification that an entry is added.
+ *
+ * @param event the notification event for the entry.
+ */
+ public void entryAdded(EntryEvent<ArpReplyNotification, byte[]> event) {
+ for (IArpReplyEventHandler arpReplyEventHandler : arpReplyEventHandlers) {
+ arpReplyEventHandler.arpReplyEvent(event.getKey());
+ }
+ }
+
+ // These methods aren't used for ARP replies
+ public void entryRemoved(EntryEvent<ArpReplyNotification, byte[]> event) {}
+ public void entryUpdated(EntryEvent<ArpReplyNotification, byte[]> event) {}
+ public void entryEvicted(EntryEvent<ArpReplyNotification, byte[]> event) {}
+ }
/**
* Initialize the Hazelcast Datagrid operation.
@@ -478,8 +498,11 @@
restApi.addRestletRoutable(new DatagridWebRoutable());
- arpMap = hazelcastInstance.getMap(arpMapName);
- arpMap.addEntryListener(new ArpMapListener(), true);
+ packetOutMap = hazelcastInstance.getMap(packetOutMapName);
+ packetOutMap.addEntryListener(new PacketOutMapListener(), true);
+
+ arpReplyMap = hazelcastInstance.getMap(arpReplyMapName);
+ arpReplyMap.addEntryListener(new ArpReplyMapListener(), true);
}
/**
@@ -540,15 +563,27 @@
}
@Override
- public void registerArpEventHandler(IArpEventHandler arpEventHandler) {
+ public void registerPacketOutEventHandler(IPacketOutEventHandler arpEventHandler) {
if (arpEventHandler != null) {
- arpEventHandlers.add(arpEventHandler);
+ packetOutEventHandlers.add(arpEventHandler);
}
}
@Override
- public void deregisterArpEventHandler(IArpEventHandler arpEventHandler) {
- arpEventHandlers.remove(arpEventHandler);
+ public void deregisterPacketOutEventHandler(IPacketOutEventHandler arpEventHandler) {
+ packetOutEventHandlers.remove(arpEventHandler);
+ }
+
+ @Override
+ public void registerArpReplyEventHandler(IArpReplyEventHandler arpReplyEventHandler) {
+ if (arpReplyEventHandler != null) {
+ arpReplyEventHandlers.add(arpReplyEventHandler);
+ }
+ }
+
+ @Override
+ public void deregisterArpReplyEventHandler(IArpReplyEventHandler arpReplyEventHandler) {
+ arpReplyEventHandlers.remove(arpReplyEventHandler);
}
/**
@@ -885,8 +920,12 @@
}
@Override
- public void sendArpRequest(ArpMessage arpMessage) {
- //log.debug("ARP bytes: {}", HexString.toHexString(arpRequest));
- arpMap.putAsync(arpMessage, dummyByte, 1L, TimeUnit.MILLISECONDS);
+ public void sendPacketOutNotification(PacketOutNotification packetOutNotification) {
+ packetOutMap.putAsync(packetOutNotification, dummyByte, 1L, TimeUnit.MILLISECONDS);
}
+
+ @Override
+ public void sendArpReplyNotification(ArpReplyNotification arpReply) {
+ arpReplyMap.putAsync(arpReply, dummyByte, 1L, TimeUnit.MILLISECONDS);
+ }
}
diff --git a/src/main/java/net/onrc/onos/datagrid/IDatagridService.java b/src/main/java/net/onrc/onos/datagrid/IDatagridService.java
index 0f03d77..90fe57c 100644
--- a/src/main/java/net/onrc/onos/datagrid/IDatagridService.java
+++ b/src/main/java/net/onrc/onos/datagrid/IDatagridService.java
@@ -4,8 +4,10 @@
import net.floodlightcontroller.core.module.IFloodlightService;
import net.onrc.onos.ofcontroller.flowmanager.IFlowEventHandlerService;
-import net.onrc.onos.ofcontroller.proxyarp.ArpMessage;
-import net.onrc.onos.ofcontroller.proxyarp.IArpEventHandler;
+import net.onrc.onos.ofcontroller.proxyarp.ArpReplyNotification;
+import net.onrc.onos.ofcontroller.proxyarp.IArpReplyEventHandler;
+import net.onrc.onos.ofcontroller.proxyarp.IPacketOutEventHandler;
+import net.onrc.onos.ofcontroller.proxyarp.PacketOutNotification;
import net.onrc.onos.ofcontroller.topology.TopologyElement;
import net.onrc.onos.ofcontroller.util.FlowEntry;
import net.onrc.onos.ofcontroller.util.FlowEntryId;
@@ -42,14 +44,18 @@
*
* @param arpEventHandler The ARP event handler to register.
*/
- public void registerArpEventHandler(IArpEventHandler arpEventHandler);
+ public void registerPacketOutEventHandler(IPacketOutEventHandler arpEventHandler);
/**
* De-register event handler service for ARP events.
*
* @param arpEventHandler The ARP event handler to de-register.
*/
- public void deregisterArpEventHandler(IArpEventHandler arpEventHandler);
+ public void deregisterPacketOutEventHandler(IPacketOutEventHandler arpEventHandler);
+
+ public void registerArpReplyEventHandler(IArpReplyEventHandler arpReplyEventHandler);
+
+ public void deregisterArpReplyEventHandler(IArpReplyEventHandler arpReplyEventHandler);
/**
* Get all Flows that are currently in the datagrid.
@@ -167,8 +173,21 @@
void notificationSendAllTopologyElementsRemoved();
/**
- * Send an ARP request to other ONOS instances
- * @param arpRequest The request packet to send
+ * Send a packet-out notification to other ONOS instances. This informs
+ * other instances that they should send this packet out some of the ports
+ * they control. Not all notifications are applicable to all instances
+ * (i.e. some notifications specify a single port to send the packet out),
+ * so each instance must determine whether it needs to take action when it
+ * receives the notification.
+ *
+ * @param packetOutNotification The packet notification to send
*/
- public void sendArpRequest(ArpMessage arpMessage);
+ public void sendPacketOutNotification(PacketOutNotification packetOutNotification);
+
+ /**
+ * Send notification to other ONOS instances that an ARP reply has been
+ * received.
+ * @param arpReply The notification of the ARP reply
+ */
+ public void sendArpReplyNotification(ArpReplyNotification arpReply);
}