91a4b806cdd3353b66df6d1c7703da176f92c98e
[bgpcep.git] / bgp / extensions / mvpn / src / main / java / org / opendaylight / protocol / bgp / mvpn / impl / attributes / OpaqueUtil.java
1 /*
2  * Copyright (c) 2016 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.bgp.mvpn.impl.attributes;
9
10 import com.google.common.base.Joiner;
11 import com.google.common.base.Splitter;
12 import io.netty.buffer.ByteBuf;
13 import io.netty.buffer.ByteBufUtil;
14 import java.util.ArrayList;
15 import java.util.List;
16 import javax.xml.bind.DatatypeConverter;
17 import org.opendaylight.protocol.util.ByteArray;
18 import org.opendaylight.protocol.util.ByteBufWriteUtil;
19 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.HexString;
20 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pmsi.tunnel.rev180329.Opaque;
21 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pmsi.tunnel.rev180329.pmsi.tunnel.pmsi.tunnel.tunnel.identifier.mldp.p2mp.lsp.mldp.p2mp.lsp.OpaqueValue;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pmsi.tunnel.rev180329.pmsi.tunnel.pmsi.tunnel.tunnel.identifier.mldp.p2mp.lsp.mldp.p2mp.lsp.OpaqueValueBuilder;
23 import org.opendaylight.yangtools.yang.common.Uint16;
24 import org.opendaylight.yangtools.yang.common.Uint8;
25 import org.opendaylight.yangtools.yang.common.netty.ByteBufUtils;
26 import org.slf4j.Logger;
27 import org.slf4j.LoggerFactory;
28
29 public final class OpaqueUtil {
30     public static final short GENERIC_LSP_IDENTIFIER = 1;
31     public static final short EXTENDED_TYPE = 255;
32     private static final Logger LOG = LoggerFactory.getLogger(OpaqueUtil.class);
33     private static final String SEPARATOR = ":";
34     private static final String EMPTY_SEPARATOR = "";
35
36     private OpaqueUtil() {
37         // Hidden on purpose
38     }
39
40     public static boolean serializeOpaque(final Opaque opaque, final ByteBuf byteBuf) {
41         final Uint8 type = opaque.getOpaqueType();
42         switch (type.toJava()) {
43             case GENERIC_LSP_IDENTIFIER:
44                 ByteBufWriteUtil.writeUnsignedByte(type, byteBuf);
45                 writeGeneric(opaque.getOpaque(), byteBuf);
46                 break;
47             case EXTENDED_TYPE:
48                 ByteBufWriteUtil.writeUnsignedByte(type, byteBuf);
49                 writeExtended(opaque.getOpaque(), opaque.getOpaqueExtendedType(), byteBuf);
50                 break;
51             default:
52                 LOG.debug("Skipping serialization of Opaque Value {}", opaque);
53                 return false;
54         }
55         return true;
56     }
57
58     private static void writeExtended(final HexString opaque, final Uint16 opaqueExtendedType, final ByteBuf byteBuf) {
59         final byte[] output = writeOpaqueValue(opaque.getValue());
60         ByteBufWriteUtil.writeUnsignedShort(opaqueExtendedType, byteBuf);
61         byteBuf.writeShort(output.length);
62         byteBuf.writeBytes(output);
63     }
64
65     private static void writeGeneric(final HexString opaque, final ByteBuf byteBuf) {
66         final byte[] output = writeOpaqueValue(opaque.getValue());
67         byteBuf.writeShort(output.length);
68         byteBuf.writeBytes(output);
69     }
70
71     private static byte[] writeOpaqueValue(final String opaque) {
72         final String joined = opaque.replace(SEPARATOR, EMPTY_SEPARATOR);
73         return DatatypeConverter.parseHexBinary(joined);
74     }
75
76     public static Opaque parseOpaque(final ByteBuf buffer) {
77         final Uint8 type = ByteBufUtils.readUint8(buffer);
78         final OpaqueValueBuilder builder = new OpaqueValueBuilder();
79         switch (type.toJava()) {
80             case GENERIC_LSP_IDENTIFIER:
81                 builder.setOpaque(buildOpaqueValue(buffer));
82                 break;
83             case EXTENDED_TYPE:
84                 buildExtended(builder, buffer);
85                 break;
86             default:
87                 final int length = buffer.readUnsignedShort();
88                 buffer.skipBytes(length);
89                 LOG.debug("Skipping parsing of Opaque Value {}", buffer);
90                 return null;
91         }
92         builder.setOpaqueType(type);
93         return builder.build();
94     }
95
96     private static void buildExtended(final OpaqueValueBuilder builder, final ByteBuf buffer) {
97         final Uint16 extendedType = ByteBufUtils.readUint16(buffer);
98         final HexString opaqueValue = buildOpaqueValue(buffer);
99         builder.setOpaqueExtendedType(extendedType).setOpaque(opaqueValue);
100     }
101
102     private static HexString buildOpaqueValue(final ByteBuf buffer) {
103         final int length = buffer.readUnsignedShort();
104         final byte[] value = ByteArray.readBytes(buffer, length);
105         final String hexDump = ByteBufUtil.hexDump(value);
106         final Iterable<String> splitted = Splitter.fixedLength(2).split(hexDump);
107         return new HexString(Joiner.on(SEPARATOR).join(splitted));
108     }
109
110     public static List<OpaqueValue> parseOpaqueList(final ByteBuf byteBuf) {
111         final List<OpaqueValue> opaqueValues = new ArrayList<>();
112         while (byteBuf.isReadable()) {
113             final Opaque opaque = parseOpaque(byteBuf);
114             if (opaque != null) {
115                 opaqueValues.add((OpaqueValue) opaque);
116             }
117         }
118         return opaqueValues;
119     }
120
121     public static boolean serializeOpaqueList(final List<OpaqueValue> mldpP2mpLsp, final ByteBuf buffer) {
122         boolean parsed = false;
123         for (final OpaqueValue opaque : mldpP2mpLsp) {
124             if (serializeOpaque(opaque, buffer)) {
125                 parsed = true;
126             }
127         }
128         return parsed;
129     }
130 }