blob: 52a02145a85f46a05572985b9c2319cb5af440cb [file] [log] [blame]
Jonathan Hart20d8e512014-10-16 11:05:52 -07001package org.onlab.onos.sdnip.bgp;
2
3import static org.easymock.EasyMock.createMock;
4import static org.easymock.EasyMock.expect;
5import static org.easymock.EasyMock.replay;
6import static org.hamcrest.Matchers.is;
7import static org.hamcrest.Matchers.not;
8import static org.junit.Assert.assertThat;
9
10import java.util.ArrayList;
11
12import org.junit.Before;
13import org.junit.Test;
14import org.onlab.packet.IpAddress;
15import org.onlab.packet.IpPrefix;
16
17/**
18 * Unit tests for the BgpRouteEntry class.
19 */
20public class BgpRouteEntryTest {
21 private BgpSession bgpSession;
22 private static final IpAddress BGP_SESSION_BGP_ID =
23 IpAddress.valueOf("10.0.0.1");
24 private static final IpAddress BGP_SESSION_IP_ADDRESS =
25 IpAddress.valueOf("20.0.0.1");
26
27 private BgpSession bgpSession2;
28 private static final IpAddress BGP_SESSION_BGP_ID2 =
29 IpAddress.valueOf("10.0.0.2");
30 private static final IpAddress BGP_SESSION_IP_ADDRESS2 =
31 IpAddress.valueOf("20.0.0.1");
32
33 private BgpSession bgpSession3;
34 private static final IpAddress BGP_SESSION_BGP_ID3 =
35 IpAddress.valueOf("10.0.0.1");
36 private static final IpAddress BGP_SESSION_IP_ADDRESS3 =
37 IpAddress.valueOf("20.0.0.2");
38
39 @Before
40 public void setUp() throws Exception {
41 // Mock objects for testing
42 bgpSession = createMock(BgpSession.class);
43 bgpSession2 = createMock(BgpSession.class);
44 bgpSession3 = createMock(BgpSession.class);
45
46 // Setup the BGP Sessions
47 expect(bgpSession.getRemoteBgpId())
48 .andReturn(BGP_SESSION_BGP_ID).anyTimes();
49 expect(bgpSession.getRemoteIp4Address())
50 .andReturn(BGP_SESSION_IP_ADDRESS).anyTimes();
51 //
52 expect(bgpSession2.getRemoteBgpId())
53 .andReturn(BGP_SESSION_BGP_ID2).anyTimes();
54 expect(bgpSession2.getRemoteIp4Address())
55 .andReturn(BGP_SESSION_IP_ADDRESS2).anyTimes();
56 //
57 expect(bgpSession3.getRemoteBgpId())
58 .andReturn(BGP_SESSION_BGP_ID3).anyTimes();
59 expect(bgpSession3.getRemoteIp4Address())
60 .andReturn(BGP_SESSION_IP_ADDRESS3).anyTimes();
61
62 replay(bgpSession);
63 replay(bgpSession2);
64 replay(bgpSession3);
65 }
66
67 /**
68 * Generates a BGP Route Entry.
69 *
70 * @return a generated BGP Route Entry
71 */
72 private BgpRouteEntry generateBgpRouteEntry() {
73 IpPrefix prefix = IpPrefix.valueOf("1.2.3.0/24");
74 IpAddress nextHop = IpAddress.valueOf("5.6.7.8");
75 byte origin = BgpConstants.Update.Origin.IGP;
76 // Setup the AS Path
77 ArrayList<BgpRouteEntry.PathSegment> pathSegments = new ArrayList<>();
78 byte pathSegmentType1 = (byte) BgpConstants.Update.AsPath.AS_SEQUENCE;
79 ArrayList<Long> segmentAsNumbers1 = new ArrayList<>();
80 segmentAsNumbers1.add((long) 1);
81 segmentAsNumbers1.add((long) 2);
82 segmentAsNumbers1.add((long) 3);
83 BgpRouteEntry.PathSegment pathSegment1 =
84 new BgpRouteEntry.PathSegment(pathSegmentType1, segmentAsNumbers1);
85 pathSegments.add(pathSegment1);
86 //
87 byte pathSegmentType2 = (byte) BgpConstants.Update.AsPath.AS_SET;
88 ArrayList<Long> segmentAsNumbers2 = new ArrayList<>();
89 segmentAsNumbers2.add((long) 4);
90 segmentAsNumbers2.add((long) 5);
91 segmentAsNumbers2.add((long) 6);
92 BgpRouteEntry.PathSegment pathSegment2 =
93 new BgpRouteEntry.PathSegment(pathSegmentType2, segmentAsNumbers2);
94 pathSegments.add(pathSegment2);
95 //
96 BgpRouteEntry.AsPath asPath = new BgpRouteEntry.AsPath(pathSegments);
97 //
98 long localPref = 100;
99 long multiExitDisc = 20;
100
101 BgpRouteEntry bgpRouteEntry =
102 new BgpRouteEntry(bgpSession, prefix, nextHop, origin, asPath,
103 localPref);
104 bgpRouteEntry.setMultiExitDisc(multiExitDisc);
105
106 return bgpRouteEntry;
107 }
108
109 /**
110 * Tests valid class constructor.
111 */
112 @Test
113 public void testConstructor() {
114 BgpRouteEntry bgpRouteEntry = generateBgpRouteEntry();
115
116 String expectedString =
117 "BgpRouteEntry{prefix=1.2.3.0/24, nextHop=5.6.7.8, " +
118 "bgpId=10.0.0.1, origin=0, asPath=AsPath{pathSegments=" +
119 "[PathSegment{type=2, segmentAsNumbers=[1, 2, 3]}, " +
120 "PathSegment{type=1, segmentAsNumbers=[4, 5, 6]}]}, " +
121 "localPref=100, multiExitDisc=20}";
122 assertThat(bgpRouteEntry.toString(), is(expectedString));
123 }
124
125 /**
126 * Tests invalid class constructor for null BGP Session.
127 */
128 @Test(expected = NullPointerException.class)
129 public void testInvalidConstructorNullBgpSession() {
130 BgpSession bgpSessionNull = null;
131 IpPrefix prefix = IpPrefix.valueOf("1.2.3.0/24");
132 IpAddress nextHop = IpAddress.valueOf("5.6.7.8");
133 byte origin = BgpConstants.Update.Origin.IGP;
134 // Setup the AS Path
135 ArrayList<BgpRouteEntry.PathSegment> pathSegments = new ArrayList<>();
136 BgpRouteEntry.AsPath asPath = new BgpRouteEntry.AsPath(pathSegments);
137 //
138 long localPref = 100;
139
140 new BgpRouteEntry(bgpSessionNull, prefix, nextHop, origin, asPath,
141 localPref);
142 }
143
144 /**
145 * Tests invalid class constructor for null AS Path.
146 */
147 @Test(expected = NullPointerException.class)
148 public void testInvalidConstructorNullAsPath() {
149 IpPrefix prefix = IpPrefix.valueOf("1.2.3.0/24");
150 IpAddress nextHop = IpAddress.valueOf("5.6.7.8");
151 byte origin = BgpConstants.Update.Origin.IGP;
152 BgpRouteEntry.AsPath asPath = null;
153 long localPref = 100;
154
155 new BgpRouteEntry(bgpSession, prefix, nextHop, origin, asPath,
156 localPref);
157 }
158
159 /**
160 * Tests getting the fields of a BGP route entry.
161 */
162 @Test
163 public void testGetFields() {
164 // Create the fields to compare against
165 IpPrefix prefix = IpPrefix.valueOf("1.2.3.0/24");
166 IpAddress nextHop = IpAddress.valueOf("5.6.7.8");
167 byte origin = BgpConstants.Update.Origin.IGP;
168 // Setup the AS Path
169 ArrayList<BgpRouteEntry.PathSegment> pathSegments = new ArrayList<>();
170 byte pathSegmentType1 = (byte) BgpConstants.Update.AsPath.AS_SEQUENCE;
171 ArrayList<Long> segmentAsNumbers1 = new ArrayList<>();
172 segmentAsNumbers1.add((long) 1);
173 segmentAsNumbers1.add((long) 2);
174 segmentAsNumbers1.add((long) 3);
175 BgpRouteEntry.PathSegment pathSegment1 =
176 new BgpRouteEntry.PathSegment(pathSegmentType1, segmentAsNumbers1);
177 pathSegments.add(pathSegment1);
178 //
179 byte pathSegmentType2 = (byte) BgpConstants.Update.AsPath.AS_SET;
180 ArrayList<Long> segmentAsNumbers2 = new ArrayList<>();
181 segmentAsNumbers2.add((long) 4);
182 segmentAsNumbers2.add((long) 5);
183 segmentAsNumbers2.add((long) 6);
184 BgpRouteEntry.PathSegment pathSegment2 =
185 new BgpRouteEntry.PathSegment(pathSegmentType2, segmentAsNumbers2);
186 pathSegments.add(pathSegment2);
187 //
188 BgpRouteEntry.AsPath asPath = new BgpRouteEntry.AsPath(pathSegments);
189 //
190 long localPref = 100;
191 long multiExitDisc = 20;
192
193 // Generate the entry to test
194 BgpRouteEntry bgpRouteEntry = generateBgpRouteEntry();
195
196 assertThat(bgpRouteEntry.prefix(), is(prefix));
197 assertThat(bgpRouteEntry.nextHop(), is(nextHop));
198 assertThat(bgpRouteEntry.getBgpSession(), is(bgpSession));
199 assertThat(bgpRouteEntry.getOrigin(), is(origin));
200 assertThat(bgpRouteEntry.getAsPath(), is(asPath));
201 assertThat(bgpRouteEntry.getLocalPref(), is(localPref));
202 assertThat(bgpRouteEntry.getMultiExitDisc(), is(multiExitDisc));
203 }
204
205 /**
206 * Tests whether a BGP route entry is a local route.
207 */
208 @Test
209 public void testIsLocalRoute() {
210 //
211 // Test non-local route
212 //
213 BgpRouteEntry bgpRouteEntry = generateBgpRouteEntry();
214 assertThat(bgpRouteEntry.isLocalRoute(), is(false));
215
216 //
217 // Test local route with AS Path that begins with AS_SET
218 //
219 IpPrefix prefix = IpPrefix.valueOf("1.2.3.0/24");
220 IpAddress nextHop = IpAddress.valueOf("5.6.7.8");
221 byte origin = BgpConstants.Update.Origin.IGP;
222 // Setup the AS Path
223 ArrayList<BgpRouteEntry.PathSegment> pathSegments = new ArrayList<>();
224 byte pathSegmentType1 = (byte) BgpConstants.Update.AsPath.AS_SET;
225 ArrayList<Long> segmentAsNumbers1 = new ArrayList<>();
226 segmentAsNumbers1.add((long) 1);
227 segmentAsNumbers1.add((long) 2);
228 segmentAsNumbers1.add((long) 3);
229 BgpRouteEntry.PathSegment pathSegment1 =
230 new BgpRouteEntry.PathSegment(pathSegmentType1, segmentAsNumbers1);
231 pathSegments.add(pathSegment1);
232 //
233 byte pathSegmentType2 = (byte) BgpConstants.Update.AsPath.AS_SEQUENCE;
234 ArrayList<Long> segmentAsNumbers2 = new ArrayList<>();
235 segmentAsNumbers2.add((long) 4);
236 segmentAsNumbers2.add((long) 5);
237 segmentAsNumbers2.add((long) 6);
238 BgpRouteEntry.PathSegment pathSegment2 =
239 new BgpRouteEntry.PathSegment(pathSegmentType2, segmentAsNumbers2);
240 pathSegments.add(pathSegment2);
241 //
242 BgpRouteEntry.AsPath asPath = new BgpRouteEntry.AsPath(pathSegments);
243 //
244 long localPref = 100;
245 long multiExitDisc = 20;
246 //
247 bgpRouteEntry =
248 new BgpRouteEntry(bgpSession, prefix, nextHop, origin, asPath,
249 localPref);
250 bgpRouteEntry.setMultiExitDisc(multiExitDisc);
251 assertThat(bgpRouteEntry.isLocalRoute(), is(true));
252
253 //
254 // Test local route with empty AS Path
255 //
256 pathSegments = new ArrayList<>();
257 asPath = new BgpRouteEntry.AsPath(pathSegments);
258 bgpRouteEntry =
259 new BgpRouteEntry(bgpSession, prefix, nextHop, origin, asPath,
260 localPref);
261 bgpRouteEntry.setMultiExitDisc(multiExitDisc);
262 assertThat(bgpRouteEntry.isLocalRoute(), is(true));
263 }
264
265 /**
266 * Tests getting the BGP Neighbor AS number for a route.
267 */
268 @Test
269 public void testGetNeighborAs() {
270 //
271 // Get neighbor AS for non-local route
272 //
273 BgpRouteEntry bgpRouteEntry = generateBgpRouteEntry();
274 assertThat(bgpRouteEntry.getNeighborAs(), is((long) 1));
275
276 //
277 // Get neighbor AS for a local route
278 //
279 IpPrefix prefix = IpPrefix.valueOf("1.2.3.0/24");
280 IpAddress nextHop = IpAddress.valueOf("5.6.7.8");
281 byte origin = BgpConstants.Update.Origin.IGP;
282 // Setup the AS Path
283 ArrayList<BgpRouteEntry.PathSegment> pathSegments = new ArrayList<>();
284 BgpRouteEntry.AsPath asPath = new BgpRouteEntry.AsPath(pathSegments);
285 //
286 long localPref = 100;
287 long multiExitDisc = 20;
288 //
289 bgpRouteEntry =
290 new BgpRouteEntry(bgpSession, prefix, nextHop, origin, asPath,
291 localPref);
292 bgpRouteEntry.setMultiExitDisc(multiExitDisc);
293 assertThat(bgpRouteEntry.getNeighborAs(), is(BgpConstants.BGP_AS_0));
294 }
295
296 /**
297 * Tests whether a BGP route entry has AS Path loop.
298 */
299 @Test
300 public void testHasAsPathLoop() {
301 BgpRouteEntry bgpRouteEntry = generateBgpRouteEntry();
302
303 // Test for loops: test each AS number in the interval [1, 6]
304 for (int i = 1; i <= 6; i++) {
305 assertThat(bgpRouteEntry.hasAsPathLoop(i), is(true));
306 }
307
308 // Test for non-loops
309 assertThat(bgpRouteEntry.hasAsPathLoop(500), is(false));
310 }
311
312 /**
313 * Tests the BGP Decision Process comparison of BGP routes.
314 */
315 @Test
316 public void testBgpDecisionProcessComparison() {
317 BgpRouteEntry bgpRouteEntry1 = generateBgpRouteEntry();
318 BgpRouteEntry bgpRouteEntry2 = generateBgpRouteEntry();
319
320 //
321 // Compare two routes that are same
322 //
323 assertThat(bgpRouteEntry1.isBetterThan(bgpRouteEntry2), is(true));
324 assertThat(bgpRouteEntry2.isBetterThan(bgpRouteEntry1), is(true));
325
326 //
327 // Compare two routes with different LOCAL_PREF
328 //
329 IpPrefix prefix = IpPrefix.valueOf("1.2.3.0/24");
330 IpAddress nextHop = IpAddress.valueOf("5.6.7.8");
331 byte origin = BgpConstants.Update.Origin.IGP;
332 // Setup the AS Path
333 ArrayList<BgpRouteEntry.PathSegment> pathSegments = new ArrayList<>();
334 byte pathSegmentType1 = (byte) BgpConstants.Update.AsPath.AS_SEQUENCE;
335 ArrayList<Long> segmentAsNumbers1 = new ArrayList<>();
336 segmentAsNumbers1.add((long) 1);
337 segmentAsNumbers1.add((long) 2);
338 segmentAsNumbers1.add((long) 3);
339 BgpRouteEntry.PathSegment pathSegment1 =
340 new BgpRouteEntry.PathSegment(pathSegmentType1, segmentAsNumbers1);
341 pathSegments.add(pathSegment1);
342 //
343 byte pathSegmentType2 = (byte) BgpConstants.Update.AsPath.AS_SET;
344 ArrayList<Long> segmentAsNumbers2 = new ArrayList<>();
345 segmentAsNumbers2.add((long) 4);
346 segmentAsNumbers2.add((long) 5);
347 segmentAsNumbers2.add((long) 6);
348 BgpRouteEntry.PathSegment pathSegment2 =
349 new BgpRouteEntry.PathSegment(pathSegmentType2, segmentAsNumbers2);
350 pathSegments.add(pathSegment2);
351 //
352 BgpRouteEntry.AsPath asPath = new BgpRouteEntry.AsPath(pathSegments);
353 //
354 long localPref = 50; // Different
355 long multiExitDisc = 20;
356 bgpRouteEntry2 =
357 new BgpRouteEntry(bgpSession, prefix, nextHop, origin, asPath,
358 localPref);
359 bgpRouteEntry2.setMultiExitDisc(multiExitDisc);
360 //
361 assertThat(bgpRouteEntry1.isBetterThan(bgpRouteEntry2), is(true));
362 assertThat(bgpRouteEntry2.isBetterThan(bgpRouteEntry1), is(false));
363 localPref = bgpRouteEntry1.getLocalPref(); // Restore
364
365 //
366 // Compare two routes with different AS_PATH length
367 //
368 ArrayList<BgpRouteEntry.PathSegment> pathSegments2 = new ArrayList<>();
369 pathSegments2.add(pathSegment1);
370 // Different AS Path
371 BgpRouteEntry.AsPath asPath2 = new BgpRouteEntry.AsPath(pathSegments2);
372 bgpRouteEntry2 =
373 new BgpRouteEntry(bgpSession, prefix, nextHop, origin, asPath2,
374 localPref);
375 bgpRouteEntry2.setMultiExitDisc(multiExitDisc);
376 //
377 assertThat(bgpRouteEntry1.isBetterThan(bgpRouteEntry2), is(false));
378 assertThat(bgpRouteEntry2.isBetterThan(bgpRouteEntry1), is(true));
379
380 //
381 // Compare two routes with different ORIGIN
382 //
383 origin = BgpConstants.Update.Origin.EGP; // Different
384 bgpRouteEntry2 =
385 new BgpRouteEntry(bgpSession, prefix, nextHop, origin, asPath,
386 localPref);
387 bgpRouteEntry2.setMultiExitDisc(multiExitDisc);
388 //
389 assertThat(bgpRouteEntry1.isBetterThan(bgpRouteEntry2), is(true));
390 assertThat(bgpRouteEntry2.isBetterThan(bgpRouteEntry1), is(false));
391 origin = bgpRouteEntry1.getOrigin(); // Restore
392
393 //
394 // Compare two routes with different MULTI_EXIT_DISC
395 //
396 multiExitDisc = 10; // Different
397 bgpRouteEntry2 =
398 new BgpRouteEntry(bgpSession, prefix, nextHop, origin, asPath,
399 localPref);
400 bgpRouteEntry2.setMultiExitDisc(multiExitDisc);
401 //
402 assertThat(bgpRouteEntry1.isBetterThan(bgpRouteEntry2), is(true));
403 assertThat(bgpRouteEntry2.isBetterThan(bgpRouteEntry1), is(false));
404 multiExitDisc = bgpRouteEntry1.getMultiExitDisc(); // Restore
405
406 //
407 // Compare two routes with different BGP ID
408 //
409 bgpRouteEntry2 =
410 new BgpRouteEntry(bgpSession2, prefix, nextHop, origin, asPath,
411 localPref);
412 bgpRouteEntry2.setMultiExitDisc(multiExitDisc);
413 //
414 assertThat(bgpRouteEntry1.isBetterThan(bgpRouteEntry2), is(true));
415 assertThat(bgpRouteEntry2.isBetterThan(bgpRouteEntry1), is(false));
416
417 //
418 // Compare two routes with different BGP address
419 //
420 bgpRouteEntry2 =
421 new BgpRouteEntry(bgpSession3, prefix, nextHop, origin, asPath,
422 localPref);
423 bgpRouteEntry2.setMultiExitDisc(multiExitDisc);
424 //
425 assertThat(bgpRouteEntry1.isBetterThan(bgpRouteEntry2), is(true));
426 assertThat(bgpRouteEntry2.isBetterThan(bgpRouteEntry1), is(false));
427 }
428
429 /**
430 * Tests equality of {@link BgpRouteEntry}.
431 */
432 @Test
433 public void testEquality() {
434 BgpRouteEntry bgpRouteEntry1 = generateBgpRouteEntry();
435 BgpRouteEntry bgpRouteEntry2 = generateBgpRouteEntry();
436
437 assertThat(bgpRouteEntry1, is(bgpRouteEntry2));
438 }
439
440 /**
441 * Tests non-equality of {@link BgpRouteEntry}.
442 */
443 @Test
444 public void testNonEquality() {
445 BgpRouteEntry bgpRouteEntry1 = generateBgpRouteEntry();
446
447 // Setup BGP Route 2
448 IpPrefix prefix = IpPrefix.valueOf("1.2.3.0/24");
449 IpAddress nextHop = IpAddress.valueOf("5.6.7.8");
450 byte origin = BgpConstants.Update.Origin.IGP;
451 // Setup the AS Path
452 ArrayList<BgpRouteEntry.PathSegment> pathSegments = new ArrayList<>();
453 byte pathSegmentType1 = (byte) BgpConstants.Update.AsPath.AS_SEQUENCE;
454 ArrayList<Long> segmentAsNumbers1 = new ArrayList<>();
455 segmentAsNumbers1.add((long) 1);
456 segmentAsNumbers1.add((long) 2);
457 segmentAsNumbers1.add((long) 3);
458 BgpRouteEntry.PathSegment pathSegment1 =
459 new BgpRouteEntry.PathSegment(pathSegmentType1, segmentAsNumbers1);
460 pathSegments.add(pathSegment1);
461 //
462 byte pathSegmentType2 = (byte) BgpConstants.Update.AsPath.AS_SET;
463 ArrayList<Long> segmentAsNumbers2 = new ArrayList<>();
464 segmentAsNumbers2.add((long) 4);
465 segmentAsNumbers2.add((long) 5);
466 segmentAsNumbers2.add((long) 6);
467 BgpRouteEntry.PathSegment pathSegment2 =
468 new BgpRouteEntry.PathSegment(pathSegmentType2, segmentAsNumbers2);
469 pathSegments.add(pathSegment2);
470 //
471 BgpRouteEntry.AsPath asPath = new BgpRouteEntry.AsPath(pathSegments);
472 //
473 long localPref = 500; // Different
474 long multiExitDisc = 20;
475 BgpRouteEntry bgpRouteEntry2 =
476 new BgpRouteEntry(bgpSession, prefix, nextHop, origin, asPath,
477 localPref);
478 bgpRouteEntry2.setMultiExitDisc(multiExitDisc);
479
480 assertThat(bgpRouteEntry1, is(not(bgpRouteEntry2)));
481 }
482
483 /**
484 * Tests object string representation.
485 */
486 @Test
487 public void testToString() {
488 BgpRouteEntry bgpRouteEntry = generateBgpRouteEntry();
489
490 String expectedString =
491 "BgpRouteEntry{prefix=1.2.3.0/24, nextHop=5.6.7.8, " +
492 "bgpId=10.0.0.1, origin=0, asPath=AsPath{pathSegments=" +
493 "[PathSegment{type=2, segmentAsNumbers=[1, 2, 3]}, " +
494 "PathSegment{type=1, segmentAsNumbers=[4, 5, 6]}]}, " +
495 "localPref=100, multiExitDisc=20}";
496 assertThat(bgpRouteEntry.toString(), is(expectedString));
497 }
498}