2 * Copyright (c) 2015 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.bgp.linkstate.attribute.sr;
10 import io.netty.buffer.ByteBuf;
11 import io.netty.buffer.Unpooled;
12 import java.util.ArrayList;
13 import java.util.List;
14 import org.opendaylight.protocol.bgp.linkstate.spi.TlvUtil;
15 import org.opendaylight.protocol.util.BitArray;
16 import org.opendaylight.protocol.util.ByteArray;
17 import org.opendaylight.protocol.util.ByteBufWriteUtil;
18 import org.opendaylight.protocol.util.Ipv4Util;
19 import org.opendaylight.protocol.util.Ipv6Util;
20 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
21 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpPrefix;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.node.state.SrAlgorithm;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.node.state.SrAlgorithmBuilder;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.node.state.SrCapabilities;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.node.state.SrCapabilitiesBuilder;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.node.state.SrSidLabel;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.node.state.SrSidLabelBuilder;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.rev150206.Algorithm;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.rev150206.SidLabel;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.rev150206.SidLabelBinding.SidLabelFlags;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.rev150206.SrCapabilities.Flags;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.rev150206.Weight;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.rev150206.sid.label.binding.SubTlvs;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.rev150206.sid.label.binding.SubTlvsBuilder;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.rev150206.sid.sub.tlvs.SubtlvType;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.rev150206.sid.sub.tlvs.subtlv.type.EroMetricCase;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.rev150206.sid.sub.tlvs.subtlv.type.EroMetricCaseBuilder;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.rev150206.sid.sub.tlvs.subtlv.type.Ipv4EroBackupCase;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.rev150206.sid.sub.tlvs.subtlv.type.Ipv4EroBackupCaseBuilder;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.rev150206.sid.sub.tlvs.subtlv.type.Ipv4EroCase;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.rev150206.sid.sub.tlvs.subtlv.type.Ipv4EroCaseBuilder;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.rev150206.sid.sub.tlvs.subtlv.type.Ipv6EroBackupCase;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.rev150206.sid.sub.tlvs.subtlv.type.Ipv6EroBackupCaseBuilder;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.rev150206.sid.sub.tlvs.subtlv.type.Ipv6EroCase;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.rev150206.sid.sub.tlvs.subtlv.type.Ipv6EroCaseBuilder;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.rev150206.sid.sub.tlvs.subtlv.type.SidLabelCase;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.rev150206.sid.sub.tlvs.subtlv.type.SidLabelCaseBuilder;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.rev150206.sid.sub.tlvs.subtlv.type.UnnumberedEroBackupCase;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.rev150206.sid.sub.tlvs.subtlv.type.UnnumberedEroBackupCaseBuilder;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.rev150206.sid.sub.tlvs.subtlv.type.UnnumberedEroCase;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.rev150206.sid.sub.tlvs.subtlv.type.UnnumberedEroCaseBuilder;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.network.concepts.rev131125.TeMetric;
53 import org.slf4j.Logger;
54 import org.slf4j.LoggerFactory;
56 public final class SrNodeAttributesParser {
58 private static final Logger LOG = LoggerFactory.getLogger(SrNodeAttributesParser.class);
60 private SrNodeAttributesParser() {
61 throw new UnsupportedOperationException();
64 private static final int FLAGS_SIZE = 8;
66 /* SR Capabilities flags */
67 private static final int IPV4 = 0;
68 private static final int IPV6 = 1;
71 private static final int AFI = 0;
72 private static final int MIRROR = 1;
74 /* SID Label Tlv types */
75 private static final int SID_TLV_TYPE = 1;
76 private static final int ERO_METRIC = 2;
77 private static final int ERO_IPV4 = 3;
78 private static final int ERO_IPV6 = 4;
79 private static final int UNNUMBERED_ERO = 5;
80 private static final int BACKUP_IPV4 = 6;
81 private static final int BACKUP_IPV6 = 7;
82 private static final int UNNUMBERED_BACKUP_ERO = 8;
84 private static final int UNNUMBERED_4_SIZE = 8;
86 private static final byte LOOSE = (byte) 128;
88 private static List<SubTlvs> parseSidSubtlvs(final ByteBuf buffer) {
89 final List<SubTlvs> subs = new ArrayList<>();
90 while (buffer.isReadable()) {
91 final int type = buffer.readUnsignedByte();
92 final int length = buffer.readUnsignedByte();
93 final ByteBuf value = buffer.readSlice(length);
94 SubtlvType sub = null;
97 sub = new SidLabelCaseBuilder().setSid(new SidLabel(ByteArray.readAllBytes(value))).build();
100 sub = new EroMetricCaseBuilder().setEroMetric(new TeMetric(value.readUnsignedInt())).build();
103 final Ipv4EroCaseBuilder ero4 = new Ipv4EroCaseBuilder().setLoose(value.readUnsignedByte() != 0);
104 ero4.setAddress(new IpAddress(Ipv4Util.addressForByteBuf(value)));
108 final Ipv6EroCaseBuilder ero6 = new Ipv6EroCaseBuilder().setLoose(value.readUnsignedByte() != 0);
109 ero6.setAddress(new IpAddress(Ipv6Util.addressForByteBuf(value)));
113 final UnnumberedEroCaseBuilder un = new UnnumberedEroCaseBuilder().setLoose(value.readUnsignedByte() != 0);
114 un.setRouterId(readRouterId(value));
115 un.setInterfaceId(value.readUnsignedInt());
119 final Ipv4EroBackupCaseBuilder erob4 = new Ipv4EroBackupCaseBuilder().setLoose(value.readUnsignedByte() != 0);
120 erob4.setAddress(new IpAddress(Ipv4Util.addressForByteBuf(value)));
124 final Ipv6EroBackupCaseBuilder erob6 = new Ipv6EroBackupCaseBuilder().setLoose(value.readUnsignedByte() != 0);
125 erob6.setAddress(new IpAddress(Ipv6Util.addressForByteBuf(value)));
128 case UNNUMBERED_BACKUP_ERO:
129 final UnnumberedEroBackupCaseBuilder unb = new UnnumberedEroBackupCaseBuilder().setLoose(value.readUnsignedByte() != 0);
130 unb.setRouterId(readRouterId(value));
131 unb.setInterfaceId(value.readUnsignedInt());
135 LOG.debug("Unknown SID Label Subtlv found, type {}", type);
136 // we don't want to add null sub-tlv, so skip to next loop iteration
139 subs.add(new SubTlvsBuilder().setSubtlvType(sub).build());
144 private static byte[] readRouterId(final ByteBuf value) {
145 if (value.readableBytes() == UNNUMBERED_4_SIZE) {
146 return ByteArray.readBytes(value, Ipv4Util.IP4_LENGTH);
148 return ByteArray.readBytes(value, Ipv6Util.IPV6_LENGTH);
151 public static SrSidLabel parseSidLabelBinding(final ByteBuf buffer) {
152 final SrSidLabelBuilder builder = new SrSidLabelBuilder();
153 final BitArray flags = BitArray.valueOf(buffer, FLAGS_SIZE);
154 builder.setSidLabelFlags(new SidLabelFlags(flags.get(AFI), flags.get(MIRROR)));
155 builder.setWeight(new Weight(buffer.readUnsignedByte()));
156 builder.setValueRange(buffer.readUnsignedShort());
157 final int bitLength = buffer.getUnsignedByte(buffer.readerIndex());
158 IpPrefix prefix = null;
159 if (bitLength / Byte.SIZE == Ipv4Util.IP4_LENGTH) {
160 prefix = new IpPrefix(Ipv4Util.prefixForByteBuf(buffer));
162 prefix = new IpPrefix(Ipv6Util.prefixForByteBuf(buffer));
164 builder.setFecPrefix(prefix);
165 builder.setSubTlvs(parseSidSubtlvs(buffer));
166 return builder.build();
169 private static byte serializeLoose(final boolean loose) {
170 return loose ? LOOSE : 0;
173 private static void serializeSidSubtlvs(final List<SubTlvs> subTlvs, final ByteBuf buffer) {
174 for (final SubTlvs sub : subTlvs) {
175 final SubtlvType type = sub.getSubtlvType();
176 if (type instanceof SidLabelCase) {
177 TlvUtil.writeSrTLV(SID_TLV_TYPE, Unpooled.wrappedBuffer(((SidLabelCase)type).getSid().getValue()), buffer);
178 } else if (type instanceof EroMetricCase) {
179 final ByteBuf b = Unpooled.buffer();
180 ByteBufWriteUtil.writeUnsignedInt(((EroMetricCase)type).getEroMetric().getValue(), b);
181 TlvUtil.writeSrTLV(ERO_METRIC, b, buffer);
182 } else if (type instanceof Ipv4EroCase) {
183 final ByteBuf b = Unpooled.buffer(Ipv4Util.IP4_LENGTH + FLAGS_SIZE);
184 final Ipv4EroCase ero = (Ipv4EroCase)type;
185 b.writeByte(serializeLoose(ero.isLoose()));
186 ByteBufWriteUtil.writeIpv4Address(ero.getAddress().getIpv4Address(), b);
187 TlvUtil.writeSrTLV(ERO_IPV4, b, buffer);
188 } else if (type instanceof Ipv6EroCase) {
189 final ByteBuf b = Unpooled.buffer(Ipv6Util.IPV6_LENGTH + FLAGS_SIZE);
190 final Ipv6EroCase ero = (Ipv6EroCase)type;
191 b.writeByte(serializeLoose(ero.isLoose()));
192 ByteBufWriteUtil.writeIpv6Address(ero.getAddress().getIpv6Address(), b);
193 TlvUtil.writeSrTLV(ERO_IPV6, b, buffer);
194 } else if (type instanceof UnnumberedEroCase) {
195 final UnnumberedEroCase ero = (UnnumberedEroCase)type;
196 final ByteBuf b = Unpooled.buffer();
197 b.writeByte(serializeLoose(ero.isLoose()));
198 b.writeBytes(ero.getRouterId());
199 ByteBufWriteUtil.writeUnsignedInt(ero.getInterfaceId(), b);
200 TlvUtil.writeSrTLV(UNNUMBERED_ERO, b, buffer);
201 } else if (type instanceof Ipv4EroBackupCase) {
202 final ByteBuf b = Unpooled.buffer(Ipv4Util.IP4_LENGTH + FLAGS_SIZE);
203 final Ipv4EroBackupCase ero = (Ipv4EroBackupCase)type;
204 b.writeByte(serializeLoose(ero.isLoose()));
205 ByteBufWriteUtil.writeIpv4Address(ero.getAddress().getIpv4Address(), b);
206 TlvUtil.writeSrTLV(BACKUP_IPV4, b, buffer);
207 } else if (type instanceof Ipv6EroBackupCase) {
208 final ByteBuf b = Unpooled.buffer(Ipv6Util.IPV6_LENGTH + FLAGS_SIZE);
209 final Ipv6EroBackupCase ero = (Ipv6EroBackupCase)type;
210 b.writeByte(serializeLoose(ero.isLoose()));
211 ByteBufWriteUtil.writeIpv6Address(ero.getAddress().getIpv6Address(), b);
212 TlvUtil.writeSrTLV(BACKUP_IPV6, b, buffer);
213 } else if (type instanceof UnnumberedEroBackupCase) {
214 final UnnumberedEroBackupCase ero = (UnnumberedEroBackupCase)type;
215 final ByteBuf b = Unpooled.buffer();
216 b.writeByte(serializeLoose(ero.isLoose()));
217 b.writeBytes(ero.getRouterId());
218 ByteBufWriteUtil.writeUnsignedInt(ero.getInterfaceId(), b);
219 TlvUtil.writeSrTLV(UNNUMBERED_BACKUP_ERO, b, buffer);
224 public static void serializeSidLabelBinding(final SrSidLabel binding, final ByteBuf buffer) {
225 final SidLabelFlags flags = binding.getSidLabelFlags();
226 final BitArray bs = new BitArray(FLAGS_SIZE);
227 bs.set(AFI, flags.isAddressFamily());
228 bs.set(MIRROR, flags.isMirrorContext());
229 bs.toByteBuf(buffer);
230 buffer.writeByte(binding.getWeight().getValue());
231 buffer.writeShort(binding.getValueRange());
232 final IpPrefix prefix = binding.getFecPrefix();
233 if (prefix.getIpv4Prefix() != null) {
234 buffer.writeBytes(Ipv4Util.bytesForPrefixBegin(prefix.getIpv4Prefix()));
236 buffer.writeBytes(Ipv6Util.bytesForPrefixBegin(prefix.getIpv6Prefix()));
238 if (binding.getSubTlvs() != null) {
239 serializeSidSubtlvs(binding.getSubTlvs(), buffer);
243 public static SrCapabilities parseSrCapabilities(final ByteBuf buffer) {
244 final SrCapabilitiesBuilder builder = new SrCapabilitiesBuilder();
245 final BitArray flags = BitArray.valueOf(buffer, FLAGS_SIZE);
246 builder.setFlags(new Flags(flags.get(IPV4), flags.get(IPV6)));
247 builder.setValueRange((long)buffer.readUnsignedMedium());
249 builder.setSid(new SidLabel(ByteArray.readAllBytes(buffer)));
250 return builder.build();
253 public static void serializeSrCapabilities(final SrCapabilities caps, final ByteBuf buffer) {
254 final Flags flags = caps.getFlags();
255 final BitArray bs = new BitArray(FLAGS_SIZE);
256 bs.set(IPV4, flags.isIpv4());
257 bs.set(IPV6, flags.isIpv6());
258 bs.toByteBuf(buffer);
259 buffer.writeMedium(caps.getValueRange().intValue());
260 buffer.writeByte(SID_TLV_TYPE);
261 final byte[] sid = caps.getSid().getValue();
262 buffer.writeByte(sid.length);
263 buffer.writeBytes(sid);
266 public static SrAlgorithm parseSrAlgorithms(final ByteBuf buffer) {
267 final SrAlgorithmBuilder builder = new SrAlgorithmBuilder();
268 final List<Algorithm> algs = new ArrayList<>();
269 while (buffer.isReadable()) {
270 algs.add(Algorithm.forValue(buffer.readUnsignedByte()));
272 builder.setAlgorithm(algs);
273 return builder.build();
276 public static void serializeSrAlgorithms(final SrAlgorithm alg, final ByteBuf buffer) {
277 if (alg.getAlgorithm() != null) {
278 for (final Algorithm a : alg.getAlgorithm()) {
279 buffer.writeByte(a.getIntValue());