From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail.valinux.co.jp (mail.valinux.co.jp [210.128.90.3]) by dpdk.org (Postfix) with ESMTP id 0439F255 for ; Sun, 23 Sep 2018 04:39:33 +0200 (CEST) Received: from localhost (localhost [127.0.0.1]) by mail.valinux.co.jp (Postfix) with ESMTP id 2DAE5B3C73 for ; Sun, 23 Sep 2018 11:39:32 +0900 (JST) X-Virus-Scanned: Debian amavisd-new at valinux.co.jp Received: from mail.valinux.co.jp ([127.0.0.1]) by localhost (mail.valinux.co.jp [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id HLWNt0FsmVHj for ; Sun, 23 Sep 2018 11:39:32 +0900 (JST) Received: from [127.0.0.1] (vagw.valinux.co.jp [210.128.90.14]) (using TLSv1 with cipher ECDHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by mail.valinux.co.jp (Postfix) with ESMTPS id 167B4B3AB6 for ; Sun, 23 Sep 2018 11:39:32 +0900 (JST) Date: Sun, 23 Sep 2018 11:39:32 +0900 From: Itsuro ODA To: spp@dpdk.org In-Reply-To: <20180923112233.2D71.277DD91C@valinux.co.jp> References: <20180923112233.2D71.277DD91C@valinux.co.jp> Message-Id: <20180923113931.2D98.277DD91C@valinux.co.jp> MIME-Version: 1.0 Content-Type: text/plain; charset="US-ASCII" Content-Transfer-Encoding: 7bit X-Mailer: Becky! ver. 2.71.01 [ja] Subject: [spp] [PATCH v2 9/9] spp-ctl: spp command interface 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: Sun, 23 Sep 2018 02:39:33 -0000 From: Itsuro Oda Signed-off-by: Itsuro Oda --- src/spp-ctl/spp_proc.py | 184 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 184 insertions(+) create mode 100644 src/spp-ctl/spp_proc.py diff --git a/src/spp-ctl/spp_proc.py b/src/spp-ctl/spp_proc.py new file mode 100644 index 0000000..929942a --- /dev/null +++ b/src/spp-ctl/spp_proc.py @@ -0,0 +1,184 @@ +# SPDX-License-Identifier: BSD-3-Clause +# Copyright(c) 2018 Nippon Telegraph and Telephone Corporation + +import bottle +import eventlet +import json +import logging + +import spp_ctl + + +LOG = logging.getLogger(__name__) + +ID_PRIMARY = 0 +TYPE_PRIMARY = "primary" +TYPE_VF = "vf" +TYPE_NFV = "nfv" + + +def exec_command(func): + """Define the common function of sending command & receiving reply + as a decorator. + each method for executing command has only to return command string. + ex. + @exec_command + def some_command(self, ...): + return "command string of some_command" + """ + def wrapper(self, *args, **kwargs): + with self.sem: + command = func(self, *args, **kwargs) + LOG.info("%s(%d) command executed: %s", self.type, self.id, + command) + data = spp_ctl.Controller._send_command(self.conn, command) + if data is None: + raise RuntimeError("%s(%d): %s: no-data returned" % + (self.type, self.id, command)) + LOG.debug("reply: %s", data) + return self._decode_reply(data) + return wrapper + + +class SppProc(object): + def __init__(self, proc_type, id, conn): + self.id = id + self.type = proc_type + # NOTE: executing command is serialized by using a semaphore + # for each process. + self.sem = eventlet.semaphore.Semaphore(value=1) + self.conn = conn + + +class VfProc(SppProc): + + def __init__(self, id, conn): + super(VfProc, self).__init__(TYPE_VF, id, conn) + + @staticmethod + def _decode_reply(data): + data = json.loads(data) + result = data["results"][0] + if result["result"] == "error": + msg = result["error_details"]["message"] + raise bottle.HTTPError(400, "command error: %s" % msg) + return data + + @staticmethod + def _decode_client_id(data): + try: + data = VfProc._decode_reply(data) + return data["client_id"] + except: + return None + + @exec_command + def get_status(self): + return "status" + + @exec_command + def start_component(self, comp_name, core_id, comp_type): + return ("component start {comp_name} {core_id} {comp_type}" + .format(**locals())) + + @exec_command + def stop_component(self, comp_name): + return "component stop {comp_name}".format(**locals()) + + @exec_command + def port_add(self, port, direction, comp_name, op, vlan_id, pcp): + command = "port add {port} {direction} {comp_name}".format(**locals()) + if op != "none": + command += " %s" % op + if op == "add_vlantag": + command += " %d %d" % (vlan_id, pcp) + return command + + @exec_command + def port_del(self, port, direction, comp_name): + return "port del {port} {direction} {comp_name}".format(**locals()) + + @exec_command + def set_classifier_table(self, mac_address, port): + return ("classifier_table add mac {mac_address} {port}" + .format(**locals())) + + @exec_command + def clear_classifier_table(self, mac_address, port): + return ("classifier_table del mac {mac_address} {port}" + .format(**locals())) + + @exec_command + def set_classifier_table_with_vlan(self, mac_address, port, + vlan_id): + return ("classifier_table add vlan {vlan_id} {mac_address} {port}" + .format(**locals())) + + @exec_command + def clear_classifier_table_with_vlan(self, mac_address, port, + vlan_id): + return ("classifier_table del vlan {vlan_id} {mac_address} {port}" + .format(**locals())) + + +class NfvProc(SppProc): + + def __init__(self, id, conn): + super(NfvProc, self).__init__(TYPE_NFV, id, conn) + + @staticmethod + def _decode_reply(data): + return data.strip('\0') + + @staticmethod + def _decode_client_id(data): + try: + return int(NfvProc._decode_reply(data)) + except: + return None + + @exec_command + def get_status(self): + return "status" + + @exec_command + def port_add(self, if_type, if_num): + return "add {if_type} {if_num}".format(**locals()) + + @exec_command + def port_del(self, if_type, if_num): + return "del {if_type} {if_num}".format(**locals()) + + @exec_command + def patch_add(self, src_port, dst_port): + return "patch {src_port} {dst_port}".format(**locals()) + + @exec_command + def patch_reset(self): + return "patch reset" + + @exec_command + def forward(self): + return "forward" + + @exec_command + def stop(self): + return "stop" + + +class PrimaryProc(SppProc): + + def __init__(self, conn): + super(PrimaryProc, self).__init__(TYPE_PRIMARY, ID_PRIMARY, conn) + + @staticmethod + def _decode_reply(data): + return data.strip('\0') + + @exec_command + def status(self): + return "status" + + @exec_command + def clear(self): + return "clear" -- 2.17.0 -- Itsuro ODA