2 * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved.
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
8 package org.opendaylight.protocol.pcep.ietf.stateful;
10 import static com.google.common.base.Preconditions.checkArgument;
11 import static java.util.Objects.requireNonNull;
13 import com.google.common.collect.ImmutableMap;
14 import com.google.common.collect.ImmutableMap.Builder;
15 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
16 import io.netty.buffer.ByteBuf;
17 import io.netty.buffer.Unpooled;
19 import org.eclipse.jdt.annotation.NonNull;
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.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev181109.path.binding.tlv.PathBinding;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev181109.path.binding.tlv.PathBindingBuilder;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev181109.path.binding.tlv.path.binding.BindingTypeValue;
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.MplsLabel;
28 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;
29 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;
30 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;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.Tlv;
32 import org.opendaylight.yangtools.yang.common.Uint16;
33 import org.opendaylight.yangtools.yang.common.Uint32;
34 import org.opendaylight.yangtools.yang.common.Uint8;
35 import org.opendaylight.yangtools.yang.common.netty.ByteBufUtils;
38 * Parser for {@link PathBinding}.
40 public final class PathBindingTlvParser implements TlvParser, TlvSerializer {
41 // TODO: to be confirmed by IANA
42 public static final int TYPE = 31;
44 private static final Uint16 MPLS_LABEL = Uint16.ZERO;
45 private static final Uint16 MPLS_STACK_ENTRY = Uint16.ONE;
47 private static final int LABEL_MASK = 0xfffff;
48 private static final int TC_MASK = 0x7;
49 private static final int S_MASK = 0x1;
50 private static final int TTL_MASK = 0xff;
51 private static final int LABEL_SHIFT = 12;
52 private static final int TC_SHIFT = LABEL_SHIFT - 3;
53 private static final int S_SHIFT = TC_SHIFT - 1;
54 // 2 bytes type + 4 bytes binding
55 private static final int MPLS_BINDING_LENGTH = 6;
57 private static final Map<Uint16, PathBindingTlvCodec> BT_PARSERS;
58 private static final Map<Class<? extends BindingTypeValue>, PathBindingTlvCodec> BT_SERIALIZERS;
61 final MplsLabelCodec mplsLabelCodec = new MplsLabelCodec();
62 final MplsLabelEntryCodec mplsLabelEntryCodec = new MplsLabelEntryCodec();
63 final Builder<Uint16, PathBindingTlvCodec> parsers = ImmutableMap.builder();
64 final Builder<Class<? extends BindingTypeValue>, PathBindingTlvCodec> serializers =
65 ImmutableMap.builder();
67 parsers.put(mplsLabelCodec.getBindingType(), mplsLabelCodec);
68 serializers.put(MplsLabel.class, mplsLabelCodec);
70 parsers.put(mplsLabelEntryCodec.getBindingType(), mplsLabelEntryCodec);
71 serializers.put(MplsLabelEntry.class, mplsLabelEntryCodec);
73 BT_PARSERS = parsers.build();
74 BT_SERIALIZERS = serializers.build();
78 public void serializeTlv(final Tlv tlv, final ByteBuf buffer) {
79 checkArgument(tlv instanceof PathBinding, "The TLV must be PathBinding type, but was %s", tlv.getClass());
80 final PathBinding pTlv = (PathBinding) tlv;
81 final BindingTypeValue bindingTypeValue = pTlv.getBindingTypeValue();
82 checkArgument(bindingTypeValue != null, "Missing Binding Value in Path Bidning TLV: %s", pTlv);
83 final ByteBuf body = Unpooled.buffer(MPLS_BINDING_LENGTH);
84 final PathBindingTlvCodec codec = BT_SERIALIZERS.get(bindingTypeValue.implementedInterface());
85 checkArgument(codec != null, "Unsupported Path Binding Type: %s", bindingTypeValue.implementedInterface());
86 codec.writeBinding(body, bindingTypeValue);
88 TlvUtil.formatTlv(TYPE, body, buffer);
92 public Tlv parseTlv(final ByteBuf buffer) throws PCEPDeserializerException {
96 final Uint16 type = ByteBufUtils.readUint16(buffer);
97 final PathBindingTlvCodec codec = BT_PARSERS.get(type);
99 throw new PCEPDeserializerException("Unsupported Path Binding Type: " + type);
101 return new PathBindingBuilder().setBindingTypeValue(codec.readEntry(buffer)).build();
104 private static final class MplsLabelCodec extends PathBindingTlvCodec {
110 void writeEntry(final ByteBuf buf, final BindingTypeValue bindingValue) {
111 checkArgument(bindingValue instanceof MplsLabel, "bindingValue is not MplsLabel");
112 final MplsLabel mplsLabel = (MplsLabel) bindingValue;
113 ByteBufUtils.write(buf, Uint32.valueOf(getMplsStackEntry(mplsLabel.getMplsLabel())));
117 BindingTypeValue readEntry(final ByteBuf buffer) {
118 return new MplsLabelBuilder().setMplsLabel(getMplsLabel(buffer.readUnsignedInt())).build();
122 private static final class MplsLabelEntryCodec extends PathBindingTlvCodec {
123 MplsLabelEntryCodec() {
124 super(MPLS_STACK_ENTRY);
128 void writeEntry(final ByteBuf buf, final BindingTypeValue bindingValue) {
129 checkArgument(bindingValue instanceof MplsLabelEntry, "bindingValue is not MplsLabelEntry");
130 final MplsLabelEntry mplsEntry = (MplsLabelEntry) bindingValue;
131 final long entry = getMplsStackEntry(mplsEntry.getLabel())
132 | mplsEntry.getTrafficClass().toJava() << TC_SHIFT
133 | (mplsEntry.isBottomOfStack() ? 1 : 0) << S_SHIFT
134 | mplsEntry.getTimeToLive().toJava();
135 ByteBufUtils.write(buf, Uint32.valueOf(entry));
139 BindingTypeValue readEntry(final ByteBuf buffer) {
140 final long entry = buffer.readUnsignedInt();
141 return new MplsLabelEntryBuilder()
142 .setLabel(getMplsLabel(entry))
143 .setTrafficClass(Uint8.valueOf(entry >> TC_SHIFT & TC_MASK))
144 .setBottomOfStack((entry >> S_SHIFT & S_MASK) == 1)
145 .setTimeToLive(Uint8.valueOf(entry & TTL_MASK))
150 private abstract static class PathBindingTlvCodec {
151 private final @NonNull Uint16 bindingType;
153 PathBindingTlvCodec(final Uint16 bindingType) {
154 this.bindingType = requireNonNull(bindingType);
157 final @NonNull Uint16 getBindingType() {
161 final void writeBinding(final ByteBuf buf, final BindingTypeValue binding) {
162 ByteBufUtils.writeMandatory(buf, bindingType, "bindingType");
163 writeEntry(buf, binding);
166 abstract BindingTypeValue readEntry(ByteBuf buf);
168 abstract void writeEntry(ByteBuf buf, BindingTypeValue value);
171 @SuppressFBWarnings(value = "UPM_UNCALLED_PRIVATE_METHOD",
172 justification = "https://github.com/spotbugs/spotbugs/issues/811")
173 private static org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.network.concepts.rev131125.MplsLabel
174 getMplsLabel(final long mplsStackEntry) {
175 return new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.network.concepts.rev131125
176 .MplsLabel(Uint32.valueOf(mplsStackEntry >> LABEL_SHIFT & LABEL_MASK));
179 @SuppressFBWarnings(value = "UPM_UNCALLED_PRIVATE_METHOD",
180 justification = "https://github.com/spotbugs/spotbugs/issues/811")
181 private static long getMplsStackEntry(final org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.network
182 .concepts.rev131125.MplsLabel mplsLabel) {
183 return mplsLabel.getValue().toJava() << LABEL_SHIFT;