Soft Patch Panel
 help / color / mirror / Atom feed
* [spp] [PATCH 0/2] spp_mirror API support
@ 2018-11-29  0:55 oda
  2018-11-29  0:55 ` [spp] [PATCH 1/2] " oda
                   ` (3 more replies)
  0 siblings, 4 replies; 8+ messages in thread
From: oda @ 2018-11-29  0:55 UTC (permalink / raw)
  To: spp, ferruh.yigit, ogawa.yasufumi

From: Itsuro Oda <oda@valinux.co.jp>

As new process spp_mirror is introduced, spp-ctl supports
its API.

Itsuro Oda (2):
  spp_mirror API support
  spp_mirror API api-reference

 docs/guides/spp-ctl/api-reference.rst | 316 ++++++++++++++++++++++++++
 src/spp-ctl/spp_ctl.py                |   2 +-
 src/spp-ctl/spp_proc.py               |  57 +++--
 src/spp-ctl/spp_webapi.py             | 120 +++++++---
 4 files changed, 443 insertions(+), 52 deletions(-)

-- 
2.17.1

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [spp] [PATCH 1/2] spp_mirror API support
  2018-11-29  0:55 [spp] [PATCH 0/2] spp_mirror API support oda
@ 2018-11-29  0:55 ` oda
  2018-11-29  0:55 ` [spp] [PATCH 2/2] spp_mirror API api-reference oda
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 8+ messages in thread
From: oda @ 2018-11-29  0:55 UTC (permalink / raw)
  To: spp, ferruh.yigit, ogawa.yasufumi

From: Itsuro Oda <oda@valinux.co.jp>

This patch adds spp_mirror APIs to spp-ctl.

Signed-off-by: Itsuro Oda <oda@valinux.co.jp>
---
 src/spp-ctl/spp_ctl.py    |   2 +-
 src/spp-ctl/spp_proc.py   |  57 +++++++++++++-----
 src/spp-ctl/spp_webapi.py | 120 ++++++++++++++++++++++++++------------
 3 files changed, 127 insertions(+), 52 deletions(-)

diff --git a/src/spp-ctl/spp_ctl.py b/src/spp-ctl/spp_ctl.py
index 0576ae1..279c180 100644
--- a/src/spp-ctl/spp_ctl.py
+++ b/src/spp-ctl/spp_ctl.py
@@ -128,7 +128,7 @@ class Controller(object):
         # it is a bit ad hoc. send "_get_clinet_id" command and try to
         # decode reply for each proc type. if success, that is the type.
         data = self._send_command(conn, "_get_client_id")
-        for proc in [spp_proc.VfProc, spp_proc.NfvProc]:
+        for proc in [spp_proc.VfProc, spp_proc.NfvProc, spp_proc.MirrorProc]:
             sec_id = proc._decode_client_id(data)
             if sec_id is not None:
                 return proc(sec_id, conn)
diff --git a/src/spp-ctl/spp_proc.py b/src/spp-ctl/spp_proc.py
index 83c59ea..648e085 100644
--- a/src/spp-ctl/spp_proc.py
+++ b/src/spp-ctl/spp_proc.py
@@ -15,6 +15,7 @@ ID_PRIMARY = 0
 TYPE_PRIMARY = "primary"
 TYPE_VF = "vf"
 TYPE_NFV = "nfv"
+TYPE_MIRROR = "mirror"
 
 
 def exec_command(func):
@@ -53,10 +54,10 @@ class SppProc(object):
         self.conn = conn
 
 
-class VfProc(SppProc):
+class VfCommon(SppProc):
 
-    def __init__(self, id, conn):
-        super(VfProc, self).__init__(TYPE_VF, id, conn)
+    def __init__(self, proc_type, id, conn):
+        super(VfCommon, self).__init__(proc_type, id, conn)
 
     @staticmethod
     def _decode_reply(data):
@@ -67,14 +68,6 @@ class VfProc(SppProc):
             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"
@@ -88,6 +81,25 @@ class VfProc(SppProc):
     def stop_component(self, comp_name):
         return "component stop {comp_name}".format(**locals())
 
+    @exec_command
+    def port_del(self, port, direction, comp_name):
+        return "port del {port} {direction} {comp_name}".format(**locals())
+
+
+class VfProc(VfCommon):
+
+    def __init__(self, id, conn):
+        super(VfProc, self).__init__(TYPE_VF, id, conn)
+
+    @staticmethod
+    def _decode_client_id(data):
+        try:
+            data = VfCommon._decode_reply(data)
+            if data["process_type"] == TYPE_VF:
+                return data["client_id"]
+        except:
+            return None
+
     @exec_command
     def port_add(self, port, direction, comp_name, op, vlan_id, pcp):
         command = "port add {port} {direction} {comp_name}".format(**locals())
@@ -97,10 +109,6 @@ class VfProc(SppProc):
                 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}"
@@ -124,6 +132,25 @@ class VfProc(SppProc):
                 .format(**locals()))
 
 
+class MirrorProc(VfCommon):
+
+    def __init__(self, id, conn):
+        super(MirrorProc, self).__init__(TYPE_MIRROR, id, conn)
+
+    @staticmethod
+    def _decode_client_id(data):
+        try:
+            data = VfCommon._decode_reply(data)
+            if data["process_type"] == TYPE_MIRROR:
+                return data["client_id"]
+        except:
+            return None
+
+    @exec_command
+    def port_add(self, port, direction, comp_name):
+        return "port add {port} {direction} {comp_name}".format(**locals())
+
+
 class NfvProc(SppProc):
 
     def __init__(self, id, conn):
diff --git a/src/spp-ctl/spp_webapi.py b/src/spp-ctl/spp_webapi.py
index 48cc1c4..7547f0e 100644
--- a/src/spp-ctl/spp_webapi.py
+++ b/src/spp-ctl/spp_webapi.py
@@ -114,6 +114,7 @@ class WebServer(BaseHandler):
     /          WebServer
     /v1          V1Handler
        /vfs        V1VFHandler
+       /mirrors    V1MirrorHandler
        /nfvs       V1NFVHandler
        /primary    V1PrimaryHandler
     """
@@ -141,6 +142,7 @@ class V1Handler(BaseHandler):
         self.set_route()
 
         self.mount("/vfs", V1VFHandler(controller))
+        self.mount("/mirrors", V1MirrorHandler(controller))
         self.mount("/nfvs", V1NFVHandler(controller))
         self.mount("/primary", V1PrimaryHandler(controller))
 
@@ -154,7 +156,46 @@ class V1Handler(BaseHandler):
         return self.ctrl.get_processes()
 
 
-class V1VFHandler(BaseHandler):
+class V1VFCommon(object):
+    """Define common methods for vf and mirror handler."""
+
+    def convert_info(self, data):
+        info = data["info"]
+        vf = {}
+        vf["client-id"] = info["client-id"]
+        vf["ports"] = []
+        for key in ["phy", "vhost", "ring"]:
+            for idx in info[key]:
+                vf["ports"].append(key + ":" + str(idx))
+        vf["components"] = info["core"]
+        if "classifier_table" in info:
+            vf["classifier_table"] = info["classifier_table"]
+
+        return vf
+
+    def validate_comp_start(self, body, types):
+        for key in ['name', 'core', 'type']:
+            if key not in body:
+                raise KeyRequired(key)
+        if not isinstance(body['name'], str):
+            raise KeyInvalid('name', body['name'])
+        if not isinstance(body['core'], int):
+            raise KeyInvalid('core', body['core'])
+        if body['type'] not in types:
+            raise KeyInvalid('type', body['type'])
+
+    def validate_comp_port(self, body):
+        for key in ['action', 'port', 'dir']:
+            if key not in body:
+                raise KeyRequired(key)
+        if body['action'] not in ["attach", "detach"]:
+            raise KeyInvalid('action', body['action'])
+        if body['dir'] not in ["rx", "tx"]:
+            raise KeyInvalid('dir', body['dir'])
+        self._validate_port(body['port'])
+
+
+class V1VFHandler(BaseHandler, V1VFCommon):
 
     def __init__(self, controller):
         super(V1VFHandler, self).__init__(controller)
@@ -177,50 +218,18 @@ class V1VFHandler(BaseHandler):
         self.route('/<sec_id:int>/classifier_table', 'PUT',
                    callback=self.vf_classifier)
 
-    def convert_vf_info(self, data):
-        info = data["info"]
-        vf = {}
-        vf["client-id"] = info["client-id"]
-        vf["ports"] = []
-        for key in ["phy", "vhost", "ring"]:
-            for idx in info[key]:
-                vf["ports"].append(key + ":" + str(idx))
-        vf["components"] = info["core"]
-        vf["classifier_table"] = info["classifier_table"]
-
-        return vf
-
     def vf_get(self, proc):
-        return self.convert_vf_info(proc.get_status())
-
-    def _validate_vf_comp_start(self, body):
-        for key in ['name', 'core', 'type']:
-            if key not in body:
-                raise KeyRequired(key)
-        if not isinstance(body['name'], str):
-            raise KeyInvalid('name', body['name'])
-        if not isinstance(body['core'], int):
-            raise KeyInvalid('core', body['core'])
-        if body['type'] not in ["forward", "merge", "classifier_mac"]:
-            raise KeyInvalid('type', body['type'])
+        return self.convert_info(proc.get_status())
 
     def vf_comp_start(self, proc, body):
-        self._validate_vf_comp_start(body)
+        self.validate_comp_start(body, ["forward", "merge", "classifier_mac"])
         proc.start_component(body['name'], body['core'], body['type'])
 
     def vf_comp_stop(self, proc, name):
         proc.stop_component(name)
 
     def _validate_vf_comp_port(self, body):
-        for key in ['action', 'port', 'dir']:
-            if key not in body:
-                raise KeyRequired(key)
-        if body['action'] not in ["attach", "detach"]:
-            raise KeyInvalid('action', body['action'])
-        if body['dir'] not in ["rx", "tx"]:
-            raise KeyInvalid('dir', body['dir'])
-        self._validate_port(body['port'])
-
+        self.validate_comp_port(body)
         if body['action'] == "attach":
             vlan = body.get('vlan')
             if vlan:
@@ -296,6 +305,45 @@ class V1VFHandler(BaseHandler):
                     mac_address, port, body['vlan'])
 
 
+class V1MirrorHandler(BaseHandler, V1VFCommon):
+
+    def __init__(self, controller):
+        super(V1MirrorHandler, self).__init__(controller)
+        self.type = spp_proc.TYPE_MIRROR
+
+        self.set_route()
+
+        self.install(self.check_sec_id)
+        self.install(self.get_body)
+        self.install(self.make_response)
+
+    def set_route(self):
+        self.route('/<sec_id:int>', 'GET', callback=self.mirror_get)
+        self.route('/<sec_id:int>/components', 'POST',
+                   callback=self.mirror_comp_start)
+        self.route('/<sec_id:int>/components/<name>', 'DELETE',
+                   callback=self.mirror_comp_stop)
+        self.route('/<sec_id:int>/components/<name>/ports', 'PUT',
+                   callback=self.mirror_comp_port)
+
+    def mirror_get(self, proc):
+        return self.convert_info(proc.get_status())
+
+    def mirror_comp_start(self, proc, body):
+        self.validate_comp_start(body, ["mirror"])
+        proc.start_component(body['name'], body['core'], body['type'])
+
+    def mirror_comp_stop(self, proc, name):
+        proc.stop_component(name)
+
+    def mirror_comp_port(self, proc, name, body):
+        self.validate_comp_port(body)
+        if body['action'] == "attach":
+            proc.port_add(body['port'], body['dir'], name)
+        else:
+            proc.port_del(body['port'], body['dir'], name)
+
+
 class V1NFVHandler(BaseHandler):
 
     def __init__(self, controller):
-- 
2.17.1

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [spp] [PATCH 2/2] spp_mirror API api-reference
  2018-11-29  0:55 [spp] [PATCH 0/2] spp_mirror API support oda
  2018-11-29  0:55 ` [spp] [PATCH 1/2] " oda
@ 2018-11-29  0:55 ` oda
  2018-11-29  1:36 ` [spp] [PATCH 0/2] spp_mirror API support Yasufumi Ogawa
  2018-11-29  2:04 ` [spp] [PATCH v2 " oda
  3 siblings, 0 replies; 8+ messages in thread
From: oda @ 2018-11-29  0:55 UTC (permalink / raw)
  To: spp, ferruh.yigit, ogawa.yasufumi

From: Itsuro Oda <oda@valinux.co.jp>

This patch adds spp_mirror API reference for spp-ctl.

Signed-off-by: Itsuro Oda <oda@valinux.co.jp>
---
 docs/guides/spp-ctl/api-reference.rst | 316 ++++++++++++++++++++++++++
 1 file changed, 316 insertions(+)

diff --git a/docs/guides/spp-ctl/api-reference.rst b/docs/guides/spp-ctl/api-reference.rst
index 70eddd6..b0d367b 100644
--- a/docs/guides/spp-ctl/api-reference.rst
+++ b/docs/guides/spp-ctl/api-reference.rst
@@ -1168,3 +1168,319 @@ type is ``vlan``
 .. code-block:: none
 
     classifier_table {action} vlan {vlan} {mac_address} {port}
+
+
+API for spp_mirror
+------------------
+
+GET /v1/mirrors/{client_id}
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Get the information of the ``spp_mirror`` process.
+
+* Normal response codes: 200
+* Error response codes: 400, 404
+
+Request(path)
+^^^^^^^^^^^^^
+
+.. _table_spp_ctl_mirrors_get:
+
+.. table:: Request parameter for getting spp_mirror.
+
+    +-----------+---------+--------------------------+
+    | Name      | Type    | Description              |
+    |           |         |                          |
+    +===========+=========+==========================+
+    | client_id | integer | client id.               |
+    +-----------+---------+--------------------------+
+
+Request example
+^^^^^^^^^^^^^^^
+
+.. code-block:: console
+
+    curl -X GET -H 'application/json' \
+    http://127.0.0.1:7777/v1/mirrors/1
+
+Response
+^^^^^^^^
+
+.. _table_spp_ctl_spp_mirror_res:
+
+.. table:: Response params of getting spp_mirror.
+
+    +------------------+---------+-----------------------------------------------+
+    | Name             | Type    | Description                                   |
+    |                  |         |                                               |
+    +==================+=========+===============================================+
+    | client-id        | integer | client id.                                    |
+    +------------------+---------+-----------------------------------------------+
+    | ports            | array   | an array of port ids used by the process.     |
+    +------------------+---------+-----------------------------------------------+
+    | components       | array   | an array of component objects in the process. |
+    +------------------+---------+-----------------------------------------------+
+
+component object:
+
+.. _table_spp_ctl_spp_mirror_res_comp:
+
+.. table:: Component objects of getting spp_mirror.
+
+    +---------+---------+---------------------------------------------------------------------+
+    | Name    | Type    | Description                                                         |
+    |         |         |                                                                     |
+    +=========+=========+=====================================================================+
+    | core    | integer | core id running on the component                                    |
+    +---------+---------+---------------------------------------------------------------------+
+    | name    | string  | an array of port ids used by the process.                           |
+    +---------+---------+---------------------------------------------------------------------+
+    | type    | string  | an array of component objects in the process.                       |
+    +---------+---------+---------------------------------------------------------------------+
+    | rx_port | array   | an array of port objects connected to the rx side of the component. |
+    +---------+---------+---------------------------------------------------------------------+
+    | tx_port | array   | an array of port objects connected to the tx side of the component. |
+    +---------+---------+---------------------------------------------------------------------+
+
+port object:
+
+.. _table_spp_ctl_spp_mirror_res_port:
+
+.. table:: Port objects of getting spp_vf.
+
+    +---------+---------+---------------------------------------------------------------+
+    | Name    | Type    | Description                                                   |
+    |         |         |                                                               |
+    +=========+=========+===============================================================+
+    | port    | string  | port id. port id is the form {interface_type}:{interface_id}. |
+    +---------+---------+---------------------------------------------------------------+
+
+Response example
+^^^^^^^^^^^^^^^^
+
+.. code-block:: json
+
+    {
+      "client-id": 1,
+      "ports": [
+        "phy:0", "phy:1", "ring:0", "ring:1", "ring:2"
+      ],
+      "components": [
+        {
+          "core": 2,
+          "name": "mirror_0",
+          "type": "mirror",
+          "rx_port": [
+            {
+            "port": "ring:0"
+            }
+          ],
+          "tx_port": [
+            {
+              "port": "ring:1"
+            },
+            {
+              "port": "ring:2"
+            }
+          ]
+        },
+        {
+          "core": 3,
+          "type": "unuse"
+        }
+      ]
+    }
+
+The component which type is ``unused`` is to indicate unused core.
+
+Equivalent CLI command
+^^^^^^^^^^^^^^^^^^^^^^
+
+.. code-block:: none
+
+    sec {client_id};status
+
+
+POST /v1/mirrors/{client_id}/components
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Start the component.
+
+* Normal response codes: 204
+* Error response codes: 400, 404
+
+Request(path)
+^^^^^^^^^^^^^
+
+.. _table_spp_ctl_spp_mirror_components:
+
+.. table:: Request params of components of spp_mirror.
+
+    +-----------+---------+-------------+
+    | Name      | Type    | Description |
+    +===========+=========+=============+
+    | client_id | integer | client id.  |
+    +-----------+---------+-------------+
+
+
+Request(body)
+^^^^^^^^^^^^^
+
+.. _table_spp_ctl_spp_mirror_components_res:
+
+.. table:: Response params of components of spp_mirror.
+
+    +-----------+---------+----------------------------------------------------------------------+
+    | Name      | Type    | Description                                                          |
+    |           |         |                                                                      |
+    +===========+=========+======================================================================+
+    | name      | string  | component name. must be unique in the process.                       |
+    +-----------+---------+----------------------------------------------------------------------+
+    | core      | integer | core id.                                                             |
+    +-----------+---------+----------------------------------------------------------------------+
+    | type      | string  | component type. only ``mirror`` is available.                        |
+    +-----------+---------+----------------------------------------------------------------------+
+
+Request example
+^^^^^^^^^^^^^^^
+
+.. code-block:: console
+
+    curl -X POST -H 'application/json' \
+    -d '{"name": "mirror_1", "core": 12, "type": "mirror"}' \
+    http://127.0.0.1:7777/v1/mirrors/1/components
+
+Response
+^^^^^^^^
+
+There is no body content for the response of a successful ``POST`` request.
+
+Equivalent CLI command
+^^^^^^^^^^^^^^^^^^^^^^
+
+.. code-block:: none
+
+    sec {client_id};component start {name} {core} {type}
+
+
+DELETE /v1/mirrors/{client_id}/components/{name}
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Stop the component.
+
+* Normal response codes: 204
+* Error response codes: 400, 404
+
+Request(path)
+^^^^^^^^^^^^^
+
+.. _table_spp_ctl_spp_mirror_del:
+
+.. table:: Request params of deleting component of spp_mirror.
+
+    +-----------+---------+---------------------------------+
+    | Name      | Type    | Description                     |
+    |           |         |                                 |
+    +===========+=========+=================================+
+    | client_id | integer | client id.                      |
+    +-----------+---------+---------------------------------+
+    | name      | string  | component name.                 |
+    +-----------+---------+---------------------------------+
+
+Request example
+^^^^^^^^^^^^^^^
+
+.. code-block:: console
+
+    curl -X DELETE -H 'application/json' \
+    http://127.0.0.1:7777/v1/mirrors/1/components/mirror_1
+
+Response
+^^^^^^^^
+
+There is no body content for the response of a successful ``POST`` request.
+
+Equivalent CLI command
+^^^^^^^^^^^^^^^^^^^^^^
+
+.. code-block:: none
+
+    sec {client_id};component stop {name}
+
+
+PUT /v1/mirrors/{client_id}/components/{name}/ports
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Add or Delete port to the component.
+
+* Normal response codes: 204
+* Error response codes: 400, 404
+
+Request(path)
+^^^^^^^^^^^^^
+
+.. _table_spp_ctl_spp_mirror_comp_port:
+
+.. table:: Request params for ports of component of spp_mirror.
+
+    +-----------+---------+---------------------------+
+    | Name      | Type    | Description               |
+    |           |         |                           |
+    +===========+=========+===========================+
+    | client_id | integer | client id.                |
+    +-----------+---------+---------------------------+
+    | name      | string  | component name.           |
+    +-----------+---------+---------------------------+
+
+Request(body)
+^^^^^^^^^^^^^
+
+.. _table_spp_ctl_spp_mirror_comp_port_body:
+
+.. table:: Request body params for ports of component of spp_mirror.
+
+    +---------+---------+-----------------------------------------------------------------+
+    | Name    | Type    | Description                                                     |
+    |         |         |                                                                 |
+    +=========+=========+=================================================================+
+    | action  | string  | ``attach`` or ``detach``.                                       |
+    +---------+---------+-----------------------------------------------------------------+
+    | port    | string  | port id. port id is the form {interface_type}:{interface_id}.   |
+    +---------+---------+-----------------------------------------------------------------+
+    | dir     | string  | ``rx`` or ``tx``.                                               |
+    +---------+---------+-----------------------------------------------------------------+
+
+Request example
+^^^^^^^^^^^^^^^
+
+.. code-block:: console
+
+    curl -X PUT -H 'application/json' \
+    -d '{"action": "attach", "port": "ring:1", "dir": "rx"}' \
+    http://127.0.0.1:7777/v1/mirrors/1/components/mirror_1/ports
+
+.. code-block:: console
+
+    curl -X PUT -H 'application/json' \
+    -d '{"action": "detach", "port": "ring:0", "dir": "tx"} \
+    http://127.0.0.1:7777/v1/mirrors/1/components/mirror_1/ports
+
+Response
+^^^^^^^^
+
+There is no body content for the response of a successful ``PUT`` request.
+
+Equivalent CLI command
+^^^^^^^^^^^^^^^^^^^^^^
+
+action is ``attach``
+
+.. code-block:: none
+
+    sec {client_id};port add {port} {dir} {name}
+
+action is ``detach``
+
+.. code-block:: none
+
+    sec {client_id};port del {port} {dir} {name}
-- 
2.17.1

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [spp] [PATCH 0/2] spp_mirror API support
  2018-11-29  0:55 [spp] [PATCH 0/2] spp_mirror API support oda
  2018-11-29  0:55 ` [spp] [PATCH 1/2] " oda
  2018-11-29  0:55 ` [spp] [PATCH 2/2] spp_mirror API api-reference oda
@ 2018-11-29  1:36 ` Yasufumi Ogawa
  2018-11-29  2:04 ` [spp] [PATCH v2 " oda
  3 siblings, 0 replies; 8+ messages in thread
From: Yasufumi Ogawa @ 2018-11-29  1:36 UTC (permalink / raw)
  To: oda; +Cc: spp, ferruh.yigit

> As new process spp_mirror is introduced, spp-ctl supports
> its API.
Hi Itsuro,

Thank you for your update quickly. Your patches are looks good, but titles of commit messages are inappropriate.

Could you revise them for v2 patches as following if you agree?
     spp-ctl: add spp_mirror API support
     docs: add spp_mirror API api-reference

Thanks,
Yasufumi
> 
> Itsuro Oda (2):
>    spp_mirror API support
>    spp_mirror API api-reference
> 
>   docs/guides/spp-ctl/api-reference.rst | 316 ++++++++++++++++++++++++++
>   src/spp-ctl/spp_ctl.py                |   2 +-
>   src/spp-ctl/spp_proc.py               |  57 +++--
>   src/spp-ctl/spp_webapi.py             | 120 +++++++---
>   4 files changed, 443 insertions(+), 52 deletions(-)

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [spp] [PATCH v2 0/2] spp_mirror API support
  2018-11-29  0:55 [spp] [PATCH 0/2] spp_mirror API support oda
                   ` (2 preceding siblings ...)
  2018-11-29  1:36 ` [spp] [PATCH 0/2] spp_mirror API support Yasufumi Ogawa
@ 2018-11-29  2:04 ` oda
  2018-11-29  2:04   ` [spp] [PATCH v2 1/2] spp-ctl: add " oda
                     ` (2 more replies)
  3 siblings, 3 replies; 8+ messages in thread
From: oda @ 2018-11-29  2:04 UTC (permalink / raw)
  To: spp, ferruh.yigit, ogawa.yasufumi

From: Itsuro Oda <oda@valinux.co.jp>

As new process spp_mirror is introduced, spp-ctl supports
its API.

Itsuro Oda (2):
  spp-ctl: add spp_mirror API support
  docs: add spp_mirror API api-reference

 docs/guides/spp-ctl/api-reference.rst | 316 ++++++++++++++++++++++++++
 src/spp-ctl/spp_ctl.py                |   2 +-
 src/spp-ctl/spp_proc.py               |  57 +++--
 src/spp-ctl/spp_webapi.py             | 120 +++++++---
 4 files changed, 443 insertions(+), 52 deletions(-)

-- 
2.17.1

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [spp] [PATCH v2 1/2] spp-ctl: add spp_mirror API support
  2018-11-29  2:04 ` [spp] [PATCH v2 " oda
@ 2018-11-29  2:04   ` oda
  2018-11-29  2:04   ` [spp] [PATCH v2 2/2] docs: add spp_mirror API api-reference oda
  2018-11-29 10:01   ` [spp] [PATCH v2 0/2] spp_mirror API support Yasufumi Ogawa
  2 siblings, 0 replies; 8+ messages in thread
From: oda @ 2018-11-29  2:04 UTC (permalink / raw)
  To: spp, ferruh.yigit, ogawa.yasufumi

From: Itsuro Oda <oda@valinux.co.jp>

This patch adds spp_mirror APIs to spp-ctl.

Signed-off-by: Itsuro Oda <oda@valinux.co.jp>
---
 src/spp-ctl/spp_ctl.py    |   2 +-
 src/spp-ctl/spp_proc.py   |  57 +++++++++++++-----
 src/spp-ctl/spp_webapi.py | 120 ++++++++++++++++++++++++++------------
 3 files changed, 127 insertions(+), 52 deletions(-)

diff --git a/src/spp-ctl/spp_ctl.py b/src/spp-ctl/spp_ctl.py
index 0576ae1..279c180 100644
--- a/src/spp-ctl/spp_ctl.py
+++ b/src/spp-ctl/spp_ctl.py
@@ -128,7 +128,7 @@ class Controller(object):
         # it is a bit ad hoc. send "_get_clinet_id" command and try to
         # decode reply for each proc type. if success, that is the type.
         data = self._send_command(conn, "_get_client_id")
-        for proc in [spp_proc.VfProc, spp_proc.NfvProc]:
+        for proc in [spp_proc.VfProc, spp_proc.NfvProc, spp_proc.MirrorProc]:
             sec_id = proc._decode_client_id(data)
             if sec_id is not None:
                 return proc(sec_id, conn)
diff --git a/src/spp-ctl/spp_proc.py b/src/spp-ctl/spp_proc.py
index 83c59ea..648e085 100644
--- a/src/spp-ctl/spp_proc.py
+++ b/src/spp-ctl/spp_proc.py
@@ -15,6 +15,7 @@ ID_PRIMARY = 0
 TYPE_PRIMARY = "primary"
 TYPE_VF = "vf"
 TYPE_NFV = "nfv"
+TYPE_MIRROR = "mirror"
 
 
 def exec_command(func):
@@ -53,10 +54,10 @@ class SppProc(object):
         self.conn = conn
 
 
-class VfProc(SppProc):
+class VfCommon(SppProc):
 
-    def __init__(self, id, conn):
-        super(VfProc, self).__init__(TYPE_VF, id, conn)
+    def __init__(self, proc_type, id, conn):
+        super(VfCommon, self).__init__(proc_type, id, conn)
 
     @staticmethod
     def _decode_reply(data):
@@ -67,14 +68,6 @@ class VfProc(SppProc):
             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"
@@ -88,6 +81,25 @@ class VfProc(SppProc):
     def stop_component(self, comp_name):
         return "component stop {comp_name}".format(**locals())
 
+    @exec_command
+    def port_del(self, port, direction, comp_name):
+        return "port del {port} {direction} {comp_name}".format(**locals())
+
+
+class VfProc(VfCommon):
+
+    def __init__(self, id, conn):
+        super(VfProc, self).__init__(TYPE_VF, id, conn)
+
+    @staticmethod
+    def _decode_client_id(data):
+        try:
+            data = VfCommon._decode_reply(data)
+            if data["process_type"] == TYPE_VF:
+                return data["client_id"]
+        except:
+            return None
+
     @exec_command
     def port_add(self, port, direction, comp_name, op, vlan_id, pcp):
         command = "port add {port} {direction} {comp_name}".format(**locals())
@@ -97,10 +109,6 @@ class VfProc(SppProc):
                 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}"
@@ -124,6 +132,25 @@ class VfProc(SppProc):
                 .format(**locals()))
 
 
+class MirrorProc(VfCommon):
+
+    def __init__(self, id, conn):
+        super(MirrorProc, self).__init__(TYPE_MIRROR, id, conn)
+
+    @staticmethod
+    def _decode_client_id(data):
+        try:
+            data = VfCommon._decode_reply(data)
+            if data["process_type"] == TYPE_MIRROR:
+                return data["client_id"]
+        except:
+            return None
+
+    @exec_command
+    def port_add(self, port, direction, comp_name):
+        return "port add {port} {direction} {comp_name}".format(**locals())
+
+
 class NfvProc(SppProc):
 
     def __init__(self, id, conn):
diff --git a/src/spp-ctl/spp_webapi.py b/src/spp-ctl/spp_webapi.py
index 48cc1c4..7547f0e 100644
--- a/src/spp-ctl/spp_webapi.py
+++ b/src/spp-ctl/spp_webapi.py
@@ -114,6 +114,7 @@ class WebServer(BaseHandler):
     /          WebServer
     /v1          V1Handler
        /vfs        V1VFHandler
+       /mirrors    V1MirrorHandler
        /nfvs       V1NFVHandler
        /primary    V1PrimaryHandler
     """
@@ -141,6 +142,7 @@ class V1Handler(BaseHandler):
         self.set_route()
 
         self.mount("/vfs", V1VFHandler(controller))
+        self.mount("/mirrors", V1MirrorHandler(controller))
         self.mount("/nfvs", V1NFVHandler(controller))
         self.mount("/primary", V1PrimaryHandler(controller))
 
@@ -154,7 +156,46 @@ class V1Handler(BaseHandler):
         return self.ctrl.get_processes()
 
 
-class V1VFHandler(BaseHandler):
+class V1VFCommon(object):
+    """Define common methods for vf and mirror handler."""
+
+    def convert_info(self, data):
+        info = data["info"]
+        vf = {}
+        vf["client-id"] = info["client-id"]
+        vf["ports"] = []
+        for key in ["phy", "vhost", "ring"]:
+            for idx in info[key]:
+                vf["ports"].append(key + ":" + str(idx))
+        vf["components"] = info["core"]
+        if "classifier_table" in info:
+            vf["classifier_table"] = info["classifier_table"]
+
+        return vf
+
+    def validate_comp_start(self, body, types):
+        for key in ['name', 'core', 'type']:
+            if key not in body:
+                raise KeyRequired(key)
+        if not isinstance(body['name'], str):
+            raise KeyInvalid('name', body['name'])
+        if not isinstance(body['core'], int):
+            raise KeyInvalid('core', body['core'])
+        if body['type'] not in types:
+            raise KeyInvalid('type', body['type'])
+
+    def validate_comp_port(self, body):
+        for key in ['action', 'port', 'dir']:
+            if key not in body:
+                raise KeyRequired(key)
+        if body['action'] not in ["attach", "detach"]:
+            raise KeyInvalid('action', body['action'])
+        if body['dir'] not in ["rx", "tx"]:
+            raise KeyInvalid('dir', body['dir'])
+        self._validate_port(body['port'])
+
+
+class V1VFHandler(BaseHandler, V1VFCommon):
 
     def __init__(self, controller):
         super(V1VFHandler, self).__init__(controller)
@@ -177,50 +218,18 @@ class V1VFHandler(BaseHandler):
         self.route('/<sec_id:int>/classifier_table', 'PUT',
                    callback=self.vf_classifier)
 
-    def convert_vf_info(self, data):
-        info = data["info"]
-        vf = {}
-        vf["client-id"] = info["client-id"]
-        vf["ports"] = []
-        for key in ["phy", "vhost", "ring"]:
-            for idx in info[key]:
-                vf["ports"].append(key + ":" + str(idx))
-        vf["components"] = info["core"]
-        vf["classifier_table"] = info["classifier_table"]
-
-        return vf
-
     def vf_get(self, proc):
-        return self.convert_vf_info(proc.get_status())
-
-    def _validate_vf_comp_start(self, body):
-        for key in ['name', 'core', 'type']:
-            if key not in body:
-                raise KeyRequired(key)
-        if not isinstance(body['name'], str):
-            raise KeyInvalid('name', body['name'])
-        if not isinstance(body['core'], int):
-            raise KeyInvalid('core', body['core'])
-        if body['type'] not in ["forward", "merge", "classifier_mac"]:
-            raise KeyInvalid('type', body['type'])
+        return self.convert_info(proc.get_status())
 
     def vf_comp_start(self, proc, body):
-        self._validate_vf_comp_start(body)
+        self.validate_comp_start(body, ["forward", "merge", "classifier_mac"])
         proc.start_component(body['name'], body['core'], body['type'])
 
     def vf_comp_stop(self, proc, name):
         proc.stop_component(name)
 
     def _validate_vf_comp_port(self, body):
-        for key in ['action', 'port', 'dir']:
-            if key not in body:
-                raise KeyRequired(key)
-        if body['action'] not in ["attach", "detach"]:
-            raise KeyInvalid('action', body['action'])
-        if body['dir'] not in ["rx", "tx"]:
-            raise KeyInvalid('dir', body['dir'])
-        self._validate_port(body['port'])
-
+        self.validate_comp_port(body)
         if body['action'] == "attach":
             vlan = body.get('vlan')
             if vlan:
@@ -296,6 +305,45 @@ class V1VFHandler(BaseHandler):
                     mac_address, port, body['vlan'])
 
 
+class V1MirrorHandler(BaseHandler, V1VFCommon):
+
+    def __init__(self, controller):
+        super(V1MirrorHandler, self).__init__(controller)
+        self.type = spp_proc.TYPE_MIRROR
+
+        self.set_route()
+
+        self.install(self.check_sec_id)
+        self.install(self.get_body)
+        self.install(self.make_response)
+
+    def set_route(self):
+        self.route('/<sec_id:int>', 'GET', callback=self.mirror_get)
+        self.route('/<sec_id:int>/components', 'POST',
+                   callback=self.mirror_comp_start)
+        self.route('/<sec_id:int>/components/<name>', 'DELETE',
+                   callback=self.mirror_comp_stop)
+        self.route('/<sec_id:int>/components/<name>/ports', 'PUT',
+                   callback=self.mirror_comp_port)
+
+    def mirror_get(self, proc):
+        return self.convert_info(proc.get_status())
+
+    def mirror_comp_start(self, proc, body):
+        self.validate_comp_start(body, ["mirror"])
+        proc.start_component(body['name'], body['core'], body['type'])
+
+    def mirror_comp_stop(self, proc, name):
+        proc.stop_component(name)
+
+    def mirror_comp_port(self, proc, name, body):
+        self.validate_comp_port(body)
+        if body['action'] == "attach":
+            proc.port_add(body['port'], body['dir'], name)
+        else:
+            proc.port_del(body['port'], body['dir'], name)
+
+
 class V1NFVHandler(BaseHandler):
 
     def __init__(self, controller):
-- 
2.17.1

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [spp] [PATCH v2 2/2] docs: add spp_mirror API api-reference
  2018-11-29  2:04 ` [spp] [PATCH v2 " oda
  2018-11-29  2:04   ` [spp] [PATCH v2 1/2] spp-ctl: add " oda
@ 2018-11-29  2:04   ` oda
  2018-11-29 10:01   ` [spp] [PATCH v2 0/2] spp_mirror API support Yasufumi Ogawa
  2 siblings, 0 replies; 8+ messages in thread
From: oda @ 2018-11-29  2:04 UTC (permalink / raw)
  To: spp, ferruh.yigit, ogawa.yasufumi

From: Itsuro Oda <oda@valinux.co.jp>

This patch adds spp_mirror API reference for spp-ctl.

Signed-off-by: Itsuro Oda <oda@valinux.co.jp>
---
 docs/guides/spp-ctl/api-reference.rst | 316 ++++++++++++++++++++++++++
 1 file changed, 316 insertions(+)

diff --git a/docs/guides/spp-ctl/api-reference.rst b/docs/guides/spp-ctl/api-reference.rst
index 70eddd6..b0d367b 100644
--- a/docs/guides/spp-ctl/api-reference.rst
+++ b/docs/guides/spp-ctl/api-reference.rst
@@ -1168,3 +1168,319 @@ type is ``vlan``
 .. code-block:: none
 
     classifier_table {action} vlan {vlan} {mac_address} {port}
+
+
+API for spp_mirror
+------------------
+
+GET /v1/mirrors/{client_id}
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Get the information of the ``spp_mirror`` process.
+
+* Normal response codes: 200
+* Error response codes: 400, 404
+
+Request(path)
+^^^^^^^^^^^^^
+
+.. _table_spp_ctl_mirrors_get:
+
+.. table:: Request parameter for getting spp_mirror.
+
+    +-----------+---------+--------------------------+
+    | Name      | Type    | Description              |
+    |           |         |                          |
+    +===========+=========+==========================+
+    | client_id | integer | client id.               |
+    +-----------+---------+--------------------------+
+
+Request example
+^^^^^^^^^^^^^^^
+
+.. code-block:: console
+
+    curl -X GET -H 'application/json' \
+    http://127.0.0.1:7777/v1/mirrors/1
+
+Response
+^^^^^^^^
+
+.. _table_spp_ctl_spp_mirror_res:
+
+.. table:: Response params of getting spp_mirror.
+
+    +------------------+---------+-----------------------------------------------+
+    | Name             | Type    | Description                                   |
+    |                  |         |                                               |
+    +==================+=========+===============================================+
+    | client-id        | integer | client id.                                    |
+    +------------------+---------+-----------------------------------------------+
+    | ports            | array   | an array of port ids used by the process.     |
+    +------------------+---------+-----------------------------------------------+
+    | components       | array   | an array of component objects in the process. |
+    +------------------+---------+-----------------------------------------------+
+
+component object:
+
+.. _table_spp_ctl_spp_mirror_res_comp:
+
+.. table:: Component objects of getting spp_mirror.
+
+    +---------+---------+---------------------------------------------------------------------+
+    | Name    | Type    | Description                                                         |
+    |         |         |                                                                     |
+    +=========+=========+=====================================================================+
+    | core    | integer | core id running on the component                                    |
+    +---------+---------+---------------------------------------------------------------------+
+    | name    | string  | an array of port ids used by the process.                           |
+    +---------+---------+---------------------------------------------------------------------+
+    | type    | string  | an array of component objects in the process.                       |
+    +---------+---------+---------------------------------------------------------------------+
+    | rx_port | array   | an array of port objects connected to the rx side of the component. |
+    +---------+---------+---------------------------------------------------------------------+
+    | tx_port | array   | an array of port objects connected to the tx side of the component. |
+    +---------+---------+---------------------------------------------------------------------+
+
+port object:
+
+.. _table_spp_ctl_spp_mirror_res_port:
+
+.. table:: Port objects of getting spp_vf.
+
+    +---------+---------+---------------------------------------------------------------+
+    | Name    | Type    | Description                                                   |
+    |         |         |                                                               |
+    +=========+=========+===============================================================+
+    | port    | string  | port id. port id is the form {interface_type}:{interface_id}. |
+    +---------+---------+---------------------------------------------------------------+
+
+Response example
+^^^^^^^^^^^^^^^^
+
+.. code-block:: json
+
+    {
+      "client-id": 1,
+      "ports": [
+        "phy:0", "phy:1", "ring:0", "ring:1", "ring:2"
+      ],
+      "components": [
+        {
+          "core": 2,
+          "name": "mirror_0",
+          "type": "mirror",
+          "rx_port": [
+            {
+            "port": "ring:0"
+            }
+          ],
+          "tx_port": [
+            {
+              "port": "ring:1"
+            },
+            {
+              "port": "ring:2"
+            }
+          ]
+        },
+        {
+          "core": 3,
+          "type": "unuse"
+        }
+      ]
+    }
+
+The component which type is ``unused`` is to indicate unused core.
+
+Equivalent CLI command
+^^^^^^^^^^^^^^^^^^^^^^
+
+.. code-block:: none
+
+    sec {client_id};status
+
+
+POST /v1/mirrors/{client_id}/components
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Start the component.
+
+* Normal response codes: 204
+* Error response codes: 400, 404
+
+Request(path)
+^^^^^^^^^^^^^
+
+.. _table_spp_ctl_spp_mirror_components:
+
+.. table:: Request params of components of spp_mirror.
+
+    +-----------+---------+-------------+
+    | Name      | Type    | Description |
+    +===========+=========+=============+
+    | client_id | integer | client id.  |
+    +-----------+---------+-------------+
+
+
+Request(body)
+^^^^^^^^^^^^^
+
+.. _table_spp_ctl_spp_mirror_components_res:
+
+.. table:: Response params of components of spp_mirror.
+
+    +-----------+---------+----------------------------------------------------------------------+
+    | Name      | Type    | Description                                                          |
+    |           |         |                                                                      |
+    +===========+=========+======================================================================+
+    | name      | string  | component name. must be unique in the process.                       |
+    +-----------+---------+----------------------------------------------------------------------+
+    | core      | integer | core id.                                                             |
+    +-----------+---------+----------------------------------------------------------------------+
+    | type      | string  | component type. only ``mirror`` is available.                        |
+    +-----------+---------+----------------------------------------------------------------------+
+
+Request example
+^^^^^^^^^^^^^^^
+
+.. code-block:: console
+
+    curl -X POST -H 'application/json' \
+    -d '{"name": "mirror_1", "core": 12, "type": "mirror"}' \
+    http://127.0.0.1:7777/v1/mirrors/1/components
+
+Response
+^^^^^^^^
+
+There is no body content for the response of a successful ``POST`` request.
+
+Equivalent CLI command
+^^^^^^^^^^^^^^^^^^^^^^
+
+.. code-block:: none
+
+    sec {client_id};component start {name} {core} {type}
+
+
+DELETE /v1/mirrors/{client_id}/components/{name}
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Stop the component.
+
+* Normal response codes: 204
+* Error response codes: 400, 404
+
+Request(path)
+^^^^^^^^^^^^^
+
+.. _table_spp_ctl_spp_mirror_del:
+
+.. table:: Request params of deleting component of spp_mirror.
+
+    +-----------+---------+---------------------------------+
+    | Name      | Type    | Description                     |
+    |           |         |                                 |
+    +===========+=========+=================================+
+    | client_id | integer | client id.                      |
+    +-----------+---------+---------------------------------+
+    | name      | string  | component name.                 |
+    +-----------+---------+---------------------------------+
+
+Request example
+^^^^^^^^^^^^^^^
+
+.. code-block:: console
+
+    curl -X DELETE -H 'application/json' \
+    http://127.0.0.1:7777/v1/mirrors/1/components/mirror_1
+
+Response
+^^^^^^^^
+
+There is no body content for the response of a successful ``POST`` request.
+
+Equivalent CLI command
+^^^^^^^^^^^^^^^^^^^^^^
+
+.. code-block:: none
+
+    sec {client_id};component stop {name}
+
+
+PUT /v1/mirrors/{client_id}/components/{name}/ports
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Add or Delete port to the component.
+
+* Normal response codes: 204
+* Error response codes: 400, 404
+
+Request(path)
+^^^^^^^^^^^^^
+
+.. _table_spp_ctl_spp_mirror_comp_port:
+
+.. table:: Request params for ports of component of spp_mirror.
+
+    +-----------+---------+---------------------------+
+    | Name      | Type    | Description               |
+    |           |         |                           |
+    +===========+=========+===========================+
+    | client_id | integer | client id.                |
+    +-----------+---------+---------------------------+
+    | name      | string  | component name.           |
+    +-----------+---------+---------------------------+
+
+Request(body)
+^^^^^^^^^^^^^
+
+.. _table_spp_ctl_spp_mirror_comp_port_body:
+
+.. table:: Request body params for ports of component of spp_mirror.
+
+    +---------+---------+-----------------------------------------------------------------+
+    | Name    | Type    | Description                                                     |
+    |         |         |                                                                 |
+    +=========+=========+=================================================================+
+    | action  | string  | ``attach`` or ``detach``.                                       |
+    +---------+---------+-----------------------------------------------------------------+
+    | port    | string  | port id. port id is the form {interface_type}:{interface_id}.   |
+    +---------+---------+-----------------------------------------------------------------+
+    | dir     | string  | ``rx`` or ``tx``.                                               |
+    +---------+---------+-----------------------------------------------------------------+
+
+Request example
+^^^^^^^^^^^^^^^
+
+.. code-block:: console
+
+    curl -X PUT -H 'application/json' \
+    -d '{"action": "attach", "port": "ring:1", "dir": "rx"}' \
+    http://127.0.0.1:7777/v1/mirrors/1/components/mirror_1/ports
+
+.. code-block:: console
+
+    curl -X PUT -H 'application/json' \
+    -d '{"action": "detach", "port": "ring:0", "dir": "tx"} \
+    http://127.0.0.1:7777/v1/mirrors/1/components/mirror_1/ports
+
+Response
+^^^^^^^^
+
+There is no body content for the response of a successful ``PUT`` request.
+
+Equivalent CLI command
+^^^^^^^^^^^^^^^^^^^^^^
+
+action is ``attach``
+
+.. code-block:: none
+
+    sec {client_id};port add {port} {dir} {name}
+
+action is ``detach``
+
+.. code-block:: none
+
+    sec {client_id};port del {port} {dir} {name}
-- 
2.17.1

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [spp] [PATCH v2 0/2] spp_mirror API support
  2018-11-29  2:04 ` [spp] [PATCH v2 " oda
  2018-11-29  2:04   ` [spp] [PATCH v2 1/2] spp-ctl: add " oda
  2018-11-29  2:04   ` [spp] [PATCH v2 2/2] docs: add spp_mirror API api-reference oda
@ 2018-11-29 10:01   ` Yasufumi Ogawa
  2 siblings, 0 replies; 8+ messages in thread
From: Yasufumi Ogawa @ 2018-11-29 10:01 UTC (permalink / raw)
  To: oda, spp; +Cc: ferruh.yigit

> As new process spp_mirror is introduced, spp-ctl supports
> its API.
Thank you for updating to v2. I have tried to your updates and confirmed it works fine!

Acked-by: Yasufumi Ogawa <ogawa.yasufumi@lab.ntt.co.jp>
> 
> Itsuro Oda (2):
>    spp-ctl: add spp_mirror API support
>    docs: add spp_mirror API api-reference
> 
>   docs/guides/spp-ctl/api-reference.rst | 316 ++++++++++++++++++++++++++
>   src/spp-ctl/spp_ctl.py                |   2 +-
>   src/spp-ctl/spp_proc.py               |  57 +++--
>   src/spp-ctl/spp_webapi.py             | 120 +++++++---
>   4 files changed, 443 insertions(+), 52 deletions(-)

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2018-11-29 10:04 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-11-29  0:55 [spp] [PATCH 0/2] spp_mirror API support oda
2018-11-29  0:55 ` [spp] [PATCH 1/2] " oda
2018-11-29  0:55 ` [spp] [PATCH 2/2] spp_mirror API api-reference oda
2018-11-29  1:36 ` [spp] [PATCH 0/2] spp_mirror API support Yasufumi Ogawa
2018-11-29  2:04 ` [spp] [PATCH v2 " oda
2018-11-29  2:04   ` [spp] [PATCH v2 1/2] spp-ctl: add " oda
2018-11-29  2:04   ` [spp] [PATCH v2 2/2] docs: add spp_mirror API api-reference oda
2018-11-29 10:01   ` [spp] [PATCH v2 0/2] spp_mirror API support Yasufumi Ogawa

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).