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.attribute.PrefixAttributesParser;
15 import org.opendaylight.protocol.bgp.linkstate.attribute.sr.SidLabelIndexParser.Size;
16 import org.opendaylight.protocol.bgp.linkstate.spi.TlvUtil;
17 import org.opendaylight.protocol.util.BitArray;
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.Ipv4Address;
21 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv6Address;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.ProtocolId;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.prefix.state.Ipv6SrPrefix;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.prefix.state.SrBindingSidLabels;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.prefix.state.SrBindingSidLabelsBuilder;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.prefix.state.SrPrefix;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev151014.Weight;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev151014.binding.sid.tlv.BindingSubTlvs;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev151014.binding.sid.tlv.BindingSubTlvsBuilder;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev151014.binding.sid.tlv.Flags;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev151014.binding.sid.tlv.flags.IsisBindingFlagsCase;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev151014.binding.sid.tlv.flags.IsisBindingFlagsCaseBuilder;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev151014.binding.sid.tlv.flags.OspfBindingFlagsCase;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev151014.binding.sid.tlv.flags.OspfBindingFlagsCaseBuilder;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev151014.binding.sub.tlvs.BindingSubTlv;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev151014.binding.sub.tlvs.binding.sub.tlv.EroMetricCase;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev151014.binding.sub.tlvs.binding.sub.tlv.EroMetricCaseBuilder;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev151014.binding.sub.tlvs.binding.sub.tlv.Ipv4EroBackupCase;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev151014.binding.sub.tlvs.binding.sub.tlv.Ipv4EroBackupCaseBuilder;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev151014.binding.sub.tlvs.binding.sub.tlv.Ipv4EroCase;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev151014.binding.sub.tlvs.binding.sub.tlv.Ipv4EroCaseBuilder;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev151014.binding.sub.tlvs.binding.sub.tlv.Ipv6EroBackupCase;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev151014.binding.sub.tlvs.binding.sub.tlv.Ipv6EroBackupCaseBuilder;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev151014.binding.sub.tlvs.binding.sub.tlv.Ipv6EroCase;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev151014.binding.sub.tlvs.binding.sub.tlv.Ipv6EroCaseBuilder;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev151014.binding.sub.tlvs.binding.sub.tlv.Ipv6PrefixSidCase;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev151014.binding.sub.tlvs.binding.sub.tlv.Ipv6PrefixSidCaseBuilder;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev151014.binding.sub.tlvs.binding.sub.tlv.PrefixSidCase;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev151014.binding.sub.tlvs.binding.sub.tlv.PrefixSidCaseBuilder;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev151014.binding.sub.tlvs.binding.sub.tlv.SidLabelCase;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev151014.binding.sub.tlvs.binding.sub.tlv.SidLabelCaseBuilder;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev151014.binding.sub.tlvs.binding.sub.tlv.UnnumberedInterfaceIdBackupEroCase;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev151014.binding.sub.tlvs.binding.sub.tlv.UnnumberedInterfaceIdBackupEroCaseBuilder;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev151014.binding.sub.tlvs.binding.sub.tlv.UnnumberedInterfaceIdEroCase;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev151014.binding.sub.tlvs.binding.sub.tlv.UnnumberedInterfaceIdEroCaseBuilder;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev151014.sid.label.index.SidLabelIndex;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.network.concepts.rev131125.TeMetric;
58 import org.slf4j.Logger;
59 import org.slf4j.LoggerFactory;
61 public final class BindingSidLabelParser {
63 private static final Logger LOG = LoggerFactory.getLogger(BindingSidLabelParser.class);
65 private BindingSidLabelParser() {
66 throw new UnsupportedOperationException();
70 private static final int FLAGS_SIZE = 8;
71 private static final int AFI = 0;
72 private static final int MIRROR_CONTEXT = 1;
73 private static final int MIRROR_CONTEXT_OSPF = 0;
74 private static final int SPREAD_TLV = 2;
75 private static final int LEAKED = 3;
76 private static final int ATTACHED = 4;
77 private static final int LOOSE = 0;
79 /* SID Label Tlv types */
80 private static final int ERO_METRIC = 1162;
81 private static final int ERO_IPV4 = 1163;
82 private static final int ERO_IPV6 = 1164;
83 private static final int UNNUMBERED_ERO = 1165;
84 private static final int BACKUP_ERO_IPV4 = 1166;
85 private static final int BACKUP_ERO_IPV6 = 1167;
86 private static final int BACKUP_UNNUMBERED_ERO = 1168;
88 private static final int RESERVED_BINDING_SID = 2;
89 private static final int RESERVED_ERO = 3;
91 public static SrBindingSidLabels parseBindingSidLabel(final ByteBuf buffer, final ProtocolId protocolId) {
92 final SrBindingSidLabelsBuilder bindingSid = new SrBindingSidLabelsBuilder();
93 bindingSid.setWeight(new Weight(buffer.readUnsignedByte()));
94 final BitArray flags = BitArray.valueOf(buffer, FLAGS_SIZE);
95 bindingSid.setFlags(parseBindingSidFlags(flags, protocolId));
96 buffer.skipBytes(RESERVED_BINDING_SID);
97 bindingSid.setBindingSubTlvs(parseBindingSubTlvs(buffer, protocolId));
98 return bindingSid.build();
101 private static Flags parseBindingSidFlags(final BitArray flags, final ProtocolId protocol) {
105 return new IsisBindingFlagsCaseBuilder().setAddressFamily(flags.get(AFI)).setMirrorContext(flags.get(MIRROR_CONTEXT))
106 .setSpreadTlv(flags.get(SPREAD_TLV)).setLeakedFromLevel2(flags.get(LEAKED)).setAttachedFlag(flags.get(ATTACHED)).build();
109 return new OspfBindingFlagsCaseBuilder().setMirroring(flags.get(MIRROR_CONTEXT_OSPF)).build();
115 private static List<BindingSubTlvs> parseBindingSubTlvs(final ByteBuf buffer, final ProtocolId protocolId) {
116 final List<BindingSubTlvs> subTlvs = new ArrayList<BindingSubTlvs>();
117 while (buffer.isReadable()) {
118 final int type = buffer.readUnsignedShort();
119 final int length = buffer.readUnsignedShort();
120 final ByteBuf slice = buffer.readSlice(length);
121 final BindingSubTlvsBuilder builder = new BindingSubTlvsBuilder();
122 parseSubTlv(type, slice, builder, protocolId);
123 subTlvs.add(builder.build());
128 private static void parseSubTlv(final int type, final ByteBuf slice, final BindingSubTlvsBuilder builder, final ProtocolId protocolId) {
130 case SidLabelIndexParser.SID_TYPE:
131 final SidLabelIndex sid = SidLabelIndexParser.parseSidLabelIndex(Size.forValue(slice.readableBytes()), slice);
132 builder.setBindingSubTlv(new SidLabelCaseBuilder()
133 .setSidLabelIndex(sid).build());
135 case PrefixAttributesParser.PREFIX_SID:
136 final SrPrefix prefix = SrPrefixAttributesParser.parseSrPrefix(slice, protocolId);
137 builder.setBindingSubTlv(new PrefixSidCaseBuilder()
138 .setAlgorithm(prefix.getAlgorithm())
139 .setFlags(prefix.getFlags())
140 .setSidLabelIndex(prefix.getSidLabelIndex()).build());
142 case PrefixAttributesParser.IPV6_PREFIX_SID:
143 final Ipv6SrPrefix ipv6Prefix = Ipv6SrPrefixAttributesParser.parseSrIpv6Prefix(slice);
144 builder.setBindingSubTlv(new Ipv6PrefixSidCaseBuilder().setAlgorithm(ipv6Prefix.getAlgorithm()).build());
147 builder.setBindingSubTlv(new EroMetricCaseBuilder()
148 .setEroMetric(new TeMetric(slice.readUnsignedInt())).build());
151 final Ipv4EroCase ipv4Ero = parseIpv4EroCase(slice);
152 builder.setBindingSubTlv(new Ipv4EroCaseBuilder()
153 .setAddress(ipv4Ero.getAddress())
154 .setLoose(ipv4Ero.isLoose()).build());
156 case BACKUP_ERO_IPV4:
157 final Ipv4EroCase ipv4Backup = parseIpv4EroCase(slice);
158 builder.setBindingSubTlv(new Ipv4EroBackupCaseBuilder()
159 .setAddress(ipv4Backup.getAddress())
160 .setLoose(ipv4Backup.isLoose()).build());
163 final Ipv6EroCase ipv6ero = parseIpv6EroCase(slice);
164 builder.setBindingSubTlv(new Ipv6EroCaseBuilder()
165 .setAddress(ipv6ero.getAddress())
166 .setLoose(ipv6ero.isLoose()).build());
168 case BACKUP_ERO_IPV6:
169 final Ipv6EroCase ipv6backup = parseIpv6EroCase(slice);
170 builder.setBindingSubTlv(new Ipv6EroBackupCaseBuilder()
171 .setAddress(ipv6backup.getAddress())
172 .setLoose(ipv6backup.isLoose()).build());
175 final UnnumberedInterfaceIdEroCase unnumbered = parseUnnumberedEroCase(slice);
176 builder.setBindingSubTlv(new UnnumberedInterfaceIdEroCaseBuilder()
177 .setLoose(unnumbered.isLoose())
178 .setRouterId(unnumbered.getRouterId())
179 .setInterfaceId(unnumbered.getInterfaceId()).build());
181 case BACKUP_UNNUMBERED_ERO:
182 final UnnumberedInterfaceIdEroCase unnumberedBackup = parseUnnumberedEroCase(slice);
183 builder.setBindingSubTlv(new UnnumberedInterfaceIdBackupEroCaseBuilder()
184 .setLoose(unnumberedBackup.isLoose())
185 .setRouterId(unnumberedBackup.getRouterId())
186 .setInterfaceId(unnumberedBackup.getInterfaceId()).build());
189 LOG.info("Unknown binding sub Tlv type {}", type);
194 private static Ipv4EroCase parseIpv4EroCase(final ByteBuf buffer) {
195 final Ipv4EroCaseBuilder builder = new Ipv4EroCaseBuilder();
196 final BitArray flags = BitArray.valueOf(buffer, FLAGS_SIZE);
197 builder.setLoose(flags.get(LOOSE));
198 buffer.skipBytes(RESERVED_ERO);
199 builder.setAddress(Ipv4Util.addressForByteBuf(buffer));
200 return builder.build();
203 private static Ipv6EroCase parseIpv6EroCase(final ByteBuf buffer) {
204 final Ipv6EroCaseBuilder builder = new Ipv6EroCaseBuilder();
205 final BitArray flags = BitArray.valueOf(buffer, FLAGS_SIZE);
206 builder.setLoose(flags.get(LOOSE));
207 buffer.skipBytes(RESERVED_ERO);
208 builder.setAddress(Ipv6Util.addressForByteBuf(buffer));
209 return builder.build();
212 private static UnnumberedInterfaceIdEroCase parseUnnumberedEroCase(final ByteBuf buffer) {
213 final UnnumberedInterfaceIdEroCaseBuilder builder = new UnnumberedInterfaceIdEroCaseBuilder();
214 final BitArray flags = BitArray.valueOf(buffer, FLAGS_SIZE);
215 builder.setLoose(flags.get(LOOSE));
216 buffer.skipBytes(RESERVED_ERO);
217 builder.setRouterId(buffer.readUnsignedInt());
218 builder.setInterfaceId(buffer.readUnsignedInt());
219 return builder.build();
222 public static void serializeBindingSidLabels(final List<SrBindingSidLabels> bindingSids, final ByteBuf aggregator, final int sidType) {
223 for (final SrBindingSidLabels bindingSid : bindingSids) {
224 final ByteBuf sidBuffer = Unpooled.buffer();
225 serializeBindingSidAttributes(bindingSid.getWeight(), bindingSid.getFlags(), bindingSid.getBindingSubTlvs(), sidBuffer);
226 TlvUtil.writeTLV(sidType, sidBuffer, aggregator);
230 static void serializeBindingSidAttributes(final Weight weight, final Flags flags, final List<BindingSubTlvs> bindingSubTlvs, final ByteBuf aggregator) {
231 aggregator.writeByte(weight.getValue());
232 final BitArray bitFlags = serializeBindingSidFlags(flags);
233 bitFlags.toByteBuf(aggregator);
234 aggregator.writeZero(RESERVED_BINDING_SID);
235 serializeBindingSubTlvs(bindingSubTlvs, aggregator);
238 private static BitArray serializeBindingSidFlags(final Flags flags) {
239 final BitArray bitFlags = new BitArray(FLAGS_SIZE);
240 if (flags instanceof IsisBindingFlagsCase) {
241 final IsisBindingFlagsCase isisFlags = (IsisBindingFlagsCase) flags;
242 bitFlags.set(AFI, isisFlags.isAddressFamily());
243 bitFlags.set(MIRROR_CONTEXT, isisFlags.isMirrorContext());
244 bitFlags.set(SPREAD_TLV, isisFlags.isSpreadTlv());
245 bitFlags.set(LEAKED, isisFlags.isLeakedFromLevel2());
246 bitFlags.set(ATTACHED, isisFlags.isAttachedFlag());
247 } else if (flags instanceof OspfBindingFlagsCase) {
248 final OspfBindingFlagsCase ospfFlags = (OspfBindingFlagsCase) flags;
249 bitFlags.set(MIRROR_CONTEXT_OSPF, ospfFlags.isMirroring());
254 private static void serializeBindingSubTlvs(final List<BindingSubTlvs> bindingSubTlvs, final ByteBuf aggregator) {
255 for (final BindingSubTlvs subTlv : bindingSubTlvs) {
256 ByteBuf buffer = Unpooled.buffer();
257 final BindingSubTlv bindingSubTlv = subTlv.getBindingSubTlv();
258 if (bindingSubTlv instanceof SidLabelCase) {
259 buffer = SidLabelIndexParser.serializeSidValue(((SidLabelCase) bindingSubTlv).getSidLabelIndex());
260 TlvUtil.writeTLV(SidLabelIndexParser.SID_TYPE, buffer, aggregator);
261 } else if (bindingSubTlv instanceof PrefixSidCase) {
262 final PrefixSidCase prefix = (PrefixSidCase) bindingSubTlv;
263 SrPrefixAttributesParser.serializePrefixAttributes(prefix.getFlags(), prefix.getAlgorithm(), prefix.getSidLabelIndex(), buffer);
264 TlvUtil.writeTLV(PrefixAttributesParser.PREFIX_SID, buffer, aggregator);
265 } else if (bindingSubTlv instanceof Ipv6PrefixSidCase) {
266 final Ipv6PrefixSidCase prefix = (Ipv6PrefixSidCase) bindingSubTlv;
267 Ipv6SrPrefixAttributesParser.serializePrefixAttributes(prefix.getAlgorithm(), buffer);
268 TlvUtil.writeTLV(PrefixAttributesParser.IPV6_PREFIX_SID, buffer, aggregator);
269 } else if (bindingSubTlv instanceof EroMetricCase) {
270 buffer.writeInt(((EroMetricCase) bindingSubTlv).getEroMetric().getValue().intValue());
271 TlvUtil.writeTLV(ERO_METRIC, buffer, aggregator);
272 } else if (bindingSubTlv instanceof Ipv4EroBackupCase) {
273 final Ipv4EroBackupCase ipv4Backup = (Ipv4EroBackupCase) bindingSubTlv;
274 buffer = serializeIpv4EroCase(ipv4Backup.isLoose(), ipv4Backup.getAddress());
275 TlvUtil.writeTLV(BACKUP_ERO_IPV4, buffer, aggregator);
276 } else if (bindingSubTlv instanceof Ipv4EroCase) {
277 final Ipv4EroCase ipv4Ero = (Ipv4EroCase) bindingSubTlv;
278 buffer = serializeIpv4EroCase(ipv4Ero.isLoose(), ipv4Ero.getAddress());
279 TlvUtil.writeTLV(ERO_IPV4, buffer, aggregator);
280 } else if (bindingSubTlv instanceof Ipv6EroBackupCase) {
281 final Ipv6EroBackupCase ipv6Backup = (Ipv6EroBackupCase) bindingSubTlv;
282 buffer = serializeIpv6EroCase(ipv6Backup.isLoose(), ipv6Backup.getAddress());
283 TlvUtil.writeTLV(BACKUP_ERO_IPV6, buffer, aggregator);
284 } else if (bindingSubTlv instanceof Ipv6EroCase) {
285 final Ipv6EroCase ipv6Ero = (Ipv6EroCase) bindingSubTlv;
286 buffer = serializeIpv6EroCase(ipv6Ero.isLoose(), ipv6Ero.getAddress());
287 TlvUtil.writeTLV(ERO_IPV6, buffer, aggregator);
288 } else if (bindingSubTlv instanceof UnnumberedInterfaceIdEroCase) {
289 final UnnumberedInterfaceIdEroCase unnumberedEro = (UnnumberedInterfaceIdEroCase) bindingSubTlv;
290 buffer = serializeUnnumberedIdEro(unnumberedEro.isLoose(), unnumberedEro.getRouterId(), unnumberedEro.getInterfaceId());
291 TlvUtil.writeTLV(UNNUMBERED_ERO, buffer, aggregator);
292 } else if (bindingSubTlv instanceof UnnumberedInterfaceIdBackupEroCase) {
293 final UnnumberedInterfaceIdBackupEroCase unnumberedBackup = (UnnumberedInterfaceIdBackupEroCase) bindingSubTlv;
294 buffer = serializeUnnumberedIdEro(unnumberedBackup.isLoose(), unnumberedBackup.getRouterId(), unnumberedBackup.getInterfaceId());
295 TlvUtil.writeTLV(BACKUP_UNNUMBERED_ERO, buffer, aggregator);
300 private static ByteBuf serializeIpv4EroCase(final Boolean loose, final Ipv4Address address) {
301 final ByteBuf buffer = Unpooled.buffer();
302 serializeEroFlags(buffer, loose);
303 buffer.writeBytes(Ipv4Util.byteBufForAddress(address));
307 private static ByteBuf serializeIpv6EroCase(final Boolean loose, final Ipv6Address address) {
308 final ByteBuf buffer = Unpooled.buffer();
309 serializeEroFlags(buffer, loose);
310 buffer.writeBytes(Ipv6Util.byteBufForAddress(address));
314 private static ByteBuf serializeUnnumberedIdEro(final Boolean loose, final Long routerId, final Long interfaceId) {
315 final ByteBuf buffer = Unpooled.buffer();
316 serializeEroFlags(buffer, loose);
317 buffer.writeInt(routerId.intValue());
318 buffer.writeInt(interfaceId.intValue());
322 private static void serializeEroFlags(final ByteBuf buffer, final Boolean loose) {
323 final BitArray flags = new BitArray(FLAGS_SIZE);
324 flags.set(LOOSE, loose);
325 flags.toByteBuf(buffer);
326 buffer.writeZero(RESERVED_ERO);