blob: 7769f6ff1c2e0ab8c57e6c0c2ec51911c8b9ae12 [file] [log] [blame]
Thomas Vachuska781d18b2014-10-27 10:31:25 -07001/*
Brian O'Connor5ab426f2016-04-09 01:19:45 -07002 * Copyright 2015-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 Hart41349e92015-02-09 14:14:02 -080016package org.onosproject.routing.bgp;
Jonathan Hart20d8e512014-10-16 11:05:52 -070017
Jonathan Hart41349e92015-02-09 14:14:02 -080018import com.google.common.net.InetAddresses;
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -080019import org.hamcrest.Description;
20import org.hamcrest.TypeSafeMatcher;
Jonathan Hart20d8e512014-10-16 11:05:52 -070021import org.jboss.netty.bootstrap.ClientBootstrap;
22import org.jboss.netty.buffer.ChannelBuffer;
23import org.jboss.netty.channel.Channel;
24import org.jboss.netty.channel.ChannelFactory;
25import org.jboss.netty.channel.ChannelPipeline;
26import org.jboss.netty.channel.ChannelPipelineFactory;
27import org.jboss.netty.channel.Channels;
28import org.jboss.netty.channel.socket.nio.NioClientSocketChannelFactory;
29import org.junit.After;
30import org.junit.Before;
31import org.junit.Test;
Pavlin Radoslavovd26f57a2014-10-23 17:19:45 -070032import org.onlab.junit.TestUtils;
33import org.onlab.junit.TestUtils.TestUtilsException;
Pavlin Radoslavov6b570732014-11-06 13:16:45 -080034import org.onlab.packet.Ip4Address;
35import org.onlab.packet.Ip4Prefix;
Jonathan Hart1ad75f22016-04-13 21:24:13 -070036import org.onosproject.incubator.net.routing.RouteAdminService;
Jonathan Hartd24fafb2015-02-09 17:55:32 -080037import org.osgi.service.component.ComponentContext;
Jonathan Hart20d8e512014-10-16 11:05:52 -070038
Jonathan Hart41349e92015-02-09 14:14:02 -080039import java.net.InetAddress;
40import java.net.InetSocketAddress;
41import java.net.SocketAddress;
42import java.util.ArrayList;
43import java.util.Collection;
Jonathan Hartd24fafb2015-02-09 17:55:32 -080044import java.util.Dictionary;
Jonathan Hart41349e92015-02-09 14:14:02 -080045import java.util.LinkedList;
46import java.util.concurrent.Executors;
47import java.util.concurrent.TimeUnit;
48
Jonathan Hartd24fafb2015-02-09 17:55:32 -080049import static org.easymock.EasyMock.createMock;
Jonathan Hart1ad75f22016-04-13 21:24:13 -070050import static org.easymock.EasyMock.createNiceMock;
Jonathan Hartd24fafb2015-02-09 17:55:32 -080051import static org.easymock.EasyMock.expect;
52import static org.easymock.EasyMock.replay;
Jonathan Hart41349e92015-02-09 14:14:02 -080053import static org.hamcrest.Matchers.hasSize;
54import static org.hamcrest.Matchers.is;
55import static org.hamcrest.Matchers.notNullValue;
56import static org.junit.Assert.assertThat;
Jonathan Hart20d8e512014-10-16 11:05:52 -070057
58/**
59 * Unit tests for the BgpSessionManager class.
60 */
61public class BgpSessionManagerTest {
Pavlin Radoslavov6b570732014-11-06 13:16:45 -080062 private static final Ip4Address IP_LOOPBACK_ID =
63 Ip4Address.valueOf("127.0.0.1");
64 private static final Ip4Address BGP_PEER1_ID =
65 Ip4Address.valueOf("10.0.0.1");
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -080066 private static final Ip4Address BGP_PEER2_ID =
67 Ip4Address.valueOf("10.0.0.2");
68 private static final Ip4Address BGP_PEER3_ID =
69 Ip4Address.valueOf("10.0.0.3");
70 private static final Ip4Address NEXT_HOP1_ROUTER =
71 Ip4Address.valueOf("10.20.30.41");
72 private static final Ip4Address NEXT_HOP2_ROUTER =
73 Ip4Address.valueOf("10.20.30.42");
74 private static final Ip4Address NEXT_HOP3_ROUTER =
75 Ip4Address.valueOf("10.20.30.43");
76
Jonathan Hart20d8e512014-10-16 11:05:52 -070077 private static final long DEFAULT_LOCAL_PREF = 10;
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -080078 private static final long BETTER_LOCAL_PREF = 20;
Jonathan Hart20d8e512014-10-16 11:05:52 -070079 private static final long DEFAULT_MULTI_EXIT_DISC = 20;
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -080080 private static final long BETTER_MULTI_EXIT_DISC = 30;
81
82 BgpRouteEntry.AsPath asPathShort;
83 BgpRouteEntry.AsPath asPathLong;
Jonathan Hart20d8e512014-10-16 11:05:52 -070084
Pavlin Radoslavov23c05692014-12-02 13:18:10 -080085 // Timeout waiting for a message to be received
86 private static final int MESSAGE_TIMEOUT_MS = 5000; // 5s
87
Jonathan Hart1ad75f22016-04-13 21:24:13 -070088 private RouteAdminService routeService;
89
Jonathan Hart20d8e512014-10-16 11:05:52 -070090 // The BGP Session Manager to test
91 private BgpSessionManager bgpSessionManager;
92
93 // Remote Peer state
Pavlin Radoslavov4b5acae2015-01-28 17:09:45 -080094 private final Collection<TestBgpPeer> peers = new LinkedList<>();
95 TestBgpPeer peer1;
96 TestBgpPeer peer2;
97 TestBgpPeer peer3;
Jonathan Hart20d8e512014-10-16 11:05:52 -070098
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -080099 // Local BGP per-peer session state
100 BgpSession bgpSession1;
101 BgpSession bgpSession2;
102 BgpSession bgpSession3;
103
104 // The socket that the remote peers should connect to
Jonathan Hart20d8e512014-10-16 11:05:52 -0700105 private InetSocketAddress connectToSocket;
106
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800107 /**
108 * A class to capture the state for a BGP peer.
109 */
110 private final class TestBgpPeer {
111 private final Ip4Address peerId;
112 private ClientBootstrap peerBootstrap;
113 private TestBgpPeerChannelHandler peerChannelHandler;
114 private TestBgpPeerFrameDecoder peerFrameDecoder =
115 new TestBgpPeerFrameDecoder();
116
117 /**
118 * Constructor.
119 *
120 * @param peerId the peer ID
121 */
122 private TestBgpPeer(Ip4Address peerId) {
123 this.peerId = peerId;
124 peerChannelHandler = new TestBgpPeerChannelHandler(peerId);
125 }
126
127 /**
Jonathan Hartde15e1c2016-02-03 10:51:50 -0800128 * Starts up the BGP peer and connects it to the tested BgpSessionManager
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800129 * instance.
130 *
131 * @param connectToSocket the socket to connect to
132 */
133 private void connect(InetSocketAddress connectToSocket)
134 throws InterruptedException {
135 //
136 // Setup the BGP Peer, i.e., the "remote" BGP router that will
137 // initiate the BGP connection, send BGP UPDATE messages, etc.
138 //
139 ChannelFactory channelFactory =
140 new NioClientSocketChannelFactory(
141 Executors.newCachedThreadPool(),
142 Executors.newCachedThreadPool());
Sho SHIMIZU74626412015-09-11 11:46:27 -0700143 ChannelPipelineFactory pipelineFactory = () -> {
144 // Setup the transmitting pipeline
145 ChannelPipeline pipeline = Channels.pipeline();
146 pipeline.addLast("TestBgpPeerFrameDecoder",
147 peerFrameDecoder);
148 pipeline.addLast("TestBgpPeerChannelHandler",
149 peerChannelHandler);
150 return pipeline;
151 };
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800152
153 peerBootstrap = new ClientBootstrap(channelFactory);
154 peerBootstrap.setOption("child.keepAlive", true);
155 peerBootstrap.setOption("child.tcpNoDelay", true);
156 peerBootstrap.setPipelineFactory(pipelineFactory);
157 peerBootstrap.connect(connectToSocket);
158
159 boolean result;
160 // Wait until the OPEN message is received
161 result = peerFrameDecoder.receivedOpenMessageLatch.await(
162 MESSAGE_TIMEOUT_MS,
163 TimeUnit.MILLISECONDS);
164 assertThat(result, is(true));
165 // Wait until the KEEPALIVE message is received
166 result = peerFrameDecoder.receivedKeepaliveMessageLatch.await(
167 MESSAGE_TIMEOUT_MS,
168 TimeUnit.MILLISECONDS);
169 assertThat(result, is(true));
170
171 for (BgpSession bgpSession : bgpSessionManager.getBgpSessions()) {
Pavlin Radoslavov8a36ce32015-01-28 12:26:57 -0800172 if (bgpSession.remoteInfo().bgpId().equals(BGP_PEER1_ID)) {
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800173 bgpSession1 = bgpSession;
174 }
Pavlin Radoslavov8a36ce32015-01-28 12:26:57 -0800175 if (bgpSession.remoteInfo().bgpId().equals(BGP_PEER2_ID)) {
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800176 bgpSession2 = bgpSession;
177 }
Pavlin Radoslavov8a36ce32015-01-28 12:26:57 -0800178 if (bgpSession.remoteInfo().bgpId().equals(BGP_PEER3_ID)) {
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800179 bgpSession3 = bgpSession;
180 }
181 }
182 }
183 }
184
185 /**
186 * Class that implements a matcher for BgpRouteEntry by considering
187 * the BGP peer the entry was received from.
188 */
189 private static final class BgpRouteEntryAndPeerMatcher
190 extends TypeSafeMatcher<Collection<BgpRouteEntry>> {
191 private final BgpRouteEntry bgpRouteEntry;
192
193 private BgpRouteEntryAndPeerMatcher(BgpRouteEntry bgpRouteEntry) {
194 this.bgpRouteEntry = bgpRouteEntry;
195 }
196
197 @Override
198 public boolean matchesSafely(Collection<BgpRouteEntry> entries) {
199 for (BgpRouteEntry entry : entries) {
200 if (bgpRouteEntry.equals(entry) &&
201 bgpRouteEntry.getBgpSession() == entry.getBgpSession()) {
202 return true;
203 }
204 }
205 return false;
206 }
207
208 @Override
209 public void describeTo(Description description) {
210 description.appendText("BGP route entry lookup for entry \"").
211 appendText(bgpRouteEntry.toString()).
212 appendText("\"");
213 }
214 }
215
216 /**
217 * A helper method used for testing whether a collection of
218 * BGP route entries contains an entry from a specific BGP peer.
219 *
220 * @param bgpRouteEntry the BGP route entry to test
221 * @return an instance of BgpRouteEntryAndPeerMatcher that implements
222 * the matching logic
223 */
224 private static BgpRouteEntryAndPeerMatcher hasBgpRouteEntry(
225 BgpRouteEntry bgpRouteEntry) {
226 return new BgpRouteEntryAndPeerMatcher(bgpRouteEntry);
227 }
228
Ray Milkey8dc82082015-02-20 16:22:38 -0800229 @SuppressWarnings("unchecked")
Jonathan Hart1ad75f22016-04-13 21:24:13 -0700230 private void getDictionaryMock(ComponentContext componentContext) {
Ray Milkey7c251822016-04-06 17:38:25 -0700231 Dictionary dictionary = createMock(Dictionary.class);
Ray Milkey8dc82082015-02-20 16:22:38 -0800232 expect(dictionary.get("bgpPort")).andReturn("0");
233 replay(dictionary);
234 expect(componentContext.getProperties()).andReturn(dictionary);
Ray Milkey8dc82082015-02-20 16:22:38 -0800235 }
236
Jonathan Hart20d8e512014-10-16 11:05:52 -0700237 @Before
238 public void setUp() throws Exception {
Pavlin Radoslavov4b5acae2015-01-28 17:09:45 -0800239 peer1 = new TestBgpPeer(BGP_PEER1_ID);
240 peer2 = new TestBgpPeer(BGP_PEER2_ID);
241 peer3 = new TestBgpPeer(BGP_PEER3_ID);
242 peers.clear();
243 peers.add(peer1);
244 peers.add(peer2);
245 peers.add(peer3);
246
Jonathan Hart20d8e512014-10-16 11:05:52 -0700247 //
248 // Setup the BGP Session Manager to test, and start listening for BGP
249 // connections.
250 //
Jonathan Hart41349e92015-02-09 14:14:02 -0800251 bgpSessionManager = new BgpSessionManager();
Jonathan Hart1ad75f22016-04-13 21:24:13 -0700252
253 routeService = createNiceMock(RouteAdminService.class);
254 replay(routeService);
255 bgpSessionManager.routeService = routeService;
256
Jonathan Hart20d8e512014-10-16 11:05:52 -0700257 // NOTE: We use port 0 to bind on any available port
Jonathan Hartd24fafb2015-02-09 17:55:32 -0800258 ComponentContext componentContext = createMock(ComponentContext.class);
Jonathan Hart1ad75f22016-04-13 21:24:13 -0700259 getDictionaryMock(componentContext);
Jonathan Hartd24fafb2015-02-09 17:55:32 -0800260 replay(componentContext);
261 bgpSessionManager.activate(componentContext);
Jonathan Hart20d8e512014-10-16 11:05:52 -0700262
263 // Get the port number the BGP Session Manager is listening on
264 Channel serverChannel = TestUtils.getField(bgpSessionManager,
265 "serverChannel");
266 SocketAddress socketAddress = serverChannel.getLocalAddress();
267 InetSocketAddress inetSocketAddress =
268 (InetSocketAddress) socketAddress;
Jonathan Hart20d8e512014-10-16 11:05:52 -0700269 InetAddress connectToAddress = InetAddresses.forString("127.0.0.1");
270 connectToSocket = new InetSocketAddress(connectToAddress,
271 inetSocketAddress.getPort());
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800272
273 //
274 // Setup the AS Paths
275 //
276 ArrayList<BgpRouteEntry.PathSegment> pathSegments = new ArrayList<>();
277 byte pathSegmentType1 = (byte) BgpConstants.Update.AsPath.AS_SEQUENCE;
278 ArrayList<Long> segmentAsNumbers1 = new ArrayList<>();
Sho SHIMIZUc14b2a22015-05-05 18:15:13 -0700279 segmentAsNumbers1.add(65010L);
280 segmentAsNumbers1.add(65020L);
281 segmentAsNumbers1.add(65030L);
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800282 BgpRouteEntry.PathSegment pathSegment1 =
283 new BgpRouteEntry.PathSegment(pathSegmentType1, segmentAsNumbers1);
284 pathSegments.add(pathSegment1);
Ray Milkey8dc82082015-02-20 16:22:38 -0800285 asPathShort = new BgpRouteEntry.AsPath(new ArrayList<>(pathSegments));
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800286 //
287 byte pathSegmentType2 = (byte) BgpConstants.Update.AsPath.AS_SET;
288 ArrayList<Long> segmentAsNumbers2 = new ArrayList<>();
Sho SHIMIZUc14b2a22015-05-05 18:15:13 -0700289 segmentAsNumbers2.add(65041L);
290 segmentAsNumbers2.add(65042L);
291 segmentAsNumbers2.add(65043L);
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800292 BgpRouteEntry.PathSegment pathSegment2 =
293 new BgpRouteEntry.PathSegment(pathSegmentType2, segmentAsNumbers2);
294 pathSegments.add(pathSegment2);
295 //
296 asPathLong = new BgpRouteEntry.AsPath(pathSegments);
Jonathan Hart20d8e512014-10-16 11:05:52 -0700297 }
298
299 @After
300 public void tearDown() throws Exception {
Pavlin Radoslavova071b1e2014-11-17 13:37:57 -0800301 bgpSessionManager.stop();
Jonathan Hart20d8e512014-10-16 11:05:52 -0700302 bgpSessionManager = null;
303 }
304
305 /**
306 * Gets BGP RIB-IN routes by waiting until they are received.
Pavlin Radoslavovf8a0f6c2015-02-04 15:31:47 -0800307 * <p>
Pavlin Radoslavov55b5f512014-12-08 09:59:35 -0800308 * NOTE: We keep checking once every 10ms the number of received routes,
Jonathan Hart20d8e512014-10-16 11:05:52 -0700309 * up to 5 seconds.
Pavlin Radoslavovf8a0f6c2015-02-04 15:31:47 -0800310 * </p>
Jonathan Hart20d8e512014-10-16 11:05:52 -0700311 *
312 * @param bgpSession the BGP session that is expected to receive the
313 * routes
314 * @param expectedRoutes the expected number of routes
315 * @return the BGP RIB-IN routes as received within the expected
316 * time interval
317 */
318 private Collection<BgpRouteEntry> waitForBgpRibIn(BgpSession bgpSession,
319 long expectedRoutes)
320 throws InterruptedException {
Pavlin Radoslavov3a0a52e2015-01-06 17:41:37 -0800321 Collection<BgpRouteEntry> bgpRibIn = bgpSession.getBgpRibIn4();
Jonathan Hart20d8e512014-10-16 11:05:52 -0700322
Pavlin Radoslavov55b5f512014-12-08 09:59:35 -0800323 final int maxChecks = 500; // Max wait of 5 seconds
Jonathan Hart20d8e512014-10-16 11:05:52 -0700324 for (int i = 0; i < maxChecks; i++) {
325 if (bgpRibIn.size() == expectedRoutes) {
326 break;
327 }
Pavlin Radoslavov55b5f512014-12-08 09:59:35 -0800328 Thread.sleep(10);
Pavlin Radoslavov3a0a52e2015-01-06 17:41:37 -0800329 bgpRibIn = bgpSession.getBgpRibIn4();
Jonathan Hart20d8e512014-10-16 11:05:52 -0700330 }
331
332 return bgpRibIn;
333 }
334
335 /**
336 * Gets BGP merged routes by waiting until they are received.
Pavlin Radoslavovf8a0f6c2015-02-04 15:31:47 -0800337 * <p>
Pavlin Radoslavov55b5f512014-12-08 09:59:35 -0800338 * NOTE: We keep checking once every 10ms the number of received routes,
Jonathan Hart20d8e512014-10-16 11:05:52 -0700339 * up to 5 seconds.
Pavlin Radoslavovf8a0f6c2015-02-04 15:31:47 -0800340 * </p>
Jonathan Hart20d8e512014-10-16 11:05:52 -0700341 *
342 * @param expectedRoutes the expected number of routes
343 * @return the BGP Session Manager routes as received within the expected
344 * time interval
345 */
346 private Collection<BgpRouteEntry> waitForBgpRoutes(long expectedRoutes)
347 throws InterruptedException {
Pavlin Radoslavov3a0a52e2015-01-06 17:41:37 -0800348 Collection<BgpRouteEntry> bgpRoutes =
349 bgpSessionManager.getBgpRoutes4();
Jonathan Hart20d8e512014-10-16 11:05:52 -0700350
Pavlin Radoslavov55b5f512014-12-08 09:59:35 -0800351 final int maxChecks = 500; // Max wait of 5 seconds
Jonathan Hart20d8e512014-10-16 11:05:52 -0700352 for (int i = 0; i < maxChecks; i++) {
353 if (bgpRoutes.size() == expectedRoutes) {
354 break;
355 }
Pavlin Radoslavov55b5f512014-12-08 09:59:35 -0800356 Thread.sleep(10);
Pavlin Radoslavov3a0a52e2015-01-06 17:41:37 -0800357 bgpRoutes = bgpSessionManager.getBgpRoutes4();
Jonathan Hart20d8e512014-10-16 11:05:52 -0700358 }
359
360 return bgpRoutes;
361 }
362
363 /**
Pavlin Radoslavovf8a0f6c2015-02-04 15:31:47 -0800364 * Gets a merged BGP route by waiting until it is received.
365 * <p>
366 * NOTE: We keep checking once every 10ms whether the route is received,
367 * up to 5 seconds.
368 * </p>
369 *
370 * @param expectedRoute the expected route
371 * @return the merged BGP route if received within the expected time
372 * interval, otherwise null
373 */
374 private BgpRouteEntry waitForBgpRoute(BgpRouteEntry expectedRoute)
375 throws InterruptedException {
376 Collection<BgpRouteEntry> bgpRoutes =
377 bgpSessionManager.getBgpRoutes4();
378
379 final int maxChecks = 500; // Max wait of 5 seconds
380 for (int i = 0; i < maxChecks; i++) {
381 for (BgpRouteEntry bgpRouteEntry : bgpRoutes) {
382 if (bgpRouteEntry.equals(expectedRoute) &&
383 bgpRouteEntry.getBgpSession() ==
384 expectedRoute.getBgpSession()) {
385 return bgpRouteEntry;
386 }
387 }
388 Thread.sleep(10);
389 bgpRoutes = bgpSessionManager.getBgpRoutes4();
390 }
391
392 return null;
393 }
394
395 /**
Jonathan Hart20d8e512014-10-16 11:05:52 -0700396 * Tests that the BGP OPEN messages have been exchanged, followed by
397 * KEEPALIVE.
398 * <p>
399 * The BGP Peer opens the sessions and transmits OPEN Message, eventually
400 * followed by KEEPALIVE. The tested BGP listener should respond by
401 * OPEN Message, followed by KEEPALIVE.
Pavlin Radoslavovf8a0f6c2015-02-04 15:31:47 -0800402 * </p>
Jonathan Hart20d8e512014-10-16 11:05:52 -0700403 *
404 * @throws TestUtilsException TestUtils error
405 */
406 @Test
407 public void testExchangedBgpOpenMessages()
408 throws InterruptedException, TestUtilsException {
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800409 // Initiate the connections
410 peer1.connect(connectToSocket);
411 peer2.connect(connectToSocket);
412 peer3.connect(connectToSocket);
Jonathan Hart20d8e512014-10-16 11:05:52 -0700413
414 //
415 // Test the fields from the BGP OPEN message:
416 // BGP version, AS number, BGP ID
417 //
Pavlin Radoslavov4b5acae2015-01-28 17:09:45 -0800418 for (TestBgpPeer peer : peers) {
419 assertThat(peer.peerFrameDecoder.remoteInfo.bgpVersion(),
420 is(BgpConstants.BGP_VERSION));
421 assertThat(peer.peerFrameDecoder.remoteInfo.bgpId(),
422 is(IP_LOOPBACK_ID));
423 assertThat(peer.peerFrameDecoder.remoteInfo.asNumber(),
424 is(TestBgpPeerChannelHandler.PEER_AS));
425 }
Jonathan Hart20d8e512014-10-16 11:05:52 -0700426
427 //
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800428 // Test that the BgpSession instances have been created
Jonathan Hart20d8e512014-10-16 11:05:52 -0700429 //
430 assertThat(bgpSessionManager.getMyBgpId(), is(IP_LOOPBACK_ID));
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800431 assertThat(bgpSessionManager.getBgpSessions(), hasSize(3));
432 assertThat(bgpSession1, notNullValue());
433 assertThat(bgpSession2, notNullValue());
434 assertThat(bgpSession3, notNullValue());
435 for (BgpSession bgpSession : bgpSessionManager.getBgpSessions()) {
Pavlin Radoslavov8a36ce32015-01-28 12:26:57 -0800436 long sessionAs = bgpSession.localInfo().asNumber();
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800437 assertThat(sessionAs, is(TestBgpPeerChannelHandler.PEER_AS));
438 }
Jonathan Hart20d8e512014-10-16 11:05:52 -0700439 }
440
Pavlin Radoslavov4b5acae2015-01-28 17:09:45 -0800441
442 /**
443 * Tests that the BGP OPEN with Capability messages have been exchanged,
444 * followed by KEEPALIVE.
445 * <p>
446 * The BGP Peer opens the sessions and transmits OPEN Message, eventually
447 * followed by KEEPALIVE. The tested BGP listener should respond by
448 * OPEN Message, followed by KEEPALIVE.
Pavlin Radoslavovf8a0f6c2015-02-04 15:31:47 -0800449 * </p>
Pavlin Radoslavov4b5acae2015-01-28 17:09:45 -0800450 *
451 * @throws TestUtilsException TestUtils error
452 */
453 @Test
454 public void testExchangedBgpOpenCapabilityMessages()
455 throws InterruptedException, TestUtilsException {
456 //
457 // Setup the BGP Capabilities for all peers
458 //
459 for (TestBgpPeer peer : peers) {
460 peer.peerChannelHandler.localInfo.setIpv4Unicast();
461 peer.peerChannelHandler.localInfo.setIpv4Multicast();
462 peer.peerChannelHandler.localInfo.setIpv6Unicast();
463 peer.peerChannelHandler.localInfo.setIpv6Multicast();
464 peer.peerChannelHandler.localInfo.setAs4OctetCapability();
465 peer.peerChannelHandler.localInfo.setAs4Number(
466 TestBgpPeerChannelHandler.PEER_AS4);
467 }
468
469 // Initiate the connections
470 peer1.connect(connectToSocket);
471 peer2.connect(connectToSocket);
472 peer3.connect(connectToSocket);
473
474 //
475 // Test the fields from the BGP OPEN message:
476 // BGP version, BGP ID
477 //
478 for (TestBgpPeer peer : peers) {
479 assertThat(peer.peerFrameDecoder.remoteInfo.bgpVersion(),
480 is(BgpConstants.BGP_VERSION));
481 assertThat(peer.peerFrameDecoder.remoteInfo.bgpId(),
482 is(IP_LOOPBACK_ID));
483 }
484
485 //
486 // Test that the BgpSession instances have been created,
487 // and contain the appropriate BGP session information.
488 //
489 assertThat(bgpSessionManager.getMyBgpId(), is(IP_LOOPBACK_ID));
490 assertThat(bgpSessionManager.getBgpSessions(), hasSize(3));
491 assertThat(bgpSession1, notNullValue());
492 assertThat(bgpSession2, notNullValue());
493 assertThat(bgpSession3, notNullValue());
494 for (BgpSession bgpSession : bgpSessionManager.getBgpSessions()) {
495 BgpSessionInfo localInfo = bgpSession.localInfo();
496 assertThat(localInfo.ipv4Unicast(), is(true));
497 assertThat(localInfo.ipv4Multicast(), is(true));
498 assertThat(localInfo.ipv6Unicast(), is(true));
499 assertThat(localInfo.ipv6Multicast(), is(true));
500 assertThat(localInfo.as4OctetCapability(), is(true));
501 assertThat(localInfo.asNumber(),
502 is(TestBgpPeerChannelHandler.PEER_AS4));
503 assertThat(localInfo.as4Number(),
504 is(TestBgpPeerChannelHandler.PEER_AS4));
505 }
506 }
507
Jonathan Hart20d8e512014-10-16 11:05:52 -0700508 /**
509 * Tests that the BGP UPDATE messages have been received and processed.
510 */
511 @Test
512 public void testProcessedBgpUpdateMessages() throws InterruptedException {
Jonathan Hart20d8e512014-10-16 11:05:52 -0700513 ChannelBuffer message;
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800514 BgpRouteEntry bgpRouteEntry;
515 Collection<BgpRouteEntry> bgpRibIn1;
516 Collection<BgpRouteEntry> bgpRibIn2;
517 Collection<BgpRouteEntry> bgpRibIn3;
Jonathan Hart20d8e512014-10-16 11:05:52 -0700518 Collection<BgpRouteEntry> bgpRoutes;
519
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800520 // Initiate the connections
521 peer1.connect(connectToSocket);
522 peer2.connect(connectToSocket);
523 peer3.connect(connectToSocket);
Jonathan Hart20d8e512014-10-16 11:05:52 -0700524
525 // Prepare routes to add/delete
Pavlin Radoslavov6b570732014-11-06 13:16:45 -0800526 Collection<Ip4Prefix> addedRoutes = new LinkedList<>();
527 Collection<Ip4Prefix> withdrawnRoutes = new LinkedList<>();
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800528
529 //
530 // Add and delete some routes
531 //
Pavlin Radoslavov6b570732014-11-06 13:16:45 -0800532 addedRoutes.add(Ip4Prefix.valueOf("0.0.0.0/0"));
533 addedRoutes.add(Ip4Prefix.valueOf("20.0.0.0/8"));
534 addedRoutes.add(Ip4Prefix.valueOf("30.0.0.0/16"));
535 addedRoutes.add(Ip4Prefix.valueOf("40.0.0.0/24"));
536 addedRoutes.add(Ip4Prefix.valueOf("50.0.0.0/32"));
537 withdrawnRoutes.add(Ip4Prefix.valueOf("60.0.0.0/8"));
538 withdrawnRoutes.add(Ip4Prefix.valueOf("70.0.0.0/16"));
539 withdrawnRoutes.add(Ip4Prefix.valueOf("80.0.0.0/24"));
540 withdrawnRoutes.add(Ip4Prefix.valueOf("90.0.0.0/32"));
Jonathan Hart1ad75f22016-04-13 21:24:13 -0700541
Jonathan Hart20d8e512014-10-16 11:05:52 -0700542 // Write the routes
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800543 message = peer1.peerChannelHandler.prepareBgpUpdate(
544 NEXT_HOP1_ROUTER,
545 DEFAULT_LOCAL_PREF,
546 DEFAULT_MULTI_EXIT_DISC,
547 asPathLong,
548 addedRoutes,
549 withdrawnRoutes);
550 peer1.peerChannelHandler.savedCtx.getChannel().write(message);
551 //
Jonathan Hart20d8e512014-10-16 11:05:52 -0700552 // Check that the routes have been received, processed and stored
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800553 //
554 bgpRibIn1 = waitForBgpRibIn(bgpSession1, 5);
555 assertThat(bgpRibIn1, hasSize(5));
Jonathan Hart20d8e512014-10-16 11:05:52 -0700556 bgpRoutes = waitForBgpRoutes(5);
557 assertThat(bgpRoutes, hasSize(5));
Jonathan Hart20d8e512014-10-16 11:05:52 -0700558 //
559 bgpRouteEntry =
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800560 new BgpRouteEntry(bgpSession1,
Pavlin Radoslavov6b570732014-11-06 13:16:45 -0800561 Ip4Prefix.valueOf("0.0.0.0/0"),
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800562 NEXT_HOP1_ROUTER,
Jonathan Hart20d8e512014-10-16 11:05:52 -0700563 (byte) BgpConstants.Update.Origin.IGP,
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800564 asPathLong,
Jonathan Hart20d8e512014-10-16 11:05:52 -0700565 DEFAULT_LOCAL_PREF);
566 bgpRouteEntry.setMultiExitDisc(DEFAULT_MULTI_EXIT_DISC);
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800567 assertThat(bgpRibIn1, hasBgpRouteEntry(bgpRouteEntry));
Pavlin Radoslavovf8a0f6c2015-02-04 15:31:47 -0800568 assertThat(waitForBgpRoute(bgpRouteEntry), notNullValue());
Jonathan Hart20d8e512014-10-16 11:05:52 -0700569 //
570 bgpRouteEntry =
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800571 new BgpRouteEntry(bgpSession1,
Pavlin Radoslavov6b570732014-11-06 13:16:45 -0800572 Ip4Prefix.valueOf("20.0.0.0/8"),
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800573 NEXT_HOP1_ROUTER,
Jonathan Hart20d8e512014-10-16 11:05:52 -0700574 (byte) BgpConstants.Update.Origin.IGP,
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800575 asPathLong,
Jonathan Hart20d8e512014-10-16 11:05:52 -0700576 DEFAULT_LOCAL_PREF);
577 bgpRouteEntry.setMultiExitDisc(DEFAULT_MULTI_EXIT_DISC);
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800578 assertThat(bgpRibIn1, hasBgpRouteEntry(bgpRouteEntry));
Pavlin Radoslavovf8a0f6c2015-02-04 15:31:47 -0800579 assertThat(waitForBgpRoute(bgpRouteEntry), notNullValue());
Jonathan Hart20d8e512014-10-16 11:05:52 -0700580 //
581 bgpRouteEntry =
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800582 new BgpRouteEntry(bgpSession1,
Pavlin Radoslavov6b570732014-11-06 13:16:45 -0800583 Ip4Prefix.valueOf("30.0.0.0/16"),
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800584 NEXT_HOP1_ROUTER,
Jonathan Hart20d8e512014-10-16 11:05:52 -0700585 (byte) BgpConstants.Update.Origin.IGP,
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800586 asPathLong,
Jonathan Hart20d8e512014-10-16 11:05:52 -0700587 DEFAULT_LOCAL_PREF);
588 bgpRouteEntry.setMultiExitDisc(DEFAULT_MULTI_EXIT_DISC);
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800589 assertThat(bgpRibIn1, hasBgpRouteEntry(bgpRouteEntry));
Pavlin Radoslavovf8a0f6c2015-02-04 15:31:47 -0800590 assertThat(waitForBgpRoute(bgpRouteEntry), notNullValue());
Jonathan Hart20d8e512014-10-16 11:05:52 -0700591 //
592 bgpRouteEntry =
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800593 new BgpRouteEntry(bgpSession1,
Pavlin Radoslavov6b570732014-11-06 13:16:45 -0800594 Ip4Prefix.valueOf("40.0.0.0/24"),
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800595 NEXT_HOP1_ROUTER,
Jonathan Hart20d8e512014-10-16 11:05:52 -0700596 (byte) BgpConstants.Update.Origin.IGP,
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800597 asPathLong,
Jonathan Hart20d8e512014-10-16 11:05:52 -0700598 DEFAULT_LOCAL_PREF);
599 bgpRouteEntry.setMultiExitDisc(DEFAULT_MULTI_EXIT_DISC);
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800600 assertThat(bgpRibIn1, hasBgpRouteEntry(bgpRouteEntry));
Pavlin Radoslavovf8a0f6c2015-02-04 15:31:47 -0800601 assertThat(waitForBgpRoute(bgpRouteEntry), notNullValue());
Jonathan Hart20d8e512014-10-16 11:05:52 -0700602 //
603 bgpRouteEntry =
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800604 new BgpRouteEntry(bgpSession1,
Pavlin Radoslavov6b570732014-11-06 13:16:45 -0800605 Ip4Prefix.valueOf("50.0.0.0/32"),
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800606 NEXT_HOP1_ROUTER,
Jonathan Hart20d8e512014-10-16 11:05:52 -0700607 (byte) BgpConstants.Update.Origin.IGP,
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800608 asPathLong,
Jonathan Hart20d8e512014-10-16 11:05:52 -0700609 DEFAULT_LOCAL_PREF);
610 bgpRouteEntry.setMultiExitDisc(DEFAULT_MULTI_EXIT_DISC);
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800611 assertThat(bgpRibIn1, hasBgpRouteEntry(bgpRouteEntry));
Pavlin Radoslavovf8a0f6c2015-02-04 15:31:47 -0800612 assertThat(waitForBgpRoute(bgpRouteEntry), notNullValue());
Jonathan Hart20d8e512014-10-16 11:05:52 -0700613
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800614 //
Jonathan Hart20d8e512014-10-16 11:05:52 -0700615 // Delete some routes
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800616 //
Jonathan Hart20d8e512014-10-16 11:05:52 -0700617 addedRoutes = new LinkedList<>();
618 withdrawnRoutes = new LinkedList<>();
Pavlin Radoslavov6b570732014-11-06 13:16:45 -0800619 withdrawnRoutes.add(Ip4Prefix.valueOf("0.0.0.0/0"));
620 withdrawnRoutes.add(Ip4Prefix.valueOf("50.0.0.0/32"));
Jonathan Hart20d8e512014-10-16 11:05:52 -0700621 // Write the routes
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800622 message = peer1.peerChannelHandler.prepareBgpUpdate(
623 NEXT_HOP1_ROUTER,
624 DEFAULT_LOCAL_PREF,
625 DEFAULT_MULTI_EXIT_DISC,
626 asPathLong,
627 addedRoutes,
628 withdrawnRoutes);
629 peer1.peerChannelHandler.savedCtx.getChannel().write(message);
630 //
Jonathan Hart20d8e512014-10-16 11:05:52 -0700631 // Check that the routes have been received, processed and stored
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800632 //
633 bgpRibIn1 = waitForBgpRibIn(bgpSession1, 3);
634 assertThat(bgpRibIn1, hasSize(3));
Jonathan Hart20d8e512014-10-16 11:05:52 -0700635 bgpRoutes = waitForBgpRoutes(3);
636 assertThat(bgpRoutes, hasSize(3));
637 //
638 bgpRouteEntry =
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800639 new BgpRouteEntry(bgpSession1,
Pavlin Radoslavov6b570732014-11-06 13:16:45 -0800640 Ip4Prefix.valueOf("20.0.0.0/8"),
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800641 NEXT_HOP1_ROUTER,
Jonathan Hart20d8e512014-10-16 11:05:52 -0700642 (byte) BgpConstants.Update.Origin.IGP,
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800643 asPathLong,
Jonathan Hart20d8e512014-10-16 11:05:52 -0700644 DEFAULT_LOCAL_PREF);
645 bgpRouteEntry.setMultiExitDisc(DEFAULT_MULTI_EXIT_DISC);
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800646 assertThat(bgpRibIn1, hasBgpRouteEntry(bgpRouteEntry));
Pavlin Radoslavovf8a0f6c2015-02-04 15:31:47 -0800647 assertThat(waitForBgpRoute(bgpRouteEntry), notNullValue());
Jonathan Hart20d8e512014-10-16 11:05:52 -0700648 //
649 bgpRouteEntry =
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800650 new BgpRouteEntry(bgpSession1,
Pavlin Radoslavov6b570732014-11-06 13:16:45 -0800651 Ip4Prefix.valueOf("30.0.0.0/16"),
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800652 NEXT_HOP1_ROUTER,
Jonathan Hart20d8e512014-10-16 11:05:52 -0700653 (byte) BgpConstants.Update.Origin.IGP,
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800654 asPathLong,
Jonathan Hart20d8e512014-10-16 11:05:52 -0700655 DEFAULT_LOCAL_PREF);
656 bgpRouteEntry.setMultiExitDisc(DEFAULT_MULTI_EXIT_DISC);
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800657 assertThat(bgpRibIn1, hasBgpRouteEntry(bgpRouteEntry));
Pavlin Radoslavovf8a0f6c2015-02-04 15:31:47 -0800658 assertThat(waitForBgpRoute(bgpRouteEntry), notNullValue());
Jonathan Hart20d8e512014-10-16 11:05:52 -0700659 //
660 bgpRouteEntry =
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800661 new BgpRouteEntry(bgpSession1,
Pavlin Radoslavov6b570732014-11-06 13:16:45 -0800662 Ip4Prefix.valueOf("40.0.0.0/24"),
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800663 NEXT_HOP1_ROUTER,
Jonathan Hart20d8e512014-10-16 11:05:52 -0700664 (byte) BgpConstants.Update.Origin.IGP,
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800665 asPathLong,
Jonathan Hart20d8e512014-10-16 11:05:52 -0700666 DEFAULT_LOCAL_PREF);
667 bgpRouteEntry.setMultiExitDisc(DEFAULT_MULTI_EXIT_DISC);
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800668 assertThat(bgpRibIn1, hasBgpRouteEntry(bgpRouteEntry));
Pavlin Radoslavovf8a0f6c2015-02-04 15:31:47 -0800669 assertThat(waitForBgpRoute(bgpRouteEntry), notNullValue());
Jonathan Hart20d8e512014-10-16 11:05:52 -0700670
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800671
672 // Close the channels and test there are no routes
673 peer1.peerChannelHandler.closeChannel();
674 peer2.peerChannelHandler.closeChannel();
675 peer3.peerChannelHandler.closeChannel();
676 bgpRoutes = waitForBgpRoutes(0);
677 assertThat(bgpRoutes, hasSize(0));
678 }
679
680 /**
681 * Tests the BGP route preference.
682 */
683 @Test
684 public void testBgpRoutePreference() throws InterruptedException {
685 ChannelBuffer message;
686 BgpRouteEntry bgpRouteEntry;
687 Collection<BgpRouteEntry> bgpRibIn1;
688 Collection<BgpRouteEntry> bgpRibIn2;
689 Collection<BgpRouteEntry> bgpRibIn3;
690 Collection<BgpRouteEntry> bgpRoutes;
691 Collection<Ip4Prefix> addedRoutes = new LinkedList<>();
692 Collection<Ip4Prefix> withdrawnRoutes = new LinkedList<>();
693
694 // Initiate the connections
695 peer1.connect(connectToSocket);
696 peer2.connect(connectToSocket);
697 peer3.connect(connectToSocket);
698
699 //
700 // Setup the initial set of routes to Peer1
701 //
702 addedRoutes.add(Ip4Prefix.valueOf("20.0.0.0/8"));
703 addedRoutes.add(Ip4Prefix.valueOf("30.0.0.0/16"));
704 // Write the routes
705 message = peer1.peerChannelHandler.prepareBgpUpdate(
706 NEXT_HOP1_ROUTER,
707 DEFAULT_LOCAL_PREF,
708 DEFAULT_MULTI_EXIT_DISC,
709 asPathLong,
710 addedRoutes,
711 withdrawnRoutes);
712 peer1.peerChannelHandler.savedCtx.getChannel().write(message);
713 bgpRoutes = waitForBgpRoutes(2);
714 assertThat(bgpRoutes, hasSize(2));
715
716 //
717 // Add a route entry to Peer2 with a better LOCAL_PREF
718 //
719 addedRoutes = new LinkedList<>();
720 withdrawnRoutes = new LinkedList<>();
721 addedRoutes.add(Ip4Prefix.valueOf("20.0.0.0/8"));
722 // Write the routes
723 message = peer2.peerChannelHandler.prepareBgpUpdate(
724 NEXT_HOP2_ROUTER,
725 BETTER_LOCAL_PREF,
726 DEFAULT_MULTI_EXIT_DISC,
727 asPathLong,
728 addedRoutes,
729 withdrawnRoutes);
730 peer2.peerChannelHandler.savedCtx.getChannel().write(message);
731 //
732 // Check that the routes have been received, processed and stored
733 //
734 bgpRibIn2 = waitForBgpRibIn(bgpSession2, 1);
735 assertThat(bgpRibIn2, hasSize(1));
736 bgpRoutes = waitForBgpRoutes(2);
737 assertThat(bgpRoutes, hasSize(2));
738 //
739 bgpRouteEntry =
740 new BgpRouteEntry(bgpSession2,
741 Ip4Prefix.valueOf("20.0.0.0/8"),
742 NEXT_HOP2_ROUTER,
743 (byte) BgpConstants.Update.Origin.IGP,
744 asPathLong,
745 BETTER_LOCAL_PREF);
746 bgpRouteEntry.setMultiExitDisc(DEFAULT_MULTI_EXIT_DISC);
747 assertThat(bgpRibIn2, hasBgpRouteEntry(bgpRouteEntry));
Pavlin Radoslavovf8a0f6c2015-02-04 15:31:47 -0800748 assertThat(waitForBgpRoute(bgpRouteEntry), notNullValue());
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800749
750 //
751 // Add a route entry to Peer3 with a shorter AS path
752 //
753 addedRoutes = new LinkedList<>();
754 withdrawnRoutes = new LinkedList<>();
755 addedRoutes.add(Ip4Prefix.valueOf("20.0.0.0/8"));
756 // Write the routes
757 message = peer3.peerChannelHandler.prepareBgpUpdate(
758 NEXT_HOP3_ROUTER,
759 BETTER_LOCAL_PREF,
760 DEFAULT_MULTI_EXIT_DISC,
761 asPathShort,
762 addedRoutes,
763 withdrawnRoutes);
764 peer3.peerChannelHandler.savedCtx.getChannel().write(message);
765 //
766 // Check that the routes have been received, processed and stored
767 //
768 bgpRibIn3 = waitForBgpRibIn(bgpSession3, 1);
769 assertThat(bgpRibIn3, hasSize(1));
770 bgpRoutes = waitForBgpRoutes(2);
771 assertThat(bgpRoutes, hasSize(2));
772 //
773 bgpRouteEntry =
774 new BgpRouteEntry(bgpSession3,
775 Ip4Prefix.valueOf("20.0.0.0/8"),
776 NEXT_HOP3_ROUTER,
777 (byte) BgpConstants.Update.Origin.IGP,
778 asPathShort,
779 BETTER_LOCAL_PREF);
780 bgpRouteEntry.setMultiExitDisc(DEFAULT_MULTI_EXIT_DISC);
781 assertThat(bgpRibIn3, hasBgpRouteEntry(bgpRouteEntry));
Pavlin Radoslavovf8a0f6c2015-02-04 15:31:47 -0800782 assertThat(waitForBgpRoute(bgpRouteEntry), notNullValue());
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800783
784 //
785 // Cleanup in preparation for next test: delete old route entry from
786 // Peer2
787 //
788 addedRoutes = new LinkedList<>();
789 withdrawnRoutes = new LinkedList<>();
790 withdrawnRoutes.add(Ip4Prefix.valueOf("20.0.0.0/8"));
791 // Write the routes
792 message = peer2.peerChannelHandler.prepareBgpUpdate(
793 NEXT_HOP2_ROUTER,
794 BETTER_LOCAL_PREF,
795 BETTER_MULTI_EXIT_DISC,
796 asPathShort,
797 addedRoutes,
798 withdrawnRoutes);
799 peer2.peerChannelHandler.savedCtx.getChannel().write(message);
800 //
801 // Check that the routes have been received, processed and stored
802 //
803 bgpRibIn2 = waitForBgpRibIn(bgpSession2, 0);
804 assertThat(bgpRibIn2, hasSize(0));
805
806 //
807 // Add a route entry to Peer2 with a better MED
808 //
809 addedRoutes = new LinkedList<>();
810 withdrawnRoutes = new LinkedList<>();
811 addedRoutes.add(Ip4Prefix.valueOf("20.0.0.0/8"));
812 // Write the routes
813 message = peer2.peerChannelHandler.prepareBgpUpdate(
814 NEXT_HOP2_ROUTER,
815 BETTER_LOCAL_PREF,
816 BETTER_MULTI_EXIT_DISC,
817 asPathShort,
818 addedRoutes,
819 withdrawnRoutes);
820 peer2.peerChannelHandler.savedCtx.getChannel().write(message);
821 //
822 // Check that the routes have been received, processed and stored
823 //
824 bgpRibIn2 = waitForBgpRibIn(bgpSession2, 1);
825 assertThat(bgpRibIn2, hasSize(1));
826 bgpRoutes = waitForBgpRoutes(2);
827 assertThat(bgpRoutes, hasSize(2));
828 //
829 bgpRouteEntry =
830 new BgpRouteEntry(bgpSession2,
831 Ip4Prefix.valueOf("20.0.0.0/8"),
832 NEXT_HOP2_ROUTER,
833 (byte) BgpConstants.Update.Origin.IGP,
834 asPathShort,
835 BETTER_LOCAL_PREF);
836 bgpRouteEntry.setMultiExitDisc(BETTER_MULTI_EXIT_DISC);
837 assertThat(bgpRibIn2, hasBgpRouteEntry(bgpRouteEntry));
Pavlin Radoslavovf8a0f6c2015-02-04 15:31:47 -0800838 assertThat(waitForBgpRoute(bgpRouteEntry), notNullValue());
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800839
840 //
841 // Add a route entry to Peer1 with a better (lower) BGP ID
842 //
843 addedRoutes = new LinkedList<>();
844 withdrawnRoutes = new LinkedList<>();
845 addedRoutes.add(Ip4Prefix.valueOf("20.0.0.0/8"));
846 withdrawnRoutes.add(Ip4Prefix.valueOf("30.0.0.0/16"));
847 // Write the routes
848 message = peer1.peerChannelHandler.prepareBgpUpdate(
849 NEXT_HOP1_ROUTER,
850 BETTER_LOCAL_PREF,
851 BETTER_MULTI_EXIT_DISC,
852 asPathShort,
853 addedRoutes,
854 withdrawnRoutes);
855 peer1.peerChannelHandler.savedCtx.getChannel().write(message);
856 //
857 // Check that the routes have been received, processed and stored
858 //
859 bgpRibIn1 = waitForBgpRibIn(bgpSession1, 1);
860 assertThat(bgpRibIn1, hasSize(1));
861 bgpRoutes = waitForBgpRoutes(1);
862 assertThat(bgpRoutes, hasSize(1));
863 //
864 bgpRouteEntry =
865 new BgpRouteEntry(bgpSession1,
866 Ip4Prefix.valueOf("20.0.0.0/8"),
867 NEXT_HOP1_ROUTER,
868 (byte) BgpConstants.Update.Origin.IGP,
869 asPathShort,
870 BETTER_LOCAL_PREF);
871 bgpRouteEntry.setMultiExitDisc(BETTER_MULTI_EXIT_DISC);
872 assertThat(bgpRibIn1, hasBgpRouteEntry(bgpRouteEntry));
Pavlin Radoslavovf8a0f6c2015-02-04 15:31:47 -0800873 assertThat(waitForBgpRoute(bgpRouteEntry), notNullValue());
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800874
875
876 // Close the channels and test there are no routes
877 peer1.peerChannelHandler.closeChannel();
878 peer2.peerChannelHandler.closeChannel();
879 peer3.peerChannelHandler.closeChannel();
Jonathan Hart20d8e512014-10-16 11:05:52 -0700880 bgpRoutes = waitForBgpRoutes(0);
881 assertThat(bgpRoutes, hasSize(0));
882 }
883}