Bump MDSAL to 4.0.0
[bgpcep.git] / pcep / ietf-stateful07 / src / main / java / org / opendaylight / protocol / pcep / ietf / stateful07 / PathBindingTlvParser.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.pcep.ietf.stateful07;
9
10 import com.google.common.base.Preconditions;
11 import com.google.common.collect.ImmutableMap;
12 import com.google.common.collect.ImmutableMap.Builder;
13 import io.netty.buffer.ByteBuf;
14 import io.netty.buffer.Unpooled;
15 import java.util.Map;
16 import org.opendaylight.protocol.pcep.spi.PCEPDeserializerException;
17 import org.opendaylight.protocol.pcep.spi.TlvParser;
18 import org.opendaylight.protocol.pcep.spi.TlvSerializer;
19 import org.opendaylight.protocol.pcep.spi.TlvUtil;
20 import org.opendaylight.protocol.util.ByteBufWriteUtil;
21 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev181109.path.binding.tlv.PathBinding;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev181109.path.binding.tlv.PathBindingBuilder;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev181109.path.binding.tlv.path.binding.BindingTypeValue;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev181109.path.binding.tlv.path.binding.binding.type.value.MplsLabel;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev181109.path.binding.tlv.path.binding.binding.type.value.MplsLabelBuilder;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev181109.path.binding.tlv.path.binding.binding.type.value.MplsLabelEntry;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev181109.path.binding.tlv.path.binding.binding.type.value.MplsLabelEntryBuilder;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.Tlv;
29 import org.opendaylight.yangtools.concepts.Codec;
30
31 /**
32  * Parser for {@link PathBinding}.
33  */
34 public final class PathBindingTlvParser implements TlvParser, TlvSerializer {
35
36     // TODO: to be confirmed by IANA
37     public static final int TYPE = 31;
38
39     private static final int MPLS_LABEL = 0;
40     private static final int MPLS_STACK_ENTRY = 1;
41
42     private static final int LABEL_MASK = 0xfffff;
43     private static final int TC_MASK = 0x7;
44     private static final int S_MASK = 0x1;
45     private static final int TTL_MASK = 0xff;
46     private static final int LABEL_SHIFT = 12;
47     private static final int TC_SHIFT = LABEL_SHIFT - 3;
48     private static final int S_SHIFT = TC_SHIFT - 1;
49     private static final int MPLS_ENTRY_LENGTH = 4;
50     private static final int MPLS_BINDING_LENGTH = MPLS_ENTRY_LENGTH + 2;
51
52     private static final Map<Integer, PathBindingTlvCodec> BT_PARSERS;
53     private static final Map<Class<? extends BindingTypeValue>, PathBindingTlvCodec> BT_SERIALIZERS;
54
55     static {
56         final MplsLabelCodec mplsLabelCodec = new MplsLabelCodec();
57         final MplsLabelEntryCodec mplsLabelEntryCodec = new MplsLabelEntryCodec();
58         final Builder<Integer, PathBindingTlvCodec> parsers = ImmutableMap.builder();
59         final Builder<Class<? extends BindingTypeValue>, PathBindingTlvCodec> serializers =
60                 ImmutableMap.builder();
61
62         parsers.put(mplsLabelCodec.getBindingType(), mplsLabelCodec);
63         serializers.put(MplsLabel.class, mplsLabelCodec);
64
65         parsers.put(mplsLabelEntryCodec.getBindingType(), mplsLabelEntryCodec);
66         serializers.put(MplsLabelEntry.class, mplsLabelEntryCodec);
67
68         BT_PARSERS = parsers.build();
69         BT_SERIALIZERS = serializers.build();
70     }
71
72     @Override
73     public void serializeTlv(final Tlv tlv, final ByteBuf buffer) {
74         Preconditions.checkArgument(tlv instanceof PathBinding,
75             "The TLV must be PathBinding type, but was %s", tlv.getClass());
76         final PathBinding pTlv = (PathBinding) tlv;
77         final BindingTypeValue bindingTypeValue = pTlv.getBindingTypeValue();
78         Preconditions.checkArgument(bindingTypeValue != null,
79             "Missing Binding Value in Path Bidning TLV: %s", pTlv);
80         final ByteBuf body = Unpooled.buffer(MPLS_BINDING_LENGTH);
81         final PathBindingTlvCodec codec = BT_SERIALIZERS.get(bindingTypeValue.implementedInterface());
82         Preconditions.checkArgument(codec != null,
83             "Unsupported Path Binding Type: %s", bindingTypeValue.implementedInterface());
84         ByteBufWriteUtil.writeUnsignedShort(codec.getBindingType(), body);
85         body.writeBytes(codec.serialize(bindingTypeValue));
86
87         TlvUtil.formatTlv(TYPE, body, buffer);
88     }
89
90     @Override
91     public Tlv parseTlv(final ByteBuf buffer) throws PCEPDeserializerException {
92         if (buffer == null) {
93             return null;
94         }
95         final int type = buffer.readUnsignedShort();
96         final PathBindingTlvCodec codec = BT_PARSERS.get(type);
97         if (codec == null) {
98             throw new PCEPDeserializerException("Unsupported Path Binding Type: " + type);
99         }
100         return new PathBindingBuilder().setBindingTypeValue(codec.deserialize(buffer)).build();
101     }
102
103     private static final class MplsLabelCodec implements PathBindingTlvCodec {
104
105         @Override
106         public ByteBuf serialize(final BindingTypeValue bindingValue) {
107             Preconditions.checkArgument(bindingValue instanceof MplsLabel, "bindingValue is not MplsLabel");
108             final MplsLabel mplsLabel = (MplsLabel) bindingValue;
109             final ByteBuf value = Unpooled.buffer(MPLS_ENTRY_LENGTH);
110             ByteBufWriteUtil.writeUnsignedInt(getMplsStackEntry(mplsLabel.getMplsLabel()), value);
111             return value;
112         }
113
114         @Override
115         public BindingTypeValue deserialize(final ByteBuf buffer) {
116             final MplsLabelBuilder builder = new MplsLabelBuilder();
117             builder.setMplsLabel(getMplsLabel(buffer.readUnsignedInt()));
118             return builder.build();
119         }
120
121         @Override
122         public int getBindingType() {
123             return MPLS_LABEL;
124         }
125     }
126
127     private static final class MplsLabelEntryCodec implements PathBindingTlvCodec {
128
129         @Override
130         public ByteBuf serialize(final BindingTypeValue bindingValue) {
131             Preconditions.checkArgument(bindingValue instanceof MplsLabelEntry,
132                     "bindingValue is not MplsLabelEntry");
133             final MplsLabelEntry mplsEntry = (MplsLabelEntry) bindingValue;
134             final ByteBuf value = Unpooled.buffer(MPLS_ENTRY_LENGTH);
135             final long entry = getMplsStackEntry(mplsEntry.getLabel())
136                     | mplsEntry.getTrafficClass() << TC_SHIFT
137                     | (mplsEntry.isBottomOfStack() ? 1 : 0) << S_SHIFT
138                     | mplsEntry.getTimeToLive();
139             ByteBufWriteUtil.writeUnsignedInt(entry, value);
140             return value;
141         }
142
143         @Override
144         public BindingTypeValue deserialize(final ByteBuf buffer) {
145             final MplsLabelEntryBuilder builder = new MplsLabelEntryBuilder();
146             final long entry = buffer.readUnsignedInt();
147             builder.setLabel(getMplsLabel(entry));
148             builder.setTrafficClass((short) (entry >> TC_SHIFT & TC_MASK));
149             builder.setBottomOfStack((entry >> S_SHIFT & S_MASK) == 1);
150             builder.setTimeToLive((short) (entry & TTL_MASK));
151             return builder.build();
152         }
153
154         @Override
155         public int getBindingType() {
156             return MPLS_STACK_ENTRY;
157         }
158     }
159
160     private interface PathBindingTlvCodec extends Codec<ByteBuf, BindingTypeValue> {
161         int getBindingType();
162     }
163
164     private static org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.network.concepts.rev131125.MplsLabel
165         getMplsLabel(final long mplsStackEntry) {
166         return new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.network.concepts.rev131125
167                 .MplsLabel(mplsStackEntry >> LABEL_SHIFT & LABEL_MASK);
168     }
169
170     private static long getMplsStackEntry(final org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.network
171             .concepts.rev131125.MplsLabel mplsLabel) {
172         return mplsLabel.getValue() << LABEL_SHIFT;
173     }
174
175 }