Moved Ipv4Util and Ipv6Util from concepts to util
[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 package org.opendaylight.protocol.bgp.parser.impl.message.update;
9
10 import com.google.common.annotations.VisibleForTesting;
11 import com.google.common.primitives.UnsignedBytes;
12 import io.netty.buffer.ByteBuf;
13 import java.util.Arrays;
14 import org.opendaylight.protocol.bgp.parser.BGPDocumentedException;
15 import org.opendaylight.protocol.bgp.parser.BGPError;
16 import org.opendaylight.protocol.util.ByteArray;
17 import org.opendaylight.protocol.util.Ipv4Util;
18 import org.opendaylight.protocol.util.ReferenceCache;
19 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.path.attributes.ExtendedCommunities;
20 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.path.attributes.ExtendedCommunitiesBuilder;
21 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.Community;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.ShortAsNumber;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.extended.community.extended.community.AsSpecificExtendedCommunityCaseBuilder;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.extended.community.extended.community.Inet4SpecificExtendedCommunityCaseBuilder;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.extended.community.extended.community.OpaqueExtendedCommunityCaseBuilder;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.extended.community.extended.community.RouteOriginExtendedCommunityCaseBuilder;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.extended.community.extended.community.RouteTargetExtendedCommunityCaseBuilder;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.extended.community.extended.community.as.specific.extended.community._case.AsSpecificExtendedCommunityBuilder;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.extended.community.extended.community.inet4.specific.extended.community._case.Inet4SpecificExtendedCommunityBuilder;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.extended.community.extended.community.opaque.extended.community._case.OpaqueExtendedCommunityBuilder;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.extended.community.extended.community.route.origin.extended.community._case.RouteOriginExtendedCommunityBuilder;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.extended.community.extended.community.route.target.extended.community._case.RouteTargetExtendedCommunityBuilder;
33
34 /**
35  * Parser for Extended Communities Path Attribute.
36  */
37 public final class CommunitiesParser {
38
39     protected static final int EXTENDED_COMMUNITY_LENGTH = 8;
40
41     protected static final int COMMUNITY_LENGTH = 4;
42
43     private static final int AS_LOCAL_ADMIN_LENGTH = 4;
44
45     private static final int INET_LOCAL_ADMIN_LENGTH = 2;
46
47     protected static final short AS_TYPE_TRANS = 0;
48
49     protected static final short AS_TYPE_NON_TRANS = 40;
50
51     protected static final short INET_TYPE_TRANS = 1;
52
53     protected static final short INET_TYPE_NON_TRANS = 41;
54
55     protected static final short OPAQUE_TYPE_TRANS = 3;
56
57     protected static final short OPAQUE_TYPE_NON_TRANS = 43;
58
59     protected static final short ROUTE_TYPE_ONLY = 2;
60
61     protected static final short ROUTE_TARGET_SUBTYPE = 2;
62
63     protected static final short ROUTE_ORIGIN_SUBTYPE = 3;
64
65     private static final byte[] NO_EXPORT = new byte[] { (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0x01 };
66
67     private static final byte[] NO_ADVERTISE = new byte[] { (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0x02 };
68
69     private static final byte[] NO_EXPORT_SUBCONFED = new byte[] { (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0x03 };
70
71     private CommunitiesParser() {
72
73     }
74
75     /**
76      * Parse known Community, if unknown, a new one will be created.
77      *
78      * @param refCache
79      *
80      * @param bytes byte array to be parsed
81      * @return new Community
82      * @throws BGPDocumentedException
83      */
84     static Community parseCommunity(final ReferenceCache refCache, final ByteBuf buffer) throws BGPDocumentedException {
85         if (buffer.readableBytes() != COMMUNITY_LENGTH) {
86             throw new BGPDocumentedException("Community with wrong length: " + buffer.readableBytes(), BGPError.OPT_ATTR_ERROR);
87         }
88         byte[] body = ByteArray.getBytes(buffer, COMMUNITY_LENGTH);
89         if (Arrays.equals(body, NO_EXPORT)) {
90             return CommunityUtil.NO_EXPORT;
91         } else if (Arrays.equals(body, NO_ADVERTISE)) {
92             return CommunityUtil.NO_ADVERTISE;
93         } else if (Arrays.equals(body, NO_EXPORT_SUBCONFED)) {
94             return CommunityUtil.NO_EXPORT_SUBCONFED;
95         }
96         return CommunityUtil.create(refCache, buffer.readUnsignedShort(), buffer.readUnsignedShort());
97     }
98
99     /**
100      * Parse Extended Community according to their type.
101      *
102      * @param bytes byte array to be parsed
103      * @return new Specific Extended Community
104      * @throws BGPDocumentedException if the type is not recognized
105      */
106     @VisibleForTesting
107     public static ExtendedCommunities parseExtendedCommunity(final ReferenceCache refCache, final ByteBuf buffer)
108             throws BGPDocumentedException {
109         final int type = UnsignedBytes.toInt(buffer.readByte());
110         final int subType = UnsignedBytes.toInt(buffer.readByte());
111
112         final ExtendedCommunitiesBuilder comm = new ExtendedCommunitiesBuilder();
113         switch (type) {
114         case AS_TYPE_TRANS:
115             comm.setCommType(AS_TYPE_TRANS);
116             if (subType == ROUTE_TARGET_SUBTYPE) {
117                 comm.setCommSubType(ROUTE_TARGET_SUBTYPE).setExtendedCommunity(
118                         new RouteTargetExtendedCommunityCaseBuilder().setRouteTargetExtendedCommunity(
119                                 new RouteTargetExtendedCommunityBuilder().setGlobalAdministrator(
120                                         new ShortAsNumber((long) buffer.readUnsignedShort())).setLocalAdministrator(
121                                         ByteArray.readBytes(buffer, AS_LOCAL_ADMIN_LENGTH)).build()).build());
122             } else if (subType == ROUTE_ORIGIN_SUBTYPE) {
123                 comm.setCommSubType(ROUTE_ORIGIN_SUBTYPE).setExtendedCommunity(
124                         new RouteOriginExtendedCommunityCaseBuilder().setRouteOriginExtendedCommunity(
125                                 new RouteOriginExtendedCommunityBuilder().setGlobalAdministrator(
126                                         new ShortAsNumber((long) buffer.readUnsignedShort())).setLocalAdministrator(
127                                         ByteArray.readBytes(buffer, AS_LOCAL_ADMIN_LENGTH)).build()).build());
128             } else {
129                 comm.setExtendedCommunity(new AsSpecificExtendedCommunityCaseBuilder().setAsSpecificExtendedCommunity(
130                         new AsSpecificExtendedCommunityBuilder().setTransitive(false).setGlobalAdministrator(
131                                 new ShortAsNumber((long) buffer.readUnsignedShort())).setLocalAdministrator(
132                                 ByteArray.readBytes(buffer, AS_LOCAL_ADMIN_LENGTH)).build()).build());
133             }
134             break;
135         case AS_TYPE_NON_TRANS:
136             comm.setCommType(AS_TYPE_NON_TRANS).setExtendedCommunity(
137                     new AsSpecificExtendedCommunityCaseBuilder().setAsSpecificExtendedCommunity(
138                             new AsSpecificExtendedCommunityBuilder().setTransitive(true).setGlobalAdministrator(
139                                     new ShortAsNumber((long) buffer.readUnsignedShort())).setLocalAdministrator(
140                                     ByteArray.readBytes(buffer, AS_LOCAL_ADMIN_LENGTH)).build()).build());
141             break;
142         case ROUTE_TYPE_ONLY:
143             comm.setCommType(ROUTE_TYPE_ONLY);
144             if (subType == ROUTE_TARGET_SUBTYPE) {
145                 comm.setCommSubType(ROUTE_TARGET_SUBTYPE).setExtendedCommunity(
146                         new RouteTargetExtendedCommunityCaseBuilder().setRouteTargetExtendedCommunity(
147                                 new RouteTargetExtendedCommunityBuilder().setGlobalAdministrator(
148                                         new ShortAsNumber((long) buffer.readUnsignedShort())).setLocalAdministrator(
149                                         ByteArray.readBytes(buffer, AS_LOCAL_ADMIN_LENGTH)).build()).build());
150             } else if (subType == ROUTE_ORIGIN_SUBTYPE) {
151                 comm.setCommSubType(ROUTE_ORIGIN_SUBTYPE).setExtendedCommunity(
152                         new RouteOriginExtendedCommunityCaseBuilder().setRouteOriginExtendedCommunity(
153                                 new RouteOriginExtendedCommunityBuilder().setGlobalAdministrator(
154                                         new ShortAsNumber((long) buffer.readUnsignedShort())).setLocalAdministrator(
155                                         ByteArray.readBytes(buffer, AS_LOCAL_ADMIN_LENGTH)).build()).build());
156             } else {
157                 throw new BGPDocumentedException("Could not parse Extended Community subtype: " + subType, BGPError.OPT_ATTR_ERROR);
158             }
159             break;
160         case INET_TYPE_TRANS:
161             comm.setCommType(INET_TYPE_TRANS);
162             if (subType == ROUTE_TARGET_SUBTYPE) {
163                 comm.setCommSubType(ROUTE_TARGET_SUBTYPE).setExtendedCommunity(
164                         new RouteTargetExtendedCommunityCaseBuilder().setRouteTargetExtendedCommunity(
165                                 new RouteTargetExtendedCommunityBuilder().setGlobalAdministrator(
166                                         new ShortAsNumber((long) buffer.readUnsignedShort())).setLocalAdministrator(
167                                         ByteArray.readBytes(buffer, AS_LOCAL_ADMIN_LENGTH)).build()).build());
168             } else if (subType == ROUTE_ORIGIN_SUBTYPE) {
169                 comm.setCommSubType(ROUTE_ORIGIN_SUBTYPE).setExtendedCommunity(
170                         new RouteOriginExtendedCommunityCaseBuilder().setRouteOriginExtendedCommunity(
171                                 new RouteOriginExtendedCommunityBuilder().setGlobalAdministrator(
172                                         new ShortAsNumber((long) buffer.readUnsignedShort())).setLocalAdministrator(
173                                         ByteArray.readBytes(buffer, AS_LOCAL_ADMIN_LENGTH)).build()).build());
174             } else {
175                 comm.setExtendedCommunity(new Inet4SpecificExtendedCommunityCaseBuilder().setInet4SpecificExtendedCommunity(
176                         new Inet4SpecificExtendedCommunityBuilder().setTransitive(false).setGlobalAdministrator(
177                                 Ipv4Util.addressForBytes(ByteArray.readBytes(buffer, Ipv4Util.IP4_LENGTH))).setLocalAdministrator(
178                                 ByteArray.readBytes(buffer, INET_LOCAL_ADMIN_LENGTH)).build()).build());
179             }
180             break;
181         case INET_TYPE_NON_TRANS:
182             comm.setCommType(INET_TYPE_NON_TRANS).setExtendedCommunity(
183                     new Inet4SpecificExtendedCommunityCaseBuilder().setInet4SpecificExtendedCommunity(
184                             new Inet4SpecificExtendedCommunityBuilder().setTransitive(true).setGlobalAdministrator(
185                                     Ipv4Util.addressForBytes(ByteArray.readBytes(buffer, Ipv4Util.IP4_LENGTH))).setLocalAdministrator(
186                                     ByteArray.readBytes(buffer, INET_LOCAL_ADMIN_LENGTH)).build()).build());
187             break;
188         case OPAQUE_TYPE_TRANS:
189             comm.setCommType(OPAQUE_TYPE_TRANS).setExtendedCommunity(
190                     new OpaqueExtendedCommunityCaseBuilder().setOpaqueExtendedCommunity(
191                             new OpaqueExtendedCommunityBuilder().setTransitive(false).setValue(ByteArray.readAllBytes(buffer)).build()).build());
192             break;
193         case OPAQUE_TYPE_NON_TRANS:
194             comm.setCommType(OPAQUE_TYPE_NON_TRANS).setExtendedCommunity(
195                     new OpaqueExtendedCommunityCaseBuilder().setOpaqueExtendedCommunity(
196                             new OpaqueExtendedCommunityBuilder().setTransitive(true).setValue(ByteArray.readAllBytes(buffer)).build()).build());
197             break;
198         default:
199             throw new BGPDocumentedException("Could not parse Extended Community type: " + type, BGPError.OPT_ATTR_ERROR);
200         }
201
202         return comm.build();
203     }
204 }