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