Pavlin Radoslavov

Added IPv6 routing support to SDN-IP, and integrated it with BGP:

 * The routing entries as received from BGP can be either IPv4 or IPv6
 * The CLI prints the IPv4 and IPv6 routes
 * The BGP peering is still over IPv4, so configuration-wise the IPv6
   routes from the eBGP peers have to be configured to use the IPv4 peering.
 * The integration/testing with the IPv6 Network Discovery Protocol is not
   done yet.
 * The integration/testing with IPv6 intents is not done yet.

Also:
 * Moved nested class BgpSessionManager.BgpRouteSelector out of the
   BgpSessionManager class.
 * Code cleanup.

Change-Id: I9f2dbe4395a72d353bbf215a8a14b01b53c3423f
...@@ -29,7 +29,7 @@ import java.util.concurrent.Executors; ...@@ -29,7 +29,7 @@ import java.util.concurrent.Executors;
29 import java.util.concurrent.Semaphore; 29 import java.util.concurrent.Semaphore;
30 30
31 import org.apache.commons.lang3.tuple.Pair; 31 import org.apache.commons.lang3.tuple.Pair;
32 -import org.onlab.packet.Ip4Prefix; 32 +import org.onlab.packet.IpPrefix;
33 import org.onosproject.core.ApplicationId; 33 import org.onosproject.core.ApplicationId;
34 import org.onosproject.net.flow.criteria.Criteria.IPCriterion; 34 import org.onosproject.net.flow.criteria.Criteria.IPCriterion;
35 import org.onosproject.net.flow.criteria.Criterion; 35 import org.onosproject.net.flow.criteria.Criterion;
...@@ -55,7 +55,7 @@ public class IntentSynchronizer { ...@@ -55,7 +55,7 @@ public class IntentSynchronizer {
55 private final ApplicationId appId; 55 private final ApplicationId appId;
56 private final IntentService intentService; 56 private final IntentService intentService;
57 private final Map<IntentKey, PointToPointIntent> peerIntents; 57 private final Map<IntentKey, PointToPointIntent> peerIntents;
58 - private final Map<Ip4Prefix, MultiPointToSinglePointIntent> routeIntents; 58 + private final Map<IpPrefix, MultiPointToSinglePointIntent> routeIntents;
59 59
60 // 60 //
61 // State to deal with SDN-IP Leader election and pushing Intents 61 // State to deal with SDN-IP Leader election and pushing Intents
...@@ -182,7 +182,7 @@ public class IntentSynchronizer { ...@@ -182,7 +182,7 @@ public class IntentSynchronizer {
182 public Collection<MultiPointToSinglePointIntent> getRouteIntents() { 182 public Collection<MultiPointToSinglePointIntent> getRouteIntents() {
183 List<MultiPointToSinglePointIntent> result = new LinkedList<>(); 183 List<MultiPointToSinglePointIntent> result = new LinkedList<>();
184 184
185 - for (Map.Entry<Ip4Prefix, MultiPointToSinglePointIntent> entry : 185 + for (Map.Entry<IpPrefix, MultiPointToSinglePointIntent> entry :
186 routeIntents.entrySet()) { 186 routeIntents.entrySet()) {
187 result.add(entry.getValue()); 187 result.add(entry.getValue());
188 } 188 }
...@@ -247,12 +247,12 @@ public class IntentSynchronizer { ...@@ -247,12 +247,12 @@ public class IntentSynchronizer {
247 * Updates multi-point-to-single-point route intents. 247 * Updates multi-point-to-single-point route intents.
248 * 248 *
249 * @param submitIntents the intents to submit 249 * @param submitIntents the intents to submit
250 - * @param withdrawPrefixes the IPv4 matching prefixes for the intents 250 + * @param withdrawPrefixes the IPv4 or IPv6 matching prefixes for the
251 - * to withdraw 251 + * intents to withdraw
252 */ 252 */
253 void updateRouteIntents( 253 void updateRouteIntents(
254 - Collection<Pair<Ip4Prefix, MultiPointToSinglePointIntent>> submitIntents, 254 + Collection<Pair<IpPrefix, MultiPointToSinglePointIntent>> submitIntents,
255 - Collection<Ip4Prefix> withdrawPrefixes) { 255 + Collection<IpPrefix> withdrawPrefixes) {
256 256
257 // 257 //
258 // NOTE: Semantically, we MUST withdraw existing intents before 258 // NOTE: Semantically, we MUST withdraw existing intents before
...@@ -269,7 +269,7 @@ public class IntentSynchronizer { ...@@ -269,7 +269,7 @@ public class IntentSynchronizer {
269 // 269 //
270 IntentOperations.Builder withdrawBuilder = 270 IntentOperations.Builder withdrawBuilder =
271 IntentOperations.builder(appId); 271 IntentOperations.builder(appId);
272 - for (Ip4Prefix prefix : withdrawPrefixes) { 272 + for (IpPrefix prefix : withdrawPrefixes) {
273 intent = routeIntents.remove(prefix); 273 intent = routeIntents.remove(prefix);
274 if (intent == null) { 274 if (intent == null) {
275 log.trace("SDN-IP No intent in routeIntents to delete " + 275 log.trace("SDN-IP No intent in routeIntents to delete " +
...@@ -287,9 +287,9 @@ public class IntentSynchronizer { ...@@ -287,9 +287,9 @@ public class IntentSynchronizer {
287 // 287 //
288 IntentOperations.Builder submitBuilder = 288 IntentOperations.Builder submitBuilder =
289 IntentOperations.builder(appId); 289 IntentOperations.builder(appId);
290 - for (Pair<Ip4Prefix, MultiPointToSinglePointIntent> pair : 290 + for (Pair<IpPrefix, MultiPointToSinglePointIntent> pair :
291 submitIntents) { 291 submitIntents) {
292 - Ip4Prefix prefix = pair.getLeft(); 292 + IpPrefix prefix = pair.getLeft();
293 intent = pair.getRight(); 293 intent = pair.getRight();
294 MultiPointToSinglePointIntent oldIntent = 294 MultiPointToSinglePointIntent oldIntent =
295 routeIntents.put(prefix, intent); 295 routeIntents.put(prefix, intent);
...@@ -382,18 +382,23 @@ public class IntentSynchronizer { ...@@ -382,18 +382,23 @@ public class IntentSynchronizer {
382 // Find the IP prefix 382 // Find the IP prefix
383 Criterion c = 383 Criterion c =
384 mp2pIntent.selector().getCriterion(Criterion.Type.IPV4_DST); 384 mp2pIntent.selector().getCriterion(Criterion.Type.IPV4_DST);
385 + if (c == null) {
386 + // Try IPv6
387 + c =
388 + mp2pIntent.selector().getCriterion(Criterion.Type.IPV6_DST);
389 + }
385 if (c != null && c instanceof IPCriterion) { 390 if (c != null && c instanceof IPCriterion) {
386 IPCriterion ipCriterion = (IPCriterion) c; 391 IPCriterion ipCriterion = (IPCriterion) c;
387 - Ip4Prefix ip4Prefix = ipCriterion.ip().getIp4Prefix(); 392 + IpPrefix ipPrefix = ipCriterion.ip();
388 - if (ip4Prefix == null) { 393 + if (ipPrefix == null) {
389 continue; 394 continue;
390 } 395 }
391 log.trace("SDN-IP Intent Synchronizer: updating " + 396 log.trace("SDN-IP Intent Synchronizer: updating " +
392 "in-memory Route Intent for prefix {}", 397 "in-memory Route Intent for prefix {}",
393 - ip4Prefix); 398 + ipPrefix);
394 - routeIntents.put(ip4Prefix, mp2pIntent); 399 + routeIntents.put(ipPrefix, mp2pIntent);
395 } else { 400 } else {
396 - log.warn("SDN-IP no IPV4_DST criterion found for Intent {}", 401 + log.warn("SDN-IP no IPV4_DST or IPV6_DST criterion found for Intent {}",
397 mp2pIntent.id()); 402 mp2pIntent.id());
398 } 403 }
399 continue; 404 continue;
......
...@@ -19,8 +19,8 @@ import static com.google.common.base.Preconditions.checkNotNull; ...@@ -19,8 +19,8 @@ import static com.google.common.base.Preconditions.checkNotNull;
19 19
20 import java.util.Objects; 20 import java.util.Objects;
21 21
22 -import org.onlab.packet.Ip4Address; 22 +import org.onlab.packet.IpAddress;
23 -import org.onlab.packet.Ip4Prefix; 23 +import org.onlab.packet.IpPrefix;
24 24
25 import com.google.common.base.MoreObjects; 25 import com.google.common.base.MoreObjects;
26 26
...@@ -28,8 +28,8 @@ import com.google.common.base.MoreObjects; ...@@ -28,8 +28,8 @@ import com.google.common.base.MoreObjects;
28 * Represents a route entry for an IP prefix. 28 * Represents a route entry for an IP prefix.
29 */ 29 */
30 public class RouteEntry { 30 public class RouteEntry {
31 - private final Ip4Prefix prefix; // The IP prefix 31 + private final IpPrefix prefix; // The IP prefix
32 - private final Ip4Address nextHop; // Next-hop IP address 32 + private final IpAddress nextHop; // Next-hop IP address
33 33
34 /** 34 /**
35 * Class constructor. 35 * Class constructor.
...@@ -37,17 +37,26 @@ public class RouteEntry { ...@@ -37,17 +37,26 @@ public class RouteEntry {
37 * @param prefix the IP prefix of the route 37 * @param prefix the IP prefix of the route
38 * @param nextHop the next hop IP address for the route 38 * @param nextHop the next hop IP address for the route
39 */ 39 */
40 - public RouteEntry(Ip4Prefix prefix, Ip4Address nextHop) { 40 + public RouteEntry(IpPrefix prefix, IpAddress nextHop) {
41 this.prefix = checkNotNull(prefix); 41 this.prefix = checkNotNull(prefix);
42 this.nextHop = checkNotNull(nextHop); 42 this.nextHop = checkNotNull(nextHop);
43 } 43 }
44 44
45 /** 45 /**
46 + * Returns the IP version of the route.
47 + *
48 + * @return the IP version of the route
49 + */
50 + public IpAddress.Version version() {
51 + return nextHop.version();
52 + }
53 +
54 + /**
46 * Returns the IP prefix of the route. 55 * Returns the IP prefix of the route.
47 * 56 *
48 * @return the IP prefix of the route 57 * @return the IP prefix of the route
49 */ 58 */
50 - public Ip4Prefix prefix() { 59 + public IpPrefix prefix() {
51 return prefix; 60 return prefix;
52 } 61 }
53 62
...@@ -56,27 +65,32 @@ public class RouteEntry { ...@@ -56,27 +65,32 @@ public class RouteEntry {
56 * 65 *
57 * @return the next hop IP address for the route 66 * @return the next hop IP address for the route
58 */ 67 */
59 - public Ip4Address nextHop() { 68 + public IpAddress nextHop() {
60 return nextHop; 69 return nextHop;
61 } 70 }
62 71
63 /** 72 /**
64 - * Creates the binary string representation of an IPv4 prefix. 73 + * Creates the binary string representation of an IP prefix.
74 + * The prefix can be either IPv4 or IPv6.
65 * The string length is equal to the prefix length. 75 * The string length is equal to the prefix length.
66 * 76 *
67 - * @param ip4Prefix the IPv4 prefix to use 77 + * @param ipPrefix the IP prefix to use
68 * @return the binary string representation 78 * @return the binary string representation
69 */ 79 */
70 - static String createBinaryString(Ip4Prefix ip4Prefix) { 80 + static String createBinaryString(IpPrefix ipPrefix) {
71 - if (ip4Prefix.prefixLength() == 0) { 81 + if (ipPrefix.prefixLength() == 0) {
72 return ""; 82 return "";
73 } 83 }
74 84
75 - StringBuilder result = new StringBuilder(ip4Prefix.prefixLength()); 85 + byte[] octets = ipPrefix.address().toOctets();
76 - long value = ip4Prefix.address().toInt() & 0xffffffffL; 86 + StringBuilder result = new StringBuilder(ipPrefix.prefixLength());
77 - for (int i = 0; i < ip4Prefix.prefixLength(); i++) { 87 + for (int i = 0; i < ipPrefix.prefixLength(); i++) {
78 - long mask = 1 << (Ip4Prefix.MAX_MASK_LENGTH - 1 - i); 88 + int byteOffset = i / Byte.SIZE;
79 - result.append(((value & mask) == 0) ? "0" : "1"); 89 + int bitOffset = i % Byte.SIZE;
90 + int mask = 1 << (Byte.SIZE - 1 - bitOffset);
91 + byte value = octets[byteOffset];
92 + boolean isSet = ((value & mask) != 0);
93 + result.append(isSet ? "1" : "0");
80 } 94 }
81 return result.toString(); 95 return result.toString();
82 } 96 }
......
...@@ -164,13 +164,23 @@ public class SdnIp implements SdnIpService { ...@@ -164,13 +164,23 @@ public class SdnIp implements SdnIpService {
164 } 164 }
165 165
166 @Override 166 @Override
167 - public Collection<BgpRouteEntry> getBgpRoutes() { 167 + public Collection<BgpRouteEntry> getBgpRoutes4() {
168 - return bgpSessionManager.getBgpRoutes(); 168 + return bgpSessionManager.getBgpRoutes4();
169 } 169 }
170 170
171 @Override 171 @Override
172 - public Collection<RouteEntry> getRoutes() { 172 + public Collection<BgpRouteEntry> getBgpRoutes6() {
173 - return router.getRoutes(); 173 + return bgpSessionManager.getBgpRoutes6();
174 + }
175 +
176 + @Override
177 + public Collection<RouteEntry> getRoutes4() {
178 + return router.getRoutes4();
179 + }
180 +
181 + @Override
182 + public Collection<RouteEntry> getRoutes6() {
183 + return router.getRoutes6();
174 } 184 }
175 185
176 @Override 186 @Override
......
...@@ -32,18 +32,32 @@ public interface SdnIpService { ...@@ -32,18 +32,32 @@ public interface SdnIpService {
32 public Collection<BgpSession> getBgpSessions(); 32 public Collection<BgpSession> getBgpSessions();
33 33
34 /** 34 /**
35 - * Gets the BGP routes. 35 + * Gets the selected IPv4 BGP routes among all BGP sessions.
36 * 36 *
37 - * @return the BGP routes 37 + * @return the selected IPv4 BGP routes among all BGP sessions
38 */ 38 */
39 - public Collection<BgpRouteEntry> getBgpRoutes(); 39 + public Collection<BgpRouteEntry> getBgpRoutes4();
40 40
41 /** 41 /**
42 - * Gets all the routes known to SDN-IP. 42 + * Gets the selected IPv6 BGP routes among all BGP sessions.
43 * 43 *
44 - * @return the SDN-IP routes 44 + * @return the selected IPv6 BGP routes among all BGP sessions
45 */ 45 */
46 - public Collection<RouteEntry> getRoutes(); 46 + public Collection<BgpRouteEntry> getBgpRoutes6();
47 +
48 + /**
49 + * Gets all IPv4 routes known to SDN-IP.
50 + *
51 + * @return the SDN-IP IPv4 routes
52 + */
53 + public Collection<RouteEntry> getRoutes4();
54 +
55 + /**
56 + * Gets all IPv6 routes known to SDN-IP.
57 + *
58 + * @return the SDN-IP IPv6 routes
59 + */
60 + public Collection<RouteEntry> getRoutes6();
47 61
48 /** 62 /**
49 * Changes whether this SDN-IP instance is the primary or not based on the 63 * Changes whether this SDN-IP instance is the primary or not based on the
......
...@@ -20,8 +20,9 @@ import static com.google.common.base.Preconditions.checkNotNull; ...@@ -20,8 +20,9 @@ import static com.google.common.base.Preconditions.checkNotNull;
20 import java.util.ArrayList; 20 import java.util.ArrayList;
21 import java.util.Objects; 21 import java.util.Objects;
22 22
23 +import org.onlab.packet.IpAddress;
24 +import org.onlab.packet.IpPrefix;
23 import org.onlab.packet.Ip4Address; 25 import org.onlab.packet.Ip4Address;
24 -import org.onlab.packet.Ip4Prefix;
25 import org.onosproject.sdnip.RouteEntry; 26 import org.onosproject.sdnip.RouteEntry;
26 import org.onosproject.sdnip.bgp.BgpConstants.Update; 27 import org.onosproject.sdnip.bgp.BgpConstants.Update;
27 28
...@@ -48,8 +49,8 @@ public class BgpRouteEntry extends RouteEntry { ...@@ -48,8 +49,8 @@ public class BgpRouteEntry extends RouteEntry {
48 * @param asPath the AS path 49 * @param asPath the AS path
49 * @param localPref the route local preference 50 * @param localPref the route local preference
50 */ 51 */
51 - public BgpRouteEntry(BgpSession bgpSession, Ip4Prefix prefix, 52 + public BgpRouteEntry(BgpSession bgpSession, IpPrefix prefix,
52 - Ip4Address nextHop, byte origin, 53 + IpAddress nextHop, byte origin,
53 BgpRouteEntry.AsPath asPath, long localPref) { 54 BgpRouteEntry.AsPath asPath, long localPref) {
54 super(prefix, nextHop); 55 super(prefix, nextHop);
55 this.bgpSession = checkNotNull(bgpSession); 56 this.bgpSession = checkNotNull(bgpSession);
......
1 +/*
2 + * Copyright 2015 Open Networking Laboratory
3 + *
4 + * Licensed under the Apache License, Version 2.0 (the "License");
5 + * you may not use this file except in compliance with the License.
6 + * You may obtain a copy of the License at
7 + *
8 + * http://www.apache.org/licenses/LICENSE-2.0
9 + *
10 + * Unless required by applicable law or agreed to in writing, software
11 + * distributed under the License is distributed on an "AS IS" BASIS,
12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 + * See the License for the specific language governing permissions and
14 + * limitations under the License.
15 + */
16 +package org.onosproject.sdnip.bgp;
17 +
18 +import java.util.Collection;
19 +import java.util.LinkedList;
20 +
21 +import org.onlab.packet.IpPrefix;
22 +import org.onosproject.sdnip.RouteUpdate;
23 +import org.slf4j.Logger;
24 +import org.slf4j.LoggerFactory;
25 +
26 +/**
27 + * Class to receive and process the BGP routes from each BGP Session/Peer.
28 + */
29 +class BgpRouteSelector {
30 + private static final Logger log =
31 + LoggerFactory.getLogger(BgpRouteSelector.class);
32 +
33 + private BgpSessionManager bgpSessionManager;
34 +
35 + /**
36 + * Constructor.
37 + *
38 + * @param bgpSessionManager the BGP Session Manager to use
39 + */
40 + BgpRouteSelector(BgpSessionManager bgpSessionManager) {
41 + this.bgpSessionManager = bgpSessionManager;
42 + }
43 +
44 + /**
45 + * Processes route entry updates: added/updated and deleted route
46 + * entries.
47 + *
48 + * @param bgpSession the BGP session the route entry updates were
49 + * received on
50 + * @param addedBgpRouteEntries the added/updated route entries to process
51 + * @param deletedBgpRouteEntries the deleted route entries to process
52 + */
53 + synchronized void routeUpdates(BgpSession bgpSession,
54 + Collection<BgpRouteEntry> addedBgpRouteEntries,
55 + Collection<BgpRouteEntry> deletedBgpRouteEntries) {
56 + Collection<RouteUpdate> routeUpdates = new LinkedList<>();
57 + RouteUpdate routeUpdate;
58 +
59 + if (bgpSessionManager.isShutdown()) {
60 + return; // Ignore any leftover updates if shutdown
61 + }
62 + // Process the deleted route entries
63 + for (BgpRouteEntry bgpRouteEntry : deletedBgpRouteEntries) {
64 + routeUpdate = processDeletedRoute(bgpSession, bgpRouteEntry);
65 + if (routeUpdate != null) {
66 + routeUpdates.add(routeUpdate);
67 + }
68 + }
69 +
70 + // Process the added/updated route entries
71 + for (BgpRouteEntry bgpRouteEntry : addedBgpRouteEntries) {
72 + routeUpdate = processAddedRoute(bgpSession, bgpRouteEntry);
73 + if (routeUpdate != null) {
74 + routeUpdates.add(routeUpdate);
75 + }
76 + }
77 + bgpSessionManager.getRouteListener().update(routeUpdates);
78 + }
79 +
80 + /**
81 + * Processes an added/updated route entry.
82 + *
83 + * @param bgpSession the BGP session the route entry update was received on
84 + * @param bgpRouteEntry the added/updated route entry
85 + * @return the result route update that should be forwarded to the
86 + * Route Listener, or null if no route update should be forwarded
87 + */
88 + private RouteUpdate processAddedRoute(BgpSession bgpSession,
89 + BgpRouteEntry bgpRouteEntry) {
90 + RouteUpdate routeUpdate;
91 + BgpRouteEntry bestBgpRouteEntry =
92 + bgpSessionManager.findBgpRoute(bgpRouteEntry.prefix());
93 +
94 + //
95 + // Install the new route entry if it is better than the
96 + // current best route.
97 + //
98 + if ((bestBgpRouteEntry == null) ||
99 + bgpRouteEntry.isBetterThan(bestBgpRouteEntry)) {
100 + bgpSessionManager.addBgpRoute(bgpRouteEntry);
101 + routeUpdate =
102 + new RouteUpdate(RouteUpdate.Type.UPDATE, bgpRouteEntry);
103 + return routeUpdate;
104 + }
105 +
106 + //
107 + // If the route entry arrived on the same BGP Session as
108 + // the current best route, then elect the next best route
109 + // and install it.
110 + //
111 + if (bestBgpRouteEntry.getBgpSession() !=
112 + bgpRouteEntry.getBgpSession()) {
113 + return null; // Nothing to do
114 + }
115 +
116 + // Find the next best route
117 + bestBgpRouteEntry = findBestBgpRoute(bgpRouteEntry.prefix());
118 + if (bestBgpRouteEntry == null) {
119 + //
120 + // TODO: Shouldn't happen. Install the new route as a
121 + // pre-caution.
122 + //
123 + log.debug("BGP next best route for prefix {} is missing. " +
124 + "Adding the route that is currently processed.",
125 + bgpRouteEntry.prefix());
126 + bestBgpRouteEntry = bgpRouteEntry;
127 + }
128 +
129 + // Install the next best route
130 + bgpSessionManager.addBgpRoute(bestBgpRouteEntry);
131 + routeUpdate = new RouteUpdate(RouteUpdate.Type.UPDATE,
132 + bestBgpRouteEntry);
133 + return routeUpdate;
134 + }
135 +
136 + /**
137 + * Processes a deleted route entry.
138 + *
139 + * @param bgpSession the BGP session the route entry update was received on
140 + * @param bgpRouteEntry the deleted route entry
141 + * @return the result route update that should be forwarded to the
142 + * Route Listener, or null if no route update should be forwarded
143 + */
144 + private RouteUpdate processDeletedRoute(BgpSession bgpSession,
145 + BgpRouteEntry bgpRouteEntry) {
146 + RouteUpdate routeUpdate;
147 + BgpRouteEntry bestBgpRouteEntry =
148 + bgpSessionManager.findBgpRoute(bgpRouteEntry.prefix());
149 +
150 + //
151 + // Remove the route entry only if it was the best one.
152 + // Install the the next best route if it exists.
153 + //
154 + // NOTE: We intentionally use "==" instead of method equals(),
155 + // because we need to check whether this is same object.
156 + //
157 + if (bgpRouteEntry != bestBgpRouteEntry) {
158 + return null; // Nothing to do
159 + }
160 +
161 + //
162 + // Find the next best route
163 + //
164 + bestBgpRouteEntry = findBestBgpRoute(bgpRouteEntry.prefix());
165 + if (bestBgpRouteEntry != null) {
166 + // Install the next best route
167 + bgpSessionManager.addBgpRoute(bestBgpRouteEntry);
168 + routeUpdate = new RouteUpdate(RouteUpdate.Type.UPDATE,
169 + bestBgpRouteEntry);
170 + return routeUpdate;
171 + }
172 +
173 + //
174 + // No route found. Remove the route entry
175 + //
176 + bgpSessionManager.removeBgpRoute(bgpRouteEntry.prefix());
177 + routeUpdate = new RouteUpdate(RouteUpdate.Type.DELETE, bgpRouteEntry);
178 + return routeUpdate;
179 + }
180 +
181 + /**
182 + * Finds the best route entry among all BGP Sessions.
183 + *
184 + * @param prefix the prefix of the route
185 + * @return the best route if found, otherwise null
186 + */
187 + private BgpRouteEntry findBestBgpRoute(IpPrefix prefix) {
188 + BgpRouteEntry bestRoute = null;
189 +
190 + // Iterate across all BGP Sessions and select the best route
191 + for (BgpSession bgpSession : bgpSessionManager.getBgpSessions()) {
192 + BgpRouteEntry route = bgpSession.findBgpRoute(prefix);
193 + if (route == null) {
194 + continue;
195 + }
196 + if ((bestRoute == null) || route.isBetterThan(bestRoute)) {
197 + bestRoute = route;
198 + }
199 + }
200 + return bestRoute;
201 + }
202 +}
...@@ -20,7 +20,6 @@ import java.net.InetSocketAddress; ...@@ -20,7 +20,6 @@ import java.net.InetSocketAddress;
20 import java.net.SocketAddress; 20 import java.net.SocketAddress;
21 import java.util.Collection; 21 import java.util.Collection;
22 import java.util.Collections; 22 import java.util.Collections;
23 -import java.util.Map;
24 import java.util.concurrent.ConcurrentHashMap; 23 import java.util.concurrent.ConcurrentHashMap;
25 import java.util.concurrent.ConcurrentMap; 24 import java.util.concurrent.ConcurrentMap;
26 import java.util.concurrent.TimeUnit; 25 import java.util.concurrent.TimeUnit;
...@@ -34,6 +33,7 @@ import org.jboss.netty.util.HashedWheelTimer; ...@@ -34,6 +33,7 @@ import org.jboss.netty.util.HashedWheelTimer;
34 import org.jboss.netty.util.Timeout; 33 import org.jboss.netty.util.Timeout;
35 import org.jboss.netty.util.Timer; 34 import org.jboss.netty.util.Timer;
36 import org.jboss.netty.util.TimerTask; 35 import org.jboss.netty.util.TimerTask;
36 +import org.onlab.packet.IpPrefix;
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.onlab.packet.Ip6Prefix;
...@@ -120,44 +120,113 @@ public class BgpSession extends SimpleChannelHandler { ...@@ -120,44 +120,113 @@ public class BgpSession extends SimpleChannelHandler {
120 } 120 }
121 121
122 /** 122 /**
123 - * Gets the BGP RIB-IN IPv4 routing entries. 123 + * Gets the IPv4 BGP RIB-IN routing entries.
124 * 124 *
125 - * @return the BGP RIB-IN IPv4 routing entries 125 + * @return the IPv4 BGP RIB-IN routing entries
126 */ 126 */
127 - public Map<Ip4Prefix, BgpRouteEntry> bgpRibIn4() { 127 + public Collection<BgpRouteEntry> getBgpRibIn4() {
128 - return bgpRibIn4; 128 + return bgpRibIn4.values();
129 } 129 }
130 130
131 /** 131 /**
132 - * Gets the BGP RIB-IN IPv6 routing entries. 132 + * Gets the IPv6 BGP RIB-IN routing entries.
133 * 133 *
134 - * @return the BGP RIB-IN IPv6 routing entries 134 + * @return the IPv6 BGP RIB-IN routing entries
135 */ 135 */
136 - public Map<Ip6Prefix, BgpRouteEntry> bgpRibIn6() { 136 + public Collection<BgpRouteEntry> getBgpRibIn6() {
137 - return bgpRibIn6; 137 + return bgpRibIn6.values();
138 } 138 }
139 139
140 /** 140 /**
141 - * Finds a BGP IPv4 routing entry in the BGP RIB-IN. 141 + * Finds an IPv4 BGP routing entry for a prefix in the IPv4 BGP RIB-IN.
142 * 142 *
143 * @param prefix the IPv4 prefix of the route to search for 143 * @param prefix the IPv4 prefix of the route to search for
144 * @return the IPv4 BGP routing entry if found, otherwise null 144 * @return the IPv4 BGP routing entry if found, otherwise null
145 */ 145 */
146 - public BgpRouteEntry findBgpRouteEntry(Ip4Prefix prefix) { 146 + public BgpRouteEntry findBgpRoute(Ip4Prefix prefix) {
147 return bgpRibIn4.get(prefix); 147 return bgpRibIn4.get(prefix);
148 } 148 }
149 149
150 /** 150 /**
151 - * Finds a BGP IPv6 routing entry in the BGP RIB-IN. 151 + * Finds an IPv6 BGP routing entry for a prefix in the IPv6 BGP RIB-IN.
152 * 152 *
153 * @param prefix the IPv6 prefix of the route to search for 153 * @param prefix the IPv6 prefix of the route to search for
154 * @return the IPv6 BGP routing entry if found, otherwise null 154 * @return the IPv6 BGP routing entry if found, otherwise null
155 */ 155 */
156 - public BgpRouteEntry findBgpRouteEntry(Ip6Prefix prefix) { 156 + public BgpRouteEntry findBgpRoute(Ip6Prefix prefix) {
157 return bgpRibIn6.get(prefix); 157 return bgpRibIn6.get(prefix);
158 } 158 }
159 159
160 /** 160 /**
161 + * Finds a BGP routing entry for a prefix in the BGP RIB-IN. The prefix
162 + * can be either IPv4 or IPv6.
163 + *
164 + * @param prefix the IP prefix of the route to search for
165 + * @return the BGP routing entry if found, otherwise null
166 + */
167 + public BgpRouteEntry findBgpRoute(IpPrefix prefix) {
168 + if (prefix.version() == Ip4Address.VERSION) {
169 + // IPv4 prefix
170 + Ip4Prefix ip4Prefix = prefix.getIp4Prefix();
171 + return bgpRibIn4.get(ip4Prefix);
172 + }
173 +
174 + // IPv6 prefix
175 + Ip6Prefix ip6Prefix = prefix.getIp6Prefix();
176 + return bgpRibIn6.get(ip6Prefix);
177 + }
178 +
179 + /**
180 + * Adds a BGP route. The route can be either IPv4 or IPv6.
181 + *
182 + * @param bgpRouteEntry the BGP route entry to use
183 + */
184 + void addBgpRoute(BgpRouteEntry bgpRouteEntry) {
185 + if (bgpRouteEntry.version() == Ip4Address.VERSION) {
186 + // IPv4 route
187 + Ip4Prefix ip4Prefix = bgpRouteEntry.prefix().getIp4Prefix();
188 + bgpRibIn4.put(ip4Prefix, bgpRouteEntry);
189 + } else {
190 + // IPv6 route
191 + Ip6Prefix ip6Prefix = bgpRouteEntry.prefix().getIp6Prefix();
192 + bgpRibIn6.put(ip6Prefix, bgpRouteEntry);
193 + }
194 + }
195 +
196 + /**
197 + * Removes an IPv4 BGP route for a prefix.
198 + *
199 + * @param prefix the prefix to use
200 + * @return true if the route was found and removed, otherwise false
201 + */
202 + boolean removeBgpRoute(Ip4Prefix prefix) {
203 + return (bgpRibIn4.remove(prefix) != null);
204 + }
205 +
206 + /**
207 + * Removes an IPv6 BGP route for a prefix.
208 + *
209 + * @param prefix the prefix to use
210 + * @return true if the route was found and removed, otherwise false
211 + */
212 + boolean removeBgpRoute(Ip6Prefix prefix) {
213 + return (bgpRibIn6.remove(prefix) != null);
214 + }
215 +
216 + /**
217 + * Removes a BGP route for a prefix. The prefix can be either IPv4 or IPv6.
218 + *
219 + * @param prefix the prefix to use
220 + * @return true if the route was found and removed, otherwise false
221 + */
222 + boolean removeBgpRoute(IpPrefix prefix) {
223 + if (prefix.version() == Ip4Address.VERSION) {
224 + return (bgpRibIn4.remove(prefix.getIp4Prefix()) != null); // IPv4
225 + }
226 + return (bgpRibIn6.remove(prefix.getIp6Prefix()) != null); // IPv6
227 + }
228 +
229 + /**
161 * Gets the BGP session remote address. 230 * Gets the BGP session remote address.
162 * 231 *
163 * @return the BGP session remote address 232 * @return the BGP session remote address
...@@ -622,7 +691,7 @@ public class BgpSession extends SimpleChannelHandler { ...@@ -622,7 +691,7 @@ public class BgpSession extends SimpleChannelHandler {
622 bgpRibIn6 = new ConcurrentHashMap<>(); 691 bgpRibIn6 = new ConcurrentHashMap<>();
623 692
624 // Push the updates to the BGP Merged RIB 693 // Push the updates to the BGP Merged RIB
625 - BgpSessionManager.BgpRouteSelector bgpRouteSelector = 694 + BgpRouteSelector bgpRouteSelector =
626 bgpSessionManager.getBgpRouteSelector(); 695 bgpSessionManager.getBgpRouteSelector();
627 Collection<BgpRouteEntry> addedRoutes = Collections.emptyList(); 696 Collection<BgpRouteEntry> addedRoutes = Collections.emptyList();
628 bgpRouteSelector.routeUpdates(this, addedRoutes, deletedRoutes4); 697 bgpRouteSelector.routeUpdates(this, addedRoutes, deletedRoutes4);
......
...@@ -25,8 +25,8 @@ import org.jboss.netty.buffer.ChannelBuffer; ...@@ -25,8 +25,8 @@ 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;
29 import org.onlab.packet.Ip4Prefix; 28 import org.onlab.packet.Ip4Prefix;
29 +import org.onlab.packet.Ip6Address;
30 import org.onlab.packet.Ip6Prefix; 30 import org.onlab.packet.Ip6Prefix;
31 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; 32 import org.onosproject.sdnip.bgp.BgpConstants.Open.Capabilities.MultiprotocolExtensions;
...@@ -112,7 +112,7 @@ final class BgpUpdate { ...@@ -112,7 +112,7 @@ final class BgpUpdate {
112 for (Ip4Prefix prefix : withdrawnPrefixes) { 112 for (Ip4Prefix prefix : withdrawnPrefixes) {
113 log.debug("BGP RX UPDATE message WITHDRAWN from {}: {}", 113 log.debug("BGP RX UPDATE message WITHDRAWN from {}: {}",
114 bgpSession.getRemoteAddress(), prefix); 114 bgpSession.getRemoteAddress(), prefix);
115 - BgpRouteEntry bgpRouteEntry = bgpSession.bgpRibIn4().get(prefix); 115 + BgpRouteEntry bgpRouteEntry = bgpSession.findBgpRoute(prefix);
116 if (bgpRouteEntry != null) { 116 if (bgpRouteEntry != null) {
117 decodedBgpRoutes.deletedUnicastRoutes4.put(prefix, 117 decodedBgpRoutes.deletedUnicastRoutes4.put(prefix,
118 bgpRouteEntry); 118 bgpRouteEntry);
...@@ -134,35 +134,30 @@ final class BgpUpdate { ...@@ -134,35 +134,30 @@ final class BgpUpdate {
134 // 134 //
135 // Update the BGP RIB-IN 135 // Update the BGP RIB-IN
136 // 136 //
137 - Collection<BgpRouteEntry> bgpRoutes; 137 + for (Ip4Prefix ip4Prefix :
138 - // 138 + decodedBgpRoutes.deletedUnicastRoutes4.keySet()) {
139 - bgpRoutes = decodedBgpRoutes.deletedUnicastRoutes4.values(); 139 + bgpSession.removeBgpRoute(ip4Prefix);
140 - for (BgpRouteEntry bgpRouteEntry : bgpRoutes) {
141 - bgpSession.bgpRibIn4().remove(bgpRouteEntry.prefix());
142 } 140 }
143 // 141 //
144 - bgpRoutes = decodedBgpRoutes.addedUnicastRoutes4.values(); 142 + for (BgpRouteEntry bgpRouteEntry :
145 - for (BgpRouteEntry bgpRouteEntry : bgpRoutes) { 143 + decodedBgpRoutes.addedUnicastRoutes4.values()) {
146 - bgpSession.bgpRibIn4().put(bgpRouteEntry.prefix(), bgpRouteEntry); 144 + bgpSession.addBgpRoute(bgpRouteEntry);
147 } 145 }
148 // 146 //
149 - bgpRoutes = decodedBgpRoutes.deletedUnicastRoutes6.values(); 147 + for (Ip6Prefix ip6Prefix :
150 - for (BgpRouteEntry bgpRouteEntry : bgpRoutes) { 148 + decodedBgpRoutes.deletedUnicastRoutes6.keySet()) {
151 - bgpSession.bgpRibIn6().remove(bgpRouteEntry.prefix()); 149 + bgpSession.removeBgpRoute(ip6Prefix);
152 } 150 }
153 // 151 //
154 - bgpRoutes = decodedBgpRoutes.addedUnicastRoutes6.values(); 152 + for (BgpRouteEntry bgpRouteEntry :
155 - // TODO: fix/enable for IPv6 153 + decodedBgpRoutes.addedUnicastRoutes6.values()) {
156 - /* 154 + bgpSession.addBgpRoute(bgpRouteEntry);
157 - for (BgpRouteEntry bgpRouteEntry : bgpRoutes) {
158 - bgpSession.bgpRibIn6().put(bgpRouteEntry.prefix(), bgpRouteEntry);
159 } 155 }
160 - */
161 156
162 // 157 //
163 // Push the updates to the BGP Merged RIB 158 // Push the updates to the BGP Merged RIB
164 // 159 //
165 - BgpSessionManager.BgpRouteSelector bgpRouteSelector = 160 + BgpRouteSelector bgpRouteSelector =
166 bgpSession.getBgpSessionManager().getBgpRouteSelector(); 161 bgpSession.getBgpSessionManager().getBgpRouteSelector();
167 bgpRouteSelector.routeUpdates(bgpSession, 162 bgpRouteSelector.routeUpdates(bgpSession,
168 decodedBgpRoutes.addedUnicastRoutes4.values(), 163 decodedBgpRoutes.addedUnicastRoutes4.values(),
...@@ -408,7 +403,7 @@ final class BgpUpdate { ...@@ -408,7 +403,7 @@ final class BgpUpdate {
408 403
409 // The deleted IPv4 routes 404 // The deleted IPv4 routes
410 for (Ip4Prefix prefix : mpNlri.nlri4) { 405 for (Ip4Prefix prefix : mpNlri.nlri4) {
411 - bgpRouteEntry = bgpSession.bgpRibIn4().get(prefix); 406 + bgpRouteEntry = bgpSession.findBgpRoute(prefix);
412 if (bgpRouteEntry != null) { 407 if (bgpRouteEntry != null) {
413 decodedBgpRoutes.deletedUnicastRoutes4.put(prefix, 408 decodedBgpRoutes.deletedUnicastRoutes4.put(prefix,
414 bgpRouteEntry); 409 bgpRouteEntry);
...@@ -417,7 +412,7 @@ final class BgpUpdate { ...@@ -417,7 +412,7 @@ final class BgpUpdate {
417 412
418 // The deleted IPv6 routes 413 // The deleted IPv6 routes
419 for (Ip6Prefix prefix : mpNlri.nlri6) { 414 for (Ip6Prefix prefix : mpNlri.nlri6) {
420 - bgpRouteEntry = bgpSession.bgpRibIn6().get(prefix); 415 + bgpRouteEntry = bgpSession.findBgpRoute(prefix);
421 if (bgpRouteEntry != null) { 416 if (bgpRouteEntry != null) {
422 decodedBgpRoutes.deletedUnicastRoutes6.put(prefix, 417 decodedBgpRoutes.deletedUnicastRoutes6.put(prefix,
423 bgpRouteEntry); 418 bgpRouteEntry);
...@@ -456,8 +451,6 @@ final class BgpUpdate { ...@@ -456,8 +451,6 @@ final class BgpUpdate {
456 } 451 }
457 452
458 // The added IPv6 routes 453 // The added IPv6 routes
459 - // TODO: fix/enable for IPv6
460 - /*
461 for (Ip6Prefix prefix : mpNlri.nlri6) { 454 for (Ip6Prefix prefix : mpNlri.nlri6) {
462 bgpRouteEntry = 455 bgpRouteEntry =
463 new BgpRouteEntry(bgpSession, prefix, mpNlri.nextHop6, 456 new BgpRouteEntry(bgpSession, prefix, mpNlri.nextHop6,
...@@ -479,7 +472,6 @@ final class BgpUpdate { ...@@ -479,7 +472,6 @@ final class BgpUpdate {
479 decodedBgpRoutes.addedUnicastRoutes6.put(prefix, 472 decodedBgpRoutes.addedUnicastRoutes6.put(prefix,
480 bgpRouteEntry); 473 bgpRouteEntry);
481 } 474 }
482 - */
483 } 475 }
484 } 476 }
485 477
......
...@@ -46,7 +46,10 @@ public class BgpRoutesListCommand extends AbstractShellCommand { ...@@ -46,7 +46,10 @@ public class BgpRoutesListCommand extends AbstractShellCommand {
46 required = false, multiValued = false) 46 required = false, multiValued = false)
47 private String bgpNeighbor; 47 private String bgpNeighbor;
48 48
49 - private static final String FORMAT_SUMMARY = "Total BGP routes = %d"; 49 + private static final String FORMAT_SUMMARY_V4 =
50 + "Total BGP IPv4 routes = %d";
51 + private static final String FORMAT_SUMMARY_V6 =
52 + "Total BGP IPv6 routes = %d";
50 private static final String FORMAT_HEADER = 53 private static final String FORMAT_HEADER =
51 " Network Next Hop Origin LocalPref MED BGP-ID"; 54 " Network Next Hop Origin LocalPref MED BGP-ID";
52 private static final String FORMAT_ROUTE_LINE1 = 55 private static final String FORMAT_ROUTE_LINE1 =
...@@ -60,7 +63,7 @@ public class BgpRoutesListCommand extends AbstractShellCommand { ...@@ -60,7 +63,7 @@ public class BgpRoutesListCommand extends AbstractShellCommand {
60 63
61 // Print summary of the routes 64 // Print summary of the routes
62 if (routesSummary) { 65 if (routesSummary) {
63 - printSummary(service.getBgpRoutes()); 66 + printSummary(service.getBgpRoutes4(), service.getBgpRoutes6());
64 return; 67 return;
65 } 68 }
66 69
...@@ -81,43 +84,61 @@ public class BgpRoutesListCommand extends AbstractShellCommand { ...@@ -81,43 +84,61 @@ public class BgpRoutesListCommand extends AbstractShellCommand {
81 84
82 // Print the routes 85 // Print the routes
83 if (foundBgpSession != null) { 86 if (foundBgpSession != null) {
84 - printRoutes(foundBgpSession.bgpRibIn4().values()); 87 + printRoutes(foundBgpSession.getBgpRibIn4(),
85 - printRoutes(foundBgpSession.bgpRibIn6().values()); 88 + foundBgpSession.getBgpRibIn6());
86 } else { 89 } else {
87 - printRoutes(service.getBgpRoutes()); 90 + printRoutes(service.getBgpRoutes4(), service.getBgpRoutes6());
88 } 91 }
89 } 92 }
90 93
91 /** 94 /**
92 * Prints summary of the routes. 95 * Prints summary of the routes.
93 * 96 *
94 - * @param routes the routes 97 + * @param routes4 the IPv4 routes
98 + * @param routes6 the IPv6 routes
95 */ 99 */
96 - private void printSummary(Collection<BgpRouteEntry> routes) { 100 + private void printSummary(Collection<BgpRouteEntry> routes4,
101 + Collection<BgpRouteEntry> routes6) {
97 if (outputJson()) { 102 if (outputJson()) {
98 ObjectMapper mapper = new ObjectMapper(); 103 ObjectMapper mapper = new ObjectMapper();
99 ObjectNode result = mapper.createObjectNode(); 104 ObjectNode result = mapper.createObjectNode();
100 - result.put("totalRoutes", routes.size()); 105 + result.put("totalRoutes4", routes4.size());
106 + result.put("totalRoutes6", routes6.size());
101 print("%s", result); 107 print("%s", result);
102 } else { 108 } else {
103 - print(FORMAT_SUMMARY, routes.size()); 109 + print(FORMAT_SUMMARY_V4, routes4.size());
110 + print(FORMAT_SUMMARY_V6, routes6.size());
104 } 111 }
105 } 112 }
106 113
107 /** 114 /**
108 * Prints all routes. 115 * Prints all routes.
109 * 116 *
110 - * @param routes the routes to print 117 + * @param routes4 the IPv4 routes to print
118 + * @param routes6 the IPv6 routes to print
111 */ 119 */
112 - private void printRoutes(Collection<BgpRouteEntry> routes) { 120 + private void printRoutes(Collection<BgpRouteEntry> routes4,
121 + Collection<BgpRouteEntry> routes6) {
113 if (outputJson()) { 122 if (outputJson()) {
114 - print("%s", json(routes)); 123 + ObjectMapper mapper = new ObjectMapper();
124 + ObjectNode result = mapper.createObjectNode();
125 + result.put("routes4", json(routes4));
126 + result.put("routes6", json(routes6));
127 + print("%s", result);
115 } else { 128 } else {
129 + // The IPv4 routes
116 print(FORMAT_HEADER); 130 print(FORMAT_HEADER);
117 - for (BgpRouteEntry route : routes) { 131 + for (BgpRouteEntry route : routes4) {
132 + printRoute(route);
133 + }
134 + print(FORMAT_SUMMARY_V4, routes4.size());
135 + print(""); // Empty separator line
136 + // The IPv6 routes
137 + print(FORMAT_HEADER);
138 + for (BgpRouteEntry route : routes6) {
118 printRoute(route); 139 printRoute(route);
119 } 140 }
120 - print(FORMAT_SUMMARY, routes.size()); 141 + print(FORMAT_SUMMARY_V6, routes6.size());
121 } 142 }
122 } 143 }
123 144
......
...@@ -38,7 +38,10 @@ public class RoutesListCommand extends AbstractShellCommand { ...@@ -38,7 +38,10 @@ public class RoutesListCommand extends AbstractShellCommand {
38 required = false, multiValued = false) 38 required = false, multiValued = false)
39 private boolean routesSummary = false; 39 private boolean routesSummary = false;
40 40
41 - private static final String FORMAT_SUMMARY = "Total SDN-IP routes = %d"; 41 + private static final String FORMAT_SUMMARY_V4 =
42 + "Total SDN-IP IPv4 routes = %d";
43 + private static final String FORMAT_SUMMARY_V6 =
44 + "Total SDN-IP IPv6 routes = %d";
42 private static final String FORMAT_HEADER = 45 private static final String FORMAT_HEADER =
43 " Network Next Hop"; 46 " Network Next Hop";
44 private static final String FORMAT_ROUTE = 47 private static final String FORMAT_ROUTE =
...@@ -50,44 +53,62 @@ public class RoutesListCommand extends AbstractShellCommand { ...@@ -50,44 +53,62 @@ public class RoutesListCommand extends AbstractShellCommand {
50 53
51 // Print summary of the routes 54 // Print summary of the routes
52 if (routesSummary) { 55 if (routesSummary) {
53 - printSummary(service.getRoutes()); 56 + printSummary(service.getRoutes4(), service.getRoutes6());
54 return; 57 return;
55 } 58 }
56 59
57 // Print all routes 60 // Print all routes
58 - printRoutes(service.getRoutes()); 61 + printRoutes(service.getRoutes4(), service.getRoutes6());
59 } 62 }
60 63
61 /** 64 /**
62 * Prints summary of the routes. 65 * Prints summary of the routes.
63 * 66 *
64 - * @param routes the routes 67 + * @param routes4 the IPv4 routes
68 + * @param routes6 the IPv6 routes
65 */ 69 */
66 - private void printSummary(Collection<RouteEntry> routes) { 70 + private void printSummary(Collection<RouteEntry> routes4,
71 + Collection<RouteEntry> routes6) {
67 if (outputJson()) { 72 if (outputJson()) {
68 ObjectMapper mapper = new ObjectMapper(); 73 ObjectMapper mapper = new ObjectMapper();
69 ObjectNode result = mapper.createObjectNode(); 74 ObjectNode result = mapper.createObjectNode();
70 - result.put("totalRoutes", routes.size()); 75 + result.put("totalRoutes4", routes4.size());
76 + result.put("totalRoutes6", routes6.size());
71 print("%s", result); 77 print("%s", result);
72 } else { 78 } else {
73 - print(FORMAT_SUMMARY, routes.size()); 79 + print(FORMAT_SUMMARY_V4, routes4.size());
80 + print(FORMAT_SUMMARY_V6, routes6.size());
74 } 81 }
75 } 82 }
76 83
77 /** 84 /**
78 * Prints all routes. 85 * Prints all routes.
79 * 86 *
80 - * @param routes the routes to print 87 + * @param routes4 the IPv4 routes to print
88 + * @param routes6 the IPv6 routes to print
81 */ 89 */
82 - private void printRoutes(Collection<RouteEntry> routes) { 90 + private void printRoutes(Collection<RouteEntry> routes4,
91 + Collection<RouteEntry> routes6) {
83 if (outputJson()) { 92 if (outputJson()) {
84 - print("%s", json(routes)); 93 + ObjectMapper mapper = new ObjectMapper();
94 + ObjectNode result = mapper.createObjectNode();
95 + result.put("routes4", json(routes4));
96 + result.put("routes6", json(routes6));
97 + print("%s", result);
85 } else { 98 } else {
99 + // The IPv4 routes
86 print(FORMAT_HEADER); 100 print(FORMAT_HEADER);
87 - for (RouteEntry route : routes) { 101 + for (RouteEntry route : routes4) {
102 + printRoute(route);
103 + }
104 + print(FORMAT_SUMMARY_V4, routes4.size());
105 + print(""); // Empty separator line
106 + // The IPv6 routes
107 + print(FORMAT_HEADER);
108 + for (RouteEntry route : routes6) {
88 printRoute(route); 109 printRoute(route);
89 } 110 }
90 - print(FORMAT_SUMMARY, routes.size()); 111 + print(FORMAT_SUMMARY_V6, routes6.size());
91 } 112 }
92 } 113 }
93 114
......
...@@ -61,8 +61,8 @@ import org.onosproject.net.provider.ProviderId; ...@@ -61,8 +61,8 @@ import org.onosproject.net.provider.ProviderId;
61 import org.onosproject.sdnip.config.Interface; 61 import org.onosproject.sdnip.config.Interface;
62 import org.onlab.packet.Ethernet; 62 import org.onlab.packet.Ethernet;
63 import org.onlab.packet.IpAddress; 63 import org.onlab.packet.IpAddress;
64 -import org.onlab.packet.Ip4Address;
65 import org.onlab.packet.IpPrefix; 64 import org.onlab.packet.IpPrefix;
65 +import org.onlab.packet.Ip4Address;
66 import org.onlab.packet.Ip4Prefix; 66 import org.onlab.packet.Ip4Prefix;
67 import org.onlab.packet.MacAddress; 67 import org.onlab.packet.MacAddress;
68 import org.onlab.packet.VlanId; 68 import org.onlab.packet.VlanId;
...@@ -308,9 +308,9 @@ public class IntentSyncTest extends AbstractIntentTest { ...@@ -308,9 +308,9 @@ public class IntentSyncTest extends AbstractIntentTest {
308 routeEntry6); 308 routeEntry6);
309 ribTable.put(RouteEntry.createBinaryString(routeEntry7.prefix()), 309 ribTable.put(RouteEntry.createBinaryString(routeEntry7.prefix()),
310 routeEntry7); 310 routeEntry7);
311 - TestUtils.setField(router, "ribTable", ribTable); 311 + TestUtils.setField(router, "ribTable4", ribTable);
312 312
313 - ConcurrentHashMap<Ip4Prefix, MultiPointToSinglePointIntent> 313 + ConcurrentHashMap<IpPrefix, MultiPointToSinglePointIntent>
314 routeIntents = new ConcurrentHashMap<>(); 314 routeIntents = new ConcurrentHashMap<>();
315 routeIntents.put(routeEntry1.prefix(), intent1); 315 routeIntents.put(routeEntry1.prefix(), intent1);
316 routeIntents.put(routeEntry3.prefix(), intent3); 316 routeIntents.put(routeEntry3.prefix(), intent3);
...@@ -364,12 +364,12 @@ public class IntentSyncTest extends AbstractIntentTest { ...@@ -364,12 +364,12 @@ public class IntentSyncTest extends AbstractIntentTest {
364 intentSynchronizer.synchronizeIntents(); 364 intentSynchronizer.synchronizeIntents();
365 365
366 // Verify 366 // Verify
367 - assertEquals(router.getRoutes().size(), 6); 367 + assertEquals(router.getRoutes4().size(), 6);
368 - assertTrue(router.getRoutes().contains(routeEntry1)); 368 + assertTrue(router.getRoutes4().contains(routeEntry1));
369 - assertTrue(router.getRoutes().contains(routeEntry3)); 369 + assertTrue(router.getRoutes4().contains(routeEntry3));
370 - assertTrue(router.getRoutes().contains(routeEntry4Update)); 370 + assertTrue(router.getRoutes4().contains(routeEntry4Update));
371 - assertTrue(router.getRoutes().contains(routeEntry5)); 371 + assertTrue(router.getRoutes4().contains(routeEntry5));
372 - assertTrue(router.getRoutes().contains(routeEntry6)); 372 + assertTrue(router.getRoutes4().contains(routeEntry6));
373 373
374 assertEquals(intentSynchronizer.getRouteIntents().size(), 6); 374 assertEquals(intentSynchronizer.getRouteIntents().size(), 6);
375 assertTrue(intentSynchronizer.getRouteIntents().contains(intent1)); 375 assertTrue(intentSynchronizer.getRouteIntents().contains(intent1));
...@@ -390,12 +390,17 @@ public class IntentSyncTest extends AbstractIntentTest { ...@@ -390,12 +390,17 @@ public class IntentSyncTest extends AbstractIntentTest {
390 * @param egressPoint to which packets should be sent 390 * @param egressPoint to which packets should be sent
391 * @return the constructed MultiPointToSinglePointIntent 391 * @return the constructed MultiPointToSinglePointIntent
392 */ 392 */
393 - private MultiPointToSinglePointIntent intentBuilder(Ip4Prefix ipPrefix, 393 + private MultiPointToSinglePointIntent intentBuilder(IpPrefix ipPrefix,
394 String nextHopMacAddress, ConnectPoint egressPoint) { 394 String nextHopMacAddress, ConnectPoint egressPoint) {
395 395
396 TrafficSelector.Builder selectorBuilder = 396 TrafficSelector.Builder selectorBuilder =
397 DefaultTrafficSelector.builder(); 397 DefaultTrafficSelector.builder();
398 - selectorBuilder.matchEthType(Ethernet.TYPE_IPV4).matchIPDst(ipPrefix); 398 + if (ipPrefix.version() == Ip4Address.VERSION) {
399 + selectorBuilder.matchEthType(Ethernet.TYPE_IPV4); // IPv4
400 + } else {
401 + selectorBuilder.matchEthType(Ethernet.TYPE_IPV6); // IPv6
402 + }
403 + selectorBuilder.matchIPDst(ipPrefix);
399 404
400 TrafficTreatment.Builder treatmentBuilder = 405 TrafficTreatment.Builder treatmentBuilder =
401 DefaultTrafficTreatment.builder(); 406 DefaultTrafficTreatment.builder();
......
...@@ -63,8 +63,8 @@ import org.onosproject.sdnip.config.Interface; ...@@ -63,8 +63,8 @@ import org.onosproject.sdnip.config.Interface;
63 import org.onosproject.sdnip.config.SdnIpConfigurationService; 63 import org.onosproject.sdnip.config.SdnIpConfigurationService;
64 import org.onlab.packet.Ethernet; 64 import org.onlab.packet.Ethernet;
65 import org.onlab.packet.IpAddress; 65 import org.onlab.packet.IpAddress;
66 -import org.onlab.packet.Ip4Address;
67 import org.onlab.packet.IpPrefix; 66 import org.onlab.packet.IpPrefix;
67 +import org.onlab.packet.Ip4Address;
68 import org.onlab.packet.Ip4Prefix; 68 import org.onlab.packet.Ip4Prefix;
69 import org.onlab.packet.MacAddress; 69 import org.onlab.packet.MacAddress;
70 import org.onlab.packet.VlanId; 70 import org.onlab.packet.VlanId;
...@@ -239,8 +239,8 @@ public class RouterAsyncArpTest extends AbstractIntentTest { ...@@ -239,8 +239,8 @@ public class RouterAsyncArpTest extends AbstractIntentTest {
239 new HostEvent(HostEvent.Type.HOST_ADDED, host)); 239 new HostEvent(HostEvent.Type.HOST_ADDED, host));
240 240
241 // Verify 241 // Verify
242 - assertEquals(router.getRoutes().size(), 1); 242 + assertEquals(router.getRoutes4().size(), 1);
243 - assertTrue(router.getRoutes().contains(routeEntry)); 243 + assertTrue(router.getRoutes4().contains(routeEntry));
244 assertEquals(intentSynchronizer.getRouteIntents().size(), 1); 244 assertEquals(intentSynchronizer.getRouteIntents().size(), 1);
245 Intent firstIntent = 245 Intent firstIntent =
246 intentSynchronizer.getRouteIntents().iterator().next(); 246 intentSynchronizer.getRouteIntents().iterator().next();
...@@ -333,8 +333,8 @@ public class RouterAsyncArpTest extends AbstractIntentTest { ...@@ -333,8 +333,8 @@ public class RouterAsyncArpTest extends AbstractIntentTest {
333 new HostEvent(HostEvent.Type.HOST_ADDED, host)); 333 new HostEvent(HostEvent.Type.HOST_ADDED, host));
334 334
335 // Verify 335 // Verify
336 - assertEquals(router.getRoutes().size(), 1); 336 + assertEquals(router.getRoutes4().size(), 1);
337 - assertTrue(router.getRoutes().contains(routeEntryUpdate)); 337 + assertTrue(router.getRoutes4().contains(routeEntryUpdate));
338 assertEquals(intentSynchronizer.getRouteIntents().size(), 1); 338 assertEquals(intentSynchronizer.getRouteIntents().size(), 1);
339 Intent firstIntent = 339 Intent firstIntent =
340 intentSynchronizer.getRouteIntents().iterator().next(); 340 intentSynchronizer.getRouteIntents().iterator().next();
...@@ -380,7 +380,7 @@ public class RouterAsyncArpTest extends AbstractIntentTest { ...@@ -380,7 +380,7 @@ public class RouterAsyncArpTest extends AbstractIntentTest {
380 router.processRouteUpdates(Collections.<RouteUpdate>singletonList(routeUpdate)); 380 router.processRouteUpdates(Collections.<RouteUpdate>singletonList(routeUpdate));
381 381
382 // Verify 382 // Verify
383 - assertEquals(router.getRoutes().size(), 0); 383 + assertEquals(router.getRoutes4().size(), 0);
384 assertEquals(intentSynchronizer.getRouteIntents().size(), 0); 384 assertEquals(intentSynchronizer.getRouteIntents().size(), 0);
385 verify(intentService); 385 verify(intentService);
386 } 386 }
...@@ -424,7 +424,7 @@ public class RouterAsyncArpTest extends AbstractIntentTest { ...@@ -424,7 +424,7 @@ public class RouterAsyncArpTest extends AbstractIntentTest {
424 new DefaultByteArrayNodeFactory()); 424 new DefaultByteArrayNodeFactory());
425 ribTable.put(RouteEntry.createBinaryString(routeEntry.prefix()), 425 ribTable.put(RouteEntry.createBinaryString(routeEntry.prefix()),
426 routeEntry); 426 routeEntry);
427 - TestUtils.setField(router, "ribTable", ribTable); 427 + TestUtils.setField(router, "ribTable4", ribTable);
428 } 428 }
429 429
430 /** 430 /**
...@@ -436,7 +436,7 @@ public class RouterAsyncArpTest extends AbstractIntentTest { ...@@ -436,7 +436,7 @@ public class RouterAsyncArpTest extends AbstractIntentTest {
436 MultiPointToSinglePointIntent intent) 436 MultiPointToSinglePointIntent intent)
437 throws TestUtilsException { 437 throws TestUtilsException {
438 438
439 - ConcurrentHashMap<Ip4Prefix, MultiPointToSinglePointIntent> 439 + ConcurrentHashMap<IpPrefix, MultiPointToSinglePointIntent>
440 routeIntents = new ConcurrentHashMap<>(); 440 routeIntents = new ConcurrentHashMap<>();
441 routeIntents.put(routeEntry.prefix(), intent); 441 routeIntents.put(routeEntry.prefix(), intent);
442 TestUtils.setField(intentSynchronizer, "routeIntents", routeIntents); 442 TestUtils.setField(intentSynchronizer, "routeIntents", routeIntents);
......
...@@ -36,10 +36,10 @@ import org.junit.Test; ...@@ -36,10 +36,10 @@ import org.junit.Test;
36 import org.onlab.junit.TestUtils; 36 import org.onlab.junit.TestUtils;
37 import org.onlab.junit.TestUtils.TestUtilsException; 37 import org.onlab.junit.TestUtils.TestUtilsException;
38 import org.onlab.packet.Ethernet; 38 import org.onlab.packet.Ethernet;
39 -import org.onlab.packet.Ip4Address;
40 -import org.onlab.packet.Ip4Prefix;
41 import org.onlab.packet.IpAddress; 39 import org.onlab.packet.IpAddress;
42 import org.onlab.packet.IpPrefix; 40 import org.onlab.packet.IpPrefix;
41 +import org.onlab.packet.Ip4Address;
42 +import org.onlab.packet.Ip4Prefix;
43 import org.onlab.packet.MacAddress; 43 import org.onlab.packet.MacAddress;
44 import org.onlab.packet.VlanId; 44 import org.onlab.packet.VlanId;
45 import org.onosproject.core.ApplicationId; 45 import org.onosproject.core.ApplicationId;
...@@ -278,8 +278,8 @@ public class RouterTest extends AbstractIntentTest { ...@@ -278,8 +278,8 @@ public class RouterTest extends AbstractIntentTest {
278 router.processRouteUpdates(Collections.<RouteUpdate>singletonList(routeUpdate)); 278 router.processRouteUpdates(Collections.<RouteUpdate>singletonList(routeUpdate));
279 279
280 // Verify 280 // Verify
281 - assertEquals(router.getRoutes().size(), 1); 281 + assertEquals(router.getRoutes4().size(), 1);
282 - assertTrue(router.getRoutes().contains(routeEntry)); 282 + assertTrue(router.getRoutes4().contains(routeEntry));
283 assertEquals(intentSynchronizer.getRouteIntents().size(), 1); 283 assertEquals(intentSynchronizer.getRouteIntents().size(), 1);
284 Intent firstIntent = 284 Intent firstIntent =
285 intentSynchronizer.getRouteIntents().iterator().next(); 285 intentSynchronizer.getRouteIntents().iterator().next();
...@@ -349,8 +349,8 @@ public class RouterTest extends AbstractIntentTest { ...@@ -349,8 +349,8 @@ public class RouterTest extends AbstractIntentTest {
349 router.processRouteUpdates(Collections.<RouteUpdate>singletonList(routeUpdate)); 349 router.processRouteUpdates(Collections.<RouteUpdate>singletonList(routeUpdate));
350 350
351 // Verify 351 // Verify
352 - assertEquals(router.getRoutes().size(), 1); 352 + assertEquals(router.getRoutes4().size(), 1);
353 - assertTrue(router.getRoutes().contains(routeEntryUpdate)); 353 + assertTrue(router.getRoutes4().contains(routeEntryUpdate));
354 assertEquals(intentSynchronizer.getRouteIntents().size(), 1); 354 assertEquals(intentSynchronizer.getRouteIntents().size(), 1);
355 Intent firstIntent = 355 Intent firstIntent =
356 intentSynchronizer.getRouteIntents().iterator().next(); 356 intentSynchronizer.getRouteIntents().iterator().next();
...@@ -393,7 +393,7 @@ public class RouterTest extends AbstractIntentTest { ...@@ -393,7 +393,7 @@ public class RouterTest extends AbstractIntentTest {
393 router.processRouteUpdates(Collections.<RouteUpdate>singletonList(routeUpdate)); 393 router.processRouteUpdates(Collections.<RouteUpdate>singletonList(routeUpdate));
394 394
395 // Verify 395 // Verify
396 - assertEquals(router.getRoutes().size(), 0); 396 + assertEquals(router.getRoutes4().size(), 0);
397 assertEquals(intentSynchronizer.getRouteIntents().size(), 0); 397 assertEquals(intentSynchronizer.getRouteIntents().size(), 0);
398 verify(intentService); 398 verify(intentService);
399 } 399 }
...@@ -422,8 +422,8 @@ public class RouterTest extends AbstractIntentTest { ...@@ -422,8 +422,8 @@ public class RouterTest extends AbstractIntentTest {
422 router.processRouteUpdates(Collections.<RouteUpdate>singletonList(routeUpdate)); 422 router.processRouteUpdates(Collections.<RouteUpdate>singletonList(routeUpdate));
423 423
424 // Verify 424 // Verify
425 - assertEquals(router.getRoutes().size(), 1); 425 + assertEquals(router.getRoutes4().size(), 1);
426 - assertTrue(router.getRoutes().contains(routeEntry)); 426 + assertTrue(router.getRoutes4().contains(routeEntry));
427 assertEquals(intentSynchronizer.getRouteIntents().size(), 0); 427 assertEquals(intentSynchronizer.getRouteIntents().size(), 0);
428 verify(intentService); 428 verify(intentService);
429 } 429 }
......
...@@ -59,10 +59,10 @@ import org.onosproject.sdnip.config.BgpPeer; ...@@ -59,10 +59,10 @@ import org.onosproject.sdnip.config.BgpPeer;
59 import org.onosproject.sdnip.config.Interface; 59 import org.onosproject.sdnip.config.Interface;
60 import org.onosproject.sdnip.config.SdnIpConfigurationService; 60 import org.onosproject.sdnip.config.SdnIpConfigurationService;
61 import org.onlab.packet.Ethernet; 61 import org.onlab.packet.Ethernet;
62 -import org.onlab.packet.Ip4Address;
63 -import org.onlab.packet.Ip4Prefix;
64 import org.onlab.packet.IpAddress; 62 import org.onlab.packet.IpAddress;
65 import org.onlab.packet.IpPrefix; 63 import org.onlab.packet.IpPrefix;
64 +import org.onlab.packet.Ip4Address;
65 +import org.onlab.packet.Ip4Prefix;
66 import org.onlab.packet.MacAddress; 66 import org.onlab.packet.MacAddress;
67 67
68 import com.google.common.collect.Sets; 68 import com.google.common.collect.Sets;
...@@ -226,7 +226,7 @@ public class SdnIpTest extends AbstractIntentTest { ...@@ -226,7 +226,7 @@ public class SdnIpTest extends AbstractIntentTest {
226 reset(intentService); 226 reset(intentService);
227 227
228 for (RouteUpdate update : routeUpdates) { 228 for (RouteUpdate update : routeUpdates) {
229 - Ip4Address nextHopAddress = update.routeEntry().nextHop(); 229 + IpAddress nextHopAddress = update.routeEntry().nextHop();
230 230
231 // Find out the egress ConnectPoint 231 // Find out the egress ConnectPoint
232 ConnectPoint egressConnectPoint = getConnectPoint(nextHopAddress); 232 ConnectPoint egressConnectPoint = getConnectPoint(nextHopAddress);
...@@ -255,7 +255,7 @@ public class SdnIpTest extends AbstractIntentTest { ...@@ -255,7 +255,7 @@ public class SdnIpTest extends AbstractIntentTest {
255 255
256 latch.await(5000, TimeUnit.MILLISECONDS); 256 latch.await(5000, TimeUnit.MILLISECONDS);
257 257
258 - assertEquals(router.getRoutes().size(), numRoutes); 258 + assertEquals(router.getRoutes4().size(), numRoutes);
259 assertEquals(intentSynchronizer.getRouteIntents().size(), 259 assertEquals(intentSynchronizer.getRouteIntents().size(),
260 numRoutes); 260 numRoutes);
261 261
...@@ -286,7 +286,7 @@ public class SdnIpTest extends AbstractIntentTest { ...@@ -286,7 +286,7 @@ public class SdnIpTest extends AbstractIntentTest {
286 reset(intentService); 286 reset(intentService);
287 287
288 for (RouteUpdate update : routeUpdates) { 288 for (RouteUpdate update : routeUpdates) {
289 - Ip4Address nextHopAddress = update.routeEntry().nextHop(); 289 + IpAddress nextHopAddress = update.routeEntry().nextHop();
290 290
291 // Find out the egress ConnectPoint 291 // Find out the egress ConnectPoint
292 ConnectPoint egressConnectPoint = getConnectPoint(nextHopAddress); 292 ConnectPoint egressConnectPoint = getConnectPoint(nextHopAddress);
...@@ -333,7 +333,7 @@ public class SdnIpTest extends AbstractIntentTest { ...@@ -333,7 +333,7 @@ public class SdnIpTest extends AbstractIntentTest {
333 333
334 deleteCount.await(5000, TimeUnit.MILLISECONDS); 334 deleteCount.await(5000, TimeUnit.MILLISECONDS);
335 335
336 - assertEquals(0, router.getRoutes().size()); 336 + assertEquals(0, router.getRoutes4().size());
337 assertEquals(0, intentSynchronizer.getRouteIntents().size()); 337 assertEquals(0, intentSynchronizer.getRouteIntents().size());
338 verify(intentService); 338 verify(intentService);
339 } 339 }
......
...@@ -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.bgpRibIn4().values(); 306 + Collection<BgpRouteEntry> bgpRibIn = bgpSession.getBgpRibIn4();
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.bgpRibIn4().values(); 314 + bgpRibIn = bgpSession.getBgpRibIn4();
315 } 315 }
316 316
317 return bgpRibIn; 317 return bgpRibIn;
...@@ -329,7 +329,8 @@ public class BgpSessionManagerTest { ...@@ -329,7 +329,8 @@ public class BgpSessionManagerTest {
329 */ 329 */
330 private Collection<BgpRouteEntry> waitForBgpRoutes(long expectedRoutes) 330 private Collection<BgpRouteEntry> waitForBgpRoutes(long expectedRoutes)
331 throws InterruptedException { 331 throws InterruptedException {
332 - Collection<BgpRouteEntry> bgpRoutes = bgpSessionManager.getBgpRoutes(); 332 + Collection<BgpRouteEntry> bgpRoutes =
333 + bgpSessionManager.getBgpRoutes4();
333 334
334 final int maxChecks = 500; // Max wait of 5 seconds 335 final int maxChecks = 500; // Max wait of 5 seconds
335 for (int i = 0; i < maxChecks; i++) { 336 for (int i = 0; i < maxChecks; i++) {
...@@ -337,7 +338,7 @@ public class BgpSessionManagerTest { ...@@ -337,7 +338,7 @@ public class BgpSessionManagerTest {
337 break; 338 break;
338 } 339 }
339 Thread.sleep(10); 340 Thread.sleep(10);
340 - bgpRoutes = bgpSessionManager.getBgpRoutes(); 341 + bgpRoutes = bgpSessionManager.getBgpRoutes4();
341 } 342 }
342 343
343 return bgpRoutes; 344 return bgpRoutes;
......