org.opendaylight.protocol.bgp.linkstate.attribute.sr.BindingSidLabelParser.java Source code

Java tutorial

Introduction

Here is the source code for org.opendaylight.protocol.bgp.linkstate.attribute.sr.BindingSidLabelParser.java

Source

/*
 * Copyright (c) 2015 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.protocol.bgp.linkstate.attribute.sr;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import java.util.ArrayList;
import java.util.List;
import org.opendaylight.protocol.bgp.linkstate.attribute.PrefixAttributesParser;
import org.opendaylight.protocol.bgp.linkstate.attribute.sr.SidLabelIndexParser.Size;
import org.opendaylight.protocol.bgp.linkstate.spi.TlvUtil;
import org.opendaylight.protocol.util.BitArray;
import org.opendaylight.protocol.util.Ipv4Util;
import org.opendaylight.protocol.util.Ipv6Util;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Address;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv6Address;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.ProtocolId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.prefix.state.SrBindingSidLabels;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.prefix.state.SrBindingSidLabelsBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.prefix.state.SrPrefix;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev151014.Weight;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev151014.binding.sid.tlv.BindingSubTlvs;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev151014.binding.sid.tlv.BindingSubTlvsBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev151014.binding.sid.tlv.Flags;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev151014.binding.sid.tlv.flags.IsisBindingFlagsCase;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev151014.binding.sid.tlv.flags.IsisBindingFlagsCaseBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev151014.binding.sid.tlv.flags.OspfBindingFlagsCase;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev151014.binding.sid.tlv.flags.OspfBindingFlagsCaseBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev151014.binding.sub.tlvs.BindingSubTlv;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev151014.binding.sub.tlvs.binding.sub.tlv.EroMetricCase;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev151014.binding.sub.tlvs.binding.sub.tlv.EroMetricCaseBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev151014.binding.sub.tlvs.binding.sub.tlv.Ipv4EroBackupCase;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev151014.binding.sub.tlvs.binding.sub.tlv.Ipv4EroBackupCaseBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev151014.binding.sub.tlvs.binding.sub.tlv.Ipv4EroCase;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev151014.binding.sub.tlvs.binding.sub.tlv.Ipv4EroCaseBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev151014.binding.sub.tlvs.binding.sub.tlv.Ipv6EroBackupCase;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev151014.binding.sub.tlvs.binding.sub.tlv.Ipv6EroBackupCaseBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev151014.binding.sub.tlvs.binding.sub.tlv.Ipv6EroCase;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev151014.binding.sub.tlvs.binding.sub.tlv.Ipv6EroCaseBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev151014.binding.sub.tlvs.binding.sub.tlv.PrefixSidCase;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev151014.binding.sub.tlvs.binding.sub.tlv.PrefixSidCaseBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev151014.binding.sub.tlvs.binding.sub.tlv.SidLabelCase;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev151014.binding.sub.tlvs.binding.sub.tlv.SidLabelCaseBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev151014.binding.sub.tlvs.binding.sub.tlv.UnnumberedInterfaceIdBackupEroCase;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev151014.binding.sub.tlvs.binding.sub.tlv.UnnumberedInterfaceIdBackupEroCaseBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev151014.binding.sub.tlvs.binding.sub.tlv.UnnumberedInterfaceIdEroCase;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev151014.binding.sub.tlvs.binding.sub.tlv.UnnumberedInterfaceIdEroCaseBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev151014.sid.label.index.SidLabelIndex;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.network.concepts.rev131125.TeMetric;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public final class BindingSidLabelParser {

    private static final Logger LOG = LoggerFactory.getLogger(BindingSidLabelParser.class);

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

    /* Flags */
    private static final int FLAGS_SIZE = 8;
    private static final int AFI = 0;
    private static final int MIRROR_CONTEXT = 1;
    private static final int MIRROR_CONTEXT_OSPF = 0;
    private static final int SPREAD_TLV = 2;
    private static final int LEAKED = 3;
    private static final int ATTACHED = 4;
    private static final int LOOSE = 0;

    /* SID Label Tlv types */
    private static final int ERO_METRIC = 1162;
    private static final int ERO_IPV4 = 1163;
    private static final int ERO_IPV6 = 1164;
    private static final int UNNUMBERED_ERO = 1165;
    private static final int BACKUP_ERO_IPV4 = 1166;
    private static final int BACKUP_ERO_IPV6 = 1167;
    private static final int BACKUP_UNNUMBERED_ERO = 1168;

    private static final int RESERVED_BINDING_SID = 2;
    private static final int RESERVED_ERO = 3;

    public static SrBindingSidLabels parseBindingSidLabel(final ByteBuf buffer, final ProtocolId protocolId) {
        final SrBindingSidLabelsBuilder bindingSid = new SrBindingSidLabelsBuilder();
        bindingSid.setWeight(new Weight(buffer.readUnsignedByte()));
        final BitArray flags = BitArray.valueOf(buffer, FLAGS_SIZE);
        bindingSid.setFlags(parseBindingSidFlags(flags, protocolId));
        buffer.skipBytes(RESERVED_BINDING_SID);
        bindingSid.setBindingSubTlvs(parseBindingSubTlvs(buffer, protocolId));
        return bindingSid.build();
    }

    private static Flags parseBindingSidFlags(final BitArray flags, final ProtocolId protocol) {
        if (protocol.equals(ProtocolId.IsisLevel1) || protocol.equals(ProtocolId.IsisLevel2)) {
            return new IsisBindingFlagsCaseBuilder().setAddressFamily(flags.get(AFI))
                    .setMirrorContext(flags.get(MIRROR_CONTEXT)).setSpreadTlv(flags.get(SPREAD_TLV))
                    .setLeakedFromLevel2(flags.get(LEAKED)).setAttachedFlag(flags.get(ATTACHED)).build();
        } else if (protocol.equals(ProtocolId.Ospf)) {
            return new OspfBindingFlagsCaseBuilder().setMirroring(flags.get(MIRROR_CONTEXT_OSPF)).build();
        }
        return null;
    }

    private static List<BindingSubTlvs> parseBindingSubTlvs(final ByteBuf buffer, final ProtocolId protocolId) {
        final List<BindingSubTlvs> subTlvs = new ArrayList<BindingSubTlvs>();
        while (buffer.isReadable()) {
            final int type = buffer.readUnsignedShort();
            final int length = buffer.readUnsignedShort();
            final ByteBuf slice = buffer.readSlice(length);
            final BindingSubTlvsBuilder builder = new BindingSubTlvsBuilder();
            parseSubTlv(type, slice, builder, protocolId);
            subTlvs.add(builder.build());
        }
        return subTlvs;
    }

    private static void parseSubTlv(final int type, final ByteBuf slice, final BindingSubTlvsBuilder builder,
            final ProtocolId protocolId) {
        switch (type) {
        case SidLabelIndexParser.SID_TYPE:
            final SidLabelIndex sid = SidLabelIndexParser.parseSidLabelIndex(Size.forValue(slice.readableBytes()),
                    slice);
            builder.setBindingSubTlv(new SidLabelCaseBuilder().setSidLabelIndex(sid).build());
            break;
        case PrefixAttributesParser.PREFIX_SID:
            final SrPrefix prefix = SrPrefixAttributesParser.parseSrPrefix(slice, protocolId);
            builder.setBindingSubTlv(new PrefixSidCaseBuilder().setAlgorithm(prefix.getAlgorithm())
                    .setFlags(prefix.getFlags()).setSidLabelIndex(prefix.getSidLabelIndex()).build());
            break;
        case ERO_METRIC:
            builder.setBindingSubTlv(
                    new EroMetricCaseBuilder().setEroMetric(new TeMetric(slice.readUnsignedInt())).build());
            break;
        case ERO_IPV4:
            final Ipv4EroCase ipv4Ero = parseIpv4EroCase(slice);
            builder.setBindingSubTlv(
                    new Ipv4EroCaseBuilder().setAddress(ipv4Ero.getAddress()).setLoose(ipv4Ero.isLoose()).build());
            break;
        case BACKUP_ERO_IPV4:
            final Ipv4EroCase ipv4Backup = parseIpv4EroCase(slice);
            builder.setBindingSubTlv(new Ipv4EroBackupCaseBuilder().setAddress(ipv4Backup.getAddress())
                    .setLoose(ipv4Backup.isLoose()).build());
            break;
        case ERO_IPV6:
            final Ipv6EroCase ipv6ero = parseIpv6EroCase(slice);
            builder.setBindingSubTlv(
                    new Ipv6EroCaseBuilder().setAddress(ipv6ero.getAddress()).setLoose(ipv6ero.isLoose()).build());
            break;
        case BACKUP_ERO_IPV6:
            final Ipv6EroCase ipv6backup = parseIpv6EroCase(slice);
            builder.setBindingSubTlv(new Ipv6EroBackupCaseBuilder().setAddress(ipv6backup.getAddress())
                    .setLoose(ipv6backup.isLoose()).build());
            break;
        case UNNUMBERED_ERO:
            final UnnumberedInterfaceIdEroCase unnumbered = parseUnnumberedEroCase(slice);
            builder.setBindingSubTlv(new UnnumberedInterfaceIdEroCaseBuilder().setLoose(unnumbered.isLoose())
                    .setRouterId(unnumbered.getRouterId()).setInterfaceId(unnumbered.getInterfaceId()).build());
            break;
        case BACKUP_UNNUMBERED_ERO:
            final UnnumberedInterfaceIdEroCase unnumberedBackup = parseUnnumberedEroCase(slice);
            builder.setBindingSubTlv(new UnnumberedInterfaceIdBackupEroCaseBuilder()
                    .setLoose(unnumberedBackup.isLoose()).setRouterId(unnumberedBackup.getRouterId())
                    .setInterfaceId(unnumberedBackup.getInterfaceId()).build());
            break;
        default:
            LOG.info("Unknown binding sub Tlv type {}", type);
            break;
        }
    }

    private static Ipv4EroCase parseIpv4EroCase(final ByteBuf buffer) {
        final Ipv4EroCaseBuilder builder = new Ipv4EroCaseBuilder();
        final BitArray flags = BitArray.valueOf(buffer, FLAGS_SIZE);
        builder.setLoose(flags.get(LOOSE));
        buffer.skipBytes(RESERVED_ERO);
        builder.setAddress(Ipv4Util.addressForByteBuf(buffer));
        return builder.build();
    }

    private static Ipv6EroCase parseIpv6EroCase(final ByteBuf buffer) {
        final Ipv6EroCaseBuilder builder = new Ipv6EroCaseBuilder();
        final BitArray flags = BitArray.valueOf(buffer, FLAGS_SIZE);
        builder.setLoose(flags.get(LOOSE));
        buffer.skipBytes(RESERVED_ERO);
        builder.setAddress(Ipv6Util.addressForByteBuf(buffer));
        return builder.build();
    }

    private static UnnumberedInterfaceIdEroCase parseUnnumberedEroCase(final ByteBuf buffer) {
        final UnnumberedInterfaceIdEroCaseBuilder builder = new UnnumberedInterfaceIdEroCaseBuilder();
        final BitArray flags = BitArray.valueOf(buffer, FLAGS_SIZE);
        builder.setLoose(flags.get(LOOSE));
        buffer.skipBytes(RESERVED_ERO);
        builder.setRouterId(buffer.readUnsignedInt());
        builder.setInterfaceId(buffer.readUnsignedInt());
        return builder.build();
    }

    public static void serializeBindingSidLabels(final List<SrBindingSidLabels> bindingSids,
            final ByteBuf aggregator, final int sid_type) {
        for (final SrBindingSidLabels bindingSid : bindingSids) {
            final ByteBuf sidBuffer = Unpooled.buffer();
            serializeBindingSidAttributes(bindingSid.getWeight(), bindingSid.getFlags(),
                    bindingSid.getBindingSubTlvs(), sidBuffer);
            TlvUtil.writeTLV(sid_type, sidBuffer, aggregator);
        }
    }

    public static void serializeBindingSidAttributes(final Weight weight, final Flags flags,
            final List<BindingSubTlvs> bindingSubTlvs, final ByteBuf aggregator) {
        aggregator.writeByte(weight.getValue());
        final BitArray bitFlags = serializeBindingSidFlags(flags);
        bitFlags.toByteBuf(aggregator);
        aggregator.writeZero(RESERVED_BINDING_SID);
        serializeBindingSubTlvs(bindingSubTlvs, aggregator);
    }

    private static BitArray serializeBindingSidFlags(final Flags flags) {
        final BitArray bitFlags = new BitArray(FLAGS_SIZE);
        if (flags instanceof IsisBindingFlagsCase) {
            final IsisBindingFlagsCase isisFlags = (IsisBindingFlagsCase) flags;
            bitFlags.set(AFI, isisFlags.isAddressFamily());
            bitFlags.set(MIRROR_CONTEXT, isisFlags.isMirrorContext());
            bitFlags.set(SPREAD_TLV, isisFlags.isSpreadTlv());
            bitFlags.set(LEAKED, isisFlags.isLeakedFromLevel2());
            bitFlags.set(ATTACHED, isisFlags.isAttachedFlag());
        } else if (flags instanceof OspfBindingFlagsCase) {
            final OspfBindingFlagsCase ospfFlags = (OspfBindingFlagsCase) flags;
            bitFlags.set(MIRROR_CONTEXT_OSPF, ospfFlags.isMirroring());
        }
        return bitFlags;
    }

    private static void serializeBindingSubTlvs(final List<BindingSubTlvs> bindingSubTlvs,
            final ByteBuf aggregator) {
        for (final BindingSubTlvs subTlv : bindingSubTlvs) {
            ByteBuf buffer = Unpooled.buffer();
            final BindingSubTlv bindingSubTlv = subTlv.getBindingSubTlv();
            if (bindingSubTlv instanceof SidLabelCase) {
                buffer = SidLabelIndexParser.serializeSidValue(((SidLabelCase) bindingSubTlv).getSidLabelIndex());
                TlvUtil.writeTLV(SidLabelIndexParser.SID_TYPE, buffer, aggregator);
            } else if (bindingSubTlv instanceof PrefixSidCase) {
                final PrefixSidCase prefix = (PrefixSidCase) bindingSubTlv;
                SrPrefixAttributesParser.serializePrefixAttributes(prefix.getFlags(), prefix.getAlgorithm(),
                        prefix.getSidLabelIndex(), buffer);
                TlvUtil.writeTLV(PrefixAttributesParser.PREFIX_SID, buffer, aggregator);
            } else if (bindingSubTlv instanceof EroMetricCase) {
                buffer.writeInt(((EroMetricCase) bindingSubTlv).getEroMetric().getValue().intValue());
                TlvUtil.writeTLV(ERO_METRIC, buffer, aggregator);
            } else if (bindingSubTlv instanceof Ipv4EroBackupCase) {
                final Ipv4EroBackupCase ipv4Backup = (Ipv4EroBackupCase) bindingSubTlv;
                buffer = serializeIpv4EroCase(ipv4Backup.isLoose(), ipv4Backup.getAddress());
                TlvUtil.writeTLV(BACKUP_ERO_IPV4, buffer, aggregator);
            } else if (bindingSubTlv instanceof Ipv4EroCase) {
                final Ipv4EroCase ipv4Ero = (Ipv4EroCase) bindingSubTlv;
                buffer = serializeIpv4EroCase(ipv4Ero.isLoose(), ipv4Ero.getAddress());
                TlvUtil.writeTLV(ERO_IPV4, buffer, aggregator);
            } else if (bindingSubTlv instanceof Ipv6EroBackupCase) {
                final Ipv6EroBackupCase ipv6Backup = (Ipv6EroBackupCase) bindingSubTlv;
                buffer = serializeIpv6EroCase(ipv6Backup.isLoose(), ipv6Backup.getAddress());
                TlvUtil.writeTLV(BACKUP_ERO_IPV6, buffer, aggregator);
            } else if (bindingSubTlv instanceof Ipv6EroCase) {
                final Ipv6EroCase ipv6Ero = (Ipv6EroCase) bindingSubTlv;
                buffer = serializeIpv6EroCase(ipv6Ero.isLoose(), ipv6Ero.getAddress());
                TlvUtil.writeTLV(ERO_IPV6, buffer, aggregator);
            } else if (bindingSubTlv instanceof UnnumberedInterfaceIdEroCase) {
                final UnnumberedInterfaceIdEroCase unnumberedEro = (UnnumberedInterfaceIdEroCase) bindingSubTlv;
                buffer = serializeUnnumberedIdEro(unnumberedEro.isLoose(), unnumberedEro.getRouterId(),
                        unnumberedEro.getInterfaceId());
                TlvUtil.writeTLV(UNNUMBERED_ERO, buffer, aggregator);
            } else if (bindingSubTlv instanceof UnnumberedInterfaceIdBackupEroCase) {
                final UnnumberedInterfaceIdBackupEroCase unnumberedBackup = (UnnumberedInterfaceIdBackupEroCase) bindingSubTlv;
                buffer = serializeUnnumberedIdEro(unnumberedBackup.isLoose(), unnumberedBackup.getRouterId(),
                        unnumberedBackup.getInterfaceId());
                TlvUtil.writeTLV(BACKUP_UNNUMBERED_ERO, buffer, aggregator);
            }
        }
    }

    private static ByteBuf serializeIpv4EroCase(final Boolean loose, final Ipv4Address address) {
        final ByteBuf buffer = Unpooled.buffer();
        serializeEroFlags(buffer, loose);
        buffer.writeBytes(Ipv4Util.byteBufForAddress(address));
        return buffer;
    }

    private static ByteBuf serializeIpv6EroCase(final Boolean loose, final Ipv6Address address) {
        final ByteBuf buffer = Unpooled.buffer();
        serializeEroFlags(buffer, loose);
        buffer.writeBytes(Ipv6Util.byteBufForAddress(address));
        return buffer;
    }

    private static ByteBuf serializeUnnumberedIdEro(final Boolean loose, final Long routerId,
            final Long interfaceId) {
        final ByteBuf buffer = Unpooled.buffer();
        serializeEroFlags(buffer, loose);
        buffer.writeInt(routerId.intValue());
        buffer.writeInt(interfaceId.intValue());
        return buffer;
    }

    private static void serializeEroFlags(final ByteBuf buffer, final Boolean loose) {
        final BitArray flags = new BitArray(FLAGS_SIZE);
        flags.set(LOOSE, loose);
        flags.toByteBuf(buffer);
        buffer.writeZero(RESERVED_ERO);
    }
}