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.pcep.segment.routing;
10 import static com.google.common.base.Preconditions.checkArgument;
12 import io.netty.buffer.ByteBuf;
13 import io.netty.buffer.Unpooled;
14 import org.opendaylight.protocol.pcep.PCEPDeserializerException;
15 import org.opendaylight.protocol.util.BitArray;
16 import org.opendaylight.protocol.util.Ipv4Util;
17 import org.opendaylight.protocol.util.Ipv6Util;
18 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddressNoZone;
19 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.segment.routing.rev200720.NaiType;
20 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.segment.routing.rev200720.SrSubobject;
21 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.segment.routing.rev200720.sr.subobject.Nai;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.segment.routing.rev200720.sr.subobject.nai.IpAdjacency;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.segment.routing.rev200720.sr.subobject.nai.IpAdjacencyBuilder;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.segment.routing.rev200720.sr.subobject.nai.IpNodeId;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.segment.routing.rev200720.sr.subobject.nai.IpNodeIdBuilder;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.segment.routing.rev200720.sr.subobject.nai.Ipv6Local;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.segment.routing.rev200720.sr.subobject.nai.Ipv6LocalBuilder;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.segment.routing.rev200720.sr.subobject.nai.UnnumberedAdjacency;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.segment.routing.rev200720.sr.subobject.nai.UnnumberedAdjacencyBuilder;
30 import org.opendaylight.yangtools.yang.common.Uint32;
31 import org.opendaylight.yangtools.yang.common.netty.ByteBufUtils;
33 public abstract class AbstractSrSubobjectParser {
34 protected static final int MINIMAL_LENGTH = 4;
35 protected static final int BITSET_LENGTH = 8;
36 protected static final int M_FLAG_POSITION = 7;
37 protected static final int C_FLAG_POSITION = 6;
38 protected static final int S_FLAG_POSITION = 5;
39 protected static final int F_FLAG_POSITION = 4;
40 protected static final int MPLS_LABEL_OFFSET = 12;
42 private static final int NAI_TYPE_BITS_OFFSET = 4;
44 private static class SrSubobjectImpl implements SrSubobject {
45 private final boolean mflag;
46 private final boolean cflag;
47 private final NaiType naiType;
48 private final Uint32 sid;
49 private final Nai nai;
51 SrSubobjectImpl(final boolean mflag, final boolean cflag, final NaiType naiType, final Uint32 sid,
55 this.naiType = naiType;
61 public Class<SrSubobject> implementedInterface() {
62 return SrSubobject.class;
66 public Boolean getMFlag() {
71 public Boolean getCFlag() {
76 public NaiType getNaiType() {
81 public Uint32 getSid() {
91 public ByteBuf serializeSubobject(final SrSubobject srSubobject) {
92 checkArgument(srSubobject.getNai() != null || srSubobject.getSid() != null,
93 "Both SID and NAI are absent in SR subobject.");
95 final ByteBuf buffer = Unpooled.buffer(MINIMAL_LENGTH);
98 buffer.writeByte(srSubobject.getNaiType().getIntValue() << NAI_TYPE_BITS_OFFSET);
100 /* Flags set according to RFC8664#section 4.3.1 */
101 final BitArray bits = new BitArray(BITSET_LENGTH);
102 bits.set(M_FLAG_POSITION, srSubobject.getMFlag());
103 /* C flag MUST be set to 0 if M flag is set to 0 */
104 if (!srSubobject.getMFlag()) {
105 bits.set(C_FLAG_POSITION, Boolean.FALSE);
107 bits.set(C_FLAG_POSITION, srSubobject.getCFlag());
109 /* M & C flags MUST be set to 0 if S flag is set to 1 */
110 if (srSubobject.getSid() == null) {
111 bits.set(M_FLAG_POSITION, Boolean.FALSE);
112 bits.set(C_FLAG_POSITION, Boolean.FALSE);
113 bits.set(S_FLAG_POSITION, Boolean.TRUE);
115 /* F flag MUST be set if NT=0 or NAI is absent */
116 if (srSubobject.getNai() == null || srSubobject.getNaiType().getIntValue() == 0) {
117 bits.set(F_FLAG_POSITION, Boolean.TRUE);
120 bits.toByteBuf(buffer);
123 if (srSubobject.getSid() != null) {
124 if (srSubobject.getMFlag()) {
125 buffer.writeInt(srSubobject.getSid().intValue() << MPLS_LABEL_OFFSET);
127 ByteBufUtils.writeOrZero(buffer, srSubobject.getSid());
132 final Nai nai = srSubobject.getNai();
134 serializeNai(nai, srSubobject.getNaiType(), buffer);
139 private static void serializeNai(final Nai nai, final NaiType naiType, final ByteBuf buffer) {
142 Ipv4Util.writeIpv4Address(((IpNodeId) nai).getIpAddress().getIpv4AddressNoZone(), buffer);
145 Ipv6Util.writeIpv6Address(((IpNodeId) nai).getIpAddress().getIpv6AddressNoZone(), buffer);
148 Ipv4Util.writeIpv4Address(((IpAdjacency) nai).getLocalIpAddress().getIpv4AddressNoZone(), buffer);
149 Ipv4Util.writeIpv4Address(((IpAdjacency) nai).getRemoteIpAddress().getIpv4AddressNoZone(), buffer);
152 Ipv6Util.writeIpv6Address(((IpAdjacency) nai).getLocalIpAddress().getIpv6AddressNoZone(), buffer);
153 Ipv6Util.writeIpv6Address(((IpAdjacency) nai).getRemoteIpAddress().getIpv6AddressNoZone(), buffer);
156 final UnnumberedAdjacency unnumbered = (UnnumberedAdjacency) nai;
157 ByteBufUtils.writeOrZero(buffer, unnumbered.getLocalNodeId());
158 ByteBufUtils.writeOrZero(buffer, unnumbered.getLocalInterfaceId());
159 ByteBufUtils.writeOrZero(buffer, unnumbered.getRemoteNodeId());
160 ByteBufUtils.writeOrZero(buffer, unnumbered.getRemoteInterfaceId());
163 final Ipv6Local ipv6Local = (Ipv6Local) nai;
164 Ipv6Util.writeIpv6Address(ipv6Local.getLocalIpv6Address(), buffer);
165 ByteBufUtils.writeOrZero(buffer, ipv6Local.getLocalId());
166 Ipv6Util.writeIpv6Address(ipv6Local.getRemoteIpv6Address(), buffer);
167 ByteBufUtils.writeOrZero(buffer, ipv6Local.getRemoteId());
174 private static Nai parseNai(final NaiType naiType, final ByteBuf buffer) {
175 return switch (naiType) {
176 case Ipv4NodeId -> new IpNodeIdBuilder()
177 .setIpAddress(new IpAddressNoZone(Ipv4Util.addressForByteBuf(buffer)))
179 case Ipv6NodeId -> new IpNodeIdBuilder()
180 .setIpAddress(new IpAddressNoZone(Ipv6Util.addressForByteBuf(buffer)))
182 case Ipv4Adjacency -> new IpAdjacencyBuilder()
183 .setLocalIpAddress(new IpAddressNoZone(Ipv4Util.addressForByteBuf(buffer)))
184 .setRemoteIpAddress(new IpAddressNoZone(Ipv4Util.addressForByteBuf(buffer)))
186 case Ipv6Adjacency -> new IpAdjacencyBuilder()
187 .setLocalIpAddress(new IpAddressNoZone(Ipv6Util.addressForByteBuf(buffer)))
188 .setRemoteIpAddress(new IpAddressNoZone(Ipv6Util.addressForByteBuf(buffer)))
190 case Unnumbered -> new UnnumberedAdjacencyBuilder()
191 .setLocalNodeId(ByteBufUtils.readUint32(buffer))
192 .setLocalInterfaceId(ByteBufUtils.readUint32(buffer))
193 .setRemoteNodeId(ByteBufUtils.readUint32(buffer))
194 .setRemoteInterfaceId(ByteBufUtils.readUint32(buffer))
196 case Ipv6Local -> new Ipv6LocalBuilder()
197 .setLocalIpv6Address(Ipv6Util.addressForByteBuf(buffer))
198 .setLocalId(ByteBufUtils.readUint32(buffer))
199 .setRemoteIpv6Address(Ipv6Util.addressForByteBuf(buffer))
200 .setRemoteId(ByteBufUtils.readUint32(buffer))
206 protected static SrSubobject parseSrSubobject(final ByteBuf buffer) throws PCEPDeserializerException {
207 final int naiTypeByte = buffer.readByte() >> NAI_TYPE_BITS_OFFSET;
208 final NaiType naiType = NaiType.forValue(naiTypeByte);
209 final BitArray bitSet = BitArray.valueOf(buffer.readByte());
210 final boolean f = bitSet.get(F_FLAG_POSITION);
211 final boolean s = bitSet.get(S_FLAG_POSITION);
212 final boolean c = bitSet.get(C_FLAG_POSITION);
213 final boolean m = bitSet.get(M_FLAG_POSITION);
216 throw new PCEPDeserializerException("Both SID and NAI are absent in SR subobject.");
221 final long tmp = buffer.readUnsignedInt();
222 sid = Uint32.valueOf(m ? tmp >> MPLS_LABEL_OFFSET : tmp);
227 if (naiType != null && naiType.getIntValue() != 0 && !f) {
228 nai = parseNai(naiType, buffer);
232 return new SrSubobjectImpl(m, c, naiType, sid, nai);