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.SrBindingSidLabel;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.prefix.state.SrBindingSidLabelBuilder;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.prefix.state.SrPrefix;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev151014.Weight;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev151014.binding.sid.tlv.BindingSubTlvs;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev151014.binding.sid.tlv.BindingSubTlvsBuilder;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev151014.binding.sid.tlv.Flags;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev151014.binding.sid.tlv.flags.IsisBindingFlagsCase;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev151014.binding.sid.tlv.flags.IsisBindingFlagsCaseBuilder;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev151014.binding.sid.tlv.flags.OspfBindingFlagsCase;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev151014.binding.sid.tlv.flags.OspfBindingFlagsCaseBuilder;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev151014.binding.sub.tlvs.BindingSubTlv;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev151014.binding.sub.tlvs.binding.sub.tlv.EroMetricCase;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev151014.binding.sub.tlvs.binding.sub.tlv.EroMetricCaseBuilder;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev151014.binding.sub.tlvs.binding.sub.tlv.Ipv4EroBackupCase;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev151014.binding.sub.tlvs.binding.sub.tlv.Ipv4EroBackupCaseBuilder;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev151014.binding.sub.tlvs.binding.sub.tlv.Ipv4EroCase;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev151014.binding.sub.tlvs.binding.sub.tlv.Ipv4EroCaseBuilder;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev151014.binding.sub.tlvs.binding.sub.tlv.Ipv6EroBackupCase;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev151014.binding.sub.tlvs.binding.sub.tlv.Ipv6EroBackupCaseBuilder;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev151014.binding.sub.tlvs.binding.sub.tlv.Ipv6EroCase;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev151014.binding.sub.tlvs.binding.sub.tlv.Ipv6EroCaseBuilder;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev151014.binding.sub.tlvs.binding.sub.tlv.PrefixSidCase;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev151014.binding.sub.tlvs.binding.sub.tlv.PrefixSidCaseBuilder;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev151014.binding.sub.tlvs.binding.sub.tlv.SidLabelCase;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev151014.binding.sub.tlvs.binding.sub.tlv.SidLabelCaseBuilder;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev151014.binding.sub.tlvs.binding.sub.tlv.UnnumberedInterfaceIdBackupEroCase;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev151014.binding.sub.tlvs.binding.sub.tlv.UnnumberedInterfaceIdBackupEroCaseBuilder;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev151014.binding.sub.tlvs.binding.sub.tlv.UnnumberedInterfaceIdEroCase;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev151014.binding.sub.tlvs.binding.sub.tlv.UnnumberedInterfaceIdEroCaseBuilder;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev151014.sid.label.index.SidLabelIndex;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.network.concepts.rev131125.TeMetric;
55 import org.slf4j.Logger;
56 import org.slf4j.LoggerFactory;
58 public final class BindingSidLabelParser {
60 private static final Logger LOG = LoggerFactory.getLogger(BindingSidLabelParser.class);
62 private BindingSidLabelParser() {
63 throw new UnsupportedOperationException();
67 private static final int FLAGS_SIZE = 8;
68 private static final int AFI = 0;
69 private static final int MIRROR_CONTEXT = 1;
70 private static final int MIRROR_CONTEXT_OSPF = 0;
71 private static final int SPREAD_TLV = 2;
72 private static final int LEAKED = 3;
73 private static final int ATTACHED = 4;
74 private static final int LOOSE = 0;
76 /* SID Label Tlv types */
77 private static final int ERO_METRIC = 1162;
78 private static final int ERO_IPV4 = 1163;
79 private static final int ERO_IPV6 = 1164;
80 private static final int UNNUMBERED_ERO = 1165;
81 private static final int BACKUP_ERO_IPV4 = 1166;
82 private static final int BACKUP_ERO_IPV6 = 1167;
83 private static final int BACKUP_UNNUMBERED_ERO = 1168;
85 private static final int RESERVED_BINDING_SID = 2;
86 private static final int RESERVED_ERO = 3;
88 public static SrBindingSidLabel parseBindingSidLabel(final ByteBuf buffer, final ProtocolId protocolId) {
89 final SrBindingSidLabelBuilder bindingSid = new SrBindingSidLabelBuilder();
90 bindingSid.setWeight(new Weight(buffer.readUnsignedByte()));
91 final BitArray flags = BitArray.valueOf(buffer, FLAGS_SIZE);
92 bindingSid.setFlags(parseBindingSidFlags(flags, protocolId));
93 buffer.skipBytes(RESERVED_BINDING_SID);
94 bindingSid.setBindingSubTlvs(parseBindingSubTlvs(buffer, protocolId));
95 return bindingSid.build();
98 private static Flags parseBindingSidFlags(final BitArray flags, final ProtocolId protocol) {
99 if (protocol.equals(ProtocolId.IsisLevel1) || protocol.equals(ProtocolId.IsisLevel2)) {
100 return new IsisBindingFlagsCaseBuilder()
101 .setAddressFamily(flags.get(AFI))
102 .setMirrorContext(flags.get(MIRROR_CONTEXT))
103 .setSpreadTlv(flags.get(SPREAD_TLV))
104 .setLeakedFromLevel2(flags.get(LEAKED))
105 .setAttachedFlag(flags.get(ATTACHED)).build();
106 } else if (protocol.equals(ProtocolId.Ospf)) {
107 return new OspfBindingFlagsCaseBuilder()
108 .setMirroring(flags.get(MIRROR_CONTEXT_OSPF)).build();
113 private static List<BindingSubTlvs> parseBindingSubTlvs(final ByteBuf buffer, final ProtocolId protocolId) {
114 final List<BindingSubTlvs> subTlvs = new ArrayList<BindingSubTlvs>();
115 while (buffer.isReadable()) {
116 final int type = buffer.readUnsignedShort();
117 final int length = buffer.readUnsignedShort();
118 final ByteBuf slice = buffer.readSlice(length);
119 final BindingSubTlvsBuilder builder = new BindingSubTlvsBuilder();
120 parseSubTlv(type, slice, builder, protocolId);
121 subTlvs.add(builder.build());
126 private static void parseSubTlv(final int type, final ByteBuf slice, final BindingSubTlvsBuilder builder, final ProtocolId protocolId) {
128 case SidLabelIndexParser.SID_TYPE:
129 final SidLabelIndex sid = SidLabelIndexParser.parseSidLabelIndex(Size.forValue(slice.readableBytes()), slice);
130 builder.setBindingSubTlv(new SidLabelCaseBuilder()
131 .setSidLabelIndex(sid).build());
133 case PrefixAttributesParser.PREFIX_SID:
134 final SrPrefix prefix = SrPrefixAttributesParser.parseSrPrefix(slice, protocolId);
135 builder.setBindingSubTlv(new PrefixSidCaseBuilder()
136 .setAlgorithm(prefix.getAlgorithm())
137 .setFlags(prefix.getFlags())
138 .setSidLabelIndex(prefix.getSidLabelIndex()).build());
141 builder.setBindingSubTlv(new EroMetricCaseBuilder()
142 .setEroMetric(new TeMetric(slice.readUnsignedInt())).build());
145 final Ipv4EroCase ipv4Ero = parseIpv4EroCase(slice);
146 builder.setBindingSubTlv(new Ipv4EroCaseBuilder()
147 .setAddress(ipv4Ero.getAddress())
148 .setLoose(ipv4Ero.isLoose()).build());
150 case BACKUP_ERO_IPV4:
151 final Ipv4EroCase ipv4Backup = parseIpv4EroCase(slice);
152 builder.setBindingSubTlv(new Ipv4EroBackupCaseBuilder()
153 .setAddress(ipv4Backup.getAddress())
154 .setLoose(ipv4Backup.isLoose()).build());
157 final Ipv6EroCase ipv6ero = parseIpv6EroCase(slice);
158 builder.setBindingSubTlv(new Ipv6EroCaseBuilder()
159 .setAddress(ipv6ero.getAddress())
160 .setLoose(ipv6ero.isLoose()).build());
162 case BACKUP_ERO_IPV6:
163 final Ipv6EroCase ipv6backup = parseIpv6EroCase(slice);
164 builder.setBindingSubTlv(new Ipv6EroBackupCaseBuilder()
165 .setAddress(ipv6backup.getAddress())
166 .setLoose(ipv6backup.isLoose()).build());
169 final UnnumberedInterfaceIdEroCase unnumbered = parseUnnumberedEroCase(slice);
170 builder.setBindingSubTlv(new UnnumberedInterfaceIdEroCaseBuilder()
171 .setLoose(unnumbered.isLoose())
172 .setRouterId(unnumbered.getRouterId())
173 .setInterfaceId(unnumbered.getInterfaceId()).build());
175 case BACKUP_UNNUMBERED_ERO:
176 final UnnumberedInterfaceIdEroCase unnumberedBackup = parseUnnumberedEroCase(slice);
177 builder.setBindingSubTlv(new UnnumberedInterfaceIdBackupEroCaseBuilder()
178 .setLoose(unnumberedBackup.isLoose())
179 .setRouterId(unnumberedBackup.getRouterId())
180 .setInterfaceId(unnumberedBackup.getInterfaceId()).build());
183 LOG.info("Unknown binding sub Tlv type {}", type);
188 private static Ipv4EroCase parseIpv4EroCase(final ByteBuf buffer) {
189 final Ipv4EroCaseBuilder builder = new Ipv4EroCaseBuilder();
190 final BitArray flags = BitArray.valueOf(buffer, FLAGS_SIZE);
191 builder.setLoose(flags.get(LOOSE));
192 buffer.skipBytes(RESERVED_ERO);
193 builder.setAddress(Ipv4Util.addressForByteBuf(buffer));
194 return builder.build();
197 private static Ipv6EroCase parseIpv6EroCase(final ByteBuf buffer) {
198 final Ipv6EroCaseBuilder builder = new Ipv6EroCaseBuilder();
199 final BitArray flags = BitArray.valueOf(buffer, FLAGS_SIZE);
200 builder.setLoose(flags.get(LOOSE));
201 buffer.skipBytes(RESERVED_ERO);
202 builder.setAddress(Ipv6Util.addressForByteBuf(buffer));
203 return builder.build();
206 private static UnnumberedInterfaceIdEroCase parseUnnumberedEroCase(final ByteBuf buffer) {
207 final UnnumberedInterfaceIdEroCaseBuilder builder = new UnnumberedInterfaceIdEroCaseBuilder();
208 final BitArray flags = BitArray.valueOf(buffer, FLAGS_SIZE);
209 builder.setLoose(flags.get(LOOSE));
210 buffer.skipBytes(RESERVED_ERO);
211 builder.setRouterId(buffer.readUnsignedInt());
212 builder.setInterfaceId(buffer.readUnsignedInt());
213 return builder.build();
216 public static void serializeBindingSidLabel(final SrBindingSidLabel bindingSid, final ByteBuf aggregator) {
217 serializeBindingSidAttributes(bindingSid.getWeight(), bindingSid.getFlags(), bindingSid.getBindingSubTlvs(), aggregator);
220 public static void serializeBindingSidAttributes(final Weight weight, final Flags flags, final List<BindingSubTlvs> bindingSubTlvs, final ByteBuf aggregator) {
221 aggregator.writeByte(weight.getValue());
222 final BitArray bitFlags = serializeBindingSidFlags(flags);
223 bitFlags.toByteBuf(aggregator);
224 aggregator.writeZero(RESERVED_BINDING_SID);
225 serializeBindingSubTlvs(bindingSubTlvs, aggregator);
228 private static BitArray serializeBindingSidFlags(final Flags flags) {
229 final BitArray bitFlags = new BitArray(FLAGS_SIZE);
230 if (flags instanceof IsisBindingFlagsCase) {
231 final IsisBindingFlagsCase isisFlags = (IsisBindingFlagsCase) flags;
232 bitFlags.set(AFI, isisFlags.isAddressFamily());
233 bitFlags.set(MIRROR_CONTEXT, isisFlags.isMirrorContext());
234 bitFlags.set(SPREAD_TLV, isisFlags.isSpreadTlv());
235 bitFlags.set(LEAKED, isisFlags.isLeakedFromLevel2());
236 bitFlags.set(ATTACHED, isisFlags.isAttachedFlag());
237 } else if (flags instanceof OspfBindingFlagsCase) {
238 final OspfBindingFlagsCase ospfFlags = (OspfBindingFlagsCase) flags;
239 bitFlags.set(MIRROR_CONTEXT_OSPF, ospfFlags.isMirroring());
244 private static void serializeBindingSubTlvs(final List<BindingSubTlvs> bindingSubTlvs, final ByteBuf aggregator) {
245 for (final BindingSubTlvs subTlv : bindingSubTlvs) {
246 ByteBuf buffer = Unpooled.buffer();
247 final BindingSubTlv bindingSubTlv = subTlv.getBindingSubTlv();
248 if (bindingSubTlv instanceof SidLabelCase) {
249 buffer = SidLabelIndexParser.serializeSidValue(((SidLabelCase) bindingSubTlv).getSidLabelIndex());
250 TlvUtil.writeTLV(SidLabelIndexParser.SID_TYPE, buffer, aggregator);
251 } else if (bindingSubTlv instanceof PrefixSidCase) {
252 final PrefixSidCase prefix = (PrefixSidCase) bindingSubTlv;
253 SrPrefixAttributesParser.serializePrefixAttributes(prefix.getFlags(), prefix.getAlgorithm(), prefix.getSidLabelIndex(), buffer);
254 TlvUtil.writeTLV(PrefixAttributesParser.PREFIX_SID, buffer, aggregator);
255 } else if (bindingSubTlv instanceof EroMetricCase) {
256 buffer.writeInt(((EroMetricCase) bindingSubTlv).getEroMetric().getValue().intValue());
257 TlvUtil.writeTLV(ERO_METRIC, buffer, aggregator);
258 } else if (bindingSubTlv instanceof Ipv4EroBackupCase) {
259 final Ipv4EroBackupCase ipv4Backup = (Ipv4EroBackupCase) bindingSubTlv;
260 buffer = serializeIpv4EroCase(ipv4Backup.isLoose(), ipv4Backup.getAddress());
261 TlvUtil.writeTLV(BACKUP_ERO_IPV4, buffer, aggregator);
262 } else if (bindingSubTlv instanceof Ipv4EroCase) {
263 final Ipv4EroCase ipv4Ero = (Ipv4EroCase) bindingSubTlv;
264 buffer = serializeIpv4EroCase(ipv4Ero.isLoose(), ipv4Ero.getAddress());
265 TlvUtil.writeTLV(ERO_IPV4, buffer, aggregator);
266 } else if (bindingSubTlv instanceof Ipv6EroBackupCase) {
267 final Ipv6EroBackupCase ipv6Backup = (Ipv6EroBackupCase) bindingSubTlv;
268 buffer = serializeIpv6EroCase(ipv6Backup.isLoose(), ipv6Backup.getAddress());
269 TlvUtil.writeTLV(BACKUP_ERO_IPV6, buffer, aggregator);
270 } else if (bindingSubTlv instanceof Ipv6EroCase) {
271 final Ipv6EroCase ipv6Ero = (Ipv6EroCase) bindingSubTlv;
272 buffer = serializeIpv6EroCase(ipv6Ero.isLoose(), ipv6Ero.getAddress());
273 TlvUtil.writeTLV(ERO_IPV6, buffer, aggregator);
274 } else if (bindingSubTlv instanceof UnnumberedInterfaceIdEroCase) {
275 final UnnumberedInterfaceIdEroCase unnumberedEro = (UnnumberedInterfaceIdEroCase) bindingSubTlv;
276 buffer = serializeUnnumberedIdEro(unnumberedEro.isLoose(), unnumberedEro.getRouterId(), unnumberedEro.getInterfaceId());
277 TlvUtil.writeTLV(UNNUMBERED_ERO, buffer, aggregator);
278 } else if (bindingSubTlv instanceof UnnumberedInterfaceIdBackupEroCase) {
279 final UnnumberedInterfaceIdBackupEroCase unnumberedBackup = (UnnumberedInterfaceIdBackupEroCase) bindingSubTlv;
280 buffer = serializeUnnumberedIdEro(unnumberedBackup.isLoose(), unnumberedBackup.getRouterId(), unnumberedBackup.getInterfaceId());
281 TlvUtil.writeTLV(BACKUP_UNNUMBERED_ERO, buffer, aggregator);
286 private static ByteBuf serializeIpv4EroCase(final Boolean loose, final Ipv4Address address) {
287 final ByteBuf buffer = Unpooled.buffer();
288 serializeEroFlags(buffer, loose);
289 buffer.writeBytes(Ipv4Util.byteBufForAddress(address));
293 private static ByteBuf serializeIpv6EroCase(final Boolean loose, final Ipv6Address address) {
294 final ByteBuf buffer = Unpooled.buffer();
295 serializeEroFlags(buffer, loose);
296 buffer.writeBytes(Ipv6Util.byteBufForAddress(address));
300 private static ByteBuf serializeUnnumberedIdEro(final Boolean loose, final Long routerId, final Long interfaceId) {
301 final ByteBuf buffer = Unpooled.buffer();
302 serializeEroFlags(buffer, loose);
303 buffer.writeInt(routerId.intValue());
304 buffer.writeInt(interfaceId.intValue());
308 private static void serializeEroFlags(final ByteBuf buffer, final Boolean loose) {
309 final BitArray flags = new BitArray(FLAGS_SIZE);
310 flags.set(LOOSE, loose);
311 flags.toByteBuf(buffer);
312 buffer.writeZero(RESERVED_ERO);