Pavlin Radoslavov

Work toward IPv6 support in BGP: implement decoding of the

BGP UPDATE attributes: MP_REACH_NLRI and MP_UNREACH_NLRI (RFC 4760).

Note: currently, the IPv6 NLRI is decoded, but it not used.

This work is in the context of ONOS-422.

Change-Id: Ia61b94dedfe0b1a7d7f563e805a3086f56d4da03
...@@ -376,6 +376,46 @@ public final class BgpConstants { ...@@ -376,6 +376,46 @@ public final class BgpConstants {
376 /** BGP UPDATE Attributes Type Code AGGREGATOR length. */ 376 /** BGP UPDATE Attributes Type Code AGGREGATOR length. */
377 public static final int LENGTH = 6; 377 public static final int LENGTH = 6;
378 } 378 }
379 +
380 + /**
381 + * BGP UPDATE: MP_REACH_NLRI related constants.
382 + */
383 + public static final class MpReachNlri {
384 + /**
385 + * Default constructor.
386 + * <p>
387 + * The constructor is private to prevent creating an instance of
388 + * this utility class.
389 + */
390 + private MpReachNlri() {
391 + }
392 +
393 + /** BGP UPDATE Attributes Type Code MP_REACH_NLRI. */
394 + public static final int TYPE = 14;
395 +
396 + /** BGP UPDATE Attributes Type Code MP_REACH_NLRI min length. */
397 + public static final int MIN_LENGTH = 5;
398 + }
399 +
400 + /**
401 + * BGP UPDATE: MP_UNREACH_NLRI related constants.
402 + */
403 + public static final class MpUnreachNlri {
404 + /**
405 + * Default constructor.
406 + * <p>
407 + * The constructor is private to prevent creating an instance of
408 + * this utility class.
409 + */
410 + private MpUnreachNlri() {
411 + }
412 +
413 + /** BGP UPDATE Attributes Type Code MP_UNREACH_NLRI. */
414 + public static final int TYPE = 15;
415 +
416 + /** BGP UPDATE Attributes Type Code MP_UNREACH_NLRI min length. */
417 + public static final int MIN_LENGTH = 3;
418 + }
379 } 419 }
380 420
381 /** 421 /**
......
...@@ -36,6 +36,7 @@ import org.jboss.netty.util.Timer; ...@@ -36,6 +36,7 @@ import org.jboss.netty.util.Timer;
36 import org.jboss.netty.util.TimerTask; 36 import org.jboss.netty.util.TimerTask;
37 import org.onlab.packet.Ip4Address; 37 import org.onlab.packet.Ip4Address;
38 import org.onlab.packet.Ip4Prefix; 38 import org.onlab.packet.Ip4Prefix;
39 +import org.onlab.packet.Ip6Prefix;
39 import org.onosproject.sdnip.bgp.BgpConstants.Notifications; 40 import org.onosproject.sdnip.bgp.BgpConstants.Notifications;
40 import org.onosproject.sdnip.bgp.BgpConstants.Notifications.HoldTimerExpired; 41 import org.onosproject.sdnip.bgp.BgpConstants.Notifications.HoldTimerExpired;
41 import org.slf4j.Logger; 42 import org.slf4j.Logger;
...@@ -62,6 +63,8 @@ public class BgpSession extends SimpleChannelHandler { ...@@ -62,6 +63,8 @@ public class BgpSession extends SimpleChannelHandler {
62 private long remoteAs4Octet; // 4 octets 63 private long remoteAs4Octet; // 4 octets
63 private long remoteHoldtime; // 2 octets 64 private long remoteHoldtime; // 2 octets
64 private Ip4Address remoteBgpId; // 4 octets -> IPv4 address 65 private Ip4Address remoteBgpId; // 4 octets -> IPv4 address
66 + private boolean remoteMpExtensions; // Peer Multiprotocol
67 + // Extensions enabled: RFC 4760
65 private boolean remoteIpv4Unicast; // Peer IPv4/UNICAST AFI/SAFI 68 private boolean remoteIpv4Unicast; // Peer IPv4/UNICAST AFI/SAFI
66 private boolean remoteIpv4Multicast; // Peer IPv4/MULTICAST AFI/SAFI 69 private boolean remoteIpv4Multicast; // Peer IPv4/MULTICAST AFI/SAFI
67 private boolean remoteIpv6Unicast; // Peer IPv6/UNICAST AFI/SAFI 70 private boolean remoteIpv6Unicast; // Peer IPv6/UNICAST AFI/SAFI
...@@ -74,6 +77,8 @@ public class BgpSession extends SimpleChannelHandler { ...@@ -74,6 +77,8 @@ public class BgpSession extends SimpleChannelHandler {
74 private long localAs; // 2 octets 77 private long localAs; // 2 octets
75 private long localHoldtime; // 2 octets 78 private long localHoldtime; // 2 octets
76 private Ip4Address localBgpId; // 4 octets -> IPv4 address 79 private Ip4Address localBgpId; // 4 octets -> IPv4 address
80 + private boolean localMpExtensions; // Local Multiprotocol
81 + // Extensions enabled: RFC 4760
77 private boolean localIpv4Unicast; // Local IPv4/UNICAST AFI/SAFI 82 private boolean localIpv4Unicast; // Local IPv4/UNICAST AFI/SAFI
78 private boolean localIpv4Multicast; // Local IPv4/MULTICAST AFI/SAFI 83 private boolean localIpv4Multicast; // Local IPv4/MULTICAST AFI/SAFI
79 private boolean localIpv6Unicast; // Local IPv6/UNICAST AFI/SAFI 84 private boolean localIpv6Unicast; // Local IPv6/UNICAST AFI/SAFI
...@@ -88,7 +93,9 @@ public class BgpSession extends SimpleChannelHandler { ...@@ -88,7 +93,9 @@ public class BgpSession extends SimpleChannelHandler {
88 private volatile Timeout sessionTimeout; // Session timeout 93 private volatile Timeout sessionTimeout; // Session timeout
89 94
90 // BGP RIB-IN routing entries from this peer 95 // BGP RIB-IN routing entries from this peer
91 - private ConcurrentMap<Ip4Prefix, BgpRouteEntry> bgpRibIn = 96 + private ConcurrentMap<Ip4Prefix, BgpRouteEntry> bgpRibIn4 =
97 + new ConcurrentHashMap<>();
98 + private ConcurrentMap<Ip6Prefix, BgpRouteEntry> bgpRibIn6 =
92 new ConcurrentHashMap<>(); 99 new ConcurrentHashMap<>();
93 100
94 /** 101 /**
...@@ -113,22 +120,41 @@ public class BgpSession extends SimpleChannelHandler { ...@@ -113,22 +120,41 @@ public class BgpSession extends SimpleChannelHandler {
113 } 120 }
114 121
115 /** 122 /**
116 - * Gets the BGP RIB-IN routing entries. 123 + * Gets the BGP RIB-IN IPv4 routing entries.
124 + *
125 + * @return the BGP RIB-IN IPv4 routing entries
126 + */
127 + public Map<Ip4Prefix, BgpRouteEntry> bgpRibIn4() {
128 + return bgpRibIn4;
129 + }
130 +
131 + /**
132 + * Gets the BGP RIB-IN IPv6 routing entries.
117 * 133 *
118 - * @return the BGP RIB-IN routing entries 134 + * @return the BGP RIB-IN IPv6 routing entries
119 */ 135 */
120 - public Map<Ip4Prefix, BgpRouteEntry> bgpRibIn() { 136 + public Map<Ip6Prefix, BgpRouteEntry> bgpRibIn6() {
121 - return bgpRibIn; 137 + return bgpRibIn6;
122 } 138 }
123 139
124 /** 140 /**
125 - * Finds a BGP routing entry in the BGP RIB-IN. 141 + * Finds a BGP IPv4 routing entry in the BGP RIB-IN.
126 * 142 *
127 - * @param prefix the prefix of the route to search for 143 + * @param prefix the IPv4 prefix of the route to search for
128 - * @return the BGP routing entry if found, otherwise null 144 + * @return the IPv4 BGP routing entry if found, otherwise null
129 */ 145 */
130 public BgpRouteEntry findBgpRouteEntry(Ip4Prefix prefix) { 146 public BgpRouteEntry findBgpRouteEntry(Ip4Prefix prefix) {
131 - return bgpRibIn.get(prefix); 147 + return bgpRibIn4.get(prefix);
148 + }
149 +
150 + /**
151 + * Finds a BGP IPv6 routing entry in the BGP RIB-IN.
152 + *
153 + * @param prefix the IPv6 prefix of the route to search for
154 + * @return the IPv6 BGP routing entry if found, otherwise null
155 + */
156 + public BgpRouteEntry findBgpRouteEntry(Ip6Prefix prefix) {
157 + return bgpRibIn6.get(prefix);
132 } 158 }
133 159
134 /** 160 /**
...@@ -256,6 +282,16 @@ public class BgpSession extends SimpleChannelHandler { ...@@ -256,6 +282,16 @@ public class BgpSession extends SimpleChannelHandler {
256 } 282 }
257 283
258 /** 284 /**
285 + * Gets the BGP Multiprotocol Extensions for the session.
286 + *
287 + * @return true if the BGP Multiprotocol Extensions are enabled for the
288 + * session, otherwise false
289 + */
290 + public boolean getMpExtensions() {
291 + return remoteMpExtensions && localMpExtensions;
292 + }
293 +
294 + /**
259 * Gets the BGP session remote AFI/SAFI configuration for IPv4 unicast. 295 * Gets the BGP session remote AFI/SAFI configuration for IPv4 unicast.
260 * 296 *
261 * @return the BGP session remote AFI/SAFI configuration for IPv4 unicast 297 * @return the BGP session remote AFI/SAFI configuration for IPv4 unicast
...@@ -268,10 +304,11 @@ public class BgpSession extends SimpleChannelHandler { ...@@ -268,10 +304,11 @@ public class BgpSession extends SimpleChannelHandler {
268 * Sets the BGP session remote AFI/SAFI configuration for IPv4 unicast. 304 * Sets the BGP session remote AFI/SAFI configuration for IPv4 unicast.
269 */ 305 */
270 void setRemoteIpv4Unicast() { 306 void setRemoteIpv4Unicast() {
307 + this.remoteMpExtensions = true;
271 this.remoteIpv4Unicast = true; 308 this.remoteIpv4Unicast = true;
272 // Copy the remote AFI/SAFI setting to the local configuration 309 // Copy the remote AFI/SAFI setting to the local configuration
273 - // NOTE: Uncomment the line below if the AFI/SAFI is supported locally 310 + this.localMpExtensions = true;
274 - // this.localIpv4Unicast = true; 311 + this.localIpv4Unicast = true;
275 } 312 }
276 313
277 /** 314 /**
...@@ -287,10 +324,11 @@ public class BgpSession extends SimpleChannelHandler { ...@@ -287,10 +324,11 @@ public class BgpSession extends SimpleChannelHandler {
287 * Sets the BGP session remote AFI/SAFI configuration for IPv4 multicast. 324 * Sets the BGP session remote AFI/SAFI configuration for IPv4 multicast.
288 */ 325 */
289 void setRemoteIpv4Multicast() { 326 void setRemoteIpv4Multicast() {
327 + this.remoteMpExtensions = true;
290 this.remoteIpv4Multicast = true; 328 this.remoteIpv4Multicast = true;
291 // Copy the remote AFI/SAFI setting to the local configuration 329 // Copy the remote AFI/SAFI setting to the local configuration
292 - // NOTE: Uncomment the line below if the AFI/SAFI is supported locally 330 + this.localMpExtensions = true;
293 - // this.localIpv4Multicast = true; 331 + this.localIpv4Multicast = true;
294 } 332 }
295 333
296 /** 334 /**
...@@ -306,10 +344,11 @@ public class BgpSession extends SimpleChannelHandler { ...@@ -306,10 +344,11 @@ public class BgpSession extends SimpleChannelHandler {
306 * Sets the BGP session remote AFI/SAFI configuration for IPv6 unicast. 344 * Sets the BGP session remote AFI/SAFI configuration for IPv6 unicast.
307 */ 345 */
308 void setRemoteIpv6Unicast() { 346 void setRemoteIpv6Unicast() {
347 + this.remoteMpExtensions = true;
309 this.remoteIpv6Unicast = true; 348 this.remoteIpv6Unicast = true;
310 // Copy the remote AFI/SAFI setting to the local configuration 349 // Copy the remote AFI/SAFI setting to the local configuration
311 - // NOTE: Uncomment the line below if the AFI/SAFI is supported locally 350 + this.localMpExtensions = true;
312 - // this.localIpv6Unicast = true; 351 + this.localIpv6Unicast = true;
313 } 352 }
314 353
315 /** 354 /**
...@@ -325,10 +364,11 @@ public class BgpSession extends SimpleChannelHandler { ...@@ -325,10 +364,11 @@ public class BgpSession extends SimpleChannelHandler {
325 * Sets the BGP session remote AFI/SAFI configuration for IPv6 multicast. 364 * Sets the BGP session remote AFI/SAFI configuration for IPv6 multicast.
326 */ 365 */
327 void setRemoteIpv6Multicast() { 366 void setRemoteIpv6Multicast() {
367 + this.remoteMpExtensions = true;
328 this.remoteIpv6Multicast = true; 368 this.remoteIpv6Multicast = true;
329 // Copy the remote AFI/SAFI setting to the local configuration 369 // Copy the remote AFI/SAFI setting to the local configuration
330 - // NOTE: Uncomment the line below if the AFI/SAFI is supported locally 370 + this.localMpExtensions = true;
331 - // this.localIpv6Multicast = true; 371 + this.localIpv6Multicast = true;
332 } 372 }
333 373
334 /** 374 /**
...@@ -576,14 +616,17 @@ public class BgpSession extends SimpleChannelHandler { ...@@ -576,14 +616,17 @@ public class BgpSession extends SimpleChannelHandler {
576 // for further processing. Otherwise, the BGP Decision Process 616 // for further processing. Otherwise, the BGP Decision Process
577 // will use those routes again. 617 // will use those routes again.
578 // 618 //
579 - Collection<BgpRouteEntry> deletedRoutes = bgpRibIn.values(); 619 + Collection<BgpRouteEntry> deletedRoutes4 = bgpRibIn4.values();
580 - bgpRibIn = new ConcurrentHashMap<>(); 620 + Collection<BgpRouteEntry> deletedRoutes6 = bgpRibIn6.values();
621 + bgpRibIn4 = new ConcurrentHashMap<>();
622 + bgpRibIn6 = new ConcurrentHashMap<>();
581 623
582 // Push the updates to the BGP Merged RIB 624 // Push the updates to the BGP Merged RIB
583 BgpSessionManager.BgpRouteSelector bgpRouteSelector = 625 BgpSessionManager.BgpRouteSelector bgpRouteSelector =
584 bgpSessionManager.getBgpRouteSelector(); 626 bgpSessionManager.getBgpRouteSelector();
585 Collection<BgpRouteEntry> addedRoutes = Collections.emptyList(); 627 Collection<BgpRouteEntry> addedRoutes = Collections.emptyList();
586 - bgpRouteSelector.routeUpdates(this, addedRoutes, deletedRoutes); 628 + bgpRouteSelector.routeUpdates(this, addedRoutes, deletedRoutes4);
629 + bgpRouteSelector.routeUpdates(this, addedRoutes, deletedRoutes6);
587 630
588 bgpSessionManager.peerDisconnected(this); 631 bgpSessionManager.peerDisconnected(this);
589 } 632 }
......
...@@ -25,9 +25,13 @@ import org.jboss.netty.buffer.ChannelBuffer; ...@@ -25,9 +25,13 @@ import org.jboss.netty.buffer.ChannelBuffer;
25 import org.jboss.netty.buffer.ChannelBuffers; 25 import org.jboss.netty.buffer.ChannelBuffers;
26 import org.jboss.netty.channel.ChannelHandlerContext; 26 import org.jboss.netty.channel.ChannelHandlerContext;
27 import org.onlab.packet.Ip4Address; 27 import org.onlab.packet.Ip4Address;
28 +import org.onlab.packet.Ip6Address;
28 import org.onlab.packet.Ip4Prefix; 29 import org.onlab.packet.Ip4Prefix;
29 -import org.onosproject.sdnip.bgp.BgpConstants.Update.AsPath; 30 +import org.onlab.packet.Ip6Prefix;
30 import org.onosproject.sdnip.bgp.BgpConstants.Notifications.UpdateMessageError; 31 import org.onosproject.sdnip.bgp.BgpConstants.Notifications.UpdateMessageError;
32 +import org.onosproject.sdnip.bgp.BgpConstants.Open.Capabilities.MultiprotocolExtensions;
33 +import org.onosproject.sdnip.bgp.BgpConstants.Update;
34 +import org.onosproject.sdnip.bgp.BgpConstants.Update.AsPath;
31 import org.onosproject.sdnip.bgp.BgpMessage.BgpParseException; 35 import org.onosproject.sdnip.bgp.BgpMessage.BgpParseException;
32 import org.slf4j.Logger; 36 import org.slf4j.Logger;
33 import org.slf4j.LoggerFactory; 37 import org.slf4j.LoggerFactory;
...@@ -57,8 +61,7 @@ final class BgpUpdate { ...@@ -57,8 +61,7 @@ final class BgpUpdate {
57 static void processBgpUpdate(BgpSession bgpSession, 61 static void processBgpUpdate(BgpSession bgpSession,
58 ChannelHandlerContext ctx, 62 ChannelHandlerContext ctx,
59 ChannelBuffer message) { 63 ChannelBuffer message) {
60 - Collection<BgpRouteEntry> addedRoutes = null; 64 + DecodedBgpRoutes decodedBgpRoutes = new DecodedBgpRoutes();
61 - Map<Ip4Prefix, BgpRouteEntry> deletedRoutes = new HashMap<>();
62 65
63 int minLength = 66 int minLength =
64 BgpConstants.BGP_UPDATE_MIN_LENGTH - BgpConstants.BGP_HEADER_LENGTH; 67 BgpConstants.BGP_UPDATE_MIN_LENGTH - BgpConstants.BGP_HEADER_LENGTH;
...@@ -97,8 +100,8 @@ final class BgpUpdate { ...@@ -97,8 +100,8 @@ final class BgpUpdate {
97 } 100 }
98 Collection<Ip4Prefix> withdrawnPrefixes = null; 101 Collection<Ip4Prefix> withdrawnPrefixes = null;
99 try { 102 try {
100 - withdrawnPrefixes = parsePackedPrefixes(withdrawnRoutesLength, 103 + withdrawnPrefixes = parsePackedIp4Prefixes(withdrawnRoutesLength,
101 - message); 104 + message);
102 } catch (BgpParseException e) { 105 } catch (BgpParseException e) {
103 // ERROR: Invalid Network Field 106 // ERROR: Invalid Network Field
104 log.debug("Exception parsing Withdrawn Prefixes from BGP peer {}: ", 107 log.debug("Exception parsing Withdrawn Prefixes from BGP peer {}: ",
...@@ -109,9 +112,10 @@ final class BgpUpdate { ...@@ -109,9 +112,10 @@ final class BgpUpdate {
109 for (Ip4Prefix prefix : withdrawnPrefixes) { 112 for (Ip4Prefix prefix : withdrawnPrefixes) {
110 log.debug("BGP RX UPDATE message WITHDRAWN from {}: {}", 113 log.debug("BGP RX UPDATE message WITHDRAWN from {}: {}",
111 bgpSession.getRemoteAddress(), prefix); 114 bgpSession.getRemoteAddress(), prefix);
112 - BgpRouteEntry bgpRouteEntry = bgpSession.bgpRibIn().get(prefix); 115 + BgpRouteEntry bgpRouteEntry = bgpSession.bgpRibIn4().get(prefix);
113 if (bgpRouteEntry != null) { 116 if (bgpRouteEntry != null) {
114 - deletedRoutes.put(prefix, bgpRouteEntry); 117 + decodedBgpRoutes.deletedUnicastRoutes4.put(prefix,
118 + bgpRouteEntry);
115 } 119 }
116 } 120 }
117 121
...@@ -119,31 +123,53 @@ final class BgpUpdate { ...@@ -119,31 +123,53 @@ final class BgpUpdate {
119 // Parse the Path Attributes 123 // Parse the Path Attributes
120 // 124 //
121 try { 125 try {
122 - addedRoutes = parsePathAttributes(bgpSession, ctx, message); 126 + parsePathAttributes(bgpSession, ctx, message, decodedBgpRoutes);
123 } catch (BgpParseException e) { 127 } catch (BgpParseException e) {
124 log.debug("Exception parsing Path Attributes from BGP peer {}: ", 128 log.debug("Exception parsing Path Attributes from BGP peer {}: ",
125 bgpSession.getRemoteBgpId(), e); 129 bgpSession.getRemoteBgpId(), e);
126 // NOTE: The session was already closed, so nothing else to do 130 // NOTE: The session was already closed, so nothing else to do
127 return; 131 return;
128 } 132 }
129 - // Ignore WITHDRAWN routes that are ADDED
130 - for (BgpRouteEntry bgpRouteEntry : addedRoutes) {
131 - deletedRoutes.remove(bgpRouteEntry.prefix());
132 - }
133 133
134 + //
134 // Update the BGP RIB-IN 135 // Update the BGP RIB-IN
135 - for (BgpRouteEntry bgpRouteEntry : deletedRoutes.values()) { 136 + //
136 - bgpSession.bgpRibIn().remove(bgpRouteEntry.prefix()); 137 + Collection<BgpRouteEntry> bgpRoutes;
138 + //
139 + bgpRoutes = decodedBgpRoutes.deletedUnicastRoutes4.values();
140 + for (BgpRouteEntry bgpRouteEntry : bgpRoutes) {
141 + bgpSession.bgpRibIn4().remove(bgpRouteEntry.prefix());
142 + }
143 + //
144 + bgpRoutes = decodedBgpRoutes.addedUnicastRoutes4.values();
145 + for (BgpRouteEntry bgpRouteEntry : bgpRoutes) {
146 + bgpSession.bgpRibIn4().put(bgpRouteEntry.prefix(), bgpRouteEntry);
137 } 147 }
138 - for (BgpRouteEntry bgpRouteEntry : addedRoutes) { 148 + //
139 - bgpSession.bgpRibIn().put(bgpRouteEntry.prefix(), bgpRouteEntry); 149 + bgpRoutes = decodedBgpRoutes.deletedUnicastRoutes6.values();
150 + for (BgpRouteEntry bgpRouteEntry : bgpRoutes) {
151 + bgpSession.bgpRibIn6().remove(bgpRouteEntry.prefix());
140 } 152 }
153 + //
154 + bgpRoutes = decodedBgpRoutes.addedUnicastRoutes6.values();
155 + // TODO: fix/enable for IPv6
156 + /*
157 + for (BgpRouteEntry bgpRouteEntry : bgpRoutes) {
158 + bgpSession.bgpRibIn6().put(bgpRouteEntry.prefix(), bgpRouteEntry);
159 + }
160 + */
141 161
162 + //
142 // Push the updates to the BGP Merged RIB 163 // Push the updates to the BGP Merged RIB
164 + //
143 BgpSessionManager.BgpRouteSelector bgpRouteSelector = 165 BgpSessionManager.BgpRouteSelector bgpRouteSelector =
144 bgpSession.getBgpSessionManager().getBgpRouteSelector(); 166 bgpSession.getBgpSessionManager().getBgpRouteSelector();
145 - bgpRouteSelector.routeUpdates(bgpSession, addedRoutes, 167 + bgpRouteSelector.routeUpdates(bgpSession,
146 - deletedRoutes.values()); 168 + decodedBgpRoutes.addedUnicastRoutes4.values(),
169 + decodedBgpRoutes.deletedUnicastRoutes4.values());
170 + bgpRouteSelector.routeUpdates(bgpSession,
171 + decodedBgpRoutes.addedUnicastRoutes6.values(),
172 + decodedBgpRoutes.deletedUnicastRoutes6.values());
147 173
148 // Start the Session Timeout timer 174 // Start the Session Timeout timer
149 bgpSession.restartSessionTimeoutTimer(ctx); 175 bgpSession.restartSessionTimeoutTimer(ctx);
...@@ -155,27 +181,34 @@ final class BgpUpdate { ...@@ -155,27 +181,34 @@ final class BgpUpdate {
155 * @param bgpSession the BGP Session to use 181 * @param bgpSession the BGP Session to use
156 * @param ctx the Channel Handler Context 182 * @param ctx the Channel Handler Context
157 * @param message the message to parse 183 * @param message the message to parse
158 - * @return a collection of the result BGP Route Entries 184 + * @param decodedBgpRoutes the container to store the decoded BGP Route
185 + * Entries. It might already contain some route entries such as withdrawn
186 + * IPv4 prefixes
159 * @throws BgpParseException 187 * @throws BgpParseException
160 */ 188 */
161 - private static Collection<BgpRouteEntry> parsePathAttributes( 189 + // CHECKSTYLE IGNORE MethodLength FOR NEXT 300 LINES
162 - BgpSession bgpSession, 190 + private static void parsePathAttributes(
163 - ChannelHandlerContext ctx, 191 + BgpSession bgpSession,
164 - ChannelBuffer message) 192 + ChannelHandlerContext ctx,
193 + ChannelBuffer message,
194 + DecodedBgpRoutes decodedBgpRoutes)
165 throws BgpParseException { 195 throws BgpParseException {
166 - Map<Ip4Prefix, BgpRouteEntry> addedRoutes = new HashMap<>();
167 196
168 // 197 //
169 // Parsed values 198 // Parsed values
170 // 199 //
171 Short origin = -1; // Mandatory 200 Short origin = -1; // Mandatory
172 BgpRouteEntry.AsPath asPath = null; // Mandatory 201 BgpRouteEntry.AsPath asPath = null; // Mandatory
173 - Ip4Address nextHop = null; // Mandatory 202 + // Legacy NLRI (RFC 4271). Mandatory NEXT_HOP if legacy NLRI is used
203 + MpNlri legacyNlri = new MpNlri(MultiprotocolExtensions.AFI_IPV4,
204 + MultiprotocolExtensions.SAFI_UNICAST);
174 long multiExitDisc = // Optional 205 long multiExitDisc = // Optional
175 - BgpConstants.Update.MultiExitDisc.LOWEST_MULTI_EXIT_DISC; 206 + Update.MultiExitDisc.LOWEST_MULTI_EXIT_DISC;
176 Long localPref = null; // Mandatory 207 Long localPref = null; // Mandatory
177 Long aggregatorAsNumber = null; // Optional: unused 208 Long aggregatorAsNumber = null; // Optional: unused
178 Ip4Address aggregatorIpAddress = null; // Optional: unused 209 Ip4Address aggregatorIpAddress = null; // Optional: unused
210 + Collection<MpNlri> mpNlriReachList = new ArrayList<>(); // Optional
211 + Collection<MpNlri> mpNlriUnreachList = new ArrayList<>(); // Optional
179 212
180 // 213 //
181 // Get and verify the Path Attributes Length 214 // Get and verify the Path Attributes Length
...@@ -188,7 +221,7 @@ final class BgpUpdate { ...@@ -188,7 +221,7 @@ final class BgpUpdate {
188 throw new BgpParseException(errorMsg); 221 throw new BgpParseException(errorMsg);
189 } 222 }
190 if (pathAttributeLength == 0) { 223 if (pathAttributeLength == 0) {
191 - return addedRoutes.values(); 224 + return;
192 } 225 }
193 226
194 // 227 //
...@@ -244,28 +277,29 @@ final class BgpUpdate { ...@@ -244,28 +277,29 @@ final class BgpUpdate {
244 // 277 //
245 switch (attrTypeCode) { 278 switch (attrTypeCode) {
246 279
247 - case BgpConstants.Update.Origin.TYPE: 280 + case Update.Origin.TYPE:
248 // Attribute Type Code ORIGIN 281 // Attribute Type Code ORIGIN
249 origin = parseAttributeTypeOrigin(bgpSession, ctx, 282 origin = parseAttributeTypeOrigin(bgpSession, ctx,
250 attrTypeCode, attrLen, 283 attrTypeCode, attrLen,
251 attrFlags, message); 284 attrFlags, message);
252 break; 285 break;
253 286
254 - case BgpConstants.Update.AsPath.TYPE: 287 + case Update.AsPath.TYPE:
255 // Attribute Type Code AS_PATH 288 // Attribute Type Code AS_PATH
256 asPath = parseAttributeTypeAsPath(bgpSession, ctx, 289 asPath = parseAttributeTypeAsPath(bgpSession, ctx,
257 attrTypeCode, attrLen, 290 attrTypeCode, attrLen,
258 attrFlags, message); 291 attrFlags, message);
259 break; 292 break;
260 293
261 - case BgpConstants.Update.NextHop.TYPE: 294 + case Update.NextHop.TYPE:
262 // Attribute Type Code NEXT_HOP 295 // Attribute Type Code NEXT_HOP
263 - nextHop = parseAttributeTypeNextHop(bgpSession, ctx, 296 + legacyNlri.nextHop4 =
264 - attrTypeCode, attrLen, 297 + parseAttributeTypeNextHop(bgpSession, ctx,
265 - attrFlags, message); 298 + attrTypeCode, attrLen,
299 + attrFlags, message);
266 break; 300 break;
267 301
268 - case BgpConstants.Update.MultiExitDisc.TYPE: 302 + case Update.MultiExitDisc.TYPE:
269 // Attribute Type Code MULTI_EXIT_DISC 303 // Attribute Type Code MULTI_EXIT_DISC
270 multiExitDisc = 304 multiExitDisc =
271 parseAttributeTypeMultiExitDisc(bgpSession, ctx, 305 parseAttributeTypeMultiExitDisc(bgpSession, ctx,
...@@ -273,7 +307,7 @@ final class BgpUpdate { ...@@ -273,7 +307,7 @@ final class BgpUpdate {
273 attrFlags, message); 307 attrFlags, message);
274 break; 308 break;
275 309
276 - case BgpConstants.Update.LocalPref.TYPE: 310 + case Update.LocalPref.TYPE:
277 // Attribute Type Code LOCAL_PREF 311 // Attribute Type Code LOCAL_PREF
278 localPref = 312 localPref =
279 parseAttributeTypeLocalPref(bgpSession, ctx, 313 parseAttributeTypeLocalPref(bgpSession, ctx,
...@@ -281,7 +315,7 @@ final class BgpUpdate { ...@@ -281,7 +315,7 @@ final class BgpUpdate {
281 attrFlags, message); 315 attrFlags, message);
282 break; 316 break;
283 317
284 - case BgpConstants.Update.AtomicAggregate.TYPE: 318 + case Update.AtomicAggregate.TYPE:
285 // Attribute Type Code ATOMIC_AGGREGATE 319 // Attribute Type Code ATOMIC_AGGREGATE
286 parseAttributeTypeAtomicAggregate(bgpSession, ctx, 320 parseAttributeTypeAtomicAggregate(bgpSession, ctx,
287 attrTypeCode, attrLen, 321 attrTypeCode, attrLen,
...@@ -289,7 +323,7 @@ final class BgpUpdate { ...@@ -289,7 +323,7 @@ final class BgpUpdate {
289 // Nothing to do: this attribute is primarily informational 323 // Nothing to do: this attribute is primarily informational
290 break; 324 break;
291 325
292 - case BgpConstants.Update.Aggregator.TYPE: 326 + case Update.Aggregator.TYPE:
293 // Attribute Type Code AGGREGATOR 327 // Attribute Type Code AGGREGATOR
294 Pair<Long, Ip4Address> aggregator = 328 Pair<Long, Ip4Address> aggregator =
295 parseAttributeTypeAggregator(bgpSession, ctx, 329 parseAttributeTypeAggregator(bgpSession, ctx,
...@@ -299,6 +333,29 @@ final class BgpUpdate { ...@@ -299,6 +333,29 @@ final class BgpUpdate {
299 aggregatorIpAddress = aggregator.getRight(); 333 aggregatorIpAddress = aggregator.getRight();
300 break; 334 break;
301 335
336 + case Update.MpReachNlri.TYPE:
337 + // Attribute Type Code MP_REACH_NLRI
338 + MpNlri mpNlriReach =
339 + parseAttributeTypeMpReachNlri(bgpSession, ctx,
340 + attrTypeCode,
341 + attrLen,
342 + attrFlags, message);
343 + if (mpNlriReach != null) {
344 + mpNlriReachList.add(mpNlriReach);
345 + }
346 + break;
347 +
348 + case Update.MpUnreachNlri.TYPE:
349 + // Attribute Type Code MP_UNREACH_NLRI
350 + MpNlri mpNlriUnreach =
351 + parseAttributeTypeMpUnreachNlri(bgpSession, ctx,
352 + attrTypeCode, attrLen,
353 + attrFlags, message);
354 + if (mpNlriUnreach != null) {
355 + mpNlriUnreachList.add(mpNlriUnreach);
356 + }
357 + break;
358 +
302 default: 359 default:
303 // NOTE: Parse any new Attribute Types if needed 360 // NOTE: Parse any new Attribute Types if needed
304 if (!optionalBit) { 361 if (!optionalBit) {
...@@ -320,17 +377,15 @@ final class BgpUpdate { ...@@ -320,17 +377,15 @@ final class BgpUpdate {
320 } 377 }
321 } 378 }
322 379
323 - // Verify the Well-known Attributes
324 - verifyBgpUpdateWellKnownAttributes(bgpSession, ctx, origin, asPath,
325 - nextHop, localPref);
326 -
327 // 380 //
328 // Parse the NLRI (Network Layer Reachability Information) 381 // Parse the NLRI (Network Layer Reachability Information)
329 // 382 //
330 - Collection<Ip4Prefix> addedPrefixes = null;
331 int nlriLength = message.readableBytes(); 383 int nlriLength = message.readableBytes();
332 try { 384 try {
333 - addedPrefixes = parsePackedPrefixes(nlriLength, message); 385 + Collection<Ip4Prefix> addedPrefixes4 =
386 + parsePackedIp4Prefixes(nlriLength, message);
387 + // Store it inside the legacy NLRI wrapper
388 + legacyNlri.nlri4 = addedPrefixes4;
334 } catch (BgpParseException e) { 389 } catch (BgpParseException e) {
335 // ERROR: Invalid Network Field 390 // ERROR: Invalid Network Field
336 log.debug("Exception parsing NLRI from BGP peer {}: ", 391 log.debug("Exception parsing NLRI from BGP peer {}: ",
...@@ -340,25 +395,92 @@ final class BgpUpdate { ...@@ -340,25 +395,92 @@ final class BgpUpdate {
340 throw e; 395 throw e;
341 } 396 }
342 397
343 - // Generate the added routes 398 + // Verify the Well-known Attributes
344 - for (Ip4Prefix prefix : addedPrefixes) { 399 + verifyBgpUpdateWellKnownAttributes(bgpSession, ctx, origin, asPath,
345 - BgpRouteEntry bgpRouteEntry = 400 + localPref, legacyNlri,
346 - new BgpRouteEntry(bgpSession, prefix, nextHop, 401 + mpNlriReachList);
347 - origin.byteValue(), asPath, localPref); 402 +
348 - bgpRouteEntry.setMultiExitDisc(multiExitDisc); 403 + //
349 - if (bgpRouteEntry.hasAsPathLoop(bgpSession.getLocalAs())) { 404 + // Generate the deleted routes
350 - log.debug("BGP RX UPDATE message IGNORED from {}: {} " + 405 + //
351 - "nextHop {}: contains AS Path loop", 406 + for (MpNlri mpNlri : mpNlriUnreachList) {
352 - bgpSession.getRemoteAddress(), prefix, nextHop); 407 + BgpRouteEntry bgpRouteEntry;
353 - continue; 408 +
354 - } else { 409 + // The deleted IPv4 routes
355 - log.debug("BGP RX UPDATE message ADDED from {}: {} nextHop {}", 410 + for (Ip4Prefix prefix : mpNlri.nlri4) {
356 - bgpSession.getRemoteAddress(), prefix, nextHop); 411 + bgpRouteEntry = bgpSession.bgpRibIn4().get(prefix);
412 + if (bgpRouteEntry != null) {
413 + decodedBgpRoutes.deletedUnicastRoutes4.put(prefix,
414 + bgpRouteEntry);
415 + }
416 + }
417 +
418 + // The deleted IPv6 routes
419 + for (Ip6Prefix prefix : mpNlri.nlri6) {
420 + bgpRouteEntry = bgpSession.bgpRibIn6().get(prefix);
421 + if (bgpRouteEntry != null) {
422 + decodedBgpRoutes.deletedUnicastRoutes6.put(prefix,
423 + bgpRouteEntry);
424 + }
357 } 425 }
358 - addedRoutes.put(prefix, bgpRouteEntry);
359 } 426 }
360 427
361 - return addedRoutes.values(); 428 + //
429 + // Generate the added routes
430 + //
431 + mpNlriReachList.add(legacyNlri);
432 + for (MpNlri mpNlri : mpNlriReachList) {
433 + BgpRouteEntry bgpRouteEntry;
434 +
435 + // The added IPv4 routes
436 + for (Ip4Prefix prefix : mpNlri.nlri4) {
437 + bgpRouteEntry =
438 + new BgpRouteEntry(bgpSession, prefix, mpNlri.nextHop4,
439 + origin.byteValue(), asPath, localPref);
440 + bgpRouteEntry.setMultiExitDisc(multiExitDisc);
441 + if (bgpRouteEntry.hasAsPathLoop(bgpSession.getLocalAs())) {
442 + log.debug("BGP RX UPDATE message IGNORED from {}: {} " +
443 + "nextHop {}: contains AS Path loop",
444 + bgpSession.getRemoteAddress(), prefix,
445 + mpNlri.nextHop4);
446 + continue;
447 + } else {
448 + log.debug("BGP RX UPDATE message ADDED from {}: {} nextHop {}",
449 + bgpSession.getRemoteAddress(), prefix,
450 + mpNlri.nextHop4);
451 + }
452 + // Remove from the collection of deleted routes
453 + decodedBgpRoutes.deletedUnicastRoutes4.remove(prefix);
454 + decodedBgpRoutes.addedUnicastRoutes4.put(prefix,
455 + bgpRouteEntry);
456 + }
457 +
458 + // The added IPv6 routes
459 + // TODO: fix/enable for IPv6
460 + /*
461 + for (Ip6Prefix prefix : mpNlri.nlri6) {
462 + bgpRouteEntry =
463 + new BgpRouteEntry(bgpSession, prefix, mpNlri.nextHop6,
464 + origin.byteValue(), asPath, localPref);
465 + bgpRouteEntry.setMultiExitDisc(multiExitDisc);
466 + if (bgpRouteEntry.hasAsPathLoop(bgpSession.getLocalAs())) {
467 + log.debug("BGP RX UPDATE message IGNORED from {}: {} " +
468 + "nextHop {}: contains AS Path loop",
469 + bgpSession.getRemoteAddress(), prefix,
470 + mpNlri.nextHop6);
471 + continue;
472 + } else {
473 + log.debug("BGP RX UPDATE message ADDED from {}: {} nextHop {}",
474 + bgpSession.getRemoteAddress(), prefix,
475 + mpNlri.nextHop6);
476 + }
477 + // Remove from the collection of deleted routes
478 + decodedBgpRoutes.deletedUnicastRoutes6.remove(prefix);
479 + decodedBgpRoutes.addedUnicastRoutes6.put(prefix,
480 + bgpRouteEntry);
481 + }
482 + */
483 + }
362 } 484 }
363 485
364 /** 486 /**
...@@ -368,8 +490,10 @@ final class BgpUpdate { ...@@ -368,8 +490,10 @@ final class BgpUpdate {
368 * @param ctx the Channel Handler Context 490 * @param ctx the Channel Handler Context
369 * @param origin the ORIGIN well-known mandatory attribute 491 * @param origin the ORIGIN well-known mandatory attribute
370 * @param asPath the AS_PATH well-known mandatory attribute 492 * @param asPath the AS_PATH well-known mandatory attribute
371 - * @param nextHop the NEXT_HOP well-known mandatory attribute
372 * @param localPref the LOCAL_PREF required attribute 493 * @param localPref the LOCAL_PREF required attribute
494 + * @param legacyNlri the legacy NLRI. Encapsulates the NEXT_HOP well-known
495 + * mandatory attribute (mandatory if legacy NLRI is used).
496 + * @param mpNlriReachList the Multiprotocol NLRI attributes
373 * @throws BgpParseException 497 * @throws BgpParseException
374 */ 498 */
375 private static void verifyBgpUpdateWellKnownAttributes( 499 private static void verifyBgpUpdateWellKnownAttributes(
...@@ -377,41 +501,65 @@ final class BgpUpdate { ...@@ -377,41 +501,65 @@ final class BgpUpdate {
377 ChannelHandlerContext ctx, 501 ChannelHandlerContext ctx,
378 Short origin, 502 Short origin,
379 BgpRouteEntry.AsPath asPath, 503 BgpRouteEntry.AsPath asPath,
380 - Ip4Address nextHop, 504 + Long localPref,
381 - Long localPref) 505 + MpNlri legacyNlri,
506 + Collection<MpNlri> mpNlriReachList)
382 throws BgpParseException { 507 throws BgpParseException {
508 + boolean hasNlri = false;
509 + boolean hasLegacyNlri = false;
510 +
511 + //
512 + // Convenience flags that are used to check for missing attributes.
513 + //
514 + // NOTE: The hasLegacyNlri flag is always set to true if the
515 + // Multiprotocol Extensions are not enabled, even if the UPDATE
516 + // message doesn't contain the legacy NLRI (per RFC 4271).
517 + //
518 + if (!bgpSession.getMpExtensions()) {
519 + hasNlri = true;
520 + hasLegacyNlri = true;
521 + } else {
522 + if (!legacyNlri.nlri4.isEmpty()) {
523 + hasNlri = true;
524 + hasLegacyNlri = true;
525 + }
526 + if (!mpNlriReachList.isEmpty()) {
527 + hasNlri = true;
528 + }
529 + }
530 +
383 // 531 //
384 // Check for Missing Well-known Attributes 532 // Check for Missing Well-known Attributes
385 // 533 //
386 - if ((origin == null) || (origin == -1)) { 534 + if (hasNlri && ((origin == null) || (origin == -1))) {
387 // Missing Attribute Type Code ORIGIN 535 // Missing Attribute Type Code ORIGIN
388 - int type = BgpConstants.Update.Origin.TYPE; 536 + int type = Update.Origin.TYPE;
389 actionsBgpUpdateMissingWellKnownAttribute(bgpSession, ctx, type); 537 actionsBgpUpdateMissingWellKnownAttribute(bgpSession, ctx, type);
390 String errorMsg = "Missing Well-known Attribute: ORIGIN"; 538 String errorMsg = "Missing Well-known Attribute: ORIGIN";
391 throw new BgpParseException(errorMsg); 539 throw new BgpParseException(errorMsg);
392 } 540 }
393 - if (asPath == null) { 541 + if (hasNlri && (asPath == null)) {
394 // Missing Attribute Type Code AS_PATH 542 // Missing Attribute Type Code AS_PATH
395 - int type = BgpConstants.Update.AsPath.TYPE; 543 + int type = Update.AsPath.TYPE;
396 actionsBgpUpdateMissingWellKnownAttribute(bgpSession, ctx, type); 544 actionsBgpUpdateMissingWellKnownAttribute(bgpSession, ctx, type);
397 String errorMsg = "Missing Well-known Attribute: AS_PATH"; 545 String errorMsg = "Missing Well-known Attribute: AS_PATH";
398 throw new BgpParseException(errorMsg); 546 throw new BgpParseException(errorMsg);
399 } 547 }
400 - if (nextHop == null) { 548 + if (hasNlri && (localPref == null)) {
401 - // Missing Attribute Type Code NEXT_HOP
402 - int type = BgpConstants.Update.NextHop.TYPE;
403 - actionsBgpUpdateMissingWellKnownAttribute(bgpSession, ctx, type);
404 - String errorMsg = "Missing Well-known Attribute: NEXT_HOP";
405 - throw new BgpParseException(errorMsg);
406 - }
407 - if (localPref == null) {
408 // Missing Attribute Type Code LOCAL_PREF 549 // Missing Attribute Type Code LOCAL_PREF
409 // NOTE: Required for iBGP 550 // NOTE: Required for iBGP
410 - int type = BgpConstants.Update.LocalPref.TYPE; 551 + int type = Update.LocalPref.TYPE;
411 actionsBgpUpdateMissingWellKnownAttribute(bgpSession, ctx, type); 552 actionsBgpUpdateMissingWellKnownAttribute(bgpSession, ctx, type);
412 String errorMsg = "Missing Well-known Attribute: LOCAL_PREF"; 553 String errorMsg = "Missing Well-known Attribute: LOCAL_PREF";
413 throw new BgpParseException(errorMsg); 554 throw new BgpParseException(errorMsg);
414 } 555 }
556 + if (hasLegacyNlri && (legacyNlri.nextHop4 == null)) {
557 + // Missing Attribute Type Code NEXT_HOP
558 + int type = Update.NextHop.TYPE;
559 + actionsBgpUpdateMissingWellKnownAttribute(bgpSession, ctx, type);
560 + String errorMsg = "Missing Well-known Attribute: NEXT_HOP";
561 + throw new BgpParseException(errorMsg);
562 + }
415 } 563 }
416 564
417 /** 565 /**
...@@ -440,34 +588,42 @@ final class BgpUpdate { ...@@ -440,34 +588,42 @@ final class BgpUpdate {
440 String typeName = "UNKNOWN"; 588 String typeName = "UNKNOWN";
441 boolean isWellKnown = false; 589 boolean isWellKnown = false;
442 switch (attrTypeCode) { 590 switch (attrTypeCode) {
443 - case BgpConstants.Update.Origin.TYPE: 591 + case Update.Origin.TYPE:
444 isWellKnown = true; 592 isWellKnown = true;
445 typeName = "ORIGIN"; 593 typeName = "ORIGIN";
446 break; 594 break;
447 - case BgpConstants.Update.AsPath.TYPE: 595 + case Update.AsPath.TYPE:
448 isWellKnown = true; 596 isWellKnown = true;
449 typeName = "AS_PATH"; 597 typeName = "AS_PATH";
450 break; 598 break;
451 - case BgpConstants.Update.NextHop.TYPE: 599 + case Update.NextHop.TYPE:
452 isWellKnown = true; 600 isWellKnown = true;
453 typeName = "NEXT_HOP"; 601 typeName = "NEXT_HOP";
454 break; 602 break;
455 - case BgpConstants.Update.MultiExitDisc.TYPE: 603 + case Update.MultiExitDisc.TYPE:
456 isWellKnown = false; 604 isWellKnown = false;
457 typeName = "MULTI_EXIT_DISC"; 605 typeName = "MULTI_EXIT_DISC";
458 break; 606 break;
459 - case BgpConstants.Update.LocalPref.TYPE: 607 + case Update.LocalPref.TYPE:
460 isWellKnown = true; 608 isWellKnown = true;
461 typeName = "LOCAL_PREF"; 609 typeName = "LOCAL_PREF";
462 break; 610 break;
463 - case BgpConstants.Update.AtomicAggregate.TYPE: 611 + case Update.AtomicAggregate.TYPE:
464 isWellKnown = true; 612 isWellKnown = true;
465 typeName = "ATOMIC_AGGREGATE"; 613 typeName = "ATOMIC_AGGREGATE";
466 break; 614 break;
467 - case BgpConstants.Update.Aggregator.TYPE: 615 + case Update.Aggregator.TYPE:
468 isWellKnown = false; 616 isWellKnown = false;
469 typeName = "AGGREGATOR"; 617 typeName = "AGGREGATOR";
470 break; 618 break;
619 + case Update.MpReachNlri.TYPE:
620 + isWellKnown = false;
621 + typeName = "MP_REACH_NLRI";
622 + break;
623 + case Update.MpUnreachNlri.TYPE:
624 + isWellKnown = false;
625 + typeName = "MP_UNREACH_NLRI";
626 + break;
471 default: 627 default:
472 isWellKnown = false; 628 isWellKnown = false;
473 typeName = "UNKNOWN(" + attrTypeCode + ")"; 629 typeName = "UNKNOWN(" + attrTypeCode + ")";
...@@ -521,7 +677,7 @@ final class BgpUpdate { ...@@ -521,7 +677,7 @@ final class BgpUpdate {
521 throws BgpParseException { 677 throws BgpParseException {
522 678
523 // Check the Attribute Length 679 // Check the Attribute Length
524 - if (attrLen != BgpConstants.Update.Origin.LENGTH) { 680 + if (attrLen != Update.Origin.LENGTH) {
525 // ERROR: Attribute Length Error 681 // ERROR: Attribute Length Error
526 actionsBgpUpdateAttributeLengthError( 682 actionsBgpUpdateAttributeLengthError(
527 bgpSession, ctx, attrTypeCode, attrLen, attrFlags, message); 683 bgpSession, ctx, attrTypeCode, attrLen, attrFlags, message);
...@@ -532,11 +688,11 @@ final class BgpUpdate { ...@@ -532,11 +688,11 @@ final class BgpUpdate {
532 message.markReaderIndex(); 688 message.markReaderIndex();
533 short origin = message.readUnsignedByte(); 689 short origin = message.readUnsignedByte();
534 switch (origin) { 690 switch (origin) {
535 - case BgpConstants.Update.Origin.IGP: 691 + case Update.Origin.IGP:
536 // FALLTHROUGH 692 // FALLTHROUGH
537 - case BgpConstants.Update.Origin.EGP: 693 + case Update.Origin.EGP:
538 // FALLTHROUGH 694 // FALLTHROUGH
539 - case BgpConstants.Update.Origin.INCOMPLETE: 695 + case Update.Origin.INCOMPLETE:
540 break; 696 break;
541 default: 697 default:
542 // ERROR: Invalid ORIGIN Attribute 698 // ERROR: Invalid ORIGIN Attribute
...@@ -590,13 +746,13 @@ final class BgpUpdate { ...@@ -590,13 +746,13 @@ final class BgpUpdate {
590 746
591 // Verify the Path Segment Type 747 // Verify the Path Segment Type
592 switch (pathSegmentType) { 748 switch (pathSegmentType) {
593 - case BgpConstants.Update.AsPath.AS_SET: 749 + case Update.AsPath.AS_SET:
594 // FALLTHROUGH 750 // FALLTHROUGH
595 - case BgpConstants.Update.AsPath.AS_SEQUENCE: 751 + case Update.AsPath.AS_SEQUENCE:
596 // FALLTHROUGH 752 // FALLTHROUGH
597 - case BgpConstants.Update.AsPath.AS_CONFED_SEQUENCE: 753 + case Update.AsPath.AS_CONFED_SEQUENCE:
598 // FALLTHROUGH 754 // FALLTHROUGH
599 - case BgpConstants.Update.AsPath.AS_CONFED_SET: 755 + case Update.AsPath.AS_CONFED_SET:
600 break; 756 break;
601 default: 757 default:
602 // ERROR: Invalid Path Segment Type 758 // ERROR: Invalid Path Segment Type
...@@ -669,7 +825,7 @@ final class BgpUpdate { ...@@ -669,7 +825,7 @@ final class BgpUpdate {
669 throws BgpParseException { 825 throws BgpParseException {
670 826
671 // Check the Attribute Length 827 // Check the Attribute Length
672 - if (attrLen != BgpConstants.Update.NextHop.LENGTH) { 828 + if (attrLen != Update.NextHop.LENGTH) {
673 // ERROR: Attribute Length Error 829 // ERROR: Attribute Length Error
674 actionsBgpUpdateAttributeLengthError( 830 actionsBgpUpdateAttributeLengthError(
675 bgpSession, ctx, attrTypeCode, attrLen, attrFlags, message); 831 bgpSession, ctx, attrTypeCode, attrLen, attrFlags, message);
...@@ -725,7 +881,7 @@ final class BgpUpdate { ...@@ -725,7 +881,7 @@ final class BgpUpdate {
725 throws BgpParseException { 881 throws BgpParseException {
726 882
727 // Check the Attribute Length 883 // Check the Attribute Length
728 - if (attrLen != BgpConstants.Update.MultiExitDisc.LENGTH) { 884 + if (attrLen != Update.MultiExitDisc.LENGTH) {
729 // ERROR: Attribute Length Error 885 // ERROR: Attribute Length Error
730 actionsBgpUpdateAttributeLengthError( 886 actionsBgpUpdateAttributeLengthError(
731 bgpSession, ctx, attrTypeCode, attrLen, attrFlags, message); 887 bgpSession, ctx, attrTypeCode, attrLen, attrFlags, message);
...@@ -759,7 +915,7 @@ final class BgpUpdate { ...@@ -759,7 +915,7 @@ final class BgpUpdate {
759 throws BgpParseException { 915 throws BgpParseException {
760 916
761 // Check the Attribute Length 917 // Check the Attribute Length
762 - if (attrLen != BgpConstants.Update.LocalPref.LENGTH) { 918 + if (attrLen != Update.LocalPref.LENGTH) {
763 // ERROR: Attribute Length Error 919 // ERROR: Attribute Length Error
764 actionsBgpUpdateAttributeLengthError( 920 actionsBgpUpdateAttributeLengthError(
765 bgpSession, ctx, attrTypeCode, attrLen, attrFlags, message); 921 bgpSession, ctx, attrTypeCode, attrLen, attrFlags, message);
...@@ -792,7 +948,7 @@ final class BgpUpdate { ...@@ -792,7 +948,7 @@ final class BgpUpdate {
792 throws BgpParseException { 948 throws BgpParseException {
793 949
794 // Check the Attribute Length 950 // Check the Attribute Length
795 - if (attrLen != BgpConstants.Update.AtomicAggregate.LENGTH) { 951 + if (attrLen != Update.AtomicAggregate.LENGTH) {
796 // ERROR: Attribute Length Error 952 // ERROR: Attribute Length Error
797 actionsBgpUpdateAttributeLengthError( 953 actionsBgpUpdateAttributeLengthError(
798 bgpSession, ctx, attrTypeCode, attrLen, attrFlags, message); 954 bgpSession, ctx, attrTypeCode, attrLen, attrFlags, message);
...@@ -825,7 +981,7 @@ final class BgpUpdate { ...@@ -825,7 +981,7 @@ final class BgpUpdate {
825 throws BgpParseException { 981 throws BgpParseException {
826 982
827 // Check the Attribute Length 983 // Check the Attribute Length
828 - if (attrLen != BgpConstants.Update.Aggregator.LENGTH) { 984 + if (attrLen != Update.Aggregator.LENGTH) {
829 // ERROR: Attribute Length Error 985 // ERROR: Attribute Length Error
830 actionsBgpUpdateAttributeLengthError( 986 actionsBgpUpdateAttributeLengthError(
831 bgpSession, ctx, attrTypeCode, attrLen, attrFlags, message); 987 bgpSession, ctx, attrTypeCode, attrLen, attrFlags, message);
...@@ -845,6 +1001,214 @@ final class BgpUpdate { ...@@ -845,6 +1001,214 @@ final class BgpUpdate {
845 } 1001 }
846 1002
847 /** 1003 /**
1004 + * Parses BGP UPDATE Attribute Type MP_REACH_NLRI.
1005 + *
1006 + * @param bgpSession the BGP Session to use
1007 + * @param ctx the Channel Handler Context
1008 + * @param attrTypeCode the attribute type code
1009 + * @param attrLen the attribute length (in octets)
1010 + * @param attrFlags the attribute flags
1011 + * @param message the message to parse
1012 + * @return the parsed MP_REACH_NLRI information if recognized, otherwise
1013 + * null
1014 + * @throws BgpParseException
1015 + */
1016 + private static MpNlri parseAttributeTypeMpReachNlri(
1017 + BgpSession bgpSession,
1018 + ChannelHandlerContext ctx,
1019 + int attrTypeCode,
1020 + int attrLen,
1021 + int attrFlags,
1022 + ChannelBuffer message)
1023 + throws BgpParseException {
1024 + int attributeEnd = message.readerIndex() + attrLen;
1025 +
1026 + // Check the Attribute Length
1027 + if (attrLen < Update.MpReachNlri.MIN_LENGTH) {
1028 + // ERROR: Attribute Length Error
1029 + actionsBgpUpdateAttributeLengthError(
1030 + bgpSession, ctx, attrTypeCode, attrLen, attrFlags, message);
1031 + String errorMsg = "Attribute Length Error";
1032 + throw new BgpParseException(errorMsg);
1033 + }
1034 +
1035 + message.markReaderIndex();
1036 + int afi = message.readUnsignedShort();
1037 + int safi = message.readUnsignedByte();
1038 + int nextHopLen = message.readUnsignedByte();
1039 +
1040 + //
1041 + // Verify the AFI/SAFI, and skip the attribute if not recognized.
1042 + // NOTE: Currently, we support only IPv4/IPv6 UNICAST
1043 + //
1044 + if (((afi != MultiprotocolExtensions.AFI_IPV4) &&
1045 + (afi != MultiprotocolExtensions.AFI_IPV6)) ||
1046 + (safi != MultiprotocolExtensions.SAFI_UNICAST)) {
1047 + // Skip the attribute
1048 + message.resetReaderIndex();
1049 + message.skipBytes(attrLen);
1050 + return null;
1051 + }
1052 +
1053 + //
1054 + // Verify the next-hop length
1055 + //
1056 + int expectedNextHopLen = 0;
1057 + switch (afi) {
1058 + case MultiprotocolExtensions.AFI_IPV4:
1059 + expectedNextHopLen = Ip4Address.BYTE_LENGTH;
1060 + break;
1061 + case MultiprotocolExtensions.AFI_IPV6:
1062 + expectedNextHopLen = Ip6Address.BYTE_LENGTH;
1063 + break;
1064 + default:
1065 + // UNREACHABLE
1066 + break;
1067 + }
1068 + if (nextHopLen != expectedNextHopLen) {
1069 + // ERROR: Optional Attribute Error
1070 + message.resetReaderIndex();
1071 + actionsBgpUpdateOptionalAttributeError(
1072 + bgpSession, ctx, attrTypeCode, attrLen, attrFlags, message);
1073 + String errorMsg = "Invalid next-hop network address length. " +
1074 + "Received " + nextHopLen + " expected " + expectedNextHopLen;
1075 + throw new BgpParseException(errorMsg);
1076 + }
1077 + // NOTE: We use "+ 1" to take into account the Reserved field (1 octet)
1078 + if (message.readerIndex() + nextHopLen + 1 >= attributeEnd) {
1079 + // ERROR: Optional Attribute Error
1080 + message.resetReaderIndex();
1081 + actionsBgpUpdateOptionalAttributeError(
1082 + bgpSession, ctx, attrTypeCode, attrLen, attrFlags, message);
1083 + String errorMsg = "Malformed next-hop network address";
1084 + throw new BgpParseException(errorMsg);
1085 + }
1086 +
1087 + //
1088 + // Get the Next-hop address, skip the Reserved field, and get the NLRI
1089 + //
1090 + byte[] nextHopBuffer = new byte[nextHopLen];
1091 + message.readBytes(nextHopBuffer, 0, nextHopLen);
1092 + int reserved = message.readUnsignedByte();
1093 + MpNlri mpNlri = new MpNlri(afi, safi);
1094 + try {
1095 + switch (afi) {
1096 + case MultiprotocolExtensions.AFI_IPV4:
1097 + // The next-hop address
1098 + mpNlri.nextHop4 = Ip4Address.valueOf(nextHopBuffer);
1099 + // The NLRI
1100 + mpNlri.nlri4 = parsePackedIp4Prefixes(
1101 + attributeEnd - message.readerIndex(),
1102 + message);
1103 + break;
1104 + case MultiprotocolExtensions.AFI_IPV6:
1105 + // The next-hop address
1106 + mpNlri.nextHop6 = Ip6Address.valueOf(nextHopBuffer);
1107 + // The NLRI
1108 + mpNlri.nlri6 = parsePackedIp6Prefixes(
1109 + attributeEnd - message.readerIndex(),
1110 + message);
1111 + break;
1112 + default:
1113 + // UNREACHABLE
1114 + break;
1115 + }
1116 + } catch (BgpParseException e) {
1117 + // ERROR: Optional Attribute Error
1118 + message.resetReaderIndex();
1119 + actionsBgpUpdateOptionalAttributeError(
1120 + bgpSession, ctx, attrTypeCode, attrLen, attrFlags, message);
1121 + String errorMsg = "Malformed network layer reachability information";
1122 + throw new BgpParseException(errorMsg);
1123 + }
1124 +
1125 + return mpNlri;
1126 + }
1127 +
1128 + /**
1129 + * Parses BGP UPDATE Attribute Type MP_UNREACH_NLRI.
1130 + *
1131 + * @param bgpSession the BGP Session to use
1132 + * @param ctx the Channel Handler Context
1133 + * @param attrTypeCode the attribute type code
1134 + * @param attrLen the attribute length (in octets)
1135 + * @param attrFlags the attribute flags
1136 + * @param message the message to parse
1137 + * @return the parsed MP_UNREACH_NLRI information if recognized, otherwise
1138 + * null
1139 + * @throws BgpParseException
1140 + */
1141 + private static MpNlri parseAttributeTypeMpUnreachNlri(
1142 + BgpSession bgpSession,
1143 + ChannelHandlerContext ctx,
1144 + int attrTypeCode,
1145 + int attrLen,
1146 + int attrFlags,
1147 + ChannelBuffer message)
1148 + throws BgpParseException {
1149 + int attributeEnd = message.readerIndex() + attrLen;
1150 +
1151 + // Check the Attribute Length
1152 + if (attrLen < Update.MpUnreachNlri.MIN_LENGTH) {
1153 + // ERROR: Attribute Length Error
1154 + actionsBgpUpdateAttributeLengthError(
1155 + bgpSession, ctx, attrTypeCode, attrLen, attrFlags, message);
1156 + String errorMsg = "Attribute Length Error";
1157 + throw new BgpParseException(errorMsg);
1158 + }
1159 +
1160 + message.markReaderIndex();
1161 + int afi = message.readUnsignedShort();
1162 + int safi = message.readUnsignedByte();
1163 +
1164 + //
1165 + // Verify the AFI/SAFI, and skip the attribute if not recognized.
1166 + // NOTE: Currently, we support only IPv4/IPv6 UNICAST
1167 + //
1168 + if (((afi != MultiprotocolExtensions.AFI_IPV4) &&
1169 + (afi != MultiprotocolExtensions.AFI_IPV6)) ||
1170 + (safi != MultiprotocolExtensions.SAFI_UNICAST)) {
1171 + // Skip the attribute
1172 + message.resetReaderIndex();
1173 + message.skipBytes(attrLen);
1174 + return null;
1175 + }
1176 +
1177 + //
1178 + // Get the Withdrawn Routes
1179 + //
1180 + MpNlri mpNlri = new MpNlri(afi, safi);
1181 + try {
1182 + switch (afi) {
1183 + case MultiprotocolExtensions.AFI_IPV4:
1184 + // The Withdrawn Routes
1185 + mpNlri.nlri4 = parsePackedIp4Prefixes(
1186 + attributeEnd - message.readerIndex(),
1187 + message);
1188 + break;
1189 + case MultiprotocolExtensions.AFI_IPV6:
1190 + // The Withdrawn Routes
1191 + mpNlri.nlri6 = parsePackedIp6Prefixes(
1192 + attributeEnd - message.readerIndex(),
1193 + message);
1194 + break;
1195 + default:
1196 + // UNREACHABLE
1197 + break;
1198 + }
1199 + } catch (BgpParseException e) {
1200 + // ERROR: Optional Attribute Error
1201 + message.resetReaderIndex();
1202 + actionsBgpUpdateOptionalAttributeError(
1203 + bgpSession, ctx, attrTypeCode, attrLen, attrFlags, message);
1204 + String errorMsg = "Malformed withdrawn routes";
1205 + throw new BgpParseException(errorMsg);
1206 + }
1207 +
1208 + return mpNlri;
1209 + }
1210 +
1211 + /**
848 * Parses a message that contains encoded IPv4 network prefixes. 1212 * Parses a message that contains encoded IPv4 network prefixes.
849 * <p> 1213 * <p>
850 * The IPv4 prefixes are encoded in the form: 1214 * The IPv4 prefixes are encoded in the form:
...@@ -857,7 +1221,7 @@ final class BgpUpdate { ...@@ -857,7 +1221,7 @@ final class BgpUpdate {
857 * @return a collection of parsed IPv4 network prefixes 1221 * @return a collection of parsed IPv4 network prefixes
858 * @throws BgpParseException 1222 * @throws BgpParseException
859 */ 1223 */
860 - private static Collection<Ip4Prefix> parsePackedPrefixes( 1224 + private static Collection<Ip4Prefix> parsePackedIp4Prefixes(
861 int totalLength, 1225 int totalLength,
862 ChannelBuffer message) 1226 ChannelBuffer message)
863 throws BgpParseException { 1227 throws BgpParseException {
...@@ -868,6 +1232,7 @@ final class BgpUpdate { ...@@ -868,6 +1232,7 @@ final class BgpUpdate {
868 } 1232 }
869 1233
870 // Parse the data 1234 // Parse the data
1235 + byte[] buffer = new byte[Ip4Address.BYTE_LENGTH];
871 int dataEnd = message.readerIndex() + totalLength; 1236 int dataEnd = message.readerIndex() + totalLength;
872 while (message.readerIndex() < dataEnd) { 1237 while (message.readerIndex() < dataEnd) {
873 int prefixBitlen = message.readUnsignedByte(); 1238 int prefixBitlen = message.readUnsignedByte();
...@@ -877,17 +1242,52 @@ final class BgpUpdate { ...@@ -877,17 +1242,52 @@ final class BgpUpdate {
877 throw new BgpParseException(errorMsg); 1242 throw new BgpParseException(errorMsg);
878 } 1243 }
879 1244
880 - long address = 0; 1245 + message.readBytes(buffer, 0, prefixBytelen);
881 - long extraShift = (4 - prefixBytelen) * 8; 1246 + Ip4Prefix prefix = Ip4Prefix.valueOf(Ip4Address.valueOf(buffer),
882 - while (prefixBytelen > 0) { 1247 + prefixBitlen);
883 - address <<= 8; 1248 + result.add(prefix);
884 - address |= message.readUnsignedByte(); 1249 + }
885 - prefixBytelen--; 1250 +
1251 + return result;
1252 + }
1253 +
1254 + /**
1255 + * Parses a message that contains encoded IPv6 network prefixes.
1256 + * <p>
1257 + * The IPv6 prefixes are encoded in the form:
1258 + * <Length, Prefix> where Length is the length in bits of the IPv6 prefix,
1259 + * and Prefix is the IPv6 prefix (padded with trailing bits to the end
1260 + * of an octet).
1261 + *
1262 + * @param totalLength the total length of the data to parse
1263 + * @param message the message with data to parse
1264 + * @return a collection of parsed IPv6 network prefixes
1265 + * @throws BgpParseException
1266 + */
1267 + private static Collection<Ip6Prefix> parsePackedIp6Prefixes(
1268 + int totalLength,
1269 + ChannelBuffer message)
1270 + throws BgpParseException {
1271 + Collection<Ip6Prefix> result = new ArrayList<>();
1272 +
1273 + if (totalLength == 0) {
1274 + return result;
1275 + }
1276 +
1277 + // Parse the data
1278 + byte[] buffer = new byte[Ip6Address.BYTE_LENGTH];
1279 + int dataEnd = message.readerIndex() + totalLength;
1280 + while (message.readerIndex() < dataEnd) {
1281 + int prefixBitlen = message.readUnsignedByte();
1282 + int prefixBytelen = (prefixBitlen + 7) / 8; // Round-up
1283 + if (message.readerIndex() + prefixBytelen > dataEnd) {
1284 + String errorMsg = "Malformed Network Prefixes";
1285 + throw new BgpParseException(errorMsg);
886 } 1286 }
887 - address <<= extraShift; 1287 +
888 - Ip4Prefix prefix = 1288 + message.readBytes(buffer, 0, prefixBytelen);
889 - Ip4Prefix.valueOf(Ip4Address.valueOf((int) address), 1289 + Ip6Prefix prefix = Ip6Prefix.valueOf(Ip6Address.valueOf(buffer),
890 - prefixBitlen); 1290 + prefixBitlen);
891 result.add(prefix); 1291 result.add(prefix);
892 } 1292 }
893 1293
...@@ -1078,7 +1478,7 @@ final class BgpUpdate { ...@@ -1078,7 +1478,7 @@ final class BgpUpdate {
1078 bgpSession.getRemoteAddress(), nextHop); 1478 bgpSession.getRemoteAddress(), nextHop);
1079 1479
1080 // 1480 //
1081 - // ERROR: Invalid ORIGIN Attribute 1481 + // ERROR: Invalid NEXT_HOP Attribute
1082 // 1482 //
1083 // Send NOTIFICATION and close the connection 1483 // Send NOTIFICATION and close the connection
1084 int errorCode = UpdateMessageError.ERROR_CODE; 1484 int errorCode = UpdateMessageError.ERROR_CODE;
...@@ -1135,6 +1535,45 @@ final class BgpUpdate { ...@@ -1135,6 +1535,45 @@ final class BgpUpdate {
1135 1535
1136 /** 1536 /**
1137 * Applies the appropriate actions after detecting BGP UPDATE 1537 * Applies the appropriate actions after detecting BGP UPDATE
1538 + * Optional Attribute Error: send NOTIFICATION and close
1539 + * the channel.
1540 + *
1541 + * @param bgpSession the BGP Session to use
1542 + * @param ctx the Channel Handler Context
1543 + * @param attrTypeCode the attribute type code
1544 + * @param attrLen the attribute length (in octets)
1545 + * @param attrFlags the attribute flags
1546 + * @param message the message with the data
1547 + */
1548 + private static void actionsBgpUpdateOptionalAttributeError(
1549 + BgpSession bgpSession,
1550 + ChannelHandlerContext ctx,
1551 + int attrTypeCode,
1552 + int attrLen,
1553 + int attrFlags,
1554 + ChannelBuffer message) {
1555 + log.debug("BGP RX UPDATE Error from {}: Optional Attribute Error: {}",
1556 + bgpSession.getRemoteAddress(), attrTypeCode);
1557 +
1558 + //
1559 + // ERROR: Optional Attribute Error
1560 + //
1561 + // Send NOTIFICATION and close the connection
1562 + int errorCode = UpdateMessageError.ERROR_CODE;
1563 + int errorSubcode =
1564 + UpdateMessageError.OPTIONAL_ATTRIBUTE_ERROR;
1565 + ChannelBuffer data =
1566 + prepareBgpUpdateNotificationDataPayload(attrTypeCode, attrLen,
1567 + attrFlags, message);
1568 + ChannelBuffer txMessage =
1569 + BgpNotification.prepareBgpNotification(errorCode, errorSubcode,
1570 + data);
1571 + ctx.getChannel().write(txMessage);
1572 + bgpSession.closeSession(ctx);
1573 + }
1574 +
1575 + /**
1576 + * Applies the appropriate actions after detecting BGP UPDATE
1138 * Attribute Length Error: send NOTIFICATION and close the channel. 1577 * Attribute Length Error: send NOTIFICATION and close the channel.
1139 * 1578 *
1140 * @param bgpSession the BGP Session to use 1579 * @param bgpSession the BGP Session to use
...@@ -1227,4 +1666,42 @@ final class BgpUpdate { ...@@ -1227,4 +1666,42 @@ final class BgpUpdate {
1227 data.writeBytes(message, attrLen); 1666 data.writeBytes(message, attrLen);
1228 return data; 1667 return data;
1229 } 1668 }
1669 +
1670 + /**
1671 + * Helper class for storing Multiprotocol Network Layer Reachability
1672 + * information.
1673 + */
1674 + private static final class MpNlri {
1675 + private final int afi;
1676 + private final int safi;
1677 + private Ip4Address nextHop4;
1678 + private Ip6Address nextHop6;
1679 + private Collection<Ip4Prefix> nlri4 = new ArrayList<>();
1680 + private Collection<Ip6Prefix> nlri6 = new ArrayList<>();
1681 +
1682 + /**
1683 + * Constructor.
1684 + *
1685 + * @param afi the Address Family Identifier
1686 + * @param safi the Subsequent Address Family Identifier
1687 + */
1688 + private MpNlri(int afi, int safi) {
1689 + this.afi = afi;
1690 + this.safi = safi;
1691 + }
1692 + }
1693 +
1694 + /**
1695 + * Helper class for storing decoded BGP routing information.
1696 + */
1697 + private static final class DecodedBgpRoutes {
1698 + private final Map<Ip4Prefix, BgpRouteEntry> addedUnicastRoutes4 =
1699 + new HashMap<>();
1700 + private final Map<Ip6Prefix, BgpRouteEntry> addedUnicastRoutes6 =
1701 + new HashMap<>();
1702 + private final Map<Ip4Prefix, BgpRouteEntry> deletedUnicastRoutes4 =
1703 + new HashMap<>();
1704 + private final Map<Ip6Prefix, BgpRouteEntry> deletedUnicastRoutes6 =
1705 + new HashMap<>();
1706 + }
1230 } 1707 }
......
...@@ -81,7 +81,8 @@ public class BgpRoutesListCommand extends AbstractShellCommand { ...@@ -81,7 +81,8 @@ public class BgpRoutesListCommand extends AbstractShellCommand {
81 81
82 // Print the routes 82 // Print the routes
83 if (foundBgpSession != null) { 83 if (foundBgpSession != null) {
84 - printRoutes(foundBgpSession.bgpRibIn().values()); 84 + printRoutes(foundBgpSession.bgpRibIn4().values());
85 + printRoutes(foundBgpSession.bgpRibIn6().values());
85 } else { 86 } else {
86 printRoutes(service.getBgpRoutes()); 87 printRoutes(service.getBgpRoutes());
87 } 88 }
......
...@@ -303,7 +303,7 @@ public class BgpSessionManagerTest { ...@@ -303,7 +303,7 @@ public class BgpSessionManagerTest {
303 private Collection<BgpRouteEntry> waitForBgpRibIn(BgpSession bgpSession, 303 private Collection<BgpRouteEntry> waitForBgpRibIn(BgpSession bgpSession,
304 long expectedRoutes) 304 long expectedRoutes)
305 throws InterruptedException { 305 throws InterruptedException {
306 - Collection<BgpRouteEntry> bgpRibIn = bgpSession.bgpRibIn().values(); 306 + Collection<BgpRouteEntry> bgpRibIn = bgpSession.bgpRibIn4().values();
307 307
308 final int maxChecks = 500; // Max wait of 5 seconds 308 final int maxChecks = 500; // Max wait of 5 seconds
309 for (int i = 0; i < maxChecks; i++) { 309 for (int i = 0; i < maxChecks; i++) {
...@@ -311,7 +311,7 @@ public class BgpSessionManagerTest { ...@@ -311,7 +311,7 @@ public class BgpSessionManagerTest {
311 break; 311 break;
312 } 312 }
313 Thread.sleep(10); 313 Thread.sleep(10);
314 - bgpRibIn = bgpSession.bgpRibIn().values(); 314 + bgpRibIn = bgpSession.bgpRibIn4().values();
315 } 315 }
316 316
317 return bgpRibIn; 317 return bgpRibIn;
......