get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

GET /api/patches/818456/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 818456,
    "url": "http://patchwork.ozlabs.org/api/patches/818456/?format=api",
    "web_url": "http://patchwork.ozlabs.org/project/openvswitch/patch/1506404199-23579-2-git-send-email-yliu@fridaylinux.org/",
    "project": {
        "id": 47,
        "url": "http://patchwork.ozlabs.org/api/projects/47/?format=api",
        "name": "Open vSwitch",
        "link_name": "openvswitch",
        "list_id": "ovs-dev.openvswitch.org",
        "list_email": "ovs-dev@openvswitch.org",
        "web_url": "http://openvswitch.org/",
        "scm_url": "git@github.com:openvswitch/ovs.git",
        "webscm_url": "https://github.com/openvswitch/ovs",
        "list_archive_url": "",
        "list_archive_url_format": "",
        "commit_url_format": ""
    },
    "msgid": "<1506404199-23579-2-git-send-email-yliu@fridaylinux.org>",
    "list_archive_url": null,
    "date": "2017-09-26T05:36:31",
    "name": "[ovs-dev,v3,1/9] dpif-netdev: associate flow with a mark id",
    "commit_ref": null,
    "pull_url": null,
    "state": "changes-requested",
    "archived": false,
    "hash": "7fd69e5d7f476882e320e536acf95259323689c1",
    "submitter": {
        "id": 72215,
        "url": "http://patchwork.ozlabs.org/api/people/72215/?format=api",
        "name": "Yuanhan Liu",
        "email": "yliu@fridaylinux.org"
    },
    "delegate": null,
    "mbox": "http://patchwork.ozlabs.org/project/openvswitch/patch/1506404199-23579-2-git-send-email-yliu@fridaylinux.org/mbox/",
    "series": [
        {
            "id": 5061,
            "url": "http://patchwork.ozlabs.org/api/series/5061/?format=api",
            "web_url": "http://patchwork.ozlabs.org/project/openvswitch/list/?series=5061",
            "date": "2017-09-26T05:36:30",
            "name": "OVS-DPDK flow offload with rte_flow",
            "version": 3,
            "mbox": "http://patchwork.ozlabs.org/series/5061/mbox/"
        }
    ],
    "comments": "http://patchwork.ozlabs.org/api/patches/818456/comments/",
    "check": "pending",
    "checks": "http://patchwork.ozlabs.org/api/patches/818456/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<ovs-dev-bounces@openvswitch.org>",
        "X-Original-To": [
            "incoming@patchwork.ozlabs.org",
            "dev@openvswitch.org"
        ],
        "Delivered-To": [
            "patchwork-incoming@bilbo.ozlabs.org",
            "ovs-dev@mail.linuxfoundation.org"
        ],
        "Authentication-Results": [
            "ozlabs.org;\n\tspf=pass (mailfrom) smtp.mailfrom=openvswitch.org\n\t(client-ip=140.211.169.12; helo=mail.linuxfoundation.org;\n\tenvelope-from=ovs-dev-bounces@openvswitch.org;\n\treceiver=<UNKNOWN>)",
            "ozlabs.org;\n\tdkim=fail reason=\"signature verification failed\" (2048-bit key;\n\tunprotected) header.d=fridaylinux-org.20150623.gappssmtp.com\n\theader.i=@fridaylinux-org.20150623.gappssmtp.com\n\theader.b=\"KFKtnLKf\"; dkim-atps=neutral"
        ],
        "Received": [
            "from mail.linuxfoundation.org (mail.linuxfoundation.org\n\t[140.211.169.12])\n\t(using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256\n\tbits)) (No client certificate requested)\n\tby ozlabs.org (Postfix) with ESMTPS id 3y1V9L57tkz9t30\n\tfor <incoming@patchwork.ozlabs.org>;\n\tTue, 26 Sep 2017 15:38:14 +1000 (AEST)",
            "from mail.linux-foundation.org (localhost [127.0.0.1])\n\tby mail.linuxfoundation.org (Postfix) with ESMTP id 87F82B5D;\n\tTue, 26 Sep 2017 05:38:11 +0000 (UTC)",
            "from smtp1.linuxfoundation.org (smtp1.linux-foundation.org\n\t[172.17.192.35])\n\tby mail.linuxfoundation.org (Postfix) with ESMTPS id D2A11B13\n\tfor <dev@openvswitch.org>; Tue, 26 Sep 2017 05:38:10 +0000 (UTC)",
            "from mail-pg0-f47.google.com (mail-pg0-f47.google.com\n\t[74.125.83.47])\n\tby smtp1.linuxfoundation.org (Postfix) with ESMTPS id 297CDD3\n\tfor <dev@openvswitch.org>; Tue, 26 Sep 2017 05:38:10 +0000 (UTC)",
            "by mail-pg0-f47.google.com with SMTP id p5so5358784pgn.7\n\tfor <dev@openvswitch.org>; Mon, 25 Sep 2017 22:38:10 -0700 (PDT)",
            "from localhost.localdomain ([101.228.205.132])\n\tby smtp.gmail.com with ESMTPSA id\n\to79sm13180077pfi.108.2017.09.25.22.37.32\n\t(version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128);\n\tMon, 25 Sep 2017 22:38:08 -0700 (PDT)"
        ],
        "X-Greylist": "whitelisted by SQLgrey-1.7.6",
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=fridaylinux-org.20150623.gappssmtp.com; s=20150623;\n\th=from:to:cc:subject:date:message-id:in-reply-to:references;\n\tbh=hbLoeIdpU7FHgEp+drPGWc9ybiGBWF+mAcK/J5A5/Dk=;\n\tb=KFKtnLKfFheO1st2vETXFzux70IFxT2ooEZtYeoyztojVo9uSPX7FhCEyA3CArx3D6\n\tibmjUDWlyf/WXMADo2+U326e1KisBv19Cyb3a6UqmGjoyxyUZ8uhayEeVgG7coWXAdMF\n\tKIhS6/x75pbHg7rEBL8EV0MU0MwxipOAQZUzApWful9Fnr/Y9o7kXcthtcOcTMTFcmAM\n\teVPYXtDafAeqdqEAMDvZzhKzlTcHUa2PLAqhcnNz1WnbNC7aCJypdykyAJmCljsxHZJF\n\tW48yc0PvZl/15X2ouKPjLtNkWWCVznk29UorPDEsbrTJpJEpdqJsiGso8HVzh3PNG36g\n\tFddw==",
        "X-Google-DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=1e100.net; s=20161025;\n\th=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to\n\t:references;\n\tbh=hbLoeIdpU7FHgEp+drPGWc9ybiGBWF+mAcK/J5A5/Dk=;\n\tb=ua6Nk3clV+eAtqaRPjCBwa1/vQUGOo4OCmc28fJ/h76oUlv1kApseoaLTT+w5FnBut\n\t/4QbaJHTpYGrsv5ZX0863A2oS9Ao8Ff4ykPPDAl71uLZea6AVd+5bzW5yCW004TbBU1Y\n\tSFz5wuVQM19qENhwnuUfwG//0FbkLhipi5xxYujZ+6r0XBibDLcR2BNXUQW+lFoNXBtG\n\t3aMUkM+gxG7g6oZGsv1e545Bs+nL9M8FGQMWZBukR1jh3enCvvq2CuKzpKaWPDee2tNJ\n\tfoKkx1n3dVB9mPJivlRUlMGEd8/TabMUlr7CsOSc4YjaPcd2hIs8ytCeZRPAygqfefY9\n\tkTLQ==",
        "X-Gm-Message-State": "AHPjjUhlCdPrwCWhwSzvq5vB+Cn2W/Tf3RsfuwY8cyuT/04s9uDb5vZw\n\tLf+ssX7uiboi/v1Ivv2Cdy6Q/dUfuObBdQ==",
        "X-Google-Smtp-Source": "AOwi7QDdB4O6C91dZ0jMetu7n6OhasM8LjQBiKQYPU5emqp5F/UDtoD+DsvDIQHYTo3KFigwOuO2XQ==",
        "X-Received": "by 10.99.185.26 with SMTP id z26mr9788097pge.438.1506404289302; \n\tMon, 25 Sep 2017 22:38:09 -0700 (PDT)",
        "From": "Yuanhan Liu <yliu@fridaylinux.org>",
        "To": "dev@openvswitch.org",
        "Date": "Tue, 26 Sep 2017 13:36:31 +0800",
        "Message-Id": "<1506404199-23579-2-git-send-email-yliu@fridaylinux.org>",
        "X-Mailer": "git-send-email 2.7.4",
        "In-Reply-To": "<1506404199-23579-1-git-send-email-yliu@fridaylinux.org>",
        "References": "<1506404199-23579-1-git-send-email-yliu@fridaylinux.org>",
        "X-Spam-Status": "No, score=0.0 required=5.0 tests=DKIM_SIGNED,DKIM_VALID,\n\tRCVD_IN_DNSWL_NONE autolearn=disabled version=3.3.1",
        "X-Spam-Checker-Version": "SpamAssassin 3.3.1 (2010-03-16) on\n\tsmtp1.linux-foundation.org",
        "Cc": "Simon Horman <simon.horman@netronome.com>",
        "Subject": "[ovs-dev] [PATCH v3 1/9] dpif-netdev: associate flow with a mark id",
        "X-BeenThere": "ovs-dev@openvswitch.org",
        "X-Mailman-Version": "2.1.12",
        "Precedence": "list",
        "List-Id": "<ovs-dev.openvswitch.org>",
        "List-Unsubscribe": "<https://mail.openvswitch.org/mailman/options/ovs-dev>,\n\t<mailto:ovs-dev-request@openvswitch.org?subject=unsubscribe>",
        "List-Archive": "<http://mail.openvswitch.org/pipermail/ovs-dev/>",
        "List-Post": "<mailto:ovs-dev@openvswitch.org>",
        "List-Help": "<mailto:ovs-dev-request@openvswitch.org?subject=help>",
        "List-Subscribe": "<https://mail.openvswitch.org/mailman/listinfo/ovs-dev>,\n\t<mailto:ovs-dev-request@openvswitch.org?subject=subscribe>",
        "MIME-Version": "1.0",
        "Content-Type": "text/plain; charset=\"us-ascii\"",
        "Content-Transfer-Encoding": "7bit",
        "Sender": "ovs-dev-bounces@openvswitch.org",
        "Errors-To": "ovs-dev-bounces@openvswitch.org"
    },
    "content": "This patch associate a flow with a mark id (a uint32_t number) by a\ndirect array. The array is initiated with 1024 slots at the begninning,\nand it will be enlarged when it's not big enough.  The mark id is\nallocated with the help of id-pool.\n\nIt re-uses the flow API (more precisely, the ->flow_put method) to setup\nthe hw flow. The flow_put implementation then is supposed to create a\nflow with MARK action for current stage, which is, only partial offload\nis supported.\n\nCo-authored-by: Finn Christensen <fc@napatech.com>\nSigned-off-by: Yuanhan Liu <yliu@fridaylinux.org>\nSigned-off-by: Finn Christensen <fc@napatech.com>\n---\n lib/dpif-netdev.c | 140 ++++++++++++++++++++++++++++++++++++++++++++++++++++++\n lib/netdev.h      |   6 +++\n 2 files changed, 146 insertions(+)",
    "diff": "diff --git a/lib/dpif-netdev.c b/lib/dpif-netdev.c\nindex 071ec14..f417b25 100644\n--- a/lib/dpif-netdev.c\n+++ b/lib/dpif-netdev.c\n@@ -453,6 +453,9 @@ struct dp_netdev_flow {\n     struct ovs_refcount ref_cnt;\n \n     bool dead;\n+    bool has_mark;               /* A flag to tell whether this flow has a\n+                                    valid mark asscoiated with it. */\n+    uint32_t mark;               /* Unique flow mark assiged to a flow */\n \n     /* Statistics. */\n     struct dp_netdev_flow_stats stats;\n@@ -1833,6 +1836,82 @@ dp_netdev_pmd_find_dpcls(struct dp_netdev_pmd_thread *pmd,\n     return cls;\n }\n \n+/*\n+ * An array to map from the flow mark (the index) to dp netdev flow.\n+ * Initial size is set to 1024, it will be resized when it's not\n+ * big enough.\n+ */\n+struct flow_mark_map {\n+    size_t max;\n+    struct ovs_mutex mutex;\n+    struct id_pool *mark_pool;\n+    struct dp_netdev_flow **flows;\n+};\n+\n+static struct flow_mark_map flow_mark_map = {\n+    .max = 1024,\n+    .mutex = OVS_MUTEX_INITIALIZER,\n+};\n+\n+static bool\n+dp_netdev_alloc_flow_mark(uint32_t *mark)\n+{\n+    bool succeed = true;\n+\n+    ovs_mutex_lock(&flow_mark_map.mutex);\n+\n+    /* Haven't initiated yet, do it here */\n+    if (!flow_mark_map.flows) {\n+        flow_mark_map.flows = xzalloc(sizeof(struct dp_netdev_flow *) *\n+                                      flow_mark_map.max);\n+        flow_mark_map.mark_pool = id_pool_create(0, UINT32_MAX / 2);\n+    }\n+\n+    do {\n+        if (!id_pool_alloc_id(flow_mark_map.mark_pool, mark)) {\n+            succeed = false;\n+            break;\n+        }\n+\n+        if (*mark >= flow_mark_map.max) {\n+            flow_mark_map.flows = xrealloc(flow_mark_map.flows,\n+                                           flow_mark_map.max * 2 *\n+                                           sizeof(struct dp_netdev_flow *));\n+            memset(&flow_mark_map.flows[flow_mark_map.max], 0,\n+                   flow_mark_map.max * sizeof(struct dp_netdev_flow *));\n+            flow_mark_map.max *= 2;\n+\n+            break;\n+        }\n+    } while (flow_mark_map.flows[*mark]);\n+\n+    ovs_mutex_unlock(&flow_mark_map.mutex);\n+\n+    return succeed;\n+}\n+\n+static void\n+dp_netdev_install_flow_mark_map(const uint32_t mark,\n+                                struct dp_netdev_flow *netdev_flow)\n+{\n+    ovs_mutex_lock(&flow_mark_map.mutex);\n+    if (mark < flow_mark_map.max) {\n+        flow_mark_map.flows[mark] = netdev_flow;\n+    }\n+    ovs_mutex_unlock(&flow_mark_map.mutex);\n+}\n+\n+static void\n+dp_netdev_remove_flow_mark_map(const uint32_t mark)\n+{\n+    ovs_mutex_lock(&flow_mark_map.mutex);\n+    id_pool_free_id(flow_mark_map.mark_pool, mark);\n+    if (mark < flow_mark_map.max) {\n+        flow_mark_map.flows[mark] = NULL;\n+    }\n+    ovs_mutex_unlock(&flow_mark_map.mutex);\n+}\n+\n static void\n dp_netdev_pmd_remove_flow(struct dp_netdev_pmd_thread *pmd,\n                           struct dp_netdev_flow *flow)\n@@ -1846,6 +1925,10 @@ dp_netdev_pmd_remove_flow(struct dp_netdev_pmd_thread *pmd,\n     ovs_assert(cls != NULL);\n     dpcls_remove(cls, &flow->cr);\n     cmap_remove(&pmd->flow_table, node, dp_netdev_flow_hash(&flow->ufid));\n+    if (flow->has_mark) {\n+        dp_netdev_remove_flow_mark_map(flow->mark);\n+        flow->has_mark = false;\n+    }\n     flow->dead = true;\n \n     dp_netdev_flow_unref(flow);\n@@ -2425,6 +2508,55 @@ out:\n     return error;\n }\n \n+static void\n+try_netdev_flow_put(struct dp_netdev_pmd_thread *pmd, odp_port_t in_port,\n+                    struct dp_netdev_flow *flow, struct match *match,\n+                    const ovs_u128 *ufid, const struct nlattr *actions,\n+                    size_t actions_len)\n+{\n+    struct offload_info info;\n+    struct dp_netdev_port *port;\n+    bool modification = flow->has_mark;\n+    const char *op = modification ? \"modify\" : \"install\";\n+    int ret;\n+\n+    port = dp_netdev_lookup_port(pmd->dp, in_port);\n+    if (!port) {\n+        return;\n+    }\n+\n+    if (modification) {\n+        info.flow_mark = flow->mark;\n+    } else {\n+        if (!netdev_is_flow_api_enabled()) {\n+            return;\n+        }\n+\n+        if (!dp_netdev_alloc_flow_mark(&info.flow_mark)) {\n+            VLOG_ERR(\"failed to allocate flow mark!\\n\");\n+            return;\n+        }\n+    }\n+\n+    ret = netdev_flow_put(port->netdev, match,\n+                          CONST_CAST(struct nlattr *, actions),\n+                          actions_len, ufid, &info, NULL);\n+    if (ret) {\n+        VLOG_ERR(\"failed to %s netdev flow with mark %u\\n\",\n+                 op, info.flow_mark);\n+        return;\n+    }\n+\n+    if (!modification) {\n+        flow->has_mark = true;\n+        flow->mark = info.flow_mark;\n+        dp_netdev_install_flow_mark_map(info.flow_mark, flow);\n+    }\n+\n+    VLOG_INFO(\"succeed to %s netdev flow with mark %u\\n\",\n+              op, flow->mark);\n+}\n+\n static struct dp_netdev_flow *\n dp_netdev_flow_add(struct dp_netdev_pmd_thread *pmd,\n                    struct match *match, const ovs_u128 *ufid,\n@@ -2460,6 +2592,7 @@ dp_netdev_flow_add(struct dp_netdev_pmd_thread *pmd,\n     memset(&flow->stats, 0, sizeof flow->stats);\n     flow->dead = false;\n     flow->batch = NULL;\n+    flow->has_mark = false;\n     *CONST_CAST(unsigned *, &flow->pmd_id) = pmd->core_id;\n     *CONST_CAST(struct flow *, &flow->flow) = match->flow;\n     *CONST_CAST(ovs_u128 *, &flow->ufid) = *ufid;\n@@ -2475,6 +2608,9 @@ dp_netdev_flow_add(struct dp_netdev_pmd_thread *pmd,\n     cmap_insert(&pmd->flow_table, CONST_CAST(struct cmap_node *, &flow->node),\n                 dp_netdev_flow_hash(&flow->ufid));\n \n+    try_netdev_flow_put(pmd, in_port, flow, match, ufid,\n+                        actions, actions_len);\n+\n     if (OVS_UNLIKELY(!VLOG_DROP_DBG((&upcall_rl)))) {\n         struct ds ds = DS_EMPTY_INITIALIZER;\n         struct ofpbuf key_buf, mask_buf;\n@@ -2555,6 +2691,7 @@ flow_put_on_pmd(struct dp_netdev_pmd_thread *pmd,\n         if (put->flags & DPIF_FP_MODIFY) {\n             struct dp_netdev_actions *new_actions;\n             struct dp_netdev_actions *old_actions;\n+            odp_port_t in_port = netdev_flow->flow.in_port.odp_port;\n \n             new_actions = dp_netdev_actions_create(put->actions,\n                                                    put->actions_len);\n@@ -2562,6 +2699,9 @@ flow_put_on_pmd(struct dp_netdev_pmd_thread *pmd,\n             old_actions = dp_netdev_flow_get_actions(netdev_flow);\n             ovsrcu_set(&netdev_flow->actions, new_actions);\n \n+            try_netdev_flow_put(pmd, in_port, netdev_flow, match, ufid,\n+                                put->actions, put->actions_len);\n+\n             if (stats) {\n                 get_dpif_flow_stats(netdev_flow, stats);\n             }\ndiff --git a/lib/netdev.h b/lib/netdev.h\nindex f8482f7..2003165 100644\n--- a/lib/netdev.h\n+++ b/lib/netdev.h\n@@ -188,6 +188,12 @@ void netdev_send_wait(struct netdev *, int qid);\n struct offload_info {\n     const struct dpif_class *dpif_class;\n     ovs_be16 tp_dst_port; /* Destination port for tunnel in SET action */\n+\n+    /*\n+     * The flow mark id assigened to the flow. If any pkts hit the flow,\n+     * it will be in the pkt meta data.\n+     */\n+    uint32_t flow_mark;\n };\n struct dpif_class;\n struct netdev_flow_dump;\n",
    "prefixes": [
        "ovs-dev",
        "v3",
        "1/9"
    ]
}