From patchwork Wed Jan 10 22:27:21 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Justin Pettit X-Patchwork-Id: 858592 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=openvswitch.org (client-ip=140.211.169.12; helo=mail.linuxfoundation.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Received: from mail.linuxfoundation.org (mail.linuxfoundation.org [140.211.169.12]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3zH3bq01N8z9s4s for ; Thu, 11 Jan 2018 09:29:58 +1100 (AEDT) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id 2B66B1030; Wed, 10 Jan 2018 22:28:21 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@mail.linuxfoundation.org Received: from smtp1.linuxfoundation.org (smtp1.linux-foundation.org [172.17.192.35]) by mail.linuxfoundation.org (Postfix) with ESMTPS id 7A6DCFFF for ; Wed, 10 Jan 2018 22:28:18 +0000 (UTC) X-Greylist: domain auto-whitelisted by SQLgrey-1.7.6 Received: from relay2-d.mail.gandi.net (relay2-d.mail.gandi.net [217.70.183.194]) by smtp1.linuxfoundation.org (Postfix) with ESMTPS id 906B9E3 for ; Wed, 10 Jan 2018 22:28:17 +0000 (UTC) X-Originating-IP: 98.234.50.139 Received: from localhost.localdomain (unknown [98.234.50.139]) (Authenticated sender: jpettit@ovn.org) by relay2-d.mail.gandi.net (Postfix) with ESMTPSA id D761AC5A50 for ; Wed, 10 Jan 2018 23:28:15 +0100 (CET) From: Justin Pettit To: dev@openvswitch.org Date: Wed, 10 Jan 2018 14:27:21 -0800 Message-Id: <1515623246-3820-3-git-send-email-jpettit@ovn.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1515623246-3820-1-git-send-email-jpettit@ovn.org> References: <1515623246-3820-1-git-send-email-jpettit@ovn.org> X-Spam-Status: No, score=-2.6 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_LOW autolearn=ham version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on smtp1.linux-foundation.org Subject: [ovs-dev] [no-slow v2 3/8] ofproto-dpif: Reorganize upcall handling. X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: ovs-dev-bounces@openvswitch.org Errors-To: ovs-dev-bounces@openvswitch.org - This reduces the number of times upcall cookies are processed. - It separate true miss calls from slow-path actions. The reorganization will also be useful for a future commit. Signed-off-by: Justin Pettit --- v1->v2: Changes suggested by Ben. --- ofproto/ofproto-dpif-upcall.c | 81 +++++++++++++++++++------------------------ 1 file changed, 36 insertions(+), 45 deletions(-) diff --git a/ofproto/ofproto-dpif-upcall.c b/ofproto/ofproto-dpif-upcall.c index ddae02dabb3f..83007d00b46c 100644 --- a/ofproto/ofproto-dpif-upcall.c +++ b/ofproto/ofproto-dpif-upcall.c @@ -183,6 +183,7 @@ struct udpif { enum upcall_type { BAD_UPCALL, /* Some kind of bug somewhere. */ MISS_UPCALL, /* A flow miss. */ + SLOW_PATH_UPCALL, /* Slow path upcall. */ SFLOW_UPCALL, /* sFlow sample. */ FLOW_SAMPLE_UPCALL, /* Per-flow sampling. */ IPFIX_UPCALL /* Per-bridge sampling. */ @@ -210,8 +211,7 @@ struct upcall { uint16_t mru; /* If !0, Maximum receive unit of fragmented IP packet */ - enum dpif_upcall_type type; /* Datapath type of the upcall. */ - const struct nlattr *userdata; /* Userdata for DPIF_UC_ACTION Upcalls. */ + enum upcall_type type; /* Type of the upcall. */ const struct nlattr *actions; /* Flow actions in DPIF_UC_ACTION Upcalls. */ bool xout_initialized; /* True if 'xout' must be uninitialized. */ @@ -235,6 +235,8 @@ struct upcall { size_t key_len; /* Datapath flow key length. */ const struct nlattr *out_tun_key; /* Datapath output tunnel key. */ + struct user_action_cookie cookie; + uint64_t odp_actions_stub[1024 / 8]; /* Stub for odp_actions. */ }; @@ -367,7 +369,8 @@ static int ukey_acquire(struct udpif *, const struct dpif_flow *, static void ukey_delete__(struct udpif_key *); static void ukey_delete(struct umap *, struct udpif_key *); static enum upcall_type classify_upcall(enum dpif_upcall_type type, - const struct nlattr *userdata); + const struct nlattr *userdata, + struct user_action_cookie *cookie); static void put_op_init(struct ukey_op *op, struct udpif_key *ukey, enum dpif_flow_put_flags flags); @@ -969,7 +972,8 @@ udpif_revalidator(void *arg) } static enum upcall_type -classify_upcall(enum dpif_upcall_type type, const struct nlattr *userdata) +classify_upcall(enum dpif_upcall_type type, const struct nlattr *userdata, + struct user_action_cookie *cookie) { /* First look at the upcall type. */ switch (type) { @@ -991,25 +995,24 @@ classify_upcall(enum dpif_upcall_type type, const struct nlattr *userdata) return BAD_UPCALL; } - struct user_action_cookie cookie; size_t userdata_len = nl_attr_get_size(userdata); - if (userdata_len != sizeof cookie) { + if (userdata_len != sizeof *cookie) { VLOG_WARN_RL(&rl, "action upcall cookie has unexpected size %"PRIuSIZE, userdata_len); return BAD_UPCALL; } - memcpy(&cookie, nl_attr_get(userdata), sizeof cookie); - if (cookie.type == USER_ACTION_COOKIE_SFLOW) { + memcpy(cookie, nl_attr_get(userdata), sizeof *cookie); + if (cookie->type == USER_ACTION_COOKIE_SFLOW) { return SFLOW_UPCALL; - } else if (cookie.type == USER_ACTION_COOKIE_SLOW_PATH) { - return MISS_UPCALL; - } else if (cookie.type == USER_ACTION_COOKIE_FLOW_SAMPLE) { + } else if (cookie->type == USER_ACTION_COOKIE_SLOW_PATH) { + return SLOW_PATH_UPCALL; + } else if (cookie->type == USER_ACTION_COOKIE_FLOW_SAMPLE) { return FLOW_SAMPLE_UPCALL; - } else if (cookie.type == USER_ACTION_COOKIE_IPFIX) { + } else if (cookie->type == USER_ACTION_COOKIE_IPFIX) { return IPFIX_UPCALL; } else { VLOG_WARN_RL(&rl, "invalid user cookie of type %"PRIu16 - " and size %"PRIuSIZE, cookie.type, userdata_len); + " and size %"PRIuSIZE, cookie->type, userdata_len); return BAD_UPCALL; } } @@ -1071,6 +1074,11 @@ upcall_receive(struct upcall *upcall, const struct dpif_backer *backer, { int error; + upcall->type = classify_upcall(type, userdata, &upcall->cookie); + if (upcall->type == BAD_UPCALL) { + return EAGAIN; + } + error = xlate_lookup(backer, flow, &upcall->ofproto, &upcall->ipfix, &upcall->sflow, NULL, &upcall->in_port); if (error) { @@ -1083,8 +1091,6 @@ upcall_receive(struct upcall *upcall, const struct dpif_backer *backer, upcall->packet = packet; upcall->ufid = ufid; upcall->pmd_id = pmd_id; - upcall->type = type; - upcall->userdata = userdata; ofpbuf_use_stub(&upcall->odp_actions, upcall->odp_actions_stub, sizeof upcall->odp_actions_stub); ofpbuf_init(&upcall->put_actions, 0); @@ -1120,7 +1126,7 @@ upcall_xlate(struct udpif *udpif, struct upcall *upcall, upcall->flow, upcall->in_port, NULL, stats.tcp_flags, upcall->packet, wc, odp_actions); - if (upcall->type == DPIF_UC_MISS) { + if (upcall->type == MISS_UPCALL) { xin.resubmit_stats = &stats; if (xin.frozen_state) { @@ -1169,7 +1175,7 @@ upcall_xlate(struct udpif *udpif, struct upcall *upcall, /* This function is also called for slow-pathed flows. As we are only * going to create new datapath flows for actual datapath misses, there is * no point in creating a ukey otherwise. */ - if (upcall->type == DPIF_UC_MISS) { + if (upcall->type == MISS_UPCALL) { upcall->ukey = ukey_create_from_upcall(upcall, wc); } } @@ -1205,7 +1211,7 @@ should_install_flow(struct udpif *udpif, struct upcall *upcall) { unsigned int flow_limit; - if (upcall->type != DPIF_UC_MISS) { + if (upcall->type != MISS_UPCALL) { return false; } else if (upcall->recirc && !upcall->have_recirc_ref) { VLOG_DBG_RL(&rl, "upcall: no reference for recirc flow"); @@ -1318,6 +1324,7 @@ dpif_read_actions(struct udpif *udpif, struct upcall *upcall, break; case BAD_UPCALL: case MISS_UPCALL: + case SLOW_PATH_UPCALL: default: break; } @@ -1329,57 +1336,46 @@ static int process_upcall(struct udpif *udpif, struct upcall *upcall, struct ofpbuf *odp_actions, struct flow_wildcards *wc) { - const struct nlattr *userdata = upcall->userdata; const struct dp_packet *packet = upcall->packet; const struct flow *flow = upcall->flow; size_t actions_len = 0; - enum upcall_type upcall_type = classify_upcall(upcall->type, userdata); - switch (upcall_type) { + switch (upcall->type) { case MISS_UPCALL: + case SLOW_PATH_UPCALL: upcall_xlate(udpif, upcall, odp_actions, wc); return 0; case SFLOW_UPCALL: if (upcall->sflow) { - struct user_action_cookie cookie; struct dpif_sflow_actions sflow_actions; - if (nl_attr_get_size(userdata) != sizeof cookie) { - return EINVAL; - } - memcpy(&cookie, nl_attr_get(userdata), sizeof cookie); memset(&sflow_actions, 0, sizeof sflow_actions); - actions_len = dpif_read_actions(udpif, upcall, flow, upcall_type, - &sflow_actions); + actions_len = dpif_read_actions(udpif, upcall, flow, + upcall->type, &sflow_actions); dpif_sflow_received(upcall->sflow, packet, flow, - flow->in_port.odp_port, &cookie, + flow->in_port.odp_port, &upcall->cookie, actions_len > 0 ? &sflow_actions : NULL); } break; case IPFIX_UPCALL: if (upcall->ipfix) { - struct user_action_cookie cookie; struct flow_tnl output_tunnel_key; struct dpif_ipfix_actions ipfix_actions; - if (nl_attr_get_size(userdata) != sizeof cookie) { - return EINVAL; - } - memcpy(&cookie, nl_attr_get(userdata), sizeof cookie); memset(&ipfix_actions, 0, sizeof ipfix_actions); if (upcall->out_tun_key) { odp_tun_key_from_attr(upcall->out_tun_key, &output_tunnel_key); } - actions_len = dpif_read_actions(udpif, upcall, flow, upcall_type, - &ipfix_actions); + actions_len = dpif_read_actions(udpif, upcall, flow, + upcall->type, &ipfix_actions); dpif_ipfix_bridge_sample(upcall->ipfix, packet, flow, flow->in_port.odp_port, - cookie.ipfix.output_odp_port, + upcall->cookie.ipfix.output_odp_port, upcall->out_tun_key ? &output_tunnel_key : NULL, actions_len > 0 ? &ipfix_actions: NULL); @@ -1388,26 +1384,21 @@ process_upcall(struct udpif *udpif, struct upcall *upcall, case FLOW_SAMPLE_UPCALL: if (upcall->ipfix) { - struct user_action_cookie cookie; struct flow_tnl output_tunnel_key; struct dpif_ipfix_actions ipfix_actions; - if (nl_attr_get_size(userdata) != sizeof cookie) { - return EINVAL; - } - memcpy(&cookie, nl_attr_get(userdata), sizeof cookie); memset(&ipfix_actions, 0, sizeof ipfix_actions); if (upcall->out_tun_key) { odp_tun_key_from_attr(upcall->out_tun_key, &output_tunnel_key); } - actions_len = dpif_read_actions(udpif, upcall, flow, upcall_type, - &ipfix_actions); + actions_len = dpif_read_actions(udpif, upcall, flow, + upcall->type, &ipfix_actions); /* The flow reflects exactly the contents of the packet. * Sample the packet using it. */ dpif_ipfix_flow_sample(upcall->ipfix, packet, flow, - &cookie, flow->in_port.odp_port, + &upcall->cookie, flow->in_port.odp_port, upcall->out_tun_key ? &output_tunnel_key : NULL, actions_len > 0 ? &ipfix_actions: NULL);