blob: 7d3414d152550b723abe79c9f08f79fdb287b0e8 [file] [log] [blame]
Thomas Vachuska781d18b2014-10-27 10:31:25 -07001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2017-present Open Networking Foundation
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 Hart10dbafd2017-05-18 15:53:03 -070037import org.onlab.packet.IpAddress;
38import org.onosproject.cluster.ClusterService;
39import org.onosproject.cluster.DefaultControllerNode;
40import org.onosproject.cluster.NodeId;
Ray Milkey69ec8712017-08-08 13:00:43 -070041import org.onosproject.routeservice.RouteAdminService;
Jonathan Hartd24fafb2015-02-09 17:55:32 -080042import org.osgi.service.component.ComponentContext;
Jonathan Hart20d8e512014-10-16 11:05:52 -070043
Jonathan Hart41349e92015-02-09 14:14:02 -080044import java.net.InetAddress;
45import java.net.InetSocketAddress;
46import java.net.SocketAddress;
47import java.util.ArrayList;
48import java.util.Collection;
Jonathan Hartd24fafb2015-02-09 17:55:32 -080049import java.util.Dictionary;
Jonathan Hart41349e92015-02-09 14:14:02 -080050import java.util.LinkedList;
51import java.util.concurrent.Executors;
52import java.util.concurrent.TimeUnit;
53
Jonathan Hartd24fafb2015-02-09 17:55:32 -080054import static org.easymock.EasyMock.createMock;
Jonathan Hart1ad75f22016-04-13 21:24:13 -070055import static org.easymock.EasyMock.createNiceMock;
Jonathan Hartd24fafb2015-02-09 17:55:32 -080056import static org.easymock.EasyMock.expect;
57import static org.easymock.EasyMock.replay;
Jonathan Hart41349e92015-02-09 14:14:02 -080058import static org.hamcrest.Matchers.hasSize;
59import static org.hamcrest.Matchers.is;
60import static org.hamcrest.Matchers.notNullValue;
61import static org.junit.Assert.assertThat;
Jonathan Hart20d8e512014-10-16 11:05:52 -070062
63/**
64 * Unit tests for the BgpSessionManager class.
65 */
66public class BgpSessionManagerTest {
Pavlin Radoslavov6b570732014-11-06 13:16:45 -080067 private static final Ip4Address IP_LOOPBACK_ID =
68 Ip4Address.valueOf("127.0.0.1");
69 private static final Ip4Address BGP_PEER1_ID =
70 Ip4Address.valueOf("10.0.0.1");
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -080071 private static final Ip4Address BGP_PEER2_ID =
72 Ip4Address.valueOf("10.0.0.2");
73 private static final Ip4Address BGP_PEER3_ID =
74 Ip4Address.valueOf("10.0.0.3");
75 private static final Ip4Address NEXT_HOP1_ROUTER =
76 Ip4Address.valueOf("10.20.30.41");
77 private static final Ip4Address NEXT_HOP2_ROUTER =
78 Ip4Address.valueOf("10.20.30.42");
79 private static final Ip4Address NEXT_HOP3_ROUTER =
80 Ip4Address.valueOf("10.20.30.43");
81
Jonathan Hart20d8e512014-10-16 11:05:52 -070082 private static final long DEFAULT_LOCAL_PREF = 10;
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -080083 private static final long BETTER_LOCAL_PREF = 20;
Jonathan Hart20d8e512014-10-16 11:05:52 -070084 private static final long DEFAULT_MULTI_EXIT_DISC = 20;
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -080085 private static final long BETTER_MULTI_EXIT_DISC = 30;
86
Jonathan Hart10dbafd2017-05-18 15:53:03 -070087 private static final NodeId NODE_ID = new NodeId("local");
88 private static final IpAddress LOCAL = IpAddress.valueOf("127.0.0.1");
89
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -080090 BgpRouteEntry.AsPath asPathShort;
91 BgpRouteEntry.AsPath asPathLong;
Jonathan Hart20d8e512014-10-16 11:05:52 -070092
Pavlin Radoslavov23c05692014-12-02 13:18:10 -080093 // Timeout waiting for a message to be received
94 private static final int MESSAGE_TIMEOUT_MS = 5000; // 5s
95
Jonathan Hart1ad75f22016-04-13 21:24:13 -070096 private RouteAdminService routeService;
97
Jonathan Hart20d8e512014-10-16 11:05:52 -070098 // The BGP Session Manager to test
99 private BgpSessionManager bgpSessionManager;
100
101 // Remote Peer state
Pavlin Radoslavov4b5acae2015-01-28 17:09:45 -0800102 private final Collection<TestBgpPeer> peers = new LinkedList<>();
103 TestBgpPeer peer1;
104 TestBgpPeer peer2;
105 TestBgpPeer peer3;
Jonathan Hart20d8e512014-10-16 11:05:52 -0700106
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800107 // Local BGP per-peer session state
108 BgpSession bgpSession1;
109 BgpSession bgpSession2;
110 BgpSession bgpSession3;
111
112 // The socket that the remote peers should connect to
Jonathan Hart20d8e512014-10-16 11:05:52 -0700113 private InetSocketAddress connectToSocket;
114
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800115 /**
116 * A class to capture the state for a BGP peer.
117 */
118 private final class TestBgpPeer {
119 private final Ip4Address peerId;
120 private ClientBootstrap peerBootstrap;
121 private TestBgpPeerChannelHandler peerChannelHandler;
122 private TestBgpPeerFrameDecoder peerFrameDecoder =
123 new TestBgpPeerFrameDecoder();
124
125 /**
126 * Constructor.
127 *
128 * @param peerId the peer ID
129 */
130 private TestBgpPeer(Ip4Address peerId) {
131 this.peerId = peerId;
132 peerChannelHandler = new TestBgpPeerChannelHandler(peerId);
133 }
134
135 /**
Jonathan Hartde15e1c2016-02-03 10:51:50 -0800136 * Starts up the BGP peer and connects it to the tested BgpSessionManager
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800137 * instance.
138 *
139 * @param connectToSocket the socket to connect to
140 */
141 private void connect(InetSocketAddress connectToSocket)
142 throws InterruptedException {
143 //
144 // Setup the BGP Peer, i.e., the "remote" BGP router that will
145 // initiate the BGP connection, send BGP UPDATE messages, etc.
146 //
147 ChannelFactory channelFactory =
148 new NioClientSocketChannelFactory(
149 Executors.newCachedThreadPool(),
150 Executors.newCachedThreadPool());
Sho SHIMIZU74626412015-09-11 11:46:27 -0700151 ChannelPipelineFactory pipelineFactory = () -> {
152 // Setup the transmitting pipeline
153 ChannelPipeline pipeline = Channels.pipeline();
154 pipeline.addLast("TestBgpPeerFrameDecoder",
155 peerFrameDecoder);
156 pipeline.addLast("TestBgpPeerChannelHandler",
157 peerChannelHandler);
158 return pipeline;
159 };
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800160
161 peerBootstrap = new ClientBootstrap(channelFactory);
162 peerBootstrap.setOption("child.keepAlive", true);
163 peerBootstrap.setOption("child.tcpNoDelay", true);
164 peerBootstrap.setPipelineFactory(pipelineFactory);
165 peerBootstrap.connect(connectToSocket);
166
167 boolean result;
168 // Wait until the OPEN message is received
169 result = peerFrameDecoder.receivedOpenMessageLatch.await(
170 MESSAGE_TIMEOUT_MS,
171 TimeUnit.MILLISECONDS);
172 assertThat(result, is(true));
173 // Wait until the KEEPALIVE message is received
174 result = peerFrameDecoder.receivedKeepaliveMessageLatch.await(
175 MESSAGE_TIMEOUT_MS,
176 TimeUnit.MILLISECONDS);
177 assertThat(result, is(true));
178
179 for (BgpSession bgpSession : bgpSessionManager.getBgpSessions()) {
Pavlin Radoslavov8a36ce32015-01-28 12:26:57 -0800180 if (bgpSession.remoteInfo().bgpId().equals(BGP_PEER1_ID)) {
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800181 bgpSession1 = bgpSession;
182 }
Pavlin Radoslavov8a36ce32015-01-28 12:26:57 -0800183 if (bgpSession.remoteInfo().bgpId().equals(BGP_PEER2_ID)) {
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800184 bgpSession2 = bgpSession;
185 }
Pavlin Radoslavov8a36ce32015-01-28 12:26:57 -0800186 if (bgpSession.remoteInfo().bgpId().equals(BGP_PEER3_ID)) {
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800187 bgpSession3 = bgpSession;
188 }
189 }
190 }
191 }
192
193 /**
194 * Class that implements a matcher for BgpRouteEntry by considering
195 * the BGP peer the entry was received from.
196 */
197 private static final class BgpRouteEntryAndPeerMatcher
198 extends TypeSafeMatcher<Collection<BgpRouteEntry>> {
199 private final BgpRouteEntry bgpRouteEntry;
200
201 private BgpRouteEntryAndPeerMatcher(BgpRouteEntry bgpRouteEntry) {
202 this.bgpRouteEntry = bgpRouteEntry;
203 }
204
205 @Override
206 public boolean matchesSafely(Collection<BgpRouteEntry> entries) {
207 for (BgpRouteEntry entry : entries) {
208 if (bgpRouteEntry.equals(entry) &&
209 bgpRouteEntry.getBgpSession() == entry.getBgpSession()) {
210 return true;
211 }
212 }
213 return false;
214 }
215
216 @Override
217 public void describeTo(Description description) {
218 description.appendText("BGP route entry lookup for entry \"").
219 appendText(bgpRouteEntry.toString()).
220 appendText("\"");
221 }
222 }
223
224 /**
225 * A helper method used for testing whether a collection of
226 * BGP route entries contains an entry from a specific BGP peer.
227 *
228 * @param bgpRouteEntry the BGP route entry to test
229 * @return an instance of BgpRouteEntryAndPeerMatcher that implements
230 * the matching logic
231 */
232 private static BgpRouteEntryAndPeerMatcher hasBgpRouteEntry(
233 BgpRouteEntry bgpRouteEntry) {
234 return new BgpRouteEntryAndPeerMatcher(bgpRouteEntry);
235 }
236
Ray Milkey8dc82082015-02-20 16:22:38 -0800237 @SuppressWarnings("unchecked")
Jonathan Hart1ad75f22016-04-13 21:24:13 -0700238 private void getDictionaryMock(ComponentContext componentContext) {
Ray Milkey7c251822016-04-06 17:38:25 -0700239 Dictionary dictionary = createMock(Dictionary.class);
Ray Milkey8dc82082015-02-20 16:22:38 -0800240 expect(dictionary.get("bgpPort")).andReturn("0");
241 replay(dictionary);
242 expect(componentContext.getProperties()).andReturn(dictionary);
Ray Milkey8dc82082015-02-20 16:22:38 -0800243 }
244
Jonathan Hart20d8e512014-10-16 11:05:52 -0700245 @Before
246 public void setUp() throws Exception {
Pavlin Radoslavov4b5acae2015-01-28 17:09:45 -0800247 peer1 = new TestBgpPeer(BGP_PEER1_ID);
248 peer2 = new TestBgpPeer(BGP_PEER2_ID);
249 peer3 = new TestBgpPeer(BGP_PEER3_ID);
250 peers.clear();
251 peers.add(peer1);
252 peers.add(peer2);
253 peers.add(peer3);
254
Jonathan Hart20d8e512014-10-16 11:05:52 -0700255 //
256 // Setup the BGP Session Manager to test, and start listening for BGP
257 // connections.
258 //
Jonathan Hart41349e92015-02-09 14:14:02 -0800259 bgpSessionManager = new BgpSessionManager();
Jonathan Hart1ad75f22016-04-13 21:24:13 -0700260
261 routeService = createNiceMock(RouteAdminService.class);
262 replay(routeService);
263 bgpSessionManager.routeService = routeService;
264
Jonathan Hart10dbafd2017-05-18 15:53:03 -0700265 ClusterService clusterService = createMock(ClusterService.class);
266 expect(clusterService.getLocalNode())
267 .andReturn(new DefaultControllerNode(NODE_ID, LOCAL)).anyTimes();
268 replay(clusterService);
269 bgpSessionManager.clusterService = clusterService;
270
Jonathan Hart20d8e512014-10-16 11:05:52 -0700271 // NOTE: We use port 0 to bind on any available port
Jonathan Hartd24fafb2015-02-09 17:55:32 -0800272 ComponentContext componentContext = createMock(ComponentContext.class);
Jonathan Hart1ad75f22016-04-13 21:24:13 -0700273 getDictionaryMock(componentContext);
Jonathan Hartd24fafb2015-02-09 17:55:32 -0800274 replay(componentContext);
275 bgpSessionManager.activate(componentContext);
Jonathan Hart20d8e512014-10-16 11:05:52 -0700276
277 // Get the port number the BGP Session Manager is listening on
278 Channel serverChannel = TestUtils.getField(bgpSessionManager,
279 "serverChannel");
280 SocketAddress socketAddress = serverChannel.getLocalAddress();
281 InetSocketAddress inetSocketAddress =
282 (InetSocketAddress) socketAddress;
Jonathan Hart20d8e512014-10-16 11:05:52 -0700283 InetAddress connectToAddress = InetAddresses.forString("127.0.0.1");
284 connectToSocket = new InetSocketAddress(connectToAddress,
285 inetSocketAddress.getPort());
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800286
287 //
288 // Setup the AS Paths
289 //
290 ArrayList<BgpRouteEntry.PathSegment> pathSegments = new ArrayList<>();
291 byte pathSegmentType1 = (byte) BgpConstants.Update.AsPath.AS_SEQUENCE;
292 ArrayList<Long> segmentAsNumbers1 = new ArrayList<>();
Sho SHIMIZUc14b2a22015-05-05 18:15:13 -0700293 segmentAsNumbers1.add(65010L);
294 segmentAsNumbers1.add(65020L);
295 segmentAsNumbers1.add(65030L);
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800296 BgpRouteEntry.PathSegment pathSegment1 =
297 new BgpRouteEntry.PathSegment(pathSegmentType1, segmentAsNumbers1);
298 pathSegments.add(pathSegment1);
Ray Milkey8dc82082015-02-20 16:22:38 -0800299 asPathShort = new BgpRouteEntry.AsPath(new ArrayList<>(pathSegments));
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800300 //
301 byte pathSegmentType2 = (byte) BgpConstants.Update.AsPath.AS_SET;
302 ArrayList<Long> segmentAsNumbers2 = new ArrayList<>();
Sho SHIMIZUc14b2a22015-05-05 18:15:13 -0700303 segmentAsNumbers2.add(65041L);
304 segmentAsNumbers2.add(65042L);
305 segmentAsNumbers2.add(65043L);
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800306 BgpRouteEntry.PathSegment pathSegment2 =
307 new BgpRouteEntry.PathSegment(pathSegmentType2, segmentAsNumbers2);
308 pathSegments.add(pathSegment2);
309 //
310 asPathLong = new BgpRouteEntry.AsPath(pathSegments);
Jonathan Hart20d8e512014-10-16 11:05:52 -0700311 }
312
313 @After
314 public void tearDown() throws Exception {
Pavlin Radoslavova071b1e2014-11-17 13:37:57 -0800315 bgpSessionManager.stop();
Jonathan Hart20d8e512014-10-16 11:05:52 -0700316 bgpSessionManager = null;
317 }
318
319 /**
320 * Gets BGP RIB-IN routes by waiting until they are received.
Pavlin Radoslavovf8a0f6c2015-02-04 15:31:47 -0800321 * <p>
Pavlin Radoslavov55b5f512014-12-08 09:59:35 -0800322 * NOTE: We keep checking once every 10ms the number of received routes,
Jonathan Hart20d8e512014-10-16 11:05:52 -0700323 * up to 5 seconds.
Pavlin Radoslavovf8a0f6c2015-02-04 15:31:47 -0800324 * </p>
Jonathan Hart20d8e512014-10-16 11:05:52 -0700325 *
326 * @param bgpSession the BGP session that is expected to receive the
327 * routes
328 * @param expectedRoutes the expected number of routes
329 * @return the BGP RIB-IN routes as received within the expected
330 * time interval
331 */
332 private Collection<BgpRouteEntry> waitForBgpRibIn(BgpSession bgpSession,
333 long expectedRoutes)
334 throws InterruptedException {
Pavlin Radoslavov3a0a52e2015-01-06 17:41:37 -0800335 Collection<BgpRouteEntry> bgpRibIn = bgpSession.getBgpRibIn4();
Jonathan Hart20d8e512014-10-16 11:05:52 -0700336
Pavlin Radoslavov55b5f512014-12-08 09:59:35 -0800337 final int maxChecks = 500; // Max wait of 5 seconds
Jonathan Hart20d8e512014-10-16 11:05:52 -0700338 for (int i = 0; i < maxChecks; i++) {
339 if (bgpRibIn.size() == expectedRoutes) {
340 break;
341 }
Pavlin Radoslavov55b5f512014-12-08 09:59:35 -0800342 Thread.sleep(10);
Pavlin Radoslavov3a0a52e2015-01-06 17:41:37 -0800343 bgpRibIn = bgpSession.getBgpRibIn4();
Jonathan Hart20d8e512014-10-16 11:05:52 -0700344 }
345
346 return bgpRibIn;
347 }
348
349 /**
350 * Gets BGP merged routes by waiting until they are received.
Pavlin Radoslavovf8a0f6c2015-02-04 15:31:47 -0800351 * <p>
Pavlin Radoslavov55b5f512014-12-08 09:59:35 -0800352 * NOTE: We keep checking once every 10ms the number of received routes,
Jonathan Hart20d8e512014-10-16 11:05:52 -0700353 * up to 5 seconds.
Pavlin Radoslavovf8a0f6c2015-02-04 15:31:47 -0800354 * </p>
Jonathan Hart20d8e512014-10-16 11:05:52 -0700355 *
356 * @param expectedRoutes the expected number of routes
357 * @return the BGP Session Manager routes as received within the expected
358 * time interval
359 */
360 private Collection<BgpRouteEntry> waitForBgpRoutes(long expectedRoutes)
361 throws InterruptedException {
Pavlin Radoslavov3a0a52e2015-01-06 17:41:37 -0800362 Collection<BgpRouteEntry> bgpRoutes =
363 bgpSessionManager.getBgpRoutes4();
Jonathan Hart20d8e512014-10-16 11:05:52 -0700364
Pavlin Radoslavov55b5f512014-12-08 09:59:35 -0800365 final int maxChecks = 500; // Max wait of 5 seconds
Jonathan Hart20d8e512014-10-16 11:05:52 -0700366 for (int i = 0; i < maxChecks; i++) {
367 if (bgpRoutes.size() == expectedRoutes) {
368 break;
369 }
Pavlin Radoslavov55b5f512014-12-08 09:59:35 -0800370 Thread.sleep(10);
Pavlin Radoslavov3a0a52e2015-01-06 17:41:37 -0800371 bgpRoutes = bgpSessionManager.getBgpRoutes4();
Jonathan Hart20d8e512014-10-16 11:05:52 -0700372 }
373
374 return bgpRoutes;
375 }
376
377 /**
Pavlin Radoslavovf8a0f6c2015-02-04 15:31:47 -0800378 * Gets a merged BGP route by waiting until it is received.
379 * <p>
380 * NOTE: We keep checking once every 10ms whether the route is received,
381 * up to 5 seconds.
382 * </p>
383 *
384 * @param expectedRoute the expected route
385 * @return the merged BGP route if received within the expected time
386 * interval, otherwise null
387 */
388 private BgpRouteEntry waitForBgpRoute(BgpRouteEntry expectedRoute)
389 throws InterruptedException {
390 Collection<BgpRouteEntry> bgpRoutes =
391 bgpSessionManager.getBgpRoutes4();
392
393 final int maxChecks = 500; // Max wait of 5 seconds
394 for (int i = 0; i < maxChecks; i++) {
395 for (BgpRouteEntry bgpRouteEntry : bgpRoutes) {
396 if (bgpRouteEntry.equals(expectedRoute) &&
397 bgpRouteEntry.getBgpSession() ==
398 expectedRoute.getBgpSession()) {
399 return bgpRouteEntry;
400 }
401 }
402 Thread.sleep(10);
403 bgpRoutes = bgpSessionManager.getBgpRoutes4();
404 }
405
406 return null;
407 }
408
409 /**
Jonathan Hart20d8e512014-10-16 11:05:52 -0700410 * Tests that the BGP OPEN messages have been exchanged, followed by
411 * KEEPALIVE.
412 * <p>
413 * The BGP Peer opens the sessions and transmits OPEN Message, eventually
414 * followed by KEEPALIVE. The tested BGP listener should respond by
415 * OPEN Message, followed by KEEPALIVE.
Pavlin Radoslavovf8a0f6c2015-02-04 15:31:47 -0800416 * </p>
Jonathan Hart20d8e512014-10-16 11:05:52 -0700417 *
418 * @throws TestUtilsException TestUtils error
419 */
420 @Test
421 public void testExchangedBgpOpenMessages()
422 throws InterruptedException, TestUtilsException {
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800423 // Initiate the connections
424 peer1.connect(connectToSocket);
425 peer2.connect(connectToSocket);
426 peer3.connect(connectToSocket);
Jonathan Hart20d8e512014-10-16 11:05:52 -0700427
428 //
429 // Test the fields from the BGP OPEN message:
430 // BGP version, AS number, BGP ID
431 //
Pavlin Radoslavov4b5acae2015-01-28 17:09:45 -0800432 for (TestBgpPeer peer : peers) {
433 assertThat(peer.peerFrameDecoder.remoteInfo.bgpVersion(),
434 is(BgpConstants.BGP_VERSION));
435 assertThat(peer.peerFrameDecoder.remoteInfo.bgpId(),
436 is(IP_LOOPBACK_ID));
437 assertThat(peer.peerFrameDecoder.remoteInfo.asNumber(),
438 is(TestBgpPeerChannelHandler.PEER_AS));
439 }
Jonathan Hart20d8e512014-10-16 11:05:52 -0700440
441 //
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800442 // Test that the BgpSession instances have been created
Jonathan Hart20d8e512014-10-16 11:05:52 -0700443 //
444 assertThat(bgpSessionManager.getMyBgpId(), is(IP_LOOPBACK_ID));
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800445 assertThat(bgpSessionManager.getBgpSessions(), hasSize(3));
446 assertThat(bgpSession1, notNullValue());
447 assertThat(bgpSession2, notNullValue());
448 assertThat(bgpSession3, notNullValue());
449 for (BgpSession bgpSession : bgpSessionManager.getBgpSessions()) {
Pavlin Radoslavov8a36ce32015-01-28 12:26:57 -0800450 long sessionAs = bgpSession.localInfo().asNumber();
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800451 assertThat(sessionAs, is(TestBgpPeerChannelHandler.PEER_AS));
452 }
Jonathan Hart20d8e512014-10-16 11:05:52 -0700453 }
454
Pavlin Radoslavov4b5acae2015-01-28 17:09:45 -0800455
456 /**
457 * Tests that the BGP OPEN with Capability messages have been exchanged,
458 * followed by KEEPALIVE.
459 * <p>
460 * The BGP Peer opens the sessions and transmits OPEN Message, eventually
461 * followed by KEEPALIVE. The tested BGP listener should respond by
462 * OPEN Message, followed by KEEPALIVE.
Pavlin Radoslavovf8a0f6c2015-02-04 15:31:47 -0800463 * </p>
Pavlin Radoslavov4b5acae2015-01-28 17:09:45 -0800464 *
465 * @throws TestUtilsException TestUtils error
466 */
467 @Test
468 public void testExchangedBgpOpenCapabilityMessages()
469 throws InterruptedException, TestUtilsException {
470 //
471 // Setup the BGP Capabilities for all peers
472 //
473 for (TestBgpPeer peer : peers) {
474 peer.peerChannelHandler.localInfo.setIpv4Unicast();
475 peer.peerChannelHandler.localInfo.setIpv4Multicast();
476 peer.peerChannelHandler.localInfo.setIpv6Unicast();
477 peer.peerChannelHandler.localInfo.setIpv6Multicast();
478 peer.peerChannelHandler.localInfo.setAs4OctetCapability();
479 peer.peerChannelHandler.localInfo.setAs4Number(
480 TestBgpPeerChannelHandler.PEER_AS4);
481 }
482
483 // Initiate the connections
484 peer1.connect(connectToSocket);
485 peer2.connect(connectToSocket);
486 peer3.connect(connectToSocket);
487
488 //
489 // Test the fields from the BGP OPEN message:
490 // BGP version, BGP ID
491 //
492 for (TestBgpPeer peer : peers) {
493 assertThat(peer.peerFrameDecoder.remoteInfo.bgpVersion(),
494 is(BgpConstants.BGP_VERSION));
495 assertThat(peer.peerFrameDecoder.remoteInfo.bgpId(),
496 is(IP_LOOPBACK_ID));
497 }
498
499 //
500 // Test that the BgpSession instances have been created,
501 // and contain the appropriate BGP session information.
502 //
503 assertThat(bgpSessionManager.getMyBgpId(), is(IP_LOOPBACK_ID));
504 assertThat(bgpSessionManager.getBgpSessions(), hasSize(3));
505 assertThat(bgpSession1, notNullValue());
506 assertThat(bgpSession2, notNullValue());
507 assertThat(bgpSession3, notNullValue());
508 for (BgpSession bgpSession : bgpSessionManager.getBgpSessions()) {
509 BgpSessionInfo localInfo = bgpSession.localInfo();
510 assertThat(localInfo.ipv4Unicast(), is(true));
511 assertThat(localInfo.ipv4Multicast(), is(true));
512 assertThat(localInfo.ipv6Unicast(), is(true));
513 assertThat(localInfo.ipv6Multicast(), is(true));
514 assertThat(localInfo.as4OctetCapability(), is(true));
515 assertThat(localInfo.asNumber(),
516 is(TestBgpPeerChannelHandler.PEER_AS4));
517 assertThat(localInfo.as4Number(),
518 is(TestBgpPeerChannelHandler.PEER_AS4));
519 }
520 }
521
Jonathan Hart20d8e512014-10-16 11:05:52 -0700522 /**
523 * Tests that the BGP UPDATE messages have been received and processed.
524 */
525 @Test
526 public void testProcessedBgpUpdateMessages() throws InterruptedException {
Jonathan Hart20d8e512014-10-16 11:05:52 -0700527 ChannelBuffer message;
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800528 BgpRouteEntry bgpRouteEntry;
529 Collection<BgpRouteEntry> bgpRibIn1;
530 Collection<BgpRouteEntry> bgpRibIn2;
531 Collection<BgpRouteEntry> bgpRibIn3;
Jonathan Hart20d8e512014-10-16 11:05:52 -0700532 Collection<BgpRouteEntry> bgpRoutes;
533
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800534 // Initiate the connections
535 peer1.connect(connectToSocket);
536 peer2.connect(connectToSocket);
537 peer3.connect(connectToSocket);
Jonathan Hart20d8e512014-10-16 11:05:52 -0700538
539 // Prepare routes to add/delete
Pavlin Radoslavov6b570732014-11-06 13:16:45 -0800540 Collection<Ip4Prefix> addedRoutes = new LinkedList<>();
541 Collection<Ip4Prefix> withdrawnRoutes = new LinkedList<>();
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800542
543 //
544 // Add and delete some routes
545 //
Pavlin Radoslavov6b570732014-11-06 13:16:45 -0800546 addedRoutes.add(Ip4Prefix.valueOf("0.0.0.0/0"));
547 addedRoutes.add(Ip4Prefix.valueOf("20.0.0.0/8"));
548 addedRoutes.add(Ip4Prefix.valueOf("30.0.0.0/16"));
549 addedRoutes.add(Ip4Prefix.valueOf("40.0.0.0/24"));
550 addedRoutes.add(Ip4Prefix.valueOf("50.0.0.0/32"));
551 withdrawnRoutes.add(Ip4Prefix.valueOf("60.0.0.0/8"));
552 withdrawnRoutes.add(Ip4Prefix.valueOf("70.0.0.0/16"));
553 withdrawnRoutes.add(Ip4Prefix.valueOf("80.0.0.0/24"));
554 withdrawnRoutes.add(Ip4Prefix.valueOf("90.0.0.0/32"));
Jonathan Hart1ad75f22016-04-13 21:24:13 -0700555
Jonathan Hart20d8e512014-10-16 11:05:52 -0700556 // Write the routes
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800557 message = peer1.peerChannelHandler.prepareBgpUpdate(
558 NEXT_HOP1_ROUTER,
559 DEFAULT_LOCAL_PREF,
560 DEFAULT_MULTI_EXIT_DISC,
561 asPathLong,
562 addedRoutes,
563 withdrawnRoutes);
564 peer1.peerChannelHandler.savedCtx.getChannel().write(message);
565 //
Jonathan Hart20d8e512014-10-16 11:05:52 -0700566 // Check that the routes have been received, processed and stored
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800567 //
568 bgpRibIn1 = waitForBgpRibIn(bgpSession1, 5);
569 assertThat(bgpRibIn1, hasSize(5));
Jonathan Hart20d8e512014-10-16 11:05:52 -0700570 bgpRoutes = waitForBgpRoutes(5);
571 assertThat(bgpRoutes, hasSize(5));
Jonathan Hart20d8e512014-10-16 11:05:52 -0700572 //
573 bgpRouteEntry =
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800574 new BgpRouteEntry(bgpSession1,
Pavlin Radoslavov6b570732014-11-06 13:16:45 -0800575 Ip4Prefix.valueOf("0.0.0.0/0"),
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800576 NEXT_HOP1_ROUTER,
Jonathan Hart20d8e512014-10-16 11:05:52 -0700577 (byte) BgpConstants.Update.Origin.IGP,
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800578 asPathLong,
Jonathan Hart20d8e512014-10-16 11:05:52 -0700579 DEFAULT_LOCAL_PREF);
580 bgpRouteEntry.setMultiExitDisc(DEFAULT_MULTI_EXIT_DISC);
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800581 assertThat(bgpRibIn1, hasBgpRouteEntry(bgpRouteEntry));
Pavlin Radoslavovf8a0f6c2015-02-04 15:31:47 -0800582 assertThat(waitForBgpRoute(bgpRouteEntry), notNullValue());
Jonathan Hart20d8e512014-10-16 11:05:52 -0700583 //
584 bgpRouteEntry =
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800585 new BgpRouteEntry(bgpSession1,
Pavlin Radoslavov6b570732014-11-06 13:16:45 -0800586 Ip4Prefix.valueOf("20.0.0.0/8"),
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800587 NEXT_HOP1_ROUTER,
Jonathan Hart20d8e512014-10-16 11:05:52 -0700588 (byte) BgpConstants.Update.Origin.IGP,
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800589 asPathLong,
Jonathan Hart20d8e512014-10-16 11:05:52 -0700590 DEFAULT_LOCAL_PREF);
591 bgpRouteEntry.setMultiExitDisc(DEFAULT_MULTI_EXIT_DISC);
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800592 assertThat(bgpRibIn1, hasBgpRouteEntry(bgpRouteEntry));
Pavlin Radoslavovf8a0f6c2015-02-04 15:31:47 -0800593 assertThat(waitForBgpRoute(bgpRouteEntry), notNullValue());
Jonathan Hart20d8e512014-10-16 11:05:52 -0700594 //
595 bgpRouteEntry =
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800596 new BgpRouteEntry(bgpSession1,
Pavlin Radoslavov6b570732014-11-06 13:16:45 -0800597 Ip4Prefix.valueOf("30.0.0.0/16"),
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800598 NEXT_HOP1_ROUTER,
Jonathan Hart20d8e512014-10-16 11:05:52 -0700599 (byte) BgpConstants.Update.Origin.IGP,
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800600 asPathLong,
Jonathan Hart20d8e512014-10-16 11:05:52 -0700601 DEFAULT_LOCAL_PREF);
602 bgpRouteEntry.setMultiExitDisc(DEFAULT_MULTI_EXIT_DISC);
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800603 assertThat(bgpRibIn1, hasBgpRouteEntry(bgpRouteEntry));
Pavlin Radoslavovf8a0f6c2015-02-04 15:31:47 -0800604 assertThat(waitForBgpRoute(bgpRouteEntry), notNullValue());
Jonathan Hart20d8e512014-10-16 11:05:52 -0700605 //
606 bgpRouteEntry =
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800607 new BgpRouteEntry(bgpSession1,
Pavlin Radoslavov6b570732014-11-06 13:16:45 -0800608 Ip4Prefix.valueOf("40.0.0.0/24"),
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800609 NEXT_HOP1_ROUTER,
Jonathan Hart20d8e512014-10-16 11:05:52 -0700610 (byte) BgpConstants.Update.Origin.IGP,
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800611 asPathLong,
Jonathan Hart20d8e512014-10-16 11:05:52 -0700612 DEFAULT_LOCAL_PREF);
613 bgpRouteEntry.setMultiExitDisc(DEFAULT_MULTI_EXIT_DISC);
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800614 assertThat(bgpRibIn1, hasBgpRouteEntry(bgpRouteEntry));
Pavlin Radoslavovf8a0f6c2015-02-04 15:31:47 -0800615 assertThat(waitForBgpRoute(bgpRouteEntry), notNullValue());
Jonathan Hart20d8e512014-10-16 11:05:52 -0700616 //
617 bgpRouteEntry =
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800618 new BgpRouteEntry(bgpSession1,
Pavlin Radoslavov6b570732014-11-06 13:16:45 -0800619 Ip4Prefix.valueOf("50.0.0.0/32"),
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800620 NEXT_HOP1_ROUTER,
Jonathan Hart20d8e512014-10-16 11:05:52 -0700621 (byte) BgpConstants.Update.Origin.IGP,
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800622 asPathLong,
Jonathan Hart20d8e512014-10-16 11:05:52 -0700623 DEFAULT_LOCAL_PREF);
624 bgpRouteEntry.setMultiExitDisc(DEFAULT_MULTI_EXIT_DISC);
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800625 assertThat(bgpRibIn1, hasBgpRouteEntry(bgpRouteEntry));
Pavlin Radoslavovf8a0f6c2015-02-04 15:31:47 -0800626 assertThat(waitForBgpRoute(bgpRouteEntry), notNullValue());
Jonathan Hart20d8e512014-10-16 11:05:52 -0700627
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800628 //
Jonathan Hart20d8e512014-10-16 11:05:52 -0700629 // Delete some routes
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800630 //
Jonathan Hart20d8e512014-10-16 11:05:52 -0700631 addedRoutes = new LinkedList<>();
632 withdrawnRoutes = new LinkedList<>();
Pavlin Radoslavov6b570732014-11-06 13:16:45 -0800633 withdrawnRoutes.add(Ip4Prefix.valueOf("0.0.0.0/0"));
634 withdrawnRoutes.add(Ip4Prefix.valueOf("50.0.0.0/32"));
Jonathan Hart20d8e512014-10-16 11:05:52 -0700635 // Write the routes
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800636 message = peer1.peerChannelHandler.prepareBgpUpdate(
637 NEXT_HOP1_ROUTER,
638 DEFAULT_LOCAL_PREF,
639 DEFAULT_MULTI_EXIT_DISC,
640 asPathLong,
641 addedRoutes,
642 withdrawnRoutes);
643 peer1.peerChannelHandler.savedCtx.getChannel().write(message);
644 //
Jonathan Hart20d8e512014-10-16 11:05:52 -0700645 // Check that the routes have been received, processed and stored
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800646 //
647 bgpRibIn1 = waitForBgpRibIn(bgpSession1, 3);
648 assertThat(bgpRibIn1, hasSize(3));
Jonathan Hart20d8e512014-10-16 11:05:52 -0700649 bgpRoutes = waitForBgpRoutes(3);
650 assertThat(bgpRoutes, hasSize(3));
651 //
652 bgpRouteEntry =
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800653 new BgpRouteEntry(bgpSession1,
Pavlin Radoslavov6b570732014-11-06 13:16:45 -0800654 Ip4Prefix.valueOf("20.0.0.0/8"),
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800655 NEXT_HOP1_ROUTER,
Jonathan Hart20d8e512014-10-16 11:05:52 -0700656 (byte) BgpConstants.Update.Origin.IGP,
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800657 asPathLong,
Jonathan Hart20d8e512014-10-16 11:05:52 -0700658 DEFAULT_LOCAL_PREF);
659 bgpRouteEntry.setMultiExitDisc(DEFAULT_MULTI_EXIT_DISC);
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800660 assertThat(bgpRibIn1, hasBgpRouteEntry(bgpRouteEntry));
Pavlin Radoslavovf8a0f6c2015-02-04 15:31:47 -0800661 assertThat(waitForBgpRoute(bgpRouteEntry), notNullValue());
Jonathan Hart20d8e512014-10-16 11:05:52 -0700662 //
663 bgpRouteEntry =
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800664 new BgpRouteEntry(bgpSession1,
Pavlin Radoslavov6b570732014-11-06 13:16:45 -0800665 Ip4Prefix.valueOf("30.0.0.0/16"),
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800666 NEXT_HOP1_ROUTER,
Jonathan Hart20d8e512014-10-16 11:05:52 -0700667 (byte) BgpConstants.Update.Origin.IGP,
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800668 asPathLong,
Jonathan Hart20d8e512014-10-16 11:05:52 -0700669 DEFAULT_LOCAL_PREF);
670 bgpRouteEntry.setMultiExitDisc(DEFAULT_MULTI_EXIT_DISC);
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800671 assertThat(bgpRibIn1, hasBgpRouteEntry(bgpRouteEntry));
Pavlin Radoslavovf8a0f6c2015-02-04 15:31:47 -0800672 assertThat(waitForBgpRoute(bgpRouteEntry), notNullValue());
Jonathan Hart20d8e512014-10-16 11:05:52 -0700673 //
674 bgpRouteEntry =
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800675 new BgpRouteEntry(bgpSession1,
Pavlin Radoslavov6b570732014-11-06 13:16:45 -0800676 Ip4Prefix.valueOf("40.0.0.0/24"),
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800677 NEXT_HOP1_ROUTER,
Jonathan Hart20d8e512014-10-16 11:05:52 -0700678 (byte) BgpConstants.Update.Origin.IGP,
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800679 asPathLong,
Jonathan Hart20d8e512014-10-16 11:05:52 -0700680 DEFAULT_LOCAL_PREF);
681 bgpRouteEntry.setMultiExitDisc(DEFAULT_MULTI_EXIT_DISC);
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800682 assertThat(bgpRibIn1, hasBgpRouteEntry(bgpRouteEntry));
Pavlin Radoslavovf8a0f6c2015-02-04 15:31:47 -0800683 assertThat(waitForBgpRoute(bgpRouteEntry), notNullValue());
Jonathan Hart20d8e512014-10-16 11:05:52 -0700684
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800685
686 // Close the channels and test there are no routes
687 peer1.peerChannelHandler.closeChannel();
688 peer2.peerChannelHandler.closeChannel();
689 peer3.peerChannelHandler.closeChannel();
690 bgpRoutes = waitForBgpRoutes(0);
691 assertThat(bgpRoutes, hasSize(0));
692 }
693
694 /**
695 * Tests the BGP route preference.
696 */
697 @Test
698 public void testBgpRoutePreference() throws InterruptedException {
699 ChannelBuffer message;
700 BgpRouteEntry bgpRouteEntry;
701 Collection<BgpRouteEntry> bgpRibIn1;
702 Collection<BgpRouteEntry> bgpRibIn2;
703 Collection<BgpRouteEntry> bgpRibIn3;
704 Collection<BgpRouteEntry> bgpRoutes;
705 Collection<Ip4Prefix> addedRoutes = new LinkedList<>();
706 Collection<Ip4Prefix> withdrawnRoutes = new LinkedList<>();
707
708 // Initiate the connections
709 peer1.connect(connectToSocket);
710 peer2.connect(connectToSocket);
711 peer3.connect(connectToSocket);
712
713 //
714 // Setup the initial set of routes to Peer1
715 //
716 addedRoutes.add(Ip4Prefix.valueOf("20.0.0.0/8"));
717 addedRoutes.add(Ip4Prefix.valueOf("30.0.0.0/16"));
718 // Write the routes
719 message = peer1.peerChannelHandler.prepareBgpUpdate(
720 NEXT_HOP1_ROUTER,
721 DEFAULT_LOCAL_PREF,
722 DEFAULT_MULTI_EXIT_DISC,
723 asPathLong,
724 addedRoutes,
725 withdrawnRoutes);
726 peer1.peerChannelHandler.savedCtx.getChannel().write(message);
727 bgpRoutes = waitForBgpRoutes(2);
728 assertThat(bgpRoutes, hasSize(2));
729
730 //
731 // Add a route entry to Peer2 with a better LOCAL_PREF
732 //
733 addedRoutes = new LinkedList<>();
734 withdrawnRoutes = new LinkedList<>();
735 addedRoutes.add(Ip4Prefix.valueOf("20.0.0.0/8"));
736 // Write the routes
737 message = peer2.peerChannelHandler.prepareBgpUpdate(
738 NEXT_HOP2_ROUTER,
739 BETTER_LOCAL_PREF,
740 DEFAULT_MULTI_EXIT_DISC,
741 asPathLong,
742 addedRoutes,
743 withdrawnRoutes);
744 peer2.peerChannelHandler.savedCtx.getChannel().write(message);
745 //
746 // Check that the routes have been received, processed and stored
747 //
748 bgpRibIn2 = waitForBgpRibIn(bgpSession2, 1);
749 assertThat(bgpRibIn2, hasSize(1));
750 bgpRoutes = waitForBgpRoutes(2);
751 assertThat(bgpRoutes, hasSize(2));
752 //
753 bgpRouteEntry =
754 new BgpRouteEntry(bgpSession2,
755 Ip4Prefix.valueOf("20.0.0.0/8"),
756 NEXT_HOP2_ROUTER,
757 (byte) BgpConstants.Update.Origin.IGP,
758 asPathLong,
759 BETTER_LOCAL_PREF);
760 bgpRouteEntry.setMultiExitDisc(DEFAULT_MULTI_EXIT_DISC);
761 assertThat(bgpRibIn2, hasBgpRouteEntry(bgpRouteEntry));
Pavlin Radoslavovf8a0f6c2015-02-04 15:31:47 -0800762 assertThat(waitForBgpRoute(bgpRouteEntry), notNullValue());
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800763
764 //
765 // Add a route entry to Peer3 with a shorter AS path
766 //
767 addedRoutes = new LinkedList<>();
768 withdrawnRoutes = new LinkedList<>();
769 addedRoutes.add(Ip4Prefix.valueOf("20.0.0.0/8"));
770 // Write the routes
771 message = peer3.peerChannelHandler.prepareBgpUpdate(
772 NEXT_HOP3_ROUTER,
773 BETTER_LOCAL_PREF,
774 DEFAULT_MULTI_EXIT_DISC,
775 asPathShort,
776 addedRoutes,
777 withdrawnRoutes);
778 peer3.peerChannelHandler.savedCtx.getChannel().write(message);
779 //
780 // Check that the routes have been received, processed and stored
781 //
782 bgpRibIn3 = waitForBgpRibIn(bgpSession3, 1);
783 assertThat(bgpRibIn3, hasSize(1));
784 bgpRoutes = waitForBgpRoutes(2);
785 assertThat(bgpRoutes, hasSize(2));
786 //
787 bgpRouteEntry =
788 new BgpRouteEntry(bgpSession3,
789 Ip4Prefix.valueOf("20.0.0.0/8"),
790 NEXT_HOP3_ROUTER,
791 (byte) BgpConstants.Update.Origin.IGP,
792 asPathShort,
793 BETTER_LOCAL_PREF);
794 bgpRouteEntry.setMultiExitDisc(DEFAULT_MULTI_EXIT_DISC);
795 assertThat(bgpRibIn3, hasBgpRouteEntry(bgpRouteEntry));
Pavlin Radoslavovf8a0f6c2015-02-04 15:31:47 -0800796 assertThat(waitForBgpRoute(bgpRouteEntry), notNullValue());
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800797
798 //
799 // Cleanup in preparation for next test: delete old route entry from
800 // Peer2
801 //
802 addedRoutes = new LinkedList<>();
803 withdrawnRoutes = new LinkedList<>();
804 withdrawnRoutes.add(Ip4Prefix.valueOf("20.0.0.0/8"));
805 // Write the routes
806 message = peer2.peerChannelHandler.prepareBgpUpdate(
807 NEXT_HOP2_ROUTER,
808 BETTER_LOCAL_PREF,
809 BETTER_MULTI_EXIT_DISC,
810 asPathShort,
811 addedRoutes,
812 withdrawnRoutes);
813 peer2.peerChannelHandler.savedCtx.getChannel().write(message);
814 //
815 // Check that the routes have been received, processed and stored
816 //
817 bgpRibIn2 = waitForBgpRibIn(bgpSession2, 0);
818 assertThat(bgpRibIn2, hasSize(0));
819
820 //
821 // Add a route entry to Peer2 with a better MED
822 //
823 addedRoutes = new LinkedList<>();
824 withdrawnRoutes = new LinkedList<>();
825 addedRoutes.add(Ip4Prefix.valueOf("20.0.0.0/8"));
826 // Write the routes
827 message = peer2.peerChannelHandler.prepareBgpUpdate(
828 NEXT_HOP2_ROUTER,
829 BETTER_LOCAL_PREF,
830 BETTER_MULTI_EXIT_DISC,
831 asPathShort,
832 addedRoutes,
833 withdrawnRoutes);
834 peer2.peerChannelHandler.savedCtx.getChannel().write(message);
835 //
836 // Check that the routes have been received, processed and stored
837 //
838 bgpRibIn2 = waitForBgpRibIn(bgpSession2, 1);
839 assertThat(bgpRibIn2, hasSize(1));
840 bgpRoutes = waitForBgpRoutes(2);
841 assertThat(bgpRoutes, hasSize(2));
842 //
843 bgpRouteEntry =
844 new BgpRouteEntry(bgpSession2,
845 Ip4Prefix.valueOf("20.0.0.0/8"),
846 NEXT_HOP2_ROUTER,
847 (byte) BgpConstants.Update.Origin.IGP,
848 asPathShort,
849 BETTER_LOCAL_PREF);
850 bgpRouteEntry.setMultiExitDisc(BETTER_MULTI_EXIT_DISC);
851 assertThat(bgpRibIn2, hasBgpRouteEntry(bgpRouteEntry));
Pavlin Radoslavovf8a0f6c2015-02-04 15:31:47 -0800852 assertThat(waitForBgpRoute(bgpRouteEntry), notNullValue());
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800853
854 //
855 // Add a route entry to Peer1 with a better (lower) BGP ID
856 //
857 addedRoutes = new LinkedList<>();
858 withdrawnRoutes = new LinkedList<>();
859 addedRoutes.add(Ip4Prefix.valueOf("20.0.0.0/8"));
860 withdrawnRoutes.add(Ip4Prefix.valueOf("30.0.0.0/16"));
861 // Write the routes
862 message = peer1.peerChannelHandler.prepareBgpUpdate(
863 NEXT_HOP1_ROUTER,
864 BETTER_LOCAL_PREF,
865 BETTER_MULTI_EXIT_DISC,
866 asPathShort,
867 addedRoutes,
868 withdrawnRoutes);
869 peer1.peerChannelHandler.savedCtx.getChannel().write(message);
870 //
871 // Check that the routes have been received, processed and stored
872 //
873 bgpRibIn1 = waitForBgpRibIn(bgpSession1, 1);
874 assertThat(bgpRibIn1, hasSize(1));
875 bgpRoutes = waitForBgpRoutes(1);
876 assertThat(bgpRoutes, hasSize(1));
877 //
878 bgpRouteEntry =
879 new BgpRouteEntry(bgpSession1,
880 Ip4Prefix.valueOf("20.0.0.0/8"),
881 NEXT_HOP1_ROUTER,
882 (byte) BgpConstants.Update.Origin.IGP,
883 asPathShort,
884 BETTER_LOCAL_PREF);
885 bgpRouteEntry.setMultiExitDisc(BETTER_MULTI_EXIT_DISC);
886 assertThat(bgpRibIn1, hasBgpRouteEntry(bgpRouteEntry));
Pavlin Radoslavovf8a0f6c2015-02-04 15:31:47 -0800887 assertThat(waitForBgpRoute(bgpRouteEntry), notNullValue());
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800888
889
890 // Close the channels and test there are no routes
891 peer1.peerChannelHandler.closeChannel();
892 peer2.peerChannelHandler.closeChannel();
893 peer3.peerChannelHandler.closeChannel();
Jonathan Hart20d8e512014-10-16 11:05:52 -0700894 bgpRoutes = waitForBgpRoutes(0);
895 assertThat(bgpRoutes, hasSize(0));
896 }
897}