blob: 25afd95fee0d939a00607f0c1162baf8e64e5aa1 [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);
46 public static final byte TYPE = (byte) 254; /* TODO: IANA Assigned */
47 public static final short LENGTH = 4;
48 public static final byte TYPE_LENGTH_SIZE = 3;
49 public static final byte FLAGS = (byte) 0x40;
50 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
241 c.writeInt(community);
242 c.writeInt(localAsn);
243 c.writeInt(contextAsn);
244
245 if (target() != null) {
246 c.writeByte(WideCommunityTarget.TYPE);
247 iTargetLenIndex = c.writerIndex();
248 c.writeShort(0); // length
249
250 target.write(c);
251
252 length = c.writerIndex() - iTargetLenIndex;
253 c.setShort(iTargetLenIndex, (short) (length - 2));
254 }
255
256 if (excludeTarget() != null) {
257 c.writeByte(WideCommunityExcludeTarget.TYPE);
258 iTargetLenIndex = c.writerIndex();
259 c.writeShort(0); // length
260
261 excludeTarget.write(c);
262
263 length = c.writerIndex() - iTargetLenIndex;
264 c.setShort(iTargetLenIndex, (short) (length - 2));
265 }
266
267 if (parameter() != null) {
268 c.writeByte(WideCommunityParameter.TYPE);
269 iTargetLenIndex = c.writerIndex();
270 c.writeShort(0); // length
271
272 parameter.write(c);
273
274 length = c.writerIndex() - iTargetLenIndex;
275 c.setShort(iTargetLenIndex, (short) (length - 2));
276 }
277
278 length = c.writerIndex() - iLengthIndex;
279 c.setShort(iLengthIndex, (short) (length - 2));
280
281 return c.writerIndex() - iLenStartIndex;
282 }
283
284 /**
285 * Reads the wide community attribute.
286 *
287 * @param c ChannelBuffer
288 * @return object of WideCommunityAttr
289 * @throws BgpParseException while parsing BgpPrefixAttrRouteTag
290 */
291 public static WideCommunity read(ChannelBuffer c) throws BgpParseException {
292
293 WideCommunityAttrHeader wideCommunityHeader;
294 int community;
295 int localAsn;
296 int contextAsn;
297 WideCommunityTarget target = null;
298 WideCommunityExcludeTarget excludeTarget = null;
299 WideCommunityParameter parameter = null;
300
301 short length = c.readShort();
302
303 if (c.readableBytes() < length) {
304 Validation.validateLen(BgpErrorType.UPDATE_MESSAGE_ERROR, BgpErrorType.ATTRIBUTE_LENGTH_ERROR, length);
305 }
306
307 wideCommunityHeader = WideCommunityAttrHeader.read(c);
308 if ((c.readableBytes() < 12) || (c.readableBytes() < wideCommunityHeader.length())) {
309 Validation.validateLen(BgpErrorType.UPDATE_MESSAGE_ERROR, BgpErrorType.ATTRIBUTE_LENGTH_ERROR, length);
310 }
311
312 community = c.readInt();
313 localAsn = c.readInt();
314 contextAsn = c.readInt();
315
316 while (c.readableBytes() > 0) {
317
318 if (c.readableBytes() < TYPE_LENGTH_SIZE) {
319 Validation.validateLen(BgpErrorType.UPDATE_MESSAGE_ERROR, BgpErrorType.ATTRIBUTE_LENGTH_ERROR,
320 c.readableBytes());
321 }
322
323 byte type = c.readByte();
324 length = c.readShort();
325
326 if (c.readableBytes() < length) {
327 Validation.validateLen(BgpErrorType.UPDATE_MESSAGE_ERROR, BgpErrorType.ATTRIBUTE_LENGTH_ERROR,
328 c.readableBytes());
329 }
330
331 if (type == WideCommunityTarget.TYPE) {
332 target = WideCommunityTarget.read(c);
333 } else if (type == WideCommunityExcludeTarget.TYPE) {
334 excludeTarget = WideCommunityExcludeTarget.read(c);
335 } else if (type == WideCommunityParameter.TYPE) {
336 parameter = WideCommunityParameter.read(c);
337 }
338 }
339 return new WideCommunity(wideCommunityHeader, community, localAsn, contextAsn,
340 target, excludeTarget, parameter);
341 }
342
343 /**
344 * Encode wide community target(s).
345 *
346 * @param c channel buffer
347 * @param targetTlv wide community include/exclude target
348 */
349 public static void encodeWideCommunityTlv(ChannelBuffer c,
350 List<BgpValueType> targetTlv) {
351
352 /*
353 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
354 | IPV4Neig(8) | Length: 8 |
355 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
356 | local 10101010 |
357 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
358 | remote 10101010 |
359 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
360 * */
361 List<BgpValueType> target = targetTlv;
362 if (target == null) {
363 log.debug("target is null");
364 return;
365 }
366 Iterator<BgpValueType> listIterator = targetTlv.iterator();
367
368 while (listIterator.hasNext()) {
369 BgpValueType attr = listIterator.next();
370 if (attr instanceof WideCommunityIpV4Neighbour) {
371 WideCommunityIpV4Neighbour ipv4Neig = (WideCommunityIpV4Neighbour) attr;
372 ipv4Neig.write(c);
373 } else if (attr instanceof WideCommunityInteger) {
374 WideCommunityInteger integer = (WideCommunityInteger) attr;
375 integer.write(c);
376 }
377 }
378 return;
379 }
380
381 /**
382 * Decode wide community target(s).
383 *
384 * @param c channel buffer
385 * @return target list
386 * @throws BgpParseException on decode error
387 */
388 public static List<BgpValueType> decodeWideCommunityTlv(ChannelBuffer c) throws BgpParseException {
389 List<BgpValueType> targetTlv = new ArrayList<>();
390
391 while (c.readableBytes() > 0) {
392 if (c.readableBytes() < TYPE_LENGTH_SIZE) {
393 Validation.validateLen(BgpErrorType.UPDATE_MESSAGE_ERROR, BgpErrorType.ATTRIBUTE_LENGTH_ERROR,
394 c.readableBytes());
395 }
396
397 byte atomType = c.readByte();
398 short atomLength = c.readShort();
399
400 if (c.readableBytes() < atomLength) {
401 Validation.validateLen(BgpErrorType.UPDATE_MESSAGE_ERROR, BgpErrorType.ATTRIBUTE_LENGTH_ERROR,
402 atomLength);
403 }
404
405 if (atomType == WideCommunityIpV4Neighbour.TYPE) {
406 ChannelBuffer tempBuf = c.readBytes(atomLength);
407
408 WideCommunityIpV4Neighbour wideCommAtom = new WideCommunityIpV4Neighbour();
409
410 while (tempBuf.readableBytes() > 0) {
411 wideCommAtom.add(IpAddress.valueOf(tempBuf.readInt()),
412 IpAddress.valueOf(tempBuf.readInt()));
413 }
414 targetTlv.add(wideCommAtom);
415 } else if (atomType == WideCommunityInteger.TYPE) {
416 ChannelBuffer tempBuf = c.readBytes(atomLength);
417 List<Integer> integer = new ArrayList<>();
418 while (tempBuf.readableBytes() > 0) {
419 integer.add(tempBuf.readInt());
420 }
421 targetTlv.add(new WideCommunityInteger(integer));
422 } else {
423 Validation.validateLen(BgpErrorType.UPDATE_MESSAGE_ERROR, BgpErrorType.MALFORMED_ATTRIBUTE_LIST,
424 atomLength);
425 }
426 }
427 return targetTlv;
428 }
429
430 @Override
431 public short getType() {
432 return TYPE;
433 }
434
435 @Override
436 public int compareTo(Object o) {
437 // TODO:
438 return 0;
439 }
440
441 @Override
442 public String toString() {
443 return MoreObjects.toStringHelper(getClass())
444 .omitNullValues()
445 .add("FLAGS", FLAGS)
446 .add("wideCommunityHeader", wideCommunityHeader)
447 .add("community", community)
448 .add("localAsn", localAsn)
449 .add("contextAsn", contextAsn)
450 .add("target", target)
451 .add("excludeTarget", excludeTarget)
452 .add("parameter", parameter).toString();
453 }
454}