blob: 80f8e9edf289d606906cc0b6ebdade3e3dc2dce6 [file] [log] [blame]
Thomas Vachuska781d18b2014-10-27 10:31:25 -07001/*
Thomas Vachuska4f1a60c2014-10-28 13:39:07 -07002 * Copyright 2014 Open Networking Laboratory
Thomas Vachuska781d18b2014-10-27 10:31:25 -07003 *
Thomas Vachuska4f1a60c2014-10-28 13:39:07 -07004 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
Thomas Vachuska781d18b2014-10-27 10:31:25 -07007 *
Thomas Vachuska4f1a60c2014-10-28 13:39:07 -07008 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
Thomas Vachuska781d18b2014-10-27 10:31:25 -070015 */
Jonathan Hart039d2b12014-10-10 09:33:04 -070016package org.onlab.onos.sdnip;
17
18import static org.slf4j.LoggerFactory.getLogger;
19
Jonathan Hart0b04bed2014-10-16 16:39:19 -070020import java.util.Collection;
Pavlin Radoslavov8b752442014-11-18 14:34:37 -080021import java.util.concurrent.ExecutorService;
22import java.util.concurrent.Executors;
Jonathan Hart0b04bed2014-10-16 16:39:19 -070023
Jonathan Hart039d2b12014-10-10 09:33:04 -070024import org.apache.felix.scr.annotations.Activate;
25import org.apache.felix.scr.annotations.Component;
26import org.apache.felix.scr.annotations.Deactivate;
Jonathan Hartdc711bd2014-10-15 11:24:23 -070027import org.apache.felix.scr.annotations.Reference;
28import org.apache.felix.scr.annotations.ReferenceCardinality;
Jonathan Hart0b04bed2014-10-16 16:39:19 -070029import org.apache.felix.scr.annotations.Service;
Thomas Vachuskae0f804a2014-10-27 23:40:48 -070030import org.onlab.onos.core.ApplicationId;
31import org.onlab.onos.core.CoreService;
Jonathan Hartdc711bd2014-10-15 11:24:23 -070032import org.onlab.onos.net.host.HostService;
33import org.onlab.onos.net.intent.IntentService;
Jonathan Hart0b04bed2014-10-16 16:39:19 -070034import org.onlab.onos.sdnip.bgp.BgpRouteEntry;
Pavlin Radoslavov0c84da82014-11-07 17:53:34 -080035import org.onlab.onos.sdnip.bgp.BgpSession;
Jonathan Hartab63aac2014-10-16 08:52:55 -070036import org.onlab.onos.sdnip.bgp.BgpSessionManager;
Jonathan Hartbac07a02014-10-13 21:29:54 -070037import org.onlab.onos.sdnip.config.SdnIpConfigReader;
Pavlin Radoslavov8b752442014-11-18 14:34:37 -080038import org.onlab.onos.store.service.Lock;
39import org.onlab.onos.store.service.LockService;
Jonathan Hart039d2b12014-10-10 09:33:04 -070040import org.slf4j.Logger;
41
Pavlin Radoslavov8b752442014-11-18 14:34:37 -080042import com.google.common.util.concurrent.ThreadFactoryBuilder;
43
Jonathan Hart039d2b12014-10-10 09:33:04 -070044/**
Jonathan Hart0b04bed2014-10-16 16:39:19 -070045 * Component for the SDN-IP peering application.
Jonathan Hart039d2b12014-10-10 09:33:04 -070046 */
47@Component(immediate = true)
Jonathan Hart0b04bed2014-10-16 16:39:19 -070048@Service
49public class SdnIp implements SdnIpService {
Jonathan Hart039d2b12014-10-10 09:33:04 -070050
Jonathan Hart31582d12014-10-22 13:52:41 -070051 private static final String SDN_IP_APP = "org.onlab.onos.sdnip";
Pavlin Radoslavov8b752442014-11-18 14:34:37 -080052 // NOTE: Must be 5s for now
53 private static final int LEASE_DURATION_MS = 5 * 1000;
54 private static final int LEASE_EXTEND_RETRY_MAX = 3;
Thomas Vachuskab97cf282014-10-20 23:31:12 -070055
Jonathan Hart039d2b12014-10-10 09:33:04 -070056 private final Logger log = getLogger(getClass());
57
Jonathan Hartdc711bd2014-10-15 11:24:23 -070058 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Thomas Vachuskab97cf282014-10-20 23:31:12 -070059 protected CoreService coreService;
60
61 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Jonathan Hartdc711bd2014-10-15 11:24:23 -070062 protected IntentService intentService;
63
64 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
65 protected HostService hostService;
66
Pavlin Radoslavov8b752442014-11-18 14:34:37 -080067 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
68 protected LockService lockService;
69
Pavlin Radoslavova071b1e2014-11-17 13:37:57 -080070 private IntentSynchronizer intentSynchronizer;
Jonathan Hartbac07a02014-10-13 21:29:54 -070071 private SdnIpConfigReader config;
Jonathan Hartce430a42014-10-16 20:44:29 -070072 private PeerConnectivityManager peerConnectivity;
Jonathan Hart335ef462014-10-16 08:20:46 -070073 private Router router;
Jonathan Hartab63aac2014-10-16 08:52:55 -070074 private BgpSessionManager bgpSessionManager;
Jonathan Hartbac07a02014-10-13 21:29:54 -070075
Pavlin Radoslavov8b752442014-11-18 14:34:37 -080076 private ExecutorService leaderElectionExecutor;
77 private Lock leaderLock;
78 private volatile boolean isShutdown = true;
79
Jonathan Hart039d2b12014-10-10 09:33:04 -070080 @Activate
81 protected void activate() {
Pavlin Radoslavov8b752442014-11-18 14:34:37 -080082 log.info("SDN-IP started");
83 isShutdown = false;
Jonathan Hartbac07a02014-10-13 21:29:54 -070084
Pavlin Radoslavova071b1e2014-11-17 13:37:57 -080085 ApplicationId appId = coreService.registerApplication(SDN_IP_APP);
Jonathan Hartbac07a02014-10-13 21:29:54 -070086 config = new SdnIpConfigReader();
87 config.init();
Jonathan Hartdc711bd2014-10-15 11:24:23 -070088
Pavlin Radoslavova071b1e2014-11-17 13:37:57 -080089 InterfaceService interfaceService =
90 new HostToInterfaceAdaptor(hostService);
Jonathan Hartdc711bd2014-10-15 11:24:23 -070091
Pavlin Radoslavova071b1e2014-11-17 13:37:57 -080092 intentSynchronizer = new IntentSynchronizer(appId, intentService);
93 intentSynchronizer.start();
Jonathan Hart31582d12014-10-22 13:52:41 -070094
95 peerConnectivity = new PeerConnectivityManager(appId, config,
96 interfaceService, intentService);
Jonathan Hartdc711bd2014-10-15 11:24:23 -070097 peerConnectivity.start();
98
Pavlin Radoslavova071b1e2014-11-17 13:37:57 -080099 router = new Router(appId, intentSynchronizer, hostService, config,
100 interfaceService);
Jonathan Hart335ef462014-10-16 08:20:46 -0700101 router.start();
102
Pavlin Radoslavov8b752442014-11-18 14:34:37 -0800103 leaderLock = lockService.create(SDN_IP_APP + "/sdnIpLeaderLock");
104 leaderElectionExecutor = Executors.newSingleThreadExecutor(
105 new ThreadFactoryBuilder()
106 .setNameFormat("sdnip-leader-election-%d").build());
107 leaderElectionExecutor.execute(new Runnable() {
108 @Override
109 public void run() {
110 doLeaderElectionThread();
111 }
112 });
113
Pavlin Radoslavova071b1e2014-11-17 13:37:57 -0800114 // Manually set the instance as the leader to allow testing
Jonathan Hartec2df012014-10-23 16:40:24 -0700115 // TODO change this when we get a leader election
Pavlin Radoslavov8b752442014-11-18 14:34:37 -0800116 // intentSynchronizer.leaderChanged(true);
Jonathan Hartec2df012014-10-23 16:40:24 -0700117
Jonathan Hartab63aac2014-10-16 08:52:55 -0700118 bgpSessionManager = new BgpSessionManager(router);
Pavlin Radoslavova071b1e2014-11-17 13:37:57 -0800119 // TODO: the local BGP listen port number should be configurable
120 bgpSessionManager.start(2000);
Jonathan Hartab63aac2014-10-16 08:52:55 -0700121
Jonathan Hart335ef462014-10-16 08:20:46 -0700122 // TODO need to disable link discovery on external ports
Jonathan Hart039d2b12014-10-10 09:33:04 -0700123 }
124
125 @Deactivate
126 protected void deactivate() {
Pavlin Radoslavov8b752442014-11-18 14:34:37 -0800127 isShutdown = true;
128
Pavlin Radoslavova071b1e2014-11-17 13:37:57 -0800129 bgpSessionManager.stop();
130 router.stop();
131 peerConnectivity.stop();
132 intentSynchronizer.stop();
Jonathan Hart739c8352014-10-29 17:49:26 -0700133
Pavlin Radoslavov8b752442014-11-18 14:34:37 -0800134 // Stop the thread(s)
135 leaderElectionExecutor.shutdownNow();
136
Jonathan Hart039d2b12014-10-10 09:33:04 -0700137 log.info("Stopped");
138 }
Jonathan Hart0b04bed2014-10-16 16:39:19 -0700139
140 @Override
Pavlin Radoslavov0c84da82014-11-07 17:53:34 -0800141 public Collection<BgpSession> getBgpSessions() {
142 return bgpSessionManager.getBgpSessions();
143 }
144
145 @Override
Jonathan Hart0b04bed2014-10-16 16:39:19 -0700146 public Collection<BgpRouteEntry> getBgpRoutes() {
147 return bgpSessionManager.getBgpRoutes();
148 }
149
150 @Override
151 public Collection<RouteEntry> getRoutes() {
152 return router.getRoutes();
153 }
Jonathan Hartce430a42014-10-16 20:44:29 -0700154
Jonathan Hartec2df012014-10-23 16:40:24 -0700155 @Override
156 public void modifyPrimary(boolean isPrimary) {
Pavlin Radoslavova071b1e2014-11-17 13:37:57 -0800157 intentSynchronizer.leaderChanged(isPrimary);
Jonathan Hartec2df012014-10-23 16:40:24 -0700158 }
159
Jonathan Hartce430a42014-10-16 20:44:29 -0700160 static String dpidToUri(String dpid) {
161 return "of:" + dpid.replace(":", "");
162 }
Pavlin Radoslavov8b752442014-11-18 14:34:37 -0800163
164 /**
165 * Performs the leader election.
166 */
167 private void doLeaderElectionThread() {
168
169 //
170 // Try to acquire the lock and keep extending it until the instance
171 // is shutdown.
172 //
173 while (!isShutdown) {
174 log.debug("SDN-IP Leader Election begin");
175
176 // Block until it becomes the leader
177 leaderLock.lock(LEASE_DURATION_MS);
178
179 // This instance is the leader
180 log.info("SDN-IP Leader Elected");
181 intentSynchronizer.leaderChanged(true);
182
183 // Keep extending the expiration until shutdown
184 int extensionFailedCountdown = LEASE_EXTEND_RETRY_MAX - 1;
185
186 //
187 // Keep periodically extending the lock expiration.
188 // If there are multiple back-to-back failures to extend (with
189 // extra sleep time between retrials), then release the lock.
190 //
191 while (!isShutdown) {
192 try {
193 Thread.sleep(LEASE_DURATION_MS / LEASE_EXTEND_RETRY_MAX);
194 if (leaderLock.extendExpiration(LEASE_DURATION_MS)) {
195 log.trace("SDN-IP Leader Extended");
196 extensionFailedCountdown = LEASE_EXTEND_RETRY_MAX;
197 } else {
198 log.debug("SDN-IP Leader Cannot Extend Election");
199 if (!leaderLock.isLocked()) {
200 log.debug("SDN-IP Leader Lock Lost");
201 intentSynchronizer.leaderChanged(false);
202 break; // Try again to get the lock
203 }
204 extensionFailedCountdown--;
205 if (extensionFailedCountdown <= 0) {
206 // Failed too many times to extend.
207 // Release the lock.
208 log.debug("SDN-IP Leader Lock Released");
209 intentSynchronizer.leaderChanged(false);
210 leaderLock.unlock();
211 break; // Try again to get the lock
212 }
213 }
214 } catch (InterruptedException e) {
215 // Thread interrupted. Time to shutdown
216 log.debug("SDN-IP Leader Interrupted");
217 }
218 }
219 }
220
221 // If we reach here, the instance was shutdown
222 intentSynchronizer.leaderChanged(false);
223 leaderLock.unlock();
224 }
Jonathan Hart039d2b12014-10-10 09:33:04 -0700225}