2 * Copyright (c) 2013 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
9 package org.opendaylight.protocol.pcep.impl;
11 import java.util.ArrayList;
12 import java.util.Arrays;
13 import java.util.HashMap;
14 import java.util.List;
16 import org.slf4j.Logger;
17 import org.slf4j.LoggerFactory;
19 import org.opendaylight.protocol.util.ByteArray;
20 import org.opendaylight.protocol.concepts.IPv4Address;
21 import org.opendaylight.protocol.concepts.IPv6Address;
22 import org.opendaylight.protocol.pcep.PCEPDeserializerException;
23 import org.opendaylight.protocol.pcep.PCEPDocumentedException;
24 import org.opendaylight.protocol.pcep.PCEPErrors;
25 import org.opendaylight.protocol.pcep.PCEPObject;
26 import org.opendaylight.protocol.pcep.impl.PCEPObjectIdentifier.ObjectClass;
27 import org.opendaylight.protocol.pcep.impl.object.PCEPBranchNodeListObjectParser;
28 import org.opendaylight.protocol.pcep.impl.object.PCEPCloseObjectParser;
29 import org.opendaylight.protocol.pcep.impl.object.PCEPEndPointsIPv4ObjectParser;
30 import org.opendaylight.protocol.pcep.impl.object.PCEPEndPointsIPv6ObjectParser;
31 import org.opendaylight.protocol.pcep.impl.object.PCEPErrorObjectParser;
32 import org.opendaylight.protocol.pcep.impl.object.PCEPExcludeRouteObjectParser;
33 import org.opendaylight.protocol.pcep.impl.object.PCEPExistingPathBandwidthObjectParser;
34 import org.opendaylight.protocol.pcep.impl.object.PCEPExplicitRouteObjectParser;
35 import org.opendaylight.protocol.pcep.impl.object.PCEPGlobalConstraintsObjectParser;
36 import org.opendaylight.protocol.pcep.impl.object.PCEPIncludeRouteObjectParser;
37 import org.opendaylight.protocol.pcep.impl.object.PCEPLoadBalancingObjectParser;
38 import org.opendaylight.protocol.pcep.impl.object.PCEPLspObjectParser;
39 import org.opendaylight.protocol.pcep.impl.object.PCEPLspaObjectParser;
40 import org.opendaylight.protocol.pcep.impl.object.PCEPMetricObjectParser;
41 import org.opendaylight.protocol.pcep.impl.object.PCEPNoPathObjectParser;
42 import org.opendaylight.protocol.pcep.impl.object.PCEPNonBranchNodeListObjectParser;
43 import org.opendaylight.protocol.pcep.impl.object.PCEPNotificationObjectParser;
44 import org.opendaylight.protocol.pcep.impl.object.PCEPObjectiveFunctionObjectParser;
45 import org.opendaylight.protocol.pcep.impl.object.PCEPOpenObjectParser;
46 import org.opendaylight.protocol.pcep.impl.object.PCEPP2MPEndPointsIPv4ObjectParser;
47 import org.opendaylight.protocol.pcep.impl.object.PCEPP2MPEndPointsIPv6ObjectParser;
48 import org.opendaylight.protocol.pcep.impl.object.PCEPReportedRouteObjectParser;
49 import org.opendaylight.protocol.pcep.impl.object.PCEPRequestParameterObjectParser;
50 import org.opendaylight.protocol.pcep.impl.object.PCEPRequestedPathBandwidthObjectParser;
51 import org.opendaylight.protocol.pcep.impl.object.PCEPSecondaryExplicitRouteObjectParser;
52 import org.opendaylight.protocol.pcep.impl.object.PCEPSecondaryRecordRouteObjectParser;
53 import org.opendaylight.protocol.pcep.impl.object.PCEPSvecObjectParser;
54 import org.opendaylight.protocol.pcep.impl.object.PCEPUnreachedIPv4DestinationObjectParser;
55 import org.opendaylight.protocol.pcep.impl.object.PCEPUnreachedIPv6DestinationObjectParser;
56 import org.opendaylight.protocol.pcep.impl.object.UnknownObject;
57 import org.opendaylight.protocol.pcep.object.PCEPBranchNodeListObject;
58 import org.opendaylight.protocol.pcep.object.PCEPBranchNodeObject;
59 import org.opendaylight.protocol.pcep.object.PCEPCloseObject;
60 import org.opendaylight.protocol.pcep.object.PCEPEndPointsObject;
61 import org.opendaylight.protocol.pcep.object.PCEPErrorObject;
62 import org.opendaylight.protocol.pcep.object.PCEPExcludeRouteObject;
63 import org.opendaylight.protocol.pcep.object.PCEPExistingPathBandwidthObject;
64 import org.opendaylight.protocol.pcep.object.PCEPExplicitRouteObject;
65 import org.opendaylight.protocol.pcep.object.PCEPGlobalConstraintsObject;
66 import org.opendaylight.protocol.pcep.object.PCEPIncludeRouteObject;
67 import org.opendaylight.protocol.pcep.object.PCEPLoadBalancingObject;
68 import org.opendaylight.protocol.pcep.object.PCEPLspObject;
69 import org.opendaylight.protocol.pcep.object.PCEPLspaObject;
70 import org.opendaylight.protocol.pcep.object.PCEPMetricObject;
71 import org.opendaylight.protocol.pcep.object.PCEPNoPathObject;
72 import org.opendaylight.protocol.pcep.object.PCEPNonBranchNodeListObject;
73 import org.opendaylight.protocol.pcep.object.PCEPNotificationObject;
74 import org.opendaylight.protocol.pcep.object.PCEPObjectiveFunctionObject;
75 import org.opendaylight.protocol.pcep.object.PCEPOpenObject;
76 import org.opendaylight.protocol.pcep.object.PCEPP2MPEndPointsObject;
77 import org.opendaylight.protocol.pcep.object.PCEPReportedRouteObject;
78 import org.opendaylight.protocol.pcep.object.PCEPRequestParameterObject;
79 import org.opendaylight.protocol.pcep.object.PCEPRequestedPathBandwidthObject;
80 import org.opendaylight.protocol.pcep.object.PCEPSecondaryExplicitRouteObject;
81 import org.opendaylight.protocol.pcep.object.PCEPSecondaryRecordRouteObject;
82 import org.opendaylight.protocol.pcep.object.PCEPSvecObject;
83 import org.opendaylight.protocol.pcep.object.PCEPUnreachedDestinationObject;
86 * Factory for subclasses of {@link org.opendaylight.protocol.pcep.PCEPObject PCEPObject}
88 public class PCEPObjectFactory {
90 private static final Logger logger = LoggerFactory.getLogger(PCEPObjectFactory.class);
93 * Map of parsers for subobjects of {@link org.opendaylight.protocol.pcep.PCEPObject
96 private static class MapOfParsers extends HashMap<PCEPObjectIdentifier, PCEPObjectParser> {
97 private static final long serialVersionUID = 1L;
99 private final static MapOfParsers instance = new MapOfParsers();
101 private MapOfParsers() {
105 private void fillInMap() {
106 this.put(new PCEPObjectIdentifier(ObjectClass.OPEN, 1), new PCEPOpenObjectParser());
107 this.put(new PCEPObjectIdentifier(ObjectClass.RP, 1), new PCEPRequestParameterObjectParser());
108 this.put(new PCEPObjectIdentifier(ObjectClass.NO_PATH, 1), new PCEPNoPathObjectParser());
109 this.put(new PCEPObjectIdentifier(ObjectClass.BANDWIDTH, 1), new PCEPRequestedPathBandwidthObjectParser());
110 this.put(new PCEPObjectIdentifier(ObjectClass.BANDWIDTH, 2), new PCEPExistingPathBandwidthObjectParser());
111 this.put(new PCEPObjectIdentifier(ObjectClass.METRIC, 1), new PCEPMetricObjectParser());
112 this.put(new PCEPObjectIdentifier(ObjectClass.END_POINTS, 1), new PCEPEndPointsIPv4ObjectParser());
113 this.put(new PCEPObjectIdentifier(ObjectClass.END_POINTS, 2), new PCEPEndPointsIPv6ObjectParser());
114 this.put(new PCEPObjectIdentifier(ObjectClass.LSPA, 1), new PCEPLspaObjectParser());
115 this.put(new PCEPObjectIdentifier(ObjectClass.SVEC, 1), new PCEPSvecObjectParser());
116 this.put(new PCEPObjectIdentifier(ObjectClass.NOTIFICATION, 1), new PCEPNotificationObjectParser());
117 this.put(new PCEPObjectIdentifier(ObjectClass.ERROR, 1), new PCEPErrorObjectParser());
118 this.put(new PCEPObjectIdentifier(ObjectClass.CLOSE, 1), new PCEPCloseObjectParser());
119 this.put(new PCEPObjectIdentifier(ObjectClass.LOAD_BALANCING, 1), new PCEPLoadBalancingObjectParser());
120 this.put(new PCEPObjectIdentifier(ObjectClass.LSP, 1), new PCEPLspObjectParser());
121 this.put(new PCEPObjectIdentifier(ObjectClass.ERO, 1), new PCEPExplicitRouteObjectParser());
122 this.put(new PCEPObjectIdentifier(ObjectClass.RRO, 1), new PCEPReportedRouteObjectParser());
123 this.put(new PCEPObjectIdentifier(ObjectClass.IRO, 1), new PCEPIncludeRouteObjectParser());
126 this.put(new PCEPObjectIdentifier(ObjectClass.XRO, 1), new PCEPExcludeRouteObjectParser());
127 this.put(new PCEPObjectIdentifier(ObjectClass.OBJCETIVE_FUNCTION, 1), new PCEPObjectiveFunctionObjectParser());
128 this.put(new PCEPObjectIdentifier(ObjectClass.GLOBAL_CONSTRAINTS, 1), new PCEPGlobalConstraintsObjectParser());
131 this.put(new PCEPObjectIdentifier(ObjectClass.END_POINTS, 3), new PCEPP2MPEndPointsIPv4ObjectParser());
132 this.put(new PCEPObjectIdentifier(ObjectClass.END_POINTS, 4), new PCEPP2MPEndPointsIPv6ObjectParser());
133 this.put(new PCEPObjectIdentifier(ObjectClass.UNREACHED_DESTINATION, 1), new PCEPUnreachedIPv4DestinationObjectParser());
134 this.put(new PCEPObjectIdentifier(ObjectClass.UNREACHED_DESTINATION, 2), new PCEPUnreachedIPv6DestinationObjectParser());
135 this.put(new PCEPObjectIdentifier(ObjectClass.SERO, 1), new PCEPSecondaryExplicitRouteObjectParser());
136 this.put(new PCEPObjectIdentifier(ObjectClass.SRRO, 1), new PCEPSecondaryRecordRouteObjectParser());
137 this.put(new PCEPObjectIdentifier(ObjectClass.BRANCH_NODE, 1), new PCEPBranchNodeListObjectParser());
138 this.put(new PCEPObjectIdentifier(ObjectClass.BRANCH_NODE, 2), new PCEPNonBranchNodeListObjectParser());
141 public static MapOfParsers getInstance() {
146 private static PCEPObject parse(final byte[] bytes, final PCEPObjectHeader header) throws PCEPDocumentedException, PCEPDeserializerException {
148 throw new IllegalArgumentException("Array of bytes is mandatory.");
150 throw new IllegalArgumentException("PCEPObjectHeader is mandatory.");
152 logger.trace("Attempt to parse object from bytes: {}", ByteArray.bytesToHexString(bytes));
155 * if PCEPObjectIdentifier.getObjectClassFromInt() don't throws
156 * exception and if Map.get() returns null, we know that we can't
157 * recognize OBJ TYPE.
159 final PCEPObjectParser objParserClass = MapOfParsers.getInstance().get(
160 new PCEPObjectIdentifier(PCEPObjectIdentifier.ObjectClass.getFromInt(header.objClass), header.objType));
161 if (objParserClass == null) {
162 logger.debug("Object could not be parsed. Header: {}. Body bytes: {}", header, Arrays.toString(bytes));
163 throw new PCEPDocumentedException("Unrecognized object type: " + header.objType + " for object class: " + header.objClass,
164 PCEPErrors.UNRECOGNIZED_OBJ_TYPE);
166 final PCEPObject obj = objParserClass.parse(bytes, header.processed, header.ignored);
167 logger.trace("Object was parsed. {}", obj);
171 public static List<PCEPObject> parseObjects(final byte[] bytes) throws PCEPDeserializerException, PCEPDocumentedException {
173 final List<PCEPObject> objs = new ArrayList<PCEPObject>();
175 while (bytes.length - offset > 0) {
176 if (bytes.length - offset < PCEPObjectHeader.COMMON_OBJECT_HEADER_LENGTH)
177 throw new PCEPDeserializerException("Too few bytes in passed array. Passed: " + (bytes.length - offset) + " Expected: >= "
178 + PCEPObjectHeader.COMMON_OBJECT_HEADER_LENGTH + ".");
180 final PCEPObjectHeader header = PCEPObjectHeader.parseHeader(Arrays.copyOfRange(bytes, offset, offset
181 + PCEPObjectHeader.COMMON_OBJECT_HEADER_LENGTH));
183 if (bytes.length - offset < header.objLength)
184 throw new PCEPDeserializerException("Too few bytes in passed array. Passed: " + (bytes.length - offset) + " Expected: >= " + header.objLength
187 // copy bytes for deeper parsing
188 final byte[] bytesToPass = ByteArray.subByte(bytes, offset + PCEPObjectHeader.COMMON_OBJECT_HEADER_LENGTH, header.objLength
189 - PCEPObjectHeader.COMMON_OBJECT_HEADER_LENGTH);
191 offset += header.objLength;
193 // if obj is not-supported or unrecognized and p flag si set
194 // adds UnknownObject to list for validation purposes
196 objs.add(PCEPObjectFactory.parse(bytesToPass, header));
197 } catch (final PCEPDocumentedException e) {
198 if (e.getError() == PCEPErrors.UNRECOGNIZED_OBJ_CLASS | e.getError() == PCEPErrors.UNRECOGNIZED_OBJ_TYPE
199 | e.getError() == PCEPErrors.NOT_SUPPORTED_OBJ_CLASS | e.getError() == PCEPErrors.NOT_SUPPORTED_OBJ_TYPE) {
200 objs.add(new UnknownObject(header.processed, header.ignored, e.getError()));
210 public static byte[] put(final List<PCEPObject> objects) {
211 if (objects == null || objects.isEmpty())
212 throw new IllegalArgumentException("List<PCEPObject> is mandatory and can't be empty.");
214 final List<byte[]> listBytes = new ArrayList<byte[]>();
218 for (final PCEPObject obj : objects) {
220 size += bytes.length;
221 listBytes.add(bytes);
224 final byte[] retBytes = new byte[size];
227 for (final byte[] bs : listBytes) {
228 ByteArray.copyWhole(bs, retBytes, offset);
235 private static byte[] put(final PCEPObject obj) {
238 ObjectClass objClass;
241 if (obj instanceof PCEPOpenObject) {
242 objClass = PCEPObjectIdentifier.ObjectClass.OPEN;
243 } else if (obj instanceof PCEPRequestParameterObject) {
244 objClass = PCEPObjectIdentifier.ObjectClass.RP;
245 } else if (obj instanceof PCEPNoPathObject) {
246 objClass = PCEPObjectIdentifier.ObjectClass.NO_PATH;
247 } else if (obj instanceof PCEPRequestedPathBandwidthObject) {
248 objClass = PCEPObjectIdentifier.ObjectClass.BANDWIDTH;
249 } else if (obj instanceof PCEPExistingPathBandwidthObject) {
250 objClass = PCEPObjectIdentifier.ObjectClass.BANDWIDTH;
252 } else if (obj instanceof PCEPMetricObject) {
253 objClass = PCEPObjectIdentifier.ObjectClass.METRIC;
254 } else if (obj instanceof PCEPEndPointsObject<?>) {
255 objClass = PCEPObjectIdentifier.ObjectClass.END_POINTS;
256 if (((PCEPEndPointsObject<?>) obj).getSourceAddress() instanceof IPv6Address) {
258 } else if (!(((PCEPEndPointsObject<?>) obj).getSourceAddress() instanceof IPv4Address))
259 throw new IllegalArgumentException("Unknown instance of Source Address.");
261 } else if (obj instanceof PCEPP2MPEndPointsObject<?>) {
262 objClass = PCEPObjectIdentifier.ObjectClass.END_POINTS;
264 if (((PCEPP2MPEndPointsObject<?>) obj).getSourceAddress() instanceof IPv6Address) {
266 } else if (!(((PCEPP2MPEndPointsObject<?>) obj).getSourceAddress() instanceof IPv4Address))
267 throw new IllegalArgumentException("Unknown instance of Source Address.");
269 } else if (obj instanceof PCEPUnreachedDestinationObject<?>) {
270 objClass = PCEPObjectIdentifier.ObjectClass.UNREACHED_DESTINATION;
271 if (((PCEPUnreachedDestinationObject<?>) obj).getUnreachedDestinations().get(0) instanceof IPv6Address) {
273 } else if (!(((PCEPUnreachedDestinationObject<?>) obj).getUnreachedDestinations().get(0) instanceof IPv4Address))
274 throw new IllegalArgumentException("Unknown instance of Source Address.");
276 } else if (obj instanceof PCEPLspaObject) {
277 objClass = PCEPObjectIdentifier.ObjectClass.LSPA;
278 } else if (obj instanceof PCEPSvecObject) {
279 objClass = PCEPObjectIdentifier.ObjectClass.SVEC;
281 } else if (obj instanceof PCEPNotificationObject) {
282 objClass = PCEPObjectIdentifier.ObjectClass.NOTIFICATION;
283 } else if (obj instanceof PCEPErrorObject) {
284 objClass = PCEPObjectIdentifier.ObjectClass.ERROR;
285 } else if (obj instanceof PCEPCloseObject) {
286 objClass = PCEPObjectIdentifier.ObjectClass.CLOSE;
287 } else if (obj instanceof PCEPLoadBalancingObject) {
288 objClass = PCEPObjectIdentifier.ObjectClass.LOAD_BALANCING;
289 } else if (obj instanceof PCEPLspObject) {
290 objClass = PCEPObjectIdentifier.ObjectClass.LSP;
291 } else if (obj instanceof PCEPExplicitRouteObject) {
292 objClass = PCEPObjectIdentifier.ObjectClass.ERO;
293 } else if (obj instanceof PCEPReportedRouteObject) {
294 objClass = PCEPObjectIdentifier.ObjectClass.RRO;
295 } else if (obj instanceof PCEPIncludeRouteObject) {
296 objClass = PCEPObjectIdentifier.ObjectClass.IRO;
297 } else if (obj instanceof PCEPExcludeRouteObject) {
298 objClass = PCEPObjectIdentifier.ObjectClass.XRO;
299 } else if (obj instanceof PCEPObjectiveFunctionObject) {
300 objClass = PCEPObjectIdentifier.ObjectClass.OBJCETIVE_FUNCTION;
301 } else if (obj instanceof PCEPGlobalConstraintsObject) {
302 objClass = PCEPObjectIdentifier.ObjectClass.GLOBAL_CONSTRAINTS;
303 } else if (obj instanceof PCEPBranchNodeObject) {
304 objClass = PCEPObjectIdentifier.ObjectClass.BRANCH_NODE;
305 if (obj instanceof PCEPNonBranchNodeListObject) {
307 } else if (!(obj instanceof PCEPBranchNodeListObject))
308 throw new IllegalArgumentException("Unknown instance of PCEPBranchNodeObject.");
309 } else if (obj instanceof PCEPSecondaryExplicitRouteObject) {
310 objClass = PCEPObjectIdentifier.ObjectClass.SERO;
311 } else if (obj instanceof PCEPSecondaryRecordRouteObject) {
312 objClass = PCEPObjectIdentifier.ObjectClass.SRRO;
314 throw new IllegalArgumentException("Unknown instance of PCEPObject.");
316 final PCEPObjectParser objParserClass = MapOfParsers.getInstance().get(new PCEPObjectIdentifier(objClass, objType));
317 objBody = objParserClass.put(obj);
319 final byte[] objHeader = PCEPObjectHeader.putHeader(new PCEPObjectHeader(objClass.getIdentifier(), objType, objBody.length
320 + PCEPObjectHeader.COMMON_OBJECT_HEADER_LENGTH, obj.isProcessed(), obj.isIgnored()));
322 assert objBody.length % 4 == 0 : "Wrong length of PCEPObjectBody. Passed object has length: " + objBody.length + " that is not multiple of 4.";
324 final byte[] retBytes = new byte[objHeader.length + objBody.length];
325 ByteArray.copyWhole(objHeader, retBytes, 0);
326 ByteArray.copyWhole(objBody, retBytes, PCEPObjectHeader.OBJ_BODY_OFFSET);