get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 812132,
    "url": "http://patchwork.ozlabs.org/api/patches/812132/?format=api",
    "web_url": "http://patchwork.ozlabs.org/project/netfilter-devel/patch/1505046662-21629-1-git-send-email-mayhs11saini@gmail.com/",
    "project": {
        "id": 26,
        "url": "http://patchwork.ozlabs.org/api/projects/26/?format=api",
        "name": "Netfilter Development",
        "link_name": "netfilter-devel",
        "list_id": "netfilter-devel.vger.kernel.org",
        "list_email": "netfilter-devel@vger.kernel.org",
        "web_url": null,
        "scm_url": null,
        "webscm_url": null,
        "list_archive_url": "",
        "list_archive_url_format": "",
        "commit_url_format": ""
    },
    "msgid": "<1505046662-21629-1-git-send-email-mayhs11saini@gmail.com>",
    "list_archive_url": null,
    "date": "2017-09-10T12:31:02",
    "name": "[RFC,nft,V2] src: Add import command for json",
    "commit_ref": null,
    "pull_url": null,
    "state": "changes-requested",
    "archived": false,
    "hash": "10609196b35fd583721ea8cf80ce5f0fc7888a37",
    "submitter": {
        "id": 69683,
        "url": "http://patchwork.ozlabs.org/api/people/69683/?format=api",
        "name": "Shyam Saini",
        "email": "mayhs11saini@gmail.com"
    },
    "delegate": {
        "id": 6139,
        "url": "http://patchwork.ozlabs.org/api/users/6139/?format=api",
        "username": "pablo",
        "first_name": "Pablo",
        "last_name": "Neira",
        "email": "pablo@netfilter.org"
    },
    "mbox": "http://patchwork.ozlabs.org/project/netfilter-devel/patch/1505046662-21629-1-git-send-email-mayhs11saini@gmail.com/mbox/",
    "series": [
        {
            "id": 2396,
            "url": "http://patchwork.ozlabs.org/api/series/2396/?format=api",
            "web_url": "http://patchwork.ozlabs.org/project/netfilter-devel/list/?series=2396",
            "date": "2017-09-10T12:31:02",
            "name": "[RFC,nft,V2] src: Add import command for json",
            "version": 2,
            "mbox": "http://patchwork.ozlabs.org/series/2396/mbox/"
        }
    ],
    "comments": "http://patchwork.ozlabs.org/api/patches/812132/comments/",
    "check": "pending",
    "checks": "http://patchwork.ozlabs.org/api/patches/812132/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<netfilter-devel-owner@vger.kernel.org>",
        "X-Original-To": "incoming@patchwork.ozlabs.org",
        "Delivered-To": "patchwork-incoming@bilbo.ozlabs.org",
        "Authentication-Results": [
            "ozlabs.org;\n\tspf=none (mailfrom) smtp.mailfrom=vger.kernel.org\n\t(client-ip=209.132.180.67; helo=vger.kernel.org;\n\tenvelope-from=netfilter-devel-owner@vger.kernel.org;\n\treceiver=<UNKNOWN>)",
            "ozlabs.org;\n\tdkim=fail reason=\"signature verification failed\" (2048-bit key;\n\tunprotected) header.d=gmail.com header.i=@gmail.com\n\theader.b=\"PXKYLl6O\"; dkim-atps=neutral"
        ],
        "Received": [
            "from vger.kernel.org (vger.kernel.org [209.132.180.67])\n\tby ozlabs.org (Postfix) with ESMTP id 3xqr5P2R2yz9s7c\n\tfor <incoming@patchwork.ozlabs.org>;\n\tSun, 10 Sep 2017 22:31:21 +1000 (AEST)",
            "(majordomo@vger.kernel.org) by vger.kernel.org via listexpand\n\tid S1751497AbdIJMbU (ORCPT <rfc822;incoming@patchwork.ozlabs.org>);\n\tSun, 10 Sep 2017 08:31:20 -0400",
            "from mail-pf0-f194.google.com ([209.85.192.194]:36001 \"EHLO\n\tmail-pf0-f194.google.com\" rhost-flags-OK-OK-OK-OK) by vger.kernel.org\n\twith ESMTP id S1751469AbdIJMbT (ORCPT\n\t<rfc822;netfilter-devel@vger.kernel.org>);\n\tSun, 10 Sep 2017 08:31:19 -0400",
            "by mail-pf0-f194.google.com with SMTP id f84so3739332pfj.3\n\tfor <netfilter-devel@vger.kernel.org>;\n\tSun, 10 Sep 2017 05:31:19 -0700 (PDT)",
            "from localhost.localdomain ([47.31.5.118])\n\tby smtp.gmail.com with ESMTPSA id\n\tl74sm13229351pfi.9.2017.09.10.05.31.15\n\t(version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128);\n\tSun, 10 Sep 2017 05:31:17 -0700 (PDT)"
        ],
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=gmail.com; s=20161025;\n\th=from:to:cc:subject:date:message-id;\n\tbh=KBw/EmV8z5EKbcTSOIEh/QkeBBbQJDRfBD7eXhQwbew=;\n\tb=PXKYLl6OwtXu4iBlHcrVFJpVQFtB/MmU+wTNGj49lnNE2HjzEa4DVROwO3DVKzc4el\n\tqn6dDfQv/PxjqyeixwWwSav09gZ4lkZ/hedzzWhYDZKzIl9vqbqs1b16Z9wTBt8ixhmm\n\tc9GaxIlyUBbwNbwbDr42lMKVp90FgfgSlKG2Urdb/COUEr4orOuos7y3dUbkWwXB+AK+\n\t3yGx+gkint/ZEjwyHXQgcImNv7gw5j/VDzdex0Q3JFOeLorKIanvBNg9Di0TPW7nr5UQ\n\tiEtWg7qik5xu2COPaQKnLlxAVRyHiSGV0u4UIOFGawrgOzRoytk7S94C14IpgSDXOFan\n\tcbXg==",
        "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;\n\tbh=KBw/EmV8z5EKbcTSOIEh/QkeBBbQJDRfBD7eXhQwbew=;\n\tb=WLBv/Qm97qtftuaIRq+xQS5ep5gPzhK+y64L/1syiyr2fwRaf9zyC5bLisqFYg35tz\n\tB60uex64RcSSZkvDY/+70CvZIdtMrJEc52aE0lPXp9rrQimb6GTAgHqfLDTfXkjTuRMf\n\toArLAa7P7dW+IGgzGHSIrOTggZa6KplZsktcpWDIY5p0MQUel5r4T313JSNNdgLC1WPC\n\t7ZxBpjMGPAJgfeA8uhgFXGuUI+cnZKJaB0LwJI9SQc9ZdiPfcqu4xyFuyQBZXMtp0clL\n\tw7SH9pBCZsoZQ4P1DiiTKtWwdngMihuYlEHdG6oiMtbvx+4J6mNaDdeuwDRik5jrmKkq\n\tdKNA==",
        "X-Gm-Message-State": "AHPjjUgXxLXKbJ/XwaQ1b07hdMVDfQmjMIGkDfVzkaxGopZvQoVLnuGy\n\t3GBTYicacTuS68YCDik=",
        "X-Google-Smtp-Source": "ADKCNb6bqvLe7IGHOY77HP7SDzKj/r/IkiMh9L6xa/m3eyyGjvTVHKcaU03LP231HrZMQ5J7m4iRuA==",
        "X-Received": "by 10.99.115.30 with SMTP id o30mr8619336pgc.449.1505046678184; \n\tSun, 10 Sep 2017 05:31:18 -0700 (PDT)",
        "From": "Shyam Saini <mayhs11saini@gmail.com>",
        "To": "netfilter-devel@vger.kernel.org",
        "Cc": "Shyam Saini <mayhs11saini@gmail.com>",
        "Subject": "[RFC PATCH nft V2] src: Add import command for json",
        "Date": "Sun, 10 Sep 2017 18:01:02 +0530",
        "Message-Id": "<1505046662-21629-1-git-send-email-mayhs11saini@gmail.com>",
        "X-Mailer": "git-send-email 1.9.1",
        "Sender": "netfilter-devel-owner@vger.kernel.org",
        "Precedence": "bulk",
        "List-ID": "<netfilter-devel.vger.kernel.org>",
        "X-Mailing-List": "netfilter-devel@vger.kernel.org"
    },
    "content": "This new operation allows to import ruleset in json to make\nincremental changes using the parse functions of libnftnl.\n\nA basic way to test this new functionality is:\n\n % cat file.json | nft import json\n\nwhere the file.json is a ruleset exported in json format.\n\nHighly based on work from  Alvaro Neira <alvaroneay@gmail.com>\nand Arturo Borrero <arturo@netfilter.org>.\n\nSigned-off-by: Shyam Saini <mayhs11saini@gmail.com>\n---\nV2:\n  Build Patch over updated repository.\n---\n include/netlink.h  |   9 ++\n include/rule.h     |  14 +--\n src/evaluate.c     |   2 +\n src/netlink.c      | 280 +++++++++++++++++++++++++++++++++++++++++++++++++++++\n src/parser_bison.y |  38 +++++---\n src/rule.c         |  44 +++++++--\n src/scanner.l      |   1 +\n 7 files changed, 361 insertions(+), 27 deletions(-)",
    "diff": "diff --git a/include/netlink.h b/include/netlink.h\nindex b395cf1cd9ad..30cf3cd997ef 100644\n--- a/include/netlink.h\n+++ b/include/netlink.h\n@@ -225,4 +225,13 @@ bool netlink_batch_supported(struct mnl_socket *nf_sock, uint32_t *seqnum);\n \n int netlink_echo_callback(const struct nlmsghdr *nlh, void *data);\n \n+struct ruleset_parse {\n+\tstruct netlink_ctx      *nl_ctx;\n+\tstruct cmd              *cmd;\n+};\n+\n+struct nftnl_parse_ctx;\n+\n+int netlink_markup_parse_cb(const struct nftnl_parse_ctx *ctx);\n+\n #endif /* NFTABLES_NETLINK_H */\ndiff --git a/include/rule.h b/include/rule.h\nindex 631a1bcdf84e..56dee9766b2b 100644\n--- a/include/rule.h\n+++ b/include/rule.h\n@@ -327,6 +327,7 @@ uint32_t obj_type_to_cmd(uint32_t type);\n  * @CMD_RESET:\t\treset container\n  * @CMD_FLUSH:\t\tflush container\n  * @CMD_RENAME:\t\trename object\n+ * @CMD_IMPORT:\t\timport a ruleset in a given format\n  * @CMD_EXPORT:\t\texport the ruleset in a given format\n  * @CMD_MONITOR:\tevent listener\n  * @CMD_DESCRIBE:\tdescribe an expression\n@@ -342,6 +343,7 @@ enum cmd_ops {\n \tCMD_RESET,\n \tCMD_FLUSH,\n \tCMD_RENAME,\n+\tCMD_IMPORT,\n \tCMD_EXPORT,\n \tCMD_MONITOR,\n \tCMD_DESCRIBE,\n@@ -361,7 +363,7 @@ enum cmd_ops {\n  * @CMD_OBJ_RULESET:\truleset\n  * @CMD_OBJ_EXPR:\texpression\n  * @CMD_OBJ_MONITOR:\tmonitor\n- * @CMD_OBJ_EXPORT:\texport\n+ * @CMD_OBJ_MARKUP:\timport/export\n  * @CMD_OBJ_COUNTER:\tcounter\n  * @CMD_OBJ_COUNTERS:\tmultiple counters\n  * @CMD_OBJ_QUOTA:\tquota\n@@ -381,7 +383,7 @@ enum cmd_obj {\n \tCMD_OBJ_RULESET,\n \tCMD_OBJ_EXPR,\n \tCMD_OBJ_MONITOR,\n-\tCMD_OBJ_EXPORT,\n+\tCMD_OBJ_MARKUP,\n \tCMD_OBJ_FLOWTABLE,\n \tCMD_OBJ_FLOWTABLES,\n \tCMD_OBJ_MAP,\n@@ -396,12 +398,12 @@ enum cmd_obj {\n \tCMD_OBJ_LIMITS,\n };\n \n-struct export {\n+struct markup {\n \tuint32_t\tformat;\n };\n \n-struct export *export_alloc(uint32_t format);\n-void export_free(struct export *e);\n+struct markup *markup_alloc(uint32_t format);\n+void markup_free(struct markup *m);\n \n enum {\n \tCMD_MONITOR_OBJ_ANY,\n@@ -454,7 +456,7 @@ struct cmd {\n \t\tstruct chain\t*chain;\n \t\tstruct table\t*table;\n \t\tstruct monitor\t*monitor;\n-\t\tstruct export\t*export;\n+\t\tstruct markup\t*markup;\n \t\tstruct obj\t*object;\n \t};\n \tconst void\t\t*arg;\ndiff --git a/src/evaluate.c b/src/evaluate.c\nindex e767542a868e..2275a3026255 100644\n--- a/src/evaluate.c\n+++ b/src/evaluate.c\n@@ -3407,6 +3407,8 @@ int cmd_evaluate(struct eval_ctx *ctx, struct cmd *cmd)\n \t\treturn 0;\n \tcase CMD_MONITOR:\n \t\treturn cmd_evaluate_monitor(ctx, cmd);\n+\tcase CMD_IMPORT:\n+\t\treturn 0;\n \tdefault:\n \t\tBUG(\"invalid command operation %u\\n\", cmd->op);\n \t};\ndiff --git a/src/netlink.c b/src/netlink.c\nindex 291bbdeeaa68..7a2519477ae8 100644\n--- a/src/netlink.c\n+++ b/src/netlink.c\n@@ -24,6 +24,7 @@\n #include <libnftnl/object.h>\n #include <libnftnl/set.h>\n #include <libnftnl/udata.h>\n+#include <libnftnl/ruleset.h>\n #include <libnftnl/common.h>\n #include <linux/netfilter/nfnetlink.h>\n #include <linux/netfilter/nf_tables.h>\n@@ -3030,6 +3031,285 @@ int netlink_monitor(struct netlink_mon_handler *monhandler,\n \treturn mnl_nft_event_listener(&ctx, netlink_events_cb, monhandler);\n }\n \n+static int netlink_markup_setelems(const struct nftnl_parse_ctx *ctx)\n+{\n+\tconst struct ruleset_parse *rp;\n+\tstruct nftnl_set *set;\n+\tuint32_t cmd;\n+\tint ret = -1;\n+\n+\tset = nftnl_ruleset_ctx_get(ctx, NFTNL_RULESET_CTX_SET);\n+\trp = nftnl_ruleset_ctx_get(ctx, NFTNL_RULESET_CTX_DATA);\n+\n+\tcmd = nftnl_ruleset_ctx_get_u32(ctx, NFTNL_RULESET_CTX_CMD);\n+\tswitch (cmd) {\n+\tcase NFTNL_CMD_ADD:\n+\t\tret = mnl_nft_setelem_batch_add(set, rp->nl_ctx->batch, 0, rp->nl_ctx->seqnum);\n+\t\tbreak;\n+\tcase NFTNL_CMD_DELETE:\n+\t\tret = mnl_nft_setelem_batch_del(set, rp->nl_ctx->batch, 0, rp->nl_ctx->seqnum);\n+\t\tbreak;\n+\tdefault:\n+\t\terrno = EOPNOTSUPP;\n+\t\tbreak;\n+\t}\n+\n+\treturn ret;\n+}\n+\n+static int netlink_markup_set(const struct nftnl_parse_ctx *ctx)\n+{\n+\tconst struct ruleset_parse *rp;\n+\tstruct nftnl_set *set;\n+\tuint32_t cmd;\n+\tint ret = -1;\n+\n+\tset = nftnl_ruleset_ctx_get(ctx, NFTNL_RULESET_CTX_SET);\n+\trp = nftnl_ruleset_ctx_get(ctx, NFTNL_RULESET_CTX_DATA);\n+\n+\tcmd = nftnl_ruleset_ctx_get_u32(ctx, NFTNL_RULESET_CTX_CMD);\n+\tswitch (cmd) {\n+\tcase NFTNL_CMD_ADD:\n+\t\tret = mnl_nft_set_batch_add(set, rp->nl_ctx->batch, NLM_F_EXCL,\n+\t\t\t\t\t\trp->nl_ctx->seqnum);\n+\t\tbreak;\n+\tcase NFTNL_CMD_DELETE:\n+\t\tret = mnl_nft_set_batch_del(set, rp->nl_ctx->batch, 0, rp->nl_ctx->seqnum);\n+\t\tbreak;\n+\tdefault:\n+\t\terrno = EOPNOTSUPP;\n+\t\tbreak;\n+\t}\n+\n+\tif (ret < 0)\n+\t\treturn ret;\n+\n+\treturn netlink_markup_setelems(ctx);\n+}\n+\n+static int netlink_markup_build_rule(const struct nftnl_parse_ctx *ctx,\n+\t\t\t\t\t\t\tuint32_t cmd, struct nftnl_rule *rule)\n+{\n+\tconst struct ruleset_parse *rp;\n+\tuint32_t nl_flags;\n+\tint ret = -1;\n+\n+\trp = nftnl_ruleset_ctx_get(ctx, NFTNL_RULESET_CTX_DATA);\n+\n+\tswitch (cmd) {\n+\tcase NFTNL_CMD_ADD:\n+\t\tnl_flags = NLM_F_APPEND | NLM_F_CREATE;\n+\t\tnftnl_rule_unset(rule, NFTNL_RULE_HANDLE);\n+\t\tret = mnl_nft_rule_batch_add(rule, rp->nl_ctx->batch, nl_flags,\n+\t\t\t\t\t\trp->nl_ctx->seqnum);\n+\t\tbreak;\n+\tcase NFTNL_CMD_DELETE:\n+\t\tret = mnl_nft_rule_batch_del(rule, rp->nl_ctx->batch, 0, rp->nl_ctx->seqnum);\n+\t\tbreak;\n+\tcase NFTNL_CMD_REPLACE:\n+\t\tnl_flags = NLM_F_REPLACE;\n+\t\tret = mnl_nft_rule_batch_add(rule, rp->nl_ctx->batch, nl_flags,\n+\t\t\t\t\t\trp->nl_ctx->seqnum);\n+\t\tbreak;\n+\tcase NFTNL_CMD_INSERT:\n+\t\tnl_flags = NLM_F_CREATE;\n+\t\tnftnl_rule_unset(rule, NFTNL_RULE_HANDLE);\n+\t\tret = mnl_nft_rule_batch_add(rule, rp->nl_ctx->batch, nl_flags,\n+\t\t\t\t\t\trp->nl_ctx->seqnum);\n+\t\tbreak;\n+\tdefault:\n+\t\terrno = EOPNOTSUPP;\n+\t\tbreak;\n+\t}\n+\n+\treturn ret;\n+\n+}\n+\n+static int netlink_markup_rule(const struct nftnl_parse_ctx *ctx)\n+{\n+\tstruct nftnl_rule *rule;\n+\tuint32_t cmd;\n+\n+\tcmd = nftnl_ruleset_ctx_get_u32(ctx, NFTNL_RULESET_CTX_CMD);\n+\trule = nftnl_ruleset_ctx_get(ctx, NFTNL_RULESET_CTX_RULE);\n+\n+\treturn netlink_markup_build_rule(ctx, cmd, rule);\n+}\n+\n+static int netlink_markup_build_flush(const struct nftnl_parse_ctx *ctx)\n+{\n+\tstruct nftnl_rule *rule;\n+\tstruct nftnl_table *table;\n+\tstruct nftnl_chain *chain;\n+\tuint32_t type;\n+\tint ret = -1;\n+\n+\trule = nftnl_rule_alloc();\n+\tif (rule == NULL)\n+\t\treturn -1;\n+\n+\ttype = nftnl_ruleset_ctx_get_u32(ctx, NFTNL_RULESET_CTX_TYPE);\n+\tswitch (type) {\n+\tcase NFTNL_RULESET_TABLE:\n+\t\ttable = nftnl_ruleset_ctx_get(ctx, NFTNL_RULESET_CTX_TABLE);\n+\n+\t\tnftnl_rule_set(rule, NFTNL_RULE_TABLE,\n+\t\t\t\t\tnftnl_table_get(table,\n+\t\t\t\t\t\t\tNFTNL_TABLE_NAME));\n+\t\tnftnl_rule_set(rule, NFTNL_RULE_FAMILY,\n+\t\t\t\t\tnftnl_table_get(table,\n+\t\t\t\t\t\t\tNFTNL_TABLE_FAMILY));\n+\t\tbreak;\n+\tcase NFTNL_RULESET_CHAIN:\n+\t\tchain = nftnl_ruleset_ctx_get(ctx, NFTNL_RULESET_CTX_CHAIN);\n+\n+\t\tnftnl_rule_set(rule, NFTNL_RULE_TABLE,\n+\t\t\t\t\tnftnl_chain_get(chain,\n+\t\t\t\t\t\t\tNFTNL_CHAIN_TABLE));\n+\t\tnftnl_rule_set(rule, NFTNL_RULE_CHAIN,\n+\t\t\t\t\tnftnl_chain_get(chain,\n+\t\t\t\t\t\t\tNFTNL_CHAIN_NAME));\n+\t\tnftnl_rule_set(rule, NFTNL_RULE_FAMILY,\n+\t\t\t\t\tnftnl_chain_get(chain,\n+\t\t\t\t\t\t\tNFTNL_TABLE_FAMILY));\n+\t\tbreak;\n+\tdefault:\n+\t\terrno = EOPNOTSUPP;\n+\t\tgoto err;\n+\t}\n+\n+\tret = netlink_markup_build_rule(ctx, NFTNL_CMD_DELETE, rule);\n+err:\n+\tnftnl_rule_free(rule);\n+\treturn ret;\n+}\n+\n+static int netlink_markup_chain(const struct nftnl_parse_ctx *ctx)\n+{\n+\tconst struct ruleset_parse *rp;\n+\tstruct nftnl_chain *chain;\n+\tuint32_t cmd;\n+\tint ret = -1;\n+\n+\tchain = nftnl_ruleset_ctx_get(ctx, NFTNL_RULESET_CTX_CHAIN);\n+\trp = nftnl_ruleset_ctx_get(ctx, NFTNL_RULESET_CTX_DATA);\n+\n+\tnftnl_chain_unset(chain, NFTNL_CHAIN_HANDLE);\n+\n+\tcmd = nftnl_ruleset_ctx_get_u32(ctx, NFTNL_RULESET_CTX_CMD);\n+\tswitch (cmd) {\n+\tcase NFTNL_CMD_ADD:\n+\t\tret = mnl_nft_chain_batch_add(chain, rp->nl_ctx->batch, 0, rp->nl_ctx->seqnum);\n+\t\tbreak;\n+\tcase NFTNL_CMD_DELETE:\n+\t\tret = mnl_nft_chain_batch_del(chain, rp->nl_ctx->batch, 0, rp->nl_ctx->seqnum);\n+\t\tbreak;\n+\tcase NFTNL_CMD_FLUSH:\n+\t\tret = netlink_markup_build_flush(ctx);\n+\t\tbreak;\n+\tdefault:\n+\t\terrno = EOPNOTSUPP;\n+\t\tbreak;\n+\t}\n+\n+\treturn ret;\n+}\n+\n+\n+static int netlink_markup_build_table(const struct nftnl_parse_ctx *ctx,\n+\t\tuint32_t cmd, struct nftnl_table *table)\n+{\n+\tstruct ruleset_parse *rp;\n+\tint ret = -1;\n+\n+\trp = nftnl_ruleset_ctx_get(ctx, NFTNL_RULESET_CTX_DATA);\n+\n+\tswitch (cmd) {\n+\tcase NFTNL_CMD_ADD:\n+\t\tret = mnl_nft_table_batch_add(table, rp->nl_ctx->batch, 0, rp->nl_ctx->seqnum);\n+\t\tbreak;\n+\tcase NFTNL_CMD_DELETE:\n+\t\tret = mnl_nft_table_batch_del(table, rp->nl_ctx->batch, 0, rp->nl_ctx->seqnum);\n+\t\tbreak;\n+\tcase NFTNL_CMD_FLUSH:\n+\t\tret = netlink_markup_build_flush(ctx);\n+\t\tbreak;\n+\tdefault:\n+\t\terrno = EOPNOTSUPP;\n+\t\tbreak;\n+\t}\n+\n+\treturn ret;\n+}\n+\n+static int netlink_markup_table(const struct nftnl_parse_ctx *ctx)\n+{\n+\tstruct nftnl_table *table;\n+\tuint32_t cmd;\n+\n+\tcmd = nftnl_ruleset_ctx_get_u32(ctx, NFTNL_RULESET_CTX_CMD);\n+\ttable = nftnl_ruleset_ctx_get(ctx, NFTNL_RULESET_CTX_TABLE);\n+\n+\treturn netlink_markup_build_table(ctx, cmd, table);\n+}\n+\n+static int netlink_markup_flush(const struct nftnl_parse_ctx *ctx)\n+{\n+\tstruct nftnl_table *table;\n+\tint ret;\n+\n+\ttable = nftnl_table_alloc();\n+\tif (table == NULL)\n+\t\treturn -1;\n+\n+\tret = netlink_markup_build_table(ctx, NFTNL_CMD_DELETE, table);\n+\tnftnl_table_free(table);\n+\n+\treturn ret;\n+}\n+\n+int netlink_markup_parse_cb(const struct nftnl_parse_ctx *ctx)\n+{\n+\tstruct ruleset_parse *rp;\n+\tuint32_t type;\n+\tint ret = -1;\n+\n+\trp = nftnl_ruleset_ctx_get(ctx, NFTNL_RULESET_CTX_DATA);\n+\n+\ttype = nftnl_ruleset_ctx_get_u32(ctx, NFTNL_RULESET_CTX_TYPE);\n+\tswitch (type) {\n+\tcase NFTNL_RULESET_TABLE:\n+\t\tret = netlink_markup_table(ctx);\n+\t\tbreak;\n+\tcase NFTNL_RULESET_CHAIN:\n+\t\tret = netlink_markup_chain(ctx);\n+\t\tbreak;\n+\tcase NFTNL_RULESET_RULE:\n+\t\tret = netlink_markup_rule(ctx);\n+\t\tbreak;\n+\tcase NFTNL_RULESET_SET:\n+\t\tret = netlink_markup_set(ctx);\n+\t\tbreak;\n+\tcase NFTNL_RULESET_SET_ELEMS:\n+\t\tret = netlink_markup_setelems(ctx);\n+\t\tbreak;\n+\tcase NFTNL_RULESET_RULESET:\n+\t\tret = netlink_markup_flush(ctx);\n+\t\tbreak;\n+\tdefault:\n+\t\terrno = EOPNOTSUPP;\n+\t\tbreak;\n+\t}\n+\n+\tnftnl_ruleset_ctx_free(ctx);\n+\tif (ret < 0)\n+\t\tnetlink_io_error(rp->nl_ctx, &rp->cmd->location,\n+\t\t\t\t\"Could not import: %s\", strerror(errno));\n+\n+\treturn 0;\n+}\n+\n bool netlink_batch_supported(struct mnl_socket *nf_sock, uint32_t *seqnum)\n {\n \treturn mnl_batch_supported(nf_sock, seqnum);\ndiff --git a/src/parser_bison.y b/src/parser_bison.y\nindex 31a7e8be2bcd..e17653e4e28f 100644\n--- a/src/parser_bison.y\n+++ b/src/parser_bison.y\n@@ -213,6 +213,7 @@ static void location_update(struct location *loc, struct location *rhs, int n)\n %token FLUSH\t\t\t\"flush\"\n %token RENAME\t\t\t\"rename\"\n %token DESCRIBE\t\t\t\"describe\"\n+%token IMPORT\t\t\t\"import\"\n %token EXPORT\t\t\t\"export\"\n %token MONITOR\t\t\t\"monitor\"\n \n@@ -475,8 +476,8 @@ static void location_update(struct location *loc, struct location *rhs, int n)\n %type <cmd>\t\t\tline\n %destructor { cmd_free($$); }\tline\n \n-%type <cmd>\t\t\tbase_cmd add_cmd replace_cmd create_cmd insert_cmd delete_cmd list_cmd reset_cmd flush_cmd rename_cmd export_cmd monitor_cmd describe_cmd\n-%destructor { cmd_free($$); }\tbase_cmd add_cmd replace_cmd create_cmd insert_cmd delete_cmd list_cmd reset_cmd flush_cmd rename_cmd export_cmd monitor_cmd describe_cmd\n+%type <cmd>\t\t\tbase_cmd add_cmd replace_cmd create_cmd insert_cmd delete_cmd list_cmd reset_cmd flush_cmd rename_cmd export_cmd monitor_cmd describe_cmd import_cmd\n+%destructor { cmd_free($$); }\tbase_cmd add_cmd replace_cmd create_cmd insert_cmd delete_cmd list_cmd reset_cmd flush_cmd rename_cmd export_cmd monitor_cmd describe_cmd import_cmd\n \n %type <handle>\t\t\ttable_spec chain_spec chain_identifier ruleid_spec handle_spec position_spec rule_position ruleset_spec\n %destructor { handle_free(&$$); } table_spec chain_spec chain_identifier ruleid_spec handle_spec position_spec rule_position ruleset_spec\n@@ -655,7 +656,7 @@ static void location_update(struct location *loc, struct location *rhs, int n)\n %destructor { expr_free($$); }\tfib_expr\n %type <val>\t\t\tfib_tuple\tfib_result\tfib_flag\n \n-%type <val>\t\t\texport_format\n+%type <val>\t\t\tmarkup_format\n %type <string>\t\t\tmonitor_event\n %destructor { xfree($$); }\tmonitor_event\n %type <val>\t\t\tmonitor_object\tmonitor_format\n@@ -788,6 +789,7 @@ base_cmd\t\t:\t/* empty */\tadd_cmd\t\t{ $$ = $1; }\n \t\t\t|\tRESET\t\treset_cmd\t{ $$ = $2; }\n \t\t\t|\tFLUSH\t\tflush_cmd\t{ $$ = $2; }\n \t\t\t|\tRENAME\t\trename_cmd\t{ $$ = $2; }\n+\t\t\t|       IMPORT          import_cmd      { $$ = $2; }\n \t\t\t|\tEXPORT\t\texport_cmd\t{ $$ = $2; }\n \t\t\t|\tMONITOR\t\tmonitor_cmd\t{ $$ = $2; }\n \t\t\t|\tDESCRIBE\tdescribe_cmd\t{ $$ = $2; }\n@@ -1196,17 +1198,31 @@ rename_cmd\t\t:\tCHAIN\t\tchain_spec\tidentifier\n \t\t\t}\n \t\t\t;\n \n-export_cmd\t\t:\tRULESET\t\texport_format\n+import_cmd\t\t\t:       RULESET         markup_format\n \t\t\t{\n \t\t\t\tstruct handle h = { .family = NFPROTO_UNSPEC };\n-\t\t\t\tstruct export *export = export_alloc($2);\n-\t\t\t\t$$ = cmd_alloc(CMD_EXPORT, CMD_OBJ_EXPORT, &h, &@$, export);\n+\t\t\t\tstruct markup *markup = markup_alloc($2);\n+\t\t\t\t$$ = cmd_alloc(CMD_IMPORT, CMD_OBJ_MARKUP, &h, &@$, markup);\n \t\t\t}\n-\t\t\t|\texport_format\n+\t\t\t|\tmarkup_format\n \t\t\t{\n \t\t\t\tstruct handle h = { .family = NFPROTO_UNSPEC };\n-\t\t\t\tstruct export *export = export_alloc($1);\n-\t\t\t\t$$ = cmd_alloc(CMD_EXPORT, CMD_OBJ_EXPORT, &h, &@$, export);\n+\t\t\t\tstruct markup *markup = markup_alloc($1);\n+\t\t\t\t$$ = cmd_alloc(CMD_IMPORT, CMD_OBJ_MARKUP, &h, &@$, markup);\n+\t\t\t}\n+\t\t\t;\n+\n+export_cmd\t\t:\tRULESET\t\tmarkup_format\n+\t\t\t{\n+\t\t\t\tstruct handle h = { .family = NFPROTO_UNSPEC };\n+\t\t\t\tstruct markup *markup = markup_alloc($2);\n+\t\t\t\t$$ = cmd_alloc(CMD_EXPORT, CMD_OBJ_MARKUP, &h, &@$, markup);\n+\t\t\t}\n+\t\t\t|\tmarkup_format\n+\t\t\t{\n+\t\t\t\tstruct handle h = { .family = NFPROTO_UNSPEC };\n+\t\t\t\tstruct markup *markup = markup_alloc($1);\n+\t\t\t\t$$ = cmd_alloc(CMD_EXPORT, CMD_OBJ_MARKUP, &h, &@$, markup);\n \t\t\t}\n \t\t\t;\n \n@@ -1234,10 +1250,10 @@ monitor_object\t\t:\t/* empty */\t{ $$ = CMD_MONITOR_OBJ_ANY; }\n \t\t\t;\n \n monitor_format\t\t:\t/* empty */\t{ $$ = NFTNL_OUTPUT_DEFAULT; }\n-\t\t\t|\texport_format\n+\t\t\t|\tmarkup_format\n \t\t\t;\n \n-export_format\t\t: \tXML \t\t{ $$ = NFTNL_OUTPUT_XML; }\n+markup_format\t\t: \tXML \t\t{ $$ = NFTNL_OUTPUT_XML; }\n \t\t\t|\tJSON\t\t{ $$ = NFTNL_OUTPUT_JSON; }\n \t\t\t;\n \ndiff --git a/src/rule.c b/src/rule.c\nindex 1bb7b4756171..932a85dfeacf 100644\n--- a/src/rule.c\n+++ b/src/rule.c\n@@ -896,19 +896,19 @@ void nft_cmd_expand(struct cmd *cmd)\n \t}\n }\n \n-struct export *export_alloc(uint32_t format)\n+struct markup *markup_alloc(uint32_t format)\n {\n-\tstruct export *export;\n+\tstruct markup *markup;\n \n-\texport = xmalloc(sizeof(struct export));\n-\texport->format = format;\n+\tmarkup = xmalloc(sizeof(struct markup));\n+\tmarkup->format = format;\n \n-\treturn export;\n+\treturn markup;\n }\n \n-void export_free(struct export *e)\n+void markup_free(struct markup *m)\n {\n-\txfree(e);\n+\txfree(m);\n }\n \n struct monitor *monitor_alloc(uint32_t format, uint32_t type, const char *event)\n@@ -956,8 +956,8 @@ void cmd_free(struct cmd *cmd)\n \t\tcase CMD_OBJ_MONITOR:\n \t\t\tmonitor_free(cmd->monitor);\n \t\t\tbreak;\n-\t\tcase CMD_OBJ_EXPORT:\n-\t\t\texport_free(cmd->export);\n+\t\tcase CMD_OBJ_MARKUP:\n+\t\t\tmarkup_free(cmd->markup);\n \t\t\tbreak;\n \t\tcase CMD_OBJ_COUNTER:\n \t\tcase CMD_OBJ_QUOTA:\n@@ -1156,13 +1156,35 @@ static int do_command_export(struct netlink_ctx *ctx, struct cmd *cmd)\n \t\t\treturn -1;\n \t} while (rs == NULL);\n \n-\tnftnl_ruleset_fprintf(stdout, rs, cmd->export->format, 0);\n+\tnftnl_ruleset_fprintf(stdout, rs, cmd->markup->format, NFTNL_OF_EVENT_NEW);\n \tfprintf(stdout, \"\\n\");\n \n \tnftnl_ruleset_free(rs);\n \treturn 0;\n }\n \n+static int do_command_import(struct netlink_ctx *ctx, struct cmd *cmd)\n+{\n+\tint ret;\n+\tstruct nftnl_parse_err *err;\n+\tstruct ruleset_parse rp = {\n+\t\t.nl_ctx = ctx,\n+\t\t.cmd    = cmd\n+\t};\n+\n+\terr = nftnl_parse_err_alloc();\n+\tif (err == NULL)\n+\t\treturn -1;\n+\n+\tret = nftnl_ruleset_parse_file_cb(cmd->markup->format, stdin, err, &rp,\n+\t\t\t\t\t  netlink_markup_parse_cb);\n+\tif (ret < 0)\n+\t\tnftnl_parse_perror(\"unable to import: parsing failed\", err);\n+\n+\tnftnl_parse_err_free(err);\n+\treturn ret;\n+}\n+\n static int do_list_table(struct netlink_ctx *ctx, struct cmd *cmd,\n \t\t\t struct table *table)\n {\n@@ -1777,6 +1799,8 @@ int do_command(struct netlink_ctx *ctx, struct cmd *cmd)\n \t\treturn do_command_flush(ctx, cmd);\n \tcase CMD_RENAME:\n \t\treturn do_command_rename(ctx, cmd);\n+\tcase CMD_IMPORT:\n+\t\treturn do_command_import(ctx, cmd);\n \tcase CMD_EXPORT:\n \t\treturn do_command_export(ctx, cmd);\n \tcase CMD_MONITOR:\ndiff --git a/src/scanner.l b/src/scanner.l\nindex 0cfb6c50e418..f6d7e1e39d5b 100644\n--- a/src/scanner.l\n+++ b/src/scanner.l\n@@ -273,6 +273,7 @@ addrstring\t({macaddr}|{ip4addr}|{ip6addr})\n \"reset\"\t\t\t{ return RESET; }\n \"flush\"\t\t\t{ return FLUSH; }\n \"rename\"\t\t{ return RENAME; }\n+\"import\"                { return IMPORT; }\n \"export\"\t\t{ return EXPORT; }\n \"monitor\"\t\t{ return MONITOR; }\n \n",
    "prefixes": [
        "RFC",
        "nft",
        "V2"
    ]
}