From patchwork Thu Mar 4 04:10:02 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ben Pfaff X-Patchwork-Id: 1447078 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.133; helo=smtp2.osuosl.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Received: from smtp2.osuosl.org (smtp2.osuosl.org [140.211.166.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 4Drcpt1Pvpz9sRf for ; Thu, 4 Mar 2021 15:10:30 +1100 (AEDT) Received: from localhost (localhost [127.0.0.1]) by smtp2.osuosl.org (Postfix) with ESMTP id AD74143202; Thu, 4 Mar 2021 04:10:27 +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 Yu0cSsAf4fbW; Thu, 4 Mar 2021 04:10:26 +0000 (UTC) Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [IPv6:2605:bc80:3010:104::8cd3:938]) by smtp2.osuosl.org (Postfix) with ESMTP id B656443192; Thu, 4 Mar 2021 04:10:25 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id 09547C0011; Thu, 4 Mar 2021 04:10:24 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@lists.linuxfoundation.org Received: from smtp1.osuosl.org (smtp1.osuosl.org [IPv6:2605:bc80:3010::138]) by lists.linuxfoundation.org (Postfix) with ESMTP id 4D5FBC0001 for ; Thu, 4 Mar 2021 04:10:22 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by smtp1.osuosl.org (Postfix) with ESMTP id 2FC778428F for ; Thu, 4 Mar 2021 04:10:22 +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 oKHj8S4yCaQM for ; Thu, 4 Mar 2021 04:10:21 +0000 (UTC) X-Greylist: domain auto-whitelisted by SQLgrey-1.8.0 Received: from relay9-d.mail.gandi.net (relay9-d.mail.gandi.net [217.70.183.199]) by smtp1.osuosl.org (Postfix) with ESMTPS id 571E38428B for ; Thu, 4 Mar 2021 04:10:21 +0000 (UTC) X-Originating-IP: 75.54.222.30 Received: from sigfpe.attlocal.net (75-54-222-30.lightspeed.rdcyca.sbcglobal.net [75.54.222.30]) (Authenticated sender: blp@ovn.org) by relay9-d.mail.gandi.net (Postfix) with ESMTPSA id 9CA5DFF804; Thu, 4 Mar 2021 04:10:18 +0000 (UTC) From: Ben Pfaff To: dev@openvswitch.org Date: Wed, 3 Mar 2021 20:10:02 -0800 Message-Id: <20210304041012.4128938-2-blp@ovn.org> X-Mailer: git-send-email 2.29.2 In-Reply-To: <20210304041012.4128938-1-blp@ovn.org> References: <20210304041012.4128938-1-blp@ovn.org> MIME-Version: 1.0 Cc: Ben Pfaff Subject: [ovs-dev] [PATCH ovn 01/11] tests: Improve synchronization and debuggability. 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" While debugging ovn-northd-ddlog, I found a few more tests that either didn't have enough synchronization points (via "ovn-nbctl sync" or waiting for ports to come up) or that just were hard to debug because they didn't dump the flow table in a useful way. This improves them. Signed-off-by: Ben Pfaff --- tests/ovn.at | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/tests/ovn.at b/tests/ovn.at index bec593dccb74..39edb6b85526 100644 --- a/tests/ovn.at +++ b/tests/ovn.at @@ -4734,7 +4734,8 @@ test_ip 33 f00000000033 f00000000013 $sip $tip 13 #dump information including flow counters ovn-nbctl show -ovn-sbctl dump-flows -- list multicast_group +ovn-sbctl dump-flows -- list multicast_group > sbflows +AT_CAPTURE_FILE([sbflows]) echo "------ hv1 dump ------" as hv1 ovs-vsctl show @@ -6344,9 +6345,8 @@ echo "---------------------" ovn-sbctl list logical_flow echo "---------------------" -echo "---------------------" -ovn-sbctl dump-flows -echo "---------------------" +ovn-sbctl dump-flows > sbflows +AT_CAPTURE_FILE([sbflows]) echo "------ hv1 dump ----------" as hv1 ovs-ofctl dump-flows br-int @@ -12478,8 +12478,11 @@ ovs-vsctl -- add-port br-int hv2-vif1 -- \ ofport-request=1 ovs-vsctl set open . external-ids:ovn-bridge-mappings=phys:br-phys -OVS_WAIT_UNTIL([test x`ovn-nbctl lsp-get-up sw0_ip6-port1` = xup]) -OVS_WAIT_UNTIL([test x`ovn-nbctl lsp-get-up sw1_ip6-port1` = xup]) +ovn-nbctl --wait=sb sync +wait_for_ports_up + +ovn-sbctl dump-flows > sbflows +AT_CAPTURE_FILE([sbflows]) # There should be 2 Neighbor Advertisement flows for the router port # aef0:: ip address in logical switch pipeline with action nd_na_router. @@ -22108,6 +22111,10 @@ ovn-nbctl lsp-add sw0 sw0-p2 ovn-nbctl lsp-set-addresses sw0-p2 "50:54:00:00:00:04 10.0.0.4" ovn-nbctl lsp-set-port-security sw0-p2 "50:54:00:00:00:04 10.0.0.4" +ovn-nbctl --wait=sb sync +ovn-sbctl dump-flows > sbflows +AT_CAPTURE_FILE([sbflows]) + as hv1 ovs-vsctl -- add-port br-int hv1-vif1 -- \ set interface hv1-vif1 external-ids:iface-id=sw0-p1 \ @@ -22156,6 +22163,10 @@ ovn-nbctl lsp-add sw0 sw0-p2 ovn-nbctl lsp-set-addresses sw0-p2 "50:54:00:00:00:04 10.0.0.4" ovn-nbctl lsp-set-port-security sw0-p2 "50:54:00:00:00:04 10.0.0.4" +ovn-nbctl --wait=sb sync +ovn-sbctl dump-flows > sbflows2 +AT_CAPTURE_FILE([sbflows2]) + as hv1 ovs-vsctl -- add-port br-int hv1-vif1 -- \ set interface hv1-vif1 external-ids:iface-id=sw0-p1 \ From patchwork Thu Mar 4 04:10:03 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ben Pfaff X-Patchwork-Id: 1447079 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.133; helo=smtp2.osuosl.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Received: from smtp2.osuosl.org (smtp2.osuosl.org [140.211.166.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 4Drcpw3dcwz9sRf for ; Thu, 4 Mar 2021 15:10:32 +1100 (AEDT) Received: from localhost (localhost [127.0.0.1]) by smtp2.osuosl.org (Postfix) with ESMTP id 7AE14431D7; Thu, 4 Mar 2021 04:10:29 +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 tPcAxCtRh644; Thu, 4 Mar 2021 04:10:28 +0000 (UTC) Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56]) by smtp2.osuosl.org (Postfix) with ESMTP id 0C4C0431D6; Thu, 4 Mar 2021 04:10:26 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id E1E61C000D; Thu, 4 Mar 2021 04:10:26 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@lists.linuxfoundation.org Received: from smtp2.osuosl.org (smtp2.osuosl.org [IPv6:2605:bc80:3010::133]) by lists.linuxfoundation.org (Postfix) with ESMTP id 28EB8C0001 for ; Thu, 4 Mar 2021 04:10:23 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by smtp2.osuosl.org (Postfix) with ESMTP id 1908842FBF for ; Thu, 4 Mar 2021 04:10:23 +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 MKxKdTbmuc5A for ; Thu, 4 Mar 2021 04:10:22 +0000 (UTC) X-Greylist: domain auto-whitelisted by SQLgrey-1.8.0 Received: from relay9-d.mail.gandi.net (relay9-d.mail.gandi.net [217.70.183.199]) by smtp2.osuosl.org (Postfix) with ESMTPS id 52CF54017F for ; Thu, 4 Mar 2021 04:10:22 +0000 (UTC) X-Originating-IP: 75.54.222.30 Received: from sigfpe.attlocal.net (75-54-222-30.lightspeed.rdcyca.sbcglobal.net [75.54.222.30]) (Authenticated sender: blp@ovn.org) by relay9-d.mail.gandi.net (Postfix) with ESMTPSA id F0C59FF805; Thu, 4 Mar 2021 04:10:19 +0000 (UTC) From: Ben Pfaff To: dev@openvswitch.org Date: Wed, 3 Mar 2021 20:10:03 -0800 Message-Id: <20210304041012.4128938-3-blp@ovn.org> X-Mailer: git-send-email 2.29.2 In-Reply-To: <20210304041012.4128938-1-blp@ovn.org> References: <20210304041012.4128938-1-blp@ovn.org> MIME-Version: 1.0 Cc: Ben Pfaff Subject: [ovs-dev] [PATCH ovn 02/11] ovs-sandbox: Make it possible to disable recording ddlog input. 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" The recording is useful for debugging and reproducing runs, but it does cost CPU time, so with this option it can be disabled. Signed-off-by: Ben Pfaff --- tutorial/ovs-sandbox | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/tutorial/ovs-sandbox b/tutorial/ovs-sandbox index 21bc594467a0..08a3629be7f6 100755 --- a/tutorial/ovs-sandbox +++ b/tutorial/ovs-sandbox @@ -73,6 +73,7 @@ installed=false built=false ovn=true ddlog=false +ddlog_record=true ovnsb_schema= ovnnb_schema= ic_sb_schema= @@ -145,6 +146,7 @@ General options: OVN options: --ddlog use ovn-northd-ddlog + --no-ddlog-record do not record ddlog transactions (for performance) --no-ovn-rbac disable role-based access control for OVN --n-northds=NUMBER run NUMBER copies of northd (default: 1) --n-ics=NUMBER run NUMBER copies of ic (default: 1) @@ -239,6 +241,9 @@ EOF --ddlog) ddlog=true ;; + --no-ddlog-record | --no-record-ddlog) + ddlog_record=false + ;; --no-ovn-rbac) ovn_rbac=false ;; @@ -624,7 +629,7 @@ fi for i in $(seq $n_northds); do if [ $i -eq 1 ]; then inst=""; else inst=$i; fi - if $ddlog; then + if $ddlog && $ddlog_record; then northd_args=--ddlog-record=replay$inst.txt fi rungdb $gdb_ovn_northd $gdb_ovn_northd_ex $OVN_NORTHD --detach \ From patchwork Thu Mar 4 04:10:04 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ben Pfaff X-Patchwork-Id: 1447082 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::137; helo=smtp4.osuosl.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Received: from smtp4.osuosl.org (smtp4.osuosl.org [IPv6:2605:bc80:3010::137]) (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 4Drcq92KSWz9sRf for ; Thu, 4 Mar 2021 15:10:45 +1100 (AEDT) Received: from localhost (localhost [127.0.0.1]) by smtp4.osuosl.org (Postfix) with ESMTP id 34D1E4EBF0; Thu, 4 Mar 2021 04:10:43 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org 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 3QQcgwib7HNU; Thu, 4 Mar 2021 04:10:38 +0000 (UTC) Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56]) by smtp4.osuosl.org (Postfix) with ESMTP id 7F3C74EBCF; Thu, 4 Mar 2021 04:10:37 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id 9CACFC0001; Thu, 4 Mar 2021 04:10:35 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@lists.linuxfoundation.org Received: from smtp3.osuosl.org (smtp3.osuosl.org [140.211.166.136]) by lists.linuxfoundation.org (Postfix) with ESMTP id 250CDC000F for ; Thu, 4 Mar 2021 04:10:33 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by smtp3.osuosl.org (Postfix) with ESMTP id 21D226FB11 for ; Thu, 4 Mar 2021 04:10:31 +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 VPSnqwGGHd99 for ; Thu, 4 Mar 2021 04:10:25 +0000 (UTC) X-Greylist: domain auto-whitelisted by SQLgrey-1.8.0 Received: from relay9-d.mail.gandi.net (relay9-d.mail.gandi.net [217.70.183.199]) by smtp3.osuosl.org (Postfix) with ESMTPS id 57B156F4D5 for ; Thu, 4 Mar 2021 04:10:24 +0000 (UTC) X-Originating-IP: 75.54.222.30 Received: from sigfpe.attlocal.net (75-54-222-30.lightspeed.rdcyca.sbcglobal.net [75.54.222.30]) (Authenticated sender: blp@ovn.org) by relay9-d.mail.gandi.net (Postfix) with ESMTPSA id 57759FF806; Thu, 4 Mar 2021 04:10:21 +0000 (UTC) From: Ben Pfaff To: dev@openvswitch.org Date: Wed, 3 Mar 2021 20:10:04 -0800 Message-Id: <20210304041012.4128938-4-blp@ovn.org> X-Mailer: git-send-email 2.29.2 In-Reply-To: <20210304041012.4128938-1-blp@ovn.org> References: <20210304041012.4128938-1-blp@ovn.org> MIME-Version: 1.0 Cc: Ben Pfaff Subject: [ovs-dev] [PATCH ovn 03/11] ovn-northd-ddlog: Improve type safety for datapath stages. 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" Until now, whether a logical flow stage was for a logical router or switch, whether it was ingress or egress, and what particular stage it was were each separate attributes. It was possible to create an invalid stage, e.g. a "logical router" stage that was actually present only in logical switches. This would result in a bug. This commit makes such bugs much harder to cause. They will generally become compile-time errors. This code refactoring shouldn't change ovn-northd-ddlog behavior. Signed-off-by: Ben Pfaff --- northd/ovn_northd.dl | 788 ++++++++++++++++++++----------------------- 1 file changed, 365 insertions(+), 423 deletions(-) diff --git a/northd/ovn_northd.dl b/northd/ovn_northd.dl index 4482cffc0324..7d636df8b69a 100644 --- a/northd/ovn_northd.dl +++ b/northd/ovn_northd.dl @@ -1358,146 +1358,80 @@ nb::Out_Logical_Router_Port(._uuid = _uuid, nb::Logical_Router_Port(._uuid = _uuid, .name = name), LRPIPv6Prefix(_uuid, ipv6_prefix). -typedef Direction = IN | OUT - -typedef PipelineStage = PORT_SEC_L2 - | PORT_SEC_IP - | PORT_SEC_ND - | LOOKUP_FDB - | PUT_FDB - | PRE_ACL - | PRE_LB - | PRE_STATEFUL - | ACL_HINT - | ACL - | QOS_MARK - | QOS_METER - | LB - | STATEFUL - | PRE_HAIRPIN - | HAIRPIN - | NAT_HAIRPIN - | ARP_ND_RSP - | DHCP_OPTIONS - | DHCP_RESPONSE - | DNS_LOOKUP - | DNS_RESPONSE - | EXTERNAL_PORT - | L2_LKUP - | L2_UNKNOWN - | ADMISSION - | LOOKUP_NEIGHBOR - | LEARN_NEIGHBOR - | IP_INPUT - | DEFRAG - | UNSNAT - | DNAT - | ECMP_STATEFUL - | ND_RA_OPTIONS - | ND_RA_RESPONSE - | IP_ROUTING - | IP_ROUTING_ECMP - | POLICY - | POLICY_ECMP - | ARP_RESOLVE - | CHK_PKT_LEN - | LARGER_PKTS - | GW_REDIRECT - | ARP_REQUEST - | UNDNAT - | SNAT - | EGR_LOOP - | DELIVERY - -typedef DatapathType = LSwitch | LRouter +typedef Pipeline = Ingress | Egress typedef Stage = Stage{ - datapath : DatapathType, - direction : Direction, - stage : PipelineStage + pipeline : Pipeline, + table_id : integer, + table_name : string } -function switch_stage(direction: Direction, stage: PipelineStage): Stage = { - Stage{LSwitch, direction, stage} -} - -function router_stage(direction: Direction, stage: PipelineStage): Stage = { - Stage{LRouter, direction, stage} -} - -function stage_id(stage: Stage): (integer, string) = -{ - match ((stage.datapath, stage.direction, stage.stage)) { - /* Logical switch ingress stages. */ - (LSwitch, IN, PORT_SEC_L2) -> (0, "ls_in_port_sec_l2"), - (LSwitch, IN, PORT_SEC_IP) -> (1, "ls_in_port_sec_ip"), - (LSwitch, IN, PORT_SEC_ND) -> (2, "ls_in_port_sec_nd"), - (LSwitch, IN, LOOKUP_FDB) -> (3, "ls_in_lookup_fdb"), - (LSwitch, IN, PUT_FDB) -> (4, "ls_in_put_fdb"), - (LSwitch, IN, PRE_ACL) -> (5, "ls_in_pre_acl"), - (LSwitch, IN, PRE_LB) -> (6, "ls_in_pre_lb"), - (LSwitch, IN, PRE_STATEFUL) -> (7, "ls_in_pre_stateful"), - (LSwitch, IN, ACL_HINT) -> (8, "ls_in_acl_hint"), - (LSwitch, IN, ACL) -> (9, "ls_in_acl"), - (LSwitch, IN, QOS_MARK) -> (10, "ls_in_qos_mark"), - (LSwitch, IN, QOS_METER) -> (11, "ls_in_qos_meter"), - (LSwitch, IN, LB) -> (12, "ls_in_lb"), - (LSwitch, IN, STATEFUL) -> (13, "ls_in_stateful"), - (LSwitch, IN, PRE_HAIRPIN) -> (14, "ls_in_pre_hairpin"), - (LSwitch, IN, NAT_HAIRPIN) -> (15, "ls_in_nat_hairpin"), - (LSwitch, IN, HAIRPIN) -> (16, "ls_in_hairpin"), - (LSwitch, IN, ARP_ND_RSP) -> (17, "ls_in_arp_rsp"), - (LSwitch, IN, DHCP_OPTIONS) -> (18, "ls_in_dhcp_options"), - (LSwitch, IN, DHCP_RESPONSE) -> (19, "ls_in_dhcp_response"), - (LSwitch, IN, DNS_LOOKUP) -> (20, "ls_in_dns_lookup"), - (LSwitch, IN, DNS_RESPONSE) -> (21, "ls_in_dns_response"), - (LSwitch, IN, EXTERNAL_PORT) -> (22, "ls_in_external_port"), - (LSwitch, IN, L2_LKUP) -> (23, "ls_in_l2_lkup"), - (LSwitch, IN, L2_UNKNOWN) -> (24, "ls_in_l2_unknown"), - - /* Logical switch egress stages. */ - (LSwitch, OUT, PRE_LB) -> (0, "ls_out_pre_lb"), - (LSwitch, OUT, PRE_ACL) -> (1, "ls_out_pre_acl"), - (LSwitch, OUT, PRE_STATEFUL) -> (2, "ls_out_pre_stateful"), - (LSwitch, OUT, LB) -> (3, "ls_out_lb"), - (LSwitch, OUT, ACL_HINT) -> (4, "ls_out_acl_hint"), - (LSwitch, OUT, ACL) -> (5, "ls_out_acl"), - (LSwitch, OUT, QOS_MARK) -> (6, "ls_out_qos_mark"), - (LSwitch, OUT, QOS_METER) -> (7, "ls_out_qos_meter"), - (LSwitch, OUT, STATEFUL) -> (8, "ls_out_stateful"), - (LSwitch, OUT, PORT_SEC_IP) -> (9, "ls_out_port_sec_ip"), - (LSwitch, OUT, PORT_SEC_L2) -> (10, "ls_out_port_sec_l2"), - - /* Logical router ingress stages. */ - (LRouter, IN, ADMISSION) -> (0, "lr_in_admission"), - (LRouter, IN, LOOKUP_NEIGHBOR) -> (1, "lr_in_lookup_neighbor"), - (LRouter, IN, LEARN_NEIGHBOR) -> (2, "lr_in_learn_neighbor"), - (LRouter, IN, IP_INPUT) -> (3, "lr_in_ip_input"), - (LRouter, IN, DEFRAG) -> (4, "lr_in_defrag"), - (LRouter, IN, UNSNAT) -> (5, "lr_in_unsnat"), - (LRouter, IN, DNAT) -> (6, "lr_in_dnat"), - (LRouter, IN, ECMP_STATEFUL) -> (7, "lr_in_ecmp_stateful"), - (LRouter, IN, ND_RA_OPTIONS) -> (8, "lr_in_nd_ra_options"), - (LRouter, IN, ND_RA_RESPONSE)-> (9, "lr_in_nd_ra_response"), - (LRouter, IN, IP_ROUTING) -> (10, "lr_in_ip_routing"), - (LRouter, IN, IP_ROUTING_ECMP) -> (11, "lr_in_ip_routing_ecmp"), - (LRouter, IN, POLICY) -> (12, "lr_in_policy"), - (LRouter, IN, POLICY_ECMP) -> (13, "lr_in_policy_ecmp"), - (LRouter, IN, ARP_RESOLVE) -> (14, "lr_in_arp_resolve"), - (LRouter, IN, CHK_PKT_LEN) -> (15, "lr_in_chk_pkt_len"), - (LRouter, IN, LARGER_PKTS) -> (16, "lr_in_larger_pkts"), - (LRouter, IN, GW_REDIRECT) -> (17, "lr_in_gw_redirect"), - (LRouter, IN, ARP_REQUEST) -> (18, "lr_in_arp_request"), - - /* Logical router egress stages. */ - (LRouter, OUT, UNDNAT) -> (0, "lr_out_undnat"), - (LRouter, OUT, SNAT) -> (1, "lr_out_snat"), - (LRouter, OUT, EGR_LOOP) -> (2, "lr_out_egr_loop"), - (LRouter, OUT, DELIVERY) -> (3, "lr_out_delivery"), - - _ -> (64'hffffffffffffffff, "") /* alternatively crash? */ - } -} +/* Logical switch ingress stages. */ +function s_SWITCH_IN_PORT_SEC_L2(): Stage { Stage{Ingress, 0, "ls_in_port_sec_l2"} } +function s_SWITCH_IN_PORT_SEC_IP(): Stage { Stage{Ingress, 1, "ls_in_port_sec_ip"} } +function s_SWITCH_IN_PORT_SEC_ND(): Stage { Stage{Ingress, 2, "ls_in_port_sec_nd"} } +function s_SWITCH_IN_LOOKUP_FDB(): Stage { Stage{Ingress, 3, "ls_in_lookup_fdb"} } +function s_SWITCH_IN_PUT_FDB(): Stage { Stage{Ingress, 4, "ls_in_put_fdb"} } +function s_SWITCH_IN_PRE_ACL(): Stage { Stage{Ingress, 5, "ls_in_pre_acl"} } +function s_SWITCH_IN_PRE_LB(): Stage { Stage{Ingress, 6, "ls_in_pre_lb"} } +function s_SWITCH_IN_PRE_STATEFUL(): Stage { Stage{Ingress, 7, "ls_in_pre_stateful"} } +function s_SWITCH_IN_ACL_HINT(): Stage { Stage{Ingress, 8, "ls_in_acl_hint"} } +function s_SWITCH_IN_ACL(): Stage { Stage{Ingress, 9, "ls_in_acl"} } +function s_SWITCH_IN_QOS_MARK(): Stage { Stage{Ingress, 10, "ls_in_qos_mark"} } +function s_SWITCH_IN_QOS_METER(): Stage { Stage{Ingress, 11, "ls_in_qos_meter"} } +function s_SWITCH_IN_LB(): Stage { Stage{Ingress, 12, "ls_in_lb"} } +function s_SWITCH_IN_STATEFUL(): Stage { Stage{Ingress, 13, "ls_in_stateful"} } +function s_SWITCH_IN_PRE_HAIRPIN(): Stage { Stage{Ingress, 14, "ls_in_pre_hairpin"} } +function s_SWITCH_IN_NAT_HAIRPIN(): Stage { Stage{Ingress, 15, "ls_in_nat_hairpin"} } +function s_SWITCH_IN_HAIRPIN(): Stage { Stage{Ingress, 16, "ls_in_hairpin"} } +function s_SWITCH_IN_ARP_ND_RSP(): Stage { Stage{Ingress, 17, "ls_in_arp_rsp"} } +function s_SWITCH_IN_DHCP_OPTIONS(): Stage { Stage{Ingress, 18, "ls_in_dhcp_options"} } +function s_SWITCH_IN_DHCP_RESPONSE(): Stage { Stage{Ingress, 19, "ls_in_dhcp_response"} } +function s_SWITCH_IN_DNS_LOOKUP(): Stage { Stage{Ingress, 20, "ls_in_dns_lookup"} } +function s_SWITCH_IN_DNS_RESPONSE(): Stage { Stage{Ingress, 21, "ls_in_dns_response"} } +function s_SWITCH_IN_EXTERNAL_PORT(): Stage { Stage{Ingress, 22, "ls_in_external_port"} } +function s_SWITCH_IN_L2_LKUP(): Stage { Stage{Ingress, 23, "ls_in_l2_lkup"} } +function s_SWITCH_IN_L2_UNKNOWN(): Stage { Stage{Ingress, 24, "ls_in_l2_unknown"} } + +/* Logical switch egress stages. */ +function s_SWITCH_OUT_PRE_LB(): Stage { Stage{ Egress, 0, "ls_out_pre_lb"} } +function s_SWITCH_OUT_PRE_ACL(): Stage { Stage{ Egress, 1, "ls_out_pre_acl"} } +function s_SWITCH_OUT_PRE_STATEFUL(): Stage { Stage{ Egress, 2, "ls_out_pre_stateful"} } +function s_SWITCH_OUT_LB(): Stage { Stage{ Egress, 3, "ls_out_lb"} } +function s_SWITCH_OUT_ACL_HINT(): Stage { Stage{ Egress, 4, "ls_out_acl_hint"} } +function s_SWITCH_OUT_ACL(): Stage { Stage{ Egress, 5, "ls_out_acl"} } +function s_SWITCH_OUT_QOS_MARK(): Stage { Stage{ Egress, 6, "ls_out_qos_mark"} } +function s_SWITCH_OUT_QOS_METER(): Stage { Stage{ Egress, 7, "ls_out_qos_meter"} } +function s_SWITCH_OUT_STATEFUL(): Stage { Stage{ Egress, 8, "ls_out_stateful"} } +function s_SWITCH_OUT_PORT_SEC_IP(): Stage { Stage{ Egress, 9, "ls_out_port_sec_ip"} } +function s_SWITCH_OUT_PORT_SEC_L2(): Stage { Stage{ Egress, 10, "ls_out_port_sec_l2"} } + +/* Logical router ingress stages. */ +function s_ROUTER_IN_ADMISSION(): Stage { Stage{Ingress, 0, "lr_in_admission"} } +function s_ROUTER_IN_LOOKUP_NEIGHBOR(): Stage { Stage{Ingress, 1, "lr_in_lookup_neighbor"} } +function s_ROUTER_IN_LEARN_NEIGHBOR(): Stage { Stage{Ingress, 2, "lr_in_learn_neighbor"} } +function s_ROUTER_IN_IP_INPUT(): Stage { Stage{Ingress, 3, "lr_in_ip_input"} } +function s_ROUTER_IN_DEFRAG(): Stage { Stage{Ingress, 4, "lr_in_defrag"} } +function s_ROUTER_IN_UNSNAT(): Stage { Stage{Ingress, 5, "lr_in_unsnat"} } +function s_ROUTER_IN_DNAT(): Stage { Stage{Ingress, 6, "lr_in_dnat"} } +function s_ROUTER_IN_ECMP_STATEFUL(): Stage { Stage{Ingress, 7, "lr_in_ecmp_stateful"} } +function s_ROUTER_IN_ND_RA_OPTIONS(): Stage { Stage{Ingress, 8, "lr_in_nd_ra_options"} } +function s_ROUTER_IN_ND_RA_RESPONSE(): Stage { Stage{Ingress, 9, "lr_in_nd_ra_response"} } +function s_ROUTER_IN_IP_ROUTING(): Stage { Stage{Ingress, 10, "lr_in_ip_routing"} } +function s_ROUTER_IN_IP_ROUTING_ECMP(): Stage { Stage{Ingress, 11, "lr_in_ip_routing_ecmp"} } +function s_ROUTER_IN_POLICY(): Stage { Stage{Ingress, 12, "lr_in_policy"} } +function s_ROUTER_IN_POLICY_ECMP(): Stage { Stage{Ingress, 13, "lr_in_policy_ecmp"} } +function s_ROUTER_IN_ARP_RESOLVE(): Stage { Stage{Ingress, 14, "lr_in_arp_resolve"} } +function s_ROUTER_IN_CHK_PKT_LEN(): Stage { Stage{Ingress, 15, "lr_in_chk_pkt_len"} } +function s_ROUTER_IN_LARGER_PKTS(): Stage { Stage{Ingress, 16, "lr_in_larger_pkts"} } +function s_ROUTER_IN_GW_REDIRECT(): Stage { Stage{Ingress, 17, "lr_in_gw_redirect"} } +function s_ROUTER_IN_ARP_REQUEST(): Stage { Stage{Ingress, 18, "lr_in_arp_request"} } + +/* Logical router egress stages. */ +function s_ROUTER_OUT_UNDNAT(): Stage { Stage{ Egress, 0, "lr_out_undnat"} } +function s_ROUTER_OUT_SNAT(): Stage { Stage{ Egress, 1, "lr_out_snat"} } +function s_ROUTER_OUT_EGR_LOOP(): Stage { Stage{ Egress, 2, "lr_out_egr_loop"} } +function s_ROUTER_OUT_DELIVERY(): Stage { Stage{ Egress, 3, "lr_out_delivery"} } /* * OVS register usage: @@ -1685,9 +1619,8 @@ AggregatedFlow(.logical_datapaths = set_singleton(logical_datapath), AnnotatedFlow(Flow{logical_datapath, stage, priority, __match, actions, external_ids}, false). for (f in AggregatedFlow()) { - (var table_id, var table_name) = stage_id(f.stage) in - var pipeline = if (f.stage.direction == IN) "ingress" else "egress" in - var external_ids = f.external_ids.insert_imm("stage-name", table_name) in + var pipeline = if (f.stage.pipeline == Ingress) "ingress" else "egress" in + var external_ids = f.external_ids.insert_imm("stage-name", f.stage.table_name) in if (f.logical_datapaths.size() == 1) { Some{var dp} = f.logical_datapaths.nth(0) in sb::Out_Logical_Flow( @@ -1695,7 +1628,7 @@ for (f in AggregatedFlow()) { .logical_datapath = Some{dp}, .logical_dp_group = None, .pipeline = pipeline, - .table_id = table_id, + .table_id = f.stage.table_id, .priority = f.priority, .__match = f.__match, .actions = f.actions, @@ -1707,7 +1640,7 @@ for (f in AggregatedFlow()) { .logical_datapath = None, .logical_dp_group = Some{group_uuid}, .pipeline = pipeline, - .table_id = table_id, + .table_id = f.stage.table_id, .priority = f.priority, .__match = f.__match, .actions = f.actions, @@ -1719,7 +1652,7 @@ for (f in AggregatedFlow()) { /* Logical flows for forwarding groups. */ Flow(.logical_datapath = sw.ls._uuid, - .stage = switch_stage(IN, ARP_ND_RSP), + .stage = s_SWITCH_IN_ARP_ND_RSP(), .priority = 50, .__match = __match, .actions = actions, @@ -1748,7 +1681,7 @@ function escape_child_ports(child_port: Set): string { escaped.join(",") } Flow(.logical_datapath = sw.ls._uuid, - .stage = switch_stage(IN, L2_LKUP), + .stage = s_SWITCH_IN_L2_LKUP(), .priority = 50, .__match = __match, .actions = actions, @@ -1768,7 +1701,7 @@ for (sw in &Switch()) { if (not sw.is_vlan_transparent) { /* Block logical VLANs. */ Flow(.logical_datapath = sw.ls._uuid, - .stage = switch_stage(IN, PORT_SEC_L2), + .stage = s_SWITCH_IN_PORT_SEC_L2(), .priority = 100, .__match = "vlan.present", .actions = "drop;", @@ -1777,7 +1710,7 @@ for (sw in &Switch()) { /* Broadcast/multicast source address is invalid */ Flow(.logical_datapath = sw.ls._uuid, - .stage = switch_stage(IN, PORT_SEC_L2), + .stage = s_SWITCH_IN_PORT_SEC_L2(), .priority = 100, .__match = "eth.src[40]", .actions = "drop;", @@ -1792,7 +1725,7 @@ function join(strings: Set, sep: string): string { } function build_port_security_ipv6_flow( - pipeline: Direction, + pipeline: Pipeline, ea: eth_addr, ipv6_addrs: Vec): string = { @@ -1802,14 +1735,14 @@ function build_port_security_ipv6_flow( ip6_addrs.push(ipv6_string_mapped(in6_generate_lla(ea))); /* Allow ip6.dst=ff00::/8 for multicast packets */ - if (pipeline == OUT) { + if (pipeline == Egress) { ip6_addrs.push("ff00::/8") }; for (addr in ipv6_addrs) { ip6_addrs.push(ipv6_netaddr_match_network(addr)) }; - var dir = if (pipeline == IN) { "src" } else { "dst" }; + var dir = if (pipeline == Ingress) { "src" } else { "dst" }; " && ip6.${dir} == {" ++ ip6_addrs.join(", ") ++ "}" } @@ -1839,26 +1772,26 @@ for (&Switch(.ls =ls)) { /* Ingress and Egress Pre-ACL Table (Priority 0): Packets are * allowed by default. */ Flow(.logical_datapath = ls._uuid, - .stage = switch_stage(IN, PRE_ACL), + .stage = s_SWITCH_IN_PRE_ACL(), .priority = 0, .__match = "1", .actions = "next;", .external_ids = map_empty()); Flow(.logical_datapath = ls._uuid, - .stage = switch_stage(OUT, PRE_ACL), + .stage = s_SWITCH_OUT_PRE_ACL(), .priority = 0, .__match = "1", .actions = "next;", .external_ids = map_empty()); Flow(.logical_datapath = ls._uuid, - .stage = switch_stage(IN, PRE_ACL), + .stage = s_SWITCH_IN_PRE_ACL(), .priority = 110, .__match = "eth.dst == $svc_monitor_mac", .actions = "next;", .external_ids = map_empty()); Flow(.logical_datapath = ls._uuid, - .stage = switch_stage(OUT, PRE_ACL), + .stage = s_SWITCH_OUT_PRE_ACL(), .priority = 110, .__match = "eth.src == $svc_monitor_mac", .actions = "next;", @@ -1886,13 +1819,13 @@ for (&SwitchPort(.lsp = lsp@nb::Logical_Switch_Port{.__type = "router"}, * on hostA, not hostB. This would only work with * distributed conntrack state across all chassis. */ Flow(.logical_datapath = ls._uuid, - .stage = switch_stage(IN, PRE_ACL), + .stage = s_SWITCH_IN_PRE_ACL(), .priority = 110, .__match = "ip && inport == ${lsp_name}", .actions = "next;", .external_ids = stage_hint(lsp._uuid)); Flow(.logical_datapath = ls._uuid, - .stage = switch_stage(OUT, PRE_ACL), + .stage = s_SWITCH_OUT_PRE_ACL(), .priority = 110, .__match = "ip && outport == ${lsp_name}", .actions = "next;", @@ -1903,13 +1836,13 @@ for (&SwitchPort(.lsp = lsp@nb::Logical_Switch_Port{.__type = "localnet"}, .json_name = lsp_name, .sw = &Switch{.ls = ls, .has_stateful_acl = true})) { Flow(.logical_datapath = ls._uuid, - .stage = switch_stage(IN, PRE_ACL), + .stage = s_SWITCH_IN_PRE_ACL(), .priority = 110, .__match = "ip && inport == ${lsp_name}", .actions = "next;", .external_ids = stage_hint(lsp._uuid)); Flow(.logical_datapath = ls._uuid, - .stage = switch_stage(OUT, PRE_ACL), + .stage = s_SWITCH_OUT_PRE_ACL(), .priority = 110, .__match = "ip && outport == ${lsp_name}", .actions = "next;", @@ -1922,14 +1855,14 @@ for (&Switch(.ls = ls, .has_stateful_acl = true)) { * Not to do conntrack on ND and ICMP destination * unreachable packets. */ Flow(.logical_datapath = ls._uuid, - .stage = switch_stage(IN, PRE_ACL), + .stage = s_SWITCH_IN_PRE_ACL(), .priority = 110, .__match = "nd || nd_rs || nd_ra || mldv1 || mldv2 || " "(udp && udp.src == 546 && udp.dst == 547)", .actions = "next;", .external_ids = map_empty()); Flow(.logical_datapath = ls._uuid, - .stage = switch_stage(OUT, PRE_ACL), + .stage = s_SWITCH_OUT_PRE_ACL(), .priority = 110, .__match = "nd || nd_rs || nd_ra || mldv1 || mldv2 || " "(udp && udp.src == 546 && udp.dst == 547)", @@ -1945,13 +1878,13 @@ for (&Switch(.ls = ls, .has_stateful_acl = true)) { * 'REGBIT_CONNTRACK_DEFRAG' is set to let the pre-stateful table send * it to conntrack for tracking and defragmentation. */ Flow(.logical_datapath = ls._uuid, - .stage = switch_stage(IN, PRE_ACL), + .stage = s_SWITCH_IN_PRE_ACL(), .priority = 100, .__match = "ip", .actions = "${rEGBIT_CONNTRACK_DEFRAG()} = 1; next;", .external_ids = map_empty()); Flow(.logical_datapath = ls._uuid, - .stage = switch_stage(OUT, PRE_ACL), + .stage = s_SWITCH_OUT_PRE_ACL(), .priority = 100, .__match = "ip", .actions = "${rEGBIT_CONNTRACK_DEFRAG()} = 1; next;", @@ -1963,13 +1896,13 @@ for (&Switch(.ls = ls)) { /* Do not send ND packets to conntrack */ var __match = "nd || nd_rs || nd_ra || mldv1 || mldv2" in { Flow(.logical_datapath = ls._uuid, - .stage = switch_stage(IN, PRE_LB), + .stage = s_SWITCH_IN_PRE_LB(), .priority = 110, .__match = __match, .actions = "next;", .external_ids = map_empty()); Flow(.logical_datapath = ls._uuid, - .stage = switch_stage(OUT, PRE_LB), + .stage = s_SWITCH_OUT_PRE_LB(), .priority = 110, .__match = __match, .actions = "next;", @@ -1978,13 +1911,13 @@ for (&Switch(.ls = ls)) { /* Do not send service monitor packets to conntrack. */ Flow(.logical_datapath = ls._uuid, - .stage = switch_stage(IN, PRE_LB), + .stage = s_SWITCH_IN_PRE_LB(), .priority = 110, .__match = "eth.dst == $svc_monitor_mac", .actions = "next;", .external_ids = map_empty()); Flow(.logical_datapath = ls._uuid, - .stage = switch_stage(OUT, PRE_LB), + .stage = s_SWITCH_OUT_PRE_LB(), .priority = 110, .__match = "eth.src == $svc_monitor_mac", .actions = "next;", @@ -1992,13 +1925,13 @@ for (&Switch(.ls = ls)) { /* Allow all packets to go to next tables by default. */ Flow(.logical_datapath = ls._uuid, - .stage = switch_stage(IN, PRE_LB), + .stage = s_SWITCH_IN_PRE_LB(), .priority = 0, .__match = "1", .actions = "next;", .external_ids = map_empty()); Flow(.logical_datapath = ls._uuid, - .stage = switch_stage(OUT, PRE_LB), + .stage = s_SWITCH_OUT_PRE_LB(), .priority = 0, .__match = "1", .actions = "next;", @@ -2008,13 +1941,13 @@ for (&Switch(.ls = ls)) { for (&SwitchPort(.lsp = lsp, .json_name = lsp_name, .sw = &Switch{.ls = ls})) if (lsp.__type == "router" or lsp.__type == "localnet") { Flow(.logical_datapath = ls._uuid, - .stage = switch_stage(IN, PRE_LB), + .stage = s_SWITCH_IN_PRE_LB(), .priority = 110, .__match = "ip && inport == ${lsp_name}", .actions = "next;", .external_ids = stage_hint(lsp._uuid)); Flow(.logical_datapath = ls._uuid, - .stage = switch_stage(OUT, PRE_LB), + .stage = s_SWITCH_OUT_PRE_LB(), .priority = 110, .__match = "ip && outport == ${lsp_name}", .actions = "next;", @@ -2085,7 +2018,7 @@ LoadBalancerEmptyEvents(lb) :- global_events or local_events. Flow(.logical_datapath = sw.ls._uuid, - .stage = switch_stage(IN, PRE_LB), + .stage = s_SWITCH_IN_PRE_LB(), .priority = 130, .__match = __match, .actions = __action, @@ -2130,13 +2063,13 @@ Flow(.logical_datapath = sw.ls._uuid, */ for (sw in &Switch(.has_lb_vip = true)) { Flow(.logical_datapath = sw.ls._uuid, - .stage = switch_stage(IN, PRE_LB), + .stage = s_SWITCH_IN_PRE_LB(), .priority = 100, .__match = "ip", .actions = "${rEGBIT_CONNTRACK_DEFRAG()} = 1; next;", .external_ids = map_empty()); Flow(.logical_datapath = sw.ls._uuid, - .stage = switch_stage(OUT, PRE_LB), + .stage = s_SWITCH_OUT_PRE_LB(), .priority = 100, .__match = "ip", .actions = "${rEGBIT_CONNTRACK_DEFRAG()} = 1; next;", @@ -2148,13 +2081,13 @@ for (&Switch(.ls = ls)) { /* Ingress and Egress pre-stateful Table (Priority 0): Packets are * allowed by default. */ Flow(.logical_datapath = ls._uuid, - .stage = switch_stage(IN, PRE_STATEFUL), + .stage = s_SWITCH_IN_PRE_STATEFUL(), .priority = 0, .__match = "1", .actions = "next;", .external_ids = map_empty()); Flow(.logical_datapath = ls._uuid, - .stage = switch_stage(OUT, PRE_STATEFUL), + .stage = s_SWITCH_OUT_PRE_STATEFUL(), .priority = 0, .__match = "1", .actions = "next;", @@ -2163,13 +2096,13 @@ for (&Switch(.ls = ls)) { /* If REGBIT_CONNTRACK_DEFRAG is set as 1, then the packets should be * sent to conntrack for tracking and defragmentation. */ Flow(.logical_datapath = ls._uuid, - .stage = switch_stage(IN, PRE_STATEFUL), + .stage = s_SWITCH_IN_PRE_STATEFUL(), .priority = 100, .__match = "${rEGBIT_CONNTRACK_DEFRAG()} == 1", .actions = "ct_next;", .external_ids = map_empty()); Flow(.logical_datapath = ls._uuid, - .stage = switch_stage(OUT, PRE_STATEFUL), + .stage = s_SWITCH_OUT_PRE_STATEFUL(), .priority = 100, .__match = "${rEGBIT_CONNTRACK_DEFRAG()} == 1", .actions = "ct_next;", @@ -2236,7 +2169,7 @@ function oVN_ACL_PRI_OFFSET(): integer = 1000 */ relation Reject( lsuuid: uuid, - pipeline: string, + pipeline: Pipeline, stage: Stage, acl: nb::ACL, fair_meter: bool, @@ -2244,6 +2177,13 @@ relation Reject( extra_actions: string) /* build_reject_acl_rules() */ +function next_to_stage(stage: Stage): string { + var pipeline = match (stage.pipeline) { + Ingress -> "ingress", + Egress -> "egress" + }; + "next(pipeline=${pipeline},table=${stage.table_id})" +} for (Reject(lsuuid, pipeline, stage, acl, fair_meter, extra_match_, extra_actions_)) { var extra_match = match (extra_match_) { "" -> "", @@ -2253,16 +2193,16 @@ for (Reject(lsuuid, pipeline, stage, acl, fair_meter, extra_match_, extra_action "" -> "", s -> "${s} " } in - var next = match (pipeline == "ingress") { - true -> "next(pipeline=egress,table=${stage_id(switch_stage(OUT, QOS_MARK)).0})", - false -> "next(pipeline=ingress,table=${stage_id(switch_stage(IN, L2_LKUP)).0})" + var next_stage = match (pipeline) { + Ingress -> s_SWITCH_OUT_QOS_MARK(), + Egress -> s_SWITCH_IN_L2_LKUP() } in var acl_log = build_acl_log(acl, fair_meter) in var __match = extra_match ++ acl.__match in var actions = acl_log ++ extra_actions ++ "reg0 = 0; " "reject { " "/* eth.dst <-> eth.src; ip.dst <-> ip.src; is implicit. */ " - "outport <-> inport; ${next}; };" in + "outport <-> inport; ${next_to_stage(next_stage)}; };" in Flow(.logical_datapath = lsuuid, .stage = stage, .priority = acl.priority + oVN_ACL_PRI_OFFSET(), @@ -2279,13 +2219,13 @@ var has_stateful = sw.has_stateful_acl or sw.has_lb_vip in * default. A related rule at priority 1 is added below if there * are any stateful ACLs in this datapath. */ Flow(.logical_datapath = ls._uuid, - .stage = switch_stage(IN, ACL), + .stage = s_SWITCH_IN_ACL(), .priority = 0, .__match = "1", .actions = "next;", .external_ids = map_empty()); Flow(.logical_datapath = ls._uuid, - .stage = switch_stage(OUT, ACL), + .stage = s_SWITCH_OUT_ACL(), .priority = 0, .__match = "1", .actions = "next;", @@ -2314,13 +2254,13 @@ var has_stateful = sw.has_stateful_acl or sw.has_lb_vip in * Subsequent packets will hit the flow at priority 0 that just * uses "next;". */ Flow(.logical_datapath = ls._uuid, - .stage = switch_stage(IN, ACL), + .stage = s_SWITCH_IN_ACL(), .priority = 1, .__match = "ip && (!ct.est || (ct.est && ct_label.blocked == 1))", .actions = "${rEGBIT_CONNTRACK_COMMIT()} = 1; next;", .external_ids = map_empty()); Flow(.logical_datapath = ls._uuid, - .stage = switch_stage(OUT, ACL), + .stage = s_SWITCH_OUT_ACL(), .priority = 1, .__match = "ip && (!ct.est || (ct.est && ct_label.blocked == 1))", .actions = "${rEGBIT_CONNTRACK_COMMIT()} = 1; next;", @@ -2334,13 +2274,13 @@ var has_stateful = sw.has_stateful_acl or sw.has_lb_vip in * * This is enforced at a higher priority than ACLs can be defined. */ Flow(.logical_datapath = ls._uuid, - .stage = switch_stage(IN, ACL), + .stage = s_SWITCH_IN_ACL(), .priority = 65535, .__match = "ct.inv || (ct.est && ct.rpl && ct_label.blocked == 1)", .actions = "drop;", .external_ids = map_empty()); Flow(.logical_datapath = ls._uuid, - .stage = switch_stage(OUT, ACL), + .stage = s_SWITCH_OUT_ACL(), .priority = 65535, .__match = "ct.inv || (ct.est && ct.rpl && ct_label.blocked == 1)", .actions = "drop;", @@ -2356,14 +2296,14 @@ var has_stateful = sw.has_stateful_acl or sw.has_lb_vip in * * This is enforced at a higher priority than ACLs can be defined. */ Flow(.logical_datapath = ls._uuid, - .stage = switch_stage(IN, ACL), + .stage = s_SWITCH_IN_ACL(), .priority = 65535, .__match = "ct.est && !ct.rel && !ct.new && !ct.inv " "&& ct.rpl && ct_label.blocked == 0", .actions = "next;", .external_ids = map_empty()); Flow(.logical_datapath = ls._uuid, - .stage = switch_stage(OUT, ACL), + .stage = s_SWITCH_OUT_ACL(), .priority = 65535, .__match = "ct.est && !ct.rel && !ct.new && !ct.inv " "&& ct.rpl && ct_label.blocked == 0", @@ -2382,14 +2322,14 @@ var has_stateful = sw.has_stateful_acl or sw.has_lb_vip in * related traffic such as an ICMP Port Unreachable through * that's generated from a non-listening UDP port. */ Flow(.logical_datapath = ls._uuid, - .stage = switch_stage(IN, ACL), + .stage = s_SWITCH_IN_ACL(), .priority = 65535, .__match = "!ct.est && ct.rel && !ct.new && !ct.inv " "&& ct_label.blocked == 0", .actions = "next;", .external_ids = map_empty()); Flow(.logical_datapath = ls._uuid, - .stage = switch_stage(OUT, ACL), + .stage = s_SWITCH_OUT_ACL(), .priority = 65535, .__match = "!ct.est && ct.rel && !ct.new && !ct.inv " "&& ct_label.blocked == 0", @@ -2400,13 +2340,13 @@ var has_stateful = sw.has_stateful_acl or sw.has_lb_vip in * * Not to do conntrack on ND packets. */ Flow(.logical_datapath = ls._uuid, - .stage = switch_stage(IN, ACL), + .stage = s_SWITCH_IN_ACL(), .priority = 65535, .__match = "nd || nd_ra || nd_rs || mldv1 || mldv2", .actions = "next;", .external_ids = map_empty()); Flow(.logical_datapath = ls._uuid, - .stage = switch_stage(OUT, ACL), + .stage = s_SWITCH_OUT_ACL(), .priority = 65535, .__match = "nd || nd_ra || nd_rs || mldv1 || mldv2", .actions = "next;", @@ -2418,7 +2358,7 @@ var has_stateful = sw.has_stateful_acl or sw.has_lb_vip in */ if (sw.has_dns_records) { Flow(.logical_datapath = ls._uuid, - .stage = switch_stage(OUT, ACL), + .stage = s_SWITCH_OUT_ACL(), .priority = 34000, .__match = "udp.src == 53", .actions = if has_stateful "ct_commit; next;" else "next;", @@ -2428,13 +2368,13 @@ var has_stateful = sw.has_stateful_acl or sw.has_lb_vip in /* Add a 34000 priority flow to advance the service monitor reply * packets to skip applying ingress ACLs. */ Flow(.logical_datapath = ls._uuid, - .stage = switch_stage(IN, ACL), + .stage = s_SWITCH_IN_ACL(), .priority = 34000, .__match = "eth.dst == $svc_monitor_mac", .actions = "next;", .external_ids = map_empty()); Flow(.logical_datapath = ls._uuid, - .stage = switch_stage(OUT, ACL), + .stage = s_SWITCH_OUT_ACL(), .priority = 34000, .__match = "eth.src == $svc_monitor_mac", .actions = "next;", @@ -2454,8 +2394,8 @@ var has_stateful = sw.has_stateful_acl or sw.has_lb_vip in * corresponding to all potential matches are set. */ input relation AclHintStages[Stage] -AclHintStages[switch_stage(IN, ACL_HINT)]. -AclHintStages[switch_stage(OUT, ACL_HINT)]. +AclHintStages[s_SWITCH_IN_ACL_HINT()]. +AclHintStages[s_SWITCH_OUT_ACL_HINT()]. for (sw in &Switch(.ls = ls)) { for (AclHintStages[stage]) { /* In any case, advance to the next stage. */ @@ -2530,8 +2470,8 @@ for (&SwitchACL(.sw = sw@&Switch{.ls = ls}, .acl = &acl, .has_fair_meter = fair_ /* consider_acl */ var has_stateful = sw.has_stateful_acl or sw.has_lb_vip in var ingress = acl.direction == "from-lport" in - var stage = if (ingress) { switch_stage(IN, ACL) } else { switch_stage(OUT, ACL) } in - var pipeline = if ingress "ingress" else "egress" in + var stage = if (ingress) { s_SWITCH_IN_ACL() } else { s_SWITCH_OUT_ACL() } in + var pipeline = if ingress Ingress else Egress in var stage_hint = stage_hint(acl._uuid) in var acl_log = build_acl_log(acl, fair_meter) in if (acl.action == "allow" or acl.action == "allow-related") { @@ -2650,7 +2590,7 @@ for (SwitchPortDHCPv4Options(.port = &SwitchPort{.lsp = lsp, .sw = &sw}, (options.get("server_id"), options.get("server_mac"), options.get("lease_time")) in var has_stateful = sw.has_stateful_acl or sw.has_lb_vip in Flow(.logical_datapath = sw.ls._uuid, - .stage = switch_stage(OUT, ACL), + .stage = s_SWITCH_OUT_ACL(), .priority = 34000, .__match = "outport == ${json_string_escape(lsp.name)} " "&& eth.src == ${server_mac} " @@ -2670,7 +2610,7 @@ for (SwitchPortDHCPv6Options(.port = &SwitchPort{.lsp = lsp, .sw = &sw}, * server MAC. */ var has_stateful = sw.has_stateful_acl or sw.has_lb_vip in Flow(.logical_datapath = sw.ls._uuid, - .stage = switch_stage(OUT, ACL), + .stage = s_SWITCH_OUT_ACL(), .priority = 34000, .__match = "outport == ${json_string_escape(lsp.name)} " "&& eth.src == ${server_mac} " @@ -2690,25 +2630,25 @@ QoSAction(qos, k, v) :- /* QoS rules */ for (&Switch(.ls = ls)) { Flow(.logical_datapath = ls._uuid, - .stage = switch_stage(IN, QOS_MARK), + .stage = s_SWITCH_IN_QOS_MARK(), .priority = 0, .__match = "1", .actions = "next;", .external_ids = map_empty()); Flow(.logical_datapath = ls._uuid, - .stage = switch_stage(OUT, QOS_MARK), + .stage = s_SWITCH_OUT_QOS_MARK(), .priority = 0, .__match = "1", .actions = "next;", .external_ids = map_empty()); Flow(.logical_datapath = ls._uuid, - .stage = switch_stage(IN, QOS_METER), + .stage = s_SWITCH_IN_QOS_METER(), .priority = 0, .__match = "1", .actions = "next;", .external_ids = map_empty()); Flow(.logical_datapath = ls._uuid, - .stage = switch_stage(OUT, QOS_METER), + .stage = s_SWITCH_OUT_QOS_METER(), .priority = 0, .__match = "1", .actions = "next;", @@ -2718,7 +2658,7 @@ for (&Switch(.ls = ls)) { for (SwitchQoS(.sw = &sw, .qos = &qos)) { var ingress = if (qos.direction == "from-lport") true else false in var pipeline = if ingress "ingress" else "egress" in { - var stage = if (ingress) { switch_stage(IN, QOS_MARK) } else { switch_stage(OUT, QOS_MARK) } in + var stage = if (ingress) { s_SWITCH_IN_QOS_MARK() } else { s_SWITCH_OUT_QOS_MARK() } in /* FIXME: Can value_action be negative? */ for (QoSAction(qos._uuid, key_action, value_action)) { if (key_action == "dscp") { @@ -2746,7 +2686,7 @@ for (SwitchQoS(.sw = &sw, .qos = &qos)) { (burst, rate) } in if (rate != 0) { - var stage = if (ingress) { switch_stage(IN, QOS_METER) } else { switch_stage(OUT, QOS_METER) } in + var stage = if (ingress) { s_SWITCH_IN_QOS_METER() } else { s_SWITCH_OUT_QOS_METER() } in var meter_action = if (burst != 0) { "set_meter(${rate}, ${burst}); next;" } else { @@ -2771,13 +2711,13 @@ for (&Switch(.ls = ls, .has_lb_vip = has_lb_vip)) { /* Ingress and Egress LB Table (Priority 0): Packets are allowed by * default. */ Flow(.logical_datapath = ls._uuid, - .stage = switch_stage(IN, LB), + .stage = s_SWITCH_IN_LB(), .priority = 0, .__match = "1", .actions = "next;", .external_ids = map_empty()); Flow(.logical_datapath = ls._uuid, - .stage = switch_stage(OUT, LB), + .stage = s_SWITCH_OUT_LB(), .priority = 0, .__match = "1", .actions = "next;", @@ -2788,13 +2728,13 @@ for (&Switch(.ls = ls, .has_lb_vip = has_lb_vip)) { .json_name = lsp_name, .sw = &Switch{.ls = ls})) { Flow(.logical_datapath = ls._uuid, - .stage = switch_stage(IN, LB), + .stage = s_SWITCH_IN_LB(), .priority = 65535, .__match = "ip && inport == ${lsp_name}", .actions = "next;", .external_ids = stage_hint(lsp._uuid)); Flow(.logical_datapath = ls._uuid, - .stage = switch_stage(OUT, LB), + .stage = s_SWITCH_OUT_LB(), .priority = 65535, .__match = "ip && outport == ${lsp_name}", .actions = "next;", @@ -2807,13 +2747,13 @@ for (&Switch(.ls = ls, .has_lb_vip = has_lb_vip)) { * * Send established traffic through conntrack for just NAT. */ Flow(.logical_datapath = ls._uuid, - .stage = switch_stage(IN, LB), + .stage = s_SWITCH_IN_LB(), .priority = 65534, .__match = "ct.est && !ct.rel && !ct.new && !ct.inv && ct_label.natted == 1", .actions = "${rEGBIT_CONNTRACK_NAT()} = 1; next;", .external_ids = map_empty()); Flow(.logical_datapath = ls._uuid, - .stage = switch_stage(OUT, LB), + .stage = s_SWITCH_OUT_LB(), .priority = 65534, .__match = "ct.est && !ct.rel && !ct.new && !ct.inv && ct_label.natted == 1", .actions = "${rEGBIT_CONNTRACK_NAT()} = 1; next;", @@ -2830,13 +2770,13 @@ for (&Switch(.ls = ls)) { /* Ingress and Egress stateful Table (Priority 0): Packets are * allowed by default. */ Flow(.logical_datapath = ls._uuid, - .stage = switch_stage(IN, STATEFUL), + .stage = s_SWITCH_IN_STATEFUL(), .priority = 0, .__match = "1", .actions = "next;", .external_ids = map_empty()); Flow(.logical_datapath = ls._uuid, - .stage = switch_stage(OUT, STATEFUL), + .stage = s_SWITCH_OUT_STATEFUL(), .priority = 0, .__match = "1", .actions = "next;", @@ -2847,13 +2787,13 @@ for (&Switch(.ls = ls)) { * any packet that makes it this far is part of a connection we * want to allow to continue. */ Flow(.logical_datapath = ls._uuid, - .stage = switch_stage(IN, STATEFUL), + .stage = s_SWITCH_IN_STATEFUL(), .priority = 100, .__match = "${rEGBIT_CONNTRACK_COMMIT()} == 1", .actions = "ct_commit { ct_label.blocked = 0; }; next;", .external_ids = map_empty()); Flow(.logical_datapath = ls._uuid, - .stage = switch_stage(OUT, STATEFUL), + .stage = s_SWITCH_OUT_STATEFUL(), .priority = 100, .__match = "${rEGBIT_CONNTRACK_COMMIT()} == 1", .actions = "ct_commit { ct_label.blocked = 0; }; next;", @@ -2871,14 +2811,14 @@ for (&Switch(.ls = ls)) { */ for (LbProtocol[protocol]) { Flow(.logical_datapath = ls._uuid, - .stage = switch_stage(IN, STATEFUL), + .stage = s_SWITCH_IN_STATEFUL(), .priority = 100, .__match = "${rEGBIT_CONNTRACK_NAT()} == 1 && ip4 && ${protocol}", .actions = "${rEG_ORIG_DIP_IPV4()} = ip4.dst; " "${rEG_ORIG_TP_DPORT()} = ${protocol}.dst; ct_lb;", .external_ids = map_empty()); Flow(.logical_datapath = ls._uuid, - .stage = switch_stage(IN, STATEFUL), + .stage = s_SWITCH_IN_STATEFUL(), .priority = 100, .__match = "${rEGBIT_CONNTRACK_NAT()} == 1 && ip6 && ${protocol}", .actions = "${rEG_ORIG_DIP_IPV6()} = ip6.dst; " @@ -2887,7 +2827,7 @@ for (&Switch(.ls = ls)) { }; Flow(.logical_datapath = ls._uuid, - .stage = switch_stage(OUT, STATEFUL), + .stage = s_SWITCH_OUT_STATEFUL(), .priority = 100, .__match = "${rEGBIT_CONNTRACK_NAT()} == 1", .actions = "ct_lb;", @@ -2945,7 +2885,7 @@ function ct_lb(backends: string, "ct_lb(" ++ args.join("; ") ++ ");" } function build_lb_vip_actions(lbvip: Ref, - table: integer, + stage: Stage, actions0: string): string { var up_backends = set_empty(); for (pair in lbvip.backends) { @@ -2957,7 +2897,7 @@ function build_lb_vip_actions(lbvip: Ref, if (up_backends.is_empty()) { if (map_get_bool_def(lbvip.lb.options, "reject", false)) { - return "reg0 = 0; reject { outport <-> inport; next(pipeline=egress,table=${table});};" + return "reg0 = 0; reject { outport <-> inport; ${next_to_stage(stage)};};" } else if (lbvip.health_check.is_some()) { return "drop;" } // else fall through @@ -2968,7 +2908,7 @@ function build_lb_vip_actions(lbvip: Ref, actions0 ++ actions } Flow(.logical_datapath = sw.ls._uuid, - .stage = switch_stage(IN, STATEFUL), + .stage = s_SWITCH_IN_STATEFUL(), .priority = priority, .__match = __match, .actions = actions, @@ -2995,7 +2935,7 @@ Flow(.logical_datapath = sw.ls._uuid, "" }; - build_lb_vip_actions(lbvip, stage_id(switch_stage(OUT, QOS_MARK)).0, actions0 ++ actions1) + build_lb_vip_actions(lbvip, s_SWITCH_OUT_QOS_MARK(), actions0 ++ actions1) }, var __match = "ct.new && " ++ get_match_for_lb_key(lbvip.vip_addr, lbvip.vip_port, lb.protocol, false). @@ -3003,13 +2943,15 @@ Flow(.logical_datapath = sw.ls._uuid, * Packets that don't need hairpinning should continue processing. */ Flow(.logical_datapath = ls_uuid, - .stage = switch_stage(IN, stage), + .stage = stage, .priority = 0, .__match = "1", .actions = "next;", .external_ids = map_empty()) :- &Switch(.ls = nb::Logical_Switch{._uuid = ls_uuid}), - var stages = [PRE_HAIRPIN, NAT_HAIRPIN, HAIRPIN], + var stages = [s_SWITCH_IN_PRE_HAIRPIN(), + s_SWITCH_IN_NAT_HAIRPIN(), + s_SWITCH_IN_HAIRPIN()], var stage = FlatMap(stages). for (&Switch(.ls = nb::Logical_Switch{._uuid = ls_uuid}, .has_lb_vip = true)) { /* Check if the packet needs to be hairpinned. @@ -3017,7 +2959,7 @@ for (&Switch(.ls = nb::Logical_Switch{._uuid = ls_uuid}, .has_lb_vip = true)) { * REGBIT_HAIRPIN_REPLY in the reply direction. */ Flow(.logical_datapath = ls_uuid, - .stage = switch_stage(IN, PRE_HAIRPIN), + .stage = s_SWITCH_IN_PRE_HAIRPIN(), .priority = 100, .__match = "ip && ct.trk", .actions = "${rEGBIT_HAIRPIN()} = chk_lb_hairpin(); " @@ -3028,7 +2970,7 @@ for (&Switch(.ls = nb::Logical_Switch{._uuid = ls_uuid}, .has_lb_vip = true)) { /* If packet needs to be hairpinned, snat the src ip with the VIP * for new sessions. */ Flow(.logical_datapath = ls_uuid, - .stage = switch_stage(IN, NAT_HAIRPIN), + .stage = s_SWITCH_IN_NAT_HAIRPIN(), .priority = 100, .__match = "ip && ct.new && ct.trk && ${rEGBIT_HAIRPIN()} == 1", .actions = "ct_snat_to_vip; next;", @@ -3038,7 +2980,7 @@ for (&Switch(.ls = nb::Logical_Switch{._uuid = ls_uuid}, .has_lb_vip = true)) { * should already be an SNAT conntrack entry. */ Flow(.logical_datapath = ls_uuid, - .stage = switch_stage(IN, NAT_HAIRPIN), + .stage = s_SWITCH_IN_NAT_HAIRPIN(), .priority = 100, .__match = "ip && ct.est && ct.trk && ${rEGBIT_HAIRPIN()} == 1", .actions = "ct_snat;", @@ -3046,7 +2988,7 @@ for (&Switch(.ls = nb::Logical_Switch{._uuid = ls_uuid}, .has_lb_vip = true)) { /* For the reply of hairpinned traffic, snat the src ip to the VIP. */ Flow(.logical_datapath = ls_uuid, - .stage = switch_stage(IN, NAT_HAIRPIN), + .stage = s_SWITCH_IN_NAT_HAIRPIN(), .priority = 90, .__match = "ip && ${rEGBIT_HAIRPIN_REPLY()} == 1", .actions = "ct_snat;", @@ -3057,7 +2999,7 @@ for (&Switch(.ls = nb::Logical_Switch{._uuid = ls_uuid}, .has_lb_vip = true)) { * looped back (i.e., swap ETH addresses and send back on inport). */ Flow(.logical_datapath = ls_uuid, - .stage = switch_stage(IN, HAIRPIN), + .stage = s_SWITCH_IN_HAIRPIN(), .priority = 1, .__match = "(${rEGBIT_HAIRPIN()} == 1 || ${rEGBIT_HAIRPIN_REPLY()} == 1)", .actions = "eth.dst <-> eth.src; outport = inport; flags.loopback = 1; output;", @@ -3080,7 +3022,7 @@ for (&SwitchPort(.lsp = lsp, .sw = &sw, .json_name = json_name, .ps_eth_addresse Some{id} -> "set_queue(${id}); next;" } in Flow(.logical_datapath = sw.ls._uuid, - .stage = switch_stage(IN, PORT_SEC_L2), + .stage = s_SWITCH_IN_PORT_SEC_L2(), .priority = 50, .__match = __match, .actions = actions, @@ -3115,7 +3057,7 @@ for (SwitchPortPSAddresses(.port = &port@SwitchPort{.sw = &sw}, .ps_addrs = ps) " && ip4.dst == 255.255.255.255" " && udp.src == 68 && udp.dst == 67" in { Flow(.logical_datapath = sw.ls._uuid, - .stage = switch_stage(IN, PORT_SEC_IP), + .stage = s_SWITCH_IN_PORT_SEC_IP(), .priority = 90, .__match = dhcp_match, .actions = "next;", @@ -3138,7 +3080,7 @@ for (SwitchPortPSAddresses(.port = &port@SwitchPort{.sw = &sw}, .ps_addrs = ps) addrs.join(", ") ++ "}" in { Flow(.logical_datapath = sw.ls._uuid, - .stage = switch_stage(IN, PORT_SEC_IP), + .stage = s_SWITCH_IN_PORT_SEC_IP(), .priority = 90, .__match = __match, .actions = "next;", @@ -3153,17 +3095,17 @@ for (SwitchPortPSAddresses(.port = &port@SwitchPort{.sw = &sw}, .ps_addrs = ps) " && icmp6.type == {131, 135, 143}" in { Flow(.logical_datapath = sw.ls._uuid, - .stage = switch_stage(IN, PORT_SEC_IP), + .stage = s_SWITCH_IN_PORT_SEC_IP(), .priority = 90, .__match = dad_match, .actions = "next;", .external_ids = stage_hint(port.lsp._uuid)) }; var __match = "inport == ${port.json_name} && eth.src == ${ps.ea}" ++ - build_port_security_ipv6_flow(IN, ps.ea, ps.ipv6_addrs) in + build_port_security_ipv6_flow(Ingress, ps.ea, ps.ipv6_addrs) in { Flow(.logical_datapath = sw.ls._uuid, - .stage = switch_stage(IN, PORT_SEC_IP), + .stage = s_SWITCH_IN_PORT_SEC_IP(), .priority = 90, .__match = __match, .actions = "next;", @@ -3173,7 +3115,7 @@ for (SwitchPortPSAddresses(.port = &port@SwitchPort{.sw = &sw}, .ps_addrs = ps) var __match = "inport == ${port.json_name} && eth.src == ${ps.ea} && ip" in { Flow(.logical_datapath = sw.ls._uuid, - .stage = switch_stage(IN, PORT_SEC_IP), + .stage = s_SWITCH_IN_PORT_SEC_IP(), .priority = 80, .__match = __match, .actions = "drop;", @@ -3221,7 +3163,7 @@ for (SwitchPortPSAddresses(.port = &port@SwitchPort{.sw = &sw}, .ps_addrs = ps) } } in { Flow(.logical_datapath = sw.ls._uuid, - .stage = switch_stage(IN, PORT_SEC_ND), + .stage = s_SWITCH_IN_PORT_SEC_ND(), .priority = 90, .__match = __match, .actions = "next;", @@ -3233,7 +3175,7 @@ for (SwitchPortPSAddresses(.port = &port@SwitchPort{.sw = &sw}, .ps_addrs = ps) build_port_security_ipv6_nd_flow(ps.ea, ps.ipv6_addrs) in { Flow(.logical_datapath = sw.ls._uuid, - .stage = switch_stage(IN, PORT_SEC_ND), + .stage = s_SWITCH_IN_PORT_SEC_ND(), .priority = 90, .__match = __match, .actions = "next;", @@ -3241,7 +3183,7 @@ for (SwitchPortPSAddresses(.port = &port@SwitchPort{.sw = &sw}, .ps_addrs = ps) } }; Flow(.logical_datapath = sw.ls._uuid, - .stage = switch_stage(IN, PORT_SEC_ND), + .stage = s_SWITCH_IN_PORT_SEC_ND(), .priority = 80, .__match = "inport == ${port.json_name} && (arp || nd)", .actions = "drop;", @@ -3253,13 +3195,13 @@ for (SwitchPortPSAddresses(.port = &port@SwitchPort{.sw = &sw}, .ps_addrs = ps) * default goto next. (priority 0)*/ for (&Switch(.ls = ls)) { Flow(.logical_datapath = ls._uuid, - .stage = switch_stage(IN, PORT_SEC_ND), + .stage = s_SWITCH_IN_PORT_SEC_ND(), .priority = 0, .__match = "1", .actions = "next;", .external_ids = map_empty()); Flow(.logical_datapath = ls._uuid, - .stage = switch_stage(IN, PORT_SEC_IP), + .stage = s_SWITCH_IN_PORT_SEC_IP(), .priority = 0, .__match = "1", .actions = "next;", @@ -3274,7 +3216,7 @@ for (&SwitchPort(.lsp = lsp, .sw = &sw, .json_name = json_name) (lsp.__type == "localnet" or lsp.__type == "vtep")) { Flow(.logical_datapath = sw.ls._uuid, - .stage = switch_stage(IN, ARP_ND_RSP), + .stage = s_SWITCH_IN_ARP_ND_RSP(), .priority = 100, .__match = "inport == ${json_name}", .actions = "next;", @@ -3295,7 +3237,7 @@ function lsp_is_up(lsp: nb::Logical_Switch_Port): bool = { * port of type 'virtual' and bind that port. * */ Flow(.logical_datapath = sp.sw.ls._uuid, - .stage = switch_stage(IN, ARP_ND_RSP), + .stage = s_SWITCH_IN_ARP_ND_RSP(), .priority = 100, .__match = "inport == ${vp.json_name} && " "((arp.op == 1 && arp.spa == ${virtual_ip} && arp.tpa == ${virtual_ip}) || " @@ -3338,7 +3280,7 @@ for (CheckLspIsUp[check_lsp_is_up]) { "flags.loopback = 1; " "output;" in Flow(.logical_datapath = sw.ls._uuid, - .stage = switch_stage(IN, ARP_ND_RSP), + .stage = s_SWITCH_IN_ARP_ND_RSP(), .priority = 50, .__match = __match, .actions = actions, @@ -3357,7 +3299,7 @@ for (CheckLspIsUp[check_lsp_is_up]) { * configured, so dropping the request would frustrate that * intent.) */ Flow(.logical_datapath = sw.ls._uuid, - .stage = switch_stage(IN, ARP_ND_RSP), + .stage = s_SWITCH_IN_ARP_ND_RSP(), .priority = 100, .__match = __match ++ " && inport == ${json_name}", .actions = "next;", @@ -3387,7 +3329,7 @@ for (SwitchPortIPv6Address(.port = &SwitchPort{.lsp = lsp, .json_name = json_nam "};" in { Flow(.logical_datapath = sw.ls._uuid, - .stage = switch_stage(IN, ARP_ND_RSP), + .stage = s_SWITCH_IN_ARP_ND_RSP(), .priority = 50, .__match = __match, .actions = actions, @@ -3396,7 +3338,7 @@ for (SwitchPortIPv6Address(.port = &SwitchPort{.lsp = lsp, .json_name = json_nam /* Do not reply to a solicitation from the port that owns the * address (otherwise DAD detection will fail). */ Flow(.logical_datapath = sw.ls._uuid, - .stage = switch_stage(IN, ARP_ND_RSP), + .stage = s_SWITCH_IN_ARP_ND_RSP(), .priority = 100, .__match = __match ++ " && inport == ${json_name}", .actions = "next;", @@ -3408,7 +3350,7 @@ for (SwitchPortIPv6Address(.port = &SwitchPort{.lsp = lsp, .json_name = json_nam * (priority 0)*/ for (ls in nb::Logical_Switch) { Flow(.logical_datapath = ls._uuid, - .stage = switch_stage(IN, ARP_ND_RSP), + .stage = s_SWITCH_IN_ARP_ND_RSP(), .priority = 0, .__match = "1", .actions = "next;", @@ -3418,7 +3360,7 @@ for (ls in nb::Logical_Switch) { /* Ingress table ARP_ND_RSP: ARP/ND responder for service monitor source ip. * (priority 110)*/ Flow(.logical_datapath = sp.sw.ls._uuid, - .stage = switch_stage(IN, ARP_ND_RSP), + .stage = s_SWITCH_IN_ARP_ND_RSP(), .priority = 110, .__match = "arp.tpa == ${svc_mon_src_ip} && arp.op == 1", .actions = "eth.dst = eth.src; " @@ -3638,7 +3580,7 @@ for (lsp in &SwitchPort "udp.src == 68 && udp.dst == 67" ++ sfx in Flow(.logical_datapath = lsuuid, - .stage = switch_stage(IN, DHCP_OPTIONS), + .stage = s_SWITCH_IN_DHCP_OPTIONS(), .priority = 100, .__match = __match, .actions = options_action, @@ -3655,7 +3597,7 @@ for (lsp in &SwitchPort var __match = pfx ++ "eth.src == ${ea} && " "${ipv4_addr_match} && udp.src == 68 && udp.dst == 67" ++ sfx in Flow(.logical_datapath = lsuuid, - .stage = switch_stage(IN, DHCP_OPTIONS), + .stage = s_SWITCH_IN_DHCP_OPTIONS(), .priority = 100, .__match = __match, .actions = options_action, @@ -3667,7 +3609,7 @@ for (lsp in &SwitchPort "ip4 && udp.src == 68 && udp.dst == 67 && " ++ rEGBIT_DHCP_OPTS_RESULT() ++ sfx in Flow(.logical_datapath = lsuuid, - .stage = switch_stage(IN, DHCP_RESPONSE), + .stage = s_SWITCH_IN_DHCP_RESPONSE(), .priority = 100, .__match = __match, .actions = response_action, @@ -3694,7 +3636,7 @@ for (lsp in &SwitchPort " udp.dst == 547" ++ sfx in { Flow(.logical_datapath = lsuuid, - .stage = switch_stage(IN, DHCP_OPTIONS), + .stage = s_SWITCH_IN_DHCP_OPTIONS(), .priority = 100, .__match = __match, .actions = options_action, @@ -3703,7 +3645,7 @@ for (lsp in &SwitchPort /* If REGBIT_DHCP_OPTS_RESULT is set to 1, it means the * put_dhcpv6_opts action is successful */ Flow(.logical_datapath = lsuuid, - .stage = switch_stage(IN, DHCP_RESPONSE), + .stage = s_SWITCH_IN_DHCP_RESPONSE(), .priority = 100, .__match = __match ++ " && ${rEGBIT_DHCP_OPTS_RESULT()}", .actions = response_action, @@ -3727,7 +3669,7 @@ for (lsp in &SwitchPort for (LogicalSwitchHasDNSRecords(ls, true)) { Flow(.logical_datapath = ls, - .stage = switch_stage(IN, DNS_LOOKUP), + .stage = s_SWITCH_IN_DNS_LOOKUP(), .priority = 100, .__match = "udp.dst == 53", .actions = "${rEGBIT_DNS_LOOKUP_RESULT()} = dns_lookup(); next;", @@ -3737,7 +3679,7 @@ for (LogicalSwitchHasDNSRecords(ls, true)) "udp.dst = udp.src; udp.src = 53; outport = inport; " "flags.loopback = 1; output;" in Flow(.logical_datapath = ls, - .stage = switch_stage(IN, DNS_RESPONSE), + .stage = s_SWITCH_IN_DNS_RESPONSE(), .priority = 100, .__match = "udp.dst == 53 && ${rEGBIT_DNS_LOOKUP_RESULT()}", .actions = action, @@ -3747,7 +3689,7 @@ for (LogicalSwitchHasDNSRecords(ls, true)) "udp.dst = udp.src; udp.src = 53; outport = inport; " "flags.loopback = 1; output;" in Flow(.logical_datapath = ls, - .stage = switch_stage(IN, DNS_RESPONSE), + .stage = s_SWITCH_IN_DNS_RESPONSE(), .priority = 100, .__match = "udp.dst == 53 && ${rEGBIT_DNS_LOOKUP_RESULT()}", .actions = action, @@ -3764,35 +3706,35 @@ for (LogicalSwitchHasDNSRecords(ls, true)) * (priority 0). */ for (ls in nb::Logical_Switch) { Flow(.logical_datapath = ls._uuid, - .stage = switch_stage(IN, DHCP_OPTIONS), + .stage = s_SWITCH_IN_DHCP_OPTIONS(), .priority = 0, .__match = "1", .actions = "next;", .external_ids = map_empty()); Flow(.logical_datapath = ls._uuid, - .stage = switch_stage(IN, DHCP_RESPONSE), + .stage = s_SWITCH_IN_DHCP_RESPONSE(), .priority = 0, .__match = "1", .actions = "next;", .external_ids = map_empty()); Flow(.logical_datapath = ls._uuid, - .stage = switch_stage(IN, DNS_LOOKUP), + .stage = s_SWITCH_IN_DNS_LOOKUP(), .priority = 0, .__match = "1", .actions = "next;", .external_ids = map_empty()); Flow(.logical_datapath = ls._uuid, - .stage = switch_stage(IN, DNS_RESPONSE), + .stage = s_SWITCH_IN_DNS_RESPONSE(), .priority = 0, .__match = "1", .actions = "next;", .external_ids = map_empty()); Flow(.logical_datapath = ls._uuid, - .stage = switch_stage(IN, EXTERNAL_PORT), + .stage = s_SWITCH_IN_EXTERNAL_PORT(), .priority = 0, .__match = "1", .actions = "next;", @@ -3800,7 +3742,7 @@ for (ls in nb::Logical_Switch) { } Flow(.logical_datapath = sw.ls._uuid, - .stage = switch_stage(IN, L2_LKUP), + .stage = s_SWITCH_IN_L2_LKUP(), .priority = 110, .__match = "eth.dst == $svc_monitor_mac", .actions = "handle_svc_check(inport);", @@ -3828,7 +3770,7 @@ for (sw in &Switch(.ls = ls, .mcast_cfg = &mcast_cfg) } in { /* Punt IGMP traffic to controller. */ UniqueFlow[Flow{.logical_datapath = ls._uuid, - .stage = switch_stage(IN, L2_LKUP), + .stage = s_SWITCH_IN_L2_LKUP(), .priority = 100, .__match = "ip4 && ip.proto == 2", .actions = "${igmp_act}", @@ -3836,7 +3778,7 @@ for (sw in &Switch(.ls = ls, .mcast_cfg = &mcast_cfg) /* Punt MLD traffic to controller. */ UniqueFlow[Flow{.logical_datapath = ls._uuid, - .stage = switch_stage(IN, L2_LKUP), + .stage = s_SWITCH_IN_L2_LKUP(), .priority = 100, .__match = "mldv1 || mldv2", .actions = "${igmp_act}", @@ -3847,7 +3789,7 @@ for (sw in &Switch(.ls = ls, .mcast_cfg = &mcast_cfg) */ var flood = json_string_escape(mC_FLOOD().0) in UniqueFlow[Flow{.logical_datapath = ls._uuid, - .stage = switch_stage(IN, L2_LKUP), + .stage = s_SWITCH_IN_L2_LKUP(), .priority = 85, .__match = "ip4.mcast && ip4.dst == 224.0.0.0/24", .actions = "outport = ${flood}; output;", @@ -3858,7 +3800,7 @@ for (sw in &Switch(.ls = ls, .mcast_cfg = &mcast_cfg) */ var flood = json_string_escape(mC_FLOOD().0) in UniqueFlow[Flow{.logical_datapath = ls._uuid, - .stage = switch_stage(IN, L2_LKUP), + .stage = s_SWITCH_IN_L2_LKUP(), .priority = 85, .__match = "ip6.mcast_flood", .actions = "outport = ${flood}; output;", @@ -3897,7 +3839,7 @@ for (sw in &Switch(.ls = ls, .mcast_cfg = &mcast_cfg) } } in UniqueFlow[Flow{.logical_datapath = ls._uuid, - .stage = switch_stage(IN, L2_LKUP), + .stage = s_SWITCH_IN_L2_LKUP(), .priority = 80, .__match = "ip4.mcast || ip6.mcast", .actions = @@ -3951,7 +3893,7 @@ for (IgmpSwitchMulticastGroup(.address = address, .switch = &sw)) { } } in UniqueFlow[Flow{.logical_datapath = sw.ls._uuid, - .stage = switch_stage(IN, L2_LKUP), + .stage = s_SWITCH_IN_L2_LKUP(), .priority = 90, .__match = "eth.mcast && ${ipX} && ${ipX}.dst == ${address}", .actions = @@ -3971,7 +3913,7 @@ for (IgmpSwitchMulticastGroup(.address = address, .switch = &sw)) { * address, if the ARP request is asking to translate the IP address of a * router port on LS. */ Flow(.logical_datapath = sp.sw.ls._uuid, - .stage = switch_stage(IN, EXTERNAL_PORT), + .stage = s_SWITCH_IN_EXTERNAL_PORT(), .priority = 100, .__match = ("inport == ${json_string_escape(localnet_port.1)} && " "eth.src == ${lp_addr.ea} && " @@ -3987,7 +3929,7 @@ Flow(.logical_datapath = sp.sw.ls._uuid, rp.lsp.__type == "router", SwitchPortIPv4Address(.port = rp, .addr = rp_addr). Flow(.logical_datapath = sp.sw.ls._uuid, - .stage = switch_stage(IN, EXTERNAL_PORT), + .stage = s_SWITCH_IN_EXTERNAL_PORT(), .priority = 100, .__match = ("inport == ${json_string_escape(localnet_port.1)} && " "eth.src == ${lp_addr.ea} && " @@ -4004,7 +3946,7 @@ Flow(.logical_datapath = sp.sw.ls._uuid, rp.lsp.__type == "router", SwitchPortIPv6Address(.port = rp, .addr = rp_addr). Flow(.logical_datapath = sp.sw.ls._uuid, - .stage = switch_stage(IN, EXTERNAL_PORT), + .stage = s_SWITCH_IN_EXTERNAL_PORT(), .priority = 100, .__match = ("inport == ${json_string_escape(localnet_port.1)} && " "eth.src == ${lp_addr.ea} && " @@ -4025,7 +3967,7 @@ Flow(.logical_datapath = sp.sw.ls._uuid, for (ls in nb::Logical_Switch) { var mc_flood = json_string_escape(mC_FLOOD().0) in UniqueFlow[Flow{.logical_datapath = ls._uuid, - .stage = switch_stage(IN, L2_LKUP), + .stage = s_SWITCH_IN_L2_LKUP(), .priority = 70, .__match = "eth.mcast", .actions = "outport = ${mc_flood}; output;", @@ -4038,7 +3980,7 @@ for (SwitchPortStaticAddresses(.port = &SwitchPort{.lsp = lsp, .json_name = json .addrs = addrs) if lsp.__type != "external") { Flow(.logical_datapath = sw.ls._uuid, - .stage = switch_stage(IN, L2_LKUP), + .stage = s_SWITCH_IN_L2_LKUP(), .priority = 50, .__match = "eth.dst == ${addrs.ea}", .actions = "outport = ${json_name}; output;", @@ -4079,7 +4021,7 @@ function lrouter_port_ip_reachable(rp: Ref, addr: v46_ip): bool { false } UniqueFlow[Flow{.logical_datapath = sw.ls._uuid, - .stage = switch_stage(IN, L2_LKUP), + .stage = s_SWITCH_IN_L2_LKUP(), .priority = 75, .__match = __match, .actions = actions, @@ -4167,7 +4109,7 @@ function get_arp_forward_ips(rp: Ref): (Set, Set) = * (This is why we match against fLAGBIT_NOT_VXLAN() here.) */ AnnotatedFlow(.f = Flow{.logical_datapath = sw.ls._uuid, - .stage = switch_stage(IN, L2_LKUP), + .stage = s_SWITCH_IN_L2_LKUP(), .priority = 80, .__match = fLAGBIT_NOT_VXLAN() ++ " && arp.op == 1 && arp.tpa == { " ++ @@ -4186,7 +4128,7 @@ AnnotatedFlow(.f = Flow{.logical_datapath = sw.ls._uuid, not all_ips_v4.is_empty(), var mc_flood_l2 = json_string_escape(mC_FLOOD_L2().0). AnnotatedFlow(.f = Flow{.logical_datapath = sw.ls._uuid, - .stage = switch_stage(IN, L2_LKUP), + .stage = s_SWITCH_IN_L2_LKUP(), .priority = 80, .__match = fLAGBIT_NOT_VXLAN() ++ " && nd_ns && nd.target == { " ++ @@ -4209,7 +4151,7 @@ for (SwitchPortNewDynamicAddress(.port = &SwitchPort{.lsp = lsp, .json_name = js .address = Some{addrs}) if lsp.__type != "external") { Flow(.logical_datapath = sw.ls._uuid, - .stage = switch_stage(IN, L2_LKUP), + .stage = s_SWITCH_IN_L2_LKUP(), .priority = 50, .__match = "eth.dst == ${addrs.ea}", .actions = "outport = ${json_name}; output;", @@ -4250,7 +4192,7 @@ for (&SwitchPort(.lsp = lsp, "eth.dst == ${mac}" } in Flow(.logical_datapath = sw.ls._uuid, - .stage = switch_stage(IN, L2_LKUP), + .stage = s_SWITCH_IN_L2_LKUP(), .priority = 50, .__match = __match, .actions = "outport = ${json_name}; output;", @@ -4266,7 +4208,7 @@ for (&SwitchPort(.lsp = lsp, Some{var nat_mac} = eth_addr_from_string(emac) in var __match = "eth.dst == ${nat_mac} && is_chassis_resident(${json_string_escape(lport)})" in Flow(.logical_datapath = sw.ls._uuid, - .stage = switch_stage(IN, L2_LKUP), + .stage = s_SWITCH_IN_L2_LKUP(), .priority = 50, .__match = __match, .actions = "outport = ${json_name}; output;", @@ -4288,14 +4230,14 @@ for (&SwitchPort(.lsp = lsp, /* Ingress table L2_LKUP and L2_UNKNOWN: Destination lookup for unknown MACs (priority 0). */ for (sw in &Switch(.ls = nb::Logical_Switch{._uuid = ls_uuid})) { Flow(.logical_datapath = ls_uuid, - .stage = switch_stage(IN, L2_LKUP), + .stage = s_SWITCH_IN_L2_LKUP(), .priority = 0, .__match = "1", .actions = "outport = get_fdb(eth.dst); next;", .external_ids = map_empty()); Flow(.logical_datapath = ls_uuid, - .stage = switch_stage(IN, L2_UNKNOWN), + .stage = s_SWITCH_IN_L2_UNKNOWN(), .priority = 50, .__match = "outport == \"none\"", .actions = if (sw.has_unknown_ports) { @@ -4307,7 +4249,7 @@ for (sw in &Switch(.ls = nb::Logical_Switch{._uuid = ls_uuid})) { .external_ids = map_empty()); Flow(.logical_datapath = ls_uuid, - .stage = switch_stage(IN, L2_UNKNOWN), + .stage = s_SWITCH_IN_L2_UNKNOWN(), .priority = 0, .__match = "1", .actions = "output;", @@ -4318,13 +4260,13 @@ for (sw in &Switch(.ls = nb::Logical_Switch{._uuid = ls_uuid})) { * Egress table PORT_SEC_L2: Egress port security L2 - multicast/broadcast (priority 100). */ for (&Switch(.ls = ls)) { Flow(.logical_datapath = ls._uuid, - .stage = switch_stage(OUT, PORT_SEC_IP), + .stage = s_SWITCH_OUT_PORT_SEC_IP(), .priority = 0, .__match = "1", .actions = "next;", .external_ids = map_empty()); Flow(.logical_datapath = ls._uuid, - .stage = switch_stage(OUT, PORT_SEC_L2), + .stage = s_SWITCH_OUT_PORT_SEC_L2(), .priority = 100, .__match = "eth.mcast", .actions = "output;", @@ -4332,13 +4274,13 @@ for (&Switch(.ls = ls)) { } Flow(.logical_datapath = ls_uuid, - .stage = switch_stage(IN, LOOKUP_FDB), + .stage = s_SWITCH_IN_LOOKUP_FDB(), .priority = 100, .__match = "inport == ${sp.json_name}", .actions = "$[rEGBIT_LKUP_FDB()} = lookup_fdb(inport, eth.src); next;", .external_ids = stage_hint(lsp_uuid)), Flow(.logical_datapath = ls_uuid, - .stage = switch_stage(IN, LOOKUP_FDB), + .stage = s_SWITCH_IN_LOOKUP_FDB(), .priority = 100, .__match = "inport == ${sp.json_name} && ${rEGBIT_LKUP_FDB()} == 0", .actions = "put_fdb(inport, eth.src); next;", @@ -4348,13 +4290,13 @@ Flow(.logical_datapath = ls_uuid, .ps_addresses = vec_empty()). Flow(.logical_datapath = ls._uuid, - .stage = switch_stage(IN, LOOKUP_FDB), + .stage = s_SWITCH_IN_LOOKUP_FDB(), .priority = 0, .__match = "1", .actions = "next;", .external_ids = map_empty()), Flow(.logical_datapath = ls._uuid, - .stage = switch_stage(IN, PUT_FDB), + .stage = s_SWITCH_IN_PUT_FDB(), .priority = 0, .__match = "1", .actions = "next;", @@ -4371,7 +4313,7 @@ Flow(.logical_datapath = ls._uuid, * Priority 150 rules drop packets to disabled logical ports, so that they * don't even receive multicast or broadcast packets. */ Flow(.logical_datapath = sw.ls._uuid, - .stage = switch_stage(OUT, PORT_SEC_L2), + .stage = s_SWITCH_OUT_PORT_SEC_L2(), .priority = 50, .__match = __match, .actions = queue_action ++ "output;", @@ -4394,7 +4336,7 @@ Flow(.logical_datapath = sw.ls._uuid, for (&SwitchPort(.lsp = lsp, .json_name = json_name, .sw = &sw) if not lsp.is_enabled() and lsp.__type != "external") { Flow(.logical_datapath = sw.ls._uuid, - .stage = switch_stage(OUT, PORT_SEC_L2), + .stage = s_SWITCH_OUT_PORT_SEC_L2(), .priority = 150, .__match = "outport == {$json_name}", .actions = "drop;", @@ -4426,7 +4368,7 @@ for (SwitchPortPSAddresses(.port = &SwitchPort{.lsp = lsp, .json_name = json_nam "outport == ${json_name} && eth.dst == ${ps.ea} && ip4.dst == {255.255.255.255, 224.0.0.0/4, " ++ addrs.join(", ") ++ "}" in Flow(.logical_datapath = sw.ls._uuid, - .stage = switch_stage(OUT, PORT_SEC_IP), + .stage = s_SWITCH_OUT_PORT_SEC_IP(), .priority = 90, .__match = __match, .actions = "next;", @@ -4434,9 +4376,9 @@ for (SwitchPortPSAddresses(.port = &SwitchPort{.lsp = lsp, .json_name = json_nam }; if (ps.ipv6_addrs.len() > 0) { var __match = "outport == ${json_name} && eth.dst == ${ps.ea}" ++ - build_port_security_ipv6_flow(OUT, ps.ea, ps.ipv6_addrs) in + build_port_security_ipv6_flow(Egress, ps.ea, ps.ipv6_addrs) in Flow(.logical_datapath = sw.ls._uuid, - .stage = switch_stage(OUT, PORT_SEC_IP), + .stage = s_SWITCH_OUT_PORT_SEC_IP(), .priority = 90, .__match = __match, .actions = "next;", @@ -4444,7 +4386,7 @@ for (SwitchPortPSAddresses(.port = &SwitchPort{.lsp = lsp, .json_name = json_nam }; var __match = "outport == ${json_name} && eth.dst == ${ps.ea} && ip" in Flow(.logical_datapath = sw.ls._uuid, - .stage = switch_stage(OUT, PORT_SEC_IP), + .stage = s_SWITCH_OUT_PORT_SEC_IP(), .priority = 80, .__match = __match, .actions = "drop;", @@ -4456,7 +4398,7 @@ for (&Router(.lr = lr)) { /* Logical VLANs not supported. * Broadcast/multicast source address is invalid. */ Flow(.logical_datapath = lr._uuid, - .stage = router_stage(IN, ADMISSION), + .stage = s_ROUTER_IN_ADMISSION(), .priority = 100, .__match = "vlan.present || eth.src[40]", .actions = "drop;", @@ -4485,7 +4427,7 @@ for (&RouterPort(.lrp = lrp, */ var actions = "${rEG_INPORT_ETH_ADDR()} = ${lrp_networks.ea}; next;" in { Flow(.logical_datapath = router.lr._uuid, - .stage = router_stage(IN, ADMISSION), + .stage = s_ROUTER_IN_ADMISSION(), .priority = 50, .__match = "eth.mcast && inport == ${json_name}", .actions = actions, @@ -4499,7 +4441,7 @@ for (&RouterPort(.lrp = lrp, " && is_chassis_resident(${json_string_escape(chassis_redirect_name(lrp.name))})" } else { "" } in Flow(.logical_datapath = router.lr._uuid, - .stage = router_stage(IN, ADMISSION), + .stage = s_ROUTER_IN_ADMISSION(), .priority = 50, .__match = __match, .actions = actions, @@ -4550,7 +4492,7 @@ var rLNR = rEGBIT_LOOKUP_NEIGHBOR_RESULT() in var rLNIR = rEGBIT_LOOKUP_NEIGHBOR_IP_RESULT() in { Flow(.logical_datapath = lr._uuid, - .stage = router_stage(IN, LOOKUP_NEIGHBOR), + .stage = s_ROUTER_IN_LOOKUP_NEIGHBOR(), .priority = 100, .__match = "arp.op == 2", .actions = @@ -4559,7 +4501,7 @@ var rLNIR = rEGBIT_LOOKUP_NEIGHBOR_IP_RESULT() in "next;", .external_ids = map_empty()); Flow(.logical_datapath = lr._uuid, - .stage = router_stage(IN, LOOKUP_NEIGHBOR), + .stage = s_ROUTER_IN_LOOKUP_NEIGHBOR(), .priority = 100, .__match = "nd_na", .actions = @@ -4568,7 +4510,7 @@ var rLNIR = rEGBIT_LOOKUP_NEIGHBOR_IP_RESULT() in "next;", .external_ids = map_empty()); Flow(.logical_datapath = lr._uuid, - .stage = router_stage(IN, LOOKUP_NEIGHBOR), + .stage = s_ROUTER_IN_LOOKUP_NEIGHBOR(), .priority = 100, .__match = "nd_ns", .actions = @@ -4581,7 +4523,7 @@ var rLNIR = rEGBIT_LOOKUP_NEIGHBOR_IP_RESULT() in /* For other packet types, we can skip neighbor learning. * So set REGBIT_LOOKUP_NEIGHBOR_RESULT to 1. */ Flow(.logical_datapath = lr._uuid, - .stage = router_stage(IN, LOOKUP_NEIGHBOR), + .stage = s_ROUTER_IN_LOOKUP_NEIGHBOR(), .priority = 0, .__match = "1", .actions = "${rLNR} = 1; next;", @@ -4590,7 +4532,7 @@ var rLNIR = rEGBIT_LOOKUP_NEIGHBOR_IP_RESULT() in /* Flows for LEARN_NEIGHBOR. */ /* Skip Neighbor learning if not required. */ Flow(.logical_datapath = lr._uuid, - .stage = router_stage(IN, LEARN_NEIGHBOR), + .stage = s_ROUTER_IN_LEARN_NEIGHBOR(), .priority = 100, .__match = "${rLNR} == 1" ++ @@ -4598,25 +4540,25 @@ var rLNIR = rEGBIT_LOOKUP_NEIGHBOR_IP_RESULT() in .actions = "next;", .external_ids = map_empty()); Flow(.logical_datapath = lr._uuid, - .stage = router_stage(IN, LEARN_NEIGHBOR), + .stage = s_ROUTER_IN_LEARN_NEIGHBOR(), .priority = 90, .__match = "arp", .actions = "put_arp(inport, arp.spa, arp.sha); next;", .external_ids = map_empty()); Flow(.logical_datapath = lr._uuid, - .stage = router_stage(IN, LEARN_NEIGHBOR), + .stage = s_ROUTER_IN_LEARN_NEIGHBOR(), .priority = 90, .__match = "arp", .actions = "put_arp(inport, arp.spa, arp.sha); next;", .external_ids = map_empty()); Flow(.logical_datapath = lr._uuid, - .stage = router_stage(IN, LEARN_NEIGHBOR), + .stage = s_ROUTER_IN_LEARN_NEIGHBOR(), .priority = 90, .__match = "nd_na", .actions = "put_nd(inport, nd.target, nd.tll); next;", .external_ids = map_empty()); Flow(.logical_datapath = lr._uuid, - .stage = router_stage(IN, LEARN_NEIGHBOR), + .stage = s_ROUTER_IN_LEARN_NEIGHBOR(), .priority = 90, .__match = "nd_ns", .actions = "put_nd(inport, ip6.src, nd.sll); next;", @@ -4649,7 +4591,7 @@ for (RouterPortNetworksIPv4Addr(rp@&RouterPort{.router = router}, addr)) { "${rLNIR} = 1; " "next;" in Flow(.logical_datapath = router.lr._uuid, - .stage = router_stage(IN, LOOKUP_NEIGHBOR), + .stage = s_ROUTER_IN_LOOKUP_NEIGHBOR(), .priority = 110, .__match = __match.join(" && "), .actions = actions, @@ -4661,7 +4603,7 @@ for (RouterPortNetworksIPv4Addr(rp@&RouterPort{.router = router}, addr)) { "${rLNIR} = lookup_arp_ip(inport, arp.spa); " } ++ "next;" in Flow(.logical_datapath = router.lr._uuid, - .stage = router_stage(IN, LOOKUP_NEIGHBOR), + .stage = s_ROUTER_IN_LOOKUP_NEIGHBOR(), .priority = 100, .__match = "${match0} && ${match1}", .actions = actions, @@ -4676,7 +4618,7 @@ for (router in &Router(.lr = lr, .mcast_cfg = &mcast_cfg)) { * source or destination, and zero network source or destination * (priority 100). */ Flow(.logical_datapath = lr._uuid, - .stage = router_stage(IN, IP_INPUT), + .stage = s_ROUTER_IN_IP_INPUT(), .priority = 100, .__match = "ip4.src_mcast ||" "ip4.src == 255.255.255.255 || " @@ -4693,7 +4635,7 @@ for (router in &Router(.lr = lr, .mcast_cfg = &mcast_cfg)) { * IPs are handled with priority-90 flows. */ Flow(.logical_datapath = lr._uuid, - .stage = router_stage(IN, IP_INPUT), + .stage = s_ROUTER_IN_IP_INPUT(), .priority = 85, .__match = "arp || nd", .actions = "drop;", @@ -4703,7 +4645,7 @@ for (router in &Router(.lr = lr, .mcast_cfg = &mcast_cfg)) { * router pipeline (e.g., router solicitations). */ Flow(.logical_datapath = lr._uuid, - .stage = router_stage(IN, IP_INPUT), + .stage = s_ROUTER_IN_IP_INPUT(), .priority = 84, .__match = "nd_rs || nd_ra", .actions = "next;", @@ -4711,7 +4653,7 @@ for (router in &Router(.lr = lr, .mcast_cfg = &mcast_cfg)) { /* Drop other reserved multicast. */ Flow(.logical_datapath = lr._uuid, - .stage = router_stage(IN, IP_INPUT), + .stage = s_ROUTER_IN_IP_INPUT(), .priority = 83, .__match = "ip6.mcast_rsvd", .actions = "drop;", @@ -4720,7 +4662,7 @@ for (router in &Router(.lr = lr, .mcast_cfg = &mcast_cfg)) { /* Allow other multicast if relay enabled (priority 82). */ var mcast_action = { if (mcast_cfg.relay) { "next;" } else { "drop;" } } in Flow(.logical_datapath = lr._uuid, - .stage = router_stage(IN, IP_INPUT), + .stage = s_ROUTER_IN_IP_INPUT(), .priority = 82, .__match = "ip4.mcast || ip6.mcast", .actions = mcast_action, @@ -4729,7 +4671,7 @@ for (router in &Router(.lr = lr, .mcast_cfg = &mcast_cfg)) { /* Drop Ethernet local broadcast. By definition this traffic should * not be forwarded.*/ Flow(.logical_datapath = lr._uuid, - .stage = router_stage(IN, IP_INPUT), + .stage = s_ROUTER_IN_IP_INPUT(), .priority = 50, .__match = "eth.bcast", .actions = "drop;", @@ -4738,7 +4680,7 @@ for (router in &Router(.lr = lr, .mcast_cfg = &mcast_cfg)) { /* TTL discard */ Flow( .logical_datapath = lr._uuid, - .stage = router_stage(IN, IP_INPUT), + .stage = s_ROUTER_IN_IP_INPUT(), .priority = 30, .__match = "ip4 && ip.ttl == {0, 1}", .actions = "drop;", @@ -4747,7 +4689,7 @@ for (router in &Router(.lr = lr, .mcast_cfg = &mcast_cfg)) { /* Pass other traffic not already handled to the next table for * routing. */ Flow(.logical_datapath = lr._uuid, - .stage = router_stage(IN, IP_INPUT), + .stage = s_ROUTER_IN_IP_INPUT(), .priority = 0, .__match = "1", .actions = "next;", @@ -4834,7 +4776,7 @@ for (&RouterPort(.router = &router, .networks = networks, .lrp = lrp) format_v4_networks(networks, true) ++ " && ${rEGBIT_EGRESS_LOOPBACK()} == 0" in Flow(.logical_datapath = router.lr._uuid, - .stage = router_stage(IN, IP_INPUT), + .stage = s_ROUTER_IN_IP_INPUT(), .priority = 100, .__match = __match, .actions = "drop;", @@ -4849,7 +4791,7 @@ for (&RouterPort(.router = &router, .networks = networks, .lrp = lrp) format_v4_networks(networks, false) ++ " && icmp4.type == 8 && icmp4.code == 0" in Flow(.logical_datapath = router.lr._uuid, - .stage = router_stage(IN, IP_INPUT), + .stage = s_ROUTER_IN_IP_INPUT(), .priority = 90, .__match = __match, .actions = "ip4.dst <-> ip4.src; " @@ -4969,7 +4911,7 @@ relation LogicalRouterArpFlow( priority: integer, external_ids: Map) Flow(.logical_datapath = lr.lr._uuid, - .stage = router_stage(IN, IP_INPUT), + .stage = s_ROUTER_IN_IP_INPUT(), .priority = priority, .__match = __match, .actions = actions, @@ -5014,7 +4956,7 @@ relation LogicalRouterNdFlow( priority: integer, external_ids: Map) Flow(.logical_datapath = lr.lr._uuid, - .stage = router_stage(IN, IP_INPUT), + .stage = s_ROUTER_IN_IP_INPUT(), .priority = priority, .__match = __match, .actions = actions, @@ -5059,7 +5001,7 @@ for (RouterPortNetworksIPv4Addr(.port = &RouterPort{.lrp = lrp, .addr = addr)) { Flow(.logical_datapath = router.lr._uuid, - .stage = router_stage(IN, IP_INPUT), + .stage = s_ROUTER_IN_IP_INPUT(), .priority = 40, .__match = "inport == ${json_name} && ip4 && " "ip.ttl == {0, 1} && !ip.later_frag", @@ -5135,7 +5077,7 @@ var residence_check = match (is_redirect) { * Priority 60. */ Flow(.logical_datapath = lr_uuid, - .stage = router_stage(IN, IP_INPUT), + .stage = s_ROUTER_IN_IP_INPUT(), .priority = 60, .__match = "ip4.dst == {" ++ match_ips.join(", ") ++ "}", .actions = "drop;", @@ -5148,7 +5090,7 @@ Flow(.logical_datapath = lr_uuid, not snat_ips.contains_key(IPv4{addr.addr}), var match_ips = "${addr.addr}".group_by((lr_uuid, lrp_uuid)).to_vec(). Flow(.logical_datapath = lr_uuid, - .stage = router_stage(IN, IP_INPUT), + .stage = s_ROUTER_IN_IP_INPUT(), .priority = 60, .__match = "ip6.dst == {" ++ match_ips.join(", ") ++ "}", .actions = "drop;", @@ -5172,7 +5114,7 @@ for (RouterPortNetworksIPv4Addr( /* UDP/TCP/SCTP port unreachable. */ var __match = "ip4 && ip4.dst == ${addr.addr} && !ip.later_frag && udp" in Flow(.logical_datapath = lr._uuid, - .stage = router_stage(IN, IP_INPUT), + .stage = s_ROUTER_IN_IP_INPUT(), .priority = 80, .__match = __match, .actions = "icmp4 {" @@ -5186,7 +5128,7 @@ for (RouterPortNetworksIPv4Addr( var __match = "ip4 && ip4.dst == ${addr.addr} && !ip.later_frag && tcp" in Flow(.logical_datapath = lr._uuid, - .stage = router_stage(IN, IP_INPUT), + .stage = s_ROUTER_IN_IP_INPUT(), .priority = 80, .__match = __match, .actions = "tcp_reset {" @@ -5197,7 +5139,7 @@ for (RouterPortNetworksIPv4Addr( var __match = "ip4 && ip4.dst == ${addr.addr} && !ip.later_frag && sctp" in Flow(.logical_datapath = lr._uuid, - .stage = router_stage(IN, IP_INPUT), + .stage = s_ROUTER_IN_IP_INPUT(), .priority = 80, .__match = __match, .actions = "sctp_abort {" @@ -5208,7 +5150,7 @@ for (RouterPortNetworksIPv4Addr( var __match = "ip4 && ip4.dst == ${addr.addr} && !ip.later_frag" in Flow(.logical_datapath = lr._uuid, - .stage = router_stage(IN, IP_INPUT), + .stage = s_ROUTER_IN_IP_INPUT(), .priority = 70, .__match = __match, .actions = "icmp4 {" @@ -5223,7 +5165,7 @@ for (RouterPortNetworksIPv4Addr( /* DHCPv6 reply handling */ Flow(.logical_datapath = rp.router.lr._uuid, - .stage = router_stage(IN, IP_INPUT), + .stage = s_ROUTER_IN_IP_INPUT(), .priority = 100, .__match = "ip6.dst == ${ipv6_addr.addr} " "&& udp.src == 547 && udp.dst == 546", @@ -5248,7 +5190,7 @@ for (&RouterPort(.router = &router, .networks = networks, .lrp = lrp) format_v6_networks(networks) ++ " && icmp6.type == 128 && icmp6.code == 0" in Flow(.logical_datapath = router.lr._uuid, - .stage = router_stage(IN, IP_INPUT), + .stage = s_ROUTER_IN_IP_INPUT(), .priority = 90, .__match = __match, .actions = "ip6.dst <-> ip6.src; " @@ -5299,7 +5241,7 @@ for (RouterPortNetworksIPv6Addr( { var __match = "ip6 && ip6.dst == ${addr.addr} && !ip.later_frag && tcp" in Flow(.logical_datapath = lr._uuid, - .stage = router_stage(IN, IP_INPUT), + .stage = s_ROUTER_IN_IP_INPUT(), .priority = 80, .__match = __match, .actions = "tcp_reset {" @@ -5310,7 +5252,7 @@ for (RouterPortNetworksIPv6Addr( var __match = "ip6 && ip6.dst == ${addr.addr} && !ip.later_frag && sctp" in Flow(.logical_datapath = lr._uuid, - .stage = router_stage(IN, IP_INPUT), + .stage = s_ROUTER_IN_IP_INPUT(), .priority = 80, .__match = __match, .actions = "sctp_abort {" @@ -5321,7 +5263,7 @@ for (RouterPortNetworksIPv6Addr( var __match = "ip6 && ip6.dst == ${addr.addr} && !ip.later_frag && udp" in Flow(.logical_datapath = lr._uuid, - .stage = router_stage(IN, IP_INPUT), + .stage = s_ROUTER_IN_IP_INPUT(), .priority = 80, .__match = __match, .actions = "icmp6 {" @@ -5335,7 +5277,7 @@ for (RouterPortNetworksIPv6Addr( var __match = "ip6 && ip6.dst == ${addr.addr} && !ip.later_frag" in Flow(.logical_datapath = lr._uuid, - .stage = router_stage(IN, IP_INPUT), + .stage = s_ROUTER_IN_IP_INPUT(), .priority = 70, .__match = __match, .actions = "icmp6 {" @@ -5368,7 +5310,7 @@ for (RouterPortNetworksIPv6Addr(.port = &RouterPort{.router = &router, "icmp6.code = 0; /* TTL exceeded in transit */ " "next; };" in Flow(.logical_datapath = router.lr._uuid, - .stage = router_stage(IN, IP_INPUT), + .stage = s_ROUTER_IN_IP_INPUT(), .priority = 40, .__match = __match, .actions = actions, @@ -5387,19 +5329,19 @@ function default_allow_flow(datapath: uuid, stage: Stage): Flow { } for (&Router(.lr = lr)) { /* Packets are allowed by default. */ - Flow[default_allow_flow(lr._uuid, router_stage(IN, DEFRAG))]; - Flow[default_allow_flow(lr._uuid, router_stage(IN, UNSNAT))]; - Flow[default_allow_flow(lr._uuid, router_stage(OUT, SNAT))]; - Flow[default_allow_flow(lr._uuid, router_stage(IN, DNAT))]; - Flow[default_allow_flow(lr._uuid, router_stage(OUT, UNDNAT))]; - Flow[default_allow_flow(lr._uuid, router_stage(OUT, EGR_LOOP))]; - Flow[default_allow_flow(lr._uuid, router_stage(IN, ECMP_STATEFUL))]; + Flow[default_allow_flow(lr._uuid, s_ROUTER_IN_DEFRAG())]; + Flow[default_allow_flow(lr._uuid, s_ROUTER_IN_UNSNAT())]; + Flow[default_allow_flow(lr._uuid, s_ROUTER_OUT_SNAT())]; + Flow[default_allow_flow(lr._uuid, s_ROUTER_IN_DNAT())]; + Flow[default_allow_flow(lr._uuid, s_ROUTER_OUT_UNDNAT())]; + Flow[default_allow_flow(lr._uuid, s_ROUTER_OUT_EGR_LOOP())]; + Flow[default_allow_flow(lr._uuid, s_ROUTER_IN_ECMP_STATEFUL())]; /* Send the IPv6 NS packets to next table. When ovn-controller * generates IPv6 NS (for the action - nd_ns{}), the injected * packet would go through conntrack - which is not required. */ Flow(.logical_datapath = lr._uuid, - .stage = router_stage(OUT, SNAT), + .stage = s_ROUTER_OUT_SNAT(), .priority = 120, .__match = "nd_ns", .actions = "next;", @@ -5462,7 +5404,7 @@ function lrouter_nat_add_ext_ip_match( ("", Some{Flow{.logical_datapath = router.lr._uuid, - .stage = if (is_src) { router_stage(IN, DNAT) } else { router_stage(OUT, SNAT) }, + .stage = if (is_src) { s_ROUTER_IN_DNAT() } else { s_ROUTER_OUT_SNAT() }, .priority = priority, .__match = "${__match} && ${ipX}.${dir} == $${__as.name}", .actions = "next;", @@ -5476,7 +5418,7 @@ relation LogicalRouterForceSnatFlows( ips: Set, context: string) Flow(.logical_datapath = logical_router, - .stage = router_stage(IN, UNSNAT), + .stage = s_ROUTER_IN_UNSNAT(), .priority = 110, .__match = "${ipX} && ${ipX}.dst == ${ip}", .actions = "ct_snat;", @@ -5485,7 +5427,7 @@ Flow(.logical_datapath = logical_router, * configured in the Gateway router. This only takes effect * when the packet has already been DNATed or load balanced once. */ Flow(.logical_datapath = logical_router, - .stage = router_stage(OUT, SNAT), + .stage = s_ROUTER_OUT_SNAT(), .priority = 100, .__match = "flags.force_snat_for_${context} == 1 && ${ipX}", .actions = "ct_snat(%{ip});", @@ -5503,7 +5445,7 @@ for (rp in &RouterPort(.router = &Router{.lr = lr}, .lrp = lrp)) { if (lb_force_snat_router_ip(lrp.options) and rp.peer != PeerNone) { Some{var ipv4} = rp.networks.ipv4_addrs.nth(0) in { Flow(.logical_datapath = lr._uuid, - .stage = router_stage(OUT, SNAT), + .stage = s_ROUTER_OUT_SNAT(), .priority = 110, .__match = "flags.force_snat_for_lb == 1 && ip4 && outport == ${rp.json_name}", .actions = "ct_snat(${ipv4.addr});", @@ -5521,7 +5463,7 @@ for (rp in &RouterPort(.router = &Router{.lr = lr}, .lrp = lrp)) { if (rp.networks.ipv6_addrs.len() > 1) { Some{var ipv6} = rp.networks.ipv6_addrs.nth(0) in { Flow(.logical_datapath = lr._uuid, - .stage = router_stage(OUT, SNAT), + .stage = s_ROUTER_OUT_SNAT(), .priority = 110, .__match = "flags.force_snat_for_lb == 1 && ip6 && outport == ${rp.json_name}", .actions = "ct_snat(${ipv6.addr});", @@ -5588,7 +5530,7 @@ for (r in &Router(.lr = lr, "ct_snat;" } in Flow(.logical_datapath = lr._uuid, - .stage = router_stage(IN, UNSNAT), + .stage = s_ROUTER_IN_UNSNAT(), .priority = 90, .__match = "ip && ${ipX}.dst == ${nat.nat.external_ip}", .actions = actions, @@ -5612,7 +5554,7 @@ for (r in &Router(.lr = lr, "ct_snat;" } in Flow(.logical_datapath = lr._uuid, - .stage = router_stage(IN, UNSNAT), + .stage = s_ROUTER_IN_UNSNAT(), .priority = 100, .__match = __match, .actions = actions, @@ -5655,7 +5597,7 @@ for (r in &Router(.lr = lr, "ct_dnat(${ip_and_ports});" } in Flow(.logical_datapath = lr._uuid, - .stage = router_stage(IN, DNAT), + .stage = s_ROUTER_IN_DNAT(), .priority = 100, .__match = __match ++ ext_ip_match, .actions = flag_action ++ nat_actions, @@ -5684,7 +5626,7 @@ for (r in &Router(.lr = lr, "ct_dnat(${ip_and_ports});" } in Flow(.logical_datapath = lr._uuid, - .stage = router_stage(IN, DNAT), + .stage = s_ROUTER_IN_DNAT(), .priority = 100, .__match = __match ++ ext_ip_match, .actions = actions, @@ -5699,7 +5641,7 @@ for (r in &Router(.lr = lr, var __match = "inport == ${gwport_name} && " "${ipX}.src == ${nat.nat.external_ip}" in Flow(.logical_datapath = lr._uuid, - .stage = router_stage(IN, IP_INPUT), + .stage = s_ROUTER_IN_IP_INPUT(), .priority = 120, .__match = __match, .actions = "next;", @@ -5714,7 +5656,7 @@ for (r in &Router(.lr = lr, None -> gwport.mac } in Flow(.logical_datapath = lr._uuid, - .stage = router_stage(IN, ARP_RESOLVE), + .stage = s_ROUTER_IN_ARP_RESOLVE(), .priority = 100, .__match = __match, .actions = "eth.dst = ${dst_mac}; next;", @@ -5751,7 +5693,7 @@ for (r in &Router(.lr = lr, "ct_dnat;" } in Flow(.logical_datapath = lr._uuid, - .stage = router_stage(OUT, UNDNAT), + .stage = s_ROUTER_OUT_UNDNAT(), .priority = 100, .__match = __match, .actions = actions, @@ -5786,7 +5728,7 @@ for (r in &Router(.lr = lr, } in Some{var plen} = ip46_count_cidr_bits(mask) in Flow(.logical_datapath = lr._uuid, - .stage = router_stage(OUT, SNAT), + .stage = s_ROUTER_OUT_SNAT(), .priority = plen as bit<64> + 1, .__match = __match ++ ext_ip_match, .actions = actions, @@ -5824,7 +5766,7 @@ for (r in &Router(.lr = lr, var priority = (plen as bit<64>) + 1 in var centralized_boost = if (mac == None) 128 else 0 in Flow(.logical_datapath = lr._uuid, - .stage = router_stage(OUT, SNAT), + .stage = s_ROUTER_OUT_SNAT(), .priority = priority + centralized_boost, .__match = __match ++ ext_ip_match, .actions = actions, @@ -5849,7 +5791,7 @@ for (r in &Router(.lr = lr, */ var actions = "${rEG_INPORT_ETH_ADDR()} = ${gwport.mac}; next;" in Flow(.logical_datapath = lr._uuid, - .stage = router_stage(IN, ADMISSION), + .stage = s_ROUTER_IN_ADMISSION(), .priority = 50, .__match = __match, .actions = actions, @@ -5876,7 +5818,7 @@ for (r in &Router(.lr = lr, "${xx}${rEG_SRC()} = ${nat.nat.external_ip}; " "next;" in Flow(.logical_datapath = lr._uuid, - .stage = router_stage(IN, GW_REDIRECT), + .stage = s_ROUTER_IN_GW_REDIRECT(), .priority = 100, .__match = __match, .actions = actions, @@ -5912,7 +5854,7 @@ for (r in &Router(.lr = lr, "${rEGBIT_EGRESS_LOOPBACK()} = 1; " "next(pipeline=ingress, table=0); };" in Flow(.logical_datapath = lr._uuid, - .stage = router_stage(OUT, EGR_LOOP), + .stage = s_ROUTER_OUT_EGR_LOOP(), .priority = 100, .__match = __match, .actions = actions, @@ -5944,7 +5886,7 @@ for (r in &Router(.lr = lr, * ip address being external IP address for IP routing, * we can do it here, saving a future re-circulation. */ Flow(.logical_datapath = lr._uuid, - .stage = router_stage(IN, DNAT), + .stage = s_ROUTER_IN_DNAT(), .priority = 50, .__match = "ip", .actions = "flags.loopback = 1; ct_dnat;", @@ -5980,7 +5922,7 @@ for (RouterLBVIP( Some {(var __match, var __action)} = build_empty_lb_event_flow(vip, lb, has_elb_meter) in Flow(.logical_datapath = lr._uuid, - .stage = router_stage(IN, DNAT), + .stage = s_ROUTER_IN_DNAT(), .priority = 130, .__match = __match, .actions = __action, @@ -6012,7 +5954,7 @@ for (RouterLBVIP( * different port numbers will produce identical flows that will * get merged by DDlog. */ Flow(.logical_datapath = lr._uuid, - .stage = router_stage(IN, DEFRAG), + .stage = s_ROUTER_IN_DEFRAG(), .priority = 100, .__match = __match, .actions = "ct_next;", @@ -6045,7 +5987,7 @@ for (RouterLBVIP( false -> "ct_dnat;" } in Flow(.logical_datapath = lr._uuid, - .stage = router_stage(IN, DNAT), + .stage = s_ROUTER_IN_DNAT(), .priority = prio, .__match = est_match, .actions = actions, @@ -6067,7 +6009,7 @@ for (RouterLBVIP( if (port != 0) { " && ${proto}.dst == ${port}" } else { "" } in Flow(.logical_datapath = lr._uuid, - .stage = router_stage(IN, UNSNAT), + .stage = s_ROUTER_IN_UNSNAT(), .priority = 120, .__match = match3, .actions = "next;", @@ -6106,7 +6048,7 @@ for (RouterLBVIP( false -> "ct_dnat;" } in Flow(.logical_datapath = lr._uuid, - .stage = router_stage(OUT, UNDNAT), + .stage = s_ROUTER_OUT_UNDNAT(), .priority = 120, .__match = undnat_match, .actions = action, @@ -6121,7 +6063,7 @@ for (RouterLBVIP( * on ct.new with an action of "ct_lb($targets);". The other * flow is for ct.est with an action of "ct_dnat;". */ Flow(.logical_datapath = r.lr._uuid, - .stage = router_stage(IN, DNAT), + .stage = s_ROUTER_IN_DNAT(), .priority = priority, .__match = __match, .actions = actions, @@ -6139,7 +6081,7 @@ Flow(.logical_datapath = r.lr._uuid, }, var priority = if (lbvip.vip_port != 0) 120 else 110, var force_snat = if (has_force_snat_ip(r.lr, "lb")) "flags.force_snat_for_lb = 1; " else "", - var actions = build_lb_vip_actions(lbvip, stage_id(router_stage(OUT, SNAT)).0, force_snat). + var actions = build_lb_vip_actions(lbvip, s_ROUTER_OUT_SNAT(), force_snat). /* Defaults based on MaxRtrInterval and MinRtrInterval from RFC 4861 section @@ -6300,7 +6242,7 @@ for (&RouterPort[port@RouterPort{.lrp = lrp@nb::Logical_Router_Port{.peer = None } in var actions = actions0 ++ router_preference ++ prefix ++ "); next;" in Flow(.logical_datapath = router.lr._uuid, - .stage = router_stage(IN, ND_RA_OPTIONS), + .stage = s_ROUTER_IN_ND_RA_OPTIONS(), .priority = 50, .__match = __match, .actions = actions, @@ -6314,7 +6256,7 @@ for (&RouterPort[port@RouterPort{.lrp = lrp@nb::Logical_Router_Port{.peer = None "outport = inport; flags.loopback = 1; " "output;" in Flow(.logical_datapath = router.lr._uuid, - .stage = router_stage(IN, ND_RA_RESPONSE), + .stage = s_ROUTER_IN_ND_RA_RESPONSE(), .priority = 50, .__match = __match, .actions = actions, @@ -6329,13 +6271,13 @@ for (&RouterPort[port@RouterPort{.lrp = lrp@nb::Logical_Router_Port{.peer = None for (&Router(.lr = lr)) { Flow(.logical_datapath = lr._uuid, - .stage = router_stage(IN, ND_RA_OPTIONS), + .stage = s_ROUTER_IN_ND_RA_OPTIONS(), .priority = 0, .__match = "1", .actions = "next;", .external_ids = map_empty()); Flow(.logical_datapath = lr._uuid, - .stage = router_stage(IN, ND_RA_RESPONSE), + .stage = s_ROUTER_IN_ND_RA_RESPONSE(), .priority = 0, .__match = "1", .actions = "next;", @@ -6397,7 +6339,7 @@ for (Route(.port = port, "next;" in { Flow(.logical_datapath = port.router.lr._uuid, - .stage = router_stage(IN, IP_ROUTING), + .stage = s_ROUTER_IN_IP_ROUTING(), .priority = priority as integer, .__match = __match, .actions = "ip.ttl--; ${actions}", @@ -6405,7 +6347,7 @@ for (Route(.port = port, if (port.has_bfd) { Flow(.logical_datapath = port.router.lr._uuid, - .stage = router_stage(IN, IP_ROUTING), + .stage = s_ROUTER_IN_IP_ROUTING(), .priority = priority as integer + 1, .__match = "${__match} && udp.dst == 3784", .actions = actions, @@ -6440,7 +6382,7 @@ Route(key, port, src_ip, None) :- var src_ip = IPv6{addr.addr}. Flow(.logical_datapath = r.lr._uuid, - .stage = router_stage(IN, IP_ROUTING_ECMP), + .stage = s_ROUTER_IN_IP_ROUTING_ECMP(), .priority = 150, .__match = "${rEG_ECMP_GROUP_ID()} == 0", .actions = "next;", @@ -6482,7 +6424,7 @@ EcmpGroup(group_id, router, key, dsts, route_match, route_priority) :- var route_priority = route_priority0 as integer. Flow(.logical_datapath = router.lr._uuid, - .stage = router_stage(IN, IP_ROUTING), + .stage = s_ROUTER_IN_IP_ROUTING(), .priority = route_priority, .__match = route_match, .actions = actions, @@ -6502,7 +6444,7 @@ Flow(.logical_datapath = router.lr._uuid, "${rEG_ECMP_MEMBER_ID()} = select(${all_member_ids});". Flow(.logical_datapath = router.lr._uuid, - .stage = router_stage(IN, IP_ROUTING_ECMP), + .stage = s_ROUTER_IN_IP_ROUTING_ECMP(), .priority = 100, .__match = __match, .actions = actions, @@ -6535,7 +6477,7 @@ EcmpSymmetricReply(router, dst, route_match, tunkey) :- PortTunKeyAllocation(.port = dst.port.lrp._uuid, .tunkey = tunkey). Flow(.logical_datapath = router.lr._uuid, - .stage = router_stage(IN, DEFRAG), + .stage = s_ROUTER_IN_DEFRAG(), .priority = 100, .__match = __match, .actions = "ct_next;", @@ -6550,7 +6492,7 @@ Flow(.logical_datapath = router.lr._uuid, * an ECMP route. */ Flow(.logical_datapath = router.lr._uuid, - .stage = router_stage(IN, ECMP_STATEFUL), + .stage = s_ROUTER_IN_ECMP_STATEFUL(), .priority = 100, .__match = __match, .actions = actions, @@ -6565,7 +6507,7 @@ Flow(.logical_datapath = router.lr._uuid, * for where to route the packet. */ Flow(.logical_datapath = router.lr._uuid, - .stage = router_stage(IN, IP_ROUTING), + .stage = s_ROUTER_IN_IP_ROUTING(), .priority = 100, .__match = "${ecmp_reply} && ${route_match}", .actions = "ip.ttl--; " @@ -6577,13 +6519,13 @@ Flow(.logical_datapath = router.lr._uuid, .external_ids = map_empty()), /* Egress reply traffic for symmetric ECMP routes skips router policies. */ Flow(.logical_datapath = router.lr._uuid, - .stage = router_stage(IN, POLICY), + .stage = s_ROUTER_IN_POLICY(), .priority = 65535, .__match = ecmp_reply, .actions = "next;", .external_ids = map_empty()), Flow(.logical_datapath = router.lr._uuid, - .stage = router_stage(IN, ARP_RESOLVE), + .stage = s_ROUTER_IN_ARP_RESOLVE(), .priority = 200, .__match = ecmp_reply, .actions = "eth.dst = ct_label.ecmp_reply_eth; next;", @@ -6600,7 +6542,7 @@ Flow(.logical_datapath = router.lr._uuid, * i.e., router solicitation and router advertisement. */ Flow(.logical_datapath = router.lr._uuid, - .stage = router_stage(IN, IP_ROUTING), + .stage = s_ROUTER_IN_IP_ROUTING(), .priority = 550, .__match = "nd_rs || nd_ra", .actions = "drop;", @@ -6625,7 +6567,7 @@ for (IgmpRouterMulticastGroup(address, &rtr, ports)) { Some{var ip} = ip46_parse(address) in var ipX = ip46_ipX(ip) in UniqueFlow[Flow{.logical_datapath = rtr.lr._uuid, - .stage = router_stage(IN, IP_ROUTING), + .stage = s_ROUTER_IN_IP_ROUTING(), .priority = 500, .__match = "${ipX} && ${ipX}.dst == ${address} ", .actions = @@ -6651,7 +6593,7 @@ for (RouterMcastFloodPorts(&rtr, flood_ports) if rtr.mcast_cfg.relay) { "drop;" } in AnnotatedFlow(.f = Flow{.logical_datapath = rtr.lr._uuid, - .stage = router_stage(IN, IP_ROUTING), + .stage = s_ROUTER_IN_IP_ROUTING(), .priority = 450, .__match = "ip4.mcast || ip6.mcast", .actions = actions, @@ -6672,14 +6614,14 @@ for (&Router(.lr = lr)) { /* This is a catch-all rule. It has the lowest priority (0) * does a match-all("1") and pass-through (next) */ Flow(.logical_datapath = lr._uuid, - .stage = router_stage(IN, POLICY), + .stage = s_ROUTER_IN_POLICY(), .priority = 0, .__match = "1", .actions = "${rEG_ECMP_GROUP_ID()} = 0; next;", .external_ids = map_empty()); Flow(.logical_datapath = lr._uuid, - .stage = router_stage(IN, POLICY_ECMP), + .stage = s_ROUTER_IN_POLICY_ECMP(), .priority = 150, .__match = "${rEG_ECMP_GROUP_ID()} == 0", .actions = "next;", @@ -6701,7 +6643,7 @@ function pkt_mark_policy(options: Map): string { } } Flow(.logical_datapath = r.lr._uuid, - .stage = router_stage(IN, POLICY), + .stage = s_ROUTER_IN_POLICY(), .priority = policy.priority, .__match = policy.__match, .actions = actions, @@ -6762,7 +6704,7 @@ EcmpReroutePolicy(r, policy, ecmp_group_id) :- (var policy, var ecmp_group_id) = pair, all_same_addr_family(policy.nexthops). Flow(.logical_datapath = r.lr._uuid, - .stage = router_stage(IN, POLICY_ECMP), + .stage = s_ROUTER_IN_POLICY_ECMP(), .priority = 100, .__match = __match, .actions = actions, @@ -6786,7 +6728,7 @@ Flow(.logical_datapath = r.lr._uuid, var __match = ("${rEG_ECMP_GROUP_ID()} == ${ecmp_group_id} && " "${rEG_ECMP_MEMBER_ID()} == ${member_id}"). Flow(.logical_datapath = r.lr._uuid, - .stage = router_stage(IN, POLICY), + .stage = s_ROUTER_IN_POLICY(), .priority = policy.priority, .__match = policy.__match, .actions = actions, @@ -6804,7 +6746,7 @@ Flow(.logical_datapath = r.lr._uuid, "${rEG_ECMP_MEMBER_ID()} = select(${member_ids});"). Flow(.logical_datapath = r.lr._uuid, - .stage = router_stage(IN, POLICY), + .stage = s_ROUTER_IN_POLICY(), .priority = policy.priority, .__match = policy.__match, .actions = "drop;", @@ -6814,7 +6756,7 @@ Flow(.logical_datapath = r.lr._uuid, policy in nb::Logical_Router_Policy(._uuid = policy_uuid), policy.action == "drop". Flow(.logical_datapath = r.lr._uuid, - .stage = router_stage(IN, POLICY), + .stage = s_ROUTER_IN_POLICY(), .priority = policy.priority, .__match = policy.__match, .actions = pkt_mark_policy(policy.options) ++ "${rEG_ECMP_GROUP_ID()} = 0; next;", @@ -6834,7 +6776,7 @@ Flow(.logical_datapath = r.lr._uuid, */ for (&Router(.lr = lr)) { Flow(.logical_datapath = lr._uuid, - .stage = router_stage(IN, ARP_RESOLVE), + .stage = s_ROUTER_IN_ARP_RESOLVE(), .priority = 500, .__match = "ip4.mcast || ip6.mcast", .actions = "next;", @@ -6869,7 +6811,7 @@ for (rp in &RouterPort(.peer = PeerRouter{peer_port, _}, "${rEG_NEXT_HOP()} == " ++ format_v4_networks(networks, false) in Flow(.logical_datapath = peer_router.lr._uuid, - .stage = router_stage(IN, ARP_RESOLVE), + .stage = s_ROUTER_IN_ARP_RESOLVE(), .priority = 100, .__match = __match, .actions = "eth.dst = ${networks.ea}; next;", @@ -6881,7 +6823,7 @@ for (rp in &RouterPort(.peer = PeerRouter{peer_port, _}, "xx${rEG_NEXT_HOP()} == " ++ format_v6_networks(networks) in Flow(.logical_datapath = peer_router.lr._uuid, - .stage = router_stage(IN, ARP_RESOLVE), + .stage = s_ROUTER_IN_ARP_RESOLVE(), .priority = 100, .__match = __match, .actions = "eth.dst = ${networks.ea}; next;", @@ -6897,7 +6839,7 @@ for (rp in &RouterPort(.peer = PeerRouter{peer_port, _}, * on this node, we will redirect the packet to gateway * chassis, by setting destination mac router port mac.*/ Flow(.logical_datapath = router.lr._uuid, - .stage = router_stage(IN, ARP_RESOLVE), + .stage = s_ROUTER_IN_ARP_RESOLVE(), .priority = 50, .__match = "outport == ${rp.json_name} && " "!is_chassis_resident(${router.redirect_port_name})", @@ -6915,7 +6857,7 @@ Flow(.logical_datapath = router.lr._uuid, * Priority 1. */ Flow(.logical_datapath = lr_uuid, - .stage = router_stage(IN, ARP_RESOLVE), + .stage = s_ROUTER_IN_ARP_RESOLVE(), .priority = 1, .__match = "ip4.dst == {" ++ match_ips.join(", ") ++ "}", .actions = "drop;", @@ -6928,7 +6870,7 @@ Flow(.logical_datapath = lr_uuid, snat_ips.contains_key(IPv4{addr.addr}), var match_ips = "${addr.addr}".group_by((lr_uuid, lrp_uuid)).to_vec(). Flow(.logical_datapath = lr_uuid, - .stage = router_stage(IN, ARP_RESOLVE), + .stage = s_ROUTER_IN_ARP_RESOLVE(), .priority = 1, .__match = "ip6.dst == {" ++ match_ips.join(", ") ++ "}", .actions = "drop;", @@ -6957,7 +6899,7 @@ for (SwitchPortIPv4Address( { Some{_} = find_lrp_member_ip(peer.networks, IPv4{addr.addr}) in Flow(.logical_datapath = peer_router.lr._uuid, - .stage = router_stage(IN, ARP_RESOLVE), + .stage = s_ROUTER_IN_ARP_RESOLVE(), .priority = 100, .__match = "outport == ${peer.json_name} && " "${rEG_NEXT_HOP()} == ${addr.addr}", @@ -6977,7 +6919,7 @@ for (SwitchPortIPv6Address( { Some{_} = find_lrp_member_ip(peer.networks, IPv6{addr.addr}) in Flow(.logical_datapath = peer_router.lr._uuid, - .stage = router_stage(IN, ARP_RESOLVE), + .stage = s_ROUTER_IN_ARP_RESOLVE(), .priority = 100, .__match = "outport == ${peer.json_name} && " "xx${rEG_NEXT_HOP()} == ${addr.addr}", @@ -7007,7 +6949,7 @@ function is_empty_set_or_string(s: Option): bool = { * resolved by router pipeline using the arp{} action. * The MAC_Binding entry for the virtual ip might be invalid. */ Flow(.logical_datapath = peer.router.lr._uuid, - .stage = router_stage(IN, ARP_RESOLVE), + .stage = s_ROUTER_IN_ARP_RESOLVE(), .priority = 100, .__match = "outport == ${peer.json_name} && " "${rEG_NEXT_HOP()} == ${virtual_ip}", @@ -7022,7 +6964,7 @@ Flow(.logical_datapath = peer.router.lr._uuid, sp2 in &SwitchPort(.sw = sp.sw, .peer = Some{peer}), Some{_} = find_lrp_member_ip(peer.networks, IPv4{virtual_ip}). Flow(.logical_datapath = peer.router.lr._uuid, - .stage = router_stage(IN, ARP_RESOLVE), + .stage = s_ROUTER_IN_ARP_RESOLVE(), .priority = 100, .__match = "outport == ${peer.json_name} && " "${rEG_NEXT_HOP()} == ${virtual_ip}", @@ -7059,7 +7001,7 @@ for (&SwitchPort(.lsp = lsp1, { if (not peer2.networks.ipv4_addrs.is_empty()) { Flow(.logical_datapath = peer_router.lr._uuid, - .stage = router_stage(IN, ARP_RESOLVE), + .stage = s_ROUTER_IN_ARP_RESOLVE(), .priority = 100, .__match = "outport == ${peer1.json_name} && " "${rEG_NEXT_HOP()} == ${format_v4_networks(peer2.networks, false)}", @@ -7069,7 +7011,7 @@ for (&SwitchPort(.lsp = lsp1, if (not peer2.networks.ipv6_addrs.is_empty()) { Flow(.logical_datapath = peer_router.lr._uuid, - .stage = router_stage(IN, ARP_RESOLVE), + .stage = s_ROUTER_IN_ARP_RESOLVE(), .priority = 100, .__match = "outport == ${peer1.json_name} && " "xx${rEG_NEXT_HOP()} == ${format_v6_networks(peer2.networks)}", @@ -7082,13 +7024,13 @@ for (&SwitchPort(.lsp = lsp1, for (&Router(.lr = lr)) { Flow(.logical_datapath = lr._uuid, - .stage = router_stage(IN, ARP_RESOLVE), + .stage = s_ROUTER_IN_ARP_RESOLVE(), .priority = 0, .__match = "ip4", .actions = "get_arp(outport, ${rEG_NEXT_HOP()}); next;", .external_ids = map_empty()); Flow(.logical_datapath = lr._uuid, - .stage = router_stage(IN, ARP_RESOLVE), + .stage = s_ROUTER_IN_ARP_RESOLVE(), .priority = 0, .__match = "ip6", .actions = "get_nd(outport, xx${rEG_NEXT_HOP()}); next;", @@ -7109,21 +7051,21 @@ for (&Router(.lr = lr)) * code 4 (Fragmentation needed). * */ Flow(.logical_datapath = lr._uuid, - .stage = router_stage(IN, CHK_PKT_LEN), + .stage = s_ROUTER_IN_CHK_PKT_LEN(), .priority = 0, .__match = "1", .actions = "next;", .external_ids = map_empty()) :- &Router(.lr = lr). Flow(.logical_datapath = lr._uuid, - .stage = router_stage(IN, LARGER_PKTS), + .stage = s_ROUTER_IN_LARGER_PKTS(), .priority = 0, .__match = "1", .actions = "next;", .external_ids = map_empty()) :- &Router(.lr = lr). Flow(.logical_datapath = lr._uuid, - .stage = router_stage(IN, CHK_PKT_LEN), + .stage = s_ROUTER_IN_CHK_PKT_LEN(), .priority = 50, .__match = "outport == ${l3dgw_port_json_name}", .actions = "${rEGBIT_PKT_LARGER()} = check_pkt_larger(${mtu}); " @@ -7137,7 +7079,7 @@ Flow(.logical_datapath = lr._uuid, gw_mtu > 0, var mtu = gw_mtu + vLAN_ETH_HEADER_LEN(). Flow(.logical_datapath = lr._uuid, - .stage = router_stage(IN, LARGER_PKTS), + .stage = s_ROUTER_IN_LARGER_PKTS(), .priority = 50, .__match = "inport == ${rp.json_name} && outport == ${l3dgw_port_json_name} && " "ip4 && ${rEGBIT_PKT_LARGER()}", @@ -7164,7 +7106,7 @@ Flow(.logical_datapath = lr._uuid, rp.lrp != l3dgw_port, Some{var first_ipv4} = rp.networks.ipv4_addrs.nth(0). Flow(.logical_datapath = lr._uuid, - .stage = router_stage(IN, LARGER_PKTS), + .stage = s_ROUTER_IN_LARGER_PKTS(), .priority = 50, .__match = "inport == ${rp.json_name} && outport == ${l3dgw_port_json_name} && " "ip6 && ${rEGBIT_PKT_LARGER()}", @@ -7208,7 +7150,7 @@ for (&Router(.lr = lr, * instance of the l3dgw_port. */ Some{var gwport} = l3dgw_port in Flow(.logical_datapath = lr._uuid, - .stage = router_stage(IN, GW_REDIRECT), + .stage = s_ROUTER_IN_GW_REDIRECT(), .priority = 50, .__match = "outport == ${json_string_escape(gwport.name)}", .actions = "outport = ${redirect_port_name}; next;", @@ -7216,7 +7158,7 @@ for (&Router(.lr = lr, /* Packets are allowed by default. */ Flow(.logical_datapath = lr._uuid, - .stage = router_stage(IN, GW_REDIRECT), + .stage = s_ROUTER_IN_GW_REDIRECT(), .priority = 0, .__match = "1", .actions = "next;", @@ -7229,7 +7171,7 @@ for (&Router(.lr = lr, * this table outputs the packet (priority 0). Otherwise, it composes * and sends an ARP/IPv6 NA request (priority 100). */ Flow(.logical_datapath = router.lr._uuid, - .stage = router_stage(IN, ARP_REQUEST), + .stage = s_ROUTER_IN_ARP_REQUEST(), .priority = 200, .__match = __match, .actions = actions, @@ -7252,7 +7194,7 @@ Flow(.logical_datapath = router.lr._uuid, for (&Router(.lr = lr)) { Flow(.logical_datapath = lr._uuid, - .stage = router_stage(IN, ARP_REQUEST), + .stage = s_ROUTER_IN_ARP_REQUEST(), .priority = 100, .__match = "eth.dst == 00:00:00:00:00:00 && ip4", .actions = "arp { " @@ -7265,7 +7207,7 @@ for (&Router(.lr = lr)) .external_ids = map_empty()); Flow(.logical_datapath = lr._uuid, - .stage = router_stage(IN, ARP_REQUEST), + .stage = s_ROUTER_IN_ARP_REQUEST(), .priority = 100, .__match = "eth.dst == 00:00:00:00:00:00 && ip6", .actions = "nd_ns { " @@ -7275,7 +7217,7 @@ for (&Router(.lr = lr)) .external_ids = map_empty()); Flow(.logical_datapath = lr._uuid, - .stage = router_stage(IN, ARP_REQUEST), + .stage = s_ROUTER_IN_ARP_REQUEST(), .priority = 0, .__match = "1", .actions = "output;", @@ -7299,7 +7241,7 @@ for (&RouterPort(.lrp = lrp, */ if (mcast_cfg.relay) { Flow(.logical_datapath = lr._uuid, - .stage = router_stage(OUT, DELIVERY), + .stage = s_ROUTER_OUT_DELIVERY(), .priority = 110, .__match = "(ip4.mcast || ip6.mcast) && " "outport == ${json_name}", @@ -7312,7 +7254,7 @@ for (&RouterPort(.lrp = lrp, * pipeline stage before egress processing. */ Flow(.logical_datapath = lr._uuid, - .stage = router_stage(OUT, DELIVERY), + .stage = s_ROUTER_OUT_DELIVERY(), .priority = 100, .__match = "outport == ${json_name}", .actions = "output;", @@ -7947,13 +7889,13 @@ function lrouter_bfd_flows(lr_uuid: uuid, lrp_uuid: uuid, ipX: string, networks: : (Flow, Flow) { (Flow{.logical_datapath = lr_uuid, - .stage = router_stage(IN, IP_INPUT), + .stage = s_ROUTER_IN_IP_INPUT(), .priority = 110, .__match = "${ipX}.src == ${networks} && udp.dst == 3784", .actions = "next; ", .external_ids = stage_hint(lrp_uuid)}, Flow{.logical_datapath = lr_uuid, - .stage = router_stage(IN, IP_INPUT), + .stage = s_ROUTER_IN_IP_INPUT(), .priority = 110, .__match = "${ipX}.dst == ${networks} && udp.dst == 3784", .actions = "handle_bfd_msg(); ", From patchwork Thu Mar 4 04:10:05 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ben Pfaff X-Patchwork-Id: 1447080 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=) 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 4Drcq00xqKz9sRf for ; Thu, 4 Mar 2021 15:10:36 +1100 (AEDT) Received: from localhost (localhost [127.0.0.1]) by smtp2.osuosl.org (Postfix) with ESMTP id C9BBD4324A; Thu, 4 Mar 2021 04:10:33 +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 zalMtuSCuDvG; Thu, 4 Mar 2021 04:10:31 +0000 (UTC) Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56]) by smtp2.osuosl.org (Postfix) with ESMTP id 0E94643253; Thu, 4 Mar 2021 04:10:29 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id CC48BC000A; Thu, 4 Mar 2021 04:10:29 +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 CF573C000A for ; Thu, 4 Mar 2021 04:10:27 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by smtp4.osuosl.org (Postfix) with ESMTP id AC7C44D7A3 for ; Thu, 4 Mar 2021 04:10:27 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org 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 WZAXOv7DOCIO for ; Thu, 4 Mar 2021 04:10:26 +0000 (UTC) X-Greylist: domain auto-whitelisted by SQLgrey-1.8.0 Received: from relay9-d.mail.gandi.net (relay9-d.mail.gandi.net [217.70.183.199]) by smtp4.osuosl.org (Postfix) with ESMTPS id C3E2A4CA27 for ; Thu, 4 Mar 2021 04:10:25 +0000 (UTC) X-Originating-IP: 75.54.222.30 Received: from sigfpe.attlocal.net (75-54-222-30.lightspeed.rdcyca.sbcglobal.net [75.54.222.30]) (Authenticated sender: blp@ovn.org) by relay9-d.mail.gandi.net (Postfix) with ESMTPSA id 5CE33FF804; Thu, 4 Mar 2021 04:10:23 +0000 (UTC) From: Ben Pfaff To: dev@openvswitch.org Date: Wed, 3 Mar 2021 20:10:05 -0800 Message-Id: <20210304041012.4128938-5-blp@ovn.org> X-Mailer: git-send-email 2.29.2 In-Reply-To: <20210304041012.4128938-1-blp@ovn.org> References: <20210304041012.4128938-1-blp@ovn.org> MIME-Version: 1.0 Cc: Ben Pfaff Subject: [ovs-dev] [PATCH ovn 04/11] ovn-northd-ddlog: Use object form of is_some(), drop is_none(). 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" DDlog supports a couple different forms of functions. You can write is_some(expr) or expr.is_some(), for example. The latter is usually easier to understand, especially in bigger expressions. It was introduced later so it's not consistently used in ovn-northd-ddlog. This commit switches to the object-like form throughout the code. Writing is_none(expr) or expr.is_none() is equivalent to writing expr == None. I think that the latter is easier to understand, so this commit also makes that change throughout. This code refactoring shouldn't change ovn-northd-ddlog behavior. Signed-off-by: Ben Pfaff --- northd/ipam.dl | 2 +- northd/lrouter.dl | 24 ++++++++++++------------ northd/lswitch.dl | 15 +++++++-------- northd/ovn_northd.dl | 32 ++++++++++++++++---------------- 4 files changed, 36 insertions(+), 37 deletions(-) diff --git a/northd/ipam.dl b/northd/ipam.dl index 879e59c3d6da..1349a933eba0 100644 --- a/northd/ipam.dl +++ b/northd/ipam.dl @@ -440,7 +440,7 @@ SwitchPortNewMACDynAddress(lsp._uuid, mac_addr) :- var mac_addr = match (static_dynamic_mac) { None -> None, Some{addr} -> { - if (is_some(sw.subnet) or is_some(sw.ipv6_prefix) or + if (sw.subnet.is_some() or sw.ipv6_prefix.is_some() or map_get(sw.ls.other_config, "mac_only") == Some{"true"}) { Some{addr} } else { diff --git a/northd/lrouter.dl b/northd/lrouter.dl index 8b8005b0ca8f..2d700e718340 100644 --- a/northd/lrouter.dl +++ b/northd/lrouter.dl @@ -91,7 +91,7 @@ FirstHopLogicalRouter(lrouter, lswitch) :- lsp in nb::Logical_Switch_Port(._uuid = lsp_uuid), lsp.__type == "router", lsp.options.get("router-port") == Some{lrp.name}, - is_none(lrp.peer). + lrp.peer == None. /* * Reachable routers. @@ -118,7 +118,7 @@ ReachableLogicalRouter(a, a) :- ReachableLogicalRouter(a, _). // ha_chassis_group and gateway_chassis may not both be present. Warning[message] :- lrp in nb::Logical_Router_Port(), - is_some(lrp.ha_chassis_group), + lrp.ha_chassis_group.is_some(), not lrp.gateway_chassis.is_empty(), var message = "Both ha_chassis_group and gateway_chassis configured on " "port ${lrp.name}; ignoring the latter". @@ -126,7 +126,7 @@ Warning[message] :- // A distributed gateway port cannot also be an L3 gateway router. Warning[message] :- lrp in nb::Logical_Router_Port(), - is_some(lrp.ha_chassis_group) or not lrp.gateway_chassis.is_empty(), + lrp.ha_chassis_group.is_some() or not lrp.gateway_chassis.is_empty(), lrp.options.contains_key("chassis"), var message = "Bad configuration: distributed gateway port configured on " "port ${lrp.name} on L3 gateway router". @@ -143,7 +143,7 @@ DistributedGatewayPortCandidate(lr_uuid, lrp_uuid) :- LogicalRouterPort(lrp_uuid, lr._uuid), lrp in nb::Logical_Router_Port(._uuid = lrp_uuid), not lrp.options.contains_key("chassis"), - var has_hcg = is_some(lrp.ha_chassis_group), + var has_hcg = lrp.ha_chassis_group.is_some(), var has_gc = not lrp.gateway_chassis.is_empty(), has_hcg or has_gc. Warning[message] :- @@ -185,7 +185,7 @@ relation HAChassis(hacg_uuid: uuid, HAChassis(ha_chassis_group_uuid(lrp._uuid), gw_chassis_uuid, chassis_name, priority, external_ids) :- DistributedGatewayPort(.lrp = lrp), - is_none(lrp.ha_chassis_group), + lrp.ha_chassis_group == None, var gw_chassis_uuid = FlatMap(lrp.gateway_chassis), nb::Gateway_Chassis(._uuid = gw_chassis_uuid, .chassis_name = chassis_name, @@ -219,7 +219,7 @@ relation HAChassisGroup(uuid: uuid, external_ids: Map) HAChassisGroup(ha_chassis_group_uuid(lrp._uuid), lrp.name, map_empty()) :- DistributedGatewayPort(.lrp = lrp), - is_none(lrp.ha_chassis_group), + lrp.ha_chassis_group == None, not lrp.gateway_chassis.is_empty(). HAChassisGroup(ha_chassis_group_uuid(hac_group_uuid), name, external_ids) :- @@ -236,7 +236,7 @@ relation LogicalRouterHAChassisGroup(lr_uuid: uuid, hacg_uuid: uuid) LogicalRouterHAChassisGroup(lr_uuid, ha_chassis_group_uuid(lrp._uuid)) :- DistributedGatewayPort(lrp, lr_uuid), - is_none(lrp.ha_chassis_group), + lrp.ha_chassis_group == None, lrp.gateway_chassis.size() > 0. LogicalRouterHAChassisGroup(lr_uuid, ha_chassis_group_uuid(hac_group_uuid)) :- @@ -300,16 +300,16 @@ Warning["Bad MAC address ${s} in nat configuration for router ${lr_name}."] :- relation LogicalRouterNAT(lr: uuid, nat: NAT) LogicalRouterNAT(lr, NAT{nat, external_ip, external_mac, None}) :- LogicalRouterNAT0(lr, nat, external_ip, external_mac), - nat.allowed_ext_ips.is_none(), - nat.exempted_ext_ips.is_none(). + nat.allowed_ext_ips == None, + nat.exempted_ext_ips == None. LogicalRouterNAT(lr, NAT{nat, external_ip, external_mac, Some{AllowedExtIps{__as}}}) :- LogicalRouterNAT0(lr, nat, external_ip, external_mac), - nat.exempted_ext_ips.is_none(), + nat.exempted_ext_ips == None, Some{var __as_uuid} = nat.allowed_ext_ips, __as in &AddressSetRef[nb::Address_Set{._uuid = __as_uuid}]. LogicalRouterNAT(lr, NAT{nat, external_ip, external_mac, Some{ExemptedExtIps{__as}}}) :- LogicalRouterNAT0(lr, nat, external_ip, external_mac), - nat.allowed_ext_ips.is_none(), + nat.allowed_ext_ips == None, Some{var __as_uuid} = nat.exempted_ext_ips, __as in &AddressSetRef[nb::Address_Set{._uuid = __as_uuid}]. Warning["NAT rule: ${nat._uuid} not applied, since" @@ -444,7 +444,7 @@ relation &Router( Some{rport} -> json_string_escape(chassis_redirect_name(rport.name)), _ -> "" }, - .is_gateway = is_some(lr.options.get("chassis")), + .is_gateway = lr.options.contains_key("chassis"), .nats = nats, .snat_ips = snat_ips, .lbs = lbs, diff --git a/northd/lswitch.dl b/northd/lswitch.dl index 4bf8a5b907a9..3ade241cf4e5 100644 --- a/northd/lswitch.dl +++ b/northd/lswitch.dl @@ -623,7 +623,7 @@ relation &SwitchPort( var dynamic_address_request = None; for (addr in lsp.addresses) { dynamic_address_request = parse_dynamic_address_request(addr); - if (is_some(dynamic_address_request)) { + if (dynamic_address_request.is_some()) { break } }; @@ -633,19 +633,18 @@ relation &SwitchPort( None -> (None, None, None, false) } }, - var needs_dynamic_ipv4address = has_dyn_lsp_addr and is_none(peer) and is_some(subnet) and - is_none(static_dynamic_ipv4), - var needs_dynamic_macaddress = has_dyn_lsp_addr and is_none(peer) and is_none(static_dynamic_mac) and - (is_some(subnet) or is_some(ipv6_prefix) or + var needs_dynamic_ipv4address = has_dyn_lsp_addr and peer == None and subnet.is_some() and + static_dynamic_ipv4 == None, + var needs_dynamic_macaddress = has_dyn_lsp_addr and peer == None and static_dynamic_mac == None and + (subnet.is_some() or ipv6_prefix.is_some() or other_config.get("mac_only") == Some{"true"}), - var needs_dynamic_ipv6address = has_dyn_lsp_addr and is_none(peer) and is_some(ipv6_prefix) and is_none(static_dynamic_ipv6), + var needs_dynamic_ipv6address = has_dyn_lsp_addr and peer == None and ipv6_prefix.is_some() and static_dynamic_ipv6 == None, var parent_name = match (lsp.parent_name) { None -> None, Some{pname} -> if (pname == "") { None } else { Some{pname} } }, /* Port needs dynamic tag if it has a parent and its `tag_request` is 0. */ - var needs_dynamic_tag = is_some(parent_name) and - lsp.tag_request == Some{0}, + var needs_dynamic_tag = parent_name.is_some() and lsp.tag_request == Some{0}, SwitchPortHAChassisGroup(.lsp_uuid = lsp._uuid, .hac_group_uuid = hac_group_uuid). diff --git a/northd/ovn_northd.dl b/northd/ovn_northd.dl index 7d636df8b69a..9285e38f5148 100644 --- a/northd/ovn_northd.dl +++ b/northd/ovn_northd.dl @@ -197,7 +197,7 @@ OutProxy_Port_Binding(._uuid = lsp._uuid, Some{nat_addresses} -> { /* Only accept manual specification of ethernet address * followed by IPv4 addresses on type "l3gateway" ports. */ - if (is_some(opt_chassis)) { + if (opt_chassis.is_some()) { match (extract_lsp_addresses(nat_addresses)) { None -> { warn("Error extracting nat-addresses."); @@ -229,9 +229,9 @@ OutProxy_Port_Binding(._uuid = lsp._uuid, Some{rport} -> match ( (map_get_bool_def(rport.lrp.options, "reside-on-redirect-chassis", false) - and is_some(l3dgw_port)) or + and l3dgw_port.is_some()) or Some{rport.lrp} == l3dgw_port or - (is_some(rport.router.lr.options.get("chassis")) and + (rport.router.lr.options.contains_key("chassis") and not sw.localnet_ports.is_empty())) { false -> set_empty(), true -> set_singleton(get_garp_nat_addresses(deref(rport))) @@ -321,7 +321,7 @@ function get_nat_addresses(rport: RouterPort): Set = { var addresses = set_empty(); var router = deref(rport.router); - var has_redirect = is_some(router.l3dgw_port); + var has_redirect = router.l3dgw_port.is_some(); match (eth_addr_from_string(rport.lrp.mac)) { None -> addresses, Some{mac} -> { @@ -333,7 +333,7 @@ function get_nat_addresses(rport: RouterPort): Set = /* Determine whether this NAT rule satisfies the conditions for * distributed NAT processing. */ if (has_redirect and nat.nat.__type == "dnat_and_snat" and - is_some(nat.nat.logical_port) and is_some(nat.external_mac)) { + nat.nat.logical_port.is_some() and nat.external_mac.is_some()) { /* Distributed NAT rule. */ var logical_port = option_unwrap_or_default(nat.nat.logical_port); var external_mac = option_unwrap_or_default(nat.external_mac); @@ -3560,7 +3560,7 @@ for (lsp in &SwitchPort * and if it doesn't belong to an HA chassis group ignore it. */ and (lsp.lsp.__type != "external" or (not lsp.sw.localnet_ports.is_empty() - and is_some(lsp.lsp.ha_chassis_group)))) + and lsp.lsp.ha_chassis_group.is_some()))) { for (lps in LogicalSwitchPort(.lport = lsp.lsp._uuid, .lswitch = lsuuid)) { var json_key = json_string_escape(lsp.lsp.name) in @@ -4733,7 +4733,7 @@ relation AddChassisResidentCheck_(lrp: uuid, add_check: bool) AddChassisResidentCheck_(lrp._uuid, res) :- &SwitchPort(.peer = Some{&RouterPort{.lrp = lrp, .router = &router, .is_redirect = is_redirect}}, .sw = sw), - is_some(router.l3dgw_port), + router.l3dgw_port.is_some(), not sw.localnet_ports.is_empty(), var res = if (is_redirect) { /* Traffic with eth.src = l3dgw_port->lrp_networks.ea @@ -5396,7 +5396,7 @@ function lrouter_nat_add_ext_ip_match( }, false -> { /* S_ROUTER_OUT_SNAT uses priority (mask + 1 + 128 + 1) */ - var is_gw_router = router.l3dgw_port.is_none(); + var is_gw_router = router.l3dgw_port == None; var mask_1bits = ip46_count_cidr_bits(mask).unwrap_or(8'd0) as integer; mask_1bits + 2 + { if (not is_gw_router) 128 else 0 } } @@ -5486,7 +5486,7 @@ for (r in &Router(.lr = lr, .l3dgw_port = l3dgw_port, .redirect_port_name = redirect_port_name, .is_gateway = is_gateway) - if is_some(l3dgw_port) or is_gateway) + if l3dgw_port.is_some() or is_gateway) { for (LogicalRouterNAT(.lr = lr._uuid, .nat = nat)) { var ipX = ip46_ipX(nat.external_ip) in @@ -5504,7 +5504,7 @@ for (r in &Router(.lr = lr, } in /* For distributed router NAT, determine whether this NAT rule * satisfies the conditions for distributed NAT processing. */ - var mac = match ((is_some(l3dgw_port) and nat.nat.__type == "dnat_and_snat", + var mac = match ((l3dgw_port.is_some() and nat.nat.__type == "dnat_and_snat", nat.nat.logical_port, nat.external_mac)) { (true, Some{_}, Some{mac}) -> Some{mac}, _ -> None @@ -5914,7 +5914,7 @@ for (RouterLBVIP( .lb = lb, .vip = vip, .backends = backends) - if is_some(l3dgw_port) or is_gateway) + if l3dgw_port.is_some() or is_gateway) { if (backends == "" and not map_get_bool_def(lb.options, "reject", false)) { for (LoadBalancerEmptyEvents(lb)) { @@ -6069,7 +6069,7 @@ Flow(.logical_datapath = r.lr._uuid, .actions = actions, .external_ids = stage_hint(lb._uuid)) :- r in &Router(), - is_some(r.l3dgw_port) or r.is_gateway, + r.l3dgw_port.is_some() or r.is_gateway, LBVIPWithStatus[lbvip@&LBVIPWithStatus{.lb = lb}], r.lr.load_balancer.contains(lb._uuid), var __match @@ -6960,7 +6960,7 @@ Flow(.logical_datapath = peer.router.lr._uuid, Some{var virtual_parents} = lsp.options.get("virtual-parents"), Some{var virtual_ip} = ip_parse(virtual_ip_s), pb in sb::Port_Binding(.logical_port = sp.lsp.name), - is_empty_set_or_string(pb.virtual_parent) or is_none(pb.chassis), + is_empty_set_or_string(pb.virtual_parent) or pb.chassis == None, sp2 in &SwitchPort(.sw = sp.sw, .peer = Some{peer}), Some{_} = find_lrp_member_ip(peer.networks, IPv4{virtual_ip}). Flow(.logical_datapath = peer.router.lr._uuid, @@ -6975,7 +6975,7 @@ Flow(.logical_datapath = peer.router.lr._uuid, Some{var virtual_parents} = lsp.options.get("virtual-parents"), Some{var virtual_ip} = ip_parse(virtual_ip_s), pb in sb::Port_Binding(.logical_port = sp.lsp.name), - not (is_empty_set_or_string(pb.virtual_parent) or is_none(pb.chassis)), + not (is_empty_set_or_string(pb.virtual_parent) or pb.chassis == None), Some{var virtual_parent} = pb.virtual_parent, vp in &SwitchPort(.lsp = nb::Logical_Switch_Port{.name = virtual_parent}), var address = FlatMap(vp.static_addresses), @@ -7647,7 +7647,7 @@ relation SwitchPortAllocatedTags(lsp_uuid: uuid, tag: Option) SwitchPortAllocatedTags(lsp_uuid, tag) :- &SwitchPort(.lsp = lsp, .needs_dynamic_tag = true, .parent_name = Some{parent_name}), - is_none(lsp.tag), + lsp.tag == None, var lsps_need_tag = lsp._uuid.group_by(parent_name).to_vec(), SwitchPortReservedTags(parent_name, reserved), var dyn_tags = allocate_opt(reserved, @@ -7680,7 +7680,7 @@ SwitchPortNewDynamicTag(lsp._uuid, Some{tag}) :- /* Case 3 */ SwitchPortNewDynamicTag(lsp._uuid, tag) :- &SwitchPort(.lsp = lsp, .needs_dynamic_tag = true), - is_none(lsp.tag), + lsp.tag == None, SwitchPortAllocatedTags(lsp._uuid, tag). /* IP_Multicast table (only applicable for Switches). */ From patchwork Thu Mar 4 04:10:06 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ben Pfaff X-Patchwork-Id: 1447081 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::137; helo=smtp4.osuosl.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Received: from smtp4.osuosl.org (smtp4.osuosl.org [IPv6:2605:bc80:3010::137]) (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 4Drcq56z59z9sRf for ; Thu, 4 Mar 2021 15:10:41 +1100 (AEDT) Received: from localhost (localhost [127.0.0.1]) by smtp4.osuosl.org (Postfix) with ESMTP id AAE8D4EBDD; Thu, 4 Mar 2021 04:10:37 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org 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 cbFRZXww9Y_7; Thu, 4 Mar 2021 04:10:36 +0000 (UTC) Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [IPv6:2605:bc80:3010:104::8cd3:938]) by smtp4.osuosl.org (Postfix) with ESMTP id E40A14EBCC; Thu, 4 Mar 2021 04:10:34 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id B43A8C000A; Thu, 4 Mar 2021 04:10:34 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@lists.linuxfoundation.org Received: from smtp2.osuosl.org (smtp2.osuosl.org [140.211.166.133]) by lists.linuxfoundation.org (Postfix) with ESMTP id 13B43C0001 for ; Thu, 4 Mar 2021 04:10:33 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by smtp2.osuosl.org (Postfix) with ESMTP id A48894325B for ; Thu, 4 Mar 2021 04:10:30 +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 dfJyAtLGF_mk for ; Thu, 4 Mar 2021 04:10:27 +0000 (UTC) X-Greylist: domain auto-whitelisted by SQLgrey-1.8.0 Received: from relay9-d.mail.gandi.net (relay9-d.mail.gandi.net [217.70.183.199]) by smtp2.osuosl.org (Postfix) with ESMTPS id 4AB73431EE for ; Thu, 4 Mar 2021 04:10:26 +0000 (UTC) X-Originating-IP: 75.54.222.30 Received: from sigfpe.attlocal.net (75-54-222-30.lightspeed.rdcyca.sbcglobal.net [75.54.222.30]) (Authenticated sender: blp@ovn.org) by relay9-d.mail.gandi.net (Postfix) with ESMTPSA id BF2DCFF802; Thu, 4 Mar 2021 04:10:24 +0000 (UTC) From: Ben Pfaff To: dev@openvswitch.org Date: Wed, 3 Mar 2021 20:10:06 -0800 Message-Id: <20210304041012.4128938-6-blp@ovn.org> X-Mailer: git-send-email 2.29.2 In-Reply-To: <20210304041012.4128938-1-blp@ovn.org> References: <20210304041012.4128938-1-blp@ovn.org> MIME-Version: 1.0 Cc: Ben Pfaff Subject: [ovs-dev] [PATCH ovn 05/11] ovn-northd-ddlog: Make map_get_*() more object-like. 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" These functions were introduced before the object-like invocation form was added to DDlog. It's usually easier to read the object-like form, so this changes the functions to this form and updates all the callers. It seemed to me that map_get_int_def_limit() was more general if we just introduced a general-purpose clamp() function, so I did that. This code refactoring shouldn't change ovn-northd-ddlog behavior. Signed-off-by: Ben Pfaff --- northd/helpers.dl | 22 ++++++------ northd/lrouter.dl | 4 +-- northd/lswitch.dl | 4 +-- northd/multicast.dl | 50 +++++++++------------------ northd/ovn_northd.dl | 82 +++++++++++++++++--------------------------- 5 files changed, 63 insertions(+), 99 deletions(-) diff --git a/northd/helpers.dl b/northd/helpers.dl index 985a13264398..32a5526d59d5 100644 --- a/northd/helpers.dl +++ b/northd/helpers.dl @@ -63,8 +63,7 @@ SwitchRouterPeer(lsp, lsp_name, lrp) :- Some{var router_port} = options.get("router-port"), nb::Logical_Router_Port(.name = router_port, ._uuid = lrp). -function map_get_bool_def(m: Map, - k: string, def: bool): bool = { +function get_bool_def(m: Map, k: string, def: bool): bool = { m.get(k) .and_then(|x| match (str_to_lower(x)) { "false" -> Some{false}, @@ -74,18 +73,19 @@ function map_get_bool_def(m: Map, .unwrap_or(def) } -function map_get_int_def(m: Map, k: string, - def: integer): integer = { +function get_int_def(m: Map, k: string, def: integer): integer = { m.get(k).and_then(parse_dec_u64).unwrap_or(def) } -function map_get_int_def_limit(m: Map, k: string, def: integer, - min: integer, max: integer): integer = { - var v = map_get_int_def(m, k, def); - var v1 = { - if (v < min) min else v - }; - if (v1 > max) max else v1 +function clamp(x: 'A, range: ('A, 'A)): 'A { + (var min, var max) = range; + if (x < min) { + min + } else if (x > max) { + max + } else { + x + } } function ha_chassis_group_uuid(uuid: uuid): uuid { hash128("hacg" ++ uuid) } diff --git a/northd/lrouter.dl b/northd/lrouter.dl index 2d700e718340..7bcacfe2aeb6 100644 --- a/northd/lrouter.dl +++ b/northd/lrouter.dl @@ -457,7 +457,7 @@ relation &Router( LogicalRouterLBs(lr._uuid, lbs), LogicalRouterSnatIPs(lr._uuid, snat_ips), mcast_cfg in &McastRouterCfg(.datapath = lr._uuid), - var learn_from_arp_request = map_get_bool_def(lr.options, "always_learn_from_arp_request", true). + var learn_from_arp_request = lr.options.get_bool_def("always_learn_from_arp_request", true). /* RouterLB: many-to-many relation between logical routers and nb::LB */ relation RouterLB(router: Ref, lb: Ref) @@ -646,7 +646,7 @@ relation &StaticRoute(lrsr: nb::Logical_Router_Static_Route, (IPv6{_}, IPv6{_}) -> true, _ -> false }, - var esr = map_get_bool_def(lrsr.options, "ecmp_symmetric_reply", false). + var esr = lrsr.options.get_bool_def("ecmp_symmetric_reply", false). /* Returns the IP address of the router port 'op' that * overlaps with 'ip'. If one is not found, returns None. */ diff --git a/northd/lswitch.dl b/northd/lswitch.dl index 3ade241cf4e5..5fcb3871c341 100644 --- a/northd/lswitch.dl +++ b/northd/lswitch.dl @@ -258,7 +258,7 @@ function ipv6_parse_prefix(s: string): Option { None -> None, Some{prefix} -> ipv6_parse_prefix(prefix) }, - var is_vlan_transparent = map_get_bool_def(ls.other_config, "vlan-passthru", false). + var is_vlan_transparent = ls.other_config.get_bool_def("vlan-passthru", false). /* SwitchLB: many-to-many relation between logical switches and nb::LB */ relation SwitchLB(sw_uuid: uuid, lb: Ref) @@ -494,7 +494,7 @@ SwitchPortUp0(lsp) :- nb::Logical_Switch_Port(._uuid = lsp, .name = lsp_name, .__type = __type), sb::Port_Binding(.logical_port = lsp_name, .up = up, .chassis = Some{chassis_uuid}), sb::Chassis(._uuid = chassis_uuid, .other_config = other_config), - if (map_get_bool_def(other_config, oVN_FEATURE_PORT_UP_NOTIF(), false)) { + if (other_config.get_bool_def(oVN_FEATURE_PORT_UP_NOTIF(), false)) { up == Some{true} } else { true diff --git a/northd/multicast.dl b/northd/multicast.dl index c3ab31e94d3e..f3989e7899d2 100644 --- a/northd/multicast.dl +++ b/northd/multicast.dl @@ -23,12 +23,10 @@ import lrouter function mCAST_DEFAULT_MAX_ENTRIES(): integer = 2048 function mCAST_DEFAULT_IDLE_TIMEOUT_S(): integer = 300 -function mCAST_DEFAULT_MIN_IDLE_TIMEOUT_S(): integer = 15 -function mCAST_DEFAULT_MAX_IDLE_TIMEOUT_S(): integer = 3600 +function mCAST_IDLE_TIMEOUT_S_RANGE(): (integer, integer) = (15, 3600) -function mCAST_DEFAULT_MIN_QUERY_INTERVAL_S(): integer = 1 -function mCAST_DEFAULT_MAX_QUERY_INTERVAL_S(): integer = - mCAST_DEFAULT_MAX_IDLE_TIMEOUT_S() +function mCAST_DEFAULT_QUERY_INTERVAL_S(): integer = 1 +function mCAST_QUERY_INTERVAL_S_RANGE(): (integer, integer) = (1, 3600) function mCAST_DEFAULT_QUERY_MAX_RESPONSE_S(): integer = 1 @@ -53,37 +51,24 @@ relation &McastSwitchCfg( &McastSwitchCfg( .datapath = ls_uuid, - .enabled = map_get_bool_def(other_config, "mcast_snoop", - false), - .querier = map_get_bool_def(other_config, "mcast_querier", - true), - .flood_unreg = map_get_bool_def(other_config, - "mcast_flood_unregistered", - false), + .enabled = other_config.get_bool_def("mcast_snoop", false), + .querier = other_config.get_bool_def("mcast_querier", true), + .flood_unreg = other_config.get_bool_def("mcast_flood_unregistered", false), .eth_src = other_config.get("mcast_eth_src").unwrap_or(""), .ip4_src = other_config.get("mcast_ip4_src").unwrap_or(""), .ip6_src = other_config.get("mcast_ip6_src").unwrap_or(""), - .table_size = map_get_int_def(other_config, - "mcast_table_size", - mCAST_DEFAULT_MAX_ENTRIES()), + .table_size = other_config.get_int_def("mcast_table_size", mCAST_DEFAULT_MAX_ENTRIES()), .idle_timeout = idle_timeout, .query_interval = query_interval, .query_max_resp = query_max_resp) :- nb::Logical_Switch(._uuid = ls_uuid, .other_config = other_config), - var idle_timeout = - map_get_int_def_limit(other_config, "mcast_idle_timeout", - mCAST_DEFAULT_IDLE_TIMEOUT_S(), - mCAST_DEFAULT_MIN_IDLE_TIMEOUT_S(), - mCAST_DEFAULT_MAX_IDLE_TIMEOUT_S()), - var query_interval = - map_get_int_def_limit(other_config, "mcast_query_interval", - idle_timeout / 2, - mCAST_DEFAULT_MIN_QUERY_INTERVAL_S(), - mCAST_DEFAULT_MAX_QUERY_INTERVAL_S()), - var query_max_resp = - map_get_int_def(other_config, "mcast_query_max_response", - mCAST_DEFAULT_QUERY_MAX_RESPONSE_S()). + var idle_timeout = other_config.get_int_def("mcast_idle_timeout", mCAST_DEFAULT_IDLE_TIMEOUT_S()) + .clamp(mCAST_IDLE_TIMEOUT_S_RANGE()), + var query_interval = other_config.get_int_def("mcast_query_interval", idle_timeout / 2) + .clamp(mCAST_QUERY_INTERVAL_S_RANGE()), + var query_max_resp = other_config.get_int_def("mcast_query_max_response", + mCAST_DEFAULT_QUERY_MAX_RESPONSE_S()). /* IP Multicast per router configuration. */ relation &McastRouterCfg( @@ -93,7 +78,7 @@ relation &McastRouterCfg( &McastRouterCfg(lr_uuid, mcast_relay) :- nb::Logical_Router(._uuid = lr_uuid, .options = options), - var mcast_relay = map_get_bool_def(options, "mcast_relay", false). + var mcast_relay = options.get_bool_def("mcast_relay", false). /* IP Multicast port configuration. */ relation &McastPortCfg( @@ -105,13 +90,12 @@ relation &McastPortCfg( &McastPortCfg(lsp_uuid, false, flood, flood_reports) :- nb::Logical_Switch_Port(._uuid = lsp_uuid, .options = options), - var flood = map_get_bool_def(options, "mcast_flood", false), - var flood_reports = map_get_bool_def(options, "mcast_flood_reports", - false). + var flood = options.get_bool_def("mcast_flood", false), + var flood_reports = options.get_bool_def("mcast_flood_reports", false). &McastPortCfg(lrp_uuid, true, flood, flood) :- nb::Logical_Router_Port(._uuid = lrp_uuid, .options = options), - var flood = map_get_bool_def(options, "mcast_flood", false). + var flood = options.get_bool_def("mcast_flood", false). /* Mapping between Switch and the set of router port uuids on which to flood * IP multicast for relay. diff --git a/northd/ovn_northd.dl b/northd/ovn_northd.dl index 9285e38f5148..4b4775a9d3bf 100644 --- a/northd/ovn_northd.dl +++ b/northd/ovn_northd.dl @@ -90,7 +90,7 @@ OutProxy_Datapath_Binding(uuid, set_empty(), external_ids) :- None -> (), Some{zone} -> eids.insert("snat-ct-zone", "${zone}") }; - var learn_from_arp_request = map_get_bool_def(options, "always_learn_from_arp_request", true); + var learn_from_arp_request = options.get_bool_def("always_learn_from_arp_request", true); if (not learn_from_arp_request) { eids.insert("always_learn_from_arp_request", "false") }; @@ -227,8 +227,7 @@ OutProxy_Port_Binding(._uuid = lsp._uuid, * */ var garp_nat_addresses = match (peer) { Some{rport} -> match ( - (map_get_bool_def(rport.lrp.options, "reside-on-redirect-chassis", - false) + (rport.lrp.options.get_bool_def("reside-on-redirect-chassis", false) and l3dgw_port.is_some()) or Some{rport.lrp} == l3dgw_port or (rport.router.lr.options.contains_key("chassis") and @@ -267,8 +266,8 @@ OutProxy_Port_Binding(._uuid = lrp._uuid, var options3 = match ((peer, rp.networks.ipv6_addrs.is_empty())) { (PeerSwitch{_, _}, false) -> { var enabled = lrp.is_enabled(); - var pd = map_get_bool_def(lrp.options, "prefix_delegation", false); - var p = map_get_bool_def(lrp.options, "prefix", false); + var pd = lrp.options.get_bool_def("prefix_delegation", false); + var p = lrp.options.get_bool_def("prefix", false); ["ipv6_prefix_delegation" -> "${pd and enabled}", "ipv6_prefix" -> "${p and enabled}"] }, @@ -588,7 +587,7 @@ sb::Out_SB_Global(._uuid = sb_global._uuid, relation ChassisPrivate( cp: sb::Chassis_Private, is_remote: bool) -ChassisPrivate(cp, map_get_bool_def(c.other_config, "is-remote", false)) :- +ChassisPrivate(cp, c.other_config.get_bool_def("is-remote", false)) :- cp in sb::Chassis_Private(.chassis = Some{uuid}), c in sb::Chassis(._uuid = uuid). ChassisPrivate(cp, false), @@ -680,7 +679,7 @@ Northd_Probe_Interval[interval] :- relation CheckLspIsUp[bool] CheckLspIsUp[check_lsp_is_up] :- nb in nb::NB_Global(), - var check_lsp_is_up = not map_get_bool_def(nb.options, "ignore_lsp_down", false). + var check_lsp_is_up = not nb.options.get_bool_def("ignore_lsp_down", false). CheckLspIsUp[true] :- Unit(), not nb in nb::NB_Global(). @@ -1340,7 +1339,7 @@ nb::Out_Logical_Switch_Port(._uuid = lsp._uuid, relation LRPIPv6Prefix0(lrp_uuid: uuid, ipv6_prefix: string) LRPIPv6Prefix0(lrp._uuid, ipv6_prefix) :- lrp in nb::Logical_Router_Port(), - map_get_bool_def(lrp.options, "prefix", false), + lrp.options.get_bool_def("prefix", false), sb::Port_Binding(.logical_port = lrp.name, .options = options), Some{var ipv6_ra_pd_list} = options.get("ipv6_ra_pd_list"), var parts = string_split(ipv6_ra_pd_list, ","), @@ -1583,7 +1582,7 @@ relation Flow( relation UseLogicalDatapathGroups[bool] UseLogicalDatapathGroups[use_logical_dp_groups] :- nb in nb::NB_Global(), - var use_logical_dp_groups = map_get_bool_def(nb.options, "use_logical_dp_groups", false). + var use_logical_dp_groups = nb.options.get_bool_def("use_logical_dp_groups", false). UseLogicalDatapathGroups[false] :- Unit(), not nb in nb::NB_Global(). @@ -2012,9 +2011,9 @@ function build_empty_lb_event_flow(key: string, lb: Ref, relation LoadBalancerEmptyEvents(lb: Ref) LoadBalancerEmptyEvents(lb) :- nb::NB_Global(.options = global_options), - var global_events = map_get_bool_def(global_options, "controller_event", false), + var global_events = global_options.get_bool_def("controller_event", false), lb in &LoadBalancerRef[nb::Load_Balancer{.options = local_options}], - var local_events = map_get_bool_def(local_options, "event", false), + var local_events = local_options.get_bool_def("event", false), global_events or local_events. Flow(.logical_datapath = sw.ls._uuid, @@ -2025,7 +2024,7 @@ Flow(.logical_datapath = sw.ls._uuid, .external_ids = stage_hint(lb._uuid)) :- SwitchLBVIP(.sw_uuid = sw_uuid, .lb = lb, .vip = vip, .backends = backends), LoadBalancerEmptyEvents(lb), - not map_get_bool_def(lb.options, "reject", false), + not lb.options.get_bool_def("reject", false), sw in &Switch(.ls = nb::Logical_Switch{._uuid = sw_uuid}), backends == "", HasEventElbMeter(has_elb_meter), @@ -2896,7 +2895,7 @@ function build_lb_vip_actions(lbvip: Ref, }; if (up_backends.is_empty()) { - if (map_get_bool_def(lbvip.lb.options, "reject", false)) { + if (lbvip.lb.options.get_bool_def("reject", false)) { return "reg0 = 0; reject { outport <-> inport; ${next_to_stage(stage)};};" } else if (lbvip.health_check.is_some()) { return "drop;" @@ -3478,7 +3477,7 @@ function build_dhcpv6_action( /* Check whether the dhcpv6 options should be configured as stateful. * Only reply with ia_addr option for dhcpv6 stateful address mode. */ - if (map_get_bool_def(dhcpv6_options.options, "dhcpv6_stateless", false) == false) { + if (not dhcpv6_options.options.get_bool_def("dhcpv6_stateless", false)) { options.push("ia_addr = ${ia_addr}") } else (); @@ -4182,7 +4181,7 @@ for (&SwitchPort(.lsp = lsp, * this logical switch should be run on the chassis * hosting the gateway port. */ - map_get_bool_def(lrp.options, "reside-on-redirect-chassis", false)) in + lrp.options.get_bool_def("reside-on-redirect-chassis", false)) in var __match = if (add_chassis_resident_check) { /* The destination lookup flow for the router's * distributed gateway port MAC address should only be @@ -4751,7 +4750,7 @@ AddChassisResidentCheck_(lrp._uuid, res) :- * hosting the gateway port and it should reply to the * ARP requests for the router port IPs. */ - map_get_bool_def(lrp.options, "reside-on-redirect-chassis", false) + lrp.options.get_bool_def("reside-on-redirect-chassis", false) }. @@ -5916,7 +5915,7 @@ for (RouterLBVIP( .backends = backends) if l3dgw_port.is_some() or is_gateway) { - if (backends == "" and not map_get_bool_def(lb.options, "reject", false)) { + if (backends == "" and not lb.options.get_bool_def("reject", false)) { for (LoadBalancerEmptyEvents(lb)) { for (HasEventElbMeter(has_elb_meter)) { Some {(var __match, var __action)} = @@ -5973,7 +5972,7 @@ for (RouterLBVIP( (110, "") } in var __match = match1 ++ match2 ++ - match ((l3dgw_port, backends != "" or map_get_bool_def(lb.options, "reject", false))) { + match ((l3dgw_port, backends != "" or lb.options.get_bool_def("reject", false))) { (Some{gwport}, true) -> " && is_chassis_resident(${redirect_port_name})", _ -> "" } in @@ -6088,17 +6087,14 @@ Flow(.logical_datapath = r.lr._uuid, * 6.2.1 */ function nD_RA_MAX_INTERVAL_DEFAULT(): integer = 600 +function nD_RA_MAX_INTERVAL_RANGE(): (integer, integer) { (4, 1800) } function nd_ra_min_interval_default(max: integer): integer = { if (max >= 9) { max / 3 } else { max * 3 / 4 } } -function nD_RA_MAX_INTERVAL_MAX(): integer = 1800 -function nD_RA_MAX_INTERVAL_MIN(): integer = 4 - -function nD_RA_MIN_INTERVAL_MAX(max: integer): integer = ((max * 3) / 4) -function nD_RA_MIN_INTERVAL_MIN(): integer = 3 +function nD_RA_MIN_INTERVAL_RANGE(max: integer): (integer, integer) = (3, ((max * 3) / 4)) function nD_MTU_DEFAULT(): integer = 0 @@ -6109,33 +6105,17 @@ function copy_ra_to_sb(port: RouterPort, address_mode: string): Map nD_RA_MAX_INTERVAL_MAX()) { - max_interval = nD_RA_MAX_INTERVAL_MAX() - }; - - if (max_interval < nD_RA_MAX_INTERVAL_MIN()) { - max_interval = nD_RA_MAX_INTERVAL_MIN() - }; - + var max_interval = port.lrp.ipv6_ra_configs + .get_int_def("max_interval", nD_RA_MAX_INTERVAL_DEFAULT()) + .clamp(nD_RA_MAX_INTERVAL_RANGE()); options.insert("ipv6_ra_max_interval", "${max_interval}"); - var min_interval = map_get_int_def(port.lrp.ipv6_ra_configs, - "min_interval", nd_ra_min_interval_default(max_interval)); - - if (min_interval > nD_RA_MIN_INTERVAL_MAX(max_interval)) { - min_interval = nD_RA_MIN_INTERVAL_MAX(max_interval) - } else (); - - if (min_interval < nD_RA_MIN_INTERVAL_MIN()) { - min_interval = nD_RA_MIN_INTERVAL_MIN() - } else (); - + var min_interval = port.lrp.ipv6_ra_configs + .get_int_def("min_interval", nd_ra_min_interval_default(max_interval)) + .clamp(nD_RA_MIN_INTERVAL_RANGE(max_interval)); options.insert("ipv6_ra_min_interval", "${min_interval}"); - var mtu = map_get_int_def(port.lrp.ipv6_ra_configs, "mtu", nD_MTU_DEFAULT()); + var mtu = port.lrp.ipv6_ra_configs.get_int_def("mtu", nD_MTU_DEFAULT()); /* RFC 2460 requires the MTU for IPv6 to be at least 1280 */ if (mtu != 0 and mtu >= 1280) { @@ -6202,7 +6182,7 @@ for (&RouterPort[port@RouterPort{.lrp = lrp@nb::Logical_Router_Port{.peer = None false } else { true } in { - if (map_get_bool_def(lrp.ipv6_ra_configs, "send_periodic", false)) { + if (lrp.ipv6_ra_configs.get_bool_def("send_periodic", false)) { RouterPortRAOptions(lrp._uuid, copy_ra_to_sb(port, address_mode)) }; @@ -6992,7 +6972,7 @@ for (&SwitchPort(.lsp = lsp1, .peer = Some{&peer1@RouterPort{.router = &peer_router}}, .sw = &sw) if lsp1.is_enabled() and - not map_get_bool_def(peer_router.lr.options, "dynamic_neigh_routers", false)) + not peer_router.lr.options.get_bool_def("dynamic_neigh_routers", false)) { for (&SwitchPort(.lsp = lsp2, .peer = Some{&peer2}, .sw = &Switch{.ls = nb::Logical_Switch{._uuid = sw.ls._uuid}}) @@ -7075,7 +7055,7 @@ Flow(.logical_datapath = lr._uuid, Some{var l3dgw_port} = r.l3dgw_port, var l3dgw_port_json_name = json_string_escape(l3dgw_port.name), r.redirect_port_name != "", - var gw_mtu = map_get_int_def(l3dgw_port.options, "gateway_mtu", 0), + var gw_mtu = l3dgw_port.options.get_int_def("gateway_mtu", 0), gw_mtu > 0, var mtu = gw_mtu + vLAN_ETH_HEADER_LEN(). Flow(.logical_datapath = lr._uuid, @@ -7100,7 +7080,7 @@ Flow(.logical_datapath = lr._uuid, Some{var l3dgw_port} = r.l3dgw_port, var l3dgw_port_json_name = json_string_escape(l3dgw_port.name), r.redirect_port_name != "", - var gw_mtu = map_get_int_def(l3dgw_port.options, "gateway_mtu", 0), + var gw_mtu = l3dgw_port.options.get_int_def("gateway_mtu", 0), gw_mtu > 0, rp in &RouterPort(.router = r), rp.lrp != l3dgw_port, @@ -7127,7 +7107,7 @@ Flow(.logical_datapath = lr._uuid, Some{var l3dgw_port} = r.l3dgw_port, var l3dgw_port_json_name = json_string_escape(l3dgw_port.name), r.redirect_port_name != "", - var gw_mtu = map_get_int_def(l3dgw_port.options, "gateway_mtu", 0), + var gw_mtu = l3dgw_port.options.get_int_def("gateway_mtu", 0), gw_mtu > 0, rp in &RouterPort(.router = r), rp.lrp != l3dgw_port, From patchwork Thu Mar 4 04:10:07 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ben Pfaff X-Patchwork-Id: 1447084 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.136; helo=smtp3.osuosl.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Received: from smtp3.osuosl.org (smtp3.osuosl.org [140.211.166.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 4DrcqP09Cqz9sRf for ; Thu, 4 Mar 2021 15:10:57 +1100 (AEDT) Received: from localhost (localhost [127.0.0.1]) by smtp3.osuosl.org (Postfix) with ESMTP id 18CC16FB82; Thu, 4 Mar 2021 04:10:55 +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 3RiasUPbZJ5U; Thu, 4 Mar 2021 04:10:50 +0000 (UTC) Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56]) by smtp3.osuosl.org (Postfix) with ESMTP id E520D6FB3B; Thu, 4 Mar 2021 04:10:39 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id 1378CC0021; Thu, 4 Mar 2021 04:10:38 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@lists.linuxfoundation.org Received: from smtp1.osuosl.org (smtp1.osuosl.org [140.211.166.138]) by lists.linuxfoundation.org (Postfix) with ESMTP id 1B015C001A for ; Thu, 4 Mar 2021 04:10:36 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by smtp1.osuosl.org (Postfix) with ESMTP id EB03184349 for ; Thu, 4 Mar 2021 04:10:30 +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 41-M-ZsiSVaK for ; Thu, 4 Mar 2021 04:10:29 +0000 (UTC) X-Greylist: domain auto-whitelisted by SQLgrey-1.8.0 Received: from relay9-d.mail.gandi.net (relay9-d.mail.gandi.net [217.70.183.199]) by smtp1.osuosl.org (Postfix) with ESMTPS id 9EC688430A for ; Thu, 4 Mar 2021 04:10:28 +0000 (UTC) X-Originating-IP: 75.54.222.30 Received: from sigfpe.attlocal.net (75-54-222-30.lightspeed.rdcyca.sbcglobal.net [75.54.222.30]) (Authenticated sender: blp@ovn.org) by relay9-d.mail.gandi.net (Postfix) with ESMTPSA id 2BCC5FF803; Thu, 4 Mar 2021 04:10:25 +0000 (UTC) From: Ben Pfaff To: dev@openvswitch.org Date: Wed, 3 Mar 2021 20:10:07 -0800 Message-Id: <20210304041012.4128938-7-blp@ovn.org> X-Mailer: git-send-email 2.29.2 In-Reply-To: <20210304041012.4128938-1-blp@ovn.org> References: <20210304041012.4128938-1-blp@ovn.org> MIME-Version: 1.0 Cc: Ben Pfaff Subject: [ovs-dev] [PATCH ovn 06/11] ovn-northd-ddlog: Add general-purpose bitwise library. 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" This should really go into upstream ddlog, but it's OK here for the moment. Signed-off-by: Ben Pfaff --- northd/automake.mk | 4 +- northd/bitwise.dl | 272 +++++++++++++++++++++++++++++++++++++++++++++ northd/bitwise.rs | 133 ++++++++++++++++++++++ northd/ovn.dl | 5 +- northd/ovn.rs | 5 - 5 files changed, 409 insertions(+), 10 deletions(-) create mode 100644 northd/bitwise.dl create mode 100644 northd/bitwise.rs diff --git a/northd/automake.mk b/northd/automake.mk index d64d1d197c77..aaea7e1b1336 100644 --- a/northd/automake.mk +++ b/northd/automake.mk @@ -17,6 +17,7 @@ EXTRA_DIST += \ northd/ovn-sb.dlopts \ northd/ovn.toml \ northd/ovn.rs \ + northd/bitwise.rs \ northd/ovsdb2ddlog2c \ $(ddlog_sources) @@ -28,7 +29,8 @@ ddlog_sources = \ northd/multicast.dl \ northd/ovn.dl \ northd/ovn.rs \ - northd/helpers.dl + northd/helpers.dl \ + northd/bitwise.dl ddlog_nodist_sources = \ northd/OVN_Northbound.dl \ northd/OVN_Southbound.dl diff --git a/northd/bitwise.dl b/northd/bitwise.dl new file mode 100644 index 000000000000..877d155a2304 --- /dev/null +++ b/northd/bitwise.dl @@ -0,0 +1,272 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Returns true if and only if 'x' is a power of 2. + */ +function is_power_of_two(x: u8): bool { x != 0 and (x & (x - 1)) == 0 } +function is_power_of_two(x: u16): bool { x != 0 and (x & (x - 1)) == 0 } +function is_power_of_two(x: u32): bool { x != 0 and (x & (x - 1)) == 0 } +function is_power_of_two(x: u64): bool { x != 0 and (x & (x - 1)) == 0 } +function is_power_of_two(x: u128): bool { x != 0 and (x & (x - 1)) == 0 } + +/* + * Returns the next power of 2 greater than 'x', or None if that's bigger than the + * type's maximum value. + */ +function next_power_of_two(x: u8): Option { u8_next_power_of_two(x) } +function next_power_of_two(x: u16): Option { u16_next_power_of_two(x) } +function next_power_of_two(x: u32): Option { u32_next_power_of_two(x) } +function next_power_of_two(x: u64): Option { u64_next_power_of_two(x) } +function next_power_of_two(x: u128): Option { u128_next_power_of_two(x) } + +extern function u8_next_power_of_two(x: u8): Option +extern function u16_next_power_of_two(x: u16): Option +extern function u32_next_power_of_two(x: u32): Option +extern function u64_next_power_of_two(x: u64): Option +extern function u128_next_power_of_two(x: u128): Option + +/* + * Returns the next power of 2 greater than 'x', or 0 if that's bigger than the + * type's maximum value. + */ +function wrapping_next_power_of_two(x: u8): u8 { u8_wrapping_next_power_of_two(x) } +function wrapping_next_power_of_two(x: u16): u16 { u16_wrapping_next_power_of_two(x) } +function wrapping_next_power_of_two(x: u32): u32 { u32_wrapping_next_power_of_two(x) } +function wrapping_next_power_of_two(x: u64): u64 { u64_wrapping_next_power_of_two(x) } +function wrapping_next_power_of_two(x: u128): u128 { u128_wrapping_next_power_of_two(x) } + +extern function u8_wrapping_next_power_of_two(x: u8): u8 +extern function u16_wrapping_next_power_of_two(x: u16): u16 +extern function u32_wrapping_next_power_of_two(x: u32): u32 +extern function u64_wrapping_next_power_of_two(x: u64): u64 +extern function u128_wrapping_next_power_of_two(x: u128): u128 + +/* + * Number of 1-bits in the binary representation of 'x'. + */ +function count_ones(x: u8): u32 { u8_count_ones(x) } +function count_ones(x: u16): u32 { u16_count_ones(x) } +function count_ones(x: u32): u32 { u32_count_ones(x) } +function count_ones(x: u64): u32 { u64_count_ones(x) } +function count_ones(x: u128): u32 { u128_count_ones(x) } + +extern function u8_count_ones(x: u8): u32 +extern function u16_count_ones(x: u16): u32 +extern function u32_count_ones(x: u32): u32 +extern function u64_count_ones(x: u64): u32 +extern function u128_count_ones(x: u128): u32 + +/* + * Number of 0-bits in the binary representation of 'x'. + */ +function count_zeros(x: u8): u32 { u8_count_zeros(x) } +function count_zeros(x: u16): u32 { u16_count_zeros(x) } +function count_zeros(x: u32): u32 { u32_count_zeros(x) } +function count_zeros(x: u64): u32 { u64_count_zeros(x) } +function count_zeros(x: u128): u32 { u128_count_zeros(x) } + +extern function u8_count_zeros(x: u8): u32 +extern function u16_count_zeros(x: u16): u32 +extern function u32_count_zeros(x: u32): u32 +extern function u64_count_zeros(x: u64): u32 +extern function u128_count_zeros(x: u128): u32 + +/* + * Number of leading 0-bits in the binary representation of 'x'. + */ +function leading_zeros(x: u8): u32 { u8_leading_zeros(x) } +function leading_zeros(x: u16): u32 { u16_leading_zeros(x) } +function leading_zeros(x: u32): u32 { u32_leading_zeros(x) } +function leading_zeros(x: u64): u32 { u64_leading_zeros(x) } +function leading_zeros(x: u128): u32 { u128_leading_zeros(x) } + +extern function u8_leading_zeros(x: u8): u32 +extern function u16_leading_zeros(x: u16): u32 +extern function u32_leading_zeros(x: u32): u32 +extern function u64_leading_zeros(x: u64): u32 +extern function u128_leading_zeros(x: u128): u32 + +/* + * Number of leading 1-bits in the binary representation of 'x'. + */ +function leading_ones(x: u8): u32 { u8_leading_ones(x) } +function leading_ones(x: u16): u32 { u16_leading_ones(x) } +function leading_ones(x: u32): u32 { u32_leading_ones(x) } +function leading_ones(x: u64): u32 { u64_leading_ones(x) } +function leading_ones(x: u128): u32 { u128_leading_ones(x) } + +extern function u8_leading_ones(x: u8): u32 +extern function u16_leading_ones(x: u16): u32 +extern function u32_leading_ones(x: u32): u32 +extern function u64_leading_ones(x: u64): u32 +extern function u128_leading_ones(x: u128): u32 + +/* + * Number of trailing 0-bits in the binary representation of 'x'. + */ +function trailing_zeros(x: u8): u32 { u8_trailing_zeros(x) } +function trailing_zeros(x: u16): u32 { u16_trailing_zeros(x) } +function trailing_zeros(x: u32): u32 { u32_trailing_zeros(x) } +function trailing_zeros(x: u64): u32 { u64_trailing_zeros(x) } +function trailing_zeros(x: u128): u32 { u128_trailing_zeros(x) } + +extern function u8_trailing_zeros(x: u8): u32 +extern function u16_trailing_zeros(x: u16): u32 +extern function u32_trailing_zeros(x: u32): u32 +extern function u64_trailing_zeros(x: u64): u32 +extern function u128_trailing_zeros(x: u128): u32 + +/* + * Number of trailing 0-bits in the binary representation of 'x'. + */ +function trailing_ones(x: u8): u32 { u8_trailing_ones(x) } +function trailing_ones(x: u16): u32 { u16_trailing_ones(x) } +function trailing_ones(x: u32): u32 { u32_trailing_ones(x) } +function trailing_ones(x: u64): u32 { u64_trailing_ones(x) } +function trailing_ones(x: u128): u32 { u128_trailing_ones(x) } + +extern function u8_trailing_ones(x: u8): u32 +extern function u16_trailing_ones(x: u16): u32 +extern function u32_trailing_ones(x: u32): u32 +extern function u64_trailing_ones(x: u64): u32 +extern function u128_trailing_ones(x: u128): u32 + +/* + * Reverses the order of bits in 'x'. + */ +function reverse_bits(x: u8): u8 { u8_reverse_bits(x) } +function reverse_bits(x: u16): u16 { u16_reverse_bits(x) } +function reverse_bits(x: u32): u32 { u32_reverse_bits(x) } +function reverse_bits(x: u64): u64 { u64_reverse_bits(x) } +function reverse_bits(x: u128): u128 { u128_reverse_bits(x) } + +extern function u8_reverse_bits(x: u8): u8 +extern function u16_reverse_bits(x: u16): u16 +extern function u32_reverse_bits(x: u32): u32 +extern function u64_reverse_bits(x: u64): u64 +extern function u128_reverse_bits(x: u128): u128 + +/* + * Reverses the order of bytes in 'x'. + */ +function swap_bytes(x: u8): u8 { u8_swap_bytes(x) } +function swap_bytes(x: u16): u16 { u16_swap_bytes(x) } +function swap_bytes(x: u32): u32 { u32_swap_bytes(x) } +function swap_bytes(x: u64): u64 { u64_swap_bytes(x) } +function swap_bytes(x: u128): u128 { u128_swap_bytes(x) } + +extern function u8_swap_bytes(x: u8): u8 +extern function u16_swap_bytes(x: u16): u16 +extern function u32_swap_bytes(x: u32): u32 +extern function u64_swap_bytes(x: u64): u64 +extern function u128_swap_bytes(x: u128): u128 + +/* + * Converts 'x' from big endian to the machine's native endianness. + * On a big-endian machine it is a no-op. + * On a little-end machine it is equivalent to swap_bytes(). + */ +function from_be(x: u8): u8 { u8_from_be(x) } +function from_be(x: u16): u16 { u16_from_be(x) } +function from_be(x: u32): u32 { u32_from_be(x) } +function from_be(x: u64): u64 { u64_from_be(x) } +function from_be(x: u128): u128 { u128_from_be(x) } + +extern function u8_from_be(x: u8): u8 +extern function u16_from_be(x: u16): u16 +extern function u32_from_be(x: u32): u32 +extern function u64_from_be(x: u64): u64 +extern function u128_from_be(x: u128): u128 + +/* + * Converts 'x' from the machine's native endianness to big endian. + * On a big-endian machine it is a no-op. + * On a little-endian machine it is equivalent to swap_bytes(). + */ +function to_be(x: u8): u8 { u8_to_be(x) } +function to_be(x: u16): u16 { u16_to_be(x) } +function to_be(x: u32): u32 { u32_to_be(x) } +function to_be(x: u64): u64 { u64_to_be(x) } +function to_be(x: u128): u128 { u128_to_be(x) } + +extern function u8_to_be(x: u8): u8 +extern function u16_to_be(x: u16): u16 +extern function u32_to_be(x: u32): u32 +extern function u64_to_be(x: u64): u64 +extern function u128_to_be(x: u128): u128 + +/* + * Converts 'x' from little endian to the machine's native endianness. + * On a little-endian machine it is a no-op. + * On a big-endian machine it is equivalent to swap_bytes(). + */ +function from_le(x: u8): u8 { u8_from_le(x) } +function from_le(x: u16): u16 { u16_from_le(x) } +function from_le(x: u32): u32 { u32_from_le(x) } +function from_le(x: u64): u64 { u64_from_le(x) } +function from_le(x: u128): u128 { u128_from_le(x) } + +extern function u8_from_le(x: u8): u8 +extern function u16_from_le(x: u16): u16 +extern function u32_from_le(x: u32): u32 +extern function u64_from_le(x: u64): u64 +extern function u128_from_le(x: u128): u128 + +/* + * Converts 'x' from the machine's native endianness to little endian. + * On a little-endian machine it is a no-op. + * On a big-endian machine it is equivalent to swap_bytes(). + */ +function to_le(x: u8): u8 { u8_to_le(x) } +function to_le(x: u16): u16 { u16_to_le(x) } +function to_le(x: u32): u32 { u32_to_le(x) } +function to_le(x: u64): u64 { u64_to_le(x) } +function to_le(x: u128): u128 { u128_to_le(x) } + +extern function u8_to_le(x: u8): u8 +extern function u16_to_le(x: u16): u16 +extern function u32_to_le(x: u32): u32 +extern function u64_to_le(x: u64): u64 +extern function u128_to_le(x: u128): u128 + +/* + * Rotates the bits in 'x' left by 'n' positions. + */ +function rotate_left(x: u8, n: u32): u8 { u8_rotate_left(x, n) } +function rotate_left(x: u16, n: u32): u16 { u16_rotate_left(x, n) } +function rotate_left(x: u32, n: u32): u32 { u32_rotate_left(x, n) } +function rotate_left(x: u64, n: u32): u64 { u64_rotate_left(x, n) } +function rotate_left(x: u128, n: u32): u128 { u128_rotate_left(x, n) } + +extern function u8_rotate_left(x: u8, n: u32): u8 +extern function u16_rotate_left(x: u16, n: u32): u16 +extern function u32_rotate_left(x: u32, n: u32): u32 +extern function u64_rotate_left(x: u64, n: u32): u64 +extern function u128_rotate_left(x: u128, n: u32): u128 + +/* + * Rotates the bits in 'x' right by 'n' positions. + */ +function rotate_right(x: u8, n: u32): u8 { u8_rotate_right(x, n) } +function rotate_right(x: u16, n: u32): u16 { u16_rotate_right(x, n) } +function rotate_right(x: u32, n: u32): u32 { u32_rotate_right(x, n) } +function rotate_right(x: u64, n: u32): u64 { u64_rotate_right(x, n) } +function rotate_right(x: u128, n: u32): u128 { u128_rotate_right(x, n) } + +extern function u8_rotate_right(x: u8, n: u32): u8 +extern function u16_rotate_right(x: u16, n: u32): u16 +extern function u32_rotate_right(x: u32, n: u32): u32 +extern function u64_rotate_right(x: u64, n: u32): u64 +extern function u128_rotate_right(x: u128, n: u32): u128 diff --git a/northd/bitwise.rs b/northd/bitwise.rs new file mode 100644 index 000000000000..97c0ecfa3632 --- /dev/null +++ b/northd/bitwise.rs @@ -0,0 +1,133 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +use ddlog_std::option2std; + +pub fn u8_next_power_of_two(x: &u8) -> ddlog_std::Option { + option2std(x.checked_next_power_of_two()) +} +pub fn u16_next_power_of_two(x: &u16) -> ddlog_std::Option { + option2std(x.checked_next_power_of_two()) +} +pub fn u32_next_power_of_two(x: &u32) -> ddlog_std::Option { + option2std(x.checked_next_power_of_two()) +} +pub fn u64_next_power_of_two(x: &u64) -> ddlog_std::Option { + option2std(x.checked_next_power_of_two()) +} +pub fn u128_next_power_of_two(x: &u128) -> ddlog_std::Option { + option2std(x.checked_next_power_of_two()) +} + +// Rust has wrapping_next_power_of_two() in nightly. We implement it +// ourselves to avoid the dependency. +pub fn u8_wrapping_next_power_of_two(x: &u8) -> u8 { + x.checked_next_power_of_two().unwrap_or(0) +} +pub fn u16_wrapping_next_power_of_two(x: &u16) -> u16 { + x.checked_next_power_of_two().unwrap_or(0) +} +pub fn u32_wrapping_next_power_of_two(x: &u32) -> u32 { + x.checked_next_power_of_two().unwrap_or(0) +} +pub fn u64_wrapping_next_power_of_two(x: &u64) -> u64 { + x.checked_next_power_of_two().unwrap_or(0) +} +pub fn u128_wrapping_next_power_of_two(x: &u128) -> u128 { + x.checked_next_power_of_two().unwrap_or(0) +} + +pub fn u8_count_ones(x: &u8) -> u32 { x.count_ones() } +pub fn u16_count_ones(x: &u16) -> u32 { x.count_ones() } +pub fn u32_count_ones(x: &u32) -> u32 { x.count_ones() } +pub fn u64_count_ones(x: &u64) -> u32 { x.count_ones() } +pub fn u128_count_ones(x: &u128) -> u32 { x.count_ones() } + +pub fn u8_count_zeros(x: &u8) -> u32 { x.count_zeros() } +pub fn u16_count_zeros(x: &u16) -> u32 { x.count_zeros() } +pub fn u32_count_zeros(x: &u32) -> u32 { x.count_zeros() } +pub fn u64_count_zeros(x: &u64) -> u32 { x.count_zeros() } +pub fn u128_count_zeros(x: &u128) -> u32 { x.count_zeros() } + +pub fn u8_leading_ones(x: &u8) -> u32 { x.leading_ones() } +pub fn u16_leading_ones(x: &u16) -> u32 { x.leading_ones() } +pub fn u32_leading_ones(x: &u32) -> u32 { x.leading_ones() } +pub fn u64_leading_ones(x: &u64) -> u32 { x.leading_ones() } +pub fn u128_leading_ones(x: &u128) -> u32 { x.leading_ones() } + +pub fn u8_leading_zeros(x: &u8) -> u32 { x.leading_zeros() } +pub fn u16_leading_zeros(x: &u16) -> u32 { x.leading_zeros() } +pub fn u32_leading_zeros(x: &u32) -> u32 { x.leading_zeros() } +pub fn u64_leading_zeros(x: &u64) -> u32 { x.leading_zeros() } +pub fn u128_leading_zeros(x: &u128) -> u32 { x.leading_zeros() } + +pub fn u8_trailing_ones(x: &u8) -> u32 { x.trailing_ones() } +pub fn u16_trailing_ones(x: &u16) -> u32 { x.trailing_ones() } +pub fn u32_trailing_ones(x: &u32) -> u32 { x.trailing_ones() } +pub fn u64_trailing_ones(x: &u64) -> u32 { x.trailing_ones() } +pub fn u128_trailing_ones(x: &u128) -> u32 { x.trailing_ones() } + +pub fn u8_trailing_zeros(x: &u8) -> u32 { x.trailing_zeros() } +pub fn u16_trailing_zeros(x: &u16) -> u32 { x.trailing_zeros() } +pub fn u32_trailing_zeros(x: &u32) -> u32 { x.trailing_zeros() } +pub fn u64_trailing_zeros(x: &u64) -> u32 { x.trailing_zeros() } +pub fn u128_trailing_zeros(x: &u128) -> u32 { x.trailing_zeros() } + +pub fn u8_reverse_bits(x: &u8) -> u8 { x.reverse_bits() } +pub fn u16_reverse_bits(x: &u16) -> u16 { x.reverse_bits() } +pub fn u32_reverse_bits(x: &u32) -> u32 { x.reverse_bits() } +pub fn u64_reverse_bits(x: &u64) -> u64 { x.reverse_bits() } +pub fn u128_reverse_bits(x: &u128) -> u128 { x.reverse_bits() } + +pub fn u8_swap_bytes(x: &u8) -> u8 { x.swap_bytes() } +pub fn u16_swap_bytes(x: &u16) -> u16 { x.swap_bytes() } +pub fn u32_swap_bytes(x: &u32) -> u32 { x.swap_bytes() } +pub fn u64_swap_bytes(x: &u64) -> u64 { x.swap_bytes() } +pub fn u128_swap_bytes(x: &u128) -> u128 { x.swap_bytes() } + +pub fn u8_from_be(x: &u8) -> u8 { u8::from_be(*x) } +pub fn u16_from_be(x: &u16) -> u16 { u16::from_be(*x) } +pub fn u32_from_be(x: &u32) -> u32 { u32::from_be(*x) } +pub fn u64_from_be(x: &u64) -> u64 { u64::from_be(*x) } +pub fn u128_from_be(x: &u128) -> u128 { u128::from_be(*x) } + +pub fn u8_to_be(x: &u8) -> u8 { x.to_be() } +pub fn u16_to_be(x: &u16) -> u16 { x.to_be() } +pub fn u32_to_be(x: &u32) -> u32 { x.to_be() } +pub fn u64_to_be(x: &u64) -> u64 { x.to_be() } +pub fn u128_to_be(x: &u128) -> u128 { x.to_be() } + +pub fn u8_from_le(x: &u8) -> u8 { u8::from_le(*x) } +pub fn u16_from_le(x: &u16) -> u16 { u16::from_le(*x) } +pub fn u32_from_le(x: &u32) -> u32 { u32::from_le(*x) } +pub fn u64_from_le(x: &u64) -> u64 { u64::from_le(*x) } +pub fn u128_from_le(x: &u128) -> u128 { u128::from_le(*x) } + +pub fn u8_to_le(x: &u8) -> u8 { x.to_le() } +pub fn u16_to_le(x: &u16) -> u16 { x.to_le() } +pub fn u32_to_le(x: &u32) -> u32 { x.to_le() } +pub fn u64_to_le(x: &u64) -> u64 { x.to_le() } +pub fn u128_to_le(x: &u128) -> u128 { x.to_le() } + +pub fn u8_rotate_left(x: &u8, n: &u32) -> u8 { x.rotate_left(*n) } +pub fn u16_rotate_left(x: &u16, n: &u32) -> u16 { x.rotate_left(*n) } +pub fn u32_rotate_left(x: &u32, n: &u32) -> u32 { x.rotate_left(*n) } +pub fn u64_rotate_left(x: &u64, n: &u32) -> u64 { x.rotate_left(*n) } +pub fn u128_rotate_left(x: &u128, n: &u32) -> u128 { x.rotate_left(*n) } + +pub fn u8_rotate_right(x: &u8, n: &u32) -> u8 { x.rotate_right(*n) } +pub fn u16_rotate_right(x: &u16, n: &u32) -> u16 { x.rotate_right(*n) } +pub fn u32_rotate_right(x: &u32, n: &u32) -> u32 { x.rotate_right(*n) } +pub fn u64_rotate_right(x: &u64, n: &u32) -> u64 { x.rotate_right(*n) } +pub fn u128_rotate_right(x: &u128, n: &u32) -> u128 { x.rotate_right(*n) } diff --git a/northd/ovn.dl b/northd/ovn.dl index 1e9e65d2a2b2..52fe3d82be33 100644 --- a/northd/ovn.dl +++ b/northd/ovn.dl @@ -13,7 +13,7 @@ */ import ovsdb - +import bitwise /* Logical port is enabled if it does not have an enabled flag or the flag is true */ function is_enabled(s: Option): bool = { @@ -375,9 +375,6 @@ extern function ovn_internal_version(): string */ extern function json_string_escape(s: string): string -/* Returns the number of 1-bits in `x`, between 0 and 64 inclusive */ -extern function count_1bits(x: bit<64>): bit<8> - /* For a 'key' of the form "IP:port" or just "IP", returns * (v46_ip, port) tuple. */ extern function ip_address_and_port_from_lb_key(k: string): Option<(v46_ip, bit<16>)> diff --git a/northd/ovn.rs b/northd/ovn.rs index 46a2e2d3c4d5..c4842bdbc424 100644 --- a/northd/ovn.rs +++ b/northd/ovn.rs @@ -488,11 +488,6 @@ pub fn ip_address_and_port_from_lb_key(k: &String) -> } } -pub fn count_1bits(x: &u64) -> u8 { - x.count_ones() as u8 -} - - pub fn str_to_int(s: &String, base: &u16) -> ddlog_std::Option { let mut i: raw::c_int = 0; let ok = unsafe { From patchwork Thu Mar 4 04:10:08 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ben Pfaff X-Patchwork-Id: 1447087 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.133; helo=smtp2.osuosl.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Received: from smtp2.osuosl.org (smtp2.osuosl.org [140.211.166.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 4Drcqc5Gwmz9sRf for ; Thu, 4 Mar 2021 15:11:08 +1100 (AEDT) Received: from localhost (localhost [127.0.0.1]) by smtp2.osuosl.org (Postfix) with ESMTP id B469443251; Thu, 4 Mar 2021 04:11:06 +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 RZ8g6bjp5LWk; Thu, 4 Mar 2021 04:10:58 +0000 (UTC) Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56]) by smtp2.osuosl.org (Postfix) with ESMTP id 4357643270; Thu, 4 Mar 2021 04:10:51 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id 0FB52C000A; Thu, 4 Mar 2021 04:10:51 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@lists.linuxfoundation.org Received: from smtp3.osuosl.org (smtp3.osuosl.org [140.211.166.136]) by lists.linuxfoundation.org (Postfix) with ESMTP id 237B6C0001 for ; Thu, 4 Mar 2021 04:10:50 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by smtp3.osuosl.org (Postfix) with ESMTP id C1E2D6FB28 for ; Thu, 4 Mar 2021 04:10:37 +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 DiD82vNOmPuW for ; Thu, 4 Mar 2021 04:10:30 +0000 (UTC) X-Greylist: domain auto-whitelisted by SQLgrey-1.8.0 Received: from relay9-d.mail.gandi.net (relay9-d.mail.gandi.net [217.70.183.199]) by smtp3.osuosl.org (Postfix) with ESMTPS id 3DF366F97E for ; Thu, 4 Mar 2021 04:10:30 +0000 (UTC) X-Originating-IP: 75.54.222.30 Received: from sigfpe.attlocal.net (75-54-222-30.lightspeed.rdcyca.sbcglobal.net [75.54.222.30]) (Authenticated sender: blp@ovn.org) by relay9-d.mail.gandi.net (Postfix) with ESMTPSA id 8F5EFFF805; Thu, 4 Mar 2021 04:10:27 +0000 (UTC) From: Ben Pfaff To: dev@openvswitch.org Date: Wed, 3 Mar 2021 20:10:08 -0800 Message-Id: <20210304041012.4128938-8-blp@ovn.org> X-Mailer: git-send-email 2.29.2 In-Reply-To: <20210304041012.4128938-1-blp@ovn.org> References: <20210304041012.4128938-1-blp@ovn.org> MIME-Version: 1.0 Cc: Ben Pfaff Subject: [ovs-dev] [PATCH ovn 07/11] ovn-northd-ddlog: Define in_addr, in6_addr, eth_addr in ddlog code. 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" All of these were defined as opaque "extern" types in the ddlog code. I have found that they are easier to work with and understand if the ddlog code can look into their implementations. This commit re-defines them in terms of proper ddlog types. It also renames many of the functions that operate on them so that they can be used in an object-like form, as well as defining many of these functions in ddlog code rather than as externs. This code refactoring shouldn't change ovn-northd-ddlog behavior. Signed-off-by: Ben Pfaff --- northd/ipam.dl | 64 +++++----- northd/lrouter.dl | 4 +- northd/lswitch.dl | 7 +- northd/multicast.dl | 2 +- northd/ovn.dl | 281 +++++++++++++++++++++-------------------- northd/ovn.rs | 290 +++++++++++++------------------------------ northd/ovn_northd.dl | 116 +++++++++-------- 7 files changed, 320 insertions(+), 444 deletions(-) diff --git a/northd/ipam.dl b/northd/ipam.dl index 1349a933eba0..589126f81288 100644 --- a/northd/ipam.dl +++ b/northd/ipam.dl @@ -30,7 +30,7 @@ import ovn import lswitch import lrouter -function mAC_ADDR_SPACE(): bit<64> = 64'hffffff +function mAC_ADDR_SPACE(): bit<48> = 48'hffffff /* * IPv4 dynamic address allocation. @@ -112,10 +112,10 @@ SwitchIPv4ReservedAddress(.lswitch = ls._uuid, Right{ranges} -> { for (rng in ranges) { (var ip_start, var ip_end) = rng; - var start = iptohl(ip_start); + var start = ip_start.a; var end = match (ip_end) { None -> start, - Some{ip} -> iptohl(ip) + Some{ip} -> ip.a }; start = max(start_ipv4, start); end = min(start_ipv4 + total_ipv4s - 1, end); @@ -147,7 +147,7 @@ SwitchIPv4ReservedAddress(.lswitch = ls._uuid, var addrs = { var addrs = set_empty(); for (addr in lport_addrs.ipv4_addrs) { - var addr_host_endian = iptohl(addr.addr); + var addr_host_endian = addr.addr.a; if (addr_host_endian >= start_ipv4 and addr_host_endian < start_ipv4 + total_ipv4s) { addrs.insert(addr_host_endian) } else () @@ -166,7 +166,7 @@ SwitchIPv4ReservedAddress(.lswitch = ls._uuid, var addrs = { var addrs = set_empty(); for (addr in rport.networks.ipv4_addrs) { - var addr_host_endian = iptohl(addr.addr); + var addr_host_endian = addr.addr.a; if (addr_host_endian >= start_ipv4 and addr_host_endian < start_ipv4 + total_ipv4s) { addrs.insert(addr_host_endian) } else () @@ -177,7 +177,7 @@ SwitchIPv4ReservedAddress(.lswitch = ls._uuid, /* Add reserved address group (5) */ SwitchIPv4ReservedAddress(.lswitch = sw.ls._uuid, - .addr = iptohl(ip_addr)) :- + .addr = ip_addr.a) :- &SwitchPort(.sw = &sw, .lsp = lsp, .static_dynamic_ipv4 = Some{ip_addr}). /* Aggregate all reserved addresses for each switch. */ @@ -236,7 +236,7 @@ SwitchPortAllocatedIPv4DynAddress(lsport, dyn_addr) :- need_addr.push(deref(port).lsp._uuid) }, Some{addr} -> { - var haddr = iptohl(addr.addr); + var haddr = addr.addr.a; if (haddr < start_ipv4 or haddr >= start_ipv4 + total_ipv4s) { need_addr.push(deref(port).lsp._uuid) } else if (used_addrs.contains(haddr)) { @@ -257,7 +257,7 @@ SwitchPortAllocatedIPv4DynAddress(lsport, dyn_addr) :- }, var port_address = FlatMap(dyn_addresses), (var lsport, var dyn_addr_bits) = port_address, - var dyn_addr = dyn_addr_bits.map(hltoip). + var dyn_addr = dyn_addr_bits.map(|x| InAddr{x}). /* Compute new dynamic IPv4 address assignment: * - port does not need dynamic IP - use static_dynamic_ip if any @@ -278,7 +278,7 @@ SwitchPortNewIPv4DynAddress(lsp._uuid, ip_addr) :- match (sw.subnet) { None -> { None }, Some{(_, _, start_ipv4, total_ipv4s)} -> { - var haddr = iptohl(addr); + var haddr = addr.a; if (haddr < start_ipv4 or haddr >= start_ipv4 + total_ipv4s) { /* new static ip is not valid */ None @@ -298,24 +298,20 @@ SwitchPortNewIPv4DynAddress(lsport, addr) :- * Dynamic MAC address allocation. */ -function get_mac_prefix(options: Map, uuid: uuid) : bit<64> = +function get_mac_prefix(options: Map, uuid: uuid) : bit<48> = { - var existing_prefix = match (map_get(options, "mac_prefix")) { - Some{prefix} -> scan_eth_addr_prefix(prefix), - None -> None - }; - match (existing_prefix) { - Some{prefix} -> prefix, - None -> pseudorandom_mac(uuid, 16'h1234) & 64'hffffff000000 + match (map_get(options, "mac_prefix").and_then(scan_eth_addr_prefix)) { + Some{prefix} -> prefix.ha, + None -> eth_addr_pseudorandom(uuid, 16'h1234).ha & 48'hffffff000000 } } -function put_mac_prefix(options: Map, mac_prefix: bit<64>) +function put_mac_prefix(options: Map, mac_prefix: bit<48>) : Map = { map_insert_imm(options, "mac_prefix", - string_substr(to_string(eth_addr_from_uint64(mac_prefix)), 0, 8)) + string_substr(to_string(EthAddr{mac_prefix}), 0, 8)) } -relation MacPrefix(mac_prefix: bit<64>) +relation MacPrefix(mac_prefix: bit<48>) MacPrefix(get_mac_prefix(options, uuid)) :- nb::NB_Global(._uuid = uuid, .options = options). @@ -324,24 +320,24 @@ MacPrefix(get_mac_prefix(options, uuid)) :- * (2) static MAC component of "dynamic" `lsp.addresses`. * (3) addresses associated with router ports peered with the switch. * - * Addresses are kept in 64-bit host-endian format. + * Addresses are kept in host-endian format. */ -relation ReservedMACAddress(addr: bit<64>) +relation ReservedMACAddress(addr: bit<48>) /* Add reserved address group (1). */ -ReservedMACAddress(.addr = eth_addr_to_uint64(lport_addrs.ea)) :- +ReservedMACAddress(.addr = lport_addrs.ea.ha) :- SwitchPortStaticAddresses(.addrs = lport_addrs). /* Add reserved address group (2). */ -ReservedMACAddress(.addr = eth_addr_to_uint64(mac_addr)) :- +ReservedMACAddress(.addr = mac_addr.ha) :- &SwitchPort(.lsp = lsp, .static_dynamic_mac = Some{mac_addr}). /* Add reserved address group (3). */ -ReservedMACAddress(.addr = eth_addr_to_uint64(rport.networks.ea)) :- +ReservedMACAddress(.addr = rport.networks.ea.ha) :- &SwitchPort(.peer = Some{&rport}). /* Aggregate all reserved MAC addresses. */ -relation ReservedMACAddresses(addrs: Set>) +relation ReservedMACAddresses(addrs: Set>) ReservedMACAddresses(addrs) :- ReservedMACAddress(addr), @@ -360,7 +356,7 @@ ReservedMACAddresses(set_empty()) :- * Case 2: needs dynamic MAC, has dynamic MAC, has existing dynamic MAC with the right prefix * needs dynamic MAC, does not have fixed dynamic MAC, doesn't have existing dynamic MAC with correct prefix */ -relation SwitchPortAllocatedMACDynAddress(lsport: uuid, dyn_addr: bit<64>) +relation SwitchPortAllocatedMACDynAddress(lsport: uuid, dyn_addr: bit<48>) SwitchPortAllocatedMACDynAddress(lsport, dyn_addr), SwitchPortDuplicateMACAddress(dup_addrs) :- @@ -380,8 +376,8 @@ SwitchPortDuplicateMACAddress(dup_addrs) :- None -> Some { mac_prefix | 1 }, Some{addr} -> { /* The tentative MAC's suffix will be in the interval (1, 0xfffffe). */ - var mac_suffix: bit<24> = iptohl(addr)[23:0] % ((mAC_ADDR_SPACE() - 1)[23:0]) + 1; - Some{ mac_prefix | (40'd0 ++ mac_suffix) } + var mac_suffix: bit<24> = addr.a[23:0] % ((mAC_ADDR_SPACE() - 1)[23:0]) + 1; + Some{ mac_prefix | (24'd0 ++ mac_suffix) } } }; match (port.dynamic_address) { @@ -390,7 +386,7 @@ SwitchPortDuplicateMACAddress(dup_addrs) :- need_addr.push((port.lsp._uuid, hint)) }, Some{dynaddr} -> { - var haddr = eth_addr_to_uint64(dynaddr.ea); + var haddr = dynaddr.ea.ha; if ((haddr ^ mac_prefix) >> 24 != 0) { /* existing dynamic address is no longer valid */ need_addr.push((port.lsp._uuid, hint)) @@ -413,7 +409,7 @@ SwitchPortDuplicateMACAddress(dup_addrs) :- var res_strs = vec_empty(); for (x in res) { (var uuid, var addr) = x; - res_strs.push("${uuid2str(uuid)}: ${eth_addr_from_uint64(addr)}") + res_strs.push("${uuid2str(uuid)}: ${EthAddr{addr}}") }; (res, dup_addrs) }, @@ -449,7 +445,7 @@ SwitchPortNewMACDynAddress(lsp._uuid, mac_addr) :- } }. -SwitchPortNewMACDynAddress(lsport, Some{eth_addr_from_uint64(addr)}) :- +SwitchPortNewMACDynAddress(lsport, Some{EthAddr{addr}}) :- SwitchPortAllocatedMACDynAddress(lsport, addr). SwitchPortNewMACDynAddress(lsp._uuid, addr) :- @@ -462,7 +458,7 @@ SwitchPortNewMACDynAddress(lsp._uuid, addr) :- /* * Dynamic IPv6 address allocation. - * `needs_dynamic_ipv6address` -> in6_generate_eui64(mac, ipv6_prefix) + * `needs_dynamic_ipv6address` -> mac.to_ipv6_eui64(ipv6_prefix) */ relation SwitchPortNewDynamicAddress(port: Ref, address: Option) @@ -479,7 +475,7 @@ SwitchPortNewDynamicAddress(port, lport_address) :- SwitchPortNewIPv4DynAddress(lsp._uuid, opt_ip4_addr), var ip6_addr = match ((static_dynamic_ipv6, needs_dynamic_ipv6address, sw.ipv6_prefix)) { (Some{ipv6}, _, _) -> " ${ipv6}", - (_, true, Some{prefix}) -> " ${in6_generate_eui64(mac_addr, prefix)}", + (_, true, Some{prefix}) -> " ${mac_addr.to_ipv6_eui64(prefix)}", _ -> "" }, var ip4_addr = match (opt_ip4_addr) { diff --git a/northd/lrouter.dl b/northd/lrouter.dl index 7bcacfe2aeb6..7786ef137fc6 100644 --- a/northd/lrouter.dl +++ b/northd/lrouter.dl @@ -655,7 +655,7 @@ function find_lrp_member_ip(networks: lport_addresses, ip: v46_ip): Option { for (na in networks.ipv4_addrs) { - if (ip_same_network((na.addr, ip4), ipv4_netaddr_mask(na))) { + if ((na.addr, ip4).same_network(na.netmask())) { /* There should be only 1 interface that matches the * supplied IP. Otherwise, it's a configuration error, * because subnets of a router's interfaces should NOT @@ -667,7 +667,7 @@ function find_lrp_member_ip(networks: lport_addresses, ip: v46_ip): Option { for (na in networks.ipv6_addrs) { - if (ipv6_same_network((na.addr, ip6), ipv6_netaddr_mask(na))) { + if ((na.addr, ip6).same_network(na.netmask())) { /* There should be only 1 interface that matches the * supplied IP. Otherwise, it's a configuration error, * because subnets of a router's interfaces should NOT diff --git a/northd/lswitch.dl b/northd/lswitch.dl index 5fcb3871c341..47c497e0cff7 100644 --- a/northd/lswitch.dl +++ b/northd/lswitch.dl @@ -242,12 +242,11 @@ function ipv6_parse_prefix(s: string): Option { None }, Right{(subnet, mask)} -> { - if (ip_count_cidr_bits(mask) == Some{32} - or not ip_is_cidr(mask)) { + if (mask.cidr_bits() == Some{32} or not mask.is_cidr()) { warn("bad 'subnet' ${subnet_str}"); None } else { - Some{(subnet, mask, (iptohl(subnet) & iptohl(mask)) + 1, ~iptohl(mask))} + Some{(subnet, mask, (subnet.a & mask.a) + 1, ~mask.a)} } } } @@ -732,7 +731,7 @@ function get_svc_monitor_mac(options: Map, uuid: uuid) }; match (existing_mac) { Some{mac} -> mac, - None -> eth_addr_from_uint64(pseudorandom_mac(uuid, 'h5678)) + None -> eth_addr_pseudorandom(uuid, 'h5678) } } function put_svc_monitor_mac(options: Map, diff --git a/northd/multicast.dl b/northd/multicast.dl index f3989e7899d2..990203bffe25 100644 --- a/northd/multicast.dl +++ b/northd/multicast.dl @@ -224,7 +224,7 @@ IgmpRouterGroupPort(address, rtr_port.router, rtr_port.lrp._uuid) :- * (RFC 4291 2.7). */ match (ipv6_parse(address)) { - Some{ipv6} -> ipv6_is_routable_multicast(ipv6), + Some{ipv6} -> ipv6.is_routable_multicast(), None -> true }, var flood_port = FlatMap(sw_flood_ports), diff --git a/northd/ovn.dl b/northd/ovn.dl index 52fe3d82be33..f23ea3b9e1b1 100644 --- a/northd/ovn.dl +++ b/northd/ovn.dl @@ -23,90 +23,69 @@ function is_enabled(s: Option): bool = { /* * Ethernet addresses */ -extern type eth_addr +typedef eth_addr = EthAddr { + ha: bit<48> // In host byte order, e.g. ha[40] is the multicast bit. +} -extern function eth_addr_zero(): eth_addr -extern function eth_addr2string(addr: eth_addr): string function to_string(addr: eth_addr): string { eth_addr2string(addr) } -extern function scan_eth_addr(s: string): Option -extern function scan_eth_addr_prefix(s: string): Option> extern function eth_addr_from_string(s: string): Option -extern function eth_addr_to_uint64(ea: eth_addr): bit<64> -extern function eth_addr_from_uint64(x: bit<64>): eth_addr -extern function eth_addr_mark_random(ea: eth_addr): eth_addr +extern function scan_eth_addr(s: string): Option +extern function scan_eth_addr_prefix(s: string): Option +function eth_addr_zero(): eth_addr { EthAddr{0} } +function eth_addr_pseudorandom(seed: uuid, variant: bit<16>) : eth_addr { + EthAddr{hash64(seed ++ variant) as bit<48>}.mark_random() +} +function mark_random(ea: eth_addr): eth_addr { EthAddr{ea.ha & ~(1 << 40) | (1 << 41)} } -function pseudorandom_mac(seed: uuid, variant: bit<16>) : bit<64> = { - eth_addr_to_uint64(eth_addr_mark_random(eth_addr_from_uint64(hash64(seed ++ variant)))) +function to_eui64(ea: eth_addr): bit<64> { + var ha = ea.ha as u64; + (((ha & 64'hffffff000000) << 16) | 64'hfffe000000 | (ha & 64'hffffff)) ^ (1 << 57) } +extern function eth_addr2string(addr: eth_addr): string + /* * IPv4 addresses */ -extern type in_addr - -function to_string(ip: in_addr): string = { - var x = iptohl(ip); - "${x >> 24}.${(x >> 16) & 'hff}.${(x >> 8) & 'hff}.${x & 'hff}" -} - -function ip_is_cidr(netmask: in_addr): bool { - var x = ~iptohl(netmask); - (x & (x + 1)) == 0 -} -function ip_is_local_multicast(ip: in_addr): bool { - (iptohl(ip) & 32'hffffff00) == 32'he0000000 -} - -function ip_create_mask(plen: bit<32>): in_addr { - hltoip((64'h00000000ffffffff << (32 - plen))[31:0]) -} - -function ip_bitxor(a: in_addr, b: in_addr): in_addr { - hltoip(iptohl(a) ^ iptohl(b)) -} - -function ip_bitand(a: in_addr, b: in_addr): in_addr { - hltoip(iptohl(a) & iptohl(b)) -} - -function ip_network(addr: in_addr, mask: in_addr): in_addr { - hltoip(iptohl(addr) & iptohl(mask)) -} - -function ip_host(addr: in_addr, mask: in_addr): in_addr { - hltoip(iptohl(addr) & ~iptohl(mask)) +typedef in_addr = InAddr { + a: bit<32> // In host byte order. } -function ip_host_is_zero(addr: in_addr, mask: in_addr): bool { - ip_is_zero(ip_host(addr, mask)) -} +extern function ip_parse(s: string): Option +extern function ip_parse_masked(s: string): Either +extern function ip_parse_cidr(s: string): Either/*plen*/)> +extern function scan_static_dynamic_ip(s: string): Option +function ip_create_mask(plen: bit<32>): in_addr { InAddr{(64'hffffffff << (32 - plen))[31:0]} } -function ip_is_zero(a: in_addr): bool { - iptohl(a) == 0 +function to_string(ip: in_addr): string = { + "${ip.a >> 24}.${(ip.a >> 16) & 'hff}.${(ip.a >> 8) & 'hff}.${ip.a & 'hff}" } -function ip_bcast(addr: in_addr, mask: in_addr): in_addr { - hltoip(iptohl(addr) | ~iptohl(mask)) +function is_cidr(netmask: in_addr): bool { var x = ~netmask.a; (x & (x + 1)) == 0 } +function is_local_multicast(ip: in_addr): bool { (ip.a & 32'hffffff00) == 32'he0000000 } +function is_zero(a: in_addr): bool { a.a == 0 } +function is_all_ones(a: in_addr): bool { a.a == 32'hffffffff } +function cidr_bits(ip: in_addr): Option> { + if (ip.is_cidr()) { + Some{32 - ip.a.trailing_zeros() as u8} + } else { + None + } } -extern function ip_parse(s: string): Option -extern function ip_parse_masked(s: string): Either -extern function ip_parse_cidr(s: string): Either/*plen*/)> -extern function ip_count_cidr_bits(ip: in_addr): Option> +function network(addr: in_addr, mask: in_addr): in_addr { InAddr{addr.a & mask.a} } +function host(addr: in_addr, mask: in_addr): in_addr { InAddr{addr.a & ~mask.a} } +function bcast(addr: in_addr, mask: in_addr): in_addr { InAddr{addr.a | ~mask.a} } /* True if both 'ips' are in the same network as defined by netmask 'mask', * false otherwise. */ -function ip_same_network(ips: (in_addr, in_addr), mask: in_addr): bool { - ((iptohl(ips.0) ^ iptohl(ips.1)) & iptohl(mask)) == 0 +function same_network(ips: (in_addr, in_addr), mask: in_addr): bool { + ((ips.0.a ^ ips.1.a) & mask.a) == 0 } -extern function iptohl(addr: in_addr): bit<32> -extern function hltoip(addr: bit<32>): in_addr -extern function scan_static_dynamic_ip(s: string): Option - /* * parse IPv4 address list of the form: * "10.0.0.4 10.0.0.10 10.0.0.20..10.0.0.50 10.0.0.100..10.0.0.110" @@ -116,48 +95,79 @@ extern function parse_ip_list(ips: string): Either // In host byte order. +} -extern function ipv6_string_mapped(addr: in6_addr): string -extern function ipv6_parse_masked(s: string): Either extern function ipv6_parse(s: string): Option +extern function ipv6_parse_masked(s: string): Either extern function ipv6_parse_cidr(s: string): Either/*plen*/)> -extern function ipv6_bitxor(a: in6_addr, b: in6_addr): in6_addr -extern function ipv6_bitand(a: in6_addr, b: in6_addr): in6_addr -extern function ipv6_bitnot(a: in6_addr): in6_addr -extern function ipv6_create_mask(mask: bit<32>): in6_addr -extern function ipv6_is_zero(a: in6_addr): bool -extern function ipv6_is_routable_multicast(a: in6_addr): bool -extern function ipv6_is_all_hosts(a: in6_addr): bool -function ipv6_network(addr: in6_addr, mask: in6_addr): in6_addr { - ipv6_bitand(addr, mask) +// Return IPv6 link local address for the given 'ea'. +function to_ipv6_lla(ea: eth_addr): in6_addr { + In6Addr{(128'hfe80 << 112) | (ea.to_eui64() as u128)} +} + +// Returns IPv6 EUI64 address for 'ea' with the given 'prefix'. +function to_ipv6_eui64(ea: eth_addr, prefix: in6_addr): in6_addr { + In6Addr{(prefix.aaaa & ~128'hffffffffffffffff) | (ea.to_eui64() as u128)} +} + +function ipv6_create_mask(plen: bit<32>): in6_addr { + if (plen == 0) { + In6Addr{0} + } else { + var shift = max(0, 128 - plen); + In6Addr{128'hffffffffffffffffffffffffffffffff << shift} + } } -function ipv6_host(addr: in6_addr, mask: in6_addr): in6_addr { - ipv6_bitand(addr, ipv6_bitnot(mask)) +function is_zero(a: in6_addr): bool { a.aaaa == 0 } +function is_all_ones(a: in6_addr): bool { a.aaaa == 128'hffffffffffffffffffffffffffffffff } +function is_lla(a: in6_addr): bool { (a.aaaa >> 64) == 128'hfe80000000000000 } +function is_all_hosts(a: in6_addr): bool { a.aaaa == 128'hff020000000000000000000000000001 } +function is_cidr(netmask: in6_addr): bool { var x = ~netmask.aaaa; (x & (x + 1)) == 0 } +function is_multicast(a: in6_addr): bool { (a.aaaa >> 120) == 128'hff } +function is_routable_multicast(a: in6_addr): bool { + a.is_multicast() and match ((a.aaaa >> 112) as u8 & 8'hf) { + 0 -> false, + 1 -> false, + 2 -> false, + 3 -> false, + 15 -> false, + _ -> true + } +} + +extern function string_mapped(addr: in6_addr): string + +function network(addr: in6_addr, mask: in6_addr): in6_addr { In6Addr{addr.aaaa & mask.aaaa} } +function host(addr: in6_addr, mask: in6_addr): in6_addr { In6Addr{addr.aaaa & ~mask.aaaa} } +function solicited_node(ip6: in6_addr): in6_addr { + In6Addr{(ip6.aaaa & 128'hffffff) | 128'hff02_0000_0000_0000_0000_0001_ff00_0000} } /* True if both 'ips' are in the same network as defined by netmask 'mask', * false otherwise. */ -function ipv6_same_network(ips: (in6_addr, in6_addr), mask: in6_addr): bool { - ipv6_network(ips.0, mask) == ipv6_network(ips.1, mask) +function same_network(ips: (in6_addr, in6_addr), mask: in6_addr): bool { + ips.0.network(mask) == ips.1.network(mask) } -extern function ipv6_multicast_to_ethernet(ip6: in6_addr): eth_addr -extern function ipv6_is_cidr(ip6: in6_addr): bool -extern function ipv6_count_cidr_bits(ip6: in6_addr): Option> +function multicast_to_ethernet(ip6: in6_addr): eth_addr { + EthAddr{48'h333300000000 | (ip6.aaaa as bit<48> & 48'hffffffff)} +} -extern function inet6_ntop(addr: in6_addr): string -function to_string(addr: in6_addr): string = { - inet6_ntop(addr) +function cidr_bits(ip6: in6_addr): Option> { + if (ip6.is_cidr()) { + Some{128 - ip6.aaaa.trailing_zeros() as u8} + } else { + None + } } +function to_string(addr: in6_addr): string { inet6_ntop(addr) } +extern function inet6_ntop(addr: in6_addr): string + /* * IPv4 | IPv6 addresses */ @@ -210,70 +220,62 @@ function to_bracketed_string(ip46: v46_ip) : string = { } } -function ip46_get_network(ip46: v46_ip, plen: bit<32>) : v46_ip { +function network(ip46: v46_ip, plen: bit<32>) : v46_ip { match (ip46) { - IPv4{ipv4} -> IPv4{ip_bitand(ipv4, ip_create_mask(plen))}, - IPv6{ipv6} -> IPv6{ipv6_bitand(ipv6, ipv6_create_mask(plen))} + IPv4{ipv4} -> IPv4{InAddr{ipv4.a & ip_create_mask(plen).a}}, + IPv6{ipv6} -> IPv6{In6Addr{ipv6.aaaa & ipv6_create_mask(plen).aaaa}} } } -function ip46_is_all_ones(ip46: v46_ip) : bool { +function is_all_ones(ip46: v46_ip) : bool { match (ip46) { - IPv4{ipv4} -> ipv4 == ip_create_mask(32), - IPv6{ipv6} -> ipv6 == ipv6_create_mask(128) + IPv4{ipv4} -> ipv4.is_all_ones(), + IPv6{ipv6} -> ipv6.is_all_ones() } } -function ip46_count_cidr_bits(ip46: v46_ip) : Option> { +function cidr_bits(ip46: v46_ip) : Option> { match (ip46) { - IPv4{ipv4} -> ip_count_cidr_bits(ipv4), - IPv6{ipv6} -> ipv6_count_cidr_bits(ipv6) + IPv4{ipv4} -> ipv4.cidr_bits(), + IPv6{ipv6} -> ipv6.cidr_bits() } } -function ip46_ipX(ip46: v46_ip) : string { +function ipX(ip46: v46_ip) : string { match (ip46) { IPv4{_} -> "ip4", IPv6{_} -> "ip6" } } -function ip46_xxreg(ip46: v46_ip) : string { +function xxreg(ip46: v46_ip) : string { match (ip46) { IPv4{_} -> "", IPv6{_} -> "xx" } } +/* + * CIDR-masked IPv4 address + */ + typedef ipv4_netaddr = IPV4NetAddr { addr: in_addr, /* 192.168.10.123 */ plen: bit<32> /* CIDR Prefix: 24. */ } -/* Returns the netmask. */ -function ipv4_netaddr_mask(na: ipv4_netaddr): in_addr { - ip_create_mask(na.plen) -} - -/* Returns the broadcast address. */ -function ipv4_netaddr_bcast(na: ipv4_netaddr): in_addr { - ip_bcast(na.addr, ipv4_netaddr_mask(na)) -} - -/* Returns the network (with the host bits zeroed). */ -function ipv4_netaddr_network(na: ipv4_netaddr): in_addr { - ip_network(na.addr, ipv4_netaddr_mask(na)) -} +function netmask(na: ipv4_netaddr): in_addr { ip_create_mask(na.plen) } +function bcast(na: ipv4_netaddr): in_addr { na.addr.bcast(na.netmask()) } -/* Returns the host (with the network bits zeroed). */ -function ipv4_netaddr_host(na: ipv4_netaddr): in_addr { - ip_host(na.addr, ipv4_netaddr_mask(na)) -} +/* Returns the network (with the host bits zeroed) + * or the host (with the network bits zeroed). */ +function network(na: ipv4_netaddr): in_addr { na.addr.network(na.netmask()) } +function host(na: ipv4_netaddr): in_addr { na.addr.host(na.netmask()) } /* Match on the host, if the host part is nonzero, or on the network * otherwise. */ -function ipv4_netaddr_match_host_or_network(na: ipv4_netaddr): string { - if (na.plen < 32 and ip_is_zero(ipv4_netaddr_host(na))) { +function match_host_or_network(na: ipv4_netaddr): string { + if (na.plen < 32 and na.host().is_zero()) { "${na.addr}/${na.plen}" } else { "${na.addr}" @@ -281,51 +283,48 @@ function ipv4_netaddr_match_host_or_network(na: ipv4_netaddr): string { } /* Match on the network. */ -function ipv4_netaddr_match_network(na: ipv4_netaddr): string { +function match_network(na: ipv4_netaddr): string { if (na.plen < 32) { - "${ipv4_netaddr_network(na)}/${na.plen}" + "${na.network()}/${na.plen}" } else { "${na.addr}" } } +/* + * CIDR-masked IPv6 address + */ + typedef ipv6_netaddr = IPV6NetAddr { addr: in6_addr, /* fc00::1 */ plen: bit<32> /* CIDR Prefix: 64 */ } -/* Returns the netmask. */ -function ipv6_netaddr_mask(na: ipv6_netaddr): in6_addr { - ipv6_create_mask(na.plen) -} +function netmask(na: ipv6_netaddr): in6_addr { ipv6_create_mask(na.plen) } -/* Returns the network (with the host bits zeroed). */ -function ipv6_netaddr_network(na: ipv6_netaddr): in6_addr { - ipv6_network(na.addr, ipv6_netaddr_mask(na)) -} +/* Returns the network (with the host bits zeroed). + * or the host (with the network bits zeroed). */ +function network(na: ipv6_netaddr): in6_addr { na.addr.network(na.netmask()) } +function host(na: ipv6_netaddr): in6_addr { na.addr.host(na.netmask()) } -/* Returns the host (with the network bits zeroed). */ -function ipv6_netaddr_host(na: ipv6_netaddr): in6_addr { - ipv6_host(na.addr, ipv6_netaddr_mask(na)) -} +function solicited_node(na: ipv6_netaddr): in6_addr { na.addr.solicited_node() } -function ipv6_netaddr_solicited_node(na: ipv6_netaddr): in6_addr { - in6_addr_solicited_node(na.addr) -} - -function ipv6_netaddr_is_lla(na: ipv6_netaddr): bool { - return in6_is_lla(ipv6_netaddr_network(na)) -} +function is_lla(na: ipv6_netaddr): bool { na.network().is_lla() } /* Match on the network. */ -function ipv6_netaddr_match_network(na: ipv6_netaddr): string { +function match_network(na: ipv6_netaddr): string { if (na.plen < 128) { - "${ipv6_netaddr_network(na)}/${na.plen}" + "${na.network()}/${na.plen}" } else { "${na.addr}" } } +/* + * Set of addresses associated with a logical port. + * + * A logical port always has one Ethernet address, plus any number of IPv4 and IPv6 addresses. + */ typedef lport_addresses = LPortAddress { ea: eth_addr, ipv4_addrs: Vec, diff --git a/northd/ovn.rs b/northd/ovn.rs index c4842bdbc424..d44f83bc7557 100644 --- a/northd/ovn.rs +++ b/northd/ovn.rs @@ -59,144 +59,77 @@ const AF_INET6: usize = 10; #[repr(C)] #[derive(Default, PartialEq, Eq, PartialOrd, Ord, Clone, Hash, Serialize, Deserialize, Debug, IntoRecord, Mutator)] -pub struct eth_addr { +pub struct eth_addr_c { x: [u8; ETH_ADDR_SIZE] } -pub fn eth_addr_zero() -> eth_addr { - eth_addr { x: [0; ETH_ADDR_SIZE] } +impl eth_addr_c { + pub fn from_ddlog(d: ð_addr) -> Self { + eth_addr_c { + x: [(d.ha >> 40) as u8, + (d.ha >> 32) as u8, + (d.ha >> 24) as u8, + (d.ha >> 16) as u8, + (d.ha >> 8) as u8, + d.ha as u8] + } + } + pub fn to_ddlog(&self) -> eth_addr { + let ea0 = u16::from_be_bytes([self.x[0], self.x[1]]) as u64; + let ea1 = u16::from_be_bytes([self.x[2], self.x[3]]) as u64; + let ea2 = u16::from_be_bytes([self.x[4], self.x[5]]) as u64; + eth_addr { ha: (ea0 << 32) | (ea1 << 16) | ea2 } + } } pub fn eth_addr2string(addr: ð_addr) -> String { + let c = eth_addr_c::from_ddlog(addr); format!("{:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}", - addr.x[0], addr.x[1], addr.x[2], addr.x[3], addr.x[4], addr.x[5]) + c.x[0], c.x[1], c.x[2], c.x[3], c.x[4], c.x[5]) } pub fn eth_addr_from_string(s: &String) -> ddlog_std::Option { - let mut ea: eth_addr = Default::default(); + let mut ea: eth_addr_c = Default::default(); unsafe { - if ovs::eth_addr_from_string(string2cstr(s).as_ptr(), &mut ea as *mut eth_addr) { - ddlog_std::Option::Some{x: ea} + if ovs::eth_addr_from_string(string2cstr(s).as_ptr(), &mut ea as *mut eth_addr_c) { + ddlog_std::Option::Some{x: ea.to_ddlog()} } else { ddlog_std::Option::None } } } -pub fn eth_addr_from_uint64(x: &u64) -> eth_addr { - let mut ea: eth_addr = Default::default(); - unsafe { - ovs::eth_addr_from_uint64(*x as libc::uint64_t, &mut ea as *mut eth_addr); - ea - } -} - -pub fn eth_addr_mark_random(ea: ð_addr) -> eth_addr { - unsafe { - let mut ea_new = ea.clone(); - ovs::eth_addr_mark_random(&mut ea_new as *mut eth_addr); - ea_new - } -} - -pub fn eth_addr_to_uint64(ea: ð_addr) -> u64 { - unsafe { - ovs::eth_addr_to_uint64(ea.clone()) as u64 - } -} - - -impl FromRecord for eth_addr { - fn from_record(val: &record::Record) -> Result { - Ok(eth_addr{x: <[u8; ETH_ADDR_SIZE]>::from_record(val)?}) - } -} - #[repr(C)] -#[derive(Default, PartialEq, Eq, PartialOrd, Ord, Clone, Hash, Serialize, Deserialize, Debug, IntoRecord, Mutator)] -pub struct in6_addr { - x: [u8; IN6_ADDR_SIZE] -} - -pub const in6addr_any: in6_addr = in6_addr{x: [0; IN6_ADDR_SIZE]}; -pub const in6addr_all_hosts: in6_addr = in6_addr{x: [ - 0xff,0x02,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01 ]}; - -impl FromRecord for in6_addr { - fn from_record(val: &record::Record) -> Result { - Ok(in6_addr{x: <[u8; IN6_ADDR_SIZE]>::from_record(val)?}) - } -} - -pub fn in6_generate_lla(ea: ð_addr) -> in6_addr { - let mut addr: in6_addr = Default::default(); - unsafe {ovs::in6_generate_lla(ea.clone(), &mut addr as *mut in6_addr)}; - addr -} - -pub fn in6_generate_eui64(ea: ð_addr, prefix: &in6_addr) -> in6_addr { - let mut addr: in6_addr = Default::default(); - unsafe {ovs::in6_generate_eui64(ea.clone(), - prefix as *const in6_addr, - &mut addr as *mut in6_addr)}; - addr +struct in6_addr_c { + bytes: [u8; 16] } -pub fn in6_is_lla(addr: &in6_addr) -> bool { - unsafe {ovs::in6_is_lla(addr as *const in6_addr)} -} - -pub fn in6_addr_solicited_node(ip6: &in6_addr) -> in6_addr -{ - let mut res: in6_addr = Default::default(); - unsafe { - ovs::in6_addr_solicited_node(&mut res as *mut in6_addr, ip6 as *const in6_addr); - } - res -} - -pub fn ipv6_bitand(a: &in6_addr, b: &in6_addr) -> in6_addr { - unsafe { - ovs::ipv6_addr_bitand(a as *const in6_addr, b as *const in6_addr) +impl Default for in6_addr_c { + fn default() -> Self { + in6_addr_c { + bytes: [0; 16] + } } } -pub fn ipv6_bitxor(a: &in6_addr, b: &in6_addr) -> in6_addr { - unsafe { - ovs::ipv6_addr_bitxor(a as *const in6_addr, b as *const in6_addr) +impl in6_addr_c { + pub fn from_ddlog(d: &in6_addr) -> Self { + in6_addr_c{bytes: d.aaaa.to_be_bytes()} } -} - -pub fn ipv6_bitnot(a: &in6_addr) -> in6_addr { - let mut result: in6_addr = Default::default(); - for i in 0..16 { - result.x[i] = !a.x[i] + pub fn to_ddlog(&self) -> in6_addr { + in6_addr{aaaa: u128::from_be_bytes(self.bytes)} } - result } -pub fn ipv6_string_mapped(addr: &in6_addr) -> String { +pub fn string_mapped(addr: &in6_addr) -> String { + let addr = in6_addr_c::from_ddlog(addr); let mut addr_str = [0 as i8; INET6_ADDRSTRLEN]; unsafe { - ovs::ipv6_string_mapped(&mut addr_str[0] as *mut raw::c_char, addr as *const in6_addr); + ovs::ipv6_string_mapped(&mut addr_str[0] as *mut raw::c_char, &addr as *const in6_addr_c); cstr2string(&addr_str as *const raw::c_char) } } -pub fn ipv6_is_zero(addr: &in6_addr) -> bool { - *addr == in6addr_any -} - -pub fn ipv6_count_cidr_bits(ip6: &in6_addr) -> ddlog_std::Option { - unsafe { - match (ipv6_is_cidr(ip6)) { - true => ddlog_std::Option::Some{x: ovs::ipv6_count_cidr_bits(ip6 as *const in6_addr) as u8}, - false => ddlog_std::Option::None - } - } -} - pub fn json_string_escape(s: &String) -> String { let mut ds = ovs_ds::new(); unsafe { @@ -263,15 +196,15 @@ pub fn ovn_internal_version() -> String { pub fn ipv6_parse_masked(s: &String) -> ddlog_std::Either> { unsafe { - let mut ip: in6_addr = Default::default(); - let mut mask: in6_addr = Default::default(); - let err = ovs::ipv6_parse_masked(string2cstr(s).as_ptr(), &mut ip as *mut in6_addr, &mut mask as *mut in6_addr); + let mut ip: in6_addr_c = Default::default(); + let mut mask: in6_addr_c = Default::default(); + let err = ovs::ipv6_parse_masked(string2cstr(s).as_ptr(), &mut ip as *mut in6_addr_c, &mut mask as *mut in6_addr_c); if (err != ptr::null_mut()) { let errstr = cstr2string(err); free(err as *mut raw::c_void); ddlog_std::Either::Left{l: errstr} } else { - ddlog_std::Either::Right{r: ddlog_std::tuple2(ip, mask)} + ddlog_std::Either::Right{r: ddlog_std::tuple2(ip.to_ddlog(), mask.to_ddlog())} } } } @@ -279,15 +212,15 @@ pub fn ipv6_parse_masked(s: &String) -> ddlog_std::Either ddlog_std::Either> { unsafe { - let mut ip: in6_addr = Default::default(); + let mut ip: in6_addr_c = Default::default(); let mut plen: raw::c_uint = 0; - let err = ovs::ipv6_parse_cidr(string2cstr(s).as_ptr(), &mut ip as *mut in6_addr, &mut plen as *mut raw::c_uint); + let err = ovs::ipv6_parse_cidr(string2cstr(s).as_ptr(), &mut ip as *mut in6_addr_c, &mut plen as *mut raw::c_uint); if (err != ptr::null_mut()) { let errstr = cstr2string(err); free(err as *mut raw::c_void); ddlog_std::Either::Left{l: errstr} } else { - ddlog_std::Either::Right{r: ddlog_std::tuple2(ip, plen as u32)} + ddlog_std::Either::Right{r: ddlog_std::tuple2(ip.to_ddlog(), plen as u32)} } } } @@ -295,54 +228,25 @@ pub fn ipv6_parse_cidr(s: &String) -> ddlog_std::Either ddlog_std::Option { unsafe { - let mut ip: in6_addr = Default::default(); - let res = ovs::ipv6_parse(string2cstr(s).as_ptr(), &mut ip as *mut in6_addr); + let mut ip: in6_addr_c = Default::default(); + let res = ovs::ipv6_parse(string2cstr(s).as_ptr(), &mut ip as *mut in6_addr_c); if (res) { - ddlog_std::Option::Some{x: ip} + ddlog_std::Option::Some{x: ip.to_ddlog()} } else { ddlog_std::Option::None } } } -pub fn ipv6_create_mask(mask: &u32) -> in6_addr -{ - unsafe {ovs::ipv6_create_mask(*mask as raw::c_uint)} -} - - -pub fn ipv6_is_routable_multicast(a: &in6_addr) -> bool -{ - unsafe{ovn_c::ipv6_addr_is_routable_multicast(a as *const in6_addr)} -} - -pub fn ipv6_is_all_hosts(a: &in6_addr) -> bool -{ - return *a == in6addr_all_hosts; -} - -pub fn ipv6_is_cidr(a: &in6_addr) -> bool -{ - unsafe{ovs::ipv6_is_cidr(a as *const in6_addr)} -} - -pub fn ipv6_multicast_to_ethernet(ip6: &in6_addr) -> eth_addr -{ - let mut eth: eth_addr = Default::default(); - unsafe{ - ovs::ipv6_multicast_to_ethernet(&mut eth as *mut eth_addr, ip6 as *const in6_addr); - } - eth -} - -pub type in_addr = u32; pub type ovs_be32 = u32; -pub fn iptohl(addr: &in_addr) -> u32 { - ddlog_std::ntohl(addr) -} -pub fn hltoip(addr: &u32) -> in_addr { - ddlog_std::htonl(addr) +impl in_addr { + pub fn from_be32(nl: ovs_be32) -> in_addr { + in_addr{a: ddlog_std::ntohl(&nl)} + } + pub fn to_be32(&self) -> ovs_be32 { + ddlog_std::htonl(&self.a) + } } pub fn ip_parse_masked(s: &String) -> ddlog_std::Either> @@ -356,7 +260,8 @@ pub fn ip_parse_masked(s: &String) -> ddlog_std::Either ddlog_std::Either ddlog_std::Option unsafe { let mut ip: ovs_be32 = 0; if (ovs::ip_parse(string2cstr(s).as_ptr(), &mut ip as *mut ovs_be32)) { - ddlog_std::Option::Some{x:ip} + ddlog_std::Option::Some{x: in_addr::from_be32(ip)} } else { ddlog_std::Option::None } } } -pub fn ip_count_cidr_bits(address: &in_addr) -> ddlog_std::Option { - unsafe { - match (ip_is_cidr(address)) { - true => ddlog_std::Option::Some{x: ovs::ip_count_cidr_bits(*address) as u8}, - false => ddlog_std::Option::None - } - } -} - pub fn is_dynamic_lsp_address(address: &String) -> bool { unsafe { ovn_c::is_dynamic_lsp_address(string2cstr(address).as_ptr()) @@ -414,21 +310,21 @@ pub fn split_addresses(addresses: &String) -> ddlog_std::tuple2 ddlog_std::Option { - let mut ea = eth_addr_zero(); + let mut ea: eth_addr_c = Default::default(); unsafe { if ovs::ovs_scan(string2cstr(s).as_ptr(), b"%hhx:%hhx:%hhx:%hhx:%hhx:%hhx\0".as_ptr() as *const raw::c_char, &mut ea.x[0] as *mut u8, &mut ea.x[1] as *mut u8, &mut ea.x[2] as *mut u8, &mut ea.x[3] as *mut u8, &mut ea.x[4] as *mut u8, &mut ea.x[5] as *mut u8) { - ddlog_std::Option::Some{x: ea} + ddlog_std::Option::Some{x: ea.to_ddlog()} } else { ddlog_std::Option::None } } } -pub fn scan_eth_addr_prefix(s: &String) -> ddlog_std::Option { +pub fn scan_eth_addr_prefix(s: &String) -> ddlog_std::Option { let mut b2: u8 = 0; let mut b1: u8 = 0; let mut b0: u8 = 0; @@ -436,7 +332,7 @@ pub fn scan_eth_addr_prefix(s: &String) -> ddlog_std::Option { if ovs::ovs_scan(string2cstr(s).as_ptr(), b"%hhx:%hhx:%hhx\0".as_ptr() as *const raw::c_char, &mut b2 as *mut u8, &mut b1 as *mut u8, &mut b0 as *mut u8) { - ddlog_std::Option::Some{x: ((b2 as u64) << 40) | ((b1 as u64) << 32) | ((b0 as u64) << 24) } + ddlog_std::Option::Some{x: eth_addr{ha: ((b2 as u64) << 40) | ((b1 as u64) << 32) | ((b0 as u64) << 24)} } } else { ddlog_std::Option::None } @@ -457,7 +353,11 @@ pub fn scan_static_dynamic_ip(s: &String) -> ddlog_std::Option { &mut ip3 as *mut u8, &mut n) && s.len() == (n as usize) { - ddlog_std::Option::Some{x: ddlog_std::htonl(&(((ip0 as u32) << 24) | ((ip1 as u32) << 16) | ((ip2 as u32) << 8) | (ip3 as u32)))} + let a0 = (ip0 as u32) << 24; + let a1 = (ip1 as u32) << 16; + let a2 = (ip2 as u32) << 8; + let a3 = ip3 as u32; + ddlog_std::Option::Some{x: in_addr{a: a0 | a1 | a2 | a3}} } else { ddlog_std::Option::None } @@ -513,9 +413,10 @@ pub fn str_to_uint(s: &String, base: &u16) -> ddlog_std::Option { } pub fn inet6_ntop(addr: &in6_addr) -> String { + let addr_c = in6_addr_c::from_ddlog(addr); let mut buf = [0 as i8; INET6_ADDRSTRLEN]; unsafe { - let res = inet_ntop(AF_INET6 as raw::c_int, addr as *const in6_addr as *const raw::c_void, + let res = inet_ntop(AF_INET6 as raw::c_int, &addr_c as *const in6_addr_c as *const raw::c_void, &mut buf[0] as *mut raw::c_char, INET6_ADDRSTRLEN as libc::socklen_t); if res == ptr::null() { warn(&format!("inet_ntop({:?}) failed", *addr)); @@ -611,9 +512,9 @@ impl Default for ipv4_netaddr_c { } impl ipv4_netaddr_c { - pub unsafe fn to_ddlog(&self) -> ipv4_netaddr { + pub fn to_ddlog(&self) -> ipv4_netaddr { ipv4_netaddr{ - addr: self.addr, + addr: in_addr::from_be32(self.addr), plen: self.plen, } } @@ -621,10 +522,10 @@ impl ipv4_netaddr_c { #[repr(C)] struct ipv6_netaddr_c { - addr: in6_addr, /* fc00::1 */ - mask: in6_addr, /* ffff:ffff:ffff:ffff:: */ - sn_addr: in6_addr, /* ff02:1:ff00::1 */ - network: in6_addr, /* fc00:: */ + addr: in6_addr_c, /* fc00::1 */ + mask: in6_addr_c, /* ffff:ffff:ffff:ffff:: */ + sn_addr: in6_addr_c, /* ff02:1:ff00::1 */ + network: in6_addr_c, /* fc00:: */ plen: raw::c_uint, /* CIDR Prefix: 64 */ addr_s: [raw::c_char; INET6_ADDRSTRLEN + 1], /* "fc00::1" */ @@ -650,7 +551,7 @@ impl Default for ipv6_netaddr_c { impl ipv6_netaddr_c { pub unsafe fn to_ddlog(&self) -> ipv6_netaddr { ipv6_netaddr{ - addr: self.addr.clone(), + addr: in6_addr_c::to_ddlog(&self.addr), plen: self.plen } } @@ -661,7 +562,7 @@ impl ipv6_netaddr_c { #[repr(C)] struct lport_addresses_c { ea_s: [raw::c_char; ETH_ADDR_STRLEN + 1], - ea: eth_addr, + ea: eth_addr_c, n_ipv4_addrs: libc::size_t, ipv4_addrs: *mut ipv4_netaddr_c, n_ipv6_addrs: libc::size_t, @@ -692,7 +593,7 @@ impl lport_addresses_c { ipv6_addrs.push((&*self.ipv6_addrs.offset(i as isize)).to_ddlog()) } let res = lport_addresses { - ea: self.ea.clone(), + ea: self.ea.to_ddlog(), ipv4_addrs: ipv4_addrs, ipv6_addrs: ipv6_addrs }; @@ -713,7 +614,7 @@ mod ovn_c { use ::libc; use super::lport_addresses_c; use super::ovs_svec; - use super::in6_addr; + use super::in6_addr_c; #[link(name = "ovn")] extern "C" { @@ -727,7 +628,6 @@ mod ovn_c { pub fn split_addresses(addresses: *const raw::c_char, ip4_addrs: *mut ovs_svec, ipv6_addrs: *mut ovs_svec); pub fn ip_address_and_port_from_lb_key(key: *const raw::c_char, ip_address: *mut *mut raw::c_char, port: *mut libc::uint16_t, addr_family: *mut raw::c_int); - pub fn ipv6_addr_is_routable_multicast(ip: *const in6_addr) -> bool; pub fn ovn_get_internal_version() -> *mut raw::c_char; } } @@ -735,40 +635,24 @@ mod ovn_c { mod ovs { use ::std::os::raw; use ::libc; - use super::in6_addr; + use super::in6_addr_c; use super::ovs_be32; use super::ovs_ds; - use super::eth_addr; + use super::eth_addr_c; use super::ovs_svec; /* functions imported from libopenvswitch */ #[link(name = "openvswitch")] extern "C" { // lib/packets.h - pub fn ipv6_string_mapped(addr_str: *mut raw::c_char, addr: *const in6_addr) -> *const raw::c_char; - pub fn ipv6_parse_masked(s: *const raw::c_char, ip: *mut in6_addr, mask: *mut in6_addr) -> *mut raw::c_char; - pub fn ipv6_parse_cidr(s: *const raw::c_char, ip: *mut in6_addr, plen: *mut raw::c_uint) -> *mut raw::c_char; - pub fn ipv6_parse(s: *const raw::c_char, ip: *mut in6_addr) -> bool; - pub fn ipv6_mask_is_any(mask: *const in6_addr) -> bool; - pub fn ipv6_count_cidr_bits(mask: *const in6_addr) -> raw::c_int; - pub fn ipv6_is_cidr(mask: *const in6_addr) -> bool; - pub fn ipv6_addr_bitxor(a: *const in6_addr, b: *const in6_addr) -> in6_addr; - pub fn ipv6_addr_bitand(a: *const in6_addr, b: *const in6_addr) -> in6_addr; - pub fn ipv6_create_mask(mask: raw::c_uint) -> in6_addr; - pub fn ipv6_is_zero(a: *const in6_addr) -> bool; - pub fn ipv6_multicast_to_ethernet(eth: *mut eth_addr, ip6: *const in6_addr); + pub fn ipv6_string_mapped(addr_str: *mut raw::c_char, addr: *const in6_addr_c) -> *const raw::c_char; + pub fn ipv6_parse_masked(s: *const raw::c_char, ip: *mut in6_addr_c, mask: *mut in6_addr_c) -> *mut raw::c_char; + pub fn ipv6_parse_cidr(s: *const raw::c_char, ip: *mut in6_addr_c, plen: *mut raw::c_uint) -> *mut raw::c_char; + pub fn ipv6_parse(s: *const raw::c_char, ip: *mut in6_addr_c) -> bool; pub fn ip_parse_masked(s: *const raw::c_char, ip: *mut ovs_be32, mask: *mut ovs_be32) -> *mut raw::c_char; pub fn ip_parse_cidr(s: *const raw::c_char, ip: *mut ovs_be32, plen: *mut raw::c_uint) -> *mut raw::c_char; pub fn ip_parse(s: *const raw::c_char, ip: *mut ovs_be32) -> bool; - pub fn ip_count_cidr_bits(mask: ovs_be32) -> raw::c_int; - pub fn eth_addr_from_string(s: *const raw::c_char, ea: *mut eth_addr) -> bool; - pub fn eth_addr_to_uint64(ea: eth_addr) -> libc::uint64_t; - pub fn eth_addr_from_uint64(x: libc::uint64_t, ea: *mut eth_addr); - pub fn eth_addr_mark_random(ea: *mut eth_addr); - pub fn in6_generate_eui64(ea: eth_addr, prefix: *const in6_addr, lla: *mut in6_addr); - pub fn in6_generate_lla(ea: eth_addr, lla: *mut in6_addr); - pub fn in6_is_lla(addr: *const in6_addr) -> bool; - pub fn in6_addr_solicited_node(addr: *mut in6_addr, ip6: *const in6_addr); + pub fn eth_addr_from_string(s: *const raw::c_char, ea: *mut eth_addr_c) -> bool; // include/openvswitch/json.h pub fn json_string_escape(str: *const raw::c_char, out: *mut ovs_ds); diff --git a/northd/ovn_northd.dl b/northd/ovn_northd.dl index 4b4775a9d3bf..13bbe17c81da 100644 --- a/northd/ovn_northd.dl +++ b/northd/ovn_northd.dl @@ -1731,14 +1731,14 @@ function build_port_security_ipv6_flow( var ip6_addrs = vec_empty(); /* Allow link-local address. */ - ip6_addrs.push(ipv6_string_mapped(in6_generate_lla(ea))); + ip6_addrs.push(ea.to_ipv6_lla().string_mapped()); /* Allow ip6.dst=ff00::/8 for multicast packets */ if (pipeline == Egress) { ip6_addrs.push("ff00::/8") }; for (addr in ipv6_addrs) { - ip6_addrs.push(ipv6_netaddr_match_network(addr)) + ip6_addrs.push(addr.match_network()) }; var dir = if (pipeline == Ingress) { "src" } else { "dst" }; @@ -1755,12 +1755,10 @@ function build_port_security_ipv6_nd_flow( if (ipv6_addrs.is_empty()) { __match ++ "))" } else { - var ip6_str = ipv6_string_mapped(in6_generate_lla(ea)); - __match = __match ++ " && (nd.target == ${ip6_str}"; + __match = __match ++ " && (nd.target == ${ea.to_ipv6_lla()}"; for(addr in ipv6_addrs) { - ip6_str = ipv6_netaddr_match_network(addr); - __match = __match ++ " || nd.target == ${ip6_str}" + __match = __match ++ " || nd.target == ${addr.match_network()}" }; __match ++ ")))" } @@ -1984,7 +1982,7 @@ function build_empty_lb_event_flow(key: string, lb: Ref, }; var __match = vec_with_capacity(2); - __match.push("${ip46_ipX(ip)}.dst == ${ip}"); + __match.push("${ip.ipX()}.dst == ${ip}"); if (port != 0) { __match.push("${protocol}.dst == ${port}"); }; @@ -2604,7 +2602,7 @@ for (SwitchPortDHCPv6Options(.port = &SwitchPort{.lsp = lsp, .sw = &sw}, if lsp.__type != "external") { Some{var server_mac} = options.get("server_id") in Some{var ea} = eth_addr_from_string(server_mac) in - var server_ip = ipv6_string_mapped(in6_generate_lla(ea)) in + var server_ip = ea.to_ipv6_lla() in /* Get the link local IP of the DHCPv6 server from the * server MAC. */ var has_stateful = sw.has_stateful_acl or sw.has_lb_vip in @@ -3070,7 +3068,7 @@ for (SwitchPortPSAddresses(.port = &port@SwitchPort{.sw = &sw}, .ps_addrs = ps) * address. If zero, the host is allowed to use any * address in the subnet. */ - addrs.push(ipv4_netaddr_match_host_or_network(addr)) + addrs.push(addr.match_host_or_network()) }; addrs } in @@ -3154,7 +3152,7 @@ for (SwitchPortPSAddresses(.port = &port@SwitchPort{.sw = &sw}, .ps_addrs = ps) if (not ps.ipv4_addrs.is_empty()) { var spas = vec_empty(); for (addr in ps.ipv4_addrs) { - spas.push(ipv4_netaddr_match_host_or_network(addr)) + spas.push(addr.match_host_or_network()) }; prefix ++ " && arp.spa == {${spas.join(\", \")}}" } else { @@ -3316,7 +3314,7 @@ for (SwitchPortIPv6Address(.port = &SwitchPort{.lsp = lsp, .json_name = json_nam (lsp_is_up(lsp) or lsp.__type == "router" or lsp.__type == "localport") and lsp.__type != "external" and lsp.__type != "virtual") { - var __match = "nd_ns && ip6.dst == {${addr.addr}, ${ipv6_netaddr_solicited_node(addr)}} && nd.target == ${addr.addr}" in + var __match = "nd_ns && ip6.dst == {${addr.addr}, ${addr.solicited_node()}} && nd.target == ${addr.addr}" in var actions = "${if (lsp.__type == \"router\") \"nd_na_router\" else \"nd_na\"} { " "eth.src = ${ea}; " "ip6.src = ${addr.addr}; " @@ -3392,7 +3390,7 @@ function build_dhcpv4_action( None }, Right{(var host_ip, var mask)} -> { - if (not ip_same_network((offer_ip, host_ip), mask)) { + if (not (offer_ip, host_ip).same_network(mask)) { /* the offer ip of the logical port doesn't belong to the cidr * defined in the DHCPv4 options. */ @@ -3451,7 +3449,7 @@ function build_dhcpv6_action( None }, Right{(var host_ip, var mask)} -> { - if (not ipv6_same_network((offer_ip, host_ip), mask)) { + if (not (offer_ip, host_ip).same_network(mask)) { /* offer_ip doesn't belongs to the cidr defined in lport's DHCPv6 * options.*/ //warn("ip does not belong to cidr"); @@ -3471,8 +3469,8 @@ function build_dhcpv6_action( }, Some{ea} -> { /* Get the link local IP of the DHCPv6 server from the server MAC. */ - var server_ip = ipv6_string_mapped(in6_generate_lla(ea)); - var ia_addr = ipv6_string_mapped(offer_ip); + var server_ip = ea.to_ipv6_lla().string_mapped(); + var ia_addr = offer_ip.string_mapped(); var options = vec_empty(); /* Check whether the dhcpv6 options should be configured as stateful. @@ -3862,10 +3860,10 @@ for (IgmpSwitchMulticastGroup(.address = address, .switch = &sw)) { */ Some{var ip} = ip46_parse(address) in (var skip_address) = match (ip) { - IPv4{ipv4} -> ip_is_local_multicast(ipv4), - IPv6{ipv6} -> ipv6_is_all_hosts(ipv6) + IPv4{ipv4} -> ipv4.is_local_multicast(), + IPv6{ipv6} -> ipv6.is_all_hosts() } in - var ipX = ip46_ipX(ip) in + var ipX = ip.ipX() in for (SwitchMcastFloodRelayPorts(&sw, relay_ports) if not skip_address) { for (SwitchMcastFloodPorts(&sw, flood_ports)) { var flood_relay = not relay_ports.is_empty() in @@ -3933,7 +3931,7 @@ Flow(.logical_datapath = sp.sw.ls._uuid, .__match = ("inport == ${json_string_escape(localnet_port.1)} && " "eth.src == ${lp_addr.ea} && " "!is_chassis_resident(${sp.json_name}) && " - "nd_ns && ip6.dst == {${rp_addr.addr}, ${ipv6_netaddr_solicited_node(rp_addr)}} && " + "nd_ns && ip6.dst == {${rp_addr.addr}, ${rp_addr.solicited_node()}} && " "nd.target == ${rp_addr.addr}"), .actions = "drop;", .external_ids = stage_hint(sp.lsp._uuid)) :- @@ -4004,14 +4002,14 @@ function lrouter_port_ip_reachable(rp: Ref, addr: v46_ip): bool { match (addr) { IPv4{ipv4} -> { for (na in rp.networks.ipv4_addrs) { - if (ip_same_network((ipv4, na.addr), ipv4_netaddr_mask(na))) { + if ((ipv4, na.addr).same_network(na.netmask())) { return true } } }, IPv6{ipv6} -> { for (na in rp.networks.ipv6_addrs) { - if (ipv6_same_network((ipv6, na.addr), ipv6_netaddr_mask(na))) { + if ((ipv6, na.addr).same_network(na.netmask())) { return true } } @@ -4356,9 +4354,9 @@ for (SwitchPortPSAddresses(.port = &SwitchPort{.lsp = lsp, .json_name = json_nam * address. If zero, the host is allowed to use any * address in the subnet. */ - addrs.push(ipv4_netaddr_match_host_or_network(addr)); - if (addr.plen < 32 and not ip_is_zero(ipv4_netaddr_host(addr))) { - addrs.push("${ipv4_netaddr_bcast(addr)}") + addrs.push(addr.match_host_or_network()); + if (addr.plen < 32 and not addr.host().is_zero()) { + addrs.push("${addr.bcast()}") } }; addrs @@ -4578,7 +4576,7 @@ for (RouterPortNetworksIPv4Addr(rp@&RouterPort{.router = router}, addr)) { var rLNR = rEGBIT_LOOKUP_NEIGHBOR_RESULT() in var rLNIR = rEGBIT_LOOKUP_NEIGHBOR_IP_RESULT() in var match0 = "inport == ${rp.json_name} && " - "arp.spa == ${ipv4_netaddr_match_network(addr)}" in + "arp.spa == ${addr.match_network()}" in var match1 = "arp.op == 1" ++ chassis_residence in var learn_from_arp_request = router.learn_from_arp_request in { if (not learn_from_arp_request) { @@ -4701,7 +4699,7 @@ function format_v4_networks(networks: lport_addresses, add_bcast: bool): string for (addr in networks.ipv4_addrs) { addrs.push("${addr.addr}"); if (add_bcast) { - addrs.push("${ipv4_netaddr_bcast(addr)}") + addrs.push("${addr.bcast()}") } else () }; if (addrs.len() == 1) { @@ -4971,7 +4969,7 @@ Flow(.logical_datapath = lr.lr._uuid, None -> () }; if (sn_ip) { - clauses.push("ip6.dst == {${ip}, ${in6_addr_solicited_node(ip)}}") + clauses.push("ip6.dst == {${ip}, ${ip.solicited_node()}}") }; clauses.push("nd_ns && nd.target == ${ip}"); clauses.append(extra_match.to_vec()); @@ -5018,7 +5016,7 @@ for (RouterPortNetworksIPv4Addr(.port = &RouterPort{.lrp = lrp, * IP address. */ for (AddChassisResidentCheck(lrp._uuid, add_chassis_resident_check)) { var __match = - "arp.spa == ${ipv4_netaddr_match_network(addr)}" ++ + "arp.spa == ${addr.match_network()}" ++ if (add_chassis_resident_check) { " && is_chassis_resident(${router.redirect_port_name})" } else "" in @@ -5295,10 +5293,10 @@ for (RouterPortNetworksIPv6Addr(.port = &RouterPort{.router = &router, .json_name = json_name}, .addr = addr) /* skip link-local address */ - if (not ipv6_netaddr_is_lla(addr))) + if (not addr.is_lla())) { var __match = "inport == ${json_name} && ip6 && " - "ip6.src == ${ipv6_netaddr_match_network(addr)} && " + "ip6.src == ${addr.match_network()} && " "ip.ttl == {0, 1} && !ip.later_frag" in var actions = "icmp6 {" "eth.dst <-> eth.src; " @@ -5396,7 +5394,7 @@ function lrouter_nat_add_ext_ip_match( false -> { /* S_ROUTER_OUT_SNAT uses priority (mask + 1 + 128 + 1) */ var is_gw_router = router.l3dgw_port == None; - var mask_1bits = ip46_count_cidr_bits(mask).unwrap_or(8'd0) as integer; + var mask_1bits = mask.cidr_bits().unwrap_or(8'd0) as integer; mask_1bits + 2 + { if (not is_gw_router) 128 else 0 } } }; @@ -5435,7 +5433,7 @@ Flow(.logical_datapath = logical_router, .ips = ips, .context = context), var ip = FlatMap(ips), - var ipX = ip46_ipX(ip). + var ipX = ip.ipX(). /* Higher priority rules to force SNAT with the router port ip. * This only takes effect when the packet has already been @@ -5488,12 +5486,12 @@ for (r in &Router(.lr = lr, if l3dgw_port.is_some() or is_gateway) { for (LogicalRouterNAT(.lr = lr._uuid, .nat = nat)) { - var ipX = ip46_ipX(nat.external_ip) in - var xx = ip46_xxreg(nat.external_ip) in + var ipX = nat.external_ip.ipX() in + var xx = nat.external_ip.xxreg() in /* Check the validity of nat->logical_ip. 'logical_ip' can * be a subnet when the type is "snat". */ Some{(_, var mask)} = ip46_parse_masked(nat.nat.logical_ip) in - true == match ((ip46_is_all_ones(mask), nat.nat.__type)) { + true == match ((mask.is_all_ones(), nat.nat.__type)) { (_, "snat") -> true, (false, _) -> { warn("bad ip ${nat.nat.logical_ip} for dnat in router ${uuid2str(lr._uuid)}"); @@ -5725,7 +5723,7 @@ for (r in &Router(.lr = lr, } else { "ct_snat(${ip_and_ports});" } in - Some{var plen} = ip46_count_cidr_bits(mask) in + Some{var plen} = mask.cidr_bits() in Flow(.logical_datapath = lr._uuid, .stage = s_ROUTER_OUT_SNAT(), .priority = plen as bit<64> + 1, @@ -5761,7 +5759,7 @@ for (r in &Router(.lr = lr, /* The priority here is calculated such that the * nat->logical_ip with the longest mask gets a higher * priority. */ - Some{var plen} = ip46_count_cidr_bits(mask) in + Some{var plen} = mask.cidr_bits() in var priority = (plen as bit<64>) + 1 in var centralized_boost = if (mac == None) 128 else 0 in Flow(.logical_datapath = lr._uuid, @@ -5934,7 +5932,7 @@ for (RouterLBVIP( /* vip contains IP:port or just IP. */ Some{(var ip_address, var port)} = ip_address_and_port_from_lb_key(vip) in - var ipX = ip46_ipX(ip_address) in + var ipX = ip_address.ipX() in var proto = match (lb.protocol) { Some{proto} -> proto, _ -> "tcp" @@ -6038,7 +6036,7 @@ for (RouterLBVIP( } in not conds.is_empty() in var undnat_match = - "${ip46_ipX(ip_address)} && (" ++ conds.join(" || ") ++ + "${ip_address.ipX()} && (" ++ conds.join(" || ") ++ ") && outport == ${json_string_escape(gwport.name)} && " "is_chassis_resident(${redirect_port_name})" in var action = @@ -6123,11 +6121,11 @@ function copy_ra_to_sb(port: RouterPort, address_mode: string): Map) = { - var ipX = ip46_ipX(key.ip_prefix); + var ipX = key.ip_prefix.ipX(); /* The priority here is calculated to implement longest-prefix-match * routing. */ @@ -6284,7 +6282,7 @@ function build_route_match(key: route_key) : (string, bit<32>) = DstIp -> ("dst", (key.plen * 2) + 1) }; - var network = ip46_get_network(key.ip_prefix, key.plen); + var network = key.ip_prefix.network(key.plen); var __match = "${ipX}.${dir} == ${network}/${key.plen}"; (__match, priority) @@ -6294,11 +6292,11 @@ for (Route(.port = port, .src_ip = src_ip, .gateway = gateway)) { - var ipX = ip46_ipX(key.ip_prefix) in - var xx = ip46_xxreg(key.ip_prefix) in + var ipX = key.ip_prefix.ipX() in + var xx = key.ip_prefix.xxreg() in /* IPv6 link-local addresses must be scoped to the local router port. */ var inport_match = match (key.ip_prefix) { - IPv6{prefix} -> if (in6_is_lla(prefix)) { + IPv6{prefix} -> if (prefix.is_lla()) { "inport == ${port.json_name} && " } else "", _ -> "" @@ -6432,7 +6430,7 @@ Flow(.logical_datapath = router.lr._uuid, EcmpGroup(group_id, router, key, dsts, _, _), var member_id_and_dst = FlatMap(numbered_vec(dsts)), (var member_id, var dst) = member_id_and_dst, - var xx = ip46_xxreg(dst.nexthop), + var xx = dst.nexthop.xxreg(), var __match = "${rEG_ECMP_GROUP_ID()} == ${group_id} && " "${rEG_ECMP_MEMBER_ID()} == ${member_id}", var actions = "${xx}${rEG_NEXT_HOP()} = ${dst.nexthop}; " @@ -6512,7 +6510,7 @@ Flow(.logical_datapath = router.lr._uuid, .external_ids = map_empty()) :- EcmpSymmetricReply(router, dst, route_match, tunkey), var ecmp_reply = "ct.rpl && ct_label.ecmp_reply_port == ${tunkey}", - var xx = ip46_xxreg(dst.nexthop). + var xx = dst.nexthop.xxreg(). /* IP Multicast lookup. Here we set the output port, adjust TTL and advance @@ -6545,7 +6543,7 @@ for (IgmpRouterMulticastGroup(address, &rtr, ports)) { } } in Some{var ip} = ip46_parse(address) in - var ipX = ip46_ipX(ip) in + var ipX = ip.ipX() in UniqueFlow[Flow{.logical_datapath = rtr.lr._uuid, .stage = s_ROUTER_IN_IP_ROUTING(), .priority = 500, @@ -6646,7 +6644,7 @@ Flow(.logical_datapath = r.lr._uuid, " priority %"PRId64" nexthop %s", rule->priority, rule->nexthop); */ - var xx = ip46_xxreg(src_ip), + var xx = src_ip.xxreg(), var actions = (pkt_mark_policy(policy.options) ++ "${xx}${rEG_NEXT_HOP()} = ${nexthop}; " "${xx}${rEG_SRC()} = ${src_ip}; " @@ -6697,7 +6695,7 @@ Flow(.logical_datapath = r.lr._uuid, Some{var nexthop} = ip46_parse(nexthop_s), out_port in &RouterPort(.router = r), Some{var src_ip} = find_lrp_member_ip(out_port.networks, nexthop), // or warn - var xx = ip46_xxreg(src_ip), + var xx = src_ip.xxreg(), var actions = (pkt_mark_policy(policy.options) ++ "${xx}${rEG_NEXT_HOP()} = ${nexthop}; " "${xx}${rEG_SRC()} = ${src_ip}; " @@ -7161,9 +7159,9 @@ Flow(.logical_datapath = router.lr._uuid, IPv6{var gw_ip6} = dst.nexthop, var __match = "eth.dst == 00:00:00:00:00:00 && " "ip6 && xx${rEG_NEXT_HOP()} == ${dst.nexthop}", - var sn_addr = in6_addr_solicited_node(gw_ip6), - var eth_dst = ipv6_multicast_to_ethernet(sn_addr), - var sn_addr_s = ipv6_string_mapped(sn_addr), + var sn_addr = gw_ip6.solicited_node(), + var eth_dst = sn_addr.multicast_to_ethernet(), + var sn_addr_s = sn_addr.string_mapped(), var actions = "nd_ns { " "eth.dst = ${eth_dst}; " "ip6.dst = ${sn_addr_s}; " From patchwork Thu Mar 4 04:10:09 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ben Pfaff X-Patchwork-Id: 1447083 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.137; helo=smtp4.osuosl.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Received: from smtp4.osuosl.org (smtp4.osuosl.org [140.211.166.137]) (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 4DrcqH6c5Zz9sRf for ; Thu, 4 Mar 2021 15:10:51 +1100 (AEDT) Received: from localhost (localhost [127.0.0.1]) by smtp4.osuosl.org (Postfix) with ESMTP id C11FF4EBC9; Thu, 4 Mar 2021 04:10:49 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org 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 5RtSUm1fVJdX; Thu, 4 Mar 2021 04:10:48 +0000 (UTC) Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56]) by smtp4.osuosl.org (Postfix) with ESMTP id 1F5164EBD9; Thu, 4 Mar 2021 04:10:47 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id E6BCAC0011; Thu, 4 Mar 2021 04:10:46 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@lists.linuxfoundation.org Received: from smtp1.osuosl.org (smtp1.osuosl.org [140.211.166.138]) by lists.linuxfoundation.org (Postfix) with ESMTP id 12AF9C0010 for ; Thu, 4 Mar 2021 04:10:45 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by smtp1.osuosl.org (Postfix) with ESMTP id A4F2B842A9 for ; Thu, 4 Mar 2021 04:10:33 +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 E2INJRPVc2OT for ; Thu, 4 Mar 2021 04:10:32 +0000 (UTC) X-Greylist: domain auto-whitelisted by SQLgrey-1.8.0 Received: from relay9-d.mail.gandi.net (relay9-d.mail.gandi.net [217.70.183.199]) by smtp1.osuosl.org (Postfix) with ESMTPS id 4019584340 for ; Thu, 4 Mar 2021 04:10:31 +0000 (UTC) X-Originating-IP: 75.54.222.30 Received: from sigfpe.attlocal.net (75-54-222-30.lightspeed.rdcyca.sbcglobal.net [75.54.222.30]) (Authenticated sender: blp@ovn.org) by relay9-d.mail.gandi.net (Postfix) with ESMTPSA id 3156DFF806; Thu, 4 Mar 2021 04:10:28 +0000 (UTC) From: Ben Pfaff To: dev@openvswitch.org Date: Wed, 3 Mar 2021 20:10:09 -0800 Message-Id: <20210304041012.4128938-9-blp@ovn.org> X-Mailer: git-send-email 2.29.2 In-Reply-To: <20210304041012.4128938-1-blp@ovn.org> References: <20210304041012.4128938-1-blp@ovn.org> MIME-Version: 1.0 Cc: Mihai Budiu , Leonid Ryhzyk , Ben Pfaff Subject: [ovs-dev] [PATCH ovn 08/11] ovn-northd-ddlog: Avoid N*M crossproduct joining switches with routers. 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" DDlog takes a literalist view of joins, executing them in the order that are written without attempting much in the way of reordering or optimization. The FirstHopLogicalRouter rule as written here joined LogicalRouterPort with LogicalSwitchPort without using any join key, and then later eliminated some of the possibilities. This meant that if there were N router ports and M switch ports, DDlog actually considered all N*M possibilities, which is expensive. This commit improves the big-O of the situation by introducing an intermediate table that contains only the switch port that connect to router ports and by giving that table a column that can be used as a join key. This allows DDlog to join them efficiently. (The new column is needed because DDlog cannot join on a member of a map directly.) Found via the DDlog profiling feature: https://github.com/vmware/differential-datalog/blob/master/doc/tutorial/tutorial.md#Profiling Suggested-by: Mihai Budiu Suggested-by: Leonid Ryhzyk Signed-off-by: Ben Pfaff --- northd/lrouter.dl | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/northd/lrouter.dl b/northd/lrouter.dl index 7786ef137fc6..4c5cf321509e 100644 --- a/northd/lrouter.dl +++ b/northd/lrouter.dl @@ -86,12 +86,14 @@ PeerLogicalRouter(lrp_uuid, peer._uuid) :- relation FirstHopLogicalRouter(lrouter: uuid, lswitch: uuid) FirstHopLogicalRouter(lrouter, lswitch) :- LogicalRouterPort(lrp_uuid, lrouter), - lrp in nb::Logical_Router_Port(._uuid = lrp_uuid), - LogicalSwitchPort(lsp_uuid, lswitch), - lsp in nb::Logical_Switch_Port(._uuid = lsp_uuid), - lsp.__type == "router", - lsp.options.get("router-port") == Some{lrp.name}, - lrp.peer == None. + lrp in nb::Logical_Router_Port(._uuid = lrp_uuid, .peer = None), + LogicalSwitchRouterPort(lsp_uuid, lrp.name, lswitch). + +relation LogicalSwitchRouterPort(lsp: uuid, lsp_router_port: string, ls: uuid) +LogicalSwitchRouterPort(lsp, lsp_router_port, ls) :- + LogicalSwitchPort(lsp, ls), + nb::Logical_Switch_Port(._uuid = lsp, .__type = "router", .options = options), + Some{var lsp_router_port} = options.get("router-port"). /* * Reachable routers. From patchwork Thu Mar 4 04:10:10 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ben Pfaff X-Patchwork-Id: 1447086 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::138; helo=smtp1.osuosl.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Received: from smtp1.osuosl.org (smtp1.osuosl.org [IPv6:2605:bc80:3010::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 4DrcqV4bldz9sSC for ; Thu, 4 Mar 2021 15:11:02 +1100 (AEDT) Received: from localhost (localhost [127.0.0.1]) by smtp1.osuosl.org (Postfix) with ESMTP id 887B98445A; Thu, 4 Mar 2021 04:10:59 +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 rtODXS45NS5P; Thu, 4 Mar 2021 04:10:57 +0000 (UTC) Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56]) by smtp1.osuosl.org (Postfix) with ESMTP id 04D06843D3; Thu, 4 Mar 2021 04:10:43 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id DB8B7C000D; Thu, 4 Mar 2021 04:10:42 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@lists.linuxfoundation.org Received: from smtp4.osuosl.org (smtp4.osuosl.org [140.211.166.137]) by lists.linuxfoundation.org (Postfix) with ESMTP id 40A58C000A for ; Thu, 4 Mar 2021 04:10:42 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by smtp4.osuosl.org (Postfix) with ESMTP id F2E574D107 for ; Thu, 4 Mar 2021 04:10:34 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org 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 erdMu_vaA_dq for ; Thu, 4 Mar 2021 04:10:34 +0000 (UTC) X-Greylist: domain auto-whitelisted by SQLgrey-1.8.0 Received: from relay9-d.mail.gandi.net (relay9-d.mail.gandi.net [217.70.183.199]) by smtp4.osuosl.org (Postfix) with ESMTPS id 955C94D4F1 for ; Thu, 4 Mar 2021 04:10:33 +0000 (UTC) X-Originating-IP: 75.54.222.30 Received: from sigfpe.attlocal.net (75-54-222-30.lightspeed.rdcyca.sbcglobal.net [75.54.222.30]) (Authenticated sender: blp@ovn.org) by relay9-d.mail.gandi.net (Postfix) with ESMTPSA id 2E40FFF803; Thu, 4 Mar 2021 04:10:30 +0000 (UTC) From: Ben Pfaff To: dev@openvswitch.org Date: Wed, 3 Mar 2021 20:10:10 -0800 Message-Id: <20210304041012.4128938-10-blp@ovn.org> X-Mailer: git-send-email 2.29.2 In-Reply-To: <20210304041012.4128938-1-blp@ovn.org> References: <20210304041012.4128938-1-blp@ovn.org> MIME-Version: 1.0 Cc: Ben Pfaff Subject: [ovs-dev] [PATCH ovn 09/11] ovn-northd-ddlog: Apply multiple database updates in single ddlog txn. 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" DDlog can apply a larger batch of updates more efficiently than a series of smaller ones. Until now, ovn-northd-ddlog has always applied updates one-by-one. This commit changes it so that if multiple updates are received in a batch, it applies all of them within a single ddlog transaction. Signed-off-by: Ben Pfaff --- northd/ovn-northd-ddlog.c | 115 ++++++++++++++++++++++++-------------- 1 file changed, 72 insertions(+), 43 deletions(-) diff --git a/northd/ovn-northd-ddlog.c b/northd/ovn-northd-ddlog.c index a510e64fd275..aa0ea73e401d 100644 --- a/northd/ovn-northd-ddlog.c +++ b/northd/ovn-northd-ddlog.c @@ -358,10 +358,11 @@ json_object_get(const struct json *json, const char *member_name) : NULL); } -/* Returns the new value of NB_Global::nb_cfg, if any, from the updates in - * provided by the caller, or INT64_MIN if none is present. */ -static int64_t -get_nb_cfg(const struct json *table_updates) +/* Stores into '*nb_cfgp' the new value of NB_Global::nb_cfg in the updates in + * provided by the caller. Leaves '*nb_cfgp' alone if the + * updates don't set NB_Global::nb_cfg. */ +static void +get_nb_cfg(const struct json *table_updates, int64_t *nb_cfgp) { const struct json *nb_global = json_object_get(table_updates, "NB_Global"); if (nb_global) { @@ -371,59 +372,72 @@ get_nb_cfg(const struct json *table_updates) const struct json *new = json_object_get(value, "new"); const struct json *nb_cfg = json_object_get(new, "nb_cfg"); if (nb_cfg && nb_cfg->type == JSON_INTEGER) { - return json_integer(nb_cfg); + *nb_cfgp = json_integer(nb_cfg); + return; } } } - return INT64_MIN; } static void -northd_parse_update(struct northd_ctx *ctx, - const struct ovsdb_cs_update_event *update) +northd_parse_updates(struct northd_ctx *ctx, struct ovs_list *updates) { + if (ovs_list_is_empty(updates)) { + return; + } + if (ddlog_transaction_start(ctx->ddlog)) { VLOG_WARN("DDlog failed to start transaction"); return; } - if (update->clear && ddlog_clear(ctx)) { - goto error; - } - char *updates_s = json_to_string(update->table_updates, 0); - if (ddlog_apply_ovsdb_updates(ctx->ddlog, ctx->prefix, updates_s)) { - VLOG_WARN("DDlog failed to apply updates %s", updates_s); - free(updates_s); - goto error; - } - free(updates_s); - /* Whenever a new 'nb_cfg' value comes in, take the current time and push - * it into the NbCfgTimestamp relation for the DDlog program to put into - * nb::NB_Global.nb_cfg_timestamp. */ + /* Whenever a new 'nb_cfg' value comes in, we take the current time and + * push it into the NbCfgTimestamp relation for the DDlog program to put + * into nb::NB_Global.nb_cfg_timestamp. + * + * The 'old_nb_cfg' variables track the state we've pushed into DDlog. + * The 'new_nb_cfg' variables track what 'updates' sets (by default, + * no change, so we initialize from the old variables). */ static int64_t old_nb_cfg = INT64_MIN; static int64_t old_nb_cfg_timestamp = INT64_MIN; - int64_t new_nb_cfg = old_nb_cfg; + int64_t new_nb_cfg = old_nb_cfg == INT64_MIN ? 0 : old_nb_cfg; int64_t new_nb_cfg_timestamp = old_nb_cfg_timestamp; - if (ctx->has_timestamp_columns) { - new_nb_cfg = get_nb_cfg(update->table_updates); - if (new_nb_cfg == INT64_MIN) { - new_nb_cfg = old_nb_cfg == INT64_MIN ? 0 : old_nb_cfg; + + struct ovsdb_cs_event *event; + LIST_FOR_EACH (event, list_node, updates) { + ovs_assert(event->type == OVSDB_CS_EVENT_TYPE_UPDATE); + struct ovsdb_cs_update_event *update = &event->update; + if (update->clear && ddlog_clear(ctx)) { + goto error; } - if (new_nb_cfg != old_nb_cfg) { - new_nb_cfg_timestamp = time_wall_msec(); - - ddlog_cmd *updates[2]; - int n_updates = 0; - if (old_nb_cfg_timestamp != INT64_MIN) { - updates[n_updates++] = ddlog_delete_val_cmd( - NB_CFG_TIMESTAMP_ID, ddlog_i64(old_nb_cfg_timestamp)); - } - updates[n_updates++] = ddlog_insert_cmd( - NB_CFG_TIMESTAMP_ID, ddlog_i64(new_nb_cfg_timestamp)); - if (ddlog_apply_updates(ctx->ddlog, updates, n_updates) < 0) { - goto error; - } + + char *updates_s = json_to_string(update->table_updates, 0); + if (ddlog_apply_ovsdb_updates(ctx->ddlog, ctx->prefix, updates_s)) { + VLOG_WARN("DDlog failed to apply updates %s", updates_s); + free(updates_s); + goto error; + } + free(updates_s); + + if (ctx->has_timestamp_columns) { + get_nb_cfg(update->table_updates, &new_nb_cfg); + } + } + + if (ctx->has_timestamp_columns && new_nb_cfg != old_nb_cfg) { + new_nb_cfg_timestamp = time_wall_msec(); + + ddlog_cmd *cmds[2]; + int n_cmds = 0; + if (old_nb_cfg_timestamp != INT64_MIN) { + cmds[n_cmds++] = ddlog_delete_val_cmd( + NB_CFG_TIMESTAMP_ID, ddlog_i64(old_nb_cfg_timestamp)); + } + cmds[n_cmds++] = ddlog_insert_cmd( + NB_CFG_TIMESTAMP_ID, ddlog_i64(new_nb_cfg_timestamp)); + if (ddlog_apply_updates(ctx->ddlog, cmds, n_cmds) < 0) { + goto error; } } @@ -486,6 +500,15 @@ northd_process_txn_reply(struct northd_ctx *ctx, } } +static void +destroy_event_list(struct ovs_list *events) +{ + struct ovsdb_cs_event *event; + LIST_FOR_EACH_POP (event, list_node, events) { + ovsdb_cs_event_destroy(event); + } +} + /* Processes a batch of messages from the database server on 'ctx'. */ static void northd_run(struct northd_ctx *ctx) @@ -493,6 +516,7 @@ northd_run(struct northd_ctx *ctx) struct ovs_list events; ovsdb_cs_run(ctx->cs, &events); + struct ovs_list updates = OVS_LIST_INITIALIZER(&updates); struct ovsdb_cs_event *event; LIST_FOR_EACH_POP (event, list_node, &events) { switch (event->type) { @@ -505,8 +529,11 @@ northd_run(struct northd_ctx *ctx) break; case OVSDB_CS_EVENT_TYPE_UPDATE: - northd_parse_update(ctx, &event->update); - break; + if (event->update.clear) { + destroy_event_list(&updates); + } + ovs_list_push_back(&updates, &event->list_node); + continue; case OVSDB_CS_EVENT_TYPE_TXN_REPLY: northd_process_txn_reply(ctx, event->txn_reply); @@ -515,6 +542,9 @@ northd_run(struct northd_ctx *ctx) ovsdb_cs_event_destroy(event); } + northd_parse_updates(ctx, &updates); + destroy_event_list(&updates); + if (ctx->state == S_INITIAL && ovsdb_cs_may_send_transaction(ctx->cs)) { northd_send_output_only_data_request(ctx); } @@ -1128,7 +1158,6 @@ main(int argc, char *argv[]) unixctl_command_register("exit", "", 0, 0, ovn_northd_exit, &exiting); unixctl_command_register("status", "", 0, 0, ovn_northd_status, &status); - ddlog_prog ddlog; ddlog = ddlog_run(1, false, ddlog_print_error, &delta); if (!ddlog) { From patchwork Thu Mar 4 04:10:11 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ben Pfaff X-Patchwork-Id: 1447085 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=) 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 4DrcqQ6RXGz9sSC for ; Thu, 4 Mar 2021 15:10:57 +1100 (AEDT) Received: from localhost (localhost [127.0.0.1]) by smtp2.osuosl.org (Postfix) with ESMTP id 2140C4326F; Thu, 4 Mar 2021 04:10:55 +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 aKjz1_LJuLtK; Thu, 4 Mar 2021 04:10:53 +0000 (UTC) Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56]) by smtp2.osuosl.org (Postfix) with ESMTP id 6B1E14329B; Thu, 4 Mar 2021 04:10:45 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id 2ABBCC000D; Thu, 4 Mar 2021 04:10:45 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@lists.linuxfoundation.org Received: from smtp4.osuosl.org (smtp4.osuosl.org [140.211.166.137]) by lists.linuxfoundation.org (Postfix) with ESMTP id 1E7DAC0019 for ; Thu, 4 Mar 2021 04:10:44 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by smtp4.osuosl.org (Postfix) with ESMTP id 080EF4EBD6 for ; Thu, 4 Mar 2021 04:10:36 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org 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 Aq1a-Vj9OpG6 for ; Thu, 4 Mar 2021 04:10:35 +0000 (UTC) X-Greylist: domain auto-whitelisted by SQLgrey-1.8.0 Received: from relay9-d.mail.gandi.net (relay9-d.mail.gandi.net [217.70.183.199]) by smtp4.osuosl.org (Postfix) with ESMTPS id DA6F94EBC8 for ; Thu, 4 Mar 2021 04:10:34 +0000 (UTC) X-Originating-IP: 75.54.222.30 Received: from sigfpe.attlocal.net (75-54-222-30.lightspeed.rdcyca.sbcglobal.net [75.54.222.30]) (Authenticated sender: blp@ovn.org) by relay9-d.mail.gandi.net (Postfix) with ESMTPSA id 8355BFF805; Thu, 4 Mar 2021 04:10:32 +0000 (UTC) From: Ben Pfaff To: dev@openvswitch.org Date: Wed, 3 Mar 2021 20:10:11 -0800 Message-Id: <20210304041012.4128938-11-blp@ovn.org> X-Mailer: git-send-email 2.29.2 In-Reply-To: <20210304041012.4128938-1-blp@ovn.org> References: <20210304041012.4128938-1-blp@ovn.org> MIME-Version: 1.0 Cc: Ben Pfaff Subject: [ovs-dev] [PATCH ovn 10/11] ovn-northd-ddlog: Rephrase RouterStaticRoute rule. 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 found that this slightly increased performance when there are lots of routers, probably because there's less data copying. Signed-off-by: Ben Pfaff --- northd/lrouter.dl | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/northd/lrouter.dl b/northd/lrouter.dl index 4c5cf321509e..9838c739a650 100644 --- a/northd/lrouter.dl +++ b/northd/lrouter.dl @@ -714,17 +714,14 @@ relation RouterStaticRoute( dsts : Set) RouterStaticRoute(router, key, dsts) :- - RouterStaticRoute_(.router = router, - .key = key, - .nexthop = nexthop, - .output_port = None, - .ecmp_symmetric_reply = ecmp_symmetric_reply), + rsr in RouterStaticRoute_(.router = router, .output_port = None), /* output_port is not specified, find the * router port matching the next hop. */ port in &RouterPort(.router = &Router{.lr = nb::Logical_Router{._uuid = router.lr._uuid}}, .networks = networks), - Some{var src_ip} = find_lrp_member_ip(networks, nexthop), - var dst = RouteDst{nexthop, src_ip, port, ecmp_symmetric_reply}, + Some{var src_ip} = find_lrp_member_ip(networks, rsr.nexthop), + var dst = RouteDst{rsr.nexthop, src_ip, port, rsr.ecmp_symmetric_reply}, + var key = rsr.key, var dsts = dst.group_by((router, key)).to_set(). RouterStaticRoute(router, key, dsts) :- From patchwork Thu Mar 4 04:10:12 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ben Pfaff X-Patchwork-Id: 1447088 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=) 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 4Drcr20m6Nz9sRf for ; Thu, 4 Mar 2021 15:11:30 +1100 (AEDT) Received: from localhost (localhost [127.0.0.1]) by smtp3.osuosl.org (Postfix) with ESMTP id 01E1D6FB87; Thu, 4 Mar 2021 04:11:26 +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 cKswSrMAGVhg; Thu, 4 Mar 2021 04:11:25 +0000 (UTC) Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56]) by smtp3.osuosl.org (Postfix) with ESMTP id 7A0A56FB3D; Thu, 4 Mar 2021 04:11:04 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id 4EFB0C0001; Thu, 4 Mar 2021 04:11:04 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@lists.linuxfoundation.org Received: from smtp1.osuosl.org (smtp1.osuosl.org [140.211.166.138]) by lists.linuxfoundation.org (Postfix) with ESMTP id 1B979C000D for ; Thu, 4 Mar 2021 04:11:03 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by smtp1.osuosl.org (Postfix) with ESMTP id 3963384393 for ; Thu, 4 Mar 2021 04:10:39 +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 csBfqGayzaem for ; Thu, 4 Mar 2021 04:10:36 +0000 (UTC) X-Greylist: domain auto-whitelisted by SQLgrey-1.8.0 Received: from relay9-d.mail.gandi.net (relay9-d.mail.gandi.net [217.70.183.199]) by smtp1.osuosl.org (Postfix) with ESMTPS id 428EB84371 for ; Thu, 4 Mar 2021 04:10:36 +0000 (UTC) X-Originating-IP: 75.54.222.30 Received: from sigfpe.attlocal.net (75-54-222-30.lightspeed.rdcyca.sbcglobal.net [75.54.222.30]) (Authenticated sender: blp@ovn.org) by relay9-d.mail.gandi.net (Postfix) with ESMTPSA id D9AF7FF807; Thu, 4 Mar 2021 04:10:33 +0000 (UTC) From: Ben Pfaff To: dev@openvswitch.org Date: Wed, 3 Mar 2021 20:10:12 -0800 Message-Id: <20210304041012.4128938-12-blp@ovn.org> X-Mailer: git-send-email 2.29.2 In-Reply-To: <20210304041012.4128938-1-blp@ovn.org> References: <20210304041012.4128938-1-blp@ovn.org> MIME-Version: 1.0 Cc: Ben Pfaff Subject: [ovs-dev] [PATCH ovn 11/11] ovn-northd-ddlog: Add profiling support. 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" DDlog has support for memory and CPU profiling. This commit adds commands for enabling CPU profiling (memory profiling is always enabled) and dumping out the profile. Signed-off-by: Ben Pfaff --- northd/ovn-northd-ddlog.c | 40 ++++++++++++++++++++++++++++++++++++++- northd/ovn-northd.8.xml | 36 ++++++++++++++++++++++++++++++++++- 2 files changed, 74 insertions(+), 2 deletions(-) diff --git a/northd/ovn-northd-ddlog.c b/northd/ovn-northd-ddlog.c index aa0ea73e401d..41e7decba76b 100644 --- a/northd/ovn-northd-ddlog.c +++ b/northd/ovn-northd-ddlog.c @@ -61,6 +61,10 @@ static unixctl_cb_func ovn_northd_resume; static unixctl_cb_func ovn_northd_is_paused; static unixctl_cb_func ovn_northd_status; +static unixctl_cb_func ovn_northd_enable_cpu_profiling; +static unixctl_cb_func ovn_northd_disable_cpu_profiling; +static unixctl_cb_func ovn_northd_profile; + /* --ddlog-record: The name of a file to which to record DDlog commands for * later replay. Useful for debugging. If null (by default), DDlog commands * are not recorded. */ @@ -391,7 +395,6 @@ northd_parse_updates(struct northd_ctx *ctx, struct ovs_list *updates) return; } - /* Whenever a new 'nb_cfg' value comes in, we take the current time and * push it into the NbCfgTimestamp relation for the DDlog program to put * into nb::NB_Global.nb_cfg_timestamp. @@ -1164,6 +1167,12 @@ main(int argc, char *argv[]) ovs_fatal(0, "DDlog instance could not be created"); } + unixctl_command_register("enable-cpu-profiling", "", 0, 0, + ovn_northd_enable_cpu_profiling, ddlog); + unixctl_command_register("disable-cpu-profiling", "", 0, 0, + ovn_northd_disable_cpu_profiling, ddlog); + unixctl_command_register("profile", "", 0, 0, ovn_northd_profile, ddlog); + int replay_fd = -1; if (record_file) { replay_fd = open(record_file, O_CREAT | O_WRONLY | O_TRUNC, 0666); @@ -1313,3 +1322,32 @@ ovn_northd_status(struct unixctl_conn *conn, int argc OVS_UNUSED, unixctl_command_reply(conn, s); free(s); } + +static void +ovn_northd_enable_cpu_profiling(struct unixctl_conn *conn, int argc OVS_UNUSED, + const char *argv[] OVS_UNUSED, void *prog_) +{ + ddlog_prog prog = prog_; + ddlog_enable_cpu_profiling(prog, true); + unixctl_command_reply(conn, NULL); +} + +static void +ovn_northd_disable_cpu_profiling(struct unixctl_conn *conn, + int argc OVS_UNUSED, + const char *argv[] OVS_UNUSED, void *prog_) +{ + ddlog_prog prog = prog_; + ddlog_enable_cpu_profiling(prog, false); + unixctl_command_reply(conn, NULL); +} + +static void +ovn_northd_profile(struct unixctl_conn *conn, int argc OVS_UNUSED, + const char *argv[] OVS_UNUSED, void *prog_) +{ + ddlog_prog prog = prog_; + char *profile = ddlog_profile(prog); + unixctl_command_reply(conn, profile); + free(profile); +} diff --git a/northd/ovn-northd.8.xml b/northd/ovn-northd.8.xml index a16937a2147c..97ef049ad9da 100644 --- a/northd/ovn-northd.8.xml +++ b/northd/ovn-northd.8.xml @@ -1,7 +1,7 @@

Name

-

ovn-northd -- Open Virtual Network central control daemon

+

ovn-northd and ovn-northd-ddlog -- Open Virtual Network central control daemon

Synopsis

ovn-northd [options]

@@ -18,6 +18,14 @@ ovn-sb(5)) below it.

+

+ ovn-northd is implemented in C. + ovn-northd-ddlog is a compatible implementation written in + DDlog, a language for incremental database processing. This + documentation applies to both implementations, with differences indicated + where relevant. +

+

Options

--ovnnb-db=database
@@ -127,6 +135,32 @@

+

+ Only ovn-northd-ddlog supports the following commands: +

+ +
+
enable-cpu-profiling
+
disable-cpu-profiling
+
+ Enables or disables profiling of CPU time used by the DDlog engine. + When CPU profiling is enabled, the profile command (see + below) will include DDlog CPU usage statistics in its output. Enabling + CPU profiling will slow ovn-northd-ddlog. Disabling CPU + profiling does not clear any previously recorded statistics. +
+ +
profile
+
+ Outputs a profile of the current and peak sizes of arrangements inside + DDlog. This profiling data can be useful for optimizing DDlog code. + If CPU profiling was previously enabled (even if it was later + disabled), the output also includes a CPU time profile. See + Profiling inside the tutorial in the DDlog repository for + an introduction to profiling DDlog. +
+
+

Active-Standby for High Availability

You may run ovn-northd more than once in an OVN deployment.