f77dd7b15ff3a018e5566bf73dc908a9aea60f1f
[bgpcep.git] / bgp / linkstate / src / main / java / org / opendaylight / protocol / bgp / linkstate / attribute / sr / BindingSidLabelParser.java
1 /*
2  * Copyright (c) 2015 Cisco Systems, Inc. and others.  All rights reserved.
3  *
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
7  */
8 package org.opendaylight.protocol.bgp.linkstate.attribute.sr;
9
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.prefix.state.SrBindingSidLabel;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.prefix.state.SrBindingSidLabelBuilder;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.prefix.state.SrPrefix;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev151014.Weight;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev151014.binding.sid.tlv.BindingSubTlvs;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev151014.binding.sid.tlv.BindingSubTlvsBuilder;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev151014.binding.sub.tlvs.BindingSubTlv;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev151014.binding.sub.tlvs.binding.sub.tlv.EroMetricCase;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev151014.binding.sub.tlvs.binding.sub.tlv.EroMetricCaseBuilder;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev151014.binding.sub.tlvs.binding.sub.tlv.Ipv4EroBackupCase;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev151014.binding.sub.tlvs.binding.sub.tlv.Ipv4EroBackupCaseBuilder;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev151014.binding.sub.tlvs.binding.sub.tlv.Ipv4EroCase;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev151014.binding.sub.tlvs.binding.sub.tlv.Ipv4EroCaseBuilder;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev151014.binding.sub.tlvs.binding.sub.tlv.Ipv6EroBackupCase;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev151014.binding.sub.tlvs.binding.sub.tlv.Ipv6EroBackupCaseBuilder;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev151014.binding.sub.tlvs.binding.sub.tlv.Ipv6EroCase;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev151014.binding.sub.tlvs.binding.sub.tlv.Ipv6EroCaseBuilder;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev151014.binding.sub.tlvs.binding.sub.tlv.PrefixSidCase;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev151014.binding.sub.tlvs.binding.sub.tlv.PrefixSidCaseBuilder;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev151014.binding.sub.tlvs.binding.sub.tlv.SidLabelCase;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev151014.binding.sub.tlvs.binding.sub.tlv.SidLabelCaseBuilder;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev151014.binding.sub.tlvs.binding.sub.tlv.UnnumberedInterfaceIdBackupEroCase;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev151014.binding.sub.tlvs.binding.sub.tlv.UnnumberedInterfaceIdBackupEroCaseBuilder;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev151014.binding.sub.tlvs.binding.sub.tlv.UnnumberedInterfaceIdEroCase;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev151014.binding.sub.tlvs.binding.sub.tlv.UnnumberedInterfaceIdEroCaseBuilder;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev151014.sid.label.index.SidLabelIndex;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.network.concepts.rev131125.TeMetric;
49 import org.slf4j.Logger;
50 import org.slf4j.LoggerFactory;
51
52 public final class BindingSidLabelParser {
53
54     private static final Logger LOG = LoggerFactory.getLogger(BindingSidLabelParser.class);
55
56     private BindingSidLabelParser() {
57         throw new UnsupportedOperationException();
58     }
59
60     /* Flags */
61     private static final int FLAGS_SIZE = 8;
62     private static final int LOOSE = 0;
63
64     /* SID Label Tlv types */
65     private static final int ERO_METRIC = 1162;
66     private static final int ERO_IPV4 = 1163;
67     private static final int ERO_IPV6 = 1164;
68     private static final int UNNUMBERED_ERO = 1165;
69     private static final int BACKUP_ERO_IPV4 = 1166;
70     private static final int BACKUP_ERO_IPV6 = 1167;
71     private static final int BACKUP_UNNUMBERED_ERO = 1168;
72
73     private static final int RESERVED_BINDING_SID = 2;
74     private static final int RESERVED_ERO = 3;
75
76     public static SrBindingSidLabel parseBindingSidLabel(final ByteBuf buffer) {
77         final SrBindingSidLabelBuilder bindingSid = new SrBindingSidLabelBuilder();
78         bindingSid.setWeight(new Weight(buffer.readUnsignedByte()));
79         bindingSid.setFlags(new byte[] { (byte) buffer.readUnsignedByte() });
80         buffer.skipBytes(RESERVED_BINDING_SID);
81         bindingSid.setBindingSubTlvs(parseBindingSubTlvs(buffer));
82         return bindingSid.build();
83     }
84
85     private static List<BindingSubTlvs> parseBindingSubTlvs(final ByteBuf buffer) {
86         final List<BindingSubTlvs> subTlvs = new ArrayList<BindingSubTlvs>();
87         while (buffer.isReadable()) {
88             final int type = buffer.readUnsignedShort();
89             final int length = buffer.readUnsignedShort();
90             final ByteBuf slice = buffer.readSlice(length);
91             final BindingSubTlvsBuilder builder = new BindingSubTlvsBuilder();
92             parseSubTlv(type, slice, builder);
93             subTlvs.add(builder.build());
94         }
95         return subTlvs;
96     }
97
98     private static void parseSubTlv(final int type, final ByteBuf slice, final BindingSubTlvsBuilder builder) {
99         switch (type) {
100         case SidLabelIndexParser.SID_TYPE:
101             final SidLabelIndex sid = SidLabelIndexParser.parseSidLabelIndex(Size.forValue(slice.readableBytes()), slice);
102             builder.setBindingSubTlv(new SidLabelCaseBuilder()
103                 .setSidLabelIndex(sid).build());
104             break;
105         case PrefixAttributesParser.PREFIX_SID:
106             final SrPrefix prefix = SrPrefixAttributesParser.parseSrPrefix(slice);
107             builder.setBindingSubTlv(new PrefixSidCaseBuilder()
108                 .setAlgorithm(prefix.getAlgorithm())
109                 .setFlags(prefix.getFlags())
110                 .setSidLabelIndex(prefix.getSidLabelIndex()).build());
111             break;
112         case ERO_METRIC:
113             builder.setBindingSubTlv(new EroMetricCaseBuilder()
114                 .setEroMetric(new TeMetric(slice.readUnsignedInt())).build());
115             break;
116         case ERO_IPV4:
117             final Ipv4EroCase ipv4Ero = parseIpv4EroCase(slice);
118             builder.setBindingSubTlv(new Ipv4EroCaseBuilder()
119                 .setAddress(ipv4Ero.getAddress())
120                 .setLoose(ipv4Ero.isLoose()).build());
121             break;
122         case BACKUP_ERO_IPV4:
123             final Ipv4EroCase ipv4Backup = parseIpv4EroCase(slice);
124             builder.setBindingSubTlv(new Ipv4EroBackupCaseBuilder()
125                 .setAddress(ipv4Backup.getAddress())
126                 .setLoose(ipv4Backup.isLoose()).build());
127             break;
128         case ERO_IPV6:
129             final Ipv6EroCase ipv6ero = parseIpv6EroCase(slice);
130             builder.setBindingSubTlv(new Ipv6EroCaseBuilder()
131                 .setAddress(ipv6ero.getAddress())
132                 .setLoose(ipv6ero.isLoose()).build());
133             break;
134         case BACKUP_ERO_IPV6:
135             final Ipv6EroCase ipv6backup = parseIpv6EroCase(slice);
136             builder.setBindingSubTlv(new Ipv6EroBackupCaseBuilder()
137                 .setAddress(ipv6backup.getAddress())
138                 .setLoose(ipv6backup.isLoose()).build());
139             break;
140         case UNNUMBERED_ERO:
141             final UnnumberedInterfaceIdEroCase unnumbered = parseUnnumberedEroCase(slice);
142             builder.setBindingSubTlv(new UnnumberedInterfaceIdEroCaseBuilder()
143                 .setLoose(unnumbered.isLoose())
144                 .setRouterId(unnumbered.getRouterId())
145                 .setInterfaceId(unnumbered.getInterfaceId()).build());
146             break;
147         case BACKUP_UNNUMBERED_ERO:
148             final UnnumberedInterfaceIdEroCase unnumberedBackup = parseUnnumberedEroCase(slice);
149             builder.setBindingSubTlv(new UnnumberedInterfaceIdBackupEroCaseBuilder()
150                 .setLoose(unnumberedBackup.isLoose())
151                 .setRouterId(unnumberedBackup.getRouterId())
152                 .setInterfaceId(unnumberedBackup.getInterfaceId()).build());
153             break;
154         default:
155             LOG.info("Unknown binding sub Tlv type {}", type);
156             break;
157         }
158     }
159
160     private static Ipv4EroCase parseIpv4EroCase(final ByteBuf buffer) {
161         final Ipv4EroCaseBuilder builder = new Ipv4EroCaseBuilder();
162         final BitArray flags = BitArray.valueOf(buffer, FLAGS_SIZE);
163         builder.setLoose(flags.get(LOOSE));
164         buffer.skipBytes(RESERVED_ERO);
165         builder.setAddress(Ipv4Util.addressForByteBuf(buffer));
166         return builder.build();
167     }
168
169     private static Ipv6EroCase parseIpv6EroCase(final ByteBuf buffer) {
170         final Ipv6EroCaseBuilder builder = new Ipv6EroCaseBuilder();
171         final BitArray flags = BitArray.valueOf(buffer, FLAGS_SIZE);
172         builder.setLoose(flags.get(LOOSE));
173         buffer.skipBytes(RESERVED_ERO);
174         builder.setAddress(Ipv6Util.addressForByteBuf(buffer));
175         return builder.build();
176     }
177
178     private static UnnumberedInterfaceIdEroCase parseUnnumberedEroCase(final ByteBuf buffer) {
179         final UnnumberedInterfaceIdEroCaseBuilder builder = new UnnumberedInterfaceIdEroCaseBuilder();
180         final BitArray flags = BitArray.valueOf(buffer, FLAGS_SIZE);
181         builder.setLoose(flags.get(LOOSE));
182         buffer.skipBytes(RESERVED_ERO);
183         builder.setRouterId(buffer.readUnsignedInt());
184         builder.setInterfaceId(buffer.readUnsignedInt());
185         return builder.build();
186     }
187
188     public static void serializeBindingSidLabel(final SrBindingSidLabel bindingSid, final ByteBuf aggregator) {
189         serializeBindingSidAttributes(bindingSid.getWeight(), bindingSid.getFlags(), bindingSid.getBindingSubTlvs(), aggregator);
190     }
191
192     public static void serializeBindingSidAttributes(final Weight weight, final byte[] flags, final List<BindingSubTlvs> bindingSubTlvs, final ByteBuf aggregator) {
193         aggregator.writeByte(weight.getValue());
194         aggregator.writeBytes(flags);
195         aggregator.writeZero(RESERVED_BINDING_SID);
196         serializeBindingSubTlvs(bindingSubTlvs, aggregator);
197     }
198
199     private static void serializeBindingSubTlvs(final List<BindingSubTlvs> bindingSubTlvs, final ByteBuf aggregator) {
200         for (final BindingSubTlvs subTlv : bindingSubTlvs) {
201             ByteBuf buffer = Unpooled.buffer();
202             final BindingSubTlv bindingSubTlv = subTlv.getBindingSubTlv();
203             if (bindingSubTlv instanceof SidLabelCase) {
204                 buffer = SidLabelIndexParser.serializeSidValue(((SidLabelCase) bindingSubTlv).getSidLabelIndex());
205                 TlvUtil.writeTLV(SidLabelIndexParser.SID_TYPE, buffer, aggregator);
206             } else if (bindingSubTlv instanceof PrefixSidCase) {
207                 final PrefixSidCase prefix = (PrefixSidCase) bindingSubTlv;
208                 SrPrefixAttributesParser.serializePrefixAttributes(prefix.getFlags(), prefix.getAlgorithm(), prefix.getSidLabelIndex(), buffer);
209                 TlvUtil.writeTLV(PrefixAttributesParser.PREFIX_SID, buffer, aggregator);
210             } else if (bindingSubTlv instanceof EroMetricCase) {
211                 buffer.writeInt(((EroMetricCase) bindingSubTlv).getEroMetric().getValue().intValue());
212                 TlvUtil.writeTLV(ERO_METRIC, buffer, aggregator);
213             } else if (bindingSubTlv instanceof Ipv4EroBackupCase) {
214                 final Ipv4EroBackupCase ipv4Backup = (Ipv4EroBackupCase) bindingSubTlv;
215                 buffer = serializeIpv4EroCase(ipv4Backup.isLoose(), ipv4Backup.getAddress());
216                 TlvUtil.writeTLV(BACKUP_ERO_IPV4, buffer, aggregator);
217             } else if (bindingSubTlv instanceof Ipv4EroCase) {
218                 final Ipv4EroCase ipv4Ero = (Ipv4EroCase) bindingSubTlv;
219                 buffer = serializeIpv4EroCase(ipv4Ero.isLoose(), ipv4Ero.getAddress());
220                 TlvUtil.writeTLV(ERO_IPV4, buffer, aggregator);
221             } else if (bindingSubTlv instanceof Ipv6EroBackupCase) {
222                 final Ipv6EroBackupCase ipv6Backup = (Ipv6EroBackupCase) bindingSubTlv;
223                 buffer = serializeIpv6EroCase(ipv6Backup.isLoose(), ipv6Backup.getAddress());
224                 TlvUtil.writeTLV(BACKUP_ERO_IPV6, buffer, aggregator);
225             } else if (bindingSubTlv instanceof Ipv6EroCase) {
226                 final Ipv6EroCase ipv6Ero = (Ipv6EroCase) bindingSubTlv;
227                 buffer = serializeIpv6EroCase(ipv6Ero.isLoose(), ipv6Ero.getAddress());
228                 TlvUtil.writeTLV(ERO_IPV6, buffer, aggregator);
229             } else if (bindingSubTlv instanceof UnnumberedInterfaceIdEroCase) {
230                 final UnnumberedInterfaceIdEroCase unnumberedEro = (UnnumberedInterfaceIdEroCase) bindingSubTlv;
231                 buffer = serializeUnnumberedIdEro(unnumberedEro.isLoose(), unnumberedEro.getRouterId(), unnumberedEro.getInterfaceId());
232                 TlvUtil.writeTLV(UNNUMBERED_ERO, buffer, aggregator);
233             } else if (bindingSubTlv instanceof UnnumberedInterfaceIdBackupEroCase) {
234                 final UnnumberedInterfaceIdBackupEroCase unnumberedBackup = (UnnumberedInterfaceIdBackupEroCase) bindingSubTlv;
235                 buffer = serializeUnnumberedIdEro(unnumberedBackup.isLoose(), unnumberedBackup.getRouterId(), unnumberedBackup.getInterfaceId());
236                 TlvUtil.writeTLV(BACKUP_UNNUMBERED_ERO, buffer, aggregator);
237             }
238         }
239     }
240
241     private static ByteBuf serializeIpv4EroCase(final Boolean loose, final Ipv4Address address) {
242         final ByteBuf buffer = Unpooled.buffer();
243         serializeEroFlags(buffer, loose);
244         buffer.writeBytes(Ipv4Util.byteBufForAddress(address));
245         return buffer;
246     }
247
248     private static ByteBuf serializeIpv6EroCase(final Boolean loose, final Ipv6Address address) {
249         final ByteBuf buffer = Unpooled.buffer();
250         serializeEroFlags(buffer, loose);
251         buffer.writeBytes(Ipv6Util.byteBufForAddress(address));
252         return buffer;
253     }
254
255     private static ByteBuf serializeUnnumberedIdEro(final Boolean loose, final Long routerId, final Long interfaceId) {
256         final ByteBuf buffer = Unpooled.buffer();
257         serializeEroFlags(buffer, loose);
258         buffer.writeInt(routerId.intValue());
259         buffer.writeInt(interfaceId.intValue());
260         return buffer;
261     }
262
263     private static void serializeEroFlags(final ByteBuf buffer, final Boolean loose) {
264         final BitArray flags = new BitArray(FLAGS_SIZE);
265         flags.set(LOOSE, loose);
266         flags.toByteBuf(buffer);
267         buffer.writeZero(RESERVED_ERO);
268     }
269 }