BUG-2794 : refactored code to use BitArray
[bgpcep.git] / pcep / segment-routing / src / main / java / org / opendaylight / protocol / pcep / segment / routing / SrSubobjectParserUtil.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.pcep.segment.routing;
9
10 import static org.opendaylight.protocol.util.ByteBufWriteUtil.writeIpv4Address;
11 import static org.opendaylight.protocol.util.ByteBufWriteUtil.writeIpv6Address;
12 import static org.opendaylight.protocol.util.ByteBufWriteUtil.writeUnsignedByte;
13 import static org.opendaylight.protocol.util.ByteBufWriteUtil.writeUnsignedInt;
14
15 import com.google.common.base.Function;
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.rev100924.IpAddress;
25 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Address;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.segment.routing.rev150112.SidType;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.segment.routing.rev150112.SrSubobject;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.segment.routing.rev150112.sr.subobject.Nai;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.segment.routing.rev150112.sr.subobject.nai.IpAdjacency;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.segment.routing.rev150112.sr.subobject.nai.IpAdjacencyBuilder;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.segment.routing.rev150112.sr.subobject.nai.IpNodeId;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.segment.routing.rev150112.sr.subobject.nai.IpNodeIdBuilder;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.segment.routing.rev150112.sr.subobject.nai.UnnumberedAdjacency;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.segment.routing.rev150112.sr.subobject.nai.UnnumberedAdjacencyBuilder;
35 import org.opendaylight.yangtools.yang.binding.DataContainer;
36
37 final class SrSubobjectParserUtil {
38
39     public static final int MINIMAL_LENGTH = 4;
40     public static final int BITSET_LENGTH = 8;
41
42     private static final int SID_TYPE_BITS_OFFSET = 4;
43
44     private SrSubobjectParserUtil() {
45         throw new UnsupportedOperationException();
46     }
47
48     public static ByteBuf serializeSrSubobject(final SrSubobject srSubobject, final BitArray bits) {
49         Preconditions.checkArgument(srSubobject.getNai() != null || srSubobject.getSid() != null,
50                 "Both SID and NAI are absent in SR subobject.");
51         final ByteBuf body = Unpooled.buffer(MINIMAL_LENGTH);
52         writeUnsignedByte((short)(srSubobject.getSidType().getIntValue() << SID_TYPE_BITS_OFFSET), body);
53         bits.toByteBuf(body);
54
55         if (srSubobject.getSid() != null) {
56             writeUnsignedInt(srSubobject.getSid(), body);
57         }
58         final Nai nai = srSubobject.getNai();
59         if (nai != null) {
60             switch (srSubobject.getSidType()) {
61             case Ipv4NodeId:
62                 writeIpv4Address(((IpNodeId) nai).getIpAddress().getIpv4Address(), body);
63                 break;
64             case Ipv6NodeId:
65                 writeIpv6Address(((IpNodeId) nai).getIpAddress().getIpv6Address(), body);
66                 break;
67             case Ipv4Adjacency:
68                 writeIpv4Address(((IpAdjacency) nai).getLocalIpAddress().getIpv4Address(), body);
69                 writeIpv4Address(((IpAdjacency) nai).getRemoteIpAddress().getIpv4Address(), body);
70                 break;
71             case Ipv6Adjacency:
72                 writeIpv6Address(((IpAdjacency) nai).getLocalIpAddress().getIpv6Address(), body);
73                 writeIpv6Address(((IpAdjacency) nai).getRemoteIpAddress().getIpv6Address(), body);
74                 break;
75             case Unnumbered:
76                 final UnnumberedAdjacency unnumbered = (UnnumberedAdjacency) nai;
77                 ByteBufWriteUtil.writeUnsignedInt(unnumbered.getLocalNodeId(), body);
78                 ByteBufWriteUtil.writeUnsignedInt(unnumbered.getLocalInterfaceId(), body);
79                 ByteBufWriteUtil.writeUnsignedInt(unnumbered.getRemoteNodeId(), body);
80                 ByteBufWriteUtil.writeUnsignedInt(unnumbered.getRemoteInterfaceId(), body);
81                 break;
82             default:
83                 break;
84             }
85         }
86         return body;
87     }
88
89     public static SrSubobject parseSrSubobject(final ByteBuf buffer, final Function<BitArray, Void> getFlags, final int fPosition, final int sPosition)
90             throws PCEPDeserializerException {
91         final int sidTypeByte = buffer.readByte() >> SID_TYPE_BITS_OFFSET;
92         final SidType sidType = SidType.forValue(sidTypeByte);
93
94         final BitArray bitSet = BitArray.valueOf(buffer.readByte());
95         getFlags.apply(bitSet);
96         final boolean f = bitSet.get(fPosition);
97         final boolean s = bitSet.get(sPosition);
98
99         if (f && s) {
100             throw new PCEPDeserializerException("Both SID and NAI are absent in SR subobject.");
101         }
102         final Long sid;
103         if (!s) {
104             sid = buffer.readUnsignedInt();
105         } else {
106             sid = null;
107         }
108
109         final Nai nai;
110
111         if (sidType != null && !f) {
112             switch (sidType) {
113             case Ipv4NodeId:
114                 nai = new IpNodeIdBuilder().setIpAddress(
115                         new IpAddress(new Ipv4Address(Ipv4Util.addressForByteBuf(buffer)))).build();
116                 break;
117             case Ipv6NodeId:
118                 nai = new IpNodeIdBuilder().setIpAddress(
119                         new IpAddress(Ipv6Util.addressForByteBuf(buffer))).build();
120                 break;
121             case Ipv4Adjacency:
122                 nai = new IpAdjacencyBuilder()
123                         .setLocalIpAddress(new IpAddress(Ipv4Util.addressForByteBuf(buffer)))
124                         .setRemoteIpAddress(new IpAddress(Ipv4Util.addressForByteBuf(buffer))).build();
125                 break;
126             case Ipv6Adjacency:
127                 nai = new IpAdjacencyBuilder()
128                         .setLocalIpAddress(new IpAddress(Ipv6Util.addressForByteBuf(buffer)))
129                         .setRemoteIpAddress(new IpAddress(Ipv6Util.addressForByteBuf(buffer))).build();
130                 break;
131             case Unnumbered:
132                 nai = new UnnumberedAdjacencyBuilder().setLocalNodeId(buffer.readUnsignedInt())
133                         .setLocalInterfaceId(buffer.readUnsignedInt()).setRemoteNodeId(buffer.readUnsignedInt())
134                         .setRemoteInterfaceId(buffer.readUnsignedInt()).build();
135                 break;
136             default:
137                 nai = null;
138                 break;
139             }
140         } else {
141             nai = null;
142         }
143
144         return new SrSubobject() {
145             @Override
146             public Class<? extends DataContainer> getImplementedInterface() {
147                 return SrSubobject.class;
148             }
149             @Override
150             public SidType getSidType() {
151                 return sidType;
152             }
153             @Override
154             public Long getSid() {
155                 return sid;
156             }
157             @Override
158             public Nai getNai() {
159                 return nai;
160             }
161         };
162     }
163 }