2 * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.protocol.pcep.impl.tlv;
10 import java.util.BitSet;
12 import org.opendaylight.protocol.concepts.Ipv4Util;
13 import org.opendaylight.protocol.concepts.Ipv6Util;
14 import org.opendaylight.protocol.pcep.PCEPDeserializerException;
15 import org.opendaylight.protocol.pcep.spi.TlvParser;
16 import org.opendaylight.protocol.pcep.spi.TlvSerializer;
17 import org.opendaylight.protocol.util.ByteArray;
18 import org.opendaylight.protocol.util.Util;
19 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
20 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.iana.rev130816.EnterpriseNumber;
21 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.RsvpErrorSpecTlv;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.Tlv;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.lsp.object.tlvs.RsvpErrorSpecBuilder;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.rsvp.error.spec.tlv.ErrorType;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.rsvp.error.spec.tlv.error.type.Rsvp;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.rsvp.error.spec.tlv.error.type.RsvpBuilder;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.rsvp.error.spec.tlv.error.type.User;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.rsvp.error.spec.tlv.error.type.UserBuilder;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.rsvp.error.spec.tlv.error.type.rsvp.RsvpError;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.rsvp.error.spec.tlv.error.type.rsvp.RsvpErrorBuilder;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.rsvp.error.spec.tlv.error.type.user.UserError;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.rsvp.error.spec.tlv.error.type.user.UserErrorBuilder;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.rsvp.rev130820.ErrorSpec.Flags;
35 import com.google.common.primitives.UnsignedBytes;
38 * Parser for {@link RsvpErrorSpecTlv}
40 public final class RSVPErrorSpecTlvParser implements TlvParser, TlvSerializer {
42 public static final int TYPE = 21;
44 private static final int IP4_F_LENGTH = 4;
45 private static final int IP6_F_LENGTH = 16;
46 private static final int FLAGS_F_LENGTH = 1;
47 private static final int ERROR_CODE_F_LENGTH = 1;
48 private static final int ERROR_VALUE_F_LENGTH = 2;
50 private static final int ENTERPRISE_F_LENGTH = 4;
51 private static final int SUB_ORG_F_LENGTH = 1;
52 private static final int ERR_DESCR_LENGTH_F_LENGTH = 1;
53 private static final int USER_VALUE_F_LENGTH = 2;
55 private static final int RSVP_ERROR_CLASS_NUM = 6;
56 private static final int RSVP_IPV4_ERROR_CLASS_TYPE = 1;
57 private static final int RSVP_IPV6_ERROR_CLASS_TYPE = 2;
59 private static final int USER_ERROR_CLASS_NUM = 194;
60 private static final int USER_ERROR_CLASS_TYPE = 1;
62 private static final int IN_PLACE_FLAG_OFFSET = 7;
63 private static final int NOT_GUILTY_FLAGS_OFFSET = 6;
65 private static final int V4_RSVP_LENGTH = 10;
66 private static final int V6_RSVP_LENGTH = 22;
69 public RsvpErrorSpecTlv parseTlv(final byte[] valueBytes) throws PCEPDeserializerException {
70 if (valueBytes == null || valueBytes.length == 0) {
71 throw new IllegalArgumentException("Value bytes array is mandatory. Can't be null or empty.");
74 final int classNum = ByteArray.bytesToInt(ByteArray.subByte(valueBytes, 0, 1));
75 final int classType = ByteArray.bytesToInt(ByteArray.subByte(valueBytes, 1, 1));
77 ErrorType errorType = null;
78 final int byteOffset = 2;
80 if (classNum == RSVP_ERROR_CLASS_NUM) {
81 errorType = parseRsvp(classType, ByteArray.cutBytes(valueBytes, byteOffset));
82 } else if (classNum == USER_ERROR_CLASS_NUM && classType == USER_ERROR_CLASS_TYPE) {
83 errorType = parseUserError(ByteArray.cutBytes(valueBytes, byteOffset));
85 return new RsvpErrorSpecBuilder().setErrorType(errorType).build();
89 public byte[] serializeTlv(final Tlv tlv) {
91 throw new IllegalArgumentException("RSVPErrorSpecTlv is mandatory.");
93 final RsvpErrorSpecTlv rsvp = (RsvpErrorSpecTlv) tlv;
95 if (rsvp.getErrorType().getImplementedInterface().equals(Rsvp.class)) {
96 final Rsvp r = (Rsvp) rsvp.getErrorType();
97 return serializeRsvp(r.getRsvpError());
99 final User u = (User) rsvp.getErrorType();
100 return serializerUserError(u.getUserError());
104 private User parseUserError(final byte[] valueBytes) {
105 final UserErrorBuilder error = new UserErrorBuilder();
107 error.setEnterprise(new EnterpriseNumber(ByteArray.bytesToLong(ByteArray.subByte(valueBytes, byteOffset, ENTERPRISE_F_LENGTH))));
108 byteOffset += ENTERPRISE_F_LENGTH;
109 error.setSubOrg((short) UnsignedBytes.toInt(valueBytes[byteOffset]));
110 byteOffset += SUB_ORG_F_LENGTH;
111 final int errDescrLength = UnsignedBytes.toInt(valueBytes[byteOffset]);
112 byteOffset += ERR_DESCR_LENGTH_F_LENGTH;
113 error.setValue(ByteArray.bytesToInt(ByteArray.subByte(valueBytes, byteOffset, USER_VALUE_F_LENGTH)));
114 byteOffset += USER_VALUE_F_LENGTH;
115 error.setDescription(ByteArray.bytesToHRString(ByteArray.subByte(valueBytes, byteOffset, errDescrLength)));
116 byteOffset += errDescrLength;
117 // TODO: if we have any subobjects
118 return new UserBuilder().setUserError(error.build()).build();
121 private byte[] serializerUserError(final UserError ue) {
122 final byte[] enterprise = ByteArray.subByte(ByteArray.longToBytes(ue.getEnterprise().getValue()), 4, ENTERPRISE_F_LENGTH);
123 final byte suborg = UnsignedBytes.checkedCast(ue.getSubOrg());
124 final byte[] value = ByteArray.subByte(ByteArray.intToBytes(ue.getValue()), 2, USER_VALUE_F_LENGTH);
125 final byte[] desc = (ue.getDescription() == null) ? new byte[0] : ue.getDescription().getBytes();
126 final byte descLen = UnsignedBytes.checkedCast(desc.length);
127 // TODO: if we have any subobjects
128 final byte[] bytes = new byte[2 + ENTERPRISE_F_LENGTH + SUB_ORG_F_LENGTH + USER_VALUE_F_LENGTH + ERR_DESCR_LENGTH_F_LENGTH
130 bytes[0] = UnsignedBytes.checkedCast(USER_ERROR_CLASS_NUM);
131 bytes[1] = UnsignedBytes.checkedCast(USER_ERROR_CLASS_TYPE);
133 ByteArray.copyWhole(enterprise, bytes, offset);
134 offset += ENTERPRISE_F_LENGTH;
135 bytes[offset] = suborg;
136 offset += SUB_ORG_F_LENGTH;
137 bytes[offset] = descLen;
138 offset += ERR_DESCR_LENGTH_F_LENGTH;
139 ByteArray.copyWhole(value, bytes, offset);
140 offset += USER_VALUE_F_LENGTH;
141 ByteArray.copyWhole(desc, bytes, offset);
145 private Rsvp parseRsvp(final int classType, final byte[] valueBytes) {
147 final RsvpErrorBuilder builder = new RsvpErrorBuilder();
148 if (classType == RSVP_IPV4_ERROR_CLASS_TYPE) {
149 builder.setNode(new IpAddress(Ipv4Util.addressForBytes(ByteArray.subByte(valueBytes, byteOffset, IP4_F_LENGTH))));
150 byteOffset += IP4_F_LENGTH;
151 } else if (classType == RSVP_IPV6_ERROR_CLASS_TYPE) {
152 builder.setNode(new IpAddress(Ipv6Util.addressForBytes(ByteArray.subByte(valueBytes, byteOffset, IP6_F_LENGTH))));
153 byteOffset += IP6_F_LENGTH;
155 final BitSet flags = ByteArray.bytesToBitSet(ByteArray.subByte(valueBytes, byteOffset, FLAGS_F_LENGTH));
156 byteOffset += FLAGS_F_LENGTH;
157 builder.setFlags(new Flags(flags.get(IN_PLACE_FLAG_OFFSET), flags.get(NOT_GUILTY_FLAGS_OFFSET)));
158 final short errorCode = (short) (valueBytes[byteOffset] & Util.BYTE_MAX_VALUE_BYTES);
159 byteOffset += ERROR_CODE_F_LENGTH;
160 builder.setCode(errorCode);
161 final int errorValue = (ByteArray.bytesToShort(ByteArray.subByte(valueBytes, byteOffset, ERROR_VALUE_F_LENGTH)) & 0xFFFF);
162 builder.setValue(errorValue);
163 return new RsvpBuilder().setRsvpError(builder.build()).build();
166 private byte[] serializeRsvp(final RsvpError rsvp) {
167 final BitSet flags = new BitSet(FLAGS_F_LENGTH * Byte.SIZE);
168 flags.set(IN_PLACE_FLAG_OFFSET, rsvp.getFlags().isInPlace());
169 flags.set(NOT_GUILTY_FLAGS_OFFSET, rsvp.getFlags().isNotGuilty());
171 final IpAddress node = rsvp.getNode();
173 if (node.getIpv4Address() != null) {
174 bytes = new byte[V4_RSVP_LENGTH];
175 bytes[0] = RSVP_ERROR_CLASS_NUM;
176 bytes[1] = RSVP_IPV4_ERROR_CLASS_TYPE;
178 ByteArray.copyWhole(Ipv4Util.bytesForAddress(node.getIpv4Address()), bytes, offset);
179 offset += IP4_F_LENGTH;
181 bytes = new byte[V6_RSVP_LENGTH];
182 bytes[0] = RSVP_ERROR_CLASS_NUM;
183 bytes[1] = RSVP_IPV6_ERROR_CLASS_TYPE;
185 ByteArray.copyWhole(Ipv6Util.bytesForAddress(node.getIpv6Address()), bytes, offset);
186 offset += IP6_F_LENGTH;
188 bytes[offset] = ByteArray.bitSetToBytes(flags, FLAGS_F_LENGTH)[0];
189 offset += FLAGS_F_LENGTH;
190 bytes[offset] = UnsignedBytes.checkedCast(rsvp.getCode());
191 offset += ERROR_CODE_F_LENGTH;
192 final byte[] value = ByteArray.subByte(ByteArray.intToBytes(rsvp.getValue().intValue()), 2, ERROR_VALUE_F_LENGTH);
193 ByteArray.copyWhole(value, bytes, offset);
198 public int getType() {