69811002b43cd8c9e639404cd28d5f0fb90ee666
[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 com.google.common.base.Preconditions;
11 import com.google.common.primitives.UnsignedBytes;
12
13 import io.netty.buffer.ByteBuf;
14 import io.netty.buffer.Unpooled;
15
16 import java.util.BitSet;
17
18 import org.opendaylight.protocol.concepts.Ipv4Util;
19 import org.opendaylight.protocol.concepts.Ipv6Util;
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.ByteArray;
25 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.iana.rev130816.EnterpriseNumber;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.rsvp.error.spec.tlv.RsvpErrorSpec;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.rsvp.error.spec.tlv.RsvpErrorSpecBuilder;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.rsvp.error.spec.tlv.rsvp.error.spec.ErrorType;
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.RsvpCase;
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.RsvpCaseBuilder;
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.UserCase;
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.UserCaseBuilder;
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.rsvp._case.RsvpError;
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.rsvp._case.RsvpErrorBuilder;
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.user._case.UserError;
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.user._case.UserErrorBuilder;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.Tlv;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.rsvp.rev130820.ErrorSpec.Flags;
40
41 /**
42  * Parser for {@link RsvpErrorSpec}
43  */
44 public final class Stateful07RSVPErrorSpecTlvParser implements TlvParser, TlvSerializer {
45
46     public static final int TYPE = 21;
47
48     private static final int FLAGS_F_LENGTH = 1;
49
50     private static final int RSVP_ERROR_CLASS_NUM = 6;
51     private static final int RSVP_IPV4_ERROR_CLASS_TYPE = 1;
52     private static final int RSVP_IPV6_ERROR_CLASS_TYPE = 2;
53
54     private static final int USER_ERROR_CLASS_NUM = 194;
55     private static final int USER_ERROR_CLASS_TYPE = 1;
56
57     private static final int IN_PLACE_FLAG_OFFSET = 7;
58     private static final int NOT_GUILTY_FLAGS_OFFSET = 6;
59
60     @Override
61     public RsvpErrorSpec parseTlv(final ByteBuf buffer) throws PCEPDeserializerException {
62         if (buffer == null) {
63             return null;
64         }
65         final int classNum = UnsignedBytes.toInt(buffer.readByte());
66         final int classType = UnsignedBytes.toInt(buffer.readByte());
67         ErrorType errorType = null;
68         if (classNum == RSVP_ERROR_CLASS_NUM) {
69             errorType = parseRsvp(classType, buffer.slice());
70         } else if (classNum == USER_ERROR_CLASS_NUM && classType == USER_ERROR_CLASS_TYPE) {
71             errorType = parseUserError(buffer.slice());
72         }
73         return new RsvpErrorSpecBuilder().setErrorType(errorType).build();
74     }
75
76     @Override
77     public void serializeTlv(final Tlv tlv, final ByteBuf buffer) {
78         Preconditions.checkArgument(tlv != null, "RSVPErrorSpecTlv is mandatory.");
79         final RsvpErrorSpec rsvp = (RsvpErrorSpec) tlv;
80         final ByteBuf body = Unpooled.buffer();
81         if (rsvp.getErrorType().getImplementedInterface().equals(RsvpCase.class)) {
82             final RsvpCase r = (RsvpCase) rsvp.getErrorType();
83             serializeRsvp(r.getRsvpError(), body);
84             TlvUtil.formatTlv(TYPE, body, buffer);
85         } else {
86             final UserCase u = (UserCase) rsvp.getErrorType();
87             serializerUserError(u.getUserError(), body);
88             TlvUtil.formatTlv(TYPE, body, buffer);
89         }
90     }
91
92     private UserCase parseUserError(final ByteBuf buffer) {
93         final UserErrorBuilder error = new UserErrorBuilder();
94         error.setEnterprise(new EnterpriseNumber(buffer.readUnsignedInt()));
95         error.setSubOrg((short) UnsignedBytes.toInt(buffer.readByte()));
96         final int errDescrLength = UnsignedBytes.toInt(buffer.readByte());
97         error.setValue(buffer.readUnsignedShort());
98         error.setDescription(ByteArray.bytesToHRString(ByteArray.readBytes(buffer, errDescrLength)));
99         // if we have any subobjects, place the implementation here
100         return new UserCaseBuilder().setUserError(error.build()).build();
101     }
102
103     private void serializerUserError(final UserError ue, final ByteBuf body) {
104         byte[] desc = (ue.getDescription() == null) ? new byte[0] : ue.getDescription().getBytes();
105         body.writeByte(USER_ERROR_CLASS_NUM);
106         body.writeByte(USER_ERROR_CLASS_TYPE);
107         body.writeInt(ue.getEnterprise().getValue().intValue());
108         body.writeByte(ue.getSubOrg());
109         body.writeByte(desc.length);
110         body.writeShort(ue.getValue().shortValue());
111         body.writeBytes(desc);
112     }
113
114     private RsvpCase parseRsvp(final int classType, final ByteBuf buffer) {
115         final RsvpErrorBuilder builder = new RsvpErrorBuilder();
116         if (classType == RSVP_IPV4_ERROR_CLASS_TYPE) {
117             builder.setNode(new IpAddress(Ipv4Util.addressForBytes(ByteArray.readBytes(buffer, Ipv4Util.IP4_LENGTH))));
118         } else if (classType == RSVP_IPV6_ERROR_CLASS_TYPE) {
119             builder.setNode(new IpAddress(Ipv6Util.addressForBytes(ByteArray.readBytes(buffer, Ipv6Util.IPV6_LENGTH))));
120         }
121         final BitSet flags = ByteArray.bytesToBitSet(ByteArray.readBytes(buffer, FLAGS_F_LENGTH));
122         builder.setFlags(new Flags(flags.get(IN_PLACE_FLAG_OFFSET), flags.get(NOT_GUILTY_FLAGS_OFFSET)));
123         final short errorCode = buffer.readUnsignedByte();
124         builder.setCode(errorCode);
125         final int errorValue = buffer.readUnsignedShort();
126         builder.setValue(errorValue);
127         return new RsvpCaseBuilder().setRsvpError(builder.build()).build();
128     }
129
130     private void serializeRsvp(final RsvpError rsvp, final ByteBuf body) {
131         final BitSet flags = new BitSet(FLAGS_F_LENGTH * Byte.SIZE);
132         flags.set(IN_PLACE_FLAG_OFFSET, rsvp.getFlags().isInPlace());
133         flags.set(NOT_GUILTY_FLAGS_OFFSET, rsvp.getFlags().isNotGuilty());
134         final IpAddress node = rsvp.getNode();
135         if (node.getIpv4Address() != null) {
136             body.writeByte(RSVP_ERROR_CLASS_NUM);
137             body.writeByte(RSVP_IPV4_ERROR_CLASS_TYPE);
138             body.writeBytes(Ipv4Util.bytesForAddress(node.getIpv4Address()));
139         } else {
140             body.writeByte(RSVP_ERROR_CLASS_NUM);
141             body.writeByte(RSVP_IPV6_ERROR_CLASS_TYPE);
142             body.writeBytes(Ipv6Util.bytesForAddress(node.getIpv6Address()));
143         }
144         body.writeBytes(ByteArray.bitSetToBytes(flags, FLAGS_F_LENGTH));
145         body.writeByte(rsvp.getCode());
146         body.writeShort(rsvp.getValue().shortValue());
147     }
148 }