Performacne improvements via adding a netty-based openflowj and openflow plugin;...
[controller.git] / opendaylight / samples / reactiveforwarding / src / main / java / org / opendaylight / controller / samples / reactiveforwarding / internal / ReactiveForwardingService.java
diff --git a/opendaylight/samples/reactiveforwarding/src/main/java/org/opendaylight/controller/samples/reactiveforwarding/internal/ReactiveForwardingService.java b/opendaylight/samples/reactiveforwarding/src/main/java/org/opendaylight/controller/samples/reactiveforwarding/internal/ReactiveForwardingService.java
new file mode 100644 (file)
index 0000000..d9c013c
--- /dev/null
@@ -0,0 +1,314 @@
+/*
+ * Copyright IBM Corporation, 2013.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.samples.reactiveforwarding.internal;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.ArrayList;
+import java.util.Dictionary;
+import java.util.List;
+
+
+import org.apache.felix.dm.Component;
+import org.opendaylight.controller.forwardingrulesmanager.FlowEntry;
+import org.opendaylight.controller.forwardingrulesmanager.IForwardingRulesManager;
+import org.opendaylight.controller.hosttracker.IfIptoHost;
+import org.opendaylight.controller.sal.action.Action;
+import org.opendaylight.controller.sal.action.Drop;
+import org.opendaylight.controller.sal.core.Node;
+import org.opendaylight.controller.sal.flowprogrammer.Flow;
+import org.opendaylight.controller.sal.match.Match;
+import org.opendaylight.controller.sal.match.MatchType;
+import org.opendaylight.controller.sal.packet.ARP;
+import org.opendaylight.controller.sal.packet.Ethernet;
+import org.opendaylight.controller.sal.packet.IDataPacketService;
+import org.opendaylight.controller.sal.packet.IListenDataPacket;
+import org.opendaylight.controller.sal.packet.IPv4;
+import org.opendaylight.controller.sal.packet.Packet;
+import org.opendaylight.controller.sal.packet.PacketResult;
+import org.opendaylight.controller.sal.packet.RawPacket;
+import org.opendaylight.controller.sal.routing.IRouting;
+import org.opendaylight.controller.sal.utils.GlobalConstants;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Plain simple reactive forwarding service which received PACKET_IN and
+ * uses Dijkstra's module (IRouting interface) to determine the shortest
+ * path between source and destination and provision the switches
+ *
+ */
+public class ReactiveForwardingService implements IListenDataPacket {
+
+    /*
+     * Logger instance
+     */
+    private static Logger lbsLogger = LoggerFactory.getLogger(ReactiveForwardingService.class);
+
+
+    /*
+     * REQUIRED for decoding the packet
+     */
+    private IDataPacketService dataPacketService = null;
+
+    /*
+     * REQUIRED for host identification from the packet
+     */
+    private IfIptoHost hostTracker;
+
+    /*
+     * REQUIRED for the flow-programming
+     */
+    private IForwardingRulesManager ruleManager;
+
+    /*
+     * REQUIRED for getting the path between source and destination determined from packet
+     */
+    private IRouting routing;
+
+    /*
+     * Load balancer application installs all flows with priority 2.
+     */
+    private static short LB_IPSWITCH_PRIORITY = 2;
+
+    /*
+     * Name of the container where this application will register.
+     */
+    private String containerName = null;
+
+    /*
+     * Set/unset methods for the service instance that load balancer
+     * service requires
+     */
+    public String getContainerName() {
+        if (containerName == null)
+            return GlobalConstants.DEFAULT.toString();
+        return containerName;
+    }
+
+    void setDataPacketService(IDataPacketService s) {
+        this.dataPacketService = s;
+    }
+
+    void unsetDataPacketService(IDataPacketService s) {
+        if (this.dataPacketService == s) {
+            this.dataPacketService = null;
+        }
+    }
+
+    public void setRouting(IRouting routing) {
+        this.routing = routing;
+    }
+
+    public void unsetRouting(IRouting routing) {
+        if (this.routing == routing) {
+            this.routing = null;
+        }
+    }
+
+    public void setHostTracker(IfIptoHost hostTracker) {
+        lbsLogger.debug("Setting HostTracker");
+        this.hostTracker = hostTracker;
+    }
+
+    public void unsetHostTracker(IfIptoHost hostTracker) {
+        if (this.hostTracker == hostTracker) {
+            this.hostTracker = null;
+        }
+    }
+
+    public void setForwardingRulesManager(
+            IForwardingRulesManager forwardingRulesManager) {
+        lbsLogger.debug("Setting ForwardingRulesManager");
+        this.ruleManager = forwardingRulesManager;
+    }
+
+    public void unsetForwardingRulesManager(
+            IForwardingRulesManager forwardingRulesManager) {
+        if (this.ruleManager == forwardingRulesManager) {
+            this.ruleManager = null;
+        }
+    }
+
+    /**
+     * This method receives first packet of flows for which there is no
+     * matching flow rule installed on the switch. IP addresses used for VIPs
+     * are not supposed to be used by any real/virtual host in the network.
+     * Hence, any forwarding/routing service will not install any flows rules matching
+     * these VIPs. This ensures that all the flows destined for VIPs will not find a match
+     * in the switch and will be forwarded to the load balancing service.
+     * Service will decide where to route this traffic based on the load balancing
+     * policy of the VIP's attached pool and will install appropriate flow rules
+     * in a reactive manner.
+     */
+    @Override
+    public PacketResult receiveDataPacket(RawPacket inPkt){
+
+        if (inPkt == null) {
+            return PacketResult.IGNORED;
+        }
+
+        Packet formattedPak = this.dataPacketService.decodeDataPacket(inPkt);
+        Node clientNode = inPkt.getIncomingNodeConnector().getNode();
+
+        if (formattedPak instanceof Ethernet) {
+
+
+            Object ipPkt = formattedPak.getPayload();
+
+            if (ipPkt instanceof ARP){
+            }
+            else{
+
+                lbsLogger.debug("RFWD >> got non-ARP ether packet");
+
+                Ethernet ether = (Ethernet) formattedPak;
+                byte[] destMacAddr = ether.getDestinationMACAddress();
+                byte[] srcMacAddr = ether.getSourceMACAddress();
+
+                //Byte[] dstMacAddr = ArrayUtils.toObject(destMacAddr);
+                //Byte[] srMacAddr = ArrayUtils.toObject(srcMacAddr);
+
+                lbsLogger.debug("RFWD >> Dst Mac Address {}", destMacAddr.toString());
+                lbsLogger.debug("RFWD >> Src Mac Address {}", srcMacAddr.toString());
+
+                //lbsLogger.debug("RFWD >> ip-pkt has dst IP as {}", destIPAddr.getHostAddress());
+                //lbsLogger.debug("RFWD >> ip-pkt has src IP as {}", srcIPAddr.getHostAddress());
+
+                installDummyFlowForCBench(clientNode, null, null, srcMacAddr, destMacAddr);
+
+            }
+
+
+
+            lbsLogger.debug("flow sent to cbench !!");
+
+
+
+            if (ipPkt instanceof IPv4) {
+
+
+
+                IPv4 ipv4Pkt = (IPv4)ipPkt;
+
+                lbsLogger.debug("RFWD >> got IP Packet");
+
+                //InetAddress destIPAddr = InetAddress.getByAddress(NetUtils.intToByteArray4(ipv4Pkt.getDestinationAddress()));
+                //InetAddress srcIPAddr = InetAddress.getByAddress(NetUtils.intToByteArray4(ipv4Pkt.getSourceAddress()));
+
+
+
+
+
+
+                lbsLogger.debug("RFWD >> got IPv4 packet");
+
+            }
+
+        }
+        return PacketResult.IGNORED;
+    }
+
+
+    /**
+     * Function called by the dependency manager when all the required
+     * dependencies are satisfied
+     *
+     */
+    void init(Component c) {
+        Dictionary<?, ?> props = c.getServiceProperties();
+        if (props != null) {
+            this.containerName = (String) props.get("containerName");
+
+            lbsLogger.info("Running container name:" + this.containerName);
+        }else {
+
+            // In the Global instance case the containerName is empty
+            this.containerName = "";
+        }
+        //lbsLogger.info(configManager.toString());
+    }
+
+    /**
+     * Function called by the dependency manager when at least one
+     * dependency become unsatisfied or when the component is shutting
+     * down because for example bundle is being stopped.
+     *
+     */
+    void destroy() {
+    }
+
+    /**
+     * Function called by dependency manager after "init ()" is called
+     * and after the services provided by the class are registered in
+     * the service registry
+     *
+     */
+    void start() {
+    }
+
+    /**
+     * Function called by the dependency manager before the services
+     * exported by the component are unregistered, this will be
+     * followed by a "destroy ()" calls
+     *
+     */
+    void stop() {
+    }
+
+
+    private boolean installDummyFlowForCBench(Node originatorSwitch, InetAddress srcIp, InetAddress dstIp, byte[] srcMac, byte[] dstMac){
+
+
+
+
+        Match match = new Match();
+        List<Action> actions = new ArrayList<Action>();
+
+        //match.setField(MatchType.DL_TYPE, EtherTypes.IPv4.shortValue());
+        //match.setField(MatchType.NW_SRC, srcIp);
+        //match.setField(MatchType.NW_DST, dstIp);
+
+        match.setField(MatchType.DL_SRC, srcMac);
+        //match.setField(MatchType.DL_DST, dstMac);
+
+        actions.add(new Drop());
+
+        Flow flow = new Flow(match, actions);
+        flow.setIdleTimeout((short) 5);
+        flow.setHardTimeout((short) 0);
+        flow.setPriority(LB_IPSWITCH_PRIORITY++);
+
+        String policyName = "cbenchpolicy";
+        String flowName ="cbenchflow";
+
+        FlowEntry fEntry = new FlowEntry(policyName, flowName, flow, originatorSwitch);
+
+        //lbsLogger.debug("Install flow entry {} on node {}",fEntry.toString(),originatorSwitch.toString());
+
+
+
+
+        //if(!this.ruleManager.checkFlowEntryConflict(fEntry)){
+            if(this.ruleManager.installFlowEntry(fEntry).isSuccess()){
+                return true;
+            }else{
+                lbsLogger.error("Error in installing flow entry to node : {}",originatorSwitch);
+            }
+
+        //}else{
+        //    lbsLogger.error("Conflicting flow entry exists : {}",fEntry.toString());
+        //}
+
+        return false;
+
+
+    }
+
+
+}