2 * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.openflowplugin.openflow.md.core.session;
10 import com.google.common.base.Preconditions;
11 import java.math.BigInteger;
12 import java.util.concurrent.Callable;
13 import java.util.concurrent.Future;
14 import java.util.concurrent.TimeUnit;
16 import org.opendaylight.openflowplugin.api.OFConstants;
17 import org.opendaylight.openflowplugin.api.openflow.md.core.session.SessionContext;
18 import org.opendaylight.openflowplugin.openflow.md.core.MessageFactory;
19 import org.opendaylight.openflowplugin.openflow.md.util.RoleUtil;
20 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.BarrierInput;
21 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.BarrierOutput;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.RoleRequestOutput;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflow.common.config.impl.rev140326.OfpRole;
24 import org.opendaylight.yangtools.yang.common.RpcResult;
25 import org.slf4j.Logger;
26 import org.slf4j.LoggerFactory;
27 import java.util.Date;
30 * push role to device - basic step:
32 * <li>here we read generationId from device and</li>
33 * <li>push role request with incremented generationId</li>
34 * <li>{@link #call()} returns true if role request was successful</li>
37 //final class RolePushTask implements Callable<Boolean> {
38 public class RolePushTask implements Callable<Boolean> {
40 private static final Logger LOG = LoggerFactory
41 .getLogger(RolePushTask.class);
43 public static final long TIMEOUT = 7000;
44 public static final TimeUnit TIMEOUT_UNIT = TimeUnit.MILLISECONDS;
46 private SessionContext session;
48 private int retryCounter;
51 * @param role openflow controller role
52 * @param session switch session context
54 public RolePushTask(OfpRole role, SessionContext session) {
55 Preconditions.checkNotNull("OfpRole can not be empty.", role);
56 Preconditions.checkNotNull("Session context can not be empty.", session);
58 this.session = session;
62 * @return the retryCounter
64 public int getRetryCounter() {
69 * @return the priority
71 public int getPriority() {
76 * @param priority the priority to set
78 public void setPriority(int priority) {
79 this.priority = priority;
83 public Boolean call() throws RolePushException {
84 if (session.getPrimaryConductor().getVersion() == OFConstants.OFP_VERSION_1_0) {
85 LOG.info("OpenFlow 1.0 devices don't support multi controller features, skipping role push.");
88 if (!session.isValid()) {
89 String msg = "Giving up role change: current session is invalid";
91 throw new RolePushException(msg);
94 // adopt actual generationId from device (first shot failed and this is retry)
95 BigInteger generationId = null;
96 String dpId = new BigInteger(session.getSessionKey().getId()).toString();
97 LOG.info("Pushing {} role configuration to device openflow:{}",
98 role==OfpRole.BECOMEMASTER?"MASTER":"SLAVE", dpId);
100 Date date = new Date();
101 Future<BigInteger> generationIdFuture = RoleUtil.readGenerationIdFromDevice(session);
102 // flush election result with barrier
103 BarrierInput barrierInput = MessageFactory.createBarrier(
104 session.getFeatures().getVersion(), session.getNextXid());
105 Future<RpcResult<BarrierOutput>> barrierResult = session.getPrimaryConductor().getConnectionAdapter().barrier(barrierInput);
107 barrierResult.get(TIMEOUT, TIMEOUT_UNIT);
108 } catch (Exception e) {
109 String msg = String.format("Giving up role change: barrier after read generation-id failed : %s", e.getMessage());
111 throw new RolePushException(msg);
114 generationId = generationIdFuture.get(0, TIMEOUT_UNIT);
115 } catch (Exception e) {
116 String msg = String.format("Giving up role change: read generation-id failed %s", e.getMessage());
117 throw new RolePushException(msg);
120 LOG.info("Received generation-id {} for role change request from device {}",
122 } catch (Exception e) {
123 LOG.error("Role push request failed for device {}",session.getSessionKey().getId(), e);
126 if (generationId == null) {
127 LOG.error("Generation ID is NULL for device {}",session.getSessionKey().getId());
128 String msg = "Giving up role change: current generation-id can not be read";
129 throw new RolePushException(msg);
132 generationId = RoleUtil.getNextGenerationId(generationId);
133 LOG.info("Pushing role change {} config request with generation-id {} to device {}",
134 role==OfpRole.BECOMEMASTER?"MASTER":"SLAVE", generationId, dpId);
137 // try to possess role on device
138 Future<RpcResult<RoleRequestOutput>> roleReply = RoleUtil.sendRoleChangeRequest(session, role, generationId);
139 // flush election result with barrier
140 BarrierInput barrierInput = MessageFactory.createBarrier(
141 session.getFeatures().getVersion(), session.getNextXid());
142 Future<RpcResult<BarrierOutput>> barrierResult = session.getPrimaryConductor().getConnectionAdapter().barrier(barrierInput);
144 barrierResult.get(TIMEOUT, TIMEOUT_UNIT);
145 } catch (Exception e) {
146 String msg = String.format("Giving up role change: barrier after role change failed: %s", e.getMessage());
148 throw new RolePushException(msg);
150 // after barrier replied there must be election result or error
152 roleReply.get(0, TimeUnit.MILLISECONDS);
153 } catch (Exception e) {
154 // no election result received - let's retry
159 // here we expect that role on device is successfully possessed
160 LOG.info("Successfully pushing {} role to the device openflow:{}",
161 role==OfpRole.BECOMEMASTER?"MASTER":"SLAVE", dpId);