MPLS label selector and treatment

Change-Id: Id1fba1e04155e6d97de4c8fd95573641537f1b7a
diff --git a/providers/openflow/flow/src/main/java/org/onlab/onos/provider/of/flow/impl/FlowEntryBuilder.java b/providers/openflow/flow/src/main/java/org/onlab/onos/provider/of/flow/impl/FlowEntryBuilder.java
index 16a32db..d7ebbd8 100644
--- a/providers/openflow/flow/src/main/java/org/onlab/onos/provider/of/flow/impl/FlowEntryBuilder.java
+++ b/providers/openflow/flow/src/main/java/org/onlab/onos/provider/of/flow/impl/FlowEntryBuilder.java
@@ -286,6 +286,10 @@
             case TCP_SRC:
                 builder.matchTcpSrc((short) match.get(MatchField.TCP_SRC).getPort());
                 break;
+            case MPLS_LABEL:
+                builder.matchMplsLabel((int) match.get(MatchField.MPLS_LABEL)
+                                            .getValue());
+                break;
             case OCH_SIGID:
                 builder.matchLambda(match.get(MatchField.OCH_SIGID).getChannelNumber());
                 break;
@@ -312,7 +316,6 @@
             case IP_DSCP:
             case IP_ECN:
             case METADATA:
-            case MPLS_LABEL:
             case MPLS_TC:
             case SCTP_DST:
             case SCTP_SRC:
diff --git a/providers/openflow/flow/src/main/java/org/onlab/onos/provider/of/flow/impl/FlowModBuilder.java b/providers/openflow/flow/src/main/java/org/onlab/onos/provider/of/flow/impl/FlowModBuilder.java
index 1e9256f..cc33f20 100644
--- a/providers/openflow/flow/src/main/java/org/onlab/onos/provider/of/flow/impl/FlowModBuilder.java
+++ b/providers/openflow/flow/src/main/java/org/onlab/onos/provider/of/flow/impl/FlowModBuilder.java
@@ -47,6 +47,7 @@
 import org.projectfloodlight.openflow.types.OFPort;
 import org.projectfloodlight.openflow.types.OFVlanVidMatch;
 import org.projectfloodlight.openflow.types.TransportPort;
+import org.projectfloodlight.openflow.types.U32;
 import org.projectfloodlight.openflow.types.U8;
 import org.projectfloodlight.openflow.types.VlanPcp;
 import org.projectfloodlight.openflow.types.VlanVid;
@@ -195,6 +196,11 @@
                 tp = (TcpPortCriterion) c;
                 mBuilder.setExact(MatchField.TCP_SRC, TransportPort.of(tp.tcpPort()));
                 break;
+            case MPLS_LABEL:
+                Criteria.MplsCriterion mp = (Criteria.MplsCriterion) c;
+                mBuilder.setExact(MatchField.MPLS_LABEL,
+                                  U32.of(mp.label().intValue()));
+                break;
             case OCH_SIGID:
                 LambdaCriterion lc = (LambdaCriterion) c;
                 mBuilder.setExact(MatchField.OCH_SIGID,
@@ -227,7 +233,6 @@
             case IP_ECN:
             case METADATA:
             case MPLS_BOS:
-            case MPLS_LABEL:
             case MPLS_TC:
             case PBB_ISID:
             case SCTP_DST:
diff --git a/providers/openflow/flow/src/main/java/org/onlab/onos/provider/of/flow/impl/FlowModBuilderVer13.java b/providers/openflow/flow/src/main/java/org/onlab/onos/provider/of/flow/impl/FlowModBuilderVer13.java
index 9ed0f58..f7cf9a5 100644
--- a/providers/openflow/flow/src/main/java/org/onlab/onos/provider/of/flow/impl/FlowModBuilderVer13.java
+++ b/providers/openflow/flow/src/main/java/org/onlab/onos/provider/of/flow/impl/FlowModBuilderVer13.java
@@ -29,6 +29,8 @@
 import org.onlab.onos.net.flow.instructions.L2ModificationInstruction.ModEtherInstruction;
 import org.onlab.onos.net.flow.instructions.L2ModificationInstruction.ModVlanIdInstruction;
 import org.onlab.onos.net.flow.instructions.L2ModificationInstruction.ModVlanPcpInstruction;
+import org.onlab.onos.net.flow.instructions.L2ModificationInstruction.ModMplsLabelInstruction;
+import org.onlab.onos.net.flow.instructions.L2ModificationInstruction.PushHeaderInstructions;
 import org.onlab.onos.net.flow.instructions.L3ModificationInstruction;
 import org.onlab.onos.net.flow.instructions.L3ModificationInstruction.ModIPInstruction;
 import org.onlab.packet.Ip4Address;
@@ -41,11 +43,13 @@
 import org.projectfloodlight.openflow.protocol.match.Match;
 import org.projectfloodlight.openflow.protocol.oxm.OFOxm;
 import org.projectfloodlight.openflow.types.CircuitSignalID;
+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.U32;
 import org.projectfloodlight.openflow.types.U64;
 import org.projectfloodlight.openflow.types.VlanPcp;
 import org.slf4j.Logger;
@@ -201,25 +205,42 @@
         ModEtherInstruction eth;
         OFOxm<?> oxm = null;
         switch (l2m.subtype()) {
-        case ETH_DST:
-            eth = (ModEtherInstruction) l2m;
-            oxm = factory().oxms().ethDst(MacAddress.of(eth.mac().toLong()));
-            break;
-        case ETH_SRC:
-            eth = (ModEtherInstruction) l2m;
-            oxm = factory().oxms().ethSrc(MacAddress.of(eth.mac().toLong()));
-            break;
-        case VLAN_ID:
-            ModVlanIdInstruction vlanId = (ModVlanIdInstruction) l2m;
-            oxm = factory().oxms().vlanVid(OFVlanVidMatch.ofVlan(vlanId.vlanId().toShort()));
-            break;
-        case VLAN_PCP:
-            ModVlanPcpInstruction vlanPcp = (ModVlanPcpInstruction) l2m;
-            oxm = factory().oxms().vlanPcp(VlanPcp.of(vlanPcp.vlanPcp()));
-            break;
-        default:
-            log.warn("Unimplemented action type {}.", l2m.subtype());
-            break;
+            case ETH_DST:
+                eth = (ModEtherInstruction) l2m;
+                oxm = factory().oxms().ethDst(MacAddress.of(eth.mac().toLong()));
+                break;
+            case ETH_SRC:
+                eth = (ModEtherInstruction) l2m;
+                oxm = factory().oxms().ethSrc(MacAddress.of(eth.mac().toLong()));
+                break;
+            case VLAN_ID:
+                ModVlanIdInstruction vlanId = (ModVlanIdInstruction) l2m;
+                oxm = factory().oxms().vlanVid(OFVlanVidMatch.ofVlan(vlanId.vlanId().toShort()));
+                break;
+            case VLAN_PCP:
+                ModVlanPcpInstruction vlanPcp = (ModVlanPcpInstruction) l2m;
+                oxm = factory().oxms().vlanPcp(VlanPcp.of(vlanPcp.vlanPcp()));
+                break;
+            case MPLS_PUSH:
+                PushHeaderInstructions pushHeaderInstructions =
+                        (PushHeaderInstructions) l2m;
+                return factory().actions().pushMpls(EthType.of(pushHeaderInstructions
+                                                               .ethernetType().getEtherType()));
+            case MPLS_POP:
+                PushHeaderInstructions  popHeaderInstructions =
+                        (PushHeaderInstructions) l2m;
+                return factory().actions().popMpls(EthType.of(popHeaderInstructions
+                                                          .ethernetType().getEtherType()));
+            case MPLS_LABEL:
+                ModMplsLabelInstruction mplsLabel =
+                        (ModMplsLabelInstruction) l2m;
+                oxm = factory().oxms().mplsLabel(U32.of(mplsLabel.label()
+                                                                  .longValue()));
+
+                break;
+            default:
+                log.warn("Unimplemented action type {}.", l2m.subtype());
+                break;
         }
 
         if (oxm != null) {