Merge "Support proper route redistribution"
[bgpcep.git] / pcep / impl / src / main / java / org / opendaylight / protocol / pcep / impl / object / PCEPRequestParameterObjectParser.java
index 7f37000df912942f52c9e0a602e7618f85ab79b7..b9fc394d8dc438ffd910b462d7ceae9f3bdbbf1e 100644 (file)
 
 package org.opendaylight.protocol.pcep.impl.object;
 
-import java.util.Arrays;
-import java.util.BitSet;
-
+import static org.opendaylight.protocol.util.ByteBufWriteUtil.writeUnsignedInt;
+
+import com.google.common.base.Preconditions;
+import com.google.common.primitives.UnsignedBytes;
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.Unpooled;
+import java.util.List;
+import org.opendaylight.protocol.pcep.spi.AbstractObjectWithTlvsParser;
+import org.opendaylight.protocol.pcep.spi.ObjectUtil;
 import org.opendaylight.protocol.pcep.spi.PCEPDeserializerException;
-import org.opendaylight.protocol.pcep.spi.TlvHandlerRegistry;
-import org.opendaylight.protocol.util.ByteArray;
+import org.opendaylight.protocol.pcep.spi.TlvRegistry;
+import org.opendaylight.protocol.pcep.spi.VendorInformationTlvRegistry;
+import org.opendaylight.protocol.util.BitArray;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.Object;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.ObjectHeader;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.RequestId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.Tlv;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.order.tlv.Order;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.path.setup.type.tlv.PathSetupType;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.rp.object.Rp;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.rp.object.RpBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.rp.object.rp.Tlvs;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.rp.object.rp.TlvsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.vendor.information.tlvs.VendorInformationTlv;
 
 /**
  * Parser for {@link Rp}
  */
-public class PCEPRequestParameterObjectParser extends AbstractObjectWithTlvsParser<RpBuilder> {
-
-       public static final int CLASS = 2;
-
-       public static final int TYPE = 1;
-
-       /*
-        * lengths of fields in bytes
-        */
-       private static final int FLAGS_PRI_MF_LENGTH = 4;
-       private static final int RID_F_LENGTH = 4;
-
-       /*
-        * lengths of subfields inside multi-field in bits
-        */
-       private static final int FLAGS_SF_LENGTH = 29;
-
-       /*
-        * offsets of field in bytes
-        */
-
-       private static final int FLAGS_PRI_MF_OFFSET = 0;
-       private static final int RID_F_OFFSET = FLAGS_PRI_MF_OFFSET + FLAGS_PRI_MF_LENGTH;
-       private static final int TLVS_OFFSET = RID_F_OFFSET + RID_F_LENGTH;
-
-       /*
-        * offsets of subfields inside multi-field in bits
-        */
-
-       private static final int FLAGS_SF_OFFSET = 0;
-       private static final int PRI_SF_OFFSET = FLAGS_SF_OFFSET + FLAGS_SF_LENGTH;
-
-       /*
-        * flags offsets inside flags sub-field in bits
-        */
-
-       private static final int O_FLAG_OFFSET = 26;
-       private static final int B_FLAG_OFFSET = 27;
-       private static final int R_FLAG_OFFSET = 28;
-
-       /*
-        * GCO extension flags offsets inside flags sub-field in bits
-        */
-       private static final int M_FLAG_OFFSET = 21;
-       private static final int D_FLAG_OFFSET = 22;
-
-       /*
-        * Path-key bit (RFC5520)
-        */
-       private static final int P_FLAG_OFFSET = 23;
-       /*
-        * OF extension flags offsets inside flags sub.field in bits
-        */
-       private static final int S_FLAG_OFFSET = 24;
-       /*
-        * RFC6006 flags
-        */
-       private static final int F_FLAG_OFFSET = 18;
-
-       private static final int N_FLAG_OFFSET = 19;
-
-       private static final int E_FLAG_OFFSET = 20;
-
-       public PCEPRequestParameterObjectParser(final TlvHandlerRegistry tlvReg) {
-               super(tlvReg);
-       }
-
-       @Override
-       public Object parseObject(final ObjectHeader header, final byte[] bytes) throws PCEPDeserializerException {
-               if (bytes == null || bytes.length == 0) {
-                       throw new IllegalArgumentException("Array of bytes is mandatory. Can't be null or empty.");
-               }
-
-               final BitSet flags = ByteArray.bytesToBitSet(Arrays.copyOfRange(bytes, FLAGS_PRI_MF_OFFSET, FLAGS_PRI_MF_OFFSET
-                               + FLAGS_PRI_MF_LENGTH));
-               short priority = 0;
-               priority |= flags.get(PRI_SF_OFFSET + 2) ? 1 : 0;
-               priority |= (flags.get(PRI_SF_OFFSET + 1) ? 1 : 0) << 1;
-               priority |= (flags.get(PRI_SF_OFFSET) ? 1 : 0) << 2;
-
-               final RpBuilder builder = new RpBuilder();
-               builder.setIgnore(header.isIgnore());
-               builder.setProcessingRule(header.isProcessingRule());
-
-               builder.setPriority(priority);
-               builder.setFragmentation(flags.get(F_FLAG_OFFSET));
-               builder.setP2mp(flags.get(N_FLAG_OFFSET));
-               builder.setEroCompression(flags.get(E_FLAG_OFFSET));
-               builder.setMakeBeforeBreak(flags.get(M_FLAG_OFFSET));
-               builder.setOrder(flags.get(D_FLAG_OFFSET));
-               builder.setPathKey(flags.get(P_FLAG_OFFSET));
-               builder.setSupplyOf(flags.get(S_FLAG_OFFSET));
-               builder.setLoose(flags.get(O_FLAG_OFFSET));
-               builder.setBiDirectional(flags.get(B_FLAG_OFFSET));
-               builder.setReoptimization(flags.get(R_FLAG_OFFSET));
-
-               builder.setRequestId(new RequestId(ByteArray.bytesToLong(Arrays.copyOfRange(bytes, RID_F_OFFSET, RID_F_OFFSET + RID_F_LENGTH))));
-               parseTlvs(builder, ByteArray.cutBytes(bytes, TLVS_OFFSET));
-
-               return builder.build();
-       }
-
-       @Override
-       public void addTlv(final RpBuilder builder, final Tlv tlv) {
-               if (tlv instanceof Order) {
-                       builder.setTlvs(new TlvsBuilder().setOrder((Order) tlv).build());
-               }
-       }
-
-       @Override
-       public byte[] serializeObject(final Object object) {
-               if (!(object instanceof Rp)) {
-                       throw new IllegalArgumentException("Wrong instance of PCEPObject. Passed " + object.getClass() + ". Needed RpObject.");
-               }
-               final Rp rPObj = (Rp) object;
-               final BitSet flags = new BitSet(FLAGS_PRI_MF_LENGTH * Byte.SIZE);
-
-               flags.set(R_FLAG_OFFSET, rPObj.isReoptimization());
-               flags.set(B_FLAG_OFFSET, rPObj.isBiDirectional());
-               flags.set(O_FLAG_OFFSET, rPObj.isLoose());
-               flags.set(M_FLAG_OFFSET, rPObj.isMakeBeforeBreak());
-               flags.set(D_FLAG_OFFSET, rPObj.isOrder());
-               flags.set(P_FLAG_OFFSET, rPObj.isPathKey());
-               flags.set(S_FLAG_OFFSET, rPObj.isSupplyOf());
-               flags.set(F_FLAG_OFFSET, rPObj.isFragmentation());
-               flags.set(N_FLAG_OFFSET, rPObj.isP2mp());
-               flags.set(E_FLAG_OFFSET, rPObj.isEroCompression());
-
-               flags.set(PRI_SF_OFFSET, (rPObj.getPriority() & 1 << 2) != 0);
-               flags.set(PRI_SF_OFFSET + 1, (rPObj.getPriority() & 1 << 1) != 0);
-               flags.set(PRI_SF_OFFSET + 2, (rPObj.getPriority() & 1) != 0);
-
-               final byte[] tlvs = serializeTlvs(rPObj.getTlvs());
-               final byte[] retBytes = new byte[TLVS_OFFSET + tlvs.length + getPadding(TLVS_OFFSET + tlvs.length, PADDED_TO)];
-
-               ByteArray.copyWhole(ByteArray.bitSetToBytes(flags, FLAGS_PRI_MF_LENGTH), retBytes, FLAGS_PRI_MF_OFFSET);
-               ByteArray.copyWhole(ByteArray.longToBytes(rPObj.getRequestId().getValue(), RID_F_LENGTH), retBytes, RID_F_OFFSET);
-               if (tlvs.length != 0) {
-                       ByteArray.copyWhole(tlvs, retBytes, TLVS_OFFSET);
-               }
-               return ObjectUtil.formatSubobject(TYPE, CLASS, object.isProcessingRule(), object.isIgnore(), retBytes);
-       }
-
-       public byte[] serializeTlvs(final Tlvs tlvs) {
-               if (tlvs == null) {
-                       return new byte[0];
-               } else if (tlvs.getOrder() != null) {
-                       return serializeTlv(tlvs.getOrder());
-               }
-               return new byte[0];
-       }
-
-       @Override
-       public int getObjectType() {
-               return TYPE;
-       }
-
-       @Override
-       public int getObjectClass() {
-               return CLASS;
-       }
+public class PCEPRequestParameterObjectParser extends AbstractObjectWithTlvsParser<TlvsBuilder> {
+
+    public static final int CLASS = 2;
+
+    public static final int TYPE = 1;
+
+    /*
+     * lengths of fields in bytes
+     */
+    private static final int FLAGS_SIZE = 32;
+
+    /*
+     * lengths of subfields inside multi-field in bits
+     */
+    private static final int FLAGS_SF_LENGTH = 29;
+
+    /*
+     * offsets of subfields inside multi-field in bits
+     */
+
+    private static final int FLAGS_SF_OFFSET = 0;
+    private static final int PRI_SF_OFFSET = FLAGS_SF_OFFSET + FLAGS_SF_LENGTH;
+
+    /*
+     * flags offsets inside flags sub-field in bits
+     */
+
+    private static final int O_FLAG_OFFSET = 26;
+    private static final int B_FLAG_OFFSET = 27;
+    private static final int R_FLAG_OFFSET = 28;
+
+    /*
+     * GCO extension flags offsets inside flags sub-field in bits
+     */
+    private static final int M_FLAG_OFFSET = 21;
+    private static final int D_FLAG_OFFSET = 22;
+
+    /*
+     * Path-key bit (RFC5520)
+     */
+    private static final int P_FLAG_OFFSET = 23;
+    /*
+     * OF extension flags offsets inside flags sub.field in bits
+     */
+    private static final int S_FLAG_OFFSET = 24;
+    /*
+     * RFC6006 flags
+     */
+    private static final int F_FLAG_OFFSET = 18;
+
+    private static final int N_FLAG_OFFSET = 19;
+
+    private static final int E_FLAG_OFFSET = 20;
+
+    public PCEPRequestParameterObjectParser(final TlvRegistry tlvReg, final VendorInformationTlvRegistry viTlvReg) {
+        super(tlvReg, viTlvReg);
+    }
+
+    @Override
+    public Object parseObject(final ObjectHeader header, final ByteBuf bytes) throws PCEPDeserializerException {
+        Preconditions.checkArgument(bytes != null && bytes.isReadable(), "Array of bytes is mandatory. Can't be null or empty.");
+        final BitArray flags = BitArray.valueOf(bytes, FLAGS_SIZE);
+
+        final RpBuilder builder = new RpBuilder();
+        builder.setIgnore(header.isIgnore());
+        builder.setProcessingRule(header.isProcessingRule());
+
+        short priority = 0;
+        priority |= flags.get(PRI_SF_OFFSET + 2) ? 1 : 0;
+        priority |= (flags.get(PRI_SF_OFFSET + 1) ? 1 : 0) << 1;
+        priority |= (flags.get(PRI_SF_OFFSET) ? 1 : 0) << 2;
+        builder.setPriority(priority);
+        builder.setFragmentation(flags.get(F_FLAG_OFFSET));
+        builder.setP2mp(flags.get(N_FLAG_OFFSET));
+        builder.setEroCompression(flags.get(E_FLAG_OFFSET));
+        builder.setMakeBeforeBreak(flags.get(M_FLAG_OFFSET));
+        builder.setOrder(flags.get(D_FLAG_OFFSET));
+        builder.setPathKey(flags.get(P_FLAG_OFFSET));
+        builder.setSupplyOf(flags.get(S_FLAG_OFFSET));
+        builder.setLoose(flags.get(O_FLAG_OFFSET));
+        builder.setBiDirectional(flags.get(B_FLAG_OFFSET));
+        builder.setReoptimization(flags.get(R_FLAG_OFFSET));
+
+        builder.setRequestId(new RequestId(bytes.readUnsignedInt()));
+        final TlvsBuilder tlvsBuilder = new TlvsBuilder();
+        parseTlvs(tlvsBuilder, bytes.slice());
+        builder.setTlvs(tlvsBuilder.build());
+        return builder.build();
+    }
+
+    @Override
+    public void addTlv(final TlvsBuilder builder, final Tlv tlv) {
+        if (tlv instanceof Order) {
+            builder.setOrder((Order) tlv);
+        }
+        if (tlv instanceof PathSetupType) {
+            builder.setPathSetupType((PathSetupType) tlv);
+        }
+    }
+
+    @Override
+    public void serializeObject(final Object object, final ByteBuf buffer) {
+        Preconditions.checkArgument(object instanceof Rp, "Wrong instance of PCEPObject. Passed %s. Needed RPObject.", object.getClass());
+        final ByteBuf body = Unpooled.buffer();
+        final Rp rpObj = (Rp) object;
+        final BitArray flags = new BitArray(FLAGS_SIZE);
+        flags.set(R_FLAG_OFFSET, rpObj.isReoptimization());
+        flags.set(B_FLAG_OFFSET, rpObj.isBiDirectional());
+        flags.set(O_FLAG_OFFSET, rpObj.isLoose());
+        flags.set(M_FLAG_OFFSET, rpObj.isMakeBeforeBreak());
+        flags.set(D_FLAG_OFFSET, rpObj.isOrder());
+        flags.set(P_FLAG_OFFSET, rpObj.isPathKey());
+        flags.set(S_FLAG_OFFSET, rpObj.isSupplyOf());
+        flags.set(F_FLAG_OFFSET, rpObj.isFragmentation());
+        flags.set(N_FLAG_OFFSET, rpObj.isP2mp());
+        flags.set(E_FLAG_OFFSET, rpObj.isEroCompression());
+        final byte[] res = flags.array();
+        if (rpObj.getPriority() != null) {
+            final byte p = UnsignedBytes.checkedCast(rpObj.getPriority().shortValue());
+            res[res.length -1] = (byte) (res[res.length -1] | p);
+        }
+        body.writeBytes(res);
+        Preconditions.checkArgument(rpObj.getRequestId() != null, "RequestId is mandatory");
+        writeUnsignedInt(rpObj.getRequestId().getValue(), body);
+        serializeTlvs(rpObj.getTlvs(), body);
+        ObjectUtil.formatSubobject(TYPE, CLASS, object.isProcessingRule(), object.isIgnore(), body, buffer);
+    }
+
+    public void serializeTlvs(final Tlvs tlvs, final ByteBuf body) {
+        if (tlvs == null) {
+            return;
+        }
+        if (tlvs.getOrder() != null) {
+            serializeTlv(tlvs.getOrder(), body);
+        }
+        if (tlvs.getPathSetupType() != null) {
+            serializeTlv(tlvs.getPathSetupType(), body);
+        }
+        serializeVendorInformationTlvs(tlvs.getVendorInformationTlv(), body);
+    }
+
+    @Override
+    protected final void addVendorInformationTlvs(final TlvsBuilder builder, final List<VendorInformationTlv> tlvs) {
+        if (!tlvs.isEmpty()) {
+            builder.setVendorInformationTlv(tlvs);
+        }
+    }
 }