Code Clean Up
[bgpcep.git] / bgp / concepts / src / main / java / org / opendaylight / bgp / concepts / RouteDistinguisherUtil.java
1 /*
2  * Copyright (c) 2016 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.bgp.concepts;
9
10 import com.google.common.base.Preconditions;
11 import io.netty.buffer.ByteBuf;
12 import org.opendaylight.protocol.util.ByteBufWriteUtil;
13 import org.opendaylight.protocol.util.Ipv4Util;
14 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address;
15 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.RdAs;
16 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.RdIpv4;
17 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.RdTwoOctetAs;
18 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.RouteDistinguisher;
19 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.RouteDistinguisherBuilder;
20 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
21 import org.opendaylight.yangtools.yang.data.api.schema.DataContainerNode;
22 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
23 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNodes;
24 import org.slf4j.Logger;
25 import org.slf4j.LoggerFactory;
26
27 /**
28  * Utility class for of RouteDistinguisher serialization and parsing.
29  * https://tools.ietf.org/html/rfc4364#section-4.2
30  */
31 public final class RouteDistinguisherUtil {
32     private static final Logger LOG = LoggerFactory.getLogger(RouteDistinguisherUtil.class);
33
34     private enum RD_TYPE {
35         AS_2BYTE(0),
36         IPV4(1),
37         AS_4BYTE(2),
38         INVALID(-1);
39
40         public final int value;
41
42         RD_TYPE(int val) {
43             this.value = val;
44         }
45
46         public static RD_TYPE valueOf(final int value) {
47             for (RD_TYPE type : values()) {
48                 if (type.value == value) {
49                     return type;
50                 }
51             }
52             return INVALID;
53         }
54     }
55
56     private static final String SEPARATOR = ":";
57     public static final int RD_LENGTH = 8;
58
59     private RouteDistinguisherUtil() {
60         throw new UnsupportedOperationException();
61     }
62
63     /**
64      * Serializes route distinguisher according to type and writes into ByteBuf.
65      *
66      * @param distinguisher
67      * @param byteAggregator
68      */
69     public static void serializeRouteDistinquisher(final RouteDistinguisher distinguisher, final ByteBuf byteAggregator) {
70         Preconditions.checkNotNull(distinguisher);
71         Preconditions.checkState(byteAggregator != null && byteAggregator.isWritable(RD_LENGTH), "Cannot write Route Distinguisher to provided buffer.");
72         if (distinguisher.getRdTwoOctetAs() != null) {
73             final String[] values = distinguisher.getRdTwoOctetAs().getValue().split(SEPARATOR);
74             byteAggregator.writeShort(RD_TYPE.AS_2BYTE.value);
75             ByteBufWriteUtil.writeUnsignedShort(Integer.parseInt(values[1]), byteAggregator);
76             final long assignedNumber = Integer.parseUnsignedInt(values[2]);
77             ByteBufWriteUtil.writeUnsignedInt(assignedNumber, byteAggregator);
78         } else if (distinguisher.getRdAs() != null) {
79             final String[] values = distinguisher.getRdAs().getValue().split(SEPARATOR);
80             byteAggregator.writeShort(RD_TYPE.AS_4BYTE.value);
81             final long admin = Integer.parseUnsignedInt(values[0]);
82             ByteBufWriteUtil.writeUnsignedInt(admin, byteAggregator);
83             ByteBufWriteUtil.writeUnsignedShort(Integer.parseInt(values[1]), byteAggregator);
84         } else if (distinguisher.getRdIpv4() != null) {
85             final String[] values = distinguisher.getRdIpv4().getValue().split(SEPARATOR);
86             final Ipv4Address ip = new Ipv4Address(values[0]);
87             byteAggregator.writeShort(RD_TYPE.IPV4.value);
88             ByteBufWriteUtil.writeIpv4Address(ip, byteAggregator);
89             ByteBufWriteUtil.writeUnsignedShort(Integer.parseInt(values[1]), byteAggregator);
90         } else {
91             LOG.warn("Unable to serialize Route Distinguisher. Invalid RD value found. RD={}", distinguisher);
92         }
93     }
94
95     /**
96      * Parses three types of route distinguisher from given ByteBuf.
97      *
98      * @param buffer
99      * @return RouteDistinguisher
100      */
101     public static RouteDistinguisher parseRouteDistinguisher(final ByteBuf buffer) {
102         Preconditions.checkState(buffer != null && buffer.isReadable(RD_LENGTH), "Cannot read Route Distinguisher from provided buffer.");
103         final int type = buffer.readUnsignedShort();
104         final RD_TYPE rdType = RD_TYPE.valueOf(type);
105         final StringBuilder routeDistiguisher = new StringBuilder();
106         switch (rdType) {
107         case AS_2BYTE:
108             routeDistiguisher.append(type);
109             routeDistiguisher.append(SEPARATOR);
110             routeDistiguisher.append(buffer.readUnsignedShort());
111             routeDistiguisher.append(SEPARATOR);
112             routeDistiguisher.append(buffer.readUnsignedInt());
113             return new RouteDistinguisher(new RdTwoOctetAs(routeDistiguisher.toString()));
114         case IPV4:
115             routeDistiguisher.append(Ipv4Util.addressForByteBuf(buffer).getValue());
116             routeDistiguisher.append(SEPARATOR);
117             routeDistiguisher.append(buffer.readUnsignedShort());
118             return new RouteDistinguisher(new RdIpv4(routeDistiguisher.toString()));
119         case AS_4BYTE:
120             routeDistiguisher.append(buffer.readUnsignedInt());
121             routeDistiguisher.append(SEPARATOR);
122             routeDistiguisher.append(buffer.readUnsignedShort());
123             return new RouteDistinguisher(new RdAs(routeDistiguisher.toString()));
124         default:
125             // now that this RD type is not supported, we want to read the remain 6 bytes
126             // in order to get the byte index correct
127             for (int i = 0; i < 6; i++) {
128                 routeDistiguisher.append("0x").append(Integer.toHexString(buffer.readByte() & 0xFF)).append(" ");
129             }
130             LOG.debug("Invalid Route Distinguisher: type={}, rawRouteDistinguisherValue={}", type, routeDistiguisher.toString());
131             throw new IllegalArgumentException("Invalid Route Distinguisher type " + type);
132         }
133     }
134
135     public static RouteDistinguisher parseRouteDistinguisher(final String str) {
136         return str == null ? null : RouteDistinguisherBuilder.getDefaultInstance(str);
137     }
138
139     public static RouteDistinguisher parseRouteDistinguisher(final Object obj) {
140         if (obj instanceof String) {
141             return RouteDistinguisherBuilder.getDefaultInstance((String) obj);
142         } else if (obj instanceof RouteDistinguisher) {
143             return (RouteDistinguisher) obj;
144         } else {
145             return null;
146         }
147     }
148
149     public static RouteDistinguisher extractRouteDistinguisher(final DataContainerNode<?> route, final NodeIdentifier rdNid) {
150         final NormalizedNode<?, ?> rdNode = NormalizedNodes.findNode(route, rdNid).orNull();
151         if (rdNode != null) {
152             return parseRouteDistinguisher(rdNode.getValue());
153         }
154         return null;
155     }
156 }