On Tue, Sep 22, 2020 at 5:40 AM Numan Siddique <num...@ovn.org> wrote:

>
>
> On Fri, Sep 11, 2020 at 3:07 AM Dumitru Ceara <dce...@redhat.com> wrote:
>
>> Until now, in case the ACL configuration generates openflows that have
>> the same match but different actions, ovn-controller was using the
>> following approach:
>> 1. If the flow being added contains conjunctive actions, merge its
>>    actions with the already existing flow.
>> 2. Otherwise, if the flow is being added incrementally
>>    (update_installed_flows_by_track), don't install the new flow but
>>    instead keep the old one.
>> 3. Otherwise, (update_installed_flows_by_compare), don't install the
>>    new flow but instead keep the old one.
>>
>> Even though one can argue that having an ACL with a match that includes
>> the match of another ACL is a misconfiguration, it can happen that the
>> users provision OVN like this. Depending on the order of reading and
>> installing the logical flows, the above operations can yield
>> unpredictable results, e.g., allow specific traffic but then after
>> ovn-controller is restarted (or a recompute happens) that specific
>> traffic starts being dropped.
>>
>> A simple example of ACL configuration is:
>> ovn-nbctl acl-add ls to-lport 3 '(ip4.src==10.0.0.1 ||
>> ip4.src==10.0.0.2) && (ip4.dst == 10.0.0.3 || ip4.dst == 10.0.0.4)' allow
>> ovn-nbctl acl-add ls to-lport 3 'ip4.src==10.0.0.1' allow
>> ovn-nbctl acl-add ls to-lport 2 'arp' allow
>> ovn-nbctl acl-add ls to-lport 1 'ip4' drop
>>
>> This is a pattern used by most CMSs:
>> - define a default deny policy.
>> - punch holes in the default deny policy based on user specific
>>   configurations.
>>
>> Without this commit the behavior for traffic from 10.0.0.1 to 10.0.0.5
>> is unpredictable. Depending on the order of operations traffic might be
>> dropped or allowed.
>>
>> It's also quite hard to force the CMS to ensure that such match overlaps
>> never occur.
>>
>> To address this issue we now resolve conflicts between flows with the
>> same match and different actions by giving precedence to less
>> restrictive flows. This means that if the installed flow has action
>> "conjunction" and the desired flow doesn't then we prefer the desired
>> flow. Similarly, if the desired flow has action "conjunction" and the
>> installed flow doesn't then we prefer the already installed flow.
>>
>> CC: Daniel Alvarez <dalva...@redhat.com>
>> CC: Han Zhou <hz...@ovn.org>
>> CC: Mark Michelson <mmich...@redhat.com>
>> CC: Numan Siddique <num...@ovn.org>
>> Reported-at: https://bugzilla.redhat.com/1871931
>> Acked-by: Mark Michelson <mmich...@redhat.com>
>> Signed-off-by: Dumitru Ceara <dce...@redhat.com>
>> ---
>>
>
>
>
> Thanks Dumitru for the patch.
>
> The added test case fails  because of recent changes to the ACL table
> number. With the below changes, the test case passes.
>
> ***********************
> diff --git a/tests/ovn.at b/tests/ovn.at
> index 9d8ce3bb2e..11e7dfd160 100644
> --- a/tests/ovn.at
> +++ b/tests/ovn.at
> @@ -13808,12 +13808,12 @@ ovn-nbctl acl-add ls1 to-lport 3
> 'ip4.src==10.0.0.1' allow
>  ovn-nbctl --wait=hv sync
>
>  # Check OVS flows, the less restrictive flows should have been installed.
> -AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=44 | \
> +AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=45 | \
>      grep "priority=1003" | awk '{print $7 " " $8}' | sort], [0], [dnl
> -priority=1003,conj_id=2,ip,metadata=0x1 actions=resubmit(,45)
> +priority=1003,conj_id=2,ip,metadata=0x1 actions=resubmit(,46)
>  priority=1003,ip,metadata=0x1,nw_dst=10.0.0.3 actions=conjunction(2,1/2)
>  priority=1003,ip,metadata=0x1,nw_dst=10.0.0.4 actions=conjunction(2,1/2)
> -priority=1003,ip,metadata=0x1,nw_src=10.0.0.1 actions=resubmit(,45)
> +priority=1003,ip,metadata=0x1,nw_src=10.0.0.1 actions=resubmit(,46)
>  priority=1003,ip,metadata=0x1,nw_src=10.0.0.2 actions=conjunction(2,2/2)
>  ])
>
> @@ -13849,9 +13849,9 @@ ovn-nbctl acl-del ls1 to-lport 3
> 'ip4.src==10.0.0.1'
>  ovn-nbctl --wait=hv sync
>
>  # Check OVS flows, the 10.0.0.1 conjunction should have been reinstalled.
> -AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=44 | \
> +AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=45 | \
>      grep "priority=1003" | awk '{print $7 " " $8}' | sort], [0], [dnl
> -priority=1003,conj_id=2,ip,metadata=0x1 actions=resubmit(,45)
> +priority=1003,conj_id=2,ip,metadata=0x1 actions=resubmit(,46)
>  priority=1003,ip,metadata=0x1,nw_dst=10.0.0.3 actions=conjunction(2,1/2)
>  priority=1003,ip,metadata=0x1,nw_dst=10.0.0.4 actions=conjunction(2,1/2)
>  priority=1003,ip,metadata=0x1,nw_src=10.0.0.1 actions=conjunction(2,2/2)
> **********************
>
> The patch LGTM with one minor comment.
>
> Acked-by: Numan Siddique <num...@ovn.org>
>
> I will wait for Han if he has any comments before applying this patch.
>
>
I will take another look at this tomorrow.

Thanks,
Han


> Thanks
> Numan
>
>
>> v3:
>> - Add Mark's ack.
>> - Add last missing pcap check in the test.
>> v2:
>> - Address Han's comments:
>>   - Do not delete desired flow that cannot be merged, it might be
>>     installed later.
>>   - Fix typos in the commit log.
>> - Update the test to check the OVS flows.
>> ---
>>  controller/ofctrl.c | 124 +++++++++++++++++++++++++++++++++++--
>>  tests/ovn.at        | 174
>> ++++++++++++++++++++++++++++++++++++++++++++++++++++
>>  2 files changed, 293 insertions(+), 5 deletions(-)
>>
>> diff --git a/controller/ofctrl.c b/controller/ofctrl.c
>> index 81a00c8..819e8cf 100644
>> --- a/controller/ofctrl.c
>> +++ b/controller/ofctrl.c
>> @@ -916,6 +916,57 @@ link_flow_to_sb(struct ovn_desired_flow_table
>> *flow_table,
>>      ovs_list_insert(&stf->flows, &sfr->flow_list);
>>  }
>>
>> +static bool
>> +flow_action_has_conj(const struct ovn_flow *f)
>> +{
>> +    const struct ofpact *a = NULL;
>> +
>> +    OFPACT_FOR_EACH (a, f->ofpacts, f->ofpacts_len) {
>> +        if (a->type == OFPACT_CONJUNCTION) {
>> +            return true;
>> +        }
>> +    }
>> +    return false;
>> +}
>> +
>> +/* Returns true if the actions of 'f1' cannot be merged with the actions
>> of
>> + * 'f2'. This is the case when one of the flow contains action
>> "conjunction"
>> + * and the other doesn't. The function always populates 'f1_has_conj' and
>> + * 'f2_has_conj'.
>> + */
>> +static bool
>> +flow_actions_conflict(const struct ovn_flow *f1, const struct ovn_flow
>> *f2,
>> +                      bool *f1_has_conj, bool *f2_has_conj)
>> +{
>> +    *f1_has_conj = flow_action_has_conj(f1);
>> +    *f2_has_conj = flow_action_has_conj(f2);
>> +
>> +    if ((*f1_has_conj) && !(*f2_has_conj) && f2->ofpacts_len) {
>> +        return true;
>> +    }
>> +
>> +    if ((*f2_has_conj) && !(*f1_has_conj) && f1->ofpacts_len) {
>> +        return true;
>> +    }
>> +
>> +    return false;
>> +}
>> +
>> +static void
>> +flow_log_actions_conflict(const char *msg, const struct ovn_flow *f1,
>> +                          const struct ovn_flow *f2)
>> +{
>> +    static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 1);
>> +
>> +    char *f1_s = ovn_flow_to_string(f1);
>> +    char *f2_s = ovn_flow_to_string(f2);
>> +
>> +    VLOG_WARN_RL(&rl, "Flow actions conflict: %s, flow-1: %s, flow-2:
>> %s",
>> +                 msg, f1_s, f2_s);
>> +    free(f1_s);
>> +    free(f2_s);
>> +}
>> +
>>  /* Flow table interfaces to the rest of ovn-controller. */
>>
>>  /* Adds a flow to 'desired_flows' with the specified 'match' and
>> 'actions' to
>> @@ -985,14 +1036,46 @@ ofctrl_add_or_append_flow(struct
>> ovn_desired_flow_table *desired_flows,
>>      struct desired_flow *existing;
>>      existing = desired_flow_lookup(desired_flows, &f->flow, NULL);
>>      if (existing) {
>> -        /* There's already a flow with this particular match. Append the
>> -         * action to that flow rather than adding a new flow
>> +        /* There's already a flow with this particular match. Try to
>> append
>> +         * the action to that flow rather than adding a new flow.
>> +         *
>> +         * If exactly one of the existing or new flow includes a
>> conjunction
>> +         * action then we can't merge the actions. In that case keep the
>> flow
>> +         * without conjunction action as this is the least restrictive
>> one.
>> +         */
>> +        bool existing_conj = false;
>> +        bool new_conj = false;
>> +
>> +        if (flow_actions_conflict(&existing->flow, &f->flow,
>> &existing_conj,
>> +                                  &new_conj)) {
>> +            flow_log_actions_conflict("Cannot merge conj with non-conj
>> action",
>> +                                      &existing->flow, &f->flow);
>> +        }
>> +
>> +        /* If the existing flow is less restrictive (i.e., no conjunction
>> +         * action) then keep it installed. Store however the flow with
>> +         * conjunction action too as it will be installed when the
>> current
>> +         * one is removed.
>>           */
>> +        if (!existing_conj && new_conj) {
>> +            hmap_insert(&desired_flows->match_flow_table,
>> &f->match_hmap_node,
>> +                        f->flow.hash);
>> +            link_flow_to_sb(desired_flows, f, sb_uuid);
>> +            return;
>> +        }
>> +
>>          uint64_t compound_stub[64 / 8];
>>          struct ofpbuf compound;
>>          ofpbuf_use_stub(&compound, compound_stub, sizeof(compound_stub));
>> -        ofpbuf_put(&compound, existing->flow.ofpacts,
>> -                   existing->flow.ofpacts_len);
>> +
>> +        /* Only merge actions if both flows either have action
>> conjunction
>> +         * or non-conjunction. Otherwise use the actions in the new flow,
>> +         * the least restrictive.
>> +         */
>> +        if (existing_conj == new_conj) {
>> +            ofpbuf_put(&compound, existing->flow.ofpacts,
>> +                       existing->flow.ofpacts_len);
>> +        }
>>
>
> In the case where 'existing_conj'  is true and 'new_conj' is false, we can
> actually avoid the compound_stub
> I'd do something like below
>
> <*************************************>
>
> static void
> ofctrl_swap_flow_actions(struct ovn_flow *a, struct ovn_flow *b)
> {
>     struct ofpact *tmp = a->ofpacts;
>     size_t tmp_len = a->ofpacts_len;
>
>     a->ofpacts = b->ofpacts;
>     a->ofpacts_len = b->ofpacts_len;
>
>     b->ofpacts = tmp;
>     b->ofpacts_len = tmp_len;
> }
>
> void
> ofctrl_add_or_append_flow(.....)
> {
> ...
> ...
> ..
> if (!existing_conj && new_conj) {
>    ...
>    ...
>    return;
> }
>
> if (existing_conj && !new_conj) {
>     ofctrl_swap_flow_actions(f, existing);
> } else {
>     uint64_t compound_stub[64 / 8];
>     struct ofpbuf compound;
>     ofpbuf_use_stub(&compound, compound_stub, sizeof(compound_stub));
>
>     ofpbuf_put(&compound, existing->flow.ofpacts,
> existing->flow.ofpacts_len);
>     ofpbuf_put(&compound, f->flow.ofpacts, f->flow.ofpacts_len);
>
>     free(existing->flow.ofpacts);
>     existing->flow.ofpacts = xmemdup(compound.data, compound.size);
>     existing->flow.ofpacts_len = compound.size;
>
>     ofpbuf_uninit(&compound);
> }
> desired_flow_destroy(f);
> f = existing;
> ...
> <**********************************************>
>
> But I'm ok with the existing code too.
>
> Thanks
> Numan
>
>
>
>
>>          ofpbuf_put(&compound, f->flow.ofpacts, f->flow.ofpacts_len);
>>
>>          free(existing->flow.ofpacts);
>> @@ -1687,6 +1770,21 @@ update_installed_flows_by_compare(struct
>> ovn_desired_flow_table *flow_table,
>>              /* Copy 'd' from 'flow_table' to installed_flows. */
>>              i = installed_flow_dup(d);
>>              hmap_insert(&installed_flows, &i->match_hmap_node,
>> i->flow.hash);
>> +        } else if (i->desired_flow != d) {
>> +            /* If a matching installed flow was found but its actions are
>> +             * conflicting with the desired flow actions, we should chose
>> +             * to install the least restrictive one (i.e., no conjunctive
>> +             * action).
>> +             */
>> +            bool i_conj = false;
>> +            bool d_conj = false;
>> +
>> +            if (flow_actions_conflict(&i->flow, &d->flow, &i_conj,
>> &d_conj) &&
>> +                    i_conj && !d_conj) {
>> +                flow_log_actions_conflict("Use new flow", &i->flow,
>> &d->flow);
>> +                installed_flow_mod(&i->flow, &d->flow, msgs);
>> +                ovn_flow_log(&i->flow, "updating installed");
>> +            }
>>          }
>>          link_installed_to_desired(i, d);
>>      }
>> @@ -1817,7 +1915,23 @@ update_installed_flows_by_track(struct
>> ovn_desired_flow_table *flow_table,
>>                  installed_flow_mod(&i->flow, &f->flow, msgs);
>>              } else {
>>                  /* Adding a new flow that conflicts with an existing
>> installed
>> -                 * flow, so just add it to the link. */
>> +                 * flow, so just add it to the link.
>> +                 *
>> +                 * However, if the existing installed flow is less
>> restrictive
>> +                 * (i.e., no conjunctive action), we should chose it
>> over the
>> +                 * existing installed flow.
>> +                 */
>> +                bool i_conj = false;
>> +                bool f_conj = false;
>> +
>> +                if (flow_actions_conflict(&i->flow, &f->flow, &i_conj,
>> +                                          &f_conj) &&
>> +                        i_conj && !f_conj) {
>> +                    flow_log_actions_conflict("Use new flow",
>> +                                              &i->flow, &f->flow);
>> +                    ovn_flow_log(&i->flow, "updating installed
>> (tracked)");
>> +                    installed_flow_mod(&i->flow, &f->flow, msgs);
>> +                }
>>                  link_installed_to_desired(i, f);
>>              }
>>              /* The track_list_node emptyness is used to check if the
>> node is
>> diff --git a/tests/ovn.at b/tests/ovn.at
>> index 4e58722..118ed48 100644
>> --- a/tests/ovn.at
>> +++ b/tests/ovn.at
>> @@ -13709,6 +13709,180 @@ grep conjunction.*conjunction.*conjunction | wc
>> -l`])
>>  OVN_CLEANUP([hv1])
>>  AT_CLEANUP
>>
>> +AT_SETUP([ovn -- Superseeding ACLs with conjunction])
>> +ovn_start
>> +
>> +ovn-nbctl ls-add ls1
>> +
>> +ovn-nbctl lsp-add ls1 ls1-lp1 \
>> +-- lsp-set-addresses ls1-lp1 "f0:00:00:00:00:01"
>> +
>> +ovn-nbctl lsp-add ls1 ls1-lp2 \
>> +-- lsp-set-addresses ls1-lp2 "f0:00:00:00:00:02"
>> +
>> +net_add n1
>> +sim_add hv1
>> +
>> +as hv1
>> +ovs-vsctl add-br br-phys
>> +ovn_attach n1 br-phys 192.168.0.1
>> +ovs-vsctl -- add-port br-int hv1-vif1 -- \
>> +    set interface hv1-vif1 external-ids:iface-id=ls1-lp1 \
>> +    options:tx_pcap=hv1/vif1-tx.pcap \
>> +    options:rxq_pcap=hv1/vif1-rx.pcap \
>> +    ofport-request=1
>> +
>> +ovs-vsctl -- add-port br-int hv1-vif2 -- \
>> +    set interface hv1-vif2 external-ids:iface-id=ls1-lp2 \
>> +    options:tx_pcap=hv1/vif2-tx.pcap \
>> +    options:rxq_pcap=hv1/vif2-rx.pcap \
>> +    ofport-request=2
>> +
>> +# test_ip INPORT SRC_MAC DST_MAC SRC_IP DST_IP OUTPORT...
>> +#
>> +# This shell function causes an ip packet to be received on INPORT.
>> +# The packet's content has Ethernet destination DST and source SRC
>> +# (each exactly 12 hex digits) and Ethernet type ETHTYPE (4 hex digits).
>> +# The OUTPORTs (zero or more) list the VIFs on which the packet should
>> +# be received.  INPORT and the OUTPORTs are specified as logical switch
>> +# port numbers, e.g. 11 for vif11.
>> +test_ip() {
>> +    # This packet has bad checksums but logical L3 routing doesn't check.
>> +    local inport=$1 src_mac=$2 dst_mac=$3 src_ip=$4 dst_ip=$5
>> +    local
>> packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}\
>> +${dst_ip}0035111100080000
>> +    shift; shift; shift; shift; shift
>> +    as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 $packet
>> +    for outport; do
>> +        echo $packet >> $outport.expected
>> +    done
>> +}
>> +
>> +ip_to_hex() {
>> +    printf "%02x%02x%02x%02x" "$@"
>> +}
>> +
>> +reset_pcap_file() {
>> +    local iface=$1
>> +    local pcap_file=$2
>> +    ovs-vsctl -- set Interface $iface options:tx_pcap=dummy-tx.pcap \
>> +options:rxq_pcap=dummy-rx.pcap
>> +    rm -f ${pcap_file}*.pcap
>> +    ovs-vsctl -- set Interface $iface
>> options:tx_pcap=${pcap_file}-tx.pcap \
>> +options:rxq_pcap=${pcap_file}-rx.pcap
>> +}
>> +
>> +# Add a default deny ACL and an allow ACL for specific IP traffic.
>> +ovn-nbctl acl-add ls1 to-lport 2 'arp' allow
>> +ovn-nbctl acl-add ls1 to-lport 1 'ip4' drop
>> +ovn-nbctl acl-add ls1 to-lport 3 '(ip4.src==10.0.0.1 ||
>> ip4.src==10.0.0.2) && (ip4.dst == 10.0.0.3 || ip4.dst == 10.0.0.4)' allow
>> +ovn-nbctl --wait=hv sync
>> +
>> +# Traffic 10.0.0.1, 10.0.0.2 -> 10.0.0.3, 10.0.0.4 should be allowed.
>> +for src in `seq 1 2`; do
>> +    for dst in `seq 3 4`; do
>> +        sip=`ip_to_hex 10 0 0 $src`
>> +        dip=`ip_to_hex 10 0 0 $dst`
>> +
>> +        test_ip 1 f00000000001 f00000000002 $sip $dip 2
>> +    done
>> +done
>> +
>> +# Traffic 10.0.0.1, 10.0.0.2 -> 10.0.0.5 should be dropped.
>> +dip=`ip_to_hex 10 0 0 5`
>> +for src in `seq 1 2`; do
>> +    sip=`ip_to_hex 10 0 0 $src`
>> +
>> +    test_ip 1 f00000000001 f00000000002 $sip $dip
>> +done
>> +
>> +cat 2.expected > expout
>> +$PYTHON "$ovs_srcdir/utilities/ovs-pcap.in" hv1/vif2-tx.pcap > 2.packets
>> +AT_CHECK([cat 2.packets], [0], [expout])
>> +reset_pcap_file hv1-vif2 hv1/vif2
>> +rm -f 2.packets
>> +> 2.expected
>> +
>> +# Add a less restrictive allow ACL for src IP 10.0.0.1
>> +ovn-nbctl acl-add ls1 to-lport 3 'ip4.src==10.0.0.1' allow
>> +ovn-nbctl --wait=hv sync
>> +
>> +# Check OVS flows, the less restrictive flows should have been installed.
>> +AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=44 | \
>> +    grep "priority=1003" | awk '{print $7 " " $8}' | sort], [0], [dnl
>> +priority=1003,conj_id=2,ip,metadata=0x1 actions=resubmit(,45)
>> +priority=1003,ip,metadata=0x1,nw_dst=10.0.0.3 actions=conjunction(2,1/2)
>> +priority=1003,ip,metadata=0x1,nw_dst=10.0.0.4 actions=conjunction(2,1/2)
>> +priority=1003,ip,metadata=0x1,nw_src=10.0.0.1 actions=resubmit(,45)
>> +priority=1003,ip,metadata=0x1,nw_src=10.0.0.2 actions=conjunction(2,2/2)
>> +])
>> +
>> +# Traffic 10.0.0.1, 10.0.0.2 -> 10.0.0.3, 10.0.0.4 should be allowed.
>> +for src in `seq 1 2`; do
>> +    for dst in `seq 3 4`; do
>> +        sip=`ip_to_hex 10 0 0 $src`
>> +        dip=`ip_to_hex 10 0 0 $dst`
>> +
>> +        test_ip 1 f00000000001 f00000000002 $sip $dip 2
>> +    done
>> +done
>> +
>> +# Traffic 10.0.0.2 -> 10.0.0.5 should be dropped.
>> +sip=`ip_to_hex 10 0 0 2`
>> +dip=`ip_to_hex 10 0 0 5`
>> +test_ip 1 f00000000001 f00000000002 $sip $dip
>> +
>> +# Traffic 10.0.0.1 -> 10.0.0.5 should be allowed.
>> +sip=`ip_to_hex 10 0 0 1`
>> +dip=`ip_to_hex 10 0 0 5`
>> +test_ip 1 f00000000001 f00000000002 $sip $dip 2
>> +
>> +cat 2.expected > expout
>> +$PYTHON "$ovs_srcdir/utilities/ovs-pcap.in" hv1/vif2-tx.pcap > 2.packets
>> +AT_CHECK([cat 2.packets], [0], [expout])
>> +reset_pcap_file hv1-vif2 hv1/vif2
>> +rm -f 2.packets
>> +> 2.expected
>> +
>> +# Remove the less restrictive allow ACL.
>> +ovn-nbctl acl-del ls1 to-lport 3 'ip4.src==10.0.0.1'
>> +ovn-nbctl --wait=hv sync
>> +
>> +# Check OVS flows, the 10.0.0.1 conjunction should have been reinstalled.
>> +AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=44 | \
>> +    grep "priority=1003" | awk '{print $7 " " $8}' | sort], [0], [dnl
>> +priority=1003,conj_id=2,ip,metadata=0x1 actions=resubmit(,45)
>> +priority=1003,ip,metadata=0x1,nw_dst=10.0.0.3 actions=conjunction(2,1/2)
>> +priority=1003,ip,metadata=0x1,nw_dst=10.0.0.4 actions=conjunction(2,1/2)
>> +priority=1003,ip,metadata=0x1,nw_src=10.0.0.1 actions=conjunction(2,2/2)
>> +priority=1003,ip,metadata=0x1,nw_src=10.0.0.2 actions=conjunction(2,2/2)
>> +])
>> +
>> +# Traffic 10.0.0.1, 10.0.0.2 -> 10.0.0.3, 10.0.0.4 should be allowed.
>> +for src in `seq 1 2`; do
>> +    for dst in `seq 3 4`; do
>> +        sip=`ip_to_hex 10 0 0 $src`
>> +        dip=`ip_to_hex 10 0 0 $dst`
>> +
>> +        test_ip 1 f00000000001 f00000000002 $sip $dip 2
>> +    done
>> +done
>> +
>> +# Traffic 10.0.0.1, 10.0.0.2 -> 10.0.0.5 should be dropped.
>> +dip=`ip_to_hex 10 0 0 5`
>> +for src in `seq 1 2`; do
>> +    sip=`ip_to_hex 10 0 0 $src`
>> +
>> +    test_ip 1 f00000000001 f00000000002 $sip $dip
>> +done
>> +
>> +cat 2.expected > expout
>> +$PYTHON "$ovs_srcdir/utilities/ovs-pcap.in" hv1/vif2-tx.pcap > 2.packets
>> +AT_CHECK([cat 2.packets], [0], [expout])
>> +
>> +OVN_CLEANUP([hv1])
>> +AT_CLEANUP
>> +
>>  # 3 hypervisors, one logical switch, 3 logical ports per hypervisor
>>  AT_SETUP([ovn -- L2 Drop and Allow ACL w/ Stateful ACL])
>>  ovn_start
>> --
>> 1.8.3.1
>>
>> _______________________________________________
>> dev mailing list
>> d...@openvswitch.org
>> https://mail.openvswitch.org/mailman/listinfo/ovs-dev
>>
>>
_______________________________________________
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to