Committed by
Gerrit Code Review
[ONOS] BGP Selection Algo and Test
Change-Id: I9d9e8c699dea46fde07b7cba526b3c7fd1f3bd34
Showing
2 changed files
with
242 additions
and
0 deletions
1 | +/* | ||
2 | + * Copyright 2015 Open Networking Laboratory | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | +package org.onosproject.bgp.controller.impl; | ||
17 | + | ||
18 | +import java.util.Comparator; | ||
19 | +import java.util.List; | ||
20 | +import java.util.ListIterator; | ||
21 | + | ||
22 | +import org.onosproject.bgpio.protocol.linkstate.PathAttrNlriDetailsLocalRib; | ||
23 | +import org.onosproject.bgpio.types.AsPath; | ||
24 | +import org.onosproject.bgpio.types.BgpValueType; | ||
25 | +import org.onosproject.bgpio.types.LocalPref; | ||
26 | +import org.onosproject.bgpio.types.Med; | ||
27 | +import org.onosproject.bgpio.types.Origin; | ||
28 | +import org.onosproject.bgpio.types.Origin.ORIGINTYPE; | ||
29 | +import org.slf4j.Logger; | ||
30 | +import org.slf4j.LoggerFactory; | ||
31 | + | ||
32 | +/** | ||
33 | + * Implementation of BGP best path Selection process. | ||
34 | + */ | ||
35 | +public final class BgpSelectionAlgo implements Comparator<PathAttrNlriDetailsLocalRib> { | ||
36 | + private static final Logger log = LoggerFactory.getLogger(BgpSelectionAlgo.class); | ||
37 | + LocalPref obj1LocPref = null; | ||
38 | + AsPath obj1Aspath = null; | ||
39 | + Origin obj1Origin = null; | ||
40 | + Med obj1Med = null; | ||
41 | + LocalPref obj2LocPref = null; | ||
42 | + AsPath obj2Aspath = null; | ||
43 | + Origin obj2Origin = null; | ||
44 | + Med obj2Med = null; | ||
45 | + | ||
46 | + @Override | ||
47 | + public int compare(PathAttrNlriDetailsLocalRib pathNlriDetails1, PathAttrNlriDetailsLocalRib pathNlriDetails2) { | ||
48 | + if (pathNlriDetails1 == null) { | ||
49 | + return -1; | ||
50 | + } | ||
51 | + if (pathNlriDetails2 == null) { | ||
52 | + return 1; | ||
53 | + } | ||
54 | + if (pathNlriDetails1.equals(pathNlriDetails2)) { | ||
55 | + return 0; | ||
56 | + } | ||
57 | + | ||
58 | + List<BgpValueType> o1 = pathNlriDetails1.localRibNlridetails().pathAttributes(); | ||
59 | + List<BgpValueType> o2 = pathNlriDetails2.localRibNlridetails().pathAttributes(); | ||
60 | + ListIterator<BgpValueType> listIteratorObj1 = o1.listIterator(); | ||
61 | + ListIterator<BgpValueType> listIteratorObj2 = o2.listIterator(); | ||
62 | + storeAttr(listIteratorObj1, listIteratorObj2); | ||
63 | + | ||
64 | + // prefer attribute with higher local preference | ||
65 | + if (obj1LocPref != null || obj2LocPref != null && (obj1LocPref != null && !obj1LocPref.equals(obj2LocPref))) { | ||
66 | + return compareLocalPref(obj1LocPref, obj2LocPref); | ||
67 | + } | ||
68 | + | ||
69 | + // prefer attribute with shortest Aspath | ||
70 | + if (!obj1Aspath.equals(obj2Aspath)) { | ||
71 | + Integer obj1Size = countASSize(obj1Aspath); | ||
72 | + Integer obj2Size = countASSize(obj2Aspath); | ||
73 | + if (obj1Size != obj2Size) { | ||
74 | + return compareAsPath(obj1Size, obj2Size); | ||
75 | + } | ||
76 | + } | ||
77 | + | ||
78 | + // prefer attribute with lowest origin type | ||
79 | + if (!obj1Origin.equals(obj2Origin)) { | ||
80 | + return compareOrigin(obj1Origin, obj2Origin); | ||
81 | + } | ||
82 | + | ||
83 | + // prefer attribute with lowest MED | ||
84 | + if (obj1Med != null || obj2Med != null && (obj1Med != null && !obj1Med.equals(obj2Med))) { | ||
85 | + return compareMed(obj1Med, obj2Med); | ||
86 | + } | ||
87 | + | ||
88 | + if ((pathNlriDetails1 != null || pathNlriDetails2 != null) && (pathNlriDetails1 != null && !pathNlriDetails1 | ||
89 | + .equals(pathNlriDetails2))) { | ||
90 | + return comparePeerDetails(pathNlriDetails1, pathNlriDetails2); | ||
91 | + } | ||
92 | + return 0; | ||
93 | + } | ||
94 | + | ||
95 | + /** | ||
96 | + * Compares local preference of two objects and returns object with higher preference. | ||
97 | + * | ||
98 | + * @param obj1LocPref local preference object1 | ||
99 | + * @param obj2LocPref local preference object2 | ||
100 | + * @return object with higher preference | ||
101 | + */ | ||
102 | + int compareLocalPref(LocalPref obj1LocPref, LocalPref obj2LocPref) { | ||
103 | + return ((Integer) (obj1LocPref.localPref())).compareTo((Integer) (obj2LocPref.localPref())); | ||
104 | + } | ||
105 | + | ||
106 | + /** | ||
107 | + * Compares AsPath of two objects and returns object with shortest AsPath. | ||
108 | + * | ||
109 | + * @param obj1Size object1 AS count | ||
110 | + * @param obj2Size object2 AS count | ||
111 | + * @return | ||
112 | + */ | ||
113 | + int compareAsPath(Integer obj1Size, Integer obj2Size) { | ||
114 | + return obj1Size.compareTo(obj2Size); | ||
115 | + } | ||
116 | + | ||
117 | + /** | ||
118 | + * Compare Origin of two objects and returns object with lowest origin value. | ||
119 | + * | ||
120 | + * @param obj1Origin Origin object1 | ||
121 | + * @param obj2Origin Origin object1 | ||
122 | + * @return object with lowest origin value | ||
123 | + */ | ||
124 | + int compareOrigin(Origin obj1Origin, Origin obj2Origin) { | ||
125 | + if (obj1Origin.origin() == ORIGINTYPE.IGP) { | ||
126 | + return 1; | ||
127 | + } | ||
128 | + if (obj2Origin.origin() == ORIGINTYPE.IGP) { | ||
129 | + return -1; | ||
130 | + } | ||
131 | + if (obj1Origin.origin() == ORIGINTYPE.EGP) { | ||
132 | + return 1; | ||
133 | + } else { | ||
134 | + return -1; | ||
135 | + } | ||
136 | + } | ||
137 | + | ||
138 | + /** | ||
139 | + * Compare Med of two objects and returns object with lowestMed value. | ||
140 | + * | ||
141 | + * @param obj1Med Med object1 | ||
142 | + * @param obj2Med Med object2 | ||
143 | + * @return returns object with lowestMed value | ||
144 | + */ | ||
145 | + int compareMed(Med obj1Med, Med obj2Med) { | ||
146 | + return ((Integer) (obj2Med.med())).compareTo((Integer) (obj1Med.med())); | ||
147 | + } | ||
148 | + | ||
149 | + /** | ||
150 | + * Compares EBGP over IBGP, BGP identifier value and peer address. | ||
151 | + * | ||
152 | + * @param pathNlriDetails1 PathAttrNlriDetailsLocalRib object1 | ||
153 | + * @param pathNlriDetails2 PathAttrNlriDetailsLocalRib object2 | ||
154 | + * @return object which as EBGP over IBGP, lowest BGP identifier value and lowest peer address | ||
155 | + */ | ||
156 | + int comparePeerDetails(PathAttrNlriDetailsLocalRib pathNlriDetails1, PathAttrNlriDetailsLocalRib pathNlriDetails2) { | ||
157 | + // consider EBGP over IBGP | ||
158 | + if (pathNlriDetails1.isLocalRibIbgpSession() != pathNlriDetails2.isLocalRibIbgpSession()) { | ||
159 | + if (pathNlriDetails1 == null || pathNlriDetails1.isLocalRibIbgpSession()) { | ||
160 | + return -1; | ||
161 | + } | ||
162 | + if (pathNlriDetails2 == null || pathNlriDetails2.isLocalRibIbgpSession()) { | ||
163 | + return 1; | ||
164 | + } | ||
165 | + } | ||
166 | + // prefer lowest BGP identifier value. | ||
167 | + if (pathNlriDetails1.localRibIdentifier() != pathNlriDetails2.localRibIdentifier()) { | ||
168 | + return ((Integer) pathNlriDetails2.localRibIdentifier()) | ||
169 | + .compareTo(pathNlriDetails1.localRibIdentifier()); | ||
170 | + } | ||
171 | + //prefer lowest peer address | ||
172 | + if (pathNlriDetails1.localRibIpAddress() != pathNlriDetails2.localRibIpAddress()) { | ||
173 | + return pathNlriDetails2.localRibIpAddress().compareTo(pathNlriDetails1.localRibIpAddress()); | ||
174 | + } | ||
175 | + return 0; | ||
176 | + } | ||
177 | + | ||
178 | + /** | ||
179 | + * Returns ASes count of AsPath attribute , if AS_SET is present then count as 1. | ||
180 | + * | ||
181 | + * @param aspath object of AsPath | ||
182 | + * @return count of ASes | ||
183 | + */ | ||
184 | + Integer countASSize(AsPath aspath) { | ||
185 | + boolean isASSet = false; | ||
186 | + int count = 0; | ||
187 | + if (!aspath.asPathSet().isEmpty()) { | ||
188 | + isASSet = true; | ||
189 | + } | ||
190 | + if (!aspath.asPathSeq().isEmpty()) { | ||
191 | + count = aspath.asPathSeq().size(); | ||
192 | + } | ||
193 | + return isASSet ? ++count : count; | ||
194 | + } | ||
195 | + | ||
196 | + /** | ||
197 | + * Stores BGP basic attributes of two objects. | ||
198 | + * | ||
199 | + * @param listIteratorObj1 list iterator of object1 | ||
200 | + * @param listIteratorObj2 list iterator of object2 | ||
201 | + */ | ||
202 | + void storeAttr(ListIterator<BgpValueType> listIteratorObj1, ListIterator<BgpValueType> listIteratorObj2) { | ||
203 | + while (listIteratorObj1.hasNext()) { | ||
204 | + BgpValueType pathAttributeObj1 = listIteratorObj1.next(); | ||
205 | + switch (pathAttributeObj1.getType()) { | ||
206 | + case LocalPref.LOCAL_PREF_TYPE: | ||
207 | + obj1LocPref = (LocalPref) pathAttributeObj1; | ||
208 | + break; | ||
209 | + case AsPath.ASPATH_TYPE: | ||
210 | + obj1Aspath = (AsPath) pathAttributeObj1; | ||
211 | + break; | ||
212 | + case Origin.ORIGIN_TYPE: | ||
213 | + obj1Origin = (Origin) pathAttributeObj1; | ||
214 | + break; | ||
215 | + case Med.MED_TYPE: | ||
216 | + obj1Med = (Med) pathAttributeObj1; | ||
217 | + break; | ||
218 | + default: | ||
219 | + log.debug("Got other type, Not required: " + pathAttributeObj1.getType()); | ||
220 | + } | ||
221 | + } | ||
222 | + while (listIteratorObj2.hasNext()) { | ||
223 | + BgpValueType pathAttributeObj2 = listIteratorObj2.next(); | ||
224 | + switch (pathAttributeObj2.getType()) { | ||
225 | + case LocalPref.LOCAL_PREF_TYPE: | ||
226 | + obj2LocPref = (LocalPref) pathAttributeObj2; | ||
227 | + break; | ||
228 | + case AsPath.ASPATH_TYPE: | ||
229 | + obj2Aspath = (AsPath) pathAttributeObj2; | ||
230 | + break; | ||
231 | + case Origin.ORIGIN_TYPE: | ||
232 | + obj2Origin = (Origin) pathAttributeObj2; | ||
233 | + break; | ||
234 | + case Med.MED_TYPE: | ||
235 | + obj2Med = (Med) pathAttributeObj2; | ||
236 | + break; | ||
237 | + default: | ||
238 | + log.debug("Got other type, Not required: " + pathAttributeObj2.getType()); | ||
239 | + } | ||
240 | + } | ||
241 | + } | ||
242 | +} | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
This diff is collapsed. Click to expand it.
-
Please register or login to post a comment