> Hi Lorenzo,

Hi Mark,

thx for the review.

> 
> I tried running the system test from this patch against ovn main and it
> passes even without the changes in northd. I think this is because the
> alice1 and foo1 ports need to be bound on different hvs to properly test the
> changes in northd.

ack, you are right. I will drop the system-ovn test and I will add ovn.at one.

> 
> See below for other comments.
> 
> On 5/24/23 13:56, Lorenzo Bianconi wrote:
> > In the current codebase for distributed gw router port use-case,
> > it is not possible to add a load balancer that redirects the traffic
> > to a back-end if it is used as internal IP of a FIP NAT rule since
> > the reply traffic is never centralized. Fix the issue centralizing the
> > traffic if it is the reply packet for the load balancer.
> > 
> > Reported-at: https://bugzilla.redhat.com/show_bug.cgi?id=2023609
> > Signed-off-by: Lorenzo Bianconi <lorenzo.bianc...@redhat.com>
> > ---
> > Changes since v2:
> > - rebase on top of ovn main branch
> > - fix spelling
> > Changes since v1:
> > - add new system-test and unit-test
> > ---
> >   northd/northd.c         |  15 ++++++
> >   northd/ovn-northd.8.xml |  16 +++++++
> >   tests/ovn-northd.at     |  48 +++++++++++++++++++
> >   tests/system-ovn.at     | 100 ++++++++++++++++++++++++++++++++++++++++
> >   4 files changed, 179 insertions(+)
> > 
> > diff --git a/northd/northd.c b/northd/northd.c
> > index a6eca916b..6317c36fd 100644
> > --- a/northd/northd.c
> > +++ b/northd/northd.c
> > @@ -10740,6 +10740,8 @@ build_distr_lrouter_nat_flows_for_lb(struct 
> > lrouter_nat_lb_flows_ctx *ctx,
> >                                        struct ovn_datapath *od)
> >   {
> >       struct ovn_port *dgp = od->l3dgw_ports[0];
> > +    struct ds gw_redir_match = DS_EMPTY_INITIALIZER;
> > +    struct ds gw_redir_action = DS_EMPTY_INITIALIZER;
> >       const char *undnat_action;
> > @@ -10784,6 +10786,17 @@ build_distr_lrouter_nat_flows_for_lb(struct 
> > lrouter_nat_lb_flows_ctx *ctx,
> >           return;
> >       }
> > +    /* We need to centralize the LB traffic to properly perform
> > +     * the undnat stage.
> > +     */
> > +    ds_put_format(&gw_redir_match, "%s) && outport == %s",
> > +                  ds_cstr(ctx->undnat_match), dgp->json_key);
> > +    ds_put_format(&gw_redir_action, "outport = %s; next;",
> > +                  dgp->cr_port->json_key);
> > +    ovn_lflow_add_with_hint(ctx->lflows, od, S_ROUTER_IN_GW_REDIRECT,
> > +                            200, ds_cstr(&gw_redir_match),
> > +                            ds_cstr(&gw_redir_action), 
> > &ctx->lb->nlb->header_);
> > +
> >       ds_put_format(ctx->undnat_match, ") && (inport == %s || outport == 
> > %s)"
> >                     " && is_chassis_resident(%s)", dgp->json_key, 
> > dgp->json_key,
> >                     dgp->cr_port->json_key);
> > @@ -10791,6 +10804,8 @@ build_distr_lrouter_nat_flows_for_lb(struct 
> > lrouter_nat_lb_flows_ctx *ctx,
> >                               ds_cstr(ctx->undnat_match), undnat_action,
> >                               &ctx->lb->nlb->header_);
> >       ds_truncate(ctx->undnat_match, undnat_match_len);
> > +    ds_destroy(&gw_redir_match);
> > +    ds_destroy(&gw_redir_action);
> >   }
> >   static void
> > diff --git a/northd/ovn-northd.8.xml b/northd/ovn-northd.8.xml
> > index 540fe03bd..295f52b11 100644
> > --- a/northd/ovn-northd.8.xml
> > +++ b/northd/ovn-northd.8.xml
> > @@ -4578,6 +4578,22 @@ icmp6 {
> >       </p>
> >       <ul>
> > +      <li>
> > +        For all the configured load balancing rules that include an IPv4
> > +        address <var>VIP</var>, and a list of IPv4 backend addresses
> > +        <var>B0</var>, <var>B1</var> .. <var>Bn</var> defined for the
> > +        <var>VIP</var> a priority-200 flow is added that matches <code>
> > +        ip4 &amp;&amp; (ip4.src == <var>B0</var> || ip4.src == 
> > <var>B1</var>
> > +        || ... || ip4.src == <var>Bn</var>)</code> with an action <code>
> > +        outport = <var>CR</var>; next;</code> where <var>CR</var> is the
> > +        <code>chassisredirect</code> port representing the instance of the
> > +        logical router distributed gateway port on the gateway chassis.
> > +        If the backend IPv4 address <var>Bx</var> is also configured with
> > +        L4 port <var>PORT</var> of protocol <var>P</var>, then the match
> > +        also includes <code>P.src</code> == <var>PORT</var>.
> > +        Similar flows are addeded for IPv6.
> 
> s/addeded/added/

ack, I will fix it.

> 
> > +      </li>
> > +
> >         <li>
> >           For each NAT rule in the OVN Northbound database that can
> >           be handled in a distributed manner, a priority-100 logical
> > diff --git a/tests/ovn-northd.at b/tests/ovn-northd.at
> > index e3669bdf5..59f932c5f 100644
> > --- a/tests/ovn-northd.at
> > +++ b/tests/ovn-northd.at
> > @@ -9484,3 +9484,51 @@ AT_CHECK([ovn-sbctl lflow-list sw | grep 
> > ls_out_pre_lb | grep priority=110 | gre
> >   AT_CLEANUP
> >   ])
> > +
> > +OVN_FOR_EACH_NORTHD_NO_HV([
> > +AT_SETUP([check fip and lb flows])
> > +AT_KEYWORDS([fip-lb-flows])
> > +ovn_start
> > +
> > +ovn-nbctl lr-add R1
> > +ovn-nbctl lrp-add R1 R1-S0 02:ac:10:01:00:01 10.0.0.1/24 1000::a/64
> > +ovn-nbctl lrp-add R1 R1-PUB 02:ac:20:01:01:01 172.16.0.1/24 3000::a/64
> > +ovn-nbctl lrp-set-gateway-chassis R1-PUB hv1 20
> > +
> > +ovn-nbctl ls-add S0
> > +ovn-nbctl lsp-add S0 S0-R1
> > +ovn-nbctl lsp-set-type S0-R1 router
> > +ovn-nbctl lsp-set-addresses S0-R1 02:ac:10:01:00:01
> > +ovn-nbctl lsp-set-options S0-R1 router-port=R1-S0
> > +ovn-nbctl lsp-add S0 S0-P0
> > +ovn-nbctl lsp-set-addresses S0-P0 "50:54:00:00:00:03 10.0.0.3 1000::3"
> > +
> > +ovn-nbctl lr-nat-add R1 dnat_and_snat 172.16.0.110 10.0.0.3 S0-P0 
> > 30:54:00:00:00:03
> > +ovn-nbctl lr-nat-add R1 dnat_and_snat 3000::c 1000::3 S0-P0 
> > 40:54:00:00:00:03
> 
> Nit: All ovn-nbctl commands should be replaced with `check ovn-nbctl`
> instead. This has two benefits:
> 
> 1) If syntax breaks for any of the commands at some point, the test will
> fail as early as possible.
> 2) The check() function echoes the command you are executing, so the
> testsuite.log file will have more information in it about what all was run.
> 
> I won't bother pointing out all of the instances where this can be done. A
> basic rule to follow is that if you are writing a command that outputs
> nothing to stdout, it's a good idea to wrap it in the check() function.

ack, I will fix it.

> 
> > +ovn-sbctl dump-flows R1 > R1flows
> > +AT_CAPTURE_FILE([R1flows])
> > +AT_CHECK([grep "lr_in_gw_redirect" R1flows | sort], [0], [dnl
> > +  table=20(lr_in_gw_redirect  ), priority=0    , match=(1), action=(next;)
> > +  table=20(lr_in_gw_redirect  ), priority=100  , match=(ip4.src == 
> > 10.0.0.3 && outport == "R1-PUB" && is_chassis_resident("S0-P0")), 
> > action=(eth.src = 30:54:00:00:00:03; reg1 = 172.16.0.110; next;)
> > +  table=20(lr_in_gw_redirect  ), priority=100  , match=(ip6.src == 1000::3 
> > && outport == "R1-PUB" && is_chassis_resident("S0-P0")), action=(eth.src = 
> > 40:54:00:00:00:03; xxreg1 = 3000::c; next;)
> > +  table=20(lr_in_gw_redirect  ), priority=50   , match=(outport == 
> > "R1-PUB"), action=(outport = "cr-R1-PUB"; next;)
> > +])
> 
> As someone who just had to make a major change to the table numbers in
> northd, I'm now going to suggest that any checks of logical flows should
> have their table numbers anonymized. This allows for changes to be made to
> the tables without affecting northd tests.
> 
> Something like:
> 
> grep "lr_in_gw_redirect" R1flows | sort | sed s'table=../table=??'
> 
> will work here.
> 
> The same goes for the logical flow check that is performed lower down as
> well.

ack, I will fix it.

> 
> > +
> > +ovn-nbctl lb-add lb_tcp4 172.16.0.100:50001 
> > 10.0.0.2:50001,10.0.0.3:50001,10.0.0.4:50001 tcp
> > +ovn-nbctl lb-add lb_tcp6 [[1000::1]]:50001 [[1000::3]]:8080
> > +ovn-nbctl --wait=sb lr-lb-add R1 lb_tcp4
> > +ovn-nbctl --wait=sb lr-lb-add R1 lb_tcp6
> > +ovn-sbctl dump-flows R1 > R1flows
> > +AT_CAPTURE_FILE([R1flows])
> > +AT_CHECK([grep "lr_in_gw_redirect" R1flows | sort], [0], [dnl
> > +  table=20(lr_in_gw_redirect  ), priority=0    , match=(1), action=(next;)
> > +  table=20(lr_in_gw_redirect  ), priority=100  , match=(ip4.src == 
> > 10.0.0.3 && outport == "R1-PUB" && is_chassis_resident("S0-P0")), 
> > action=(eth.src = 30:54:00:00:00:03; reg1 = 172.16.0.110; next;)
> > +  table=20(lr_in_gw_redirect  ), priority=100  , match=(ip6.src == 1000::3 
> > && outport == "R1-PUB" && is_chassis_resident("S0-P0")), action=(eth.src = 
> > 40:54:00:00:00:03; xxreg1 = 3000::c; next;)
> > +  table=20(lr_in_gw_redirect  ), priority=200  , match=(ip4 && ((ip4.src 
> > == 10.0.0.2 && tcp.src == 50001) || (ip4.src == 10.0.0.3 && tcp.src == 
> > 50001) || (ip4.src == 10.0.0.4 && tcp.src == 50001)) && outport == 
> > "R1-PUB"), action=(outport = "cr-R1-PUB"; next;)
> > +  table=20(lr_in_gw_redirect  ), priority=200  , match=(ip6 && ((ip6.src 
> > == 1000::3 && tcp.src == 8080)) && outport == "R1-PUB"), action=(outport = 
> > "cr-R1-PUB"; next;)
> > +  table=20(lr_in_gw_redirect  ), priority=50   , match=(outport == 
> > "R1-PUB"), action=(outport = "cr-R1-PUB"; next;)
> > +])
> > +
> > +AT_CLEANUP
> > +])
> > diff --git a/tests/system-ovn.at b/tests/system-ovn.at
> > index c2490008d..cd9bb7433 100644
> > --- a/tests/system-ovn.at
> > +++ b/tests/system-ovn.at
> > @@ -11546,3 +11546,103 @@ OVS_TRAFFIC_VSWITCHD_STOP(["/failed to query port 
> > patch-.*/d
> >   AT_CLEANUP
> >   ])
> > +
> > +OVN_FOR_EACH_NORTHD([
> > +AT_SETUP([DNAT_SNAT and LB traffic])
> > +AT_SKIP_IF([test $HAVE_NC = no])
> > +AT_SKIP_IF([test $HAVE_TCPDUMP = no])
> > +AT_KEYWORDS([dnat-snat-lb])
> > +
> > +CHECK_CONNTRACK()
> > +CHECK_CONNTRACK_NAT()
> > +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 lr-add R1
> > +
> > +ovn-nbctl ls-add foo
> > +ovn-nbctl ls-add alice
> > +
> > +ovn-nbctl lrp-add R1 foo 00:00:01:01:02:03 192.168.1.1/24
> > +ovn-nbctl lrp-add R1 alice 00:00:02:01:02:03 172.16.1.1/24 \
> > +    -- lrp-set-gateway-chassis alice hv1
> > +
> > +ovn-nbctl lsp-add foo rp-foo -- set Logical_Switch_Port rp-foo \
> > +    type=router options:router-port=foo \
> > +    -- lsp-set-addresses rp-foo router
> > +
> > +ovn-nbctl lsp-add alice rp-alice -- set Logical_Switch_Port rp-alice \
> > +    type=router options:router-port=alice \
> > +    -- lsp-set-addresses rp-alice router
> > +
> > +ADD_NAMESPACES(foo1)
> > +ADD_VETH(foo1, foo1, br-int, "192.168.1.2/24", "f0:00:00:01:02:03", \
> > +         "192.168.1.1")
> > +ovn-nbctl lsp-add foo foo1 \
> > +-- lsp-set-addresses foo1 "f0:00:00:01:02:03 192.168.1.2"
> > +
> > +# Logical port 'alice1' in switch 'alice'.
> > +ADD_NAMESPACES(alice1)
> > +ADD_VETH(alice1, alice1, br-int, "172.16.1.2/24", "f0:00:00:01:02:05", \
> > +         "172.16.1.1")
> > +ovn-nbctl lsp-add alice alice1 \
> > +-- lsp-set-addresses alice1 "f0:00:00:01:02:05 172.16.1.2"
> > +
> > +AT_CHECK([ovn-nbctl lr-nat-add R1 dnat_and_snat 172.16.1.3 192.168.1.2 
> > foo1 00:00:02:02:03:04])
> > +AT_CHECK([ovn-nbctl lr-nat-add R1 snat 172.16.1.1 192.168.1.0/24])
> 
> nit: It's simpler to use the check function instead of AT_CHECK here. As I
> stated in the ovn-northd test you added, it has the benefit of echoing the
> command to testsuite.log as well.

ack, but I will drop this test

> 
> > +
> > +OVS_START_L7([foo1], [http])
> > +
> > +NS_CHECK_EXEC([alice1], [tcpdump -l -c 6 -neei alice1 host 172.16.1.3 and 
> > tcp > dna_snat.pcap 2>dna_snat_err &])
> > +OVS_WAIT_UNTIL([grep "listening" dna_snat_err])
> > +
> > +ovn-nbctl --wait=hv sync
> > +
> > +NS_CHECK_EXEC([alice1], [nc 172.16.1.3 80 -z], [0], [ignore], [ignore])
> > +
> > +OVS_WAIT_UNTIL([
> > +    n_pkt=$(cat dna_snat.pcap | wc -l)
> > +    test "${n_pkt}" = "6"
> > +])
> 
> Why do we expect 6 packets?

SYN + SYACK + ACK + FIN + FINACK + ACK

Regards,
Lorenzo

> 
> > +
> > +ovn-nbctl lb-add lb0 172.16.1.100:80 192.168.1.2:80 tcp
> > +ovn-nbctl --wait=hv lr-lb-add R1 lb0
> > +
> > +NS_CHECK_EXEC([alice1], [tcpdump -l -c 6 -neei alice1 host 172.16.1.100 
> > and tcp > lb.pcap 2>lb_err &])
> 
> If I understand tcpdump properly, "host 172.16.1.100" will satisfy any
> packet that has src or dst address set to 172.16.1.100. The nc below sends
> traffic to 172.16.1.100, meaning that tcpdump will capture the request
> traffic. Since our goal is to ensure that reply traffic is reaching alice1,
> would it be better to use "dst net 172.16.1.2" as our filter?
> 
> > +OVS_WAIT_UNTIL([grep "listening" lb_err])
> > +
> > +NS_CHECK_EXEC([alice1], [nc 172.16.1.100 80 -z], [0], [ignore], [ignore])
> > +
> > +OVS_WAIT_UNTIL([
> > +    n_pkt=$(cat lb.pcap | wc -l)
> > +    test "${n_pkt}" = "6"
> > +])
> > +
> > +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
> > +])
> 
_______________________________________________
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to