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.parser.BGPDocumentedException;
14 import org.opendaylight.protocol.bgp.parser.BGPError;
15 import org.opendaylight.protocol.concepts.Ipv4Util;
16 import org.opendaylight.protocol.util.ByteArray;
17 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.AsNumber;
18 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.Community;
19 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.extended.community.ExtendedCommunity;
20 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.extended.community.extended.community.CAsSpecificExtendedCommunityBuilder;
21 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.extended.community.extended.community.CInet4SpecificExtendedCommunityBuilder;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.extended.community.extended.community.COpaqueExtendedCommunityBuilder;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.extended.community.extended.community.CRouteOriginExtendedCommunityBuilder;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.extended.community.extended.community.CRouteTargetExtendedCommunityBuilder;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.extended.community.extended.community.c.as.specific.extended.community.AsSpecificExtendedCommunityBuilder;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.extended.community.extended.community.c.inet4.specific.extended.community.Inet4SpecificExtendedCommunityBuilder;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.extended.community.extended.community.c.opaque.extended.community.OpaqueExtendedCommunityBuilder;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.extended.community.extended.community.c.route.origin.extended.community.RouteOriginExtendedCommunityBuilder;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.extended.community.extended.community.c.route.target.extended.community.RouteTargetExtendedCommunityBuilder;
31 import com.google.common.annotations.VisibleForTesting;
32 import com.google.common.primitives.UnsignedBytes;
35 * Parser for Extended Communities Path Attribute.
37 public final class CommunitiesParser {
39 public static final int EXTENDED_COMMUNITY_LENGTH = 8;
41 public static final int COMMUNITY_LENGTH = 4;
43 private static final int TYPE_LENGTH = 2;
45 private static final int AS_NUMBER_LENGTH = 2;
47 private static final int AS_LOCAL_ADMIN_LENGTH = 4;
49 private CommunitiesParser() {
54 * Parse known Community, if unknown, a new one will be created.
56 * @param bytes byte array to be parsed
57 * @return new Community
58 * @throws BGPDocumentedException
60 static Community parseCommunity(final byte[] bytes) throws BGPDocumentedException {
61 if (bytes.length != COMMUNITY_LENGTH) {
62 throw new BGPDocumentedException("Community with wrong length: " + bytes.length, BGPError.OPT_ATTR_ERROR);
64 if (Arrays.equals(bytes, new byte[] { (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0x01 })) {
65 return CommunityUtil.NO_EXPORT;
66 } else if (Arrays.equals(bytes, new byte[] { (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0x02 })) {
67 return CommunityUtil.NO_ADVERTISE;
68 } else if (Arrays.equals(bytes, new byte[] { (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0x03 })) {
69 return CommunityUtil.NO_EXPORT_SUBCONFED;
71 return CommunityUtil.create((ByteArray.bytesToLong(Arrays.copyOfRange(bytes, 0, AS_NUMBER_LENGTH))),
72 ByteArray.bytesToInt(Arrays.copyOfRange(bytes, AS_NUMBER_LENGTH, AS_NUMBER_LENGTH + AS_NUMBER_LENGTH)));
76 * Parse Extended Community according to their type.
78 * @param bytes byte array to be parsed
79 * @return new Specific Extended Community
80 * @throws BGPDocumentedException if the type is not recognized
83 // FIXME: switch to return ExtendedCommunities with setType and subtype
84 public static ExtendedCommunity parseExtendedCommunity(final byte[] bytes) throws BGPDocumentedException {
85 final int type = UnsignedBytes.toInt(bytes[0]);
86 final int subType = UnsignedBytes.toInt(bytes[1]);
87 final byte[] value = ByteArray.subByte(bytes, TYPE_LENGTH, bytes.length - TYPE_LENGTH);
92 return new CRouteTargetExtendedCommunityBuilder().setRouteTargetExtendedCommunity(
93 new RouteTargetExtendedCommunityBuilder().setGlobalAdministrator(
94 new AsNumber(ByteArray.bytesToLong(ByteArray.subByte(value, 0, AS_NUMBER_LENGTH)))).setLocalAdministrator(
95 ByteArray.subByte(value, AS_NUMBER_LENGTH, AS_LOCAL_ADMIN_LENGTH)).build()).build();
96 } else if (subType == 3) {
97 return new CRouteOriginExtendedCommunityBuilder().setRouteOriginExtendedCommunity(
98 new RouteOriginExtendedCommunityBuilder().setGlobalAdministrator(
99 new AsNumber(ByteArray.bytesToLong(ByteArray.subByte(value, 0, AS_NUMBER_LENGTH)))).setLocalAdministrator(
100 ByteArray.subByte(value, AS_NUMBER_LENGTH, AS_LOCAL_ADMIN_LENGTH)).build()).build();
102 return new CAsSpecificExtendedCommunityBuilder().setAsSpecificExtendedCommunity(
103 new AsSpecificExtendedCommunityBuilder().setTransitive(false).setGlobalAdministrator(
104 new AsNumber(ByteArray.bytesToLong(ByteArray.subByte(value, 0, AS_NUMBER_LENGTH)))).setLocalAdministrator(
105 ByteArray.subByte(value, AS_NUMBER_LENGTH, AS_LOCAL_ADMIN_LENGTH)).build()).build();
108 return new CAsSpecificExtendedCommunityBuilder().setAsSpecificExtendedCommunity(
109 new AsSpecificExtendedCommunityBuilder().setTransitive(true).setGlobalAdministrator(
110 new AsNumber(ByteArray.bytesToLong(ByteArray.subByte(value, 0, AS_NUMBER_LENGTH)))).setLocalAdministrator(
111 ByteArray.subByte(value, AS_NUMBER_LENGTH, AS_LOCAL_ADMIN_LENGTH)).build()).build();
114 return new CRouteTargetExtendedCommunityBuilder().setRouteTargetExtendedCommunity(
115 new RouteTargetExtendedCommunityBuilder().setGlobalAdministrator(
116 new AsNumber(ByteArray.bytesToLong(ByteArray.subByte(value, 0, AS_NUMBER_LENGTH)))).setLocalAdministrator(
117 ByteArray.subByte(value, AS_NUMBER_LENGTH, AS_LOCAL_ADMIN_LENGTH)).build()).build();
118 } else if (subType == 3) {
119 return new CRouteOriginExtendedCommunityBuilder().setRouteOriginExtendedCommunity(
120 new RouteOriginExtendedCommunityBuilder().setGlobalAdministrator(
121 new AsNumber(ByteArray.bytesToLong(ByteArray.subByte(value, 0, AS_NUMBER_LENGTH)))).setLocalAdministrator(
122 ByteArray.subByte(value, AS_NUMBER_LENGTH, AS_LOCAL_ADMIN_LENGTH)).build()).build();
124 throw new BGPDocumentedException("Could not parse Extended Community subtype: " + subType, BGPError.OPT_ATTR_ERROR);
128 return new CRouteTargetExtendedCommunityBuilder().setRouteTargetExtendedCommunity(
129 new RouteTargetExtendedCommunityBuilder().setGlobalAdministrator(
130 new AsNumber(ByteArray.bytesToLong(ByteArray.subByte(value, 0, AS_NUMBER_LENGTH)))).setLocalAdministrator(
131 ByteArray.subByte(value, AS_NUMBER_LENGTH, AS_LOCAL_ADMIN_LENGTH)).build()).build();
132 } else if (subType == 3) {
133 return new CRouteOriginExtendedCommunityBuilder().setRouteOriginExtendedCommunity(
134 new RouteOriginExtendedCommunityBuilder().setGlobalAdministrator(
135 new AsNumber(ByteArray.bytesToLong(ByteArray.subByte(value, 0, AS_NUMBER_LENGTH)))).setLocalAdministrator(
136 ByteArray.subByte(value, AS_NUMBER_LENGTH, AS_LOCAL_ADMIN_LENGTH)).build()).build();
138 return new CInet4SpecificExtendedCommunityBuilder().setInet4SpecificExtendedCommunity(
139 new Inet4SpecificExtendedCommunityBuilder().setTransitive(false).setGlobalAdministrator(
140 Ipv4Util.addressForBytes(ByteArray.subByte(value, 0, 4))).setLocalAdministrator(
141 ByteArray.subByte(value, 4, 2)).build()).build();
144 return new CInet4SpecificExtendedCommunityBuilder().setInet4SpecificExtendedCommunity(
145 new Inet4SpecificExtendedCommunityBuilder().setTransitive(true).setGlobalAdministrator(
146 Ipv4Util.addressForBytes(ByteArray.subByte(value, 0, 4))).setLocalAdministrator(ByteArray.subByte(value, 4, 2)).build()).build();
148 return new COpaqueExtendedCommunityBuilder().setOpaqueExtendedCommunity(
149 new OpaqueExtendedCommunityBuilder().setTransitive(false).setValue(value).build()).build();
151 return new COpaqueExtendedCommunityBuilder().setOpaqueExtendedCommunity(
152 new OpaqueExtendedCommunityBuilder().setTransitive(true).setValue(value).build()).build();
154 throw new BGPDocumentedException("Could not parse Extended Community type: " + type, BGPError.OPT_ATTR_ERROR);