/* * 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.rib.impl; import com.google.common.base.Optional; import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableList; import java.util.Collection; import java.util.List; import javax.annotation.concurrent.NotThreadSafe; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.AsNumber; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.path.attributes.attributes.AsPath; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.path.attributes.attributes.LocalPref; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.path.attributes.attributes.MultiExitDisc; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.path.attributes.attributes.Origin; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.path.attributes.attributes.as.path.Segments; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.BgpOrigin; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.as.path.segment.c.segment.AListCase; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.as.path.segment.c.segment.ASetCase; import org.opendaylight.yangtools.yang.common.QName; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument; import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode; import org.opendaylight.yangtools.yang.data.api.schema.LeafNode; import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode; import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNodes; import org.opendaylight.yangtools.yang.data.api.schema.UnkeyedListEntryNode; import org.opendaylight.yangtools.yang.data.api.schema.UnkeyedListNode; @NotThreadSafe final class BestPathState { private static final Collection AS_PATH = ImmutableList.of(new NodeIdentifier(AsPath.QNAME), new NodeIdentifier(Segments.QNAME)); private static final Collection LOCAL_PREF = ImmutableList.of(new NodeIdentifier(LocalPref.QNAME), new NodeIdentifier(QName.create(LocalPref.QNAME, "pref"))); private static final Collection MED = ImmutableList.of(new NodeIdentifier(MultiExitDisc.QNAME), new NodeIdentifier(QName.create(MultiExitDisc.QNAME, "med"))); private static final Collection ORIGIN = ImmutableList.of(new NodeIdentifier(Origin.QNAME), new NodeIdentifier(QName.create(Origin.QNAME, "value"))); private final ContainerNode attributes; private Long localPref; private Long multiExitDisc; private BgpOrigin origin; private static final Long peerAs = 0L; private static final int asPathLength = 0; private boolean resolved; BestPathState(final ContainerNode attributes) { this.attributes = Preconditions.checkNotNull(attributes); } private static BgpOrigin fromString(final String originStr) { switch (originStr) { case "igp": return BgpOrigin.Igp; case "egp": return BgpOrigin.Egp; case "incomplete": return BgpOrigin.Incomplete; default: throw new IllegalArgumentException("Unhandleed origin value " + originStr); } } private void resolveValues() { if (this.resolved) { return; } final Optional> maybeLocalPref = NormalizedNodes.findNode(this.attributes, LOCAL_PREF); if (maybeLocalPref.isPresent()) { this.localPref = (Long) ((LeafNode)maybeLocalPref.get()).getValue(); } else { this.localPref = null; } final Optional> maybeMultiExitDisc = NormalizedNodes.findNode(this.attributes, MED); if (maybeMultiExitDisc.isPresent()) { this.multiExitDisc = (Long) ((LeafNode)maybeMultiExitDisc.get()).getValue(); } else { this.multiExitDisc = null; } final Optional> maybeOrigin = NormalizedNodes.findNode(this.attributes, ORIGIN); if (maybeOrigin.isPresent()) { this.origin = fromString((String) ((LeafNode)maybeOrigin.get()).getValue()); } else { this.origin = null; } final Optional> maybeSegments = NormalizedNodes.findNode(this.attributes, AS_PATH); if (maybeSegments.isPresent()) { final UnkeyedListNode segments = (UnkeyedListNode) maybeSegments.get(); if (segments.getSize() != 0) { // FIXME: peer AS number // FIXME: asPathLength = countAsPath(this.bestState.getAsPath().getSegments()); final boolean haveSegment; for (final UnkeyedListEntryNode s : segments.getValue()) { } } } this.resolved = true; } Long getLocalPref() { resolveValues(); return this.localPref; } Long getMultiExitDisc() { resolveValues(); return this.multiExitDisc; } BgpOrigin getOrigin() { resolveValues(); return this.origin; } Long getPeerAs() { resolveValues(); return this.peerAs; } int getAsPathLength() { resolveValues(); return asPathLength; } private static int countAsPath(final List segments) { // an AS_SET counts as 1, no matter how many ASs are in the set. int count = 0; boolean setPresent = false; for (final Segments s : segments) { if (s.getCSegment() instanceof ASetCase) { setPresent = true; } else { final AListCase list = (AListCase) s.getCSegment(); count += list.getAList().getAsSequence().size(); } } return (setPresent) ? count + 1 : count; } private static AsNumber getPeerAs(final List segments) { if (segments.isEmpty()) { return null; } final AListCase first = (AListCase) segments.get(0).getCSegment(); return first.getAList().getAsSequence().get(0).getAs(); } ContainerNode getAttributes() { return this.attributes; } }