blob: 9f9ad3c8211d23f0eee86bfe651e89425c16e175 [file] [log] [blame]
Thomas Vachuska781d18b2014-10-27 10:31:25 -07001/*
Jonathan Hartf4bd0482017-01-27 15:11:18 -08002 * Copyright 2017-present Open Networking Laboratory
Thomas Vachuska781d18b2014-10-27 10:31:25 -07003 *
Thomas Vachuska4f1a60c2014-10-28 13:39:07 -07004 * 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
Thomas Vachuska781d18b2014-10-27 10:31:25 -07007 *
Thomas Vachuska4f1a60c2014-10-28 13:39:07 -07008 * 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.
Thomas Vachuska781d18b2014-10-27 10:31:25 -070015 */
Jonathan Hartf4bd0482017-01-27 15:11:18 -080016
Jonathan Hart41349e92015-02-09 14:14:02 -080017package org.onosproject.routing.bgp;
Jonathan Hart20d8e512014-10-16 11:05:52 -070018
Jonathan Hart41349e92015-02-09 14:14:02 -080019import com.google.common.net.InetAddresses;
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -080020import org.hamcrest.Description;
21import org.hamcrest.TypeSafeMatcher;
Jonathan Hart20d8e512014-10-16 11:05:52 -070022import org.jboss.netty.bootstrap.ClientBootstrap;
23import org.jboss.netty.buffer.ChannelBuffer;
24import org.jboss.netty.channel.Channel;
25import org.jboss.netty.channel.ChannelFactory;
26import org.jboss.netty.channel.ChannelPipeline;
27import org.jboss.netty.channel.ChannelPipelineFactory;
28import org.jboss.netty.channel.Channels;
29import org.jboss.netty.channel.socket.nio.NioClientSocketChannelFactory;
30import org.junit.After;
31import org.junit.Before;
32import org.junit.Test;
Pavlin Radoslavovd26f57a2014-10-23 17:19:45 -070033import org.onlab.junit.TestUtils;
34import org.onlab.junit.TestUtils.TestUtilsException;
Pavlin Radoslavov6b570732014-11-06 13:16:45 -080035import org.onlab.packet.Ip4Address;
36import org.onlab.packet.Ip4Prefix;
Jonathan Hart1ad75f22016-04-13 21:24:13 -070037import org.onosproject.incubator.net.routing.RouteAdminService;
Jonathan Hartd24fafb2015-02-09 17:55:32 -080038import org.osgi.service.component.ComponentContext;
Jonathan Hart20d8e512014-10-16 11:05:52 -070039
Jonathan Hart41349e92015-02-09 14:14:02 -080040import java.net.InetAddress;
41import java.net.InetSocketAddress;
42import java.net.SocketAddress;
43import java.util.ArrayList;
44import java.util.Collection;
Jonathan Hartd24fafb2015-02-09 17:55:32 -080045import java.util.Dictionary;
Jonathan Hart41349e92015-02-09 14:14:02 -080046import java.util.LinkedList;
47import java.util.concurrent.Executors;
48import java.util.concurrent.TimeUnit;
49
Jonathan Hartd24fafb2015-02-09 17:55:32 -080050import static org.easymock.EasyMock.createMock;
Jonathan Hart1ad75f22016-04-13 21:24:13 -070051import static org.easymock.EasyMock.createNiceMock;
Jonathan Hartd24fafb2015-02-09 17:55:32 -080052import static org.easymock.EasyMock.expect;
53import static org.easymock.EasyMock.replay;
Jonathan Hart41349e92015-02-09 14:14:02 -080054import static org.hamcrest.Matchers.hasSize;
55import static org.hamcrest.Matchers.is;
56import static org.hamcrest.Matchers.notNullValue;
57import static org.junit.Assert.assertThat;
Jonathan Hart20d8e512014-10-16 11:05:52 -070058
59/**
60 * Unit tests for the BgpSessionManager class.
61 */
62public class BgpSessionManagerTest {
Pavlin Radoslavov6b570732014-11-06 13:16:45 -080063 private static final Ip4Address IP_LOOPBACK_ID =
64 Ip4Address.valueOf("127.0.0.1");
65 private static final Ip4Address BGP_PEER1_ID =
66 Ip4Address.valueOf("10.0.0.1");
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -080067 private static final Ip4Address BGP_PEER2_ID =
68 Ip4Address.valueOf("10.0.0.2");
69 private static final Ip4Address BGP_PEER3_ID =
70 Ip4Address.valueOf("10.0.0.3");
71 private static final Ip4Address NEXT_HOP1_ROUTER =
72 Ip4Address.valueOf("10.20.30.41");
73 private static final Ip4Address NEXT_HOP2_ROUTER =
74 Ip4Address.valueOf("10.20.30.42");
75 private static final Ip4Address NEXT_HOP3_ROUTER =
76 Ip4Address.valueOf("10.20.30.43");
77
Jonathan Hart20d8e512014-10-16 11:05:52 -070078 private static final long DEFAULT_LOCAL_PREF = 10;
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -080079 private static final long BETTER_LOCAL_PREF = 20;
Jonathan Hart20d8e512014-10-16 11:05:52 -070080 private static final long DEFAULT_MULTI_EXIT_DISC = 20;
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -080081 private static final long BETTER_MULTI_EXIT_DISC = 30;
82
83 BgpRouteEntry.AsPath asPathShort;
84 BgpRouteEntry.AsPath asPathLong;
Jonathan Hart20d8e512014-10-16 11:05:52 -070085
Pavlin Radoslavov23c05692014-12-02 13:18:10 -080086 // Timeout waiting for a message to be received
87 private static final int MESSAGE_TIMEOUT_MS = 5000; // 5s
88
Jonathan Hart1ad75f22016-04-13 21:24:13 -070089 private RouteAdminService routeService;
90
Jonathan Hart20d8e512014-10-16 11:05:52 -070091 // The BGP Session Manager to test
92 private BgpSessionManager bgpSessionManager;
93
94 // Remote Peer state
Pavlin Radoslavov4b5acae2015-01-28 17:09:45 -080095 private final Collection<TestBgpPeer> peers = new LinkedList<>();
96 TestBgpPeer peer1;
97 TestBgpPeer peer2;
98 TestBgpPeer peer3;
Jonathan Hart20d8e512014-10-16 11:05:52 -070099
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800100 // Local BGP per-peer session state
101 BgpSession bgpSession1;
102 BgpSession bgpSession2;
103 BgpSession bgpSession3;
104
105 // The socket that the remote peers should connect to
Jonathan Hart20d8e512014-10-16 11:05:52 -0700106 private InetSocketAddress connectToSocket;
107
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800108 /**
109 * A class to capture the state for a BGP peer.
110 */
111 private final class TestBgpPeer {
112 private final Ip4Address peerId;
113 private ClientBootstrap peerBootstrap;
114 private TestBgpPeerChannelHandler peerChannelHandler;
115 private TestBgpPeerFrameDecoder peerFrameDecoder =
116 new TestBgpPeerFrameDecoder();
117
118 /**
119 * Constructor.
120 *
121 * @param peerId the peer ID
122 */
123 private TestBgpPeer(Ip4Address peerId) {
124 this.peerId = peerId;
125 peerChannelHandler = new TestBgpPeerChannelHandler(peerId);
126 }
127
128 /**
Jonathan Hartde15e1c2016-02-03 10:51:50 -0800129 * Starts up the BGP peer and connects it to the tested BgpSessionManager
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800130 * instance.
131 *
132 * @param connectToSocket the socket to connect to
133 */
134 private void connect(InetSocketAddress connectToSocket)
135 throws InterruptedException {
136 //
137 // Setup the BGP Peer, i.e., the "remote" BGP router that will
138 // initiate the BGP connection, send BGP UPDATE messages, etc.
139 //
140 ChannelFactory channelFactory =
141 new NioClientSocketChannelFactory(
142 Executors.newCachedThreadPool(),
143 Executors.newCachedThreadPool());
Sho SHIMIZU74626412015-09-11 11:46:27 -0700144 ChannelPipelineFactory pipelineFactory = () -> {
145 // Setup the transmitting pipeline
146 ChannelPipeline pipeline = Channels.pipeline();
147 pipeline.addLast("TestBgpPeerFrameDecoder",
148 peerFrameDecoder);
149 pipeline.addLast("TestBgpPeerChannelHandler",
150 peerChannelHandler);
151 return pipeline;
152 };
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800153
154 peerBootstrap = new ClientBootstrap(channelFactory);
155 peerBootstrap.setOption("child.keepAlive", true);
156 peerBootstrap.setOption("child.tcpNoDelay", true);
157 peerBootstrap.setPipelineFactory(pipelineFactory);
158 peerBootstrap.connect(connectToSocket);
159
160 boolean result;
161 // Wait until the OPEN message is received
162 result = peerFrameDecoder.receivedOpenMessageLatch.await(
163 MESSAGE_TIMEOUT_MS,
164 TimeUnit.MILLISECONDS);
165 assertThat(result, is(true));
166 // Wait until the KEEPALIVE message is received
167 result = peerFrameDecoder.receivedKeepaliveMessageLatch.await(
168 MESSAGE_TIMEOUT_MS,
169 TimeUnit.MILLISECONDS);
170 assertThat(result, is(true));
171
172 for (BgpSession bgpSession : bgpSessionManager.getBgpSessions()) {
Pavlin Radoslavov8a36ce32015-01-28 12:26:57 -0800173 if (bgpSession.remoteInfo().bgpId().equals(BGP_PEER1_ID)) {
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800174 bgpSession1 = bgpSession;
175 }
Pavlin Radoslavov8a36ce32015-01-28 12:26:57 -0800176 if (bgpSession.remoteInfo().bgpId().equals(BGP_PEER2_ID)) {
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800177 bgpSession2 = bgpSession;
178 }
Pavlin Radoslavov8a36ce32015-01-28 12:26:57 -0800179 if (bgpSession.remoteInfo().bgpId().equals(BGP_PEER3_ID)) {
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800180 bgpSession3 = bgpSession;
181 }
182 }
183 }
184 }
185
186 /**
187 * Class that implements a matcher for BgpRouteEntry by considering
188 * the BGP peer the entry was received from.
189 */
190 private static final class BgpRouteEntryAndPeerMatcher
191 extends TypeSafeMatcher<Collection<BgpRouteEntry>> {
192 private final BgpRouteEntry bgpRouteEntry;
193
194 private BgpRouteEntryAndPeerMatcher(BgpRouteEntry bgpRouteEntry) {
195 this.bgpRouteEntry = bgpRouteEntry;
196 }
197
198 @Override
199 public boolean matchesSafely(Collection<BgpRouteEntry> entries) {
200 for (BgpRouteEntry entry : entries) {
201 if (bgpRouteEntry.equals(entry) &&
202 bgpRouteEntry.getBgpSession() == entry.getBgpSession()) {
203 return true;
204 }
205 }
206 return false;
207 }
208
209 @Override
210 public void describeTo(Description description) {
211 description.appendText("BGP route entry lookup for entry \"").
212 appendText(bgpRouteEntry.toString()).
213 appendText("\"");
214 }
215 }
216
217 /**
218 * A helper method used for testing whether a collection of
219 * BGP route entries contains an entry from a specific BGP peer.
220 *
221 * @param bgpRouteEntry the BGP route entry to test
222 * @return an instance of BgpRouteEntryAndPeerMatcher that implements
223 * the matching logic
224 */
225 private static BgpRouteEntryAndPeerMatcher hasBgpRouteEntry(
226 BgpRouteEntry bgpRouteEntry) {
227 return new BgpRouteEntryAndPeerMatcher(bgpRouteEntry);
228 }
229
Ray Milkey8dc82082015-02-20 16:22:38 -0800230 @SuppressWarnings("unchecked")
Jonathan Hart1ad75f22016-04-13 21:24:13 -0700231 private void getDictionaryMock(ComponentContext componentContext) {
Ray Milkey7c251822016-04-06 17:38:25 -0700232 Dictionary dictionary = createMock(Dictionary.class);
Ray Milkey8dc82082015-02-20 16:22:38 -0800233 expect(dictionary.get("bgpPort")).andReturn("0");
234 replay(dictionary);
235 expect(componentContext.getProperties()).andReturn(dictionary);
Ray Milkey8dc82082015-02-20 16:22:38 -0800236 }
237
Jonathan Hart20d8e512014-10-16 11:05:52 -0700238 @Before
239 public void setUp() throws Exception {
Pavlin Radoslavov4b5acae2015-01-28 17:09:45 -0800240 peer1 = new TestBgpPeer(BGP_PEER1_ID);
241 peer2 = new TestBgpPeer(BGP_PEER2_ID);
242 peer3 = new TestBgpPeer(BGP_PEER3_ID);
243 peers.clear();
244 peers.add(peer1);
245 peers.add(peer2);
246 peers.add(peer3);
247
Jonathan Hart20d8e512014-10-16 11:05:52 -0700248 //
249 // Setup the BGP Session Manager to test, and start listening for BGP
250 // connections.
251 //
Jonathan Hart41349e92015-02-09 14:14:02 -0800252 bgpSessionManager = new BgpSessionManager();
Jonathan Hart1ad75f22016-04-13 21:24:13 -0700253
254 routeService = createNiceMock(RouteAdminService.class);
255 replay(routeService);
256 bgpSessionManager.routeService = routeService;
257
Jonathan Hart20d8e512014-10-16 11:05:52 -0700258 // NOTE: We use port 0 to bind on any available port
Jonathan Hartd24fafb2015-02-09 17:55:32 -0800259 ComponentContext componentContext = createMock(ComponentContext.class);
Jonathan Hart1ad75f22016-04-13 21:24:13 -0700260 getDictionaryMock(componentContext);
Jonathan Hartd24fafb2015-02-09 17:55:32 -0800261 replay(componentContext);
262 bgpSessionManager.activate(componentContext);
Jonathan Hart20d8e512014-10-16 11:05:52 -0700263
264 // Get the port number the BGP Session Manager is listening on
265 Channel serverChannel = TestUtils.getField(bgpSessionManager,
266 "serverChannel");
267 SocketAddress socketAddress = serverChannel.getLocalAddress();
268 InetSocketAddress inetSocketAddress =
269 (InetSocketAddress) socketAddress;
Jonathan Hart20d8e512014-10-16 11:05:52 -0700270 InetAddress connectToAddress = InetAddresses.forString("127.0.0.1");
271 connectToSocket = new InetSocketAddress(connectToAddress,
272 inetSocketAddress.getPort());
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800273
274 //
275 // Setup the AS Paths
276 //
277 ArrayList<BgpRouteEntry.PathSegment> pathSegments = new ArrayList<>();
278 byte pathSegmentType1 = (byte) BgpConstants.Update.AsPath.AS_SEQUENCE;
279 ArrayList<Long> segmentAsNumbers1 = new ArrayList<>();
Sho SHIMIZUc14b2a22015-05-05 18:15:13 -0700280 segmentAsNumbers1.add(65010L);
281 segmentAsNumbers1.add(65020L);
282 segmentAsNumbers1.add(65030L);
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800283 BgpRouteEntry.PathSegment pathSegment1 =
284 new BgpRouteEntry.PathSegment(pathSegmentType1, segmentAsNumbers1);
285 pathSegments.add(pathSegment1);
Ray Milkey8dc82082015-02-20 16:22:38 -0800286 asPathShort = new BgpRouteEntry.AsPath(new ArrayList<>(pathSegments));
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800287 //
288 byte pathSegmentType2 = (byte) BgpConstants.Update.AsPath.AS_SET;
289 ArrayList<Long> segmentAsNumbers2 = new ArrayList<>();
Sho SHIMIZUc14b2a22015-05-05 18:15:13 -0700290 segmentAsNumbers2.add(65041L);
291 segmentAsNumbers2.add(65042L);
292 segmentAsNumbers2.add(65043L);
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800293 BgpRouteEntry.PathSegment pathSegment2 =
294 new BgpRouteEntry.PathSegment(pathSegmentType2, segmentAsNumbers2);
295 pathSegments.add(pathSegment2);
296 //
297 asPathLong = new BgpRouteEntry.AsPath(pathSegments);
Jonathan Hart20d8e512014-10-16 11:05:52 -0700298 }
299
300 @After
301 public void tearDown() throws Exception {
Pavlin Radoslavova071b1e2014-11-17 13:37:57 -0800302 bgpSessionManager.stop();
Jonathan Hart20d8e512014-10-16 11:05:52 -0700303 bgpSessionManager = null;
304 }
305
306 /**
307 * Gets BGP RIB-IN routes by waiting until they are received.
Pavlin Radoslavovf8a0f6c2015-02-04 15:31:47 -0800308 * <p>
Pavlin Radoslavov55b5f512014-12-08 09:59:35 -0800309 * NOTE: We keep checking once every 10ms the number of received routes,
Jonathan Hart20d8e512014-10-16 11:05:52 -0700310 * up to 5 seconds.
Pavlin Radoslavovf8a0f6c2015-02-04 15:31:47 -0800311 * </p>
Jonathan Hart20d8e512014-10-16 11:05:52 -0700312 *
313 * @param bgpSession the BGP session that is expected to receive the
314 * routes
315 * @param expectedRoutes the expected number of routes
316 * @return the BGP RIB-IN routes as received within the expected
317 * time interval
318 */
319 private Collection<BgpRouteEntry> waitForBgpRibIn(BgpSession bgpSession,
320 long expectedRoutes)
321 throws InterruptedException {
Pavlin Radoslavov3a0a52e2015-01-06 17:41:37 -0800322 Collection<BgpRouteEntry> bgpRibIn = bgpSession.getBgpRibIn4();
Jonathan Hart20d8e512014-10-16 11:05:52 -0700323
Pavlin Radoslavov55b5f512014-12-08 09:59:35 -0800324 final int maxChecks = 500; // Max wait of 5 seconds
Jonathan Hart20d8e512014-10-16 11:05:52 -0700325 for (int i = 0; i < maxChecks; i++) {
326 if (bgpRibIn.size() == expectedRoutes) {
327 break;
328 }
Pavlin Radoslavov55b5f512014-12-08 09:59:35 -0800329 Thread.sleep(10);
Pavlin Radoslavov3a0a52e2015-01-06 17:41:37 -0800330 bgpRibIn = bgpSession.getBgpRibIn4();
Jonathan Hart20d8e512014-10-16 11:05:52 -0700331 }
332
333 return bgpRibIn;
334 }
335
336 /**
337 * Gets BGP merged routes by waiting until they are received.
Pavlin Radoslavovf8a0f6c2015-02-04 15:31:47 -0800338 * <p>
Pavlin Radoslavov55b5f512014-12-08 09:59:35 -0800339 * NOTE: We keep checking once every 10ms the number of received routes,
Jonathan Hart20d8e512014-10-16 11:05:52 -0700340 * up to 5 seconds.
Pavlin Radoslavovf8a0f6c2015-02-04 15:31:47 -0800341 * </p>
Jonathan Hart20d8e512014-10-16 11:05:52 -0700342 *
343 * @param expectedRoutes the expected number of routes
344 * @return the BGP Session Manager routes as received within the expected
345 * time interval
346 */
347 private Collection<BgpRouteEntry> waitForBgpRoutes(long expectedRoutes)
348 throws InterruptedException {
Pavlin Radoslavov3a0a52e2015-01-06 17:41:37 -0800349 Collection<BgpRouteEntry> bgpRoutes =
350 bgpSessionManager.getBgpRoutes4();
Jonathan Hart20d8e512014-10-16 11:05:52 -0700351
Pavlin Radoslavov55b5f512014-12-08 09:59:35 -0800352 final int maxChecks = 500; // Max wait of 5 seconds
Jonathan Hart20d8e512014-10-16 11:05:52 -0700353 for (int i = 0; i < maxChecks; i++) {
354 if (bgpRoutes.size() == expectedRoutes) {
355 break;
356 }
Pavlin Radoslavov55b5f512014-12-08 09:59:35 -0800357 Thread.sleep(10);
Pavlin Radoslavov3a0a52e2015-01-06 17:41:37 -0800358 bgpRoutes = bgpSessionManager.getBgpRoutes4();
Jonathan Hart20d8e512014-10-16 11:05:52 -0700359 }
360
361 return bgpRoutes;
362 }
363
364 /**
Pavlin Radoslavovf8a0f6c2015-02-04 15:31:47 -0800365 * Gets a merged BGP route by waiting until it is received.
366 * <p>
367 * NOTE: We keep checking once every 10ms whether the route is received,
368 * up to 5 seconds.
369 * </p>
370 *
371 * @param expectedRoute the expected route
372 * @return the merged BGP route if received within the expected time
373 * interval, otherwise null
374 */
375 private BgpRouteEntry waitForBgpRoute(BgpRouteEntry expectedRoute)
376 throws InterruptedException {
377 Collection<BgpRouteEntry> bgpRoutes =
378 bgpSessionManager.getBgpRoutes4();
379
380 final int maxChecks = 500; // Max wait of 5 seconds
381 for (int i = 0; i < maxChecks; i++) {
382 for (BgpRouteEntry bgpRouteEntry : bgpRoutes) {
383 if (bgpRouteEntry.equals(expectedRoute) &&
384 bgpRouteEntry.getBgpSession() ==
385 expectedRoute.getBgpSession()) {
386 return bgpRouteEntry;
387 }
388 }
389 Thread.sleep(10);
390 bgpRoutes = bgpSessionManager.getBgpRoutes4();
391 }
392
393 return null;
394 }
395
396 /**
Jonathan Hart20d8e512014-10-16 11:05:52 -0700397 * Tests that the BGP OPEN messages have been exchanged, followed by
398 * KEEPALIVE.
399 * <p>
400 * The BGP Peer opens the sessions and transmits OPEN Message, eventually
401 * followed by KEEPALIVE. The tested BGP listener should respond by
402 * OPEN Message, followed by KEEPALIVE.
Pavlin Radoslavovf8a0f6c2015-02-04 15:31:47 -0800403 * </p>
Jonathan Hart20d8e512014-10-16 11:05:52 -0700404 *
405 * @throws TestUtilsException TestUtils error
406 */
407 @Test
408 public void testExchangedBgpOpenMessages()
409 throws InterruptedException, TestUtilsException {
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800410 // Initiate the connections
411 peer1.connect(connectToSocket);
412 peer2.connect(connectToSocket);
413 peer3.connect(connectToSocket);
Jonathan Hart20d8e512014-10-16 11:05:52 -0700414
415 //
416 // Test the fields from the BGP OPEN message:
417 // BGP version, AS number, BGP ID
418 //
Pavlin Radoslavov4b5acae2015-01-28 17:09:45 -0800419 for (TestBgpPeer peer : peers) {
420 assertThat(peer.peerFrameDecoder.remoteInfo.bgpVersion(),
421 is(BgpConstants.BGP_VERSION));
422 assertThat(peer.peerFrameDecoder.remoteInfo.bgpId(),
423 is(IP_LOOPBACK_ID));
424 assertThat(peer.peerFrameDecoder.remoteInfo.asNumber(),
425 is(TestBgpPeerChannelHandler.PEER_AS));
426 }
Jonathan Hart20d8e512014-10-16 11:05:52 -0700427
428 //
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800429 // Test that the BgpSession instances have been created
Jonathan Hart20d8e512014-10-16 11:05:52 -0700430 //
431 assertThat(bgpSessionManager.getMyBgpId(), is(IP_LOOPBACK_ID));
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800432 assertThat(bgpSessionManager.getBgpSessions(), hasSize(3));
433 assertThat(bgpSession1, notNullValue());
434 assertThat(bgpSession2, notNullValue());
435 assertThat(bgpSession3, notNullValue());
436 for (BgpSession bgpSession : bgpSessionManager.getBgpSessions()) {
Pavlin Radoslavov8a36ce32015-01-28 12:26:57 -0800437 long sessionAs = bgpSession.localInfo().asNumber();
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800438 assertThat(sessionAs, is(TestBgpPeerChannelHandler.PEER_AS));
439 }
Jonathan Hart20d8e512014-10-16 11:05:52 -0700440 }
441
Pavlin Radoslavov4b5acae2015-01-28 17:09:45 -0800442
443 /**
444 * Tests that the BGP OPEN with Capability messages have been exchanged,
445 * followed by KEEPALIVE.
446 * <p>
447 * The BGP Peer opens the sessions and transmits OPEN Message, eventually
448 * followed by KEEPALIVE. The tested BGP listener should respond by
449 * OPEN Message, followed by KEEPALIVE.
Pavlin Radoslavovf8a0f6c2015-02-04 15:31:47 -0800450 * </p>
Pavlin Radoslavov4b5acae2015-01-28 17:09:45 -0800451 *
452 * @throws TestUtilsException TestUtils error
453 */
454 @Test
455 public void testExchangedBgpOpenCapabilityMessages()
456 throws InterruptedException, TestUtilsException {
457 //
458 // Setup the BGP Capabilities for all peers
459 //
460 for (TestBgpPeer peer : peers) {
461 peer.peerChannelHandler.localInfo.setIpv4Unicast();
462 peer.peerChannelHandler.localInfo.setIpv4Multicast();
463 peer.peerChannelHandler.localInfo.setIpv6Unicast();
464 peer.peerChannelHandler.localInfo.setIpv6Multicast();
465 peer.peerChannelHandler.localInfo.setAs4OctetCapability();
466 peer.peerChannelHandler.localInfo.setAs4Number(
467 TestBgpPeerChannelHandler.PEER_AS4);
468 }
469
470 // Initiate the connections
471 peer1.connect(connectToSocket);
472 peer2.connect(connectToSocket);
473 peer3.connect(connectToSocket);
474
475 //
476 // Test the fields from the BGP OPEN message:
477 // BGP version, BGP ID
478 //
479 for (TestBgpPeer peer : peers) {
480 assertThat(peer.peerFrameDecoder.remoteInfo.bgpVersion(),
481 is(BgpConstants.BGP_VERSION));
482 assertThat(peer.peerFrameDecoder.remoteInfo.bgpId(),
483 is(IP_LOOPBACK_ID));
484 }
485
486 //
487 // Test that the BgpSession instances have been created,
488 // and contain the appropriate BGP session information.
489 //
490 assertThat(bgpSessionManager.getMyBgpId(), is(IP_LOOPBACK_ID));
491 assertThat(bgpSessionManager.getBgpSessions(), hasSize(3));
492 assertThat(bgpSession1, notNullValue());
493 assertThat(bgpSession2, notNullValue());
494 assertThat(bgpSession3, notNullValue());
495 for (BgpSession bgpSession : bgpSessionManager.getBgpSessions()) {
496 BgpSessionInfo localInfo = bgpSession.localInfo();
497 assertThat(localInfo.ipv4Unicast(), is(true));
498 assertThat(localInfo.ipv4Multicast(), is(true));
499 assertThat(localInfo.ipv6Unicast(), is(true));
500 assertThat(localInfo.ipv6Multicast(), is(true));
501 assertThat(localInfo.as4OctetCapability(), is(true));
502 assertThat(localInfo.asNumber(),
503 is(TestBgpPeerChannelHandler.PEER_AS4));
504 assertThat(localInfo.as4Number(),
505 is(TestBgpPeerChannelHandler.PEER_AS4));
506 }
507 }
508
Jonathan Hart20d8e512014-10-16 11:05:52 -0700509 /**
510 * Tests that the BGP UPDATE messages have been received and processed.
511 */
512 @Test
513 public void testProcessedBgpUpdateMessages() throws InterruptedException {
Jonathan Hart20d8e512014-10-16 11:05:52 -0700514 ChannelBuffer message;
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800515 BgpRouteEntry bgpRouteEntry;
516 Collection<BgpRouteEntry> bgpRibIn1;
517 Collection<BgpRouteEntry> bgpRibIn2;
518 Collection<BgpRouteEntry> bgpRibIn3;
Jonathan Hart20d8e512014-10-16 11:05:52 -0700519 Collection<BgpRouteEntry> bgpRoutes;
520
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800521 // Initiate the connections
522 peer1.connect(connectToSocket);
523 peer2.connect(connectToSocket);
524 peer3.connect(connectToSocket);
Jonathan Hart20d8e512014-10-16 11:05:52 -0700525
526 // Prepare routes to add/delete
Pavlin Radoslavov6b570732014-11-06 13:16:45 -0800527 Collection<Ip4Prefix> addedRoutes = new LinkedList<>();
528 Collection<Ip4Prefix> withdrawnRoutes = new LinkedList<>();
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800529
530 //
531 // Add and delete some routes
532 //
Pavlin Radoslavov6b570732014-11-06 13:16:45 -0800533 addedRoutes.add(Ip4Prefix.valueOf("0.0.0.0/0"));
534 addedRoutes.add(Ip4Prefix.valueOf("20.0.0.0/8"));
535 addedRoutes.add(Ip4Prefix.valueOf("30.0.0.0/16"));
536 addedRoutes.add(Ip4Prefix.valueOf("40.0.0.0/24"));
537 addedRoutes.add(Ip4Prefix.valueOf("50.0.0.0/32"));
538 withdrawnRoutes.add(Ip4Prefix.valueOf("60.0.0.0/8"));
539 withdrawnRoutes.add(Ip4Prefix.valueOf("70.0.0.0/16"));
540 withdrawnRoutes.add(Ip4Prefix.valueOf("80.0.0.0/24"));
541 withdrawnRoutes.add(Ip4Prefix.valueOf("90.0.0.0/32"));
Jonathan Hart1ad75f22016-04-13 21:24:13 -0700542
Jonathan Hart20d8e512014-10-16 11:05:52 -0700543 // Write the routes
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800544 message = peer1.peerChannelHandler.prepareBgpUpdate(
545 NEXT_HOP1_ROUTER,
546 DEFAULT_LOCAL_PREF,
547 DEFAULT_MULTI_EXIT_DISC,
548 asPathLong,
549 addedRoutes,
550 withdrawnRoutes);
551 peer1.peerChannelHandler.savedCtx.getChannel().write(message);
552 //
Jonathan Hart20d8e512014-10-16 11:05:52 -0700553 // Check that the routes have been received, processed and stored
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800554 //
555 bgpRibIn1 = waitForBgpRibIn(bgpSession1, 5);
556 assertThat(bgpRibIn1, hasSize(5));
Jonathan Hart20d8e512014-10-16 11:05:52 -0700557 bgpRoutes = waitForBgpRoutes(5);
558 assertThat(bgpRoutes, hasSize(5));
Jonathan Hart20d8e512014-10-16 11:05:52 -0700559 //
560 bgpRouteEntry =
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800561 new BgpRouteEntry(bgpSession1,
Pavlin Radoslavov6b570732014-11-06 13:16:45 -0800562 Ip4Prefix.valueOf("0.0.0.0/0"),
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800563 NEXT_HOP1_ROUTER,
Jonathan Hart20d8e512014-10-16 11:05:52 -0700564 (byte) BgpConstants.Update.Origin.IGP,
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800565 asPathLong,
Jonathan Hart20d8e512014-10-16 11:05:52 -0700566 DEFAULT_LOCAL_PREF);
567 bgpRouteEntry.setMultiExitDisc(DEFAULT_MULTI_EXIT_DISC);
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800568 assertThat(bgpRibIn1, hasBgpRouteEntry(bgpRouteEntry));
Pavlin Radoslavovf8a0f6c2015-02-04 15:31:47 -0800569 assertThat(waitForBgpRoute(bgpRouteEntry), notNullValue());
Jonathan Hart20d8e512014-10-16 11:05:52 -0700570 //
571 bgpRouteEntry =
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800572 new BgpRouteEntry(bgpSession1,
Pavlin Radoslavov6b570732014-11-06 13:16:45 -0800573 Ip4Prefix.valueOf("20.0.0.0/8"),
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800574 NEXT_HOP1_ROUTER,
Jonathan Hart20d8e512014-10-16 11:05:52 -0700575 (byte) BgpConstants.Update.Origin.IGP,
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800576 asPathLong,
Jonathan Hart20d8e512014-10-16 11:05:52 -0700577 DEFAULT_LOCAL_PREF);
578 bgpRouteEntry.setMultiExitDisc(DEFAULT_MULTI_EXIT_DISC);
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800579 assertThat(bgpRibIn1, hasBgpRouteEntry(bgpRouteEntry));
Pavlin Radoslavovf8a0f6c2015-02-04 15:31:47 -0800580 assertThat(waitForBgpRoute(bgpRouteEntry), notNullValue());
Jonathan Hart20d8e512014-10-16 11:05:52 -0700581 //
582 bgpRouteEntry =
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800583 new BgpRouteEntry(bgpSession1,
Pavlin Radoslavov6b570732014-11-06 13:16:45 -0800584 Ip4Prefix.valueOf("30.0.0.0/16"),
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800585 NEXT_HOP1_ROUTER,
Jonathan Hart20d8e512014-10-16 11:05:52 -0700586 (byte) BgpConstants.Update.Origin.IGP,
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800587 asPathLong,
Jonathan Hart20d8e512014-10-16 11:05:52 -0700588 DEFAULT_LOCAL_PREF);
589 bgpRouteEntry.setMultiExitDisc(DEFAULT_MULTI_EXIT_DISC);
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800590 assertThat(bgpRibIn1, hasBgpRouteEntry(bgpRouteEntry));
Pavlin Radoslavovf8a0f6c2015-02-04 15:31:47 -0800591 assertThat(waitForBgpRoute(bgpRouteEntry), notNullValue());
Jonathan Hart20d8e512014-10-16 11:05:52 -0700592 //
593 bgpRouteEntry =
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800594 new BgpRouteEntry(bgpSession1,
Pavlin Radoslavov6b570732014-11-06 13:16:45 -0800595 Ip4Prefix.valueOf("40.0.0.0/24"),
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800596 NEXT_HOP1_ROUTER,
Jonathan Hart20d8e512014-10-16 11:05:52 -0700597 (byte) BgpConstants.Update.Origin.IGP,
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800598 asPathLong,
Jonathan Hart20d8e512014-10-16 11:05:52 -0700599 DEFAULT_LOCAL_PREF);
600 bgpRouteEntry.setMultiExitDisc(DEFAULT_MULTI_EXIT_DISC);
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800601 assertThat(bgpRibIn1, hasBgpRouteEntry(bgpRouteEntry));
Pavlin Radoslavovf8a0f6c2015-02-04 15:31:47 -0800602 assertThat(waitForBgpRoute(bgpRouteEntry), notNullValue());
Jonathan Hart20d8e512014-10-16 11:05:52 -0700603 //
604 bgpRouteEntry =
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800605 new BgpRouteEntry(bgpSession1,
Pavlin Radoslavov6b570732014-11-06 13:16:45 -0800606 Ip4Prefix.valueOf("50.0.0.0/32"),
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800607 NEXT_HOP1_ROUTER,
Jonathan Hart20d8e512014-10-16 11:05:52 -0700608 (byte) BgpConstants.Update.Origin.IGP,
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800609 asPathLong,
Jonathan Hart20d8e512014-10-16 11:05:52 -0700610 DEFAULT_LOCAL_PREF);
611 bgpRouteEntry.setMultiExitDisc(DEFAULT_MULTI_EXIT_DISC);
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800612 assertThat(bgpRibIn1, hasBgpRouteEntry(bgpRouteEntry));
Pavlin Radoslavovf8a0f6c2015-02-04 15:31:47 -0800613 assertThat(waitForBgpRoute(bgpRouteEntry), notNullValue());
Jonathan Hart20d8e512014-10-16 11:05:52 -0700614
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800615 //
Jonathan Hart20d8e512014-10-16 11:05:52 -0700616 // Delete some routes
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800617 //
Jonathan Hart20d8e512014-10-16 11:05:52 -0700618 addedRoutes = new LinkedList<>();
619 withdrawnRoutes = new LinkedList<>();
Pavlin Radoslavov6b570732014-11-06 13:16:45 -0800620 withdrawnRoutes.add(Ip4Prefix.valueOf("0.0.0.0/0"));
621 withdrawnRoutes.add(Ip4Prefix.valueOf("50.0.0.0/32"));
Jonathan Hart20d8e512014-10-16 11:05:52 -0700622 // Write the routes
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800623 message = peer1.peerChannelHandler.prepareBgpUpdate(
624 NEXT_HOP1_ROUTER,
625 DEFAULT_LOCAL_PREF,
626 DEFAULT_MULTI_EXIT_DISC,
627 asPathLong,
628 addedRoutes,
629 withdrawnRoutes);
630 peer1.peerChannelHandler.savedCtx.getChannel().write(message);
631 //
Jonathan Hart20d8e512014-10-16 11:05:52 -0700632 // Check that the routes have been received, processed and stored
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800633 //
634 bgpRibIn1 = waitForBgpRibIn(bgpSession1, 3);
635 assertThat(bgpRibIn1, hasSize(3));
Jonathan Hart20d8e512014-10-16 11:05:52 -0700636 bgpRoutes = waitForBgpRoutes(3);
637 assertThat(bgpRoutes, hasSize(3));
638 //
639 bgpRouteEntry =
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800640 new BgpRouteEntry(bgpSession1,
Pavlin Radoslavov6b570732014-11-06 13:16:45 -0800641 Ip4Prefix.valueOf("20.0.0.0/8"),
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800642 NEXT_HOP1_ROUTER,
Jonathan Hart20d8e512014-10-16 11:05:52 -0700643 (byte) BgpConstants.Update.Origin.IGP,
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800644 asPathLong,
Jonathan Hart20d8e512014-10-16 11:05:52 -0700645 DEFAULT_LOCAL_PREF);
646 bgpRouteEntry.setMultiExitDisc(DEFAULT_MULTI_EXIT_DISC);
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800647 assertThat(bgpRibIn1, hasBgpRouteEntry(bgpRouteEntry));
Pavlin Radoslavovf8a0f6c2015-02-04 15:31:47 -0800648 assertThat(waitForBgpRoute(bgpRouteEntry), notNullValue());
Jonathan Hart20d8e512014-10-16 11:05:52 -0700649 //
650 bgpRouteEntry =
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800651 new BgpRouteEntry(bgpSession1,
Pavlin Radoslavov6b570732014-11-06 13:16:45 -0800652 Ip4Prefix.valueOf("30.0.0.0/16"),
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800653 NEXT_HOP1_ROUTER,
Jonathan Hart20d8e512014-10-16 11:05:52 -0700654 (byte) BgpConstants.Update.Origin.IGP,
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800655 asPathLong,
Jonathan Hart20d8e512014-10-16 11:05:52 -0700656 DEFAULT_LOCAL_PREF);
657 bgpRouteEntry.setMultiExitDisc(DEFAULT_MULTI_EXIT_DISC);
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800658 assertThat(bgpRibIn1, hasBgpRouteEntry(bgpRouteEntry));
Pavlin Radoslavovf8a0f6c2015-02-04 15:31:47 -0800659 assertThat(waitForBgpRoute(bgpRouteEntry), notNullValue());
Jonathan Hart20d8e512014-10-16 11:05:52 -0700660 //
661 bgpRouteEntry =
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800662 new BgpRouteEntry(bgpSession1,
Pavlin Radoslavov6b570732014-11-06 13:16:45 -0800663 Ip4Prefix.valueOf("40.0.0.0/24"),
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800664 NEXT_HOP1_ROUTER,
Jonathan Hart20d8e512014-10-16 11:05:52 -0700665 (byte) BgpConstants.Update.Origin.IGP,
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800666 asPathLong,
Jonathan Hart20d8e512014-10-16 11:05:52 -0700667 DEFAULT_LOCAL_PREF);
668 bgpRouteEntry.setMultiExitDisc(DEFAULT_MULTI_EXIT_DISC);
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800669 assertThat(bgpRibIn1, hasBgpRouteEntry(bgpRouteEntry));
Pavlin Radoslavovf8a0f6c2015-02-04 15:31:47 -0800670 assertThat(waitForBgpRoute(bgpRouteEntry), notNullValue());
Jonathan Hart20d8e512014-10-16 11:05:52 -0700671
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800672
673 // Close the channels and test there are no routes
674 peer1.peerChannelHandler.closeChannel();
675 peer2.peerChannelHandler.closeChannel();
676 peer3.peerChannelHandler.closeChannel();
677 bgpRoutes = waitForBgpRoutes(0);
678 assertThat(bgpRoutes, hasSize(0));
679 }
680
681 /**
682 * Tests the BGP route preference.
683 */
684 @Test
685 public void testBgpRoutePreference() throws InterruptedException {
686 ChannelBuffer message;
687 BgpRouteEntry bgpRouteEntry;
688 Collection<BgpRouteEntry> bgpRibIn1;
689 Collection<BgpRouteEntry> bgpRibIn2;
690 Collection<BgpRouteEntry> bgpRibIn3;
691 Collection<BgpRouteEntry> bgpRoutes;
692 Collection<Ip4Prefix> addedRoutes = new LinkedList<>();
693 Collection<Ip4Prefix> withdrawnRoutes = new LinkedList<>();
694
695 // Initiate the connections
696 peer1.connect(connectToSocket);
697 peer2.connect(connectToSocket);
698 peer3.connect(connectToSocket);
699
700 //
701 // Setup the initial set of routes to Peer1
702 //
703 addedRoutes.add(Ip4Prefix.valueOf("20.0.0.0/8"));
704 addedRoutes.add(Ip4Prefix.valueOf("30.0.0.0/16"));
705 // Write the routes
706 message = peer1.peerChannelHandler.prepareBgpUpdate(
707 NEXT_HOP1_ROUTER,
708 DEFAULT_LOCAL_PREF,
709 DEFAULT_MULTI_EXIT_DISC,
710 asPathLong,
711 addedRoutes,
712 withdrawnRoutes);
713 peer1.peerChannelHandler.savedCtx.getChannel().write(message);
714 bgpRoutes = waitForBgpRoutes(2);
715 assertThat(bgpRoutes, hasSize(2));
716
717 //
718 // Add a route entry to Peer2 with a better LOCAL_PREF
719 //
720 addedRoutes = new LinkedList<>();
721 withdrawnRoutes = new LinkedList<>();
722 addedRoutes.add(Ip4Prefix.valueOf("20.0.0.0/8"));
723 // Write the routes
724 message = peer2.peerChannelHandler.prepareBgpUpdate(
725 NEXT_HOP2_ROUTER,
726 BETTER_LOCAL_PREF,
727 DEFAULT_MULTI_EXIT_DISC,
728 asPathLong,
729 addedRoutes,
730 withdrawnRoutes);
731 peer2.peerChannelHandler.savedCtx.getChannel().write(message);
732 //
733 // Check that the routes have been received, processed and stored
734 //
735 bgpRibIn2 = waitForBgpRibIn(bgpSession2, 1);
736 assertThat(bgpRibIn2, hasSize(1));
737 bgpRoutes = waitForBgpRoutes(2);
738 assertThat(bgpRoutes, hasSize(2));
739 //
740 bgpRouteEntry =
741 new BgpRouteEntry(bgpSession2,
742 Ip4Prefix.valueOf("20.0.0.0/8"),
743 NEXT_HOP2_ROUTER,
744 (byte) BgpConstants.Update.Origin.IGP,
745 asPathLong,
746 BETTER_LOCAL_PREF);
747 bgpRouteEntry.setMultiExitDisc(DEFAULT_MULTI_EXIT_DISC);
748 assertThat(bgpRibIn2, hasBgpRouteEntry(bgpRouteEntry));
Pavlin Radoslavovf8a0f6c2015-02-04 15:31:47 -0800749 assertThat(waitForBgpRoute(bgpRouteEntry), notNullValue());
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800750
751 //
752 // Add a route entry to Peer3 with a shorter AS path
753 //
754 addedRoutes = new LinkedList<>();
755 withdrawnRoutes = new LinkedList<>();
756 addedRoutes.add(Ip4Prefix.valueOf("20.0.0.0/8"));
757 // Write the routes
758 message = peer3.peerChannelHandler.prepareBgpUpdate(
759 NEXT_HOP3_ROUTER,
760 BETTER_LOCAL_PREF,
761 DEFAULT_MULTI_EXIT_DISC,
762 asPathShort,
763 addedRoutes,
764 withdrawnRoutes);
765 peer3.peerChannelHandler.savedCtx.getChannel().write(message);
766 //
767 // Check that the routes have been received, processed and stored
768 //
769 bgpRibIn3 = waitForBgpRibIn(bgpSession3, 1);
770 assertThat(bgpRibIn3, hasSize(1));
771 bgpRoutes = waitForBgpRoutes(2);
772 assertThat(bgpRoutes, hasSize(2));
773 //
774 bgpRouteEntry =
775 new BgpRouteEntry(bgpSession3,
776 Ip4Prefix.valueOf("20.0.0.0/8"),
777 NEXT_HOP3_ROUTER,
778 (byte) BgpConstants.Update.Origin.IGP,
779 asPathShort,
780 BETTER_LOCAL_PREF);
781 bgpRouteEntry.setMultiExitDisc(DEFAULT_MULTI_EXIT_DISC);
782 assertThat(bgpRibIn3, hasBgpRouteEntry(bgpRouteEntry));
Pavlin Radoslavovf8a0f6c2015-02-04 15:31:47 -0800783 assertThat(waitForBgpRoute(bgpRouteEntry), notNullValue());
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800784
785 //
786 // Cleanup in preparation for next test: delete old route entry from
787 // Peer2
788 //
789 addedRoutes = new LinkedList<>();
790 withdrawnRoutes = new LinkedList<>();
791 withdrawnRoutes.add(Ip4Prefix.valueOf("20.0.0.0/8"));
792 // Write the routes
793 message = peer2.peerChannelHandler.prepareBgpUpdate(
794 NEXT_HOP2_ROUTER,
795 BETTER_LOCAL_PREF,
796 BETTER_MULTI_EXIT_DISC,
797 asPathShort,
798 addedRoutes,
799 withdrawnRoutes);
800 peer2.peerChannelHandler.savedCtx.getChannel().write(message);
801 //
802 // Check that the routes have been received, processed and stored
803 //
804 bgpRibIn2 = waitForBgpRibIn(bgpSession2, 0);
805 assertThat(bgpRibIn2, hasSize(0));
806
807 //
808 // Add a route entry to Peer2 with a better MED
809 //
810 addedRoutes = new LinkedList<>();
811 withdrawnRoutes = new LinkedList<>();
812 addedRoutes.add(Ip4Prefix.valueOf("20.0.0.0/8"));
813 // Write the routes
814 message = peer2.peerChannelHandler.prepareBgpUpdate(
815 NEXT_HOP2_ROUTER,
816 BETTER_LOCAL_PREF,
817 BETTER_MULTI_EXIT_DISC,
818 asPathShort,
819 addedRoutes,
820 withdrawnRoutes);
821 peer2.peerChannelHandler.savedCtx.getChannel().write(message);
822 //
823 // Check that the routes have been received, processed and stored
824 //
825 bgpRibIn2 = waitForBgpRibIn(bgpSession2, 1);
826 assertThat(bgpRibIn2, hasSize(1));
827 bgpRoutes = waitForBgpRoutes(2);
828 assertThat(bgpRoutes, hasSize(2));
829 //
830 bgpRouteEntry =
831 new BgpRouteEntry(bgpSession2,
832 Ip4Prefix.valueOf("20.0.0.0/8"),
833 NEXT_HOP2_ROUTER,
834 (byte) BgpConstants.Update.Origin.IGP,
835 asPathShort,
836 BETTER_LOCAL_PREF);
837 bgpRouteEntry.setMultiExitDisc(BETTER_MULTI_EXIT_DISC);
838 assertThat(bgpRibIn2, hasBgpRouteEntry(bgpRouteEntry));
Pavlin Radoslavovf8a0f6c2015-02-04 15:31:47 -0800839 assertThat(waitForBgpRoute(bgpRouteEntry), notNullValue());
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800840
841 //
842 // Add a route entry to Peer1 with a better (lower) BGP ID
843 //
844 addedRoutes = new LinkedList<>();
845 withdrawnRoutes = new LinkedList<>();
846 addedRoutes.add(Ip4Prefix.valueOf("20.0.0.0/8"));
847 withdrawnRoutes.add(Ip4Prefix.valueOf("30.0.0.0/16"));
848 // Write the routes
849 message = peer1.peerChannelHandler.prepareBgpUpdate(
850 NEXT_HOP1_ROUTER,
851 BETTER_LOCAL_PREF,
852 BETTER_MULTI_EXIT_DISC,
853 asPathShort,
854 addedRoutes,
855 withdrawnRoutes);
856 peer1.peerChannelHandler.savedCtx.getChannel().write(message);
857 //
858 // Check that the routes have been received, processed and stored
859 //
860 bgpRibIn1 = waitForBgpRibIn(bgpSession1, 1);
861 assertThat(bgpRibIn1, hasSize(1));
862 bgpRoutes = waitForBgpRoutes(1);
863 assertThat(bgpRoutes, hasSize(1));
864 //
865 bgpRouteEntry =
866 new BgpRouteEntry(bgpSession1,
867 Ip4Prefix.valueOf("20.0.0.0/8"),
868 NEXT_HOP1_ROUTER,
869 (byte) BgpConstants.Update.Origin.IGP,
870 asPathShort,
871 BETTER_LOCAL_PREF);
872 bgpRouteEntry.setMultiExitDisc(BETTER_MULTI_EXIT_DISC);
873 assertThat(bgpRibIn1, hasBgpRouteEntry(bgpRouteEntry));
Pavlin Radoslavovf8a0f6c2015-02-04 15:31:47 -0800874 assertThat(waitForBgpRoute(bgpRouteEntry), notNullValue());
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800875
876
877 // Close the channels and test there are no routes
878 peer1.peerChannelHandler.closeChannel();
879 peer2.peerChannelHandler.closeChannel();
880 peer3.peerChannelHandler.closeChannel();
Jonathan Hart20d8e512014-10-16 11:05:52 -0700881 bgpRoutes = waitForBgpRoutes(0);
882 assertThat(bgpRoutes, hasSize(0));
883 }
884}