blob: 634e87b9480f40ea05d3c1f4e87fdddb0e8c014e [file] [log] [blame]
Thomas Vachuska781d18b2014-10-27 10:31:25 -07001/*
Ray Milkey34c95902015-04-15 09:47:53 -07002 * Copyright 2014-2015 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 Hart2da1e602015-02-18 19:09:24 -080036import org.onosproject.routing.RouteListener;
37import org.onosproject.routing.RouteUpdate;
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;
51import 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 Hart20d8e512014-10-16 11:05:52 -070088 // The BGP Session Manager to test
89 private BgpSessionManager bgpSessionManager;
90
91 // Remote Peer state
Pavlin Radoslavov4b5acae2015-01-28 17:09:45 -080092 private final Collection<TestBgpPeer> peers = new LinkedList<>();
93 TestBgpPeer peer1;
94 TestBgpPeer peer2;
95 TestBgpPeer peer3;
Jonathan Hart20d8e512014-10-16 11:05:52 -070096
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -080097 // Local BGP per-peer session state
98 BgpSession bgpSession1;
99 BgpSession bgpSession2;
100 BgpSession bgpSession3;
101
102 // The socket that the remote peers should connect to
Jonathan Hart20d8e512014-10-16 11:05:52 -0700103 private InetSocketAddress connectToSocket;
104
105 private final DummyRouteListener dummyRouteListener =
106 new DummyRouteListener();
107
108 /**
109 * Dummy implementation for the RouteListener interface.
110 */
111 private class DummyRouteListener implements RouteListener {
112 @Override
Pavlin Radoslavov248c2ae2014-12-02 09:51:25 -0800113 public void update(Collection<RouteUpdate> routeUpdate) {
Jonathan Hart20d8e512014-10-16 11:05:52 -0700114 // Nothing to do
115 }
116 }
117
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800118 /**
119 * A class to capture the state for a BGP peer.
120 */
121 private final class TestBgpPeer {
122 private final Ip4Address peerId;
123 private ClientBootstrap peerBootstrap;
124 private TestBgpPeerChannelHandler peerChannelHandler;
125 private TestBgpPeerFrameDecoder peerFrameDecoder =
126 new TestBgpPeerFrameDecoder();
127
128 /**
129 * Constructor.
130 *
131 * @param peerId the peer ID
132 */
133 private TestBgpPeer(Ip4Address peerId) {
134 this.peerId = peerId;
135 peerChannelHandler = new TestBgpPeerChannelHandler(peerId);
136 }
137
138 /**
139 * Starts up the BGP peer and connects it to the tested SDN-IP
140 * instance.
141 *
142 * @param connectToSocket the socket to connect to
143 */
144 private void connect(InetSocketAddress connectToSocket)
145 throws InterruptedException {
146 //
147 // Setup the BGP Peer, i.e., the "remote" BGP router that will
148 // initiate the BGP connection, send BGP UPDATE messages, etc.
149 //
150 ChannelFactory channelFactory =
151 new NioClientSocketChannelFactory(
152 Executors.newCachedThreadPool(),
153 Executors.newCachedThreadPool());
154 ChannelPipelineFactory pipelineFactory =
155 new ChannelPipelineFactory() {
156 @Override
157 public ChannelPipeline getPipeline() throws Exception {
158 // Setup the transmitting pipeline
159 ChannelPipeline pipeline = Channels.pipeline();
160 pipeline.addLast("TestBgpPeerFrameDecoder",
161 peerFrameDecoder);
162 pipeline.addLast("TestBgpPeerChannelHandler",
163 peerChannelHandler);
164 return pipeline;
165 }
166 };
167
168 peerBootstrap = new ClientBootstrap(channelFactory);
169 peerBootstrap.setOption("child.keepAlive", true);
170 peerBootstrap.setOption("child.tcpNoDelay", true);
171 peerBootstrap.setPipelineFactory(pipelineFactory);
172 peerBootstrap.connect(connectToSocket);
173
174 boolean result;
175 // Wait until the OPEN message is received
176 result = peerFrameDecoder.receivedOpenMessageLatch.await(
177 MESSAGE_TIMEOUT_MS,
178 TimeUnit.MILLISECONDS);
179 assertThat(result, is(true));
180 // Wait until the KEEPALIVE message is received
181 result = peerFrameDecoder.receivedKeepaliveMessageLatch.await(
182 MESSAGE_TIMEOUT_MS,
183 TimeUnit.MILLISECONDS);
184 assertThat(result, is(true));
185
186 for (BgpSession bgpSession : bgpSessionManager.getBgpSessions()) {
Pavlin Radoslavov8a36ce32015-01-28 12:26:57 -0800187 if (bgpSession.remoteInfo().bgpId().equals(BGP_PEER1_ID)) {
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800188 bgpSession1 = bgpSession;
189 }
Pavlin Radoslavov8a36ce32015-01-28 12:26:57 -0800190 if (bgpSession.remoteInfo().bgpId().equals(BGP_PEER2_ID)) {
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800191 bgpSession2 = bgpSession;
192 }
Pavlin Radoslavov8a36ce32015-01-28 12:26:57 -0800193 if (bgpSession.remoteInfo().bgpId().equals(BGP_PEER3_ID)) {
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800194 bgpSession3 = bgpSession;
195 }
196 }
197 }
198 }
199
200 /**
201 * Class that implements a matcher for BgpRouteEntry by considering
202 * the BGP peer the entry was received from.
203 */
204 private static final class BgpRouteEntryAndPeerMatcher
205 extends TypeSafeMatcher<Collection<BgpRouteEntry>> {
206 private final BgpRouteEntry bgpRouteEntry;
207
208 private BgpRouteEntryAndPeerMatcher(BgpRouteEntry bgpRouteEntry) {
209 this.bgpRouteEntry = bgpRouteEntry;
210 }
211
212 @Override
213 public boolean matchesSafely(Collection<BgpRouteEntry> entries) {
214 for (BgpRouteEntry entry : entries) {
215 if (bgpRouteEntry.equals(entry) &&
216 bgpRouteEntry.getBgpSession() == entry.getBgpSession()) {
217 return true;
218 }
219 }
220 return false;
221 }
222
223 @Override
224 public void describeTo(Description description) {
225 description.appendText("BGP route entry lookup for entry \"").
226 appendText(bgpRouteEntry.toString()).
227 appendText("\"");
228 }
229 }
230
231 /**
232 * A helper method used for testing whether a collection of
233 * BGP route entries contains an entry from a specific BGP peer.
234 *
235 * @param bgpRouteEntry the BGP route entry to test
236 * @return an instance of BgpRouteEntryAndPeerMatcher that implements
237 * the matching logic
238 */
239 private static BgpRouteEntryAndPeerMatcher hasBgpRouteEntry(
240 BgpRouteEntry bgpRouteEntry) {
241 return new BgpRouteEntryAndPeerMatcher(bgpRouteEntry);
242 }
243
Ray Milkey8dc82082015-02-20 16:22:38 -0800244 @SuppressWarnings("unchecked")
245 private Dictionary<String, String>
246 getDictionaryMock(ComponentContext componentContext) {
247 Dictionary<String, String> dictionary = createMock(Dictionary.class);
248 expect(dictionary.get("bgpPort")).andReturn("0");
249 replay(dictionary);
250 expect(componentContext.getProperties()).andReturn(dictionary);
251 return dictionary;
252 }
253
Jonathan Hart20d8e512014-10-16 11:05:52 -0700254 @Before
255 public void setUp() throws Exception {
Pavlin Radoslavov4b5acae2015-01-28 17:09:45 -0800256 peer1 = new TestBgpPeer(BGP_PEER1_ID);
257 peer2 = new TestBgpPeer(BGP_PEER2_ID);
258 peer3 = new TestBgpPeer(BGP_PEER3_ID);
259 peers.clear();
260 peers.add(peer1);
261 peers.add(peer2);
262 peers.add(peer3);
263
Jonathan Hart20d8e512014-10-16 11:05:52 -0700264 //
265 // Setup the BGP Session Manager to test, and start listening for BGP
266 // connections.
267 //
Jonathan Hart41349e92015-02-09 14:14:02 -0800268 bgpSessionManager = new BgpSessionManager();
Jonathan Hart20d8e512014-10-16 11:05:52 -0700269 // NOTE: We use port 0 to bind on any available port
Jonathan Hartd24fafb2015-02-09 17:55:32 -0800270 ComponentContext componentContext = createMock(ComponentContext.class);
Ray Milkey8dc82082015-02-20 16:22:38 -0800271 Dictionary<String, String> dictionary = getDictionaryMock(componentContext);
Jonathan Hartd24fafb2015-02-09 17:55:32 -0800272 replay(componentContext);
273 bgpSessionManager.activate(componentContext);
274 bgpSessionManager.start(dummyRouteListener);
Jonathan Hart20d8e512014-10-16 11:05:52 -0700275
276 // Get the port number the BGP Session Manager is listening on
277 Channel serverChannel = TestUtils.getField(bgpSessionManager,
278 "serverChannel");
279 SocketAddress socketAddress = serverChannel.getLocalAddress();
280 InetSocketAddress inetSocketAddress =
281 (InetSocketAddress) socketAddress;
Jonathan Hart20d8e512014-10-16 11:05:52 -0700282 InetAddress connectToAddress = InetAddresses.forString("127.0.0.1");
283 connectToSocket = new InetSocketAddress(connectToAddress,
284 inetSocketAddress.getPort());
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800285
286 //
287 // Setup the AS Paths
288 //
289 ArrayList<BgpRouteEntry.PathSegment> pathSegments = new ArrayList<>();
290 byte pathSegmentType1 = (byte) BgpConstants.Update.AsPath.AS_SEQUENCE;
291 ArrayList<Long> segmentAsNumbers1 = new ArrayList<>();
Sho SHIMIZUc14b2a22015-05-05 18:15:13 -0700292 segmentAsNumbers1.add(65010L);
293 segmentAsNumbers1.add(65020L);
294 segmentAsNumbers1.add(65030L);
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800295 BgpRouteEntry.PathSegment pathSegment1 =
296 new BgpRouteEntry.PathSegment(pathSegmentType1, segmentAsNumbers1);
297 pathSegments.add(pathSegment1);
Ray Milkey8dc82082015-02-20 16:22:38 -0800298 asPathShort = new BgpRouteEntry.AsPath(new ArrayList<>(pathSegments));
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800299 //
300 byte pathSegmentType2 = (byte) BgpConstants.Update.AsPath.AS_SET;
301 ArrayList<Long> segmentAsNumbers2 = new ArrayList<>();
Sho SHIMIZUc14b2a22015-05-05 18:15:13 -0700302 segmentAsNumbers2.add(65041L);
303 segmentAsNumbers2.add(65042L);
304 segmentAsNumbers2.add(65043L);
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800305 BgpRouteEntry.PathSegment pathSegment2 =
306 new BgpRouteEntry.PathSegment(pathSegmentType2, segmentAsNumbers2);
307 pathSegments.add(pathSegment2);
308 //
309 asPathLong = new BgpRouteEntry.AsPath(pathSegments);
Jonathan Hart20d8e512014-10-16 11:05:52 -0700310 }
311
312 @After
313 public void tearDown() throws Exception {
Pavlin Radoslavova071b1e2014-11-17 13:37:57 -0800314 bgpSessionManager.stop();
Jonathan Hart20d8e512014-10-16 11:05:52 -0700315 bgpSessionManager = null;
316 }
317
318 /**
319 * Gets BGP RIB-IN routes by waiting until they are received.
Pavlin Radoslavovf8a0f6c2015-02-04 15:31:47 -0800320 * <p>
Pavlin Radoslavov55b5f512014-12-08 09:59:35 -0800321 * NOTE: We keep checking once every 10ms the number of received routes,
Jonathan Hart20d8e512014-10-16 11:05:52 -0700322 * up to 5 seconds.
Pavlin Radoslavovf8a0f6c2015-02-04 15:31:47 -0800323 * </p>
Jonathan Hart20d8e512014-10-16 11:05:52 -0700324 *
325 * @param bgpSession the BGP session that is expected to receive the
326 * routes
327 * @param expectedRoutes the expected number of routes
328 * @return the BGP RIB-IN routes as received within the expected
329 * time interval
330 */
331 private Collection<BgpRouteEntry> waitForBgpRibIn(BgpSession bgpSession,
332 long expectedRoutes)
333 throws InterruptedException {
Pavlin Radoslavov3a0a52e2015-01-06 17:41:37 -0800334 Collection<BgpRouteEntry> bgpRibIn = bgpSession.getBgpRibIn4();
Jonathan Hart20d8e512014-10-16 11:05:52 -0700335
Pavlin Radoslavov55b5f512014-12-08 09:59:35 -0800336 final int maxChecks = 500; // Max wait of 5 seconds
Jonathan Hart20d8e512014-10-16 11:05:52 -0700337 for (int i = 0; i < maxChecks; i++) {
338 if (bgpRibIn.size() == expectedRoutes) {
339 break;
340 }
Pavlin Radoslavov55b5f512014-12-08 09:59:35 -0800341 Thread.sleep(10);
Pavlin Radoslavov3a0a52e2015-01-06 17:41:37 -0800342 bgpRibIn = bgpSession.getBgpRibIn4();
Jonathan Hart20d8e512014-10-16 11:05:52 -0700343 }
344
345 return bgpRibIn;
346 }
347
348 /**
349 * Gets BGP merged routes by waiting until they are received.
Pavlin Radoslavovf8a0f6c2015-02-04 15:31:47 -0800350 * <p>
Pavlin Radoslavov55b5f512014-12-08 09:59:35 -0800351 * NOTE: We keep checking once every 10ms the number of received routes,
Jonathan Hart20d8e512014-10-16 11:05:52 -0700352 * up to 5 seconds.
Pavlin Radoslavovf8a0f6c2015-02-04 15:31:47 -0800353 * </p>
Jonathan Hart20d8e512014-10-16 11:05:52 -0700354 *
355 * @param expectedRoutes the expected number of routes
356 * @return the BGP Session Manager routes as received within the expected
357 * time interval
358 */
359 private Collection<BgpRouteEntry> waitForBgpRoutes(long expectedRoutes)
360 throws InterruptedException {
Pavlin Radoslavov3a0a52e2015-01-06 17:41:37 -0800361 Collection<BgpRouteEntry> bgpRoutes =
362 bgpSessionManager.getBgpRoutes4();
Jonathan Hart20d8e512014-10-16 11:05:52 -0700363
Pavlin Radoslavov55b5f512014-12-08 09:59:35 -0800364 final int maxChecks = 500; // Max wait of 5 seconds
Jonathan Hart20d8e512014-10-16 11:05:52 -0700365 for (int i = 0; i < maxChecks; i++) {
366 if (bgpRoutes.size() == expectedRoutes) {
367 break;
368 }
Pavlin Radoslavov55b5f512014-12-08 09:59:35 -0800369 Thread.sleep(10);
Pavlin Radoslavov3a0a52e2015-01-06 17:41:37 -0800370 bgpRoutes = bgpSessionManager.getBgpRoutes4();
Jonathan Hart20d8e512014-10-16 11:05:52 -0700371 }
372
373 return bgpRoutes;
374 }
375
376 /**
Pavlin Radoslavovf8a0f6c2015-02-04 15:31:47 -0800377 * Gets a merged BGP route by waiting until it is received.
378 * <p>
379 * NOTE: We keep checking once every 10ms whether the route is received,
380 * up to 5 seconds.
381 * </p>
382 *
383 * @param expectedRoute the expected route
384 * @return the merged BGP route if received within the expected time
385 * interval, otherwise null
386 */
387 private BgpRouteEntry waitForBgpRoute(BgpRouteEntry expectedRoute)
388 throws InterruptedException {
389 Collection<BgpRouteEntry> bgpRoutes =
390 bgpSessionManager.getBgpRoutes4();
391
392 final int maxChecks = 500; // Max wait of 5 seconds
393 for (int i = 0; i < maxChecks; i++) {
394 for (BgpRouteEntry bgpRouteEntry : bgpRoutes) {
395 if (bgpRouteEntry.equals(expectedRoute) &&
396 bgpRouteEntry.getBgpSession() ==
397 expectedRoute.getBgpSession()) {
398 return bgpRouteEntry;
399 }
400 }
401 Thread.sleep(10);
402 bgpRoutes = bgpSessionManager.getBgpRoutes4();
403 }
404
405 return null;
406 }
407
408 /**
Jonathan Hart20d8e512014-10-16 11:05:52 -0700409 * Tests that the BGP OPEN messages have been exchanged, followed by
410 * KEEPALIVE.
411 * <p>
412 * The BGP Peer opens the sessions and transmits OPEN Message, eventually
413 * followed by KEEPALIVE. The tested BGP listener should respond by
414 * OPEN Message, followed by KEEPALIVE.
Pavlin Radoslavovf8a0f6c2015-02-04 15:31:47 -0800415 * </p>
Jonathan Hart20d8e512014-10-16 11:05:52 -0700416 *
417 * @throws TestUtilsException TestUtils error
418 */
419 @Test
420 public void testExchangedBgpOpenMessages()
421 throws InterruptedException, TestUtilsException {
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800422 // Initiate the connections
423 peer1.connect(connectToSocket);
424 peer2.connect(connectToSocket);
425 peer3.connect(connectToSocket);
Jonathan Hart20d8e512014-10-16 11:05:52 -0700426
427 //
428 // Test the fields from the BGP OPEN message:
429 // BGP version, AS number, BGP ID
430 //
Pavlin Radoslavov4b5acae2015-01-28 17:09:45 -0800431 for (TestBgpPeer peer : peers) {
432 assertThat(peer.peerFrameDecoder.remoteInfo.bgpVersion(),
433 is(BgpConstants.BGP_VERSION));
434 assertThat(peer.peerFrameDecoder.remoteInfo.bgpId(),
435 is(IP_LOOPBACK_ID));
436 assertThat(peer.peerFrameDecoder.remoteInfo.asNumber(),
437 is(TestBgpPeerChannelHandler.PEER_AS));
438 }
Jonathan Hart20d8e512014-10-16 11:05:52 -0700439
440 //
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800441 // Test that the BgpSession instances have been created
Jonathan Hart20d8e512014-10-16 11:05:52 -0700442 //
443 assertThat(bgpSessionManager.getMyBgpId(), is(IP_LOOPBACK_ID));
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800444 assertThat(bgpSessionManager.getBgpSessions(), hasSize(3));
445 assertThat(bgpSession1, notNullValue());
446 assertThat(bgpSession2, notNullValue());
447 assertThat(bgpSession3, notNullValue());
448 for (BgpSession bgpSession : bgpSessionManager.getBgpSessions()) {
Pavlin Radoslavov8a36ce32015-01-28 12:26:57 -0800449 long sessionAs = bgpSession.localInfo().asNumber();
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800450 assertThat(sessionAs, is(TestBgpPeerChannelHandler.PEER_AS));
451 }
Jonathan Hart20d8e512014-10-16 11:05:52 -0700452 }
453
Pavlin Radoslavov4b5acae2015-01-28 17:09:45 -0800454
455 /**
456 * Tests that the BGP OPEN with Capability messages have been exchanged,
457 * followed by KEEPALIVE.
458 * <p>
459 * The BGP Peer opens the sessions and transmits OPEN Message, eventually
460 * followed by KEEPALIVE. The tested BGP listener should respond by
461 * OPEN Message, followed by KEEPALIVE.
Pavlin Radoslavovf8a0f6c2015-02-04 15:31:47 -0800462 * </p>
Pavlin Radoslavov4b5acae2015-01-28 17:09:45 -0800463 *
464 * @throws TestUtilsException TestUtils error
465 */
466 @Test
467 public void testExchangedBgpOpenCapabilityMessages()
468 throws InterruptedException, TestUtilsException {
469 //
470 // Setup the BGP Capabilities for all peers
471 //
472 for (TestBgpPeer peer : peers) {
473 peer.peerChannelHandler.localInfo.setIpv4Unicast();
474 peer.peerChannelHandler.localInfo.setIpv4Multicast();
475 peer.peerChannelHandler.localInfo.setIpv6Unicast();
476 peer.peerChannelHandler.localInfo.setIpv6Multicast();
477 peer.peerChannelHandler.localInfo.setAs4OctetCapability();
478 peer.peerChannelHandler.localInfo.setAs4Number(
479 TestBgpPeerChannelHandler.PEER_AS4);
480 }
481
482 // Initiate the connections
483 peer1.connect(connectToSocket);
484 peer2.connect(connectToSocket);
485 peer3.connect(connectToSocket);
486
487 //
488 // Test the fields from the BGP OPEN message:
489 // BGP version, BGP ID
490 //
491 for (TestBgpPeer peer : peers) {
492 assertThat(peer.peerFrameDecoder.remoteInfo.bgpVersion(),
493 is(BgpConstants.BGP_VERSION));
494 assertThat(peer.peerFrameDecoder.remoteInfo.bgpId(),
495 is(IP_LOOPBACK_ID));
496 }
497
498 //
499 // Test that the BgpSession instances have been created,
500 // and contain the appropriate BGP session information.
501 //
502 assertThat(bgpSessionManager.getMyBgpId(), is(IP_LOOPBACK_ID));
503 assertThat(bgpSessionManager.getBgpSessions(), hasSize(3));
504 assertThat(bgpSession1, notNullValue());
505 assertThat(bgpSession2, notNullValue());
506 assertThat(bgpSession3, notNullValue());
507 for (BgpSession bgpSession : bgpSessionManager.getBgpSessions()) {
508 BgpSessionInfo localInfo = bgpSession.localInfo();
509 assertThat(localInfo.ipv4Unicast(), is(true));
510 assertThat(localInfo.ipv4Multicast(), is(true));
511 assertThat(localInfo.ipv6Unicast(), is(true));
512 assertThat(localInfo.ipv6Multicast(), is(true));
513 assertThat(localInfo.as4OctetCapability(), is(true));
514 assertThat(localInfo.asNumber(),
515 is(TestBgpPeerChannelHandler.PEER_AS4));
516 assertThat(localInfo.as4Number(),
517 is(TestBgpPeerChannelHandler.PEER_AS4));
518 }
519 }
520
Jonathan Hart20d8e512014-10-16 11:05:52 -0700521 /**
522 * Tests that the BGP UPDATE messages have been received and processed.
523 */
524 @Test
525 public void testProcessedBgpUpdateMessages() throws InterruptedException {
Jonathan Hart20d8e512014-10-16 11:05:52 -0700526 ChannelBuffer message;
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800527 BgpRouteEntry bgpRouteEntry;
528 Collection<BgpRouteEntry> bgpRibIn1;
529 Collection<BgpRouteEntry> bgpRibIn2;
530 Collection<BgpRouteEntry> bgpRibIn3;
Jonathan Hart20d8e512014-10-16 11:05:52 -0700531 Collection<BgpRouteEntry> bgpRoutes;
532
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800533 // Initiate the connections
534 peer1.connect(connectToSocket);
535 peer2.connect(connectToSocket);
536 peer3.connect(connectToSocket);
Jonathan Hart20d8e512014-10-16 11:05:52 -0700537
538 // Prepare routes to add/delete
Pavlin Radoslavov6b570732014-11-06 13:16:45 -0800539 Collection<Ip4Prefix> addedRoutes = new LinkedList<>();
540 Collection<Ip4Prefix> withdrawnRoutes = new LinkedList<>();
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800541
542 //
543 // Add and delete some routes
544 //
Pavlin Radoslavov6b570732014-11-06 13:16:45 -0800545 addedRoutes.add(Ip4Prefix.valueOf("0.0.0.0/0"));
546 addedRoutes.add(Ip4Prefix.valueOf("20.0.0.0/8"));
547 addedRoutes.add(Ip4Prefix.valueOf("30.0.0.0/16"));
548 addedRoutes.add(Ip4Prefix.valueOf("40.0.0.0/24"));
549 addedRoutes.add(Ip4Prefix.valueOf("50.0.0.0/32"));
550 withdrawnRoutes.add(Ip4Prefix.valueOf("60.0.0.0/8"));
551 withdrawnRoutes.add(Ip4Prefix.valueOf("70.0.0.0/16"));
552 withdrawnRoutes.add(Ip4Prefix.valueOf("80.0.0.0/24"));
553 withdrawnRoutes.add(Ip4Prefix.valueOf("90.0.0.0/32"));
Jonathan Hart20d8e512014-10-16 11:05:52 -0700554 // Write the routes
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800555 message = peer1.peerChannelHandler.prepareBgpUpdate(
556 NEXT_HOP1_ROUTER,
557 DEFAULT_LOCAL_PREF,
558 DEFAULT_MULTI_EXIT_DISC,
559 asPathLong,
560 addedRoutes,
561 withdrawnRoutes);
562 peer1.peerChannelHandler.savedCtx.getChannel().write(message);
563 //
Jonathan Hart20d8e512014-10-16 11:05:52 -0700564 // Check that the routes have been received, processed and stored
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800565 //
566 bgpRibIn1 = waitForBgpRibIn(bgpSession1, 5);
567 assertThat(bgpRibIn1, hasSize(5));
Jonathan Hart20d8e512014-10-16 11:05:52 -0700568 bgpRoutes = waitForBgpRoutes(5);
569 assertThat(bgpRoutes, hasSize(5));
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("0.0.0.0/0"),
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("20.0.0.0/8"),
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("30.0.0.0/16"),
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("40.0.0.0/24"),
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 //
615 bgpRouteEntry =
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800616 new BgpRouteEntry(bgpSession1,
Pavlin Radoslavov6b570732014-11-06 13:16:45 -0800617 Ip4Prefix.valueOf("50.0.0.0/32"),
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800618 NEXT_HOP1_ROUTER,
Jonathan Hart20d8e512014-10-16 11:05:52 -0700619 (byte) BgpConstants.Update.Origin.IGP,
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800620 asPathLong,
Jonathan Hart20d8e512014-10-16 11:05:52 -0700621 DEFAULT_LOCAL_PREF);
622 bgpRouteEntry.setMultiExitDisc(DEFAULT_MULTI_EXIT_DISC);
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800623 assertThat(bgpRibIn1, hasBgpRouteEntry(bgpRouteEntry));
Pavlin Radoslavovf8a0f6c2015-02-04 15:31:47 -0800624 assertThat(waitForBgpRoute(bgpRouteEntry), notNullValue());
Jonathan Hart20d8e512014-10-16 11:05:52 -0700625
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800626 //
Jonathan Hart20d8e512014-10-16 11:05:52 -0700627 // Delete some routes
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800628 //
Jonathan Hart20d8e512014-10-16 11:05:52 -0700629 addedRoutes = new LinkedList<>();
630 withdrawnRoutes = new LinkedList<>();
Pavlin Radoslavov6b570732014-11-06 13:16:45 -0800631 withdrawnRoutes.add(Ip4Prefix.valueOf("0.0.0.0/0"));
632 withdrawnRoutes.add(Ip4Prefix.valueOf("50.0.0.0/32"));
Jonathan Hart20d8e512014-10-16 11:05:52 -0700633 // Write the routes
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800634 message = peer1.peerChannelHandler.prepareBgpUpdate(
635 NEXT_HOP1_ROUTER,
636 DEFAULT_LOCAL_PREF,
637 DEFAULT_MULTI_EXIT_DISC,
638 asPathLong,
639 addedRoutes,
640 withdrawnRoutes);
641 peer1.peerChannelHandler.savedCtx.getChannel().write(message);
642 //
Jonathan Hart20d8e512014-10-16 11:05:52 -0700643 // Check that the routes have been received, processed and stored
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800644 //
645 bgpRibIn1 = waitForBgpRibIn(bgpSession1, 3);
646 assertThat(bgpRibIn1, hasSize(3));
Jonathan Hart20d8e512014-10-16 11:05:52 -0700647 bgpRoutes = waitForBgpRoutes(3);
648 assertThat(bgpRoutes, hasSize(3));
649 //
650 bgpRouteEntry =
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800651 new BgpRouteEntry(bgpSession1,
Pavlin Radoslavov6b570732014-11-06 13:16:45 -0800652 Ip4Prefix.valueOf("20.0.0.0/8"),
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("30.0.0.0/16"),
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 //
672 bgpRouteEntry =
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800673 new BgpRouteEntry(bgpSession1,
Pavlin Radoslavov6b570732014-11-06 13:16:45 -0800674 Ip4Prefix.valueOf("40.0.0.0/24"),
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800675 NEXT_HOP1_ROUTER,
Jonathan Hart20d8e512014-10-16 11:05:52 -0700676 (byte) BgpConstants.Update.Origin.IGP,
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800677 asPathLong,
Jonathan Hart20d8e512014-10-16 11:05:52 -0700678 DEFAULT_LOCAL_PREF);
679 bgpRouteEntry.setMultiExitDisc(DEFAULT_MULTI_EXIT_DISC);
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800680 assertThat(bgpRibIn1, hasBgpRouteEntry(bgpRouteEntry));
Pavlin Radoslavovf8a0f6c2015-02-04 15:31:47 -0800681 assertThat(waitForBgpRoute(bgpRouteEntry), notNullValue());
Jonathan Hart20d8e512014-10-16 11:05:52 -0700682
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800683
684 // Close the channels and test there are no routes
685 peer1.peerChannelHandler.closeChannel();
686 peer2.peerChannelHandler.closeChannel();
687 peer3.peerChannelHandler.closeChannel();
688 bgpRoutes = waitForBgpRoutes(0);
689 assertThat(bgpRoutes, hasSize(0));
690 }
691
692 /**
693 * Tests the BGP route preference.
694 */
695 @Test
696 public void testBgpRoutePreference() throws InterruptedException {
697 ChannelBuffer message;
698 BgpRouteEntry bgpRouteEntry;
699 Collection<BgpRouteEntry> bgpRibIn1;
700 Collection<BgpRouteEntry> bgpRibIn2;
701 Collection<BgpRouteEntry> bgpRibIn3;
702 Collection<BgpRouteEntry> bgpRoutes;
703 Collection<Ip4Prefix> addedRoutes = new LinkedList<>();
704 Collection<Ip4Prefix> withdrawnRoutes = new LinkedList<>();
705
706 // Initiate the connections
707 peer1.connect(connectToSocket);
708 peer2.connect(connectToSocket);
709 peer3.connect(connectToSocket);
710
711 //
712 // Setup the initial set of routes to Peer1
713 //
714 addedRoutes.add(Ip4Prefix.valueOf("20.0.0.0/8"));
715 addedRoutes.add(Ip4Prefix.valueOf("30.0.0.0/16"));
716 // Write the routes
717 message = peer1.peerChannelHandler.prepareBgpUpdate(
718 NEXT_HOP1_ROUTER,
719 DEFAULT_LOCAL_PREF,
720 DEFAULT_MULTI_EXIT_DISC,
721 asPathLong,
722 addedRoutes,
723 withdrawnRoutes);
724 peer1.peerChannelHandler.savedCtx.getChannel().write(message);
725 bgpRoutes = waitForBgpRoutes(2);
726 assertThat(bgpRoutes, hasSize(2));
727
728 //
729 // Add a route entry to Peer2 with a better LOCAL_PREF
730 //
731 addedRoutes = new LinkedList<>();
732 withdrawnRoutes = new LinkedList<>();
733 addedRoutes.add(Ip4Prefix.valueOf("20.0.0.0/8"));
734 // Write the routes
735 message = peer2.peerChannelHandler.prepareBgpUpdate(
736 NEXT_HOP2_ROUTER,
737 BETTER_LOCAL_PREF,
738 DEFAULT_MULTI_EXIT_DISC,
739 asPathLong,
740 addedRoutes,
741 withdrawnRoutes);
742 peer2.peerChannelHandler.savedCtx.getChannel().write(message);
743 //
744 // Check that the routes have been received, processed and stored
745 //
746 bgpRibIn2 = waitForBgpRibIn(bgpSession2, 1);
747 assertThat(bgpRibIn2, hasSize(1));
748 bgpRoutes = waitForBgpRoutes(2);
749 assertThat(bgpRoutes, hasSize(2));
750 //
751 bgpRouteEntry =
752 new BgpRouteEntry(bgpSession2,
753 Ip4Prefix.valueOf("20.0.0.0/8"),
754 NEXT_HOP2_ROUTER,
755 (byte) BgpConstants.Update.Origin.IGP,
756 asPathLong,
757 BETTER_LOCAL_PREF);
758 bgpRouteEntry.setMultiExitDisc(DEFAULT_MULTI_EXIT_DISC);
759 assertThat(bgpRibIn2, hasBgpRouteEntry(bgpRouteEntry));
Pavlin Radoslavovf8a0f6c2015-02-04 15:31:47 -0800760 assertThat(waitForBgpRoute(bgpRouteEntry), notNullValue());
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800761
762 //
763 // Add a route entry to Peer3 with a shorter AS path
764 //
765 addedRoutes = new LinkedList<>();
766 withdrawnRoutes = new LinkedList<>();
767 addedRoutes.add(Ip4Prefix.valueOf("20.0.0.0/8"));
768 // Write the routes
769 message = peer3.peerChannelHandler.prepareBgpUpdate(
770 NEXT_HOP3_ROUTER,
771 BETTER_LOCAL_PREF,
772 DEFAULT_MULTI_EXIT_DISC,
773 asPathShort,
774 addedRoutes,
775 withdrawnRoutes);
776 peer3.peerChannelHandler.savedCtx.getChannel().write(message);
777 //
778 // Check that the routes have been received, processed and stored
779 //
780 bgpRibIn3 = waitForBgpRibIn(bgpSession3, 1);
781 assertThat(bgpRibIn3, hasSize(1));
782 bgpRoutes = waitForBgpRoutes(2);
783 assertThat(bgpRoutes, hasSize(2));
784 //
785 bgpRouteEntry =
786 new BgpRouteEntry(bgpSession3,
787 Ip4Prefix.valueOf("20.0.0.0/8"),
788 NEXT_HOP3_ROUTER,
789 (byte) BgpConstants.Update.Origin.IGP,
790 asPathShort,
791 BETTER_LOCAL_PREF);
792 bgpRouteEntry.setMultiExitDisc(DEFAULT_MULTI_EXIT_DISC);
793 assertThat(bgpRibIn3, hasBgpRouteEntry(bgpRouteEntry));
Pavlin Radoslavovf8a0f6c2015-02-04 15:31:47 -0800794 assertThat(waitForBgpRoute(bgpRouteEntry), notNullValue());
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800795
796 //
797 // Cleanup in preparation for next test: delete old route entry from
798 // Peer2
799 //
800 addedRoutes = new LinkedList<>();
801 withdrawnRoutes = new LinkedList<>();
802 withdrawnRoutes.add(Ip4Prefix.valueOf("20.0.0.0/8"));
803 // Write the routes
804 message = peer2.peerChannelHandler.prepareBgpUpdate(
805 NEXT_HOP2_ROUTER,
806 BETTER_LOCAL_PREF,
807 BETTER_MULTI_EXIT_DISC,
808 asPathShort,
809 addedRoutes,
810 withdrawnRoutes);
811 peer2.peerChannelHandler.savedCtx.getChannel().write(message);
812 //
813 // Check that the routes have been received, processed and stored
814 //
815 bgpRibIn2 = waitForBgpRibIn(bgpSession2, 0);
816 assertThat(bgpRibIn2, hasSize(0));
817
818 //
819 // Add a route entry to Peer2 with a better MED
820 //
821 addedRoutes = new LinkedList<>();
822 withdrawnRoutes = new LinkedList<>();
823 addedRoutes.add(Ip4Prefix.valueOf("20.0.0.0/8"));
824 // Write the routes
825 message = peer2.peerChannelHandler.prepareBgpUpdate(
826 NEXT_HOP2_ROUTER,
827 BETTER_LOCAL_PREF,
828 BETTER_MULTI_EXIT_DISC,
829 asPathShort,
830 addedRoutes,
831 withdrawnRoutes);
832 peer2.peerChannelHandler.savedCtx.getChannel().write(message);
833 //
834 // Check that the routes have been received, processed and stored
835 //
836 bgpRibIn2 = waitForBgpRibIn(bgpSession2, 1);
837 assertThat(bgpRibIn2, hasSize(1));
838 bgpRoutes = waitForBgpRoutes(2);
839 assertThat(bgpRoutes, hasSize(2));
840 //
841 bgpRouteEntry =
842 new BgpRouteEntry(bgpSession2,
843 Ip4Prefix.valueOf("20.0.0.0/8"),
844 NEXT_HOP2_ROUTER,
845 (byte) BgpConstants.Update.Origin.IGP,
846 asPathShort,
847 BETTER_LOCAL_PREF);
848 bgpRouteEntry.setMultiExitDisc(BETTER_MULTI_EXIT_DISC);
849 assertThat(bgpRibIn2, hasBgpRouteEntry(bgpRouteEntry));
Pavlin Radoslavovf8a0f6c2015-02-04 15:31:47 -0800850 assertThat(waitForBgpRoute(bgpRouteEntry), notNullValue());
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800851
852 //
853 // Add a route entry to Peer1 with a better (lower) BGP ID
854 //
855 addedRoutes = new LinkedList<>();
856 withdrawnRoutes = new LinkedList<>();
857 addedRoutes.add(Ip4Prefix.valueOf("20.0.0.0/8"));
858 withdrawnRoutes.add(Ip4Prefix.valueOf("30.0.0.0/16"));
859 // Write the routes
860 message = peer1.peerChannelHandler.prepareBgpUpdate(
861 NEXT_HOP1_ROUTER,
862 BETTER_LOCAL_PREF,
863 BETTER_MULTI_EXIT_DISC,
864 asPathShort,
865 addedRoutes,
866 withdrawnRoutes);
867 peer1.peerChannelHandler.savedCtx.getChannel().write(message);
868 //
869 // Check that the routes have been received, processed and stored
870 //
871 bgpRibIn1 = waitForBgpRibIn(bgpSession1, 1);
872 assertThat(bgpRibIn1, hasSize(1));
873 bgpRoutes = waitForBgpRoutes(1);
874 assertThat(bgpRoutes, hasSize(1));
875 //
876 bgpRouteEntry =
877 new BgpRouteEntry(bgpSession1,
878 Ip4Prefix.valueOf("20.0.0.0/8"),
879 NEXT_HOP1_ROUTER,
880 (byte) BgpConstants.Update.Origin.IGP,
881 asPathShort,
882 BETTER_LOCAL_PREF);
883 bgpRouteEntry.setMultiExitDisc(BETTER_MULTI_EXIT_DISC);
884 assertThat(bgpRibIn1, hasBgpRouteEntry(bgpRouteEntry));
Pavlin Radoslavovf8a0f6c2015-02-04 15:31:47 -0800885 assertThat(waitForBgpRoute(bgpRouteEntry), notNullValue());
Pavlin Radoslavov0af11c12014-12-10 18:16:25 -0800886
887
888 // Close the channels and test there are no routes
889 peer1.peerChannelHandler.closeChannel();
890 peer2.peerChannelHandler.closeChannel();
891 peer3.peerChannelHandler.closeChannel();
Jonathan Hart20d8e512014-10-16 11:05:52 -0700892 bgpRoutes = waitForBgpRoutes(0);
893 assertThat(bgpRoutes, hasSize(0));
894 }
895}