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