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