2 * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved.
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
8 package org.opendaylight.bgp.concepts;
10 import static com.google.common.base.Preconditions.checkState;
11 import static java.util.Objects.requireNonNull;
13 import com.google.common.annotations.VisibleForTesting;
14 import com.google.common.base.Preconditions;
15 import io.netty.buffer.ByteBuf;
16 import org.opendaylight.protocol.util.Ipv4Util;
17 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address;
18 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev180329.RdAs;
19 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev180329.RdIpv4;
20 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev180329.RdTwoOctetAs;
21 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev180329.RouteDistinguisher;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev180329.RouteDistinguisherBuilder;
23 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
24 import org.opendaylight.yangtools.yang.data.api.schema.DataContainerNode;
25 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
26 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNodes;
27 import org.slf4j.Logger;
28 import org.slf4j.LoggerFactory;
31 * Utility class for of RouteDistinguisher serialization and parsing.
32 * https://tools.ietf.org/html/rfc4364#section-4.2
34 public final class RouteDistinguisherUtil {
35 public static final int RD_LENGTH = 8;
37 private static final Logger LOG = LoggerFactory.getLogger(RouteDistinguisherUtil.class);
39 static final char SEPARATOR = ':';
41 private RouteDistinguisherUtil() {
46 * Serializes route distinguisher according to type and writes into ByteBuf.
48 public static void serializeRouteDistinquisher(final RouteDistinguisher distinguisher,
49 final ByteBuf byteAggregator) {
50 requireNonNull(distinguisher);
51 checkState(byteAggregator != null && byteAggregator.isWritable(RD_LENGTH),
52 "Cannot write Route Distinguisher to provided buffer.");
53 if (distinguisher.getRdTwoOctetAs() != null) {
54 serialize(byteAggregator, distinguisher.getRdTwoOctetAs());
55 } else if (distinguisher.getRdAs() != null) {
56 serialize(byteAggregator, distinguisher.getRdAs());
57 } else if (distinguisher.getRdIpv4() != null) {
58 serialize(byteAggregator, distinguisher.getRdIpv4());
60 LOG.warn("Unable to serialize Route Distinguisher. Invalid RD value found. RD={}", distinguisher);
64 private static void serialize(final ByteBuf buf, final RdAs as) {
65 final String value = as.getValue();
66 final int first = findSeparator(value, 0);
67 checkNoColon(value, first);
69 buf.writeShort(RDType.AS_4BYTE.value);
70 buf.writeInt(Integer.parseUnsignedInt(value.substring(0, first)));
71 buf.writeShort(Integer.parseUnsignedInt(value.substring(first + 1)));
74 private static void serialize(final ByteBuf buf, final RdTwoOctetAs as) {
75 final String value = as.getValue();
76 final int first = findSeparator(value, 0) + 1;
77 final int second = findSeparator(value, first);
78 checkNoColon(value, second);
80 buf.writeShort(RDType.AS_2BYTE.value);
81 buf.writeShort(Integer.parseUnsignedInt(value.substring(first, second)));
82 buf.writeInt(Integer.parseUnsignedInt(value.substring(second + 1)));
85 private static void serialize(final ByteBuf buf, final RdIpv4 ipv4) {
86 final String value = ipv4.getValue();
87 final int first = findSeparator(value, 0);
88 checkNoColon(value, first);
90 buf.writeShort(RDType.IPV4.value);
91 buf.writeBytes(Ipv4Util.bytesForAddress(new Ipv4Address(value.substring(0, first))));
92 buf.writeShort(Integer.parseUnsignedInt(value.substring(first + 1)));
95 private static int findSeparator(final String str, final int fromIndex) {
96 final int found = str.indexOf(SEPARATOR, fromIndex);
97 checkState(found != -1, "Invalid route distinguiser %s", str);
101 private static void checkNoColon(final String str, final int lastIndex) {
102 checkState(str.indexOf(SEPARATOR, lastIndex + 1) == -1, "Invalid route distinguiser %s", str);
106 * Parses three types of route distinguisher from given ByteBuf.
108 public static RouteDistinguisher parseRouteDistinguisher(final ByteBuf buffer) {
109 Preconditions.checkState(buffer != null && buffer.isReadable(RD_LENGTH),
110 "Cannot read Route Distinguisher from provided buffer.");
111 final int type = buffer.readUnsignedShort();
112 final RDType rdType = RDType.valueOf(type);
115 return new RouteDistinguisher(new RdTwoOctetAs(new StringBuilder()
118 .append(buffer.readUnsignedShort())
120 .append(buffer.readUnsignedInt())
123 return new RouteDistinguisher(new RdIpv4(new StringBuilder()
124 .append(Ipv4Util.addressForByteBuf(buffer).getValue())
126 .append(buffer.readUnsignedShort())
129 return new RouteDistinguisher(new RdAs(new StringBuilder()
130 .append(buffer.readUnsignedInt())
132 .append(buffer.readUnsignedShort())
135 // now that this RD type is not supported, we want to read the remain 6 bytes
136 // in order to get the byte index correct
137 final StringBuilder routeDistiguisher = new StringBuilder();
138 for (int i = 0; i < 6; i++) {
139 routeDistiguisher.append("0x").append(Integer.toHexString(buffer.readByte() & 0xFF)).append(' ');
141 LOG.debug("Invalid Route Distinguisher: type={}, rawRouteDistinguisherValue={}", type,
143 throw new IllegalArgumentException("Invalid Route Distinguisher type " + type);
147 public static RouteDistinguisher parseRouteDistinguisher(final String str) {
148 return str == null ? null : RouteDistinguisherBuilder.getDefaultInstance(str);
151 public static RouteDistinguisher parseRouteDistinguisher(final Object obj) {
152 if (obj instanceof String) {
153 return RouteDistinguisherBuilder.getDefaultInstance((String) obj);
154 } else if (obj instanceof RouteDistinguisher) {
155 return (RouteDistinguisher) obj;
161 public static RouteDistinguisher extractRouteDistinguisher(final DataContainerNode<?> route,
162 final NodeIdentifier rdNid) {
163 final NormalizedNode<?, ?> rdNode = NormalizedNodes.findNode(route, rdNid).orElse(null);
164 return rdNode == null ? null : parseRouteDistinguisher(rdNode.getValue());
167 private enum RDType {
173 public final int value;
175 RDType(final int val) {
179 static RDType valueOf(final int value) {
180 for (RDType type : values()) {
181 if (type.value == value) {