BUG-47: more subobject models
[bgpcep.git] / pcep / impl / src / main / java / org / opendaylight / protocol / pcep / impl / PCEPXROSubobjectParser.java
1 /*
2  * Copyright (c) 2013 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.impl;
9
10 import java.util.ArrayList;
11 import java.util.List;
12
13 import org.opendaylight.protocol.pcep.PCEPDeserializerException;
14 import org.opendaylight.protocol.pcep.impl.subobject.XROAsNumberSubobjectParser;
15 import org.opendaylight.protocol.pcep.impl.subobject.XROIPv4PrefixSubobjectParser;
16 import org.opendaylight.protocol.pcep.impl.subobject.XROIPv6PrefixSubobjectParser;
17 import org.opendaylight.protocol.pcep.impl.subobject.XROSRLGSubobjectParser;
18 import org.opendaylight.protocol.pcep.impl.subobject.XROUnnumberedInterfaceSubobjectParser;
19 import org.opendaylight.protocol.pcep.subobject.ExcludeRouteSubobject;
20 import org.opendaylight.protocol.pcep.subobject.XROAsNumberSubobject;
21 import org.opendaylight.protocol.pcep.subobject.XROIPPrefixSubobject;
22 import org.opendaylight.protocol.pcep.subobject.XROSRLGSubobject;
23 import org.opendaylight.protocol.pcep.subobject.XROUnnumberedInterfaceSubobject;
24 import org.opendaylight.protocol.util.ByteArray;
25 import org.slf4j.Logger;
26 import org.slf4j.LoggerFactory;
27
28 /**
29  * Parser for {@link org.opendaylight.protocol.pcep.PCEPXROSubobject PCEPXROSubobject}
30  */
31 public class PCEPXROSubobjectParser {
32
33         private static final Logger logger = LoggerFactory.getLogger(PCEPXROSubobjectParser.class);
34
35         /**
36          * Type identifier for {@link org.opendaylight.protocol.pcep.PCEPXROSubobject PCEPXROSubobject}
37          */
38         public enum PCEPXROSubobjectType {
39                 IPv4_PREFIX(1), IPv6_PREFIX(2), UNNUMBERED_INTERFACE_ID(4), AS_NUMBER(32), SRLG(34);
40
41                 private final int indicator;
42
43                 PCEPXROSubobjectType(final int indicator) {
44                         this.indicator = indicator;
45                 }
46
47                 public int getIndicator() {
48                         return this.indicator;
49                 }
50
51                 public static PCEPXROSubobjectType getFromInt(final int type) throws PCEPDeserializerException {
52
53                         for (final PCEPXROSubobjectType type_e : PCEPXROSubobjectType.values()) {
54                                 if (type_e.getIndicator() == type)
55                                         return type_e;
56                         }
57
58                         throw new PCEPDeserializerException("Unknown Subobject type. Passed: " + type + "; Known: " + PCEPXROSubobjectType.values()
59                                         + ".");
60                 }
61         }
62
63         /*
64          * Fields lengths in Bytes
65          */
66         public static final int TYPE_FLAG_F_LENGTH = 1;
67         public static final int LENGTH_F_LENGTH = 1;
68
69         /*
70          * Fields offsets in Bytes
71          */
72         public static final int TYPE_FLAG_F_OFFSET = 0;
73         public static final int LENGTH_F_OFFSET = TYPE_FLAG_F_OFFSET + TYPE_FLAG_F_LENGTH;
74         public static final int SO_CONTENTS_OFFSET = LENGTH_F_OFFSET + LENGTH_F_LENGTH;
75
76         public static List<ExcludeRouteSubobject> parse(final byte[] bytes) throws PCEPDeserializerException {
77                 if (bytes == null)
78                         throw new IllegalArgumentException("Byte array is mandatory.");
79
80                 final List<ExcludeRouteSubobject> subobjsList = new ArrayList<ExcludeRouteSubobject>();
81                 boolean mandatoryFlag;
82                 PCEPXROSubobjectType type;
83                 byte[] soContentsBytes;
84                 int length;
85                 int offset = 0;
86
87                 while (offset < bytes.length) {
88
89                         mandatoryFlag = ((bytes[offset + TYPE_FLAG_F_OFFSET] & (1 << 7)) != 0);
90                         length = ByteArray.bytesToInt(ByteArray.subByte(bytes, offset + LENGTH_F_OFFSET, LENGTH_F_LENGTH));
91
92                         type = PCEPXROSubobjectType.getFromInt((bytes[offset + TYPE_FLAG_F_OFFSET] & 0xff) & ~(1 << 7));
93
94                         if (length > bytes.length - offset)
95                                 throw new PCEPDeserializerException("Wrong length specified. Passed: " + length + "; Expected: <= "
96                                                 + (bytes.length - offset));
97
98                         soContentsBytes = new byte[length - SO_CONTENTS_OFFSET];
99                         System.arraycopy(bytes, offset + SO_CONTENTS_OFFSET, soContentsBytes, 0, length - SO_CONTENTS_OFFSET);
100
101                         logger.debug("Attempt to parse exclude route objects subobject from bytes: {}", ByteArray.bytesToHexString(soContentsBytes));
102                         final ExcludeRouteSubobject subObj = parseSpecificSubobject(type, soContentsBytes, mandatoryFlag);
103                         logger.debug("Subobject was parsed. {}", subObj);
104
105                         subobjsList.add(subObj);
106
107                         offset += length;
108                 }
109
110                 return subobjsList;
111         }
112
113         public static byte[] put(final List<ExcludeRouteSubobject> objsToSerialize) {
114                 final List<byte[]> bytesList = new ArrayList<byte[]>(objsToSerialize.size());
115
116                 int length = 0;
117                 for (final ExcludeRouteSubobject obj : objsToSerialize) {
118                         final byte[] bytes = put(obj);
119                         length += bytes.length;
120                         bytesList.add(bytes);
121                 }
122
123                 final byte[] retBytes = new byte[length];
124
125                 int offset = 0;
126                 for (final byte[] bytes : bytesList) {
127                         System.arraycopy(bytes, 0, retBytes, offset, bytes.length);
128                         offset += bytes.length;
129                 }
130
131                 return retBytes;
132         }
133
134         public static byte[] put(final ExcludeRouteSubobject objToSerialize) {
135                 int typeIndicator = 0;
136
137                 final byte[] soContentsBytes;
138
139                 if (objToSerialize instanceof XROIPPrefixSubobject && ((XROIPPrefixSubobject) objToSerialize).getPrefix().getIpv4Prefix() != null) {
140                         typeIndicator = PCEPXROSubobjectType.IPv4_PREFIX.getIndicator();
141                         soContentsBytes = XROIPv4PrefixSubobjectParser.put(objToSerialize);
142                 } else if (objToSerialize instanceof XROIPPrefixSubobject
143                                 && ((XROIPPrefixSubobject) objToSerialize).getPrefix().getIpv6Prefix() != null) {
144                         typeIndicator = PCEPXROSubobjectType.IPv6_PREFIX.getIndicator();
145                         soContentsBytes = XROIPv6PrefixSubobjectParser.put(objToSerialize);
146                 } else if (objToSerialize instanceof XROAsNumberSubobject) {
147                         typeIndicator = PCEPXROSubobjectType.AS_NUMBER.getIndicator();
148                         soContentsBytes = XROAsNumberSubobjectParser.put(objToSerialize);
149                 } else if (objToSerialize instanceof XROUnnumberedInterfaceSubobject) {
150                         typeIndicator = PCEPXROSubobjectType.UNNUMBERED_INTERFACE_ID.getIndicator();
151                         soContentsBytes = XROUnnumberedInterfaceSubobjectParser.put(objToSerialize);
152                 } else if (objToSerialize instanceof XROSRLGSubobject) {
153                         typeIndicator = PCEPXROSubobjectType.SRLG.getIndicator();
154                         soContentsBytes = XROSRLGSubobjectParser.put(objToSerialize);
155                 } else
156                         throw new IllegalArgumentException("Unknown instance of PCEPXROSubobject. Passed: " + objToSerialize.getClass() + ".");
157
158                 final byte[] bytes = new byte[SO_CONTENTS_OFFSET + soContentsBytes.length];
159
160                 bytes[TYPE_FLAG_F_OFFSET] = (byte) (ByteArray.cutBytes(ByteArray.intToBytes(typeIndicator), (Integer.SIZE / 8) - TYPE_FLAG_F_LENGTH)[0] | (objToSerialize.isMandatory() ? 1 << 7
161                                 : 0));
162                 bytes[LENGTH_F_OFFSET] = ByteArray.cutBytes(ByteArray.intToBytes(soContentsBytes.length + SO_CONTENTS_OFFSET), (Integer.SIZE / 8)
163                                 - LENGTH_F_LENGTH)[0];
164
165                 System.arraycopy(soContentsBytes, 0, bytes, SO_CONTENTS_OFFSET, soContentsBytes.length);
166
167                 return bytes;
168         }
169
170         private static ExcludeRouteSubobject parseSpecificSubobject(final PCEPXROSubobjectType type, final byte[] soContentsBytes,
171                         final boolean mandatory) throws PCEPDeserializerException {
172
173                 switch (type) {
174                 case IPv4_PREFIX:
175                         return XROIPv4PrefixSubobjectParser.parse(soContentsBytes, mandatory);
176                 case IPv6_PREFIX:
177                         return XROIPv6PrefixSubobjectParser.parse(soContentsBytes, mandatory);
178                 case UNNUMBERED_INTERFACE_ID:
179                         return XROUnnumberedInterfaceSubobjectParser.parse(soContentsBytes, mandatory);
180                 case AS_NUMBER:
181                         return XROAsNumberSubobjectParser.parse(soContentsBytes, mandatory);
182                 case SRLG:
183                         return XROSRLGSubobjectParser.parse(soContentsBytes, mandatory);
184                 default:
185                         throw new PCEPDeserializerException("Unknown Subobject type. Passed: " + type + ".");
186                 }
187         }
188 }