baec04d8e54b6a571c31475892b2fc1bd6b02525
[bgpcep.git] / pcep / impl / src / main / java / org / opendaylight / protocol / pcep / impl / message / PCEPReplyMessageParser.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.Optional;
11 import com.google.common.base.Preconditions;
12 import io.netty.buffer.ByteBuf;
13 import io.netty.buffer.Unpooled;
14 import java.util.ArrayList;
15 import java.util.List;
16 import org.opendaylight.protocol.pcep.impl.spi.Util;
17 import org.opendaylight.protocol.pcep.spi.AbstractMessageParser;
18 import org.opendaylight.protocol.pcep.spi.MessageUtil;
19 import org.opendaylight.protocol.pcep.spi.ObjectRegistry;
20 import org.opendaylight.protocol.pcep.spi.PCEPDeserializerException;
21 import org.opendaylight.protocol.pcep.spi.PCEPErrors;
22 import org.opendaylight.protocol.pcep.spi.VendorInformationObjectRegistry;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.message.rev131007.Pcrep;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.message.rev131007.PcrepBuilder;
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.explicit.route.object.Ero;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.include.route.object.Iro;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.lsp.attributes.Metrics;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.lsp.attributes.MetricsBuilder;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.lspa.object.Lspa;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.metric.object.Metric;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.monitoring.metrics.MetricPce;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.monitoring.object.Monitoring;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.of.object.Of;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.pcc.id.req.object.PccIdReq;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.pce.id.object.PceId;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.pcrep.message.PcrepMessageBuilder;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.pcrep.message.pcrep.message.Replies;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.pcrep.message.pcrep.message.RepliesBuilder;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.pcrep.message.pcrep.message.replies.Result;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.pcrep.message.pcrep.message.replies.result.FailureCase;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.pcrep.message.pcrep.message.replies.result.FailureCaseBuilder;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.pcrep.message.pcrep.message.replies.result.SuccessCase;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.pcrep.message.pcrep.message.replies.result.SuccessCaseBuilder;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.pcrep.message.pcrep.message.replies.result.failure._case.NoPath;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.pcrep.message.pcrep.message.replies.result.success._case.SuccessBuilder;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.pcrep.message.pcrep.message.replies.result.success._case.success.Paths;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.pcrep.message.pcrep.message.replies.result.success._case.success.PathsBuilder;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.rp.object.Rp;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.vendor.information.objects.VendorInformationObject;
53
54 /**
55  * Parser for {@link Pcrep}
56  */
57 public class PCEPReplyMessageParser extends AbstractMessageParser {
58
59     public static final int TYPE = 4;
60
61     public PCEPReplyMessageParser(final ObjectRegistry registry, final VendorInformationObjectRegistry viRegistry) {
62         super(registry, viRegistry);
63     }
64
65     @Override
66     public void serializeMessage(final Message message, final ByteBuf out) {
67         Preconditions.checkArgument(message instanceof Pcrep, "Wrong instance of Message. Passed instance of %s. Need Pcrep.", message.getClass());
68         final org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.pcrep.message.PcrepMessage repMsg = ((Pcrep) message).getPcrepMessage();
69         Preconditions.checkArgument(repMsg.getReplies() != null && !repMsg.getReplies().isEmpty(), "Replies cannot be null or empty.");
70         final ByteBuf buffer = Unpooled.buffer();
71         for (final Replies reply : repMsg.getReplies()) {
72             Preconditions.checkArgument(reply.getRp() != null, "Reply must contain RP object.");
73             serializeReply(reply, buffer);
74         }
75         MessageUtil.formatMessage(TYPE, buffer, out);
76     }
77
78     protected void serializeReply(final Replies reply, final ByteBuf buffer) {
79         serializeObject(reply.getRp(), buffer);
80         serializeMonitoring(reply, buffer);
81         serializeVendorInformationObjects(reply.getVendorInformationObject(), buffer);
82         if (reply.getResult() == null) {
83             return;
84         }
85         if (reply.getResult() instanceof FailureCase) {
86             final FailureCase f = ((FailureCase) reply.getResult());
87             serializeFailure(f, buffer);
88             return;
89         }
90         final SuccessCase s = (SuccessCase) reply.getResult();
91         serializeSuccess(s, buffer);
92         serializeMonitoringMetrics(reply, buffer);
93     }
94
95     private void serializeFailure(final FailureCase f, final ByteBuf buffer) {
96         if (f == null) {
97             return;
98         }
99         serializeObject(f.getNoPath(), buffer);
100         serializeObject(f.getLspa(), buffer);
101         serializeObject(f.getBandwidth(), buffer);
102         if (f.getMetrics() != null) {
103             for (final Metrics m : f.getMetrics()) {
104                 serializeObject(m.getMetric(), buffer);
105             }
106         }
107         serializeObject(f.getIro(), buffer);
108     }
109
110     private void serializeSuccess(final SuccessCase s, final ByteBuf buffer) {
111         if (s == null || s.getSuccess() == null) {
112             return;
113         }
114         for (final Paths p : s.getSuccess().getPaths()) {
115             serializeObject(p.getEro(), buffer);
116             serializeObject(p.getLspa(), buffer);
117             serializeObject(p.getOf(), buffer);
118             serializeObject(p.getBandwidth(), buffer);
119             if (p.getMetrics() != null) {
120                 for (final Metrics m : p.getMetrics()) {
121                     serializeObject(m.getMetric(), buffer);
122                 }
123             }
124             serializeObject(p.getIro(), buffer);
125         }
126         serializeVendorInformationObjects(s.getSuccess().getVendorInformationObject(), buffer);
127     }
128
129     private void serializeMonitoring(final Replies reply, final ByteBuf buffer) {
130         serializeObject(reply.getMonitoring(), buffer);
131         serializeObject(reply.getPccIdReq(), buffer);
132     }
133
134     private void serializeMonitoringMetrics(final Replies reply, final ByteBuf buffer) {
135         if (reply.getMetricPce() != null) {
136             for (final MetricPce metricPce : reply.getMetricPce()) {
137                 serializeMetricPce(metricPce, buffer);
138             }
139         }
140     }
141
142     protected void serializeMetricPce(final MetricPce metricPce, final ByteBuf buffer) {
143         Preconditions.checkArgument(metricPce.getPceId() != null, "PCE-ID must be present.");
144         serializeObject(metricPce.getPceId(), buffer);
145         serializeObject(metricPce.getProcTime(), buffer);
146         serializeObject(metricPce.getOverload(), buffer);
147     }
148
149     @Override
150     protected Pcrep validate(final List<Object> objects, final List<Message> errors) throws PCEPDeserializerException {
151         Preconditions.checkArgument(objects != null, "Passed list can't be null.");
152         if (objects.isEmpty()) {
153             throw new PCEPDeserializerException("Pcrep message cannot be empty.");
154         }
155         final List<Replies> replies = new ArrayList<>();
156         while (!objects.isEmpty()) {
157             final Replies r = this.getValidReply(objects, errors);
158             if (r != null) {
159                 replies.add(r);
160             }
161         }
162         if (!objects.isEmpty()) {
163             throw new PCEPDeserializerException("Unprocessed Objects: " + objects);
164         }
165         return new PcrepBuilder().setPcrepMessage(new PcrepMessageBuilder().setReplies(replies).build()).build();
166     }
167
168     protected Replies getValidReply(final List<Object> objects, final List<Message> errors) throws PCEPDeserializerException {
169         if (!(objects.get(0) instanceof Rp)) {
170             errors.add(createErrorMsg(PCEPErrors.RP_MISSING, Optional.<Rp>absent()));
171             return null;
172         }
173         final Rp rp = (Rp) objects.get(0);
174         objects.remove(0);
175         final RepliesBuilder repliesBuilder = new RepliesBuilder();
176         if (!objects.isEmpty() && objects.get(0) instanceof Monitoring) {
177             repliesBuilder.setMonitoring((Monitoring) objects.get(0));
178             objects.remove(0);
179         }
180         if (!objects.isEmpty() && objects.get(0) instanceof PccIdReq) {
181             repliesBuilder.setPccIdReq((PccIdReq) objects.get(0));
182             objects.remove(0);
183         }
184         final List<VendorInformationObject> vendorInfo = addVendorInformationObjects(objects);
185         Result res = null;
186         if (!objects.isEmpty()) {
187             if (objects.get(0) instanceof NoPath) {
188                 res = handleNoPath((NoPath) objects.get(0), objects);
189             } else if (objects.get(0) instanceof Ero) {
190                 res = handleEro((Ero) objects.get(0), objects);
191             }
192         }
193         final List<MetricPce> metricPceList = new ArrayList<>();
194         if (!objects.isEmpty() && objects.get(0) instanceof PceId) {
195             while (!objects.isEmpty()) {
196                 metricPceList.add(Util.validateMonitoringMetrics(objects));
197             }
198         }
199         if (!vendorInfo.isEmpty()) {
200             repliesBuilder.setVendorInformationObject(vendorInfo);
201         }
202         if (!metricPceList.isEmpty()) {
203             repliesBuilder.setMetricPce(metricPceList);
204         }
205         return repliesBuilder.setRp(rp).setResult(res).build();
206     }
207
208     private Result handleNoPath(final NoPath noPath, final List<Object> objects) {
209         objects.remove(0);
210         final FailureCaseBuilder builder = new FailureCaseBuilder();
211         builder.setNoPath(noPath);
212         while (!objects.isEmpty() && !(objects.get(0) instanceof PceId)) {
213             this.parseAttributes(builder, objects);
214         }
215         return builder.build();
216     }
217
218     private Result handleEro(final Ero ero, final List<Object> objects) {
219         objects.remove(0);
220         final SuccessBuilder builder = new SuccessBuilder();
221         final List<Paths> paths = new ArrayList<>();
222         final PathsBuilder pBuilder = new PathsBuilder();
223         pBuilder.setEro(ero);
224         while (!objects.isEmpty() && !(objects.get(0) instanceof PceId)) {
225             final List<VendorInformationObject> vendorInfoObjects = addVendorInformationObjects(objects);
226             if (!vendorInfoObjects.isEmpty()) {
227                 builder.setVendorInformationObject(vendorInfoObjects);
228             }
229             this.parsePath(pBuilder, objects);
230             paths.add(pBuilder.build());
231         }
232         builder.setPaths(paths);
233         return new SuccessCaseBuilder().setSuccess(builder.build()).build();
234     }
235
236     protected void parseAttributes(final FailureCaseBuilder builder, final List<Object> objects) {
237         final List<Metrics> pathMetrics = new ArrayList<>();
238
239         Object obj;
240         State state = State.INIT;
241         while (!objects.isEmpty() && !state.equals(State.END)) {
242             obj = objects.get(0);
243             state = insertObject(state, obj, builder, pathMetrics);
244             if (!state.equals(State.END)) {
245                 objects.remove(0);
246             }
247         }
248         if (!pathMetrics.isEmpty()) {
249             builder.setMetrics(pathMetrics);
250         }
251     }
252
253     private State insertObject(final State state, final Object obj, final FailureCaseBuilder builder, final List<Metrics> pathMetrics) {
254         switch (state) {
255         case INIT:
256             if (obj instanceof Lspa) {
257                 builder.setLspa((Lspa) obj);
258                 return State.LSPA_IN;
259             }
260         case LSPA_IN:
261             if (obj instanceof Bandwidth) {
262                 builder.setBandwidth((Bandwidth) obj);
263                 return State.BANDWIDTH_IN;
264             }
265         case BANDWIDTH_IN:
266             if (obj instanceof Metric) {
267                 pathMetrics.add(new MetricsBuilder().setMetric((Metric) obj).build());
268                 return State.BANDWIDTH_IN;
269             }
270         case METRIC_IN:
271             if (obj instanceof Iro) {
272                 builder.setIro((Iro) obj);
273                 return State.IRO_IN;
274             }
275         case IRO_IN:
276         case END:
277             return State.END;
278         default:
279             return state;
280         }
281     }
282
283     protected void parsePath(final PathsBuilder builder, final List<Object> objects) {
284         final List<Metrics> pathMetrics = new ArrayList<>();
285
286         Object obj;
287         State state = State.INIT;
288         while (!objects.isEmpty() && !state.equals(State.END)) {
289             obj = objects.get(0);
290             state = insertObject(state, obj, builder, pathMetrics);
291             if (!state.equals(State.END)) {
292                 objects.remove(0);
293             }
294         }
295         if (!pathMetrics.isEmpty()) {
296             builder.setMetrics(pathMetrics);
297         }
298     }
299
300     private State insertObject(final State state, final Object obj, final PathsBuilder builder, final List<Metrics> pathMetrics) {
301         switch (state) {
302         case INIT:
303             if (obj instanceof Lspa) {
304                 builder.setLspa((Lspa) obj);
305                 return State.LSPA_IN;
306             }
307         case LSPA_IN:
308             if (obj instanceof Of) {
309                 builder.setOf((Of) obj);
310                 return State.OF_IN;
311             }
312         case OF_IN:
313             if (obj instanceof Bandwidth) {
314                 builder.setBandwidth((Bandwidth) obj);
315                 return State.BANDWIDTH_IN;
316             }
317         case BANDWIDTH_IN:
318             if (obj instanceof Metric) {
319                 pathMetrics.add(new MetricsBuilder().setMetric((Metric) obj).build());
320                 return State.BANDWIDTH_IN;
321             }
322         case METRIC_IN:
323             if (obj instanceof Iro) {
324                 builder.setIro((Iro) obj);
325                 return State.IRO_IN;
326             }
327         case IRO_IN:
328         case END:
329             return State.END;
330         default:
331             return state;
332         }
333     }
334
335     private enum State {
336         INIT, LSPA_IN, OF_IN, BANDWIDTH_IN, METRIC_IN, IRO_IN, END
337     }
338 }