diff --git a/dts/framework/remote_session/remote/testpmd_shell.py b/dts/framework/remote_session/remote/testpmd_shell.py
index 1455b5a199..4feed3bdb8 100644
--- a/dts/framework/remote_session/remote/testpmd_shell.py
+++ b/dts/framework/remote_session/remote/testpmd_shell.py
@@ -3,6 +3,8 @@
 
 from pathlib import PurePath
 from typing import Callable
+from framework.settings import SETTINGS
+import time
 
 from .interactive_shell import InteractiveShell
 
@@ -29,7 +31,7 @@ def _start_application(
         self, get_privileged_command: Callable[[str], str] | None
     ) -> None:
         """See "_start_application" in InteractiveShell."""
-        self._app_args += " -- -i"
+        self._app_args += " -i"
         super()._start_application(get_privileged_command)
 
     def get_devices(self) -> list[TestPmdDevice]:
@@ -47,3 +49,29 @@ def get_devices(self) -> list[TestPmdDevice]:
             if "device name:" in line.lower():
                 dev_list.append(TestPmdDevice(line))
         return dev_list
+
+    def wait_link_status_up(self, port_id: int, timeout=SETTINGS.timeout) -> bool:
+        """Wait until the link status on the given port is "up".
+
+        Arguments:
+            port_id: Port to check the link status on.
+            timeout: time to wait for the link to come up.
+
+        Returns:
+            If the link came up in time or not.
+        """
+        time_to_stop = time.time() + timeout
+        while time.time() < time_to_stop:
+            port_info = self.send_command(f"show port info {port_id}")
+            if "Link status: up" in port_info:
+                break
+            time.sleep(0.5)
+        else:
+            self._logger.error(
+                f"The link for port {port_id} did not come up in the given timeout."
+            )
+        return "Link status: up" in port_info
+
+    def close(self) -> None:
+        self.send_command("exit", "")
+        return super().close()
diff --git a/dts/framework/testbed_model/__init__.py b/dts/framework/testbed_model/__init__.py
index 5cbb859e47..ead25aea8e 100644
--- a/dts/framework/testbed_model/__init__.py
+++ b/dts/framework/testbed_model/__init__.py
@@ -17,6 +17,8 @@
     LogicalCoreListFilter,
     VirtualDevice,
     lcore_filter,
+    Port,
+    PortLink
 )
 from .node import Node
 from .sut_node import SutNode
diff --git a/dts/framework/testbed_model/hw/__init__.py b/dts/framework/testbed_model/hw/__init__.py
index 88ccac0b0e..5719af2017 100644
--- a/dts/framework/testbed_model/hw/__init__.py
+++ b/dts/framework/testbed_model/hw/__init__.py
@@ -12,6 +12,7 @@
     LogicalCoreListFilter,
 )
 from .virtual_device import VirtualDevice
+from .port import Port, PortLink
 
 
 def lcore_filter(
diff --git a/dts/framework/testbed_model/hw/port.py b/dts/framework/testbed_model/hw/port.py
index 680c29bfe3..97cfd01b6b 100644
--- a/dts/framework/testbed_model/hw/port.py
+++ b/dts/framework/testbed_model/hw/port.py
@@ -27,6 +27,7 @@ class Port:
         Example: mlx5_core
 
     peer: The identifier of a port this port is connected with.
+    logical_name: The logical name of the port (e.g. ens162)
     """
 
     identifier: PortIdentifier
@@ -35,6 +36,7 @@ class Port:
     peer: PortIdentifier
     mac_address: str = ""
     logical_name: str = ""
+    _id: int | None
 
     def __init__(self, node_name: str, config: PortConfig):
         self.identifier = PortIdentifier(
@@ -44,6 +46,7 @@ def __init__(self, node_name: str, config: PortConfig):
         self.os_driver = config.os_driver
         self.os_driver_for_dpdk = config.os_driver_for_dpdk
         self.peer = PortIdentifier(node=config.peer_node, pci=config.peer_pci)
+        self._id = None
 
     @property
     def node(self) -> str:
@@ -53,6 +56,12 @@ def node(self) -> str:
     def pci(self) -> str:
         return self.identifier.pci
 
+    @property
+    def id(self) -> int:
+        if self._id is None:
+            self._id = self.pci.split(".")[-1]
+        return self._id
+
 
 @dataclass(slots=True, frozen=True)
 class PortLink:
diff --git a/dts/framework/testbed_model/sut_node.py b/dts/framework/testbed_model/sut_node.py
index 202aebfd06..8779c1e1b0 100644
--- a/dts/framework/testbed_model/sut_node.py
+++ b/dts/framework/testbed_model/sut_node.py
@@ -360,6 +360,7 @@ def create_interactive_shell(
         timeout: float = SETTINGS.timeout,
         privileged: bool = False,
         eal_parameters: EalParameters | str | None = None,
+        app_parameters: str | None = None
     ) -> InteractiveShellType:
         """Factory method for creating a handler for an interactive session.
 
@@ -374,6 +375,8 @@ def create_interactive_shell(
             eal_parameters: List of EAL parameters to use to launch the app. If this
                 isn't provided or an empty string is passed, it will default to calling
                 create_eal_parameters().
+            app_parameters: Additional arguments to pass into the application on the
+                command-line.
         Returns:
             Instance of the desired interactive application.
         """
@@ -387,5 +390,5 @@ def create_interactive_shell(
             )
 
         return super().create_interactive_shell(
-            shell_cls, timeout, privileged, str(eal_parameters)
+            shell_cls, timeout, privileged, f"{eal_parameters} -- {app_parameters}"
         )
diff --git a/dts/tests/TestSuite_scatter.py b/dts/tests/TestSuite_scatter.py
new file mode 100644
index 0000000000..898d56e288
--- /dev/null
+++ b/dts/tests/TestSuite_scatter.py
@@ -0,0 +1,62 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2023 University of New Hampshire
+
+from framework.test_suite import TestSuite
+from framework.testbed_model import PortLink
+from framework.remote_session import TestPmdShell
+
+
+class Scatter(TestSuite):
+    port_link_for_testing: PortLink
+    mbsize: int
+
+    def set_up_suite(self) -> None:
+        self.verify(
+            len(self._port_links) > 0,
+            "Must have at least one port link to run scatter"
+        )
+        self.port_link_for_testing = self._port_links[0]
+        self.mbsize = 1024  # TODO: make this 2048 for some NICs like in old DTS
+        self.tg_node.main_session.send_command(
+            f"ifconfig {self.port_link_for_testing.tg_port.logical_name} mtu 9000"
+        )
+
+    def scatter_pktgen_send_packet(self, pktsize: int) -> None:
+        """Generate and send packet to the SUT.
+
+        Functional test for scatter packets.
+
+        Args:
+            pktsize: Size of the packet to generate and send.
+        """
+        dest_mac = self.port_link_for_testing.sut_port.mac_address
+        # TODO: Need to create the packet and then send it and receive
+
+    def test_scatter_mbuf_2048(self) -> None:
+        """
+        Test:
+            Start testpmd and run functional test with preset mbsize.
+        """
+        testpmd = self.sut_node.create_interactive_shell(
+            TestPmdShell,
+            app_parameters=f"--mbcache=200 \
+                            --mbuf-size={self.mbsize} \
+                            --portmask=0x1 \
+                            --max-pkt-len=9000 \
+                            --port-topology=loop \
+                            --tx-offloads=0x00008000"
+        )
+        testpmd.send_command("set fwd mac")
+        testpmd.send_command("start")
+        link_is_up = testpmd.wait_link_status_up(self.port_link_for_testing.sut_port.id)
+        self.verify(link_is_up, "Link never came up in TestPMD.")
+
+        for offset in [-1, 0, 1, 4, 5]:
+            self.scatter_pktgen_send_packet(self.mbsize + offset)
+
+        testpmd.send_command("stop")
+
+    def tear_down_suite(self) -> None:
+        self.tg_node.main_session.send_command(
+            f"ifconfig {self.port_link_for_testing.tg_port.logical_name} mtu 1500"
+        )
