On Wed, Mar 9, 2016 at 1:51 PM, Russell Bryant <russ...@ovn.org> wrote:
>
> Prior to this commit, once a connection had been committed to the
> connection tracker, the connection would continue to be allowed, even
> if the policy defined in the ACL table changed.  This patch changes
> the implementation so that existing connections are affected by policy
> changes.
>
> The implementation is based on the suggested approach in this mailing
> list thread:
>
>     http://openvswitch.org/pipermail/dev/2016-February/065716.html
>
> Instead of always allowing packets associated with an established
> connection, we now put all packets in the request direction through
> the flows generated based on OVN ACLs.  If a packet associated with an
> established connection hits a "drop" ACL, that means we have
> encountered a policy change and should drop packets associated with
> this connection from now on.  We handle this by setting "ct_mark" on
> the associated connection tracking entry.
>
> One difference in the implementation vs. the mailing list proposal is
> the use of "ct_mark" instead of "ct_label".  The OpenFlow interface to
> both fields is identical, other than the size of the field (32-bit for
> ct_mark, 128-bit for ct_label).  We see two uses for these fields in
> OVN: bit twiddling for state tracking (this patch) and possibly
> associating connection tracking entries with OVN ACLs.  The easiest
> way to do that sort of association would be to use a UUID, which is
> 128-bits, so we reserve ct_label for that purpose and use the 32-bits
> of ct_mark for custom state tracking.
>
> There are also some differences in the flows needed to account for
> re-allowing a known connection after ct_mark had been set on it.
> This can happen if you delete an ACL and then re-create it while
> connection state is still known.
>
> The proposal on the mailing list also discussed the idea that
> ovn-controller could periodically sweep the connection tracker and
> delete entries with ct_mark set.  That is not implemented in this
> patch.  Instead, we rely on connections dying since we're dropping
> its packets and then allowing the connection tracking entry to
> eventually time out.  More proactively clearing them out could be a
> future enhancement.
>
> As a realistic example of how this works, consider this security policy
> from an OpenStack+OVN development environment.
>
>     +---------+-----------------------+
>     | name    | security_group_rules  |
>     +---------+-----------------------+
>     | default | egress, IPv4          |
>     |         | egress, IPv6          |
>     |         | ingress, IPv4, 22/tcp |
>     |         | ingress, IPv4, icmp   |
>     +---------+-----------------------+
>
> The OpenStack Neutron plugin creates ACLs that drop traffic by default
> and higher priority ACLs for each type of traffic that is allowed.  In
> this case, the ACLs for a port using the "default" security group are:
>
>   from-lport  1002 (inport == "0a7409c8-d179-4915-9eb2-f53426ae16dd" &&
ip4) allow-related
>   from-lport  1002 (inport == "0a7409c8-d179-4915-9eb2-f53426ae16dd" &&
ip6) allow-related
>   from-lport  1001 (inport == "0a7409c8-d179-4915-9eb2-f53426ae16dd" &&
ip) drop
>     to-lport  1002 (outport == "0a7409c8-d179-4915-9eb2-f53426ae16dd" &&
ip4 && icmp4) allow-related
>     to-lport  1002 (outport == "0a7409c8-d179-4915-9eb2-f53426ae16dd" &&
ip4 && tcp && tcp.dst == 22) allow-related
>     to-lport  1001 (outport == "0a7409c8-d179-4915-9eb2-f53426ae16dd" &&
ip) drop
>
> which results in the following logical flows:
>
> ...
>   table=1(   ls_in_pre_acl), priority=  100, match=(ip), action=(ct_next;)
>   table=1(   ls_in_pre_acl), priority=    0, match=(1), action=(next;)
>   table=2(       ls_in_acl), priority=65535, match=(!ct.est && ct.rel &&
!ct.new && !ct.inv && ct_mark[0] == 0), action=(next;)
>   table=2(       ls_in_acl), priority=65535, match=(ct.est && !ct.rel &&
!ct.new && !ct.inv && ct.rpl && ct_mark[0] == 0), action=(next;)
>   table=2(       ls_in_acl), priority=65535, match=(ct.inv || (ct.est &&
ct.rpl && ct_mark[0] == 1)), action=(drop;)
>   table=2(       ls_in_acl), priority= 2002, match=(!ct.new && ct.est &&
!ct.rpl && ct_mark[0] == 0 && (inport ==
"0a7409c8-d179-4915-9eb2-f53426ae16dd" && ip4)), action=(next;)
>   table=2(       ls_in_acl), priority= 2002, match=(!ct.new && ct.est &&
!ct.rpl && ct_mark[0] == 0 && (inport ==
"0a7409c8-d179-4915-9eb2-f53426ae16dd" && ip6)), action=(next;)
>   table=2(       ls_in_acl), priority= 2002, match=(((ct.new && !ct.est)
|| (!ct.new && ct.est && !ct.rpl && ct_mark[0] == 1)) && (inport ==
"0a7409c8-d179-4915-9eb2-f53426ae16dd" && ip4)),
action=(ct_commit(ct_mark=0); next;)
>   table=2(       ls_in_acl), priority= 2002, match=(((ct.new && !ct.est)
|| (!ct.new && ct.est && !ct.rpl && ct_mark[0] == 1)) && (inport ==
"0a7409c8-d179-4915-9eb2-f53426ae16dd" && ip6)),
action=(ct_commit(ct_mark=0); next;)
>   table=2(       ls_in_acl), priority= 2001, match=((!ct.est || (ct.est
&& ct_mark[0] == 1)) && (inport == "0a7409c8-d179-4915-9eb2-f53426ae16dd"
&& ip)), action=(drop;)
>   table=2(       ls_in_acl), priority= 2001, match=(ct.est && ct_mark[0]
== 0 && (inport == "0a7409c8-d179-4915-9eb2-f53426ae16dd" && ip)),
action=(ct_commit(ct_mark=1);)
>   table=2(       ls_in_acl), priority=    1, match=(ip && (!ct.est ||
(ct.est && ct_mark[0] == 1))), action=(ct_commit(ct_mark=0); next;)
>   table=2(       ls_in_acl), priority=    0, match=(1), action=(next;)
> ...
>   table=0(  ls_out_pre_acl), priority=  100, match=(ip), action=(ct_next;)
>   table=0(  ls_out_pre_acl), priority=    0, match=(1), action=(next;)
>   table=1(      ls_out_acl), priority=65535, match=(!ct.est && ct.rel &&
!ct.new && !ct.inv && ct_mark[0] == 0), action=(next;)
>   table=1(      ls_out_acl), priority=65535, match=(ct.est && !ct.rel &&
!ct.new && !ct.inv && ct.rpl && ct_mark[0] == 0), action=(next;)
>   table=1(      ls_out_acl), priority=65535, match=(ct.inv || (ct.est &&
ct.rpl && ct_mark[0] == 1)), action=(drop;)
>   table=1(      ls_out_acl), priority= 2002, match=(!ct.new && ct.est &&
!ct.rpl && ct_mark[0] == 0 && (outport ==
"0a7409c8-d179-4915-9eb2-f53426ae16dd" && ip4 && icmp4)), action=(next;)
>   table=1(      ls_out_acl), priority= 2002, match=(!ct.new && ct.est &&
!ct.rpl && ct_mark[0] == 0 && (outport ==
"0a7409c8-d179-4915-9eb2-f53426ae16dd" && ip4 && tcp && tcp.dst == 22)),
action=(next;)
>   table=1(      ls_out_acl), priority= 2002, match=(((ct.new && !ct.est)
|| (!ct.new && ct.est && !ct.rpl && ct_mark[0] == 1)) && (outport ==
"0a7409c8-d179-4915-9eb2-f53426ae16dd" && ip4 && icmp4)),
action=(ct_commit(ct_mark=0); next;)
>   table=1(      ls_out_acl), priority= 2002, match=(((ct.new && !ct.est)
|| (!ct.new && ct.est && !ct.rpl && ct_mark[0] == 1)) && (outport ==
"0a7409c8-d179-4915-9eb2-f53426ae16dd" && ip4 && tcp && tcp.dst == 22)),
action=(ct_commit(ct_mark=0); next;)
>   table=1(      ls_out_acl), priority= 2001, match=((!ct.est || (ct.est
&& ct_mark[0] == 1)) && (outport == "0a7409c8-d179-4915-9eb2-f53426ae16dd"
&& ip)), action=(drop;)
>   table=1(      ls_out_acl), priority= 2001, match=(ct.est && ct_mark[0]
== 0 && (outport == "0a7409c8-d179-4915-9eb2-f53426ae16dd" && ip)),
action=(ct_commit(ct_mark=1);)
>   table=1(      ls_out_acl), priority=    1, match=(ip && (!ct.est ||
(ct.est && ct_mark[0] == 1))), action=(ct_commit(ct_mark=0); next;)
>   table=1(      ls_out_acl), priority=    0, match=(1), action=(next;)
> ...
>
> One way I tested this by leaving ping running, ensuring that it was
> blocked when the rule for ICMP was deleted, and then re-allowed when
> the rule allowing ICMP was restored.  In this case, the ICMP
> connection is still known by the connection tracker, but the flows
> ensure that ct_mark gets reset back to 0.
>
> Reported-by: Xiao Li Xu <xiaol...@cn.ibm.com>
> Reported-at: https://bugs.launchpad.net/networking-ovn/+bug/1536080
> Suggested-by: Justin Pettit <jpet...@ovn.org>
> Signed-off-by: Russell Bryant <russ...@ovn.org>
> ---
>  ovn/northd/ovn-northd.8.xml |  56 ++++++++++---
>  ovn/northd/ovn-northd.c     | 189
+++++++++++++++++++++++++++++++++-----------
>  2 files changed, 184 insertions(+), 61 deletions(-)
>
> diff --git a/ovn/northd/ovn-northd.8.xml b/ovn/northd/ovn-northd.8.xml
> index 902b916..c8ddb1b 100644
> --- a/ovn/northd/ovn-northd.8.xml
> +++ b/ovn/northd/ovn-northd.8.xml
> @@ -146,7 +146,8 @@
>        in table 2.  It contains a priority-0 flow that simply moves
>        traffic to table 2.  If stateful ACLs are used in the logical
>        datapath, a priority-100 flow is added that sends IP packets to
> -      the connection tracker before advancing to table 2.
> +      the connection tracker with the <code>ct_next;</code> action
> +      before advancing to table 2.
>      </p>
>
>      <h3>Ingress table 2: <code>from-lport</code> ACLs</h3>
> @@ -154,15 +155,31 @@
>      <p>
>        Logical flows in this table closely reproduce those in the
>        <code>ACL</code> table in the <code>OVN_Northbound</code> database
> -      for the <code>from-lport</code> direction.  <code>allow</code>
> -      ACLs translate into logical flows with the <code>next;</code>
> -      action, <code>allow-related</code> ACLs translate into logical
> -      flows with the <code>ct_commit; next;</code> actions, other ACLs
> -      translate to <code>drop;</code>.  The <code>priority</code> values
> -      from the <code>ACL</code> 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 <code>from-lport</code> direction. The
<code>priority</code>
> +      values from the <code>ACL</code> table have a limited range and
have
> +      1000 added to them to leave room for OVN default flows at both
> +      higher and lower priorities.
>      </p>
> +    <ul>
> +      <li>
> +        <code>allow</code> ACLs translate into logical flows with
> +        the <code>next;</code> action.  If there are any stateful ACLs
> +        on this datapath, then <code>alloc</code> ACLs translate to
> +        <code>ct_commit; next;</code>.
> +      </li>
> +      <li>
> +        <code>allow-related</code> ACLs translate into logical
> +        flows with the <code>ct_commit(ct_mark=0); next;</code> actions
> +        for new connections and "next;" for existing connections.
> +      </li>
> +      <li>
> +        Other ACLs translate to <code>drop;</code> for new or untracked
> +        connections and <code>ct_commit(ct_mark=1);</code> for known
> +        connections.  Setting <code>ct_mark</code> marks a connection
> +        as one that was previously allowed, but should no longer be
> +        allowed due to a policy change.
> +      </li>
> +    </ul>
>
>      <p>
>        Ingress table 2 also contains a priority 0 flow with action
> @@ -181,19 +198,32 @@
>        </li>
>
>        <li>
> -        A priority-65535 flow that allows any traffic that has been
> -        committed to the connection tracker (i.e., established flows).
> +        A priority-65535 flow that allows any traffic in the reply
> +        direction for a connection that has been committed to the
> +        connection tracker (i.e., established flows), as long as
> +        the committed flow does not have <code>ct_mark=1</code> set.
> +        We only handle traffic in the reply direction here because
> +        we want all packets going in the request direction to still
> +        go through the flows that implement the currently defined
> +        policy based on ACLs.  If a connection is no longer allowed by
> +        policy, <code>ct_mark</code> will get set and packets in the
> +        reply direction will no longer be allowed, either.
>        </li>
>
>        <li>
>          A priority-65535 flow that allows any traffic that is considered
>          related to a committed flow in the connection tracker (e.g., an
> -        ICMP Port Unreachable from a non-listening UDP port).
> +        ICMP Port Unreachable from a non-listening UDP port), as long
> +        as the committed flow does not have <code>ct_mark=1</code> set.
>        </li>
>
>        <li>
>          A priority-65535 flow that drops all traffic marked by the
> -        connection tracker as invalid.
> +        connection tracker as invalid or reply packets with
> +        <code>ct_mark=1</code> set meaning that the connection should
> +        no longer be allowed due to a policy change.  Packets in the
> +        request direction are skipped here to let a newly created
> +        ACL re-allow this connection.
>        </li>
>      </ul>
>
> diff --git a/ovn/northd/ovn-northd.c b/ovn/northd/ovn-northd.c
> index 35ec267..04364a6 100644
> --- a/ovn/northd/ovn-northd.c
> +++ b/ovn/northd/ovn-northd.c
> @@ -1134,48 +1134,77 @@ build_acls(struct ovn_datapath *od, struct hmap
*lflows, struct hmap *ports)
>           * commit IP flows.  This is because, while the initiater's
>           * direction may not have any stateful rules, the server's may
>           * and then its return traffic would not have an associated
> -         * conntrack entry and would return "+invalid". */
> -        ovn_lflow_add(lflows, od, S_SWITCH_IN_ACL, 1, "ip",
> -                      "ct_commit; next;");
> -        ovn_lflow_add(lflows, od, S_SWITCH_OUT_ACL, 1, "ip",
> -                      "ct_commit; next;");
> +         * conntrack entry and would return "+invalid".
> +         *
> +         * We use "ct_commit" for a connection that is not already known
> +         * by the connection tracker.  Once a connection is committed,
> +         * subsequent packets will hit the flow at priority 0 that just
> +         * uses "next;"
> +         *
> +         * We also check for established connections that have ct_mark
set
> +         * on them.  That's a connection that was disallowed, but is now
> +         * allowed by policy again since it hit this default-allow flow.
> +         * We need to clear the mark to let the connection continue.
> +         * Subsequent packets will hit the flow at priority 0 that just
> +         * uses "next;". */
> +        ovn_lflow_add(lflows, od, S_SWITCH_IN_ACL, 1,
> +                      "ip && (!ct.est || (ct.est && ct_mark[0] == 1))",
> +                      "ct_commit(ct_mark=0); next;");
> +        ovn_lflow_add(lflows, od, S_SWITCH_OUT_ACL, 1,
> +                      "ip && (!ct.est || (ct.est && ct_mark[0] == 1))",
> +                      "ct_commit(ct_mark=0); next;");
>
>          /* Ingress and Egress ACL Table (Priority 65535).
>           *
> -         * Always drop traffic that's in an invalid state.  This is
> -         * enforced at a higher priority than ACLs can be defined. */
> +         * Always drop traffic that's in an invalid state.  Also drop
> +         * reply direction packets for connections that have been marked
> +         * for deletion (bit 0 of ct_mark is set).
> +         *
> +         * This is enforced at a higher priority than ACLs can be
defined. */
>          ovn_lflow_add(lflows, od, S_SWITCH_IN_ACL, UINT16_MAX,
> -                      "ct.inv", "drop;");
> +                      "ct.inv || (ct.est && ct.rpl && ct_mark[0] == 1)",
> +                      "drop;");
>          ovn_lflow_add(lflows, od, S_SWITCH_OUT_ACL, UINT16_MAX,
> -                      "ct.inv", "drop;");
> +                      "ct.inv || (ct.est && ct.rpl && ct_mark[0] == 1)",
> +                      "drop;");
>
>          /* Ingress and Egress ACL Table (Priority 65535).
>           *
> -         * Always allow traffic that is established to a committed
> -         * conntrack entry.  This is enforced at a higher priority than
> +         * Allow reply traffic that is part of an established
> +         * conntrack entry that has not been marked for deletion
> +         * (bit 0 of ct_mark).  We only match traffic in the
> +         * reply direction because we want traffic in the request
> +         * direction to hit the currently defined policy from ACLs.
> +         *
> +         * This is enforced at a higher priority than
>           * ACLs can be defined. */
>          ovn_lflow_add(lflows, od, S_SWITCH_IN_ACL, UINT16_MAX,
> -                      "ct.est && !ct.rel && !ct.new && !ct.inv",
> +                      "ct.est && !ct.rel && !ct.new && !ct.inv "
> +                      "&& ct.rpl && ct_mark[0] == 0",
>                        "next;");
>          ovn_lflow_add(lflows, od, S_SWITCH_OUT_ACL, UINT16_MAX,
> -                      "ct.est && !ct.rel && !ct.new && !ct.inv",
> +                      "ct.est && !ct.rel && !ct.new && !ct.inv "
> +                      "&& ct.rpl && ct_mark[0] == 0",
>                        "next;");
>
>          /* Ingress and Egress ACL Table (Priority 65535).
>           *
> -         * Always allow traffic that is related to an existing conntrack
> -         * entry.  This is enforced at a higher priority than ACLs can
> -         * be defined.
> +         * Allow traffic that is related to an existing conntrack entry
that
> +         * has not been marked for deletion (bit 0 of ct_mark).
> +         *
> +         * This is enforced at a higher priority than ACLs can be
defined.
>           *
>           * NOTE: This does not support related data sessions (eg,
>           * a dynamically negotiated FTP data channel), but will allow
>           * related traffic such as an ICMP Port Unreachable through
>           * that's generated from a non-listening UDP port.  */
>          ovn_lflow_add(lflows, od, S_SWITCH_IN_ACL, UINT16_MAX,
> -                      "!ct.est && ct.rel && !ct.new && !ct.inv",
> +                      "!ct.est && ct.rel && !ct.new && !ct.inv "
> +                      "&& ct_mark[0] == 0",
>                        "next;");
>          ovn_lflow_add(lflows, od, S_SWITCH_OUT_ACL, UINT16_MAX,
> -                      "!ct.est && ct.rel && !ct.new && !ct.inv",
> +                      "!ct.est && ct.rel && !ct.new && !ct.inv "
> +                      "&& ct_mark[0] == 0",
>                        "next;");
>      }
>
> @@ -1185,38 +1214,102 @@ build_acls(struct ovn_datapath *od, struct hmap
*lflows, struct hmap *ports)
>          bool ingress = !strcmp(acl->direction, "from-lport") ? true
:false;
>          enum ovn_stage stage = ingress ? S_SWITCH_IN_ACL :
S_SWITCH_OUT_ACL;
>
> -        if (!strcmp(acl->action, "allow")) {
> -            /* If there are any stateful flows, we must even commit
"allow"
> -             * actions.  This is because, while the initiater's
> -             * direction may not have any stateful rules, the server's
> -             * may and then its return traffic would not have an
> -             * associated conntrack entry and would return "+invalid". */
> -            const char *actions = has_stateful ? "ct_commit; next;" :
"next;";
> -            ovn_lflow_add(lflows, od, stage,
> -                          acl->priority + OVN_ACL_PRI_OFFSET,
> -                          acl->match, actions);
> -        } else if (!strcmp(acl->action, "allow-related")) {
> +        if (!strcmp(acl->action, "allow")
> +            || !strcmp(acl->action, "allow-related")) {
> +            if (!has_stateful) {
> +                /* If there are any stateful flows, we must even commit
"allow"
> +                 * actions.  This is because, while the initiater's
> +                 * direction may not have any stateful rules, the
server's
> +                 * may and then its return traffic would not have an
> +                 * associated conntrack entry and would return
"+invalid". */
> +                ovn_lflow_add(lflows, od, stage,
> +                              acl->priority + OVN_ACL_PRI_OFFSET,
> +                              acl->match, "next;");
> +            } else {
> +                struct ds match = DS_EMPTY_INITIALIZER;
> +
> +                /* Commit the connection tracking entry if its a new
connection
> +                 * that matches this ACL.  After this commit, the reply
traffic
> +                 * is allowed by a flow we create at priority 65535,
defined
> +                 * earlier.
> +                 *
> +                 * It's also possible that a known connection was marked
for
> +                 * deletion after a policy was deleted, but the policy
was
> +                 * re-added while that connection is still known.  We
catch that
> +                 * case here and un-set ct_mark to indicate that the
connection
> +                 * should be allowed to resume.
> +                 */
> +                ds_put_format(&match, "((ct.new && !ct.est)"
> +                                      " || (!ct.new && ct.est && !ct.rpl
"
> +                                           "&& ct_mark[0] == 1)) "
> +                                      "&& (%s)", acl->match);
> +                ovn_lflow_add(lflows, od, stage,
> +                              acl->priority + OVN_ACL_PRI_OFFSET,
> +                              ds_cstr(&match), "ct_commit(ct_mark=0);
next;");
> +
> +                /* Match on traffic in the request direction for an
established
> +                 * connection tracking entry that has not been marked for
> +                 * deletion.  There is no need to commit here, so we can
just
> +                 * proceed to the next table. We use this to ensure that
this
> +                 * connection is still allowed by the currently defined
> +                 * policy. */
> +                ds_clear(&match);
> +                ds_put_format(&match,
> +                              "!ct.new && ct.est && !ct.rpl"
> +                              " && ct_mark[0] == 0 && (%s)",
> +                              acl->match);
> +                ovn_lflow_add(lflows, od, stage,
> +                              acl->priority + OVN_ACL_PRI_OFFSET,
> +                              ds_cstr(&match), "next;");
> +
> +                ds_destroy(&match);
> +            }
> +        } else if (!strcmp(acl->action, "drop")
> +                   || !strcmp(acl->action, "reject")) {
>              struct ds match = DS_EMPTY_INITIALIZER;
> +            /* XXX Need to support "reject", treat it as "drop;" for
now. */
> +
> +            if (has_stateful) {
> +                /* The implementation of "drop" differs if stateful ACLs
are in
> +                 * use for this datapath.  In that case, the actions
differ
> +                 * depending on whether the connection was previous
committed
> +                 * to the connection tracker with ct_commit.
> +                 *
> +                 * If the packet is not part of an established
connection, then
> +                 * we can simply drop it. */
> +                ds_put_format(&match,
> +                              "(!ct.est || (ct.est && ct_mark[0] == 1)) "
> +                              "&& (%s)",
> +                              acl->match);
> +                ovn_lflow_add(lflows, od, stage, acl->priority +
> +                        OVN_ACL_PRI_OFFSET, ds_cstr(&match), "drop;");
> +
> +                /* For an existing connection without ct_mark set, we've
> +                 * encountered a policy change. ACLs previously allowed
> +                 * this connection and we committed the connection
tracking
> +                 * entry.  Current policy says that we should drop this
> +                 * connection.  First, we set bit 0 of ct_mark to
indicate
> +                 * that this connection is set for deletion.  By not
> +                 * specifying "next;", we implicitly drop the packet
after
> +                 * updating conntrack state. */
> +
> +                ds_clear(&match);
> +                ds_put_format(&match,
> +                              "ct.est && ct_mark[0] == 0 && (%s)",
> +                              acl->match);
> +                ovn_lflow_add(lflows, od, stage,
> +                              acl->priority + OVN_ACL_PRI_OFFSET,
> +                              ds_cstr(&match), "ct_commit(ct_mark=1);");
>
> -            /* Commit the connection tracking entry, which allows all
> -             * other traffic related to this entry to flow due to the
> -             * 65535 priority flow defined earlier. */
> -            ds_put_format(&match, "ct.new && (%s)", acl->match);
> -            ovn_lflow_add(lflows, od, stage,
> -                          acl->priority + OVN_ACL_PRI_OFFSET,
> -                          ds_cstr(&match), "ct_commit; next;");
> -
> -            ds_destroy(&match);
> -        } else if (!strcmp(acl->action, "drop")) {
> -            ovn_lflow_add(lflows, od, stage,
> -                          acl->priority + OVN_ACL_PRI_OFFSET,
> -                          acl->match, "drop;");
> -        } else if (!strcmp(acl->action, "reject")) {
> -            /* xxx Need to support "reject". */
> -            VLOG_INFO("reject is not a supported action");
> -            ovn_lflow_add(lflows, od, stage,
> -                          acl->priority + OVN_ACL_PRI_OFFSET,
> -                          acl->match, "drop;");
> +                ds_destroy(&match);
> +            } else {
> +                /* There are no stateful ACLs in use on this datapath,
> +                 * so a "drop" ACL is simply the "drop" logical flow
action
> +                 * in all cases. */
> +                ovn_lflow_add(lflows, od, stage,
> +                              acl->priority + OVN_ACL_PRI_OFFSET,
> +                              acl->match, "drop;");
> +            }
>          }
>      }
>  }
> --
> 2.5.0
>

Acked-by: Han Zhou <zhou...@gmail.com>

--
Best regards,
Han
_______________________________________________
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev

Reply via email to