package net.floodlightcontroller.core.util; import java.nio.ByteBuffer; import java.util.Objects; import org.projectfloodlight.openflow.protocol.OFFactory; import org.projectfloodlight.openflow.protocol.match.Match; import org.projectfloodlight.openflow.protocol.match.MatchField; import org.projectfloodlight.openflow.types.ArpOpcode; import org.projectfloodlight.openflow.types.EthType; import org.projectfloodlight.openflow.types.ICMPv4Code; import org.projectfloodlight.openflow.types.ICMPv4Type; import org.projectfloodlight.openflow.types.IPv4Address; import org.projectfloodlight.openflow.types.IpDscp; import org.projectfloodlight.openflow.types.IpEcn; import org.projectfloodlight.openflow.types.IpProtocol; import org.projectfloodlight.openflow.types.MacAddress; import org.projectfloodlight.openflow.types.OFPort; import org.projectfloodlight.openflow.types.OFVlanVidMatch; import org.projectfloodlight.openflow.types.TransportPort; import org.projectfloodlight.openflow.types.U8; import org.projectfloodlight.openflow.types.VlanPcp; public class OFUtils { public static Match loadFromPacket(byte[] packetData, OFPort inputPort, OFFactory factory) { short scratch; int transportOffset = 34; ByteBuffer packetDataBB = ByteBuffer.wrap(packetData); int limit = packetDataBB.limit(); assert (limit >= 14); Match.Builder builder = factory.buildMatch(); if (!Objects.equals(inputPort, OFPort.ALL)) builder.setExact(MatchField.IN_PORT, inputPort); // dl dst byte[] dataLayerDestination = new byte[6]; packetDataBB.get(dataLayerDestination); builder.setExact(MatchField.ETH_DST, MacAddress.of(dataLayerDestination)); // dl src byte[] dataLayerSource = new byte[6]; packetDataBB.get(dataLayerSource); builder.setExact(MatchField.ETH_SRC, MacAddress.of(dataLayerSource)); // dl type short dataLayerType = packetDataBB.getShort(); builder.setExact(MatchField.ETH_TYPE, EthType.of(dataLayerType)); if (dataLayerType != (short) 0x8100) { // need cast to avoid signed // bug builder.setExact(MatchField.VLAN_VID, OFVlanVidMatch.UNTAGGED); builder.setExact(MatchField.VLAN_PCP, VlanPcp.NONE); } else { // has vlan tag scratch = packetDataBB.getShort(); builder.setExact(MatchField.VLAN_VID, OFVlanVidMatch.ofVlan(0xfff & scratch)); builder.setExact(MatchField.VLAN_PCP, VlanPcp.of((byte)((0xe000 & scratch) >> 13))); dataLayerType = packetDataBB.getShort(); } short networkProtocol; int networkSource; int networkDestination; switch (dataLayerType) { case 0x0800: // ipv4 // check packet length scratch = packetDataBB.get(); scratch = (short) (0xf & scratch); transportOffset = (packetDataBB.position() - 1) + (scratch * 4); // nw tos (dscp+ecn) scratch = packetDataBB.get(); builder.setExact(MatchField.IP_ECN, IpEcn.of((byte)(scratch & 0x03))); builder.setExact(MatchField.IP_DSCP, IpDscp.of((byte) ((0xfc & scratch) >> 2))); // nw protocol packetDataBB.position(packetDataBB.position() + 7); networkProtocol = packetDataBB.get(); builder.setExact(MatchField.IP_PROTO, IpProtocol.of(networkProtocol)); // nw src packetDataBB.position(packetDataBB.position() + 2); networkSource = packetDataBB.getInt(); builder.setExact(MatchField.IPV4_SRC, IPv4Address.of(networkSource)); // nw dst networkDestination = packetDataBB.getInt(); builder.setExact(MatchField.IPV4_DST, IPv4Address.of(networkDestination)); packetDataBB.position(transportOffset); int port; switch (networkProtocol) { case 0x01: // icmp // type short type = U8.f(packetDataBB.get()); builder.setExact(MatchField.ICMPV4_TYPE, ICMPv4Type.of(type)); // code short code = U8.f(packetDataBB.get()); builder.setExact(MatchField.ICMPV4_CODE, ICMPv4Code.of(code)); break; case 0x06: // tcp // tcp src port = packetDataBB.getShort(); builder.setExact(MatchField.TCP_SRC, TransportPort.of(port)); // tcp dest port = packetDataBB.getShort(); builder.setExact(MatchField.TCP_DST, TransportPort.of(port)); break; case 0x11: // udp // udp src port = packetDataBB.getShort(); builder.setExact(MatchField.UDP_SRC, TransportPort.of(port)); // udp dest port = packetDataBB.getShort(); builder.setExact(MatchField.UDP_DST, TransportPort.of(port)); break; default: // Unknown network proto. break; } break; case 0x0806: // arp int arpPos = packetDataBB.position(); // opcode scratch = packetDataBB.getShort(arpPos + 6); builder.setExact(MatchField.ARP_OP, ArpOpcode.of(0xff & scratch)); scratch = packetDataBB.getShort(arpPos + 2); // if ipv4 and addr len is 4 if (scratch == 0x800 && packetDataBB.get(arpPos + 5) == 4) { networkSource = packetDataBB.getInt(arpPos + 14); networkDestination = packetDataBB.getInt(arpPos + 24); } else { networkSource = 0; networkDestination = 0; } builder.setExact(MatchField.ARP_SPA, IPv4Address.of(networkSource)); builder.setExact(MatchField.ARP_TPA, IPv4Address.of(networkDestination)); break; default: // Not ARP or IP. // Don't specify any network fields break; } return builder.build(); } }