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
9 package org.opendaylight.protocol.pcep.ietf.stateful07;
11 import com.google.common.base.Preconditions;
12 import com.google.common.collect.ImmutableMap;
13 import com.google.common.collect.ImmutableMap.Builder;
14 import io.netty.buffer.ByteBuf;
15 import io.netty.buffer.Unpooled;
17 import org.opendaylight.protocol.pcep.spi.PCEPDeserializerException;
18 import org.opendaylight.protocol.pcep.spi.TlvParser;
19 import org.opendaylight.protocol.pcep.spi.TlvSerializer;
20 import org.opendaylight.protocol.pcep.spi.TlvUtil;
21 import org.opendaylight.protocol.util.ByteBufWriteUtil;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev181109.path.binding.tlv.PathBinding;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev181109.path.binding.tlv.PathBindingBuilder;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev181109.path.binding.tlv.path.binding.BindingTypeValue;
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.MplsLabel;
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.MplsLabelBuilder;
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.MplsLabelEntry;
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.MplsLabelEntryBuilder;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.Tlv;
30 import org.opendaylight.yangtools.concepts.Codec;
33 * Parser for {@link PathBinding}
35 public final class PathBindingTlvParser implements TlvParser, TlvSerializer {
37 // TODO: to be confirmed by IANA
38 public static final int TYPE = 31;
40 private static final int MPLS_LABEL = 0;
41 private static final int MPLS_STACK_ENTRY = 1;
43 private static final int LABEL_MASK = 0xfffff;
44 private static final int TC_MASK = 0x7;
45 private static final int S_MASK = 0x1;
46 private static final int TTL_MASK = 0xff;
47 private static final int LABEL_SHIFT = 12;
48 private static final int TC_SHIFT = LABEL_SHIFT - 3;
49 private static final int S_SHIFT = TC_SHIFT - 1;
50 private static final int MPLS_ENTRY_LENGTH = 4;
51 private static final int MPLS_BINDING_LENGTH = MPLS_ENTRY_LENGTH + 2;
53 private static final Map<Integer, PathBindingTlvCodec> BT_PARSERS;
54 private static final Map<Class<? extends BindingTypeValue>, PathBindingTlvCodec> BT_SERIALIZERS;
57 final MplsLabelCodec mplsLabelCodec = new MplsLabelCodec();
58 final MplsLabelEntryCodec mplsLabelEntryCodec = new MplsLabelEntryCodec();
59 final Builder<Integer, PathBindingTlvCodec> parsers = ImmutableMap.builder();
60 final Builder<Class<? extends BindingTypeValue>, PathBindingTlvCodec> serializers =
61 ImmutableMap.builder();
63 parsers.put(mplsLabelCodec.getBindingType(), mplsLabelCodec);
64 serializers.put(MplsLabel.class, mplsLabelCodec);
66 parsers.put(mplsLabelEntryCodec.getBindingType(), mplsLabelEntryCodec);
67 serializers.put(MplsLabelEntry.class, mplsLabelEntryCodec);
69 BT_PARSERS = parsers.build();
70 BT_SERIALIZERS = serializers.build();
74 public void serializeTlv(final Tlv tlv, final ByteBuf buffer) {
75 Preconditions.checkArgument(tlv instanceof PathBinding,
76 "The TLV must be PathBinding type, but was %s", tlv.getClass());
77 final PathBinding pTlv = (PathBinding) tlv;
78 final BindingTypeValue bindingTypeValue = pTlv.getBindingTypeValue();
79 Preconditions.checkArgument(bindingTypeValue != null,
80 "Missing Binding Value in Path Bidning TLV: %s", pTlv);
81 final ByteBuf body = Unpooled.buffer(MPLS_BINDING_LENGTH);
82 final PathBindingTlvCodec codec = BT_SERIALIZERS.get(bindingTypeValue.getImplementedInterface());
83 Preconditions.checkArgument(codec != null,
84 "Unsupported Path Binding Type: %s", bindingTypeValue.getImplementedInterface());
85 ByteBufWriteUtil.writeUnsignedShort(codec.getBindingType(), body);
86 body.writeBytes(codec.serialize(bindingTypeValue));
88 TlvUtil.formatTlv(TYPE, body, buffer);
92 public Tlv parseTlv(final ByteBuf buffer) throws PCEPDeserializerException {
96 final int type = buffer.readUnsignedShort();
97 final PathBindingTlvCodec codec = BT_PARSERS.get(type);
99 throw new PCEPDeserializerException("Unsupported Path Binding Type: " + type);
101 return new PathBindingBuilder().setBindingTypeValue(codec.deserialize(buffer)).build();
104 private static final class MplsLabelCodec implements PathBindingTlvCodec {
107 public ByteBuf serialize(final BindingTypeValue bindingValue) {
108 Preconditions.checkArgument(bindingValue instanceof MplsLabel, "bindingValue is not MplsLabel");
109 final MplsLabel mplsLabel = (MplsLabel) bindingValue;
110 final ByteBuf value = Unpooled.buffer(MPLS_ENTRY_LENGTH);
111 ByteBufWriteUtil.writeUnsignedInt(getMplsStackEntry(mplsLabel.getMplsLabel()), value);
116 public BindingTypeValue deserialize(final ByteBuf buffer) {
117 final MplsLabelBuilder builder = new MplsLabelBuilder();
118 builder.setMplsLabel(getMplsLabel(buffer.readUnsignedInt()));
119 return builder.build();
123 public int getBindingType() {
128 private static final class MplsLabelEntryCodec implements PathBindingTlvCodec {
131 public ByteBuf serialize(final BindingTypeValue bindingValue) {
132 Preconditions.checkArgument(bindingValue instanceof MplsLabelEntry,
133 "bindingValue is not MplsLabelEntry");
134 final MplsLabelEntry mplsEntry = (MplsLabelEntry) bindingValue;
135 final ByteBuf value = Unpooled.buffer(MPLS_ENTRY_LENGTH);
136 final long entry = getMplsStackEntry(mplsEntry.getLabel())
137 | mplsEntry.getTrafficClass() << TC_SHIFT
138 | (mplsEntry.isBottomOfStack() ? 1 : 0) << S_SHIFT
139 | mplsEntry.getTimeToLive();
140 ByteBufWriteUtil.writeUnsignedInt(entry, value);
145 public BindingTypeValue deserialize(final ByteBuf buffer) {
146 final MplsLabelEntryBuilder builder = new MplsLabelEntryBuilder();
147 final long entry = buffer.readUnsignedInt();
148 builder.setLabel(getMplsLabel(entry));
149 builder.setTrafficClass((short) (entry >> TC_SHIFT & TC_MASK));
150 builder.setBottomOfStack((entry >> S_SHIFT & S_MASK) == 1);
151 builder.setTimeToLive((short) (entry & TTL_MASK));
152 return builder.build();
156 public int getBindingType() {
157 return MPLS_STACK_ENTRY;
161 private interface PathBindingTlvCodec extends Codec<ByteBuf, BindingTypeValue> {
162 int getBindingType();
165 private static org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.network.concepts.rev131125.MplsLabel getMplsLabel(
166 final long mplsStackEntry) {
167 return new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.network.concepts.rev131125.MplsLabel(
168 mplsStackEntry >> LABEL_SHIFT & LABEL_MASK);
171 private static long getMplsStackEntry(
172 final org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.network.concepts.rev131125.MplsLabel mplsLabel) {
173 return mplsLabel.getValue() << LABEL_SHIFT;