From: ogawa.yasufumi@lab.ntt.co.jp
To: ferruh.yigit@intel.com, spp@dpdk.org
Cc: Yasufumi Ogawa <ogawa.yasufumi@lab.ntt.co.jp>
Subject: [spp] [PATCH 05/15] tools/sppc: add spp-primary app continer
Date: Fri, 15 Jun 2018 17:37:44 +0900 [thread overview]
Message-ID: <20180615083754.20220-6-ogawa.yasufumi@lab.ntt.co.jp> (raw)
In-Reply-To: <20180615083754.20220-1-ogawa.yasufumi@lab.ntt.co.jp>
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
next prev parent reply other threads:[~2018-06-15 8:38 UTC|newest]
Thread overview: 17+ messages / expand[flat|nested] mbox.gz Atom feed top
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 ` ogawa.yasufumi [this message]
2018-06-15 8:37 ` [spp] [PATCH 06/15] tools/sppc: add spp-nfv app continer 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
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20180615083754.20220-6-ogawa.yasufumi@lab.ntt.co.jp \
--to=ogawa.yasufumi@lab.ntt.co.jp \
--cc=ferruh.yigit@intel.com \
--cc=spp@dpdk.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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).