Re: [ovs-dev] [OVN Patch v14 1/3] ovn-libs: Add support for parallel processing
On 18/02/2021 22:36, Mark Michelson wrote: Hi Anton, in short: Acked-by: Mark Michelson I think this can go in as-is. My only question is with regards to how dp_groups are handled. The current patch makes it so that when dp_groups are used, we parallelize the work. However, instead of each thread creating discrete segments of lflows, each thread shares a reference to the same large lflow hmap. This means the threads have to lock the pertinent hash row each time they add a lflow to the hmap. This makes sense since the entire lflow hmap needs to be taken into account when determining if a flow is repeated between different datapaths. I'm curious if this contention might result in poorer parallization speedup. It does. According to Newman's results the speedup is ~ 2 times instead of 4+ Without having done any profiling, my assumption is that this shouldn't perform worse than single-threaded code, but that it likely isn't performing that much better either. See above. Because this isn't actively *harming* performance, that's why I went ahead and acked the patch series. Once we have run some performance tests, it would be worth determining if the algorithm used for dp_groups could be improved. I have a couple of thoughts: 1) It might just make sense to disable parallelization when dp_groups are enabled. This certainly wouldn't help performance, but it would simplify northd somewhat. This might be an OK tradeoff if the performance improvement from parallelization with dp_groups is insignificant. Actually, it looks like it is still faster if you have at least 8 threads to throw at it. 2) We could fully parallelize lflow table creation just like we do when dp_groups are disabled: split the lflow hmap into segments for each worker to fill in, and then merge them together once all threads are complete. Then after merging, we could iterate over the completed lflow hmap and determine the dp_groups at that point, rather than when inserting the lflow into the hmap. This extra hmap traversal might slow things down some, but uncontended parallelization could more than offset that cost. I would suggest leaving it as is. It does not lock full table - it locks "hash rows". So the contention is not as bad as one would expect and it still provides a reasonable gain. What do you think about these ideas? I bring them up because OVN is trending towards eventually having dp_groups enabled and no longer being disable-able. On 2/12/21 9:49 AM, Anton Ivanov wrote: This adds a set of functions and macros intended to process hashes in parallel. The principles of operation are documented in the fasthmap.h If these one day go into the OVS tree, the OVS tree versions would be used in preference. Signed-off-by: Anton Ivanov --- lib/automake.mk | 2 + lib/ovn-parallel-hmap.c | 455 lib/ovn-parallel-hmap.h | 285 + 3 files changed, 742 insertions(+) create mode 100644 lib/ovn-parallel-hmap.c create mode 100644 lib/ovn-parallel-hmap.h diff --git a/lib/automake.mk b/lib/automake.mk index 250c7aefa..781be2109 100644 --- a/lib/automake.mk +++ b/lib/automake.mk @@ -13,6 +13,8 @@ lib_libovn_la_SOURCES = \ lib/expr.c \ lib/extend-table.h \ lib/extend-table.c \ + lib/ovn-parallel-hmap.h \ + lib/ovn-parallel-hmap.c \ lib/ip-mcast-index.c \ lib/ip-mcast-index.h \ lib/mcast-group-index.c \ diff --git a/lib/ovn-parallel-hmap.c b/lib/ovn-parallel-hmap.c new file mode 100644 index 0..06aa95aba --- /dev/null +++ b/lib/ovn-parallel-hmap.c @@ -0,0 +1,455 @@ +/* + * Copyright (c) 2020 Red Hat, Inc. + * Copyright (c) 2008, 2009, 2010, 2012, 2013, 2015, 2019 Nicira, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "fatal-signal.h" +#include "util.h" +#include "openvswitch/vlog.h" +#include "openvswitch/hmap.h" +#include "openvswitch/thread.h" +#include "ovn-parallel-hmap.h" +#include "ovs-atomic.h" +#include "ovs-thread.h" +#include "ovs-numa.h" +#include "random.h" + +VLOG_DEFINE_THIS_MODULE(ovn_parallel_hmap); + +#ifndef OVS_HAS_PARALLEL_HMAP + +#define WORKER_SEM_NAME "%x-%p-%x" +#define MAIN_SEM_NAME "%x-%p-main" + +/* These are accessed under mutex inside add_worker_pool(). + * They do not need to be atomic. + */ + +static
Re: [ovs-dev] [PATCH ovn v3] northd: Provide the Gateway router option 'lb_force_snat_ip' to take router port ips.
On Fri, Feb 19, 2021 at 12:53 AM Mark Gray wrote: > > On 18/02/2021 19:00, num...@ovn.org wrote: > > From: Numan Siddique > > > > When a Gateway router is configured with a load balancer > > and it is also configured with options:lb_force_snat_ip=, > > OVN after load balancing the destination IP to one of the > > backend also does a NAT on the source ip with the > > lb_force_snat_ip if the packet is destined to a load balancer > > VIP. > > > > There is a problem with the snat of source ip to 'lb_force_snat_ip' > > in one particular usecase. When the packet enters the Gateway router > > from a provider logical switch destined to the load balancer VIP, > > then it is first load balanced to one of the backend and then > > the source ip is snatted to 'lb_force_snat_ip'. If the chosen > > backend is reachable via the provider logical switch, then the > > packet is hairpinned back and it may hit the wire with > > the source ip 'lb_force_snat_ip'. If 'lb_force_snat_ip' happens > > to be an OVN internal IP then the packet may be dropped. > > > > This patch addresses this issue by providing the option to > > set the option - 'lb_force_snat_ip=router_ip'. If 'router_ip' > > is set, then OVN will snat the load balanced packet to the > > router ip of the logical router port which is chosen as 'outport' > > in lr_in_ip_routing stage. > > > > Example. > > > > If the gateway router is > > > > ovn-nbctl show lr0 > > router 68f20092-5563-44b8-9ccb-b11de3e3a66c (lr0) > > port lr0-sw0 > > mac: "00:00:00:00:ff:01" > > networks: ["10.0.0.1/24"] > > port lr0-public > > mac: "00:00:20:20:12:13" > > networks: ["172.168.0.100/24"] > > > > Then the below logical flows are added if 'lb_force_snat_ip' > > is configured to 'router_ip'. > > > > table=1 (lr_out_snat), priority=110 > >match=(flags.force_snat_for_lb == 1 && ip4 && outport == "lr0-public"), > >action=(ct_snat(172.168.0.100);) > > > > table=1 (lr_out_snat), priority=110 > >match=(flags.force_snat_for_lb == 1 && ip4 && outport == "lr0-sw0") > >action=(ct_snat(10.0.0.1);) > > > > For the above described scenario, the packet will have source ip as > > 172.168.0.100 which belongs to the provider logical switch CIDR. > > > > Reported-by: Tim Rozet > > Signed-off-by: Numan Siddique > > --- > > northd/ovn-northd.8.xml | 35 > > northd/ovn-northd.c | 91 + > > ovn-nb.xml | 33 ++- > > tests/ovn-northd.at | 79 +++ > > 4 files changed, 220 insertions(+), 18 deletions(-) > > > > diff --git a/northd/ovn-northd.8.xml b/northd/ovn-northd.8.xml > > index 2f8b4e8c30..1d8f5edee1 100644 > > --- a/northd/ovn-northd.8.xml > > +++ b/northd/ovn-northd.8.xml > > @@ -3654,6 +3654,32 @@ nd_ns { > >flags.force_snat_for_dnat == 1 ip with an > >action ct_snat(B);. > > > > + > > + > > + > > + > > + If the Gateway router in the OVN Northbound database has been > > + configured to force SNAT a packet (that has been previously > > + load-balanced) using router IP (i.e > + table="Logical_Router"/>:lb_force_snat_ip=router_ip), then for > > + each logical router port P attached to the Gateway > > + router, a priority-110 flow matches > > + flags.force_snat_for_lb == 1 outport == > > P > > + with an action ct_snat(R); > > + where R is the IP configured on the router port. > > + If R is an IPv4 address then the match will also > > + include ip4 and if it is an IPv6 address, then the > > + match will also include ip6. > > + > > + > > + > > + If the logical router port P is configured with > > multiple > > + IPv4 and multiple IPv6 addresses, only the first IPv4 and first > > IPv6 > > + address is considered. > > + > > + > > + > > + > > > >If the Gateway router in the OVN Northbound database has been > >configured to force SNAT a packet (that has been previously > > @@ -3661,6 +3687,9 @@ nd_ns { > >flags.force_snat_for_lb == 1 ip with an > >action ct_snat(B);. > > > > + > > + > > + > > > >For each configuration in the OVN Northbound database, that asks > >to change the source IP address of a packet from an IP address of > > @@ -3674,14 +3703,18 @@ nd_ns { > >options, then the action would be ip4/6.src= > >(B). > > > > + > > > > + > > > >If the NAT rule has allowed_ext_ips configured, then > >there is an additional match ip4.dst == > > allowed_ext_ips > >. Similarly, for IPV6, match would be ip6.dst > > == > >allowed_ext_ips. > > > > + > > > > + > > > >
Re: [ovs-dev] [PATCHv2] connmgr: Check nullptr inside ofmonitor_report()
Hi, Looks like this bug is caused by violating the fact that if a rule is referenced, the related ofproto should not be destroyed. If so, I have a patch that also fixes the problem, not sure if this helps. http://patchwork.ozlabs.org/project/openvswitch/patch/20200717015041.82746-1-hepeng.0...@bytedance.com/ William Tu 于2021年2月19日周五 上午8:10写道: > > On Wed, Feb 17, 2021 at 1:09 PM Yifeng Sun wrote: > > > > ovs-vswitchd could crash under these circumstances: > > 1. When one bridge is being destroyed, ofproto_destroy() is called and > > connmgr pointer of its ofproto struct is nullified. This ofproto struct is > > deallocated through 'ovsrcu_postpone(ofproto_destroy_defer__, p);'. > > 2. Before RCU enters quiesce state to actually free this ofproto struct, > > revalidator thread calls udpif_revalidator(), which could handle > > a learn flow and calls ofproto_flow_mod_learn(), it later calls > > ofmonitor_report() and ofproto struct's connmgr pointer is accessed. > > > > The crash stack trace is shown below: > > > > 0 ofmonitor_report (mgr=0x0, rule=rule@entry=0x7fa4ac067c30, > > event=event@entry=NXFME_ADDED, > > reason=reason@entry=OFPRR_IDLE_TIMEOUT, abbrev_ofconn=0x0, > > abbrev_xid=0, old_actions=old_actions@entry=0x0) > > at ofproto/connmgr.c:2160 > > 1 0x7fa4d6803495 in add_flow_finish (ofproto=0x55d9075d4ab0, > > ofm=, req=req@entry=0x0) > > at ofproto/ofproto.c:5221 > > 2 0x7fa4d68036af in modify_flows_finish (req=0x0, ofm=0x7fa4980753f0, > > ofproto=0x55d9075d4ab0) > > at ofproto/ofproto.c:5823 > > 3 ofproto_flow_mod_finish (ofproto=0x55d9075d4ab0, > > ofm=ofm@entry=0x7fa4980753f0, req=req@entry=0x0) > > at ofproto/ofproto.c:8088 > > 4 0x7fa4d680372d in ofproto_flow_mod_learn_finish > > (ofm=ofm@entry=0x7fa4980753f0, > > orig_ofproto=orig_ofproto@entry=0x0) at ofproto/ofproto.c:5439 > > 5 0x7fa4d68072f9 in ofproto_flow_mod_learn (ofm=0x7fa4980753f0, > > keep_ref=keep_ref@entry=true, > > limit=, below_limitp=below_limitp@entry=0x0) at > > ofproto/ofproto.c:5499 > > 6 0x7fa4d6835d33 in xlate_push_stats_entry (entry=0x7fa498012448, > > stats=stats@entry=0x7fa4d2701a10, > > offloaded=offloaded@entry=false) at > > ofproto/ofproto-dpif-xlate-cache.c:127 > > 7 0x7fa4d6835e3a in xlate_push_stats (xcache=, > > stats=stats@entry=0x7fa4d2701a10, > > offloaded=offloaded@entry=false) at > > ofproto/ofproto-dpif-xlate-cache.c:181 > > 8 0x7fa4d6822046 in revalidate_ukey (udpif=udpif@entry=0x55d90760b240, > > ukey=ukey@entry=0x7fa4b0191660, > > stats=stats@entry=0x7fa4d2705118, > > odp_actions=odp_actions@entry=0x7fa4d2701b50, > > reval_seq=reval_seq@entry=5655486242, > > recircs=recircs@entry=0x7fa4d2701b40, offloaded=false) > > at ofproto/ofproto-dpif-upcall.c:2294 > > 9 0x7fa4d6825aee in revalidate (revalidator=0x55d90769dd00) at > > ofproto/ofproto-dpif-upcall.c:2683 > > 10 0x7fa4d6825cf3 in udpif_revalidator (arg=0x55d90769dd00) at > > ofproto/ofproto-dpif-upcall.c:936 > > 11 0x7fa4d6259c9f in ovsthread_wrapper (aux_=) at > > lib/ovs-thread.c:423 > > 12 0x7fa4d582cea5 in start_thread () from /usr/lib64/libpthread.so.0 > > 13 0x7fa4d504b96d in clone () from /usr/lib64/libc.so.6 > > > > At the time of crash, the involved ofproto was already deallocated: > > > > (gdb) print *ofproto > > $1 = ..., name = 0x55d907602820 "nsx-managed", ..., ports = {..., > > one = 0x0, mask = 63, n = 0}, ..., connmgr = 0x0, ... > > > > This patch fixes it. > > > > VMware-BZ: #2700626 > > Signed-off-by: Yifeng Sun > > --- > > v1->v2: Add check for ofmonitor_flush, thanks William. > > > > LGTM, thanks. > Acked-by: William Tu < u9012...@gmail.com> > > CC Ilya and Ben to see if any comments. > > I feel this kind of RCU issue is hard to find out, and > existing tools such as addressSanitizer are usually > not helpful. > > William > > > ofproto/connmgr.c | 6 +- > > 1 file changed, 5 insertions(+), 1 deletion(-) > > > > diff --git a/ofproto/connmgr.c b/ofproto/connmgr.c > > index 9c5c633b4171..fa8f6cd0e83a 100644 > > --- a/ofproto/connmgr.c > > +++ b/ofproto/connmgr.c > > @@ -2140,7 +2140,7 @@ ofmonitor_report(struct connmgr *mgr, struct rule > > *rule, > > const struct rule_actions *old_actions) > > OVS_REQUIRES(ofproto_mutex) > > { > > -if (rule_is_hidden(rule)) { > > +if (!mgr || rule_is_hidden(rule)) { > > return; > > } > > > > @@ -2244,6 +2244,10 @@ ofmonitor_flush(struct connmgr *mgr) > > { > > struct ofconn *ofconn; > > > > +if (!mgr) { > > +return; > > +} > > + > > LIST_FOR_EACH (ofconn, connmgr_node, >conns) { > > struct rconn_packet_counter *counter = ofconn->monitor_counter; > > > > -- > > 2.7.4 > > > > ___ > > dev mailing list > > d...@openvswitch.org > > https://mail.openvswitch.org/mailman/listinfo/ovs-dev > ___ > dev
Re: [ovs-dev] [PATCH ovn 0/6] MAC learning support in OVN.
Aside from the comments on patch 1, Acked-by: Mark Michelson On 2/5/21 1:56 AM, num...@ovn.org wrote: From: Numan Siddique This series adds the support to learn the macs seen on logical port VIF's whose port security is disabled and 'unknown' address set. A new table - FDB is added in Southboud database to store the port-to-mac mappings. The first patch is a small refactor and moves the mac_binding related code from pinctrl.c to a separate file - mac-learn.c. pinctrl.c still writes the learnt mac_bindings to the MAC_Binding table. The remaining patches actually adds the mac learning support. The main usecase of this patch series is to stop flooding of the packet to all the logical ports which accept unknown destinations once the mac is learnt from such ports. This patch excludes learning the macs from the localnet ports as this could cause lot of FDB entries since such ports can receive the broad cast traffic fron the physical network. Numan Siddique (6): controller: Split mac learning code to a separate file. MAC learning: Add a new FDB table in southbound db. MAC learning: Add new actions - put_fdb, get_fdb and lookup_fdb. controller: MAC learning: Add OF rules for the FDB entries. northd: MAC learning: Add logical flows for fdb. northd: Cleanup stale FDB entries. controller/automake.mk | 5 +- controller/lflow.c | 110 +++ controller/lflow.h | 13 +- controller/mac-learn.c | 180 +++ controller/mac-learn.h | 66 controller/ovn-controller.c | 32 +- controller/pinctrl.c | 220 +- controller/pinctrl.h | 1 + include/ovn/actions.h| 33 ++ include/ovn/logical-fields.h | 4 + lib/actions.c| 176 +++ lib/ovn-util.c | 20 +- lib/ovn-util.h | 4 + northd/ovn-northd.8.xml | 162 -- northd/ovn-northd.c | 136 +++-- ovn-sb.ovsschema | 19 +- ovn-sb.xml | 86 ++ tests/ovn-northd.at | 92 +- tests/ovn.at | 575 --- tests/test-ovn.c | 2 + utilities/ovn-trace.c| 145 - 21 files changed, 1887 insertions(+), 194 deletions(-) create mode 100644 controller/mac-learn.c create mode 100644 controller/mac-learn.h ___ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev
Re: [ovs-dev] [PATCH ovn] northd: Fix ha_chassis_group txn error for external ports.
Acked-by: Mark Michelson On 2/12/21 2:21 AM, num...@ovn.org wrote: From: Numan Siddique If an external logical port 'sw0-p1' is associated with an ha_chassis_group and later CMS runs a command to clear the ha_chassis_group and set the type to normal in the same transaction, i.e ovn-nbctl clear logical_switch_port sw0-p1 ha_chassis_group -- \ set logical_switch_port sw0-p1 'type=""' then, ovn-northd goes into a continous loop trying to delete the ha_chassis_group in SB DB . ovn-northd doesn't clear the ha_chassis_group of the port binding sw0-p1 in the SB DB and hence the constraint violation is seen. This issue is seen when lport sw0-p1 is the only one referencing the ha_chassis_group in SB DB. This patch fixes this issue. Reported-at: https://bugzilla.redhat.com/show_bug.cgi?id=1927369 Reported-by: Jakub Libosvar Signed-off-by: Numan Siddique --- northd/ovn-northd.c | 6 ++ tests/ovn-northd.at | 47 ++--- 2 files changed, 50 insertions(+), 3 deletions(-) diff --git a/northd/ovn-northd.c b/northd/ovn-northd.c index b2b5f6a1b..83af4464c 100644 --- a/northd/ovn-northd.c +++ b/northd/ovn-northd.c @@ -2976,6 +2976,12 @@ ovn_port_update_sbrec(struct northd_context *ctx, } else { sbrec_port_binding_set_ha_chassis_group(op->sb, NULL); } +} else if (op->sb->ha_chassis_group) { +/* Clear the port bindings ha_chassis_group if the type is + * not external and if this column is set. This can happen + * when an external port is reset to type normal and + * ha_chassis_group cleared in the same transaction. */ +sbrec_port_binding_set_ha_chassis_group(op->sb, NULL); } } else { const char *chassis = NULL; diff --git a/tests/ovn-northd.at b/tests/ovn-northd.at index 64a788067..5af77470a 100644 --- a/tests/ovn-northd.at +++ b/tests/ovn-northd.at @@ -605,11 +605,12 @@ wait_row_count Port_Binding 0 logical_port=sw0-pext1 'chassis!=[[]]' wait_row_count HA_Chassis_Group 1 name=hagrp1 wait_row_count HA_Chassis 3 -# Clear ha_chassis_group for sw0-pext2 -ovn-nbctl --wait=sb clear logical_switch_port sw0-pext2 ha_chassis_group +AS_BOX([Clear ha_chassis_group for sw0-pext2 and reset port type to normal in the same txn]) -wait_row_count Port_Binding 0 logical_port=sw0-pext2 'chassis!=[[]]' +check ovn-nbctl --wait=sb clear logical_switch_port sw0-pext2 \ +ha_chassis_group -- set logical_switch_port sw0-pext2 'type=""' wait_row_count HA_Chassis_Group 0 +wait_row_count Port_Binding 0 logical_port=sw0-pext2 'chassis!=[[]]' check_row_count HA_Chassis 0 as ovn-sb @@ -2520,3 +2521,43 @@ check ovn-sbctl set chassis hv1 other_config:port-up-notif=true wait_row_count nb:Logical_Switch_Port 1 up=false name=lsp1 AT_CLEANUP + +AT_SETUP([ovn -- HA chassis group cleanup for external port ]) +ovn_start + +check ovn-nbctl ls-add sw0 +check ovn-nbctl lsp-add sw0 sw0-p1 +check ovn-nbctl lsp-set-type sw0-p1 external + +check ovn-sbctl chassis-add ch1 geneve 127.0.0.1 +check ovn-sbctl chassis-add ch2 geneve 127.0.0.2 + +check ovn-nbctl ha-chassis-group-add hagrp1 +check ovn-nbctl ha-chassis-group-add-chassis hagrp1 ch1 20 +check ovn-nbctl --wait=sb ha-chassis-group-add-chassis hagrp1 ch2 10 + +ha_grp1_uuid=$(fetch_column nb:ha_chassis_group _uuid) +echo "ha grp1 uuid = $ha_grp1_uuid" +ovn-nbctl list ha_chassis_group +check ovn-nbctl set logical_switch_port sw0-p1 ha_chassis_group=$ha_grp1_uuid + +wait_row_count ha_chassis_group 1 +check ovn-nbctl clear logical_switch_port sw0-p1 ha_chassis_group +wait_row_count ha_chassis_group 0 + +check ovn-nbctl set logical_switch_port sw0-p1 ha_chassis_group=$ha_grp1_uuid +wait_row_count ha_chassis_group 1 +sb_ha_grp1_uuid=$(fetch_column ha_chassis_group _uuid) + +echo +echo "__file__:__line__:Check that port_binding sw0-p1 has ha_chassis_group set" + +check_column "$sb_ha_grp1_uuid" Port_Binding ha_chassis_group logical_port=sw0-p1 + +AS_BOX([Clear ha_chassis_group for sw0-p1 and reset port type to normal port in the same txn]) + +check ovn-nbctl clear logical_switch_port sw0-p1 ha_chassis_group -- set logical_switch_port sw0-p1 'type=""' +wait_row_count ha_chassis_group 0 +check_column "" Port_Binding chassis logical_port=sw0-p1 + +AT_CLEANUP ___ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev
Re: [ovs-dev] [PATCHv2] connmgr: Check nullptr inside ofmonitor_report()
On Wed, Feb 17, 2021 at 1:09 PM Yifeng Sun wrote: > > ovs-vswitchd could crash under these circumstances: > 1. When one bridge is being destroyed, ofproto_destroy() is called and > connmgr pointer of its ofproto struct is nullified. This ofproto struct is > deallocated through 'ovsrcu_postpone(ofproto_destroy_defer__, p);'. > 2. Before RCU enters quiesce state to actually free this ofproto struct, > revalidator thread calls udpif_revalidator(), which could handle > a learn flow and calls ofproto_flow_mod_learn(), it later calls > ofmonitor_report() and ofproto struct's connmgr pointer is accessed. > > The crash stack trace is shown below: > > 0 ofmonitor_report (mgr=0x0, rule=rule@entry=0x7fa4ac067c30, > event=event@entry=NXFME_ADDED, > reason=reason@entry=OFPRR_IDLE_TIMEOUT, abbrev_ofconn=0x0, abbrev_xid=0, > old_actions=old_actions@entry=0x0) > at ofproto/connmgr.c:2160 > 1 0x7fa4d6803495 in add_flow_finish (ofproto=0x55d9075d4ab0, > ofm=, req=req@entry=0x0) > at ofproto/ofproto.c:5221 > 2 0x7fa4d68036af in modify_flows_finish (req=0x0, ofm=0x7fa4980753f0, > ofproto=0x55d9075d4ab0) > at ofproto/ofproto.c:5823 > 3 ofproto_flow_mod_finish (ofproto=0x55d9075d4ab0, > ofm=ofm@entry=0x7fa4980753f0, req=req@entry=0x0) > at ofproto/ofproto.c:8088 > 4 0x7fa4d680372d in ofproto_flow_mod_learn_finish > (ofm=ofm@entry=0x7fa4980753f0, > orig_ofproto=orig_ofproto@entry=0x0) at ofproto/ofproto.c:5439 > 5 0x7fa4d68072f9 in ofproto_flow_mod_learn (ofm=0x7fa4980753f0, > keep_ref=keep_ref@entry=true, > limit=, below_limitp=below_limitp@entry=0x0) at > ofproto/ofproto.c:5499 > 6 0x7fa4d6835d33 in xlate_push_stats_entry (entry=0x7fa498012448, > stats=stats@entry=0x7fa4d2701a10, > offloaded=offloaded@entry=false) at ofproto/ofproto-dpif-xlate-cache.c:127 > 7 0x7fa4d6835e3a in xlate_push_stats (xcache=, > stats=stats@entry=0x7fa4d2701a10, > offloaded=offloaded@entry=false) at ofproto/ofproto-dpif-xlate-cache.c:181 > 8 0x7fa4d6822046 in revalidate_ukey (udpif=udpif@entry=0x55d90760b240, > ukey=ukey@entry=0x7fa4b0191660, > stats=stats@entry=0x7fa4d2705118, > odp_actions=odp_actions@entry=0x7fa4d2701b50, > reval_seq=reval_seq@entry=5655486242, > recircs=recircs@entry=0x7fa4d2701b40, offloaded=false) > at ofproto/ofproto-dpif-upcall.c:2294 > 9 0x7fa4d6825aee in revalidate (revalidator=0x55d90769dd00) at > ofproto/ofproto-dpif-upcall.c:2683 > 10 0x7fa4d6825cf3 in udpif_revalidator (arg=0x55d90769dd00) at > ofproto/ofproto-dpif-upcall.c:936 > 11 0x7fa4d6259c9f in ovsthread_wrapper (aux_=) at > lib/ovs-thread.c:423 > 12 0x7fa4d582cea5 in start_thread () from /usr/lib64/libpthread.so.0 > 13 0x7fa4d504b96d in clone () from /usr/lib64/libc.so.6 > > At the time of crash, the involved ofproto was already deallocated: > > (gdb) print *ofproto > $1 = ..., name = 0x55d907602820 "nsx-managed", ..., ports = {..., > one = 0x0, mask = 63, n = 0}, ..., connmgr = 0x0, ... > > This patch fixes it. > > VMware-BZ: #2700626 > Signed-off-by: Yifeng Sun > --- > v1->v2: Add check for ofmonitor_flush, thanks William. > LGTM, thanks. Acked-by: William Tu < u9012...@gmail.com> CC Ilya and Ben to see if any comments. I feel this kind of RCU issue is hard to find out, and existing tools such as addressSanitizer are usually not helpful. William > ofproto/connmgr.c | 6 +- > 1 file changed, 5 insertions(+), 1 deletion(-) > > diff --git a/ofproto/connmgr.c b/ofproto/connmgr.c > index 9c5c633b4171..fa8f6cd0e83a 100644 > --- a/ofproto/connmgr.c > +++ b/ofproto/connmgr.c > @@ -2140,7 +2140,7 @@ ofmonitor_report(struct connmgr *mgr, struct rule *rule, > const struct rule_actions *old_actions) > OVS_REQUIRES(ofproto_mutex) > { > -if (rule_is_hidden(rule)) { > +if (!mgr || rule_is_hidden(rule)) { > return; > } > > @@ -2244,6 +2244,10 @@ ofmonitor_flush(struct connmgr *mgr) > { > struct ofconn *ofconn; > > +if (!mgr) { > +return; > +} > + > LIST_FOR_EACH (ofconn, connmgr_node, >conns) { > struct rconn_packet_counter *counter = ofconn->monitor_counter; > > -- > 2.7.4 > > ___ > 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
Re: [ovs-dev] [PATCH ovn v10.1 0/6] Add DDlog implementation of ovn-northd
This passed in the ovsrobot CI: https://github.com/ovsrobot/ovn/actions/runs/579307688 I think that we have arrived at consensus to push this to ovn master after branching happens tomorrow. Please, let me know if I misunderstood! ___ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev
[ovs-dev] [bug] uuid_from_string conflicts with FreeBSD libc
Hi! I've found an old bug in FreeBSD bugzilla: https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=238331 reporting an incorrect behavior of ovs due to conflict of uuid_from_string() defined in lib/uuid.* with the function with same name from FreeBSD standard C library: void uuid_from_string(const char*, uuid_t*, uint32_t*); Here's FreeBSD manpage with the list of all functions (by pure change tere are no other conflicts): https://www.unix.com/man-page/FreeBSD/3/uuid_create/ The suggested workaround was to switch to static linking to make ovs' symbol used. IMO this should be fixed upstream, probably by prefixing uuid_* functions to avoid this and similar conflicts. -- Dmitry Marakasov . 55B5 0596 FF1E 8D84 5F56 9510 D35A 80DD F9D2 F77D amd...@amdmi3.ru ..: https://github.com/AMDmi3 ___ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev
Re: [ovs-dev] [OVN Patch v14 1/3] ovn-libs: Add support for parallel processing
Hi Anton, in short: Acked-by: Mark Michelson I think this can go in as-is. My only question is with regards to how dp_groups are handled. The current patch makes it so that when dp_groups are used, we parallelize the work. However, instead of each thread creating discrete segments of lflows, each thread shares a reference to the same large lflow hmap. This means the threads have to lock the pertinent hash row each time they add a lflow to the hmap. This makes sense since the entire lflow hmap needs to be taken into account when determining if a flow is repeated between different datapaths. I'm curious if this contention might result in poorer parallization speedup. Without having done any profiling, my assumption is that this shouldn't perform worse than single-threaded code, but that it likely isn't performing that much better either. Because this isn't actively *harming* performance, that's why I went ahead and acked the patch series. Once we have run some performance tests, it would be worth determining if the algorithm used for dp_groups could be improved. I have a couple of thoughts: 1) It might just make sense to disable parallelization when dp_groups are enabled. This certainly wouldn't help performance, but it would simplify northd somewhat. This might be an OK tradeoff if the performance improvement from parallelization with dp_groups is insignificant. 2) We could fully parallelize lflow table creation just like we do when dp_groups are disabled: split the lflow hmap into segments for each worker to fill in, and then merge them together once all threads are complete. Then after merging, we could iterate over the completed lflow hmap and determine the dp_groups at that point, rather than when inserting the lflow into the hmap. This extra hmap traversal might slow things down some, but uncontended parallelization could more than offset that cost. What do you think about these ideas? I bring them up because OVN is trending towards eventually having dp_groups enabled and no longer being disable-able. On 2/12/21 9:49 AM, Anton Ivanov wrote: This adds a set of functions and macros intended to process hashes in parallel. The principles of operation are documented in the fasthmap.h If these one day go into the OVS tree, the OVS tree versions would be used in preference. Signed-off-by: Anton Ivanov --- lib/automake.mk | 2 + lib/ovn-parallel-hmap.c | 455 lib/ovn-parallel-hmap.h | 285 + 3 files changed, 742 insertions(+) create mode 100644 lib/ovn-parallel-hmap.c create mode 100644 lib/ovn-parallel-hmap.h diff --git a/lib/automake.mk b/lib/automake.mk index 250c7aefa..781be2109 100644 --- a/lib/automake.mk +++ b/lib/automake.mk @@ -13,6 +13,8 @@ lib_libovn_la_SOURCES = \ lib/expr.c \ lib/extend-table.h \ lib/extend-table.c \ + lib/ovn-parallel-hmap.h \ + lib/ovn-parallel-hmap.c \ lib/ip-mcast-index.c \ lib/ip-mcast-index.h \ lib/mcast-group-index.c \ diff --git a/lib/ovn-parallel-hmap.c b/lib/ovn-parallel-hmap.c new file mode 100644 index 0..06aa95aba --- /dev/null +++ b/lib/ovn-parallel-hmap.c @@ -0,0 +1,455 @@ +/* + * Copyright (c) 2020 Red Hat, Inc. + * Copyright (c) 2008, 2009, 2010, 2012, 2013, 2015, 2019 Nicira, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "fatal-signal.h" +#include "util.h" +#include "openvswitch/vlog.h" +#include "openvswitch/hmap.h" +#include "openvswitch/thread.h" +#include "ovn-parallel-hmap.h" +#include "ovs-atomic.h" +#include "ovs-thread.h" +#include "ovs-numa.h" +#include "random.h" + +VLOG_DEFINE_THIS_MODULE(ovn_parallel_hmap); + +#ifndef OVS_HAS_PARALLEL_HMAP + +#define WORKER_SEM_NAME "%x-%p-%x" +#define MAIN_SEM_NAME "%x-%p-main" + +/* These are accessed under mutex inside add_worker_pool(). + * They do not need to be atomic. + */ + +static atomic_bool initial_pool_setup = ATOMIC_VAR_INIT(false); +static bool can_parallelize = false; + +/* This is set only in the process of exit and the set is + * accompanied by a fence. It does not need to be atomic or be + * accessed under a lock. + */ + +static bool workers_must_exit = false; + +static struct ovs_list worker_pools = OVS_LIST_INITIALIZER(_pools); + +static struct ovs_mutex init_mutex =
Re: [ovs-dev] [PATCH ovn v10.1 6/6] ovn-northd-ddlog: New implementation of ovn-northd based on ddlog.
Bleep bloop. Greetings Ben Pfaff, I am a robot and I have tried out your patch. Thanks for your contribution. I encountered some error that I wasn't expecting. See the details below. checkpatch: WARNING: Comment with 'xxx' marker #3724 FILE: northd/ovn-northd-ddlog.c:166: .cs = ovsdb_cs_create(database, 1 /* XXX */, _cs_ops, ctx), WARNING: Comment with 'xxx' marker #4512 FILE: northd/ovn-northd-ddlog.c:954: * XXX If the transaction we're sending to the database fails, then WARNING: Line lacks whitespace around operator WARNING: Line lacks whitespace around operator WARNING: Line lacks whitespace around operator #4565 FILE: northd/ovn-northd-ddlog.c:1007: --ovnnb-db=DATABASE connect to ovn-nb database at DATABASE\n\ WARNING: Line lacks whitespace around operator WARNING: Line lacks whitespace around operator WARNING: Line lacks whitespace around operator #4567 FILE: northd/ovn-northd-ddlog.c:1009: --ovnsb-db=DATABASE connect to ovn-sb database at DATABASE\n\ WARNING: Line lacks whitespace around operator WARNING: Line lacks whitespace around operator #4569 FILE: northd/ovn-northd-ddlog.c:1011: --unixctl=SOCKET override default control socket name\n\ WARNING: Line has trailing whitespace #6344 FILE: northd/ovn_northd.dl:176: var l3dgw_port = peer.and_then(|p| p.router.l3dgw_port), WARNING: Line has non-spaces leading whitespace WARNING: Line has trailing whitespace #9126 FILE: northd/ovn_northd.dl:2958: WARNING: Line has non-spaces leading whitespace WARNING: Line has trailing whitespace #12818 FILE: northd/ovn_northd.dl:6650: WARNING: Line has non-spaces leading whitespace WARNING: Line has trailing whitespace #13787 FILE: northd/ovn_northd.dl:7619: WARNING: Line has trailing whitespace #13988 FILE: northd/ovn_northd.dl:7820: } WARNING: Line has non-spaces leading whitespace WARNING: Line has trailing whitespace #13989 FILE: northd/ovn_northd.dl:7821: WARNING: Line has non-spaces leading whitespace WARNING: Line has trailing whitespace #13990 FILE: northd/ovn_northd.dl:7822: Lines checked: 14607, Warnings: 22, Errors: 0 Please check this out. If you feel there has been an error, please email acon...@redhat.com Thanks, 0-day Robot ___ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev
Re: [ovs-dev] [PATCH ovn v10.1 1/6] Export `VLOG_WARN` and `VLOG_ERR` from libovn for use in ddlog
Bleep bloop. Greetings Ben Pfaff, I am a robot and I have tried out your patch. Thanks for your contribution. I encountered some error that I wasn't expecting. See the details below. checkpatch: WARNING: Unexpected sign-offs from developers who are not authors or co-authors or committers: Ben Pfaff Lines checked: 77, Warnings: 1, Errors: 0 Please check this out. If you feel there has been an error, please email acon...@redhat.com Thanks, 0-day Robot ___ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev
[ovs-dev] [PATCH ovn v10.1 2/6] tests: Prepare for multiple northd types.
The idea is to run each test twice, once with ovn-northd, once with ovn-northd-ddlog. To do that, we add a macro OVN_FOR_EACH_NORTHD and bracket each test that uses ovn-northd in it. Signed-off-by: Ben Pfaff Acked-by: Dumitru Ceara --- tests/ovn-ic.at | 11 +- tests/ovn-macros.at | 96 +-- tests/ovn-northd.at | 100 --- tests/ovn.at| 288 tests/ovs-macros.at | 20 +-- tests/system-ovn.at | 124 ++- 6 files changed, 528 insertions(+), 111 deletions(-) diff --git a/tests/ovn-ic.at b/tests/ovn-ic.at index 0638af401295..2a4fba031f36 100644 --- a/tests/ovn-ic.at +++ b/tests/ovn-ic.at @@ -1,4 +1,5 @@ AT_BANNER([OVN Interconnection Controller]) +OVN_FOR_EACH_NORTHD([ AT_SETUP([ovn-ic -- AZ register]) ovn_init_ic_db @@ -29,7 +30,9 @@ availability-zone az3 OVN_CLEANUP_IC([az1], [az2]) AT_CLEANUP +]) +OVN_FOR_EACH_NORTHD([ AT_SETUP([ovn-ic -- transit switch handling]) ovn_init_ic_db @@ -59,7 +62,9 @@ check_column ts2 nb:Logical_Switch name OVN_CLEANUP_IC([az1]) AT_CLEANUP +]) +OVN_FOR_EACH_NORTHD([ AT_SETUP([ovn-ic -- gateway sync]) ovn_init_ic_db @@ -120,8 +125,9 @@ OVN_CLEANUP_SBOX(gw2) OVN_CLEANUP_IC([az1], [az2]) AT_CLEANUP +]) - +OVN_FOR_EACH_NORTHD([ AT_SETUP([ovn-ic -- port sync]) ovn_init_ic_db @@ -185,7 +191,9 @@ OVN_CLEANUP_SBOX(gw1) OVN_CLEANUP_IC([az1], [az2]) AT_CLEANUP +]) +OVN_FOR_EACH_NORTHD([ AT_SETUP([ovn-ic -- route sync]) ovn_init_ic_db @@ -310,3 +318,4 @@ OVS_WAIT_WHILE([ovn_as az1 ovn-nbctl lr-route-list lr1 | grep learned | grep 10. OVN_CLEANUP_IC([az1], [az2]) AT_CLEANUP +]) diff --git a/tests/ovn-macros.at b/tests/ovn-macros.at index 2ba29a960edc..a6b908741673 100644 --- a/tests/ovn-macros.at +++ b/tests/ovn-macros.at @@ -47,10 +47,12 @@ m4_define([OVN_CLEANUP],[ OVS_APP_EXIT_AND_WAIT([ovsdb-server]) as northd -OVS_APP_EXIT_AND_WAIT([ovn-northd]) +OVS_APP_EXIT_AND_WAIT([[$NORTHD_TYPE]]) -as northd-backup -OVS_APP_EXIT_AND_WAIT([ovn-northd]) +if test -d northd-backup; then +as northd-backup +OVS_APP_EXIT_AND_WAIT([[$NORTHD_TYPE]]) +fi OVN_CLEANUP_VSWITCH([main]) ]) @@ -69,10 +71,12 @@ m4_define([OVN_CLEANUP_AZ],[ OVS_APP_EXIT_AND_WAIT([ovsdb-server]) as $1/northd -OVS_APP_EXIT_AND_WAIT([ovn-northd]) +OVS_APP_EXIT_AND_WAIT([[$NORTHD_TYPE]]) -as $1/northd-backup -OVS_APP_EXIT_AND_WAIT([ovn-northd]) +if test -d $1/northd-backup; then +as $1/northd-backup +OVS_APP_EXIT_AND_WAIT([[$NORTHD_TYPE]]) +fi as $1/ic OVS_APP_EXIT_AND_WAIT([ovn-ic]) @@ -134,15 +138,48 @@ ovn_init_ic_db () { ovn_init_db ovn-ic-sb } -# ovn_start [AZ] +# ovn_start_northd (primary|backup) [AZ] +ovn_start_northd() { +local priority=$1 +local AZ=$2 +local msg_prefix=${AZ:+$AZ: } +local d_prefix=${AZ:+$AZ/} + +local suffix= +case $priority in +backup) suffix=-backup ;; +esac + +local northd_args= +case ${NORTHD_TYPE:=ovn-northd} in +ovn-northd) ;; +ovn-northd-ddlog) northd_args="--ddlog-record=${AZ:+$AZ/}replay$suffix.dat -v" ;; +esac + +local name=${d_prefix}northd${suffix} +echo "${prefix}starting $name" +test -d "$ovs_base/$name" || mkdir "$ovs_base/$name" +as $name start_daemon $NORTHD_TYPE $northd_args -vjsonrpc \ + --ovnnb-db=$OVN_NB_DB --ovnsb-db=$OVN_SB_DB +} + +# ovn_start [--no-backup-northd] [AZ] # # Creates and initializes ovn-sb and ovn-nb databases and starts their # ovsdb-server instance, sets appropriate environment variables so that # ovn-sbctl and ovn-nbctl use them by default, and starts ovn-northd running # against them. ovn_start () { -if test -n "$1"; then -mkdir "$ovs_base"/$1 +local backup_northd=: +case $1 in +--no-backup-northd) backup_northd=false; shift ;; +esac +local AZ=$1 +local msg_prefix=${AZ:+$AZ: } +local d_prefix=${AZ:+$AZ/} + +if test -n "$AZ"; then +mkdir "$ovs_base"/$AZ fi ovn_init_db ovn-sb $1; ovn-sbctl init @@ -150,36 +187,19 @@ ovn_start () { if test -n "$1"; then ovn-nbctl set NB_Global . name=$1 fi -local ovn_sb_db=$OVN_SB_DB -local ovn_nb_db=$OVN_NB_DB -local as_d=northd -if test -n "$1"; then -as_d=$1/$as_d +ovn_start_northd primary $AZ +if $backup_northd; then +ovn_start_northd backup $AZ fi -echo "starting ovn-northd" -mkdir "$ovs_base"/$as_d -as $as_d start_daemon ovn-northd -v \ - --ovnnb-db=$ovn_nb_db \ - --ovnsb-db=$ovn_sb_db -as_d=northd-backup -if test -n "$1"; then -as_d=$1/$as_d -fi -echo "starting backup ovn-northd" -mkdir "$ovs_base"/$as_d -as $as_d start_daemon ovn-northd -v \ - --ovnnb-db=$ovn_nb_db \ - --ovnsb-db=$ovn_sb_db +if test -n "$AZ"; then
[ovs-dev] [PATCH ovn v10.1 4/6] ovn-northd: Simplify logic in build_bfd_table().
The code here checked whether 'bfd_e' was null even though that wasn't necessary given the control flow just above it. Signed-off-by: Ben Pfaff --- northd/ovn-northd.c | 16 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/northd/ovn-northd.c b/northd/ovn-northd.c index 39d798782002..8c74c9fd66b9 100644 --- a/northd/ovn-northd.c +++ b/northd/ovn-northd.c @@ -7457,15 +7457,15 @@ build_bfd_table(struct northd_context *ctx, struct hmap *bfd_connections, int d_mult = nb_bt->n_detect_mult ? nb_bt->detect_mult[0] : BFD_DEF_DETECT_MULT; sbrec_bfd_set_detect_mult(sb_bt, d_mult); -} else if (strcmp(bfd_e->sb_bt->status, nb_bt->status)) { -if (!strcmp(nb_bt->status, "admin_down") || -!strcmp(bfd_e->sb_bt->status, "admin_down")) { -sbrec_bfd_set_status(bfd_e->sb_bt, nb_bt->status); -} else { -nbrec_bfd_set_status(nb_bt, bfd_e->sb_bt->status); +} else { +if (strcmp(bfd_e->sb_bt->status, nb_bt->status)) { +if (!strcmp(nb_bt->status, "admin_down") || +!strcmp(bfd_e->sb_bt->status, "admin_down")) { +sbrec_bfd_set_status(bfd_e->sb_bt, nb_bt->status); +} else { +nbrec_bfd_set_status(nb_bt, bfd_e->sb_bt->status); +} } -} -if (bfd_e) { build_bfd_update_sb_conf(nb_bt, bfd_e->sb_bt); hmap_remove(_only, _e->hmap_node); -- 2.28.0 ___ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev
[ovs-dev] [PATCH ovn v10.1 5/6] ovn-sb: Allow Multicast_Group to have empty set of ports.
I don't know a good reason to intentionally create an empty multicast group, but disallowing empty multicast groups has an odd side effect: you can delete all but one of the ports that a group contains and the database will happily remove the ports from the group automatically (because 'ports' is a set of weak references) but if you try to delete the last port that the group contained, the database server will reject the whole transaction. That's really weird. By allowing a multicast group with no ports, we avoid this special case. Signed-off-by: Ben Pfaff --- ovn-sb.ovsschema | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ovn-sb.ovsschema b/ovn-sb.ovsschema index 0d20f0826646..07eb54b10dd4 100644 --- a/ovn-sb.ovsschema +++ b/ovn-sb.ovsschema @@ -1,7 +1,7 @@ { "name": "OVN_Southbound", -"version": "20.15.0", -"cksum": "539683023 25965", +"version": "20.16.0", +"cksum": "3127541865 25965", "tables": { "SB_Global": { "columns": { @@ -133,7 +133,7 @@ "ports": {"type": {"key": {"type": "uuid", "refTable": "Port_Binding", "refType": "weak"}, - "min": 1, "max": "unlimited"}}}, + "min": 0, "max": "unlimited"}}}, "indexes": [["datapath", "tunnel_key"], ["datapath", "name"]], "isRoot": true}, -- 2.28.0 ___ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev
[ovs-dev] [PATCH ovn v10.1 3/6] tests: Wait for updates in "check BFD config propagation to BFD" test.
Otherwise this test is racy because it assumes that northd finishes its updates between the ovn-nbctl changes and the subsequent checks. Also, simplify some series of "check_column" into single "check_row_count" calls (that then become "wait_row_count"). Signed-off-by: Ben Pfaff --- tests/ovn-northd.at | 44 ++-- 1 file changed, 14 insertions(+), 30 deletions(-) diff --git a/tests/ovn-northd.at b/tests/ovn-northd.at index e4fceff037a8..1a941efe9b5c 100644 --- a/tests/ovn-northd.at +++ b/tests/ovn-northd.at @@ -2463,55 +2463,39 @@ ovn-nbctl create bfd logical_port=r0-sw2 dst_ip=192.168.20.2 status=down min_tx= ovn-nbctl create bfd logical_port=r0-sw3 dst_ip=192.168.30.2 status=down ovn-nbctl create bfd logical_port=r0-sw4 dst_ip=192.168.40.2 status=down min_tx=0 detect_mult=0 -check_column 10 bfd detect_mult logical_port=r0-sw1 -check_column "192.168.10.2" bfd dst_ip logical_port=r0-sw1 -check_column 250 bfd min_rx logical_port=r0-sw1 -check_column 250 bfd min_tx logical_port=r0-sw1 -check_column admin_down bfd status logical_port=r0-sw1 - -check_column 20 bfd detect_mult logical_port=r0-sw2 -check_column "192.168.20.2" bfd dst_ip logical_port=r0-sw2 -check_column 500 bfd min_rx logical_port=r0-sw2 -check_column 500 bfd min_tx logical_port=r0-sw2 -check_column admin_down bfd status logical_port=r0-sw2 - -check_column 5 bfd detect_mult logical_port=r0-sw3 -check_column "192.168.30.2" bfd dst_ip logical_port=r0-sw3 -check_column 1000 bfd min_rx logical_port=r0-sw3 -check_column 1000 bfd min_tx logical_port=r0-sw3 -check_column admin_down bfd status logical_port=r0-sw3 +wait_row_count bfd 1 logical_port=r0-sw1 detect_mult=10 dst_ip=192.168.10.2 \ + min_rx=250 min_tx=250 status=admin_down +wait_row_count bfd 1 logical_port=r0-sw2 detect_mult=20 dst_ip=192.168.20.2 \ + min_rx=500 min_tx=500 status=admin_down +wait_row_count bfd 1 logical_port=r0-sw3 detect_mult=5 dst_ip=192.168.30.2 \ + min_rx=1000 min_tx=1000 status=admin_down uuid=$(fetch_column nb:bfd _uuid logical_port=r0-sw1) -check ovn-nbctl set bfd $uuid min_tx=1000 -check ovn-nbctl set bfd $uuid min_rx=1000 -check ovn-nbctl set bfd $uuid detect_mult=100 +check ovn-nbctl set bfd $uuid min_tx=1000 min_rx=1000 detect_mult=100 uuid_2=$(fetch_column nb:bfd _uuid logical_port=r0-sw2) check ovn-nbctl clear bfd $uuid_2 min_rx -check_column 1000 bfd min_rx logical_port=r0-sw2 - -check_column 1000 bfd min_tx logical_port=r0-sw1 -check_column 1000 bfd min_rx logical_port=r0-sw1 -check_column 100 bfd detect_mult logical_port=r0-sw1 +wait_row_count bfd 1 logical_port=r0-sw2 min_rx=1000 +wait_row_count bfd 1 logical_port=r0-sw1 min_rx=1000 min_tx=1000 detect_mult=100 check ovn-nbctl --bfd=$uuid lr-route-add r0 100.0.0.0/8 192.168.10.2 -check_column down bfd status logical_port=r0-sw1 +wait_column down bfd status logical_port=r0-sw1 AT_CHECK([ovn-nbctl lr-route-list r0 | grep 192.168.10.2 | grep -q bfd],[0]) check ovn-nbctl --bfd lr-route-add r0 200.0.0.0/8 192.168.20.2 -check_column down bfd status logical_port=r0-sw2 +wait_column down bfd status logical_port=r0-sw2 AT_CHECK([ovn-nbctl lr-route-list r0 | grep 192.168.20.2 | grep -q bfd],[0]) check ovn-nbctl --bfd lr-route-add r0 240.0.0.0/8 192.168.50.2 r0-sw5 -check_column down bfd status logical_port=r0-sw5 +wait_column down bfd status logical_port=r0-sw5 AT_CHECK([ovn-nbctl lr-route-list r0 | grep 192.168.50.2 | grep -q bfd],[0]) route_uuid=$(fetch_column nb:logical_router_static_route _uuid ip_prefix="100.0.0.0/8") check ovn-nbctl clear logical_router_static_route $route_uuid bfd -check_column admin_down bfd status logical_port=r0-sw1 +wait_column admin_down bfd status logical_port=r0-sw1 ovn-nbctl destroy bfd $uuid -check_row_count bfd 3 +wait_row_count bfd 3 AT_CLEANUP ]) -- 2.28.0 ___ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev
[ovs-dev] [PATCH ovn v10.1 1/6] Export `VLOG_WARN` and `VLOG_ERR` from libovn for use in ddlog
From: Leonid Ryzhyk Export `ddlog_warn` and `ddlog_err` functions that are just wrappers around `VLOG_WARN` and `VLOG_ERR`. This is not ideal because the functions are exported by `ovn_util.c` and the resulting log messages use `ovn_util` as module name. More importantly, these functions do not do log rate limiting. Signed-off-by: Leonid Ryzhyk Signed-off-by: Ben Pfaff Acked-by: Dumitru Ceara --- TODO.rst | 6 ++ lib/ovn-util.c | 15 +++ lib/ovn-util.h | 5 + 3 files changed, 26 insertions(+) diff --git a/TODO.rst b/TODO.rst index c15815539f4f..ecfe62870fb0 100644 --- a/TODO.rst +++ b/TODO.rst @@ -153,6 +153,12 @@ OVN To-do List hashtable lookup in parse_port_group() which can be avoided when we are sure that the Southbound DB uses the new format. +* ovn-northd-ddlog: Calls to warn() and err() from DDlog code would be + better refactored to use the Warning[] relation (and introduce an + Error[] relation once we want to issue some errors that way). This + would be easier with some improvements in DDlog to more easily + output to multiple relations from a single production. + * IP Multicast Relay * When connecting bridged logical switches (localnet) to logical routers diff --git a/lib/ovn-util.c b/lib/ovn-util.c index b6471063ef7e..a5e0ecd214b2 100644 --- a/lib/ovn-util.c +++ b/lib/ovn-util.c @@ -758,3 +758,18 @@ ovn_get_internal_version(void) sbrec_get_db_version(), N_OVNACTS, OVN_INTERNAL_MINOR_VER); } + +#ifdef DDLOG +/* Callbacks used by the ddlog northd code to print warnings and errors. */ +void +ddlog_warn(const char *msg) +{ +VLOG_WARN("%s", msg); +} + +void +ddlog_err(const char *msg) +{ +VLOG_ERR("%s", msg); +} +#endif diff --git a/lib/ovn-util.h b/lib/ovn-util.h index 08234611838a..55c7bf382a95 100644 --- a/lib/ovn-util.h +++ b/lib/ovn-util.h @@ -261,4 +261,9 @@ BUILD_ASSERT_DECL(SCTP_INIT_CHUNK_LEN == sizeof(struct sctp_init_chunk)); /* See RFC 4960 Sections 3.3.7 and 8.5.1 for information on this flag. */ #define SCTP_ABORT_CHUNK_FLAG_T (1 << 0) +#ifdef DDLOG +void ddlog_warn(const char *msg); +void ddlog_err(const char *msg); +#endif + #endif -- 2.28.0 ___ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev
[ovs-dev] [PATCH ovn v10.1 0/6] Add DDlog implementation of ovn-northd
v10.1: - Fold in fix to northd makefile. v10: - Fix linking problem reported by Dumitru and others. - Update to ddlog 0.36.0 (thanks Leonid!). - Port OVN commits up to 858d1dd716db ("ofctrl: Fix the assert seen when flood removing flows.") - Fix IGMP and MLD snoop/querier/reply tests (thanks Dumitru!). - New commit "ovn-sb: Allow Multicast_Group to have empty set of ports." - New commit "ovn-northd: Simplify logic in build_bfd_table()." - New commit "tests: Wait for updates in "check BFD config propagation to BFD" test." v9: - Add ddlog.stamp to BUILT_SOURCES, to fix the dependencies "for sure". - Rebase against ovn/master. - Port commit fdf295d5eb3a ("pinctrl: Honor always_learn_from_arp_request for self created MAC_Bindings.") - Update to work with and require v2 of the ovsdb-cs library (see https://mail.openvswitch.org/pipermail/ovs-dev/2020-December/378180.html). - All non-skipped tests pass, although some are still racy. - This is also available as the ddlog14 branch here: https://github.com/blp/ovs-reviews/commits/ddlog14 - Haven't done performance tests. I aim to do that for v10. v8: - Rebase against latest ovn master. - Port commit f9cab11d5fab ("Allow explicit setting of the SNAT zone on a gateway router.") - Port commit f1119c125765 ("northd: Refactor load balancer vip parsing.") - Port commit 1dd27ea7aea4 ("Provide the option to pin ovn-controller and ovn-northd to a specific version."). - Port commit 880dca99eaf7 ("northd: Enhance the implementation of ACL log meters (pre-ddlog merge).") - Make ovn-northd-ddlog use the new ovsdb-cs (client sync) library proposed for OVS (https://mail.openvswitch.org/pipermail/ovs-dev/2020-November/377828.html). In addition to eliminating duplicated code, this should make it able to connect to a raft cluster. - Further improvements to test improvement patch (mostly added "check"s and AS_BOX(...) to announce parts of a test) - Modernize some of the ddlog code a bit, e.g. by using the method-like calls such as foo.get("key") in place of map_get(foo, "key"). v7: - Fixed "make dist" (thanks to Numan for reporting this.) - Fix probe interval setting (thanks to Numan again). - Small amount of improvement of OVN DDlog code (use lambdas in more places). - Fine-tuning of ovn-northd-ddlog code for jsonrpc session usage. - Fix newline issues in tests reported by Dumitru. - Add ack from Dumitru. v6: - Applied and dropped patch for "test a == b". - Applied and dropped patch to allow more args to wait_for_row_count(). - Applied and dropped ARP/ND broadcast test improvement patch. - Fix whitespace in patch to export ddlog_warn() and ddlog_err(). v5: - Drop patch for ACL log meters (this was included in v4.1 by mistake). - In addition to waiting for database, also wait for ports to come up. - New patch to support more arguments to wait_for_row_count that waiting for ports indirectly needed. - Port commit c29221d9322a ("Allow VLAN traffic when LS:vlan-passthru=true"). - Port commit 36a8745de859 ("Add support for DHCP options 28 (Broadcast Address)") - Add patch to improve "ARP/ND request broadcast limiting" test. v4: - Fix dependencies for parallel build. - Fix spelling error in documentation. - Use --wait=sb, not --wait=hv, when no chassis are running. - Fixed IGMP and MLD tests by porting commit 9d2e8d32fb98 ("ofctrl.c: Fix duplicated flow handling in I-P while merging opposite changes."), which I had missed before. Ben Pfaff (4): tests: Prepare for multiple northd types. tests: Wait for updates in "check BFD config propagation to BFD" test. ovn-northd: Simplify logic in build_bfd_table(). ovn-sb: Allow Multicast_Group to have empty set of ports. Leonid Ryzhyk (2): Export `VLOG_WARN` and `VLOG_ERR` from libovn for use in ddlog ovn-northd-ddlog: New implementation of ovn-northd based on ddlog. Documentation/automake.mk |2 + Documentation/intro/install/general.rst | 31 +- Documentation/topics/debugging-ddlog.rst | 280 + Documentation/topics/index.rst|1 + Documentation/tutorials/ddlog-new-feature.rst | 362 + Documentation/tutorials/index.rst |1 + NEWS |6 + TODO.rst |6 + acinclude.m4 | 43 + build-aux/automake.mk |1 + build-aux/libtool-deps| 35 + configure.ac |5 + lib/ovn-util.c| 15 + lib/ovn-util.h|5 + m4/ovn.m4 | 16 + northd/.gitignore |4 + northd/automake.mk| 108 + northd/helpers.dl | 96 + northd/ipam.dl
Re: [ovs-dev] [PATCH ovn v3] northd: Provide the Gateway router option 'lb_force_snat_ip' to take router port ips.
On 18/02/2021 19:00, num...@ovn.org wrote: > From: Numan Siddique > > When a Gateway router is configured with a load balancer > and it is also configured with options:lb_force_snat_ip=, > OVN after load balancing the destination IP to one of the > backend also does a NAT on the source ip with the > lb_force_snat_ip if the packet is destined to a load balancer > VIP. > > There is a problem with the snat of source ip to 'lb_force_snat_ip' > in one particular usecase. When the packet enters the Gateway router > from a provider logical switch destined to the load balancer VIP, > then it is first load balanced to one of the backend and then > the source ip is snatted to 'lb_force_snat_ip'. If the chosen > backend is reachable via the provider logical switch, then the > packet is hairpinned back and it may hit the wire with > the source ip 'lb_force_snat_ip'. If 'lb_force_snat_ip' happens > to be an OVN internal IP then the packet may be dropped. > > This patch addresses this issue by providing the option to > set the option - 'lb_force_snat_ip=router_ip'. If 'router_ip' > is set, then OVN will snat the load balanced packet to the > router ip of the logical router port which is chosen as 'outport' > in lr_in_ip_routing stage. > > Example. > > If the gateway router is > > ovn-nbctl show lr0 > router 68f20092-5563-44b8-9ccb-b11de3e3a66c (lr0) > port lr0-sw0 > mac: "00:00:00:00:ff:01" > networks: ["10.0.0.1/24"] > port lr0-public > mac: "00:00:20:20:12:13" > networks: ["172.168.0.100/24"] > > Then the below logical flows are added if 'lb_force_snat_ip' > is configured to 'router_ip'. > > table=1 (lr_out_snat), priority=110 >match=(flags.force_snat_for_lb == 1 && ip4 && outport == "lr0-public"), >action=(ct_snat(172.168.0.100);) > > table=1 (lr_out_snat), priority=110 >match=(flags.force_snat_for_lb == 1 && ip4 && outport == "lr0-sw0") >action=(ct_snat(10.0.0.1);) > > For the above described scenario, the packet will have source ip as > 172.168.0.100 which belongs to the provider logical switch CIDR. > > Reported-by: Tim Rozet > Signed-off-by: Numan Siddique > --- > northd/ovn-northd.8.xml | 35 > northd/ovn-northd.c | 91 + > ovn-nb.xml | 33 ++- > tests/ovn-northd.at | 79 +++ > 4 files changed, 220 insertions(+), 18 deletions(-) > > diff --git a/northd/ovn-northd.8.xml b/northd/ovn-northd.8.xml > index 2f8b4e8c30..1d8f5edee1 100644 > --- a/northd/ovn-northd.8.xml > +++ b/northd/ovn-northd.8.xml > @@ -3654,6 +3654,32 @@ nd_ns { >flags.force_snat_for_dnat == 1 ip with an >action ct_snat(B);. > > + > + > + > + > + If the Gateway router in the OVN Northbound database has been > + configured to force SNAT a packet (that has been previously > + load-balanced) using router IP (i.e + table="Logical_Router"/>:lb_force_snat_ip=router_ip), then for > + each logical router port P attached to the Gateway > + router, a priority-110 flow matches > + flags.force_snat_for_lb == 1 outport == > P > + with an action ct_snat(R); > + where R is the IP configured on the router port. > + If R is an IPv4 address then the match will also > + include ip4 and if it is an IPv6 address, then the > + match will also include ip6. > + > + > + > + If the logical router port P is configured with multiple > + IPv4 and multiple IPv6 addresses, only the first IPv4 and first > IPv6 > + address is considered. > + > + > + > + > >If the Gateway router in the OVN Northbound database has been >configured to force SNAT a packet (that has been previously > @@ -3661,6 +3687,9 @@ nd_ns { >flags.force_snat_for_lb == 1 ip with an >action ct_snat(B);. > > + > + > + > >For each configuration in the OVN Northbound database, that asks >to change the source IP address of a packet from an IP address of > @@ -3674,14 +3703,18 @@ nd_ns { >options, then the action would be ip4/6.src= >(B). > > + > > + > >If the NAT rule has allowed_ext_ips configured, then >there is an additional match ip4.dst == allowed_ext_ips >. Similarly, for IPV6, match would be ip6.dst == >allowed_ext_ips. > > + > > + > >If the NAT rule has exempted_ext_ips set, then >there is an additional flow configured at the priority + 1 of > @@ -3690,7 +3723,9 @@ nd_ns { >. This flow is used to bypass the ct_snat action for a > packet >which is destinted to exempted_ext_ips. > >
[ovs-dev] [PATCH ovn v3] northd: Provide the Gateway router option 'lb_force_snat_ip' to take router port ips.
From: Numan Siddique When a Gateway router is configured with a load balancer and it is also configured with options:lb_force_snat_ip=, OVN after load balancing the destination IP to one of the backend also does a NAT on the source ip with the lb_force_snat_ip if the packet is destined to a load balancer VIP. There is a problem with the snat of source ip to 'lb_force_snat_ip' in one particular usecase. When the packet enters the Gateway router from a provider logical switch destined to the load balancer VIP, then it is first load balanced to one of the backend and then the source ip is snatted to 'lb_force_snat_ip'. If the chosen backend is reachable via the provider logical switch, then the packet is hairpinned back and it may hit the wire with the source ip 'lb_force_snat_ip'. If 'lb_force_snat_ip' happens to be an OVN internal IP then the packet may be dropped. This patch addresses this issue by providing the option to set the option - 'lb_force_snat_ip=router_ip'. If 'router_ip' is set, then OVN will snat the load balanced packet to the router ip of the logical router port which is chosen as 'outport' in lr_in_ip_routing stage. Example. If the gateway router is ovn-nbctl show lr0 router 68f20092-5563-44b8-9ccb-b11de3e3a66c (lr0) port lr0-sw0 mac: "00:00:00:00:ff:01" networks: ["10.0.0.1/24"] port lr0-public mac: "00:00:20:20:12:13" networks: ["172.168.0.100/24"] Then the below logical flows are added if 'lb_force_snat_ip' is configured to 'router_ip'. table=1 (lr_out_snat), priority=110 match=(flags.force_snat_for_lb == 1 && ip4 && outport == "lr0-public"), action=(ct_snat(172.168.0.100);) table=1 (lr_out_snat), priority=110 match=(flags.force_snat_for_lb == 1 && ip4 && outport == "lr0-sw0") action=(ct_snat(10.0.0.1);) For the above described scenario, the packet will have source ip as 172.168.0.100 which belongs to the provider logical switch CIDR. Reported-by: Tim Rozet Signed-off-by: Numan Siddique --- northd/ovn-northd.8.xml | 35 northd/ovn-northd.c | 91 + ovn-nb.xml | 33 ++- tests/ovn-northd.at | 79 +++ 4 files changed, 220 insertions(+), 18 deletions(-) diff --git a/northd/ovn-northd.8.xml b/northd/ovn-northd.8.xml index 2f8b4e8c30..1d8f5edee1 100644 --- a/northd/ovn-northd.8.xml +++ b/northd/ovn-northd.8.xml @@ -3654,6 +3654,32 @@ nd_ns { flags.force_snat_for_dnat == 1 ip with an action ct_snat(B);. + + + + + If the Gateway router in the OVN Northbound database has been + configured to force SNAT a packet (that has been previously + load-balanced) using router IP (i.e :lb_force_snat_ip=router_ip), then for + each logical router port P attached to the Gateway + router, a priority-110 flow matches + flags.force_snat_for_lb == 1 outport == P + with an action ct_snat(R); + where R is the IP configured on the router port. + If R is an IPv4 address then the match will also + include ip4 and if it is an IPv6 address, then the + match will also include ip6. + + + + If the logical router port P is configured with multiple + IPv4 and multiple IPv6 addresses, only the first IPv4 and first IPv6 + address is considered. + + + + If the Gateway router in the OVN Northbound database has been configured to force SNAT a packet (that has been previously @@ -3661,6 +3687,9 @@ nd_ns { flags.force_snat_for_lb == 1 ip with an action ct_snat(B);. + + + For each configuration in the OVN Northbound database, that asks to change the source IP address of a packet from an IP address of @@ -3674,14 +3703,18 @@ nd_ns { options, then the action would be ip4/6.src= (B). + + If the NAT rule has allowed_ext_ips configured, then there is an additional match ip4.dst == allowed_ext_ips . Similarly, for IPV6, match would be ip6.dst == allowed_ext_ips. + + If the NAT rule has exempted_ext_ips set, then there is an additional flow configured at the priority + 1 of @@ -3690,7 +3723,9 @@ nd_ns { . This flow is used to bypass the ct_snat action for a packet which is destinted to exempted_ext_ips. + + A priority-0 logical flow with match 1 has actions next;. diff --git a/northd/ovn-northd.c b/northd/ovn-northd.c index 39d7987820..0bbe92c09d 100644 --- a/northd/ovn-northd.c +++ b/northd/ovn-northd.c @@ -624,6 +624,7 @@ struct ovn_datapath { struct lport_addresses dnat_force_snat_addrs;
[ovs-dev] [PATCH ovn v10.1 0/6] Add DDlog implementation of ovn-northd
v10.1: - Fold in fix to northd makefile. v10: - Fix linking problem reported by Dumitru and others. - Update to ddlog 0.36.0 (thanks Leonid!). - Port OVN commits up to 858d1dd716db ("ofctrl: Fix the assert seen when flood removing flows.") - Fix IGMP and MLD snoop/querier/reply tests (thanks Dumitru!). - New commit "ovn-sb: Allow Multicast_Group to have empty set of ports." - New commit "ovn-northd: Simplify logic in build_bfd_table()." - New commit "tests: Wait for updates in "check BFD config propagation to BFD" test." v9: - Add ddlog.stamp to BUILT_SOURCES, to fix the dependencies "for sure". - Rebase against ovn/master. - Port commit fdf295d5eb3a ("pinctrl: Honor always_learn_from_arp_request for self created MAC_Bindings.") - Update to work with and require v2 of the ovsdb-cs library (see https://mail.openvswitch.org/pipermail/ovs-dev/2020-December/378180.html). - All non-skipped tests pass, although some are still racy. - This is also available as the ddlog14 branch here: https://github.com/blp/ovs-reviews/commits/ddlog14 - Haven't done performance tests. I aim to do that for v10. v8: - Rebase against latest ovn master. - Port commit f9cab11d5fab ("Allow explicit setting of the SNAT zone on a gateway router.") - Port commit f1119c125765 ("northd: Refactor load balancer vip parsing.") - Port commit 1dd27ea7aea4 ("Provide the option to pin ovn-controller and ovn-northd to a specific version."). - Port commit 880dca99eaf7 ("northd: Enhance the implementation of ACL log meters (pre-ddlog merge).") - Make ovn-northd-ddlog use the new ovsdb-cs (client sync) library proposed for OVS (https://mail.openvswitch.org/pipermail/ovs-dev/2020-November/377828.html). In addition to eliminating duplicated code, this should make it able to connect to a raft cluster. - Further improvements to test improvement patch (mostly added "check"s and AS_BOX(...) to announce parts of a test) - Modernize some of the ddlog code a bit, e.g. by using the method-like calls such as foo.get("key") in place of map_get(foo, "key"). v7: - Fixed "make dist" (thanks to Numan for reporting this.) - Fix probe interval setting (thanks to Numan again). - Small amount of improvement of OVN DDlog code (use lambdas in more places). - Fine-tuning of ovn-northd-ddlog code for jsonrpc session usage. - Fix newline issues in tests reported by Dumitru. - Add ack from Dumitru. v6: - Applied and dropped patch for "test a == b". - Applied and dropped patch to allow more args to wait_for_row_count(). - Applied and dropped ARP/ND broadcast test improvement patch. - Fix whitespace in patch to export ddlog_warn() and ddlog_err(). v5: - Drop patch for ACL log meters (this was included in v4.1 by mistake). - In addition to waiting for database, also wait for ports to come up. - New patch to support more arguments to wait_for_row_count that waiting for ports indirectly needed. - Port commit c29221d9322a ("Allow VLAN traffic when LS:vlan-passthru=true"). - Port commit 36a8745de859 ("Add support for DHCP options 28 (Broadcast Address)") - Add patch to improve "ARP/ND request broadcast limiting" test. v4: - Fix dependencies for parallel build. - Fix spelling error in documentation. - Use --wait=sb, not --wait=hv, when no chassis are running. - Fixed IGMP and MLD tests by porting commit 9d2e8d32fb98 ("ofctrl.c: Fix duplicated flow handling in I-P while merging opposite changes."), which I had missed before. Ben Pfaff (4): tests: Prepare for multiple northd types. tests: Wait for updates in "check BFD config propagation to BFD" test. ovn-northd: Simplify logic in build_bfd_table(). ovn-sb: Allow Multicast_Group to have empty set of ports. Leonid Ryzhyk (2): Export `VLOG_WARN` and `VLOG_ERR` from libovn for use in ddlog ovn-northd-ddlog: New implementation of ovn-northd based on ddlog. Documentation/automake.mk |2 + Documentation/intro/install/general.rst | 31 +- Documentation/topics/debugging-ddlog.rst | 280 + Documentation/topics/index.rst|1 + Documentation/tutorials/ddlog-new-feature.rst | 362 + Documentation/tutorials/index.rst |1 + NEWS |6 + TODO.rst |6 + acinclude.m4 | 43 + build-aux/automake.mk |1 + build-aux/libtool-deps| 35 + configure.ac |5 + lib/ovn-util.c| 15 + lib/ovn-util.h|5 + m4/ovn.m4 | 16 + northd/.gitignore |4 + northd/automake.mk| 108 + northd/helpers.dl | 96 + northd/ipam.dl
Re: [ovs-dev] [PATCH ovn v10 6/6] ovn-northd-ddlog: New implementation of ovn-northd based on ddlog.
This had a bug in the makefile. I fixed it: https://github.com/blp/ovs-reviews/actions/runs/579105628 I'll post a v10.1. ___ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev
[ovs-dev] [PATCH ovn v2] ofctrl: Do not link a desired flow twice.
Depending on the logical flow matches, multiple SB flows can point to the same desired flow. If it happens that the desired flow conflicts with a more restrictive (already installed) flow, then we shouldn't try to add the desired flow multiple times to the list maintained for the installed flow. Fixes: 6f0b1e02d9ab ("ofctrl: Incremental processing for flow installation by tracking.") Signed-off-by: Dumitru Ceara --- Note: I'm quite sure about the "Fixes" tag above, however, I couldn't reproduce the issue without the following commit: dadae4f800cc ("ofctrl.c: Only merge actions for conjunctive flows.") v2: - Address Mark's comments: - readd log message removed by accident. - add comments to the new test. --- controller/ofctrl.c | 2 +- tests/ovn.at| 23 +++ 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/controller/ofctrl.c b/controller/ofctrl.c index 1c9694a..415d9b7 100644 --- a/controller/ofctrl.c +++ b/controller/ofctrl.c @@ -1989,7 +1989,7 @@ update_installed_flows_by_track(struct ovn_desired_flow_table *flow_table, * tracked, so it must have been modified. */ installed_flow_mod(>flow, >flow, msgs); ovn_flow_log(>flow, "updating installed (tracked)"); -} else { +} else if (!f->installed_flow) { /* Adding a new flow that conflicts with an existing installed * flow, so add it to the link. If this flow becomes active, * e.g., it is less restrictive than the previous active flow diff --git a/tests/ovn.at b/tests/ovn.at index 344e6bf..3d027c4 100644 --- a/tests/ovn.at +++ b/tests/ovn.at @@ -13955,6 +13955,29 @@ AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=45 | ofctl_strip_all | \ table=45, priority=1003,ip,metadata=0x1,nw_src=10.0.0.42 actions=conjunction() ]) +# Add another ACL that overlaps with the existing less restrictive ones. +check ovn-nbctl acl-add ls1 to-lport 3 'udp || ((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 +check ovn-nbctl --wait=hv sync + +# Check OVS flows, the same conjunctive flows as above should still be there, +# with an additional conjunction action. +# +# New non-conjunctive flows should be added to match on 'udp'. +AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=45 | ofctl_strip_all | \ + grep "priority=1003" | \ + sed 's/conjunction([[^)]]*)/conjunction()/g' | sort], [0], [dnl + table=45, priority=1003,conj_id=2,ip,metadata=0x1 actions=resubmit(,46) + table=45, priority=1003,conj_id=3,ip,metadata=0x1 actions=resubmit(,46) + table=45, priority=1003,conj_id=4,ip,metadata=0x1 actions=resubmit(,46) + table=45, priority=1003,ip,metadata=0x1,nw_dst=10.0.0.3 actions=conjunction(),conjunction(),conjunction() + table=45, priority=1003,ip,metadata=0x1,nw_dst=10.0.0.4 actions=conjunction(),conjunction(),conjunction() + table=45, priority=1003,ip,metadata=0x1,nw_src=10.0.0.1 actions=resubmit(,46) + table=45, priority=1003,ip,metadata=0x1,nw_src=10.0.0.2 actions=conjunction(),conjunction() + table=45, priority=1003,ip,metadata=0x1,nw_src=10.0.0.42 actions=conjunction() + table=45, priority=1003,udp,metadata=0x1 actions=resubmit(,46) + table=45, priority=1003,udp6,metadata=0x1 actions=resubmit(,46) +]) + OVN_CLEANUP([hv1]) AT_CLEANUP -- 1.8.3.1 ___ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev
Re: [ovs-dev] [PATCH ovn] northd: Provide the Gateway router option 'lb_force_snat_ip' to take router port ips.
On Thu, Feb 18, 2021 at 11:56 PM Mark Gray wrote: > > On 18/02/2021 17:26, Numan Siddique wrote: > > On Thu, Feb 18, 2021 at 9:15 PM Mark Gray wrote: > >> > >> On 18/02/2021 14:30, Numan Siddique wrote: > >>> On Wed, Feb 17, 2021 at 7:37 PM Mark Gray wrote: > > Thanks Numan, some suggestions below! > >>> > >>> Hi Mark G, > >>> > >>> Thanks for the review. > >>> > >>> PSB for a few comments. > >>> > > On 09/02/2021 18:44, num...@ovn.org wrote: > > From: Numan Siddique > > > > When a Gateway router is configured with a load balancer > > and it is also configured with options:lb_force_snat_ip=, > > OVN after load balancing the destination IP to one of the > > backend also does a NAT on the source ip with the > > lb_force_snat_ip if the packet is destined to a load balancer > > VIP. > > > > There is a problem with the snat of source ip to 'lb_force_snat_ip' > > in one particular usecase. When the packet enters the Gateway router > > from a provider logical switch destined to the load balancer VIP, > > then it is first load balanced to one of the backend and then > > the source ip is snatted to 'lb_force_snat_ip'. If the chosen > > backend is reachable via the provider logical switch, then the > > packet is hairpinned back and it may hit the wire with > > the source ip 'lb_force_snat_ip'. If 'lb_force_snat_ip' happens > > to be an OVN internal IP then the packet may be dropped. > > > > This patch addresses this issue by providing the option to > > set the option - 'lb_force_snat_ip=router_ip'. If 'router_ip' > > is set, then OVN will snat the load balanced packet to the > > router ip of the logical router port which chosen as 'outport' > > in lr_in_ip_routing stage. > > It almost feels like this should be the default behaviour? > >>> > >>> > >>> Can you please elaborate more ? You mean ideally CMS should set > >>> - router_ip ? > >> > >> I was thinking that it could just be lb_force_snat_ip=true (default to > >> remote_ip)? > > > > You mean 'router_ip' ? If it is 'true' then, IMHO, it is not clear with > > what IP > > to snat with. > > > > Since lb_force_snat_ip can take other IP addresses (which is the present > > case), > > I am not sure if mixing bool/string would be clear enough for the user. > > > > Let me know if you think it is obvious that it will be router ip if set to > > true. > > Let me rephrase. Is there a use case in which IP should be specified? > However, thinking about it more, I think I have answered myself, it > could be that if a link had multiple IPs, you would want to specify > which IP it should take. Also right now with the present master, we do support IP for lb_force_snat_ip An example - https://github.com/ovn-org/ovn/blob/master/tests/ovn.at#L22669 Ok. Let me know if you are fine with the patch If I do the other changes ? I can definitely spin up another version if you prefer. Thanks Numan > > > > > Thanks > > Numan > > > > > >>> > >>> > > > > Example. > > > > If the gateway router is > > > > ovn-nbctl show lr0 > > router 68f20092-5563-44b8-9ccb-b11de3e3a66c (lr0) > > port lr0-sw0 > > mac: "00:00:00:00:ff:01" > > networks: ["10.0.0.1/24"] > > port lr0-public > > mac: "00:00:20:20:12:13" > > networks: ["172.168.0.100/24"] > > > > Then the below logical flows are added if 'lb_force_snat_ip' > > is configured to 'router_ip'. > > > > table=1 (lr_out_snat), priority=110 > >match=(flags.force_snat_for_lb == 1 && ip4 && outport == > > "lr0-public"), > >action=(ct_snat(172.168.0.100);) > > > > table=1 (lr_out_snat), priority=110 > >match=(flags.force_snat_for_lb == 1 && ip4 && outport == "lr0-sw0") > >action=(ct_snat(10.0.0.1);) > > > > For the above described scenario, the packet will have source ip as > > 172.168.0.100 which belongs to the provider logical switch CIDR. > > > > Reported-by: Tim Rozet > > Signed-off-by: Numan Siddique > > --- > > northd/ovn-northd.8.xml | 35 ++ > > northd/ovn-northd.c | 66 -- > > tests/ovn-northd.at | 79 + > > 3 files changed, 177 insertions(+), 3 deletions(-) > > > > diff --git a/northd/ovn-northd.8.xml b/northd/ovn-northd.8.xml > > index 70065a36d9..27b28aff93 100644 > > --- a/northd/ovn-northd.8.xml > > +++ b/northd/ovn-northd.8.xml > > Should 'ovn-nb.xml' also be updated? > >>> > >>> Great catch. I totally missed it. > >>> > > > @@ -3653,6 +3653,32 @@ nd_ns { > >flags.force_snat_for_dnat == 1 ip > > with an > >action ct_snat(B);. > > > > + > > + > > + > > + > > + If the Gateway
[ovs-dev] [RFC PATCH ovn] binding: Do not try to incrementally process former VIF updates.
If a Port_Binding corresponding to a VIF changes in the Southbound to represent a port that cannot be bound locally (e.g., localport, localnet, patch) then ovn-controller should not try to process this update incrementally. If it would try, it would need to first remove cleanup all previous lbindings from memory which is not trivial. Failing to do so might cause ovn-controller to access already freed memory later on. However, because this is an unlikely scenario, to avoid over complicating the incremental processing engine, we now rely to a regular recompute when such Port_Binding updates are detected. This implies though that when the runtime_data I-P node is updated we also need to recompute physical flows to make sure that flows for specific types of ports, e.g., localports, are properly installed. To reproduce the issue, this patch also modifies the "ovn -- 2 HVs, 1 lport/HV, localport ports" test. More tests are added for all types of port bindings that shouldn't be claimed locally. Fixes: 354bdba51abf ("ovn-controller: I-P for SB port binding and OVS interface in runtime_data.") Signed-off-by: Dumitru Ceara --- Note: sending this patch as RFC for now because I'm not completely sure if the physical_run() call in the I-P engine can be avoided. --- controller/binding.c| 32 controller/ovn-controller.c | 2 ++ tests/ovn.at| 59 - 3 files changed, 87 insertions(+), 6 deletions(-) diff --git a/controller/binding.c b/controller/binding.c index efaa109..9ce5c01 100644 --- a/controller/binding.c +++ b/controller/binding.c @@ -1027,6 +1027,17 @@ is_lbinding_container_parent(struct local_binding *lbinding) } static bool +is_non_local_port_bound(const struct sbrec_port_binding *pb, +enum en_lport_type lport_type) +{ +if (lport_type == LP_PATCH || lport_type == LP_LOCALNET || +lport_type == LP_LOCALPORT) { +return !!pb->chassis; +} +return false; +} + +static bool release_local_binding_children(const struct sbrec_chassis *chassis_rec, struct local_binding *lbinding, bool sb_readonly, @@ -1486,9 +1497,17 @@ binding_run(struct binding_ctx_in *b_ctx_in, struct binding_ctx_out *b_ctx_out) b_ctx_in->port_binding_table) { enum en_lport_type lport_type = get_lport_type(pb); +if (is_non_local_port_bound(pb, lport_type)) { +release_lport(pb, !b_ctx_in->ovnsb_idl_txn, NULL); +} + switch (lport_type) { case LP_PATCH: +update_local_lport_ids(pb, b_ctx_out); +break; case LP_LOCALPORT: +update_local_lport_ids(pb, b_ctx_out); +break; case LP_VTEP: update_local_lport_ids(pb, b_ctx_out); break; @@ -1818,6 +1837,12 @@ consider_iface_claim(const struct ovsrec_interface *iface_rec, } if (lbinding->pb) { +enum en_lport_type lport_type = get_lport_type(lbinding->pb); + +if (lport_type != LP_VIF && lport_type != LP_VIRTUAL) { +return true; +} + if (!consider_vif_lport(lbinding->pb, b_ctx_in, b_ctx_out, lbinding, qos_map)) { return false; @@ -2419,6 +2444,13 @@ delete_done: break; } +/* Former VIFs that changed to non-local ports should be released, + * but we cannot handle this incrementally. + */ +if (is_non_local_port_bound(pb, lport_type)) { +handled = false; +} + if (!handled) { break; } diff --git a/controller/ovn-controller.c b/controller/ovn-controller.c index 4343650..15c78db 100644 --- a/controller/ovn-controller.c +++ b/controller/ovn-controller.c @@ -2306,6 +2306,8 @@ flow_output_runtime_data_handler(struct engine_node *node, struct physical_ctx p_ctx; init_physical_ctx(node, rt_data, _ctx); +physical_run(_ctx, >flow_table); + struct tracked_binding_datapath *tdp; HMAP_FOR_EACH (tdp, node, tracked_dp_bindings) { if (tdp->is_new) { diff --git a/tests/ovn.at b/tests/ovn.at index 344e6bf..b3a8b03 100644 --- a/tests/ovn.at +++ b/tests/ovn.at @@ -11319,11 +11319,6 @@ ovn_start ovn-nbctl ls-add ls1 -# Add localport to the switch -ovn-nbctl lsp-add ls1 lp01 -ovn-nbctl lsp-set-addresses lp01 f0:00:00:00:00:01 -ovn-nbctl lsp-set-type lp01 localport - net_add n1 for i in 1 2; do @@ -11350,10 +11345,17 @@ for i in 1 2; do OVS_WAIT_UNTIL([test x`ovn-nbctl lsp-get-up lp${i}1` = xup]) done +# Add localport to the switch +ovn-nbctl lsp-add ls1 lp01 +ovn-nbctl lsp-set-addresses lp01 f0:00:00:00:00:01 +ovn-nbctl lsp-set-type lp01 localport + wait_for_ports_up -ovn-nbctl --wait=sb sync +ovn-nbctl --wait=hv sync ovn-sbctl dump-flows +check_column "" Port_Binding
Re: [ovs-dev] [PATCH ovn] northd: Provide the Gateway router option 'lb_force_snat_ip' to take router port ips.
On 18/02/2021 17:26, Numan Siddique wrote: > On Thu, Feb 18, 2021 at 9:15 PM Mark Gray wrote: >> >> On 18/02/2021 14:30, Numan Siddique wrote: >>> On Wed, Feb 17, 2021 at 7:37 PM Mark Gray wrote: Thanks Numan, some suggestions below! >>> >>> Hi Mark G, >>> >>> Thanks for the review. >>> >>> PSB for a few comments. >>> On 09/02/2021 18:44, num...@ovn.org wrote: > From: Numan Siddique > > When a Gateway router is configured with a load balancer > and it is also configured with options:lb_force_snat_ip=, > OVN after load balancing the destination IP to one of the > backend also does a NAT on the source ip with the > lb_force_snat_ip if the packet is destined to a load balancer > VIP. > > There is a problem with the snat of source ip to 'lb_force_snat_ip' > in one particular usecase. When the packet enters the Gateway router > from a provider logical switch destined to the load balancer VIP, > then it is first load balanced to one of the backend and then > the source ip is snatted to 'lb_force_snat_ip'. If the chosen > backend is reachable via the provider logical switch, then the > packet is hairpinned back and it may hit the wire with > the source ip 'lb_force_snat_ip'. If 'lb_force_snat_ip' happens > to be an OVN internal IP then the packet may be dropped. > > This patch addresses this issue by providing the option to > set the option - 'lb_force_snat_ip=router_ip'. If 'router_ip' > is set, then OVN will snat the load balanced packet to the > router ip of the logical router port which chosen as 'outport' > in lr_in_ip_routing stage. It almost feels like this should be the default behaviour? >>> >>> >>> Can you please elaborate more ? You mean ideally CMS should set >>> - router_ip ? >> >> I was thinking that it could just be lb_force_snat_ip=true (default to >> remote_ip)? > > You mean 'router_ip' ? If it is 'true' then, IMHO, it is not clear with what > IP > to snat with. > > Since lb_force_snat_ip can take other IP addresses (which is the present > case), > I am not sure if mixing bool/string would be clear enough for the user. > > Let me know if you think it is obvious that it will be router ip if set to > true. Let me rephrase. Is there a use case in which IP should be specified? However, thinking about it more, I think I have answered myself, it could be that if a link had multiple IPs, you would want to specify which IP it should take. > > Thanks > Numan > > >>> >>> > > Example. > > If the gateway router is > > ovn-nbctl show lr0 > router 68f20092-5563-44b8-9ccb-b11de3e3a66c (lr0) > port lr0-sw0 > mac: "00:00:00:00:ff:01" > networks: ["10.0.0.1/24"] > port lr0-public > mac: "00:00:20:20:12:13" > networks: ["172.168.0.100/24"] > > Then the below logical flows are added if 'lb_force_snat_ip' > is configured to 'router_ip'. > > table=1 (lr_out_snat), priority=110 >match=(flags.force_snat_for_lb == 1 && ip4 && outport == "lr0-public"), >action=(ct_snat(172.168.0.100);) > > table=1 (lr_out_snat), priority=110 >match=(flags.force_snat_for_lb == 1 && ip4 && outport == "lr0-sw0") >action=(ct_snat(10.0.0.1);) > > For the above described scenario, the packet will have source ip as > 172.168.0.100 which belongs to the provider logical switch CIDR. > > Reported-by: Tim Rozet > Signed-off-by: Numan Siddique > --- > northd/ovn-northd.8.xml | 35 ++ > northd/ovn-northd.c | 66 -- > tests/ovn-northd.at | 79 + > 3 files changed, 177 insertions(+), 3 deletions(-) > > diff --git a/northd/ovn-northd.8.xml b/northd/ovn-northd.8.xml > index 70065a36d9..27b28aff93 100644 > --- a/northd/ovn-northd.8.xml > +++ b/northd/ovn-northd.8.xml Should 'ovn-nb.xml' also be updated? >>> >>> Great catch. I totally missed it. >>> > @@ -3653,6 +3653,32 @@ nd_ns { >flags.force_snat_for_dnat == 1 ip with > an >action ct_snat(B);. > > + > + > + > + > + If the Gateway router in the OVN Northbound database has been > + configured to force SNAT a packet (that has been previously > + load-balanced) using router IP (i.e + table="Logical_Router"/>:lb_force_snat_ip=router_ip), then for > + each logical router port P attached to the Gateway > + router, a priority-110 flow matches > + flags.force_snat_for_lb == 1 outport == > P > + with an action ct_snat(R); > + where R is the router port IP configured. maybe rephrase to "is the IP configured on the router
Re: [ovs-dev] [PATCH ovn v2] northd: Provide the Gateway router option 'lb_force_snat_ip' to take router port ips.
On Thu, Feb 18, 2021 at 10:57 PM Mark Gray wrote: > > On 18/02/2021 17:21, Numan Siddique wrote: > > On Thu, Feb 18, 2021 at 9:08 PM Mark Gray wrote: > >> > >> On 18/02/2021 14:30, num...@ovn.org wrote: > >>> From: Numan Siddique > >>> > >>> When a Gateway router is configured with a load balancer > >>> and it is also configured with options:lb_force_snat_ip=, > >>> OVN after load balancing the destination IP to one of the > >>> backend also does a NAT on the source ip with the > >>> lb_force_snat_ip if the packet is destined to a load balancer > >>> VIP. > >>> > >>> There is a problem with the snat of source ip to 'lb_force_snat_ip' > >>> in one particular usecase. When the packet enters the Gateway router > >>> from a provider logical switch destined to the load balancer VIP, > >>> then it is first load balanced to one of the backend and then > >>> the source ip is snatted to 'lb_force_snat_ip'. If the chosen > >>> backend is reachable via the provider logical switch, then the > >>> packet is hairpinned back and it may hit the wire with > >>> the source ip 'lb_force_snat_ip'. If 'lb_force_snat_ip' happens > >>> to be an OVN internal IP then the packet may be dropped. > >>> > >>> This patch addresses this issue by providing the option to > >>> set the option - 'lb_force_snat_ip=router_ip'. If 'router_ip' > >>> is set, then OVN will snat the load balanced packet to the > >>> router ip of the logical router port which is chosen as 'outport' > >>> in lr_in_ip_routing stage. > >>> > >>> Example. > >>> > >>> If the gateway router is > >>> > >>> ovn-nbctl show lr0 > >>> router 68f20092-5563-44b8-9ccb-b11de3e3a66c (lr0) > >>> port lr0-sw0 > >>> mac: "00:00:00:00:ff:01" > >>> networks: ["10.0.0.1/24"] > >>> port lr0-public > >>> mac: "00:00:20:20:12:13" > >>> networks: ["172.168.0.100/24"] > >>> > >>> Then the below logical flows are added if 'lb_force_snat_ip' > >>> is configured to 'router_ip'. > >>> > >>> table=1 (lr_out_snat), priority=110 > >>>match=(flags.force_snat_for_lb == 1 && ip4 && outport == "lr0-public"), > >>>action=(ct_snat(172.168.0.100);) > >>> > >>> table=1 (lr_out_snat), priority=110 > >>>match=(flags.force_snat_for_lb == 1 && ip4 && outport == "lr0-sw0") > >>>action=(ct_snat(10.0.0.1);) > >>> > >>> For the above described scenario, the packet will have source ip as > >>> 172.168.0.100 which belongs to the provider logical switch CIDR. > >>> > >>> Reported-by: Tim Rozet > >>> Signed-off-by: Numan Siddique > >>> --- > >>> > >>> v1 -> v2 > >>> --- > >>> * Addressed review comments from Mark Gray. > >>> > >>> northd/ovn-northd.8.xml | 35 > >>> northd/ovn-northd.c | 93 + > >>> ovn-nb.xml | 33 ++- > >>> tests/ovn-northd.at | 79 ++ > >>> 4 files changed, 222 insertions(+), 18 deletions(-) > >>> > >>> diff --git a/northd/ovn-northd.8.xml b/northd/ovn-northd.8.xml > >>> index 2f8b4e8c30..1d8f5edee1 100644 > >>> --- a/northd/ovn-northd.8.xml > >>> +++ b/northd/ovn-northd.8.xml > >>> @@ -3654,6 +3654,32 @@ nd_ns { > >>>flags.force_snat_for_dnat == 1 ip with > >>> an > >>>action ct_snat(B);. > >>> > >>> + > >>> + > >>> + > >>> + > >>> + If the Gateway router in the OVN Northbound database has been > >>> + configured to force SNAT a packet (that has been previously > >>> + load-balanced) using router IP (i.e >>> + table="Logical_Router"/>:lb_force_snat_ip=router_ip), then for > >>> + each logical router port P attached to the Gateway > >>> + router, a priority-110 flow matches > >>> + flags.force_snat_for_lb == 1 outport == > >>> P > >>> + with an action ct_snat(R); > >>> + where R is the IP configured on the router port. > >>> + If R is an IPv4 address then the match will also > >>> + include ip4 and if it is an IPv6 address, then the > >>> + match will also include ip6. > >>> + > >>> + > >>> + > >>> + If the logical router port P is configured with > >>> multiple > >>> + IPv4 and multiple IPv6 addresses, only the first IPv4 and > >>> first IPv6 > >>> + address is considered. > >>> + > >>> + > >>> + > >>> + > >>> > >>>If the Gateway router in the OVN Northbound database has been > >>>configured to force SNAT a packet (that has been previously > >>> @@ -3661,6 +3687,9 @@ nd_ns { > >>>flags.force_snat_for_lb == 1 ip with an > >>>action ct_snat(B);. > >>> > >>> + > >>> + > >>> + > >>> > >>>For each configuration in the OVN Northbound database, that > >>> asks > >>>to change the source IP address of a packet from an IP address > >>> of > >>> @@ -3674,14 +3703,18 @@
Re: [ovs-dev] [PATCH ovn branch-20.06 00/15] Backport rollup
On Thu, Feb 18, 2021 at 10:34 AM Dumitru Ceara wrote: > > On 2/18/21 9:09 AM, Frode Nordahl wrote: > > Hello all, > > Hi Frode, > > Many thanks for this! You're very welcome, thank you for all the bits! > > > > In Ubuntu we have backported a set of fixes to our OVN 20.06 and OVN > > 20.03 packages. In preparing for new point releases for OVN 20.06 > > and OVN 20.03, we would very much like to add these patches to the > > upstream branches. > > > > The issues solved for OVN 20.06 with these patches are: > > > >* Fix for upgrading database schema of clustered databases on package > > upgrade (LP: #1907081)[0] > >* Fixes for predictable resolution for conflicting flow actions. > > (LP: #1906922)[1] > > You might want to wait a bit with releasing new packages and include > more patches (some are not merged in upstream master yet) that fix > crashes due some of the ofctrl changes: > > https://github.com/ovn-org/ovn/commit/858d1dd716db1a1e664a7c1737fd34f04fcbda5e > (in upstream master and branch20.12) > > http://patchwork.ozlabs.org/project/ovn/patch/1613490806-11143-1-git-send-email-dce...@redhat.com/ > (I'll be submitting a v2 today). Thank you for bringing those to my attention, we'll monitor those closely. We have had this code running in the wild in select deployments for months without any issues so far, the updated packages have also been in our proposed pockets for an extended period before being shipped today. So while we really should get these fixes in as soon as possible, luckily it does not appear to happen too often in the wild. I'll work towards getting these backported too so that we can consume them from a point release update. -- Frode Nordahl > Regards, > Dumitru > ___ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev
Re: [ovs-dev] [PATCH ovn v2] northd: Provide the Gateway router option 'lb_force_snat_ip' to take router port ips.
On 18/02/2021 17:21, Numan Siddique wrote: > On Thu, Feb 18, 2021 at 9:08 PM Mark Gray wrote: >> >> On 18/02/2021 14:30, num...@ovn.org wrote: >>> From: Numan Siddique >>> >>> When a Gateway router is configured with a load balancer >>> and it is also configured with options:lb_force_snat_ip=, >>> OVN after load balancing the destination IP to one of the >>> backend also does a NAT on the source ip with the >>> lb_force_snat_ip if the packet is destined to a load balancer >>> VIP. >>> >>> There is a problem with the snat of source ip to 'lb_force_snat_ip' >>> in one particular usecase. When the packet enters the Gateway router >>> from a provider logical switch destined to the load balancer VIP, >>> then it is first load balanced to one of the backend and then >>> the source ip is snatted to 'lb_force_snat_ip'. If the chosen >>> backend is reachable via the provider logical switch, then the >>> packet is hairpinned back and it may hit the wire with >>> the source ip 'lb_force_snat_ip'. If 'lb_force_snat_ip' happens >>> to be an OVN internal IP then the packet may be dropped. >>> >>> This patch addresses this issue by providing the option to >>> set the option - 'lb_force_snat_ip=router_ip'. If 'router_ip' >>> is set, then OVN will snat the load balanced packet to the >>> router ip of the logical router port which is chosen as 'outport' >>> in lr_in_ip_routing stage. >>> >>> Example. >>> >>> If the gateway router is >>> >>> ovn-nbctl show lr0 >>> router 68f20092-5563-44b8-9ccb-b11de3e3a66c (lr0) >>> port lr0-sw0 >>> mac: "00:00:00:00:ff:01" >>> networks: ["10.0.0.1/24"] >>> port lr0-public >>> mac: "00:00:20:20:12:13" >>> networks: ["172.168.0.100/24"] >>> >>> Then the below logical flows are added if 'lb_force_snat_ip' >>> is configured to 'router_ip'. >>> >>> table=1 (lr_out_snat), priority=110 >>>match=(flags.force_snat_for_lb == 1 && ip4 && outport == "lr0-public"), >>>action=(ct_snat(172.168.0.100);) >>> >>> table=1 (lr_out_snat), priority=110 >>>match=(flags.force_snat_for_lb == 1 && ip4 && outport == "lr0-sw0") >>>action=(ct_snat(10.0.0.1);) >>> >>> For the above described scenario, the packet will have source ip as >>> 172.168.0.100 which belongs to the provider logical switch CIDR. >>> >>> Reported-by: Tim Rozet >>> Signed-off-by: Numan Siddique >>> --- >>> >>> v1 -> v2 >>> --- >>> * Addressed review comments from Mark Gray. >>> >>> northd/ovn-northd.8.xml | 35 >>> northd/ovn-northd.c | 93 + >>> ovn-nb.xml | 33 ++- >>> tests/ovn-northd.at | 79 ++ >>> 4 files changed, 222 insertions(+), 18 deletions(-) >>> >>> diff --git a/northd/ovn-northd.8.xml b/northd/ovn-northd.8.xml >>> index 2f8b4e8c30..1d8f5edee1 100644 >>> --- a/northd/ovn-northd.8.xml >>> +++ b/northd/ovn-northd.8.xml >>> @@ -3654,6 +3654,32 @@ nd_ns { >>>flags.force_snat_for_dnat == 1 ip with an >>>action ct_snat(B);. >>> >>> + >>> + >>> + >>> + >>> + If the Gateway router in the OVN Northbound database has been >>> + configured to force SNAT a packet (that has been previously >>> + load-balanced) using router IP (i.e >> + table="Logical_Router"/>:lb_force_snat_ip=router_ip), then for >>> + each logical router port P attached to the Gateway >>> + router, a priority-110 flow matches >>> + flags.force_snat_for_lb == 1 outport == >>> P >>> + with an action ct_snat(R); >>> + where R is the IP configured on the router port. >>> + If R is an IPv4 address then the match will also >>> + include ip4 and if it is an IPv6 address, then the >>> + match will also include ip6. >>> + >>> + >>> + >>> + If the logical router port P is configured with >>> multiple >>> + IPv4 and multiple IPv6 addresses, only the first IPv4 and first >>> IPv6 >>> + address is considered. >>> + >>> + >>> + >>> + >>> >>>If the Gateway router in the OVN Northbound database has been >>>configured to force SNAT a packet (that has been previously >>> @@ -3661,6 +3687,9 @@ nd_ns { >>>flags.force_snat_for_lb == 1 ip with an >>>action ct_snat(B);. >>> >>> + >>> + >>> + >>> >>>For each configuration in the OVN Northbound database, that asks >>>to change the source IP address of a packet from an IP address of >>> @@ -3674,14 +3703,18 @@ nd_ns { >>>options, then the action would be ip4/6.src= >>>(B). >>> >>> + >>> >>> + >>> >>>If the NAT rule has allowed_ext_ips configured, then >>>there is an additional match ip4.dst == >>> allowed_ext_ips >>>. Similarly, for
Re: [ovs-dev] [PATCH ovn] northd: Provide the Gateway router option 'lb_force_snat_ip' to take router port ips.
On Thu, Feb 18, 2021 at 9:15 PM Mark Gray wrote: > > On 18/02/2021 14:30, Numan Siddique wrote: > > On Wed, Feb 17, 2021 at 7:37 PM Mark Gray wrote: > >> > >> Thanks Numan, some suggestions below! > > > > Hi Mark G, > > > > Thanks for the review. > > > > PSB for a few comments. > > > >> > >> On 09/02/2021 18:44, num...@ovn.org wrote: > >>> From: Numan Siddique > >>> > >>> When a Gateway router is configured with a load balancer > >>> and it is also configured with options:lb_force_snat_ip=, > >>> OVN after load balancing the destination IP to one of the > >>> backend also does a NAT on the source ip with the > >>> lb_force_snat_ip if the packet is destined to a load balancer > >>> VIP. > >>> > >>> There is a problem with the snat of source ip to 'lb_force_snat_ip' > >>> in one particular usecase. When the packet enters the Gateway router > >>> from a provider logical switch destined to the load balancer VIP, > >>> then it is first load balanced to one of the backend and then > >>> the source ip is snatted to 'lb_force_snat_ip'. If the chosen > >>> backend is reachable via the provider logical switch, then the > >>> packet is hairpinned back and it may hit the wire with > >>> the source ip 'lb_force_snat_ip'. If 'lb_force_snat_ip' happens > >>> to be an OVN internal IP then the packet may be dropped. > >>> > >>> This patch addresses this issue by providing the option to > >>> set the option - 'lb_force_snat_ip=router_ip'. If 'router_ip' > >>> is set, then OVN will snat the load balanced packet to the > >>> router ip of the logical router port which chosen as 'outport' > >>> in lr_in_ip_routing stage. > >> > >> It almost feels like this should be the default behaviour? > > > > > > Can you please elaborate more ? You mean ideally CMS should set > > - router_ip ? > > I was thinking that it could just be lb_force_snat_ip=true (default to > remote_ip)? You mean 'router_ip' ? If it is 'true' then, IMHO, it is not clear with what IP to snat with. Since lb_force_snat_ip can take other IP addresses (which is the present case), I am not sure if mixing bool/string would be clear enough for the user. Let me know if you think it is obvious that it will be router ip if set to true. Thanks Numan > > > > > >>> > >>> Example. > >>> > >>> If the gateway router is > >>> > >>> ovn-nbctl show lr0 > >>> router 68f20092-5563-44b8-9ccb-b11de3e3a66c (lr0) > >>> port lr0-sw0 > >>> mac: "00:00:00:00:ff:01" > >>> networks: ["10.0.0.1/24"] > >>> port lr0-public > >>> mac: "00:00:20:20:12:13" > >>> networks: ["172.168.0.100/24"] > >>> > >>> Then the below logical flows are added if 'lb_force_snat_ip' > >>> is configured to 'router_ip'. > >>> > >>> table=1 (lr_out_snat), priority=110 > >>>match=(flags.force_snat_for_lb == 1 && ip4 && outport == "lr0-public"), > >>>action=(ct_snat(172.168.0.100);) > >>> > >>> table=1 (lr_out_snat), priority=110 > >>>match=(flags.force_snat_for_lb == 1 && ip4 && outport == "lr0-sw0") > >>>action=(ct_snat(10.0.0.1);) > >>> > >>> For the above described scenario, the packet will have source ip as > >>> 172.168.0.100 which belongs to the provider logical switch CIDR. > >>> > >>> Reported-by: Tim Rozet > >>> Signed-off-by: Numan Siddique > >>> --- > >>> northd/ovn-northd.8.xml | 35 ++ > >>> northd/ovn-northd.c | 66 -- > >>> tests/ovn-northd.at | 79 + > >>> 3 files changed, 177 insertions(+), 3 deletions(-) > >>> > >>> diff --git a/northd/ovn-northd.8.xml b/northd/ovn-northd.8.xml > >>> index 70065a36d9..27b28aff93 100644 > >>> --- a/northd/ovn-northd.8.xml > >>> +++ b/northd/ovn-northd.8.xml > >> > >> Should 'ovn-nb.xml' also be updated? > > > > Great catch. I totally missed it. > > > >> > >>> @@ -3653,6 +3653,32 @@ nd_ns { > >>>flags.force_snat_for_dnat == 1 ip with > >>> an > >>>action ct_snat(B);. > >>> > >>> + > >>> + > >>> + > >>> + > >>> + If the Gateway router in the OVN Northbound database has been > >>> + configured to force SNAT a packet (that has been previously > >>> + load-balanced) using router IP (i.e >>> + table="Logical_Router"/>:lb_force_snat_ip=router_ip), then for > >>> + each logical router port P attached to the Gateway > >>> + router, a priority-110 flow matches > >>> + flags.force_snat_for_lb == 1 outport == > >>> P > >>> + with an action ct_snat(R); > >>> + where R is the router port IP configured. > >> > >> maybe rephrase to "is the IP configured on the router port." > > > > Ack. done > > > >> > >>> + If R is an IPv4 address then the match will also > >>> + include ip4 and if it is an IPv6 address, then the > >>> + match will also include ip6. > >>> + > >>> + > >>> + > >>> + If the logical router port P is configured with >
Re: [ovs-dev] [PATCH ovn v2] northd: Provide the Gateway router option 'lb_force_snat_ip' to take router port ips.
On Thu, Feb 18, 2021 at 9:08 PM Mark Gray wrote: > > On 18/02/2021 14:30, num...@ovn.org wrote: > > From: Numan Siddique > > > > When a Gateway router is configured with a load balancer > > and it is also configured with options:lb_force_snat_ip=, > > OVN after load balancing the destination IP to one of the > > backend also does a NAT on the source ip with the > > lb_force_snat_ip if the packet is destined to a load balancer > > VIP. > > > > There is a problem with the snat of source ip to 'lb_force_snat_ip' > > in one particular usecase. When the packet enters the Gateway router > > from a provider logical switch destined to the load balancer VIP, > > then it is first load balanced to one of the backend and then > > the source ip is snatted to 'lb_force_snat_ip'. If the chosen > > backend is reachable via the provider logical switch, then the > > packet is hairpinned back and it may hit the wire with > > the source ip 'lb_force_snat_ip'. If 'lb_force_snat_ip' happens > > to be an OVN internal IP then the packet may be dropped. > > > > This patch addresses this issue by providing the option to > > set the option - 'lb_force_snat_ip=router_ip'. If 'router_ip' > > is set, then OVN will snat the load balanced packet to the > > router ip of the logical router port which is chosen as 'outport' > > in lr_in_ip_routing stage. > > > > Example. > > > > If the gateway router is > > > > ovn-nbctl show lr0 > > router 68f20092-5563-44b8-9ccb-b11de3e3a66c (lr0) > > port lr0-sw0 > > mac: "00:00:00:00:ff:01" > > networks: ["10.0.0.1/24"] > > port lr0-public > > mac: "00:00:20:20:12:13" > > networks: ["172.168.0.100/24"] > > > > Then the below logical flows are added if 'lb_force_snat_ip' > > is configured to 'router_ip'. > > > > table=1 (lr_out_snat), priority=110 > >match=(flags.force_snat_for_lb == 1 && ip4 && outport == "lr0-public"), > >action=(ct_snat(172.168.0.100);) > > > > table=1 (lr_out_snat), priority=110 > >match=(flags.force_snat_for_lb == 1 && ip4 && outport == "lr0-sw0") > >action=(ct_snat(10.0.0.1);) > > > > For the above described scenario, the packet will have source ip as > > 172.168.0.100 which belongs to the provider logical switch CIDR. > > > > Reported-by: Tim Rozet > > Signed-off-by: Numan Siddique > > --- > > > > v1 -> v2 > > --- > > * Addressed review comments from Mark Gray. > > > > northd/ovn-northd.8.xml | 35 > > northd/ovn-northd.c | 93 + > > ovn-nb.xml | 33 ++- > > tests/ovn-northd.at | 79 ++ > > 4 files changed, 222 insertions(+), 18 deletions(-) > > > > diff --git a/northd/ovn-northd.8.xml b/northd/ovn-northd.8.xml > > index 2f8b4e8c30..1d8f5edee1 100644 > > --- a/northd/ovn-northd.8.xml > > +++ b/northd/ovn-northd.8.xml > > @@ -3654,6 +3654,32 @@ nd_ns { > >flags.force_snat_for_dnat == 1 ip with an > >action ct_snat(B);. > > > > + > > + > > + > > + > > + If the Gateway router in the OVN Northbound database has been > > + configured to force SNAT a packet (that has been previously > > + load-balanced) using router IP (i.e > + table="Logical_Router"/>:lb_force_snat_ip=router_ip), then for > > + each logical router port P attached to the Gateway > > + router, a priority-110 flow matches > > + flags.force_snat_for_lb == 1 outport == > > P > > + with an action ct_snat(R); > > + where R is the IP configured on the router port. > > + If R is an IPv4 address then the match will also > > + include ip4 and if it is an IPv6 address, then the > > + match will also include ip6. > > + > > + > > + > > + If the logical router port P is configured with > > multiple > > + IPv4 and multiple IPv6 addresses, only the first IPv4 and first > > IPv6 > > + address is considered. > > + > > + > > + > > + > > > >If the Gateway router in the OVN Northbound database has been > >configured to force SNAT a packet (that has been previously > > @@ -3661,6 +3687,9 @@ nd_ns { > >flags.force_snat_for_lb == 1 ip with an > >action ct_snat(B);. > > > > + > > + > > + > > > >For each configuration in the OVN Northbound database, that asks > >to change the source IP address of a packet from an IP address of > > @@ -3674,14 +3703,18 @@ nd_ns { > >options, then the action would be ip4/6.src= > >(B). > > > > + > > > > + > > > >If the NAT rule has allowed_ext_ips configured, then > >there is an additional match ip4.dst == > > allowed_ext_ips > >. Similarly, for IPV6, match would be ip6.dst > > == > >
Re: [ovs-dev] [PATCHv2] Documentation: Fix DPDK qos example.
On 18 Feb 2021, at 16:24, William Tu wrote: > Fix the example use case based on the decription. > EIR and CIR are measured in bytes/sec and considered 64-byte > IP packets size withtout 14-byte Ethernet header. > So fix the 1000pps example by: (64 - 14) * 1000 = 50,000 > If the frame includes 4-byte FCS header, then it's > (64 - 14 - 4) * 1000 = 46,000 > > Fixes: e61bdffc2a98 ("netdev-dpdk: Add new DPDK RFC 4115 egress policer") > Signed-off-by: William Tu Looks good, thanks for taking the time to fix this! Acked-by: Eelco Chaudron ___ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev
[ovs-dev] [PATCH ovn] binding: Fix potential crash when binding_seqno_run is skipped.
The prerequisite for binding_seqno_run() is that it has to be called while there are valid SB and OVS transactions available. ovn-controller's main() function respects that but that means that there is a small window (when OVS transaction is still in progress) when port bindings might be deleted from the Southbound. When binding_seqno_run() was finally called, it was asserting that the Port_bindings to still exist. This check is too restrictive and the solution is to just skip bindings that have become partial (i.e., no SB.Port_Binding or no OVS.Interface). Fixes: 4d3cb42b076b ("binding: Set Logical_Switch_Port.up when all OVS flows are installed.") Reported-at: https://bugzilla.redhat.com/1930030 Reported-by: Numan Siddique Signed-off-by: Dumitru Ceara --- Note: the window to reproduce the issue is quite narrow so I didn't manage to write a test that would hit the issue consistently. --- controller/binding.c | 14 -- 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/controller/binding.c b/controller/binding.c index efaa109..2b19fd0 100644 --- a/controller/binding.c +++ b/controller/binding.c @@ -2498,13 +2498,15 @@ binding_seqno_run(struct shash *local_bindings) SSET_FOR_EACH_SAFE (iface_id, iface_id_next, _iface_bound_set) { struct shash_node *lb_node = shash_find(local_bindings, iface_id); -if (lb_node) { -/* This is a newly bound interface, make sure we reset the - * Port_Binding 'up' field and the OVS Interface 'external-id'. - */ -struct local_binding *lb = lb_node->data; +struct local_binding *lb = lb_node ? lb_node->data : NULL; -ovs_assert(lb->pb && lb->iface); +/* Make sure the binding is still complete, i.e., both SB port_binding + * and OVS interface still exist. + * + * If so, then this is a newly bound interface, make sure we reset the + * Port_Binding 'up' field and the OVS Interface 'external-id'. + */ +if (lb && lb->pb && lb->iface) { new_ifaces = true; if (smap_get(>iface->external_ids, OVN_INSTALLED_EXT_ID)) { -- 1.8.3.1 ___ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev
Re: [ovs-dev] [PATCH V2 00/14] Netdev vxlan-decap offload
<...> > Sending to Marko. As he wasn't subscribed to ovs-dev then. > <...> > > VXLAN decap in OVS-DPDK configuration consists of two flows: > > F1: in_port(ens1f0),eth(),ipv4(),udp(), actions:tnl_pop(vxlan_sys_4789) > > F2: tunnel(),in_port(vxlan_sys_4789),eth(),ipv4(), actions:ens1f0_0 > > > > F1 is a classification flow. It has outer headers matches and it classifies > > the > > packet as a VXLAN packet, and using tnl_pop action the packet continues > > processing in F2. > > F2 is a flow that has matches on tunnel metadata as well as on the inner > > packet headers (as any other flow). > > <...> Hi Eli, Hi, After testing the patchset it seems after the tenth patch I start seeing a drop in the scatter performance around ~4% decrease across all packet sizes tested(112,256,512,1518) Burst measurement see a decrease also but not as much as the scatter does. Patch10 fff1f9168 netdev-offload-dpdk: Support tunnel pop action The test used for this is a 32 virito-user ports with 1Millions flows. Traffic @ Phy NIC Rx: Ether()/IP()/UDP()/VXLAN()/Ether()/IP() Burst: on the outer ip we do a burst of 32 packets with same ip then switch for next 32 and so on Scatter: for scatter we do incrementally for 32 And on the inner packet we have a total of 1048576 flows I can send on a diagram directly just restricted with html here to send the diagram here of the test setup Thanks Marko K ___ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev
[ovs-dev] [PATCH ovn v3] ovn-controller: Split logical flow and phsyical flow processing.
From: Numan Siddique Presently, the 'flow_output' engine node recomputes physical flows by calling physical_run() in the 'physical_flow_changes' handler.in some scenarios. Because of this, an engine run can do a full recompute of physical flows but not full recompute of logical flows. Although this works now, it is problematic as the same desired flow table is used for both physical and logical flows. This patch now separates the handling of logical flows and physical flows. Two separate engine nodes are added - lflow_output and pflow_output with their own flow tables and these two nodes are now inputs to the main engine node - flow_output. CC: Han Zhou Signed-off-by: Numan Siddique --- v2 -> v3 - * Rebased to resolve conflicts. v1 -> v2 - * Rebased to resolve conflicts. TODO.rst| 6 + controller/lflow.c | 14 +- controller/lflow.h | 6 +- controller/ofctrl.c | 215 +++ controller/ofctrl.h | 37 +- controller/ovn-controller.c | 691 ++-- controller/physical.c | 28 +- controller/physical.h | 12 +- 8 files changed, 543 insertions(+), 466 deletions(-) diff --git a/TODO.rst b/TODO.rst index c15815539f..910531e7e3 100644 --- a/TODO.rst +++ b/TODO.rst @@ -160,3 +160,9 @@ OVN To-do List to find a way of determining if routing has already been executed (on a different hypervisor) for the IP multicast packet being processed locally in the router pipeline. + +* ovn-controller Incremental processing + + * physical.c has a global simap -localvif_to_ofport which stores the +local OVS interfaces and the ofport numbers. Move this to the engine data +of the engine data node - ed_type_pflow_output. diff --git a/controller/lflow.c b/controller/lflow.c index 4bdd953bee..8b1e4770ba 100644 --- a/controller/lflow.c +++ b/controller/lflow.c @@ -966,7 +966,7 @@ static void consider_neighbor_flow(struct ovsdb_idl_index *sbrec_port_binding_by_name, const struct hmap *local_datapaths, const struct sbrec_mac_binding *b, - struct ovn_desired_flow_table *flow_table) + struct ovn_flow_table *flow_table) { const struct sbrec_port_binding *pb = lport_lookup_by_name(sbrec_port_binding_by_name, b->logical_port); @@ -1046,7 +1046,7 @@ static void add_neighbor_flows(struct ovsdb_idl_index *sbrec_port_binding_by_name, const struct sbrec_mac_binding_table *mac_binding_table, const struct hmap *local_datapaths, - struct ovn_desired_flow_table *flow_table) + struct ovn_flow_table *flow_table) { const struct sbrec_mac_binding *b; SBREC_MAC_BINDING_TABLE_FOR_EACH (b, mac_binding_table) { @@ -1232,7 +1232,7 @@ add_lb_vip_hairpin_flows(struct ovn_controller_lb *lb, struct ovn_lb_vip *lb_vip, struct ovn_lb_backend *lb_backend, uint8_t lb_proto, - struct ovn_desired_flow_table *flow_table) + struct ovn_flow_table *flow_table) { uint64_t stub[1024 / 8]; struct ofpbuf ofpacts = OFPBUF_STUB_INITIALIZER(stub); @@ -1301,7 +1301,7 @@ static void add_lb_ct_snat_vip_flows(struct ovn_controller_lb *lb, struct ovn_lb_vip *lb_vip, uint8_t lb_proto, - struct ovn_desired_flow_table *flow_table) + struct ovn_flow_table *flow_table) { uint64_t stub[1024 / 8]; struct ofpbuf ofpacts = OFPBUF_STUB_INITIALIZER(stub); @@ -1369,7 +1369,7 @@ add_lb_ct_snat_vip_flows(struct ovn_controller_lb *lb, static void consider_lb_hairpin_flows(const struct sbrec_load_balancer *sbrec_lb, const struct hmap *local_datapaths, - struct ovn_desired_flow_table *flow_table) + struct ovn_flow_table *flow_table) { /* Check if we need to add flows or not. If there is one datapath * in the local_datapaths, it means all the datapaths of the lb @@ -1417,7 +1417,7 @@ consider_lb_hairpin_flows(const struct sbrec_load_balancer *sbrec_lb, static void add_lb_hairpin_flows(const struct sbrec_load_balancer_table *lb_table, const struct hmap *local_datapaths, - struct ovn_desired_flow_table *flow_table) + struct ovn_flow_table *flow_table) { const struct sbrec_load_balancer *lb; SBREC_LOAD_BALANCER_TABLE_FOR_EACH (lb, lb_table) { @@ -1431,7 +1431,7 @@ lflow_handle_changed_neighbors( struct ovsdb_idl_index *sbrec_port_binding_by_name, const struct sbrec_mac_binding_table *mac_binding_table, const struct hmap *local_datapaths, -struct ovn_desired_flow_table *flow_table) +struct ovn_flow_table *flow_table) { const
Re: [ovs-dev] [PATCH ovn] northd: Provide the Gateway router option 'lb_force_snat_ip' to take router port ips.
On 18/02/2021 14:30, Numan Siddique wrote: > On Wed, Feb 17, 2021 at 7:37 PM Mark Gray wrote: >> >> Thanks Numan, some suggestions below! > > Hi Mark G, > > Thanks for the review. > > PSB for a few comments. > >> >> On 09/02/2021 18:44, num...@ovn.org wrote: >>> From: Numan Siddique >>> >>> When a Gateway router is configured with a load balancer >>> and it is also configured with options:lb_force_snat_ip=, >>> OVN after load balancing the destination IP to one of the >>> backend also does a NAT on the source ip with the >>> lb_force_snat_ip if the packet is destined to a load balancer >>> VIP. >>> >>> There is a problem with the snat of source ip to 'lb_force_snat_ip' >>> in one particular usecase. When the packet enters the Gateway router >>> from a provider logical switch destined to the load balancer VIP, >>> then it is first load balanced to one of the backend and then >>> the source ip is snatted to 'lb_force_snat_ip'. If the chosen >>> backend is reachable via the provider logical switch, then the >>> packet is hairpinned back and it may hit the wire with >>> the source ip 'lb_force_snat_ip'. If 'lb_force_snat_ip' happens >>> to be an OVN internal IP then the packet may be dropped. >>> >>> This patch addresses this issue by providing the option to >>> set the option - 'lb_force_snat_ip=router_ip'. If 'router_ip' >>> is set, then OVN will snat the load balanced packet to the >>> router ip of the logical router port which chosen as 'outport' >>> in lr_in_ip_routing stage. >> >> It almost feels like this should be the default behaviour? > > > Can you please elaborate more ? You mean ideally CMS should set > - router_ip ? I was thinking that it could just be lb_force_snat_ip=true (default to remote_ip)? > > >>> >>> Example. >>> >>> If the gateway router is >>> >>> ovn-nbctl show lr0 >>> router 68f20092-5563-44b8-9ccb-b11de3e3a66c (lr0) >>> port lr0-sw0 >>> mac: "00:00:00:00:ff:01" >>> networks: ["10.0.0.1/24"] >>> port lr0-public >>> mac: "00:00:20:20:12:13" >>> networks: ["172.168.0.100/24"] >>> >>> Then the below logical flows are added if 'lb_force_snat_ip' >>> is configured to 'router_ip'. >>> >>> table=1 (lr_out_snat), priority=110 >>>match=(flags.force_snat_for_lb == 1 && ip4 && outport == "lr0-public"), >>>action=(ct_snat(172.168.0.100);) >>> >>> table=1 (lr_out_snat), priority=110 >>>match=(flags.force_snat_for_lb == 1 && ip4 && outport == "lr0-sw0") >>>action=(ct_snat(10.0.0.1);) >>> >>> For the above described scenario, the packet will have source ip as >>> 172.168.0.100 which belongs to the provider logical switch CIDR. >>> >>> Reported-by: Tim Rozet >>> Signed-off-by: Numan Siddique >>> --- >>> northd/ovn-northd.8.xml | 35 ++ >>> northd/ovn-northd.c | 66 -- >>> tests/ovn-northd.at | 79 + >>> 3 files changed, 177 insertions(+), 3 deletions(-) >>> >>> diff --git a/northd/ovn-northd.8.xml b/northd/ovn-northd.8.xml >>> index 70065a36d9..27b28aff93 100644 >>> --- a/northd/ovn-northd.8.xml >>> +++ b/northd/ovn-northd.8.xml >> >> Should 'ovn-nb.xml' also be updated? > > Great catch. I totally missed it. > >> >>> @@ -3653,6 +3653,32 @@ nd_ns { >>>flags.force_snat_for_dnat == 1 ip with an >>>action ct_snat(B);. >>> >>> + >>> + >>> + >>> + >>> + If the Gateway router in the OVN Northbound database has been >>> + configured to force SNAT a packet (that has been previously >>> + load-balanced) using router IP (i.e >> + table="Logical_Router"/>:lb_force_snat_ip=router_ip), then for >>> + each logical router port P attached to the Gateway >>> + router, a priority-110 flow matches >>> + flags.force_snat_for_lb == 1 outport == >>> P >>> + with an action ct_snat(R); >>> + where R is the router port IP configured. >> >> maybe rephrase to "is the IP configured on the router port." > > Ack. done > >> >>> + If R is an IPv4 address then the match will also >>> + include ip4 and if it is an IPv6 address, then the >>> + match will also include ip6. >>> + >>> + >>> + >>> + If the logical router port P is configured with >>> multiple >>> + IPv4 and multiple IPv6 addresses, only the first IPv4 and first >>> IPv6 >>> + address is considered. >> >> Should we log this condition? > > Ack. I have added the log for this in v2. > > >> >>> + >>> + >>> + >>> + >>> >>>If the Gateway router in the OVN Northbound database has been >>>configured to force SNAT a packet (that has been previously >>> @@ -3660,6 +3686,9 @@ nd_ns { >>>flags.force_snat_for_lb == 1 ip with an >>>action ct_snat(B);. >>> >>> + >>> + >>> + >>> >>>For
Re: [ovs-dev] [PATCH ovn v2] northd: Provide the Gateway router option 'lb_force_snat_ip' to take router port ips.
On 18/02/2021 14:30, num...@ovn.org wrote: > From: Numan Siddique > > When a Gateway router is configured with a load balancer > and it is also configured with options:lb_force_snat_ip=, > OVN after load balancing the destination IP to one of the > backend also does a NAT on the source ip with the > lb_force_snat_ip if the packet is destined to a load balancer > VIP. > > There is a problem with the snat of source ip to 'lb_force_snat_ip' > in one particular usecase. When the packet enters the Gateway router > from a provider logical switch destined to the load balancer VIP, > then it is first load balanced to one of the backend and then > the source ip is snatted to 'lb_force_snat_ip'. If the chosen > backend is reachable via the provider logical switch, then the > packet is hairpinned back and it may hit the wire with > the source ip 'lb_force_snat_ip'. If 'lb_force_snat_ip' happens > to be an OVN internal IP then the packet may be dropped. > > This patch addresses this issue by providing the option to > set the option - 'lb_force_snat_ip=router_ip'. If 'router_ip' > is set, then OVN will snat the load balanced packet to the > router ip of the logical router port which is chosen as 'outport' > in lr_in_ip_routing stage. > > Example. > > If the gateway router is > > ovn-nbctl show lr0 > router 68f20092-5563-44b8-9ccb-b11de3e3a66c (lr0) > port lr0-sw0 > mac: "00:00:00:00:ff:01" > networks: ["10.0.0.1/24"] > port lr0-public > mac: "00:00:20:20:12:13" > networks: ["172.168.0.100/24"] > > Then the below logical flows are added if 'lb_force_snat_ip' > is configured to 'router_ip'. > > table=1 (lr_out_snat), priority=110 >match=(flags.force_snat_for_lb == 1 && ip4 && outport == "lr0-public"), >action=(ct_snat(172.168.0.100);) > > table=1 (lr_out_snat), priority=110 >match=(flags.force_snat_for_lb == 1 && ip4 && outport == "lr0-sw0") >action=(ct_snat(10.0.0.1);) > > For the above described scenario, the packet will have source ip as > 172.168.0.100 which belongs to the provider logical switch CIDR. > > Reported-by: Tim Rozet > Signed-off-by: Numan Siddique > --- > > v1 -> v2 > --- > * Addressed review comments from Mark Gray. > > northd/ovn-northd.8.xml | 35 > northd/ovn-northd.c | 93 + > ovn-nb.xml | 33 ++- > tests/ovn-northd.at | 79 ++ > 4 files changed, 222 insertions(+), 18 deletions(-) > > diff --git a/northd/ovn-northd.8.xml b/northd/ovn-northd.8.xml > index 2f8b4e8c30..1d8f5edee1 100644 > --- a/northd/ovn-northd.8.xml > +++ b/northd/ovn-northd.8.xml > @@ -3654,6 +3654,32 @@ nd_ns { >flags.force_snat_for_dnat == 1 ip with an >action ct_snat(B);. > > + > + > + > + > + If the Gateway router in the OVN Northbound database has been > + configured to force SNAT a packet (that has been previously > + load-balanced) using router IP (i.e + table="Logical_Router"/>:lb_force_snat_ip=router_ip), then for > + each logical router port P attached to the Gateway > + router, a priority-110 flow matches > + flags.force_snat_for_lb == 1 outport == > P > + with an action ct_snat(R); > + where R is the IP configured on the router port. > + If R is an IPv4 address then the match will also > + include ip4 and if it is an IPv6 address, then the > + match will also include ip6. > + > + > + > + If the logical router port P is configured with multiple > + IPv4 and multiple IPv6 addresses, only the first IPv4 and first > IPv6 > + address is considered. > + > + > + > + > >If the Gateway router in the OVN Northbound database has been >configured to force SNAT a packet (that has been previously > @@ -3661,6 +3687,9 @@ nd_ns { >flags.force_snat_for_lb == 1 ip with an >action ct_snat(B);. > > + > + > + > >For each configuration in the OVN Northbound database, that asks >to change the source IP address of a packet from an IP address of > @@ -3674,14 +3703,18 @@ nd_ns { >options, then the action would be ip4/6.src= >(B). > > + > > + > >If the NAT rule has allowed_ext_ips configured, then >there is an additional match ip4.dst == allowed_ext_ips >. Similarly, for IPV6, match would be ip6.dst == >allowed_ext_ips. > > + > > + > >If the NAT rule has exempted_ext_ips set, then >there is an additional flow configured at the priority + 1 of > @@ -3690,7 +3723,9 @@ nd_ns { >. This flow is used to bypass the ct_snat action for a >
[ovs-dev] [PATCHv2] Documentation: Fix DPDK qos example.
Fix the example use case based on the decription. EIR and CIR are measured in bytes/sec and considered 64-byte IP packets size withtout 14-byte Ethernet header. So fix the 1000pps example by: (64 - 14) * 1000 = 50,000 If the frame includes 4-byte FCS header, then it's (64 - 14 - 4) * 1000 = 46,000 Fixes: e61bdffc2a98 ("netdev-dpdk: Add new DPDK RFC 4115 egress policer") Signed-off-by: William Tu --- Documentation/topics/dpdk/qos.rst | 14 -- vswitchd/vswitch.xml | 6 -- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/Documentation/topics/dpdk/qos.rst b/Documentation/topics/dpdk/qos.rst index 103495415a9c..a98ec672fcf5 100644 --- a/Documentation/topics/dpdk/qos.rst +++ b/Documentation/topics/dpdk/qos.rst @@ -69,22 +69,24 @@ to prioritize certain traffic over others at a port level. For example, the following configuration will limit the traffic rate at a port level to a maximum of 2000 packets a second (64 bytes IPv4 packets). -100pps as CIR (Committed Information Rate) and 1000pps as EIR (Excess -Information Rate). High priority traffic is routed to queue 10, which marks +1000pps as CIR (Committed Information Rate) and 1000pps as EIR (Excess +Information Rate). CIR and EIR are measured in bytes without Ethernet header. +As a result, 1000pps means (64-byte - 14-byte) * 1000 = 50,000 in the +configuration below. High priority traffic is routed to queue 10, which marks all traffic as CIR, i.e. Green. All low priority traffic, queue 20, is marked as EIR, i.e. Yellow:: $ ovs-vsctl --timeout=5 set port dpdk1 qos=@myqos -- \ --id=@myqos create qos type=trtcm-policer \ -other-config:cir=52000 other-config:cbs=2048 \ -other-config:eir=52000 other-config:ebs=2048 \ +other-config:cir=5 other-config:cbs=2048 \ +other-config:eir=5 other-config:ebs=2048 \ queues:10=@dpdk1Q10 queues:20=@dpdk1Q20 -- \ --id=@dpdk1Q10 create queue \ - other-config:cir=4160 other-config:cbs=2048 \ + other-config:cir=10 other-config:cbs=2048 \ other-config:eir=0 other-config:ebs=0 -- \ --id=@dpdk1Q20 create queue \ other-config:cir=0 other-config:cbs=0 \ - other-config:eir=4160 other-config:ebs=2048 \ + other-config:eir=5 other-config:ebs=2048 This configuration accomplishes that the high priority traffic has a guaranteed bandwidth egressing the ports at CIR (1000pps), but it can also diff --git a/vswitchd/vswitch.xml b/vswitchd/vswitch.xml index a2ad84edefa9..4597a215d936 100644 --- a/vswitchd/vswitch.xml +++ b/vswitchd/vswitch.xml @@ -4660,7 +4660,8 @@ ovs-vsctl add-port br0 p0 -- set Interface p0 type=patch options:peer=p1 \ packets per second the CIR would be set to to to 4600. This value can be broken into '1,000,000 x 46'. Where 1,000,000 is the policing rate for the number of packets per second and 46 represents the size -of the packet data for a 64 byte ip packet. +of the packet data for a 64 bytes IP packet without 14 bytes Ethernet +and 4 bytes FCS header. The Committed Burst Size (CBS) is measured in bytes and represents a @@ -4681,7 +4682,8 @@ ovs-vsctl add-port br0 p0 -- set Interface p0 type=patch options:peer=p1 \ packets per second the EIR would be set to to to 4600. This value can be broken into '1,000,000 x 46'. Where 1,000,000 is the policing rate for the number of packets per second and 46 represents the size -of the packet data for a 64 byte ip packet. +of the packet data for a 64 bytes IP packet without 14 bytes Ethernet +and 4 bytes FCS header. The Excess Burst Size (EBS) is measured in bytes and represents a -- 2.7.4 ___ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev
Re: [ovs-dev] [PATCH] Documentation: Fix DPDK qos example.
On Thu, Feb 18, 2021 at 6:55 AM Eelco Chaudron wrote: > > > > On 18 Feb 2021, at 15:40, William Tu wrote: > > > On Thu, Feb 18, 2021 at 1:23 AM Eelco Chaudron > > wrote: > >> > >> > >> > >> On 17 Feb 2021, at 18:41, William Tu wrote: > >> > > >> Information Rate). High priority traffic is routed to queue 10, > >> which marks > >> all traffic as CIR, i.e. Green. All low priority traffic, queue > >> 20, > >> is > >> marked as EIR, i.e. Yellow:: > >> > >> $ ovs-vsctl --timeout=5 set port dpdk1 qos=@myqos -- \ > >> --id=@myqos create qos type=trtcm-policer \ > >> -other-config:cir=52000 other-config:cbs=2048 \ > >> -other-config:eir=52000 other-config:ebs=2048 \ > > 52000 is fine as our documentation states cir, eir are in bytes per > second, minus the ethernet header. > So (64-12) * 1000 = 52000 > >>> > >>> How come it's not minus 14-byte ethernet header? > >> > >> You are right, it should be 14, miscounted the rte_ether_hdr > >> structure size :( > >> > > Thank you! > > at vswitchd/vswitch.xml, it uses "46", should I change it to "64- 14 = > > 50"? > > calculated by (pps x packet data size). For example assuming > > a user > > wishes to limit a stream consisting of 64 byte packets to 1 > > million > > packets per second the EIR would be set to to to 4600. > > This value > > can be broken into '1,000,000 x 46'. Where 1,000,000 is the > > policing > > rate for the number of packets per second and 46 represents > > the size > > of the packet data for a 64 byte ip packet. > > William > > Guess they take of the FCS also, so the packets they sent are 14 bytes > ethernet, + 46 bytes IP + 4 FCS. I see, thanks! > > In my tests I sent 64 byte packets, i.e. 14 bytes ethernet + 50 bytes > IP. > > Maybe we should clarify this in the text some how? > Sure, I will do it. William ___ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev
Re: [ovs-dev] [PATCH ovn v2] northd: Provide the Gateway router option 'lb_force_snat_ip' to take router port ips.
On Thu, Feb 18, 2021 at 8:31 PM 0-day Robot wrote: > > Bleep bloop. Greetings Numan Siddique, I am a robot and I have tried out > your patch. > Thanks for your contribution. > > I encountered some error that I wasn't expecting. See the details below. > > > checkpatch: > WARNING: Line is 94 characters long (recommended limit is 79) > WARNING: Line has trailing whitespace > #224 FILE: northd/ovn-northd.c:9001: > op->lrp_networks.ipv4_addrs[0].addr_s); > > WARNING: Line is 94 characters long (recommended limit is 79) > WARNING: Line has trailing whitespace > #249 FILE: northd/ovn-northd.c:9026: > op->lrp_networks.ipv6_addrs[0].addr_s); > > Lines checked: 399, Warnings: 4, Errors: 0 Sorry for these checkpatch warnings. Please ignore this during review. I'll address them. Thanks Numan > > > Please check this out. If you feel there has been an error, please email > acon...@redhat.com > > Thanks, > 0-day Robot > ___ > 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
Re: [ovs-dev] [PATCH ovn v2] northd: Provide the Gateway router option 'lb_force_snat_ip' to take router port ips.
Bleep bloop. Greetings Numan Siddique, I am a robot and I have tried out your patch. Thanks for your contribution. I encountered some error that I wasn't expecting. See the details below. checkpatch: WARNING: Line is 94 characters long (recommended limit is 79) WARNING: Line has trailing whitespace #224 FILE: northd/ovn-northd.c:9001: op->lrp_networks.ipv4_addrs[0].addr_s); WARNING: Line is 94 characters long (recommended limit is 79) WARNING: Line has trailing whitespace #249 FILE: northd/ovn-northd.c:9026: op->lrp_networks.ipv6_addrs[0].addr_s); Lines checked: 399, Warnings: 4, Errors: 0 Please check this out. If you feel there has been an error, please email acon...@redhat.com Thanks, 0-day Robot ___ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev
Re: [ovs-dev] [PATCH] Documentation: Fix DPDK qos example.
On 18 Feb 2021, at 15:40, William Tu wrote: On Thu, Feb 18, 2021 at 1:23 AM Eelco Chaudron wrote: On 17 Feb 2021, at 18:41, William Tu wrote: Information Rate). High priority traffic is routed to queue 10, which marks all traffic as CIR, i.e. Green. All low priority traffic, queue 20, is marked as EIR, i.e. Yellow:: $ ovs-vsctl --timeout=5 set port dpdk1 qos=@myqos -- \ --id=@myqos create qos type=trtcm-policer \ -other-config:cir=52000 other-config:cbs=2048 \ -other-config:eir=52000 other-config:ebs=2048 \ 52000 is fine as our documentation states cir, eir are in bytes per second, minus the ethernet header. So (64-12) * 1000 = 52000 How come it's not minus 14-byte ethernet header? You are right, it should be 14, miscounted the rte_ether_hdr structure size :( Thank you! at vswitchd/vswitch.xml, it uses "46", should I change it to "64- 14 = 50"? calculated by (pps x packet data size). For example assuming a user wishes to limit a stream consisting of 64 byte packets to 1 million packets per second the EIR would be set to to to 4600. This value can be broken into '1,000,000 x 46'. Where 1,000,000 is the policing rate for the number of packets per second and 46 represents the size of the packet data for a 64 byte ip packet. William Guess they take of the FCS also, so the packets they sent are 14 bytes ethernet, + 46 bytes IP + 4 FCS. In my tests I sent 64 byte packets, i.e. 14 bytes ethernet + 50 bytes IP. Maybe we should clarify this in the text some how? ___ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev
Re: [ovs-dev] [PATCH] Documentation: Fix DPDK qos example.
On Thu, Feb 18, 2021 at 1:23 AM Eelco Chaudron wrote: > > > > On 17 Feb 2021, at 18:41, William Tu wrote: > > >> > Information Rate). High priority traffic is routed to queue 10, > which marks > all traffic as CIR, i.e. Green. All low priority traffic, queue 20, > is > marked as EIR, i.e. Yellow:: > > $ ovs-vsctl --timeout=5 set port dpdk1 qos=@myqos -- \ > --id=@myqos create qos type=trtcm-policer \ > -other-config:cir=52000 other-config:cbs=2048 \ > -other-config:eir=52000 other-config:ebs=2048 \ > >> > >> 52000 is fine as our documentation states cir, eir are in bytes per > >> second, minus the ethernet header. > >> So (64-12) * 1000 = 52000 > > > > How come it's not minus 14-byte ethernet header? > > You are right, it should be 14, miscounted the rte_ether_hdr structure size :( > Thank you! at vswitchd/vswitch.xml, it uses "46", should I change it to "64- 14 = 50"? calculated by (pps x packet data size). For example assuming a user wishes to limit a stream consisting of 64 byte packets to 1 million packets per second the EIR would be set to to to 4600. This value can be broken into '1,000,000 x 46'. Where 1,000,000 is the policing rate for the number of packets per second and 46 represents the size of the packet data for a 64 byte ip packet. William ___ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev
Re: [ovs-dev] [PATCH ovn] northd: Provide the Gateway router option 'lb_force_snat_ip' to take router port ips.
On Wed, Feb 17, 2021 at 7:37 PM Mark Gray wrote: > > Thanks Numan, some suggestions below! Hi Mark G, Thanks for the review. PSB for a few comments. > > On 09/02/2021 18:44, num...@ovn.org wrote: > > From: Numan Siddique > > > > When a Gateway router is configured with a load balancer > > and it is also configured with options:lb_force_snat_ip=, > > OVN after load balancing the destination IP to one of the > > backend also does a NAT on the source ip with the > > lb_force_snat_ip if the packet is destined to a load balancer > > VIP. > > > > There is a problem with the snat of source ip to 'lb_force_snat_ip' > > in one particular usecase. When the packet enters the Gateway router > > from a provider logical switch destined to the load balancer VIP, > > then it is first load balanced to one of the backend and then > > the source ip is snatted to 'lb_force_snat_ip'. If the chosen > > backend is reachable via the provider logical switch, then the > > packet is hairpinned back and it may hit the wire with > > the source ip 'lb_force_snat_ip'. If 'lb_force_snat_ip' happens > > to be an OVN internal IP then the packet may be dropped. > > > > This patch addresses this issue by providing the option to > > set the option - 'lb_force_snat_ip=router_ip'. If 'router_ip' > > is set, then OVN will snat the load balanced packet to the > > router ip of the logical router port which chosen as 'outport' > > in lr_in_ip_routing stage. > > It almost feels like this should be the default behaviour? Can you please elaborate more ? You mean ideally CMS should set - router_ip ? > > > > Example. > > > > If the gateway router is > > > > ovn-nbctl show lr0 > > router 68f20092-5563-44b8-9ccb-b11de3e3a66c (lr0) > > port lr0-sw0 > > mac: "00:00:00:00:ff:01" > > networks: ["10.0.0.1/24"] > > port lr0-public > > mac: "00:00:20:20:12:13" > > networks: ["172.168.0.100/24"] > > > > Then the below logical flows are added if 'lb_force_snat_ip' > > is configured to 'router_ip'. > > > > table=1 (lr_out_snat), priority=110 > >match=(flags.force_snat_for_lb == 1 && ip4 && outport == "lr0-public"), > >action=(ct_snat(172.168.0.100);) > > > > table=1 (lr_out_snat), priority=110 > >match=(flags.force_snat_for_lb == 1 && ip4 && outport == "lr0-sw0") > >action=(ct_snat(10.0.0.1);) > > > > For the above described scenario, the packet will have source ip as > > 172.168.0.100 which belongs to the provider logical switch CIDR. > > > > Reported-by: Tim Rozet > > Signed-off-by: Numan Siddique > > --- > > northd/ovn-northd.8.xml | 35 ++ > > northd/ovn-northd.c | 66 -- > > tests/ovn-northd.at | 79 + > > 3 files changed, 177 insertions(+), 3 deletions(-) > > > > diff --git a/northd/ovn-northd.8.xml b/northd/ovn-northd.8.xml > > index 70065a36d9..27b28aff93 100644 > > --- a/northd/ovn-northd.8.xml > > +++ b/northd/ovn-northd.8.xml > > Should 'ovn-nb.xml' also be updated? Great catch. I totally missed it. > > > @@ -3653,6 +3653,32 @@ nd_ns { > >flags.force_snat_for_dnat == 1 ip with an > >action ct_snat(B);. > > > > + > > + > > + > > + > > + If the Gateway router in the OVN Northbound database has been > > + configured to force SNAT a packet (that has been previously > > + load-balanced) using router IP (i.e > + table="Logical_Router"/>:lb_force_snat_ip=router_ip), then for > > + each logical router port P attached to the Gateway > > + router, a priority-110 flow matches > > + flags.force_snat_for_lb == 1 outport == > > P > > + with an action ct_snat(R); > > + where R is the router port IP configured. > > maybe rephrase to "is the IP configured on the router port." Ack. done > > > + If R is an IPv4 address then the match will also > > + include ip4 and if it is an IPv6 address, then the > > + match will also include ip6. > > + > > + > > + > > + If the logical router port P is configured with > > multiple > > + IPv4 and multiple IPv6 addresses, only the first IPv4 and first > > IPv6 > > + address is considered. > > Should we log this condition? Ack. I have added the log for this in v2. > > > + > > + > > + > > + > > > >If the Gateway router in the OVN Northbound database has been > >configured to force SNAT a packet (that has been previously > > @@ -3660,6 +3686,9 @@ nd_ns { > >flags.force_snat_for_lb == 1 ip with an > >action ct_snat(B);. > > > > + > > + > > + > > > >For each configuration in the OVN Northbound database, that asks > >to change the source IP address of a packet from an IP address of > > @@ -3673,14 +3702,18 @@ nd_ns { > >
[ovs-dev] [PATCH ovn v2] northd: Provide the Gateway router option 'lb_force_snat_ip' to take router port ips.
From: Numan Siddique When a Gateway router is configured with a load balancer and it is also configured with options:lb_force_snat_ip=, OVN after load balancing the destination IP to one of the backend also does a NAT on the source ip with the lb_force_snat_ip if the packet is destined to a load balancer VIP. There is a problem with the snat of source ip to 'lb_force_snat_ip' in one particular usecase. When the packet enters the Gateway router from a provider logical switch destined to the load balancer VIP, then it is first load balanced to one of the backend and then the source ip is snatted to 'lb_force_snat_ip'. If the chosen backend is reachable via the provider logical switch, then the packet is hairpinned back and it may hit the wire with the source ip 'lb_force_snat_ip'. If 'lb_force_snat_ip' happens to be an OVN internal IP then the packet may be dropped. This patch addresses this issue by providing the option to set the option - 'lb_force_snat_ip=router_ip'. If 'router_ip' is set, then OVN will snat the load balanced packet to the router ip of the logical router port which is chosen as 'outport' in lr_in_ip_routing stage. Example. If the gateway router is ovn-nbctl show lr0 router 68f20092-5563-44b8-9ccb-b11de3e3a66c (lr0) port lr0-sw0 mac: "00:00:00:00:ff:01" networks: ["10.0.0.1/24"] port lr0-public mac: "00:00:20:20:12:13" networks: ["172.168.0.100/24"] Then the below logical flows are added if 'lb_force_snat_ip' is configured to 'router_ip'. table=1 (lr_out_snat), priority=110 match=(flags.force_snat_for_lb == 1 && ip4 && outport == "lr0-public"), action=(ct_snat(172.168.0.100);) table=1 (lr_out_snat), priority=110 match=(flags.force_snat_for_lb == 1 && ip4 && outport == "lr0-sw0") action=(ct_snat(10.0.0.1);) For the above described scenario, the packet will have source ip as 172.168.0.100 which belongs to the provider logical switch CIDR. Reported-by: Tim Rozet Signed-off-by: Numan Siddique --- v1 -> v2 --- * Addressed review comments from Mark Gray. northd/ovn-northd.8.xml | 35 northd/ovn-northd.c | 93 + ovn-nb.xml | 33 ++- tests/ovn-northd.at | 79 ++ 4 files changed, 222 insertions(+), 18 deletions(-) diff --git a/northd/ovn-northd.8.xml b/northd/ovn-northd.8.xml index 2f8b4e8c30..1d8f5edee1 100644 --- a/northd/ovn-northd.8.xml +++ b/northd/ovn-northd.8.xml @@ -3654,6 +3654,32 @@ nd_ns { flags.force_snat_for_dnat == 1 ip with an action ct_snat(B);. + + + + + If the Gateway router in the OVN Northbound database has been + configured to force SNAT a packet (that has been previously + load-balanced) using router IP (i.e :lb_force_snat_ip=router_ip), then for + each logical router port P attached to the Gateway + router, a priority-110 flow matches + flags.force_snat_for_lb == 1 outport == P + with an action ct_snat(R); + where R is the IP configured on the router port. + If R is an IPv4 address then the match will also + include ip4 and if it is an IPv6 address, then the + match will also include ip6. + + + + If the logical router port P is configured with multiple + IPv4 and multiple IPv6 addresses, only the first IPv4 and first IPv6 + address is considered. + + + + If the Gateway router in the OVN Northbound database has been configured to force SNAT a packet (that has been previously @@ -3661,6 +3687,9 @@ nd_ns { flags.force_snat_for_lb == 1 ip with an action ct_snat(B);. + + + For each configuration in the OVN Northbound database, that asks to change the source IP address of a packet from an IP address of @@ -3674,14 +3703,18 @@ nd_ns { options, then the action would be ip4/6.src= (B). + + If the NAT rule has allowed_ext_ips configured, then there is an additional match ip4.dst == allowed_ext_ips . Similarly, for IPV6, match would be ip6.dst == allowed_ext_ips. + + If the NAT rule has exempted_ext_ips set, then there is an additional flow configured at the priority + 1 of @@ -3690,7 +3723,9 @@ nd_ns { . This flow is used to bypass the ct_snat action for a packet which is destinted to exempted_ext_ips. + + A priority-0 logical flow with match 1 has actions next;. diff --git a/northd/ovn-northd.c b/northd/ovn-northd.c index 39d7987820..816836ab02 100644 --- a/northd/ovn-northd.c +++ b/northd/ovn-northd.c @@ -624,6 +624,7 @@ struct
Re: [ovs-dev] [PATCH] ci: Use parrallel build for distcheck.
Ilya Maximets writes: > 'distcheck' target builds the whole OVS, but for some reason we're > running it in a single-threaded mode. Running in parallel saves > a couple of minutes. > > Signed-off-by: Ilya Maximets > --- Cool - from what I can tell of the jobs, it shaves a couple minutes off the build time (looking at the 'linux gcc test' builds that run the distcheck). Acked-by: Aaron Conole ___ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev
Re: [ovs-dev] [PATCH V2 00/14] Netdev vxlan-decap offload
Sending to Marko. As he wasn't subscribed to ovs-dev then. > -Original Message- > From: dev On Behalf Of Eli Britstein > Sent: Wednesday, February 10, 2021 8:57 PM > To: d...@openvswitch.org; Ilya Maximets > Cc: Eli Britstein ; Ameer Mahagneh > ; Majd Dibbiny ; Gaetan Rivet > > Subject: [ovs-dev] [PATCH V2 00/14] Netdev vxlan-decap offload > > VXLAN decap in OVS-DPDK configuration consists of two flows: > F1: in_port(ens1f0),eth(),ipv4(),udp(), actions:tnl_pop(vxlan_sys_4789) > F2: tunnel(),in_port(vxlan_sys_4789),eth(),ipv4(), actions:ens1f0_0 > > F1 is a classification flow. It has outer headers matches and it classifies > the > packet as a VXLAN packet, and using tnl_pop action the packet continues > processing in F2. > F2 is a flow that has matches on tunnel metadata as well as on the inner > packet headers (as any other flow). > > In order to fully offload VXLAN decap path, both F1 and F2 should be > offloaded. As there are more than one flow in HW, it is possible that > F1 is done by HW but F2 is not. Packet is received by SW, and should be > processed starting from F2 as F1 was already done by HW. > Rte_flows are applicable only on physical port IDs. Keeping the original > physical in port on which the packet is received on enables applying vport > flows (e.g. F2) on that physical port. > > This patch-set makes use of [1] introduced in DPDK 20.11, that adds API for > tunnel offloads. > > v2-v1: > - Tracking original in_port, and applying vport on that physical port instead > of > all PFs. > > Travis: > v1: https://travis-ci.org/github/elibritstein/OVS/builds/756418552 > v2: https://travis-ci.org/github/elibritstein/OVS/builds/758382963 > > GitHub Actions: > v1: https://github.com/elibritstein/OVS/actions/runs/515334647 > v2: https://github.com/elibritstein/OVS/actions/runs/554986007 > > [1] https://mails.dpdk.org/archives/dev/2020-October/187314.html > > Eli Britstein (11): > netdev-offload: Add HW miss packet state recover API > netdev-dpdk: Introduce DPDK tunnel APIs > netdev-offload-dpdk: Implement flow dump create/destroy APIs > netdev-dpdk: Add flow_api support for netdev vxlan vports > netdev-offload-dpdk: Implement HW miss packet recover for vport > dpif-netdev: Add HW miss packet state recover logic > netdev-offload-dpdk: Change log rate limits > netdev-offload-dpdk: Support tunnel pop action > netdev-offload-dpdk: Refactor offload rule creation > netdev-offload-dpdk: Support vports flows offload > netdev-dpdk-offload: Add vxlan pattern matching function > > Ilya Maximets (2): > netdev-offload: Allow offloading to netdev without ifindex. > netdev-offload: Disallow offloading to unrelated tunneling vports. > > Sriharsha Basavapatna (1): > dpif-netdev: Provide orig_in_port in metadata for tunneled packets > > Documentation/howto/dpdk.rst | 1 + > NEWS | 2 + > lib/dpif-netdev.c | 69 ++-- > lib/netdev-dpdk.c | 118 ++ > lib/netdev-dpdk.h | 102 - > lib/netdev-offload-dpdk.c | 706 +- > lib/netdev-offload-provider.h | 5 + > lib/netdev-offload-tc.c | 8 + > lib/netdev-offload.c | 29 +- > lib/netdev-offload.h | 2 + > lib/packets.h | 8 +- > 11 files changed, 921 insertions(+), 129 deletions(-) > > -- > 2.28.0.546.g385c171 > > ___ > 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
Re: [ovs-dev] [PATCH v2 ovn] controller: introduce coverage_counters for ovn-controller incremental processing
> On 17/02/2021 19:33, Lorenzo Bianconi wrote: > > Should the subject have an underscore? 'coverage_counters' ops, sorry..I forgot to fix it. > > > In order to help understanding system behaviour for debugging purpose, > > introduce coverage counters for run handlers of ovn-controller > > I-P engine nodes. Moreover add a global counter for engine abort. > > > > https://bugzilla.redhat.com/show_bug.cgi?id=1890902 > > Signed-off-by: Lorenzo Bianconi > > --- > > Changes since v1: > > - drop handler counters and add global abort counter > > - improve documentation and naming scheme > > - introduce engine_set_node_updated utility macro > > --- > > controller/ovn-controller.c | 39 +++-- > > lib/inc-proc-eng.c | 5 + > > lib/inc-proc-eng.h | 12 +++- > > 3 files changed, 45 insertions(+), 11 deletions(-) > > > > diff --git a/controller/ovn-controller.c b/controller/ovn-controller.c > > index 4343650fc..42eed9ebd 100644 > > --- a/controller/ovn-controller.c > > +++ b/controller/ovn-controller.c > > @@ -69,6 +69,7 @@ > > #include "stopwatch.h" > > #include "lib/inc-proc-eng.h" > > #include "hmapx.h" > > +#include "coverage.h" > > > > VLOG_DEFINE_THIS_MODULE(main); > > > > @@ -85,6 +86,18 @@ static unixctl_cb_func lflow_cache_flush_cmd; > > static unixctl_cb_func lflow_cache_show_stats_cmd; > > static unixctl_cb_func debug_delay_nb_cfg_report; > > > > +/* Coverage counters for run handlers of OVN controller > > + * incremental processing nodes > > + */ > > +ENGINE_RUN_COVERAGE_DEFINE(flow_output); > > +ENGINE_RUN_COVERAGE_DEFINE(runtime_data); > > +ENGINE_RUN_COVERAGE_DEFINE(addr_sets); > > +ENGINE_RUN_COVERAGE_DEFINE(port_groups); > > +ENGINE_RUN_COVERAGE_DEFINE(ct_zones); > > +ENGINE_RUN_COVERAGE_DEFINE(mff_ovn_geneve); > > +ENGINE_RUN_COVERAGE_DEFINE(ofctrl_is_connected); > > +ENGINE_RUN_COVERAGE_DEFINE(physical_flow_changes); > > > I would like these counters to be part of the framework (i.e. > inc-proc-eng.c/h) rather than being exposed out. The reasoning is that > we shouldn't rely on a developer to modify them correctly when updating > the _handler() and the _run() functions as it is too error-prone IMHO. > For example, if a _run() function exits early and also sets a node to > updated or aborts a node, will the developer/reviewer remember to update > the corresponding counter? Also, if we need to make changes to the > counters, it would be preferable to make the changes in one location. > > I realize that this causes issues for per-node counters as currently > implemented: inc-proc-eng.c has no idea about which nodes are which at > compilation time and COVERAGE_INC() is a macro which requires templating > the name of the node at compilation time. > > For this reason, I suggest the following: > > * Add counters to 'struct engine_node' and/or 'struct engine_context' > * Create an ovs-appctl command, something like `ovs-appctl-ctl -t > ovs-controller inc-proc-eng/stats-show` and `ovs-appctl-ctl -t > ovs-controller inc-proc-eng/stats-clear` that will show/clear these > stats to the user > > This follows a common pattern in OVS/OVN code. e.g. > https://github.com/openvswitch/ovs/blob/master/Documentation/topics/dpdk/pmd.rst#pmd-thread-statistics. > > The next question is what counters to expose. As I think it should be > easier to expose counters using the `appctl` above, I would suggest > exposing as much as you can. However, you could also get feedback from > those in the community who have more operational experience with OVN. > > Here are some suggestions: > > * Total number of engine runs > * Total number of engine aborts > * Total number of engine recomputes > * Number of runs for each node > * Number of computes for each node > * Number of recomputes for each node > * Number of transitions to ABORT for each node > * Number of transitions to UNCHANGED for each node > * Number of transitions to UPDATED for each node > > What do you think? yes, I like the idea...avoiding COVERAGE_* macros will allow a more manageable code. I will work on a PoC, thx :) Regards, Lorenzo > > > + > > #define DEFAULT_BRIDGE_NAME "br-int" > > #define DEFAULT_PROBE_INTERVAL_MSEC 5000 > > #define OFCTRL_DEFAULT_PROBE_INTERVAL_SEC 0 > > @@ -955,6 +968,10 @@ ctrl_register_ovs_idl(struct ovsdb_idl *ovs_idl) > > SB_NODE(dns, "dns") \ > > SB_NODE(load_balancer, "load_balancer") > > > > +#define SB_NODE(NAME, NAME_STR) ENGINE_RUN_COVERAGE_DEFINE(sb_##NAME); > > +SB_NODES > > +#undef SB_NODE > > + > > enum sb_engine_node { > > #define SB_NODE(NAME, NAME_STR) SB_##NAME, > > SB_NODES > > @@ -972,6 +989,10 @@ enum sb_engine_node { > > OVS_NODE(interface, "interface") \ > > OVS_NODE(qos, "qos") > > > > +#define OVS_NODE(NAME, NAME_STR) ENGINE_RUN_COVERAGE_DEFINE(ovs_##NAME); > > +OVS_NODES > > +#undef OVS_NODE > > + > > enum ovs_engine_node { > > #define OVS_NODE(NAME, NAME_STR) OVS_##NAME, > >
Re: [ovs-dev] [PATCH] ci: Use parrallel build for distcheck.
On 2/18/21 1:20 PM, Tonghao Zhang wrote: > On Thu, Feb 18, 2021 at 6:33 PM Ilya Maximets wrote: >> >> 'distcheck' target builds the whole OVS, but for some reason we're >> running it in a single-threaded mode. Running in parallel saves >> a couple of minutes. >> >> Signed-off-by: Ilya Maximets >> --- >> .ci/linux-build.sh | 2 +- >> 1 file changed, 1 insertion(+), 1 deletion(-) >> >> diff --git a/.ci/linux-build.sh b/.ci/linux-build.sh >> index 581ab..977449350 100755 >> --- a/.ci/linux-build.sh >> +++ b/.ci/linux-build.sh >> @@ -244,7 +244,7 @@ if [ "$TESTSUITE" ]; then >> configure_ovs >> >> export DISTCHECK_CONFIGURE_FLAGS="$OPTS" >> -if ! make distcheck CFLAGS="${CFLAGS_FOR_OVS}" \ >> +if ! make distcheck -j4 CFLAGS="${CFLAGS_FOR_OVS}" \ > why not use $(nproc)? >> TESTSUITEFLAGS=-j4 RECHECK=yes; then > and -j4 --> $(nproc) ? CI systems provides 2 CPUs, so nproc is equal to 2. Both build and tests are IO intensive and not able to fully utilize CPU resources while waiting on IO, so we're creating more threads than CPUs. From my experience 2x is enough, higher parallelism doesn't usually give any improvement. We can replace 4 with 'nproc * 2', but I do not expect changes in number of available CPU cores in CI, so it's not very important. >> # testsuite.log is necessary for debugging. >> cat */_build/sub/tests/testsuite.log >> -- >> 2.26.2 ___ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev
Re: [ovs-dev] [PATCH] ci: Use parrallel build for distcheck.
On Thu, Feb 18, 2021 at 6:33 PM Ilya Maximets wrote: > > 'distcheck' target builds the whole OVS, but for some reason we're > running it in a single-threaded mode. Running in parallel saves > a couple of minutes. > > Signed-off-by: Ilya Maximets > --- > .ci/linux-build.sh | 2 +- > 1 file changed, 1 insertion(+), 1 deletion(-) > > diff --git a/.ci/linux-build.sh b/.ci/linux-build.sh > index 581ab..977449350 100755 > --- a/.ci/linux-build.sh > +++ b/.ci/linux-build.sh > @@ -244,7 +244,7 @@ if [ "$TESTSUITE" ]; then > configure_ovs > > export DISTCHECK_CONFIGURE_FLAGS="$OPTS" > -if ! make distcheck CFLAGS="${CFLAGS_FOR_OVS}" \ > +if ! make distcheck -j4 CFLAGS="${CFLAGS_FOR_OVS}" \ why not use $(nproc)? > TESTSUITEFLAGS=-j4 RECHECK=yes; then and -j4 --> $(nproc) ? > # testsuite.log is necessary for debugging. > cat */_build/sub/tests/testsuite.log > -- > 2.26.2 > > ___ > dev mailing list > d...@openvswitch.org > https://mail.openvswitch.org/mailman/listinfo/ovs-dev -- Best regards, Tonghao ___ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev
Re: [ovs-dev] [PATCH v2 ovn] controller: introduce coverage_counters for ovn-controller incremental processing
On 17/02/2021 19:33, Lorenzo Bianconi wrote: Should the subject have an underscore? 'coverage_counters' > In order to help understanding system behaviour for debugging purpose, > introduce coverage counters for run handlers of ovn-controller > I-P engine nodes. Moreover add a global counter for engine abort. > > https://bugzilla.redhat.com/show_bug.cgi?id=1890902 > Signed-off-by: Lorenzo Bianconi > --- > Changes since v1: > - drop handler counters and add global abort counter > - improve documentation and naming scheme > - introduce engine_set_node_updated utility macro > --- > controller/ovn-controller.c | 39 +++-- > lib/inc-proc-eng.c | 5 + > lib/inc-proc-eng.h | 12 +++- > 3 files changed, 45 insertions(+), 11 deletions(-) > > diff --git a/controller/ovn-controller.c b/controller/ovn-controller.c > index 4343650fc..42eed9ebd 100644 > --- a/controller/ovn-controller.c > +++ b/controller/ovn-controller.c > @@ -69,6 +69,7 @@ > #include "stopwatch.h" > #include "lib/inc-proc-eng.h" > #include "hmapx.h" > +#include "coverage.h" > > VLOG_DEFINE_THIS_MODULE(main); > > @@ -85,6 +86,18 @@ static unixctl_cb_func lflow_cache_flush_cmd; > static unixctl_cb_func lflow_cache_show_stats_cmd; > static unixctl_cb_func debug_delay_nb_cfg_report; > > +/* Coverage counters for run handlers of OVN controller > + * incremental processing nodes > + */ > +ENGINE_RUN_COVERAGE_DEFINE(flow_output); > +ENGINE_RUN_COVERAGE_DEFINE(runtime_data); > +ENGINE_RUN_COVERAGE_DEFINE(addr_sets); > +ENGINE_RUN_COVERAGE_DEFINE(port_groups); > +ENGINE_RUN_COVERAGE_DEFINE(ct_zones); > +ENGINE_RUN_COVERAGE_DEFINE(mff_ovn_geneve); > +ENGINE_RUN_COVERAGE_DEFINE(ofctrl_is_connected); > +ENGINE_RUN_COVERAGE_DEFINE(physical_flow_changes); I would like these counters to be part of the framework (i.e. inc-proc-eng.c/h) rather than being exposed out. The reasoning is that we shouldn't rely on a developer to modify them correctly when updating the _handler() and the _run() functions as it is too error-prone IMHO. For example, if a _run() function exits early and also sets a node to updated or aborts a node, will the developer/reviewer remember to update the corresponding counter? Also, if we need to make changes to the counters, it would be preferable to make the changes in one location. I realize that this causes issues for per-node counters as currently implemented: inc-proc-eng.c has no idea about which nodes are which at compilation time and COVERAGE_INC() is a macro which requires templating the name of the node at compilation time. For this reason, I suggest the following: * Add counters to 'struct engine_node' and/or 'struct engine_context' * Create an ovs-appctl command, something like `ovs-appctl-ctl -t ovs-controller inc-proc-eng/stats-show` and `ovs-appctl-ctl -t ovs-controller inc-proc-eng/stats-clear` that will show/clear these stats to the user This follows a common pattern in OVS/OVN code. e.g. https://github.com/openvswitch/ovs/blob/master/Documentation/topics/dpdk/pmd.rst#pmd-thread-statistics. The next question is what counters to expose. As I think it should be easier to expose counters using the `appctl` above, I would suggest exposing as much as you can. However, you could also get feedback from those in the community who have more operational experience with OVN. Here are some suggestions: * Total number of engine runs * Total number of engine aborts * Total number of engine recomputes * Number of runs for each node * Number of computes for each node * Number of recomputes for each node * Number of transitions to ABORT for each node * Number of transitions to UNCHANGED for each node * Number of transitions to UPDATED for each node What do you think? > + > #define DEFAULT_BRIDGE_NAME "br-int" > #define DEFAULT_PROBE_INTERVAL_MSEC 5000 > #define OFCTRL_DEFAULT_PROBE_INTERVAL_SEC 0 > @@ -955,6 +968,10 @@ ctrl_register_ovs_idl(struct ovsdb_idl *ovs_idl) > SB_NODE(dns, "dns") \ > SB_NODE(load_balancer, "load_balancer") > > +#define SB_NODE(NAME, NAME_STR) ENGINE_RUN_COVERAGE_DEFINE(sb_##NAME); > +SB_NODES > +#undef SB_NODE > + > enum sb_engine_node { > #define SB_NODE(NAME, NAME_STR) SB_##NAME, > SB_NODES > @@ -972,6 +989,10 @@ enum sb_engine_node { > OVS_NODE(interface, "interface") \ > OVS_NODE(qos, "qos") > > +#define OVS_NODE(NAME, NAME_STR) ENGINE_RUN_COVERAGE_DEFINE(ovs_##NAME); > +OVS_NODES > +#undef OVS_NODE > + > enum ovs_engine_node { > #define OVS_NODE(NAME, NAME_STR) OVS_##NAME, > OVS_NODES > @@ -1011,7 +1032,7 @@ en_ofctrl_is_connected_run(struct engine_node *node, > void *data) > ofctrl_seqno_flush(); > binding_seqno_flush(); > } > -engine_set_node_state(node, EN_UPDATED); > +engine_set_node_updated(node, ofctrl_is_connected); > return; > } > engine_set_node_state(node, EN_UNCHANGED); > @@ -1067,7 +1088,7 @@
[ovs-dev] [PATCH 0/1] PMD auto balance unit tests.
These are some initial unit tests for PMD auto load balance that focus on enabling/disabling and user parameters. While writing these, I found some gaps in the logs and sent patches [1]. The existing logs were not incorrect but there was a few scenarios where it would be reasonable and helpful to expect a log that didn't appear. v1: - Patch 1/2 in [1] that logs the state of alb was applied - Patch 2/2 in [1] that logs the reason alb was not enabled was not applied - Make v1 and remove check for reason logs [1] http://patchwork.ozlabs.org/project/openvswitch/list/?series=228233 Kevin Traynor (1): tests: Add PMD auto load balance unit tests. tests/alb.at | 256 + tests/automake.mk | 1 + tests/testsuite.at | 1 + 3 files changed, 258 insertions(+) create mode 100644 tests/alb.at -- 2.26.2 ___ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev
[ovs-dev] [PATCH 1/1] tests: Add PMD auto load balance unit tests.
These tests focus on enabling/disabling and user parameters. Signed-off-by: Kevin Traynor --- tests/alb.at | 256 + tests/automake.mk | 1 + tests/testsuite.at | 1 + 3 files changed, 258 insertions(+) create mode 100644 tests/alb.at diff --git a/tests/alb.at b/tests/alb.at new file mode 100644 index 0..136c26c44 --- /dev/null +++ b/tests/alb.at @@ -0,0 +1,256 @@ +AT_BANNER([PMD Auto Load Balance]) + +m4_divert_push([PREPARE_TESTS]) + +get_log_line_num () { +LINENUM=$(cat ovs-vswitchd.log | wc -l | tr -d [[:blank:]]) +} + +m4_divert_pop([PREPARE_TESTS]) + +m4_define([DUMMY_NUMA], [--dummy-numa="0,0"]) + +dnl CHECK_INTERVAL_PARAM([interval_time], [+line]) +dnl +dnl Waits for alb interval time in logs and checks if time matches +dnl $1. Checking starts from line number 'line' in ovs-vswithd.log . +m4_define([CHECK_INTERVAL_PARAM], [ +PATTERN="PMD auto load balance interval set to [[0-9]]* mins" +line_st=$2 +if [[ -z "$line_st" ]] +then +line_st="+0" +fi +OVS_WAIT_UNTIL([tail -n $line_st ovs-vswitchd.log | grep "$PATTERN"]) +TIME=$(tail -n $line_st ovs-vswitchd.log | grep "$PATTERN" | tail -1 | sed -e 's/.* \([[0-9]]*\) mins/\1/') +AT_CHECK([test "$TIME" -eq "$1"]) +]) + +dnl CHECK_LOAD_PARAM([load], [+line]) +dnl +dnl Waits for alb load threshold in logs and checks if threshold matches +dnl $1. Checking starts from line number 'line' in ovs-vswithd.log . +m4_define([CHECK_LOAD_PARAM], [ +PATTERN="PMD auto load balance load threshold set to [[0-9]]*" +line_st=$2 +if [[ -z "$line_st" ]] +then +line_st="+0" +fi +OVS_WAIT_UNTIL([tail -n $line_st ovs-vswitchd.log | grep "$PATTERN"]) +LOAD=$(tail -n $line_st ovs-vswitchd.log | grep "$PATTERN" | tail -1 | tr -d '%' | sed -e 's/.* \([[0-9]]*\)/\1/') +AT_CHECK([test "$LOAD" -eq "$1"]) +]) + +dnl CHECK_IMPROVE_PARAM([load], [+line]) +dnl +dnl Waits for alb improve threshold in logs and checks if threshold matches +dnl $1. Checking starts from line number 'line' in ovs-vswithd.log . +m4_define([CHECK_IMPROVE_PARAM], [ +PATTERN="PMD auto load balance improvement threshold set to [[0-9]]*" +line_st=$3 +if [[ -z "$line_st" ]] +then +line_st="+0" +fi +OVS_WAIT_UNTIL([tail -n $line_st ovs-vswitchd.log | grep "$PATTERN"]) +IMPROVE=$(tail -n $line_st ovs-vswitchd.log | grep "$PATTERN" | tail -1 | tr -d '%' | sed -e 's/.* \([[0-9]]*\)/\1/') +AT_CHECK([test "$IMPROVE" -eq "$1"]) +]) + + +AT_SETUP([ALB - default state]) +OVS_VSWITCHD_START +OVS_WAIT_UNTIL([grep "PMD auto load balance is disabled" ovs-vswitchd.log]) + +OVS_VSWITCHD_STOP +AT_CLEANUP + +AT_SETUP([ALB - enable/disable]) +OVS_VSWITCHD_START([add-port br0 p0 \ +-- set Interface p0 type=dummy-pmd options:n_rxq=3 \ +-- set Open_vSwitch . other_config:pmd-cpu-mask=3 \ +-- set open_vswitch . other_config:pmd-auto-lb="true"], + [], [], [DUMMY_NUMA]) +OVS_WAIT_UNTIL([grep "PMD auto load balance is enabled" ovs-vswitchd.log]) + +get_log_line_num +AT_CHECK([ovs-vsctl set open_vswitch . other_config:pmd-auto-lb="false"]) +OVS_WAIT_UNTIL([tail -n +$LINENUM ovs-vswitchd.log | grep "PMD auto load balance is disabled"]) + +get_log_line_num +AT_CHECK([ovs-vsctl set open_vswitch . other_config:pmd-auto-lb="true"]) +OVS_WAIT_UNTIL([tail -n +$LINENUM ovs-vswitchd.log | grep "PMD auto load balance is enabled"]) + +OVS_VSWITCHD_STOP +AT_CLEANUP + +AT_SETUP([ALB - min num PMD/RxQ]) +OVS_VSWITCHD_START([add-port br0 p0 \ +-- set Interface p0 type=dummy-pmd options:n_rxq=2 \ +-- set Open_vSwitch . other_config:pmd-cpu-mask=1 \ +-- set open_vswitch . other_config:pmd-auto-lb="true"], + [], [], [DUMMY_NUMA]) +OVS_WAIT_UNTIL([grep "PMD auto load balance is disabled" ovs-vswitchd.log]) + +# Add more PMD +AT_CHECK([ovs-vsctl set Open_vSwitch . other_config:pmd-cpu-mask=0x3]) +OVS_WAIT_UNTIL([grep "There are 2 pmd threads on numa node" ovs-vswitchd.log]) + +# Add one more rxq to have 2 rxq on a PMD +get_log_line_num +AT_CHECK([ovs-vsctl set interface p0 options:n_rxq=3]) +OVS_WAIT_UNTIL([tail -n +$LINENUM ovs-vswitchd.log | grep "PMD auto load balance is enabled"]) + +# Reduce PMD +get_log_line_num +AT_CHECK([ovs-vsctl set Open_vSwitch . other_config:pmd-cpu-mask=0x1]) +OVS_WAIT_UNTIL([tail -n +$LINENUM ovs-vswitchd.log | grep "PMD auto load balance is disabled"]) + +# Check logs when try to enable but min PMD/RxQ prevents +get_log_line_num +AT_CHECK([ovs-vsctl set open_vswitch . other_config:pmd-auto-lb="false"]) +OVS_WAIT_UNTIL([tail -n +$LINENUM ovs-vswitchd.log | grep "PMD auto load balance is disabled"]) +get_log_line_num +AT_CHECK([ovs-vsctl set open_vswitch . other_config:pmd-auto-lb="true"]) +OVS_WAIT_UNTIL([tail -n +$LINENUM ovs-vswitchd.log | grep "PMD auto load balance is
[ovs-dev] [PATCH] ci: Use parrallel build for distcheck.
'distcheck' target builds the whole OVS, but for some reason we're running it in a single-threaded mode. Running in parallel saves a couple of minutes. Signed-off-by: Ilya Maximets --- .ci/linux-build.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.ci/linux-build.sh b/.ci/linux-build.sh index 581ab..977449350 100755 --- a/.ci/linux-build.sh +++ b/.ci/linux-build.sh @@ -244,7 +244,7 @@ if [ "$TESTSUITE" ]; then configure_ovs export DISTCHECK_CONFIGURE_FLAGS="$OPTS" -if ! make distcheck CFLAGS="${CFLAGS_FOR_OVS}" \ +if ! make distcheck -j4 CFLAGS="${CFLAGS_FOR_OVS}" \ TESTSUITEFLAGS=-j4 RECHECK=yes; then # testsuite.log is necessary for debugging. cat */_build/sub/tests/testsuite.log -- 2.26.2 ___ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev
Re: [ovs-dev] [PATCH v2] ofproto-dpif-xlate: fix zone set from non-frozen-metadata fields
Bleep bloop. Greetings 贺鹏, I am a robot and I have tried out your patch. Thanks for your contribution. I encountered some error that I wasn't expecting. See the details below. checkpatch: ERROR: Author Peng He needs to sign off. WARNING: Unexpected sign-offs from developers who are not authors or co-authors or committers: Peng He Lines checked: 163, Warnings: 1, Errors: 1 Please check this out. If you feel there has been an error, please email acon...@redhat.com Thanks, 0-day Robot ___ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev
Re: [ovs-dev] [PATCH v1] ofproto-dpif-xlate: fix zone set from non frozen metadata field
Hi, I've already sent a v2 patch. Mark Gray 于2021年2月17日周三 下午6:44写道: > > On 17/02/2021 10:40, 贺鹏 wrote: > > Hi, > > > > Thanks for the review. > > > > Mark Gray 于2021年2月17日周三 下午6:13写道: > >> > >> I'm not too familiar with this code but I have some comments. > >> > >> On 15/02/2021 09:50, Peng He wrote: > >>> CT zone could be set from a field that is not included in frozen > >>> metedata. Consider the belowing cases which is normally used in > >> > >> Nits: > >> > >> s/metedata/metadata > >> s/belowing cases which is/cases below which are > > > > sorry for the typo, will fix it in the next version > > > >> > >>> OpenStack security group rules: > >>> > >>> priority=100,in_port=1,tcp,ct_state=-trk,action=ct(zone=5,table=0) > >>> priority=100,in_port=1,tcp,ct_state=+trk,action=ct(commit,zone=NXM_NX_CT_ZONE[]),2 > >>> > >>> The zone is set from the first rule's ct action. These two rules will > >>> generate two megaflows: the first one uses zone=5 to query the CT module, > >>> the second one set zone from the first megaflow and commit to CT. > >>> > >>> The current implementation will generate a megaflow which does not use > >>> ct_zone=5 as a match, but directly commit into the ct using zone=5, as > >>> zone is > >>> set by an Imm not a field. > >>> > >>> Consider a situation that one changes the zone id (for example to 15) > >>> in the first rule however still keep the second rule unchanged. During > >>> this change, there is traffic hitting the two generated megaflows, the > >>> revaldiator would revalidate all megaflows, however, the revalidator will > >>> not change the second megaflow, because zone=5 is recorded in the > >>> megaflow, so the xlate will still translate the commit action into zone=5, > >>> and the new traffic will still commit to CT as zone=5, not zone=15, > >>> resulting in taffic drops and other issues. > >>> > >>> Just like OVS set-field action, if the field X is set by Y, we should also > >>> mask Y as a match in the generated megaflow. An exception is that, if the > >>> zone > >>> is set by the field that is included in the frozen state and this upcall > >>> is > >>> a resume of a thawed xlate, the masking can be skipped, as if one changes > >>> the previous rule, the generated recirc_id will be changed, and all > >>> megaflows > >>> with the old recirc id will be invalid later, i.e. the revalidator will > >>> not reuse the old megaflows at all. > >>> > >>> Fixes: 07659514c3 ("Add support for connection tracking.") > >>> Reported-by: Sai Su > >>> Signed-off-by: Peng He > >>> --- > >>> include/openvswitch/meta-flow.h | 1 + > >>> lib/meta-flow.c | 13 +++ > >>> ofproto/ofproto-dpif-xlate.c| 15 + > >>> tests/system-traffic.at | 39 + > >>> 4 files changed, 68 insertions(+) > >>> > >>> diff --git a/include/openvswitch/meta-flow.h > >>> b/include/openvswitch/meta-flow.h > >>> index 95e52e358..045dce8f5 100644 > >>> --- a/include/openvswitch/meta-flow.h > >>> +++ b/include/openvswitch/meta-flow.h > >>> @@ -2305,6 +2305,7 @@ void mf_set_flow_value_masked(const struct mf_field > >>> *, > >>>const union mf_value *mask, > >>>struct flow *); > >>> bool mf_is_tun_metadata(const struct mf_field *); > >>> +bool mf_is_frozen_metadata(const struct mf_field *); > >>> bool mf_is_pipeline_field(const struct mf_field *); > >>> bool mf_is_set(const struct mf_field *, const struct flow *); > >>> void mf_mask_field(const struct mf_field *, struct flow_wildcards *); > >>> diff --git a/lib/meta-flow.c b/lib/meta-flow.c > >>> index c808d205d..e03cd8d0c 100644 > >>> --- a/lib/meta-flow.c > >>> +++ b/lib/meta-flow.c > >>> @@ -1788,6 +1788,19 @@ mf_is_tun_metadata(const struct mf_field *mf) > >>> mf->id < MFF_TUN_METADATA0 + TUN_METADATA_NUM_OPTS; > >>> } > >>> > >>> +bool > >>> +mf_is_frozen_metadata(const struct mf_field *mf) > >>> +{ > >>> +if (mf->id >= MFF_TUN_ID && mf->id <= MFF_IN_PORT_OXM) { > >>> +return true; > >>> +} > >>> + > >>> +if (mf->id >= MFF_REG0 && mf->id < MFF_ETH_SRC) { > >>> +return true; > >>> +} > >>> +return false; > >>> +} > >>> + > >>> bool > >>> mf_is_pipeline_field(const struct mf_field *mf) > >>> { > >>> diff --git a/ofproto/ofproto-dpif-xlate.c b/ofproto/ofproto-dpif-xlate.c > >>> index 7108c8a30..5d1f029fd 100644 > >>> --- a/ofproto/ofproto-dpif-xlate.c > >>> +++ b/ofproto/ofproto-dpif-xlate.c > >>> @@ -6212,6 +6212,21 @@ compose_conntrack_action(struct xlate_ctx *ctx, > >>> struct ofpact_conntrack *ofc, > >>> >xin->flow, ctx->wc, zone); > >>> } > >>> } > >>> + > >>> +if (ofc->zone_src.field) { > >>> +if (ctx->xin->frozen_state) { > >>> +/* If the upcall is a resume of a recirculation, we only > >>> need to > >>> + * unwildcard the fields that are not in the > >>> frozen_metadata, as > >>> +
[ovs-dev] [PATCH v2] ofproto-dpif-xlate: fix zone set from non-frozen-metadata fields
CT zone could be set from a field that is not included in frozen metadata. Consider the example rules which are typically seen in OpenStack security group rules: priority=100,in_port=1,tcp,ct_state=-trk,action=ct(zone=5,table=0) priority=100,in_port=1,tcp,ct_state=+trk,action=ct(commit,zone=NXM_NX_CT_ZONE[]),2 The zone is set from the first rule's ct action. These two rules will generate two megaflows: the first one uses zone=5 to query the CT module, the second one sets the zone-id from the first megaflow and commit to CT. The current implementation will generate a megaflow that does not use ct_zone=5 as a match, but directly commit into the ct using zone=5, as zone is set by an Imm not a field. Consider a situation that one changes the zone id (for example to 15) in the first rule, however, still keep the second rule unchanged. During this change, there is traffic hitting the two generated megaflows, the revaldiator would revalidate all megaflows, however, the revalidator will not change the second megaflow, because zone=5 is recorded in the megaflow, so the xlate will still translate the commit action into zone=5, and the new traffic will still commit to CT as zone=5, not zone=15, resulting in taffic drops and other issues. Just like OVS set-field convention, if a field X is set by Y (Y is a variable not an Imm), we should also mask Y as a match in the generated megaflow. An exception is that if the zone-id is set by the field that is included in the frozen state (i.e. regs) and this upcall is a resume of a thawed xlate, the un-wildcarding can be skipped, as the recirc_id is a hash of the values in these fields, and it will change following the changes of these fields. When the recirc_id changes, all megaflows with the old recirc id will be invalid later. Fixes: 07659514c3 ("Add support for connection tracking.") Reported-by: Sai Su Signed-off-by: Peng He --- include/openvswitch/meta-flow.h | 1 + lib/meta-flow.c | 13 ++ ofproto/ofproto-dpif-xlate.c| 12 ++ tests/system-traffic.at | 42 + 4 files changed, 68 insertions(+) diff --git a/include/openvswitch/meta-flow.h b/include/openvswitch/meta-flow.h index 95e52e358..045dce8f5 100644 --- a/include/openvswitch/meta-flow.h +++ b/include/openvswitch/meta-flow.h @@ -2305,6 +2305,7 @@ void mf_set_flow_value_masked(const struct mf_field *, const union mf_value *mask, struct flow *); bool mf_is_tun_metadata(const struct mf_field *); +bool mf_is_frozen_metadata(const struct mf_field *); bool mf_is_pipeline_field(const struct mf_field *); bool mf_is_set(const struct mf_field *, const struct flow *); void mf_mask_field(const struct mf_field *, struct flow_wildcards *); diff --git a/lib/meta-flow.c b/lib/meta-flow.c index c808d205d..e03cd8d0c 100644 --- a/lib/meta-flow.c +++ b/lib/meta-flow.c @@ -1788,6 +1788,19 @@ mf_is_tun_metadata(const struct mf_field *mf) mf->id < MFF_TUN_METADATA0 + TUN_METADATA_NUM_OPTS; } +bool +mf_is_frozen_metadata(const struct mf_field *mf) +{ +if (mf->id >= MFF_TUN_ID && mf->id <= MFF_IN_PORT_OXM) { +return true; +} + +if (mf->id >= MFF_REG0 && mf->id < MFF_ETH_SRC) { +return true; +} +return false; +} + bool mf_is_pipeline_field(const struct mf_field *mf) { diff --git a/ofproto/ofproto-dpif-xlate.c b/ofproto/ofproto-dpif-xlate.c index 7108c8a30..14d00db1e 100644 --- a/ofproto/ofproto-dpif-xlate.c +++ b/ofproto/ofproto-dpif-xlate.c @@ -6195,6 +6195,18 @@ compose_conntrack_action(struct xlate_ctx *ctx, struct ofpact_conntrack *ofc, if (ofc->zone_src.field) { zone = mf_get_subfield(>zone_src, >xin->flow); +if (ctx->xin->frozen_state) { +/* If the upcall is a resume of a recirculation, we only need to + * unwildcard the fields that are not in the frozen_metadata, as + * when the rules update, OVS will generate a new recirc_id, + * which will invalidate the megaflow with old the recirc_id. + */ +if (!mf_is_frozen_metadata(ofc->zone_src.field)) { +mf_mask_field(ofc->zone_src.field, ctx->wc); +} +} else { +mf_mask_field(ofc->zone_src.field, ctx->wc); +} } else { zone = ofc->zone_imm; } diff --git a/tests/system-traffic.at b/tests/system-traffic.at index fb5b9a36d..84a9759ea 100644 --- a/tests/system-traffic.at +++ b/tests/system-traffic.at @@ -1927,6 +1927,48 @@ tcp,orig=(src=10.1.1.3,dst=10.1.1.4,sport=,dport=),reply=(src= OVS_TRAFFIC_VSWITCHD_STOP AT_CLEANUP +AT_SETUP([conntrack - zones from other field]) +CHECK_CONNTRACK() +OVS_TRAFFIC_VSWITCHD_START() + +ADD_NAMESPACES(at_ns0, at_ns1) + +ADD_VETH(p0, at_ns0, br0, "10.1.1.1/24") +ADD_VETH(p1, at_ns1, br0, "10.1.1.2/24") + +dnl Allow any traffic from ns0->ns1. Only allow nd, return traffic from ns1->ns0.
Re: [ovs-dev] [PATCH ovn branch-20.06 00/15] Backport rollup
On 2/18/21 9:09 AM, Frode Nordahl wrote: Hello all, Hi Frode, Many thanks for this! In Ubuntu we have backported a set of fixes to our OVN 20.06 and OVN 20.03 packages. In preparing for new point releases for OVN 20.06 and OVN 20.03, we would very much like to add these patches to the upstream branches. The issues solved for OVN 20.06 with these patches are: * Fix for upgrading database schema of clustered databases on package upgrade (LP: #1907081)[0] * Fixes for predictable resolution for conflicting flow actions. (LP: #1906922)[1] You might want to wait a bit with releasing new packages and include more patches (some are not merged in upstream master yet) that fix crashes due some of the ofctrl changes: https://github.com/ovn-org/ovn/commit/858d1dd716db1a1e664a7c1737fd34f04fcbda5e (in upstream master and branch20.12) http://patchwork.ozlabs.org/project/ovn/patch/1613490806-11143-1-git-send-email-dce...@redhat.com/ (I'll be submitting a v2 today). Regards, Dumitru ___ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev
Re: [ovs-dev] [PATCH] Documentation: Fix DPDK qos example.
On 17 Feb 2021, at 18:41, William Tu wrote: >> Information Rate). High priority traffic is routed to queue 10, which marks all traffic as CIR, i.e. Green. All low priority traffic, queue 20, is marked as EIR, i.e. Yellow:: $ ovs-vsctl --timeout=5 set port dpdk1 qos=@myqos -- \ --id=@myqos create qos type=trtcm-policer \ -other-config:cir=52000 other-config:cbs=2048 \ -other-config:eir=52000 other-config:ebs=2048 \ >> >> 52000 is fine as our documentation states cir, eir are in bytes per >> second, minus the ethernet header. >> So (64-12) * 1000 = 52000 > > How come it's not minus 14-byte ethernet header? You are right, it should be 14, miscounted the rte_ether_hdr structure size :( ___ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev
Re: [ovs-dev] [PATCH ovn branch-20.03 01/16] ovn-ctl: Handle cluster db upgrades for run_(nb/sb)_ovsdb
Bleep bloop. Greetings Frode Nordahl, I am a robot and I have tried out your patch. Thanks for your contribution. I encountered some error that I wasn't expecting. See the details below. checkpatch: WARNING: Unexpected sign-offs from developers who are not authors or co-authors or committers: Frode Nordahl WARNING: Line is 91 characters long (recommended limit is 79) #35 FILE: utilities/ovn-ctl:289: if test X$detach = Xno && test $mode = cluster && test -z "$cluster_remote_addr" ; then Lines checked: 64, Warnings: 2, Errors: 0 build: gcc -std=gnu99 -DHAVE_CONFIG_H -I. -I ./include -I ./include -I ./ovn -I ./include -I /var/lib/jenkins/jobs/0day_robot_upstream_build_ovn_from_pw/workspace/OVSDIR/include -I /var/lib/jenkins/jobs/0day_robot_upstream_build_ovn_from_pw/workspace/OVSDIR/include -I /var/lib/jenkins/jobs/0day_robot_upstream_build_ovn_from_pw/workspace/OVSDIR/lib -I /var/lib/jenkins/jobs/0day_robot_upstream_build_ovn_from_pw/workspace/OVSDIR/lib -I /var/lib/jenkins/jobs/0day_robot_upstream_build_ovn_from_pw/workspace/OVSDIR -I /var/lib/jenkins/jobs/0day_robot_upstream_build_ovn_from_pw/workspace/OVSDIR -I ./lib -I ./lib-Wstrict-prototypes -Wall -Wextra -Wno-sign-compare -Wpointer-arith -Wformat -Wformat-security -Wswitch-enum -Wunused-parameter -Wbad-function-cast -Wcast-align -Wstrict-prototypes -Wold-style-definition -Wmissing-prototypes -Wmissing-field-initializers -fno-strict-aliasing -Wshadow -Werror -Werror -g -O2 -MT controller/pinctrl.o -MD -MP -MF $depbase.Tpo -c -o controller/pinctrl.o controller/pinctrl.c &&\ mv -f $depbase.Tpo $depbase.Po depbase=`echo controller/patch.o | sed 's|[^/]*$|.deps/&|;s|\.o$||'`;\ gcc -std=gnu99 -DHAVE_CONFIG_H -I. -I ./include -I ./include -I ./ovn -I ./include -I /var/lib/jenkins/jobs/0day_robot_upstream_build_ovn_from_pw/workspace/OVSDIR/include -I /var/lib/jenkins/jobs/0day_robot_upstream_build_ovn_from_pw/workspace/OVSDIR/include -I /var/lib/jenkins/jobs/0day_robot_upstream_build_ovn_from_pw/workspace/OVSDIR/lib -I /var/lib/jenkins/jobs/0day_robot_upstream_build_ovn_from_pw/workspace/OVSDIR/lib -I /var/lib/jenkins/jobs/0day_robot_upstream_build_ovn_from_pw/workspace/OVSDIR -I /var/lib/jenkins/jobs/0day_robot_upstream_build_ovn_from_pw/workspace/OVSDIR -I ./lib -I ./lib-Wstrict-prototypes -Wall -Wextra -Wno-sign-compare -Wpointer-arith -Wformat -Wformat-security -Wswitch-enum -Wunused-parameter -Wbad-function-cast -Wcast-align -Wstrict-prototypes -Wold-style-definition -Wmissing-prototypes -Wmissing-field-initializers -fno-strict-aliasing -Wshadow -Werror -Werror -g -O2 -MT controller/patch.o -MD -MP -MF $depbase.Tpo -c -o controller/patch.o controller/patch.c &&\ mv -f $depbase.Tpo $depbase.Po depbase=`echo controller/ovn-controller.o | sed 's|[^/]*$|.deps/&|;s|\.o$||'`;\ gcc -std=gnu99 -DHAVE_CONFIG_H -I. -I ./include -I ./include -I ./ovn -I ./include -I /var/lib/jenkins/jobs/0day_robot_upstream_build_ovn_from_pw/workspace/OVSDIR/include -I /var/lib/jenkins/jobs/0day_robot_upstream_build_ovn_from_pw/workspace/OVSDIR/include -I /var/lib/jenkins/jobs/0day_robot_upstream_build_ovn_from_pw/workspace/OVSDIR/lib -I /var/lib/jenkins/jobs/0day_robot_upstream_build_ovn_from_pw/workspace/OVSDIR/lib -I /var/lib/jenkins/jobs/0day_robot_upstream_build_ovn_from_pw/workspace/OVSDIR -I /var/lib/jenkins/jobs/0day_robot_upstream_build_ovn_from_pw/workspace/OVSDIR -I ./lib -I ./lib-Wstrict-prototypes -Wall -Wextra -Wno-sign-compare -Wpointer-arith -Wformat -Wformat-security -Wswitch-enum -Wunused-parameter -Wbad-function-cast -Wcast-align -Wstrict-prototypes -Wold-style-definition -Wmissing-prototypes -Wmissing-field-initializers -fno-strict-aliasing -Wshadow -Werror -Werror -g -O2 -MT controller/ovn-controller.o -MD -MP -MF $depbase.Tpo -c -o controller/ovn-controller.o controller/ovn-controller.c &&\ mv -f $depbase.Tpo $depbase.Po depbase=`echo controller/physical.o | sed 's|[^/]*$|.deps/&|;s|\.o$||'`;\ gcc -std=gnu99 -DHAVE_CONFIG_H -I. -I ./include -I ./include -I ./ovn -I ./include -I /var/lib/jenkins/jobs/0day_robot_upstream_build_ovn_from_pw/workspace/OVSDIR/include -I /var/lib/jenkins/jobs/0day_robot_upstream_build_ovn_from_pw/workspace/OVSDIR/include -I /var/lib/jenkins/jobs/0day_robot_upstream_build_ovn_from_pw/workspace/OVSDIR/lib -I /var/lib/jenkins/jobs/0day_robot_upstream_build_ovn_from_pw/workspace/OVSDIR/lib -I /var/lib/jenkins/jobs/0day_robot_upstream_build_ovn_from_pw/workspace/OVSDIR -I /var/lib/jenkins/jobs/0day_robot_upstream_build_ovn_from_pw/workspace/OVSDIR -I ./lib -I ./lib-Wstrict-prototypes -Wall -Wextra -Wno-sign-compare -Wpointer-arith -Wformat -Wformat-security -Wswitch-enum -Wunused-parameter -Wbad-function-cast -Wcast-align -Wstrict-prototypes -Wold-style-definition -Wmissing-prototypes -Wmissing-field-initializers -fno-strict-aliasing -Wshadow -Werror -Werror -g -O2 -MT controller/physical.o -MD -MP -MF $depbase.Tpo -c -o
Re: [ovs-dev] [PATCH ovn branch-20.06 04/15] ofctrl: Incremental processing for flow installation by tracking.
Bleep bloop. Greetings Frode Nordahl, I am a robot and I have tried out your patch. Thanks for your contribution. I encountered some error that I wasn't expecting. See the details below. git-am: error: patch fragment without header at line 127: @@ -861,6 +955,7 @@ ofctrl_check_and_add_flow(struct ovn_desired_flow_table *flow_table, error: could not build fake ancestor hint: Use 'git am --show-current-patch' to see the failed patch Patch failed at 0001 ofctrl: Incremental processing for flow installation by tracking. When you have resolved this problem, run "git am --continue". If you prefer to skip this patch, run "git am --skip" instead. To restore the original branch and stop patching, run "git am --abort". Please check this out. If you feel there has been an error, please email acon...@redhat.com Thanks, 0-day Robot ___ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev
[ovs-dev] [PATCH ovn branch-20.03 16/16] tests: Fix test "ovn -- Superseding ACLs with conjunction".
From: Dumitru Ceara The test was checking the output of "ovs-ofctl dump-flows" without taking into account that some fields don't have predictable values, e.g., hard_age. Instead, use ofctl_strip_all(). Fixes: 986b3d5e4ad6 ("ofctrl.c: Add a predictable resolution for conflicting flow actions.") Reported-by: Numan Siddique Signed-off-by: Dumitru Ceara Signed-off-by: Numan Siddique (cherry picked from commit 6e3d69e6b5153e26c869a03ec7dd1aaa40488005) (patch was adapted to branch-20.03 by checking table 44 not 45) Signed-off-by: Frode Nordahl --- tests/ovn.at | 72 ++-- 1 file changed, 36 insertions(+), 36 deletions(-) diff --git a/tests/ovn.at b/tests/ovn.at index 55d4784b7..7cda84428 100644 --- a/tests/ovn.at +++ b/tests/ovn.at @@ -12653,16 +12653,16 @@ 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=45 | \ -grep "priority=1003" | awk '{print $7 " " $8}' | \ +AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=44 | ofctl_strip_all | \ +grep "priority=1003" | \ sed 's/conjunction([[^)]]*)/conjunction()/g' | sort], [0], [dnl -priority=1003,conj_id=2,ip,metadata=0x1 actions=resubmit(,46) -priority=1003,conj_id=3,ip,metadata=0x1 actions=resubmit(,46) -priority=1003,ip,metadata=0x1,nw_dst=10.0.0.3 actions=conjunction(),conjunction() -priority=1003,ip,metadata=0x1,nw_dst=10.0.0.4 actions=conjunction(),conjunction() -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() -priority=1003,ip,metadata=0x1,nw_src=10.0.0.42 actions=conjunction() + table=44, priority=1003,conj_id=2,ip,metadata=0x1 actions=resubmit(,45) + table=44, priority=1003,conj_id=3,ip,metadata=0x1 actions=resubmit(,45) + table=44, priority=1003,ip,metadata=0x1,nw_dst=10.0.0.3 actions=conjunction(),conjunction() + table=44, priority=1003,ip,metadata=0x1,nw_dst=10.0.0.4 actions=conjunction(),conjunction() + table=44, priority=1003,ip,metadata=0x1,nw_src=10.0.0.1 actions=resubmit(,45) + table=44, priority=1003,ip,metadata=0x1,nw_src=10.0.0.2 actions=conjunction() + table=44, priority=1003,ip,metadata=0x1,nw_src=10.0.0.42 actions=conjunction() ]) # Traffic 10.0.0.1, 10.0.0.2 -> 10.0.0.3, 10.0.0.4 should be allowed. @@ -12699,16 +12699,16 @@ ovn-nbctl acl-del ls1 to-lport 3 'ip4.src==10.0.0.1 || ip4.src==10.0.0.1' ovn-nbctl --wait=hv sync # Check OVS flows, the second less restrictive allow ACL should have been installed. -AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=45 | \ -grep "priority=1003" | awk '{print $7 " " $8}' | \ +AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=44 | ofctl_strip_all | \ +grep "priority=1003" | \ sed 's/conjunction([[^)]]*)/conjunction()/g' | sort], [0], [dnl -priority=1003,conj_id=2,ip,metadata=0x1 actions=resubmit(,46) -priority=1003,conj_id=3,ip,metadata=0x1 actions=resubmit(,46) -priority=1003,ip,metadata=0x1,nw_dst=10.0.0.3 actions=conjunction(),conjunction() -priority=1003,ip,metadata=0x1,nw_dst=10.0.0.4 actions=conjunction(),conjunction() -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() -priority=1003,ip,metadata=0x1,nw_src=10.0.0.42 actions=conjunction() + table=44, priority=1003,conj_id=2,ip,metadata=0x1 actions=resubmit(,45) + table=44, priority=1003,conj_id=3,ip,metadata=0x1 actions=resubmit(,45) + table=44, priority=1003,ip,metadata=0x1,nw_dst=10.0.0.3 actions=conjunction(),conjunction() + table=44, priority=1003,ip,metadata=0x1,nw_dst=10.0.0.4 actions=conjunction(),conjunction() + table=44, priority=1003,ip,metadata=0x1,nw_src=10.0.0.1 actions=resubmit(,45) + table=44, priority=1003,ip,metadata=0x1,nw_src=10.0.0.2 actions=conjunction() + table=44, priority=1003,ip,metadata=0x1,nw_src=10.0.0.42 actions=conjunction() ]) # Remove the less restrictive allow ACL. @@ -12716,16 +12716,16 @@ 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=45 | \ -grep "priority=1003" | awk '{print $7 " " $8}' | \ +AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=44 | ofctl_strip_all | \ +grep "priority=1003" | \ sed 's/conjunction([[^)]]*)/conjunction()/g' | sort], [0], [dnl -priority=1003,conj_id=2,ip,metadata=0x1 actions=resubmit(,46) -priority=1003,conj_id=3,ip,metadata=0x1 actions=resubmit(,46) -priority=1003,ip,metadata=0x1,nw_dst=10.0.0.3 actions=conjunction(),conjunction() -priority=1003,ip,metadata=0x1,nw_dst=10.0.0.4 actions=conjunction(),conjunction() -priority=1003,ip,metadata=0x1,nw_src=10.0.0.1 actions=conjunction(),conjunction() -priority=1003,ip,metadata=0x1,nw_src=10.0.0.2 actions=conjunction()
[ovs-dev] [PATCH ovn branch-20.03 07/16] ofctrl.c: Fix duplicated flow handling in I-P while merging opposite changes.
From: Han Zhou In a scenario in I-P when a desired flow is removed and an exactly same flow is added back in the same iteration, the merge_tracked_flows() function will merge the operation without firing any OpenFlow action. However, if there are multiple desired flows (e.g. F1 and F2) matching the same installed flow, and if the one being re-added (say, F1) is the one currently installed in OVS, the current implementation will update the currently installed flow to F2 in the data structure while the actual OVS flow is not updated (still F1). So far there is still no problem, but the member desired_flow of the installed flow is pointing to the wrong desired flow. Now there is only one place where the desired_flow member is consulted, in update_installed_flows_by_track() for handling a tracked *modified* flow. In reality flow modification happens only when conjunction flows need to be combined, which would never happen together with the above scenario of merge_tracked_flows(). So this wrong desired_flow pointer doesn't cause any real problem yet. However, there is a place that can already utilize this active desired_flow information, which is when handling a tracked flow deletion in update_installed_flows_by_track(): we can check if the flow being deleted is the currently active one installed in OVS. If not, we don't need to send and OpenFlow modify to OVS. This optimization is added in this patch, apart from fixing the problem of merge_tracked_flows(). Without the fix, this optimization would cause the test case added in this patch fail. Fixes: f4e508dd7 ("ofctrl.c: Merge opposite changes of tracked flows before installing.") Acked-by: Dumitru Ceara Signed-off-by: Han Zhou (cherry picked from commit 9d2e8d32fb9865513b70408a665184a67564390d) Signed-off-by: Frode Nordahl --- controller/ofctrl.c | 28 +++- tests/ovn.at| 108 2 files changed, 134 insertions(+), 2 deletions(-) diff --git a/controller/ofctrl.c b/controller/ofctrl.c index b526c68f4..41495c41f 100644 --- a/controller/ofctrl.c +++ b/controller/ofctrl.c @@ -788,6 +788,24 @@ ofctrl_recv(const struct ofp_header *oh, enum ofptype type) } } +/* Returns true if a desired flow is active (the one currently installed + * among the list of desired flows that are linked to the same installed + * flow). */ +static inline bool +desired_flow_is_active(struct desired_flow *d) +{ +return (d->installed_flow && d->installed_flow->desired_flow == d); +} + +/* Set a desired flow as the active one among the list of desired flows + * that are linked to the same installed flow. */ +static inline void +desired_flow_set_active(struct desired_flow *d) +{ +ovs_assert(d->installed_flow); +d->installed_flow->desired_flow = d; +} + static void link_installed_to_desired(struct installed_flow *i, struct desired_flow *d) { @@ -1679,6 +1697,8 @@ merge_tracked_flows(struct ovn_desired_flow_table *flow_table) /* del_f must have been installed, otherwise it should have been * removed during track_flow_add_or_modify. */ ovs_assert(del_f->installed_flow); + +bool del_f_was_active = desired_flow_is_active(del_f); if (!f->installed_flow) { /* f is not installed yet. */ struct installed_flow *i = del_f->installed_flow; @@ -1690,6 +1710,9 @@ merge_tracked_flows(struct ovn_desired_flow_table *flow_table) ovs_assert(f->installed_flow == del_f->installed_flow); unlink_installed_to_desired(del_f->installed_flow, del_f); } +if (del_f_was_active) { +desired_flow_set_active(f); +} hmap_remove(_flows, _f->match_hmap_node); ovs_list_remove(_f->track_list_node); desired_flow_destroy(del_f); @@ -1717,6 +1740,7 @@ update_installed_flows_by_track(struct ovn_desired_flow_table *flow_table, /* The desired flow was deleted */ if (f->installed_flow) { struct installed_flow *i = f->installed_flow; +bool was_active = desired_flow_is_active(f); unlink_installed_to_desired(i, f); if (!i->desired_flow) { @@ -1725,7 +1749,7 @@ update_installed_flows_by_track(struct ovn_desired_flow_table *flow_table, hmap_remove(_flows, >match_hmap_node); installed_flow_destroy(i); -} else { +} else if (was_active) { /* There are other desired flow(s) referencing this * installed flow, so update the OVS flow for the new * active flow (at least the cookie will be different, @@ -1749,7 +1773,7 @@ update_installed_flows_by_track(struct ovn_desired_flow_table *flow_table, hmap_insert(_flows, _node->match_hmap_node,
[ovs-dev] [PATCH ovn branch-20.03 15/16] tests: Add ofctl_strip_all() to filter OVS flow outputs.
From: Dumitru Ceara Extend the already existing ofctl_strip() to also ignore n_packets, n_bytes, cookie. Use some helper functions from tests/system-userspace-packet-type-aware.at, which will be removed by a future commit. Signed-off-by: Dumitru Ceara Signed-off-by: Numan Siddique (cherry picked from commit 0879a0aa9f332bdc689769a1bc2f156f1c3149a5) Signed-off-by: Frode Nordahl --- tests/ofproto-macros.at | 23 ++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/tests/ofproto-macros.at b/tests/ofproto-macros.at index 6c4ff60e7..22999c1ca 100644 --- a/tests/ofproto-macros.at +++ b/tests/ofproto-macros.at @@ -1,12 +1,27 @@ m4_divert_push([PREPARE_TESTS]) [ +# Strips 'n_packets=...' from ovs-ofctl output. +strip_n_packets () { +sed 's/ n_packets=[0-9]*,//' +} + +# Strips 'n_bytes=...' from ovs-ofctl output. +strip_n_bytes () { +sed 's/ n_bytes=[0-9]*,//' +} + +# Strips 'cookie=...' from ovs-ofctl output. +strip_cookie () { +sed 's/ cookie=0x[0-9a-fA-F]*,//' +} + # Strips out uninteresting parts of ovs-ofctl output, as well as parts # that vary from one run to another. ofctl_strip () { sed ' s/ (xid=0x[0-9a-fA-F]*)// s/ duration=[0-9.]*s,// -s/ cookie=0x0,// +s/ cookie=0,// s/ table=0,// s/ n_packets=0,// s/ n_bytes=0,// @@ -19,6 +34,12 @@ s/dir\/[0-9]*\/br0.mgmt/dir\/\/br0.mgmt/ ' } +# Strips out uninteresting parts of ovs-ofctl output, including n_packets=.. +# n_bytes=.. +ofctl_strip_all () { +ofctl_strip | strip_n_packets | strip_n_bytes | strip_cookie +} + # Filter (multiline) vconn debug messages from ovs-vswitchd.log. # Use with vconn_sub() and ofctl_strip() print_vconn_debug () { awk -F\| < ovs-vswitchd.log ' -- 2.30.0 ___ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev
[ovs-dev] [PATCH ovn branch-20.03 14/16] ovn.at: Make some of the tests more predictable.
From: Dumitru Ceara Fix some of the race conditions that are present in the current OVN test suite. Signed-off-by: Dumitru Ceara Signed-off-by: Ben Pfaff (cherry picked from commit d6594a4695084e1b0f4fb3170547942876d3a81a) Signed-off-by: Frode Nordahl --- tests/ovn.at | 48 +++- 1 file changed, 27 insertions(+), 21 deletions(-) diff --git a/tests/ovn.at b/tests/ovn.at index b186adefb..55d4784b7 100644 --- a/tests/ovn.at +++ b/tests/ovn.at @@ -3417,6 +3417,7 @@ for i in 1 2 3; do ovn-nbctl lsp-set-addresses lp$i$j "f0:00:00:00:00:$i$j 192.168.0.$i$j" "$extra_addr" ovn-nbctl lsp-set-port-security lp$i$j "f0:00:00:00:00:$i$j 192.168.0.$i$j" "$extra_addr" fi +OVS_WAIT_UNTIL([test x`ovn-nbctl lsp-get-up lp$i$j` = xup]) done done @@ -12653,14 +12654,15 @@ 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=45 | \ -grep "priority=1003" | awk '{print $7 " " $8}' | sort], [0], [dnl +grep "priority=1003" | awk '{print $7 " " $8}' | \ +sed 's/conjunction([[^)]]*)/conjunction()/g' | sort], [0], [dnl priority=1003,conj_id=2,ip,metadata=0x1 actions=resubmit(,46) priority=1003,conj_id=3,ip,metadata=0x1 actions=resubmit(,46) -priority=1003,ip,metadata=0x1,nw_dst=10.0.0.3 actions=conjunction(2,1/2),conjunction(3,1/2) -priority=1003,ip,metadata=0x1,nw_dst=10.0.0.4 actions=conjunction(2,1/2),conjunction(3,1/2) +priority=1003,ip,metadata=0x1,nw_dst=10.0.0.3 actions=conjunction(),conjunction() +priority=1003,ip,metadata=0x1,nw_dst=10.0.0.4 actions=conjunction(),conjunction() 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) -priority=1003,ip,metadata=0x1,nw_src=10.0.0.42 actions=conjunction(3,2/2) +priority=1003,ip,metadata=0x1,nw_src=10.0.0.2 actions=conjunction() +priority=1003,ip,metadata=0x1,nw_src=10.0.0.42 actions=conjunction() ]) # Traffic 10.0.0.1, 10.0.0.2 -> 10.0.0.3, 10.0.0.4 should be allowed. @@ -12698,14 +12700,15 @@ ovn-nbctl --wait=hv sync # Check OVS flows, the second less restrictive allow ACL should have been installed. AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=45 | \ -grep "priority=1003" | awk '{print $7 " " $8}' | sort], [0], [dnl +grep "priority=1003" | awk '{print $7 " " $8}' | \ +sed 's/conjunction([[^)]]*)/conjunction()/g' | sort], [0], [dnl priority=1003,conj_id=2,ip,metadata=0x1 actions=resubmit(,46) priority=1003,conj_id=3,ip,metadata=0x1 actions=resubmit(,46) -priority=1003,ip,metadata=0x1,nw_dst=10.0.0.3 actions=conjunction(2,1/2),conjunction(3,1/2) -priority=1003,ip,metadata=0x1,nw_dst=10.0.0.4 actions=conjunction(2,1/2),conjunction(3,1/2) +priority=1003,ip,metadata=0x1,nw_dst=10.0.0.3 actions=conjunction(),conjunction() +priority=1003,ip,metadata=0x1,nw_dst=10.0.0.4 actions=conjunction(),conjunction() 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) -priority=1003,ip,metadata=0x1,nw_src=10.0.0.42 actions=conjunction(3,2/2) +priority=1003,ip,metadata=0x1,nw_src=10.0.0.2 actions=conjunction() +priority=1003,ip,metadata=0x1,nw_src=10.0.0.42 actions=conjunction() ]) # Remove the less restrictive allow ACL. @@ -12714,14 +12717,15 @@ 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=45 | \ -grep "priority=1003" | awk '{print $7 " " $8}' | sort], [0], [dnl +grep "priority=1003" | awk '{print $7 " " $8}' | \ +sed 's/conjunction([[^)]]*)/conjunction()/g' | sort], [0], [dnl priority=1003,conj_id=2,ip,metadata=0x1 actions=resubmit(,46) priority=1003,conj_id=3,ip,metadata=0x1 actions=resubmit(,46) -priority=1003,ip,metadata=0x1,nw_dst=10.0.0.3 actions=conjunction(2,1/2),conjunction(3,1/2) -priority=1003,ip,metadata=0x1,nw_dst=10.0.0.4 actions=conjunction(2,1/2),conjunction(3,1/2) -priority=1003,ip,metadata=0x1,nw_src=10.0.0.1 actions=conjunction(2,2/2),conjunction(3,2/2) -priority=1003,ip,metadata=0x1,nw_src=10.0.0.2 actions=conjunction(2,2/2) -priority=1003,ip,metadata=0x1,nw_src=10.0.0.42 actions=conjunction(3,2/2) +priority=1003,ip,metadata=0x1,nw_dst=10.0.0.3 actions=conjunction(),conjunction() +priority=1003,ip,metadata=0x1,nw_dst=10.0.0.4 actions=conjunction(),conjunction() +priority=1003,ip,metadata=0x1,nw_src=10.0.0.1 actions=conjunction(),conjunction() +priority=1003,ip,metadata=0x1,nw_src=10.0.0.2 actions=conjunction() +priority=1003,ip,metadata=0x1,nw_src=10.0.0.42 actions=conjunction() ]) # Traffic 10.0.0.1, 10.0.0.2 -> 10.0.0.3, 10.0.0.4 should be allowed. @@ -12752,14 +12756,15 @@ ovn-nbctl --wait=hv sync # Check OVS flows, the less restrictive flows should have been installed. AT_CHECK([as hv1 ovs-ofctl dump-flows
[ovs-dev] [PATCH ovn branch-20.03 05/16] ofctrl: Incremental processing for flow installation by tracking.
From: Han Zhou With incremental processing for flow computation, the bottle neck of ovn-controller in large scale environment is in the flow installation (ofctrl_put()), which does full comparison between the two big flow tables: the installed flows and desired flows. This patch implements tracking desired flow changes when flows are incrementally computed by I-P engine, and then incrementally processing the flow installation using the tracked information in ofctrl_put(). It falls back to the full comparison whenever tracking information is unavailable, e.g. when I-P engine triggers full recompute. In ovn-scale-test with 3000 HVs and 30k lports, the end-to-end latency between the moment a lflow is updated in SB DB and the moment when all the 3K HVs complete OVS flow updating has reduced around 60% (from 1s to 400ms). Below is the perf result for a ovn-controller processing a new port-binding: Beore: + 96.76% 0.00% ovn-controller [unknown] [k] 0x + 90.21% 0.00% ovn-controller ovn-controller [.] main + 39.93% 1.19% ovn-controller ovn-controller [.] ofctrl_put + 31.27%12.47% ovn-controller ovn-controller [.] ovn_flow_lookup + 22.12% 3.12% ovn-controller ovn-controller [.] encaps_run + 18.69% 2.77% ovn-controller ovn-controller [.] minimatch_equal + 17.63% 4.11% ovn-controller ovn-controller [.] patch_run + 15.91% 0.00% ovn-controller ovn-controller [.] add_bridge_mappings (inlined) + 14.03%12.08% ovn-controller ovn-controller [.] minimask_equal + 12.41% 0.00% ovn-controller ovn-controller [.] chassis_tunnel_add (inlined) + 11.40% 0.00% ovn-controller ovn-controller [.] tunnel_add (inlined) After: + 94.59% 0.00% ovn-controller [unknown] [k] 0x + 83.56% 0.09% ovn-controller ovn-controller [.] main + 35.37% 3.13% ovn-controller ovn-controller [.] encaps_run + 27.54% 7.53% ovn-controller ovn-controller [.] patch_run + 24.86% 0.00% ovn-controller ovn-controller [.] add_bridge_mappings (inlined) + 20.01% 0.00% ovn-controller ovn-controller [.] chassis_tunnel_add (inlined) + 18.51% 0.00% ovn-controller ovn-controller [.] tunnel_add (inlined) + 14.08% 0.17% ovn-controller ovn-controller [.] physical_run + 11.37%11.28% ovn-controller ovn-controller [.] next_real_row + 10.50% 2.59% ovn-controller ovn-controller [.] consider_port_binding ... +2.14% 0.32% ovn-controller ovn-controller [.] ofctrl_put ▒ Before the optimization, ofctrl_put took 40% of CPU, and now it disappears from the hot spots. Acked-by: Mark Michelson Signed-off-by: Han Zhou (cherry picked from commit 6f0b1e02d9ab3a94048c4818f2d382938cad4b71) Signed-off-by: Frode Nordahl --- controller/ofctrl.c | 289 +++- controller/ofctrl.h | 6 +- 2 files changed, 240 insertions(+), 55 deletions(-) diff --git a/controller/ofctrl.c b/controller/ofctrl.c index 6de14ac9d..3ff8604b1 100644 --- a/controller/ofctrl.c +++ b/controller/ofctrl.c @@ -101,6 +101,39 @@ struct ovn_flow { * * The links are updated whenever there is a change in desired flows, which is * usually triggered by a SB data change in I-P engine. + * + * ** Tracking ** + * + * A desired flow can be tracked - listed in ovn_desired_flow_table's + * tracked_flows. + * + * Tracked flows is initially empty, and stays empty after the first run of I-P + * engine when installed flows are initially populated. After that, flow + * changes are tracked when I-P engine incrementally computes flow changes. + * Tracked flows are then processed and removed completely in ofctrl_put. + * ("processed" means OpenFlow change messages are composed and sent/queued to + * OVS, which ensures flows in OVS is always in sync (eventually) with the + * installed flows table). + * + * In case of full recompute of I-P engine, tracked flows are not + * added/removed, and ofctrl_put will not rely on tracked flows. (It is I-P + * engine's responsibility to ensure the tracked flows are cleared before + * recompute). + * + * Tracked flows can be preserved across multiple I-P engine runs - if in some + * iterations ofctrl_put() is skipped. Tracked flows are cleared only when it + * is consumed or when flow recompute happens. + * + * The "change_tracked" member of desired flow table maintains the status of + * whether flow changes are tracked or not. It is always set to true when + * ofctrl_put is completed, and transition to false whenever + * ovn_desired_flow_table_clear is called. + * + * NOTE: A tracked flow is just a reference to a desired
[ovs-dev] [PATCH ovn branch-20.03 13/16] ofctrl.c: Add a predictable resolution for conflicting flow actions.
From: Dumitru Ceara 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 ensure that all desired flows refering the same installed flow are partially sorted in the following way: - first all flows with action "allow". - then all flows with action "drop". - then a single flow with action "conjunction" (resulting from merging all flows with the same match and action conjunction). This ensures that "allow" flows have precedence over "drop" flows which in turn have precedence over "conjunction" flows. Essentially less restrictive flows are always preferred over more restrictive flows whenever a match conflict happens. CC: Daniel Alvarez Reported-at: https://bugzilla.redhat.com/1871931 Signed-off-by: Dumitru Ceara Acked-by: Mark Gray Signed-off-by: Han Zhou (cherry picked from commit 986b3d5e4ad6f05245d021ba699c957246294a22) Signed-off-by: Frode Nordahl --- controller/ofctrl.c | 74 +-- tests/ovn.at| 214 2 files changed, 283 insertions(+), 5 deletions(-) diff --git a/controller/ofctrl.c b/controller/ofctrl.c index f06b68b78..60ce6f1c2 100644 --- a/controller/ofctrl.c +++ b/controller/ofctrl.c @@ -188,6 +188,14 @@ struct sb_flow_ref { * relationship is 1 to N. A link is added when a flow addition is processed. * A link is removed when a flow deletion is processed, the desired flow * table is cleared, or the installed flow table is cleared. + * + * To ensure predictable behavior, the list of desired flows is maintained + * partially sorted in the following way (from least restrictive to most + * restrictive wrt. match): + * - allow flows without action conjunction. + * - drop flows without action conjunction. + * - a single flow with action conjunction. + * * The first desired_flow in the list is the active one, the one that is * actually installed. */ @@ -795,6 +803,12 @@ ofctrl_recv(const struct ofp_header *oh, enum ofptype type) } } +static bool +flow_action_has_drop(const struct ovn_flow *f) +{ +return f->ofpacts_len == 0; +} + static bool flow_action_has_conj(const struct ovn_flow *f) { @@ -808,6 +822,33 @@ flow_action_has_conj(const struct ovn_flow *f) return false; } +static bool +flow_action_has_allow(const struct ovn_flow *f) +{ +return !flow_action_has_drop(f) && !flow_action_has_conj(f); +} + +/* Returns true if flow 'a' is preferred over flow 'b'. */ +static bool +flow_is_preferred(const struct ovn_flow *a, const struct ovn_flow *b) +{ +if (flow_action_has_allow(b)) { +return false; +} +if (flow_action_has_allow(a)) { +return true; +} +if (flow_action_has_drop(b)) { +return false; +} +if (flow_action_has_drop(a)) { +return true; +} + +/* Flows 'a' and 'b' should never both have action conjunction. */ +OVS_NOT_REACHED(); +} + /* Adds the desired flow to the list of desired flows that have same match * conditions as the installed flow. * @@ -820,8 +861,18 @@ flow_action_has_conj(const struct ovn_flow *f) static bool link_installed_to_desired(struct installed_flow *i, struct desired_flow *d) { +struct desired_flow *f; + +/* Find first 'f' such that 'd' is preferred over 'f'. If no such desired + * flow exists then 'f' will point after the last element of
[ovs-dev] [PATCH ovn branch-20.03 11/16] ofctrl.c: Simplify active desired flow selection.
From: Dumitru Ceara Always consider the first "desired flow" in the list of flows that refer an "installed flow" as the active flow. This simplifies the logic of the flow update code and is used in a further commit to implement a partial ordering of desired flows within installed flows. Signed-off-by: Dumitru Ceara Signed-off-by: Han Zhou (cherry picked from commit 107bb25029350bd0f7dfeeb0ef3053adbd504e3e) Signed-off-by: Frode Nordahl --- controller/ofctrl.c | 91 ++--- 1 file changed, 36 insertions(+), 55 deletions(-) diff --git a/controller/ofctrl.c b/controller/ofctrl.c index 843c7b2be..890ab4bb5 100644 --- a/controller/ofctrl.c +++ b/controller/ofctrl.c @@ -188,6 +188,8 @@ struct sb_flow_ref { * relationship is 1 to N. A link is added when a flow addition is processed. * A link is removed when a flow deletion is processed, the desired flow * table is cleared, or the installed flow table is cleared. + * The first desired_flow in the list is the active one, the one that is + * actually installed. */ struct installed_flow { struct ovn_flow flow; @@ -199,11 +201,6 @@ struct installed_flow { * installed flow, e.g. when there are conflict/duplicated ACLs that * generates same match conditions). */ struct ovs_list desired_refs; - -/* The corresponding flow in desired table. It must be one of the flows in - * desired_refs list. If there are more than one flows in references list, - * this is the one that is actually installed. */ -struct desired_flow *desired_flow; }; typedef bool @@ -231,6 +228,7 @@ static struct installed_flow *installed_flow_lookup( const struct ovn_flow *target); static void installed_flow_destroy(struct installed_flow *); static struct installed_flow *installed_flow_dup(struct desired_flow *); +static struct desired_flow *installed_flow_get_active(struct installed_flow *); static uint32_t ovn_flow_match_hash(const struct ovn_flow *); static char *ovn_flow_to_string(const struct ovn_flow *); @@ -796,24 +794,6 @@ ofctrl_recv(const struct ofp_header *oh, enum ofptype type) log_openflow_rl(, VLL_DBG, oh, "OpenFlow packet ignored"); } } - -/* Returns true if a desired flow is active (the one currently installed - * among the list of desired flows that are linked to the same installed - * flow). */ -static inline bool -desired_flow_is_active(struct desired_flow *d) -{ -return (d->installed_flow && d->installed_flow->desired_flow == d); -} - -/* Set a desired flow as the active one among the list of desired flows - * that are linked to the same installed flow. */ -static inline void -desired_flow_set_active(struct desired_flow *d) -{ -ovs_assert(d->installed_flow); -d->installed_flow->desired_flow = d; -} static bool flow_action_has_conj(const struct ovn_flow *f) @@ -831,27 +811,22 @@ flow_action_has_conj(const struct ovn_flow *f) /* Adds the desired flow to the list of desired flows that have same match * conditions as the installed flow. * - * If the newly added desired flow is the first one in the list, it is also set - * as the active one. - * * It is caller's responsibility to make sure the link between the pair didn't - * exist before. */ -static void + * exist before. + * + * Returns true if the newly added desired flow is selected to be the active + * one. + */ +static bool link_installed_to_desired(struct installed_flow *i, struct desired_flow *d) { -ovs_assert(i->desired_flow != d); -if (ovs_list_is_empty(>desired_refs)) { -ovs_assert(!i->desired_flow); -i->desired_flow = d; -} -ovs_list_insert(>desired_refs, >installed_ref_list_node); d->installed_flow = i; +ovs_list_push_back(>desired_refs, >installed_ref_list_node); +return installed_flow_get_active(i) == d; } /* Replaces 'old_desired' with 'new_desired' in the list of desired flows * that have same match conditions as the installed flow. - * - * If 'old_desired' was the active flow, 'new_desired' becomes the active one. */ static void replace_installed_to_desired(struct installed_flow *i, @@ -863,24 +838,22 @@ replace_installed_to_desired(struct installed_flow *i, _desired->installed_ref_list_node); old_desired->installed_flow = NULL; new_desired->installed_flow = i; -if (i->desired_flow == old_desired) { -i->desired_flow = new_desired; -} } -static void +/* Removes the desired flow from the list of desired flows that have the same + * match conditions as the installed flow. + * + * Returns true if the desired flow was the previously active flow. + */ +static bool unlink_installed_to_desired(struct installed_flow *i, struct desired_flow *d) { -ovs_assert(i && i->desired_flow && !ovs_list_is_empty(>desired_refs)); +struct desired_flow *old_active = installed_flow_get_active(i); + ovs_assert(d && d->installed_flow == i);
[ovs-dev] [PATCH ovn branch-20.03 12/16] ofctrl.c: Always log the most recent flow changes.
From: Dumitru Ceara Fixes: 6f0b1e02d9ab ("ofctrl: Incremental processing for flow installation by tracking.") Signed-off-by: Dumitru Ceara Signed-off-by: Han Zhou (cherry picked from commit 33c15c145988daa6172928dc870f3a0225515f50) Signed-off-by: Frode Nordahl --- controller/ofctrl.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/controller/ofctrl.c b/controller/ofctrl.c index 890ab4bb5..f06b68b78 100644 --- a/controller/ofctrl.c +++ b/controller/ofctrl.c @@ -1833,8 +1833,8 @@ update_installed_flows_by_track(struct ovn_desired_flow_table *flow_table, * installed flow, so update the OVS flow for the new * active flow (at least the cookie will be different, * even if the actions are the same). */ -ovn_flow_log(>flow, "updating installed (tracked)"); installed_flow_mod(>flow, >flow, msgs); +ovn_flow_log(>flow, "updating installed (tracked)"); } } desired_flow_destroy(f); @@ -1854,8 +1854,8 @@ update_installed_flows_by_track(struct ovn_desired_flow_table *flow_table, } else if (installed_flow_get_active(i) == f) { /* The installed flow is installed for f, but f has change * tracked, so it must have been modified. */ -ovn_flow_log(>flow, "updating installed (tracked)"); installed_flow_mod(>flow, >flow, msgs); +ovn_flow_log(>flow, "updating installed (tracked)"); } else { /* Adding a new flow that conflicts with an existing installed * flow, so just add it to the link. */ -- 2.30.0 ___ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev
[ovs-dev] [PATCH ovn branch-20.03 08/16] ofctrl.c: Avoid repeatedly linking an installed flow and a desired flow.
From: Han Zhou In update_installed_flows_by_compare() there are two loops. The first loop iterates the installed flows and find its peer in desired flows to: 1. uninstall flows that are not needed anymore 2. update flows if needed At the same time, it links the desired flow found for the installed flow which also set the desired flow as the current active installed flow. The second loop iterates the desired flows and find its peer in installed flows to install missing flows. At the same time it will detect if there are conflict desired flows matching same installed flow then just link them. However, currently in the second loop, it blindly link the desired flows to the installed flows, without checking if it is already linked in the first loop. Lucky enough, this won't cause any real problem so far, because when there are conflict flows, the one found in the first loop will be set as active in the installed_flow, and in the function link_installed_to_desired() checks if it is already the active desired flow it just does nothing but return. However, the check in the link_installed_to_desired() is confusing because a desired_flow may be linked to the installed_flow already but not the active flow, and the check is insufficient. It should be rather an assertion and let the caller ensure that a pair of desired_flow and installed_flow is never linked twice. For the above reason, this patch does the following changes: 1. Removes the check in link_installed_to_desired() and convert it to an assert. 2. Before calling link_installed_to_desired() in the above mentioned loop, check if the desired flow is already installed. Acked-by: Dumitru Ceara Signed-off-by: Han Zhou (cherry picked from commit 7cab7bd1268ba67429954da4f73de91090acf779) Signed-off-by: Frode Nordahl --- controller/ofctrl.c | 19 ++- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/controller/ofctrl.c b/controller/ofctrl.c index 41495c41f..70ec3e82b 100644 --- a/controller/ofctrl.c +++ b/controller/ofctrl.c @@ -806,13 +806,18 @@ desired_flow_set_active(struct desired_flow *d) d->installed_flow->desired_flow = d; } +/* Adds the desired flow to the list of desired flows that have same match + * conditions as the installed flow. + * + * If the newly added desired flow is the first one in the list, it is also set + * as the active one. + * + * It is caller's responsibility to make sure the link between the pair didn't + * exist before. */ static void link_installed_to_desired(struct installed_flow *i, struct desired_flow *d) { -if (i->desired_flow == d) { -return; -} - +ovs_assert(i->desired_flow != d); if (ovs_list_is_empty(>desired_refs)) { ovs_assert(!i->desired_flow); i->desired_flow = d; @@ -1644,8 +1649,12 @@ 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(_flows, >match_hmap_node, i->flow.hash); +link_installed_to_desired(i, d); +} else if (!d->installed_flow) { +/* This is a desired_flow that conflicts with one installed + * previously but not linked yet. */ +link_installed_to_desired(i, d); } -link_installed_to_desired(i, d); } } -- 2.30.0 ___ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev
[ovs-dev] [PATCH ovn branch-20.03 02/16] Revert "Manage ARP process locally in a DVR scenario"
From: Lorenzo Bianconi This reverts commit c0bf32d72f8b893bbe3cb64912b0fd259d71555f. Signed-off-by: Lorenzo Bianconi Signed-off-by: Han Zhou (cherry picked from commit d9ed450713eda62af1bec5009694b2d206c9f435) Signed-off-by: Frode Nordahl --- northd/ovn-northd.8.xml | 37 ++-- northd/ovn-northd.c | 53 + tests/ovn.at| 14 --- 3 files changed, 3 insertions(+), 101 deletions(-) diff --git a/northd/ovn-northd.8.xml b/northd/ovn-northd.8.xml index f5a14d26e..4b8264bb4 100644 --- a/northd/ovn-northd.8.xml +++ b/northd/ovn-northd.8.xml @@ -2484,46 +2484,13 @@ output; - - - For distributed logical routers where one of the logical router ports - specifies a redirect-chassis, a priority-400 logical - flow for each dnat_and_snat NAT rules configured. - These flows will allow to properly forward traffic to the external - connections if available and avoid sending it through the tunnel. - Assuming the following NAT rule has been configured: - - - -external_ip = A; -external_mac = B; -logical_ip = C; - - - - the following action will be applied: - - - -ip.ttl--; -reg0 = ip.dst; -reg1 = A; -eth.src = B; -outport = router-port; -next; - - - - IPv4 routing table. For each route to IPv4 network N with netmask M, on router port P with IP address A and Ethernet address E, a logical flow with match ip4.dst == - N/M, whose priority is 400 - + the number of 1-bits in M if the router port is not a - distributed gateway port, else the priority is the number of + N/M, whose priority is the number of 1-bits in M, has the following actions: @@ -2922,7 +2889,7 @@ icmp4 { For each NAT rule in the OVN Northbound database that can -be handled in a distributed manner, a priority-200 logical +be handled in a distributed manner, a priority-100 logical flow with match ip4.src == B outport == GW, where GW is the logical router distributed gateway port, with actions diff --git a/northd/ovn-northd.c b/northd/ovn-northd.c index 62911986b..2453dca08 100644 --- a/northd/ovn-northd.c +++ b/northd/ovn-northd.c @@ -7060,8 +7060,6 @@ build_routing_policy_flow(struct hmap *lflows, struct ovn_datapath *od, ds_destroy(); } -/* default logical flow prioriry for distributed routes */ -#define DROUTE_PRIO 400 struct parsed_route { struct ovs_list list_node; struct v46_ip prefix; @@ -7449,40 +7447,6 @@ build_ecmp_route_flow(struct hmap *lflows, struct ovn_datapath *od, ds_destroy(); } -static void -add_distributed_routes(struct hmap *lflows, struct ovn_datapath *od) -{ -struct ds actions = DS_EMPTY_INITIALIZER; -struct ds match = DS_EMPTY_INITIALIZER; - -for (size_t i = 0; i < od->nbr->n_nat; i++) { -const struct nbrec_nat *nat = od->nbr->nat[i]; - -if (strcmp(nat->type, "dnat_and_snat") || -!nat->external_mac) { -continue; -} - -bool is_ipv4 = strchr(nat->logical_ip, '.') ? true : false; -ds_put_format(, "ip%s.src == %s && is_chassis_resident(\"%s\")", - is_ipv4 ? "4" : "6", nat->logical_ip, - nat->logical_port); -char *prefix = is_ipv4 ? "" : "xx"; -ds_put_format(, "outport = %s; eth.src = %s; " - "%sreg0 = ip%s.dst; %sreg1 = %s; next;", - od->l3dgw_port->json_key, nat->external_mac, - prefix, is_ipv4 ? "4" : "6", - prefix, nat->external_ip); -ovn_lflow_add(lflows, od, S_ROUTER_IN_IP_ROUTING, DROUTE_PRIO, - ds_cstr(), ds_cstr()); -ds_clear(); -ds_clear(); -} - -ds_destroy(); -ds_destroy(); -} - static void add_route(struct hmap *lflows, const struct ovn_port *op, const char *lrp_addr_s, const char *network_s, int plen, @@ -7504,12 +7468,6 @@ add_route(struct hmap *lflows, const struct ovn_port *op, } build_route_match(op_inport, network_s, plen, is_src_route, is_ipv4, , ); -/* traffic for internal IPs of logical switch ports must be sent to - * the gw controller through the overlay tunnels - */ -if (op->nbrp && !op->nbrp->n_gateway_chassis) { -priority += DROUTE_PRIO; -} struct ds actions = DS_EMPTY_INITIALIZER; ds_put_format(, "ip.ttl--; "REG_ECMP_GROUP_ID" = 0; %sreg0 = ", @@ -9119,7 +9077,7 @@ build_lrouter_flows(struct hmap *datapaths, struct hmap *ports, nat->logical_ip, od->l3dgw_port->json_key); ovn_lflow_add_with_hint(lflows, od, S_ROUTER_IN_GW_REDIRECT,
[ovs-dev] [PATCH ovn branch-20.03 09/16] ofctrl.c: Only merge actions for conjunctive flows.
From: Dumitru Ceara In ofctrl_add_or_append_flow() when merging flow actions make sure we only do that for conjunctive flows. All other actions can not be merged with action "conjunction". CC: Mark Michelson Fixes: e659bab31a91 ("Combine conjunctions with identical matches into one flow.") Signed-off-by: Dumitru Ceara Signed-off-by: Han Zhou (cherry picked from commit dadae4f800ccb1f2759378f0bd804dd002e31605) Signed-off-by: Frode Nordahl --- controller/ofctrl.c | 124 +++- 1 file changed, 99 insertions(+), 25 deletions(-) diff --git a/controller/ofctrl.c b/controller/ofctrl.c index 70ec3e82b..5322d5148 100644 --- a/controller/ofctrl.c +++ b/controller/ofctrl.c @@ -206,6 +206,9 @@ struct installed_flow { struct desired_flow *desired_flow; }; +typedef bool +(*desired_flow_match_cb)(const struct desired_flow *candidate, + const void *arg); static struct desired_flow *desired_flow_alloc( uint8_t table_id, uint16_t priority, @@ -213,9 +216,15 @@ static struct desired_flow *desired_flow_alloc( const struct match *match, const struct ofpbuf *actions); static struct desired_flow *desired_flow_lookup( +struct ovn_desired_flow_table *, +const struct ovn_flow *target); +static struct desired_flow *desired_flow_lookup_check_uuid( struct ovn_desired_flow_table *, const struct ovn_flow *target, -const struct uuid *sb_uuid); +const struct uuid *); +static struct desired_flow *desired_flow_lookup_conjunctive( +struct ovn_desired_flow_table *, +const struct ovn_flow *target); static void desired_flow_destroy(struct desired_flow *); static struct installed_flow *installed_flow_lookup( @@ -806,6 +815,19 @@ desired_flow_set_active(struct desired_flow *d) d->installed_flow->desired_flow = d; } +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; +} + /* Adds the desired flow to the list of desired flows that have same match * conditions as the installed flow. * @@ -962,7 +984,7 @@ ofctrl_check_and_add_flow(struct ovn_desired_flow_table *flow_table, struct desired_flow *f = desired_flow_alloc(table_id, priority, cookie, match, actions); -if (desired_flow_lookup(flow_table, >flow, sb_uuid)) { +if (desired_flow_lookup_check_uuid(flow_table, >flow, sb_uuid)) { if (log_duplicate_flow) { static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 5); if (!VLOG_DROP_DBG()) { @@ -1002,14 +1024,15 @@ ofctrl_add_or_append_flow(struct ovn_desired_flow_table *desired_flows, const struct ofpbuf *actions, const struct uuid *sb_uuid) { -struct desired_flow *f = desired_flow_alloc(table_id, priority, cookie, -match, actions); - struct desired_flow *existing; -existing = desired_flow_lookup(desired_flows, >flow, NULL); +struct desired_flow *f; + +f = desired_flow_alloc(table_id, priority, cookie, match, actions); +existing = desired_flow_lookup_conjunctive(desired_flows, >flow); 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 and action + * 'conjunction'. Append the action to that flow rather than + * adding a new flow. */ uint64_t compound_stub[64 / 8]; struct ofpbuf compound; @@ -1248,15 +1271,11 @@ installed_flow_dup(struct desired_flow *src) return dst; } -/* Finds and returns a desired_flow in 'flow_table' whose key is identical to - * 'target''s key, or NULL if there is none. - * - * If sb_uuid is not NULL, the function will also check if the found flow is - * referenced by the sb_uuid. */ static struct desired_flow * -desired_flow_lookup(struct ovn_desired_flow_table *flow_table, -const struct ovn_flow *target, -const struct uuid *sb_uuid) +desired_flow_lookup__(struct ovn_desired_flow_table *flow_table, + const struct ovn_flow *target, + desired_flow_match_cb match_cb, + const void *arg) { struct desired_flow *d; HMAP_FOR_EACH_WITH_HASH (d, match_hmap_node, target->hash, @@ -1265,20 +1284,76 @@ desired_flow_lookup(struct ovn_desired_flow_table *flow_table, if (f->table_id == target->table_id && f->priority == target->priority && minimatch_equal(>match, >match)) { -if (!sb_uuid) { + +if (!match_cb || match_cb(d, arg)) { return d;
[ovs-dev] [PATCH ovn branch-20.03 10/16] ofctrl.c: Do not change flow ordering when merging opposite changes.
From: Dumitru Ceara Instead of removing the old desired flow from the list and inserting the new one at the end we now directly replace the old flow with the new one while maintaining the same ordering. For now order of the flows is not relevant but further commits require maintaining the order of desired flows. Signed-off-by: Dumitru Ceara Signed-off-by: Han Zhou (cherry picked from commit e49ce9a33f38f29c44e3c30afcc189b5f6a9ef8e) Signed-off-by: Frode Nordahl --- controller/ofctrl.c | 28 +--- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/controller/ofctrl.c b/controller/ofctrl.c index 5322d5148..843c7b2be 100644 --- a/controller/ofctrl.c +++ b/controller/ofctrl.c @@ -848,6 +848,26 @@ link_installed_to_desired(struct installed_flow *i, struct desired_flow *d) d->installed_flow = i; } +/* Replaces 'old_desired' with 'new_desired' in the list of desired flows + * that have same match conditions as the installed flow. + * + * If 'old_desired' was the active flow, 'new_desired' becomes the active one. + */ +static void +replace_installed_to_desired(struct installed_flow *i, + struct desired_flow *old_desired, + struct desired_flow *new_desired) +{ +ovs_assert(old_desired->installed_flow == i); +ovs_list_replace(_desired->installed_ref_list_node, + _desired->installed_ref_list_node); +old_desired->installed_flow = NULL; +new_desired->installed_flow = i; +if (i->desired_flow == old_desired) { +i->desired_flow = new_desired; +} +} + static void unlink_installed_to_desired(struct installed_flow *i, struct desired_flow *d) { @@ -1781,21 +1801,15 @@ merge_tracked_flows(struct ovn_desired_flow_table *flow_table) * removed during track_flow_add_or_modify. */ ovs_assert(del_f->installed_flow); -bool del_f_was_active = desired_flow_is_active(del_f); if (!f->installed_flow) { /* f is not installed yet. */ -struct installed_flow *i = del_f->installed_flow; -unlink_installed_to_desired(i, del_f); -link_installed_to_desired(i, f); +replace_installed_to_desired(del_f->installed_flow, del_f, f); } else { /* f has been installed before, and now was updated to exact * the same flow as del_f. */ ovs_assert(f->installed_flow == del_f->installed_flow); unlink_installed_to_desired(del_f->installed_flow, del_f); } -if (del_f_was_active) { -desired_flow_set_active(f); -} hmap_remove(_flows, _f->match_hmap_node); ovs_list_remove(_f->track_list_node); desired_flow_destroy(del_f); -- 2.30.0 ___ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev
[ovs-dev] [PATCH ovn branch-20.03 01/16] ovn-ctl: Handle cluster db upgrades for run_(nb/sb)_ovsdb
From: Numan Siddique when ovn-ctl run_(nb_sb)_ovsdb is called, the ovsdb-server is started without passing --detach and --monoitor and the process is exec'd. For cluster mode, upgrade_cluster is never called and hence the dbs are not upraded to new schema. CMS has to handle the db upgrade separately. This patch handles the db upgrade by starting ovsdb-server in background and then waits on ovsdb-server to complete. Reported-at: https://bugzilla.redhat.com/show_bug.cgi?id=1868392 Acked-by: Mark Michelson Signed-off-by: Numan Siddique (cherry picked from commit 67e2f386cc838d0b0f9b4b5da7fe611e1113b70c) Signed-off-by: Frode Nordahl --- utilities/ovn-ctl | 20 +++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/utilities/ovn-ctl b/utilities/ovn-ctl index c7cb42bc1..7285c0533 100755 --- a/utilities/ovn-ctl +++ b/utilities/ovn-ctl @@ -284,7 +284,21 @@ $cluster_remote_port set "$@" --sync-from=`cat $active_conf_file` fi -"$@" "$file" +local run_ovsdb_in_bg="no" +local process_id= +if test X$detach = Xno && test $mode = cluster && test -z "$cluster_remote_addr" ; then +# When detach is no (for run_nb_ovsdb/run_sb_ovsdb commands) +# we want to run ovsdb-server in background rather than running it in +# foreground so that the OVN dbs are upgraded for the cluster mode. +# Otherwise, CMS has to take the responsibility of upgrading the dbs. +# Note: We run only the ovsdb-server in backgroud which created the +# cluster (i.e cluster_remote_addr is not set.). +run_ovsdb_in_bg="yes" +"$@" $file & +process_id=$! +else +start_wrapped_daemon "$wrapper" ovsdb-$db "" "$@" "$file" +fi # Initialize the database if it's running standalone, # active-passive, or is the first server in a cluster. @@ -295,6 +309,10 @@ $cluster_remote_port if test $mode = cluster; then upgrade_cluster "$schema" "unix:$sock" fi + +if test $run_ovsdb_in_bg = yes; then +wait $process_id +fi } start_nb_ovsdb() { -- 2.30.0 ___ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev
[ovs-dev] [PATCH ovn branch-20.03 06/16] ofctrl.c: Merge opposite changes of tracked flows before installing.
From: Han Zhou This patch optimizes the previous patch that incrementally processes flow installation by merging the "add-after-delete" flow changes as much as possible to avoid unnecessary OpenFlow updates. Acked-by: Mark Michelson Signed-off-by: Han Zhou (cherry picked from commit f4e508dd7a6cfbfc2e3250a8c11a8d0fdc1dfdd0) Signed-off-by: Frode Nordahl --- controller/ofctrl.c | 74 + 1 file changed, 74 insertions(+) diff --git a/controller/ofctrl.c b/controller/ofctrl.c index 3ff8604b1..b526c68f4 100644 --- a/controller/ofctrl.c +++ b/controller/ofctrl.c @@ -1631,10 +1631,84 @@ update_installed_flows_by_compare(struct ovn_desired_flow_table *flow_table, } } +/* Finds and returns a desired_flow in 'deleted_flows' that is exactly the + * same as 'target', including cookie and actions. + */ +static struct desired_flow * +deleted_flow_lookup(struct hmap *deleted_flows, struct ovn_flow *target) +{ +struct desired_flow *d; +HMAP_FOR_EACH_WITH_HASH (d, match_hmap_node, target->hash, + deleted_flows) { +struct ovn_flow *f = >flow; +if (f->table_id == target->table_id +&& f->priority == target->priority +&& minimatch_equal(>match, >match) +&& f->cookie == target->cookie +&& ofpacts_equal(f->ofpacts, f->ofpacts_len, target->ofpacts, + target->ofpacts_len)) { +return d; +} +} +return NULL; +} + +/* This function scans the tracked flow changes in the order and merges "add" + * or "update" after "deleted" operations for exactly same flow (priority, + * table, match, action and cookie), to avoid unnecessary OF messages being + * sent to OVS. */ +static void +merge_tracked_flows(struct ovn_desired_flow_table *flow_table) +{ +struct hmap deleted_flows = HMAP_INITIALIZER(_flows); +struct desired_flow *f, *next; +LIST_FOR_EACH_SAFE (f, next, track_list_node, +_table->tracked_flows) { +if (f->is_deleted) { +/* reuse f->match_hmap_node field since it is already removed from + * the desired flow table's match index. */ +hmap_insert(_flows, >match_hmap_node, +f->flow.hash); +} else { +struct desired_flow *del_f = deleted_flow_lookup(_flows, + >flow); +if (!del_f) { +continue; +} + +/* del_f must have been installed, otherwise it should have been + * removed during track_flow_add_or_modify. */ +ovs_assert(del_f->installed_flow); +if (!f->installed_flow) { +/* f is not installed yet. */ +struct installed_flow *i = del_f->installed_flow; +unlink_installed_to_desired(i, del_f); +link_installed_to_desired(i, f); +} else { +/* f has been installed before, and now was updated to exact + * the same flow as del_f. */ +ovs_assert(f->installed_flow == del_f->installed_flow); +unlink_installed_to_desired(del_f->installed_flow, del_f); +} +hmap_remove(_flows, _f->match_hmap_node); +ovs_list_remove(_f->track_list_node); +desired_flow_destroy(del_f); + +ovs_list_remove(>track_list_node); +ovs_list_init(>track_list_node); +} +} +HMAP_FOR_EACH_SAFE (f, next, match_hmap_node, _flows) { +hmap_remove(_flows, >match_hmap_node); +} +hmap_destroy(_flows); +} + static void update_installed_flows_by_track(struct ovn_desired_flow_table *flow_table, struct ovs_list *msgs) { +merge_tracked_flows(flow_table); struct desired_flow *f, *f_next; LIST_FOR_EACH_SAFE (f, f_next, track_list_node, _table->tracked_flows) { -- 2.30.0 ___ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev
[ovs-dev] [PATCH ovn branch-20.03 03/16] ofctrl.c: Maintain references between installed flows and desired flows.
From: Han Zhou Currently there is no link maintained between installed flows and desired flows. This patch maintains the mapping between them, which will be useful for a future patch that incrementally processes the flow installation without having to do the full comparison between them. This patch also refactors the struct ovn_flow with two different wrapper types: desired_flow and installed_flow, and the related static functions, to make the code easier to read and avoid misuses of the struct. Acked-by: Mark Michelson Signed-off-by: Han Zhou (cherry picked from commit 354d3853d40cbce89a434632f67daed7fc992d8b) Signed-off-by: Frode Nordahl --- controller/ofctrl.c | 428 ++-- 1 file changed, 294 insertions(+), 134 deletions(-) diff --git a/controller/ofctrl.c b/controller/ofctrl.c index 2a337e309..0d6326fc3 100644 --- a/controller/ofctrl.c +++ b/controller/ofctrl.c @@ -51,7 +51,27 @@ VLOG_DEFINE_THIS_MODULE(ofctrl); -/* An OpenFlow flow. +/* An OpenFlow flow. */ +struct ovn_flow { +/* Key. */ +uint8_t table_id; +uint16_t priority; +struct minimatch match; + +/* Hash. */ +uint32_t hash; + +/* Data. */ +struct ofpact *ofpacts; +size_t ofpacts_len; +uint64_t cookie; +}; + +/* A desired flow, in struct ovn_desired_flow_table, calculated by the + * incremental processing engine. + * - They are added/removed incrementally when I-P engine is able to process + * the changes incrementally, or + * - Completely cleared and recomputed by I-P engine when recompute happens. * * Links are maintained between desired flows and SB data. The relationship * is M to N. The struct sb_flow_ref is used to link a pair of desired flow @@ -82,52 +102,92 @@ VLOG_DEFINE_THIS_MODULE(ofctrl); * The links are updated whenever there is a change in desired flows, which is * usually triggered by a SB data change in I-P engine. */ -struct ovn_flow { +struct desired_flow { +struct ovn_flow flow; struct hmap_node match_hmap_node; /* For match based hashing. */ struct ovs_list list_node; /* For handling lists of flows. */ -struct ovs_list references; /* A list of struct sb_flow_ref nodes, which - references this flow. (There are cases - that multiple SB entities share the same - desired OpenFlow flow, e.g. when - conjunction is used.) */ -/* Key. */ -uint8_t table_id; -uint16_t priority; -struct minimatch match; +/* A list of struct sb_flow_ref nodes, which references this flow. (There + * are cases that multiple SB entities share the same desired OpenFlow + * flow, e.g. when conjunction is used.) */ +struct ovs_list references; -/* Data. */ -struct ofpact *ofpacts; -size_t ofpacts_len; -uint64_t cookie; +/* The corresponding flow in installed table. */ +struct installed_flow *installed_flow; + +/* Node in installed_flow.desired_refs list. */ +struct ovs_list installed_ref_list_node; }; struct sb_to_flow { struct hmap_node hmap_node; /* Node in ovn_desired_flow_table.uuid_flow_table. */ struct uuid sb_uuid; -struct ovs_list flows; /* A list of struct sb_flow_ref nodes that are - referenced by the sb_uuid. */ +struct ovs_list flows; /* A list of struct sb_flow_ref nodes that + are referenced by the sb_uuid. */ }; struct sb_flow_ref { -struct ovs_list sb_list; /* List node in ovn_flow.references. */ -struct ovs_list flow_list; /* List node in sb_to_flow.ovn_flows. */ -struct ovn_flow *flow; +struct ovs_list sb_list; /* List node in desired_flow.references. */ +struct ovs_list flow_list; /* List node in sb_to_flow.desired_flows. */ +struct desired_flow *flow; struct uuid sb_uuid; }; -static struct ovn_flow *ovn_flow_alloc(uint8_t table_id, uint16_t priority, - uint64_t cookie, - const struct match *match, - const struct ofpbuf *actions); +/* A installed flow, in static variable installed_flows. + * + * Installed flows are updated in ofctrl_put for maintaining the flow + * installation to OVS. They are updated according to desired flows: either by + * processing the tracked desired flow changes, or by comparing desired flows + * with currently installed flows when tracked desired flows changes are not + * available. + * + * In addition, when ofctrl state machine enters S_CLEAR, the installed flows + * will be cleared. (This happens in initialization phase and also when + * ovs-vswitchd is disconnected/reconnected). + * + * Links are maintained between installed flows and desired flows. The + * relationship is 1 to N. A link is added when a flow addition is
[ovs-dev] [PATCH ovn branch-20.03 04/16] ofctrl.c: Refactor - move openflow msg construction to functions.
From: Han Zhou These functions will be reused in multiple places in a future patch. Acked-by: Mark Michelson Signed-off-by: Han Zhou (cherry picked from commit 23063cf4178c05f5d6b3e4ec6d323ccc88df6101) Signed-off-by: Frode Nordahl --- controller/ofctrl.c | 103 ++-- 1 file changed, 60 insertions(+), 43 deletions(-) diff --git a/controller/ofctrl.c b/controller/ofctrl.c index 0d6326fc3..6de14ac9d 100644 --- a/controller/ofctrl.c +++ b/controller/ofctrl.c @@ -1419,6 +1419,63 @@ add_meter(struct ovn_extend_table_info *m_desired, free(mm.meter.bands); } +static void +installed_flow_add(struct ovn_flow *d, struct ovs_list *msgs) +{ +/* Send flow_mod to add flow. */ +struct ofputil_flow_mod fm = { +.match = d->match, +.priority = d->priority, +.table_id = d->table_id, +.ofpacts = d->ofpacts, +.ofpacts_len = d->ofpacts_len, +.new_cookie = htonll(d->cookie), +.command = OFPFC_ADD, +}; +add_flow_mod(, msgs); +} + +static void +installed_flow_mod(struct ovn_flow *i, struct ovn_flow *d, + struct ovs_list *msgs) +{ +/* Update actions in installed flow. */ +struct ofputil_flow_mod fm = { +.match = i->match, +.priority = i->priority, +.table_id = i->table_id, +.ofpacts = d->ofpacts, +.ofpacts_len = d->ofpacts_len, +.command = OFPFC_MODIFY_STRICT, +}; +/* Update cookie if it is changed. */ +if (i->cookie != d->cookie) { +fm.modify_cookie = true; +fm.new_cookie = htonll(d->cookie); +/* Use OFPFC_ADD so that cookie can be updated. */ +fm.command = OFPFC_ADD; +} +add_flow_mod(, msgs); + +/* Replace 'i''s actions and cookie by 'd''s. */ +free(i->ofpacts); +i->ofpacts = xmemdup(d->ofpacts, d->ofpacts_len); +i->ofpacts_len = d->ofpacts_len; +i->cookie = d->cookie; +} + +static void +installed_flow_del(struct ovn_flow *i, struct ovs_list *msgs) +{ +struct ofputil_flow_mod fm = { +.match = i->match, +.priority = i->priority, +.table_id = i->table_id, +.command = OFPFC_DELETE_STRICT, +}; +add_flow_mod(, msgs); +} + /* The flow table can be updated if the connection to the switch is up and * in the correct state and not backlogged with existing flow_mods. (Our * criteria for being backlogged appear very conservative, but the socket @@ -1544,46 +1601,16 @@ ofctrl_put(struct ovn_desired_flow_table *flow_table, if (!d) { /* Installed flow is no longer desirable. Delete it from the * switch and from installed_flows. */ -struct ofputil_flow_mod fm = { -.match = i->flow.match, -.priority = i->flow.priority, -.table_id = i->flow.table_id, -.command = OFPFC_DELETE_STRICT, -}; -add_flow_mod(, ); +installed_flow_del(>flow, ); ovn_flow_log(>flow, "removing installed"); - hmap_remove(_flows, >match_hmap_node); installed_flow_destroy(i); } else { if (!ofpacts_equal(i->flow.ofpacts, i->flow.ofpacts_len, d->flow.ofpacts, d->flow.ofpacts_len) || i->flow.cookie != d->flow.cookie) { -/* Update actions in installed flow. */ -struct ofputil_flow_mod fm = { -.match = i->flow.match, -.priority = i->flow.priority, -.table_id = i->flow.table_id, -.ofpacts = d->flow.ofpacts, -.ofpacts_len = d->flow.ofpacts_len, -.command = OFPFC_MODIFY_STRICT, -}; -/* Update cookie if it is changed. */ -if (i->flow.cookie != d->flow.cookie) { -fm.modify_cookie = true; -fm.new_cookie = htonll(d->flow.cookie); -/* Use OFPFC_ADD so that cookie can be updated. */ -fm.command = OFPFC_ADD, -i->flow.cookie = d->flow.cookie; -} -add_flow_mod(, ); ovn_flow_log(>flow, "updating installed"); - -/* Replace 'i''s actions by 'd''s. */ -free(i->flow.ofpacts); -i->flow.ofpacts = xmemdup(d->flow.ofpacts, - d->flow.ofpacts_len); -i->flow.ofpacts_len = d->flow.ofpacts_len; +installed_flow_mod(>flow, >flow, ); } link_installed_to_desired(i, d); @@ -1596,17 +1623,7 @@ ofctrl_put(struct ovn_desired_flow_table *flow_table, HMAP_FOR_EACH (d, match_hmap_node, _table->match_flow_table) { i = installed_flow_lookup(>flow); if (!i) { -/* Send flow_mod to add flow. */ -struct ofputil_flow_mod
[ovs-dev] [PATCH ovn branch-20.03 00/16] Backport rollup
Hello all, In Ubuntu we have backported a set of fixes to our OVN 20.06 and OVN 20.03 packages. In preparing for new point releases for OVN 20.06 and OVN 20.03, we would very much like to add these patches to the upstream branches. The issues solved for OVN 20.03 with these patches are: * Fix for incorrect ARP processing with DVR enabled (LP: #1905933)[0] * Fix for upgrading database schema of clustered databases on package upgrade (LP: #1907081)[1] * Fixes for predictable resolution for conflicting flow actions. (LP: #1906922)[2] We are cognizant of the large number of patches required to cleanly backport the conflicting flow actions fixes, and have verified the end result thouroughly. From our experience these fixes are required to use OVN with OpenStack in a meaningful way, for example with k8s on top of OpenStack. 0: https://bugs.launchpad.net/bugs/1905933 1: https://bugs.launchpad.net/bugs/1907081 2: https://bugs.launchpad.net/bugs/1906922 Dumitru Ceara (8): ofctrl.c: Only merge actions for conjunctive flows. ofctrl.c: Do not change flow ordering when merging opposite changes. ofctrl.c: Simplify active desired flow selection. ofctrl.c: Always log the most recent flow changes. ofctrl.c: Add a predictable resolution for conflicting flow actions. ovn.at: Make some of the tests more predictable. tests: Add ofctl_strip_all() to filter OVS flow outputs. tests: Fix test "ovn -- Superseding ACLs with conjunction". Han Zhou (6): ofctrl.c: Maintain references between installed flows and desired flows. ofctrl.c: Refactor - move openflow msg construction to functions. ofctrl: Incremental processing for flow installation by tracking. ofctrl.c: Merge opposite changes of tracked flows before installing. ofctrl.c: Fix duplicated flow handling in I-P while merging opposite changes. ofctrl.c: Avoid repeatedly linking an installed flow and a desired flow. Lorenzo Bianconi (1): Revert "Manage ARP process locally in a DVR scenario" Numan Siddique (1): ovn-ctl: Handle cluster db upgrades for run_(nb/sb)_ovsdb controller/ofctrl.c | 966 controller/ofctrl.h | 6 +- northd/ovn-northd.8.xml | 37 +- northd/ovn-northd.c | 53 +-- tests/ofproto-macros.at | 23 +- tests/ovn.at| 342 +- utilities/ovn-ctl | 20 +- 7 files changed, 1159 insertions(+), 288 deletions(-) -- 2.30.0 ___ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev
[ovs-dev] [PATCH ovn branch-20.06 15/15] tests: Fix test "ovn -- Superseding ACLs with conjunction".
The test was checking the output of "ovs-ofctl dump-flows" without taking into account that some fields don't have predictable values, e.g., hard_age. Instead, use ofctl_strip_all(). Fixes: 986b3d5e4ad6 ("ofctrl.c: Add a predictable resolution for conflicting flow actions.") Reported-by: Numan Siddique Signed-off-by: Dumitru Ceara Signed-off-by: Numan Siddique (cherry picked from commit 6e3d69e6b5153e26c869a03ec7dd1aaa40488005) Signed-off-by: Frode Nordahl --- tests/ovn.at | 72 ++-- 1 file changed, 36 insertions(+), 36 deletions(-) diff --git a/tests/ovn.at b/tests/ovn.at index b38f6c9bc..24f83f2c5 100644 --- a/tests/ovn.at +++ b/tests/ovn.at @@ -13435,16 +13435,16 @@ 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=45 | \ -grep "priority=1003" | awk '{print $7 " " $8}' | \ +AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=45 | ofctl_strip_all | \ +grep "priority=1003" | \ sed 's/conjunction([[^)]]*)/conjunction()/g' | sort], [0], [dnl -priority=1003,conj_id=2,ip,metadata=0x1 actions=resubmit(,46) -priority=1003,conj_id=3,ip,metadata=0x1 actions=resubmit(,46) -priority=1003,ip,metadata=0x1,nw_dst=10.0.0.3 actions=conjunction(),conjunction() -priority=1003,ip,metadata=0x1,nw_dst=10.0.0.4 actions=conjunction(),conjunction() -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() -priority=1003,ip,metadata=0x1,nw_src=10.0.0.42 actions=conjunction() + table=45, priority=1003,conj_id=2,ip,metadata=0x1 actions=resubmit(,46) + table=45, priority=1003,conj_id=3,ip,metadata=0x1 actions=resubmit(,46) + table=45, priority=1003,ip,metadata=0x1,nw_dst=10.0.0.3 actions=conjunction(),conjunction() + table=45, priority=1003,ip,metadata=0x1,nw_dst=10.0.0.4 actions=conjunction(),conjunction() + table=45, priority=1003,ip,metadata=0x1,nw_src=10.0.0.1 actions=resubmit(,46) + table=45, priority=1003,ip,metadata=0x1,nw_src=10.0.0.2 actions=conjunction() + table=45, priority=1003,ip,metadata=0x1,nw_src=10.0.0.42 actions=conjunction() ]) # Traffic 10.0.0.1, 10.0.0.2 -> 10.0.0.3, 10.0.0.4 should be allowed. @@ -13481,16 +13481,16 @@ ovn-nbctl acl-del ls1 to-lport 3 'ip4.src==10.0.0.1 || ip4.src==10.0.0.1' ovn-nbctl --wait=hv sync # Check OVS flows, the second less restrictive allow ACL should have been installed. -AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=45 | \ -grep "priority=1003" | awk '{print $7 " " $8}' | \ +AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=45 | ofctl_strip_all | \ +grep "priority=1003" | \ sed 's/conjunction([[^)]]*)/conjunction()/g' | sort], [0], [dnl -priority=1003,conj_id=2,ip,metadata=0x1 actions=resubmit(,46) -priority=1003,conj_id=3,ip,metadata=0x1 actions=resubmit(,46) -priority=1003,ip,metadata=0x1,nw_dst=10.0.0.3 actions=conjunction(),conjunction() -priority=1003,ip,metadata=0x1,nw_dst=10.0.0.4 actions=conjunction(),conjunction() -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() -priority=1003,ip,metadata=0x1,nw_src=10.0.0.42 actions=conjunction() + table=45, priority=1003,conj_id=2,ip,metadata=0x1 actions=resubmit(,46) + table=45, priority=1003,conj_id=3,ip,metadata=0x1 actions=resubmit(,46) + table=45, priority=1003,ip,metadata=0x1,nw_dst=10.0.0.3 actions=conjunction(),conjunction() + table=45, priority=1003,ip,metadata=0x1,nw_dst=10.0.0.4 actions=conjunction(),conjunction() + table=45, priority=1003,ip,metadata=0x1,nw_src=10.0.0.1 actions=resubmit(,46) + table=45, priority=1003,ip,metadata=0x1,nw_src=10.0.0.2 actions=conjunction() + table=45, priority=1003,ip,metadata=0x1,nw_src=10.0.0.42 actions=conjunction() ]) # Remove the less restrictive allow ACL. @@ -13498,16 +13498,16 @@ 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=45 | \ -grep "priority=1003" | awk '{print $7 " " $8}' | \ +AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=45 | ofctl_strip_all | \ +grep "priority=1003" | \ sed 's/conjunction([[^)]]*)/conjunction()/g' | sort], [0], [dnl -priority=1003,conj_id=2,ip,metadata=0x1 actions=resubmit(,46) -priority=1003,conj_id=3,ip,metadata=0x1 actions=resubmit(,46) -priority=1003,ip,metadata=0x1,nw_dst=10.0.0.3 actions=conjunction(),conjunction() -priority=1003,ip,metadata=0x1,nw_dst=10.0.0.4 actions=conjunction(),conjunction() -priority=1003,ip,metadata=0x1,nw_src=10.0.0.1 actions=conjunction(),conjunction() -priority=1003,ip,metadata=0x1,nw_src=10.0.0.2 actions=conjunction() -priority=1003,ip,metadata=0x1,nw_src=10.0.0.42 actions=conjunction() + table=45,
[ovs-dev] [PATCH ovn branch-20.06 14/15] tests: Add ofctl_strip_all() to filter OVS flow outputs.
Extend the already existing ofctl_strip() to also ignore n_packets, n_bytes, cookie. Use some helper functions from tests/system-userspace-packet-type-aware.at, which will be removed by a future commit. Signed-off-by: Dumitru Ceara Signed-off-by: Numan Siddique (cherry picked from commit 0879a0aa9f332bdc689769a1bc2f156f1c3149a5) Signed-off-by: Frode Nordahl --- tests/ofproto-macros.at | 23 ++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/tests/ofproto-macros.at b/tests/ofproto-macros.at index 6c4ff60e7..22999c1ca 100644 --- a/tests/ofproto-macros.at +++ b/tests/ofproto-macros.at @@ -1,12 +1,27 @@ m4_divert_push([PREPARE_TESTS]) [ +# Strips 'n_packets=...' from ovs-ofctl output. +strip_n_packets () { +sed 's/ n_packets=[0-9]*,//' +} + +# Strips 'n_bytes=...' from ovs-ofctl output. +strip_n_bytes () { +sed 's/ n_bytes=[0-9]*,//' +} + +# Strips 'cookie=...' from ovs-ofctl output. +strip_cookie () { +sed 's/ cookie=0x[0-9a-fA-F]*,//' +} + # Strips out uninteresting parts of ovs-ofctl output, as well as parts # that vary from one run to another. ofctl_strip () { sed ' s/ (xid=0x[0-9a-fA-F]*)// s/ duration=[0-9.]*s,// -s/ cookie=0x0,// +s/ cookie=0,// s/ table=0,// s/ n_packets=0,// s/ n_bytes=0,// @@ -19,6 +34,12 @@ s/dir\/[0-9]*\/br0.mgmt/dir\/\/br0.mgmt/ ' } +# Strips out uninteresting parts of ovs-ofctl output, including n_packets=.. +# n_bytes=.. +ofctl_strip_all () { +ofctl_strip | strip_n_packets | strip_n_bytes | strip_cookie +} + # Filter (multiline) vconn debug messages from ovs-vswitchd.log. # Use with vconn_sub() and ofctl_strip() print_vconn_debug () { awk -F\| < ovs-vswitchd.log ' -- 2.30.0 ___ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev
[ovs-dev] [PATCH ovn branch-20.06 13/15] ovn.at: Make some of the tests more predictable.
Fix some of the race conditions that are present in the current OVN test suite. Signed-off-by: Dumitru Ceara Signed-off-by: Ben Pfaff (cherry picked from commit d6594a4695084e1b0f4fb3170547942876d3a81a) Signed-off-by: Frode Nordahl --- tests/ovn.at | 48 +++- 1 file changed, 27 insertions(+), 21 deletions(-) diff --git a/tests/ovn.at b/tests/ovn.at index 8f7dec55d..b38f6c9bc 100644 --- a/tests/ovn.at +++ b/tests/ovn.at @@ -4045,6 +4045,7 @@ for i in 1 2 3; do ovn-nbctl lsp-set-addresses lp$i$j "f0:00:00:00:00:$i$j 192.168.0.$i$j" "$extra_addr" ovn-nbctl lsp-set-port-security lp$i$j "f0:00:00:00:00:$i$j 192.168.0.$i$j" "$extra_addr" fi +OVS_WAIT_UNTIL([test x`ovn-nbctl lsp-get-up lp$i$j` = xup]) done done @@ -13435,14 +13436,15 @@ 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=45 | \ -grep "priority=1003" | awk '{print $7 " " $8}' | sort], [0], [dnl +grep "priority=1003" | awk '{print $7 " " $8}' | \ +sed 's/conjunction([[^)]]*)/conjunction()/g' | sort], [0], [dnl priority=1003,conj_id=2,ip,metadata=0x1 actions=resubmit(,46) priority=1003,conj_id=3,ip,metadata=0x1 actions=resubmit(,46) -priority=1003,ip,metadata=0x1,nw_dst=10.0.0.3 actions=conjunction(2,1/2),conjunction(3,1/2) -priority=1003,ip,metadata=0x1,nw_dst=10.0.0.4 actions=conjunction(2,1/2),conjunction(3,1/2) +priority=1003,ip,metadata=0x1,nw_dst=10.0.0.3 actions=conjunction(),conjunction() +priority=1003,ip,metadata=0x1,nw_dst=10.0.0.4 actions=conjunction(),conjunction() 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) -priority=1003,ip,metadata=0x1,nw_src=10.0.0.42 actions=conjunction(3,2/2) +priority=1003,ip,metadata=0x1,nw_src=10.0.0.2 actions=conjunction() +priority=1003,ip,metadata=0x1,nw_src=10.0.0.42 actions=conjunction() ]) # Traffic 10.0.0.1, 10.0.0.2 -> 10.0.0.3, 10.0.0.4 should be allowed. @@ -13480,14 +13482,15 @@ ovn-nbctl --wait=hv sync # Check OVS flows, the second less restrictive allow ACL should have been installed. AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=45 | \ -grep "priority=1003" | awk '{print $7 " " $8}' | sort], [0], [dnl +grep "priority=1003" | awk '{print $7 " " $8}' | \ +sed 's/conjunction([[^)]]*)/conjunction()/g' | sort], [0], [dnl priority=1003,conj_id=2,ip,metadata=0x1 actions=resubmit(,46) priority=1003,conj_id=3,ip,metadata=0x1 actions=resubmit(,46) -priority=1003,ip,metadata=0x1,nw_dst=10.0.0.3 actions=conjunction(2,1/2),conjunction(3,1/2) -priority=1003,ip,metadata=0x1,nw_dst=10.0.0.4 actions=conjunction(2,1/2),conjunction(3,1/2) +priority=1003,ip,metadata=0x1,nw_dst=10.0.0.3 actions=conjunction(),conjunction() +priority=1003,ip,metadata=0x1,nw_dst=10.0.0.4 actions=conjunction(),conjunction() 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) -priority=1003,ip,metadata=0x1,nw_src=10.0.0.42 actions=conjunction(3,2/2) +priority=1003,ip,metadata=0x1,nw_src=10.0.0.2 actions=conjunction() +priority=1003,ip,metadata=0x1,nw_src=10.0.0.42 actions=conjunction() ]) # Remove the less restrictive allow ACL. @@ -13496,14 +13499,15 @@ 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=45 | \ -grep "priority=1003" | awk '{print $7 " " $8}' | sort], [0], [dnl +grep "priority=1003" | awk '{print $7 " " $8}' | \ +sed 's/conjunction([[^)]]*)/conjunction()/g' | sort], [0], [dnl priority=1003,conj_id=2,ip,metadata=0x1 actions=resubmit(,46) priority=1003,conj_id=3,ip,metadata=0x1 actions=resubmit(,46) -priority=1003,ip,metadata=0x1,nw_dst=10.0.0.3 actions=conjunction(2,1/2),conjunction(3,1/2) -priority=1003,ip,metadata=0x1,nw_dst=10.0.0.4 actions=conjunction(2,1/2),conjunction(3,1/2) -priority=1003,ip,metadata=0x1,nw_src=10.0.0.1 actions=conjunction(2,2/2),conjunction(3,2/2) -priority=1003,ip,metadata=0x1,nw_src=10.0.0.2 actions=conjunction(2,2/2) -priority=1003,ip,metadata=0x1,nw_src=10.0.0.42 actions=conjunction(3,2/2) +priority=1003,ip,metadata=0x1,nw_dst=10.0.0.3 actions=conjunction(),conjunction() +priority=1003,ip,metadata=0x1,nw_dst=10.0.0.4 actions=conjunction(),conjunction() +priority=1003,ip,metadata=0x1,nw_src=10.0.0.1 actions=conjunction(),conjunction() +priority=1003,ip,metadata=0x1,nw_src=10.0.0.2 actions=conjunction() +priority=1003,ip,metadata=0x1,nw_src=10.0.0.42 actions=conjunction() ]) # Traffic 10.0.0.1, 10.0.0.2 -> 10.0.0.3, 10.0.0.4 should be allowed. @@ -13534,14 +13538,15 @@ 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=45 | \ -
[ovs-dev] [PATCH ovn branch-20.06 12/15] ofctrl.c: Add a predictable resolution for conflicting flow actions.
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 ensure that all desired flows refering the same installed flow are partially sorted in the following way: - first all flows with action "allow". - then all flows with action "drop". - then a single flow with action "conjunction" (resulting from merging all flows with the same match and action conjunction). This ensures that "allow" flows have precedence over "drop" flows which in turn have precedence over "conjunction" flows. Essentially less restrictive flows are always preferred over more restrictive flows whenever a match conflict happens. CC: Daniel Alvarez Reported-at: https://bugzilla.redhat.com/1871931 Signed-off-by: Dumitru Ceara Acked-by: Mark Gray Signed-off-by: Han Zhou (cherry picked from commit 986b3d5e4ad6f05245d021ba699c957246294a22) Signed-off-by: Frode Nordahl --- controller/ofctrl.c | 74 +-- tests/ovn.at| 214 2 files changed, 283 insertions(+), 5 deletions(-) diff --git a/controller/ofctrl.c b/controller/ofctrl.c index 16dc10cfb..c1bbc589e 100644 --- a/controller/ofctrl.c +++ b/controller/ofctrl.c @@ -188,6 +188,14 @@ struct sb_flow_ref { * relationship is 1 to N. A link is added when a flow addition is processed. * A link is removed when a flow deletion is processed, the desired flow * table is cleared, or the installed flow table is cleared. + * + * To ensure predictable behavior, the list of desired flows is maintained + * partially sorted in the following way (from least restrictive to most + * restrictive wrt. match): + * - allow flows without action conjunction. + * - drop flows without action conjunction. + * - a single flow with action conjunction. + * * The first desired_flow in the list is the active one, the one that is * actually installed. */ @@ -795,6 +803,12 @@ ofctrl_recv(const struct ofp_header *oh, enum ofptype type) } } +static bool +flow_action_has_drop(const struct ovn_flow *f) +{ +return f->ofpacts_len == 0; +} + static bool flow_action_has_conj(const struct ovn_flow *f) { @@ -808,6 +822,33 @@ flow_action_has_conj(const struct ovn_flow *f) return false; } +static bool +flow_action_has_allow(const struct ovn_flow *f) +{ +return !flow_action_has_drop(f) && !flow_action_has_conj(f); +} + +/* Returns true if flow 'a' is preferred over flow 'b'. */ +static bool +flow_is_preferred(const struct ovn_flow *a, const struct ovn_flow *b) +{ +if (flow_action_has_allow(b)) { +return false; +} +if (flow_action_has_allow(a)) { +return true; +} +if (flow_action_has_drop(b)) { +return false; +} +if (flow_action_has_drop(a)) { +return true; +} + +/* Flows 'a' and 'b' should never both have action conjunction. */ +OVS_NOT_REACHED(); +} + /* Adds the desired flow to the list of desired flows that have same match * conditions as the installed flow. * @@ -820,8 +861,18 @@ flow_action_has_conj(const struct ovn_flow *f) static bool link_installed_to_desired(struct installed_flow *i, struct desired_flow *d) { +struct desired_flow *f; + +/* Find first 'f' such that 'd' is preferred over 'f'. If no such desired + * flow exists then 'f' will point after the last element of the list. + */ +
[ovs-dev] [PATCH ovn branch-20.06 11/15] ofctrl.c: Always log the most recent flow changes.
Fixes: 6f0b1e02d9ab ("ofctrl: Incremental processing for flow installation by tracking.") Signed-off-by: Dumitru Ceara Signed-off-by: Han Zhou (cherry picked from commit 33c15c145988daa6172928dc870f3a0225515f50) Signed-off-by: Frode Nordahl --- controller/ofctrl.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/controller/ofctrl.c b/controller/ofctrl.c index c03c2d7b4..16dc10cfb 100644 --- a/controller/ofctrl.c +++ b/controller/ofctrl.c @@ -1895,8 +1895,8 @@ update_installed_flows_by_track(struct ovn_desired_flow_table *flow_table, * installed flow, so update the OVS flow for the new * active flow (at least the cookie will be different, * even if the actions are the same). */ -ovn_flow_log(>flow, "updating installed (tracked)"); installed_flow_mod(>flow, >flow, msgs); +ovn_flow_log(>flow, "updating installed (tracked)"); } } desired_flow_destroy(f); @@ -1916,8 +1916,8 @@ update_installed_flows_by_track(struct ovn_desired_flow_table *flow_table, } else if (installed_flow_get_active(i) == f) { /* The installed flow is installed for f, but f has change * tracked, so it must have been modified. */ -ovn_flow_log(>flow, "updating installed (tracked)"); installed_flow_mod(>flow, >flow, msgs); +ovn_flow_log(>flow, "updating installed (tracked)"); } else { /* Adding a new flow that conflicts with an existing installed * flow, so just add it to the link. */ -- 2.30.0 ___ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev
[ovs-dev] [PATCH ovn branch-20.06 10/15] ofctrl.c: Simplify active desired flow selection.
Always consider the first "desired flow" in the list of flows that refer an "installed flow" as the active flow. This simplifies the logic of the flow update code and is used in a further commit to implement a partial ordering of desired flows within installed flows. Signed-off-by: Dumitru Ceara Signed-off-by: Han Zhou (cherry picked from commit 107bb25029350bd0f7dfeeb0ef3053adbd504e3e) Signed-off-by: Frode Nordahl --- controller/ofctrl.c | 91 ++--- 1 file changed, 36 insertions(+), 55 deletions(-) diff --git a/controller/ofctrl.c b/controller/ofctrl.c index 0262a5cc3..c03c2d7b4 100644 --- a/controller/ofctrl.c +++ b/controller/ofctrl.c @@ -188,6 +188,8 @@ struct sb_flow_ref { * relationship is 1 to N. A link is added when a flow addition is processed. * A link is removed when a flow deletion is processed, the desired flow * table is cleared, or the installed flow table is cleared. + * The first desired_flow in the list is the active one, the one that is + * actually installed. */ struct installed_flow { struct ovn_flow flow; @@ -199,11 +201,6 @@ struct installed_flow { * installed flow, e.g. when there are conflict/duplicated ACLs that * generates same match conditions). */ struct ovs_list desired_refs; - -/* The corresponding flow in desired table. It must be one of the flows in - * desired_refs list. If there are more than one flows in references list, - * this is the one that is actually installed. */ -struct desired_flow *desired_flow; }; typedef bool @@ -231,6 +228,7 @@ static struct installed_flow *installed_flow_lookup( const struct ovn_flow *target); static void installed_flow_destroy(struct installed_flow *); static struct installed_flow *installed_flow_dup(struct desired_flow *); +static struct desired_flow *installed_flow_get_active(struct installed_flow *); static uint32_t ovn_flow_match_hash(const struct ovn_flow *); static char *ovn_flow_to_string(const struct ovn_flow *); @@ -796,24 +794,6 @@ ofctrl_recv(const struct ofp_header *oh, enum ofptype type) log_openflow_rl(, VLL_DBG, oh, "OpenFlow packet ignored"); } } - -/* Returns true if a desired flow is active (the one currently installed - * among the list of desired flows that are linked to the same installed - * flow). */ -static inline bool -desired_flow_is_active(struct desired_flow *d) -{ -return (d->installed_flow && d->installed_flow->desired_flow == d); -} - -/* Set a desired flow as the active one among the list of desired flows - * that are linked to the same installed flow. */ -static inline void -desired_flow_set_active(struct desired_flow *d) -{ -ovs_assert(d->installed_flow); -d->installed_flow->desired_flow = d; -} static bool flow_action_has_conj(const struct ovn_flow *f) @@ -831,27 +811,22 @@ flow_action_has_conj(const struct ovn_flow *f) /* Adds the desired flow to the list of desired flows that have same match * conditions as the installed flow. * - * If the newly added desired flow is the first one in the list, it is also set - * as the active one. - * * It is caller's responsibility to make sure the link between the pair didn't - * exist before. */ -static void + * exist before. + * + * Returns true if the newly added desired flow is selected to be the active + * one. + */ +static bool link_installed_to_desired(struct installed_flow *i, struct desired_flow *d) { -ovs_assert(i->desired_flow != d); -if (ovs_list_is_empty(>desired_refs)) { -ovs_assert(!i->desired_flow); -i->desired_flow = d; -} -ovs_list_insert(>desired_refs, >installed_ref_list_node); d->installed_flow = i; +ovs_list_push_back(>desired_refs, >installed_ref_list_node); +return installed_flow_get_active(i) == d; } /* Replaces 'old_desired' with 'new_desired' in the list of desired flows * that have same match conditions as the installed flow. - * - * If 'old_desired' was the active flow, 'new_desired' becomes the active one. */ static void replace_installed_to_desired(struct installed_flow *i, @@ -863,24 +838,22 @@ replace_installed_to_desired(struct installed_flow *i, _desired->installed_ref_list_node); old_desired->installed_flow = NULL; new_desired->installed_flow = i; -if (i->desired_flow == old_desired) { -i->desired_flow = new_desired; -} } -static void +/* Removes the desired flow from the list of desired flows that have the same + * match conditions as the installed flow. + * + * Returns true if the desired flow was the previously active flow. + */ +static bool unlink_installed_to_desired(struct installed_flow *i, struct desired_flow *d) { -ovs_assert(i && i->desired_flow && !ovs_list_is_empty(>desired_refs)); +struct desired_flow *old_active = installed_flow_get_active(i); + ovs_assert(d && d->installed_flow == i); ovs_list_remove(>installed_ref_list_node);
[ovs-dev] [PATCH ovn branch-20.06 09/15] ofctrl.c: Do not change flow ordering when merging opposite changes.
Instead of removing the old desired flow from the list and inserting the new one at the end we now directly replace the old flow with the new one while maintaining the same ordering. For now order of the flows is not relevant but further commits require maintaining the order of desired flows. Signed-off-by: Dumitru Ceara Signed-off-by: Han Zhou (cherry picked from commit e49ce9a33f38f29c44e3c30afcc189b5f6a9ef8e) Signed-off-by: Frode Nordahl --- controller/ofctrl.c | 28 +--- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/controller/ofctrl.c b/controller/ofctrl.c index 8404479bc..0262a5cc3 100644 --- a/controller/ofctrl.c +++ b/controller/ofctrl.c @@ -848,6 +848,26 @@ link_installed_to_desired(struct installed_flow *i, struct desired_flow *d) d->installed_flow = i; } +/* Replaces 'old_desired' with 'new_desired' in the list of desired flows + * that have same match conditions as the installed flow. + * + * If 'old_desired' was the active flow, 'new_desired' becomes the active one. + */ +static void +replace_installed_to_desired(struct installed_flow *i, + struct desired_flow *old_desired, + struct desired_flow *new_desired) +{ +ovs_assert(old_desired->installed_flow == i); +ovs_list_replace(_desired->installed_ref_list_node, + _desired->installed_ref_list_node); +old_desired->installed_flow = NULL; +new_desired->installed_flow = i; +if (i->desired_flow == old_desired) { +i->desired_flow = new_desired; +} +} + static void unlink_installed_to_desired(struct installed_flow *i, struct desired_flow *d) { @@ -1843,21 +1863,15 @@ merge_tracked_flows(struct ovn_desired_flow_table *flow_table) * removed during track_flow_add_or_modify. */ ovs_assert(del_f->installed_flow); -bool del_f_was_active = desired_flow_is_active(del_f); if (!f->installed_flow) { /* f is not installed yet. */ -struct installed_flow *i = del_f->installed_flow; -unlink_installed_to_desired(i, del_f); -link_installed_to_desired(i, f); +replace_installed_to_desired(del_f->installed_flow, del_f, f); } else { /* f has been installed before, and now was updated to exact * the same flow as del_f. */ ovs_assert(f->installed_flow == del_f->installed_flow); unlink_installed_to_desired(del_f->installed_flow, del_f); } -if (del_f_was_active) { -desired_flow_set_active(f); -} hmap_remove(_flows, _f->match_hmap_node); ovs_list_remove(_f->track_list_node); desired_flow_destroy(del_f); -- 2.30.0 ___ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev
[ovs-dev] [PATCH ovn branch-20.06 08/15] ofctrl.c: Only merge actions for conjunctive flows.
In ofctrl_add_or_append_flow() when merging flow actions make sure we only do that for conjunctive flows. All other actions can not be merged with action "conjunction". CC: Mark Michelson Fixes: e659bab31a91 ("Combine conjunctions with identical matches into one flow.") Signed-off-by: Dumitru Ceara Signed-off-by: Han Zhou (cherry picked from commit dadae4f800ccb1f2759378f0bd804dd002e31605) Signed-off-by: Frode Nordahl --- controller/ofctrl.c | 124 +++- 1 file changed, 99 insertions(+), 25 deletions(-) diff --git a/controller/ofctrl.c b/controller/ofctrl.c index 384659d0c..8404479bc 100644 --- a/controller/ofctrl.c +++ b/controller/ofctrl.c @@ -206,6 +206,9 @@ struct installed_flow { struct desired_flow *desired_flow; }; +typedef bool +(*desired_flow_match_cb)(const struct desired_flow *candidate, + const void *arg); static struct desired_flow *desired_flow_alloc( uint8_t table_id, uint16_t priority, @@ -213,9 +216,15 @@ static struct desired_flow *desired_flow_alloc( const struct match *match, const struct ofpbuf *actions); static struct desired_flow *desired_flow_lookup( +struct ovn_desired_flow_table *, +const struct ovn_flow *target); +static struct desired_flow *desired_flow_lookup_check_uuid( struct ovn_desired_flow_table *, const struct ovn_flow *target, -const struct uuid *sb_uuid); +const struct uuid *); +static struct desired_flow *desired_flow_lookup_conjunctive( +struct ovn_desired_flow_table *, +const struct ovn_flow *target); static void desired_flow_destroy(struct desired_flow *); static struct installed_flow *installed_flow_lookup( @@ -806,6 +815,19 @@ desired_flow_set_active(struct desired_flow *d) d->installed_flow->desired_flow = d; } +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; +} + /* Adds the desired flow to the list of desired flows that have same match * conditions as the installed flow. * @@ -962,7 +984,7 @@ ofctrl_check_and_add_flow(struct ovn_desired_flow_table *flow_table, struct desired_flow *f = desired_flow_alloc(table_id, priority, cookie, match, actions); -if (desired_flow_lookup(flow_table, >flow, sb_uuid)) { +if (desired_flow_lookup_check_uuid(flow_table, >flow, sb_uuid)) { if (log_duplicate_flow) { static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 5); if (!VLOG_DROP_DBG()) { @@ -1002,14 +1024,15 @@ ofctrl_add_or_append_flow(struct ovn_desired_flow_table *desired_flows, const struct ofpbuf *actions, const struct uuid *sb_uuid) { -struct desired_flow *f = desired_flow_alloc(table_id, priority, cookie, -match, actions); - struct desired_flow *existing; -existing = desired_flow_lookup(desired_flows, >flow, NULL); +struct desired_flow *f; + +f = desired_flow_alloc(table_id, priority, cookie, match, actions); +existing = desired_flow_lookup_conjunctive(desired_flows, >flow); 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 and action + * 'conjunction'. Append the action to that flow rather than + * adding a new flow. */ uint64_t compound_stub[64 / 8]; struct ofpbuf compound; @@ -1248,15 +1271,11 @@ installed_flow_dup(struct desired_flow *src) return dst; } -/* Finds and returns a desired_flow in 'flow_table' whose key is identical to - * 'target''s key, or NULL if there is none. - * - * If sb_uuid is not NULL, the function will also check if the found flow is - * referenced by the sb_uuid. */ static struct desired_flow * -desired_flow_lookup(struct ovn_desired_flow_table *flow_table, -const struct ovn_flow *target, -const struct uuid *sb_uuid) +desired_flow_lookup__(struct ovn_desired_flow_table *flow_table, + const struct ovn_flow *target, + desired_flow_match_cb match_cb, + const void *arg) { struct desired_flow *d; HMAP_FOR_EACH_WITH_HASH (d, match_hmap_node, target->hash, @@ -1265,20 +1284,76 @@ desired_flow_lookup(struct ovn_desired_flow_table *flow_table, if (f->table_id == target->table_id && f->priority == target->priority && minimatch_equal(>match, >match)) { -if (!sb_uuid) { + +if (!match_cb || match_cb(d, arg)) { return d; } -struct
Re: [ovs-dev] [RFC ovn] northd: set max priority for automatic routes
Hi guys, On 2/18/21 12:16 AM, Han Zhou wrote: On Wed, Feb 17, 2021 at 2:36 PM Tim Rozet wrote: On Tue, Feb 16, 2021 at 4:21 AM Han Zhou wrote: On Wed, Feb 10, 2021 at 2:17 PM Lorenzo Bianconi < lorenzo.bianc...@redhat.com> wrote: Increase priority for automatic routes (routes created assigning IP addresses to OVN logical router interfaces) in order to always prefer them over static routes since the router has a direct link to the destination address (possible use-case can be found here [0]). [0] https://bugzilla.redhat.com/show_bug.cgi?id=1891516 Hi Lorenzo, Tim, While the patch may solve the problem in the bug report, I think there is something more fundamental to be discussed. The problem is caused by ovn-k8s's use of "src-ip" in static routes which overrides the direct-connected route. I think the implementation of "src-ip" support in the static route is somehow flawed. The priorities of the flows generated by static routes are calculated according to the prefix length, so that longest prefix routes are prioritised when there are multiple route matches, which is correct when comparing matches among "dst-ip" routes or among "src-ip" routes, but is not correct between "dst-ip" and "src-ip" routes. Comparison of prefix length between these two types of static routes doesn't make sense, because they match by different fields (src-ip v.s. dst-ip). For example, when there are static routes: 1. 192.168.0.0/24 via 100.64.0.1 src-ip 2. 10.0.0.0/20 via 100.64.0.2 dst-ip In this example, a packet from 192.168.0.1 to 10.0.0.1 matches both routes, but it is unreasonable to say it should follow the 1st route just because it has longer prefix length. Instead, we should prioritize one type over the other. It seems in physical router implementation policy based routing always has higher priority than destination routing, so we should probably enforce it in a similar way in OVN, i.e. set "src-ip" flows with higher priority than all the "dst-ip" flows. In fact, the policy routing table already supported this behavior because it is examined before the static route table. Since the "src-ip" feature in the static route table is flawed, and can be replaced by the policy routing table, I'd suggest to deprecate it. For I agree. correctness, users (like ovn-k8s) should use the policy routing table instead for the src-ip based routing rules. Users have full control of how they want the packets to be routed. For the use case mentioned in the bug report, it should have two rules in the policy routing table: 100 ip.dst == 100.64.0.0/16 accept # for directly connected destination, skip the src-ip rules 90 ip.src == 10.244.0.0/24 nexthop 100.64.0.1 # src-ip rules Would this better satisfy the need of ovn-k8s? I believe this is correct. src-ip matching should be done in the policy table so traditional dest based routing is handled in default routing table. Need to go double check though. One example, but should be the same for all "traditional" routers, "The Policy-Based Routing feature is a process whereby a device puts packets through a route map before routing the packets.": https://www.cisco.com/c/en/us/td/docs/ios-xml/ios/iproute_pi/configuration/15-mt/iri-15-mt-book/iri-pbr.html If the above is agreed, the priority change of directly connected routes from this patch is irrelevant to the problem reported in the bug, because policy routing rules are examined before the static routing table anyway, so no matter how high the route priority is, it wouldn't matter. In addition, it seems to me no real use cases would benefit from this change, but I could be wrong and please correct me if so. I disagree with this. Trying to override a directly connected route is fundamentally wrong, which is why real routers specifically stop a user from being able to do this. What if a user who had a router attached to 100.64.0.0/16, adds a /32 route for 100.64.0.1 via another interface/subnet? That would take precedence over the directly attached route in OVN iiuc and pretty much guarantee improper networking. Directly connected routes should always take precedence, and therefore the default route lflows that get installed should always have the highest possible priority. I think there's some confusion here. In "traditional" routers, longest prefix match has priority in the route selection process. If two routes (from different protocols, including "directly connected") are available for the *same* prefix *and* length then, and only then, the one with the lowest administrative distance is selected. Most of the times "directly connected" routes have a lower admin distance by default compared to static routes so they are preferred *if* such a selection has to happen. The admin distance is also usually configurable (although not usually recommended) and allows users to override the default preference of routes. Back to the example above, in a "traditional" router, when the
[ovs-dev] [PATCH ovn branch-20.06 06/15] ofctrl.c: Fix duplicated flow handling in I-P while merging opposite changes.
In a scenario in I-P when a desired flow is removed and an exactly same flow is added back in the same iteration, the merge_tracked_flows() function will merge the operation without firing any OpenFlow action. However, if there are multiple desired flows (e.g. F1 and F2) matching the same installed flow, and if the one being re-added (say, F1) is the one currently installed in OVS, the current implementation will update the currently installed flow to F2 in the data structure while the actual OVS flow is not updated (still F1). So far there is still no problem, but the member desired_flow of the installed flow is pointing to the wrong desired flow. Now there is only one place where the desired_flow member is consulted, in update_installed_flows_by_track() for handling a tracked *modified* flow. In reality flow modification happens only when conjunction flows need to be combined, which would never happen together with the above scenario of merge_tracked_flows(). So this wrong desired_flow pointer doesn't cause any real problem yet. However, there is a place that can already utilize this active desired_flow information, which is when handling a tracked flow deletion in update_installed_flows_by_track(): we can check if the flow being deleted is the currently active one installed in OVS. If not, we don't need to send and OpenFlow modify to OVS. This optimization is added in this patch, apart from fixing the problem of merge_tracked_flows(). Without the fix, this optimization would cause the test case added in this patch fail. Fixes: f4e508dd7 ("ofctrl.c: Merge opposite changes of tracked flows before installing.") Acked-by: Dumitru Ceara Signed-off-by: Han Zhou (cherry picked from commit 9d2e8d32fb9865513b70408a665184a67564390d) Signed-off-by: Frode Nordahl --- controller/ofctrl.c | 28 +++- tests/ovn.at| 108 2 files changed, 134 insertions(+), 2 deletions(-) diff --git a/controller/ofctrl.c b/controller/ofctrl.c index 2d0e15978..3225e6c67 100644 --- a/controller/ofctrl.c +++ b/controller/ofctrl.c @@ -788,6 +788,24 @@ ofctrl_recv(const struct ofp_header *oh, enum ofptype type) } } +/* Returns true if a desired flow is active (the one currently installed + * among the list of desired flows that are linked to the same installed + * flow). */ +static inline bool +desired_flow_is_active(struct desired_flow *d) +{ +return (d->installed_flow && d->installed_flow->desired_flow == d); +} + +/* Set a desired flow as the active one among the list of desired flows + * that are linked to the same installed flow. */ +static inline void +desired_flow_set_active(struct desired_flow *d) +{ +ovs_assert(d->installed_flow); +d->installed_flow->desired_flow = d; +} + static void link_installed_to_desired(struct installed_flow *i, struct desired_flow *d) { @@ -1741,6 +1759,8 @@ merge_tracked_flows(struct ovn_desired_flow_table *flow_table) /* del_f must have been installed, otherwise it should have been * removed during track_flow_add_or_modify. */ ovs_assert(del_f->installed_flow); + +bool del_f_was_active = desired_flow_is_active(del_f); if (!f->installed_flow) { /* f is not installed yet. */ struct installed_flow *i = del_f->installed_flow; @@ -1752,6 +1772,9 @@ merge_tracked_flows(struct ovn_desired_flow_table *flow_table) ovs_assert(f->installed_flow == del_f->installed_flow); unlink_installed_to_desired(del_f->installed_flow, del_f); } +if (del_f_was_active) { +desired_flow_set_active(f); +} hmap_remove(_flows, _f->match_hmap_node); ovs_list_remove(_f->track_list_node); desired_flow_destroy(del_f); @@ -1779,6 +1802,7 @@ update_installed_flows_by_track(struct ovn_desired_flow_table *flow_table, /* The desired flow was deleted */ if (f->installed_flow) { struct installed_flow *i = f->installed_flow; +bool was_active = desired_flow_is_active(f); unlink_installed_to_desired(i, f); if (!i->desired_flow) { @@ -1787,7 +1811,7 @@ update_installed_flows_by_track(struct ovn_desired_flow_table *flow_table, hmap_remove(_flows, >match_hmap_node); installed_flow_destroy(i); -} else { +} else if (was_active) { /* There are other desired flow(s) referencing this * installed flow, so update the OVS flow for the new * active flow (at least the cookie will be different, @@ -1811,7 +1835,7 @@ update_installed_flows_by_track(struct ovn_desired_flow_table *flow_table, hmap_insert(_flows, _node->match_hmap_node, new_node->flow.hash);
[ovs-dev] [PATCH ovn branch-20.06 07/15] ofctrl.c: Avoid repeatedly linking an installed flow and a desired flow.
In update_installed_flows_by_compare() there are two loops. The first loop iterates the installed flows and find its peer in desired flows to: 1. uninstall flows that are not needed anymore 2. update flows if needed At the same time, it links the desired flow found for the installed flow which also set the desired flow as the current active installed flow. The second loop iterates the desired flows and find its peer in installed flows to install missing flows. At the same time it will detect if there are conflict desired flows matching same installed flow then just link them. However, currently in the second loop, it blindly link the desired flows to the installed flows, without checking if it is already linked in the first loop. Lucky enough, this won't cause any real problem so far, because when there are conflict flows, the one found in the first loop will be set as active in the installed_flow, and in the function link_installed_to_desired() checks if it is already the active desired flow it just does nothing but return. However, the check in the link_installed_to_desired() is confusing because a desired_flow may be linked to the installed_flow already but not the active flow, and the check is insufficient. It should be rather an assertion and let the caller ensure that a pair of desired_flow and installed_flow is never linked twice. For the above reason, this patch does the following changes: 1. Removes the check in link_installed_to_desired() and convert it to an assert. 2. Before calling link_installed_to_desired() in the above mentioned loop, check if the desired flow is already installed. Acked-by: Dumitru Ceara Signed-off-by: Han Zhou (cherry picked from commit 7cab7bd1268ba67429954da4f73de91090acf779) Signed-off-by: Frode Nordahl --- controller/ofctrl.c | 19 ++- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/controller/ofctrl.c b/controller/ofctrl.c index 3225e6c67..384659d0c 100644 --- a/controller/ofctrl.c +++ b/controller/ofctrl.c @@ -806,13 +806,18 @@ desired_flow_set_active(struct desired_flow *d) d->installed_flow->desired_flow = d; } +/* Adds the desired flow to the list of desired flows that have same match + * conditions as the installed flow. + * + * If the newly added desired flow is the first one in the list, it is also set + * as the active one. + * + * It is caller's responsibility to make sure the link between the pair didn't + * exist before. */ static void link_installed_to_desired(struct installed_flow *i, struct desired_flow *d) { -if (i->desired_flow == d) { -return; -} - +ovs_assert(i->desired_flow != d); if (ovs_list_is_empty(>desired_refs)) { ovs_assert(!i->desired_flow); i->desired_flow = d; @@ -1706,8 +1711,12 @@ 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(_flows, >match_hmap_node, i->flow.hash); +link_installed_to_desired(i, d); +} else if (!d->installed_flow) { +/* This is a desired_flow that conflicts with one installed + * previously but not linked yet. */ +link_installed_to_desired(i, d); } -link_installed_to_desired(i, d); } } -- 2.30.0 ___ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev
[ovs-dev] [PATCH ovn branch-20.06 05/15] ofctrl.c: Merge opposite changes of tracked flows before installing.
This patch optimizes the previous patch that incrementally processes flow installation by merging the "add-after-delete" flow changes as much as possible to avoid unnecessary OpenFlow updates. Acked-by: Mark Michelson Signed-off-by: Han Zhou (cherry picked from commit f4e508dd7a6cfbfc2e3250a8c11a8d0fdc1dfdd0) Signed-off-by: Frode Nordahl --- controller/ofctrl.c | 74 + 1 file changed, 74 insertions(+) diff --git a/controller/ofctrl.c b/controller/ofctrl.c index b0670bf44..2d0e15978 100644 --- a/controller/ofctrl.c +++ b/controller/ofctrl.c @@ -1693,10 +1693,84 @@ update_installed_flows_by_compare(struct ovn_desired_flow_table *flow_table, } } +/* Finds and returns a desired_flow in 'deleted_flows' that is exactly the + * same as 'target', including cookie and actions. + */ +static struct desired_flow * +deleted_flow_lookup(struct hmap *deleted_flows, struct ovn_flow *target) +{ +struct desired_flow *d; +HMAP_FOR_EACH_WITH_HASH (d, match_hmap_node, target->hash, + deleted_flows) { +struct ovn_flow *f = >flow; +if (f->table_id == target->table_id +&& f->priority == target->priority +&& minimatch_equal(>match, >match) +&& f->cookie == target->cookie +&& ofpacts_equal(f->ofpacts, f->ofpacts_len, target->ofpacts, + target->ofpacts_len)) { +return d; +} +} +return NULL; +} + +/* This function scans the tracked flow changes in the order and merges "add" + * or "update" after "deleted" operations for exactly same flow (priority, + * table, match, action and cookie), to avoid unnecessary OF messages being + * sent to OVS. */ +static void +merge_tracked_flows(struct ovn_desired_flow_table *flow_table) +{ +struct hmap deleted_flows = HMAP_INITIALIZER(_flows); +struct desired_flow *f, *next; +LIST_FOR_EACH_SAFE (f, next, track_list_node, +_table->tracked_flows) { +if (f->is_deleted) { +/* reuse f->match_hmap_node field since it is already removed from + * the desired flow table's match index. */ +hmap_insert(_flows, >match_hmap_node, +f->flow.hash); +} else { +struct desired_flow *del_f = deleted_flow_lookup(_flows, + >flow); +if (!del_f) { +continue; +} + +/* del_f must have been installed, otherwise it should have been + * removed during track_flow_add_or_modify. */ +ovs_assert(del_f->installed_flow); +if (!f->installed_flow) { +/* f is not installed yet. */ +struct installed_flow *i = del_f->installed_flow; +unlink_installed_to_desired(i, del_f); +link_installed_to_desired(i, f); +} else { +/* f has been installed before, and now was updated to exact + * the same flow as del_f. */ +ovs_assert(f->installed_flow == del_f->installed_flow); +unlink_installed_to_desired(del_f->installed_flow, del_f); +} +hmap_remove(_flows, _f->match_hmap_node); +ovs_list_remove(_f->track_list_node); +desired_flow_destroy(del_f); + +ovs_list_remove(>track_list_node); +ovs_list_init(>track_list_node); +} +} +HMAP_FOR_EACH_SAFE (f, next, match_hmap_node, _flows) { +hmap_remove(_flows, >match_hmap_node); +} +hmap_destroy(_flows); +} + static void update_installed_flows_by_track(struct ovn_desired_flow_table *flow_table, struct ovs_list *msgs) { +merge_tracked_flows(flow_table); struct desired_flow *f, *f_next; LIST_FOR_EACH_SAFE (f, f_next, track_list_node, _table->tracked_flows) { -- 2.30.0 ___ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev
[ovs-dev] [PATCH ovn branch-20.06 04/15] ofctrl: Incremental processing for flow installation by tracking.
With incremental processing for flow computation, the bottle neck of ovn-controller in large scale environment is in the flow installation (ofctrl_put()), which does full comparison between the two big flow tables: the installed flows and desired flows. This patch implements tracking desired flow changes when flows are incrementally computed by I-P engine, and then incrementally processing the flow installation using the tracked information in ofctrl_put(). It falls back to the full comparison whenever tracking information is unavailable, e.g. when I-P engine triggers full recompute. In ovn-scale-test with 3000 HVs and 30k lports, the end-to-end latency between the moment a lflow is updated in SB DB and the moment when all the 3K HVs complete OVS flow updating has reduced around 60% (from 1s to 400ms). Below is the perf result for a ovn-controller processing a new port-binding: Beore: + 96.76% 0.00% ovn-controller [unknown] [k] 0x + 90.21% 0.00% ovn-controller ovn-controller [.] main + 39.93% 1.19% ovn-controller ovn-controller [.] ofctrl_put + 31.27%12.47% ovn-controller ovn-controller [.] ovn_flow_lookup + 22.12% 3.12% ovn-controller ovn-controller [.] encaps_run + 18.69% 2.77% ovn-controller ovn-controller [.] minimatch_equal + 17.63% 4.11% ovn-controller ovn-controller [.] patch_run + 15.91% 0.00% ovn-controller ovn-controller [.] add_bridge_mappings (inlined) + 14.03%12.08% ovn-controller ovn-controller [.] minimask_equal + 12.41% 0.00% ovn-controller ovn-controller [.] chassis_tunnel_add (inlined) + 11.40% 0.00% ovn-controller ovn-controller [.] tunnel_add (inlined) After: + 94.59% 0.00% ovn-controller [unknown] [k] 0x + 83.56% 0.09% ovn-controller ovn-controller [.] main + 35.37% 3.13% ovn-controller ovn-controller [.] encaps_run + 27.54% 7.53% ovn-controller ovn-controller [.] patch_run + 24.86% 0.00% ovn-controller ovn-controller [.] add_bridge_mappings (inlined) + 20.01% 0.00% ovn-controller ovn-controller [.] chassis_tunnel_add (inlined) + 18.51% 0.00% ovn-controller ovn-controller [.] tunnel_add (inlined) + 14.08% 0.17% ovn-controller ovn-controller [.] physical_run + 11.37%11.28% ovn-controller ovn-controller [.] next_real_row + 10.50% 2.59% ovn-controller ovn-controller [.] consider_port_binding .. +2.14% 0.32% ovn-controller ovn-controller [.] ofctrl_put ▒ Before the optimization, ofctrl_put took 40% of CPU, and now it disappears from the hot spots. Acked-by: Mark Michelson Signed-off-by: Han Zhou (cherry picked from commit 6f0b1e02d9ab3a94048c4818f2d382938cad4b71) Signed-off-by: Frode Nordahl --- controller/ofctrl.c | 289 +++- controller/ofctrl.h | 6 +- 2 files changed, 240 insertions(+), 55 deletions(-) diff --git a/controller/ofctrl.c b/controller/ofctrl.c index 98e291243..b0670bf44 100644 --- a/controller/ofctrl.c +++ b/controller/ofctrl.c @@ -101,6 +101,39 @@ struct ovn_flow { * * The links are updated whenever there is a change in desired flows, which is * usually triggered by a SB data change in I-P engine. + * + * ** Tracking ** + * + * A desired flow can be tracked - listed in ovn_desired_flow_table's + * tracked_flows. + * + * Tracked flows is initially empty, and stays empty after the first run of I-P + * engine when installed flows are initially populated. After that, flow + * changes are tracked when I-P engine incrementally computes flow changes. + * Tracked flows are then processed and removed completely in ofctrl_put. + * ("processed" means OpenFlow change messages are composed and sent/queued to + * OVS, which ensures flows in OVS is always in sync (eventually) with the + * installed flows table). + * + * In case of full recompute of I-P engine, tracked flows are not + * added/removed, and ofctrl_put will not rely on tracked flows. (It is I-P + * engine's responsibility to ensure the tracked flows are cleared before + * recompute). + * + * Tracked flows can be preserved across multiple I-P engine runs - if in some + * iterations ofctrl_put() is skipped. Tracked flows are cleared only when it + * is consumed or when flow recompute happens. + * + * The "change_tracked" member of desired flow table maintains the status of + * whether flow changes are tracked or not. It is always set to true when + * ofctrl_put is completed, and transition to false whenever + * ovn_desired_flow_table_clear is called. + * + * NOTE: A tracked flow is just a reference to a desired flow, instead of a
[ovs-dev] [PATCH ovn branch-20.06 03/15] ofctrl.c: Refactor - move openflow msg construction to functions.
These functions will be reused in multiple places in a future patch. Acked-by: Mark Michelson Signed-off-by: Han Zhou (cherry picked from commit 23063cf4178c05f5d6b3e4ec6d323ccc88df6101) Signed-off-by: Frode Nordahl --- controller/ofctrl.c | 103 ++-- 1 file changed, 60 insertions(+), 43 deletions(-) diff --git a/controller/ofctrl.c b/controller/ofctrl.c index a28c6b759..98e291243 100644 --- a/controller/ofctrl.c +++ b/controller/ofctrl.c @@ -1481,6 +1481,63 @@ add_meter(struct ovn_extend_table_info *m_desired, free(mm.meter.bands); } +static void +installed_flow_add(struct ovn_flow *d, struct ovs_list *msgs) +{ +/* Send flow_mod to add flow. */ +struct ofputil_flow_mod fm = { +.match = d->match, +.priority = d->priority, +.table_id = d->table_id, +.ofpacts = d->ofpacts, +.ofpacts_len = d->ofpacts_len, +.new_cookie = htonll(d->cookie), +.command = OFPFC_ADD, +}; +add_flow_mod(, msgs); +} + +static void +installed_flow_mod(struct ovn_flow *i, struct ovn_flow *d, + struct ovs_list *msgs) +{ +/* Update actions in installed flow. */ +struct ofputil_flow_mod fm = { +.match = i->match, +.priority = i->priority, +.table_id = i->table_id, +.ofpacts = d->ofpacts, +.ofpacts_len = d->ofpacts_len, +.command = OFPFC_MODIFY_STRICT, +}; +/* Update cookie if it is changed. */ +if (i->cookie != d->cookie) { +fm.modify_cookie = true; +fm.new_cookie = htonll(d->cookie); +/* Use OFPFC_ADD so that cookie can be updated. */ +fm.command = OFPFC_ADD; +} +add_flow_mod(, msgs); + +/* Replace 'i''s actions and cookie by 'd''s. */ +free(i->ofpacts); +i->ofpacts = xmemdup(d->ofpacts, d->ofpacts_len); +i->ofpacts_len = d->ofpacts_len; +i->cookie = d->cookie; +} + +static void +installed_flow_del(struct ovn_flow *i, struct ovs_list *msgs) +{ +struct ofputil_flow_mod fm = { +.match = i->match, +.priority = i->priority, +.table_id = i->table_id, +.command = OFPFC_DELETE_STRICT, +}; +add_flow_mod(, msgs); +} + /* The flow table can be updated if the connection to the switch is up and * in the correct state and not backlogged with existing flow_mods. (Our * criteria for being backlogged appear very conservative, but the socket @@ -1606,46 +1663,16 @@ ofctrl_put(struct ovn_desired_flow_table *flow_table, if (!d) { /* Installed flow is no longer desirable. Delete it from the * switch and from installed_flows. */ -struct ofputil_flow_mod fm = { -.match = i->flow.match, -.priority = i->flow.priority, -.table_id = i->flow.table_id, -.command = OFPFC_DELETE_STRICT, -}; -add_flow_mod(, ); +installed_flow_del(>flow, ); ovn_flow_log(>flow, "removing installed"); - hmap_remove(_flows, >match_hmap_node); installed_flow_destroy(i); } else { if (!ofpacts_equal(i->flow.ofpacts, i->flow.ofpacts_len, d->flow.ofpacts, d->flow.ofpacts_len) || i->flow.cookie != d->flow.cookie) { -/* Update actions in installed flow. */ -struct ofputil_flow_mod fm = { -.match = i->flow.match, -.priority = i->flow.priority, -.table_id = i->flow.table_id, -.ofpacts = d->flow.ofpacts, -.ofpacts_len = d->flow.ofpacts_len, -.command = OFPFC_MODIFY_STRICT, -}; -/* Update cookie if it is changed. */ -if (i->flow.cookie != d->flow.cookie) { -fm.modify_cookie = true; -fm.new_cookie = htonll(d->flow.cookie); -/* Use OFPFC_ADD so that cookie can be updated. */ -fm.command = OFPFC_ADD, -i->flow.cookie = d->flow.cookie; -} -add_flow_mod(, ); ovn_flow_log(>flow, "updating installed"); - -/* Replace 'i''s actions by 'd''s. */ -free(i->flow.ofpacts); -i->flow.ofpacts = xmemdup(d->flow.ofpacts, - d->flow.ofpacts_len); -i->flow.ofpacts_len = d->flow.ofpacts_len; +installed_flow_mod(>flow, >flow, ); } link_installed_to_desired(i, d); @@ -1658,17 +1685,7 @@ ofctrl_put(struct ovn_desired_flow_table *flow_table, HMAP_FOR_EACH (d, match_hmap_node, _table->match_flow_table) { i = installed_flow_lookup(>flow); if (!i) { -/* Send flow_mod to add flow. */ -struct ofputil_flow_mod fm = { -
[ovs-dev] [PATCH ovn branch-20.06 02/15] ofctrl.c: Maintain references between installed flows and desired flows.
Currently there is no link maintained between installed flows and desired flows. This patch maintains the mapping between them, which will be useful for a future patch that incrementally processes the flow installation without having to do the full comparison between them. This patch also refactors the struct ovn_flow with two different wrapper types: desired_flow and installed_flow, and the related static functions, to make the code easier to read and avoid misuses of the struct. Acked-by: Mark Michelson Signed-off-by: Han Zhou (cherry picked from commit 354d3853d40cbce89a434632f67daed7fc992d8b) Signed-off-by: Frode Nordahl --- controller/ofctrl.c | 428 ++-- 1 file changed, 294 insertions(+), 134 deletions(-) diff --git a/controller/ofctrl.c b/controller/ofctrl.c index 11832b8d7..a28c6b759 100644 --- a/controller/ofctrl.c +++ b/controller/ofctrl.c @@ -51,7 +51,27 @@ VLOG_DEFINE_THIS_MODULE(ofctrl); -/* An OpenFlow flow. +/* An OpenFlow flow. */ +struct ovn_flow { +/* Key. */ +uint8_t table_id; +uint16_t priority; +struct minimatch match; + +/* Hash. */ +uint32_t hash; + +/* Data. */ +struct ofpact *ofpacts; +size_t ofpacts_len; +uint64_t cookie; +}; + +/* A desired flow, in struct ovn_desired_flow_table, calculated by the + * incremental processing engine. + * - They are added/removed incrementally when I-P engine is able to process + * the changes incrementally, or + * - Completely cleared and recomputed by I-P engine when recompute happens. * * Links are maintained between desired flows and SB data. The relationship * is M to N. The struct sb_flow_ref is used to link a pair of desired flow @@ -82,52 +102,92 @@ VLOG_DEFINE_THIS_MODULE(ofctrl); * The links are updated whenever there is a change in desired flows, which is * usually triggered by a SB data change in I-P engine. */ -struct ovn_flow { +struct desired_flow { +struct ovn_flow flow; struct hmap_node match_hmap_node; /* For match based hashing. */ struct ovs_list list_node; /* For handling lists of flows. */ -struct ovs_list references; /* A list of struct sb_flow_ref nodes, which - references this flow. (There are cases - that multiple SB entities share the same - desired OpenFlow flow, e.g. when - conjunction is used.) */ -/* Key. */ -uint8_t table_id; -uint16_t priority; -struct minimatch match; +/* A list of struct sb_flow_ref nodes, which references this flow. (There + * are cases that multiple SB entities share the same desired OpenFlow + * flow, e.g. when conjunction is used.) */ +struct ovs_list references; -/* Data. */ -struct ofpact *ofpacts; -size_t ofpacts_len; -uint64_t cookie; +/* The corresponding flow in installed table. */ +struct installed_flow *installed_flow; + +/* Node in installed_flow.desired_refs list. */ +struct ovs_list installed_ref_list_node; }; struct sb_to_flow { struct hmap_node hmap_node; /* Node in ovn_desired_flow_table.uuid_flow_table. */ struct uuid sb_uuid; -struct ovs_list flows; /* A list of struct sb_flow_ref nodes that are - referenced by the sb_uuid. */ +struct ovs_list flows; /* A list of struct sb_flow_ref nodes that + are referenced by the sb_uuid. */ }; struct sb_flow_ref { -struct ovs_list sb_list; /* List node in ovn_flow.references. */ -struct ovs_list flow_list; /* List node in sb_to_flow.ovn_flows. */ -struct ovn_flow *flow; +struct ovs_list sb_list; /* List node in desired_flow.references. */ +struct ovs_list flow_list; /* List node in sb_to_flow.desired_flows. */ +struct desired_flow *flow; struct uuid sb_uuid; }; -static struct ovn_flow *ovn_flow_alloc(uint8_t table_id, uint16_t priority, - uint64_t cookie, - const struct match *match, - const struct ofpbuf *actions); +/* A installed flow, in static variable installed_flows. + * + * Installed flows are updated in ofctrl_put for maintaining the flow + * installation to OVS. They are updated according to desired flows: either by + * processing the tracked desired flow changes, or by comparing desired flows + * with currently installed flows when tracked desired flows changes are not + * available. + * + * In addition, when ofctrl state machine enters S_CLEAR, the installed flows + * will be cleared. (This happens in initialization phase and also when + * ovs-vswitchd is disconnected/reconnected). + * + * Links are maintained between installed flows and desired flows. The + * relationship is 1 to N. A link is added when a flow addition is processed. + * A
[ovs-dev] [PATCH ovn branch-20.06 01/15] ovn-ctl: Handle cluster db upgrades for run_(nb/sb)_ovsdb
when ovn-ctl run_(nb_sb)_ovsdb is called, the ovsdb-server is started without passing --detach and --monoitor and the process is exec'd. For cluster mode, upgrade_cluster is never called and hence the dbs are not upraded to new schema. CMS has to handle the db upgrade separately. This patch handles the db upgrade by starting ovsdb-server in background and then waits on ovsdb-server to complete. Reported-at: https://bugzilla.redhat.com/show_bug.cgi?id=1868392 Acked-by: Mark Michelson Signed-off-by: Numan Siddique (cherry picked from commit 67e2f386cc838d0b0f9b4b5da7fe611e1113b70c) Signed-off-by: Frode Nordahl --- utilities/ovn-ctl | 20 +++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/utilities/ovn-ctl b/utilities/ovn-ctl index 8afe68a0a..ad8e6bb04 100755 --- a/utilities/ovn-ctl +++ b/utilities/ovn-ctl @@ -288,7 +288,21 @@ $cluster_remote_port set "$@" --sync-from=`cat $active_conf_file` fi -"$@" "$file" +local run_ovsdb_in_bg="no" +local process_id= +if test X$detach = Xno && test $mode = cluster && test -z "$cluster_remote_addr" ; then +# When detach is no (for run_nb_ovsdb/run_sb_ovsdb commands) +# we want to run ovsdb-server in background rather than running it in +# foreground so that the OVN dbs are upgraded for the cluster mode. +# Otherwise, CMS has to take the responsibility of upgrading the dbs. +# Note: We run only the ovsdb-server in backgroud which created the +# cluster (i.e cluster_remote_addr is not set.). +run_ovsdb_in_bg="yes" +"$@" $file & +process_id=$! +else +start_wrapped_daemon "$wrapper" ovsdb-$db "" "$@" "$file" +fi # Initialize the database if it's NOT joining a cluster. if test -z "$cluster_remote_addr"; then @@ -298,6 +312,10 @@ $cluster_remote_port if test $mode = cluster; then upgrade_cluster "$schema" "unix:$sock" fi + +if test $run_ovsdb_in_bg = yes; then +wait $process_id +fi } start_nb_ovsdb() { -- 2.30.0 ___ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev
[ovs-dev] [PATCH ovn branch-20.06 00/15] Backport rollup
Hello all, In Ubuntu we have backported a set of fixes to our OVN 20.06 and OVN 20.03 packages. In preparing for new point releases for OVN 20.06 and OVN 20.03, we would very much like to add these patches to the upstream branches. The issues solved for OVN 20.06 with these patches are: * Fix for upgrading database schema of clustered databases on package upgrade (LP: #1907081)[0] * Fixes for predictable resolution for conflicting flow actions. (LP: #1906922)[1] We are cognizant of the large number of patches required to cleanly backport the conflicting flow actions fixes, and have verified the end result thouroughly. From our experience these fixes are required to use OVN with OpenStack in a meaningful way, for example with k8s on top of OpenStack. 0: https://bugs.launchpad.net/bugs/1907081 1: https://bugs.launchpad.net/bugs/1906922 Dumitru Ceara (8): ofctrl.c: Only merge actions for conjunctive flows. ofctrl.c: Do not change flow ordering when merging opposite changes. ofctrl.c: Simplify active desired flow selection. ofctrl.c: Always log the most recent flow changes. ofctrl.c: Add a predictable resolution for conflicting flow actions. ovn.at: Make some of the tests more predictable. tests: Add ofctl_strip_all() to filter OVS flow outputs. tests: Fix test "ovn -- Superseding ACLs with conjunction". Han Zhou (6): ofctrl.c: Maintain references between installed flows and desired flows. ofctrl.c: Refactor - move openflow msg construction to functions. ofctrl: Incremental processing for flow installation by tracking. ofctrl.c: Merge opposite changes of tracked flows before installing. ofctrl.c: Fix duplicated flow handling in I-P while merging opposite changes. ofctrl.c: Avoid repeatedly linking an installed flow and a desired flow. Numan Siddique (1): ovn-ctl: Handle cluster db upgrades for run_(nb/sb)_ovsdb controller/ofctrl.c | 966 controller/ofctrl.h | 6 +- tests/ofproto-macros.at | 23 +- tests/ovn.at| 328 ++ utilities/ovn-ctl | 20 +- 5 files changed, 1156 insertions(+), 187 deletions(-) -- 2.30.0 ___ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev