From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mogw0505.ocn.ad.jp (mogw0505.ocn.ad.jp [118.23.178.147]) by dpdk.org (Postfix) with ESMTP id B62BF1D8DB for ; Fri, 15 Jun 2018 10:38:03 +0200 (CEST) Received: from mf-smf-ucb033c2 (mf-smf-ucb033c2.ocn.ad.jp [153.153.66.225]) by mogw0505.ocn.ad.jp (Postfix) with ESMTP id 560AE39830E; Fri, 15 Jun 2018 17:38:02 +0900 (JST) Received: from ntt.pod01.mv-mta-ucb021 ([153.149.142.84]) by mf-smf-ucb033c2 with ESMTP id TkF3fICaKSNiFTkF8f8dYT; Fri, 15 Jun 2018 17:38:02 +0900 Received: from smtp.ocn.ne.jp ([153.149.227.166]) by ntt.pod01.mv-mta-ucb021 with id ywe11x00t3c2f7501we1Bj; Fri, 15 Jun 2018 08:38:02 +0000 Received: from localhost.localdomain (p5164-ipngn8501marunouchi.tokyo.ocn.ne.jp [153.214.228.164]) by smtp.ocn.ne.jp (Postfix) with ESMTPA; Fri, 15 Jun 2018 17:38:01 +0900 (JST) From: ogawa.yasufumi@lab.ntt.co.jp To: ferruh.yigit@intel.com, spp@dpdk.org Cc: Yasufumi Ogawa Date: Fri, 15 Jun 2018 17:37:44 +0900 Message-Id: <20180615083754.20220-6-ogawa.yasufumi@lab.ntt.co.jp> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20180615083754.20220-1-ogawa.yasufumi@lab.ntt.co.jp> References: <20180615083754.20220-1-ogawa.yasufumi@lab.ntt.co.jp> Subject: [spp] [PATCH 05/15] tools/sppc: add spp-primary app continer X-BeenThere: spp@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: Soft Patch Panel List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 15 Jun 2018 08:38:04 -0000 From: Yasufumi Ogawa 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 --- 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