Package: release.debian.org
Severity: normal
User: release.debian....@packages.debian.org
Usertags: unblock

Dear release team,

I'd like to upload OpenVSwitch 3.1.1 as the fix for CVE-2023-1668.

The upstream last point release contains only bugfixes, however,
the diff is still kind of significant.

The upstream diff contained lots of noise, like documentation,
tests, an update of the configure script and so on, that made the
diff more difficult to read. I have therefore filtered the diff for
all of this, and rm these in the attached diff:

- rhel (folder)
- Documentation/ref/ovs-actions.7.rst
- config.h.in
- build-aux
- configure
- tests (folder)

Does the release team agree that it's ok to upload 3.1.1, or should
I aim for a more targeted fix?

The diff upstream more specific to this CVE is:
https://github.com/openvswitch/ovs/commit/61b39d8c4797f1b668e4d5e5350d639fca6082a9

I would still prefer to include all bugfixes though, if possible.
Please let me know ASAP, as this is a grave security fix.
Also note that I've already sent to the security team the fix for
the version in Bullseye (and I'll probably also attempt to fix
in Buster, maybe later on...).

Cheers,

Thomas Goirand (zigo)
diff -u -N -r openvswitch-3.1.0/aclocal.m4 openvswitch-3.1.1/aclocal.m4
--- openvswitch-3.1.0/aclocal.m4        2023-02-16 17:31:22.310879633 +0100
+++ openvswitch-3.1.1/aclocal.m4        2023-04-06 17:12:17.243817086 +0200
@@ -1,6 +1,6 @@
-# generated automatically by aclocal 1.16.2 -*- Autoconf -*-
+# generated automatically by aclocal 1.16.5 -*- Autoconf -*-
 
-# Copyright (C) 1996-2020 Free Software Foundation, Inc.
+# Copyright (C) 1996-2021 Free Software Foundation, Inc.
 
 # This file is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
@@ -14,13 +14,13 @@
 m4_ifndef([AC_CONFIG_MACRO_DIRS], [m4_defun([_AM_CONFIG_MACRO_DIRS], 
[])m4_defun([AC_CONFIG_MACRO_DIRS], [_AM_CONFIG_MACRO_DIRS($@)])])
 m4_ifndef([AC_AUTOCONF_VERSION],
   [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
-m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.69],,
-[m4_warning([this file was generated for autoconf 2.69.
+m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.71],,
+[m4_warning([this file was generated for autoconf 2.71.
 You have another version of autoconf.  It may work, but is not guaranteed to.
 If you have problems, you may need to regenerate the build system entirely.
 To do so, use the procedure documented by the package, typically 
'autoreconf'.])])
 
-# Copyright (C) 2002-2020 Free Software Foundation, Inc.
+# Copyright (C) 2002-2021 Free Software Foundation, Inc.
 #
 # This file is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
@@ -35,7 +35,7 @@
 [am__api_version='1.16'
 dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to
 dnl require some minimum version.  Point them to the right macro.
-m4_if([$1], [1.16.2], [],
+m4_if([$1], [1.16.5], [],
       [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl
 ])
 
@@ -51,14 +51,14 @@
 # Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced.
 # This function is AC_REQUIREd by AM_INIT_AUTOMAKE.
 AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION],
-[AM_AUTOMAKE_VERSION([1.16.2])dnl
+[AM_AUTOMAKE_VERSION([1.16.5])dnl
 m4_ifndef([AC_AUTOCONF_VERSION],
   [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
 _AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))])
 
 # AM_AUX_DIR_EXPAND                                         -*- Autoconf -*-
 
-# Copyright (C) 2001-2020 Free Software Foundation, Inc.
+# Copyright (C) 2001-2021 Free Software Foundation, Inc.
 #
 # This file is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
@@ -110,7 +110,7 @@
 
 # AM_CONDITIONAL                                            -*- Autoconf -*-
 
-# Copyright (C) 1997-2020 Free Software Foundation, Inc.
+# Copyright (C) 1997-2021 Free Software Foundation, Inc.
 #
 # This file is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
@@ -141,7 +141,7 @@
 Usually this means the macro was only invoked conditionally.]])
 fi])])
 
-# Copyright (C) 1999-2020 Free Software Foundation, Inc.
+# Copyright (C) 1999-2021 Free Software Foundation, Inc.
 #
 # This file is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
@@ -332,7 +332,7 @@
 
 # Generate code to set up dependency tracking.              -*- Autoconf -*-
 
-# Copyright (C) 1999-2020 Free Software Foundation, Inc.
+# Copyright (C) 1999-2021 Free Software Foundation, Inc.
 #
 # This file is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
@@ -400,7 +400,7 @@
 
 # Do all the work for Automake.                             -*- Autoconf -*-
 
-# Copyright (C) 1996-2020 Free Software Foundation, Inc.
+# Copyright (C) 1996-2021 Free Software Foundation, Inc.
 #
 # This file is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
@@ -428,6 +428,10 @@
 # release and drop the old call support.
 AC_DEFUN([AM_INIT_AUTOMAKE],
 [AC_PREREQ([2.65])dnl
+m4_ifdef([_$0_ALREADY_INIT],
+  [m4_fatal([$0 expanded multiple times
+]m4_defn([_$0_ALREADY_INIT]))],
+  [m4_define([_$0_ALREADY_INIT], m4_expansion_stack)])dnl
 dnl Autoconf wants to disallow AM_ names.  We explicitly allow
 dnl the ones we care about.
 m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl
@@ -464,7 +468,7 @@
 [_AM_SET_OPTIONS([$1])dnl
 dnl Diagnose old-style AC_INIT with new-style AM_AUTOMAKE_INIT.
 m4_if(
-  m4_ifdef([AC_PACKAGE_NAME], [ok]):m4_ifdef([AC_PACKAGE_VERSION], [ok]),
+  m4_ifset([AC_PACKAGE_NAME], [ok]):m4_ifset([AC_PACKAGE_VERSION], [ok]),
   [ok:ok],,
   [m4_fatal([AC_INIT should be called with package and version arguments])])dnl
  AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl
@@ -516,6 +520,20 @@
                  [m4_define([AC_PROG_OBJCXX],
                             
m4_defn([AC_PROG_OBJCXX])[_AM_DEPENDENCIES([OBJCXX])])])dnl
 ])
+# Variables for tags utilities; see am/tags.am
+if test -z "$CTAGS"; then
+  CTAGS=ctags
+fi
+AC_SUBST([CTAGS])
+if test -z "$ETAGS"; then
+  ETAGS=etags
+fi
+AC_SUBST([ETAGS])
+if test -z "$CSCOPE"; then
+  CSCOPE=cscope
+fi
+AC_SUBST([CSCOPE])
+
 AC_REQUIRE([AM_SILENT_RULES])dnl
 dnl The testsuite driver may need to know about EXEEXT, so add the
 dnl 'am__EXEEXT' conditional if _AM_COMPILER_EXEEXT was seen.  This
@@ -597,7 +615,7 @@
 done
 echo "timestamp for $_am_arg" 
>`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count])
 
-# Copyright (C) 2001-2020 Free Software Foundation, Inc.
+# Copyright (C) 2001-2021 Free Software Foundation, Inc.
 #
 # This file is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
@@ -618,7 +636,7 @@
 fi
 AC_SUBST([install_sh])])
 
-# Copyright (C) 2003-2020 Free Software Foundation, Inc.
+# Copyright (C) 2003-2021 Free Software Foundation, Inc.
 #
 # This file is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
@@ -639,7 +657,7 @@
 
 # Check to see how 'make' treats includes.                 -*- Autoconf -*-
 
-# Copyright (C) 2001-2020 Free Software Foundation, Inc.
+# Copyright (C) 2001-2021 Free Software Foundation, Inc.
 #
 # This file is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
@@ -682,7 +700,7 @@
 
 # Fake the existence of programs that GNU maintainers use.  -*- Autoconf -*-
 
-# Copyright (C) 1997-2020 Free Software Foundation, Inc.
+# Copyright (C) 1997-2021 Free Software Foundation, Inc.
 #
 # This file is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
@@ -703,12 +721,7 @@
 [AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
 AC_REQUIRE_AUX_FILE([missing])dnl
 if test x"${MISSING+set}" != xset; then
-  case $am_aux_dir in
-  *\ * | *\    *)
-    MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;;
-  *)
-    MISSING="\${SHELL} $am_aux_dir/missing" ;;
-  esac
+  MISSING="\${SHELL} '$am_aux_dir/missing'"
 fi
 # Use eval to expand $SHELL
 if eval "$MISSING --is-lightweight"; then
@@ -721,7 +734,7 @@
 
 # Helper functions for option handling.                     -*- Autoconf -*-
 
-# Copyright (C) 2001-2020 Free Software Foundation, Inc.
+# Copyright (C) 2001-2021 Free Software Foundation, Inc.
 #
 # This file is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
@@ -750,7 +763,7 @@
 AC_DEFUN([_AM_IF_OPTION],
 [m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])])
 
-# Copyright (C) 1999-2020 Free Software Foundation, Inc.
+# Copyright (C) 1999-2021 Free Software Foundation, Inc.
 #
 # This file is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
@@ -797,7 +810,7 @@
 # For backward compatibility.
 AC_DEFUN_ONCE([AM_PROG_CC_C_O], [AC_REQUIRE([AC_PROG_CC])])
 
-# Copyright (C) 2001-2020 Free Software Foundation, Inc.
+# Copyright (C) 2001-2021 Free Software Foundation, Inc.
 #
 # This file is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
@@ -816,7 +829,7 @@
 
 # Check to make sure that the build environment is sane.    -*- Autoconf -*-
 
-# Copyright (C) 1996-2020 Free Software Foundation, Inc.
+# Copyright (C) 1996-2021 Free Software Foundation, Inc.
 #
 # This file is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
@@ -897,7 +910,7 @@
 rm -f conftest.file
 ])
 
-# Copyright (C) 2009-2020 Free Software Foundation, Inc.
+# Copyright (C) 2009-2021 Free Software Foundation, Inc.
 #
 # This file is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
@@ -957,7 +970,7 @@
 _AM_SUBST_NOTMAKE([AM_BACKSLASH])dnl
 ])
 
-# Copyright (C) 2001-2020 Free Software Foundation, Inc.
+# Copyright (C) 2001-2021 Free Software Foundation, Inc.
 #
 # This file is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
@@ -985,7 +998,7 @@
 INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s"
 AC_SUBST([INSTALL_STRIP_PROGRAM])])
 
-# Copyright (C) 2006-2020 Free Software Foundation, Inc.
+# Copyright (C) 2006-2021 Free Software Foundation, Inc.
 #
 # This file is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
@@ -1004,7 +1017,7 @@
 
 # Check how to create a tarball.                            -*- Autoconf -*-
 
-# Copyright (C) 2004-2020 Free Software Foundation, Inc.
+# Copyright (C) 2004-2021 Free Software Foundation, Inc.
 #
 # This file is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
diff -u -N -r openvswitch-3.1.0/configure.ac openvswitch-3.1.1/configure.ac
--- openvswitch-3.1.0/configure.ac      2023-02-16 17:31:15.018879633 +0100
+++ openvswitch-3.1.1/configure.ac      2023-04-06 17:12:13.110813762 +0200
@@ -13,7 +13,7 @@
 # limitations under the License.
 
 AC_PREREQ(2.63)
-AC_INIT(openvswitch, 3.1.0, b...@openvswitch.org)
+AC_INIT(openvswitch, 3.1.1, b...@openvswitch.org)
 AC_CONFIG_SRCDIR([vswitchd/ovs-vswitchd.c])
 AC_CONFIG_MACRO_DIR([m4])
 AC_CONFIG_AUX_DIR([build-aux])
diff -u -N -r openvswitch-3.1.0/include/openvswitch/meta-flow.h 
openvswitch-3.1.1/include/openvswitch/meta-flow.h
--- openvswitch-3.1.0/include/openvswitch/meta-flow.h   2023-02-16 
17:31:13.516879633 +0100
+++ openvswitch-3.1.1/include/openvswitch/meta-flow.h   2023-04-06 
17:09:19.474674139 +0200
@@ -2366,6 +2366,10 @@
 void field_array_set(enum mf_field_id id, const union mf_value *,
                      struct field_array *);
 
+/* Mask the required l3 prerequisites if a 'set' action occurs. */
+void mf_set_mask_l3_prereqs(const struct mf_field *, const struct flow *,
+                            struct flow_wildcards *);
+
 #ifdef __cplusplus
 }
 #endif
diff -u -N -r openvswitch-3.1.0/include/openvswitch/version.h 
openvswitch-3.1.1/include/openvswitch/version.h
--- openvswitch-3.1.0/include/openvswitch/version.h     2023-02-16 
17:31:42.511879633 +0100
+++ openvswitch-3.1.1/include/openvswitch/version.h     2023-04-06 
17:12:25.786823955 +0200
@@ -18,8 +18,8 @@
 #ifndef OPENVSWITCH_VERSION_H
 #define OPENVSWITCH_VERSION_H 1
 
-#define OVS_PACKAGE_STRING  "openvswitch 3.1.0"
-#define OVS_PACKAGE_VERSION "3.1.0"
+#define OVS_PACKAGE_STRING  "openvswitch 3.1.1"
+#define OVS_PACKAGE_VERSION "3.1.1"
 
 #define OVS_LIB_VERSION     0
 #define OVS_LIB_REVISION    0
diff -u -N -r openvswitch-3.1.0/lib/classifier.c 
openvswitch-3.1.1/lib/classifier.c
--- openvswitch-3.1.0/lib/classifier.c  2023-02-16 17:31:13.527879633 +0100
+++ openvswitch-3.1.1/lib/classifier.c  2023-04-06 17:10:44.138742219 +0200
@@ -1695,6 +1695,8 @@
     const struct cls_match *rule = NULL;
     struct flowmap stages_map = FLOWMAP_EMPTY_INITIALIZER;
     unsigned int mask_offset = 0;
+    bool adjust_ports_mask = false;
+    ovs_be32 ports_mask;
     int i;
 
     /* Try to finish early by checking fields in segments. */
@@ -1722,6 +1724,9 @@
                     subtable->index_maps[i], flow, wc)) {
         goto no_match;
     }
+    /* Accumulate the map used so far. */
+    stages_map = flowmap_or(stages_map, subtable->index_maps[i]);
+
     hash = flow_hash_in_minimask_range(flow, &subtable->mask,
                                        subtable->index_maps[i],
                                        &mask_offset, &basis);
@@ -1731,14 +1736,16 @@
          * unwildcarding all the ports bits, use the ports trie to figure out a
          * smaller set of bits to unwildcard. */
         unsigned int mbits;
-        ovs_be32 value, plens, mask;
+        ovs_be32 value, plens;
 
-        mask = miniflow_get_ports(&subtable->mask.masks);
-        value = ((OVS_FORCE ovs_be32 *)flow)[TP_PORTS_OFS32] & mask;
+        ports_mask = miniflow_get_ports(&subtable->mask.masks);
+        value = ((OVS_FORCE ovs_be32 *) flow)[TP_PORTS_OFS32] & ports_mask;
         mbits = trie_lookup_value(&subtable->ports_trie, &value, &plens, 32);
 
-        ((OVS_FORCE ovs_be32 *)&wc->masks)[TP_PORTS_OFS32] |=
-            mask & be32_prefix_mask(mbits);
+        ports_mask &= be32_prefix_mask(mbits);
+        ports_mask |= ((OVS_FORCE ovs_be32 *) &wc->masks)[TP_PORTS_OFS32];
+
+        adjust_ports_mask = true;
 
         goto no_match;
     }
@@ -1751,6 +1758,14 @@
     /* Unwildcard the bits in stages so far, as they were used in determining
      * there is no match. */
     flow_wildcards_fold_minimask_in_map(wc, &subtable->mask, stages_map);
+    if (adjust_ports_mask) {
+        /* This has to be done after updating flow wildcards to overwrite
+         * the ports mask back.  We can't simply disable the corresponding bit
+         * in the stages map, because it has 64-bit resolution, i.e. one
+         * bit covers not only tp_src/dst, but also ct_tp_src/dst, which are
+         * not covered by the trie. */
+        ((OVS_FORCE ovs_be32 *) &wc->masks)[TP_PORTS_OFS32] = ports_mask;
+    }
     return NULL;
 }
 
diff -u -N -r openvswitch-3.1.0/lib/conntrack.c 
openvswitch-3.1.1/lib/conntrack.c
--- openvswitch-3.1.0/lib/conntrack.c   2023-02-16 17:31:13.530879633 +0100
+++ openvswitch-3.1.1/lib/conntrack.c   2023-04-06 17:12:13.115813766 +0200
@@ -1512,12 +1512,12 @@
     clean_end = n_conn_limit / 64;
 
     for (i = ct->next_sweep; i < N_EXP_LISTS; i++) {
-        count += ct_sweep(ct, &ct->exp_lists[i], now);
-
         if (count > clean_end) {
             next_wakeup = 0;
             break;
         }
+
+        count += ct_sweep(ct, &ct->exp_lists[i], now);
     }
 
     ct->next_sweep = (i < N_EXP_LISTS) ? i : 0;
diff -u -N -r openvswitch-3.1.0/lib/conntrack-tp.h 
openvswitch-3.1.1/lib/conntrack-tp.h
--- openvswitch-3.1.0/lib/conntrack-tp.h        2023-02-16 17:31:13.529879633 
+0100
+++ openvswitch-3.1.1/lib/conntrack-tp.h        2023-04-06 17:10:44.138742219 
+0200
@@ -17,8 +17,15 @@
 #ifndef CONNTRACK_TP_H
 #define CONNTRACK_TP_H 1
 
+#include <stdint.h>
+
 #define CT_DPIF_NETDEV_TP_MIN 30
+
 enum ct_timeout;
+struct conn;
+struct conntrack;
+struct timeout_policy;
+
 void timeout_policy_init(struct conntrack *ct);
 int timeout_policy_update(struct conntrack *ct, struct timeout_policy *tp);
 int timeout_policy_delete(struct conntrack *ct, uint32_t tp_id);
diff -u -N -r openvswitch-3.1.0/lib/db-ctl-base.c 
openvswitch-3.1.1/lib/db-ctl-base.c
--- openvswitch-3.1.0/lib/db-ctl-base.c 2023-02-16 17:31:13.532879633 +0100
+++ openvswitch-3.1.1/lib/db-ctl-base.c 2023-04-06 17:12:13.115813766 +0200
@@ -1492,7 +1492,7 @@
     const struct ovsdb_idl_column *column;
     const struct ovsdb_idl_row *row;
     const struct ovsdb_type *type;
-    struct ovsdb_datum new;
+    struct ovsdb_datum old;
     int i;
 
     ctx->error = get_table(table_name, &table);
@@ -1516,13 +1516,7 @@
     }
 
     type = &column->type;
-
-    if (ctx->last_command) {
-        ovsdb_datum_init_empty(&new);
-    } else {
-        ovsdb_datum_clone(&new, ovsdb_idl_read(row, column));
-    }
-
+    ovsdb_datum_clone(&old, ovsdb_idl_read(row, column));
     for (i = 4; i < ctx->argc; i++) {
         struct ovsdb_type add_type;
         struct ovsdb_datum add;
@@ -1533,41 +1527,23 @@
         ctx->error = ovsdb_datum_from_string(&add, &add_type, ctx->argv[i],
                                              ctx->symtab);
         if (ctx->error) {
-            ovsdb_datum_destroy(&new, &column->type);
+            ovsdb_datum_destroy(&old, &column->type);
             return;
         }
-        ovsdb_datum_union(&new, &add, type);
+        ovsdb_datum_union(&old, &add, type);
         ovsdb_datum_destroy(&add, type);
     }
-
-    if (!ctx->last_command && new.n > type->n_max) {
+    if (old.n > type->n_max) {
         ctl_error(ctx, "\"add\" operation would put %u %s in column %s of "
                   "table %s but the maximum number is %u",
-                  new.n,
+                  old.n,
                   type->value.type == OVSDB_TYPE_VOID ? "values" : "pairs",
                   column->name, table->name, type->n_max);
-        ovsdb_datum_destroy(&new, &column->type);
+        ovsdb_datum_destroy(&old, &column->type);
         return;
     }
-
-    if (ctx->last_command) {
-        /* Partial updates can only be made one by one. */
-        for (i = 0; i < new.n; i++) {
-            struct ovsdb_datum *datum = xmalloc(sizeof *datum);
-
-            ovsdb_datum_init_empty(datum);
-            ovsdb_datum_add_from_index_unsafe(datum, &new, i, type);
-            if (ovsdb_type_is_map(type)) {
-                ovsdb_idl_txn_write_partial_map(row, column, datum);
-            } else {
-                ovsdb_idl_txn_write_partial_set(row, column, datum);
-            }
-        }
-        ovsdb_datum_destroy(&new, &column->type);
-    } else {
-        ovsdb_idl_txn_verify(row, column);
-        ovsdb_idl_txn_write(row, column, &new);
-    }
+    ovsdb_idl_txn_verify(row, column);
+    ovsdb_idl_txn_write(row, column, &old);
 
     invalidate_cache(ctx);
 }
diff -u -N -r openvswitch-3.1.0/lib/dpctl.c openvswitch-3.1.1/lib/dpctl.c
--- openvswitch-3.1.0/lib/dpctl.c       2023-02-16 17:31:15.023879633 +0100
+++ openvswitch-3.1.1/lib/dpctl.c       2023-04-06 17:12:13.116813766 +0200
@@ -1713,10 +1713,16 @@
     uint16_t zone, *pzone = NULL;
     int error;
     int args = argc - 1;
+    int zone_pos = 1;
+
+    if (dp_arg_exists(argc, argv)) {
+        args--;
+        zone_pos = 2;
+    }
 
     /* Parse zone. */
-    if (args && !strncmp(argv[1], "zone=", 5)) {
-        if (!ovs_scan(argv[1], "zone=%"SCNu16, &zone)) {
+    if (args && !strncmp(argv[zone_pos], "zone=", 5)) {
+        if (!ovs_scan(argv[zone_pos], "zone=%"SCNu16, &zone)) {
             ds_put_cstr(&ds, "failed to parse zone");
             error = EINVAL;
             goto error;
@@ -1744,7 +1750,7 @@
     }
 
     /* Report error if there is more than one unparsed argument. */
-    if (args > 1) {
+    if (args > 0) {
         ds_put_cstr(&ds, "invalid arguments");
         error = EINVAL;
         goto error;
diff -u -N -r openvswitch-3.1.0/lib/dpif.c openvswitch-3.1.1/lib/dpif.c
--- openvswitch-3.1.0/lib/dpif.c        2023-02-16 17:31:13.541879633 +0100
+++ openvswitch-3.1.1/lib/dpif.c        2023-04-06 17:10:44.145742224 +0200
@@ -2109,3 +2109,9 @@
            ? dpif->dpif_class->cache_set_size(dpif, level, size)
            : EOPNOTSUPP;
 }
+
+bool
+dpif_synced_dp_layers(struct dpif *dpif)
+{
+    return dpif->dpif_class->synced_dp_layers;
+}
diff -u -N -r openvswitch-3.1.0/lib/dpif.h openvswitch-3.1.1/lib/dpif.h
--- openvswitch-3.1.0/lib/dpif.h        2023-02-16 17:31:13.542879633 +0100
+++ openvswitch-3.1.1/lib/dpif.h        2023-04-06 17:10:44.145742224 +0200
@@ -939,6 +939,7 @@
 char *dpif_get_dp_version(const struct dpif *);
 bool dpif_supports_tnl_push_pop(const struct dpif *);
 bool dpif_supports_explicit_drop_action(const struct dpif *);
+bool dpif_synced_dp_layers(struct dpif *);
 
 /* Log functions. */
 struct vlog_module;
diff -u -N -r openvswitch-3.1.0/lib/dpif-netdev.c 
openvswitch-3.1.1/lib/dpif-netdev.c
--- openvswitch-3.1.0/lib/dpif-netdev.c 2023-02-16 17:31:13.539879633 +0100
+++ openvswitch-3.1.1/lib/dpif-netdev.c 2023-04-06 17:12:13.118813768 +0200
@@ -9616,6 +9616,7 @@
 const struct dpif_class dpif_netdev_class = {
     "netdev",
     true,                       /* cleanup_required */
+    true,                       /* synced_dp_layers */
     dpif_netdev_init,
     dpif_netdev_enumerate,
     dpif_netdev_port_open_type,
diff -u -N -r openvswitch-3.1.0/lib/dpif-netlink.c 
openvswitch-3.1.1/lib/dpif-netlink.c
--- openvswitch-3.1.0/lib/dpif-netlink.c        2023-02-16 17:31:15.028879633 
+0100
+++ openvswitch-3.1.1/lib/dpif-netlink.c        2023-04-06 17:12:13.119813769 
+0200
@@ -2582,7 +2582,7 @@
         n_handlers = MIN(next_prime_num, total_cores);
     }
 
-    return n_handlers;
+    return MAX(n_handlers, 1);
 }
 
 static int
@@ -4515,6 +4515,7 @@
 const struct dpif_class dpif_netlink_class = {
     "system",
     false,                      /* cleanup_required */
+    false,                      /* synced_dp_layers */
     NULL,                       /* init */
     dpif_netlink_enumerate,
     NULL,
diff -u -N -r openvswitch-3.1.0/lib/dpif-provider.h 
openvswitch-3.1.1/lib/dpif-provider.h
--- openvswitch-3.1.0/lib/dpif-provider.h       2023-02-16 17:31:13.541879633 
+0100
+++ openvswitch-3.1.1/lib/dpif-provider.h       2023-04-06 17:10:44.144742223 
+0200
@@ -127,6 +127,14 @@
      * datapaths that can not exist without it (e.g. netdev datapath).  */
     bool cleanup_required;
 
+    /* If 'true' the specific dpif implementation synchronizes the various
+     * datapath implementation layers, i.e., the dpif's layer in combination
+     * with the underlying netdev offload layers. For example, dpif-netlink
+     * does not sync its kernel flows with the tc ones, i.e., only one gets
+     * installed. On the other hand, dpif-netdev installs both flows,
+     * internally keeps track of both, and represents them as one. */
+    bool synced_dp_layers;
+
     /* Called when the dpif provider is registered, typically at program
      * startup.  Returning an error from this function will prevent any
      * datapath with this class from being created.
diff -u -N -r openvswitch-3.1.0/lib/meta-flow.c 
openvswitch-3.1.1/lib/meta-flow.c
--- openvswitch-3.1.0/lib/meta-flow.c   2023-02-16 17:31:13.550879633 +0100
+++ openvswitch-3.1.1/lib/meta-flow.c   2023-04-06 17:10:44.147742226 +0200
@@ -3676,3 +3676,28 @@
     bitmap_not(x.bm, MFF_N_IDS);
     return x;
 }
+
+void
+mf_set_mask_l3_prereqs(const struct mf_field *mf, const struct flow *fl,
+                       struct flow_wildcards *wc)
+{
+    if (is_ip_any(fl) &&
+        ((mf->id == MFF_IPV4_SRC) ||
+         (mf->id == MFF_IPV4_DST) ||
+         (mf->id == MFF_IPV6_SRC) ||
+         (mf->id == MFF_IPV6_DST) ||
+         (mf->id == MFF_IPV6_LABEL) ||
+         (mf->id == MFF_IP_DSCP) ||
+         (mf->id == MFF_IP_ECN) ||
+         (mf->id == MFF_IP_TTL))) {
+        WC_MASK_FIELD(wc, nw_proto);
+    } else if ((fl->dl_type == htons(ETH_TYPE_ARP)) &&
+               ((mf->id == MFF_ARP_OP) ||
+                (mf->id == MFF_ARP_SHA) ||
+                (mf->id == MFF_ARP_THA) ||
+                (mf->id == MFF_ARP_SPA) ||
+                (mf->id == MFF_ARP_TPA))) {
+        /* mask only the lower 8 bits. */
+        wc->masks.nw_proto = 0xff;
+    }
+}
diff -u -N -r openvswitch-3.1.0/lib/netdev-offload-tc.c 
openvswitch-3.1.1/lib/netdev-offload-tc.c
--- openvswitch-3.1.0/lib/netdev-offload-tc.c   2023-02-16 17:31:15.036879633 
+0100
+++ openvswitch-3.1.1/lib/netdev-offload-tc.c   2023-04-06 17:12:13.122813771 
+0200
@@ -276,8 +276,9 @@
     }
 
     err = tc_del_flower_filter(id);
-    if (!err) {
+    if (!err || err == ENODEV) {
         del_ufid_tc_mapping(ufid);
+        return 0;
     }
     return err;
 }
@@ -871,7 +872,7 @@
                 outport =
                     netdev_ifindex_to_odp_port(action->out.ifindex_out);
                 if (!outport) {
-                    return ENOENT;
+                    return -ENOENT;
                 }
             }
             nl_msg_put_u32(buf, OVS_ACTION_ATTR_OUTPUT, odp_to_u32(outport));
@@ -964,7 +965,7 @@
             uint32_t meter_id;
 
             if (police_idx_lookup(action->police.index, &meter_id)) {
-                return ENOENT;
+                return -ENOENT;
             }
             nl_msg_put_u32(buf, OVS_ACTION_ATTR_METER, meter_id);
         }
@@ -983,6 +984,9 @@
                 buf, OVS_CHECK_PKT_LEN_ATTR_ACTIONS_IF_GREATER);
             i = parse_tc_flower_to_actions__(flower, buf, i + 1,
                                              action->police.result_jump);
+            if (i < 0) {
+                return i;
+            }
             nl_msg_end_nested(buf, act_offset);
 
             act_offset = nl_msg_start_nested(
@@ -994,6 +998,9 @@
             }
             if (jump != 0) {
                 i = parse_tc_flower_to_actions__(flower, buf, i, jump);
+                if (i < 0) {
+                    return i;
+                }
             }
             nl_msg_end_nested(buf, act_offset);
 
@@ -1013,11 +1020,11 @@
     return i;
 }
 
-static void
+static int
 parse_tc_flower_to_actions(struct tc_flower *flower,
                            struct ofpbuf *buf)
 {
-    parse_tc_flower_to_actions__(flower, buf, 0, 0);
+    return parse_tc_flower_to_actions__(flower, buf, 0, 0);
 }
 
 static int
@@ -1030,9 +1037,10 @@
                          struct ofpbuf *buf,
                          bool terse)
 {
-    size_t act_off;
     struct tc_flower_key *key = &flower->key;
     struct tc_flower_key *mask = &flower->mask;
+    size_t act_off;
+    int err;
 
     if (terse) {
         return parse_tc_flower_terse_to_match(flower, match, stats, attrs);
@@ -1229,7 +1237,10 @@
     }
 
     act_off = nl_msg_start_nested(buf, OVS_FLOW_ATTR_ACTIONS);
-    parse_tc_flower_to_actions(flower, buf);
+    err = parse_tc_flower_to_actions(flower, buf);
+    if (err < 0) {
+        return -err;
+    }
     nl_msg_end_nested(buf, act_off);
 
     *actions = ofpbuf_at_assert(buf, act_off, sizeof(struct nlattr));
@@ -1272,8 +1283,8 @@
             continue;
         }
 
-        if (flower.act_cookie.len) {
-            *ufid = *((ovs_u128 *) flower.act_cookie.data);
+        if (flower.act_cookie.len >= sizeof *ufid) {
+            *ufid = get_32aligned_u128(flower.act_cookie.data);
         } else if (!find_ufid(netdev, &id, ufid)) {
             continue;
         }
@@ -2490,15 +2501,23 @@
 
     err = tc_get_flower(&id, &flower);
     if (err) {
-        VLOG_ERR_RL(&error_rl, "flow get failed (dev %s prio %d handle %d): 
%s",
+        VLOG_ERR_RL(&error_rl,
+                    "flow get failed (dev %s prio %d handle %d): %s",
                     netdev_get_name(netdev), id.prio, id.handle,
                     ovs_strerror(err));
         return err;
     }
 
     in_port = netdev_ifindex_to_odp_port(id.ifindex);
-    parse_tc_flower_to_match(netdev, &flower, match, actions,
-                             stats, attrs, buf, false);
+    err = parse_tc_flower_to_match(netdev, &flower, match, actions,
+                                   stats, attrs, buf, false);
+    if (err) {
+        VLOG_ERR_RL(&error_rl,
+                    "flow get parse failed (dev %s prio %d handle %d): %s",
+                    netdev_get_name(netdev), id.prio, id.handle,
+                    ovs_strerror(err));
+        return err;
+    }
 
     if (stats) {
         struct dpif_flow_stats adjust_stats;
diff -u -N -r openvswitch-3.1.0/lib/netdev-windows.c 
openvswitch-3.1.1/lib/netdev-windows.c
--- openvswitch-3.1.0/lib/netdev-windows.c      2023-02-16 17:31:13.557879633 
+0100
+++ openvswitch-3.1.1/lib/netdev-windows.c      2023-04-06 15:05:22.449692897 
+0200
@@ -156,6 +156,7 @@
     struct netdev_windows_netdev_info info;
     struct ofpbuf *buf;
     int ret;
+    const char    *type = NULL;
 
     /* Query the attributes and runtime status of the netdev. */
     ret = query_netdev(netdev_get_name(&netdev->up), &info, &buf);
@@ -167,6 +168,16 @@
     }
     ofpbuf_delete(buf);
 
+    /* Don't create netdev if ovs-type is "internal"
+     * but the type of netdev->up is "system". */
+    type = netdev_get_type(&netdev->up);
+    if (type && !strcmp(type, "system") &&
+        (info.ovs_type == OVS_VPORT_TYPE_INTERNAL)) {
+        VLOG_DBG("construct device %s, ovs_type: %u failed",
+                 netdev_get_name(&netdev->up), info.ovs_type);
+        return 1;
+    }
+
     netdev->change_seq = 1;
     netdev->dev_type = info.ovs_type;
     netdev->port_no = info.port_no;
diff -u -N -r openvswitch-3.1.0/lib/ovs-thread.c 
openvswitch-3.1.1/lib/ovs-thread.c
--- openvswitch-3.1.0/lib/ovs-thread.c  2023-02-16 17:31:13.574879633 +0100
+++ openvswitch-3.1.1/lib/ovs-thread.c  2023-04-06 17:12:13.123813772 +0200
@@ -674,7 +674,7 @@
     static int cpu_cores;
 
     ovs_mutex_lock(&cpu_cores_mutex);
-    if (now - last_updated >= COUNT_CPU_UPDATE_TIME_MS) {
+    if (!last_updated || now - last_updated >= COUNT_CPU_UPDATE_TIME_MS) {
         last_updated = now;
         cpu_cores = count_cpu_cores__();
     }
diff -u -N -r openvswitch-3.1.0/m4/libtool.m4 openvswitch-3.1.1/m4/libtool.m4
--- openvswitch-3.1.0/m4/libtool.m4     2023-02-16 17:31:19.616879633 +0100
+++ openvswitch-3.1.1/m4/libtool.m4     2023-04-06 17:12:15.932816031 +0200
@@ -1,6 +1,7 @@
 # libtool.m4 - Configure libtool for the host system. -*-Autoconf-*-
 #
-#   Copyright (C) 1996-2001, 2003-2015 Free Software Foundation, Inc.
+#   Copyright (C) 1996-2001, 2003-2019, 2021-2022 Free Software
+#   Foundation, Inc.
 #   Written by Gordon Matzigkeit, 1996
 #
 # This file is free software; the Free Software Foundation gives
@@ -31,7 +32,7 @@
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 ])
 
-# serial 58 LT_INIT
+# serial 59 LT_INIT
 
 
 # LT_PREREQ(VERSION)
@@ -181,6 +182,7 @@
 m4_require([_LT_CHECK_SHELL_FEATURES])dnl
 m4_require([_LT_PATH_CONVERSION_FUNCTIONS])dnl
 m4_require([_LT_CMD_RELOAD])dnl
+m4_require([_LT_DECL_FILECMD])dnl
 m4_require([_LT_CHECK_MAGIC_METHOD])dnl
 m4_require([_LT_CHECK_SHAREDLIB_FROM_LINKLIB])dnl
 m4_require([_LT_CMD_OLD_ARCHIVE])dnl
@@ -219,8 +221,8 @@
 ofile=libtool
 can_build_shared=yes
 
-# All known linkers require a '.a' archive for static linking (except MSVC,
-# which needs '.lib').
+# All known linkers require a '.a' archive for static linking (except MSVC and
+# ICC, which need '.lib').
 libext=a
 
 with_gnu_ld=$lt_cv_prog_gnu_ld
@@ -778,7 +780,7 @@
   # if finds mixed CR/LF and LF-only lines.  Since sed operates in
   # text mode, it properly converts lines to CR/LF.  This bash problem
   # is reportedly fixed, but why not run on old versions too?
-  sed '$q' "$ltmain" >> "$cfgfile" \
+  $SED '$q' "$ltmain" >> "$cfgfile" \
      || (rm -f "$cfgfile"; exit 1)
 
    mv -f "$cfgfile" "$ofile" ||
@@ -1042,8 +1044,8 @@
 _LT_EOF
       echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&AS_MESSAGE_LOG_FD
       $LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&AS_MESSAGE_LOG_FD
-      echo "$AR cru libconftest.a conftest.o" >&AS_MESSAGE_LOG_FD
-      $AR cru libconftest.a conftest.o 2>&AS_MESSAGE_LOG_FD
+      echo "$AR $AR_FLAGS libconftest.a conftest.o" >&AS_MESSAGE_LOG_FD
+      $AR $AR_FLAGS libconftest.a conftest.o 2>&AS_MESSAGE_LOG_FD
       echo "$RANLIB libconftest.a" >&AS_MESSAGE_LOG_FD
       $RANLIB libconftest.a 2>&AS_MESSAGE_LOG_FD
       cat > conftest.c << _LT_EOF
@@ -1067,17 +1069,12 @@
       _lt_dar_allow_undefined='$wl-undefined ${wl}suppress' ;;
     darwin1.*)
       _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' 
;;
-    darwin*) # darwin 5.x on
-      # if running on 10.5 or later, the deployment target defaults
-      # to the OS version, if on x86, and 10.4, the deployment
-      # target defaults to 10.4. Don't you love it?
-      case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in
-       10.0,*86*-darwin8*|10.0,*-darwin[[91]]*)
-         _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;;
-       10.[[012]][[,.]]*)
-         _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined 
${wl}suppress' ;;
-       10.*)
-         _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;;
+    darwin*)
+      case $MACOSX_DEPLOYMENT_TARGET,$host in
+        10.[[012]],*|,*powerpc*-darwin[[5-8]]*)
+          _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined 
${wl}suppress' ;;
+        *)
+          _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;;
       esac
     ;;
   esac
@@ -1126,12 +1123,12 @@
     output_verbose_link_cmd=func_echo_all
     _LT_TAGVAR(archive_cmds, $1)="\$CC -dynamiclib \$allow_undefined_flag -o 
\$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname 
\$verstring $_lt_dar_single_mod$_lt_dsymutil"
     _LT_TAGVAR(module_cmds, $1)="\$CC \$allow_undefined_flag -o \$lib -bundle 
\$libobjs \$deplibs \$compiler_flags$_lt_dsymutil"
-    _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's|^|_|' < \$export_symbols > 
\$output_objdir/\$libname-symbols.expsym~\$CC -dynamiclib 
\$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags 
-install_name \$rpath/\$soname \$verstring 
$_lt_dar_single_mod$_lt_dar_export_syms$_lt_dsymutil"
-    _LT_TAGVAR(module_expsym_cmds, $1)="sed -e 's|^|_|' < \$export_symbols > 
\$output_objdir/\$libname-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib 
-bundle \$libobjs \$deplibs \$compiler_flags$_lt_dar_export_syms$_lt_dsymutil"
+    _LT_TAGVAR(archive_expsym_cmds, $1)="$SED 's|^|_|' < \$export_symbols > 
\$output_objdir/\$libname-symbols.expsym~\$CC -dynamiclib 
\$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags 
-install_name \$rpath/\$soname \$verstring 
$_lt_dar_single_mod$_lt_dar_export_syms$_lt_dsymutil"
+    _LT_TAGVAR(module_expsym_cmds, $1)="$SED -e 's|^|_|' < \$export_symbols > 
\$output_objdir/\$libname-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib 
-bundle \$libobjs \$deplibs \$compiler_flags$_lt_dar_export_syms$_lt_dsymutil"
     m4_if([$1], [CXX],
 [   if test yes != "$lt_cv_apple_cc_single_mod"; then
       _LT_TAGVAR(archive_cmds, $1)="\$CC -r -keep_private_externs -nostdlib -o 
\$lib-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib 
\$lib-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname 
\$verstring$_lt_dsymutil"
-      _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's|^|_|' < \$export_symbols > 
\$output_objdir/\$libname-symbols.expsym~\$CC -r -keep_private_externs 
-nostdlib -o \$lib-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag 
-o \$lib \$lib-master.o \$deplibs \$compiler_flags -install_name 
\$rpath/\$soname \$verstring$_lt_dar_export_syms$_lt_dsymutil"
+      _LT_TAGVAR(archive_expsym_cmds, $1)="$SED 's|^|_|' < \$export_symbols > 
\$output_objdir/\$libname-symbols.expsym~\$CC -r -keep_private_externs 
-nostdlib -o \$lib-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag 
-o \$lib \$lib-master.o \$deplibs \$compiler_flags -install_name 
\$rpath/\$soname \$verstring$_lt_dar_export_syms$_lt_dsymutil"
     fi
 ],[])
   else
@@ -1245,7 +1242,8 @@
 # _LT_WITH_SYSROOT
 # ----------------
 AC_DEFUN([_LT_WITH_SYSROOT],
-[AC_MSG_CHECKING([for sysroot])
+[m4_require([_LT_DECL_SED])dnl
+AC_MSG_CHECKING([for sysroot])
 AC_ARG_WITH([sysroot],
 [AS_HELP_STRING([--with-sysroot@<:@=DIR@:>@],
   [Search for dependent libraries within DIR (or the compiler's sysroot
@@ -1262,7 +1260,7 @@
    fi
    ;; #(
  /*)
-   lt_sysroot=`echo "$with_sysroot" | sed -e "$sed_quote_subst"`
+   lt_sysroot=`echo "$with_sysroot" | $SED -e "$sed_quote_subst"`
    ;; #(
  no|'')
    ;; #(
@@ -1292,7 +1290,7 @@
   # options accordingly.
   echo 'int i;' > conftest.$ac_ext
   if AC_TRY_EVAL(ac_compile); then
-    case `/usr/bin/file conftest.$ac_objext` in
+    case `$FILECMD conftest.$ac_objext` in
       *ELF-32*)
        HPUX_IA64_MODE=32
        ;;
@@ -1309,7 +1307,7 @@
   echo '[#]line '$LINENO' "configure"' > conftest.$ac_ext
   if AC_TRY_EVAL(ac_compile); then
     if test yes = "$lt_cv_prog_gnu_ld"; then
-      case `/usr/bin/file conftest.$ac_objext` in
+      case `$FILECMD conftest.$ac_objext` in
        *32-bit*)
          LD="${LD-ld} -melf32bsmip"
          ;;
@@ -1321,7 +1319,7 @@
        ;;
       esac
     else
-      case `/usr/bin/file conftest.$ac_objext` in
+      case `$FILECMD conftest.$ac_objext` in
        *32-bit*)
          LD="${LD-ld} -32"
          ;;
@@ -1343,7 +1341,7 @@
   echo '[#]line '$LINENO' "configure"' > conftest.$ac_ext
   if AC_TRY_EVAL(ac_compile); then
     emul=elf
-    case `/usr/bin/file conftest.$ac_objext` in
+    case `$FILECMD conftest.$ac_objext` in
       *32-bit*)
        emul="${emul}32"
        ;;
@@ -1351,7 +1349,7 @@
        emul="${emul}64"
        ;;
     esac
-    case `/usr/bin/file conftest.$ac_objext` in
+    case `$FILECMD conftest.$ac_objext` in
       *MSB*)
        emul="${emul}btsmip"
        ;;
@@ -1359,7 +1357,7 @@
        emul="${emul}ltsmip"
        ;;
     esac
-    case `/usr/bin/file conftest.$ac_objext` in
+    case `$FILECMD conftest.$ac_objext` in
       *N32*)
        emul="${emul}n32"
        ;;
@@ -1379,14 +1377,14 @@
   # not appear in the list.
   echo 'int i;' > conftest.$ac_ext
   if AC_TRY_EVAL(ac_compile); then
-    case `/usr/bin/file conftest.o` in
+    case `$FILECMD conftest.o` in
       *32-bit*)
        case $host in
          x86_64-*kfreebsd*-gnu)
            LD="${LD-ld} -m elf_i386_fbsd"
            ;;
          x86_64-*linux*)
-           case `/usr/bin/file conftest.o` in
+           case `$FILECMD conftest.o` in
              *x86-64*)
                LD="${LD-ld} -m elf32_x86_64"
                ;;
@@ -1454,7 +1452,7 @@
   # options accordingly.
   echo 'int i;' > conftest.$ac_ext
   if AC_TRY_EVAL(ac_compile); then
-    case `/usr/bin/file conftest.o` in
+    case `$FILECMD conftest.o` in
     *64-bit*)
       case $lt_cv_prog_gnu_ld in
       yes*)
@@ -1493,9 +1491,22 @@
 m4_defun([_LT_PROG_AR],
 [AC_CHECK_TOOLS(AR, [ar], false)
 : ${AR=ar}
-: ${AR_FLAGS=cru}
 _LT_DECL([], [AR], [1], [The archiver])
-_LT_DECL([], [AR_FLAGS], [1], [Flags to create an archive])
+
+# Use ARFLAGS variable as AR's operation code to sync the variable naming with
+# Automake.  If both AR_FLAGS and ARFLAGS are specified, AR_FLAGS should have
+# higher priority because thats what people were doing historically (setting
+# ARFLAGS for automake and AR_FLAGS for libtool).  FIXME: Make the AR_FLAGS
+# variable obsoleted/removed.
+
+test ${AR_FLAGS+y} || AR_FLAGS=${ARFLAGS-cr}
+lt_ar_flags=$AR_FLAGS
+_LT_DECL([], [lt_ar_flags], [0], [Flags to create an archive (by configure)])
+
+# Make AR_FLAGS overridable by 'make ARFLAGS='.  Don't try to run-time override
+# by AR_FLAGS because that was never working and AR_FLAGS is about to die.
+_LT_DECL([], [AR_FLAGS], [\@S|@{ARFLAGS-"\@S|@lt_ar_flags"}],
+         [Flags to create an archive])
 
 AC_CACHE_CHECK([for archiver @FILE support], [lt_cv_ar_at_file],
   [lt_cv_ar_at_file=no
@@ -1714,7 +1725,7 @@
     lt_cv_sys_max_cmd_len=8192;
     ;;
 
-  bitrig* | darwin* | dragonfly* | freebsd* | netbsd* | openbsd*)
+  bitrig* | darwin* | dragonfly* | freebsd* | midnightbsd* | netbsd* | 
openbsd*)
     # This has been around since 386BSD, at least.  Likely further.
     if test -x /sbin/sysctl; then
       lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax`
@@ -1757,7 +1768,7 @@
   sysv5* | sco5v6* | sysv4.2uw2*)
     kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null`
     if test -n "$kargmax"; then
-      lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[[        ]]//'`
+      lt_cv_sys_max_cmd_len=`echo $kargmax | $SED 's/.*[[       ]]//'`
     else
       lt_cv_sys_max_cmd_len=32768
     fi
@@ -2207,26 +2218,35 @@
 striplib=
 old_striplib=
 AC_MSG_CHECKING([whether stripping libraries is possible])
-if test -n "$STRIP" && $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then
-  test -z "$old_striplib" && old_striplib="$STRIP --strip-debug"
-  test -z "$striplib" && striplib="$STRIP --strip-unneeded"
-  AC_MSG_RESULT([yes])
+if test -z "$STRIP"; then
+  AC_MSG_RESULT([no])
 else
-# FIXME - insert some real tests, host_os isn't really good enough
-  case $host_os in
-  darwin*)
-    if test -n "$STRIP"; then
+  if $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then
+    old_striplib="$STRIP --strip-debug"
+    striplib="$STRIP --strip-unneeded"
+    AC_MSG_RESULT([yes])
+  else
+    case $host_os in
+    darwin*)
+      # FIXME - insert some real tests, host_os isn't really good enough
       striplib="$STRIP -x"
       old_striplib="$STRIP -S"
       AC_MSG_RESULT([yes])
-    else
+      ;;
+    freebsd*)
+      if $STRIP -V 2>&1 | $GREP "elftoolchain" >/dev/null; then
+        old_striplib="$STRIP --strip-debug"
+        striplib="$STRIP --strip-unneeded"
+        AC_MSG_RESULT([yes])
+      else
+        AC_MSG_RESULT([no])
+      fi
+      ;;
+    *)
       AC_MSG_RESULT([no])
-    fi
-    ;;
-  *)
-    AC_MSG_RESULT([no])
-    ;;
-  esac
+      ;;
+    esac
+  fi
 fi
 _LT_DECL([], [old_striplib], [1], [Commands to strip libraries])
 _LT_DECL([], [striplib], [1])
@@ -2549,7 +2569,7 @@
     case $host_os in
     cygwin*)
       # Cygwin DLLs use 'cyg' prefix rather than 'lib'
-      soname_spec='`echo $libname | sed -e 's/^lib/cyg/'``echo $release | $SED 
-e 's/[[.]]/-/g'`$versuffix$shared_ext'
+      soname_spec='`echo $libname | $SED -e 's/^lib/cyg/'``echo $release | 
$SED -e 's/[[.]]/-/g'`$versuffix$shared_ext'
 m4_if([$1], [],[
       sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api"])
       ;;
@@ -2559,14 +2579,14 @@
       ;;
     pw32*)
       # pw32 DLLs use 'pw' prefix rather than 'lib'
-      library_names_spec='`echo $libname | sed -e 's/^lib/pw/'``echo $release 
| $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext'
+      library_names_spec='`echo $libname | $SED -e 's/^lib/pw/'``echo $release 
| $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext'
       ;;
     esac
     dynamic_linker='Win32 ld.exe'
     ;;
 
-  *,cl*)
-    # Native MSVC
+  *,cl* | *,icl*)
+    # Native MSVC or ICC
     libname_spec='$name'
     soname_spec='$libname`echo $release | $SED -e 
's/[[.]]/-/g'`$versuffix$shared_ext'
     library_names_spec='$libname.dll.lib'
@@ -2585,7 +2605,7 @@
       done
       IFS=$lt_save_ifs
       # Convert to MSYS style.
-      sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | sed -e 
's|\\\\|/|g' -e 's| \\([[a-zA-Z]]\\):| /\\1|g' -e 's|^ ||'`
+      sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 
's|\\\\|/|g' -e 's| \\([[a-zA-Z]]\\):| /\\1|g' -e 's|^ ||'`
       ;;
     cygwin*)
       # Convert to unix form, then to dos form, then back to unix form
@@ -2622,7 +2642,7 @@
     ;;
 
   *)
-    # Assume MSVC wrapper
+    # Assume MSVC and ICC wrapper
     library_names_spec='$libname`echo $release | $SED -e 
's/[[.]]/-/g'`$versuffix$shared_ext $libname.lib'
     dynamic_linker='Win32 ld.exe'
     ;;
@@ -2655,7 +2675,7 @@
   shlibpath_var=LD_LIBRARY_PATH
   ;;
 
-freebsd* | dragonfly*)
+freebsd* | dragonfly* | midnightbsd*)
   # DragonFly does not have aout.  When/if they implement a new
   # versioning mechanism, adjust this.
   if test -x /usr/bin/objformat; then
@@ -3457,7 +3477,7 @@
 
 bsdi[[45]]*)
   lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB 
(shared object|dynamic lib)'
-  lt_cv_file_magic_cmd='/usr/bin/file -L'
+  lt_cv_file_magic_cmd='$FILECMD -L'
   lt_cv_file_magic_test_file=/shlib/libc.so
   ;;
 
@@ -3491,14 +3511,14 @@
   lt_cv_deplibs_check_method=pass_all
   ;;
 
-freebsd* | dragonfly*)
+freebsd* | dragonfly* | midnightbsd*)
   if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then
     case $host_cpu in
     i*86 )
       # Not sure whether the presence of OpenBSD here was a mistake.
       # Let's accept both of them until this is cleared up.
       lt_cv_deplibs_check_method='file_magic 
(FreeBSD|OpenBSD|DragonFly)/i[[3-9]]86 (compact )?demand paged shared library'
-      lt_cv_file_magic_cmd=/usr/bin/file
+      lt_cv_file_magic_cmd=$FILECMD
       lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*`
       ;;
     esac
@@ -3512,7 +3532,7 @@
   ;;
 
 hpux10.20* | hpux11*)
-  lt_cv_file_magic_cmd=/usr/bin/file
+  lt_cv_file_magic_cmd=$FILECMD
   case $host_cpu in
   ia64*)
     lt_cv_deplibs_check_method='file_magic 
(s[[0-9]][[0-9]][[0-9]]|ELF-[[0-9]][[0-9]]) shared object file - IA64'
@@ -3559,7 +3579,7 @@
 
 newos6*)
   lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB 
(executable|dynamic lib)'
-  lt_cv_file_magic_cmd=/usr/bin/file
+  lt_cv_file_magic_cmd=$FILECMD
   lt_cv_file_magic_test_file=/usr/lib/libnls.so
   ;;
 
@@ -3686,13 +3706,13 @@
        mingw*) lt_bad_file=conftest.nm/nofile ;;
        *) lt_bad_file=/dev/null ;;
        esac
-       case `"$tmp_nm" -B $lt_bad_file 2>&1 | sed '1q'` in
+       case `"$tmp_nm" -B $lt_bad_file 2>&1 | $SED '1q'` in
        *$lt_bad_file* | *'Invalid file or object type'*)
          lt_cv_path_NM="$tmp_nm -B"
          break 2
          ;;
        *)
-         case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in
+         case `"$tmp_nm" -p /dev/null 2>&1 | $SED '1q'` in
          */dev/null*)
            lt_cv_path_NM="$tmp_nm -p"
            break 2
@@ -3718,7 +3738,7 @@
     # Let the user override the test.
   else
     AC_CHECK_TOOLS(DUMPBIN, [dumpbin "link -dump"], :)
-    case `$DUMPBIN -symbols -headers /dev/null 2>&1 | sed '1q'` in
+    case `$DUMPBIN -symbols -headers /dev/null 2>&1 | $SED '1q'` in
     *COFF*)
       DUMPBIN="$DUMPBIN -symbols -headers"
       ;;
@@ -3958,7 +3978,7 @@
 
 if test "$lt_cv_nm_interface" = "MS dumpbin"; then
   # Gets list of data symbols to import.
-  lt_cv_sys_global_symbol_to_import="sed -n -e 's/^I .* \(.*\)$/\1/p'"
+  lt_cv_sys_global_symbol_to_import="$SED -n -e 's/^I .* \(.*\)$/\1/p'"
   # Adjust the below global symbol transforms to fixup imported variables.
   lt_cdecl_hook=" -e 's/^I .* \(.*\)$/extern __declspec(dllimport) char \1;/p'"
   lt_c_name_hook=" -e 's/^I .* \(.*\)$/  {\"\1\", (void *) 0},/p'"
@@ -3976,20 +3996,20 @@
 # Transform an extracted symbol line into a proper C declaration.
 # Some systems (esp. on ia64) link data and code symbols differently,
 # so use this general approach.
-lt_cv_sys_global_symbol_to_cdecl="sed -n"\
+lt_cv_sys_global_symbol_to_cdecl="$SED -n"\
 $lt_cdecl_hook\
 " -e 's/^T .* \(.*\)$/extern int \1();/p'"\
 " -e 's/^$symcode$symcode* .* \(.*\)$/extern char \1;/p'"
 
 # Transform an extracted symbol line into symbol name and symbol address
-lt_cv_sys_global_symbol_to_c_name_address="sed -n"\
+lt_cv_sys_global_symbol_to_c_name_address="$SED -n"\
 $lt_c_name_hook\
 " -e 's/^: \(.*\) .*$/  {\"\1\", (void *) 0},/p'"\
 " -e 's/^$symcode$symcode* .* \(.*\)$/  {\"\1\", (void *) \&\1},/p'"
 
 # Transform an extracted symbol line into symbol name with lib prefix and
 # symbol address.
-lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n"\
+lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="$SED -n"\
 $lt_c_name_lib_hook\
 " -e 's/^: \(.*\) .*$/  {\"\1\", (void *) 0},/p'"\
 " -e 's/^$symcode$symcode* .* \(lib.*\)$/  {\"\1\", (void *) \&\1},/p'"\
@@ -4013,7 +4033,7 @@
   if test "$lt_cv_nm_interface" = "MS dumpbin"; then
     # Fake it for dumpbin and say T for any non-static function,
     # D for any global variable and I for any imported variable.
-    # Also find C++ and __fastcall symbols from MSVC++,
+    # Also find C++ and __fastcall symbols from MSVC++ or ICC,
     # which start with @ or ?.
     lt_cv_sys_global_symbol_pipe="$AWK ['"\
 "     {last_section=section; section=\$ 3};"\
@@ -4031,9 +4051,9 @@
 "     s[1]~prfx {split(s[1],t,\"@\"); print f,t[1],substr(t[1],length(prfx))}"\
 "     ' prfx=^$ac_symprfx]"
   else
-    lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[[    
]]\($symcode$symcode*\)[[       ]][[    
]]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'"
+    lt_cv_sys_global_symbol_pipe="$SED -n -e 's/^.*[[   
]]\($symcode$symcode*\)[[       ]][[    
]]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'"
   fi
-  lt_cv_sys_global_symbol_pipe="$lt_cv_sys_global_symbol_pipe | sed '/ 
__gnu_lto/d'"
+  lt_cv_sys_global_symbol_pipe="$lt_cv_sys_global_symbol_pipe | $SED '/ 
__gnu_lto/d'"
 
   # Check to see that the pipe works correctly.
   pipe_works=no
@@ -4320,7 +4340,7 @@
            ;;
        esac
        ;;
-      freebsd* | dragonfly*)
+      freebsd* | dragonfly* | midnightbsd*)
        # FreeBSD uses GNU C++
        ;;
       hpux9* | hpux10* | hpux11*)
@@ -4403,7 +4423,7 @@
            _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink'
            ;;
          *)
-           case `$CC -V 2>&1 | sed 5q` in
+           case `$CC -V 2>&1 | $SED 5q` in
            *Sun\ C*)
              # Sun C++ 5.9
              _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
@@ -4739,7 +4759,7 @@
        _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink'
        ;;
       *)
-       case `$CC -V 2>&1 | sed 5q` in
+       case `$CC -V 2>&1 | $SED 5q` in
        *Sun\ Ceres\ Fortran* | *Sun*Fortran*\ [[1-7]].* | *Sun*Fortran*\ 
8.[[0-3]]*)
          # Sun Fortran 8.3 passes all unrecognized flags to the linker
          _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
@@ -4922,7 +4942,7 @@
     if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then
       _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | 
awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == 
"W")) && ([substr](\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } 
else { print \$ 3 } } }'\'' | sort -u > $export_symbols'
     else
-      _LT_TAGVAR(export_symbols_cmds, $1)='`func_echo_all $NM | $SED -e 
'\''s/B\([[^B]]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 
2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W") || (\$ 2 == "V") 
|| (\$ 2 == "Z")) && ([substr](\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 
== "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | 
sort -u > $export_symbols'
+      _LT_TAGVAR(export_symbols_cmds, $1)='`func_echo_all $NM | $SED -e 
'\''s/B\([[^B]]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 
2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "L") || (\$ 2 == "W") 
|| (\$ 2 == "V") || (\$ 2 == "Z")) && ([substr](\$ 1,1,1) != ".")) { if ((\$ 2 
== "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print 
\$ 1 } } }'\'' | sort -u > $export_symbols'
     fi
     ;;
   pw32*)
@@ -4930,7 +4950,7 @@
     ;;
   cygwin* | mingw* | cegcc*)
     case $cc_basename in
-    cl*)
+    cl* | icl*)
       _LT_TAGVAR(exclude_expsyms, 
$1)='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*'
       ;;
     *)
@@ -4987,15 +5007,15 @@
 
   case $host_os in
   cygwin* | mingw* | pw32* | cegcc*)
-    # FIXME: the MSVC++ port hasn't been tested in a loooong time
+    # FIXME: the MSVC++ and ICC port hasn't been tested in a loooong time
     # When not using gcc, we currently assume that we are using
-    # Microsoft Visual C++.
+    # Microsoft Visual C++ or Intel C++ Compiler.
     if test yes != "$GCC"; then
       with_gnu_ld=no
     fi
     ;;
   interix*)
-    # we just hope/assume this is gcc and not c89 (= MSVC++)
+    # we just hope/assume this is gcc and not c89 (= MSVC++ or ICC)
     with_gnu_ld=yes
     ;;
   openbsd* | bitrig*)
@@ -5047,7 +5067,7 @@
       _LT_TAGVAR(whole_archive_flag_spec, $1)=
     fi
     supports_anon_versioning=no
-    case `$LD -v | $SED -e 's/([^)]\+)\s\+//' 2>&1` in
+    case `$LD -v | $SED -e 's/([[^)]]\+)\s\+//' 2>&1` in
       *GNU\ gold*) supports_anon_versioning=yes ;;
       *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.10.*) ;; # catch versions < 2.11
       *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ...
@@ -5159,6 +5179,7 @@
        emximp -o $lib $output_objdir/$libname.def'
       _LT_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o 
$output_objdir/${libname}_dll.a $output_objdir/$libname.def'
       _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
+      _LT_TAGVAR(file_list_spec, $1)='@'
       ;;
 
     interix[[3-9]]*)
@@ -5173,7 +5194,7 @@
       # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link
       # time.  Moving up from 0x10000000 also allows more sbrk(2) space.
       _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs 
$compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 
262144 + 1342177280` -o $lib'
-      _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s|^|_|" $export_symbols 
>$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs 
$compiler_flags $wl-h,$soname 
$wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr 
${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+      _LT_TAGVAR(archive_expsym_cmds, $1)='$SED "s|^|_|" $export_symbols 
>$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs 
$compiler_flags $wl-h,$soname 
$wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr 
${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
       ;;
 
     gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu)
@@ -5216,7 +5237,7 @@
          _LT_TAGVAR(compiler_needs_object, $1)=yes
          ;;
        esac
-       case `$CC -V 2>&1 | sed 5q` in
+       case `$CC -V 2>&1 | $SED 5q` in
        *Sun\ C*)                       # Sun C 5.9
          _LT_TAGVAR(whole_archive_flag_spec, 
$1)='$wl--whole-archive`new_convenience=; for conv in $convenience\"\"; do test 
-z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all 
\"$new_convenience\"` $wl--no-whole-archive'
          _LT_TAGVAR(compiler_needs_object, $1)=yes
@@ -5228,7 +5249,7 @@
 
         if test yes = "$supports_anon_versioning"; then
           _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > 
$output_objdir/$libname.ver~
-            cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> 
$output_objdir/$libname.ver~
+            cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> 
$output_objdir/$libname.ver~
             echo "local: *; };" >> $output_objdir/$libname.ver~
             $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs 
$compiler_flags $wl-soname $wl$soname $wl-version-script 
$wl$output_objdir/$libname.ver -o $lib'
         fi
@@ -5244,7 +5265,7 @@
          _LT_TAGVAR(archive_cmds, $1)='$LD -shared $libobjs $deplibs 
$linker_flags -soname $soname -o $lib'
          if test yes = "$supports_anon_versioning"; then
            _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > 
$output_objdir/$libname.ver~
-              cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> 
$output_objdir/$libname.ver~
+              cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> 
$output_objdir/$libname.ver~
               echo "local: *; };" >> $output_objdir/$libname.ver~
               $LD -shared $libobjs $deplibs $linker_flags -soname $soname 
-version-script $output_objdir/$libname.ver -o $lib'
          fi
@@ -5376,7 +5397,7 @@
        if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then
          _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | 
awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == 
"W")) && ([substr](\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } 
else { print \$ 3 } } }'\'' | sort -u > $export_symbols'
        else
-         _LT_TAGVAR(export_symbols_cmds, $1)='`func_echo_all $NM | $SED -e 
'\''s/B\([[^B]]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 
2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W") || (\$ 2 == "V") 
|| (\$ 2 == "Z")) && ([substr](\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 
== "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | 
sort -u > $export_symbols'
+         _LT_TAGVAR(export_symbols_cmds, $1)='`func_echo_all $NM | $SED -e 
'\''s/B\([[^B]]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 
2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "L") || (\$ 2 == "W") 
|| (\$ 2 == "V") || (\$ 2 == "Z")) && ([substr](\$ 1,1,1) != ".")) { if ((\$ 2 
== "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print 
\$ 1 } } }'\'' | sort -u > $export_symbols'
        fi
        aix_use_runtimelinking=no
 
@@ -5559,12 +5580,12 @@
 
     cygwin* | mingw* | pw32* | cegcc*)
       # When not using gcc, we currently assume that we are using
-      # Microsoft Visual C++.
+      # Microsoft Visual C++ or Intel C++ Compiler.
       # hardcode_libdir_flag_spec is actually meaningless, as there is
       # no search path for DLLs.
       case $cc_basename in
-      cl*)
-       # Native MSVC
+      cl* | icl*)
+       # Native MSVC or ICC
        _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' '
        _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
        _LT_TAGVAR(always_export_symbols, $1)=yes
@@ -5605,7 +5626,7 @@
           fi'
        ;;
       *)
-       # Assume MSVC wrapper
+       # Assume MSVC and ICC wrapper
        _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' '
        _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
        # Tell ltmain to make .lib files, not .a files.
@@ -5653,7 +5674,7 @@
       ;;
 
     # FreeBSD 3 and greater uses gcc -shared to do shared libraries.
-    freebsd* | dragonfly*)
+    freebsd* | dragonfly* | midnightbsd*)
       _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs 
$deplibs $compiler_flags'
       _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
       _LT_TAGVAR(hardcode_direct, $1)=yes
@@ -5864,6 +5885,7 @@
        emximp -o $lib $output_objdir/$libname.def'
       _LT_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o 
$output_objdir/${libname}_dll.a $output_objdir/$libname.def'
       _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
+      _LT_TAGVAR(file_list_spec, $1)='@'
       ;;
 
     osf3*)
@@ -6634,8 +6656,8 @@
 
       cygwin* | mingw* | pw32* | cegcc*)
        case $GXX,$cc_basename in
-       ,cl* | no,cl*)
-         # Native MSVC
+       ,cl* | no,cl* | ,icl* | no,icl*)
+         # Native MSVC or ICC
          # hardcode_libdir_flag_spec is actually meaningless, as there is
          # no search path for DLLs.
          _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' '
@@ -6733,6 +6755,7 @@
          emximp -o $lib $output_objdir/$libname.def'
        _LT_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o 
$output_objdir/${libname}_dll.a $output_objdir/$libname.def'
        _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
+       _LT_TAGVAR(file_list_spec, $1)='@'
        ;;
 
       dgux*)
@@ -6763,7 +6786,7 @@
         _LT_TAGVAR(archive_cmds_need_lc, $1)=no
         ;;
 
-      freebsd* | dragonfly*)
+      freebsd* | dragonfly* | midnightbsd*)
         # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF
         # conventions
         _LT_TAGVAR(ld_shlibs, $1)=yes
@@ -6900,7 +6923,7 @@
        # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link
        # time.  Moving up from 0x10000000 also allows more sbrk(2) space.
        _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs 
$compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 
262144 + 1342177280` -o $lib'
-       _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s|^|_|" $export_symbols 
>$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs 
$compiler_flags $wl-h,$soname 
$wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr 
${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+       _LT_TAGVAR(archive_expsym_cmds, $1)='$SED "s|^|_|" $export_symbols 
>$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs 
$compiler_flags $wl-h,$soname 
$wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr 
${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
        ;;
       irix5* | irix6*)
         case $cc_basename in
@@ -7040,13 +7063,13 @@
            _LT_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj $libobjs $deplibs 
$compiler_flags $wl-soname $wl$soname -o $lib'
            if test yes = "$supports_anon_versioning"; then
              _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > 
$output_objdir/$libname.ver~
-                cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> 
$output_objdir/$libname.ver~
+                cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> 
$output_objdir/$libname.ver~
                 echo "local: *; };" >> $output_objdir/$libname.ver~
                 $CC -qmkshrobj $libobjs $deplibs $compiler_flags $wl-soname 
$wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib'
            fi
            ;;
          *)
-           case `$CC -V 2>&1 | sed 5q` in
+           case `$CC -V 2>&1 | $SED 5q` in
            *Sun\ C*)
              # Sun C++ 5.9
              _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs'
@@ -8192,6 +8215,14 @@
 AC_SUBST([DLLTOOL])
 ])
 
+# _LT_DECL_FILECMD
+# ----------------
+# Check for a file(cmd) program that can be used to detect file type and magic
+m4_defun([_LT_DECL_FILECMD],
+[AC_CHECK_TOOL([FILECMD], [file], [:])
+_LT_DECL([], [FILECMD], [1], [A file(cmd) program that detects file types])
+])# _LD_DECL_FILECMD
+
 # _LT_DECL_SED
 # ------------
 # Check for a fully-functional sed program, that truncates
diff -u -N -r openvswitch-3.1.0/m4/lt~obsolete.m4 
openvswitch-3.1.1/m4/lt~obsolete.m4
--- openvswitch-3.1.0/m4/lt~obsolete.m4 2023-02-16 17:31:20.076879633 +0100
+++ openvswitch-3.1.1/m4/lt~obsolete.m4 2023-04-06 17:12:16.008816092 +0200
@@ -1,7 +1,7 @@
 # lt~obsolete.m4 -- aclocal satisfying obsolete definitions.    -*-Autoconf-*-
 #
-#   Copyright (C) 2004-2005, 2007, 2009, 2011-2015 Free Software
-#   Foundation, Inc.
+#   Copyright (C) 2004-2005, 2007, 2009, 2011-2019, 2021-2022 Free
+#   Software Foundation, Inc.
 #   Written by Scott James Remnant, 2004.
 #
 # This file is free software; the Free Software Foundation gives
diff -u -N -r openvswitch-3.1.0/m4/ltoptions.m4 
openvswitch-3.1.1/m4/ltoptions.m4
--- openvswitch-3.1.0/m4/ltoptions.m4   2023-02-16 17:31:19.730879633 +0100
+++ openvswitch-3.1.1/m4/ltoptions.m4   2023-04-06 17:12:15.950816046 +0200
@@ -1,7 +1,7 @@
 # Helper functions for option handling.                    -*- Autoconf -*-
 #
-#   Copyright (C) 2004-2005, 2007-2009, 2011-2015 Free Software
-#   Foundation, Inc.
+#   Copyright (C) 2004-2005, 2007-2009, 2011-2019, 2021-2022 Free
+#   Software Foundation, Inc.
 #   Written by Gary V. Vaughan, 2004
 #
 # This file is free software; the Free Software Foundation gives
diff -u -N -r openvswitch-3.1.0/m4/ltsugar.m4 openvswitch-3.1.1/m4/ltsugar.m4
--- openvswitch-3.1.0/m4/ltsugar.m4     2023-02-16 17:31:19.846879633 +0100
+++ openvswitch-3.1.1/m4/ltsugar.m4     2023-04-06 17:12:15.968816060 +0200
@@ -1,6 +1,6 @@
 # ltsugar.m4 -- libtool m4 base layer.                         -*-Autoconf-*-
 #
-# Copyright (C) 2004-2005, 2007-2008, 2011-2015 Free Software
+# Copyright (C) 2004-2005, 2007-2008, 2011-2019, 2021-2022 Free Software
 # Foundation, Inc.
 # Written by Gary V. Vaughan, 2004
 #
diff -u -N -r openvswitch-3.1.0/m4/ltversion.m4 
openvswitch-3.1.1/m4/ltversion.m4
--- openvswitch-3.1.0/m4/ltversion.m4   2023-02-16 17:31:19.961879633 +0100
+++ openvswitch-3.1.1/m4/ltversion.m4   2023-04-06 17:12:15.987816076 +0200
@@ -1,6 +1,7 @@
 # ltversion.m4 -- version numbers                      -*- Autoconf -*-
 #
-#   Copyright (C) 2004, 2011-2015 Free Software Foundation, Inc.
+#   Copyright (C) 2004, 2011-2019, 2021-2022 Free Software Foundation,
+#   Inc.
 #   Written by Scott James Remnant, 2004
 #
 # This file is free software; the Free Software Foundation gives
@@ -9,15 +10,15 @@
 
 # @configure_input@
 
-# serial 4179 ltversion.m4
+# serial 4245 ltversion.m4
 # This file is part of GNU Libtool
 
-m4_define([LT_PACKAGE_VERSION], [2.4.6])
-m4_define([LT_PACKAGE_REVISION], [2.4.6])
+m4_define([LT_PACKAGE_VERSION], [2.4.7])
+m4_define([LT_PACKAGE_REVISION], [2.4.7])
 
 AC_DEFUN([LTVERSION_VERSION],
-[macro_version='2.4.6'
-macro_revision='2.4.6'
+[macro_version='2.4.7'
+macro_revision='2.4.7'
 _LT_DECL(, macro_version, 0, [Which release of libtool.m4 was used?])
 _LT_DECL(, macro_revision, 0)
 ])
diff -u -N -r openvswitch-3.1.0/Makefile.in openvswitch-3.1.1/Makefile.in
--- openvswitch-3.1.0/Makefile.in       2023-02-16 17:31:24.981879633 +0100
+++ openvswitch-3.1.1/Makefile.in       2023-04-06 17:12:18.798818336 +0200
@@ -1,7 +1,7 @@
-# Makefile.in generated by automake 1.16.2 from Makefile.am.
+# Makefile.in generated by automake 1.16.5 from Makefile.am.
 # @configure_input@
 
-# Copyright (C) 1994-2020 Free Software Foundation, Inc.
+# Copyright (C) 1994-2021 Free Software Foundation, Inc.
 
 # This Makefile.in is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
@@ -1259,9 +1259,6 @@
   unique=`for i in $$list; do \
     if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
   done | $(am__uniquify_input)`
-ETAGS = etags
-CTAGS = ctags
-CSCOPE = cscope
 AM_RECURSIVE_TARGETS = cscope
 am__DIST_COMMON = $(dist_man_MANS) $(srcdir)/Documentation/automake.mk \
        $(srcdir)/Makefile.in $(srcdir)/build-aux/automake.mk \
@@ -1317,6 +1314,8 @@
 DIST_ARCHIVES = $(distdir).tar.gz
 GZIP_ENV = --best
 DIST_TARGETS = dist-gzip
+# Exists only to be overridden by the user if desired.
+AM_DISTCHECK_DVI_TARGET = dvi
 distuninstallcheck_listfiles = find . -type f -print
 am__distuninstallcheck_listfiles = $(distuninstallcheck_listfiles) \
   | sed 's|^\./|$(prefix)/|' | grep -v '$(infodir)/dir$$'
@@ -1337,6 +1336,8 @@
 CGCCFLAGS = @CGCCFLAGS@
 CPP = @CPP@
 CPPFLAGS = @CPPFLAGS@
+CSCOPE = @CSCOPE@
+CTAGS = @CTAGS@
 CXX = @CXX@
 CXXCPP = @CXXCPP@
 CXXDEPMODE = @CXXDEPMODE@
@@ -1355,8 +1356,10 @@
 ECHO_N = @ECHO_N@
 ECHO_T = @ECHO_T@
 EGREP = @EGREP@
+ETAGS = @ETAGS@
 EXEEXT = @EXEEXT@
 FGREP = @FGREP@
+FILECMD = @FILECMD@
 FLAKE8_WERROR = @FLAKE8_WERROR@
 GREP = @GREP@
 HAVE_CXX11 = @HAVE_CXX11@
@@ -5500,7 +5503,6 @@
 distclean-tags:
        -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
        -rm -f cscope.out cscope.in.out cscope.po.out cscope.files
-
 distdir: $(BUILT_SOURCES)
        $(MAKE) $(AM_MAKEFLAGS) distdir-am
 
@@ -5625,7 +5627,7 @@
            $(DISTCHECK_CONFIGURE_FLAGS) \
            --srcdir=../.. --prefix="$$dc_install_base" \
          && $(MAKE) $(AM_MAKEFLAGS) \
-         && $(MAKE) $(AM_MAKEFLAGS) dvi \
+         && $(MAKE) $(AM_MAKEFLAGS) $(AM_DISTCHECK_DVI_TARGET) \
          && $(MAKE) $(AM_MAKEFLAGS) check \
          && $(MAKE) $(AM_MAKEFLAGS) install \
          && $(MAKE) $(AM_MAKEFLAGS) installcheck \
@@ -5683,15 +5685,20 @@
        $(MAKE) $(AM_MAKEFLAGS) check-am
 all-am: Makefile $(PROGRAMS) $(LTLIBRARIES) $(SCRIPTS) $(MANS) $(DATA) \
                $(HEADERS) config.h all-local
+install-EXTRAPROGRAMS: install-libLTLIBRARIES
+
 install-binPROGRAMS: install-libLTLIBRARIES
 
+install-sbinPROGRAMS: install-libLTLIBRARIES
+
 installdirs:
        for dir in "$(DESTDIR)$(bindir)" "$(DESTDIR)$(sbindir)" 
"$(DESTDIR)$(libdir)" "$(DESTDIR)$(bindir)" "$(DESTDIR)$(completiondir)" 
"$(DESTDIR)$(pkgdatadir)" "$(DESTDIR)$(sbindir)" "$(DESTDIR)$(scriptsdir)" 
"$(DESTDIR)$(sbindir)" "$(DESTDIR)$(scriptsdir)" "$(DESTDIR)$(usdtdir)" 
"$(DESTDIR)$(man1dir)" "$(DESTDIR)$(man5dir)" "$(DESTDIR)$(man7dir)" 
"$(DESTDIR)$(man8dir)" "$(DESTDIR)$(pkgdatadir)" "$(DESTDIR)$(scriptsdir)" 
"$(DESTDIR)$(pkgdatadir)" "$(DESTDIR)$(pkgconfigdir)" "$(DESTDIR)$(pkgdatadir)" 
"$(DESTDIR)$(scriptsdir)" "$(DESTDIR)$(openflowincludedir)" 
"$(DESTDIR)$(openvswitchincludedir)"; do \
          test -z "$$dir" || $(MKDIR_P) "$$dir"; \
        done
 install: $(BUILT_SOURCES)
        $(MAKE) $(AM_MAKEFLAGS) install-am
-install-exec: install-exec-am
+install-exec: $(BUILT_SOURCES)
+       $(MAKE) $(AM_MAKEFLAGS) install-exec-am
 install-data: install-data-am
 uninstall: uninstall-am
 
@@ -6529,7 +6536,8 @@
 uninstall-man: uninstall-man1 uninstall-man5 uninstall-man7 \
        uninstall-man8
 
-.MAKE: all check check-am install install-am install-strip
+.MAKE: all check check-am install install-am install-exec \
+       install-strip
 
 .PHONY: CTAGS GTAGS TAGS all all-am all-local am--depfiles am--refresh \
        check check-am check-local clean clean-binPROGRAMS \
diff -u -N -r openvswitch-3.1.0/NEWS openvswitch-3.1.1/NEWS
--- openvswitch-3.1.0/NEWS      2023-02-16 17:31:15.018879633 +0100
+++ openvswitch-3.1.1/NEWS      2023-04-06 17:12:13.110813762 +0200
@@ -1,3 +1,9 @@
+v3.1.1 - 06 Apr 2023
+--------------------
+   - Bug fixes
+   - Security:
+     * Fixed vulnerability CVE-2023-1668.
+
 v3.1.0 - 16 Feb 2023
 --------------------
    - ovs-vswitchd now detects changes in CPU affinity and adjusts the number
diff -u -N -r openvswitch-3.1.0/ofproto/ofproto.c 
openvswitch-3.1.1/ofproto/ofproto.c
--- openvswitch-3.1.0/ofproto/ofproto.c 2023-02-16 17:31:15.046879633 +0100
+++ openvswitch-3.1.1/ofproto/ofproto.c 2023-04-06 17:12:13.131813779 +0200
@@ -311,6 +311,7 @@
 unsigned ofproto_max_idle = OFPROTO_MAX_IDLE_DEFAULT;
 unsigned ofproto_max_revalidator = OFPROTO_MAX_REVALIDATOR_DEFAULT;
 unsigned ofproto_min_revalidate_pps = OFPROTO_MIN_REVALIDATE_PPS_DEFAULT;
+unsigned ofproto_offloaded_stats_delay = OFPROTO_OFFLOADED_STATS_DELAY;
 
 uint32_t n_handlers, n_revalidators;
 
@@ -727,6 +728,15 @@
     ofproto_min_revalidate_pps = min_revalidate_pps ? min_revalidate_pps : 1;
 }
 
+/* Set worst case delay (in ms) it might take before statistics of offloaded
+ * flows are updated. Offloaded flows younger than this delay will always be
+ * revalidated regardless of ofproto_min_revalidate_pps. */
+void
+ofproto_set_offloaded_stats_delay(unsigned offloaded_stats_delay)
+{
+    ofproto_offloaded_stats_delay = offloaded_stats_delay;
+}
+
 /* If forward_bpdu is true, the NORMAL action will forward frames with
  * reserved (e.g. STP) destination Ethernet addresses. if forward_bpdu is 
false,
  * the NORMAL action will drop these frames. */
diff -u -N -r openvswitch-3.1.0/ofproto/ofproto-dpif.c 
openvswitch-3.1.1/ofproto/ofproto-dpif.c
--- openvswitch-3.1.0/ofproto/ofproto-dpif.c    2023-02-16 17:31:13.604879633 
+0100
+++ openvswitch-3.1.1/ofproto/ofproto-dpif.c    2023-04-06 17:12:13.130813778 
+0200
@@ -714,12 +714,6 @@
     free(backer);
 }
 
-/* Datapath port slated for removal from datapath. */
-struct odp_garbage {
-    struct ovs_list list_node;
-    odp_port_t odp_port;
-};
-
 static void check_support(struct dpif_backer *backer);
 
 static int
@@ -729,8 +723,6 @@
     struct dpif_port_dump port_dump;
     struct dpif_port port;
     struct shash_node *node;
-    struct ovs_list garbage_list;
-    struct odp_garbage *garbage;
 
     struct sset names;
     char *backer_name;
@@ -792,25 +784,23 @@
         dpif_flow_flush(backer->dpif);
     }
 
-    /* Loop through the ports already on the datapath and remove any
-     * that we don't need anymore. */
-    ovs_list_init(&garbage_list);
+    /* Loop through the ports already on the datapath and find ones that are
+     * not on the initial OpenFlow ports list.  These are stale ports, that we
+     * do not need anymore, or tunnel backing interfaces, that do not generally
+     * match the name of OpenFlow tunnel ports, or both.  Add all of them to
+     * the list of tunnel backers.  type_run() will garbage collect those that
+     * are not active tunnel backing interfaces during revalidation. */
     dpif_port_dump_start(&port_dump, backer->dpif);
     while (dpif_port_dump_next(&port_dump, &port)) {
         node = shash_find(&init_ofp_ports, port.name);
         if (!node && strcmp(port.name, dpif_base_name(backer->dpif))) {
-            garbage = xmalloc(sizeof *garbage);
-            garbage->odp_port = port.port_no;
-            ovs_list_push_front(&garbage_list, &garbage->list_node);
+            simap_put(&backer->tnl_backers, port.name,
+                      odp_to_u32(port.port_no));
+            backer->need_revalidate = REV_RECONFIGURE;
         }
     }
     dpif_port_dump_done(&port_dump);
 
-    LIST_FOR_EACH_POP (garbage, list_node, &garbage_list) {
-        dpif_port_del(backer->dpif, garbage->odp_port, false);
-        free(garbage);
-    }
-
     shash_add(&all_dpif_backers, type, backer);
 
     check_support(backer);
diff -u -N -r openvswitch-3.1.0/ofproto/ofproto-dpif-ipfix.c 
openvswitch-3.1.1/ofproto/ofproto-dpif-ipfix.c
--- openvswitch-3.1.0/ofproto/ofproto-dpif-ipfix.c      2023-02-16 
17:31:13.599879633 +0100
+++ openvswitch-3.1.1/ofproto/ofproto-dpif-ipfix.c      2023-04-06 
17:10:44.164742239 +0200
@@ -124,11 +124,18 @@
     uint32_t ifindex;
 };
 
+struct dpif_ipfix_domain {
+    struct hmap_node hmap_node; /* In struct dpif_ipfix_exporter's domains. */
+    time_t last_template_set_time;
+};
+
 struct dpif_ipfix_exporter {
     uint32_t exporter_id; /* Exporting Process identifier */
-    struct collectors *collectors;
     uint32_t seq_number;
-    time_t last_template_set_time;
+    struct collectors *collectors;
+    struct hmap domains; /* Contains struct dpif_ipfix_domain indexed by
+                            observation domain id. */
+    time_t last_stats_sent_time;
     struct hmap cache_flow_key_map;  /* ipfix_flow_cache_entry. */
     struct ovs_list cache_flow_start_timestamp_list;  /* 
ipfix_flow_cache_entry. */
     uint32_t cache_active_timeout;  /* In seconds. */
@@ -617,6 +624,9 @@
 
 static void dpif_ipfix_cache_expire_now(struct dpif_ipfix_exporter *, bool);
 
+static void dpif_ipfix_exporter_del_domain(struct dpif_ipfix_exporter *,
+                                           struct dpif_ipfix_domain *);
+
 static bool
 ofproto_ipfix_bridge_exporter_options_equal(
     const struct ofproto_ipfix_bridge_exporter_options *a,
@@ -697,13 +707,14 @@
     exporter->exporter_id = ++exporter_total_count;
     exporter->collectors = NULL;
     exporter->seq_number = 1;
-    exporter->last_template_set_time = 0;
+    exporter->last_stats_sent_time = 0;
     hmap_init(&exporter->cache_flow_key_map);
     ovs_list_init(&exporter->cache_flow_start_timestamp_list);
     exporter->cache_active_timeout = 0;
     exporter->cache_max_flows = 0;
     exporter->virtual_obs_id = NULL;
     exporter->virtual_obs_len = 0;
+    hmap_init(&exporter->domains);
 
     memset(&exporter->ipfix_global_stats, 0,
            sizeof(struct dpif_ipfix_global_stats));
@@ -711,6 +722,7 @@
 
 static void
 dpif_ipfix_exporter_clear(struct dpif_ipfix_exporter *exporter)
+    OVS_REQUIRES(mutex)
 {
     /* Flush the cache with flow end reason "forced end." */
     dpif_ipfix_cache_expire_now(exporter, true);
@@ -719,22 +731,29 @@
     exporter->exporter_id = 0;
     exporter->collectors = NULL;
     exporter->seq_number = 1;
-    exporter->last_template_set_time = 0;
+    exporter->last_stats_sent_time = 0;
     exporter->cache_active_timeout = 0;
     exporter->cache_max_flows = 0;
     free(exporter->virtual_obs_id);
     exporter->virtual_obs_id = NULL;
     exporter->virtual_obs_len = 0;
 
+    struct dpif_ipfix_domain *dom;
+    HMAP_FOR_EACH_SAFE (dom, hmap_node, &exporter->domains) {
+        dpif_ipfix_exporter_del_domain(exporter, dom);
+    }
+
     memset(&exporter->ipfix_global_stats, 0,
            sizeof(struct dpif_ipfix_global_stats));
 }
 
 static void
 dpif_ipfix_exporter_destroy(struct dpif_ipfix_exporter *exporter)
+    OVS_REQUIRES(mutex)
 {
     dpif_ipfix_exporter_clear(exporter);
     hmap_destroy(&exporter->cache_flow_key_map);
+    hmap_destroy(&exporter->domains);
 }
 
 static bool
@@ -742,7 +761,7 @@
                                 const struct sset *targets,
                                 const uint32_t cache_active_timeout,
                                 const uint32_t cache_max_flows,
-                                const char *virtual_obs_id)
+                                const char *virtual_obs_id) OVS_REQUIRES(mutex)
 {
     size_t virtual_obs_len;
     collectors_destroy(exporter->collectors);
@@ -769,6 +788,37 @@
     return true;
 }
 
+static struct dpif_ipfix_domain *
+dpif_ipfix_exporter_find_domain(const struct dpif_ipfix_exporter *exporter,
+                                uint32_t domain_id) OVS_REQUIRES(mutex)
+{
+    struct dpif_ipfix_domain *dom;
+    HMAP_FOR_EACH_WITH_HASH (dom, hmap_node, hash_int(domain_id, 0),
+                             &exporter->domains) {
+        return dom;
+    }
+    return NULL;
+}
+
+static struct dpif_ipfix_domain *
+dpif_ipfix_exporter_insert_domain(struct dpif_ipfix_exporter *exporter,
+                                  const uint32_t domain_id) OVS_REQUIRES(mutex)
+{
+    struct dpif_ipfix_domain *dom = xmalloc(sizeof *dom);
+    dom->last_template_set_time = 0;
+    hmap_insert(&exporter->domains, &dom->hmap_node, hash_int(domain_id, 0));
+    return dom;
+}
+
+static void
+dpif_ipfix_exporter_del_domain(struct dpif_ipfix_exporter *exporter,
+                               struct dpif_ipfix_domain *dom)
+    OVS_REQUIRES(mutex)
+{
+    hmap_remove(&exporter->domains, &dom->hmap_node);
+    free(dom);
+}
+
 static struct dpif_ipfix_port *
 dpif_ipfix_find_port(const struct dpif_ipfix *di,
                      odp_port_t odp_port) OVS_REQUIRES(mutex)
@@ -909,6 +959,7 @@
 
 static void
 dpif_ipfix_bridge_exporter_clear(struct dpif_ipfix_bridge_exporter *exporter)
+    OVS_REQUIRES(mutex)
 {
     dpif_ipfix_exporter_clear(&exporter->exporter);
     ofproto_ipfix_bridge_exporter_options_destroy(exporter->options);
@@ -918,6 +969,7 @@
 
 static void
 dpif_ipfix_bridge_exporter_destroy(struct dpif_ipfix_bridge_exporter *exporter)
+    OVS_REQUIRES(mutex)
 {
     dpif_ipfix_bridge_exporter_clear(exporter);
     dpif_ipfix_exporter_destroy(&exporter->exporter);
@@ -927,7 +979,7 @@
 dpif_ipfix_bridge_exporter_set_options(
     struct dpif_ipfix_bridge_exporter *exporter,
     const struct ofproto_ipfix_bridge_exporter_options *options,
-    bool *options_changed)
+    bool *options_changed) OVS_REQUIRES(mutex)
 {
     if (!options || sset_is_empty(&options->targets)) {
         /* No point in doing any work if there are no targets. */
@@ -1003,6 +1055,7 @@
 
 static void
 dpif_ipfix_flow_exporter_clear(struct dpif_ipfix_flow_exporter *exporter)
+    OVS_REQUIRES(mutex)
 {
     dpif_ipfix_exporter_clear(&exporter->exporter);
     ofproto_ipfix_flow_exporter_options_destroy(exporter->options);
@@ -1011,6 +1064,7 @@
 
 static void
 dpif_ipfix_flow_exporter_destroy(struct dpif_ipfix_flow_exporter *exporter)
+    OVS_REQUIRES(mutex)
 {
     dpif_ipfix_flow_exporter_clear(exporter);
     dpif_ipfix_exporter_destroy(&exporter->exporter);
@@ -1020,7 +1074,7 @@
 dpif_ipfix_flow_exporter_set_options(
     struct dpif_ipfix_flow_exporter *exporter,
     const struct ofproto_ipfix_flow_exporter_options *options,
-    bool *options_changed)
+    bool *options_changed) OVS_REQUIRES(mutex)
 {
     if (sset_is_empty(&options->targets)) {
         /* No point in doing any work if there are no targets. */
@@ -1071,6 +1125,7 @@
 static void
 remove_flow_exporter(struct dpif_ipfix *di,
                      struct dpif_ipfix_flow_exporter_map_node *node)
+                     OVS_REQUIRES(mutex)
 {
     hmap_remove(&di->flow_exporter_map, &node->node);
     dpif_ipfix_flow_exporter_destroy(&node->exporter);
@@ -2000,6 +2055,7 @@
 ipfix_cache_update(struct dpif_ipfix_exporter *exporter,
                    struct ipfix_flow_cache_entry *entry,
                    enum ipfix_sampled_packet_type sampled_pkt_type)
+                   OVS_REQUIRES(mutex)
 {
     struct ipfix_flow_cache_entry *old_entry;
     size_t current_flows = 0;
@@ -2811,14 +2867,36 @@
     ovs_mutex_unlock(&mutex);
 }
 
+static bool
+dpif_ipfix_should_send_template(struct dpif_ipfix_exporter *exporter,
+                                const uint32_t observation_domain_id,
+                                const uint32_t export_time_sec)
+    OVS_REQUIRES(mutex)
+{
+    struct dpif_ipfix_domain *domain;
+    domain = dpif_ipfix_exporter_find_domain(exporter,
+                                             observation_domain_id);
+    if (!domain) {
+        /* First time we see this obs_domain_id. */
+        domain = dpif_ipfix_exporter_insert_domain(exporter,
+                                                   observation_domain_id);
+    }
+
+    if ((domain->last_template_set_time + IPFIX_TEMPLATE_INTERVAL)
+        <= export_time_sec) {
+        domain->last_template_set_time = export_time_sec;
+        return true;
+    }
+    return false;
+}
+
 static void
 dpif_ipfix_cache_expire(struct dpif_ipfix_exporter *exporter,
                         bool forced_end, const uint64_t export_time_usec,
-                        const uint32_t export_time_sec)
+                        const uint32_t export_time_sec) OVS_REQUIRES(mutex)
 {
     struct ipfix_flow_cache_entry *entry;
     uint64_t max_flow_start_timestamp_usec;
-    bool template_msg_sent = false;
     enum ipfix_flow_end_reason flow_end_reason;
 
     if (ovs_list_is_empty(&exporter->cache_flow_start_timestamp_list)) {
@@ -2844,25 +2922,28 @@
             break;
         }
 
-        ovs_list_remove(&entry->cache_flow_start_timestamp_list_node);
-        hmap_remove(&exporter->cache_flow_key_map,
-                    &entry->flow_key_map_node);
+        /* XXX: Make frequency of the (Options) Template and Exporter Process
+         * Statistics transmission configurable.
+         * Cf. IETF RFC 5101 Section 4.3. and 10.3.6. */
+        if ((exporter->last_stats_sent_time + IPFIX_TEMPLATE_INTERVAL)
+             <= export_time_sec) {
+            exporter->last_stats_sent_time = export_time_sec;
+            ipfix_send_exporter_data_msg(exporter, export_time_sec);
+        }
 
-         /* XXX: Make frequency of the (Options) Template and Exporter Process
-          * Statistics transmission configurable.
-          * Cf. IETF RFC 5101 Section 4.3. and 10.3.6. */
-        if (!template_msg_sent
-            && (exporter->last_template_set_time + IPFIX_TEMPLATE_INTERVAL)
-                <= export_time_sec) {
+        if (dpif_ipfix_should_send_template(exporter,
+                                            entry->flow_key.obs_domain_id,
+                                            export_time_sec)) {
+            VLOG_DBG("Sending templates for ObservationDomainID %"PRIu32,
+                     entry->flow_key.obs_domain_id);
             ipfix_send_template_msgs(exporter, export_time_sec,
                                      entry->flow_key.obs_domain_id);
-            exporter->last_template_set_time = export_time_sec;
-            template_msg_sent = true;
-
-            /* Send Exporter Process Statistics. */
-            ipfix_send_exporter_data_msg(exporter, export_time_sec);
         }
 
+        ovs_list_remove(&entry->cache_flow_start_timestamp_list_node);
+        hmap_remove(&exporter->cache_flow_key_map,
+                    &entry->flow_key_map_node);
+
         /* XXX: Group multiple data records for the same obs domain id
          * into the same message. */
         ipfix_send_data_msg(exporter, export_time_sec, entry, flow_end_reason);
@@ -2883,7 +2964,7 @@
 
 static void
 dpif_ipfix_cache_expire_now(struct dpif_ipfix_exporter *exporter,
-                            bool forced_end)
+                            bool forced_end) OVS_REQUIRES(mutex)
 {
     uint64_t export_time_usec;
     uint32_t export_time_sec;
diff -u -N -r openvswitch-3.1.0/ofproto/ofproto-dpif-upcall.c 
openvswitch-3.1.1/ofproto/ofproto-dpif-upcall.c
--- openvswitch-3.1.0/ofproto/ofproto-dpif-upcall.c     2023-02-16 
17:31:15.042879633 +0100
+++ openvswitch-3.1.1/ofproto/ofproto-dpif-upcall.c     2023-04-06 
17:12:13.127813775 +0200
@@ -47,17 +47,20 @@
 
 #define UPCALL_MAX_BATCH 64
 #define REVALIDATE_MAX_BATCH 50
+#define UINT64_THREE_QUARTERS (UINT64_MAX / 4 * 3)
 
 VLOG_DEFINE_THIS_MODULE(ofproto_dpif_upcall);
 
 COVERAGE_DEFINE(dumped_duplicate_flow);
 COVERAGE_DEFINE(dumped_new_flow);
 COVERAGE_DEFINE(handler_duplicate_upcall);
-COVERAGE_DEFINE(upcall_ukey_contention);
-COVERAGE_DEFINE(upcall_ukey_replace);
 COVERAGE_DEFINE(revalidate_missed_dp_flow);
+COVERAGE_DEFINE(ukey_dp_change);
+COVERAGE_DEFINE(ukey_invalid_stat_reset);
 COVERAGE_DEFINE(upcall_flow_limit_hit);
 COVERAGE_DEFINE(upcall_flow_limit_kill);
+COVERAGE_DEFINE(upcall_ukey_contention);
+COVERAGE_DEFINE(upcall_ukey_replace);
 
 /* A thread that reads upcalls from dpif, forwards each upcall's packet,
  * and possibly sets up a kernel flow as a cache. */
@@ -287,6 +290,7 @@
 
     struct ovs_mutex mutex;                   /* Guards the following. */
     struct dpif_flow_stats stats OVS_GUARDED; /* Last known stats.*/
+    const char *dp_layer OVS_GUARDED;         /* Last known dp_layer. */
     long long int created OVS_GUARDED;        /* Estimate of creation time. */
     uint64_t dump_seq OVS_GUARDED;            /* Tracks udpif->dump_seq. */
     uint64_t reval_seq OVS_GUARDED;           /* Tracks udpif->reval_seq. */
@@ -780,6 +784,17 @@
         atomic_store_relaxed(&udpif->n_flows_timestamp, now);
         dpif_get_dp_stats(udpif->dpif, &stats);
         flow_count = stats.n_flows;
+
+        if (!dpif_synced_dp_layers(udpif->dpif)) {
+            /* If the dpif layer does not sync the flows, we need to include
+             * the hardware offloaded flows separately. */
+            uint64_t hw_flows;
+
+            if (!dpif_get_n_offloaded_flows(udpif->dpif, &hw_flows)) {
+                flow_count += hw_flows;
+            }
+        }
+
         atomic_store_relaxed(&udpif->n_flows, flow_count);
         ovs_mutex_unlock(&udpif->n_flows_mutex);
     } else {
@@ -1766,6 +1781,7 @@
     ukey->created = ukey->flow_time = time_msec();
     memset(&ukey->stats, 0, sizeof ukey->stats);
     ukey->stats.used = used;
+    ukey->dp_layer = NULL;
     ukey->xcache = NULL;
 
     ukey->offloaded = false;
@@ -2095,10 +2111,12 @@
 }
 
 static bool
-should_revalidate(const struct udpif *udpif, uint64_t packets,
-                  long long int used)
+should_revalidate(const struct udpif *udpif, const struct udpif_key *ukey,
+                  uint64_t packets)
+    OVS_REQUIRES(ukey->mutex)
 {
     long long int metric, now, duration;
+    long long int used = ukey->stats.used;
 
     if (!used) {
         /* Always revalidate the first time a flow is dumped. */
@@ -2125,8 +2143,12 @@
     duration = now - used;
     metric = duration / packets;
 
-    if (metric < 1000 / ofproto_min_revalidate_pps) {
-        /* The flow is receiving more than min-revalidate-pps, so keep it. */
+    if (metric < 1000 / ofproto_min_revalidate_pps ||
+        (ukey->offloaded && duration < ofproto_offloaded_stats_delay)) {
+        /* The flow is receiving more than min-revalidate-pps, so keep it.
+         * Or it's a hardware offloaded flow that might take up to X seconds
+         * to update its statistics. Until we are sure the statistics had a
+         * chance to be updated, also keep it. */
         return true;
     }
     return false;
@@ -2324,7 +2346,7 @@
 revalidate_ukey(struct udpif *udpif, struct udpif_key *ukey,
                 const struct dpif_flow_stats *stats,
                 struct ofpbuf *odp_actions, uint64_t reval_seq,
-                struct recirc_refs *recircs, bool offloaded)
+                struct recirc_refs *recircs)
     OVS_REQUIRES(ukey->mutex)
 {
     bool need_revalidate = ukey->reval_seq != reval_seq;
@@ -2342,8 +2364,15 @@
                     ? stats->n_bytes - ukey->stats.n_bytes
                     : 0);
 
+    if (stats->n_packets < ukey->stats.n_packets &&
+        ukey->stats.n_packets < UINT64_THREE_QUARTERS) {
+        /* Report cases where the packet counter is lower than the previous
+         * instance, but exclude the potential wrapping of an uint64_t. */
+        COVERAGE_INC(ukey_invalid_stat_reset);
+    }
+
     if (need_revalidate) {
-        if (should_revalidate(udpif, push.n_packets, ukey->stats.used)) {
+        if (should_revalidate(udpif, ukey, push.n_packets)) {
             if (!ukey->xcache) {
                 ukey->xcache = xlate_cache_new();
             } else {
@@ -2359,7 +2388,7 @@
 
     /* Stats for deleted flows will be attributed upon flow deletion. Skip. */
     if (result != UKEY_DELETE) {
-        xlate_push_stats(ukey->xcache, &push, offloaded);
+        xlate_push_stats(ukey->xcache, &push, ukey->offloaded);
         ukey->stats = *stats;
         ukey->reval_seq = reval_seq;
     }
@@ -2455,6 +2484,15 @@
             push->tcp_flags = stats->tcp_flags | op->ukey->stats.tcp_flags;
             push->n_packets = stats->n_packets - op->ukey->stats.n_packets;
             push->n_bytes = stats->n_bytes - op->ukey->stats.n_bytes;
+
+            if (stats->n_packets < op->ukey->stats.n_packets &&
+                op->ukey->stats.n_packets < UINT64_THREE_QUARTERS) {
+                /* Report cases where the packet counter is lower than the
+                 * previous instance, but exclude the potential wrapping of an
+                 * uint64_t. */
+                COVERAGE_INC(ukey_invalid_stat_reset);
+            }
+
             ovs_mutex_unlock(&op->ukey->mutex);
         } else {
             push = stats;
@@ -2759,6 +2797,22 @@
                 continue;
             }
 
+            ukey->offloaded = f->attrs.offloaded;
+            if (!ukey->dp_layer
+                || (!dpif_synced_dp_layers(udpif->dpif)
+                    && strcmp(ukey->dp_layer, f->attrs.dp_layer))) {
+
+                if (ukey->dp_layer) {
+                    /* The dp_layer has changed this is probably due to an
+                     * earlier revalidate cycle moving it to/from hw offload.
+                     * In this case we should reset the ukey stored statistics,
+                     * as they are from the deleted DP flow. */
+                    COVERAGE_INC(ukey_dp_change);
+                    memset(&ukey->stats, 0, sizeof ukey->stats);
+                }
+                ukey->dp_layer = f->attrs.dp_layer;
+            }
+
             already_dumped = ukey->dump_seq == dump_seq;
             if (already_dumped) {
                 /* The flow has already been handled during this flow dump
@@ -2790,8 +2844,7 @@
                 result = UKEY_DELETE;
             } else {
                 result = revalidate_ukey(udpif, ukey, &stats, &odp_actions,
-                                         reval_seq, &recircs,
-                                         f->attrs.offloaded);
+                                         reval_seq, &recircs);
             }
             ukey->dump_seq = dump_seq;
 
@@ -2876,7 +2929,7 @@
                     COVERAGE_INC(revalidate_missed_dp_flow);
                     memcpy(&stats, &ukey->stats, sizeof stats);
                     result = revalidate_ukey(udpif, ukey, &stats, &odp_actions,
-                                             reval_seq, &recircs, false);
+                                             reval_seq, &recircs);
                 }
                 if (result != UKEY_KEEP) {
                     /* Clears 'recircs' if filled by revalidate_ukey(). */
diff -u -N -r openvswitch-3.1.0/ofproto/ofproto-dpif-xlate.c 
openvswitch-3.1.1/ofproto/ofproto-dpif-xlate.c
--- openvswitch-3.1.0/ofproto/ofproto-dpif-xlate.c      2023-02-16 
17:31:13.603879633 +0100
+++ openvswitch-3.1.1/ofproto/ofproto-dpif-xlate.c      2023-04-06 
17:12:13.129813777 +0200
@@ -5211,6 +5211,7 @@
     }
 
     ctx->wc->masks.nw_ttl = 0xff;
+    WC_MASK_FIELD(ctx->wc, nw_proto);
     if (flow->nw_ttl > 1) {
         flow->nw_ttl--;
         return false;
@@ -7128,6 +7129,7 @@
         case OFPACT_SET_IPV4_SRC:
             if (flow->dl_type == htons(ETH_TYPE_IP)) {
                 memset(&wc->masks.nw_src, 0xff, sizeof wc->masks.nw_src);
+                WC_MASK_FIELD(wc, nw_proto);
                 flow->nw_src = ofpact_get_SET_IPV4_SRC(a)->ipv4;
             }
             break;
@@ -7135,12 +7137,14 @@
         case OFPACT_SET_IPV4_DST:
             if (flow->dl_type == htons(ETH_TYPE_IP)) {
                 memset(&wc->masks.nw_dst, 0xff, sizeof wc->masks.nw_dst);
+                WC_MASK_FIELD(wc, nw_proto);
                 flow->nw_dst = ofpact_get_SET_IPV4_DST(a)->ipv4;
             }
             break;
 
         case OFPACT_SET_IP_DSCP:
             if (is_ip_any(flow)) {
+                WC_MASK_FIELD(wc, nw_proto);
                 wc->masks.nw_tos |= IP_DSCP_MASK;
                 flow->nw_tos &= ~IP_DSCP_MASK;
                 flow->nw_tos |= ofpact_get_SET_IP_DSCP(a)->dscp;
@@ -7149,6 +7153,7 @@
 
         case OFPACT_SET_IP_ECN:
             if (is_ip_any(flow)) {
+                WC_MASK_FIELD(wc, nw_proto);
                 wc->masks.nw_tos |= IP_ECN_MASK;
                 flow->nw_tos &= ~IP_ECN_MASK;
                 flow->nw_tos |= ofpact_get_SET_IP_ECN(a)->ecn;
@@ -7157,6 +7162,7 @@
 
         case OFPACT_SET_IP_TTL:
             if (is_ip_any(flow)) {
+                WC_MASK_FIELD(wc, nw_proto);
                 wc->masks.nw_ttl = 0xff;
                 flow->nw_ttl = ofpact_get_SET_IP_TTL(a)->ttl;
             }
@@ -7224,6 +7230,7 @@
 
             /* Set the field only if the packet actually has it. */
             if (mf_are_prereqs_ok(mf, flow, wc)) {
+                mf_set_mask_l3_prereqs(mf, flow, wc);
                 mf_mask_field_masked(mf, ofpact_set_field_mask(set_field), wc);
                 mf_set_flow_value_masked(mf, set_field->value,
                                          ofpact_set_field_mask(set_field),
@@ -7280,6 +7287,7 @@
 
         case OFPACT_DEC_TTL:
             wc->masks.nw_ttl = 0xff;
+            WC_MASK_FIELD(wc, nw_proto);
             if (compose_dec_ttl(ctx, ofpact_get_DEC_TTL(a))) {
                 return;
             }
diff -u -N -r openvswitch-3.1.0/ofproto/ofproto.h 
openvswitch-3.1.1/ofproto/ofproto.h
--- openvswitch-3.1.0/ofproto/ofproto.h 2023-02-16 17:31:13.606879633 +0100
+++ openvswitch-3.1.1/ofproto/ofproto.h 2023-04-06 17:10:44.169742243 +0200
@@ -311,6 +311,7 @@
 #define OFPROTO_MAX_IDLE_DEFAULT 10000 /* ms */
 #define OFPROTO_MAX_REVALIDATOR_DEFAULT 500 /* ms */
 #define OFPROTO_MIN_REVALIDATE_PPS_DEFAULT 5
+#define OFPROTO_OFFLOADED_STATS_DELAY 2000 /* ms */
 
 const char *ofproto_port_open_type(const struct ofproto *,
                                    const char *port_type);
@@ -340,6 +341,7 @@
 void ofproto_set_max_idle(unsigned max_idle);
 void ofproto_set_max_revalidator(unsigned max_revalidator);
 void ofproto_set_min_revalidate_pps(unsigned min_revalidate_pps);
+void ofproto_set_offloaded_stats_delay(unsigned offloaded_stats_delay);
 void ofproto_set_forward_bpdu(struct ofproto *, bool forward_bpdu);
 void ofproto_set_mac_table_config(struct ofproto *, unsigned idle_time,
                                   size_t max_entries);
diff -u -N -r openvswitch-3.1.0/ofproto/ofproto-provider.h 
openvswitch-3.1.1/ofproto/ofproto-provider.h
--- openvswitch-3.1.0/ofproto/ofproto-provider.h        2023-02-16 
17:31:13.605879633 +0100
+++ openvswitch-3.1.1/ofproto/ofproto-provider.h        2023-04-06 
17:12:13.130813778 +0200
@@ -541,6 +541,11 @@
  * duration exceeds half of max-revalidator config variable. */
 extern unsigned ofproto_min_revalidate_pps;
 
+/* Worst case delay (in ms) it might take before statistics of offloaded flows
+ * are updated. Offloaded flows younger than this delay will always be
+ * revalidated regardless of ofproto_min_revalidate_pps. */
+extern unsigned ofproto_offloaded_stats_delay;
+
 /* Number of upcall handler and revalidator threads. Only affects the
  * ofproto-dpif implementation. */
 extern uint32_t n_handlers, n_revalidators;
diff -u -N -r openvswitch-3.1.0/package.m4 openvswitch-3.1.1/package.m4
--- openvswitch-3.1.0/package.m4        2023-02-16 17:31:47.536879633 +0100
+++ openvswitch-3.1.1/package.m4        2023-04-06 17:12:33.534830185 +0200
@@ -1,6 +1,6 @@
 # Signature of the current package.
 m4_define([AT_PACKAGE_NAME],      [openvswitch])
 m4_define([AT_PACKAGE_TARNAME],   [openvswitch])
-m4_define([AT_PACKAGE_VERSION],   [3.1.0])
-m4_define([AT_PACKAGE_STRING],    [openvswitch 3.1.0])
+m4_define([AT_PACKAGE_VERSION],   [3.1.1])
+m4_define([AT_PACKAGE_STRING],    [openvswitch 3.1.1])
 m4_define([AT_PACKAGE_BUGREPORT], [b...@openvswitch.org])
diff -u -N -r openvswitch-3.1.0/python/ovs/version.py 
openvswitch-3.1.1/python/ovs/version.py
--- openvswitch-3.1.0/python/ovs/version.py     2023-02-16 17:32:08.445879633 
+0100
+++ openvswitch-3.1.1/python/ovs/version.py     2023-04-06 17:12:53.509846247 
+0200
@@ -1,2 +1,2 @@
 # Generated automatically -- do not modify!    -*- buffer-read-only: t -*-
-VERSION = "3.1.0"
+VERSION = "3.1.1"
diff -u -N -r openvswitch-3.1.0/utilities/ovs-ofctl.c 
openvswitch-3.1.1/utilities/ovs-ofctl.c
--- openvswitch-3.1.0/utilities/ovs-ofctl.c     2023-02-16 17:31:13.662879633 
+0100
+++ openvswitch-3.1.1/utilities/ovs-ofctl.c     2023-04-06 17:12:13.141813787 
+0200
@@ -3089,6 +3089,10 @@
         args--;
     }
 
+    if (args > 0) {
+        ovs_fatal(0, "Invalid arguments");
+    }
+
     open_vconn(ctx->argv[1], &vconn);
     enum ofp_version version = vconn_get_version(vconn);
     struct ofpbuf *msg = ofp_ct_match_encode(&match, pzone, version);
diff -u -N -r openvswitch-3.1.0/vswitchd/bridge.c 
openvswitch-3.1.1/vswitchd/bridge.c
--- openvswitch-3.1.0/vswitchd/bridge.c 2023-02-16 17:31:15.063879633 +0100
+++ openvswitch-3.1.1/vswitchd/bridge.c 2023-04-06 17:12:13.142813787 +0200
@@ -832,6 +832,9 @@
     ofproto_set_min_revalidate_pps(
         smap_get_uint(&ovs_cfg->other_config, "min-revalidate-pps",
                      OFPROTO_MIN_REVALIDATE_PPS_DEFAULT));
+    ofproto_set_offloaded_stats_delay(
+        smap_get_uint(&ovs_cfg->other_config, "offloaded-stats-delay",
+                      OFPROTO_OFFLOADED_STATS_DELAY));
     ofproto_set_vlan_limit(smap_get_int(&ovs_cfg->other_config, "vlan-limit",
                                        LEGACY_MAX_VLAN_HEADERS));
     ofproto_set_bundle_idle_timeout(smap_get_uint(&ovs_cfg->other_config,
diff -u -N -r openvswitch-3.1.0/vswitchd/vswitch.xml 
openvswitch-3.1.1/vswitchd/vswitch.xml
--- openvswitch-3.1.0/vswitchd/vswitch.xml      2023-02-16 17:31:15.066879633 
+0100
+++ openvswitch-3.1.1/vswitchd/vswitch.xml      2023-04-06 17:12:13.144813789 
+0200
@@ -215,6 +215,19 @@
         </p>
       </column>
 
+      <column name="other_config" key="offloaded-stats-delay"
+              type='{"type": "integer", "minInteger": 0}'>
+        <p>
+          Set worst case delay (in ms) it might take before statistics of
+          offloaded flows are updated. Offloaded flows younger than this
+          delay will always be revalidated regardless of
+          <ref column="other_config" key="min-revalidate-pps"/>.
+        </p>
+        <p>
+          The default is 2000.
+        </p>
+      </column>
+
       <column name="other_config" key="hw-offload"
               type='{"type": "boolean"}'>
         <p>
@@ -6296,6 +6309,12 @@
         translated to an ephemeral port. If there is no collision, no SNAT
         is performed.
       </column>
+      <column name="capabilities" key="ct_flush"
+              type='{"type": "boolean"}'>
+        True if the datapath supports CT flush OpenFlow Nicira extension
+        called <code>NXT_CT_FLUSH</code>. The <code>NXT_CT_FLUSH</code>
+        extensions allows to flush CT entries based on specified parameters.
+      </column>
     </group>
 
     <group title="Common Columns">

Reply via email to