From patchwork Fri Jun 1 17:42:04 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Han Zhou X-Patchwork-Id: 924272 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=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="OrZVQPPZ"; dkim-atps=neutral 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 40yBgD3j2Qz9ry1 for ; Sat, 2 Jun 2018 03:50:00 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id 3FD2CF7E; Fri, 1 Jun 2018 17:43:00 +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 6EAB2F19 for ; Fri, 1 Jun 2018 17:42:53 +0000 (UTC) X-Greylist: whitelisted by SQLgrey-1.7.6 Received: from mail-pl0-f42.google.com (mail-pl0-f42.google.com [209.85.160.42]) by smtp1.linuxfoundation.org (Postfix) with ESMTPS id 943E5CF for ; Fri, 1 Jun 2018 17:42:52 +0000 (UTC) Received: by mail-pl0-f42.google.com with SMTP id v24-v6so15722858plo.3 for ; Fri, 01 Jun 2018 10:42:52 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=piCuT+zuzJJscHwCfjYPqMS4WmYMmskFdvn0FFcaPes=; b=OrZVQPPZyEONgNZiczeitPWC9xEWxGqkcaghUEdhWrJWSTb0MMb+VkE/QMYHScgYJZ pt8AiRCvmaQUHvQ0nTWvzxp0tn49LOYs1hCOJLwwiZe9Sw9sJzJFQe0amxMHij1kwU7N jUXGNXzKRSHLmTPfBPi2GdOTd+UFAUB5AOOcqvrm71dNKQruTWysRym8Ej+wcuV8SvQO rRerkqvsxLQnCvbhJn48wsVUgtGNRR0Phb/6Q+kEmkTcrWem7Af3gZtq9nTTO+9qEGGc RGcI3JOQL2noXVQmQxJkigSOCC/VHMRrRfuf7NM4pwwA08Y+kB+Kv1PSC+QYp/T5hLji a/UA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=piCuT+zuzJJscHwCfjYPqMS4WmYMmskFdvn0FFcaPes=; b=bxnas0jwCeYfczOYqnkoV5yPxQ9eZeSKwDsM1p0p86DBDbcIwiNYSbdlev6L9XXHU0 L3Np2Rg5Y1mq2a2a1ygwekJvc0X+YVRDhZRrERdg8wGc1T6mhcPLJzWR3yP6gx+MDYAX fsPuDH3hjfz+TZhuh3C5pOdmXxaO2wXVtvyIVr2IDFXvjzaGvw9U97G3mzFAy8Wzdoo2 md0bDiLawy4vvXf8yniRlRkGRKtgrIRdI14Xs1/Z1EpUCue396lNQRIHzfsHtez40Kyb wzX+2Em4R3awMurqJgrKbfF/Z/DxpJqOisJZoKMH7+rKxZh7fsBMvNHgiH3p8TAy9guP Olrw== X-Gm-Message-State: ALKqPwfgvs7Aq67P49WRdZiJylGBNZN1Niv94Tef2ysVPFCIHVvsMNdn M54r2waUGSwMJGSjnTbyrA+k3g== X-Google-Smtp-Source: ADUXVKK/Nx4VD08CblBHDt+1r2iRNjGQIE66mLDoL7HHgRlY2Cpw54wrPfgX80dHOlN46TISJd0dpA== X-Received: by 2002:a17:902:1a6:: with SMTP id b35-v6mr11989167plb.80.1527874971939; Fri, 01 Jun 2018 10:42:51 -0700 (PDT) Received: from localhost.localdomain.localdomain (c-73-162-150-77.hsd1.ca.comcast.net. [73.162.150.77]) by smtp.gmail.com with ESMTPSA id v26-v6sm9600279pfe.13.2018.06.01.10.42.50 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 01 Jun 2018 10:42:51 -0700 (PDT) From: Han Zhou X-Google-Original-From: Han Zhou To: dev@openvswitch.org Date: Fri, 1 Jun 2018 10:42:04 -0700 Message-Id: <1527874926-40450-15-git-send-email-hzhou8@ebay.com> X-Mailer: git-send-email 2.1.0 In-Reply-To: <1527874926-40450-1-git-send-email-hzhou8@ebay.com> References: <1527874926-40450-1-git-send-email-hzhou8@ebay.com> X-Spam-Status: No, score=-2.0 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, FREEMAIL_FROM, RCVD_IN_DNSWL_NONE 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] [PATCH v3 14/16] ovn-controller: Incremental processing for address-set changes. 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 Signed-off-by: Han Zhou --- ovn/controller/lflow.c | 100 ++++++++++++++++++++++++++++++++++++++++ ovn/controller/lflow.h | 16 +++++++ ovn/controller/ovn-controller.c | 72 ++++++++++++++++++++++++++++- tests/ovn.at | 71 ++++++++++++++++++++++++++++ 4 files changed, 258 insertions(+), 1 deletion(-) diff --git a/ovn/controller/lflow.c b/ovn/controller/lflow.c index a39e241..17c9f20 100644 --- a/ovn/controller/lflow.c +++ b/ovn/controller/lflow.c @@ -392,6 +392,106 @@ lflow_handle_changed_flows(struct ovn_desired_flow_table *flow_table, return ret; } +bool +lflow_handle_changed_ref(struct ovn_desired_flow_table *flow_table, + struct lflow_resource_ref *lfrr, + enum ref_type ref_type, + const char *ref_name, + struct controller_ctx *ctx, + const struct sbrec_chassis *chassis, + const struct chassis_index *chassis_index, + const struct hmap *local_datapaths, + struct ovn_extend_table *group_table, + struct ovn_extend_table *meter_table, + const struct shash *addr_sets, + const struct shash *port_groups, + struct sset *active_tunnels, + struct sset *local_lport_ids, + uint32_t *conj_id_ofs, + bool *changed) +{ + struct ref_lflow_node *rlfn = ref_lflow_lookup(&lfrr->ref_lflow_table, + ref_type, ref_name); + if (!rlfn) { + *changed = false; + return true; + } + VLOG_DBG("Handle changed lflow reference for resource type: %d," + " name: %s.", ref_type, ref_name); + *changed = false; + bool ret = true; + + hmap_remove(&lfrr->ref_lflow_table, &rlfn->node); + + struct lflow_ref_list_node *lrln, *next; + /* Detach the rlfn->ref_lflow_head nodes from the lfrr table and clean + * up all other nodes related to the lflows that uses the resource, + * so that the old nodes won't interfere with updating the lfrr table + * when reparsing the lflows. */ + LIST_FOR_EACH (lrln, ref_list, &rlfn->ref_lflow_head) { + ovs_list_remove(&lrln->lflow_list); + lflow_resource_destroy_lflow(lfrr, &lrln->lflow_uuid); + } + + struct hmap dhcp_opts = HMAP_INITIALIZER(&dhcp_opts); + struct hmap dhcpv6_opts = HMAP_INITIALIZER(&dhcpv6_opts); + const struct sbrec_dhcp_options *dhcp_opt_row; + SBREC_DHCP_OPTIONS_FOR_EACH (dhcp_opt_row, ctx->ovnsb_idl) { + dhcp_opt_add(&dhcp_opts, dhcp_opt_row->name, dhcp_opt_row->code, + dhcp_opt_row->type); + } + + + const struct sbrec_dhcpv6_options *dhcpv6_opt_row; + SBREC_DHCPV6_OPTIONS_FOR_EACH(dhcpv6_opt_row, ctx->ovnsb_idl) { + dhcp_opt_add(&dhcpv6_opts, dhcpv6_opt_row->name, dhcpv6_opt_row->code, + dhcpv6_opt_row->type); + } + + struct hmap nd_ra_opts = HMAP_INITIALIZER(&nd_ra_opts); + nd_ra_opts_init(&nd_ra_opts); + + /* Re-parse the related lflows. */ + LIST_FOR_EACH (lrln, ref_list, &rlfn->ref_lflow_head) { + const struct sbrec_logical_flow *lflow = + sbrec_logical_flow_get_for_uuid(ctx->ovnsb_idl, + &lrln->lflow_uuid); + if (!lflow) { + VLOG_DBG("Reprocess lflow "UUID_FMT" for resource type: %d," + " name: %s - not found.", + UUID_ARGS(&lrln->lflow_uuid), + ref_type, ref_name); + continue; + } + VLOG_DBG("Reprocess lflow "UUID_FMT" for resource type: %d," + " name: %s.", + UUID_ARGS(&lrln->lflow_uuid), + ref_type, ref_name); + ofctrl_remove_flows(flow_table, &lrln->lflow_uuid); + if (!consider_logical_flow(flow_table, lfrr, ctx, chassis_index, + lflow, local_datapaths, + group_table, meter_table, chassis, + &dhcp_opts, &dhcpv6_opts, &nd_ra_opts, + conj_id_ofs, addr_sets, port_groups, + active_tunnels, local_lport_ids)) { + ret = false; + break; + } + *changed = true; + } + + LIST_FOR_EACH_SAFE (lrln, next, ref_list, &rlfn->ref_lflow_head) { + ovs_list_remove(&lrln->ref_list); + free(lrln); + } + free(rlfn); + + dhcp_opts_destroy(&dhcp_opts); + dhcp_opts_destroy(&dhcpv6_opts); + nd_ra_opts_destroy(&nd_ra_opts); + return ret; +} + static bool update_conj_id_ofs(uint32_t *conj_id_ofs, uint32_t n_conjs) { diff --git a/ovn/controller/lflow.h b/ovn/controller/lflow.h index bc6c7ac..a5c42f1 100644 --- a/ovn/controller/lflow.h +++ b/ovn/controller/lflow.h @@ -139,6 +139,22 @@ bool lflow_handle_changed_flows(struct ovn_desired_flow_table *, struct sset *active_tunnels, struct sset *local_lport_ids, uint32_t *conj_id_ofs); +bool lflow_handle_changed_ref(struct ovn_desired_flow_table *, + struct lflow_resource_ref *, + enum ref_type, + const char *ref_name, + struct controller_ctx *ctx, + const struct sbrec_chassis *chassis, + const struct chassis_index *chassis_index, + const struct hmap *local_datapaths, + struct ovn_extend_table *group_table, + struct ovn_extend_table *meter_table, + const struct shash *addr_sets, + const struct shash *port_groups, + struct sset *active_tunnels, + struct sset *local_lport_ids, + uint32_t *conj_id_ofs, + bool *changed); void lflow_destroy(void); #endif /* ovn/lflow.h */ diff --git a/ovn/controller/ovn-controller.c b/ovn/controller/ovn-controller.c index 7d0bde5..953582f 100644 --- a/ovn/controller/ovn-controller.c +++ b/ovn/controller/ovn-controller.c @@ -1075,6 +1075,76 @@ flow_output_sb_multicast_group_handler(struct engine_node *node) } +static bool +flow_output_addr_sets_handler(struct engine_node *node) +{ + struct controller_ctx *ctx = (struct controller_ctx *)node->context; + struct ed_type_runtime_data *data = + (struct ed_type_runtime_data *)engine_get_input( + "runtime_data", node)->data; + struct hmap *local_datapaths = &data->local_datapaths; + struct sset *local_lport_ids = &data->local_lport_ids; + struct sset *active_tunnels = &data->active_tunnels; + struct chassis_index *chassis_index = &data->chassis_index; + struct shash *port_groups = &data->port_groups; + struct ed_type_addr_sets *as_data = + (struct ed_type_addr_sets *)engine_get_input("addr_sets", node)->data; + struct shash *addr_sets = &as_data->addr_sets; + const struct ovsrec_bridge *br_int = get_br_int(ctx); + const char *chassis_id = get_chassis_id(ctx->ovs_idl); + + const struct sbrec_chassis *chassis = NULL; + if (chassis_id) { + chassis = get_chassis(ctx->ovnsb_idl, chassis_id); + } + + ovs_assert(br_int && chassis); + + struct ed_type_flow_output *fo = + (struct ed_type_flow_output *)node->data; + struct ovn_desired_flow_table *flow_table = &fo->flow_table; + struct ovn_extend_table *group_table = &fo->group_table; + struct ovn_extend_table *meter_table = &fo->meter_table; + uint32_t *conj_id_ofs = &fo->conj_id_ofs; + struct lflow_resource_ref *lfrr = &fo->lflow_resource_ref; + + bool changed; + const char *as; + + SSET_FOR_EACH (as, &as_data->deleted) { + if (!lflow_handle_changed_ref(flow_table, lfrr, REF_TYPE_ADDRSET, + as, ctx, chassis, chassis_index, local_datapaths, + group_table, meter_table, addr_sets, port_groups, + active_tunnels, local_lport_ids, conj_id_ofs, + &changed)) { + return false; + } + node->changed = changed || node->changed; + } + SSET_FOR_EACH (as, &as_data->updated) { + if (!lflow_handle_changed_ref(flow_table, lfrr, REF_TYPE_ADDRSET, + as, ctx, chassis, chassis_index, local_datapaths, + group_table, meter_table, addr_sets, port_groups, + active_tunnels, local_lport_ids, conj_id_ofs, + &changed)) { + return false; + } + node->changed = changed || node->changed; + } + SSET_FOR_EACH (as, &as_data->new) { + if (!lflow_handle_changed_ref(flow_table, lfrr, REF_TYPE_ADDRSET, + as, ctx, chassis, chassis_index, local_datapaths, + group_table, meter_table, addr_sets, port_groups, + active_tunnels, local_lport_ids, conj_id_ofs, + &changed)) { + return false; + } + node->changed = changed || node->changed; + } + + return true; +} + int main(int argc, char *argv[]) { @@ -1156,7 +1226,7 @@ main(int argc, char *argv[]) engine_add_input(&en_addr_sets, &en_sb_address_set, NULL); - engine_add_input(&en_flow_output, &en_addr_sets, NULL); + engine_add_input(&en_flow_output, &en_addr_sets, flow_output_addr_sets_handler); engine_add_input(&en_flow_output, &en_runtime_data, NULL); engine_add_input(&en_flow_output, &en_ovs_port, NULL); diff --git a/tests/ovn.at b/tests/ovn.at index f12c24c..c933f70 100644 --- a/tests/ovn.at +++ b/tests/ovn.at @@ -10267,3 +10267,74 @@ $PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/vif2-tx.pcap > 2.packets AT_CHECK([cat 2.packets], [0], []) AT_CLEANUP + +AT_SETUP([ovn -- Address Set Incremental Processing]) +AT_KEYWORDS([ovn_as_inc]) +AT_SKIP_IF([test $HAVE_PYTHON = no]) +ovn_start + +net_add n1 +sim_add hv1 +as hv1 +ovs-vsctl add-br br-phys +ovn_attach n1 br-phys 192.168.0.10 + +ovn-nbctl ls-add ls1 +for i in 1 2; do + ovn-nbctl lsp-add ls1 lp$i \ + -- lsp-set-addresses lp$i "f0:00:00:00:00:0$i 192.168.1.$i" + as hv1 ovs-vsctl \ + -- add-port br-int vif$i \ + -- set Interface vif$i \ + external-ids:iface-id=lp$i +done + +for i in 1 2 3; do + as1_uuid=`ovn-nbctl --wait=hv create addr name=as1` + as2_uuid=`ovn-nbctl --wait=hv create addr name=as2` + ovn-nbctl --wait=hv acl-add ls1 to-lport 200 \ + 'outport=="lp1" && ip4 && ip4.src == {$as1, $as2}' allow-related + ovn-nbctl --wait=hv set addr as1 addresses="10.1.2.10" + AT_CHECK([ovs-ofctl dump-flows br-int | grep "10.1.2.10"], [0], [ignore]) + + # Update address set as1 + ovn-nbctl --wait=hv set addr as1 addresses="10.1.2.10 10.1.2.11" + AT_CHECK([ovs-ofctl dump-flows br-int | grep "10.1.2.11"], [0], [ignore]) + + # Update address set as2 + ovn-nbctl --wait=hv set addr as2 addresses="10.1.2.12 10.1.2.13" + AT_CHECK([ovs-ofctl dump-flows br-int | grep "10.1.2.12"], [0], [ignore]) + + # Add another ACL referencing as1 + n_flows_before=`ovs-ofctl dump-flows br-int | grep "10.1.2.10" | wc -l` + ovn-nbctl --wait=hv acl-add ls1 to-lport 200 \ + 'outport=="lp2" && ip4 && ip4.src == $as1' allow-related + n_flows_after=`ovs-ofctl dump-flows br-int | grep "10.1.2.10" | wc -l` + AT_CHECK([test $(expr $n_flows_before \* 2) = $n_flows_after], [0], [ignore]) + + # Remove an ACL + ovn-nbctl --wait=hv acl-del ls1 to-lport 200 \ + 'outport=="lp2" && ip4 && ip4.src == $as1' + n_flows_after=`ovs-ofctl dump-flows br-int | grep "10.1.2.10" | wc -l` + AT_CHECK([test $n_flows_before = $n_flows_after], [0], [ignore]) + + # Remove as1 while it is still used by an ACL, the lflows should be reparsed and + # parsing should fail. + ovn-nbctl --wait=hv destroy addr $as1_uuid + AT_CHECK([ovs-ofctl dump-flows br-int | grep "10.1.2.10"], [1], [ignore]) + AT_CHECK([ovs-ofctl dump-flows br-int | grep "10.1.2.12"], [1], [ignore]) + + # Recreate as1 + as1_uuid=`ovn-nbctl --wait=hv create addr name=as1` + AT_CHECK([ovs-ofctl dump-flows br-int | grep "10.1.2.12"], [0], [ignore]) + + # Remove ACLs and address sets + ovn-nbctl --wait=hv destroy addr $as1_uuid -- destroy addr $as2_uuid + AT_CHECK([ovs-ofctl dump-flows br-int | grep "10.1.2.12"], [1], [ignore]) + + ovn-nbctl --wait=hv acl-del ls1 +done + +# Gracefully terminate daemons +OVN_CLEANUP([hv1]) +AT_CLEANUP