get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 814768,
    "url": "http://patchwork.ozlabs.org/api/1.2/patches/814768/?format=api",
    "web_url": "http://patchwork.ozlabs.org/project/openvswitch/patch/1505708164-10270-5-git-send-email-roid@mellanox.com/",
    "project": {
        "id": 47,
        "url": "http://patchwork.ozlabs.org/api/1.2/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": "<1505708164-10270-5-git-send-email-roid@mellanox.com>",
    "list_archive_url": null,
    "date": "2017-09-18T04:16:04",
    "name": "[ovs-dev,V2,4/4] netdev-tc-offloads: Add support for action set",
    "commit_ref": null,
    "pull_url": null,
    "state": "changes-requested",
    "archived": false,
    "hash": "bac3dd33e44ec752ab37ebea8bd8f1536df34455",
    "submitter": {
        "id": 70307,
        "url": "http://patchwork.ozlabs.org/api/1.2/people/70307/?format=api",
        "name": "Roi Dayan",
        "email": "roid@mellanox.com"
    },
    "delegate": null,
    "mbox": "http://patchwork.ozlabs.org/project/openvswitch/patch/1505708164-10270-5-git-send-email-roid@mellanox.com/mbox/",
    "series": [
        {
            "id": 3557,
            "url": "http://patchwork.ozlabs.org/api/1.2/series/3557/?format=api",
            "web_url": "http://patchwork.ozlabs.org/project/openvswitch/list/?series=3557",
            "date": "2017-09-18T04:16:00",
            "name": "Add offload support for action set",
            "version": 2,
            "mbox": "http://patchwork.ozlabs.org/series/3557/mbox/"
        }
    ],
    "comments": "http://patchwork.ozlabs.org/api/patches/814768/comments/",
    "check": "pending",
    "checks": "http://patchwork.ozlabs.org/api/patches/814768/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>)",
        "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 3xwXmm3x6fz9s7G\n\tfor <incoming@patchwork.ozlabs.org>;\n\tMon, 18 Sep 2017 14:18:16 +1000 (AEST)",
            "from mail.linux-foundation.org (localhost [127.0.0.1])\n\tby mail.linuxfoundation.org (Postfix) with ESMTP id B19DAA73;\n\tMon, 18 Sep 2017 04:16:22 +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 73226941\n\tfor <dev@openvswitch.org>; Mon, 18 Sep 2017 04:16:18 +0000 (UTC)",
            "from mellanox.co.il (mail-il-dmz.mellanox.com [193.47.165.129])\n\tby smtp1.linuxfoundation.org (Postfix) with ESMTP id 4A50E157\n\tfor <dev@openvswitch.org>; Mon, 18 Sep 2017 04:16:17 +0000 (UTC)",
            "from Internal Mail-Server by MTLPINE1 (envelope-from\n\troid@mellanox.com)\n\twith ESMTPS (AES256-SHA encrypted); 18 Sep 2017 07:16:12 +0300",
            "from dev-r-vrt-189.mtr.labs.mlnx (dev-r-vrt-189.mtr.labs.mlnx\n\t[10.212.189.1])\n\tby labmailer.mlnx (8.13.8/8.13.8) with ESMTP id v8I4GBDU001186;\n\tMon, 18 Sep 2017 07:16:11 +0300"
        ],
        "X-Greylist": "domain auto-whitelisted by SQLgrey-1.7.6",
        "From": "Roi Dayan <roid@mellanox.com>",
        "To": "dev@openvswitch.org",
        "Date": "Mon, 18 Sep 2017 07:16:04 +0300",
        "Message-Id": "<1505708164-10270-5-git-send-email-roid@mellanox.com>",
        "X-Mailer": "git-send-email 2.7.5",
        "In-Reply-To": "<1505708164-10270-1-git-send-email-roid@mellanox.com>",
        "References": "<1505708164-10270-1-git-send-email-roid@mellanox.com>",
        "X-Spam-Status": "No, score=0.0 required=5.0 tests=RP_MATCHES_RCVD,\n\tUNPARSEABLE_RELAY 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 V2 4/4] netdev-tc-offloads: Add support for action\n\tset",
        "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": "From: Paul Blakey <paulb@mellanox.com>\n\nImplement support for offloading ovs action set using\ntc header rewrite action.\n\nSigned-off-by: Paul Blakey <paulb@mellanox.com>\nReviewed-by: Roi Dayan <roid@mellanox.com>\n---\n lib/netdev-tc-offloads.c | 201 +++++++++++++++++++++++++++++++++++++++++++++--\n 1 file changed, 195 insertions(+), 6 deletions(-)",
    "diff": "diff --git a/lib/netdev-tc-offloads.c b/lib/netdev-tc-offloads.c\nindex 3c145c2..4044a77 100644\n--- a/lib/netdev-tc-offloads.c\n+++ b/lib/netdev-tc-offloads.c\n@@ -27,11 +27,13 @@\n #include \"openvswitch/ofpbuf.h\"\n #include \"openvswitch/thread.h\"\n #include \"openvswitch/types.h\"\n+#include \"openvswitch/util.h\"\n #include \"openvswitch/vlog.h\"\n #include \"netdev-linux.h\"\n #include \"netlink.h\"\n #include \"netlink-socket.h\"\n #include \"odp-netlink.h\"\n+#include \"odp-util.h\"\n #include \"tc.h\"\n #include \"unaligned.h\"\n #include \"util.h\"\n@@ -41,6 +43,76 @@ VLOG_DEFINE_THIS_MODULE(netdev_tc_offloads);\n static struct vlog_rate_limit error_rl = VLOG_RATE_LIMIT_INIT(60, 5);\n \n static struct hmap ufid_tc = HMAP_INITIALIZER(&ufid_tc);\n+\n+struct netlink_field {\n+    int offset;\n+    int flower_offset;\n+    int size;\n+};\n+\n+static struct netlink_field set_flower_map[][3] = {\n+    [OVS_KEY_ATTR_IPV4] = {\n+        { offsetof(struct ovs_key_ipv4, ipv4_src),\n+          offsetof(struct tc_flower_key, ipv4.ipv4_src),\n+          MEMBER_SIZEOF(struct tc_flower_key, ipv4.ipv4_src)\n+        },\n+        { offsetof(struct ovs_key_ipv4, ipv4_dst),\n+          offsetof(struct tc_flower_key, ipv4.ipv4_dst),\n+          MEMBER_SIZEOF(struct tc_flower_key, ipv4.ipv4_dst)\n+        },\n+        { offsetof(struct ovs_key_ipv4, ipv4_ttl),\n+          offsetof(struct tc_flower_key, ipv4.rewrite_ttl),\n+          MEMBER_SIZEOF(struct tc_flower_key, ipv4.rewrite_ttl)\n+        },\n+    },\n+    [OVS_KEY_ATTR_IPV6] = {\n+        { offsetof(struct ovs_key_ipv6, ipv6_src),\n+          offsetof(struct tc_flower_key, ipv6.ipv6_src),\n+          MEMBER_SIZEOF(struct tc_flower_key, ipv6.ipv6_src)\n+        },\n+        { offsetof(struct ovs_key_ipv6, ipv6_dst),\n+          offsetof(struct tc_flower_key, ipv6.ipv6_dst),\n+          MEMBER_SIZEOF(struct tc_flower_key, ipv6.ipv6_dst)\n+        },\n+    },\n+    [OVS_KEY_ATTR_ETHERNET] = {\n+        { offsetof(struct ovs_key_ethernet, eth_src),\n+          offsetof(struct tc_flower_key, src_mac),\n+          MEMBER_SIZEOF(struct tc_flower_key, src_mac)\n+        },\n+        { offsetof(struct ovs_key_ethernet, eth_dst),\n+          offsetof(struct tc_flower_key, dst_mac),\n+          MEMBER_SIZEOF(struct tc_flower_key, dst_mac)\n+        },\n+    },\n+    [OVS_KEY_ATTR_ETHERTYPE] = {\n+        { 0,\n+          offsetof(struct tc_flower_key, eth_type),\n+          MEMBER_SIZEOF(struct tc_flower_key, eth_type)\n+        },\n+    },\n+    [OVS_KEY_ATTR_TCP] = {\n+        { offsetof(struct ovs_key_tcp, tcp_src),\n+          offsetof(struct tc_flower_key, tcp_src),\n+          MEMBER_SIZEOF(struct tc_flower_key, tcp_src)\n+        },\n+        { offsetof(struct ovs_key_tcp, tcp_dst),\n+          offsetof(struct tc_flower_key, tcp_dst),\n+          MEMBER_SIZEOF(struct tc_flower_key, tcp_dst)\n+        },\n+    },\n+    [OVS_KEY_ATTR_UDP] = {\n+        { offsetof(struct ovs_key_udp, udp_src),\n+          offsetof(struct tc_flower_key, udp_src),\n+          MEMBER_SIZEOF(struct tc_flower_key, udp_src)\n+        },\n+        { offsetof(struct ovs_key_udp, udp_dst),\n+          offsetof(struct tc_flower_key, udp_dst),\n+          MEMBER_SIZEOF(struct tc_flower_key, udp_dst)\n+        },\n+    },\n+};\n+\n static struct ovs_mutex ufid_lock = OVS_MUTEX_INITIALIZER;\n \n /**\n@@ -274,6 +346,48 @@ netdev_tc_flow_dump_destroy(struct netdev_flow_dump *dump)\n     return 0;\n }\n \n+static void\n+parse_flower_rewrite_to_netlink_action(struct ofpbuf *buf,\n+                                       struct tc_flower *flower)\n+{\n+    char *mask = (char *) &flower->rewrite.mask;\n+    char *data = (char *) &flower->rewrite.key;\n+\n+    for (int type = 0; type < ARRAY_SIZE(set_flower_map); type++) {\n+        char *put = NULL;\n+        size_t nested = 0;\n+        int len = ovs_flow_key_attr_lens[type].len;\n+\n+        if (len <= 0) {\n+            continue;\n+        }\n+\n+        for (int j = 0; j < ARRAY_SIZE(set_flower_map[type]); j++) {\n+            struct netlink_field *f = &set_flower_map[type][j];\n+\n+            if (!f->size) {\n+                break;\n+            }\n+\n+            if (!is_all_zeros(mask + f->flower_offset, f->size)) {\n+                if (!put) {\n+                    nested = nl_msg_start_nested(buf,\n+                                                 OVS_ACTION_ATTR_SET_MASKED);\n+                    put = nl_msg_put_unspec_zero(buf, type, len * 2);\n+                }\n+\n+                memcpy(put + f->offset, data + f->flower_offset, f->size);\n+                memcpy(put + len + f->offset,\n+                       mask + f->flower_offset, f->size);\n+            }\n+        }\n+\n+        if (put) {\n+            nl_msg_end_nested(buf, nested);\n+        }\n+    }\n+}\n+\n static int\n parse_tc_flower_to_match(struct tc_flower *flower,\n                          struct match *match,\n@@ -367,6 +481,10 @@ parse_tc_flower_to_match(struct tc_flower *flower,\n                                    | VLAN_CFI);\n         }\n \n+        if (flower->rewrite.rewrite) {\n+            parse_flower_rewrite_to_netlink_action(buf, flower);\n+        }\n+\n         if (flower->set.set) {\n             size_t set_offset = nl_msg_start_nested(buf, OVS_ACTION_ATTR_SET);\n             size_t tunnel_offset =\n@@ -457,14 +575,77 @@ netdev_tc_flow_dump_next(struct netdev_flow_dump *dump,\n }\n \n static int\n+parse_put_flow_set_masked_action(struct tc_flower *flower,\n+                                 const struct nlattr *set,\n+                                 size_t set_len,\n+                                 bool hasmask)\n+{\n+    static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 20);\n+    char *set_buff[set_len], *set_data, *set_mask;\n+    char *key = (char *) &flower->rewrite.key;\n+    char *mask = (char *) &flower->rewrite.mask;\n+    const struct nlattr *attr;\n+    int i, j, type;\n+    size_t size;\n+\n+    /* copy so we can set attr mask to 0 for used ovs key struct members  */\n+    memcpy(set_buff, set, set_len);\n+    attr = (struct nlattr *) set_buff;\n+\n+    type = nl_attr_type(attr);\n+    size = nl_attr_get_size(attr) / 2;\n+    set_data = CONST_CAST(char *, nl_attr_get(attr));\n+    set_mask = set_data + size;\n+\n+    if (type >= ARRAY_SIZE(set_flower_map)\n+        || !set_flower_map[type][0].size) {\n+        VLOG_DBG_RL(&rl, \"unsupported set action type: %d\", type);\n+        return EOPNOTSUPP;\n+    }\n+\n+    for (i = 0; i < ARRAY_SIZE(set_flower_map[type]); i++) {\n+        struct netlink_field *f = &set_flower_map[type][i];\n+\n+        if (!f->size) {\n+            break;\n+        }\n+\n+        /* copy masked value */\n+        for (j = 0; j < f->size; j++) {\n+            char maskval = hasmask ? set_mask[f->offset + j] : 0xFF;\n+\n+            key[f->flower_offset + j] = maskval & set_data[f->offset + j];\n+            mask[f->flower_offset + j] = maskval;\n+\n+        }\n+\n+        /* set its mask to 0 to show it's been used. */\n+        if (hasmask) {\n+            memset(set_mask + f->offset, 0, f->size);\n+        }\n+    }\n+\n+    if (!is_all_zeros(&flower->rewrite, sizeof flower->rewrite)) {\n+        flower->rewrite.rewrite = true;\n+    }\n+\n+    if (hasmask && !is_all_zeros(set_mask, size)) {\n+        VLOG_DBG_RL(&rl, \"unsupported sub attribute of set action type %d\",\n+                    type);\n+        return EOPNOTSUPP;\n+    }\n+\n+    return 0;\n+}\n+\n+static int\n parse_put_flow_set_action(struct tc_flower *flower, const struct nlattr *set,\n                           size_t set_len)\n {\n-    static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 20);\n     const struct nlattr *set_attr;\n     size_t set_left;\n \n-    NL_ATTR_FOR_EACH_UNSAFE(set_attr, set_left, set, set_len) {\n+    NL_ATTR_FOR_EACH_UNSAFE (set_attr, set_left, set, set_len) {\n         if (nl_attr_type(set_attr) == OVS_KEY_ATTR_TUNNEL) {\n             const struct nlattr *tunnel = nl_attr_get(set_attr);\n             const size_t tunnel_len = nl_attr_get_size(set_attr);\n@@ -472,7 +653,7 @@ parse_put_flow_set_action(struct tc_flower *flower, const struct nlattr *set,\n             size_t tun_left;\n \n             flower->set.set = true;\n-            NL_ATTR_FOR_EACH_UNSAFE(tun_attr, tun_left, tunnel, tunnel_len) {\n+            NL_ATTR_FOR_EACH_UNSAFE (tun_attr, tun_left, tunnel, tunnel_len) {\n                 switch (nl_attr_type(tun_attr)) {\n                 case OVS_TUNNEL_KEY_ATTR_ID: {\n                     flower->set.id = nl_attr_get_be64(tun_attr);\n@@ -507,9 +688,8 @@ parse_put_flow_set_action(struct tc_flower *flower, const struct nlattr *set,\n                 }\n             }\n         } else {\n-            VLOG_DBG_RL(&rl, \"unsupported set action type: %d\",\n-                        nl_attr_type(set_attr));\n-            return EOPNOTSUPP;\n+            return parse_put_flow_set_masked_action(flower, set, set_len,\n+                                                    false);\n         }\n     }\n     return 0;\n@@ -827,6 +1007,15 @@ netdev_tc_flow_put(struct netdev *netdev, struct match *match,\n             if (err) {\n                 return err;\n             }\n+        } else if (nl_attr_type(nla) == OVS_ACTION_ATTR_SET_MASKED) {\n+            const struct nlattr *set = nl_attr_get(nla);\n+            const size_t set_len = nl_attr_get_size(nla);\n+\n+            err = parse_put_flow_set_masked_action(&flower, set, set_len,\n+                                                   true);\n+            if (err) {\n+                return err;\n+            }\n         } else {\n             VLOG_DBG_RL(&rl, \"unsupported put action type: %d\",\n                         nl_attr_type(nla));\n",
    "prefixes": [
        "ovs-dev",
        "V2",
        "4/4"
    ]
}