Fix race to become master in P4Runtime before pipeline config set

Change-Id: Id02e33a1d72d16ec49634ac57b6a4b56acdcf796
(cherry picked from commit 86f82c9e7ccd3912f77840e38eb7402a04f93681)
This commit is contained in:
Carmelo Cascone 2018-08-23 19:06:29 -07:00
parent e0260e1988
commit 85d72efe96

View File

@ -207,7 +207,7 @@ final class P4RuntimeClientImpl implements P4RuntimeClient {
@Override @Override
public CompletableFuture<Boolean> start() { public CompletableFuture<Boolean> start() {
return supplyInContext(this::doBecomeMaster, return supplyInContext(() -> sendMasterArbitrationUpdate(false),
"start-initStreamChannel"); "start-initStreamChannel");
} }
@ -219,7 +219,7 @@ final class P4RuntimeClientImpl implements P4RuntimeClient {
@Override @Override
public CompletableFuture<Boolean> becomeMaster() { public CompletableFuture<Boolean> becomeMaster() {
return supplyInContext(this::doBecomeMaster, return supplyInContext(() -> sendMasterArbitrationUpdate(true),
"becomeMaster"); "becomeMaster");
} }
@ -326,19 +326,20 @@ final class P4RuntimeClientImpl implements P4RuntimeClient {
/* Blocking method implementations below */ /* Blocking method implementations below */
private boolean doBecomeMaster() { private boolean sendMasterArbitrationUpdate(boolean asMaster) {
final Uint128 newId = bigIntegerToUint128( BigInteger newId = controller.newMasterElectionId(deviceId);
controller.newMasterElectionId(deviceId)); if (asMaster) {
if (sendMasterArbitrationUpdate(newId)) { // Becoming master is a race. Here we increase our chances of win
clientElectionId = newId; // against other ONOS nodes in the cluster that are calling start()
return true; // (which is used to start the stream RPC session, not to become
// master).
newId = newId.add(BigInteger.valueOf(1000));
} }
return false; final Uint128 idMsg = bigIntegerToUint128(
} controller.newMasterElectionId(deviceId));
private boolean sendMasterArbitrationUpdate(Uint128 electionId) {
log.info("Sending arbitration update to {}... electionId={}", log.info("Sending arbitration update to {}... electionId={}",
deviceId, uint128ToBigInteger(electionId)); deviceId, newId);
try { try {
streamRequestObserver.onNext( streamRequestObserver.onNext(
StreamMessageRequest.newBuilder() StreamMessageRequest.newBuilder()
@ -346,9 +347,10 @@ final class P4RuntimeClientImpl implements P4RuntimeClient {
MasterArbitrationUpdate MasterArbitrationUpdate
.newBuilder() .newBuilder()
.setDeviceId(p4DeviceId) .setDeviceId(p4DeviceId)
.setElectionId(electionId) .setElectionId(idMsg)
.build()) .build())
.build()); .build());
clientElectionId = idMsg;
return true; return true;
} catch (StatusRuntimeException e) { } catch (StatusRuntimeException e) {
log.error("Unable to perform arbitration update on {}: {}", deviceId, e.getMessage()); log.error("Unable to perform arbitration update on {}: {}", deviceId, e.getMessage());