BUG-4802: LS-SR enabling multiple SIDs
[bgpcep.git] / bgp / linkstate / src / main / java / org / opendaylight / protocol / bgp / linkstate / attribute / sr / SrLinkAttributesParser.java
1 /*
2  * Copyright (c) 2014 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.List;
13 import org.opendaylight.protocol.bgp.linkstate.attribute.sr.SidLabelIndexParser.Size;
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.Ipv4Util;
18 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.ProtocolId;
19 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.link.state.SrLanAdjIds;
20 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.link.state.SrLanAdjIdsBuilder;
21 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev151014.AdjSidTlv;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev151014.Weight;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev151014.adj.flags.Flags;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev151014.adj.flags.flags.IsisAdjFlagsCase;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev151014.adj.flags.flags.IsisAdjFlagsCaseBuilder;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev151014.adj.flags.flags.OspfAdjFlagsCase;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev151014.adj.flags.flags.OspfAdjFlagsCaseBuilder;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev151014.sid.label.index.SidLabelIndex;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.network.concepts.rev131125.IsoSystemIdentifier;
30 import org.opendaylight.yangtools.yang.binding.DataContainer;
31
32 public final class SrLinkAttributesParser {
33
34     private static final int ISO_SYSTEM_ID_SIZE = 6;
35     private static final int RESERVED = 2;
36
37     /* Adj-SID flags */
38     private static final int ADDRESS_FAMILY_FLAG = 0;
39     private static final int BACKUP_ISIS = 1;
40     private static final int BACKUP_OSPF = 0;
41     private static final int VALUE_ISIS = 2;
42     private static final int VALUE_OSPF = 1;
43     private static final int VALUE_EPE = 0;
44     private static final int LOCAL_ISIS = 3;
45     private static final int LOCAL_OSPF = 2;
46     private static final int LOCAL_EPE = 1;
47     private static final int SET_ISIS = 4;
48     private static final int SET_OSPF = 3;
49     private static final int FLAGS_SIZE = 8;
50
51     /** OSPF flags
52        0 1 2 3 4 5 6 7
53       +-+-+-+-+-+-+-+-+
54       |B|V|L|S|       |
55       +-+-+-+-+-+-+-+-+
56
57        ISIS flags
58        0 1 2 3 4 5 6 7
59       +-+-+-+-+-+-+-+-+
60       |F|B|V|L|S|     |
61       +-+-+-+-+-+-+-+-+
62      */
63
64     private SrLinkAttributesParser() {
65         throw new UnsupportedOperationException();
66     }
67
68     public static AdjSidTlv parseAdjacencySegmentIdentifier(final ByteBuf buffer, final ProtocolId protocolId) {
69         final Flags adjFlags;
70         final Weight weight;
71         final SidLabelIndex sidValue;
72         if (buffer.isReadable()) {
73             final BitArray flags = BitArray.valueOf(buffer, FLAGS_SIZE);
74             adjFlags = parseFlags(flags, protocolId);
75             weight = new Weight(buffer.readUnsignedByte());
76             buffer.skipBytes(RESERVED);
77             sidValue = SidLabelIndexParser.parseSidLabelIndex(Size.forValue(buffer.readableBytes()), buffer);
78         } else {
79             adjFlags = null;
80             weight = null;
81             sidValue = null;
82         }
83         return new AdjSidTlv() {
84             @Override
85             public Class<? extends DataContainer> getImplementedInterface() {
86                 return AdjSidTlv.class;
87             }
88             @Override
89             public Weight getWeight() {
90                 return weight;
91             }
92             @Override
93             public SidLabelIndex getSidLabelIndex() {
94                 return sidValue;
95             }
96             @Override
97             public Flags getFlags() {
98                 return adjFlags;
99             }
100         };
101     }
102
103     public static SrLanAdjIds parseLanAdjacencySegmentIdentifier(final ByteBuf buffer, final ProtocolId protocolId) {
104         if (!buffer.isReadable()) {
105             return new SrLanAdjIdsBuilder().build();
106         }
107         final SrLanAdjIdsBuilder srLanAdjIdBuilder = new SrLanAdjIdsBuilder();
108         final BitArray flags = BitArray.valueOf(buffer, FLAGS_SIZE);
109         srLanAdjIdBuilder.setFlags(parseFlags(flags, protocolId));
110         srLanAdjIdBuilder.setWeight(new Weight(buffer.readUnsignedByte()));
111         buffer.skipBytes(RESERVED);
112         if (protocolId.equals(ProtocolId.IsisLevel1) || protocolId.equals(ProtocolId.IsisLevel2)) {
113             srLanAdjIdBuilder.setIsoSystemId(new IsoSystemIdentifier(ByteArray.readBytes(buffer, ISO_SYSTEM_ID_SIZE)));
114         } else if (protocolId.equals(ProtocolId.Ospf)) {
115             srLanAdjIdBuilder.setNeighborId(Ipv4Util.addressForByteBuf(buffer));
116         }
117         // length determines a type of next field, which is used for parsing
118         srLanAdjIdBuilder.setSidLabelIndex(SidLabelIndexParser.parseSidLabelIndex(Size.forValue(buffer.readableBytes()), buffer));
119         return srLanAdjIdBuilder.build();
120     }
121
122     private static Flags parseFlags(final BitArray flags, final ProtocolId protocol) {
123         if (protocol == null) {
124             return null;
125         }
126         if (protocol.equals(ProtocolId.IsisLevel1) || protocol.equals(ProtocolId.IsisLevel2)) {
127             return new IsisAdjFlagsCaseBuilder()
128                 .setAddressFamily(flags.get(ADDRESS_FAMILY_FLAG))
129                 .setBackup(flags.get(BACKUP_ISIS))
130                 .setSet(flags.get(SET_ISIS)).build();
131         } else if (protocol.equals(ProtocolId.Ospf)) {
132             return new OspfAdjFlagsCaseBuilder()
133                 .setBackup(flags.get(BACKUP_OSPF))
134                 .setSet(flags.get(SET_OSPF)).build();
135         }
136         return null;
137     }
138
139     public static <T extends AdjSidTlv> void serializeAdjacencySegmentIdentifiers(final List<T> adjSids, final int type, final ByteBuf byteAggregator) {
140         for (final T id : adjSids) {
141             TlvUtil.writeTLV(type, serializeAdjacencySegmentIdentifier(id), byteAggregator);
142         }
143     }
144
145     public static ByteBuf serializeAdjacencySegmentIdentifier(final AdjSidTlv adjSid) {
146         final ByteBuf value = Unpooled.buffer();
147         final BitArray flags = serializeAdjFlags(adjSid.getFlags(), adjSid.getSidLabelIndex());
148         flags.toByteBuf(value);
149         value.writeByte(adjSid.getWeight().getValue());
150         value.writeZero(RESERVED);
151         value.writeBytes(SidLabelIndexParser.serializeSidValue(adjSid.getSidLabelIndex()));
152         return value;
153     }
154
155     public static void serializeLanAdjacencySegmentIdentifiers(final List<SrLanAdjIds> srLanAdjIds, final int srLanAdjId, final ByteBuf byteAggregator) {
156         for (final SrLanAdjIds id : srLanAdjIds) {
157             TlvUtil.writeTLV(srLanAdjId, serializeLanAdjacencySegmentIdentifier(id), byteAggregator);
158         }
159     }
160
161     public static ByteBuf serializeLanAdjacencySegmentIdentifier(final SrLanAdjIds srLanAdjId) {
162         final ByteBuf value = Unpooled.buffer();
163         final BitArray flags = serializeAdjFlags(srLanAdjId.getFlags(), srLanAdjId.getSidLabelIndex());
164         flags.toByteBuf(value);
165         value.writeByte(srLanAdjId.getWeight().getValue());
166         value.writeZero(RESERVED);
167         if (srLanAdjId.getIsoSystemId() != null) {
168             value.writeBytes(srLanAdjId.getIsoSystemId().getValue());
169         } else if (srLanAdjId.getNeighborId() != null) {
170             value.writeBytes(Ipv4Util.byteBufForAddress(srLanAdjId.getNeighborId()));
171         }
172         value.writeBytes(SidLabelIndexParser.serializeSidValue(srLanAdjId.getSidLabelIndex()));
173         return value;
174     }
175
176     private static BitArray serializeAdjFlags(final Flags flags, final SidLabelIndex sidLabelIndex) {
177         final BitArray bitFlags = new BitArray(FLAGS_SIZE);
178         if (flags instanceof OspfAdjFlagsCase) {
179             final OspfAdjFlagsCase ospfFlags = (OspfAdjFlagsCase) flags;
180             bitFlags.set(BACKUP_OSPF, ospfFlags.isBackup());
181             bitFlags.set(SET_OSPF, ospfFlags.isSet());
182             SidLabelIndexParser.setFlags(sidLabelIndex, bitFlags, VALUE_OSPF, LOCAL_OSPF);
183         } else if (flags instanceof IsisAdjFlagsCase) {
184             final IsisAdjFlagsCase isisFlags = (IsisAdjFlagsCase) flags;
185             bitFlags.set(ADDRESS_FAMILY_FLAG, isisFlags.isAddressFamily());
186             bitFlags.set(BACKUP_ISIS, isisFlags.isBackup());
187             bitFlags.set(SET_ISIS, isisFlags.isSet());
188             SidLabelIndexParser.setFlags(sidLabelIndex, bitFlags, VALUE_ISIS, LOCAL_ISIS);
189         } else if (flags == null){
190             SidLabelIndexParser.setFlags(sidLabelIndex, bitFlags, VALUE_EPE, LOCAL_EPE);
191         }
192         return bitFlags;
193     }
194
195 }