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