Merge "Fixed add/push flow methods for path redirect."
authorSuchi Raman <suchi.raman@plexxi.com>
Thu, 10 Oct 2013 21:59:32 +0000 (21:59 +0000)
committerGerrit Code Review <gerrit@opendaylight.org>
Thu, 10 Oct 2013 21:59:32 +0000 (21:59 +0000)
affinity/api/src/main/java/org/opendaylight/affinity/affinity/IAffinityManager.java
affinity/implementation/pom.xml
affinity/implementation/src/main/java/org/opendaylight/affinity/affinity/internal/Activator.java
affinity/implementation/src/main/java/org/opendaylight/affinity/affinity/internal/AffinityManagerImpl.java
l2agent/src/main/java/org/opendaylight/l2agent/L2Agent.java
scripts/affinity.py
scripts/stats.py

index 9ae2718804828bd6952f10830431689fa13c1191..0a276ad40289a036340bb7b7c9bbfc8eba35e514 100644 (file)
@@ -54,5 +54,5 @@ public interface IAffinityManager {
     public List<Entry<AffinityIdentifier, AffinityIdentifier>> getAllFlowsByAffinityIdentifier(AffinityLink al);
 
     public Status addFlowRulesForRedirect(AffinityLink al) throws Exception;
-    public Status pushFlowRule(Flow flow, byte [] mac);
+    public Status pushFlowRule(InetAddress from, InetAddress to, byte [] mac);
 }
index 84df90b5a512513a2e03d7a857b52874f6bc432a..28fc01fa01254e8aa78f5945a7fae7a03d1dd471 100644 (file)
@@ -45,6 +45,7 @@
               org.opendaylight.controller.sal.packet,
               org.opendaylight.controller.sal.inventory,
               org.opendaylight.controller.sal.flowprogrammer, 
+              org.opendaylight.controller.forwardingrulesmanager, 
               org.opendaylight.controller.sal.match,
               org.opendaylight.controller.sal.action,
               org.opendaylight.controller.switchmanager,
index 1eff38f2046e2eda8a501e2a3825d185472f7614..cdff5a7cc019a02bc5a2bc02cae26f5098f9aef6 100644 (file)
@@ -26,6 +26,7 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.opendaylight.affinity.l2agent.IfL2Agent;
 import org.opendaylight.controller.sal.flowprogrammer.IFlowProgrammerService;
+//import org.opendaylight.controller.forwardingrulesmanager.IForwardingRulesManager;
 
 /**
  * AffinityManager Bundle Activator
@@ -101,8 +102,15 @@ public class Activator extends ComponentActivatorAbstractBase {
                   .setService(IfL2Agent.class)
                   .setCallbacks("setL2Agent", "unsetL2Agent")
                   .setRequired(true));
-            c.add(createContainerServiceDependency(containerName).setService(IFlowProgrammerService.class)
-                    .setCallbacks("setFlowProgrammerService", "unsetFlowProgrammerService").setRequired(true));
+            /*            c.add(createContainerServiceDependency(containerName).setService(
+                    IForwardingRulesManager.class).setCallbacks(
+                    "setForwardingRulesManager", "unsetForwardingRulesManager")
+                    .setRequired(true));
+            */
+            c.add(createContainerServiceDependency(containerName)
+                  .setService(IFlowProgrammerService.class)
+                  .setCallbacks("setFlowProgrammerService", "unsetFlowProgrammerService")
+                  .setRequired(true));
             c.add(createContainerServiceDependency(containerName).setService(
                     IClusterContainerServices.class).setCallbacks(
                     "setClusterContainerService",
index 713e2042121a9991208c1f826c43b11848157ad5..445b9d5f89688b5347d569dafcb94474a220e2b1 100644 (file)
@@ -50,7 +50,12 @@ import org.opendaylight.controller.clustering.services.ICacheUpdateAware;
 import org.opendaylight.controller.clustering.services.IClusterContainerServices;
 import org.opendaylight.controller.clustering.services.IClusterServices;
 import org.opendaylight.controller.configuration.IConfigurationContainerAware;
-import org.opendaylight.controller.forwardingrulesmanager.FlowEntry;
+//import org.opendaylight.controller.forwardingrulesmanager.FlowEntry;
+//import org.opendaylight.controller.forwardingrulesmanager.IForwardingRulesManager;
+import org.opendaylight.controller.sal.flowprogrammer.IFlowProgrammerService;
+import org.opendaylight.controller.sal.flowprogrammer.Flow;
+import org.opendaylight.controller.sal.utils.IPProtocols;
+
 import org.opendaylight.controller.sal.core.IContainer;
 import org.opendaylight.controller.sal.core.Node;
 import org.opendaylight.controller.sal.core.Host;
@@ -58,13 +63,14 @@ import org.opendaylight.controller.sal.core.NodeConnector;
 import org.opendaylight.controller.sal.core.NodeTable;
 import org.opendaylight.controller.sal.core.Property;
 import org.opendaylight.controller.sal.core.UpdateType;
-import org.opendaylight.controller.sal.flowprogrammer.IFlowProgrammerService;
+
 import org.opendaylight.controller.sal.flowprogrammer.Flow;
 import org.opendaylight.controller.sal.match.Match;
 import org.opendaylight.controller.sal.match.MatchType;
 import org.opendaylight.controller.sal.match.MatchField;
 import org.opendaylight.controller.sal.action.Action;
 import org.opendaylight.controller.sal.action.Output;
+import org.opendaylight.controller.sal.utils.EtherTypes;
 
 import org.opendaylight.controller.sal.reader.FlowOnNode;
 import org.opendaylight.controller.sal.reader.IReadService;
@@ -105,7 +111,9 @@ public class AffinityManagerImpl implements IAffinityManager, IConfigurationCont
     private static final String SAVE = "Save";
     private String affinityLinkFileName = null;
     private String affinityGroupFileName = null;
-    private IFlowProgrammerService fps = null;
+    //    private IForwardingRulesManager ruleManager;
+    private IFlowProgrammerService programmer = null;
+    
     private ISwitchManager switchManager = null;
     private IfL2Agent l2agent = null;
     private IfIptoHost hostTracker = null;
@@ -126,6 +134,8 @@ public class AffinityManagerImpl implements IAffinityManager, IConfigurationCont
     private boolean isDefaultContainer = true;
     private static final int REPLACE_RETRY = 1;
 
+    private static short REDIRECT_IPSWITCH_PRIORITY = 3;
+
     public enum ReasonCode {
         SUCCESS("Success"), FAILURE("Failure"), INVALID_CONF(
                 "Invalid Configuration"), EXIST("Entry Already Exist"), CONFLICT(
@@ -236,14 +246,27 @@ public class AffinityManagerImpl implements IAffinityManager, IConfigurationCont
             this.hostTracker = null;
         }
     }
-    void setFlowProgrammerService(IFlowProgrammerService s)
+    /*    public void setForwardingRulesManager(
+            IForwardingRulesManager forwardingRulesManager) {
+        log.debug("Setting ForwardingRulesManager");
+        this.ruleManager = forwardingRulesManager;
+    }
+
+    public void unsetForwardingRulesManager(
+            IForwardingRulesManager forwardingRulesManager) {
+        if (this.ruleManager == forwardingRulesManager) {
+            this.ruleManager = null;
+        }
+    }
+    */
+    public void setFlowProgrammerService(IFlowProgrammerService s)
     {
-        this.fps = s;
+        this.programmer = s;
     }
 
-    void unsetFlowProgrammerService(IFlowProgrammerService s) {
-        if (this.fps == s) {
-            this.fps = null;
+    public void unsetFlowProgrammerService(IFlowProgrammerService s) {
+        if (this.programmer == s) {
+            this.programmer = null;
         }
     }
     void setL2Agent(IfL2Agent s)
@@ -309,13 +332,33 @@ public class AffinityManagerImpl implements IAffinityManager, IConfigurationCont
         return new Status(StatusCode.SUCCESS);
     }
 
+    /*
+    private Status installRedirectionFlow(Node sw, Flow flow) {
+        FlowEntry fEntry = new FlowEntry("path-redir", "flow", flow, sw);
+        Status success = new Status(StatusCode.SUCCESS);
+        Status error = new Status(StatusCode.NOTFOUND);
+            
+        log.info("Install flow entry {} on node {}", fEntry.toString(), sw.toString());
+        
+        if (!this.ruleManager.checkFlowEntryConflict(fEntry)) {
+            if (this.ruleManager.installFlowEntry(fEntry).isSuccess()) {
+                return success;
+            } else {
+                log.error("Error in installing flow entry to node : {}", sw);
+            }
+        } else {
+            log.error("Conflicting flow entry exists : {}", fEntry.toString());
+        }
+        return error;
+    }
+    */
 
     /** 
      * Fetch all node connectors. Each switch port will receive a flow
      * rule. Do not stop on error. Pass in the waypointMAC address so
      * that the correct output port can be determined.
      */
-    public Status pushFlowRule(Flow flow, byte [] waypointMAC) {
+    public Status pushFlowRule(InetAddress from, InetAddress to, byte [] waypointMAC) {
         /* Get all node connectors. */
         Set<Node> nodes = switchManager.getNodes();
         Status success = new Status(StatusCode.SUCCESS);
@@ -325,18 +368,32 @@ public class AffinityManagerImpl implements IAffinityManager, IConfigurationCont
             log.debug("No nodes in network.");
             return success;
         } 
+
+        /* Send this flow rule to all nodes in the network. */
         for (Node node: nodes) {
+            List<Action> actions = new ArrayList<Action>();
+            Match match = new Match();
+            match.setField(new MatchField(MatchType.NW_SRC, from, null));
+            match.setField(new MatchField(MatchType.NW_DST, to, null));
+            match.setField(MatchType.DL_TYPE, EtherTypes.IPv4.shortValue());  
+        
+            Flow f = new Flow(match, actions);
+            f.setMatch(match);
+            f.setPriority(REDIRECT_IPSWITCH_PRIORITY);
+
             /* Look up the output port leading to the waypoint. */
             NodeConnector dst_connector = l2agent.lookup_output_port(node, waypointMAC);
 
             log.debug("Waypoint direction: node {} and connector {}", node, dst_connector);
             if (dst_connector != null) {
-                flow.addAction(new Output(dst_connector));
-                log.debug("flow push flow = {} to node = {} using fps = {} ", flow, node, fps);
-                Status status = fps.addFlow(node, flow);
+                f.setActions(actions);
+                f.addAction(new Output(dst_connector));
+                log.debug("flow push flow = {} to node = {} ", f, node);
+                /*                Status status = installRedirectionFlow(node, flow);*/
+                Status status = programmer.addFlow(node, f);
                 if (!status.isSuccess()) {
                     log.debug("Error during addFlow: {} on {}. The failure is: {}",
-                              flow, node, status.getDescription());
+                              f, node, status.getDescription());
                 }
             }
         }
@@ -347,33 +404,32 @@ public class AffinityManagerImpl implements IAffinityManager, IConfigurationCont
      * add flow rules for each node connector.
      */
     public Status addFlowRulesForRedirect(AffinityLink al) throws Exception {
-        Match match = new Match();
-        List<Action> actions = new ArrayList<Action>();
 
         InetAddress address1, address2;
         InetAddress mask;
         mask = InetAddress.getByName("255.255.255.255");
 
-        Flow f = new Flow(match, actions);
         String waypoint = al.getWaypoint();
 
         log.debug("addFlowRulesForRedirect link = {} waypoint = {}", al.getName(), al.getWaypoint());
         List<Entry<Host,Host>> hostPairList= getAllFlowsByHost(al);
         for (Entry<Host,Host> hostPair : hostPairList) {
             /* Create a match for each host pair in the affinity link. */
+            Match match = new Match();
+
             log.debug("Processing next hostPair {}", hostPair);
             Host host1 = hostPair.getKey();
             Host host2 = hostPair.getValue();
+            if (host1 == null || host2 == null) {
+                log.debug("Hosts in hostpair {} -> {} not found in hosttracker.", host1, host2);
+                return new Status(StatusCode.NOTFOUND);
+            }
             log.debug("Adding a flow for host pair {} -> {}", host1, host2);
             address1 = host1.getNetworkAddress();
             address2 = host2.getNetworkAddress();
             log.debug("Adding a flow for {} -> {}", address1, address2);
-            match.setField(MatchType.NW_SRC, address1, mask);
-            match.setField(MatchType.NW_DST, address2, mask);
-            
-            /* Send this flow rule to all nodes in the network. */
-            byte [] dstMAC = InetAddressToMAC(waypoint);
-            pushFlowRule(f, dstMAC);
+            byte [] waypointMAC = InetAddressToMAC(waypoint);
+            pushFlowRule(address1, address2, waypointMAC);
         }
        return new Status(StatusCode.SUCCESS);
     }
index 112e90bf1565e339811b085de9dcc5615356b645..0d52c1ce66623c42dee194f94604a14f2685d3e4 100644 (file)
@@ -248,7 +248,7 @@ public class L2Agent implements IListenDataPacket, IfL2Agent {
     public NodeConnector lookup_output_port(Node node, byte [] dstMAC) {
         long dstMAC_val = BitBufferHelper.toNumber(dstMAC);
         NodeConnector nc = this.mac_to_ports.get(node).get(dstMAC_val);
-        logger.debug("lookup_output_port: Node = {}, dst mac = {}, Nodeconnector = {}", node, dstMAC_val, nc);
+        logger.debug("lookup_output_port: Node = {}, dst mac = {}, Nodeconnector = {}", node, dstMAC, nc);
         return nc;
     }
 }
index 0b4f099c82c8439147b571eb2e9d3489e5e02230..b559637ff7b268dda475da75a5d5dbcbb59483fa 100644 (file)
@@ -17,13 +17,25 @@ def rest_method(url, verb):
     print content
     print "return code %d" % (resp.status)
     print "done"
-    
+    return content
+
 
 def list_all_hosts(): 
 
-    print "list all hosts"
+    print "list active hosts"
     put_url = 'http://localhost:8080/controller/nb/v2/hosttracker/default/hosts/active'
+    content = rest_method(put_url, "GET")
+    hostCfg = json.loads(content)
+    for host in hostCfg['hostConfig']:
+        print host
+
+    print "list inactive hosts"
+    put_url = 'http://localhost:8080/controller/nb/v2/hosttracker/default/hosts/inactive'
     rest_method(put_url, "GET")
+    content = rest_method(put_url, "GET")
+    hostCfg = json.loads(content)
+    for host in hostCfg['hostConfig']:
+        print host
     
 
 def waypoint_init():
@@ -42,15 +54,15 @@ def waypoint_init():
     rest_method(put_url, "PUT")
 
     print "add ip to webservers"
-    put_url = 'http://localhost:8080/affinity/nb/v2/affinity/default/group/webservers/add/ip/192.168.1.1'
+    put_url = 'http://localhost:8080/affinity/nb/v2/affinity/default/group/webservers/add/ip/10.0.0.1'
     rest_method(put_url, "PUT")
 
-    print "add ip to webservers"
-    put_url = 'http://localhost:8080/affinity/nb/v2/affinity/default/group/webservers/add/ip/192.168.1.2'
-    rest_method(put_url, "PUT")
+#    print "add ip to webservers"
+#    put_url = 'http://localhost:8080/affinity/nb/v2/affinity/default/group/webservers/add/ip/10.0.0.2'
+#    rest_method(put_url, "PUT")
 
     print "add ip to external"    
-    put_url = 'http://localhost:8080/affinity/nb/v2/affinity/default/group/clients/add/ip/10.10.0.0'
+    put_url = 'http://localhost:8080/affinity/nb/v2/affinity/default/group/clients/add/ip/10.0.0.3'
     rest_method(put_url, "PUT")
 
 
@@ -59,6 +71,7 @@ def get_all_affinity_groups():
     get_url = 'http://localhost:8080/affinity/nb/v2/affinity/default/affinity-groups'
     rest_method(get_url, "GET")
 
+# Tbd
 def get_all_affinity_links(): 
     print "get all affinity groups"
     get_url = 'http://localhost:8080/affinity/nb/v2/affinity/default/affinity-links'
@@ -69,35 +82,30 @@ def get_affinity_group(groupname):
     rest_method(get_url, "GET")
 
 def set_waypoint_address():
-    wp = "192.168.1.10"
+    wp = "10.0.0.2"
     put_url = 'http://localhost:8080/affinity/nb/v2/affinity/default/link/inflows/setwaypoint/' + wp
     rest_method(put_url, "PUT")
 
-def demo_set_waypoint_address():
-    wp = "10.0.0.4"
-    put_url = 'http://localhost:8080/affinity/nb/v2/affinity/default/link/testAL/setwaypoint/' + wp
-    rest_method(put_url, "PUT")
-
 # Add waypoint IP to an affinity link.
 def main():
     global h
-    h = httplib2.Http(".cache")
-    h.add_credentials('admin', 'admin')
-
-#    waypoint_init()
-    demo_set_waypoint_address()
-#    unset_waypoint_address()
 
-#    get_affinity_group('webservers')
-#    get_affinity_group('clients')
+    waypoint_init()
 
-#    get_all_affinity_groups()
+    get_affinity_group('webservers')
+    get_affinity_group('clients')
 
+    get_all_affinity_groups()
     list_all_hosts()
-#    get_all_affinity_links()
 
-if __name__ == "__main__":
-    main()
+    set_waypoint_address()
+
+#if __name__ == "__main__":
+#    main()
+
+h = httplib2.Http(".cache")
+h.add_credentials('admin', 'admin')
+
 
     
 
index b0152fbfa20d4b852bd170e5a5c875d2f4a65c5f..dba4b3dcef5e4892db16f6b2535fcfdfa0fba970 100644 (file)
@@ -1,31 +1,43 @@
 import httplib2
 import json
+import pprint
  
 h = httplib2.Http(".cache")
 h.add_credentials('admin', 'admin')
 
-resp, content = h.request('http://localhost:8080/controller/nb/v2/statistics/default/flowstats', "GET")
-allFlowStats = json.loads(content)
-flowStats = allFlowStats['flowStatistics']
-print flowStats
-
-# These JSON dumps were handy when trying to parse the responses 
-#print json.dumps(flowStats[0]['flowStat'][1], indent = 2)
-#print json.dumps(flowStats[4], indent = 2)
-for fs in flowStats:
-    print "\nSwitch ID : " + fs['node']['@id']
-    print '{0:8} {1:8} {2:5} {3:15}'.format('Count', 'Action', 'Port', 'DestIP')
-    for aFlow in fs['flowStat']:
-        count = aFlow['packetCount']
-actions = aFlow['flow']['actions'] 
-actionType = ''
-actionPort = ''
-#print actions
-if(type(actions) == type(list())):
-    actionType = actions[1]['@type']
-    actionPort = actions[1]['port']['@id']
-else:
-    actionType = actions['@type']
-    actionPort = actions['port']['@id']
-dst = aFlow['flow']['match']['matchField'][0]['value']
-print '{0:8} {1:8} {2:5} {3:15}'.format(count, actionType, actionPort, dst)
+# Flow statistics. 
+def get_flow_stats(): 
+    global h
+    resp, content = h.request('http://localhost:8080/controller/nb/v2/statistics/default/flow', "GET")
+    allFlowStats = json.loads(content)
+
+    # raw dump
+    print content
+
+    # raw dumps
+    json.dumps(allFlowStats, indent=2, default=str)
+    s = pprint.pformat(allFlowStats, indent=4)
+    print s
+
+
+    for fs in allFlowStats["flowStatistics"]: 
+        node = fs["node"]
+        flows = fs["flowStatistic"]
+
+        print "#### Switch = " + node["id"] + ", type = " + node["type"]
+        print "# flows =  %d" % len(flows)
+        for f in flows: 
+            print f["flow"]["match"], "priority = ", f["flow"]["priority"]
+            print "\t Actions:"
+            for a in f["flow"]["actions"]:
+                print "\t \t", a 
+
+
+def get_all_nodes():
+    global h
+    resp, content = h.request('http://localhost:8080/controller/nb/v2/switchmanager/default/nodes', 'GET')
+    nodes = json.loads(content)
+    return nodes
+
+get_flow_stats()
+#get_all_nodes()