BUG-5731: Send Error Message if LSP-IDENTIFIERS TLV is missing
[bgpcep.git] / pcep / ietf-stateful07 / src / main / java / org / opendaylight / protocol / pcep / ietf / stateful07 / Stateful07PCReportMessageParser.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.ietf.stateful07;
9
10 import com.google.common.base.Optional;
11 import com.google.common.base.Preconditions;
12 import com.google.common.collect.Lists;
13 import io.netty.buffer.ByteBuf;
14 import io.netty.buffer.Unpooled;
15 import java.util.List;
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.protocol.pcep.spi.PSTUtil;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.Pcrpt;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.PcrptBuilder;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.lsp.object.Lsp;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.pcrpt.message.PcrptMessageBuilder;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.pcrpt.message.pcrpt.message.Reports;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.pcrpt.message.pcrpt.message.ReportsBuilder;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.pcrpt.message.pcrpt.message.reports.Path;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.pcrpt.message.pcrpt.message.reports.PathBuilder;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.srp.object.Srp;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.srp.object.srp.Tlvs;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.Message;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.Object;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.bandwidth.object.Bandwidth;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.explicit.route.object.Ero;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.include.route.object.Iro;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.lsp.attributes.Metrics;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.lsp.attributes.MetricsBuilder;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.lspa.object.Lspa;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.metric.object.Metric;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.reported.route.object.Rro;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.rp.object.Rp;
43
44 /**
45  * Parser for {@link Pcrpt}
46  */
47 public class Stateful07PCReportMessageParser extends AbstractMessageParser {
48
49     public static final int TYPE = 10;
50
51     public Stateful07PCReportMessageParser(final ObjectRegistry registry) {
52         super(registry);
53     }
54
55     @Override
56     public void serializeMessage(final Message message, final ByteBuf out) {
57         Preconditions.checkArgument(message instanceof Pcrpt, "Wrong instance of Message. Passed instance of %s. Need Pcrpt.", message.getClass());
58         final Pcrpt msg = (Pcrpt) message;
59         final List<Reports> reports = msg.getPcrptMessage().getReports();
60         final ByteBuf buffer = Unpooled.buffer();
61         for (final Reports report : reports) {
62             serializeReport(report, buffer);
63         }
64         MessageUtil.formatMessage(TYPE, buffer, out);
65     }
66
67     protected void serializeReport(final Reports report, final ByteBuf buffer) {
68         if (report.getSrp() != null) {
69             serializeObject(report.getSrp(), buffer);
70         }
71         serializeObject(report.getLsp(), buffer);
72         final Path p = report.getPath();
73         if (p != null) {
74             serializeObject(p.getEro(), buffer);
75             serializeObject(p.getLspa(), buffer);
76             serializeObject(p.getBandwidth(), buffer);
77             if (p.getMetrics() != null) {
78                 for (final Metrics m : p.getMetrics()) {
79                     serializeObject(m.getMetric(), buffer);
80                 }
81             }
82             serializeObject(p.getIro(), buffer);
83             serializeObject(p.getRro(), buffer);
84         }
85     }
86
87     @Override
88     public Message validate(final List<Object> objects, final List<Message> errors) throws PCEPDeserializerException {
89         Preconditions.checkArgument(objects != null, "Passed list can't be null.");
90         if (objects.isEmpty()) {
91             throw new PCEPDeserializerException("Pcrpt message cannot be empty.");
92         }
93
94         final List<Reports> reports = Lists.newArrayList();
95
96         while (!objects.isEmpty()) {
97             final Reports report = getValidReports(objects, errors);
98             if (report != null) {
99                 reports.add(report);
100             }
101         }
102         return new PcrptBuilder().setPcrptMessage(new PcrptMessageBuilder().setReports(reports).build()).build();
103     }
104
105     protected Reports getValidReports(final List<Object> objects, final List<Message> errors) {
106         boolean isValid = true;
107         final ReportsBuilder builder = new ReportsBuilder();
108         boolean lspViaSR = false;
109         if (objects.get(0) instanceof Srp) {
110             final Srp srp = (Srp) objects.get(0);
111             final Tlvs tlvs = srp.getTlvs();
112             if (tlvs != null) {
113                 lspViaSR = PSTUtil.isDefaultPST(tlvs.getPathSetupType());
114             }
115             builder.setSrp(srp);
116             objects.remove(0);
117         }
118
119         if (objects.get(0) instanceof Lsp) {
120             final Lsp lsp = (Lsp) objects.get(0);
121             if(!lspViaSR && lsp.getTlvs().getLspIdentifiers() == null && lsp.getPlspId().getValue() != 0) {
122                 errors.add(createErrorMsg(PCEPErrors.LSP_IDENTIFIERS_TLV_MISSING, Optional.<Rp>absent()));
123                 isValid = false;
124             } else {
125                 builder.setLsp(lsp);
126                 objects.remove(0);
127             }
128         } else {
129             errors.add(createErrorMsg(PCEPErrors.LSP_MISSING, Optional.<Rp>absent()));
130             isValid = false;
131         }
132         if (!objects.isEmpty()) {
133             final PathBuilder pBuilder = new PathBuilder();
134             if (objects.get(0) instanceof Ero) {
135                 pBuilder.setEro((Ero) objects.get(0));
136                 objects.remove(0);
137             } else {
138                 errors.add(createErrorMsg(PCEPErrors.ERO_MISSING, Optional.<Rp>absent()));
139                 isValid = false;
140             }
141             parsePath(objects, pBuilder);
142             builder.setPath(pBuilder.build());
143         }
144         if(isValid) {
145             return builder.build();
146         }
147         return null;
148     }
149
150     private void parsePath(final List<Object> objects, final PathBuilder builder) {
151         final List<Metrics> pathMetrics = Lists.newArrayList();
152         Object obj;
153         State state = State.INIT;
154         while (!objects.isEmpty() && !state.equals(State.END)) {
155             obj = objects.get(0);
156             state = insertObject(state, obj, builder, pathMetrics);
157             if (!state.equals(State.END)) {
158                 objects.remove(0);
159             }
160         }
161         if (!pathMetrics.isEmpty()) {
162             builder.setMetrics(pathMetrics);
163         }
164     }
165
166     private State insertObject(final State state, final Object obj, final PathBuilder builder, final List<Metrics> pathMetrics) {
167         switch (state) {
168         case INIT:
169             if (obj instanceof Lspa) {
170                 builder.setLspa((Lspa) obj);
171                 return State.LSPA_IN;
172             }
173         case LSPA_IN:
174             if (obj instanceof Bandwidth) {
175                 builder.setBandwidth((Bandwidth) obj);
176                 return State.BANDWIDTH_IN;
177             }
178         case BANDWIDTH_IN:
179             if (obj instanceof Metric) {
180                 pathMetrics.add(new MetricsBuilder().setMetric((Metric) obj).build());
181                 return State.BANDWIDTH_IN;
182             }
183         case METRIC_IN:
184             if (obj instanceof Iro) {
185                 builder.setIro((Iro) obj);
186                 return State.IRO_IN;
187             }
188         case IRO_IN:
189             if (obj instanceof Rro) {
190                 builder.setRro((Rro) obj);
191                 return State.RRO_IN;
192             }
193         case RRO_IN:
194         case END:
195             return State.END;
196         default:
197             return state;
198         }
199     }
200
201     private enum State {
202         INIT, LSPA_IN, BANDWIDTH_IN, METRIC_IN, IRO_IN, RRO_IN, END
203     }
204 }