diff --git a/client-level/fl-ho-cl/.classpath b/client-level/fl-ho-cl/.classpath index a1f69b2..bd7ea8f 100644 --- a/client-level/fl-ho-cl/.classpath +++ b/client-level/fl-ho-cl/.classpath @@ -24,6 +24,7 @@ + @@ -31,6 +32,5 @@ - diff --git a/client-level/fl-ho-cl/src/main/java/net/floodlightcontroller/ARPRewrite b/client-level/fl-ho-cl/src/main/java/net/floodlightcontroller/ARPRewrite deleted file mode 160000 index 06e5cfd..0000000 --- a/client-level/fl-ho-cl/src/main/java/net/floodlightcontroller/ARPRewrite +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 06e5cfd49f1ec2fdfcbad9b7ef032d9c1027e568 diff --git a/client-level/fl-ho-cl/src/main/java/net/floodlightcontroller/ARPRewrite/ARPRewrite.java b/client-level/fl-ho-cl/src/main/java/net/floodlightcontroller/ARPRewrite/ARPRewrite.java new file mode 100644 index 0000000..7f12fdf --- /dev/null +++ b/client-level/fl-ho-cl/src/main/java/net/floodlightcontroller/ARPRewrite/ARPRewrite.java @@ -0,0 +1,312 @@ +package net.floodlightcontroller.ARPRewrite; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Map; + +import net.floodlightcontroller.core.FloodlightContext; +import net.floodlightcontroller.core.IFloodlightProviderService; +import net.floodlightcontroller.core.IOFSwitch; +import net.floodlightcontroller.core.module.FloodlightModuleContext; +import net.floodlightcontroller.core.module.FloodlightModuleException; +import net.floodlightcontroller.core.module.IFloodlightModule; +import net.floodlightcontroller.core.module.IFloodlightService; +import net.floodlightcontroller.forwarding.Forwarding; +import net.floodlightcontroller.packet.ARP; +import net.floodlightcontroller.packet.Ethernet; +import net.floodlightcontroller.packet.IPacket; +import net.floodlightcontroller.packet.IPv4; +import net.floodlightcontroller.routing.IRoutingDecision; +import net.floodlightcontroller.staticflowentry.IStaticFlowEntryPusherService; +import net.floodlightcontroller.storage.IStorageSourceService; +import net.floodlightcontroller.util.MACAddress; + +import org.openflow.protocol.OFFlowMod; +import org.openflow.protocol.OFPacketIn; +import org.openflow.protocol.OFPacketOut; +import org.openflow.protocol.OFType; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class ARPRewrite extends Forwarding implements +IFloodlightModule { + protected static Logger log = LoggerFactory.getLogger(ARPRewrite.class); + // proxyArp MAC address - can replace with other values in future + public static String TAP_MAC_ADDRESS = "12:51:16:90:8f:ee"; // Tap + public static String IFACE1_MAC_ADDRESS = "00:1d:e1:3b:48:1d"; // WiMAX + public static String IFACE2_MAC_ADDRESS = "00:23:15:81:8b:f8"; // WiFi + public static String IFACE3_MAC_ADDRESS = "00:23:15:81:8b:f8"; // WiFi #2 (Not Used, GEC18) + public static String IFACE4_MAC_ADDRESS = "00:1d:e1:3b:48:1d"; // WiMAX #2 (Not Used, GEC18) + public static String BROADCAST_MAC = "ff:ff:ff:ff:ff:ff"; + + public static String IFACE1_DPID; + public static String IFACE2_DPID; + public static String IFACE3_DPID; + public static String IFACE4_DPID; + public static String TAP_DPID; + + protected MACAddress TAP_MAC; + protected MACAddress IFACE1_MAC; + protected MACAddress IFACE2_MAC; + protected MACAddress IFACE3_MAC; + protected MACAddress IFACE4_MAC; + protected MACAddress BCAST_MAC; + + protected IStaticFlowEntryPusherService sfep; + protected IFloodlightProviderService floodlightProvider; + + @Override + public Collection> getModuleDependencies() { + Collection> l = + new ArrayList>(); + l.add(IFloodlightProviderService.class); + l.add(IStorageSourceService.class); + l.add(IStaticFlowEntryPusherService.class); + return l; + } + + @Override + public void init(FloodlightModuleContext context) + throws FloodlightModuleException { + + sfep = context.getServiceImpl(IStaticFlowEntryPusherService.class); + floodlightProvider = context.getServiceImpl(IFloodlightProviderService.class); + + /* read our config options */ + Map configOptions = context.getConfigParams(this); + + TAP_MAC_ADDRESS = configOptions.get("tap-mac-address"); + IFACE1_MAC_ADDRESS = configOptions.get("wimax-mac-address"); + IFACE2_MAC_ADDRESS = configOptions.get("wifi-mac-address"); + IFACE3_MAC_ADDRESS = configOptions.get("iface3-mac-address"); + IFACE4_MAC_ADDRESS = configOptions.get("iface4-mac-address"); + + TAP_DPID = configOptions.get("tap-dpid"); + IFACE1_DPID = configOptions.get("wimax-dpid"); + IFACE2_DPID = configOptions.get("wifi-dpid"); + IFACE3_DPID = configOptions.get("iface3-dpid"); + IFACE4_DPID = configOptions.get("iface4-dpid"); + + TAP_MAC = MACAddress.valueOf(TAP_MAC_ADDRESS); + IFACE1_MAC = MACAddress.valueOf(IFACE1_MAC_ADDRESS); + IFACE2_MAC = MACAddress.valueOf(IFACE2_MAC_ADDRESS); + IFACE3_MAC = MACAddress.valueOf(IFACE3_MAC_ADDRESS); + IFACE4_MAC = MACAddress.valueOf(IFACE4_MAC_ADDRESS); + BCAST_MAC = MACAddress.valueOf(BROADCAST_MAC); + + super.init(context); + } + + + @Override + public void startUp(FloodlightModuleContext context) { + floodlightProvider.addOFMessageListener(OFType.PACKET_IN, this); + } + + @Override + public Command processPacketInMessage(IOFSwitch sw, OFPacketIn pi, + IRoutingDecision decision, FloodlightContext cntx) { + Ethernet eth = IFloodlightProviderService.bcStore.get(cntx, + IFloodlightProviderService.CONTEXT_PI_PAYLOAD); + if (eth.getEtherType() == Ethernet.TYPE_ARP) { + + // retrieve arp to determine addresses + ARP arpPayload = (ARP) eth.getPayload(); + + // (1) Get flows from switch + // (2) Find flow with matching ingress port + // (3) Use matching flow and extract output port + // (4) Use switch DPID and use correct (hard-coded) MAC of physical interface on that switch + // This is only for ARP. DHCP is ethertype 0x800, which will work with existing flows. + + // (1) Get flows + Map flows; + //long switchIDAsLong = sw.getId(); + //String switchIDAsString = Long.toString(switchIDAsLong); + //flows = sfep.getFlows("00:00:00:00:00:00:00:0".concat(switchIDAsString)); // This might not convert correctly + flows = sfep.getFlows(sw.getStringId()); // This might not convert correctly + Collection flowsAsCollection; + if (flows != null) { + flowsAsCollection = flows.values(); + } else { + log.debug("No flows on switch " + sw.getStringId()); + return Command.CONTINUE; + } + short inPort = pi.getInPort(); + short outPort = 0; + log.debug("Packet from switch " + sw.getStringId() + " on port " + inPort); + + + // (2) and (3) Get output port from matching ingress port + if (!flows.isEmpty()) { + for (OFFlowMod myFlow : flowsAsCollection) { + if (myFlow.getMatch().getInputPort() == inPort) { + outPort = myFlow.getOutPort(); + log.debug("Got (inPort, outPort) pair (" + inPort + ", " + outPort + ")"); + break; + } + } + } else { + log.info("No flows returned for DPID " + sw.getStringId()); + return Command.CONTINUE; + } + + if (outPort == 0) { + log.debug("No matching flow found"); + return Command.CONTINUE; + } + + // (4) Determine MAC address to rewrite + // ingress on tap + + MACAddress targetMAC; + MACAddress sourceMAC; + MACAddress destinationMAC; + boolean isIngress = false; + boolean isRequest = false; + short arpOpCode = arpPayload.getOpCode(); + if (arpOpCode == ARP.OP_REQUEST) { + log.info("ARP packet is a request"); + destinationMAC = BCAST_MAC; + isRequest = true; + } else if (arpOpCode == ARP.OP_REPLY) { + log.info("ARP packet is a reply"); + } else { + log.info("ARP packet was neither request nor reply"); + return Command.CONTINUE; + } + if (sw.getStringId() == TAP_DPID) { + if (outPort == 1 || outPort == 65534 || outPort == -1) { + targetMAC = TAP_MAC; + sourceMAC = null; + isIngress = true; + } else { + targetMAC = null; + sourceMAC = TAP_MAC; + } + } else if (sw.getStringId() == IFACE1_DPID) { + if (outPort == 1 || outPort == 65534 || outPort == -1) { + targetMAC = null; + sourceMAC = IFACE1_MAC; + } else { + targetMAC = TAP_MAC; + sourceMAC = null; + isIngress = true; + } + } else if (sw.getStringId() == IFACE2_DPID) { + if (outPort == 1 || outPort == 65534 || outPort == -1) { + targetMAC = null; + sourceMAC = IFACE2_MAC; + } else { + targetMAC = TAP_MAC; + sourceMAC = null; + isIngress = true; + } + } else if (sw.getStringId() == IFACE3_DPID) { + if (outPort == 1 || outPort == 65534 || outPort == -1) { + targetMAC = null; + sourceMAC = IFACE3_MAC; + } else { + targetMAC = TAP_MAC; + sourceMAC = null; + isIngress = true; + } + } else if (sw.getStringId() == IFACE4_DPID) { + if (outPort == 1 || outPort == 65534 || outPort == -1) { + targetMAC = null; + sourceMAC = IFACE4_MAC; + } else { + targetMAC = TAP_MAC; + sourceMAC = null; + isIngress = true; + } + } else { + sourceMAC = null; + targetMAC = null; + log.debug("Did find a matching DPID"); + } + + // 4 Cases: Only rewrite on non-TAP switch. The tap switch will have 4 flows for 0x800 and 0x806. + // All rewrites source and destination will occur on the OVS switch at the physical interface. + // (1) Ingress Packet, ARP Request -- rewrite nothing (need to find MAC aka request) + // (2) Ingress Packet, ARP Reply -- rewrite destination MAC to tap + // (3) Outbound Packet, ARP Request -- rewrite source MAC to physical (need to be able to respond and send on IFACE) + // (4) Outbound Packet, ARP Reply -- rewrite source MAC to physical (need to be able to send on IFACE) + if (isRequest && sw.getStringId() == TAP_DPID && isIngress) { + log.debug("Sending request out with SRC " + sourceMAC.toString() + " DST " + MACAddress.valueOf(arpPayload.getTargetHardwareAddress()) + + " from port " + inPort + " to port " + outPort); + destinationMAC = BCAST_MAC; + sendARP(sw, pi, cntx, inPort, (short)65534, arpOpCode, + arpPayload.getSenderHardwareAddress(), arpPayload.getTargetHardwareAddress(), destinationMAC.toBytes()); + } else if (!isRequest && sw.getStringId() == TAP_DPID && isIngress) { + log.debug("Sending reply out with SRC " + sourceMAC.toString() + " DST " + MACAddress.valueOf(arpPayload.getTargetHardwareAddress()) + + " from port " + inPort + " to port " + outPort); + destinationMAC = targetMAC; + sendARP(sw, pi, cntx, inPort, (short)65534, arpOpCode, + arpPayload.getSenderHardwareAddress(), targetMAC.toBytes(), destinationMAC.toBytes()); + } else if (isRequest && sw.getStringId() != TAP_DPID && !isIngress) { + log.debug("Sending request out with SRC " + sourceMAC.toString() + " DST " + MACAddress.valueOf(arpPayload.getTargetHardwareAddress()) + + " from port " + inPort + " to port " + outPort); + destinationMAC = BCAST_MAC; + // removed (-) from outPort for testing + sendARP(sw, pi, cntx, inPort, (short)-outPort, arpOpCode, + sourceMAC.toBytes(), arpPayload.getTargetHardwareAddress(), destinationMAC.toBytes()); + } else if (!isRequest && sw.getStringId() != TAP_DPID && !isIngress) { + log.debug("Sending reply out with SRC " + sourceMAC.toString() + " DST " + MACAddress.valueOf(arpPayload.getTargetHardwareAddress()) + + " from port " + inPort + " to port " + outPort); + destinationMAC = targetMAC; + sendARP(sw, pi, cntx, inPort, (short)-outPort, arpOpCode, + sourceMAC.toBytes(), arpPayload.getTargetHardwareAddress(), destinationMAC.toBytes()); + } else { + log.debug("Determining how to rewrite ARP packet failed!"); + } + } else { + // Do nothing + } + + return Command.CONTINUE; + } + + protected void sendARP(IOFSwitch sw, OFPacketIn pi, FloodlightContext cntx, short inPort, short outPort, + short arpOpCode , byte[] sourceMACAddress, byte[] targetMACAddress, byte[] destinationMACAddress) { + + Ethernet eth = IFloodlightProviderService.bcStore.get(cntx, IFloodlightProviderService.CONTEXT_PI_PAYLOAD); + // retrieve original ARP + ARP arpPayload = (ARP) eth.getPayload(); + log.debug("ARP to " + IPv4.fromIPv4Address(IPv4.toIPv4Address(arpPayload.getTargetProtocolAddress()))); + + // Modify original ARP packet + IPacket newARPPacket = new Ethernet() + .setSourceMACAddress(sourceMACAddress) + .setDestinationMACAddress(destinationMACAddress) + .setEtherType(Ethernet.TYPE_ARP) + .setVlanID(eth.getVlanID()) + .setPriorityCode(eth.getPriorityCode()) + .setPayload( + new ARP() + .setHardwareType(ARP.HW_TYPE_ETHERNET) + .setProtocolType(ARP.PROTO_TYPE_IP) + .setHardwareAddressLength((byte) 6) + .setProtocolAddressLength((byte) 4) + .setOpCode(arpOpCode) + .setSenderHardwareAddress(sourceMACAddress) + .setSenderProtocolAddress( + arpPayload.getSenderProtocolAddress()) + .setTargetHardwareAddress( + targetMACAddress) + .setTargetProtocolAddress( + arpPayload.getTargetProtocolAddress())); + + // push ARP out + pushPacket(newARPPacket, sw, OFPacketOut.BUFFER_ID_NONE, inPort, outPort, cntx, true); + log.debug("ARP packet pushed out PORT " + outPort + " on SWITCH " + sw.getStringId() + " with SRC " + MACAddress.valueOf(sourceMACAddress) + + " and TGT " + MACAddress.valueOf(targetMACAddress) + " and DST " + MACAddress.valueOf(destinationMACAddress)); + return; + } + + @Override + public Collection> getModuleServices() { + return null; + } + +} diff --git a/client-level/fl-ho-cl/src/main/java/net/floodlightcontroller/handover/Handover.java b/client-level/fl-ho-cl/src/main/java/net/floodlightcontroller/handover/Handover.java index d523d4d..8824dbf 100644 --- a/client-level/fl-ho-cl/src/main/java/net/floodlightcontroller/handover/Handover.java +++ b/client-level/fl-ho-cl/src/main/java/net/floodlightcontroller/handover/Handover.java @@ -130,7 +130,7 @@ public class Handover implements IFloodlightModule { private static ArrayList ACTIVE_FLOWS; private static final String OFFLINE = "offline"; private static String ACTIVE_NETWORK_TYPE = OFFLINE; - + @Override public Collection> getModuleServices() { return null; @@ -258,6 +258,7 @@ public void handleDevice(DeviceObject device) { log.debug("GPSD: Updated DEVICE"); } }); + GPSD_CONN.start(); log.debug("Version: " + GPSD_CONN.version().toString()); @@ -590,7 +591,7 @@ private String askGRC() { obj.put("operator", netType.equals("Wifi")? "" :"Clemson"); netTypeObjs.add(obj); } - + //create a JSON array containing all of our JSON objects, and include it in our request log.debug("Latitude: " + Double.toString(GPSD_LATITUDE) + ", Longitude: " + Double.toString(GPSD_LONGITUDE)); JSONArray jNetTypesArray = new JSONArray(netTypeObjs); @@ -602,7 +603,7 @@ private String askGRC() { httpPost.setEntity(new UrlEncodedFormEntity(nvps)); HttpResponse response = httpclient.execute(httpPost); int status = response.getStatusLine().getStatusCode(); - + //retreive JSON response String body; if(status >= 200 && status < 300){ @@ -611,7 +612,7 @@ private String askGRC() { } else { body = "ERROR"; } - + //parse JSON response JSONObject responseObj = new JSONObject(body); String responseNet = responseObj.getString("network"); @@ -637,4 +638,4 @@ public void run() { return; } } // END GRCProbe Class -} // END Handover Module \ No newline at end of file +} // END Handover Module diff --git a/client-level/fl-ho-cl/src/main/resources/floodlightdefault.properties b/client-level/fl-ho-cl/src/main/resources/floodlightdefault.properties index 7f30ab2..dbd2ecb 100644 --- a/client-level/fl-ho-cl/src/main/resources/floodlightdefault.properties +++ b/client-level/fl-ho-cl/src/main/resources/floodlightdefault.properties @@ -62,4 +62,4 @@ net.floodlightcontroller.handover.Handover.ovs-wifi0-iface-port = 0 net.floodlightcontroller.handover.Handover.ovs-wifi1-iface-port = 0 net.floodlightcontroller.handover.Handover.ovs-wimax0-iface-port = 0 net.floodlightcontroller.handover.Handover.ovs-wimax1-iface-port = 0 -net.floodlightcontroller.handover.Handover.ovs-ethernet-iface-port = 0 \ No newline at end of file +net.floodlightcontroller.handover.Handover.ovs-ethernet-iface-port = 0