Updates for SDN-IP:
* Use the new Leadership Service instead of Distributed Lock to elect the SDN-IP Leader * Reimplement the SDN-IP Intent Synchronizer. In the new implementation the Point-to-Point Peer intents are also synchronized by and pushed only by the Leader (same as the Multipoint-to-SinglePoint Route intents) * Minor cleanups Change-Id: I8e142781211a1d0f2d362875bc28fd05d843cd4b
Showing
11 changed files
with
135 additions
and
138 deletions
| ... | @@ -49,6 +49,12 @@ | ... | @@ -49,6 +49,12 @@ |
| 49 | </dependency> | 49 | </dependency> |
| 50 | 50 | ||
| 51 | <dependency> | 51 | <dependency> |
| 52 | + <groupId>org.apache.commons</groupId> | ||
| 53 | + <artifactId>commons-collections4</artifactId> | ||
| 54 | + <version>4.0</version> | ||
| 55 | + </dependency> | ||
| 56 | + | ||
| 57 | + <dependency> | ||
| 52 | <groupId>org.onlab.onos</groupId> | 58 | <groupId>org.onlab.onos</groupId> |
| 53 | <artifactId>onlab-thirdparty</artifactId> | 59 | <artifactId>onlab-thirdparty</artifactId> |
| 54 | </dependency> | 60 | </dependency> |
| ... | @@ -69,10 +75,12 @@ | ... | @@ -69,10 +75,12 @@ |
| 69 | <artifactId>onos-cli</artifactId> | 75 | <artifactId>onos-cli</artifactId> |
| 70 | <version>${project.version}</version> | 76 | <version>${project.version}</version> |
| 71 | </dependency> | 77 | </dependency> |
| 78 | + | ||
| 72 | <dependency> | 79 | <dependency> |
| 73 | <groupId>org.apache.karaf.shell</groupId> | 80 | <groupId>org.apache.karaf.shell</groupId> |
| 74 | <artifactId>org.apache.karaf.shell.console</artifactId> | 81 | <artifactId>org.apache.karaf.shell.console</artifactId> |
| 75 | </dependency> | 82 | </dependency> |
| 83 | + | ||
| 76 | <dependency> | 84 | <dependency> |
| 77 | <groupId>org.osgi</groupId> | 85 | <groupId>org.osgi</groupId> |
| 78 | <artifactId>org.osgi.core</artifactId> | 86 | <artifactId>org.osgi.core</artifactId> | ... | ... |
This diff is collapsed. Click to expand it.
| ... | @@ -16,6 +16,7 @@ | ... | @@ -16,6 +16,7 @@ |
| 16 | package org.onlab.onos.sdnip; | 16 | package org.onlab.onos.sdnip; |
| 17 | 17 | ||
| 18 | import java.util.ArrayList; | 18 | import java.util.ArrayList; |
| 19 | +import java.util.Collection; | ||
| 19 | import java.util.List; | 20 | import java.util.List; |
| 20 | 21 | ||
| 21 | import org.onlab.onos.core.ApplicationId; | 22 | import org.onlab.onos.core.ApplicationId; |
| ... | @@ -24,8 +25,6 @@ import org.onlab.onos.net.flow.DefaultTrafficSelector; | ... | @@ -24,8 +25,6 @@ import org.onlab.onos.net.flow.DefaultTrafficSelector; |
| 24 | import org.onlab.onos.net.flow.DefaultTrafficTreatment; | 25 | import org.onlab.onos.net.flow.DefaultTrafficTreatment; |
| 25 | import org.onlab.onos.net.flow.TrafficSelector; | 26 | import org.onlab.onos.net.flow.TrafficSelector; |
| 26 | import org.onlab.onos.net.flow.TrafficTreatment; | 27 | import org.onlab.onos.net.flow.TrafficTreatment; |
| 27 | -import org.onlab.onos.net.intent.Intent; | ||
| 28 | -import org.onlab.onos.net.intent.IntentService; | ||
| 29 | import org.onlab.onos.net.intent.PointToPointIntent; | 28 | import org.onlab.onos.net.intent.PointToPointIntent; |
| 30 | import org.onlab.onos.sdnip.bgp.BgpConstants; | 29 | import org.onlab.onos.sdnip.bgp.BgpConstants; |
| 31 | import org.onlab.onos.sdnip.config.BgpPeer; | 30 | import org.onlab.onos.sdnip.config.BgpPeer; |
| ... | @@ -48,9 +47,9 @@ public class PeerConnectivityManager { | ... | @@ -48,9 +47,9 @@ public class PeerConnectivityManager { |
| 48 | private static final Logger log = LoggerFactory.getLogger( | 47 | private static final Logger log = LoggerFactory.getLogger( |
| 49 | PeerConnectivityManager.class); | 48 | PeerConnectivityManager.class); |
| 50 | 49 | ||
| 50 | + private final IntentSynchronizer intentSynchronizer; | ||
| 51 | private final SdnIpConfigService configService; | 51 | private final SdnIpConfigService configService; |
| 52 | private final InterfaceService interfaceService; | 52 | private final InterfaceService interfaceService; |
| 53 | - private final IntentService intentService; | ||
| 54 | 53 | ||
| 55 | private final ApplicationId appId; | 54 | private final ApplicationId appId; |
| 56 | 55 | ||
| ... | @@ -58,18 +57,18 @@ public class PeerConnectivityManager { | ... | @@ -58,18 +57,18 @@ public class PeerConnectivityManager { |
| 58 | * Creates a new PeerConnectivityManager. | 57 | * Creates a new PeerConnectivityManager. |
| 59 | * | 58 | * |
| 60 | * @param appId the application ID | 59 | * @param appId the application ID |
| 60 | + * @param intentSynchronizer the intent synchronizer | ||
| 61 | * @param configService the SDN-IP config service | 61 | * @param configService the SDN-IP config service |
| 62 | * @param interfaceService the interface service | 62 | * @param interfaceService the interface service |
| 63 | - * @param intentService the intent service | ||
| 64 | */ | 63 | */ |
| 65 | public PeerConnectivityManager(ApplicationId appId, | 64 | public PeerConnectivityManager(ApplicationId appId, |
| 65 | + IntentSynchronizer intentSynchronizer, | ||
| 66 | SdnIpConfigService configService, | 66 | SdnIpConfigService configService, |
| 67 | - InterfaceService interfaceService, | 67 | + InterfaceService interfaceService) { |
| 68 | - IntentService intentService) { | ||
| 69 | this.appId = appId; | 68 | this.appId = appId; |
| 69 | + this.intentSynchronizer = intentSynchronizer; | ||
| 70 | this.configService = configService; | 70 | this.configService = configService; |
| 71 | this.interfaceService = interfaceService; | 71 | this.interfaceService = interfaceService; |
| 72 | - this.intentService = intentService; | ||
| 73 | } | 72 | } |
| 74 | 73 | ||
| 75 | /** | 74 | /** |
| ... | @@ -107,6 +106,8 @@ public class PeerConnectivityManager { | ... | @@ -107,6 +106,8 @@ public class PeerConnectivityManager { |
| 107 | * {@link BgpSpeaker}s and all external {@link BgpPeer}s. | 106 | * {@link BgpSpeaker}s and all external {@link BgpPeer}s. |
| 108 | */ | 107 | */ |
| 109 | private void setUpConnectivity() { | 108 | private void setUpConnectivity() { |
| 109 | + List<PointToPointIntent> intents = new ArrayList<>(); | ||
| 110 | + | ||
| 110 | for (BgpSpeaker bgpSpeaker : configService.getBgpSpeakers() | 111 | for (BgpSpeaker bgpSpeaker : configService.getBgpSpeakers() |
| 111 | .values()) { | 112 | .values()) { |
| 112 | log.debug("Start to set up BGP paths for BGP speaker: {}", | 113 | log.debug("Start to set up BGP paths for BGP speaker: {}", |
| ... | @@ -117,9 +118,12 @@ public class PeerConnectivityManager { | ... | @@ -117,9 +118,12 @@ public class PeerConnectivityManager { |
| 117 | log.debug("Start to set up BGP paths between BGP speaker: {} " | 118 | log.debug("Start to set up BGP paths between BGP speaker: {} " |
| 118 | + "to BGP peer: {}", bgpSpeaker, bgpPeer); | 119 | + "to BGP peer: {}", bgpSpeaker, bgpPeer); |
| 119 | 120 | ||
| 120 | - buildPeerIntents(bgpSpeaker, bgpPeer); | 121 | + intents.addAll(buildPeerIntents(bgpSpeaker, bgpPeer)); |
| 121 | } | 122 | } |
| 122 | } | 123 | } |
| 124 | + | ||
| 125 | + // Submit all the intents. | ||
| 126 | + intentSynchronizer.submitPeerIntents(intents); | ||
| 123 | } | 127 | } |
| 124 | 128 | ||
| 125 | /** | 129 | /** |
| ... | @@ -128,9 +132,12 @@ public class PeerConnectivityManager { | ... | @@ -128,9 +132,12 @@ public class PeerConnectivityManager { |
| 128 | * | 132 | * |
| 129 | * @param bgpSpeaker the BGP speaker | 133 | * @param bgpSpeaker the BGP speaker |
| 130 | * @param bgpPeer the BGP peer | 134 | * @param bgpPeer the BGP peer |
| 135 | + * @return the intents to install | ||
| 131 | */ | 136 | */ |
| 132 | - private void buildPeerIntents(BgpSpeaker bgpSpeaker, BgpPeer bgpPeer) { | 137 | + private Collection<PointToPointIntent> buildPeerIntents( |
| 133 | - List<Intent> intents = new ArrayList<Intent>(); | 138 | + BgpSpeaker bgpSpeaker, |
| 139 | + BgpPeer bgpPeer) { | ||
| 140 | + List<PointToPointIntent> intents = new ArrayList<>(); | ||
| 134 | 141 | ||
| 135 | ConnectPoint bgpdConnectPoint = bgpSpeaker.connectPoint(); | 142 | ConnectPoint bgpdConnectPoint = bgpSpeaker.connectPoint(); |
| 136 | 143 | ||
| ... | @@ -142,7 +149,7 @@ public class PeerConnectivityManager { | ... | @@ -142,7 +149,7 @@ public class PeerConnectivityManager { |
| 142 | 149 | ||
| 143 | if (peerInterface == null) { | 150 | if (peerInterface == null) { |
| 144 | log.error("No interface found for peer {}", bgpPeer.ipAddress()); | 151 | log.error("No interface found for peer {}", bgpPeer.ipAddress()); |
| 145 | - return; | 152 | + return intents; |
| 146 | } | 153 | } |
| 147 | 154 | ||
| 148 | IpAddress bgpdAddress = null; | 155 | IpAddress bgpdAddress = null; |
| ... | @@ -156,7 +163,7 @@ public class PeerConnectivityManager { | ... | @@ -156,7 +163,7 @@ public class PeerConnectivityManager { |
| 156 | if (bgpdAddress == null) { | 163 | if (bgpdAddress == null) { |
| 157 | log.debug("No IP address found for peer {} on interface {}", | 164 | log.debug("No IP address found for peer {} on interface {}", |
| 158 | bgpPeer, bgpPeer.connectPoint()); | 165 | bgpPeer, bgpPeer.connectPoint()); |
| 159 | - return; | 166 | + return intents; |
| 160 | } | 167 | } |
| 161 | 168 | ||
| 162 | IpAddress bgpdPeerAddress = bgpPeer.ipAddress(); | 169 | IpAddress bgpdPeerAddress = bgpPeer.ipAddress(); |
| ... | @@ -231,11 +238,7 @@ public class PeerConnectivityManager { | ... | @@ -231,11 +238,7 @@ public class PeerConnectivityManager { |
| 231 | intents.add(new PointToPointIntent(appId, selector, treatment, | 238 | intents.add(new PointToPointIntent(appId, selector, treatment, |
| 232 | bgpdPeerConnectPoint, bgpdConnectPoint)); | 239 | bgpdPeerConnectPoint, bgpdConnectPoint)); |
| 233 | 240 | ||
| 234 | - // Submit all the intents. | 241 | + return intents; |
| 235 | - // TODO submit as a batch | ||
| 236 | - for (Intent intent : intents) { | ||
| 237 | - intentService.submit(intent); | ||
| 238 | - } | ||
| 239 | } | 242 | } |
| 240 | 243 | ||
| 241 | /** | 244 | /** |
| ... | @@ -249,7 +252,8 @@ public class PeerConnectivityManager { | ... | @@ -249,7 +252,8 @@ public class PeerConnectivityManager { |
| 249 | * @return the new traffic selector | 252 | * @return the new traffic selector |
| 250 | */ | 253 | */ |
| 251 | private TrafficSelector buildSelector(byte ipProto, IpAddress srcIp, | 254 | private TrafficSelector buildSelector(byte ipProto, IpAddress srcIp, |
| 252 | - IpAddress dstIp, Short srcTcpPort, Short dstTcpPort) { | 255 | + IpAddress dstIp, Short srcTcpPort, |
| 256 | + Short dstTcpPort) { | ||
| 253 | TrafficSelector.Builder builder = DefaultTrafficSelector.builder() | 257 | TrafficSelector.Builder builder = DefaultTrafficSelector.builder() |
| 254 | .matchEthType(Ethernet.TYPE_IPV4) | 258 | .matchEthType(Ethernet.TYPE_IPV4) |
| 255 | .matchIPProtocol(ipProto) | 259 | .matchIPProtocol(ipProto) | ... | ... |
| ... | @@ -92,18 +92,19 @@ public class Router implements RouteListener { | ... | @@ -92,18 +92,19 @@ public class Router implements RouteListener { |
| 92 | * | 92 | * |
| 93 | * @param appId the application ID | 93 | * @param appId the application ID |
| 94 | * @param intentSynchronizer the intent synchronizer | 94 | * @param intentSynchronizer the intent synchronizer |
| 95 | - * @param hostService the host service | ||
| 96 | * @param configService the configuration service | 95 | * @param configService the configuration service |
| 97 | * @param interfaceService the interface service | 96 | * @param interfaceService the interface service |
| 97 | + * @param hostService the host service | ||
| 98 | */ | 98 | */ |
| 99 | public Router(ApplicationId appId, IntentSynchronizer intentSynchronizer, | 99 | public Router(ApplicationId appId, IntentSynchronizer intentSynchronizer, |
| 100 | - HostService hostService, SdnIpConfigService configService, | 100 | + SdnIpConfigService configService, |
| 101 | - InterfaceService interfaceService) { | 101 | + InterfaceService interfaceService, |
| 102 | + HostService hostService) { | ||
| 102 | this.appId = appId; | 103 | this.appId = appId; |
| 103 | this.intentSynchronizer = intentSynchronizer; | 104 | this.intentSynchronizer = intentSynchronizer; |
| 104 | - this.hostService = hostService; | ||
| 105 | this.configService = configService; | 105 | this.configService = configService; |
| 106 | this.interfaceService = interfaceService; | 106 | this.interfaceService = interfaceService; |
| 107 | + this.hostService = hostService; | ||
| 107 | 108 | ||
| 108 | this.hostListener = new InternalHostListener(); | 109 | this.hostListener = new InternalHostListener(); |
| 109 | 110 | ... | ... |
| ... | @@ -18,8 +18,6 @@ package org.onlab.onos.sdnip; | ... | @@ -18,8 +18,6 @@ package org.onlab.onos.sdnip; |
| 18 | import static org.slf4j.LoggerFactory.getLogger; | 18 | import static org.slf4j.LoggerFactory.getLogger; |
| 19 | 19 | ||
| 20 | import java.util.Collection; | 20 | import java.util.Collection; |
| 21 | -import java.util.concurrent.ExecutorService; | ||
| 22 | -import java.util.concurrent.Executors; | ||
| 23 | 21 | ||
| 24 | import org.apache.felix.scr.annotations.Activate; | 22 | import org.apache.felix.scr.annotations.Activate; |
| 25 | import org.apache.felix.scr.annotations.Component; | 23 | import org.apache.felix.scr.annotations.Component; |
| ... | @@ -27,6 +25,11 @@ import org.apache.felix.scr.annotations.Deactivate; | ... | @@ -27,6 +25,11 @@ import org.apache.felix.scr.annotations.Deactivate; |
| 27 | import org.apache.felix.scr.annotations.Reference; | 25 | import org.apache.felix.scr.annotations.Reference; |
| 28 | import org.apache.felix.scr.annotations.ReferenceCardinality; | 26 | import org.apache.felix.scr.annotations.ReferenceCardinality; |
| 29 | import org.apache.felix.scr.annotations.Service; | 27 | import org.apache.felix.scr.annotations.Service; |
| 28 | +import org.onlab.onos.cluster.ClusterService; | ||
| 29 | +import org.onlab.onos.cluster.ControllerNode; | ||
| 30 | +import org.onlab.onos.cluster.LeadershipEvent; | ||
| 31 | +import org.onlab.onos.cluster.LeadershipEventListener; | ||
| 32 | +import org.onlab.onos.cluster.LeadershipService; | ||
| 30 | import org.onlab.onos.core.ApplicationId; | 33 | import org.onlab.onos.core.ApplicationId; |
| 31 | import org.onlab.onos.core.CoreService; | 34 | import org.onlab.onos.core.CoreService; |
| 32 | import org.onlab.onos.net.host.HostService; | 35 | import org.onlab.onos.net.host.HostService; |
| ... | @@ -35,11 +38,8 @@ import org.onlab.onos.sdnip.bgp.BgpRouteEntry; | ... | @@ -35,11 +38,8 @@ import org.onlab.onos.sdnip.bgp.BgpRouteEntry; |
| 35 | import org.onlab.onos.sdnip.bgp.BgpSession; | 38 | import org.onlab.onos.sdnip.bgp.BgpSession; |
| 36 | import org.onlab.onos.sdnip.bgp.BgpSessionManager; | 39 | import org.onlab.onos.sdnip.bgp.BgpSessionManager; |
| 37 | import org.onlab.onos.sdnip.config.SdnIpConfigReader; | 40 | import org.onlab.onos.sdnip.config.SdnIpConfigReader; |
| 38 | -import org.onlab.onos.store.service.Lock; | ||
| 39 | -import org.onlab.onos.store.service.LockService; | ||
| 40 | -import org.slf4j.Logger; | ||
| 41 | 41 | ||
| 42 | -import com.google.common.util.concurrent.ThreadFactoryBuilder; | 42 | +import org.slf4j.Logger; |
| 43 | 43 | ||
| 44 | /** | 44 | /** |
| 45 | * Component for the SDN-IP peering application. | 45 | * Component for the SDN-IP peering application. |
| ... | @@ -65,55 +65,49 @@ public class SdnIp implements SdnIpService { | ... | @@ -65,55 +65,49 @@ public class SdnIp implements SdnIpService { |
| 65 | protected HostService hostService; | 65 | protected HostService hostService; |
| 66 | 66 | ||
| 67 | @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | 67 | @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) |
| 68 | - protected LockService lockService; | 68 | + protected ClusterService clusterService; |
| 69 | + | ||
| 70 | + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | ||
| 71 | + protected LeadershipService leadershipService; | ||
| 69 | 72 | ||
| 70 | private IntentSynchronizer intentSynchronizer; | 73 | private IntentSynchronizer intentSynchronizer; |
| 71 | private SdnIpConfigReader config; | 74 | private SdnIpConfigReader config; |
| 72 | private PeerConnectivityManager peerConnectivity; | 75 | private PeerConnectivityManager peerConnectivity; |
| 73 | private Router router; | 76 | private Router router; |
| 74 | private BgpSessionManager bgpSessionManager; | 77 | private BgpSessionManager bgpSessionManager; |
| 75 | - | 78 | + private LeadershipEventListener leadershipEventListener = |
| 76 | - private ExecutorService leaderElectionExecutor; | 79 | + new InnerLeadershipEventListener(); |
| 77 | - private Lock leaderLock; | 80 | + ApplicationId appId; |
| 78 | - private volatile boolean isShutdown = true; | 81 | + private ControllerNode localControllerNode; |
| 79 | 82 | ||
| 80 | @Activate | 83 | @Activate |
| 81 | protected void activate() { | 84 | protected void activate() { |
| 82 | log.info("SDN-IP started"); | 85 | log.info("SDN-IP started"); |
| 83 | - isShutdown = false; | ||
| 84 | 86 | ||
| 85 | - ApplicationId appId = coreService.registerApplication(SDN_IP_APP); | 87 | + appId = coreService.registerApplication(SDN_IP_APP); |
| 86 | config = new SdnIpConfigReader(); | 88 | config = new SdnIpConfigReader(); |
| 87 | config.init(); | 89 | config.init(); |
| 88 | 90 | ||
| 91 | + localControllerNode = clusterService.getLocalNode(); | ||
| 92 | + | ||
| 89 | InterfaceService interfaceService = | 93 | InterfaceService interfaceService = |
| 90 | new HostToInterfaceAdaptor(hostService); | 94 | new HostToInterfaceAdaptor(hostService); |
| 91 | 95 | ||
| 92 | intentSynchronizer = new IntentSynchronizer(appId, intentService); | 96 | intentSynchronizer = new IntentSynchronizer(appId, intentService); |
| 93 | intentSynchronizer.start(); | 97 | intentSynchronizer.start(); |
| 94 | 98 | ||
| 95 | - peerConnectivity = new PeerConnectivityManager(appId, config, | 99 | + peerConnectivity = new PeerConnectivityManager(appId, |
| 96 | - interfaceService, intentService); | 100 | + intentSynchronizer, |
| 101 | + config, | ||
| 102 | + interfaceService); | ||
| 97 | peerConnectivity.start(); | 103 | peerConnectivity.start(); |
| 98 | 104 | ||
| 99 | - router = new Router(appId, intentSynchronizer, hostService, config, | 105 | + router = new Router(appId, intentSynchronizer, config, |
| 100 | - interfaceService); | 106 | + interfaceService, hostService); |
| 101 | router.start(); | 107 | router.start(); |
| 102 | 108 | ||
| 103 | - leaderLock = lockService.create(SDN_IP_APP + "/sdnIpLeaderLock"); | 109 | + leadershipService.addListener(leadershipEventListener); |
| 104 | - leaderElectionExecutor = Executors.newSingleThreadExecutor( | 110 | + leadershipService.runForLeadership(appId.name()); |
| 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 | - | ||
| 114 | - // Manually set the instance as the leader to allow testing | ||
| 115 | - // TODO change this when we get a leader election | ||
| 116 | - // intentSynchronizer.leaderChanged(true); | ||
| 117 | 111 | ||
| 118 | bgpSessionManager = new BgpSessionManager(router); | 112 | bgpSessionManager = new BgpSessionManager(router); |
| 119 | // TODO: the local BGP listen port number should be configurable | 113 | // TODO: the local BGP listen port number should be configurable |
| ... | @@ -124,17 +118,16 @@ public class SdnIp implements SdnIpService { | ... | @@ -124,17 +118,16 @@ public class SdnIp implements SdnIpService { |
| 124 | 118 | ||
| 125 | @Deactivate | 119 | @Deactivate |
| 126 | protected void deactivate() { | 120 | protected void deactivate() { |
| 127 | - isShutdown = true; | ||
| 128 | 121 | ||
| 129 | bgpSessionManager.stop(); | 122 | bgpSessionManager.stop(); |
| 130 | router.stop(); | 123 | router.stop(); |
| 131 | peerConnectivity.stop(); | 124 | peerConnectivity.stop(); |
| 132 | intentSynchronizer.stop(); | 125 | intentSynchronizer.stop(); |
| 133 | 126 | ||
| 134 | - // Stop the thread(s) | 127 | + leadershipService.withdraw(appId.name()); |
| 135 | - leaderElectionExecutor.shutdownNow(); | 128 | + leadershipService.removeListener(leadershipEventListener); |
| 136 | 129 | ||
| 137 | - log.info("Stopped"); | 130 | + log.info("SDN-IP Stopped"); |
| 138 | } | 131 | } |
| 139 | 132 | ||
| 140 | @Override | 133 | @Override |
| ... | @@ -162,63 +155,38 @@ public class SdnIp implements SdnIpService { | ... | @@ -162,63 +155,38 @@ public class SdnIp implements SdnIpService { |
| 162 | } | 155 | } |
| 163 | 156 | ||
| 164 | /** | 157 | /** |
| 165 | - * Performs the leader election. | 158 | + * A listener for Leadership Events. |
| 166 | */ | 159 | */ |
| 167 | - private void doLeaderElectionThread() { | 160 | + private class InnerLeadershipEventListener |
| 161 | + implements LeadershipEventListener { | ||
| 168 | 162 | ||
| 169 | - // | 163 | + @Override |
| 170 | - // Try to acquire the lock and keep extending it until the instance | 164 | + public void event(LeadershipEvent event) { |
| 171 | - // is shutdown. | 165 | + log.debug("Leadership Event: time = {} type = {} event = {}", |
| 172 | - // | 166 | + event.time(), event.type(), event); |
| 173 | - while (!isShutdown) { | ||
| 174 | - log.debug("SDN-IP Leader Election begin"); | ||
| 175 | 167 | ||
| 176 | - // Block until it becomes the leader | 168 | + if (!event.subject().topic().equals(appId.name())) { |
| 177 | - try { | 169 | + return; // Not our topic: ignore |
| 178 | - leaderLock.lock(LEASE_DURATION_MS); | 170 | + } |
| 171 | + if (!event.subject().leader().id().equals( | ||
| 172 | + localControllerNode.id())) { | ||
| 173 | + return; // The event is not about this instance: ignore | ||
| 174 | + } | ||
| 179 | 175 | ||
| 180 | - // This instance is the leader | 176 | + switch (event.type()) { |
| 177 | + case LEADER_ELECTED: | ||
| 181 | log.info("SDN-IP Leader Elected"); | 178 | log.info("SDN-IP Leader Elected"); |
| 182 | intentSynchronizer.leaderChanged(true); | 179 | intentSynchronizer.leaderChanged(true); |
| 183 | - | 180 | + break; |
| 184 | - // Keep extending the expiration until shutdown | 181 | + case LEADER_BOOTED: |
| 185 | - int extensionFailedCountdown = LEASE_EXTEND_RETRY_MAX - 1; | 182 | + log.info("SDN-IP Leader Lost Election"); |
| 186 | - | 183 | + intentSynchronizer.leaderChanged(false); |
| 187 | - // | 184 | + break; |
| 188 | - // Keep periodically extending the lock expiration. | 185 | + case LEADER_REELECTED: |
| 189 | - // If there are multiple back-to-back failures to extend (with | 186 | + break; |
| 190 | - // extra sleep time between retrials), then release the lock. | 187 | + default: |
| 191 | - // | 188 | + break; |
| 192 | - while (!isShutdown) { | ||
| 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 | - } | ||
| 215 | - } catch (InterruptedException e) { | ||
| 216 | - // Thread interrupted. Time to shutdown | ||
| 217 | - log.debug("SDN-IP Leader Interrupted"); | ||
| 218 | } | 189 | } |
| 219 | } | 190 | } |
| 220 | - // If we reach here, the instance was shutdown | ||
| 221 | - intentSynchronizer.leaderChanged(false); | ||
| 222 | - leaderLock.unlock(); | ||
| 223 | } | 191 | } |
| 224 | } | 192 | } | ... | ... |
This diff is collapsed. Click to expand it.
| ... | @@ -20,6 +20,8 @@ import org.easymock.IArgumentMatcher; | ... | @@ -20,6 +20,8 @@ import org.easymock.IArgumentMatcher; |
| 20 | import org.junit.Before; | 20 | import org.junit.Before; |
| 21 | import org.junit.Ignore; | 21 | import org.junit.Ignore; |
| 22 | import org.junit.Test; | 22 | import org.junit.Test; |
| 23 | +import org.onlab.junit.TestUtils; | ||
| 24 | +import org.onlab.junit.TestUtils.TestUtilsException; | ||
| 23 | import org.onlab.onos.core.ApplicationId; | 25 | import org.onlab.onos.core.ApplicationId; |
| 24 | import org.onlab.onos.net.ConnectPoint; | 26 | import org.onlab.onos.net.ConnectPoint; |
| 25 | import org.onlab.onos.net.DeviceId; | 27 | import org.onlab.onos.net.DeviceId; |
| ... | @@ -70,9 +72,10 @@ public class PeerConnectivityManagerTest { | ... | @@ -70,9 +72,10 @@ public class PeerConnectivityManagerTest { |
| 70 | }; | 72 | }; |
| 71 | 73 | ||
| 72 | private PeerConnectivityManager peerConnectivityManager; | 74 | private PeerConnectivityManager peerConnectivityManager; |
| 73 | - private IntentService intentService; | 75 | + private IntentSynchronizer intentSynchronizer; |
| 74 | private SdnIpConfigService configInfoService; | 76 | private SdnIpConfigService configInfoService; |
| 75 | private InterfaceService interfaceService; | 77 | private InterfaceService interfaceService; |
| 78 | + private IntentService intentService; | ||
| 76 | 79 | ||
| 77 | private Map<String, BgpSpeaker> bgpSpeakers; | 80 | private Map<String, BgpSpeaker> bgpSpeakers; |
| 78 | private Map<String, Interface> interfaces; | 81 | private Map<String, Interface> interfaces; |
| ... | @@ -525,8 +528,10 @@ public class PeerConnectivityManagerTest { | ... | @@ -525,8 +528,10 @@ public class PeerConnectivityManagerTest { |
| 525 | 528 | ||
| 526 | /** | 529 | /** |
| 527 | * Initializes peer connectivity testing environment. | 530 | * Initializes peer connectivity testing environment. |
| 531 | + * | ||
| 532 | + * @throws TestUtilsException if exceptions when using TestUtils | ||
| 528 | */ | 533 | */ |
| 529 | - private void initPeerConnectivity() { | 534 | + private void initPeerConnectivity() throws TestUtilsException { |
| 530 | 535 | ||
| 531 | configInfoService = createMock(SdnIpConfigService.class); | 536 | configInfoService = createMock(SdnIpConfigService.class); |
| 532 | expect(configInfoService.getBgpPeers()).andReturn(peers).anyTimes(); | 537 | expect(configInfoService.getBgpPeers()).andReturn(peers).anyTimes(); |
| ... | @@ -536,8 +541,13 @@ public class PeerConnectivityManagerTest { | ... | @@ -536,8 +541,13 @@ public class PeerConnectivityManagerTest { |
| 536 | intentService = createMock(IntentService.class); | 541 | intentService = createMock(IntentService.class); |
| 537 | replay(intentService); | 542 | replay(intentService); |
| 538 | 543 | ||
| 539 | - peerConnectivityManager = new PeerConnectivityManager(APPID, configInfoService, | 544 | + intentSynchronizer = new IntentSynchronizer(APPID, intentService); |
| 540 | - interfaceService, intentService); | 545 | + intentSynchronizer.leaderChanged(true); |
| 546 | + TestUtils.setField(intentSynchronizer, "isActivatedLeader", true); | ||
| 547 | + | ||
| 548 | + peerConnectivityManager = | ||
| 549 | + new PeerConnectivityManager(APPID, intentSynchronizer, | ||
| 550 | + configInfoService, interfaceService); | ||
| 541 | } | 551 | } |
| 542 | 552 | ||
| 543 | /* | 553 | /* | ... | ... |
| ... | @@ -115,8 +115,8 @@ public class RouterTest { | ... | @@ -115,8 +115,8 @@ public class RouterTest { |
| 115 | intentService = createMock(IntentService.class); | 115 | intentService = createMock(IntentService.class); |
| 116 | 116 | ||
| 117 | intentSynchronizer = new IntentSynchronizer(APPID, intentService); | 117 | intentSynchronizer = new IntentSynchronizer(APPID, intentService); |
| 118 | - router = new Router(APPID, intentSynchronizer, | 118 | + router = new Router(APPID, intentSynchronizer, sdnIpConfigService, |
| 119 | - hostService, sdnIpConfigService, interfaceService); | 119 | + interfaceService, hostService); |
| 120 | } | 120 | } |
| 121 | 121 | ||
| 122 | /** | 122 | /** |
| ... | @@ -267,8 +267,8 @@ public class RouterTest { | ... | @@ -267,8 +267,8 @@ public class RouterTest { |
| 267 | // Verify | 267 | // Verify |
| 268 | assertEquals(router.getRoutes().size(), 1); | 268 | assertEquals(router.getRoutes().size(), 1); |
| 269 | assertTrue(router.getRoutes().contains(routeEntry)); | 269 | assertTrue(router.getRoutes().contains(routeEntry)); |
| 270 | - assertEquals(intentSynchronizer.getPushedRouteIntents().size(), 1); | 270 | + assertEquals(intentSynchronizer.getRouteIntents().size(), 1); |
| 271 | - assertEquals(intentSynchronizer.getPushedRouteIntents().iterator().next(), | 271 | + assertEquals(intentSynchronizer.getRouteIntents().iterator().next(), |
| 272 | intent); | 272 | intent); |
| 273 | verify(intentService); | 273 | verify(intentService); |
| 274 | } | 274 | } |
| ... | @@ -347,8 +347,8 @@ public class RouterTest { | ... | @@ -347,8 +347,8 @@ public class RouterTest { |
| 347 | // Verify | 347 | // Verify |
| 348 | assertEquals(router.getRoutes().size(), 1); | 348 | assertEquals(router.getRoutes().size(), 1); |
| 349 | assertTrue(router.getRoutes().contains(routeEntryUpdate)); | 349 | assertTrue(router.getRoutes().contains(routeEntryUpdate)); |
| 350 | - assertEquals(intentSynchronizer.getPushedRouteIntents().size(), 1); | 350 | + assertEquals(intentSynchronizer.getRouteIntents().size(), 1); |
| 351 | - assertEquals(intentSynchronizer.getPushedRouteIntents().iterator().next(), | 351 | + assertEquals(intentSynchronizer.getRouteIntents().iterator().next(), |
| 352 | intentNew); | 352 | intentNew); |
| 353 | verify(intentService); | 353 | verify(intentService); |
| 354 | } | 354 | } |
| ... | @@ -397,7 +397,7 @@ public class RouterTest { | ... | @@ -397,7 +397,7 @@ public class RouterTest { |
| 397 | 397 | ||
| 398 | // Verify | 398 | // Verify |
| 399 | assertEquals(router.getRoutes().size(), 0); | 399 | assertEquals(router.getRoutes().size(), 0); |
| 400 | - assertEquals(intentSynchronizer.getPushedRouteIntents().size(), 0); | 400 | + assertEquals(intentSynchronizer.getRouteIntents().size(), 0); |
| 401 | verify(intentService); | 401 | verify(intentService); |
| 402 | } | 402 | } |
| 403 | 403 | ||
| ... | @@ -425,7 +425,7 @@ public class RouterTest { | ... | @@ -425,7 +425,7 @@ public class RouterTest { |
| 425 | // Verify | 425 | // Verify |
| 426 | assertEquals(router.getRoutes().size(), 1); | 426 | assertEquals(router.getRoutes().size(), 1); |
| 427 | assertTrue(router.getRoutes().contains(routeEntry)); | 427 | assertTrue(router.getRoutes().contains(routeEntry)); |
| 428 | - assertEquals(intentSynchronizer.getPushedRouteIntents().size(), 0); | 428 | + assertEquals(intentSynchronizer.getRouteIntents().size(), 0); |
| 429 | verify(intentService); | 429 | verify(intentService); |
| 430 | } | 430 | } |
| 431 | } | 431 | } | ... | ... |
| ... | @@ -117,7 +117,7 @@ public class RouterTestWithAsyncArp { | ... | @@ -117,7 +117,7 @@ public class RouterTestWithAsyncArp { |
| 117 | 117 | ||
| 118 | intentSynchronizer = new IntentSynchronizer(APPID, intentService); | 118 | intentSynchronizer = new IntentSynchronizer(APPID, intentService); |
| 119 | router = new Router(APPID, intentSynchronizer, | 119 | router = new Router(APPID, intentSynchronizer, |
| 120 | - hostService, sdnIpConfigService, interfaceService); | 120 | + sdnIpConfigService, interfaceService, hostService); |
| 121 | internalHostListener = router.new InternalHostListener(); | 121 | internalHostListener = router.new InternalHostListener(); |
| 122 | } | 122 | } |
| 123 | 123 | ||
| ... | @@ -229,8 +229,8 @@ public class RouterTestWithAsyncArp { | ... | @@ -229,8 +229,8 @@ public class RouterTestWithAsyncArp { |
| 229 | // Verify | 229 | // Verify |
| 230 | assertEquals(router.getRoutes().size(), 1); | 230 | assertEquals(router.getRoutes().size(), 1); |
| 231 | assertTrue(router.getRoutes().contains(routeEntry)); | 231 | assertTrue(router.getRoutes().contains(routeEntry)); |
| 232 | - assertEquals(intentSynchronizer.getPushedRouteIntents().size(), 1); | 232 | + assertEquals(intentSynchronizer.getRouteIntents().size(), 1); |
| 233 | - assertEquals(intentSynchronizer.getPushedRouteIntents().iterator().next(), | 233 | + assertEquals(intentSynchronizer.getRouteIntents().iterator().next(), |
| 234 | intent); | 234 | intent); |
| 235 | verify(intentService); | 235 | verify(intentService); |
| 236 | verify(hostService); | 236 | verify(hostService); |
| ... | @@ -254,9 +254,9 @@ public class RouterTestWithAsyncArp { | ... | @@ -254,9 +254,9 @@ public class RouterTestWithAsyncArp { |
| 254 | MultiPointToSinglePointIntent intent = staticIntentBuilder(); | 254 | MultiPointToSinglePointIntent intent = staticIntentBuilder(); |
| 255 | 255 | ||
| 256 | // Set up the bgpRoutes field of Router class with existing route, and | 256 | // Set up the bgpRoutes field of Router class with existing route, and |
| 257 | - // pushedRouteIntents field with the corresponding existing intent | 257 | + // routeIntents field with the corresponding existing intent |
| 258 | setBgpRoutesField(routeEntry); | 258 | setBgpRoutesField(routeEntry); |
| 259 | - setPushedRouteIntentsField(routeEntry, intent); | 259 | + setRouteIntentsField(routeEntry, intent); |
| 260 | 260 | ||
| 261 | // Start to construct a new route entry and new intent | 261 | // Start to construct a new route entry and new intent |
| 262 | RouteEntry routeEntryUpdate = new RouteEntry( | 262 | RouteEntry routeEntryUpdate = new RouteEntry( |
| ... | @@ -312,8 +312,8 @@ public class RouterTestWithAsyncArp { | ... | @@ -312,8 +312,8 @@ public class RouterTestWithAsyncArp { |
| 312 | // Verify | 312 | // Verify |
| 313 | assertEquals(router.getRoutes().size(), 1); | 313 | assertEquals(router.getRoutes().size(), 1); |
| 314 | assertTrue(router.getRoutes().contains(routeEntryUpdate)); | 314 | assertTrue(router.getRoutes().contains(routeEntryUpdate)); |
| 315 | - assertEquals(intentSynchronizer.getPushedRouteIntents().size(), 1); | 315 | + assertEquals(intentSynchronizer.getRouteIntents().size(), 1); |
| 316 | - assertEquals(intentSynchronizer.getPushedRouteIntents().iterator().next(), | 316 | + assertEquals(intentSynchronizer.getRouteIntents().iterator().next(), |
| 317 | intentNew); | 317 | intentNew); |
| 318 | verify(intentService); | 318 | verify(intentService); |
| 319 | verify(hostService); | 319 | verify(hostService); |
| ... | @@ -334,9 +334,9 @@ public class RouterTestWithAsyncArp { | ... | @@ -334,9 +334,9 @@ public class RouterTestWithAsyncArp { |
| 334 | MultiPointToSinglePointIntent intent = staticIntentBuilder(); | 334 | MultiPointToSinglePointIntent intent = staticIntentBuilder(); |
| 335 | 335 | ||
| 336 | // Set up the bgpRoutes field of Router class with existing route, and | 336 | // Set up the bgpRoutes field of Router class with existing route, and |
| 337 | - // pushedRouteIntents field with the corresponding existing intent | 337 | + // routeIntents field with the corresponding existing intent |
| 338 | setBgpRoutesField(routeEntry); | 338 | setBgpRoutesField(routeEntry); |
| 339 | - setPushedRouteIntentsField(routeEntry, intent); | 339 | + setRouteIntentsField(routeEntry, intent); |
| 340 | 340 | ||
| 341 | // Set up expectation | 341 | // Set up expectation |
| 342 | reset(intentService); | 342 | reset(intentService); |
| ... | @@ -350,7 +350,7 @@ public class RouterTestWithAsyncArp { | ... | @@ -350,7 +350,7 @@ public class RouterTestWithAsyncArp { |
| 350 | 350 | ||
| 351 | // Verify | 351 | // Verify |
| 352 | assertEquals(router.getRoutes().size(), 0); | 352 | assertEquals(router.getRoutes().size(), 0); |
| 353 | - assertEquals(intentSynchronizer.getPushedRouteIntents().size(), 0); | 353 | + assertEquals(intentSynchronizer.getRouteIntents().size(), 0); |
| 354 | verify(intentService); | 354 | verify(intentService); |
| 355 | } | 355 | } |
| 356 | 356 | ||
| ... | @@ -397,17 +397,17 @@ public class RouterTestWithAsyncArp { | ... | @@ -397,17 +397,17 @@ public class RouterTestWithAsyncArp { |
| 397 | } | 397 | } |
| 398 | 398 | ||
| 399 | /** | 399 | /** |
| 400 | - * Sets pushedRouteIntentsField in Router class. | 400 | + * Sets routeIntentsField in IntentSynchronizer class. |
| 401 | * | 401 | * |
| 402 | * @throws TestUtilsException | 402 | * @throws TestUtilsException |
| 403 | */ | 403 | */ |
| 404 | - private void setPushedRouteIntentsField(RouteEntry routeEntry, | 404 | + private void setRouteIntentsField(RouteEntry routeEntry, |
| 405 | MultiPointToSinglePointIntent intent) | 405 | MultiPointToSinglePointIntent intent) |
| 406 | throws TestUtilsException { | 406 | throws TestUtilsException { |
| 407 | 407 | ||
| 408 | ConcurrentHashMap<Ip4Prefix, MultiPointToSinglePointIntent> | 408 | ConcurrentHashMap<Ip4Prefix, MultiPointToSinglePointIntent> |
| 409 | - pushedRouteIntents = new ConcurrentHashMap<>(); | 409 | + routeIntents = new ConcurrentHashMap<>(); |
| 410 | - pushedRouteIntents.put(routeEntry.prefix(), intent); | 410 | + routeIntents.put(routeEntry.prefix(), intent); |
| 411 | - TestUtils.setField(router, "pushedRouteIntents", pushedRouteIntents); | 411 | + TestUtils.setField(intentSynchronizer, "routeIntents", routeIntents); |
| 412 | } | 412 | } |
| 413 | } | 413 | } |
| ... | \ No newline at end of file | ... | \ No newline at end of file | ... | ... |
| ... | @@ -113,8 +113,8 @@ public class SdnIpTest { | ... | @@ -113,8 +113,8 @@ public class SdnIpTest { |
| 113 | random = new Random(); | 113 | random = new Random(); |
| 114 | 114 | ||
| 115 | intentSynchronizer = new IntentSynchronizer(APPID, intentService); | 115 | intentSynchronizer = new IntentSynchronizer(APPID, intentService); |
| 116 | - router = new Router(APPID, intentSynchronizer, hostService, | 116 | + router = new Router(APPID, intentSynchronizer, sdnIpConfigService, |
| 117 | - sdnIpConfigService, interfaceService); | 117 | + interfaceService, hostService); |
| 118 | } | 118 | } |
| 119 | 119 | ||
| 120 | /** | 120 | /** |
| ... | @@ -241,7 +241,7 @@ public class SdnIpTest { | ... | @@ -241,7 +241,7 @@ public class SdnIpTest { |
| 241 | latch.await(5000, TimeUnit.MILLISECONDS); | 241 | latch.await(5000, TimeUnit.MILLISECONDS); |
| 242 | 242 | ||
| 243 | assertEquals(router.getRoutes().size(), numRoutes); | 243 | assertEquals(router.getRoutes().size(), numRoutes); |
| 244 | - assertEquals(intentSynchronizer.getPushedRouteIntents().size(), | 244 | + assertEquals(intentSynchronizer.getRouteIntents().size(), |
| 245 | numRoutes); | 245 | numRoutes); |
| 246 | 246 | ||
| 247 | verify(intentService); | 247 | verify(intentService); |
| ... | @@ -317,7 +317,7 @@ public class SdnIpTest { | ... | @@ -317,7 +317,7 @@ public class SdnIpTest { |
| 317 | deleteCount.await(5000, TimeUnit.MILLISECONDS); | 317 | deleteCount.await(5000, TimeUnit.MILLISECONDS); |
| 318 | 318 | ||
| 319 | assertEquals(0, router.getRoutes().size()); | 319 | assertEquals(0, router.getRoutes().size()); |
| 320 | - assertEquals(0, intentSynchronizer.getPushedRouteIntents().size()); | 320 | + assertEquals(0, intentSynchronizer.getRouteIntents().size()); |
| 321 | verify(intentService); | 321 | verify(intentService); |
| 322 | } | 322 | } |
| 323 | 323 | ... | ... |
| ... | @@ -139,6 +139,12 @@ | ... | @@ -139,6 +139,12 @@ |
| 139 | </dependency> | 139 | </dependency> |
| 140 | 140 | ||
| 141 | <dependency> | 141 | <dependency> |
| 142 | + <groupId>org.apache.commons</groupId> | ||
| 143 | + <artifactId>commons-collections4</artifactId> | ||
| 144 | + <version>4.0</version> | ||
| 145 | + </dependency> | ||
| 146 | + | ||
| 147 | + <dependency> | ||
| 142 | <groupId>org.codehaus.jackson</groupId> | 148 | <groupId>org.codehaus.jackson</groupId> |
| 143 | <artifactId>jackson-core-asl</artifactId> | 149 | <artifactId>jackson-core-asl</artifactId> |
| 144 | <version>1.9.13</version> | 150 | <version>1.9.13</version> | ... | ... |
-
Please register or login to post a comment