diff --git a/src/main/java/net/floodlightcontroller/loadbalancer/ILoadBalancerService.java b/src/main/java/net/floodlightcontroller/loadbalancer/ILoadBalancerService.java
index a335bf4daf1459b7de2764c475ad045121fd761f..0ef66f58f5bf2712bc8daad234df84bb9f2f1186 100644
--- a/src/main/java/net/floodlightcontroller/loadbalancer/ILoadBalancerService.java
+++ b/src/main/java/net/floodlightcontroller/loadbalancer/ILoadBalancerService.java
@@ -154,5 +154,21 @@ public interface ILoadBalancerService extends IFloodlightService {
      * @return int: removal status 
      */
     public int removeMonitor(String monitorId);
+    
+    /**
+     * Set member weight for WRR algorithm.
+     * @param String memberId: the Id of the member
+     * @param String weight: the weight to use in the WRR
+     * @return int: removal status
+     */
+	public int setMemberWeight(String memberId, String weight);
 
+	 /**
+     * Set member to prioritize for WRR algorithm.
+     * @param String memberId: the Id of the member
+     * @param String poolId: the id of the pool
+     * @return int: operation status
+     */
+	public int setPriorityToMember(String poolId, String memberId);
+    
 }
diff --git a/src/main/java/net/floodlightcontroller/loadbalancer/LBMember.java b/src/main/java/net/floodlightcontroller/loadbalancer/LBMember.java
index 40569b478bd171f212d969b6e61cf9d1da3c5c12..0d2aff0039cf1ab2b9ec16679acb5e68f45ef7af 100644
--- a/src/main/java/net/floodlightcontroller/loadbalancer/LBMember.java
+++ b/src/main/java/net/floodlightcontroller/loadbalancer/LBMember.java
@@ -38,6 +38,7 @@ public class LBMember {
 
     protected String poolId;
     protected String vipId;
+    protected short weight;
     
     public LBMember() {
         id = String.valueOf((int) (Math.random()*10000));
@@ -50,5 +51,6 @@ public class LBMember {
         status = 0;
         poolId = null;
         vipId = null;
+        weight = 1;
     }
 }
diff --git a/src/main/java/net/floodlightcontroller/loadbalancer/LBMemberSerializer.java b/src/main/java/net/floodlightcontroller/loadbalancer/LBMemberSerializer.java
index f77e8d30c38e1707241f2e54ee75558fbe19ba24..36a326e6420a9a49f8046b5016d134ad60d4f8cb 100644
--- a/src/main/java/net/floodlightcontroller/loadbalancer/LBMemberSerializer.java
+++ b/src/main/java/net/floodlightcontroller/loadbalancer/LBMemberSerializer.java
@@ -36,6 +36,7 @@ public class LBMemberSerializer extends JsonSerializer<LBMember>{
         jGen.writeStringField("port", Short.toString(member.port));
         jGen.writeStringField("poolId", member.poolId);
         jGen.writeStringField("vipId", member.vipId);
+        jGen.writeStringField("weight", Short.toString(member.weight));
 
         jGen.writeEndObject();
     }
diff --git a/src/main/java/net/floodlightcontroller/loadbalancer/LBPool.java b/src/main/java/net/floodlightcontroller/loadbalancer/LBPool.java
index 1f842aea7f12c7492eb5298e6665829817c7ce6f..2259a64d50c3e1c56ebaa1aafc66f293da0464bc 100644
--- a/src/main/java/net/floodlightcontroller/loadbalancer/LBPool.java
+++ b/src/main/java/net/floodlightcontroller/loadbalancer/LBPool.java
@@ -16,7 +16,16 @@
 
 package net.floodlightcontroller.loadbalancer;
 
+
 import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Random;
+
+import org.projectfloodlight.openflow.types.U64;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import com.fasterxml.jackson.databind.annotation.JsonSerialize;
 
@@ -32,43 +41,86 @@ import net.floodlightcontroller.loadbalancer.LoadBalancer.IPClient;
 
 @JsonSerialize(using=LBPoolSerializer.class)
 public class LBPool {
-    protected String id;
-    protected String name;
-    protected String tenantId;
-    protected String netId;
-    protected short lbMethod;
-    protected byte protocol;
-    protected ArrayList<String> members;
-    protected ArrayList<String> monitors;
-    protected short adminState;
-    protected short status;
-    
-    protected String vipId;
-    
-    protected int previousMemberIndex;
-    
-    public LBPool() {
-        id = String.valueOf((int) (Math.random()*10000));
-        name = null;
-        tenantId = null;
-        netId = null;
-        lbMethod = 0;
-        protocol = 0;
-        members = new ArrayList<String>();
-        monitors = new ArrayList<String>();
-        adminState = 0;
-        status = 0;
-        previousMemberIndex = -1;
-    }
-    
-    public String pickMember(IPClient client) {
-        // simple round robin for now; add different lbmethod later
-        if (members.size() > 0) {
-            previousMemberIndex = (previousMemberIndex + 1) % members.size();
-            return members.get(previousMemberIndex);
-        } else {
-            return null;
-        }
-    }
+	protected static Logger log = LoggerFactory.getLogger(LBPool.class);
+	protected String id;
+	protected String name;
+	protected String tenantId;
+	protected String netId;
+	protected short lbMethod;
+	protected byte protocol;
+	protected ArrayList<String> members;
+	protected ArrayList<String> monitors;
+	protected short adminState;
+	protected short status;
+	protected final static short ROUND_ROBIN = 1;
+	protected final static short STATISTICS = 2;
+	protected final static short WEIGHTED_RR = 3;
+
+	protected String vipId;
+
+	protected int previousMemberIndex;
+
+	public LBPool() {
+		id = String.valueOf((int) (Math.random()*10000));
+		name = null;
+		tenantId = null;
+		netId = null;
+		lbMethod = 0;
+		protocol = 0;
+		members = new ArrayList<String>();
+		monitors = new ArrayList<String>();
+		adminState = 0;
+		status = 0;
+		previousMemberIndex = -1;
+	}
+
+	public String pickMember(IPClient client, HashMap<String,U64> membersBandwidth,HashMap<String,Short> membersWeight) {
+
+		// Get the members that belong to this pool and the statistics for them
+		if(members.size() > 0){
+			if (lbMethod == STATISTICS && !membersBandwidth.isEmpty() && membersBandwidth.values() !=null) {	
+				ArrayList<String> poolMembersId = new ArrayList<String>();
+				for(String memberId: membersBandwidth.keySet()){
+					for(int i=0;i<members.size();i++){
+						if(members.get(i).equals(memberId)){
+							poolMembersId.add(memberId);
+						}
+					}
+				}
+				// return the member which has the minimum bandwidth usage, out of this pool members
+				if(!poolMembersId.isEmpty()){
+					ArrayList<U64> bandwidthValues = new ArrayList<U64>();
+
+					for(int j=0;j<poolMembersId.size();j++){
+						bandwidthValues.add(membersBandwidth.get(poolMembersId.get(j)));
+					}
+					log.debug("Member picked using LB statistics: {}", poolMembersId.get(bandwidthValues.indexOf(Collections.min(bandwidthValues))));
+					return poolMembersId.get(bandwidthValues.indexOf(Collections.min(bandwidthValues)));
+				}
+				return null;
+			} else if(lbMethod == WEIGHTED_RR && !membersWeight.isEmpty()){
+				Random randomNumb = new Random();
+				short totalWeight = 0; 
 
+				for(Short weight: membersWeight.values()){
+					totalWeight += weight;
+				}
+				int rand = randomNumb.nextInt(totalWeight);
+				short val = 0;
+				for(String memberId: membersWeight.keySet()){
+					val += membersWeight.get(memberId);
+					if(val > rand){
+						log.debug("Member picked using WRR: {}",memberId);
+						return memberId;
+					}
+				}
+				return null;
+			}else {
+				// simple round robin
+				previousMemberIndex = (previousMemberIndex + 1) % members.size();
+				return members.get(previousMemberIndex);
+			}
+		}
+		return null;
+	}
 }
diff --git a/src/main/java/net/floodlightcontroller/loadbalancer/LoadBalancer.java b/src/main/java/net/floodlightcontroller/loadbalancer/LoadBalancer.java
index de0dbc10c24278460216dbf458988ba284e2a676..fef0276326de333fd77934a141c87eb046075f70 100644
--- a/src/main/java/net/floodlightcontroller/loadbalancer/LoadBalancer.java
+++ b/src/main/java/net/floodlightcontroller/loadbalancer/LoadBalancer.java
@@ -16,6 +16,7 @@
 
 package net.floodlightcontroller.loadbalancer;
 
+
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
@@ -74,6 +75,8 @@ import net.floodlightcontroller.restserver.IRestApiService;
 import net.floodlightcontroller.routing.IRoutingService;
 import net.floodlightcontroller.routing.Path;
 import net.floodlightcontroller.staticentry.IStaticEntryPusherService;
+import net.floodlightcontroller.statistics.IStatisticsService;
+import net.floodlightcontroller.statistics.SwitchPortBandwidth;
 import net.floodlightcontroller.topology.ITopologyService;
 import net.floodlightcontroller.util.FlowModUtils;
 import net.floodlightcontroller.util.OFMessageUtils;
@@ -93,758 +96,851 @@ import net.floodlightcontroller.util.OFMessageUtils;
  * @edited Ryan Izard, rizard@g.clemson.edu, ryan.izard@bigswitch.com
  */
 public class LoadBalancer implements IFloodlightModule,
-    ILoadBalancerService, IOFMessageListener {
-
-    protected static Logger log = LoggerFactory.getLogger(LoadBalancer.class);
-
-    // Our dependencies
-    protected IFloodlightProviderService floodlightProviderService;
-    protected IRestApiService restApiService;
-    
-    protected IDebugCounterService debugCounterService;
-    private IDebugCounter counterPacketOut;
-    protected IDeviceService deviceManagerService;
-    protected IRoutingService routingEngineService;
-    protected ITopologyService topologyService;
-    protected IStaticEntryPusherService sfpService;
-    protected IOFSwitchService switchService;
-    
-    protected HashMap<String, LBVip> vips;
-    protected HashMap<String, LBPool> pools;
-    protected HashMap<String, LBMember> members;
-    protected HashMap<Integer, String> vipIpToId;
-    protected HashMap<Integer, MacAddress> vipIpToMac;
-    protected HashMap<Integer, String> memberIpToId;
-    protected HashMap<IPClient, LBMember> clientToMember;
-    
-    //Copied from Forwarding with message damper routine for pushing proxy Arp 
-    protected static int OFMESSAGE_DAMPER_CAPACITY = 10000; // ms. 
-    protected static int OFMESSAGE_DAMPER_TIMEOUT = 250; // ms 
-    protected static String LB_ETHER_TYPE = "0x800";
-    protected static int LB_PRIORITY = 32768;
-    
-    // Comparator for sorting by SwitchCluster
-    public Comparator<SwitchPort> clusterIdComparator =
-            new Comparator<SwitchPort>() {
-                @Override
-                public int compare(SwitchPort d1, SwitchPort d2) {
-                    DatapathId d1ClusterId = topologyService.getClusterId(d1.getNodeId());
-                    DatapathId d2ClusterId = topologyService.getClusterId(d2.getNodeId());
-                    return d1ClusterId.compareTo(d2ClusterId);
-                }
-            };
-
-    // data structure for storing connected
-    public class IPClient {
-        IPv4Address ipAddress;
-        IpProtocol nw_proto;
-        TransportPort srcPort; // tcp/udp src port. icmp type (OFMatch convention)
-        TransportPort targetPort; // tcp/udp dst port, icmp code (OFMatch convention)
-        
-        public IPClient() {
-            ipAddress = IPv4Address.NONE;
-            nw_proto = IpProtocol.NONE;
-            srcPort = TransportPort.NONE;
-            targetPort = TransportPort.NONE;
-        }
-    }
-    
-    @Override
-    public String getName() {
-        return "loadbalancer";
-    }
-
-    @Override
-    public boolean isCallbackOrderingPrereq(OFType type, String name) {
-        return (type.equals(OFType.PACKET_IN) && 
-                (name.equals("topology") || 
-                 name.equals("devicemanager") ||
-                 name.equals("virtualizer")));
-    }
-
-    @Override
-    public boolean isCallbackOrderingPostreq(OFType type, String name) {
-        return (type.equals(OFType.PACKET_IN) && name.equals("forwarding"));
-   }
-
-    @Override
-    public net.floodlightcontroller.core.IListener.Command
-            receive(IOFSwitch sw, OFMessage msg, FloodlightContext cntx) {
-        switch (msg.getType()) {
-            case PACKET_IN:
-                return processPacketIn(sw, (OFPacketIn)msg, cntx);
-            default:
-                break;
-        }
-        log.warn("Received unexpected message {}", msg);
-        return Command.CONTINUE;
-    }
-
-    private net.floodlightcontroller.core.IListener.Command processPacketIn(IOFSwitch sw, OFPacketIn pi, FloodlightContext cntx) {
-        
-        Ethernet eth = IFloodlightProviderService.bcStore.get(cntx, IFloodlightProviderService.CONTEXT_PI_PAYLOAD);
-        IPacket pkt = eth.getPayload(); 
- 
-        if (eth.isBroadcast() || eth.isMulticast()) {
-            // handle ARP for VIP
-            if (pkt instanceof ARP) {
-                // retrieve arp to determine target IP address                                                       
-                ARP arpRequest = (ARP) eth.getPayload();
-
-                IPv4Address targetProtocolAddress = arpRequest.getTargetProtocolAddress();
-
-                if (vipIpToId.containsKey(targetProtocolAddress.getInt())) {
-                    String vipId = vipIpToId.get(targetProtocolAddress.getInt());
-                    vipProxyArpReply(sw, pi, cntx, vipId);
-                    return Command.STOP;
-                }
-            }
-        } else {
-            // currently only load balance IPv4 packets - no-op for other traffic 
-            if (pkt instanceof IPv4) {
-                IPv4 ip_pkt = (IPv4) pkt;
-                
-                // If match Vip and port, check pool and choose member
-                int destIpAddress = ip_pkt.getDestinationAddress().getInt();
-                
-                if (vipIpToId.containsKey(destIpAddress)){
-                    IPClient client = new IPClient();
-                    client.ipAddress = ip_pkt.getSourceAddress();
-                    client.nw_proto = ip_pkt.getProtocol();
-                    if (ip_pkt.getPayload() instanceof TCP) {
-                        TCP tcp_pkt = (TCP) ip_pkt.getPayload();
-                        client.srcPort = tcp_pkt.getSourcePort();
-                        client.targetPort = tcp_pkt.getDestinationPort();
-                    }
-                    if (ip_pkt.getPayload() instanceof UDP) {
-                        UDP udp_pkt = (UDP) ip_pkt.getPayload();
-                        client.srcPort = udp_pkt.getSourcePort();
-                        client.targetPort = udp_pkt.getDestinationPort();
-                    }
-                    if (ip_pkt.getPayload() instanceof ICMP) {
-                        client.srcPort = TransportPort.of(8); 
-                        client.targetPort = TransportPort.of(0); 
-                    }
-                    
-                    LBVip vip = vips.get(vipIpToId.get(destIpAddress));
-                    if (vip == null)			// fix dereference violations           
-                    	return Command.CONTINUE;
-                    LBPool pool = pools.get(vip.pickPool(client));
-                    if (pool == null)			// fix dereference violations
-                    	return Command.CONTINUE;
-                    LBMember member = members.get(pool.pickMember(client));
-                    if(member == null)			//fix dereference violations
-                    	return Command.CONTINUE;
-                    
-                    // for chosen member, check device manager and find and push routes, in both directions                    
-                    pushBidirectionalVipRoutes(sw, pi, cntx, client, member);
-                   
-                    // packet out based on table rule
-                    pushPacket(pkt, sw, pi.getBufferId(), (pi.getVersion().compareTo(OFVersion.OF_12) < 0) ? pi.getInPort() : pi.getMatch().get(MatchField.IN_PORT), OFPort.TABLE,
-                                cntx, true);
-
-                    return Command.STOP;
-                }
-            }
-        }
-        // bypass non-load-balanced traffic for normal processing (forwarding)
-        return Command.CONTINUE;
-    }
-
-    /**
-     * used to send proxy Arp for load balanced service requests
-     * @param IOFSwitch sw
-     * @param OFPacketIn pi
-     * @param FloodlightContext cntx
-     * @param String vipId
-     */
-    
-    protected void vipProxyArpReply(IOFSwitch sw, OFPacketIn pi, FloodlightContext cntx, String vipId) {
-        log.debug("vipProxyArpReply");
-            
-        Ethernet eth = IFloodlightProviderService.bcStore.get(cntx,
-                                                              IFloodlightProviderService.CONTEXT_PI_PAYLOAD);
-
-        // retrieve original arp to determine host configured gw IP address                                          
-        if (! (eth.getPayload() instanceof ARP))
-            return;
-        ARP arpRequest = (ARP) eth.getPayload();
-        
-        // have to do proxy arp reply since at this point we cannot determine the requesting application type
-        
-        // generate proxy ARP reply
-        IPacket arpReply = new Ethernet()
-            .setSourceMACAddress(vips.get(vipId).proxyMac)
-            .setDestinationMACAddress(eth.getSourceMACAddress())
-            .setEtherType(EthType.ARP)
-            .setVlanID(eth.getVlanID())
-            .setPriorityCode(eth.getPriorityCode())
-            .setPayload(
-                new ARP()
-                .setHardwareType(ARP.HW_TYPE_ETHERNET)
-                .setProtocolType(ARP.PROTO_TYPE_IP)
-                .setHardwareAddressLength((byte) 6)
-                .setProtocolAddressLength((byte) 4)
-                .setOpCode(ARP.OP_REPLY)
-                .setSenderHardwareAddress(vips.get(vipId).proxyMac)
-                .setSenderProtocolAddress(arpRequest.getTargetProtocolAddress())
-                .setTargetHardwareAddress(eth.getSourceMACAddress())
-                .setTargetProtocolAddress(arpRequest.getSenderProtocolAddress()));
-                
-        // push ARP reply out
-        pushPacket(arpReply, sw, OFBufferId.NO_BUFFER, OFPort.ANY, (pi.getVersion().compareTo(OFVersion.OF_12) < 0 ? pi.getInPort() : pi.getMatch().get(MatchField.IN_PORT)), cntx, true);
-        log.debug("proxy ARP reply pushed as {}", IPv4.fromIPv4Address(vips.get(vipId).address));
-        
-        return;
-    }
-
-    /**
-     * used to push any packet - borrowed routine from Forwarding
-     * 
-     * @param OFPacketIn pi
-     * @param IOFSwitch sw
-     * @param int bufferId
-     * @param short inPort
-     * @param short outPort
-     * @param FloodlightContext cntx
-     * @param boolean flush
-     */    
-    public void pushPacket(IPacket packet, 
-                           IOFSwitch sw,
-                           OFBufferId bufferId,
-                           OFPort inPort,
-                           OFPort outPort, 
-                           FloodlightContext cntx,
-                           boolean flush) {
-        if (log.isTraceEnabled()) {
-            log.trace("PacketOut srcSwitch={} inPort={} outPort={}", 
-                      new Object[] {sw, inPort, outPort});
-        }
-
-        OFPacketOut.Builder pob = sw.getOFFactory().buildPacketOut();
-
-        // set actions
-        List<OFAction> actions = new ArrayList<OFAction>();
-        actions.add(sw.getOFFactory().actions().buildOutput().setPort(outPort).setMaxLen(Integer.MAX_VALUE).build());
-
-        pob.setActions(actions);
-        
-        // set buffer_id, in_port
-        pob.setBufferId(bufferId);
-        pob.setInPort(inPort);
-
-        // set data - only if buffer_id == -1
-        if (pob.getBufferId() == OFBufferId.NO_BUFFER) {
-            if (packet == null) {
-                log.error("BufferId is not set and packet data is null. " +
-                          "Cannot send packetOut. " +
-                        "srcSwitch={} inPort={} outPort={}",
-                        new Object[] {sw, inPort, outPort});
-                return;
-            }
-            byte[] packetData = packet.serialize();
-            pob.setData(packetData);
-        }
-
-        counterPacketOut.increment();
-        sw.write(pob.build());
-    }
-
-    /**
-     * used to find and push in-bound and out-bound routes using StaticFlowEntryPusher
-     * @param IOFSwitch sw
-     * @param OFPacketIn pi
-     * @param FloodlightContext cntx
-     * @param IPClient client
-     * @param LBMember member
-     */
-    protected void pushBidirectionalVipRoutes(IOFSwitch sw, OFPacketIn pi, FloodlightContext cntx, IPClient client, LBMember member) {
-        
-        // borrowed code from Forwarding to retrieve src and dst device entities
-        // Check if we have the location of the destination
-        IDevice srcDevice = null;
-        IDevice dstDevice = null;
-        
-        // retrieve all known devices
-        Collection<? extends IDevice> allDevices = deviceManagerService.getAllDevices();
-        
-        for (IDevice d : allDevices) {
-            for (int j = 0; j < d.getIPv4Addresses().length; j++) {
-                    if (srcDevice == null && client.ipAddress.equals(d.getIPv4Addresses()[j]))
-                        srcDevice = d;
-                    if (dstDevice == null && member.address == d.getIPv4Addresses()[j].getInt()) {
-                        dstDevice = d;
-                        member.macString = dstDevice.getMACAddressString();
-                    }
-                    if (srcDevice != null && dstDevice != null)
-                        break;
-            }
-        }  
-        
-        // srcDevice and/or dstDevice is null, no route can be pushed
-        if (srcDevice == null || dstDevice == null) return;
-        
-        DatapathId srcIsland = topologyService.getClusterId(sw.getId());
-
-        if (srcIsland == null) {
-            log.debug("No openflow island found for source {}/{}", 
-                      sw.getId().toString(), pi.getInPort());
-            return;
-        }
-        
-        // Validate that we have a destination known on the same island
-        // Validate that the source and destination are not on the same switchport
-        boolean on_same_island = false;
-        boolean on_same_if = false;
-        for (SwitchPort dstDap : dstDevice.getAttachmentPoints()) {
-            DatapathId dstSwDpid = dstDap.getNodeId();
-            DatapathId dstIsland = topologyService.getClusterId(dstSwDpid);
-            if ((dstIsland != null) && dstIsland.equals(srcIsland)) {
-                on_same_island = true;
-                if ((sw.getId().equals(dstSwDpid)) && OFMessageUtils.getInPort(pi).equals(dstDap.getPortId())) {
-                    on_same_if = true;
-                }
-                break;
-            }
-        }
-        
-        if (!on_same_island) {
-            // Flood since we don't know the dst device
-            if (log.isTraceEnabled()) {
-                log.trace("No first hop island found for destination " + 
-                        "device {}, Action = flooding", dstDevice);
-            }
-            return;
-        }            
-        
-        if (on_same_if) {
-            if (log.isTraceEnabled()) {
-                log.trace("Both source and destination are on the same " + 
-                        "switch/port {}/{}, Action = NOP", 
-                        sw.toString(), pi.getInPort());
-            }
-            return;
-        }
-        
-        // Install all the routes where both src and dst have attachment
-        // points.  Since the lists are stored in sorted order we can 
-        // traverse the attachment points in O(m+n) time
-        SwitchPort[] srcDaps = srcDevice.getAttachmentPoints();
-        Arrays.sort(srcDaps, clusterIdComparator);
-        SwitchPort[] dstDaps = dstDevice.getAttachmentPoints();
-        Arrays.sort(dstDaps, clusterIdComparator);
-        
-        int iSrcDaps = 0, iDstDaps = 0;
-
-        // following Forwarding's same routing routine, retrieve both in-bound and out-bound routes for
-        // all clusters.
-        while ((iSrcDaps < srcDaps.length) && (iDstDaps < dstDaps.length)) {
-            SwitchPort srcDap = srcDaps[iSrcDaps];
-            SwitchPort dstDap = dstDaps[iDstDaps];
-            DatapathId srcCluster = 
-                    topologyService.getClusterId(srcDap.getNodeId());
-            DatapathId dstCluster = 
-                    topologyService.getClusterId(dstDap.getNodeId());
-
-            int srcVsDest = srcCluster.compareTo(dstCluster);
-            if (srcVsDest == 0) {
-                if (!srcDap.equals(dstDap) && 
-                        (srcCluster != null) && 
-                        (dstCluster != null)) {
-                    Path routeIn = 
-                            routingEngineService.getPath(srcDap.getNodeId(),
-                                                   srcDap.getPortId(),
-                                                   dstDap.getNodeId(),
-                                                   dstDap.getPortId());
-                    Path routeOut = 
-                            routingEngineService.getPath(dstDap.getNodeId(),
-                                                   dstDap.getPortId(),
-                                                   srcDap.getNodeId(),
-                                                   srcDap.getPortId());
-
-                    // use static flow entry pusher to push flow mod along in and out path
-                    // in: match src client (ip, port), rewrite dest from vip ip/port to member ip/port, forward
-                    // out: match dest client (ip, port), rewrite src from member ip/port to vip ip/port, forward
-                    
-                    if (! routeIn.getPath().isEmpty()) {
-                        pushStaticVipRoute(true, routeIn, client, member, sw);
-                    }
-                    
-                    if (! routeOut.getPath().isEmpty()) {
-                        pushStaticVipRoute(false, routeOut, client, member, sw);
-                    }
-
-                }
-                iSrcDaps++;
-                iDstDaps++;
-            } else if (srcVsDest < 0) {
-                iSrcDaps++;
-            } else {
-                iDstDaps++;
-            }
-        }
-        return;
-    }
-    
-    /**
-     * used to push given route using static flow entry pusher
-     * @param boolean inBound
-     * @param Path route
-     * @param IPClient client
-     * @param LBMember member
-     * @param long pinSwitch
-     */
-    public void pushStaticVipRoute(boolean inBound, Path route, IPClient client, LBMember member, IOFSwitch pinSwitch) {
-        List<NodePortTuple> path = route.getPath();
-        if (path.size() > 0) {
-           for (int i = 0; i < path.size(); i+=2) {
-               DatapathId sw = path.get(i).getNodeId();
-               String entryName;
-               Match.Builder mb = pinSwitch.getOFFactory().buildMatch();
-               ArrayList<OFAction> actions = new ArrayList<OFAction>();
-               
-               OFFlowMod.Builder fmb = pinSwitch.getOFFactory().buildFlowAdd();
-
-               fmb.setIdleTimeout(FlowModUtils.INFINITE_TIMEOUT);
-               fmb.setHardTimeout(FlowModUtils.INFINITE_TIMEOUT);
-               fmb.setBufferId(OFBufferId.NO_BUFFER);
-               fmb.setOutPort(OFPort.ANY);
-               fmb.setCookie(U64.of(0));  
-               fmb.setPriority(FlowModUtils.PRIORITY_MAX);
-               
-               
-               if (inBound) {
-                   entryName = "inbound-vip-"+ member.vipId+"-client-"+client.ipAddress
-                		   +"-srcport-"+client.srcPort+"-dstport-"+client.targetPort
-                           +"-srcswitch-"+path.get(0).getNodeId()+"-sw-"+sw;
-                   mb.setExact(MatchField.ETH_TYPE, EthType.IPv4)
-                   .setExact(MatchField.IP_PROTO, client.nw_proto)
-                   .setExact(MatchField.IPV4_SRC, client.ipAddress)
-                   .setExact(MatchField.IN_PORT, path.get(i).getPortId());
-                   if (client.nw_proto.equals(IpProtocol.TCP)) {
-                	   mb.setExact(MatchField.TCP_SRC, client.srcPort);
-                   } else if (client.nw_proto.equals(IpProtocol.UDP)) {
-                	   mb.setExact(MatchField.UDP_SRC, client.srcPort);
-                   } else if (client.nw_proto.equals(IpProtocol.SCTP)) {
-                	   mb.setExact(MatchField.SCTP_SRC, client.srcPort);
-                   } else if (client.nw_proto.equals(IpProtocol.ICMP)) {
-                	   /* no-op */
-                   } else {
-                	   log.error("Unknown IpProtocol {} detected during inbound static VIP route push.", client.nw_proto);
-                   }
-                   
-
-                   if (sw.equals(pinSwitch.getId())) {
-                       if (pinSwitch.getOFFactory().getVersion().compareTo(OFVersion.OF_12) < 0) { 
-                    	   actions.add(pinSwitch.getOFFactory().actions().setDlDst(MacAddress.of(member.macString)));
-                    	   actions.add(pinSwitch.getOFFactory().actions().setNwDst(IPv4Address.of(member.address)));
-                    	   actions.add(pinSwitch.getOFFactory().actions().output(path.get(i+1).getPortId(), Integer.MAX_VALUE));
-                       } else { // OXM introduced in OF1.2
-                    	   actions.add(pinSwitch.getOFFactory().actions().setField(pinSwitch.getOFFactory().oxms().ethDst(MacAddress.of(member.macString))));
-                    	   actions.add(pinSwitch.getOFFactory().actions().setField(pinSwitch.getOFFactory().oxms().ipv4Dst(IPv4Address.of(member.address))));
-                    	   actions.add(pinSwitch.getOFFactory().actions().output(path.get(i+1).getPortId(), Integer.MAX_VALUE));
-                       }
-                   } else {
-                	   //fix concurrency errors
-                	   try{
-                		   actions.add(switchService.getSwitch(path.get(i+1).getNodeId()).getOFFactory().actions().output(path.get(i+1).getPortId(), Integer.MAX_VALUE));
-                	   }
-                	   catch(NullPointerException e){
-                		   log.error("Fail to install loadbalancer flow rules to offline switch {}.", path.get(i+1).getNodeId());
-                	   }
-                   }
-               } else {
-                   entryName = "outbound-vip-"+ member.vipId+"-client-"+client.ipAddress
-                		   +"-srcport-"+client.srcPort+"-dstport-"+client.targetPort
-                           +"-srcswitch-"+path.get(0).getNodeId()+"-sw-"+sw;
-                   mb.setExact(MatchField.ETH_TYPE, EthType.IPv4)
-                   .setExact(MatchField.IP_PROTO, client.nw_proto)
-                   .setExact(MatchField.IPV4_DST, client.ipAddress)
-                   .setExact(MatchField.IN_PORT, path.get(i).getPortId());
-                   if (client.nw_proto.equals(IpProtocol.TCP)) {
-                	   mb.setExact(MatchField.TCP_DST, client.srcPort);
-                   } else if (client.nw_proto.equals(IpProtocol.UDP)) {
-                	   mb.setExact(MatchField.UDP_DST, client.srcPort);
-                   } else if (client.nw_proto.equals(IpProtocol.SCTP)) {
-                	   mb.setExact(MatchField.SCTP_DST, client.srcPort);
-                   } else if (client.nw_proto.equals(IpProtocol.ICMP)) {
-                	   /* no-op */
-                   } else {
-                	   log.error("Unknown IpProtocol {} detected during outbound static VIP route push.", client.nw_proto);
-                   }
-                   
-                   if (sw.equals(pinSwitch.getId())) {
-                       if (pinSwitch.getOFFactory().getVersion().compareTo(OFVersion.OF_12) < 0) { 
-                    	   actions.add(pinSwitch.getOFFactory().actions().setDlSrc(vips.get(member.vipId).proxyMac));
-                    	   actions.add(pinSwitch.getOFFactory().actions().setNwSrc(IPv4Address.of(vips.get(member.vipId).address)));
-                    	   actions.add(pinSwitch.getOFFactory().actions().output(path.get(i+1).getPortId(), Integer.MAX_VALUE));
-                       } else { // OXM introduced in OF1.2
-                    	   actions.add(pinSwitch.getOFFactory().actions().setField(pinSwitch.getOFFactory().oxms().ethSrc(vips.get(member.vipId).proxyMac)));
-                    	   actions.add(pinSwitch.getOFFactory().actions().setField(pinSwitch.getOFFactory().oxms().ipv4Src(IPv4Address.of(vips.get(member.vipId).address))));
-                    	   actions.add(pinSwitch.getOFFactory().actions().output(path.get(i+1).getPortId(), Integer.MAX_VALUE));
-                       }
-                   } else {
-                	   //fix concurrency errors
-                	   try{
-                		   actions.add(switchService.getSwitch(path.get(i+1).getNodeId()).getOFFactory().actions().output(path.get(i+1).getPortId(), Integer.MAX_VALUE));
-                	   }
-                	   catch(NullPointerException e){
-                		   log.error("Fail to install loadbalancer flow rules to offline switches {}.", path.get(i+1).getNodeId());
-                	   }
-                   }
-                   
-               }
-               
-               
-               fmb.setActions(actions);
-               fmb.setPriority(U16.t(LB_PRIORITY));
-               fmb.setMatch(mb.build());
-               sfpService.addFlow(entryName, fmb.build(), sw);
-           }
-        }
-        return;
-    }
-
-    
-    @Override
-    public Collection<LBVip> listVips() {
-        return vips.values();
-    }
-
-    @Override
-    public Collection<LBVip> listVip(String vipId) {
-        Collection<LBVip> result = new HashSet<LBVip>();
-        result.add(vips.get(vipId));
-        return result;
-    }
-
-    @Override
-    public LBVip createVip(LBVip vip) {
-        if (vip == null)
-            vip = new LBVip();
-        
-        vips.put(vip.id, vip);
-        vipIpToId.put(vip.address, vip.id);
-        vipIpToMac.put(vip.address, vip.proxyMac);
-        
-        return vip;
-    }
-
-    @Override
-    public LBVip updateVip(LBVip vip) {
-        vips.put(vip.id, vip);
-        return vip;
-    }
-
-    @Override
-    public int removeVip(String vipId) {
-        if(vips.containsKey(vipId)){
-            vips.remove(vipId);
-            return 0;
-        } else {
-            return -1;
-        }
-    }
-
-    @Override
-    public Collection<LBPool> listPools() {
-        return pools.values();
-    }
-
-    @Override
-    public Collection<LBPool> listPool(String poolId) {
-        Collection<LBPool> result = new HashSet<LBPool>();
-        result.add(pools.get(poolId));
-        return result;
-    }
-
-    @Override
-    public LBPool createPool(LBPool pool) {
-        if (pool == null)
-            pool = new LBPool();
-        
-        pools.put(pool.id, pool);
-        if (pool.vipId != null && vips.containsKey(pool.vipId))
-            vips.get(pool.vipId).pools.add(pool.id);
-        else {
-            log.error("specified vip-id must exist");
-            pool.vipId = null;
-            pools.put(pool.id, pool);
-        }
-        return pool;
-    }
-
-    @Override
-    public LBPool updatePool(LBPool pool) {
-        pools.put(pool.id, pool);
-        return null;
-    }
-
-    @Override
-    public int removePool(String poolId) {
-        LBPool pool;
-        if (pools != null) {
-            pool = pools.get(poolId);
-            if (pool == null)	// fix dereference violations
-            	return -1;
-            if (pool.vipId != null && vips.containsKey(pool.vipId))
-                vips.get(pool.vipId).pools.remove(poolId);
-            pools.remove(poolId);
-            return 0;
-        } else {
-            return -1;
-        }
-    }
-
-    @Override
-    public Collection<LBMember> listMembers() {
-        return members.values();
-    }
-
-    @Override
-    public Collection<LBMember> listMember(String memberId) {
-        Collection<LBMember> result = new HashSet<LBMember>();
-        result.add(members.get(memberId));
-        return result;
-        }
-
-    @Override
-    public Collection<LBMember> listMembersByPool(String poolId) {
-        Collection<LBMember> result = new HashSet<LBMember>();
-        
-        if(pools.containsKey(poolId)) {
-            ArrayList<String> memberIds = pools.get(poolId).members;
-            for (int i = 0; i<memberIds.size(); i++)
-                result.add(members.get(memberIds.get(i)));
-        }
-        return result;
-    }
-    
-    @Override
-    public LBMember createMember(LBMember member) {
-        if (member == null)
-            member = new LBMember();
-
-        members.put(member.id, member);
-        memberIpToId.put(member.address, member.id);
-
-        if (member.poolId != null && pools.get(member.poolId) != null) {
-            member.vipId = pools.get(member.poolId).vipId;
-            if (!pools.get(member.poolId).members.contains(member.id))
-                pools.get(member.poolId).members.add(member.id);
-        } else
-            log.error("member must be specified with non-null pool_id");
-        
-        return member;
-    }
-
-    @Override
-    public LBMember updateMember(LBMember member) {
-        members.put(member.id, member);
-        return member;
-    }
-
-    @Override
-    public int removeMember(String memberId) {
-        LBMember member;
-        member = members.get(memberId);
-        
-        if(member != null){
-            if (member.poolId != null && pools.containsKey(member.poolId))
-                pools.get(member.poolId).members.remove(memberId);
-            members.remove(memberId);
-            return 0;
-        } else {
-            return -1;
-        }    
-    }
-
-    @Override
-    public Collection<LBMonitor> listMonitors() {
-        return null;
-    }
-
-    @Override
-    public Collection<LBMonitor> listMonitor(String monitorId) {
-        return null;
-    }
-
-    @Override
-    public LBMonitor createMonitor(LBMonitor monitor) {
-        return null;
-    }
-
-    @Override
-    public LBMonitor updateMonitor(LBMonitor monitor) {
-        return null;
-    }
-
-    @Override
-    public int removeMonitor(String monitorId) {
-        return 0;
-    }
-
-    @Override
-    public Collection<Class<? extends IFloodlightService>>
-            getModuleServices() {
-        Collection<Class<? extends IFloodlightService>> l = 
-                new ArrayList<Class<? extends IFloodlightService>>();
-        l.add(ILoadBalancerService.class);
-        return l;
-   }
-
-    @Override
-    public Map<Class<? extends IFloodlightService>, IFloodlightService>
-            getServiceImpls() {
-        Map<Class<? extends IFloodlightService>, IFloodlightService> m = 
-                new HashMap<Class<? extends IFloodlightService>,
-                    IFloodlightService>();
-        m.put(ILoadBalancerService.class, this);
-        return m;
-    }
-
-    @Override
-    public Collection<Class<? extends IFloodlightService>>
-            getModuleDependencies() {
-        Collection<Class<? extends IFloodlightService>> l = 
-                new ArrayList<Class<? extends IFloodlightService>>();
-        l.add(IFloodlightProviderService.class);
-        l.add(IRestApiService.class);
-        l.add(IOFSwitchService.class);
-        l.add(IDeviceService.class);
-        l.add(IDebugCounterService.class);
-        l.add(ITopologyService.class);
-        l.add(IRoutingService.class);
-        l.add(IStaticEntryPusherService.class);
-
-        return l;
-    }
-
-    @Override
-    public void init(FloodlightModuleContext context)
-                                                 throws FloodlightModuleException {
-        floodlightProviderService = context.getServiceImpl(IFloodlightProviderService.class);
-        restApiService = context.getServiceImpl(IRestApiService.class);
-        debugCounterService = context.getServiceImpl(IDebugCounterService.class);
-        deviceManagerService = context.getServiceImpl(IDeviceService.class);
-        routingEngineService = context.getServiceImpl(IRoutingService.class);
-        topologyService = context.getServiceImpl(ITopologyService.class);
-        sfpService = context.getServiceImpl(IStaticEntryPusherService.class);
-        switchService = context.getServiceImpl(IOFSwitchService.class);
-        
-        vips = new HashMap<String, LBVip>();
-        pools = new HashMap<String, LBPool>();
-        members = new HashMap<String, LBMember>();
-        vipIpToId = new HashMap<Integer, String>();
-        vipIpToMac = new HashMap<Integer, MacAddress>();
-        memberIpToId = new HashMap<Integer, String>();
-    }
-
-    @Override
-    public void startUp(FloodlightModuleContext context) {
-        floodlightProviderService.addOFMessageListener(OFType.PACKET_IN, this);
-        restApiService.addRestletRoutable(new LoadBalancerWebRoutable());
-        debugCounterService.registerModule(this.getName());
-        counterPacketOut = debugCounterService.registerCounter(this.getName(), "packet-outs-written", "Packet outs written by the LoadBalancer", MetaData.WARN);
-    }
+ILoadBalancerService, IOFMessageListener {
+
+	protected static Logger log = LoggerFactory.getLogger(LoadBalancer.class);
+
+	// Our dependencies
+	protected IFloodlightProviderService floodlightProviderService;
+	protected IRestApiService restApiService;
+
+	protected IDebugCounterService debugCounterService;
+	private IDebugCounter counterPacketOut;
+	protected IDeviceService deviceManagerService;
+	protected IRoutingService routingEngineService;
+	protected ITopologyService topologyService;
+	protected IStaticEntryPusherService sfpService;
+	protected IOFSwitchService switchService;
+	protected IStatisticsService statisticsService;
+
+	protected HashMap<String, LBVip> vips;
+	protected HashMap<String, LBPool> pools;
+	protected HashMap<String, LBMember> members;
+	protected HashMap<Integer, String> vipIpToId;
+	protected HashMap<Integer, MacAddress> vipIpToMac;
+	protected HashMap<Integer, String> memberIpToId;
+	protected HashMap<IPClient, LBMember> clientToMember;
+
+	//Copied from Forwarding with message damper routine for pushing proxy Arp 
+	protected static String LB_ETHER_TYPE = "0x800";
+	protected static int LB_PRIORITY = 32768;
+
+	// Comparator for sorting by SwitchCluster
+	public Comparator<SwitchPort> clusterIdComparator =
+			new Comparator<SwitchPort>() {
+		@Override
+		public int compare(SwitchPort d1, SwitchPort d2) {
+			DatapathId d1ClusterId = topologyService.getClusterId(d1.getNodeId());
+			DatapathId d2ClusterId = topologyService.getClusterId(d2.getNodeId());
+			return d1ClusterId.compareTo(d2ClusterId);
+		}
+	};
+
+	// data structure for storing connected
+	public class IPClient {
+		IPv4Address ipAddress;
+		IpProtocol nw_proto;
+		TransportPort srcPort; // tcp/udp src port. icmp type (OFMatch convention)
+		TransportPort targetPort; // tcp/udp dst port, icmp code (OFMatch convention)
+
+		public IPClient() {
+			ipAddress = IPv4Address.NONE;
+			nw_proto = IpProtocol.NONE;
+			srcPort = TransportPort.NONE;
+			targetPort = TransportPort.NONE;
+		}
+	}
+
+	@Override
+	public String getName() {
+		return "loadbalancer";
+	}
+
+	@Override
+	public boolean isCallbackOrderingPrereq(OFType type, String name) {
+		return (type.equals(OFType.PACKET_IN) && 
+				(name.equals("topology") || 
+						name.equals("devicemanager") ||
+						name.equals("virtualizer")));
+	}
+
+	@Override
+	public boolean isCallbackOrderingPostreq(OFType type, String name) {
+		return (type.equals(OFType.PACKET_IN) && name.equals("forwarding"));
+	}
+
+	@Override
+	public net.floodlightcontroller.core.IListener.Command
+	receive(IOFSwitch sw, OFMessage msg, FloodlightContext cntx) {
+		switch (msg.getType()) {
+		case PACKET_IN:
+			return processPacketIn(sw, (OFPacketIn)msg, cntx);
+		default:
+			break;
+		}
+		log.warn("Received unexpected message {}", msg);
+		return Command.CONTINUE;
+	}
+
+	private net.floodlightcontroller.core.IListener.Command processPacketIn(IOFSwitch sw, OFPacketIn pi, FloodlightContext cntx) {
+
+		Ethernet eth = IFloodlightProviderService.bcStore.get(cntx, IFloodlightProviderService.CONTEXT_PI_PAYLOAD);
+		IPacket pkt = eth.getPayload(); 	
+
+		if (eth.isBroadcast() || eth.isMulticast()) {
+			// handle ARP for VIP
+			if (pkt instanceof ARP) {
+				// retrieve arp to determine target IP address                                                       
+				ARP arpRequest = (ARP) eth.getPayload();
+
+				IPv4Address targetProtocolAddress = arpRequest.getTargetProtocolAddress();
+
+				if (vipIpToId.containsKey(targetProtocolAddress.getInt())) {
+					String vipId = vipIpToId.get(targetProtocolAddress.getInt());
+					vipProxyArpReply(sw, pi, cntx, vipId);
+					return Command.STOP;
+				}
+			}
+		} else {
+			// currently only load balance IPv4 packets - no-op for other traffic 
+			if (pkt instanceof IPv4) {
+				IPv4 ip_pkt = (IPv4) pkt;
+
+				// If match Vip and port, check pool and choose member
+				int destIpAddress = ip_pkt.getDestinationAddress().getInt();
+
+				if (vipIpToId.containsKey(destIpAddress)){
+					
+					IPClient client = new IPClient();
+					client.ipAddress = ip_pkt.getSourceAddress();
+					client.nw_proto = ip_pkt.getProtocol();
+					if (ip_pkt.getPayload() instanceof TCP) {
+						TCP tcp_pkt = (TCP) ip_pkt.getPayload();
+
+						client.srcPort = tcp_pkt.getSourcePort();
+						client.targetPort = tcp_pkt.getDestinationPort();
+					}
+					if (ip_pkt.getPayload() instanceof UDP) {
+						UDP udp_pkt = (UDP) ip_pkt.getPayload();
+						client.srcPort = udp_pkt.getSourcePort();
+						client.targetPort = udp_pkt.getDestinationPort();
+					}
+					if (ip_pkt.getPayload() instanceof ICMP) {
+						client.srcPort = TransportPort.of(8); 
+						client.targetPort = TransportPort.of(0); 
+					}
+
+					LBVip vip = vips.get(vipIpToId.get(destIpAddress));
+					if (vip == null)			// fix dereference violations           
+						return Command.CONTINUE;
+					LBPool pool = pools.get(vip.pickPool(client));
+					if (pool == null)			// fix dereference violations
+						return Command.CONTINUE;
+
+					HashMap<String, Short> memberWeights = new HashMap<String, Short>();
+					HashMap<String, U64> memberPortBandwidth = new HashMap<String, U64>();
+					
+					if(pool.lbMethod == LBPool.WEIGHTED_RR){
+						for(String memberId: pool.members){
+							memberWeights.put(memberId,members.get(memberId).weight);
+						}
+					}
+					// Switch statistics collection
+					if(pool.lbMethod == LBPool.STATISTICS && statisticsService != null)
+						memberPortBandwidth = collectSwitchPortBandwidth();
+					
+					LBMember member = members.get(pool.pickMember(client,memberPortBandwidth,memberWeights));
+					if(member == null)			//fix dereference violations
+						return Command.CONTINUE;
+
+					// for chosen member, check device manager and find and push routes, in both directions                    
+					pushBidirectionalVipRoutes(sw, pi, cntx, client, member);
+
+					// packet out based on table rule
+					pushPacket(pkt, sw, pi.getBufferId(), (pi.getVersion().compareTo(OFVersion.OF_12) < 0) ? pi.getInPort() : pi.getMatch().get(MatchField.IN_PORT), OFPort.TABLE,
+							cntx, true);
+
+
+					return Command.STOP;
+				}
+			}
+		}
+		// bypass non-load-balanced traffic for normal processing (forwarding)
+		return Command.CONTINUE;
+	}
+
+	/**
+	 * used to collect statistics from members switch port
+	 * @return HashMap<String, U64> portBandwidth <memberId,bitsPerSecond RX> of port connected to member
+	 */
+	public HashMap<String, U64> collectSwitchPortBandwidth(){
+		HashMap<String,U64> memberPortBandwidth = new HashMap<String, U64>();
+		HashMap<IDevice,String> deviceToMemberId = new HashMap<IDevice, String>();
+
+		// retrieve all known devices to know which ones are attached to the members
+		Collection<? extends IDevice> allDevices = deviceManagerService.getAllDevices();
+
+		for (IDevice d : allDevices) {
+			for (int j = 0; j < d.getIPv4Addresses().length; j++) {
+				if(members != null){
+					for(LBMember member: members.values()){
+						if (member.address == d.getIPv4Addresses()[j].getInt())
+							deviceToMemberId.put(d, member.id);
+					}
+				}
+			}
+		}
+		// collect statistics of the switch ports attached to the members
+		if(deviceToMemberId !=null){
+			for(IDevice membersDevice: deviceToMemberId.keySet()){
+				String memberId = deviceToMemberId.get(membersDevice);
+				for(SwitchPort dstDap: membersDevice.getAttachmentPoints()){					
+					SwitchPortBandwidth bandwidthOfPort = statisticsService.getBandwidthConsumption(dstDap.getNodeId(), dstDap.getPortId());
+					if(bandwidthOfPort != null) // needs time for 1st collection, this avoids nullPointerException 
+						memberPortBandwidth.put(memberId, bandwidthOfPort.getBitsPerSecondRx());
+				}
+			}
+		}
+		return memberPortBandwidth;
+	}
+
+	/**
+	 * used to send proxy Arp for load balanced service requests
+	 * @param IOFSwitch sw
+	 * @param OFPacketIn pi
+	 * @param FloodlightContext cntx
+	 * @param String vipId
+	 */
+
+	protected void vipProxyArpReply(IOFSwitch sw, OFPacketIn pi, FloodlightContext cntx, String vipId) {
+		log.debug("vipProxyArpReply");
+
+		Ethernet eth = IFloodlightProviderService.bcStore.get(cntx,
+				IFloodlightProviderService.CONTEXT_PI_PAYLOAD);
+
+		// retrieve original arp to determine host configured gw IP address                                          
+		if (! (eth.getPayload() instanceof ARP))
+			return;
+		ARP arpRequest = (ARP) eth.getPayload();
+
+		// have to do proxy arp reply since at this point we cannot determine the requesting application type
+
+		// generate proxy ARP reply
+		IPacket arpReply = new Ethernet()
+				.setSourceMACAddress(vips.get(vipId).proxyMac)
+				.setDestinationMACAddress(eth.getSourceMACAddress())
+				.setEtherType(EthType.ARP)
+				.setVlanID(eth.getVlanID())
+				.setPriorityCode(eth.getPriorityCode())
+				.setPayload(
+						new ARP()
+						.setHardwareType(ARP.HW_TYPE_ETHERNET)
+						.setProtocolType(ARP.PROTO_TYPE_IP)
+						.setHardwareAddressLength((byte) 6)
+						.setProtocolAddressLength((byte) 4)
+						.setOpCode(ARP.OP_REPLY)
+						.setSenderHardwareAddress(vips.get(vipId).proxyMac)
+						.setSenderProtocolAddress(arpRequest.getTargetProtocolAddress())
+						.setTargetHardwareAddress(eth.getSourceMACAddress())
+						.setTargetProtocolAddress(arpRequest.getSenderProtocolAddress()));
+
+		// push ARP reply out
+		pushPacket(arpReply, sw, OFBufferId.NO_BUFFER, OFPort.ANY, (pi.getVersion().compareTo(OFVersion.OF_12) < 0 ? pi.getInPort() : pi.getMatch().get(MatchField.IN_PORT)), cntx, true);
+		log.debug("proxy ARP reply pushed as {}", IPv4.fromIPv4Address(vips.get(vipId).address));
+
+		return;
+	}
+
+	/**
+	 * used to push any packet - borrowed routine from Forwarding
+	 * 
+	 * @param OFPacketIn pi
+	 * @param IOFSwitch sw
+	 * @param int bufferId
+	 * @param short inPort
+	 * @param short outPort
+	 * @param FloodlightContext cntx
+	 * @param boolean flush
+	 */    
+	public void pushPacket(IPacket packet, 
+			IOFSwitch sw,
+			OFBufferId bufferId,
+			OFPort inPort,
+			OFPort outPort, 
+			FloodlightContext cntx,
+			boolean flush) {
+		if (log.isTraceEnabled()) {
+			log.trace("PacketOut srcSwitch={} inPort={} outPort={}", 
+					new Object[] {sw, inPort, outPort});
+		}
+
+		OFPacketOut.Builder pob = sw.getOFFactory().buildPacketOut();
+
+		// set actions
+		List<OFAction> actions = new ArrayList<OFAction>();
+		actions.add(sw.getOFFactory().actions().buildOutput().setPort(outPort).setMaxLen(Integer.MAX_VALUE).build());
+
+		pob.setActions(actions);
+
+		// set buffer_id, in_port
+		pob.setBufferId(bufferId);
+		pob.setInPort(inPort);
+
+		// set data - only if buffer_id == -1
+		if (pob.getBufferId() == OFBufferId.NO_BUFFER) {
+			if (packet == null) {
+				log.error("BufferId is not set and packet data is null. " +
+						"Cannot send packetOut. " +
+						"srcSwitch={} inPort={} outPort={}",
+						new Object[] {sw, inPort, outPort});
+				return;
+			}
+			byte[] packetData = packet.serialize();
+			pob.setData(packetData);
+		}
+
+
+		counterPacketOut.increment();
+		sw.write(pob.build());
+
+	}
+
+	/**
+	 * used to find and push in-bound and out-bound routes using StaticFlowEntryPusher
+	 * @param IOFSwitch sw
+	 * @param OFPacketIn pi
+	 * @param FloodlightContext cntx
+	 * @param IPClient client
+	 * @param LBMember member
+	 */
+	protected void pushBidirectionalVipRoutes(IOFSwitch sw, OFPacketIn pi, FloodlightContext cntx, IPClient client, LBMember member) {
+
+		// borrowed code from Forwarding to retrieve src and dst device entities
+		// Check if we have the location of the destination
+		IDevice srcDevice = null;
+		IDevice dstDevice = null;
+
+		// retrieve all known devices
+		Collection<? extends IDevice> allDevices = deviceManagerService.getAllDevices();
+
+		for (IDevice d : allDevices) {
+			for (int j = 0; j < d.getIPv4Addresses().length; j++) {
+				if (srcDevice == null && client.ipAddress.equals(d.getIPv4Addresses()[j]))
+					srcDevice = d;
+				if (dstDevice == null && member.address == d.getIPv4Addresses()[j].getInt()) {
+					dstDevice = d;
+					member.macString = dstDevice.getMACAddressString();
+				}
+				if (srcDevice != null && dstDevice != null)
+					break;
+			}
+		}  
+
+		// srcDevice and/or dstDevice is null, no route can be pushed
+		if (srcDevice == null || dstDevice == null) return;
+
+		DatapathId srcIsland = topologyService.getClusterId(sw.getId());
+
+		if (srcIsland == null) {
+			log.debug("No openflow island found for source {}/{}", 
+					sw.getId().toString(), pi.getInPort());
+			return;
+		}
+
+		// Validate that we have a destination known on the same island
+		// Validate that the source and destination are not on the same switchport
+		boolean on_same_island = false;
+		boolean on_same_if = false;
+		//Switch
+		for (SwitchPort dstDap : dstDevice.getAttachmentPoints()) {
+			DatapathId dstSwDpid = dstDap.getNodeId();
+			DatapathId dstIsland = topologyService.getClusterId(dstSwDpid);
+			if ((dstIsland != null) && dstIsland.equals(srcIsland)) {
+				on_same_island = true;
+				if ((sw.getId().equals(dstSwDpid)) && OFMessageUtils.getInPort(pi).equals(dstDap.getPortId())) {
+					on_same_if = true;
+				}
+				break;
+			}
+		}
+
+		if (!on_same_island) {
+			// Flood since we don't know the dst device
+			if (log.isTraceEnabled()) {
+				log.trace("No first hop island found for destination " + 
+						"device {}, Action = flooding", dstDevice);
+			}
+			return;
+		}            
+
+		if (on_same_if) {
+			if (log.isTraceEnabled()) {
+				log.trace("Both source and destination are on the same " + 
+						"switch/port {}/{}, Action = NOP", 
+						sw.toString(), pi.getInPort());
+			}
+			return;
+		}	
+
+		// Install all the routes where both src and dst have attachment
+		// points.  Since the lists are stored in sorted order we can 
+		// traverse the attachment points in O(m+n) time
+		SwitchPort[] srcDaps = srcDevice.getAttachmentPoints();
+		Arrays.sort(srcDaps, clusterIdComparator);
+		SwitchPort[] dstDaps = dstDevice.getAttachmentPoints();
+		Arrays.sort(dstDaps, clusterIdComparator);
+
+		int iSrcDaps = 0, iDstDaps = 0;
+
+		// following Forwarding's same routing routine, retrieve both in-bound and out-bound routes for
+		// all clusters.
+		while ((iSrcDaps < srcDaps.length) && (iDstDaps < dstDaps.length)) {
+			SwitchPort srcDap = srcDaps[iSrcDaps];
+			SwitchPort dstDap = dstDaps[iDstDaps];
+			DatapathId srcCluster = 
+					topologyService.getClusterId(srcDap.getNodeId());
+			DatapathId dstCluster = 
+					topologyService.getClusterId(dstDap.getNodeId());
+
+			int srcVsDest = srcCluster.compareTo(dstCluster);
+			if (srcVsDest == 0) {
+				if (!srcDap.equals(dstDap) && 
+						(srcCluster != null) && 
+						(dstCluster != null)) {
+					Path routeIn = 
+							routingEngineService.getPath(srcDap.getNodeId(),
+									srcDap.getPortId(),
+									dstDap.getNodeId(),
+									dstDap.getPortId());
+					Path routeOut = 
+							routingEngineService.getPath(dstDap.getNodeId(),
+									dstDap.getPortId(),
+									srcDap.getNodeId(),
+									srcDap.getPortId());
+
+					// use static flow entry pusher to push flow mod along in and out path
+					// in: match src client (ip, port), rewrite dest from vip ip/port to member ip/port, forward
+					// out: match dest client (ip, port), rewrite src from member ip/port to vip ip/port, forward
+
+					if (! routeIn.getPath().isEmpty()) {
+						pushStaticVipRoute(true, routeIn, client, member, sw);
+					}
+
+					if (! routeOut.getPath().isEmpty()) {
+						pushStaticVipRoute(false, routeOut, client, member, sw);
+					}
+
+				}
+				iSrcDaps++;
+				iDstDaps++;
+			} else if (srcVsDest < 0) {
+				iSrcDaps++;
+			} else {
+				iDstDaps++;
+			}
+		}
+		return;
+	}
+
+	/**
+	 * used to push given route using static flow entry pusher
+	 * @param boolean inBound
+	 * @param Path route
+	 * @param IPClient client
+	 * @param LBMember member
+	 * @param long pinSwitch
+	 */
+	public void pushStaticVipRoute(boolean inBound, Path route, IPClient client, LBMember member, IOFSwitch pinSwitch) {
+
+		List<NodePortTuple> path = route.getPath();
+		if (path.size() > 0) {
+			for (int i = 0; i < path.size(); i+=2) {
+				DatapathId sw = path.get(i).getNodeId();
+				String entryName;
+				Match.Builder mb = pinSwitch.getOFFactory().buildMatch();
+				ArrayList<OFAction> actions = new ArrayList<OFAction>();
+
+				OFFlowMod.Builder fmb = pinSwitch.getOFFactory().buildFlowAdd();
+
+				fmb.setIdleTimeout(FlowModUtils.INFINITE_TIMEOUT);
+				fmb.setHardTimeout(FlowModUtils.INFINITE_TIMEOUT);
+				fmb.setBufferId(OFBufferId.NO_BUFFER);
+				fmb.setOutPort(OFPort.ANY);
+				fmb.setCookie(U64.of(0));  
+				fmb.setPriority(FlowModUtils.PRIORITY_MAX);
+
+
+				if (inBound) {
+					entryName = "inbound-vip-"+ member.vipId+"-client-"+client.ipAddress
+							+"-srcport-"+client.srcPort+"-dstport-"+client.targetPort
+							+"-srcswitch-"+path.get(0).getNodeId()+"-sw-"+sw;
+					mb.setExact(MatchField.ETH_TYPE, EthType.IPv4)
+					.setExact(MatchField.IP_PROTO, client.nw_proto)
+					.setExact(MatchField.IPV4_SRC, client.ipAddress)
+					.setExact(MatchField.IN_PORT, path.get(i).getPortId());
+					if (client.nw_proto.equals(IpProtocol.TCP)) {
+						mb.setExact(MatchField.TCP_SRC, client.srcPort);
+					} else if (client.nw_proto.equals(IpProtocol.UDP)) {
+						mb.setExact(MatchField.UDP_SRC, client.srcPort);
+					} else if (client.nw_proto.equals(IpProtocol.SCTP)) {
+						mb.setExact(MatchField.SCTP_SRC, client.srcPort);
+					} else if (client.nw_proto.equals(IpProtocol.ICMP)) {
+						/* no-op */
+					} else {
+						log.error("Unknown IpProtocol {} detected during inbound static VIP route push.", client.nw_proto);
+					}
+
+
+					if (sw.equals(pinSwitch.getId())) {
+						if (pinSwitch.getOFFactory().getVersion().compareTo(OFVersion.OF_12) < 0) {
+							actions.add(pinSwitch.getOFFactory().actions().setDlDst(MacAddress.of(member.macString)));
+							actions.add(pinSwitch.getOFFactory().actions().setNwDst(IPv4Address.of(member.address)));
+							actions.add(pinSwitch.getOFFactory().actions().output(path.get(i+1).getPortId(), Integer.MAX_VALUE));
+						} else { // OXM introduced in OF1.2
+							actions.add(pinSwitch.getOFFactory().actions().setField(pinSwitch.getOFFactory().oxms().ethDst(MacAddress.of(member.macString))));
+							actions.add(pinSwitch.getOFFactory().actions().setField(pinSwitch.getOFFactory().oxms().ipv4Dst(IPv4Address.of(member.address))));
+							actions.add(pinSwitch.getOFFactory().actions().output(path.get(i+1).getPortId(), Integer.MAX_VALUE));
+						}
+					} else {
+						//fix concurrency errors
+						try{
+							actions.add(switchService.getSwitch(path.get(i+1).getNodeId()).getOFFactory().actions().output(path.get(i+1).getPortId(), Integer.MAX_VALUE));
+						}
+						catch(NullPointerException e){
+							log.error("Fail to install loadbalancer flow rules to offline switch {}.", path.get(i+1).getNodeId());
+						}
+					}
+				} else {
+					entryName = "outbound-vip-"+ member.vipId+"-client-"+client.ipAddress
+							+"-srcport-"+client.srcPort+"-dstport-"+client.targetPort
+							+"-srcswitch-"+path.get(0).getNodeId()+"-sw-"+sw;
+					mb.setExact(MatchField.ETH_TYPE, EthType.IPv4)
+					.setExact(MatchField.IP_PROTO, client.nw_proto)
+					.setExact(MatchField.IPV4_DST, client.ipAddress)
+					.setExact(MatchField.IN_PORT, path.get(i).getPortId());
+					if (client.nw_proto.equals(IpProtocol.TCP)) {
+						mb.setExact(MatchField.TCP_DST, client.srcPort);
+					} else if (client.nw_proto.equals(IpProtocol.UDP)) {
+						mb.setExact(MatchField.UDP_DST, client.srcPort);
+					} else if (client.nw_proto.equals(IpProtocol.SCTP)) {
+						mb.setExact(MatchField.SCTP_DST, client.srcPort);
+					} else if (client.nw_proto.equals(IpProtocol.ICMP)) {
+						/* no-op */
+					} else {
+						log.error("Unknown IpProtocol {} detected during outbound static VIP route push.", client.nw_proto);
+					}
+
+					if (sw.equals(pinSwitch.getId())) {
+						if (pinSwitch.getOFFactory().getVersion().compareTo(OFVersion.OF_12) < 0) { 
+							actions.add(pinSwitch.getOFFactory().actions().setDlSrc(vips.get(member.vipId).proxyMac));
+							actions.add(pinSwitch.getOFFactory().actions().setNwSrc(IPv4Address.of(vips.get(member.vipId).address)));
+							actions.add(pinSwitch.getOFFactory().actions().output(path.get(i+1).getPortId(), Integer.MAX_VALUE));
+						} else { // OXM introduced in OF1.2
+							actions.add(pinSwitch.getOFFactory().actions().setField(pinSwitch.getOFFactory().oxms().ethSrc(vips.get(member.vipId).proxyMac)));
+							actions.add(pinSwitch.getOFFactory().actions().setField(pinSwitch.getOFFactory().oxms().ipv4Src(IPv4Address.of(vips.get(member.vipId).address))));
+							actions.add(pinSwitch.getOFFactory().actions().output(path.get(i+1).getPortId(), Integer.MAX_VALUE));
+
+						}
+					} else {
+						//fix concurrency errors
+						try{
+							actions.add(switchService.getSwitch(path.get(i+1).getNodeId()).getOFFactory().actions().output(path.get(i+1).getPortId(), Integer.MAX_VALUE));
+						}
+						catch(NullPointerException e){
+							log.error("Fail to install loadbalancer flow rules to offline switches {}.", path.get(i+1).getNodeId());
+						}
+					}
+
+				}
+
+
+				fmb.setActions(actions);
+				fmb.setPriority(U16.t(LB_PRIORITY));
+				fmb.setMatch(mb.build());
+				sfpService.addFlow(entryName, fmb.build(), sw);
+			}
+		}
+
+		return;
+	}
+
+	@Override
+	public Collection<LBVip> listVips() {
+		return vips.values();
+	}
+
+	@Override
+	public Collection<LBVip> listVip(String vipId) {
+		Collection<LBVip> result = new HashSet<LBVip>();
+		result.add(vips.get(vipId));
+		return result;
+	}
+
+	@Override
+	public LBVip createVip(LBVip vip) {
+		if (vip == null)
+			vip = new LBVip();
+
+		vips.put(vip.id, vip);
+		vipIpToId.put(vip.address, vip.id);
+		vipIpToMac.put(vip.address, vip.proxyMac);
+
+		return vip;
+	}
+
+	@Override
+	public LBVip updateVip(LBVip vip) {
+		vips.put(vip.id, vip);
+		return vip;
+	}
+
+	@Override
+	public int removeVip(String vipId) {
+		if(vips.containsKey(vipId)){
+			vips.remove(vipId);
+			return 0;
+		} else {
+			return -1;
+		}
+	}
+
+	@Override
+	public Collection<LBPool> listPools() {
+		return pools.values();
+	}
+
+	@Override
+	public Collection<LBPool> listPool(String poolId) {
+		Collection<LBPool> result = new HashSet<LBPool>();
+		result.add(pools.get(poolId));
+		return result;
+	}
+
+	@Override
+	public LBPool createPool(LBPool pool) {
+		if (pool == null)
+			pool = new LBPool();
+
+		pools.put(pool.id, pool);
+		if (pool.vipId != null && vips.containsKey(pool.vipId))
+			vips.get(pool.vipId).pools.add(pool.id);
+		else {
+			log.error("specified vip-id must exist");
+			pool.vipId = null;
+			pools.put(pool.id, pool);
+		}
+		return pool;
+	}
+
+	@Override
+	public LBPool updatePool(LBPool pool) {
+		pools.put(pool.id, pool);
+		return null;
+	}
+
+	@Override
+	public int removePool(String poolId) {
+		LBPool pool;
+		if (pools != null) {
+			pool = pools.get(poolId);
+			if (pool == null)	// fix dereference violations
+				return -1;
+			if (pool.vipId != null && vips.containsKey(pool.vipId))
+				vips.get(pool.vipId).pools.remove(poolId);
+			pools.remove(poolId);
+			return 0;
+		} else {
+			return -1;
+		}
+	}
+
+	@Override
+	public Collection<LBMember> listMembers() {
+		return members.values();
+	}
+
+	@Override
+	public Collection<LBMember> listMember(String memberId) {
+		Collection<LBMember> result = new HashSet<LBMember>();
+		result.add(members.get(memberId));
+		return result;
+	}
+
+	@Override
+	public Collection<LBMember> listMembersByPool(String poolId) {
+		Collection<LBMember> result = new HashSet<LBMember>();
+
+		if(pools.containsKey(poolId)) {
+			ArrayList<String> memberIds = pools.get(poolId).members;
+			if(memberIds !=null && members != null){
+				for (int i = 0; i<memberIds.size(); i++)
+					result.add(members.get(memberIds.get(i)));
+			}
+		}
+		return result;
+	}
+
+	@Override
+	public LBMember createMember(LBMember member) {
+		if (member == null)
+			member = new LBMember();
+
+		members.put(member.id, member);
+		memberIpToId.put(member.address, member.id);
+
+		if (member.poolId != null && pools.get(member.poolId) != null) {
+			member.vipId = pools.get(member.poolId).vipId;
+			if (!pools.get(member.poolId).members.contains(member.id))
+				pools.get(member.poolId).members.add(member.id);
+		} else
+			log.error("member must be specified with non-null pool_id");
+
+		return member;
+	}
+
+	@Override
+	public LBMember updateMember(LBMember member) {
+		members.put(member.id, member);
+		return member;
+	}
+
+	@Override
+	public int removeMember(String memberId) {
+		LBMember member;
+		member = members.get(memberId);
+
+		if(member != null){
+			if (member.poolId != null && pools.containsKey(member.poolId))
+				pools.get(member.poolId).members.remove(memberId);
+			members.remove(memberId);
+			return 0;
+		} else {
+			return -1;
+		}    
+	}
+
+	@Override
+	public int setMemberWeight(String memberId, String weight){
+		LBMember member;
+		short value;
+		member = members.get(memberId);
+
+		try{
+			value = Short.parseShort(weight);
+		} catch(Exception e){
+			log.error("Invalid value for member weight " + e.getMessage());
+			return -1;
+		}
+		if(member != null && (value <= 10 && value >= 1)){
+			member.weight = value;
+			return 0;
+		}
+		return -1;
+	}
+
+	public int setPriorityToMember(String poolId ,String memberId){
+		if(pools.containsKey(poolId)) {
+			ArrayList<String> memberIds = pools.get(poolId).members;
+			if(memberIds !=null && members != null && memberIds.contains(memberId)){
+				for (int i = 0; i<memberIds.size(); i++){
+					if(members.get(memberIds.get(i)).id.equals(memberId)){
+						members.get(memberId).weight=(short) (1 + memberIds.size()/2);
+					}else
+						members.get(memberIds.get(i)).weight=1;
+				}
+				return 0;
+			}
+		}
+		return -1;
+	}
+	@Override
+	public Collection<LBMonitor> listMonitors() {
+		return null;
+	}
+
+	@Override
+	public Collection<LBMonitor> listMonitor(String monitorId) {
+		return null;
+	}
+
+	@Override
+	public LBMonitor createMonitor(LBMonitor monitor) {
+		return null;
+	}
+
+	@Override
+	public LBMonitor updateMonitor(LBMonitor monitor) {
+		return null;
+	}
+
+	@Override
+	public int removeMonitor(String monitorId) {
+		return 0;
+	}
+
+	@Override
+	public Collection<Class<? extends IFloodlightService>>
+	getModuleServices() {
+		Collection<Class<? extends IFloodlightService>> l = 
+				new ArrayList<Class<? extends IFloodlightService>>();
+		l.add(ILoadBalancerService.class);
+		return l;
+	}
+
+	@Override
+	public Map<Class<? extends IFloodlightService>, IFloodlightService>
+	getServiceImpls() {
+		Map<Class<? extends IFloodlightService>, IFloodlightService> m = 
+				new HashMap<Class<? extends IFloodlightService>,
+				IFloodlightService>();
+		m.put(ILoadBalancerService.class, this);
+		return m;
+	}
+
+	@Override
+	public Collection<Class<? extends IFloodlightService>>
+	getModuleDependencies() {
+		Collection<Class<? extends IFloodlightService>> l = 
+				new ArrayList<Class<? extends IFloodlightService>>();
+		l.add(IFloodlightProviderService.class);
+		l.add(IRestApiService.class);
+		l.add(IOFSwitchService.class);
+		l.add(IDeviceService.class);
+		l.add(IDebugCounterService.class);
+		l.add(ITopologyService.class);
+		l.add(IRoutingService.class);
+		l.add(IStaticEntryPusherService.class);
+		l.add(IStatisticsService.class);
+
+		return l;
+	}
+
+	@Override
+	public void init(FloodlightModuleContext context)
+			throws FloodlightModuleException {
+		floodlightProviderService = context.getServiceImpl(IFloodlightProviderService.class);
+		restApiService = context.getServiceImpl(IRestApiService.class);
+		debugCounterService = context.getServiceImpl(IDebugCounterService.class);
+		deviceManagerService = context.getServiceImpl(IDeviceService.class);
+		routingEngineService = context.getServiceImpl(IRoutingService.class);
+		topologyService = context.getServiceImpl(ITopologyService.class);
+		sfpService = context.getServiceImpl(IStaticEntryPusherService.class);
+		switchService = context.getServiceImpl(IOFSwitchService.class);
+		statisticsService = context.getServiceImpl(IStatisticsService.class);
+
+		vips = new HashMap<String, LBVip>();
+		pools = new HashMap<String, LBPool>();
+		members = new HashMap<String, LBMember>();
+		vipIpToId = new HashMap<Integer, String>();
+		vipIpToMac = new HashMap<Integer, MacAddress>();
+		memberIpToId = new HashMap<Integer, String>();
+	}
+
+	@Override
+	public void startUp(FloodlightModuleContext context) {
+		floodlightProviderService.addOFMessageListener(OFType.PACKET_IN, this);
+		restApiService.addRestletRoutable(new LoadBalancerWebRoutable());
+		debugCounterService.registerModule(this.getName());
+		counterPacketOut = debugCounterService.registerCounter(this.getName(), "packet-outs-written", "Packet outs written by the LoadBalancer", MetaData.WARN);
+	}
 }
diff --git a/src/main/java/net/floodlightcontroller/loadbalancer/LoadBalancerWebRoutable.java b/src/main/java/net/floodlightcontroller/loadbalancer/LoadBalancerWebRoutable.java
index 52c5f567d0b7b59443de7c615dc7832317554c9a..eeb3a9a8a8ac7773712ec473585f5e925bb634a9 100644
--- a/src/main/java/net/floodlightcontroller/loadbalancer/LoadBalancerWebRoutable.java
+++ b/src/main/java/net/floodlightcontroller/loadbalancer/LoadBalancerWebRoutable.java
@@ -34,9 +34,11 @@ public class LoadBalancerWebRoutable implements RestletRoutable {
         router.attach("/pools/{pool}", PoolsResource.class); // GET, PUT, DELETE
         router.attach("/members/", MembersResource.class); // GET, POST
         router.attach("/members/{member}", MembersResource.class); // GET, PUT, DELETE
+        router.attach("/members/{member}/{weight}", WRRResource.class); // PUT, POST
         router.attach("/pools/{pool}/members", PoolMemberResource.class); //GET
+        router.attach("/pools/{pool}/members/{member}", PoolMemberResource.class); // PUT, POST
         router.attach("/health_monitors/", MonitorsResource.class); //GET, POST
-        router.attach("/health_monitors/{monitor}", MonitorsResource.class); //GET, PUT, DELETE        
+        router.attach("/health_monitors/{monitor}", MonitorsResource.class); //GET, PUT, DELETE
         router.attachDefault(NoOp.class);
         return router;
      }
diff --git a/src/main/java/net/floodlightcontroller/loadbalancer/MembersResource.java b/src/main/java/net/floodlightcontroller/loadbalancer/MembersResource.java
index c7301aca513d6ef6d22d93f87699e35d47197970..746d2dd915f40d3efebae64414a672ba791a6e41 100644
--- a/src/main/java/net/floodlightcontroller/loadbalancer/MembersResource.java
+++ b/src/main/java/net/floodlightcontroller/loadbalancer/MembersResource.java
@@ -136,7 +136,11 @@ public class MembersResource extends ServerResource {
             if (n.equals("pool_id")) {
                 member.poolId = jp.getText();
                 continue;
-            } 
+            }
+            if(n.equals("weight")){
+            	member.weight = Short.parseShort(jp.getText());
+            	continue;
+            }
             
             log.warn("Unrecognized field {} in " +
                     "parsing Members", 
diff --git a/src/main/java/net/floodlightcontroller/loadbalancer/PoolMemberResource.java b/src/main/java/net/floodlightcontroller/loadbalancer/PoolMemberResource.java
index 481baeabedce85af632cb7c2e53efb3f55e94416..4f553f799a1f0e91c4509789653417f8ea171698 100644
--- a/src/main/java/net/floodlightcontroller/loadbalancer/PoolMemberResource.java
+++ b/src/main/java/net/floodlightcontroller/loadbalancer/PoolMemberResource.java
@@ -19,6 +19,8 @@ package net.floodlightcontroller.loadbalancer;
 import java.util.Collection;
 
 import org.restlet.resource.Get;
+import org.restlet.resource.Post;
+import org.restlet.resource.Put;
 import org.restlet.resource.ServerResource;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -38,4 +40,19 @@ public class PoolMemberResource extends ServerResource {
         else
             return null;
     }
+    
+    @Put
+	@Post
+	public int setPriorityToMember(){
+
+		String poolId = (String) getRequestAttributes().get("pool");
+		String memberId = (String) getRequestAttributes().get("member");
+
+		ILoadBalancerService lbs =
+				(ILoadBalancerService)getContext().getAttributes().
+				get(ILoadBalancerService.class.getCanonicalName());
+
+		return lbs.setPriorityToMember(poolId,memberId);
+
+	}
 }
diff --git a/src/main/java/net/floodlightcontroller/loadbalancer/PoolsResource.java b/src/main/java/net/floodlightcontroller/loadbalancer/PoolsResource.java
index 82a041a20751fe32b5556c80cc5683234e9efb43..433de10946215f5f8e2bd1430bdcfe710802424b 100644
--- a/src/main/java/net/floodlightcontroller/loadbalancer/PoolsResource.java
+++ b/src/main/java/net/floodlightcontroller/loadbalancer/PoolsResource.java
@@ -128,7 +128,15 @@ public class PoolsResource extends ServerResource {
                 continue;
             }
             if (n.equals("lb_method")) {
-                pool.lbMethod = Short.parseShort(jp.getText());
+            	String method = jp.getText();
+            	if(method.equalsIgnoreCase("RR")){
+            		pool.lbMethod = (short) 1;
+            	} else if(method.equalsIgnoreCase("STATISTICS")){
+            		pool.lbMethod = (short) 2;
+            	} else if(method.equalsIgnoreCase("WRR")){
+            		pool.lbMethod = (short) 3;
+            	}
+            		
                 continue;
             }
             if (n.equals("protocol")) {
diff --git a/src/main/java/net/floodlightcontroller/loadbalancer/WRRResource.java b/src/main/java/net/floodlightcontroller/loadbalancer/WRRResource.java
new file mode 100644
index 0000000000000000000000000000000000000000..78c2c71d1f68ffe51d8db2bc624c25038c469754
--- /dev/null
+++ b/src/main/java/net/floodlightcontroller/loadbalancer/WRRResource.java
@@ -0,0 +1,27 @@
+package net.floodlightcontroller.loadbalancer;
+
+
+import org.restlet.resource.Post;
+import org.restlet.resource.Put;
+import org.restlet.resource.ServerResource;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class WRRResource extends ServerResource{
+	protected static Logger log = LoggerFactory.getLogger(WRRResource.class);
+		
+	@Put
+	@Post
+	public int setMemberWeight(){
+
+		String memberId = (String) getRequestAttributes().get("member");
+		String weight = (String) getRequestAttributes().get("weight");
+
+		ILoadBalancerService lbs =
+				(ILoadBalancerService)getContext().getAttributes().
+				get(ILoadBalancerService.class.getCanonicalName());
+
+		return lbs.setMemberWeight(memberId,weight);
+
+	}	
+}
diff --git a/src/main/java/net/floodlightcontroller/packet/TCP.java b/src/main/java/net/floodlightcontroller/packet/TCP.java
index 1fdf1aafd933a67c61d45213693c96dfcfba9614..3d2f4805e43f2febeaebddf0a21be3d83c3d9858 100644
--- a/src/main/java/net/floodlightcontroller/packet/TCP.java
+++ b/src/main/java/net/floodlightcontroller/packet/TCP.java
@@ -178,6 +178,7 @@ public class TCP extends BasePacket {
         byte[] payloadData = null;
         if (payload != null) {
             payload.setParent(this);
+           
             payloadData = payload.serialize();
             length += payloadData.length;
         }
@@ -379,7 +380,7 @@ public class TCP extends BasePacket {
     @Override
     public IPacket deserialize(byte[] data, int offset, int length)
             throws PacketParsingException {
-        ByteBuffer bb = ByteBuffer.wrap(data, offset, length);
+        ByteBuffer bb = ByteBuffer.wrap(data, offset, length);        
         this.sourcePort = TransportPort.of((int) (bb.getShort() & 0xffff)); // short will be signed, pos or neg
         this.destinationPort = TransportPort.of((int) (bb.getShort() & 0xffff)); // convert range 0 to 65534, not -32768 to 32767
         this.sequence = bb.getInt();
@@ -405,11 +406,12 @@ public class TCP extends BasePacket {
                 this.options = null;
             }
         }
-
+                        
         this.payload = new Data();
         int remLength = bb.limit()-bb.position();
         this.payload = payload.deserialize(data, bb.position(), remLength);
+        
         this.payload.setParent(this);
         return this;
-    }
+    }   
 }
diff --git a/src/main/java/net/floodlightcontroller/routing/ForwardingBase.java b/src/main/java/net/floodlightcontroller/routing/ForwardingBase.java
index a624f2119f8e89ad66e11179d6892bd8a4e1a749..aa104bc19590a4c528af4e738bfd2664b3e4e2a2 100644
--- a/src/main/java/net/floodlightcontroller/routing/ForwardingBase.java
+++ b/src/main/java/net/floodlightcontroller/routing/ForwardingBase.java
@@ -341,7 +341,6 @@ public abstract class ForwardingBase implements IOFMessageListener {
         }
 
         pob.setInPort((pi.getVersion().compareTo(OFVersion.OF_12) < 0 ? pi.getInPort() : pi.getMatch().get(MatchField.IN_PORT)));
-
         messageDamper.write(sw, pob.build());
     }
 
diff --git a/src/test/java/net/floodlightcontroller/loadbalancer/LoadBalancerTest.java b/src/test/java/net/floodlightcontroller/loadbalancer/LoadBalancerTest.java
index df26f7c614bdb46e4dac1a10a885bdbf38006920..c1551b86e1da5d25e3357b22cf6e13b7d4258ed5 100644
--- a/src/test/java/net/floodlightcontroller/loadbalancer/LoadBalancerTest.java
+++ b/src/test/java/net/floodlightcontroller/loadbalancer/LoadBalancerTest.java
@@ -51,6 +51,7 @@ import org.projectfloodlight.openflow.types.IpProtocol;
 import org.projectfloodlight.openflow.types.MacAddress;
 import org.projectfloodlight.openflow.types.OFBufferId;
 import org.projectfloodlight.openflow.types.OFPort;
+import org.projectfloodlight.openflow.types.U64;
 import org.projectfloodlight.openflow.types.VlanVid;
 import org.projectfloodlight.openflow.protocol.OFPacketInReason;
 import org.projectfloodlight.openflow.protocol.action.OFAction;
@@ -72,6 +73,7 @@ import net.floodlightcontroller.devicemanager.IDeviceService;
 import net.floodlightcontroller.devicemanager.IEntityClassifierService;
 import net.floodlightcontroller.devicemanager.internal.DefaultEntityClassifier;
 import net.floodlightcontroller.devicemanager.test.MockDeviceManager;
+import net.floodlightcontroller.loadbalancer.LoadBalancer.IPClient;
 import net.floodlightcontroller.packet.ARP;
 import net.floodlightcontroller.packet.Ethernet;
 import net.floodlightcontroller.packet.ICMP;
@@ -105,12 +107,14 @@ public class LoadBalancerTest extends FloodlightTestCase {
 	protected RestApiServer restApi;
 	protected VipsResource vipsResource;
 	protected PoolsResource poolsResource;
+	protected WRRResource wrrResource;
+	protected PoolMemberResource poolMemberResource;
 	protected MembersResource membersResource;
 	private MockSyncService mockSyncService;
 	protected IDebugCounterService debugCounterService;
 	protected LBVip vip1, vip2;
 	protected LBPool pool1, pool2, pool3;
-	protected LBMember member1, member2, member3, member4;
+	protected LBMember member1, member2, member3, member4, member5, member6;
 	private OFFactory factory;
 
 	@Override
@@ -119,7 +123,7 @@ public class LoadBalancerTest extends FloodlightTestCase {
 		super.setUp();
 
 		factory = OFFactories.getFactory(OFVersion.OF_13);
-		
+
 		lb = new LoadBalancer();
 
 		cntx = new FloodlightContext();
@@ -178,6 +182,8 @@ public class LoadBalancerTest extends FloodlightTestCase {
 		vipsResource = new VipsResource();
 		poolsResource = new PoolsResource();
 		membersResource = new MembersResource();
+		wrrResource = new WRRResource();
+		poolMemberResource = new PoolMemberResource();
 
 		vip1=null;
 		vip2=null;
@@ -190,6 +196,8 @@ public class LoadBalancerTest extends FloodlightTestCase {
 		member2=null;
 		member3=null;
 		member4=null;
+		member5=null;
+		member6=null;
 	}
 
 	@Test
@@ -249,8 +257,8 @@ public class LoadBalancerTest extends FloodlightTestCase {
 
 		testCreateVip();
 
-		postData1 = "{\"id\":\"1\",\"name\":\"pool1\",\"protocol\":\"icmp\",\"vip_id\":\"1\"}";
-		postData2 = "{\"id\":\"2\",\"name\":\"pool2\",\"protocol\":\"tcp\",\"vip_id\":\"2\"}";
+		postData1 = "{\"id\":\"1\",\"name\":\"pool1\",\"protocol\":\"icmp\",\"lb_method\":\"STATISTICS\",\"vip_id\":\"1\"}";
+		postData2 = "{\"id\":\"2\",\"name\":\"pool2\",\"protocol\":\"tcp\",\"lb_method\":\"WRR\",\"vip_id\":\"2\"}";
 		postData3 = "{\"id\":\"3\",\"name\":\"pool3\",\"protocol\":\"udp\",\"vip_id\":\"3\"}";
 
 		try {
@@ -317,16 +325,19 @@ public class LoadBalancerTest extends FloodlightTestCase {
 
 	@Test
 	public void testCreateMember() {
-		String postData1, postData2, postData3, postData4;
+		String postData1, postData2, postData3, postData4,postData5,postData6;
 		IOException error = null;
 
 		testCreateVip();
 		testCreatePool();
 
-		postData1 = "{\"id\":\"1\",\"address\":\"10.0.0.3\",\"port\":\"8\",\"pool_id\":\"1\"}";
-		postData2 = "{\"id\":\"2\",\"address\":\"10.0.0.4\",\"port\":\"8\",\"pool_id\":\"1\"}";
-		postData3 = "{\"id\":\"3\",\"address\":\"10.0.0.5\",\"port\":\"100\",\"pool_id\":\"2\"}";
+		postData1 = "{\"id\":\"1\",\"address\":\"10.0.0.3\",\"port\":\"8\",\"pool_id\":\"1\",\"weight\":\"2\"}";
+		postData2 = "{\"id\":\"2\",\"address\":\"10.0.0.4\",\"port\":\"8\",\"pool_id\":\"1\",\"weight\":\"3\"}";
+		postData3 = "{\"id\":\"3\",\"address\":\"10.0.0.5\",\"port\":\"100\",\"pool_id\":\"2\",\"weight\":\"4\"}";
 		postData4 = "{\"id\":\"4\",\"address\":\"10.0.0.6\",\"port\":\"100\",\"pool_id\":\"2\"}";
+		postData5 = "{\"id\":\"5\",\"address\":\"10.0.0.7\",\"port\":\"100\",\"pool_id\":\"1\",\"weight\":\"5\"}";
+		postData6 = "{\"id\":\"6\",\"address\":\"10.0.0.8\",\"port\":\"100\",\"pool_id\":\"1\",\"weight\":\"5\"}";
+
 
 		try {
 			member1 = membersResource.jsonToMember(postData1);
@@ -348,18 +359,33 @@ public class LoadBalancerTest extends FloodlightTestCase {
 		} catch (IOException e) {
 			error = e;
 		}
+		try {
+			member5= membersResource.jsonToMember(postData5);
+		} catch (IOException e) {
+			error = e;
+		}
+		try {
+			member6= membersResource.jsonToMember(postData6);
+		} catch (IOException e) {
+			error = e;
+		}
+
 
 		// verify correct parsing
 		assertFalse(member1==null);
 		assertFalse(member2==null);
 		assertFalse(member3==null);
 		assertFalse(member4==null);
+		assertFalse(member5==null);
+		assertFalse(member6==null);
 		assertTrue(error==null);
 
 		lb.createMember(member1);
 		lb.createMember(member2);
 		lb.createMember(member3);
 		lb.createMember(member4);
+		lb.createMember(member5);
+		lb.createMember(member6);
 
 		// add the same server a second time
 		lb.createMember(member1);
@@ -369,12 +395,23 @@ public class LoadBalancerTest extends FloodlightTestCase {
 		assertTrue(lb.members.containsKey(member2.id));
 		assertTrue(lb.members.containsKey(member3.id));
 		assertTrue(lb.members.containsKey(member4.id));
+		assertTrue(lb.members.containsKey(member5.id));
+		assertTrue(lb.members.containsKey(member6.id));
 
-		assertTrue(lb.pools.get(member1.poolId).members.size()==2);
+		assertTrue(lb.pools.get(member1.poolId).members.size()==4);
 		assertTrue(lb.pools.get(member3.poolId).members.size()==2);
 
 		// member1 should inherit valid vipId from pool
 		assertTrue(lb.vips.get(member1.vipId)!=null);
+
+		assertTrue(member1.weight==2);
+		assertTrue(member2.weight==3);
+		assertTrue(member3.weight==4);
+		assertTrue(member5.weight==5);
+		assertTrue(member6.weight==5);
+	
+		// default weight value
+		assertTrue(member4.weight==1);
 	}
 
 	@Test
@@ -439,10 +476,10 @@ public class LoadBalancerTest extends FloodlightTestCase {
 		expect(sw1.hasAttribute(IOFSwitch.PROP_SUPPORTS_OFPP_TABLE)).andReturn(true).anyTimes();
 		expect(sw1.getOFFactory()).andReturn(factory).anyTimes();
 		expect(sw1.write(capture(wc1))).andReturn(true).anyTimes();
-		
+
 		replay(sw1);
 		sfp.switchAdded(DatapathId.of(1L));
-		
+
 		verify(sw1);
 
 		/* Test plan:
@@ -469,22 +506,22 @@ public class LoadBalancerTest extends FloodlightTestCase {
 
 		// Build arp packets
 		arpRequest1 = new Ethernet()
-		.setSourceMACAddress("00:00:00:00:00:01")
-		.setDestinationMACAddress("ff:ff:ff:ff:ff:ff")
-		.setEtherType(EthType.ARP)
-		.setVlanID((short) 0)
-		.setPriorityCode((byte) 0)
-		.setPayload(
-				new ARP()
-				.setHardwareType(ARP.HW_TYPE_ETHERNET)
-				.setProtocolType(ARP.PROTO_TYPE_IP)
-				.setHardwareAddressLength((byte) 6)
-				.setProtocolAddressLength((byte) 4)
-				.setOpCode(ARP.OP_REQUEST)
-				.setSenderHardwareAddress(MacAddress.of("00:00:00:00:00:01"))
-				.setSenderProtocolAddress(IPv4Address.of("10.0.0.1"))
-				.setTargetHardwareAddress(MacAddress.of("00:00:00:00:00:00"))
-				.setTargetProtocolAddress(IPv4Address.of("10.0.0.100")));
+				.setSourceMACAddress("00:00:00:00:00:01")
+				.setDestinationMACAddress("ff:ff:ff:ff:ff:ff")
+				.setEtherType(EthType.ARP)
+				.setVlanID((short) 0)
+				.setPriorityCode((byte) 0)
+				.setPayload(
+						new ARP()
+						.setHardwareType(ARP.HW_TYPE_ETHERNET)
+						.setProtocolType(ARP.PROTO_TYPE_IP)
+						.setHardwareAddressLength((byte) 6)
+						.setProtocolAddressLength((byte) 4)
+						.setOpCode(ARP.OP_REQUEST)
+						.setSenderHardwareAddress(MacAddress.of("00:00:00:00:00:01"))
+						.setSenderProtocolAddress(IPv4Address.of("10.0.0.1"))
+						.setTargetHardwareAddress(MacAddress.of("00:00:00:00:00:00"))
+						.setTargetProtocolAddress(IPv4Address.of("10.0.0.100")));
 
 		arpRequest1Serialized = arpRequest1.serialize();
 
@@ -501,22 +538,22 @@ public class LoadBalancerTest extends FloodlightTestCase {
 
 		// Mock proxy arp packet-out
 		arpReply1 = new Ethernet()
-		.setSourceMACAddress(LBVip.LB_PROXY_MAC)
-		.setDestinationMACAddress(MacAddress.of("00:00:00:00:00:01"))
-		.setEtherType(EthType.ARP)
-		.setVlanID((short) 0)
-		.setPriorityCode((byte) 0)
-		.setPayload(
-				new ARP()
-				.setHardwareType(ARP.HW_TYPE_ETHERNET)
-				.setProtocolType(ARP.PROTO_TYPE_IP)
-				.setHardwareAddressLength((byte) 6)
-				.setProtocolAddressLength((byte) 4)
-				.setOpCode(ARP.OP_REPLY)
-				.setSenderHardwareAddress(MacAddress.of(LBVip.LB_PROXY_MAC))
-				.setSenderProtocolAddress(IPv4Address.of("10.0.0.100"))
-				.setTargetHardwareAddress(MacAddress.of("00:00:00:00:00:01"))
-				.setTargetProtocolAddress(IPv4Address.of("10.0.0.1")));
+				.setSourceMACAddress(LBVip.LB_PROXY_MAC)
+				.setDestinationMACAddress(MacAddress.of("00:00:00:00:00:01"))
+				.setEtherType(EthType.ARP)
+				.setVlanID((short) 0)
+				.setPriorityCode((byte) 0)
+				.setPayload(
+						new ARP()
+						.setHardwareType(ARP.HW_TYPE_ETHERNET)
+						.setProtocolType(ARP.PROTO_TYPE_IP)
+						.setHardwareAddressLength((byte) 6)
+						.setProtocolAddressLength((byte) 4)
+						.setOpCode(ARP.OP_REPLY)
+						.setSenderHardwareAddress(MacAddress.of(LBVip.LB_PROXY_MAC))
+						.setSenderProtocolAddress(IPv4Address.of("10.0.0.100"))
+						.setTargetHardwareAddress(MacAddress.of("00:00:00:00:00:01"))
+						.setTargetProtocolAddress(IPv4Address.of("10.0.0.1")));
 
 		arpReply1Serialized = arpReply1.serialize();
 
@@ -530,7 +567,7 @@ public class LoadBalancerTest extends FloodlightTestCase {
 				.setXid(22)
 				.build();
 		sw1.write(arpReplyPacketOut1);
-		
+
 		lb.receive(sw1, arpRequestPacketIn1, cntx);
 		verify(sw1, topology);
 
@@ -540,7 +577,7 @@ public class LoadBalancerTest extends FloodlightTestCase {
 
 		for (OFMessage m: msglist1) {
 			if (m instanceof OFPacketOut)
-                assertEquals(OFMessageUtils.OFMessageIgnoreXid.of(arpReplyPacketOut1), OFMessageUtils.OFMessageIgnoreXid.of(m));
+				assertEquals(OFMessageUtils.OFMessageIgnoreXid.of(arpReplyPacketOut1), OFMessageUtils.OFMessageIgnoreXid.of(m));
 			else
 				assertTrue(false); // unexpected message
 		}
@@ -549,7 +586,7 @@ public class LoadBalancerTest extends FloodlightTestCase {
 		// Skip arpRequest2 test - in reality this will happen, but for unit test the same logic
 		// is already validated with arpRequest1 test above
 		//
-		
+
 		// Keep the StaticFlowEntryPusher happy with a switch in the switch service
 		Map<DatapathId, IOFSwitch> switches = new HashMap<DatapathId, IOFSwitch>(1);
 		switches.put(DatapathId.of(1), sw1);
@@ -558,19 +595,19 @@ public class LoadBalancerTest extends FloodlightTestCase {
 
 		// Build icmp packets
 		icmpPacket1 = new Ethernet()
-		.setSourceMACAddress("00:00:00:00:00:01")
-		.setDestinationMACAddress(LBVip.LB_PROXY_MAC)
-		.setEtherType(EthType.IPv4)
-		.setVlanID((short) 0)
-		.setPriorityCode((byte) 0)
-		.setPayload(
-				new IPv4()
-				.setSourceAddress("10.0.0.1")
-				.setDestinationAddress("10.0.0.100")
-				.setProtocol(IpProtocol.ICMP)
-				.setPayload(new ICMP()
-				.setIcmpCode((byte) 0)
-				.setIcmpType((byte) 0)));
+				.setSourceMACAddress("00:00:00:00:00:01")
+				.setDestinationMACAddress(LBVip.LB_PROXY_MAC)
+				.setEtherType(EthType.IPv4)
+				.setVlanID((short) 0)
+				.setPriorityCode((byte) 0)
+				.setPayload(
+						new IPv4()
+						.setSourceAddress("10.0.0.1")
+						.setDestinationAddress("10.0.0.100")
+						.setProtocol(IpProtocol.ICMP)
+						.setPayload(new ICMP()
+								.setIcmpCode((byte) 0)
+								.setIcmpType((byte) 0)));
 
 		icmpPacket1Serialized = icmpPacket1.serialize();
 
@@ -581,19 +618,19 @@ public class LoadBalancerTest extends FloodlightTestCase {
 				.setReason(OFPacketInReason.NO_MATCH)
 				.build();
 		icmpPacket2 = new Ethernet()
-		.setSourceMACAddress("00:00:00:00:00:02")
-		.setDestinationMACAddress(LBVip.LB_PROXY_MAC)
-		.setEtherType(EthType.IPv4)
-		.setVlanID((short) 0)
-		.setPriorityCode((byte) 0)
-		.setPayload(
-				new IPv4()
-				.setSourceAddress("10.0.0.2")
-				.setDestinationAddress("10.0.0.100")
-				.setProtocol(IpProtocol.ICMP)
-				.setPayload(new ICMP()
-				.setIcmpCode((byte) 0)
-				.setIcmpType((byte) 0)));
+				.setSourceMACAddress("00:00:00:00:00:02")
+				.setDestinationMACAddress(LBVip.LB_PROXY_MAC)
+				.setEtherType(EthType.IPv4)
+				.setVlanID((short) 0)
+				.setPriorityCode((byte) 0)
+				.setPayload(
+						new IPv4()
+						.setSourceAddress("10.0.0.2")
+						.setDestinationAddress("10.0.0.100")
+						.setProtocol(IpProtocol.ICMP)
+						.setPayload(new ICMP()
+								.setIcmpCode((byte) 0)
+								.setIcmpType((byte) 0)));
 
 		icmpPacket2Serialized = icmpPacket2.serialize();
 
@@ -683,5 +720,72 @@ public class LoadBalancerTest extends FloodlightTestCase {
 		assertTrue(map.size()==4);
 	}
 
+	@Test
+	public void testSetMemberWeight() {		
+		testCreateVip();
+		testCreatePool();
+		testCreateMember();	
+
+		lb.setMemberWeight(member1.id, "5");
+		lb.setMemberWeight(member2.id, "2");
+		lb.setMemberWeight(member3.id, "2");
+		lb.setMemberWeight(member4.id, "9");
+
+		assertTrue(member1.weight==5);
+		assertTrue(member2.weight==2);
+		assertTrue(member3.weight==2);
+		assertTrue(member4.weight==9);
 
+		int inf_limit = lb.setMemberWeight(member1.id,"0");
+
+		int sup_limit = lb.setMemberWeight(member1.id,"11");
+
+		assertTrue(inf_limit == -1);
+		assertTrue(sup_limit == -1);
+	}
+
+	@Test
+	public void testSetPriorityMember() {		
+		testCreateVip();
+		testCreatePool();
+		testCreateMember();
+
+		lb.setPriorityToMember(member1.id,member1.poolId);
+
+		assertTrue(member1.weight==3);
+		assertTrue(member2.weight==1);
+		assertTrue(member5.weight==1);
+		assertTrue(member6.weight==1);
+	}
+
+	@Test
+	public void testPoolAlgorithms() {	
+		testCreateVip();
+		testCreatePool();
+		testCreateMember();
+
+		IPClient client = lb.new IPClient();
+
+		HashMap<String, U64> membersBandwidth = new HashMap<String, U64>();
+		membersBandwidth.put(member1.id,U64.of(4999));
+		membersBandwidth.put(member2.id,U64.of(1344));
+		membersBandwidth.put(member3.id,U64.ZERO);
+		membersBandwidth.put(member4.id,U64.of(230));
+		membersBandwidth.put(member5.id,U64.of(2002));
+		membersBandwidth.put(member6.id,U64.of(1345));
+
+		HashMap<String, Short> membersWeight = new HashMap<String, Short>();
+		
+		String memberPickedStats = pool1.pickMember(client, membersBandwidth, membersWeight);
+		
+		String noMembers = pool3.pickMember(client, membersBandwidth, membersWeight);
+
+		membersBandwidth.clear();
+		String memberPickedNoData = pool1.pickMember(client, membersBandwidth, membersWeight);
+		
+		assertTrue(memberPickedStats.equals("2"));
+		assertTrue(memberPickedNoData.equals("1")); // simple round robin
+		
+		assertTrue(noMembers==null);
+	}
 }