On Tue, May 26, 2020 at 9:16 PM Dumitru Ceara <dce...@redhat.com> wrote:
> On 5/26/20 5:39 PM, Lorenzo Bianconi wrote: > >> On 5/26/20 5:23 AM, Han Zhou wrote: > >>> > >>> > >>> On Mon, May 25, 2020 at 2:55 PM Lorenzo Bianconi > >>> <lorenzo.bianc...@redhat.com <mailto:lorenzo.bianc...@redhat.com>> > wrote: > >>>> > >>>> Introduce 150-priority logical flows for each NAT rule that can > >>>> be handled in a distributed manner to manage ARP request locally > >>>> for FIP traffic. In particular set reg1 and eth.src to NAT external > >>>> ip and NAT external mac respectivelly and do not distribute ARP > >>>> traffic using FIP > >>>> > >>>> Signed-off-by: Lorenzo Bianconi <lorenzo.bianc...@redhat.com > >>> <mailto:lorenzo.bianc...@redhat.com>> > >>>> --- > >>>> northd/ovn-northd.8.xml | 12 ++++++++++++ > >>>> northd/ovn-northd.c | 18 +++++++++++++++++- > >>>> tests/ovn.at <http://ovn.at> | 28 > +++++++++++++++++++++++++--- > >>>> tests/system-ovn.at <http://system-ovn.at> | 28 > >>> ++++++++++++++++++++++++++++ > >>>> 4 files changed, 82 insertions(+), 4 deletions(-) > >>>> > >>>> diff --git a/northd/ovn-northd.8.xml b/northd/ovn-northd.8.xml > >>>> index 9423cbfd1..5e37d9758 100644 > >>>> --- a/northd/ovn-northd.8.xml > >>>> +++ b/northd/ovn-northd.8.xml > >>>> @@ -2875,6 +2875,18 @@ icmp4 { > >>>> </p> > >>>> > >>>> <ul> > >>>> + <li> > >>>> + For each NAT rule in the OVN Northbound database that can > >>>> + be handled in a distributed manner, a priorirty-150 logical > >>>> + flow with match <code>ip.src == <var>A</var> && > >>>> + is_chassis_resident(<var>B</var>)</code>, where <var>A</var> > >>>> + is NAT logical ip and <var>B</var> is NAT logical port. > >>>> + IP traffic matching the above rule will be managed locally > >>>> + setting <code>reg1</code> to <var>C</var> and > >>> <code>eth.src</code> > >>>> + to <var>D</var>, where <var>C</var> is NAT external ip and > >>>> + <var>D</var> is NAT external mac. > >>>> + </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/northd/ovn-northd.c b/northd/ovn-northd.c > >>>> index 7ae5e45da..20f0ee2e4 100644 > >>>> --- a/northd/ovn-northd.c > >>>> +++ b/northd/ovn-northd.c > >>>> @@ -9181,8 +9181,24 @@ build_lrouter_flows(struct hmap *datapaths, > >>> struct hmap *ports, > >>>> /* Ingress Gateway Redirect Table: For NAT on a > distributed > >>>> * router, add flows that are specific to a NAT rule. > These > >>>> * flows indicate the presence of an applicable NAT rule > that > >>>> - * can be applied in a distributed manner. */ > >>>> + * can be applied in a distributed manner. > >>>> + * Moreover add logical flows to avoid ARP distributing > >>> when the > >>>> + * chassis has a direct connection to the underlay > >>> network through > >>>> + * a localnet port > >>> > >>> I think the two flows may be combined, right? Firstly, the match > >>> "outport == DGW" is missing from the new flow. Secondly, the > >>> "is_chassis_resident()" seems to be missing from the original flow. If > >>> this understanding is correct, the both flows just have same match > >>> condition, so the actions should be combined as well. > >>> > >> > >> Hi Lorenzo, Han, > >> > >> I agree that both flows should have the same match and that actions > >> should be combined. > >> > >> I'm not sure however if we can ever hit these flows if > >> is_chassis_resident(logical_port) == false. If I understand correctly we > >> can't, but just to be safe it's probably fine to add the > >> is_chassis_resident(logical_port) check. > >> > >>> In addition, I'd suggest to add more clear comment to state the reason > >>> why setting reg1 and eth.src. For example: it is done to make sure when > >>> ARP request is triggered (in next stage), the ARP generated can have > the > >>> eth.src = xxx and src IP as yyy, so that it can bypass the flow that > >>> redirect the ARP request to GW node ... > >>> > >>> Thanks, > >>> Han > >>> > >>>> + */ > >>>> if (distributed) { > >>>> + ds_clear(&match); > >>>> + ds_clear(&actions); > >>>> + ds_put_format(&match, > >>>> + "ip%s.src == %s && > >>> is_chassis_resident(\"%s\")", > >>>> + is_v6 ? "6" : "4", nat->logical_ip, > >>>> + nat->logical_port); > >>>> + ds_put_format(&actions, "eth.src = %s; %sreg1 = %s; > >>> next;", > >>>> + nat->external_mac, is_v6 ? "xx" : "", > >>>> + nat->external_ip); > >>>> + ovn_lflow_add(lflows, od, S_ROUTER_IN_GW_REDIRECT, > 150, > >>>> + ds_cstr(&match), ds_cstr(&actions)); > >>>> + > >>>> ds_clear(&match); > >>>> ds_put_format(&match, "ip%s.src == %s && outport == > %s", > >>>> is_v6 ? "6" : "4", > >>>> diff --git a/tests/ovn.at <http://ovn.at> b/tests/ovn.at < > http://ovn.at> > >>>> index 8fa1a7e1b..15b40ca1e 100644 > >>>> --- a/tests/ovn.at <http://ovn.at> > >>>> +++ b/tests/ovn.at <http://ovn.at> > >>>> @@ -14943,9 +14943,14 @@ ovs-vsctl -- add-port br-int hv2-vif1 -- \ > >>>> set interface hv2-vif1 external-ids:iface-id=sw1-p0 \ > >>>> options:tx_pcap=hv2/vif1-tx.pcap \ > >>>> options:rxq_pcap=hv2/vif1-rx.pcap \ > >>>> - ofport-request=1 > >>>> + ofport-request=2 > >>>> +ovs-vsctl -- add-port br-int hv2-vif2 -- \ > >>>> + set interface hv2-vif2 external-ids:iface-id=sw0-p1 \ > >>>> + options:tx_pcap=hv2/vif2-tx.pcap \ > >>>> + options:rxq_pcap=hv2/vif2-rx.pcap \ > >>>> + ofport-request=3 > >>>> > >>>> -ovn-nbctl create Logical_Router name=lr0 options:chassis=hv1 > >>>> +ovn-nbctl create Logical_Router name=lr0 > >>>> ovn-nbctl ls-add sw0 > >>>> ovn-nbctl ls-add sw1 > >>>> > >>>> @@ -14954,13 +14959,16 @@ ovn-nbctl lsp-add sw0 rp-sw0 -- set > >>> Logical_Switch_Port rp-sw0 \ > >>>> type=router options:router-port=sw0 \ > >>>> -- lsp-set-addresses rp-sw0 router > >>>> > >>>> -ovn-nbctl lrp-add lr0 sw1 00:00:02:01:02:03 172.16.1.1/24 > >>> <http://172.16.1.1/24> 2002:0:0:0:0:0:0:1/64 > >>>> +ovn-nbctl lrp-add lr0 sw1 00:00:02:01:02:03 172.16.1.1/24 > >>> <http://172.16.1.1/24> 2002:0:0:0:0:0:0:1/64 \ > >>>> + -- set Logical_Router_Port sw1 options:redirect-chassis="hv2" > >>>> ovn-nbctl lsp-add sw1 rp-sw1 -- set Logical_Switch_Port rp-sw1 \ > >>>> type=router options:router-port=sw1 \ > >>>> -- lsp-set-addresses rp-sw1 router > >>>> > >>>> ovn-nbctl lsp-add sw0 sw0-p0 \ > >>>> -- lsp-set-addresses sw0-p0 "f0:00:00:01:02:03 192.168.1.2 > 2001::2" > >>>> +ovn-nbctl lsp-add sw0 sw0-p1 \ > >>>> + -- lsp-set-addresses sw0-p1 "f0:00:00:11:02:03 192.168.1.3 > 2001::3" > >>>> > >>>> ovn-nbctl lsp-add sw1 sw1-p0 \ > >>>> -- lsp-set-addresses sw1-p0 unknown > >>>> @@ -15006,6 +15014,20 @@ send_na 2 1 $dst_mac $router_mac1 $dst_ip6 > >>> $router_ip6 > >>>> > >>>> OVN_CHECK_PACKETS([hv2/vif1-tx.pcap], [expected]) > >>>> > >>>> +# Create FIP on sw0-p0, add a route on logical router pipeline and > >>>> +# ARP request for a unkwon destination is sent using FIP MAC/IP > >>>> +ovn-nbctl lr-nat-add lr0 dnat_and_snat 172.16.1.2 192.168.1.3 sw0-p1 > >>> f0:00:00:01:02:04 > >>>> +ovn-nbctl lr-route-add lr0 172.16.2.0/24 <http://172.16.2.0/24> > >>> 172.16.1.11 > >>>> + > >>>> +dst_ip=$(ip_to_hex 172 16 2 10) > >>>> +fip_ip=$(ip_to_hex 172 16 1 2) > >>>> +src_ip=$(ip_to_hex 192 168 1 3) > >>>> +gw_router=$(ip_to_hex 172 16 1 11) > >>>> +send_icmp_packet 2 2 f00000110203 $router_mac0 $src_ip $dst_ip 0000 > $data > >>>> +echo $(get_arp_req f00000010204 $fip_ip $gw_router) >> expected > >>>> + > >>>> +OVN_CHECK_PACKETS([hv2/vif1-tx.pcap], [expected]) > >>>> + > >>>> OVN_CLEANUP([hv1],[hv2]) > >>>> AT_CLEANUP > >>>> > >>>> diff --git a/tests/system-ovn.at <http://system-ovn.at> > >>> b/tests/system-ovn.at <http://system-ovn.at> > >>>> index 9ae6c6b1f..99a0ee07b 100644 > >>>> --- a/tests/system-ovn.at <http://system-ovn.at> > >>>> +++ b/tests/system-ovn.at <http://system-ovn.at> > >>>> @@ -2747,6 +2747,17 @@ ADD_VETH(alice1, alice1, br-int, " > 172.16.1.2/24 > >>> <http://172.16.1.2/24>", "f0:00:00:01:02:05", \ > >>>> ovn-nbctl lsp-add alice alice1 \ > >>>> -- lsp-set-addresses alice1 "f0:00:00:01:02:05 172.16.1.2" > >>>> > >>>> +# Add external network > >>>> +ADD_NAMESPACES(ext-net) > >>>> +ip link add alice-ext netns alice1 type veth peer name ext-veth netns > >>> ext-net > >>>> +ip -n ext-net link set dev ext-veth up > >>>> +ip -n ext-net addr add 10.0.0.1/24 <http://10.0.0.1/24> dev ext-veth > >>>> +ip -n ext-net route add default via 10.0.0.2 > >>>> + > >>>> +ip -n alice1 link set dev alice-ext up > >>>> +ip -n alice1 addr add 10.0.0.2/24 <http://10.0.0.2/24> dev alice-ext > >>>> +ip netns exec alice1 sysctl -w net.ipv4.conf.all.forwarding=1 > >>>> + > >> > >> Shouldn't we use NS_CHECK_EXEC() instead of "ip -n"/"ip netns"? > > > > Hi Dumitru, > > > > thx for the review. I guess we can use NS_EXEC instead, right? > > > > I guess we could but we don't use NS_EXEC() anywhere in the > system-ovn.at tests. Also I don't see any harm in the additional checks > done by NS_CHECK_EXEC(). > I'm not sure in this particular case, but in this patch [1] which I submitted a while back, I couldn't use NS_CHECK_EXEC() and hence used "ip netns " directly. I wanted to do "nc 10.0.0.4 84 2> r" using NS_CHECK_EXEC() but it failed for some reason. [1] - https://github.com/ovn-org/ovn/commit/f792b1a00b439a949e3b7aae4951f8513340c1a1#diff-eaa18a11c5b23c901f9a4dd849c58db6R3802 > Thanks, > Dumitru > > > Regards, > > Lorenzo > > > >> > >> Regards, > >> Dumitru > >> > >>>> # Add DNAT rules > >>>> 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 dnat_and_snat 172.16.1.4 > >>> 192.168.1.3 foo2 00:00:02:02:03:05]) > >>>> @@ -2754,6 +2765,9 @@ AT_CHECK([ovn-nbctl lr-nat-add R1 dnat_and_snat > >>> 172.16.1.4 192.168.1.3 foo2 00:0 > >>>> # Add a SNAT rule > >>>> AT_CHECK([ovn-nbctl lr-nat-add R1 snat 172.16.1.1 192.168.0.0/16 > >>> <http://192.168.0.0/16>]) > >>>> > >>>> +# Add default route to ext-net > >>>> +AT_CHECK([ovn-nbctl lr-route-add R1 10.0.0.0/24 <http://10.0.0.0/24> > >>> 172.16.1.2]) > >>>> + > >>>> ovn-nbctl --wait=hv sync > >>>> OVS_WAIT_UNTIL([ovs-ofctl dump-flows br-int | grep > >>> 'nat(src=172.16.1.1)']) > >>>> > >>>> @@ -2797,6 +2811,20 @@ sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], > >>> [dnl > >>>> > >>> > > icmp,orig=(src=192.168.2.2,dst=172.16.1.2,id=<cleared>,type=8,code=0),reply=(src=172.16.1.2,dst=172.16.1.1,id=<cleared>,type=0,code=0),zone=<cleared> > >>>> ]) > >>>> > >>>> +# Try to ping external network > >>>> +NS_CHECK_EXEC([ext-net], [tcpdump -n -c 3 -i ext-veth dst 172.16.1.3 > >>> and icmp > ext-net.pcap &]) > >>>> +sleep 1 > >>>> +AT_CHECK([ovn-nbctl lr-nat-del R1 snat]) > >>>> +NS_CHECK_EXEC([foo1], [ping -q -c 3 -i 0.3 -w 2 10.0.0.1 | > >>> FORMAT_PING], \ > >>>> +[0], [dnl > >>>> +3 packets transmitted, 3 received, 0% packet loss, time 0ms > >>>> +]) > >>>> + > >>>> +OVS_WAIT_UNTIL([ > >>>> + total_pkts=$(cat ext-net.pcap | wc -l) > >>>> + test "${total_pkts}" = "3" > >>>> +]) > >>>> + > >>>> OVS_APP_EXIT_AND_WAIT([ovn-controller]) > >>>> > >>>> as ovn-sb > >>>> -- > >>>> 2.26.2 > >>>> > >> > > _______________________________________________ > 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