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