In the case when sync msg failed, the returned error msg is listened by both sync...
[controller.git] / opendaylight / protocol_plugins / openflow / src / main / java / org / opendaylight / controller / protocol_plugin / openflow / internal / FlowProgrammerService.java
index 230376555eb556a58ecee41892e3cde47b7aa5c0..d473a462c410332781b906c743804bca54d3da8a 100644 (file)
@@ -72,6 +72,7 @@ public class FlowProgrammerService implements IPluginInFlowProgrammerService,
     public FlowProgrammerService() {
         controller = null;
         flowProgrammerNotifiers = new ConcurrentHashMap<String, IFlowProgrammerNotifier>();
+        containerToNc = new HashMap<String, Set<NodeConnector>>();
         xid2rid = new ConcurrentHashMap<Long, Map<Integer, Long>>();
     }
 
@@ -116,6 +117,7 @@ public class FlowProgrammerService implements IPluginInFlowProgrammerService,
      */
     void init() {
         this.controller.addMessageListener(OFType.FLOW_REMOVED, this);
+        this.controller.addMessageListener(OFType.ERROR, this);
         registerWithOSGIConsole();
     }
 
@@ -397,6 +399,8 @@ public class FlowProgrammerService implements IPluginInFlowProgrammerService,
     public void receive(ISwitch sw, OFMessage msg) {
         if (msg instanceof OFFlowRemoved) {
             handleFlowRemovedMessage(sw, (OFFlowRemoved) msg);
+        } else if (msg instanceof OFError) {
+            handleErrorMessage(sw, (OFError) msg);
         }
     }
 
@@ -431,6 +435,37 @@ public class FlowProgrammerService implements IPluginInFlowProgrammerService,
         }
     }
 
+    private void handleErrorMessage(ISwitch sw, OFError errorMsg) {
+        Node node = NodeCreator.createOFNode(sw.getId());
+        OFMessage offendingMsg = errorMsg.getOffendingMsg();
+        Integer xid;
+        if (offendingMsg != null) {
+            xid = offendingMsg.getXid();
+        } else {
+            xid = errorMsg.getXid();
+        }
+
+        Long rid = getMessageRid(sw.getId(), xid);
+        /*
+         * Null or zero requestId indicates that the error message is meant for
+         * a sync message. It will be handled by the sync message worker thread.
+         * Hence we are done here.
+         */
+        if ((rid == null) || (rid == 0)) {
+            return;
+        }
+        
+        /*
+         * Notifies the caller that error has been reported for a previous flow
+         * programming request
+         */
+        for (Map.Entry<String, IFlowProgrammerNotifier> containerNotifier : flowProgrammerNotifiers
+                .entrySet()) {
+            IFlowProgrammerNotifier notifier = containerNotifier.getValue();
+            notifier.flowErrorReported(node, rid, errorMsg);
+        }
+    }
+
     @Override
     public void tagUpdated(String containerName, Node n, short oldTag,
             short newTag, UpdateType t) {
@@ -563,10 +598,14 @@ public class FlowProgrammerService implements IPluginInFlowProgrammerService,
      *            The OF message xid
      * @return The Request ID
      */
-    public long getMessageRid(long swid, int xid) {
+    private Long getMessageRid(long swid, Integer xid) {
+        Long rid = null;
+
+        if (xid == null) {
+            return rid;
+        }
+
         Map<Integer, Long> swxid2rid = this.xid2rid.get(swid);
-        long rid = 0;
-        
         if (swxid2rid != null) {
             rid = swxid2rid.get(xid);
         }