ICMP Handler Fix: Create Labelled packet instead of setting MPLS actions on the PacketOut
Change-Id: Ibaa31935066c4254384c1aef081cddec536698c4
diff --git a/src/main/java/net/onrc/onos/apps/segmentrouting/IcmpHandler.java b/src/main/java/net/onrc/onos/apps/segmentrouting/IcmpHandler.java
index 6c68d53..0dcf429c 100644
--- a/src/main/java/net/onrc/onos/apps/segmentrouting/IcmpHandler.java
+++ b/src/main/java/net/onrc/onos/apps/segmentrouting/IcmpHandler.java
@@ -14,11 +14,11 @@
import net.floodlightcontroller.core.IFloodlightProviderService;
import net.floodlightcontroller.core.IOFSwitch;
import net.floodlightcontroller.core.module.FloodlightModuleContext;
-import net.onrc.onos.core.drivermanager.OFSwitchImplDellOSR;
import net.onrc.onos.core.flowprogrammer.IFlowPusherService;
import net.onrc.onos.core.packet.Ethernet;
import net.onrc.onos.core.packet.ICMP;
import net.onrc.onos.core.packet.IPv4;
+import net.onrc.onos.core.packet.MPLS;
import net.onrc.onos.core.topology.Host;
import net.onrc.onos.core.topology.ITopologyService;
import net.onrc.onos.core.topology.MutableTopology;
@@ -35,18 +35,13 @@
import org.projectfloodlight.openflow.protocol.OFPacketOut;
import org.projectfloodlight.openflow.protocol.action.OFAction;
import org.projectfloodlight.openflow.protocol.instruction.OFInstruction;
-import org.projectfloodlight.openflow.protocol.oxm.OFOxmEthDst;
import org.projectfloodlight.openflow.protocol.oxm.OFOxmInPort;
-import org.projectfloodlight.openflow.protocol.oxm.OFOxmMplsLabel;
import org.projectfloodlight.openflow.protocol.oxm.OFOxmVlanVid;
-import org.projectfloodlight.openflow.types.EthType;
import org.projectfloodlight.openflow.types.IPv4Address;
-import org.projectfloodlight.openflow.types.MacAddress;
import org.projectfloodlight.openflow.types.OFBufferId;
import org.projectfloodlight.openflow.types.OFPort;
import org.projectfloodlight.openflow.types.OFVlanVidMatch;
import org.projectfloodlight.openflow.types.TableId;
-import org.projectfloodlight.openflow.types.U32;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -294,19 +289,17 @@
if (!sameSubnet && !targetMac.equals(destMacAddress)) {
int mplsLabel = getMplsLabelFromConfig(targetAddress);
if (mplsLabel > 0) {
- OFAction pushlabel = factory.actions().pushMpls(EthType.MPLS_UNICAST);
- OFOxmMplsLabel l = factory.oxms()
- .mplsLabel(U32.of(mplsLabel));
- OFAction setlabelid = factory.actions().buildSetField()
- .setField(l).build();
- OFAction copyTtlOut = factory.actions().copyTtlOut();
- actions.add(pushlabel);
- actions.add(setlabelid);
- actions.add(copyTtlOut);
+ packet.setEtherType(Ethernet.TYPE_MPLS_UNICAST);
+ MPLS mplsPkt = new MPLS();
+ mplsPkt.setLabel(mplsLabel);
+ mplsPkt.setBos((byte)1);
+ mplsPkt.setTtl(((IPv4) packet.getPayload()).getTtl());
+ mplsPkt.setPayload(((IPv4) packet.getPayload()));
+ packet.setPayload(mplsPkt);
//If the next hop is the DELL switch, then we need to set
// MPLS MAC as the destination MAC
- IOFSwitch sw13 = this.floodlightProvider.getMasterSwitch(
+ /*IOFSwitch sw13 = this.floodlightProvider.getMasterSwitch(
sw.getDpid().value());
if (sw13 == null) {
log.debug("Failed to get the IOFSwitch object for {}", sw);
@@ -320,7 +313,7 @@
.setField(dmac).build();
actions.add(setDAAction);
- }
+ }*/
}
}
diff --git a/src/main/java/net/onrc/onos/core/packet/Ethernet.java b/src/main/java/net/onrc/onos/core/packet/Ethernet.java
index 1eb6d69..cf6bd90 100644
--- a/src/main/java/net/onrc/onos/core/packet/Ethernet.java
+++ b/src/main/java/net/onrc/onos/core/packet/Ethernet.java
@@ -35,6 +35,7 @@
public static final short TYPE_ARP = 0x0806;
public static final short TYPE_RARP = (short) 0x8035;
public static final short TYPE_IPV4 = 0x0800;
+ public static final short TYPE_MPLS_UNICAST = (short)0x8847;
public static final short TYPE_LLDP = (short) 0x88cc;
public static final short TYPE_BSN = (short) 0x8942;
public static final short VLAN_UNTAGGED = (short) 0xffff;
@@ -46,6 +47,7 @@
ETHER_TYPE_CLASS_MAP.put(TYPE_ARP, ARP.class);
ETHER_TYPE_CLASS_MAP.put(TYPE_RARP, ARP.class);
ETHER_TYPE_CLASS_MAP.put(TYPE_IPV4, IPv4.class);
+ ETHER_TYPE_CLASS_MAP.put(TYPE_MPLS_UNICAST, MPLS.class);
ETHER_TYPE_CLASS_MAP.put(TYPE_LLDP, LLDP.class);
}
diff --git a/src/main/java/net/onrc/onos/core/packet/MPLS.java b/src/main/java/net/onrc/onos/core/packet/MPLS.java
new file mode 100644
index 0000000..e7a3e44
--- /dev/null
+++ b/src/main/java/net/onrc/onos/core/packet/MPLS.java
@@ -0,0 +1,111 @@
+package net.onrc.onos.core.packet;
+
+import java.nio.ByteBuffer;
+import java.util.HashMap;
+import java.util.Map;
+
+public class MPLS extends BasePacket {
+ public static final int ADDRESS_LENGTH = 4;
+ public static final byte PROTOCOL_IPv4 = 0x1;
+ public static final byte PROTOCOL_MPLS = 0x6;
+ public static final Map<Byte, Class<? extends IPacket>> PROTOCOL_CLASS_MAP;
+
+ static {
+ PROTOCOL_CLASS_MAP = new HashMap<Byte, Class<? extends IPacket>>();
+ PROTOCOL_CLASS_MAP.put(PROTOCOL_IPv4, IPv4.class);
+ PROTOCOL_CLASS_MAP.put(PROTOCOL_MPLS, MPLS.class);
+ }
+
+ protected int label; //20bits
+ protected byte bos; //1bit
+ protected byte ttl; //8bits
+ protected byte protocol;
+
+ /**
+ * Default constructor that sets the version to 4.
+ */
+ public MPLS() {
+ super();
+ this.bos = 1;
+ this.protocol = PROTOCOL_IPv4;
+ }
+
+ @Override
+ public byte[] serialize() {
+ byte[] payloadData = null;
+ if (payload != null) {
+ payload.setParent(this);
+ payloadData = payload.serialize();
+ }
+
+ byte[] data = new byte[(4 + ((payloadData != null) ? payloadData.length : 0)) ];
+ ByteBuffer bb = ByteBuffer.wrap(data);
+
+ bb.putInt(((this.label & 0x000fffff) << 12) | ((this.bos & 0x1) << 8 | (this.ttl & 0xff)));
+ if (payloadData != null) {
+ bb.put(payloadData);
+ }
+
+ return data;
+ }
+
+ @Override
+ public IPacket deserialize(byte[] data, int offset, int length) {
+ ByteBuffer bb = ByteBuffer.wrap(data, offset, length);
+
+ int mplsheader = bb.getInt();
+ this.label = ((mplsheader & 0xfffff000) >> 12);
+ this.bos = (byte)((mplsheader & 0x00000100) >> 8);
+ this.bos = (byte)(mplsheader & 0x000000ff);
+ this.protocol = (this.bos == 1)?PROTOCOL_IPv4 : PROTOCOL_MPLS;
+
+ IPacket payload;
+ if (IPv4.PROTOCOL_CLASS_MAP.containsKey(this.protocol)) {
+ Class<? extends IPacket> clazz = IPv4.PROTOCOL_CLASS_MAP.get(this.protocol);
+ try {
+ payload = clazz.newInstance();
+ } catch (Exception e) {
+ throw new RuntimeException("Error parsing payload for MPLS packet", e);
+ }
+ } else {
+ payload = new Data();
+ }
+ this.payload = payload.deserialize(data, bb.position(), bb.limit() - bb.position());
+ this.payload.setParent(this);
+
+ return this;
+ }
+
+ public int getLabel() {
+ return label;
+ }
+
+ public void setLabel(int label) {
+ this.label = label;
+ }
+
+ public byte getBos() {
+ return bos;
+ }
+
+ public void setBos(byte bos) {
+ this.bos = bos;
+ }
+
+ public byte getTtl() {
+ return ttl;
+ }
+
+ public void setTtl(byte ttl) {
+ this.ttl = ttl;
+ }
+
+ public byte getProtocol() {
+ return protocol;
+ }
+
+ public void setProtocol(byte protocol) {
+ this.protocol = protocol;
+ }
+
+}
\ No newline at end of file