/**
* Copyright 2013, Big Switch Networks, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License. You may obtain
* a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
**/
package net.floodlightcontroller.core.test;
import java.util.ArrayList;
import java.util.List;
import net.floodlightcontroller.core.IOFSwitch;
import org.projectfloodlight.openflow.protocol.OFFactory;
import org.projectfloodlight.openflow.protocol.OFPacketIn;
import org.projectfloodlight.openflow.protocol.OFPacketInReason;
import org.projectfloodlight.openflow.protocol.OFVersion;
import org.projectfloodlight.openflow.protocol.match.MatchField;
import org.projectfloodlight.openflow.types.EthType;
import org.projectfloodlight.openflow.types.IPv4Address;
import org.projectfloodlight.openflow.types.IpProtocol;
import org.projectfloodlight.openflow.types.MacAddress;
import org.projectfloodlight.openflow.types.OFPort;
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;
/**
* 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";
/**
* 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(IOFSwitch sw,
MacAddress hostMac) {
byte[] serializedPacket = DhcpDiscoveryRequestEthernet(hostMac).serialize();
OFFactory factory = sw.getOFFactory();
OFPacketIn.Builder packetInBuilder = factory.buildPacketIn();
if (factory.getVersion() == OFVersion.OF_10) {
packetInBuilder
.setInPort(OFPort.of(1))
.setData(serializedPacket)
.setReason(OFPacketInReason.NO_MATCH);
} else {
packetInBuilder
.setMatch(factory.buildMatch().setExact(MatchField.IN_PORT, OFPort.of(1)).build())
.setData(serializedPacket)
.setReason(OFPacketInReason.NO_MATCH);
}
return packetInBuilder.build();
}
/**
* 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.getBytes(), 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.getBytes())
.setDestinationMACAddress(broadcastMac)
.setEtherType(EthType.IPv4)
.setPayload(
new IPv4()
.setVersion((byte)4)
.setDiffServ((byte)0)
.setIdentification((short)100)
.setFlags((byte)0)
.setFragmentOffset((short)0)
.setTtl((byte)250)
.setProtocol(IpProtocol.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(IPv4Address.NONE)
.setYourIPAddress(IPv4Address.NONE)
.setServerIPAddress(IPv4Address.NONE)
.setGatewayIPAddress(IPv4Address.NONE)
.setClientHardwareAddress(hostMac)
.setOptions(optionList))));
return requestPacket;
}
}