BUG-2982 : moved path-attributes container to grouping
[bgpcep.git] / bgp / rib-impl / src / main / java / org / opendaylight / protocol / bgp / rib / impl / BestPathState.java
1 /*
2  * Copyright (c) 2015 Cisco Systems, Inc. and others.  All rights reserved.
3  *
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
7  */
8 package org.opendaylight.protocol.bgp.rib.impl;
9
10 import com.google.common.base.Optional;
11 import com.google.common.base.Preconditions;
12 import com.google.common.collect.ImmutableList;
13 import java.util.Collection;
14 import java.util.List;
15 import javax.annotation.concurrent.NotThreadSafe;
16 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.AsNumber;
17 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.path.attributes.attributes.AsPath;
18 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.path.attributes.attributes.LocalPref;
19 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.path.attributes.attributes.MultiExitDisc;
20 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.path.attributes.attributes.Origin;
21 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.path.attributes.attributes.as.path.Segments;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.BgpOrigin;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.as.path.segment.c.segment.AListCase;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.as.path.segment.c.segment.ASetCase;
25 import org.opendaylight.yangtools.yang.common.QName;
26 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
27 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
28 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
29 import org.opendaylight.yangtools.yang.data.api.schema.LeafNode;
30 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
31 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNodes;
32 import org.opendaylight.yangtools.yang.data.api.schema.UnkeyedListEntryNode;
33 import org.opendaylight.yangtools.yang.data.api.schema.UnkeyedListNode;
34
35 @NotThreadSafe
36 final class BestPathState {
37     private static final Collection<PathArgument> AS_PATH = ImmutableList.<PathArgument>of(new NodeIdentifier(AsPath.QNAME), new NodeIdentifier(Segments.QNAME));
38     private static final Collection<PathArgument> LOCAL_PREF = ImmutableList.<PathArgument>of(new NodeIdentifier(LocalPref.QNAME), new NodeIdentifier(QName.create(LocalPref.QNAME, "pref")));
39     private static final Collection<PathArgument> MED = ImmutableList.<PathArgument>of(new NodeIdentifier(MultiExitDisc.QNAME), new NodeIdentifier(QName.create(MultiExitDisc.QNAME, "med")));
40     private static final Collection<PathArgument> ORIGIN = ImmutableList.<PathArgument>of(new NodeIdentifier(Origin.QNAME), new NodeIdentifier(QName.create(Origin.QNAME, "value")));
41
42     private final ContainerNode attributes;
43     private Long localPref;
44     private Long multiExitDisc;
45     private BgpOrigin origin;
46     private static final Long peerAs = 0L;
47     private static final int asPathLength = 0;
48     private boolean resolved;
49
50     BestPathState(final ContainerNode attributes) {
51         this.attributes = Preconditions.checkNotNull(attributes);
52     }
53
54     private static BgpOrigin fromString(final String originStr) {
55         switch (originStr) {
56         case "igp":
57             return BgpOrigin.Igp;
58         case "egp":
59             return BgpOrigin.Egp;
60         case "incomplete":
61             return BgpOrigin.Incomplete;
62         default:
63             throw new IllegalArgumentException("Unhandleed origin value " + originStr);
64         }
65     }
66
67     private void resolveValues() {
68         if (this.resolved) {
69             return;
70         }
71
72         final Optional<NormalizedNode<?, ?>> maybeLocalPref = NormalizedNodes.findNode(this.attributes, LOCAL_PREF);
73         if (maybeLocalPref.isPresent()) {
74             this.localPref = (Long) ((LeafNode<?>)maybeLocalPref.get()).getValue();
75         } else {
76             this.localPref = null;
77         }
78
79         final Optional<NormalizedNode<?, ?>> maybeMultiExitDisc = NormalizedNodes.findNode(this.attributes, MED);
80         if (maybeMultiExitDisc.isPresent()) {
81             this.multiExitDisc = (Long) ((LeafNode<?>)maybeMultiExitDisc.get()).getValue();
82         } else {
83             this.multiExitDisc = null;
84         }
85
86         final Optional<NormalizedNode<?, ?>> maybeOrigin = NormalizedNodes.findNode(this.attributes, ORIGIN);
87         if (maybeOrigin.isPresent()) {
88             this.origin = fromString((String) ((LeafNode<?>)maybeOrigin.get()).getValue());
89         } else {
90             this.origin = null;
91         }
92
93         final Optional<NormalizedNode<?, ?>> maybeSegments = NormalizedNodes.findNode(this.attributes, AS_PATH);
94         if (maybeSegments.isPresent()) {
95             final UnkeyedListNode segments = (UnkeyedListNode) maybeSegments.get();
96
97             if (segments.getSize() != 0) {
98                 // FIXME: peer AS number
99
100                 // FIXME: asPathLength = countAsPath(this.bestState.getAsPath().getSegments());
101                 final boolean haveSegment;
102                 for (final UnkeyedListEntryNode s : segments.getValue()) {
103
104                 }
105             }
106         }
107
108         this.resolved = true;
109     }
110
111     Long getLocalPref() {
112         resolveValues();
113         return this.localPref;
114     }
115
116     Long getMultiExitDisc() {
117         resolveValues();
118         return this.multiExitDisc;
119     }
120
121     BgpOrigin getOrigin() {
122         resolveValues();
123         return this.origin;
124     }
125
126     Long getPeerAs() {
127         resolveValues();
128         return this.peerAs;
129     }
130
131     int getAsPathLength() {
132         resolveValues();
133         return asPathLength;
134     }
135
136     private static int countAsPath(final List<Segments> segments) {
137         // an AS_SET counts as 1, no matter how many ASs are in the set.
138         int count = 0;
139         boolean setPresent = false;
140         for (final Segments s : segments) {
141             if (s.getCSegment() instanceof ASetCase) {
142                 setPresent = true;
143             } else {
144                 final AListCase list = (AListCase) s.getCSegment();
145                 count += list.getAList().getAsSequence().size();
146             }
147         }
148         return (setPresent) ? count + 1 : count;
149     }
150
151     private static AsNumber getPeerAs(final List<Segments> segments) {
152         if (segments.isEmpty()) {
153             return null;
154         }
155
156         final AListCase first = (AListCase) segments.get(0).getCSegment();
157         return first.getAList().getAsSequence().get(0).getAs();
158     }
159
160     ContainerNode getAttributes() {
161         return this.attributes;
162     }
163 }