Priyanka B
Committed by Gerrit Code Review

[ONOS] BGP Selection Algo and Test

Change-Id: I9d9e8c699dea46fde07b7cba526b3c7fd1f3bd34
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