Merge "Activate augment"
[bgpcep.git] / bgp / parser-impl / src / main / java / org / opendaylight / protocol / bgp / parser / impl / message / update / CommunitiesParser.java
1 /*
2  * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
3  *
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
7  */
8
9 package org.opendaylight.protocol.bgp.parser.impl.message.update;
10
11 import java.util.Arrays;
12
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;
30
31 import com.google.common.annotations.VisibleForTesting;
32 import com.google.common.primitives.UnsignedBytes;
33
34 /**
35  * Parser for Extended Communities Path Attribute.
36  */
37 public final class CommunitiesParser {
38
39         public static final int EXTENDED_COMMUNITY_LENGTH = 8;
40
41         public static final int COMMUNITY_LENGTH = 4;
42
43         private static final int TYPE_LENGTH = 2;
44
45         private static final int AS_NUMBER_LENGTH = 2;
46
47         private static final int AS_LOCAL_ADMIN_LENGTH = 4;
48
49         private CommunitiesParser() {
50
51         }
52
53         /**
54          * Parse known Community, if unknown, a new one will be created.
55          * 
56          * @param bytes byte array to be parsed
57          * @return new Community
58          * @throws BGPDocumentedException
59          */
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);
63                 }
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;
70                 }
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)));
73         }
74
75         /**
76          * Parse Extended Community according to their type.
77          * 
78          * @param bytes byte array to be parsed
79          * @return new Specific Extended Community
80          * @throws BGPDocumentedException if the type is not recognized
81          */
82         @VisibleForTesting
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);
88
89                 switch (type) {
90                 case 0:
91                         if (subType == 2) {
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();
101                         } else {
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();
106                         }
107                 case 40:
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();
112                 case 2:
113                         if (subType == 2) {
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();
123                         } else {
124                                 throw new BGPDocumentedException("Could not parse Extended Community subtype: " + subType, BGPError.OPT_ATTR_ERROR);
125                         }
126                 case 1:
127                         if (subType == 2) {
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();
137                         } else {
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();
142                         }
143                 case 41:
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();
147                 case 3:
148                         return new COpaqueExtendedCommunityBuilder().setOpaqueExtendedCommunity(
149                                         new OpaqueExtendedCommunityBuilder().setTransitive(false).setValue(value).build()).build();
150                 case 43:
151                         return new COpaqueExtendedCommunityBuilder().setOpaqueExtendedCommunity(
152                                         new OpaqueExtendedCommunityBuilder().setTransitive(true).setValue(value).build()).build();
153                 default:
154                         throw new BGPDocumentedException("Could not parse Extended Community type: " + type, BGPError.OPT_ATTR_ERROR);
155                 }
156         }
157 }