get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 77057,
    "url": "http://patches.dpdk.org/api/patches/77057/?format=api",
    "web_url": "http://patches.dpdk.org/project/dpdk/patch/20200909140006.23788-3-hyonkim@cisco.com/",
    "project": {
        "id": 1,
        "url": "http://patches.dpdk.org/api/projects/1/?format=api",
        "name": "DPDK",
        "link_name": "dpdk",
        "list_id": "dev.dpdk.org",
        "list_email": "dev@dpdk.org",
        "web_url": "http://core.dpdk.org",
        "scm_url": "git://dpdk.org/dpdk",
        "webscm_url": "http://git.dpdk.org/dpdk",
        "list_archive_url": "https://inbox.dpdk.org/dev",
        "list_archive_url_format": "https://inbox.dpdk.org/dev/{}",
        "commit_url_format": ""
    },
    "msgid": "<20200909140006.23788-3-hyonkim@cisco.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/20200909140006.23788-3-hyonkim@cisco.com",
    "date": "2020-09-09T14:00:02",
    "name": "[2/6] net/enic: support egress PORT_ID action",
    "commit_ref": null,
    "pull_url": null,
    "state": "accepted",
    "archived": true,
    "hash": "b4481854602c234c068cb9608a0e512eda79fdaa",
    "submitter": {
        "id": 948,
        "url": "http://patches.dpdk.org/api/people/948/?format=api",
        "name": "Hyong Youb Kim (hyonkim)",
        "email": "hyonkim@cisco.com"
    },
    "delegate": {
        "id": 319,
        "url": "http://patches.dpdk.org/api/users/319/?format=api",
        "username": "fyigit",
        "first_name": "Ferruh",
        "last_name": "Yigit",
        "email": "ferruh.yigit@amd.com"
    },
    "mbox": "http://patches.dpdk.org/project/dpdk/patch/20200909140006.23788-3-hyonkim@cisco.com/mbox/",
    "series": [
        {
            "id": 12058,
            "url": "http://patches.dpdk.org/api/series/12058/?format=api",
            "web_url": "http://patches.dpdk.org/project/dpdk/list/?series=12058",
            "date": "2020-09-09T14:00:00",
            "name": "net/enic: minor updates to flow implementation",
            "version": 1,
            "mbox": "http://patches.dpdk.org/series/12058/mbox/"
        }
    ],
    "comments": "http://patches.dpdk.org/api/patches/77057/comments/",
    "check": "success",
    "checks": "http://patches.dpdk.org/api/patches/77057/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<dev-bounces@dpdk.org>",
        "X-Original-To": "patchwork@inbox.dpdk.org",
        "Delivered-To": "patchwork@inbox.dpdk.org",
        "Received": [
            "from dpdk.org (dpdk.org [92.243.14.124])\n\tby inbox.dpdk.org (Postfix) with ESMTP id 369B2A04B5;\n\tWed,  9 Sep 2020 16:00:57 +0200 (CEST)",
            "from [92.243.14.124] (localhost [127.0.0.1])\n\tby dpdk.org (Postfix) with ESMTP id AE4181C0D4;\n\tWed,  9 Sep 2020 16:00:51 +0200 (CEST)",
            "from alln-iport-5.cisco.com (alln-iport-5.cisco.com [173.37.142.92])\n by dpdk.org (Postfix) with ESMTP id 9C784255\n for <dev@dpdk.org>; Wed,  9 Sep 2020 16:00:49 +0200 (CEST)",
            "from rcdn-core-11.cisco.com ([173.37.93.147])\n by alln-iport-5.cisco.com with ESMTP/TLS/DHE-RSA-SEED-SHA;\n 09 Sep 2020 14:00:48 +0000",
            "from cisco.com (savbu-usnic-a.cisco.com [10.193.184.48])\n by rcdn-core-11.cisco.com (8.15.2/8.15.2) with ESMTP id 089E0lxP030171;\n Wed, 9 Sep 2020 14:00:48 GMT",
            "by cisco.com (Postfix, from userid 508933)\n id BB71420F2005; Wed,  9 Sep 2020 07:00:47 -0700 (PDT)"
        ],
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/simple;\n d=cisco.com; i=@cisco.com; l=8334; q=dns/txt; s=iport;\n t=1599660049; x=1600869649;\n h=from:to:cc:subject:date:message-id:in-reply-to:\n references:mime-version:content-transfer-encoding;\n bh=2jSc8sZc/E/Xk0GoPqX+WMIWuke6Z5rnz2N4GexGZ8M=;\n b=XOZS/UhYL3ZymJ+k47m12LASWvKLBbg1U/vQmALbzEwzwB4eVxiTCplV\n NjL1lhfFL9DBIBm2nga22Ib5d37ws27EwkrK5egnAWbsdxhZGN6z+xsIF\n Vf4Un91lTVjID0e32q+0vPnbA+zJs7B8oYj0Eo7EzyzXp/iXsgfJpmzz/ U=;",
        "X-IronPort-AV": "E=Sophos;i=\"5.76,409,1592870400\"; d=\"scan'208\";a=\"551712241\"",
        "From": "Hyong Youb Kim <hyonkim@cisco.com>",
        "To": "Ferruh Yigit <ferruh.yigit@intel.com>",
        "Cc": "dev@dpdk.org, Hyong Youb Kim <hyonkim@cisco.com>,\n John Daley <johndale@cisco.com>",
        "Date": "Wed,  9 Sep 2020 07:00:02 -0700",
        "Message-Id": "<20200909140006.23788-3-hyonkim@cisco.com>",
        "X-Mailer": "git-send-email 2.26.2",
        "In-Reply-To": "<20200909140006.23788-1-hyonkim@cisco.com>",
        "References": "<20200909140006.23788-1-hyonkim@cisco.com>",
        "MIME-Version": "1.0",
        "Content-Transfer-Encoding": "8bit",
        "X-Outbound-SMTP-Client": "10.193.184.48, savbu-usnic-a.cisco.com",
        "X-Outbound-Node": "rcdn-core-11.cisco.com",
        "Subject": "[dpdk-dev] [PATCH 2/6] net/enic: support egress PORT_ID action",
        "X-BeenThere": "dev@dpdk.org",
        "X-Mailman-Version": "2.1.15",
        "Precedence": "list",
        "List-Id": "DPDK patches and discussions <dev.dpdk.org>",
        "List-Unsubscribe": "<https://mails.dpdk.org/options/dev>,\n <mailto:dev-request@dpdk.org?subject=unsubscribe>",
        "List-Archive": "<http://mails.dpdk.org/archives/dev/>",
        "List-Post": "<mailto:dev@dpdk.org>",
        "List-Help": "<mailto:dev-request@dpdk.org?subject=help>",
        "List-Subscribe": "<https://mails.dpdk.org/listinfo/dev>,\n <mailto:dev-request@dpdk.org?subject=subscribe>",
        "Errors-To": "dev-bounces@dpdk.org",
        "Sender": "\"dev\" <dev-bounces@dpdk.org>"
    },
    "content": "Use Flow Manager (flowman) to support egress PORT_ID action. It can\nsteer egress packets from PFs and VFs to any uplink port as long as\nthey are all on the same VIC adapter. It can also steer packets\nbetween ports on the same VIC adapter (i.e. loopback).\n\nSigned-off-by: Hyong Youb Kim <hyonkim@cisco.com>\nReviewed-by: John Daley <johndale@cisco.com>\n---\n doc/guides/rel_notes/release_20_11.rst |   1 +\n drivers/net/enic/enic_fm_flow.c        | 154 +++++++++++++++++++++++++\n 2 files changed, 155 insertions(+)",
    "diff": "diff --git a/doc/guides/rel_notes/release_20_11.rst b/doc/guides/rel_notes/release_20_11.rst\nindex 180ab8fa0..afe81711a 100644\n--- a/doc/guides/rel_notes/release_20_11.rst\n+++ b/doc/guides/rel_notes/release_20_11.rst\n@@ -138,3 +138,4 @@ Tested Platforms\n * **Updated Cisco enic driver.**\n \n   * Added support for VF representors with single-queue Tx/Rx and flow API\n+  * Added support for egress PORT_ID action\ndiff --git a/drivers/net/enic/enic_fm_flow.c b/drivers/net/enic/enic_fm_flow.c\nindex 9255f2592..296e7e30d 100644\n--- a/drivers/net/enic/enic_fm_flow.c\n+++ b/drivers/net/enic/enic_fm_flow.c\n@@ -97,6 +97,8 @@ struct enic_fm_flow {\n \tuint64_t action_handle;\n \tstruct enic_fm_counter *counter;\n \tstruct enic_fm_fet *fet;\n+\t/* Auto-added steer action for hairpin flows (e.g. vnic->vnic) */\n+\tstruct enic_fm_flow *hairpin_steer_flow;\n };\n \n struct enic_fm_jump_flow {\n@@ -166,6 +168,9 @@ struct enic_flowman {\n \tint action_op_count;\n \t/* Tags used for representor flows */\n \tuint8_t vf_rep_tag;\n+\t/* For auto-added steer action for hairpin */\n+\tint need_hairpin_steer;\n+\tuint64_t hairpin_steer_vnic_h;\n };\n \n static int enic_fm_tbl_free(struct enic_flowman *fm, uint64_t handle);\n@@ -244,6 +249,7 @@ static const enum rte_flow_action_type enic_fm_supported_eg_actions[] = {\n \tRTE_FLOW_ACTION_TYPE_OF_PUSH_VLAN,\n \tRTE_FLOW_ACTION_TYPE_OF_SET_VLAN_PCP,\n \tRTE_FLOW_ACTION_TYPE_OF_SET_VLAN_VID,\n+\tRTE_FLOW_ACTION_TYPE_PORT_ID,\n \tRTE_FLOW_ACTION_TYPE_PASSTHRU,\n \tRTE_FLOW_ACTION_TYPE_VOID,\n \tRTE_FLOW_ACTION_TYPE_VXLAN_ENCAP,\n@@ -1120,6 +1126,68 @@ enic_fm_find_vnic(struct enic *enic, const struct rte_pci_addr *addr,\n \treturn 0;\n }\n \n+/*\n+ * Egress: target port should be either PF uplink or VF.\n+ * Supported cases\n+ * 1. VF egress -> PF uplink\n+ *   PF may be this VF's PF, or another PF, as long as they are on the same VIC.\n+ * 2. VF egress -> VF\n+ *\n+ * Unsupported cases\n+ * 1. PF egress -> VF\n+ *   App should be using representor to pass packets to VF\n+ */\n+static int\n+vf_egress_port_id_action(struct enic_flowman *fm,\n+\t\t\t struct rte_eth_dev *dst_dev,\n+\t\t\t uint64_t dst_vnic_h,\n+\t\t\t struct fm_action_op *fm_op,\n+\t\t\t struct rte_flow_error *error)\n+{\n+\tstruct enic *src_enic, *dst_enic;\n+\tstruct enic_vf_representor *vf;\n+\tuint8_t uif;\n+\tint ret;\n+\n+\tENICPMD_FUNC_TRACE();\n+\tsrc_enic = fm->user_enic;\n+\tdst_enic = pmd_priv(dst_dev);\n+\tif (!(src_enic->rte_dev->data->dev_flags & RTE_ETH_DEV_REPRESENTOR)) {\n+\t\treturn rte_flow_error_set(error, EINVAL,\n+\t\t\tRTE_FLOW_ERROR_TYPE_ACTION,\n+\t\t\tNULL, \"source port is not VF representor\");\n+\t}\n+\n+\t/* VF -> PF uplink. dst is not VF representor */\n+\tif (!(dst_dev->data->dev_flags & RTE_ETH_DEV_REPRESENTOR)) {\n+\t\t/* PF is the VF's PF? Then nothing to do */\n+\t\tvf = VF_ENIC_TO_VF_REP(src_enic);\n+\t\tif (vf->pf == dst_enic) {\n+\t\t\tENICPMD_LOG(DEBUG, \"destination port is VF's PF\");\n+\t\t\treturn 0;\n+\t\t}\n+\t\t/* If not, steer to the remote PF's uplink */\n+\t\tuif = dst_enic->fm_vnic_uif;\n+\t\tENICPMD_LOG(DEBUG, \"steer to uplink %u\", uif);\n+\t\tmemset(fm_op, 0, sizeof(*fm_op));\n+\t\tfm_op->fa_op = FMOP_SET_EGPORT;\n+\t\tfm_op->set_egport.egport = uif;\n+\t\tret = enic_fm_append_action_op(fm, fm_op, error);\n+\t\treturn ret;\n+\t}\n+\n+\t/* VF -> VF loopback. Hairpin and steer to vnic */\n+\tmemset(fm_op, 0, sizeof(*fm_op));\n+\tfm_op->fa_op = FMOP_EG_HAIRPIN;\n+\tret = enic_fm_append_action_op(fm, fm_op, error);\n+\tif (ret)\n+\t\treturn ret;\n+\tENICPMD_LOG(DEBUG, \"egress hairpin\");\n+\tfm->hairpin_steer_vnic_h = dst_vnic_h;\n+\tfm->need_hairpin_steer = 1;\n+\treturn 0;\n+}\n+\n /* Translate flow actions to flowman TCAM entry actions */\n static int\n enic_fm_copy_action(struct enic_flowman *fm,\n@@ -1310,6 +1378,10 @@ enic_fm_copy_action(struct enic_flowman *fm,\n \t\t\tconst struct rte_flow_action_port_id *port;\n \t\t\tstruct rte_eth_dev *dev;\n \n+\t\t\tif (!ingress && (overlap & PORT_ID)) {\n+\t\t\t\tENICPMD_LOG(DEBUG, \"cannot have multiple egress PORT_ID actions\");\n+\t\t\t\tgoto unsupported;\n+\t\t\t}\n \t\t\tport = actions->conf;\n \t\t\tif (port->original) {\n \t\t\t\tvnic_h = enic->fm_vnic_handle; /* This port */\n@@ -1339,6 +1411,13 @@ enic_fm_copy_action(struct enic_flowman *fm,\n \t\t\t * Ingress. Nothing more to do. We add an implicit\n \t\t\t * steer at the end if needed.\n \t\t\t */\n+\t\t\tif (ingress)\n+\t\t\t\tbreak;\n+\t\t\t/* Egress */\n+\t\t\tret = vf_egress_port_id_action(fm, dev, vnic_h, &fm_op,\n+\t\t\t\terror);\n+\t\t\tif (ret)\n+\t\t\t\treturn ret;\n \t\t\tbreak;\n \t\t}\n \t\tcase RTE_FLOW_ACTION_TYPE_VXLAN_DECAP: {\n@@ -1920,9 +1999,15 @@ __enic_fm_flow_free(struct enic_flowman *fm, struct enic_fm_flow *fm_flow)\n static void\n enic_fm_flow_free(struct enic_flowman *fm, struct rte_flow *flow)\n {\n+\tstruct enic_fm_flow *steer = flow->fm->hairpin_steer_flow;\n+\n \tif (flow->fm->fet && flow->fm->fet->default_key)\n \t\tremove_jump_flow(fm, flow);\n \t__enic_fm_flow_free(fm, flow->fm);\n+\tif (steer) {\n+\t\t__enic_fm_flow_free(fm, steer);\n+\t\tfree(steer);\n+\t}\n \tfree(flow->fm);\n \tfree(flow);\n }\n@@ -2173,11 +2258,71 @@ convert_jump_flows(struct enic_flowman *fm, struct enic_fm_fet *fet,\n \t}\n }\n \n+static int\n+add_hairpin_steer(struct enic_flowman *fm, struct rte_flow *flow,\n+\t\t  struct rte_flow_error *error)\n+{\n+\tstruct fm_tcam_match_entry *fm_tcam_entry;\n+\tstruct enic_fm_flow *fm_flow;\n+\tstruct fm_action *fm_action;\n+\tstruct fm_action_op fm_op;\n+\tint ret;\n+\n+\tENICPMD_FUNC_TRACE();\n+\tfm_flow = calloc(1, sizeof(*fm_flow));\n+\tif (fm_flow == NULL) {\n+\t\trte_flow_error_set(error, ENOMEM, RTE_FLOW_ERROR_TYPE_HANDLE,\n+\t\t\tNULL, \"enic: cannot allocate rte_flow\");\n+\t\treturn -ENOMEM;\n+\t}\n+\t/* Original egress hairpin flow */\n+\tfm_tcam_entry = &fm->tcam_entry;\n+\tfm_action = &fm->action;\n+\t/* Use the match pattern of the egress flow as is, without counters */\n+\tfm_tcam_entry->ftm_flags &= ~FMEF_COUNTER;\n+\t/* The only action is steer to vnic */\n+\tfm->action_op_count = 0;\n+\tmemset(fm_action, 0, sizeof(*fm_action));\n+\tmemset(&fm_op, 0, sizeof(fm_op));\n+\t/* Always to queue 0 for now */\n+\tfm_op.fa_op = FMOP_RQ_STEER;\n+\tfm_op.rq_steer.rq_index = 0;\n+\tfm_op.rq_steer.vnic_handle = fm->hairpin_steer_vnic_h;\n+\tret = enic_fm_append_action_op(fm, &fm_op, error);\n+\tif (ret)\n+\t\tgoto error_with_flow;\n+\tENICPMD_LOG(DEBUG, \"add steer op\");\n+\t/* Add required END */\n+\tmemset(&fm_op, 0, sizeof(fm_op));\n+\tfm_op.fa_op = FMOP_END;\n+\tret = enic_fm_append_action_op(fm, &fm_op, error);\n+\tif (ret)\n+\t\tgoto error_with_flow;\n+\t/* Add the ingress flow */\n+\tfm_flow->action_handle = FM_INVALID_HANDLE;\n+\tfm_flow->entry_handle = FM_INVALID_HANDLE;\n+\tret = __enic_fm_flow_add_entry(fm, fm_flow, fm_tcam_entry, fm_action,\n+\t\t\t\t       FM_TCAM_RTE_GROUP, 1 /* ingress */, error);\n+\tif (ret) {\n+\t\tENICPMD_LOG(ERR, \"cannot add hairpin-steer flow\");\n+\t\tgoto error_with_flow;\n+\t}\n+\t/* The new flow is now the egress flow's paired flow */\n+\tflow->fm->hairpin_steer_flow = fm_flow;\n+\treturn 0;\n+\n+error_with_flow:\n+\tfree(fm_flow);\n+\treturn ret;\n+}\n+\n static void\n enic_fm_open_scratch(struct enic_flowman *fm)\n {\n \tfm->action_op_count = 0;\n \tfm->fet = NULL;\n+\tfm->need_hairpin_steer = 0;\n+\tfm->hairpin_steer_vnic_h = 0;\n \tmemset(&fm->tcam_entry, 0, sizeof(fm->tcam_entry));\n \tmemset(&fm->action, 0, sizeof(fm->action));\n }\n@@ -2325,6 +2470,15 @@ enic_fm_flow_create(struct rte_eth_dev *dev,\n \tflow = enic_fm_flow_add_entry(fm, fm_tcam_entry, fm_action,\n \t\t\t\t      attrs, error);\n \tif (flow) {\n+\t\t/* Add ingress rule that pairs with hairpin rule */\n+\t\tif (fm->need_hairpin_steer) {\n+\t\t\tret = add_hairpin_steer(fm, flow, error);\n+\t\t\tif (ret) {\n+\t\t\t\tenic_fm_flow_free(fm, flow);\n+\t\t\t\tflow = NULL;\n+\t\t\t\tgoto error_with_scratch;\n+\t\t\t}\n+\t\t}\n \t\tLIST_INSERT_HEAD(&enic->flows, flow, next);\n \t\tfet = flow->fm->fet;\n \t\tif (fet && fet->default_key) {\n",
    "prefixes": [
        "2/6"
    ]
}