From d808dbff4684ac3825672e6ebfd584476726d8d3 Mon Sep 17 00:00:00 2001
From: kwanggithub <kwang@clemson.edu>
Date: Mon, 28 Jan 2013 11:51:52 -0800
Subject: [PATCH] refactor loadbalancer to not use StaticFlowEntries

---
 .../loadbalancer/LoadBalancer.java            | 504 +++++++++++++++++-
 1 file changed, 502 insertions(+), 2 deletions(-)

diff --git a/src/main/java/net/floodlightcontroller/loadbalancer/LoadBalancer.java b/src/main/java/net/floodlightcontroller/loadbalancer/LoadBalancer.java
index 25303373c..a58aa64c4 100644
--- a/src/main/java/net/floodlightcontroller/loadbalancer/LoadBalancer.java
+++ b/src/main/java/net/floodlightcontroller/loadbalancer/LoadBalancer.java
@@ -8,8 +8,11 @@ import java.util.Comparator;
 import java.util.EnumSet;
 import java.util.HashMap;
 import java.util.HashSet;
+import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 
 import org.openflow.protocol.OFFlowMod;
 import org.openflow.protocol.OFMatch;
@@ -19,7 +22,18 @@ import org.openflow.protocol.OFPacketOut;
 import org.openflow.protocol.OFPort;
 import org.openflow.protocol.OFType;
 import org.openflow.protocol.action.OFAction;
+import org.openflow.protocol.action.OFActionDataLayerDestination;
+import org.openflow.protocol.action.OFActionDataLayerSource;
+import org.openflow.protocol.action.OFActionEnqueue;
+import org.openflow.protocol.action.OFActionNetworkLayerDestination;
+import org.openflow.protocol.action.OFActionNetworkLayerSource;
+import org.openflow.protocol.action.OFActionNetworkTypeOfService;
 import org.openflow.protocol.action.OFActionOutput;
+import org.openflow.protocol.action.OFActionStripVirtualLan;
+import org.openflow.protocol.action.OFActionTransportLayerDestination;
+import org.openflow.protocol.action.OFActionTransportLayerSource;
+import org.openflow.protocol.action.OFActionVirtualLanIdentifier;
+import org.openflow.protocol.action.OFActionVirtualLanPriorityCodePoint;
 import org.openflow.util.HexString;
 import org.openflow.util.U16;
 import org.slf4j.Logger;
@@ -47,7 +61,6 @@ import net.floodlightcontroller.restserver.IRestApiService;
 import net.floodlightcontroller.routing.IRoutingService;
 import net.floodlightcontroller.routing.Route;
 import net.floodlightcontroller.staticflowentry.IStaticFlowEntryPusherService;
-import net.floodlightcontroller.staticflowentry.StaticFlowEntries;
 import net.floodlightcontroller.topology.ITopologyService;
 import net.floodlightcontroller.topology.NodePortTuple;
 import net.floodlightcontroller.util.MACAddress;
@@ -540,7 +553,7 @@ public class LoadBalancer implements IFloodlightModule,
                    
                }
                
-               StaticFlowEntries.parseActionString(fm, actionString, log);
+               parseActionString(fm, actionString, log);
 
                fm.setPriority(U16.t(LB_PRIORITY));
 
@@ -808,4 +821,491 @@ public class LoadBalancer implements IFloodlightModule,
         restApi.addRestletRoutable(new LoadBalancerWebRoutable());
     }
 
+    // Utilities borrowed from StaticFlowEntries
+    
+    private static class SubActionStruct {
+        OFAction action;
+        int      len;
+    }
+    
+    /**
+     * Parses OFFlowMod actions from strings.
+     * @param flowMod The OFFlowMod to set the actions for
+     * @param actionstr The string containing all the actions
+     * @param log A logger to log for errors.
+     */
+    public static void parseActionString(OFFlowMod flowMod, String actionstr, Logger log) {
+        List<OFAction> actions = new LinkedList<OFAction>();
+        int actionsLength = 0;
+        if (actionstr != null) {
+            actionstr = actionstr.toLowerCase();
+            for (String subaction : actionstr.split(",")) {
+                String action = subaction.split("[=:]")[0];
+                SubActionStruct subaction_struct = null;
+                
+                if (action.equals("output")) {
+                    subaction_struct = decode_output(subaction, log);
+                }
+                else if (action.equals("enqueue")) {
+                    subaction_struct = decode_enqueue(subaction, log);
+                }
+                else if (action.equals("strip-vlan")) {
+                    subaction_struct = decode_strip_vlan(subaction, log);
+                }
+                else if (action.equals("set-vlan-id")) {
+                    subaction_struct = decode_set_vlan_id(subaction, log);
+                }
+                else if (action.equals("set-vlan-priority")) {
+                    subaction_struct = decode_set_vlan_priority(subaction, log);
+                }
+                else if (action.equals("set-src-mac")) {
+                    subaction_struct = decode_set_src_mac(subaction, log);
+                }
+                else if (action.equals("set-dst-mac")) {
+                    subaction_struct = decode_set_dst_mac(subaction, log);
+                }
+                else if (action.equals("set-tos-bits")) {
+                    subaction_struct = decode_set_tos_bits(subaction, log);
+                }
+                else if (action.equals("set-src-ip")) {
+                    subaction_struct = decode_set_src_ip(subaction, log);
+                }
+                else if (action.equals("set-dst-ip")) {
+                    subaction_struct = decode_set_dst_ip(subaction, log);
+                }
+                else if (action.equals("set-src-port")) {
+                    subaction_struct = decode_set_src_port(subaction, log);
+                }
+                else if (action.equals("set-dst-port")) {
+                    subaction_struct = decode_set_dst_port(subaction, log);
+                }
+                else {
+                    log.error("Unexpected action '{}', '{}'", action, subaction);
+                }
+                
+                if (subaction_struct != null) {
+                    actions.add(subaction_struct.action);
+                    actionsLength += subaction_struct.len;
+                }
+            }
+        }
+        log.debug("action {}", actions);
+        
+        flowMod.setActions(actions);
+        flowMod.setLengthU(OFFlowMod.MINIMUM_LENGTH + actionsLength);
+    } 
+    
+    private static SubActionStruct decode_output(String subaction, Logger log) {
+        SubActionStruct sa = null;
+        Matcher n;
+        
+        n = Pattern.compile("output=(?:((?:0x)?\\d+)|(all)|(controller)|(local)|(ingress-port)|(normal)|(flood))").matcher(subaction);
+        if (n.matches()) {
+            OFActionOutput action = new OFActionOutput();
+            action.setMaxLength((short) Short.MAX_VALUE);
+            short port = OFPort.OFPP_NONE.getValue();
+            if (n.group(1) != null) {
+                try {
+                    port = get_short(n.group(1));
+                }
+                catch (NumberFormatException e) {
+                    log.debug("Invalid port in: '{}' (error ignored)", subaction);
+                    return null;
+                }
+            }
+            else if (n.group(2) != null)
+                port = OFPort.OFPP_ALL.getValue();
+            else if (n.group(3) != null)
+                port = OFPort.OFPP_CONTROLLER.getValue();
+            else if (n.group(4) != null)
+                port = OFPort.OFPP_LOCAL.getValue();
+            else if (n.group(5) != null)
+                port = OFPort.OFPP_IN_PORT.getValue();
+            else if (n.group(6) != null)
+                port = OFPort.OFPP_NORMAL.getValue();
+            else if (n.group(7) != null)
+                port = OFPort.OFPP_FLOOD.getValue();
+            action.setPort(port);
+            log.debug("action {}", action);
+            
+            sa = new SubActionStruct();
+            sa.action = action;
+            sa.len = OFActionOutput.MINIMUM_LENGTH;
+        }
+        else {
+            log.error("Invalid subaction: '{}'", subaction);
+            return null;
+        }
+        
+        return sa;
+    }
+    
+    private static SubActionStruct decode_enqueue(String subaction, Logger log) {
+        SubActionStruct sa = null;
+        Matcher n;
+        
+        n = Pattern.compile("enqueue=(?:((?:0x)?\\d+)\\:((?:0x)?\\d+))").matcher(subaction);
+        if (n.matches()) {
+            short portnum = 0;
+            if (n.group(1) != null) {
+                try {
+                    portnum = get_short(n.group(1));
+                }
+                catch (NumberFormatException e) {
+                    log.debug("Invalid port-num in: '{}' (error ignored)", subaction);
+                    return null;
+                }
+            }
+
+            int queueid = 0;
+            if (n.group(2) != null) {
+                try {
+                    queueid = get_int(n.group(2));
+                }
+                catch (NumberFormatException e) {
+                    log.debug("Invalid queue-id in: '{}' (error ignored)", subaction);
+                    return null;
+               }
+            }
+            
+            OFActionEnqueue action = new OFActionEnqueue();
+            action.setPort(portnum);
+            action.setQueueId(queueid);
+            log.debug("action {}", action);
+            
+            sa = new SubActionStruct();
+            sa.action = action;
+            sa.len = OFActionEnqueue.MINIMUM_LENGTH;
+        }
+        else {
+            log.debug("Invalid action: '{}'", subaction);
+            return null;
+        }
+        
+        return sa;
+    }
+    
+    private static SubActionStruct decode_strip_vlan(String subaction, Logger log) {
+        SubActionStruct sa = null;
+        Matcher n = Pattern.compile("strip-vlan").matcher(subaction);
+        
+        if (n.matches()) {
+            OFActionStripVirtualLan action = new OFActionStripVirtualLan();
+            log.debug("action {}", action);
+            
+            sa = new SubActionStruct();
+            sa.action = action;
+            sa.len = OFActionStripVirtualLan.MINIMUM_LENGTH;
+        }
+        else {
+            log.debug("Invalid action: '{}'", subaction);
+            return null;
+        }
+
+        return sa;
+    }
+    
+    private static SubActionStruct decode_set_vlan_id(String subaction, Logger log) {
+        SubActionStruct sa = null;
+        Matcher n = Pattern.compile("set-vlan-id=((?:0x)?\\d+)").matcher(subaction);
+        
+        if (n.matches()) {            
+            if (n.group(1) != null) {
+                try {
+                    short vlanid = get_short(n.group(1));
+                    OFActionVirtualLanIdentifier action = new OFActionVirtualLanIdentifier();
+                    action.setVirtualLanIdentifier(vlanid);
+                    log.debug("  action {}", action);
+
+                    sa = new SubActionStruct();
+                    sa.action = action;
+                    sa.len = OFActionVirtualLanIdentifier.MINIMUM_LENGTH;
+                }
+                catch (NumberFormatException e) {
+                    log.debug("Invalid VLAN in: {} (error ignored)", subaction);
+                    return null;
+                }
+            }          
+        }
+        else {
+            log.debug("Invalid action: '{}'", subaction);
+            return null;
+        }
+
+        return sa;
+    }
+    
+    private static SubActionStruct decode_set_vlan_priority(String subaction, Logger log) {
+        SubActionStruct sa = null;
+        Matcher n = Pattern.compile("set-vlan-priority=((?:0x)?\\d+)").matcher(subaction); 
+        
+        if (n.matches()) {            
+            if (n.group(1) != null) {
+                try {
+                    byte prior = get_byte(n.group(1));
+                    OFActionVirtualLanPriorityCodePoint action = new OFActionVirtualLanPriorityCodePoint();
+                    action.setVirtualLanPriorityCodePoint(prior);
+                    log.debug("  action {}", action);
+                    
+                    sa = new SubActionStruct();
+                    sa.action = action;
+                    sa.len = OFActionVirtualLanPriorityCodePoint.MINIMUM_LENGTH;
+                }
+                catch (NumberFormatException e) {
+                    log.debug("Invalid VLAN priority in: {} (error ignored)", subaction);
+                    return null;
+                }
+            }
+        }
+        else {
+            log.debug("Invalid action: '{}'", subaction);
+            return null;
+        }
+
+        return sa;
+    }
+    
+    private static SubActionStruct decode_set_src_mac(String subaction, Logger log) {
+        SubActionStruct sa = null;
+        Matcher n = Pattern.compile("set-src-mac=(?:(\\p{XDigit}+)\\:(\\p{XDigit}+)\\:(\\p{XDigit}+)\\:(\\p{XDigit}+)\\:(\\p{XDigit}+)\\:(\\p{XDigit}+))").matcher(subaction); 
+
+        if (n.matches()) {
+            byte[] macaddr = get_mac_addr(n, subaction, log);
+            if (macaddr != null) {
+                OFActionDataLayerSource action = new OFActionDataLayerSource();
+                action.setDataLayerAddress(macaddr);
+                log.debug("action {}", action);
+
+                sa = new SubActionStruct();
+                sa.action = action;
+                sa.len = OFActionDataLayerSource.MINIMUM_LENGTH;
+            }            
+        }
+        else {
+            log.debug("Invalid action: '{}'", subaction);
+            return null;
+        }
+
+        return sa;
+    }
+
+    private static SubActionStruct decode_set_dst_mac(String subaction, Logger log) {
+        SubActionStruct sa = null;
+        Matcher n = Pattern.compile("set-dst-mac=(?:(\\p{XDigit}+)\\:(\\p{XDigit}+)\\:(\\p{XDigit}+)\\:(\\p{XDigit}+)\\:(\\p{XDigit}+)\\:(\\p{XDigit}+))").matcher(subaction);
+        
+        if (n.matches()) {
+            byte[] macaddr = get_mac_addr(n, subaction, log);            
+            if (macaddr != null) {
+                OFActionDataLayerDestination action = new OFActionDataLayerDestination();
+                action.setDataLayerAddress(macaddr);
+                log.debug("  action {}", action);
+                
+                sa = new SubActionStruct();
+                sa.action = action;
+                sa.len = OFActionDataLayerDestination.MINIMUM_LENGTH;
+            }
+        }
+        else {
+            log.debug("Invalid action: '{}'", subaction);
+            return null;
+        }
+
+        return sa;
+    }
+    
+    private static SubActionStruct decode_set_tos_bits(String subaction, Logger log) {
+        SubActionStruct sa = null;
+        Matcher n = Pattern.compile("set-tos-bits=((?:0x)?\\d+)").matcher(subaction); 
+
+        if (n.matches()) {
+            if (n.group(1) != null) {
+                try {
+                    byte tosbits = get_byte(n.group(1));
+                    OFActionNetworkTypeOfService action = new OFActionNetworkTypeOfService();
+                    action.setNetworkTypeOfService(tosbits);
+                    log.debug("  action {}", action);
+                    
+                    sa = new SubActionStruct();
+                    sa.action = action;
+                    sa.len = OFActionNetworkTypeOfService.MINIMUM_LENGTH;
+                }
+                catch (NumberFormatException e) {
+                    log.debug("Invalid dst-port in: {} (error ignored)", subaction);
+                    return null;
+                }
+            }
+        }
+        else {
+            log.debug("Invalid action: '{}'", subaction);
+            return null;
+        }
+
+        return sa;
+    }
+    
+    private static SubActionStruct decode_set_src_ip(String subaction, Logger log) {
+        SubActionStruct sa = null;
+        Matcher n = Pattern.compile("set-src-ip=(?:(\\d+)\\.(\\d+)\\.(\\d+)\\.(\\d+))").matcher(subaction);
+
+        if (n.matches()) {
+            int ipaddr = get_ip_addr(n, subaction, log);
+            OFActionNetworkLayerSource action = new OFActionNetworkLayerSource();
+            action.setNetworkAddress(ipaddr);
+            log.debug("  action {}", action);
+
+            sa = new SubActionStruct();
+            sa.action = action;
+            sa.len = OFActionNetworkLayerSource.MINIMUM_LENGTH;
+        }
+        else {
+            log.debug("Invalid action: '{}'", subaction);
+            return null;
+        }
+
+        return sa;
+    }
+
+    private static SubActionStruct decode_set_dst_ip(String subaction, Logger log) {
+        SubActionStruct sa = null;
+        Matcher n = Pattern.compile("set-dst-ip=(?:(\\d+)\\.(\\d+)\\.(\\d+)\\.(\\d+))").matcher(subaction);
+
+        if (n.matches()) {
+            int ipaddr = get_ip_addr(n, subaction, log);
+            OFActionNetworkLayerDestination action = new OFActionNetworkLayerDestination();
+            action.setNetworkAddress(ipaddr);
+            log.debug("action {}", action);
+ 
+            sa = new SubActionStruct();
+            sa.action = action;
+            sa.len = OFActionNetworkLayerDestination.MINIMUM_LENGTH;
+        }
+        else {
+            log.debug("Invalid action: '{}'", subaction);
+            return null;
+        }
+
+        return sa;
+    }
+
+    private static SubActionStruct decode_set_src_port(String subaction, Logger log) {
+        SubActionStruct sa = null;
+        Matcher n = Pattern.compile("set-src-port=((?:0x)?\\d+)").matcher(subaction); 
+
+        if (n.matches()) {
+            if (n.group(1) != null) {
+                try {
+                    short portnum = get_short(n.group(1));
+                    OFActionTransportLayerSource action = new OFActionTransportLayerSource();
+                    action.setTransportPort(portnum);
+                    log.debug("action {}", action);
+                    
+                    sa = new SubActionStruct();
+                    sa.action = action;
+                    sa.len = OFActionTransportLayerSource.MINIMUM_LENGTH;;
+                }
+                catch (NumberFormatException e) {
+                    log.debug("Invalid src-port in: {} (error ignored)", subaction);
+                    return null;
+                }
+            }
+        }
+        else {
+            log.debug("Invalid action: '{}'", subaction);
+            return null;
+        }
+
+        return sa;
+    }
+
+    private static SubActionStruct decode_set_dst_port(String subaction, Logger log) {
+        SubActionStruct sa = null;
+        Matcher n = Pattern.compile("set-dst-port=((?:0x)?\\d+)").matcher(subaction);
+
+        if (n.matches()) {
+            if (n.group(1) != null) {
+                try {
+                    short portnum = get_short(n.group(1));
+                    OFActionTransportLayerDestination action = new OFActionTransportLayerDestination();
+                    action.setTransportPort(portnum);
+                    log.debug("action {}", action);
+                    
+                    sa = new SubActionStruct();
+                    sa.action = action;
+                    sa.len = OFActionTransportLayerDestination.MINIMUM_LENGTH;;
+                }
+                catch (NumberFormatException e) {
+                    log.debug("Invalid dst-port in: {} (error ignored)", subaction);
+                    return null;
+                }
+            }
+        }
+        else {
+            log.debug("Invalid action: '{}'", subaction);
+            return null;
+        }
+
+        return sa;
+    }
+    
+    private static byte[] get_mac_addr(Matcher n, String subaction, Logger log) {
+        byte[] macaddr = new byte[6];
+        
+        for (int i=0; i<6; i++) {
+            if (n.group(i+1) != null) {
+                try {
+                    macaddr[i] = get_byte("0x" + n.group(i+1));
+                }
+                catch (NumberFormatException e) {
+                    log.debug("Invalid src-mac in: '{}' (error ignored)", subaction);
+                    return null;
+                }
+            }
+            else { 
+                log.debug("Invalid src-mac in: '{}' (null, error ignored)", subaction);
+                return null;
+            }
+        }
+        
+        return macaddr;
+    }
+    
+    private static int get_ip_addr(Matcher n, String subaction, Logger log) {
+        int ipaddr = 0;
+
+        for (int i=0; i<4; i++) {
+            if (n.group(i+1) != null) {
+                try {
+                    ipaddr = ipaddr<<8;
+                    ipaddr = ipaddr | get_int(n.group(i+1));
+                }
+                catch (NumberFormatException e) {
+                    log.debug("Invalid src-ip in: '{}' (error ignored)", subaction);
+                    return 0;
+                }
+            }
+            else {
+                log.debug("Invalid src-ip in: '{}' (null, error ignored)", subaction);
+                return 0;
+            }
+        }
+        
+        return ipaddr;
+    }
+    
+    // Parse int as decimal, hex (start with 0x or #) or octal (starts with 0)
+    private static int get_int(String str) {
+        return (int)Integer.decode(str);
+    }
+   
+    // Parse short as decimal, hex (start with 0x or #) or octal (starts with 0)
+    private static short get_short(String str) {
+        return (short)(int)Integer.decode(str);
+    }
+   
+    // Parse byte as decimal, hex (start with 0x or #) or octal (starts with 0)
+    private static byte get_byte(String str) {
+        return Integer.decode(str).byteValue();
+    }
+
+    
 }
-- 
GitLab