org.opendaylight.bgp.concepts.RouteDistinguisherUtil.java Source code

Java tutorial

Introduction

Here is the source code for org.opendaylight.bgp.concepts.RouteDistinguisherUtil.java

Source

/*
 * Copyright (c) 2016 Cisco Systems, Inc. and others.  All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
 * and is available at http://www.eclipse.org/legal/epl-v10.html
 */
package org.opendaylight.bgp.concepts;

import com.google.common.base.Preconditions;
import io.netty.buffer.ByteBuf;
import org.opendaylight.protocol.util.ByteBufWriteUtil;
import org.opendaylight.protocol.util.Ipv4Util;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.RdAs;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.RdIpv4;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.RdTwoOctetAs;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.RouteDistinguisher;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.RouteDistinguisherBuilder;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
import org.opendaylight.yangtools.yang.data.api.schema.DataContainerNode;
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNodes;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Utility class for of RouteDistinguisher serialization and parsing.
 * https://tools.ietf.org/html/rfc4364#section-4.2
 */
public final class RouteDistinguisherUtil {
    private static final Logger LOG = LoggerFactory.getLogger(RouteDistinguisherUtil.class);

    private enum RD_TYPE {
        AS_2BYTE(0), IPV4(1), AS_4BYTE(2), INVALID(-1);

        public final int value;

        RD_TYPE(int val) {
            value = val;
        }

        public static RD_TYPE valueOf(final int value) {
            for (RD_TYPE type : values()) {
                if (type.value == value) {
                    return type;
                }
            }
            return INVALID;
        }
    }

    private static final String SEPARATOR = ":";
    public static final int RD_LENGTH = 8;

    private RouteDistinguisherUtil() {
        throw new UnsupportedOperationException();
    }

    /**
     * Serializes route distinguisher according to type and writes into ByteBuf.
     *
     * @param distinguisher
     * @param byteAggregator
     */
    public static void serializeRouteDistinquisher(final RouteDistinguisher distinguisher,
            final ByteBuf byteAggregator) {
        Preconditions.checkNotNull(distinguisher);
        Preconditions.checkState(byteAggregator != null && byteAggregator.isWritable(RD_LENGTH),
                "Cannot write Route Distinguisher to provided buffer.");
        if (distinguisher.getRdTwoOctetAs() != null) {
            final String[] values = distinguisher.getRdTwoOctetAs().getValue().split(SEPARATOR);
            byteAggregator.writeShort(RD_TYPE.AS_2BYTE.value);
            ByteBufWriteUtil.writeUnsignedShort(Integer.parseInt(values[1]), byteAggregator);
            final long assignedNumber = Integer.parseUnsignedInt(values[2]);
            ByteBufWriteUtil.writeUnsignedInt(assignedNumber, byteAggregator);
        } else if (distinguisher.getRdAs() != null) {
            final String[] values = distinguisher.getRdAs().getValue().split(SEPARATOR);
            byteAggregator.writeShort(RD_TYPE.AS_4BYTE.value);
            final long admin = Integer.parseUnsignedInt(values[0]);
            ByteBufWriteUtil.writeUnsignedInt(admin, byteAggregator);
            ByteBufWriteUtil.writeUnsignedShort(Integer.parseInt(values[1]), byteAggregator);
        } else if (distinguisher.getRdIpv4() != null) {
            final String[] values = distinguisher.getRdIpv4().getValue().split(SEPARATOR);
            final Ipv4Address ip = new Ipv4Address(values[0]);
            byteAggregator.writeShort(RD_TYPE.IPV4.value);
            ByteBufWriteUtil.writeIpv4Address(ip, byteAggregator);
            ByteBufWriteUtil.writeUnsignedShort(Integer.parseInt(values[1]), byteAggregator);
        } else {
            LOG.warn("Unable to serialize Route Distinguisher. Invalid RD value found. RD={}", distinguisher);
        }
    }

    /**
     * Parses three types of route distinguisher from given ByteBuf.
     *
     * @param buffer
     * @return RouteDistinguisher
     */
    public static RouteDistinguisher parseRouteDistinguisher(final ByteBuf buffer) {
        Preconditions.checkState(buffer != null && buffer.isReadable(RD_LENGTH),
                "Cannot read Route Distinguisher from provided buffer.");
        final int type = buffer.readUnsignedShort();
        final RD_TYPE rdType = RD_TYPE.valueOf(type);
        final StringBuilder routeDistiguisher = new StringBuilder();
        switch (rdType) {
        case AS_2BYTE:
            routeDistiguisher.append(type);
            routeDistiguisher.append(SEPARATOR);
            routeDistiguisher.append(buffer.readUnsignedShort());
            routeDistiguisher.append(SEPARATOR);
            routeDistiguisher.append(buffer.readUnsignedInt());
            return new RouteDistinguisher(new RdTwoOctetAs(routeDistiguisher.toString()));
        case IPV4:
            routeDistiguisher.append(Ipv4Util.addressForByteBuf(buffer).getValue());
            routeDistiguisher.append(SEPARATOR);
            routeDistiguisher.append(buffer.readUnsignedShort());
            return new RouteDistinguisher(new RdIpv4(routeDistiguisher.toString()));
        case AS_4BYTE:
            routeDistiguisher.append(buffer.readUnsignedInt());
            routeDistiguisher.append(SEPARATOR);
            routeDistiguisher.append(buffer.readUnsignedShort());
            return new RouteDistinguisher(new RdAs(routeDistiguisher.toString()));
        default:
            // now that this RD type is not supported, we want to read the remain 6 bytes
            // in order to get the byte index correct
            for (int i = 0; i < 6; i++) {
                routeDistiguisher.append("0x").append(Integer.toHexString(buffer.readByte() & 0xFF)).append(" ");
            }
            LOG.debug("Invalid Route Distinguisher: type={}, rawRouteDistinguisherValue={}", type,
                    routeDistiguisher.toString());
            throw new IllegalArgumentException("Invalid Route Distinguisher type " + type);
        }
    }

    public static RouteDistinguisher parseRouteDistinguisher(final String str) {
        return str == null ? null : RouteDistinguisherBuilder.getDefaultInstance(str);
    }

    public static RouteDistinguisher parseRouteDistinguisher(final Object obj) {
        if (obj instanceof String) {
            return RouteDistinguisherBuilder.getDefaultInstance((String) obj);
        } else if (obj instanceof RouteDistinguisher) {
            return (RouteDistinguisher) obj;
        } else {
            return null;
        }
    }

    public static RouteDistinguisher extractRouteDistinguisher(final DataContainerNode<?> route,
            final NodeIdentifier rdNid) {
        final NormalizedNode<?, ?> rdNode = NormalizedNodes.findNode(route, rdNid).orNull();
        if (rdNode != null) {
            return parseRouteDistinguisher(rdNode.getValue());
        }
        return null;
    }
}