@Override
  public ExtensionSelector mapOxm(OFOxm<?> oxm) {
    VlanId vlanId;

    if (oxm.getMatchField().equals(MatchField.VLAN_VID)) {
      if (oxm.isMasked()) {
        OFVlanVidMatch vid = ((OFOxmVlanVidMasked) oxm).getValue();
        OFVlanVidMatch mask = ((OFOxmVlanVidMasked) oxm).getMask();

        if (vid.equals(OFVlanVidMatch.ofRawVid((short) 0))) {
          vlanId = VlanId.NONE;
        } else if (vid.equals(OFVlanVidMatch.PRESENT) && mask.equals(OFVlanVidMatch.PRESENT)) {
          vlanId = VlanId.ANY;
        } else {
          vlanId = VlanId.vlanId(vid.getVlan());
        }
      } else {
        OFVlanVidMatch vid = ((OFOxmVlanVid) oxm).getValue();

        if (!vid.isPresentBitSet()) {
          vlanId = VlanId.NONE;
        } else {
          vlanId = VlanId.vlanId(vid.getVlan());
        }
      }
      return new OfdpaMatchVlanVid(vlanId);
    }
    throw new UnsupportedOperationException("Unexpected OXM: " + oxm.toString());
  }
  @Override
  public int hashCode() {
    final int prime = 31;
    int result = 1;

    result = prime * result + ((value == null) ? 0 : value.hashCode());
    return result;
  }
  private OFAction buildL2Modification(Instruction i) {
    L2ModificationInstruction l2m = (L2ModificationInstruction) i;
    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;
      case MPLS_PUSH:
        PushHeaderInstructions pushHeaderInstructions = (PushHeaderInstructions) l2m;
        return factory()
            .actions()
            .pushMpls(EthType.of(pushHeaderInstructions.ethernetType().toShort()));
      case MPLS_POP:
        PushHeaderInstructions popHeaderInstructions = (PushHeaderInstructions) l2m;
        return factory()
            .actions()
            .popMpls(EthType.of(popHeaderInstructions.ethernetType().toShort()));
      case MPLS_LABEL:
        ModMplsLabelInstruction mplsLabel = (ModMplsLabelInstruction) l2m;
        oxm = factory().oxms().mplsLabel(U32.of(mplsLabel.label().longValue()));
        break;
      case DEC_MPLS_TTL:
        return factory().actions().decMplsTtl();
      case VLAN_POP:
        return factory().actions().popVlan();
      case VLAN_PUSH:
        PushHeaderInstructions pushVlanInstruction = (PushHeaderInstructions) l2m;
        return factory()
            .actions()
            .pushVlan(EthType.of(pushVlanInstruction.ethernetType().toShort()));
      default:
        log.warn("Unimplemented action type {}.", l2m.subtype());
        break;
    }

    if (oxm != null) {
      return factory().actions().buildSetField().setField(oxm).build();
    }
    return null;
  }
 @Override
 public OFOxm<?> mapSelector(OFFactory factory, ExtensionSelector extensionSelector) {
   ExtensionSelectorType type = extensionSelector.type();
   if (type.equals(ExtensionSelectorType.ExtensionSelectorTypes.OFDPA_MATCH_VLAN_VID.type())) {
     VlanId vlanId = ((OfdpaMatchVlanVid) extensionSelector).vlanId();
     // Special VLAN 0x0000/0x1FFF required by OFDPA
     if (vlanId.equals(VlanId.NONE)) {
       OFVlanVidMatch vid = OFVlanVidMatch.ofRawVid((short) 0x0000);
       OFVlanVidMatch mask = OFVlanVidMatch.ofRawVid((short) 0x1FFF);
       return factory.oxms().vlanVidMasked(vid, mask);
       // Normal case
     } else if (vlanId.equals(VlanId.ANY)) {
       return factory.oxms().vlanVidMasked(OFVlanVidMatch.PRESENT, OFVlanVidMatch.PRESENT);
     } else {
       return factory.oxms().vlanVid(OFVlanVidMatch.ofVlanVid(VlanVid.ofVlan(vlanId.toShort())));
     }
   }
   throw new UnsupportedOperationException(
       "Unexpected ExtensionSelector: " + extensionSelector.toString());
 }
  @Override
  public boolean equals(Object obj) {
    if (this == obj) return true;
    if (obj == null) return false;
    if (getClass() != obj.getClass()) return false;
    OFOxmVlanVidVer14 other = (OFOxmVlanVidVer14) obj;

    if (value == null) {
      if (other.value != null) return false;
    } else if (!value.equals(other.value)) return false;
    return true;
  }
    @Override
    public OFOxmVlanVid readFrom(ChannelBuffer bb) throws OFParseError {
      // fixed value property typeLen == 0x80000c02L
      int typeLen = bb.readInt();
      if (typeLen != (int) 0x80000c02)
        throw new OFParseError("Wrong typeLen: Expected=0x80000c02L(0x80000c02L), got=" + typeLen);
      OFVlanVidMatch value = OFVlanVidMatch.read2Bytes(bb);

      OFOxmVlanVidVer14 oxmVlanVidVer14 = new OFOxmVlanVidVer14(value);
      if (logger.isTraceEnabled()) logger.trace("readFrom - read={}", oxmVlanVidVer14);
      return oxmVlanVidVer14;
    }