2 * Copyright (c) 2015 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.protocol.bgp.rib.impl;
10 import com.google.common.base.MoreObjects;
11 import com.google.common.base.MoreObjects.ToStringHelper;
12 import com.google.common.base.Optional;
13 import com.google.common.base.Preconditions;
14 import com.google.common.collect.ImmutableList;
15 import java.util.Collection;
16 import java.util.List;
17 import javax.annotation.concurrent.NotThreadSafe;
18 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.AsNumber;
19 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.path.attributes.attributes.AsPath;
20 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.path.attributes.attributes.LocalPref;
21 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.path.attributes.attributes.MultiExitDisc;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.path.attributes.attributes.Origin;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.path.attributes.attributes.as.path.Segments;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.BgpOrigin;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.as.path.segment.c.segment.AListCase;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.as.path.segment.c.segment.ASetCase;
27 import org.opendaylight.yangtools.yang.common.QName;
28 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
29 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
30 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
31 import org.opendaylight.yangtools.yang.data.api.schema.LeafNode;
32 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
33 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNodes;
34 import org.opendaylight.yangtools.yang.data.api.schema.UnkeyedListEntryNode;
35 import org.opendaylight.yangtools.yang.data.api.schema.UnkeyedListNode;
38 final class BestPathState {
39 private static final Collection<PathArgument> AS_PATH = ImmutableList.<PathArgument>of(new NodeIdentifier(AsPath.QNAME), new NodeIdentifier(Segments.QNAME));
40 private static final Collection<PathArgument> LOCAL_PREF = ImmutableList.<PathArgument>of(new NodeIdentifier(LocalPref.QNAME), new NodeIdentifier(QName.create(LocalPref.QNAME, "pref")));
41 private static final Collection<PathArgument> MED = ImmutableList.<PathArgument>of(new NodeIdentifier(MultiExitDisc.QNAME), new NodeIdentifier(QName.create(MultiExitDisc.QNAME, "med")));
42 private static final Collection<PathArgument> ORIGIN = ImmutableList.<PathArgument>of(new NodeIdentifier(Origin.QNAME), new NodeIdentifier(QName.create(Origin.QNAME, "value")));
44 private final ContainerNode attributes;
45 private Long localPref;
46 private Long multiExitDisc;
47 private BgpOrigin origin;
48 private static final Long peerAs = 0L;
49 private static final int asPathLength = 0;
50 private boolean resolved;
52 BestPathState(final ContainerNode attributes) {
53 this.attributes = Preconditions.checkNotNull(attributes);
56 private static BgpOrigin fromString(final String originStr) {
63 return BgpOrigin.Incomplete;
65 throw new IllegalArgumentException("Unhandled origin value " + originStr);
69 private void resolveValues() {
74 final Optional<NormalizedNode<?, ?>> maybeLocalPref = NormalizedNodes.findNode(this.attributes, LOCAL_PREF);
75 if (maybeLocalPref.isPresent()) {
76 this.localPref = (Long) ((LeafNode<?>)maybeLocalPref.get()).getValue();
78 this.localPref = null;
81 final Optional<NormalizedNode<?, ?>> maybeMultiExitDisc = NormalizedNodes.findNode(this.attributes, MED);
82 if (maybeMultiExitDisc.isPresent()) {
83 this.multiExitDisc = (Long) ((LeafNode<?>)maybeMultiExitDisc.get()).getValue();
85 this.multiExitDisc = null;
88 final Optional<NormalizedNode<?, ?>> maybeOrigin = NormalizedNodes.findNode(this.attributes, ORIGIN);
89 if (maybeOrigin.isPresent()) {
90 this.origin = fromString((String) ((LeafNode<?>)maybeOrigin.get()).getValue());
95 final Optional<NormalizedNode<?, ?>> maybeSegments = NormalizedNodes.findNode(this.attributes, AS_PATH);
96 if (maybeSegments.isPresent()) {
97 final UnkeyedListNode segments = (UnkeyedListNode) maybeSegments.get();
99 if (segments.getSize() != 0) {
100 // FIXME: peer AS number
102 // FIXME: asPathLength = countAsPath(this.bestState.getAsPath().getSegments());
103 final boolean haveSegment;
104 for (final UnkeyedListEntryNode s : segments.getValue()) {
110 this.resolved = true;
113 Long getLocalPref() {
115 return this.localPref;
118 Long getMultiExitDisc() {
120 return this.multiExitDisc;
123 BgpOrigin getOrigin() {
133 int getAsPathLength() {
138 private static int countAsPath(final List<Segments> segments) {
139 // an AS_SET counts as 1, no matter how many ASs are in the set.
141 boolean setPresent = false;
142 for (final Segments s : segments) {
143 if (s.getCSegment() instanceof ASetCase) {
146 final AListCase list = (AListCase) s.getCSegment();
147 count += list.getAList().getAsSequence().size();
150 return (setPresent) ? count + 1 : count;
153 private static AsNumber getPeerAs(final List<Segments> segments) {
154 if (segments.isEmpty()) {
158 final AListCase first = (AListCase) segments.get(0).getCSegment();
159 return first.getAList().getAsSequence().get(0).getAs();
162 ContainerNode getAttributes() {
163 return this.attributes;
166 private ToStringHelper addToStringAttributes(final ToStringHelper toStringHelper) {
167 toStringHelper.add("attributes", this.attributes);
168 toStringHelper.add("localPref", this.localPref);
169 toStringHelper.add("multiExitDisc", this.multiExitDisc);
170 toStringHelper.add("origin", this.origin);
171 toStringHelper.add("resolved", this.resolved);
172 return toStringHelper;
176 public String toString() {
177 return addToStringAttributes(MoreObjects.toStringHelper(this)).toString();
181 public int hashCode() {
182 final int prime = 31;
184 result = prime * result + this.attributes.hashCode();
185 result = prime * result + ((this.localPref == null) ? 0 : this.localPref.hashCode());
186 result = prime * result + ((this.multiExitDisc == null) ? 0 : this.multiExitDisc.hashCode());
187 result = prime * result + ((this.origin == null) ? 0 : this.origin.hashCode());
192 public boolean equals(final Object obj) {
196 if (!(obj instanceof BestPathState)) {
199 final BestPathState other = (BestPathState) obj;
200 if (!this.attributes.equals(other.attributes)) {
203 if (this.localPref == null) {
204 if (other.localPref != null) {
207 } else if (!this.localPref.equals(other.localPref)) {
210 if (this.multiExitDisc == null) {
211 if (other.multiExitDisc != null) {
214 } else if (!this.multiExitDisc.equals(other.multiExitDisc)) {
217 if (this.origin != other.origin) {