From patchwork Wed Jun 16 17:56:09 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mark Michelson X-Patchwork-Id: 1493020 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=openvswitch.org (client-ip=2605:bc80:3010::136; helo=smtp3.osuosl.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=NLasZ9Ch; dkim-atps=neutral Received: from smtp3.osuosl.org (smtp3.osuosl.org [IPv6:2605:bc80:3010::136]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4G4tD325vCz9sXN for ; Thu, 17 Jun 2021 03:56:35 +1000 (AEST) Received: from localhost (localhost [127.0.0.1]) by smtp3.osuosl.org (Postfix) with ESMTP id 3AEAE60A9F; Wed, 16 Jun 2021 17:56:32 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from smtp3.osuosl.org ([127.0.0.1]) by localhost (smtp3.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id sWyLPewsRjDC; Wed, 16 Jun 2021 17:56:26 +0000 (UTC) Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [IPv6:2605:bc80:3010:104::8cd3:938]) by smtp3.osuosl.org (Postfix) with ESMTPS id F0D9760A91; Wed, 16 Jun 2021 17:56:24 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id C1D0DC000F; Wed, 16 Jun 2021 17:56:24 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@lists.linuxfoundation.org Received: from smtp3.osuosl.org (smtp3.osuosl.org [IPv6:2605:bc80:3010::136]) by lists.linuxfoundation.org (Postfix) with ESMTP id 69DD6C000B for ; Wed, 16 Jun 2021 17:56:21 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by smtp3.osuosl.org (Postfix) with ESMTP id 4EA6760619 for ; Wed, 16 Jun 2021 17:56:21 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from smtp3.osuosl.org ([127.0.0.1]) by localhost (smtp3.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id zrZA5TVWdm11 for ; Wed, 16 Jun 2021 17:56:19 +0000 (UTC) X-Greylist: domain auto-whitelisted by SQLgrey-1.8.0 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by smtp3.osuosl.org (Postfix) with ESMTPS id 25EDE60635 for ; Wed, 16 Jun 2021 17:56:18 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1623866177; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=2HctEcYi9nNeyOakliFCiahhStmoaSh0B4vgGeTp8CA=; b=NLasZ9ChyvwJeUl81DBo2RTKH3hLc0UsedjSh44EewLLBjKOQhv9l5oaF+sT0HN2NGTttN nAw2SBILW6svcjIlv2EOM1xs69dOiK3yLVbAaZ9q5TdBlpLB8hr6XyaU6PAwrtWI10Mc/u /L5unpe8RwTifE03kuCHPAmQI36bmkk= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-422-KeuSPeoXNkS5VV4UzXFqow-1; Wed, 16 Jun 2021 13:56:14 -0400 X-MC-Unique: KeuSPeoXNkS5VV4UzXFqow-1 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 101E1100CEE5 for ; Wed, 16 Jun 2021 17:56:14 +0000 (UTC) Received: from localhost.localdomain.com (ovpn-115-92.rdu2.redhat.com [10.10.115.92]) by smtp.corp.redhat.com (Postfix) with ESMTP id 7F6106090F for ; Wed, 16 Jun 2021 17:56:13 +0000 (UTC) From: Mark Michelson To: dev@openvswitch.org Date: Wed, 16 Jun 2021 13:56:09 -0400 Message-Id: <20210616175611.597915-2-mmichels@redhat.com> In-Reply-To: <20210616175611.597915-1-mmichels@redhat.com> References: <20210616175611.597915-1-mmichels@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.13 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=mmichels@redhat.com X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Subject: [ovs-dev] [PATCH RFC ovn 1/3] northd: Use thread-local storage for logical flow matches. X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: ovs-dev-bounces@openvswitch.org Sender: "dev" For this commit, only the most trivial dynamic string matches have been replaced with a thread-local buffer. This prevents a great deal of memory allocations and frees. Follow-up commits will take care of some of the more complex uses of dynamic string matches. Signed-off-by: Mark Michelson --- northd/ovn-northd.c | 376 +++++++++++++++++++++----------------------- 1 file changed, 180 insertions(+), 196 deletions(-) diff --git a/northd/ovn-northd.c b/northd/ovn-northd.c index d872f6a3c..6b51d12de 100644 --- a/northd/ovn-northd.c +++ b/northd/ovn-northd.c @@ -56,6 +56,7 @@ #include "util.h" #include "uuid.h" #include "openvswitch/vlog.h" +#include "ovs-thread.h" VLOG_DEFINE_THIS_MODULE(ovn_northd); @@ -4083,6 +4084,16 @@ static bool use_parallel_build = true; static struct hashrow_locks lflow_locks; +DEFINE_STATIC_PER_THREAD_DATA(struct ds, match, DS_EMPTY_INITIALIZER); + +static struct ds * +match_get_clear(void) +{ + struct ds *match = match_get(); + ds_clear(match); + return match; +} + /* Adds a row with the specified contents to the Logical_Flow table. * Version to use when locking is required. */ @@ -4338,21 +4349,21 @@ static void build_port_security_nd(struct ovn_port *op, struct hmap *lflows, const struct ovsdb_idl_row *stage_hint) { - struct ds match = DS_EMPTY_INITIALIZER; + struct ds *match = match_get(); for (size_t i = 0; i < op->n_ps_addrs; i++) { struct lport_addresses *ps = &op->ps_addrs[i]; bool no_ip = !(ps->n_ipv4_addrs || ps->n_ipv6_addrs); - ds_clear(&match); + ds_clear(match); if (ps->n_ipv4_addrs || no_ip) { - ds_put_format(&match, + ds_put_format(match, "inport == %s && eth.src == %s && arp.sha == %s", op->json_key, ps->ea_s, ps->ea_s); if (ps->n_ipv4_addrs) { - ds_put_cstr(&match, " && arp.spa == {"); + ds_put_cstr(match, " && arp.spa == {"); for (size_t j = 0; j < ps->n_ipv4_addrs; j++) { /* When the netmask is applied, if the host portion is * non-zero, the host can only use the specified @@ -4360,38 +4371,37 @@ build_port_security_nd(struct ovn_port *op, struct hmap *lflows, * to use any address in the subnet. */ if (ps->ipv4_addrs[j].plen == 32 || ps->ipv4_addrs[j].addr & ~ps->ipv4_addrs[j].mask) { - ds_put_cstr(&match, ps->ipv4_addrs[j].addr_s); + ds_put_cstr(match, ps->ipv4_addrs[j].addr_s); } else { - ds_put_format(&match, "%s/%d", + ds_put_format(match, "%s/%d", ps->ipv4_addrs[j].network_s, ps->ipv4_addrs[j].plen); } - ds_put_cstr(&match, ", "); + ds_put_cstr(match, ", "); } - ds_chomp(&match, ' '); - ds_chomp(&match, ','); - ds_put_cstr(&match, "}"); + ds_chomp(match, ' '); + ds_chomp(match, ','); + ds_put_cstr(match, "}"); } ovn_lflow_add_with_hint(lflows, op->od, S_SWITCH_IN_PORT_SEC_ND, - 90, ds_cstr(&match), "next;", stage_hint); + 90, ds_cstr(match), "next;", stage_hint); } if (ps->n_ipv6_addrs || no_ip) { - ds_clear(&match); - ds_put_format(&match, "inport == %s && eth.src == %s", + ds_clear(match); + ds_put_format(match, "inport == %s && eth.src == %s", op->json_key, ps->ea_s); - build_port_security_ipv6_nd_flow(&match, ps->ea, ps->ipv6_addrs, + build_port_security_ipv6_nd_flow(match, ps->ea, ps->ipv6_addrs, ps->n_ipv6_addrs); ovn_lflow_add_with_hint(lflows, op->od, S_SWITCH_IN_PORT_SEC_ND, - 90, ds_cstr(&match), "next;", stage_hint); + 90, ds_cstr(match), "next;", stage_hint); } } - ds_clear(&match); - ds_put_format(&match, "inport == %s && (arp || nd)", op->json_key); + ds_clear(match); + ds_put_format(match, "inport == %s && (arp || nd)", op->json_key); ovn_lflow_add_with_hint(lflows, op->od, S_SWITCH_IN_PORT_SEC_ND, 80, - ds_cstr(&match), "drop;", stage_hint); - ds_destroy(&match); + ds_cstr(match), "drop;", stage_hint); } /** @@ -4432,7 +4442,7 @@ build_port_security_ip(enum ovn_pipeline pipeline, struct ovn_port *op, } if (ps->n_ipv4_addrs) { - struct ds match = DS_EMPTY_INITIALIZER; + struct ds *match = match_get_clear(); if (pipeline == P_IN) { /* Permit use of the unspecified address for DHCP discovery */ struct ds dhcp_match = DS_EMPTY_INITIALIZER; @@ -4446,11 +4456,11 @@ build_port_security_ip(enum ovn_pipeline pipeline, struct ovn_port *op, ds_cstr(&dhcp_match), "next;", stage_hint); ds_destroy(&dhcp_match); - ds_put_format(&match, "inport == %s && eth.src == %s" + ds_put_format(match, "inport == %s && eth.src == %s" " && ip4.src == {", op->json_key, ps->ea_s); } else { - ds_put_format(&match, "outport == %s && eth.dst == %s" + ds_put_format(match, "outport == %s && eth.dst == %s" " && ip4.dst == {255.255.255.255, 224.0.0.0/4, ", op->json_key, ps->ea_s); } @@ -4464,33 +4474,32 @@ build_port_security_ip(enum ovn_pipeline pipeline, struct ovn_port *op, */ if (ps->ipv4_addrs[j].plen == 32 || ps->ipv4_addrs[j].addr & ~mask) { - ds_put_format(&match, "%s", ps->ipv4_addrs[j].addr_s); + ds_put_format(match, "%s", ps->ipv4_addrs[j].addr_s); if (pipeline == P_OUT && ps->ipv4_addrs[j].plen != 32) { /* Host is also allowed to receive packets to the * broadcast address in the specified subnet. */ - ds_put_format(&match, ", %s", + ds_put_format(match, ", %s", ps->ipv4_addrs[j].bcast_s); } } else { /* host portion is zero */ - ds_put_format(&match, "%s/%d", ps->ipv4_addrs[j].network_s, + ds_put_format(match, "%s/%d", ps->ipv4_addrs[j].network_s, ps->ipv4_addrs[j].plen); } - ds_put_cstr(&match, ", "); + ds_put_cstr(match, ", "); } /* Replace ", " by "}". */ - ds_chomp(&match, ' '); - ds_chomp(&match, ','); - ds_put_cstr(&match, "}"); + ds_chomp(match, ' '); + ds_chomp(match, ','); + ds_put_cstr(match, "}"); ovn_lflow_add_with_hint(lflows, op->od, stage, 90, - ds_cstr(&match), "next;", + ds_cstr(match), "next;", stage_hint); - ds_destroy(&match); } if (ps->n_ipv6_addrs) { - struct ds match = DS_EMPTY_INITIALIZER; + struct ds *match = match_get_clear(); if (pipeline == P_IN) { /* Permit use of unspecified address for duplicate address * detection */ @@ -4506,15 +4515,14 @@ build_port_security_ip(enum ovn_pipeline pipeline, struct ovn_port *op, stage_hint); ds_destroy(&dad_match); } - ds_put_format(&match, "%s == %s && %s == %s", + ds_put_format(match, "%s == %s && %s == %s", port_direction, op->json_key, pipeline == P_IN ? "eth.src" : "eth.dst", ps->ea_s); - build_port_security_ipv6_flow(pipeline, &match, ps->ea, + build_port_security_ipv6_flow(pipeline, match, ps->ea, ps->ipv6_addrs, ps->n_ipv6_addrs); ovn_lflow_add_with_hint(lflows, op->od, stage, 90, - ds_cstr(&match), "next;", + ds_cstr(match), "next;", stage_hint); - ds_destroy(&match); } char *match = xasprintf("%s == %s && %s == %s && ip", @@ -5122,19 +5130,19 @@ build_empty_lb_event_flow(struct ovn_datapath *od, struct hmap *lflows, } bool ipv4 = IN6_IS_ADDR_V4MAPPED(&lb_vip->vip); - struct ds match = DS_EMPTY_INITIALIZER; + struct ds *match = match_get_clear(); char *meter = "", *action; if (meter_groups && shash_find(meter_groups, "event-elb")) { meter = "event-elb"; } - ds_put_format(&match, "ip%s.dst == %s && %s", + ds_put_format(match, "ip%s.dst == %s && %s", ipv4 ? "4": "6", lb_vip->vip_str, lb->protocol); char *vip = lb_vip->vip_str; if (lb_vip->vip_port) { - ds_put_format(&match, " && %s.dst == %u", lb->protocol, + ds_put_format(match, " && %s.dst == %u", lb->protocol, lb_vip->vip_port); vip = xasprintf("%s%s%s:%u", ipv4 ? "" : "[", lb_vip->vip_str, ipv4 ? "" : "]", lb_vip->vip_port); @@ -5147,9 +5155,8 @@ build_empty_lb_event_flow(struct ovn_datapath *od, struct hmap *lflows, event_to_string(OVN_EVENT_EMPTY_LB_BACKENDS), meter, vip, lb->protocol, UUID_ARGS(&lb->header_.uuid)); - ovn_lflow_add_with_hint(lflows, od, pl, 130, ds_cstr(&match), action, + ovn_lflow_add_with_hint(lflows, od, pl, 130, ds_cstr(match), action, &lb->header_); - ds_destroy(&match); if (lb_vip->vip_port) { free(vip); } @@ -5270,32 +5277,31 @@ build_pre_stateful(struct ovn_datapath *od, struct hmap *lflows) const char *lb_protocols[] = {"tcp", "udp", "sctp"}; struct ds actions = DS_EMPTY_INITIALIZER; - struct ds match = DS_EMPTY_INITIALIZER; + struct ds *match = match_get(); for (size_t i = 0; i < ARRAY_SIZE(lb_protocols); i++) { - ds_clear(&match); + ds_clear(match); ds_clear(&actions); - ds_put_format(&match, REGBIT_CONNTRACK_NAT" == 1 && ip4 && %s", + ds_put_format(match, REGBIT_CONNTRACK_NAT" == 1 && ip4 && %s", lb_protocols[i]); ds_put_format(&actions, REG_ORIG_DIP_IPV4 " = ip4.dst; " REG_ORIG_TP_DPORT " = %s.dst; ct_lb;", lb_protocols[i]); ovn_lflow_add(lflows, od, S_SWITCH_IN_PRE_STATEFUL, 120, - ds_cstr(&match), ds_cstr(&actions)); + ds_cstr(match), ds_cstr(&actions)); - ds_clear(&match); + ds_clear(match); ds_clear(&actions); - ds_put_format(&match, REGBIT_CONNTRACK_NAT" == 1 && ip6 && %s", + ds_put_format(match, REGBIT_CONNTRACK_NAT" == 1 && ip6 && %s", lb_protocols[i]); ds_put_format(&actions, REG_ORIG_DIP_IPV6 " = ip6.dst; " REG_ORIG_TP_DPORT " = %s.dst; ct_lb;", lb_protocols[i]); ovn_lflow_add(lflows, od, S_SWITCH_IN_PRE_STATEFUL, 120, - ds_cstr(&match), ds_cstr(&actions)); + ds_cstr(match), ds_cstr(&actions)); } ds_destroy(&actions); - ds_destroy(&match); ovn_lflow_add(lflows, od, S_SWITCH_IN_PRE_STATEFUL, 110, REGBIT_CONNTRACK_NAT" == 1", "ct_lb;"); @@ -5559,7 +5565,7 @@ consider_acl(struct hmap *lflows, struct ovn_datapath *od, &acl->header_); ds_destroy(&actions); } else { - struct ds match = DS_EMPTY_INITIALIZER; + struct ds *match = match_get_clear(); struct ds actions = DS_EMPTY_INITIALIZER; /* Commit the connection tracking entry if it's a new @@ -5574,14 +5580,14 @@ consider_acl(struct hmap *lflows, struct ovn_datapath *od, * by ct_commit in the "stateful" stage) to indicate that the * connection should be allowed to resume. */ - ds_put_format(&match, REGBIT_ACL_HINT_ALLOW_NEW " == 1 && (%s)", + ds_put_format(match, REGBIT_ACL_HINT_ALLOW_NEW " == 1 && (%s)", acl->match); ds_put_cstr(&actions, REGBIT_CONNTRACK_COMMIT" = 1; "); build_acl_log(&actions, acl, meter_groups); ds_put_cstr(&actions, "next;"); ovn_lflow_add_with_hint(lflows, od, stage, acl->priority + OVN_ACL_PRI_OFFSET, - ds_cstr(&match), + ds_cstr(match), ds_cstr(&actions), &acl->header_); @@ -5591,24 +5597,23 @@ consider_acl(struct hmap *lflows, struct ovn_datapath *od, * proceed to the next table. We use this to ensure that this * connection is still allowed by the currently defined * policy. Match untracked packets too. */ - ds_clear(&match); + ds_clear(match); ds_clear(&actions); - ds_put_format(&match, REGBIT_ACL_HINT_ALLOW " == 1 && (%s)", + ds_put_format(match, REGBIT_ACL_HINT_ALLOW " == 1 && (%s)", acl->match); build_acl_log(&actions, acl, meter_groups); ds_put_cstr(&actions, "next;"); ovn_lflow_add_with_hint(lflows, od, stage, acl->priority + OVN_ACL_PRI_OFFSET, - ds_cstr(&match), ds_cstr(&actions), + ds_cstr(match), ds_cstr(&actions), &acl->header_); - ds_destroy(&match); ds_destroy(&actions); } } else if (!strcmp(acl->action, "drop") || !strcmp(acl->action, "reject")) { - struct ds match = DS_EMPTY_INITIALIZER; + struct ds *match = match_get_clear(); struct ds actions = DS_EMPTY_INITIALIZER; /* The implementation of "drop" differs if stateful ACLs are in @@ -5618,17 +5623,17 @@ consider_acl(struct hmap *lflows, struct ovn_datapath *od, if (has_stateful) { /* If the packet is not tracked or not part of an established * connection, then we can simply reject/drop it. */ - ds_put_cstr(&match, REGBIT_ACL_HINT_DROP " == 1"); + ds_put_cstr(match, REGBIT_ACL_HINT_DROP " == 1"); if (!strcmp(acl->action, "reject")) { - build_reject_acl_rules(od, lflows, stage, acl, &match, + build_reject_acl_rules(od, lflows, stage, acl, match, &actions, &acl->header_, meter_groups); } else { - ds_put_format(&match, " && (%s)", acl->match); + ds_put_format(match, " && (%s)", acl->match); build_acl_log(&actions, acl, meter_groups); ds_put_cstr(&actions, "/* drop */"); ovn_lflow_add_with_hint(lflows, od, stage, acl->priority + OVN_ACL_PRI_OFFSET, - ds_cstr(&match), ds_cstr(&actions), + ds_cstr(match), ds_cstr(&actions), &acl->header_); } /* For an existing connection without ct_label set, we've @@ -5642,20 +5647,20 @@ consider_acl(struct hmap *lflows, struct ovn_datapath *od, * ct_commit() to the "stateful" stage, but since we're * rejecting/dropping the packet, we go ahead and do it here. */ - ds_clear(&match); + ds_clear(match); ds_clear(&actions); - ds_put_cstr(&match, REGBIT_ACL_HINT_BLOCK " == 1"); + ds_put_cstr(match, REGBIT_ACL_HINT_BLOCK " == 1"); ds_put_cstr(&actions, "ct_commit { ct_label.blocked = 1; }; "); if (!strcmp(acl->action, "reject")) { - build_reject_acl_rules(od, lflows, stage, acl, &match, + build_reject_acl_rules(od, lflows, stage, acl, match, &actions, &acl->header_, meter_groups); } else { - ds_put_format(&match, " && (%s)", acl->match); + ds_put_format(match, " && (%s)", acl->match); build_acl_log(&actions, acl, meter_groups); ds_put_cstr(&actions, "/* drop */"); ovn_lflow_add_with_hint(lflows, od, stage, acl->priority + OVN_ACL_PRI_OFFSET, - ds_cstr(&match), ds_cstr(&actions), + ds_cstr(match), ds_cstr(&actions), &acl->header_); } } else { @@ -5663,7 +5668,7 @@ consider_acl(struct hmap *lflows, struct ovn_datapath *od, * so a "reject/drop" ACL is simply the "reject/drop" * logical flow action in all cases. */ if (!strcmp(acl->action, "reject")) { - build_reject_acl_rules(od, lflows, stage, acl, &match, + build_reject_acl_rules(od, lflows, stage, acl, match, &actions, &acl->header_, meter_groups); } else { build_acl_log(&actions, acl, meter_groups); @@ -5674,7 +5679,6 @@ consider_acl(struct hmap *lflows, struct ovn_datapath *od, &acl->header_); } } - ds_destroy(&match); ds_destroy(&actions); } } @@ -5889,17 +5893,16 @@ build_acls(struct ovn_datapath *od, struct hmap *lflows, const char *lease_time = smap_get( &od->nbs->ports[i]->dhcpv4_options->options, "lease_time"); if (server_id && server_mac && lease_time) { - struct ds match = DS_EMPTY_INITIALIZER; + struct ds *match = match_get_clear(); const char *actions = has_stateful ? "ct_commit; next;" : "next;"; - ds_put_format(&match, "outport == \"%s\" && eth.src == %s " + ds_put_format(match, "outport == \"%s\" && eth.src == %s " "&& ip4.src == %s && udp && udp.src == 67 " "&& udp.dst == 68", od->nbs->ports[i]->name, server_mac, server_id); ovn_lflow_add_with_hint( - lflows, od, S_SWITCH_OUT_ACL, 34000, ds_cstr(&match), + lflows, od, S_SWITCH_OUT_ACL, 34000, ds_cstr(match), actions, &od->nbs->ports[i]->dhcpv4_options->header_); - ds_destroy(&match); } } @@ -5916,17 +5919,16 @@ build_acls(struct ovn_datapath *od, struct hmap *lflows, char server_ip[INET6_ADDRSTRLEN + 1]; ipv6_string_mapped(server_ip, &lla); - struct ds match = DS_EMPTY_INITIALIZER; + struct ds *match = match_get_clear(); const char *actions = has_stateful ? "ct_commit; next;" : "next;"; - ds_put_format(&match, "outport == \"%s\" && eth.src == %s " + ds_put_format(match, "outport == \"%s\" && eth.src == %s " "&& ip6.src == %s && udp && udp.src == 547 " "&& udp.dst == 546", od->nbs->ports[i]->name, server_mac, server_ip); ovn_lflow_add_with_hint( - lflows, od, S_SWITCH_OUT_ACL, 34000, ds_cstr(&match), + lflows, od, S_SWITCH_OUT_ACL, 34000, ds_cstr(match), actions, &od->nbs->ports[i]->dhcpv6_options->header_); - ds_destroy(&match); } } } @@ -6021,7 +6023,7 @@ build_lb_rules(struct ovn_datapath *od, struct hmap *lflows, struct ovn_northd_lb *lb) { struct ds action = DS_EMPTY_INITIALIZER; - struct ds match = DS_EMPTY_INITIALIZER; + struct ds *match = match_get(); for (size_t i = 0; i < lb->n_vips; i++) { struct ovn_lb_vip *lb_vip = &lb->vips[i]; @@ -6029,7 +6031,7 @@ build_lb_rules(struct ovn_datapath *od, struct hmap *lflows, const char *ip_match = NULL; ds_clear(&action); - ds_clear(&match); + ds_clear(match); /* Store the original destination IP to be used when generating * hairpin flows. @@ -6066,21 +6068,20 @@ build_lb_rules(struct ovn_datapath *od, struct hmap *lflows, build_lb_vip_actions(lb_vip, lb_vip_nb, &action, lb->selection_fields, true); - ds_put_format(&match, "ct.new && %s.dst == %s", ip_match, + ds_put_format(match, "ct.new && %s.dst == %s", ip_match, lb_vip->vip_str); if (lb_vip->vip_port) { - ds_put_format(&match, " && %s.dst == %d", proto, lb_vip->vip_port); + ds_put_format(match, " && %s.dst == %d", proto, lb_vip->vip_port); ovn_lflow_add_with_hint(lflows, od, S_SWITCH_IN_STATEFUL, 120, - ds_cstr(&match), ds_cstr(&action), + ds_cstr(match), ds_cstr(&action), &lb->nlb->header_); } else { ovn_lflow_add_with_hint(lflows, od, S_SWITCH_IN_STATEFUL, 110, - ds_cstr(&match), ds_cstr(&action), + ds_cstr(match), ds_cstr(&action), &lb->nlb->header_); } } ds_destroy(&action); - ds_destroy(&match); } static void @@ -6179,7 +6180,7 @@ build_fwd_group_lflows(struct ovn_datapath *od, struct hmap *lflows) { if (!(!od->nbs || !od->nbs->n_forwarding_groups)) { - struct ds match = DS_EMPTY_INITIALIZER; + struct ds *match = match_get_clear(); struct ds actions = DS_EMPTY_INITIALIZER; struct ds group_ports = DS_EMPTY_INITIALIZER; @@ -6191,7 +6192,7 @@ build_fwd_group_lflows(struct ovn_datapath *od, struct hmap *lflows) } /* ARP responder for the forwarding group's virtual IP */ - ds_put_format(&match, "arp.tpa == %s && arp.op == 1", + ds_put_format(match, "arp.tpa == %s && arp.op == 1", fwd_group->vip); ds_put_format(&actions, "eth.dst = eth.src; " @@ -6207,12 +6208,12 @@ build_fwd_group_lflows(struct ovn_datapath *od, struct hmap *lflows) fwd_group->vmac, fwd_group->vmac, fwd_group->vip); ovn_lflow_add_with_hint(lflows, od, S_SWITCH_IN_ARP_ND_RSP, 50, - ds_cstr(&match), ds_cstr(&actions), + ds_cstr(match), ds_cstr(&actions), &fwd_group->header_); /* L2 lookup for the forwarding group's virtual MAC */ - ds_clear(&match); - ds_put_format(&match, "eth.dst == %s", fwd_group->vmac); + ds_clear(match); + ds_put_format(match, "eth.dst == %s", fwd_group->vmac); /* Create a comma separated string of child ports */ ds_clear(&group_ports); @@ -6230,11 +6231,10 @@ build_fwd_group_lflows(struct ovn_datapath *od, struct hmap *lflows) ds_clear(&actions); ds_put_format(&actions, "fwd_group(%s);", ds_cstr(&group_ports)); ovn_lflow_add_with_hint(lflows, od, S_SWITCH_IN_L2_LKUP, 50, - ds_cstr(&match), ds_cstr(&actions), + ds_cstr(match), ds_cstr(&actions), &fwd_group->header_); } - ds_destroy(&match); ds_destroy(&actions); ds_destroy(&group_ports); } @@ -6390,7 +6390,7 @@ build_lswitch_rport_arp_req_self_orig_flow(struct ovn_port *op, { struct sset all_eth_addrs = SSET_INITIALIZER(&all_eth_addrs); struct ds eth_src = DS_EMPTY_INITIALIZER; - struct ds match = DS_EMPTY_INITIALIZER; + struct ds *match = match_get_clear(); sset_add(&all_eth_addrs, op->lrp_networks.ea_s); @@ -6445,15 +6445,14 @@ build_lswitch_rport_arp_req_self_orig_flow(struct ovn_port *op, ds_chomp(ð_src, ','); ds_put_cstr(ð_src, "}"); - ds_put_format(&match, "eth.src == %s && (arp.op == 1 || nd_ns)", + ds_put_format(match, "eth.src == %s && (arp.op == 1 || nd_ns)", ds_cstr(ð_src)); ovn_lflow_add_unique(lflows, od, S_SWITCH_IN_L2_LKUP, priority, - ds_cstr(&match), + ds_cstr(match), "outport = \""MC_FLOOD_L2"\"; output;"); sset_destroy(&all_eth_addrs); ds_destroy(ð_src); - ds_destroy(&match); } /* @@ -6470,7 +6469,7 @@ build_lswitch_rport_arp_req_flow_for_ip(struct sset *ips, struct hmap *lflows, const struct ovsdb_idl_row *stage_hint) { - struct ds match = DS_EMPTY_INITIALIZER; + struct ds *match = match_get_clear(); struct ds actions = DS_EMPTY_INITIALIZER; /* Packets received from VXLAN tunnels have already been through the @@ -6478,22 +6477,22 @@ build_lswitch_rport_arp_req_flow_for_ip(struct sset *ips, * multicast_group implementation (VXLAN packets skip table 32 which * delivers to patch ports) but we're bypassing multicast_groups. */ - ds_put_cstr(&match, FLAGBIT_NOT_VXLAN " && "); + ds_put_cstr(match, FLAGBIT_NOT_VXLAN " && "); if (addr_family == AF_INET) { - ds_put_cstr(&match, "arp.op == 1 && arp.tpa == { "); + ds_put_cstr(match, "arp.op == 1 && arp.tpa == { "); } else { - ds_put_cstr(&match, "nd_ns && nd.target == { "); + ds_put_cstr(match, "nd_ns && nd.target == { "); } const char *ip_address; SSET_FOR_EACH (ip_address, ips) { - ds_put_format(&match, "%s, ", ip_address); + ds_put_format(match, "%s, ", ip_address); } - ds_chomp(&match, ' '); - ds_chomp(&match, ','); - ds_put_cstr(&match, "}"); + ds_chomp(match, ' '); + ds_chomp(match, ','); + ds_put_cstr(match, "}"); /* Send a the packet to the router pipeline. If the switch has non-router * ports then flood it there as well. @@ -6503,16 +6502,15 @@ build_lswitch_rport_arp_req_flow_for_ip(struct sset *ips, "outport = \""MC_FLOOD_L2"\"; output;", patch_op->json_key); ovn_lflow_add_unique_with_hint(lflows, od, S_SWITCH_IN_L2_LKUP, - priority, ds_cstr(&match), + priority, ds_cstr(match), ds_cstr(&actions), stage_hint); } else { ds_put_format(&actions, "outport = %s; output;", patch_op->json_key); ovn_lflow_add_with_hint(lflows, od, S_SWITCH_IN_L2_LKUP, priority, - ds_cstr(&match), ds_cstr(&actions), + ds_cstr(match), ds_cstr(&actions), stage_hint); } - ds_destroy(&match); ds_destroy(&actions); } @@ -6645,7 +6643,7 @@ build_dhcpv4_options_flows(struct ovn_port *op, const char *json_key, bool is_external, struct hmap *lflows) { - struct ds match = DS_EMPTY_INITIALIZER; + struct ds *match = match_get(); for (size_t j = 0; j < lsp_addrs->n_ipv4_addrs; j++) { struct ds options_action = DS_EMPTY_INITIALIZER; @@ -6654,24 +6652,24 @@ build_dhcpv4_options_flows(struct ovn_port *op, if (build_dhcpv4_action( op, lsp_addrs->ipv4_addrs[j].addr, &options_action, &response_action, &ipv4_addr_match)) { - ds_clear(&match); + ds_clear(match); ds_put_format( - &match, "inport == %s && eth.src == %s && " + match, "inport == %s && eth.src == %s && " "ip4.src == 0.0.0.0 && ip4.dst == 255.255.255.255 && " "udp.src == 68 && udp.dst == 67", json_key, lsp_addrs->ea_s); if (is_external) { - ds_put_format(&match, " && is_chassis_resident(%s)", + ds_put_format(match, " && is_chassis_resident(%s)", op->json_key); } ovn_lflow_add_with_hint(lflows, op->od, S_SWITCH_IN_DHCP_OPTIONS, 100, - ds_cstr(&match), + ds_cstr(match), ds_cstr(&options_action), &op->nbsp->dhcpv4_options->header_); - ds_clear(&match); + ds_clear(match); /* Allow ip4.src = OFFER_IP and * ip4.dst = {SERVER_IP, 255.255.255.255} for the below * cases @@ -6681,38 +6679,38 @@ build_dhcpv4_options_flows(struct ovn_port *op, * broadcasting the DHCPREQUEST. */ ds_put_format( - &match, "inport == %s && eth.src == %s && " + match, "inport == %s && eth.src == %s && " "%s && udp.src == 68 && udp.dst == 67", json_key, lsp_addrs->ea_s, ds_cstr(&ipv4_addr_match)); if (is_external) { - ds_put_format(&match, " && is_chassis_resident(%s)", + ds_put_format(match, " && is_chassis_resident(%s)", op->json_key); } ovn_lflow_add_with_hint(lflows, op->od, S_SWITCH_IN_DHCP_OPTIONS, 100, - ds_cstr(&match), + ds_cstr(match), ds_cstr(&options_action), &op->nbsp->dhcpv4_options->header_); - ds_clear(&match); + ds_clear(match); /* If REGBIT_DHCP_OPTS_RESULT is set, it means the * put_dhcp_opts action is successful. */ ds_put_format( - &match, "inport == %s && eth.src == %s && " + match, "inport == %s && eth.src == %s && " "ip4 && udp.src == 68 && udp.dst == 67" " && "REGBIT_DHCP_OPTS_RESULT, json_key, lsp_addrs->ea_s); if (is_external) { - ds_put_format(&match, " && is_chassis_resident(%s)", + ds_put_format(match, " && is_chassis_resident(%s)", op->json_key); } ovn_lflow_add_with_hint(lflows, op->od, S_SWITCH_IN_DHCP_RESPONSE, 100, - ds_cstr(&match), + ds_cstr(match), ds_cstr(&response_action), &op->nbsp->dhcpv4_options->header_); ds_destroy(&options_action); @@ -6721,7 +6719,6 @@ build_dhcpv4_options_flows(struct ovn_port *op, break; } } - ds_destroy(&match); } static void @@ -6730,7 +6727,7 @@ build_dhcpv6_options_flows(struct ovn_port *op, const char *json_key, bool is_external, struct hmap *lflows) { - struct ds match = DS_EMPTY_INITIALIZER; + struct ds *match = match_get(); for (size_t j = 0; j < lsp_addrs->n_ipv6_addrs; j++) { struct ds options_action = DS_EMPTY_INITIALIZER; @@ -6738,30 +6735,30 @@ build_dhcpv6_options_flows(struct ovn_port *op, if (build_dhcpv6_action( op, &lsp_addrs->ipv6_addrs[j].addr, &options_action, &response_action)) { - ds_clear(&match); + ds_clear(match); ds_put_format( - &match, "inport == %s && eth.src == %s" + match, "inport == %s && eth.src == %s" " && ip6.dst == ff02::1:2 && udp.src == 546 &&" " udp.dst == 547", json_key, lsp_addrs->ea_s); if (is_external) { - ds_put_format(&match, " && is_chassis_resident(%s)", + ds_put_format(match, " && is_chassis_resident(%s)", op->json_key); } ovn_lflow_add_with_hint(lflows, op->od, S_SWITCH_IN_DHCP_OPTIONS, 100, - ds_cstr(&match), + ds_cstr(match), ds_cstr(&options_action), &op->nbsp->dhcpv6_options->header_); /* If REGBIT_DHCP_OPTS_RESULT is set to 1, it means the * put_dhcpv6_opts action is successful */ - ds_put_cstr(&match, " && "REGBIT_DHCP_OPTS_RESULT); + ds_put_cstr(match, " && "REGBIT_DHCP_OPTS_RESULT); ovn_lflow_add_with_hint(lflows, op->od, S_SWITCH_IN_DHCP_RESPONSE, 100, - ds_cstr(&match), + ds_cstr(match), ds_cstr(&response_action), &op->nbsp->dhcpv6_options->header_); ds_destroy(&options_action); @@ -6769,7 +6766,6 @@ build_dhcpv6_options_flows(struct ovn_port *op, break; } } - ds_destroy(&match); } static void @@ -6777,16 +6773,16 @@ build_drop_arp_nd_flows_for_unbound_router_ports(struct ovn_port *op, const struct ovn_port *port, struct hmap *lflows) { - struct ds match = DS_EMPTY_INITIALIZER; + struct ds *match = match_get(); for (size_t i = 0; i < op->n_lsp_addrs; i++) { for (size_t j = 0; j < op->od->n_router_ports; j++) { struct ovn_port *rp = op->od->router_ports[j]; for (size_t k = 0; k < rp->n_lsp_addrs; k++) { for (size_t l = 0; l < rp->lsp_addrs[k].n_ipv4_addrs; l++) { - ds_clear(&match); + ds_clear(match); ds_put_format( - &match, "inport == %s && eth.src == %s" + match, "inport == %s && eth.src == %s" " && !is_chassis_resident(%s)" " && arp.tpa == %s && arp.op == 1", port->json_key, @@ -6794,13 +6790,13 @@ build_drop_arp_nd_flows_for_unbound_router_ports(struct ovn_port *op, rp->lsp_addrs[k].ipv4_addrs[l].addr_s); ovn_lflow_add_with_hint(lflows, op->od, S_SWITCH_IN_EXTERNAL_PORT, - 100, ds_cstr(&match), "drop;", + 100, ds_cstr(match), "drop;", &op->nbsp->header_); } for (size_t l = 0; l < rp->lsp_addrs[k].n_ipv6_addrs; l++) { - ds_clear(&match); + ds_clear(match); ds_put_format( - &match, "inport == %s && eth.src == %s" + match, "inport == %s && eth.src == %s" " && !is_chassis_resident(%s)" " && nd_ns && ip6.dst == {%s, %s} && nd.target == %s", port->json_key, @@ -6810,13 +6806,13 @@ build_drop_arp_nd_flows_for_unbound_router_ports(struct ovn_port *op, rp->lsp_addrs[k].ipv6_addrs[l].addr_s); ovn_lflow_add_with_hint(lflows, op->od, S_SWITCH_IN_EXTERNAL_PORT, 100, - ds_cstr(&match), "drop;", + ds_cstr(match), "drop;", &op->nbsp->header_); } - ds_clear(&match); + ds_clear(match); ds_put_format( - &match, "inport == %s && eth.src == %s" + match, "inport == %s && eth.src == %s" " && eth.dst == %s" " && !is_chassis_resident(%s)", port->json_key, @@ -6824,12 +6820,11 @@ build_drop_arp_nd_flows_for_unbound_router_ports(struct ovn_port *op, op->json_key); ovn_lflow_add_with_hint(lflows, op->od, S_SWITCH_IN_EXTERNAL_PORT, - 100, ds_cstr(&match), "drop;", + 100, ds_cstr(match), "drop;", &op->nbsp->header_); } } } - ds_destroy(&match); } static bool @@ -6844,7 +6839,6 @@ build_lswitch_flows(struct hmap *datapaths, struct hmap *lflows) /* This flow table structure is documented in ovn-northd(8), so please * update ovn-northd.8.xml if you change anything. */ - struct ds match = DS_EMPTY_INITIALIZER; struct ds actions = DS_EMPTY_INITIALIZER; struct ovn_datapath *od; @@ -6869,7 +6863,6 @@ build_lswitch_flows(struct hmap *datapaths, struct hmap *lflows) "output;"); } - ds_destroy(&match); ds_destroy(&actions); } @@ -7870,7 +7863,7 @@ build_routing_policy_flow(struct hmap *lflows, struct ovn_datapath *od, const struct nbrec_logical_router_policy *rule, const struct ovsdb_idl_row *stage_hint) { - struct ds match = DS_EMPTY_INITIALIZER; + struct ds *match = match_get_clear(); struct ds actions = DS_EMPTY_INITIALIZER; if (!strcmp(rule->action, "reroute")) { @@ -7921,11 +7914,10 @@ build_routing_policy_flow(struct hmap *lflows, struct ovn_datapath *od, } ds_put_cstr(&actions, REG_ECMP_GROUP_ID" = 0; next;"); } - ds_put_format(&match, "%s", rule->match); + ds_put_format(match, "%s", rule->match); ovn_lflow_add_with_hint(lflows, od, S_ROUTER_IN_POLICY, rule->priority, - ds_cstr(&match), ds_cstr(&actions), stage_hint); - ds_destroy(&match); + ds_cstr(match), ds_cstr(&actions), stage_hint); ds_destroy(&actions); } @@ -7958,7 +7950,7 @@ build_ecmp_routing_policy_flows(struct hmap *lflows, struct ovn_datapath *od, } } - struct ds match = DS_EMPTY_INITIALIZER; + struct ds *match = match_get(); struct ds actions = DS_EMPTY_INITIALIZER; for (size_t i = 0; i < rule->n_nexthops; i++) { @@ -7999,12 +7991,12 @@ build_ecmp_routing_policy_flows(struct hmap *lflows, struct ovn_datapath *od, out_port->lrp_networks.ea_s, out_port->json_key); - ds_clear(&match); - ds_put_format(&match, REG_ECMP_GROUP_ID" == %"PRIu16" && " + ds_clear(match); + ds_put_format(match, REG_ECMP_GROUP_ID" == %"PRIu16" && " REG_ECMP_MEMBER_ID" == %"PRIuSIZE, ecmp_group_id, i + 1); ovn_lflow_add_with_hint(lflows, od, S_ROUTER_IN_POLICY_ECMP, - 100, ds_cstr(&match), + 100, ds_cstr(match), ds_cstr(&actions), &rule->header_); } @@ -8026,7 +8018,6 @@ build_ecmp_routing_policy_flows(struct hmap *lflows, struct ovn_datapath *od, ds_cstr(&actions), &rule->header_); cleanup: - ds_destroy(&match); ds_destroy(&actions); } @@ -8390,7 +8381,7 @@ add_ecmp_symmetric_reply_flows(struct hmap *lflows, struct ds *route_match) { const struct nbrec_logical_router_static_route *st_route = route->route; - struct ds match = DS_EMPTY_INITIALIZER; + struct ds *match = match_get_clear(); struct ds actions = DS_EMPTY_INITIALIZER; struct ds ecmp_reply = DS_EMPTY_INITIALIZER; char *cidr = normalize_v46_prefix(&route->prefix, route->plen); @@ -8398,14 +8389,14 @@ add_ecmp_symmetric_reply_flows(struct hmap *lflows, /* If symmetric ECMP replies are enabled, then packets that arrive over * an ECMP route need to go through conntrack. */ - ds_put_format(&match, "inport == %s && ip%s.%s == %s", + ds_put_format(match, "inport == %s && ip%s.%s == %s", out_port->json_key, IN6_IS_ADDR_V4MAPPED(&route->prefix) ? "4" : "6", route->is_src_route ? "dst" : "src", cidr); free(cidr); ovn_lflow_add_with_hint(lflows, od, S_ROUTER_IN_DEFRAG, 100, - ds_cstr(&match), "ct_next;", + ds_cstr(match), "ct_next;", &st_route->header_); /* And packets that go out over an ECMP route need conntrack */ @@ -8419,13 +8410,13 @@ add_ecmp_symmetric_reply_flows(struct hmap *lflows, * NOTE: we purposely are not clearing match before this * ds_put_cstr() call. The previous contents are needed. */ - ds_put_cstr(&match, " && (ct.new && !ct.est)"); + ds_put_cstr(match, " && (ct.new && !ct.est)"); ds_put_format(&actions, "ct_commit { ct_label.ecmp_reply_eth = eth.src;" " ct_label.ecmp_reply_port = %" PRId64 ";}; next;", out_port->sb->tunnel_key); ovn_lflow_add_with_hint(lflows, od, S_ROUTER_IN_ECMP_STATEFUL, 100, - ds_cstr(&match), ds_cstr(&actions), + ds_cstr(match), ds_cstr(&actions), &st_route->header_); /* Bypass ECMP selection if we already have ct_label information @@ -8433,8 +8424,8 @@ add_ecmp_symmetric_reply_flows(struct hmap *lflows, */ ds_put_format(&ecmp_reply, "ct.rpl && ct_label.ecmp_reply_port == %" PRId64, out_port->sb->tunnel_key); - ds_clear(&match); - ds_put_format(&match, "%s && %s", ds_cstr(&ecmp_reply), + ds_clear(match); + ds_put_format(match, "%s && %s", ds_cstr(&ecmp_reply), ds_cstr(route_match)); ds_clear(&actions); ds_put_format(&actions, "ip.ttl--; flags.loopback = 1; " @@ -8443,7 +8434,7 @@ add_ecmp_symmetric_reply_flows(struct hmap *lflows, IN6_IS_ADDR_V4MAPPED(&route->prefix) ? "" : "xx", port_ip, out_port->json_key); ovn_lflow_add_with_hint(lflows, od, S_ROUTER_IN_IP_ROUTING, 300, - ds_cstr(&match), ds_cstr(&actions), + ds_cstr(match), ds_cstr(&actions), &st_route->header_); /* Egress reply traffic for symmetric ECMP routes skips router policies. */ @@ -8456,7 +8447,6 @@ add_ecmp_symmetric_reply_flows(struct hmap *lflows, 200, ds_cstr(&ecmp_reply), action, &st_route->header_); - ds_destroy(&match); ds_destroy(&actions); ds_destroy(&ecmp_reply); } @@ -8497,7 +8487,7 @@ build_ecmp_route_flow(struct hmap *lflows, struct ovn_datapath *od, ds_cstr(&route_match), ds_cstr(&actions)); /* Add per member flow */ - struct ds match = DS_EMPTY_INITIALIZER; + struct ds *match = match_get(); struct sset visited_ports = SSET_INITIALIZER(&visited_ports); LIST_FOR_EACH (er, list_node, &eg->route_list) { const struct parsed_route *route_ = er->route; @@ -8518,8 +8508,8 @@ build_ecmp_route_flow(struct hmap *lflows, struct ovn_datapath *od, add_ecmp_symmetric_reply_flows(lflows, od, lrp_addr_s, out_port, route_, &route_match); } - ds_clear(&match); - ds_put_format(&match, REG_ECMP_GROUP_ID" == %"PRIu16" && " + ds_clear(match); + ds_put_format(match, REG_ECMP_GROUP_ID" == %"PRIu16" && " REG_ECMP_MEMBER_ID" == %"PRIu16, eg->id, er->id); ds_clear(&actions); @@ -8535,11 +8525,10 @@ build_ecmp_route_flow(struct hmap *lflows, struct ovn_datapath *od, out_port->lrp_networks.ea_s, out_port->json_key); ovn_lflow_add_with_hint(lflows, od, S_ROUTER_IN_IP_ROUTING_ECMP, 100, - ds_cstr(&match), ds_cstr(&actions), + ds_cstr(match), ds_cstr(&actions), &route->header_); } sset_destroy(&visited_ports); - ds_destroy(&match); ds_destroy(&route_match); ds_destroy(&actions); } @@ -8552,7 +8541,7 @@ add_route(struct hmap *lflows, struct ovn_datapath *od, bool is_discard_route) { bool is_ipv4 = strchr(network_s, '.') ? true : false; - struct ds match = DS_EMPTY_INITIALIZER; + struct ds *match = match_get_clear(); uint16_t priority; const struct ovn_port *op_inport = NULL; @@ -8565,7 +8554,7 @@ add_route(struct hmap *lflows, struct ovn_datapath *od, } } build_route_match(op_inport, network_s, plen, is_src_route, is_ipv4, - &match, &priority); + match, &priority); struct ds common_actions = DS_EMPTY_INITIALIZER; struct ds actions = DS_EMPTY_INITIALIZER; @@ -8593,15 +8582,14 @@ add_route(struct hmap *lflows, struct ovn_datapath *od, } ovn_lflow_add_with_hint(lflows, od, S_ROUTER_IN_IP_ROUTING, priority, - ds_cstr(&match), ds_cstr(&actions), + ds_cstr(match), ds_cstr(&actions), stage_hint); if (op && op->has_bfd) { - ds_put_format(&match, " && udp.dst == 3784"); + ds_put_format(match, " && udp.dst == 3784"); ovn_lflow_add_with_hint(lflows, op->od, S_ROUTER_IN_IP_ROUTING, - priority + 1, ds_cstr(&match), + priority + 1, ds_cstr(match), ds_cstr(&common_actions), stage_hint); } - ds_destroy(&match); ds_destroy(&common_actions); ds_destroy(&actions); } @@ -9224,7 +9212,7 @@ build_lrouter_port_nat_arp_nd_flow(struct ovn_port *op, { struct lport_addresses *ext_addrs = &nat_entry->ext_addrs; const struct nbrec_nat *nat = nat_entry->nb; - struct ds match = DS_EMPTY_INITIALIZER; + struct ds *match = match_get_clear(); /* Mac address to use when replying to ARP/NS. */ const char *mac_s = REG_INPORT_ETH_ADDR; @@ -9240,7 +9228,7 @@ build_lrouter_port_nat_arp_nd_flow(struct ovn_port *op, * resident, so that upstream MAC learning points to the * correct chassis. Also need to avoid generation of * multiple ARP responses from different chassis. */ - ds_put_format(&match, "is_chassis_resident(\"%s\")", + ds_put_format(match, "is_chassis_resident(\"%s\")", nat->logical_port); } else { mac_s = REG_INPORT_ETH_ADDR; @@ -9250,7 +9238,7 @@ build_lrouter_port_nat_arp_nd_flow(struct ovn_port *op, * Also need to avoid generation of multiple ARP responses * from different chassis. */ if (op->od->l3redirect_port) { - ds_put_format(&match, "is_chassis_resident(%s)", + ds_put_format(match, "is_chassis_resident(%s)", op->od->l3redirect_port->json_key); } } @@ -9262,7 +9250,7 @@ build_lrouter_port_nat_arp_nd_flow(struct ovn_port *op, build_lrouter_nd_flow(op->od, op, "nd_na", ext_addrs->ipv6_addrs[0].addr_s, ext_addrs->ipv6_addrs[0].sn_addr_s, - mac_s, &match, false, 92, + mac_s, match, false, 92, &nat->header_, lflows); build_lrouter_nd_flow(op->od, op, "nd_na", ext_addrs->ipv6_addrs[0].addr_s, @@ -9272,15 +9260,13 @@ build_lrouter_port_nat_arp_nd_flow(struct ovn_port *op, } else { build_lrouter_arp_flow(op->od, op, ext_addrs->ipv4_addrs[0].addr_s, - mac_s, &match, false, 92, + mac_s, match, false, 92, &nat->header_, lflows); build_lrouter_arp_flow(op->od, op, ext_addrs->ipv4_addrs[0].addr_s, mac_s, NULL, true, 91, &nat->header_, lflows); } - - ds_destroy(&match); } static void @@ -9347,24 +9333,23 @@ build_lrouter_force_snat_flows(struct hmap *lflows, struct ovn_datapath *od, const char *ip_version, const char *ip_addr, const char *context) { - struct ds match = DS_EMPTY_INITIALIZER; + struct ds *match = match_get_clear(); struct ds actions = DS_EMPTY_INITIALIZER; - ds_put_format(&match, "ip%s && ip%s.dst == %s", + ds_put_format(match, "ip%s && ip%s.dst == %s", ip_version, ip_version, ip_addr); ovn_lflow_add(lflows, od, S_ROUTER_IN_UNSNAT, 110, - ds_cstr(&match), "ct_snat;"); + ds_cstr(match), "ct_snat;"); /* Higher priority rules to force SNAT with the IP addresses * configured in the Gateway router. This only takes effect * when the packet has already been DNATed or load balanced once. */ - ds_clear(&match); - ds_put_format(&match, "flags.force_snat_for_%s == 1 && ip%s", + ds_clear(match); + ds_put_format(match, "flags.force_snat_for_%s == 1 && ip%s", context, ip_version); ds_put_format(&actions, "ct_snat(%s);", ip_addr); ovn_lflow_add(lflows, od, S_ROUTER_OUT_SNAT, 100, - ds_cstr(&match), ds_cstr(&actions)); + ds_cstr(match), ds_cstr(&actions)); - ds_destroy(&match); ds_destroy(&actions); } @@ -9448,42 +9433,41 @@ build_lrouter_bfd_flows(struct hmap *lflows, struct ovn_port *op) } struct ds ip_list = DS_EMPTY_INITIALIZER; - struct ds match = DS_EMPTY_INITIALIZER; + struct ds *match = match_get_clear(); if (op->lrp_networks.n_ipv4_addrs) { op_put_v4_networks(&ip_list, op, false); - ds_put_format(&match, "ip4.src == %s && udp.dst == 3784", + ds_put_format(match, "ip4.src == %s && udp.dst == 3784", ds_cstr(&ip_list)); ovn_lflow_add_with_hint(lflows, op->od, S_ROUTER_IN_IP_INPUT, 110, - ds_cstr(&match), "next; ", + ds_cstr(match), "next; ", &op->nbrp->header_); - ds_clear(&match); - ds_put_format(&match, "ip4.dst == %s && udp.dst == 3784", + ds_clear(match); + ds_put_format(match, "ip4.dst == %s && udp.dst == 3784", ds_cstr(&ip_list)); ovn_lflow_add_with_hint(lflows, op->od, S_ROUTER_IN_IP_INPUT, 110, - ds_cstr(&match), "handle_bfd_msg(); ", + ds_cstr(match), "handle_bfd_msg(); ", &op->nbrp->header_); } if (op->lrp_networks.n_ipv6_addrs) { ds_clear(&ip_list); - ds_clear(&match); + ds_clear(match); op_put_v6_networks(&ip_list, op); - ds_put_format(&match, "ip6.src == %s && udp.dst == 3784", + ds_put_format(match, "ip6.src == %s && udp.dst == 3784", ds_cstr(&ip_list)); ovn_lflow_add_with_hint(lflows, op->od, S_ROUTER_IN_IP_INPUT, 110, - ds_cstr(&match), "next; ", + ds_cstr(match), "next; ", &op->nbrp->header_); - ds_clear(&match); - ds_put_format(&match, "ip6.dst == %s && udp.dst == 3784", + ds_clear(match); + ds_put_format(match, "ip6.dst == %s && udp.dst == 3784", ds_cstr(&ip_list)); ovn_lflow_add_with_hint(lflows, op->od, S_ROUTER_IN_IP_INPUT, 110, - ds_cstr(&match), "handle_bfd_msg(); ", + ds_cstr(match), "handle_bfd_msg(); ", &op->nbrp->header_); } ds_destroy(&ip_list); - ds_destroy(&match); } /* Logical router ingress Table 0: L2 Admission Control From patchwork Wed Jun 16 17:56:10 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mark Michelson X-Patchwork-Id: 1493019 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=openvswitch.org (client-ip=140.211.166.138; helo=smtp1.osuosl.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=Xm6c41Dn; dkim-atps=neutral Received: from smtp1.osuosl.org (smtp1.osuosl.org [140.211.166.138]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4G4tCv1D9Nz9sXN for ; Thu, 17 Jun 2021 03:56:26 +1000 (AEST) Received: from localhost (localhost [127.0.0.1]) by smtp1.osuosl.org (Postfix) with ESMTP id 36AEF83C44; Wed, 16 Jun 2021 17:56:24 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from smtp1.osuosl.org ([127.0.0.1]) by localhost (smtp1.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id pkPeGQGDcO5Q; Wed, 16 Jun 2021 17:56:22 +0000 (UTC) Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56]) by smtp1.osuosl.org (Postfix) with ESMTPS id DACB783B4D; Wed, 16 Jun 2021 17:56:21 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id AC26CC000D; Wed, 16 Jun 2021 17:56:21 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@lists.linuxfoundation.org Received: from smtp4.osuosl.org (smtp4.osuosl.org [IPv6:2605:bc80:3010::137]) by lists.linuxfoundation.org (Postfix) with ESMTP id C9CDBC000B for ; Wed, 16 Jun 2021 17:56:20 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by smtp4.osuosl.org (Postfix) with ESMTP id ADBF8405E6 for ; Wed, 16 Jun 2021 17:56:20 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Authentication-Results: smtp4.osuosl.org (amavisd-new); dkim=pass (1024-bit key) header.d=redhat.com Received: from smtp4.osuosl.org ([127.0.0.1]) by localhost (smtp4.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id 8kWe94CtZb3q for ; Wed, 16 Jun 2021 17:56:18 +0000 (UTC) X-Greylist: domain auto-whitelisted by SQLgrey-1.8.0 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [216.205.24.124]) by smtp4.osuosl.org (Postfix) with ESMTPS id 80A8340E43 for ; Wed, 16 Jun 2021 17:56:18 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1623866176; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=QV9GQxEevEvoThyVy6/yQY8SA5vJlwdr4/pMdnrSems=; b=Xm6c41Dn4MUzPfSVzuffYlfCNh4W5vkYYZr7ue8DQLzMd2aS0zkRzzrTq4cMy10qZrRUq3 1OiiylQgZa5Ei2xhR3FxlmlUqV9BnkKDjeqor1IAFKAdoAsNFTISkx2FeMYkxLmQKmIhWX Mwu5vZtZ52j60PAiOmlD+NNxN9WDzIU= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-41--vUkfn7uMQm4VoGjlnDddQ-1; Wed, 16 Jun 2021 13:56:15 -0400 X-MC-Unique: -vUkfn7uMQm4VoGjlnDddQ-1 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 93CE5100CEE6 for ; Wed, 16 Jun 2021 17:56:14 +0000 (UTC) Received: from localhost.localdomain.com (ovpn-115-92.rdu2.redhat.com [10.10.115.92]) by smtp.corp.redhat.com (Postfix) with ESMTP id 40E8F6090F for ; Wed, 16 Jun 2021 17:56:14 +0000 (UTC) From: Mark Michelson To: dev@openvswitch.org Date: Wed, 16 Jun 2021 13:56:10 -0400 Message-Id: <20210616175611.597915-3-mmichels@redhat.com> In-Reply-To: <20210616175611.597915-1-mmichels@redhat.com> References: <20210616175611.597915-1-mmichels@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.13 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=mmichels@redhat.com X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Subject: [ovs-dev] [PATCH RFC ovn 2/3] northd: Do some of the more complex match dynamic string alterations. X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: ovs-dev-bounces@openvswitch.org Sender: "dev" Signed-off-by: Mark Michelson --- northd/ovn-northd.c | 223 ++++++++++++++++++++++---------------------- 1 file changed, 111 insertions(+), 112 deletions(-) diff --git a/northd/ovn-northd.c b/northd/ovn-northd.c index 6b51d12de..59e3c5f84 100644 --- a/northd/ovn-northd.c +++ b/northd/ovn-northd.c @@ -4441,21 +4441,20 @@ build_port_security_ip(enum ovn_pipeline pipeline, struct ovn_port *op, continue; } + struct ds *match = match_get_clear(); if (ps->n_ipv4_addrs) { - struct ds *match = match_get_clear(); if (pipeline == P_IN) { /* Permit use of the unspecified address for DHCP discovery */ - struct ds dhcp_match = DS_EMPTY_INITIALIZER; - ds_put_format(&dhcp_match, "inport == %s" + ds_put_format(match, "inport == %s" " && eth.src == %s" " && ip4.src == 0.0.0.0" " && ip4.dst == 255.255.255.255" " && udp.src == 68 && udp.dst == 67", op->json_key, ps->ea_s); ovn_lflow_add_with_hint(lflows, op->od, stage, 90, - ds_cstr(&dhcp_match), "next;", + ds_cstr(match), "next;", stage_hint); - ds_destroy(&dhcp_match); + ds_clear(match); ds_put_format(match, "inport == %s && eth.src == %s" " && ip4.src == {", op->json_key, ps->ea_s); @@ -4498,22 +4497,21 @@ build_port_security_ip(enum ovn_pipeline pipeline, struct ovn_port *op, stage_hint); } + ds_clear(match); if (ps->n_ipv6_addrs) { - struct ds *match = match_get_clear(); if (pipeline == P_IN) { /* Permit use of unspecified address for duplicate address * detection */ - struct ds dad_match = DS_EMPTY_INITIALIZER; - ds_put_format(&dad_match, "inport == %s" + ds_put_format(match, "inport == %s" " && eth.src == %s" " && ip6.src == ::" " && ip6.dst == ff02::/16" " && icmp6.type == {131, 135, 143}", op->json_key, ps->ea_s); ovn_lflow_add_with_hint(lflows, op->od, stage, 90, - ds_cstr(&dad_match), "next;", + ds_cstr(match), "next;", stage_hint); - ds_destroy(&dad_match); + ds_clear(match); } ds_put_format(match, "%s == %s && %s == %s", port_direction, op->json_key, @@ -4525,13 +4523,13 @@ build_port_security_ip(enum ovn_pipeline pipeline, struct ovn_port *op, stage_hint); } - char *match = xasprintf("%s == %s && %s == %s && ip", - port_direction, op->json_key, - pipeline == P_IN ? "eth.src" : "eth.dst", - ps->ea_s); - ovn_lflow_add_with_hint(lflows, op->od, stage, 80, match, "drop;", - stage_hint); - free(match); + ds_clear(match); + ds_put_format(match, "%s == %s && %s == %s && ip", + port_direction, op->json_key, + pipeline == P_IN ? "eth.src" : "eth.dst", + ps->ea_s); + ovn_lflow_add_with_hint(lflows, op->od, stage, 80, ds_cstr(match), + "drop;", stage_hint); } } @@ -4981,20 +4979,17 @@ skip_port_from_conntrack(struct ovn_datapath *od, struct ovn_port *op, * know about the connection, as the icmp request went through the logical * router on hostA, not hostB. This would only work with distributed * conntrack state across all chassis. */ - struct ds match_in = DS_EMPTY_INITIALIZER; - struct ds match_out = DS_EMPTY_INITIALIZER; + struct ds *match = match_get_clear(); - ds_put_format(&match_in, "ip && inport == %s", op->json_key); - ds_put_format(&match_out, "ip && outport == %s", op->json_key); + ds_put_format(match, "ip && inport == %s", op->json_key); ovn_lflow_add_with_hint(lflows, od, in_stage, priority, - ds_cstr(&match_in), "next;", + ds_cstr(match), "next;", &op->nbsp->header_); + ds_clear(match); + ds_put_format(match, "ip && outport == %s", op->json_key); ovn_lflow_add_with_hint(lflows, od, out_stage, priority, - ds_cstr(&match_out), "next;", + ds_cstr(match), "next;", &op->nbsp->header_); - - ds_destroy(&match_in); - ds_destroy(&match_out); } static void @@ -5494,11 +5489,10 @@ build_acl_log(struct ds *actions, const struct nbrec_acl *acl, static void build_reject_acl_rules(struct ovn_datapath *od, struct hmap *lflows, enum ovn_stage stage, struct nbrec_acl *acl, - struct ds *extra_match, struct ds *extra_actions, + struct ds *match, struct ds *extra_actions, const struct ovsdb_idl_row *stage_hint, const struct shash *meter_groups) { - struct ds match = DS_EMPTY_INITIALIZER; struct ds actions = DS_EMPTY_INITIALIZER; bool ingress = (stage == S_SWITCH_IN_ACL); @@ -5509,10 +5503,10 @@ build_reject_acl_rules(struct ovn_datapath *od, struct hmap *lflows, : ovn_stage_get_table(S_SWITCH_IN_L2_LKUP)); build_acl_log(&actions, acl, meter_groups); - if (extra_match->length > 0) { - ds_put_format(&match, "(%s) && ", extra_match->string); + if (match->length > 0) { + ds_put_cstr(match, " && "); } - ds_put_cstr(&match, acl->match); + ds_put_cstr(match, acl->match); if (extra_actions->length > 0) { ds_put_format(&actions, "%s ", extra_actions->string); @@ -5524,10 +5518,9 @@ build_reject_acl_rules(struct ovn_datapath *od, struct hmap *lflows, "outport <-> inport; %s };", next_action); ovn_lflow_add_with_hint(lflows, od, stage, acl->priority + OVN_ACL_PRI_OFFSET, - ds_cstr(&match), ds_cstr(&actions), stage_hint); + ds_cstr(match), ds_cstr(&actions), stage_hint); free(next_action); - ds_destroy(&match); ds_destroy(&actions); } @@ -5623,7 +5616,7 @@ consider_acl(struct hmap *lflows, struct ovn_datapath *od, if (has_stateful) { /* If the packet is not tracked or not part of an established * connection, then we can simply reject/drop it. */ - ds_put_cstr(match, REGBIT_ACL_HINT_DROP " == 1"); + ds_put_cstr(match, "(" REGBIT_ACL_HINT_DROP " == 1)"); if (!strcmp(acl->action, "reject")) { build_reject_acl_rules(od, lflows, stage, acl, match, &actions, &acl->header_, meter_groups); @@ -5649,7 +5642,7 @@ consider_acl(struct hmap *lflows, struct ovn_datapath *od, */ ds_clear(match); ds_clear(&actions); - ds_put_cstr(match, REGBIT_ACL_HINT_BLOCK " == 1"); + ds_put_cstr(match, "(" REGBIT_ACL_HINT_BLOCK " == 1)"); ds_put_cstr(&actions, "ct_commit { ct_label.blocked = 1; }; "); if (!strcmp(acl->action, "reject")) { build_reject_acl_rules(od, lflows, stage, acl, match, @@ -8690,8 +8683,8 @@ static void add_router_lb_flow(struct hmap *lflows, struct ovn_datapath *od, struct ds *match, struct ds *actions, int priority, enum lb_snat_type snat_type, struct ovn_lb_vip *lb_vip, - const char *proto, struct nbrec_load_balancer *lb, - struct shash *meter_groups, struct sset *nat_entries) + struct nbrec_load_balancer *lb, + struct shash *meter_groups) { build_empty_lb_event_flow(od, lflows, lb_vip, lb, S_ROUTER_IN_DNAT, meter_groups); @@ -8725,7 +8718,15 @@ add_router_lb_flow(struct hmap *lflows, struct ovn_datapath *od, free(new_match); free(est_match); +} +static void +add_router_lb_undnat_unsnat_flows(struct hmap *lflows, struct ovn_datapath *od, + enum lb_snat_type snat_type, + struct ovn_lb_vip *lb_vip, const char *proto, + struct nbrec_load_balancer *lb, + struct sset *nat_entries) +{ const char *ip_match = NULL; if (IN6_IS_ADDR_V4MAPPED(&lb_vip->vip)) { ip_match = "ip4"; @@ -8733,6 +8734,8 @@ add_router_lb_flow(struct hmap *lflows, struct ovn_datapath *od, ip_match = "ip6"; } + struct ds *match = match_get_clear(); + if (sset_contains(nat_entries, lb_vip->vip_str)) { /* The load balancer vip is also present in the NAT entries. * So add a high priority lflow to advance the the packet @@ -8745,18 +8748,15 @@ add_router_lb_flow(struct hmap *lflows, struct ovn_datapath *od, * unsnat stage, the conntrack flags are not set properly, and * it doesn't hit the established state flows in * S_ROUTER_IN_DNAT stage. */ - struct ds unsnat_match = DS_EMPTY_INITIALIZER; - ds_put_format(&unsnat_match, "%s && %s.dst == %s && %s", + ds_put_format(match, "%s && %s.dst == %s && %s", ip_match, ip_match, lb_vip->vip_str, proto); if (lb_vip->vip_port) { - ds_put_format(&unsnat_match, " && %s.dst == %d", proto, + ds_put_format(match, " && %s.dst == %d", proto, lb_vip->vip_port); } ovn_lflow_add_with_hint(lflows, od, S_ROUTER_IN_UNSNAT, 120, - ds_cstr(&unsnat_match), "next;", &lb->header_); - - ds_destroy(&unsnat_match); + ds_cstr(match), "next;", &lb->header_); } if (!od->l3dgw_port || !od->l3redirect_port || !lb_vip->n_backends) { @@ -8767,43 +8767,41 @@ add_router_lb_flow(struct hmap *lflows, struct ovn_datapath *od, * the router egress pipleine stage - S_ROUTER_OUT_UNDNAT if the logical * router has a gateway router port associated. */ - struct ds undnat_match = DS_EMPTY_INITIALIZER; - ds_put_format(&undnat_match, "%s && (", ip_match); + ds_clear(match); + ds_put_format(match, "%s && (", ip_match); for (size_t i = 0; i < lb_vip->n_backends; i++) { struct ovn_lb_backend *backend = &lb_vip->backends[i]; - ds_put_format(&undnat_match, "(%s.src == %s", ip_match, + ds_put_format(match, "(%s.src == %s", ip_match, backend->ip_str); if (backend->port) { - ds_put_format(&undnat_match, " && %s.src == %d) || ", + ds_put_format(match, " && %s.src == %d) || ", proto, backend->port); } else { - ds_put_cstr(&undnat_match, ") || "); + ds_put_cstr(match, ") || "); } } - ds_chomp(&undnat_match, ' '); - ds_chomp(&undnat_match, '|'); - ds_chomp(&undnat_match, '|'); - ds_chomp(&undnat_match, ' '); - ds_put_format(&undnat_match, ") && outport == %s && " + ds_chomp(match, ' '); + ds_chomp(match, '|'); + ds_chomp(match, '|'); + ds_chomp(match, ' '); + ds_put_format(match, ") && outport == %s && " "is_chassis_resident(%s)", od->l3dgw_port->json_key, od->l3redirect_port->json_key); if (snat_type == FORCE_SNAT || snat_type == SKIP_SNAT) { char *action = xasprintf("flags.%s_snat_for_lb = 1; ct_dnat;", snat_type == SKIP_SNAT ? "skip" : "force"); ovn_lflow_add_with_hint(lflows, od, S_ROUTER_OUT_UNDNAT, 120, - ds_cstr(&undnat_match), action, + ds_cstr(match), action, &lb->header_); free(action); } else { ovn_lflow_add_with_hint(lflows, od, S_ROUTER_OUT_UNDNAT, 120, - ds_cstr(&undnat_match), "ct_dnat;", + ds_cstr(match), "ct_dnat;", &lb->header_); } - - ds_destroy(&undnat_match); } static void @@ -8898,8 +8896,10 @@ build_lrouter_lb_flows(struct hmap *lflows, struct ovn_datapath *od, snat_type = FORCE_SNAT; } add_router_lb_flow(lflows, od, match, actions, prio, - snat_type, lb_vip, proto, nb_lb, - meter_groups, nat_entries); + snat_type, lb_vip, nb_lb, + meter_groups); + add_router_lb_undnat_unsnat_flows(lflows, od, snat_type, lb_vip, + proto, nb_lb, nat_entries); } } sset_destroy(&all_ips); @@ -9274,9 +9274,10 @@ build_lrouter_drop_own_dest(struct ovn_port *op, enum ovn_stage stage, uint16_t priority, bool drop_snat_ip, struct hmap *lflows) { - struct ds match_ips = DS_EMPTY_INITIALIZER; + struct ds *match_ips = match_get_clear(); if (op->lrp_networks.n_ipv4_addrs) { + ds_put_cstr(match_ips, "ip4.dst == {"); for (size_t i = 0; i < op->lrp_networks.n_ipv4_addrs; i++) { const char *ip = op->lrp_networks.ipv4_addrs[i].addr_s; @@ -9284,24 +9285,25 @@ build_lrouter_drop_own_dest(struct ovn_port *op, enum ovn_stage stage, bool drop_router_ip = (drop_snat_ip == router_ip_in_snat_ips); if (drop_router_ip) { - ds_put_format(&match_ips, "%s, ", ip); + ds_put_format(match_ips, "%s, ", ip); } } - if (ds_last(&match_ips) != EOF) { - ds_chomp(&match_ips, ' '); - ds_chomp(&match_ips, ','); + if (ds_last(match_ips) != EOF) { + ds_chomp(match_ips, ' '); + ds_chomp(match_ips, ','); - char *match = xasprintf("ip4.dst == {%s}", ds_cstr(&match_ips)); + ds_put_cstr(match_ips, "}"); ovn_lflow_add_with_hint(lflows, op->od, stage, priority, - match, "drop;", + ds_cstr(match_ips), "drop;", &op->nbrp->header_); - free(match); } } if (op->lrp_networks.n_ipv6_addrs) { - ds_clear(&match_ips); + ds_clear(match_ips); + + ds_put_cstr(match_ips, "ip6.dst == {"); for (size_t i = 0; i < op->lrp_networks.n_ipv6_addrs; i++) { const char *ip = op->lrp_networks.ipv6_addrs[i].addr_s; @@ -9310,22 +9312,20 @@ build_lrouter_drop_own_dest(struct ovn_port *op, enum ovn_stage stage, bool drop_router_ip = (drop_snat_ip == router_ip_in_snat_ips); if (drop_router_ip) { - ds_put_format(&match_ips, "%s, ", ip); + ds_put_format(match_ips, "%s, ", ip); } } - if (ds_last(&match_ips) != EOF) { - ds_chomp(&match_ips, ' '); - ds_chomp(&match_ips, ','); + if (ds_last(match_ips) != EOF) { + ds_chomp(match_ips, ' '); + ds_chomp(match_ips, ','); - char *match = xasprintf("ip6.dst == {%s}", ds_cstr(&match_ips)); + ds_put_cstr(match_ips, "}"); ovn_lflow_add_with_hint(lflows, op->od, stage, priority, - match, "drop;", + ds_cstr(match_ips), "drop;", &op->nbrp->header_); - free(match); } } - ds_destroy(&match_ips); } static void @@ -11872,7 +11872,6 @@ struct lswitch_flow_build_info { struct hmap *lbs; struct hmap *bfd_connections; char *svc_check_match; - struct ds match; struct ds actions; }; @@ -11885,7 +11884,8 @@ struct lswitch_flow_build_info { static void build_lswitch_and_lrouter_iterate_by_od(struct ovn_datapath *od, - struct lswitch_flow_build_info *lsi) + struct lswitch_flow_build_info *lsi, + struct ds *match) { /* Build Logical Switch Flows. */ build_lswitch_lflows_pre_acl_and_acl(od, lsi->port_groups, lsi->lflows, @@ -11903,69 +11903,70 @@ build_lswitch_and_lrouter_iterate_by_od(struct ovn_datapath *od, /* Build Logical Router Flows. */ build_adm_ctrl_flows_for_lrouter(od, lsi->lflows); - build_neigh_learning_flows_for_lrouter(od, lsi->lflows, &lsi->match, + build_neigh_learning_flows_for_lrouter(od, lsi->lflows, match, &lsi->actions); build_ND_RA_flows_for_lrouter(od, lsi->lflows); build_static_route_flows_for_lrouter(od, lsi->lflows, lsi->ports, lsi->bfd_connections); - build_mcast_lookup_flows_for_lrouter(od, lsi->lflows, &lsi->match, + build_mcast_lookup_flows_for_lrouter(od, lsi->lflows, match, &lsi->actions); build_ingress_policy_flows_for_lrouter(od, lsi->lflows, lsi->ports); build_arp_resolve_flows_for_lrouter(od, lsi->lflows); build_check_pkt_len_flows_for_lrouter(od, lsi->lflows, lsi->ports, - &lsi->match, &lsi->actions); - build_gateway_redirect_flows_for_lrouter(od, lsi->lflows, &lsi->match, + match, &lsi->actions); + build_gateway_redirect_flows_for_lrouter(od, lsi->lflows, match, &lsi->actions); - build_arp_request_flows_for_lrouter(od, lsi->lflows, &lsi->match, + build_arp_request_flows_for_lrouter(od, lsi->lflows, match, &lsi->actions); build_misc_local_traffic_drop_flows_for_lrouter(od, lsi->lflows); build_lrouter_arp_nd_for_datapath(od, lsi->lflows); build_lrouter_nat_defrag_and_lb(od, lsi->lflows, lsi->meter_groups, - lsi->lbs, &lsi->match, &lsi->actions); + lsi->lbs, match, &lsi->actions); } /* Helper function to combine all lflow generation which is iterated by port. */ static void build_lswitch_and_lrouter_iterate_by_op(struct ovn_port *op, - struct lswitch_flow_build_info *lsi) + struct lswitch_flow_build_info *lsi, + struct ds *match) { /* Build Logical Switch Flows. */ build_lswitch_input_port_sec_op(op, lsi->lflows, &lsi->actions, - &lsi->match); + match); build_lswitch_learn_fdb_op(op, lsi->lflows, &lsi->actions, - &lsi->match); + match); build_lswitch_arp_nd_responder_skip_local(op, lsi->lflows, - &lsi->match); + match); build_lswitch_arp_nd_responder_known_ips(op, lsi->lflows, lsi->ports, &lsi->actions, - &lsi->match); + match); build_lswitch_dhcp_options_and_response(op, lsi->lflows); build_lswitch_external_port(op, lsi->lflows); build_lswitch_ip_unicast_lookup(op, lsi->lflows, lsi->mcgroups, - &lsi->actions, &lsi->match); + &lsi->actions, match); build_lswitch_output_port_sec_op(op, lsi->lflows, - &lsi->actions, &lsi->match); + &lsi->actions, match); /* Build Logical Router Flows. */ - build_adm_ctrl_flows_for_lrouter_port(op, lsi->lflows, &lsi->match, + build_adm_ctrl_flows_for_lrouter_port(op, lsi->lflows, match, &lsi->actions); - build_neigh_learning_flows_for_lrouter_port(op, lsi->lflows, &lsi->match, + build_neigh_learning_flows_for_lrouter_port(op, lsi->lflows, match, &lsi->actions); build_ip_routing_flows_for_lrouter_port(op, lsi->lflows); - build_ND_RA_flows_for_lrouter_port(op, lsi->lflows, &lsi->match, + build_ND_RA_flows_for_lrouter_port(op, lsi->lflows, match, &lsi->actions); build_arp_resolve_flows_for_lrouter_port(op, lsi->lflows, lsi->ports, - &lsi->match, &lsi->actions); - build_egress_delivery_flows_for_lrouter_port(op, lsi->lflows, &lsi->match, + match, &lsi->actions); + build_egress_delivery_flows_for_lrouter_port(op, lsi->lflows, match, &lsi->actions); - build_dhcpv6_reply_flows_for_lrouter_port(op, lsi->lflows, &lsi->match); + build_dhcpv6_reply_flows_for_lrouter_port(op, lsi->lflows, match); build_ipv6_input_flows_for_lrouter_port(op, lsi->lflows, - &lsi->match, &lsi->actions); + match, &lsi->actions); build_lrouter_ipv4_ip_input(op, lsi->lflows, - &lsi->match, &lsi->actions); - build_lrouter_force_snat_flows_op(op, lsi->lflows, &lsi->match, + match, &lsi->actions); + build_lrouter_force_snat_flows_op(op, lsi->lflows, match, &lsi->actions); } @@ -11994,6 +11995,7 @@ build_lflows_thread(void *arg) if (stop_parallel_processing()) { return NULL; } + struct ds *match = match_get_clear(); if (lsi && workload) { /* Iterate over bucket ThreadID, ThreadID+size, ... */ for (bnum = control->id; @@ -12004,7 +12006,7 @@ build_lflows_thread(void *arg) if (stop_parallel_processing()) { return NULL; } - build_lswitch_and_lrouter_iterate_by_od(od, lsi); + build_lswitch_and_lrouter_iterate_by_od(od, lsi, match); } } for (bnum = control->id; @@ -12015,7 +12017,7 @@ build_lflows_thread(void *arg) if (stop_parallel_processing()) { return NULL; } - build_lswitch_and_lrouter_iterate_by_op(op, lsi); + build_lswitch_and_lrouter_iterate_by_op(op, lsi, match); } } for (bnum = control->id; @@ -12027,7 +12029,7 @@ build_lflows_thread(void *arg) return NULL; } build_lswitch_arp_nd_service_monitor(lb, lsi->lflows, - &lsi->match, + match, &lsi->actions); } } @@ -12041,7 +12043,7 @@ build_lflows_thread(void *arg) return NULL; } build_lswitch_ip_mcast_igmp_mld(igmp_group, lsi->lflows, - &lsi->match, + match, &lsi->actions); } } @@ -12140,7 +12142,6 @@ build_lswitch_and_lrouter_flows(struct hmap *datapaths, struct hmap *ports, lsiv[index].lbs = lbs; lsiv[index].bfd_connections = bfd_connections; lsiv[index].svc_check_match = svc_check_match; - ds_init(&lsiv[index].match); ds_init(&lsiv[index].actions); build_lflows_pool->pool->controls[index].data = &lsiv[index]; @@ -12154,7 +12155,6 @@ build_lswitch_and_lrouter_flows(struct hmap *datapaths, struct hmap *ports, } for (index = 0; index < build_lflows_pool->pool->size; index++) { - ds_destroy(&lsiv[index].match); ds_destroy(&lsiv[index].actions); } free(lflow_segs); @@ -12175,32 +12175,31 @@ build_lswitch_and_lrouter_flows(struct hmap *datapaths, struct hmap *ports, .lbs = lbs, .bfd_connections = bfd_connections, .svc_check_match = svc_check_match, - .match = DS_EMPTY_INITIALIZER, .actions = DS_EMPTY_INITIALIZER, }; + struct ds *match = match_get_clear(); /* Combined build - all lflow generation from lswitch and lrouter * will move here and will be reogranized by iterator type. */ HMAP_FOR_EACH (od, key_node, datapaths) { - build_lswitch_and_lrouter_iterate_by_od(od, &lsi); + build_lswitch_and_lrouter_iterate_by_od(od, &lsi, match); } HMAP_FOR_EACH (op, key_node, ports) { - build_lswitch_and_lrouter_iterate_by_op(op, &lsi); + build_lswitch_and_lrouter_iterate_by_op(op, &lsi, match); } HMAP_FOR_EACH (lb, hmap_node, lbs) { build_lswitch_arp_nd_service_monitor(lb, lsi.lflows, &lsi.actions, - &lsi.match); + match); } HMAP_FOR_EACH (igmp_group, hmap_node, igmp_groups) { build_lswitch_ip_mcast_igmp_mld(igmp_group, lsi.lflows, &lsi.actions, - &lsi.match); + match); } - ds_destroy(&lsi.match); ds_destroy(&lsi.actions); } From patchwork Wed Jun 16 17:56:11 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mark Michelson X-Patchwork-Id: 1493022 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=openvswitch.org (client-ip=2605:bc80:3010::133; helo=smtp2.osuosl.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=RGslKsXx; dkim-atps=neutral Received: from smtp2.osuosl.org (smtp2.osuosl.org [IPv6:2605:bc80:3010::133]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4G4tFd6Flqz9sXN for ; Thu, 17 Jun 2021 03:57:57 +1000 (AEST) Received: from localhost (localhost [127.0.0.1]) by smtp2.osuosl.org (Postfix) with ESMTP id D213D404BF; Wed, 16 Jun 2021 17:57:54 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from smtp2.osuosl.org ([127.0.0.1]) by localhost (smtp2.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id IfcIa0Jaj7QU; Wed, 16 Jun 2021 17:57:54 +0000 (UTC) Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [IPv6:2605:bc80:3010:104::8cd3:938]) by smtp2.osuosl.org (Postfix) with ESMTPS id 1C3E84015B; Wed, 16 Jun 2021 17:57:53 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id E44A5C000B; Wed, 16 Jun 2021 17:57:52 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@lists.linuxfoundation.org Received: from smtp4.osuosl.org (smtp4.osuosl.org [IPv6:2605:bc80:3010::137]) by lists.linuxfoundation.org (Postfix) with ESMTP id 1782FC000D for ; Wed, 16 Jun 2021 17:57:51 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by smtp4.osuosl.org (Postfix) with ESMTP id 067444149A for ; Wed, 16 Jun 2021 17:57:51 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Authentication-Results: smtp4.osuosl.org (amavisd-new); dkim=pass (1024-bit key) header.d=redhat.com Received: from smtp4.osuosl.org ([127.0.0.1]) by localhost (smtp4.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id smu7MmJDQCH9 for ; Wed, 16 Jun 2021 17:57:50 +0000 (UTC) X-Greylist: domain auto-whitelisted by SQLgrey-1.8.0 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by smtp4.osuosl.org (Postfix) with ESMTPS id 2E9C14148E for ; Wed, 16 Jun 2021 17:57:50 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1623866269; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=1NonEbf+2fXCazZds4c4gvHWpQFkC55vZ52l05C+D2c=; b=RGslKsXx4VT3CrWLoER7MpZujkmdLMIjvk545Pg+N+Li7daCHnql4HfN/Q54zw155A6qBm GGjZCAC7rkP6rcGBOz+U5WfzImC6Shwwfat3A+D6Abd/bK1CGAQGDORXqooCPm1WwH6wH7 mG4oWCtaUAyNnZpMkpSYkbr/qb2egbU= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-374-F2RjKd1xMJC98gG9wlYaWQ-1; Wed, 16 Jun 2021 13:56:15 -0400 X-MC-Unique: F2RjKd1xMJC98gG9wlYaWQ-1 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 1ED778E6AFE for ; Wed, 16 Jun 2021 17:56:15 +0000 (UTC) Received: from localhost.localdomain.com (ovpn-115-92.rdu2.redhat.com [10.10.115.92]) by smtp.corp.redhat.com (Postfix) with ESMTP id C2F576090F for ; Wed, 16 Jun 2021 17:56:14 +0000 (UTC) From: Mark Michelson To: dev@openvswitch.org Date: Wed, 16 Jun 2021 13:56:11 -0400 Message-Id: <20210616175611.597915-4-mmichels@redhat.com> In-Reply-To: <20210616175611.597915-1-mmichels@redhat.com> References: <20210616175611.597915-1-mmichels@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.13 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=mmichels@redhat.com X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Subject: [ovs-dev] [PATCH RFC ovn 3/3] northd: Memory cleanup for thread-local match. X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: ovs-dev-bounces@openvswitch.org Sender: "dev" I forgot to do this in the earlier patches, so I'm adding it here. If this weren't an RFC series, I'd roll this into earlier commits, but I'm playing a bit more loosely with it here. Signed-off-by: Mark Michelson --- northd/ovn-northd.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/northd/ovn-northd.c b/northd/ovn-northd.c index 59e3c5f84..9c1de4969 100644 --- a/northd/ovn-northd.c +++ b/northd/ovn-northd.c @@ -11988,6 +11988,7 @@ build_lflows_thread(void *arg) struct ovn_igmp_group *igmp_group; int bnum; + struct ds *match = match_get(); while (!stop_parallel_processing()) { wait_for_work(control); workload = (struct lflows_thread_pool *) control->workload; @@ -11995,7 +11996,7 @@ build_lflows_thread(void *arg) if (stop_parallel_processing()) { return NULL; } - struct ds *match = match_get_clear(); + ds_clear(match); if (lsi && workload) { /* Iterate over bucket ThreadID, ThreadID+size, ... */ for (bnum = control->id; @@ -12050,6 +12051,7 @@ build_lflows_thread(void *arg) } post_completed_work(control); } + ds_destroy(match); return NULL; } @@ -14529,6 +14531,9 @@ main(int argc, char *argv[]) ovsdb_idl_loop_destroy(&ovnsb_idl_loop); service_stop(); + struct ds *match = match_get(); + ds_destroy(match); + exit(res); }