Bump mdsal to 5.0.2
[bgpcep.git] / pcep / segment-routing / src / main / java / org / opendaylight / protocol / pcep / segment / routing / AbstractSrSubobjectParser.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.pcep.segment.routing;
9
10 import static com.google.common.base.Preconditions.checkArgument;
11 import static org.opendaylight.protocol.util.ByteBufWriteUtil.writeIpv4Address;
12 import static org.opendaylight.protocol.util.ByteBufWriteUtil.writeIpv6Address;
13 import static org.opendaylight.protocol.util.ByteBufWriteUtil.writeUnsignedByte;
14 import static org.opendaylight.protocol.util.ByteBufWriteUtil.writeUnsignedInt;
15
16 import io.netty.buffer.ByteBuf;
17 import io.netty.buffer.Unpooled;
18 import org.opendaylight.protocol.pcep.spi.PCEPDeserializerException;
19 import org.opendaylight.protocol.util.BitArray;
20 import org.opendaylight.protocol.util.ByteBufWriteUtil;
21 import org.opendaylight.protocol.util.Ipv4Util;
22 import org.opendaylight.protocol.util.Ipv6Util;
23 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddressNoZone;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.segment.routing.rev181109.SidType;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.segment.routing.rev181109.SrSubobject;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.segment.routing.rev181109.sr.subobject.Nai;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.segment.routing.rev181109.sr.subobject.nai.IpAdjacency;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.segment.routing.rev181109.sr.subobject.nai.IpAdjacencyBuilder;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.segment.routing.rev181109.sr.subobject.nai.IpNodeId;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.segment.routing.rev181109.sr.subobject.nai.IpNodeIdBuilder;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.segment.routing.rev181109.sr.subobject.nai.UnnumberedAdjacency;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.segment.routing.rev181109.sr.subobject.nai.UnnumberedAdjacencyBuilder;
33 import org.opendaylight.yangtools.yang.common.Uint32;
34
35 public abstract class AbstractSrSubobjectParser {
36
37     protected static final int MINIMAL_LENGTH = 4;
38     protected static final int BITSET_LENGTH = 8;
39     protected static final int M_FLAG_POSITION = 7;
40     protected static final int C_FLAG_POSITION = 6;
41     protected static final int S_FLAG_POSITION = 5;
42     protected static final int F_FLAG_POSITION = 4;
43     protected static final int MPLS_LABEL_OFFSET = 12;
44
45     private static final int SID_TYPE_BITS_OFFSET = 4;
46
47     private static class SrSubobjectImpl implements SrSubobject {
48         private final boolean mflag;
49         private final boolean cflag;
50         private final SidType sidType;
51         private final Uint32 sid;
52         private final Nai nai;
53
54         SrSubobjectImpl(final boolean mflag, final boolean cflag, final SidType sidType, final Uint32 sid,
55                 final Nai nai) {
56             this.mflag = mflag;
57             this.cflag = cflag;
58             this.sidType = sidType;
59             this.sid = sid;
60             this.nai = nai;
61         }
62
63         @Override
64         public Class<SrSubobject> implementedInterface() {
65             return SrSubobject.class;
66         }
67
68         @Override
69         public Boolean isMFlag() {
70             return this.mflag;
71         }
72
73         @Override
74         public Boolean isCFlag() {
75             return this.cflag;
76         }
77
78         @Override
79         public SidType getSidType() {
80             return this.sidType;
81         }
82
83         @Override
84         public Uint32 getSid() {
85             return this.sid;
86         }
87
88         @Override
89         public Nai getNai() {
90             return this.nai;
91         }
92     }
93
94     public ByteBuf serializeSubobject(final SrSubobject srSubobject) {
95         final ByteBuf buffer = Unpooled.buffer(MINIMAL_LENGTH);
96         // sid type
97         writeUnsignedByte((short)(srSubobject.getSidType().getIntValue() << SID_TYPE_BITS_OFFSET), buffer);
98
99         final BitArray bits = new BitArray(BITSET_LENGTH);
100         bits.set(M_FLAG_POSITION, srSubobject.isMFlag());
101         bits.set(C_FLAG_POSITION, srSubobject.isCFlag());
102         if (srSubobject.getSid() == null) {
103             bits.set(S_FLAG_POSITION, Boolean.TRUE);
104         }
105         if (srSubobject.getNai() == null) {
106             bits.set(F_FLAG_POSITION, Boolean.TRUE);
107         }
108         // bits
109         bits.toByteBuf(buffer);
110         // sid
111         checkArgument(srSubobject.getNai() != null || srSubobject.getSid() != null,
112                 "Both SID and NAI are absent in SR subobject.");
113         if (srSubobject.getSid() != null) {
114             if (srSubobject.isMFlag()) {
115                 writeUnsignedInt(srSubobject.getSid().toJava() << MPLS_LABEL_OFFSET, buffer);
116             } else {
117                 writeUnsignedInt(srSubobject.getSid(), buffer);
118             }
119         }
120         // nai
121         final Nai nai = srSubobject.getNai();
122         if (nai != null) {
123             serializeNai(nai, srSubobject.getSidType() ,buffer);
124         }
125         return buffer;
126     }
127
128     private static void serializeNai(final Nai nai, final SidType sidType, final ByteBuf buffer) {
129         switch (sidType) {
130             case Ipv4NodeId:
131                 writeIpv4Address(((IpNodeId) nai).getIpAddress().getIpv4AddressNoZone(), buffer);
132                 break;
133             case Ipv6NodeId:
134                 writeIpv6Address(((IpNodeId) nai).getIpAddress().getIpv6AddressNoZone(), buffer);
135                 break;
136             case Ipv4Adjacency:
137                 writeIpv4Address(((IpAdjacency) nai).getLocalIpAddress().getIpv4AddressNoZone(), buffer);
138                 writeIpv4Address(((IpAdjacency) nai).getRemoteIpAddress().getIpv4AddressNoZone(), buffer);
139                 break;
140             case Ipv6Adjacency:
141                 writeIpv6Address(((IpAdjacency) nai).getLocalIpAddress().getIpv6AddressNoZone(), buffer);
142                 writeIpv6Address(((IpAdjacency) nai).getRemoteIpAddress().getIpv6AddressNoZone(), buffer);
143                 break;
144             case Unnumbered:
145                 final UnnumberedAdjacency unnumbered = (UnnumberedAdjacency) nai;
146                 ByteBufWriteUtil.writeUnsignedInt(unnumbered.getLocalNodeId(), buffer);
147                 ByteBufWriteUtil.writeUnsignedInt(unnumbered.getLocalInterfaceId(), buffer);
148                 ByteBufWriteUtil.writeUnsignedInt(unnumbered.getRemoteNodeId(), buffer);
149                 ByteBufWriteUtil.writeUnsignedInt(unnumbered.getRemoteInterfaceId(), buffer);
150                 break;
151             default:
152                 break;
153         }
154     }
155
156     private static Nai parseNai(final SidType sidType, final ByteBuf buffer) {
157         switch (sidType) {
158             case Ipv4NodeId:
159                 return new IpNodeIdBuilder().setIpAddress(
160                     new IpAddressNoZone(Ipv4Util.noZoneAddressForByteBuf(buffer))).build();
161             case Ipv6NodeId:
162                 return new IpNodeIdBuilder().setIpAddress(
163                     new IpAddressNoZone(Ipv6Util.noZoneAddressForByteBuf(buffer))).build();
164             case Ipv4Adjacency:
165                 return new IpAdjacencyBuilder()
166                         .setLocalIpAddress(new IpAddressNoZone(Ipv4Util.noZoneAddressForByteBuf(buffer)))
167                         .setRemoteIpAddress(new IpAddressNoZone(Ipv4Util.noZoneAddressForByteBuf(buffer))).build();
168             case Ipv6Adjacency:
169                 return new IpAdjacencyBuilder()
170                         .setLocalIpAddress(new IpAddressNoZone(Ipv6Util.noZoneAddressForByteBuf(buffer)))
171                         .setRemoteIpAddress(new IpAddressNoZone(Ipv6Util.noZoneAddressForByteBuf(buffer))).build();
172             case Unnumbered:
173                 return new UnnumberedAdjacencyBuilder().setLocalNodeId(buffer.readUnsignedInt())
174                         .setLocalInterfaceId(buffer.readUnsignedInt()).setRemoteNodeId(buffer.readUnsignedInt())
175                         .setRemoteInterfaceId(buffer.readUnsignedInt()).build();
176             default:
177                 return null;
178         }
179     }
180
181     protected static SrSubobject parseSrSubobject(final ByteBuf buffer) throws PCEPDeserializerException {
182         final int sidTypeByte = buffer.readByte() >> SID_TYPE_BITS_OFFSET;
183         final SidType sidType = SidType.forValue(sidTypeByte);
184         final BitArray bitSet = BitArray.valueOf(buffer.readByte());
185         final boolean f = bitSet.get(F_FLAG_POSITION);
186         final boolean s = bitSet.get(S_FLAG_POSITION);
187         final boolean c = bitSet.get(C_FLAG_POSITION);
188         final boolean m = bitSet.get(M_FLAG_POSITION);
189
190         if (f && s) {
191             throw new PCEPDeserializerException("Both SID and NAI are absent in SR subobject.");
192         }
193
194         final Uint32 sid;
195         if (!s) {
196             final long tmp = buffer.readUnsignedInt();
197             sid = Uint32.valueOf(m ? tmp >> MPLS_LABEL_OFFSET : tmp);
198         } else {
199             sid = null;
200         }
201         final Nai nai;
202         if (sidType != null && !f) {
203             nai = parseNai(sidType, buffer);
204         } else {
205             nai = null;
206         }
207         return new SrSubobjectImpl(m, c, sidType, sid, nai);
208     }
209 }