Add new revision for pcep types model
[bgpcep.git] / pcep / base-parser / src / main / java / org / opendaylight / protocol / pcep / parser / message / PCEPRequestMessageParser.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.parser.message;
9
10 import com.google.common.base.Preconditions;
11 import io.netty.buffer.ByteBuf;
12 import io.netty.buffer.Unpooled;
13 import java.util.ArrayList;
14 import java.util.List;
15 import java.util.Optional;
16 import org.opendaylight.protocol.pcep.spi.AbstractMessageParser;
17 import org.opendaylight.protocol.pcep.spi.MessageUtil;
18 import org.opendaylight.protocol.pcep.spi.ObjectRegistry;
19 import org.opendaylight.protocol.pcep.spi.PCEPDeserializerException;
20 import org.opendaylight.protocol.pcep.spi.PCEPErrors;
21 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.message.rev181109.Pcreq;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.message.rev181109.PcreqBuilder;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.Message;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.Object;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.bandwidth.object.Bandwidth;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.classtype.object.ClassType;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.endpoints.object.EndpointsObj;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.exclude.route.object.Xro;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.gc.object.Gc;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.include.route.object.Iro;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.load.balancing.object.LoadBalancing;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.lsp.attributes.Metrics;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.lsp.attributes.MetricsBuilder;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.lspa.object.Lspa;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.metric.object.Metric;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.monitoring.object.Monitoring;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.of.object.Of;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.path.key.object.PathKey;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.pcc.id.req.object.PccIdReq;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.pce.id.object.PceId;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.pcreq.message.PcreqMessage;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.pcreq.message.PcreqMessageBuilder;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.pcreq.message.pcreq.message.MonitoringRequest;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.pcreq.message.pcreq.message.MonitoringRequestBuilder;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.pcreq.message.pcreq.message.Requests;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.pcreq.message.pcreq.message.RequestsBuilder;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.pcreq.message.pcreq.message.Svec;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.pcreq.message.pcreq.message.SvecBuilder;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.pcreq.message.pcreq.message.monitoring.request.PceIdList;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.pcreq.message.pcreq.message.monitoring.request.PceIdListBuilder;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.pcreq.message.pcreq.message.requests.PathKeyExpansionBuilder;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.pcreq.message.pcreq.message.requests.SegmentComputation;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.pcreq.message.pcreq.message.requests.SegmentComputationBuilder;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.pcreq.message.pcreq.message.requests.segment.computation.P2p;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.pcreq.message.pcreq.message.requests.segment.computation.P2pBuilder;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.pcreq.message.pcreq.message.requests.segment.computation.p2p.ReportedRoute;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.reported.route.object.Rro;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.rp.object.Rp;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.vendor.information.objects.VendorInformationObject;
60
61 /**
62  * Parser for {@link Pcreq}
63  */
64 public class PCEPRequestMessageParser extends AbstractMessageParser {
65
66     public static final int TYPE = 3;
67
68     public PCEPRequestMessageParser(final ObjectRegistry registry) {
69         super(registry);
70     }
71
72     @Override
73     public void serializeMessage(final Message message, final ByteBuf out) {
74         Preconditions.checkArgument(message instanceof Pcreq, "Wrong instance of Message. Passed instance of %s. Need Pcreq.", message.getClass());
75         final PcreqMessage msg = ((Pcreq) message).getPcreqMessage();
76         Preconditions.checkArgument(msg.getRequests() != null && !msg.getRequests().isEmpty(), "Requests cannot be null or empty.");
77         final ByteBuf buffer = Unpooled.buffer();
78         if (msg.getMonitoringRequest() != null) {
79             serializeMonitoringRequest(msg.getMonitoringRequest(), buffer);
80         }
81         if (msg.getSvec() != null) {
82             serializeSvec(msg, buffer);
83         }
84         serializeRequest(msg, buffer);
85         MessageUtil.formatMessage(TYPE, buffer, out);
86     }
87
88     protected void serializeRequest(final PcreqMessage msg, final ByteBuf buffer) {
89         for (final Requests req : msg.getRequests()) {
90             serializeObject(req.getRp(), buffer);
91             serializeVendorInformationObjects(req.getVendorInformationObject(), buffer);
92             if (req.getPathKeyExpansion() != null) {
93                 serializeObject(req.getPathKeyExpansion().getPathKey(), buffer);
94             }
95             if (req.getSegmentComputation() != null) {
96                 final SegmentComputation sc = req.getSegmentComputation();
97                 if (sc.getP2p() != null) {
98                     serializeP2P(buffer, sc.getP2p());
99                 }
100             }
101         }
102     }
103
104     protected void serializeSvec(final PcreqMessage msg, final ByteBuf buffer) {
105         for (final Svec s : msg.getSvec()) {
106             serializeObject(s.getSvec(), buffer);
107             serializeObject(s.getOf(), buffer);
108             serializeObject(s.getGc(), buffer);
109             serializeObject(s.getXro(), buffer);
110             if (s.getMetric() != null) {
111                 for (final org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.pcreq.message.pcreq.message.svec.Metric m : s.getMetric()) {
112                     serializeObject(m.getMetric(), buffer);
113                 }
114             }
115             serializeVendorInformationObjects(s.getVendorInformationObject(), buffer);
116         }
117     }
118
119     protected void serializeP2P(final ByteBuf buffer, final P2p p2p) {
120         serializeObject(p2p.getEndpointsObj(), buffer);
121         serializeVendorInformationObjects(p2p.getVendorInformationObject(), buffer);
122         if (p2p.getReportedRoute() != null) {
123             final ReportedRoute rr = p2p.getReportedRoute();
124             if (rr != null) {
125                 serializeObject(rr.getRro(), buffer);
126                 serializeObject(rr.getReoptimizationBandwidth(), buffer);
127             }
128         }
129         serializeObject(p2p.getLoadBalancing(), buffer);
130         serializeObject(p2p.getLspa(), buffer);
131         serializeObject(p2p.getBandwidth(), buffer);
132         if (p2p.getMetrics() != null) {
133             for (final Metrics m : p2p.getMetrics()) {
134                 serializeObject(m.getMetric(), buffer);
135             }
136         }
137         serializeObject(p2p.getIro(), buffer);
138         serializeObject(p2p.getRro(), buffer);
139         serializeObject(p2p.getXro(), buffer);
140         serializeObject(p2p.getOf(), buffer);
141         serializeObject(p2p.getClassType(), buffer);
142     }
143
144     protected void serializeMonitoringRequest(final MonitoringRequest monReq, final ByteBuf out) {
145         serializeObject(monReq.getMonitoring(), out);
146         serializeObject(monReq.getPccIdReq(), out);
147         if (monReq.getPceIdList() != null) {
148             for (final PceIdList pceId : monReq.getPceIdList()) {
149                 serializeObject(pceId.getPceId(), out);
150             }
151         }
152     }
153
154     @Override
155     protected Message validate(final List<Object> objects, final List<Message> errors) throws PCEPDeserializerException {
156         Preconditions.checkArgument(objects != null, "Passed list can't be null.");
157         if (objects.isEmpty()) {
158             throw new PCEPDeserializerException("Pcrep message cannot be empty.");
159         }
160         final PcreqMessageBuilder mBuilder = new PcreqMessageBuilder();
161         mBuilder.setMonitoringRequest(getMonitoring(objects));
162         final List<Svec> svecs = getSvecs(objects);
163         if (!svecs.isEmpty()) {
164             mBuilder.setSvec(svecs);
165         }
166         final List<Requests> requests = getRequests(objects, errors);
167         if (requests != null) {
168             mBuilder.setRequests(requests);
169         } else {
170             errors.add(createErrorMsg(PCEPErrors.RP_MISSING, Optional.empty()));
171         }
172         if (!objects.isEmpty()) {
173             throw new PCEPDeserializerException("Unprocessed Objects: " + objects);
174         }
175         return new PcreqBuilder().setPcreqMessage(mBuilder.build()).build();
176     }
177
178     protected List<Svec> getSvecs(final List<Object> objects) {
179         final List<Svec> svecList = new ArrayList<>();
180         while (!objects.isEmpty()) {
181             final SvecBuilder sBuilder = new SvecBuilder();
182             final Svec svecComp = getValidSvec(sBuilder, objects);
183             if (svecComp == null) {
184                 break;
185             }
186             svecList.add(svecComp);
187         }
188         return svecList;
189     }
190
191     protected List<Requests> getRequests(final List<Object> objects, final List<Message> errors) {
192         final List<Requests> requests = new ArrayList<>();
193         while (!objects.isEmpty()) {
194             final RequestsBuilder rBuilder = new RequestsBuilder();
195             Rp rpObj = null;
196             if (!(objects.get(0) instanceof Rp)) {
197                 // if RP obj is missing return error only
198                 errors.add(createErrorMsg(PCEPErrors.RP_MISSING, Optional.empty()));
199                 return null;
200             }
201             rpObj = (Rp) objects.get(0);
202             objects.remove(0);
203             if (!rpObj.isProcessingRule()) {
204                 errors.add(createErrorMsg(PCEPErrors.P_FLAG_NOT_SET, Optional.empty()));
205             } else {
206                 rBuilder.setRp(rpObj);
207             }
208             final List<VendorInformationObject> vendorInfo = addVendorInformationObjects(objects);
209             if (!vendorInfo.isEmpty()) {
210                 rBuilder.setVendorInformationObject(vendorInfo);
211             }
212             // expansion
213             if (rpObj.isPathKey() && objects.get(0) instanceof PathKey) {
214                 rBuilder.setPathKeyExpansion(new PathKeyExpansionBuilder().setPathKey((PathKey) objects.get(0)).build());
215             }
216
217             final P2pBuilder p2pBuilder = new P2pBuilder();
218
219             if (!objects.isEmpty() && objects.get(0) instanceof EndpointsObj) {
220                 final EndpointsObj ep = (EndpointsObj) objects.get(0);
221                 objects.remove(0);
222                 if (!ep.isProcessingRule()) {
223                     errors.add(createErrorMsg(PCEPErrors.P_FLAG_NOT_SET, Optional.of(rpObj)));
224                 } else {
225                     p2pBuilder.setEndpointsObj(ep);
226                 }
227             } else {
228                 errors.add(createErrorMsg(PCEPErrors.END_POINTS_MISSING, Optional.of(rpObj)));
229                 return null;
230             }
231             // p2p
232             if (!rpObj.isP2mp()) {
233                 final SegmentComputation segm = getSegmentComputation(p2pBuilder, objects, errors, rpObj);
234                 if (segm != null) {
235                     rBuilder.setSegmentComputation(segm);
236                 }
237             }
238             requests.add(rBuilder.build());
239         }
240         return requests;
241     }
242
243     protected SegmentComputation getSegmentComputation(final P2pBuilder builder, final List<Object> objects, final List<Message> errors,
244             final Rp rp) {
245         final List<Metrics> metrics = new ArrayList<>();
246         final List<VendorInformationObject> viObjects = new ArrayList<>();
247
248         State state = State.INIT;
249         while (!objects.isEmpty() && state != State.END) {
250             state = insertObject(state, objects, viObjects, builder, metrics, errors, rp);
251             if (!state.equals(State.END)) {
252                 objects.remove(0);
253             }
254         }
255         if (!metrics.isEmpty()) {
256             builder.setMetrics(metrics);
257         }
258         if (!viObjects.isEmpty()) {
259             builder.setVendorInformationObject(viObjects);
260         }
261
262         if (rp.isReoptimization()
263                 && builder.getBandwidth() != null
264                 && !builder.getReportedRoute().getReoptimizationBandwidth().getBandwidth().equals(
265                         new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.network.concepts.rev131125.Bandwidth(new byte[] { 0 }))
266                 && builder.getReportedRoute().getRro() == null) {
267             errors.add(createErrorMsg(PCEPErrors.RRO_MISSING, Optional.of(rp)));
268             return null;
269         }
270         return new SegmentComputationBuilder().setP2p(builder.build()).build();
271     }
272
273     private static State insertObject(final State state, final List<Object> objects,
274             final List<VendorInformationObject> viObjects, final P2pBuilder builder, final List<Metrics> metrics,
275             final List<Message> errors, final Rp rp) {
276         final Object obj = objects.get(0);
277         switch (state) {
278         case INIT:
279             if (obj instanceof Rro) {
280                 builder.setRro((Rro) obj);
281                 objects.remove(0);
282                 final Object nextObj = objects.get(0);
283                 if (nextObj instanceof org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types
284                         .rev181109.reoptimization.bandwidth.object.ReoptimizationBandwidth) {
285                     builder.setReoptimizationBandwidth((org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns
286                             .yang.pcep.types.rev181109.reoptimization.bandwidth.object
287                             .ReoptimizationBandwidth) nextObj);
288                 }
289                 return State.REPORTED_IN;
290             }
291         case REPORTED_IN:
292             if (obj instanceof VendorInformationObject) {
293                 viObjects.add((VendorInformationObject) obj);
294                 return State.REPORTED_IN;
295             }
296         case VENDOR_INFO_LIST:
297             if (obj instanceof LoadBalancing) {
298                 builder.setLoadBalancing((LoadBalancing) obj);
299                 return State.LOAD_BIN;
300             }
301         case LOAD_BIN:
302             if (obj instanceof Lspa) {
303                 builder.setLspa((Lspa) obj);
304                 return State.LSPA_IN;
305             }
306         case LSPA_IN:
307             if (obj instanceof Bandwidth) {
308                 builder.setBandwidth((Bandwidth) obj);
309                 return State.BANDWIDTH_IN;
310             }
311         case BANDWIDTH_IN:
312             if (obj instanceof Metric) {
313                 metrics.add(new MetricsBuilder().setMetric((Metric) obj).build());
314                 return State.BANDWIDTH_IN;
315             }
316         case METRIC_IN:
317             if (obj instanceof Iro) {
318                 builder.setIro((Iro) obj);
319                 return State.IRO_IN;
320             }
321         case IRO_IN:
322             if (obj instanceof Rro) {
323                 builder.setRro((Rro) obj);
324                 return State.RRO_IN;
325             }
326         case RRO_IN:
327             if (obj instanceof Xro) {
328                 builder.setXro((Xro) obj);
329                 return State.XRO_IN;
330             }
331         case XRO_IN:
332             if (obj instanceof Of) {
333                 builder.setOf((Of) obj);
334                 return State.OF_IN;
335             }
336         case OF_IN:
337             if (obj instanceof ClassType) {
338                 final ClassType classType = (ClassType) obj;
339                 if (!classType.isProcessingRule()) {
340                     errors.add(createErrorMsg(PCEPErrors.P_FLAG_NOT_SET, Optional.of(rp)));
341                 } else {
342                     builder.setClassType(classType);
343                 }
344                 return State.CT_IN;
345             }
346         case CT_IN:
347         case END:
348             return State.END;
349         default:
350             return state;
351         }
352     }
353
354     private enum State {
355         INIT, REPORTED_IN, VENDOR_INFO_LIST, LOAD_BIN, LSPA_IN, BANDWIDTH_IN, METRIC_IN, IRO_IN, RRO_IN, XRO_IN, OF_IN, CT_IN, END
356     }
357
358     private static Svec getValidSvec(final SvecBuilder builder, final List<Object> objects) {
359         Preconditions.checkArgument(objects != null && !objects.isEmpty(), "Passed list can't be null or empty.");
360
361         if (objects.get(0) instanceof org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.svec.object.Svec) {
362             builder.setSvec((org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.svec.object.Svec) objects.get(0));
363             objects.remove(0);
364         } else {
365             return null;
366         }
367
368         final List<Metrics> metrics = new ArrayList<>();
369         final List<VendorInformationObject> viObjects = new ArrayList<>();
370
371         Object obj = null;
372         SvecState state = SvecState.INIT;
373         while (!objects.isEmpty() && !state.equals(SvecState.END)) {
374             obj = objects.get(0);
375             state = insertObject(state, obj, builder, metrics, viObjects);
376             if (!state.equals(SvecState.END)) {
377                 objects.remove(0);
378             }
379         }
380         if (!viObjects.isEmpty()) {
381             builder.setVendorInformationObject(viObjects);
382         }
383         return builder.build();
384     }
385
386     private static SvecState insertObject(final SvecState state, final Object obj, final SvecBuilder builder,
387             final List<Metrics> metrics, final List<VendorInformationObject> viObjects) {
388         switch (state) {
389         case INIT:
390             if (obj instanceof Of) {
391                 builder.setOf((Of) obj);
392                 return SvecState.OF_IN;
393             }
394         case OF_IN:
395             if (obj instanceof Gc) {
396                 builder.setGc((Gc) obj);
397                 return SvecState.GC_IN;
398             }
399         case GC_IN:
400             if (obj instanceof Xro) {
401                 builder.setXro((Xro) obj);
402                 return SvecState.XRO_IN;
403             }
404         case XRO_IN:
405             if (obj instanceof Metric) {
406                 metrics.add(new MetricsBuilder().setMetric((Metric) obj).build());
407                 return SvecState.XRO_IN;
408             }
409         case METRIC_IN:
410             if (obj instanceof VendorInformationObject) {
411                 viObjects.add((VendorInformationObject) obj);
412                 return SvecState.METRIC_IN;
413             }
414         case VENDOR_INFO:
415         case END:
416             return SvecState.END;
417         default:
418             return state;
419         }
420     }
421
422     private enum SvecState {
423         INIT, OF_IN, GC_IN, XRO_IN, METRIC_IN, VENDOR_INFO, END
424     }
425
426     protected MonitoringRequest getMonitoring(final List<Object> objects) {
427         final MonitoringRequestBuilder builder = new MonitoringRequestBuilder();
428         if (!objects.isEmpty() && objects.get(0) instanceof Monitoring) {
429             builder.setMonitoring((Monitoring) objects.get(0));
430             objects.remove(0);
431         } else {
432             return null;
433         }
434         if (!objects.isEmpty() && objects.get(0) instanceof PccIdReq) {
435             builder.setPccIdReq((PccIdReq) objects.get(0));
436             objects.remove(0);
437         }
438         final List<PceIdList> pceIdList = new ArrayList<>();
439         while(!objects.isEmpty() && objects.get(0) instanceof PceId) {
440             pceIdList.add(new PceIdListBuilder().setPceId((PceId) objects.get(0)).build());
441             objects.remove(0);
442         }
443         if (!pceIdList.isEmpty()) {
444             builder.setPceIdList(pceIdList);
445         }
446         return builder.build();
447     }
448 }