Refactor the SDN-IP BGP code so the BGP routes are withdrawn if
the onos-app-sdnip feature is uninstalled.
Change-Id: I49c40ee172a06d5809da69f736648fa639745975
diff --git a/apps/sdnip/src/main/java/org/onlab/onos/sdnip/Router.java b/apps/sdnip/src/main/java/org/onlab/onos/sdnip/Router.java
index 3ae5b82..6316b59 100644
--- a/apps/sdnip/src/main/java/org/onlab/onos/sdnip/Router.java
+++ b/apps/sdnip/src/main/java/org/onlab/onos/sdnip/Router.java
@@ -167,8 +167,33 @@
* Shuts the router down.
*/
public void shutdown() {
+ // Stop all threads
bgpUpdatesExecutor.shutdownNow();
bgpIntentsSynchronizerExecutor.shutdownNow();
+
+ synchronized (this) {
+ // Cleanup all local state
+ bgpRoutes = new ConcurrentInvertedRadixTree<>(
+ new DefaultByteArrayNodeFactory());
+ routeUpdates.clear();
+ routesWaitingOnArp.clear();
+ pushedRouteIntents.clear();
+
+ //
+ // Withdraw all SDN-IP intents
+ //
+ if (!isElectedLeader) {
+ return; // Nothing to do: not the leader anymore
+ }
+ log.debug("Withdrawing all SDN-IP Route Intents...");
+ for (Intent intent : intentService.getIntents()) {
+ if (!(intent instanceof MultiPointToSinglePointIntent)
+ || !intent.appId().equals(appId)) {
+ continue;
+ }
+ intentService.withdraw(intent);
+ }
+ }
}
//@Override TODO hook this up to something
diff --git a/apps/sdnip/src/main/java/org/onlab/onos/sdnip/bgp/BgpSession.java b/apps/sdnip/src/main/java/org/onlab/onos/sdnip/bgp/BgpSession.java
index e0a710a..8b620a9 100644
--- a/apps/sdnip/src/main/java/org/onlab/onos/sdnip/bgp/BgpSession.java
+++ b/apps/sdnip/src/main/java/org/onlab/onos/sdnip/bgp/BgpSession.java
@@ -237,6 +237,18 @@
}
@Override
+ public void channelOpen(ChannelHandlerContext ctx,
+ ChannelStateEvent channelEvent) {
+ bgpSessionManager.addSessionChannel(channelEvent.getChannel());
+ }
+
+ @Override
+ public void channelClosed(ChannelHandlerContext ctx,
+ ChannelStateEvent channelEvent) {
+ bgpSessionManager.removeSessionChannel(channelEvent.getChannel());
+ }
+
+ @Override
public void channelConnected(ChannelHandlerContext ctx,
ChannelStateEvent channelEvent) {
localAddress = ctx.getChannel().getLocalAddress();
diff --git a/apps/sdnip/src/main/java/org/onlab/onos/sdnip/bgp/BgpSessionManager.java b/apps/sdnip/src/main/java/org/onlab/onos/sdnip/bgp/BgpSessionManager.java
index 38fad6c..b6dfd34 100644
--- a/apps/sdnip/src/main/java/org/onlab/onos/sdnip/bgp/BgpSessionManager.java
+++ b/apps/sdnip/src/main/java/org/onlab/onos/sdnip/bgp/BgpSessionManager.java
@@ -32,6 +32,8 @@
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelPipelineFactory;
import org.jboss.netty.channel.Channels;
+import org.jboss.netty.channel.group.ChannelGroup;
+import org.jboss.netty.channel.group.DefaultChannelGroup;
import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory;
import org.onlab.onos.sdnip.RouteListener;
import org.onlab.onos.sdnip.RouteUpdate;
@@ -46,7 +48,10 @@
public class BgpSessionManager {
private static final Logger log =
LoggerFactory.getLogger(BgpSessionManager.class);
+ boolean isShutdown = true;
private Channel serverChannel; // Listener for incoming BGP connections
+ private ServerBootstrap serverBootstrap;
+ private ChannelGroup allChannels = new DefaultChannelGroup();
private ConcurrentMap<SocketAddress, BgpSession> bgpSessions =
new ConcurrentHashMap<>();
private Ip4Address myBgpId; // Same BGP ID for all peers
@@ -85,6 +90,24 @@
}
/**
+ * Adds the channel for a BGP session.
+ *
+ * @param channel the channel to add
+ */
+ void addSessionChannel(Channel channel) {
+ allChannels.add(channel);
+ }
+
+ /**
+ * Removes the channel for a BGP session.
+ *
+ * @param channel the channel to remove
+ */
+ void removeSessionChannel(Channel channel) {
+ allChannels.remove(channel);
+ }
+
+ /**
* Processes the connection from a BGP peer.
*
* @param bgpSession the BGP session for the peer
@@ -160,6 +183,7 @@
*/
public void startUp(int listenPortNumber) {
log.debug("BGP Session Manager startUp()");
+ isShutdown = false;
ChannelFactory channelFactory =
new NioServerSocketChannelFactory(Executors.newCachedThreadPool(),
@@ -183,13 +207,14 @@
InetSocketAddress listenAddress =
new InetSocketAddress(listenPortNumber);
- ServerBootstrap serverBootstrap = new ServerBootstrap(channelFactory);
+ serverBootstrap = new ServerBootstrap(channelFactory);
// serverBootstrap.setOptions("reuseAddr", true);
serverBootstrap.setOption("child.keepAlive", true);
serverBootstrap.setOption("child.tcpNoDelay", true);
serverBootstrap.setPipelineFactory(pipelineFactory);
try {
serverChannel = serverBootstrap.bind(listenAddress);
+ allChannels.add(serverChannel);
} catch (ChannelException e) {
log.debug("Exception binding to BGP port {}: ",
listenAddress.getPort(), e);
@@ -200,10 +225,9 @@
* Shuts down the BGP Session Manager operation.
*/
public void shutDown() {
- // TODO: Complete the implementation: remove routes, etc.
- if (serverChannel != null) {
- serverChannel.close();
- }
+ isShutdown = true;
+ allChannels.close().awaitUninterruptibly();
+ serverBootstrap.releaseExternalResources();
}
/**
@@ -223,6 +247,9 @@
synchronized void routeUpdates(BgpSession bgpSession,
Collection<BgpRouteEntry> addedBgpRouteEntries,
Collection<BgpRouteEntry> deletedBgpRouteEntries) {
+ if (isShutdown) {
+ return; // Ignore any leftover updates if shutdown
+ }
// Process the deleted route entries
for (BgpRouteEntry bgpRouteEntry : deletedBgpRouteEntries) {
processDeletedRoute(bgpSession, bgpRouteEntry);