aceb7ea0bb59eff869e49aafc430aa9ae91009e3
[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 package org.onosproject.pcepio.types;
17
18 import java.util.Iterator;
19 import java.util.LinkedList;
20 import java.util.ListIterator;
21 import java.util.Objects;
22
23 import org.jboss.netty.buffer.ChannelBuffer;
24 import org.onosproject.pcepio.exceptions.PcepParseException;
25 import org.onosproject.pcepio.protocol.PcepVersion;
26 import org.slf4j.Logger;
27 import org.slf4j.LoggerFactory;
28
29 import com.google.common.base.MoreObjects;
30
31 /**
32  * Provides Remote TE Node Descriptors TLV.
33  */
34 public class RemoteTENodeDescriptorsTlv implements PcepValueType {
35
36     /* Reference :PCEP Extension for Transporting TE Data
37         draft-dhodylee-pce-pcep-te-data-extn-02
38      *
39           0                   1                   2                   3
40           0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
41          +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
42          |           Type=[TBD9]         |             Length            |
43          +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
44          |                                                               |
45          //              Node Descriptor Sub-TLVs (variable)            //
46          |                                                               |
47          +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
48      */
49
50     protected static final Logger log = LoggerFactory.getLogger(RemoteTENodeDescriptorsTlv.class);
51
52     public static final short TYPE = 1003; //TODD:change this TBD9
53     public short hLength;
54
55     public static final int TLV_HEADER_LENGTH = 4;
56     // Node Descriptor Sub-TLVs (variable)
57     private LinkedList<PcepValueType> llRemoteTENodeDescriptorSubTLVs;
58
59     /**
60      * Constructor to initialize llRemoteTENodeDescriptorSubTLVs.
61      *
62      * @param llRemoteTENodeDescriptorSubTLVs LinkedList of PcepValueType
63      */
64     public RemoteTENodeDescriptorsTlv(LinkedList<PcepValueType> llRemoteTENodeDescriptorSubTLVs) {
65         this.llRemoteTENodeDescriptorSubTLVs = llRemoteTENodeDescriptorSubTLVs;
66     }
67
68     /**
69      * Returns object of Remote TE Node Descriptors TLV.
70      *
71      * @param llRemoteTENodeDescriptorSubTLVs LinkedList of PcepValueType
72      * @return object of RemoteTENodeDescriptorsTLV
73      */
74     public static RemoteTENodeDescriptorsTlv of(final LinkedList<PcepValueType> llRemoteTENodeDescriptorSubTLVs) {
75         return new RemoteTENodeDescriptorsTlv(llRemoteTENodeDescriptorSubTLVs);
76     }
77
78     /**
79      * Returns Remote TE Node Descriptor Sub TLVs.
80      *
81      * @return llRemoteTENodeDescriptorSubTLVs
82      */
83     public LinkedList<PcepValueType> getllRemoteTENodeDescriptorSubTLVs() {
84         return llRemoteTENodeDescriptorSubTLVs;
85     }
86
87     @Override
88     public PcepVersion getVersion() {
89         return PcepVersion.PCEP_1;
90     }
91
92     @Override
93     public short getType() {
94         return TYPE;
95     }
96
97     @Override
98     public short getLength() {
99         return hLength;
100     }
101
102     @Override
103     public int hashCode() {
104         return Objects.hash(llRemoteTENodeDescriptorSubTLVs.hashCode());
105     }
106
107     @Override
108     public boolean equals(Object obj) {
109         if (this == obj) {
110             return true;
111         }
112         /*
113          * Here we have a list of Tlv so to compare each sub tlv between the object
114          * we have to take a list iterator so one by one we can get each sub tlv object
115          * and can compare them.
116          * it may be possible that the size of 2 lists is not equal so we have to first check
117          * the size, if both are same then we should check for the subtlv objects otherwise
118          * we should return false.
119          */
120         if (obj instanceof RemoteTENodeDescriptorsTlv) {
121             int countObjSubTlv = 0;
122             int countOtherSubTlv = 0;
123             boolean isCommonSubTlv = true;
124             RemoteTENodeDescriptorsTlv other = (RemoteTENodeDescriptorsTlv) obj;
125             Iterator<PcepValueType> objListIterator = ((RemoteTENodeDescriptorsTlv) obj).llRemoteTENodeDescriptorSubTLVs
126                     .iterator();
127             countObjSubTlv = ((RemoteTENodeDescriptorsTlv) obj).llRemoteTENodeDescriptorSubTLVs.size();
128             countOtherSubTlv = other.llRemoteTENodeDescriptorSubTLVs.size();
129             if (countObjSubTlv != countOtherSubTlv) {
130                 return false;
131             } else {
132                 while (objListIterator.hasNext() && isCommonSubTlv) {
133                     PcepValueType subTlv = objListIterator.next();
134                     isCommonSubTlv = Objects.equals(llRemoteTENodeDescriptorSubTLVs.contains(subTlv),
135                             other.llRemoteTENodeDescriptorSubTLVs.contains(subTlv));
136                 }
137                 return isCommonSubTlv;
138             }
139         }
140         return false;
141     }
142
143     @Override
144     public int write(ChannelBuffer c) {
145
146         int tlvStartIndex = c.writerIndex();
147         c.writeShort(TYPE);
148         int tlvLenIndex = c.writerIndex();
149         hLength = 0;
150         c.writeShort(hLength);
151
152         ListIterator<PcepValueType> listIterator = llRemoteTENodeDescriptorSubTLVs.listIterator();
153
154         while (listIterator.hasNext()) {
155             PcepValueType tlv = listIterator.next();
156
157             if (tlv == null) {
158                 log.debug("TLV is null from subTlv list");
159                 continue;
160             }
161             tlv.write(c);
162
163             // need to take care of padding
164             int pad = tlv.getLength() % 4;
165
166             if (0 != pad) {
167                 pad = 4 - pad;
168                 for (int i = 0; i < pad; ++i) {
169                     c.writeByte((byte) 0);
170                 }
171             }
172         }
173
174         hLength = (short) (c.writerIndex() - tlvStartIndex);
175         c.setShort(tlvLenIndex, (hLength - TLV_HEADER_LENGTH));
176
177         return c.writerIndex() - tlvStartIndex;
178     }
179
180     /**
181      * Reads channel buffer and returns object of Remote TE Node Descriptors TLV.
182      *
183      * @param c input channel buffer
184      * @param length length of buffer
185      * @return object of RemoteTENodeDescriptorsTLV
186      * @throws PcepParseException if mandatory fields are missing
187      */
188     public static PcepValueType read(ChannelBuffer c , short length) throws PcepParseException {
189
190         // Node Descriptor Sub-TLVs (variable)
191         LinkedList<PcepValueType> llRemoteTENodeDescriptorSubTLVs = new LinkedList<>();
192
193         ChannelBuffer tempCb = c.readBytes(length);
194
195         while (TLV_HEADER_LENGTH <= tempCb.readableBytes()) {
196
197             PcepValueType tlv;
198             short hType = tempCb.readShort();
199             int iValue = 0;
200             short hLength = tempCb.readShort();
201             switch (hType) {
202
203             case AutonomousSystemTlv.TYPE:
204                 iValue = tempCb.readInt();
205                 tlv = new AutonomousSystemTlv(iValue);
206                 break;
207             case BGPLSidentifierTlv.TYPE:
208                 iValue = tempCb.readInt();
209                 tlv = new BGPLSidentifierTlv(iValue);
210                 break;
211             case OSPFareaIDsubTlv.TYPE:
212                 iValue = tempCb.readInt();
213                 tlv = new OSPFareaIDsubTlv(iValue);
214                 break;
215             case RouterIDSubTlv.TYPE:
216                 tlv = RouterIDSubTlv.read(tempCb, hLength);
217                 break;
218
219             default:
220                 throw new PcepParseException("Unsupported Sub TLV type :" + hType);
221             }
222
223             // Check for the padding
224             int pad = hLength % 4;
225             if (0 < pad) {
226                 pad = 4 - pad;
227                 if (pad <= tempCb.readableBytes()) {
228                     tempCb.skipBytes(pad);
229                 }
230             }
231
232             llRemoteTENodeDescriptorSubTLVs.add(tlv);
233         }
234
235         if (0 < tempCb.readableBytes()) {
236
237             throw new PcepParseException("Sub Tlv parsing error. Extra bytes received.");
238         }
239         return new RemoteTENodeDescriptorsTlv(llRemoteTENodeDescriptorSubTLVs);
240     }
241
242     @Override
243     public String toString() {
244         return MoreObjects.toStringHelper(getClass())
245                 .add("Type", TYPE)
246                 .add("Length", hLength)
247                 .add("RemoteTeNodeDescriptorSubTLVs", llRemoteTENodeDescriptorSubTLVs)
248                 .toString();
249     }
250 }