Skip to content
Snippets Groups Projects
Commit 328791e8 authored by abat's avatar abat
Browse files

Merge into master from pull request #161:

VirtualNetworkFilter now allows any DHCP traffic. (https://github.com/floodlight/floodlight/pull/161)
parents e034cbb0 1bf172b0
No related branches found
No related tags found
No related merge requests found
......@@ -170,6 +170,7 @@
<fileset dir="${source-test}">
<exclude name="**/storage/tests/StorageTest.java"/>
<exclude name="**/test/Mock*"/>
<exclude name="**/core/test/**"/>
</fileset>
</batchtest>
</junit>
......
......@@ -10,7 +10,7 @@ public interface IVirtualNetworkService extends IFloodlightService {
* and the fields you want to update.
* @param network The network name. Must be unique.
* @param guid The ID of the network. Must be unique.
* @param gateway The IP address of the network gateway, null if none. Must be unique.
* @param gateway The IP address of the network gateway, null if none.
*/
public void createNetwork(String guid, String network, Integer gateway);
......
......@@ -56,6 +56,10 @@ public class NetworkResource extends ServerResource {
network.name = jp.getText();
} else if (field.equals("gateway")) {
network.gateway = jp.getText();
} else {
log.warn("Unrecognized field {} in " +
"parsing network definition",
jp.getText());
}
}
}
......
......@@ -33,7 +33,9 @@ import net.floodlightcontroller.core.module.IFloodlightModule;
import net.floodlightcontroller.core.module.IFloodlightService;
import net.floodlightcontroller.core.util.AppCookie;
import net.floodlightcontroller.packet.ARP;
import net.floodlightcontroller.packet.DHCP;
import net.floodlightcontroller.packet.Ethernet;
import net.floodlightcontroller.packet.IPacket;
import net.floodlightcontroller.packet.IPv4;
import net.floodlightcontroller.restserver.IRestApiService;
import net.floodlightcontroller.util.MACAddress;
......@@ -48,6 +50,7 @@ import net.floodlightcontroller.virtualnetwork.IVirtualNetworkService;
* - This module does not allow overlapping of IPs or MACs
* - You can only have 1 gateway per virtual network (can be shared)
* - There is filtering of multicast/broadcast traffic
* - All DHCP traffic will be allowed, regardless of unicast/broadcast
*
* @author alexreimers
*/
......@@ -291,18 +294,33 @@ public class VirtualNetworkFilter
return srcNetwork.equals(dstNetwork);
}
protected boolean isDhcpPacket(Ethernet frame) {
IPacket payload = frame.getPayload(); // IP
if (payload == null) return false;
IPacket p2 = payload.getPayload(); // TCP or UDP
if (p2 == null) return false;
IPacket p3 = p2.getPayload(); // Application
if ((p3 != null) && (p3 instanceof DHCP)) return true;
return false;
}
protected Command processPacketIn(IOFSwitch sw, OFPacketIn msg, FloodlightContext cntx) {
Ethernet eth = IFloodlightProviderService.bcStore.get(cntx,
IFloodlightProviderService.CONTEXT_PI_PAYLOAD);
Command ret = Command.STOP;
String srcNetwork = macToGuid.get(eth.getSourceMAC());
if (srcNetwork == null && !(eth.getPayload() instanceof ARP)) {
// If the host is on an unknown network we deny it.
// We make exceptions for ARP in order to handle gateways
// and for DHCP.
if (isDhcpPacket(eth)) {
log.trace("Letting DHCP traffic through");
ret = Command.CONTINUE;
} else if (srcNetwork == null && !(eth.getPayload() instanceof ARP)) {
log.debug("Blocking traffic from host {} because it is not attached to any network.",
HexString.toHexString(eth.getSourceMACAddress()));
ret = Command.STOP;
} else {
if (eth.isBroadcast() || eth.isMulticast()) {
if (eth.isBroadcast() || eth.isMulticast() || (eth.getPayload() instanceof DHCP)) {
return Command.CONTINUE;
}
......
package net.floodlightcontroller.core.test;
import java.util.ArrayList;
import java.util.List;
import net.floodlightcontroller.packet.DHCP;
import net.floodlightcontroller.packet.DHCPOption;
import net.floodlightcontroller.packet.Ethernet;
import net.floodlightcontroller.packet.IPv4;
import net.floodlightcontroller.packet.UDP;
import net.floodlightcontroller.util.MACAddress;
import org.openflow.protocol.OFPacketIn;
import org.openflow.protocol.OFPacketOut;
import org.openflow.protocol.OFType;
import org.openflow.protocol.OFPacketIn.OFPacketInReason;
import org.openflow.protocol.factory.BasicFactory;
/**
* A class to that creates many types of L2/L3/L4 or OpenFlow packets.
* This is used in testing.
* @author alexreimers
*
*/
public class PacketFactory {
public static String broadcastMac = "ff:ff:ff:ff:ff:ff";
public static String broadcastIp = "255.255.255.255";
protected static BasicFactory OFMessageFactory = new BasicFactory();
/**
* Generates a DHCP request OFPacketIn.
* @param hostMac The host MAC address of for the request.
* @return An OFPacketIn that contains a DHCP request packet.
*/
public static OFPacketIn DhcpDiscoveryRequestOFPacketIn(MACAddress hostMac) {
byte[] serializedPacket = DhcpDiscoveryRequestEthernet(hostMac).serialize();
return (((OFPacketIn)OFMessageFactory
.getMessage(OFType.PACKET_IN))
.setBufferId(OFPacketOut.BUFFER_ID_NONE)
.setInPort((short) 1)
.setPacketData(serializedPacket)
.setReason(OFPacketInReason.NO_MATCH)
.setTotalLength((short)serializedPacket.length));
}
/**
* Generates a DHCP request Ethernet frame.
* @param hostMac The host MAC address of for the request.
* @returnAn An Ethernet frame that contains a DHCP request packet.
*/
public static Ethernet DhcpDiscoveryRequestEthernet(MACAddress hostMac) {
List<DHCPOption> optionList = new ArrayList<DHCPOption>();
byte[] requestValue = new byte[4];
requestValue[0] = requestValue[1] = requestValue[2] = requestValue[3] = 0;
DHCPOption requestOption =
new DHCPOption()
.setCode(DHCP.DHCPOptionCode.OptionCode_RequestedIP.
getValue())
.setLength((byte)4)
.setData(requestValue);
byte[] msgTypeValue = new byte[1];
msgTypeValue[0] = 1; // DHCP request
DHCPOption msgTypeOption =
new DHCPOption()
.setCode(DHCP.DHCPOptionCode.OptionCode_MessageType.
getValue())
.setLength((byte)1)
.setData(msgTypeValue);
byte[] reqParamValue = new byte[4];
reqParamValue[0] = 1; // subnet mask
reqParamValue[1] = 3; // Router
reqParamValue[2] = 6; // Domain Name Server
reqParamValue[3] = 42; // NTP Server
DHCPOption reqParamOption =
new DHCPOption()
.setCode(DHCP.DHCPOptionCode.OptionCode_RequestedParameters.
getValue())
.setLength((byte)4)
.setData(reqParamValue);
byte[] clientIdValue = new byte[7];
clientIdValue[0] = 1; // Ethernet
System.arraycopy(hostMac.toBytes(), 0,
clientIdValue, 1, 6);
DHCPOption clientIdOption =
new DHCPOption()
.setCode(DHCP.DHCPOptionCode.OptionCode_ClientID.
getValue())
.setLength((byte)7)
.setData(clientIdValue);
DHCPOption endOption =
new DHCPOption()
.setCode(DHCP.DHCPOptionCode.OptionCode_END.
getValue())
.setLength((byte)0)
.setData(null);
optionList.add(requestOption);
optionList.add(msgTypeOption);
optionList.add(reqParamOption);
optionList.add(clientIdOption);
optionList.add(endOption);
Ethernet requestPacket = new Ethernet();
requestPacket.setSourceMACAddress(hostMac.toBytes())
.setDestinationMACAddress(broadcastMac)
.setEtherType(Ethernet.TYPE_IPv4)
.setPayload(
new IPv4()
.setVersion((byte)4)
.setDiffServ((byte)0)
.setIdentification((short)100)
.setFlags((byte)0)
.setFragmentOffset((short)0)
.setTtl((byte)250)
.setProtocol(IPv4.PROTOCOL_UDP)
.setChecksum((short)0)
.setSourceAddress(0)
.setDestinationAddress(broadcastIp)
.setPayload(
new UDP()
.setSourcePort(UDP.DHCP_CLIENT_PORT)
.setDestinationPort(UDP.DHCP_SERVER_PORT)
.setChecksum((short)0)
.setPayload(
new DHCP()
.setOpCode(DHCP.OPCODE_REQUEST)
.setHardwareType(DHCP.HWTYPE_ETHERNET)
.setHardwareAddressLength((byte)6)
.setHops((byte)0)
.setTransactionId(0x00003d1d)
.setSeconds((short)0)
.setFlags((short)0)
.setClientIPAddress(0)
.setYourIPAddress(0)
.setServerIPAddress(0)
.setGatewayIPAddress(0)
.setClientHardwareAddress(hostMac.toBytes())
.setOptions(optionList))));
return requestPacket;
}
}
......@@ -17,6 +17,7 @@ import net.floodlightcontroller.core.IOFMessageListener;
import net.floodlightcontroller.core.IListener.Command;
import net.floodlightcontroller.core.IOFSwitch;
import net.floodlightcontroller.core.module.FloodlightModuleContext;
import net.floodlightcontroller.core.test.PacketFactory;
import net.floodlightcontroller.packet.Data;
import net.floodlightcontroller.packet.Ethernet;
import net.floodlightcontroller.packet.IPacket;
......@@ -64,6 +65,7 @@ public class VirtualNetworkFilterTest extends FloodlightTestCase {
protected OFPacketIn mac1ToGwPacketIn;
protected IPacket mac1ToGwPacketIntestPacket;
protected byte[] mac1ToGwPacketIntestPacketSerialized;
protected OFPacketIn packetInDHCPDiscoveryRequest;
@Before
public void setUp() throws Exception {
......@@ -268,7 +270,6 @@ public class VirtualNetworkFilterTest extends FloodlightTestCase {
(Ethernet)mac1ToMac2PacketIntestPacket);
Command ret = listener.receive(sw1, mac1ToMac2PacketIn, cntx);
assertTrue(ret == Command.CONTINUE);
//reset(sw1);
// make sure mac1 can't communicate with mac4
cntx = new FloodlightContext();
IFloodlightProviderService.bcStore.put(cntx,
......@@ -290,4 +291,18 @@ public class VirtualNetworkFilterTest extends FloodlightTestCase {
Command ret = listener.receive(sw1, mac1ToGwPacketIn, cntx);
assertTrue(ret == Command.CONTINUE);
}
@Test
public void testDhcp() {
IOFMessageListener listener = mockFloodlightProvider.getListeners().
get(OFType.PACKET_IN).get(0);
Ethernet dhcpPacket = PacketFactory.DhcpDiscoveryRequestEthernet(mac1);
OFPacketIn dhcpPacketOf = PacketFactory.DhcpDiscoveryRequestOFPacketIn(mac1);
cntx = new FloodlightContext();
IFloodlightProviderService.bcStore.put(cntx,
IFloodlightProviderService.CONTEXT_PI_PAYLOAD,
dhcpPacket);
Command ret = listener.receive(sw1, dhcpPacketOf, cntx);
assertTrue(ret == Command.CONTINUE);
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment