Bumped to ietf-stateful-02.
[bgpcep.git] / pcep / impl / src / main / java / org / opendaylight / protocol / pcep / impl / stateful02 / RSVPErrorSpecTlvParser.java
1 /*
2  * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
3  *
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
7  */
8 package org.opendaylight.protocol.pcep.impl.stateful02;
9
10 import java.util.BitSet;
11
12 import org.opendaylight.protocol.concepts.Ipv4Util;
13 import org.opendaylight.protocol.concepts.Ipv6Util;
14 import org.opendaylight.protocol.pcep.spi.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.Values;
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.crabbe.stateful._02.rev140110.rsvp.error.spec.tlv.RsvpErrorSpec;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.crabbe.stateful._02.rev140110.rsvp.error.spec.tlv.RsvpErrorSpecBuilder;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.crabbe.stateful._02.rev140110.rsvp.error.spec.tlv.rsvp.error.spec.ErrorType;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.crabbe.stateful._02.rev140110.rsvp.error.spec.tlv.rsvp.error.spec.error.type.RsvpCase;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.crabbe.stateful._02.rev140110.rsvp.error.spec.tlv.rsvp.error.spec.error.type.RsvpCaseBuilder;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.crabbe.stateful._02.rev140110.rsvp.error.spec.tlv.rsvp.error.spec.error.type.UserCase;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.crabbe.stateful._02.rev140110.rsvp.error.spec.tlv.rsvp.error.spec.error.type.UserCaseBuilder;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.crabbe.stateful._02.rev140110.rsvp.error.spec.tlv.rsvp.error.spec.error.type.rsvp._case.RsvpError;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.crabbe.stateful._02.rev140110.rsvp.error.spec.tlv.rsvp.error.spec.error.type.rsvp._case.RsvpErrorBuilder;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.crabbe.stateful._02.rev140110.rsvp.error.spec.tlv.rsvp.error.spec.error.type.user._case.UserError;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.crabbe.stateful._02.rev140110.rsvp.error.spec.tlv.rsvp.error.spec.error.type.user._case.UserErrorBuilder;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.Tlv;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.rsvp.rev130820.ErrorSpec.Flags;
34
35 import com.google.common.primitives.UnsignedBytes;
36
37 /**
38  * Parser for {@link RsvpErrorSpec}
39  */
40 public final class RSVPErrorSpecTlvParser implements TlvParser, TlvSerializer {
41
42         public static final int TYPE = 21;
43
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;
49
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;
54
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;
58
59         private static final int USER_ERROR_CLASS_NUM = 194;
60         private static final int USER_ERROR_CLASS_TYPE = 1;
61
62         private static final int IN_PLACE_FLAG_OFFSET = 7;
63         private static final int NOT_GUILTY_FLAGS_OFFSET = 6;
64
65         private static final int V4_RSVP_LENGTH = 10;
66         private static final int V6_RSVP_LENGTH = 22;
67
68         @Override
69         public RsvpErrorSpec 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.");
72                 }
73
74                 final int classNum = ByteArray.bytesToInt(ByteArray.subByte(valueBytes, 0, 1));
75                 final int classType = ByteArray.bytesToInt(ByteArray.subByte(valueBytes, 1, 1));
76
77                 ErrorType errorType = null;
78                 final int byteOffset = 2;
79
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));
84                 }
85                 return new RsvpErrorSpecBuilder().setErrorType(errorType).build();
86         }
87
88         @Override
89         public byte[] serializeTlv(final Tlv tlv) {
90                 if (tlv == null) {
91                         throw new IllegalArgumentException("RSVPErrorSpecTlv is mandatory.");
92                 }
93                 final RsvpErrorSpec rsvp = (RsvpErrorSpec) tlv;
94
95                 if (rsvp.getErrorType().getImplementedInterface().equals(RsvpCase.class)) {
96                         final RsvpCase r = (RsvpCase) rsvp.getErrorType();
97                         return serializeRsvp(r.getRsvpError());
98                 } else {
99                         final UserCase u = (UserCase) rsvp.getErrorType();
100                         return serializerUserError(u.getUserError());
101                 }
102         }
103
104         private UserCase parseUserError(final byte[] valueBytes) {
105                 final UserErrorBuilder error = new UserErrorBuilder();
106                 int byteOffset = 0;
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                 // if we have any subobjects, place the implementation here
118                 return new UserCaseBuilder().setUserError(error.build()).build();
119         }
120
121         private byte[] serializerUserError(final UserError ue) {
122                 final byte[] enterprise = ByteArray.longToBytes(ue.getEnterprise().getValue(), ENTERPRISE_F_LENGTH);
123                 final byte suborg = UnsignedBytes.checkedCast(ue.getSubOrg());
124                 final byte[] value = ByteArray.intToBytes(ue.getValue(), 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                 // if we have any subobjects, place the implementation here
128                 final byte[] bytes = new byte[2 + ENTERPRISE_F_LENGTH + SUB_ORG_F_LENGTH + USER_VALUE_F_LENGTH + ERR_DESCR_LENGTH_F_LENGTH
129                                 + desc.length];
130                 bytes[0] = UnsignedBytes.checkedCast(USER_ERROR_CLASS_NUM);
131                 bytes[1] = UnsignedBytes.checkedCast(USER_ERROR_CLASS_TYPE);
132                 int offset = 2;
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);
142                 return bytes;
143         }
144
145         private RsvpCase parseRsvp(final int classType, final byte[] valueBytes) {
146                 int byteOffset = 0;
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;
154                 }
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] & Values.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 RsvpCaseBuilder().setRsvpError(builder.build()).build();
164         }
165
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());
170                 int offset = 0;
171                 final IpAddress node = rsvp.getNode();
172                 byte[] bytes;
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;
177                         offset += 2;
178                         ByteArray.copyWhole(Ipv4Util.bytesForAddress(node.getIpv4Address()), bytes, offset);
179                         offset += IP4_F_LENGTH;
180                 } else {
181                         bytes = new byte[V6_RSVP_LENGTH];
182                         bytes[0] = RSVP_ERROR_CLASS_NUM;
183                         bytes[1] = RSVP_IPV6_ERROR_CLASS_TYPE;
184                         offset += 2;
185                         ByteArray.copyWhole(Ipv6Util.bytesForAddress(node.getIpv6Address()), bytes, offset);
186                         offset += IP6_F_LENGTH;
187                 }
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.intToBytes(rsvp.getValue().intValue(), ERROR_VALUE_F_LENGTH);
193                 ByteArray.copyWhole(value, bytes, offset);
194                 return bytes;
195         }
196
197         @Override
198         public int getType() {
199                 return TYPE;
200         }
201 }