blob: 6e823440dc824a53207a3d1475ba60326e22f389 [file] [log] [blame]
Priyanka Be25cefe82015-11-28 14:47:23 +05301/*
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 */
16package org.onosproject.bgp.controller.impl;
17
Priyanka Be25cefe82015-11-28 14:47:23 +053018import org.onosproject.bgpio.protocol.linkstate.PathAttrNlriDetailsLocalRib;
19import org.onosproject.bgpio.types.AsPath;
20import org.onosproject.bgpio.types.BgpValueType;
21import org.onosproject.bgpio.types.LocalPref;
22import org.onosproject.bgpio.types.Med;
23import org.onosproject.bgpio.types.Origin;
Jonathan Hart51539b82015-10-29 09:53:04 -070024import org.onosproject.bgpio.types.Origin.OriginType;
Priyanka Be25cefe82015-11-28 14:47:23 +053025import org.slf4j.Logger;
26import org.slf4j.LoggerFactory;
27
Jonathan Hart51539b82015-10-29 09:53:04 -070028import java.util.Comparator;
29import java.util.List;
30import java.util.ListIterator;
31
Priyanka Be25cefe82015-11-28 14:47:23 +053032/**
33 * Implementation of BGP best path Selection process.
34 */
35public 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
Jian Lidfba7392016-01-22 16:46:58 -0800111 * @return object with shortest AsPath
Priyanka Be25cefe82015-11-28 14:47:23 +0530112 */
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) {
Jonathan Hart51539b82015-10-29 09:53:04 -0700125 if (obj1Origin.origin() == OriginType.IGP) {
Priyanka Be25cefe82015-11-28 14:47:23 +0530126 return 1;
127 }
Jonathan Hart51539b82015-10-29 09:53:04 -0700128 if (obj2Origin.origin() == OriginType.IGP) {
Priyanka Be25cefe82015-11-28 14:47:23 +0530129 return -1;
130 }
Jonathan Hart51539b82015-10-29 09:53:04 -0700131 if (obj1Origin.origin() == OriginType.EGP) {
Priyanka Be25cefe82015-11-28 14:47:23 +0530132 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 }
Jonathan Hart51539b82015-10-29 09:53:04 -0700242}