ONOS-3343 Initial scapy implementation commit

scapy host discovery and re-ordering of setup cases

scapy checkConnection dependency function to check connection with specified packets from given sender(s) to given recipient(s). CASE3000 now uses checkConnection to test one way single to multi point intents.

CASE 3000 scapy implementation complete

CASE 4000, 5000, 1000 scapy implementation and breakup of dependency functions

Change-Id: I9fc277d0e5ba5dd50246f7fc1be76c15566d796c

Finished Implementation of Scapy within FUNCintent

Refactored FUNCintent for clarity and sense
-Now uses dictionaries instead of lists for function params
-separated installing and testing intents into distinct functions
-merged non-host intent testing into one function called testPointIntent

Change-Id: I8ffbe6dcc00994e3b40c9ba0fe7e4188bb2019f7
diff --git a/TestON/drivers/common/cli/emulator/scapyclidriver.py b/TestON/drivers/common/cli/emulator/scapyclidriver.py
new file mode 100644
index 0000000..a083183
--- /dev/null
+++ b/TestON/drivers/common/cli/emulator/scapyclidriver.py
@@ -0,0 +1,925 @@
+#!/usr/bin/env python
+"""
+2015-2016
+
+TestON is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+( at your option ) any later version.
+
+TestON is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with TestON.  If not, see <http://www.gnu.org/licenses/>.
+
+ScapyCliDriver is the basic driver which will handle the Scapy functions
+
+TODO: Add Explanation on how to install scapy
+"""
+import pexpect
+import re
+import sys
+import types
+import os
+from drivers.common.cli.emulatordriver import Emulator
+
+
+class ScapyCliDriver( Emulator ):
+
+    """
+       ScapyCliDriver is the basic driver which will handle
+       the Scapy functions"""
+    def __init__( self ):
+        super( Emulator, self ).__init__()
+        self.handle = self
+        self.name = None
+        self.home = None
+        self.wrapped = sys.modules[ __name__ ]
+        self.flag = 0
+        # TODO: Refactor driver to use these everywhere
+        self.hostPrompt = "~#"
+        self.bashPrompt = "\$"
+        self.scapyPrompt = ">>>"
+
+    def connect( self, **connectargs ):
+        """
+           Here the main is the TestON instance after creating
+           all the log handles."""
+        try:
+            for key in connectargs:
+                vars( self )[ key ] = connectargs[ key ]
+            self.home = "~/mininet"
+            self.name = self.options[ 'name' ]
+            for key in self.options:
+                if key == "home":
+                    self.home = self.options[ 'home' ]
+                    break
+            if self.home is None or self.home == "":
+                self.home = "~/mininet"
+
+            try:
+                if os.getenv( str( self.ip_address ) ) is not None:
+                    self.ip_address = os.getenv( str( self.ip_address ) )
+                else:
+                    main.log.info( self.name +
+                                   ": Trying to connect to " +
+                                   self.ip_address )
+
+            except KeyError:
+                main.log.info( "Invalid host name," +
+                               " connecting to local host instead" )
+                self.ip_address = 'localhost'
+            except Exception as inst:
+                main.log.error( "Uncaught exception: " + str( inst ) )
+
+            self.handle = super(
+                ScapyCliDriver,
+                self ).connect(
+                user_name=self.user_name,
+                ip_address=self.ip_address,
+                port=None,
+                pwd=self.pwd )
+
+            if self.handle:
+                main.log.info( "Connection successful to the host " +
+                               self.user_name +
+                               "@" +
+                               self.ip_address )
+                return main.TRUE
+            else:
+                main.log.error( "Connection failed to the host " +
+                                self.user_name +
+                                "@" +
+                                self.ip_address )
+                main.log.error( "Failed to connect to the Mininet Host" )
+                return main.FALSE
+        except pexpect.EOF:
+            main.log.error( self.name + ": EOF exception found" )
+            main.log.error( self.name + ":     " + self.handle.before )
+            main.cleanup()
+            main.exit()
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
+            main.cleanup()
+            main.exit()
+
+    def disconnect( self ):
+        """
+        Called at the end of the test to stop the scapy component and
+        disconnect the handle.
+        """
+        self.handle.sendline( '' )
+        i = self.handle.expect( [ 'mininet>', pexpect.EOF, pexpect.TIMEOUT ],
+                                timeout=2 )
+        response = main.TRUE
+        if i == 0:
+            response = self.stopNet()
+        elif i == 1:
+            return main.TRUE
+        # print "Disconnecting Mininet"
+        if self.handle:
+            self.handle.sendline( "exit" )
+            self.handle.expect( "exit" )
+            self.handle.expect( "(.*)" )
+        else:
+            main.log.error( "Connection failed to the host" )
+        return response
+
+    def stopNet( self, fileName="", timeout=5 ):
+        """
+        Stops mininet.
+        Returns main.TRUE if the mininet successfully stops and
+                main.FALSE if the pexpect handle does not exist.
+
+        Will cleanup and exit the test if scapy fails to stop
+        """
+        main.log.info( self.name + ": Stopping scapy..." )
+        response = ''
+        if self.handle:
+            try:
+                self.handle.sendline( "" )
+                i = self.handle.expect( [ '>>>',
+                                          '\$',
+                                          pexpect.EOF,
+                                          pexpect.TIMEOUT ],
+                                        timeout )
+                if i == 0:
+                    main.log.info( "Exiting scapy..." )
+                response = self.execute(
+                    cmd="exit",
+                    prompt="(.*)",
+                    timeout=120 )
+                main.log.info( self.name + ": Stopped" )
+                response = main.TRUE
+
+                if i == 1:
+                    main.log.info( " Mininet trying to exit while not " +
+                                   "in the mininet prompt" )
+                elif i == 2:
+                    main.log.error( "Something went wrong exiting mininet" )
+                elif i == 3:  # timeout
+                    main.log.error( "Something went wrong exiting mininet " +
+                                    "TIMEOUT" )
+
+                if fileName:
+                    self.handle.sendline( "" )
+                    self.handle.expect( '\$' )
+                    self.handle.sendline(
+                        "sudo kill -9 \`ps -ef | grep \"" +
+                        fileName +
+                        "\" | grep -v grep | awk '{print $2}'\`" )
+            except pexpect.EOF:
+                main.log.error( self.name + ": EOF exception found" )
+                main.log.error( self.name + ":     " + self.handle.before )
+                main.cleanup()
+                main.exit()
+        else:
+            main.log.error( self.name + ": Connection failed to the host" )
+            response = main.FALSE
+        return response
+
+    def createHostComponent( self, name ):
+        """
+        Creates a new mininet cli component with the same parameters as self.
+        This new component is intended to be used to login to the hosts created
+        by mininet.
+
+        Arguments:
+            name - The string of the name of this component. The new component
+                   will be assigned to main.<name> .
+                   In addition, main.<name>.name = str( name )
+        """
+        try:
+            # look to see if this component already exists
+            getattr( main, name )
+        except AttributeError:
+            # namespace is clear, creating component
+            main.componentDictionary[name] = main.componentDictionary[self.name].copy()
+            main.componentDictionary[name]['connect_order'] = str( int( main.componentDictionary[name]['connect_order'] ) + 1 )
+            main.componentInit( name )
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
+            main.cleanup()
+            main.exit()
+        else:
+            # namespace is not clear!
+            main.log.error( name + " component already exists!" )
+            main.cleanup()
+            main.exit()
+
+    def removeHostComponent( self, name ):
+        """
+        Remove host component
+        Arguments:
+            name - The string of the name of the component to delete.
+        """
+        try:
+            # Get host component
+            component = getattr( main, name )
+        except AttributeError:
+            main.log.error( "Component " + name + " does not exist." )
+            return main.FALSE
+        try:
+            # Disconnect from component
+            component.disconnect()
+            # Delete component
+            delattr( main, name )
+            # Delete component from ComponentDictionary
+            del( main.componentDictionary[name] )
+            return main.TRUE
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
+            main.cleanup()
+            main.exit()
+
+    def startHostCli( self, host=None ):
+        """
+        Use the mininet m utility to connect to the host's cli
+        """
+        # These are fields that can be used by scapy packets. Initialized to None
+        self.hostIp = None
+        self.hostMac = None
+        try:
+            if not host:
+                host = self.name
+            self.handle.sendline( self.home + "/util/m " + host )
+            self.handle.expect( self.hostPrompt )
+            return main.TRUE
+        except pexpect.TIMEOUT:
+            main.log.exception( self.name + ": Command timed out" )
+            return main.FALSE
+        except pexpect.EOF:
+            main.log.exception( self.name + ": connection closed." )
+            main.cleanup()
+            main.exit()
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
+            main.cleanup()
+            main.exit()
+
+    def startScapy( self, mplsPath="" ):
+        """
+        Start the Scapy cli
+        optional:
+            mplsPath - The path where the MPLS class is located
+            NOTE: This can be a relative path from the user's home dir
+        """
+        mplsLines = ['import imp',
+            'imp.load_source( "mplsClass", "{}mplsClass.py" )'.format(mplsPath),
+            'from mplsClass import MPLS',
+            'bind_layers(Ether, MPLS, type = 0x8847)',
+            'bind_layers(MPLS, MPLS, bottom_of_label_stack = 0)',
+            'bind_layers(MPLS, IP)']
+
+        try:
+            self.handle.sendline( "scapy" )
+            self.handle.expect( self.scapyPrompt )
+            self.handle.sendline( "conf.color_theme = NoTheme()" )
+            self.handle.expect( self.scapyPrompt )
+            if mplsPath:
+                main.log.info( "Adding MPLS class" )
+                main.log.info( "MPLS class path: " + mplsPath )
+                for line in mplsLines:
+                    main.log.info( "sending line: " + line )
+                    self.handle.sendline( line )
+                    self.handle.expect( self.scapyPrompt )
+            return main.TRUE
+        except pexpect.TIMEOUT:
+            main.log.exception( self.name + ": Command timed out" )
+            return main.FALSE
+        except pexpect.EOF:
+            main.log.exception( self.name + ": connection closed." )
+            main.cleanup()
+            main.exit()
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
+            main.cleanup()
+            main.exit()
+
+    def stopScapy( self ):
+        """
+        Exit the Scapy cli
+        """
+        try:
+            self.handle.sendline( "exit()" )
+            self.handle.expect( self.hostPrompt )
+            return main.TRUE
+        except pexpect.TIMEOUT:
+            main.log.exception( self.name + ": Command timed out" )
+            return main.FALSE
+        except pexpect.EOF:
+            main.log.exception( self.name + ": connection closed." )
+            main.cleanup()
+            main.exit()
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
+            main.cleanup()
+            main.exit()
+
+    def buildEther( self, **kwargs ):
+        """
+        Build an Ethernet frame
+
+        Will create a frame class with the given options. If a field is
+        left blank it will default to the below value unless it is
+        overwritten by the next frame.
+        Default frame:
+        ###[ Ethernet ]###
+          dst= ff:ff:ff:ff:ff:ff
+          src= 00:00:00:00:00:00
+          type= 0x800
+
+        Returns main.TRUE or main.FALSE on error
+        """
+        try:
+            # Set the Ethernet frame
+            cmd = 'ether = Ether( '
+            options = []
+            for key, value in kwargs.iteritems():
+                if isinstance( value, str ):
+                    value = '"' + value + '"'
+                options.append( str( key ) + "=" + str( value ) )
+            cmd += ", ".join( options )
+            cmd += ' )'
+            self.handle.sendline( cmd )
+            self.handle.expect( self.scapyPrompt )
+            if "Traceback" in self.handle.before:
+                # KeyError, SyntaxError, ...
+                main.log.error( "Error in sending command: " + self.handle.before )
+                return main.FALSE
+            self.handle.sendline( "packet = ether" )
+            self.handle.expect( self.scapyPrompt )
+            if "Traceback" in self.handle.before:
+                # KeyError, SyntaxError, ...
+                main.log.error( "Error in sending command: " + self.handle.before )
+                return main.FALSE
+            return main.TRUE
+        except pexpect.TIMEOUT:
+            main.log.exception( self.name + ": Command timed out" )
+            return main.FALSE
+        except pexpect.EOF:
+            main.log.exception( self.name + ": connection closed." )
+            main.cleanup()
+            main.exit()
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
+            main.cleanup()
+            main.exit()
+
+    def buildIP( self, **kwargs ):
+        """
+        Build an IP frame
+
+        Will create a frame class with the given options. If a field is
+        left blank it will default to the below value unless it is
+        overwritten by the next frame.
+        Default frame:
+        ###[ IP ]###
+          version= 4
+          ihl= None
+          tos= 0x0
+          len= None
+          id= 1
+          flags=
+          frag= 0
+          ttl= 64
+          proto= hopopt
+          chksum= None
+          src= 127.0.0.1
+          dst= 127.0.0.1
+          \options\
+
+        Returns main.TRUE or main.FALSE on error
+        """
+        try:
+            # Set the IP frame
+            cmd = 'ip = IP( '
+            options = []
+            for key, value in kwargs.iteritems():
+                if isinstance( value, str ):
+                    value = '"' + value + '"'
+                options.append( str( key ) + "=" + str( value ) )
+            cmd += ", ".join( options )
+            cmd += ' )'
+            self.handle.sendline( cmd )
+            self.handle.expect( self.scapyPrompt )
+            if "Traceback" in self.handle.before:
+                # KeyError, SyntaxError, ...
+                main.log.error( "Error in sending command: " + self.handle.before )
+                return main.FALSE
+            self.handle.sendline( "packet = ether/ip" )
+            self.handle.expect( self.scapyPrompt )
+            if "Traceback" in self.handle.before:
+                # KeyError, SyntaxError, ...
+                main.log.error( "Error in sending command: " + self.handle.before )
+                return main.FALSE
+            return main.TRUE
+        except pexpect.TIMEOUT:
+            main.log.exception( self.name + ": Command timed out" )
+            return main.FALSE
+        except pexpect.EOF:
+            main.log.exception( self.name + ": connection closed." )
+            main.cleanup()
+            main.exit()
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
+            main.cleanup()
+            main.exit()
+
+    def buildIPv6( self, **kwargs ):
+        """
+        Build an IPv6 frame
+
+        Will create a frame class with the given options. If a field is
+        left blank it will default to the below value unless it is
+        overwritten by the next frame.
+        Default frame:
+        ###[ IPv6 ]###
+          version= 6
+          tc= 0
+          fl= 0
+          plen= None
+          nh= No Next Header
+          hlim= 64
+          src= ::1
+          dst= ::1
+
+        Returns main.TRUE or main.FALSE on error
+        """
+        try:
+            # Set the IPv6 frame
+            cmd = 'ipv6 = IPv6( '
+            options = []
+            for key, value in kwargs.iteritems():
+                if isinstance( value, str ):
+                    value = '"' + value + '"'
+                options.append( str( key ) + "=" + str( value ) )
+            cmd += ", ".join( options )
+            cmd += ' )'
+            self.handle.sendline( cmd )
+            self.handle.expect( self.scapyPrompt )
+            if "Traceback" in self.handle.before:
+                # KeyError, SyntaxError, ...
+                main.log.error( "Error in sending command: " + self.handle.before )
+                return main.FALSE
+            self.handle.sendline( "packet = ether/ipv6" )
+            self.handle.expect( self.scapyPrompt )
+            if "Traceback" in self.handle.before:
+                # KeyError, SyntaxError, ...
+                main.log.error( "Error in sending command: " + self.handle.before )
+                return main.FALSE
+            return main.TRUE
+        except pexpect.TIMEOUT:
+            main.log.exception( self.name + ": Command timed out" )
+            return main.FALSE
+        except pexpect.EOF:
+            main.log.exception( self.name + ": connection closed." )
+            main.cleanup()
+            main.exit()
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
+            main.cleanup()
+            main.exit()
+
+    def buildTCP( self, ipVersion=4, **kwargs ):
+        """
+        Build an TCP frame
+
+        Will create a frame class with the given options. If a field is
+        left blank it will default to the below value unless it is
+        overwritten by the next frame.
+
+        NOTE: Some arguments require quotes around them. It's up to you to
+        know which ones and to add them yourself. Arguments with an asterisk
+        do not need quotes.
+
+        Options:
+        ipVersion - Either 4 (default) or 6, indicates what Internet Protocol
+                    frame to use to encapsulate into
+        Default frame:
+        ###[ TCP ]###
+          sport= ftp_data *
+          dport= http *
+          seq= 0
+          ack= 0
+          dataofs= None
+          reserved= 0
+          flags= S
+          window= 8192
+          chksum= None
+          urgptr= 0
+          options= {}
+
+        Returns main.TRUE or main.FALSE on error
+        """
+        try:
+            # Set the TCP frame
+            cmd = 'tcp = TCP( '
+            options = []
+            for key, value in kwargs.iteritems():
+                options.append( str( key ) + "=" + str( value ) )
+            cmd += ", ".join( options )
+            cmd += ' )'
+            self.handle.sendline( cmd )
+            self.handle.expect( self.scapyPrompt )
+            if "Traceback" in self.handle.before:
+                # KeyError, SyntaxError, ...
+                main.log.error( "Error in sending command: " + self.handle.before )
+                return main.FALSE
+            if str( ipVersion ) is '4':
+                self.handle.sendline( "packet = ether/ip/tcp" )
+            elif str( ipVersion ) is '6':
+                self.handle.sendline( "packet = ether/ipv6/tcp" )
+            else:
+                main.log.error( "Unrecognized option for ipVersion, given " +
+                                repr( ipVersion ) )
+                return main.FALSE
+            self.handle.expect( self.scapyPrompt )
+            if "Traceback" in self.handle.before:
+                # KeyError, SyntaxError, ...
+                main.log.error( "Error in sending command: " + self.handle.before )
+                return main.FALSE
+            return main.TRUE
+        except pexpect.TIMEOUT:
+            main.log.exception( self.name + ": Command timed out" )
+            return main.FALSE
+        except pexpect.EOF:
+            main.log.exception( self.name + ": connection closed." )
+            main.cleanup()
+            main.exit()
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
+            main.cleanup()
+            main.exit()
+
+    def buildUDP( self, ipVersion=4, **kwargs ):
+        """
+        Build an UDP frame
+
+        Will create a frame class with the given options. If a field is
+        left blank it will default to the below value unless it is
+        overwritten by the next frame.
+
+        NOTE: Some arguments require quotes around them. It's up to you to
+        know which ones and to add them yourself. Arguments with an asterisk
+        do not need quotes.
+
+        Options:
+        ipVersion - Either 4 (default) or 6, indicates what Internet Protocol
+                    frame to use to encapsulate into
+        Default frame:
+        ###[ UDP ]###
+          sport= domain *
+          dport= domain *
+          len= None
+          chksum= None
+
+        Returns main.TRUE or main.FALSE on error
+        """
+        try:
+            # Set the UDP frame
+            cmd = 'udp = UDP( '
+            options = []
+            for key, value in kwargs.iteritems():
+                options.append( str( key ) + "=" + str( value ) )
+            cmd += ", ".join( options )
+            cmd += ' )'
+            self.handle.sendline( cmd )
+            self.handle.expect( self.scapyPrompt )
+            if "Traceback" in self.handle.before:
+                # KeyError, SyntaxError, ...
+                main.log.error( "Error in sending command: " + self.handle.before )
+                return main.FALSE
+            if str( ipVersion ) is '4':
+                self.handle.sendline( "packet = ether/ip/udp" )
+            elif str( ipVersion ) is '6':
+                self.handle.sendline( "packet = ether/ipv6/udp" )
+            else:
+                main.log.error( "Unrecognized option for ipVersion, given " +
+                                repr( ipVersion ) )
+                return main.FALSE
+            self.handle.expect( self.scapyPrompt )
+            if "Traceback" in self.handle.before:
+                # KeyError, SyntaxError, ...
+                main.log.error( "Error in sending command: " + self.handle.before )
+                return main.FALSE
+            return main.TRUE
+        except pexpect.TIMEOUT:
+            main.log.exception( self.name + ": Command timed out" )
+            return main.FALSE
+        except pexpect.EOF:
+            main.log.exception( self.name + ": connection closed." )
+            main.cleanup()
+            main.exit()
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
+            main.cleanup()
+            main.exit()
+
+    def buildICMP( self, **kwargs ):
+        """
+        Build an ICMP frame
+
+        Will create a frame class with the given options. If a field is
+        left blank it will default to the below value unless it is
+        overwritten by the next frame.
+        Default frame:
+        ###[ ICMP ]###
+          type= echo-request
+          code= 0
+          chksum= None
+          id= 0x0
+          seq= 0x0
+
+        Returns main.TRUE or main.FALSE on error
+        """
+        try:
+            # Set the ICMP frame
+            cmd = 'icmp = ICMP( '
+            options = []
+            for key, value in kwargs.iteritems():
+                if isinstance( value, str ):
+                    value = '"' + value + '"'
+                options.append( str( key ) + "=" + str( value ) )
+            cmd += ", ".join( options )
+            cmd += ' )'
+            self.handle.sendline( cmd )
+            self.handle.expect( self.scapyPrompt )
+            if "Traceback" in self.handle.before:
+                # KeyError, SyntaxError, ...
+                main.log.error( "Error in sending command: " + self.handle.before )
+                return main.FALSE
+            self.handle.sendline( "packet = ether/ip/icmp" )
+            self.handle.expect( self.scapyPrompt )
+            if "Traceback" in self.handle.before:
+                # KeyError, SyntaxError, ...
+                main.log.error( "Error in sending command: " + self.handle.before )
+                return main.FALSE
+            return main.TRUE
+        except pexpect.TIMEOUT:
+            main.log.exception( self.name + ": Command timed out" )
+            return main.FALSE
+        except pexpect.EOF:
+            main.log.exception( self.name + ": connection closed." )
+            main.cleanup()
+            main.exit()
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
+            main.cleanup()
+            main.exit()
+
+    def sendPacket( self, iface=None, packet=None, timeout=1 ):
+        """
+        Send a packet with either the given scapy packet command, or use the
+        packet saved in the variable 'packet'.
+
+        Examples of a valid string for packet:
+
+        Simple IP packet
+        packet='Ether(dst="a6:d9:26:df:1d:4b")/IP(dst="10.0.0.2")'
+
+        A Ping with two vlan tags
+        packet='Ether(dst='ff:ff:ff:ff:ff:ff')/Dot1Q(vlan=1)/Dot1Q(vlan=10)/
+                IP(dst='255.255.255.255', src='192.168.0.1')/ICMP()'
+
+        Returns main.TRUE or main.FALSE on error
+        """
+        try:
+            # TODO: add all params, or use kwargs
+            sendCmd = 'srp( '
+            if packet:
+                sendCmd += packet
+            else:
+                sendCmd += "packet"
+            if iface:
+                sendCmd += ", iface='{}'".format( iface )
+
+            sendCmd += ', timeout=' + str( timeout ) + ')'
+            self.handle.sendline( sendCmd )
+            self.handle.expect( self.scapyPrompt )
+            if "Traceback" in self.handle.before:
+                # KeyError, SyntaxError, ...
+                main.log.error( "Error in sending command: " + self.handle.before )
+                return main.FALSE
+            # TODO: Check # of packets sent?
+            return main.TRUE
+        except pexpect.TIMEOUT:
+            main.log.exception( self.name + ": Command timed out" )
+            return main.FALSE
+        except pexpect.EOF:
+            main.log.exception( self.name + ": connection closed." )
+            main.cleanup()
+            main.exit()
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
+            main.cleanup()
+            main.exit()
+
+    def startFilter( self, ifaceName=None, sniffCount=1, pktFilter="ip" ):
+        """
+        Listen for packets using the given filters
+
+        Options:
+        ifaceName - the name of the interface to listen on. If none is given,
+                    defaults to <host name>-eth0
+        pktFilter - A string in Berkeley Packet Filter (BPF) format which
+                    specifies which packets to sniff
+        sniffCount - The number of matching packets to capture before returning
+
+        Returns main.TRUE or main.FALSE on error
+        """
+        try:
+            # TODO: add all params, or use kwargs
+            ifaceName = str( ifaceName ) if ifaceName else self.name + "-eth0"
+            # Set interface
+            self.handle.sendline( ' conf.iface = "' + ifaceName + '"' )
+            self.handle.expect( self.scapyPrompt )
+            cmd = 'pkt = sniff(count = ' + str( sniffCount ) +\
+                  ', filter = "' + str( pktFilter ) + '")'
+            print self.name + ' > ' + cmd
+            self.handle.sendline( cmd )
+            self.handle.expect( '"\)\r\n' )
+            # TODO: parse this?
+            return main.TRUE
+        except pexpect.TIMEOUT:
+            main.log.exception( self.name + ": Command timed out" )
+            return main.FALSE
+        except pexpect.EOF:
+            main.log.exception( self.name + ": connection closed." )
+            main.cleanup()
+            main.exit()
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
+            main.cleanup()
+            main.exit()
+
+    def checkFilter( self, timeout=10 ):
+        """
+        Check that a filter returned and returns the reponse
+        """
+        try:
+            i = self.handle.expect( [ self.scapyPrompt, pexpect.TIMEOUT ], timeout=timeout )
+            if i == 0:
+                return main.TRUE
+            else:
+                return main.FALSE
+        except pexpect.EOF:
+            main.log.exception( self.name + ": connection closed." )
+            main.cleanup()
+            main.exit()
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
+            main.cleanup()
+            main.exit()
+
+    def killFilter( self ):
+        """
+        Kill a scapy filter
+        """
+        try:
+            self.handle.send( "\x03" )  # Send a ctrl-c to kill the filter
+            self.handle.expect( self.scapyPrompt )
+            return self.handle.before
+        except pexpect.TIMEOUT:
+            main.log.exception( self.name + ": Command timed out" )
+            return None
+        except pexpect.EOF:
+            main.log.exception( self.name + ": connection closed." )
+            main.cleanup()
+            main.exit()
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
+            main.cleanup()
+            main.exit()
+
+    def readPackets( self ):
+        """
+        Read all the packets captured by the previous filter
+        """
+        try:
+            self.handle.sendline( "for p in pkt: p \n")
+            self.handle.expect( "for p in pkt: p \r\n... \r\n" )
+            self.handle.expect( self.scapyPrompt )
+        except pexpect.TIMEOUT:
+            main.log.exception( self.name + ": Command timed out" )
+            return None
+        except pexpect.EOF:
+            main.log.exception( self.name + ": connection closed." )
+            main.cleanup()
+            main.exit()
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
+            main.cleanup()
+            main.exit()
+        return self.handle.before
+
+    def updateSelf( self ):
+        """
+        Updates local MAC and IP fields
+        """
+        self.hostMac = self.getMac()
+        self.hostIp = self.getIp()
+
+    def getMac( self, ifaceName=None ):
+        """
+        Save host's MAC address
+        """
+        try:
+            ifaceName = str( ifaceName ) if ifaceName else self.name + "-eth0"
+            cmd = 'get_if_hwaddr("' + str( ifaceName ) + '")'
+            self.handle.sendline( cmd )
+            self.handle.expect( self.scapyPrompt )
+            pattern = r'(([0-9a-f]{2}[:-]){5}([0-9a-f]{2}))'
+            match = re.search( pattern, self.handle.before )
+            if match:
+                return match.group()
+            else:
+                # the command will have an exception if iface doesn't exist
+                return None
+        except pexpect.TIMEOUT:
+            main.log.exception( self.name + ": Command timed out" )
+            return None
+        except pexpect.EOF:
+            main.log.exception( self.name + ": connection closed." )
+            main.cleanup()
+            main.exit()
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
+            main.cleanup()
+            main.exit()
+
+    def getIp( self, ifaceName=None ):
+        """
+        Save host's IP address
+
+        Returns the IP of the first interface that is not a loopback device.
+        If no IP could be found then it will return 0.0.0.0.
+        """
+        def getIPofInterface( ifaceName ):
+            cmd = 'get_if_addr("' + str( ifaceName ) + '")'
+            self.handle.sendline( cmd )
+            self.handle.expect( self.scapyPrompt )
+
+            pattern = r'(((2[0-5]|1[0-9]|[0-9])?[0-9]\.){3}((2[0-5]|1[0-9]|[0-9])?[0-9]))'
+            match = re.search( pattern, self.handle.before )
+            if match:
+                # NOTE: The command will return 0.0.0.0 if the iface doesn't exist
+                if match.group() == '0.0.0.0':
+                    main.log.warn( 'iface {0} has no IPv4 address'.format( ifaceName ) )
+                return match.group()
+            else:
+                return None
+        try:
+            if not ifaceName:
+                # Get list of interfaces
+                ifList = self.getIfList()
+                for ifaceName in ifList:
+                    if ifaceName == "lo":
+                        continue
+                    ip = getIPofInterface( ifaceName )
+                    if ip != "0.0.0.0":
+                        return ip
+                return "0.0.0.0"
+            else:
+                return getIPofInterface( ifaceName )
+
+        except pexpect.TIMEOUT:
+            main.log.exception( self.name + ": Command timed out" )
+            return None
+        except pexpect.EOF:
+            main.log.exception( self.name + ": connection closed." )
+            main.cleanup()
+            main.exit()
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
+            main.cleanup()
+            main.exit()
+
+    def getIfList( self ):
+        """
+        Return List of Interfaces
+        """
+        try:
+            self.handle.sendline( 'get_if_list()' )
+            self.handle.expect( self.scapyPrompt )
+            ifList = self.handle.before.split( '\r\n' )
+            ifList = ifList[ 1 ].replace( "'","" )[ 1:-1 ].split( ', ' )
+            return ifList
+
+        except pexpect.TIMEOUT:
+            main.log.exception( self.name + ": Command timed out" )
+            return None
+        except pexpect.EOF:
+            main.log.exception( self.name + ": connection closed." )
+            main.cleanup()
+            main.exit()
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
+            main.cleanup()
+            main.exit()
+
+if __name__ != "__main__":
+    sys.modules[ __name__ ] = ScapyCliDriver()
diff --git a/TestON/tests/FUNCintent/Dependency/FuncIntentFunction.py b/TestON/tests/FUNCintent/Dependency/FuncIntentFunction.py
index 9efe5d0..067ed3e 100644
--- a/TestON/tests/FUNCintent/Dependency/FuncIntentFunction.py
+++ b/TestON/tests/FUNCintent/Dependency/FuncIntentFunction.py
@@ -10,324 +10,308 @@
 def __init__( self ):
     self.default = ''
 
-def hostIntent( main,
-                name,
-                host1,
-                host2,
-                onosNode=0,
-                host1Id="",
-                host2Id="",
-                mac1="",
-                mac2="",
-                vlan1="-1",
-                vlan2="-1",
-                sw1="",
-                sw2="",
-                expectedLink=0 ):
+def installHostIntent( main,
+                                name,
+                                host1,
+                                host2,
+                                onosNode=0,
+                                ethType="",
+                                bandwidth="",
+                                lambdaAlloc=False,
+                                ipProto="",
+                                ipAddresses="",
+                                tcp="",
+                                sw1="",
+                                sw2=""):
     """
+    Installs a Host Intent
+
     Description:
-        Verify add-host-intent
+        Install a host intent using
+        add-host-intent
+
     Steps:
-        - Discover hosts
-        - Add host intents
-        - Check intents
-        - Verify flows
-        - Ping hosts
-        - Reroute
-            - Link down
-            - Verify flows
-            - Check topology
-            - Ping hosts
-            - Link up
-            - Verify flows
-            - Check topology
-            - Ping hosts
-        - Remove intents
-    Required:
-        name - Type of host intent to add eg. IPV4 | VLAN | Dualstack
-        host1 - Name of first host
-        host2 - Name of second host
-    Optional:
-        onosNode - ONOS node to install the intents in main.CLIs[ ]
-                   0 by default so that it will always use the first
-                   ONOS node
-        host1Id - ONOS id of the first host eg. 00:00:00:00:00:01/-1
-        host2Id - ONOS id of the second host
-        mac1 - Mac address of first host
-        mac2 - Mac address of the second host
-        vlan1 - Vlan tag of first host, defaults to -1
-        vlan2 - Vlan tag of second host, defaults to -1
-        sw1 - First switch to bring down & up for rerouting purpose
-        sw2 - Second switch to bring down & up for rerouting purpose
-        expectedLink - Expected link when the switches are down, it should
-                       be two links lower than the links before the two
-                       switches are down
-    Return:
-        Returns main.TRUE if all verification passed, otherwise return
-        main.FALSE; returns main.FALSE if there is a key error
-    """
-
-    # Assert variables
-    assert main, "There is no main variable"
-    assert name, "variable name is empty"
-    assert host1 and host2, "You must specify hosts"
-
-    global itemName
-    itemName = name
-    h1Id = host1Id
-    h2Id = host2Id
-    h1Mac = mac1
-    h2Mac = mac2
-    vlan1 = vlan1
-    vlan2 = vlan2
-    hostNames = [ host1 , host2 ]
-    intentsId = []
-    stepResult = main.TRUE
-    pingResult = main.TRUE
-    intentResult = main.TRUE
-    removeIntentResult = main.TRUE
-    flowResult = main.TRUE
-    topoResult = main.TRUE
-    linkDownResult = main.TRUE
-    linkUpResult = main.TRUE
-    onosNode = int( onosNode )
-
-    try:
-        if main.hostsData:
-            if not h1Mac:
-                h1Mac = main.hostsData[ host1 ][ 'mac' ]
-            if not h2Mac:
-                h2Mac = main.hostsData[ host2 ][ 'mac' ]
-            if main.hostsData[ host1 ].get( 'vlan' ):
-                vlan1 = main.hostsData[ host1 ][ 'vlan' ]
-            if main.hostsData[ host1 ].get( 'vlan' ):
-                vlan2 = main.hostsData[ host2 ][ 'vlan' ]
-            if not h1Id:
-                h1Id = main.hostsData[ host1 ][ 'id' ]
-            if not h2Id:
-                h2Id = main.hostsData[ host2 ][ 'id' ]
-
-        assert h1Id and h2Id, "You must specify host IDs"
-        if not ( h1Id and h2Id ):
-            main.log.info( "There are no host IDs" )
-            return main.FALSE
-
-    except KeyError:
-        main.log.error( itemName + ": Key error Exception" )
-        return main.FALSE
-
-    # Discover hosts using arping incase pingall discovery failed
-    main.log.info( itemName + ": Discover host using arping" )
-    main.Mininet1.arping( srcHost=host1, dstHost=host2 )
-    main.Mininet1.arping( srcHost=host2, dstHost=host1 )
-    host1 = main.CLIs[ 0 ].getHost( mac=h1Mac )
-    host2 = main.CLIs[ 0 ].getHost( mac=h2Mac )
-
-    # Check flows count in each node
-    checkFlowsCount( main )
-
-    # Adding host intents
-    main.log.info( itemName + ": Adding host intents" )
-    intent1 = main.CLIs[ onosNode ].addHostIntent( hostIdOne=h1Id,
-                                                   hostIdTwo=h2Id )
-    intentsId.append( intent1 )
-
-    # Check intents state
-    time.sleep( main.checkIntentSleep )
-    intentResult = checkIntentState( main, intentsId )
-    checkFlowsCount( main )
-
-    # Check intents state again if first check fails...
-    if not intentResult:
-        intentResult = checkIntentState( main, intentsId )
-
-    # Check flows count in each node
-    checkFlowsCount( main )
-    # Verify flows
-    checkFlowsState( main )
-
-    # Ping hosts
-    firstPingResult = pingallHosts( main, hostNames )
-    if not firstPingResult:
-        main.log.debug( "First ping failed, there must be" +
-                       " something wrong with ONOS performance" )
-
-    # Ping hosts again...
-    pingTemp = pingallHosts( main, hostNames )
-    pingResult = pingResult and pingTemp
-    if pingTemp:
-        main.assertReturnString += 'Initial Pingall Passed\n'
-    else:
-        main.assertReturnString += 'Initial Pingall Failed\n'
-
-    # Test rerouting if these variables exist
-    if sw1 and sw2 and expectedLink:
-        # Link down
-        linkDownResult = link( main, sw1, sw2, "down" )
-
-        if linkDownResult:
-            main.assertReturnString += 'Link Down Passed\n'
-        else:
-            main.assertReturnString += 'Link Down Failed\n'
-
-        # Check flows count in each node
-        checkFlowsCount( main )
-        # Verify flows
-        checkFlowsState( main )
-
-        # Check OnosTopology
-        topoResult = checkTopology( main, expectedLink )
-        if topoResult:
-            main.assertReturnString += 'Link Down Topology State Passed\n'
-        else:
-            main.assertReturnString += 'Link Down Topology State Failed\n'
-
-        # Ping hosts
-        pingTemp = pingallHosts( main, hostNames )
-        pingResult = pingResult and pingTemp
-
-        if pingTemp:
-            main.assertReturnString += 'Link Down Pingall Passed\n'
-        else:
-            main.assertReturnString += 'Link Down Pingall Failed\n'
-
-        # Check intent states
-        intentTemp = checkIntentState( main, intentsId )
-        intentResult = intentResult and intentTemp
-        if intentTemp:
-            main.assertReturnString += 'Link Down Intent State Passed\n'
-        else:
-            main.assertReturnString += 'Link Down Intent State Failed\n'
-
-        # Checks ONOS state in link down
-        if linkDownResult and topoResult and pingResult and intentResult:
-            main.log.info( itemName + ": Successfully brought link down" )
-        else:
-            main.log.error( itemName + ": Failed to bring link down" )
-
-        # Link up
-        linkUpResult = link( main, sw1, sw2, "up" )
-        time.sleep( main.rerouteSleep )
-
-        if linkUpResult:
-            main.assertReturnString += 'Link Up Passed\n'
-        else:
-            main.assertReturnString += 'Link Up Failed\n'
-
-        # Check flows count in each node
-        checkFlowsCount( main )
-        # Verify flows
-        checkFlowsState( main )
-
-        # Check OnosTopology
-        topoResult = checkTopology( main, main.numLinks )
-
-        if topoResult:
-            main.assertReturnString += 'Link Up Topology State Passed\n'
-        else:
-            main.assertReturnString += 'Link Up Topology State Failed\n'
-
-        # Ping hosts
-        pingTemp = pingallHosts( main, hostNames )
-        pingResult = pingResult and pingTemp
-
-        if pingTemp:
-            main.assertReturnString += 'Link Up Pingall Passed\n'
-        else:
-            main.assertReturnString += 'Link Up Pingall Failed\n'
-
-        intentTemp = checkIntentState( main, intentsId )
-        intentResult = intentResult and intentTemp
-        if intentTemp:
-            main.assertReturnString += 'Link Up Intent State Passed\n'
-        else:
-            main.assertReturnString += 'Link Up Intent State Failed\n'
-
-        # Checks ONOS state in link up
-        if linkUpResult and topoResult and pingResult and intentResult:
-            main.log.info( itemName + ": Successfully brought link back up" )
-        else:
-            main.log.error( itemName + ": Failed to bring link back up" )
-
-    # Remove all intents
-    removeIntentResult = removeAllIntents( main, intentsId )
-
-    if removeIntentResult:
-        main.assertReturnString += 'Remove Intents Passed'
-    else:
-        main.assertReturnString += 'Remove Intents Failed'
-
-    stepResult = pingResult and linkDownResult and linkUpResult \
-                 and intentResult and removeIntentResult
-
-    return stepResult
-
-def pointIntent( main,
-                 name,
-                 host1,
-                 host2,
-                 onosNode=0,
-                 deviceId1="",
-                 deviceId2="",
-                 port1="",
-                 port2="",
-                 ethType="",
-                 mac1="",
-                 mac2="",
-                 bandwidth="",
-                 lambdaAlloc=False,
-                 ipProto="",
-                 ip1="",
-                 ip2="",
-                 tcp1="",
-                 tcp2="",
-                 sw1="",
-                 sw2="",
-                 expectedLink=0 ):
-
-    """
-    Description:
-        Verify add-point-intent
-    Steps:
-        - Get device ids | ports
-        - Add point intents
-        - Check intents
-        - Verify flows
-        - Ping hosts
-        - Reroute
-            - Link down
-            - Verify flows
-            - Check topology
-            - Ping hosts
-            - Link up
-            - Verify flows
-            - Check topology
-            - Ping hosts
-        - Remove intents
+        - Fetch host data if not given
+        - Add host intent
+            - Ingress device is the first sender host
+            - Egress devices are the recipient devices
+            - Ports if defined in senders or recipients
+            - MAC address ethSrc loaded from Ingress device
+        - Check intent state with retry
     Required:
         name - Type of point intent to add eg. IPV4 | VLAN | Dualstack
-        host1 - Name of first host
-        host2 - Name of second host
+        host1 - Dictionary for host1
+            { "name":"h8", "id":"of:0000000000000005/8" }
+        host2 - Dictionary for host2
+            { "name":"h16", "id":"of:0000000000000006/8" }
     Optional:
         onosNode - ONOS node to install the intents in main.CLIs[ ]
                    0 by default so that it will always use the first
                    ONOS node
-        deviceId1 - ONOS device id of the first switch, the same as the
-                    location of the first host eg. of:0000000000000001/1,
-                    located at device 1 port 1
-        deviceId2 - ONOS device id of the second switch
-        port1 - The port number where the first host is attached
-        port2 - The port number where the second host is attached
         ethType - Ethernet type eg. IPV4, IPV6
-        mac1 - Mac address of first host
-        mac2 - Mac address of the second host
         bandwidth - Bandwidth capacity
         lambdaAlloc - Allocate lambda, defaults to False
         ipProto - IP protocol
-        ip1 - IP address of first host
-        ip2 - IP address of second host
-        tcp1 - TCP port of first host
-        tcp2 - TCP port of second host
+        tcp - TCP ports in the same order as the hosts in hostNames
+    """
+
+    assert main, "There is no main variable"
+    assert host1, "You must specify host1"
+    assert host2, "You must specify host2"
+
+    global itemName  # The name of this run. Used for logs.
+    itemName = name
+    onosNode = int( onosNode )
+
+    main.log.info( itemName + ": Adding single point to multi point intents" )
+
+    if not host1.get( "id" ):
+        main.log.warn( "ID not given for host1 {0}. Loading from main.hostData".format( host1.get( "name" ) ) )
+        main.log.debug( main.hostsData.get( host1.get( "name" ) ) )
+        host1[ "id" ] = main.hostsData.get( host1.get( "name" ) ).get( "id" )
+
+    if not host2.get( "id" ):
+        main.log.warn( "ID not given for host2 {0}. Loading from main.h ostData".format( host2.get( "name" ) ) )
+        host2[ "id" ] = main.hostsData.get( host2.get( "name" ) ).get( "id" )
+
+    # Adding point intent
+    intentId = main.CLIs[ onosNode ].addHostIntent( hostIdOne=host1.get( "id" ),
+                                                    hostIdTwo=host2.get( "id" ) )
+
+    # Check intents state
+    if utilities.retry( f=checkIntentState, retValue=main.FALSE,
+                        args=( main, [ intentId ] ), sleep=main.checkIntentSleep ):
+        return intentId
+    else:
+        main.log.error( "Single to Multi Intent did not install correctly" )
+        return main.FALSE
+
+def testHostIntent( main,
+                    name,
+                    intentId,
+                    host1,
+                    host2,
+                    onosNode=0,
+                    sw1="s5",
+                    sw2="s2",
+                    expectedLink=0):
+    """
+    Test a Host Intent
+
+    Description:
+        Test a host intent of given ID between given hosts
+
+    Steps:
+        - Fetch host data if not given
+        - Check Intent State
+        - Check Flow State
+        - Check Connectivity
+        - Check Lack of Connectivity Between Hosts not in the Intent
+        - Reroute
+            - Take Expected Link Down
+            - Check Intent State
+            - Check Flow State
+            - Check Topology
+            - Check Connectivity
+            - Bring Expected Link Up
+            - Check Intent State
+            - Check Flow State
+            - Check Topology
+            - Check Connectivity
+        - Remove Topology
+
+    Required:
+        name - Type of point intent to add eg. IPV4 | VLAN | Dualstack
+        intentId - intent ID to be tested ( and removed )
+        host1 - Dictionary for host1
+            { "name":"h8", "id":"of:0000000000000005/8" }
+        host2 - Dictionary for host2
+            { "name":"h16", "id":"of:0000000000000006/8" }
+    Optional:
+        onosNode - ONOS node to install the intents in main.CLIs[ ]
+                   0 by default so that it will always use the first
+                   ONOS node
+        sw1 - First switch to bring down & up for rerouting purpose
+        sw2 - Second switch to bring down & up for rerouting purpose
+        expectedLink - Expected link when the switches are down, it should
+                       be two links lower than the links before the two
+                       switches are down
+
+    """
+
+    # Parameter Validity Check
+    assert main, "There is no main variable"
+    assert host1, "You must specify host1"
+    assert host2, "You must specify host2"
+
+    global itemName
+    itemName = name
+    tempHostsData = {}
+    onosNode = int( onosNode )
+
+    main.log.info( itemName + ": Testing Single to Multi Point Intent" )
+
+    if not host1.get( "id" ):
+        main.log.warn( "Id not given for host1 {0}. Loading from main.hostData".format( host1.get( "name" ) ) )
+        host1[ "id" ] = main.hostsData.get( host1.get( "name" ) ).get( "location" )
+
+    if not host2.get( "id" ):
+        main.log.warn( "Id not given for host2 {0}. Loading from main.hostData".format( host2.get( "name" ) ) )
+        host2[ "id" ] = main.hostsData.get( host2.get( "name" ) ).get( "location" )
+
+    senderNames = [ host1.get( "name" ), host2.get( "name" ) ]
+    recipientNames = [ host1.get( "name" ), host2.get( "name" ) ]
+
+    testResult = main.TRUE
+    main.log.info( itemName + ": Adding single point to multi point intents" )
+
+    # Check intent state
+    if utilities.retry( f=checkIntentState, retValue=main.FALSE, args=( main, [ intentId ] ), sleep=main.checkIntentSleep ):
+        main.assertReturnString += 'Initial Intent State Passed\n'
+    else:
+        main.assertReturnString += 'Initial Intent State Failed\n'
+        testResult = main.FALSE
+
+    # Check flows count in each node
+    if utilities.retry( f=checkFlowsCount, retValue=main.FALSE, args=[ main ] ) and utilities.retry( f=checkFlowsState, retValue=main.FALSE, args=[ main ] ):
+        main.assertReturnString += 'Initial Flow State Passed\n'
+    else:
+        main.assertReturnString += 'Intial Flow State Failed\n'
+        testResult = main.FALSE
+
+    # Check Connectivity
+    if utilities.retry( f=scapyCheckConnection, retValue=main.FALSE, args=( main, senderNames, recipientNames ) ):
+        main.assertReturnString += 'Initial Ping Passed\n'
+    else:
+        main.assertReturnString += 'Initial Ping Failed\n'
+        testResult = main.FALSE
+
+    # Test rerouting if these variables exist
+    if sw1 and sw2 and expectedLink:
+        # Take link down
+        if utilities.retry( f=link, retValue=main.FALSE, args=( main, sw1, sw2, "down" ) ):
+            main.assertReturnString += 'Link Down Passed\n'
+        else:
+            main.assertReturnString += 'Link Down Failed\n'
+            testResult = main.FALSE
+
+        # Check intent state
+        if utilities.retry( f=checkIntentState, retValue=main.FALSE, args=( main, [ intentId ] ), sleep=main.checkIntentSleep ):
+            main.assertReturnString += 'Link Down Intent State Passed\n'
+        else:
+            main.assertReturnString += 'Link Down Intent State Failed\n'
+            testResult = main.FALSE
+
+        # Check flows count in each node
+        if utilities.retry( f=checkFlowsCount, retValue=main.FALSE, args=[ main ] ) and utilities.retry( f=checkFlowsState, retValue=main.FALSE, args=[ main ] ):
+            main.assertReturnString += 'Link Down Flow State Passed\n'
+        else:
+            main.assertReturnString += 'Link Down Flow State Failed\n'
+            testResult = main.FALSE
+
+        # Check OnosTopology
+        if utilities.retry( f=checkTopology, retValue=main.FALSE, args=( main, expectedLink ) ):
+            main.assertReturnString += 'Link Down Topology State Passed\n'
+        else:
+            main.assertReturnString += 'Link Down Topology State Failed\n'
+            testResult = main.FALSE
+
+        # Check Connection
+        if utilities.retry( f=scapyCheckConnection, retValue=main.FALSE, args=( main, senderNames, recipientNames ) ):
+            main.assertReturnString += 'Link Down Pingall Passed\n'
+        else:
+            main.assertReturnString += 'Link Down Pingall Failed\n'
+            testResult = main.FALSE
+
+        # Bring link up
+        if utilities.retry( f=link, retValue=main.FALSE, args=( main, sw1, sw2, "up" ) ):
+            main.assertReturnString += 'Link Up Passed\n'
+        else:
+            main.assertReturnString += 'Link Up Failed\n'
+            testResult = main.FALSE
+
+        # Wait for reroute
+        time.sleep( main.rerouteSleep )
+
+        # Check Intents
+        if utilities.retry( f=checkIntentState, retValue=main.FALSE, args=( main, [ intentId ] ), sleep=main.checkIntentSleep ):
+            main.assertReturnString += 'Link Up Intent State Passed\n'
+        else:
+            main.assertReturnString += 'Link Up Intent State Failed\n'
+            testResult = main.FALSE
+
+        # Check flows count in each node
+        if utilities.retry( f=checkFlowsCount, retValue=main.FALSE, args=[ main ] ) and utilities.retry( f=checkFlowsState, retValue=main.FALSE, args=[ main ] ):
+            main.assertReturnString += 'Link Up Flow State Passed\n'
+        else:
+            main.assertReturnString += 'Link Up Flow State Failed\n'
+            testResult = main.FALSE
+
+        # Check OnosTopology
+        if utilities.retry( f=checkTopology, retValue=main.FALSE, args=( main, main.numLinks ) ):
+            main.assertReturnString += 'Link Up Topology State Passed\n'
+        else:
+            main.assertReturnString += 'Link Up Topology State Failed\n'
+            testResult = main.FALSE
+
+        # Check Connection
+        if utilities.retry( f=scapyCheckConnection, retValue=main.FALSE, args=( main, senderNames, recipientNames ) ):
+            main.assertReturnString += 'Link Up Pingall Passed\n'
+        else:
+            main.assertReturnString += 'Link Up Pingall Failed\n'
+            testResult = main.FALSE
+
+    # Remove all intents
+    if utilities.retry( f=removeAllIntents, retValue=main.FALSE, args=( main, [ intentId ] ) ):
+        main.assertReturnString += 'Remove Intents Passed'
+    else:
+        main.assertReturnString += 'Remove Intents Failed'
+        testResult = main.FALSE
+
+    return testResult
+
+def installPointIntent( main,
+                        name,
+                        senders,
+                        recipients,
+                        onosNode=0,
+                        ethType="",
+                        bandwidth="",
+                        lambdaAlloc=False,
+                        ipProto="",
+                        ipSrc="",
+                        ipDst="",
+                        tcpSrc="",
+                        tcpDst=""):
+    """
+    Installs a Single to Single Point Intent
+
+    Description:
+        Install a single to single point intent
+
+    Steps:
+        - Fetch host data if not given
+        - Add point intent
+            - Ingress device is the first sender device
+            - Egress device is the first recipient device
+            - Ports if defined in senders or recipients
+            - MAC address ethSrc loaded from Ingress device
+        - Check intent state with retry
+    Required:
+        name - Type of point intent to add eg. IPV4 | VLAN | Dualstack
+        senders - List of host dictionaries i.e.
+            [ { "name":"h8", "device":"of:0000000000000005/8","mac":"00:00:00:00:00:08" } ]
+        recipients - List of host dictionaries i.e.
+            [ { "name":"h16", "device":"of:0000000000000006/8", "mac":"00:00:00:00:00:10" } ]
+    Optional:
+        onosNode - ONOS node to install the intents in main.CLIs[ ]
+                   0 by default so that it will always use the first
+                   ONOS node
+        ethType - Ethernet type eg. IPV4, IPV6
+        bandwidth - Bandwidth capacity
+        lambdaAlloc - Allocate lambda, defaults to False
+        ipProto - IP protocol
+        tcp - TCP ports in the same order as the hosts in hostNames
         sw1 - First switch to bring down & up for rerouting purpose
         sw2 - Second switch to bring down & up for rerouting purpose
         expectedLink - Expected link when the switches are down, it should
@@ -336,180 +320,60 @@
     """
 
     assert main, "There is no main variable"
-    assert name, "variable name is empty"
-    assert host1 and host2, "You must specify hosts"
+    assert senders, "You must specify a sender"
+    assert recipients, "You must specify a recipient"
+    # Assert devices or main.hostsData, "You must specify devices"
 
-    global itemName
+    global itemName  # The name of this run. Used for logs.
     itemName = name
-    host1 = host1
-    host2 = host2
-    hostNames = [ host1, host2 ]
-    intentsId = []
-
-    pingResult = main.TRUE
-    intentResult = main.TRUE
-    removeIntentResult = main.TRUE
-    flowResult = main.TRUE
-    topoResult = main.TRUE
-    linkDownResult = main.TRUE
-    linkUpResult = main.TRUE
     onosNode = int( onosNode )
 
-    # Adding bidirectional point  intents
-    main.log.info( itemName + ": Adding point intents" )
-    intent1 = main.CLIs[ onosNode ].addPointIntent( ingressDevice=deviceId1,
-                                             egressDevice=deviceId2,
-                                             portIngress=port1,
-                                             portEgress=port2,
-                                             ethType=ethType,
-                                             ethSrc=mac1,
-                                             ethDst=mac2,
-                                             bandwidth=bandwidth,
-                                             lambdaAlloc=lambdaAlloc,
-                                             ipProto=ipProto,
-                                             ipSrc=ip1,
-                                             ipDst=ip2,
-                                             tcpSrc=tcp1,
-                                             tcpDst=tcp2 )
+    main.log.info( itemName + ": Adding mutli to single point intents" )
 
-    intentsId.append( intent1 )
-    intent2 = main.CLIs[ onosNode ].addPointIntent( ingressDevice=deviceId2,
-                                             egressDevice=deviceId1,
-                                             portIngress=port2,
-                                             portEgress=port1,
-                                             ethType=ethType,
-                                             ethSrc=mac2,
-                                             ethDst=mac1,
-                                             bandwidth=bandwidth,
-                                             lambdaAlloc=lambdaAlloc,
-                                             ipProto=ipProto,
-                                             ipSrc=ip2,
-                                             ipDst=ip1,
-                                             tcpSrc=tcp2,
-                                             tcpDst=tcp1 )
-    intentsId.append( intent2 )
+    for sender in senders:
+        if not sender.get( "device" ):
+            main.log.warn( "Device not given for sender {0}. Loading from main.hostData".format( sender.get( "name" ) ) )
+            sender[ "device" ] = main.hostsData.get( sender.get( "name" ) ).get( "location" )
+
+    for recipient in recipients:
+        if not recipient.get( "device" ):
+            main.log.warn( "Device not given for recipient {0}. Loading from main.hostData".format( recipient.get( "name" ) ) )
+            recipient[ "device" ] = main.hostsData.get( recipient.get( "name" ) ).get( "location" )
+
+
+    ingressDevice = senders[ 0 ].get( "device" )
+    egressDevice = recipients[ 0 ].get( "device" )
+
+    portIngress = senders[ 0 ].get( "port", "" )
+    portEgress = recipients[ 0 ].get( "port", "" )
+
+    dstMac = recipients[ 0 ].get( "mac" )
+
+    ipSrc = senders[ 0 ].get( "ip" )
+    ipDst = recipients[ 0 ].get( "ip" )
+
+    # Adding point intent
+    intentId = main.CLIs[ onosNode ].addPointIntent(
+                                        ingressDevice=ingressDevice,
+                                        egressDevice=egressDevice,
+                                        portIngress=portIngress,
+                                        portEgress=portEgress,
+                                        ethType=ethType,
+                                        ethDst=dstMac,
+                                        bandwidth=bandwidth,
+                                        lambdaAlloc=lambdaAlloc,
+                                        ipProto=ipProto,
+                                        ipSrc=ipSrc,
+                                        ipDst=ipDst,
+                                        tcpSrc=tcpSrc,
+                                        tcpDst=tcpDst )
 
     # Check intents state
-    time.sleep( main.checkIntentSleep )
-    intentResult = checkIntentState( main, intentsId )
-    # Check flows count in each node
-    checkFlowsCount( main )
-
-    # Check intents state again if first check fails...
-    if not intentResult:
-        intentResult = checkIntentState( main, intentsId )
-
-    # Check flows count in each node
-    checkFlowsCount( main )
-    # Verify flows
-    checkFlowsState( main )
-
-    # Ping hosts
-    pingTemp = pingallHosts( main, hostNames )
-    pingResult = pingResult and pingTemp
-    if pingTemp:
-        main.assertReturnString += 'Initial Pingall Passed\n'
+    if utilities.retry( f=checkIntentState, retValue=main.FALSE, args=( main, [ intentId ] ), sleep=main.checkIntentSleep ):
+        return intentId
     else:
-        main.assertReturnString += 'Initial Pingall Failed\n'
-
-    # Test rerouting if these variables exist
-    if sw1 and sw2 and expectedLink:
-        # link down
-        linkDownResult = link( main, sw1, sw2, "down" )
-
-        if linkDownResult:
-            main.assertReturnString += 'Link Down Passed\n'
-        else:
-            main.assertReturnString += 'Link Down Failed\n'
-
-        # Check flows count in each node
-        checkFlowsCount( main )
-        # Verify flows
-        checkFlowsState( main )
-
-        # Check OnosTopology
-        topoResult = checkTopology( main, expectedLink )
-        if topoResult:
-            main.assertReturnString += 'Link Down Topology State Passed\n'
-        else:
-            main.assertReturnString += 'Link Down Topology State Failed\n'
-
-        # Ping hosts
-        pingTemp = pingallHosts( main, hostNames )
-        pingResult = pingResult and pingTemp
-        if pingTemp:
-            main.assertReturnString += 'Link Down Pingall Passed\n'
-        else:
-            main.assertReturnString += 'Link Down Pingall Failed\n'
-
-        # Check intent state
-        intentTemp = checkIntentState( main, intentsId )
-        intentResult = intentResult and intentTemp
-        if intentTemp:
-            main.assertReturnString += 'Link Down Intent State Passed\n'
-        else:
-            main.assertReturnString += 'Link Down Intent State Failed\n'
-
-        # Checks ONOS state in link down
-        if linkDownResult and topoResult and pingResult and intentResult:
-            main.log.info( itemName + ": Successfully brought link down" )
-        else:
-            main.log.error( itemName + ": Failed to bring link down" )
-
-        # link up
-        linkUpResult = link( main, sw1, sw2, "up" )
-        if linkUpResult:
-            main.assertReturnString += 'Link Up Passed\n'
-        else:
-            main.assertReturnString += 'Link Up Failed\n'
-
-        time.sleep( main.rerouteSleep )
-
-        # Check flows count in each node
-        checkFlowsCount( main )
-        # Verify flows
-        checkFlowsState( main )
-
-        # Check OnosTopology
-        topoResult = checkTopology( main, main.numLinks )
-        if topoResult:
-            main.assertReturnString += 'Link Up Topology State Passed\n'
-        else:
-            main.assertReturnString += 'Link Up Topology State Failed\n'
-
-        # Ping hosts
-        pingTemp = pingallHosts( main, hostNames )
-        pingResult = pingResult and pingTemp
-
-        if pingTemp:
-            main.assertReturnString += 'Link Up Pingall Passed\n'
-        else:
-            main.assertReturnString += 'Link Up Pingall Failed\n'
-
-        intentTemp = checkIntentState( main, intentsId )
-        intentResult = intentResult and intentTemp
-        if intentTemp:
-            main.assertReturnString += 'Link Up Intent State Passed\n'
-        else:
-            main.assertReturnString += 'Link Up Intent State Failed\n'
-
-        # Checks ONOS state in link up
-        if linkUpResult and topoResult and pingResult and intentResult:
-            main.log.info( itemName + ": Successfully brought link back up" )
-        else:
-            main.log.error( itemName + ": Failed to bring link back up" )
-
-    # Remove all intents
-    removeIntentResult = removeAllIntents( main, intentsId )
-    if removeIntentResult:
-        main.assertReturnString += 'Remove Intents Passed'
-    else:
-        main.assertReturnString += 'Remove Intents Failed'
-
-    stepResult = pingResult and linkDownResult and linkUpResult \
-                 and intentResult and removeIntentResult
-
-    return stepResult
+        main.log.error( "Point Intent did not install correctly" )
+        return main.FALSE
 
 def pointIntentTcp( main,
                     name,
@@ -794,69 +658,48 @@
 
     return stepResult
 
-def singleToMultiIntent( main,
-                         name,
-                         hostNames,
-                         onosNode=0,
-                         devices="",
-                         ports=None,
-                         ethType="",
-                         macs=None,
-                         bandwidth="",
-                         lambdaAlloc=False,
-                         ipProto="",
-                         ipAddresses="",
-                         tcp="",
-                         sw1="",
-                         sw2="",
-                         expectedLink=0 ):
+def installSingleToMultiIntent( main,
+                                name,
+                                senders,
+                                recipients,
+                                onosNode=0,
+                                ethType="",
+                                bandwidth="",
+                                lambdaAlloc=False,
+                                ipProto="",
+                                ipAddresses="",
+                                tcp="",
+                                sw1="",
+                                sw2=""):
     """
-    Verify Single to Multi Point intents
-    NOTE:If main.hostsData is not defined, variables data should be passed
-    in the same order index wise. All devices in the list should have the same
-    format, either all the devices have its port or it doesn't.
-    eg. hostName = [ 'h1', 'h2' ,..  ]
-        devices = [ 'of:0000000000000001', 'of:0000000000000002', ...]
-        ports = [ '1', '1', ..]
-        ...
+    Installs a Single to Multi Point Intent
+
     Description:
-        Verify add-single-to-multi-intent iterates through the list of given
-        host | devices and add intents
+        Install a single to multi point intent using
+        add-single-to-multi-intent
+
     Steps:
-        - Get device ids | ports
-        - Add single to multi point intents
-        - Check intents
-        - Verify flows
-        - Ping hosts
-        - Reroute
-            - Link down
-            - Verify flows
-            - Check topology
-            - Ping hosts
-            - Link up
-            - Verify flows
-            - Check topology
-            - Ping hosts
-        - Remove intents
+        - Fetch host data if not given
+        - Add single to multi intent
+            - Ingress device is the first sender host
+            - Egress devices are the recipient devices
+            - Ports if defined in senders or recipients
+            - MAC address ethSrc loaded from Ingress device
+        - Check intent state with retry
     Required:
         name - Type of point intent to add eg. IPV4 | VLAN | Dualstack
-        hostNames - List of host names
+        senders - List of host dictionaries i.e.
+            { "name":"h8", "device":"of:0000000000000005/8","mac":"00:00:00:00:00:08" }
+        recipients - List of host dictionaries i.e.
+            { "name":"h16", "device":"of:0000000000000006/8", "mac":"00:00:00:00:00:10" }
     Optional:
         onosNode - ONOS node to install the intents in main.CLIs[ ]
                    0 by default so that it will always use the first
                    ONOS node
-        devices - List of device ids in the same order as the hosts
-                  in hostNames
-        ports - List of port numbers in the same order as the device in
-                devices
         ethType - Ethernet type eg. IPV4, IPV6
-        macs - List of hosts mac address in the same order as the hosts in
-               hostNames
         bandwidth - Bandwidth capacity
         lambdaAlloc - Allocate lambda, defaults to False
         ipProto - IP protocol
-        ipAddresses - IP addresses of host in the same order as the hosts in
-                      hostNames
         tcp - TCP ports in the same order as the hosts in hostNames
         sw1 - First switch to bring down & up for rerouting purpose
         sw2 - Second switch to bring down & up for rerouting purpose
@@ -866,287 +709,102 @@
     """
 
     assert main, "There is no main variable"
-    assert hostNames, "You must specify hosts"
-    assert devices or main.hostsData, "You must specify devices"
+    assert senders, "You must specify a sender"
+    assert recipients, "You must specify a recipient"
+    # Assert devices or main.hostsData, "You must specify devices"
 
-    global itemName
+    global itemName  # The name of this run. Used for logs.
     itemName = name
-    tempHostsData = {}
-    intentsId = []
     onosNode = int( onosNode )
 
-    macsDict = {}
-    ipDict = {}
-    if hostNames and devices:
-        if len( hostNames ) != len( devices ):
-            main.log.debug( "hosts and devices does not have the same length" )
-            #print "len hostNames = ", len( hostNames )
-            #print "len devices = ", len( devices )
-            return main.FALSE
-        if ports:
-            if len( ports ) != len( devices ):
-                main.log.error( "Ports and devices does " +
-                                "not have the same length" )
-                #print "len devices = ", len( devices )
-                #print "len ports = ", len( ports )
-                return main.FALSE
-        else:
-            main.log.info( "Device Ports are not specified" )
-        if macs:
-            for i in range( len( devices ) ):
-                macsDict[ devices[ i ] ] = macs[ i ]
-
-    elif hostNames and not devices and main.hostsData:
-        devices = []
-        main.log.info( "singleToMultiIntent function is using main.hostsData" )
-        for host in hostNames:
-               devices.append( main.hostsData.get( host ).get( 'location' ) )
-               macsDict[ main.hostsData.get( host ).get( 'location' ) ] = \
-                           main.hostsData.get( host ).get( 'mac' )
-               ipDict[ main.hostsData.get( host ).get( 'location' ) ] = \
-                           main.hostsData.get( host ).get( 'ipAddresses' )
-        #print main.hostsData
-
-    #print 'host names = ', hostNames
-    #print 'devices = ', devices
-    #print "macsDict = ", macsDict
-
-    pingResult = main.TRUE
-    intentResult = main.TRUE
-    removeIntentResult = main.TRUE
-    flowResult = main.TRUE
-    topoResult = main.TRUE
-    linkDownResult = main.TRUE
-    linkUpResult = main.TRUE
-
-    devicesCopy = copy.copy( devices )
-    if ports:
-        portsCopy = copy.copy( ports )
     main.log.info( itemName + ": Adding single point to multi point intents" )
 
-    # Check flows count in each node
-    checkFlowsCount( main )
+    for sender in senders:
+        if not sender.get( "device" ):
+            main.log.warn( "Device not given for sender {0}. Loading from main.hostData".format( sender.get( "name" ) ) )
+            sender[ "device" ] = main.hostsData.get( sender.get( "name" ) ).get( "location" )
 
-    # Adding bidirectional point  intents
-    for i in range( len( devices ) ):
-        ingressDevice = devicesCopy[ i ]
-        egressDeviceList = copy.copy( devicesCopy )
-        egressDeviceList.remove( ingressDevice )
-        if ports:
-            portIngress = portsCopy[ i ]
-            portEgressList = copy.copy( portsCopy )
-            del portEgressList[ i ]
-        else:
-            portIngress = ""
-            portEgressList = None
-        if not macsDict:
-            srcMac = ""
-        else:
-            srcMac = macsDict[ ingressDevice ]
-            if srcMac == None:
-                main.log.debug( "There is no MAC in device - " + ingressDevice )
-                srcMac = ""
+    for recipient in recipients:
+        if not recipient.get( "device" ):
+            main.log.warn( "Device not given for recipient {0}. Loading from main.hostData".format( recipient.get( "name" ) ) )
+            recipient[ "device" ] = main.hostsData.get( recipient.get( "name" ) ).get( "location" )
 
-        intentsId.append(
-                        main.CLIs[ onosNode ].addSinglepointToMultipointIntent(
-                                            ingressDevice=ingressDevice,
-                                            egressDeviceList=egressDeviceList,
-                                            portIngress=portIngress,
-                                            portEgressList=portEgressList,
-                                            ethType=ethType,
-                                            ethSrc=srcMac,
-                                            bandwidth=bandwidth,
-                                            lambdaAlloc=lambdaAlloc,
-                                            ipProto=ipProto,
-                                            ipSrc="",
-                                            ipDst="",
-                                            tcpSrc="",
-                                            tcpDst="" ) )
 
-    # Wait some time for the flow to go through when using multi instance
-    pingTemp = pingallHosts( main, hostNames )
+    ingressDevice = senders[ 0 ].get( "device" )
+    egressDeviceList = [ x.get( "device" ) for x in recipients if x.get( "device" ) ]
+
+    portIngress = senders[ 0 ].get( "port", "" )
+    portEgressList = [ x.get( "port" ) for x in recipients if x.get( "port" ) ]
+    if not portEgressList:
+        portEgressList = None
+
+    srcMac = senders[ 0 ].get( "mac" )
+
+    # Adding point intent
+    intentId = main.CLIs[ onosNode ].addSinglepointToMultipointIntent(
+                                        ingressDevice=ingressDevice,
+                                        egressDeviceList=egressDeviceList,
+                                        portIngress=portIngress,
+                                        portEgressList=portEgressList,
+                                        ethType=ethType,
+                                        ethSrc=srcMac,
+                                        bandwidth=bandwidth,
+                                        lambdaAlloc=lambdaAlloc,
+                                        ipProto=ipProto,
+                                        ipSrc="",
+                                        ipDst="",
+                                        tcpSrc="",
+                                        tcpDst="" )
 
     # Check intents state
-    time.sleep( main.checkIntentSleep )
-    intentResult = checkIntentState( main, intentsId )
-
-    # Check intents state again if first check fails...
-    if not intentResult:
-        intentResult = checkIntentState( main, intentsId )
-
-    # Check flows count in each node
-    checkFlowsCount( main )
-    # Verify flows
-    checkFlowsState( main )
-
-    pingTemp = pingallHosts( main, hostNames )
-    pingResult = pingResult and pingTemp
-    if pingTemp:
-        main.assertReturnString += 'Initial Pingall Passed\n'
+    if utilities.retry( f=checkIntentState, retValue=main.FALSE, args=( main, [ intentId ] ), sleep=main.checkIntentSleep ):
+        return intentId
     else:
-        main.assertReturnString += 'Initial Pingall Failed\n'
+        main.log.error( "Single to Multi Intent did not install correctly" )
+        return main.FALSE
 
-    # Test rerouting if these variables exist
-    if sw1 and sw2 and expectedLink:
-        # link down
-        linkDownResult = link( main, sw1, sw2, "down" )
-
-        if linkDownResult:
-            main.assertReturnString += 'Link Down Passed\n'
-        else:
-            main.assertReturnString += 'Link Down Failed\n'
-
-        # Check flows count in each node
-        checkFlowsCount( main )
-        # Verify flows
-        checkFlowsState( main )
-
-        # Check OnosTopology
-        topoResult = checkTopology( main, expectedLink )
-        if topoResult:
-            main.assertReturnString += 'Link Down Topology State Passed\n'
-        else:
-            main.assertReturnString += 'Link Down Topology State Failed\n'
-
-        # Ping hosts
-        pingTemp = pingallHosts( main, hostNames )
-        pingResult = pingResult and pingTemp
-        if pingTemp:
-            main.assertReturnString += 'Link Down Pingall Passed\n'
-        else:
-            main.assertReturnString += 'Link Down Pingall Failed\n'
-
-        # Check intent state
-        intentTemp = checkIntentState( main, intentsId )
-        intentResult = intentResult and intentTemp
-        if intentTemp:
-            main.assertReturnString += 'Link Down Intent State Passed\n'
-        else:
-            main.assertReturnString += 'Link Down Intent State Failed\n'
-
-        # Checks ONOS state in link down
-        if linkDownResult and topoResult and pingResult and intentResult:
-            main.log.info( itemName + ": Successfully brought link down" )
-        else:
-            main.log.error( itemName + ": Failed to bring link down" )
-
-        # link up
-        linkUpResult = link( main, sw1, sw2, "up" )
-        if linkUpResult:
-            main.assertReturnString += 'Link Up Passed\n'
-        else:
-            main.assertReturnString += 'Link Up Failed\n'
-
-        time.sleep( main.rerouteSleep )
-
-        # Check flows count in each node
-        checkFlowsCount( main )
-        # Verify flows
-        checkFlowsState( main )
-
-        # Check OnosTopology
-        topoResult = checkTopology( main, main.numLinks )
-        if topoResult:
-            main.assertReturnString += 'Link Up Topology State Passed\n'
-        else:
-            main.assertReturnString += 'Link Up Topology State Failed\n'
-
-        # Ping hosts
-        pingTemp = pingallHosts( main, hostNames )
-        pingResult = pingResult and pingTemp
-        if pingTemp:
-            main.assertReturnString += 'Link Up Pingall Passed\n'
-        else:
-            main.assertReturnString += 'Link Up Pingall Failed\n'
-
-        # Check Intents
-        intentTemp = checkIntentState( main, intentsId )
-        intentResult = intentResult and intentTemp
-        if intentTemp:
-            main.assertReturnString += 'Link Up Intent State Passed\n'
-        else:
-            main.assertReturnString += 'Link Up Intent State Failed\n'
-
-        # Checks ONOS state in link up
-        if linkUpResult and topoResult and pingResult and intentResult:
-            main.log.info( itemName + ": Successfully brought link back up" )
-        else:
-            main.log.error( itemName + ": Failed to bring link back up" )
-
-    # Remove all intents
-    removeIntentResult = removeAllIntents( main, intentsId )
-    if removeIntentResult:
-        main.assertReturnString += 'Remove Intents Passed'
-    else:
-        main.assertReturnString += 'Remove Intents Failed'
-
-    stepResult = pingResult and linkDownResult and linkUpResult \
-                 and intentResult and removeIntentResult
-
-    return stepResult
-
-def multiToSingleIntent( main,
-                         name,
-                         hostNames,
-                         onosNode=0,
-                         devices="",
-                         ports=None,
-                         ethType="",
-                         macs=None,
-                         bandwidth="",
-                         lambdaAlloc=False,
-                         ipProto="",
-                         ipAddresses="",
-                         tcp="",
-                         sw1="",
-                         sw2="",
-                         expectedLink=0 ):
+def installMultiToSingleIntent( main,
+                                name,
+                                senders,
+                                recipients,
+                                onosNode=0,
+                                ethType="",
+                                bandwidth="",
+                                lambdaAlloc=False,
+                                ipProto="",
+                                ipAddresses="",
+                                tcp="",
+                                sw1="",
+                                sw2=""):
     """
-    Verify Single to Multi Point intents
-    NOTE:If main.hostsData is not defined, variables data should be passed in the
-    same order index wise. All devices in the list should have the same
-    format, either all the devices have its port or it doesn't.
-    eg. hostName = [ 'h1', 'h2' ,..  ]
-        devices = [ 'of:0000000000000001', 'of:0000000000000002', ...]
-        ports = [ '1', '1', ..]
-        ...
+    Installs a Multi to Single Point Intent
+
     Description:
-        Verify add-multi-to-single-intent
+        Install a multi to single point intent using
+        add-multi-to-single-intent
+
     Steps:
-        - Get device ids | ports
-        - Add multi to single point intents
-        - Check intents
-        - Verify flows
-        - Ping hosts
-        - Reroute
-            - Link down
-            - Verify flows
-            - Check topology
-            - Ping hosts
-            - Link up
-            - Verify flows
-            - Check topology
-            - Ping hosts
-        - Remove intents
+        - Fetch host data if not given
+        - Add multi to single intent
+            - Ingress devices are the senders devices
+            - Egress device is the first recipient host
+            - Ports if defined in senders or recipients
+            - MAC address ethSrc loaded from Ingress device
+        - Check intent state with retry
     Required:
         name - Type of point intent to add eg. IPV4 | VLAN | Dualstack
-        hostNames - List of host names
+        senders - List of host dictionaries i.e.
+            [ { "name":"h8", "device":"of:0000000000000005/8","mac":"00:00:00:00:00:08" } ]
+        recipients - List of host dictionaries i.e.
+            [ { "name":"h16", "device":"of:0000000000000006/8", "mac":"00:00:00:00:00:10" } ]
     Optional:
         onosNode - ONOS node to install the intents in main.CLIs[ ]
                    0 by default so that it will always use the first
                    ONOS node
-        devices - List of device ids in the same order as the hosts
-                  in hostNames
-        ports - List of port numbers in the same order as the device in
-                devices
         ethType - Ethernet type eg. IPV4, IPV6
-        macs - List of hosts mac address in the same order as the hosts in
-               hostNames
         bandwidth - Bandwidth capacity
         lambdaAlloc - Allocate lambda, defaults to False
         ipProto - IP protocol
-        ipAddresses - IP addresses of host in the same order as the hosts in
-                      hostNames
         tcp - TCP ports in the same order as the hosts in hostNames
         sw1 - First switch to bring down & up for rerouting purpose
         sw2 - Second switch to bring down & up for rerouting purpose
@@ -1156,280 +814,404 @@
     """
 
     assert main, "There is no main variable"
-    assert hostNames, "You must specify hosts"
-    assert devices or main.hostsData, "You must specify devices"
+    assert senders, "You must specify a sender"
+    assert recipients, "You must specify a recipient"
+    # Assert devices or main.hostsData, "You must specify devices"
+
+    global itemName  # The name of this run. Used for logs.
+    itemName = name
+    onosNode = int( onosNode )
+
+    main.log.info( itemName + ": Adding mutli to single point intents" )
+
+    for sender in senders:
+        if not sender.get( "device" ):
+            main.log.warn( "Device not given for sender {0}. Loading from main.hostData".format( sender.get( "name" ) ) )
+            sender[ "device" ] = main.hostsData.get( sender.get( "name" ) ).get( "location" )
+
+    for recipient in recipients:
+        if not recipient.get( "device" ):
+            main.log.warn( "Device not given for recipient {0}. Loading from main.hostData".format( recipient.get( "name" ) ) )
+            recipient[ "device" ] = main.hostsData.get( recipient.get( "name" ) ).get( "location" )
+
+
+    ingressDeviceList = [ x.get( "device" ) for x in senders if x.get( "device" ) ]
+    egressDevice = recipients[ 0 ].get( "device" )
+
+    portIngressList = [ x.get( "port" ) for x in senders if x.get( "port" ) ]
+    portEgress = recipients[ 0 ].get( "port", "" )
+    if not portIngressList:
+        portIngressList = None
+
+    dstMac = recipients[ 0 ].get( "mac" )
+
+    # Adding point intent
+    intentId = main.CLIs[ onosNode ].addMultipointToSinglepointIntent(
+                                        ingressDeviceList=ingressDeviceList,
+                                        egressDevice=egressDevice,
+                                        portIngressList=portIngressList,
+                                        portEgress=portEgress,
+                                        ethType=ethType,
+                                        ethDst=dstMac,
+                                        bandwidth=bandwidth,
+                                        lambdaAlloc=lambdaAlloc,
+                                        ipProto=ipProto,
+                                        ipSrc="",
+                                        ipDst="",
+                                        tcpSrc="",
+                                        tcpDst="" )
+
+    # Check intents state
+    if utilities.retry( f=checkIntentState, retValue=main.FALSE, args=( main, [ intentId ] ), sleep=main.checkIntentSleep ):
+        return intentId
+    else:
+        main.log.error( "Multi to Single Intent did not install correctly" )
+        return main.FALSE
+
+def testPointIntent( main,
+                             name,
+                             intentId,
+                             senders,
+                             recipients,
+                             badSenders={},
+                             badRecipients={},
+                             onosNode=0,
+                             ethType="",
+                             bandwidth="",
+                             lambdaAlloc=False,
+                             ipProto="",
+                             ipAddresses="",
+                             tcp="",
+                             sw1="s5",
+                             sw2="s2",
+                             expectedLink=0):
+    """
+    Test a Point Intent
+
+    Description:
+        Test a point intent
+
+    Steps:
+        - Fetch host data if not given
+        - Check Intent State
+        - Check Flow State
+        - Check Connectivity
+        - Check Lack of Connectivity Between Hosts not in the Intent
+        - Reroute
+            - Take Expected Link Down
+            - Check Intent State
+            - Check Flow State
+            - Check Topology
+            - Check Connectivity
+            - Bring Expected Link Up
+            - Check Intent State
+            - Check Flow State
+            - Check Topology
+            - Check Connectivity
+        - Remove Topology
+
+    Required:
+        name - Type of point intent to add eg. IPV4 | VLAN | Dualstack
+
+        senders - List of host dictionaries i.e.
+            { "name":"h8", "device":"of:0000000000000005/8","mac":"00:00:00:00:00:08" }
+        recipients - List of host dictionaries i.e.
+            { "name":"h16", "device":"of:0000000000000006/8", "mac":"00:00:00:00:00:10" }
+    Optional:
+        onosNode - ONOS node to install the intents in main.CLIs[ ]
+                   0 by default so that it will always use the first
+                   ONOS node
+        ethType - Ethernet type eg. IPV4, IPV6
+        bandwidth - Bandwidth capacity
+        lambdaAlloc - Allocate lambda, defaults to False
+        ipProto - IP protocol
+        tcp - TCP ports in the same order as the hosts in hostNames
+        sw1 - First switch to bring down & up for rerouting purpose
+        sw2 - Second switch to bring down & up for rerouting purpose
+        expectedLink - Expected link when the switches are down, it should
+                       be two links lower than the links before the two
+                       switches are down
+
+    """
+
+    # Parameter Validity Check
+    assert main, "There is no main variable"
+    assert senders, "You must specify a sender"
+    assert recipients, "You must specify a recipient"
 
     global itemName
     itemName = name
     tempHostsData = {}
-    intentsId = []
     onosNode = int( onosNode )
 
-    macsDict = {}
-    ipDict = {}
-    if hostNames and devices:
-        if len( hostNames ) != len( devices ):
-            main.log.debug( "hosts and devices does not have the same length" )
-            #print "len hostNames = ", len( hostNames )
-            #print "len devices = ", len( devices )
-            return main.FALSE
-        if ports:
-            if len( ports ) != len( devices ):
-                main.log.error( "Ports and devices does " +
-                                "not have the same length" )
-                #print "len devices = ", len( devices )
-                #print "len ports = ", len( ports )
-                return main.FALSE
-        else:
-            main.log.info( "Device Ports are not specified" )
-        if macs:
-            for i in range( len( devices ) ):
-                macsDict[ devices[ i ] ] = macs[ i ]
-    elif hostNames and not devices and main.hostsData:
-        devices = []
-        main.log.info( "multiToSingleIntent function is using main.hostsData" )
-        for host in hostNames:
-               devices.append( main.hostsData.get( host ).get( 'location' ) )
-               macsDict[ main.hostsData.get( host ).get( 'location' ) ] = \
-                           main.hostsData.get( host ).get( 'mac' )
-               ipDict[ main.hostsData.get( host ).get( 'location' ) ] = \
-                           main.hostsData.get( host ).get( 'ipAddresses' )
-        #print main.hostsData
+    main.log.info( itemName + ": Testing Point Intent" )
 
-    #print 'host names = ', hostNames
-    #print 'devices = ', devices
-    #print "macsDict = ", macsDict
+    # Names for scapy
+    senderNames = [ x.get( "name" ) for x in senders ]
+    recipientNames = [ x.get( "name" ) for x in recipients ]
+    badSenderNames = [ x.get( "name" ) for x in badSenders ]
+    badRecipientNames = [ x.get( "name" ) for x in badRecipients ]
 
-    pingResult = main.TRUE
-    intentResult = main.TRUE
-    removeIntentResult = main.TRUE
-    flowResult = main.TRUE
-    topoResult = main.TRUE
-    linkDownResult = main.TRUE
-    linkUpResult = main.TRUE
+    for sender in senders:
+        if not sender.get( "device" ):
+            main.log.warn( "Device not given for sender {0}. Loading from main.hostData".format( sender.get( "name" ) ) )
+            sender[ "device" ] = main.hostsData.get( sender.get( "name" ) ).get( "location" )
 
-    devicesCopy = copy.copy( devices )
-    if ports:
-        portsCopy = copy.copy( ports )
-    main.log.info( itemName + ": Adding multi point to single point intents" )
+    for recipient in recipients:
+        if not recipient.get( "device" ):
+            main.log.warn( "Device not given for recipient {0}. Loading from main.hostData".format( recipient.get( "name" ) ) )
+            recipient[ "device" ] = main.hostsData.get( recipient.get( "name" ) ).get( "location" )
 
-    # Check flows count in each node
-    checkFlowsCount( main )
+    testResult = main.TRUE
+    main.log.info( itemName + ": Adding single point to multi point intents" )
 
-    # Adding bidirectional point  intents
-    for i in range( len( devices ) ):
-        egressDevice = devicesCopy[ i ]
-        ingressDeviceList = copy.copy( devicesCopy )
-        ingressDeviceList.remove( egressDevice )
-        if ports:
-            portEgress = portsCopy[ i ]
-            portIngressList = copy.copy( portsCopy )
-            del portIngressList[ i ]
-        else:
-            portEgress = ""
-            portIngressList = None
-        if not macsDict:
-            dstMac = ""
-        else:
-            dstMac = macsDict[ egressDevice ]
-            if dstMac == None:
-                main.log.debug( "There is no MAC in device - " + egressDevice )
-                dstMac = ""
-
-        intentsId.append(
-                        main.CLIs[ onosNode ].addMultipointToSinglepointIntent(
-                                            ingressDeviceList=ingressDeviceList,
-                                            egressDevice=egressDevice,
-                                            portIngressList=portIngressList,
-                                            portEgress=portEgress,
-                                            ethType=ethType,
-                                            ethDst=dstMac,
-                                            bandwidth=bandwidth,
-                                            lambdaAlloc=lambdaAlloc,
-                                            ipProto=ipProto,
-                                            ipSrc="",
-                                            ipDst="",
-                                            tcpSrc="",
-                                            tcpDst="" ) )
-
-    pingTemp = pingallHosts( main, hostNames )
-
-    # Check intents state
-    time.sleep( main.checkIntentSleep )
-    intentResult = checkIntentState( main, intentsId )
-
-    # Check intents state again if first check fails...
-    if not intentResult:
-        intentResult = checkIntentState( main, intentsId )
-
-    # Check flows count in each node
-    checkFlowsCount( main )
-    # Verify flows
-    checkFlowsState( main )
-
-    # Ping hosts
-    pingTemp = pingallHosts( main, hostNames )
-
-    # Ping hosts again...
-    pingTemp = pingallHosts( main, hostNames )
-    pingResult = pingResult and pingTemp
-    if pingTemp:
-        main.assertReturnString += 'Initial Pingall Passed\n'
+    # Check intent state
+    if utilities.retry( f=checkIntentState, retValue=main.FALSE, args=( main, [ intentId ] ), sleep=main.checkIntentSleep ):
+        main.assertReturnString += 'Initial Intent State Passed\n'
     else:
-        main.assertReturnString += 'Initial Pingall Failed\n'
+        main.assertReturnString += 'Initial Intent State Failed\n'
+        testResult = main.FALSE
+
+    # Check flows count in each node
+    if utilities.retry( f=checkFlowsCount, retValue=main.FALSE, args=[ main ] ) and utilities.retry( f=checkFlowsState, retValue=main.FALSE, args=[ main ] ):
+        main.assertReturnString += 'Initial Flow State Passed\n'
+    else:
+        main.assertReturnString += 'Intial Flow State Failed\n'
+        testResult = main.FALSE
+
+    # Check Connectivity
+    if utilities.retry( f=scapyCheckConnection, retValue=main.FALSE, args=( main, senderNames, recipientNames ) ):
+        main.assertReturnString += 'Initial Ping Passed\n'
+    else:
+        main.assertReturnString += 'Initial Ping Failed\n'
+        testResult = main.FALSE
+
+    # Check connections that shouldn't work
+    if badSenderNames:
+        main.log.info( "Checking that packets from incorrect sender do not go through" )
+        if utilities.retry( f=scapyCheckConnection, retValue=main.FALSE, args=( main, badSenderNames, recipientNames ), kwargs={ "expectFailure":True } ):
+            main.assertReturnString += 'Bad Sender Ping Passed\n'
+        else:
+            main.assertReturnString += 'Bad Sender Ping Failed\n'
+            testResult = main.FALSE
+
+    if badRecipientNames:
+        main.log.info( "Checking that packets to incorrect recipients do not go through" )
+        if utilities.retry( f=scapyCheckConnection, retValue=main.FALSE, args=( main, senderNames, badRecipientNames ), kwargs={ "expectFailure":True } ):
+            main.assertReturnString += 'Bad Recipient Ping Passed\n'
+        else:
+            main.assertReturnString += 'Bad Recipient Ping Failed\n'
+            testResult = main.FALSE
 
     # Test rerouting if these variables exist
     if sw1 and sw2 and expectedLink:
-        # link down
-        linkDownResult = link( main, sw1, sw2, "down" )
-
-        if linkDownResult:
+        # Take link down
+        if utilities.retry( f=link, retValue=main.FALSE, args=( main, sw1, sw2, "down" ) ):
             main.assertReturnString += 'Link Down Passed\n'
         else:
             main.assertReturnString += 'Link Down Failed\n'
-
-        # Check flows count in each node
-        checkFlowsCount( main )
-        # Verify flows
-        checkFlowsState( main )
-
-        # Check OnosTopology
-        topoResult = checkTopology( main, expectedLink )
-        if topoResult:
-            main.assertReturnString += 'Link Down Topology State Passed\n'
-        else:
-            main.assertReturnString += 'Link Down Topology State Failed\n'
-
-        # Ping hosts
-        pingTemp = pingallHosts( main, hostNames )
-        pingResult = pingResult and pingTemp
-        if pingTemp:
-            main.assertReturnString += 'Link Down Pingall Passed\n'
-        else:
-            main.assertReturnString += 'Link Down Pingall Failed\n'
+            testResult = main.FALSE
 
         # Check intent state
-        intentTemp = checkIntentState( main, intentsId )
-        intentResult = intentResult and intentTemp
-        if intentTemp:
+        if utilities.retry( f=checkIntentState, retValue=main.FALSE, args=( main, [ intentId ] ), sleep=main.checkIntentSleep ):
             main.assertReturnString += 'Link Down Intent State Passed\n'
         else:
             main.assertReturnString += 'Link Down Intent State Failed\n'
+            testResult = main.FALSE
 
-        # Checks ONOS state in link down
-        if linkDownResult and topoResult and pingResult and intentResult:
-            main.log.info( itemName + ": Successfully brought link down" )
+        # Check flows count in each node
+        if utilities.retry( f=checkFlowsCount, retValue=main.FALSE, args=[ main ] ) and utilities.retry( f=checkFlowsState, retValue=main.FALSE, args=[ main ] ):
+            main.assertReturnString += 'Link Down Flow State Passed\n'
         else:
-            main.log.error( itemName + ": Failed to bring link down" )
+            main.assertReturnString += 'Link Down Flow State Failed\n'
+            testResult = main.FALSE
 
-        # link up
-        linkUpResult = link( main, sw1, sw2, "up" )
-        if linkUpResult:
+        # Check OnosTopology
+        if utilities.retry( f=checkTopology, retValue=main.FALSE, args=( main, expectedLink ) ):
+            main.assertReturnString += 'Link Down Topology State Passed\n'
+        else:
+            main.assertReturnString += 'Link Down Topology State Failed\n'
+            testResult = main.FALSE
+
+        # Check Connection
+        if utilities.retry( f=scapyCheckConnection, retValue=main.FALSE, args=( main, senderNames, recipientNames ) ):
+            main.assertReturnString += 'Link Down Pingall Passed\n'
+        else:
+            main.assertReturnString += 'Link Down Pingall Failed\n'
+            testResult = main.FALSE
+
+        # Bring link up
+        if utilities.retry( f=link, retValue=main.FALSE, args=( main, sw1, sw2, "up" ) ):
             main.assertReturnString += 'Link Up Passed\n'
         else:
             main.assertReturnString += 'Link Up Failed\n'
+            testResult = main.FALSE
 
+        # Wait for reroute
         time.sleep( main.rerouteSleep )
 
-        # Check flows count in each node
-        checkFlowsCount( main )
-        # Verify flows
-        checkFlowsState( main )
-
-        # Check OnosTopology
-        topoResult = checkTopology( main, main.numLinks )
-        if topoResult:
-            main.assertReturnString += 'Link Up Topology State Passed\n'
-        else:
-            main.assertReturnString += 'Link Up Topology State Failed\n'
-
-        # Ping hosts
-        pingTemp = pingallHosts( main, hostNames )
-        pingResult = pingResult and pingTemp
-        if pingTemp:
-            main.assertReturnString += 'Link Up Pingall Passed\n'
-        else:
-            main.assertReturnString += 'Link Up Pingall Failed\n'
-
         # Check Intents
-        intentTemp = checkIntentState( main, intentsId )
-        intentResult = intentResult and intentTemp
-        if intentTemp:
+        if utilities.retry( f=checkIntentState, retValue=main.FALSE, args=( main, [ intentId ] ), sleep=main.checkIntentSleep ):
             main.assertReturnString += 'Link Up Intent State Passed\n'
         else:
             main.assertReturnString += 'Link Up Intent State Failed\n'
+            testResult = main.FALSE
 
-        # Checks ONOS state in link up
-        if linkUpResult and topoResult and pingResult and intentResult:
-            main.log.info( itemName + ": Successfully brought link back up" )
+        # Check flows count in each node
+        if utilities.retry( f=checkFlowsCount, retValue=main.FALSE, args=[ main ] ) and utilities.retry( f=checkFlowsState, retValue=main.FALSE, args=[ main ] ):
+            main.assertReturnString += 'Link Up Flow State Passed\n'
         else:
-            main.log.error( itemName + ": Failed to bring link back up" )
+            main.assertReturnString += 'Link Up Flow State Failed\n'
+            testResult = main.FALSE
+
+        # Check OnosTopology
+        if utilities.retry( f=checkTopology, retValue=main.FALSE, args=( main, main.numLinks ) ):
+            main.assertReturnString += 'Link Up Topology State Passed\n'
+        else:
+            main.assertReturnString += 'Link Up Topology State Failed\n'
+            testResult = main.FALSE
+
+        # Check Connection
+        if utilities.retry( f=scapyCheckConnection, retValue=main.FALSE, args=( main, senderNames, recipientNames ) ):
+            main.assertReturnString += 'Link Up Scapy Packet Received Passed\n'
+        else:
+            main.assertReturnString += 'Link Up Scapy Packet Recieved Failed\n'
+            testResult = main.FALSE
 
     # Remove all intents
-    removeIntentResult = removeAllIntents( main, intentsId )
-    if removeIntentResult:
+    if utilities.retry( f=removeAllIntents, retValue=main.FALSE, args=( main, [ intentId ] ) ):
         main.assertReturnString += 'Remove Intents Passed'
     else:
         main.assertReturnString += 'Remove Intents Failed'
+        testResult = main.FALSE
 
-    stepResult = pingResult and linkDownResult and linkUpResult \
-                 and intentResult and removeIntentResult
-
-    return stepResult
+    return testResult
 
 def pingallHosts( main, hostList ):
-    # Ping all host in the hosts list variable
+    """
+        Ping all host in the hosts list variable
+    """
     main.log.info( "Pinging: " + str( hostList ) )
     return main.Mininet1.pingallHosts( hostList )
 
-def getHostsData( main ):
+def fwdPingall( main ):
     """
         Use fwd app and pingall to discover all the hosts
     """
-
     activateResult = main.TRUE
     appCheck = main.TRUE
     getDataResult = main.TRUE
     main.log.info( "Activating reactive forwarding app " )
     activateResult = main.CLIs[ 0 ].activateApp( "org.onosproject.fwd" )
+
+    # Wait for forward app activation to propagate
     time.sleep( main.fwdSleep )
 
+    # Check that forwarding is enabled on all nodes
     for i in range( main.numCtrls ):
         appCheck = appCheck and main.CLIs[ i ].appToIDCheck()
         if appCheck != main.TRUE:
             main.log.warn( main.CLIs[ i ].apps() )
             main.log.warn( main.CLIs[ i ].appIDs() )
 
+    # Send pingall in mininet
+    main.log.info( "Run Pingall" )
     pingResult = main.Mininet1.pingall( timeout = 600 )
-    hostsJson = json.loads( main.CLIs[ 0 ].hosts() )
-    hosts = main.Mininet1.getHosts().keys()
-    # TODO: Make better use of new getHosts function
-    for host in hosts:
-        main.hostsData[ host ] = {}
-        main.hostsData[ host ][ 'mac' ] =  \
-            main.Mininet1.getMacAddress( host ).upper()
-        for hostj in hostsJson:
-            if main.hostsData[ host ][ 'mac' ] == hostj[ 'mac' ]:
-                main.hostsData[ host ][ 'id' ] = hostj[ 'id' ]
-                main.hostsData[ host ][ 'vlan' ] = hostj[ 'vlan' ]
-                main.hostsData[ host ][ 'location' ] = \
-                            hostj[ 'location' ][ 'elementId' ] + '/' + \
-                            hostj[ 'location' ][ 'port' ]
-                main.hostsData[ host ][ 'ipAddresses' ] = hostj[ 'ipAddresses' ]
 
     main.log.info( "Deactivating reactive forwarding app " )
     deactivateResult = main.CLIs[ 0 ].deactivateApp( "org.onosproject.fwd" )
-    if activateResult and deactivateResult and main.hostsData:
-        main.log.info( "Successfully used fwd app to discover hosts " )
+    if activateResult and deactivateResult:
+        main.log.info( "Successfully used fwd app to discover hosts" )
         getDataResult = main.TRUE
     else:
-        main.log.info( "Failed to use fwd app to discover hosts " )
+        main.log.info( "Failed to use fwd app to discover hosts" )
         getDataResult = main.FALSE
-
-    print main.hostsData
-
     return getDataResult
 
+def confirmHostDiscovery( main ):
+    """
+        Confirms that all ONOS nodes have discovered all scapy hosts
+    """
+    import collections
+    scapyHostCount = len( main.scapyHosts )
+    hosts = main.topo.getAllHosts( main )  # Get host data from each ONOS node
+    hostFails = []  # Reset for each failed attempt
+
+    #  Check for matching hosts on each node
+    scapyHostIPs = [ x.hostIp for x in main.scapyHosts if x.hostIp != "0.0.0.0" ]
+    for controller in range( main.numCtrls ):
+        controllerStr = str( controller + 1 )  # ONOS node number
+        # Compare Hosts
+        # Load hosts data for controller node
+        if hosts[ controller ] and "Error" not in hosts[ controller ]:
+            try:
+                hostData = json.loads( hosts[ controller ] )
+            except ( TypeError, ValueError ):
+                main.log.error( "Could not load json:" + str( hosts[ controller ] ) )
+                hostFails.append( controllerStr )
+            else:
+                onosHostIPs = [ x.get( "ipAddresses" )[ 0 ]
+                                for x in hostData
+                                if len( x.get( "ipAddresses" ) ) > 0 ]
+                if not set( collections.Counter( scapyHostIPs ) ).issubset( set ( collections.Counter( onosHostIPs ) ) ):
+                    main.log.warn( "Controller {0} only sees nodes with {1} IPs. It should see all of the following: {2}".format( controllerStr, onosHostIPs, scapyHostIPs ) )
+                    hostFails.append( controllerStr )
+        else:
+            main.log.error( "Hosts returned nothing or an error." )
+            hostFails.append( controllerStr )
+
+    if hostFails:
+        main.log.error( "List of failed ONOS Nodes:" + ', '.join(map(str, hostFails )) )
+        return main.FALSE
+    else:
+        return main.TRUE
+
+def sendDiscoveryArp( main, hosts=None ):
+    """
+        Sends Discovery ARP packets from each host provided
+        Defaults to each host in main.scapyHosts
+    """
+    # Send an arp ping from each host
+    if not hosts:
+        hosts = main.scapyHosts
+    for host in hosts:
+        pkt = 'Ether( src="{0}")/ARP( psrc="{1}")'.format( host.hostMac ,host.hostIp )
+        # Send from the VLAN interface if there is one so ONOS discovers the VLAN correctly
+        iface = None
+        for interface in host.getIfList():
+            if '.' in interface:
+                main.log.debug( "Detected VLAN interface {0}. Sending ARP packet from {0}".format( interface ) )
+                iface = interface
+                break
+        host.sendPacket( packet=pkt, iface=iface )
+        main.log.info( "Sending ARP packet from {0}".format( host.name ) )
+
+def populateHostData( main ):
+    """
+        Populates hostsData
+    """
+    import json
+    try:
+        hostsJson = json.loads( main.CLIs[ 0 ].hosts() )
+        hosts = main.Mininet1.getHosts().keys()
+        # TODO: Make better use of new getHosts function
+        for host in hosts:
+            main.hostsData[ host ] = {}
+            main.hostsData[ host ][ 'mac' ] =  \
+                main.Mininet1.getMacAddress( host ).upper()
+            for hostj in hostsJson:
+                if main.hostsData[ host ][ 'mac' ] == hostj[ 'mac' ]:
+                    main.hostsData[ host ][ 'id' ] = hostj[ 'id' ]
+                    main.hostsData[ host ][ 'vlan' ] = hostj[ 'vlan' ]
+                    main.hostsData[ host ][ 'location' ] = \
+                                hostj[ 'location' ][ 'elementId' ] + '/' + \
+                                hostj[ 'location' ][ 'port' ]
+                    main.hostsData[ host ][ 'ipAddresses' ] = hostj[ 'ipAddresses' ]
+        return main.TRUE
+    except KeyError:
+        main.log.error( "KeyError while populating hostsData")
+        return main.FALSE
+
 def checkTopology( main, expectedLink ):
     statusResult = main.TRUE
     # Check onos topology
@@ -1500,6 +1282,73 @@
     linkResult = main.Mininet1.link( end1=sw1, end2=sw2, option=option )
     return linkResult
 
+def scapyCheckConnection( main, senders, recipients, packet=None, packetFilter=None, expectFailure=False ):
+    """
+        Checks the connectivity between all given sender hosts and all given recipient hosts
+        Packet may be specified. Defaults to Ether/IP packet
+        Packet Filter may be specified. Defaults to Ether/IP from current sender MAC
+            Todo: Optional packet and packet filter attributes for sender and recipients
+        Expect Failure when the sender and recipient are not supposed to have connectivity
+            Timeout of 1 second, returns main.TRUE if the filter is not triggered and kills the filter
+
+    """
+    connectionsFunctional = main.TRUE
+
+    if not packetFilter:
+        packetFilter = 'ether host {}'
+
+    if expectFailure:
+        timeout = 1
+    else:
+        timeout = 10
+
+    for sender in senders:
+        try:
+            senderComp = getattr( main, sender )
+        except AttributeError:
+            main.log.error( "main has no attribute {}".format( sender ) )
+            connectionsFunctional = main.FALSE
+            continue
+
+        for recipient in recipients:
+            # Do not send packets to self since recipient CLI will already be busy
+            if recipient == sender:
+                continue
+            try:
+                recipientComp = getattr( main, recipient )
+            except AttributeError:
+                main.log.error( "main has no attribute {}".format( recipient ) )
+                connectionsFunctional = main.FALSE
+                continue
+
+            recipientComp.startFilter( pktFilter = packetFilter.format( senderComp.hostMac ) )
+
+            if not packet:
+                pkt = 'Ether( src="{0}", dst="{2}" )/IP( src="{1}", dst="{3}" )'.format(
+                    senderComp.hostMac,
+                    senderComp.hostIp,
+                    recipientComp.hostMac,
+                    recipientComp.hostIp )
+            else:
+                pkt = packet
+            senderComp.sendPacket( packet = pkt )
+
+            if recipientComp.checkFilter( timeout ):
+                if expectFailure:
+                    main.log.error( "Packet from {0} successfully received by {1} when it should not have been".format( sender , recipient ) )
+                    connectionsFunctional = main.FALSE
+                else:
+                    main.log.info( "Packet from {0} successfully received by {1}".format( sender , recipient ) )
+            else:
+                recipientComp.killFilter()
+                if expectFailure:
+                    main.log.info( "As expected, packet from {0} was not received by {1}".format( sender , recipient ) )
+                else:
+                    main.log.error( "Packet from {0} was not received by {1}".format( sender , recipient ) )
+                    connectionsFunctional = main.FALSE
+
+        return connectionsFunctional
+
 def removeAllIntents( main, intentsId ):
     """
         Remove all intents in the intentsId
@@ -1536,7 +1385,6 @@
     """
         Check flows count in each node
     """
-
     flowsCount = []
     main.log.info( itemName + ": Checking flows count in each ONOS node" )
     for i in range( main.numCtrls ):
@@ -1602,9 +1450,8 @@
 
 def report( main ):
     """
-    Report errors/warnings/exceptions
+        Report errors/warnings/exceptions
     """
-
     main.ONOSbench.logReport( main.ONOSip[ 0 ],
                               [ "INFO",
                                 "FOLLOWER",
diff --git a/TestON/tests/FUNCintent/FUNCintent.params b/TestON/tests/FUNCintent/FUNCintent.params
index dca495e..843848b 100644
--- a/TestON/tests/FUNCintent/FUNCintent.params
+++ b/TestON/tests/FUNCintent/FUNCintent.params
@@ -7,15 +7,17 @@
     # 10 - Start Mininet with Openflow 1.0
     # 11 - Start Mininet with Openflow 1.3
     # 12 - Assign switch to controller
-    # 13 - Create a data of hosts information
-    # 14 - Stop Mininet
+    # 13 - Create Scapy Components
+    # 14 - Discover hosts with Mininet Pingall
+    $ 15 - Discover hosts with Scapy arping ( only discovers scapy hosts )
+    # 16 - Stop Mininet
     # 1000 - Test host intents
     # 2000 - Test point intents
     # 3000 - Test single to multi point intents
     # 4000 - Test multi to single point intents
     # 5000 - Test host mobility
 
-    <testcases>1,[2,10,12,8,13,1000,2000,3000,4000,5000,14]*2,[2,11,12,8,13,1000,2000,3000,4000,5000,14]*2</testcases>
+    <testcases>1,[2,10,12,13,15,2000,3000,4000,16]*2,[2,11,12,13,15,2000,3000,4000,16]*2</testcases>
 
     <SCALE>
         <size>1,3,1,3</size>
@@ -51,6 +53,10 @@
         <links>20</links>
     </MININET>
 
+    <SCAPY>
+        <HOSTNAMES>h1,h2,h3,h4,h5,h6,h7,h8,h9,h10,h11,h12,h13,h14,h15,h16,h17,h18,h19,h20,h21,h22,h23,h24</HOSTNAMES>
+    </SCAPY>
+
     # Intent tests params
     <SDNIP>
         <tcpProto>6</tcpProto>
diff --git a/TestON/tests/FUNCintent/FUNCintent.py b/TestON/tests/FUNCintent/FUNCintent.py
index e5d0654..9660fdc 100644
--- a/TestON/tests/FUNCintent/FUNCintent.py
+++ b/TestON/tests/FUNCintent/FUNCintent.py
@@ -56,6 +56,8 @@
             main.hostsData = {}
             main.CLIs = []
             main.ONOSip = []
+            main.scapyHostNames = main.params[ 'SCAPY' ][ 'HOSTNAMES' ].split( ',' )
+            main.scapyHosts = []  # List of scapy hosts for iterating
             main.assertReturnString = ''  # Assembled assert return string
 
             main.ONOSip = main.ONOSbench.getOnosIps()
@@ -84,7 +86,7 @@
             copyResult1 = main.ONOSbench.scp( main.Mininet1,
                                               main.dependencyPath +
                                               main.topology,
-                                              main.Mininet1.home,
+                                              main.Mininet1.home + "custom/",
                                               direction="to" )
             if main.CLIs:
                 stepResult = main.TRUE
@@ -144,6 +146,18 @@
         main.log.info( "Safety check, killing all ONOS processes" +
                        " before initiating environment setup" )
 
+        time.sleep( main.startUpSleep )
+        main.step( "Uninstalling ONOS package" )
+        onosUninstallResult = main.TRUE
+        for ip in main.ONOSip:
+            onosUninstallResult = onosUninstallResult and \
+                    main.ONOSbench.onosUninstall( nodeIp=ip )
+        stepResult = onosUninstallResult
+        utilities.assert_equals( expect=main.TRUE,
+                                 actual=stepResult,
+                                 onpass="Successfully uninstalled ONOS package",
+                                 onfail="Failed to uninstall ONOS package" )
+
         for i in range( main.maxNodes ):
             main.ONOSbench.onosDie( main.ONOSip[ i ] )
 
@@ -176,18 +190,6 @@
                                  onfail="Failed to create ONOS package" )
 
         time.sleep( main.startUpSleep )
-        main.step( "Uninstalling ONOS package" )
-        onosUninstallResult = main.TRUE
-        for ip in main.ONOSip:
-            onosUninstallResult = onosUninstallResult and \
-                    main.ONOSbench.onosUninstall( nodeIp=ip )
-        stepResult = onosUninstallResult
-        utilities.assert_equals( expect=main.TRUE,
-                                 actual=stepResult,
-                                 onpass="Successfully uninstalled ONOS package",
-                                 onfail="Failed to uninstall ONOS package" )
-
-        time.sleep( main.startUpSleep )
         main.step( "Installing ONOS package" )
         onosInstallResult = main.TRUE
         for i in range( main.numCtrls ):
@@ -273,15 +275,15 @@
                 devices = main.topo.getAllDevices( main )
                 ports = main.topo.getAllPorts( main )
                 devicesResults = main.TRUE
-                deviceFails = []  # Reset for each attempt
+                deviceFails = []  # Reset for each failed attempt
             if not linksResults:
                 links = main.topo.getAllLinks( main )
                 linksResults = main.TRUE
-                linkFails = []  # Reset for each attempt
+                linkFails = []  # Reset for each failed attempt
             if not hostsResults:
                 hosts = main.topo.getAllHosts( main )
                 hostsResults = main.TRUE
-                hostFails = []  # Reset for each attempt
+                hostFails = []  # Reset for each failed attempt
 
             #  Check for matching topology on each node
             for controller in range( main.numCtrls ):
@@ -295,7 +297,7 @@
                         deviceData = json.loads( devices[ controller ] )
                         portData = json.loads( ports[ controller ] )
                     except (TypeError,ValueError):
-                        main.log.error("Could not load json:" + str( devices[ controller ] ) + ' or ' + str( ports[ controller ] ))
+                        main.log.error( "Could not load json: {0} or {1}".format( str( devices[ controller ] ), str( ports[ controller ] ) ) )
                         currentDevicesResult = main.FALSE
                     else:
                         currentDevicesResult = main.Mininet1.compareSwitches(
@@ -456,38 +458,122 @@
                                  onfail="Failed to assign switches to " +
                                         "controller" )
 
-    def CASE13( self, main ):
+    def CASE13( self,main ):
         """
-            Discover all hosts and store its data to a dictionary
+            Create Scapy components
+        """
+        main.case( "Create scapy components" )
+        main.step( "Create scapy components" )
+        import json
+        scapyResult = main.TRUE
+        for hostName in main.scapyHostNames:
+            main.Scapy1.createHostComponent( hostName )
+            main.scapyHosts.append( getattr( main, hostName ) )
+
+        main.step( "Start scapy components" )
+        for host in main.scapyHosts:
+            host.startHostCli()
+            host.startScapy()
+            host.updateSelf()
+            main.log.debug( host.name )
+            main.log.debug( host.hostIp )
+            main.log.debug( host.hostMac )
+
+
+        utilities.assert_equals( expect=main.TRUE,
+                                 actual=scapyResult,
+                                 onpass="Successfully created Scapy Components",
+                                 onfail="Failed to discover Scapy Components" )
+
+    def CASE14( self, main ):
+        """
+            Discover all hosts with fwd and pingall and store its data in a dictionary
         """
         main.case( "Discover all hosts" )
+        main.step( "Pingall hosts and confirm ONOS discovery" )
+        utilities.retry( f=main.intentFunction.fwdPingall, retValue=main.FALSE, args=[ main ] )
 
-        stepResult = main.TRUE
-        main.step( "Discover all hosts using pingall " )
-        stepResult = main.intentFunction.getHostsData( main )
+        utilities.retry( f=main.intentFunction.confirmHostDiscovery, retValue=main.FALSE,
+                         args=[ main ], attempts=main.checkTopoAttempts, sleep=2 )
         utilities.assert_equals( expect=main.TRUE,
                                  actual=stepResult,
                                  onpass="Successfully discovered hosts",
                                  onfail="Failed to discover hosts" )
 
-    def CASE14( self, main ):
-        """
-            Stop mininet
-        """
-        main.log.report( "Stop Mininet topology" )
-        main.case( "Stop Mininet topology" )
-        main.caseExplanation = "Stopping the current mininet topology " +\
-                                "to start up fresh"
-
-        main.step( "Stopping Mininet Topology" )
-        topoResult = main.Mininet1.stopNet( )
-        stepResult = topoResult
+        main.step( "Populate hostsData" )
+        stepResult = main.intentFunction.populateHostData( main )
         utilities.assert_equals( expect=main.TRUE,
                                  actual=stepResult,
-                                 onpass="Successfully stop mininet",
-                                 onfail="Failed to stop mininet" )
+                                 onpass="Successfully populated hostsData",
+                                 onfail="Failed to populate hostsData" )
+
+    def CASE15( self, main ):
+        """
+            Discover all hosts with scapy arp packets and store its data to a dictionary
+        """
+        main.case( "Discover all hosts using scapy" )
+        main.step( "Send packets from each host to the first host and confirm onos discovery" )
+
+        import collections
+        if len( main.scapyHosts ) < 1:
+            main.log.error( "No scapy hosts have been created" )
+            main.skipCase()
+
+        # Send ARP packets from each scapy host component
+        main.intentFunction.sendDiscoveryArp( main, main.scapyHosts )
+
+        stepResult = utilities.retry( f=main.intentFunction.confirmHostDiscovery,
+                                      retValue=main.FALSE, args=[ main ],
+                                      attempts=main.checkTopoAttempts, sleep=2 )
+
+        utilities.assert_equals( expect=main.TRUE,
+                                 actual=stepResult,
+                                 onpass="ONOS correctly discovered all hosts",
+                                 onfail="ONOS incorrectly discovered hosts" )
+
+        main.step( "Populate hostsData" )
+        stepResult = main.intentFunction.populateHostData( main )
+        utilities.assert_equals( expect=main.TRUE,
+                                 actual=stepResult,
+                                 onpass="Successfully populated hostsData",
+                                 onfail="Failed to populate hostsData" )
+
+
+    def CASE16( self, main ):
+        """
+            Stop mininet and remove scapy host
+        """
+        main.log.report( "Stop Mininet and Scapy" )
+        main.case( "Stop Mininet and Scapy" )
+        main.caseExplanation = "Stopping the current mininet topology " +\
+                                "to start up fresh"
+        main.step( "Stopping and Removing Scapy Host Components" )
+        scapyResult = main.TRUE
+        for host in main.scapyHosts:
+            scapyResult = scapyResult and host.stopScapy()
+            main.log.info( "Stopped Scapy Host: {0}".format( host.name ) )
+
+        for host in main.scapyHosts:
+            scapyResult = scapyResult and main.Scapy1.removeHostComponent( host.name )
+            main.log.info( "Removed Scapy Host Component: {0}".format( host.name ) )
+
+        main.scapyHosts = []
+        main.scapyHostIPs = []
+
+        utilities.assert_equals( expect=main.TRUE,
+                                 actual=scapyResult,
+                                 onpass="Successfully stopped scapy and removed host components",
+                                 onfail="Failed to stop mininet and scapy" )
+
+        main.step( "Stopping Mininet Topology" )
+        mininetResult = main.Mininet1.stopNet( )
+
+        utilities.assert_equals( expect=main.TRUE,
+                                 actual=mininetResult,
+                                 onpass="Successfully stopped mininet and scapy",
+                                 onfail="Failed to stop mininet and scapy" )
         # Exit if topology did not load properly
-        if not topoResult:
+        if not ( mininetResult and scapyResult ):
             main.cleanup()
             main.exit()
 
@@ -522,6 +608,7 @@
         assert main.numSwitch, "Placed the total number of switch topology in \
                                 main.numSwitch"
 
+        # Save leader candidates
         intentLeadersOld = main.CLIs[ 0 ].leaderCandidates()
 
         main.testName = "Host Intents"
@@ -536,105 +623,175 @@
 
         main.step( "IPV4: Add host intents between h1 and h9" )
         main.assertReturnString = "Assertion Result for IPV4 host intent with mac addresses\n"
-        stepResult = main.TRUE
-        stepResult = main.intentFunction.hostIntent( main,
-                                              onosNode='0',
+        host1 = { "name":"h1","id":"00:00:00:00:00:01/-1" }
+        host2 = { "name":"h9","id":"00:00:00:00:00:09/-1" }
+        testResult = main.FALSE
+        installResult = main.intentFunction.installHostIntent( main,
                                               name='IPV4',
-                                              host1='h1',
-                                              host2='h9',
-                                              host1Id='00:00:00:00:00:01/-1',
-                                              host2Id='00:00:00:00:00:09/-1',
+                                              onosNode='0',
+                                              host1=host1,
+                                              host2=host2)
+        if installResult:
+            testResult = main.intentFunction.testHostIntent( main,
+                                              name='IPV4',
+                                              intentId = installResult,
+                                              onosNode='0',
+                                              host1=host1,
+                                              host2=host2,
                                               sw1='s5',
                                               sw2='s2',
-                                              expectedLink=18 )
+                                              expectedLink = 18)
+
         utilities.assert_equals( expect=main.TRUE,
-                                 actual=stepResult,
+                                 actual=testResult,
                                  onpass=main.assertReturnString,
                                  onfail=main.assertReturnString)
 
         main.step( "DUALSTACK1: Add host intents between h3 and h11" )
         main.assertReturnString = "Assertion Result for dualstack IPV4 with MAC addresses\n"
-        stepResult = main.TRUE
-        stepResult = main.intentFunction.hostIntent( main,
+        host1 = { "name":"h3","id":"00:00:00:00:00:03/-1" }
+        host2 = { "name":"h11","id":"00:00:00:00:00:0B/-1 "}
+        testResult = main.FALSE
+        installResult = main.intentFunction.installHostIntent( main,
                                               name='DUALSTACK',
-                                              host1='h3',
-                                              host2='h11',
-                                              host1Id='00:00:00:00:00:03/-1',
-                                              host2Id='00:00:00:00:00:0B/-1',
+                                              onosNode='0',
+                                              host1=host1,
+                                              host2=host2)
+
+        if installResult:
+            testResult = main.intentFunction.testHostIntent( main,
+                                              name='DUALSTACK',
+                                              intentId = installResult,
+                                              onosNode='0',
+                                              host1=host1,
+                                              host2=host2,
                                               sw1='s5',
                                               sw2='s2',
-                                              expectedLink=18 )
+                                              expectedLink = 18)
 
         utilities.assert_equals( expect=main.TRUE,
-                                 actual=stepResult,
+                                 actual=testResult,
                                  onpass=main.assertReturnString,
-                                 onfail=main.assertReturnString )
+                                 onfail=main.assertReturnString)
 
         main.step( "DUALSTACK2: Add host intents between h1 and h11" )
         main.assertReturnString = "Assertion Result for dualstack2 host intent\n"
-        stepResult = main.TRUE
-        stepResult = main.intentFunction.hostIntent( main,
+        host1 = { "name":"h1" }
+        host2 = { "name":"h11" }
+        testResult = main.FALSE
+        installResult = main.intentFunction.installHostIntent( main,
                                               name='DUALSTACK2',
-                                              host1='h1',
-                                              host2='h11',
+                                              onosNode='0',
+                                              host1=host1,
+                                              host2=host2)
+
+        if installResult:
+            testResult = main.intentFunction.testHostIntent( main,
+                                              name='DUALSTACK2',
+                                              intentId = installResult,
+                                              onosNode='0',
+                                              host1=host1,
+                                              host2=host2,
                                               sw1='s5',
                                               sw2='s2',
-                                              expectedLink=18 )
+                                              expectedLink = 18)
 
         utilities.assert_equals( expect=main.TRUE,
-                                 actual=stepResult,
+                                 actual=testResult,
                                  onpass=main.assertReturnString,
-                                 onfail=main.assertReturnString )
+                                 onfail=main.assertReturnString)
 
         main.step( "1HOP: Add host intents between h1 and h3" )
         main.assertReturnString = "Assertion Result for 1HOP for IPV4 same switch\n"
-        stepResult = main.TRUE
-        stepResult = main.intentFunction.hostIntent( main,
+        host1 = { "name":"h1" }
+        host2 = { "name":"h3" }
+        testResult = main.FALSE
+        installResult = main.intentFunction.installHostIntent( main,
                                               name='1HOP',
-                                              host1='h1',
-                                              host2='h3' )
+                                              onosNode='0',
+                                              host1=host1,
+                                              host2=host2)
+
+        if installResult:
+            testResult = main.intentFunction.testHostIntent( main,
+                                              name='1HOP',
+                                              intentId = installResult,
+                                              onosNode='0',
+                                              host1=host1,
+                                              host2=host2,
+                                              sw1='s5',
+                                              sw2='s2',
+                                              expectedLink = 18)
 
         utilities.assert_equals( expect=main.TRUE,
-                                 actual=stepResult,
+                                 actual=testResult,
                                  onpass=main.assertReturnString,
-                                 onfail=main.assertReturnString )
+                                 onfail=main.assertReturnString)
 
         main.step( "VLAN1: Add vlan host intents between h4 and h12" )
         main.assertReturnString = "Assertion Result vlan IPV4\n"
-        stepResult = main.TRUE
-        stepResult = main.intentFunction.hostIntent( main,
+        host1 = { "name":"h4","id":"00:00:00:00:00:04/100" }
+        host2 = { "name":"h12","id":"00:00:00:00:00:0C/100 "}
+        testResult = main.FALSE
+        installResult = main.intentFunction.installHostIntent( main,
                                               name='VLAN1',
-                                              host1='h4',
-                                              host2='h12',
-                                              host1Id='00:00:00:00:00:04/100',
-                                              host2Id='00:00:00:00:00:0C/100',
+                                              onosNode='0',
+                                              host1=host1,
+                                              host2=host2)
+
+        if installResult:
+            testResult = main.intentFunction.testHostIntent( main,
+                                              name='VLAN1',
+                                              intentId = installResult,
+                                              onosNode='0',
+                                              host1=host1,
+                                              host2=host2,
                                               sw1='s5',
                                               sw2='s2',
-                                              expectedLink=18 )
+                                              expectedLink = 18)
 
         utilities.assert_equals( expect=main.TRUE,
-                                 actual=stepResult,
+                                 actual=testResult,
                                  onpass=main.assertReturnString,
-                                 onfail=main.assertReturnString )
+                                 onfail=main.assertReturnString)
 
         main.step( "VLAN2: Add inter vlan host intents between h13 and h20" )
         main.assertReturnString = "Assertion Result different VLAN negative test\n"
-        stepResult = main.TRUE
-        stepResult = main.intentFunction.hostIntent( main,
+        host1 = { "name":"h13" }
+        host2 = { "name":"h20" }
+        testResult = main.FALSE
+        installResult = main.intentFunction.installHostIntent( main,
                                               name='VLAN2',
-                                              host1='h13',
-                                              host2='h20' )
+                                              onosNode='0',
+                                              host1=host1,
+                                              host2=host2)
 
-        utilities.assert_equals( expect=main.FALSE,
-                                 actual=stepResult,
+        if installResult:
+            testResult = main.intentFunction.testHostIntent( main,
+                                              name='VLAN2',
+                                              intentId = installResult,
+                                              onosNode='0',
+                                              host1=host1,
+                                              host2=host2,
+                                              sw1='s5',
+                                              sw2='s2',
+                                              expectedLink = 18)
+
+        utilities.assert_equals( expect=main.TRUE,
+                                 actual=testResult,
                                  onpass=main.assertReturnString,
-                                 onfail=main.assertReturnString )
+                                 onfail=main.assertReturnString)
 
-
+        main.step( "Confirm that ONOS leadership is unchanged")
         intentLeadersNew = main.CLIs[ 0 ].leaderCandidates()
         main.intentFunction.checkLeaderChange( intentLeadersOld,
                                                 intentLeadersNew )
 
+        utilities.assert_equals( expect=main.TRUE,
+                                 actual=testResult,
+                                 onpass="ONOS Leaders Unchanged",
+                                 onfail="ONOS Leader Mismatch")
+
         main.intentFunction.report( main )
 
     def CASE2000( self, main ):
@@ -682,110 +839,134 @@
         # No option point intents
         main.step( "NOOPTION: Add point intents between h1 and h9" )
         main.assertReturnString = "Assertion Result for NOOPTION point intent\n"
-        stepResult = main.TRUE
-        stepResult = main.intentFunction.pointIntent(
+        senders = [
+            { "name":"h1","device":"of:0000000000000005/1" }
+        ]
+        recipients = [
+            { "name":"h9","device":"of:0000000000000006/1" }
+        ]
+        installResult = main.intentFunction.installPointIntent(
                                        main,
                                        name="NOOPTION",
-                                       host1="h1",
-                                       host2="h9",
-                                       deviceId1="of:0000000000000005/1",
-                                       deviceId2="of:0000000000000006/1",
-                                       sw1="s5",
-                                       sw2="s2",
-                                       expectedLink=18 )
+                                       senders=senders,
+                                       recipients=recipients )
+
+        if installResult:
+            testResult = main.intentFunction.testPointIntent(
+                                         main,
+                                         intentId=installResult,
+                                         name="NOOPTION",
+                                         senders=senders,
+                                         recipients=recipients,
+                                         sw1="s5",
+                                         sw2="s2",
+                                         expectedLink=18)
 
         utilities.assert_equals( expect=main.TRUE,
-                                 actual=stepResult,
+                                 actual=testResult,
                                  onpass=main.assertReturnString,
                                  onfail=main.assertReturnString )
 
         stepResult = main.TRUE
         main.step( "IPV4: Add point intents between h1 and h9" )
         main.assertReturnString = "Assertion Result for IPV4 point intent\n"
-        stepResult = main.intentFunction.pointIntent(
+        senders = [
+            { "name":"h1","device":"of:0000000000000005/1","mac":"00:00:00:00:00:01" }
+        ]
+        recipients = [
+            { "name":"h9","device":"of:0000000000000006/1","mac":"00:00:00:00:00:09" }
+        ]
+        installResult = main.intentFunction.installPointIntent(
                                        main,
                                        name="IPV4",
-                                       host1="h1",
-                                       host2="h9",
-                                       deviceId1="of:0000000000000005/1",
-                                       deviceId2="of:0000000000000006/1",
-                                       port1="",
-                                       port2="",
-                                       ethType="IPV4",
-                                       mac1="00:00:00:00:00:01",
-                                       mac2="00:00:00:00:00:09",
-                                       bandwidth="",
-                                       lambdaAlloc=False,
-                                       ipProto="",
-                                       ip1="",
-                                       ip2="",
-                                       tcp1="",
-                                       tcp2="",
-                                       sw1="s5",
-                                       sw2="s2",
-                                       expectedLink=18 )
+                                       senders=senders,
+                                       recipients=recipients,
+                                       ethType="IPV4" )
+
+        if installResult:
+            testResult = main.intentFunction.testPointIntent(
+                                         main,
+                                         intentId=installResult,
+                                         name="IPV4",
+                                         senders=senders,
+                                         recipients=recipients,
+                                         sw1="s5",
+                                         sw2="s2",
+                                         expectedLink=18)
 
         utilities.assert_equals( expect=main.TRUE,
-                                 actual=stepResult,
+                                 actual=testResult,
                                  onpass=main.assertReturnString,
                                  onfail=main.assertReturnString )
         main.step( "IPV4_2: Add point intents between h1 and h9" )
         main.assertReturnString = "Assertion Result for IPV4 no mac address point intents\n"
-        stepResult = main.intentFunction.pointIntent(
+        senders = [
+            { "name":"h1","device":"of:0000000000000005/1" }
+        ]
+        recipients = [
+            { "name":"h9","device":"of:0000000000000006/1" }
+        ]
+        installResult = main.intentFunction.installPointIntent(
                                        main,
                                        name="IPV4_2",
-                                       host1="h1",
-                                       host2="h9",
-                                       deviceId1="of:0000000000000005/1",
-                                       deviceId2="of:0000000000000006/1",
-                                       ipProto="",
-                                       ip1="",
-                                       ip2="",
-                                       tcp1="",
-                                       tcp2="",
-                                       sw1="s5",
-                                       sw2="s2",
-                                       expectedLink=18 )
+                                       senders=senders,
+                                       recipients=recipients,
+                                       ethType="IPV4" )
+
+        if installResult:
+            testResult = main.intentFunction.testPointIntent(
+                                         main,
+                                         intentId=installResult,
+                                         name="IPV4_2",
+                                         senders=senders,
+                                         recipients=recipients,
+                                         sw1="s5",
+                                         sw2="s2",
+                                         expectedLink=18)
 
         utilities.assert_equals( expect=main.TRUE,
-                                 actual=stepResult,
+                                 actual=testResult,
                                  onpass=main.assertReturnString,
                                  onfail=main.assertReturnString )
 
         main.step( "SDNIP-ICMP: Add point intents between h1 and h9" )
         main.assertReturnString = "Assertion Result for SDNIP-ICMP IPV4 using TCP point intents\n"
-        mac1 = main.hostsData[ 'h1' ][ 'mac' ]
-        mac2 = main.hostsData[ 'h9' ][ 'mac' ]
-        try:
-            ip1 = str( main.hostsData[ 'h1' ][ 'ipAddresses' ][ 0 ] ) + "/24"
-            ip2 = str( main.hostsData[ 'h9' ][ 'ipAddresses' ][ 0 ] ) + "/24"
-        except KeyError:
-            main.log.debug( "Key Error getting IP addresses of h1 | h9 in" +
-                            "main.hostsData" )
-            ip1 = main.Mininet1.getIPAddress( 'h1')
-            ip2 = main.Mininet1.getIPAddress( 'h9')
-
+        senders = [
+            { "name":"h1","device":"of:0000000000000005/1","mac":"00:00:00:00:00:01",
+              "ip":main.h1.hostIp }
+        ]
+        recipients = [
+            { "name":"h9","device":"of:0000000000000006/1","mac":"00:00:00:00:00:09",
+              "ip":main.h9.hostIp }
+        ]
         ipProto = main.params[ 'SDNIP' ][ 'icmpProto' ]
         # Uneccessary, not including this in the selectors
-        tcp1 = main.params[ 'SDNIP' ][ 'srcPort' ]
-        tcp2 = main.params[ 'SDNIP' ][ 'dstPort' ]
+        tcpSrc = main.params[ 'SDNIP' ][ 'srcPort' ]
+        tcpDst = main.params[ 'SDNIP' ][ 'dstPort' ]
 
-        stepResult = main.intentFunction.pointIntent(
-                                           main,
-                                           name="SDNIP-ICMP",
-                                           host1="h1",
-                                           host2="h9",
-                                           deviceId1="of:0000000000000005/1",
-                                           deviceId2="of:0000000000000006/1",
-                                           mac1=mac1,
-                                           mac2=mac2,
-                                           ethType="IPV4",
-                                           ipProto=ipProto,
-                                           ip1=ip1,
-                                           ip2=ip2 )
+        installResult = main.intentFunction.installPointIntent(
+                                       main,
+                                       name="SDNIP-ICMP",
+                                       senders=senders,
+                                       recipients=recipients,
+                                       ethType="IPV4",
+                                       ipProto=ipProto,
+                                       tcpSrc=tcpSrc,
+                                       tcpDst=tcpDst )
+
+        if installResult:
+            testResult = main.intentFunction.testPointIntent(
+                                         main,
+                                         intentId=installResult,
+                                         name="SDNIP_ICMP",
+                                         senders=senders,
+                                         recipients=recipients,
+                                         sw1="s5",
+                                         sw2="s2",
+                                         expectedLink=18)
 
         utilities.assert_equals( expect=main.TRUE,
-                                 actual=stepResult,
+                                 actual=testResult,
                                  onpass=main.assertReturnString,
                                  onfail=main.assertReturnString )
 
@@ -822,73 +1003,94 @@
 
         main.step( "DUALSTACK1: Add point intents between h3 and h11" )
         main.assertReturnString = "Assertion Result for Dualstack1 IPV4 with mac address point intents\n"
-        stepResult = main.intentFunction.pointIntent(
+        senders = [
+            { "name":"h3","device":"of:0000000000000005/3","mac":"00:00:00:00:00:03" }
+        ]
+        recipients = [
+            { "name":"h11","device":"of:0000000000000006/3","mac":"00:00:00:00:00:0B" }
+        ]
+        installResult = main.intentFunction.installPointIntent(
                                        main,
                                        name="DUALSTACK1",
-                                       host1="h3",
-                                       host2="h11",
-                                       deviceId1="of:0000000000000005",
-                                       deviceId2="of:0000000000000006",
-                                       port1="3",
-                                       port2="3",
-                                       ethType="IPV4",
-                                       mac1="00:00:00:00:00:03",
-                                       mac2="00:00:00:00:00:0B",
-                                       bandwidth="",
-                                       lambdaAlloc=False,
-                                       ipProto="",
-                                       ip1="",
-                                       ip2="",
-                                       tcp1="",
-                                       tcp2="",
-                                       sw1="s5",
-                                       sw2="s2",
-                                       expectedLink=18 )
+                                       senders=senders,
+                                       recipients=recipients,
+                                       ethType="IPV4" )
+
+        if installResult:
+            testResult = main.intentFunction.testPointIntent(
+                                         main,
+                                         intentId=installResult,
+                                         name="DUALSTACK1",
+                                         senders=senders,
+                                         recipients=recipients,
+                                         sw1="s5",
+                                         sw2="s2",
+                                         expectedLink=18)
 
         utilities.assert_equals( expect=main.TRUE,
-                                 actual=stepResult,
+                                 actual=testResult,
                                  onpass=main.assertReturnString,
                                  onfail=main.assertReturnString )
 
         main.step( "VLAN: Add point intents between h5 and h21" )
         main.assertReturnString = "Assertion Result for VLAN IPV4 with mac address point intents\n"
-        stepResult = main.intentFunction.pointIntent(
+        senders = [
+            { "name":"h5","device":"of:0000000000000005/5","mac":"00:00:00:00:00:05" }
+        ]
+        recipients = [
+            { "name":"h21","device":"of:0000000000000007/5","mac":"00:00:00:00:00:15" }
+        ]
+        installResult = main.intentFunction.installPointIntent(
                                        main,
-                                       name="VLAN",
-                                       host1="h5",
-                                       host2="h21",
-                                       deviceId1="of:0000000000000005/5",
-                                       deviceId2="of:0000000000000007/5",
-                                       port1="",
-                                       port2="",
-                                       ethType="IPV4",
-                                       mac1="00:00:00:00:00:05",
-                                       mac2="00:00:00:00:00:15",
-                                       bandwidth="",
-                                       lambdaAlloc=False,
-                                       ipProto="",
-                                       ip1="",
-                                       ip2="",
-                                       tcp1="",
-                                       tcp2="",
-                                       sw1="s5",
-                                       sw2="s2",
-                                       expectedLink=18 )
+                                       name="DUALSTACK1",
+                                       senders=senders,
+                                       recipients=recipients,
+                                       ethType="IPV4" )
+
+        if installResult:
+            testResult = main.intentFunction.testPointIntent(
+                                         main,
+                                         intentId=installResult,
+                                         name="DUALSTACK1",
+                                         senders=senders,
+                                         recipients=recipients,
+                                         sw1="s5",
+                                         sw2="s2",
+                                         expectedLink=18)
 
         utilities.assert_equals( expect=main.TRUE,
-                                 actual=stepResult,
+                                 actual=testResult,
                                  onpass=main.assertReturnString,
                                  onfail=main.assertReturnString )
 
         main.step( "1HOP: Add point intents between h1 and h3" )
         main.assertReturnString = "Assertion Result for 1HOP IPV4 with no mac address point intents\n"
-        stepResult = main.intentFunction.hostIntent( main,
-                                              name='1HOP',
-                                              host1='h1',
-                                              host2='h3' )
+        senders = [
+            { "name":"h1","device":"of:0000000000000005/1","mac":"00:00:00:00:00:01" }
+        ]
+        recipients = [
+            { "name":"h3","device":"of:0000000000000005/3","mac":"00:00:00:00:00:03" }
+        ]
+        installResult = main.intentFunction.installPointIntent(
+                                       main,
+                                       name="1HOP IPV4",
+                                       senders=senders,
+                                       recipients=recipients,
+                                       ethType="IPV4" )
+
+        if installResult:
+            testResult = main.intentFunction.testPointIntent(
+                                         main,
+                                         intentId=installResult,
+                                         name="1HOP IPV4",
+                                         senders=senders,
+                                         recipients=recipients,
+                                         sw1="s5",
+                                         sw2="s2",
+                                         expectedLink=18)
 
         utilities.assert_equals( expect=main.TRUE,
-                                 actual=stepResult,
+                                 actual=testResult,
                                  onpass=main.assertReturnString,
                                  onfail=main.assertReturnString )
 
@@ -930,101 +1132,158 @@
                                ";\nThe test will use OF " + main.OFProtocol +\
                                " OVS running in Mininet"
 
-        hostNames = [ 'h8', 'h16', 'h24' ]
-        devices = [ 'of:0000000000000005/8', 'of:0000000000000006/8', \
-                    'of:0000000000000007/8' ]
-        macs = [ '00:00:00:00:00:08', '00:00:00:00:00:10', '00:00:00:00:00:18' ]
-
-        # This test as written attempts something that is improbable to succeed
-        # Single to Multi Point Raw intent cannot be bi-directional, so pings are not usable to test it
-        # This test should be re-written so that one single-to-multi NOOPTION
-        # intent is installed, with listeners at the destinations, so that one way
-        # packets can be detected
-        #
-        # main.step( "NOOPTION: Add single point to multi point intents" )
-        # stepResult = main.TRUE
-        # stepResult = main.intentFunction.singleToMultiIntent(
-        #                                  main,
-        #                                  name="NOOPTION",
-        #                                  hostNames=hostNames,
-        #                                  devices=devices,
-        #                                  sw1="s5",
-        #                                  sw2="s2",
-        #                                  expectedLink=18 )
-        #
-        # utilities.assert_equals( expect=main.TRUE,
-        #                          actual=stepResult,
-        #                          onpass="NOOPTION: Successfully added single "
-        #                                 + " point to multi point intents" +
-        #                                 " with no match action",
-        #                          onfail="NOOPTION: Failed to add single point"
-        #                                 + " point to multi point intents" +
-        #                                 " with no match action" )
-
-        main.step( "IPV4: Add single point to multi point intents" )
-        main.assertReturnString = "Assertion results for IPV4 single to multi point intent with IPV4 type and MAC addresses\n"
-        stepResult = main.intentFunction.singleToMultiIntent(
+        main.step( "NOOPTION: Install and test single point to multi point intents" )
+        main.assertReturnString = "Assertion results for IPV4 single to multi point intent with no options set\n"
+        senders = [
+            { "name":"h8", "device":"of:0000000000000005/8" }
+        ]
+        recipients = [
+            { "name":"h16", "device":"of:0000000000000006/8" },
+            { "name":"h24", "device":"of:0000000000000007/8" }
+        ]
+        badSenders=[ { "name":"h9" } ]  # Senders that are not in the intent
+        badRecipients=[ { "name":"h17" } ]  # Recipients that are not in the intent
+        testResult = main.FALSE
+        installResult = main.intentFunction.installSingleToMultiIntent(
                                          main,
-                                         name="IPV4",
-                                         hostNames=hostNames,
-                                         devices=devices,
-                                         ports=None,
-                                         ethType="IPV4",
-                                         macs=macs,
-                                         bandwidth="",
-                                         lambdaAlloc=False,
-                                         ipProto="",
-                                         ipAddresses="",
-                                         tcp="",
+                                         name="NOOPTION",
+                                         senders=senders,
+                                         recipients=recipients,
+                                         sw1="s5",
+                                         sw2="s2")
+
+        if installResult:
+            testResult = main.intentFunction.testPointIntent(
+                                         main,
+                                         intentId=installResult,
+                                         name="NOOPTION",
+                                         senders=senders,
+                                         recipients=recipients,
+                                         badSenders=badSenders,
+                                         badRecipients=badRecipients,
                                          sw1="s5",
                                          sw2="s2",
-                                         expectedLink=18 )
+                                         expectedLink=18)
 
         utilities.assert_equals( expect=main.TRUE,
-                                 actual=stepResult,
+                                 actual=testResult,
+                                 onpass=main.assertReturnString,
+                                 onfail=main.assertReturnString )
+
+        main.step( "IPV4: Install and test single point to multi point intents" )
+        main.assertReturnString = "Assertion results for IPV4 single to multi point intent with IPV4 type and MAC addresses\n"
+        senders = [
+            { "name":"h8", "device":"of:0000000000000005/8","mac":"00:00:00:00:00:08" }
+        ]
+        recipients = [
+            { "name":"h16", "device":"of:0000000000000006/8", "mac":"00:00:00:00:00:10" },
+            { "name":"h24", "device":"of:0000000000000007/8", "mac":"00:00:00:00:00:18" }
+        ]
+        badSenders=[ { "name":"h9" } ]  # Senders that are not in the intent
+        badRecipients=[ { "name":"h17" } ]  # Recipients that are not in the intent
+        testResult = main.FALSE
+        installResult = main.intentFunction.installSingleToMultiIntent(
+                                         main,
+                                         name="IPV4",
+                                         senders=senders,
+                                         recipients=recipients,
+                                         ethType="IPV4",
+                                         sw1="s5",
+                                         sw2="s2")
+
+        if installResult:
+            testResult = main.intentFunction.testPointIntent(
+                                         main,
+                                         intentId=installResult,
+                                         name="IPV4",
+                                         senders=senders,
+                                         recipients=recipients,
+                                         badSenders=badSenders,
+                                         badRecipients=badRecipients,
+                                         sw1="s5",
+                                         sw2="s2",
+                                         expectedLink=18)
+
+        utilities.assert_equals( expect=main.TRUE,
+                                 actual=testResult,
                                  onpass=main.assertReturnString,
                                  onfail=main.assertReturnString )
 
         main.step( "IPV4_2: Add single point to multi point intents" )
         main.assertReturnString = "Assertion results for IPV4 single to multi point intent with IPV4 type and no MAC addresses\n"
-        hostNames = [ 'h8', 'h16', 'h24' ]
-        stepResult = main.intentFunction.singleToMultiIntent(
+        senders = [
+            { "name":"h8", "device":"of:0000000000000005/8" }
+        ]
+        recipients = [
+            { "name":"h16", "device":"of:0000000000000006/8" },
+            { "name":"h24", "device":"of:0000000000000007/8" }
+        ]
+        badSenders=[ { "name":"h9" } ]  # Senders that are not in the intent
+        badRecipients=[ { "name":"h17" } ]  # Recipients that are not in the intent
+        testResult = main.FALSE
+        installResult = main.intentFunction.installSingleToMultiIntent(
                                          main,
-                                         name="IPV4",
-                                         hostNames=hostNames,
+                                         name="IPV4_2",
+                                         senders=senders,
+                                         recipients=recipients,
                                          ethType="IPV4",
-                                         lambdaAlloc=False )
+                                         sw1="s5",
+                                         sw2="s2")
+
+        if installResult:
+            testResult = main.intentFunction.testPointIntent(
+                                         main,
+                                         intentId=installResult,
+                                         name="IPV4_2",
+                                         senders=senders,
+                                         recipients=recipients,
+                                         badSenders=badSenders,
+                                         badRecipients=badRecipients,
+                                         sw1="s5",
+                                         sw2="s2",
+                                         expectedLink=18)
 
         utilities.assert_equals( expect=main.TRUE,
-                                 actual=stepResult,
+                                 actual=testResult,
                                  onpass=main.assertReturnString,
                                  onfail=main.assertReturnString )
 
         main.step( "VLAN: Add single point to multi point intents" )
         main.assertReturnString = "Assertion results for IPV4 single to multi point intent with IPV4 type and MAC addresses in the same VLAN\n"
-        hostNames = [ 'h4', 'h12', 'h20' ]
-        devices = [ 'of:0000000000000005/4', 'of:0000000000000006/4', \
-                    'of:0000000000000007/4' ]
-        macs = [ '00:00:00:00:00:04', '00:00:00:00:00:0C', '00:00:00:00:00:14' ]
-        stepResult = main.intentFunction.singleToMultiIntent(
+        senders = [
+            { "name":"h4", "device":"of:0000000000000005/4", "mac":"00:00:00:00:00:04" }
+        ]
+        recipients = [
+            { "name":"h12", "device":"of:0000000000000006/4", "mac":"00:00:00:00:00:0C" },
+            { "name":"h20", "device":"of:0000000000000007/4", "mac":"00:00:00:00:00:14" }
+        ]
+        badSenders=[ { "name":"h13" } ]  # Senders that are not in the intent
+        badRecipients=[ { "name":"h21" } ]  # Recipients that are not in the intent
+        testResult = main.FALSE
+        installResult = main.intentFunction.installSingleToMultiIntent(
                                          main,
-                                         name="VLAN",
-                                         hostNames=hostNames,
-                                         devices=devices,
-                                         ports=None,
+                                         name="IPV4",
+                                         senders=senders,
+                                         recipients=recipients,
                                          ethType="IPV4",
-                                         macs=macs,
-                                         bandwidth="",
-                                         lambdaAlloc=False,
-                                         ipProto="",
-                                         ipAddresses="",
-                                         tcp="",
+                                         sw1="s5",
+                                         sw2="s2")
+
+        if installResult:
+            testResult = main.intentFunction.testPointIntent(
+                                         main,
+                                         intentId=installResult,
+                                         name="IPV4",
+                                         senders=senders,
+                                         recipients=recipients,
+                                         badSenders=badSenders,
+                                         badRecipients=badRecipients,
                                          sw1="s5",
                                          sw2="s2",
-                                         expectedLink=18 )
+                                         expectedLink=18)
 
         utilities.assert_equals( expect=main.TRUE,
-                                 actual=stepResult,
+                                 actual=testResult,
                                  onpass=main.assertReturnString,
                                  onfail=main.assertReturnString )
 
@@ -1066,104 +1325,163 @@
                                ";\nThe test will use OF " + main.OFProtocol +\
                                " OVS running in Mininet"
 
-        hostNames = [ 'h8', 'h16', 'h24' ]
-        devices = [ 'of:0000000000000005/8', 'of:0000000000000006/8', \
-                    'of:0000000000000007/8' ]
-        macs = [ '00:00:00:00:00:08', '00:00:00:00:00:10', '00:00:00:00:00:18' ]
+        main.step( "NOOPTION: Add multi point to single point intents" )
+        main.assertReturnString = "Assertion results for NOOPTION multi to single point intent\n"
+        senders = [
+            { "name":"h16", "device":"of:0000000000000006/8" },
+            { "name":"h24", "device":"of:0000000000000007/8" }
+        ]
+        recipients = [
+            { "name":"h8", "device":"of:0000000000000005/8" }
+        ]
+        badSenders=[ { "name":"h17" } ]  # Senders that are not in the intent
+        badRecipients=[ { "name":"h9" } ]  # Recipients that are not in the intent
+        testResult = main.FALSE
+        installResult = main.intentFunction.installMultiToSingleIntent(
+                                         main,
+                                         name="NOOPTION",
+                                         senders=senders,
+                                         recipients=recipients,
+                                         sw1="s5",
+                                         sw2="s2")
 
-        # This test as written attempts something that is impossible
-        # Multi to Single Raw intent cannot be bi-directional, so pings are not usable to test it
-        # This test should be re-written so that one multi-to-single NOOPTION
-        # intent is installed, with listeners at the destinations, so that one way
-        # packets can be detected
-        #
-        # main.step( "NOOPTION: Add multi point to single point intents" )
-        # stepResult = main.TRUE
-        # stepResult = main.intentFunction.multiToSingleIntent(
-        #                                  main,
-        #                                  name="NOOPTION",
-        #                                  hostNames=hostNames,
-        #                                  devices=devices,
-        #                                  sw1="s5",
-        #                                  sw2="s2",
-        #                                  expectedLink=18 )
-        #
-        # utilities.assert_equals( expect=main.TRUE,
-        #                          actual=stepResult,
-        #                          onpass="NOOPTION: Successfully added multi "
-        #                                 + " point to single point intents" +
-        #                                 " with no match action",
-        #                          onfail="NOOPTION: Failed to add multi point" +
-        #                                 " to single point intents" +
-        #                                 " with no match action" )
+        if installResult:
+            testResult = main.intentFunction.testPointIntent(
+                                         main,
+                                         intentId=installResult,
+                                         name="NOOPTION",
+                                         senders=senders,
+                                         recipients=recipients,
+                                         badSenders=badSenders,
+                                         badRecipients=badRecipients,
+                                         sw1="s5",
+                                         sw2="s2",
+                                         expectedLink=18)
+
+        utilities.assert_equals( expect=main.TRUE,
+                                 actual=testResult,
+                                 onpass=main.assertReturnString,
+                                 onfail=main.assertReturnString )
 
         main.step( "IPV4: Add multi point to single point intents" )
         main.assertReturnString = "Assertion results for IPV4 multi to single point intent with IPV4 type and MAC addresses\n"
-        stepResult = main.intentFunction.multiToSingleIntent(
+        senders = [
+            { "name":"h16", "device":"of:0000000000000006/8", "mac":"00:00:00:00:00:10" },
+            { "name":"h24", "device":"of:0000000000000007/8", "mac":"00:00:00:00:00:18" }
+        ]
+        recipients = [
+            { "name":"h8", "device":"of:0000000000000005/8", "mac":"00:00:00:00:00:08" }
+        ]
+        badSenders=[ { "name":"h17" } ]  # Senders that are not in the intent
+        badRecipients=[ { "name":"h9" } ]  # Recipients that are not in the intent
+        testResult = main.FALSE
+        installResult = main.intentFunction.installMultiToSingleIntent(
                                          main,
                                          name="IPV4",
-                                         hostNames=hostNames,
-                                         devices=devices,
-                                         ports=None,
+                                         senders=senders,
+                                         recipients=recipients,
                                          ethType="IPV4",
-                                         macs=macs,
-                                         bandwidth="",
-                                         lambdaAlloc=False,
-                                         ipProto="",
-                                         ipAddresses="",
-                                         tcp="",
+                                         sw1="s5",
+                                         sw2="s2")
+
+        if installResult:
+            testResult = main.intentFunction.testPointIntent(
+                                         main,
+                                         intentId=installResult,
+                                         name="IPV4",
+                                         senders=senders,
+                                         recipients=recipients,
+                                         badSenders=badSenders,
+                                         badRecipients=badRecipients,
                                          sw1="s5",
                                          sw2="s2",
-                                         expectedLink=18 )
+                                         expectedLink=18)
 
         utilities.assert_equals( expect=main.TRUE,
-                                 actual=stepResult,
+                                 actual=testResult,
                                  onpass=main.assertReturnString,
                                  onfail=main.assertReturnString )
 
         main.step( "IPV4_2: Add multi point to single point intents" )
         main.assertReturnString = "Assertion results for IPV4 multi to single point intent with IPV4 type and no MAC addresses\n"
-        hostNames = [ 'h8', 'h16', 'h24' ]
-        stepResult = main.intentFunction.multiToSingleIntent(
+        senders = [
+            { "name":"h16", "device":"of:0000000000000006/8" },
+            { "name":"h24", "device":"of:0000000000000007/8" }
+        ]
+        recipients = [
+            { "name":"h8", "device":"of:0000000000000005/8" }
+        ]
+        badSenders=[ { "name":"h17" } ]  # Senders that are not in the intent
+        badRecipients=[ { "name":"h9" } ]  # Recipients that are not in the intent
+        testResult = main.FALSE
+        installResult = main.intentFunction.installMultiToSingleIntent(
                                          main,
-                                         name="IPV4",
-                                         hostNames=hostNames,
+                                         name="IPV4_2",
+                                         senders=senders,
+                                         recipients=recipients,
                                          ethType="IPV4",
-                                         lambdaAlloc=False )
+                                         sw1="s5",
+                                         sw2="s2")
+
+        if installResult:
+            testResult = main.intentFunction.testPointIntent(
+                                         main,
+                                         intentId=installResult,
+                                         name="IPV4_2",
+                                         senders=senders,
+                                         recipients=recipients,
+                                         badSenders=badSenders,
+                                         badRecipients=badRecipients,
+                                         sw1="s5",
+                                         sw2="s2",
+                                         expectedLink=18)
 
         utilities.assert_equals( expect=main.TRUE,
-                                 actual=stepResult,
+                                 actual=testResult,
                                  onpass=main.assertReturnString,
                                  onfail=main.assertReturnString )
 
         main.step( "VLAN: Add multi point to single point intents" )
         main.assertReturnString = "Assertion results for IPV4 multi to single point intent with IPV4 type and no MAC addresses in the same VLAN\n"
-        hostNames = [ 'h5', 'h13', 'h21' ]
-        devices = [ 'of:0000000000000005/5', 'of:0000000000000006/5', \
-                    'of:0000000000000007/5' ]
-        macs = [ '00:00:00:00:00:05', '00:00:00:00:00:0D', '00:00:00:00:00:15' ]
-        stepResult = main.intentFunction.multiToSingleIntent(
+        senders = [
+            { "name":"h13", "device":"of:0000000000000006/5" },
+            { "name":"h21", "device":"of:0000000000000007/5" }
+        ]
+        recipients = [
+            { "name":"h5", "device":"of:0000000000000005/5" }
+        ]
+        badSenders=[ { "name":"h12" } ]  # Senders that are not in the intent
+        badRecipients=[ { "name":"h20" } ]  # Recipients that are not in the intent
+        testResult = main.FALSE
+        installResult = main.intentFunction.installMultiToSingleIntent(
                                          main,
                                          name="VLAN",
-                                         hostNames=hostNames,
-                                         devices=devices,
-                                         ports=None,
+                                         senders=senders,
+                                         recipients=recipients,
                                          ethType="IPV4",
-                                         macs=macs,
-                                         bandwidth="",
-                                         lambdaAlloc=False,
-                                         ipProto="",
-                                         ipAddresses="",
-                                         tcp="",
+                                         sw1="s5",
+                                         sw2="s2")
+
+        if installResult:
+            testResult = main.intentFunction.testPointIntent(
+                                         main,
+                                         intentId=installResult,
+                                         name="VLAN",
+                                         senders=senders,
+                                         recipients=recipients,
+                                         badSenders=badSenders,
+                                         badRecipients=badRecipients,
                                          sw1="s5",
                                          sw2="s2",
-                                         expectedLink=18 )
+                                         expectedLink=18)
 
         utilities.assert_equals( expect=main.TRUE,
-                                 actual=stepResult,
+                                 actual=testResult,
                                  onpass=main.assertReturnString,
                                  onfail=main.assertReturnString )
 
+        main.intentFunction.report( main )
+
     def CASE5000( self, main ):
         """
         Tests Host Mobility
@@ -1175,14 +1493,23 @@
         assert main.numSwitch, "Placed the total number of switch topology in \
                                 main.numSwitch"
         main.case( "Test host mobility with host intents " )
-        main.step( " Testing host mobility by moving h1 from s5 to s6" )
+        main.step( "Testing host mobility by moving h1 from s5 to s6" )
         h1PreMove = main.hostsData[ "h1" ][ "location" ][ 0:19 ]
 
         main.log.info( "Moving h1 from s5 to s6")
-
         main.Mininet1.moveHost( "h1","s5","s6" )
 
-        main.intentFunction.getHostsData( main )
+        # Send discovery ping from moved host
+        # Moving the host brings down the default interfaces and creates a new one.
+        # Scapy is restarted on this host to detect the new interface
+        main.h1.stopScapy()
+        main.h1.startScapy()
+
+        # Discover new host location in ONOS and populate host data.
+        # Host 1 IP and MAC should be unchanged
+        main.intentFunction.sendDiscoveryArp( main, [ main.h1 ] )
+        main.intentFunction.populateHostData( main )
+
         h1PostMove = main.hostsData[ "h1" ][ "location" ][ 0:19 ]
 
         utilities.assert_equals( expect="of:0000000000000006",
@@ -1195,16 +1522,27 @@
 
         main.step( "IPV4: Add host intents between h1 and h9" )
         main.assertReturnString = "Assert result for IPV4 host intent between h1, moved, and h9\n"
-        stepResult = main.intentFunction.hostIntent( main,
+        host1 = { "name":"h1","id":"00:00:00:00:00:01/-1" }
+        host2 = { "name":"h9","id":"00:00:00:00:00:09/-1" }
+
+        installResult = main.intentFunction.installHostIntent( main,
+                                              name='IPV4 Mobility IPV4',
                                               onosNode='0',
-                                              name='IPV4',
-                                              host1='h1',
-                                              host2='h9',
-                                              host1Id='00:00:00:00:00:01/-1',
-                                              host2Id='00:00:00:00:00:09/-1' )
+                                              host1=host1,
+                                              host2=host2)
+
+        testResult = main.intentFunction.testHostIntent( main,
+                                              name='Host Mobility IPV4',
+                                              intentId = installResult,
+                                              onosNode='0',
+                                              host1=host1,
+                                              host2=host2,
+                                              sw1="s6",
+                                              sw2="s2",
+                                              expectedLink=18 )
 
         utilities.assert_equals( expect=main.TRUE,
-                                 actual=stepResult,
+                                 actual=testResult,
                                  onpass=main.assertReturnString,
                                  onfail=main.assertReturnString )
 
diff --git a/TestON/tests/FUNCintent/FUNCintent.topo b/TestON/tests/FUNCintent/FUNCintent.topo
index 617e8c0..46dc357 100755
--- a/TestON/tests/FUNCintent/FUNCintent.topo
+++ b/TestON/tests/FUNCintent/FUNCintent.topo
@@ -46,9 +46,17 @@
             <type>MininetCliDriver</type>
             <connect_order>5</connect_order>
             <COMPONENTS>
-                <home>~/mininet/custom/</home>
+                <home>~/mininet/</home>
             </COMPONENTS>
         </Mininet1>
 
+        <Scapy1>
+            <host>OCN</host>
+            <user>admin</user>
+            <password></password>
+            <type>ScapyCliDriver</type>
+            <connect_order>6</connect_order>
+        </Scapy1>
+
     </COMPONENT>
 </TOPOLOGY>