From patchwork Mon Mar 7 17:46:32 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Numan Siddique X-Patchwork-Id: 1602449 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 bilbo.ozlabs.org (Postfix) with ESMTPS id 4KC5W651tLz9sGP for ; Tue, 8 Mar 2022 04:46:56 +1100 (AEDT) Received: from localhost (localhost [127.0.0.1]) by smtp4.osuosl.org (Postfix) with ESMTP id 04316416EC; Mon, 7 Mar 2022 17:46:54 +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 Wo19wwRgiyYO; Mon, 7 Mar 2022 17:46:51 +0000 (UTC) Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56]) by smtp4.osuosl.org (Postfix) with ESMTPS id CC1C1416D9; Mon, 7 Mar 2022 17:46:50 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id 9C508C001D; Mon, 7 Mar 2022 17:46:50 +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 2F8A9C000B for ; Mon, 7 Mar 2022 17:46:49 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by smtp1.osuosl.org (Postfix) with ESMTP id F3EFB82EBA for ; Mon, 7 Mar 2022 17:46:48 +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 2xz6jg2G-Iw3 for ; Mon, 7 Mar 2022 17:46:46 +0000 (UTC) X-Greylist: domain auto-whitelisted by SQLgrey-1.8.0 Received: from relay6-d.mail.gandi.net (relay6-d.mail.gandi.net [217.70.183.198]) by smtp1.osuosl.org (Postfix) with ESMTPS id 8C83782C91 for ; Mon, 7 Mar 2022 17:46:45 +0000 (UTC) Received: (Authenticated sender: numans@ovn.org) by mail.gandi.net (Postfix) with ESMTPSA id AA711C000A; Mon, 7 Mar 2022 17:46:38 +0000 (UTC) From: numans@ovn.org To: dev@openvswitch.org Date: Mon, 7 Mar 2022 12:46:32 -0500 Message-Id: <20220307174632.1087082-1-numans@ovn.org> X-Mailer: git-send-email 2.34.1 MIME-Version: 1.0 Cc: Dumitru Ceara Subject: [ovs-dev] [PATCH ovn] northd: Support the option to apply from-lport ACLs after load balancer. 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" From: Numan Siddique Presently for ACLs and LBs we do the following in the logical switch ingress pipeline 1. Send the packet to conntrack. 2. Apply ACLs (from-lport) 3a. If the packet is a new connection and it is destined to the LB VIP, then select a backend (and commit to conntrack with DNAT). 3b. If the packet is a new connection and it doesn't match 3a, then commit to conntrack. With the above approach, we cannot address the scenario of applying ACLs after the load balancing. There can be ACLs which could match on the load balancer backend ips. This patch addresses this usecase by 1. Send the packet to conntrack. 2. Apply ACLs (from-lport, not configured with apply-after-lb=true) 3. If the packet is a new connection and it is destined to the LB VIP, then select a backend (and commit to conntrack with DNAT). 4. Apply ACLs (from-lport, configured with apply-after-lb=true) 5. If the packet is a new connection and it didn't match (2), then commit to conntrack. In order to support this usecase, this patch supports an option "apply-after-lb=true" in the ACL table. This option is valid only for "from-lport" ACLs. Suggested-by: Dumitru Ceara Signed-off-by: Numan Siddique Acked-by: Han Zhou Acked-by: Dumitru Ceara --- northd/northd.c | 90 +++--- northd/ovn-northd.8.xml | 110 +++++-- ovn-nb.xml | 28 ++ tests/ovn-northd.at | 359 ++++++++++++++++------ tests/ovn.at | 46 +-- tests/system-ovn.at | 614 +++++++++++++++++++++++++++++++++++++- utilities/ovn-nbctl.8.xml | 9 +- utilities/ovn-nbctl.c | 12 +- 8 files changed, 1093 insertions(+), 175 deletions(-) diff --git a/northd/northd.c b/northd/northd.c index 294a59bd7e..b22da67e9c 100644 --- a/northd/northd.c +++ b/northd/northd.c @@ -112,18 +112,20 @@ enum ovn_stage { PIPELINE_STAGE(SWITCH, IN, ACL, 9, "ls_in_acl") \ PIPELINE_STAGE(SWITCH, IN, QOS_MARK, 10, "ls_in_qos_mark") \ PIPELINE_STAGE(SWITCH, IN, QOS_METER, 11, "ls_in_qos_meter") \ - PIPELINE_STAGE(SWITCH, IN, STATEFUL, 12, "ls_in_stateful") \ - PIPELINE_STAGE(SWITCH, IN, PRE_HAIRPIN, 13, "ls_in_pre_hairpin") \ - PIPELINE_STAGE(SWITCH, IN, NAT_HAIRPIN, 14, "ls_in_nat_hairpin") \ - PIPELINE_STAGE(SWITCH, IN, HAIRPIN, 15, "ls_in_hairpin") \ - PIPELINE_STAGE(SWITCH, IN, ARP_ND_RSP, 16, "ls_in_arp_rsp") \ - PIPELINE_STAGE(SWITCH, IN, DHCP_OPTIONS, 17, "ls_in_dhcp_options") \ - PIPELINE_STAGE(SWITCH, IN, DHCP_RESPONSE, 18, "ls_in_dhcp_response") \ - PIPELINE_STAGE(SWITCH, IN, DNS_LOOKUP, 19, "ls_in_dns_lookup") \ - PIPELINE_STAGE(SWITCH, IN, DNS_RESPONSE, 20, "ls_in_dns_response") \ - PIPELINE_STAGE(SWITCH, IN, EXTERNAL_PORT, 21, "ls_in_external_port") \ - PIPELINE_STAGE(SWITCH, IN, L2_LKUP, 22, "ls_in_l2_lkup") \ - PIPELINE_STAGE(SWITCH, IN, L2_UNKNOWN, 23, "ls_in_l2_unknown") \ + PIPELINE_STAGE(SWITCH, IN, LB, 12, "ls_in_lb") \ + PIPELINE_STAGE(SWITCH, IN, ACL_AFTER_LB, 13, "ls_in_acl_after_lb") \ + PIPELINE_STAGE(SWITCH, IN, STATEFUL, 14, "ls_in_stateful") \ + PIPELINE_STAGE(SWITCH, IN, PRE_HAIRPIN, 15, "ls_in_pre_hairpin") \ + PIPELINE_STAGE(SWITCH, IN, NAT_HAIRPIN, 16, "ls_in_nat_hairpin") \ + PIPELINE_STAGE(SWITCH, IN, HAIRPIN, 17, "ls_in_hairpin") \ + PIPELINE_STAGE(SWITCH, IN, ARP_ND_RSP, 18, "ls_in_arp_rsp") \ + PIPELINE_STAGE(SWITCH, IN, DHCP_OPTIONS, 19, "ls_in_dhcp_options") \ + PIPELINE_STAGE(SWITCH, IN, DHCP_RESPONSE, 20, "ls_in_dhcp_response") \ + PIPELINE_STAGE(SWITCH, IN, DNS_LOOKUP, 21, "ls_in_dns_lookup") \ + PIPELINE_STAGE(SWITCH, IN, DNS_RESPONSE, 22, "ls_in_dns_response") \ + PIPELINE_STAGE(SWITCH, IN, EXTERNAL_PORT, 23, "ls_in_external_port") \ + PIPELINE_STAGE(SWITCH, IN, L2_LKUP, 24, "ls_in_l2_lkup") \ + PIPELINE_STAGE(SWITCH, IN, L2_UNKNOWN, 25, "ls_in_l2_unknown") \ \ /* Logical switch egress stages. */ \ PIPELINE_STAGE(SWITCH, OUT, PRE_LB, 0, "ls_out_pre_lb") \ @@ -6145,7 +6147,7 @@ build_reject_acl_rules(struct ovn_datapath *od, struct hmap *lflows, { struct ds match = DS_EMPTY_INITIALIZER; struct ds actions = DS_EMPTY_INITIALIZER; - bool ingress = (stage == S_SWITCH_IN_ACL); + bool ingress = (ovn_stage_get_pipeline(stage) == P_IN); char *next_action = xasprintf("next(pipeline=%s,table=%d);", @@ -6186,7 +6188,15 @@ consider_acl(struct hmap *lflows, struct ovn_datapath *od, struct ds *actions) { bool ingress = !strcmp(acl->direction, "from-lport") ? true :false; - enum ovn_stage stage = ingress ? S_SWITCH_IN_ACL : S_SWITCH_OUT_ACL; + enum ovn_stage stage; + + if (ingress && smap_get_bool(&acl->options, "apply-after-lb", false)) { + stage = S_SWITCH_IN_ACL_AFTER_LB; + } else if (ingress) { + stage = S_SWITCH_IN_ACL; + } else { + stage = S_SWITCH_OUT_ACL; + } if (!strcmp(acl->action, "allow-stateless")) { ds_clear(actions); @@ -6471,6 +6481,8 @@ build_acls(struct ovn_datapath *od, struct hmap *lflows, ovn_lflow_add(lflows, od, S_SWITCH_OUT_ACL, 0, "1", "next;"); } + ovn_lflow_add(lflows, od, S_SWITCH_IN_ACL_AFTER_LB, 0, "1", "next;"); + if (has_stateful) { /* Ingress and Egress ACL Table (Priority 1). * @@ -6529,7 +6541,8 @@ build_acls(struct ovn_datapath *od, struct hmap *lflows, "ct.rpl && ct_label.blocked == 0", use_ct_inv_match ? " && !ct.inv" : ""); ovn_lflow_add(lflows, od, S_SWITCH_IN_ACL, UINT16_MAX - 3, - ds_cstr(&match), "next;"); + ds_cstr(&match), REGBIT_ACL_HINT_DROP" = 0; " + REGBIT_ACL_HINT_BLOCK" = 0; next;"); ovn_lflow_add(lflows, od, S_SWITCH_OUT_ACL, UINT16_MAX - 3, ds_cstr(&match), "next;"); @@ -6736,6 +6749,10 @@ build_lb_rules(struct hmap *lflows, struct ovn_northd_lb *lb, ds_clear(action); ds_clear(match); + /* Make sure that we clear the REGBIT_CONNTRACK_COMMIT flag. Otherwise + * the load balanced packet will be committed again in + * S_SWITCH_IN_STATEFUL. */ + ds_put_format(action, REGBIT_CONNTRACK_COMMIT" = 0; "); /* Store the original destination IP to be used when generating * hairpin flows. */ @@ -6782,8 +6799,8 @@ build_lb_rules(struct hmap *lflows, struct ovn_northd_lb *lb, struct ovn_lflow *lflow_ref = NULL; uint32_t hash = ovn_logical_flow_hash( - ovn_stage_get_table(S_SWITCH_IN_STATEFUL), - ovn_stage_get_pipeline(S_SWITCH_IN_STATEFUL), priority, + ovn_stage_get_table(S_SWITCH_IN_LB), + ovn_stage_get_pipeline(S_SWITCH_IN_LB), priority, ds_cstr(match), ds_cstr(action)); for (size_t j = 0; j < lb->n_nb_ls; j++) { @@ -6796,7 +6813,7 @@ build_lb_rules(struct hmap *lflows, struct ovn_northd_lb *lb, continue; } lflow_ref = ovn_lflow_add_at_with_hash(lflows, od, - S_SWITCH_IN_STATEFUL, priority, + S_SWITCH_IN_LB, priority, ds_cstr(match), ds_cstr(action), NULL, meter, &lb->nlb->header_, OVS_SOURCE_LOCATOR, hash); @@ -6807,8 +6824,9 @@ build_lb_rules(struct hmap *lflows, struct ovn_northd_lb *lb, static void build_stateful(struct ovn_datapath *od, struct hmap *lflows) { - /* Ingress and Egress stateful Table (Priority 0): Packets are + /* Ingress LB, Ingress and Egress stateful Table (Priority 0): Packets are * allowed by default. */ + ovn_lflow_add(lflows, od, S_SWITCH_IN_LB, 0, "1", "next;"); ovn_lflow_add(lflows, od, S_SWITCH_IN_STATEFUL, 0, "1", "next;"); ovn_lflow_add(lflows, od, S_SWITCH_OUT_STATEFUL, 0, "1", "next;"); @@ -7072,7 +7090,7 @@ build_lrouter_groups(struct hmap *ports, struct ovs_list *lr_list) } /* - * Ingress table 22: Flows that flood self originated ARP/ND packets in the + * Ingress table 24: Flows that flood self originated ARP/ND packets in the * switching domain. */ static void @@ -7185,7 +7203,7 @@ lrouter_port_ipv6_reachable(const struct ovn_port *op, } /* - * Ingress table 22: Flows that forward ARP/ND requests only to the routers + * Ingress table 24: Flows that forward ARP/ND requests only to the routers * that own the addresses. Other ARP/ND packets are still flooded in the * switching domain as regular broadcast. */ @@ -7222,7 +7240,7 @@ build_lswitch_rport_arp_req_flow(const char *ips, } /* - * Ingress table 22: Flows that forward ARP/ND requests only to the routers + * Ingress table 24: Flows that forward ARP/ND requests only to the routers * that own the addresses. * Priorities: * - 80: self originated GARPs that need to follow regular processing. @@ -7550,7 +7568,7 @@ build_lswitch_flows(const struct hmap *datapaths, struct ovn_datapath *od; - /* Ingress table 23: Destination lookup for unknown MACs (priority 0). */ + /* Ingress table 25: Destination lookup for unknown MACs (priority 0). */ HMAP_FOR_EACH (od, key_node, datapaths) { if (!od->nbs) { continue; @@ -7619,7 +7637,7 @@ build_lswitch_lflows_admission_control(struct ovn_datapath *od, } } -/* Ingress table 16: ARP/ND responder, skip requests coming from localnet +/* Ingress table 18: ARP/ND responder, skip requests coming from localnet * and vtep ports. (priority 100); see ovn-northd.8.xml for the * rationale. */ @@ -7641,7 +7659,7 @@ build_lswitch_arp_nd_responder_skip_local(struct ovn_port *op, } } -/* Ingress table 16: ARP/ND responder, reply for known IPs. +/* Ingress table 18: ARP/ND responder, reply for known IPs. * (priority 50). */ static void build_lswitch_arp_nd_responder_known_ips(struct ovn_port *op, @@ -7901,7 +7919,7 @@ build_lswitch_arp_nd_responder_known_ips(struct ovn_port *op, } } -/* Ingress table 16: ARP/ND responder, by default goto next. +/* Ingress table 18: ARP/ND responder, by default goto next. * (priority 0)*/ static void build_lswitch_arp_nd_responder_default(struct ovn_datapath *od, @@ -7912,7 +7930,7 @@ build_lswitch_arp_nd_responder_default(struct ovn_datapath *od, } } -/* Ingress table 16: ARP/ND responder for service monitor source ip. +/* Ingress table 18: ARP/ND responder for service monitor source ip. * (priority 110)*/ static void build_lswitch_arp_nd_service_monitor(struct ovn_northd_lb *lb, @@ -7960,7 +7978,7 @@ build_lswitch_arp_nd_service_monitor(struct ovn_northd_lb *lb, } -/* Logical switch ingress table 14 and 15: DHCP options and response +/* Logical switch ingress table 19 and 20: DHCP options and response * priority 100 flows. */ static void build_lswitch_dhcp_options_and_response(struct ovn_port *op, @@ -8012,11 +8030,11 @@ build_lswitch_dhcp_options_and_response(struct ovn_port *op, } } -/* Ingress table 14 and 15: DHCP options and response, by default goto +/* Ingress table 19 and 20: DHCP options and response, by default goto * next. (priority 0). - * Ingress table 16 and 17: DNS lookup and response, by default goto next. + * Ingress table 21 and 22: DNS lookup and response, by default goto next. * (priority 0). - * Ingress table 18 - External port handling, by default goto next. + * Ingress table 23 - External port handling, by default goto next. * (priority 0). */ static void build_lswitch_dhcp_and_dns_defaults(struct ovn_datapath *od, @@ -8031,7 +8049,7 @@ build_lswitch_dhcp_and_dns_defaults(struct ovn_datapath *od, } } -/* Logical switch ingress table 17 and 18: DNS lookup and response +/* Logical switch ingress table 21 and 22: DNS lookup and response * priority 100 flows. */ static void @@ -8059,7 +8077,7 @@ build_lswitch_dns_lookup_and_response(struct ovn_datapath *od, } } -/* Table 18: External port. Drop ARP request for router ips from +/* Table 23: External port. Drop ARP request for router ips from * external ports on chassis not binding those ports. * This makes the router pipeline to be run only on the chassis * binding the external ports. */ @@ -8076,7 +8094,7 @@ build_lswitch_external_port(struct ovn_port *op, } } -/* Ingress table 22: Destination lookup, broadcast and multicast handling +/* Ingress table 24: Destination lookup, broadcast and multicast handling * (priority 70 - 100). */ static void build_lswitch_destination_lookup_bmcast(struct ovn_datapath *od, @@ -8168,7 +8186,7 @@ build_lswitch_destination_lookup_bmcast(struct ovn_datapath *od, } -/* Ingress table 22: Add IP multicast flows learnt from IGMP/MLD +/* Ingress table 24: Add IP multicast flows learnt from IGMP/MLD * (priority 90). */ static void build_lswitch_ip_mcast_igmp_mld(struct ovn_igmp_group *igmp_group, @@ -8246,7 +8264,7 @@ build_lswitch_ip_mcast_igmp_mld(struct ovn_igmp_group *igmp_group, static struct ovs_mutex mcgroup_mutex = OVS_MUTEX_INITIALIZER; -/* Ingress table 22: Destination lookup, unicast handling (priority 50), */ +/* Ingress table 24: Destination lookup, unicast handling (priority 50), */ static void build_lswitch_ip_unicast_lookup(struct ovn_port *op, struct hmap *lflows, diff --git a/northd/ovn-northd.8.xml b/northd/ovn-northd.8.xml index e495db46a0..1c9d408afe 100644 --- a/northd/ovn-northd.8.xml +++ b/northd/ovn-northd.8.xml @@ -712,15 +712,16 @@ -

Ingress table 9: from-lport ACLs

+

Ingress table 9: from-lport ACLs before LB

Logical flows in this table closely reproduce those in the ACL table in the OVN_Northbound database - for the from-lport direction. The priority - values from the ACL table have a limited range and have - 1000 added to them to leave room for OVN default flows at both - higher and lower priorities. + for the from-lport direction without the option + apply-after-lb set or set to false. + The priority values from the ACL table have a + limited range and have 1000 added to them to leave room for OVN default + flows at both higher and lower priorities.

  • @@ -795,10 +796,11 @@ go through the flows that implement the currently defined policy based on ACLs. If a connection is no longer allowed by policy, ct_label.blocked will get set and packets in the - reply direction will no longer be allowed, either. If ACL logging - and logging of related packets is enabled, then a companion priority- - 65533 flow will be installed that accomplishes the same thing but - also logs the traffic. + reply direction will no longer be allowed, either. This flow also + clears the register bits reg0[9] and + reg0[10]. If ACL logging and logging of related packets + is enabled, then a companion priority-65533 flow will be installed that + accomplishes the same thing but also logs the traffic.
  • @@ -893,7 +895,7 @@
-

Ingress Table 12: Stateful

+

Ingress Table 12: LB

  • @@ -944,7 +946,73 @@ Please note using --reject option will disable empty_lb SB controller event for this load balancer.
  • +
+ +

Ingress table 13: from-lport ACLs after LB

+ +

+ Logical flows in this table closely reproduce those in the + ACL table in the OVN_Northbound database + for the from-lport direction with the option + apply-after-lb set to true. + The priority values from the ACL table have a + limited range and have 1000 added to them to leave room for OVN default + flows at both higher and lower priorities. +

+ +
    +
  • + allow apply-after-lb ACLs translate into logical flows + with the next; action. If there are any stateful ACLs + (including both before-lb and after-lb ACLs) + on this datapath, then allow ACLs translate to + ct_commit; next; (which acts as a hint for the next tables + to commit the connection to conntrack). In case the ACL + has a label then reg3 is loaded with the label value and + reg0[13] bit is set to 1 (which acts as a hint for the + next tables to commit the label to conntrack). +
  • +
  • + allow-related apply-after-lb ACLs translate into logical + flows with the ct_commit(ct_label=0/1); next; actions + for new connections and reg0[1] = 1; next; for existing + connections. In case the ACL has a label then + reg3 is loaded with the label value and + reg0[13] bit is set to 1 (which acts as a hint for the + next tables to commit the label to conntrack). +
  • +
  • + allow-stateless apply-after-lb ACLs translate into logical + flows with the next; action. +
  • +
  • + reject apply-after-lb ACLs translate into logical + flows with the + tcp_reset { output <-> inport; + next(pipeline=egress,table=5);} + action for TCP connections,icmp4/icmp6 action + for UDP connections, and sctp_abort {output <-%gt; inport; + next(pipeline=egress,table=5);} action for SCTP associations. +
  • +
  • + Other apply-after-lb ACLs translate to drop; for new + or untracked connections and ct_commit(ct_label=1/1); for + known connections. Setting ct_label marks a connection + as one that was previously allowed, but should no longer be + allowed due to a policy change. +
  • +
+ +
    +
  • + One priority-0 fallback flow that matches all packets and advances to + the next table. +
  • +
+ +

Ingress Table 14: Stateful

+
  • A priority 100 flow is added which commits the packet to the conntrack and sets the most significant 32-bits of ct_label with the @@ -965,7 +1033,7 @@
-

Ingress Table 13: Pre-Hairpin

+

Ingress Table 15: Pre-Hairpin

  • If the logical switch has load balancer(s) configured, then a @@ -983,7 +1051,7 @@
-

Ingress Table 14: Nat-Hairpin

+

Ingress Table 16: Nat-Hairpin

  • If the logical switch has load balancer(s) configured, then a @@ -1018,7 +1086,7 @@
-

Ingress Table 15: Hairpin

+

Ingress Table 17: Hairpin

  • A priority-1 flow that hairpins traffic matched by non-default @@ -1031,7 +1099,7 @@
-

Ingress Table 16: ARP/ND responder

+

Ingress Table 18: ARP/ND responder

This table implements ARP/ND responder in a logical switch for known @@ -1333,7 +1401,7 @@ output; -

Ingress Table 17: DHCP option processing

+

Ingress Table 19: DHCP option processing

This table adds the DHCPv4 options to a DHCPv4 packet from the @@ -1394,7 +1462,7 @@ next; -

Ingress Table 18: DHCP responses

+

Ingress Table 20: DHCP responses

This table implements DHCP responder for the DHCP replies generated by @@ -1475,7 +1543,7 @@ output; -

Ingress Table 19 DNS Lookup

+

Ingress Table 21 DNS Lookup

This table looks up and resolves the DNS names to the corresponding @@ -1504,7 +1572,7 @@ reg0[4] = dns_lookup(); next; -

Ingress Table 20 DNS Responses

+

Ingress Table 22 DNS Responses

This table implements DNS responder for the DNS replies generated by @@ -1539,7 +1607,7 @@ output; -

Ingress table 21 External ports

+

Ingress table 23 External ports

Traffic from the external logical ports enter the ingress @@ -1582,7 +1650,7 @@ output; -

Ingress Table 22 Destination Lookup

+

Ingress Table 24 Destination Lookup

This table implements switching behavior. It contains these logical @@ -1754,7 +1822,7 @@ output; -

Ingress Table 24 Destination unknown

+

Ingress Table 25 Destination unknown

This table handles the packets whose destination was not found or diff --git a/ovn-nb.xml b/ovn-nb.xml index beb3ded798..cea105b545 100644 --- a/ovn-nb.xml +++ b/ovn-nb.xml @@ -2029,6 +2029,34 @@ + +

+ ACLs options. +

+ +

+ If set to true, the ACL will be applied after load balancing + stage. Supported only for from-lport direction. +

+ +

+ The main usecase of this option is to support ACLs matching on + the destination IP address of the packet for the backend IPs + of load balancers. +

+ +

+ OVN will apply the from-lportACLs in two + stages. ACLs without this option apply-after-lb + set, will be applied before the load balancer stage and ACLs + with this option set will be applied after the load balancer + stage. Hence CMS should be extra careful when using this option + and should carefully evaluate the priorities of all the ACLs and + the default deny/allow ACLs if any. +

+
+ +

These columns control whether and how OVN logs packets that match an diff --git a/tests/ovn-northd.at b/tests/ovn-northd.at index fe27869737..3865003bf8 100644 --- a/tests/ovn-northd.at +++ b/tests/ovn-northd.at @@ -1226,7 +1226,7 @@ check ovn-nbctl --wait=sb ls-lb-add sw0 lb1 AT_CAPTURE_FILE([sbflows]) OVS_WAIT_FOR_OUTPUT( [ovn-sbctl dump-flows sw0 | tee sbflows | grep 'priority=120.*backends' | sed 's/table=..//'], 0, [dnl - (ls_in_stateful ), priority=120 , match=(ct.new && ip4.dst == 10.0.0.10 && tcp.dst == 80), action=(reg1 = 10.0.0.10; reg2[[0..15]] = 80; ct_lb(backends=10.0.0.3:80,20.0.0.3:80);) + (ls_in_lb ), priority=120 , match=(ct.new && ip4.dst == 10.0.0.10 && tcp.dst == 80), action=(reg0[[1]] = 0; reg1 = 10.0.0.10; reg2[[0..15]] = 80; ct_lb(backends=10.0.0.3:80,20.0.0.3:80);) ]) AS_BOX([Delete the Load_Balancer_Health_Check]) @@ -1236,7 +1236,7 @@ wait_row_count Service_Monitor 0 AT_CAPTURE_FILE([sbflows2]) OVS_WAIT_FOR_OUTPUT( [ovn-sbctl dump-flows sw0 | tee sbflows2 | grep 'priority=120.*backends' | sed 's/table=..//'], [0], -[ (ls_in_stateful ), priority=120 , match=(ct.new && ip4.dst == 10.0.0.10 && tcp.dst == 80), action=(reg1 = 10.0.0.10; reg2[[0..15]] = 80; ct_lb(backends=10.0.0.3:80,20.0.0.3:80);) +[ (ls_in_lb ), priority=120 , match=(ct.new && ip4.dst == 10.0.0.10 && tcp.dst == 80), action=(reg0[[1]] = 0; reg1 = 10.0.0.10; reg2[[0..15]] = 80; ct_lb(backends=10.0.0.3:80,20.0.0.3:80);) ]) AS_BOX([Create the Load_Balancer_Health_Check again.]) @@ -1248,7 +1248,7 @@ check ovn-nbctl --wait=sb sync ovn-sbctl dump-flows sw0 | grep backends | grep priority=120 > lflows.txt AT_CHECK([cat lflows.txt | sed 's/table=..//'], [0], [dnl - (ls_in_stateful ), priority=120 , match=(ct.new && ip4.dst == 10.0.0.10 && tcp.dst == 80), action=(reg1 = 10.0.0.10; reg2[[0..15]] = 80; ct_lb(backends=10.0.0.3:80,20.0.0.3:80);) + (ls_in_lb ), priority=120 , match=(ct.new && ip4.dst == 10.0.0.10 && tcp.dst == 80), action=(reg0[[1]] = 0; reg1 = 10.0.0.10; reg2[[0..15]] = 80; ct_lb(backends=10.0.0.3:80,20.0.0.3:80);) ]) AS_BOX([Get the uuid of both the service_monitor]) @@ -1258,7 +1258,7 @@ sm_sw1_p1=$(fetch_column Service_Monitor _uuid logical_port=sw1-p1) AT_CAPTURE_FILE([sbflows3]) OVS_WAIT_FOR_OUTPUT( [ovn-sbctl dump-flows sw0 | tee sbflows 3 | grep 'priority=120.*backends' | sed 's/table=..//'], [0], -[ (ls_in_stateful ), priority=120 , match=(ct.new && ip4.dst == 10.0.0.10 && tcp.dst == 80), action=(reg1 = 10.0.0.10; reg2[[0..15]] = 80; ct_lb(backends=10.0.0.3:80,20.0.0.3:80);) +[ (ls_in_lb ), priority=120 , match=(ct.new && ip4.dst == 10.0.0.10 && tcp.dst == 80), action=(reg0[[1]] = 0; reg1 = 10.0.0.10; reg2[[0..15]] = 80; ct_lb(backends=10.0.0.3:80,20.0.0.3:80);) ]) AS_BOX([Set the service monitor for sw1-p1 to offline]) @@ -1269,7 +1269,7 @@ check ovn-nbctl --wait=sb sync AT_CAPTURE_FILE([sbflows4]) OVS_WAIT_FOR_OUTPUT( [ovn-sbctl dump-flows sw0 | tee sbflows4 | grep 'priority=120.*backends' | sed 's/table=..//'], [0], -[ (ls_in_stateful ), priority=120 , match=(ct.new && ip4.dst == 10.0.0.10 && tcp.dst == 80), action=(reg1 = 10.0.0.10; reg2[[0..15]] = 80; ct_lb(backends=10.0.0.3:80);) +[ (ls_in_lb ), priority=120 , match=(ct.new && ip4.dst == 10.0.0.10 && tcp.dst == 80), action=(reg0[[1]] = 0; reg1 = 10.0.0.10; reg2[[0..15]] = 80; ct_lb(backends=10.0.0.3:80);) ]) AS_BOX([Set the service monitor for sw0-p1 to offline]) @@ -1285,7 +1285,7 @@ OVS_WAIT_FOR_OUTPUT( AT_CAPTURE_FILE([sbflows6]) OVS_WAIT_FOR_OUTPUT( [ovn-sbctl dump-flows sw0 | tee sbflows6 | grep "ip4.dst == 10.0.0.10 && tcp.dst == 80" | grep priority=120 | sed 's/table=..//'], [0], [dnl - (ls_in_stateful ), priority=120 , match=(ct.new && ip4.dst == 10.0.0.10 && tcp.dst == 80), action=(drop;) + (ls_in_lb ), priority=120 , match=(ct.new && ip4.dst == 10.0.0.10 && tcp.dst == 80), action=(drop;) ]) AS_BOX([Set the service monitor for sw0-p1 and sw1-p1 to online]) @@ -1298,7 +1298,7 @@ check ovn-nbctl --wait=sb sync AT_CAPTURE_FILE([sbflows7]) OVS_WAIT_FOR_OUTPUT( [ovn-sbctl dump-flows sw0 | tee sbflows7 | grep backends | grep priority=120 | sed 's/table=..//'], 0, -[ (ls_in_stateful ), priority=120 , match=(ct.new && ip4.dst == 10.0.0.10 && tcp.dst == 80), action=(reg1 = 10.0.0.10; reg2[[0..15]] = 80; ct_lb(backends=10.0.0.3:80,20.0.0.3:80);) +[ (ls_in_lb ), priority=120 , match=(ct.new && ip4.dst == 10.0.0.10 && tcp.dst == 80), action=(reg0[[1]] = 0; reg1 = 10.0.0.10; reg2[[0..15]] = 80; ct_lb(backends=10.0.0.3:80,20.0.0.3:80);) ]) AS_BOX([Set the service monitor for sw1-p1 to error]) @@ -1309,7 +1309,7 @@ check ovn-nbctl --wait=sb sync ovn-sbctl dump-flows sw0 | grep "ip4.dst == 10.0.0.10 && tcp.dst == 80" \ | grep priority=120 > lflows.txt AT_CHECK([cat lflows.txt | sed 's/table=..//'], [0], [dnl - (ls_in_stateful ), priority=120 , match=(ct.new && ip4.dst == 10.0.0.10 && tcp.dst == 80), action=(reg1 = 10.0.0.10; reg2[[0..15]] = 80; ct_lb(backends=10.0.0.3:80);) + (ls_in_lb ), priority=120 , match=(ct.new && ip4.dst == 10.0.0.10 && tcp.dst == 80), action=(reg0[[1]] = 0; reg1 = 10.0.0.10; reg2[[0..15]] = 80; ct_lb(backends=10.0.0.3:80);) ]) AS_BOX([Add one more vip to lb1]) @@ -1335,8 +1335,8 @@ AT_CAPTURE_FILE([sbflows9]) OVS_WAIT_FOR_OUTPUT( [ovn-sbctl dump-flows sw0 | tee sbflows9 | grep backends | grep priority=120 | sed 's/table=..//' | sort], 0, -[ (ls_in_stateful ), priority=120 , match=(ct.new && ip4.dst == 10.0.0.10 && tcp.dst == 80), action=(reg1 = 10.0.0.10; reg2[[0..15]] = 80; ct_lb(backends=10.0.0.3:80);) - (ls_in_stateful ), priority=120 , match=(ct.new && ip4.dst == 10.0.0.40 && tcp.dst == 1000), action=(reg1 = 10.0.0.40; reg2[[0..15]] = 1000; ct_lb(backends=10.0.0.3:1000);) +[ (ls_in_lb ), priority=120 , match=(ct.new && ip4.dst == 10.0.0.10 && tcp.dst == 80), action=(reg0[[1]] = 0; reg1 = 10.0.0.10; reg2[[0..15]] = 80; ct_lb(backends=10.0.0.3:80);) + (ls_in_lb ), priority=120 , match=(ct.new && ip4.dst == 10.0.0.40 && tcp.dst == 1000), action=(reg0[[1]] = 0; reg1 = 10.0.0.40; reg2[[0..15]] = 1000; ct_lb(backends=10.0.0.3:1000);) ]) AS_BOX([Set the service monitor for sw1-p1 to online]) @@ -1349,8 +1349,8 @@ AT_CAPTURE_FILE([sbflows10]) OVS_WAIT_FOR_OUTPUT( [ovn-sbctl dump-flows sw0 | tee sbflows10 | grep backends | grep priority=120 | sed 's/table=..//' | sort], 0, -[ (ls_in_stateful ), priority=120 , match=(ct.new && ip4.dst == 10.0.0.10 && tcp.dst == 80), action=(reg1 = 10.0.0.10; reg2[[0..15]] = 80; ct_lb(backends=10.0.0.3:80,20.0.0.3:80);) - (ls_in_stateful ), priority=120 , match=(ct.new && ip4.dst == 10.0.0.40 && tcp.dst == 1000), action=(reg1 = 10.0.0.40; reg2[[0..15]] = 1000; ct_lb(backends=10.0.0.3:1000,20.0.0.3:80);) +[ (ls_in_lb ), priority=120 , match=(ct.new && ip4.dst == 10.0.0.10 && tcp.dst == 80), action=(reg0[[1]] = 0; reg1 = 10.0.0.10; reg2[[0..15]] = 80; ct_lb(backends=10.0.0.3:80,20.0.0.3:80);) + (ls_in_lb ), priority=120 , match=(ct.new && ip4.dst == 10.0.0.40 && tcp.dst == 1000), action=(reg0[[1]] = 0; reg1 = 10.0.0.40; reg2[[0..15]] = 1000; ct_lb(backends=10.0.0.3:1000,20.0.0.3:80);) ]) AS_BOX([Associate lb1 to sw1]) @@ -1359,8 +1359,8 @@ AT_CAPTURE_FILE([sbflows11]) OVS_WAIT_FOR_OUTPUT( [ovn-sbctl dump-flows sw1 | tee sbflows11 | grep backends | grep priority=120 | sed 's/table=..//' | sort], 0, [dnl - (ls_in_stateful ), priority=120 , match=(ct.new && ip4.dst == 10.0.0.10 && tcp.dst == 80), action=(reg1 = 10.0.0.10; reg2[[0..15]] = 80; ct_lb(backends=10.0.0.3:80,20.0.0.3:80);) - (ls_in_stateful ), priority=120 , match=(ct.new && ip4.dst == 10.0.0.40 && tcp.dst == 1000), action=(reg1 = 10.0.0.40; reg2[[0..15]] = 1000; ct_lb(backends=10.0.0.3:1000,20.0.0.3:80);) + (ls_in_lb ), priority=120 , match=(ct.new && ip4.dst == 10.0.0.10 && tcp.dst == 80), action=(reg0[[1]] = 0; reg1 = 10.0.0.10; reg2[[0..15]] = 80; ct_lb(backends=10.0.0.3:80,20.0.0.3:80);) + (ls_in_lb ), priority=120 , match=(ct.new && ip4.dst == 10.0.0.40 && tcp.dst == 1000), action=(reg0[[1]] = 0; reg1 = 10.0.0.40; reg2[[0..15]] = 1000; ct_lb(backends=10.0.0.3:1000,20.0.0.3:80);) ]) AS_BOX([Now create lb2 same as lb1 but udp protocol.]) @@ -1417,7 +1417,7 @@ ovn-sbctl set service_monitor $sm_sw1_p1 status=offline AT_CAPTURE_FILE([sbflows12]) OVS_WAIT_FOR_OUTPUT( [ovn-sbctl dump-flows sw0 | tee sbflows12 | grep "ip4.dst == 10.0.0.10 && tcp.dst == 80" | grep priority=120 | sed 's/table=..//'], [0], [dnl - (ls_in_stateful ), priority=120 , match=(ct.new && ip4.dst == 10.0.0.10 && tcp.dst == 80), action=(reg0 = 0; reject { outport <-> inport; next(pipeline=egress,table=5);};) + (ls_in_lb ), priority=120 , match=(ct.new && ip4.dst == 10.0.0.10 && tcp.dst == 80), action=(reg0 = 0; reject { outport <-> inport; next(pipeline=egress,table=5);};) ]) AT_CLEANUP @@ -2037,9 +2037,9 @@ AT_CAPTURE_FILE([sw1flows]) AT_CHECK( [grep -E 'ls_(in|out)_acl' sw0flows sw1flows | grep pg0 | sort], [0], [dnl -sw0flows: table=4 (ls_out_acl ), priority=2003 , match=(outport == @pg0 && ip6 && udp), action=(reg0 = 0; reject { /* eth.dst <-> eth.src; ip.dst <-> ip.src; is implicit. */ outport <-> inport; next(pipeline=ingress,table=22); };) +sw0flows: table=4 (ls_out_acl ), priority=2003 , match=(outport == @pg0 && ip6 && udp), action=(reg0 = 0; reject { /* eth.dst <-> eth.src; ip.dst <-> ip.src; is implicit. */ outport <-> inport; next(pipeline=ingress,table=24); };) sw0flows: table=9 (ls_in_acl ), priority=2002 , match=(inport == @pg0 && ip4 && tcp && tcp.dst == 80), action=(reg0 = 0; reject { /* eth.dst <-> eth.src; ip.dst <-> ip.src; is implicit. */ outport <-> inport; next(pipeline=egress,table=5); };) -sw1flows: table=4 (ls_out_acl ), priority=2003 , match=(outport == @pg0 && ip6 && udp), action=(reg0 = 0; reject { /* eth.dst <-> eth.src; ip.dst <-> ip.src; is implicit. */ outport <-> inport; next(pipeline=ingress,table=22); };) +sw1flows: table=4 (ls_out_acl ), priority=2003 , match=(outport == @pg0 && ip6 && udp), action=(reg0 = 0; reject { /* eth.dst <-> eth.src; ip.dst <-> ip.src; is implicit. */ outport <-> inport; next(pipeline=ingress,table=24); };) sw1flows: table=9 (ls_in_acl ), priority=2002 , match=(inport == @pg0 && ip4 && tcp && tcp.dst == 80), action=(reg0 = 0; reject { /* eth.dst <-> eth.src; ip.dst <-> ip.src; is implicit. */ outport <-> inport; next(pipeline=egress,table=5); };) ]) @@ -2053,10 +2053,10 @@ ovn-sbctl dump-flows sw1 > sw1flows2 AT_CAPTURE_FILE([sw1flows2]) AT_CHECK([grep "ls_out_acl" sw0flows2 sw1flows2 | grep pg0 | sort], [0], [dnl -sw0flows2: table=4 (ls_out_acl ), priority=2002 , match=(outport == @pg0 && ip4 && udp), action=(reg0 = 0; reject { /* eth.dst <-> eth.src; ip.dst <-> ip.src; is implicit. */ outport <-> inport; next(pipeline=ingress,table=22); };) -sw0flows2: table=4 (ls_out_acl ), priority=2003 , match=(outport == @pg0 && ip6 && udp), action=(reg0 = 0; reject { /* eth.dst <-> eth.src; ip.dst <-> ip.src; is implicit. */ outport <-> inport; next(pipeline=ingress,table=22); };) -sw1flows2: table=4 (ls_out_acl ), priority=2002 , match=(outport == @pg0 && ip4 && udp), action=(reg0 = 0; reject { /* eth.dst <-> eth.src; ip.dst <-> ip.src; is implicit. */ outport <-> inport; next(pipeline=ingress,table=22); };) -sw1flows2: table=4 (ls_out_acl ), priority=2003 , match=(outport == @pg0 && ip6 && udp), action=(reg0 = 0; reject { /* eth.dst <-> eth.src; ip.dst <-> ip.src; is implicit. */ outport <-> inport; next(pipeline=ingress,table=22); };) +sw0flows2: table=4 (ls_out_acl ), priority=2002 , match=(outport == @pg0 && ip4 && udp), action=(reg0 = 0; reject { /* eth.dst <-> eth.src; ip.dst <-> ip.src; is implicit. */ outport <-> inport; next(pipeline=ingress,table=24); };) +sw0flows2: table=4 (ls_out_acl ), priority=2003 , match=(outport == @pg0 && ip6 && udp), action=(reg0 = 0; reject { /* eth.dst <-> eth.src; ip.dst <-> ip.src; is implicit. */ outport <-> inport; next(pipeline=ingress,table=24); };) +sw1flows2: table=4 (ls_out_acl ), priority=2002 , match=(outport == @pg0 && ip4 && udp), action=(reg0 = 0; reject { /* eth.dst <-> eth.src; ip.dst <-> ip.src; is implicit. */ outport <-> inport; next(pipeline=ingress,table=24); };) +sw1flows2: table=4 (ls_out_acl ), priority=2003 , match=(outport == @pg0 && ip6 && udp), action=(reg0 = 0; reject { /* eth.dst <-> eth.src; ip.dst <-> ip.src; is implicit. */ outport <-> inport; next(pipeline=ingress,table=24); };) ]) AS_BOX([3]) @@ -2071,16 +2071,16 @@ AT_CAPTURE_FILE([sw1flows3]) AT_CHECK([grep "ls_out_acl" sw0flows3 sw1flows3 | grep pg0 | sort], [0], [dnl sw0flows3: table=4 (ls_out_acl ), priority=2001 , match=(reg0[[7]] == 1 && (outport == @pg0 && ip)), action=(reg0[[1]] = 1; next;) sw0flows3: table=4 (ls_out_acl ), priority=2001 , match=(reg0[[8]] == 1 && (outport == @pg0 && ip)), action=(next;) -sw0flows3: table=4 (ls_out_acl ), priority=2002 , match=((reg0[[10]] == 1) && outport == @pg0 && ip4 && udp), action=(ct_commit { ct_label.blocked = 1; }; reg0 = 0; reject { /* eth.dst <-> eth.src; ip.dst <-> ip.src; is implicit. */ outport <-> inport; next(pipeline=ingress,table=22); };) -sw0flows3: table=4 (ls_out_acl ), priority=2002 , match=((reg0[[9]] == 1) && outport == @pg0 && ip4 && udp), action=(reg0 = 0; reject { /* eth.dst <-> eth.src; ip.dst <-> ip.src; is implicit. */ outport <-> inport; next(pipeline=ingress,table=22); };) -sw0flows3: table=4 (ls_out_acl ), priority=2003 , match=((reg0[[10]] == 1) && outport == @pg0 && ip6 && udp), action=(ct_commit { ct_label.blocked = 1; }; reg0 = 0; reject { /* eth.dst <-> eth.src; ip.dst <-> ip.src; is implicit. */ outport <-> inport; next(pipeline=ingress,table=22); };) -sw0flows3: table=4 (ls_out_acl ), priority=2003 , match=((reg0[[9]] == 1) && outport == @pg0 && ip6 && udp), action=(reg0 = 0; reject { /* eth.dst <-> eth.src; ip.dst <-> ip.src; is implicit. */ outport <-> inport; next(pipeline=ingress,table=22); };) +sw0flows3: table=4 (ls_out_acl ), priority=2002 , match=((reg0[[10]] == 1) && outport == @pg0 && ip4 && udp), action=(ct_commit { ct_label.blocked = 1; }; reg0 = 0; reject { /* eth.dst <-> eth.src; ip.dst <-> ip.src; is implicit. */ outport <-> inport; next(pipeline=ingress,table=24); };) +sw0flows3: table=4 (ls_out_acl ), priority=2002 , match=((reg0[[9]] == 1) && outport == @pg0 && ip4 && udp), action=(reg0 = 0; reject { /* eth.dst <-> eth.src; ip.dst <-> ip.src; is implicit. */ outport <-> inport; next(pipeline=ingress,table=24); };) +sw0flows3: table=4 (ls_out_acl ), priority=2003 , match=((reg0[[10]] == 1) && outport == @pg0 && ip6 && udp), action=(ct_commit { ct_label.blocked = 1; }; reg0 = 0; reject { /* eth.dst <-> eth.src; ip.dst <-> ip.src; is implicit. */ outport <-> inport; next(pipeline=ingress,table=24); };) +sw0flows3: table=4 (ls_out_acl ), priority=2003 , match=((reg0[[9]] == 1) && outport == @pg0 && ip6 && udp), action=(reg0 = 0; reject { /* eth.dst <-> eth.src; ip.dst <-> ip.src; is implicit. */ outport <-> inport; next(pipeline=ingress,table=24); };) sw1flows3: table=4 (ls_out_acl ), priority=2001 , match=(reg0[[7]] == 1 && (outport == @pg0 && ip)), action=(reg0[[1]] = 1; next;) sw1flows3: table=4 (ls_out_acl ), priority=2001 , match=(reg0[[8]] == 1 && (outport == @pg0 && ip)), action=(next;) -sw1flows3: table=4 (ls_out_acl ), priority=2002 , match=((reg0[[10]] == 1) && outport == @pg0 && ip4 && udp), action=(ct_commit { ct_label.blocked = 1; }; reg0 = 0; reject { /* eth.dst <-> eth.src; ip.dst <-> ip.src; is implicit. */ outport <-> inport; next(pipeline=ingress,table=22); };) -sw1flows3: table=4 (ls_out_acl ), priority=2002 , match=((reg0[[9]] == 1) && outport == @pg0 && ip4 && udp), action=(reg0 = 0; reject { /* eth.dst <-> eth.src; ip.dst <-> ip.src; is implicit. */ outport <-> inport; next(pipeline=ingress,table=22); };) -sw1flows3: table=4 (ls_out_acl ), priority=2003 , match=((reg0[[10]] == 1) && outport == @pg0 && ip6 && udp), action=(ct_commit { ct_label.blocked = 1; }; reg0 = 0; reject { /* eth.dst <-> eth.src; ip.dst <-> ip.src; is implicit. */ outport <-> inport; next(pipeline=ingress,table=22); };) -sw1flows3: table=4 (ls_out_acl ), priority=2003 , match=((reg0[[9]] == 1) && outport == @pg0 && ip6 && udp), action=(reg0 = 0; reject { /* eth.dst <-> eth.src; ip.dst <-> ip.src; is implicit. */ outport <-> inport; next(pipeline=ingress,table=22); };) +sw1flows3: table=4 (ls_out_acl ), priority=2002 , match=((reg0[[10]] == 1) && outport == @pg0 && ip4 && udp), action=(ct_commit { ct_label.blocked = 1; }; reg0 = 0; reject { /* eth.dst <-> eth.src; ip.dst <-> ip.src; is implicit. */ outport <-> inport; next(pipeline=ingress,table=24); };) +sw1flows3: table=4 (ls_out_acl ), priority=2002 , match=((reg0[[9]] == 1) && outport == @pg0 && ip4 && udp), action=(reg0 = 0; reject { /* eth.dst <-> eth.src; ip.dst <-> ip.src; is implicit. */ outport <-> inport; next(pipeline=ingress,table=24); };) +sw1flows3: table=4 (ls_out_acl ), priority=2003 , match=((reg0[[10]] == 1) && outport == @pg0 && ip6 && udp), action=(ct_commit { ct_label.blocked = 1; }; reg0 = 0; reject { /* eth.dst <-> eth.src; ip.dst <-> ip.src; is implicit. */ outport <-> inport; next(pipeline=ingress,table=24); };) +sw1flows3: table=4 (ls_out_acl ), priority=2003 , match=((reg0[[9]] == 1) && outport == @pg0 && ip6 && udp), action=(reg0 = 0; reject { /* eth.dst <-> eth.src; ip.dst <-> ip.src; is implicit. */ outport <-> inport; next(pipeline=ingress,table=24); };) ]) AT_CLEANUP ]) @@ -2240,7 +2240,7 @@ AT_CHECK([ovn-sbctl lflow-list ls | grep -e ls_in_acl_hint -e ls_out_acl_hint -e table=8 (ls_in_acl_hint ), priority=7 , match=(ct.new && !ct.est), action=(reg0[[7]] = 1; reg0[[9]] = 1; next;) table=9 (ls_in_acl ), priority=1 , match=(ip && (!ct.est || (ct.est && ct_label.blocked == 1))), action=(reg0[[1]] = 1; next;) table=9 (ls_in_acl ), priority=65532, match=(!ct.est && ct.rel && !ct.new && !ct.inv && ct_label.blocked == 0), action=(next;) - table=9 (ls_in_acl ), priority=65532, match=(ct.est && !ct.rel && !ct.new && !ct.inv && ct.rpl && ct_label.blocked == 0), action=(next;) + table=9 (ls_in_acl ), priority=65532, match=(ct.est && !ct.rel && !ct.new && !ct.inv && ct.rpl && ct_label.blocked == 0), action=(reg0[[9]] = 0; reg0[[10]] = 0; next;) table=9 (ls_in_acl ), priority=65532, match=(ct.inv || (ct.est && ct.rpl && ct_label.blocked == 1)), action=(drop;) ]) @@ -2252,6 +2252,7 @@ check ovn-nbctl --wait=sb \ -- ls-lb-add ls lb AT_CHECK([ovn-sbctl lflow-list ls | grep -e ls_in_acl_hint -e ls_out_acl_hint -e ls_in_acl -e ls_out_acl | sort], [0], [dnl + table=13(ls_in_acl_after_lb ), priority=0 , match=(1), action=(next;) table=3 (ls_out_acl_hint ), priority=0 , match=(1), action=(next;) table=3 (ls_out_acl_hint ), priority=1 , match=(ct.est && ct_label.blocked == 0), action=(reg0[[10]] = 1; next;) table=3 (ls_out_acl_hint ), priority=2 , match=(ct.est && ct_label.blocked == 1), action=(reg0[[9]] = 1; next;) @@ -2283,7 +2284,7 @@ AT_CHECK([ovn-sbctl lflow-list ls | grep -e ls_in_acl_hint -e ls_out_acl_hint -e table=9 (ls_in_acl ), priority=1001 , match=(reg0[[8]] == 1 && (ip)), action=(next;) table=9 (ls_in_acl ), priority=34000, match=(eth.dst == $svc_monitor_mac), action=(next;) table=9 (ls_in_acl ), priority=65532, match=(!ct.est && ct.rel && !ct.new && !ct.inv && ct_label.blocked == 0), action=(next;) - table=9 (ls_in_acl ), priority=65532, match=(ct.est && !ct.rel && !ct.new && !ct.inv && ct.rpl && ct_label.blocked == 0), action=(next;) + table=9 (ls_in_acl ), priority=65532, match=(ct.est && !ct.rel && !ct.new && !ct.inv && ct.rpl && ct_label.blocked == 0), action=(reg0[[9]] = 0; reg0[[10]] = 0; next;) table=9 (ls_in_acl ), priority=65532, match=(ct.inv || (ct.est && ct.rpl && ct_label.blocked == 1)), action=(drop;) table=9 (ls_in_acl ), priority=65532, match=(nd || nd_ra || nd_rs || mldv1 || mldv2), action=(next;) ]) @@ -2292,6 +2293,7 @@ ovn-nbctl --wait=sb clear logical_switch ls acls ovn-nbctl --wait=sb clear logical_switch ls load_balancer AT_CHECK([ovn-sbctl lflow-list ls | grep -e ls_in_acl_hint -e ls_out_acl_hint -e ls_in_acl -e ls_out_acl | sort], [0], [dnl + table=13(ls_in_acl_after_lb ), priority=0 , match=(1), action=(next;) table=3 (ls_out_acl_hint ), priority=65535, match=(1), action=(next;) table=4 (ls_out_acl ), priority=65535, match=(1), action=(next;) table=8 (ls_in_acl_hint ), priority=65535, match=(1), action=(next;) @@ -2578,56 +2580,56 @@ check ovn-nbctl \ -- ls-lb-add sw0 lb0 check ovn-nbctl --wait=sb sync -AT_CHECK([ovn-sbctl lflow-list sw0 | grep ls_in_pre_hairpin | sort], [0], [dnl - table=13(ls_in_pre_hairpin ), priority=0 , match=(1), action=(next;) - table=13(ls_in_pre_hairpin ), priority=100 , match=(ip && ct.trk), action=(reg0[[6]] = chk_lb_hairpin(); reg0[[12]] = chk_lb_hairpin_reply(); next;) +AT_CHECK([ovn-sbctl lflow-list sw0 | grep ls_in_pre_hairpin | sort | sed 's/table=../table=??/'], [0], [dnl + table=??(ls_in_pre_hairpin ), priority=0 , match=(1), action=(next;) + table=??(ls_in_pre_hairpin ), priority=100 , match=(ip && ct.trk), action=(reg0[[6]] = chk_lb_hairpin(); reg0[[12]] = chk_lb_hairpin_reply(); next;) ]) -AT_CHECK([ovn-sbctl lflow-list sw0 | grep ls_in_nat_hairpin | sort], [0], [dnl - table=14(ls_in_nat_hairpin ), priority=0 , match=(1), action=(next;) - table=14(ls_in_nat_hairpin ), priority=100 , match=(ip && ct.est && ct.trk && reg0[[6]] == 1), action=(ct_snat;) - table=14(ls_in_nat_hairpin ), priority=100 , match=(ip && ct.new && ct.trk && reg0[[6]] == 1), action=(ct_snat_to_vip; next;) - table=14(ls_in_nat_hairpin ), priority=90 , match=(ip && reg0[[12]] == 1), action=(ct_snat;) +AT_CHECK([ovn-sbctl lflow-list sw0 | grep ls_in_nat_hairpin | sort | sed 's/table=../table=??/'], [0], [dnl + table=??(ls_in_nat_hairpin ), priority=0 , match=(1), action=(next;) + table=??(ls_in_nat_hairpin ), priority=100 , match=(ip && ct.est && ct.trk && reg0[[6]] == 1), action=(ct_snat;) + table=??(ls_in_nat_hairpin ), priority=100 , match=(ip && ct.new && ct.trk && reg0[[6]] == 1), action=(ct_snat_to_vip; next;) + table=??(ls_in_nat_hairpin ), priority=90 , match=(ip && reg0[[12]] == 1), action=(ct_snat;) ]) -AT_CHECK([ovn-sbctl lflow-list sw0 | grep ls_in_hairpin | sort], [0], [dnl - table=15(ls_in_hairpin ), priority=0 , match=(1), action=(next;) - table=15(ls_in_hairpin ), priority=1 , match=((reg0[[6]] == 1 || reg0[[12]] == 1)), action=(eth.dst <-> eth.src; outport = inport; flags.loopback = 1; output;) +AT_CHECK([ovn-sbctl lflow-list sw0 | grep ls_in_hairpin | sort | sed 's/table=../table=??/'], [0], [dnl + table=??(ls_in_hairpin ), priority=0 , match=(1), action=(next;) + table=??(ls_in_hairpin ), priority=1 , match=((reg0[[6]] == 1 || reg0[[12]] == 1)), action=(eth.dst <-> eth.src; outport = inport; flags.loopback = 1; output;) ]) check ovn-nbctl -- ls-lb-del sw0 lb0 check ovn-nbctl --wait=sb sync -AT_CHECK([ovn-sbctl lflow-list sw0 | grep ls_in_pre_hairpin | sort], [0], [dnl - table=13(ls_in_pre_hairpin ), priority=0 , match=(1), action=(next;) +AT_CHECK([ovn-sbctl lflow-list sw0 | grep ls_in_pre_hairpin | sort | sed 's/table=../table=??/'], [0], [dnl + table=??(ls_in_pre_hairpin ), priority=0 , match=(1), action=(next;) ]) -AT_CHECK([ovn-sbctl lflow-list sw0 | grep ls_in_nat_hairpin | sort], [0], [dnl - table=14(ls_in_nat_hairpin ), priority=0 , match=(1), action=(next;) +AT_CHECK([ovn-sbctl lflow-list sw0 | grep ls_in_nat_hairpin | sort | sed 's/table=../table=??/'], [0], [dnl + table=??(ls_in_nat_hairpin ), priority=0 , match=(1), action=(next;) ]) -AT_CHECK([ovn-sbctl lflow-list sw0 | grep ls_in_hairpin | sort], [0], [dnl - table=15(ls_in_hairpin ), priority=0 , match=(1), action=(next;) +AT_CHECK([ovn-sbctl lflow-list sw0 | grep ls_in_hairpin | sort | sed 's/table=../table=??/'], [0], [dnl + table=??(ls_in_hairpin ), priority=0 , match=(1), action=(next;) ]) check ovn-nbctl -- add load_balancer_group $lbg load_balancer $lb0 check ovn-nbctl --wait=sb sync -AT_CHECK([ovn-sbctl lflow-list sw0 | grep ls_in_pre_hairpin | sort], [0], [dnl - table=13(ls_in_pre_hairpin ), priority=0 , match=(1), action=(next;) - table=13(ls_in_pre_hairpin ), priority=100 , match=(ip && ct.trk), action=(reg0[[6]] = chk_lb_hairpin(); reg0[[12]] = chk_lb_hairpin_reply(); next;) +AT_CHECK([ovn-sbctl lflow-list sw0 | grep ls_in_pre_hairpin | sort | sed 's/table=../table=??/'], [0], [dnl + table=??(ls_in_pre_hairpin ), priority=0 , match=(1), action=(next;) + table=??(ls_in_pre_hairpin ), priority=100 , match=(ip && ct.trk), action=(reg0[[6]] = chk_lb_hairpin(); reg0[[12]] = chk_lb_hairpin_reply(); next;) ]) -AT_CHECK([ovn-sbctl lflow-list sw0 | grep ls_in_nat_hairpin | sort], [0], [dnl - table=14(ls_in_nat_hairpin ), priority=0 , match=(1), action=(next;) - table=14(ls_in_nat_hairpin ), priority=100 , match=(ip && ct.est && ct.trk && reg0[[6]] == 1), action=(ct_snat;) - table=14(ls_in_nat_hairpin ), priority=100 , match=(ip && ct.new && ct.trk && reg0[[6]] == 1), action=(ct_snat_to_vip; next;) - table=14(ls_in_nat_hairpin ), priority=90 , match=(ip && reg0[[12]] == 1), action=(ct_snat;) +AT_CHECK([ovn-sbctl lflow-list sw0 | grep ls_in_nat_hairpin | sort | sed 's/table=../table=??/'], [0], [dnl + table=??(ls_in_nat_hairpin ), priority=0 , match=(1), action=(next;) + table=??(ls_in_nat_hairpin ), priority=100 , match=(ip && ct.est && ct.trk && reg0[[6]] == 1), action=(ct_snat;) + table=??(ls_in_nat_hairpin ), priority=100 , match=(ip && ct.new && ct.trk && reg0[[6]] == 1), action=(ct_snat_to_vip; next;) + table=??(ls_in_nat_hairpin ), priority=90 , match=(ip && reg0[[12]] == 1), action=(ct_snat;) ]) -AT_CHECK([ovn-sbctl lflow-list sw0 | grep ls_in_hairpin | sort], [0], [dnl - table=15(ls_in_hairpin ), priority=0 , match=(1), action=(next;) - table=15(ls_in_hairpin ), priority=1 , match=((reg0[[6]] == 1 || reg0[[12]] == 1)), action=(eth.dst <-> eth.src; outport = inport; flags.loopback = 1; output;) +AT_CHECK([ovn-sbctl lflow-list sw0 | grep ls_in_hairpin | sort | sed 's/table=../table=??/'], [0], [dnl + table=??(ls_in_hairpin ), priority=0 , match=(1), action=(next;) + table=??(ls_in_hairpin ), priority=1 , match=((reg0[[6]] == 1 || reg0[[12]] == 1)), action=(eth.dst <-> eth.src; outport = inport; flags.loopback = 1; output;) ]) AT_CLEANUP @@ -3948,12 +3950,16 @@ check_stateful_flows() { table=7 (ls_in_pre_stateful ), priority=120 , match=(reg0[[2]] == 1 && ip6 && udp), action=(xxreg1 = ip6.dst; reg2[[0..15]] = udp.dst; ct_lb;) ]) + AT_CHECK([grep "ls_in_lb" sw0flows | sort], [0], [dnl + table=12(ls_in_lb ), priority=0 , match=(1), action=(next;) + table=12(ls_in_lb ), priority=120 , match=(ct.new && ip4.dst == 10.0.0.10 && tcp.dst == 80), action=(reg0[[1]] = 0; reg1 = 10.0.0.10; reg2[[0..15]] = 80; ct_lb(backends=10.0.0.4:8080);) + table=12(ls_in_lb ), priority=120 , match=(ct.new && ip4.dst == 10.0.0.20 && tcp.dst == 80), action=(reg0[[1]] = 0; reg1 = 10.0.0.20; reg2[[0..15]] = 80; ct_lb(backends=10.0.0.40:8080);) +]) + AT_CHECK([grep "ls_in_stateful" sw0flows | sort], [0], [dnl - table=12(ls_in_stateful ), priority=0 , match=(1), action=(next;) - table=12(ls_in_stateful ), priority=100 , match=(reg0[[1]] == 1 && reg0[[13]] == 0), action=(ct_commit { ct_label.blocked = 0; }; next;) - table=12(ls_in_stateful ), priority=100 , match=(reg0[[1]] == 1 && reg0[[13]] == 1), action=(ct_commit { ct_label.blocked = 0; ct_label.label = reg3; }; next;) - table=12(ls_in_stateful ), priority=120 , match=(ct.new && ip4.dst == 10.0.0.10 && tcp.dst == 80), action=(reg1 = 10.0.0.10; reg2[[0..15]] = 80; ct_lb(backends=10.0.0.4:8080);) - table=12(ls_in_stateful ), priority=120 , match=(ct.new && ip4.dst == 10.0.0.20 && tcp.dst == 80), action=(reg1 = 10.0.0.20; reg2[[0..15]] = 80; ct_lb(backends=10.0.0.40:8080);) + table=14(ls_in_stateful ), priority=0 , match=(1), action=(next;) + table=14(ls_in_stateful ), priority=100 , match=(reg0[[1]] == 1 && reg0[[13]] == 0), action=(ct_commit { ct_label.blocked = 0; }; next;) + table=14(ls_in_stateful ), priority=100 , match=(reg0[[1]] == 1 && reg0[[13]] == 1), action=(ct_commit { ct_label.blocked = 0; ct_label.label = reg3; }; next;) ]) AT_CHECK([grep "ls_out_pre_lb" sw0flows | sort], [0], [dnl @@ -4016,10 +4022,14 @@ AT_CHECK([grep "ls_in_pre_stateful" sw0flows | sort], [0], [dnl table=7 (ls_in_pre_stateful ), priority=120 , match=(reg0[[2]] == 1 && ip6 && udp), action=(xxreg1 = ip6.dst; reg2[[0..15]] = udp.dst; ct_lb;) ]) +AT_CHECK([grep "ls_in_lb" sw0flows | sort], [0], [dnl + table=12(ls_in_lb ), priority=0 , match=(1), action=(next;) +]) + AT_CHECK([grep "ls_in_stateful" sw0flows | sort], [0], [dnl - table=12(ls_in_stateful ), priority=0 , match=(1), action=(next;) - table=12(ls_in_stateful ), priority=100 , match=(reg0[[1]] == 1 && reg0[[13]] == 0), action=(ct_commit { ct_label.blocked = 0; }; next;) - table=12(ls_in_stateful ), priority=100 , match=(reg0[[1]] == 1 && reg0[[13]] == 1), action=(ct_commit { ct_label.blocked = 0; ct_label.label = reg3; }; next;) + table=14(ls_in_stateful ), priority=0 , match=(1), action=(next;) + table=14(ls_in_stateful ), priority=100 , match=(reg0[[1]] == 1 && reg0[[13]] == 0), action=(ct_commit { ct_label.blocked = 0; }; next;) + table=14(ls_in_stateful ), priority=100 , match=(reg0[[1]] == 1 && reg0[[13]] == 1), action=(ct_commit { ct_label.blocked = 0; ct_label.label = reg3; }; next;) ]) AT_CHECK([grep "ls_out_pre_lb" sw0flows | sort], [0], [dnl @@ -4063,9 +4073,9 @@ AT_CHECK([grep -w "ls_in_acl" sw0flows | grep 2002 | sort], [0], [dnl table=9 (ls_in_acl ), priority=2002 , match=(reg0[[8]] == 1 && (tcp)), action=(reg0[[1]] = 1; reg0[[13]] = 1; reg3 = 1234; next;) ]) AT_CHECK([grep "ls_in_stateful" sw0flows | sort], [0], [dnl - table=12(ls_in_stateful ), priority=0 , match=(1), action=(next;) - table=12(ls_in_stateful ), priority=100 , match=(reg0[[1]] == 1 && reg0[[13]] == 0), action=(ct_commit { ct_label.blocked = 0; }; next;) - table=12(ls_in_stateful ), priority=100 , match=(reg0[[1]] == 1 && reg0[[13]] == 1), action=(ct_commit { ct_label.blocked = 0; ct_label.label = reg3; }; next;) + table=14(ls_in_stateful ), priority=0 , match=(1), action=(next;) + table=14(ls_in_stateful ), priority=100 , match=(reg0[[1]] == 1 && reg0[[13]] == 0), action=(ct_commit { ct_label.blocked = 0; }; next;) + table=14(ls_in_stateful ), priority=100 , match=(reg0[[1]] == 1 && reg0[[13]] == 1), action=(ct_commit { ct_label.blocked = 0; ct_label.label = reg3; }; next;) ]) AT_CHECK([grep -w "ls_out_acl" sw0flows | grep 2002 | sort], [0], [dnl @@ -4092,9 +4102,9 @@ AT_CHECK([grep -w "ls_in_acl" sw0flows | grep 2002 | sort], [0], [dnl table=9 (ls_in_acl ), priority=2002 , match=(reg0[[8]] == 1 && (udp)), action=(next;) ]) AT_CHECK([grep "ls_in_stateful" sw0flows | sort], [0], [dnl - table=12(ls_in_stateful ), priority=0 , match=(1), action=(next;) - table=12(ls_in_stateful ), priority=100 , match=(reg0[[1]] == 1 && reg0[[13]] == 0), action=(ct_commit { ct_label.blocked = 0; }; next;) - table=12(ls_in_stateful ), priority=100 , match=(reg0[[1]] == 1 && reg0[[13]] == 1), action=(ct_commit { ct_label.blocked = 0; ct_label.label = reg3; }; next;) + table=14(ls_in_stateful ), priority=0 , match=(1), action=(next;) + table=14(ls_in_stateful ), priority=100 , match=(reg0[[1]] == 1 && reg0[[13]] == 0), action=(ct_commit { ct_label.blocked = 0; }; next;) + table=14(ls_in_stateful ), priority=100 , match=(reg0[[1]] == 1 && reg0[[13]] == 1), action=(ct_commit { ct_label.blocked = 0; ct_label.label = reg3; }; next;) ]) AT_CHECK([grep -w "ls_out_acl" sw0flows | grep 2002 | sort], [0], [dnl @@ -4121,9 +4131,9 @@ AT_CHECK([grep -w "ls_in_acl" sw0flows | grep 2002 | sort], [0], [dnl table=9 (ls_in_acl ), priority=2002 , match=(reg0[[8]] == 1 && (udp)), action=(next;) ]) AT_CHECK([grep "ls_in_stateful" sw0flows | sort], [0], [dnl - table=12(ls_in_stateful ), priority=0 , match=(1), action=(next;) - table=12(ls_in_stateful ), priority=100 , match=(reg0[[1]] == 1 && reg0[[13]] == 0), action=(ct_commit { ct_label.blocked = 0; }; next;) - table=12(ls_in_stateful ), priority=100 , match=(reg0[[1]] == 1 && reg0[[13]] == 1), action=(ct_commit { ct_label.blocked = 0; ct_label.label = reg3; }; next;) + table=14(ls_in_stateful ), priority=0 , match=(1), action=(next;) + table=14(ls_in_stateful ), priority=100 , match=(reg0[[1]] == 1 && reg0[[13]] == 0), action=(ct_commit { ct_label.blocked = 0; }; next;) + table=14(ls_in_stateful ), priority=100 , match=(reg0[[1]] == 1 && reg0[[13]] == 1), action=(ct_commit { ct_label.blocked = 0; ct_label.label = reg3; }; next;) ]) AT_CHECK([grep -w "ls_out_acl" sw0flows | grep 2002 | sort], [0], [dnl @@ -4152,7 +4162,7 @@ AT_CAPTURE_FILE([sw0flows]) AT_CHECK([grep -w "ls_in_acl" sw0flows | grep 6553 | sort], [0], [dnl table=9 (ls_in_acl ), priority=65532, match=(!ct.est && ct.rel && !ct.new && !ct.inv && ct_label.blocked == 0), action=(next;) - table=9 (ls_in_acl ), priority=65532, match=(ct.est && !ct.rel && !ct.new && !ct.inv && ct.rpl && ct_label.blocked == 0), action=(next;) + table=9 (ls_in_acl ), priority=65532, match=(ct.est && !ct.rel && !ct.new && !ct.inv && ct.rpl && ct_label.blocked == 0), action=(reg0[[9]] = 0; reg0[[10]] = 0; next;) table=9 (ls_in_acl ), priority=65532, match=(ct.inv || (ct.est && ct.rpl && ct_label.blocked == 1)), action=(drop;) table=9 (ls_in_acl ), priority=65532, match=(nd || nd_ra || nd_rs || mldv1 || mldv2), action=(next;) ]) @@ -4173,7 +4183,7 @@ AT_CAPTURE_FILE([sw0flows]) AT_CHECK([grep -w "ls_in_acl" sw0flows | grep 6553 | sort], [0], [dnl table=9 (ls_in_acl ), priority=65532, match=(!ct.est && ct.rel && !ct.new && ct_label.blocked == 0), action=(next;) table=9 (ls_in_acl ), priority=65532, match=((ct.est && ct.rpl && ct_label.blocked == 1)), action=(drop;) - table=9 (ls_in_acl ), priority=65532, match=(ct.est && !ct.rel && !ct.new && ct.rpl && ct_label.blocked == 0), action=(next;) + table=9 (ls_in_acl ), priority=65532, match=(ct.est && !ct.rel && !ct.new && ct.rpl && ct_label.blocked == 0), action=(reg0[[9]] = 0; reg0[[10]] = 0; next;) table=9 (ls_in_acl ), priority=65532, match=(nd || nd_ra || nd_rs || mldv1 || mldv2), action=(next;) ]) @@ -4196,7 +4206,7 @@ AT_CAPTURE_FILE([sw0flows]) AT_CHECK([grep -w "ls_in_acl" sw0flows | grep 6553 | sort], [0], [dnl table=9 (ls_in_acl ), priority=65532, match=(!ct.est && ct.rel && !ct.new && !ct.inv && ct_label.blocked == 0), action=(next;) - table=9 (ls_in_acl ), priority=65532, match=(ct.est && !ct.rel && !ct.new && !ct.inv && ct.rpl && ct_label.blocked == 0), action=(next;) + table=9 (ls_in_acl ), priority=65532, match=(ct.est && !ct.rel && !ct.new && !ct.inv && ct.rpl && ct_label.blocked == 0), action=(reg0[[9]] = 0; reg0[[10]] = 0; next;) table=9 (ls_in_acl ), priority=65532, match=(ct.inv || (ct.est && ct.rpl && ct_label.blocked == 1)), action=(drop;) table=9 (ls_in_acl ), priority=65532, match=(nd || nd_ra || nd_rs || mldv1 || mldv2), action=(next;) ]) @@ -4368,20 +4378,20 @@ ovn-nbctl --wait=sb lsp-set-dhcpv4-options sw0-port1 $CIDR_UUID ovn-sbctl dump-flows sw0 > sw0flows AT_CAPTURE_FILE([sw0flows]) -AT_CHECK([grep -w "ls_in_dhcp_options" sw0flows | sort], [0], [dnl - table=17(ls_in_dhcp_options ), priority=0 , match=(1), action=(next;) - table=17(ls_in_dhcp_options ), priority=100 , match=(inport == "sw0-port1" && eth.src == 50:54:00:00:00:01 && ip4.src == 0.0.0.0 && ip4.dst == 255.255.255.255 && udp.src == 68 && udp.dst == 67), action=(reg0[[3]] = put_dhcp_opts(offerip = 10.0.0.2, hostname = "foo", lease_time = 3600, netmask = 255.255.255.0, router = 10.0.0.1, server_id = 10.0.0.1); next;) - table=17(ls_in_dhcp_options ), priority=100 , match=(inport == "sw0-port1" && eth.src == 50:54:00:00:00:01 && ip4.src == 10.0.0.2 && ip4.dst == {10.0.0.1, 255.255.255.255} && udp.src == 68 && udp.dst == 67), action=(reg0[[3]] = put_dhcp_opts(offerip = 10.0.0.2, hostname = "foo", lease_time = 3600, netmask = 255.255.255.0, router = 10.0.0.1, server_id = 10.0.0.1); next;) +AT_CHECK([grep -w "ls_in_dhcp_options" sw0flows | sort | sed 's/table=../table=??/'], [0], [dnl + table=??(ls_in_dhcp_options ), priority=0 , match=(1), action=(next;) + table=??(ls_in_dhcp_options ), priority=100 , match=(inport == "sw0-port1" && eth.src == 50:54:00:00:00:01 && ip4.src == 0.0.0.0 && ip4.dst == 255.255.255.255 && udp.src == 68 && udp.dst == 67), action=(reg0[[3]] = put_dhcp_opts(offerip = 10.0.0.2, hostname = "foo", lease_time = 3600, netmask = 255.255.255.0, router = 10.0.0.1, server_id = 10.0.0.1); next;) + table=??(ls_in_dhcp_options ), priority=100 , match=(inport == "sw0-port1" && eth.src == 50:54:00:00:00:01 && ip4.src == 10.0.0.2 && ip4.dst == {10.0.0.1, 255.255.255.255} && udp.src == 68 && udp.dst == 67), action=(reg0[[3]] = put_dhcp_opts(offerip = 10.0.0.2, hostname = "foo", lease_time = 3600, netmask = 255.255.255.0, router = 10.0.0.1, server_id = 10.0.0.1); next;) ]) check ovn-nbctl --wait=sb lsp-set-options sw0-port1 hostname="\"port1\"" ovn-sbctl dump-flows sw0 > sw0flows AT_CAPTURE_FILE([sw0flows]) -AT_CHECK([grep -w "ls_in_dhcp_options" sw0flows | sort], [0], [dnl - table=17(ls_in_dhcp_options ), priority=0 , match=(1), action=(next;) - table=17(ls_in_dhcp_options ), priority=100 , match=(inport == "sw0-port1" && eth.src == 50:54:00:00:00:01 && ip4.src == 0.0.0.0 && ip4.dst == 255.255.255.255 && udp.src == 68 && udp.dst == 67), action=(reg0[[3]] = put_dhcp_opts(offerip = 10.0.0.2, hostname = "port1", lease_time = 3600, netmask = 255.255.255.0, router = 10.0.0.1, server_id = 10.0.0.1); next;) - table=17(ls_in_dhcp_options ), priority=100 , match=(inport == "sw0-port1" && eth.src == 50:54:00:00:00:01 && ip4.src == 10.0.0.2 && ip4.dst == {10.0.0.1, 255.255.255.255} && udp.src == 68 && udp.dst == 67), action=(reg0[[3]] = put_dhcp_opts(offerip = 10.0.0.2, hostname = "port1", lease_time = 3600, netmask = 255.255.255.0, router = 10.0.0.1, server_id = 10.0.0.1); next;) +AT_CHECK([grep -w "ls_in_dhcp_options" sw0flows | sort | sed 's/table=../table=??/'], [0], [dnl + table=??(ls_in_dhcp_options ), priority=0 , match=(1), action=(next;) + table=??(ls_in_dhcp_options ), priority=100 , match=(inport == "sw0-port1" && eth.src == 50:54:00:00:00:01 && ip4.src == 0.0.0.0 && ip4.dst == 255.255.255.255 && udp.src == 68 && udp.dst == 67), action=(reg0[[3]] = put_dhcp_opts(offerip = 10.0.0.2, hostname = "port1", lease_time = 3600, netmask = 255.255.255.0, router = 10.0.0.1, server_id = 10.0.0.1); next;) + table=??(ls_in_dhcp_options ), priority=100 , match=(inport == "sw0-port1" && eth.src == 50:54:00:00:00:01 && ip4.src == 10.0.0.2 && ip4.dst == {10.0.0.1, 255.255.255.255} && udp.src == 68 && udp.dst == 67), action=(reg0[[3]] = put_dhcp_opts(offerip = 10.0.0.2, hostname = "port1", lease_time = 3600, netmask = 255.255.255.0, router = 10.0.0.1, server_id = 10.0.0.1); next;) ]) ovn-nbctl dhcp-options-set-options $CIDR_UUID lease_time=3600 router=10.0.0.1 server_id=10.0.0.1 server_mac=c0:ff:ee:00:00:01 @@ -4389,10 +4399,10 @@ check ovn-nbctl --wait=sb lsp-set-options sw0-port1 hostname="\"bar\"" ovn-sbctl dump-flows sw0 > sw0flows AT_CAPTURE_FILE([sw0flows]) -AT_CHECK([grep -w "ls_in_dhcp_options" sw0flows | sort], [0], [dnl - table=17(ls_in_dhcp_options ), priority=0 , match=(1), action=(next;) - table=17(ls_in_dhcp_options ), priority=100 , match=(inport == "sw0-port1" && eth.src == 50:54:00:00:00:01 && ip4.src == 0.0.0.0 && ip4.dst == 255.255.255.255 && udp.src == 68 && udp.dst == 67), action=(reg0[[3]] = put_dhcp_opts(offerip = 10.0.0.2, hostname = "bar", lease_time = 3600, netmask = 255.255.255.0, router = 10.0.0.1, server_id = 10.0.0.1); next;) - table=17(ls_in_dhcp_options ), priority=100 , match=(inport == "sw0-port1" && eth.src == 50:54:00:00:00:01 && ip4.src == 10.0.0.2 && ip4.dst == {10.0.0.1, 255.255.255.255} && udp.src == 68 && udp.dst == 67), action=(reg0[[3]] = put_dhcp_opts(offerip = 10.0.0.2, hostname = "bar", lease_time = 3600, netmask = 255.255.255.0, router = 10.0.0.1, server_id = 10.0.0.1); next;) +AT_CHECK([grep -w "ls_in_dhcp_options" sw0flows | sort | sed 's/table=../table=??/'], [0], [dnl + table=??(ls_in_dhcp_options ), priority=0 , match=(1), action=(next;) + table=??(ls_in_dhcp_options ), priority=100 , match=(inport == "sw0-port1" && eth.src == 50:54:00:00:00:01 && ip4.src == 0.0.0.0 && ip4.dst == 255.255.255.255 && udp.src == 68 && udp.dst == 67), action=(reg0[[3]] = put_dhcp_opts(offerip = 10.0.0.2, hostname = "bar", lease_time = 3600, netmask = 255.255.255.0, router = 10.0.0.1, server_id = 10.0.0.1); next;) + table=??(ls_in_dhcp_options ), priority=100 , match=(inport == "sw0-port1" && eth.src == 50:54:00:00:00:01 && ip4.src == 10.0.0.2 && ip4.dst == {10.0.0.1, 255.255.255.255} && udp.src == 68 && udp.dst == 67), action=(reg0[[3]] = put_dhcp_opts(offerip = 10.0.0.2, hostname = "bar", lease_time = 3600, netmask = 255.255.255.0, router = 10.0.0.1, server_id = 10.0.0.1); next;) ]) AT_CLEANUP @@ -6249,3 +6259,170 @@ check_log_flows_count 0 in AT_CLEANUP ]) + +AT_SETUP([ACLs after lb]) +AT_KEYWORDS([acl]) +ovn_start + +check ovn-nbctl --wait=sb \ + -- ls-add ls \ + -- lsp-add ls lsp + +check ovn-nbctl pg-add pg0 lsp + +check ovn-nbctl acl-add pg0 from-lport 1004 "ip4 && ip4.dst == 10.0.0.2" drop +check ovn-nbctl acl-add pg0 from-lport 1002 "ip4 && tcp" allow-related +check ovn-nbctl acl-add pg0 from-lport 1003 "ip4 && icmp" allow-related +check ovn-nbctl acl-add pg0 from-lport 1001 "ip4" drop + +check ovn-nbctl lb-add lb0 10.0.0.2 10.0.0.10 +check ovn-nbctl ls-lb-add ls lb0 +check ovn-nbctl --wait=sb sync + +ovn-sbctl dump-flows ls > lsflows +AT_CAPTURE_FILE([lsflows]) + +AT_CHECK([grep -e "ls_in_acl" lsflows | sed 's/table=../table=??/' | sort], [0], [dnl + table=??(ls_in_acl ), priority=0 , match=(1), action=(next;) + table=??(ls_in_acl ), priority=1 , match=(ip && (!ct.est || (ct.est && ct_label.blocked == 1))), action=(reg0[[1]] = 1; next;) + table=??(ls_in_acl ), priority=2001 , match=(reg0[[10]] == 1 && (ip4)), action=(ct_commit { ct_label.blocked = 1; }; /* drop */) + table=??(ls_in_acl ), priority=2001 , match=(reg0[[9]] == 1 && (ip4)), action=(/* drop */) + table=??(ls_in_acl ), priority=2002 , match=(reg0[[7]] == 1 && (ip4 && tcp)), action=(reg0[[1]] = 1; next;) + table=??(ls_in_acl ), priority=2002 , match=(reg0[[8]] == 1 && (ip4 && tcp)), action=(next;) + table=??(ls_in_acl ), priority=2003 , match=(reg0[[7]] == 1 && (ip4 && icmp)), action=(reg0[[1]] = 1; next;) + table=??(ls_in_acl ), priority=2003 , match=(reg0[[8]] == 1 && (ip4 && icmp)), action=(next;) + table=??(ls_in_acl ), priority=2004 , match=(reg0[[10]] == 1 && (ip4 && ip4.dst == 10.0.0.2)), action=(ct_commit { ct_label.blocked = 1; }; /* drop */) + table=??(ls_in_acl ), priority=2004 , match=(reg0[[9]] == 1 && (ip4 && ip4.dst == 10.0.0.2)), action=(/* drop */) + table=??(ls_in_acl ), priority=34000, match=(eth.dst == $svc_monitor_mac), action=(next;) + table=??(ls_in_acl ), priority=65532, match=(!ct.est && ct.rel && !ct.new && !ct.inv && ct_label.blocked == 0), action=(next;) + table=??(ls_in_acl ), priority=65532, match=(ct.est && !ct.rel && !ct.new && !ct.inv && ct.rpl && ct_label.blocked == 0), action=(reg0[[9]] = 0; reg0[[10]] = 0; next;) + table=??(ls_in_acl ), priority=65532, match=(ct.inv || (ct.est && ct.rpl && ct_label.blocked == 1)), action=(drop;) + table=??(ls_in_acl ), priority=65532, match=(nd || nd_ra || nd_rs || mldv1 || mldv2), action=(next;) + table=??(ls_in_acl_after_lb ), priority=0 , match=(1), action=(next;) + table=??(ls_in_acl_hint ), priority=0 , match=(1), action=(next;) + table=??(ls_in_acl_hint ), priority=1 , match=(ct.est && ct_label.blocked == 0), action=(reg0[[10]] = 1; next;) + table=??(ls_in_acl_hint ), priority=2 , match=(ct.est && ct_label.blocked == 1), action=(reg0[[9]] = 1; next;) + table=??(ls_in_acl_hint ), priority=3 , match=(!ct.est), action=(reg0[[9]] = 1; next;) + table=??(ls_in_acl_hint ), priority=4 , match=(!ct.new && ct.est && !ct.rpl && ct_label.blocked == 0), action=(reg0[[8]] = 1; reg0[[10]] = 1; next;) + table=??(ls_in_acl_hint ), priority=5 , match=(!ct.trk), action=(reg0[[8]] = 1; reg0[[9]] = 1; next;) + table=??(ls_in_acl_hint ), priority=6 , match=(!ct.new && ct.est && !ct.rpl && ct_label.blocked == 1), action=(reg0[[7]] = 1; reg0[[9]] = 1; next;) + table=??(ls_in_acl_hint ), priority=7 , match=(ct.new && !ct.est), action=(reg0[[7]] = 1; reg0[[9]] = 1; next;) +]) + +AT_CHECK([grep -e "ls_in_lb" lsflows | sed 's/table=../table=??/' | sort], [0], [dnl + table=??(ls_in_lb ), priority=0 , match=(1), action=(next;) + table=??(ls_in_lb ), priority=110 , match=(ct.new && ip4.dst == 10.0.0.2), action=(reg0[[1]] = 0; reg1 = 10.0.0.2; ct_lb(backends=10.0.0.10);) +]) + +AT_CHECK([grep -e "ls_in_stateful" lsflows | sed 's/table=../table=??/' | sort], [0], [dnl + table=??(ls_in_stateful ), priority=0 , match=(1), action=(next;) + table=??(ls_in_stateful ), priority=100 , match=(reg0[[1]] == 1 && reg0[[13]] == 0), action=(ct_commit { ct_label.blocked = 0; }; next;) + table=??(ls_in_stateful ), priority=100 , match=(reg0[[1]] == 1 && reg0[[13]] == 1), action=(ct_commit { ct_label.blocked = 0; ct_label.label = reg3; }; next;) +]) + +AS_BOX([Remove and add the ACLs back with the apply-after-lb option]) + +check ovn-nbctl clear port_group . acls + +check ovn-nbctl --apply-after-lb acl-add pg0 from-lport 1004 "ip4 && ip4.dst == 10.0.0.2" drop +check ovn-nbctl --apply-after-lb acl-add pg0 from-lport 1002 "ip4 && tcp" allow-related +check ovn-nbctl --apply-after-lb acl-add pg0 from-lport 1003 "ip4 && icmp" allow-related +check ovn-nbctl --apply-after-lb acl-add pg0 from-lport 1001 "ip4" drop + +check ovn-nbctl --wait=sb sync + +ovn-sbctl dump-flows ls > lsflows +AT_CAPTURE_FILE([lsflows]) + +AT_CHECK([grep -e "ls_in_acl" lsflows | sed 's/table=../table=??/' | sort], [0], [dnl + table=??(ls_in_acl ), priority=0 , match=(1), action=(next;) + table=??(ls_in_acl ), priority=1 , match=(ip && (!ct.est || (ct.est && ct_label.blocked == 1))), action=(reg0[[1]] = 1; next;) + table=??(ls_in_acl ), priority=34000, match=(eth.dst == $svc_monitor_mac), action=(next;) + table=??(ls_in_acl ), priority=65532, match=(!ct.est && ct.rel && !ct.new && !ct.inv && ct_label.blocked == 0), action=(next;) + table=??(ls_in_acl ), priority=65532, match=(ct.est && !ct.rel && !ct.new && !ct.inv && ct.rpl && ct_label.blocked == 0), action=(reg0[[9]] = 0; reg0[[10]] = 0; next;) + table=??(ls_in_acl ), priority=65532, match=(ct.inv || (ct.est && ct.rpl && ct_label.blocked == 1)), action=(drop;) + table=??(ls_in_acl ), priority=65532, match=(nd || nd_ra || nd_rs || mldv1 || mldv2), action=(next;) + table=??(ls_in_acl_after_lb ), priority=0 , match=(1), action=(next;) + table=??(ls_in_acl_after_lb ), priority=2001 , match=(reg0[[10]] == 1 && (ip4)), action=(ct_commit { ct_label.blocked = 1; }; /* drop */) + table=??(ls_in_acl_after_lb ), priority=2001 , match=(reg0[[9]] == 1 && (ip4)), action=(/* drop */) + table=??(ls_in_acl_after_lb ), priority=2002 , match=(reg0[[7]] == 1 && (ip4 && tcp)), action=(reg0[[1]] = 1; next;) + table=??(ls_in_acl_after_lb ), priority=2002 , match=(reg0[[8]] == 1 && (ip4 && tcp)), action=(next;) + table=??(ls_in_acl_after_lb ), priority=2003 , match=(reg0[[7]] == 1 && (ip4 && icmp)), action=(reg0[[1]] = 1; next;) + table=??(ls_in_acl_after_lb ), priority=2003 , match=(reg0[[8]] == 1 && (ip4 && icmp)), action=(next;) + table=??(ls_in_acl_after_lb ), priority=2004 , match=(reg0[[10]] == 1 && (ip4 && ip4.dst == 10.0.0.2)), action=(ct_commit { ct_label.blocked = 1; }; /* drop */) + table=??(ls_in_acl_after_lb ), priority=2004 , match=(reg0[[9]] == 1 && (ip4 && ip4.dst == 10.0.0.2)), action=(/* drop */) + table=??(ls_in_acl_hint ), priority=0 , match=(1), action=(next;) + table=??(ls_in_acl_hint ), priority=1 , match=(ct.est && ct_label.blocked == 0), action=(reg0[[10]] = 1; next;) + table=??(ls_in_acl_hint ), priority=2 , match=(ct.est && ct_label.blocked == 1), action=(reg0[[9]] = 1; next;) + table=??(ls_in_acl_hint ), priority=3 , match=(!ct.est), action=(reg0[[9]] = 1; next;) + table=??(ls_in_acl_hint ), priority=4 , match=(!ct.new && ct.est && !ct.rpl && ct_label.blocked == 0), action=(reg0[[8]] = 1; reg0[[10]] = 1; next;) + table=??(ls_in_acl_hint ), priority=5 , match=(!ct.trk), action=(reg0[[8]] = 1; reg0[[9]] = 1; next;) + table=??(ls_in_acl_hint ), priority=6 , match=(!ct.new && ct.est && !ct.rpl && ct_label.blocked == 1), action=(reg0[[7]] = 1; reg0[[9]] = 1; next;) + table=??(ls_in_acl_hint ), priority=7 , match=(ct.new && !ct.est), action=(reg0[[7]] = 1; reg0[[9]] = 1; next;) +]) + +AT_CHECK([grep -e "ls_in_lb" lsflows | sed 's/table=../table=??/' | sort], [0], [dnl + table=??(ls_in_lb ), priority=0 , match=(1), action=(next;) + table=??(ls_in_lb ), priority=110 , match=(ct.new && ip4.dst == 10.0.0.2), action=(reg0[[1]] = 0; reg1 = 10.0.0.2; ct_lb(backends=10.0.0.10);) +]) + +AT_CHECK([grep -e "ls_in_stateful" lsflows | sed 's/table=../table=??/' | sort], [0], [dnl + table=??(ls_in_stateful ), priority=0 , match=(1), action=(next;) + table=??(ls_in_stateful ), priority=100 , match=(reg0[[1]] == 1 && reg0[[13]] == 0), action=(ct_commit { ct_label.blocked = 0; }; next;) + table=??(ls_in_stateful ), priority=100 , match=(reg0[[1]] == 1 && reg0[[13]] == 1), action=(ct_commit { ct_label.blocked = 0; ct_label.label = reg3; }; next;) +]) + +AS_BOX([Remove and add the ACLs back with a few ACLs with apply-after-lb option]) + +check ovn-nbctl clear port_group . acls + +check ovn-nbctl --apply-after-lb acl-add pg0 from-lport 1004 "ip4 && ip4.dst == 10.0.0.2" drop +check ovn-nbctl acl-add pg0 from-lport 1002 "ip4 && tcp" allow-related +check ovn-nbctl acl-add pg0 from-lport 1003 "ip4 && icmp" allow-related +check ovn-nbctl --apply-after-lb acl-add pg0 from-lport 1001 "ip4" drop + +check ovn-nbctl --wait=sb sync + +ovn-sbctl dump-flows ls > lsflows +AT_CAPTURE_FILE([lsflows]) + +AT_CHECK([grep -e "ls_in_acl" lsflows | sed 's/table=../table=??/' | sort], [0], [dnl + table=??(ls_in_acl ), priority=0 , match=(1), action=(next;) + table=??(ls_in_acl ), priority=1 , match=(ip && (!ct.est || (ct.est && ct_label.blocked == 1))), action=(reg0[[1]] = 1; next;) + table=??(ls_in_acl ), priority=2002 , match=(reg0[[7]] == 1 && (ip4 && tcp)), action=(reg0[[1]] = 1; next;) + table=??(ls_in_acl ), priority=2002 , match=(reg0[[8]] == 1 && (ip4 && tcp)), action=(next;) + table=??(ls_in_acl ), priority=2003 , match=(reg0[[7]] == 1 && (ip4 && icmp)), action=(reg0[[1]] = 1; next;) + table=??(ls_in_acl ), priority=2003 , match=(reg0[[8]] == 1 && (ip4 && icmp)), action=(next;) + table=??(ls_in_acl ), priority=34000, match=(eth.dst == $svc_monitor_mac), action=(next;) + table=??(ls_in_acl ), priority=65532, match=(!ct.est && ct.rel && !ct.new && !ct.inv && ct_label.blocked == 0), action=(next;) + table=??(ls_in_acl ), priority=65532, match=(ct.est && !ct.rel && !ct.new && !ct.inv && ct.rpl && ct_label.blocked == 0), action=(reg0[[9]] = 0; reg0[[10]] = 0; next;) + table=??(ls_in_acl ), priority=65532, match=(ct.inv || (ct.est && ct.rpl && ct_label.blocked == 1)), action=(drop;) + table=??(ls_in_acl ), priority=65532, match=(nd || nd_ra || nd_rs || mldv1 || mldv2), action=(next;) + table=??(ls_in_acl_after_lb ), priority=0 , match=(1), action=(next;) + table=??(ls_in_acl_after_lb ), priority=2001 , match=(reg0[[10]] == 1 && (ip4)), action=(ct_commit { ct_label.blocked = 1; }; /* drop */) + table=??(ls_in_acl_after_lb ), priority=2001 , match=(reg0[[9]] == 1 && (ip4)), action=(/* drop */) + table=??(ls_in_acl_after_lb ), priority=2004 , match=(reg0[[10]] == 1 && (ip4 && ip4.dst == 10.0.0.2)), action=(ct_commit { ct_label.blocked = 1; }; /* drop */) + table=??(ls_in_acl_after_lb ), priority=2004 , match=(reg0[[9]] == 1 && (ip4 && ip4.dst == 10.0.0.2)), action=(/* drop */) + table=??(ls_in_acl_hint ), priority=0 , match=(1), action=(next;) + table=??(ls_in_acl_hint ), priority=1 , match=(ct.est && ct_label.blocked == 0), action=(reg0[[10]] = 1; next;) + table=??(ls_in_acl_hint ), priority=2 , match=(ct.est && ct_label.blocked == 1), action=(reg0[[9]] = 1; next;) + table=??(ls_in_acl_hint ), priority=3 , match=(!ct.est), action=(reg0[[9]] = 1; next;) + table=??(ls_in_acl_hint ), priority=4 , match=(!ct.new && ct.est && !ct.rpl && ct_label.blocked == 0), action=(reg0[[8]] = 1; reg0[[10]] = 1; next;) + table=??(ls_in_acl_hint ), priority=5 , match=(!ct.trk), action=(reg0[[8]] = 1; reg0[[9]] = 1; next;) + table=??(ls_in_acl_hint ), priority=6 , match=(!ct.new && ct.est && !ct.rpl && ct_label.blocked == 1), action=(reg0[[7]] = 1; reg0[[9]] = 1; next;) + table=??(ls_in_acl_hint ), priority=7 , match=(ct.new && !ct.est), action=(reg0[[7]] = 1; reg0[[9]] = 1; next;) +]) + +AT_CHECK([grep -e "ls_in_lb" lsflows | sed 's/table=../table=??/' | sort], [0], [dnl + table=??(ls_in_lb ), priority=0 , match=(1), action=(next;) + table=??(ls_in_lb ), priority=110 , match=(ct.new && ip4.dst == 10.0.0.2), action=(reg0[[1]] = 0; reg1 = 10.0.0.2; ct_lb(backends=10.0.0.10);) +]) + +AT_CHECK([grep -e "ls_in_stateful" lsflows | sed 's/table=../table=??/' | sort], [0], [dnl + table=??(ls_in_stateful ), priority=0 , match=(1), action=(next;) + table=??(ls_in_stateful ), priority=100 , match=(reg0[[1]] == 1 && reg0[[13]] == 0), action=(ct_commit { ct_label.blocked = 0; }; next;) + table=??(ls_in_stateful ), priority=100 , match=(reg0[[1]] == 1 && reg0[[13]] == 1), action=(ct_commit { ct_label.blocked = 0; ct_label.label = reg3; }; next;) +]) + +AT_CLEANUP +]) diff --git a/tests/ovn.at b/tests/ovn.at index 69270601ab..a19ab4651d 100644 --- a/tests/ovn.at +++ b/tests/ovn.at @@ -3393,8 +3393,8 @@ wait_for_ports_up ovn-sbctl dump-flows ls > lsflows AT_CAPTURE_FILE([lsflows]) -AT_CHECK([grep -w "ls_in_arp_rsp" lsflows | sort], [0], [dnl - table=16(ls_in_arp_rsp ), priority=0 , match=(1), action=(next;) +AT_CHECK([grep -w "ls_in_arp_rsp" lsflows | sed 's/table=../table=??/' | sort], [0], [dnl + table=??(ls_in_arp_rsp ), priority=0 , match=(1), action=(next;) ]) for i in 1 2; do @@ -3456,8 +3456,8 @@ wait_for_ports_up ovn-sbctl dump-flows ls > lsflows AT_CAPTURE_FILE([lsflows]) -AT_CHECK([grep -w "ls_in_arp_rsp" lsflows | sort], [0], [dnl - table=16(ls_in_arp_rsp ), priority=0 , match=(1), action=(next;) +AT_CHECK([grep -w "ls_in_arp_rsp" lsflows | sed 's/table=../table=??/' | sort], [0], [dnl + table=??(ls_in_arp_rsp ), priority=0 , match=(1), action=(next;) ]) test_nd_na() { @@ -14457,7 +14457,7 @@ ovn-sbctl dump-flows sw0 > sw0-flows AT_CAPTURE_FILE([sw0-flows]) AT_CHECK([grep -E 'ls_(in|out)_acl' sw0-flows |grep reject| sed 's/table=../table=??/' | sort], [0], [dnl - table=??(ls_out_acl ), priority=2002 , match=(ip), action=(reg0 = 0; reject { /* eth.dst <-> eth.src; ip.dst <-> ip.src; is implicit. */ outport <-> inport; next(pipeline=ingress,table=22); };) + table=??(ls_out_acl ), priority=2002 , match=(ip), action=(reg0 = 0; reject { /* eth.dst <-> eth.src; ip.dst <-> ip.src; is implicit. */ outport <-> inport; next(pipeline=ingress,table=24); };) ]) @@ -16348,17 +16348,17 @@ ovs-vsctl set open . external-ids:ovn-bridge-mappings=phys:br-phys AT_CHECK([ovn-sbctl dump-flows ls1 | grep "offerip = 10.0.0.6" | \ wc -l], [0], [0 ]) -AT_CHECK([as hv1 ovs-ofctl dump-flows br-int | grep table=23 | \ +AT_CHECK([as hv1 ovs-ofctl dump-flows br-int | grep table=25 | \ grep controller | grep "0a.00.00.06" | wc -l], [0], [0 ]) -AT_CHECK([as hv2 ovs-ofctl dump-flows br-int | grep table=23 | \ +AT_CHECK([as hv2 ovs-ofctl dump-flows br-int | grep table=25 | \ grep controller | grep "0a.00.00.06" | wc -l], [0], [0 ]) -AT_CHECK([as hv1 ovs-ofctl dump-flows br-int | grep table=23 | \ +AT_CHECK([as hv1 ovs-ofctl dump-flows br-int | grep table=25 | \ grep controller | grep tp_src=546 | grep \ "ae.70.00.00.00.00.00.00.00.00.00.00.00.00.00.06" | wc -l], [0], [0 ]) -AT_CHECK([as hv2 ovs-ofctl dump-flows br-int | grep table=23 | \ +AT_CHECK([as hv2 ovs-ofctl dump-flows br-int | grep table=25 | \ grep controller | grep tp_src=546 | grep \ "ae.70.00.00.00.00.00.00.00.00.00.00.00.00.00.06" | wc -l], [0], [0 ]) @@ -16966,7 +16966,7 @@ wait_for_ports_up ls1-lp_ext1 # There should be a flow in hv2 to drop traffic from ls1-lp_ext1 destined # to router mac. AT_CHECK([as hv2 ovs-ofctl dump-flows br-int \ -table=29,dl_src=f0:00:00:00:00:03,dl_dst=a0:10:00:00:00:01 | \ +table=31,dl_src=f0:00:00:00:00:03,dl_dst=a0:10:00:00:00:01 | \ grep -c "actions=drop"], [0], [1 ]) @@ -18643,7 +18643,7 @@ check_row_count Port_Binding 1 logical_port=sw0-vir virtual_parent=sw0-p1 wait_for_ports_up sw0-vir check ovn-nbctl --wait=hv sync AT_CHECK([test 2 = `cat hv1/ovn-controller.log | grep "pinctrl received packet-in" | \ -grep opcode=BIND_VPORT | grep OF_Table_ID=24 | wc -l`]) +grep opcode=BIND_VPORT | grep OF_Table_ID=26 | wc -l`]) wait_row_count Port_Binding 1 logical_port=sw0-vir6 chassis=$hv1_ch_uuid check_row_count Port_Binding 1 logical_port=sw0-vir6 virtual_parent=sw0-p1 @@ -18692,7 +18692,7 @@ eth_dst=00000000ff01 ip_src=$(ip_to_hex 10 0 0 10) ip_dst=$(ip_to_hex 172 168 0 101) send_icmp_packet 1 1 $eth_src $eth_dst $ip_src $ip_dst c4c9 0000000000000000000000 -AT_CHECK([as hv1 ovs-ofctl dump-flows br-int | awk '/table=26, n_packets=1, n_bytes=45/{print $7" "$8}'],[0],[dnl +AT_CHECK([as hv1 ovs-ofctl dump-flows br-int metadata=0x$lr0_dp_key | awk '/table=26, n_packets=1, n_bytes=45/{print $7" "$8}'],[0],[dnl priority=80,ip,reg15=0x3,metadata=0x3,nw_src=10.0.0.10 actions=drop ]) @@ -21832,7 +21832,7 @@ OVS_WAIT_FOR_OUTPUT( (ls_in_pre_stateful ), priority=120 , match=(reg0[[2]] == 1 && ip6 && sctp), action=(xxreg1 = ip6.dst; reg2[[0..15]] = sctp.dst; ct_lb;) (ls_in_pre_stateful ), priority=120 , match=(reg0[[2]] == 1 && ip6 && tcp), action=(xxreg1 = ip6.dst; reg2[[0..15]] = tcp.dst; ct_lb;) (ls_in_pre_stateful ), priority=120 , match=(reg0[[2]] == 1 && ip6 && udp), action=(xxreg1 = ip6.dst; reg2[[0..15]] = udp.dst; ct_lb;) - (ls_in_stateful ), priority=120 , match=(ct.new && ip4.dst == 10.0.0.10 && tcp.dst == 80), action=(reg1 = 10.0.0.10; reg2[[0..15]] = 80; ct_lb(backends=10.0.0.3:80,20.0.0.3:80; hash_fields="ip_dst,ip_src,tcp_dst,tcp_src");) + (ls_in_lb ), priority=120 , match=(ct.new && ip4.dst == 10.0.0.10 && tcp.dst == 80), action=(reg0[[1]] = 0; reg1 = 10.0.0.10; reg2[[0..15]] = 80; ct_lb(backends=10.0.0.3:80,20.0.0.3:80; hash_fields="ip_dst,ip_src,tcp_dst,tcp_src");) ]) AT_CAPTURE_FILE([sbflows2]) @@ -21874,7 +21874,7 @@ ovn-sbctl dump-flows sw0 > sbflows3 AT_CHECK( [grep "ip4.dst == 10.0.0.10 && tcp.dst == 80" sbflows3 | grep priority=120 |\ sed 's/table=../table=??/'], [0], - [ table=??(ls_in_stateful ), priority=120 , match=(ct.new && ip4.dst == 10.0.0.10 && tcp.dst == 80), action=(drop;) + [ table=??(ls_in_lb ), priority=120 , match=(ct.new && ip4.dst == 10.0.0.10 && tcp.dst == 80), action=(drop;) ]) AT_CAPTURE_FILE([sbflows4]) @@ -28772,8 +28772,8 @@ options arp_proxy='"169.254.239.254 169.254.239.2"' ovn-sbctl dump-flows > sbflows AT_CAPTURE_FILE([sbflows]) -AT_CHECK([ovn-sbctl dump-flows | grep ls_in_arp_rsp | grep "169.254.239.2"], [0], [dnl - table=16(ls_in_arp_rsp ), priority=50 , match=(arp.op == 1 && arp.tpa == {169.254.239.254,169.254.239.2}), dnl +AT_CHECK([ovn-sbctl dump-flows | grep ls_in_arp_rsp | grep "169.254.239.2" | sed 's/table=../table=??/'], [0], [dnl + table=??(ls_in_arp_rsp ), priority=50 , match=(arp.op == 1 && arp.tpa == {169.254.239.254,169.254.239.2}), dnl action=(eth.dst = eth.src; eth.src = 00:00:00:01:02:f1; arp.op = 2; /* ARP reply */ arp.tha = arp.sha; arp.sha = 00:00:00:01:02:f1; arp.tpa <-> arp.spa; outport = inport; flags.loopback = 1; output;) ]) @@ -29254,26 +29254,26 @@ done check ovn-nbctl --wait=hv sync # hv0 should see flows for lsp1 but not lsp2 -AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=24 | grep 10.0.1.2], [0], [ignore]) -AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=24 | grep 10.0.2.2], [1]) +AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=26 | grep 10.0.1.2], [0], [ignore]) +AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=26 | grep 10.0.2.2], [1]) # hv2 should see flows for lsp2 but not lsp1 -AT_CHECK([as hv2 ovs-ofctl dump-flows br-int table=24 | grep 10.0.2.2], [0], [ignore]) -AT_CHECK([as hv2 ovs-ofctl dump-flows br-int table=24 | grep 10.0.1.2], [1]) +AT_CHECK([as hv2 ovs-ofctl dump-flows br-int table=26 | grep 10.0.2.2], [0], [ignore]) +AT_CHECK([as hv2 ovs-ofctl dump-flows br-int table=26 | grep 10.0.1.2], [1]) # Change lrp_lr_ls1 to a regular lrp, hv2 should see flows for lsp1 check ovn-nbctl --wait=hv lrp-del-gateway-chassis lrp_lr_ls1 hv1 -AT_CHECK([as hv2 ovs-ofctl dump-flows br-int table=24 | grep 10.0.1.2], [0], [ignore]) +AT_CHECK([as hv2 ovs-ofctl dump-flows br-int table=26 | grep 10.0.1.2], [0], [ignore]) # Change it back, and trigger recompute to make sure extra flows are removed # from hv2 (recompute is needed because currently I-P adds local datapaths but # doesn't remove.) check ovn-nbctl --wait=hv lrp-set-gateway-chassis lrp_lr_ls1 hv1 1 as hv2 check ovn-appctl -t ovn-controller recompute -AT_CHECK([as hv2 ovs-ofctl dump-flows br-int table=24 | grep 10.0.1.2], [1]) +AT_CHECK([as hv2 ovs-ofctl dump-flows br-int table=26 | grep 10.0.1.2], [1]) # Enable dnat_and_snat on lr, and now hv2 should see flows for lsp1. AT_CHECK([ovn-nbctl --wait=hv lr-nat-add lr dnat_and_snat 192.168.0.1 10.0.1.3 lsp1 f0:00:00:00:00:03]) -AT_CHECK([as hv2 ovs-ofctl dump-flows br-int table=24 | grep 10.0.1.2], [0], [ignore]) +AT_CHECK([as hv2 ovs-ofctl dump-flows br-int table=26 | grep 10.0.1.2], [0], [ignore]) OVN_CLEANUP([hv1],[hv2]) AT_CLEANUP diff --git a/tests/system-ovn.at b/tests/system-ovn.at index f57d752d44..d4c22e7e90 100644 --- a/tests/system-ovn.at +++ b/tests/system-ovn.at @@ -1448,6 +1448,32 @@ OVS_START_L7([bar1], [http]) OVS_START_L7([bar2], [http]) OVS_START_L7([bar3], [http]) +# Add ACLs (after lb) to drop the traffic if destined to backend ips. +check ovn-nbctl --apply-after-lb acl-add foo from-lport 1002 "ip4 && ip4.dst == {172.16.1.2,172.16.1.3,172.16.1.4} && ct.new" drop +check ovn-nbctl --wait=hv sync + +AT_CHECK([ip netns exec foo1 wget 30.0.0.1 -t 3 -T 1], [4], [ignore], [ignore]) + +AT_CHECK([ovs-appctl dpctl/flush-conntrack]) + +# Clear the apply-after-lb option. The traffic will be allowed. +check ovn-nbctl clear acl . options +ovn-nbctl --wait=hv sync + +OVS_WAIT_FOR_OUTPUT([ + for i in `seq 1 20`; do + ip netns exec foo1 wget 30.0.0.1 -t 5 -T 1 --retry-connrefused -v -o wget$i.log; + done + ovs-appctl dpctl/dump-conntrack | FORMAT_CT(30.0.0.1) | \ + sed -e 's/zone=[[0-9]]*/zone=/'], [0], [dnl +tcp,orig=(src=192.168.1.2,dst=30.0.0.1,sport=,dport=),reply=(src=172.16.1.2,dst=192.168.1.2,sport=,dport=),zone=,labels=0x2,protoinfo=(state=) +tcp,orig=(src=192.168.1.2,dst=30.0.0.1,sport=,dport=),reply=(src=172.16.1.3,dst=192.168.1.2,sport=,dport=),zone=,labels=0x2,protoinfo=(state=) +tcp,orig=(src=192.168.1.2,dst=30.0.0.1,sport=,dport=),reply=(src=172.16.1.4,dst=192.168.1.2,sport=,dport=),zone=,labels=0x2,protoinfo=(state=) +]) + +ovn-nbctl acl-del foo from-lport 1002 "ip4 && ip4.dst == {172.16.1.2,172.16.1.3,172.16.1.4} && ct.new" +ovn-nbctl --wait=hv sync + dnl Should work with the virtual IP 30.0.0.1 address through NAT dnl Each server should have at least one connection. dnl With 20 requests, one server might not receive any connection @@ -4895,6 +4921,247 @@ aef0::3 udp port 90" | uniq | wc -l) ]) +OVS_APP_EXIT_AND_WAIT([ovn-controller]) + +as ovn-sb +OVS_APP_EXIT_AND_WAIT([ovsdb-server]) + +as ovn-nb +OVS_APP_EXIT_AND_WAIT([ovsdb-server]) + +as northd +OVS_APP_EXIT_AND_WAIT([NORTHD_TYPE]) + +as +OVS_TRAFFIC_VSWITCHD_STOP(["/failed to query port patch-.*/d +/connection dropped.*/d"]) + +AT_CLEANUP +]) + +OVN_FOR_EACH_NORTHD([ +AT_SETUP([ACL after lb - reject]) +AT_SKIP_IF([test $HAVE_NC = no]) +AT_KEYWORDS([lb]) + +ovn_start + +OVS_TRAFFIC_VSWITCHD_START() +ADD_BR([br-int]) + +# Set external-ids in br-int needed for ovn-controller +ovs-vsctl \ + -- set Open_vSwitch . external-ids:system-id=hv1 \ + -- set Open_vSwitch . external-ids:ovn-remote=unix:$ovs_base/ovn-sb/ovn-sb.sock \ + -- set Open_vSwitch . external-ids:ovn-encap-type=geneve \ + -- set Open_vSwitch . external-ids:ovn-encap-ip=169.0.0.1 \ + -- set bridge br-int fail-mode=secure other-config:disable-in-band=true + +# Start ovn-controller +start_daemon ovn-controller + +ovn-nbctl ls-add sw0 + +ovn-nbctl lsp-add sw0 sw0-p1-rej +ovn-nbctl lsp-set-addresses sw0-p1-rej "50:54:00:00:00:03 10.0.0.3 aef0::3" +ovn-nbctl lsp-set-port-security sw0-p1-rej "50:54:00:00:00:03 10.0.0.3 aef0::3" + +ovn-nbctl lsp-add sw0 sw0-p2-rej +ovn-nbctl lsp-set-addresses sw0-p2-rej "50:54:00:00:00:04 10.0.0.4 aef0::4" +ovn-nbctl lsp-set-port-security sw0-p2-rej "50:54:00:00:00:04 10.0.0.4 aef0::4" + +# Create port group and ACLs for sw0 ports. +ovn-nbctl pg-add pg0_drop sw0-p1-rej sw0-p2-rej +ovn-nbctl --apply-after-lb acl-add pg0_drop from-lport 1001 "inport == @pg0_drop && ip" drop +ovn-nbctl acl-add pg0_drop to-lport 1001 "outport == @pg0_drop && ip" drop + +ovn-nbctl pg-add pg0 sw0-p1-rej sw0-p2-rej +ovn-nbctl --apply-after-lb acl-add pg0 from-lport 1002 "inport == @pg0 && ip" allow-related +ovn-nbctl --log --apply-after-lb acl-add pg0 from-lport 1004 "inport == @pg0 && ip && tcp && tcp.dst == 80" reject +ovn-nbctl --log --apply-after-lb acl-add pg0 from-lport 1004 "inport == @pg0 && ip && udp && udp.dst == 90" reject + +ovn-nbctl acl-add pg0 to-lport 1002 "outport == @pg0 && ip4 && ip4.src == 0.0.0.0/0 && tcp && tcp.dst == 82" allow-related +ovn-nbctl acl-add pg0 to-lport 1002 "outport == @pg0 && ip4 && ip4.src == 0.0.0.0/0 && udp && udp.dst == 82" allow-related +ovn-nbctl --log acl-add pg0 to-lport 1004 "inport == @pg0 && ip && tcp && tcp.dst == 84" reject +ovn-nbctl --log acl-add pg0 to-lport 1004 "inport == @pg0 && ip && udp && udp.dst == 94" reject + +ovn-nbctl ls-add sw1 +ovn-nbctl lsp-add sw1 sw1-p1-rej +ovn-nbctl lsp-set-addresses sw1-p1-rej "40:54:00:00:00:03 20.0.0.3" +ovn-nbctl lsp-set-port-security sw1-p1-rej "40:54:00:00:00:03 20.0.0.3" + +ovn-nbctl lr-add lr0 +ovn-nbctl lrp-add lr0 lr0-sw0 00:00:00:00:ff:01 10.0.0.1/24 +ovn-nbctl lsp-add sw0 sw0-lr0 +ovn-nbctl lsp-set-type sw0-lr0 router +ovn-nbctl lsp-set-addresses sw0-lr0 router +ovn-nbctl lsp-set-options sw0-lr0 router-port=lr0-sw0 + +ovn-nbctl lrp-add lr0 lr0-sw1 00:00:00:00:ff:02 20.0.0.1/24 +ovn-nbctl lsp-add sw1 sw1-lr0 +ovn-nbctl lsp-set-type sw1-lr0 router +ovn-nbctl lsp-set-addresses sw1-lr0 router +ovn-nbctl lsp-set-options sw1-lr0 router-port=lr0-sw1 + +OVN_POPULATE_ARP +ovn-nbctl --wait=hv sync + +ADD_NAMESPACES(sw0-p1-rej) +ADD_VETH(sw0-p1-rej, sw0-p1-rej, br-int, "10.0.0.3/24", "50:54:00:00:00:03", \ + "10.0.0.1") + +ADD_NAMESPACES(sw0-p2-rej) +ADD_VETH(sw0-p2-rej, sw0-p2-rej, br-int, "10.0.0.4/24", "50:54:00:00:00:04", \ + "10.0.0.1") + +NS_CHECK_EXEC([sw0-p1-rej], [ip a a aef0::3/64 dev sw0-p1-rej], [0]) +NS_CHECK_EXEC([sw0-p2-rej], [ip a a aef0::4/64 dev sw0-p2-rej], [0]) + +ADD_NAMESPACES(sw1-p1-rej) +ADD_VETH(sw1-p1-rej, sw1-p1-rej, br-int, "20.0.0.3/24", "40:54:00:00:00:03", \ + "20.0.0.1") + +sleep 1 + +# Capture packets in sw0-p1-rej. +NS_CHECK_EXEC([sw0-p1-rej], [tcpdump -nn -c 4 -i sw0-p1-rej tcp > sw0-p1-rej-ip4.pcap &], [0]) + +sleep 1 + +OVS_WAIT_UNTIL([ + ip netns exec sw0-p1-rej nc -vz 10.0.0.4 80 2>&1 | grep -i 'connection refused' +]) + +# Now send traffic to port 84 +OVS_WAIT_UNTIL([ + ip netns exec sw0-p1-rej nc -vz 10.0.0.4 84 2>&1 | grep -i 'connection refused' +]) + +OVS_WAIT_UNTIL([ + n_pkt=$(ovs-ofctl dump-flows br-int table=44 | grep -v n_packets=0 | \ +grep controller | grep tp_dst=84 -c) + test $n_pkt -eq 1 +]) + +OVS_WAIT_UNTIL([ + total=`cat sw0-p1-rej-ip4.pcap | wc -l` + echo "total = $total" + test "${total}" = "4" +]) + +# Without this sleep, test case fails intermittently. +sleep 3 + +NS_CHECK_EXEC([sw0-p2-rej], [tcpdump -nn -c 2 -i sw0-p2-rej tcp port 80 > sw0-p2-rej-ip6.pcap &], [0]) + +sleep 1 + +OVS_WAIT_UNTIL([ + ip netns exec sw0-p2-rej nc -vz6 aef0::3 80 2>&1 | grep -i 'connection refused' +]) + + +OVS_WAIT_UNTIL([ + total=`cat sw0-p2-rej-ip6.pcap | wc -l` + echo "total = $total" + test "${total}" = "2" +]) + +ovn-nbctl --apply-after-lb acl-add sw1 from-lport 1004 "ip" allow-related +ovn-nbctl acl-add sw1 to-lport 1004 "ip" allow-related +ovn-nbctl --log acl-add pg0 to-lport 1004 "outport == @pg0 && ip && tcp && tcp.dst == 84" reject + +OVS_WAIT_UNTIL([ + ip netns exec sw1-p1-rej nc -vz 10.0.0.4 84 2>&1 | grep -i 'connection refused' +]) + +# Now test for IPv4 UDP. +NS_CHECK_EXEC([sw0-p1-rej], [tcpdump -nn -c 1 -i sw0-p1-rej udp port 90 > sw0-p1-rej-udp.pcap &], [0]) +NS_CHECK_EXEC([sw0-p1-rej], [tcpdump -nn -c 1 -i sw0-p1-rej icmp > sw0-p1-rej-icmp.pcap &], [0]) + +printf '.%.0s' {1..100} > foo +OVS_WAIT_UNTIL([ + ip netns exec sw0-p1-rej nc -u 10.0.0.4 90 < foo + c=$(cat sw0-p1-rej-icmp.pcap | grep \ +"10.0.0.4 > 10.0.0.3: ICMP 10.0.0.4 udp port 90 unreachable" | uniq | wc -l) + test $c -eq 1 +]) + +rm -f *.pcap + +NS_CHECK_EXEC([sw0-p1-rej], [tcpdump -nn -c 1 -i sw0-p1-rej udp port 94 > sw0-p1-rej-udp.pcap &], [0]) +NS_CHECK_EXEC([sw0-p1-rej], [tcpdump -nn -c 1 -i sw0-p1-rej icmp > sw0-p1-rej-icmp.pcap &], [0]) + +OVS_WAIT_UNTIL([ + ip netns exec sw0-p1-rej nc -u 10.0.0.4 94 < foo + c=$(cat sw0-p1-rej-icmp.pcap | grep \ +"10.0.0.4 > 10.0.0.3: ICMP 10.0.0.4 udp port 94 unreachable" | uniq | wc -l) + test $c -eq 1 +]) + +# Now test for IPv6 UDP. +NS_CHECK_EXEC([sw0-p2-rej], [tcpdump -nn -c 1 -i sw0-p2-rej udp port 90 > sw0-p2-rej-ip6-udp.pcap &], [0]) +NS_CHECK_EXEC([sw0-p2-rej], [tcpdump -nn -c 1 -i sw0-p2-rej icmp6 > sw0-p2-rej-icmp6.pcap &], [0]) + +OVS_WAIT_UNTIL([ + ip netns exec sw0-p2-rej nc -u -6 aef0::3 90 < foo + c=$(cat sw0-p2-rej-icmp6.pcap | grep \ +"IP6 aef0::3 > aef0::4: ICMP6, destination unreachable, unreachable port, \ +aef0::3 udp port 90" | uniq | wc -l) + test $c -eq 1 +]) + +rm -f *.pcap + +NS_CHECK_EXEC([sw0-p2-rej], [tcpdump -nn -c 1 -i sw0-p2-rej udp port 94 > sw0-p2-rej-ip6-udp.pcap &], [0]) +NS_CHECK_EXEC([sw0-p2-rej], [tcpdump -nn -c 1 -i sw0-p2-rej icmp6 > sw0-p2-rej-icmp6.pcap &], [0]) + +OVS_WAIT_UNTIL([ + ip netns exec sw0-p2-rej nc -u -6 aef0::3 94 < foo + c=$(cat sw0-p2-rej-icmp6.pcap | grep \ +"IP6 aef0::3 > aef0::4: ICMP6, destination unreachable, unreachable port, \ +aef0::3 udp port 94" | uniq | wc -l) + test $c -eq 1 +]) + +# Delete all the ACLs of pg0 and add the ACL with a generic match with reject action. +ovn-nbctl pg-del pg0 +ovn-nbctl pg-add pg0 sw0-p1-rej sw0-p2-rej +ovn-nbctl --log --apply-after-lb acl-add pg0 from-lport 1004 "inport == @pg0 && ip && (tcp || udp)" reject + +OVS_WAIT_UNTIL([ + ip netns exec sw0-p1-rej nc -vz 10.0.0.4 80 2>&1 | grep -i 'connection refused' +]) + +OVS_WAIT_UNTIL([ + ip netns exec sw0-p2-rej nc -vz6 aef0::3 80 2>&1 | grep -i 'connection refused' +]) + +rm -f *.pcap + +NS_CHECK_EXEC([sw0-p1-rej], [tcpdump -nn -c 1 -i sw0-p1-rej icmp > sw0-p1-rej-icmp.pcap &], [0]) + +printf '.%.0s' {1..100} > foo +OVS_WAIT_UNTIL([ + ip netns exec sw0-p1-rej nc -u 10.0.0.4 90 < foo + c=$(cat sw0-p1-rej-icmp.pcap | grep \ +"10.0.0.4 > 10.0.0.3: ICMP 10.0.0.4 udp port 90 unreachable" | uniq | wc -l) + test $c -eq 1 +]) + +rm -f *.pcap +# Now test for IPv6 UDP. +NS_CHECK_EXEC([sw0-p2-rej], [tcpdump -nn -c 1 -i sw0-p2-rej icmp6 > sw0-p2-rej-icmp6.pcap &], [0]) + +OVS_WAIT_UNTIL([ + ip netns exec sw0-p2-rej nc -u -6 aef0::3 90 < foo + c=$(cat sw0-p2-rej-icmp6.pcap | grep \ +"IP6 aef0::3 > aef0::4: ICMP6, destination unreachable, unreachable port, \ +aef0::3 udp port 90" | uniq | wc -l) + test $c -eq 1 +]) + + OVS_APP_EXIT_AND_WAIT([ovn-controller]) as ovn-sb @@ -6907,8 +7174,150 @@ AT_CLEANUP ]) OVN_FOR_EACH_NORTHD([ -AT_SETUP([ACL label - conntrack label change]) -AT_KEYWORDS([acl label ct_commit label change]) +AT_SETUP([ACL label - conntrack ct_label - acl after lb]) +AT_KEYWORDS([acl label ct_commit]) + +CHECK_CONNTRACK() +ovn_start + +OVS_TRAFFIC_VSWITCHD_START() +ADD_BR([br-int]) + +# Set external-ids in br-int needed for ovn-controller +ovs-vsctl \ + -- set Open_vSwitch . external-ids:system-id=hv1 \ + -- set Open_vSwitch . external-ids:ovn-remote=unix:$ovs_base/ovn-sb/ovn-sb.sock \ + -- set Open_vSwitch . external-ids:ovn-encap-type=geneve \ + -- set Open_vSwitch . external-ids:ovn-encap-ip=169.0.0.1 \ + -- set bridge br-int fail-mode=secure other-config:disable-in-band=true + +# Start ovn-controller +start_daemon ovn-controller + +check ovn-nbctl ls-add sw0 + +check ovn-nbctl lsp-add sw0 sw0-p1 +check ovn-nbctl lsp-set-addresses sw0-p1 "50:54:00:00:00:02 10.0.0.2" +check ovn-nbctl lsp-set-port-security sw0-p1 "50:54:00:00:00:02 10.0.0.2" + +check ovn-nbctl lsp-add sw0 sw0-p2 +check ovn-nbctl lsp-set-addresses sw0-p2 "50:54:00:00:00:03 10.0.0.3" +check ovn-nbctl lsp-set-port-security sw0-p2 "50:54:00:00:00:03 10.0.0.3" + +check ovn-nbctl lsp-add sw0 sw0-p3 +check ovn-nbctl lsp-set-addresses sw0-p3 "50:54:00:00:00:04 10.0.0.4" +check ovn-nbctl lsp-set-port-security sw0-p3 "50:54:00:00:00:04 10.0.0.4" + +# ACLs +# Case 1: sw0-p1 ---> sw0-p3 allowed, label=1234 +# Case 2: sw0-p3 ---> sw0-p1 allowed, label=1235 +# Case 3: sw0-p1 ---> sw0-p2 allowed, no label +# Case 4: sw0-p2 ---> sw0-p1 allowed, no label + +check ovn-nbctl --label=1234 --apply-after-lb acl-add sw0 from-lport 1002 'ip4 && inport == "sw0-p1" && ip4.dst == 10.0.0.4' allow-related +check ovn-nbctl --label=1235 acl-add sw0 to-lport 1002 'ip4 && outport == "sw0-p1" && ip4.src == 10.0.0.4' allow-related +check ovn-nbctl --apply-after-lb acl-add sw0 from-lport 1001 "ip" allow-related +check ovn-nbctl acl-add sw0 to-lport 1001 "ip" allow-related + + +ADD_NAMESPACES(sw0-p1) +ADD_VETH(sw0-p1, sw0-p1, br-int, "10.0.0.2/24", "50:54:00:00:00:02", \ + "10.0.0.1") +ADD_NAMESPACES(sw0-p2) +ADD_VETH(sw0-p2, sw0-p2, br-int, "10.0.0.3/24", "50:54:00:00:00:03", \ + "10.0.0.1") +ADD_NAMESPACES(sw0-p3) +ADD_VETH(sw0-p3, sw0-p3, br-int, "10.0.0.4/24", "50:54:00:00:00:04", \ + "10.0.0.1") + +# Ensure ovn-controller is caught up +ovn-nbctl --wait=hv sync + +on_exit 'ovn-nbctl acl-list sw0' +on_exit 'ovn-sbctl lflow-list' +on_exit 'ovs-ofctl dump-flows br-int' + +wait_for_ports_up + +AT_CHECK([ovs-appctl dpctl/flush-conntrack]) +# 'sw0-p1' should be able to ping 'sw0-p3'. +NS_CHECK_EXEC([sw0-p1], [ping -q -c 10 -i 0.3 -w 15 10.0.0.4 | FORMAT_PING], \ +[0], [dnl +10 packets transmitted, 10 received, 0% packet loss, time 0ms +]) + +# Ensure conntrack entry is present and ct_label is set. +AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(10.0.0.4) | \ +sed -e 's/zone=[[0-9]]*/zone=/' | \ +sed -e 's/labels=0x4d2[[0-9a-f]]*/labels=0x4d2000000000000000000000000/'], [0], [dnl +icmp,orig=(src=10.0.0.2,dst=10.0.0.4,id=,type=8,code=0),reply=(src=10.0.0.4,dst=10.0.0.2,id=,type=0,code=0),zone=,labels=0x4d2000000000000000000000000 +icmp,orig=(src=10.0.0.2,dst=10.0.0.4,id=,type=8,code=0),reply=(src=10.0.0.4,dst=10.0.0.2,id=,type=0,code=0),zone= +]) + +AT_CHECK([ovs-appctl dpctl/flush-conntrack]) +# 'sw0-p3' should be able to ping 'sw0-p1'. +NS_CHECK_EXEC([sw0-p3], [ping -q -c 10 -i 0.3 -w 15 10.0.0.2 | FORMAT_PING], \ +[0], [dnl +10 packets transmitted, 10 received, 0% packet loss, time 0ms +]) + +# Ensure conntrack entry is present and ct_label is set. +AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(10.0.0.2) | \ +sed -e 's/zone=[[0-9]]*/zone=/' | \ +sed -e 's/labels=0x4d3[[0-9a-f]]*/labels=0x4d3000000000000000000000000/'], [0], [dnl +icmp,orig=(src=10.0.0.4,dst=10.0.0.2,id=,type=8,code=0),reply=(src=10.0.0.2,dst=10.0.0.4,id=,type=0,code=0),zone=,labels=0x4d3000000000000000000000000 +icmp,orig=(src=10.0.0.4,dst=10.0.0.2,id=,type=8,code=0),reply=(src=10.0.0.2,dst=10.0.0.4,id=,type=0,code=0),zone= +]) + +AT_CHECK([ovs-appctl dpctl/flush-conntrack]) +# 'sw0-p1' should be able to ping 'sw0-p2'. +NS_CHECK_EXEC([sw0-p1], [ping -q -c 10 -i 0.3 -w 15 10.0.0.3 | FORMAT_PING], \ +[0], [dnl +10 packets transmitted, 10 received, 0% packet loss, time 0ms +]) + +# Ensure conntrack entry is present and ct_label is not set. +AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(10.0.0.3) | \ +sed -e 's/zone=[[0-9]]*/zone=/'], [0], [dnl +icmp,orig=(src=10.0.0.2,dst=10.0.0.3,id=,type=8,code=0),reply=(src=10.0.0.3,dst=10.0.0.2,id=,type=0,code=0),zone= +icmp,orig=(src=10.0.0.2,dst=10.0.0.3,id=,type=8,code=0),reply=(src=10.0.0.3,dst=10.0.0.2,id=,type=0,code=0),zone= +]) + +AT_CHECK([ovs-appctl dpctl/flush-conntrack]) +# 'sw0-p2' should be able to ping 'sw0-p1'. +NS_CHECK_EXEC([sw0-p2], [ping -q -c 10 -i 0.3 -w 15 10.0.0.2 | FORMAT_PING], \ +[0], [dnl +10 packets transmitted, 10 received, 0% packet loss, time 0ms +]) + +# Ensure conntrack entry is present and ct_label is not set. +AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(10.0.0.2) | \ +sed -e 's/zone=[[0-9]]*/zone=/'], [0], [dnl +icmp,orig=(src=10.0.0.3,dst=10.0.0.2,id=,type=8,code=0),reply=(src=10.0.0.2,dst=10.0.0.3,id=,type=0,code=0),zone= +icmp,orig=(src=10.0.0.3,dst=10.0.0.2,id=,type=8,code=0),reply=(src=10.0.0.2,dst=10.0.0.3,id=,type=0,code=0),zone= +]) + +OVS_APP_EXIT_AND_WAIT([ovn-controller]) + +as ovn-sb +OVS_APP_EXIT_AND_WAIT([ovsdb-server]) + +as ovn-nb +OVS_APP_EXIT_AND_WAIT([ovsdb-server]) + +as northd +OVS_APP_EXIT_AND_WAIT([NORTHD_TYPE]) + +as +OVS_TRAFFIC_VSWITCHD_STOP(["/failed to query port patch-.*/d +/connection dropped.*/d"]) + +AT_CLEANUP +]) + +OVN_FOR_EACH_NORTHD([ +AT_SETUP([ACL label - conntrack label change]) +AT_KEYWORDS([acl label ct_commit label change]) CHECK_CONNTRACK() ovn_start @@ -7007,6 +7416,207 @@ OVS_TRAFFIC_VSWITCHD_STOP(["/failed to query port patch-.*/d AT_CLEANUP ]) +OVN_FOR_EACH_NORTHD([ +AT_SETUP([ACL label - conntrack label change - acl after lb]) +AT_KEYWORDS([acl label ct_commit label change]) + +CHECK_CONNTRACK() +ovn_start + +OVS_TRAFFIC_VSWITCHD_START() +ADD_BR([br-int]) + +# Set external-ids in br-int needed for ovn-controller +ovs-vsctl \ + -- set Open_vSwitch . external-ids:system-id=hv1 \ + -- set Open_vSwitch . external-ids:ovn-remote=unix:$ovs_base/ovn-sb/ovn-sb.sock \ + -- set Open_vSwitch . external-ids:ovn-encap-type=geneve \ + -- set Open_vSwitch . external-ids:ovn-encap-ip=169.0.0.1 \ + -- set bridge br-int fail-mode=secure other-config:disable-in-band=true + +# Start ovn-controller +start_daemon ovn-controller + +check ovn-nbctl ls-add sw0 + +check ovn-nbctl lsp-add sw0 sw0-p1 +check ovn-nbctl lsp-set-addresses sw0-p1 "50:54:00:00:00:02 10.0.0.2" +check ovn-nbctl lsp-set-port-security sw0-p1 "50:54:00:00:00:02 10.0.0.2" + +check ovn-nbctl lsp-add sw0 sw0-p2 +check ovn-nbctl lsp-set-addresses sw0-p2 "50:54:00:00:00:03 10.0.0.3" +check ovn-nbctl lsp-set-port-security sw0-p2 "50:54:00:00:00:03 10.0.0.3" + +# ACLs +# sw0-p1 ---> sw0-p2 allowed, label=1234 + +check ovn-nbctl --label=1234 --apply-after-lb acl-add sw0 from-lport 1002 'ip4 && inport == "sw0-p1" && ip4.dst == 10.0.0.3' allow-related + +ADD_NAMESPACES(sw0-p1) +ADD_VETH(sw0-p1, sw0-p1, br-int, "10.0.0.2/24", "50:54:00:00:00:02", \ + "10.0.0.1") +ADD_NAMESPACES(sw0-p2) +ADD_VETH(sw0-p2, sw0-p2, br-int, "10.0.0.3/24", "50:54:00:00:00:03", \ + "10.0.0.1") + +# Ensure ovn-controller is caught up +ovn-nbctl --wait=hv sync + +on_exit 'ovn-nbctl acl-list sw0' +on_exit 'ovn-sbctl lflow-list' +on_exit 'ovs-ofctl dump-flows br-int' + +wait_for_ports_up + +AT_CHECK([ovs-appctl dpctl/flush-conntrack]) + +# start a background ping for ~30 secs. +NETNS_DAEMONIZE([sw0-p1], [[ping -q -c 100 -i 0.3 -w 15 10.0.0.3]], [ns-sw0-p1.pid]) + +sleep 3s + +# Ensure conntrack entry is present and ct_label is set. +AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(10.0.0.3) | \ +sed -e 's/zone=[[0-9]]*/zone=/' | \ +sed -e 's/labels=0x4d2[[0-9a-f]]*/labels=0x4d2000000000000000000000000/'], [0], [dnl +icmp,orig=(src=10.0.0.2,dst=10.0.0.3,id=,type=8,code=0),reply=(src=10.0.0.3,dst=10.0.0.2,id=,type=0,code=0),zone=,labels=0x4d2000000000000000000000000 +icmp,orig=(src=10.0.0.2,dst=10.0.0.3,id=,type=8,code=0),reply=(src=10.0.0.3,dst=10.0.0.2,id=,type=0,code=0),zone= +]) + +# Add a higher priority ACL with different label. +# This ACL also allows the ping running in background. + +check ovn-nbctl --label=1235 --apply-after-lb acl-add sw0 from-lport 1003 'ip4 && inport == "sw0-p1" && ip4.dst == 10.0.0.3' allow-related +ovn-nbctl --wait=hv sync + +sleep 3s + +# Ensure conntrack entry is updated with new ct_label is set. +AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(10.0.0.3) | \ +sed -e 's/zone=[[0-9]]*/zone=/' | \ +sed -e 's/labels=0x4d3[[0-9a-f]]*/labels=0x4d3000000000000000000000000/'], [0], [dnl +icmp,orig=(src=10.0.0.2,dst=10.0.0.3,id=,type=8,code=0),reply=(src=10.0.0.3,dst=10.0.0.2,id=,type=0,code=0),zone=,labels=0x4d3000000000000000000000000 +icmp,orig=(src=10.0.0.2,dst=10.0.0.3,id=,type=8,code=0),reply=(src=10.0.0.3,dst=10.0.0.2,id=,type=0,code=0),zone= +]) + +OVS_APP_EXIT_AND_WAIT([ovn-controller]) + +as ovn-sb +OVS_APP_EXIT_AND_WAIT([ovsdb-server]) + +as ovn-nb +OVS_APP_EXIT_AND_WAIT([ovsdb-server]) + +as northd +OVS_APP_EXIT_AND_WAIT([NORTHD_TYPE]) + +as +OVS_TRAFFIC_VSWITCHD_STOP(["/failed to query port patch-.*/d +/connection dropped.*/d"]) + +AT_CLEANUP +]) + +OVN_FOR_EACH_NORTHD([ +AT_SETUP([ACL all drop and allow related - acl after lb]) +AT_KEYWORDS([ACL all drop and allow related]) + +CHECK_CONNTRACK() +ovn_start + +OVS_TRAFFIC_VSWITCHD_START() +ADD_BR([br-int]) + +# Set external-ids in br-int needed for ovn-controller +ovs-vsctl \ + -- set Open_vSwitch . external-ids:system-id=hv1 \ + -- set Open_vSwitch . external-ids:ovn-remote=unix:$ovs_base/ovn-sb/ovn-sb.sock \ + -- set Open_vSwitch . external-ids:ovn-encap-type=geneve \ + -- set Open_vSwitch . external-ids:ovn-encap-ip=169.0.0.1 \ + -- set bridge br-int fail-mode=secure other-config:disable-in-band=true + +# Start ovn-controller +start_daemon ovn-controller + + +# No ACLs in sw0. +check ovn-nbctl ls-add sw0 + +check ovn-nbctl lsp-add sw0 sw0p1 +check ovn-nbctl lsp-set-addresses sw0p1 "50:54:00:00:00:02 10.0.0.3" + +# ACLs to drop every thing and just allow-related. +check ovn-nbctl ls-add sw1 + +check ovn-nbctl lsp-add sw1 sw1p1 +check ovn-nbctl lsp-set-addresses sw1p1 "50:54:00:00:00:03 20.0.0.3" + +check ovn-nbctl --apply-after-lb acl-add sw1 from-lport 1001 'inport == "sw1p1" && ip4' drop + +check ovn-nbctl acl-add sw1 to-lport 1002 'ip4 && tcp && tcp.dst == 80' allow-related +check ovn-nbctl acl-add sw1 to-lport 1001 'ip4' drop + +ADD_NAMESPACES(sw0p1) +ADD_VETH(sw0p1, sw0p1, br-int, "10.0.0.3/24", "50:54:00:00:00:02", \ + "10.0.0.1") +ADD_NAMESPACES(sw1p1) +ADD_VETH(sw1p1, sw1p1, br-int, "20.0.0.3/24", "50:54:00:00:00:03", \ + "20.0.0.1") + +# Create a logical router and attach both logical switches +check ovn-nbctl lr-add lr0 +check ovn-nbctl lrp-add lr0 lr0-sw0 00:00:00:00:ff:01 10.0.0.1/24 +check ovn-nbctl lsp-add sw0 sw0-lr0 +check ovn-nbctl lsp-set-type sw0-lr0 router +check ovn-nbctl lsp-set-addresses sw0-lr0 00:00:00:00:ff:01 +check ovn-nbctl lsp-set-options sw0-lr0 router-port=lr0-sw0 + +check ovn-nbctl lrp-add lr0 lr0-sw1 00:00:00:00:ff:02 20.0.0.1/24 +check ovn-nbctl lsp-add sw1 sw1-lr0 +check ovn-nbctl lsp-set-type sw1-lr0 router +check ovn-nbctl lsp-set-addresses sw1-lr0 00:00:00:00:ff:02 +check ovn-nbctl lsp-set-options sw1-lr0 router-port=lr0-sw1 + +# Ensure ovn-controller is caught up +ovn-nbctl --wait=hv sync + +on_exit 'ovn-nbctl acl-list sw0' +on_exit 'ovn-sbctl lflow-list' +on_exit 'ovs-ofctl dump-flows br-int' + +wait_for_ports_up + +# Start webservers in 'sw1-p1' +OVS_START_L7([sw1p1], [http]) + +AT_CHECK([ip netns exec sw0p1 wget 20.0.0.3 -t 3 -T 1], [0], [ignore], [ignore]) + +# Clear the apply-after-lb option for the ACL +check ovn-nbctl acl-del sw1 from-lport 1001 'inport == "sw1p1" && ip4' +check ovn-nbctl acl-add sw1 from-lport 1001 'inport == "sw1p1" && ip4' drop + +check ovn-nbctl --wait=hv sync + +AT_CHECK([ip netns exec sw0p1 wget 20.0.0.3 -t 3 -T 1], [0], [ignore], [ignore]) + +OVS_APP_EXIT_AND_WAIT([ovn-controller]) + +as ovn-sb +OVS_APP_EXIT_AND_WAIT([ovsdb-server]) + +as ovn-nb +OVS_APP_EXIT_AND_WAIT([ovsdb-server]) + +as northd +OVS_APP_EXIT_AND_WAIT([NORTHD_TYPE]) + +as +OVS_TRAFFIC_VSWITCHD_STOP(["/failed to query port patch-.*/d +/connection dropped.*/d"]) + +AT_CLEANUP +]) + OVN_FOR_EACH_NORTHD([ AT_SETUP([ACL log_related]) diff --git a/utilities/ovn-nbctl.8.xml b/utilities/ovn-nbctl.8.xml index 545f3bf27b..74651c7623 100644 --- a/utilities/ovn-nbctl.8.xml +++ b/utilities/ovn-nbctl.8.xml @@ -399,7 +399,7 @@ must be either switch or port-group.

-
[--type={switch | port-group}] [--log] [--meter=meter] [--severity=severity] [--name=name] [--label=label] [--may-exist] acl-add entity direction priority match verdict
+
[--type={switch | port-group}] [--log] [--meter=meter] [--severity=severity] [--name=name] [--label=label] [--may-exist] [--apply-after-lb] acl-add entity direction priority match verdict

Adds the specified ACL to entity. direction @@ -423,6 +423,13 @@ is used to rate-limit packet logging. The meter argument names a meter configured by meter-add.

+ +

+ The --apply-after-lb option sets + apply-after-lb=true in the options column + of the ACL table. As the option name suggests, the ACL + will be applied after the logical switch load balancer stage. +

[--type={switch | port-group}] acl-del entity [direction [priority match]]
diff --git a/utilities/ovn-nbctl.c b/utilities/ovn-nbctl.c index adb08c6c96..7bcc2c66a8 100644 --- a/utilities/ovn-nbctl.c +++ b/utilities/ovn-nbctl.c @@ -2132,6 +2132,7 @@ nbctl_pre_acl(struct ctl_context *ctx) ovsdb_idl_add_column(ctx->idl, &nbrec_acl_col_direction); ovsdb_idl_add_column(ctx->idl, &nbrec_acl_col_priority); ovsdb_idl_add_column(ctx->idl, &nbrec_acl_col_match); + ovsdb_idl_add_column(ctx->idl, &nbrec_acl_col_options); } static void @@ -2145,6 +2146,7 @@ nbctl_pre_acl_list(struct ctl_context *ctx) ovsdb_idl_add_column(ctx->idl, &nbrec_acl_col_severity); ovsdb_idl_add_column(ctx->idl, &nbrec_acl_col_meter); ovsdb_idl_add_column(ctx->idl, &nbrec_acl_col_label); + ovsdb_idl_add_column(ctx->idl, &nbrec_acl_col_options); } static void @@ -2231,6 +2233,13 @@ nbctl_acl_add(struct ctl_context *ctx) nbrec_acl_set_label(acl, label_value); } + if (!strcmp(direction, "from-lport") && + (shash_find(&ctx->options, "--apply-after-lb") != NULL)) { + const struct smap options = SMAP_CONST1(&options, "apply-after-lb", + "true"); + nbrec_acl_set_options(acl, &options); + } + /* Check if same acl already exists for the ls/portgroup */ size_t n_acls = pg ? pg->n_acls : ls->n_acls; struct nbrec_acl **acls = pg ? pg->acls : ls->acls; @@ -6959,7 +6968,8 @@ static const struct ctl_command_syntax nbctl_commands[] = { /* acl commands. */ { "acl-add", 5, 6, "{SWITCH | PORTGROUP} DIRECTION PRIORITY MATCH ACTION", nbctl_pre_acl, nbctl_acl_add, NULL, - "--log,--may-exist,--type=,--name=,--severity=,--meter=,--label=", RW }, + "--log,--may-exist,--type=,--name=,--severity=,--meter=,--label=," + "--apply-after-lb", RW }, { "acl-del", 1, 4, "{SWITCH | PORTGROUP} [DIRECTION [PRIORITY MATCH]]", nbctl_pre_acl, nbctl_acl_del, NULL, "--type=", RW }, { "acl-list", 1, 1, "{SWITCH | PORTGROUP}",