Pavlin Radoslavov

* Add unit tests for the BGP route preference comparison mechanism

  This addresses ONOS-134
* Refactor existing BGP unit tests

Change-Id: Ia0ad7954632ec6b856d1a8a972f1837179121abb
...@@ -15,7 +15,6 @@ ...@@ -15,7 +15,6 @@
15 */ 15 */
16 package org.onosproject.sdnip.bgp; 16 package org.onosproject.sdnip.bgp;
17 17
18 -import static org.hamcrest.Matchers.hasItem;
19 import static org.hamcrest.Matchers.hasSize; 18 import static org.hamcrest.Matchers.hasSize;
20 import static org.hamcrest.Matchers.is; 19 import static org.hamcrest.Matchers.is;
21 import static org.hamcrest.Matchers.notNullValue; 20 import static org.hamcrest.Matchers.notNullValue;
...@@ -30,6 +29,8 @@ import java.util.LinkedList; ...@@ -30,6 +29,8 @@ import java.util.LinkedList;
30 import java.util.concurrent.Executors; 29 import java.util.concurrent.Executors;
31 import java.util.concurrent.TimeUnit; 30 import java.util.concurrent.TimeUnit;
32 31
32 +import org.hamcrest.Description;
33 +import org.hamcrest.TypeSafeMatcher;
33 import org.jboss.netty.bootstrap.ClientBootstrap; 34 import org.jboss.netty.bootstrap.ClientBootstrap;
34 import org.jboss.netty.buffer.ChannelBuffer; 35 import org.jboss.netty.buffer.ChannelBuffer;
35 import org.jboss.netty.channel.Channel; 36 import org.jboss.netty.channel.Channel;
...@@ -58,8 +59,24 @@ public class BgpSessionManagerTest { ...@@ -58,8 +59,24 @@ public class BgpSessionManagerTest {
58 Ip4Address.valueOf("127.0.0.1"); 59 Ip4Address.valueOf("127.0.0.1");
59 private static final Ip4Address BGP_PEER1_ID = 60 private static final Ip4Address BGP_PEER1_ID =
60 Ip4Address.valueOf("10.0.0.1"); 61 Ip4Address.valueOf("10.0.0.1");
62 + private static final Ip4Address BGP_PEER2_ID =
63 + Ip4Address.valueOf("10.0.0.2");
64 + private static final Ip4Address BGP_PEER3_ID =
65 + Ip4Address.valueOf("10.0.0.3");
66 + private static final Ip4Address NEXT_HOP1_ROUTER =
67 + Ip4Address.valueOf("10.20.30.41");
68 + private static final Ip4Address NEXT_HOP2_ROUTER =
69 + Ip4Address.valueOf("10.20.30.42");
70 + private static final Ip4Address NEXT_HOP3_ROUTER =
71 + Ip4Address.valueOf("10.20.30.43");
72 +
61 private static final long DEFAULT_LOCAL_PREF = 10; 73 private static final long DEFAULT_LOCAL_PREF = 10;
74 + private static final long BETTER_LOCAL_PREF = 20;
62 private static final long DEFAULT_MULTI_EXIT_DISC = 20; 75 private static final long DEFAULT_MULTI_EXIT_DISC = 20;
76 + private static final long BETTER_MULTI_EXIT_DISC = 30;
77 +
78 + BgpRouteEntry.AsPath asPathShort;
79 + BgpRouteEntry.AsPath asPathLong;
63 80
64 // Timeout waiting for a message to be received 81 // Timeout waiting for a message to be received
65 private static final int MESSAGE_TIMEOUT_MS = 5000; // 5s 82 private static final int MESSAGE_TIMEOUT_MS = 5000; // 5s
...@@ -68,13 +85,16 @@ public class BgpSessionManagerTest { ...@@ -68,13 +85,16 @@ public class BgpSessionManagerTest {
68 private BgpSessionManager bgpSessionManager; 85 private BgpSessionManager bgpSessionManager;
69 86
70 // Remote Peer state 87 // Remote Peer state
71 - private ClientBootstrap peerBootstrap; 88 + TestBgpPeer peer1 = new TestBgpPeer(BGP_PEER1_ID);
72 - private TestBgpPeerChannelHandler peerChannelHandler = 89 + TestBgpPeer peer2 = new TestBgpPeer(BGP_PEER2_ID);
73 - new TestBgpPeerChannelHandler(BGP_PEER1_ID, DEFAULT_LOCAL_PREF); 90 + TestBgpPeer peer3 = new TestBgpPeer(BGP_PEER3_ID);
74 - private TestBgpPeerFrameDecoder peerFrameDecoder = 91 +
75 - new TestBgpPeerFrameDecoder(); 92 + // Local BGP per-peer session state
93 + BgpSession bgpSession1;
94 + BgpSession bgpSession2;
95 + BgpSession bgpSession3;
76 96
77 - // The socket that the Remote Peer should connect to 97 + // The socket that the remote peers should connect to
78 private InetSocketAddress connectToSocket; 98 private InetSocketAddress connectToSocket;
79 99
80 private final DummyRouteListener dummyRouteListener = 100 private final DummyRouteListener dummyRouteListener =
...@@ -90,6 +110,132 @@ public class BgpSessionManagerTest { ...@@ -90,6 +110,132 @@ public class BgpSessionManagerTest {
90 } 110 }
91 } 111 }
92 112
113 + /**
114 + * A class to capture the state for a BGP peer.
115 + */
116 + private final class TestBgpPeer {
117 + private final Ip4Address peerId;
118 + private ClientBootstrap peerBootstrap;
119 + private TestBgpPeerChannelHandler peerChannelHandler;
120 + private TestBgpPeerFrameDecoder peerFrameDecoder =
121 + new TestBgpPeerFrameDecoder();
122 +
123 + /**
124 + * Constructor.
125 + *
126 + * @param peerId the peer ID
127 + */
128 + private TestBgpPeer(Ip4Address peerId) {
129 + this.peerId = peerId;
130 + peerChannelHandler = new TestBgpPeerChannelHandler(peerId);
131 + }
132 +
133 + /**
134 + * Starts up the BGP peer and connects it to the tested SDN-IP
135 + * instance.
136 + *
137 + * @param connectToSocket the socket to connect to
138 + */
139 + private void connect(InetSocketAddress connectToSocket)
140 + throws InterruptedException {
141 + //
142 + // Setup the BGP Peer, i.e., the "remote" BGP router that will
143 + // initiate the BGP connection, send BGP UPDATE messages, etc.
144 + //
145 + ChannelFactory channelFactory =
146 + new NioClientSocketChannelFactory(
147 + Executors.newCachedThreadPool(),
148 + Executors.newCachedThreadPool());
149 + ChannelPipelineFactory pipelineFactory =
150 + new ChannelPipelineFactory() {
151 + @Override
152 + public ChannelPipeline getPipeline() throws Exception {
153 + // Setup the transmitting pipeline
154 + ChannelPipeline pipeline = Channels.pipeline();
155 + pipeline.addLast("TestBgpPeerFrameDecoder",
156 + peerFrameDecoder);
157 + pipeline.addLast("TestBgpPeerChannelHandler",
158 + peerChannelHandler);
159 + return pipeline;
160 + }
161 + };
162 +
163 + peerBootstrap = new ClientBootstrap(channelFactory);
164 + peerBootstrap.setOption("child.keepAlive", true);
165 + peerBootstrap.setOption("child.tcpNoDelay", true);
166 + peerBootstrap.setPipelineFactory(pipelineFactory);
167 + peerBootstrap.connect(connectToSocket);
168 +
169 + boolean result;
170 + // Wait until the OPEN message is received
171 + result = peerFrameDecoder.receivedOpenMessageLatch.await(
172 + MESSAGE_TIMEOUT_MS,
173 + TimeUnit.MILLISECONDS);
174 + assertThat(result, is(true));
175 + // Wait until the KEEPALIVE message is received
176 + result = peerFrameDecoder.receivedKeepaliveMessageLatch.await(
177 + MESSAGE_TIMEOUT_MS,
178 + TimeUnit.MILLISECONDS);
179 + assertThat(result, is(true));
180 +
181 + for (BgpSession bgpSession : bgpSessionManager.getBgpSessions()) {
182 + if (bgpSession.getRemoteBgpId().equals(BGP_PEER1_ID)) {
183 + bgpSession1 = bgpSession;
184 + }
185 + if (bgpSession.getRemoteBgpId().equals(BGP_PEER2_ID)) {
186 + bgpSession2 = bgpSession;
187 + }
188 + if (bgpSession.getRemoteBgpId().equals(BGP_PEER3_ID)) {
189 + bgpSession3 = bgpSession;
190 + }
191 + }
192 + }
193 + }
194 +
195 + /**
196 + * Class that implements a matcher for BgpRouteEntry by considering
197 + * the BGP peer the entry was received from.
198 + */
199 + private static final class BgpRouteEntryAndPeerMatcher
200 + extends TypeSafeMatcher<Collection<BgpRouteEntry>> {
201 + private final BgpRouteEntry bgpRouteEntry;
202 +
203 + private BgpRouteEntryAndPeerMatcher(BgpRouteEntry bgpRouteEntry) {
204 + this.bgpRouteEntry = bgpRouteEntry;
205 + }
206 +
207 + @Override
208 + public boolean matchesSafely(Collection<BgpRouteEntry> entries) {
209 + for (BgpRouteEntry entry : entries) {
210 + if (bgpRouteEntry.equals(entry) &&
211 + bgpRouteEntry.getBgpSession() == entry.getBgpSession()) {
212 + return true;
213 + }
214 + }
215 + return false;
216 + }
217 +
218 + @Override
219 + public void describeTo(Description description) {
220 + description.appendText("BGP route entry lookup for entry \"").
221 + appendText(bgpRouteEntry.toString()).
222 + appendText("\"");
223 + }
224 + }
225 +
226 + /**
227 + * A helper method used for testing whether a collection of
228 + * BGP route entries contains an entry from a specific BGP peer.
229 + *
230 + * @param bgpRouteEntry the BGP route entry to test
231 + * @return an instance of BgpRouteEntryAndPeerMatcher that implements
232 + * the matching logic
233 + */
234 + private static BgpRouteEntryAndPeerMatcher hasBgpRouteEntry(
235 + BgpRouteEntry bgpRouteEntry) {
236 + return new BgpRouteEntryAndPeerMatcher(bgpRouteEntry);
237 + }
238 +
93 @Before 239 @Before
94 public void setUp() throws Exception { 240 public void setUp() throws Exception {
95 // 241 //
...@@ -106,35 +252,34 @@ public class BgpSessionManagerTest { ...@@ -106,35 +252,34 @@ public class BgpSessionManagerTest {
106 SocketAddress socketAddress = serverChannel.getLocalAddress(); 252 SocketAddress socketAddress = serverChannel.getLocalAddress();
107 InetSocketAddress inetSocketAddress = 253 InetSocketAddress inetSocketAddress =
108 (InetSocketAddress) socketAddress; 254 (InetSocketAddress) socketAddress;
109 -
110 - //
111 - // Setup the BGP Peer, i.e., the "remote" BGP router that will
112 - // initiate the BGP connection, send BGP UPDATE messages, etc.
113 - //
114 - ChannelFactory channelFactory =
115 - new NioClientSocketChannelFactory(Executors.newCachedThreadPool(),
116 - Executors.newCachedThreadPool());
117 - ChannelPipelineFactory pipelineFactory = new ChannelPipelineFactory() {
118 - @Override
119 - public ChannelPipeline getPipeline() throws Exception {
120 - // Setup the transmitting pipeline
121 - ChannelPipeline pipeline = Channels.pipeline();
122 - pipeline.addLast("TestBgpPeerFrameDecoder",
123 - peerFrameDecoder);
124 - pipeline.addLast("TestBgpPeerChannelHandler",
125 - peerChannelHandler);
126 - return pipeline;
127 - }
128 - };
129 -
130 - peerBootstrap = new ClientBootstrap(channelFactory);
131 - peerBootstrap.setOption("child.keepAlive", true);
132 - peerBootstrap.setOption("child.tcpNoDelay", true);
133 - peerBootstrap.setPipelineFactory(pipelineFactory);
134 -
135 InetAddress connectToAddress = InetAddresses.forString("127.0.0.1"); 255 InetAddress connectToAddress = InetAddresses.forString("127.0.0.1");
136 connectToSocket = new InetSocketAddress(connectToAddress, 256 connectToSocket = new InetSocketAddress(connectToAddress,
137 inetSocketAddress.getPort()); 257 inetSocketAddress.getPort());
258 +
259 + //
260 + // Setup the AS Paths
261 + //
262 + ArrayList<BgpRouteEntry.PathSegment> pathSegments = new ArrayList<>();
263 + byte pathSegmentType1 = (byte) BgpConstants.Update.AsPath.AS_SEQUENCE;
264 + ArrayList<Long> segmentAsNumbers1 = new ArrayList<>();
265 + segmentAsNumbers1.add((long) 65010);
266 + segmentAsNumbers1.add((long) 65020);
267 + segmentAsNumbers1.add((long) 65030);
268 + BgpRouteEntry.PathSegment pathSegment1 =
269 + new BgpRouteEntry.PathSegment(pathSegmentType1, segmentAsNumbers1);
270 + pathSegments.add(pathSegment1);
271 + asPathShort = new BgpRouteEntry.AsPath(new ArrayList(pathSegments));
272 + //
273 + byte pathSegmentType2 = (byte) BgpConstants.Update.AsPath.AS_SET;
274 + ArrayList<Long> segmentAsNumbers2 = new ArrayList<>();
275 + segmentAsNumbers2.add((long) 65041);
276 + segmentAsNumbers2.add((long) 65042);
277 + segmentAsNumbers2.add((long) 65043);
278 + BgpRouteEntry.PathSegment pathSegment2 =
279 + new BgpRouteEntry.PathSegment(pathSegmentType2, segmentAsNumbers2);
280 + pathSegments.add(pathSegment2);
281 + //
282 + asPathLong = new BgpRouteEntry.AsPath(pathSegments);
138 } 283 }
139 284
140 @After 285 @After
...@@ -211,36 +356,46 @@ public class BgpSessionManagerTest { ...@@ -211,36 +356,46 @@ public class BgpSessionManagerTest {
211 @Test 356 @Test
212 public void testExchangedBgpOpenMessages() 357 public void testExchangedBgpOpenMessages()
213 throws InterruptedException, TestUtilsException { 358 throws InterruptedException, TestUtilsException {
214 - // Initiate the connection 359 + // Initiate the connections
215 - peerBootstrap.connect(connectToSocket); 360 + peer1.connect(connectToSocket);
216 - 361 + peer2.connect(connectToSocket);
217 - // Wait until the OPEN message is received 362 + peer3.connect(connectToSocket);
218 - peerFrameDecoder.receivedOpenMessageLatch.await(MESSAGE_TIMEOUT_MS,
219 - TimeUnit.MILLISECONDS);
220 - // Wait until the KEEPALIVE message is received
221 - peerFrameDecoder.receivedKeepaliveMessageLatch.await(MESSAGE_TIMEOUT_MS,
222 - TimeUnit.MILLISECONDS);
223 363
224 // 364 //
225 // Test the fields from the BGP OPEN message: 365 // Test the fields from the BGP OPEN message:
226 // BGP version, AS number, BGP ID 366 // BGP version, AS number, BGP ID
227 // 367 //
228 - assertThat(peerFrameDecoder.remoteBgpVersion, 368 + assertThat(peer1.peerFrameDecoder.remoteBgpVersion,
369 + is(BgpConstants.BGP_VERSION));
370 + assertThat(peer1.peerFrameDecoder.remoteAs,
371 + is(TestBgpPeerChannelHandler.PEER_AS));
372 + assertThat(peer1.peerFrameDecoder.remoteBgpIdentifier,
373 + is(IP_LOOPBACK_ID));
374 + assertThat(peer2.peerFrameDecoder.remoteBgpVersion,
229 is(BgpConstants.BGP_VERSION)); 375 is(BgpConstants.BGP_VERSION));
230 - assertThat(peerFrameDecoder.remoteAs, 376 + assertThat(peer2.peerFrameDecoder.remoteAs,
231 is(TestBgpPeerChannelHandler.PEER_AS)); 377 is(TestBgpPeerChannelHandler.PEER_AS));
232 - assertThat(peerFrameDecoder.remoteBgpIdentifier, is(IP_LOOPBACK_ID)); 378 + assertThat(peer2.peerFrameDecoder.remoteBgpIdentifier,
379 + is(IP_LOOPBACK_ID));
380 + assertThat(peer3.peerFrameDecoder.remoteBgpVersion,
381 + is(BgpConstants.BGP_VERSION));
382 + assertThat(peer3.peerFrameDecoder.remoteAs,
383 + is(TestBgpPeerChannelHandler.PEER_AS));
384 + assertThat(peer3.peerFrameDecoder.remoteBgpIdentifier,
385 + is(IP_LOOPBACK_ID));
233 386
234 // 387 //
235 - // Test that a BgpSession instance has been created 388 + // Test that the BgpSession instances have been created
236 // 389 //
237 assertThat(bgpSessionManager.getMyBgpId(), is(IP_LOOPBACK_ID)); 390 assertThat(bgpSessionManager.getMyBgpId(), is(IP_LOOPBACK_ID));
238 - assertThat(bgpSessionManager.getBgpSessions(), hasSize(1)); 391 + assertThat(bgpSessionManager.getBgpSessions(), hasSize(3));
239 - BgpSession bgpSession = 392 + assertThat(bgpSession1, notNullValue());
240 - bgpSessionManager.getBgpSessions().iterator().next(); 393 + assertThat(bgpSession2, notNullValue());
241 - assertThat(bgpSession, notNullValue()); 394 + assertThat(bgpSession3, notNullValue());
242 - long sessionAs = TestUtils.getField(bgpSession, "localAs"); 395 + for (BgpSession bgpSession : bgpSessionManager.getBgpSessions()) {
243 - assertThat(sessionAs, is(TestBgpPeerChannelHandler.PEER_AS)); 396 + long sessionAs = TestUtils.getField(bgpSession, "localAs");
397 + assertThat(sessionAs, is(TestBgpPeerChannelHandler.PEER_AS));
398 + }
244 } 399 }
245 400
246 /** 401 /**
...@@ -248,30 +403,25 @@ public class BgpSessionManagerTest { ...@@ -248,30 +403,25 @@ public class BgpSessionManagerTest {
248 */ 403 */
249 @Test 404 @Test
250 public void testProcessedBgpUpdateMessages() throws InterruptedException { 405 public void testProcessedBgpUpdateMessages() throws InterruptedException {
251 - BgpSession bgpSession;
252 - Ip4Address nextHopRouter;
253 - BgpRouteEntry bgpRouteEntry;
254 ChannelBuffer message; 406 ChannelBuffer message;
255 - Collection<BgpRouteEntry> bgpRibIn; 407 + BgpRouteEntry bgpRouteEntry;
408 + Collection<BgpRouteEntry> bgpRibIn1;
409 + Collection<BgpRouteEntry> bgpRibIn2;
410 + Collection<BgpRouteEntry> bgpRibIn3;
256 Collection<BgpRouteEntry> bgpRoutes; 411 Collection<BgpRouteEntry> bgpRoutes;
257 412
258 - // Initiate the connection 413 + // Initiate the connections
259 - peerBootstrap.connect(connectToSocket); 414 + peer1.connect(connectToSocket);
260 - 415 + peer2.connect(connectToSocket);
261 - // Wait until the OPEN message is received 416 + peer3.connect(connectToSocket);
262 - peerFrameDecoder.receivedOpenMessageLatch.await(MESSAGE_TIMEOUT_MS,
263 - TimeUnit.MILLISECONDS);
264 - // Wait until the KEEPALIVE message is received
265 - peerFrameDecoder.receivedKeepaliveMessageLatch.await(MESSAGE_TIMEOUT_MS,
266 - TimeUnit.MILLISECONDS);
267 -
268 - // Get the BGP Session handler
269 - bgpSession = bgpSessionManager.getBgpSessions().iterator().next();
270 417
271 // Prepare routes to add/delete 418 // Prepare routes to add/delete
272 - nextHopRouter = Ip4Address.valueOf("10.20.30.40");
273 Collection<Ip4Prefix> addedRoutes = new LinkedList<>(); 419 Collection<Ip4Prefix> addedRoutes = new LinkedList<>();
274 Collection<Ip4Prefix> withdrawnRoutes = new LinkedList<>(); 420 Collection<Ip4Prefix> withdrawnRoutes = new LinkedList<>();
421 +
422 + //
423 + // Add and delete some routes
424 + //
275 addedRoutes.add(Ip4Prefix.valueOf("0.0.0.0/0")); 425 addedRoutes.add(Ip4Prefix.valueOf("0.0.0.0/0"));
276 addedRoutes.add(Ip4Prefix.valueOf("20.0.0.0/8")); 426 addedRoutes.add(Ip4Prefix.valueOf("20.0.0.0/8"));
277 addedRoutes.add(Ip4Prefix.valueOf("30.0.0.0/16")); 427 addedRoutes.add(Ip4Prefix.valueOf("30.0.0.0/16"));
...@@ -282,140 +432,343 @@ public class BgpSessionManagerTest { ...@@ -282,140 +432,343 @@ public class BgpSessionManagerTest {
282 withdrawnRoutes.add(Ip4Prefix.valueOf("80.0.0.0/24")); 432 withdrawnRoutes.add(Ip4Prefix.valueOf("80.0.0.0/24"));
283 withdrawnRoutes.add(Ip4Prefix.valueOf("90.0.0.0/32")); 433 withdrawnRoutes.add(Ip4Prefix.valueOf("90.0.0.0/32"));
284 // Write the routes 434 // Write the routes
285 - message = peerChannelHandler.prepareBgpUpdate(nextHopRouter, 435 + message = peer1.peerChannelHandler.prepareBgpUpdate(
286 - addedRoutes, 436 + NEXT_HOP1_ROUTER,
287 - withdrawnRoutes); 437 + DEFAULT_LOCAL_PREF,
288 - peerChannelHandler.savedCtx.getChannel().write(message); 438 + DEFAULT_MULTI_EXIT_DISC,
289 - 439 + asPathLong,
440 + addedRoutes,
441 + withdrawnRoutes);
442 + peer1.peerChannelHandler.savedCtx.getChannel().write(message);
443 + //
290 // Check that the routes have been received, processed and stored 444 // Check that the routes have been received, processed and stored
291 - bgpRibIn = waitForBgpRibIn(bgpSession, 5); 445 + //
292 - assertThat(bgpRibIn, hasSize(5)); 446 + bgpRibIn1 = waitForBgpRibIn(bgpSession1, 5);
447 + assertThat(bgpRibIn1, hasSize(5));
293 bgpRoutes = waitForBgpRoutes(5); 448 bgpRoutes = waitForBgpRoutes(5);
294 assertThat(bgpRoutes, hasSize(5)); 449 assertThat(bgpRoutes, hasSize(5));
295 -
296 - // Setup the AS Path
297 - ArrayList<BgpRouteEntry.PathSegment> pathSegments = new ArrayList<>();
298 - byte pathSegmentType1 = (byte) BgpConstants.Update.AsPath.AS_SEQUENCE;
299 - ArrayList<Long> segmentAsNumbers1 = new ArrayList<>();
300 - segmentAsNumbers1.add((long) 65010);
301 - segmentAsNumbers1.add((long) 65020);
302 - segmentAsNumbers1.add((long) 65030);
303 - BgpRouteEntry.PathSegment pathSegment1 =
304 - new BgpRouteEntry.PathSegment(pathSegmentType1, segmentAsNumbers1);
305 - pathSegments.add(pathSegment1);
306 - //
307 - byte pathSegmentType2 = (byte) BgpConstants.Update.AsPath.AS_SET;
308 - ArrayList<Long> segmentAsNumbers2 = new ArrayList<>();
309 - segmentAsNumbers2.add((long) 65041);
310 - segmentAsNumbers2.add((long) 65042);
311 - segmentAsNumbers2.add((long) 65043);
312 - BgpRouteEntry.PathSegment pathSegment2 =
313 - new BgpRouteEntry.PathSegment(pathSegmentType2, segmentAsNumbers2);
314 - pathSegments.add(pathSegment2);
315 - //
316 - BgpRouteEntry.AsPath asPath = new BgpRouteEntry.AsPath(pathSegments);
317 -
318 // 450 //
319 bgpRouteEntry = 451 bgpRouteEntry =
320 - new BgpRouteEntry(bgpSession, 452 + new BgpRouteEntry(bgpSession1,
321 Ip4Prefix.valueOf("0.0.0.0/0"), 453 Ip4Prefix.valueOf("0.0.0.0/0"),
322 - nextHopRouter, 454 + NEXT_HOP1_ROUTER,
323 (byte) BgpConstants.Update.Origin.IGP, 455 (byte) BgpConstants.Update.Origin.IGP,
324 - asPath, 456 + asPathLong,
325 DEFAULT_LOCAL_PREF); 457 DEFAULT_LOCAL_PREF);
326 bgpRouteEntry.setMultiExitDisc(DEFAULT_MULTI_EXIT_DISC); 458 bgpRouteEntry.setMultiExitDisc(DEFAULT_MULTI_EXIT_DISC);
327 - assertThat(bgpRibIn, hasItem(bgpRouteEntry)); 459 + assertThat(bgpRibIn1, hasBgpRouteEntry(bgpRouteEntry));
460 + assertThat(bgpRoutes, hasBgpRouteEntry(bgpRouteEntry));
328 // 461 //
329 bgpRouteEntry = 462 bgpRouteEntry =
330 - new BgpRouteEntry(bgpSession, 463 + new BgpRouteEntry(bgpSession1,
331 Ip4Prefix.valueOf("20.0.0.0/8"), 464 Ip4Prefix.valueOf("20.0.0.0/8"),
332 - nextHopRouter, 465 + NEXT_HOP1_ROUTER,
333 (byte) BgpConstants.Update.Origin.IGP, 466 (byte) BgpConstants.Update.Origin.IGP,
334 - asPath, 467 + asPathLong,
335 DEFAULT_LOCAL_PREF); 468 DEFAULT_LOCAL_PREF);
336 bgpRouteEntry.setMultiExitDisc(DEFAULT_MULTI_EXIT_DISC); 469 bgpRouteEntry.setMultiExitDisc(DEFAULT_MULTI_EXIT_DISC);
337 - assertThat(bgpRibIn, hasItem(bgpRouteEntry)); 470 + assertThat(bgpRibIn1, hasBgpRouteEntry(bgpRouteEntry));
471 + assertThat(bgpRoutes, hasBgpRouteEntry(bgpRouteEntry));
338 // 472 //
339 bgpRouteEntry = 473 bgpRouteEntry =
340 - new BgpRouteEntry(bgpSession, 474 + new BgpRouteEntry(bgpSession1,
341 Ip4Prefix.valueOf("30.0.0.0/16"), 475 Ip4Prefix.valueOf("30.0.0.0/16"),
342 - nextHopRouter, 476 + NEXT_HOP1_ROUTER,
343 (byte) BgpConstants.Update.Origin.IGP, 477 (byte) BgpConstants.Update.Origin.IGP,
344 - asPath, 478 + asPathLong,
345 DEFAULT_LOCAL_PREF); 479 DEFAULT_LOCAL_PREF);
346 bgpRouteEntry.setMultiExitDisc(DEFAULT_MULTI_EXIT_DISC); 480 bgpRouteEntry.setMultiExitDisc(DEFAULT_MULTI_EXIT_DISC);
347 - assertThat(bgpRibIn, hasItem(bgpRouteEntry)); 481 + assertThat(bgpRibIn1, hasBgpRouteEntry(bgpRouteEntry));
482 + assertThat(bgpRoutes, hasBgpRouteEntry(bgpRouteEntry));
348 // 483 //
349 bgpRouteEntry = 484 bgpRouteEntry =
350 - new BgpRouteEntry(bgpSession, 485 + new BgpRouteEntry(bgpSession1,
351 Ip4Prefix.valueOf("40.0.0.0/24"), 486 Ip4Prefix.valueOf("40.0.0.0/24"),
352 - nextHopRouter, 487 + NEXT_HOP1_ROUTER,
353 (byte) BgpConstants.Update.Origin.IGP, 488 (byte) BgpConstants.Update.Origin.IGP,
354 - asPath, 489 + asPathLong,
355 DEFAULT_LOCAL_PREF); 490 DEFAULT_LOCAL_PREF);
356 bgpRouteEntry.setMultiExitDisc(DEFAULT_MULTI_EXIT_DISC); 491 bgpRouteEntry.setMultiExitDisc(DEFAULT_MULTI_EXIT_DISC);
357 - assertThat(bgpRibIn, hasItem(bgpRouteEntry)); 492 + assertThat(bgpRibIn1, hasBgpRouteEntry(bgpRouteEntry));
493 + assertThat(bgpRoutes, hasBgpRouteEntry(bgpRouteEntry));
358 // 494 //
359 bgpRouteEntry = 495 bgpRouteEntry =
360 - new BgpRouteEntry(bgpSession, 496 + new BgpRouteEntry(bgpSession1,
361 Ip4Prefix.valueOf("50.0.0.0/32"), 497 Ip4Prefix.valueOf("50.0.0.0/32"),
362 - nextHopRouter, 498 + NEXT_HOP1_ROUTER,
363 (byte) BgpConstants.Update.Origin.IGP, 499 (byte) BgpConstants.Update.Origin.IGP,
364 - asPath, 500 + asPathLong,
365 DEFAULT_LOCAL_PREF); 501 DEFAULT_LOCAL_PREF);
366 bgpRouteEntry.setMultiExitDisc(DEFAULT_MULTI_EXIT_DISC); 502 bgpRouteEntry.setMultiExitDisc(DEFAULT_MULTI_EXIT_DISC);
367 - assertThat(bgpRibIn, hasItem(bgpRouteEntry)); 503 + assertThat(bgpRibIn1, hasBgpRouteEntry(bgpRouteEntry));
504 + assertThat(bgpRoutes, hasBgpRouteEntry(bgpRouteEntry));
368 505
506 + //
369 // Delete some routes 507 // Delete some routes
508 + //
370 addedRoutes = new LinkedList<>(); 509 addedRoutes = new LinkedList<>();
371 withdrawnRoutes = new LinkedList<>(); 510 withdrawnRoutes = new LinkedList<>();
372 withdrawnRoutes.add(Ip4Prefix.valueOf("0.0.0.0/0")); 511 withdrawnRoutes.add(Ip4Prefix.valueOf("0.0.0.0/0"));
373 withdrawnRoutes.add(Ip4Prefix.valueOf("50.0.0.0/32")); 512 withdrawnRoutes.add(Ip4Prefix.valueOf("50.0.0.0/32"));
374 -
375 // Write the routes 513 // Write the routes
376 - message = peerChannelHandler.prepareBgpUpdate(nextHopRouter, 514 + message = peer1.peerChannelHandler.prepareBgpUpdate(
377 - addedRoutes, 515 + NEXT_HOP1_ROUTER,
378 - withdrawnRoutes); 516 + DEFAULT_LOCAL_PREF,
379 - peerChannelHandler.savedCtx.getChannel().write(message); 517 + DEFAULT_MULTI_EXIT_DISC,
380 - 518 + asPathLong,
519 + addedRoutes,
520 + withdrawnRoutes);
521 + peer1.peerChannelHandler.savedCtx.getChannel().write(message);
522 + //
381 // Check that the routes have been received, processed and stored 523 // Check that the routes have been received, processed and stored
382 - bgpRibIn = waitForBgpRibIn(bgpSession, 3); 524 + //
383 - assertThat(bgpRibIn, hasSize(3)); 525 + bgpRibIn1 = waitForBgpRibIn(bgpSession1, 3);
526 + assertThat(bgpRibIn1, hasSize(3));
384 bgpRoutes = waitForBgpRoutes(3); 527 bgpRoutes = waitForBgpRoutes(3);
385 assertThat(bgpRoutes, hasSize(3)); 528 assertThat(bgpRoutes, hasSize(3));
386 // 529 //
387 bgpRouteEntry = 530 bgpRouteEntry =
388 - new BgpRouteEntry(bgpSession, 531 + new BgpRouteEntry(bgpSession1,
389 Ip4Prefix.valueOf("20.0.0.0/8"), 532 Ip4Prefix.valueOf("20.0.0.0/8"),
390 - nextHopRouter, 533 + NEXT_HOP1_ROUTER,
391 (byte) BgpConstants.Update.Origin.IGP, 534 (byte) BgpConstants.Update.Origin.IGP,
392 - asPath, 535 + asPathLong,
393 DEFAULT_LOCAL_PREF); 536 DEFAULT_LOCAL_PREF);
394 bgpRouteEntry.setMultiExitDisc(DEFAULT_MULTI_EXIT_DISC); 537 bgpRouteEntry.setMultiExitDisc(DEFAULT_MULTI_EXIT_DISC);
395 - assertThat(bgpRibIn, hasItem(bgpRouteEntry)); 538 + assertThat(bgpRibIn1, hasBgpRouteEntry(bgpRouteEntry));
539 + assertThat(bgpRoutes, hasBgpRouteEntry(bgpRouteEntry));
396 // 540 //
397 bgpRouteEntry = 541 bgpRouteEntry =
398 - new BgpRouteEntry(bgpSession, 542 + new BgpRouteEntry(bgpSession1,
399 Ip4Prefix.valueOf("30.0.0.0/16"), 543 Ip4Prefix.valueOf("30.0.0.0/16"),
400 - nextHopRouter, 544 + NEXT_HOP1_ROUTER,
401 (byte) BgpConstants.Update.Origin.IGP, 545 (byte) BgpConstants.Update.Origin.IGP,
402 - asPath, 546 + asPathLong,
403 DEFAULT_LOCAL_PREF); 547 DEFAULT_LOCAL_PREF);
404 bgpRouteEntry.setMultiExitDisc(DEFAULT_MULTI_EXIT_DISC); 548 bgpRouteEntry.setMultiExitDisc(DEFAULT_MULTI_EXIT_DISC);
405 - assertThat(bgpRibIn, hasItem(bgpRouteEntry)); 549 + assertThat(bgpRibIn1, hasBgpRouteEntry(bgpRouteEntry));
550 + assertThat(bgpRoutes, hasBgpRouteEntry(bgpRouteEntry));
406 // 551 //
407 bgpRouteEntry = 552 bgpRouteEntry =
408 - new BgpRouteEntry(bgpSession, 553 + new BgpRouteEntry(bgpSession1,
409 Ip4Prefix.valueOf("40.0.0.0/24"), 554 Ip4Prefix.valueOf("40.0.0.0/24"),
410 - nextHopRouter, 555 + NEXT_HOP1_ROUTER,
411 (byte) BgpConstants.Update.Origin.IGP, 556 (byte) BgpConstants.Update.Origin.IGP,
412 - asPath, 557 + asPathLong,
413 DEFAULT_LOCAL_PREF); 558 DEFAULT_LOCAL_PREF);
414 bgpRouteEntry.setMultiExitDisc(DEFAULT_MULTI_EXIT_DISC); 559 bgpRouteEntry.setMultiExitDisc(DEFAULT_MULTI_EXIT_DISC);
415 - assertThat(bgpRibIn, hasItem(bgpRouteEntry)); 560 + assertThat(bgpRibIn1, hasBgpRouteEntry(bgpRouteEntry));
561 + assertThat(bgpRoutes, hasBgpRouteEntry(bgpRouteEntry));
562 +
563 +
564 + // Close the channels and test there are no routes
565 + peer1.peerChannelHandler.closeChannel();
566 + peer2.peerChannelHandler.closeChannel();
567 + peer3.peerChannelHandler.closeChannel();
568 + bgpRoutes = waitForBgpRoutes(0);
569 + assertThat(bgpRoutes, hasSize(0));
570 + }
571 +
572 + /**
573 + * Tests the BGP route preference.
574 + */
575 + @Test
576 + public void testBgpRoutePreference() throws InterruptedException {
577 + ChannelBuffer message;
578 + BgpRouteEntry bgpRouteEntry;
579 + Collection<BgpRouteEntry> bgpRibIn1;
580 + Collection<BgpRouteEntry> bgpRibIn2;
581 + Collection<BgpRouteEntry> bgpRibIn3;
582 + Collection<BgpRouteEntry> bgpRoutes;
583 + Collection<Ip4Prefix> addedRoutes = new LinkedList<>();
584 + Collection<Ip4Prefix> withdrawnRoutes = new LinkedList<>();
585 +
586 + // Initiate the connections
587 + peer1.connect(connectToSocket);
588 + peer2.connect(connectToSocket);
589 + peer3.connect(connectToSocket);
590 +
591 + //
592 + // Setup the initial set of routes to Peer1
593 + //
594 + addedRoutes.add(Ip4Prefix.valueOf("20.0.0.0/8"));
595 + addedRoutes.add(Ip4Prefix.valueOf("30.0.0.0/16"));
596 + // Write the routes
597 + message = peer1.peerChannelHandler.prepareBgpUpdate(
598 + NEXT_HOP1_ROUTER,
599 + DEFAULT_LOCAL_PREF,
600 + DEFAULT_MULTI_EXIT_DISC,
601 + asPathLong,
602 + addedRoutes,
603 + withdrawnRoutes);
604 + peer1.peerChannelHandler.savedCtx.getChannel().write(message);
605 + bgpRoutes = waitForBgpRoutes(2);
606 + assertThat(bgpRoutes, hasSize(2));
607 +
608 + //
609 + // Add a route entry to Peer2 with a better LOCAL_PREF
610 + //
611 + addedRoutes = new LinkedList<>();
612 + withdrawnRoutes = new LinkedList<>();
613 + addedRoutes.add(Ip4Prefix.valueOf("20.0.0.0/8"));
614 + // Write the routes
615 + message = peer2.peerChannelHandler.prepareBgpUpdate(
616 + NEXT_HOP2_ROUTER,
617 + BETTER_LOCAL_PREF,
618 + DEFAULT_MULTI_EXIT_DISC,
619 + asPathLong,
620 + addedRoutes,
621 + withdrawnRoutes);
622 + peer2.peerChannelHandler.savedCtx.getChannel().write(message);
623 + //
624 + // Check that the routes have been received, processed and stored
625 + //
626 + bgpRibIn2 = waitForBgpRibIn(bgpSession2, 1);
627 + assertThat(bgpRibIn2, hasSize(1));
628 + bgpRoutes = waitForBgpRoutes(2);
629 + assertThat(bgpRoutes, hasSize(2));
630 + //
631 + bgpRouteEntry =
632 + new BgpRouteEntry(bgpSession2,
633 + Ip4Prefix.valueOf("20.0.0.0/8"),
634 + NEXT_HOP2_ROUTER,
635 + (byte) BgpConstants.Update.Origin.IGP,
636 + asPathLong,
637 + BETTER_LOCAL_PREF);
638 + bgpRouteEntry.setMultiExitDisc(DEFAULT_MULTI_EXIT_DISC);
639 + assertThat(bgpRibIn2, hasBgpRouteEntry(bgpRouteEntry));
640 + assertThat(bgpRoutes, hasBgpRouteEntry(bgpRouteEntry));
641 +
642 + //
643 + // Add a route entry to Peer3 with a shorter AS path
644 + //
645 + addedRoutes = new LinkedList<>();
646 + withdrawnRoutes = new LinkedList<>();
647 + addedRoutes.add(Ip4Prefix.valueOf("20.0.0.0/8"));
648 + // Write the routes
649 + message = peer3.peerChannelHandler.prepareBgpUpdate(
650 + NEXT_HOP3_ROUTER,
651 + BETTER_LOCAL_PREF,
652 + DEFAULT_MULTI_EXIT_DISC,
653 + asPathShort,
654 + addedRoutes,
655 + withdrawnRoutes);
656 + peer3.peerChannelHandler.savedCtx.getChannel().write(message);
657 + //
658 + // Check that the routes have been received, processed and stored
659 + //
660 + bgpRibIn3 = waitForBgpRibIn(bgpSession3, 1);
661 + assertThat(bgpRibIn3, hasSize(1));
662 + bgpRoutes = waitForBgpRoutes(2);
663 + assertThat(bgpRoutes, hasSize(2));
664 + //
665 + bgpRouteEntry =
666 + new BgpRouteEntry(bgpSession3,
667 + Ip4Prefix.valueOf("20.0.0.0/8"),
668 + NEXT_HOP3_ROUTER,
669 + (byte) BgpConstants.Update.Origin.IGP,
670 + asPathShort,
671 + BETTER_LOCAL_PREF);
672 + bgpRouteEntry.setMultiExitDisc(DEFAULT_MULTI_EXIT_DISC);
673 + assertThat(bgpRibIn3, hasBgpRouteEntry(bgpRouteEntry));
674 + assertThat(bgpRoutes, hasBgpRouteEntry(bgpRouteEntry));
675 +
676 + //
677 + // Cleanup in preparation for next test: delete old route entry from
678 + // Peer2
679 + //
680 + addedRoutes = new LinkedList<>();
681 + withdrawnRoutes = new LinkedList<>();
682 + withdrawnRoutes.add(Ip4Prefix.valueOf("20.0.0.0/8"));
683 + // Write the routes
684 + message = peer2.peerChannelHandler.prepareBgpUpdate(
685 + NEXT_HOP2_ROUTER,
686 + BETTER_LOCAL_PREF,
687 + BETTER_MULTI_EXIT_DISC,
688 + asPathShort,
689 + addedRoutes,
690 + withdrawnRoutes);
691 + peer2.peerChannelHandler.savedCtx.getChannel().write(message);
692 + //
693 + // Check that the routes have been received, processed and stored
694 + //
695 + bgpRibIn2 = waitForBgpRibIn(bgpSession2, 0);
696 + assertThat(bgpRibIn2, hasSize(0));
697 +
698 + //
699 + // Add a route entry to Peer2 with a better MED
700 + //
701 + addedRoutes = new LinkedList<>();
702 + withdrawnRoutes = new LinkedList<>();
703 + addedRoutes.add(Ip4Prefix.valueOf("20.0.0.0/8"));
704 + // Write the routes
705 + message = peer2.peerChannelHandler.prepareBgpUpdate(
706 + NEXT_HOP2_ROUTER,
707 + BETTER_LOCAL_PREF,
708 + BETTER_MULTI_EXIT_DISC,
709 + asPathShort,
710 + addedRoutes,
711 + withdrawnRoutes);
712 + peer2.peerChannelHandler.savedCtx.getChannel().write(message);
713 + //
714 + // Check that the routes have been received, processed and stored
715 + //
716 + bgpRibIn2 = waitForBgpRibIn(bgpSession2, 1);
717 + assertThat(bgpRibIn2, hasSize(1));
718 + bgpRoutes = waitForBgpRoutes(2);
719 + assertThat(bgpRoutes, hasSize(2));
720 + //
721 + bgpRouteEntry =
722 + new BgpRouteEntry(bgpSession2,
723 + Ip4Prefix.valueOf("20.0.0.0/8"),
724 + NEXT_HOP2_ROUTER,
725 + (byte) BgpConstants.Update.Origin.IGP,
726 + asPathShort,
727 + BETTER_LOCAL_PREF);
728 + bgpRouteEntry.setMultiExitDisc(BETTER_MULTI_EXIT_DISC);
729 + assertThat(bgpRibIn2, hasBgpRouteEntry(bgpRouteEntry));
730 + assertThat(bgpRoutes, hasBgpRouteEntry(bgpRouteEntry));
731 +
732 + //
733 + // Add a route entry to Peer1 with a better (lower) BGP ID
734 + //
735 + addedRoutes = new LinkedList<>();
736 + withdrawnRoutes = new LinkedList<>();
737 + addedRoutes.add(Ip4Prefix.valueOf("20.0.0.0/8"));
738 + withdrawnRoutes.add(Ip4Prefix.valueOf("30.0.0.0/16"));
739 + // Write the routes
740 + message = peer1.peerChannelHandler.prepareBgpUpdate(
741 + NEXT_HOP1_ROUTER,
742 + BETTER_LOCAL_PREF,
743 + BETTER_MULTI_EXIT_DISC,
744 + asPathShort,
745 + addedRoutes,
746 + withdrawnRoutes);
747 + peer1.peerChannelHandler.savedCtx.getChannel().write(message);
748 + //
749 + // Check that the routes have been received, processed and stored
750 + //
751 + bgpRibIn1 = waitForBgpRibIn(bgpSession1, 1);
752 + assertThat(bgpRibIn1, hasSize(1));
753 + bgpRoutes = waitForBgpRoutes(1);
754 + assertThat(bgpRoutes, hasSize(1));
755 + //
756 + bgpRouteEntry =
757 + new BgpRouteEntry(bgpSession1,
758 + Ip4Prefix.valueOf("20.0.0.0/8"),
759 + NEXT_HOP1_ROUTER,
760 + (byte) BgpConstants.Update.Origin.IGP,
761 + asPathShort,
762 + BETTER_LOCAL_PREF);
763 + bgpRouteEntry.setMultiExitDisc(BETTER_MULTI_EXIT_DISC);
764 + assertThat(bgpRibIn1, hasBgpRouteEntry(bgpRouteEntry));
765 + assertThat(bgpRoutes, hasBgpRouteEntry(bgpRouteEntry));
766 +
416 767
417 - // Close the channel and test there are no routes 768 + // Close the channels and test there are no routes
418 - peerChannelHandler.closeChannel(); 769 + peer1.peerChannelHandler.closeChannel();
770 + peer2.peerChannelHandler.closeChannel();
771 + peer3.peerChannelHandler.closeChannel();
419 bgpRoutes = waitForBgpRoutes(0); 772 bgpRoutes = waitForBgpRoutes(0);
420 assertThat(bgpRoutes, hasSize(0)); 773 assertThat(bgpRoutes, hasSize(0));
421 } 774 }
......
...@@ -32,20 +32,15 @@ class TestBgpPeerChannelHandler extends SimpleChannelHandler { ...@@ -32,20 +32,15 @@ class TestBgpPeerChannelHandler extends SimpleChannelHandler {
32 static final long PEER_AS = 65001; 32 static final long PEER_AS = 65001;
33 static final int PEER_HOLDTIME = 120; // 120 seconds 33 static final int PEER_HOLDTIME = 120; // 120 seconds
34 final Ip4Address bgpId; // The BGP ID 34 final Ip4Address bgpId; // The BGP ID
35 - final long localPref; // Local preference for routes
36 - final long multiExitDisc = 20; // MED value
37 -
38 ChannelHandlerContext savedCtx; 35 ChannelHandlerContext savedCtx;
39 36
40 /** 37 /**
41 * Constructor for given BGP ID. 38 * Constructor for given BGP ID.
42 * 39 *
43 * @param bgpId the BGP ID to use 40 * @param bgpId the BGP ID to use
44 - * @param localPref the local preference for the routes to use
45 */ 41 */
46 - TestBgpPeerChannelHandler(Ip4Address bgpId, long localPref) { 42 + TestBgpPeerChannelHandler(Ip4Address bgpId) {
47 this.bgpId = bgpId; 43 this.bgpId = bgpId;
48 - this.localPref = localPref;
49 } 44 }
50 45
51 /** 46 /**
...@@ -94,11 +89,17 @@ class TestBgpPeerChannelHandler extends SimpleChannelHandler { ...@@ -94,11 +89,17 @@ class TestBgpPeerChannelHandler extends SimpleChannelHandler {
94 * Prepares BGP UPDATE message. 89 * Prepares BGP UPDATE message.
95 * 90 *
96 * @param nextHopRouter the next-hop router address for the routes to add 91 * @param nextHopRouter the next-hop router address for the routes to add
92 + * @param localPref the local preference for the routes to use
93 + * @param multiExitDisc the MED value
94 + * @param asPath the AS path for the routes to add
97 * @param addedRoutes the routes to add 95 * @param addedRoutes the routes to add
98 * @param withdrawnRoutes the routes to withdraw 96 * @param withdrawnRoutes the routes to withdraw
99 * @return the message to transmit (BGP header included) 97 * @return the message to transmit (BGP header included)
100 */ 98 */
101 ChannelBuffer prepareBgpUpdate(Ip4Address nextHopRouter, 99 ChannelBuffer prepareBgpUpdate(Ip4Address nextHopRouter,
100 + long localPref,
101 + long multiExitDisc,
102 + BgpRouteEntry.AsPath asPath,
102 Collection<Ip4Prefix> addedRoutes, 103 Collection<Ip4Prefix> addedRoutes,
103 Collection<Ip4Prefix> withdrawnRoutes) { 104 Collection<Ip4Prefix> withdrawnRoutes) {
104 int attrFlags; 105 int attrFlags;
...@@ -119,23 +120,14 @@ class TestBgpPeerChannelHandler extends SimpleChannelHandler { ...@@ -119,23 +120,14 @@ class TestBgpPeerChannelHandler extends SimpleChannelHandler {
119 pathAttributes.writeByte(BgpConstants.Update.Origin.TYPE); 120 pathAttributes.writeByte(BgpConstants.Update.Origin.TYPE);
120 pathAttributes.writeByte(1); // Data length 121 pathAttributes.writeByte(1); // Data length
121 pathAttributes.writeByte(BgpConstants.Update.Origin.IGP); 122 pathAttributes.writeByte(BgpConstants.Update.Origin.IGP);
122 - // AS_PATH: Two Path Segments of 3 ASes each 123 +
124 + // AS_PATH: asPath
123 attrFlags = 0x40; // Transitive flag 125 attrFlags = 0x40; // Transitive flag
124 pathAttributes.writeByte(attrFlags); 126 pathAttributes.writeByte(attrFlags);
125 pathAttributes.writeByte(BgpConstants.Update.AsPath.TYPE); 127 pathAttributes.writeByte(BgpConstants.Update.AsPath.TYPE);
126 - pathAttributes.writeByte(16); // Data length 128 + ChannelBuffer encodedAsPath = encodeAsPath(asPath);
127 - byte pathSegmentType1 = (byte) BgpConstants.Update.AsPath.AS_SEQUENCE; 129 + pathAttributes.writeByte(encodedAsPath.readableBytes()); // Data length
128 - pathAttributes.writeByte(pathSegmentType1); 130 + pathAttributes.writeBytes(encodedAsPath);
129 - pathAttributes.writeByte(3); // Three ASes
130 - pathAttributes.writeShort(65010); // AS=65010
131 - pathAttributes.writeShort(65020); // AS=65020
132 - pathAttributes.writeShort(65030); // AS=65030
133 - byte pathSegmentType2 = (byte) BgpConstants.Update.AsPath.AS_SET;
134 - pathAttributes.writeByte(pathSegmentType2);
135 - pathAttributes.writeByte(3); // Three ASes
136 - pathAttributes.writeShort(65041); // AS=65041
137 - pathAttributes.writeShort(65042); // AS=65042
138 - pathAttributes.writeShort(65043); // AS=65043
139 // NEXT_HOP: nextHopRouter 131 // NEXT_HOP: nextHopRouter
140 attrFlags = 0x40; // Transitive flag 132 attrFlags = 0x40; // Transitive flag
141 pathAttributes.writeByte(attrFlags); 133 pathAttributes.writeByte(attrFlags);
...@@ -203,6 +195,27 @@ class TestBgpPeerChannelHandler extends SimpleChannelHandler { ...@@ -203,6 +195,27 @@ class TestBgpPeerChannelHandler extends SimpleChannelHandler {
203 } 195 }
204 196
205 /** 197 /**
198 + * Encodes an AS path.
199 + *
200 + * @param asPath the AS path to encode
201 + * @return the buffer with the encoded AS path
202 + */
203 + private ChannelBuffer encodeAsPath(BgpRouteEntry.AsPath asPath) {
204 + ChannelBuffer message =
205 + ChannelBuffers.buffer(BgpConstants.BGP_MESSAGE_MAX_LENGTH);
206 +
207 + for (BgpRouteEntry.PathSegment pathSegment : asPath.getPathSegments()) {
208 + message.writeByte(pathSegment.getType());
209 + message.writeByte(pathSegment.getSegmentAsNumbers().size());
210 + for (Long asNumber : pathSegment.getSegmentAsNumbers()) {
211 + message.writeShort(asNumber.intValue());
212 + }
213 + }
214 +
215 + return message;
216 + }
217 +
218 + /**
206 * Prepares BGP KEEPALIVE message. 219 * Prepares BGP KEEPALIVE message.
207 * 220 *
208 * @return the message to transmit (BGP header included) 221 * @return the message to transmit (BGP header included)
......