BUG-2794 : refactored code to use BitArray
[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 static org.opendaylight.protocol.util.ByteBufWriteUtil.writeIpv4Address;
11 import static org.opendaylight.protocol.util.ByteBufWriteUtil.writeIpv6Address;
12 import static org.opendaylight.protocol.util.ByteBufWriteUtil.writeUnsignedByte;
13 import static org.opendaylight.protocol.util.ByteBufWriteUtil.writeUnsignedInt;
14 import static org.opendaylight.protocol.util.ByteBufWriteUtil.writeUnsignedShort;
15
16 import com.google.common.base.Charsets;
17 import com.google.common.base.Preconditions;
18 import io.netty.buffer.ByteBuf;
19 import io.netty.buffer.Unpooled;
20 import org.opendaylight.protocol.pcep.spi.PCEPDeserializerException;
21 import org.opendaylight.protocol.pcep.spi.TlvParser;
22 import org.opendaylight.protocol.pcep.spi.TlvSerializer;
23 import org.opendaylight.protocol.pcep.spi.TlvUtil;
24 import org.opendaylight.protocol.util.BitArray;
25 import org.opendaylight.protocol.util.ByteArray;
26 import org.opendaylight.protocol.util.Ipv4Util;
27 import org.opendaylight.protocol.util.Ipv6Util;
28 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.iana.rev130816.EnterpriseNumber;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.rsvp.error.spec.tlv.RsvpErrorSpec;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.rsvp.error.spec.tlv.RsvpErrorSpecBuilder;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.rsvp.error.spec.tlv.rsvp.error.spec.ErrorType;
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.RsvpCase;
34 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;
35 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;
36 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;
37 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;
38 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;
39 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;
40 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;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.Tlv;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.rsvp.rev130820.ErrorSpec.Flags;
43
44 /**
45  * Parser for {@link RsvpErrorSpec}
46  */
47 public final class Stateful07RSVPErrorSpecTlvParser implements TlvParser, TlvSerializer {
48
49     public static final int TYPE = 21;
50
51     private static final int FLAGS_SIZE = 8;
52     private static final int HEADER_LENGTH = 4;
53
54     private static final int RSVP_ERROR_CLASS_NUM = 6;
55     private static final int RSVP_IPV4_ERROR_CLASS_TYPE = 1;
56     private static final int RSVP_IPV6_ERROR_CLASS_TYPE = 2;
57
58     private static final int USER_ERROR_CLASS_NUM = 194;
59     private static final int USER_ERROR_CLASS_TYPE = 1;
60
61     private static final int IN_PLACE = 7;
62     private static final int NOT_GUILTY = 6;
63
64     @Override
65     public RsvpErrorSpec parseTlv(final ByteBuf buffer) throws PCEPDeserializerException {
66         if (buffer == null) {
67             return null;
68         }
69         // throw away contents of length field
70         buffer.readUnsignedShort();
71         final int classNum = buffer.readUnsignedByte();
72         final int classType = buffer.readUnsignedByte();
73         ErrorType errorType = null;
74         if (classNum == RSVP_ERROR_CLASS_NUM) {
75             errorType = parseRsvp(classType, buffer.slice());
76         } else if (classNum == USER_ERROR_CLASS_NUM && classType == USER_ERROR_CLASS_TYPE) {
77             errorType = parseUserError(buffer.slice());
78         }
79         return new RsvpErrorSpecBuilder().setErrorType(errorType).build();
80     }
81
82     @Override
83     public void serializeTlv(final Tlv tlv, final ByteBuf buffer) {
84         Preconditions.checkArgument(tlv instanceof RsvpErrorSpec, "RSVPErrorSpecTlv is mandatory.");
85         final RsvpErrorSpec rsvp = (RsvpErrorSpec) tlv;
86         final ByteBuf body = Unpooled.buffer();
87         if (rsvp.getErrorType().getImplementedInterface().equals(RsvpCase.class)) {
88             final RsvpCase r = (RsvpCase) rsvp.getErrorType();
89             serializeRsvp(r.getRsvpError(), body);
90             TlvUtil.formatTlv(TYPE, body, buffer);
91         } else {
92             final UserCase u = (UserCase) rsvp.getErrorType();
93             serializerUserError(u.getUserError(), body);
94             TlvUtil.formatTlv(TYPE, body, buffer);
95         }
96     }
97
98     private UserCase parseUserError(final ByteBuf buffer) {
99         final UserErrorBuilder error = new UserErrorBuilder();
100         error.setEnterprise(new EnterpriseNumber(buffer.readUnsignedInt()));
101         error.setSubOrg(buffer.readUnsignedByte());
102         final int errDescrLength = buffer.readUnsignedByte();
103         error.setValue(buffer.readUnsignedShort());
104         error.setDescription(ByteArray.bytesToHRString(ByteArray.readBytes(buffer, errDescrLength)));
105         // if we have any subobjects, place the implementation here
106         return new UserCaseBuilder().setUserError(error.build()).build();
107     }
108
109     private void serializerUserError(final UserError ue, final ByteBuf body) {
110         final byte[] desc = (ue.getDescription() == null) ? new byte[0] : ue.getDescription().getBytes(Charsets.UTF_8);
111         final ByteBuf userErrorBuf = Unpooled.buffer();
112         Preconditions.checkArgument(ue.getEnterprise() != null, "EnterpriseNumber is mandatory");
113         writeUnsignedInt(ue.getEnterprise().getValue(), userErrorBuf);
114         writeUnsignedByte(ue.getSubOrg(), userErrorBuf);
115         userErrorBuf.writeByte(desc.length);
116         Preconditions.checkArgument(ue.getValue() != null, "Value is mandatory.");
117         writeUnsignedShort(ue.getValue(), userErrorBuf);
118         userErrorBuf.writeBytes(desc);
119         userErrorBuf.writeZero(TlvUtil.getPadding(desc.length, TlvUtil.PADDED_TO));
120         formatRSVPObject(USER_ERROR_CLASS_NUM, USER_ERROR_CLASS_TYPE, userErrorBuf, body);
121     }
122
123     private RsvpCase parseRsvp(final int classType, final ByteBuf buffer) {
124         final RsvpErrorBuilder builder = new RsvpErrorBuilder();
125         if (classType == RSVP_IPV4_ERROR_CLASS_TYPE) {
126             builder.setNode(new IpAddress(Ipv4Util.addressForByteBuf(buffer)));
127         } else if (classType == RSVP_IPV6_ERROR_CLASS_TYPE) {
128             builder.setNode(new IpAddress(Ipv6Util.addressForByteBuf(buffer)));
129         }
130         final BitArray flags = BitArray.valueOf(buffer, FLAGS_SIZE);
131         builder.setFlags(new Flags(flags.get(IN_PLACE), flags.get(NOT_GUILTY)));
132         final short errorCode = buffer.readUnsignedByte();
133         builder.setCode(errorCode);
134         final int errorValue = buffer.readUnsignedShort();
135         builder.setValue(errorValue);
136         return new RsvpCaseBuilder().setRsvpError(builder.build()).build();
137     }
138
139     private void serializeRsvp(final RsvpError rsvp, final ByteBuf body) {
140         final BitArray flags = new BitArray(FLAGS_SIZE);
141         flags.set(IN_PLACE, rsvp.getFlags().isInPlace());
142         flags.set(NOT_GUILTY, rsvp.getFlags().isNotGuilty());
143         final IpAddress node = rsvp.getNode();
144         Preconditions.checkArgument(node != null, "Node is mandatory.");
145         final ByteBuf rsvpObjBuf = Unpooled.buffer();
146         int type = 0;
147         if (node.getIpv4Address() != null) {
148             type = RSVP_IPV4_ERROR_CLASS_TYPE;
149             writeIpv4Address(node.getIpv4Address(), rsvpObjBuf);
150         } else {
151             type = RSVP_IPV6_ERROR_CLASS_TYPE;
152             writeIpv6Address(node.getIpv6Address(), rsvpObjBuf);
153         }
154         flags.toByteBuf(rsvpObjBuf);
155         Preconditions.checkArgument(rsvp.getCode() != null, "Code is mandatory.");
156         writeUnsignedByte(rsvp.getCode(), rsvpObjBuf);
157         Preconditions.checkArgument(rsvp.getValue() != null, "Value is mandatory.");
158         writeUnsignedShort(rsvp.getValue(), rsvpObjBuf);
159         formatRSVPObject(RSVP_ERROR_CLASS_NUM, type, rsvpObjBuf, body);
160     }
161
162     private static void formatRSVPObject(final int objClass, final int type, final ByteBuf body, final ByteBuf out) {
163         out.writeShort(body.writerIndex() + HEADER_LENGTH);
164         out.writeByte(objClass);
165         out.writeByte(type);
166         out.writeBytes(body);
167     }
168 }