2 * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
9 package org.opendaylight.protocol.bgp.parser.impl.message.update;
11 import java.util.Arrays;
13 import org.opendaylight.protocol.bgp.concepts.ASSpecificExtendedCommunity;
14 import org.opendaylight.protocol.bgp.concepts.Community;
15 import org.opendaylight.protocol.bgp.concepts.ExtendedCommunity;
16 import org.opendaylight.protocol.bgp.concepts.Inet4SpecificExtendedCommunity;
17 import org.opendaylight.protocol.bgp.concepts.OpaqueExtendedCommunity;
18 import org.opendaylight.protocol.bgp.concepts.RouteOriginCommunity;
19 import org.opendaylight.protocol.bgp.concepts.RouteTargetCommunity;
20 import org.opendaylight.protocol.bgp.parser.BGPDocumentedException;
21 import org.opendaylight.protocol.bgp.parser.BGPError;
22 import org.opendaylight.protocol.util.ByteArray;
23 import org.opendaylight.protocol.concepts.ASNumber;
24 import org.opendaylight.protocol.concepts.IPv4Address;
25 import com.google.common.annotations.VisibleForTesting;
26 import com.google.common.primitives.UnsignedBytes;
29 * Parser for Extended Communities Path Attribute.
31 public class CommunitiesParser {
33 public static final int EXTENDED_COMMUNITY_LENGTH = 8; // bytes
35 public static final int COMMUNITY_LENGTH = 4; // bytes
37 private static final int TYPE_LENGTH = 2; // bytes
39 private static final int AS_NUMBER_LENGTH = 2; // bytes
41 private static final int AS_LOCAL_ADMIN_LENGTH = 4; // bytes
43 private CommunitiesParser() {
48 * Parse known Community, if unknown, a new one will be created.
50 * @param bytes byte array to be parsed
51 * @return new Community
52 * @throws BGPDocumentedException
54 static Community parseCommunity(final byte[] bytes) throws BGPDocumentedException {
55 if (bytes.length != COMMUNITY_LENGTH)
56 throw new BGPDocumentedException("Community with wrong length: " + bytes.length, BGPError.OPT_ATTR_ERROR);
57 if (Arrays.equals(bytes, new byte[] { (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0x01 })) {
58 return Community.NO_EXPORT;
59 } else if (Arrays.equals(bytes, new byte[] { (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0x02 })) {
60 return Community.NO_ADVERTISE;
61 } else if (Arrays.equals(bytes, new byte[] { (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0x03 })) {
62 return Community.NO_EXPORT_SUBCONFED;
64 return new Community(new ASNumber(ByteArray.bytesToLong(Arrays.copyOfRange(bytes, 0, AS_NUMBER_LENGTH))), ByteArray.bytesToInt(Arrays.copyOfRange(
65 bytes, AS_NUMBER_LENGTH, AS_NUMBER_LENGTH + AS_NUMBER_LENGTH)));
69 * Parse Extended Community according to their type.
71 * @param bytes byte array to be parsed
72 * @return new Specific Extended Community
73 * @throws BGPDocumentedException if the type is not recognized
76 public static ExtendedCommunity parseExtendedCommunity(final byte[] bytes) throws BGPDocumentedException {
77 // final int type = ByteArray.bytesToInt(ByteArray.subByte(bytes, 0, TYPE_LENGTH));
78 final int type = UnsignedBytes.toInt(bytes[0]);
79 final int subType = UnsignedBytes.toInt(bytes[1]);
80 final byte[] value = ByteArray.subByte(bytes, TYPE_LENGTH, bytes.length - TYPE_LENGTH);
84 return new RouteTargetCommunity(new ASNumber(ByteArray.bytesToInt(ByteArray.subByte(value, 0, AS_NUMBER_LENGTH))), ByteArray.subByte(
85 value, AS_NUMBER_LENGTH, AS_LOCAL_ADMIN_LENGTH));
86 } else if (subType == 3) {
87 return new RouteOriginCommunity(new ASNumber(ByteArray.bytesToInt(ByteArray.subByte(value, 0, AS_NUMBER_LENGTH))), ByteArray.subByte(
88 value, AS_NUMBER_LENGTH, AS_LOCAL_ADMIN_LENGTH));
90 return new ASSpecificExtendedCommunity(false, subType, new ASNumber(ByteArray.bytesToInt(ByteArray.subByte(value, 0,
91 AS_NUMBER_LENGTH))), ByteArray.subByte(value, AS_NUMBER_LENGTH, AS_LOCAL_ADMIN_LENGTH));
93 return new ASSpecificExtendedCommunity(true, subType, new ASNumber(ByteArray.bytesToInt(ByteArray.subByte(value, 0,
94 AS_NUMBER_LENGTH))), ByteArray.subByte(value, AS_NUMBER_LENGTH, AS_LOCAL_ADMIN_LENGTH));
97 return new RouteTargetCommunity(new ASNumber(ByteArray.bytesToInt(ByteArray.subByte(value, 0, AS_NUMBER_LENGTH))), ByteArray.subByte(
98 value, AS_NUMBER_LENGTH, AS_LOCAL_ADMIN_LENGTH));
99 } else if (subType == 3) {
100 return new RouteOriginCommunity(new ASNumber(ByteArray.bytesToInt(ByteArray.subByte(value, 0, AS_NUMBER_LENGTH))), ByteArray.subByte(
101 value, AS_NUMBER_LENGTH, AS_LOCAL_ADMIN_LENGTH));
103 throw new BGPDocumentedException("Could not parse Extended Community subtype: " + subType, BGPError.OPT_ATTR_ERROR);
106 return new RouteTargetCommunity(new ASNumber(ByteArray.bytesToInt(ByteArray.subByte(value, 0, AS_NUMBER_LENGTH))), ByteArray.subByte(
107 value, AS_NUMBER_LENGTH, AS_LOCAL_ADMIN_LENGTH));
108 } else if (subType == 3) {
109 return new RouteOriginCommunity(new ASNumber(ByteArray.bytesToInt(ByteArray.subByte(value, 0, AS_NUMBER_LENGTH))), ByteArray.subByte(
110 value, AS_NUMBER_LENGTH, AS_LOCAL_ADMIN_LENGTH));
112 return new Inet4SpecificExtendedCommunity(false, subType, new IPv4Address(ByteArray.subByte(value, 0, 4)), ByteArray.subByte(
115 return new Inet4SpecificExtendedCommunity(true, subType, new IPv4Address(ByteArray.subByte(value, 0, 4)), ByteArray.subByte(
118 return new OpaqueExtendedCommunity(false, subType, value);
120 return new OpaqueExtendedCommunity(true, subType, value);
122 throw new BGPDocumentedException("Could not parse Extended Community type: " + type, BGPError.OPT_ATTR_ERROR);