From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from dpdk.org (dpdk.org [92.243.14.124]) by inbox.dpdk.org (Postfix) with ESMTP id 4AD17A317C for ; Thu, 17 Oct 2019 14:57:55 +0200 (CEST) Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id 34E981E976; Thu, 17 Oct 2019 14:57:55 +0200 (CEST) Received: from mail-pf1-f193.google.com (mail-pf1-f193.google.com [209.85.210.193]) by dpdk.org (Postfix) with ESMTP id 8F5761E976 for ; Thu, 17 Oct 2019 14:57:54 +0200 (CEST) Received: by mail-pf1-f193.google.com with SMTP id a2so1610313pfo.10 for ; Thu, 17 Oct 2019 05:57:54 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:subject:date:message-id; bh=8YIjQf+loWdSNVLWlrGzZ63AFpLtPGr1A5bgqhCTKj8=; b=oaMbj1v6XFPd00igd7y39pZYAR2fGFxF/c0Zy1hfSBQM1JkSyyY7A4Ud6S05Qol0JE Io3DS4y8v0powKkbLH8l6GlBT7SF60WF/AvyHcvp2MVW3ewIvFi51Bj1iEWVDWIQcZMY 2gh+V5Orw5hXEZxtz9ob1fCAWxkxs5+WX03n9Dbw6cpGFoBVYG5lAdjPM4jMX47FF5tO NAvkSCOOPcTcKag9utk90rUzUmf2JgAKfsUZr4VwEj+SvFA6a+6IDS1Z55O9OghDpo+D glOKnaZGJRvLdtChV59QqUiO89iBcr8SDgtmCsdYdb9c4Zrw/5CFNfoTY8fY4669ZgzR 9M3Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:subject:date:message-id; bh=8YIjQf+loWdSNVLWlrGzZ63AFpLtPGr1A5bgqhCTKj8=; b=C9IK3tQMXfUH+BFX6o8Rl4Uh22JFLy2A19JJk4mJWzgEqsR+z7UArYKkWpOVtP9rAX R5tlBt0anH9uRD50Sh1aIsgMd04+GAqFXwQoT6iPYtTlOckaEeCpf8jbVjMz6ndY0+u9 AtoAhSPHsRcCZLPSRCYx9YlxMUE78luu+NnN3bCOtBtXwTEK7i+ldmRCXbeNc6mO69rq QpoiVFhkOKfBUNnoVXWJNrCha8ZH3+vgeJAWUo01rSeFRVr51KrV5Rxzclb/yK2FC9ey b1lBSSPpNz3SWBc7iqrX+IzhYS5VUdI08hXnPXMUmZ6v6JSifGMs0+VeOyrohT8iA4nI AwqA== X-Gm-Message-State: APjAAAUmfU3MUufwNQKQCH4R6CBGd7bCelZYVNWWzNk2Xo2kh/ZG/gTq mxCX76/rOF8DfjvAVW7f4ZEZTgEV8b8= X-Google-Smtp-Source: APXvYqypdJXx11HlUm5LyyqebSHTTcfeRRAjJKDoY6RgDuugPiBfHcb8xU/F9EzcY7hNIt86N1biUA== X-Received: by 2002:a63:1209:: with SMTP id h9mr3893196pgl.394.1571317073400; Thu, 17 Oct 2019 05:57:53 -0700 (PDT) Received: from localhost.localdomain ([192.47.164.146]) by smtp.gmail.com with ESMTPSA id x12sm2386200pfm.130.2019.10.17.05.57.52 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 17 Oct 2019 05:57:53 -0700 (PDT) From: yasufum.o@gmail.com To: spp@dpdk.org, ferruh.yigit@intel.com, yasufum.o@gmail.com Date: Thu, 17 Oct 2019 21:57:49 +0900 Message-Id: <20191017125749.29141-1-yasufum.o@gmail.com> X-Mailer: git-send-email 2.17.1 Subject: [spp] [PATCH] cli: add methods to manage ports for primary 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: , Errors-To: spp-bounces@dpdk.org Sender: "spp" From: Yasufumi Ogawa * Add methods for running commands, add, del and patch, for spp_primary. * Add methods for running forward and del commmad for spp_primary. * Add several TODO comments for refactoring. Signed-off-by: Yasufumi Ogawa --- src/cli/commands/nfv.py | 4 + src/cli/commands/pri.py | 192 +++++++++++++++++++++++++++++++++++++++- 2 files changed, 195 insertions(+), 1 deletion(-) diff --git a/src/cli/commands/nfv.py b/src/cli/commands/nfv.py index 0989eba..1144eca 100644 --- a/src/cli/commands/nfv.py +++ b/src/cli/commands/nfv.py @@ -95,6 +95,7 @@ class SppNfv(object): else: print(' - {} -> {}'.format(port, dst)) + # TODO(yasufum) change name starts with '_' as private def get_ports(self): """Get all of ports as a list.""" @@ -108,6 +109,7 @@ class SppNfv(object): else: print('Error: unknown response.') + # TODO(yasufum) change name starts with '_' as private def get_patches(self): """Get all of patched ports as a list of dicts. @@ -126,6 +128,7 @@ class SppNfv(object): else: print('Error: unknown response.') + # TODO(yasufum) change name starts with '_' as private def get_ports_and_patches(self): """Get all of ports and patchs at once. @@ -147,6 +150,7 @@ class SppNfv(object): else: print('Error: unknown response.') + # TODO(yasufum) change name starts with '_' as private def get_patched_ports(self): """Get all of patched ports as a list. diff --git a/src/cli/commands/pri.py b/src/cli/commands/pri.py index da5eca6..c711c72 100644 --- a/src/cli/commands/pri.py +++ b/src/cli/commands/pri.py @@ -18,11 +18,15 @@ class SppPrimary(object): """ # All of primary commands used for validation and completion. - PRI_CMDS = ['status', 'launch', 'clear'] + PRI_CMDS = ['status', 'add', 'del', 'forward', 'stop', 'patch', + 'launch', 'clear'] def __init__(self, spp_ctl_cli): self.spp_ctl_cli = spp_ctl_cli + self.ports = [] # registered ports + self.patchs = [] + # Default args for `pri; launch`, used if given cli_config is invalid # Setup template of args for `pri; launch` @@ -59,6 +63,18 @@ class SppPrimary(object): else: print('Error: unknown response.') + elif subcmd == 'add': + self._run_add(params) + + elif subcmd == 'del': + self._run_del(params) + + elif subcmd == 'forward' or cmd == 'stop': + self._run_forward_or_stop(cmd) + + elif subcmd == 'patch': + self._run_patch(params) + elif subcmd == 'launch': wait_time = float(cli_config['sec_wait_launch']['val']) self._run_launch(params, wait_time) @@ -154,6 +170,75 @@ class SppPrimary(object): rid=rports['id'], rx=rports['rx'], tx=rports['tx'], rx_drop=rports['rx_drop'], tx_drop=rports['tx_drop'])) + # TODO(yasufum) make methods start with '_get' to be shared + # because it is similar to nfv. _get_ports(self) is changed as + # _get_ports(self, proc_type). + def _get_ports(self): + """Get all of ports as a list.""" + + res = self.spp_ctl_cli.get('primary') + if res is not None: + error_codes = self.spp_ctl_cli.rest_common_error_codes + if res.status_code == 200: + return res.json()['ports'] + elif res.status_code in error_codes: + pass + else: + print('Error: unknown response.') + + def _get_patches(self): + """Get all of patched ports as a list of dicts. + + Returned value is like as + [{'src': 'phy:0', 'dst': 'ring:0'}, + {'src': 'ring:1', 'dst':'vhost:1'}, ...] + """ + + res = self.spp_ctl_cli.get('primary') + if res is not None: + error_codes = self.spp_ctl_cli.rest_common_error_codes + if res.status_code == 200: + return res.json()['patches'] + elif res.status_code in error_codes: + pass + else: + print('Error: unknown response.') + + def _get_ports_and_patches(self): + """Get all of ports and patchs at once. + + This method is to execute `_get_ports()` and `_get_patches()` at + once to reduce request to spp-ctl. Returned value is a set of + lists. You use this method as following. + ports, patches = _get_ports_and_patches() + """ + + res = self.spp_ctl_cli.get('primary') + if res is not None: + error_codes = self.spp_ctl_cli.rest_common_error_codes + if res.status_code == 200: + ports = res.json()['ports'] + patches = res.json()['patches'] + return ports, patches + elif res.status_code in error_codes: + pass + else: + print('Error: unknown response.') + + def _get_patched_ports(self): + """Get all of patched ports as a list. + + This method is to get a list of patched ports instead of a dict. + You use this method if you simply get patches without `src` and + `dst`. + """ + + patched_ports = [] + for pport in self.patches: + patched_ports.append(pport['src']) + patched_ports.append(pport['dst']) + return list(set(patched_ports)) + def _get_empty_lcores(self): """Get lcore usage from spp-ctl for making launch options. @@ -442,6 +527,111 @@ class SppPrimary(object): prekey = None return opts_dict + def _run_add(self, params): + """Run `add` command.""" + + if len(params) == 0: + print('Port is required!') + elif params[0] in self.ports: + print("'%s' is already added." % params[0]) + else: + self.ports = self._get_ports() + + req_params = {'action': 'add', 'port': params[0]} + + res = self.spp_ctl_cli.put('primary/ports', req_params) + if res is not None: + error_codes = self.spp_ctl_cli.rest_common_error_codes + if res.status_code == 204: + print('Add %s.' % params[0]) + elif res.status_code in error_codes: + pass + else: + print('Error: unknown response.') + + def _run_del(self, params): + """Run `del` command.""" + + if len(params) == 0: + print('Port is required!') + elif 'phy:' in params[0]: + print("Cannot delete phy port '%s'." % params[0]) + else: + self.patches = self._get_patches() + + # Patched ports should not be deleted. + patched_ports = self._get_patched_ports() + + if params[0] in patched_ports: + print("Cannot delete patched port '%s'." % params[0]) + else: + req_params = {'action': 'del', 'port': params[0]} + res = self.spp_ctl_cli.put('primary/ports', req_params) + if res is not None: + error_codes = self.spp_ctl_cli.rest_common_error_codes + if res.status_code == 204: + print('Delete %s.' % params[0]) + elif res.status_code in error_codes: + pass + else: + print('Error: unknown response.') + + def _run_forward_or_stop(self, cmd): + """Run `forward` or `stop` command.""" + + if cmd == 'forward': + req_params = {'action': 'start'} + elif cmd == 'stop': + req_params = {'action': 'stop'} + else: + print('Unknown command. "forward" or "stop"?') + + res = self.spp_ctl_cli.put('primary/forward', req_params) + + if res is not None: + error_codes = self.spp_ctl_cli.rest_common_error_codes + if res.status_code == 204: + if cmd == 'forward': + print('Start forwarding.') + else: + print('Stop forwarding.') + elif res.status_code in error_codes: + pass + else: + print('Error: unknown response.') + + def _run_patch(self, params): + """Run `patch` command.""" + + if len(params) == 0: + print('Params are required!') + elif params[0] == 'reset': + res = self.spp_ctl_cli.delete('primary/patches') + if res is not None: + error_codes = self.spp_ctl_cli.rest_common_error_codes + if res.status_code == 204: + print('Clear all of patches.') + elif res.status_code in error_codes: + pass + else: + print('Error: unknown response.') + else: + if len(params) < 2: + print('Dst port is required!') + else: + req_params = {'src': params[0], 'dst': params[1]} + res = self.spp_ctl_cli.put('primary/patches', + req_params) + if res is not None: + error_codes = self.spp_ctl_cli.rest_common_error_codes + if res.status_code == 204: + print('Patch ports (%s -> %s).' % ( + params[0], params[1])) + elif res.status_code in error_codes: + pass + else: + print('Error: unknown response.') + def _run_launch(self, params, wait_time): """Launch secondary process. -- 2.17.1