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