Bug 4988: OF statistics & REST client 81/31681/34
authorMatej Perina <matej.perina@pantheon.sk>
Wed, 24 Feb 2016 09:32:37 +0000 (10:32 +0100)
committerMatej Perina <matej.perina@pantheon.sk>
Wed, 24 Feb 2016 09:32:37 +0000 (10:32 +0100)
Change-Id: I48c8302196f997abf6c6180e36beae5886d7be48
Signed-off-by: Konstantin Blagov <kblagov@cisco.com>
Signed-off-by: Keith Burns (alagalah) <alagalah@gmail.com>
Signed-off-by: Martin Sunal <msunal@cisco.com>
Signed-off-by: Matej Perina <matej.perina@pantheon.sk>
54 files changed:
demos/gbpsfc-env/.gitignore [changed mode: 0644->0755]
demos/gbpsfc-env/cleandemo.sh
demos/gbpsfc-env/demo-asymmetric-chain/rest.py
demos/gbpsfc-env/demo-asymmetric-coexistence/rest.py
demos/gbpsfc-env/demo-gbp1/infrastructure_config.py
demos/gbpsfc-env/demo-gbp1/rest.py
demos/gbpsfc-env/demo-gbp2/get-nsps.py [new file with mode: 0755]
demos/gbpsfc-env/demo-gbp2/infrastructure_config.py [new file with mode: 0755]
demos/gbpsfc-env/demo-gbp2/rest.py [new file with mode: 0755]
demos/gbpsfc-env/demo-symmetric-chain/rest.py
demos/gbpsfc-env/demo-symmetric-coexistence/rest.py
demos/gbpsfc-env/infrastructure_launch.py
demos/gbpsfc-env/install_java.sh [new file with mode: 0755]
demos/gbpsfc-env/sflow/.gitignore [new file with mode: 0755]
demos/gbpsfc-env/sflow/README
demos/gbpsfc-env/sflow/install_sflow-rt.sh [new file with mode: 0755]
demos/gbpsfc-env/sflow/internal_settings.sh [moved from demos/gbpsfc-env/sflow/internal_settings with 80% similarity]
demos/gbpsfc-env/sflow/internal_start.sh [moved from demos/gbpsfc-env/sflow/internal_start with 81% similarity]
demos/gbpsfc-env/sflow/internal_stop.sh [moved from demos/gbpsfc-env/sflow/internal_stop with 58% similarity]
demos/gbpsfc-env/sflow/set_collector_ip.sh [new file with mode: 0755]
demos/gbpsfc-env/sflow/settings.sh [moved from demos/gbpsfc-env/sflow/settings with 65% similarity]
demos/gbpsfc-env/sflow/start
demos/gbpsfc-env/sflow/stop
demos/gbpsfc-env/sflow/stop_sflow-rt.sh [new file with mode: 0755]
features/src/main/features/features.xml
groupbasedpolicy/src/main/java/org/opendaylight/groupbasedpolicy/resolver/PolicyResolver.java
groupbasedpolicy/src/main/java/org/opendaylight/groupbasedpolicy/statistics/StatisticsManagerImpl.java [changed mode: 0644->0755]
groupbasedpolicy/src/test/java/org/opendaylight/groupbasedpolicy/statistics/StatisticManagerImplTest.java [changed mode: 0644->0755]
renderers/ofoverlay/pom.xml
renderers/ofoverlay/src/main/config/default-config.xml [changed mode: 0644->0755]
renderers/ofoverlay/src/main/java/org/opendaylight/controller/config/yang/config/ofoverlay_provider/impl/OFOverlayProviderModule.java [changed mode: 0644->0755]
renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/OFOverlayRenderer.java [changed mode: 0644->0755]
renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/PolicyManager.java
renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/endpoint/EndpointManager.java [changed mode: 0644->0755]
renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/statistics/JsonRestClient.java [new file with mode: 0755]
renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/statistics/JsonRestClientResponse.java [new file with mode: 0644]
renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/statistics/OFStatisticsManager.java [new file with mode: 0755]
renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/statistics/ProcessDataTask.java [new file with mode: 0755]
renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/statistics/ReadGbpFlowCacheTask.java [new file with mode: 0755]
renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/statistics/ResolvedPolicyClassifierListener.java [new file with mode: 0644]
renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/statistics/SFlowRTConnection.java [new file with mode: 0755]
renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/statistics/SflowClientSettingsListener.java [new file with mode: 0755]
renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/statistics/flowcache/FlowCache.java [new file with mode: 0755]
renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/statistics/flowcache/FlowCacheData.java [new file with mode: 0755]
renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/statistics/flowcache/FlowCacheDefinition.java [new file with mode: 0755]
renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/statistics/flowcache/FlowCacheFactory.java [new file with mode: 0644]
renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/statistics/flowcache/FlowCacheFilter.java [new file with mode: 0644]
renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/statistics/flowcache/FlowCacheKeys.java [new file with mode: 0644]
renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/statistics/util/FlowCacheCons.java [new file with mode: 0644]
renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/statistics/util/IidSflowNameUtil.java [new file with mode: 0644]
renderers/ofoverlay/src/main/yang/ofoverlay-provider-impl.yang [changed mode: 0644->0755]
renderers/ofoverlay/src/main/yang/ofoverlay.yang [changed mode: 0644->0755]
renderers/ofoverlay/src/test/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/OFOverlayRendererTest.java [changed mode: 0644->0755]
renderers/ofoverlay/src/test/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/endpoint/EndpointManagerTest.java

old mode 100644 (file)
new mode 100755 (executable)
index 0c9bef2..439d707
@@ -1,6 +1,6 @@
 .vagrant
 *.pyc
 .vagrant
 *.pyc
-get-nsps.py
-infrastructure_config.py
+/get-nsps.py
+/infrastructure_config.py
 demo.lock
 
 demo.lock
 
index 64b95ec1cd5529c8d44669d40e89fa8d91d27ae7..5e8b5762d5d3d12a8d7ec6be877f6b0d79c34c48 100755 (executable)
@@ -5,10 +5,10 @@ for i in `seq 1 $NUM_NODES`; do
   hostname="gbpsfc"$i
   switchname="sw"$i
   echo $hostname
   hostname="gbpsfc"$i
   switchname="sw"$i
   echo $hostname
-  vagrant ssh $hostname -c "sudo ovs-vsctl del-br $switchname; sudo ovs-vsctl del-manager; sudo /vagrant/vmclean.sh"
+  vagrant ssh $hostname -c "sudo ovs-vsctl del-br $switchname; sudo ovs-vsctl del-manager; sudo /vagrant/vmclean.sh; sudo /vagrant/sflow/stop_sflow-rt.sh  >/dev/null 2>&1"
 
 done
 
 done
+
 ./rest-clean.py
 
 if [ -f "demo.lock" ] ; then
 ./rest-clean.py
 
 if [ -f "demo.lock" ] ; then
index e2438a1c788c8f51a27d5c8e5f5e3162f74e8f6c..baf88ba840d5b2b59a26637dfb5573fd932532d9 100755 (executable)
@@ -375,8 +375,14 @@ def get_tenant_data():
                           "order": 0,
                           "classifier-ref": [
                             {
                           "order": 0,
                           "classifier-ref": [
                             {
-                              "name": "icmp",
-                              "instance-name": "icmp"
+                              "name": "icmp-in",
+                              "instance-name": "icmp",
+                              "direction": "in"
+                            },
+                            {
+                              "name": "icmp-out",
+                              "instance-name": "icmp",
+                              "direction": "out"
                             }
                           ],
                           "action-ref": [
                             }
                           ],
                           "action-ref": [
index 722f6b589c9e07d69554510e95e36e1941ed1080..41264d665b54cc4a1149e7027c6548338659b10c 100644 (file)
@@ -375,8 +375,14 @@ def get_tenant_data():
                           "order": 0,
                           "classifier-ref": [
                             {
                           "order": 0,
                           "classifier-ref": [
                             {
-                              "name": "icmp",
-                              "instance-name": "icmp"
+                              "name": "icmp-in",
+                              "instance-name": "icmp",
+                              "direction": "in"
+                            },
+                            {
+                              "name": "icmp-out",
+                              "instance-name": "icmp",
+                              "direction": "out"
                             }
                           ],
                           "action-ref": [
                             }
                           ],
                           "action-ref": [
index cc33d253e71af3d87e0ffba4729f18715fd13543..a05ecf610fe56816e99add3e645d04ef3dd917b0 100755 (executable)
@@ -10,7 +10,7 @@ switches = [
              'type': 'gbp',
              'dpid': '3'},
             {'name': 'sw4',
              'type': 'gbp',
              'dpid': '3'},
             {'name': 'sw4',
-             'type': 'none',
+             'type': 'sflow',
              'dpid': '4'},
             {'name': 'sw5',
              'type': 'none',
              'dpid': '4'},
             {'name': 'sw5',
              'type': 'none',
index 35fceb86581f65788556bdad4e62ddaf441bb48e..7c7f4993e9d11c3e64f5d891a24e1e14674d1546 100755 (executable)
@@ -53,7 +53,7 @@ def post(host, port, uri, data, debug=False):
     if debug == True:
         print r.text
     r.raise_for_status()
     if debug == True:
         print r.text
     r.raise_for_status()
-    
+
 
 def get_tenant_data():
     return {
 
 def get_tenant_data():
     return {
@@ -143,8 +143,14 @@ def get_tenant_data():
                       {
                         "classifier-ref": [
                           {
                       {
                         "classifier-ref": [
                           {
-                            "name": "icmp",
-                            "instance-name": "icmp"
+                            "name": "icmp-in",
+                            "instance-name": "icmp",
+                            "direction": "in"
+                          },
+                          {
+                            "name": "icmp-out",
+                            "instance-name": "icmp",
+                            "direction": "out"
                           }
                         ],
                         "action-ref": [
                           }
                         ],
                         "action-ref": [
@@ -239,17 +245,17 @@ def get_tenant_data():
     }
 
 # Main definition - constants
     }
 
 # Main definition - constants
+
 # =======================
 #     MENUS FUNCTIONS
 # =======================
 # =======================
 #     MENUS FUNCTIONS
 # =======================
+
 # Main menu
 
 # =======================
 #      MAIN PROGRAM
 # =======================
 # Main menu
 
 # =======================
 #      MAIN PROGRAM
 # =======================
+
 # Main Program
 
 def get_tenant_uri():
 # Main Program
 
 def get_tenant_uri():
@@ -311,11 +317,11 @@ def get_tunnel_data():
           }
         ]
       },
           }
         ]
       },
-             
+
     ]
   }
             }
     ]
   }
             }
-    
+
 def get_tunnel_uri():
     return "/restconf/config/opendaylight-inventory:nodes"
 
 def get_tunnel_uri():
     return "/restconf/config/opendaylight-inventory:nodes"
 
@@ -323,159 +329,159 @@ def get_endpoint_data():
     return [{
     "input": {
 
     return [{
     "input": {
 
-        "endpoint-group": "clients", 
+        "endpoint-group": "clients",
 
         "network-containment" : "subnet-10.0.35.0/24",
 
 
         "network-containment" : "subnet-10.0.35.0/24",
 
-        "l2-context": "bridge-domain1", 
-        "mac-address": "00:00:00:00:35:02", 
+        "l2-context": "bridge-domain1",
+        "mac-address": "00:00:00:00:35:02",
 
         "l3-address": [
             {
 
         "l3-address": [
             {
-                "ip-address": "10.0.35.2", 
+                "ip-address": "10.0.35.2",
                 "l3-context": "l3-context-vrf-red"
             }
                 "l3-context": "l3-context-vrf-red"
             }
-        ], 
-        "port-name": "vethl-h35_2", 
+        ],
+        "port-name": "vethl-h35_2",
         "tenant": "tenant-red"
     }
 },
             {
     "input": {
 
         "tenant": "tenant-red"
     }
 },
             {
     "input": {
 
-        "endpoint-group": "clients", 
+        "endpoint-group": "clients",
 
         "network-containment" : "subnet-10.0.35.0/24",
 
 
         "network-containment" : "subnet-10.0.35.0/24",
 
-        "l2-context": "bridge-domain1", 
-        "mac-address": "00:00:00:00:35:03", 
+        "l2-context": "bridge-domain1",
+        "mac-address": "00:00:00:00:35:03",
 
         "l3-address": [
             {
 
         "l3-address": [
             {
-                "ip-address": "10.0.35.3", 
+                "ip-address": "10.0.35.3",
                 "l3-context": "l3-context-vrf-red"
             }
                 "l3-context": "l3-context-vrf-red"
             }
-        ], 
-        "port-name": "vethl-h35_3", 
+        ],
+        "port-name": "vethl-h35_3",
         "tenant": "tenant-red"
     }
 },
             {
     "input": {
 
         "tenant": "tenant-red"
     }
 },
             {
     "input": {
 
-        "endpoint-group": "clients", 
+        "endpoint-group": "clients",
 
         "network-containment" : "subnet-10.0.35.0/24",
 
 
         "network-containment" : "subnet-10.0.35.0/24",
 
-        "l2-context": "bridge-domain1", 
-        "mac-address": "00:00:00:00:35:04", 
+        "l2-context": "bridge-domain1",
+        "mac-address": "00:00:00:00:35:04",
 
         "l3-address": [
             {
 
         "l3-address": [
             {
-                "ip-address": "10.0.35.4", 
+                "ip-address": "10.0.35.4",
                 "l3-context": "l3-context-vrf-red"
             }
                 "l3-context": "l3-context-vrf-red"
             }
-        ], 
-        "port-name": "vethl-h35_4", 
+        ],
+        "port-name": "vethl-h35_4",
         "tenant": "tenant-red"
     }
 },
             {
     "input": {
 
         "tenant": "tenant-red"
     }
 },
             {
     "input": {
 
-        "endpoint-group": "clients", 
+        "endpoint-group": "clients",
 
         "network-containment" : "subnet-10.0.35.0/24",
 
 
         "network-containment" : "subnet-10.0.35.0/24",
 
-        "l2-context": "bridge-domain1", 
-        "mac-address": "00:00:00:00:35:05", 
+        "l2-context": "bridge-domain1",
+        "mac-address": "00:00:00:00:35:05",
 
         "l3-address": [
             {
 
         "l3-address": [
             {
-                "ip-address": "10.0.35.5", 
+                "ip-address": "10.0.35.5",
                 "l3-context": "l3-context-vrf-red"
             }
                 "l3-context": "l3-context-vrf-red"
             }
-        ], 
-        "port-name": "vethl-h35_5", 
+        ],
+        "port-name": "vethl-h35_5",
         "tenant": "tenant-red"
     }
 },
             {
     "input": {
 
         "tenant": "tenant-red"
     }
 },
             {
     "input": {
 
-        "endpoint-group": "webservers", 
+        "endpoint-group": "webservers",
 
         "network-containment" : "subnet-10.0.36.0/24",
 
 
         "network-containment" : "subnet-10.0.36.0/24",
 
-        "l2-context": "bridge-domain1", 
-        "mac-address": "00:00:00:00:36:02", 
+        "l2-context": "bridge-domain1",
+        "mac-address": "00:00:00:00:36:02",
 
         "l3-address": [
             {
 
         "l3-address": [
             {
-                "ip-address": "10.0.36.2", 
+                "ip-address": "10.0.36.2",
                 "l3-context": "l3-context-vrf-red"
             }
                 "l3-context": "l3-context-vrf-red"
             }
-        ], 
-        "port-name": "vethl-h36_2", 
+        ],
+        "port-name": "vethl-h36_2",
         "tenant": "tenant-red"
     }
 },
             {
     "input": {
 
         "tenant": "tenant-red"
     }
 },
             {
     "input": {
 
-        "endpoint-group": "webservers", 
+        "endpoint-group": "webservers",
 
         "network-containment" : "subnet-10.0.36.0/24",
 
 
         "network-containment" : "subnet-10.0.36.0/24",
 
-        "l2-context": "bridge-domain1", 
-        "mac-address": "00:00:00:00:36:03", 
+        "l2-context": "bridge-domain1",
+        "mac-address": "00:00:00:00:36:03",
 
         "l3-address": [
             {
 
         "l3-address": [
             {
-                "ip-address": "10.0.36.3", 
+                "ip-address": "10.0.36.3",
                 "l3-context": "l3-context-vrf-red"
             }
                 "l3-context": "l3-context-vrf-red"
             }
-        ], 
-        "port-name": "vethl-h36_3", 
+        ],
+        "port-name": "vethl-h36_3",
         "tenant": "tenant-red"
     }
 },
             {
     "input": {
 
         "tenant": "tenant-red"
     }
 },
             {
     "input": {
 
-        "endpoint-group": "webservers", 
+        "endpoint-group": "webservers",
 
         "network-containment" : "subnet-10.0.36.0/24",
 
 
         "network-containment" : "subnet-10.0.36.0/24",
 
-        "l2-context": "bridge-domain1", 
-        "mac-address": "00:00:00:00:36:04", 
+        "l2-context": "bridge-domain1",
+        "mac-address": "00:00:00:00:36:04",
 
         "l3-address": [
             {
 
         "l3-address": [
             {
-                "ip-address": "10.0.36.4", 
+                "ip-address": "10.0.36.4",
                 "l3-context": "l3-context-vrf-red"
             }
                 "l3-context": "l3-context-vrf-red"
             }
-        ], 
-        "port-name": "vethl-h36_4", 
+        ],
+        "port-name": "vethl-h36_4",
         "tenant": "tenant-red"
     }
 },{
     "input": {
 
         "tenant": "tenant-red"
     }
 },{
     "input": {
 
-        "endpoint-group": "webservers", 
+        "endpoint-group": "webservers",
 
         "network-containment" : "subnet-10.0.36.0/24",
 
 
         "network-containment" : "subnet-10.0.36.0/24",
 
-        "l2-context": "bridge-domain1", 
-        "mac-address": "00:00:00:00:36:05", 
+        "l2-context": "bridge-domain1",
+        "mac-address": "00:00:00:00:36:05",
 
         "l3-address": [
             {
 
         "l3-address": [
             {
-                "ip-address": "10.0.36.5", 
+                "ip-address": "10.0.36.5",
                 "l3-context": "l3-context-vrf-red"
             }
                 "l3-context": "l3-context-vrf-red"
             }
-        ], 
-        "port-name": "vethl-h36_5", 
+        ],
+        "port-name": "vethl-h36_5",
         "tenant": "tenant-red"
     }
 }]
         "tenant": "tenant-red"
     }
 }]
@@ -491,12 +497,12 @@ if __name__ == "__main__":
     controller=os.environ.get('ODL')
     if controller == None:
         sys.exit("No controller set.")
     controller=os.environ.get('ODL')
     if controller == None:
         sys.exit("No controller set.")
-    
+
 
     print "tenants"
     tenants=get(controller,DEFAULT_PORT,CONF_TENANT)
     print tenants
 
     print "tenants"
     tenants=get(controller,DEFAULT_PORT,CONF_TENANT)
     print tenants
-    
+
     print "sending tenant"
     put(controller, DEFAULT_PORT, get_tenant_uri(), get_tenant_data(),True)
     print "sending tunnel"
     print "sending tenant"
     put(controller, DEFAULT_PORT, get_tenant_uri(), get_tenant_data(),True)
     print "sending tunnel"
@@ -504,7 +510,7 @@ if __name__ == "__main__":
     print "registering endpoints"
     for endpoint in get_endpoint_data():
         post(controller, DEFAULT_PORT, get_endpoint_uri(),endpoint,True)
     print "registering endpoints"
     for endpoint in get_endpoint_data():
         post(controller, DEFAULT_PORT, get_endpoint_uri(),endpoint,True)
-        
-        
-    
-    
+
+
+
+
diff --git a/demos/gbpsfc-env/demo-gbp2/get-nsps.py b/demos/gbpsfc-env/demo-gbp2/get-nsps.py
new file mode 100755 (executable)
index 0000000..c8ac97c
--- /dev/null
@@ -0,0 +1,8 @@
+#!/usr/bin/python
+
+if __name__ == "__main__":
+    # Launch main menu
+
+
+    # Some sensible defaults
+    print "Nothing"
diff --git a/demos/gbpsfc-env/demo-gbp2/infrastructure_config.py b/demos/gbpsfc-env/demo-gbp2/infrastructure_config.py
new file mode 100755 (executable)
index 0000000..09eb1f9
--- /dev/null
@@ -0,0 +1,67 @@
+# Config for switches, tunnelIP is the local IP address.
+switches = [
+            {'name': 'sw1',
+             'type': 'gbp',
+             'dpid': '1'},
+            {'name': 'sw2',
+             'type': 'gbp',
+             'dpid': '2'},
+            {'name': 'sw3',
+             'type': 'sflow',
+             'dpid': '3'},
+            {'name': 'sw4',
+             'type': 'none',
+             'dpid': '4'},
+            {'name': 'sw5',
+             'type': 'none',
+             'dpid': '5'},
+            {'name': 'sw6',
+             'type': 'none',
+             'dpid': '6'},
+            {'name': 'sw7',
+             'type': 'none',
+             'dpid': '7'},
+            {'name': 'sw8',
+             'type': 'none',
+             'dpid': '8'}
+           ]
+
+defaultContainerImage='alagalah/odlpoc_ovs230'
+#defaultContainerImage='ubuntu:14.04'
+
+#Note that tenant name and endpointGroup name come from policy_config.py
+
+hosts = [{'name': 'h35_2',
+          'mac': '00:00:00:00:35:02',
+          'ip': '10.0.35.2/24',
+          'switch': 'sw1'},
+         {'name': 'h35_3',
+          'ip': '10.0.35.3/24',
+          'mac': '00:00:00:00:35:03',
+          'switch': 'sw1'},
+         {'name': 'h35_4',
+          'ip': '10.0.35.4/24',
+          'mac': '00:00:00:00:35:04',
+          'switch': 'sw1'},
+         {'name': 'h35_5',
+          'ip': '10.0.35.5/24',
+          'mac': '00:00:00:00:35:05',
+          'switch': 'sw1'},
+         {'name': 'h36_2',
+          'ip': '10.0.36.2/24',
+          'mac': '00:00:00:00:36:02',
+          'switch': 'sw2'},
+         {'name': 'h36_3',
+          'ip': '10.0.36.3/24',
+          'mac': '00:00:00:00:36:03',
+          'switch': 'sw2'},
+         {'name': 'h36_4',
+          'ip': '10.0.36.4/24',
+          'mac': '00:00:00:00:36:04',
+          'switch': 'sw2'},
+         {'name': 'h36_5',
+          'ip': '10.0.36.5/24',
+          'mac': '00:00:00:00:36:05',
+          'switch': 'sw2'}
+          ]
+
diff --git a/demos/gbpsfc-env/demo-gbp2/rest.py b/demos/gbpsfc-env/demo-gbp2/rest.py
new file mode 100755 (executable)
index 0000000..d08aa82
--- /dev/null
@@ -0,0 +1,528 @@
+#!/usr/bin/python
+import argparse
+import requests,json
+from requests.auth import HTTPBasicAuth
+from subprocess import call
+import time
+import sys
+import os
+
+
+DEFAULT_PORT='8181'
+
+
+USERNAME='admin'
+PASSWORD='admin'
+
+
+OPER_NODES='/restconf/operational/opendaylight-inventory:nodes/'
+CONF_TENANT='/restconf/config/policy:tenants'
+
+def get(host, port, uri):
+    url='http://'+host+":"+port+uri
+    #print url
+    r = requests.get(url, auth=HTTPBasicAuth(USERNAME, PASSWORD))
+    jsondata=json.loads(r.text)
+    return jsondata
+
+def put(host, port, uri, data, debug=False):
+    '''Perform a PUT rest operation, using the URL and data provided'''
+
+    url='http://'+host+":"+port+uri
+
+    headers = {'Content-type': 'application/yang.data+json',
+               'Accept': 'application/yang.data+json'}
+    if debug == True:
+        print "PUT %s" % url
+        print json.dumps(data, indent=4, sort_keys=True)
+    r = requests.put(url, data=json.dumps(data), headers=headers, auth=HTTPBasicAuth(USERNAME, PASSWORD))
+    if debug == True:
+        print r.text
+    r.raise_for_status()
+
+def post(host, port, uri, data, debug=False):
+    '''Perform a POST rest operation, using the URL and data provided'''
+
+    url='http://'+host+":"+port+uri
+    headers = {'Content-type': 'application/yang.data+json',
+               'Accept': 'application/yang.data+json'}
+    if debug == True:
+        print "POST %s" % url
+        print json.dumps(data, indent=4, sort_keys=True)
+    r = requests.post(url, data=json.dumps(data), headers=headers, auth=HTTPBasicAuth(USERNAME, PASSWORD))
+    if debug == True:
+        print r.text
+    r.raise_for_status()
+
+
+def get_tenant_data():
+    return {
+        "policy:tenant": {
+          "id": "tenant-red",
+          "name": "GBPPOC",
+          "forwarding-context": {
+            "l2-bridge-domain": [
+              {
+                "id": "bridge-domain1",
+                "parent": "l3-context-vrf-red"
+              }
+            ],
+            "l2-flood-domain": [
+              {
+                "id": "flood-domain-1",
+                "parent": "bridge-domain1"
+              },
+              {
+                "id": "flood-domain1",
+                "parent": "bridge-domain1"
+              }
+            ],
+            "l3-context": [
+              {
+                "id": "l3-context-vrf-red"
+              }
+            ],
+            "subnet": [
+              {
+                "id": "subnet-10.0.35.0/24",
+                "ip-prefix": "10.0.35.1/24",
+                "parent": "flood-domain-1",
+                "virtual-router-ip": "10.0.35.1"
+              },
+              {
+                "id": "subnet-10.0.36.0/24",
+                "ip-prefix": "10.0.36.1/24",
+                "parent": "flood-domain1",
+                "virtual-router-ip": "10.0.36.1"
+              }
+            ]
+          },
+          "policy": {
+            "contract": [
+              {
+                "clause": [
+                  {
+                    "name": "allow-http-clause",
+                    "subject-refs": [
+                      "allow-http-subject",
+                      "allow-icmp-subject"
+                    ]
+                  }
+                ],
+                "id": "icmp-http-contract",
+                "subject": [
+                  {
+                    "name": "allow-http-subject",
+                    "rule": [
+                      {
+                        "classifier-ref": [
+                          {
+                            "direction": "in",
+                            "name": "http-dest",
+                            "instance-name": "http-dest"
+                          },
+                          {
+                            "direction": "out",
+                            "name": "http-src",
+                            "instance-name": "http-src"
+                          }
+                        ],
+                        "action-ref": [
+                          {
+                            "name": "allow1",
+                            "order": 0
+                          }
+                        ],
+                        "name": "allow-http-rule"
+                      }
+                    ]
+                  },
+                  {
+                    "name": "allow-icmp-subject",
+                    "rule": [
+                      {
+                        "classifier-ref": [
+                          {
+                            "name": "icmp-in",
+                            "instance-name": "icmp",
+                            "direction": "in"
+                          },
+                          {
+                            "name": "icmp-out",
+                            "instance-name": "icmp",
+                            "direction": "out"
+                          }
+                        ],
+                        "action-ref": [
+                          {
+                            "name": "allow1",
+                            "order": 0
+                          }
+                        ],
+                        "name": "allow-icmp-rule"
+                      }
+                    ]
+                  }
+                ]
+              }
+            ],
+            "endpoint-group": [
+              {
+                "consumer-named-selector": [
+                  {
+                    "contract": [
+                      "icmp-http-contract"
+                    ],
+                    "name": "webservers-clients-icmp-http-contract"
+                  }
+                ],
+                "id": "clients",
+                "provider-named-selector": []
+              },
+              {
+                "consumer-named-selector": [],
+                "id": "webservers1",
+                "provider-named-selector": [
+                  {
+                    "contract": [
+                      "icmp-http-contract"
+                    ],
+                    "name": "webservers-clients-icmp-http-contract"
+                  }
+                ]
+              },
+              {
+                "consumer-named-selector": [],
+                "id": "webservers2",
+                "provider-named-selector": [
+                  {
+                    "contract": [
+                      "icmp-http-contract"
+                    ],
+                    "name": "webservers-clients-icmp-http-contract"
+                  }
+                ]
+              }
+            ],
+            "subject-feature-instances": {
+              "classifier-instance": [
+                {
+                  "classifier-definition-id": "Classifier-L4",
+                  "name": "http-dest",
+                  "parameter-value": [
+                    {
+                      "int-value": "6",
+                      "name": "proto"
+                    },
+                    {
+                      "int-value": "80",
+                      "name": "destport"
+                    }
+                  ]
+                },
+                {
+                  "classifier-definition-id": "Classifier-L4",
+                  "name": "http-src",
+                  "parameter-value": [
+                    {
+                      "int-value": "6",
+                      "name": "proto"
+                    },
+                    {
+                      "int-value": "80",
+                      "name": "sourceport"
+                    }
+                  ]
+                },
+                {
+                  "classifier-definition-id": "Classifier-IP-Protocol",
+                  "name": "icmp",
+                  "parameter-value": [
+                    {
+                      "int-value": "1",
+                      "name": "proto"
+                    }
+                  ]
+                }
+              ],
+              "action-instance": [
+                {
+                  "name": "allow1",
+                  "action-definition-id": "Action-Allow"
+                }
+              ]
+            }
+          }
+        }
+    }
+
+# Main definition - constants
+
+# =======================
+#     MENUS FUNCTIONS
+# =======================
+
+# Main menu
+
+# =======================
+#      MAIN PROGRAM
+# =======================
+
+# Main Program
+
+def get_tenant_uri():
+    return "/restconf/config/policy:tenants/policy:tenant/tenant-red"
+
+
+def get_tunnel_data():
+    return {
+  "opendaylight-inventory:nodes": {
+    "node": [
+      {
+        "id": "openflow:1",
+        "ofoverlay:tunnel": [
+          {
+            "tunnel-type": "overlay:tunnel-type-vxlan-gpe",
+            "node-connector-id": "openflow:1:1",
+            "ip": "192.168.50.70",
+            "port": 6633
+          },
+          {
+            "tunnel-type": "overlay:tunnel-type-vxlan",
+            "node-connector-id": "openflow:1:2",
+            "ip": "192.168.50.70",
+            "port": 4789
+          }
+        ]
+      },
+      {
+        "id": "openflow:2",
+        "ofoverlay:tunnel": [
+          {
+            "tunnel-type": "overlay:tunnel-type-vxlan-gpe",
+            "node-connector-id": "openflow:2:1",
+            "ip": "192.168.50.71",
+            "port": 6633
+          },
+          {
+            "tunnel-type": "overlay:tunnel-type-vxlan",
+            "node-connector-id": "openflow:2:2",
+            "ip": "192.168.50.71",
+            "port": 4789
+          }
+        ]
+      },
+                   {
+        "id": "openflow:3",
+        "ofoverlay:tunnel": [
+          {
+            "tunnel-type": "overlay:tunnel-type-vxlan-gpe",
+            "node-connector-id": "openflow:3:1",
+            "ip": "192.168.50.72",
+            "port": 6633
+          },
+          {
+            "tunnel-type": "overlay:tunnel-type-vxlan",
+            "node-connector-id": "openflow:3:2",
+            "ip": "192.168.50.72",
+            "port": 4789
+          }
+        ]
+      },
+
+    ]
+  }
+            }
+
+def get_tunnel_uri():
+    return "/restconf/config/opendaylight-inventory:nodes"
+
+def get_endpoint_data():
+    return [{
+    "input": {
+
+        "endpoint-group": "clients",
+
+        "network-containment" : "subnet-10.0.35.0/24",
+
+        "l2-context": "bridge-domain1",
+        "mac-address": "00:00:00:00:35:02",
+
+        "l3-address": [
+            {
+                "ip-address": "10.0.35.2",
+                "l3-context": "l3-context-vrf-red"
+            }
+        ],
+        "port-name": "vethl-h35_2",
+        "tenant": "tenant-red"
+    }
+},
+            {
+    "input": {
+
+        "endpoint-group": "clients",
+
+        "network-containment" : "subnet-10.0.35.0/24",
+
+        "l2-context": "bridge-domain1",
+        "mac-address": "00:00:00:00:35:03",
+
+        "l3-address": [
+            {
+                "ip-address": "10.0.35.3",
+                "l3-context": "l3-context-vrf-red"
+            }
+        ],
+        "port-name": "vethl-h35_3",
+        "tenant": "tenant-red"
+    }
+},
+            {
+    "input": {
+
+        "endpoint-group": "clients",
+
+        "network-containment" : "subnet-10.0.35.0/24",
+
+        "l2-context": "bridge-domain1",
+        "mac-address": "00:00:00:00:35:04",
+
+        "l3-address": [
+            {
+                "ip-address": "10.0.35.4",
+                "l3-context": "l3-context-vrf-red"
+            }
+        ],
+        "port-name": "vethl-h35_4",
+        "tenant": "tenant-red"
+    }
+},
+            {
+    "input": {
+
+        "endpoint-group": "clients",
+
+        "network-containment" : "subnet-10.0.35.0/24",
+
+        "l2-context": "bridge-domain1",
+        "mac-address": "00:00:00:00:35:05",
+
+        "l3-address": [
+            {
+                "ip-address": "10.0.35.5",
+                "l3-context": "l3-context-vrf-red"
+            }
+        ],
+        "port-name": "vethl-h35_5",
+        "tenant": "tenant-red"
+    }
+},
+            {
+    "input": {
+
+        "endpoint-group": "webservers1",
+
+        "network-containment" : "subnet-10.0.36.0/24",
+
+        "l2-context": "bridge-domain1",
+        "mac-address": "00:00:00:00:36:02",
+
+        "l3-address": [
+            {
+                "ip-address": "10.0.36.2",
+                "l3-context": "l3-context-vrf-red"
+            }
+        ],
+        "port-name": "vethl-h36_2",
+        "tenant": "tenant-red"
+    }
+},
+            {
+    "input": {
+
+        "endpoint-group": "webservers2",
+
+        "network-containment" : "subnet-10.0.36.0/24",
+
+        "l2-context": "bridge-domain1",
+        "mac-address": "00:00:00:00:36:03",
+
+        "l3-address": [
+            {
+                "ip-address": "10.0.36.3",
+                "l3-context": "l3-context-vrf-red"
+            }
+        ],
+        "port-name": "vethl-h36_3",
+        "tenant": "tenant-red"
+    }
+},
+            {
+    "input": {
+
+        "endpoint-group": "webservers1",
+
+        "network-containment" : "subnet-10.0.36.0/24",
+
+        "l2-context": "bridge-domain1",
+        "mac-address": "00:00:00:00:36:04",
+
+        "l3-address": [
+            {
+                "ip-address": "10.0.36.4",
+                "l3-context": "l3-context-vrf-red"
+            }
+        ],
+        "port-name": "vethl-h36_4",
+        "tenant": "tenant-red"
+    }
+},{
+    "input": {
+
+        "endpoint-group": "webservers2",
+
+        "network-containment" : "subnet-10.0.36.0/24",
+
+        "l2-context": "bridge-domain1",
+        "mac-address": "00:00:00:00:36:05",
+
+        "l3-address": [
+            {
+                "ip-address": "10.0.36.5",
+                "l3-context": "l3-context-vrf-red"
+            }
+        ],
+        "port-name": "vethl-h36_5",
+        "tenant": "tenant-red"
+    }
+}]
+
+def get_endpoint_uri():
+    return "/restconf/operations/endpoint:register-endpoint"
+
+if __name__ == "__main__":
+    # Launch main menu
+
+
+    # Some sensible defaults
+    controller=os.environ.get('ODL')
+    if controller == None:
+        sys.exit("No controller set.")
+
+
+    print "tenants"
+    tenants=get(controller,DEFAULT_PORT,CONF_TENANT)
+    print tenants
+
+    print "sending tenant"
+    put(controller, DEFAULT_PORT, get_tenant_uri(), get_tenant_data(),True)
+    print "sending tunnel"
+    put(controller, DEFAULT_PORT, get_tunnel_uri(), get_tunnel_data(), True)
+    print "registering endpoints"
+    for endpoint in get_endpoint_data():
+        post(controller, DEFAULT_PORT, get_endpoint_uri(),endpoint,True)
+
+
+
+
index edc74553800c99dcffe1aaa4bb7ef201febaa7b8..c22c322d44cc19ff91796dfd1e1a30d63fa65c18 100755 (executable)
@@ -377,8 +377,14 @@ def get_tenant_data():
                           "order": 0,
                           "classifier-ref": [
                             {
                           "order": 0,
                           "classifier-ref": [
                             {
-                              "name": "icmp",
-                              "instance-name": "icmp"
+                              "name": "icmp-in",
+                              "instance-name": "icmp",
+                              "direction": "in"
+                            },
+                            {
+                              "name": "icmp-out",
+                              "instance-name": "icmp",
+                              "direction": "out"
                             }
                           ],
                           "action-ref": [
                             }
                           ],
                           "action-ref": [
index c8caa10096e8e4bb7ddcd5dd2a5dfef623acf07a..2884d76a0e900d9a52638f44215347220c9c3e99 100644 (file)
@@ -375,8 +375,14 @@ def get_tenant_data():
                           "order": 0,
                           "classifier-ref": [
                             {
                           "order": 0,
                           "classifier-ref": [
                             {
-                              "name": "icmp",
-                              "instance-name": "icmp"
+                              "name": "icmp-in",
+                              "instance-name": "icmp",
+                              "direction": "in"
+                            },
+                            {
+                              "name": "icmp-out",
+                              "instance-name": "icmp",
+                              "direction": "out"
                             }
                           ],
                           "action-ref": [
                             }
                           ],
                           "action-ref": [
index 713aaef6c58334c614510cebc281aa7b966270d2..5653063c93bfe0f2623afb4a610eb65bcccef117 100755 (executable)
@@ -147,4 +147,15 @@ if __name__ == "__main__" :
            print "*****************************"
            doCmd('sudo /vagrant/sf-config.sh')
            #addGpeTunnel(switches[sw_index]['name'])
            print "*****************************"
            doCmd('sudo /vagrant/sf-config.sh')
            #addGpeTunnel(switches[sw_index]['name'])
+       elif sw_type == 'sflow':
+           print "*****************************"
+           print "Configuring %s as an sFlow-RT collector." % sw_name
+           print "*****************************"
+           doCmd('sudo /vagrant/install_java.sh')
+           doCmd('sudo /vagrant/sflow/install_sflow-rt.sh')
+           call('sudo /home/vagrant/sflow-rt/gbp_start.sh &'.split())
+           doCmd('sudo /vagrant/sflow/set_collector_ip.sh')
+           doCmd('sudo /vagrant/sflow/curl_put_collector.sh')
+           print "Configuring finished."
+
 
 
diff --git a/demos/gbpsfc-env/install_java.sh b/demos/gbpsfc-env/install_java.sh
new file mode 100755 (executable)
index 0000000..6420b2d
--- /dev/null
@@ -0,0 +1,6 @@
+#!/usr/bin/env bash
+
+if ! java -version 2>/dev/null; then
+  sudo apt-get update
+  sudo apt-get install openjdk-7-jre-headless -y
+fi
diff --git a/demos/gbpsfc-env/sflow/.gitignore b/demos/gbpsfc-env/sflow/.gitignore
new file mode 100755 (executable)
index 0000000..3604b91
--- /dev/null
@@ -0,0 +1 @@
+/curl_put_collector.sh
index 6a15973cd94580cb2c95b392c39072b388b937f7..552ce6fbe46e93847919d3ec9ae12f33a2bcaebf 100755 (executable)
@@ -4,11 +4,11 @@ contains a list of numbers to append to "gbpsfc" to get the VMs' names
 start [<name>]
 stop [<name>]
 list [<name>]
 start [<name>]
 stop [<name>]
 list [<name>]
-No parameters: machines' names are generated from settings file.
-One parameter: operation will take place on than machine only
+No parameters: machines' names are generated from settings.sh file (SFLOW_LIST should contain numbers used for vagrant's names of VMs).
+One parameter: operation will take place on than machine only (ex., `start gbpsfc2')
 
 start
 
 start
-Start sending sFlow data from OVS (all parameters are set in internal_settings)
+Start sending sFlow data from OVS (all parameters are set in internal_settings.sh)
 
 stop
 Stop sending sFlow data
 
 stop
 Stop sending sFlow data
@@ -16,10 +16,10 @@ Stop sending sFlow data
 list
 Show actual state of sFlow, or will not show anything if sFlow is stopped.
 
 list
 Show actual state of sFlow, or will not show anything if sFlow is stopped.
 
-internal_settings
+internal_settings.sh
 Settings used to start sFlow sending on a machine
 
 Settings used to start sFlow sending on a machine
 
-internal_start, internal_stop
+internal_start.sh, internal_stop.sh
 Not to be run manually. Starting/stopping sFlow sending on individual machine
 
 
 Not to be run manually. Starting/stopping sFlow sending on individual machine
 
 
diff --git a/demos/gbpsfc-env/sflow/install_sflow-rt.sh b/demos/gbpsfc-env/sflow/install_sflow-rt.sh
new file mode 100755 (executable)
index 0000000..6e1e614
--- /dev/null
@@ -0,0 +1,13 @@
+#!/usr/bin/env bash
+
+if [ ! -d /home/vagrant/sflow-rt ]; then
+  echo "/home/vagrant/sflow-rt not found; installing sFlow-RT..."
+  wget http://www.inmon.com/products/sFlow-RT/sflow-rt.tar.gz
+  tar -xvzf sflow-rt.tar.gz
+  sudo chown -R vagrant:vagrant /home/vagrant/sflow-rt
+fi
+
+if [ ! -f /home/vagrant/sflow-rt/gbp_start.sh ]; then
+  sed '/exec java/c sudo nohup java ${JVM_OPTS} ${RT_OPTS} ${SCRIPTS} -jar ${JAR} 1>rt.out 2>&1 &' ~/sflow-rt/start.sh >/home/vagrant/sflow-rt/gbp_start.sh
+  sudo chmod +x /home/vagrant/sflow-rt/gbp_start.sh
+fi
similarity index 80%
rename from demos/gbpsfc-env/sflow/internal_settings
rename to demos/gbpsfc-env/sflow/internal_settings.sh
index 5398af747d69a08efa96d31096374308fe2045cd..030d218ac38b8c56b15eac44062ddb921e5baaa6 100755 (executable)
@@ -1,6 +1,6 @@
 #!/usr/bin/env bash
 
 #!/usr/bin/env bash
 
-export COLLECTOR_IP=192.168.53.2
+export COLLECTOR_IP=192.168.53.73
 export COLLECTOR_PORT=6343
 export AGENT_IP=eth2
 export HEADER_BYTES=128
 export COLLECTOR_PORT=6343
 export AGENT_IP=eth2
 export HEADER_BYTES=128
similarity index 81%
rename from demos/gbpsfc-env/sflow/internal_start
rename to demos/gbpsfc-env/sflow/internal_start.sh
index 0e3218c131c73419fe06acd214a947f785779355..46797cd280e17f8136df5c563ebc6e7291313de0 100755 (executable)
@@ -1,12 +1,12 @@
 #!/usr/bin/env bash
 
 #!/usr/bin/env bash
 
-. /vagrant/sflow/internal_settings
+. /vagrant/sflow/internal_settings.sh
 hostnum=${HOSTNAME#"gbpsfc"}
 sw="sw$hostnum"
 
 if [ -f ~/sflow_uuid ]; then
   echo "sflow_uuid already present; cleaning..."
 hostnum=${HOSTNAME#"gbpsfc"}
 sw="sw$hostnum"
 
 if [ -f ~/sflow_uuid ]; then
   echo "sflow_uuid already present; cleaning..."
-  sudo ovs-vsctl remove bridge $sw sflow `cat ~/sflow_uuid` 
+  sudo ovs-vsctl remove bridge $sw sflow `cat ~/sflow_uuid`
   rm ~/sflow_uuid
 fi
 
   rm ~/sflow_uuid
 fi
 
similarity index 58%
rename from demos/gbpsfc-env/sflow/internal_stop
rename to demos/gbpsfc-env/sflow/internal_stop.sh
index 005be483abbe83edf41f308fde6103b22774fc09..b21192b6417b07a6611536667d6af1b666d8420c 100755 (executable)
@@ -1,12 +1,12 @@
 #!/usr/bin/env bash
 
 if [ ! -f ~/sflow_uuid ]; then
 #!/usr/bin/env bash
 
 if [ ! -f ~/sflow_uuid ]; then
-  echo "No sflow_uuid found!"
+  echo "No sflow_uuid found."
   exit 1
 fi
 
 hostnum=${HOSTNAME#"gbpsfc"}
 sw="sw$hostnum"
 
   exit 1
 fi
 
 hostnum=${HOSTNAME#"gbpsfc"}
 sw="sw$hostnum"
 
-sudo ovs-vsctl remove bridge $sw sflow `cat ~/sflow_uuid` 
+sudo ovs-vsctl remove bridge $sw sflow `cat ~/sflow_uuid`
 rm ~/sflow_uuid
 rm ~/sflow_uuid
diff --git a/demos/gbpsfc-env/sflow/set_collector_ip.sh b/demos/gbpsfc-env/sflow/set_collector_ip.sh
new file mode 100755 (executable)
index 0000000..092c631
--- /dev/null
@@ -0,0 +1,10 @@
+#!/usr/bin/env bash
+
+source /vagrant/env.sh
+source /vagrant/sflow/settings.sh
+export THIS_IP=$(ifconfig | grep -A 1 'eth2' | tail -1 | cut -d ':' -f 2 | cut -d ' ' -f 1)
+
+echo "#!/usr/bin/env bash" >/vagrant/sflow/curl_put_collector.sh
+echo "curl -H \"Content-Type:application/yang.data+json\" -X PUT --data \"{'ofoverlay:of-overlay-config': {'sflow-client-settings': {'gbp-ofoverlay-sflow-retrieve-interval': $SFLOW_INTERVAL, 'gbp-ofoverlay-sflow-collector-uri': 'http://$THIS_IP:8008'}}}\" http://admin:admin@$ODL:8181/restconf/config/ofoverlay:of-overlay-config" >>/vagrant/sflow/curl_put_collector.sh
+
+sed -i "/export COLLECTOR_IP=/c export COLLECTOR_IP=$THIS_IP" /vagrant/sflow/internal_settings.sh
similarity index 65%
rename from demos/gbpsfc-env/sflow/settings
rename to demos/gbpsfc-env/sflow/settings.sh
index 27e2f4d0712bb463a559d1e8fa0560617db94f88..02d3f961cb189bb54282643cc6d05a0adf93f615 100755 (executable)
@@ -1,4 +1,5 @@
 #!/usr/bin/env bash
 
 export SFLOW_LIST="1 2 3"
 #!/usr/bin/env bash
 
 export SFLOW_LIST="1 2 3"
+export SFLOW_INTERVAL=30
 
 
index b78316da576b4594ad02b71e83cc482a675c6228..3c5cab633a6ae762441709ab2efb9efddbf4c138 100755 (executable)
@@ -1,13 +1,13 @@
 #!/usr/bin/env bash
 
 if [ $1 ]; then
 #!/usr/bin/env bash
 
 if [ $1 ]; then
-  vagrant ssh $1 -c "bash -E /vagrant/sflow/internal_start"
+  vagrant ssh $1 -c "bash -E /vagrant/sflow/internal_start.sh"
 else
 else
-  . sflow/settings
+  . sflow/settings.sh
   for i in $SFLOW_LIST
   do
     echo; echo "gbpsfc$i"
   for i in $SFLOW_LIST
   do
     echo; echo "gbpsfc$i"
-    vagrant ssh gbpsfc$i -c "bash -E /vagrant/sflow/internal_start"
+    vagrant ssh gbpsfc$i -c "bash -E /vagrant/sflow/internal_start.sh"
   done
 fi
 
   done
 fi
 
index b0514aea632f1ce5b7bd7a0e78c4789b90a219e5..f66330e6e834173d88dd47e1d69220ddfef7e13b 100755 (executable)
@@ -1,12 +1,12 @@
 #!/usr/bin/env bash
 
 if [ $1 ]; then
 #!/usr/bin/env bash
 
 if [ $1 ]; then
-  vagrant ssh $1 -c "bash -E /vagrant/sflow/internal_stop"
+  vagrant ssh $1 -c "bash -E /vagrant/sflow/internal_stop.sh"
 else
 else
-  . sflow/settings
+  . sflow/settings.sh
   for i in $SFLOW_LIST
   do
     echo; echo "gbpsfc$i"
   for i in $SFLOW_LIST
   do
     echo; echo "gbpsfc$i"
-    vagrant ssh gbpsfc$i -c "bash -E /vagrant/sflow/internal_stop"
+    vagrant ssh gbpsfc$i -c "bash -E /vagrant/sflow/internal_stop.sh"
   done
 fi
   done
 fi
diff --git a/demos/gbpsfc-env/sflow/stop_sflow-rt.sh b/demos/gbpsfc-env/sflow/stop_sflow-rt.sh
new file mode 100755 (executable)
index 0000000..238ec3b
--- /dev/null
@@ -0,0 +1,5 @@
+#!/usr/bin/env bash
+
+sudo kill $(ps -fe | grep port=6343 | grep -v grep | awk 'NR==1 {print $2}')
+sudo rm /home/vagrant/sflow-rt/rt.out.old
+sudo mv /home/vagrant/sflow-rt/rt.out /home/vagrant/sflow-rt/rt.out.old
index 5f0bc9ad8ab66329a9b5b33738effe64b962e590..bcd48f8dbfbf74630f6748553c9f398173781584 100755 (executable)
@@ -56,6 +56,9 @@
         <feature version='${sfc.version}'>odl-sfc-ui</feature>
         <bundle>mvn:commons-net/commons-net/{{VERSION}}</bundle>
         <bundle>mvn:org.opendaylight.groupbasedpolicy/ofoverlay-renderer/{{VERSION}}</bundle>
         <feature version='${sfc.version}'>odl-sfc-ui</feature>
         <bundle>mvn:commons-net/commons-net/{{VERSION}}</bundle>
         <bundle>mvn:org.opendaylight.groupbasedpolicy/ofoverlay-renderer/{{VERSION}}</bundle>
+        <bundle>mvn:com.sun.jersey/jersey-core/{{VERSION}}</bundle>
+        <bundle>mvn:com.sun.jersey/jersey-client/{{VERSION}}</bundle>
+        <bundle>mvn:com.google.code.gson/gson/{{VERSION}}</bundle>
         <configfile finalname="${config.configfile.directory}/15-groupbasedpolicy-ofoverlay.xml">mvn:org.opendaylight.groupbasedpolicy/ofoverlay-renderer/{{VERSION}}/xml/config</configfile>
     </feature>
 
         <configfile finalname="${config.configfile.directory}/15-groupbasedpolicy-ofoverlay.xml">mvn:org.opendaylight.groupbasedpolicy/ofoverlay-renderer/{{VERSION}}/xml/config</configfile>
     </feature>
 
index 255e90a5e002f948c0169ad51aad11f9fb62e544..370f82bc7d52ce81a199c7fc8de425ecae6264ff 100755 (executable)
@@ -38,11 +38,13 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ClassifierDefinitionId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.TenantId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.Tenants;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ClassifierDefinitionId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.TenantId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.Tenants;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.has.classifier.refs.ClassifierRef;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.Tenant;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.Policy;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.SubjectFeatureInstances;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.subject.feature.instances.ActionInstance;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.subject.feature.instances.ClassifierInstance;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.Tenant;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.Policy;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.SubjectFeatureInstances;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.subject.feature.instances.ActionInstance;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.subject.feature.instances.ClassifierInstance;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.subject.feature.instances.ClassifierInstanceBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.resolved.policy.rev150828.ResolvedPolicies;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.resolved.policy.rev150828.ResolvedPoliciesBuilder;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.resolved.policy.rev150828.ResolvedPolicies;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.resolved.policy.rev150828.ResolvedPoliciesBuilder;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
@@ -316,6 +318,21 @@ public class PolicyResolver implements PolicyValidatorRegistry, AutoCloseable {
             synchronized (subscribersPerTenant) {
                 if (subscribersPerTenant.contains(tenantAfter.getId())) {
                     updateTenant(tenantAfter.getId(), tenantAfter);
             synchronized (subscribersPerTenant) {
                 if (subscribersPerTenant.contains(tenantAfter.getId())) {
                     updateTenant(tenantAfter.getId(), tenantAfter);
+                    tenantAfter.getPolicy().getContract().get(0).getId();
+                    tenantAfter.getPolicy().getContract().get(0).getSubject().get(0).getName();
+                    tenantAfter.getPolicy().getContract().get(0).getSubject().get(0).getRule().get(0).getName();
+                    List<ClassifierRef> cref = tenantAfter.getPolicy()
+                            .getContract()
+                            .get(0)
+                            .getSubject()
+                            .get(0)
+                            .getRule()
+                            .get(0)
+                            .getClassifierRef();
+                    cref.get(0).getInstanceName();
+                    tenantAfter.getPolicy().getSubjectFeatureInstances().getClassifierInstance().get(0).getName();
+                    tenantAfter.getPolicy().getSubjectFeatureInstances().getClassifierInstance().get(0).getParameterValue()
+                            .get(0);
                 }
             }
         }
                 }
             }
         }
old mode 100644 (file)
new mode 100755 (executable)
index 0ac0899..eebbfe5
@@ -19,6 +19,7 @@ import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.groupbasedpolicy.api.StatisticsManager;
 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.groupbasedpolicy.api.StatisticsManager;
+import org.opendaylight.groupbasedpolicy.util.DataStoreHelper;
 import org.opendaylight.groupbasedpolicy.util.IidFactory;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.L2BridgeDomainId;
 import org.opendaylight.groupbasedpolicy.util.IidFactory;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.L2BridgeDomainId;
@@ -72,15 +73,16 @@ public class StatisticsManagerImpl implements StatisticsManager, AutoCloseable {
 
     @Override
     public boolean writeStat(StatRecords record) {
 
     @Override
     public boolean writeStat(StatRecords record) {
+        WriteTransaction wtx = dataBroker.newWriteOnlyTransaction();
         for (EpToEpStatistic epStats : record.getEpToEpStatistic()) {
             SrcEndpointBuilder srcBuilder = new SrcEndpointBuilder();
             DstEndpointBuilder dstBuilder = new DstEndpointBuilder();
             srcBuilder.setMacAddress(epStats.getSrcMacAddress())
         for (EpToEpStatistic epStats : record.getEpToEpStatistic()) {
             SrcEndpointBuilder srcBuilder = new SrcEndpointBuilder();
             DstEndpointBuilder dstBuilder = new DstEndpointBuilder();
             srcBuilder.setMacAddress(epStats.getSrcMacAddress())
-                .setL2Context(epStats.getSrcL2c())
-                .setTenant(epStats.getSrcTenant());
+                    .setL2Context(epStats.getSrcL2c())
+                    .setTenant(epStats.getSrcTenant());
             dstBuilder.setMacAddress(epStats.getDstMacAddress())
             dstBuilder.setMacAddress(epStats.getDstMacAddress())
-                .setL2Context(epStats.getDstL2c())
-                .setTenant(epStats.getDstTenant());
+                    .setL2Context(epStats.getDstL2c())
+                    .setTenant(epStats.getDstTenant());
             for (EpEpgToEpEpgStatistic epgStats : epStats.getEpEpgToEpEpgStatistic()) {
                 StatisticRecordKey key = new StatisticRecordKey(new RecordId(recordKey++));
                 StatisticRecord statRecord;
             for (EpEpgToEpEpgStatistic epgStats : epStats.getEpEpgToEpEpgStatistic()) {
                 StatisticRecordKey key = new StatisticRecordKey(new RecordId(recordKey++));
                 StatisticRecord statRecord;
@@ -89,35 +91,33 @@ public class StatisticsManagerImpl implements StatisticsManager, AutoCloseable {
                 List<Statistic> statisticList = new ArrayList<>();
                 for (MatchedRuleStatistic ruleStats : epgStats.getMatchedRuleStatistic()) {
                     Statistic statistic = new StatisticBuilder()
                 List<Statistic> statisticList = new ArrayList<>();
                 for (MatchedRuleStatistic ruleStats : epgStats.getMatchedRuleStatistic()) {
                     Statistic statistic = new StatisticBuilder()
-                        .setKey(new StatisticKey(ruleStats.getContract(), ruleStats.getMatchedRule(),
-                                ruleStats.getSubject()))
-                        .setContract(ruleStats.getContract())
-                        .setSubject(ruleStats.getSubject())
-                        .setRule(ruleStats.getMatchedRule())
-                        .setAction(ruleStats.getAction())
-                        .setClassifier(ruleStats.getClassifier())
-                        .setByteCount(ruleStats.getByteCount())
-                        .setPacketCount(ruleStats.getPacketCount())
-                        .build();
+                            .setKey(new StatisticKey(ruleStats.getContract(),
+                                    ruleStats.getMatchedRule(), ruleStats.getSubject()))
+                            .setContract(ruleStats.getContract())
+                            .setSubject(ruleStats.getSubject())
+                            .setRule(ruleStats.getMatchedRule())
+                            .setAction(ruleStats.getAction())
+                            .setClassifier(ruleStats.getClassifier())
+                            .setByteCount(ruleStats.getByteCount())
+                            .setPacketCount(ruleStats.getPacketCount())
+                            .build();
                     statisticList.add(statistic);
 
                 }
                 statRecord = new StatisticRecordBuilder().setKey(key)
                     statisticList.add(statistic);
 
                 }
                 statRecord = new StatisticRecordBuilder().setKey(key)
-                    .setRecordId(new RecordId(recordKey))
-                    .setTimestamp(epStats.getTimestamp())
-                    .setSrcEndpoint(srcBuilder.build())
-                    .setDstEndpoint(dstBuilder.build())
-                    .setStatistic(statisticList)
-                    .build();
+                        .setRecordId(new RecordId(recordKey))
+                        .setTimestamp(epStats.getTimestamp())
+                        .setSrcEndpoint(srcBuilder.build())
+                        .setDstEndpoint(dstBuilder.build())
+                        .setStatistic(statisticList)
+                        .build();
 
                 InstanceIdentifier<StatisticRecord> statIID = IidFactory.statisticRecordIid(key);
 
                 InstanceIdentifier<StatisticRecord> statIID = IidFactory.statisticRecordIid(key);
-                WriteTransaction wtx = dataBroker.newWriteOnlyTransaction();
-                LOG.debug("Writing statistics to datastore");
-                wtx.put(LogicalDatastoreType.OPERATIONAL, statIID, statRecord);
-                wtx.submit();
+                LOG.debug("Writing statistics to datastore: {}", statRecord);
+                wtx.put(LogicalDatastoreType.OPERATIONAL, statIID, statRecord, true);
             }
         }
             }
         }
-        return true;
+        return DataStoreHelper.submitToDs(wtx);
     }
 
     @Override
     }
 
     @Override
old mode 100644 (file)
new mode 100755 (executable)
index 1330fc0..4d2f694
@@ -20,6 +20,7 @@ import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
+import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
 import org.opendaylight.groupbasedpolicy.util.IidFactory;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ActionName;
 import org.opendaylight.groupbasedpolicy.util.IidFactory;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ActionName;
@@ -132,10 +133,18 @@ public class StatisticManagerImplTest {
             .setSrcEndpoint(srcBuilder.build())
             .setDstEndpoint(dstBuilder.build());
 
             .setSrcEndpoint(srcBuilder.build())
             .setDstEndpoint(dstBuilder.build());
 
+//        manager.writeStat(recordsBuilder.build());
+//        Mockito.verify(wtx).put(LogicalDatastoreType.OPERATIONAL,
+//                IidFactory.statisticRecordIid(key),
+//                statRecord.build());
+        CheckedFuture<Void,TransactionCommitFailedException> future = Mockito.mock(CheckedFuture.class);
+        Mockito.when(wtx.submit()).thenReturn(future);
+        Mockito.when(dataBroker.newWriteOnlyTransaction()).thenReturn(wtx);
+
         manager.writeStat(recordsBuilder.build());
         Mockito.verify(wtx).put(LogicalDatastoreType.OPERATIONAL,
                 IidFactory.statisticRecordIid(key),
         manager.writeStat(recordsBuilder.build());
         Mockito.verify(wtx).put(LogicalDatastoreType.OPERATIONAL,
                 IidFactory.statisticRecordIid(key),
-                statRecord.build());
+                statRecord.build(), true);
     }
 
     @Test
     }
 
     @Test
index f6eda37894309dfb32c14ee1e98b8f2b5c9f37b5..ef2d52038df6657c8f8b03034b243db07581b56f 100755 (executable)
       <groupId>commons-net</groupId>
       <artifactId>commons-net</artifactId>
     </dependency>
       <groupId>commons-net</groupId>
       <artifactId>commons-net</artifactId>
     </dependency>
+    <!-- REST client-->
+    <dependency>
+       <groupId>com.sun.jersey</groupId>
+       <artifactId>jersey-client</artifactId>
+    </dependency>
+    <dependency>
+       <groupId>com.google.code.gson</groupId>
+       <artifactId>gson</artifactId>
+    </dependency>
     <!-- SFC -->
     <dependency>
       <groupId>org.opendaylight.sfc</groupId>
     <!-- SFC -->
     <dependency>
       <groupId>org.opendaylight.sfc</groupId>
old mode 100644 (file)
new mode 100755 (executable)
index a572908..8388627
                         <name>policy-validator-registry</name>
                     </policy-validator-registry>
 
                         <name>policy-validator-registry</name>
                     </policy-validator-registry>
 
+                    <statistics-manager>
+                        <type xmlns:gbp="urn:opendaylight:params:xml:ns:yang:controller:config:groupbasedpolicy">gbp:statistics-manager</type>
+                        <name>statistics-manager</name>
+                    </statistics-manager>
+
                     <gbp-ofoverlay-table-offset>0</gbp-ofoverlay-table-offset>
                     <gbp-ofoverlay-table-offset>0</gbp-ofoverlay-table-offset>
+
+                    <!--<gbp-ofoverlay-sflow-start>false</gbp-ofoverlay-sflow-start>-->
+                    <!--<gbp-ofoverlay-sflow-collector-uri>http://192.168.53.2:8008</gbp-ofoverlay-sflow-collector-uri>-->
                 </module>
             </modules>
         </data>
                 </module>
             </modules>
         </data>
old mode 100644 (file)
new mode 100755 (executable)
index 20b69ab..a6cb224
@@ -38,6 +38,7 @@ public class OFOverlayProviderModule extends org.opendaylight.controller.config.
                                      getNotificationAdapterDependency(),
                                      getEpRendererAugmentationRegistryDependency(),
                                      getPolicyValidatorRegistryDependency(),
                                      getNotificationAdapterDependency(),
                                      getEpRendererAugmentationRegistryDependency(),
                                      getPolicyValidatorRegistryDependency(),
+                                     getStatisticsManagerDependency(),
                                      getGbpOfoverlayTableOffset().shortValue());
     }
 
                                      getGbpOfoverlayTableOffset().shortValue());
     }
 
old mode 100644 (file)
new mode 100755 (executable)
index 6ca185f..53b7c07
@@ -28,6 +28,7 @@ import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
 import org.opendaylight.groupbasedpolicy.api.EpRendererAugmentationRegistry;
 import org.opendaylight.groupbasedpolicy.api.PolicyValidatorRegistry;
 import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
 import org.opendaylight.groupbasedpolicy.api.EpRendererAugmentationRegistry;
 import org.opendaylight.groupbasedpolicy.api.PolicyValidatorRegistry;
+import org.opendaylight.groupbasedpolicy.api.StatisticsManager;
 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.endpoint.EndpointManager;
 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.endpoint.OfOverlayAug;
 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.endpoint.OfOverlayL3NatAug;
 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.endpoint.EndpointManager;
 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.endpoint.OfOverlayAug;
 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.endpoint.OfOverlayL3NatAug;
@@ -36,6 +37,7 @@ import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.sf.Action;
 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.sf.ActionDefinitionListener;
 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.sf.ClassifierDefinitionListener;
 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.sf.SubjectFeatures;
 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.sf.ActionDefinitionListener;
 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.sf.ClassifierDefinitionListener;
 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.sf.SubjectFeatures;
+import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.statistics.SflowClientSettingsListener;
 import org.opendaylight.groupbasedpolicy.util.DataStoreHelper;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ActionDefinitionId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.ofoverlay.rev140528.OfOverlayConfig;
 import org.opendaylight.groupbasedpolicy.util.DataStoreHelper;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ActionDefinitionId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.ofoverlay.rev140528.OfOverlayConfig;
@@ -56,6 +58,7 @@ import com.google.common.util.concurrent.ListenableFuture;
  * using Open vSwitch.
  */
 public class OFOverlayRenderer implements AutoCloseable, DataChangeListener {
  * using Open vSwitch.
  */
 public class OFOverlayRenderer implements AutoCloseable, DataChangeListener {
+
     private static final Logger LOG =
             LoggerFactory.getLogger(OFOverlayRenderer.class);
     public static final RendererName RENDERER_NAME = new RendererName("OFOverlay");
     private static final Logger LOG =
             LoggerFactory.getLogger(OFOverlayRenderer.class);
     public static final RendererName RENDERER_NAME = new RendererName("OFOverlay");
@@ -65,6 +68,7 @@ public class OFOverlayRenderer implements AutoCloseable, DataChangeListener {
     private final EndpointManager endpointManager;
     private final PolicyManager policyManager;
     private final ClassifierDefinitionListener classifierDefinitionListener;
     private final EndpointManager endpointManager;
     private final PolicyManager policyManager;
     private final ClassifierDefinitionListener classifierDefinitionListener;
+    private final SflowClientSettingsListener sflowClientSettingsListener;
     private ActionDefinitionListener actionDefinitionListener;
     private final OfOverlayAug ofOverlayAug;
     private final OfOverlayL3NatAug ofOverlayL3NatAug;
     private ActionDefinitionListener actionDefinitionListener;
     private final OfOverlayAug ofOverlayAug;
     private final OfOverlayL3NatAug ofOverlayL3NatAug;
@@ -77,11 +81,12 @@ public class OFOverlayRenderer implements AutoCloseable, DataChangeListener {
     ListenerRegistration<DataChangeListener> configReg;
 
     public OFOverlayRenderer(final DataBroker dataProvider,
     ListenerRegistration<DataChangeListener> configReg;
 
     public OFOverlayRenderer(final DataBroker dataProvider,
-                             RpcProviderRegistry rpcRegistry,
-                             NotificationService notificationService,
-                             EpRendererAugmentationRegistry epRendererAugmentationRegistry,
-                             PolicyValidatorRegistry policyValidatorRegistry,
-                             final short tableOffset) {
+            RpcProviderRegistry rpcRegistry,
+            NotificationService notificationService,
+            EpRendererAugmentationRegistry epRendererAugmentationRegistry,
+            PolicyValidatorRegistry policyValidatorRegistry,
+            StatisticsManager statisticsManager,
+            final short tableOffset) {
         super();
         this.dataBroker = dataProvider;
         int numCPU = Runtime.getRuntime().availableProcessors();
         super();
         this.dataBroker = dataProvider;
         int numCPU = Runtime.getRuntime().availableProcessors();
@@ -99,6 +104,8 @@ public class OFOverlayRenderer implements AutoCloseable, DataChangeListener {
             policyValidatorRegistry.register(entry.getKey(), entry.getValue());
         }
 
             policyValidatorRegistry.register(entry.getKey(), entry.getValue());
         }
 
+        sflowClientSettingsListener = new SflowClientSettingsListener(dataProvider, executor, statisticsManager);
+
         policyManager = new PolicyManager(dataProvider,
                 switchManager,
                 endpointManager,
         policyManager = new PolicyManager(dataProvider,
                 switchManager,
                 endpointManager,
@@ -116,6 +123,11 @@ public class OFOverlayRenderer implements AutoCloseable, DataChangeListener {
             configBuilder.setGbpOfoverlayTableOffset(tableOffset).build();
             writeTableOffset(configBuilder.build());
         }
             configBuilder.setGbpOfoverlayTableOffset(tableOffset).build();
             writeTableOffset(configBuilder.build());
         }
+
+    }
+
+    public ScheduledExecutorService getExecutor() {
+        return executor;
     }
 
     // *************
     }
 
     // *************
@@ -133,6 +145,7 @@ public class OFOverlayRenderer implements AutoCloseable, DataChangeListener {
         if (ofOverlayAug != null) ofOverlayAug.close();
         if (ofOverlayL3NatAug != null) ofOverlayL3NatAug.close();
         if (policyManager != null) policyManager.close();
         if (ofOverlayAug != null) ofOverlayAug.close();
         if (ofOverlayL3NatAug != null) ofOverlayL3NatAug.close();
         if (policyManager != null) policyManager.close();
+        if (sflowClientSettingsListener != null) sflowClientSettingsListener.close();
     }
 
     // ******************
     }
 
     // ******************
index 02fba5e9d6cbc91a8a65a47063d17e2fe9443283..20b66c6857f6d0f105524cec487d1b293cf01db0 100755 (executable)
@@ -11,10 +11,12 @@ package org.opendaylight.groupbasedpolicy.renderer.ofoverlay;
 import java.io.Closeable;
 import java.io.IOException;
 import java.util.ArrayList;
 import java.io.Closeable;
 import java.io.IOException;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collection;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Collection;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Map.Entry;
 import java.util.concurrent.Callable;
 import java.util.concurrent.CompletionService;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.Callable;
 import java.util.concurrent.CompletionService;
 import java.util.concurrent.ExecutionException;
@@ -23,6 +25,7 @@ import java.util.concurrent.ScheduledExecutorService;
 import java.util.concurrent.TimeUnit;
 
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import java.util.concurrent.TimeUnit;
 
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.DataObjectModification;
 import org.opendaylight.controller.md.sal.binding.api.DataTreeChangeListener;
 import org.opendaylight.controller.md.sal.binding.api.DataTreeIdentifier;
 import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
 import org.opendaylight.controller.md.sal.binding.api.DataTreeChangeListener;
 import org.opendaylight.controller.md.sal.binding.api.DataTreeIdentifier;
 import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
@@ -45,6 +48,7 @@ import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.SourceMapper;
 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.node.SwitchListener;
 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.node.SwitchManager;
 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.sfcutils.SfcIidFactory;
 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.node.SwitchListener;
 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.node.SwitchManager;
 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.sfcutils.SfcIidFactory;
+import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.statistics.OFStatisticsManager;
 import org.opendaylight.groupbasedpolicy.util.DataStoreHelper;
 import org.opendaylight.groupbasedpolicy.util.IidFactory;
 import org.opendaylight.groupbasedpolicy.util.SingletonTask;
 import org.opendaylight.groupbasedpolicy.util.DataStoreHelper;
 import org.opendaylight.groupbasedpolicy.util.IidFactory;
 import org.opendaylight.groupbasedpolicy.util.SingletonTask;
@@ -56,11 +60,17 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.ofoverlay.
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.interests.followed.tenants.followed.tenant.FollowedEndpointGroup;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.interests.followed.tenants.followed.tenant.FollowedEndpointGroupBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.resolved.policy.rev150828.ResolvedPolicies;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.interests.followed.tenants.followed.tenant.FollowedEndpointGroup;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.interests.followed.tenants.followed.tenant.FollowedEndpointGroupBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.resolved.policy.rev150828.ResolvedPolicies;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.resolved.policy.rev150828.has.classifiers.Classifier;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.resolved.policy.rev150828.has.resolved.rules.ResolvedRule;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.resolved.policy.rev150828.resolved.policies.ResolvedPolicy;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.resolved.policy.rev150828.resolved.policies.ResolvedPolicy;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.resolved.policy.rev150828.resolved.policies.resolved.policy.PolicyRuleGroupWithEndpointConstraints;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.resolved.policy.rev150828.resolved.policies.resolved.policy.policy.rule.group.with.endpoint.constraints.PolicyRuleGroup;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.TableId;
 import org.opendaylight.yangtools.concepts.ListenerRegistration;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.TableId;
 import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.Item;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
old mode 100644 (file)
new mode 100755 (executable)
index 6162c54..65ba240
@@ -37,6 +37,7 @@ import org.opendaylight.groupbasedpolicy.dto.IndexedTenant;
 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.EndpointListener;
 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.arp.ArpTasker;
 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.node.SwitchManager;
 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.EndpointListener;
 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.arp.ArpTasker;
 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.node.SwitchManager;
+import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.statistics.OFStatisticsManager;
 import org.opendaylight.groupbasedpolicy.util.DataStoreHelper;
 import org.opendaylight.groupbasedpolicy.util.IidFactory;
 import org.opendaylight.groupbasedpolicy.util.SetUtils;
 import org.opendaylight.groupbasedpolicy.util.DataStoreHelper;
 import org.opendaylight.groupbasedpolicy.util.IidFactory;
 import org.opendaylight.groupbasedpolicy.util.SetUtils;
@@ -281,6 +282,7 @@ public class EndpointManager implements AutoCloseable {
         // create L3 endpoint
         if (oldL3Ep == null && newL3Ep != null) {
             createL3Endpoint(newL3Ep);
         // create L3 endpoint
         if (oldL3Ep == null && newL3Ep != null) {
             createL3Endpoint(newL3Ep);
+            OFStatisticsManager.addL3Endpoint(newL3Ep);
         }
 
         // update L3 endpoint
         }
 
         // update L3 endpoint
@@ -290,6 +292,7 @@ public class EndpointManager implements AutoCloseable {
 
         // remove L3 endpoint
         if (oldL3Ep != null && newL3Ep == null) {
 
         // remove L3 endpoint
         if (oldL3Ep != null && newL3Ep == null) {
+            OFStatisticsManager.removeL3Endpoint(oldL3Ep);
             removeL3Endpoint(oldL3Ep);
         }
     }
             removeL3Endpoint(oldL3Ep);
         }
     }
@@ -531,7 +534,7 @@ public class EndpointManager implements AutoCloseable {
 
     /**
      * An endpoint is external if its endpoint-group is external implicit group.
 
     /**
      * An endpoint is external if its endpoint-group is external implicit group.
-     * 
+     *
      * @param ep an endpoint
      * @param eigs external implicit groups
      * @return {@code true} if the given endpoint has EPG representing external implicit group;
      * @param ep an endpoint
      * @param eigs external implicit groups
      * @return {@code true} if the given endpoint has EPG representing external implicit group;
@@ -545,7 +548,7 @@ public class EndpointManager implements AutoCloseable {
 
     /**
      * An endpoint is internal if none of its endpoint-groups is external implicit group.
 
     /**
      * An endpoint is internal if none of its endpoint-groups is external implicit group.
-     * 
+     *
      * @param ep an endpoint
      * @param eigs external implicit groups
      * @return {@code true} if the given endpoint does not have EPG representing external implicit
      * @param ep an endpoint
      * @param eigs external implicit groups
      * @return {@code true} if the given endpoint does not have EPG representing external implicit
@@ -606,7 +609,8 @@ public class EndpointManager implements AutoCloseable {
         }
         ReadOnlyTransaction rTx = dataProvider.newReadOnlyTransaction();
         Optional<Endpoints> endpoints =
         }
         ReadOnlyTransaction rTx = dataProvider.newReadOnlyTransaction();
         Optional<Endpoints> endpoints =
-                DataStoreHelper.readFromDs(LogicalDatastoreType.OPERATIONAL, IidFactory.endpointsIidWildcard(), rTx);
+                DataStoreHelper.readFromDs(LogicalDatastoreType.OPERATIONAL,
+                        IidFactory.endpointsIidWildcard(), rTx);
         if (!endpoints.isPresent()) {
             LOG.warn("No Endpoints present in data store.");
             return null;
         if (!endpoints.isPresent()) {
             LOG.warn("No Endpoints present in data store.");
             return null;
diff --git a/renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/statistics/JsonRestClient.java b/renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/statistics/JsonRestClient.java
new file mode 100755 (executable)
index 0000000..40dbc18
--- /dev/null
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.groupbasedpolicy.renderer.ofoverlay.statistics;
+
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+
+import com.google.common.base.Preconditions;
+import com.sun.jersey.api.client.Client;
+import com.sun.jersey.api.client.ClientHandlerException;
+import com.sun.jersey.api.client.ClientResponse;
+import com.sun.jersey.api.client.WebResource;
+import com.sun.jersey.api.client.config.ClientConfig;
+import com.sun.jersey.api.client.config.DefaultClientConfig;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class JsonRestClient {
+
+    private static final Logger LOG = LoggerFactory.getLogger(JsonRestClient.class);
+
+    private String uri;
+    private ClientConfig clientConfig;
+    private Client client;
+    private WebResource webResource;
+
+    public JsonRestClient(String uri, Integer connectTimeout, Integer readTimeout) {
+        Preconditions.checkNotNull(uri);
+
+        this.uri = uri;
+        clientConfig = new DefaultClientConfig();
+        clientConfig.getProperties()
+                .put(ClientConfig.PROPERTY_CONNECT_TIMEOUT, connectTimeout);
+        clientConfig.getProperties().put(ClientConfig.PROPERTY_READ_TIMEOUT, readTimeout);
+
+        client = Client.create(clientConfig);
+        webResource = client.resource(this.uri);
+    }
+
+    public String getHost() {
+        return webResource.getURI().getHost();
+    }
+
+    public JsonRestClientResponse get(String path) throws ClientHandlerException {
+        return get(path, null);
+    }
+
+    public JsonRestClientResponse get(String path, MultivaluedMap<String, String> params)
+            throws ClientHandlerException {
+        ClientResponse response;
+        WebResource r = this.webResource.path(path);
+        if (params == null) {
+            response = r.accept(MediaType.APPLICATION_JSON_TYPE).get(ClientResponse.class);
+        } else {
+            response = r.queryParams(params)
+                    .accept(MediaType.APPLICATION_JSON_TYPE)
+                    .get(ClientResponse.class);
+        }
+        return new JsonRestClientResponse(response);
+    }
+
+    public JsonRestClientResponse post(String path, String someJson) throws ClientHandlerException {
+        ClientResponse response;
+        response = webResource.path(path)
+                .accept(MediaType.APPLICATION_JSON_TYPE)
+                .type(MediaType.APPLICATION_JSON_TYPE)
+                .post(ClientResponse.class, someJson);
+        return new JsonRestClientResponse(response);
+    }
+
+    public JsonRestClientResponse put(String path, String someJson) throws ClientHandlerException {
+        ClientResponse response;
+        response = webResource.path(path)
+                .accept(MediaType.APPLICATION_JSON_TYPE)
+                .type(MediaType.APPLICATION_JSON_TYPE)
+                .put(ClientResponse.class, someJson);
+        return new JsonRestClientResponse(response);
+    }
+
+    public JsonRestClientResponse delete(String path) throws ClientHandlerException {
+        ClientResponse response;
+        response = webResource.path(path)
+                .accept(MediaType.APPLICATION_JSON_TYPE)
+                .delete(ClientResponse.class);
+        return new JsonRestClientResponse(response);
+    }
+
+}
diff --git a/renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/statistics/JsonRestClientResponse.java b/renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/statistics/JsonRestClientResponse.java
new file mode 100644 (file)
index 0000000..055baf5
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.groupbasedpolicy.renderer.ofoverlay.statistics;
+
+import javax.annotation.Nullable;
+
+import com.sun.jersey.api.client.ClientHandlerException;
+import com.sun.jersey.api.client.ClientResponse;
+import com.sun.jersey.api.client.UniformInterfaceException;
+
+public class JsonRestClientResponse {
+
+    private ClientResponse clientResponse;
+    private String entity;
+    private int statusCode;
+    private ClientHandlerException clientHandlerException;
+
+    public JsonRestClientResponse(ClientResponse clientResponse) {
+        this.clientResponse = clientResponse;
+        try {
+            entity = clientResponse.getEntity(String.class);
+        } catch (UniformInterfaceException e) {
+            // in case of 204 No Content
+            entity = null;
+        } catch (ClientHandlerException ex) {
+            clientHandlerException = ex;
+            // LOG.warn("Error getting response entity while status code is: {}",
+            // clientResponse.getClientResponseStatus(), ex);
+            entity = null;
+        }
+        this.statusCode = clientResponse.getStatus();
+    }
+
+    public ClientResponse getClientResponse() {
+        return clientResponse;
+    }
+
+    public int getStatusCode() {
+        return statusCode;
+    }
+
+    @Nullable
+    public String getJsonResponse() {
+        return entity;
+    }
+
+    @Nullable
+    public ClientHandlerException getClientHandlerException() {
+        return clientHandlerException;
+    }
+
+}
diff --git a/renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/statistics/OFStatisticsManager.java b/renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/statistics/OFStatisticsManager.java
new file mode 100755 (executable)
index 0000000..a17c315
--- /dev/null
@@ -0,0 +1,149 @@
+/*
+ * Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.groupbasedpolicy.renderer.ofoverlay.statistics;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.ScheduledFuture;
+import java.util.concurrent.TimeUnit;
+
+import javax.annotation.Nullable;
+
+import org.apache.commons.lang3.tuple.Pair;
+import org.opendaylight.groupbasedpolicy.api.StatisticsManager;
+import org.opendaylight.groupbasedpolicy.dto.ConsEpgKey;
+import org.opendaylight.groupbasedpolicy.dto.EpgKeyDto;
+import org.opendaylight.groupbasedpolicy.dto.ProvEpgKey;
+import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.statistics.flowcache.FlowCache;
+import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.statistics.flowcache.FlowCacheFactory;
+import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.statistics.util.FlowCacheCons;
+import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.statistics.util.IidSflowNameUtil;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ContractId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointL3;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.resolved.policy.rev150828.has.classifiers.Classifier;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.resolved.policy.rev150828.resolved.policies.ResolvedPolicy;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.resolved.policy.rev150828.resolved.policies.ResolvedPolicyKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.HashMultimap;
+import com.google.common.collect.SetMultimap;
+
+public class OFStatisticsManager implements AutoCloseable {
+
+    // key is String (not a full IpAddress) because
+    // we will get String from REST query to sFlow
+    private static ConcurrentMap<String, EndpointL3> endpointL3ByIpMap = new ConcurrentHashMap<>();
+
+    private static final Logger LOG = LoggerFactory.getLogger(OFStatisticsManager.class);
+
+    private final ScheduledExecutorService executor;
+    private final StatisticsManager statisticsManager;
+    private final Set<String> flowCacheNames = new HashSet<>();
+    private static final SetMultimap<ContractId, Pair<ConsEpgKey, ProvEpgKey>> epgsByContractId = HashMultimap.create();
+    private List<ScheduledFuture<?>> collectStatsTasks = new ArrayList<>();
+
+    private static int MAX_FLOWS = 100;
+    private static double MIN_VALUE_IN_FLOW = 0.1;
+    private static final String AGG_MODE = "sum";
+    private Long delay;
+    private String sflowCollectorUri;
+
+    public OFStatisticsManager(ScheduledExecutorService executor, StatisticsManager statisticsManager) {
+        this.executor = executor;
+        this.statisticsManager = statisticsManager;
+    }
+
+    public synchronized void pullStatsForClassifier(InstanceIdentifier<Classifier> classifierIid,
+            Classifier classifier) {
+        Preconditions.checkNotNull(sflowCollectorUri);
+        Preconditions.checkNotNull(delay);
+        FlowCache flowCache = FlowCacheFactory.createFlowCache(classifierIid, classifier, FlowCacheCons.Value.BYTES);
+        setStatsPulling(flowCache, classifierIid);
+        flowCache = FlowCacheFactory.createFlowCache(classifierIid, classifier, FlowCacheCons.Value.FRAMES);
+        setStatsPulling(flowCache, classifierIid);
+    }
+
+    private void setStatsPulling(FlowCache flowCache, InstanceIdentifier<Classifier> classifierIid) {
+        if (flowCache == null) {
+            LOG.trace("Flow cache is null for classifier {}", classifierIid);
+            return;
+        }
+        ResolvedPolicyKey resolvedPolicyKey = classifierIid.firstKeyOf(ResolvedPolicy.class);
+        ConsEpgKey consEpgKey =
+                new EpgKeyDto(resolvedPolicyKey.getConsumerEpgId(), resolvedPolicyKey.getConsumerTenantId());
+        ProvEpgKey provEpgKey =
+                new EpgKeyDto(resolvedPolicyKey.getProviderEpgId(), resolvedPolicyKey.getProviderTenantId());
+        String flowCacheName = flowCache.getName();
+        ContractId contractId = IidSflowNameUtil.resolveContractIdFromFlowCacheName(flowCacheName);
+        epgsByContractId.put(contractId, Pair.of(consEpgKey, provEpgKey));
+        boolean isFlowCacheNew = flowCacheNames.add(flowCacheName);
+        if (isFlowCacheNew) {
+            SFlowRTConnection sFlowRTConnection = new SFlowRTConnection(executor, sflowCollectorUri, flowCache);
+            ScheduledFuture<?> collectStatsTask = this.executor.scheduleWithFixedDelay(new ReadGbpFlowCacheTask(flowCacheName, sFlowRTConnection,
+                    statisticsManager, MAX_FLOWS, MIN_VALUE_IN_FLOW, AGG_MODE), 0, delay, TimeUnit.SECONDS);
+            collectStatsTasks.add(collectStatsTask);
+        }
+    }
+
+    public synchronized static Set<Pair<ConsEpgKey, ProvEpgKey>> getEpgsForContract(ContractId contractId) {
+        return epgsByContractId.get(contractId);
+    }
+
+    public synchronized void setSflowCollectorUri(String sflowCollectorUri) {
+        this.sflowCollectorUri = sflowCollectorUri;
+    }
+
+    public synchronized void setDelay(Long delay) {
+        this.delay = delay;
+    }
+
+    public static EndpointL3 getEndpointL3ForIp(@Nullable String ipAddress) {
+        if (ipAddress == null) {
+            return null;
+        }
+        return endpointL3ByIpMap.get(ipAddress);
+    }
+
+    public static void addL3Endpoint(EndpointL3 endpointL3) {
+        endpointL3ByIpMap.put(getStringIpAddress(endpointL3.getIpAddress()), endpointL3);
+    }
+
+    public static void removeL3Endpoint(EndpointL3 endpointL3) {
+        endpointL3ByIpMap.remove(getStringIpAddress(endpointL3.getIpAddress()));
+    }
+
+    private static String getStringIpAddress(IpAddress ipAddress) {
+        if (ipAddress.getIpv4Address() != null) {
+            return ipAddress.getIpv4Address().getValue();
+        }
+        return ipAddress.getIpv6Address().getValue();
+    }
+
+    @Override
+    public synchronized void close() throws Exception {
+        Iterator<ScheduledFuture<?>> tasksIterator = collectStatsTasks.iterator();
+        while (tasksIterator.hasNext()) {
+            ScheduledFuture<?> scheduledFuture = tasksIterator.next();
+            scheduledFuture.cancel(false);
+            tasksIterator.remove();
+        }
+        epgsByContractId.clear();
+    }
+
+}
diff --git a/renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/statistics/ProcessDataTask.java b/renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/statistics/ProcessDataTask.java
new file mode 100755 (executable)
index 0000000..1126150
--- /dev/null
@@ -0,0 +1,183 @@
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.groupbasedpolicy.renderer.ofoverlay.statistics;
+
+import java.math.BigInteger;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.commons.lang3.tuple.Pair;
+import org.opendaylight.groupbasedpolicy.api.StatisticsManager;
+import org.opendaylight.groupbasedpolicy.dto.ConsEpgKey;
+import org.opendaylight.groupbasedpolicy.dto.EpgKey;
+import org.opendaylight.groupbasedpolicy.dto.EpgKeyDto;
+import org.opendaylight.groupbasedpolicy.dto.ProvEpgKey;
+import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.statistics.flowcache.FlowCache;
+import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.statistics.flowcache.FlowCacheData;
+import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.statistics.util.FlowCacheCons;
+import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.statistics.util.IidSflowNameUtil;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ContractId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.EndpointGroupId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.TenantId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointL3;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.HasDirection.Direction;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.statistics.rev151215.statistic.records.StatRecords;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.statistics.rev151215.statistic.records.StatRecordsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.statistics.rev151215.statistic.records.stat.records.EpToEpStatistic;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.statistics.rev151215.statistic.records.stat.records.EpToEpStatisticBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.statistics.rev151215.statistic.records.stat.records.ep.to.ep.statistic.EpEpgToEpEpgStatistic;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.statistics.rev151215.statistic.records.stat.records.ep.to.ep.statistic.EpEpgToEpEpgStatisticBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.statistics.rev151215.statistic.records.stat.records.ep.to.ep.statistic.ep.epg.to.ep.epg.statistic.MatchedRuleStatisticBuilder;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.collect.ImmutableList;
+
+public class ProcessDataTask implements Runnable {
+
+    private static final Logger LOG = LoggerFactory.getLogger(ProcessDataTask.class);
+
+    private FlowCache flowCache;
+    private BigInteger timestamp;
+    private StatisticsManager statisticsManager;
+    List<FlowCacheData> dataList;
+
+    public ProcessDataTask(FlowCache flowCache, List<FlowCacheData> dataList, BigInteger timestamp,
+            StatisticsManager statisticsManager) {
+        this.flowCache = flowCache;
+        this.dataList = dataList;
+        this.timestamp = timestamp;
+        this.statisticsManager = statisticsManager;
+    }
+
+    @Override
+    public void run() {
+        for (FlowCacheData flowCacheData : dataList) {
+            Map<String, String> flowCacheDataMap = createFlowCacheDataMap(flowCacheData);
+            if (flowCacheDataMap == null) {
+                LOG.info("Stats are skipped for {}", flowCacheData);
+                continue;
+            }
+            String srcIp = flowCacheDataMap.get(FlowCacheCons.Key.IP_SOURCE.get());
+            String dstIp = flowCacheDataMap.get(FlowCacheCons.Key.IP_DESTINATION.get());
+            EndpointL3 srcEpL3 = OFStatisticsManager.getEndpointL3ForIp(srcIp);
+            EndpointL3 dstEpL3 = OFStatisticsManager.getEndpointL3ForIp(dstIp);
+            if (srcEpL3 != null && dstEpL3 != null) {
+                ContractId contractId = IidSflowNameUtil.resolveContractIdFromFlowCacheName(flowCache.getName());
+                MatchedRuleStatisticBuilder matchedRuleStatisticBuilder = new MatchedRuleStatisticBuilder()
+                .setContract(contractId)
+                .setSubject(IidSflowNameUtil.resolveSubjectNameFromFlowCacheName(flowCache.getName()))
+                .setMatchedRule(IidSflowNameUtil.resolveRuleNameFromFlowCacheName(flowCache.getName()))
+                .setClassifier(ImmutableList
+                    .of(IidSflowNameUtil.resolveClassifierNameFromFlowCacheName(flowCache.getName())));
+                if (FlowCacheCons.Value.BYTES.get().equals(IidSflowNameUtil.resolveFlowCacheValue(flowCache.getName()))) {
+                    matchedRuleStatisticBuilder.setByteCount(Math.round(flowCacheData.getValue()));
+                } else if (FlowCacheCons.Value.FRAMES.get().equals(IidSflowNameUtil.resolveFlowCacheValue(flowCache.getName()))) {
+                    matchedRuleStatisticBuilder.setPacketCount(Math.round(flowCacheData.getValue()));
+                }
+
+                Set<Pair<ConsEpgKey, ProvEpgKey>> epgsForContract = OFStatisticsManager.getEpgsForContract(contractId);
+                Set<EpgKey> epgsFromSrcEp = getEpgsFromEndpoint(srcEpL3);
+                Set<EpgKey> epgsFromDstEp = getEpgsFromEndpoint(dstEpL3);
+                Pair<? extends EpgKey, ? extends EpgKey> leftSrcEpgRightDstEpg = getMatchingEpgs(epgsForContract, epgsFromSrcEp, epgsFromDstEp, flowCache.getDirection());
+                if (leftSrcEpgRightDstEpg == null) {
+                    LOG.info("Stats are skipped for {}", flowCacheData);
+                    continue;
+                }
+
+                EpEpgToEpEpgStatistic epEpgToEpEpgStats = new EpEpgToEpEpgStatisticBuilder()
+                    .setSrcEpg(leftSrcEpgRightDstEpg.getLeft().getEpgId())
+                    .setDstEpg(leftSrcEpgRightDstEpg.getRight().getEpgId())
+                    .setMatchedRuleStatistic(ImmutableList.of(matchedRuleStatisticBuilder.build()))
+                    .build();
+
+                EpToEpStatistic e2e = new EpToEpStatisticBuilder().setSrcL2c(srcEpL3.getL2Context())
+                    .setSrcMacAddress(srcEpL3.getMacAddress())
+                    .setSrcTenant(srcEpL3.getTenant())
+                    .setDstL2c(dstEpL3.getL2Context())
+                    .setDstMacAddress(dstEpL3.getMacAddress())
+                    .setDstTenant(dstEpL3.getTenant())
+                    .setEpEpgToEpEpgStatistic(ImmutableList.of(epEpgToEpEpgStats))
+                    .setTimestamp(timestamp)
+                    .build();
+
+                StatRecords statRecords = new StatRecordsBuilder().setEpToEpStatistic(ImmutableList.of(e2e)).build();
+
+                if (LOG.isTraceEnabled()) {
+                    LOG.trace("[sflow] writing StatRecords: {}", statRecords);
+                }
+                statisticsManager.writeStat(statRecords);
+            }
+        }
+    }
+
+    private Set<EpgKey> getEpgsFromEndpoint(EndpointL3 epL3) {
+        Set<EpgKey> result = new HashSet<>();
+        TenantId tenantId = epL3.getTenant();
+        if (epL3.getEndpointGroup() != null) {
+            result.add(new EpgKeyDto(epL3.getEndpointGroup(), tenantId));
+        }
+        List<EndpointGroupId> epgs = epL3.getEndpointGroups();
+        if (epgs != null) {
+            for (EndpointGroupId epg : epgs) {
+                result.add(new EpgKeyDto(epg, tenantId));
+            }
+        }
+        return result;
+    }
+
+    private Pair<? extends EpgKey, ? extends EpgKey> getMatchingEpgs(Set<Pair<ConsEpgKey, ProvEpgKey>> epgsForContract,
+            Set<EpgKey> epgsFromSrcEp, Set<EpgKey> epgsFromDstEp, Direction direction) {
+        if (direction == null || Direction.Bidirectional == direction) {
+            LOG.info("The bidirectional direction is not supported.");
+            return null;
+        }
+        for (Pair<ConsEpgKey, ProvEpgKey> epgForContract : epgsForContract) {
+            ConsEpgKey consEpg = epgForContract.getLeft();
+            ProvEpgKey provEpg = epgForContract.getRight();
+            if (epgsFromSrcEp.contains(consEpg) && epgsFromDstEp.contains(provEpg)) {
+                if (Direction.In.equals(direction)) {
+                    return Pair.of(consEpg, provEpg);
+                } else if (Direction.Out.equals(direction)) {
+                    return Pair.of(provEpg, consEpg);
+                }
+            }
+            if (epgsFromSrcEp.contains(provEpg) && epgsFromDstEp.contains(consEpg)) {
+                if (Direction.In.equals(direction)) {
+                    return Pair.of(consEpg, provEpg);
+                } else if (Direction.Out.equals(direction)) {
+                    return Pair.of(provEpg, consEpg);
+                }
+            }
+        }
+        LOG.info(
+                "EPGs of srcEP and dstEp does not match against EPGs for contract:"
+                        + "\nsrcEP EPGs: {}\ndstEP EPGs: {}\nEPGs for contract: {}",
+                epgsFromSrcEp, epgsFromDstEp, epgsForContract);
+        return null;
+    }
+
+    private Map<String, String> createFlowCacheDataMap(FlowCacheData flowCacheData) {
+        String[] splitValues = flowCacheData.getKey().split(",");
+        if (splitValues.length != flowCache.getKeyNum()) {
+            LOG.error(
+                    "Key names and key values lists length do not match: {} != {}. Not processing.",
+                    flowCache.getKeyNum(), splitValues.length);
+            return null;
+        }
+        Map<String, String> flowCacheDataMap = new HashMap<>();
+        for (int i = 0; i < flowCache.getKeyNum(); i++) {
+            flowCacheDataMap.put(flowCache.getKeyNames()[i], splitValues[i]);
+        }
+        return flowCacheDataMap;
+    }
+
+}
diff --git a/renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/statistics/ReadGbpFlowCacheTask.java b/renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/statistics/ReadGbpFlowCacheTask.java
new file mode 100755 (executable)
index 0000000..bd476cf
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.groupbasedpolicy.renderer.ofoverlay.statistics;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.lang.reflect.Type;
+import java.math.BigInteger;
+import java.util.Date;
+import java.util.List;
+
+import javax.ws.rs.core.MultivaluedMap;
+
+import org.opendaylight.groupbasedpolicy.api.StatisticsManager;
+import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.statistics.flowcache.FlowCacheData;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.gson.Gson;
+import com.google.gson.reflect.TypeToken;
+import com.sun.jersey.core.util.MultivaluedMapImpl;
+
+public class ReadGbpFlowCacheTask implements Runnable {
+
+    private static final Logger LOG = LoggerFactory.getLogger(ReadGbpFlowCacheTask.class);
+
+    private static final Type LIST_OF_FLOW_CACHE_DATA = new TypeToken<List<FlowCacheData>>() {}.getType();
+    private static final Gson GSON = new Gson();
+    private static final String MAX_FLOWS_PARAM = "maxFlows";
+    private static final String MIN_VALUE_PARAM = "minValue";
+    private static final String AGG_MODE_PARAM = "aggMode";
+
+    private final SFlowRTConnection sFlowRTConnection;
+    private final StatisticsManager statisticsManager;
+    private final String maxFlows;
+    private final String minValue;
+    private final String aggMode;
+    private final String path;
+
+    public ReadGbpFlowCacheTask(String flowCacheName, SFlowRTConnection sFlowRTConnection,
+            StatisticsManager statisticsManager, Integer maxFlows, Double minValue, String aggMode) {
+        this.path = "/activeflows/ALL/" + checkNotNull(flowCacheName) + "/json";
+        this.sFlowRTConnection = checkNotNull(sFlowRTConnection);
+        this.statisticsManager = checkNotNull(statisticsManager);
+        this.maxFlows = String.valueOf(checkNotNull(maxFlows));
+        this.minValue = String.valueOf(checkNotNull(minValue));
+        this.aggMode = checkNotNull(aggMode);
+    }
+
+    @Override
+    public void run() {
+        MultivaluedMap<String, String> params = new MultivaluedMapImpl();
+        params.add(MAX_FLOWS_PARAM, maxFlows);
+        params.add(MIN_VALUE_PARAM, minValue);
+        params.add(AGG_MODE_PARAM, aggMode);
+        JsonRestClientResponse result = sFlowRTConnection.get(path, params);
+
+        if (result != null && result.getJsonResponse() != null) {
+            List<FlowCacheData> dataList = GSON.fromJson(result.getJsonResponse(), LIST_OF_FLOW_CACHE_DATA);
+            if (dataList == null) {
+                LOG.trace("Empty reply, not processing");
+                return;
+            }
+            if (LOG.isTraceEnabled()) {
+                LOG.trace("Got sFlow reply: {}", result.getJsonResponse());
+            }
+
+            if (result.getStatusCode() < 300) {
+                sFlowRTConnection.getExecutor().execute((new ProcessDataTask(sFlowRTConnection.getFlowCache(), dataList,
+                        BigInteger.valueOf(new Date().getTime()), statisticsManager)));
+            } else if (result.getStatusCode() < 400) {
+                LOG.warn("Status code {}, not processing data. Response: {}", result.getStatusCode(),
+                        result.getClientResponse().toString());
+            } else {
+                LOG.error("Status code {}, not processing data. Response: {}", result.getStatusCode(),
+                        result.getClientResponse().toString());
+            }
+        }
+    }
+}
diff --git a/renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/statistics/ResolvedPolicyClassifierListener.java b/renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/statistics/ResolvedPolicyClassifierListener.java
new file mode 100644 (file)
index 0000000..e7faaac
--- /dev/null
@@ -0,0 +1,124 @@
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.groupbasedpolicy.renderer.ofoverlay.statistics;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.DataObjectModification;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeIdentifier;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.groupbasedpolicy.util.DataTreeChangeHandler;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.resolved.policy.rev150828.ResolvedPolicies;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.resolved.policy.rev150828.has.classifiers.Classifier;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.resolved.policy.rev150828.has.resolved.rules.ResolvedRule;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.resolved.policy.rev150828.resolved.policies.ResolvedPolicy;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.resolved.policy.rev150828.resolved.policies.resolved.policy.PolicyRuleGroupWithEndpointConstraints;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.resolved.policy.rev150828.resolved.policies.resolved.policy.policy.rule.group.with.endpoint.constraints.PolicyRuleGroup;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.collect.MapDifference;
+import com.google.common.collect.Maps;
+
+public class ResolvedPolicyClassifierListener extends DataTreeChangeHandler<ResolvedPolicy> {
+
+    private static final Logger LOG = LoggerFactory.getLogger(ResolvedPolicyClassifierListener.class);
+    private final OFStatisticsManager ofStatsManager;
+
+    public ResolvedPolicyClassifierListener(DataBroker dataProvider, OFStatisticsManager ofStatsManager) {
+        super(dataProvider, new DataTreeIdentifier<>(LogicalDatastoreType.OPERATIONAL,
+                InstanceIdentifier.builder(ResolvedPolicies.class).child(ResolvedPolicy.class).build()));
+        this.ofStatsManager = checkNotNull(ofStatsManager);
+    }
+
+    @Override
+    protected void onWrite(DataObjectModification<ResolvedPolicy> rootNode,
+            InstanceIdentifier<ResolvedPolicy> rootIdentifier) {
+        ResolvedPolicy resolvedPolicy = rootNode.getDataAfter();
+        Map<InstanceIdentifier<Classifier>, Classifier> classifierByIid =
+                resolveClassifiers(resolvedPolicy, rootIdentifier);
+        for (Entry<InstanceIdentifier<Classifier>, Classifier> classfierEntry : classifierByIid.entrySet()) {
+            LOG.trace("New classifier created: {}\n{}", classfierEntry.getKey(), classfierEntry.getValue());
+            ofStatsManager.pullStatsForClassifier(classfierEntry.getKey(), classfierEntry.getValue());
+        }
+    }
+
+    @Override
+    protected void onDelete(DataObjectModification<ResolvedPolicy> rootNode,
+            InstanceIdentifier<ResolvedPolicy> rootIdentifier) {
+        LOG.debug("Delete is not supported yet.");
+    }
+
+    @Override
+    protected void onSubtreeModified(DataObjectModification<ResolvedPolicy> rootNode,
+            InstanceIdentifier<ResolvedPolicy> rootIdentifier) {
+        ResolvedPolicy resolvedPolicyAfter = rootNode.getDataAfter();
+        ResolvedPolicy resolvedPolicyBefore = rootNode.getDataBefore();
+        Map<InstanceIdentifier<Classifier>, Classifier> classifierByIidAfter =
+                resolveClassifiers(resolvedPolicyAfter, rootIdentifier);
+        Map<InstanceIdentifier<Classifier>, Classifier> classifierByIidBefore =
+                resolveClassifiers(resolvedPolicyBefore, rootIdentifier);
+        MapDifference<InstanceIdentifier<Classifier>, Classifier> difference =
+                Maps.difference(classifierByIidBefore, classifierByIidAfter);
+        Map<InstanceIdentifier<Classifier>, Classifier> createdClassifierByIid = difference.entriesOnlyOnRight();
+        for (Entry<InstanceIdentifier<Classifier>, Classifier> createdClassfierEntry : createdClassifierByIid
+            .entrySet()) {
+            LOG.trace("New classifier created: {}\n{}", createdClassfierEntry.getKey(),
+                    createdClassfierEntry.getValue());
+            ofStatsManager.pullStatsForClassifier(createdClassfierEntry.getKey(), createdClassfierEntry.getValue());
+        }
+        // TODO missing impl for case when classifier is changed or removed
+    }
+
+    private Map<InstanceIdentifier<Classifier>, Classifier> resolveClassifiers(ResolvedPolicy resolvedPolicy,
+            InstanceIdentifier<ResolvedPolicy> resolvedPolicyIid) {
+        List<PolicyRuleGroupWithEndpointConstraints> policyRgWithEcs =
+                resolvedPolicy.getPolicyRuleGroupWithEndpointConstraints();
+        if (policyRgWithEcs == null) {
+            return Collections.emptyMap();
+        }
+        Map<InstanceIdentifier<Classifier>, Classifier> result = new HashMap<>();
+        for (PolicyRuleGroupWithEndpointConstraints policyRgWithEc : policyRgWithEcs) {
+            List<PolicyRuleGroup> policyRuleGroups = policyRgWithEc.getPolicyRuleGroup();
+            if (policyRuleGroups == null) {
+                continue;
+            }
+            for (PolicyRuleGroup policyRuleGroup : policyRuleGroups) {
+                List<ResolvedRule> resolvedRules = policyRuleGroup.getResolvedRule();
+                if (resolvedRules == null) {
+                    continue;
+                }
+                for (ResolvedRule resolvedRule : resolvedRules) {
+                    List<Classifier> classifiers = resolvedRule.getClassifier();
+                    if (classifiers == null) {
+                        continue;
+                    }
+                    for (Classifier classifier : classifiers) {
+                        InstanceIdentifier<Classifier> classifierIid = resolvedPolicyIid.builder()
+                            .child(PolicyRuleGroupWithEndpointConstraints.class)
+                            .child(PolicyRuleGroup.class, policyRuleGroup.getKey())
+                            .child(ResolvedRule.class, resolvedRule.getKey())
+                            .child(Classifier.class, classifier.getKey())
+                            .build();
+                        result.put(classifierIid, classifier);
+                    }
+                }
+            }
+        }
+        return result;
+    }
+
+}
diff --git a/renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/statistics/SFlowRTConnection.java b/renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/statistics/SFlowRTConnection.java
new file mode 100755 (executable)
index 0000000..9a390fe
--- /dev/null
@@ -0,0 +1,178 @@
+/*
+ * Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.groupbasedpolicy.renderer.ofoverlay.statistics;
+
+import javax.annotation.Nullable;
+import javax.ws.rs.core.MultivaluedMap;
+import java.util.concurrent.ScheduledExecutorService;
+
+import com.google.common.base.Preconditions;
+import com.sun.jersey.api.client.ClientHandlerException;
+import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.statistics.flowcache.FlowCache;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class SFlowRTConnection {
+
+    private static final Logger LOG = LoggerFactory.getLogger(SFlowRTConnection.class);
+
+    private static final int CONNECT_TIMEOUT_MILLISEC = 20000;
+    private static final int READ_TIMEOUT_MILLISEC = 30000;
+    private static final String GET = "GET";
+    private static final String PUT = "PUT";
+    private static final String DELETE = "DELETE";
+
+    private final FlowCache flowCache;
+    private JsonRestClient client;
+    private boolean isInitialized = false;
+    private final ScheduledExecutorService executor;
+    private final String collectorUri;
+
+    public SFlowRTConnection(ScheduledExecutorService executor, String collectorUri, FlowCache flowCache) {
+        this.executor = Preconditions.checkNotNull(executor);
+        this.collectorUri = Preconditions.checkNotNull(collectorUri);
+        this.flowCache = Preconditions.checkNotNull(flowCache);
+
+        this.client = new JsonRestClient(collectorUri, CONNECT_TIMEOUT_MILLISEC,
+                READ_TIMEOUT_MILLISEC);
+        initialize();
+    }
+
+    @Nullable
+    public String getJsonResponse(String path, MultivaluedMap<String, String> params) {
+        try {
+            JsonRestClientResponse responce = client.get(path, params);
+            Preconditions.checkNotNull(responce);
+            logStatusCode(GET, responce.getStatusCode(), path, params);
+            return responce.getJsonResponse();
+        } catch (ClientHandlerException e) {
+            processClientHandlerException(e);
+        }
+        return null;
+    }
+
+    @Nullable
+    public JsonRestClientResponse get(String path,
+            MultivaluedMap<String, String> params) {
+        if (!isInitialized()) {
+            throw new IllegalStateException("SFlowRTConnection is not initialized.");
+        }
+        try {
+            JsonRestClientResponse responce = client.get(path, params);
+            Preconditions.checkNotNull(responce);
+            return responce;
+        } catch (ClientHandlerException e) {
+            processClientHandlerException(e);
+        }
+        return null;
+    }
+
+    @Nullable
+    public JsonRestClientResponse put(String path, String someJson) {
+        if (!isInitialized()) {
+            throw new IllegalStateException("SFlowRTConnection is not initialized.");
+        }
+        return putWithoutInitCheck(path, someJson);
+    }
+
+    private JsonRestClientResponse putWithoutInitCheck(String path,
+            String someJson) {
+        try {
+            JsonRestClientResponse responce = client.put(path, someJson);
+            Preconditions.checkNotNull(responce);
+            logStatusCode(PUT, responce.getStatusCode(), path, null);
+            return responce;
+        } catch (ClientHandlerException e) {
+            processClientHandlerException(e);
+        }
+        return null;
+    }
+
+    public JsonRestClientResponse delete(String path) {
+        if (!isInitialized()) {
+            throw new IllegalStateException("SFlowRTConnection is not initialized.");
+        }
+        try {
+            JsonRestClientResponse responce = client.delete(path);
+            Preconditions.checkNotNull(responce);
+            logStatusCode(DELETE, responce.getStatusCode(), path, null);
+            return responce;
+        } catch (ClientHandlerException e) {
+            processClientHandlerException(e);
+        }
+        return null;
+    }
+
+    public boolean isInitialized() {
+        return isInitialized;
+    }
+
+    public FlowCache getFlowCache() {
+        return flowCache;
+    }
+
+    public ScheduledExecutorService getExecutor() {
+        return executor;
+    }
+
+    public String getCollectorUri() {
+        return collectorUri;
+    }
+
+    public void initialize() {
+        if (LOG.isTraceEnabled()) {
+            LOG.trace("Initializing flow {}", flowCache);
+        }
+        JsonRestClientResponse initResp =
+                putWithoutInitCheck(flowCache.getPath(), flowCache.getJsonDefinition());
+        Preconditions.checkNotNull(initResp);
+        if (initResp.getStatusCode() < 300) {
+            LOG.info("sFlow connection {} initialization status code {}", getCollectorUri(), initResp.getStatusCode());
+        } else if (initResp.getStatusCode() < 400) {
+            LOG.warn("sFlow connection {} initialization status code {}", getCollectorUri(), initResp.getStatusCode());
+        } else {
+            LOG.error("sFlow connection {} initialization status code {}", getCollectorUri(), initResp.getStatusCode());
+        }
+        this.isInitialized = true;
+    }
+
+    private void processClientHandlerException(ClientHandlerException e) {
+        if (e.getCause() instanceof java.net.SocketTimeoutException || e.getCause() instanceof java.net.ConnectException) {
+            LOG.error("Connection to {} failed: {}", client.getHost(), e.getMessage());
+            this.isInitialized = false;
+            throw e;
+        } else {
+            throw e;
+        }
+    }
+
+    private void logStatusCode(String verb, int status, String path,
+            MultivaluedMap<String, String> params) {
+        if (params != null) {
+            if (status <= 204) {
+                LOG.trace("Query {} {} with params {} returned status {}", verb, path, params,
+                        status);
+            } else if (status < 400) {
+                LOG.warn("Query {} {} with params {} returned status {}", verb, path, params,
+                        status);
+            } else {
+                LOG.error("Query {} {} with params {} returned status {}", verb, path, params,
+                        status);
+            }
+        } else {
+            if (status <= 204) {
+                LOG.trace("Query {} {} returned status {}", verb, path, status);
+            } else if (status < 400) {
+                LOG.warn("Query {} {} returned status {}", verb, path, status);
+            } else {
+                LOG.error("Query {} {} returned status {}", verb, path, status);
+            }
+        }
+    }
+
+}
diff --git a/renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/statistics/SflowClientSettingsListener.java b/renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/statistics/SflowClientSettingsListener.java
new file mode 100755 (executable)
index 0000000..ec0a0bf
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.groupbasedpolicy.renderer.ofoverlay.statistics;
+
+import java.util.concurrent.ScheduledExecutorService;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.DataObjectModification;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeIdentifier;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.groupbasedpolicy.api.StatisticsManager;
+import org.opendaylight.groupbasedpolicy.util.DataTreeChangeHandler;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.ofoverlay.rev140528.OfOverlayConfig;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.ofoverlay.rev140528.sflow.values.SflowClientSettings;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Preconditions;
+
+public class SflowClientSettingsListener extends DataTreeChangeHandler<SflowClientSettings> {
+
+    private static final Logger LOG = LoggerFactory.getLogger(SflowClientSettingsListener.class);
+    private static InstanceIdentifier<SflowClientSettings> IID =
+            InstanceIdentifier.builder(OfOverlayConfig.class)
+                    .child(SflowClientSettings.class)
+                    .build();
+    private OFStatisticsManager ofStatisticsManager;
+    private final ScheduledExecutorService executor;
+    private final StatisticsManager statisticsManager;
+    private ResolvedPolicyClassifierListener classifierListener;
+
+    public SflowClientSettingsListener(DataBroker dataprovider, ScheduledExecutorService executor, StatisticsManager statisticsManager) {
+        super(dataprovider, new DataTreeIdentifier<>(LogicalDatastoreType.CONFIGURATION, IID));
+        this.statisticsManager = Preconditions.checkNotNull(statisticsManager);
+        this.executor = Preconditions.checkNotNull(executor);
+    }
+
+    @Override
+    protected void onWrite(DataObjectModification<SflowClientSettings> rootNode,
+            InstanceIdentifier<SflowClientSettings> rootIdentifier) {
+        onSubtreeModified(rootNode, rootIdentifier);
+    }
+
+    @Override
+    protected void onDelete(DataObjectModification<SflowClientSettings> rootNode,
+            InstanceIdentifier<SflowClientSettings> rootIdentifier) {
+        try {
+            classifierListener.close();
+            ofStatisticsManager.close();
+        } catch (Exception e) {
+            LOG.error(
+                    "Error during closing OFStatisticsManager and ResolvedPolicyClassifierListener. "
+                    + "Statistics do not have to be correct because of illegal state.", e);
+        }
+    }
+
+    @Override
+    protected void onSubtreeModified(DataObjectModification<SflowClientSettings> rootNode,
+            InstanceIdentifier<SflowClientSettings> rootIdentifier) {
+        SflowClientSettings sflowClientSettings =
+                Preconditions.checkNotNull(rootNode.getDataAfter());
+        if (classifierListener != null && ofStatisticsManager != null) {
+            try {
+                classifierListener.close();
+                ofStatisticsManager.close();
+            } catch (Exception e) {
+                LOG.error(
+                        "Error during closing OFStatisticsManager and ResolvedPolicyClassifierListener. "
+                        + "Statistics do not have to be correct because of illegal state.", e);
+            }
+        }
+        ofStatisticsManager = new OFStatisticsManager(executor, statisticsManager);
+        ofStatisticsManager.setSflowCollectorUri(sflowClientSettings.getGbpOfoverlaySflowCollectorUri());
+        ofStatisticsManager.setDelay(sflowClientSettings.getGbpOfoverlaySflowRetrieveInterval());
+        classifierListener = new ResolvedPolicyClassifierListener(dataProvider, ofStatisticsManager);
+    }
+}
diff --git a/renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/statistics/flowcache/FlowCache.java b/renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/statistics/flowcache/FlowCache.java
new file mode 100755 (executable)
index 0000000..6aca699
--- /dev/null
@@ -0,0 +1,128 @@
+/*
+ * Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.groupbasedpolicy.renderer.ofoverlay.statistics.flowcache;
+
+import java.util.Arrays;
+
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.HasDirection.Direction;
+
+import com.google.common.base.Preconditions;
+import com.google.gson.Gson;
+
+public class FlowCache {
+
+    static final String API_FLOW = "/flow/";
+    static final String SUFFIX_JSON = "/json";
+
+    private transient Direction direction;
+    private String name;
+    private FlowCacheDefinition definition;
+
+    /** Array containing key names from FlowCacheDefinition */
+    private String[] keyNames;
+    private int keyNum;
+
+    private FlowCache() {
+    }
+
+    private FlowCache(FlowCacheBuilder builder) {
+        this.name = builder.getName();
+        this.definition = builder.getDefinition();
+        this.direction = builder.getDirection();
+
+        this.keyNames = this.definition.getKeys().split(",");
+        this.keyNum = this.keyNames.length;
+        for (int i = 0; i < this.keyNum; i++) {
+            keyNames[i] = parseNullableKeyName(keyNames[i]);
+        }
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public FlowCacheDefinition getDefinition() {
+        return definition;
+    }
+
+    public Direction getDirection() {
+        return direction;
+    }
+
+    public String[] getKeyNames() {
+        return keyNames;
+    }
+
+    public int getKeyNum() {
+        return keyNum;
+    }
+
+    public String getPath() {
+        return API_FLOW + name + SUFFIX_JSON;
+    }
+
+    public String getJsonDefinition() {
+        Gson gson = new Gson();
+        return gson.toJson(definition);
+    }
+
+    public static FlowCacheBuilder builder() {
+        return new FlowCacheBuilder();
+    }
+
+    private String parseNullableKeyName(String nullableKeyName) {
+        String res = nullableKeyName.replaceAll("^\\w+:(\\w+):.*", "$1");
+        return "".equals(res) ? nullableKeyName : res;
+    }
+
+    @Override
+    public String toString() {
+        return "FlowCache [name=" + name + ", definition=" + definition + ", keyNames=" + Arrays.toString(keyNames)
+                + ", keyNum=" + keyNum + "]";
+    }
+
+    public static class FlowCacheBuilder {
+
+        private String name;
+        private FlowCacheDefinition definition;
+        private Direction direction;
+
+        public String getName() {
+            return name;
+        }
+
+        public FlowCacheBuilder setName(String name) {
+            Preconditions.checkNotNull(name);
+            this.name = name;
+            return this;
+        }
+
+        public FlowCacheDefinition getDefinition() {
+            return definition;
+        }
+
+        public FlowCacheBuilder setDefinition(FlowCacheDefinition definition) {
+            Preconditions.checkNotNull(definition);
+            this.definition = definition;
+            return this;
+        }
+
+        public Direction getDirection() {
+            return direction;
+        }
+
+        public FlowCacheBuilder setDirection(Direction direction) {
+            this.direction = direction;
+            return this;
+        }
+
+        public FlowCache build() {
+            return new FlowCache(this);
+        }
+    }
+}
diff --git a/renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/statistics/flowcache/FlowCacheData.java b/renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/statistics/flowcache/FlowCacheData.java
new file mode 100755 (executable)
index 0000000..77e4ce4
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.groupbasedpolicy.renderer.ofoverlay.statistics.flowcache;
+
+public class FlowCacheData {
+
+    private String key;
+    private double value;
+
+    private FlowCacheData() {
+    }
+
+    public String getKey() {
+        return key;
+    }
+
+    public double getValue() {
+        return value;
+    }
+
+    @Override
+    public String toString() {
+        return "FlowCacheData [key=" + key + ", value=" + value + "]";
+    }
+
+}
diff --git a/renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/statistics/flowcache/FlowCacheDefinition.java b/renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/statistics/flowcache/FlowCacheDefinition.java
new file mode 100755 (executable)
index 0000000..f060e49
--- /dev/null
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.groupbasedpolicy.renderer.ofoverlay.statistics.flowcache;
+
+import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.statistics.flowcache.FlowCacheFilter.FlowCacheFilterBuilder;
+import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.statistics.flowcache.FlowCacheKeys.FlowCacheKeysBuilder;
+
+import com.google.common.base.Preconditions;
+
+/**
+ * An object to handle flow-cache parameters for JSON conversion
+ */
+public final class FlowCacheDefinition {
+
+    private String keys;
+    private String value;
+    private String filter;
+    private boolean log;
+
+    private FlowCacheDefinition() {
+    }
+
+    private FlowCacheDefinition(FlowCacheDefinitionBuilder builder) {
+        this.keys = builder.getKeysBuilder().build().getValue();
+        this.value = builder.getValue();
+        this.filter = builder.getFilterBuilder().build().getValue();
+        this.log = builder.isLog();
+    }
+
+    public String getKeys() {
+        return keys;
+    }
+
+    public String getValue() {
+        return value;
+    }
+
+    public String getFilter() {
+        return filter;
+    }
+
+    public boolean getLog() {
+        return log;
+    }
+
+    public static FlowCacheDefinitionBuilder builder(){
+        return new FlowCacheDefinitionBuilder();
+    }
+
+    @Override
+    public String toString() {
+        return "FlowCacheDefinition [keys=" + keys + ", value=" + value + ", filter=" + filter + ", log=" + log + "]";
+    }
+
+    public static class FlowCacheDefinitionBuilder {
+
+        private String value;
+        private boolean log = false;
+        private final FlowCacheKeysBuilder keysBuilder = new FlowCacheKeysBuilder();
+        private final FlowCacheFilterBuilder filterBuilder = new FlowCacheFilterBuilder();
+
+        public FlowCacheKeysBuilder getKeysBuilder() {
+            return keysBuilder;
+        }
+
+        public String getValue() {
+            return value;
+        }
+
+        public FlowCacheDefinitionBuilder setValue(String value) {
+            Preconditions.checkNotNull(value);
+            this.value = value;
+            return this;
+        }
+
+        public FlowCacheFilterBuilder getFilterBuilder() {
+            return filterBuilder;
+        }
+
+        public boolean isLog() {
+            return log;
+        }
+
+        public FlowCacheDefinitionBuilder setLog(boolean log) {
+            this.log = log;
+            return this;
+        }
+
+        public FlowCacheDefinition build() {
+            return new FlowCacheDefinition(this);
+        }
+    }
+}
diff --git a/renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/statistics/flowcache/FlowCacheFactory.java b/renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/statistics/flowcache/FlowCacheFactory.java
new file mode 100644 (file)
index 0000000..d40465e
--- /dev/null
@@ -0,0 +1,159 @@
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.groupbasedpolicy.renderer.ofoverlay.statistics.flowcache;
+
+import java.util.List;
+
+import org.opendaylight.groupbasedpolicy.api.sf.EtherTypeClassifierDefinition;
+import org.opendaylight.groupbasedpolicy.api.sf.IpProtoClassifierDefinition;
+import org.opendaylight.groupbasedpolicy.api.sf.L4ClassifierDefinition;
+import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils;
+import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.statistics.flowcache.FlowCache.FlowCacheBuilder;
+import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.statistics.flowcache.FlowCacheDefinition.FlowCacheDefinitionBuilder;
+import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.statistics.util.FlowCacheCons;
+import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.statistics.util.IidSflowNameUtil;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.subject.feature.instance.ParameterValue;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.resolved.policy.rev150828.has.classifiers.Classifier;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class FlowCacheFactory {
+
+    private static final Logger LOG = LoggerFactory.getLogger(FlowCacheFactory.class);
+
+    public static FlowCache createFlowCache(InstanceIdentifier<Classifier> classifierIid, Classifier classifier,
+            FlowCacheCons.Value value) {
+        FlowCacheDefinition flowCacheDefinition = creteFlowCacheDefinition(classifier, value);
+        if (flowCacheDefinition == null) {
+            LOG.info("Cannot create flow cache for statistics of classifier {}\n{}", classifierIid, classifier);
+            return null;
+        }
+        return new FlowCacheBuilder().setDefinition(flowCacheDefinition)
+            .setName(IidSflowNameUtil.createFlowCacheName(classifierIid, value))
+            .setDirection(classifier.getDirection())
+            .build();
+    }
+
+    public static FlowCacheDefinition creteFlowCacheDefinition(Classifier classifier, FlowCacheCons.Value value) {
+        FlowCacheDefinitionBuilder fcdBuilder = new FlowCacheDefinitionBuilder();
+        if (L4ClassifierDefinition.ID.equals(classifier.getClassifierDefinitionId())) {
+            addEthTypeInfoToFlowCache(classifier, fcdBuilder);
+            if (!addIpProtoInfoToFlowCache(classifier, fcdBuilder)) {
+                return null;
+            }
+            if (!addL4InfoToFlowCache(classifier, fcdBuilder)) {
+                return null;
+            }
+        } else if (IpProtoClassifierDefinition.ID.equals(classifier.getClassifierDefinitionId())) {
+            addEthTypeInfoToFlowCache(classifier, fcdBuilder);
+            if (!addIpProtoInfoToFlowCache(classifier, fcdBuilder)) {
+                return null;
+            }
+        } else if (EtherTypeClassifierDefinition.ID.equals(classifier.getClassifierDefinitionId())) {
+            addEthTypeInfoToFlowCache(classifier, fcdBuilder);
+        } else {
+            LOG.warn("Sflow stats will not be pulled because of unknown classifier: {}", classifier);
+            return null;
+        }
+        fcdBuilder.getKeysBuilder().addValue(FlowCacheCons.Key.IP_SOURCE.get()).addValue(FlowCacheCons.Key.IP_DESTINATION.get());
+        fcdBuilder.setValue(value.get());
+        return fcdBuilder.build();
+    }
+
+    private static void addEthTypeInfoToFlowCache(Classifier classifier, FlowCacheDefinitionBuilder fcdBuilder) {
+        List<ParameterValue> parametersAndValues = classifier.getParameterValue();
+        ParameterValue ethTypeParam = getParamVal(parametersAndValues, EtherTypeClassifierDefinition.ETHERTYPE_PARAM);
+        if (ethTypeParam != null) {
+            fcdBuilder.getKeysBuilder().addValue(FlowCacheCons.Key.ETH_PROTOCOL.get());
+            fcdBuilder.getFilterBuilder()
+                .addValue(FlowCacheCons.Key.ETH_PROTOCOL.get() + FlowCacheCons.EQ + ethTypeParam.getIntValue());
+        } else {
+            fcdBuilder.getKeysBuilder().addValue(FlowCacheCons.Key.ETH_PROTOCOL.get());
+            fcdBuilder.getFilterBuilder()
+                .addValue(FlowCacheCons.Key.ETH_PROTOCOL.get() + FlowCacheCons.EQ + FlowUtils.IPv4 + FlowCacheCons.OR
+                        + FlowCacheCons.Key.ETH_PROTOCOL.get() + FlowCacheCons.EQ + FlowUtils.IPv6);
+        }
+    }
+
+    private static boolean addIpProtoInfoToFlowCache(Classifier classifier, FlowCacheDefinitionBuilder fcdBuilder) {
+        List<ParameterValue> parametersAndValues = classifier.getParameterValue();
+        ParameterValue ipProtoParam = getParamVal(parametersAndValues, IpProtoClassifierDefinition.PROTO_PARAM);
+        if (ipProtoParam != null) {
+            fcdBuilder.getKeysBuilder().addValue(FlowCacheCons.Key.IP_PROTOCOL.get());
+            fcdBuilder.getFilterBuilder()
+                .addValue(FlowCacheCons.Key.IP_PROTOCOL.get() + FlowCacheCons.EQ + ipProtoParam.getIntValue());
+            return true;
+        } else {
+            LOG.trace("Cannot add ip-proto information to flow cache for Sflow-RT.");
+            return false;
+        }
+    }
+
+    private static boolean addL4InfoToFlowCache(Classifier classifier, FlowCacheDefinitionBuilder fcdBuilder) {
+        List<ParameterValue> parametersAndValues = classifier.getParameterValue();
+        ParameterValue ipProtoParam = getParamVal(parametersAndValues, IpProtoClassifierDefinition.PROTO_PARAM);
+        ParameterValue dstPortParam = getParamVal(parametersAndValues, L4ClassifierDefinition.DST_PORT_PARAM);
+        ParameterValue srcPortParam = getParamVal(parametersAndValues, L4ClassifierDefinition.SRC_PORT_PARAM);
+        if (ipProtoParam == null || (dstPortParam == null && srcPortParam == null)) {
+            LOG.trace(
+                    "Cannot add L4 information to flow cache for Sflow-RT."
+                            + "\nipProtoParam:{} dstPortParam:{} srcPortParam:{}",
+                    ipProtoParam, dstPortParam, srcPortParam);
+            return false;
+        }
+        if (dstPortParam != null) {
+            if (!addTcpUdpPortKeys(ipProtoParam.getIntValue(), dstPortParam.getIntValue(), true, fcdBuilder)) {
+                return false;
+            }
+        }
+        if (srcPortParam != null) {
+            if (!addTcpUdpPortKeys(ipProtoParam.getIntValue(), srcPortParam.getIntValue(), false, fcdBuilder)) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    private static ParameterValue getParamVal(List<ParameterValue> parametersAndValues, String paramName) {
+        for (ParameterValue paramVal : parametersAndValues) {
+            if (paramName.equals(paramVal.getName().getValue())) {
+                return paramVal;
+            }
+        }
+        return null;
+    }
+
+    private static boolean addTcpUdpPortKeys(Long ipProto, Long port, boolean isDstPort,
+            FlowCacheDefinitionBuilder fcdBuilder) {
+        if (isDstPort) {
+            if (ipProto == IpProtoClassifierDefinition.TCP_VALUE) {
+                fcdBuilder.getKeysBuilder().addValue(FlowCacheCons.Key.TCP_DST_PORT.get());
+                fcdBuilder.getFilterBuilder().addValue(FlowCacheCons.Key.TCP_DST_PORT.get() + FlowCacheCons.EQ + port);
+            } else if (ipProto == IpProtoClassifierDefinition.UDP_VALUE) {
+                fcdBuilder.getKeysBuilder().addValue(FlowCacheCons.Key.UDP_DST_PORT.get());
+                fcdBuilder.getFilterBuilder().addValue(FlowCacheCons.Key.UDP_DST_PORT.get() + FlowCacheCons.EQ + port);
+            } else {
+                LOG.info("Statistics cannot be collected for ip-proto {} and port {}", ipProto, port);
+                return false;
+            }
+        } else {
+            if (ipProto == IpProtoClassifierDefinition.TCP_VALUE) {
+                fcdBuilder.getKeysBuilder().addValue(FlowCacheCons.Key.TCP_SRC_PORT.get());
+                fcdBuilder.getFilterBuilder().addValue(FlowCacheCons.Key.TCP_SRC_PORT.get() + FlowCacheCons.EQ + port);
+            } else if (ipProto == IpProtoClassifierDefinition.UDP_VALUE) {
+                fcdBuilder.getKeysBuilder().addValue(FlowCacheCons.Key.UDP_SRC_PORT.get());
+                fcdBuilder.getFilterBuilder().addValue(FlowCacheCons.Key.UDP_SRC_PORT.get() + FlowCacheCons.EQ + port);
+            } else {
+                LOG.info("Statistics cannot be collected for ip-proto {} and port {}", ipProto, port);
+                return false;
+            }
+        }
+        return true;
+    }
+}
diff --git a/renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/statistics/flowcache/FlowCacheFilter.java b/renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/statistics/flowcache/FlowCacheFilter.java
new file mode 100644 (file)
index 0000000..ffaa766
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.groupbasedpolicy.renderer.ofoverlay.statistics.flowcache;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import com.google.common.base.Joiner;
+import com.google.common.base.Preconditions;
+
+public final class FlowCacheFilter {
+
+    private static final String AND = "&";
+    private static final String LB = "(";
+    private static final String RB = ")";
+
+    private String value;
+
+    private FlowCacheFilter(FlowCacheFilterBuilder builder) {
+        this.value = Joiner.on(AND).join(builder.getValues());
+    }
+
+    public String getValue() {
+        return value;
+    }
+
+    public static FlowCacheFilterBuilder builder(){
+        return new FlowCacheFilterBuilder();
+    }
+
+    public static class FlowCacheFilterBuilder {
+
+        private List<String> values = new ArrayList<>();
+
+        public List<String> getValues() {
+            return values;
+        }
+
+        public FlowCacheFilterBuilder setValues(List<String> values) {
+            this.values = Preconditions.checkNotNull(values);
+            return this;
+        }
+
+        public FlowCacheFilterBuilder addValue(String value) {
+            values.add(LB + Preconditions.checkNotNull(value)  + RB);
+            return this;
+        }
+
+        public FlowCacheFilter build() {
+            return new FlowCacheFilter(this);
+        }
+    }
+}
diff --git a/renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/statistics/flowcache/FlowCacheKeys.java b/renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/statistics/flowcache/FlowCacheKeys.java
new file mode 100644 (file)
index 0000000..3761b25
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.groupbasedpolicy.renderer.ofoverlay.statistics.flowcache;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import com.google.common.base.Joiner;
+import com.google.common.base.Preconditions;
+
+public final class FlowCacheKeys {
+
+    private static final String SEPARATOR = ",";
+
+    private String value;
+
+    private FlowCacheKeys(FlowCacheKeysBuilder builder) {
+        this.value = Joiner.on(SEPARATOR).join(builder.getValues());
+    }
+
+    public String getValue() {
+        return value;
+    }
+
+    public static FlowCacheKeysBuilder builder(){
+        return new FlowCacheKeysBuilder();
+    }
+
+    public static class FlowCacheKeysBuilder {
+
+        private List<String> values = new ArrayList<>();
+
+        public List<String> getValues() {
+            return values;
+        }
+
+        public FlowCacheKeysBuilder setValues(List<String> values) {
+            this.values = Preconditions.checkNotNull(values);
+            return this;
+        }
+
+        public FlowCacheKeysBuilder addValue(String value) {
+            values.add(Preconditions.checkNotNull(value));
+            return this;
+        }
+
+        public FlowCacheKeys build() {
+            return new FlowCacheKeys(this);
+        }
+    }
+}
diff --git a/renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/statistics/util/FlowCacheCons.java b/renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/statistics/util/FlowCacheCons.java
new file mode 100644 (file)
index 0000000..4bf7cce
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.groupbasedpolicy.renderer.ofoverlay.statistics.util;
+
+public class FlowCacheCons {
+
+    public static final String EQ = "=";
+    public static final String OR = "|";
+
+    public static enum Key {
+        TCP_DST_PORT("tcpdestinationport"),
+        TCP_SRC_PORT("tcpsourceport"),
+        UDP_DST_PORT("udpdestinationport"),
+        UDP_SRC_PORT("udpsourceport"),
+        IP_PROTOCOL("ipprotocol"),
+        ETH_PROTOCOL("ethernetprotocol"),
+        IP_SOURCE("ipsource"),
+        IP_DESTINATION("ipdestination");
+
+        private String val;
+
+        private Key(String val) {
+            this.val = val;
+        }
+
+        public String get() {
+            return val;
+        }
+    }
+
+    public static enum Value {
+        BYTES("bytes"),
+        FRAMES("frames");
+
+        private String val;
+
+        private Value(String val) {
+            this.val = val;
+        }
+
+        public String get() {
+            return val;
+        }
+    }
+
+}
diff --git a/renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/statistics/util/IidSflowNameUtil.java b/renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/statistics/util/IidSflowNameUtil.java
new file mode 100644 (file)
index 0000000..57df0bc
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.groupbasedpolicy.renderer.ofoverlay.statistics.util;
+
+import java.util.List;
+
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ClassifierName;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ContractId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.RuleName;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.SubjectName;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.resolved.policy.rev150828.has.classifiers.Classifier;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.resolved.policy.rev150828.has.classifiers.ClassifierKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.resolved.policy.rev150828.has.resolved.rules.ResolvedRule;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.resolved.policy.rev150828.has.resolved.rules.ResolvedRuleKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.resolved.policy.rev150828.resolved.policies.resolved.policy.policy.rule.group.with.endpoint.constraints.PolicyRuleGroup;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.resolved.policy.rev150828.resolved.policies.resolved.policy.policy.rule.group.with.endpoint.constraints.PolicyRuleGroupKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+import com.google.common.base.Joiner;
+import com.google.common.base.Splitter;
+
+public class IidSflowNameUtil {
+
+    public static final String DELIMETER = "_-_";
+    public static final String KEY_DELIMETER = "-_-";
+
+    public static String createFlowCacheName(InstanceIdentifier<Classifier> classifierIid, FlowCacheCons.Value value) {
+        PolicyRuleGroupKey policyRuleGroup = classifierIid.firstKeyOf(PolicyRuleGroup.class);
+        ResolvedRuleKey resolvedRule = classifierIid.firstKeyOf(ResolvedRule.class);
+        ClassifierKey classifier = classifierIid.firstKeyOf(Classifier.class);
+        StringBuilder sb = new StringBuilder();
+        sb.append(createStringFromCompositeKey(policyRuleGroup.getTenantId().getValue(),
+                policyRuleGroup.getContractId().getValue(), policyRuleGroup.getSubjectName().getValue()))
+            .append(DELIMETER)
+            .append(resolvedRule.getName().getValue())
+            .append(DELIMETER)
+            .append(classifier.getName().getValue())
+            .append(DELIMETER)
+            .append(value.get());
+        return sb.toString();
+    }
+
+    private static String createStringFromCompositeKey(String... keys) {
+        return Joiner.on(KEY_DELIMETER).join(keys);
+    }
+
+    public static ContractId resolveContractIdFromFlowCacheName(String flowCacheName) {
+        List<String> keys = Splitter.on(DELIMETER).splitToList(flowCacheName);
+        String policyRuleGroupKey = keys.get(0);
+        String contractId = Splitter.on(KEY_DELIMETER).splitToList(policyRuleGroupKey).get(1);
+        return new ContractId(contractId);
+    }
+
+    public static SubjectName resolveSubjectNameFromFlowCacheName(String flowCacheName) {
+        List<String> keys = Splitter.on(DELIMETER).splitToList(flowCacheName);
+        String policyRuleGroupKey = keys.get(0);
+        String subjectName = Splitter.on(KEY_DELIMETER).splitToList(policyRuleGroupKey).get(2);
+        return new SubjectName(subjectName);
+    }
+
+    public static RuleName resolveRuleNameFromFlowCacheName(String flowCacheName) {
+        List<String> keys = Splitter.on(DELIMETER).splitToList(flowCacheName);
+        String ruleName = keys.get(1);
+        return new RuleName(ruleName);
+    }
+
+    public static ClassifierName resolveClassifierNameFromFlowCacheName(String flowCacheName) {
+        List<String> keys = Splitter.on(DELIMETER).splitToList(flowCacheName);
+        String classifierName = keys.get(2);
+        return new ClassifierName(classifierName);
+    }
+
+    public static String resolveFlowCacheValue(String flowCacheName) {
+        List<String> keys = Splitter.on(DELIMETER).splitToList(flowCacheName);
+        return keys.get(3);
+    }
+}
old mode 100644 (file)
new mode 100755 (executable)
index 2c1835e..c3d95c8
@@ -33,7 +33,7 @@ module ofoverlay-provider-impl {
         config:java-name-prefix OFOverlayProvider;
     }
 
         config:java-name-prefix OFOverlayProvider;
     }
 
-    // Augments the 'configuration' choice node under modules/module.  
+    // Augments the 'configuration' choice node under modules/module.
     augment "/config:modules/config:module/config:configuration" {
         case ofoverlay-provider-impl {
             when "/config:modules/config:module/config:type = 'ofoverlay-provider-impl'";
     augment "/config:modules/config:module/config:configuration" {
         case ofoverlay-provider-impl {
             when "/config:modules/config:module/config:type = 'ofoverlay-provider-impl'";
@@ -83,8 +83,18 @@ module ofoverlay-provider-impl {
                     }
                 }
             }
                     }
                 }
             }
+            // StatisticsManager service
+            container statistics-manager {
+                uses config:service-ref {
+                    refine type {
+                        mandatory true;
+                        config:required-identity gbpcfg:statistics-manager;
+                    }
+                }
+            }
 
             uses ofoverlay:initial-values;
 
             uses ofoverlay:initial-values;
+            //uses ofoverlay:sflow-values;
         }
     }
 }
         }
     }
 }
old mode 100644 (file)
new mode 100755 (executable)
index ae4aeb1..b013b63
@@ -62,6 +62,7 @@ module ofoverlay {
         }
 
         uses initial-values;
         }
 
         uses initial-values;
+        uses sflow-values;
     }
 
     grouping initial-values {
     }
 
     grouping initial-values {
@@ -75,6 +76,25 @@ module ofoverlay {
         }
     }
 
         }
     }
 
+    grouping sflow-values {
+        description
+            "Values for sFlow-RT collector setup";
+        container sflow-client-settings {
+            leaf gbp-ofoverlay-sflow-retrieve-interval {
+                description
+                    "Interval (seconds) for periodical flowcache data retrieve.";
+                type uint32;
+                default 20;
+            }
+            leaf gbp-ofoverlay-sflow-collector-uri {
+                description
+                    "URI of sFlow-RT collector, including schema, IP/domain, port. No trailing slash.";
+                mandatory true;
+                type string;
+            }
+        }
+    }
+
     grouping endpoint-location {
         description
             "The location for this endpoint in the overlay network";
     grouping endpoint-location {
         description
             "The location for this endpoint in the overlay network";
old mode 100644 (file)
new mode 100755 (executable)
index a1fd3b8..ea5b03b
@@ -31,6 +31,7 @@ import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
 import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
 import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
 import org.opendaylight.groupbasedpolicy.api.PolicyValidatorRegistry;
 import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
 import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
 import org.opendaylight.groupbasedpolicy.api.PolicyValidatorRegistry;
+import org.opendaylight.groupbasedpolicy.api.StatisticsManager;
 import org.opendaylight.groupbasedpolicy.endpoint.EndpointRpcRegistry;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.ofoverlay.rev140528.OfOverlayConfig;
 import org.opendaylight.yangtools.concepts.ListenerRegistration;
 import org.opendaylight.groupbasedpolicy.endpoint.EndpointRpcRegistry;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.ofoverlay.rev140528.OfOverlayConfig;
 import org.opendaylight.yangtools.concepts.ListenerRegistration;
@@ -49,6 +50,7 @@ public class OFOverlayRendererTest {
     private EndpointRpcRegistry endpointRpcRegistry;
     private NotificationService notificationService;
     private PolicyValidatorRegistry policyValidatorRegistry;
     private EndpointRpcRegistry endpointRpcRegistry;
     private NotificationService notificationService;
     private PolicyValidatorRegistry policyValidatorRegistry;
+    private StatisticsManager statisticsManager;
     private short tableOffset;
     private CheckedFuture<Optional<OfOverlayConfig>, ReadFailedException> future;
     private ListenerRegistration<DataChangeListener> configReg;
     private short tableOffset;
     private CheckedFuture<Optional<OfOverlayConfig>, ReadFailedException> future;
     private ListenerRegistration<DataChangeListener> configReg;
@@ -62,6 +64,7 @@ public class OFOverlayRendererTest {
         endpointRpcRegistry = mock(EndpointRpcRegistry.class);
         notificationService = mock(NotificationService.class);
         policyValidatorRegistry = mock(PolicyValidatorRegistry.class);
         endpointRpcRegistry = mock(EndpointRpcRegistry.class);
         notificationService = mock(NotificationService.class);
         policyValidatorRegistry = mock(PolicyValidatorRegistry.class);
+        statisticsManager = mock(StatisticsManager.class);
         tableOffset = 5;
         configReg = mock(ListenerRegistration.class);
         when(dataProvider.registerDataChangeListener(any(LogicalDatastoreType.class), any(InstanceIdentifier.class),
         tableOffset = 5;
         configReg = mock(ListenerRegistration.class);
         when(dataProvider.registerDataChangeListener(any(LogicalDatastoreType.class), any(InstanceIdentifier.class),
@@ -79,13 +82,13 @@ public class OFOverlayRendererTest {
         future = Futures.immediateCheckedFuture(Optional.<OfOverlayConfig> absent());
         when(readTransaction.read(any(LogicalDatastoreType.class), any(InstanceIdentifier.class))).thenReturn(future);
         renderer = new OFOverlayRenderer(dataProvider, rpcRegistry, notificationService, endpointRpcRegistry,
         future = Futures.immediateCheckedFuture(Optional.<OfOverlayConfig> absent());
         when(readTransaction.read(any(LogicalDatastoreType.class), any(InstanceIdentifier.class))).thenReturn(future);
         renderer = new OFOverlayRenderer(dataProvider, rpcRegistry, notificationService, endpointRpcRegistry,
-                policyValidatorRegistry, tableOffset);
+                policyValidatorRegistry, statisticsManager, tableOffset);
     }
 
     @Test
     public void constructorTest() throws Exception {
         renderer.close();
     }
 
     @Test
     public void constructorTest() throws Exception {
         renderer.close();
-        verify(configReg, times(10)).close();
+        verify(configReg, times(11)).close();
     }
 
     @Test
     }
 
     @Test
index 724a813cd358ce88566c415652d582f8af04980d..cc267d2c9b8959accc7583364d86a51aed0cede6 100644 (file)
@@ -49,6 +49,7 @@ import org.opendaylight.groupbasedpolicy.dto.EpKey;
 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.EndpointListener;
 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.node.SwitchManager;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.EndpointListener;
 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.node.SwitchManager;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Address;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ConditionName;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.EndpointGroupId;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ConditionName;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.EndpointGroupId;
@@ -131,7 +132,7 @@ public class EndpointManagerTest {
         tenantId = mock(TenantId.class);
         endpointGroupId = mock(EndpointGroupId.class);
         l2BridgeDomainId = mock(L2BridgeDomainId.class);
         tenantId = mock(TenantId.class);
         endpointGroupId = mock(EndpointGroupId.class);
         l2BridgeDomainId = mock(L2BridgeDomainId.class);
-        MacAddress macAddress = mock(MacAddress.class);
+        MacAddress macAddress = new MacAddress("12:34:56:78:9a:bc");
         when(endpoint1.getTenant()).thenReturn(tenantId);
         when(endpoint1.getEndpointGroup()).thenReturn(endpointGroupId);
         when(endpoint1.getL2Context()).thenReturn(l2BridgeDomainId);
         when(endpoint1.getTenant()).thenReturn(tenantId);
         when(endpoint1.getEndpointGroup()).thenReturn(endpointGroupId);
         when(endpoint1.getL2Context()).thenReturn(l2BridgeDomainId);
@@ -383,7 +384,7 @@ public class EndpointManagerTest {
         when(newL3Ep.getKey()).thenReturn(endpointL3Key);
         IpAddress ipAddress = mock(IpAddress.class);
         when(endpointL3Key.getIpAddress()).thenReturn(ipAddress);
         when(newL3Ep.getKey()).thenReturn(endpointL3Key);
         IpAddress ipAddress = mock(IpAddress.class);
         when(endpointL3Key.getIpAddress()).thenReturn(ipAddress);
-
+        when(newL3Ep.getIpAddress()).thenReturn(new IpAddress(new Ipv4Address("1.1.1.1")));
         manager.processL3Endpoint(null, newL3Ep);
         verify(endpointListener,never()).endpointUpdated(any(EpKey.class));
     }
         manager.processL3Endpoint(null, newL3Ep);
         verify(endpointListener,never()).endpointUpdated(any(EpKey.class));
     }
@@ -404,7 +405,7 @@ public class EndpointManagerTest {
         when(newL3Ep.getKey()).thenReturn(endpointL3Key);
         IpAddress ipAddress = mock(IpAddress.class);
         when(endpointL3Key.getIpAddress()).thenReturn(ipAddress);
         when(newL3Ep.getKey()).thenReturn(endpointL3Key);
         IpAddress ipAddress = mock(IpAddress.class);
         when(endpointL3Key.getIpAddress()).thenReturn(ipAddress);
-
+        when(newL3Ep.getIpAddress()).thenReturn(new IpAddress(new Ipv4Address("1.1.1.1")));
         manager.processL3Endpoint(null, newL3Ep);
         verify(endpointListener,never()).endpointUpdated(any(EpKey.class));
     }
         manager.processL3Endpoint(null, newL3Ep);
         verify(endpointListener,never()).endpointUpdated(any(EpKey.class));
     }
@@ -423,7 +424,7 @@ public class EndpointManagerTest {
 
         when(newL3Ep.getL2Context()).thenReturn(mock(L2BridgeDomainId.class));
         when(newL3Ep.getMacAddress()).thenReturn(mock(MacAddress.class));
 
         when(newL3Ep.getL2Context()).thenReturn(mock(L2BridgeDomainId.class));
         when(newL3Ep.getMacAddress()).thenReturn(mock(MacAddress.class));
-
+        when(newL3Ep.getIpAddress()).thenReturn(new IpAddress(new Ipv4Address("1.1.1.1")));
         manager.processL3Endpoint(null, newL3Ep);
         verify(endpointListener).endpointUpdated(any(EpKey.class));
     }
         manager.processL3Endpoint(null, newL3Ep);
         verify(endpointListener).endpointUpdated(any(EpKey.class));
     }
@@ -434,13 +435,14 @@ public class EndpointManagerTest {
         when(newL3Ep.getEndpointGroup()).thenReturn(mock(EndpointGroupId.class));
         when(newL3Ep.getL3Context()).thenReturn(mock(L3ContextId.class));
         when(newL3Ep.getIpAddress()).thenReturn(null);
         when(newL3Ep.getEndpointGroup()).thenReturn(mock(EndpointGroupId.class));
         when(newL3Ep.getL3Context()).thenReturn(mock(L3ContextId.class));
         when(newL3Ep.getIpAddress()).thenReturn(null);
-
+        when(newL3Ep.getIpAddress()).thenReturn(new IpAddress(new Ipv4Address("1.1.1.1")));
         manager.processL3Endpoint(null, newL3Ep);
         verify(endpointListener,never()).endpointUpdated(any(EpKey.class));
     }
 
     @Test
     public void updateEndpointL3TestDelete() throws Exception {
         manager.processL3Endpoint(null, newL3Ep);
         verify(endpointListener,never()).endpointUpdated(any(EpKey.class));
     }
 
     @Test
     public void updateEndpointL3TestDelete() throws Exception {
+        when(oldL3Ep.getIpAddress()).thenReturn(new IpAddress(new Ipv4Address("1.1.1.1")));
         manager.processL3Endpoint(oldL3Ep, null);
         verify(endpointListener).endpointUpdated(any(EpKey.class));
     }
         manager.processL3Endpoint(oldL3Ep, null);
         verify(endpointListener).endpointUpdated(any(EpKey.class));
     }