Merge "BUG-45 : migrated Extended Communities path attribute to generated source...
[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.bgp.parser.impl.CommunityUtil;
16 import org.opendaylight.protocol.concepts.Ipv4Util;
17 import org.opendaylight.protocol.util.ByteArray;
18 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.AsNumber;
19 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.Community;
20 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.extended.community.ExtendedCommunity;
21 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.extended.community.extended.community.CAsSpecificExtendedCommunityBuilder;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.extended.community.extended.community.CInet4SpecificExtendedCommunityBuilder;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.extended.community.extended.community.COpaqueExtendedCommunityBuilder;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.extended.community.extended.community.CRouteOriginExtendedCommunityBuilder;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.extended.community.extended.community.CRouteTargetExtendedCommunityBuilder;
26 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;
27 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;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.extended.community.extended.community.c.opaque.extended.community.OpaqueExtendedCommunityBuilder;
29 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;
30 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
32 import com.google.common.annotations.VisibleForTesting;
33 import com.google.common.primitives.UnsignedBytes;
34
35 /**
36  * Parser for Extended Communities Path Attribute.
37  */
38 public class CommunitiesParser {
39
40         public static final int EXTENDED_COMMUNITY_LENGTH = 8; // bytes
41
42         public static final int COMMUNITY_LENGTH = 4; // bytes
43
44         private static final int TYPE_LENGTH = 2; // bytes
45
46         private static final int AS_NUMBER_LENGTH = 2; // bytes
47
48         private static final int AS_LOCAL_ADMIN_LENGTH = 4; // bytes
49
50         private CommunitiesParser() {
51
52         }
53
54         /**
55          * Parse known Community, if unknown, a new one will be created.
56          * 
57          * @param bytes byte array to be parsed
58          * @return new Community
59          * @throws BGPDocumentedException
60          */
61         static Community parseCommunity(final byte[] bytes) throws BGPDocumentedException {
62                 if (bytes.length != COMMUNITY_LENGTH)
63                         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;
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         public static ExtendedCommunity parseExtendedCommunity(final byte[] bytes) throws BGPDocumentedException {
84                 final int type = UnsignedBytes.toInt(bytes[0]);
85                 final int subType = UnsignedBytes.toInt(bytes[1]);
86                 final byte[] value = ByteArray.subByte(bytes, TYPE_LENGTH, bytes.length - TYPE_LENGTH);
87
88                 switch (type) {
89                 case 0:
90                         if (subType == 2) {
91                                 return new CRouteTargetExtendedCommunityBuilder().setRouteTargetExtendedCommunity(
92                                                 new RouteTargetExtendedCommunityBuilder().setGlobalAdministrator(
93                                                                 new AsNumber(ByteArray.bytesToLong(ByteArray.subByte(value, 0, AS_NUMBER_LENGTH)))).setLocalAdministrator(
94                                                                 ByteArray.subByte(value, AS_NUMBER_LENGTH, AS_LOCAL_ADMIN_LENGTH)).build()).build();
95                         } else if (subType == 3) {
96                                 return new CRouteOriginExtendedCommunityBuilder().setRouteOriginExtendedCommunity(
97                                                 new RouteOriginExtendedCommunityBuilder().setGlobalAdministrator(
98                                                                 new AsNumber(ByteArray.bytesToLong(ByteArray.subByte(value, 0, AS_NUMBER_LENGTH)))).setLocalAdministrator(
99                                                                 ByteArray.subByte(value, AS_NUMBER_LENGTH, AS_LOCAL_ADMIN_LENGTH)).build()).build();
100                         } else
101                                 return new CAsSpecificExtendedCommunityBuilder().setAsSpecificExtendedCommunity(
102                                                 new AsSpecificExtendedCommunityBuilder().setTransitive(false).setGlobalAdministrator(
103                                                                 new AsNumber(ByteArray.bytesToLong(ByteArray.subByte(value, 0, AS_NUMBER_LENGTH)))).setLocalAdministrator(
104                                                                 ByteArray.subByte(value, AS_NUMBER_LENGTH, AS_LOCAL_ADMIN_LENGTH)).build()).build();
105                 case 40: // 01000000
106                         return new CAsSpecificExtendedCommunityBuilder().setAsSpecificExtendedCommunity(
107                                         new AsSpecificExtendedCommunityBuilder().setTransitive(true).setGlobalAdministrator(
108                                                         new AsNumber(ByteArray.bytesToLong(ByteArray.subByte(value, 0, AS_NUMBER_LENGTH)))).setLocalAdministrator(
109                                                         ByteArray.subByte(value, AS_NUMBER_LENGTH, AS_LOCAL_ADMIN_LENGTH)).build()).build();
110                 case 2:
111                         if (subType == 2) {
112                                 return new CRouteTargetExtendedCommunityBuilder().setRouteTargetExtendedCommunity(
113                                                 new RouteTargetExtendedCommunityBuilder().setGlobalAdministrator(
114                                                                 new AsNumber(ByteArray.bytesToLong(ByteArray.subByte(value, 0, AS_NUMBER_LENGTH)))).setLocalAdministrator(
115                                                                 ByteArray.subByte(value, AS_NUMBER_LENGTH, AS_LOCAL_ADMIN_LENGTH)).build()).build();
116                         } else if (subType == 3) {
117                                 return new CRouteOriginExtendedCommunityBuilder().setRouteOriginExtendedCommunity(
118                                                 new RouteOriginExtendedCommunityBuilder().setGlobalAdministrator(
119                                                                 new AsNumber(ByteArray.bytesToLong(ByteArray.subByte(value, 0, AS_NUMBER_LENGTH)))).setLocalAdministrator(
120                                                                 ByteArray.subByte(value, AS_NUMBER_LENGTH, AS_LOCAL_ADMIN_LENGTH)).build()).build();
121                         } else
122                                 throw new BGPDocumentedException("Could not parse Extended Community subtype: " + subType, BGPError.OPT_ATTR_ERROR);
123                 case 1:
124                         if (subType == 2) {
125                                 return new CRouteTargetExtendedCommunityBuilder().setRouteTargetExtendedCommunity(
126                                                 new RouteTargetExtendedCommunityBuilder().setGlobalAdministrator(
127                                                                 new AsNumber(ByteArray.bytesToLong(ByteArray.subByte(value, 0, AS_NUMBER_LENGTH)))).setLocalAdministrator(
128                                                                 ByteArray.subByte(value, AS_NUMBER_LENGTH, AS_LOCAL_ADMIN_LENGTH)).build()).build();
129                         } else if (subType == 3) {
130                                 return new CRouteOriginExtendedCommunityBuilder().setRouteOriginExtendedCommunity(
131                                                 new RouteOriginExtendedCommunityBuilder().setGlobalAdministrator(
132                                                                 new AsNumber(ByteArray.bytesToLong(ByteArray.subByte(value, 0, AS_NUMBER_LENGTH)))).setLocalAdministrator(
133                                                                 ByteArray.subByte(value, AS_NUMBER_LENGTH, AS_LOCAL_ADMIN_LENGTH)).build()).build();
134                         } else
135                                 return new CInet4SpecificExtendedCommunityBuilder().setInet4SpecificExtendedCommunity(
136                                                 new Inet4SpecificExtendedCommunityBuilder().setTransitive(false).setGlobalAdministrator(
137                                                                 Ipv4Util.addressForBytes(ByteArray.subByte(value, 0, 4))).setLocalAdministrator(
138                                                                 ByteArray.subByte(value, 4, 2)).build()).build();
139                 case 41: // 01000001
140                         return new CInet4SpecificExtendedCommunityBuilder().setInet4SpecificExtendedCommunity(
141                                         new Inet4SpecificExtendedCommunityBuilder().setTransitive(true).setGlobalAdministrator(
142                                                         Ipv4Util.addressForBytes(ByteArray.subByte(value, 0, 4))).setLocalAdministrator(ByteArray.subByte(value, 4, 2)).build()).build();
143                 case 3:
144                         return new COpaqueExtendedCommunityBuilder().setOpaqueExtendedCommunity(
145                                         new OpaqueExtendedCommunityBuilder().setTransitive(false).setValue(value).build()).build();
146                 case 43: // 01000011
147                         return new COpaqueExtendedCommunityBuilder().setOpaqueExtendedCommunity(
148                                         new OpaqueExtendedCommunityBuilder().setTransitive(true).setValue(value).build()).build();
149                 default:
150                         throw new BGPDocumentedException("Could not parse Extended Community type: " + type, BGPError.OPT_ATTR_ERROR);
151                 }
152         }
153 }