Soft Patch Panel
 help / color / mirror / Atom feed
From: x-fn-spp@sl.ntt-tx.co.jp
To: ferruh.yigit@intel.com, ogawa.yasufumi@lab.ntt.co.jp
Cc: spp@dpdk.org
Subject: [spp] [PATCH v2 6/7] controller: add SppPcap class
Date: Fri,  8 Feb 2019 17:44:37 +0900	[thread overview]
Message-ID: <201902080844.x188icKv030833@imss04.silk.ntt-tx.co.jp> (raw)
In-Reply-To: <20190208084438.7952-1-x-fn-spp@sl.ntt-tx.co.jp>

From: Hideyuki Yamashita <yamashita.hideyuki@po.ntt-tx.co.jp>

This update is to add SppPcap class behaviour as a client for spp-ctl.
An instance of the class is intended to be used from do_pcap() and
complete_pcap() methods of Shell class in 'spp.py'.

Signed-off-by: Hideyuki Yamashita <yamashita.hideyuki@po.ntt-tx.co.jp>
Signed-off-by: Naoki Takada <takada.naoki@lab.ntt.co.jp>
---
 src/controller/commands/pcap.py | 230 ++++++++++++++++++++++++++++++++
 1 file changed, 230 insertions(+)
 create mode 100644 src/controller/commands/pcap.py

diff --git a/src/controller/commands/pcap.py b/src/controller/commands/pcap.py
new file mode 100644
index 0000000..89a1a5f
--- /dev/null
+++ b/src/controller/commands/pcap.py
@@ -0,0 +1,230 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2019 Nippon Telegraph and Telephone Corporation
+
+
+class SppPcap(object):
+    """Exec spp_pcap command.
+
+    SppPcap class is intended to be used in Shell class as a delegator
+    for running 'pcap' command.
+
+    'self.command()' is called from do_pcap() and 'self.complete()' is called
+    from complete_() of both of which is defined in Shell.
+    """
+
+    # All of commands and sub-commands used for validation and completion.
+    PCAP_CMDS = {
+            'status': None,
+            'start': None,
+            'stop': None,
+            'exit': None}
+
+    WORKER_TYPES = ['receive', 'write']
+
+    def __init__(self, spp_ctl_cli, sec_id, use_cache=False):
+        self.spp_ctl_cli = spp_ctl_cli
+        self.sec_id = sec_id
+
+        # Update 'self.worker_names' and 'self.unused_core_ids' each time
+        # 'self.run()' is called if it is 'False'.
+        # True to 'True' if you do not wait for spp_pcap's response.
+        self.use_cache = use_cache
+
+        # Names and core IDs of worker threads
+        pcap_status = self._get_status(self.sec_id)
+
+        core_ids = pcap_status['core_ids']
+        for wk in pcap_status['workers']:
+            if wk['core_id'] in core_ids:
+                core_ids.remove(wk['core_id'])
+        self.unused_core_ids = core_ids  # used while completion to exclude
+
+        self.workers = pcap_status['workers']
+        self.worker_names = [attr['role'] for attr in pcap_status['workers']]
+
+    def run(self, cmdline):
+        """Called from do_sec() to Send command to secondary process."""
+
+        # update status each time if configured not to use cache
+        if self.use_cache is False:
+            pcap_status = self._get_status(self.sec_id)
+
+            core_ids = pcap_status['core_ids']
+            for wk in pcap_status['workers']:
+                if wk['core_id'] in core_ids:
+                    core_ids.remove(wk['core_id'])
+            self.unused_core_ids = core_ids  # used while completion to exclude
+
+            self.workers = pcap_status['workers']
+            self.worker_names = [attr['role']
+                                 for attr in pcap_status['workers']]
+
+        cmd = cmdline.split(' ')[0]
+        params = cmdline.split(' ')[1:]
+
+        if cmd == 'status':
+            res = self.spp_ctl_cli.get('pcaps/%d' % self.sec_id)
+            if res is not None:
+                error_codes = self.spp_ctl_cli.rest_common_error_codes
+                if res.status_code == 200:
+                    self.print_status(res.json())
+                elif res.status_code in error_codes:
+                    pass
+                else:
+                    print('Error: unknown response.')
+
+        elif cmd == 'start':
+            req_params = {'action': 'start'}
+            res = self.spp_ctl_cli.put('pcaps/%d/capture'
+                                       % (self.sec_id), req_params)
+            if res is not None:
+                error_codes = self.spp_ctl_cli.rest_common_error_codes
+                if res.status_code == 204:
+                    print("Start packet capture.")
+                elif res.status_code in error_codes:
+                    pass
+                else:
+                    print('Error: unknown response.')
+
+        elif cmd == 'stop':
+            req_params = {'action': 'stop'}
+            res = self.spp_ctl_cli.put('pcaps/%d/capture'
+                                       % (self.sec_id), req_params)
+            if res is not None:
+                error_codes = self.spp_ctl_cli.rest_common_error_codes
+                if res.status_code == 204:
+                    print("Stop packet capture.")
+                elif res.status_code in error_codes:
+                    pass
+                else:
+                    print('Error: unknown response.')
+
+        elif cmd == 'exit':
+            res = self.spp_ctl_cli.delete('pcaps/%d' % (self.sec_id))
+            if res is not None:
+                error_codes = self.spp_ctl_cli.rest_common_error_codes
+                if res.status_code == 204:
+                    print("Exit pcap %d." % (self.sec_id))
+                elif res.status_code in error_codes:
+                    pass
+                else:
+                    print('Error: unknown response.')
+
+        else:
+            print('Invalid command "%s".' % cmd)
+
+    def print_status(self, json_obj):
+        """Parse and print message from SPP PCAP.
+
+        Print status received from spp_pcap.
+
+          spp > pcap 1; status
+            - client-id: 3
+            - satus: running
+            - core:2, receive
+              - rx: phy:0
+            - core:3, write
+              - file: /tmp/spp_pcap.20181108110600.phy0.1.1.pcap
+            - core:4, write
+              - file: /tmp/spp_pcap.20181108110600.phy0.2.1.pcap
+            - core:5, write
+              - file: /tmp/spp_pcap.20181108110600.phy0.3.1.pcap
+            ...
+
+        """
+
+        # client id and status
+        print('  - client-id: %d' % json_obj['client-id'])
+        print('  - status: %s' % json_obj['status'])
+
+        # Core
+        for worker in json_obj['core']:
+            if 'role' in worker.keys():
+                print("  - core:%d %s" % (
+                        worker['core'], worker['role']))
+
+                if worker['role'] == 'receive':
+                    pt = worker['rx_port'][0]['port']
+                    msg = '    - %s:%s'
+                    print(msg % ('rx', pt))
+                else:
+                    print('    - filename: %s' % worker['filename'])
+
+    def complete(self, sec_ids, text, line, begidx, endidx):
+        """Completion for spp_pcap commands.
+
+        Called from complete_pcap() to complete.
+        """
+
+        try:
+            completions = []
+            tokens = line.split(';')
+
+            if len(tokens) == 2:
+                sub_tokens = tokens[1].split(' ')
+
+                if len(sub_tokens) == 1:
+                    if not (sub_tokens[0] in self.PCAP_CMDS.keys()):
+                        completions = self._compl_first_tokens(sub_tokens[0])
+                else:
+                    if sub_tokens[0] == 'status':
+                        if len(sub_tokens) < 2:
+                            if 'status'.startswith(sub_tokens[1]):
+                                completions = ['status']
+
+                    elif sub_tokens[0] == 'start':
+                        if len(sub_tokens) < 2:
+                            if 'start'.startswith(sub_tokens[1]):
+                                completions = ['start']
+
+                    elif sub_tokens[0] == 'stop':
+                        if len(sub_tokens) < 2:
+                            if 'stop'.startswith(sub_tokens[1]):
+                                completions = ['stop']
+            return completions
+        except Exception as e:
+            print(e)
+
+    def _compl_first_tokens(self, token):
+        res = []
+        for kw in self.PCAP_CMDS.keys():
+            if kw.startswith(token):
+                res.append(kw)
+        return res
+
+    def _get_status(self, sec_id):
+        """Get status of spp_pcap.
+
+        To update status of the instance of SppPcap, get the status from
+        spp-ctl. This method returns the result as a dict. For considering
+        behaviour of spp_pcap, it is enough to return worker's name and core
+        IDs as the status, but might need to be update for future updates.
+
+        # return worker's role and used core IDs, and all of core IDs.
+        {
+          'workers': [
+            {'role': 'receive', 'core_id': 5},
+            {'role': 'write', 'core_id': 6},
+            ...
+          ],
+          'core_ids': [5, 6, 7, ...]
+        }
+
+        """
+
+        status = {'workers': [], 'core_ids': []}
+        res = self.spp_ctl_cli.get('pcaps/%d' % self.sec_id)
+        if res is not None:
+            if res.status_code == 200:
+                json_obj = res.json()
+
+                if 'core' in json_obj.keys():
+                    for wk in json_obj['core']:
+                        if 'core' in wk.keys():
+                            if 'role' in wk.keys():
+                                status['workers'].append(
+                                        {'role': wk['role'],
+                                         'core_id': wk['core']})
+                            status['core_ids'].append(wk['core'])
+
+        return status
-- 
2.17.1

  parent reply	other threads:[~2019-02-08  8:46 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <20190208084438.7952-1-x-fn-spp@sl.ntt-tx.co.jp>
2019-02-08  8:44 ` [spp] [PATCH v2 1/7] spp_pcap: add command main x-fn-spp
2019-02-08  8:44 ` [spp] [PATCH v2 2/7] spp_pcap: add command decode x-fn-spp
2019-02-08  8:44 ` [spp] [PATCH v2 3/7] spp_pcap: add management function x-fn-spp
2019-02-08  8:44 ` [spp] [PATCH v2 4/7] spp_pcap: add spp_pcap main function x-fn-spp
2019-02-08  8:44 ` [spp] [PATCH v2 5/7] spp_pcap: add Makefile for spp_pcap x-fn-spp
2019-02-08  8:44 ` x-fn-spp [this message]
2019-02-08  8:44 ` [spp] [PATCH v2 7/7] controller: add pcap command to SPP controller x-fn-spp

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=201902080844.x188icKv030833@imss04.silk.ntt-tx.co.jp \
    --to=x-fn-spp@sl.ntt-tx.co.jp \
    --cc=ferruh.yigit@intel.com \
    --cc=ogawa.yasufumi@lab.ntt.co.jp \
    --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).