Fix junit dependencies in poms. Reuse existing from parent,
[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                 }
65                 if (Arrays.equals(bytes, new byte[] { (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0x01 })) {
66                         return CommunityUtil.NO_EXPORT;
67                 } else if (Arrays.equals(bytes, new byte[] { (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0x02 })) {
68                         return CommunityUtil.NO_ADVERTISE;
69                 } else if (Arrays.equals(bytes, new byte[] { (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0x03 })) {
70                         return CommunityUtil.NO_EXPORT_SUBCONFED;
71                 }
72                 return CommunityUtil.create((ByteArray.bytesToLong(Arrays.copyOfRange(bytes, 0, AS_NUMBER_LENGTH))),
73                                 ByteArray.bytesToInt(Arrays.copyOfRange(bytes, AS_NUMBER_LENGTH, AS_NUMBER_LENGTH + AS_NUMBER_LENGTH)));
74         }
75
76         /**
77          * Parse Extended Community according to their type.
78          * 
79          * @param bytes byte array to be parsed
80          * @return new Specific Extended Community
81          * @throws BGPDocumentedException if the type is not recognized
82          */
83         @VisibleForTesting
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: // 01000000
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: // 01000001
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: // 01000011
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 }