Soft Patch Panel
 help / color / mirror / Atom feed
* [spp] [PATCH 00/15] Add SPP container tools
@ 2018-06-15  8:37 ogawa.yasufumi
  2018-06-15  8:37 ` [spp] [PATCH 01/15] tools/sppc: add SPP container build tool ogawa.yasufumi
                   ` (15 more replies)
  0 siblings, 16 replies; 17+ messages in thread
From: ogawa.yasufumi @ 2018-06-15  8:37 UTC (permalink / raw)
  To: ferruh.yigit, spp; +Cc: Yasufumi Ogawa

From: Yasufumi Ogawa <ogawa.yasufumi@lab.ntt.co.jp>

This series of patches is to add SPP container. It consists of build
tool and app container launcher scripts.

Build tool is for creating container image and install DPDK and
applications on the image. It also includes Dockerfiles of several
versions of DPDK and Ubuntu.

App container scripts for launching app container with simple command
line interfaces.


Yasufumi Ogawa (15):
  tools/sppc: add SPP container build tool
  tools/sppc: add dockerfiles for DPDK
  tools/sppc: add dockerfiles for pktgen
  tools/sppc: add dockerfiles for SPP
  tools/sppc: add spp-primary app continer
  tools/sppc: add spp-nfv app continer
  tools/sppc: add spp-vm app continer
  tools/sppc: add l2fwd app continer
  tools/sppc: add testpmd app continer
  tools/sppc: add l3fwd app continer
  tools/sppc: add pktgen app continer
  tools/sppc: add load-balancer app continer
  tools/sppc: add helloworld app continer
  tools/sppc: add helper script for build
  tools/sppc: add spp launcher script

 .gitignore                                    |   1 +
 tools/sppc/app/__init__.py                    |   0
 tools/sppc/app/helloworld.py                  |  75 ++
 tools/sppc/app/l2fwd.py                       |  96 ++
 tools/sppc/app/l3fwd.py                       | 292 ++++++
 tools/sppc/app/load-balancer.py               | 141 +++
 tools/sppc/app/pktgen.py                      | 182 ++++
 tools/sppc/app/spp-nfv.py                     | 127 +++
 tools/sppc/app/spp-primary.py                 | 171 ++++
 tools/sppc/app/spp-vm.py                      | 107 +++
 tools/sppc/app/testpmd.py                     | 857 ++++++++++++++++++
 tools/sppc/build/main.py                      | 188 ++++
 tools/sppc/build/run.sh                       |  34 +
 tools/sppc/build/ubuntu/dpdk/Dockerfile.16.04 |  44 +
 tools/sppc/build/ubuntu/dpdk/Dockerfile.18.04 |  44 +
 .../sppc/build/ubuntu/dpdk/Dockerfile.latest  |  44 +
 .../sppc/build/ubuntu/pktgen/Dockerfile.16.04 |  48 +
 .../sppc/build/ubuntu/pktgen/Dockerfile.18.04 |  48 +
 .../build/ubuntu/pktgen/Dockerfile.latest     |  48 +
 tools/sppc/build/ubuntu/spp/Dockerfile.16.04  |  47 +
 tools/sppc/build/ubuntu/spp/Dockerfile.18.04  |  47 +
 tools/sppc/build/ubuntu/spp/Dockerfile.latest |  47 +
 tools/sppc/conf/__init__.py                   |   0
 tools/sppc/conf/env.py                        |  13 +
 tools/sppc/lib/__init__.py                    |   0
 tools/sppc/lib/app_helper.py                  | 269 ++++++
 tools/sppc/lib/common.py                      |  30 +
 tools/sppc/tools/spp-launcher.py              |  96 ++
 28 files changed, 3096 insertions(+)
 create mode 100644 tools/sppc/app/__init__.py
 create mode 100755 tools/sppc/app/helloworld.py
 create mode 100755 tools/sppc/app/l2fwd.py
 create mode 100755 tools/sppc/app/l3fwd.py
 create mode 100755 tools/sppc/app/load-balancer.py
 create mode 100755 tools/sppc/app/pktgen.py
 create mode 100755 tools/sppc/app/spp-nfv.py
 create mode 100755 tools/sppc/app/spp-primary.py
 create mode 100755 tools/sppc/app/spp-vm.py
 create mode 100755 tools/sppc/app/testpmd.py
 create mode 100755 tools/sppc/build/main.py
 create mode 100755 tools/sppc/build/run.sh
 create mode 100644 tools/sppc/build/ubuntu/dpdk/Dockerfile.16.04
 create mode 100644 tools/sppc/build/ubuntu/dpdk/Dockerfile.18.04
 create mode 100644 tools/sppc/build/ubuntu/dpdk/Dockerfile.latest
 create mode 100644 tools/sppc/build/ubuntu/pktgen/Dockerfile.16.04
 create mode 100644 tools/sppc/build/ubuntu/pktgen/Dockerfile.18.04
 create mode 100644 tools/sppc/build/ubuntu/pktgen/Dockerfile.latest
 create mode 100644 tools/sppc/build/ubuntu/spp/Dockerfile.16.04
 create mode 100644 tools/sppc/build/ubuntu/spp/Dockerfile.18.04
 create mode 100644 tools/sppc/build/ubuntu/spp/Dockerfile.latest
 create mode 100644 tools/sppc/conf/__init__.py
 create mode 100644 tools/sppc/conf/env.py
 create mode 100644 tools/sppc/lib/__init__.py
 create mode 100644 tools/sppc/lib/app_helper.py
 create mode 100644 tools/sppc/lib/common.py
 create mode 100755 tools/sppc/tools/spp-launcher.py

-- 
2.17.1

^ permalink raw reply	[flat|nested] 17+ messages in thread

* [spp] [PATCH 01/15] tools/sppc: add SPP container build tool
  2018-06-15  8:37 [spp] [PATCH 00/15] Add SPP container tools ogawa.yasufumi
@ 2018-06-15  8:37 ` ogawa.yasufumi
  2018-06-15  8:37 ` [spp] [PATCH 02/15] tools/sppc: add dockerfiles for DPDK ogawa.yasufumi
                   ` (14 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: ogawa.yasufumi @ 2018-06-15  8:37 UTC (permalink / raw)
  To: ferruh.yigit, spp; +Cc: Yasufumi Ogawa

From: Yasufumi Ogawa <ogawa.yasufumi@lab.ntt.co.jp>

Build tool is used for creating docker image. It consists of main
script and common libraries.

  * build/main.py
  * lib/common.py
  * conf/env.py

You can specify the versions of DPDK or other applications and
repository if you need. You can also specify Linux distribution and its
version.

  $ python build/build.py --dpdk-branch v18.02 \
    --spp-repo https://github.com/your/spp.git

'env.py' defines environmental variables used on the container image.

Signed-off-by: Yasufumi Ogawa <ogawa.yasufumi@lab.ntt.co.jp>
---
 tools/sppc/build/main.py    | 188 ++++++++++++++++++++++++++++++++++++
 tools/sppc/conf/__init__.py |   0
 tools/sppc/conf/env.py      |  13 +++
 tools/sppc/lib/__init__.py  |   0
 tools/sppc/lib/common.py    |  30 ++++++
 5 files changed, 231 insertions(+)
 create mode 100755 tools/sppc/build/main.py
 create mode 100644 tools/sppc/conf/__init__.py
 create mode 100644 tools/sppc/conf/env.py
 create mode 100644 tools/sppc/lib/__init__.py
 create mode 100644 tools/sppc/lib/common.py

diff --git a/tools/sppc/build/main.py b/tools/sppc/build/main.py
new file mode 100755
index 0000000..d33a6f2
--- /dev/null
+++ b/tools/sppc/build/main.py
@@ -0,0 +1,188 @@
+#!/usr/bin/env python
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2018 Nippon Telegraph and Telephone Corporation
+
+from __future__ import absolute_import
+import argparse
+import os
+import subprocess
+import sys
+
+work_dir = os.path.dirname(__file__)
+sys.path.append(work_dir + '/..')
+from lib import common
+from conf import env
+
+
+def parse_args():
+    parser = argparse.ArgumentParser(
+        description="Docker image builder for DPDK applications")
+    parser.add_argument(
+        '-t', '--target',
+        type=str,
+        help="Build target ('dpdk', 'pktgen' or 'spp')")
+    parser.add_argument(
+        '-ci', '--container-image',
+        type=str,
+        help="Name of container image")
+    parser.add_argument(
+        '--dist-name',
+        type=str,
+        default='ubuntu',
+        help="Name of Linux distribution")
+    parser.add_argument(
+        '--dist-ver',
+        type=str,
+        default='latest',
+        help="Version of Linux distribution")
+    parser.add_argument(
+        '--dpdk-repo',
+        type=str,
+        default="http://dpdk.org/git/dpdk",
+        help="Git URL of DPDK")
+    parser.add_argument(
+        '--dpdk-branch',
+        type=str,
+        help="Specific version or branch of DPDK")
+    parser.add_argument(
+        '--pktgen-repo',
+        type=str,
+        default="http://dpdk.org/git/apps/pktgen-dpdk",
+        help="Git URL of pktgen-dpdk")
+    parser.add_argument(
+        '--pktgen-branch',
+        type=str,
+        help="Specific version or branch of pktgen-dpdk")
+    parser.add_argument(
+        '--spp-repo',
+        type=str,
+        default="http://dpdk.org/git/apps/spp",
+        help="Git URL of SPP")
+    parser.add_argument(
+        '--spp-branch',
+        type=str,
+        help="Specific version or branch of SPP")
+    parser.add_argument(
+        '--only-envsh',
+        action='store_true',
+        help="Create config 'env.sh' and exit without docker build")
+    parser.add_argument(
+        '--dry-run',
+        action='store_true',
+        help="Print matrix for checking and exit without docker build")
+    return parser.parse_args()
+
+
+def create_env_sh(dst_dir):
+    """Create config file for DPDK environment variables
+
+    Create 'env.sh' which defines $RTE_SDK and $RTE_TARGET inside a
+    container to be referredd from 'run.sh' and Dockerfile.
+    """
+    contents = "export RTE_SDK=%s\n" % env.RTE_SDK
+    contents += "export RTE_TARGET=%s" % env.RTE_TARGET
+
+    f = open('%s/env.sh' % dst_dir, 'w')
+    f.write(contents)
+    f.close()
+
+
+def main():
+    args = parse_args()
+
+    if args.target is not None:
+        target_dir = '%s/%s/%s' % (  # Dockerfile is contained here
+            work_dir, args.dist_name, args.target)
+        # Container image name, for exp 'sppc/dpdk-ubuntu:18.04'
+        container_image = common.container_img_name(
+            env.CONTAINER_IMG_NAME[args.target],
+            args.dist_name,
+            args.dist_ver)
+    else:
+        print("Error: Target '-t [dpdk|pktgen|spp]' is required!")
+        exit()
+
+    # Decide which of Dockerfile with given base image version
+    dockerfile = '%s/Dockerfile.%s' % (target_dir, args.dist_ver)
+
+    # Overwrite container's name if it is given.
+    if args.container_image is not None:
+        container_image = args.container_image
+
+    # Setup branches if user specifies.
+    if args.dpdk_branch is not None:
+        dpdk_branch = "-b %s" % args.dpdk_branch
+    else:
+        dpdk_branch = ''
+
+    if args.pktgen_branch is not None:
+        pktgen_branch = "-b %s" % args.pktgen_branch
+    else:
+        pktgen_branch = ''
+
+    if args.spp_branch is not None:
+        spp_branch = "-b %s" % args.spp_branch
+    else:
+        spp_branch = ''
+
+    # Check for just creating env.sh, or run docker build.
+    if args.only_envsh is True:
+        if args.dry_run is False:
+            create_env_sh(target_dir)
+            print("Info: '%s/env.sh' created." % target_dir)
+            exit()
+        else:
+            print("Info: Nothin done because you gave %s with %s." % (
+                '--only-envsh', '--dry-run'))
+            exit()
+    else:
+        create_env_sh(target_dir)
+
+    # Setup environment variables on host to pass 'docker build'.
+    env_opts = [
+        'http_proxy',
+        'https_proxy',
+        'no_proxy'
+    ]
+
+    docker_cmd = ['sudo', 'docker', 'build', '\\']
+
+    for opt in env_opts:
+        if opt in os.environ.keys():
+            docker_cmd += [
+                '--build-arg', '%s=%s' % (opt, os.environ[opt]), '\\']
+
+    docker_cmd += [
+        '--build-arg', 'home_dir=%s' % env.HOMEDIR, '\\',
+        '--build-arg', 'rte_sdk=%s' % env.RTE_SDK, '\\',
+        '--build-arg', 'rte_target=%s' % env.RTE_TARGET, '\\',
+        '--build-arg', 'dpdk_repo=%s' % args.dpdk_repo, '\\',
+        '--build-arg', 'dpdk_branch=%s' % dpdk_branch, '\\']
+
+    if args.target == 'pktgen':
+        docker_cmd += [
+            '--build-arg', 'pktgen_repo=%s' % args.pktgen_repo, '\\',
+            '--build-arg', 'pktgen_branch=%s' % pktgen_branch, '\\']
+    elif args.target == 'spp':
+        docker_cmd += [
+            '--build-arg', 'spp_repo=%s' % args.spp_repo, '\\',
+            '--build-arg', 'spp_branch=%s' % spp_branch, '\\']
+
+    docker_cmd += [
+        '-f', '%s' % dockerfile, '\\',
+        '-t', container_image, '\\',
+        target_dir]
+
+    common.print_pretty_commands(docker_cmd)
+
+    if args.dry_run is True:
+        exit()
+
+    # Remove delimiters for print_pretty_commands().
+    while '\\' in docker_cmd:
+        docker_cmd.remove('\\')
+    subprocess.call(docker_cmd)
+
+
+if __name__ == '__main__':
+    main()
diff --git a/tools/sppc/conf/__init__.py b/tools/sppc/conf/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/tools/sppc/conf/env.py b/tools/sppc/conf/env.py
new file mode 100644
index 0000000..f6df15a
--- /dev/null
+++ b/tools/sppc/conf/env.py
@@ -0,0 +1,13 @@
+#!/usr/bin/env python
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2018 Nippon Telegraph and Telephone Corporation
+
+
+HOMEDIR = '/root'
+RTE_SDK = '/root/dpdk'
+RTE_TARGET = 'x86_64-native-linuxapp-gcc'
+
+CONTAINER_IMG_NAME = {
+    'dpdk': 'sppc/dpdk',
+    'pktgen': 'sppc/pktgen',
+    'spp': 'sppc/spp'}
diff --git a/tools/sppc/lib/__init__.py b/tools/sppc/lib/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/tools/sppc/lib/common.py b/tools/sppc/lib/common.py
new file mode 100644
index 0000000..7102d43
--- /dev/null
+++ b/tools/sppc/lib/common.py
@@ -0,0 +1,30 @@
+#!/usr/bin/env python
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2018 Nippon Telegraph and Telephone Corporation
+
+
+def print_pretty_commands(cmds):
+    """Print given command in pretty format"""
+
+    print(' '.join(cmds).replace('\\', '\\\n'))
+
+
+def container_img_name(base, dist_name, dist_ver):
+    """Generate container image name
+
+    Return the name of container image for '-t' of docker command
+    such as 'sppc/dpdk-ubuntu:16.04' or 'sppc/spp-ubuntu:18.04'.
+    'base' is defined as 'env.CONTAINER_IMG_NAME' in lib module.
+    """
+    return '%s-%s:%s' % (base, dist_name, dist_ver)
+
+
+def error_exit(objname):
+    """Print error message and exit
+
+    This function is used for notifying an argument for the object
+    is not given.
+    """
+
+    print('Error: \'%s\' is not defined.' % objname)
+    exit()
-- 
2.17.1

^ permalink raw reply	[flat|nested] 17+ messages in thread

* [spp] [PATCH 02/15] tools/sppc: add dockerfiles for DPDK
  2018-06-15  8:37 [spp] [PATCH 00/15] Add SPP container tools ogawa.yasufumi
  2018-06-15  8:37 ` [spp] [PATCH 01/15] tools/sppc: add SPP container build tool ogawa.yasufumi
@ 2018-06-15  8:37 ` ogawa.yasufumi
  2018-06-15  8:37 ` [spp] [PATCH 03/15] tools/sppc: add dockerfiles for pktgen ogawa.yasufumi
                   ` (13 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: ogawa.yasufumi @ 2018-06-15  8:37 UTC (permalink / raw)
  To: ferruh.yigit, spp; +Cc: Yasufumi Ogawa

From: Yasufumi Ogawa <ogawa.yasufumi@lab.ntt.co.jp>

Add Dockerfiles for installing DPDK on Ubuntu image. The number of
versions means the versions of distribution. Build tool understand that
which of Dockerfile should be used with given options.

Signed-off-by: Yasufumi Ogawa <ogawa.yasufumi@lab.ntt.co.jp>
---
 .gitignore                                    |  1 +
 tools/sppc/build/ubuntu/dpdk/Dockerfile.16.04 | 44 +++++++++++++++++++
 tools/sppc/build/ubuntu/dpdk/Dockerfile.18.04 | 44 +++++++++++++++++++
 .../sppc/build/ubuntu/dpdk/Dockerfile.latest  | 44 +++++++++++++++++++
 4 files changed, 133 insertions(+)
 create mode 100644 tools/sppc/build/ubuntu/dpdk/Dockerfile.16.04
 create mode 100644 tools/sppc/build/ubuntu/dpdk/Dockerfile.18.04
 create mode 100644 tools/sppc/build/ubuntu/dpdk/Dockerfile.latest

diff --git a/.gitignore b/.gitignore
index e2c6c1e..ff9ba64 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,3 +3,4 @@
 *.log
 docs/guides/_build/*
 src/controller/3rd_party/*
+tools/sppc/build/*/*/env.sh
diff --git a/tools/sppc/build/ubuntu/dpdk/Dockerfile.16.04 b/tools/sppc/build/ubuntu/dpdk/Dockerfile.16.04
new file mode 100644
index 0000000..b4b3681
--- /dev/null
+++ b/tools/sppc/build/ubuntu/dpdk/Dockerfile.16.04
@@ -0,0 +1,44 @@
+FROM ubuntu:16.04
+
+ARG rte_sdk
+ARG rte_target
+ARG home_dir
+ARG dpdk_repo
+ARG dpdk_branch
+
+ENV PATH ${rte_sdk}/${rte_target}/app:${PATH}
+ENV http_proxy ${http_proxy}
+ENV https_proxy $https_proxy
+ENV no_proxy ${no_proxy}
+ENV RTE_SDK ${rte_sdk}
+ENV RTE_TARGET ${rte_target}
+
+
+RUN apt-get update && apt-get install -y \
+    git \
+    gcc \
+    python \
+    pciutils \
+    make \
+    libnuma-dev \
+    gcc-multilib \
+    libarchive-dev \
+    linux-headers-$(uname -r) \
+    libpcap-dev \
+    pkg-config \
+    && apt-get clean \
+    && rm -rf /var/lib/apt/lists/*
+
+WORKDIR $home_dir
+RUN git clone $dpdk_branch $dpdk_repo
+
+# Compile DPDK
+WORKDIR $rte_sdk
+RUN make install T=$rte_target
+RUN make app T=$rte_target
+RUN make examples T=$rte_target
+
+# Set working directory when container is launched
+WORKDIR ${home_dir}
+ADD env.sh ${home_dir}/env.sh
+RUN echo "source ${home_dir}/env.sh" >> ${home_dir}/.bashrc
diff --git a/tools/sppc/build/ubuntu/dpdk/Dockerfile.18.04 b/tools/sppc/build/ubuntu/dpdk/Dockerfile.18.04
new file mode 100644
index 0000000..16fcf39
--- /dev/null
+++ b/tools/sppc/build/ubuntu/dpdk/Dockerfile.18.04
@@ -0,0 +1,44 @@
+FROM ubuntu:18.04
+
+ARG rte_sdk
+ARG rte_target
+ARG home_dir
+ARG dpdk_repo
+ARG dpdk_branch
+
+ENV PATH ${rte_sdk}/${rte_target}/app:${PATH}
+ENV http_proxy ${http_proxy}
+ENV https_proxy $https_proxy
+ENV no_proxy ${no_proxy}
+ENV RTE_SDK ${rte_sdk}
+ENV RTE_TARGET ${rte_target}
+
+
+RUN apt-get update && apt-get install -y \
+    git \
+    gcc \
+    python \
+    pciutils \
+    make \
+    libnuma-dev \
+    gcc-multilib \
+    libarchive-dev \
+    linux-headers-$(uname -r) \
+    libpcap-dev \
+    pkg-config \
+    && apt-get clean \
+    && rm -rf /var/lib/apt/lists/*
+
+WORKDIR $home_dir
+RUN git clone $dpdk_branch $dpdk_repo
+
+# Compile DPDK
+WORKDIR $rte_sdk
+RUN make install T=$rte_target
+RUN make app T=$rte_target
+RUN make examples T=$rte_target
+
+# Set working directory when container is launched
+WORKDIR ${home_dir}
+ADD env.sh ${home_dir}/env.sh
+RUN echo "source ${home_dir}/env.sh" >> ${home_dir}/.bashrc
diff --git a/tools/sppc/build/ubuntu/dpdk/Dockerfile.latest b/tools/sppc/build/ubuntu/dpdk/Dockerfile.latest
new file mode 100644
index 0000000..832b0e2
--- /dev/null
+++ b/tools/sppc/build/ubuntu/dpdk/Dockerfile.latest
@@ -0,0 +1,44 @@
+FROM ubuntu:latest
+
+ARG rte_sdk
+ARG rte_target
+ARG home_dir
+ARG dpdk_repo
+ARG dpdk_branch
+
+ENV PATH ${rte_sdk}/${rte_target}/app:${PATH}
+ENV http_proxy ${http_proxy}
+ENV https_proxy $https_proxy
+ENV no_proxy ${no_proxy}
+ENV RTE_SDK ${rte_sdk}
+ENV RTE_TARGET ${rte_target}
+
+
+RUN apt-get update && apt-get install -y \
+    git \
+    gcc \
+    python \
+    pciutils \
+    make \
+    libnuma-dev \
+    gcc-multilib \
+    libarchive-dev \
+    linux-headers-$(uname -r) \
+    libpcap-dev \
+    pkg-config \
+    && apt-get clean \
+    && rm -rf /var/lib/apt/lists/*
+
+WORKDIR $home_dir
+RUN git clone $dpdk_branch $dpdk_repo
+
+# Compile DPDK
+WORKDIR $rte_sdk
+RUN make install T=$rte_target
+RUN make app T=$rte_target
+RUN make examples T=$rte_target
+
+# Set working directory when container is launched
+WORKDIR ${home_dir}
+ADD env.sh ${home_dir}/env.sh
+RUN echo "source ${home_dir}/env.sh" >> ${home_dir}/.bashrc
-- 
2.17.1

^ permalink raw reply	[flat|nested] 17+ messages in thread

* [spp] [PATCH 03/15] tools/sppc: add dockerfiles for pktgen
  2018-06-15  8:37 [spp] [PATCH 00/15] Add SPP container tools ogawa.yasufumi
  2018-06-15  8:37 ` [spp] [PATCH 01/15] tools/sppc: add SPP container build tool ogawa.yasufumi
  2018-06-15  8:37 ` [spp] [PATCH 02/15] tools/sppc: add dockerfiles for DPDK ogawa.yasufumi
@ 2018-06-15  8:37 ` ogawa.yasufumi
  2018-06-15  8:37 ` [spp] [PATCH 04/15] tools/sppc: add dockerfiles for SPP ogawa.yasufumi
                   ` (12 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: ogawa.yasufumi @ 2018-06-15  8:37 UTC (permalink / raw)
  To: ferruh.yigit, spp; +Cc: Yasufumi Ogawa

From: Yasufumi Ogawa <ogawa.yasufumi@lab.ntt.co.jp>

Add Dockerfiles for installing DPDK and pktgen on Ubuntu image. The
number of versions means the versions of distribution.

Signed-off-by: Yasufumi Ogawa <ogawa.yasufumi@lab.ntt.co.jp>
---
 .../sppc/build/ubuntu/pktgen/Dockerfile.16.04 | 48 +++++++++++++++++++
 .../sppc/build/ubuntu/pktgen/Dockerfile.18.04 | 48 +++++++++++++++++++
 .../build/ubuntu/pktgen/Dockerfile.latest     | 48 +++++++++++++++++++
 3 files changed, 144 insertions(+)
 create mode 100644 tools/sppc/build/ubuntu/pktgen/Dockerfile.16.04
 create mode 100644 tools/sppc/build/ubuntu/pktgen/Dockerfile.18.04
 create mode 100644 tools/sppc/build/ubuntu/pktgen/Dockerfile.latest

diff --git a/tools/sppc/build/ubuntu/pktgen/Dockerfile.16.04 b/tools/sppc/build/ubuntu/pktgen/Dockerfile.16.04
new file mode 100644
index 0000000..e72dc74
--- /dev/null
+++ b/tools/sppc/build/ubuntu/pktgen/Dockerfile.16.04
@@ -0,0 +1,48 @@
+FROM ubuntu:16.04
+
+ARG rte_sdk
+ARG rte_target
+ARG home_dir
+ARG dpdk_repo
+ARG dpdk_branch
+ARG pktgen_repo
+ARG pktgen_branch
+
+ENV PATH ${rte_sdk}/${rte_target}/app:${PATH}
+ENV http_proxy ${http_proxy}
+ENV https_proxy $https_proxy
+ENV no_proxy ${no_proxy}
+ENV RTE_SDK ${rte_sdk}
+ENV RTE_TARGET ${rte_target}
+
+RUN apt-get update && apt-get install -y \
+    git \
+    gcc \
+    python \
+    pciutils \
+    make \
+    libnuma-dev \
+    gcc-multilib \
+    libarchive-dev \
+    linux-headers-$(uname -r) \
+    libpcap-dev \
+    pkg-config \
+    wget \
+    && apt-get clean \
+    && rm -rf /var/lib/apt/lists/*
+
+WORKDIR $home_dir
+RUN git clone $dpdk_branch $dpdk_repo
+RUN git clone $pktgen_branch $pktgen_repo
+
+# Compile DPDK and pktgen
+WORKDIR $rte_sdk
+RUN make install T=$rte_target
+
+WORKDIR ${home_dir}/pktgen-dpdk
+RUN make
+
+# Set working directory when container is launched
+WORKDIR ${home_dir}
+ADD env.sh ${home_dir}/env.sh
+RUN echo "source ${home_dir}/env.sh" >> ${home_dir}/.bashrc
diff --git a/tools/sppc/build/ubuntu/pktgen/Dockerfile.18.04 b/tools/sppc/build/ubuntu/pktgen/Dockerfile.18.04
new file mode 100644
index 0000000..6097fbc
--- /dev/null
+++ b/tools/sppc/build/ubuntu/pktgen/Dockerfile.18.04
@@ -0,0 +1,48 @@
+FROM ubuntu:18.04
+
+ARG rte_sdk
+ARG rte_target
+ARG home_dir
+ARG dpdk_repo
+ARG dpdk_branch
+ARG pktgen_repo
+ARG pktgen_branch
+
+ENV PATH ${rte_sdk}/${rte_target}/app:${PATH}
+ENV http_proxy ${http_proxy}
+ENV https_proxy $https_proxy
+ENV no_proxy ${no_proxy}
+ENV RTE_SDK ${rte_sdk}
+ENV RTE_TARGET ${rte_target}
+
+RUN apt-get update && apt-get install -y \
+    git \
+    gcc \
+    python \
+    pciutils \
+    make \
+    libnuma-dev \
+    gcc-multilib \
+    libarchive-dev \
+    linux-headers-$(uname -r) \
+    libpcap-dev \
+    pkg-config \
+    wget \
+    && apt-get clean \
+    && rm -rf /var/lib/apt/lists/*
+
+WORKDIR $home_dir
+RUN git clone $dpdk_branch $dpdk_repo
+RUN git clone $pktgen_branch $pktgen_repo
+
+# Compile DPDK and pktgen
+WORKDIR $rte_sdk
+RUN make install T=$rte_target
+
+WORKDIR ${home_dir}/pktgen-dpdk
+RUN make
+
+# Set working directory when container is launched
+WORKDIR ${home_dir}
+ADD env.sh ${home_dir}/env.sh
+RUN echo "source ${home_dir}/env.sh" >> ${home_dir}/.bashrc
diff --git a/tools/sppc/build/ubuntu/pktgen/Dockerfile.latest b/tools/sppc/build/ubuntu/pktgen/Dockerfile.latest
new file mode 100644
index 0000000..ae70368
--- /dev/null
+++ b/tools/sppc/build/ubuntu/pktgen/Dockerfile.latest
@@ -0,0 +1,48 @@
+FROM ubuntu:latest
+
+ARG rte_sdk
+ARG rte_target
+ARG home_dir
+ARG dpdk_repo
+ARG dpdk_branch
+ARG pktgen_repo
+ARG pktgen_branch
+
+ENV PATH ${rte_sdk}/${rte_target}/app:${PATH}
+ENV http_proxy ${http_proxy}
+ENV https_proxy $https_proxy
+ENV no_proxy ${no_proxy}
+ENV RTE_SDK ${rte_sdk}
+ENV RTE_TARGET ${rte_target}
+
+RUN apt-get update && apt-get install -y \
+    git \
+    gcc \
+    python \
+    pciutils \
+    make \
+    libnuma-dev \
+    gcc-multilib \
+    libarchive-dev \
+    linux-headers-$(uname -r) \
+    libpcap-dev \
+    pkg-config \
+    wget \
+    && apt-get clean \
+    && rm -rf /var/lib/apt/lists/*
+
+WORKDIR $home_dir
+RUN git clone $dpdk_branch $dpdk_repo
+RUN git clone $pktgen_branch $pktgen_repo
+
+# Compile DPDK and pktgen
+WORKDIR $rte_sdk
+RUN make install T=$rte_target
+
+WORKDIR ${home_dir}/pktgen-dpdk
+RUN make
+
+# Set working directory when container is launched
+WORKDIR ${home_dir}
+ADD env.sh ${home_dir}/env.sh
+RUN echo "source ${home_dir}/env.sh" >> ${home_dir}/.bashrc
-- 
2.17.1

^ permalink raw reply	[flat|nested] 17+ messages in thread

* [spp] [PATCH 04/15] tools/sppc: add dockerfiles for SPP
  2018-06-15  8:37 [spp] [PATCH 00/15] Add SPP container tools ogawa.yasufumi
                   ` (2 preceding siblings ...)
  2018-06-15  8:37 ` [spp] [PATCH 03/15] tools/sppc: add dockerfiles for pktgen ogawa.yasufumi
@ 2018-06-15  8:37 ` ogawa.yasufumi
  2018-06-15  8:37 ` [spp] [PATCH 05/15] tools/sppc: add spp-primary app continer ogawa.yasufumi
                   ` (11 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: ogawa.yasufumi @ 2018-06-15  8:37 UTC (permalink / raw)
  To: ferruh.yigit, spp; +Cc: Yasufumi Ogawa

From: Yasufumi Ogawa <ogawa.yasufumi@lab.ntt.co.jp>

Add Dockerfiles for installing DPDK and SPP on Ubuntu image. The number
of versions means the versions of distribution.

Signed-off-by: Yasufumi Ogawa <ogawa.yasufumi@lab.ntt.co.jp>
---
 tools/sppc/build/ubuntu/spp/Dockerfile.16.04  | 47 +++++++++++++++++++
 tools/sppc/build/ubuntu/spp/Dockerfile.18.04  | 47 +++++++++++++++++++
 tools/sppc/build/ubuntu/spp/Dockerfile.latest | 47 +++++++++++++++++++
 3 files changed, 141 insertions(+)
 create mode 100644 tools/sppc/build/ubuntu/spp/Dockerfile.16.04
 create mode 100644 tools/sppc/build/ubuntu/spp/Dockerfile.18.04
 create mode 100644 tools/sppc/build/ubuntu/spp/Dockerfile.latest

diff --git a/tools/sppc/build/ubuntu/spp/Dockerfile.16.04 b/tools/sppc/build/ubuntu/spp/Dockerfile.16.04
new file mode 100644
index 0000000..cceb7e3
--- /dev/null
+++ b/tools/sppc/build/ubuntu/spp/Dockerfile.16.04
@@ -0,0 +1,47 @@
+FROM ubuntu:16.04
+
+ARG rte_sdk
+ARG rte_target
+ARG home_dir
+ARG dpdk_repo
+ARG dpdk_branch
+ARG spp_repo
+ARG spp_branch
+
+ENV PATH ${rte_sdk}/${rte_target}/app:${PATH}
+ENV http_proxy ${http_proxy}
+ENV https_proxy $https_proxy
+ENV no_proxy ${no_proxy}
+ENV RTE_SDK ${rte_sdk}
+ENV RTE_TARGET ${rte_target}
+
+RUN apt-get update && apt-get install -y \
+    git \
+    gcc \
+    python \
+    pciutils \
+    make \
+    libnuma-dev \
+    gcc-multilib \
+    libarchive-dev \
+    linux-headers-$(uname -r) \
+    libpcap-dev \
+    pkg-config \
+    && apt-get clean \
+    && rm -rf /var/lib/apt/lists/*
+
+WORKDIR $home_dir
+RUN git clone $dpdk_branch $dpdk_repo
+RUN git clone $spp_branch $spp_repo
+
+# Compile DPDK and SPP
+WORKDIR $rte_sdk
+RUN make install T=$rte_target
+
+WORKDIR ${home_dir}/spp
+RUN make
+
+# Set working directory when container is launched
+WORKDIR ${home_dir}
+ADD env.sh ${home_dir}/env.sh
+RUN echo "source ${home_dir}/env.sh" >> ${home_dir}/.bashrc
diff --git a/tools/sppc/build/ubuntu/spp/Dockerfile.18.04 b/tools/sppc/build/ubuntu/spp/Dockerfile.18.04
new file mode 100644
index 0000000..51a0902
--- /dev/null
+++ b/tools/sppc/build/ubuntu/spp/Dockerfile.18.04
@@ -0,0 +1,47 @@
+FROM ubuntu:18.04
+
+ARG rte_sdk
+ARG rte_target
+ARG home_dir
+ARG dpdk_repo
+ARG dpdk_branch
+ARG spp_repo
+ARG spp_branch
+
+ENV PATH ${rte_sdk}/${rte_target}/app:${PATH}
+ENV http_proxy ${http_proxy}
+ENV https_proxy $https_proxy
+ENV no_proxy ${no_proxy}
+ENV RTE_SDK ${rte_sdk}
+ENV RTE_TARGET ${rte_target}
+
+RUN apt-get update && apt-get install -y \
+    git \
+    gcc \
+    python \
+    pciutils \
+    make \
+    libnuma-dev \
+    gcc-multilib \
+    libarchive-dev \
+    linux-headers-$(uname -r) \
+    libpcap-dev \
+    pkg-config \
+    && apt-get clean \
+    && rm -rf /var/lib/apt/lists/*
+
+WORKDIR $home_dir
+RUN git clone $dpdk_branch $dpdk_repo
+RUN git clone $spp_branch $spp_repo
+
+# Compile DPDK and SPP
+WORKDIR $rte_sdk
+RUN make install T=$rte_target
+
+WORKDIR ${home_dir}/spp
+RUN make
+
+# Set working directory when container is launched
+WORKDIR ${home_dir}
+ADD env.sh ${home_dir}/env.sh
+RUN echo "source ${home_dir}/env.sh" >> ${home_dir}/.bashrc
diff --git a/tools/sppc/build/ubuntu/spp/Dockerfile.latest b/tools/sppc/build/ubuntu/spp/Dockerfile.latest
new file mode 100644
index 0000000..3142c11
--- /dev/null
+++ b/tools/sppc/build/ubuntu/spp/Dockerfile.latest
@@ -0,0 +1,47 @@
+FROM ubuntu:latest
+
+ARG rte_sdk
+ARG rte_target
+ARG home_dir
+ARG dpdk_repo
+ARG dpdk_branch
+ARG spp_repo
+ARG spp_branch
+
+ENV PATH ${rte_sdk}/${rte_target}/app:${PATH}
+ENV http_proxy ${http_proxy}
+ENV https_proxy $https_proxy
+ENV no_proxy ${no_proxy}
+ENV RTE_SDK ${rte_sdk}
+ENV RTE_TARGET ${rte_target}
+
+RUN apt-get update && apt-get install -y \
+    git \
+    gcc \
+    python \
+    pciutils \
+    make \
+    libnuma-dev \
+    gcc-multilib \
+    libarchive-dev \
+    linux-headers-$(uname -r) \
+    libpcap-dev \
+    pkg-config \
+    && apt-get clean \
+    && rm -rf /var/lib/apt/lists/*
+
+WORKDIR $home_dir
+RUN git clone $dpdk_branch $dpdk_repo
+RUN git clone $spp_branch $spp_repo
+
+# Compile DPDK and SPP
+WORKDIR $rte_sdk
+RUN make install T=$rte_target
+
+WORKDIR ${home_dir}/spp
+RUN make
+
+# Set working directory when container is launched
+WORKDIR ${home_dir}
+ADD env.sh ${home_dir}/env.sh
+RUN echo "source ${home_dir}/env.sh" >> ${home_dir}/.bashrc
-- 
2.17.1

^ permalink raw reply	[flat|nested] 17+ messages in thread

* [spp] [PATCH 05/15] tools/sppc: add spp-primary app continer
  2018-06-15  8:37 [spp] [PATCH 00/15] Add SPP container tools ogawa.yasufumi
                   ` (3 preceding siblings ...)
  2018-06-15  8:37 ` [spp] [PATCH 04/15] tools/sppc: add dockerfiles for SPP ogawa.yasufumi
@ 2018-06-15  8:37 ` ogawa.yasufumi
  2018-06-15  8:37 ` [spp] [PATCH 06/15] tools/sppc: add spp-nfv " ogawa.yasufumi
                   ` (10 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: ogawa.yasufumi @ 2018-06-15  8:37 UTC (permalink / raw)
  To: ferruh.yigit, spp; +Cc: Yasufumi Ogawa

From: Yasufumi Ogawa <ogawa.yasufumi@lab.ntt.co.jp>

App container launcher is a script for launching application running
on a container. This app container launcher is for SPP primary.

This patch is to add spp-primary app container and helper library used
from app container launcher scripts commonly.

Signed-off-by: Yasufumi Ogawa <ogawa.yasufumi@lab.ntt.co.jp>
---
 tools/sppc/app/__init__.py    |   0
 tools/sppc/app/spp-primary.py | 171 +++++++++++++++++++++
 tools/sppc/lib/app_helper.py  | 269 ++++++++++++++++++++++++++++++++++
 3 files changed, 440 insertions(+)
 create mode 100644 tools/sppc/app/__init__.py
 create mode 100755 tools/sppc/app/spp-primary.py
 create mode 100644 tools/sppc/lib/app_helper.py

diff --git a/tools/sppc/app/__init__.py b/tools/sppc/app/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/tools/sppc/app/spp-primary.py b/tools/sppc/app/spp-primary.py
new file mode 100755
index 0000000..a3fc9f8
--- /dev/null
+++ b/tools/sppc/app/spp-primary.py
@@ -0,0 +1,171 @@
+#!/usr/bin/env python
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2018 Nippon Telegraph and Telephone Corporation
+
+import argparse
+import os
+import subprocess
+import sys
+
+work_dir = os.path.dirname(__file__)
+sys.path.append(work_dir + '/..')
+from conf import env
+from lib import app_helper
+from lib import common
+
+target_name = 'spp'
+
+
+def parse_args():
+    parser = argparse.ArgumentParser(
+        description="Launcher for spp-primary application container")
+
+    parser = app_helper.add_eal_args(parser)
+
+    # Application specific arguments
+    parser.add_argument(
+        '-n', '--nof-ring',
+        type=int,
+        default=10,
+        help='Maximum number of Ring PMD')
+    parser.add_argument(
+        '-p', '--port-mask',
+        type=str,
+        help='Port mask')
+    parser.add_argument(
+        '-dv', '--dev-vhost-ids',
+        type=str,
+        help='vhost device IDs')
+    parser.add_argument(
+        '-dt', '--dev-tap-ids',
+        type=str,
+        help='TAP device IDs')
+    parser.add_argument(
+        '-ip', '--ctrl-ip',
+        type=str,
+        help="IP address of SPP controller")
+    parser.add_argument(
+        '--ctrl-port',
+        type=int,
+        default=5555,
+        help="Port of SPP controller")
+
+    parser = app_helper.add_sppc_args(parser)
+
+    return parser.parse_args()
+
+
+def main():
+    args = parse_args()
+
+    # Setup docker command.
+    docker_cmd = ['sudo', 'docker', 'run', '\\']
+    docker_opts = []
+
+    # This container is running in backgroud in defualt.
+    if args.foreground is not True:
+        docker_opts += ['-d', '\\']
+    else:
+        docker_opts += ['-it', '\\']
+
+    docker_opts += [
+        '--privileged', '\\',  # should be privileged
+        '-v', '/dev/hugepages:/dev/hugepages', '\\',
+        '-v', '/var/run/:/var/run/', '\\']
+
+    if args.dev_vhost_ids is not None:
+        docker_opts += ['-v', '/tmp:/tmp', '\\']
+
+    # Setup for TAP devices with given device IDs.
+    if args.dev_tap_ids is not None:
+        dev_tap_ids = app_helper.dev_ids_to_list(args.dev_tap_ids)
+    else:
+        dev_tap_ids = []
+
+    # Setup for vhost devices with given device IDs.
+    if args.dev_vhost_ids is not None:
+        dev_vhost_ids = app_helper.dev_ids_to_list(args.dev_vhost_ids)
+        socks = []
+        for dev_id in dev_vhost_ids:
+            socks.append({
+                'host': '/tmp/sock%d' % dev_id,
+                'guest': '/tmp/sock%d' % dev_id})
+    else:
+        dev_vhost_ids = []
+
+    if args.container_image is not None:
+        container_image = args.container_image
+    else:
+        # Container image name, for exp 'sppc/dpdk-ubuntu:18.04'
+        container_image = common.container_img_name(
+            env.CONTAINER_IMG_NAME[target_name],
+            args.dist_name,
+            args.dist_ver)
+
+    docker_opts += [
+        container_image, '\\']
+
+    # Setup spp primary command.
+    cmd_path = '%s/../spp/src/primary/%s/spp_primary' % (
+        env.RTE_SDK, env.RTE_TARGET)
+
+    spp_cmd = [cmd_path, '\\']
+
+    # Do not use 'app_helper.setup_eal_opts()' because spp_primary does
+    # not use virtio vdev but TAP or vhost, which should be added manually.
+    core_opt = app_helper.get_core_opt(args)
+    mem_opt = app_helper.get_mem_opt(args)
+    eal_opts = [
+        core_opt['attr'], core_opt['val'], '\\',
+        '-n', str(args.nof_memchan), '\\',
+        mem_opt['attr'], mem_opt['val'], '\\',
+        '--huge-dir', '/dev/hugepages', '\\',
+        '--proc-type', 'primary', '\\']
+
+    # Add TAP vdevs
+    for i in range(len(dev_tap_ids)):
+        eal_opts += [
+            '--vdev', 'net_tap%d,iface=foo%d' % (
+                dev_tap_ids[i], dev_tap_ids[i]), '\\']
+
+    # Add vhost vdevs
+    for i in range(len(dev_vhost_ids)):
+        eal_opts += [
+            '--vdev', 'eth_vhost%d,iface=%s' % (
+                dev_vhost_ids[i], socks[i]['guest']), '\\']
+
+    eal_opts += ['--', '\\']
+
+    spp_opts = []
+    # Check for other mandatory opitons.
+    if args.port_mask is None:
+        common.error_exit('port_mask')
+    else:
+        spp_opts += ['-p', args.port_mask, '\\']
+
+    spp_opts += ['-n', str(args.nof_ring), '\\']
+
+    # IP address of SPP controller.
+    ctrl_ip = os.getenv('SPP_CTRL_IP', args.ctrl_ip)
+    if ctrl_ip is None:
+        common.error_exit('SPP_CTRL_IP')
+    else:
+        spp_opts += ['-s', '%s:%d' % (ctrl_ip, args.ctrl_port), '\\']
+
+    cmds = docker_cmd + docker_opts + spp_cmd + eal_opts + spp_opts
+    if cmds[-1] == '\\':
+        cmds.pop()
+    common.print_pretty_commands(cmds)
+
+    if args.dry_run is True:
+        exit()
+
+    # Remove delimiters for print_pretty_commands().
+    while '\\' in cmds:
+        cmds.remove('\\')
+
+    subprocess.call(cmds)
+
+
+if __name__ == '__main__':
+    main()
diff --git a/tools/sppc/lib/app_helper.py b/tools/sppc/lib/app_helper.py
new file mode 100644
index 0000000..c15c852
--- /dev/null
+++ b/tools/sppc/lib/app_helper.py
@@ -0,0 +1,269 @@
+#!/usr/bin/env python
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2018 Nippon Telegraph and Telephone Corporation
+
+import common
+import os
+import sys
+
+work_dir = os.path.dirname(__file__)
+sys.path.append(work_dir + '/..')
+from conf import env
+
+
+def add_eal_args(parser, mem_size=1024, mem_channel=4):
+    parser.add_argument(
+        '-l', '--core-list',
+        type=str,
+        help='Core list')
+    parser.add_argument(
+        '-c', '--core-mask',
+        type=str,
+        help='Core mask')
+    parser.add_argument(
+        '-m', '--mem',
+        type=int,
+        default=mem_size,
+        help='Memory size (default is %s)' % mem_size)
+    parser.add_argument(
+        '--socket-mem',
+        type=str,
+        help='Memory size')
+    parser.add_argument(
+        '--nof-memchan',
+        type=int,
+        default=mem_channel,
+        help='Number of memory channels (default is %s)' % mem_channel)
+    return parser
+
+
+def get_core_opt(args):
+    # Check core_mask or core_list is defined.
+    if args.core_mask is not None:
+        core_opt = {'attr': '-c', 'val': args.core_mask}
+    elif args.core_list is not None:
+        core_opt = {'attr': '-l', 'val': args.core_list}
+    else:
+        common.error_exit('core_mask or core_list')
+    return core_opt
+
+
+def get_mem_opt(args):
+    # Check memory option is defined.
+    if args.socket_mem is not None:
+        mem_opt = {'attr': '--socket-mem', 'val': args.socket_mem}
+    else:
+        mem_opt = {'attr': '-m', 'val': str(args.mem)}
+    return mem_opt
+
+
+def setup_eal_opts(args, file_prefix, proc_type='auto', hugedir=None):
+    core_opt = get_core_opt(args)
+    mem_opt = get_mem_opt(args)
+
+    eal_opts = [
+        core_opt['attr'], core_opt['val'], '\\',
+        '-n', str(args.nof_memchan), '\\',
+        mem_opt['attr'], mem_opt['val'], '\\',
+        '--proc-type', proc_type, '\\']
+
+    if args.dev_ids is None:
+        common.error_exit('--dev-ids')
+    else:
+        dev_ids = dev_ids_to_list(args.dev_ids)
+
+    socks = []
+    for dev_id in dev_ids:
+        socks.append({
+            'host': '/tmp/sock%d' % dev_id,
+            'guest': '/var/run/usvhost%d' % dev_id})
+
+    for i in range(len(dev_ids)):
+        eal_opts += [
+            '--vdev', 'virtio_user%d,queues=%d,path=%s' % (
+                dev_ids[i], args.nof_queues, socks[i]['guest']), '\\']
+
+    eal_opts += [
+        '--file-prefix', file_prefix, '\\',
+        '--', '\\']
+
+    return eal_opts
+
+
+def add_sppc_args(parser):
+    parser.add_argument(
+        '--dist-name',
+        type=str,
+        default='ubuntu',
+        help="Name of Linux distribution")
+    parser.add_argument(
+        '--dist-ver',
+        type=str,
+        default='latest',
+        help="Version of Linux distribution")
+    parser.add_argument(
+        '-ci', '--container-image',
+        type=str,
+        help="Name of container image")
+    parser.add_argument(
+        '-fg', '--foreground',
+        action='store_true',
+        help="Run container as foreground mode")
+    parser.add_argument(
+        '--dry-run',
+        action='store_true',
+        help="Only print matrix, do not run, and exit")
+    return parser
+
+
+def setup_docker_opts(args, target_name, sock_files, workdir=None):
+    docker_opts = []
+
+    if args.foreground is True:
+        docker_opts = ['-it', '\\']
+    else:
+        docker_opts = ['-d', '\\']
+
+    if workdir is not None:
+        docker_opts += ['--workdir', workdir, '\\']
+
+    if args.no_privileged is not True:
+        docker_opts += ['--privileged', '\\']
+
+    for sock in sock_files:
+        docker_opts += [
+            '-v', '%s:%s' % (sock['host'], sock['guest']), '\\']
+
+    if args.container_image is not None:
+        container_image = args.container_image
+    else:
+        # Container image name, for exp 'sppc/dpdk-ubuntu:18.04'
+        container_image = common.container_img_name(
+            env.CONTAINER_IMG_NAME[target_name],
+            args.dist_name,
+            args.dist_ver)
+
+    docker_opts += [
+        '-v', '/dev/hugepages:/dev/hugepages', '\\',
+        container_image, '\\']
+
+    return docker_opts
+
+
+def add_appc_args(parser):
+    parser.add_argument(
+        '-d', '--dev-ids',
+        type=str,
+        help='two or more even vhost device IDs')
+    parser.add_argument(
+        '-nq', '--nof-queues',
+        type=int,
+        default=1,
+        help="Number of queues of virtio (default is 1)")
+    parser.add_argument(
+        '--no-privileged',
+        action='store_true',
+        help="Disable docker's privileged mode if it's needed")
+    return parser
+
+
+def uniq(dup_list):
+    """Remove duplicated elements in a list and return a unique list
+
+    Example: [1,1,2,2,3,3] #=> [1,2,3]
+    """
+
+    return list(set(dup_list))
+
+
+def dev_ids_to_list(dev_ids):
+    """Parse vhost device IDs and return as a list.
+
+    Example:
+    '1,3-5' #=> [1,3,4,5]
+    """
+
+    res = []
+    for dev_id_part in dev_ids.split(','):
+        if '-' in dev_id_part:
+            cl = dev_id_part.split('-')
+            res = res + range(int(cl[0]), int(cl[1])+1)
+        else:
+            res.append(int(dev_id_part))
+    return res
+
+
+def is_sufficient_dev_ids(dev_ids, port_mask):
+    """Check if ports can be reserved for dev_ids
+
+    Return true if the number of dev IDs equals or more than given ports.
+    'dev_ids' is a value of '-d' or '--dev-ids' such as '1,2'.
+    """
+
+    dev_ids_list = dev_ids_to_list(dev_ids)
+    if not ('0x' in port_mask):  # invalid port mask
+        return False
+
+    ports_in_binary = format(int(port_mask, 16), 'b')
+    if len(dev_ids_list) >= len(ports_in_binary):
+        return True
+    else:
+        return False
+
+
+def sock_files(dev_ids_list):
+    socks = []
+    for dev_id in dev_ids_list:
+        socks.append({
+            'host': '/tmp/sock%d' % dev_id,
+            'guest': '/var/run/usvhost%d' % dev_id})
+    return socks
+
+
+def count_ports(port_mask):
+    """Return the number of ports of given portmask"""
+
+    ports_in_binary = format(int(port_mask, 16), 'b')
+    nof_ports = ports_in_binary.count('1')
+    return nof_ports
+
+
+def cores_to_list(core_opt):
+    """Expand DPDK core option to ranged list.
+
+    Core option must be a hash of attritute and its value.
+    Attribute is -c(core mask) or -l(core list).
+    For example, '-c 0x03' is described as:
+      core_opt = {'attr': '-c', 'val': '0x03'}
+    or '-l 0-1' is as
+      core_opt = {'attr': '-l', 'val': '0-1'}
+
+    Returned value is a list, such as:
+      '0x17' is converted to [1,2,3,5].
+    or
+      '-l 1-3,5' is converted to [1,2,3,5],
+    """
+
+    res = []
+    if core_opt['attr'] == '-c':
+        bin_list = list(
+            format(
+                int(core_opt['val'], 16), 'b'))
+        cnt = 1
+        bin_list.reverse()
+        for i in bin_list:
+            if i == '1':
+                res.append(cnt)
+            cnt += 1
+    elif core_opt['attr'] == '-l':
+        for core_part in core_opt['val'].split(','):
+            if '-' in core_part:
+                cl = core_part.split('-')
+                res = res + range(int(cl[0]), int(cl[1])+1)
+            else:
+                res.append(int(core_part))
+    else:
+        pass
+    res = uniq(res)
+    res.sort()
+    return res
-- 
2.17.1

^ permalink raw reply	[flat|nested] 17+ messages in thread

* [spp] [PATCH 06/15] tools/sppc: add spp-nfv app continer
  2018-06-15  8:37 [spp] [PATCH 00/15] Add SPP container tools ogawa.yasufumi
                   ` (4 preceding siblings ...)
  2018-06-15  8:37 ` [spp] [PATCH 05/15] tools/sppc: add spp-primary app continer ogawa.yasufumi
@ 2018-06-15  8:37 ` ogawa.yasufumi
  2018-06-15  8:37 ` [spp] [PATCH 07/15] tools/sppc: add spp-vm " ogawa.yasufumi
                   ` (9 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: ogawa.yasufumi @ 2018-06-15  8:37 UTC (permalink / raw)
  To: ferruh.yigit, spp; +Cc: Yasufumi Ogawa

From: Yasufumi Ogawa <ogawa.yasufumi@lab.ntt.co.jp>

Signed-off-by: Yasufumi Ogawa <ogawa.yasufumi@lab.ntt.co.jp>
---
 tools/sppc/app/spp-nfv.py | 127 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 127 insertions(+)
 create mode 100755 tools/sppc/app/spp-nfv.py

diff --git a/tools/sppc/app/spp-nfv.py b/tools/sppc/app/spp-nfv.py
new file mode 100755
index 0000000..cdb61a8
--- /dev/null
+++ b/tools/sppc/app/spp-nfv.py
@@ -0,0 +1,127 @@
+#!/usr/bin/env python
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2018 Nippon Telegraph and Telephone Corporation
+
+import argparse
+import os
+import subprocess
+import sys
+
+work_dir = os.path.dirname(__file__)
+sys.path.append(work_dir + '/..')
+from conf import env
+from lib import app_helper
+from lib import common
+
+target_name = 'spp'
+
+
+def parse_args():
+    parser = argparse.ArgumentParser(
+        description="Launcher for spp-nfv application container")
+
+    parser = app_helper.add_eal_args(parser)
+
+    # Application specific arguments
+    parser.add_argument(
+        '-i', '--sec-id',
+        type=int,
+        help='Secondary ID')
+    parser.add_argument(
+        '-ip', '--ctrl-ip',
+        type=str,
+        help="IP address of SPP controller")
+    parser.add_argument(
+        '--ctrl-port',
+        type=int,
+        default=6666,
+        help="Port of SPP controller")
+
+    parser = app_helper.add_sppc_args(parser)
+
+    return parser.parse_args()
+
+
+def main():
+    args = parse_args()
+
+    # Setup docker command.
+    docker_cmd = ['sudo', 'docker', 'run', '\\']
+    docker_opts = []
+
+    # This container is running in backgroud in defualt.
+    if args.foreground is not True:
+        docker_opts += ['-d', '\\']
+    else:
+        docker_opts += ['-it', '\\']
+
+    if args.container_image is not None:
+        container_image = args.container_image
+    else:
+        # Container image name, for exp 'sppc/dpdk-ubuntu:18.04'
+        container_image = common.container_img_name(
+            env.CONTAINER_IMG_NAME[target_name],
+            args.dist_name,
+            args.dist_ver)
+
+    docker_opts += [
+        '--privileged', '\\',  # should be privileged
+        '-v', '/dev/hugepages:/dev/hugepages', '\\',
+        '-v', '/var/run/:/var/run/', '\\',
+        '-v', '/tmp/:/tmp/', '\\',
+        container_image, '\\'
+    ]
+
+    # This container is running in backgroud in defualt.
+    if args.foreground is not True:
+        docker_run_opt = '-d'
+    else:
+        docker_run_opt = '-it'
+
+    # Setup spp_nfv command.
+    cmd_path = '%s/../spp/src/nfv/%s/spp_nfv' % (
+        env.RTE_SDK, env.RTE_TARGET)
+
+    spp_cmd = [cmd_path, '\\']
+
+    # Do not use 'app_helper.setup_eal_opts()' because spp_nfv does
+    # not use virtio.
+    core_opt = app_helper.get_core_opt(args)
+    mem_opt = app_helper.get_mem_opt(args)
+    eal_opts = [
+        core_opt['attr'], core_opt['val'], '\\',
+        '-n', str(args.nof_memchan), '\\',
+        mem_opt['attr'], mem_opt['val'], '\\',
+        '--proc-type', 'secondary', '\\',
+        '--', '\\']
+
+    spp_opts = []
+    # Check for other mandatory opitons.
+    if args.sec_id is None:
+        common.error_exit('--sec-id')
+    else:
+        spp_opts += ['-n', str(args.sec_id), '\\']
+
+    # IP address of SPP controller.
+    ctrl_ip = os.getenv('SPP_CTRL_IP', args.ctrl_ip)
+    if ctrl_ip is None:
+        common.error_exit('SPP_CTRL_IP')
+    else:
+        spp_opts += ['-s', '%s:%d' % (ctrl_ip, args.ctrl_port), '\\']
+
+    cmds = docker_cmd + docker_opts + spp_cmd + eal_opts + spp_opts
+    if cmds[-1] == '\\':
+        cmds.pop()
+    common.print_pretty_commands(cmds)
+
+    if args.dry_run is True:
+        exit()
+
+    # Remove delimiters for print_pretty_commands().
+    while '\\' in cmds:
+        cmds.remove('\\')
+    subprocess.call(cmds)
+
+
+if __name__ == '__main__':
+    main()
-- 
2.17.1

^ permalink raw reply	[flat|nested] 17+ messages in thread

* [spp] [PATCH 07/15] tools/sppc: add spp-vm app continer
  2018-06-15  8:37 [spp] [PATCH 00/15] Add SPP container tools ogawa.yasufumi
                   ` (5 preceding siblings ...)
  2018-06-15  8:37 ` [spp] [PATCH 06/15] tools/sppc: add spp-nfv " ogawa.yasufumi
@ 2018-06-15  8:37 ` ogawa.yasufumi
  2018-06-15  8:37 ` [spp] [PATCH 08/15] tools/sppc: add l2fwd " ogawa.yasufumi
                   ` (8 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: ogawa.yasufumi @ 2018-06-15  8:37 UTC (permalink / raw)
  To: ferruh.yigit, spp; +Cc: Yasufumi Ogawa

From: Yasufumi Ogawa <ogawa.yasufumi@lab.ntt.co.jp>

Signed-off-by: Yasufumi Ogawa <ogawa.yasufumi@lab.ntt.co.jp>
---
 tools/sppc/app/spp-vm.py | 107 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 107 insertions(+)
 create mode 100755 tools/sppc/app/spp-vm.py

diff --git a/tools/sppc/app/spp-vm.py b/tools/sppc/app/spp-vm.py
new file mode 100755
index 0000000..864ec61
--- /dev/null
+++ b/tools/sppc/app/spp-vm.py
@@ -0,0 +1,107 @@
+#!/usr/bin/env python
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2018 Nippon Telegraph and Telephone Corporation
+
+import argparse
+import os
+import subprocess
+import sys
+
+work_dir = os.path.dirname(__file__)
+sys.path.append(work_dir + '/..')
+from conf import env
+from lib import app_helper
+from lib import common
+
+target_name = 'spp'
+
+
+def parse_args():
+    parser = argparse.ArgumentParser(
+        description="Launcher for spp-vm application container")
+
+    parser = app_helper.add_eal_args(parser)
+    parser = app_helper.add_appc_args(parser)
+
+    # Application specific arguments
+    parser.add_argument(
+        '-i', '--sec-id',
+        type=int,
+        help='Secondary ID')
+    parser.add_argument(
+        '-ip', '--ctrl-ip',
+        type=str,
+        help="IP address of SPP controller")
+    parser.add_argument(
+        '--ctrl-port',
+        type=int,
+        default=6666,
+        help="Port of SPP controller")
+    parser.add_argument(
+        '-p', '--port-mask',
+        type=str,
+        help="Port mask")
+
+    parser = app_helper.add_sppc_args(parser)
+
+    return parser.parse_args()
+
+
+def main():
+    args = parse_args()
+
+    # Check for other mandatory opitons.
+    if args.sec_id is None:
+        common.error_exit('--sec-id')
+
+    if args.dev_ids is None:
+        common.error_exit('--dev-ids')
+
+    if args.port_mask is None:
+        common.error_exit('--port-mask')
+
+    # Setup for vhost devices with given device IDs.
+    dev_ids_list = app_helper.dev_ids_to_list(args.dev_ids)
+    sock_files = app_helper.sock_files(dev_ids_list)
+
+    # Setup docker command.
+    docker_cmd = ['sudo', 'docker', 'run', '\\']
+    docker_opts = app_helper.setup_docker_opts(
+        args, target_name, sock_files)
+
+    # IP address of SPP controller.
+    ctrl_ip = os.getenv('SPP_CTRL_IP', args.ctrl_ip)
+    if ctrl_ip is None:
+        common.error_exit('SPP_CTRL_IP')
+
+    # Setup spp_vm command.
+    cmd_path = '%s/../spp/src/vm/%s/spp_vm' % (
+        env.RTE_SDK, env.RTE_TARGET)
+
+    spp_cmd = [cmd_path, '\\']
+
+    file_prefix = 'spp-l2fwd-container%d' % dev_ids_list[0]
+    eal_opts = app_helper.setup_eal_opts(args, file_prefix)
+
+    spp_opts = [
+        '-n', str(args.sec_id), '\\',
+        '-p', args.port_mask, '\\',
+        '-s', '%s:%d' % (ctrl_ip, args.ctrl_port)
+    ]
+
+    cmds = docker_cmd + docker_opts + spp_cmd + eal_opts + spp_opts
+    if cmds[-1] == '\\':
+        cmds.pop()
+    common.print_pretty_commands(cmds)
+
+    if args.dry_run is True:
+        exit()
+
+    # Remove delimiters for print_pretty_commands().
+    while '\\' in cmds:
+        cmds.remove('\\')
+    subprocess.call(cmds)
+
+
+if __name__ == '__main__':
+    main()
-- 
2.17.1

^ permalink raw reply	[flat|nested] 17+ messages in thread

* [spp] [PATCH 08/15] tools/sppc: add l2fwd app continer
  2018-06-15  8:37 [spp] [PATCH 00/15] Add SPP container tools ogawa.yasufumi
                   ` (6 preceding siblings ...)
  2018-06-15  8:37 ` [spp] [PATCH 07/15] tools/sppc: add spp-vm " ogawa.yasufumi
@ 2018-06-15  8:37 ` ogawa.yasufumi
  2018-06-15  8:37 ` [spp] [PATCH 09/15] tools/sppc: add testpmd " ogawa.yasufumi
                   ` (7 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: ogawa.yasufumi @ 2018-06-15  8:37 UTC (permalink / raw)
  To: ferruh.yigit, spp; +Cc: Yasufumi Ogawa

From: Yasufumi Ogawa <ogawa.yasufumi@lab.ntt.co.jp>

Signed-off-by: Yasufumi Ogawa <ogawa.yasufumi@lab.ntt.co.jp>
---
 tools/sppc/app/l2fwd.py | 96 +++++++++++++++++++++++++++++++++++++++++
 1 file changed, 96 insertions(+)
 create mode 100755 tools/sppc/app/l2fwd.py

diff --git a/tools/sppc/app/l2fwd.py b/tools/sppc/app/l2fwd.py
new file mode 100755
index 0000000..3b7789c
--- /dev/null
+++ b/tools/sppc/app/l2fwd.py
@@ -0,0 +1,96 @@
+#!/usr/bin/env python
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2018 Nippon Telegraph and Telephone Corporation
+
+import argparse
+import os
+import subprocess
+import sys
+
+work_dir = os.path.dirname(__file__)
+sys.path.append(work_dir + '/..')
+from conf import env
+from lib import app_helper
+from lib import common
+
+target_name = 'dpdk'
+
+
+def parse_args():
+    parser = argparse.ArgumentParser(
+        description="Launcher for l2fwd application container")
+
+    parser = app_helper.add_eal_args(parser)
+    parser = app_helper.add_appc_args(parser)
+
+    # Application specific args
+    parser.add_argument(
+        '-p', '--port-mask',
+        type=str,
+        help="Port mask")
+
+    parser = app_helper.add_sppc_args(parser)
+    return parser.parse_args()
+
+
+def main():
+    args = parse_args()
+
+    # Check for other mandatory opitons.
+    if args.port_mask is None:
+        common.error_exit('--port-mask')
+    if args.dev_ids is None:
+        common.error_exit('--dev-ids')
+
+    # Setup for vhost devices with given device IDs.
+    dev_ids_list = app_helper.dev_ids_to_list(args.dev_ids)
+    sock_files = app_helper.sock_files(dev_ids_list)
+
+    # Setup docker command.
+    docker_cmd = ['sudo', 'docker', 'run', '\\']
+    docker_opts = app_helper.setup_docker_opts(
+        args, target_name, sock_files)
+
+    # Check if the number of ports is even for l2fwd.
+    nof_ports = app_helper.count_ports(args.port_mask)
+    if (nof_ports % 2) != 0:
+        print("Error: Number of ports must be an even number!")
+        exit()
+
+    # Setup l2fwd command run on container.
+    cmd_path = '%s/examples/l2fwd/%s/l2fwd' % (
+        env.RTE_SDK, env.RTE_TARGET)
+
+    l2fwd_cmd = [cmd_path, '\\']
+
+    file_prefix = 'spp-l2fwd-container%d' % dev_ids_list[0]
+    eal_opts = app_helper.setup_eal_opts(args, file_prefix)
+
+    l2fwd_opts = ['-p', args.port_mask, '\\']
+
+    # Parse vhost device IDs and Check the number of devices is
+    # sufficient for port mask.
+    if app_helper.is_sufficient_dev_ids(
+            args.dev_ids, args.port_mask) is not True:
+        print("Error: Cannot reserve ports '%s (= 0b%s)' on '%s'." % (
+            args.port_mask,
+            format(int(args.port_mask, 16), 'b'),
+            args.dev_ids))
+        exit()
+
+    cmds = docker_cmd + docker_opts + l2fwd_cmd + eal_opts + l2fwd_opts
+    if cmds[-1] == '\\':
+        cmds.pop()
+    common.print_pretty_commands(cmds)
+
+    if args.dry_run is True:
+        exit()
+
+    # Remove delimiters for print_pretty_commands().
+    while '\\' in cmds:
+        cmds.remove('\\')
+    subprocess.call(cmds)
+
+
+if __name__ == '__main__':
+    main()
-- 
2.17.1

^ permalink raw reply	[flat|nested] 17+ messages in thread

* [spp] [PATCH 09/15] tools/sppc: add testpmd app continer
  2018-06-15  8:37 [spp] [PATCH 00/15] Add SPP container tools ogawa.yasufumi
                   ` (7 preceding siblings ...)
  2018-06-15  8:37 ` [spp] [PATCH 08/15] tools/sppc: add l2fwd " ogawa.yasufumi
@ 2018-06-15  8:37 ` ogawa.yasufumi
  2018-06-15  8:37 ` [spp] [PATCH 10/15] tools/sppc: add l3fwd " ogawa.yasufumi
                   ` (6 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: ogawa.yasufumi @ 2018-06-15  8:37 UTC (permalink / raw)
  To: ferruh.yigit, spp; +Cc: Yasufumi Ogawa

From: Yasufumi Ogawa <ogawa.yasufumi@lab.ntt.co.jp>

Signed-off-by: Yasufumi Ogawa <ogawa.yasufumi@lab.ntt.co.jp>
---
 tools/sppc/app/testpmd.py | 857 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 857 insertions(+)
 create mode 100755 tools/sppc/app/testpmd.py

diff --git a/tools/sppc/app/testpmd.py b/tools/sppc/app/testpmd.py
new file mode 100755
index 0000000..8d4057c
--- /dev/null
+++ b/tools/sppc/app/testpmd.py
@@ -0,0 +1,857 @@
+#!/usr/bin/env python
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2018 Nippon Telegraph and Telephone Corporation
+
+import argparse
+import os
+import re
+import subprocess
+import sys
+
+work_dir = os.path.dirname(__file__)
+sys.path.append(work_dir + '/..')
+from conf import env
+from lib import app_helper
+from lib import common
+
+target_name = 'dpdk'
+
+
+def parse_args():
+    parser = argparse.ArgumentParser(
+        description="Launcher for testpmd application container")
+
+    parser = app_helper.add_eal_args(parser)
+    parser = app_helper.add_appc_args(parser)
+
+    # Application specific args
+    parser.add_argument(
+        '--pci',
+        action='store_true',
+        help="Enable PCI (default is None)")
+    parser.add_argument(
+        '-i', '--interactive',
+        action='store_true',
+        help="Run in interactive mode (default is None)")
+    parser.add_argument(
+        '-a', '--auto-start',
+        action='store_true',
+        help="Start forwarding on initialization (default is None)")
+    parser.add_argument(
+        '--tx-first',
+        action='store_true',
+        help="Start forwarding, after sending a burst of packets first")
+    parser.add_argument(
+        '--stats-period',
+        type=int,
+        help="Period of displaying stats, if interactive is disabled")
+    parser.add_argument(
+        '--nb-cores',
+        type=int,
+        help="Number of forwarding cores")
+    parser.add_argument(
+        '--coremask',
+        type=str,
+        help="Hexadecimal bitmask of the cores, " +
+        "do not include master lcore")
+    parser.add_argument(
+        '--portmask',
+        type=str,
+        help="Hexadecimal bitmask of the ports")
+    parser.add_argument(
+        '--no-numa',
+        action='store_true',
+        help="Disable NUMA-aware allocation of RX/TX rings and RX mbuf")
+    parser.add_argument(
+        '--port-numa-config',
+        type=str,
+        help="Specify port allocation as (port,socket)[,(port,socket)]")
+    parser.add_argument(
+        '--ring-numa-config',
+        type=str,
+        help="Specify ring allocation as " +
+        "(port,flag,socket)[,(port,flag,socket)]")
+    parser.add_argument(
+        '--socket-num',
+        type=int,
+        help="Socket from which all memory is allocated in NUMA mode")
+    parser.add_argument(
+        '--mbuf-size',
+        type=int,
+        help="Size of mbufs used to N (< 65536) bytes (default is 2048)")
+    parser.add_argument(
+        '--total-num-mbufs',
+        type=int,
+        help="Number of mbufs allocated in mbuf pools, N > 1024.")
+    parser.add_argument(
+        '--max-pkt-len',
+        type=int,
+        help="Maximum packet size to N (>= 64) bytes (default is 1518)")
+    parser.add_argument(
+        '--eth-peers-configfile',
+        type=str,
+        help="Config file of Ether addrs of the peer ports")
+    parser.add_argument(
+        '--eth-peer',
+        type=str,
+        help="Set MAC addr of port N as 'N,XX:XX:XX:XX:XX:XX'")
+    parser.add_argument(
+        '--pkt-filter-mode',
+        type=str,
+        help="Flow Director mode, " +
+        "'none'(default), 'signature' or 'perfect'")
+    parser.add_argument(
+        '--pkt-filter-report-hash',
+        type=str,
+        help="Flow Director hash match mode, " +
+        "'none', 'match'(default) or 'always'")
+    parser.add_argument(
+        '--pkt-filter-size',
+        type=str,
+        help="Flow Director memory size ('64K', '128K', '256K'). " +
+        "The default is 64K.")
+    parser.add_argument(
+        '--pkt-filter-flexbytes-offset',
+        type=int,
+        help="Flexbytes offset (0-32, default is 0x6) defined in " +
+        "words counted from the first byte of the dest MAC address")
+    parser.add_argument(
+        '--pkt-filter-drop-queue',
+        type=int,
+        help="Set the drop-queue (default is 127)")
+    parser.add_argument(
+        '--disable-crc-strip',
+        action='store_true',
+        help="Disable hardware CRC stripping")
+    parser.add_argument(
+        '--enable-lro',
+        action='store_true',
+        help="Enable large receive offload")
+    parser.add_argument(
+        '--enable-rx-cksum',
+        action='store_true',
+        help="Enable hardware RX checksum offload")
+    parser.add_argument(
+        '--enable-scatter',
+        action='store_true',
+        help="Enable scatter (multi-segment) RX")
+    parser.add_argument(
+        '--enable-hw-vlan',
+        action='store_true',
+        help="Enable hardware vlan (default is None)")
+    parser.add_argument(
+        '--enable-hw-vlan-filter',
+        action='store_true',
+        help="Enable hardware VLAN filter")
+    parser.add_argument(
+        '--enable-hw-vlan-strip',
+        action='store_true',
+        help="Enable hardware VLAN strip")
+    parser.add_argument(
+        '--enable-hw-vlan-extend',
+        action='store_true',
+        help="Enable hardware VLAN extend")
+    parser.add_argument(
+        '--enable-drop-en',
+        action='store_true',
+        help="Enable per-queue packet drop if no descriptors")
+    parser.add_argument(
+        '--disable-rss',
+        action='store_true',
+        help="Disable RSS (Receive Side Scaling")
+    parser.add_argument(
+        '--port-topology',
+        type=str,
+        help="Port topology, 'paired' (the default) or 'chained'")
+    parser.add_argument(
+        '--forward-mode',
+        type=str,
+        help="Forwarding mode, " +
+        "'io' (default), 'mac', 'mac_swap', 'flowgen', 'rxonly', " +
+        "'txonly', 'csum', 'icmpecho', 'ieee1588', 'tm'")
+    parser.add_argument(
+        '--rss-ip',
+        action='store_true',
+        help="Set RSS functions for IPv4/IPv6 only")
+    parser.add_argument(
+        '--rss-udp',
+        action='store_true',
+        help="Set RSS functions for IPv4/IPv6 and UDP")
+    parser.add_argument(
+        '--rxq',
+        type=int,
+        help="Number of RX queues per port, 1-65535 (default is 1)")
+    parser.add_argument(
+        '--rxd',
+        type=int,
+        help="Number of descriptors in the RX rings (default is 128)")
+    parser.add_argument(
+        '--txq',
+        type=int,
+        help="Number of TX queues per port, 1-65535 (default is 1)")
+    parser.add_argument(
+        '--txd',
+        type=int,
+        help="Number of descriptors in the TX rings (default is 512)")
+    parser.add_argument(
+        '--burst',
+        type=int,
+        help="Number of packets per burst, 1-512 (default is 32)")
+    parser.add_argument(
+        '--mbcache',
+        type=int,
+        help="Cache of mbuf memory pools, 0-512 (default is 16)")
+    parser.add_argument(
+        '--rxpt',
+        type=int,
+        help="Prefetch threshold register of RX rings (default is 8)")
+    parser.add_argument(
+        '--rxht',
+        type=int,
+        help="Host threshold register of RX rings (default is 8)")
+    parser.add_argument(
+        '--rxfreet',
+        type=int,
+        help="Free threshold of RX descriptors,0-'rxd' (default is 0)")
+    parser.add_argument(
+        '--rxwt',
+        type=int,
+        help="Write-back threshold register of RX rings (default is 4)")
+    parser.add_argument(
+        '--txpt',
+        type=int,
+        help="Prefetch threshold register of TX rings (default is 36)")
+    parser.add_argument(
+        '--txht',
+        type=int,
+        help="Host threshold register of TX rings (default is 0)")
+    parser.add_argument(
+        '--txwt',
+        type=int,
+        help="Write-back threshold register of TX rings (default is 0)")
+    parser.add_argument(
+        '--txfreet',
+        type=int,
+        help="Free threshold of RX descriptors, 0-'txd' (default is 0)")
+    parser.add_argument(
+        '--txrst',
+        type=int,
+        help="Transmit RS bit threshold of TX rings, 0-'txd' (default is 0)")
+    parser.add_argument(
+        '--rx-queue-stats-mapping',
+        type=str,
+        help="RX queues statistics counters mapping 0-15 as " +
+        "'(port,queue,mapping)[,(port,queue,mapping)]'")
+    parser.add_argument(
+        '--tx-queue-stats-mapping',
+        type=str,
+        help="TX queues statistics counters mapping 0-15 as " +
+        "'(port,queue,mapping)[,(port,queue,mapping)]'")
+    parser.add_argument(
+        '--no-flush-rx',
+        action='store_true',
+        help="Don’t flush the RX streams before starting forwarding, " +
+        "Used mainly with the PCAP PMD")
+    parser.add_argument(
+        '--txpkts',
+        type=str,
+        help="TX segment sizes or total packet length, " +
+        "Valid for tx-only and flowgen")
+    parser.add_argument(
+        '--disable-link-check',
+        action='store_true',
+        help="Disable check on link status when starting/stopping ports")
+    parser.add_argument(
+        '--no-lsc-interrupt',
+        action='store_true',
+        help="Disable LSC interrupts for all ports")
+    parser.add_argument(
+        '--no-rmv-interrupt',
+        action='store_true',
+        help="Disable RMV interrupts for all ports")
+    parser.add_argument(
+        '--bitrate-stats',
+        nargs='*',
+        action='append',
+        type=int,
+        help="Logical core N to perform bitrate calculation")
+    parser.add_argument(
+        '--print-event',
+        type=str,
+        help="Enable printing the occurrence of the designated event, " +
+        "<unknown|intr_lsc|queue_state|intr_reset|vf_mbox|macsec|" +
+        "intr_rmv|dev_probed|dev_released|all>")
+    parser.add_argument(
+        '--mask-event',
+        type=str,
+        help="Disable printing the occurrence of the designated event, " +
+        "<unknown|intr_lsc|queue_state|intr_reset|vf_mbox|macsec|" +
+        "intr_rmv|dev_probed|dev_released|all>")
+    parser.add_argument(
+        '--flow-isolate-all',
+        action='store_true',
+        help="Providing this parameter requests flow API isolated mode " +
+        "on all ports at initialization time")
+    parser.add_argument(
+        '--tx-offloads',
+        type=str,
+        help="Hexadecimal bitmask of TX queue offloads (default is 0)")
+    parser.add_argument(
+        '--hot-plug',
+        action='store_true',
+        help="Enable device event monitor machenism for hotplug")
+    parser.add_argument(
+        '--vxlan-gpe-port',
+        type=int,
+        help="UDP port number of tunnel VXLAN-GPE (default is 4790)")
+    parser.add_argument(
+        '--mlockall',
+        action='store_true',
+        help="Enable locking all memory")
+    parser.add_argument(
+        '--no-mlockall',
+        action='store_true',
+        help="Disable locking all memory")
+
+    parser = app_helper.add_sppc_args(parser)
+
+    return parser.parse_args()
+
+
+def check_eth_peer(eth_peer):
+    """Check if --eth-peer option is valied
+
+    Format of --eth-peer for port X should be 'N,XX:XX:XX:XX:XX:XX'.
+    """
+
+    xx = '[0-9A-Fa-f][0-9A-Fa-f]'
+    ptn = re.compile(
+        r'(\d+),(%s:%s:%s:%s:%s:%s)' % (xx, xx, xx, xx, xx, xx))
+    m = re.match(ptn, eth_peer)
+    if m is None:
+            return False
+    return True
+
+
+def check_pkt_filter_mode(mode):
+    """Check if Flow Director mode is valid
+
+    There are three modes for Flow Director.
+      * none (default)
+      * signature
+      * perfect
+    """
+
+    if mode in ['none', 'signature', 'perfect']:
+        return True
+    else:
+        return False
+
+
+def check_pkt_filter_report_hash(mode):
+    """Check if Flow Director hash match reporting mode is valid
+
+    There are three modes for the reporting mode.
+      * none
+      * match (default)
+      * always
+    """
+
+    if mode in ['none', 'match', 'always']:
+        return True
+    else:
+        return False
+
+
+def check_pkt_filter_size(pkt_size):
+    """Check if Flow Director size is valid
+
+    Packet size should be 64K, 128K or 256K
+    """
+
+    if pkt_size in ['64K', '128K', '256K']:
+        return True
+    else:
+        return False
+
+
+def check_txpkts(txpkts):
+    # TODO(yasufum) add impl
+    # --txpkts is valid for 'tx-only' or 'flowgen' forwarding modes
+    return True
+
+
+def check_event(event):
+    events = ['unknown', 'intr_lsc', 'queue_state', 'intr_reset',
+              'vf_mbox', 'macsec', 'intr_rmv', 'dev_probed',
+              'dev_released', 'all']
+    if event in events:
+        return True
+    else:
+        return False
+
+
+def print_not_supported(opt_name):
+    print("Error: '%s' is not supported yet" % opt_name)
+
+
+def main():
+    args = parse_args()
+
+    # Check for other mandatory opitons.
+    if args.dev_ids is None:
+        common.error_exit('--dev-ids')
+
+    # Setup for vhost devices with given device IDs.
+    dev_ids_list = app_helper.dev_ids_to_list(args.dev_ids)
+    sock_files = app_helper.sock_files(dev_ids_list)
+
+    # Setup docker command.
+    docker_cmd = ['sudo', 'docker', 'run', '\\']
+    docker_opts = app_helper.setup_docker_opts(
+        args, target_name, sock_files)
+
+    cmd_path = 'testpmd'
+
+    # Setup testpmd command.
+    testpmd_cmd = [cmd_path, '\\']
+
+    # Setup EAL options
+    file_prefix = 'spp-testpmd-container%d' % dev_ids_list[0]
+    eal_opts = app_helper.setup_eal_opts(args, file_prefix)
+
+    # Setup testpmd options
+    testpmd_opts = []
+
+    if args.interactive is True:
+        testpmd_opts += ['--interactive', '\\']
+
+    if args.auto_start is True:
+        testpmd_opts += ['--auto-start', '\\']
+
+    if args.tx_first is True:
+        if args.interactive is not True:
+            testpmd_opts += ['--tx-first', '\\']
+        else:
+            print("Error: '%s' cannot be used in interactive mode" % (
+                '--tx-first'))
+            exit()
+
+    if args.stats_period is not None:
+        testpmd_opts += ['--stats-period', str(args.stats_period), '\\']
+
+    if args.nb_cores is not None:
+        testpmd_opts += ['--nb-cores=%d' % args.nb_cores, '\\']
+
+    if args.coremask is not None:
+        testpmd_opts += ['--coremask=%s' % args.coremask, '\\']
+
+    if args.portmask is not None:
+        testpmd_opts += ['--portmask=%s' % args.portmask, '\\']
+
+    if args.no_numa is True:
+        testpmd_opts += ['--no-numa', '\\']
+
+    # TODO(yasufum) add impl
+    if args.port_numa_config is not None:
+        print_not_supported('--port-numa-config')
+        exit()
+
+    # TODO(yasufum) add impl
+    if args.ring_numa_config is not None:
+        print_not_supported('--ring-numa-config')
+        exit()
+
+    if args.socket_num is not None:
+        testpmd_opts += ['%s=%d' % (
+            '--socket-num', args.socket_num), '\\']
+
+    if args.mbuf_size is not None:
+        mbuf_limit = 65536
+        if args.mbuf_size > mbuf_limit:
+            print("Error: '%s' should be less than %d" % (
+                '--mbuf-size', mbuf_limit))
+            exit()
+        else:
+            testpmd_opts += ['%s=%d' % (
+                '--mbuf-size', args.mbuf_size), '\\']
+
+    if args.total_num_mbufs is not None:
+        nof_mbuf_limit = 1024
+        if args.total_num_mbufs <= nof_mbuf_limit:
+            print("Error: '%s' should be more than %d" % (
+                '--total-num-mbufs', nof_mbuf_limit))
+            exit()
+        else:
+            testpmd_opts += ['%s=%d' % (
+                '--total-num-mbufs', args.total_num_mbufs), '\\']
+
+    if args.max_pkt_len is not None:
+        pkt_len_limit = 64
+        if args.max_pkt_len < pkt_len_limit:
+            print("Error: '%s' should be equal or more than %d" % (
+                '--max-pkt-len', pkt_len_limit))
+            exit()
+        else:
+            testpmd_opts += ['%s=%d' % (
+                '--max-pkt-len', args.max_pkt_len), '\\']
+
+    if args.eth_peers_configfile is not None:
+        testpmd_opts += ['%s=%s' % (
+            '--eth-peers-configfile',
+            args.eth_peers_configfile), '\\']
+
+    if args.eth_peer is not None:
+        if check_eth_peer(args.eth_peer) is True:
+            testpmd_opts += ['%s=%s' % (
+                '--eth-peer', args.eth_peer), '\\']
+        else:
+            print("Error: invalid '--eth-peer' option")
+            exit()
+
+    if args.pkt_filter_mode is not None:
+        if check_pkt_filter_mode(args.pkt_filter_mode) is True:
+            testpmd_opts += ['%s=%s' % (
+                '--pkt-filter-mode', args.pkt_filter_mode), '\\']
+        else:
+            print("Error: '--pkt-filter-mode' should be " +
+                  "'none', 'signature' or 'perfect'")
+            exit()
+
+    if args.pkt_filter_report_hash is not None:
+        if check_pkt_filter_report_hash(args.pkt_filter_report_hash) is True:
+            testpmd_opts += ['%s=%s' % (
+                '--pkt-filter-report-hash',
+                args.pkt_filter_report_hash), '\\']
+        else:
+            print("Error: '--pkt-filter-report-hash' should be " +
+                  "'none', 'match' or 'always'")
+            exit()
+
+    if args.pkt_filter_size is not None:
+        if check_pkt_filter_size(args.pkt_filter_size) is True:
+            testpmd_opts += ['%s=%s' % (
+                '--pkt-filter-size', args.pkt_filter_size), '\\']
+        else:
+            print("Error: '--pkt-filter-size' should be " +
+                  "'64K', '128K' or '256K'")
+            exit()
+
+    # TODO(yasufum) Confirm this option is supported in dpdk 18.02
+    if args.pkt_filter_flexbytes_offset is not None:
+        print_not_supported('--pkt-filter-flexbytes-offset')
+        exit()
+    # It causes 'unrecognized option' error.
+    # if args.pkt_filter_flexbytes_offset is not None:
+    #     f_offset = args.pkt_filter_flexbytes_offset
+    #     f_offset_min = 0
+    #     f_offset_max = 32
+    #     if (f_offset < f_offset_min) or (f_offset > f_offset_max):
+    #         print("Error: '%s' should be %d-%d" % (
+    #             '--pkt-filter-flexbytes-offset',
+    #             f_offset_min, f_offset_max))
+    #         exit()
+    #     else:
+    #         testpmd_opts += ['%s=%d' % (
+    #             '--pkt-filter-flexbytes-offset', f_offset), '\\']
+
+    if args.pkt_filter_drop_queue is not None:
+        testpmd_opts += ['%s=%d' % (
+            '--pkt-filter-drop-queue', args.pkt_filter_drop_queue), '\\']
+
+    if args.disable_crc_strip is True:
+        testpmd_opts += ['--disable-crc-strip', '\\']
+
+    if args.enable_lro is True:
+        testpmd_opts += ['--enable-lro', '\\']
+
+    if args.enable_rx_cksum is True:
+        testpmd_opts += ['--enable-rx-cksum', '\\']
+
+    if args.enable_scatter is True:
+        testpmd_opts += ['--enable-scatter', '\\']
+
+    if args.enable_hw_vlan is True:
+        testpmd_opts += ['--enable-hw-vlan', '\\']
+
+    if args.enable_hw_vlan_filter is True:
+        testpmd_opts += ['--enable-hw-vlan-filter', '\\']
+
+    if args.enable_hw_vlan_strip is True:
+        testpmd_opts += ['--enable-hw-vlan-strip', '\\']
+
+    if args.enable_hw_vlan_extend is True:
+        testpmd_opts += ['--enable-hw-vlan-extend', '\\']
+
+    if args.enable_drop_en is True:
+        testpmd_opts += ['--enable-drop-en', '\\']
+
+    if args.disable_rss is True:
+        testpmd_opts += ['--disable-rss', '\\']
+
+    # TODO(yasufum) add impl
+    if args.port_topology is not None:
+        print_not_supported('--port-topology')
+        exit()
+
+    # TODO(yasufum) add impl
+    if args.forward_mode is not None:
+        print_not_supported('--forward-mode')
+        exit()
+
+    if args.rss_ip is True:
+        testpmd_opts += ['--rss-ip', '\\']
+
+    if args.rss_udp is True:
+        testpmd_opts += ['--rss-udp', '\\']
+
+    if args.rxq is not None:
+        nof_q_min = 1
+        nof_q_max = 65535
+        if (args.rxq < nof_q_min) or (nof_q_max < args.rxq):
+            print("Error: '%s' should be %d-%d" % (
+                '--rxq', nof_q_min, nof_q_max))
+            exit()
+        else:
+            testpmd_opts += ['%s=%d' % ('--rxq', args.rxq), '\\']
+
+    if args.rxd is not None:
+        nof_d_min = 1
+        if (args.rxd < nof_d_min):
+            print("Error: '%s' should be equal or more than %d" % (
+                '--rxd', nof_d_min))
+            exit()
+        else:
+            testpmd_opts += ['%s=%d' % ('--rxd', args.rxd), '\\']
+
+    if args.txq is not None:
+        nof_q_min = 1
+        nof_q_max = 65535
+        if (args.txq < nof_q_min) or (nof_q_max < args.txq):
+            print("Error: '%s' should be %d-%d" % (
+                '--txq', nof_q_min, nof_q_max))
+            exit()
+        else:
+            testpmd_opts += ['%s=%d' % ('--txq', args.txq), '\\']
+
+    if args.txd is not None:
+        nof_d_min = 1
+        if (args.txd < nof_d_min):
+            print("Error: '%s' should be equal or more than %d" % (
+                '--txd', nof_d_min))
+            exit()
+        else:
+            testpmd_opts += ['%s=%d' % ('--txd', args.txd), '\\']
+
+    if args.burst is not None:
+        b_min = 1
+        b_max = 512
+        if (args.burst < b_min) or (b_max < args.burst):
+            print("Error: '%s' should be %d-%d" % (
+                '--burst', b_min, b_max))
+            exit()
+        else:
+            testpmd_opts += ['%s=%d' % ('--burst', args.burst), '\\']
+
+    if args.mbcache is not None:
+        mb_min = 0
+        mb_max = 512
+        if (args.mbcache < mb_min) or (mb_max < args.mbcache):
+            print("Error: '%s' should be %d-%d" % (
+                '--mbcache', mb_min, mb_max))
+            exit()
+        else:
+            testpmd_opts += ['%s=%d' % ('--mbcache', args.mbcache), '\\']
+
+    if args.rxpt is not None:
+        nof_p_min = 0
+        if (args.rxpt < nof_p_min):
+            print("Error: '%s' should be equal or more than %d" % (
+                '--rxpt', nof_p_min))
+            exit()
+        else:
+            testpmd_opts += ['%s=%d' % ('--rxpt', args.rxpt), '\\']
+
+    if args.rxht is not None:
+        nof_h_min = 0
+        if (args.rxht < nof_h_min):
+            print("Error: '%s' should be equal or more than %d" % (
+                '--rxht', nof_h_min))
+            exit()
+        else:
+            testpmd_opts += ['%s=%d' % ('--rxht', args.rxht), '\\']
+
+    if args.rxfreet is not None:
+        nof_f_min = 0
+        if args.rxd is not None:
+            nof_f_max = args.rxd - 1
+        else:
+            nof_f_max = 128 - 1  # as default of rxd - 1
+        if (args.rxfreet < nof_f_min) or (nof_f_max < args.rxfreet):
+            print("Error: '%s' should be %d-%d" % (
+                '--rxfreet', nof_f_min, nof_f_max))
+            exit()
+        else:
+            testpmd_opts += ['%s=%d' % ('--rxfreet', args.rxfreet), '\\']
+
+    if args.rxwt is not None:
+        nof_w_min = 0
+        if (args.rxwt < nof_w_min):
+            print("Error: '%s' should be equal or more than %d" % (
+                '--rxwt', nof_w_min))
+            exit()
+        else:
+            testpmd_opts += ['%s=%d' % ('--rxwt', args.rxwt), '\\']
+
+    if args.txpt is not None:
+        nof_p_min = 0
+        if (args.txpt < nof_p_min):
+            print("Error: '%s' should be equal or more than %d" % (
+                '--txpt', nof_p_min))
+            exit()
+        else:
+            testpmd_opts += ['%s=%d' % ('--txpt', args.txpt), '\\']
+
+    if args.txht is not None:
+        nof_h_min = 0
+        if (args.txht < nof_h_min):
+            print("Error: '%s' should be equal or more than %d" % (
+                '--txht', nof_h_min))
+            exit()
+        else:
+            testpmd_opts += ['%s=%d' % ('--txht', args.txht), '\\']
+
+    if args.txwt is not None:
+        nof_w_min = 0
+        if (args.txwt < nof_w_min):
+            print("Error: '%s' should be equal or more than %d" % (
+                '--txwt', nof_w_min))
+            exit()
+        else:
+            testpmd_opts += ['%s=%d' % ('--txwt', args.txwt), '\\']
+
+    if args.txfreet is not None:
+        nof_f_min = 0
+        if args.txd is not None:
+            nof_f_max = args.txd
+        else:
+            nof_f_max = 512  # as default of txd
+        if (args.txfreet < nof_f_min) or (nof_f_max < args.txfreet):
+            print("Error: '%s' should be %d-%d" % (
+                '--txfreet', nof_f_min, nof_f_max))
+            exit()
+        else:
+            testpmd_opts += ['%s=%d' % ('--txfreet', args.txfreet), '\\']
+
+    if args.txrst is not None:
+        nof_r_min = 0
+        if args.txd is not None:
+            nof_r_max = args.txd
+        else:
+            nof_r_max = 512  # as default of txd
+        if (args.txrst < nof_r_min) or (nof_r_max < args.txrst):
+            print("Error: '%s' should be %d-%d" % (
+                '--txrst', nof_r_min, nof_r_max))
+            exit()
+        else:
+            testpmd_opts += ['%s=%d' % ('--txrst', args.txrst), '\\']
+
+    # TODO(yasufum) add impl
+    if args.rx_queue_stats_mapping is not None:
+        print_not_supported('--rx-queue-stats-mapping')
+        exit()
+
+    # TODO(yasufum) add impl
+    if args.tx_queue_stats_mapping is not None:
+        print_not_supported('--tx-queue-stats-mapping')
+        exit()
+
+    if args.no_flush_rx is True:
+        testpmd_opts += ['--no-flush-rx', '\\']
+
+    if args.txpkts is not None:
+        if check_txpkts(args.txpkts) is True:
+            testpmd_opts += ['%s=%s' % (
+                '--txpkts', args.txpkts), '\\']
+        else:
+            print("Error: invalid '--txpkts' option")
+            exit()
+
+    if args.disable_link_check is True:
+        testpmd_opts += ['--disable-link-check', '\\']
+
+    if args.no_lsc_interrupt is True:
+        testpmd_opts += ['--no-lsc-interrupt', '\\']
+
+    if args.no_rmv_interrupt is True:
+        testpmd_opts += ['--no-rmv-interrupt', '\\']
+
+    if args.bitrate_stats is not None:
+        # --bitrate-stats can be several
+        for stat in args.bitrate_stats:
+            if stat[0] >= 0:
+                testpmd_opts += ['%s=%d' % (
+                    '--bitrate-stats', stat[0]), '\\']
+            else:
+                print("Error: '--bitrate-stats' should be <= 0")
+                exit()
+
+    if args.print_event is not None:
+        if check_event(args.print_event) is True:
+            testpmd_opts += ['%s=%s' % (
+                '--print-event', args.print_event), '\\']
+        else:
+            print("Error: invalid '--print-event' option")
+            exit()
+
+    if args.mask_event is not None:
+        if check_event(args.mask_event) is True:
+            testpmd_opts += ['%s=%s' % (
+                '--mask-event', args.mask_event), '\\']
+        else:
+            print("Error: invalid '--mask-event' option")
+            exit()
+
+    if args.flow_isolate_all is True:
+        testpmd_opts += ['--flow-isolate-all', '\\']
+
+    if args.tx_offloads is not None:
+        # TODO(yasufum) check if it is hexadecimal bitmask
+        testpmd_opts += ['%s=%s' % (
+            '--tx-offloads', args.tx_offloads), '\\']
+
+    if args.hot_plug is True:
+        testpmd_opts += ['--hot-plug', '\\']
+
+    if args.vxlan_gpe_port is not None:
+        nof_p_min = 0
+        if (args.vxlan_gpe_port < nof_p_min):
+            print("Error: '%s' should be <= %d" % (
+                '--vxlan-gpe-port', nof_p_min))
+            exit()
+        else:
+            testpmd_opts += ['%s=%d' % (
+                '--vxlan-gpe-port', args.vxlan_gpe_port), '\\']
+
+    if args.mlockall is True:
+        testpmd_opts += ['--mlockall', '\\']
+
+    if args.no_mlockall is True:
+        testpmd_opts += ['--no-mlockall', '\\']
+
+    cmds = docker_cmd + docker_opts + testpmd_cmd + eal_opts + testpmd_opts
+    if cmds[-1] == '\\':
+        cmds.pop()
+    common.print_pretty_commands(cmds)
+
+    if args.dry_run is True:
+        exit()
+
+    # Remove delimiters for print_pretty_commands().
+    while '\\' in cmds:
+        cmds.remove('\\')
+    subprocess.call(cmds)
+
+
+if __name__ == '__main__':
+    main()
-- 
2.17.1

^ permalink raw reply	[flat|nested] 17+ messages in thread

* [spp] [PATCH 10/15] tools/sppc: add l3fwd app continer
  2018-06-15  8:37 [spp] [PATCH 00/15] Add SPP container tools ogawa.yasufumi
                   ` (8 preceding siblings ...)
  2018-06-15  8:37 ` [spp] [PATCH 09/15] tools/sppc: add testpmd " ogawa.yasufumi
@ 2018-06-15  8:37 ` ogawa.yasufumi
  2018-06-15  8:37 ` [spp] [PATCH 11/15] tools/sppc: add pktgen " ogawa.yasufumi
                   ` (5 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: ogawa.yasufumi @ 2018-06-15  8:37 UTC (permalink / raw)
  To: ferruh.yigit, spp; +Cc: Yasufumi Ogawa

From: Yasufumi Ogawa <ogawa.yasufumi@lab.ntt.co.jp>

Signed-off-by: Yasufumi Ogawa <ogawa.yasufumi@lab.ntt.co.jp>
---
 tools/sppc/app/l3fwd.py | 292 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 292 insertions(+)
 create mode 100755 tools/sppc/app/l3fwd.py

diff --git a/tools/sppc/app/l3fwd.py b/tools/sppc/app/l3fwd.py
new file mode 100755
index 0000000..d7e8528
--- /dev/null
+++ b/tools/sppc/app/l3fwd.py
@@ -0,0 +1,292 @@
+#!/usr/bin/env python
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2018 Nippon Telegraph and Telephone Corporation
+
+import argparse
+import os
+import re
+import subprocess
+import sys
+
+work_dir = os.path.dirname(__file__)
+sys.path.append(work_dir + '/..')
+from conf import env
+from lib import app_helper
+from lib import common
+
+target_name = 'dpdk'
+
+
+def parse_args():
+    parser = argparse.ArgumentParser(
+        description="Launcher for l3fwd application container")
+
+    parser = app_helper.add_eal_args(parser)
+    parser = app_helper.add_appc_args(parser)
+
+    # Application specific args
+    parser.add_argument(
+        '-p', '--port-mask',
+        type=str,
+        help='(Mandatory) Port mask')
+    parser.add_argument(
+        '--config',
+        type=str,
+        help='(Mandatory) Define set of port, queue, lcore for ports')
+    parser.add_argument(
+        '-P', '--promiscous',
+        action='store_true',
+        help='Set all ports to promiscous mode (default is None)')
+    parser.add_argument(
+        '-E', '--exact-match',
+        action='store_true',
+        help='Enable exact match (default is None)')
+    parser.add_argument(
+        '-L', '--longest-prefix-match',
+        action='store_true',
+        help='Enable longest prefix match (default is None)')
+    parser.add_argument(
+        '-dst', '--eth-dest',
+        nargs='*',
+        action='append',
+        type=str,
+        help='Ethernet dest for port X (X,MM:MM:MM:MM:MM:MM)')
+    parser.add_argument(
+        '--enable-jumbo',
+        action='store_true',
+        help='Enable jumbo frames, [--enable-jumbo [--max-pkt-len PKTLEN]]')
+    parser.add_argument(
+        '--max-pkt-len',
+        type=int,
+        help='Max packet length (64-9600) if jumbo is enabled.')
+    parser.add_argument(
+        '--no-numa',
+        action='store_true',
+        help='Disable NUMA awareness (default is None)')
+    parser.add_argument(
+        '--hash-entry-num',
+        action='store_true',
+        help='Specify the hash entry number in hexadecimal (default is None)')
+    parser.add_argument(
+        '--ipv6',
+        action='store_true',
+        help='Specify the hash entry number in hexadecimal (default is None)')
+    parser.add_argument(
+        '--parse-ptype',
+        type=str,
+        default='ipv4',
+        help='Set analyze packet type, ipv4 or ipv6 (default is ipv4)')
+
+    parser = app_helper.add_sppc_args(parser)
+
+    return parser.parse_args()
+
+
+def check_config_format(config_opt, nof_queues):
+    """Check if config format is valid
+
+    Config options is for Determining which queues from which ports
+    are mapped to which cores.
+
+      --config (port,queue,lcore)[,(port,queue,lcore)]
+
+    Queue IDs should be started from 0 and sequential for each of
+    ports. For example, '(0,1,0),(0,0,1)' is invlid because queue IDs
+    of port 0 are '1, 0' and it does started from 1 and not sequential.
+
+    The number of tx queues should be equal or less than the number of
+    queues of virtio device defined with '-nq' or '--nof-queues' option.
+    """
+
+    config_opt = re.sub(r'\s+', '', config_opt)
+
+    config_opt = config_opt.lstrip('(').rstrip(')')
+    nof_tx_queues = len(config_opt.split('),('))
+
+    ptn = re.compile(r'(\d+)\,(\d+)\,(\d+)')
+    port_conf = {}
+    for c in config_opt.split('),('):
+        m = re.match(ptn, c)
+        port_idx = int(m.group(1))
+        if port_conf.get(port_idx) is None:
+            port_conf[port_idx] = [[int(m.group(2)), int(m.group(3))]]
+        else:
+            port_conf[port_idx].append([int(m.group(2)), int(m.group(3))])
+
+    for attrs in port_conf.values():
+        i = 0
+        for attr in attrs:
+            if attr[0] != i:
+                print('Error: queue ids should be started from 0 ' +
+                      'and sequential!')
+                return False
+            i = i + 1
+
+    if nof_tx_queues > nof_queues:
+        print('Error: %s=%d should be equal or less than %s=%d!' %
+              ('tx_queues', nof_tx_queues, 'nof_queues', nof_queues))
+        print("\tnof_queues is defiend with '-nq' or '--nof-queues' option")
+        return False
+
+    return True
+
+
+def check_jumbo_opt(enable_jumbo, max_pkt_len):
+    """Check if jumbo frame option is valid
+
+    Jumbo frame is enabled with '--enable-jumbo' and max packet size is
+    defined with '--max-pkt-len'.
+    '--max-pkt-len' cannot be used without '--enable-jumbo'.
+    """
+
+    if (enable_jumbo is None) and (max_pkt_len is not None):
+        print('Error: --enable-jumbo is required')
+        return False
+
+    if max_pkt_len is not None:
+        if (max_pkt_len < 64) or (max_pkt_len > 9600):
+            print('Error: --max-pkt-len %s should be %d-%d' % (
+                max_pkt_len, 64, 9600))
+            return False
+
+    return True
+
+
+def check_eth_dest(eth_dests):
+    """Check if --eth-dest option is valied
+
+    Format of --eth-dest for port X should be 'X,MM:MM:MM:MM:MM:MM'.
+    This options can be given for several ports and 'eth_dests' arg
+    is passed as a double array as below.
+        [['0,ca:a4:45:e7:6a:ee'], ['1,ca:a4:45:e7:6a:ee'], ...]
+    """
+
+    xx = '[0-9A-Fa-f][0-9A-Fa-f]'
+    ptn = re.compile(
+        r'(\d+),(%s:%s:%s:%s:%s:%s)' % (xx, xx, xx, xx, xx, xx))
+    for eth_dest in eth_dests:
+        m = re.match(ptn, eth_dest[0])
+        if m is None:
+            return False
+
+    return True
+
+
+def main():
+    args = parse_args()
+
+    # Check for other mandatory opitons.
+    if args.port_mask is None:
+        common.error_exit('--port-mask')
+    if args.dev_ids is None:
+        common.error_exit('--dev-ids')
+
+    # Setup for vhost devices with given device IDs.
+    dev_ids_list = app_helper.dev_ids_to_list(args.dev_ids)
+    sock_files = app_helper.sock_files(dev_ids_list)
+
+    # Setup docker command.
+    docker_cmd = ['sudo', 'docker', 'run', '\\']
+    docker_opts = app_helper.setup_docker_opts(
+        args, target_name, sock_files)
+
+    # Parse vhost device IDs and Check the number of devices is
+    # sufficient for port mask.
+    if app_helper.is_sufficient_dev_ids(
+            args.dev_ids, args.port_mask) is not True:
+        print("Error: Cannot reserve ports '%s (= 0b%s)' on '%s'." % (
+            args.port_mask,
+            format(int(args.port_mask, 16), 'b'),
+            args.dev_ids))
+        exit()
+
+    # Setup l3fwd command runs on container.
+    cmd_path = '%s/examples/l3fwd/%s/l3fwd' % (
+        env.RTE_SDK, env.RTE_TARGET)
+
+    l3fwd_cmd = [cmd_path, '\\']
+
+    # Setup EAL options.
+    file_prefix = 'spp-l3fwd-container%d' % dev_ids_list[0]
+    eal_opts = app_helper.setup_eal_opts(args, file_prefix)
+
+    # Setup l3fwd options.
+    l3fwd_opts = ['-p', args.port_mask, '\\']
+
+    if args.config is None:
+        common.error_exit('--config')
+    elif check_config_format(args.config, args.nof_queues) is not True:
+        print('Invalid config: %s' % args.config)
+        exit()
+    else:
+        l3fwd_opts += ['--config', '"%s"' % args.config, '\\']
+
+    # '--parse-ptype' is optional on host, but not on container.
+    if args.parse_ptype == 'ipv4' or args.parse_ptype == 'ipv6':
+        ptype_valid = True
+    else:
+        ptype_valid = False
+    if ptype_valid is False:
+        print('Error: invalid --parse-ptype %s' % args.parse_ptype)
+        exit()
+    else:
+        l3fwd_opts += ['--parse-ptype', args.parse_ptype, '\\']
+
+    # Check for optional opitons of l3fwd.
+    if (args.exact_match is True) and (args.longest_prefix_match) is True:
+        print('Error: -L and -E are mutually exclusive, select only one')
+        exit()
+
+    jumbo_opt_valid = False
+    if args.enable_jumbo is True:
+        jumbo_opt_valid = check_jumbo_opt(
+            args.enable_jumbo, args.max_pkt_len)
+        if jumbo_opt_valid is False:
+            print('Error: invalid jumbo frame option(s)')
+            exit()
+
+    eth_dest_opt_valid = False
+    if args.eth_dest is not None:
+        eth_dest_opt_valid = check_eth_dest(args.eth_dest)
+        if eth_dest_opt_valid is False:
+            print('Error: invalid --eth-dest option')
+            exit()
+
+    if args.promiscous is True:
+        l3fwd_opts += ['-P', '\\']
+    if args.exact_match is True:
+        l3fwd_opts += ['-E', '\\']
+    if args.longest_prefix_match is True:
+        l3fwd_opts += ['-L', '\\']
+    if (args.eth_dest is not None) and (eth_dest_opt_valid is True):
+        for eth_dest in args.eth_dest:  # args.eth_dest is a double array
+            l3fwd_opts += ['--eth-dest %s' % eth_dest[0], '\\']
+    if (args.enable_jumbo is not None) and (jumbo_opt_valid is True):
+        l3fwd_opts += ['--enable-jumbo', '\\']
+        if args.max_pkt_len is not None:
+            l3fwd_opts += ['--max-pkt-len %d' % args.max_pkt_len, '\\']
+    if args.no_numa is True:
+        l3fwd_opts += ['--no-numa', '\\']
+    if args.hash_entry_num is True:
+        l3fwd_opts += ['--hash-entry-num', '\\']
+    if args.ipv6 is True:
+        l3fwd_opts += ['--ipv6', '\\']
+
+    cmds = docker_cmd + docker_opts + l3fwd_cmd + eal_opts + l3fwd_opts
+    if cmds[-1] == '\\':
+        cmds.pop()
+    common.print_pretty_commands(cmds)
+
+    if args.dry_run is True:
+        exit()
+
+    # Remove delimiters for print_pretty_commands().
+    while '\\' in cmds:
+        cmds.remove('\\')
+    # Call with shell=True because parsing '--eth_dest' option is failed
+    # without it.
+    subprocess.call(' '.join(cmds), shell=True)
+
+
+if __name__ == '__main__':
+    main()
-- 
2.17.1

^ permalink raw reply	[flat|nested] 17+ messages in thread

* [spp] [PATCH 11/15] tools/sppc: add pktgen app continer
  2018-06-15  8:37 [spp] [PATCH 00/15] Add SPP container tools ogawa.yasufumi
                   ` (9 preceding siblings ...)
  2018-06-15  8:37 ` [spp] [PATCH 10/15] tools/sppc: add l3fwd " ogawa.yasufumi
@ 2018-06-15  8:37 ` ogawa.yasufumi
  2018-06-15  8:37 ` [spp] [PATCH 12/15] tools/sppc: add load-balancer " ogawa.yasufumi
                   ` (4 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: ogawa.yasufumi @ 2018-06-15  8:37 UTC (permalink / raw)
  To: ferruh.yigit, spp; +Cc: Yasufumi Ogawa

From: Yasufumi Ogawa <ogawa.yasufumi@lab.ntt.co.jp>

Signed-off-by: Yasufumi Ogawa <ogawa.yasufumi@lab.ntt.co.jp>
---
 tools/sppc/app/pktgen.py | 182 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 182 insertions(+)
 create mode 100755 tools/sppc/app/pktgen.py

diff --git a/tools/sppc/app/pktgen.py b/tools/sppc/app/pktgen.py
new file mode 100755
index 0000000..0b79bd3
--- /dev/null
+++ b/tools/sppc/app/pktgen.py
@@ -0,0 +1,182 @@
+#!/usr/bin/env python
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2018 Nippon Telegraph and Telephone Corporation
+
+import argparse
+import os
+import subprocess
+import sys
+
+work_dir = os.path.dirname(__file__)
+sys.path.append(work_dir + '/..')
+from conf import env
+from lib import app_helper
+from lib import common
+
+target_name = 'pktgen'
+
+
+def parse_args():
+    parser = argparse.ArgumentParser(
+        description="Launcher for pktgen-dpdk application container")
+
+    parser = app_helper.add_eal_args(parser)
+    parser = app_helper.add_appc_args(parser)
+
+    parser.add_argument(
+        '-s', '--pcap-file',
+        type=str,
+        help="PCAP packet flow file of port, defined as 'N:filename'")
+    parser.add_argument(
+        '-f', '--script-file',
+        type=str,
+        help="Pktgen script (.pkt) to or a Lua script (.lua)")
+    parser.add_argument(
+        '-lf', '--log-file',
+        type=str,
+        help="Filename to write a log, as '-l' of pktgen")
+    parser.add_argument(
+        '-P', '--promiscuous',
+        action='store_true',
+        help="Enable PROMISCUOUS mode on all ports")
+    parser.add_argument(
+        '-G', '--sock-default',
+        action='store_true',
+        help="Enable socket support using default server values of " +
+        "localhost:0x5606")
+    parser.add_argument(
+        '-g', '--sock-address',
+        type=str,
+        help="Same as -G but with an optional IP address and port number")
+    parser.add_argument(
+        '-T', '--term-color',
+        action='store_true',
+        help="Enable color terminal output in VT100")
+    parser.add_argument(
+        '-N', '--numa',
+        action='store_true',
+        help="Enable NUMA support")
+    parser.add_argument(
+        '--matrix',
+        type=str,
+        help="Matrix of cores and port as '-m' of pktgen, " +
+        "such as [1:2].0 or 1.0")
+
+    parser = app_helper.add_sppc_args(parser)
+    return parser.parse_args()
+
+
+def main():
+    args = parse_args()
+
+    # Setup for vhost devices with given device IDs.
+    dev_ids_list = app_helper.dev_ids_to_list(args.dev_ids)
+    sock_files = app_helper.sock_files(dev_ids_list)
+
+    # Setup docker command.
+    docker_cmd = ['sudo', 'docker', 'run', '\\']
+    docker_opts = app_helper.setup_docker_opts(
+        args, target_name, sock_files,
+        '%s/../pktgen-dpdk' % env.RTE_SDK)
+
+    cmd_path = '%s/../pktgen-dpdk/app/%s/pktgen' % (
+        env.RTE_SDK, env.RTE_TARGET)
+
+    # Setup pktgen command
+    pktgen_cmd = [cmd_path, '\\']
+
+    file_prefix = 'spp-pktgen-container%d' % dev_ids_list[0]
+    eal_opts = app_helper.setup_eal_opts(args, file_prefix)
+
+    # Setup matrix for assignment of cores and ports.
+    if args.matrix is not None:
+        matrix = args.matrix
+    else:
+        # Get core_list such as [0,1,2] from '-c 0x07' or '-l 0-2'
+        core_opt = app_helper.get_core_opt(args)
+        core_list = app_helper.cores_to_list(core_opt)
+        if len(core_list) < 2:
+            print("Error: Two or more cores required!")
+            exit()
+
+        slave_core_list = core_list[1:]
+        nof_slave_cores = len(slave_core_list)
+        nof_ports = len(dev_ids_list)
+        nof_cores_each_port = nof_slave_cores / nof_ports
+        if nof_cores_each_port < 1:
+            print("Error: Too few cores for given port(s)!")
+            print("%d cores required for %d port(s)" % (
+                (nof_slave_cores + 1), nof_ports))
+            exit()
+
+        matrix_list = []
+        if nof_cores_each_port == 1:
+            for i in range(0, nof_ports):
+                matrix_list.append('%d.%d' % (slave_core_list[i], i))
+        elif nof_cores_each_port == 2:
+            for i in range(0, nof_ports):
+                matrix_list.append('[%d:%d].%d' % (
+                    slave_core_list[2*i], slave_core_list[2*i + 1], i))
+        elif nof_cores_each_port == 3:  # Two cores for rx, one for tx
+            for i in range(0, nof_ports):
+                matrix_list.append('[%d-%d:%d].%d' % (
+                    slave_core_list[3*i],
+                    slave_core_list[3*i + 1],
+                    slave_core_list[3*i + 2], i))
+        elif nof_cores_each_port == 4:
+            for i in range(0, nof_ports):
+                matrix_list.append('[%d-%d:%d-%d].%d' % (
+                    slave_core_list[4*i],
+                    slave_core_list[4*i + 1],
+                    slave_core_list[4*i + 2],
+                    slave_core_list[4*i + 3], i))
+        # Do not support more than five because it is rare case and
+        # calculation is complex.
+        else:
+            print("Error: Too many cores for calculation for ports!")
+            print("Consider to use '--matrix' for assigning directly")
+            exit()
+        matrix = ','.join(matrix_list)
+
+    pktgen_opts = ['-m', matrix, '\\']
+
+    if args.pcap_file is not None:
+        pktgen_opts += ['-s', args.pcap_file, '\\']
+
+    if args.script_file is not None:
+        pktgen_opts += ['-f', args.script_file, '\\']
+
+    if args.log_file is not None:
+        pktgen_opts += ['-l', args.log_file, '\\']
+
+    if args.promiscuous is True:
+        pktgen_opts += ['-P', '\\']
+
+    if args.sock_default is True:
+        pktgen_opts += ['-G', '\\']
+
+    if args.sock_address is not None:
+        pktgen_opts += ['-g', args.sock_address, '\\']
+
+    if args.term_color is True:
+        pktgen_opts += ['-T', '\\']
+
+    if args.numa is True:
+        pktgen_opts += ['-N', '\\']
+
+    cmds = docker_cmd + docker_opts + pktgen_cmd + eal_opts + pktgen_opts
+    if cmds[-1] == '\\':
+        cmds.pop()
+    common.print_pretty_commands(cmds)
+
+    if args.dry_run is True:
+        exit()
+
+    # Remove delimiters for print_pretty_commands().
+    while '\\' in cmds:
+        cmds.remove('\\')
+    subprocess.call(cmds)
+
+
+if __name__ == '__main__':
+    main()
-- 
2.17.1

^ permalink raw reply	[flat|nested] 17+ messages in thread

* [spp] [PATCH 12/15] tools/sppc: add load-balancer app continer
  2018-06-15  8:37 [spp] [PATCH 00/15] Add SPP container tools ogawa.yasufumi
                   ` (10 preceding siblings ...)
  2018-06-15  8:37 ` [spp] [PATCH 11/15] tools/sppc: add pktgen " ogawa.yasufumi
@ 2018-06-15  8:37 ` ogawa.yasufumi
  2018-06-15  8:37 ` [spp] [PATCH 13/15] tools/sppc: add helloworld " ogawa.yasufumi
                   ` (3 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: ogawa.yasufumi @ 2018-06-15  8:37 UTC (permalink / raw)
  To: ferruh.yigit, spp; +Cc: Yasufumi Ogawa

From: Yasufumi Ogawa <ogawa.yasufumi@lab.ntt.co.jp>

Signed-off-by: Yasufumi Ogawa <ogawa.yasufumi@lab.ntt.co.jp>
---
 tools/sppc/app/load-balancer.py | 141 ++++++++++++++++++++++++++++++++
 1 file changed, 141 insertions(+)
 create mode 100755 tools/sppc/app/load-balancer.py

diff --git a/tools/sppc/app/load-balancer.py b/tools/sppc/app/load-balancer.py
new file mode 100755
index 0000000..0f6d6e1
--- /dev/null
+++ b/tools/sppc/app/load-balancer.py
@@ -0,0 +1,141 @@
+#!/usr/bin/env python
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2018 Nippon Telegraph and Telephone Corporation
+
+import argparse
+import os
+import subprocess
+import sys
+
+work_dir = os.path.dirname(__file__)
+sys.path.append(work_dir + '/..')
+from conf import env
+from lib import app_helper
+from lib import common
+
+target_name = 'dpdk'
+
+
+def parse_args():
+    parser = argparse.ArgumentParser(
+        description="Launcher for load-balancer application container")
+
+    parser = app_helper.add_eal_args(parser)
+    parser = app_helper.add_appc_args(parser)
+
+    # Application specific args
+    parser.add_argument(
+        '-rx', '--rx-ports',
+        type=str,
+        help="List of rx ports and queues handled by the I/O rx lcores")
+    parser.add_argument(
+        '-tx', '--tx-ports',
+        type=str,
+        help="List of tx ports and queues handled by the I/O tx lcores")
+    parser.add_argument(
+        '-w', '--worker-lcores',
+        type=str,
+        help="List of worker lcores")
+    parser.add_argument(
+        '-rsz', '--ring-sizes',
+        type=str,
+        help="Ring sizes of 'rx_read,rx_send,w_send,tx_written'")
+    parser.add_argument(
+        '-bsz', '--burst-sizes',
+        type=str,
+        help="Burst sizes of rx, worker or tx")
+    parser.add_argument(
+        '--lpm',
+        type=str,
+        help="List of LPM rules")
+    parser.add_argument(
+        '--pos-lb',
+        type=int,
+        help="Position of the 1-byte field used for identify worker")
+
+    parser = app_helper.add_sppc_args(parser)
+    return parser.parse_args()
+
+
+def main():
+    args = parse_args()
+
+    # Check for other mandatory opitons.
+    if args.dev_ids is None:
+        common.error_exit('--dev-ids')
+
+    # Setup for vhost devices with given device IDs.
+    dev_ids_list = app_helper.dev_ids_to_list(args.dev_ids)
+    sock_files = app_helper.sock_files(dev_ids_list)
+
+    # Setup docker command.
+    docker_cmd = ['sudo', 'docker', 'run', '\\']
+    docker_opts = app_helper.setup_docker_opts(
+        args, target_name, sock_files)
+
+    app_name = 'load_balancer'
+    cmd_path = '%s/examples/%s/%s/%s' % (
+        env.RTE_SDK, app_name, env.RTE_TARGET, app_name)
+
+    # Setup testpmd command.
+    lb_cmd = [cmd_path, '\\']
+
+    file_prefix = 'spp-lb-container%d' % dev_ids_list[0]
+    eal_opts = app_helper.setup_eal_opts(args, file_prefix)
+
+    lb_opts = []
+
+    # Check for other mandatory opitons.
+    if args.rx_ports is None:
+        common.error_exit('--rx-ports')
+    else:
+        rx_ports = '"%s"' % args.rx_ports
+        lb_opts += ['--rx', rx_ports, '\\']
+
+    if args.tx_ports is None:
+        common.error_exit('--tx-ports')
+    else:
+        tx_ports = '"%s"' % args.tx_ports
+        lb_opts += ['--tx', tx_ports, '\\']
+
+    if args.worker_lcores is None:
+        common.error_exit('--worker-lcores')
+    else:
+        worker_lcores = '%s' % args.worker_lcores
+        lb_opts += ['--w', worker_lcores, '\\']
+
+    if args.lpm is None:
+        common.error_exit('--lpm')
+    else:
+        lpm = '"%s"' % args.lpm
+        lb_opts += ['--lpm', lpm, '\\']
+
+    # Check optional opitons.
+    if args.ring_sizes is not None:
+        lb_opts += [
+            '--ring-sizes', args.ring_sizes, '\\']
+    if args.burst_sizes is not None:
+        lb_opts += [
+            '--burst-sizes', args.burst_sizes, '\\']
+    if args.pos_lb is not None:
+        lb_opts += [
+            '--pos-lb', str(args.pos_lb)]
+
+    cmds = docker_cmd + docker_opts + lb_cmd + eal_opts + lb_opts
+    if cmds[-1] == '\\':
+        cmds.pop()
+    common.print_pretty_commands(cmds)
+
+    if args.dry_run is True:
+        exit()
+
+    # Remove delimiters for print_pretty_commands().
+    while '\\' in cmds:
+        cmds.remove('\\')
+    # Call with shell=True because parsing '--w' option is failed
+    # without it.
+    subprocess.call(' '.join(cmds), shell=True)
+
+
+if __name__ == '__main__':
+    main()
-- 
2.17.1

^ permalink raw reply	[flat|nested] 17+ messages in thread

* [spp] [PATCH 13/15] tools/sppc: add helloworld app continer
  2018-06-15  8:37 [spp] [PATCH 00/15] Add SPP container tools ogawa.yasufumi
                   ` (11 preceding siblings ...)
  2018-06-15  8:37 ` [spp] [PATCH 12/15] tools/sppc: add load-balancer " ogawa.yasufumi
@ 2018-06-15  8:37 ` ogawa.yasufumi
  2018-06-15  8:37 ` [spp] [PATCH 14/15] tools/sppc: add helper script for build ogawa.yasufumi
                   ` (2 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: ogawa.yasufumi @ 2018-06-15  8:37 UTC (permalink / raw)
  To: ferruh.yigit, spp; +Cc: Yasufumi Ogawa

From: Yasufumi Ogawa <ogawa.yasufumi@lab.ntt.co.jp>

Signed-off-by: Yasufumi Ogawa <ogawa.yasufumi@lab.ntt.co.jp>
---
 tools/sppc/app/helloworld.py | 75 ++++++++++++++++++++++++++++++++++++
 1 file changed, 75 insertions(+)
 create mode 100755 tools/sppc/app/helloworld.py

diff --git a/tools/sppc/app/helloworld.py b/tools/sppc/app/helloworld.py
new file mode 100755
index 0000000..fada61e
--- /dev/null
+++ b/tools/sppc/app/helloworld.py
@@ -0,0 +1,75 @@
+#!/usr/bin/env python
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2018 Nippon Telegraph and Telephone Corporation
+
+import argparse
+import os
+import subprocess
+import sys
+
+work_dir = os.path.dirname(__file__)
+sys.path.append(work_dir + '/..')
+from conf import env
+from lib import app_helper
+from lib import common
+
+target_name = 'dpdk'
+
+
+def parse_args():
+    parser = argparse.ArgumentParser(
+        description="Launcher for l2fwd application container")
+
+    parser = app_helper.add_eal_args(parser)
+    parser = app_helper.add_appc_args(parser)
+
+    # No application specific args for helloworld
+
+    parser = app_helper.add_sppc_args(parser)
+    return parser.parse_args()
+
+
+def main():
+    args = parse_args()
+
+    # Check for other mandatory opitons.
+    if args.dev_ids is None:
+        common.error_exit('--dev-ids')
+
+    # Setup for vhost devices with given device IDs.
+    dev_ids_list = app_helper.dev_ids_to_list(args.dev_ids)
+    sock_files = app_helper.sock_files(dev_ids_list)
+
+    # Setup docker command.
+    docker_cmd = ['sudo', 'docker', 'run', '\\']
+    docker_opts = app_helper.setup_docker_opts(
+        args, target_name, sock_files)
+
+    # Setup helloworld run on container.
+    cmd_path = '%s/examples/helloworld/%s/helloworld' % (
+        env.RTE_SDK, env.RTE_TARGET)
+
+    hello_cmd = [cmd_path, '\\']
+
+    file_prefix = 'spp-hello-container%d' % dev_ids_list[0]
+    eal_opts = app_helper.setup_eal_opts(args, file_prefix)
+
+    # No application specific options for helloworld
+    hello_opts = []
+
+    cmds = docker_cmd + docker_opts + hello_cmd + eal_opts + hello_opts
+    if cmds[-1] == '\\':
+        cmds.pop()
+    common.print_pretty_commands(cmds)
+
+    if args.dry_run is True:
+        exit()
+
+    # Remove delimiters for print_pretty_commands().
+    while '\\' in cmds:
+        cmds.remove('\\')
+    subprocess.call(cmds)
+
+
+if __name__ == '__main__':
+    main()
-- 
2.17.1

^ permalink raw reply	[flat|nested] 17+ messages in thread

* [spp] [PATCH 14/15] tools/sppc: add helper script for build
  2018-06-15  8:37 [spp] [PATCH 00/15] Add SPP container tools ogawa.yasufumi
                   ` (12 preceding siblings ...)
  2018-06-15  8:37 ` [spp] [PATCH 13/15] tools/sppc: add helloworld " ogawa.yasufumi
@ 2018-06-15  8:37 ` ogawa.yasufumi
  2018-06-15  8:37 ` [spp] [PATCH 15/15] tools/sppc: add spp launcher script ogawa.yasufumi
  2018-08-15 15:34 ` [spp] [PATCH 00/15] Add SPP container tools Ferruh Yigit
  15 siblings, 0 replies; 17+ messages in thread
From: ogawa.yasufumi @ 2018-06-15  8:37 UTC (permalink / raw)
  To: ferruh.yigit, spp; +Cc: Yasufumi Ogawa

From: Yasufumi Ogawa <ogawa.yasufumi@lab.ntt.co.jp>

'build/run.sh' is a helper script to inspect inside the container.
You can run bash on the container to confirm behaviour of targetting
application, or run any of command.

Signed-off-by: Yasufumi Ogawa <ogawa.yasufumi@lab.ntt.co.jp>
---
 tools/sppc/build/run.sh | 34 ++++++++++++++++++++++++++++++++++
 1 file changed, 34 insertions(+)
 create mode 100755 tools/sppc/build/run.sh

diff --git a/tools/sppc/build/run.sh b/tools/sppc/build/run.sh
new file mode 100755
index 0000000..ace7ee8
--- /dev/null
+++ b/tools/sppc/build/run.sh
@@ -0,0 +1,34 @@
+#!/bin/bash
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2018 Nippon Telegraph and Telephone Corporation
+
+CONTAINER_IMG_NAME=$1
+CMD=$2
+APP_DIR=`dirname ${0}`
+ENVSH=${APP_DIR}/ubuntu/dpdk/env.sh
+
+# Include env.sh
+if [ -e ${ENVSH} ];then
+  . ${ENVSH}
+else
+  _build_env='./build/main.py --only-envsh'
+  echo "[Error] ${ENVSH} does not exist!"
+  echo "You have to build image or run '${_build_env}' to create it."
+  exit
+fi
+
+if [ ! $2 ]; then
+  echo "usage: $0 [IMAGE] [COMMAND]"
+  exit
+fi
+
+#cd ${APP_DIR}; \
+sudo docker run -i -t \
+	-e http_proxy=${http_proxy} \
+	-e https_proxy=${https_proxy} \
+	-e HTTP_PROXY=${http_proxy} \
+	-e HTTPS_PROXY=${https_proxy} \
+	-e RTE_SDK=${RTE_SDK} \
+	-e RTE_TARGET=${RTE_TARGET} \
+	${CONTAINER_IMG_NAME} \
+  ${CMD}
-- 
2.17.1

^ permalink raw reply	[flat|nested] 17+ messages in thread

* [spp] [PATCH 15/15] tools/sppc: add spp launcher script
  2018-06-15  8:37 [spp] [PATCH 00/15] Add SPP container tools ogawa.yasufumi
                   ` (13 preceding siblings ...)
  2018-06-15  8:37 ` [spp] [PATCH 14/15] tools/sppc: add helper script for build ogawa.yasufumi
@ 2018-06-15  8:37 ` ogawa.yasufumi
  2018-08-15 15:34 ` [spp] [PATCH 00/15] Add SPP container tools Ferruh Yigit
  15 siblings, 0 replies; 17+ messages in thread
From: ogawa.yasufumi @ 2018-06-15  8:37 UTC (permalink / raw)
  To: ferruh.yigit, spp; +Cc: Yasufumi Ogawa

From: Yasufumi Ogawa <ogawa.yasufumi@lab.ntt.co.jp>

SPP consists of a primary and several secondary processes. It usually
five or more processes are required to configure network, but it takes
a time to launch processes one by one.

This patch is for adding a helper script to launch all of processes
at once.

Signed-off-by: Yasufumi Ogawa <ogawa.yasufumi@lab.ntt.co.jp>
---
 tools/sppc/tools/spp-launcher.py | 96 ++++++++++++++++++++++++++++++++
 1 file changed, 96 insertions(+)
 create mode 100755 tools/sppc/tools/spp-launcher.py

diff --git a/tools/sppc/tools/spp-launcher.py b/tools/sppc/tools/spp-launcher.py
new file mode 100755
index 0000000..0bdd6e3
--- /dev/null
+++ b/tools/sppc/tools/spp-launcher.py
@@ -0,0 +1,96 @@
+#!/usr/bin/env python
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2018 Nippon Telegraph and Telephone Corporation
+
+import argparse
+import subprocess
+from time import sleep
+
+
+def parse_args():
+    parser = argparse.ArgumentParser(
+        description="Launcher for SPP")
+
+    parser.add_argument(
+        '-pl', '--pri-lcore',
+        type=int,
+        default='0',
+        help="SPP primary lcore ID")
+    parser.add_argument(
+        '-dt', '--dev-tap-ids',
+        type=str,
+        default='1',
+        help="Set of IDs of TAP device such as '1,2'")
+    parser.add_argument(
+        '-p', '--portmask',
+        type=str,
+        default='0x01',
+        help="Portmask")
+    parser.add_argument(
+        '-sid', '--nfv-master-lcore-id',
+        type=int,
+        default=1,
+        help="ID of spp_nfv master lcore")
+    parser.add_argument(
+        '-n', '--nof-spp-nfv',
+        type=int,
+        default=1,
+        help="Number of spp_nfv")
+    parser.add_argument(
+        '--shared',
+        action='store_true',
+        help="Set master lcore is shared among spp_nfv(s)")
+    parser.add_argument(
+        '--dist-ver',
+        type=str,
+        default='latest',
+        help="Version of Linux distribution")
+    parser.add_argument(
+        '-wt', '--wait-time',
+        type=int,
+        default=1,
+        help="Sleep time for waiting launching spp_nfv(s)")
+
+    return parser.parse_args()
+
+
+def main():
+    args = parse_args()
+
+    cmd = ['app/spp-primary.py',
+           '-l', str(args.pri_lcore),
+           '-dt', args.dev_tap_ids,
+           '-p', args.portmask,
+           '--dist-ver', args.dist_ver]
+    subprocess.call(cmd)
+
+    sleep(args.wait_time)
+
+    master_id = args.nfv_master_lcore_id
+    for i in range(1, args.nof_spp_nfv + 1):
+        cmd = ['sudo', 'rm', '-rf', '/tmp/sock%d' % i]
+        subprocess.call(cmd)
+
+        if args.shared is True:
+            slave_id = master_id + i
+            l_opt = '%d,%d' % (master_id, slave_id)
+        else:
+            slave_id = master_id + 1
+            l_opt = '%d,%d' % (master_id, slave_id)
+            # update master lcore ID to not be shared
+            master_id = slave_id + 1
+
+        if (args.pri_lcore == master_id) or (args.pri_lcore == slave_id):
+            print("Error: cannot assign primary and secondary " +
+                  "on the same lcore")
+            exit()
+
+        cmd = ['app/spp-nfv.py',
+               '-i', str(i),
+               '-l', l_opt,
+               '--dist-ver', args.dist_ver]
+        subprocess.call(cmd)
+
+
+if __name__ == '__main__':
+    main()
-- 
2.17.1

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [spp] [PATCH 00/15] Add SPP container tools
  2018-06-15  8:37 [spp] [PATCH 00/15] Add SPP container tools ogawa.yasufumi
                   ` (14 preceding siblings ...)
  2018-06-15  8:37 ` [spp] [PATCH 15/15] tools/sppc: add spp launcher script ogawa.yasufumi
@ 2018-08-15 15:34 ` Ferruh Yigit
  15 siblings, 0 replies; 17+ messages in thread
From: Ferruh Yigit @ 2018-08-15 15:34 UTC (permalink / raw)
  To: ogawa.yasufumi, spp

On 6/15/2018 9:37 AM, ogawa.yasufumi@lab.ntt.co.jp wrote:
> From: Yasufumi Ogawa <ogawa.yasufumi@lab.ntt.co.jp>
> 
> This series of patches is to add SPP container. It consists of build
> tool and app container launcher scripts.
> 
> Build tool is for creating container image and install DPDK and
> applications on the image. It also includes Dockerfiles of several
> versions of DPDK and Ubuntu.
> 
> App container scripts for launching app container with simple command
> line interfaces.
> 
> 
> Yasufumi Ogawa (15):
>   tools/sppc: add SPP container build tool
>   tools/sppc: add dockerfiles for DPDK
>   tools/sppc: add dockerfiles for pktgen
>   tools/sppc: add dockerfiles for SPP
>   tools/sppc: add spp-primary app continer
>   tools/sppc: add spp-nfv app continer
>   tools/sppc: add spp-vm app continer
>   tools/sppc: add l2fwd app continer
>   tools/sppc: add testpmd app continer
>   tools/sppc: add l3fwd app continer
>   tools/sppc: add pktgen app continer
>   tools/sppc: add load-balancer app continer
>   tools/sppc: add helloworld app continer
>   tools/sppc: add helper script for build
>   tools/sppc: add spp launcher script

Series applied, thanks.

^ permalink raw reply	[flat|nested] 17+ messages in thread

end of thread, other threads:[~2018-08-15 15:34 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-06-15  8:37 [spp] [PATCH 00/15] Add SPP container tools ogawa.yasufumi
2018-06-15  8:37 ` [spp] [PATCH 01/15] tools/sppc: add SPP container build tool ogawa.yasufumi
2018-06-15  8:37 ` [spp] [PATCH 02/15] tools/sppc: add dockerfiles for DPDK ogawa.yasufumi
2018-06-15  8:37 ` [spp] [PATCH 03/15] tools/sppc: add dockerfiles for pktgen ogawa.yasufumi
2018-06-15  8:37 ` [spp] [PATCH 04/15] tools/sppc: add dockerfiles for SPP ogawa.yasufumi
2018-06-15  8:37 ` [spp] [PATCH 05/15] tools/sppc: add spp-primary app continer ogawa.yasufumi
2018-06-15  8:37 ` [spp] [PATCH 06/15] tools/sppc: add spp-nfv " ogawa.yasufumi
2018-06-15  8:37 ` [spp] [PATCH 07/15] tools/sppc: add spp-vm " ogawa.yasufumi
2018-06-15  8:37 ` [spp] [PATCH 08/15] tools/sppc: add l2fwd " ogawa.yasufumi
2018-06-15  8:37 ` [spp] [PATCH 09/15] tools/sppc: add testpmd " ogawa.yasufumi
2018-06-15  8:37 ` [spp] [PATCH 10/15] tools/sppc: add l3fwd " ogawa.yasufumi
2018-06-15  8:37 ` [spp] [PATCH 11/15] tools/sppc: add pktgen " ogawa.yasufumi
2018-06-15  8:37 ` [spp] [PATCH 12/15] tools/sppc: add load-balancer " ogawa.yasufumi
2018-06-15  8:37 ` [spp] [PATCH 13/15] tools/sppc: add helloworld " ogawa.yasufumi
2018-06-15  8:37 ` [spp] [PATCH 14/15] tools/sppc: add helper script for build ogawa.yasufumi
2018-06-15  8:37 ` [spp] [PATCH 15/15] tools/sppc: add spp launcher script ogawa.yasufumi
2018-08-15 15:34 ` [spp] [PATCH 00/15] Add SPP container tools Ferruh Yigit

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).