26e48dbd7d52ab65d6867148cb0c1aaacbe8fd45
[onosfw.git] /
1 /*
2  * Copyright 2015 Open Networking Laboratory
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 package org.onosproject.pcepio.protocol.ver1;
18
19 import java.util.LinkedList;
20 import java.util.ListIterator;
21
22 import org.jboss.netty.buffer.ChannelBuffer;
23 import org.onosproject.pcepio.exceptions.PcepParseException;
24 import org.onosproject.pcepio.protocol.PcepLspObject;
25 import org.onosproject.pcepio.protocol.PcepMessageReader;
26 import org.onosproject.pcepio.protocol.PcepMessageWriter;
27 import org.onosproject.pcepio.protocol.PcepReportMsg;
28 import org.onosproject.pcepio.protocol.PcepSrpObject;
29 import org.onosproject.pcepio.protocol.PcepStateReport;
30 import org.onosproject.pcepio.protocol.PcepType;
31 import org.onosproject.pcepio.protocol.PcepVersion;
32 import org.onosproject.pcepio.types.PcepObjectHeader;
33 import org.slf4j.Logger;
34 import org.slf4j.LoggerFactory;
35
36 import com.google.common.base.MoreObjects;
37
38 /**
39  * Provides PCEP report message.
40  */
41 class PcepReportMsgVer1 implements PcepReportMsg {
42
43     // Pcep version: 1
44
45     /*
46      * The format of the PCRpt message is as follows:
47      *   <PCRpt Message>        ::= <Common Header>
48      *                              <state-report-list>
49      *Where:
50      *   <state-report-list>    ::= <state-report>[<state-report-list>]
51      *   <state-report>         ::= [<SRP>]
52      *                              <LSP>
53      *                              <path>
54      * Where:
55      *   <path>                 ::= <ERO><attribute-list>[<RRO>]
56      *   Where:
57      *   <attribute-list> is defined in [RFC5440] and extended by PCEP extensions.
58      *    where:
59      *    <attribute-list>      ::=[<LSPA>]
60      *                             [<BANDWIDTH>]
61      *                             [<metric-list>]
62      *                             [<IRO>]
63      *    <metric-list>       ::=<METRIC>[<metric-list>]
64      */
65     protected static final Logger log = LoggerFactory.getLogger(PcepReportMsgVer1.class);
66
67     public static final byte PACKET_VERSION = 1;
68     //PACKET_MINIMUM_LENGTH = CommonHeaderLen(4)+LspObjMinLen(8)+EroObjMinLen(12)
69     public static final int PACKET_MINIMUM_LENGTH = 24;
70     public static final PcepType MSG_TYPE = PcepType.REPORT;
71     public static final byte REPORT_OBJ_TYPE = 1;
72     //Optional TLV
73     private LinkedList<PcepStateReport> llStateReportList;
74
75     public static final PcepReportMsgVer1.Reader READER = new Reader();
76
77     /**
78      * Reader class for reading PCEP report message from channel buffer.
79      */
80     static class Reader implements PcepMessageReader<PcepReportMsg> {
81
82         LinkedList<PcepStateReport> llStateReportList;
83
84         @Override
85         public PcepReportMsg readFrom(ChannelBuffer cb) throws PcepParseException {
86
87             if (cb.readableBytes() < PACKET_MINIMUM_LENGTH) {
88                 throw new PcepParseException("Received packet size " + cb.readableBytes()
89                         + " is less than the expected size: " + PACKET_MINIMUM_LENGTH);
90             }
91             llStateReportList = new LinkedList<>();
92             byte version = cb.readByte();
93             version = (byte) (version >> PcepMessageVer1.SHIFT_FLAG);
94
95             if (version != PACKET_VERSION) {
96                 throw new PcepParseException(" Invalid version: " + version);
97             }
98
99             byte type = cb.readByte();
100
101             if (type != MSG_TYPE.getType()) {
102                 throw new PcepParseException("Unexpected type: " + type);
103             }
104
105             short length = cb.readShort();
106
107             if (length < PACKET_MINIMUM_LENGTH) {
108                 throw new PcepParseException("Wrong length. Expected to be >= " + PACKET_MINIMUM_LENGTH + ", was: "
109                         + length);
110             }
111             // parse state report list
112             parseStateReportList(cb);
113             return new PcepReportMsgVer1(llStateReportList);
114         }
115
116         // Parse State Report list
117         public void parseStateReportList(ChannelBuffer cb) throws PcepParseException {
118
119             /*
120                                 <state-report-list>
121             Where:
122                     <state-report-list>     ::= <state-report>[<state-report-list>]
123                     <state-report>          ::=  [<SRP>]
124                                                   <LSP>
125                                                   <path>
126             Where:
127                     <path>                  ::= <ERO><attribute-list>[<RRO>]
128             Where:
129                     <attribute-list> is defined in [RFC5440] and extended by PCEP extensions.
130
131              */
132
133             while (0 < cb.readableBytes()) {
134
135                 PcepStateReport pcestateReq = new PcepStateReportVer1();
136
137                 /*
138                  * SRP is optional
139                  * Check whether SRP Object is available, if yes store it.
140                  * First read common object header and check the Object Class whether it is SRP or LSP
141                  * If it is LSP then store only LSP. So, SRP is optional. then read path and store.
142                  * If it is SRP then store SRP and then read LSP, path and store them.
143                  */
144
145                 //mark the reader index to reset
146                 cb.markReaderIndex();
147                 PcepObjectHeader tempObjHeader = PcepObjectHeader.read(cb);
148
149                 byte yObjectClass = tempObjHeader.getObjClass();
150                 byte yObjectType = tempObjHeader.getObjType();
151
152                 //reset reader index
153                 cb.resetReaderIndex();
154                 //If SRP present then store it.
155                 if ((PcepSrpObjectVer1.SRP_OBJ_CLASS == yObjectClass)
156                         && (PcepSrpObjectVer1.SRP_OBJ_TYPE == yObjectType)) {
157                     PcepSrpObject srpObj;
158                     srpObj = PcepSrpObjectVer1.read(cb);
159                     pcestateReq.setSrpObject(srpObj);
160                 }
161
162                 //store LSP object
163                 PcepLspObject lspObj;
164                 lspObj = PcepLspObjectVer1.read(cb);
165                 pcestateReq.setLspObject(lspObj);
166
167                 //store path
168                 PcepStateReport.PcepMsgPath msgPath = new PcepStateReportVer1().new PcepMsgPath().read(cb);
169                 pcestateReq.setMsgPath(msgPath);
170
171                 llStateReportList.add(pcestateReq);
172             }
173         }
174     }
175
176     /**
177      * Constructor to initialize State Report List.
178      *
179      * @param llStateReportList list of type Pcep state report
180      */
181     PcepReportMsgVer1(LinkedList<PcepStateReport> llStateReportList) {
182         this.llStateReportList = llStateReportList;
183     }
184
185     /**
186      * Builder class for PCEP Report message.
187      */
188     static class Builder implements PcepReportMsg.Builder {
189         // Pcep report message fields
190         LinkedList<PcepStateReport> llStateReportList;
191
192         @Override
193         public PcepVersion getVersion() {
194             return PcepVersion.PCEP_1;
195         }
196
197         @Override
198         public PcepType getType() {
199             return PcepType.REPORT;
200         }
201
202         @Override
203         public PcepReportMsg build() {
204             return new PcepReportMsgVer1(this.llStateReportList);
205         }
206
207         @Override
208         public LinkedList<PcepStateReport> getStateReportList() {
209             return this.llStateReportList;
210         }
211
212         @Override
213         public Builder setStateReportList(LinkedList<PcepStateReport> ll) {
214             this.llStateReportList = ll;
215             return this;
216         }
217     }
218
219     @Override
220     public void writeTo(ChannelBuffer cb) throws PcepParseException {
221         WRITER.write(cb, this);
222     }
223
224     static final Writer WRITER = new Writer();
225
226     /**
227      * Writer class for writing PCEP report message to channel buffer.
228      */
229     static class Writer implements PcepMessageWriter<PcepReportMsgVer1> {
230
231         @Override
232         public void write(ChannelBuffer cb, PcepReportMsgVer1 message) throws PcepParseException {
233
234             int startIndex = cb.writerIndex();
235
236             // first 3 bits set to version
237             cb.writeByte((byte) (PACKET_VERSION << PcepMessageVer1.SHIFT_FLAG));
238
239             // message type
240             cb.writeByte(MSG_TYPE.getType());
241
242             // length is length of variable message, will be updated at the end
243             // Store the position of message
244             // length in buffer
245             int msgLenIndex = cb.writerIndex();
246
247             cb.writeShort((short) 0);
248             ListIterator<PcepStateReport> listIterator = message.llStateReportList.listIterator();
249
250             while (listIterator.hasNext()) {
251
252                 PcepStateReport stateRpt = listIterator.next();
253                 PcepSrpObject srpObj = stateRpt.getSrpObject();
254
255                 //SRP object is optional
256                 if (srpObj != null) {
257                     srpObj.write(cb);
258                 }
259
260                 //LSP object is mandatory
261                 PcepLspObject lspObj = stateRpt.getLspObject();
262                 if (lspObj == null) {
263                     throw new PcepParseException("LSP Object is mandatory object for PcRpt message.");
264                 } else {
265                     lspObj.write(cb);
266                 }
267
268                 //path is mandatory
269                 PcepStateReport.PcepMsgPath msgPath = stateRpt.getMsgPath();
270                 if (msgPath == null) {
271                     throw new PcepParseException("Message path is mandatory object for PcRpt message.");
272                 } else {
273                     msgPath.write(cb);
274                 }
275             }
276
277             // update message length field
278             int length = cb.writerIndex() - startIndex;
279             cb.setShort(msgLenIndex, (short) length);
280         }
281     }
282
283     @Override
284     public PcepVersion getVersion() {
285         return PcepVersion.PCEP_1;
286     }
287
288     @Override
289     public PcepType getType() {
290         return MSG_TYPE;
291     }
292
293     @Override
294     public LinkedList<PcepStateReport> getStateReportList() {
295         return this.llStateReportList;
296     }
297
298     @Override
299     public void setStateReportList(LinkedList<PcepStateReport> ll) {
300         this.llStateReportList = ll;
301     }
302
303     @Override
304     public String toString() {
305         return MoreObjects.toStringHelper(getClass())
306                 .add("StateReportList", llStateReportList)
307                 .toString();
308     }
309 }