Ported proxyarp to the new packet-out interface.
Removed dependency on FloodlightProvider and FlowPusher.
Change-Id: Ifc18380255546b5271c5c7a6671f92953b90124a
diff --git a/src/main/java/net/onrc/onos/apps/proxyarp/ProxyArpManager.java b/src/main/java/net/onrc/onos/apps/proxyarp/ProxyArpManager.java
index 7ee498a..c1f80d8 100644
--- a/src/main/java/net/onrc/onos/apps/proxyarp/ProxyArpManager.java
+++ b/src/main/java/net/onrc/onos/apps/proxyarp/ProxyArpManager.java
@@ -13,41 +13,29 @@
import java.util.Timer;
import java.util.TimerTask;
-import net.floodlightcontroller.core.FloodlightContext;
-import net.floodlightcontroller.core.IFloodlightProviderService;
-import net.floodlightcontroller.core.IOFMessageListener;
-import net.floodlightcontroller.core.IOFSwitch;
import net.floodlightcontroller.core.module.FloodlightModuleContext;
import net.floodlightcontroller.core.module.IFloodlightModule;
import net.floodlightcontroller.core.module.IFloodlightService;
import net.floodlightcontroller.restserver.IRestApiService;
import net.floodlightcontroller.util.MACAddress;
+import net.onrc.onos.api.packet.IPacketListener;
+import net.onrc.onos.api.packet.IPacketService;
import net.onrc.onos.apps.sdnip.Interface;
import net.onrc.onos.core.datagrid.IDatagridService;
import net.onrc.onos.core.datagrid.IEventChannel;
import net.onrc.onos.core.datagrid.IEventChannelListener;
import net.onrc.onos.core.devicemanager.IOnosDeviceService;
-import net.onrc.onos.core.flowprogrammer.IFlowPusherService;
import net.onrc.onos.core.main.config.IConfigInfoService;
import net.onrc.onos.core.packet.ARP;
import net.onrc.onos.core.packet.Ethernet;
import net.onrc.onos.core.packet.IPv4;
-import net.onrc.onos.core.packetservice.BroadcastPacketOutNotification;
-import net.onrc.onos.core.packetservice.SinglePacketOutNotification;
import net.onrc.onos.core.topology.Device;
import net.onrc.onos.core.topology.INetworkGraphService;
import net.onrc.onos.core.topology.NetworkGraph;
+import net.onrc.onos.core.topology.Port;
import net.onrc.onos.core.topology.Switch;
-import net.onrc.onos.core.util.Dpid;
import net.onrc.onos.core.util.SwitchPort;
-import org.openflow.protocol.OFMessage;
-import org.openflow.protocol.OFPacketIn;
-import org.openflow.protocol.OFPacketOut;
-import org.openflow.protocol.OFPort;
-import org.openflow.protocol.OFType;
-import org.openflow.protocol.action.OFAction;
-import org.openflow.protocol.action.OFActionOutput;
import org.openflow.util.HexString;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -56,8 +44,8 @@
import com.google.common.collect.Multimaps;
import com.google.common.collect.SetMultimap;
-public class ProxyArpManager implements IProxyArpService, IOFMessageListener,
- IFloodlightModule {
+public class ProxyArpManager implements IProxyArpService, IFloodlightModule,
+ IPacketListener {
private static final Logger log = LoggerFactory
.getLogger(ProxyArpManager.class);
@@ -65,28 +53,21 @@
private static int arpRequestTimeoutConfig = 2000; // ms
private long arpCleaningTimerPeriodConfig = 60 * 1000; // ms (1 min)
- private IFloodlightProviderService floodlightProvider;
private IDatagridService datagrid;
private IEventChannel<Long, ArpReplyNotification> arpReplyEventChannel;
- private IEventChannel<Long, BroadcastPacketOutNotification> broadcastPacketOutEventChannel;
- private IEventChannel<Long, SinglePacketOutNotification> singlePacketOutEventChannel;
private IEventChannel<String, ArpCacheNotification> arpCacheEventChannel;
private static final String ARP_REPLY_CHANNEL_NAME = "onos.arp_reply";
- private static final String BROADCAST_PACKET_OUT_CHANNEL_NAME = "onos.broadcast_packet_out";
- private static final String SINGLE_PACKET_OUT_CHANNEL_NAME = "onos.single_packet_out";
private static final String ARP_CACHE_CHANNEL_NAME = "onos.arp_cache";
private final ArpReplyEventHandler arpReplyEventHandler = new ArpReplyEventHandler();
- private final BroadcastPacketOutEventHandler broadcastPacketOutEventHandler = new BroadcastPacketOutEventHandler();
- private final SinglePacketOutEventHandler singlePacketOutEventHandler = new SinglePacketOutEventHandler();
private final ArpCacheEventHandler arpCacheEventHandler = new ArpCacheEventHandler();
private IConfigInfoService configService;
private IRestApiService restApi;
- private IFlowPusherService flowPusher;
private INetworkGraphService networkGraphService;
private NetworkGraph networkGraph;
private IOnosDeviceService onosDeviceService;
+ private IPacketService packetService;
private short vlan;
private static final short NO_VLAN = 0;
@@ -95,91 +76,6 @@
private ArpCache arpCache;
- private class BroadcastPacketOutEventHandler implements
- IEventChannelListener<Long, BroadcastPacketOutNotification> {
-
- @Override
- public void entryAdded(BroadcastPacketOutNotification value) {
- if (log.isTraceEnabled()) {
- log.trace("entryAdded for BroadcastPacketOutEventHandler, ip{}, sw {}, port {}",
- value.getTargetAddress(), value.getInSwitch(), value.getInPort());
- }
- BroadcastPacketOutNotification notification = value;
- broadcastArpRequestOutMyEdge(notification.getPacketData(),
- notification.getInSwitch(),
- notification.getInPort());
-
- // set timestamp
- //This 4 means ipv4 addr size. Need to change it in the future.
- ByteBuffer buffer = ByteBuffer.allocate(4);
- buffer.putInt(notification.getTargetAddress());
- InetAddress addr = null;
- try {
- addr = InetAddress.getByAddress(buffer.array());
- } catch (UnknownHostException e) {
- log.error("Exception:", e);
- }
-
- if (addr != null) {
- for (ArpRequest request : arpRequests.get(addr)) {
- request.setRequestTime();
- }
- }
- }
-
- @Override
- public void entryUpdated(BroadcastPacketOutNotification value) {
- log.debug("entryUpdated for BroadcastPacketOutEventHandler");
- entryAdded(value);
- }
-
- @Override
- public void entryRemoved(BroadcastPacketOutNotification value) {
- //Not implemented. BroadcastPacketOutNotification is used only for remote messaging.
- }
- }
-
- private class SinglePacketOutEventHandler implements
- IEventChannelListener<Long, SinglePacketOutNotification> {
- @Override
- public void entryAdded(SinglePacketOutNotification packetOutNotification) {
- log.debug("entryAdded for SinglePacketOutEventHandler");
- SinglePacketOutNotification notification =
- packetOutNotification;
- sendArpRequestOutPort(notification.getPacketData(),
- notification.getOutSwitch(),
- notification.getOutPort());
-
- // set timestamp
- //This 4 means ipv4 addr size. Need to change it in the future.
- ByteBuffer buffer = ByteBuffer.allocate(4);
- buffer.putInt(notification.getTargetAddress());
- InetAddress addr = null;
- try {
- addr = InetAddress.getByAddress(buffer.array());
- } catch (UnknownHostException e) {
- log.error("Exception:", e);
- }
-
- if (addr != null) {
- for (ArpRequest request : arpRequests.get(addr)) {
- request.setRequestTime();
- }
- }
- }
-
- @Override
- public void entryUpdated(SinglePacketOutNotification packetOutNotification) {
- log.debug("entryUpdated for SinglePacketOutEventHandler");
- entryAdded(packetOutNotification);
- }
-
- @Override
- public void entryRemoved(SinglePacketOutNotification packetOutNotification) {
- //Not implemented. SinglePacketOutNotification is used only for remote messaging.
- }
- }
-
private class ArpReplyEventHandler implements
IEventChannelListener<Long, ArpReplyNotification> {
@@ -346,25 +242,23 @@
public Collection<Class<? extends IFloodlightService>> getModuleDependencies() {
Collection<Class<? extends IFloodlightService>> dependencies =
new ArrayList<Class<? extends IFloodlightService>>();
- dependencies.add(IFloodlightProviderService.class);
dependencies.add(IRestApiService.class);
dependencies.add(IDatagridService.class);
dependencies.add(IConfigInfoService.class);
- dependencies.add(IFlowPusherService.class);
dependencies.add(INetworkGraphService.class);
dependencies.add(IOnosDeviceService.class);
+ dependencies.add(IPacketService.class);
return dependencies;
}
@Override
public void init(FloodlightModuleContext context) {
- this.floodlightProvider = context.getServiceImpl(IFloodlightProviderService.class);
this.configService = context.getServiceImpl(IConfigInfoService.class);
this.restApi = context.getServiceImpl(IRestApiService.class);
this.datagrid = context.getServiceImpl(IDatagridService.class);
- this.flowPusher = context.getServiceImpl(IFlowPusherService.class);
this.networkGraphService = context.getServiceImpl(INetworkGraphService.class);
this.onosDeviceService = context.getServiceImpl(IOnosDeviceService.class);
+ this.packetService = context.getServiceImpl(IPacketService.class);
Map<String, String> configOptions = context.getConfigParams(this);
@@ -398,21 +292,12 @@
log.info("vlan set to {}", this.vlan);
restApi.addRestletRoutable(new ArpWebRoutable());
- floodlightProvider.addOFMessageListener(OFType.PACKET_IN, this);
+ packetService.registerPacketListener(this);
networkGraph = networkGraphService.getNetworkGraph();
//
// Event notification setup: channels and event handlers
//
- broadcastPacketOutEventChannel = datagrid.addListener(BROADCAST_PACKET_OUT_CHANNEL_NAME,
- broadcastPacketOutEventHandler,
- Long.class,
- BroadcastPacketOutNotification.class);
-
- singlePacketOutEventChannel = datagrid.addListener(SINGLE_PACKET_OUT_CHANNEL_NAME,
- singlePacketOutEventHandler,
- Long.class,
- SinglePacketOutNotification.class);
arpReplyEventChannel = datagrid.addListener(ARP_REPLY_CHANNEL_NAME,
arpReplyEventHandler,
@@ -507,55 +392,18 @@
}
@Override
- public String getName() {
- return "proxyarpmanager";
- }
-
- @Override
- public boolean isCallbackOrderingPrereq(OFType type, String name) {
- if (type == OFType.PACKET_IN) {
- return "devicemanager".equals(name)
- || "onosdevicemanager".equals(name);
- } else {
- return false;
- }
- }
-
- @Override
- public boolean isCallbackOrderingPostreq(OFType type, String name) {
- return type == OFType.PACKET_IN && "onosforwarding".equals(name);
- }
-
- @Override
- public Command receive(IOFSwitch sw, OFMessage msg, FloodlightContext cntx) {
- if (!(msg instanceof OFPacketIn)) {
- return Command.CONTINUE;
- }
-
- Ethernet eth = IFloodlightProviderService.bcStore.get(cntx,
- IFloodlightProviderService.CONTEXT_PI_PAYLOAD);
-
- return classifyPacket(sw, msg, eth);
- }
-
- protected Command classifyPacket(IOFSwitch sw, OFMessage msg, Ethernet eth) {
- OFPacketIn pi = (OFPacketIn) msg;
-
+ public void receive(Switch sw, Port inPort, Ethernet eth) {
if (eth.getEtherType() == Ethernet.TYPE_ARP) {
ARP arp = (ARP) eth.getPayload();
learnArp(arp);
if (arp.getOpCode() == ARP.OP_REQUEST) {
- handleArpRequest(sw, pi, arp, eth);
+ handleArpRequest(sw.getDpid(), inPort.getNumber().shortValue(),
+ arp, eth);
} else if (arp.getOpCode() == ARP.OP_REPLY) {
// For replies we simply send a notification via Hazelcast
- sendArpReplyNotification(eth, pi);
+ sendArpReplyNotification(eth);
}
- // Stop ARP packets here
- return Command.STOP;
}
-
- // Propagate everything else
- return Command.CONTINUE;
}
private void learnArp(ARP arp) {
@@ -570,8 +418,7 @@
}
}
- private void handleArpRequest(IOFSwitch sw, OFPacketIn pi, ARP arp,
- Ethernet eth) {
+ private void handleArpRequest(long dpid, short inPort, ARP arp, Ethernet eth) {
if (log.isTraceEnabled()) {
log.trace("ARP request received for {}",
inetAddressToString(arp.getTargetProtocolAddress()));
@@ -585,7 +432,7 @@
return;
}
- if (configService.fromExternalNetwork(sw.getId(), pi.getInPort())) {
+ if (configService.fromExternalNetwork(dpid, inPort)) {
// If the request came from outside our network, we only care if
// it was a request for one of our interfaces.
if (configService.isInterfaceAddress(target)) {
@@ -594,7 +441,7 @@
target.getHostAddress(),
configService.getRouterMacAddress());
- sendArpReply(arp, sw.getId(), pi.getInPort(),
+ sendArpReply(arp, dpid, inPort,
configService.getRouterMacAddress());
}
@@ -603,10 +450,12 @@
//MACAddress mac = arpCache.lookup(target);
- arpRequests.put(target, new ArpRequest(new HostArpRequester(arp, sw.getId(), pi.getInPort()), false));
+ arpRequests.put(target, new ArpRequest(
+ new HostArpRequester(arp, dpid, inPort), false));
networkGraph.acquireReadLock();
- Device targetDevice = networkGraph.getDeviceByMac(MACAddress.valueOf(arp.getTargetHardwareAddress()));
+ Device targetDevice = networkGraph.getDeviceByMac(
+ MACAddress.valueOf(arp.getTargetHardwareAddress()));
networkGraph.releaseReadLock();
if (targetDevice == null) {
@@ -616,12 +465,8 @@
}
// We don't know the device so broadcast the request out
- BroadcastPacketOutNotification value =
- new BroadcastPacketOutNotification(eth.serialize(),
- ByteBuffer.wrap(arp.getTargetProtocolAddress()).getInt(), sw.getId(), pi.getInPort());
- log.debug("broadcastPacketOutEventChannel mac {}, ip {}, dpid {}, port {}, paket {}", eth.getSourceMAC().toLong(),
- ByteBuffer.wrap(arp.getTargetProtocolAddress()).getInt(), sw.getId(), pi.getInPort(), eth.serialize().length);
- broadcastPacketOutEventChannel.addTransientEntry(eth.getDestinationMAC().toLong(), value);
+ packetService.broadcastPacket(eth,
+ new SwitchPort(dpid, inPort));
} else {
// Even if the device exists in our database, we do not reply to
// the request directly, but check whether the device is still valid
@@ -632,7 +477,7 @@
new Object[]{
inetAddressToString(arp.getTargetProtocolAddress()),
macAddress,
- HexString.toHexString(sw.getId()), pi.getInPort()});
+ HexString.toHexString(dpid), inPort});
}
// sendArpReply(arp, sw.getId(), pi.getInPort(), macAddress);
@@ -645,10 +490,8 @@
" - broadcasting", macAddress);
}
- BroadcastPacketOutNotification value =
- new BroadcastPacketOutNotification(eth.serialize(),
- ByteBuffer.wrap(arp.getTargetProtocolAddress()).getInt(), sw.getId(), pi.getInPort());
- broadcastPacketOutEventChannel.addTransientEntry(eth.getDestinationMAC().toLong(), value);
+ packetService.broadcastPacket(eth,
+ new SwitchPort(dpid, inPort));
} else {
for (net.onrc.onos.core.topology.Port portObject : outPorts) {
@@ -666,15 +509,14 @@
HexString.toHexString(outSwitch), outPort});
}
- SinglePacketOutNotification value =
- new SinglePacketOutNotification(eth.serialize(),
- ByteBuffer.wrap(target.getAddress()).getInt(), outSwitch, outPort);
- singlePacketOutEventChannel.addTransientEntry(eth.getDestinationMAC().toLong(), value);
+ packetService.sendPacket(
+ new SwitchPort(outSwitch, outPort), eth);
}
}
}
}
+ // TODO this method has not been tested after recent implementation changes.
private void sendArpRequestForAddress(InetAddress ipAddress) {
// TODO what should the sender IP address and MAC address be if no
// IP addresses are configured? Will there ever be a need to send
@@ -731,11 +573,9 @@
}
// sendArpRequestToSwitches(ipAddress, eth.serialize());
- SinglePacketOutNotification value =
- new SinglePacketOutNotification(eth.serialize(), ByteBuffer.wrap(ipAddress.getAddress()).getInt(),
- intf.getDpid(), intf.getPort());
- singlePacketOutEventChannel.addTransientEntry(MACAddress.valueOf(senderMacAddress).toLong(), value);
+ packetService.sendPacket(
+ new SwitchPort(intf.getDpid(), intf.getPort()), eth);
}
//Please leave it for now because this code is needed for SDN-IP. It will be removed soon.
@@ -769,7 +609,7 @@
}
*/
- private void sendArpReplyNotification(Ethernet eth, OFPacketIn pi) {
+ private void sendArpReplyNotification(Ethernet eth) {
ARP arp = (ARP) eth.getPayload();
if (log.isTraceEnabled()) {
@@ -795,95 +635,13 @@
arpReplyEventChannel.addTransientEntry(mac.toLong(), value);
}
- private void broadcastArpRequestOutMyEdge(byte[] arpRequest, long inSwitch,
- short inPort) {
- List<SwitchPort> switchPorts = new ArrayList<SwitchPort>();
-
- for (IOFSwitch sw : floodlightProvider.getSwitches().values()) {
-
- OFPacketOut po = new OFPacketOut();
- po.setInPort(OFPort.OFPP_NONE).setBufferId(-1)
- .setPacketData(arpRequest);
-
- List<OFAction> actions = new ArrayList<OFAction>();
-
- networkGraph.acquireReadLock();
- Switch graphSw = networkGraph.getSwitch(sw.getId());
- networkGraph.releaseReadLock();
-
- Collection<net.onrc.onos.core.topology.Port> ports = graphSw.getPorts();
-
- if (ports == null) {
- continue;
- }
-
- for (net.onrc.onos.core.topology.Port portObject : ports) {
- if (portObject.getOutgoingLink() == null && portObject.getNumber() > 0) {
- Long portNumber = portObject.getNumber();
-
- if (sw.getId() == inSwitch && portNumber.shortValue() == inPort) {
- // This is the port that the ARP message came in,
- // so don't broadcast out this port
- continue;
- }
- switchPorts.add(new SwitchPort(new Dpid(sw.getId()),
- new net.onrc.onos.core.util.Port(portNumber.shortValue())));
- actions.add(new OFActionOutput(portNumber.shortValue()));
- }
- }
-
- po.setActions(actions);
- short actionsLength = (short) (actions.size() * OFActionOutput.MINIMUM_LENGTH);
- po.setActionsLength(actionsLength);
- po.setLengthU(OFPacketOut.MINIMUM_LENGTH + actionsLength
- + arpRequest.length);
-
- flowPusher.add(sw, po);
- }
-
- if (log.isTraceEnabled()) {
- log.trace("Broadcast ARP request to: {}", switchPorts);
- }
- }
-
- private void sendArpRequestOutPort(byte[] arpRequest, long dpid, short port) {
- if (log.isTraceEnabled()) {
- log.trace("Sending ARP request out {}/{}",
- HexString.toHexString(dpid), port);
- }
-
- OFPacketOut po = new OFPacketOut();
- po.setInPort(OFPort.OFPP_NONE).setBufferId(-1)
- .setPacketData(arpRequest);
-
- List<OFAction> actions = new ArrayList<OFAction>();
- actions.add(new OFActionOutput(port));
- po.setActions(actions);
- short actionsLength = (short) (actions.size() * OFActionOutput.MINIMUM_LENGTH);
- po.setActionsLength(actionsLength);
- po.setLengthU(OFPacketOut.MINIMUM_LENGTH + actionsLength
- + arpRequest.length);
-
- IOFSwitch sw = floodlightProvider.getSwitches().get(dpid);
-
- if (sw == null) {
- log.warn("Switch not found when sending ARP request");
- return;
- }
-
- flowPusher.add(sw, po);
- }
-
private void sendArpReply(ARP arpRequest, long dpid, short port,
MACAddress targetMac) {
if (log.isTraceEnabled()) {
- log.trace(
- "Sending reply {} => {} to {}",
+ log.trace("Sending reply {} => {} to {}",
new Object[]{
- inetAddressToString(arpRequest
- .getTargetProtocolAddress()),
- targetMac,
- inetAddressToString(arpRequest
+ inetAddressToString(arpRequest.getTargetProtocolAddress()),
+ targetMac, inetAddressToString(arpRequest
.getSenderProtocolAddress())});
}
@@ -908,32 +666,7 @@
eth.setVlanID(vlan).setPriorityCode((byte) 0);
}
- List<OFAction> actions = new ArrayList<OFAction>();
- actions.add(new OFActionOutput(port));
-
- OFPacketOut po = new OFPacketOut();
- po.setInPort(OFPort.OFPP_NONE)
- .setBufferId(-1)
- .setPacketData(eth.serialize())
- .setActions(actions)
- .setActionsLength((short) OFActionOutput.MINIMUM_LENGTH)
- .setLengthU(
- OFPacketOut.MINIMUM_LENGTH
- + OFActionOutput.MINIMUM_LENGTH
- + po.getPacketData().length);
-
- List<OFMessage> msgList = new ArrayList<OFMessage>();
- msgList.add(po);
-
- IOFSwitch sw = floodlightProvider.getSwitches().get(dpid);
-
- if (sw == null) {
- log.warn("Switch {} not found when sending ARP reply",
- HexString.toHexString(dpid));
- return;
- }
-
- flowPusher.add(sw, po);
+ packetService.sendPacket(new SwitchPort(dpid, port), eth);
}
private String inetAddressToString(byte[] bytes) {
diff --git a/src/main/java/net/onrc/onos/core/packetservice/BroadcastPacketOutNotification.java b/src/main/java/net/onrc/onos/core/packetservice/BroadcastPacketOutNotification.java
index bf5c700..e2f9d21 100644
--- a/src/main/java/net/onrc/onos/core/packetservice/BroadcastPacketOutNotification.java
+++ b/src/main/java/net/onrc/onos/core/packetservice/BroadcastPacketOutNotification.java
@@ -25,11 +25,14 @@
private final long inSwitch;
private final short inPort;
+ /**
+ * Default constructor, used for deserialization.
+ */
protected BroadcastPacketOutNotification() {
super();
- this.address = -1;
- this.inSwitch = -1;
- this.inPort = -1;
+ this.address = 0;
+ this.inSwitch = 0;
+ this.inPort = 0;
}
/**
diff --git a/src/main/java/net/onrc/onos/core/packetservice/PacketOutNotification.java b/src/main/java/net/onrc/onos/core/packetservice/PacketOutNotification.java
index d95ddf2..0307d2f 100644
--- a/src/main/java/net/onrc/onos/core/packetservice/PacketOutNotification.java
+++ b/src/main/java/net/onrc/onos/core/packetservice/PacketOutNotification.java
@@ -20,7 +20,7 @@
private final byte[] packet;
/**
- * Default constructor.
+ * Default constructor, used for deserialization.
*/
protected PacketOutNotification() {
packet = null;
diff --git a/src/main/java/net/onrc/onos/core/packetservice/SinglePacketOutNotification.java b/src/main/java/net/onrc/onos/core/packetservice/SinglePacketOutNotification.java
index cd604ea..edf017b 100644
--- a/src/main/java/net/onrc/onos/core/packetservice/SinglePacketOutNotification.java
+++ b/src/main/java/net/onrc/onos/core/packetservice/SinglePacketOutNotification.java
@@ -16,6 +16,9 @@
private final long outSwitch;
private final short outPort;
+ /**
+ * Default constructor, used for deserialization.
+ */
protected SinglePacketOutNotification() {
address = 0;
outSwitch = 0;