Send node details notification up to the application, 29/33529/3
authorAnil Vishnoi <vishnoianil@gmail.com>
Tue, 26 Jan 2016 02:49:03 +0000 (18:49 -0800)
committerAnil Vishnoi <vishnoianil@gmail.com>
Tue, 26 Jan 2016 04:53:22 +0000 (20:53 -0800)
once switch role is configured. Currently application were getting notified when switch Description message
received by the controller, and application assume that switch is configured and ready to use.
This patch, send the desc request when switch role is configured and it's ready to use

Change-Id: I8a02c209c4796b7aa01161257d523139fdc9c881
Signed-off-by: Anil Vishnoi <vishnoianil@gmail.com>
openflowplugin-api/src/main/java/org/opendaylight/openflowplugin/api/openflow/md/ModelDrivenSwitch.java
openflowplugin/src/main/java/org/opendaylight/openflowplugin/openflow/md/core/ConnectionConductorImpl.java
openflowplugin/src/main/java/org/opendaylight/openflowplugin/openflow/md/core/role/OfEntityManager.java
openflowplugin/src/main/java/org/opendaylight/openflowplugin/openflow/md/core/sal/ModelDrivenSwitchImpl.java
openflowplugin/src/main/java/org/opendaylight/openflowplugin/openflow/md/core/session/RolePushTask.java
openflowplugin/src/test/java/org/opendaylight/openflowplugin/openflow/md/core/ConnectionConductorImplTest.java

index d923209c3d95630879d7c9979cf67cd9881da4ba..0120d9004f226ab95a92fd5e6f9f450980d4fdfc 100644 (file)
@@ -79,4 +79,10 @@ public interface ModelDrivenSwitch
      */
     Optional<BigInteger> sendEmptyTableFeatureRequest();
 
+    /**
+     * Method send port/desc multipart request to the switch to fetch the initial details.
+     */
+
+    public abstract void requestSwitchDetails();
+
 }
index 612bf01997b323a8910f728e5d45b3af35a3cedf..d6852e12d7077fbc957db9edfe94398358f2adae 100644 (file)
@@ -35,8 +35,6 @@ import org.opendaylight.openflowplugin.api.openflow.md.queue.WaterMarkListenerIm
 import org.opendaylight.openflowplugin.openflow.md.core.session.OFSessionUtil;
 import org.opendaylight.openflowplugin.openflow.md.core.session.PortFeaturesUtil;
 import org.opendaylight.openflowplugin.openflow.md.queue.QueueKeeperFactory;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MultipartRequestFlags;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MultipartType;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.EchoInputBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.EchoOutput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.EchoReplyInputBuilder;
@@ -47,17 +45,12 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.GetFeaturesOutput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.HelloMessage;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartReplyMessage;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartRequestInputBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.OfHeader;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.OpenflowProtocolListener;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.PacketInMessage;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.PortGrouping;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.PortStatus;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.PortStatusMessage;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.multipart.request.body.MultipartRequestDescCaseBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.multipart.request.body.MultipartRequestGroupFeaturesCaseBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.multipart.request.body.MultipartRequestMeterFeaturesCaseBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.multipart.request.body.MultipartRequestPortDescCaseBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.system.rev130927.DisconnectEvent;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.system.rev130927.SwitchIdleEvent;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.system.rev130927.SystemNotificationsListener;
@@ -466,13 +459,6 @@ public class ConnectionConductorImpl implements OpenflowProtocolListener,
     public void onHandshakeSuccessfull(GetFeaturesOutput featureOutput,
                                        Short negotiatedVersion) {
         postHandshakeBasic(featureOutput, negotiatedVersion);
-
-        // post-handshake actions
-        if (version == OFConstants.OFP_VERSION_1_3) {
-            requestPorts();
-        }
-
-        requestDesc();
     }
 
     @Override
@@ -509,63 +495,6 @@ public class ConnectionConductorImpl implements OpenflowProtocolListener,
         OFSessionUtil.setRole(sessionContext);
     }
 
-    /*
-     * Send an OFPMP_DESC request message to the switch
-     */
-    private void requestDesc() {
-        MultipartRequestInputBuilder builder = new MultipartRequestInputBuilder();
-        builder.setType(MultipartType.OFPMPDESC);
-        builder.setVersion(getVersion());
-        builder.setFlags(new MultipartRequestFlags(false));
-        builder.setMultipartRequestBody(new MultipartRequestDescCaseBuilder()
-                .build());
-        builder.setXid(getSessionContext().getNextXid());
-        getConnectionAdapter().multipartRequest(builder.build());
-    }
-
-    private void requestPorts() {
-        MultipartRequestInputBuilder builder = new MultipartRequestInputBuilder();
-        builder.setType(MultipartType.OFPMPPORTDESC);
-        builder.setVersion(getVersion());
-        builder.setFlags(new MultipartRequestFlags(false));
-        builder.setMultipartRequestBody(new MultipartRequestPortDescCaseBuilder()
-                .build());
-        builder.setXid(getSessionContext().getNextXid());
-        getConnectionAdapter().multipartRequest(builder.build());
-    }
-
-    private void requestGroupFeatures() {
-        MultipartRequestInputBuilder mprInput = new MultipartRequestInputBuilder();
-        mprInput.setType(MultipartType.OFPMPGROUPFEATURES);
-        mprInput.setVersion(getVersion());
-        mprInput.setFlags(new MultipartRequestFlags(false));
-        mprInput.setXid(getSessionContext().getNextXid());
-
-        MultipartRequestGroupFeaturesCaseBuilder mprGroupFeaturesBuild = new MultipartRequestGroupFeaturesCaseBuilder();
-        mprInput.setMultipartRequestBody(mprGroupFeaturesBuild.build());
-
-        LOG.debug("Send group features statistics request :{}",
-                mprGroupFeaturesBuild);
-        getConnectionAdapter().multipartRequest(mprInput.build());
-
-    }
-
-    private void requestMeterFeatures() {
-        MultipartRequestInputBuilder mprInput = new MultipartRequestInputBuilder();
-        mprInput.setType(MultipartType.OFPMPMETERFEATURES);
-        mprInput.setVersion(getVersion());
-        mprInput.setFlags(new MultipartRequestFlags(false));
-        mprInput.setXid(getSessionContext().getNextXid());
-
-        MultipartRequestMeterFeaturesCaseBuilder mprMeterFeaturesBuild = new MultipartRequestMeterFeaturesCaseBuilder();
-        mprInput.setMultipartRequestBody(mprMeterFeaturesBuild.build());
-
-        LOG.debug("Send meter features statistics request :{}",
-                mprMeterFeaturesBuild);
-        getConnectionAdapter().multipartRequest(mprInput.build());
-
-    }
-
     /**
      * @param isBitmapNegotiationEnable the isBitmapNegotiationEnable to set
      */
index 1475c84877585ba5cf1dd0d4abdc45835276f95a..ab0dca8e1c1b9ff935b5d81c776721ea0639c884 100644 (file)
@@ -177,7 +177,7 @@ public class OfEntityManager implements TransactionChainListener{
         newRole = OfpRole.BECOMESLAVE;
         if (sessionContext != null) {
             final BigInteger targetSwitchDPId = sessionContext.getFeatures().getDatapathId();
-            LOG.info("setSlaveRole: Set controller as a SLAVE controller for {}", targetSwitchDPId.toString());
+            LOG.debug("setSlaveRole: Set controller as a SLAVE controller for {}", targetSwitchDPId.toString());
 
             RolePushTask task = new RolePushTask(newRole, sessionContext);
             ListenableFuture<Boolean> rolePushResult = pool.submit(task);
@@ -186,7 +186,7 @@ public class OfEntityManager implements TransactionChainListener{
             Futures.addCallback(rolePushResult, new FutureCallback<Boolean>(){
                 @Override
                 public void onSuccess(Boolean result){
-                    LOG.info("setSlaveRole: Controller is set as a SLAVE for {}", targetSwitchDPId.toString());
+                    LOG.debug("setSlaveRole: Controller is set as a SLAVE for {}", targetSwitchDPId.toString());
                 }
                 @Override
                 public void onFailure(Throwable e){
@@ -195,7 +195,7 @@ public class OfEntityManager implements TransactionChainListener{
                 }
             });
         } else {
-            LOG.warn("setSlaveRole: sessionContext is not set. Session might have been removed");
+            LOG.warn("setSlaveRole: sessionContext is not set. Device is not connected anymore");
         }
     }
 
@@ -218,13 +218,12 @@ public class OfEntityManager implements TransactionChainListener{
                 sendNodeAddedNotification(entsession.get(entity));
                 if(ownershipChange.wasOwner()) {
                     deregisterRoutedRPCForSwitch(entsession.get(entity));
-                    // You don't have to explictly set role to Slave in this case,
+                    // You don't have to explicitly set role to Slave in this case,
                     // because other controller will be taking over the master role
                     // and that will force other controller to become slave.
                 }
-                return;
             }
-
+            return;
         }
         if (sessionContext != null) {
             //Register the RPC, given *this* controller instance is going to be master owner.
@@ -292,8 +291,11 @@ public class OfEntityManager implements TransactionChainListener{
                 }
             });
         } else {
-            LOG.warn("onDeviceOwnershipChanged: sessionContext is not set. " +
-                    "Session might have been removed {}", entity);
+            LOG.warn("onDeviceOwnershipChanged: sessionContext is not available. Releasing ownership of the device");
+            EntityOwnershipCandidateRegistration ownershipRegistrent = entRegistrationMap.get(entity);
+            if (ownershipRegistrent != null) {
+                ownershipRegistrent.close();
+            }
         }
     }
 
@@ -360,6 +362,9 @@ public class OfEntityManager implements TransactionChainListener{
 
         entityMetadata.getContext().getNotificationEnqueuer().enqueueNotification(
                 entityMetadata.getWrappedNotification());
+
+        //Send multipart request to get other details of the switch.
+        entityMetadata.getOfSwitch().requestSwitchDetails();
     }
 
     private class MDSwitchMetaData {
index df42e34ccdb838169cbc8222f71dc58917ccfa71..aee9dffc1e2f408bac254a6b4d5a47562c48501b 100644 (file)
@@ -14,10 +14,10 @@ import com.google.common.util.concurrent.Futures;
 import com.google.common.util.concurrent.ListenableFuture;
 
 import java.math.BigInteger;
-import java.util.concurrent.ExecutionException;
 import java.util.concurrent.Future;
 import java.util.concurrent.TimeUnit;
 import org.opendaylight.controller.sal.binding.api.NotificationProviderService;
+import org.opendaylight.openflowplugin.api.OFConstants;
 import org.opendaylight.openflowplugin.api.openflow.md.core.SwitchConnectionDistinguisher;
 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.PacketOutConvertor;
 import org.opendaylight.openflowplugin.api.openflow.md.core.session.IMessageDispatchService;
@@ -78,6 +78,8 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev13
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MultipartType;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartRequestInputBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.PacketOutInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.multipart.request.body.MultipartRequestDescCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.multipart.request.body.MultipartRequestPortDescCaseBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.multipart.request.body.MultipartRequestTableFeaturesCaseBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.multipart.request.body.multipart.request.table.features._case.MultipartRequestTableFeaturesBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.ConnectionCookie;
@@ -492,7 +494,6 @@ public class ModelDrivenSwitchImpl extends AbstractModelDrivenSwitch {
         OFRpcTask<SetConfigInput, RpcResult<SetConfigOutput>> task = OFRpcTaskFactory.createSetNodeConfigTask(rpcTaskContext, input, null);
         return task.submit();
     }
-
     @Override
     public Optional<BigInteger> sendEmptyTableFeatureRequest() {
         LOG.debug("Send table feature request to {}",nodeId);
@@ -518,4 +519,38 @@ public class ModelDrivenSwitchImpl extends AbstractModelDrivenSwitch {
 
     }
 
+    @Override
+    public void requestSwitchDetails(){
+        // post-handshake actions
+        if (version == OFConstants.OFP_VERSION_1_3) {
+            requestPorts();
+        }
+
+        requestDesc();
+    }
+
+    /*
+     * Send an OFPMP_DESC request message to the switch
+     */
+    private void requestDesc() {
+        MultipartRequestInputBuilder builder = new MultipartRequestInputBuilder();
+        builder.setType(MultipartType.OFPMPDESC);
+        builder.setVersion(version);
+        builder.setFlags(new MultipartRequestFlags(false));
+        builder.setMultipartRequestBody(new MultipartRequestDescCaseBuilder()
+                .build());
+        builder.setXid(getSessionContext().getNextXid());
+        rpcTaskContext.getSession().getPrimaryConductor().getConnectionAdapter().multipartRequest(builder.build());
+    }
+
+    private void requestPorts() {
+        MultipartRequestInputBuilder builder = new MultipartRequestInputBuilder();
+        builder.setType(MultipartType.OFPMPPORTDESC);
+        builder.setVersion(version);
+        builder.setFlags(new MultipartRequestFlags(false));
+        builder.setMultipartRequestBody(new MultipartRequestPortDescCaseBuilder()
+                .build());
+        builder.setXid(getSessionContext().getNextXid());
+        rpcTaskContext.getSession().getPrimaryConductor().getConnectionAdapter().multipartRequest(builder.build());
+    }
 }
index 51d9d3dda969c291ffec73f4a269bd0d8dd48745..ed5cd2fe6e1991e1a0c2c5d42f1039f21dd84e60 100644 (file)
@@ -157,6 +157,8 @@ public class RolePushTask implements Callable<Boolean> {
         }
 
         // here we expect that role on device is successfully possessed
+        LOG.info("Successfully pushing {} role to the device openflow:{}",
+                role==OfpRole.BECOMEMASTER?"MASTER":"SLAVE", dpId);
         return true;
     }
 }
index 78b35752d278f1dea7d20a33929ebbac2f1985de..36e4dec0495aa748f03fb10e87903408eb07ee66 100644 (file)
@@ -263,8 +263,6 @@ public class ConnectionConductorImplTest {
                 EventFactory.DEFAULT_VERSION, getFeatureResponseMsg()));
 
         int i = 1;
-        eventPlan.add(0, EventFactory.createDefaultWaitForRpcEvent(i++, "multipartRequestInput"));
-        eventPlan.add(0, EventFactory.createDefaultWaitForRpcEvent(i++, "multipartRequestInput"));
         executeNow();
 
         Assert.assertEquals(ConnectionConductor.CONDUCTOR_STATE.WORKING,
@@ -289,10 +287,6 @@ public class ConnectionConductorImplTest {
         eventPlan.add(0, EventFactory.createDefaultRpcResponseEvent(43,
                 EventFactory.DEFAULT_VERSION, getFeatureResponseMsg()));
 
-        int i = 1;
-        eventPlan.add(0, EventFactory.createDefaultWaitForRpcEvent(i++, "multipartRequestInput"));
-        eventPlan.add(0, EventFactory.createDefaultWaitForRpcEvent(i++, "multipartRequestInput"));
-
         executeNow();
 
         Assert.assertEquals(ConnectionConductor.CONDUCTOR_STATE.WORKING,
@@ -327,9 +321,6 @@ public class ConnectionConductorImplTest {
         eventPlan.add(0, EventFactory.createDefaultRpcResponseEvent(45,
                 (short) 0x01, getFeatureResponseMsg()));
 
-        int i = 1;
-        eventPlan.add(0, EventFactory.createDefaultWaitForRpcEvent(i++, "multipartRequestInput"));
-
         executeNow();
 
         Assert.assertEquals(ConnectionConductor.CONDUCTOR_STATE.WORKING,
@@ -365,9 +356,6 @@ public class ConnectionConductorImplTest {
         eventPlan.add(0, EventFactory.createDefaultRpcResponseEvent(45,
                 (short) 0x01, getFeatureResponseMsg()));
 
-        int i = 1;
-        eventPlan.add(0, EventFactory.createDefaultWaitForRpcEvent(i++, "multipartRequestInput"));
-
         executeNow();
 
         Assert.assertEquals(ConnectionConductor.CONDUCTOR_STATE.WORKING,