Soft Patch Panel
 help / color / mirror / Atom feed
From: ogawa.yasufumi@lab.ntt.co.jp
To: spp@dpdk.org, ferruh.yigit@intel.com, ogawa.yasufumi@lab.ntt.co.jp
Subject: [spp] [PATCH 1/5] controller: add config command
Date: Mon,  4 Feb 2019 12:11:57 +0900	[thread overview]
Message-ID: <1549249921-31638-2-git-send-email-ogawa.yasufumi@lab.ntt.co.jp> (raw)
In-Reply-To: <1549249921-31638-1-git-send-email-ogawa.yasufumi@lab.ntt.co.jp>

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

`config` command is for managing default configurations of SPP CLI.
For example, you can change default command prompt `spp > ` to another
one.

List of all of configurations is referred with `config`, or list of
started with `p` is referred with `config p`.

  # show all configs
  spp > config
  - topo_size: "60%"	# Percentage or ratio of topo
  - prompt: "spp > "	# Command prompt
  ...

  # only started with `p`
  spp > config p
  - prompt: "spp > "	# Command prompt

To change configuration, specify key and its value.

  # set prompt
  Set prompt: "$ spp "
  $ spp

Signed-off-by: Yasufumi Ogawa <ogawa.yasufumi@lab.ntt.co.jp>
---
 src/controller/commands/pri.py |  14 ++++--
 src/controller/shell.py        | 103 ++++++++++++++++++++++++++++++++++++++---
 2 files changed, 105 insertions(+), 12 deletions(-)

diff --git a/src/controller/commands/pri.py b/src/controller/commands/pri.py
index b9f1234..b03524b 100644
--- a/src/controller/commands/pri.py
+++ b/src/controller/commands/pri.py
@@ -141,7 +141,7 @@ class SppPrimary(object):
                     rports['id'], rports['rx'],  rports['tx'],
                     rports['rx_drop'], rports['tx_drop']))
 
-    def complete(self, text, line, begidx, endidx):
+    def complete(self, text, line, begidx, endidx, cli_config, template):
         """Completion for primary process commands.
 
         Called from complete_pri() to complete primary command.
@@ -150,8 +150,12 @@ class SppPrimary(object):
         candidates = []
         tokens = line.split(' ')
 
-        base_core = 1  # shared among secondaries
-        mytemplate = "-l {},{} -m 512 -- {} {} -s {}"
+        template = template.replace('__MEM__', cli_config['sec_mem']['val'])
+        template = template.replace('__BASE_LCORE__', cli_config['sec_base_lcore']['val'])
+        if cli_config['sec_vhost_cli']['val']:
+            template = template.replace('__VHOST_CLI__', '--vhost-client')
+        else:
+            template = template.replace('__VHOST_CLI__', '')
 
         if tokens[0].endswith(';'):
 
@@ -195,8 +199,8 @@ class SppPrimary(object):
                     elif ptype == 'pcap':  # at least two cores
                         rest_core = '{}-{}'.format(int(sid), int(sid)+1)
 
-                    candidates = [mytemplate.format(
-                        base_core, rest_core, opt_sid, sid, server_addr)]
+                    candidates = [template.format(
+                        rest_core, opt_sid, sid, server_addr)]
 
         if not text:
             completions = candidates
diff --git a/src/controller/shell.py b/src/controller/shell.py
index e68ac63..8cf10e6 100644
--- a/src/controller/shell.py
+++ b/src/controller/shell.py
@@ -23,17 +23,43 @@ import subprocess
 class Shell(cmd.Cmd, object):
     """SPP command prompt."""
 
-    recorded_file = None
+    # Default config, but changed via `config` command
+    cli_config = {
+            'prompt': {
+                'val': 'spp > ', 'desc': 'Command prompt'},
+            'topo_size': {
+                'val': '60%', 'desc': 'Percentage or ratio of topo'},
+            'sec_mem': {
+                'val':'-m 512', 'desc': 'Mem size'},
+            'sec_base_lcore': {
+                'val': '1', 'desc': 'Shared lcore among secondaryes'},
+            'sec_vf_nof_lcores': {
+                'val': '3', 'desc': 'Number of lcores for vf workers'},
+            'sec_vhost_cli': {
+                'val': '', 'desc': 'Vhost client mode'},
+            }
+
+    # Setup template of `pri; launch`
+    template = "-l __BASE_LCORE__,{} "
+    template = template + "__MEM__ "
+    template = template + "-- "
+    template = template + "{} {} "  # '-n 1' or '--client-id 1'
+    template = template + "-s {} "  # '-s 192.168.1.100:6666'
+    template = template + "__VHOST_CLI__"
+
     hist_file = os.path.expanduser('~/.spp_history')
+    PLUGIN_DIR = 'plugins'
 
     # Commands not included in history
     HIST_EXCEPT = ['bye', 'exit', 'history', 'redo']
 
+    # Shell settings which are reserved vars of Cmd class.
+    # `intro` is to be shown as a welcome message.
     intro = 'Welcome to the SPP CLI. Type `help` or `?` to list commands.\n'
-    prompt = 'spp > '
+    prompt = cli_config['prompt']['val']  # command prompt
 
-    PLUGIN_DIR = 'plugins'
-    topo_size = '60%'
+    # Recipe file to be recorded with `record` command
+    recorded_file = None
 
     # setup history file
     if os.path.exists(hist_file):
@@ -47,7 +73,8 @@ class Shell(cmd.Cmd, object):
         self.spp_ctl_cli = spp_cli_objs[0]
         self.use_cache = use_cache
         self.init_spp_procs()
-        self.spp_topo = topo.SppTopo(self.spp_ctl_cli, {}, self.topo_size)
+        self.spp_topo = topo.SppTopo(
+                self.spp_ctl_cli, {}, self.cli_config['topo_size']['val'])
 
         common.set_current_server_addr(
                 self.spp_ctl_cli.ip_addr, self.spp_ctl_cli.port)
@@ -249,7 +276,7 @@ class Shell(cmd.Cmd, object):
         """Close record file"""
 
         if self.recorded_file:
-            print("closing file")
+            print("Closing file")
             self.recorded_file.close()
             self.recorded_file = None
 
@@ -331,7 +358,8 @@ class Shell(cmd.Cmd, object):
         """Completion for primary process commands."""
 
         line = re.sub(r'\s+', " ", line)
-        return self.primary.complete(text, line, begidx, endidx)
+        return self.primary.complete(text, line, begidx, endidx,
+                self.cli_config, self.template)
 
     def do_nfv(self, cmd):
         """Send a command to spp_nfv specified with ID.
@@ -618,6 +646,67 @@ class Shell(cmd.Cmd, object):
     def complete_playback(self, text, line, begidx, endidx):
         return common.compl_common(text, line)
 
+    def do_config(self, args):
+        """Show or update config.
+
+        # show list of config
+        spp > config
+
+        # set prompt to "$ spp "
+        spp > config prompt "$ spp "
+        """
+
+        tokens = args.strip().split(' ')
+        if len(tokens) == 1:
+            key = tokens[0]
+            if key == '':
+                for k,v in self.cli_config.items():
+                    print('- {}: "{}"\t# {}'.format(k, v['val'], v['desc']))
+            elif key in self.cli_config.keys():
+                print('- {}: "{}"\t# {}'.format(
+                    key, self.cli_config[key]['val'],
+                    self.cli_config[key]['desc']))
+            else:
+                res = {}
+                for k, v in self.cli_config.items():
+                    if k.startswith(key):
+                        res[k] = {'val': v['val'], 'desc': v['desc']}
+                for k, v in res.items():
+                    print('- {}: "{}"\t# {}'.format(k, v['val'], v['desc']))
+
+        elif len(tokens) > 1:
+            key = tokens[0]
+            if key in self.cli_config.keys():
+                for s in ['"', "'"]:
+                    args = args.replace(s, '')
+
+                # TODO(yasufum) add validation for given value
+                self.cli_config[key]['val'] = args[(len(key) + 1):]
+                print('Set {}: "{}"'.format(key, self.cli_config[key]['val']))
+
+                # Command prompt should be updated immediately
+                if key == 'prompt':
+                    self.prompt = self.cli_config['prompt']['val']
+
+    def complete_config(self, text, line, begidx, endidx):
+        candidates = []
+        tokens = line.strip().split(' ')
+
+        if len(tokens) == 1:
+            candidates = self.cli_config.keys()
+        elif len(tokens) == 2:
+            if text:
+                candidates = self.cli_config.keys()
+
+        if not text:
+            completions = candidates
+        else:
+            logger.debug(candidates)
+            completions = [p for p in candidates
+                           if p.startswith(text)
+                           ]
+        return completions
+
     def do_pwd(self, args):
         """Show corrent directory.
 
-- 
2.7.4

  reply	other threads:[~2019-02-04  3:14 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-02-04  3:11 [spp] [PATCH 0/5] Add " ogawa.yasufumi
2019-02-04  3:11 ` ogawa.yasufumi [this message]
2019-02-04  3:11 ` [spp] [PATCH 2/5] controller: refactor pri launch command ogawa.yasufumi
2019-02-04  3:11 ` [spp] [PATCH 3/5] controller: remove nouse check_sec_cmds ogawa.yasufumi
2019-02-04  3:12 ` [spp] [PATCH 4/5] controller: add max_secondary to config ogawa.yasufumi
2019-02-04  3:12 ` [spp] [PATCH 5/5] controller: change nof worker lcores configurable ogawa.yasufumi

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=1549249921-31638-2-git-send-email-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).