Updated flow decomposer to del flows that fail to decompose'.

 Changes to be committed:
	modified:   voltha/core/flow_decomposer.py
	modified:   voltha/core/logical_device_agent.py

 Updated to delete flows from logical device that fail to decompose. This will
 allows ONOS handle (resend) and follows normal openflow switch behavior.

Change-Id: Ic8e7f20e6190c5b27e8a0edadedc50a7e3afca79
diff --git a/voltha/core/flow_decomposer.py b/voltha/core/flow_decomposer.py
index d123743..726e8df 100644
--- a/voltha/core/flow_decomposer.py
+++ b/voltha/core/flow_decomposer.py
@@ -511,7 +511,8 @@
         route = self.get_route(in_port_no, out_port_no)
         if route is None:
             log.error('no-route', in_port_no=in_port_no,
-                      out_port_no=out_port_no, comment='ignoring flow')
+                      out_port_no=out_port_no, comment='deleting flow')
+            self.flow_delete(flow)
             return device_rules
 
         assert len(route) == 2
@@ -637,7 +638,8 @@
                         route = self.get_route(in_port_no, inner_tag)
                         if route is None:
                             log.error('no-route-double-tag', in_port_no=in_port_no,
-                                      out_port_no=inner_tag, comment='ignoring flow')
+                                      out_port_no=inner_tag, comment='deleting flow')
+                            self.flow_delete(flow)
                             return device_rules
                         assert len(route) == 2
                         ingress_hop, egress_hop = route
@@ -724,7 +726,8 @@
                         if route2 is None:
                             log.error('mc-no-route', in_port_no=in_port_no,
                                 out_port_no=out_port_no, route2=route2,
-                                comment='ignoring flow')
+                                comment='deleting flow')
+                            self.flow_delete(flow)
                             continue
 
                         assert len(route2) == 2
@@ -762,3 +765,7 @@
 
     def get_wildcard_input_ports(self, exclude_port=None):
         raise NotImplementedError('derived class must provide')
+
+    def flow_delete(self, mod):
+        raise NotImplementedError('derived class must provide')
+        
diff --git a/voltha/core/logical_device_agent.py b/voltha/core/logical_device_agent.py
index c6bd3e8..5949372 100644
--- a/voltha/core/logical_device_agent.py
+++ b/voltha/core/logical_device_agent.py
@@ -210,7 +210,7 @@
             self.flows_proxy.update('/', Flows(items=flows))
 
     def flow_delete(self, mod):
-        assert isinstance(mod, ofp.ofp_flow_mod)
+        assert isinstance(mod, (ofp.ofp_flow_mod, ofp.ofp_flow_stats))
 
         # read from model
         flows = list(self.flows_proxy.get('/').items)
@@ -231,8 +231,10 @@
         if to_delete:
             self.flows_proxy.update('/', Flows(items=flows))
 
-        # send notifications for discarded flow as required by OpenFlow
-        self.announce_flows_deleted(to_delete)
+        # from mod send announcement
+        if isinstance(mod, ofp.ofp_flow_mod):
+            # send notifications for discarded flow as required by OpenFlow
+            self.announce_flows_deleted(to_delete)
 
     def flow_delete_strict(self, mod):
         assert isinstance(mod, ofp.ofp_flow_mod)
@@ -298,7 +300,10 @@
         """
 
         assert isinstance(flow, ofp.ofp_flow_stats)
-        assert isinstance(flow_mod, ofp.ofp_flow_mod)
+        assert isinstance(flow_mod, (ofp.ofp_flow_mod, ofp.ofp_flow_stats))
+
+        if isinstance(flow_mod, ofp.ofp_flow_stats):
+            return cls.flow_match(flow, flow_mod)
 
         # Check if flow.cookie is covered by mod.cookie and mod.cookie_mask
         if (flow.cookie & flow_mod.cookie_mask) != \
@@ -319,7 +324,6 @@
         if (flow_mod.out_group & 0x7fffffff) != ofp.OFPG_ANY and \
                 not cls.flow_has_out_group(flow, flow_mod.out_group):
             return False
-
         # Priority is ignored
 
         # Check match condition