BUG-612 : switched PCEP Tlvs to ByteBuf
[bgpcep.git] / pcep / ietf-stateful07 / src / main / java / org / opendaylight / protocol / pcep / ietf / stateful07 / Stateful07RSVPErrorSpecTlvParser.java
1 /*
2  * Copyright (c) 2013 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.ietf.stateful07;
9
10 import io.netty.buffer.ByteBuf;
11
12 import java.util.BitSet;
13
14 import org.opendaylight.protocol.concepts.Ipv4Util;
15 import org.opendaylight.protocol.concepts.Ipv6Util;
16 import org.opendaylight.protocol.pcep.impl.tlv.TlvUtil;
17 import org.opendaylight.protocol.pcep.spi.PCEPDeserializerException;
18 import org.opendaylight.protocol.pcep.spi.TlvParser;
19 import org.opendaylight.protocol.pcep.spi.TlvSerializer;
20 import org.opendaylight.protocol.util.ByteArray;
21 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.iana.rev130816.EnterpriseNumber;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.rsvp.error.spec.tlv.RsvpErrorSpec;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.rsvp.error.spec.tlv.RsvpErrorSpecBuilder;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.rsvp.error.spec.tlv.rsvp.error.spec.ErrorType;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.rsvp.error.spec.tlv.rsvp.error.spec.error.type.RsvpCase;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.rsvp.error.spec.tlv.rsvp.error.spec.error.type.RsvpCaseBuilder;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.rsvp.error.spec.tlv.rsvp.error.spec.error.type.UserCase;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.rsvp.error.spec.tlv.rsvp.error.spec.error.type.UserCaseBuilder;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.rsvp.error.spec.tlv.rsvp.error.spec.error.type.rsvp._case.RsvpError;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.rsvp.error.spec.tlv.rsvp.error.spec.error.type.rsvp._case.RsvpErrorBuilder;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.rsvp.error.spec.tlv.rsvp.error.spec.error.type.user._case.UserError;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.rsvp.error.spec.tlv.rsvp.error.spec.error.type.user._case.UserErrorBuilder;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.Tlv;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.rsvp.rev130820.ErrorSpec.Flags;
36
37 import com.google.common.primitives.UnsignedBytes;
38
39 /**
40  * Parser for {@link RsvpErrorSpec}
41  */
42 public final class Stateful07RSVPErrorSpecTlvParser implements TlvParser, TlvSerializer {
43
44         public static final int TYPE = 21;
45
46         private static final int IP4_F_LENGTH = 4;
47         private static final int IP6_F_LENGTH = 16;
48         private static final int FLAGS_F_LENGTH = 1;
49         private static final int ERROR_CODE_F_LENGTH = 1;
50         private static final int ERROR_VALUE_F_LENGTH = 2;
51
52         private static final int ENTERPRISE_F_LENGTH = 4;
53         private static final int SUB_ORG_F_LENGTH = 1;
54         private static final int ERR_DESCR_LENGTH_F_LENGTH = 1;
55         private static final int USER_VALUE_F_LENGTH = 2;
56
57         private static final int RSVP_ERROR_CLASS_NUM = 6;
58         private static final int RSVP_IPV4_ERROR_CLASS_TYPE = 1;
59         private static final int RSVP_IPV6_ERROR_CLASS_TYPE = 2;
60
61         private static final int USER_ERROR_CLASS_NUM = 194;
62         private static final int USER_ERROR_CLASS_TYPE = 1;
63
64         private static final int IN_PLACE_FLAG_OFFSET = 7;
65         private static final int NOT_GUILTY_FLAGS_OFFSET = 6;
66
67         private static final int V4_RSVP_LENGTH = 10;
68         private static final int V6_RSVP_LENGTH = 22;
69
70         @Override
71         public RsvpErrorSpec parseTlv(final ByteBuf buffer) throws PCEPDeserializerException {
72                 if (buffer == null) {
73                         return null;
74                 }
75                 final int classNum = UnsignedBytes.toInt(buffer.readByte());
76                 final int classType = UnsignedBytes.toInt(buffer.readByte());
77                 ErrorType errorType = null;
78                 if (classNum == RSVP_ERROR_CLASS_NUM) {
79                         errorType = parseRsvp(classType, buffer.slice());
80                 } else if (classNum == USER_ERROR_CLASS_NUM && classType == USER_ERROR_CLASS_TYPE) {
81                         errorType = parseUserError(buffer.slice());
82                 }
83                 return new RsvpErrorSpecBuilder().setErrorType(errorType).build();
84         }
85
86         @Override
87         public byte[] serializeTlv(final Tlv tlv) {
88                 if (tlv == null) {
89                         throw new IllegalArgumentException("RSVPErrorSpecTlv is mandatory.");
90                 }
91                 final RsvpErrorSpec rsvp = (RsvpErrorSpec) tlv;
92
93                 if (rsvp.getErrorType().getImplementedInterface().equals(RsvpCase.class)) {
94                         final RsvpCase r = (RsvpCase) rsvp.getErrorType();
95                         return TlvUtil.formatTlv(TYPE, serializeRsvp(r.getRsvpError()));
96                 } else {
97                         final UserCase u = (UserCase) rsvp.getErrorType();
98                         return TlvUtil.formatTlv(TYPE, serializerUserError(u.getUserError()));
99                 }
100         }
101
102         private UserCase parseUserError(final ByteBuf buffer) {
103                 final UserErrorBuilder error = new UserErrorBuilder();
104                 error.setEnterprise(new EnterpriseNumber(buffer.readUnsignedInt()));
105                 error.setSubOrg((short) UnsignedBytes.toInt(buffer.readByte()));
106                 final int errDescrLength = UnsignedBytes.toInt(buffer.readByte());
107                 error.setValue(buffer.readUnsignedShort());
108                 error.setDescription(ByteArray.bytesToHRString(ByteArray.readBytes(buffer, errDescrLength)));
109                 // if we have any subobjects, place the implementation here
110                 return new UserCaseBuilder().setUserError(error.build()).build();
111         }
112
113         private byte[] serializerUserError(final UserError ue) {
114                 final byte[] enterprise = ByteArray.longToBytes(ue.getEnterprise().getValue(), ENTERPRISE_F_LENGTH);
115                 final byte suborg = UnsignedBytes.checkedCast(ue.getSubOrg());
116                 final byte[] value = ByteArray.intToBytes(ue.getValue(), USER_VALUE_F_LENGTH);
117                 final byte[] desc = (ue.getDescription() == null) ? new byte[0] : ue.getDescription().getBytes();
118                 final byte descLen = UnsignedBytes.checkedCast(desc.length);
119                 // if we have any subobjects, place the implementation here
120                 final byte[] bytes = new byte[2 + ENTERPRISE_F_LENGTH + SUB_ORG_F_LENGTH + USER_VALUE_F_LENGTH + ERR_DESCR_LENGTH_F_LENGTH
121                                               + desc.length];
122                 bytes[0] = UnsignedBytes.checkedCast(USER_ERROR_CLASS_NUM);
123                 bytes[1] = UnsignedBytes.checkedCast(USER_ERROR_CLASS_TYPE);
124                 int offset = 2;
125                 ByteArray.copyWhole(enterprise, bytes, offset);
126                 offset += ENTERPRISE_F_LENGTH;
127                 bytes[offset] = suborg;
128                 offset += SUB_ORG_F_LENGTH;
129                 bytes[offset] = descLen;
130                 offset += ERR_DESCR_LENGTH_F_LENGTH;
131                 ByteArray.copyWhole(value, bytes, offset);
132                 offset += USER_VALUE_F_LENGTH;
133                 ByteArray.copyWhole(desc, bytes, offset);
134                 return bytes;
135         }
136
137         private RsvpCase parseRsvp(final int classType, final ByteBuf buffer) {
138                 final RsvpErrorBuilder builder = new RsvpErrorBuilder();
139                 if (classType == RSVP_IPV4_ERROR_CLASS_TYPE) {
140                         builder.setNode(new IpAddress(Ipv4Util.addressForBytes(ByteArray.readBytes(buffer, IP4_F_LENGTH))));
141                 } else if (classType == RSVP_IPV6_ERROR_CLASS_TYPE) {
142                         builder.setNode(new IpAddress(Ipv6Util.addressForBytes(ByteArray.readBytes(buffer, IP6_F_LENGTH))));
143                 }
144                 final BitSet flags = ByteArray.bytesToBitSet(ByteArray.readBytes(buffer, FLAGS_F_LENGTH));
145                 builder.setFlags(new Flags(flags.get(IN_PLACE_FLAG_OFFSET), flags.get(NOT_GUILTY_FLAGS_OFFSET)));
146                 final short errorCode = buffer.readUnsignedByte();
147                 builder.setCode(errorCode);
148                 final int errorValue = buffer.readUnsignedShort();
149                 builder.setValue(errorValue);
150                 return new RsvpCaseBuilder().setRsvpError(builder.build()).build();
151         }
152
153         private byte[] serializeRsvp(final RsvpError rsvp) {
154                 final BitSet flags = new BitSet(FLAGS_F_LENGTH * Byte.SIZE);
155                 flags.set(IN_PLACE_FLAG_OFFSET, rsvp.getFlags().isInPlace());
156                 flags.set(NOT_GUILTY_FLAGS_OFFSET, rsvp.getFlags().isNotGuilty());
157                 int offset = 0;
158                 final IpAddress node = rsvp.getNode();
159                 byte[] bytes;
160                 if (node.getIpv4Address() != null) {
161                         bytes = new byte[V4_RSVP_LENGTH];
162                         bytes[0] = RSVP_ERROR_CLASS_NUM;
163                         bytes[1] = RSVP_IPV4_ERROR_CLASS_TYPE;
164                         offset += 2;
165                         ByteArray.copyWhole(Ipv4Util.bytesForAddress(node.getIpv4Address()), bytes, offset);
166                         offset += IP4_F_LENGTH;
167                 } else {
168                         bytes = new byte[V6_RSVP_LENGTH];
169                         bytes[0] = RSVP_ERROR_CLASS_NUM;
170                         bytes[1] = RSVP_IPV6_ERROR_CLASS_TYPE;
171                         offset += 2;
172                         ByteArray.copyWhole(Ipv6Util.bytesForAddress(node.getIpv6Address()), bytes, offset);
173                         offset += IP6_F_LENGTH;
174                 }
175                 bytes[offset] = ByteArray.bitSetToBytes(flags, FLAGS_F_LENGTH)[0];
176                 offset += FLAGS_F_LENGTH;
177                 bytes[offset] = UnsignedBytes.checkedCast(rsvp.getCode());
178                 offset += ERROR_CODE_F_LENGTH;
179                 final byte[] value = ByteArray.intToBytes(rsvp.getValue().intValue(), ERROR_VALUE_F_LENGTH);
180                 ByteArray.copyWhole(value, bytes, offset);
181                 return bytes;
182         }
183 }