eeb5b058f58de63ebc9e7a0138cefdc5ca49d0ee
[bgpcep.git] / pcep / segment-routing / src / main / java / org / opendaylight / protocol / pcep / segment / routing02 / SrEroSubobjectParser.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
9 package org.opendaylight.protocol.pcep.segment.routing02;
10
11 import static org.opendaylight.protocol.util.ByteBufWriteUtil.writeBitSet;
12 import static org.opendaylight.protocol.util.ByteBufWriteUtil.writeIpv4Address;
13 import static org.opendaylight.protocol.util.ByteBufWriteUtil.writeIpv6Address;
14 import static org.opendaylight.protocol.util.ByteBufWriteUtil.writeUnsignedByte;
15 import static org.opendaylight.protocol.util.ByteBufWriteUtil.writeUnsignedInt;
16
17 import com.google.common.base.Preconditions;
18 import io.netty.buffer.ByteBuf;
19 import io.netty.buffer.Unpooled;
20 import java.util.BitSet;
21 import org.opendaylight.protocol.pcep.spi.EROSubobjectParser;
22 import org.opendaylight.protocol.pcep.spi.EROSubobjectSerializer;
23 import org.opendaylight.protocol.pcep.spi.EROSubobjectUtil;
24 import org.opendaylight.protocol.pcep.spi.PCEPDeserializerException;
25 import org.opendaylight.protocol.util.ByteArray;
26 import org.opendaylight.protocol.util.ByteBufWriteUtil;
27 import org.opendaylight.protocol.util.Ipv4Util;
28 import org.opendaylight.protocol.util.Ipv6Util;
29 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
30 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Address;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.segment.routing._02.rev140506.SidType;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.segment.routing._02.rev140506.SrEroSubobject;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.segment.routing._02.rev140506.SrEroSubobject.Flags;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.segment.routing._02.rev140506.add.lsp.input.arguments.ero.subobject.subobject.type.SrEroTypeBuilder;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.segment.routing._02.rev140506.sr.ero.subobject.Nai;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.segment.routing._02.rev140506.sr.ero.subobject.nai.IpAdjacency;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.segment.routing._02.rev140506.sr.ero.subobject.nai.IpAdjacencyBuilder;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.segment.routing._02.rev140506.sr.ero.subobject.nai.IpNodeId;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.segment.routing._02.rev140506.sr.ero.subobject.nai.IpNodeIdBuilder;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.segment.routing._02.rev140506.sr.ero.subobject.nai.UnnumberedAdjacency;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.segment.routing._02.rev140506.sr.ero.subobject.nai.UnnumberedAdjacencyBuilder;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.explicit.route.object.ero.Subobject;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.explicit.route.object.ero.SubobjectBuilder;
44
45 public class SrEroSubobjectParser implements EROSubobjectParser, EROSubobjectSerializer {
46
47     public static final int TYPE = 5;
48
49     private static final int FLAGS_OFFSET = 1;
50     private static final int SID_TYPE_BITS_OFFSET = 4;
51     private static final int MINIMAL_LENGTH = 4;
52
53     private static final int M_FLAG_POSITION = 7;
54     private static final int C_FLAG_POSITION = 6;
55     private static final int S_FLAG_POSITION = 5;
56     private static final int F_FLAG_POSITION = 4;
57
58     @Override
59     public void serializeSubobject(final Subobject subobject, final ByteBuf buffer) {
60         Preconditions.checkArgument(subobject.getSubobjectType() instanceof SrEroSubobject,
61                 "Unknown subobject instance. Passed %s. Needed SrEroSubobject.", subobject.getSubobjectType()
62                         .getClass());
63
64         final SrEroSubobject srEroSubobject = (SrEroSubobject) subobject.getSubobjectType();
65         final ByteBuf body = Unpooled.buffer(MINIMAL_LENGTH);
66         writeUnsignedByte((short)(srEroSubobject.getSidType().getIntValue() << SID_TYPE_BITS_OFFSET), body);
67
68         final Flags flags = srEroSubobject.getFlags();
69         final BitSet bits = new BitSet();
70         if (flags != null) {
71             bits.set(M_FLAG_POSITION, flags.isM());
72             bits.set(C_FLAG_POSITION, flags.isC());
73             bits.set(S_FLAG_POSITION, flags.isS());
74             bits.set(F_FLAG_POSITION, flags.isF());
75         }
76         writeBitSet(bits, FLAGS_OFFSET, body);
77
78         if (srEroSubobject.getSid() != null && !flags.isS()) {
79             writeUnsignedInt(srEroSubobject.getSid(), body);
80         }
81         final Nai nai = srEroSubobject.getNai();
82         if (nai != null && !flags.isF()) {
83             switch (srEroSubobject.getSidType()) {
84             case Ipv4NodeId:
85                 writeIpv4Address(((IpNodeId) nai).getIpAddress().getIpv4Address(), body);
86                 break;
87             case Ipv6NodeId:
88                 writeIpv6Address(((IpNodeId) nai).getIpAddress().getIpv6Address(), body);
89                 break;
90             case Ipv4Adjacency:
91                 writeIpv4Address(((IpAdjacency) nai).getLocalIpAddress().getIpv4Address(), body);
92                 writeIpv4Address(((IpAdjacency) nai).getRemoteIpAddress().getIpv4Address(), body);
93                 break;
94             case Ipv6Adjacency:
95                 writeIpv6Address(((IpAdjacency) nai).getLocalIpAddress().getIpv6Address(), body);
96                 writeIpv6Address(((IpAdjacency) nai).getRemoteIpAddress().getIpv6Address(), body);
97                 break;
98             case Unnumbered:
99                 final UnnumberedAdjacency unnumbered = (UnnumberedAdjacency) nai;
100                 ByteBufWriteUtil.writeUnsignedInt(unnumbered.getLocalNodeId(), body);
101                 ByteBufWriteUtil.writeUnsignedInt(unnumbered.getLocalInterfaceId(), body);
102                 ByteBufWriteUtil.writeUnsignedInt(unnumbered.getRemoteNodeId(), body);
103                 ByteBufWriteUtil.writeUnsignedInt(unnumbered.getRemoteInterfaceId(), body);
104                 break;
105             default:
106                 break;
107             }
108         }
109         EROSubobjectUtil.formatSubobject(TYPE, subobject.isLoose(), body, buffer);
110     }
111
112     @Override
113     public Subobject parseSubobject(final ByteBuf buffer, final boolean loose) throws PCEPDeserializerException {
114         Preconditions.checkArgument(buffer != null && buffer.isReadable(),
115                 "Array of bytes is mandatory. Can't be null or empty.");
116         if (buffer.readableBytes() <= MINIMAL_LENGTH) {
117             throw new PCEPDeserializerException("Wrong length of array of bytes. Passed: " + buffer.readableBytes() + ";");
118         }
119
120         final SrEroTypeBuilder srEroSubobjectBuilder = new SrEroTypeBuilder();
121         final int sidTypeByte = buffer.readByte() >> SID_TYPE_BITS_OFFSET;
122         final SidType sidType = SidType.forValue(sidTypeByte);
123         srEroSubobjectBuilder.setSidType(sidType);
124
125         final BitSet bitSet = ByteArray.bytesToBitSet(new byte[] { buffer.readByte() });
126         final boolean f = bitSet.get(F_FLAG_POSITION);
127         final boolean s = bitSet.get(S_FLAG_POSITION);
128         final boolean c = bitSet.get(C_FLAG_POSITION);
129         final boolean m = bitSet.get(M_FLAG_POSITION);
130         final Flags flags = new Flags(c, f, m, s);
131         srEroSubobjectBuilder.setFlags(flags);
132
133         if (!flags.isS()) {
134             final long sid = buffer.readUnsignedInt();
135             srEroSubobjectBuilder.setSid(sid);
136         }
137         if (sidType != null && !flags.isF()) {
138             switch (sidType) {
139             case Ipv4NodeId:
140                 srEroSubobjectBuilder.setNai(new IpNodeIdBuilder().setIpAddress(
141                         new IpAddress(new Ipv4Address(Ipv4Util.addressForByteBuf(buffer)))).build());
142                 break;
143             case Ipv6NodeId:
144                 srEroSubobjectBuilder.setNai(new IpNodeIdBuilder().setIpAddress(
145                         new IpAddress(Ipv6Util.addressForByteBuf(buffer))).build());
146                 break;
147             case Ipv4Adjacency:
148                 srEroSubobjectBuilder.setNai(new IpAdjacencyBuilder()
149                         .setLocalIpAddress(new IpAddress(Ipv4Util.addressForByteBuf(buffer)))
150                         .setRemoteIpAddress(new IpAddress(Ipv4Util.addressForByteBuf(buffer))).build());
151                 break;
152             case Ipv6Adjacency:
153                 srEroSubobjectBuilder.setNai(new IpAdjacencyBuilder()
154                         .setLocalIpAddress(new IpAddress(Ipv6Util.addressForByteBuf(buffer)))
155                         .setRemoteIpAddress(new IpAddress(Ipv6Util.addressForByteBuf(buffer))).build());
156                 break;
157             case Unnumbered:
158                 srEroSubobjectBuilder.setNai(new UnnumberedAdjacencyBuilder().setLocalNodeId(buffer.readUnsignedInt())
159                         .setLocalInterfaceId(buffer.readUnsignedInt()).setRemoteNodeId(buffer.readUnsignedInt())
160                         .setRemoteInterfaceId(buffer.readUnsignedInt()).build());
161                 break;
162             default:
163                 break;
164             }
165         }
166         final SubobjectBuilder subobjectBuilder = new SubobjectBuilder();
167         subobjectBuilder.setLoose(loose);
168         subobjectBuilder.setSubobjectType(srEroSubobjectBuilder.build());
169         return subobjectBuilder.build();
170     }
171
172 }