blob: f797f5b17d7c082e3a1399b4799fff7097ee92b1 [file] [log] [blame]
Shashikanth VH73b12772016-04-18 14:28:45 +05301/*
2 * Copyright 2016-present 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 */
16package org.onosproject.bgpio.types.attr;
17
18import com.google.common.base.MoreObjects;
19
20import org.jboss.netty.buffer.ChannelBuffer;
21import org.onlab.packet.IpAddress;
22import org.onosproject.bgpio.exceptions.BgpParseException;
23import org.onosproject.bgpio.types.BgpErrorType;
24import org.onosproject.bgpio.types.BgpValueType;
25import org.onosproject.bgpio.types.WideCommunityAttrHeader;
26import org.onosproject.bgpio.types.WideCommunityExcludeTarget;
27import org.onosproject.bgpio.types.WideCommunityInteger;
28import org.onosproject.bgpio.types.WideCommunityIpV4Neighbour;
29import org.onosproject.bgpio.types.WideCommunityParameter;
30import org.onosproject.bgpio.types.WideCommunityTarget;
31import org.onosproject.bgpio.util.Validation;
32import org.slf4j.Logger;
33import org.slf4j.LoggerFactory;
34
35import java.util.ArrayList;
36import java.util.Iterator;
37import java.util.List;
38import java.util.Objects;
39
40/**
41 * Provides implementation of wide community path attribute.
42 */
43public class WideCommunity implements BgpValueType {
44
45 private static final Logger log = LoggerFactory.getLogger(WideCommunity.class);
Shashikanth VHe38c21e2016-05-26 21:37:25 +053046 public static final byte TYPE = (byte) 129;
Shashikanth VH73b12772016-04-18 14:28:45 +053047 public static final short LENGTH = 4;
48 public static final byte TYPE_LENGTH_SIZE = 3;
Shashikanth VHe38c21e2016-05-26 21:37:25 +053049 public static final byte FLAGS = (byte) 0x90;
Shashikanth VH73b12772016-04-18 14:28:45 +053050 private WideCommunityAttrHeader wideCommunityHeader;
51 private int community;
52 private int localAsn;
53 private int contextAsn;
54 private WideCommunityTarget target;
55 private WideCommunityExcludeTarget excludeTarget;
56 private WideCommunityParameter parameter;
57
58 /**
59 * Creates an instance of wide community.
60 *
61 * @param wideCommunityHeader wide community header
62 * @param community wide community
63 * @param localAsn local ASN number
64 * @param contextAsn context ASN number
65 * @param target wide community include target
66 * @param excludeTarget wide community exclude target
67 * @param parameter wide community parameter
68 */
69 public WideCommunity(WideCommunityAttrHeader wideCommunityHeader, int community, int localAsn, int contextAsn,
70 WideCommunityTarget target, WideCommunityExcludeTarget excludeTarget,
71 WideCommunityParameter parameter) {
72 this.wideCommunityHeader = wideCommunityHeader;
73 this.community = community;
74 this.localAsn = localAsn;
75 this.contextAsn = contextAsn;
76 this.target = target;
77 this.excludeTarget = excludeTarget;
78 this.parameter = parameter;
79 }
80
81 /**
82 * Returns object of this class with specified values.
83 *
Ray Milkeybb23e0b2016-08-02 17:00:21 -070084 * @param wideCommunityHeader community header
Shashikanth VH73b12772016-04-18 14:28:45 +053085 * @param community wide community
86 * @param localAsn local ASN number
87 * @param contextAsn context ASN number
88 * @param target wide community include target
89 * @param excludeTarget wide community exclude target
90 * @param parameter wide community parameter
91 * @return object of WideCommunityAttr
92 */
93 public static WideCommunity of(WideCommunityAttrHeader wideCommunityHeader, int community, int localAsn,
94 int contextAsn, WideCommunityTarget target,
95 WideCommunityExcludeTarget excludeTarget, WideCommunityParameter parameter) {
96 return new WideCommunity(wideCommunityHeader, community, localAsn, contextAsn, target, excludeTarget,
97 parameter);
98 }
99
100 /**
101 * Returns wide community value.
102 *
103 * @return wide community value
104 */
105 public int community() {
106 return community;
107 }
108
109 /**
110 * Sets wide community value.
111 *
112 * @param community wide community value
113 */
114 public void setCommunity(int community) {
115 this.community = community;
116 }
117
118 /**
119 * Returns wide community local autonomous number.
120 *
121 * @return local autonomous number
122 */
123 public int localAsn() {
124 return localAsn;
125 }
126
127 /**
128 * Sets wide community local autonomous number.
129 *
130 * @param localAsn local autonomous number
131 */
132 public void setLocalAsn(int localAsn) {
133 this.localAsn = localAsn;
134 }
135
136 /**
137 * Returns wide community context autonomous number.
138 *
139 * @return contest autonomous number
140 */
141 public int contextAsn() {
142 return contextAsn;
143 }
144
145 /**
146 * Sets wide community context autonomous number.
147 *
148 * @param contextAsn context autonomous number
149 */
150 public void setContextAsn(int contextAsn) {
151 this.contextAsn = contextAsn;
152 }
153
154 /**
155 * Returns wide community target.
156 *
157 * @return wide community target
158 */
159 public WideCommunityTarget target() {
160 return target;
161 }
162
163 /**
164 * Sets wide community target.
165 *
166 * @param target wide community target
167 */
168 public void setTarget(WideCommunityTarget target) {
169 this.target = target;
170 }
171
172 /**
173 * Returns wide community exclude target.
174 *
175 * @return wide community exclude target
176 */
177 public WideCommunityExcludeTarget excludeTarget() {
178 return excludeTarget;
179 }
180
181 /**
182 * Sets wide community exclude target.
183 *
184 * @param excludeTarget wide community texclude arget
185 */
186 public void setExcludeTarget(WideCommunityExcludeTarget excludeTarget) {
187 this.excludeTarget = excludeTarget;
188 }
189
190 /**
191 * Returns wide community parameter.
192 *
193 * @return wide community parameter
194 */
195 public WideCommunityParameter parameter() {
196 return parameter;
197 }
198
199 /**
200 * Sets wide community parameter.
201 *
202 * @param parameter wide community parameter
203 */
204 public void setParameter(WideCommunityParameter parameter) {
205 this.parameter = parameter;
206 }
207
208 @Override
209 public int hashCode() {
210 return Objects.hash(wideCommunityHeader, community, localAsn, contextAsn, target, excludeTarget, parameter);
211 }
212
213 @Override
214 public boolean equals(Object obj) {
215 if (this == obj) {
216 return true;
217 }
218
219 if (obj instanceof WideCommunity) {
220 WideCommunity other = (WideCommunity) obj;
221 return Objects.equals(wideCommunityHeader, other.wideCommunityHeader)
222 && Objects.equals(community, other.community) && Objects.equals(localAsn, other.localAsn)
223 && Objects.equals(contextAsn, other.contextAsn) && Objects.equals(target, other.target)
224 && Objects.equals(excludeTarget, other.excludeTarget) && Objects.equals(parameter, other.parameter);
225 }
226 return false;
227 }
228
229 @Override
230 public int write(ChannelBuffer c) {
231 int iTargetLenIndex;
232 int length;
233 int iLenStartIndex = c.writerIndex();
234 c.writeByte(FLAGS); // TODO: update flag value
235 c.writeByte(TYPE);
236
237 int iLengthIndex = c.writerIndex();
238 c.writeShort(0);
239
240 wideCommunityHeader.write(c);
241
Shashikanth VHe38c21e2016-05-26 21:37:25 +0530242 int iComLengthIndex = c.writerIndex();
243 c.writeShort(0);
244
Shashikanth VH73b12772016-04-18 14:28:45 +0530245 c.writeInt(community);
246 c.writeInt(localAsn);
247 c.writeInt(contextAsn);
248
249 if (target() != null) {
250 c.writeByte(WideCommunityTarget.TYPE);
251 iTargetLenIndex = c.writerIndex();
252 c.writeShort(0); // length
253
254 target.write(c);
255
256 length = c.writerIndex() - iTargetLenIndex;
257 c.setShort(iTargetLenIndex, (short) (length - 2));
258 }
259
260 if (excludeTarget() != null) {
261 c.writeByte(WideCommunityExcludeTarget.TYPE);
262 iTargetLenIndex = c.writerIndex();
263 c.writeShort(0); // length
264
265 excludeTarget.write(c);
266
267 length = c.writerIndex() - iTargetLenIndex;
268 c.setShort(iTargetLenIndex, (short) (length - 2));
269 }
270
271 if (parameter() != null) {
272 c.writeByte(WideCommunityParameter.TYPE);
273 iTargetLenIndex = c.writerIndex();
274 c.writeShort(0); // length
275
276 parameter.write(c);
277
278 length = c.writerIndex() - iTargetLenIndex;
279 c.setShort(iTargetLenIndex, (short) (length - 2));
280 }
281
Shashikanth VHe38c21e2016-05-26 21:37:25 +0530282 length = c.writerIndex() - iComLengthIndex;
283 c.setShort(iComLengthIndex, (short) (length - 2));
284
Shashikanth VH73b12772016-04-18 14:28:45 +0530285 length = c.writerIndex() - iLengthIndex;
286 c.setShort(iLengthIndex, (short) (length - 2));
287
288 return c.writerIndex() - iLenStartIndex;
289 }
290
291 /**
292 * Reads the wide community attribute.
293 *
294 * @param c ChannelBuffer
295 * @return object of WideCommunityAttr
296 * @throws BgpParseException while parsing BgpPrefixAttrRouteTag
297 */
298 public static WideCommunity read(ChannelBuffer c) throws BgpParseException {
299
300 WideCommunityAttrHeader wideCommunityHeader;
301 int community;
302 int localAsn;
303 int contextAsn;
304 WideCommunityTarget target = null;
305 WideCommunityExcludeTarget excludeTarget = null;
306 WideCommunityParameter parameter = null;
307
308 short length = c.readShort();
309
310 if (c.readableBytes() < length) {
311 Validation.validateLen(BgpErrorType.UPDATE_MESSAGE_ERROR, BgpErrorType.ATTRIBUTE_LENGTH_ERROR, length);
312 }
313
314 wideCommunityHeader = WideCommunityAttrHeader.read(c);
315 if ((c.readableBytes() < 12) || (c.readableBytes() < wideCommunityHeader.length())) {
316 Validation.validateLen(BgpErrorType.UPDATE_MESSAGE_ERROR, BgpErrorType.ATTRIBUTE_LENGTH_ERROR, length);
317 }
318
319 community = c.readInt();
320 localAsn = c.readInt();
321 contextAsn = c.readInt();
322
323 while (c.readableBytes() > 0) {
324
325 if (c.readableBytes() < TYPE_LENGTH_SIZE) {
326 Validation.validateLen(BgpErrorType.UPDATE_MESSAGE_ERROR, BgpErrorType.ATTRIBUTE_LENGTH_ERROR,
327 c.readableBytes());
328 }
329
330 byte type = c.readByte();
331 length = c.readShort();
332
333 if (c.readableBytes() < length) {
334 Validation.validateLen(BgpErrorType.UPDATE_MESSAGE_ERROR, BgpErrorType.ATTRIBUTE_LENGTH_ERROR,
335 c.readableBytes());
336 }
337
338 if (type == WideCommunityTarget.TYPE) {
339 target = WideCommunityTarget.read(c);
340 } else if (type == WideCommunityExcludeTarget.TYPE) {
341 excludeTarget = WideCommunityExcludeTarget.read(c);
342 } else if (type == WideCommunityParameter.TYPE) {
343 parameter = WideCommunityParameter.read(c);
344 }
345 }
346 return new WideCommunity(wideCommunityHeader, community, localAsn, contextAsn,
347 target, excludeTarget, parameter);
348 }
349
350 /**
351 * Encode wide community target(s).
352 *
353 * @param c channel buffer
354 * @param targetTlv wide community include/exclude target
355 */
356 public static void encodeWideCommunityTlv(ChannelBuffer c,
357 List<BgpValueType> targetTlv) {
358
359 /*
360 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
361 | IPV4Neig(8) | Length: 8 |
362 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
363 | local 10101010 |
364 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
365 | remote 10101010 |
366 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
367 * */
368 List<BgpValueType> target = targetTlv;
369 if (target == null) {
370 log.debug("target is null");
371 return;
372 }
373 Iterator<BgpValueType> listIterator = targetTlv.iterator();
374
375 while (listIterator.hasNext()) {
376 BgpValueType attr = listIterator.next();
377 if (attr instanceof WideCommunityIpV4Neighbour) {
378 WideCommunityIpV4Neighbour ipv4Neig = (WideCommunityIpV4Neighbour) attr;
379 ipv4Neig.write(c);
380 } else if (attr instanceof WideCommunityInteger) {
381 WideCommunityInteger integer = (WideCommunityInteger) attr;
382 integer.write(c);
383 }
384 }
385 return;
386 }
387
388 /**
389 * Decode wide community target(s).
390 *
391 * @param c channel buffer
392 * @return target list
393 * @throws BgpParseException on decode error
394 */
395 public static List<BgpValueType> decodeWideCommunityTlv(ChannelBuffer c) throws BgpParseException {
396 List<BgpValueType> targetTlv = new ArrayList<>();
397
398 while (c.readableBytes() > 0) {
399 if (c.readableBytes() < TYPE_LENGTH_SIZE) {
400 Validation.validateLen(BgpErrorType.UPDATE_MESSAGE_ERROR, BgpErrorType.ATTRIBUTE_LENGTH_ERROR,
401 c.readableBytes());
402 }
403
404 byte atomType = c.readByte();
405 short atomLength = c.readShort();
406
407 if (c.readableBytes() < atomLength) {
408 Validation.validateLen(BgpErrorType.UPDATE_MESSAGE_ERROR, BgpErrorType.ATTRIBUTE_LENGTH_ERROR,
409 atomLength);
410 }
411
412 if (atomType == WideCommunityIpV4Neighbour.TYPE) {
413 ChannelBuffer tempBuf = c.readBytes(atomLength);
414
415 WideCommunityIpV4Neighbour wideCommAtom = new WideCommunityIpV4Neighbour();
416
417 while (tempBuf.readableBytes() > 0) {
418 wideCommAtom.add(IpAddress.valueOf(tempBuf.readInt()),
419 IpAddress.valueOf(tempBuf.readInt()));
420 }
421 targetTlv.add(wideCommAtom);
422 } else if (atomType == WideCommunityInteger.TYPE) {
423 ChannelBuffer tempBuf = c.readBytes(atomLength);
424 List<Integer> integer = new ArrayList<>();
425 while (tempBuf.readableBytes() > 0) {
426 integer.add(tempBuf.readInt());
427 }
428 targetTlv.add(new WideCommunityInteger(integer));
429 } else {
430 Validation.validateLen(BgpErrorType.UPDATE_MESSAGE_ERROR, BgpErrorType.MALFORMED_ATTRIBUTE_LIST,
431 atomLength);
432 }
433 }
434 return targetTlv;
435 }
436
437 @Override
438 public short getType() {
439 return TYPE;
440 }
441
442 @Override
443 public int compareTo(Object o) {
444 // TODO:
445 return 0;
446 }
447
448 @Override
449 public String toString() {
450 return MoreObjects.toStringHelper(getClass())
451 .omitNullValues()
452 .add("FLAGS", FLAGS)
453 .add("wideCommunityHeader", wideCommunityHeader)
454 .add("community", community)
455 .add("localAsn", localAsn)
456 .add("contextAsn", contextAsn)
457 .add("target", target)
458 .add("excludeTarget", excludeTarget)
459 .add("parameter", parameter).toString();
460 }
461}