Re: [ovs-dev] [PATCH net v2 1/1] openvswitch: Fix setting ipv6 fields causing hw csum failure

2022-02-14 Thread Jakub Kicinski
On Mon, 14 Feb 2022 14:48:51 +0200 Paul Blakey wrote:
> Ipv6 ttl, label and tos fields are modified without first
> pulling/pushing the ipv6 header, which would have updated
> the hw csum (if available). This might cause csum validation
> when sending the packet to the stack, as can be seen in
> the trace below.
> 
> Fix this by updating skb->csum if available.

> Fixes: 3fdbd1ce11e5 ("openvswitch: add ipv6 'set' action")
> Signed-off-by: Paul Blakey 
> ---
>  Changelog:
> v1->v2:
>   Replaced push pull rcsum checksum calc with actual checksum calc

Well, what I had in mind was an skb helper which would take skb, u32
new_val, u32 old_val, but this works, too.

Please fix the new sparse warnings tho, and..

> diff --git a/net/openvswitch/actions.c b/net/openvswitch/actions.c
> index 076774034bb9..3725801cb040 100644
> --- a/net/openvswitch/actions.c
> +++ b/net/openvswitch/actions.c
> @@ -423,12 +423,44 @@ static void set_ipv6_addr(struct sk_buff *skb, u8 
> l4_proto,
>   memcpy(addr, new_addr, sizeof(__be32[4]));
>  }
>  
> -static void set_ipv6_fl(struct ipv6hdr *nh, u32 fl, u32 mask)
> +static void set_ipv6_dsfield(struct sk_buff *skb, struct ipv6hdr *nh, __u8 
> ipv6_tclass, __u8 mask)
>  {
> + __u8 old_ipv6_tclass = ipv6_get_dsfield(nh);

use normal u8, __u8 is for uAPI.

___
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev


[ovs-dev] [PATCH v5 2/2] ofproto-dpif: avoid unneccesary backer revalidation

2022-02-14 Thread lic121
If lldp didn't change, we are not supposed to trigger backer
revalidation.
Without this patch, bridge_reconfigure() always trigger udpif
revalidator because of lldp.

This patch also fix lldp memory leak bug:
lldp_create() malloc memory for lldp->lldpd->g_hardware. lldp_unref
is supposed to free the memory, but it doesn't.

Signed-off-by: lic121 
Signed-off-by: Eelco Chaudron 
Co-authored-by: Eelco Chaudron 
---
 lib/lldp/lldpd.c   | 10 +++---
 lib/ovs-lldp.c |  8 
 lib/ovs-lldp.h |  1 +
 ofproto/ofproto-dpif.c |  7 +--
 tests/ofproto-dpif.at  | 33 +
 5 files changed, 50 insertions(+), 9 deletions(-)

diff --git a/lib/lldp/lldpd.c b/lib/lldp/lldpd.c
index a024dc5..ee1051d 100644
--- a/lib/lldp/lldpd.c
+++ b/lib/lldp/lldpd.c
@@ -140,13 +140,9 @@ lldpd_cleanup(struct lldpd *cfg)
 VLOG_DBG("cleanup all ports");

 LIST_FOR_EACH_SAFE (hw, hw_next, h_entries, >g_hardware) {
-if (!hw->h_flags) {
-ovs_list_remove(>h_entries);
-lldpd_remote_cleanup(hw, NULL, true);
-lldpd_hardware_cleanup(cfg, hw);
-} else {
-lldpd_remote_cleanup(hw, NULL, false);
-}
+ovs_list_remove(>h_entries);
+lldpd_remote_cleanup(hw, NULL, true);
+lldpd_hardware_cleanup(cfg, hw);
 }

 VLOG_DBG("cleanup all chassis");
diff --git a/lib/ovs-lldp.c b/lib/ovs-lldp.c
index 162311f..bfc69a3 100644
--- a/lib/ovs-lldp.c
+++ b/lib/ovs-lldp.c
@@ -738,6 +738,14 @@ lldp_put_packet(struct lldp *lldp, struct dp_packet 
*packet,
 ovs_mutex_unlock();
 }

+/* Is LLDP enabled?
+ */
+bool
+lldp_is_enabled(struct lldp *lldp)
+{
+return lldp ? lldp->enabled : false;
+}
+
 /* Configures the LLDP stack.
  */
 bool
diff --git a/lib/ovs-lldp.h b/lib/ovs-lldp.h
index 0e536e8..661ac4e 100644
--- a/lib/ovs-lldp.h
+++ b/lib/ovs-lldp.h
@@ -86,6 +86,7 @@ void lldp_run(struct lldpd *cfg);
 bool lldp_should_send_packet(struct lldp *cfg);
 bool lldp_should_process_flow(struct lldp *lldp, const struct flow *flow);
 bool lldp_configure(struct lldp *lldp, const struct smap *cfg);
+bool lldp_is_enabled(struct lldp *lldp);
 void lldp_process_packet(struct lldp *cfg, const struct dp_packet *);
 void lldp_put_packet(struct lldp *lldp, struct dp_packet *packet,
  const struct eth_addr eth_src);
diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c
index ced67b0..a580fd4 100644
--- a/ofproto/ofproto-dpif.c
+++ b/ofproto/ofproto-dpif.c
@@ -2499,11 +2499,11 @@ set_lldp(struct ofport *ofport_,
 {
 struct ofport_dpif *ofport = ofport_dpif_cast(ofport_);
 struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofport->up.ofproto);
+bool old_enable = lldp_is_enabled(ofport->lldp);
 int error = 0;

-if (cfg) {
+if (cfg && !smap_is_empty(cfg)) {
 if (!ofport->lldp) {
-ofproto->backer->need_revalidate = REV_RECONFIGURE;
 ofport->lldp = lldp_create(ofport->up.netdev, ofport_->mtu, cfg);
 }

@@ -2515,6 +2515,9 @@ set_lldp(struct ofport *ofport_,
 } else if (ofport->lldp) {
 lldp_unref(ofport->lldp);
 ofport->lldp = NULL;
+}
+
+if (lldp_is_enabled(ofport->lldp) != old_enable) {
 ofproto->backer->need_revalidate = REV_RECONFIGURE;
 }

diff --git a/tests/ofproto-dpif.at b/tests/ofproto-dpif.at
index 7f273e5..edb6aa1 100644
--- a/tests/ofproto-dpif.at
+++ b/tests/ofproto-dpif.at
@@ -29,6 +29,39 @@ AT_CHECK([ovs-appctl revalidator/wait])
 OVS_VSWITCHD_STOP
 AT_CLEANUP

+AT_SETUP([ofproto-dpif - lldp revalidator event(REV_RECONFIGURE)])
+OVS_VSWITCHD_START(
+[add-port br0 p1 -- set interface p1 ofport_request=1 type=dummy]
+)
+dnl first revalidation triggered by add interface
+AT_CHECK([ovs-appctl coverage/read-counter rev_reconfigure], [0], [dnl
+1
+])
+
+dnl enable lldp
+AT_CHECK([ovs-vsctl set interface p1 lldp:enable=true])
+AT_CHECK([ovs-appctl revalidator/wait])
+AT_CHECK([ovs-appctl coverage/read-counter rev_reconfigure], [0], [dnl
+2
+])
+
+dnl disable lldp
+AT_CHECK([ovs-vsctl set interface p1 lldp:enable=false])
+AT_CHECK([ovs-appctl revalidator/wait])
+AT_CHECK([ovs-appctl coverage/read-counter rev_reconfigure], [0], [dnl
+3
+])
+
+dnl remove lldp, no revalidation as lldp was disabled
+AT_CHECK([ovs-vsctl remove interface p1 lldp enable])
+AT_CHECK([ovs-appctl revalidator/wait])
+AT_CHECK([ovs-appctl coverage/read-counter rev_reconfigure], [0], [dnl
+3
+])
+
+OVS_VSWITCHD_STOP
+AT_CLEANUP
+
 AT_SETUP([ofproto-dpif - active-backup bonding (with primary)])

 dnl Create br0 with members p1, p2 and p7, creating bond0 with p1 and
--
1.8.3.1

___
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev


[ovs-dev] [PATCH v5 1/2] ofproto-dpif: trigger revalidation when ipfix config set

2022-02-14 Thread lic121
Currently, ipfix conf creation/deletion don't trigger dpif backer
revalidation. This is not expected, as we need the revalidation
to commit ipfix into xlate. So that xlate can generate ipfix
actions.

This patch covers only new creation/deletion of ipfix config.
Will upload one more patch to cover ipfix option changes.

Signed-off-by: lic121 
---
 ofproto/ofproto-dpif.c | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c
index 8143dd9..ced67b0 100644
--- a/ofproto/ofproto-dpif.c
+++ b/ofproto/ofproto-dpif.c
@@ -2371,6 +2371,12 @@ set_ipfix(
 dpif_ipfix_unref(di);
 ofproto->ipfix = NULL;
 }
+
+/* TODO: need to consider ipfix option changes more than
+ * enable/disable */
+if (new_di || !ofproto->ipfix) {
+ofproto->backer->need_revalidate = REV_RECONFIGURE;
+}
 }

 return 0;
--
1.8.3.1

___
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev


[ovs-dev] [PATCH v5 0/2] fix dpif backer revalidation

2022-02-14 Thread lic121
v5:
- merge patch #2 and patch #3 to retrigger CI, as it could be failed
  by anccident.

v4:
- fix lldp memory leak
- add '!smap_is_empty(cfg)' condition

v3:
- fix lldp test case failure

v2:
- add TODO comments to clear ipfix patch coverage
- test lldp enabling more than pointer
- add test cases for lldp

ovsdb change or netlink notification trigger bridge_reconfigure.
In bridge_reconfigure, backer->need_revalidate flag is set if backer
revalidation is needed.

This series fix two places where need_revalidate flag is not set
correctly.

lic121 (2):
  ofproto-dpif: trigger revalidation when ipfix config set
  ofproto-dpif: avoid unneccesary backer revalidation

 lib/lldp/lldpd.c   | 10 +++---
 lib/ovs-lldp.c |  8 
 lib/ovs-lldp.h |  1 +
 ofproto/ofproto-dpif.c | 13 +++--
 tests/ofproto-dpif.at  | 33 +
 5 files changed, 56 insertions(+), 9 deletions(-)

--
1.8.3.1

___
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev


Re: [ovs-dev] [PATCH ovn 12/15] Introduce LSP:options:requested-additional-chassis

2022-02-14 Thread 0-day Robot
Bleep bloop.  Greetings Ihar Hrachyshka, 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.


build:
-e 's,[@]PKIDIR[@],/usr/local/var/lib/openvswitch/pki,g' \
-e 's,[@]LOGDIR[@],/usr/local/var/log/ovn,g' \
-e 's,[@]DBDIR[@],/usr/local/etc/ovn,g' \
-e 's,[@]PYTHON3[@],/bin/python3,g' \
-e 's,[@]OVN_RUNDIR[@],/usr/local/var/run/ovn,g' \
-e 
's,[@]OVSBUILDDIR[@],/var/lib/jenkins/jobs/0day_robot_upstream_build_ovn_from_pw/workspace/OVSDIR,g'
 \
-e 's,[@]VERSION[@],21.12.90,g' \
-e 's,[@]OVSVERSION[@],2.17.90,g' \
-e 's,[@]localstatedir[@],/usr/local/var,g' \
-e 's,[@]pkgdatadir[@],/usr/local/share/ovn,g' \
-e 's,[@]sysconfdir[@],/usr/local/etc,g' \
-e 's,[@]bindir[@],/usr/local/bin,g' \
-e 's,[@]sbindir[@],/usr/local/sbin,g' \
-e 
's,[@]abs_builddir[@],/var/lib/jenkins/jobs/0day_robot_upstream_build_ovn_from_pw/workspace,g'
 \
-e 
's,[@]abs_top_srcdir[@],/var/lib/jenkins/jobs/0day_robot_upstream_build_ovn_from_pw/workspace,g'
 \
  > utilities/ovn-lib.tmp
mv utilities/ovn-lib.tmp utilities/ovn-lib
/bin/sh 
/var/lib/jenkins/jobs/0day_robot_upstream_build_ovn_from_pw/workspace/build-aux/missing
 autom4te --language=autotest -I '.' -o tests/testsuite.tmp tests/testsuite.at
mv tests/testsuite.tmp tests/testsuite
touch -c manpage-check
./build-aux/cksum-schema-check ovn-sb.ovsschema ovn-sb.ovsschema.stamp
ovn-sb.ovsschema:4: The checksum "2080576408 27879" was calculated from the 
schema file and does not match cksum field in the schema file - you should 
probably update the version number and the checksum in the schema file with the 
value listed here.
make[1]: *** [ovn-sb.ovsschema.stamp] Error 1
make[1]: Leaving directory 
`/var/lib/jenkins/jobs/0day_robot_upstream_build_ovn_from_pw/workspace'
make: *** [all] Error 2


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 13/15] Clone packets to both port chassis

2022-02-14 Thread Ihar Hrachyshka
When requested-additional-chassis is set, port binding is configured
in two cluster locations. In case of live migration scenario, only one
of the locations run a workload at a particular point in time. Yet,
it's expected that the workload may switch to running at the
additional-chassis at any moment during live migration (depends on
libvirt / qemu migration progress). To speed up the switch to near
instant, do the following:

When a port located sends a packet to another port that has two
chassis then, in addition to sending the packet to the main chassis,
also send it to the additional chassis. When the sending port is bound
on either the main or additional chassis, then handle the packet
locally plus send it to the other chassis.

This is achieved with additional flows in tables 37 and 38.

Signed-off-by: Ihar Hrachyshka 
---
 controller/physical.c | 180 +++
 tests/ovn.at  | 335 ++
 2 files changed, 486 insertions(+), 29 deletions(-)

diff --git a/controller/physical.c b/controller/physical.c
index bc4f7c4f0..8aa94d850 100644
--- a/controller/physical.c
+++ b/controller/physical.c
@@ -287,12 +287,13 @@ match_outport_dp_and_port_keys(struct match *match,
 }
 
 static void
-put_remote_port_redirect_overlay(const struct
- sbrec_port_binding *binding,
+put_remote_port_redirect_overlay(const struct sbrec_port_binding *binding,
  bool is_ha_remote,
  struct ha_chassis_ordered *ha_ch_ordered,
  enum mf_field_id mff_ovn_geneve,
  const struct chassis_tunnel *tun,
+ const struct chassis_tunnel *additional_tun,
+ uint32_t dp_key,
  uint32_t port_key,
  struct match *match,
  struct ofpbuf *ofpacts_p,
@@ -301,14 +302,51 @@ put_remote_port_redirect_overlay(const struct
 {
 if (!is_ha_remote) {
 /* Setup encapsulation */
-if (!tun) {
-return;
+bool is_vtep = !strcmp(binding->type, "vtep");
+if (!additional_tun) {
+/* Output to main chassis tunnel. */
+put_encapsulation(mff_ovn_geneve, tun, binding->datapath, port_key,
+  is_vtep, ofpacts_p);
+ofpact_put_OUTPUT(ofpacts_p)->port = tun->ofport;
+
+ofctrl_add_flow(flow_table, OFTABLE_REMOTE_OUTPUT, 100,
+binding->header_.uuid.parts[0],
+match, ofpacts_p, >header_.uuid);
+} else {
+/* For packets arriving from tunnels, don't clone to avoid sending
+ * packets received from another chassis back to it. */
+match_outport_dp_and_port_keys(match, dp_key, port_key);
+match_set_reg_masked(match, MFF_LOG_FLAGS - MFF_REG0,
+ MLF_LOCAL_ONLY, MLF_LOCAL_ONLY);
+
+/* Output to main chassis tunnel. */
+put_encapsulation(mff_ovn_geneve, tun, binding->datapath, port_key,
+  is_vtep, ofpacts_p);
+ofpact_put_OUTPUT(ofpacts_p)->port = tun->ofport;
+
+ofctrl_add_flow(flow_table, OFTABLE_REMOTE_OUTPUT, 110,
+binding->header_.uuid.parts[0], match, ofpacts_p,
+>header_.uuid);
+
+/* For packets originating from this chassis, clone in addition to
+ * handling it locally. */
+match_outport_dp_and_port_keys(match, dp_key, port_key);
+ofpbuf_clear(ofpacts_p);
+
+/* Output to main chassis tunnel. */
+put_encapsulation(mff_ovn_geneve, tun, binding->datapath, port_key,
+  is_vtep, ofpacts_p);
+ofpact_put_OUTPUT(ofpacts_p)->port = tun->ofport;
+
+/* Output to additional chassis tunnel. */
+put_encapsulation(mff_ovn_geneve, additional_tun,
+  binding->datapath, port_key, is_vtep, ofpacts_p);
+ofpact_put_OUTPUT(ofpacts_p)->port = additional_tun->ofport;
+
+ofctrl_add_flow(flow_table, OFTABLE_REMOTE_OUTPUT, 100,
+binding->header_.uuid.parts[0], match, ofpacts_p,
+>header_.uuid);
 }
-put_encapsulation(mff_ovn_geneve, tun, binding->datapath, port_key,
-  !strcmp(binding->type, "vtep"),
-  ofpacts_p);
-/* Output to tunnel. */
-ofpact_put_OUTPUT(ofpacts_p)->port = tun->ofport;
 } else {
 /* Make sure all tunnel endpoints use the same encapsulation,
  * and set it up */
@@ -376,10 +414,11 @@ put_remote_port_redirect_overlay(const struct
 bundle->basis = 0;
 bundle->fields = 

[ovs-dev] [PATCH ovn 15/15] Implement RARP activation strategy for ports

2022-02-14 Thread Ihar Hrachyshka
When options:activation-strategy is set to "rarp" for LSP, when used in
combination with options:requested-additional-chassis, the additional
chassis will install special flows that would block all ingress and
egress traffic for the port until a special activation event happens.

For "rarp" strategy, an observation of a RARP packet sent from the port
on the additional chassis is such an event. When it occurs, a special
flow passes control to a controller() action handler that removes the
installed blocking flows and also marks the port as
options:additional-chassis-activated in southbound db. Once vswitchd
processes the flow mod request, the port is ready to communicate from
the new location.

This feature is useful in live migration scenarios where it's not
advisable to unlock the destination port location prematurily to avoid
duplicate packets originating from the port.

Signed-off-by: Ihar Hrachyshka 
---
 controller/physical.c |  74 +++
 controller/pinctrl.c  | 161 +-
 controller/pinctrl.h  |   2 +
 include/ovn/actions.h |   9 +++
 lib/actions.c |  40 ++-
 northd/northd.c   |   7 ++
 northd/ovn-northd.c   |   5 +-
 ovn-nb.xml|  10 +++
 ovn-sb.xml|  15 
 tests/ovn.at  | 160 +
 utilities/ovn-trace.c |   3 +
 11 files changed, 482 insertions(+), 4 deletions(-)

diff --git a/controller/physical.c b/controller/physical.c
index 5d1598116..4bb0ed317 100644
--- a/controller/physical.c
+++ b/controller/physical.c
@@ -40,7 +40,9 @@
 #include "lib/mcast-group-index.h"
 #include "lib/ovn-sb-idl.h"
 #include "lib/ovn-util.h"
+#include "ovn/actions.h"
 #include "physical.h"
+#include "pinctrl.h"
 #include "openvswitch/shash.h"
 #include "simap.h"
 #include "smap.h"
@@ -988,6 +990,59 @@ get_additional_tunnel(const struct sbrec_port_binding 
*binding,
 return tun;
 }
 
+static void
+setup_rarp_activation_strategy(const struct sbrec_port_binding *binding,
+   struct ovn_desired_flow_table *flow_table,
+   struct ofpbuf *ofpacts_p)
+{
+struct match match = MATCH_CATCHALL_INITIALIZER;
+uint32_t dp_key = binding->datapath->tunnel_key;
+uint32_t port_key = binding->tunnel_key;
+
+/* Unblock the port on ingress RARP. */
+match_set_metadata(, htonll(dp_key));
+match_set_dl_type(, htons(ETH_TYPE_RARP));
+match_set_reg(, MFF_LOG_INPORT - MFF_REG0, port_key);
+ofpbuf_clear(ofpacts_p);
+
+size_t ofs = ofpacts_p->size;
+struct ofpact_controller *oc = ofpact_put_CONTROLLER(ofpacts_p);
+oc->max_len = UINT16_MAX;
+oc->reason = OFPR_ACTION;
+oc->pause = true;
+
+struct action_header ah = {
+.opcode = htonl(ACTION_OPCODE_ACTIVATION_STRATEGY_RARP)
+};
+ofpbuf_put(ofpacts_p, , sizeof ah);
+
+ofpacts_p->header = oc;
+oc->userdata_len = ofpacts_p->size - (ofs + sizeof *oc);
+ofpact_finish_CONTROLLER(ofpacts_p, );
+
+ofctrl_add_flow(flow_table, OFTABLE_LOG_INGRESS_PIPELINE, 1010,
+binding->header_.uuid.parts[0],
+, ofpacts_p, >header_.uuid);
+ofpbuf_clear(ofpacts_p);
+
+/* Block all non-RARP traffic for the port, both directions. */
+match_init_catchall();
+match_set_metadata(, htonll(dp_key));
+match_set_reg(, MFF_LOG_INPORT - MFF_REG0, port_key);
+
+ofctrl_add_flow(flow_table, OFTABLE_LOG_INGRESS_PIPELINE, 1000,
+binding->header_.uuid.parts[0],
+, ofpacts_p, >header_.uuid);
+
+match_init_catchall();
+match_set_metadata(, htonll(dp_key));
+match_set_reg(, MFF_LOG_OUTPORT - MFF_REG0, port_key);
+
+ofctrl_add_flow(flow_table, OFTABLE_LOG_EGRESS_PIPELINE, 1000,
+binding->header_.uuid.parts[0],
+, ofpacts_p, >header_.uuid);
+}
+
 static void
 consider_port_binding(struct ovsdb_idl_index *sbrec_port_binding_by_name,
   enum mf_field_id mff_ovn_geneve,
@@ -1212,6 +1267,25 @@ consider_port_binding(struct ovsdb_idl_index 
*sbrec_port_binding_by_name,
 }
 }
 
+if (binding->additional_chassis == chassis) {
+const char *strategy = smap_get(>options,
+"activation-strategy");
+if (strategy
+&& !smap_get_bool(>options,
+  "additional-chassis-activated", false)
+&& !pinctrl_is_port_activated(dp_key, port_key)) {
+if (!strcmp(strategy, "rarp")) {
+setup_rarp_activation_strategy(binding, flow_table, ofpacts_p);
+} else {
+static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 1);
+VLOG_WARN_RL(,
+ "Unknown activation strategy defined for "
+ "port %s: %s", binding->logical_port, strategy);
+goto out;
+

[ovs-dev] [PATCH ovn 12/15] Introduce LSP:options:requested-additional-chassis

2022-02-14 Thread Ihar Hrachyshka
If used in conjunction with requested-chassis, OVN will attempt to
bind the port at another location in addition to the main chassis.

This is useful in live migration scenarios where it's important to
prepare the environment for workloads to move to, avoiding costly flow
configuration at the moment of the final port binding location change.

The patch mimics behavior of requested-chassis. Corresponding database
fields (pb->additional_chassis, pb->requested_additional_chassis,
pb->additional_encap) are introduced as part of the patch.

Signed-off-by: Ihar Hrachyshka 
---
 controller/binding.c | 178 +--
 controller/lport.c   |  19 -
 northd/northd.c  |  64 +---
 northd/ovn-northd.c  |   4 +-
 ovn-nb.xml   |   8 ++
 ovn-sb.ovsschema |  15 +++-
 ovn-sb.xml   |  58 +-
 tests/ovn.at |  91 ++
 8 files changed, 379 insertions(+), 58 deletions(-)

diff --git a/controller/binding.c b/controller/binding.c
index c7a13d5d5..ec8bff3d8 100644
--- a/controller/binding.c
+++ b/controller/binding.c
@@ -912,6 +912,26 @@ claimed_lport_set_up(const struct sbrec_port_binding *pb,
 }
 }
 
+typedef void (*set_func)(const struct sbrec_port_binding *pb,
+ const struct sbrec_encap *);
+
+static bool
+update_port_encap_if_needed(const struct sbrec_port_binding *pb,
+const struct sbrec_chassis *chassis_rec,
+const struct ovsrec_interface *iface_rec,
+bool sb_readonly, set_func f)
+{
+const struct sbrec_encap *encap_rec =
+sbrec_get_port_encap(chassis_rec, iface_rec);
+if (encap_rec && pb->encap != encap_rec) {
+if (sb_readonly) {
+return false;
+}
+f(pb, encap_rec);
+}
+return true;
+}
+
 /* Returns false if lport is not claimed due to 'sb_readonly'.
  * Returns true otherwise.
  */
@@ -928,37 +948,68 @@ claim_lport(const struct sbrec_port_binding *pb,
 claimed_lport_set_up(pb, parent_pb, chassis_rec, notify_up, if_mgr);
 }
 
-if (pb->chassis != chassis_rec) {
-if (sb_readonly) {
-return false;
-}
+if (!pb->requested_chassis || pb->requested_chassis == chassis_rec) {
+if (pb->chassis != chassis_rec) {
+if (sb_readonly) {
+return false;
+}
 
-if (pb->chassis) {
-VLOG_INFO("Changing chassis for lport %s from %s to %s.",
-pb->logical_port, pb->chassis->name,
-chassis_rec->name);
-} else {
-VLOG_INFO("Claiming lport %s for this chassis.", pb->logical_port);
-}
-for (int i = 0; i < pb->n_mac; i++) {
-VLOG_INFO("%s: Claiming %s", pb->logical_port, pb->mac[i]);
+if (pb->chassis) {
+VLOG_INFO("Changing chassis for lport %s from %s to %s.",
+pb->logical_port, pb->chassis->name,
+chassis_rec->name);
+} else {
+VLOG_INFO("Claiming lport %s for this chassis.",
+  pb->logical_port);
+}
+for (int i = 0; i < pb->n_mac; i++) {
+VLOG_INFO("%s: Claiming %s", pb->logical_port, pb->mac[i]);
+}
+
+sbrec_port_binding_set_chassis(pb, chassis_rec);
+if (pb->additional_chassis == chassis_rec) {
+sbrec_port_binding_set_additional_chassis(pb, NULL);
+if (pb->additional_encap) {
+sbrec_port_binding_set_additional_encap(pb, NULL);
+}
+}
 }
+} else if (pb->requested_additional_chassis == chassis_rec) {
+if (pb->additional_chassis != chassis_rec) {
+if (sb_readonly) {
+return false;
+}
 
-sbrec_port_binding_set_chassis(pb, chassis_rec);
+if (pb->additional_chassis) {
+VLOG_INFO(
+"Changing additional chassis for lport %s from %s to %s.",
+pb->logical_port, pb->chassis->name, chassis_rec->name);
+} else {
+VLOG_INFO(
+"Claiming lport %s for this additional chassis.",
+pb->logical_port);
+}
+for (int i = 0; i < pb->n_mac; i++) {
+VLOG_INFO("%s: Claiming %s", pb->logical_port, pb->mac[i]);
+}
 
-if (tracked_datapaths) {
-update_lport_tracking(pb, tracked_datapaths, true);
+sbrec_port_binding_set_additional_chassis(pb, chassis_rec);
 }
 }
 
+if (tracked_datapaths) {
+update_lport_tracking(pb, tracked_datapaths, true);
+}
+
 /* Check if the port encap binding, if any, has changed */
-struct sbrec_encap *encap_rec =
-sbrec_get_port_encap(chassis_rec, iface_rec);
-if 

[ovs-dev] [PATCH ovn 11/15] Update port-up on main chassis only

2022-02-14 Thread Ihar Hrachyshka
In a future patch, there will be a scenario where the same port has
attachments at multiple (specifically, 2) chassis, so make sure that
'up' property is updated by the main chassis only.

Signed-off-by: Ihar Hrachyshka 
---
 controller/binding.c| 10 +++---
 controller/binding.h|  2 ++
 controller/if-status.c  | 15 ++-
 controller/if-status.h  |  1 +
 controller/ovn-controller.c |  4 ++--
 5 files changed, 22 insertions(+), 10 deletions(-)

diff --git a/controller/binding.c b/controller/binding.c
index 4d62b0858..c7a13d5d5 100644
--- a/controller/binding.c
+++ b/controller/binding.c
@@ -681,6 +681,7 @@ local_binding_is_down(struct shash *local_bindings, const 
char *pb_name)
 
 void
 local_binding_set_up(struct shash *local_bindings, const char *pb_name,
+ const struct sbrec_chassis *chassis_rec,
  const char *ts_now_str, bool sb_readonly,
  bool ovs_readonly)
 {
@@ -700,8 +701,9 @@ local_binding_set_up(struct shash *local_bindings, const 
char *pb_name,
 ts_now_str);
 }
 
-if (!sb_readonly && lbinding && b_lport && b_lport->pb->n_up
-&& !b_lport->pb->up[0]) {
+if (!sb_readonly && lbinding && b_lport && b_lport->pb->n_up &&
+!b_lport->pb->up[0] &&
+(!b_lport->pb->chassis || b_lport->pb->chassis == chassis_rec)) {
 VLOG_INFO("Setting lport %s up in Southbound", pb_name);
 binding_lport_set_up(b_lport, sb_readonly);
 LIST_FOR_EACH (b_lport, list_node, >binding_lports) {
@@ -712,6 +714,7 @@ local_binding_set_up(struct shash *local_bindings, const 
char *pb_name,
 
 void
 local_binding_set_down(struct shash *local_bindings, const char *pb_name,
+   const struct sbrec_chassis *chassis_rec,
bool sb_readonly, bool ovs_readonly)
 {
 struct local_binding *lbinding =
@@ -726,7 +729,8 @@ local_binding_set_down(struct shash *local_bindings, const 
char *pb_name,
 OVN_INSTALLED_EXT_ID);
 }
 
-if (!sb_readonly && b_lport && b_lport->pb->n_up && b_lport->pb->up[0]) {
+if (!sb_readonly && b_lport && b_lport->pb->n_up && b_lport->pb->up[0] &&
+(!b_lport->pb->chassis || b_lport->pb->chassis == chassis_rec)) {
 VLOG_INFO("Setting lport %s down in Southbound", pb_name);
 binding_lport_set_down(b_lport, sb_readonly);
 LIST_FOR_EACH (b_lport, list_node, >binding_lports) {
diff --git a/controller/binding.h b/controller/binding.h
index 430a8d9b1..46f88aff7 100644
--- a/controller/binding.h
+++ b/controller/binding.h
@@ -154,9 +154,11 @@ ofp_port_t local_binding_get_lport_ofport(const struct 
shash *local_bindings,
 bool local_binding_is_up(struct shash *local_bindings, const char *pb_name);
 bool local_binding_is_down(struct shash *local_bindings, const char *pb_name);
 void local_binding_set_up(struct shash *local_bindings, const char *pb_name,
+  const struct sbrec_chassis *chassis_rec,
   const char *ts_now_str, bool sb_readonly,
   bool ovs_readonly);
 void local_binding_set_down(struct shash *local_bindings, const char *pb_name,
+const struct sbrec_chassis *chassis_rec,
 bool sb_readonly, bool ovs_readonly);
 
 void binding_register_ovs_idl(struct ovsdb_idl *);
diff --git a/controller/if-status.c b/controller/if-status.c
index fa4c8bd94..ee00f2cc6 100644
--- a/controller/if-status.c
+++ b/controller/if-status.c
@@ -115,6 +115,7 @@ static void ovs_iface_set_state(struct if_status_mgr *, 
struct ovs_iface *,
 
 static void if_status_mgr_update_bindings(
 struct if_status_mgr *mgr, struct local_binding_data *binding_data,
+const struct sbrec_chassis *,
 bool sb_readonly, bool ovs_readonly);
 
 struct if_status_mgr *
@@ -311,6 +312,7 @@ if_status_mgr_update(struct if_status_mgr *mgr,
 void
 if_status_mgr_run(struct if_status_mgr *mgr,
   struct local_binding_data *binding_data,
+  const struct sbrec_chassis *chassis_rec,
   bool sb_readonly, bool ovs_readonly)
 {
 struct ofctrl_acked_seqnos *acked_seqnos =
@@ -335,8 +337,8 @@ if_status_mgr_run(struct if_status_mgr *mgr,
 ofctrl_acked_seqnos_destroy(acked_seqnos);
 
 /* Update binding states. */
-if_status_mgr_update_bindings(mgr, binding_data, sb_readonly,
-  ovs_readonly);
+if_status_mgr_update_bindings(mgr, binding_data, chassis_rec,
+  sb_readonly, ovs_readonly);
 }
 
 static void
@@ -397,6 +399,7 @@ ovs_iface_set_state(struct if_status_mgr *mgr, struct 
ovs_iface *iface,
 static void
 if_status_mgr_update_bindings(struct if_status_mgr *mgr,
   struct local_binding_data *binding_data,
+  

[ovs-dev] [PATCH ovn 14/15] Enforce tunneling when additional-chassis is set

2022-02-14 Thread Ihar Hrachyshka
When additional-chassis is set, we cannot guarantee the upstream
switch to deliver a unicast packet sent through a localnet port to
both port chassis locations (pb->chassis and pb->additional_chassis).
To deliver packets to both locations, switch to tunneling.

Signed-off-by: Ihar Hrachyshka 
---
 controller/physical.c |  11 +-
 tests/ovn.at  | 360 ++
 2 files changed, 365 insertions(+), 6 deletions(-)

diff --git a/controller/physical.c b/controller/physical.c
index 8aa94d850..5d1598116 100644
--- a/controller/physical.c
+++ b/controller/physical.c
@@ -1184,7 +1184,9 @@ consider_port_binding(struct ovsdb_idl_index 
*sbrec_port_binding_by_name,
 if (!ofport) {
 /* It is remote port, may be reached by tunnel or localnet port */
 is_remote = true;
-if (localnet_port) {
+/* Enforce tunneling while we clone packets to additional chassis b/c
+ * otherwise upstream switch won't flood the packet to both chassis. */
+if (localnet_port && !binding->additional_chassis) {
 ofport = u16_to_ofp(simap_get(patch_ofports,
   localnet_port->logical_port));
 if (!ofport) {
@@ -1211,11 +1213,8 @@ consider_port_binding(struct ovsdb_idl_index 
*sbrec_port_binding_by_name,
 }
 
 /* Clone packets to additional chassis if needed. */
-const struct chassis_tunnel *additional_tun = NULL;
-if (!localnet_port) {
-additional_tun = get_additional_tunnel(binding, chassis,
-   chassis_tunnels);
-}
+const struct chassis_tunnel *additional_tun;
+additional_tun = get_additional_tunnel(binding, chassis, chassis_tunnels);
 
 if (!is_remote) {
 /* Packets that arrive from a vif can belong to a VM or
diff --git a/tests/ovn.at b/tests/ovn.at
index 2c8c706df..1ccec492d 100644
--- a/tests/ovn.at
+++ b/tests/ovn.at
@@ -14023,6 +14023,366 @@ OVN_CLEANUP([hv1],[hv2],[hv3])
 AT_CLEANUP
 ])
 
+OVN_FOR_EACH_NORTHD([
+AT_SETUP([localnet connectivity with options:requested-additional-chassis])
+ovn_start
+
+net_add n1
+for i in 1 2 3; do
+sim_add hv$i
+as hv$i
+check ovs-vsctl add-br br-phys
+ovn_attach n1 br-phys 192.168.0.$i
+check ovs-vsctl set open . external-ids:ovn-bridge-mappings=phys:br-phys
+done
+
+# Disable local ARP responder to pass ARP requests through tunnels
+check ovn-nbctl ls-add ls0 -- add Logical_Switch ls0 other_config 
vlan-passthru=true
+
+check ovn-nbctl lsp-add ls0 first
+check ovn-nbctl lsp-add ls0 second
+check ovn-nbctl lsp-add ls0 third
+check ovn-nbctl lsp-add ls0 migrator
+check ovn-nbctl lsp-set-addresses first "00:00:00:00:00:01 10.0.0.1"
+check ovn-nbctl lsp-set-addresses second "00:00:00:00:00:02 10.0.0.2"
+check ovn-nbctl lsp-set-addresses third "00:00:00:00:00:03 10.0.0.3"
+check ovn-nbctl lsp-set-addresses migrator "00:00:00:00:00:ff 10.0.0.100"
+
+check ovn-nbctl lsp-add ls0 public
+check ovn-nbctl lsp-set-type public localnet
+check ovn-nbctl lsp-set-addresses public unknown
+check ovn-nbctl lsp-set-options public network_name=phys
+
+# The test scenario will migrate Migrator port between hv1 and hv2 and check
+# that connectivity to and from the port is functioning properly for both
+# chassis locations. Connectivity will be checked for resources located at hv1
+# (First) and hv2 (Second) as well as for hv3 (Third) that does not take part
+# in port migration.
+check ovn-nbctl lsp-set-options first requested-chassis=hv1
+check ovn-nbctl lsp-set-options second requested-chassis=hv2
+check ovn-nbctl lsp-set-options third requested-chassis=hv3
+
+as hv1 check ovs-vsctl -- add-port br-int first -- \
+set Interface first external-ids:iface-id=first \
+options:tx_pcap=hv1/first-tx.pcap \
+options:rxq_pcap=hv1/first-rx.pcap
+as hv2 check ovs-vsctl -- add-port br-int second -- \
+set Interface second external-ids:iface-id=second \
+options:tx_pcap=hv2/second-tx.pcap \
+options:rxq_pcap=hv2/second-rx.pcap
+as hv3 check ovs-vsctl -- add-port br-int third -- \
+set Interface third external-ids:iface-id=third \
+options:tx_pcap=hv3/third-tx.pcap \
+options:rxq_pcap=hv3/third-rx.pcap
+
+# Create Migrator interfaces on both hv1 and hv2
+for hv in hv1 hv2; do
+as $hv check ovs-vsctl -- add-port br-int migrator -- \
+set Interface migrator external-ids:iface-id=migrator \
+options:tx_pcap=$hv/migrator-tx.pcap \
+options:rxq_pcap=$hv/migrator-rx.pcap
+done
+
+send_arp() {
+local hv=$1 inport=$2 eth_src=$3 eth_dst=$4 spa=$5 tpa=$6
+local 
request=${eth_dst}${eth_src}08060001080006040001${eth_src}${spa}${eth_dst}${tpa}
+as ${hv} ovs-appctl netdev-dummy/receive $inport $request
+echo "${request}"
+}
+
+send_garp() {
+local hv=$1 inport=$2 eth_src=$3 eth_dst=$4 spa=$5 tpa=$6
+local 
request=${eth_dst}${eth_src}08060001080006040002${eth_src}${spa}${eth_dst}${tpa}
+as ${hv} 

[ovs-dev] [PATCH ovn 06/15] Pass chassis and encap into get_port_binding_tun

2022-02-14 Thread Ihar Hrachyshka
Next patches will need the same functionality while passing a
different chassis / encap configuration that is not the primary for a
port binding.

Signed-off-by: Ihar Hrachyshka 
---
 controller/physical.c | 13 ++---
 1 file changed, 6 insertions(+), 7 deletions(-)

diff --git a/controller/physical.c b/controller/physical.c
index 3a7fbfb21..7ad142293 100644
--- a/controller/physical.c
+++ b/controller/physical.c
@@ -124,17 +124,15 @@ put_resubmit(uint8_t table_id, struct ofpbuf *ofpacts)
 }
 
 /*
- * For a port binding, get the corresponding ovn-chassis-id tunnel port
- * from the associated encap.
+ * For an encap and a chassis, get the corresponding ovn-chassis-id tunnel
+ * port.
  */
 static struct chassis_tunnel *
-get_port_binding_tun(const struct sbrec_port_binding *binding,
+get_port_binding_tun(const struct sbrec_encap *encap,
+ const struct sbrec_chassis *chassis,
  const struct hmap *chassis_tunnels)
 {
-struct sbrec_encap *encap = binding->encap;
-struct sbrec_chassis *chassis = binding->chassis;
 struct chassis_tunnel *tun = NULL;
-
 if (encap) {
 tun = chassis_tunnel_find(chassis_tunnels, chassis->name, encap->ip);
 }
@@ -295,7 +293,8 @@ put_remote_port_redirect_overlay(const struct
 if (!is_ha_remote) {
 /* Setup encapsulation */
 const struct chassis_tunnel *rem_tun =
-get_port_binding_tun(binding, chassis_tunnels);
+get_port_binding_tun(binding->encap, binding->chassis,
+chassis_tunnels);
 if (!rem_tun) {
 return;
 }
-- 
2.34.1

___
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev


[ovs-dev] [PATCH ovn 10/15] Tag all packets that arrived from a tunnel as LOCAL_ONLY

2022-02-14 Thread Ihar Hrachyshka
A next patch may need to clone packets to another chassis as part of
"port migration" procedure, but only if they haven't originated at
another chassis. This LOCAL_ONLY tag will enforce the requirement.

Signed-off-by: Ihar Hrachyshka 
---
 controller/physical.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/controller/physical.c b/controller/physical.c
index 0f9dd91e5..bc4f7c4f0 100644
--- a/controller/physical.c
+++ b/controller/physical.c
@@ -1727,6 +1727,7 @@ physical_run(struct physical_ctx *p_ctx,
 OVS_NOT_REACHED();
 }
 
+put_load(1, MFF_LOG_FLAGS, MLF_LOCAL_ONLY_BIT, 1, );
 put_resubmit(OFTABLE_LOCAL_OUTPUT, );
 
 ofctrl_add_flow(flow_table, OFTABLE_PHY_TO_LOG, 100, 0, ,
-- 
2.34.1

___
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev


[ovs-dev] [PATCH ovn 07/15] Introduce match_outport_dp_and_port_keys in physical.c

2022-02-14 Thread Ihar Hrachyshka
This helper prepares a 'match' struct to match against a datapath and
a port key. All existing spots in the file that use such a 'match'
struct were updated. It will also be reused later.

Signed-off-by: Ihar Hrachyshka 
---
 controller/physical.c | 65 +++
 1 file changed, 23 insertions(+), 42 deletions(-)

diff --git a/controller/physical.c b/controller/physical.c
index 7ad142293..e0afd83ab 100644
--- a/controller/physical.c
+++ b/controller/physical.c
@@ -277,6 +277,15 @@ put_remote_port_redirect_bridged(const struct
 
 }
 
+static void
+match_outport_dp_and_port_keys(struct match *match,
+   uint32_t dp_key, uint32_t port_key)
+{
+match_init_catchall(match);
+match_set_metadata(match, htonll(dp_key));
+match_set_reg(match, MFF_LOG_OUTPORT - MFF_REG0, port_key);
+}
+
 static void
 put_remote_port_redirect_overlay(const struct
  sbrec_port_binding *binding,
@@ -670,7 +679,6 @@ put_replace_router_port_mac_flows(struct ovsdb_idl_index
  * a. Flow replaces ingress router port mac with a chassis mac.
  * b. Flow appends the vlan id localnet port is configured with.
  */
-match_init_catchall();
 ofpbuf_clear(ofpacts_p);
 
 ovs_assert(rport_binding->n_mac == 1);
@@ -684,8 +692,7 @@ put_replace_router_port_mac_flows(struct ovsdb_idl_index
 }
 
 /* Replace Router mac flow */
-match_set_metadata(, htonll(dp_key));
-match_set_reg(, MFF_LOG_OUTPORT - MFF_REG0, port_key);
+match_outport_dp_and_port_keys(, dp_key, port_key);
 match_set_dl_src(, router_port_mac);
 
 replace_mac = ofpact_put_SET_ETH_SRC(ofpacts_p);
@@ -723,12 +730,10 @@ put_local_common_flows(uint32_t dp_key,
  * table 39.
  */
 
-match_init_catchall();
 ofpbuf_clear(ofpacts_p);
 
 /* Match MFF_LOG_DATAPATH, MFF_LOG_OUTPORT. */
-match_set_metadata(, htonll(dp_key));
-match_set_reg(, MFF_LOG_OUTPORT - MFF_REG0, port_key);
+match_outport_dp_and_port_keys(, dp_key, port_key);
 
 if (zone_ids) {
 if (zone_ids->ct) {
@@ -786,10 +791,8 @@ put_local_common_flows(uint32_t dp_key,
  * */
 
 bool nested_container = parent_pb ? true: false;
-match_init_catchall();
 ofpbuf_clear(ofpacts_p);
-match_set_metadata(, htonll(dp_key));
-match_set_reg(, MFF_LOG_OUTPORT - MFF_REG0, port_key);
+match_outport_dp_and_port_keys(, dp_key, port_key);
 if (!nested_container) {
 match_set_reg_masked(, MFF_LOG_FLAGS - MFF_REG0,
  MLF_ALLOW_LOOPBACK, MLF_ALLOW_LOOPBACK);
@@ -820,11 +823,8 @@ put_local_common_flows(uint32_t dp_key,
  * ports even if they don't have any child ports which is
  * unnecessary.
  */
-match_init_catchall();
 ofpbuf_clear(ofpacts_p);
-match_set_metadata(, htonll(dp_key));
-match_set_reg(, MFF_LOG_OUTPORT - MFF_REG0,
-  parent_pb->tunnel_key);
+match_outport_dp_and_port_keys(, dp_key, port_key);
 match_set_reg_masked(, MFF_LOG_FLAGS - MFF_REG0,
  MLF_NESTED_CONTAINER, MLF_NESTED_CONTAINER);
 
@@ -920,10 +920,8 @@ consider_port_binding(struct ovsdb_idl_index 
*sbrec_port_binding_by_name,
 put_local_common_flows(dp_key, binding, NULL, _zones,
ofpacts_p, flow_table);
 
-match_init_catchall();
 ofpbuf_clear(ofpacts_p);
-match_set_metadata(, htonll(dp_key));
-match_set_reg(, MFF_LOG_OUTPORT - MFF_REG0, port_key);
+match_outport_dp_and_port_keys(, dp_key, port_key);
 
 size_t clone_ofs = ofpacts_p->size;
 struct ofpact_nest *clone = ofpact_put_CLONE(ofpacts_p);
@@ -966,10 +964,8 @@ consider_port_binding(struct ovsdb_idl_index 
*sbrec_port_binding_by_name,
  * output port is changed from the "chassisredirect" port to the
  * underlying distributed port. */
 
-match_init_catchall();
 ofpbuf_clear(ofpacts_p);
-match_set_metadata(, htonll(dp_key));
-match_set_reg(, MFF_LOG_OUTPORT - MFF_REG0, port_key);
+match_outport_dp_and_port_keys(, dp_key, port_key);
 
 const char *distributed_port = smap_get_def(>options,
 "distributed-port", "");
@@ -1203,10 +1199,8 @@ consider_port_binding(struct ovsdb_idl_index 
*sbrec_port_binding_by_name,
  * ===
  *
  * Deliver the packet to the local vif. */
-match_init_catchall();
 ofpbuf_clear(ofpacts_p);
-match_set_metadata(, htonll(dp_key));
-match_set_reg(, MFF_LOG_OUTPORT - MFF_REG0, port_key);
+match_outport_dp_and_port_keys(, dp_key, port_key);
 if (tag) {
 /* For containers sitting behind a local vif, tag the packets
  * before delivering them. */
@@ -1240,10 +1234,8 

[ovs-dev] [PATCH ovn 08/15] Split code to set zone info into put_zones_ofpacts

2022-02-14 Thread Ihar Hrachyshka
Signed-off-by: Ihar Hrachyshka 
---
 controller/physical.c | 28 +---
 1 file changed, 17 insertions(+), 11 deletions(-)

diff --git a/controller/physical.c b/controller/physical.c
index e0afd83ab..c47b15f3e 100644
--- a/controller/physical.c
+++ b/controller/physical.c
@@ -710,6 +710,22 @@ put_replace_router_port_mac_flows(struct ovsdb_idl_index
 }
 }
 
+static void
+put_zones_ofpacts(const struct zone_ids *zone_ids, struct ofpbuf *ofpacts_p)
+{
+if (zone_ids) {
+if (zone_ids->ct) {
+put_load(zone_ids->ct, MFF_LOG_CT_ZONE, 0, 32, ofpacts_p);
+}
+if (zone_ids->dnat) {
+put_load(zone_ids->dnat, MFF_LOG_DNAT_ZONE, 0, 32, ofpacts_p);
+}
+if (zone_ids->snat) {
+put_load(zone_ids->snat, MFF_LOG_SNAT_ZONE, 0, 32, ofpacts_p);
+}
+}
+}
+
 static void
 put_local_common_flows(uint32_t dp_key,
const struct sbrec_port_binding *pb,
@@ -735,17 +751,7 @@ put_local_common_flows(uint32_t dp_key,
 /* Match MFF_LOG_DATAPATH, MFF_LOG_OUTPORT. */
 match_outport_dp_and_port_keys(, dp_key, port_key);
 
-if (zone_ids) {
-if (zone_ids->ct) {
-put_load(zone_ids->ct, MFF_LOG_CT_ZONE, 0, 32, ofpacts_p);
-}
-if (zone_ids->dnat) {
-put_load(zone_ids->dnat, MFF_LOG_DNAT_ZONE, 0, 32, ofpacts_p);
-}
-if (zone_ids->snat) {
-put_load(zone_ids->snat, MFF_LOG_SNAT_ZONE, 0, 32, ofpacts_p);
-}
-}
+put_zones_ofpacts(zone_ids, ofpacts_p);
 
 /* Resubmit to table 39. */
 put_resubmit(OFTABLE_CHECK_LOOPBACK, ofpacts_p);
-- 
2.34.1

___
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev


[ovs-dev] [PATCH ovn 09/15] Use get_port_binding_tun instead of chassis_tunnel_find

2022-02-14 Thread Ihar Hrachyshka
Right now consider_port_binding first extracts *a* tunnel for a
chassis, then later in put_remote_port_redirect_overlay it fetches
*the* proper tunnel before configuring encapsulation.

Instead of doing it in two steps, just extract the proper tunnel info
earlier.

Signed-off-by: Ihar Hrachyshka 
---
 controller/physical.c | 11 ---
 1 file changed, 4 insertions(+), 7 deletions(-)

diff --git a/controller/physical.c b/controller/physical.c
index c47b15f3e..0f9dd91e5 100644
--- a/controller/physical.c
+++ b/controller/physical.c
@@ -301,17 +301,14 @@ put_remote_port_redirect_overlay(const struct
 {
 if (!is_ha_remote) {
 /* Setup encapsulation */
-const struct chassis_tunnel *rem_tun =
-get_port_binding_tun(binding->encap, binding->chassis,
-chassis_tunnels);
-if (!rem_tun) {
+if (!tun) {
 return;
 }
 put_encapsulation(mff_ovn_geneve, tun, binding->datapath, port_key,
   !strcmp(binding->type, "vtep"),
   ofpacts_p);
 /* Output to tunnel. */
-ofpact_put_OUTPUT(ofpacts_p)->port = rem_tun->ofport;
+ofpact_put_OUTPUT(ofpacts_p)->port = tun->ofport;
 } else {
 /* Make sure all tunnel endpoints use the same encapsulation,
  * and set it up */
@@ -1097,8 +1094,8 @@ consider_port_binding(struct ovsdb_idl_index 
*sbrec_port_binding_by_name,
 if (!binding->chassis) {
 goto out;
 }
-tun = chassis_tunnel_find(chassis_tunnels,
-  binding->chassis->name, NULL);
+tun = get_port_binding_tun(binding->encap, binding->chassis,
+   chassis_tunnels);
 if (!tun) {
 goto out;
 }
-- 
2.34.1

___
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev


[ovs-dev] [PATCH ovn 05/15] northd: separate code for nb->sb port binding chassis update

2022-02-14 Thread Ihar Hrachyshka
The ovn_port_update_sbrec function became too long, and the next
patches will touch the code to update chassis mapping for ports. This
patch prepares for the next step.

Signed-off-by: Ihar Hrachyshka 
---
 northd/northd.c | 62 -
 1 file changed, 36 insertions(+), 26 deletions(-)

diff --git a/northd/northd.c b/northd/northd.c
index 0f694cb2d..0179b2bc9 100644
--- a/northd/northd.c
+++ b/northd/northd.c
@@ -3132,6 +3132,40 @@ chassis_lookup(struct ovsdb_idl_index 
*sbrec_chassis_by_name,
 sbrec_chassis_by_hostname, name_or_hostname);
 }
 
+static void
+ovn_port_update_sbrec_chassis(
+struct ovsdb_idl_index *sbrec_chassis_by_name,
+struct ovsdb_idl_index *sbrec_chassis_by_hostname,
+const struct ovn_port *op)
+{
+const char *requested_chassis; /* May be NULL. */
+bool reset_requested_chassis = false;
+requested_chassis = smap_get(>nbsp->options,
+ "requested-chassis");
+if (requested_chassis) {
+const struct sbrec_chassis *chassis = chassis_lookup(
+sbrec_chassis_by_name, sbrec_chassis_by_hostname,
+requested_chassis);
+if (chassis) {
+sbrec_port_binding_set_requested_chassis(op->sb, chassis);
+} else {
+reset_requested_chassis = true;
+static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(
+1, 1);
+VLOG_WARN_RL(
+,
+"Unknown chassis '%s' set as "
+"options:requested-chassis on LSP '%s'.",
+requested_chassis, op->nbsp->name);
+}
+} else if (op->sb->requested_chassis) {
+reset_requested_chassis = true;
+}
+if (reset_requested_chassis) {
+sbrec_port_binding_set_requested_chassis(op->sb, NULL);
+}
+}
+
 static void
 ovn_port_update_sbrec(struct northd_input *input_data,
   struct ovsdb_idl_txn *ovnsb_txn,
@@ -3322,32 +3356,8 @@ ovn_port_update_sbrec(struct northd_input *input_data,
 sbrec_port_binding_set_ha_chassis_group(op->sb, NULL);
 }
 
-const char *requested_chassis; /* May be NULL. */
-bool reset_requested_chassis = false;
-requested_chassis = smap_get(>nbsp->options,
- "requested-chassis");
-if (requested_chassis) {
-const struct sbrec_chassis *chassis = chassis_lookup(
-sbrec_chassis_by_name, sbrec_chassis_by_hostname,
-requested_chassis);
-if (chassis) {
-sbrec_port_binding_set_requested_chassis(op->sb, chassis);
-} else {
-reset_requested_chassis = true;
-static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(
-1, 1);
-VLOG_WARN_RL(
-,
-"Unknown chassis '%s' set as "
-"options:requested-chassis on LSP '%s'.",
-requested_chassis, op->nbsp->name);
-}
-} else if (op->sb->requested_chassis) {
-reset_requested_chassis = true;
-}
-if (reset_requested_chassis) {
-sbrec_port_binding_set_requested_chassis(op->sb, NULL);
-}
+ovn_port_update_sbrec_chassis(sbrec_chassis_by_name,
+  sbrec_chassis_by_hostname, op);
 } else {
 const char *chassis = NULL;
 if (op->peer && op->peer->od && op->peer->od->nbr) {
-- 
2.34.1

___
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev


[ovs-dev] [PATCH ovn 04/15] northd: introduce separate function to look up chassis

2022-02-14 Thread Ihar Hrachyshka
This function will be reused later.

Signed-off-by: Ihar Hrachyshka 
---
 northd/northd.c | 21 +++--
 1 file changed, 15 insertions(+), 6 deletions(-)

diff --git a/northd/northd.c b/northd/northd.c
index fc7a64f99..0f694cb2d 100644
--- a/northd/northd.c
+++ b/northd/northd.c
@@ -3120,6 +3120,18 @@ ovn_update_ipv6_prefix(struct hmap *ports)
 }
 }
 
+static const struct sbrec_chassis *
+chassis_lookup(struct ovsdb_idl_index *sbrec_chassis_by_name,
+   struct ovsdb_idl_index *sbrec_chassis_by_hostname,
+   const char *name_or_hostname)
+{
+const struct sbrec_chassis *chassis; /* May be NULL. */
+chassis = chassis_lookup_by_name(sbrec_chassis_by_name,
+ name_or_hostname);
+return chassis ? chassis : chassis_lookup_by_hostname(
+sbrec_chassis_by_hostname, name_or_hostname);
+}
+
 static void
 ovn_port_update_sbrec(struct northd_input *input_data,
   struct ovsdb_idl_txn *ovnsb_txn,
@@ -3315,12 +3327,9 @@ ovn_port_update_sbrec(struct northd_input *input_data,
 requested_chassis = smap_get(>nbsp->options,
  "requested-chassis");
 if (requested_chassis) {
-const struct sbrec_chassis *chassis; /* May be NULL. */
-chassis = chassis_lookup_by_name(sbrec_chassis_by_name,
- requested_chassis);
-chassis = chassis ? chassis : chassis_lookup_by_hostname(
-sbrec_chassis_by_hostname, requested_chassis);
-
+const struct sbrec_chassis *chassis = chassis_lookup(
+sbrec_chassis_by_name, sbrec_chassis_by_hostname,
+requested_chassis);
 if (chassis) {
 sbrec_port_binding_set_requested_chassis(op->sb, chassis);
 } else {
-- 
2.34.1

___
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev


[ovs-dev] [PATCH ovn 02/15] tests: don't bail from OVN_CHECK_PACKETS_CONTAIN prematurily

2022-02-14 Thread Ihar Hrachyshka
When the expected number of packets arrive, OVN_CHECK_PACKETS_CONTAIN
bails out. But it should bail out from waiting only when the expected
packets were observed or when timeout reached, because the whole point
of the function is to allow to ignore some packets (usually garps
generated by ports) while waiting on the desired packets to arrive.

Signed-off-by: Ihar Hrachyshka 
---
 tests/ovn.at | 14 --
 1 file changed, 12 insertions(+), 2 deletions(-)

diff --git a/tests/ovn.at b/tests/ovn.at
index 5d587dde2..bbba41af4 100644
--- a/tests/ovn.at
+++ b/tests/ovn.at
@@ -52,6 +52,17 @@ m4_divert_text([PREPARE_TESTS],
[dump_diff__ "$rcv_pcap" "$exp_text"])
  sort $exp_text > expout
}
+   ovn_wait_packets__ () {
+ echo "$3: waiting for packets from $2 at $1:"
+ rcv_pcap=$1
+ rcv_text=`echo "$rcv_pcap.packets" | sed 's/\.pcap//'`
+ exp_text=$2
+ OVS_WAIT_UNTIL(
+   [$PYTHON "$ovs_srcdir/utilities/ovs-pcap.in" $rcv_pcap > $rcv_text
+sort $exp_text > expout
+test x"$(sort $rcv_text | comm -2 -3 expout -)" = "x"],
+   [dump_diff__ "$rcv_pcap" "$exp_text"])
+   }
 ])
 
 m4_define([OVN_CHECK_PACKETS],
@@ -63,8 +74,7 @@ m4_define([OVN_CHECK_PACKETS_REMOVE_BROADCAST],
AT_CHECK([sort $rcv_text], [0], [expout], [ignore], [dump_diff__ "$1" 
"$2"])])
 
 m4_define([OVN_CHECK_PACKETS_CONTAIN],
-  [ovn_check_packets__ "$1" "$2" "__file__:__line__"
-   AT_CHECK([sort $rcv_text | comm -2 -3 expout -], [0], [])])
+  [ovn_wait_packets__ "$1" "$2" "__file__:__line__"])
 
 AT_BANNER([OVN components])
 
-- 
2.34.1

___
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev


[ovs-dev] [PATCH ovn 03/15] Introduce chassis_is_vtep

2022-02-14 Thread Ihar Hrachyshka
This tiny helper will be reused later.

Signed-off-by: Ihar Hrachyshka 
---
 controller/physical.c | 9 +++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/controller/physical.c b/controller/physical.c
index 6bfa2304d..3a7fbfb21 100644
--- a/controller/physical.c
+++ b/controller/physical.c
@@ -1408,6 +1408,12 @@ fanout_to_chassis(enum mf_field_id mff_ovn_geneve,
 }
 }
 
+static bool
+chassis_is_vtep(const struct sbrec_chassis *chassis)
+{
+return smap_get_bool(>other_config, "is-vtep", false);
+}
+
 static void
 consider_mc_group(struct ovsdb_idl_index *sbrec_port_binding_by_name,
   enum mf_field_id mff_ovn_geneve,
@@ -1519,8 +1525,7 @@ consider_mc_group(struct ovsdb_idl_index 
*sbrec_port_binding_by_name,
 /* Add remote chassis only when localnet port not exist,
  * otherwise multicast will reach remote ports through localnet
  * port. */
-if (smap_get_bool(>chassis->other_config,
-  "is-vtep", false)) {
+if (chassis_is_vtep(port->chassis)) {
 sset_add(_chassis, port->chassis->name);
 } else {
 sset_add(_chassis, port->chassis->name);
-- 
2.34.1

___
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev


[ovs-dev] [PATCH ovn 01/15] tests: log more info on OVN_CHECK_PACKETS* failure

2022-02-14 Thread Ihar Hrachyshka
Right now it logs diff between expected and observed only when enough
packets arrived. If less than expected packets arrived, only the
number of packets observed was logged, but not the packets themselves.
This patch makes the functions log the expected packets, the observed
packets, as well as the diff between them in this situation.

Signed-off-by: Ihar Hrachyshka 
---
 tests/ovn.at | 24 +++-
 1 file changed, 19 insertions(+), 5 deletions(-)

diff --git a/tests/ovn.at b/tests/ovn.at
index 957eb7850..5d587dde2 100644
--- a/tests/ovn.at
+++ b/tests/ovn.at
@@ -10,7 +10,19 @@
 # testsuite file since the shell function is only emitted once even
 # when this macro is invoked many times.
 m4_divert_text([PREPARE_TESTS],
-  [ovn_check_packets__ () {
+  [dump_diff__ () {
+ local rcv_pcap=$1 exp_text=$2
+ rcv_text=`echo "$rcv_pcap.packets" | sed 's/\.pcap//'`
+ echo "Expected:"
+ sort $exp_text
+ echo "Received:"
+ sort $rcv_text
+ sort $exp_text -o $exp_text.sorted
+ sort $rcv_text -o $rcv_text.sorted
+ echo "Diff:"
+ diff -u $exp_text.sorted $rcv_text.sorted
+   }
+   ovn_check_packets__ () {
  echo
  echo "$3: checking packets in $1 against $2:"
  rcv_pcap=$1
@@ -21,7 +33,8 @@ m4_divert_text([PREPARE_TESTS],
[$PYTHON "$ovs_srcdir/utilities/ovs-pcap.in" $rcv_pcap > $rcv_text
 rcv_n=`wc -l < "$rcv_text"`
 echo "rcv_n=$rcv_n exp_n=$exp_n"
-test $rcv_n -ge $exp_n])
+test $rcv_n -ge $exp_n],
+   [dump_diff__ "$rcv_pcap" "$exp_text"])
  sort $exp_text > expout
}
ovn_check_packets_remove_broadcast__ () {
@@ -35,18 +48,19 @@ m4_divert_text([PREPARE_TESTS],
 sed -i '//d' $rcv_text
 rcv_n=`wc -l < "$rcv_text"`
 echo "rcv_n=$rcv_n exp_n=$exp_n"
-test $rcv_n -ge $exp_n])
+test $rcv_n -ge $exp_n],
+   [dump_diff__ "$rcv_pcap" "$exp_text"])
  sort $exp_text > expout
}
 ])
 
 m4_define([OVN_CHECK_PACKETS],
   [ovn_check_packets__ "$1" "$2" "__file__:__line__"
-   AT_CHECK([sort $rcv_text], [0], [expout])])
+   AT_CHECK([sort $rcv_text], [0], [expout], [ignore], [dump_diff__ "$1" 
"$2"])])
 
 m4_define([OVN_CHECK_PACKETS_REMOVE_BROADCAST],
   [ovn_check_packets_remove_broadcast__ "$1" "$2" "__file__:__line__"
-   AT_CHECK([sort $rcv_text], [0], [expout])])
+   AT_CHECK([sort $rcv_text], [0], [expout], [ignore], [dump_diff__ "$1" 
"$2"])])
 
 m4_define([OVN_CHECK_PACKETS_CONTAIN],
   [ovn_check_packets__ "$1" "$2" "__file__:__line__"
-- 
2.34.1

___
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev


[ovs-dev] [PATCH ovn 00/15] Support additional-chassis for ports

2022-02-14 Thread Ihar Hrachyshka
This is a series of patches that was initially sent to the ML as a
single draft blob. The new series is much improved in functionality,
quality and test coverage. It starts with a number of small preparatory
patches that move the code around and fix test suite helper functions
that are later used in added test scenarios.

The only missing part in the series is ddlog support. All but four last
patches in the series don't need any ddlog modifications and can be
merged if ready.

Ihar Hrachyshka (15):
  tests: log more info on OVN_CHECK_PACKETS* failure
  tests: don't bail from OVN_CHECK_PACKETS_CONTAIN prematurily
  Introduce chassis_is_vtep
  northd: introduce separate function to look up chassis
  northd: separate code for nb->sb port binding chassis update
  Pass chassis and encap into get_port_binding_tun
  Introduce match_outport_dp_and_port_keys in physical.c
  Split code to set zone info into put_zones_ofpacts
  Use get_port_binding_tun instead of chassis_tunnel_find
  Tag all packets that arrived from a tunnel as LOCAL_ONLY
  Update port-up on main chassis only
  Introduce LSP:options:requested-additional-chassis
  Clone packets to both port chassis
  Enforce tunneling when additional-chassis is set
  Implement RARP activation strategy for ports

 controller/binding.c| 188 +--
 controller/binding.h|   2 +
 controller/if-status.c  |  15 +-
 controller/if-status.h  |   1 +
 controller/lport.c  |  19 +-
 controller/ovn-controller.c |   4 +-
 controller/physical.c   | 368 ++
 controller/pinctrl.c| 161 +-
 controller/pinctrl.h|   2 +
 include/ovn/actions.h   |   9 +
 lib/actions.c   |  40 +-
 northd/northd.c | 130 +++--
 northd/ovn-northd.c |   7 +-
 ovn-nb.xml  |  18 +
 ovn-sb.ovsschema|  15 +-
 ovn-sb.xml  |  73 ++-
 tests/ovn.at| 984 +++-
 utilities/ovn-trace.c   |   3 +
 18 files changed, 1849 insertions(+), 190 deletions(-)

-- 
2.34.1

___
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev


Re: [ovs-dev] [External] Re: [PATCH 2/5] ipf: add ipf context

2022-02-14 Thread . 贺鹏
On Tue, Feb 15, 2022 at 2:10 AM Ilya Maximets  wrote:
>
> On 1/28/22 17:14, Aaron Conole wrote:
> > From: Peng He 
> >
> > ipf_postprocess will emit packets into the datapath pipeline ignoring
> > the conntrack context, this might casuse weird issues when a packet
> > batch has less space to hold all the fragments belonging to single
> > packet.
> >
> > Given the below ruleest and consider sending a 64K ICMP packet which
> > is splitted into 64 fragments.
> >
> > priority=1,action=drop
> > priority=10,arp,action=normal
> > priority=100,in_port=1,ct_state=-trk,icmp,action=ct(zone=9,table=0)
> > priority=100,in_port=1,ct_state=+new+trk,icmp,action=ct(zone=9,commit),2
> > priority=100,in_port=1,ct_state=-new+est+trk,icmp,action=2
> > priority=100,in_port=2,ct_state=-trk,icmp,action=ct(table=0,zone=9)
> > priority=100,in_port=2,ct_state=+trk+est-new,icmp,action=1
> >
> > Batch 1:
> > the first 32 packets will be buffered in the ipf preprocessing, nothing
> > more proceeds.
> >
> > Batch 2:
> > the second 32 packets succeed the fragment reassembly and goes to ct
> > and ipf_post will emits the first 32 packets due to the limit of batch
> > size.
> >
> > the first 32 packets goes to the datapath again due to the
> > recirculation, and again buffered at ipf preprocessing before ct commit,
> > then the ovs tries to call ct commit as well as ipf_postprocessing which 
> > emits
> > the last 32 packets, in this case the last 32 packets will follow
> > the current actions which will be sent to port 2 directly without
> > recirculation and going to ipf preprocssing and ct commit again.
> >
> > This will cause the first 32 packets never get the chance to
> > reassemble and evevntually this large ICMP packets fail to transmit.
> >
> > this patch fixes this issue by adding firstly ipf context to avoid
> > ipf_postprocessing emits packets in the wrong context. Then by
> > re-executing the action list again to emit the last 32 packets
> > in the right context to correctly transmitting multiple fragments.
> >
> > This might be one of the root cause why the OVS log warns:
> >
> > "
> > skipping output to input port on bridge br-int while processing
> > "
> >
> > As a pkt might enter into different ipf context.
> >
> > One implementation trick of implementing ipf_ctx_eq, is to use ipf_list's
> > key instead of the first frag's metadata, this can reduce quite a lot of
> > cache misses as at the time of calling ipf_ctx_eq, ipf_list is cache-hot.
> > On x86_64, this trick saves 2% of CPU usage of ipf processing.
> >
> > Signed-off-by: Peng He 
> > Co-authored-by: Mike Pattrick 
> > Signed-off-by: Aaron Conole 
> > ---
> >  lib/conntrack.c |  9 ---
> >  lib/conntrack.h | 15 ++--
> >  lib/dpif-netdev.c   | 52 +
> >  lib/ipf.c   | 39 ---
> >  lib/ipf.h   | 11 +++--
> >  tests/system-traffic.at | 33 ++
> >  tests/test-conntrack.c  |  6 ++---
> >  7 files changed, 135 insertions(+), 30 deletions(-)
> >
> > diff --git a/lib/conntrack.c b/lib/conntrack.c
> > index 33a1a92953..72999f1aed 100644
> > --- a/lib/conntrack.c
> > +++ b/lib/conntrack.c
> > @@ -1434,14 +1434,14 @@ process_one(struct conntrack *ct, struct dp_packet 
> > *pkt,
> >   * connection tables.  'setmark', if not NULL, should point to a two
> >   * elements array containing a value and a mask to set the connection mark.
> >   * 'setlabel' behaves similarly for the connection label.*/
> > -int
> > +bool
> >  conntrack_execute(struct conntrack *ct, struct dp_packet_batch *pkt_batch,
> >ovs_be16 dl_type, bool force, bool commit, uint16_t zone,
> >const uint32_t *setmark,
> >const struct ovs_key_ct_labels *setlabel,
> >ovs_be16 tp_src, ovs_be16 tp_dst, const char *helper,
> >const struct nat_action_info_t *nat_action_info,
> > -  long long now, uint32_t tp_id)
> > +  long long now, uint32_t tp_id, struct ipf_ctx *ipf_ctx)
> >  {
> >  ipf_preprocess_conntrack(ct->ipf, pkt_batch, now, dl_type, zone,
> >   ct->hash_basis);
> > @@ -1468,9 +1468,8 @@ conntrack_execute(struct conntrack *ct, struct 
> > dp_packet_batch *pkt_batch,
> >  }
> >  }
> >
> > -ipf_postprocess_conntrack(ct->ipf, pkt_batch, now, dl_type);
> > -
> > -return 0;
> > +return ipf_postprocess_conntrack(ct->ipf, pkt_batch, ipf_ctx, \
> > + now, dl_type);
> >  }
> >
> >  void
> > diff --git a/lib/conntrack.h b/lib/conntrack.h
> > index 9553b188a4..211efad3f3 100644
> > --- a/lib/conntrack.h
> > +++ b/lib/conntrack.h
> > @@ -64,6 +64,7 @@
> >  struct dp_packet_batch;
> >
> >  struct conntrack;
> > +struct ipf_ctx;
> >
> >  union ct_addr {
> >  ovs_be32 ipv4;
> > @@ -88,13 +89,13 @@ struct nat_action_info_t {
> >  struct conntrack 

Re: [ovs-dev] [PATCH v2] ofproto-dpif: fix packet_execute_prepare

2022-02-14 Thread Peng He
Aaron Conole  于2022年2月15日周二 01:33写道:

> Peng He  writes:
>
> > In the commit 1df7f7aac8c976690167261fec9a50d832ef9e7e, the packet
> > metadata's in_port has been changed from ofp port into odp port,
> > however, the odp->flow->in_port is still ofp_port. This patch changes
> > the odp->flow->in_port into odp_port.
> >
> > Fixes: 1df7f7aac8 ("ofproto-dpif: Restore packet metadata when a
> > continuation is resumed.")
>
> This tag is still wrapped, and I don't think the fixes tag is for the
> correct commit.
>

Oh, sorry, I thought this was Ilya's reply.

please check the link:

http://patchwork.ozlabs.org/project/openvswitch/patch/20220213023642.4248-1-hepeng.0...@bytedance.com/
shows the tag is ok? am I missing something?



>
> > Signed-off-by: Peng He 
> > ---
> >  ofproto/ofproto-dpif.c | 1 +
>
> Also, seems there is no unit test as requested.  Can you please address
> these?
>
> >  1 file changed, 1 insertion(+)
> >
> > diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c
> > index cba49a99e..72de67c63 100644
> > --- a/ofproto/ofproto-dpif.c
> > +++ b/ofproto/ofproto-dpif.c
> > @@ -4973,6 +4973,7 @@ packet_execute_prepare(struct ofproto *ofproto_,
> >  ofproto_dpif_set_packet_odp_port(ofproto,
> opo->flow->in_port.ofp_port,
> >   opo->packet);
> >
> > +opo->flow->in_port = opo->packet->md.in_port;
> >  ofproto_dpif_packet_out_delete(aux);
> >  opo->aux = execute;
> >  }
>
>

-- 
hepeng
___
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev


Re: [ovs-dev] [PATCH v2] ofproto-dpif: fix packet_execute_prepare

2022-02-14 Thread Peng He
Ilya Maximets  于2022年2月15日周二 01:42写道:

> On 2/14/22 18:32, Aaron Conole wrote:
> > Peng He  writes:
> >
> >> In the commit 1df7f7aac8c976690167261fec9a50d832ef9e7e, the packet
> >> metadata's in_port has been changed from ofp port into odp port,
> >> however, the odp->flow->in_port is still ofp_port. This patch changes
> >> the odp->flow->in_port into odp_port.
> >>
> >> Fixes: 1df7f7aac8 ("ofproto-dpif: Restore packet metadata when a
> >> continuation is resumed.")
> >
> > This tag is still wrapped, and I don't think the fixes tag is for the
> > correct commit.
>
weird. the link:
http://patchwork.ozlabs.org/project/openvswitch/patch/20220213023642.4248-1-hepeng.0...@bytedance.com/
shows the tag is not wrapped. If by tag, you mean the line "Fixes: [commit
id] ("title")".


> >
> >> Signed-off-by: Peng He 
> >> ---
> >>  ofproto/ofproto-dpif.c | 1 +
> >
> > Also, seems there is no unit test as requested.  Can you please address
> > these?
>
> This patch is needed for ipf_ctx to pass through the testsuite.

BTW, If we will not touch the flow struct here, is it ok to touch it at
dpif_execute and finally at dpif_netdev_execute? As it is now in the
datapath ctx and it is ok to assume flow->in_port is the odp port, and
this fix is mainly for the userspace datapath for ipf_ctx.

the reason I prefer using flow->in_port is mainly that it is more
cache efficient to touch a flow struct than packet->md (since you have to
touch
packet metadata, it's changing and more likely not in cahce compared to
flow).
But I am ok if changed to using packet->md.




> I'm not sure the unit test is possible here, as datapath currently
> doesn't use the in_port from the flow structure while executing
> actions.  And taking into account my previous reply here:
>   https://mail.openvswitch.org/pipermail/ovs-dev/2022-February/391570.html
> I'd say that having OpenFlow port number in that structure is fairly
> correct and we need to fix the ipf_ctx patch to use the port number
> from the packet metadata instead.
>
> I'll also post a couple of questions for the ipf_ctx patch.




> >
> >>  1 file changed, 1 insertion(+)
> >>
> >> diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c
> >> index cba49a99e..72de67c63 100644
> >> --- a/ofproto/ofproto-dpif.c
> >> +++ b/ofproto/ofproto-dpif.c
> >> @@ -4973,6 +4973,7 @@ packet_execute_prepare(struct ofproto *ofproto_,
> >>  ofproto_dpif_set_packet_odp_port(ofproto,
> opo->flow->in_port.ofp_port,
> >>   opo->packet);
> >>
> >> +opo->flow->in_port = opo->packet->md.in_port;
> >>  ofproto_dpif_packet_out_delete(aux);
> >>  opo->aux = execute;
> >>  }
> >
>
>

-- 
hepeng
___
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev


Re: [ovs-dev] [PATCH v3 08/14] treewide: Avoid offsetting NULL pointers.

2022-02-14 Thread Ilya Maximets
On 1/24/22 15:19, Dumitru Ceara wrote:
> This is undefined behavior and was reported by UB Sanitizer:
>   lib/meta-flow.c:3445:16: runtime error: member access within null pointer 
> of type 'struct vl_mf_field'
>   #0 0x6aad0f in mf_get_vl_mff lib/meta-flow.c:3445
>   #1 0x6d96d7 in mf_from_oxm_header lib/nx-match.c:260
>   #2 0x6d9e2e in nx_pull_header__ lib/nx-match.c:341
>   #3 0x6daafa in nx_pull_header lib/nx-match.c:488
>   #4 0x6abcb6 in mf_vl_mff_nx_pull_header lib/meta-flow.c:3605
>   #5 0x73b9be in decode_NXAST_RAW_REG_MOVE lib/ofp-actions.c:2652
>   #6 0x764ccd in ofpact_decode lib/ofp-actions.inc2:4681
>   [...]
>   lib/sset.c:315:12: runtime error: applying zero offset to null pointer
>   #0 0xcc2e6a in sset_at_position /root/ovs/lib/sset.c:315:12
>   #1 0x5734b3 in port_dump_next /root/ovs/ofproto/ofproto-dpif.c:4083:20
>   [...]
>   lib/ovsdb-data.c:2194:56: runtime error: applying zero offset to null 
> pointer
>   #0 0x5e9530 in ovsdb_datum_added_removed 
> /root/ovs/lib/ovsdb-data.c:2194:56
>   #1 0x4d6258 in update_row_ref_count /root/ovs/ovsdb/transaction.c:335:17
>   #2 0x4c360b in for_each_txn_row /root/ovs/ovsdb/transaction.c:1572:33
>   [...]
>   lib/ofpbuf.c:440:30: runtime error: applying zero offset to null pointer
>   #0 0x75066d in ofpbuf_push_uninit lib/ofpbuf.c:440
>   #1 0x46ac8a in ovnacts_parse lib/actions.c:4190
>   #2 0x46ad91 in ovnacts_parse_string lib/actions.c:4208
>   #3 0x4106d1 in test_parse_actions tests/test-ovn.c:1324
>   [...]
>   lib/ofp-actions.c:3205:22: runtime error: applying non-zero offset 2 to 
> null pointer
>   #0 0x6e1641 in set_field_split_str /root/ovs/lib/ofp-actions.c:3205:22
>   [...]
>   lib/tnl-ports.c:74:12: runtime error: applying zero offset to null pointer
>   #0 0xceffe7 in tnl_port_cast /root/ovs/lib/tnl-ports.c:74:12
>   #1 0xcf14c3 in map_insert /root/ovs/lib/tnl-ports.c:116:13
>   [...]
>   ofproto/ofproto.c:8905:16: runtime error: applying zero offset to null 
> pointer
>   #0 0x556795 in eviction_group_hash_rule 
> /root/ovs/ofproto/ofproto.c:8905:16
>   #1 0x503f8d in eviction_group_add_rule 
> /root/ovs/ofproto/ofproto.c:9022:42
>   [...]
> 
> Also, it's valid to have an empty ofpact list and we should be able to
> try to iterate through it.
> 
> UB Sanitizer report:
>   include/openvswitch/ofp-actions.h:222:12: runtime error: applying zero 
> offset to null pointer
>   #0 0x665d69 in ofpact_end 
> /root/ovs/./include/openvswitch/ofp-actions.h:222:12
>   #1 0x66b2cf in ofpacts_put_openflow_actions 
> /root/ovs/lib/ofp-actions.c:8861:5
>   #2 0x6ffdd1 in ofputil_encode_flow_mod /root/ovs/lib/ofp-flow.c:447:9
>   [...]
> 
> Signed-off-by: Dumitru Ceara 
> ---
>  include/openvswitch/ofp-actions.h |4 +++-
>  include/openvswitch/ofpbuf.h  |   17 -
>  lib/dynamic-string.c  |   10 --
>  lib/meta-flow.c   |4 +++-
>  lib/ofp-actions.c |8 
>  lib/ofpbuf.c  |4 
>  lib/ovsdb-data.c  |   37 
> +
>  lib/ovsdb-data.h  |4 
>  lib/sset.c|4 +++-
>  lib/tnl-ports.c   |2 +-
>  ofproto/ofproto.c |2 +-
>  11 files changed, 64 insertions(+), 32 deletions(-)
> 
> diff --git a/include/openvswitch/ofp-actions.h 
> b/include/openvswitch/ofp-actions.h
> index 41bcb55d2056..b7231c7bb334 100644
> --- a/include/openvswitch/ofp-actions.h
> +++ b/include/openvswitch/ofp-actions.h
> @@ -218,7 +218,9 @@ struct ofpact *ofpact_next_flattened(const struct ofpact 
> *);
>  static inline struct ofpact *
>  ofpact_end(const struct ofpact *ofpacts, size_t ofpacts_len)
>  {
> -return ALIGNED_CAST(struct ofpact *, (uint8_t *) ofpacts + ofpacts_len);
> +return ofpacts
> +   ? ALIGNED_CAST(struct ofpact *, (uint8_t *) ofpacts + ofpacts_len)
> +   : NULL;
>  }
>  
>  static inline bool
> diff --git a/include/openvswitch/ofpbuf.h b/include/openvswitch/ofpbuf.h
> index 1136ba04c84e..a9ff8a56e81c 100644
> --- a/include/openvswitch/ofpbuf.h
> +++ b/include/openvswitch/ofpbuf.h
> @@ -179,7 +179,9 @@ static inline void ofpbuf_delete(struct ofpbuf *b)
>  static inline void *ofpbuf_at(const struct ofpbuf *b, size_t offset,
>size_t size)
>  {
> -return offset + size <= b->size ? (char *) b->data + offset : NULL;
> +return offset + size <= b->size && b->data

It's better to parenthesize the condition.

> +   ? (char *) b->data + offset
> +   : NULL;
>  }
>  
>  /* Returns a pointer to byte 'offset' in 'b', which must contain at least
> @@ -188,20 +190,20 @@ static inline void *ofpbuf_at_assert(const struct 
> ofpbuf *b, size_t offset,
>   size_t size)
>  {
>  ovs_assert(offset + 

Re: [ovs-dev] [PATCH v2 ovn] introduce rdnss, dnssl and route_info opt in put_nd_ra_opts action

2022-02-14 Thread Numan Siddique
On Fri, Feb 11, 2022 at 5:41 PM Lorenzo Bianconi
 wrote:
>
> > On Tue, Feb 8, 2022 at 1:27 PM Mark Michelson  wrote:
> > >
> > > Thanks Lorenzo.
> > >
> > > Acked-by: Mark Michelson 
> >
> > Thanks.  I applied to the main branch.
>
> Thanks Numan. I guess this patch can be considered a bug-fix, so can you 
> please
> backport it? Thanks.

I've backported to branch-21.12.  Do let me know if it needs
backporting further down.

Numan

>
> Regards,
> Lorenzo
>
> >
> > Numan
> >
> > >
> > > On 2/4/22 19:19, Lorenzo Bianconi wrote:
> > > > Send non-periodic Router Advertisement with rdnss, dnssl and route_info
> > > > options if configured by the user.
> > > >
> > > > Reported-at: https://bugzilla.redhat.com/show_bug.cgi?id=1851788
> > > > Signed-off-by: Lorenzo Bianconi 
> > > > ---
> > > > Changes since v1:
> > > > - copy input string before running strtok_r() in encode_ra_dnssl_opt() 
> > > > and
> > > >encode_ra_route_info_opt().
> > > > - cap max len value in encode_ra_dnssl_opt().
> > > > ---
> > > >   controller/pinctrl.c  |  35 ++
> > > >   include/ovn/actions.h |   1 +
> > > >   lib/actions.c | 153 ++
> > > >   lib/ovn-l7.h  |   3 +
> > > >   northd/northd.c   |  16 +
> > > >   tests/ovn.at  |  30 +++--
> > > >   6 files changed, 204 insertions(+), 34 deletions(-)
> > > >
> > > > diff --git a/controller/pinctrl.c b/controller/pinctrl.c
> > > > index 293aecea2..ac6ec26e0 100644
> > > > --- a/controller/pinctrl.c
> > > > +++ b/controller/pinctrl.c
> > > > @@ -3712,37 +3712,14 @@ static void
> > > >   packet_put_ra_dnssl_opt(struct dp_packet *b, ovs_be32 lifetime,
> > > >   char *dnssl_data)
> > > >   {
> > > > -char *dnssl_list, *t0, *r0 = NULL, dnssl[255] = {};
> > > >   size_t prev_l4_size = dp_packet_l4_size(b);
> > > > -size_t size = sizeof(struct ovs_nd_dnssl);
> > > > -int i = 0;
> > > > +char dnssl[255] = {};
> > > > +int size;
> > > >
> > > > -dnssl_list = xstrdup(dnssl_data);
> > > > -
> > > > -/* Multiple DNS Search List must be 'comma' separated
> > > > - * (e.g. "a.b.c, d.e.f"). Domain names must be encoded
> > > > - * as described in Section 3.1 of RFC1035.
> > > > - * (e.g if dns list is a.b.c,www.ovn.org, it will be encoded as:
> > > > - * 01 61 01 62 01 63 00 03 77 77 77 03 6f 76 63 03 6f 72 67 00
> > > > - */
> > > > -for (t0 = strtok_r(dnssl_list, ",", ); t0;
> > > > - t0 = strtok_r(NULL, ",", )) {
> > > > -char *t1, *r1 = NULL;
> > > > -
> > > > -size += strlen(t0) + 2;
> > > > -if (size > sizeof(dnssl)) {
> > > > -goto out;
> > > > -}
> > > > -
> > > > -for (t1 = strtok_r(t0, ".", ); t1;
> > > > - t1 = strtok_r(NULL, ".", )) {
> > > > -dnssl[i++] = strlen(t1);
> > > > -memcpy([i], t1, strlen(t1));
> > > > -i += strlen(t1);
> > > > -}
> > > > -dnssl[i++] = 0;
> > > > +size = encode_ra_dnssl_opt(dnssl_data, dnssl, sizeof(dnssl));
> > > > +if (size < 0) {
> > > > +return;
> > > >   }
> > > > -size = ROUND_UP(size, 8);
> > > >
> > > >   struct ip6_hdr *nh = dp_packet_l3(b);
> > > >   nh->ip6_plen = htons(prev_l4_size + size);
> > > > @@ -3760,8 +3737,6 @@ packet_put_ra_dnssl_opt(struct dp_packet *b, 
> > > > ovs_be32 lifetime,
> > > >   uint32_t icmp_csum = packet_csum_pseudoheader6(dp_packet_l3(b));
> > > >   ra->icmph.icmp6_cksum = csum_finish(csum_continue(icmp_csum, ra,
> > > > prev_l4_size + 
> > > > size));
> > > > -out:
> > > > -free(dnssl_list);
> > > >   }
> > > >
> > > >   static void
> > > > diff --git a/include/ovn/actions.h b/include/ovn/actions.h
> > > > index cdef5fb03..0641b927e 100644
> > > > --- a/include/ovn/actions.h
> > > > +++ b/include/ovn/actions.h
> > > > @@ -807,5 +807,6 @@ void ovnacts_encode(const struct ovnact[], size_t 
> > > > ovnacts_len,
> > > >
> > > >   void ovnacts_free(struct ovnact[], size_t ovnacts_len);
> > > >   char *ovnact_op_to_string(uint32_t);
> > > > +int encode_ra_dnssl_opt(char *data, char *buf, int buf_len);
> > > >
> > > >   #endif /* ovn/actions.h */
> > > > diff --git a/lib/actions.c b/lib/actions.c
> > > > index d5d8391bb..5d3caaf2b 100644
> > > > --- a/lib/actions.c
> > > > +++ b/lib/actions.c
> > > > @@ -40,6 +40,7 @@
> > > >   #include "simap.h"
> > > >   #include "uuid.h"
> > > >   #include "socket-util.h"
> > > > +#include "lib/ovn-util.h"
> > > >
> > > >   VLOG_DEFINE_THIS_MODULE(actions);
> > > >
> > > > @@ -2992,6 +2993,15 @@ parse_put_nd_ra_opts(struct action_context *ctx, 
> > > > const struct expr_field *dst,
> > > >   case ND_OPT_MTU:
> > > >   ok = c->format == LEX_F_DECIMAL;
> > > >   break;
> > > > +
> > > > +case ND_OPT_RDNSS:
> > > > +ok = c->format == LEX_F_IPV6;
> > > > +   

Re: [ovs-dev] [PATCH v3 04/14] treewide: Fix invalid bit shift operations.

2022-02-14 Thread Ilya Maximets
On 1/24/22 15:18, Dumitru Ceara wrote:
> UB Sanitizer reports:
>   tests/test-hash.c:59:40: runtime error: shift exponent 64 is too large for 
> 64-bit type 'long unsigned int'
>   #0 0x44c3c9 in get_range128 tests/test-hash.c:59
>   #1 0x44cb2e in check_hash_bytes128 tests/test-hash.c:178
>   #2 0x44d14d in test_hash_main tests/test-hash.c:282
>   [...]
>   ofproto/ofproto-dpif-xlate.c:5607:45: runtime error: left shift of 65535 by 
> 16 places cannot be represented in type 'int'
>   #0 0x53fe9f in xlate_sample_action ofproto/ofproto-dpif-xlate.c:5607
>   #1 0x54d625 in do_xlate_actions ofproto/ofproto-dpif-xlate.c:7160
>   #2 0x553b76 in xlate_actions ofproto/ofproto-dpif-xlate.c:7806
>   #3 0x4fcb49 in upcall_xlate ofproto/ofproto-dpif-upcall.c:1237
>   #4 0x4fe02f in process_upcall ofproto/ofproto-dpif-upcall.c:1456
>   #5 0x4fda99 in upcall_cb ofproto/ofproto-dpif-upcall.c:1358
>   [...]
>   tests/test-util.c:89:23: runtime error: left shift of 1 by 31 places cannot 
> be represented in type 'int'
>   #0 0x476415 in test_ctz tests/test-util.c:89
>   [...]
>   lib/dpif-netlink.c:396:33: runtime error: left shift of 1 by 31 places 
> cannot be represented in type 'int'
>   #0 0x571b9f in dpif_netlink_open lib/dpif-netlink.c:396
> 
> Acked-by: Aaron Conole 
> Signed-off-by: Dumitru Ceara 
> ---
> v3: Added Aaron's ack.
> ---
>  lib/dpif-netlink.c   |2 +-
>  ofproto/ofproto-dpif-xlate.c |3 ++-
>  tests/test-hash.c|2 +-
>  tests/test-util.c|   13 ++---
>  4 files changed, 10 insertions(+), 10 deletions(-)
> 
> diff --git a/lib/dpif-netlink.c b/lib/dpif-netlink.c
> index 71e35ccddaae..06e1e8ca0283 100644
> --- a/lib/dpif-netlink.c
> +++ b/lib/dpif-netlink.c
> @@ -85,7 +85,7 @@ enum { MAX_PORTS = USHRT_MAX };
>  #define EPOLLEXCLUSIVE (1u << 28)
>  #endif
>  
> -#define OVS_DP_F_UNSUPPORTED (1 << 31);
> +#define OVS_DP_F_UNSUPPORTED (1u << 31);
>  
>  /* This PID is not used by the kernel datapath when using dispatch per CPU,
>   * but it is required to be set (not zero). */
> diff --git a/ofproto/ofproto-dpif-xlate.c b/ofproto/ofproto-dpif-xlate.c
> index 6fb59e1702ec..d2b26f8ee27d 100644
> --- a/ofproto/ofproto-dpif-xlate.c
> +++ b/ofproto/ofproto-dpif-xlate.c
> @@ -5618,7 +5618,8 @@ xlate_sample_action(struct xlate_ctx *ctx,
>  
>  /* Scale the probability from 16-bit to 32-bit while representing
>   * the same percentage. */
> -uint32_t probability = (os->probability << 16) | os->probability;
> +uint32_t probability =
> +((uint32_t) os->probability << 16) | os->probability;
>  
>  /* If ofp_port in flow sample action is equel to ofp_port,
>   * this sample action is a input port action. */
> diff --git a/tests/test-hash.c b/tests/test-hash.c
> index 5d3f8ea43f65..7c33922e3f02 100644
> --- a/tests/test-hash.c
> +++ b/tests/test-hash.c
> @@ -174,7 +174,7 @@ check_hash_bytes128(void (*hash)(const void *, size_t, 
> uint32_t, ovs_u128 *),
>  
>  set_bit128(, j, n_bits);
>  hash(, sizeof(ovs_u128), 0, );
> -for (ofs = 0; ofs < 128 - min_unique; ofs++) {
> +for (ofs = 1; ofs < 128 - min_unique; ofs++) {

It looks like we're reducing the quality of the test here.
Shouldn't we change get_range128() function to return
"value->u64.lo & mask" if ofs == 0 instead?

>  uint64_t bits1 = get_range128(, ofs, unique_mask);
>  uint64_t bits2 = get_range128(, ofs, unique_mask);
>  
___
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev


Re: [ovs-dev] [PATCH 5/5] system-traffic.at: Do not use ranges with broadcast address.

2022-02-14 Thread Ilya Maximets
On 1/28/22 17:14, Aaron Conole wrote:
> From: Paolo Valerio 
> 
> turn a bunch of test ranges from 10.1.1.240-10.1.1.255 to
> 10.1.1.240-10.1.1.254. 10.1.1.255 is the broadcast address for
> 10.1.1.0/24 and can be picked to SNAT packets causing the subsequent
> failure of the test.
> 
> Fixes: 9ac0aadab9f9 ("conntrack: Add support for NAT.")
> Fixes: e32cd4c6292e ("conntrack: ignore port for ICMP/ICMPv6 NAT.")
> Signed-off-by: Paolo Valerio 
> Acked-by: Eelco Chaudron 
> Acked-by: Aaron Conole 
> Signed-off-by: Aaron Conole 
> ---
>  tests/system-traffic.at | 14 +++---
>  1 file changed, 7 insertions(+), 7 deletions(-)

Applied this one for now.  Thanks!

Best regards, Ilya Maximets.
___
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev


Re: [ovs-dev] [PATCH] conntrack: Avoid sporadic failures during IPv6 HTTP/FTP tests

2022-02-14 Thread Ilya Maximets
On 12/27/21 14:27, Paolo Valerio wrote:
> Some sporadic false positive may be visible for the following tests:
> 
> - conntrack - IPv6 HTTP
> - conntrack - FTP over IPv6
> 
> The failures show up randomly.
> The reason appears to be source address used when performing the
> request using wget:
> -tcp,orig=(src=fc00::1,dst=fc00::2,sport=,dport=),reply=(src=fc00::2,dst=fc00::1,sport=,dport=),protoinfo=(state=)
> +tcp,orig=(src=fe80::f0eb:f8ff:fef0:138f,dst=fc00::2,sport=,dport=),reply=(src=fc00::2,dst=fe80::f0eb:f8ff:fef0:138f,sport=,dport=),protoinfo=(state=)
> 
> It seems that the problem can be addressed in multiple ways, but using
> "nodad" seems to be safe enough to fix the issue that now, after
> hundreds of attempts, is no longer present.
> 
> Signed-off-by: Paolo Valerio 
> ---
>  tests/system-traffic.at |   13 +++--
>  1 file changed, 7 insertions(+), 6 deletions(-)

Applied.  Thanks!

Best regards, Ilya Maximets.
___
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev


Re: [ovs-dev] [PATCH ovn] NEWS: add info about ovn-controller-vtep version pinning

2022-02-14 Thread Numan Siddique
On Mon, Feb 14, 2022 at 12:54 PM Vladislav Odintsov  wrote:
>
> Signed-off-by: Vladislav Odintsov 

Thanks.  Applied.

Numan

> ---
>  NEWS | 3 +++
>  1 file changed, 3 insertions(+)
>
> diff --git a/NEWS b/NEWS
> index bf052838d..984e9977e 100644
> --- a/NEWS
> +++ b/NEWS
> @@ -7,6 +7,9 @@ Post v21.12.0
>  - ovn-nbctl copp-list 
>  - ovn-nbctl ls-copp-add  
>  - ovn-nbctl lr-copp-add  
> +  - Support version pinning between ovn-northd and ovn-controller-vtep as an
> +option. If the option is enabled and the versions don't match,
> +ovn-controller-vtep will not process any DB changes.
>
>  OVN v21.12.0 - 22 Dec 2021
>  --
> --
> 2.26.3
>
> ___
> 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 v9 4/6] northd, utils: support for RouteTables in LRs

2022-02-14 Thread Vladislav Odintsov
Hi Dumitru,

I’ve got a general question about what the logical topology you’d like to 
implement.

Also, please see inline comments.


Regards,
Vladislav Odintsov

> On 14 Feb 2022, at 15:51, Dumitru Ceara  wrote:
> 
> Hi Vladislav,
> 
> I was looking at what options we have in OVN to implement a VRF-like
> behavior and then remembered you had worked on the multiple routing
> table feature.
> 
> On 11/19/21 17:07, Vladislav Odintsov wrote:
>> This patch extends Logical Router's routing functionality.
>> Now user may create multiple routing tables within a Logical Router
>> and assign them to Logical Router Ports.
>> 
>> Traffic coming from Logical Router Port with assigned route_table
>> is checked against Logical_Router_Static_Routes with same route_table
>> field value and routes to connected networks. If no route_table option
>> is set to the LRP, routes' lookup is done agains routes with no
>> route_table field value ("", empty string) and against routes to
>> connected networks.
> 
> I was a bit surprised by the fact that if there's no static route with
> the same route_table value as the ingress router port we go ahead and
> match against all connected networks, regardless of their ports' route
> tables.

The current behaviour is expected — earlier while code review I’ve described 
it’s similar
to AWS/GCP VPC lookup logic: the "local" route (route to connected 
networks/subnets) is present
always and can’t be deleted or modified.
This means that "connected" routes (including learned routes from other AZs, 
which
have "connected" origin) are installed in the routing table regardless of their 
`route_table` value.
But the user may create more specific static route if he/she needs it and this 
route doesn’t break
necessary connectivity.

> Does it make sense to change this and perform longest prefix match in
> general, always matching on route_table?

I can’t imagine how to easy support current behaviour with such change. I mean 
how
to force a match against all connected routes regardless of routing table.
The only one option I see is to add an option for LR, which configures a mode of
local routes match: with or without route_table value respect.
> 
> In this case connected routes could inherit the route_table value from
> the corresponding router ports where they're defined.
> 
> Would that break your use case?

Please, see previous comment.

> 
> Thanks,
> Dumitru
> 
> ___
> 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 2/5] ipf: add ipf context

2022-02-14 Thread Ilya Maximets
On 1/28/22 17:14, Aaron Conole wrote:
> From: Peng He 
> 
> ipf_postprocess will emit packets into the datapath pipeline ignoring
> the conntrack context, this might casuse weird issues when a packet
> batch has less space to hold all the fragments belonging to single
> packet.
> 
> Given the below ruleest and consider sending a 64K ICMP packet which
> is splitted into 64 fragments.
> 
> priority=1,action=drop
> priority=10,arp,action=normal
> priority=100,in_port=1,ct_state=-trk,icmp,action=ct(zone=9,table=0)
> priority=100,in_port=1,ct_state=+new+trk,icmp,action=ct(zone=9,commit),2
> priority=100,in_port=1,ct_state=-new+est+trk,icmp,action=2
> priority=100,in_port=2,ct_state=-trk,icmp,action=ct(table=0,zone=9)
> priority=100,in_port=2,ct_state=+trk+est-new,icmp,action=1
> 
> Batch 1:
> the first 32 packets will be buffered in the ipf preprocessing, nothing
> more proceeds.
> 
> Batch 2:
> the second 32 packets succeed the fragment reassembly and goes to ct
> and ipf_post will emits the first 32 packets due to the limit of batch
> size.
> 
> the first 32 packets goes to the datapath again due to the
> recirculation, and again buffered at ipf preprocessing before ct commit,
> then the ovs tries to call ct commit as well as ipf_postprocessing which emits
> the last 32 packets, in this case the last 32 packets will follow
> the current actions which will be sent to port 2 directly without
> recirculation and going to ipf preprocssing and ct commit again.
> 
> This will cause the first 32 packets never get the chance to
> reassemble and evevntually this large ICMP packets fail to transmit.
> 
> this patch fixes this issue by adding firstly ipf context to avoid
> ipf_postprocessing emits packets in the wrong context. Then by
> re-executing the action list again to emit the last 32 packets
> in the right context to correctly transmitting multiple fragments.
> 
> This might be one of the root cause why the OVS log warns:
> 
> "
> skipping output to input port on bridge br-int while processing
> "
> 
> As a pkt might enter into different ipf context.
> 
> One implementation trick of implementing ipf_ctx_eq, is to use ipf_list's
> key instead of the first frag's metadata, this can reduce quite a lot of
> cache misses as at the time of calling ipf_ctx_eq, ipf_list is cache-hot.
> On x86_64, this trick saves 2% of CPU usage of ipf processing.
> 
> Signed-off-by: Peng He 
> Co-authored-by: Mike Pattrick 
> Signed-off-by: Aaron Conole 
> ---
>  lib/conntrack.c |  9 ---
>  lib/conntrack.h | 15 ++--
>  lib/dpif-netdev.c   | 52 +
>  lib/ipf.c   | 39 ---
>  lib/ipf.h   | 11 +++--
>  tests/system-traffic.at | 33 ++
>  tests/test-conntrack.c  |  6 ++---
>  7 files changed, 135 insertions(+), 30 deletions(-)
> 
> diff --git a/lib/conntrack.c b/lib/conntrack.c
> index 33a1a92953..72999f1aed 100644
> --- a/lib/conntrack.c
> +++ b/lib/conntrack.c
> @@ -1434,14 +1434,14 @@ process_one(struct conntrack *ct, struct dp_packet 
> *pkt,
>   * connection tables.  'setmark', if not NULL, should point to a two
>   * elements array containing a value and a mask to set the connection mark.
>   * 'setlabel' behaves similarly for the connection label.*/
> -int
> +bool
>  conntrack_execute(struct conntrack *ct, struct dp_packet_batch *pkt_batch,
>ovs_be16 dl_type, bool force, bool commit, uint16_t zone,
>const uint32_t *setmark,
>const struct ovs_key_ct_labels *setlabel,
>ovs_be16 tp_src, ovs_be16 tp_dst, const char *helper,
>const struct nat_action_info_t *nat_action_info,
> -  long long now, uint32_t tp_id)
> +  long long now, uint32_t tp_id, struct ipf_ctx *ipf_ctx)
>  {
>  ipf_preprocess_conntrack(ct->ipf, pkt_batch, now, dl_type, zone,
>   ct->hash_basis);
> @@ -1468,9 +1468,8 @@ conntrack_execute(struct conntrack *ct, struct 
> dp_packet_batch *pkt_batch,
>  }
>  }
>  
> -ipf_postprocess_conntrack(ct->ipf, pkt_batch, now, dl_type);
> -
> -return 0;
> +return ipf_postprocess_conntrack(ct->ipf, pkt_batch, ipf_ctx, \
> + now, dl_type);
>  }
>  
>  void
> diff --git a/lib/conntrack.h b/lib/conntrack.h
> index 9553b188a4..211efad3f3 100644
> --- a/lib/conntrack.h
> +++ b/lib/conntrack.h
> @@ -64,6 +64,7 @@
>  struct dp_packet_batch;
>  
>  struct conntrack;
> +struct ipf_ctx;
>  
>  union ct_addr {
>  ovs_be32 ipv4;
> @@ -88,13 +89,13 @@ struct nat_action_info_t {
>  struct conntrack *conntrack_init(void);
>  void conntrack_destroy(struct conntrack *);
>  
> -int conntrack_execute(struct conntrack *ct, struct dp_packet_batch 
> *pkt_batch,
> -  ovs_be16 dl_type, bool force, bool commit, uint16_t 
> zone,
> -  const uint32_t 

Re: [ovs-dev] [PATCH ovn] vtep: provide option to check ovn-controller-vtep and ovn-northd versions

2022-02-14 Thread Vladislav Odintsov
Thanks Numan,

done: 
https://patchwork.ozlabs.org/project/ovn/patch/20220214175335.1956758-1-odiv...@gmail.com/

Regards,
Vladislav Odintsov

> On 11 Feb 2022, at 23:56, Numan Siddique  wrote:
> 
> On Wed, Feb 2, 2022 at 3:39 PM Vladislav Odintsov  > wrote:
>> 
>> Simlar to ovn-controller's behavior with checking internal
>> version of ovn-northd and ovn-controller when option
>> ovn-match-northd-version is defined, this commit adds same
>> functionality for the ovn-controller-vtep daemon.
>> 
>> This configuration option is located in the configured
>> hardware_vtep database in the Global table's
>> other_config:ovn-match-northd-version column/key.
>> True value enforces check, while false or not defined values
>> skip the check.
>> 
>> The appropriate testcase is added as well.
>> 
>> Signed-off-by: Vladislav Odintsov 
> 
> Thanks.  I applied this patch to the main branch.
> 
> Can you please submit another patch adding a news entry for this ?
> 
> Numan
> 
>> ---
>> controller-vtep/ovn-controller-vtep.8.xml | 23 +-
>> controller-vtep/ovn-controller-vtep.c | 50 +++--
>> tests/ovn-controller-vtep.at  | 55 +++
>> 3 files changed, 124 insertions(+), 4 deletions(-)
>> 
>> diff --git a/controller-vtep/ovn-controller-vtep.8.xml 
>> b/controller-vtep/ovn-controller-vtep.8.xml
>> index 2c706e46e..0b9987bdb 100644
>> --- a/controller-vtep/ovn-controller-vtep.8.xml
>> +++ b/controller-vtep/ovn-controller-vtep.8.xml
>> @@ -34,7 +34,7 @@
>>   information from both the ovnsb and the vtep database.  If the
>>   database locations are not given from command line, the default
>>   is the db.sock in local OVSDB's 'run' directory.
>> -  The datapath location must take one of the following forms:
>> +  The database location must take one of the following forms:
>> 
>> 
>>   
>> @@ -77,4 +77,25 @@
>> 
>>   
>> 
>> +
>> +
>> +  ovn-controller-vtep assumes it gets configuration
>> +  information from the following keys in the Global
>> +  table of the connected hardware_vtep database:
>> +
>> +
>> +
>> +
>> +  other_config:ovn-match-northd-version
>> +  
>> +The boolean flag indicates if ovn-controller-vtep 
>> needs to
>> +check ovn-northd version. If this flag is set to true 
>> and
>> +the ovn-northd's version (reported in the Southbound
>> +database) doesn't match with the ovn-controller-vtep's
>> +internal version, then it will stop processing the southbound and
>> +connected hardware_vtep database changes.
>> +The default value is considered false if this option is not defined.
>> +  
>> +
>> +
>> 
>> diff --git a/controller-vtep/ovn-controller-vtep.c 
>> b/controller-vtep/ovn-controller-vtep.c
>> index 1d35c7f04..50f412b95 100644
>> --- a/controller-vtep/ovn-controller-vtep.c
>> +++ b/controller-vtep/ovn-controller-vtep.c
>> @@ -30,6 +30,7 @@
>> #include "fatal-signal.h"
>> #include "openvswitch/poll-loop.h"
>> #include "simap.h"
>> +#include "ovsdb-idl.h"
>> #include "stream.h"
>> #include "stream-ssl.h"
>> #include "unixctl.h"
>> @@ -45,6 +46,8 @@
>> #include "vtep.h"
>> #include "ovn-controller-vtep.h"
>> 
>> +VLOG_DEFINE_THIS_MODULE(main);
>> +
>> static unixctl_cb_func ovn_controller_vtep_exit;
>> 
>> static void parse_options(int argc, char *argv[]);
>> @@ -54,6 +57,37 @@ static char *vtep_remote;
>> static char *ovnsb_remote;
>> static char *default_db_;
>> 
>> +/* Returns true if the northd internal version stored in SB_Global
>> + * and ovn-controller-vtep internal version match.
>> + */
>> +static bool
>> +check_northd_version(struct ovsdb_idl *vtep_idl, struct ovsdb_idl 
>> *ovnsb_idl,
>> + const char *version)
>> +{
>> +const struct vteprec_global *cfg = vteprec_global_first(vtep_idl);
>> +if (!cfg || !smap_get_bool(>other_config, 
>> "ovn-match-northd-version",
>> +   false)) {
>> +return true;
>> +}
>> +
>> +const struct sbrec_sb_global *sb = sbrec_sb_global_first(ovnsb_idl);
>> +if (!sb) {
>> +return false;
>> +}
>> +
>> +const char *northd_version =
>> +smap_get_def(>options, "northd_internal_version", "");
>> +
>> +if (strcmp(northd_version, version)) {
>> +static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 1);
>> +VLOG_WARN_RL(, "controller-vtep version - %s mismatch with 
>> northd "
>> + "version - %s", version, northd_version);
>> +return false;
>> +}
>> +
>> +return true;
>> +}
>> +
>> int
>> main(int argc, char *argv[])
>> {
>> @@ -91,6 +125,9 @@ main(int argc, char *argv[])
>> ovsdb_idl_create(ovnsb_remote, _idl_class, true, true));
>> ovsdb_idl_get_initial_snapshot(ovnsb_idl_loop.idl);
>> 
>> +char *ovn_version = ovn_get_internal_version();
>> +VLOG_INFO("OVN internal version is 

[ovs-dev] [PATCH ovn] NEWS: add info about ovn-controller-vtep version pinning

2022-02-14 Thread Vladislav Odintsov
Signed-off-by: Vladislav Odintsov 
---
 NEWS | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/NEWS b/NEWS
index bf052838d..984e9977e 100644
--- a/NEWS
+++ b/NEWS
@@ -7,6 +7,9 @@ Post v21.12.0
 - ovn-nbctl copp-list 
 - ovn-nbctl ls-copp-add  
 - ovn-nbctl lr-copp-add  
+  - Support version pinning between ovn-northd and ovn-controller-vtep as an
+option. If the option is enabled and the versions don't match,
+ovn-controller-vtep will not process any DB changes.
 
 OVN v21.12.0 - 22 Dec 2021
 --
-- 
2.26.3

___
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev


Re: [ovs-dev] [PATCH v2] ofproto-dpif: fix packet_execute_prepare

2022-02-14 Thread Ilya Maximets
On 2/14/22 18:32, Aaron Conole wrote:
> Peng He  writes:
> 
>> In the commit 1df7f7aac8c976690167261fec9a50d832ef9e7e, the packet
>> metadata's in_port has been changed from ofp port into odp port,
>> however, the odp->flow->in_port is still ofp_port. This patch changes
>> the odp->flow->in_port into odp_port.
>>
>> Fixes: 1df7f7aac8 ("ofproto-dpif: Restore packet metadata when a
>> continuation is resumed.")
> 
> This tag is still wrapped, and I don't think the fixes tag is for the
> correct commit.
> 
>> Signed-off-by: Peng He 
>> ---
>>  ofproto/ofproto-dpif.c | 1 +
> 
> Also, seems there is no unit test as requested.  Can you please address
> these?

I'm not sure the unit test is possible here, as datapath currently
doesn't use the in_port from the flow structure while executing
actions.  And taking into account my previous reply here:
  https://mail.openvswitch.org/pipermail/ovs-dev/2022-February/391570.html
I'd say that having OpenFlow port number in that structure is fairly
correct and we need to fix the ipf_ctx patch to use the port number
from the packet metadata instead.

I'll also post a couple of questions for the ipf_ctx patch.

> 
>>  1 file changed, 1 insertion(+)
>>
>> diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c
>> index cba49a99e..72de67c63 100644
>> --- a/ofproto/ofproto-dpif.c
>> +++ b/ofproto/ofproto-dpif.c
>> @@ -4973,6 +4973,7 @@ packet_execute_prepare(struct ofproto *ofproto_,
>>  ofproto_dpif_set_packet_odp_port(ofproto, opo->flow->in_port.ofp_port,
>>   opo->packet);
>>  
>> +opo->flow->in_port = opo->packet->md.in_port;
>>  ofproto_dpif_packet_out_delete(aux);
>>  opo->aux = execute;
>>  }
> 

___
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev


Re: [ovs-dev] [PATCH v2] dpif-netdev-dpcls: Make subtable reprobe thread-safe.

2022-02-14 Thread Ilya Maximets
On 2/14/22 17:39, Stokes, Ian wrote:
>> The subtable search function can be used at any time by a PMD thread.
>> Setting the subtable search function should be done atomically to
>> prevent garbage data from being read.
>>
>> A dpcls_subtable_lookup_reprobe() call can happen at the same time that
>> DPCLS subtables are being sorted. This could lead to modifications done
>> by the reprobe() to be lost. Prevent this from happening by locking on
>> pmd->flow_mutex. After this change both the reprobe function and a
>> subtable sort will share the flow_mutex preventing modifications by
>> either one from being lost.
>>
>> Also remove the pvector_publish() call. The pvector is not being changed
>> in dpcls_subtable_lookup_reprobe(), only the data pointed to by pointers
>> in the vector are being changed.
> 
> Hi Cian,
> 
> Thanks for the patch, in general this looks ok to me, but I realize Ilya had 
> a few comments on the v1. I think these are addressed here but maybe Ilya 
> would like to confirm before sign off?

Thanks, Ian.
I'll take a look at this patch tomorrow.

> 
> @Ilya Maximets should this go into branch 2.17 as well before release?

I'd say, if it applies cleanly, we should try to backport it down to 2.14,
because the issue may cause OVS crash.

Best regards, Ilya Maximets.

> 
> Thanks
> Ian
> 
>>
>> Fixes: 3d018c3ea79d ("dpif-netdev: add subtable lookup prio set command.")
>> Reported-by: Ilya Maximets 
>> Reported-at: https://mail.openvswitch.org/pipermail/ovs-dev/2022-
>> January/390757.html
>> Signed-off-by: Cian Ferriter 
>> ---
>>  lib/dpif-netdev-private-dpcls.h |  6 --
>>  lib/dpif-netdev.c   | 20 
>>  2 files changed, 20 insertions(+), 6 deletions(-)
>>
>> diff --git a/lib/dpif-netdev-private-dpcls.h 
>> b/lib/dpif-netdev-private-dpcls.h
>> index 7c4a840cb..0d5da73c7 100644
>> --- a/lib/dpif-netdev-private-dpcls.h
>> +++ b/lib/dpif-netdev-private-dpcls.h
>> @@ -83,8 +83,10 @@ struct dpcls_subtable {
>>  /* The lookup function to use for this subtable. If there is a known
>>   * property of the subtable (eg: only 3 bits of miniflow metadata is
>>   * used for the lookup) then this can point at an optimized version of
>> - * the lookup function for this particular subtable. */
>> -dpcls_subtable_lookup_func lookup_func;
>> + * the lookup function for this particular subtable. The lookup function
>> + * can be used at any time by a PMD thread, so it's declared as an 
>> atomic
>> + * here to prevent garbage from being read. */
>> +ATOMIC(dpcls_subtable_lookup_func) lookup_func;
>>
>>  /* Caches the masks to match a packet to, reducing runtime 
>> calculations. */
>>  uint64_t *mf_masks;
>> diff --git a/lib/dpif-netdev.c b/lib/dpif-netdev.c
>> index e28e0b554..71f608a7c 100644
>> --- a/lib/dpif-netdev.c
>> +++ b/lib/dpif-netdev.c
>> @@ -1074,7 +1074,9 @@ dpif_netdev_subtable_lookup_set(struct unixctl_conn
>> *conn, int argc OVS_UNUSED,
>>  if (!cls) {
>>  continue;
>>  }
>> +ovs_mutex_lock(>flow_mutex);
>>  uint32_t subtbl_changes = 
>> dpcls_subtable_lookup_reprobe(cls);
>> +ovs_mutex_unlock(>flow_mutex);
>>  if (subtbl_changes) {
>>  lookup_dpcls_changed++;
>>  lookup_subtable_changed += subtbl_changes;
>> @@ -9736,9 +9738,12 @@ dpcls_create_subtable(struct dpcls *cls, const struct
>> netdev_flow_key *mask)
>>
>>  /* Get the preferred subtable search function for this (u0,u1) subtable.
>>   * The function is guaranteed to always return a valid implementation, 
>> and
>> - * possibly an ISA optimized, and/or specialized implementation.
>> + * possibly an ISA optimized, and/or specialized implementation. 
>> Initialize
>> + * the subtable search function atomically to avoid garbage data being 
>> read
>> + * by the PMD thread.
>>   */
>> -subtable->lookup_func = dpcls_subtable_get_best_impl(unit0, unit1);
>> +atomic_init(>lookup_func,
>> +dpcls_subtable_get_best_impl(unit0, unit1));
>>
>>  cmap_insert(>subtables_map, >cmap_node, mask->hash);
>>  /* Add the new subtable at the end of the pvector (with no hits yet) */
>> @@ -9767,6 +9772,10 @@ dpcls_find_subtable(struct dpcls *cls, const struct
>> netdev_flow_key *mask)
>>  /* Checks for the best available implementation for each subtable lookup
>>   * function, and assigns it as the lookup function pointer for each 
>> subtable.
>>   * Returns the number of subtables that have changed lookup implementation.
>> + * This function requires holding a flow_mutex when called. This is to make
>> + * sure modifications done by this function are not overwritten. This could
>> + * happen if dpcls_sort_subtable_vector() is called at the same time as this
>> + * function.
>>   */
>>  static uint32_t
>>  dpcls_subtable_lookup_reprobe(struct dpcls *cls)
>> @@ 

Re: [ovs-dev] [PATCH v2] ofproto-dpif: fix packet_execute_prepare

2022-02-14 Thread Aaron Conole
Peng He  writes:

> In the commit 1df7f7aac8c976690167261fec9a50d832ef9e7e, the packet
> metadata's in_port has been changed from ofp port into odp port,
> however, the odp->flow->in_port is still ofp_port. This patch changes
> the odp->flow->in_port into odp_port.
>
> Fixes: 1df7f7aac8 ("ofproto-dpif: Restore packet metadata when a
> continuation is resumed.")

This tag is still wrapped, and I don't think the fixes tag is for the
correct commit.

> Signed-off-by: Peng He 
> ---
>  ofproto/ofproto-dpif.c | 1 +

Also, seems there is no unit test as requested.  Can you please address
these?

>  1 file changed, 1 insertion(+)
>
> diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c
> index cba49a99e..72de67c63 100644
> --- a/ofproto/ofproto-dpif.c
> +++ b/ofproto/ofproto-dpif.c
> @@ -4973,6 +4973,7 @@ packet_execute_prepare(struct ofproto *ofproto_,
>  ofproto_dpif_set_packet_odp_port(ofproto, opo->flow->in_port.ofp_port,
>   opo->packet);
>  
> +opo->flow->in_port = opo->packet->md.in_port;
>  ofproto_dpif_packet_out_delete(aux);
>  opo->aux = execute;
>  }

___
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev


Re: [ovs-dev] [PATCH v2 05/16] list: use short version of safe loops if possible

2022-02-14 Thread Ilya Maximets
On 2/14/22 11:13, Adrian Moreno wrote:
> Using the SHORT version of the *_SAFE loops makes the code cleaner
> and less error-prone. So, use the SHORT version and remove the extra
> variable when possible.
> 
> In order to be able to use both long and short versions without changing
> the name of the macro for all the clients, overload the existing name
> and select the appropriate version depending on the number of arguments.
> 
> Signed-off-by: Adrian Moreno 
> ---
>  include/openvswitch/list.h   | 32 +--
>  lib/conntrack.c  |  4 ++--
>  lib/fat-rwlock.c |  4 ++--
>  lib/id-fpool.c   |  3 +--
>  lib/ipf.c| 22 ++---
>  lib/lldp/lldpd-structs.c |  7 +++
>  lib/lldp/lldpd.c |  8 
>  lib/mcast-snooping.c | 12 ++--
>  lib/netdev-afxdp.c   |  4 ++--
>  lib/netdev-dpdk.c|  4 ++--
>  lib/ofp-msgs.c   |  4 ++--
>  lib/ovs-lldp.c   | 12 ++--
>  lib/ovsdb-idl.c  | 30 ++---
>  lib/seq.c|  4 ++--
>  lib/tnl-ports.c  | 16 
>  lib/unixctl.c|  8 
>  lib/vconn.c  |  4 ++--
>  ofproto/connmgr.c|  8 
>  ofproto/ofproto-dpif-ipfix.c |  4 ++--
>  ofproto/ofproto-dpif-trace.c |  4 ++--
>  ofproto/ofproto-dpif-xlate.c |  4 ++--
>  ofproto/ofproto-dpif.c   | 24 +++
>  ovsdb/jsonrpc-server.c   | 16 
>  ovsdb/monitor.c  | 24 +++
>  ovsdb/ovsdb.c|  4 ++--
>  ovsdb/raft.c | 15 +++
>  ovsdb/transaction-forward.c  |  6 +++---
>  ovsdb/transaction.c  | 28 +--
>  ovsdb/trigger.c  |  4 ++--
>  tests/test-list.c| 37 
>  utilities/ovs-ofctl.c|  4 ++--
>  utilities/ovs-vsctl.c|  8 
>  vswitchd/bridge.c| 16 
>  vtep/vtep-ctl.c  | 12 ++--
>  34 files changed, 228 insertions(+), 168 deletions(-)
> 
> diff --git a/include/openvswitch/list.h b/include/openvswitch/list.h
> index 997afc0e4..c6941e896 100644
> --- a/include/openvswitch/list.h
> +++ b/include/openvswitch/list.h
> @@ -93,7 +93,8 @@ static inline bool ovs_list_is_short(const struct ovs_list 
> *);
>   CONDITION_MULTIVAR(VAR, MEMBER, ITER_VAR(VAR) != (LIST));   
>  \
>   UPDATE_MULTIVAR(VAR, (ITER_VAR(VAR) = ITER_VAR(VAR)->prev)))
>  
> -#define LIST_FOR_EACH_REVERSE_SAFE(VAR, PREV, MEMBER, LIST)  
>  \
> +/* LONG version of SAFE iterators */
> +#define LIST_FOR_EACH_REVERSE_SAFE_LONG(VAR, PREV, MEMBER, LIST) 
> \
>  for (INIT_MULTIVAR_SAFE_LONG(VAR, PREV, MEMBER, (LIST)->prev);   
>  \
>   CONDITION_MULTIVAR_SAFE_LONG(VAR, PREV, MEMBER, 
>  \
>ITER_VAR(VAR) != (LIST),   
>  \
> @@ -101,7 +102,7 @@ static inline bool ovs_list_is_short(const struct 
> ovs_list *);
>ITER_VAR(PREV) != (LIST)); 
>  \
>   UPDATE_MULTIVAR_SAFE_LONG(VAR, PREV))
>  
> -#define LIST_FOR_EACH_SAFE(VAR, NEXT, MEMBER, LIST)  
>  \
> +#define LIST_FOR_EACH_SAFE_LONG(VAR, NEXT, MEMBER, LIST) 
>  \
>  for (INIT_MULTIVAR_SAFE_LONG(VAR, NEXT, MEMBER, (LIST)->next);   
>  \
>   CONDITION_MULTIVAR_SAFE_LONG(VAR, NEXT, MEMBER, 
>  \
>ITER_VAR(VAR) != (LIST),   
>  \
> @@ -109,6 +110,33 @@ static inline bool ovs_list_is_short(const struct 
> ovs_list *);
>ITER_VAR(NEXT) != (LIST)); 
>  \
>   UPDATE_MULTIVAR_SAFE_LONG(VAR, NEXT))
>  
> +/* SHORT version of SAFE iterators */
> +#define LIST_FOR_EACH_REVERSE_SAFE_SHORT(VAR, MEMBER, LIST)  
>  \
> +for (INIT_MULTIVAR_SAFE_SHORT(VAR, MEMBER, (LIST)->prev);
>  \
> + CONDITION_MULTIVAR_SAFE_SHORT(VAR, MEMBER,  
>  \
> +   ITER_VAR(VAR) != (LIST),  
>  \
> + ITER_NEXT_VAR(VAR) = ITER_VAR(VAR)->prev);  
>  \
> + UPDATE_MULTIVAR_SAFE_SHORT(VAR))
> +
> +#define LIST_FOR_EACH_SAFE_SHORT(VAR, MEMBER, LIST)  
>  \
> +for (INIT_MULTIVAR_SAFE_SHORT(VAR, MEMBER, (LIST)->next);
>  \
> + CONDITION_MULTIVAR_SAFE_SHORT(VAR, MEMBER,  
>  \
> +   ITER_VAR(VAR) != (LIST),  
>  \
> + ITER_NEXT_VAR(VAR) = ITER_VAR(VAR)->next);  
>  \
> + UPDATE_MULTIVAR_SAFE_SHORT(VAR))
> +
> +/* 

[ovs-dev] [PATCH 1/1] ovs-monitor-ipsec: Migration from ipsec.conf to swanctl.conf

2022-02-14 Thread Emeel Hakim via dev
As strongswan moved to the modern vici-based interface,this patch
modifies ovs-monitor-ipsec to use strongswan's vici-based
configuration instead of the legacy stroke-based configuration.

Signed-off-by: Emeel Hakim 
Reviewed-by: Nick Desaulniers  is interface name (as in OVSDB)
 and  is another dictionary.  This another dictionary
 uses strongSwan connection name as  and more detailed
 sample line from the parsed outpus as . """
 
 conns = {}
-proc = subprocess.Popen([self.IPSEC, 'status'], stdout=subprocess.PIPE)
+proc = subprocess.Popen([self.SWANCTL, '--list-conns'],
+   stdout=subprocess.PIPE)
 
 while True:
 line = proc.stdout.readline().strip().decode()
@@ -272,10 +401,8 @@ conn prevent_unencrypted_vxlan
 return conns
 
 def config_init(self):
-self.conf_file = open(self.IPSEC_CONF, "w")
-self.secrets_file = open(self.IPSEC_SECRETS, "w")
-self.conf_file.write(self.CONF_HEADER)
-self.secrets_file.write(FILE_HEADER)
+self.conf_file = open(self.SWANCTL_CONF, "w")
+self.conf_file.write(self.SWANCTL_CONF_HEADER)
 
 def config_global(self, monitor):
 """Configure the global state of IPsec tunnels."""
@@ -299,13 +426,10 @@ conn prevent_unencrypted_vxlan
 
 def config_tunnel(self, tunnel):
 if tunnel.conf["psk"]:
-self.secrets_file.write('%%any %s : PSK "%s"\n' %
-(tunnel.conf["remote_ip"], tunnel.conf["psk"]))
 auth_section = self.auth_tmpl["psk"].substitute(tunnel.conf)
+secrets = Template(self.SECRETS_SECTION).substitute(tunnel.conf)
 else:
-self.secrets_file.write("%%any %s : RSA %s\n" %
-(tunnel.conf["remote_ip"],
-tunnel.conf["private_key"]))
+secrets = None
 if tunnel.conf["remote_cert"]:
 tmpl = self.auth_tmpl["pki_remote"]
 auth_section = tmpl.substitute(tunnel.conf)
@@ -316,38 +440,43 @@ conn prevent_unencrypted_vxlan
 vals = tunnel.conf.copy()
 vals["auth_section"] = auth_section
 vals["version"] = tunnel.version
-conf_text = transp_tmpl[tunnel.conf["tunnel_type"]].substitute(vals)
+if tunnel.conf["address_family"] == "IPv6":
+vals["local_addrs"] = "::/0"
+vals["subnet"] = "64"
+else:
+vals["local_addrs"] = "0.0.0.0/0"
+vals["subnet"] = "32"
+if vals["local_ip"] == "%defaultroute":
+if tunnel.conf["address_family"] == "IPv6":
+vals["local_ip"] = "::/0"
+else:
+vals["local_ip"] = "0.0.0.0/0"
+conf_text = self.transp_tmpl[tunnel.conf[
+"tunnel_type"]].substitute(vals)
 self.conf_file.write(conf_text)
 
+if secrets is not None:
+self.conf_file.write(secrets)
+
 def config_fini(self):
-self.secrets_file.close()
 self.conf_file.close()
-self.secrets_file = None
 self.conf_file = None
 
 def refresh(self, monitor):
 """This functions refreshes strongSwan configuration.  Behind the
 scenes this function calls:
-1. once "ipsec update" command that tells strongSwan to load
+1. once "swanctl --load-all" command that tells strongSwan to load
all new tunnels from "ipsec.conf"; and
-2. once "ipsec rereadsecrets" command that tells strongswan to load
-   secrets from "ipsec.conf" file
-3. for every removed tunnel "ipsec stroke down-nb " command
+2. for every removed tunnel "swanctl -t --child " command
that removes old tunnels.
 Once strongSwan vici bindings will be distributed with major
 Linux distributions this function could be simplified."""
 vlog.info("Refreshing StrongSwan configuration")
-subprocess.call([self.IPSEC, "update"])
-subprocess.call([self.IPSEC, "rereadsecrets"])
-# "ipsec update" command does not remove those tunnels that were
-# updated or that disappeared from the ipsec.conf file.  So, we have
-# to manually remove them by calling "ipsec stroke down-nb "
+# "swanctl --load-all" command does not remove those tunnels that were
+# updated or that disappeared from the swanctl.conf files.  So, we have
+# to manually remove them by calling "swanctl -t --child  "
 # command.  We use  number to tell apart tunnels that
 # were just updated.
-# "ipsec down-nb" command is designed to be non-blocking (opposed
-# to "ipsec down" command).  This means that we should not be concerned
-# about possibility of ovs-monitor-ipsec to block for each tunnel
-# while strongSwan sends IKE messages over Internet.
 conns_dict 

Re: [ovs-dev] ovs/ipsec: Libreswan report connection failures to ovs logs

2022-02-14 Thread Mike Pattrick
On Thu, Feb 3, 2022 at 9:17 AM Mohammad Heib  wrote:
>
> Currently when the user adds an IPsec tunnel port to the
> ovs bridge the ovs-monitor-ipsec script will submit a request
> to start the IPsec connection for this port and ignores
> the request output which can contain an error message.
>
> This patch captures the request output and prints
> the error message to the ovs logs.
>
> Signed-off-by: Mohammad Heib 

This should make it easier to debug IPSec issues.

Acked-by: Mike Pattrick 

___
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev


Re: [ovs-dev] [PATCH v2] dpif-netdev-dpcls: Make subtable reprobe thread-safe.

2022-02-14 Thread Stokes, Ian
> The subtable search function can be used at any time by a PMD thread.
> Setting the subtable search function should be done atomically to
> prevent garbage data from being read.
> 
> A dpcls_subtable_lookup_reprobe() call can happen at the same time that
> DPCLS subtables are being sorted. This could lead to modifications done
> by the reprobe() to be lost. Prevent this from happening by locking on
> pmd->flow_mutex. After this change both the reprobe function and a
> subtable sort will share the flow_mutex preventing modifications by
> either one from being lost.
> 
> Also remove the pvector_publish() call. The pvector is not being changed
> in dpcls_subtable_lookup_reprobe(), only the data pointed to by pointers
> in the vector are being changed.

Hi Cian,

Thanks for the patch, in general this looks ok to me, but I realize Ilya had a 
few comments on the v1. I think these are addressed here but maybe Ilya would 
like to confirm before sign off?

@Ilya Maximets should this go into branch 2.17 as well before release?

Thanks
Ian

> 
> Fixes: 3d018c3ea79d ("dpif-netdev: add subtable lookup prio set command.")
> Reported-by: Ilya Maximets 
> Reported-at: https://mail.openvswitch.org/pipermail/ovs-dev/2022-
> January/390757.html
> Signed-off-by: Cian Ferriter 
> ---
>  lib/dpif-netdev-private-dpcls.h |  6 --
>  lib/dpif-netdev.c   | 20 
>  2 files changed, 20 insertions(+), 6 deletions(-)
> 
> diff --git a/lib/dpif-netdev-private-dpcls.h b/lib/dpif-netdev-private-dpcls.h
> index 7c4a840cb..0d5da73c7 100644
> --- a/lib/dpif-netdev-private-dpcls.h
> +++ b/lib/dpif-netdev-private-dpcls.h
> @@ -83,8 +83,10 @@ struct dpcls_subtable {
>  /* The lookup function to use for this subtable. If there is a known
>   * property of the subtable (eg: only 3 bits of miniflow metadata is
>   * used for the lookup) then this can point at an optimized version of
> - * the lookup function for this particular subtable. */
> -dpcls_subtable_lookup_func lookup_func;
> + * the lookup function for this particular subtable. The lookup function
> + * can be used at any time by a PMD thread, so it's declared as an atomic
> + * here to prevent garbage from being read. */
> +ATOMIC(dpcls_subtable_lookup_func) lookup_func;
> 
>  /* Caches the masks to match a packet to, reducing runtime calculations. 
> */
>  uint64_t *mf_masks;
> diff --git a/lib/dpif-netdev.c b/lib/dpif-netdev.c
> index e28e0b554..71f608a7c 100644
> --- a/lib/dpif-netdev.c
> +++ b/lib/dpif-netdev.c
> @@ -1074,7 +1074,9 @@ dpif_netdev_subtable_lookup_set(struct unixctl_conn
> *conn, int argc OVS_UNUSED,
>  if (!cls) {
>  continue;
>  }
> +ovs_mutex_lock(>flow_mutex);
>  uint32_t subtbl_changes = dpcls_subtable_lookup_reprobe(cls);
> +ovs_mutex_unlock(>flow_mutex);
>  if (subtbl_changes) {
>  lookup_dpcls_changed++;
>  lookup_subtable_changed += subtbl_changes;
> @@ -9736,9 +9738,12 @@ dpcls_create_subtable(struct dpcls *cls, const struct
> netdev_flow_key *mask)
> 
>  /* Get the preferred subtable search function for this (u0,u1) subtable.
>   * The function is guaranteed to always return a valid implementation, 
> and
> - * possibly an ISA optimized, and/or specialized implementation.
> + * possibly an ISA optimized, and/or specialized implementation. 
> Initialize
> + * the subtable search function atomically to avoid garbage data being 
> read
> + * by the PMD thread.
>   */
> -subtable->lookup_func = dpcls_subtable_get_best_impl(unit0, unit1);
> +atomic_init(>lookup_func,
> +dpcls_subtable_get_best_impl(unit0, unit1));
> 
>  cmap_insert(>subtables_map, >cmap_node, mask->hash);
>  /* Add the new subtable at the end of the pvector (with no hits yet) */
> @@ -9767,6 +9772,10 @@ dpcls_find_subtable(struct dpcls *cls, const struct
> netdev_flow_key *mask)
>  /* Checks for the best available implementation for each subtable lookup
>   * function, and assigns it as the lookup function pointer for each subtable.
>   * Returns the number of subtables that have changed lookup implementation.
> + * This function requires holding a flow_mutex when called. This is to make
> + * sure modifications done by this function are not overwritten. This could
> + * happen if dpcls_sort_subtable_vector() is called at the same time as this
> + * function.
>   */
>  static uint32_t
>  dpcls_subtable_lookup_reprobe(struct dpcls *cls)
> @@ -9779,10 +9788,13 @@ dpcls_subtable_lookup_reprobe(struct dpcls *cls)
>  uint32_t u0_bits = subtable->mf_bits_set_unit0;
>  uint32_t u1_bits = subtable->mf_bits_set_unit1;
>  void *old_func = subtable->lookup_func;
> -subtable->lookup_func = dpcls_subtable_get_best_impl(u0_bits, 
> u1_bits);
> +
> +/* Set the subtable lookup 

Re: [ovs-dev] [PATCH ovn v4] acl-log: Log the direction (logical pipeline) of the matching ACL.

2022-02-14 Thread 0-day Robot
Bleep bloop.  Greetings Dumitru Ceara, 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: Failed to merge in the changes.
hint: Use 'git am --show-current-patch' to see the failed patch
Patch failed at 0001 acl-log: Log the direction (logical pipeline) of the 
matching ACL.
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


Re: [ovs-dev] [PATCH ovn v3] acl-log: Log the direction (logical pipeline) of the matching ACL.

2022-02-14 Thread Dumitru Ceara
On 2/11/22 19:31, Numan Siddique wrote:
> On Fri, Feb 11, 2022 at 9:42 AM Dumitru Ceara  wrote:
>> It's useful to differentiate between ingress and egress pipelines in the
>> ACL logs.  To achieve this we determine the direction by interpreting the
>> openflow table ID when processing packets punted to pinctrl by "log()"
>> action.
>>
>> Reported-at: https://bugzilla.redhat.com/show_bug.cgi?id=1992641
>> Signed-off-by: Dumitru Ceara 
>> ---
>> v3: Simplify the patch as suggested by Numan; detect pipeline based on
>> openflow table id.
>> v2: Add the "direction" after the "verdict" and "severity" fields in the
>> ACL logs.
>> ---
> Thanks for v3.
> 
> I've one minor comment.  I somehow feel using "from-lport" and
> "to-lport" instead of "IN" and "OUT"
> would be more appropriate.  But I'm fine with the present patch too.
> 
> Acked-by: Numan Siddique 
> 

Thanks, I sent a v4 including your ack and the suggested change.

Regards,
Dumitru

___
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev


[ovs-dev] [PATCH ovn v4] acl-log: Log the direction (logical pipeline) of the matching ACL.

2022-02-14 Thread Dumitru Ceara
It's useful to differentiate between ingress and egress pipelines in the
ACL logs.  To achieve this we determine the direction by interpreting the
openflow table ID when processing packets punted to pinctrl by "log()"
action.

Reported-at: https://bugzilla.redhat.com/show_bug.cgi?id=1992641
Acked-by: Numan Siddique 
Signed-off-by: Dumitru Ceara 
---
v4:
- Log direction as from-lport/to-lport.
- Add Numan's ack.
v3: Simplify the patch as suggested by Numan; detect pipeline based on
openflow table id.
v2: Add the "direction" after the "verdict" and "severity" fields in the
ACL logs.
---
 NEWS  |  2 ++
 controller/pinctrl.c  |  4 ++-
 lib/acl-log.c |  8 +++--
 lib/acl-log.h |  3 +-
 tests/ovn.at  | 68 ++-
 utilities/ovn-trace.c |  9 --
 6 files changed, 73 insertions(+), 21 deletions(-)

diff --git a/NEWS b/NEWS
index 194557410b..a01820dfe6 100644
--- a/NEWS
+++ b/NEWS
@@ -1,5 +1,7 @@
 Post v21.12.0
 -
+  - When configured to log packtes matching ACLs, log the direction (logical
+pipeline) too.
 
 OVN v21.12.0 - 22 Dec 2021
 --
diff --git a/controller/pinctrl.c b/controller/pinctrl.c
index fd0bccdb6c..a0656b69e8 100644
--- a/controller/pinctrl.c
+++ b/controller/pinctrl.c
@@ -3166,7 +3166,9 @@ process_packet_in(struct rconn *swconn, const struct 
ofp_header *msg)
 break;
 
 case ACTION_OPCODE_LOG:
-handle_acl_log(, );
+handle_acl_log(, ,
+   pin.table_id < OFTABLE_LOG_EGRESS_PIPELINE
+   ? "from-lport" : "to-lport");
 break;
 
 case ACTION_OPCODE_PUT_ND_RA_OPTS:
diff --git a/lib/acl-log.c b/lib/acl-log.c
index 220b6dc30e..9530dd7635 100644
--- a/lib/acl-log.c
+++ b/lib/acl-log.c
@@ -76,7 +76,8 @@ log_severity_from_string(const char *name)
 }
 
 void
-handle_acl_log(const struct flow *headers, struct ofpbuf *userdata)
+handle_acl_log(const struct flow *headers, struct ofpbuf *userdata,
+   const char *direction)
 {
 if (!VLOG_IS_INFO_ENABLED()) {
 return;
@@ -94,9 +95,10 @@ handle_acl_log(const struct flow *headers, struct ofpbuf 
*userdata)
 struct ds ds = DS_EMPTY_INITIALIZER;
 ds_put_cstr(, "name=");
 json_string_escape(name_len ? name : "", );
-ds_put_format(, ", verdict=%s, severity=%s: ",
+ds_put_format(, ", verdict=%s, severity=%s, direction=%s: ",
   log_verdict_to_string(lph->verdict),
-  log_severity_to_string(lph->severity));
+  log_severity_to_string(lph->severity),
+  direction);
 flow_format(, headers, NULL);
 
 VLOG_INFO("%s", ds_cstr());
diff --git a/lib/acl-log.h b/lib/acl-log.h
index 4f23f790dd..da7fa2f02c 100644
--- a/lib/acl-log.h
+++ b/lib/acl-log.h
@@ -49,6 +49,7 @@ const char *log_verdict_to_string(uint8_t verdict);
 const char *log_severity_to_string(uint8_t severity);
 uint8_t log_severity_from_string(const char *name);
 
-void handle_acl_log(const struct flow *headers, struct ofpbuf *userdata);
+void handle_acl_log(const struct flow *headers, struct ofpbuf *userdata,
+const char *direction);
 
 #endif /* lib/acl-log.h */
diff --git a/tests/ovn.at b/tests/ovn.at
index 957eb7850f..25e59da562 100644
--- a/tests/ovn.at
+++ b/tests/ovn.at
@@ -8965,33 +8965,59 @@ ovn-nbctl lsp-set-addresses lp2 $lp2_mac
 ovn-nbctl --wait=sb sync
 wait_for_ports_up
 
-ovn-nbctl acl-add lsw0 to-lport 1000 'tcp.dst==80' drop
-ovn-nbctl --log --severity=alert --name=drop-flow acl-add lsw0 to-lport 1000 
'tcp.dst==81' drop
+ovn-nbctl acl-add lsw0 from-lport 1000 'tcp.dst==80' drop
+ovn-nbctl --log --severity=alert --name=drop-flow acl-add lsw0 from-lport 1000 
'tcp.dst==81' drop
+
+ovn-nbctl acl-add lsw0 to-lport 1000 'tcp.dst==180' drop
+ovn-nbctl --log --severity=alert --name=drop-flow acl-add lsw0 to-lport 1000 
'tcp.dst==181' drop
+
+ovn-nbctl acl-add lsw0 from-lport 1000 'tcp.dst==82' allow
+ovn-nbctl --log --severity=info --name=allow-flow acl-add lsw0 from-lport 1000 
'tcp.dst==83' allow
 
 ovn-nbctl acl-add lsw0 to-lport 1000 'tcp.dst==82' allow
 ovn-nbctl --log --severity=info --name=allow-flow acl-add lsw0 to-lport 1000 
'tcp.dst==83' allow
 
+ovn-nbctl acl-add lsw0 from-lport 1000 'tcp.dst==84' allow-related
+ovn-nbctl --log acl-add lsw0 from-lport 1000 'tcp.dst==85' allow-related
+
 ovn-nbctl acl-add lsw0 to-lport 1000 'tcp.dst==84' allow-related
 ovn-nbctl --log acl-add lsw0 to-lport 1000 'tcp.dst==85' allow-related
 
-ovn-nbctl acl-add lsw0 to-lport 1000 'tcp.dst==86' reject
-ovn-nbctl --wait=hv --log --severity=alert --name=reject-flow acl-add lsw0 
to-lport 1000 'tcp.dst==87' reject
+ovn-nbctl acl-add lsw0 from-lport 1000 'tcp.dst==86' reject
+ovn-nbctl --log --severity=alert --name=reject-flow acl-add lsw0 from-lport 
1000 'tcp.dst==87' reject
+
+ovn-nbctl acl-add lsw0 to-lport 1000 'tcp.dst==186' reject
+ovn-nbctl --log --severity=alert --name=reject-flow 

Re: [ovs-dev] [PATCH 1/1] ovs-monitor-ipsec: Migration from ipsec.conf to swanctl.conf

2022-02-14 Thread Mohammad Heib

Hi Emeel,

Thank you for submitting this patch.

please see few comments below


On 2/14/22 16:21, Emeel Hakim wrote:

As strongswan moved to the modern vici-based interface,this patch
modifies ovs-monitor-ipsec to use strongswan's vici-based
configuration instead of the legacy stroke-based configuration.

Signed-off-by: Emeel Hakim
Reviewed-by: Nick Desaulniers   
  
  FILE_HEADER = "# Generated by ovs-monitor-ipsec...do not modify by hand!\n\n"

-transp_tmpl = {"gre": Template("""\
-conn $ifname-$version
-$auth_section
-leftprotoport=gre
-rightprotoport=gre
-
-"""), "gre64": Template("""\
-conn $ifname-$version
-$auth_section
-leftprotoport=gre
-rightprotoport=gre
-
-"""), "geneve": Template("""\
-conn $ifname-in-$version
-$auth_section
-leftprotoport=udp/6081
-rightprotoport=udp
-
-conn $ifname-out-$version
-$auth_section
-leftprotoport=udp
-rightprotoport=udp/6081
-
-"""), "stt": Template("""\
-conn $ifname-in-$version
-$auth_section
-leftprotoport=tcp/7471
-rightprotoport=tcp
-
-conn $ifname-out-$version
-$auth_section
-leftprotoport=tcp
-rightprotoport=tcp/7471
-
-"""), "vxlan": Template("""\
-conn $ifname-in-$version
-$auth_section
-leftprotoport=udp/4789
-rightprotoport=udp
-
-conn $ifname-out-$version
-$auth_section
-leftprotoport=udp
-rightprotoport=udp/4789
-
-""")}
  vlog = ovs.vlog.Vlog("ovs-monitor-ipsec")
  exiting = False
  monitor = None
@@ -160,72 +114,249 @@ charon {
  }
  """ % (FILE_HEADER)
  
-CONF_HEADER = """%s

-config setup
-uniqueids=yes
+SWANCTL_CONF_HEADER = """%s
+conn-defaults {
+  unique = replace
+  reauth_time = 0
+  version = 2
+  proposals = aes128-sha256-x25519
+}
  
-conn %%default

-keyingtries=%%forever
-type=transport
-keyexchange=ikev2
-auto=route
-ike=aes256gcm16-sha256-modp2048
-esp=aes256gcm16-modp2048
+child-defaults {
+  esp_proposals = aes256gcm16-modp2048-esn
+  mode = transport
+  policies_fwd_out = yes
+  start_action = start
+}
  
  """ % (FILE_HEADER)
  
-CA_SECTION = """ca ca_auth

-cacert=%s
+CA_SECTION = """authorities {
+ca_auth {
+cacert=%s
+}
+}
  
  """
  
-SHUNT_POLICY = """conn prevent_unencrypted_gre

-type=drop
-leftprotoport=gre
-mark={0}
+SHUNT_POLICY = """connections {{
+   shunts {{
+  children {{
+ prevent_unencrypted_gre {{
+local_ts = 0.0.0.0/0 [gre]
+mark_in = {0}
+mark_out = {0}
+mode = drop
+start_action = trap
+ }}
+ prevent_unencrypted_gre_ipv6 {{
+local_ts = ::/0 [gre]
+mark_in = {0}
+mark_out = {0}
+mode = drop
+start_action = trap
+ }}
+ prevent_unencrypted_geneve {{
+local_ts = 0.0.0.0/0 [udp/6081]
+mark_in = {0}
+mark_out = {0}
+mode = drop
+start_action = trap
+ }}
+ prevent_unencrypted_geneve_ipv6 {{
+local_ts = ::/0 [udp/6081]
+mark_in = {0}
+mark_out = {0}
+mode = drop
+start_action = trap
+ }}
+ prevent_unencrypted_stt {{
+local_ts = 0.0.0.0/0 [tcp/7471]
+mark_in = {0}
+mark_out = {0}
+mode = drop
+start_action = trap
+ }}
+ prevent_unencrypted_stt_ipv6 {{
+local_ts = ::/0 [tcp/7471]
+mark_in = {0}
+mark_out = {0}
+mode = drop
+start_action = trap
+ }}
+ prevent_unencrypted_vxlan {{
+local_ts = 0.0.0.0/0 [udp/4789]
+mark_in = {0}
+mark_out = {0}
+mode = drop
+start_action = trap
+ }}
+ prevent_unencrypted_vxlan_ipv6 {{
+local_ts = ::/0 [udp/4789]
+mark_in = {0}
+mark_out = {0}
+mode = drop
+start_action = trap
+ }}
+  }}
+   }}
+}}
+"""
+auth_tmpl = {"psk": Template("""\
+local {
+auth = psk
+id = $local_ip
+ }
+ remote {
+auth = psk
+id = $remote_ip
+ }"""),
+ "pki_remote": Template("""\
+local {
+auth = pubkey
+id = $local_name
+certs = $certificate
+}
+remote {
+   auth = pubkey
+   id = $remote_name
+   certs = $remote_cert
+}"""),
+ "pki_ca": Template("""\
+local {
+auth = pubkey
+id = $local_name
+certs = $certificate
+}
+remote {
+  auth = pubkey
+  id = $remote_name
+}""")}
+
+SECRETS_SECTION = """secrets {
+ike-$ifname {
+id = $local_ip
+secret = $psk
+}
+}
  
-conn prevent_unencrypted_geneve

-type=drop
-

Re: [ovs-dev] [PATCH ovn v9 4/6] northd, utils: support for RouteTables in LRs

2022-02-14 Thread Dumitru Ceara
Hi Vladislav,

I was looking at what options we have in OVN to implement a VRF-like
behavior and then remembered you had worked on the multiple routing
table feature.

On 11/19/21 17:07, Vladislav Odintsov wrote:
> This patch extends Logical Router's routing functionality.
> Now user may create multiple routing tables within a Logical Router
> and assign them to Logical Router Ports.
> 
> Traffic coming from Logical Router Port with assigned route_table
> is checked against Logical_Router_Static_Routes with same route_table
> field value and routes to connected networks. If no route_table option
> is set to the LRP, routes' lookup is done agains routes with no
> route_table field value ("", empty string) and against routes to
> connected networks.

I was a bit surprised by the fact that if there's no static route with
the same route_table value as the ingress router port we go ahead and
match against all connected networks, regardless of their ports' route
tables.

Does it make sense to change this and perform longest prefix match in
general, always matching on route_table?

In this case connected routes could inherit the route_table value from
the corresponding router ports where they're defined.

Would that break your use case?

Thanks,
Dumitru

___
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev


[ovs-dev] [PATCH net v2 1/1] openvswitch: Fix setting ipv6 fields causing hw csum failure

2022-02-14 Thread Paul Blakey via dev
Ipv6 ttl, label and tos fields are modified without first
pulling/pushing the ipv6 header, which would have updated
the hw csum (if available). This might cause csum validation
when sending the packet to the stack, as can be seen in
the trace below.

Fix this by updating skb->csum if available.

Trace resulted by ipv6 ttl dec and then sending packet
to conntrack [actions: set(ipv6(hlimit=63)),ct(zone=99)]:
[295241.900063] s_pf0vf2: hw csum failure
[295241.923191] Call Trace:
[295241.925728]  
[295241.927836]  dump_stack+0x5c/0x80
[295241.931240]  __skb_checksum_complete+0xac/0xc0
[295241.935778]  nf_conntrack_tcp_packet+0x398/0xba0 [nf_conntrack]
[295241.953030]  nf_conntrack_in+0x498/0x5e0 [nf_conntrack]
[295241.958344]  __ovs_ct_lookup+0xac/0x860 [openvswitch]
[295241.968532]  ovs_ct_execute+0x4a7/0x7c0 [openvswitch]
[295241.979167]  do_execute_actions+0x54a/0xaa0 [openvswitch]
[295242.001482]  ovs_execute_actions+0x48/0x100 [openvswitch]
[295242.006966]  ovs_dp_process_packet+0x96/0x1d0 [openvswitch]
[295242.012626]  ovs_vport_receive+0x6c/0xc0 [openvswitch]
[295242.028763]  netdev_frame_hook+0xc0/0x180 [openvswitch]
[295242.034074]  __netif_receive_skb_core+0x2ca/0xcb0
[295242.047498]  netif_receive_skb_internal+0x3e/0xc0
[295242.052291]  napi_gro_receive+0xba/0xe0
[295242.056231]  mlx5e_handle_rx_cqe_mpwrq_rep+0x12b/0x250 [mlx5_core]
[295242.062513]  mlx5e_poll_rx_cq+0xa0f/0xa30 [mlx5_core]
[295242.067669]  mlx5e_napi_poll+0xe1/0x6b0 [mlx5_core]
[295242.077958]  net_rx_action+0x149/0x3b0
[295242.086762]  __do_softirq+0xd7/0x2d6
[295242.090427]  irq_exit+0xf7/0x100
[295242.093748]  do_IRQ+0x7f/0xd0
[295242.096806]  common_interrupt+0xf/0xf
[295242.100559]  
[295242.102750] RIP: 0033:0x7f9022e88cbd
[295242.125246] RSP: 002b:7f9022282b20 EFLAGS: 0246 ORIG_RAX: 
ffda
[295242.132900] RAX: 0005 RBX: 0010 RCX: 

[295242.140120] RDX: 7f9022282ba8 RSI: 7f9022282a30 RDI: 
7f9014005c30
[295242.147337] RBP: 7f9014014d60 R08: 0020 R09: 
7f90254a8340
[295242.154557] R10: 7f9022282a28 R11: 0246 R12: 

[295242.161775] R13: 7f902308c000 R14: 002b R15: 
7f9022b71f40

Fixes: 3fdbd1ce11e5 ("openvswitch: add ipv6 'set' action")
Signed-off-by: Paul Blakey 
---
 Changelog:
v1->v2:
  Replaced push pull rcsum checksum calc with actual checksum calc
 
 net/openvswitch/actions.c | 47 ---
 1 file changed, 39 insertions(+), 8 deletions(-)

diff --git a/net/openvswitch/actions.c b/net/openvswitch/actions.c
index 076774034bb9..3725801cb040 100644
--- a/net/openvswitch/actions.c
+++ b/net/openvswitch/actions.c
@@ -423,12 +423,44 @@ static void set_ipv6_addr(struct sk_buff *skb, u8 
l4_proto,
memcpy(addr, new_addr, sizeof(__be32[4]));
 }
 
-static void set_ipv6_fl(struct ipv6hdr *nh, u32 fl, u32 mask)
+static void set_ipv6_dsfield(struct sk_buff *skb, struct ipv6hdr *nh, __u8 
ipv6_tclass, __u8 mask)
 {
+   __u8 old_ipv6_tclass = ipv6_get_dsfield(nh);
+
+   ipv6_tclass = OVS_MASKED(old_ipv6_tclass, ipv6_tclass, mask);
+
+   if (skb->ip_summed == CHECKSUM_COMPLETE)
+   skb->csum = ~csum_block_add(csum_block_sub(~skb->csum, 
ipv6_tclass << 4, 1),
+   old_ipv6_tclass << 4, 1);
+
+   ipv6_change_dsfield(nh, ~mask, ipv6_tclass);
+}
+
+static void set_ipv6_fl(struct sk_buff *skb, struct ipv6hdr *nh, u32 fl, u32 
mask)
+{
+   u32 old_fl;
+
+   old_fl = nh->flow_lbl[0] << 16 |  nh->flow_lbl[1] << 8 |  
nh->flow_lbl[2];
+   fl = OVS_MASKED(old_fl, fl, mask);
+
/* Bits 21-24 are always unmasked, so this retains their values. */
-   OVS_SET_MASKED(nh->flow_lbl[0], (u8)(fl >> 16), (u8)(mask >> 16));
-   OVS_SET_MASKED(nh->flow_lbl[1], (u8)(fl >> 8), (u8)(mask >> 8));
-   OVS_SET_MASKED(nh->flow_lbl[2], (u8)fl, (u8)mask);
+   nh->flow_lbl[0] = (u8)(fl >> 16);
+   nh->flow_lbl[1] = (u8)(fl >> 8);
+   nh->flow_lbl[2] = (u8)fl;
+
+   if (skb->ip_summed == CHECKSUM_COMPLETE)
+   skb->csum = ~csum_block_add(csum_block_sub(~skb->csum, 
htonl(fl), 0),
+   htonl(old_fl), 0);
+}
+
+static void set_ipv6_ttl(struct sk_buff *skb, struct ipv6hdr *nh, u8 new_ttl, 
u8 mask)
+{
+   new_ttl = OVS_MASKED(nh->hop_limit, new_ttl, mask);
+
+   if (skb->ip_summed == CHECKSUM_COMPLETE)
+   skb->csum = ~csum_block_add(csum_block_sub(~skb->csum, new_ttl, 
1),
+   nh->hop_limit, 1);
+   nh->hop_limit = new_ttl;
 }
 
 static void set_ip_ttl(struct sk_buff *skb, struct iphdr *nh, u8 new_ttl,
@@ -546,18 +578,17 @@ static int set_ipv6(struct sk_buff *skb, struct 
sw_flow_key *flow_key,
}
}
if (mask->ipv6_tclass) {
-   ipv6_change_dsfield(nh, ~mask->ipv6_tclass, key->ipv6_tclass);
+   

Re: [ovs-dev] [PATCH] ofproto: fix use-after-free for "ofproto".

2022-02-14 Thread Adrian Moreno



On 1/18/22 14:28, wangyunjian via dev wrote:

http://patchwork.ozlabs.org/project/openvswitch/patch/20200306130555.19884-1-guohongz...@huawei.com/
This patch has been applied. But this patch do not fix the problem I stated.
I think this problem is that hmap does not support concurrent access.

Thanks,
Yunjian

From: 贺鹏 [mailto:xnhp0...@gmail.com]
Sent: Tuesday, January 18, 2022 3:23 PM
To: wangyunjian 
Cc: d...@openvswitch.org; i.maxim...@ovn.org; dingxiaoxiong 

Subject: Re: [ovs-dev] [PATCH] ofproto: fix use-after-free for "ofproto".

Hi, yunjian and Ilya,

this patch reminds me of the discussion we have in March last year, and during 
the discussion, you have spotted this
thread-safety issue of uuid map. Unfortunately, in that email, you did not 
reply to the mailist, so I cannot give a link to
the email. I attach it as a reference.

I quote it here:

"
That is an interesting example here...
I can't help but notice that this function is typically called
from different handler or pmd threads and modified by the main thread
while upcalls enabled.  And hmap is not a thread-safe structure.
I guess, we have another possible problem here.  We need to protect
at least this hmap and the other one with rw lock or something...
Am I right or am I missing something?  What else we need to protect?
"

And this patch fixes exactly the problem you stated.



wangyunjian via dev mailto:ovs-dev@openvswitch.org>> 
于2022年1月8日周六 17:18写道:
Friendly ping.


-Original Message-
From: wangyunjian
Sent: Friday, December 3, 2021 7:25 PM
To: d...@openvswitch.org; 
i.maxim...@ovn.org
Cc: dingxiaoxiong mailto:dingxiaoxi...@huawei.com>>; 
xudingke
mailto:xudin...@huawei.com>>; wangyunjian 
mailto:wangyunj...@huawei.com>>; Justin
Pettit mailto:jpet...@ovn.org>>
Subject: [ovs-dev] [PATCH] ofproto: fix use-after-free for "ofproto".

When handler threads lookup a "ofproto" and use it, main thread maybe
remove and free the "ofproto" at the same time. The "ofproto" has not
been protected well, which can lead to an OVS crash.

This patch fixes this by making the "ofproto" lookup RCU-safe by using
cmap instead of hmap and moving remove "ofproto" call before
xlate_txn_commit().

(gdb) bt
   hmap_next (hmap.h:398)
   seq_wake_waiters (seq.c:326)
   seq_change_protected (seq.c:134)
   seq_change (seq.c:144)
   ofproto_dpif_send_async_msg (ofproto_dpif.c:263)
   process_upcall (ofproto_dpif_upcall.c:1782)
   recv_upcalls (ofproto_dpif_upcall.c:1026)
   udpif_upcall_handler (ofproto/ofproto_dpif_upcall.c:945)
   ovsthread_wrapper (ovs_thread.c:734)

Cc: Justin Pettit mailto:jpet...@ovn.org>>
Fixes: fcb9579be3c7 ("ofproto: Add 'ofproto_uuid' and 'ofp_in_port' to user
action cookie.")
Signed-off-by: Yunjian Wang 
mailto:wangyunj...@huawei.com>>
---
  ofproto/ofproto-dpif.c | 12 ++--
  ofproto/ofproto-dpif.h |  2 +-
  2 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c
index cba49a99e..aa8d32f81 100644
--- a/ofproto/ofproto-dpif.c
+++ b/ofproto/ofproto-dpif.c
@@ -216,8 +216,7 @@ static struct hmap all_ofproto_dpifs_by_name =

HMAP_INITIALIZER(_ofproto_dpifs_by_name);

  /* All existing ofproto_dpif instances, indexed by ->uuid. */
-static struct hmap all_ofproto_dpifs_by_uuid =
-
HMAP_INITIALIZER(_ofproto_dpifs_by_uuid);
+static struct cmap all_ofproto_dpifs_by_uuid = CMAP_INITIALIZER;

  static bool ofproto_use_tnl_push_pop = true;
  static void ofproto_unixctl_init(void);
@@ -1682,7 +1681,7 @@ construct(struct ofproto *ofproto_)
  hmap_insert(_ofproto_dpifs_by_name,
  >all_ofproto_dpifs_by_name_node,
  hash_string(ofproto->up.name, 0));
-hmap_insert(_ofproto_dpifs_by_uuid,
+cmap_insert(_ofproto_dpifs_by_uuid,
  >all_ofproto_dpifs_by_uuid_node,
  uuid_hash(>uuid));
  memset(>stats, 0, sizeof ofproto->stats);
@@ -1778,12 +1777,13 @@ destruct(struct ofproto *ofproto_, bool del)
  ofproto->backer->need_revalidate = REV_RECONFIGURE;
  xlate_txn_start();
  xlate_remove_ofproto(ofproto);
+cmap_remove(_ofproto_dpifs_by_uuid,
+>all_ofproto_dpifs_by_uuid_node,
+uuid_hash(>uuid));


I guess some comments are needed here, you actually make use of
the rcu_synchronize in the xlate_txn_commit to avoid access to the
ofproto from other thread through uuid map.


Relying on the synchronization mechanism of another data structure (in this 
case, the struct xlate_cfg) is a bit strange. For any change that we do on 
xlate_cfg's synchronization now we have to consider that it can affect 
all_ofproto_dpifs_by_uuid_node.


Have you considered adding "all_ofproto_dpifs_by_uuid_node" to "struct 
xlate_cfg"?




  xlate_txn_commit();

  hmap_remove(_ofproto_dpifs_by_name,
  >all_ofproto_dpifs_by_name_node);
-hmap_remove(_ofproto_dpifs_by_uuid,
-

Re: [ovs-dev] [PATCH v3 2/2] ofproto-dpif: avoid unneccesary backer revalidation

2022-02-14 Thread lic121
>On 6 Feb 2022, at 4:58, lic121 wrote:
>
>>> If lldp didn't change, we are not supposed to trigger backer
>>> revalidation.
>>>
>>> Without this patch, bridge_reconfigure() always trigger udpif
>>> revalidator because of lldp.
>>>
>>> Signed-off-by: lic121 
>>> Co-authored-by: Eelco Chaudron 
>>> ---
>>> lib/ovs-lldp.c |  8 
>>> lib/ovs-lldp.h |  1 +
>>> ofproto/ofproto-dpif.c |  5 -
>>> tests/ofproto-dpif.at  | 33 +
>>> 4 files changed, 46 insertions(+), 1 deletion(-)
>>>
>>> diff --git a/lib/ovs-lldp.c b/lib/ovs-lldp.c
>>> index 162311f..bfc69a3 100644
>>> --- a/lib/ovs-lldp.c
>>> +++ b/lib/ovs-lldp.c
>>> @@ -738,6 +738,14 @@ lldp_put_packet(struct lldp *lldp, struct dp_packet 
>>> *packet,
>>> ovs_mutex_unlock();
>>> }
>>>
>>> +/* Is LLDP enabled?
>>> + */
>>> +bool
>>> +lldp_is_enabled(struct lldp *lldp)
>>> +{
>>> +return lldp ? lldp->enabled : false;
>>> +}
>>> +
>>> /* Configures the LLDP stack.
>>>  */
>>> bool
>>> diff --git a/lib/ovs-lldp.h b/lib/ovs-lldp.h
>>> index 0e536e8..661ac4e 100644
>>> --- a/lib/ovs-lldp.h
>>> +++ b/lib/ovs-lldp.h
>>> @@ -86,6 +86,7 @@ void lldp_run(struct lldpd *cfg);
>>> bool lldp_should_send_packet(struct lldp *cfg);
>>> bool lldp_should_process_flow(struct lldp *lldp, const struct flow *flow);
>>> bool lldp_configure(struct lldp *lldp, const struct smap *cfg);
>>> +bool lldp_is_enabled(struct lldp *lldp);
>>> void lldp_process_packet(struct lldp *cfg, const struct dp_packet *);
>>> void lldp_put_packet(struct lldp *lldp, struct dp_packet *packet,
>>>  const struct eth_addr eth_src);
>>> diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c
>>> index ced67b0..c2f5b12 100644
>>> --- a/ofproto/ofproto-dpif.c
>>> +++ b/ofproto/ofproto-dpif.c
>>> @@ -2499,11 +2499,11 @@ set_lldp(struct ofport *ofport_,
>>> {
>>> struct ofport_dpif *ofport = ofport_dpif_cast(ofport_);
>>> struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofport->up.ofproto);
>>> +bool old_enable = lldp_is_enabled(ofport->lldp);
>>> int error = 0;
>>>
>>> if (cfg) {
>>> if (!ofport->lldp) {
>>> -ofproto->backer->need_revalidate = REV_RECONFIGURE;
>>> ofport->lldp = lldp_create(ofport->up.netdev, ofport_->mtu, 
>>> cfg);
>>> }
>>>
>>> @@ -2515,6 +2515,9 @@ set_lldp(struct ofport *ofport_,
>>> } else if (ofport->lldp) {
>>> lldp_unref(ofport->lldp);
>>> ofport->lldp = NULL;
>>> +}
>>> +
>>> +if (lldp_is_enabled(ofport->lldp) != old_enable) {
>>> ofproto->backer->need_revalidate = REV_RECONFIGURE;
>>> }
>>>
>>> diff --git a/tests/ofproto-dpif.at b/tests/ofproto-dpif.at
>>> index 7f273e5..edb6aa1 100644
>>> --- a/tests/ofproto-dpif.at
>>> +++ b/tests/ofproto-dpif.at
>>> @@ -29,6 +29,39 @@ AT_CHECK([ovs-appctl revalidator/wait])
>>> OVS_VSWITCHD_STOP
>>> AT_CLEANUP
>>>
>>> +AT_SETUP([ofproto-dpif - lldp revalidator event(REV_RECONFIGURE)])
>>> +OVS_VSWITCHD_START(
>>> +[add-port br0 p1 -- set interface p1 ofport_request=1 type=dummy]
>>> +)
>>> +dnl first revalidation triggered by add interface
>>> +AT_CHECK([ovs-appctl coverage/read-counter rev_reconfigure], [0], [dnl
>>> +1
>>> +])
>>> +
>>> +dnl enable lldp
>>> +AT_CHECK([ovs-vsctl set interface p1 lldp:enable=true])
>>
>> CI test shows that setting lldp cause memory leaks, will try to find out the 
>> places.
>
>
>Ack, I’ll wait for reviewing once you found/fix it.

v4 is uploaded

>
>PS: You can add me as a co-author and sign off in your next iteration for the 
>changes I made.
>

Sure, please let me know if I haven't done it in the right way.

>>> +AT_CHECK([ovs-appctl revalidator/wait])
>>> +AT_CHECK([ovs-appctl coverage/read-counter rev_reconfigure], [0], [dnl
>>> +2
>>> +])
>>> +
>>> +dnl disable lldp
>>> +AT_CHECK([ovs-vsctl set interface p1 lldp:enable=false])
>>> +AT_CHECK([ovs-appctl revalidator/wait])
>>> +AT_CHECK([ovs-appctl coverage/read-counter rev_reconfigure], [0], [dnl
>>> +3
>>> +])
>>> +
>>> +dnl remove lldp, no revalidation as lldp was disabled
>>> +AT_CHECK([ovs-vsctl remove interface p1 lldp enable])
>>> +AT_CHECK([ovs-appctl revalidator/wait])
>>> +AT_CHECK([ovs-appctl coverage/read-counter rev_reconfigure], [0], [dnl
>>> +3
>>> +])
>>> +
>>> +OVS_VSWITCHD_STOP
>>> +AT_CLEANUP
>>> +
>>> AT_SETUP([ofproto-dpif - active-backup bonding (with primary)])
>>>
>>> dnl Create br0 with members p1, p2 and p7, creating bond0 with p1 and
>>> --
>>> 1.8.3.1
>>>
>
>

___
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev


[ovs-dev] [PATCH v4 3/3] ofproto-dpif: avoid unneccesary backer revalidation

2022-02-14 Thread lic121
If lldp didn't change, we are not supposed to trigger backer
revalidation.

Without this patch, bridge_reconfigure() always trigger udpif
revalidator because of lldp.

Signed-off-by: lic121 
Signed-off-by: Eelco Chaudron 
Co-authored-by: Eelco Chaudron 
---
 lib/ovs-lldp.c |  8 
 lib/ovs-lldp.h |  1 +
 ofproto/ofproto-dpif.c |  7 +--
 tests/ofproto-dpif.at  | 33 +
 4 files changed, 47 insertions(+), 2 deletions(-)

diff --git a/lib/ovs-lldp.c b/lib/ovs-lldp.c
index 162311f..bfc69a3 100644
--- a/lib/ovs-lldp.c
+++ b/lib/ovs-lldp.c
@@ -738,6 +738,14 @@ lldp_put_packet(struct lldp *lldp, struct dp_packet 
*packet,
 ovs_mutex_unlock();
 }

+/* Is LLDP enabled?
+ */
+bool
+lldp_is_enabled(struct lldp *lldp)
+{
+return lldp ? lldp->enabled : false;
+}
+
 /* Configures the LLDP stack.
  */
 bool
diff --git a/lib/ovs-lldp.h b/lib/ovs-lldp.h
index 0e536e8..661ac4e 100644
--- a/lib/ovs-lldp.h
+++ b/lib/ovs-lldp.h
@@ -86,6 +86,7 @@ void lldp_run(struct lldpd *cfg);
 bool lldp_should_send_packet(struct lldp *cfg);
 bool lldp_should_process_flow(struct lldp *lldp, const struct flow *flow);
 bool lldp_configure(struct lldp *lldp, const struct smap *cfg);
+bool lldp_is_enabled(struct lldp *lldp);
 void lldp_process_packet(struct lldp *cfg, const struct dp_packet *);
 void lldp_put_packet(struct lldp *lldp, struct dp_packet *packet,
  const struct eth_addr eth_src);
diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c
index ced67b0..a580fd4 100644
--- a/ofproto/ofproto-dpif.c
+++ b/ofproto/ofproto-dpif.c
@@ -2499,11 +2499,11 @@ set_lldp(struct ofport *ofport_,
 {
 struct ofport_dpif *ofport = ofport_dpif_cast(ofport_);
 struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofport->up.ofproto);
+bool old_enable = lldp_is_enabled(ofport->lldp);
 int error = 0;

-if (cfg) {
+if (cfg && !smap_is_empty(cfg)) {
 if (!ofport->lldp) {
-ofproto->backer->need_revalidate = REV_RECONFIGURE;
 ofport->lldp = lldp_create(ofport->up.netdev, ofport_->mtu, cfg);
 }

@@ -2515,6 +2515,9 @@ set_lldp(struct ofport *ofport_,
 } else if (ofport->lldp) {
 lldp_unref(ofport->lldp);
 ofport->lldp = NULL;
+}
+
+if (lldp_is_enabled(ofport->lldp) != old_enable) {
 ofproto->backer->need_revalidate = REV_RECONFIGURE;
 }

diff --git a/tests/ofproto-dpif.at b/tests/ofproto-dpif.at
index 7f273e5..edb6aa1 100644
--- a/tests/ofproto-dpif.at
+++ b/tests/ofproto-dpif.at
@@ -29,6 +29,39 @@ AT_CHECK([ovs-appctl revalidator/wait])
 OVS_VSWITCHD_STOP
 AT_CLEANUP

+AT_SETUP([ofproto-dpif - lldp revalidator event(REV_RECONFIGURE)])
+OVS_VSWITCHD_START(
+[add-port br0 p1 -- set interface p1 ofport_request=1 type=dummy]
+)
+dnl first revalidation triggered by add interface
+AT_CHECK([ovs-appctl coverage/read-counter rev_reconfigure], [0], [dnl
+1
+])
+
+dnl enable lldp
+AT_CHECK([ovs-vsctl set interface p1 lldp:enable=true])
+AT_CHECK([ovs-appctl revalidator/wait])
+AT_CHECK([ovs-appctl coverage/read-counter rev_reconfigure], [0], [dnl
+2
+])
+
+dnl disable lldp
+AT_CHECK([ovs-vsctl set interface p1 lldp:enable=false])
+AT_CHECK([ovs-appctl revalidator/wait])
+AT_CHECK([ovs-appctl coverage/read-counter rev_reconfigure], [0], [dnl
+3
+])
+
+dnl remove lldp, no revalidation as lldp was disabled
+AT_CHECK([ovs-vsctl remove interface p1 lldp enable])
+AT_CHECK([ovs-appctl revalidator/wait])
+AT_CHECK([ovs-appctl coverage/read-counter rev_reconfigure], [0], [dnl
+3
+])
+
+OVS_VSWITCHD_STOP
+AT_CLEANUP
+
 AT_SETUP([ofproto-dpif - active-backup bonding (with primary)])

 dnl Create br0 with members p1, p2 and p7, creating bond0 with p1 and
--
1.8.3.1

___
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev


Re: [ovs-dev] [PATCH 1/5] ofproto-dpif: fix packet_execute_prepare

2022-02-14 Thread Ilya Maximets
On 2/13/22 03:32, Peng He wrote:
> 
> 
> Ilya Maximets mailto:i.maxim...@ovn.org>> 于2022年2月12日周六 
> 05:34写道:
> 
> On 1/28/22 17:14, Aaron Conole wrote:
> > From: Peng He mailto:xnhp0...@gmail.com>>
> >
> > In the commit 1df7f7aac8c976690167261fec9a50d832ef9e7e, the packet
> > metadata's in_port has been changed from ofp port into odp port,
> > however, the odp->flow->in_port is still ofp_port. This patch changes
> > the odp->flow->in_port into odp_port.
> >
> > Fixes: 1df7f7aac8 ("ofproto-dpif: Restore packet metadata when a
> > continuation is resumed.")
> 
> Nit: please, don't wrap the tags.
> 
> 
> I'm sorry, but I'm getting trouble relating the mentioned commit
> with the code change here.  Commit 1df7f7aac8 made only cosmetic
> change to the 'execution' path in order to split out the function.
> The real change was made only for the packet resume, which doesn't
> seem to be the case for the current patch.
> 
> 
> In the commit 1df7f7aac8, it adds a function to set the correct in_port
> in the packet md:

Yes, but that is for 'resume' code path, not for 'execute'.  Code change
for the 'execute' path in the commit 1df7f7aac8 looks like this:

@@ -3704,11 +3713,7 @@ ofproto_dpif_execute_actions__(struct ofproto_dpif 
*ofproto,
 execute.mtu = 0;
 
 /* Fix up in_port. */
-in_port = flow->in_port.ofp_port;
-if (in_port == OFPP_NONE) {
-in_port = OFPP_LOCAL;
-}
-execute.packet->md.in_port.odp_port = ofp_port_to_odp_port(ofproto, 
in_port);
+ofproto_dpif_set_packet_odp_port(ofproto, flow->in_port.ofp_port, packet);
 
 error = dpif_execute(ofproto->backer->dpif, );
 out:
---

Meaning, the in_port update was there already and was only replaced with
a function to avoid code duplication.

> 
> +static void
> +ofproto_dpif_set_packet_odp_port(const struct ofproto_dpif *ofproto,
> +                                 ofp_port_t in_port, struct dp_packet 
> *packet)
> +{
> +    if (in_port == OFPP_NONE) {
> +        in_port = OFPP_LOCAL;
> +    }
> +    packet->md.in_port.odp_port = ofp_port_to_odp_port(ofproto, in_port);
> +}
> +
> 
> however it forgets to change the in_port field in the flow struct. This is ok 
> when
> the ipf_ctx patch is not added. If the ipf_ctx is added, it will use flow's 
> in_port as
> part of ipf_ctx.

I'm not sure if "forgets" is a correct word here.  AFAICT, 'in_port' is an
odp_port only when flow structure is constructed out of netlink attributes,
i.e. from the datapath flow.  And that is not the case here as we're dealing
with the OpenFlow match provided by the OF controller.

It might be better to not touch this structure and use the packet metadata
instead in the datapath code. (If you have a batch instead of a single
packet in the datapath, we can get the in_port from the metadata of the
first packet in that batch.  Datapath code already assumes that all the
packets in the batch has the same origin.)

> 
> If this patch is not added, the ipf_ctx patch will break some testsuites 
> which uses
> packetout to inject a test packet.
> 
> 
> 
> I managed to trace the in_port update in the 'execution' path down
> to commit 758c456df570 ("dpif: Use explicit packet metadata.").
> It significantly changed the way code is structured, so it's more
> likely a commit to blame.
> 
> I don't think that commit message here makes sense.  So, I'm not
> sure what exactly this patch is fixing.  Am I missing something?
> 
> I think, we need a new commit message that describes what actually
> the problem is and how it affects packet processing.  And we
> definitely need a unit test for that patch.
> 
> Best regards, Ilya Maximets.
> 
> > Signed-off-by: Peng He  >
> > Acked-by: Mike Pattrick mailto:m...@redhat.com>>
> > Signed-off-by: Aaron Conole  >
> > ---
> >  ofproto/ofproto-dpif.c | 1 +
> >  1 file changed, 1 insertion(+)
> >
> > diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c
> > index 8143dd965f..fed037b8d9 100644
> > --- a/ofproto/ofproto-dpif.c
> > +++ b/ofproto/ofproto-dpif.c
> > @@ -5011,6 +5011,7 @@ packet_execute_prepare(struct ofproto *ofproto_,
> >      ofproto_dpif_set_packet_odp_port(ofproto, 
> opo->flow->in_port.ofp_port,
> >                                       opo->packet);
> > 
> > +    opo->flow->in_port = opo->packet->md.in_port;
> >      ofproto_dpif_packet_out_delete(aux);
> >      opo->aux = execute;
> >  }
> 
> ___
> dev mailing list
> d...@openvswitch.org 
> https://mail.openvswitch.org/mailman/listinfo/ovs-dev 
> 
> 
> 
> 
> -- 
> hepeng

___
dev mailing list
d...@openvswitch.org

[ovs-dev] [PATCH v4 2/3] lldp: fix memory leak

2022-02-14 Thread lic121
lldp_create() malloc memory for lldp->lldpd->g_hardware. lldp_unref
is supposed to free the memory, but it doesn't.

Signed-off-by: lic121 
---
 lib/lldp/lldpd.c | 10 +++---
 1 file changed, 3 insertions(+), 7 deletions(-)

diff --git a/lib/lldp/lldpd.c b/lib/lldp/lldpd.c
index a024dc5..ee1051d 100644
--- a/lib/lldp/lldpd.c
+++ b/lib/lldp/lldpd.c
@@ -140,13 +140,9 @@ lldpd_cleanup(struct lldpd *cfg)
 VLOG_DBG("cleanup all ports");

 LIST_FOR_EACH_SAFE (hw, hw_next, h_entries, >g_hardware) {
-if (!hw->h_flags) {
-ovs_list_remove(>h_entries);
-lldpd_remote_cleanup(hw, NULL, true);
-lldpd_hardware_cleanup(cfg, hw);
-} else {
-lldpd_remote_cleanup(hw, NULL, false);
-}
+ovs_list_remove(>h_entries);
+lldpd_remote_cleanup(hw, NULL, true);
+lldpd_hardware_cleanup(cfg, hw);
 }

 VLOG_DBG("cleanup all chassis");
--
1.8.3.1

___
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev


[ovs-dev] [PATCH v4 1/3] ofproto-dpif: trigger revalidation when ipfix config set

2022-02-14 Thread lic121
Currently, ipfix conf creation/deletion don't trigger dpif backer
revalidation. This is not expected, as we need the revalidation
to commit ipfix into xlate. So that xlate can generate ipfix
actions.

This patch covers only new creation/deletion of ipfix config.
Will upload one more patch to cover ipfix option changes.

Signed-off-by: lic121 
---
 ofproto/ofproto-dpif.c | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c
index 8143dd9..ced67b0 100644
--- a/ofproto/ofproto-dpif.c
+++ b/ofproto/ofproto-dpif.c
@@ -2371,6 +2371,12 @@ set_ipfix(
 dpif_ipfix_unref(di);
 ofproto->ipfix = NULL;
 }
+
+/* TODO: need to consider ipfix option changes more than
+ * enable/disable */
+if (new_di || !ofproto->ipfix) {
+ofproto->backer->need_revalidate = REV_RECONFIGURE;
+}
 }

 return 0;
--
1.8.3.1

___
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev


[ovs-dev] [PATCH v4 0/3] fix dpif backer revalidation

2022-02-14 Thread lic121
v4:
- one patch is added to fix lldp memory leak
- add '!smap_is_empty(cfg)' condition

v3:
- fix lldp test case failure

v2:
- add TODO comments to clear ipfix patch coverage
- test lldp enabling more than pointer
- add test cases for lldp

ovsdb change or netlink notification trigger bridge_reconfigure.
In bridge_reconfigure, backer->need_revalidate flag is set if backer
revalidation is needed.

This series fix two places where need_revalidate flag is not set
correctly.

lic121 (3):
  ofproto-dpif: trigger revalidation when ipfix config set
  lldp: fix memory leak
  ofproto-dpif: avoid unneccesary backer revalidation

 lib/lldp/lldpd.c   | 10 +++---
 lib/ovs-lldp.c |  8 
 lib/ovs-lldp.h |  1 +
 ofproto/ofproto-dpif.c | 13 +++--
 tests/ofproto-dpif.at  | 33 +
 5 files changed, 56 insertions(+), 9 deletions(-)

--
1.8.3.1

___
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev


Re: [ovs-dev] [External] Re: [PATCH] dpif-netdev: add an option to assign pmd rxq to all numas

2022-02-14 Thread Wan Junjie
On Mon, Feb 14, 2022 at 6:54 PM Jan Scheurich
 wrote:
>
> > > We do acknowledge the benefit of non-pinned polling of phy rx queues by
> > PMD threads on all NUMA nodes. It gives the auto-load balancer much better
> > options to utilize spare capacity on PMDs on all NUMA nodes.
> > >
> > > Our patch proposed in
> > > https://protect2.fireeye.com/v1/url?k=31323334-501d5122-313273af-45444
> > > 731-c996011189a3eea8=1=0dc6a0b0-959c-493e-a3de-
> > fea8f3151705=
> > > https%3A%2F%2Fmail.openvswitch.org%2Fpipermail%2Fovs-dev%2F2021-
> > June%2
> > > F384547.html indeed covers the difference between phy and vhu ports.
> > > One has to explicitly enable cross-NUMA-polling for individual interfaces
> > with:
> > >
> > >ovs-vsctl set interface  other_config:cross-numa-polling=true
> > >
> > > This would typically only be done by static configuration for the fixed 
> > > set of
> > physical ports. There is no code in the OpenStack's os-vif handler to apply 
> > such
> > configuration for dynamically created vhu ports.
> > >
> > > I would strongly suggest that cross-num-polling be introduced as a per-
> > interface option as in our patch rather than as a per-datapath option as in 
> > your
> > patch. Why not adapt our original patch to the latest OVS code base? We can
> > help you with that.
> > >
> > > BR, Jan
> > >
> >
> > Hi, Jan Scheurich
> >
> > We can achieve the static setting of pinning a phy port by combining 
> > pmd-rxq-
> > isolate and pmd-rxq-affinity.  This setting can get the same result. And we 
> > have
> > seen the benefits.
> > The new issue is the polling of vhu on one numa. Under heavy traffic, 
> > polling
> > vhu + phy will make the pmds reach 100% usage. While other pmds on the
> > other numa with only phy port reaches 70% usage. Enabling cross-numa polling
> > for a vhu port would give us more benefits in this case. Overloads of 
> > different
> > pmds on both numa would be balanced.
> > As you have mentioned, there is no code to apply this config for vhu while
> > creating them. A global setting would save us from dynamically detecting the
> > vhu name or any new creation.
>
> Hi Wan Junjie,
>
> We have done extensive benchmarking and found that we get better overall PMD 
> load balance and resulting OVS performance when we do not statically pin any 
> rx queues and instead let the auto-load-balancing find the optimal 
> distribution of phy rx queues over both NUMA nodes to balance an asymmetric 
> load of vhu rx queues (polled only on the local NUMA node).
>
> Cross-NUMA polling of vhu rx queues comes with a very high latency cost due 
> to cross-NUMA access to volatile virtio ring pointers in every iteration (not 
> only when actually copying packets). Cross-NUMA polling of phy rx queues 
> doesn't have a similar issue.
>
> BR, Jan
>

Hi Jan Scheurich,

Thanks for the info. Yes I am using the static pinning. It should have
saved the cost for calculating the 'load'. I'm with you on that.
Kevin's RFC seems to be like using dynamic calculating.
As for the latency cost of cross-numa on vhu, it seems to be a
concern. I would say It is a trade-off with a cost. I have no bias for
using the cross-numa by default.  Maybe for different traffic
patterns, different settings could be a proper way.

Regards,
Wan Junjie
___
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev


Re: [ovs-dev] [PATCH v2 15/16] sparse: bump recommended version and include headers

2022-02-14 Thread 0-day Robot
Bleep bloop.  Greetings Adrian Moreno, 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: Co-author Dumitru Ceara  needs to sign off.
Lines checked: 45, Warnings: 0, 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 v2 11/16] hindex: remove the next variable in safe loops

2022-02-14 Thread 0-day Robot
Bleep bloop.  Greetings Adrian Moreno, 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: Use ovs_assert() in place of assert()
#122 FILE: tests/test-hindex.c:296:
assert(n == n_remaining);

ERROR: Use ovs_assert() in place of assert()
#131 FILE: tests/test-hindex.c:305:
assert(i < n);

ERROR: Use ovs_assert() in place of assert()
#136 FILE: tests/test-hindex.c:310:
assert(j < n_remaining);

ERROR: Use ovs_assert() in place of assert()
#146 FILE: tests/test-hindex.c:320:
assert(i == n);

Lines checked: 154, Warnings: 0, Errors: 4


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 v2 10/16] hindex: use multi-variable iterators

2022-02-14 Thread 0-day Robot
Bleep bloop.  Greetings Adrian Moreno, 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: Use ovs_assert() in place of assert()
#92 FILE: tests/test-hindex.c:269:
assert(next == NULL);

ERROR: Use ovs_assert() in place of assert()
#94 FILE: tests/test-hindex.c:271:
assert(>node == hindex_next(, >node));

ERROR: Use ovs_assert() in place of assert()
#103 FILE: tests/test-hindex.c:289:
assert(next == NULL);

Lines checked: 110, Warnings: 0, Errors: 3


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 v2 09/16] cmap: use multi-variable iterators

2022-02-14 Thread 0-day Robot
Bleep bloop.  Greetings Adrian Moreno, 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: Use ovs_assert() in place of assert()
#74 FILE: tests/test-cmap.c:77:
assert(e == NULL);

ERROR: Use ovs_assert() in place of assert()
#82 FILE: tests/test-cmap.c:111:
assert(e == NULL);

ERROR: Use ovs_assert() in place of assert()
#90 FILE: tests/test-cmap.c:135:
assert(e == NULL);

Lines checked: 97, Warnings: 0, Errors: 3


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] [External] Re: [PATCH] dpif-netdev: add an option to assign pmd rxq to all numas

2022-02-14 Thread Jan Scheurich via dev
> > We do acknowledge the benefit of non-pinned polling of phy rx queues by
> PMD threads on all NUMA nodes. It gives the auto-load balancer much better
> options to utilize spare capacity on PMDs on all NUMA nodes.
> >
> > Our patch proposed in
> > https://protect2.fireeye.com/v1/url?k=31323334-501d5122-313273af-45444
> > 731-c996011189a3eea8=1=0dc6a0b0-959c-493e-a3de-
> fea8f3151705=
> > https%3A%2F%2Fmail.openvswitch.org%2Fpipermail%2Fovs-dev%2F2021-
> June%2
> > F384547.html indeed covers the difference between phy and vhu ports.
> > One has to explicitly enable cross-NUMA-polling for individual interfaces
> with:
> >
> >ovs-vsctl set interface  other_config:cross-numa-polling=true
> >
> > This would typically only be done by static configuration for the fixed set 
> > of
> physical ports. There is no code in the OpenStack's os-vif handler to apply 
> such
> configuration for dynamically created vhu ports.
> >
> > I would strongly suggest that cross-num-polling be introduced as a per-
> interface option as in our patch rather than as a per-datapath option as in 
> your
> patch. Why not adapt our original patch to the latest OVS code base? We can
> help you with that.
> >
> > BR, Jan
> >
> 
> Hi, Jan Scheurich
> 
> We can achieve the static setting of pinning a phy port by combining pmd-rxq-
> isolate and pmd-rxq-affinity.  This setting can get the same result. And we 
> have
> seen the benefits.
> The new issue is the polling of vhu on one numa. Under heavy traffic, polling
> vhu + phy will make the pmds reach 100% usage. While other pmds on the
> other numa with only phy port reaches 70% usage. Enabling cross-numa polling
> for a vhu port would give us more benefits in this case. Overloads of 
> different
> pmds on both numa would be balanced.
> As you have mentioned, there is no code to apply this config for vhu while
> creating them. A global setting would save us from dynamically detecting the
> vhu name or any new creation.

Hi Wan Junjie,

We have done extensive benchmarking and found that we get better overall PMD 
load balance and resulting OVS performance when we do not statically pin any rx 
queues and instead let the auto-load-balancing find the optimal distribution of 
phy rx queues over both NUMA nodes to balance an asymmetric load of vhu rx 
queues (polled only on the local NUMA node).

Cross-NUMA polling of vhu rx queues comes with a very high latency cost due to 
cross-NUMA access to volatile virtio ring pointers in every iteration (not only 
when actually copying packets). Cross-NUMA polling of phy rx queues doesn't 
have a similar issue.

BR, Jan

___
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev


Re: [ovs-dev] [PATCH v2 08/16] hmap: use short version of safe loops if possible

2022-02-14 Thread 0-day Robot
Bleep bloop.  Greetings Adrian Moreno, 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: Inappropriate bracing around statement
#87 FILE: include/openvswitch/hmap.h:182:
HMAP_FOR_EACH_SAFE_LONG_INIT (NODE, NEXT, MEMBER, HMAP, (void) NEXT)

ERROR: Inappropriate bracing around statement
#102 FILE: include/openvswitch/hmap.h:195:
HMAP_FOR_EACH_SAFE_SHORT_INIT (NODE, MEMBER, HMAP, (void) 0)

ERROR: Use ovs_assert() in place of assert()
#1551 FILE: tests/test-hmap.c:277:
assert(n == n_remaining);

ERROR: Use ovs_assert() in place of assert()
#1560 FILE: tests/test-hmap.c:286:
assert(i < n);

ERROR: Use ovs_assert() in place of assert()
#1565 FILE: tests/test-hmap.c:291:
assert(j < n_remaining);

ERROR: Use ovs_assert() in place of assert()
#1575 FILE: tests/test-hmap.c:301:
assert(i == n);

ERROR: Use ovs_assert() in place of assert()
#1576 FILE: tests/test-hmap.c:302:
assert(e == NULL);

Lines checked: 1847, Warnings: 0, Errors: 7


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 v2 07/16] hmap: implement UB-safe hmap pop iterator

2022-02-14 Thread 0-day Robot
Bleep bloop.  Greetings Adrian Moreno, 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: Use ovs_assert() in place of assert()
#76 FILE: tests/test-hmap.c:320:
assert(e == NULL);

Lines checked: 83, Warnings: 0, 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 v2 06/16] hmap: use multi-variable helpers for hmap loops

2022-02-14 Thread 0-day Robot
Bleep bloop.  Greetings Adrian Moreno, 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: Inappropriate bracing around statement
#77 FILE: include/openvswitch/hmap.h:182:
HMAP_FOR_EACH_SAFE_INIT (NODE, NEXT, MEMBER, HMAP, (void) NEXT)

ERROR: Inappropriate bracing around statement
#115 FILE: lib/ovs-numa.h:71:
HMAP_FOR_EACH (ITER, hmap_node, &(DUMP)->cores)

ERROR: Inappropriate bracing around statement
#119 FILE: lib/ovs-numa.h:74:
HMAP_FOR_EACH (ITER, hmap_node, &(DUMP)->numas)

ERROR: Use ovs_assert() in place of assert()
#130 FILE: tests/test-hmap.c:65:
assert(e == NULL);

ERROR: Use ovs_assert() in place of assert()
#138 FILE: tests/test-hmap.c:86:
assert(e == NULL);

ERROR: Use ovs_assert() in place of assert()
#147 FILE: tests/test-hmap.c:249:
assert(next == NULL);

ERROR: Use ovs_assert() in place of assert()
#149 FILE: tests/test-hmap.c:251:
assert(>node == hmap_next(, >node));

ERROR: Use ovs_assert() in place of assert()
#158 FILE: tests/test-hmap.c:269:
assert(next == NULL);

ERROR: Use ovs_assert() in place of assert()
#159 FILE: tests/test-hmap.c:270:
assert(e == NULL);

Lines checked: 166, Warnings: 0, Errors: 9


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 v2 05/16] list: use short version of safe loops if possible

2022-02-14 Thread 0-day Robot
Bleep bloop.  Greetings Adrian Moreno, 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: Use ovs_assert() in place of assert()
#1174 FILE: tests/test-list.c:148:
assert(next == NULL);

ERROR: Use ovs_assert() in place of assert()
#1177 FILE: tests/test-list.c:151:
assert(>node == e->node.next);

ERROR: Use ovs_assert() in place of assert()
#1195 FILE: tests/test-list.c:184:
assert(i < n);

ERROR: Use ovs_assert() in place of assert()
#1208 FILE: tests/test-list.c:197:
assert(i == n);

ERROR: Use ovs_assert() in place of assert()
#1209 FILE: tests/test-list.c:198:
assert(e == NULL);

Lines checked: 1383, Warnings: 0, Errors: 5


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 v2 03/16] list: use multi-variable helpers for list loops

2022-02-14 Thread 0-day Robot
Bleep bloop.  Greetings Adrian Moreno, 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: Use ovs_assert() in place of assert()
#128 FILE: tests/test-list.c:64:
assert(e == NULL);

ERROR: Use ovs_assert() in place of assert()
#137 FILE: tests/test-list.c:73:
assert(e == NULL);

ERROR: Use ovs_assert() in place of assert()
#147 FILE: tests/test-list.c:140:
assert(next == NULL);

ERROR: Use ovs_assert() in place of assert()
#149 FILE: tests/test-list.c:142:
assert(>node == e->node.next);

ERROR: Use ovs_assert() in place of assert()
#165 FILE: tests/test-list.c:159:
assert(e == NULL);

ERROR: Use ovs_assert() in place of assert()
#166 FILE: tests/test-list.c:160:
assert(next == NULL);

Lines checked: 173, Warnings: 0, Errors: 6


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] [External] Re: [PATCH] dpif-netdev: add an option to assign pmd rxq to all numas

2022-02-14 Thread Wan Junjie
On Mon, Feb 14, 2022 at 6:12 PM Jan Scheurich
 wrote:
>
> > >
> > > Btw, this patch is similar in functionality to the one posted by
> > > Anurag [0] and there was also some discussion about this approach here 
> > > [1].
> > >
> >
> > Thanks for pointing this out.
> > IMO, setting interface cross-numa would be good for phy port but not good 
> > for
> > vhu.  Since vhu can be destroyed and created relatively frequently.
> > But yes the main idea is the same.
> >
>
> We do acknowledge the benefit of non-pinned polling of phy rx queues by PMD 
> threads on all NUMA nodes. It gives the auto-load balancer much better 
> options to utilize spare capacity on PMDs on all NUMA nodes.
>
> Our patch proposed in 
> https://mail.openvswitch.org/pipermail/ovs-dev/2021-June/384547.html
> indeed covers the difference between phy and vhu ports. One has to explicitly 
> enable cross-NUMA-polling for individual interfaces with:
>
>ovs-vsctl set interface  other_config:cross-numa-polling=true
>
> This would typically only be done by static configuration for the fixed set 
> of physical ports. There is no code in the OpenStack's os-vif handler to 
> apply such configuration for dynamically created vhu ports.
>
> I would strongly suggest that cross-num-polling be introduced as a 
> per-interface option as in our patch rather than as a per-datapath option as 
> in your patch. Why not adapt our original patch to the latest OVS code base? 
> We can help you with that.
>
> BR, Jan
>

Hi, Jan Scheurich

We can achieve the static setting of pinning a phy port by combining
pmd-rxq-isolate and pmd-rxq-affinity.  This setting can get the same
result. And we have seen the benefits.
The new issue is the polling of vhu on one numa. Under heavy traffic,
polling vhu + phy will make the pmds reach 100% usage. While other
pmds on the other numa with only phy port reaches 70% usage. Enabling
cross-numa polling for a vhu port would give us more benefits in this
case. Overloads of different pmds on both numa would be balanced.
As you have mentioned, there is no code to apply this config for vhu
while creating them. A global setting would save us from dynamically
detecting the vhu name or any new creation.


Regards,
Wan Junjie
___
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev


Re: [ovs-dev] [PATCH 15/16] sparse: bump recommended version and include headers

2022-02-14 Thread 0-day Robot
Bleep bloop.  Greetings Adrian Moreno, 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: Dumitru Ceara 
Lines checked: 45, 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


Re: [ovs-dev] [PATCH 11/16] hindex: remove the next variable in safe loops

2022-02-14 Thread 0-day Robot
Bleep bloop.  Greetings Adrian Moreno, 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: Use ovs_assert() in place of assert()
#122 FILE: tests/test-hindex.c:296:
assert(n == n_remaining);

ERROR: Use ovs_assert() in place of assert()
#131 FILE: tests/test-hindex.c:305:
assert(i < n);

ERROR: Use ovs_assert() in place of assert()
#136 FILE: tests/test-hindex.c:310:
assert(j < n_remaining);

ERROR: Use ovs_assert() in place of assert()
#146 FILE: tests/test-hindex.c:320:
assert(i == n);

Lines checked: 154, Warnings: 0, Errors: 4


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 v2 11/16] hindex: remove the next variable in safe loops

2022-02-14 Thread Adrian Moreno
Using SHORT version of the *_SAFE loops makes the code cleaner and less
error prone. So, use the SHORT version and remove the extra variable
when possible for HINDEX_*_SAFE.

In order to be able to use both long and short versions without changing
the name of the macro for all the clients, overload the existing name
and select the appropriate version depending on the number of arguments.

Signed-off-by: Adrian Moreno 
---
 lib/conntrack.c |  4 ++--
 lib/hindex.h| 46 +
 tests/test-hindex.c | 31 ++
 3 files changed, 71 insertions(+), 10 deletions(-)

diff --git a/lib/conntrack.c b/lib/conntrack.c
index 9c96b69e4..2f0777102 100644
--- a/lib/conntrack.c
+++ b/lib/conntrack.c
@@ -2857,8 +2857,8 @@ expectation_clean(struct conntrack *ct, const struct 
conn_key *parent_key)
 {
 ovs_rwlock_wrlock(>resources_lock);
 
-struct alg_exp_node *node, *next;
-HINDEX_FOR_EACH_WITH_HASH_SAFE (node, next, node_ref,
+struct alg_exp_node *node;
+HINDEX_FOR_EACH_WITH_HASH_SAFE (node, node_ref,
 conn_key_hash(parent_key, ct->hash_basis),
 >alg_expectation_refs) {
 if (!conn_key_cmp(>parent_key, parent_key)) {
diff --git a/lib/hindex.h b/lib/hindex.h
index c20752c25..8f537069c 100644
--- a/lib/hindex.h
+++ b/lib/hindex.h
@@ -134,15 +134,31 @@ void hindex_remove(struct hindex *, struct hindex_node *);
 
 /* Safe when NODE may be freed (not needed when NODE may be removed from the
  * hash map but its members remain accessible and intact). */
-#define HINDEX_FOR_EACH_WITH_HASH_SAFE(NODE, NEXT, MEMBER, HASH, HINDEX)\
-for (INIT_MULTIVAR_SAFE_LONG(NODE, NEXT, MEMBER,\
-hindex_node_with_hash(HINDEX, HASH));   \
- CONDITION_MULTIVAR_SAFE_LONG(NODE, NEXT, MEMBER,   \
-  ITER_VAR(NODE) != NULL,   \
-  ITER_VAR(NEXT) = ITER_VAR(NODE)->s,   \
-  ITER_VAR(NEXT) != NULL);  \
+#define HINDEX_FOR_EACH_WITH_HASH_SAFE_LONG(NODE, NEXT, MEMBER, HASH, HINDEX) \
+for (INIT_MULTIVAR_SAFE_LONG(NODE, NEXT, MEMBER,  \
+hindex_node_with_hash(HINDEX, HASH)); \
+ CONDITION_MULTIVAR_SAFE_LONG(NODE, NEXT, MEMBER, \
+  ITER_VAR(NODE) != NULL, \
+  ITER_VAR(NEXT) = ITER_VAR(NODE)->s, \
+  ITER_VAR(NEXT) != NULL);\
  UPDATE_MULTIVAR_SAFE_LONG(NODE, NEXT))
 
+/* Short version of HINDEX_FOR_EACH_WITH_HASH_SAFE */
+#define HINDEX_FOR_EACH_WITH_HASH_SAFE_SHORT(NODE, MEMBER, HASH, HINDEX)  \
+for (INIT_MULTIVAR_SAFE_SHORT(NODE, MEMBER,   \
+hindex_node_with_hash(HINDEX, HASH)); \
+ CONDITION_MULTIVAR_SAFE_SHORT(NODE, MEMBER,  \
+   ITER_VAR(NODE) != NULL,\
+ ITER_NEXT_VAR(NODE) = ITER_VAR(NODE)->s);\
+ UPDATE_MULTIVAR_SAFE_SHORT(NODE))
+
+#define HINDEX_GET_SAFE_MACRO_WITH_HASH(_1, _2, _3, _4, _5, NAME, ...) NAME
+#define HINDEX_FOR_EACH_WITH_HASH_SAFE(...)   \
+HINDEX_GET_SAFE_MACRO_WITH_HASH(__VA_ARGS__,  \
+HINDEX_FOR_EACH_WITH_HASH_SAFE_LONG,  \
+HINDEX_FOR_EACH_WITH_HASH_SAFE_SHORT)(__VA_ARGS__)
+
+
 /* Returns the head node in 'hindex' with the given 'hash', or a null pointer
  * if no nodes have that hash value. */
 static inline struct hindex_node *
@@ -167,7 +183,7 @@ hindex_node_with_hash(const struct hindex *hindex, size_t 
hash)
 
 /* Safe when NODE may be freed (not needed when NODE may be removed from the
  * hash index but its members remain accessible and intact). */
-#define HINDEX_FOR_EACH_SAFE(NODE, NEXT, MEMBER, HINDEX)  \
+#define HINDEX_FOR_EACH_SAFE_LONG(NODE, NEXT, MEMBER, HINDEX) \
 for (INIT_MULTIVAR_SAFE_LONG(NODE, NEXT, MEMBER, hindex_first(HINDEX));   \
  CONDITION_MULTIVAR_SAFE_LONG(NODE, NEXT, MEMBER, \
   ITER_VAR(NODE) != NULL, \
@@ -175,6 +191,20 @@ hindex_node_with_hash(const struct hindex *hindex, size_t 
hash)
   ITER_VAR(NEXT) != NULL);\
  UPDATE_MULTIVAR_SAFE_LONG(NODE, NEXT))
 
+/* Short version of HINDEX_FOR_EACH_SAFE */
+#define HINDEX_FOR_EACH_SAFE_SHORT(NODE, MEMBER, HINDEX)  \
+for (INIT_MULTIVAR_SAFE_SHORT(NODE, MEMBER, hindex_first(HINDEX));\

[ovs-dev] [PATCH v2 10/16] hindex: use multi-variable iterators

2022-02-14 Thread Adrian Moreno
Re-write hindex's loops using multi-variable helpers.

For safe loops, use the LONG version to maintain backwards
compatibility.

Signed-off-by: Adrian Moreno 
---
 lib/hindex.h| 42 +++---
 tests/test-hindex.c |  6 ++
 2 files changed, 29 insertions(+), 19 deletions(-)

diff --git a/lib/hindex.h b/lib/hindex.h
index 876c5a9e3..c20752c25 100644
--- a/lib/hindex.h
+++ b/lib/hindex.h
@@ -128,18 +128,20 @@ void hindex_remove(struct hindex *, struct hindex_node *);
  * Evaluates HASH only once.
  */
 #define HINDEX_FOR_EACH_WITH_HASH(NODE, MEMBER, HASH, HINDEX)   \
-for (INIT_CONTAINER(NODE, hindex_node_with_hash(HINDEX, HASH), MEMBER); \
- NODE != OBJECT_CONTAINING(NULL, NODE, MEMBER); \
- ASSIGN_CONTAINER(NODE, (NODE)->MEMBER.s, MEMBER))
+for (INIT_MULTIVAR(NODE, MEMBER, hindex_node_with_hash(HINDEX, HASH));  \
+ CONDITION_MULTIVAR(NODE, MEMBER, ITER_VAR(NODE) != NULL);  \
+ UPDATE_MULTIVAR(NODE, ITER_VAR(NODE) = ITER_VAR(NODE)->s))
 
 /* Safe when NODE may be freed (not needed when NODE may be removed from the
  * hash map but its members remain accessible and intact). */
-#define HINDEX_FOR_EACH_WITH_HASH_SAFE(NODE, NEXT, MEMBER, HASH, HINDEX) \
-for (INIT_CONTAINER(NODE, hindex_node_with_hash(HINDEX, HASH), MEMBER); \
- (NODE != OBJECT_CONTAINING(NULL, NODE, MEMBER) \
-  ? INIT_CONTAINER(NEXT, (NODE)->MEMBER.s, MEMBER), 1   \
-  : 0); \
- (NODE) = (NEXT))
+#define HINDEX_FOR_EACH_WITH_HASH_SAFE(NODE, NEXT, MEMBER, HASH, HINDEX)\
+for (INIT_MULTIVAR_SAFE_LONG(NODE, NEXT, MEMBER,\
+hindex_node_with_hash(HINDEX, HASH));   \
+ CONDITION_MULTIVAR_SAFE_LONG(NODE, NEXT, MEMBER,   \
+  ITER_VAR(NODE) != NULL,   \
+  ITER_VAR(NEXT) = ITER_VAR(NODE)->s,   \
+  ITER_VAR(NEXT) != NULL);  \
+ UPDATE_MULTIVAR_SAFE_LONG(NODE, NEXT))
 
 /* Returns the head node in 'hindex' with the given 'hash', or a null pointer
  * if no nodes have that hash value. */
@@ -157,19 +159,21 @@ hindex_node_with_hash(const struct hindex *hindex, size_t 
hash)
 /* Iteration. */
 
 /* Iterates through every node in HINDEX. */
-#define HINDEX_FOR_EACH(NODE, MEMBER, HINDEX)   \
-for (INIT_CONTAINER(NODE, hindex_first(HINDEX), MEMBER);\
- NODE != OBJECT_CONTAINING(NULL, NODE, MEMBER); \
- ASSIGN_CONTAINER(NODE, hindex_next(HINDEX, &(NODE)->MEMBER), MEMBER))
+#define HINDEX_FOR_EACH(NODE, MEMBER, HINDEX) \
+for (INIT_MULTIVAR(NODE, MEMBER, hindex_first(HINDEX));   \
+ CONDITION_MULTIVAR(NODE, MEMBER, ITER_VAR(NODE) != NULL);\
+ UPDATE_MULTIVAR(NODE,\
+ ITER_VAR(NODE) = hindex_next(HINDEX, ITER_VAR(NODE
 
 /* Safe when NODE may be freed (not needed when NODE may be removed from the
  * hash index but its members remain accessible and intact). */
-#define HINDEX_FOR_EACH_SAFE(NODE, NEXT, MEMBER, HINDEX)  \
-for (INIT_CONTAINER(NODE, hindex_first(HINDEX), MEMBER);  \
- (NODE != OBJECT_CONTAINING(NULL, NODE, MEMBER) \
-  ? INIT_CONTAINER(NEXT, hindex_next(HINDEX, &(NODE)->MEMBER), 
MEMBER), 1 \
-  : 0); \
- (NODE) = (NEXT))
+#define HINDEX_FOR_EACH_SAFE(NODE, NEXT, MEMBER, HINDEX)  \
+for (INIT_MULTIVAR_SAFE_LONG(NODE, NEXT, MEMBER, hindex_first(HINDEX));   \
+ CONDITION_MULTIVAR_SAFE_LONG(NODE, NEXT, MEMBER, \
+  ITER_VAR(NODE) != NULL, \
+ITER_VAR(NEXT) = hindex_next(HINDEX, ITER_VAR(NODE)), \
+  ITER_VAR(NEXT) != NULL);\
+ UPDATE_MULTIVAR_SAFE_LONG(NODE, NEXT))
 
 struct hindex_node *hindex_first(const struct hindex *);
 struct hindex_node *hindex_next(const struct hindex *,
diff --git a/tests/test-hindex.c b/tests/test-hindex.c
index af06be5fc..95e49284e 100644
--- a/tests/test-hindex.c
+++ b/tests/test-hindex.c
@@ -265,6 +265,11 @@ test_hindex_for_each_safe(hash_func *hash)
 i = 0;
 n_remaining = n;
 HINDEX_FOR_EACH_SAFE (e, next, node, ) {
+if (hindex_next(, >node) == NULL) {
+assert(next == NULL);
+} else {
+assert(>node == hindex_next(, >node));
+}
 assert(i < n);
 if (pattern & (1ul << 

[ovs-dev] [PATCH v2 08/16] hmap: use short version of safe loops if possible

2022-02-14 Thread Adrian Moreno
Using SHORT version of the *_SAFE loops makes the code cleaner and less
error prone. So, use the SHORT version and remove the extra variable
when possible for hmap and all its derived types.

In order to be able to use both long and short versions without changing
the name of the macro for all the clients, overload the existing name
and select the appropriate version depending on the number of arguments.

Signed-off-by: Adrian Moreno 
---
 include/openvswitch/hmap.h   | 28 +++---
 include/openvswitch/shash.h  | 16 +--
 lib/cfm.c|  4 +--
 lib/classifier.c |  4 +--
 lib/dns-resolve.c|  4 +--
 lib/dpif-netdev.c| 19 ++--
 lib/hmapx.c  |  4 +--
 lib/hmapx.h  | 15 --
 lib/json.c   |  4 +--
 lib/lacp.c   |  4 +--
 lib/mac-learning.c   |  4 +--
 lib/namemap.c|  4 +--
 lib/netdev-dpdk.c|  4 +--
 lib/netdev-linux.c   |  4 +--
 lib/netdev-offload-tc.c  |  4 +--
 lib/ofp-msgs.c   |  4 +--
 lib/ovsdb-cs.c   | 12 
 lib/ovsdb-idl.c  | 16 +--
 lib/ovsdb-map-op.c   |  4 +--
 lib/ovsdb-set-op.c   |  4 +--
 lib/pcap-file.c  |  4 +--
 lib/perf-counter.c   |  4 +--
 lib/poll-loop.c  |  4 +--
 lib/seq.c|  4 +--
 lib/shash.c  |  8 +++---
 lib/simap.c  |  4 +--
 lib/simap.h  | 17 +--
 lib/smap.c   |  4 +--
 lib/smap.h   | 16 +--
 lib/stopwatch.c  |  4 +--
 ofproto/bond.c   |  4 +--
 ofproto/connmgr.c| 20 ++---
 ofproto/in-band.c|  4 +--
 ofproto/netflow.c|  8 +++---
 ofproto/ofproto-dpif-ipfix.c |  8 +++---
 ofproto/ofproto-dpif-sflow.c |  4 +--
 ofproto/ofproto-dpif-xlate.c |  8 +++---
 ofproto/ofproto-dpif.c   |  4 +--
 ofproto/ofproto.c| 16 +--
 ovsdb/condition.c|  8 +++---
 ovsdb/jsonrpc-server.c   | 24 
 ovsdb/monitor.c  | 12 
 ovsdb/ovsdb-server.c | 11 ---
 ovsdb/ovsdb-tool.c   |  7 ++---
 ovsdb/query.c|  4 +--
 ovsdb/raft-private.c |  4 +--
 ovsdb/raft.c | 18 ++--
 ovsdb/relay.c|  4 +--
 ovsdb/replication.c  |  8 +++---
 ovsdb/table.c|  4 +--
 ovsdb/transaction-forward.c  |  4 +--
 ovsdb/transaction.c  |  8 +++---
 tests/test-cmap.c|  4 +--
 tests/test-hmap.c| 32 +
 tests/test-list.c|  2 +-
 utilities/ovs-vsctl.c|  4 +--
 vswitchd/bridge.c| 56 ++--
 vtep/vtep-ctl.c  |  6 ++--
 58 files changed, 311 insertions(+), 216 deletions(-)

diff --git a/include/openvswitch/hmap.h b/include/openvswitch/hmap.h
index 283407e3a..a3a979880 100644
--- a/include/openvswitch/hmap.h
+++ b/include/openvswitch/hmap.h
@@ -178,11 +178,11 @@ bool hmap_contains(const struct hmap *, const struct 
hmap_node *);
 
 /* Safe when NODE may be freed (not needed when NODE may be removed from the
  * hash map but its members remain accessible and intact). */
-#define HMAP_FOR_EACH_SAFE(NODE, NEXT, MEMBER, HMAP) \
-HMAP_FOR_EACH_SAFE_INIT (NODE, NEXT, MEMBER, HMAP, (void) NEXT)
+#define HMAP_FOR_EACH_SAFE_LONG(NODE, NEXT, MEMBER, HMAP) \
+HMAP_FOR_EACH_SAFE_LONG_INIT (NODE, NEXT, MEMBER, HMAP, (void) NEXT)
 
-#define HMAP_FOR_EACH_SAFE_INIT(NODE, NEXT, MEMBER, HMAP, ...)\
-for (INIT_MULTIVAR_SAFE_LONG_EXP(NODE, NEXT, MEMBER, hmap_first(HMAP),\
+#define HMAP_FOR_EACH_SAFE_LONG_INIT(NODE, NEXT, MEMBER, HMAP, ...)   \
+for (INIT_MULTIVAR_SAFE_LONG_EXP(NODE, NEXT, MEMBER, hmap_first(HMAP),   \
   __VA_ARGS__);   \
  CONDITION_MULTIVAR_SAFE_LONG(NODE, NEXT, MEMBER, \
   ITER_VAR(NODE) != NULL, \
@@ -190,6 +190,26 @@ bool hmap_contains(const struct hmap *, const struct 
hmap_node *);
   ITER_VAR(NEXT) != NULL);\
  UPDATE_MULTIVAR_SAFE_LONG(NODE, NEXT))
 
+/* Short versions of HMAP_FOR_EACH_SAFE */
+#define HMAP_FOR_EACH_SAFE_SHORT(NODE, MEMBER, HMAP)  \
+HMAP_FOR_EACH_SAFE_SHORT_INIT (NODE, MEMBER, HMAP, (void) 0)
+
+#define HMAP_FOR_EACH_SAFE_SHORT_INIT(NODE, MEMBER, HMAP, ...)\
+for (INIT_MULTIVAR_SAFE_SHORT_EXP(NODE, MEMBER,   \
+  hmap_first(HMAP), __VA_ARGS__); \
+ CONDITION_MULTIVAR_SAFE_SHORT(NODE, MEMBER,  \
+   ITER_VAR(NODE) != NULL,

[ovs-dev] [PATCH v2 14/16] idlc: support short version of SAFE macros

2022-02-14 Thread Adrian Moreno
In order to be consistent with the rest of the SAFE loop macros,
overload each of the generated *_SAFE macro with a SHORT version that
does not require the user to provide the NEXT variable.

Signed-off-by: Adrian Moreno 
---
 ovsdb/ovsdb-idlc.in   | 23 +--
 utilities/ovs-vsctl.c | 36 ++--
 2 files changed, 39 insertions(+), 20 deletions(-)

diff --git a/ovsdb/ovsdb-idlc.in b/ovsdb/ovsdb-idlc.in
index 5a02c8f93..4346a572a 100755
--- a/ovsdb/ovsdb-idlc.in
+++ b/ovsdb/ovsdb-idlc.in
@@ -251,10 +251,20 @@ const struct %(s)s *%(s)s_table_first(const struct 
%(s)s_table *);
 for ((ROW) = %(s)s_table_first(TABLE); \\
  (ROW); \\
  (ROW) = %(s)s_next(ROW))
-#define %(S)s_TABLE_FOR_EACH_SAFE(ROW, NEXT, TABLE) \\
+#define %(S)s_TABLE_FOR_EACH_SAFE_LONG(ROW, NEXT, TABLE) \\
 for ((ROW) = %(s)s_table_first(TABLE); \\
  (ROW) ? ((NEXT) = %(s)s_next(ROW), 1) : 0; \\
  (ROW) = (NEXT))
+#define %(S)s_TABLE_FOR_EACH_SAFE_SHORT(ROW, TABLE) \\
+for (OVS_TYPEOF(ROW) ROW__next = ((ROW) = %(s)s_table_first(TABLE), 
NULL); \\
+ (ROW) ? (ROW__next = %(s)s_next(ROW), 1) : (ROW__next = NULL, 0); 
\\
+ (ROW) = ROW__next)
+#define %(S)s_TABLE_GET_SAFE_MACRO(_1, _2, _3, NAME) NAME
+#define %(S)s_TABLE_FOR_EACH_SAFE(...) \\
+%(S)s_TABLE_GET_SAFE_MACRO(__VA_ARGS__,\\
+   %(S)s_TABLE_FOR_EACH_SAFE_LONG, \\
+   %(S)s_TABLE_FOR_EACH_SAFE_SHORT)(__VA_ARGS__)
+
 
 const struct %(s)s *%(s)s_get_for_uuid(const struct ovsdb_idl *, const struct 
uuid *);
 const struct %(s)s *%(s)s_table_get_for_uuid(const struct %(s)s_table *, const 
struct uuid *);
@@ -264,10 +274,19 @@ const struct %(s)s *%(s)s_next(const struct %(s)s *);
 for ((ROW) = %(s)s_first(IDL); \\
  (ROW); \\
  (ROW) = %(s)s_next(ROW))
-#define %(S)s_FOR_EACH_SAFE(ROW, NEXT, IDL) \\
+#define %(S)s_FOR_EACH_SAFE_LONG(ROW, NEXT, IDL) \\
 for ((ROW) = %(s)s_first(IDL); \\
  (ROW) ? ((NEXT) = %(s)s_next(ROW), 1) : 0; \\
  (ROW) = (NEXT))
+#define %(S)s_FOR_EACH_SAFE_SHORT(ROW, IDL) \\
+for (OVS_TYPEOF(ROW) ROW__next = ((ROW) = %(s)s_first(IDL), NULL); \\
+ (ROW) ? (ROW__next = %(s)s_next(ROW), 1) : (ROW__next = NULL, 0); 
\\
+ (ROW) = ROW__next)
+#define %(S)s_GET_SAFE_MACRO(_1, _2, _3, NAME) NAME
+#define %(S)s_FOR_EACH_SAFE(...) \\
+%(S)s_GET_SAFE_MACRO(__VA_ARGS__,\\
+   %(S)s_FOR_EACH_SAFE_LONG, \\
+   %(S)s_FOR_EACH_SAFE_SHORT)(__VA_ARGS__)
 
 unsigned int %(s)s_get_seqno(const struct ovsdb_idl *);
 unsigned int %(s)s_row_get_seqno(const struct %(s)s *row, enum 
ovsdb_idl_change change);
diff --git a/utilities/ovs-vsctl.c b/utilities/ovs-vsctl.c
index 14f5cb92e..1032089fc 100644
--- a/utilities/ovs-vsctl.c
+++ b/utilities/ovs-vsctl.c
@@ -1100,14 +1100,14 @@ cmd_emer_reset(struct ctl_context *ctx)
 const struct ovsrec_bridge *br;
 const struct ovsrec_port *port;
 const struct ovsrec_interface *iface;
-const struct ovsrec_mirror *mirror, *next_mirror;
-const struct ovsrec_controller *ctrl, *next_ctrl;
-const struct ovsrec_manager *mgr, *next_mgr;
-const struct ovsrec_netflow *nf, *next_nf;
-const struct ovsrec_ssl *ssl, *next_ssl;
-const struct ovsrec_sflow *sflow, *next_sflow;
-const struct ovsrec_ipfix *ipfix, *next_ipfix;
-const struct ovsrec_flow_sample_collector_set *fscset, *next_fscset;
+const struct ovsrec_mirror *mirror;
+const struct ovsrec_controller *ctrl;
+const struct ovsrec_manager *mgr;
+const struct ovsrec_netflow *nf;
+const struct ovsrec_ssl *ssl;
+const struct ovsrec_sflow *sflow;
+const struct ovsrec_ipfix *ipfix;
+const struct ovsrec_flow_sample_collector_set *fscset;
 
 /* Reset the Open_vSwitch table. */
 ovsrec_open_vswitch_set_manager_options(vsctl_ctx->ovs, NULL, 0);
@@ -1145,35 +1145,35 @@ cmd_emer_reset(struct ctl_context *ctx)
 ovsrec_interface_set_ingress_policing_burst(iface, 0);
 }
 
-OVSREC_MIRROR_FOR_EACH_SAFE (mirror, next_mirror, idl) {
+OVSREC_MIRROR_FOR_EACH_SAFE (mirror, idl) {
 ovsrec_mirror_delete(mirror);
 }
 
-OVSREC_CONTROLLER_FOR_EACH_SAFE (ctrl, next_ctrl, idl) {
+OVSREC_CONTROLLER_FOR_EACH_SAFE (ctrl, idl) {
 ovsrec_controller_delete(ctrl);
 }
 
-OVSREC_MANAGER_FOR_EACH_SAFE (mgr, next_mgr, idl) {
+OVSREC_MANAGER_FOR_EACH_SAFE (mgr, idl) {
 ovsrec_manager_delete(mgr);
 }
 
-OVSREC_NETFLOW_FOR_EACH_SAFE (nf, next_nf, idl) {
+OVSREC_NETFLOW_FOR_EACH_SAFE (nf, idl) {
 ovsrec_netflow_delete(nf);
 }
 
-OVSREC_SSL_FOR_EACH_SAFE (ssl, next_ssl, idl) {
+

[ovs-dev] [PATCH v2 12/16] rculist: use multi-variable helpers for loop macros

2022-02-14 Thread Adrian Moreno
Use multi-variable iteration helpers to rewrite rculist loops macros.

There is an important behavior change compared with the previous
implementation: When the loop ends normally (i.e: not via "break;"),
the object pointer provided by the user is NULL. This is safer
because it's not guaranteed that it would end up pointing a valid
address.

Signed-off-by: Adrian Moreno 
---
 lib/rculist.h | 79 ---
 1 file changed, 49 insertions(+), 30 deletions(-)

diff --git a/lib/rculist.h b/lib/rculist.h
index 1072b87af..896aaf4a6 100644
--- a/lib/rculist.h
+++ b/lib/rculist.h
@@ -365,35 +365,54 @@ rculist_is_singleton_protected(const struct rculist *list)
 return list_next == list->prev && list_next != list;
 }
 
-#define RCULIST_FOR_EACH(ITER, MEMBER, RCULIST) \
-for (INIT_CONTAINER(ITER, rculist_next(RCULIST), MEMBER);   \
- &(ITER)->MEMBER != (RCULIST);  \
- ASSIGN_CONTAINER(ITER, rculist_next(&(ITER)->MEMBER), MEMBER))
-#define RCULIST_FOR_EACH_CONTINUE(ITER, MEMBER, RCULIST)\
-for (ASSIGN_CONTAINER(ITER, rculist_next(&(ITER)->MEMBER), MEMBER); \
- &(ITER)->MEMBER != (RCULIST);  \
- ASSIGN_CONTAINER(ITER, rculist_next(&(ITER)->MEMBER), MEMBER))
-
-#define RCULIST_FOR_EACH_REVERSE_PROTECTED(ITER, MEMBER, RCULIST)   \
-for (INIT_CONTAINER(ITER, (RCULIST)->prev, MEMBER); \
- &(ITER)->MEMBER != (RCULIST);  \
- ASSIGN_CONTAINER(ITER, (ITER)->MEMBER.prev, MEMBER))
-#define RCULIST_FOR_EACH_REVERSE_PROTECTED_CONTINUE(ITER, MEMBER, RCULIST) \
-for (ASSIGN_CONTAINER(ITER, (ITER)->MEMBER.prev, MEMBER);   \
- &(ITER)->MEMBER != (RCULIST);  \
- ASSIGN_CONTAINER(ITER, (ITER)->MEMBER.prev, MEMBER))
-
-#define RCULIST_FOR_EACH_PROTECTED(ITER, MEMBER, RCULIST)   \
-for (INIT_CONTAINER(ITER, rculist_next_protected(RCULIST), MEMBER); \
- &(ITER)->MEMBER != (RCULIST);  \
- ASSIGN_CONTAINER(ITER, rculist_next_protected(&(ITER)->MEMBER), \
-  MEMBER))
-
-#define RCULIST_FOR_EACH_SAFE_PROTECTED(ITER, NEXT, MEMBER, RCULIST)\
-for (INIT_CONTAINER(ITER, rculist_next_protected(RCULIST), MEMBER); \
- (&(ITER)->MEMBER != (RCULIST)  \
-  ? INIT_CONTAINER(NEXT, rculist_next_protected(&(ITER)->MEMBER), \
-   MEMBER), 1 : 0); \
- (ITER) = (NEXT))
+#define RCULIST_FOR_EACH(ITER, MEMBER, RCULIST)   \
+for (INIT_MULTIVAR(ITER, MEMBER, rculist_next(RCULIST));  \
+ CONDITION_MULTIVAR(ITER, MEMBER, ITER_VAR(ITER) != (RCULIST));   \
+ UPDATE_MULTIVAR(ITER, ITER_VAR(ITER) = rculist_next(ITER_VAR(ITER
+
+#define RCULIST_FOR_EACH_CONTINUE(ITER, MEMBER, RCULIST)  \
+for (INIT_MULTIVAR(ITER, MEMBER, rculist_next(&(ITER)->MEMBER));  \
+ CONDITION_MULTIVAR(ITER, MEMBER, ITER_VAR(ITER) != (RCULIST));   \
+ UPDATE_MULTIVAR(ITER, ITER_VAR(ITER) = rculist_next(ITER_VAR(ITER
+
+#define RCULIST_FOR_EACH_REVERSE_PROTECTED(ITER, MEMBER, RCULIST) \
+for (INIT_MULTIVAR(ITER, MEMBER, (RCULIST)->prev);\
+ CONDITION_MULTIVAR(ITER, MEMBER, ITER_VAR(ITER) != (RCULIST));   \
+ UPDATE_MULTIVAR(ITER, ITER_VAR(ITER) = ITER_VAR(VAR).prev))
+
+#define RCULIST_FOR_EACH_REVERSE_PROTECTED_CONTINUE(ITER, MEMBER, RCULIST)\
+for (INIT_MULTIVAR(ITER, MEMBER, (ITER)->MEMBER.prev);\
+ CONDITION_MULTIVAR(ITER, MEMBER, ITER_VAR(ITER) != (RCULIST));   \
+ UPDATE_MULTIVAR(ITER, ITER_VAR(ITER) = ITER_VAR(VAR).prev))
+
+#define RCULIST_FOR_EACH_PROTECTED(ITER, MEMBER, RCULIST) \
+for (INIT_MULTIVAR(ITER, MEMBER, rculist_next_protected(RCULIST));\
+ CONDITION_MULTIVAR(ITER, MEMBER, ITER_VAR(ITER) != (RCULIST));   \
+ UPDATE_MULTIVAR(ITER,\
+ ITER_VAR(ITER) = rculist_next_protected(ITER_VAR(ITER))) \
+
+#define RCULIST_FOR_EACH_SAFE_SHORT_PROTECTED(ITER, MEMBER, RCULIST)  \
+for (INIT_MULTIVAR_SAFE_SHORT(ITER, MEMBER,   \
+  rculist_next_protected(RCULIST));   \
+ CONDITION_MULTIVAR_SAFE_SHORT(ITER, MEMBER,  \
+   ITER_VAR(ITER) != (RCULIST),   \
+ ITER_NEXT_VAR(ITER) = rculist_next_protected(ITER_VAR(VAR)));\
+UPDATE_MULTIVAR_SHORT(ITER))
+
+#define RCULIST_FOR_EACH_SAFE_LONG_PROTECTED(ITER, NEXT, MEMBER, RCULIST) \
+for 

[ovs-dev] [PATCH v2 16/16] sset: add SHORT version of SAFE loop macros

2022-02-14 Thread Adrian Moreno
Add SHORT version of SAFE loop macros and overload the current macro
name to keep backwards compatibility.

Signed-off-by: Adrian Moreno 
---
 lib/sset.c |  8 
 lib/sset.h | 16 +++-
 2 files changed, 19 insertions(+), 5 deletions(-)

diff --git a/lib/sset.c b/lib/sset.c
index b2e3f43ec..c3197e305 100644
--- a/lib/sset.c
+++ b/lib/sset.c
@@ -212,9 +212,9 @@ sset_add_array(struct sset *set, char **names, size_t n)
 void
 sset_clear(struct sset *set)
 {
-const char *name, *next;
+const char *name;
 
-SSET_FOR_EACH_SAFE (name, next, set) {
+SSET_FOR_EACH_SAFE (name, set) {
 sset_delete(set, SSET_NODE_FROM_NAME(name));
 }
 }
@@ -320,9 +320,9 @@ sset_at_position(const struct sset *set, struct 
sset_position *pos)
 void
 sset_intersect(struct sset *a, const struct sset *b)
 {
-const char *name, *next;
+const char *name;
 
-SSET_FOR_EACH_SAFE (name, next, a) {
+SSET_FOR_EACH_SAFE (name, a) {
 if (!sset_contains(b, name)) {
 sset_delete(a, SSET_NODE_FROM_NAME(name));
 }
diff --git a/lib/sset.h b/lib/sset.h
index f0bb8b534..3a028c012 100644
--- a/lib/sset.h
+++ b/lib/sset.h
@@ -87,13 +87,27 @@ void sset_intersect(struct sset *, const struct sset *);
  NAME != NULL;  \
  (NAME) = SSET_NEXT(SSET, NAME))
 
-#define SSET_FOR_EACH_SAFE(NAME, NEXT, SSET)\
+#define SSET_FOR_EACH_SAFE_LONG(NAME, NEXT, SSET)   \
 for ((NAME) = SSET_FIRST(SSET); \
  (NAME != NULL  \
   ? (NEXT) = SSET_NEXT(SSET, NAME), true\
   : false); \
  (NAME) = (NEXT))
 
+#define SSET_FOR_EACH_SAFE_SHORT(NAME, SSET)   \
+for (OVS_TYPEOF(NAME) NAME__next = \
+ ((NAME) = SSET_FIRST(SSET), NULL);\
+ (NAME != NULL \
+  ? (NAME__next = SSET_NEXT(SSET, NAME), true) \
+  : (NAME__next = NULL, false));   \
+ (NAME) = NAME__next)
+
+#define SSET_GET_SAFE_MACRO(_1, _2, _3, NAME, ...) NAME
+#define SSET_FOR_EACH_SAFE(...)  \
+SSET_GET_SAFE_MACRO(__VA_ARGS__, \
+   SSET_FOR_EACH_SAFE_LONG,  \
+   SSET_FOR_EACH_SAFE_SHORT)(__VA_ARGS__)
+
 const char **sset_array(const struct sset *);
 const char **sset_sort(const struct sset *);
 
-- 
2.34.1

___
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev


Re: [ovs-dev] [PATCH 10/16] hindex: use multi-variable iterators

2022-02-14 Thread 0-day Robot
Bleep bloop.  Greetings Adrian Moreno, 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: Use ovs_assert() in place of assert()
#92 FILE: tests/test-hindex.c:269:
assert(next == NULL);

ERROR: Use ovs_assert() in place of assert()
#94 FILE: tests/test-hindex.c:271:
assert(>node == hindex_next(, >node));

ERROR: Use ovs_assert() in place of assert()
#103 FILE: tests/test-hindex.c:289:
assert(next == NULL);

Lines checked: 110, Warnings: 0, Errors: 3


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 v2 15/16] sparse: bump recommended version and include headers

2022-02-14 Thread Adrian Moreno
It seems versions older than 0.6.2 generate false positives. Bump the
recommended version and make sure we uset the headers from the

Co-authored-by: Dumitru Ceara 
Signed-off-by: Adrian Moreno 
---
 Documentation/intro/install/general.rst | 2 +-
 acinclude.m4| 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/Documentation/intro/install/general.rst 
b/Documentation/intro/install/general.rst
index c4300cd53..a297aadac 100644
--- a/Documentation/intro/install/general.rst
+++ b/Documentation/intro/install/general.rst
@@ -169,7 +169,7 @@ other than plain text, only if you have the following:
 If you are going to extensively modify Open vSwitch, consider installing the
 following to obtain better warnings:
 
-- "sparse" version 0.5.1 or later
+- "sparse" version 0.6.2 or later
   (https://git.kernel.org/pub/scm/devel/sparse/sparse.git/).
 
 - GNU make.
diff --git a/acinclude.m4 b/acinclude.m4
index 0c360fd1e..f704bf36c 100644
--- a/acinclude.m4
+++ b/acinclude.m4
@@ -1424,7 +1424,7 @@ AC_DEFUN([OVS_ENABLE_SPARSE],
: ${SPARSE=sparse}
AC_SUBST([SPARSE])
AC_CONFIG_COMMANDS_PRE(
- [CC='$(if $(C:0=),env REAL_CC="'"$CC"'" CHECK="$(SPARSE) $(SPARSE_WERROR) 
-I $(top_srcdir)/include/sparse $(SPARSEFLAGS) $(SPARSE_EXTRA_INCLUDES) " cgcc 
$(CGCCFLAGS),'"$CC"')'])
+ [CC='$(if $(C:0=),env REAL_CC="'"$CC"'" CHECK="$(SPARSE) $(SPARSE_WERROR) 
-I $(top_srcdir)/include/sparse -I $(top_srcdir)/include $(SPARSEFLAGS) 
$(SPARSE_EXTRA_INCLUDES) " cgcc $(CGCCFLAGS),'"$CC"')'])
 
AC_ARG_ENABLE(
  [sparse],
-- 
2.34.1

___
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev


[ovs-dev] [PATCH v2 05/16] list: use short version of safe loops if possible

2022-02-14 Thread Adrian Moreno
Using the SHORT version of the *_SAFE loops makes the code cleaner
and less error-prone. So, use the SHORT version and remove the extra
variable when possible.

In order to be able to use both long and short versions without changing
the name of the macro for all the clients, overload the existing name
and select the appropriate version depending on the number of arguments.

Signed-off-by: Adrian Moreno 
---
 include/openvswitch/list.h   | 32 +--
 lib/conntrack.c  |  4 ++--
 lib/fat-rwlock.c |  4 ++--
 lib/id-fpool.c   |  3 +--
 lib/ipf.c| 22 ++---
 lib/lldp/lldpd-structs.c |  7 +++
 lib/lldp/lldpd.c |  8 
 lib/mcast-snooping.c | 12 ++--
 lib/netdev-afxdp.c   |  4 ++--
 lib/netdev-dpdk.c|  4 ++--
 lib/ofp-msgs.c   |  4 ++--
 lib/ovs-lldp.c   | 12 ++--
 lib/ovsdb-idl.c  | 30 ++---
 lib/seq.c|  4 ++--
 lib/tnl-ports.c  | 16 
 lib/unixctl.c|  8 
 lib/vconn.c  |  4 ++--
 ofproto/connmgr.c|  8 
 ofproto/ofproto-dpif-ipfix.c |  4 ++--
 ofproto/ofproto-dpif-trace.c |  4 ++--
 ofproto/ofproto-dpif-xlate.c |  4 ++--
 ofproto/ofproto-dpif.c   | 24 +++
 ovsdb/jsonrpc-server.c   | 16 
 ovsdb/monitor.c  | 24 +++
 ovsdb/ovsdb.c|  4 ++--
 ovsdb/raft.c | 15 +++
 ovsdb/transaction-forward.c  |  6 +++---
 ovsdb/transaction.c  | 28 +--
 ovsdb/trigger.c  |  4 ++--
 tests/test-list.c| 37 
 utilities/ovs-ofctl.c|  4 ++--
 utilities/ovs-vsctl.c|  8 
 vswitchd/bridge.c| 16 
 vtep/vtep-ctl.c  | 12 ++--
 34 files changed, 228 insertions(+), 168 deletions(-)

diff --git a/include/openvswitch/list.h b/include/openvswitch/list.h
index 997afc0e4..c6941e896 100644
--- a/include/openvswitch/list.h
+++ b/include/openvswitch/list.h
@@ -93,7 +93,8 @@ static inline bool ovs_list_is_short(const struct ovs_list *);
  CONDITION_MULTIVAR(VAR, MEMBER, ITER_VAR(VAR) != (LIST));\
  UPDATE_MULTIVAR(VAR, (ITER_VAR(VAR) = ITER_VAR(VAR)->prev)))
 
-#define LIST_FOR_EACH_REVERSE_SAFE(VAR, PREV, MEMBER, LIST)   \
+/* LONG version of SAFE iterators */
+#define LIST_FOR_EACH_REVERSE_SAFE_LONG(VAR, PREV, MEMBER, LIST) \
 for (INIT_MULTIVAR_SAFE_LONG(VAR, PREV, MEMBER, (LIST)->prev);\
  CONDITION_MULTIVAR_SAFE_LONG(VAR, PREV, MEMBER,  \
   ITER_VAR(VAR) != (LIST),\
@@ -101,7 +102,7 @@ static inline bool ovs_list_is_short(const struct ovs_list 
*);
   ITER_VAR(PREV) != (LIST));  \
  UPDATE_MULTIVAR_SAFE_LONG(VAR, PREV))
 
-#define LIST_FOR_EACH_SAFE(VAR, NEXT, MEMBER, LIST)   \
+#define LIST_FOR_EACH_SAFE_LONG(VAR, NEXT, MEMBER, LIST)  \
 for (INIT_MULTIVAR_SAFE_LONG(VAR, NEXT, MEMBER, (LIST)->next);\
  CONDITION_MULTIVAR_SAFE_LONG(VAR, NEXT, MEMBER,  \
   ITER_VAR(VAR) != (LIST),\
@@ -109,6 +110,33 @@ static inline bool ovs_list_is_short(const struct ovs_list 
*);
   ITER_VAR(NEXT) != (LIST));  \
  UPDATE_MULTIVAR_SAFE_LONG(VAR, NEXT))
 
+/* SHORT version of SAFE iterators */
+#define LIST_FOR_EACH_REVERSE_SAFE_SHORT(VAR, MEMBER, LIST)   \
+for (INIT_MULTIVAR_SAFE_SHORT(VAR, MEMBER, (LIST)->prev); \
+ CONDITION_MULTIVAR_SAFE_SHORT(VAR, MEMBER,   \
+   ITER_VAR(VAR) != (LIST),   \
+ ITER_NEXT_VAR(VAR) = ITER_VAR(VAR)->prev);   \
+ UPDATE_MULTIVAR_SAFE_SHORT(VAR))
+
+#define LIST_FOR_EACH_SAFE_SHORT(VAR, MEMBER, LIST)   \
+for (INIT_MULTIVAR_SAFE_SHORT(VAR, MEMBER, (LIST)->next); \
+ CONDITION_MULTIVAR_SAFE_SHORT(VAR, MEMBER,   \
+   ITER_VAR(VAR) != (LIST),   \
+ ITER_NEXT_VAR(VAR) = ITER_VAR(VAR)->next);   \
+ UPDATE_MULTIVAR_SAFE_SHORT(VAR))
+
+/* Select the right SAFE macro depending on the number of arguments .*/
+#define LIST_GET_SAFE_MACRO(_1, _2, _3, _4, NAME, ...) NAME
+#define LIST_FOR_EACH_SAFE(...)   \
+LIST_GET_SAFE_MACRO(__VA_ARGS__,  \

[ovs-dev] [PATCH v2 09/16] cmap: use multi-variable iterators

2022-02-14 Thread Adrian Moreno
Re-write cmap's loops using multi-variable helpers.

For iterators based on cmap_cursor, we just need to make sure the NODE
variable is not used after the loop, so we set it to NULL.

Signed-off-by: Adrian Moreno 
---
 lib/cmap.h| 24 ++--
 tests/test-cmap.c |  3 +++
 2 files changed, 17 insertions(+), 10 deletions(-)

diff --git a/lib/cmap.h b/lib/cmap.h
index c502d2311..8c06d7123 100644
--- a/lib/cmap.h
+++ b/lib/cmap.h
@@ -108,6 +108,8 @@ size_t cmap_replace(struct cmap *, struct cmap_node 
*old_node,
  *
  * CMAP and HASH are evaluated only once.  NODE is evaluated many times.
  *
+ * After a normal exit of the loop (not through a "break;" statement) NODE is
+ * NULL.
  *
  * Thread-safety
  * =
@@ -128,15 +130,17 @@ size_t cmap_replace(struct cmap *, struct cmap_node 
*old_node,
  * CMAP_FOR_EACH_WITH_HASH_PROTECTED may only be used if CMAP is guaranteed not
  * to change during iteration.  It may be very slightly faster.
  */
-#define CMAP_NODE_FOR_EACH(NODE, MEMBER, CMAP_NODE) \
-for (INIT_CONTAINER(NODE, CMAP_NODE, MEMBER);   \
- (NODE) != OBJECT_CONTAINING(NULL, NODE, MEMBER);   \
- ASSIGN_CONTAINER(NODE, cmap_node_next(&(NODE)->MEMBER), MEMBER))
-#define CMAP_NODE_FOR_EACH_PROTECTED(NODE, MEMBER, CMAP_NODE)   \
-for (INIT_CONTAINER(NODE, CMAP_NODE, MEMBER);   \
- (NODE) != OBJECT_CONTAINING(NULL, NODE, MEMBER);   \
- ASSIGN_CONTAINER(NODE, cmap_node_next_protected(&(NODE)->MEMBER), \
-  MEMBER))
+#define CMAP_NODE_FOR_EACH(NODE, MEMBER, CMAP_NODE)\
+for (INIT_MULTIVAR(NODE, MEMBER, CMAP_NODE);   \
+ CONDITION_MULTIVAR(NODE, MEMBER, ITER_VAR(NODE) != NULL); \
+ UPDATE_MULTIVAR(NODE, \
+ ITER_VAR(NODE) = cmap_node_next(ITER_VAR(NODE
+#define CMAP_NODE_FOR_EACH_PROTECTED(NODE, MEMBER, CMAP_NODE)  \
+for (INIT_MULTIVAR(NODE, MEMBER, CMAP_NODE);   \
+ CONDITION_MULTIVAR(NODE, MEMBER, ITER_VAR(NODE) != NULL); \
+ UPDATE_MULTIVAR(NODE, \
+ITER_VAR(NODE) = cmap_node_next_protected(ITER_VAR(NODE
+
 #define CMAP_FOR_EACH_WITH_HASH(NODE, MEMBER, HASH, CMAP)   \
 CMAP_NODE_FOR_EACH(NODE, MEMBER, cmap_find(CMAP, HASH))
 #define CMAP_FOR_EACH_WITH_HASH_PROTECTED(NODE, MEMBER, HASH, CMAP) \
@@ -223,7 +227,7 @@ unsigned long cmap_find_batch(const struct cmap *cmap, 
unsigned long map,
  ? (INIT_CONTAINER(NODE, (CURSOR)->node, MEMBER),   \
 cmap_cursor_advance(CURSOR),\
 true)   \
- : false)
+ : (NODE = NULL, false))
 
 #define CMAP_CURSOR_FOR_EACH(NODE, MEMBER, CURSOR, CMAP)\
 for (*(CURSOR) = cmap_cursor_start(CMAP);   \
diff --git a/tests/test-cmap.c b/tests/test-cmap.c
index bc1f45642..588a5dea6 100644
--- a/tests/test-cmap.c
+++ b/tests/test-cmap.c
@@ -74,6 +74,7 @@ check_cmap(struct cmap *cmap, const int values[], size_t n,
 cmap_values[i++] = e->value;
 }
 assert(i == n);
+assert(e == NULL);
 
 /* Here we test iteration with cmap_next_position() */
 i = 0;
@@ -107,6 +108,7 @@ check_cmap(struct cmap *cmap, const int values[], size_t n,
 count += e->value == values[i];
 }
 assert(count == 1);
+assert(e == NULL);
 }
 
 /* Check that all the values are there in batched lookup. */
@@ -130,6 +132,7 @@ check_cmap(struct cmap *cmap, const int values[], size_t n,
 CMAP_NODE_FOR_EACH (e, node, nodes[k]) {
 count += e->value == values[i + k];
 }
+assert(e == NULL);
 }
 assert(count == j); /* j elements in a batch. */
 }
-- 
2.34.1

___
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev


[ovs-dev] [PATCH v2 13/16] vtep: use _SAFE iterator if freeing the iterator

2022-02-14 Thread Adrian Moreno
The _SAFE version of the iterator allows the user to free the iterator
structure safely.

Signed-off-by: Adrian Moreno 
---
 vtep/vtep-ctl.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/vtep/vtep-ctl.c b/vtep/vtep-ctl.c
index 99c4adcd5..685b0007a 100644
--- a/vtep/vtep-ctl.c
+++ b/vtep/vtep-ctl.c
@@ -738,7 +738,7 @@ del_ploc_from_mcast_mac(struct vtep_ctl_mcast_mac 
*mcast_mac,
 {
 struct vtep_ctl_ploc *ploc;
 
-LIST_FOR_EACH (ploc, locators_node, _mac->locators) {
+LIST_FOR_EACH_SAFE (ploc, locators_node, _mac->locators) {
 if (ploc->ploc_cfg == ploc_cfg) {
 ovs_list_remove(>locators_node);
 free(ploc);
-- 
2.34.1

___
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev


[ovs-dev] [PATCH v2 06/16] hmap: use multi-variable helpers for hmap loops

2022-02-14 Thread Adrian Moreno
Rewrite hmap's loops using multi-variable helpers.

For SAFE loops, use the LONG version of the multi-variable macros to
keep backwards compatibility.

Signed-off-by: Adrian Moreno 
---
 include/openvswitch/hmap.h | 62 --
 lib/ovs-numa.h |  4 +--
 tests/test-hmap.c  |  9 ++
 3 files changed, 43 insertions(+), 32 deletions(-)

diff --git a/include/openvswitch/hmap.h b/include/openvswitch/hmap.h
index 4e001cc69..356ea3582 100644
--- a/include/openvswitch/hmap.h
+++ b/include/openvswitch/hmap.h
@@ -134,17 +134,17 @@ struct hmap_node *hmap_random_node(const struct hmap *);
  * without using 'break', NODE will be NULL.  This is true for all of the
  * HMAP_FOR_EACH_*() macros.
  */
-#define HMAP_FOR_EACH_WITH_HASH(NODE, MEMBER, HASH, HMAP)   \
-for (INIT_CONTAINER(NODE, hmap_first_with_hash(HMAP, HASH), MEMBER); \
- (NODE != OBJECT_CONTAINING(NULL, NODE, MEMBER))\
- || ((NODE = NULL), false); \
- ASSIGN_CONTAINER(NODE, hmap_next_with_hash(&(NODE)->MEMBER),   \
-  MEMBER))
-#define HMAP_FOR_EACH_IN_BUCKET(NODE, MEMBER, HASH, HMAP)   \
-for (INIT_CONTAINER(NODE, hmap_first_in_bucket(HMAP, HASH), MEMBER); \
- (NODE != OBJECT_CONTAINING(NULL, NODE, MEMBER))\
- || ((NODE = NULL), false); \
- ASSIGN_CONTAINER(NODE, hmap_next_in_bucket(&(NODE)->MEMBER), MEMBER))
+#define HMAP_FOR_EACH_WITH_HASH(NODE, MEMBER, HASH, HMAP) \
+for (INIT_MULTIVAR(NODE, MEMBER, hmap_first_with_hash(HMAP, HASH));   \
+ CONDITION_MULTIVAR(NODE, MEMBER, ITER_VAR(NODE) != NULL);\
+ UPDATE_MULTIVAR(NODE,\
+ ITER_VAR(NODE) = hmap_next_with_hash(ITER_VAR(NODE
+
+#define HMAP_FOR_EACH_IN_BUCKET(NODE, MEMBER, HASH, HMAP) \
+for (INIT_MULTIVAR(NODE, MEMBER, hmap_first_in_bucket(HMAP, HASH));   \
+ CONDITION_MULTIVAR(NODE, MEMBER, ITER_VAR(NODE) != NULL);\
+ UPDATE_MULTIVAR(NODE,\
+ ITER_VAR(NODE) = hmap_next_in_bucket(ITER_VAR(NODE
 
 static inline struct hmap_node *hmap_first_with_hash(const struct hmap *,
  size_t hash);
@@ -170,33 +170,35 @@ bool hmap_contains(const struct hmap *, const struct 
hmap_node *);
 /* Iterates through every node in HMAP. */
 #define HMAP_FOR_EACH(NODE, MEMBER, HMAP) \
 HMAP_FOR_EACH_INIT(NODE, MEMBER, HMAP, (void) 0)
-#define HMAP_FOR_EACH_INIT(NODE, MEMBER, HMAP, ...) \
-for (INIT_CONTAINER(NODE, hmap_first(HMAP), MEMBER), __VA_ARGS__;   \
- (NODE != OBJECT_CONTAINING(NULL, NODE, MEMBER))\
- || ((NODE = NULL), false); \
- ASSIGN_CONTAINER(NODE, hmap_next(HMAP, &(NODE)->MEMBER), MEMBER))
+#define HMAP_FOR_EACH_INIT(NODE, MEMBER, HMAP, ...)   \
+for (INIT_MULTIVAR_EXP(NODE, MEMBER, hmap_first(HMAP),  __VA_ARGS__); \
+ CONDITION_MULTIVAR(NODE, MEMBER, ITER_VAR(NODE) != NULL);\
+ UPDATE_MULTIVAR(NODE,\
+ ITER_VAR(NODE) = hmap_next(HMAP, ITER_VAR(NODE   \
 
 /* Safe when NODE may be freed (not needed when NODE may be removed from the
  * hash map but its members remain accessible and intact). */
 #define HMAP_FOR_EACH_SAFE(NODE, NEXT, MEMBER, HMAP) \
-HMAP_FOR_EACH_SAFE_INIT(NODE, NEXT, MEMBER, HMAP, (void) 0)
-#define HMAP_FOR_EACH_SAFE_INIT(NODE, NEXT, MEMBER, HMAP, ...)  \
-for (INIT_CONTAINER(NODE, hmap_first(HMAP), MEMBER), __VA_ARGS__;   \
- ((NODE != OBJECT_CONTAINING(NULL, NODE, MEMBER))   \
-  || ((NODE = NULL), false) \
-  ? INIT_CONTAINER(NEXT, hmap_next(HMAP, &(NODE)->MEMBER), MEMBER), 1 \
-  : 0); \
- (NODE) = (NEXT))
+HMAP_FOR_EACH_SAFE_INIT (NODE, NEXT, MEMBER, HMAP, (void) NEXT)
+
+#define HMAP_FOR_EACH_SAFE_INIT(NODE, NEXT, MEMBER, HMAP, ...)\
+for (INIT_MULTIVAR_SAFE_LONG_EXP(NODE, NEXT, MEMBER, hmap_first(HMAP),\
+  __VA_ARGS__);   \
+ CONDITION_MULTIVAR_SAFE_LONG(NODE, NEXT, MEMBER, \
+  ITER_VAR(NODE) != NULL, \
+ITER_VAR(NEXT) = hmap_next(HMAP, ITER_VAR(NODE)), \
+  ITER_VAR(NEXT) != NULL);\
+ UPDATE_MULTIVAR_SAFE_LONG(NODE, NEXT))
 
 /* Continues an iteration from just after NODE. */
 

[ovs-dev] [PATCH v2 07/16] hmap: implement UB-safe hmap pop iterator

2022-02-14 Thread Adrian Moreno
HMAP_FOR_EACH_POP iterator has an additional difficulty, which is the
use of two iterator variables of different types.

In order to re-write this loop in a UB-safe manner, create a iterator
struct to be used as loop variable.

Signed-off-by: Adrian Moreno 
---
 include/openvswitch/hmap.h | 31 +++
 tests/test-hmap.c  |  1 +
 2 files changed, 20 insertions(+), 12 deletions(-)

diff --git a/include/openvswitch/hmap.h b/include/openvswitch/hmap.h
index 356ea3582..283407e3a 100644
--- a/include/openvswitch/hmap.h
+++ b/include/openvswitch/hmap.h
@@ -200,26 +200,33 @@ bool hmap_contains(const struct hmap *, const struct 
hmap_node *);
  UPDATE_MULTIVAR(NODE,\
  ITER_VAR(NODE) = hmap_next(HMAP, ITER_VAR(NODE   \
 
-static inline struct hmap_node *
-hmap_pop_helper__(struct hmap *hmap, size_t *bucket) {
+struct hmap_pop_helper_iter__ {
+size_t bucket;
+struct hmap_node *node;
+};
+
+static inline void
+hmap_pop_helper__(struct hmap *hmap, struct hmap_pop_helper_iter__ *iter) {
 
-for (; *bucket <= hmap->mask; (*bucket)++) {
-struct hmap_node *node = hmap->buckets[*bucket];
+for (; iter->bucket <= hmap->mask; (iter->bucket)++) {
+struct hmap_node *node = hmap->buckets[iter->bucket];
 
 if (node) {
 hmap_remove(hmap, node);
-return node;
+iter->node = node;
+return;
 }
 }
-
-return NULL;
+iter->node = NULL;
 }
 
-#define HMAP_FOR_EACH_POP(NODE, MEMBER, HMAP)   \
-for (size_t bucket__ = 0;   \
- INIT_CONTAINER(NODE, hmap_pop_helper__(HMAP, __), MEMBER),  \
- (NODE != OBJECT_CONTAINING(NULL, NODE, MEMBER))\
- || ((NODE = NULL), false);)
+#define HMAP_FOR_EACH_POP(NODE, MEMBER, HMAP) \
+for (struct hmap_pop_helper_iter__ ITER_VAR(NODE) = { 0, NULL };  \
+ hmap_pop_helper__(HMAP, _VAR(NODE)),\
+ (ITER_VAR(NODE).node != NULL) ?  \
+(((NODE) = OBJECT_CONTAINING(ITER_VAR(NODE).node, \
+ NODE, MEMBER)),1):   \
+(((NODE) = NULL), 0);)
 
 static inline struct hmap_node *hmap_first(const struct hmap *);
 static inline struct hmap_node *hmap_next(const struct hmap *,
diff --git a/tests/test-hmap.c b/tests/test-hmap.c
index a40ac8953..47b475538 100644
--- a/tests/test-hmap.c
+++ b/tests/test-hmap.c
@@ -317,6 +317,7 @@ test_hmap_for_each_pop(hash_func *hash)
 i++;
 }
 assert(i == n);
+assert(e == NULL);
 
 hmap_destroy();
 }
-- 
2.34.1

___
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev


[ovs-dev] [PATCH v2 04/16] list: ensure iterator is NULL after pop loop

2022-02-14 Thread Adrian Moreno
After the loop ends, the iterator is not guaranteed to point to a valid
object and should not be used. Make it NULL to avoid undefined behavior.

Signed-off-by: Adrian Moreno 
---
 include/openvswitch/list.h | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/include/openvswitch/list.h b/include/openvswitch/list.h
index 7cc1419a1..997afc0e4 100644
--- a/include/openvswitch/list.h
+++ b/include/openvswitch/list.h
@@ -110,8 +110,9 @@ static inline bool ovs_list_is_short(const struct ovs_list 
*);
  UPDATE_MULTIVAR_SAFE_LONG(VAR, NEXT))
 
 #define LIST_FOR_EACH_POP(ITER, MEMBER, LIST) \
-while (!ovs_list_is_empty(LIST)   \
-   && (INIT_CONTAINER(ITER, ovs_list_pop_front(LIST), MEMBER), 1))
+while (!ovs_list_is_empty(LIST) ? \
+   (INIT_CONTAINER(ITER, ovs_list_pop_front(LIST), MEMBER), 1) :  \
+   (ITER = NULL, 0))
 
 /* Inline implementations. */
 
-- 
2.34.1

___
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev


[ovs-dev] [PATCH v2 03/16] list: use multi-variable helpers for list loops

2022-02-14 Thread Adrian Moreno
Use multi-variable iteration helpers to rewrite non-safe loops.

There is an important behavior change compared with the previous
implementation: When the loop ends normally (i.e: not via "break;"), the
object pointer provided by the user is NULL. This is safer because it's
not guaranteed that it would end up pointing a valid address.

Clang-analyzer has successfully picked the potential null-pointer
dereference on the code that triggered this change (bond.c) and nothing
else has been detected.

For _SAFE loops, use the LONG version for backwards compatibility.

Signed-off-by: Adrian Moreno 
---
 include/openvswitch/list.h | 69 +-
 ofproto/bond.c |  2 +-
 tests/test-list.c  | 15 +++--
 3 files changed, 52 insertions(+), 34 deletions(-)

diff --git a/include/openvswitch/list.h b/include/openvswitch/list.h
index 8ad5eeb32..7cc1419a1 100644
--- a/include/openvswitch/list.h
+++ b/include/openvswitch/list.h
@@ -72,36 +72,45 @@ static inline bool ovs_list_is_empty(const struct ovs_list 
*);
 static inline bool ovs_list_is_singleton(const struct ovs_list *);
 static inline bool ovs_list_is_short(const struct ovs_list *);
 
-#define LIST_FOR_EACH(ITER, MEMBER, LIST)   \
-for (INIT_CONTAINER(ITER, (LIST)->next, MEMBER);\
- &(ITER)->MEMBER != (LIST); \
- ASSIGN_CONTAINER(ITER, (ITER)->MEMBER.next, MEMBER))
-#define LIST_FOR_EACH_CONTINUE(ITER, MEMBER, LIST)  \
-for (ASSIGN_CONTAINER(ITER, (ITER)->MEMBER.next, MEMBER); \
- &(ITER)->MEMBER != (LIST); \
- ASSIGN_CONTAINER(ITER, (ITER)->MEMBER.next, MEMBER))
-#define LIST_FOR_EACH_REVERSE(ITER, MEMBER, LIST)   \
-for (INIT_CONTAINER(ITER, (LIST)->prev, MEMBER);\
- &(ITER)->MEMBER != (LIST); \
- ASSIGN_CONTAINER(ITER, (ITER)->MEMBER.prev, MEMBER))
-#define LIST_FOR_EACH_REVERSE_SAFE(ITER, PREV, MEMBER, LIST)\
-for (INIT_CONTAINER(ITER, (LIST)->prev, MEMBER);\
- (&(ITER)->MEMBER != (LIST) \
-  ? INIT_CONTAINER(PREV, (ITER)->MEMBER.prev, MEMBER), 1\
-  : 0); \
- (ITER) = (PREV))
-#define LIST_FOR_EACH_REVERSE_CONTINUE(ITER, MEMBER, LIST)  \
-for (ASSIGN_CONTAINER(ITER, (ITER)->MEMBER.prev, MEMBER);   \
- &(ITER)->MEMBER != (LIST); \
- ASSIGN_CONTAINER(ITER, (ITER)->MEMBER.prev, MEMBER))
-#define LIST_FOR_EACH_SAFE(ITER, NEXT, MEMBER, LIST)   \
-for (INIT_CONTAINER(ITER, (LIST)->next, MEMBER);   \
- (&(ITER)->MEMBER != (LIST)\
-  ? INIT_CONTAINER(NEXT, (ITER)->MEMBER.next, MEMBER), 1   \
-  : 0);\
- (ITER) = (NEXT))
-#define LIST_FOR_EACH_POP(ITER, MEMBER, LIST)  \
-while (!ovs_list_is_empty(LIST)\
+#define LIST_FOR_EACH(VAR, MEMBER, LIST)  \
+for (INIT_MULTIVAR(VAR, MEMBER, (LIST)->next);\
+ CONDITION_MULTIVAR(VAR, MEMBER, ITER_VAR(VAR) != (LIST));\
+ UPDATE_MULTIVAR(VAR, (ITER_VAR(VAR) = ITER_VAR(VAR)->next)))
+
+#define LIST_FOR_EACH_CONTINUE(VAR, MEMBER, LIST) \
+for (INIT_MULTIVAR(VAR, MEMBER, VAR->MEMBER.next);\
+ CONDITION_MULTIVAR(VAR, MEMBER, ITER_VAR(VAR) != (LIST));\
+ UPDATE_MULTIVAR(VAR, (ITER_VAR(VAR) = ITER_VAR(VAR)->next)))
+
+#define LIST_FOR_EACH_REVERSE(VAR, MEMBER, LIST)  \
+for (INIT_MULTIVAR(VAR, MEMBER, (LIST)->prev);\
+ CONDITION_MULTIVAR(VAR, MEMBER, ITER_VAR(VAR) != (LIST));\
+ UPDATE_MULTIVAR(VAR, (ITER_VAR(VAR) = ITER_VAR(VAR)->prev)))
+
+
+#define LIST_FOR_EACH_REVERSE_CONTINUE(VAR, MEMBER, LIST) \
+for (INIT_MULTIVAR(VAR, MEMBER, VAR->MEMBER.prev);\
+ CONDITION_MULTIVAR(VAR, MEMBER, ITER_VAR(VAR) != (LIST));\
+ UPDATE_MULTIVAR(VAR, (ITER_VAR(VAR) = ITER_VAR(VAR)->prev)))
+
+#define LIST_FOR_EACH_REVERSE_SAFE(VAR, PREV, MEMBER, LIST)   \
+for (INIT_MULTIVAR_SAFE_LONG(VAR, PREV, MEMBER, (LIST)->prev);\
+ CONDITION_MULTIVAR_SAFE_LONG(VAR, PREV, MEMBER,  \
+  ITER_VAR(VAR) != (LIST),\
+  ITER_VAR(PREV) = ITER_VAR(VAR)->prev,   \
+  ITER_VAR(PREV) != (LIST));

[ovs-dev] [PATCH v2 02/16] util: add safe multi-variable iterators

2022-02-14 Thread Adrian Moreno
Safe version of multi-variable iterator helpers declare an internal
variable to store the next value of the iterator temporarily.

Two versions of the macro are provided, one that still uses the NEXT
variable for backwards compatibility and a shorter version that does not
require the use of an additional variable provided by the user.

Signed-off-by: Adrian Moreno 
---
 include/openvswitch/util.h | 81 ++
 1 file changed, 81 insertions(+)

diff --git a/include/openvswitch/util.h b/include/openvswitch/util.h
index 174b7711b..1a127fe41 100644
--- a/include/openvswitch/util.h
+++ b/include/openvswitch/util.h
@@ -190,6 +190,87 @@ OVS_NO_RETURN void ovs_assert_failure(const char *, const 
char *, const char *);
 #define UPDATE_MULTIVAR(VAR, EXPR)\
 ((EXPR), (VAR) = NULL)
 
+
+/* In the safe version of the multi-variable container iteration, the next
+ * value of the iterator is precalculated on the condition expression.
+ * This allows for the iterator to be freed inside the loop.
+ *
+ * Two versions of the macros are provided:
+ *
+ * * In the _SHORT version, the user does not have to provide a variable to
+ * store the next value of the iterator. Instead, a second iterator variable
+ * is declared in the INIT_ macro and its name is determined by
+ * ITER_NEXT_VAR(OBJECT).
+ *
+ * * In the _LONG version, the user provides another variable of the same type
+ * as the iterator object variable to store the next containing object.
+ * We still declare an iterator variable inside the loop but in this case it's
+ * name is derived from the name of the next containing variable.
+ * The value of the next containing object will only be set
+ * (via OBJECT_CONTAINING) if an additional condition is statisfied. This
+ * second condition must ensure it is safe to call OBJECT_CONTAINING on the
+ * next iterator variable.
+ * With respect to the value of the next containing object:
+ *  - Inside of the loop: the variable is either NULL or safe to use.
+ *  - Outside of the loop: the variable is NULL if the loop ends normally.
+ * If the loop ends with a "break;" statement, rules of Inside the loop
+ * apply.
+ */
+#define ITER_NEXT_VAR(NAME) NAME ## __iterator__next__
+
+/* Safe initialization declares both iterators. */
+#define INIT_MULTIVAR_SAFE_SHORT(VAR, MEMBER, POINTER)\
+INIT_MULTIVAR_SAFE_SHORT_EXP(VAR, MEMBER, POINTER, (void) 0)
+
+#define INIT_MULTIVAR_SAFE_SHORT_EXP(VAR, MEMBER, POINTER, ...)   \
+OVS_TYPEOF(VAR->MEMBER) *ITER_VAR(VAR) =  \
+( __VA_ARGS__ , (OVS_TYPEOF(&(VAR->MEMBER))) POINTER),\
+*ITER_NEXT_VAR(VAR) = NULL
+
+/* Evaluate the condition expression and, if satisfied, update the _next_
+ * iterator with the NEXT_EXPR.
+ * Both EXPR and NEXT_EXPR should only use ITER_VAR(VAR) and
+ * ITER_NEXT_VAR(VAR).
+ */
+#define CONDITION_MULTIVAR_SAFE_SHORT(VAR, MEMBER, EXPR, NEXT_EXPR)   \
+((EXPR) ? \
+ (((VAR) = OBJECT_CONTAINING(ITER_VAR(VAR), VAR, MEMBER)),\
+  (NEXT_EXPR), 1) :   \
+ (((VAR) = NULL), 0))
+
+#define UPDATE_MULTIVAR_SAFE_SHORT(VAR)   \
+UPDATE_MULTIVAR(VAR, ITER_VAR(VAR) = ITER_NEXT_VAR(VAR))
+
+/*_LONG versions of the macros*/
+
+#define INIT_MULTIVAR_SAFE_LONG(VAR, NEXT_VAR, MEMBER, POINTER)   \
+INIT_MULTIVAR_SAFE_LONG_EXP(VAR, NEXT_VAR, MEMBER, POINTER, (void) 0) \
+
+#define INIT_MULTIVAR_SAFE_LONG_EXP(VAR, NEXT_VAR, MEMBER, POINTER, ...)  \
+OVS_TYPEOF(VAR->MEMBER) *ITER_VAR(VAR) =  \
+( __VA_ARGS__ , (OVS_TYPEOF(&(VAR->MEMBER))) POINTER),\
+*ITER_VAR(NEXT_VAR) = NULL
+
+/* Evaluate the condition expression and, if satisfied, update the _next_
+ * iterator with the NEXT_EXPR. After, evaluate the NEXT_COND and, if
+ * satisfied, set the value to NEXT_VAR. NEXT_COND must use ITER_VAR(NEXT_VAR).
+ *
+ * Both EXPR and NEXT_EXPR should only use ITER_VAR(VAR) and
+ * ITER_VAR(NEXT_VAR).
+ */
+#define CONDITION_MULTIVAR_SAFE_LONG(VAR, NEXT_VAR, MEMBER, EXPR, NEXT_EXPR,  \
+ NEXT_COND)   \
+((EXPR) ? \
+ (((VAR) = OBJECT_CONTAINING(ITER_VAR(VAR), VAR, MEMBER)),\
+  (NEXT_EXPR), ((NEXT_COND) ? \
+   ((NEXT_VAR) =  \
+OBJECT_CONTAINING(ITER_VAR(NEXT_VAR), NEXT_VAR, MEMBER)) :\
+   ((NEXT_VAR) = NULL)), 1) : \
+ (((VAR) = NULL), ((NEXT_VAR) = NULL), 0))
+
+#define 

Re: [ovs-dev] [PATCH 09/16] cmap: use multi-variable iterators

2022-02-14 Thread 0-day Robot
Bleep bloop.  Greetings Adrian Moreno, 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: Use ovs_assert() in place of assert()
#74 FILE: tests/test-cmap.c:77:
assert(e == NULL);

ERROR: Use ovs_assert() in place of assert()
#82 FILE: tests/test-cmap.c:111:
assert(e == NULL);

ERROR: Use ovs_assert() in place of assert()
#90 FILE: tests/test-cmap.c:135:
assert(e == NULL);

Lines checked: 97, Warnings: 0, Errors: 3


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 v2 01/16] util: add multi-variable loop iterator macros

2022-02-14 Thread Adrian Moreno
Multi-variable loop iterators avoid potential undefined behavior by
using an internal iterator variable to perform the iteration and only
referencing the containing object (via OBJECT_CONTAINING) if the
iterator has been validated via the second expression of the for
statement.

That way, the user can easily implement a loop that never tries to
obtain the object containing NULL or stack-allocated non-contained
nodes.

When the loop ends normally (not via "break;") the user-provided
variable is set to NULL.

Signed-off-by: Adrian Moreno 
---
 include/openvswitch/util.h | 45 ++
 1 file changed, 45 insertions(+)

diff --git a/include/openvswitch/util.h b/include/openvswitch/util.h
index 228b185c3..174b7711b 100644
--- a/include/openvswitch/util.h
+++ b/include/openvswitch/util.h
@@ -145,6 +145,51 @@ OVS_NO_RETURN void ovs_assert_failure(const char *, const 
char *, const char *);
 #define INIT_CONTAINER(OBJECT, POINTER, MEMBER) \
 ((OBJECT) = NULL, ASSIGN_CONTAINER(OBJECT, POINTER, MEMBER))
 
+
+/* Multi-variable container iterators.
+ *
+ * The following macros facilitate safe iteration over data structures
+ * contained in objects. It does so by using an internal iterator variable of
+ * the type of the member object pointer (i.e: pointer to the data structure).
+ */
+
+/* Multi-variable iterator variable name.
+ * Returns the name of the internal iterator variable.
+ */
+#define ITER_VAR(NAME) NAME ## __iterator__
+
+/* Multi-variable initialization. Creates an internal iterator variable that
+ * points to the provided pointer. The type of the pointer must be that of the
+ * iterator variable, not the containing object.
+ *
+ * The _EXP version evaluates the given expressions once.
+ */
+#define INIT_MULTIVAR(VAR, MEMBER, POINTER, ...)\
+INIT_MULTIVAR_EXP(VAR, MEMBER, POINTER, (void) 0)
+
+#define INIT_MULTIVAR_EXP(VAR, MEMBER, POINTER, ...)\
+OVS_TYPEOF(&(VAR->MEMBER)) ITER_VAR(VAR) = ( __VA_ARGS__ ,  \
+((OVS_TYPEOF(&(VAR->MEMBER))) POINTER))
+
+/* Multi-variable condition.
+ * Evaluates the condition expression (that must be based on the internal
+ * iterator variable). Only if the result of expression is true, the OBJECT is
+ * set to the object containing the current value of the iterator variable.
+ *
+ * It is up to the caller to make sure it is safe to run OBJECT_CONTAINING on
+ * the pointers that verify the condition.
+ */
+#define CONDITION_MULTIVAR(VAR, MEMBER, EXPR) \
+((EXPR) ? \
+ (((VAR) = OBJECT_CONTAINING(ITER_VAR(VAR), VAR, MEMBER)), 1) :   \
+ (((VAR) = NULL), 0))
+
+/* Multi-variable update.
+ * Evaluates the expresssion that is supposed to update the iterator variable.
+ */
+#define UPDATE_MULTIVAR(VAR, EXPR)\
+((EXPR), (VAR) = NULL)
+
 /* Returns the number of elements in ARRAY. */
 #define ARRAY_SIZE(ARRAY) __ARRAY_SIZE(ARRAY)
 
-- 
2.34.1

___
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev


[ovs-dev] [PATCH v2 00/16] Fix undefined behavior in loop macros

2022-02-14 Thread Adrian Moreno
When running builds with UBSan, some undefined behavior was detected in the 
iteration of common data data structures in OVS.
Coincidentally, a bug was reported [1] whose root cause whas another, this time 
undetected, undefined behavior in the iteration macros.

>From both cases, we conclude that the way we're currently iterating the data 
>structures is prone to errors and UB. This series is an attempt to rewrite 
>those macros in a UB-safe manner.

The core problem is that #define OBJECT_CONTAINING(POINTER, OBJECT, MEMBER) 
macro is being used on invalid POINTER values. In some cases we use NULL to 
compute the end-of-loop condition. In others, we allow it to point to 
non-contained objects (e.g: a non-contained stack allocated "struct ovs_list" 
as in [1]).

In order to systematically solve this in all cases this series introduces a new 
set of macros that implement a multi-variable loop iteration. They declare a 
hidden iterator variable inside the loop, used to iterate and evaluate the loop 
condition and only compute its OBJECT_CONTAINING if it satisfies the loop 
condition. One consequence of this safety guard is that the pointer provided by 
the user is set to NULL after the loop (if not exited via "break;").

Apart from normal iteration, many OVS data structures have a _SAFE version of 
the loop which require the user to declare an extra variable to hold the next 
value of the iterator.
The use of internal iterator variables makes the declaration variable not 
necessary. However, some users might still need that extra variable. For that 
reason, this series introduces two versions of _SAFE iteration loops: 
- The _LONG version keeps using the external variable but avoids calling 
OBJECT_CONTAINING on invalid values. Note that alghough this version still uses 
an external variable, it's behavior changes slightly as the "next" variable 
could be NULL if it's not safe to calculate the OBJECT_CONTAINING of its 
internal iterator value.
- The _SHORT version removes the use of the external variable alltogether.
On relevant data structures, an initial patch rewrites the macros using the 
_LONG, backwards-compatible helpers. A second patch adds the _SHORT version and 
removes the unneeded variable from the callers. In order to be even more 
flexible, the original macro name is overloaded and the right version is 
selected depending on the number of arguments provided by the user. The first 
patch would be easy to backport and the second would make code cleaner for the 
master branch.

* Testing / reviewing notes *
In order to verify this series removes all the loop-related UB, I've tested it 
on top of Dumitru's series [2] (without patch 1/11, which can hide some still 
invalid use of OBJECT_CONTAINING).
I've also verified no extra errors are reported through clang-analyzer or ASan.

There are a number of checkpatch.py errors:
- ERROR: Inappropriate bracing around statement: Seems a limitation in 
checkpatch.py that only happens when a FOR_EACH* macro calls another FOR_EACH* 
macro. I don't think it's worth modifying checkpatch.py for this.
- ERROR: Use ovs_assert() in place of assert(): On tests/*, I'll send an 
independent patch to exclude the "tests" directory from this check.

Note this series changes some potential undefined behavior with some potential 
NULL pointer dereferencing, which should be easier to catch by the static and 
dynamic analyzers.

* Limitations *
The proposed approach benefits code readability, therefore the name of the 
iterator variable is derived from the name of the object pointer given by the 
caller. This means that in an unlikely but still possible case in which a 
caller wants to nest two loops with the same iterating pointer object, the 
inner loop iterator variable will hide the one declared in the outer loop. This 
limitation is easy to spot (the compiler will warn) and easy to work around 
(just declaring another object pointer variable). I found no such code in the 
OvS or OVN tree.

V1 -> V2
- Added LONG and SHORT versions of _SAFE macros with macro name overloading.
- Rebased on top of latest master.
- Added Dumitru's patch to fix sparse header inclusion and version 
recommendation.
- Homogenize argument order in helper macros: VAR and MEMBER always first.
- Added SHORT version of _SAFE loops to SSET and idlc.

[1] https://bugzilla.redhat.com/show_bug.cgi?id=2014942
[2] https://patchwork.ozlabs.org/project/openvswitch/list/?series=277900


Adrian Moreno (16):
  util: add multi-variable loop iterator macros
  util: add safe multi-variable iterators
  list: use multi-variable helpers for list loops
  list: ensure iterator is NULL after pop loop
  list: use short version of safe loops if possible
  hmap: use multi-variable helpers for hmap loops
  hmap: implement UB-safe hmap pop iterator
  hmap: use short version of safe loops if possible
  cmap: use multi-variable iterators
  hindex: use multi-variable iterators
  hindex: remove the next variable in safe loops
  

Re: [ovs-dev] [PATCH 08/16] hmap: use short version of safe loops if possible

2022-02-14 Thread 0-day Robot
Bleep bloop.  Greetings Adrian Moreno, 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: Inappropriate bracing around statement
#87 FILE: include/openvswitch/hmap.h:182:
HMAP_FOR_EACH_SAFE_LONG_INIT (NODE, NEXT, MEMBER, HMAP, (void) NEXT)

ERROR: Inappropriate bracing around statement
#102 FILE: include/openvswitch/hmap.h:195:
HMAP_FOR_EACH_SAFE_SHORT_INIT (NODE, MEMBER, HMAP, (void) 0)

ERROR: Use ovs_assert() in place of assert()
#1551 FILE: tests/test-hmap.c:277:
assert(n == n_remaining);

ERROR: Use ovs_assert() in place of assert()
#1560 FILE: tests/test-hmap.c:286:
assert(i < n);

ERROR: Use ovs_assert() in place of assert()
#1565 FILE: tests/test-hmap.c:291:
assert(j < n_remaining);

ERROR: Use ovs_assert() in place of assert()
#1575 FILE: tests/test-hmap.c:301:
assert(i == n);

ERROR: Use ovs_assert() in place of assert()
#1576 FILE: tests/test-hmap.c:302:
assert(e == NULL);

Lines checked: 1847, Warnings: 0, Errors: 7


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] [External] Re: [PATCH] dpif-netdev: add an option to assign pmd rxq to all numas

2022-02-14 Thread Jan Scheurich via dev
> >
> > Btw, this patch is similar in functionality to the one posted by
> > Anurag [0] and there was also some discussion about this approach here [1].
> >
> 
> Thanks for pointing this out.
> IMO, setting interface cross-numa would be good for phy port but not good for
> vhu.  Since vhu can be destroyed and created relatively frequently.
> But yes the main idea is the same.
> 

We do acknowledge the benefit of non-pinned polling of phy rx queues by PMD 
threads on all NUMA nodes. It gives the auto-load balancer much better options 
to utilize spare capacity on PMDs on all NUMA nodes.

Our patch proposed in 
https://mail.openvswitch.org/pipermail/ovs-dev/2021-June/384547.html
indeed covers the difference between phy and vhu ports. One has to explicitly 
enable cross-NUMA-polling for individual interfaces with:

   ovs-vsctl set interface  other_config:cross-numa-polling=true

This would typically only be done by static configuration for the fixed set of 
physical ports. There is no code in the OpenStack's os-vif handler to apply 
such configuration for dynamically created vhu ports.

I would strongly suggest that cross-num-polling be introduced as a 
per-interface option as in our patch rather than as a per-datapath option as in 
your patch. Why not adapt our original patch to the latest OVS code base? We 
can help you with that.

BR, Jan

___
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev


Re: [ovs-dev] [PATCH 07/16] hmap: implement UB-safe hmap pop iterator

2022-02-14 Thread 0-day Robot
Bleep bloop.  Greetings Adrian Moreno, 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: Use ovs_assert() in place of assert()
#76 FILE: tests/test-hmap.c:320:
assert(e == NULL);

Lines checked: 83, Warnings: 0, 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 06/16] hmap: use multi-variable helpers for hmap loops

2022-02-14 Thread 0-day Robot
Bleep bloop.  Greetings Adrian Moreno, 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: Inappropriate bracing around statement
#77 FILE: include/openvswitch/hmap.h:182:
HMAP_FOR_EACH_SAFE_INIT (NODE, NEXT, MEMBER, HMAP, (void) NEXT)

ERROR: Inappropriate bracing around statement
#115 FILE: lib/ovs-numa.h:71:
HMAP_FOR_EACH (ITER, hmap_node, &(DUMP)->cores)

ERROR: Inappropriate bracing around statement
#119 FILE: lib/ovs-numa.h:74:
HMAP_FOR_EACH (ITER, hmap_node, &(DUMP)->numas)

ERROR: Use ovs_assert() in place of assert()
#130 FILE: tests/test-hmap.c:65:
assert(e == NULL);

ERROR: Use ovs_assert() in place of assert()
#138 FILE: tests/test-hmap.c:86:
assert(e == NULL);

ERROR: Use ovs_assert() in place of assert()
#147 FILE: tests/test-hmap.c:249:
assert(next == NULL);

ERROR: Use ovs_assert() in place of assert()
#149 FILE: tests/test-hmap.c:251:
assert(>node == hmap_next(, >node));

ERROR: Use ovs_assert() in place of assert()
#158 FILE: tests/test-hmap.c:269:
assert(next == NULL);

ERROR: Use ovs_assert() in place of assert()
#159 FILE: tests/test-hmap.c:270:
assert(e == NULL);

Lines checked: 166, Warnings: 0, Errors: 9


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 05/16] list: use short version of safe loops if possible

2022-02-14 Thread 0-day Robot
Bleep bloop.  Greetings Adrian Moreno, 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: Use ovs_assert() in place of assert()
#1174 FILE: tests/test-list.c:148:
assert(next == NULL);

ERROR: Use ovs_assert() in place of assert()
#1177 FILE: tests/test-list.c:151:
assert(>node == e->node.next);

ERROR: Use ovs_assert() in place of assert()
#1195 FILE: tests/test-list.c:184:
assert(i < n);

ERROR: Use ovs_assert() in place of assert()
#1208 FILE: tests/test-list.c:197:
assert(i == n);

ERROR: Use ovs_assert() in place of assert()
#1209 FILE: tests/test-list.c:198:
assert(e == NULL);

Lines checked: 1383, Warnings: 0, Errors: 5


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 03/16] list: use multi-variable helpers for list loops

2022-02-14 Thread 0-day Robot
Bleep bloop.  Greetings Adrian Moreno, 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: Use ovs_assert() in place of assert()
#128 FILE: tests/test-list.c:64:
assert(e == NULL);

ERROR: Use ovs_assert() in place of assert()
#137 FILE: tests/test-list.c:73:
assert(e == NULL);

ERROR: Use ovs_assert() in place of assert()
#147 FILE: tests/test-list.c:140:
assert(next == NULL);

ERROR: Use ovs_assert() in place of assert()
#149 FILE: tests/test-list.c:142:
assert(>node == e->node.next);

ERROR: Use ovs_assert() in place of assert()
#165 FILE: tests/test-list.c:159:
assert(e == NULL);

ERROR: Use ovs_assert() in place of assert()
#166 FILE: tests/test-list.c:160:
assert(next == NULL);

Lines checked: 173, Warnings: 0, Errors: 6


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 14/16] idlc: support short version of SAFE macros

2022-02-14 Thread Adrian Moreno
In order to be consistent with the rest of the SAFE loop macros,
overload each of the generated *_SAFE macro with a SHORT version that
does not require the user to provide the NEXT variable.

Signed-off-by: Adrian Moreno 
---
 ovsdb/ovsdb-idlc.in   | 23 +--
 utilities/ovs-vsctl.c | 36 ++--
 2 files changed, 39 insertions(+), 20 deletions(-)

diff --git a/ovsdb/ovsdb-idlc.in b/ovsdb/ovsdb-idlc.in
index 5a02c8f93..4346a572a 100755
--- a/ovsdb/ovsdb-idlc.in
+++ b/ovsdb/ovsdb-idlc.in
@@ -251,10 +251,20 @@ const struct %(s)s *%(s)s_table_first(const struct 
%(s)s_table *);
 for ((ROW) = %(s)s_table_first(TABLE); \\
  (ROW); \\
  (ROW) = %(s)s_next(ROW))
-#define %(S)s_TABLE_FOR_EACH_SAFE(ROW, NEXT, TABLE) \\
+#define %(S)s_TABLE_FOR_EACH_SAFE_LONG(ROW, NEXT, TABLE) \\
 for ((ROW) = %(s)s_table_first(TABLE); \\
  (ROW) ? ((NEXT) = %(s)s_next(ROW), 1) : 0; \\
  (ROW) = (NEXT))
+#define %(S)s_TABLE_FOR_EACH_SAFE_SHORT(ROW, TABLE) \\
+for (OVS_TYPEOF(ROW) ROW__next = ((ROW) = %(s)s_table_first(TABLE), 
NULL); \\
+ (ROW) ? (ROW__next = %(s)s_next(ROW), 1) : (ROW__next = NULL, 0); 
\\
+ (ROW) = ROW__next)
+#define %(S)s_TABLE_GET_SAFE_MACRO(_1, _2, _3, NAME) NAME
+#define %(S)s_TABLE_FOR_EACH_SAFE(...) \\
+%(S)s_TABLE_GET_SAFE_MACRO(__VA_ARGS__,\\
+   %(S)s_TABLE_FOR_EACH_SAFE_LONG, \\
+   %(S)s_TABLE_FOR_EACH_SAFE_SHORT)(__VA_ARGS__)
+
 
 const struct %(s)s *%(s)s_get_for_uuid(const struct ovsdb_idl *, const struct 
uuid *);
 const struct %(s)s *%(s)s_table_get_for_uuid(const struct %(s)s_table *, const 
struct uuid *);
@@ -264,10 +274,19 @@ const struct %(s)s *%(s)s_next(const struct %(s)s *);
 for ((ROW) = %(s)s_first(IDL); \\
  (ROW); \\
  (ROW) = %(s)s_next(ROW))
-#define %(S)s_FOR_EACH_SAFE(ROW, NEXT, IDL) \\
+#define %(S)s_FOR_EACH_SAFE_LONG(ROW, NEXT, IDL) \\
 for ((ROW) = %(s)s_first(IDL); \\
  (ROW) ? ((NEXT) = %(s)s_next(ROW), 1) : 0; \\
  (ROW) = (NEXT))
+#define %(S)s_FOR_EACH_SAFE_SHORT(ROW, IDL) \\
+for (OVS_TYPEOF(ROW) ROW__next = ((ROW) = %(s)s_first(IDL), NULL); \\
+ (ROW) ? (ROW__next = %(s)s_next(ROW), 1) : (ROW__next = NULL, 0); 
\\
+ (ROW) = ROW__next)
+#define %(S)s_GET_SAFE_MACRO(_1, _2, _3, NAME) NAME
+#define %(S)s_FOR_EACH_SAFE(...) \\
+%(S)s_GET_SAFE_MACRO(__VA_ARGS__,\\
+   %(S)s_FOR_EACH_SAFE_LONG, \\
+   %(S)s_FOR_EACH_SAFE_SHORT)(__VA_ARGS__)
 
 unsigned int %(s)s_get_seqno(const struct ovsdb_idl *);
 unsigned int %(s)s_row_get_seqno(const struct %(s)s *row, enum 
ovsdb_idl_change change);
diff --git a/utilities/ovs-vsctl.c b/utilities/ovs-vsctl.c
index 14f5cb92e..1032089fc 100644
--- a/utilities/ovs-vsctl.c
+++ b/utilities/ovs-vsctl.c
@@ -1100,14 +1100,14 @@ cmd_emer_reset(struct ctl_context *ctx)
 const struct ovsrec_bridge *br;
 const struct ovsrec_port *port;
 const struct ovsrec_interface *iface;
-const struct ovsrec_mirror *mirror, *next_mirror;
-const struct ovsrec_controller *ctrl, *next_ctrl;
-const struct ovsrec_manager *mgr, *next_mgr;
-const struct ovsrec_netflow *nf, *next_nf;
-const struct ovsrec_ssl *ssl, *next_ssl;
-const struct ovsrec_sflow *sflow, *next_sflow;
-const struct ovsrec_ipfix *ipfix, *next_ipfix;
-const struct ovsrec_flow_sample_collector_set *fscset, *next_fscset;
+const struct ovsrec_mirror *mirror;
+const struct ovsrec_controller *ctrl;
+const struct ovsrec_manager *mgr;
+const struct ovsrec_netflow *nf;
+const struct ovsrec_ssl *ssl;
+const struct ovsrec_sflow *sflow;
+const struct ovsrec_ipfix *ipfix;
+const struct ovsrec_flow_sample_collector_set *fscset;
 
 /* Reset the Open_vSwitch table. */
 ovsrec_open_vswitch_set_manager_options(vsctl_ctx->ovs, NULL, 0);
@@ -1145,35 +1145,35 @@ cmd_emer_reset(struct ctl_context *ctx)
 ovsrec_interface_set_ingress_policing_burst(iface, 0);
 }
 
-OVSREC_MIRROR_FOR_EACH_SAFE (mirror, next_mirror, idl) {
+OVSREC_MIRROR_FOR_EACH_SAFE (mirror, idl) {
 ovsrec_mirror_delete(mirror);
 }
 
-OVSREC_CONTROLLER_FOR_EACH_SAFE (ctrl, next_ctrl, idl) {
+OVSREC_CONTROLLER_FOR_EACH_SAFE (ctrl, idl) {
 ovsrec_controller_delete(ctrl);
 }
 
-OVSREC_MANAGER_FOR_EACH_SAFE (mgr, next_mgr, idl) {
+OVSREC_MANAGER_FOR_EACH_SAFE (mgr, idl) {
 ovsrec_manager_delete(mgr);
 }
 
-OVSREC_NETFLOW_FOR_EACH_SAFE (nf, next_nf, idl) {
+OVSREC_NETFLOW_FOR_EACH_SAFE (nf, idl) {
 ovsrec_netflow_delete(nf);
 }
 
-OVSREC_SSL_FOR_EACH_SAFE (ssl, next_ssl, idl) {
+

[ovs-dev] [PATCH 16/16] sset: add SHORT version of SAFE loop macros

2022-02-14 Thread Adrian Moreno
Add SHORT version of SAFE loop macros and overload the current macro
name to keep backwards compatibility.

Signed-off-by: Adrian Moreno 
---
 lib/sset.c |  8 
 lib/sset.h | 16 +++-
 2 files changed, 19 insertions(+), 5 deletions(-)

diff --git a/lib/sset.c b/lib/sset.c
index b2e3f43ec..c3197e305 100644
--- a/lib/sset.c
+++ b/lib/sset.c
@@ -212,9 +212,9 @@ sset_add_array(struct sset *set, char **names, size_t n)
 void
 sset_clear(struct sset *set)
 {
-const char *name, *next;
+const char *name;
 
-SSET_FOR_EACH_SAFE (name, next, set) {
+SSET_FOR_EACH_SAFE (name, set) {
 sset_delete(set, SSET_NODE_FROM_NAME(name));
 }
 }
@@ -320,9 +320,9 @@ sset_at_position(const struct sset *set, struct 
sset_position *pos)
 void
 sset_intersect(struct sset *a, const struct sset *b)
 {
-const char *name, *next;
+const char *name;
 
-SSET_FOR_EACH_SAFE (name, next, a) {
+SSET_FOR_EACH_SAFE (name, a) {
 if (!sset_contains(b, name)) {
 sset_delete(a, SSET_NODE_FROM_NAME(name));
 }
diff --git a/lib/sset.h b/lib/sset.h
index f0bb8b534..3a028c012 100644
--- a/lib/sset.h
+++ b/lib/sset.h
@@ -87,13 +87,27 @@ void sset_intersect(struct sset *, const struct sset *);
  NAME != NULL;  \
  (NAME) = SSET_NEXT(SSET, NAME))
 
-#define SSET_FOR_EACH_SAFE(NAME, NEXT, SSET)\
+#define SSET_FOR_EACH_SAFE_LONG(NAME, NEXT, SSET)   \
 for ((NAME) = SSET_FIRST(SSET); \
  (NAME != NULL  \
   ? (NEXT) = SSET_NEXT(SSET, NAME), true\
   : false); \
  (NAME) = (NEXT))
 
+#define SSET_FOR_EACH_SAFE_SHORT(NAME, SSET)   \
+for (OVS_TYPEOF(NAME) NAME__next = \
+ ((NAME) = SSET_FIRST(SSET), NULL);\
+ (NAME != NULL \
+  ? (NAME__next = SSET_NEXT(SSET, NAME), true) \
+  : (NAME__next = NULL, false));   \
+ (NAME) = NAME__next)
+
+#define SSET_GET_SAFE_MACRO(_1, _2, _3, NAME, ...) NAME
+#define SSET_FOR_EACH_SAFE(...)  \
+SSET_GET_SAFE_MACRO(__VA_ARGS__, \
+   SSET_FOR_EACH_SAFE_LONG,  \
+   SSET_FOR_EACH_SAFE_SHORT)(__VA_ARGS__)
+
 const char **sset_array(const struct sset *);
 const char **sset_sort(const struct sset *);
 
-- 
2.34.1

___
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev


[ovs-dev] [PATCH 15/16] sparse: bump recommended version and include headers

2022-02-14 Thread Adrian Moreno
It seems versions older than 0.6.2 generate false positives. Bump the
recommended version and make sure we uset the headers from the

Signed-off-by: Dumitru Ceara 
Signed-off-by: Adrian Moreno 
---
 Documentation/intro/install/general.rst | 2 +-
 acinclude.m4| 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/Documentation/intro/install/general.rst 
b/Documentation/intro/install/general.rst
index c4300cd53..a297aadac 100644
--- a/Documentation/intro/install/general.rst
+++ b/Documentation/intro/install/general.rst
@@ -169,7 +169,7 @@ other than plain text, only if you have the following:
 If you are going to extensively modify Open vSwitch, consider installing the
 following to obtain better warnings:
 
-- "sparse" version 0.5.1 or later
+- "sparse" version 0.6.2 or later
   (https://git.kernel.org/pub/scm/devel/sparse/sparse.git/).
 
 - GNU make.
diff --git a/acinclude.m4 b/acinclude.m4
index 0c360fd1e..f704bf36c 100644
--- a/acinclude.m4
+++ b/acinclude.m4
@@ -1424,7 +1424,7 @@ AC_DEFUN([OVS_ENABLE_SPARSE],
: ${SPARSE=sparse}
AC_SUBST([SPARSE])
AC_CONFIG_COMMANDS_PRE(
- [CC='$(if $(C:0=),env REAL_CC="'"$CC"'" CHECK="$(SPARSE) $(SPARSE_WERROR) 
-I $(top_srcdir)/include/sparse $(SPARSEFLAGS) $(SPARSE_EXTRA_INCLUDES) " cgcc 
$(CGCCFLAGS),'"$CC"')'])
+ [CC='$(if $(C:0=),env REAL_CC="'"$CC"'" CHECK="$(SPARSE) $(SPARSE_WERROR) 
-I $(top_srcdir)/include/sparse -I $(top_srcdir)/include $(SPARSEFLAGS) 
$(SPARSE_EXTRA_INCLUDES) " cgcc $(CGCCFLAGS),'"$CC"')'])
 
AC_ARG_ENABLE(
  [sparse],
-- 
2.34.1

___
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev


[ovs-dev] [PATCH 12/16] rculist: use multi-variable helpers for loop macros

2022-02-14 Thread Adrian Moreno
Use multi-variable iteration helpers to rewrite rculist loops macros.

There is an important behavior change compared with the previous
implementation: When the loop ends normally (i.e: not via "break;"),
the object pointer provided by the user is NULL. This is safer
because it's not guaranteed that it would end up pointing a valid
address.

Signed-off-by: Adrian Moreno 
---
 lib/rculist.h | 79 ---
 1 file changed, 49 insertions(+), 30 deletions(-)

diff --git a/lib/rculist.h b/lib/rculist.h
index 1072b87af..896aaf4a6 100644
--- a/lib/rculist.h
+++ b/lib/rculist.h
@@ -365,35 +365,54 @@ rculist_is_singleton_protected(const struct rculist *list)
 return list_next == list->prev && list_next != list;
 }
 
-#define RCULIST_FOR_EACH(ITER, MEMBER, RCULIST) \
-for (INIT_CONTAINER(ITER, rculist_next(RCULIST), MEMBER);   \
- &(ITER)->MEMBER != (RCULIST);  \
- ASSIGN_CONTAINER(ITER, rculist_next(&(ITER)->MEMBER), MEMBER))
-#define RCULIST_FOR_EACH_CONTINUE(ITER, MEMBER, RCULIST)\
-for (ASSIGN_CONTAINER(ITER, rculist_next(&(ITER)->MEMBER), MEMBER); \
- &(ITER)->MEMBER != (RCULIST);  \
- ASSIGN_CONTAINER(ITER, rculist_next(&(ITER)->MEMBER), MEMBER))
-
-#define RCULIST_FOR_EACH_REVERSE_PROTECTED(ITER, MEMBER, RCULIST)   \
-for (INIT_CONTAINER(ITER, (RCULIST)->prev, MEMBER); \
- &(ITER)->MEMBER != (RCULIST);  \
- ASSIGN_CONTAINER(ITER, (ITER)->MEMBER.prev, MEMBER))
-#define RCULIST_FOR_EACH_REVERSE_PROTECTED_CONTINUE(ITER, MEMBER, RCULIST) \
-for (ASSIGN_CONTAINER(ITER, (ITER)->MEMBER.prev, MEMBER);   \
- &(ITER)->MEMBER != (RCULIST);  \
- ASSIGN_CONTAINER(ITER, (ITER)->MEMBER.prev, MEMBER))
-
-#define RCULIST_FOR_EACH_PROTECTED(ITER, MEMBER, RCULIST)   \
-for (INIT_CONTAINER(ITER, rculist_next_protected(RCULIST), MEMBER); \
- &(ITER)->MEMBER != (RCULIST);  \
- ASSIGN_CONTAINER(ITER, rculist_next_protected(&(ITER)->MEMBER), \
-  MEMBER))
-
-#define RCULIST_FOR_EACH_SAFE_PROTECTED(ITER, NEXT, MEMBER, RCULIST)\
-for (INIT_CONTAINER(ITER, rculist_next_protected(RCULIST), MEMBER); \
- (&(ITER)->MEMBER != (RCULIST)  \
-  ? INIT_CONTAINER(NEXT, rculist_next_protected(&(ITER)->MEMBER), \
-   MEMBER), 1 : 0); \
- (ITER) = (NEXT))
+#define RCULIST_FOR_EACH(ITER, MEMBER, RCULIST)   \
+for (INIT_MULTIVAR(ITER, MEMBER, rculist_next(RCULIST));  \
+ CONDITION_MULTIVAR(ITER, MEMBER, ITER_VAR(ITER) != (RCULIST));   \
+ UPDATE_MULTIVAR(ITER, ITER_VAR(ITER) = rculist_next(ITER_VAR(ITER
+
+#define RCULIST_FOR_EACH_CONTINUE(ITER, MEMBER, RCULIST)  \
+for (INIT_MULTIVAR(ITER, MEMBER, rculist_next(&(ITER)->MEMBER));  \
+ CONDITION_MULTIVAR(ITER, MEMBER, ITER_VAR(ITER) != (RCULIST));   \
+ UPDATE_MULTIVAR(ITER, ITER_VAR(ITER) = rculist_next(ITER_VAR(ITER
+
+#define RCULIST_FOR_EACH_REVERSE_PROTECTED(ITER, MEMBER, RCULIST) \
+for (INIT_MULTIVAR(ITER, MEMBER, (RCULIST)->prev);\
+ CONDITION_MULTIVAR(ITER, MEMBER, ITER_VAR(ITER) != (RCULIST));   \
+ UPDATE_MULTIVAR(ITER, ITER_VAR(ITER) = ITER_VAR(VAR).prev))
+
+#define RCULIST_FOR_EACH_REVERSE_PROTECTED_CONTINUE(ITER, MEMBER, RCULIST)\
+for (INIT_MULTIVAR(ITER, MEMBER, (ITER)->MEMBER.prev);\
+ CONDITION_MULTIVAR(ITER, MEMBER, ITER_VAR(ITER) != (RCULIST));   \
+ UPDATE_MULTIVAR(ITER, ITER_VAR(ITER) = ITER_VAR(VAR).prev))
+
+#define RCULIST_FOR_EACH_PROTECTED(ITER, MEMBER, RCULIST) \
+for (INIT_MULTIVAR(ITER, MEMBER, rculist_next_protected(RCULIST));\
+ CONDITION_MULTIVAR(ITER, MEMBER, ITER_VAR(ITER) != (RCULIST));   \
+ UPDATE_MULTIVAR(ITER,\
+ ITER_VAR(ITER) = rculist_next_protected(ITER_VAR(ITER))) \
+
+#define RCULIST_FOR_EACH_SAFE_SHORT_PROTECTED(ITER, MEMBER, RCULIST)  \
+for (INIT_MULTIVAR_SAFE_SHORT(ITER, MEMBER,   \
+  rculist_next_protected(RCULIST));   \
+ CONDITION_MULTIVAR_SAFE_SHORT(ITER, MEMBER,  \
+   ITER_VAR(ITER) != (RCULIST),   \
+ ITER_NEXT_VAR(ITER) = rculist_next_protected(ITER_VAR(VAR)));\
+UPDATE_MULTIVAR_SHORT(ITER))
+
+#define RCULIST_FOR_EACH_SAFE_LONG_PROTECTED(ITER, NEXT, MEMBER, RCULIST) \
+for 

[ovs-dev] [PATCH 13/16] vtep: use _SAFE iterator if freeing the iterator

2022-02-14 Thread Adrian Moreno
The _SAFE version of the iterator allows the user to free the iterator
structure safely.

Signed-off-by: Adrian Moreno 
---
 vtep/vtep-ctl.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/vtep/vtep-ctl.c b/vtep/vtep-ctl.c
index 99c4adcd5..685b0007a 100644
--- a/vtep/vtep-ctl.c
+++ b/vtep/vtep-ctl.c
@@ -738,7 +738,7 @@ del_ploc_from_mcast_mac(struct vtep_ctl_mcast_mac 
*mcast_mac,
 {
 struct vtep_ctl_ploc *ploc;
 
-LIST_FOR_EACH (ploc, locators_node, _mac->locators) {
+LIST_FOR_EACH_SAFE (ploc, locators_node, _mac->locators) {
 if (ploc->ploc_cfg == ploc_cfg) {
 ovs_list_remove(>locators_node);
 free(ploc);
-- 
2.34.1

___
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev


[ovs-dev] [PATCH 11/16] hindex: remove the next variable in safe loops

2022-02-14 Thread Adrian Moreno
Using SHORT version of the *_SAFE loops makes the code cleaner and less
error prone. So, use the SHORT version and remove the extra variable
when possible for HINDEX_*_SAFE.

In order to be able to use both long and short versions without changing
the name of the macro for all the clients, overload the existing name
and select the appropriate version depending on the number of arguments.

Signed-off-by: Adrian Moreno 
---
 lib/conntrack.c |  4 ++--
 lib/hindex.h| 46 +
 tests/test-hindex.c | 31 ++
 3 files changed, 71 insertions(+), 10 deletions(-)

diff --git a/lib/conntrack.c b/lib/conntrack.c
index 9c96b69e4..2f0777102 100644
--- a/lib/conntrack.c
+++ b/lib/conntrack.c
@@ -2857,8 +2857,8 @@ expectation_clean(struct conntrack *ct, const struct 
conn_key *parent_key)
 {
 ovs_rwlock_wrlock(>resources_lock);
 
-struct alg_exp_node *node, *next;
-HINDEX_FOR_EACH_WITH_HASH_SAFE (node, next, node_ref,
+struct alg_exp_node *node;
+HINDEX_FOR_EACH_WITH_HASH_SAFE (node, node_ref,
 conn_key_hash(parent_key, ct->hash_basis),
 >alg_expectation_refs) {
 if (!conn_key_cmp(>parent_key, parent_key)) {
diff --git a/lib/hindex.h b/lib/hindex.h
index c20752c25..8f537069c 100644
--- a/lib/hindex.h
+++ b/lib/hindex.h
@@ -134,15 +134,31 @@ void hindex_remove(struct hindex *, struct hindex_node *);
 
 /* Safe when NODE may be freed (not needed when NODE may be removed from the
  * hash map but its members remain accessible and intact). */
-#define HINDEX_FOR_EACH_WITH_HASH_SAFE(NODE, NEXT, MEMBER, HASH, HINDEX)\
-for (INIT_MULTIVAR_SAFE_LONG(NODE, NEXT, MEMBER,\
-hindex_node_with_hash(HINDEX, HASH));   \
- CONDITION_MULTIVAR_SAFE_LONG(NODE, NEXT, MEMBER,   \
-  ITER_VAR(NODE) != NULL,   \
-  ITER_VAR(NEXT) = ITER_VAR(NODE)->s,   \
-  ITER_VAR(NEXT) != NULL);  \
+#define HINDEX_FOR_EACH_WITH_HASH_SAFE_LONG(NODE, NEXT, MEMBER, HASH, HINDEX) \
+for (INIT_MULTIVAR_SAFE_LONG(NODE, NEXT, MEMBER,  \
+hindex_node_with_hash(HINDEX, HASH)); \
+ CONDITION_MULTIVAR_SAFE_LONG(NODE, NEXT, MEMBER, \
+  ITER_VAR(NODE) != NULL, \
+  ITER_VAR(NEXT) = ITER_VAR(NODE)->s, \
+  ITER_VAR(NEXT) != NULL);\
  UPDATE_MULTIVAR_SAFE_LONG(NODE, NEXT))
 
+/* Short version of HINDEX_FOR_EACH_WITH_HASH_SAFE */
+#define HINDEX_FOR_EACH_WITH_HASH_SAFE_SHORT(NODE, MEMBER, HASH, HINDEX)  \
+for (INIT_MULTIVAR_SAFE_SHORT(NODE, MEMBER,   \
+hindex_node_with_hash(HINDEX, HASH)); \
+ CONDITION_MULTIVAR_SAFE_SHORT(NODE, MEMBER,  \
+   ITER_VAR(NODE) != NULL,\
+ ITER_NEXT_VAR(NODE) = ITER_VAR(NODE)->s);\
+ UPDATE_MULTIVAR_SAFE_SHORT(NODE))
+
+#define HINDEX_GET_SAFE_MACRO_WITH_HASH(_1, _2, _3, _4, _5, NAME, ...) NAME
+#define HINDEX_FOR_EACH_WITH_HASH_SAFE(...)   \
+HINDEX_GET_SAFE_MACRO_WITH_HASH(__VA_ARGS__,  \
+HINDEX_FOR_EACH_WITH_HASH_SAFE_LONG,  \
+HINDEX_FOR_EACH_WITH_HASH_SAFE_SHORT)(__VA_ARGS__)
+
+
 /* Returns the head node in 'hindex' with the given 'hash', or a null pointer
  * if no nodes have that hash value. */
 static inline struct hindex_node *
@@ -167,7 +183,7 @@ hindex_node_with_hash(const struct hindex *hindex, size_t 
hash)
 
 /* Safe when NODE may be freed (not needed when NODE may be removed from the
  * hash index but its members remain accessible and intact). */
-#define HINDEX_FOR_EACH_SAFE(NODE, NEXT, MEMBER, HINDEX)  \
+#define HINDEX_FOR_EACH_SAFE_LONG(NODE, NEXT, MEMBER, HINDEX) \
 for (INIT_MULTIVAR_SAFE_LONG(NODE, NEXT, MEMBER, hindex_first(HINDEX));   \
  CONDITION_MULTIVAR_SAFE_LONG(NODE, NEXT, MEMBER, \
   ITER_VAR(NODE) != NULL, \
@@ -175,6 +191,20 @@ hindex_node_with_hash(const struct hindex *hindex, size_t 
hash)
   ITER_VAR(NEXT) != NULL);\
  UPDATE_MULTIVAR_SAFE_LONG(NODE, NEXT))
 
+/* Short version of HINDEX_FOR_EACH_SAFE */
+#define HINDEX_FOR_EACH_SAFE_SHORT(NODE, MEMBER, HINDEX)  \
+for (INIT_MULTIVAR_SAFE_SHORT(NODE, MEMBER, hindex_first(HINDEX));\

[ovs-dev] [PATCH 10/16] hindex: use multi-variable iterators

2022-02-14 Thread Adrian Moreno
Re-write hindex's loops using multi-variable helpers.

For safe loops, use the LONG version to maintain backwards
compatibility.

Signed-off-by: Adrian Moreno 
---
 lib/hindex.h| 42 +++---
 tests/test-hindex.c |  6 ++
 2 files changed, 29 insertions(+), 19 deletions(-)

diff --git a/lib/hindex.h b/lib/hindex.h
index 876c5a9e3..c20752c25 100644
--- a/lib/hindex.h
+++ b/lib/hindex.h
@@ -128,18 +128,20 @@ void hindex_remove(struct hindex *, struct hindex_node *);
  * Evaluates HASH only once.
  */
 #define HINDEX_FOR_EACH_WITH_HASH(NODE, MEMBER, HASH, HINDEX)   \
-for (INIT_CONTAINER(NODE, hindex_node_with_hash(HINDEX, HASH), MEMBER); \
- NODE != OBJECT_CONTAINING(NULL, NODE, MEMBER); \
- ASSIGN_CONTAINER(NODE, (NODE)->MEMBER.s, MEMBER))
+for (INIT_MULTIVAR(NODE, MEMBER, hindex_node_with_hash(HINDEX, HASH));  \
+ CONDITION_MULTIVAR(NODE, MEMBER, ITER_VAR(NODE) != NULL);  \
+ UPDATE_MULTIVAR(NODE, ITER_VAR(NODE) = ITER_VAR(NODE)->s))
 
 /* Safe when NODE may be freed (not needed when NODE may be removed from the
  * hash map but its members remain accessible and intact). */
-#define HINDEX_FOR_EACH_WITH_HASH_SAFE(NODE, NEXT, MEMBER, HASH, HINDEX) \
-for (INIT_CONTAINER(NODE, hindex_node_with_hash(HINDEX, HASH), MEMBER); \
- (NODE != OBJECT_CONTAINING(NULL, NODE, MEMBER) \
-  ? INIT_CONTAINER(NEXT, (NODE)->MEMBER.s, MEMBER), 1   \
-  : 0); \
- (NODE) = (NEXT))
+#define HINDEX_FOR_EACH_WITH_HASH_SAFE(NODE, NEXT, MEMBER, HASH, HINDEX)\
+for (INIT_MULTIVAR_SAFE_LONG(NODE, NEXT, MEMBER,\
+hindex_node_with_hash(HINDEX, HASH));   \
+ CONDITION_MULTIVAR_SAFE_LONG(NODE, NEXT, MEMBER,   \
+  ITER_VAR(NODE) != NULL,   \
+  ITER_VAR(NEXT) = ITER_VAR(NODE)->s,   \
+  ITER_VAR(NEXT) != NULL);  \
+ UPDATE_MULTIVAR_SAFE_LONG(NODE, NEXT))
 
 /* Returns the head node in 'hindex' with the given 'hash', or a null pointer
  * if no nodes have that hash value. */
@@ -157,19 +159,21 @@ hindex_node_with_hash(const struct hindex *hindex, size_t 
hash)
 /* Iteration. */
 
 /* Iterates through every node in HINDEX. */
-#define HINDEX_FOR_EACH(NODE, MEMBER, HINDEX)   \
-for (INIT_CONTAINER(NODE, hindex_first(HINDEX), MEMBER);\
- NODE != OBJECT_CONTAINING(NULL, NODE, MEMBER); \
- ASSIGN_CONTAINER(NODE, hindex_next(HINDEX, &(NODE)->MEMBER), MEMBER))
+#define HINDEX_FOR_EACH(NODE, MEMBER, HINDEX) \
+for (INIT_MULTIVAR(NODE, MEMBER, hindex_first(HINDEX));   \
+ CONDITION_MULTIVAR(NODE, MEMBER, ITER_VAR(NODE) != NULL);\
+ UPDATE_MULTIVAR(NODE,\
+ ITER_VAR(NODE) = hindex_next(HINDEX, ITER_VAR(NODE
 
 /* Safe when NODE may be freed (not needed when NODE may be removed from the
  * hash index but its members remain accessible and intact). */
-#define HINDEX_FOR_EACH_SAFE(NODE, NEXT, MEMBER, HINDEX)  \
-for (INIT_CONTAINER(NODE, hindex_first(HINDEX), MEMBER);  \
- (NODE != OBJECT_CONTAINING(NULL, NODE, MEMBER) \
-  ? INIT_CONTAINER(NEXT, hindex_next(HINDEX, &(NODE)->MEMBER), 
MEMBER), 1 \
-  : 0); \
- (NODE) = (NEXT))
+#define HINDEX_FOR_EACH_SAFE(NODE, NEXT, MEMBER, HINDEX)  \
+for (INIT_MULTIVAR_SAFE_LONG(NODE, NEXT, MEMBER, hindex_first(HINDEX));   \
+ CONDITION_MULTIVAR_SAFE_LONG(NODE, NEXT, MEMBER, \
+  ITER_VAR(NODE) != NULL, \
+ITER_VAR(NEXT) = hindex_next(HINDEX, ITER_VAR(NODE)), \
+  ITER_VAR(NEXT) != NULL);\
+ UPDATE_MULTIVAR_SAFE_LONG(NODE, NEXT))
 
 struct hindex_node *hindex_first(const struct hindex *);
 struct hindex_node *hindex_next(const struct hindex *,
diff --git a/tests/test-hindex.c b/tests/test-hindex.c
index af06be5fc..95e49284e 100644
--- a/tests/test-hindex.c
+++ b/tests/test-hindex.c
@@ -265,6 +265,11 @@ test_hindex_for_each_safe(hash_func *hash)
 i = 0;
 n_remaining = n;
 HINDEX_FOR_EACH_SAFE (e, next, node, ) {
+if (hindex_next(, >node) == NULL) {
+assert(next == NULL);
+} else {
+assert(>node == hindex_next(, >node));
+}
 assert(i < n);
 if (pattern & (1ul << 

  1   2   >