diff --git a/.ci/linux-prepare.sh b/.ci/linux-prepare.sh
index 5f8a1db6af..51e5a7e7dd 100755
--- a/.ci/linux-prepare.sh
+++ b/.ci/linux-prepare.sh
@@ -12,10 +12,11 @@ fi
#
# Disabling sqlite support because sindex build fails and we don't
# really need this utility being installed.
-git clone git://git.kernel.org/pub/scm/devel/sparse/sparse.git
-cd sparse
-make -j4 HAVE_SQLITE= install
-cd ..
+if test -d sparse; then
+ pushd sparse
+ make -j4 HAVE_SQLITE= install
+ popd
+fi
# Installing wheel separately because it may be needed to build some
# of the packages during dependency backtracking and pip >= 22.0 will
diff --git a/.github/workflows/build-and-test.yml b/.github/workflows/build-and-test.yml
index d90b9273a6..cea15fbb52 100644
--- a/.github/workflows/build-and-test.yml
+++ b/.github/workflows/build-and-test.yml
@@ -306,6 +306,13 @@ jobs:
if: matrix.m32 != ''
run: sudo apt install -y gcc-multilib
+ - name: checkout sparse
+ uses: actions/checkout@v4
+ # Official mirror of the git.kernel.org/pub/scm/devel/sparse/sparse.git.
+ with:
+ repository: lucvoo/sparse
+ path: sparse
+
- name: prepare
run: ./.ci/linux-prepare.sh
diff --git a/Makefile.am b/Makefile.am
index a61a1cadfb..cdcc4e9bdb 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -406,9 +406,10 @@ ALL_LOCAL += flake8-check
# W504 line break after binary operator
# F*** -- warnings native to flake8
# F811 redefinition of unused <name> from line <N> (only from flake8 v2.0)
+# F824 a `global` or `nonlocal` statement where the name is never reassigned
# D*** -- warnings from flake8-docstrings plugin
# H*** -- warnings from flake8 hacking plugin (custom style checks beyond PEP8)
-FLAKE8_IGNORE = E121,E123,E125,E126,E127,E128,E129,E131,E203,E722,W503,W504,F811,D,H,I
+FLAKE8_IGNORE = E121,E123,E125,E126,E127,E128,E129,E131,E203,E722,W503,W504,F811,F824,D,H,I
flake8-check: $(FLAKE8_PYFILES)
$(FLAKE8_WERROR)$(AM_V_GEN) \
src='$^' && \
diff --git a/NEWS b/NEWS
index 2e5356c5cd..c670cf8f35 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,6 @@
+v3.5.1 - xx xxx xxxx
+--------------------
+
v3.5.0 - 17 Feb 2025
--------------------
- The limit on the number of fields for address prefix tracking in flow
diff --git a/configure.ac b/configure.ac
index 2b19888775..60122e4913 100644
--- a/configure.ac
+++ b/configure.ac
@@ -13,7 +13,7 @@
# limitations under the License.
AC_PREREQ(2.63)
-AC_INIT(openvswitch, 3.5.0, bugs@openvswitch.org)
+AC_INIT(openvswitch, 3.5.1, bugs@openvswitch.org)
AC_CONFIG_SRCDIR([vswitchd/ovs-vswitchd.c])
AC_CONFIG_MACRO_DIR([m4])
AC_CONFIG_AUX_DIR([build-aux])
diff --git a/debian/changelog b/debian/changelog
index 1ba7afbf40..ad638cc44f 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,9 @@
+openvswitch (3.5.1-1) unstable; urgency=low
+ [ Open vSwitch team ]
+ * New upstream version
+
+ -- Open vSwitch team <dev@openvswitch.org> Mon, 17 Feb 2025 13:13:23 +0100
+
openvswitch (3.5.0-1) unstable; urgency=low
* New upstream version
diff --git a/ofproto/ofproto-dpif-xlate.c b/ofproto/ofproto-dpif-xlate.c
index e59ff17ade..d9962765f1 100644
--- a/ofproto/ofproto-dpif-xlate.c
+++ b/ofproto/ofproto-dpif-xlate.c
@@ -3925,9 +3925,9 @@ native_tunnel_output(struct xlate_ctx *ctx, const struct xport *xport,
"sending %s request",
buf_dip6, out_dev->xbridge->name, d_ip ? "ARP" : "ND");
- err = ovs_router_get_netdev_source_address(&d_ip6,
- out_dev->xbridge->name,
- &nh_s_ip6);
+ err = ovs_router_get_netdev_source_address(
+ &d_ip6, netdev_get_name(out_dev->netdev), &nh_s_ip6);
+
if (err) {
nh_s_ip6 = s_ip6;
}
diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c
index bf43d5d4bc..354357b50a 100644
--- a/ofproto/ofproto-dpif.c
+++ b/ofproto/ofproto-dpif.c
@@ -102,7 +102,7 @@ struct ofbundle {
* NULL if all VLANs are trunked. */
unsigned long *cvlans;
struct lacp *lacp; /* LACP if LACP is enabled, otherwise NULL. */
- struct bond *bond; /* Nonnull iff more than one port. */
+ struct bond *bond; /* Nonnull if more than one port. */
enum port_priority_tags_mode use_priority_tags;
/* Use 802.1p tag for frames in VLAN 0? */
@@ -1508,7 +1508,7 @@ check_max_dp_hash_alg(struct dpif_backer *backer)
ofpbuf_use_stack(&key, &keybuf, sizeof keybuf);
odp_flow_key_from_flow(&odp_parms, &key);
- /* All datapaths support algortithm 0 (OVS_HASH_ALG_L4). */
+ /* All datapaths support algorithm 0 (OVS_HASH_ALG_L4). */
for (int alg = 1; alg < __OVS_HASH_MAX; alg++) {
struct ofpbuf actions;
bool ok;
@@ -3642,7 +3642,7 @@ bundle_set(struct ofproto *ofproto_, void *aux,
bundle->bond = NULL;
}
- /* Set proteced port mode */
+ /* Set protected port mode. */
if (s->protected != bundle->protected) {
bundle->protected = s->protected;
need_flush = true;
@@ -4609,7 +4609,7 @@ ofproto_dpif_credit_table_stats(struct ofproto_dpif *ofproto, uint8_t table_id,
/* Look up 'flow' in 'ofproto''s classifier version 'version', starting from
* table '*table_id'. Returns the rule that was found, which may be one of the
- * special rules according to packet miss hadling. If 'may_packet_in' is
+ * special rules according to packet miss handling. If 'may_packet_in' is
* false, returning of the miss_rule (which issues packet ins for the
* controller) is avoided. Updates 'wc', if nonnull, to reflect the fields
* that were used during the lookup.
@@ -5392,7 +5392,6 @@ group_set_selection_method(struct group_dpif *group)
const struct ofputil_group_props *props = &group->up.props;
const char *selection_method = props->selection_method;
- VLOG_DBG("Constructing select group %"PRIu32, group->up.group_id);
if (selection_method[0] == '\0') {
VLOG_DBG("No selection method specified. Trying dp_hash.");
/* If the controller has not specified a selection method, check if
@@ -5459,6 +5458,7 @@ group_construct(struct ofgroup *group_)
group_construct_stats(group);
group->hash_map = NULL;
if (group->up.type == OFPGT11_SELECT) {
+ VLOG_DBG("Constructing select group %"PRIu32, group->up.group_id);
group_set_selection_method(group);
}
ovs_mutex_unlock(&group->stats_mutex);
@@ -5476,6 +5476,21 @@ group_destruct(struct ofgroup *group_)
}
}
+static void
+group_modify(struct ofgroup *group_)
+{
+ struct group_dpif *group = group_dpif_cast(group_);
+
+ if (group->hash_map) {
+ free(group->hash_map);
+ group->hash_map = NULL;
+ }
+ if (group->up.type == OFPGT11_SELECT) {
+ VLOG_DBG("Modifying select group %"PRIu32, group->up.group_id);
+ group_set_selection_method(group);
+ }
+}
+
static enum ofperr
group_get_stats(const struct ofgroup *group_, struct ofputil_group_stats *ogs)
{
@@ -6477,7 +6492,7 @@ struct dpif_support_field {
enum dpif_support_field_type type;
};
-#define DPIF_SUPPORT_FIELD_INTIALIZER(RT_PTR, BT_PTR, TITLE, TYPE) \
+#define DPIF_SUPPORT_FIELD_INITIALIZER(RT_PTR, BT_PTR, TITLE, TYPE) \
(struct dpif_support_field) {RT_PTR, BT_PTR, TITLE, TYPE}
static void
@@ -6543,26 +6558,26 @@ dpif_set_support(struct dpif_backer_support *rt_support,
struct shash_node *node;
bool changed = false;
-#define DPIF_SUPPORT_FIELD(TYPE, NAME, TITLE) \
- {\
- struct dpif_support_field *f = xmalloc(sizeof *f); \
- *f = DPIF_SUPPORT_FIELD_INTIALIZER(&rt_support->NAME, \
- &bt_support->NAME, \
- TITLE, \
- DPIF_SUPPORT_FIELD_##TYPE);\
- shash_add_once(&all_fields, #NAME, f); \
+#define DPIF_SUPPORT_FIELD(TYPE, NAME, TITLE) \
+ { \
+ struct dpif_support_field *f = xmalloc(sizeof *f); \
+ *f = DPIF_SUPPORT_FIELD_INITIALIZER(&rt_support->NAME, \
+ &bt_support->NAME, \
+ TITLE, \
+ DPIF_SUPPORT_FIELD_##TYPE); \
+ shash_add_once(&all_fields, #NAME, f); \
}
DPIF_SUPPORT_FIELDS;
#undef DPIF_SUPPORT_FIELD
-#define ODP_SUPPORT_FIELD(TYPE, NAME, TITLE) \
- {\
- struct dpif_support_field *f = xmalloc(sizeof *f); \
- *f = DPIF_SUPPORT_FIELD_INTIALIZER(&rt_support->odp.NAME, \
- &bt_support->odp.NAME, \
- TITLE, \
- DPIF_SUPPORT_FIELD_##TYPE);\
- shash_add_once(&all_fields, #NAME, f); \
+#define ODP_SUPPORT_FIELD(TYPE, NAME, TITLE) \
+ { \
+ struct dpif_support_field *f = xmalloc(sizeof *f); \
+ *f = DPIF_SUPPORT_FIELD_INITIALIZER(&rt_support->odp.NAME, \
+ &bt_support->odp.NAME, \
+ TITLE, \
+ DPIF_SUPPORT_FIELD_##TYPE); \
+ shash_add_once(&all_fields, #NAME, f); \
}
ODP_SUPPORT_FIELDS;
#undef ODP_SUPPORT_FIELD
@@ -6597,7 +6612,8 @@ dpif_set_support(struct dpif_backer_support *rt_support,
*(bool *) field->rt_ptr = true;
changed = true;
} else {
- ds_put_cstr(ds, "Can not enable features not supported by the datapth");
+ ds_put_cstr(ds,
+ "Can not enable features not supported by the datapath");
}
} else if (!strcasecmp(value, "false")) {
*(bool *)field->rt_ptr = false;
@@ -7299,7 +7315,7 @@ const struct ofproto_class ofproto_dpif_class = {
group_construct, /* group_construct */
group_destruct, /* group_destruct */
group_dealloc, /* group_dealloc */
- NULL, /* group_modify */
+ group_modify, /* group_modify */
group_get_stats, /* group_get_stats */
get_datapath_version, /* get_datapath_version */
get_datapath_cap,
diff --git a/ovsdb/raft.c b/ovsdb/raft.c
index 9c3c351b5b..7d78f710ef 100644
--- a/ovsdb/raft.c
+++ b/ovsdb/raft.c
@@ -65,6 +65,8 @@ enum raft_role {
RAFT_LEADER
};
+static const char *raft_role_to_string(enum raft_role);
+
/* Flags for unit tests. */
enum raft_failure_test {
FT_NO_TEST,
@@ -375,6 +377,11 @@ static void raft_send_append_request(struct raft *,
struct raft_server *, unsigned int n,
const char *comment);
+static void raft_role_transition_at(struct raft *, enum raft_role,
+ const char *func, const char *source);
+#define raft_role_transition(raft, role) \
+ raft_role_transition_at(raft, role, __func__, OVS_SOURCE_LOCATOR)
+
static void raft_become_leader(struct raft *);
static void raft_become_follower(struct raft *);
static void raft_reset_election_timer(struct raft *);
@@ -436,7 +443,7 @@ raft_alloc(void)
hmap_node_nullify(&raft->hmap_node);
hmap_init(&raft->servers);
raft->log_start = raft->log_end = 1;
- raft->role = RAFT_FOLLOWER;
+ raft_role_transition(raft, RAFT_FOLLOWER);
sset_init(&raft->remote_addresses);
raft->join_timeout = LLONG_MAX;
ovs_list_init(&raft->waiters);
@@ -1370,8 +1377,29 @@ raft_send_remove_server_requests(struct raft *raft)
raft_send(raft, &rpc);
}
}
+}
+
+/* Sends requests required to leave the cluster and schedules the next time
+ * this function should be called. */
+static void
+raft_send_leave_requests(struct raft *raft)
+{
+ long long int delay = raft->election_timer;
- raft->leave_timeout = time_msec() + raft->election_timer;
+ if (raft->role == RAFT_LEADER) {
+ raft_transfer_leadership(raft, "this server is leaving the cluster");
+ raft_become_follower(raft);
+ /* Not sending the RemoveServerRequest right away, because a new
+ * leader has to be elected first for the request to be successful.
+ * But setting a shorter delay to avoid waiting for too long when
+ * the leader re-election is fast. Randomized to avoid two servers
+ * bouncing the leadership between each other and never actually
+ * leaving. */
+ delay = delay / 10 + random_range(delay / 10);
+ } else {
+ raft_send_remove_server_requests(raft);
+ }
+ raft->leave_timeout = time_msec() + delay;
}
/* Attempts to start 'raft' leaving its cluster. The caller can check progress
@@ -1385,10 +1413,7 @@ raft_leave(struct raft *raft)
VLOG_INFO(SID_FMT": starting to leave cluster "CID_FMT,
SID_ARGS(&raft->sid), CID_ARGS(&raft->cid));
raft->leaving = true;
- raft_transfer_leadership(raft, "this server is leaving the cluster");
- raft_become_follower(raft);
- raft_send_remove_server_requests(raft);
- raft->leave_timeout = time_msec() + raft->election_timer;
+ raft_send_leave_requests(raft);
}
/* Returns true if 'raft' is currently attempting to leave its cluster. */
@@ -1860,10 +1885,6 @@ raft_start_election(struct raft *raft, bool is_prevote,
/* Leadership transfer doesn't use pre-vote. */
ovs_assert(!is_prevote || !leadership_transfer);
- if (raft->leaving) {
- return;
- }
-
struct raft_server *me = raft_find_server(raft, &raft->sid);
if (!me) {
return;
@@ -1876,8 +1897,8 @@ raft_start_election(struct raft *raft, bool is_prevote,
ovs_assert(raft->role != RAFT_LEADER);
raft->leader_sid = UUID_ZERO;
- raft->role = RAFT_CANDIDATE;
raft->prevote_passed = !is_prevote;
+ raft_role_transition(raft, RAFT_CANDIDATE);
if (is_prevote || leadership_transfer) {
/* If there was no leader elected since last election, we know we are
@@ -1990,6 +2011,12 @@ raft_conn_should_stay_open(struct raft *raft, struct raft_conn *conn)
return true;
}
+ /* Keep the connection until we send a RemoveServerReply. */
+ if (raft->remove_server
+ && uuid_equals(&conn->sid, &raft->remove_server->sid)) {
+ return true;
+ }
+
/* We have joined the cluster. If we did that "recently", then there is a
* chance that we do not have the most recent server configuration log
* entry. If so, it's a waste to disconnect from the servers that were in
@@ -2116,6 +2143,8 @@ raft_run(struct raft *raft)
count ++;
}
}
+ VLOG_DBG("%d out of %"PRIuSIZE" servers replied",
+ count, hmap_count(&raft->servers));
if (count >= hmap_count(&raft->servers) / 2) {
HMAP_FOR_EACH (server, hmap_node, &raft->servers) {
server->replied = false;
@@ -2132,7 +2161,7 @@ raft_run(struct raft *raft)
}
if (raft->leaving && time_msec() >= raft->leave_timeout) {
- raft_send_remove_server_requests(raft);
+ raft_send_leave_requests(raft);
}
if (raft->joining && time_msec() >= raft->join_timeout) {
@@ -2170,9 +2199,14 @@ raft_run(struct raft *raft)
raft_reset_ping_timer(raft);
}
- uint64_t interval = raft->joining
- ? RAFT_JOIN_TIMEOUT_MS
- : RAFT_TIMER_THRESHOLD(raft->election_timer);
+ uint64_t interval = RAFT_TIMER_THRESHOLD(raft->election_timer);
+
+ if (raft->joining) {
+ interval = RAFT_JOIN_TIMEOUT_MS;
+ } else if (uuid_is_zero(&raft->leader_sid)) {
+ /* There are no heartbeats to handle when there is no leader. */
+ interval = raft->election_timer;
+ }
cooperative_multitasking_set(
&raft_run_cb, (void *) raft, time_msec(),
interval + interval / 10, "raft_run");
@@ -2440,7 +2474,7 @@ raft_command_execute__(struct raft *raft, const struct json *data,
const struct json *servers, uint64_t election_timer,
const struct uuid *prereq, struct uuid *result)
{
- if (raft->joining || raft->leaving || raft->left || raft->failed) {
+ if (raft->joining || raft->left || raft->failed) {
return raft_command_create_completed(RAFT_CMD_SHUTDOWN);
}
@@ -2778,7 +2812,7 @@ raft_become_follower(struct raft *raft)
return;
}
- raft->role = RAFT_FOLLOWER;
+ raft_role_transition(raft, RAFT_FOLLOWER);
raft_reset_election_timer(raft);
/* Notify clients about lost leadership.
@@ -2895,6 +2929,26 @@ raft_set_leader(struct raft *raft, const struct uuid *sid)
raft->candidate_retrying = false;
}
+static const char *
+raft_role_to_string(enum raft_role role)
+{
+ switch (role) {
+ case RAFT_FOLLOWER: return "follower";
+ case RAFT_CANDIDATE: return "candidate";
+ case RAFT_LEADER: return "leader";
+ default: return "<error>";
+ }
+}
+
+static void
+raft_role_transition_at(struct raft *raft, enum raft_role role,
+ const char *func, const char *source)
+{
+ VLOG_DBG("%s(%s): role transition: %s --> %s", func, source,
+ raft_role_to_string(raft->role), raft_role_to_string(role));
+ raft->role = role;
+}
+
static void
raft_become_leader(struct raft *raft)
{
@@ -2906,7 +2960,7 @@ raft_become_leader(struct raft *raft)
raft->n_votes, hmap_count(&raft->servers));
ovs_assert(raft->role != RAFT_LEADER);
- raft->role = RAFT_LEADER;
+ raft_role_transition(raft, RAFT_LEADER);
raft->election_won = time_msec();
raft_set_leader(raft, &raft->sid);
raft_reset_election_timer(raft);
@@ -3367,7 +3421,7 @@ raft_update_leader(struct raft *raft, const struct uuid *sid)
* least as large as the candidate's current term, then the
* candidate recognizes the leader as legitimate and returns to
* follower state. */
- raft->role = RAFT_FOLLOWER;
+ raft_role_transition(raft, RAFT_FOLLOWER);
}
return true;
}
@@ -4143,6 +4197,14 @@ raft_handle_remove_server_request(struct raft *raft,
return;
}
+ /* Check for the server already being removed. */
+ if (raft->remove_server
+ && uuid_equals(&rq->sid, &raft->remove_server->sid)) {
+ raft_send_remove_server_reply(raft, rq,
+ false, RAFT_SERVER_IN_PROGRESS);
+ return;
+ }
+
/* If the server isn't configured, report that. */
target = raft_find_server(raft, &rq->sid);
if (!target) {
@@ -4877,11 +4939,7 @@ raft_unixctl_status(struct unixctl_conn *conn,
}
}
- ds_put_format(&s, "Role: %s\n",
- raft->role == RAFT_LEADER ? "leader"
- : raft->role == RAFT_CANDIDATE ? "candidate"
- : raft->role == RAFT_FOLLOWER ? "follower"
- : "<error>");
+ ds_put_format(&s, "Role: %s\n", raft_role_to_string(raft->role));
ds_put_format(&s, "Term: %"PRIu64"\n", raft->term);
raft_put_sid("Leader", &raft->leader_sid, raft, &s);
raft_put_sid("Vote", &raft->vote, raft, &s);
diff --git a/python/ovs/db/idl.py b/python/ovs/db/idl.py
index c8cc543465..384428c3fc 100644
--- a/python/ovs/db/idl.py
+++ b/python/ovs/db/idl.py
@@ -1731,7 +1731,7 @@ class Transaction(object):
and ovs.ovsuuid.is_valid_string(json[1])):
uuid = ovs.ovsuuid.from_string(json[1])
row = self._txn_rows.get(uuid, None)
- if row and row._data is None:
+ if row and row._data is None and not row._persist_uuid:
return ["named-uuid", _uuid_name_from_uuid(uuid)]
else:
return [self._substitute_uuids(elem) for elem in json]
@@ -1856,7 +1856,7 @@ class Transaction(object):
else:
# Let ovsdb-server decide whether to really delete it.
pass
- elif row._changes:
+ else:
op = {"table": row._table.name}
if row._data is None:
op["op"] = "insert"
diff --git a/python/ovs/stream.py b/python/ovs/stream.py
index 2282905ed6..4b4b07d032 100644
--- a/python/ovs/stream.py
+++ b/python/ovs/stream.py
@@ -585,9 +585,9 @@ class PassiveStream(object):
if not PassiveStream.is_valid_name(name):
return errno.EAFNOSUPPORT, None
- bind_path = name[6:]
+ bind_path = None
if name.startswith("punix:"):
- bind_path = ovs.util.abs_file_name(ovs.dirs.RUNDIR, bind_path)
+ bind_path = ovs.util.abs_file_name(ovs.dirs.RUNDIR, name[6:])
if sys.platform != 'win32':
error, sock = ovs.socket_util.make_unix_socket(
socket.SOCK_STREAM, True, bind_path, None)
diff --git a/rhel/usr_lib_systemd_system_ovsdb-server.service b/rhel/usr_lib_systemd_system_ovsdb-server.service
index 558632320c..43ea3a5703 100644
--- a/rhel/usr_lib_systemd_system_ovsdb-server.service
+++ b/rhel/usr_lib_systemd_system_ovsdb-server.service
@@ -18,7 +18,8 @@ EnvironmentFile=-/run/openvswitch.useropts
# OVS_USER_ID from default.conf or sysconfig.
ExecStartPre=/usr/bin/rm -f /run/openvswitch.useropts
-ExecStartPre=-/usr/bin/chown ${OVS_USER_ID} /run/openvswitch /var/log/openvswitch
+ExecStartPre=-/usr/bin/chown -R ${OVS_USER_ID} \
+ /etc/openvswitch /run/openvswitch /var/log/openvswitch
ExecStartPre=/bin/sh -c '/usr/bin/echo "OVS_USER_ID=${OVS_USER_ID}" > /run/openvswitch.useropts'
ExecStartPre=/bin/sh -c 'if [ "$${OVS_USER_ID/:*/}" != "root" ]; then /usr/bin/echo "OVS_USER_OPT=--ovs-user=${OVS_USER_ID}" >> /run/openvswitch.useropts; fi'
ExecStart=/usr/share/openvswitch/scripts/ovs-ctl \
diff --git a/tests/checkpatch.at b/tests/checkpatch.at
index 2ed2ec878b..3182ca8808 100755
--- a/tests/checkpatch.at
+++ b/tests/checkpatch.at
@@ -38,6 +38,31 @@ Subject: Patch this is.
$top_srcdir/utilities/checkpatch.py $3 -q test.patch])
fi
}
+
+# try_checkpatch_c_file SOURCE [ERRORS] [CHECKPATCH-ARGS]
+#
+# Runs checkpatch against test SOURCE expecting the set of specified
+# ERRORS (and warnings). Optionally, sets [CHECKPATCH-ARGS]
+try_checkpatch_c_file() {
+ echo "$1" | sed 's/^ //' > test.c
+
+ # Take expected output from $2.
+ if test -n "$2"; then
+ echo "$2" | sed 's/^ //' > expout
+ else
+ : > expout
+ fi
+
+ if test -s expout; then
+ AT_CHECK([OVS_SRC_DIR=$top_srcdir $PYTHON3 \
+ $top_srcdir/utilities/checkpatch.py $3 -q -f test.c],
+ [1], [stdout])
+ AT_CHECK([sed '/^Lines checked:/,$d' stdout], [0], [expout])
+ else
+ AT_CHECK([OVS_SRC_DIR=$top_srcdir $PYTHON3 \
+ $top_srcdir/utilities/checkpatch.py $3 -q -f test.c])
+ fi
+}
OVS_END_SHELL_HELPERS
AT_SETUP([checkpatch - sign-offs])
@@ -657,3 +682,47 @@ try_checkpatch \
"-a"
AT_CLEANUP
+
+AT_SETUP([checkpatch - file contents checks - bare return])
+try_checkpatch_c_file \
+ "#include <foo.h>
+ #include <bar.h>
+
+ void foo() {
+ return;
+ }" \
+ "WARNING: Empty return followed by brace, consider omitting
+ test.c:6:
+ }
+ "
+AT_CLEANUP
+
+AT_SETUP([checkpatch - file contents checks - parenthesized constructs])
+
+for ctr in 'if' 'while' 'switch' 'HMAP_FOR_EACH' 'BITMAP_FOR_EACH_1'; do
+try_checkpatch_c_file \
+ "#include <foo.h>
+ #include <bar.h>
+
+ void foo() {
+ $ctr (check_node) {
+ something(check_node);
+ }
+ }
+ "
+
+try_checkpatch_c_file \
+ "#include <foo.h>
+ #include <bar.h>
+
+ void foo() {
+ $ctr ( first_run) {
+ something(check_node);
+ }
+ }" \
+ "ERROR: Improper whitespace around control block
+ test.c:5:
+ $ctr ( first_run) {
+ "
+done
+AT_CLEANUP
diff --git a/tests/dpif-netdev.at b/tests/dpif-netdev.at
index 60060ee2e0..920bbcac0b 100644
--- a/tests/dpif-netdev.at
+++ b/tests/dpif-netdev.at
@@ -230,6 +230,7 @@ m4_define([DPIF_NETDEV_MISS_FLOW_DUMP],
AT_CHECK([ovs-appctl upcall/disable-ufid], [0], [Datapath dumping tersely using UFID disabled
], [])
AT_CHECK([ovs-appctl vlog/set dpif:dbg dpif_netdev:dbg])
+ AT_CHECK([ovs-appctl vlog/disable-rate-limit dpif])
AT_CHECK([ovs-ofctl add-flow br0 action=normal])
AT_CHECK([ovs-appctl netdev-dummy/receive p1 'in_port(1),packet_type(ns=0,id=0),eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0a),eth_type(0x0800),ipv4(src=10.0.0.2,dst=10.0.0.1,proto=1,tos=0,ttl=64,frag=no),icmp(type=8,code=0)'])
diff --git a/tests/ofproto-dpif.at b/tests/ofproto-dpif.at
index fa5f148b4c..fbc3deb68e 100644
--- a/tests/ofproto-dpif.at
+++ b/tests/ofproto-dpif.at
@@ -1335,6 +1335,99 @@ m4_for([id], [1], [64], [1], [
OVS_VSWITCHD_STOP
AT_CLEANUP
+AT_SETUP([ofproto-dpif - select group with dp_hash, insert/remove buckets])
+
+OVS_VSWITCHD_START
+add_of_ports br0 1 10
+
+AT_CHECK([ovs-appctl vlog/set ofproto_dpif:file:dbg])
+
+dnl Add a group without buckets.
+AT_CHECK([ovs-ofctl -O OpenFlow15 add-group br0 \
+ 'group_id=1235,type=select,selection_method=dp_hash'])
+AT_CHECK([grep -A3 "Constructing select group 1235" ovs-vswitchd.log \
+ | sed 's/^.*ofproto_dpif/ofproto_dpif/'], [0], [dnl
+ofproto_dpif|DBG|Constructing select group 1235
+ofproto_dpif|DBG|Selection method specified: dp_hash.
+ofproto_dpif|DBG| Don't apply dp_hash method without buckets.
+ofproto_dpif|DBG|Falling back to default hash method.
+])
+
+m4_define([OFG_BUCKET], [bucket=weight=$1,bucket_id=$1,output:10])
+
+dnl Add two buckets one by one.
+get_log_next_line_num
+AT_CHECK([ovs-ofctl -O OpenFlow15 insert-buckets br0 \
+ group_id=1235,command_bucket_id=last,OFG_BUCKET([5])])
+AT_CHECK([tail -n +$LINENUM ovs-vswitchd.log | grep -E '(Bucket|group 1235)' \
+ | sed 's/^.*ofproto_dpif/ofproto_dpif/'], [0], [dnl
+ofproto_dpif|DBG|Constructing select group 1235
+ofproto_dpif|DBG| Bucket 5: weight=5, target=16.00 hits=16
+ofproto_dpif|DBG|Modifying select group 1235
+ofproto_dpif|DBG| Bucket 5: weight=5, target=16.00 hits=16
+])
+get_log_next_line_num
+AT_CHECK([ovs-ofctl -O OpenFlow15 insert-buckets br0 \
+ group_id=1235,command_bucket_id=last,OFG_BUCKET([6])])
+AT_CHECK([tail -n +$LINENUM ovs-vswitchd.log | grep -E '(Bucket|group 1235)' \
+ | sed 's/^.*ofproto_dpif/ofproto_dpif/'], [0], [dnl
+ofproto_dpif|DBG|Constructing select group 1235
+ofproto_dpif|DBG| Bucket 6: weight=6, target=16.00 hits=16
+ofproto_dpif|DBG|Modifying select group 1235
+ofproto_dpif|DBG| Bucket 5: weight=5, target=7.27 hits=7
+ofproto_dpif|DBG| Bucket 6: weight=6, target=8.73 hits=9
+])
+dnl Add two more in the middle.
+get_log_next_line_num
+AT_CHECK([ovs-ofctl -O OpenFlow15 insert-buckets br0 \
+ group_id=1235,command_bucket_id=5,OFG_BUCKET([7]),OFG_BUCKET([8])])
+AT_CHECK([tail -n +$LINENUM ovs-vswitchd.log | grep -E '(Bucket|group 1235)' \
+ | sed 's/^.*ofproto_dpif/ofproto_dpif/'], [0], [dnl
+ofproto_dpif|DBG|Constructing select group 1235
+ofproto_dpif|DBG| Bucket 7: weight=7, target=7.47 hits=7
+ofproto_dpif|DBG| Bucket 8: weight=8, target=8.53 hits=9
+ofproto_dpif|DBG|Modifying select group 1235
+ofproto_dpif|DBG| Bucket 5: weight=5, target=3.08 hits=3
+ofproto_dpif|DBG| Bucket 7: weight=7, target=4.31 hits=4
+ofproto_dpif|DBG| Bucket 8: weight=8, target=4.92 hits=5
+ofproto_dpif|DBG| Bucket 6: weight=6, target=3.69 hits=4
+])
+dnl Remove the last bucket.
+get_log_next_line_num
+AT_CHECK([ovs-ofctl -O OpenFlow15 remove-buckets br0 \
+ group_id=1235,command_bucket_id=last])
+AT_CHECK([tail -n +$LINENUM ovs-vswitchd.log | grep -E '(Bucket|group 1235)' \
+ | sed 's/^.*ofproto_dpif/ofproto_dpif/'], [0], [dnl
+ofproto_dpif|DBG|Constructing select group 1235
+ofproto_dpif|DBG|Modifying select group 1235
+ofproto_dpif|DBG| Bucket 5: weight=5, target=4.00 hits=4
+ofproto_dpif|DBG| Bucket 7: weight=7, target=5.60 hits=6
+ofproto_dpif|DBG| Bucket 8: weight=8, target=6.40 hits=6
+])
+dnl Remove the one in the middle.
+get_log_next_line_num
+AT_CHECK([ovs-ofctl -O OpenFlow15 remove-buckets br0 \
+ group_id=1235,command_bucket_id=7])
+AT_CHECK([tail -n +$LINENUM ovs-vswitchd.log | grep -E '(Bucket|group 1235)' \
+ | sed 's/^.*ofproto_dpif/ofproto_dpif/'], [0], [dnl
+ofproto_dpif|DBG|Constructing select group 1235
+ofproto_dpif|DBG|Modifying select group 1235
+ofproto_dpif|DBG| Bucket 5: weight=5, target=6.15 hits=6
+ofproto_dpif|DBG| Bucket 8: weight=8, target=9.85 hits=10
+])
+dnl Remove all the remaining.
+get_log_next_line_num
+AT_CHECK([ovs-ofctl -O OpenFlow15 remove-buckets br0 \
+ group_id=1235,command_bucket_id=all])
+AT_CHECK([tail -n +$LINENUM ovs-vswitchd.log | grep -E '(Bucket|group 1235)' \
+ | sed 's/^.*ofproto_dpif/ofproto_dpif/'], [0], [dnl
+ofproto_dpif|DBG|Constructing select group 1235
+ofproto_dpif|DBG|Modifying select group 1235
+])
+
+OVS_VSWITCHD_STOP
+AT_CLEANUP
+
AT_SETUP([ofproto-dpif - select group with explicit dp_hash selection method])
OVS_VSWITCHD_START
@@ -9482,6 +9575,7 @@ AT_CHECK([ovs-appctl upcall/disable-ufid], [0], [Datapath dumping tersely using
], [])
AT_CHECK([ovs-appctl time/stop])
AT_CHECK([ovs-appctl vlog/set dpif:dbg dpif_netdev:dbg])
+AT_CHECK([ovs-appctl vlog/disable-rate-limit dpif])
AT_CHECK([ovs-ofctl add-flow br0 actions=LOCAL,output:1,output:2])
AT_CHECK([ovs-ofctl add-flow br1 actions=LOCAL,output:1,output:3])
@@ -10197,6 +10291,7 @@ m4_define([OFPROTO_DPIF_MEGAFLOW_DISABLED],
[AT_SETUP([ofproto-dpif megaflow - disabled$1])
OVS_VSWITCHD_START([], [], [], [m4_if([$1], [], [], [--dummy-numa="0,0,0,0,1,1,1,1"])])
AT_CHECK([ovs-appctl vlog/set dpif:dbg dpif_netdev:dbg])
+ AT_CHECK([ovs-appctl vlog/disable-rate-limit dpif])
func=`printf '%s_' "$1" | cut -c 4-`
add_${func}of_ports br0 1 2
AT_DATA([flows.txt], [dnl
diff --git a/tests/ovsdb-cluster.at b/tests/ovsdb-cluster.at
index 9d8b4d06a4..91a76cb813 100644
--- a/tests/ovsdb-cluster.at
+++ b/tests/ovsdb-cluster.at
@@ -578,6 +578,165 @@ for i in $(seq $n); do
OVS_APP_EXIT_AND_WAIT_BY_TARGET([$(pwd)/s$i], [s$i.pid])
done
+AT_CLEANUP
+
+AT_BANNER([OVSDB - cluster failure while leaving])
+AT_SETUP([OVSDB cluster - leaving the cluster with some servers down])
+AT_KEYWORDS([ovsdb server negative unix cluster leave])
+
+AT_CHECK([ovsdb-tool '-vPATTERN:console:%c|%p|%m' create-cluster s1.db \
+ $top_srcdir/vswitchd/vswitch.ovsschema unix:s1.raft], [0], [], [stderr])
+schema_name=$(ovsdb-tool schema-name $top_srcdir/vswitchd/vswitch.ovsschema)
+for i in 2 3 4 5; do
+ AT_CHECK([ovsdb-tool join-cluster s$i.db $schema_name unix:s$i.raft unix:s1.raft])
+done
+
+on_exit 'kill $(cat *.pid)'
+on_exit "
+ for i in \$(ls $(pwd)/s[[0-5]]); do
+ ovs-appctl --timeout 1 -t \$i cluster/status $schema_name;
+ done
+"
+dnl Starting all the servers.
+for i in 1 2 3 4 5; do
+ AT_CHECK([ovsdb-server -v -vconsole:off -vsyslog:off \
+ --detach --no-chdir --log-file=s$i.log \
+ --pidfile=s$i.pid --unixctl=s$i \
+ --remote=punix:s$i.ovsdb s$i.db])
+done
+
+dnl Make sure that all servers joined the cluster.
+for i in 1 2 3 4 5; do
+ AT_CHECK([ovsdb_client_wait unix:s$i.ovsdb $schema_name connected])
+done
+
+dnl Make sure the cluster is operational.
+m4_define([DB_REMOTE], [unix:s1.ovsdb,unix:s2.ovsdb,unix:s3.ovsdb,unix:s4.ovsdb,unix:s5.ovsdb])
+AT_CHECK([ovs-vsctl --db="DB_REMOTE" --no-wait init])
+AT_CHECK([ovs-vsctl --db="DB_REMOTE" -vovsdb_cs:console:dbg --no-leader-only \
+ --no-wait create QoS type=test-1], [0], [ignore], [ignore])
+
+dnl Stop servers 1 and 2.
+OVS_APP_EXIT_AND_WAIT_BY_TARGET([$(pwd)/s1], [s1.pid])
+OVS_APP_EXIT_AND_WAIT_BY_TARGET([$(pwd)/s2], [s2.pid])
+
+dnl Make sure that all remaining servers are functional as a cluster.
+for i in 3 4 5; do
+ AT_CHECK([ovsdb_client_wait unix:s$i.ovsdb $schema_name connected])
+done
+
+dnl Make sure the cluster is still operational.
+m4_define([DB_REMOTE], [unix:s3.ovsdb,unix:s4.ovsdb,unix:s5.ovsdb])
+AT_CHECK([ovs-vsctl --db="DB_REMOTE" -vovsdb_cs:console:dbg --no-leader-only \
+ --no-wait create QoS type=test-2], [0], [ignore], [ignore])
+
+dnl Servers 1 and 2 in a cluster of 5 are down, 3 servers are still alive.
+dnl Server 3 can't leave, because the NEW configuration will be a cluster of
+dnl 4 with 2 servers down and it doesn't have a quorum. Try it.
+dnl The cluster will fall apart until servers 1 or 2 come back to resolve
+dnl the quorum issue, because servers 4 and 5 will no longer consider 3
+dnl to be part of the configuration.
+AT_CHECK([ovs-appctl -t $(pwd)/s3 cluster/leave $schema_name])
+
+dnl Check that the cluster is not operational.
+for i in 3 4 5; do
+ OVS_WAIT_UNTIL([ovs-appctl -t $(pwd)/s$i cluster/status $schema_name \
+ | grep -qE 'leaving|disconnected'])
+done
+
+dnl Try to commit a transaction, it should not be successful.
+m4_define([DB_REMOTE], [unix:s3.ovsdb,unix:s4.ovsdb,unix:s5.ovsdb])
+AT_CHECK([ovs-vsctl --db="DB_REMOTE" -vovsdb_cs:console:dbg --no-leader-only \
+ --no-wait create QoS type=test-3], [1], [ignore], [stderr])
+
+dnl Now bring back the server 2. This should allow server 3 to leave.
+AT_CHECK([ovsdb-server -v -vconsole:off -vsyslog:off \
+ --detach --no-chdir --log-file=s2.log \
+ --pidfile=s2.pid --unixctl=s2 \
+ --remote=punix:s2.ovsdb s2.db])
+
+dnl Wait for server 3 to actually leave and stop the server.
+AT_CHECK([ovsdb_client_wait unix:s3.ovsdb $schema_name removed])
+OVS_APP_EXIT_AND_WAIT_BY_TARGET([$(pwd)/s3], [s3.pid])
+
+dnl Make sure that all remaining servers are functional as a cluster.
+for i in 2 4 5; do
+ AT_CHECK([ovsdb_client_wait unix:s$i.ovsdb $schema_name connected])
+done
+dnl Make sure the cluster is operational again.
+m4_define([DB_REMOTE], [unix:s2.ovsdb,unix:s4.ovsdb,unix:s5.ovsdb])
+AT_CHECK([ovs-vsctl --db="DB_REMOTE" -vovsdb_cs:console:dbg --no-leader-only \
+ --no-wait create QoS type=test-4], [0], [ignore], [ignore])
+
+dnl Now we have a cluster of 4 servers (1, 2, 4, 5) with 1 server down.
+dnl Server 2 should be able to leave, because the NEW configuration will
+dnl be a cluster of 3 servers with 1 being down and it has a quorum.
+AT_CHECK([ovs-appctl -t $(pwd)/s2 cluster/leave $schema_name])
+dnl Wait for server 2 to actually leave and stop the server.
+AT_CHECK([ovsdb_client_wait unix:s2.ovsdb $schema_name removed])
+OVS_APP_EXIT_AND_WAIT_BY_TARGET([$(pwd)/s2], [s2.pid])
+
+dnl Make sure the cluster is still operational.
+m4_define([DB_REMOTE], [unix:s4.ovsdb,unix:s5.ovsdb])
+AT_CHECK([ovs-vsctl --db="DB_REMOTE" -vovsdb_cs:console:dbg --no-leader-only \
+ --no-wait create QoS type=test-5], [0], [ignore], [ignore])
+
+dnl Now we have a cluster of 3 servers (1, 4, 5) with 1 server down.
+dnl None of the alive servers can leave, because the NEW configuration
+dnl will be a cluster of 2 with 1 server down and it has no quorum.
+dnl Request both to leave anyway.
+for i in 4 5; do
+ AT_CHECK([ovs-appctl -t $(pwd)/s$i cluster/leave $schema_name])
+done
+
+dnl Check that the cluster is not operational.
+for i in 4 5; do
+ OVS_WAIT_UNTIL([ovs-appctl -t $(pwd)/s$i cluster/status $schema_name \
+ | grep -qE 'leaving|disconnected'])
+done
+
+dnl Try to commit a transaction, it should not be successful.
+m4_define([DB_REMOTE], [unix:s4.ovsdb,unix:s5.ovsdb])
+AT_CHECK([ovs-vsctl --db="DB_REMOTE" -vovsdb_cs:console:dbg --no-leader-only \
+ --no-wait create QoS type=test-6], [1], [ignore], [stderr])
+
+dnl Now bring back the first server.
+AT_CHECK([ovsdb-server -v -vconsole:off -vsyslog:off \
+ --detach --no-chdir --log-file=s1.log \
+ --pidfile=s1.pid --unixctl=s1 \
+ --remote=punix:s1.ovsdb s1.db])
+
+dnl Now it should be possible for all the other servers to leave, so we
+dnl should end up with a single-node cluster that consists of server 1.
+for i in 4 5; do
+ AT_CHECK([ovsdb_client_wait unix:s$i.ovsdb $schema_name removed])
+done
+for i in 4 5; do
+ OVS_APP_EXIT_AND_WAIT_BY_TARGET([$(pwd)/s$i], [s$i.pid])
+done
+
+dnl Wait for the first server to become a leader of a single-node cluster.
+OVS_WAIT_UNTIL([ovs-appctl -t $(pwd)/s1 cluster/status $schema_name \
+ | grep -q 'Role: leader'])
+AT_CHECK([ovs-appctl -t $(pwd)/s1 cluster/status $schema_name \
+ | grep -c ' s[[1-5]] '], [0], [dnl
+1
+])
+
+dnl Check that the database is operational and the data is still in there.
+m4_define([DB_REMOTE], [unix:s1.ovsdb])
+AT_CHECK([ovs-vsctl --db="DB_REMOTE" -vovsdb_cs:console:dbg --no-wait \
+ create QoS type=test-7], [0], [ignore], [ignore])
+AT_CHECK([ovs-vsctl --db="DB_REMOTE" --no-wait \
+ --columns=type --bare list QoS | sed '/^$/d' | sort], [0], [dnl
+test-1
+test-2
+test-4
+test-5
+test-7
+])
+
+OVS_APP_EXIT_AND_WAIT_BY_TARGET([$(pwd)/s1], [s1.pid])
AT_CLEANUP
diff --git a/tests/ovsdb-idl.at b/tests/ovsdb-idl.at
index f9f79f1941..a88706982d 100644
--- a/tests/ovsdb-idl.at
+++ b/tests/ovsdb-idl.at
@@ -494,6 +494,15 @@ OVSDB_CHECK_IDL([simple idl, writing via IDL with unicode],
003: done
]])
+OVSDB_CHECK_IDL([simple idl, inserting without modifying a column, insert_no_columns_changed],
+ [],
+ [['insert_no_columns_changed']],
+ [[000: empty
+001: commit, status=success
+002: table simple: i=0 r=0 b=false s= u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1>
+003: done
+]])
+
m4_define([OVSDB_CHECK_IDL_PY_WITH_EXPOUT],
[AT_SETUP([ovsdb-idl - $1 - Python3])
AT_KEYWORDS([ovsdb server idl positive Python $5])
@@ -1567,6 +1576,7 @@ OVSDB_CHECK_IDL_TRACK([track, simple idl, initially populated, weak references,
{"op": "delete",
"table": "simple",
"where": [["s", "==", "row1_s"]]}]' \
+ '+sleep' \
'["idltest",
{"op": "insert",
"table": "simple",
@@ -1579,16 +1589,17 @@ OVSDB_CHECK_IDL_TRACK([track, simple idl, initially populated, weak references,
001: table simple: updated columns: s
002: {"error":null,"result":[{"uuid":["uuid","<3>"]},{"count":1}]}
003: {"error":null,"result":[{"count":1}]}
-004: table simple6: name=row0_s6 weak_ref=[<0>] uuid=<1>
-004: table simple6: updated columns: weak_ref
-004: table simple: inserted/deleted row: i=0 r=0 b=false s=row1_s u=<2> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<3>
-004: table simple: updated columns: s
-005: {"error":null,"result":[{"uuid":["uuid","<4>"]}]}
-006: table simple6: name=row0_s6 weak_ref=[<0>] uuid=<1>
-006: table simple: i=0 r=0 b=false s=row0_s u=<2> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<0>
-006: table simple: inserted row: i=0 r=0 b=false s=row2_s u=<2> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<4>
-006: table simple: updated columns: s
-007: done
+004: sleep
+005: table simple6: name=row0_s6 weak_ref=[<0>] uuid=<1>
+005: table simple6: updated columns: weak_ref
+005: table simple: inserted/deleted row: i=0 r=0 b=false s=row1_s u=<2> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<3>
+005: table simple: updated columns: s
+006: {"error":null,"result":[{"uuid":["uuid","<4>"]}]}
+007: table simple6: name=row0_s6 weak_ref=[<0>] uuid=<1>
+007: table simple: i=0 r=0 b=false s=row0_s u=<2> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<0>
+007: table simple: inserted row: i=0 r=0 b=false s=row2_s u=<2> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<4>
+007: table simple: updated columns: s
+008: done
]])
dnl This test checks that deleting both the destination and source of the
@@ -1762,14 +1773,16 @@ OVSDB_CHECK_IDL_TRACK([track, simple idl, initially empty, strong references, in
'+["idltest",
{"op": "delete",
"table": "link2",
- "where": [["i", "==", 2]]}]'
+ "where": [["i", "==", 2]]}]' \
+ '+sleep'
]],
[[000: empty
001: {"error":null,"result":[{"uuid":["uuid","<0>"]},{"uuid":["uuid","<1>"]}]}
002: {"error":null,"result":[{"count":1}]}
-003: table link1: inserted row: i=1 k=1 ka=[] l2= uuid=<0>
-003: table link1: updated columns: i k
-004: done
+003: sleep
+004: table link1: inserted row: i=1 k=1 ka=[] l2= uuid=<0>
+004: table link1: updated columns: i k
+005: done
]])
OVSDB_CHECK_IDL_TRACK([track, simple idl, initially empty, various ops],
@@ -2746,6 +2759,7 @@ OVSDB_CHECK_IDL_TRACK([track, insert and delete, refs to link1],
"table": "link2",
"where": [["i", "==", 2]]}
]' \
+ '+sleep' \
'["idltest",
{"op": "delete",
"table": "link2",
@@ -2755,15 +2769,16 @@ OVSDB_CHECK_IDL_TRACK([track, insert and delete, refs to link1],
[[000: empty
001: {"error":null,"result":[{"uuid":["uuid","<0>"]},{"uuid":["uuid","<1>"]},{"uuid":["uuid","<2>"]}]}
002: {"error":null,"result":[{"count":1}]}
-003: table link1: inserted row: i=1 k=1 ka=[] l2= uuid=<1>
-003: table link1: updated columns: i k
-003: table link2: inserted row: i=1 l1=1 uuid=<0>
-003: table link2: inserted/deleted row: i=2 l1=1 uuid=<2>
-003: table link2: updated columns: i l1
-003: table link2: updated columns: i l1
-004: {"error":null,"result":[{"count":1}]}
-005: table link1: i=1 k=1 ka=[] l2= uuid=<1>
-006: done
+003: sleep
+004: table link1: inserted row: i=1 k=1 ka=[] l2= uuid=<1>
+004: table link1: updated columns: i k
+004: table link2: inserted row: i=1 l1=1 uuid=<0>
+004: table link2: inserted/deleted row: i=2 l1=1 uuid=<2>
+004: table link2: updated columns: i l1
+004: table link2: updated columns: i l1
+005: {"error":null,"result":[{"count":1}]}
+006: table link1: i=1 k=1 ka=[] l2= uuid=<1>
+007: done
]])
OVSDB_CHECK_IDL_TRACK([track, insert and delete, refs to link2],
[],
@@ -2789,6 +2804,7 @@ OVSDB_CHECK_IDL_TRACK([track, insert and delete, refs to link2],
"table": "link1",
"where": [["i", "==", 2]]}
]' \
+ '+sleep' \
'["idltest",
{"op": "delete",
"table": "link1",
@@ -2798,15 +2814,16 @@ OVSDB_CHECK_IDL_TRACK([track, insert and delete, refs to link2],
[[000: empty
001: {"error":null,"result":[{"uuid":["uuid","<0>"]},{"uuid":["uuid","<1>"]},{"uuid":["uuid","<2>"]}]}
002: {"error":null,"result":[{"count":1}]}
-003: table link1: inserted row: i=1 k=1 ka=[] l2=1 uuid=<0>
-003: table link1: inserted/deleted row: i=2 k=1 ka=[] l2=1 uuid=<2>
-003: table link1: updated columns: i k l2
-003: table link1: updated columns: i k l2
-003: table link2: inserted row: i=1 l1= uuid=<1>
-003: table link2: updated columns: i
-004: {"error":null,"result":[{"count":1}]}
-005: table link2: i=1 l1= uuid=<1>
-006: done
+003: sleep
+004: table link1: inserted row: i=1 k=1 ka=[] l2=1 uuid=<0>
+004: table link1: inserted/deleted row: i=2 k=1 ka=[] l2=1 uuid=<2>
+004: table link1: updated columns: i k l2
+004: table link1: updated columns: i k l2
+004: table link2: inserted row: i=1 l1= uuid=<1>
+004: table link2: updated columns: i
+005: {"error":null,"result":[{"count":1}]}
+006: table link2: i=1 l1= uuid=<1>
+007: done
]])
m4_define([OVSDB_CHECK_IDL_PERS_UUID_INSERT_C],
@@ -2817,7 +2834,7 @@ m4_define([OVSDB_CHECK_IDL_PERS_UUID_INSERT_C],
[0], [stdout], [stderr])
AT_CHECK([sort stdout],
[0], [$3])
- AT_CHECK([grep $4 stderr], [0], [ignore])
+ m4_if([$4], [], [], [AT_CHECK([grep $4 stderr], [0], [ignore])])
OVSDB_SERVER_SHUTDOWN
AT_CLEANUP])
@@ -2829,7 +2846,7 @@ m4_define([OVSDB_CHECK_IDL_PERS_UUID_INSERT_PY],
[0], [stdout], [stderr])
AT_CHECK([sort stdout],
[0], [$3])
- AT_CHECK([grep $4 stderr], [0], [ignore])
+ m4_if([$4], [], [], [AT_CHECK([grep $4 stderr], [0], [ignore])])
OVSDB_SERVER_SHUTDOWN
AT_CLEANUP])
@@ -2867,6 +2884,14 @@ OVSDB_CHECK_IDL_PERS_UUID_INSERT([simple idl, persistent uuid insert],
]],
[['This UUID would duplicate a UUID already present within the table or deleted within the same transaction']])
+OVSDB_CHECK_IDL_PERS_UUID_INSERT([simple idl, persistent uuid insert uref],
+ [['insert_uuid_uref d7f2845f-2e8d-46a9-8330-f6d0b7d2ca36 689420a0-515b-4c0f-8eba-7ad59a344b54']],
+ [[000: empty
+001: commit, status=success
+002: table simple3: name= uset=[] uref=[689420a0-515b-4c0f-8eba-7ad59a344b54] uuid=d7f2845f-2e8d-46a9-8330-f6d0b7d2ca36
+002: table simple4: name= uuid=689420a0-515b-4c0f-8eba-7ad59a344b54
+003: done
+]])
OVSDB_CHECK_IDL_PY([simple idl, python, add_op],
[],
diff --git a/tests/system-traffic.at b/tests/system-traffic.at
index 0215453230..f2d3552808 100644
--- a/tests/system-traffic.at
+++ b/tests/system-traffic.at
@@ -7590,6 +7590,10 @@ dnl Solicit another "destination unreachable" response.
dnl To verify that after flushing, the same openflow rules are matched.
NS_CHECK_EXEC([at_ns0], [bash -c "echo a | nc $NC_EOF_OPT -u 10.1.1.2 10000"])
+AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(10.1.1.2) | sed -e 's/dst=10.1.1.2[[45]][[0-9]]/dst=10.1.1.2XX/'], [0], [dnl
+udp,orig=(src=10.1.1.1,dst=10.1.1.2,sport=<cleared>,dport=<cleared>),reply=(src=10.1.1.2,dst=10.1.1.2XX,sport=<cleared>,dport=<cleared>)
+])
+
AT_CHECK([ovs-appctl revalidator/purge], [0])
AT_CHECK([ovs-ofctl -O OpenFlow15 dump-flows br0 | ofctl_strip | ofctl_strip_bytes | sort | grep -v drop], [0], [dnl
n_packets=1, priority=10,arp actions=NORMAL
@@ -7606,10 +7610,6 @@ AT_CHECK([ovs-ofctl -O OpenFlow15 dump-flows br0 | ofctl_strip | ofctl_strip_byt
OFPST_FLOW reply (OF1.5):
])
-AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(10.1.1.2) | sed -e 's/dst=10.1.1.2[[45]][[0-9]]/dst=10.1.1.2XX/'], [0], [dnl
-udp,orig=(src=10.1.1.1,dst=10.1.1.2,sport=<cleared>,dport=<cleared>),reply=(src=10.1.1.2,dst=10.1.1.2XX,sport=<cleared>,dport=<cleared>)
-])
-
AT_CHECK([tcpdump -n -v "icmp" -r p0.pcap 2>/dev/null | grep -E 'wrong|bad'], [1], [ignore-nolog])
OVS_TRAFFIC_VSWITCHD_STOP
diff --git a/tests/test-ovsdb.c b/tests/test-ovsdb.c
index 710341b655..6a0e0d8341 100644
--- a/tests/test-ovsdb.c
+++ b/tests/test-ovsdb.c
@@ -2451,6 +2451,10 @@ idl_set(struct ovsdb_idl *idl, char *commands, int step)
struct ovsdb_idl_txn *txn;
enum ovsdb_idl_txn_status status;
bool increment = false;
+ /* FIXME: ovsdb_idl_check_consistency() doesn't currently handle refs added
+ * in the same txn, so if any op does this, we need to skip the check until
+ * that is fixed. */
+ bool skip_pre_commit_consistency_check = false;
txn = ovsdb_idl_txn_create(idl);
ovsdb_idl_check_consistency(idl);
@@ -2502,6 +2506,8 @@ idl_set(struct ovsdb_idl *idl, char *commands, int step)
s = idltest_simple_insert(txn);
idltest_simple_set_i(s, atoi(arg1));
+ } else if (!strcmp(name, "insert_no_columns_changed")) {
+ idltest_simple_insert(txn);
} else if (!strcmp(name, "insert_uuid")) {
struct idltest_simple *s;
@@ -2515,6 +2521,26 @@ idl_set(struct ovsdb_idl *idl, char *commands, int step)
}
s = idltest_simple_insert_persist_uuid(txn, &s_uuid);
idltest_simple_set_i(s, atoi(arg2));
+ } else if (!strcmp(name, "insert_uuid_uref")) {
+ struct idltest_simple3 *s3;
+ struct idltest_simple4 *s4;
+
+ if (!arg1 || !arg2) {
+ ovs_fatal(0,
+ "\"insert_uuid_uref\" command requires 2 arguments");
+ }
+
+ struct uuid s3_uuid;
+ struct uuid s4_uuid;
+ if (!uuid_from_string(&s3_uuid, arg1) ||
+ !uuid_from_string(&s4_uuid, arg2)) {
+ ovs_fatal(
+ 0, "\"insert_uuid_uref\" command requires 2 valid uuids");
+ }
+ s4 = idltest_simple4_insert_persist_uuid(txn, &s4_uuid);
+ s3 = idltest_simple3_insert_persist_uuid(txn, &s3_uuid);
+ idltest_simple3_set_uref(s3, &s4, 1);
+ skip_pre_commit_consistency_check = true;
} else if (!strcmp(name, "delete")) {
const struct idltest_simple *s;
@@ -2583,7 +2609,9 @@ idl_set(struct ovsdb_idl *idl, char *commands, int step)
} else {
ovs_fatal(0, "unknown command %s", name);
}
- ovsdb_idl_check_consistency(idl);
+ if (!skip_pre_commit_consistency_check) {
+ ovsdb_idl_check_consistency(idl);
+ }
}
status = ovsdb_idl_txn_commit_block(txn);
@@ -2856,6 +2884,9 @@ do_idl(struct ovs_cmdl_context *ctx)
if (!strcmp(arg, "reconnect")) {
print_and_log("%03d: reconnect", step++);
ovsdb_idl_force_reconnect(idl);
+ } else if (!strcmp(arg, "sleep")) {
+ print_and_log("%03d: sleep", step++);
+ xsleep(1);
} else if (!strncmp(arg, remote_s, strlen(remote_s))) {
ovsdb_idl_set_remote(idl, arg + strlen(remote_s), true);
print_and_log("%03d: new remotes: %s, is connected: %s", step++,
diff --git a/tests/test-ovsdb.py b/tests/test-ovsdb.py
index 57fc1d4497..b690b4f076 100644
--- a/tests/test-ovsdb.py
+++ b/tests/test-ovsdb.py
@@ -508,6 +508,8 @@ def idl_set(idl, commands, step):
s = txn.insert(idl.tables["simple"])
s.i = int(args[0])
+ elif name == "insert_no_columns_changed":
+ txn.insert(idl.tables["simple"])
elif name == "insert_uuid":
if len(args) != 2:
sys.stderr.write('"set" command requires 2 argument\n')
@@ -516,6 +518,17 @@ def idl_set(idl, commands, step):
s = txn.insert(idl.tables["simple"], new_uuid=uuid.UUID(args[0]),
persist_uuid=True)
s.i = int(args[1])
+ elif name == "insert_uuid_uref":
+ if len(args) != 2:
+ sys.stderr.write('"set" command requires 2 argument\n')
+ sys.exit(1)
+
+ s4 = txn.insert(idl.tables["simple4"], new_uuid=uuid.UUID(args[1]),
+ persist_uuid=True)
+ s3 = txn.insert(idl.tables["simple3"], new_uuid=uuid.UUID(args[0]),
+ persist_uuid=True)
+ s3.uref = s4
+
elif name == "add_op":
if len(args) != 1:
sys.stderr.write('"add_op" command requires 1 argument\n')
diff --git a/utilities/checkpatch.py b/utilities/checkpatch.py
index fe6aa79b0d..4a4d9dbaa3 100755
--- a/utilities/checkpatch.py
+++ b/utilities/checkpatch.py
@@ -1184,10 +1184,12 @@ def ovs_checkpatch_file(filename):
else:
mail.add_header('Subject', sys.argv[-1])
- print("Subject missing! Your provisional subject is",
- mail['Subject'])
+ if not checking_file:
+ print("Subject missing! Your provisional subject is",
+ mail['Subject'])
- if run_subject_checks('Subject: ' + mail['Subject'], spellcheck):
+ if not checking_file and run_subject_checks('Subject: ' + mail['Subject'],
+ spellcheck):
result = True
ovs_checkpatch_print_result()
diff --git a/dpdk/VERSION b/dpdk/VERSION
index 0a492611a0..9e2934aa34 100644
--- a/dpdk/VERSION
+++ b/dpdk/VERSION
@@ -1 +1 @@
-24.11.0
+24.11.1
diff --git a/dpdk/doc/guides/rel_notes/release_24_11.rst b/dpdk/doc/guides/rel_notes/release_24_11.rst
index 8486cd986f..f9df63141e 100644
--- a/dpdk/doc/guides/rel_notes/release_24_11.rst
+++ b/dpdk/doc/guides/rel_notes/release_24_11.rst
@@ -616,3 +616,22 @@ Tested Platforms
* Firmware version: 2.14, 0x8000028c
* Device id (pf): 8086:125b
* Driver version(in-tree): 6.8.0-45-generic (Ubuntu24.04.1)(igc)
+
+24.11.1 Release Notes
+---------------------
+
+
+24.11.1 Fixes
+~~~~~~~~~~~~~
+
+* net/virtio: fix Rx checksum calculation
+
+24.11.1 Validation
+~~~~~~~~~~~~~~~~~~
+
+* Tested by Red Hat validation team
+
+24.11.1 Known Issues
+~~~~~~~~~~~~~~~~~~~~
+
+* DPDK 24.11.1 contains DPDK 24.11 plus the fix for CVE-2024-11614 only
diff --git a/dpdk/kernel/linux/uapi/linux/vduse.h b/dpdk/kernel/linux/uapi/linux/vduse.h
new file mode 100644
index 0000000000..11bd48c72c
--- /dev/null
+++ b/dpdk/kernel/linux/uapi/linux/vduse.h
@@ -0,0 +1,353 @@
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+#ifndef _UAPI_VDUSE_H_
+#define _UAPI_VDUSE_H_
+
+#include <linux/types.h>
+
+#define VDUSE_BASE 0x81
+
+/* The ioctls for control device (/dev/vduse/control) */
+
+#define VDUSE_API_VERSION 0
+
+/*
+ * Get the version of VDUSE API that kernel supported (VDUSE_API_VERSION).
+ * This is used for future extension.
+ */
+#define VDUSE_GET_API_VERSION _IOR(VDUSE_BASE, 0x00, __u64)
+
+/* Set the version of VDUSE API that userspace supported. */
+#define VDUSE_SET_API_VERSION _IOW(VDUSE_BASE, 0x01, __u64)
+
+/**
+ * struct vduse_dev_config - basic configuration of a VDUSE device
+ * @name: VDUSE device name, needs to be NUL terminated
+ * @vendor_id: virtio vendor id
+ * @device_id: virtio device id
+ * @features: virtio features
+ * @vq_num: the number of virtqueues
+ * @vq_align: the allocation alignment of virtqueue's metadata
+ * @reserved: for future use, needs to be initialized to zero
+ * @config_size: the size of the configuration space
+ * @config: the buffer of the configuration space
+ *
+ * Structure used by VDUSE_CREATE_DEV ioctl to create VDUSE device.
+ */
+struct vduse_dev_config {
+#define VDUSE_NAME_MAX 256
+ char name[VDUSE_NAME_MAX];
+ __u32 vendor_id;
+ __u32 device_id;
+ __u64 features;
+ __u32 vq_num;
+ __u32 vq_align;
+ __u32 reserved[13];
+ __u32 config_size;
+ __u8 config[];
+};
+
+/* Create a VDUSE device which is represented by a char device (/dev/vduse/$NAME) */
+#define VDUSE_CREATE_DEV _IOW(VDUSE_BASE, 0x02, struct vduse_dev_config)
+
+/*
+ * Destroy a VDUSE device. Make sure there are no more references
+ * to the char device (/dev/vduse/$NAME).
+ */
+#define VDUSE_DESTROY_DEV _IOW(VDUSE_BASE, 0x03, char[VDUSE_NAME_MAX])
+
+/* The ioctls for VDUSE device (/dev/vduse/$NAME) */
+
+/**
+ * struct vduse_iotlb_entry - entry of IOTLB to describe one IOVA region [start, last]
+ * @offset: the mmap offset on returned file descriptor
+ * @start: start of the IOVA region
+ * @last: last of the IOVA region
+ * @perm: access permission of the IOVA region
+ *
+ * Structure used by VDUSE_IOTLB_GET_FD ioctl to find an overlapped IOVA region.
+ */
+struct vduse_iotlb_entry {
+ __u64 offset;
+ __u64 start;
+ __u64 last;
+#define VDUSE_ACCESS_RO 0x1
+#define VDUSE_ACCESS_WO 0x2
+#define VDUSE_ACCESS_RW 0x3
+ __u8 perm;
+};
+
+/*
+ * Find the first IOVA region that overlaps with the range [start, last]
+ * and return the corresponding file descriptor. Return -EINVAL means the
+ * IOVA region doesn't exist. Caller should set start and last fields.
+ */
+#define VDUSE_IOTLB_GET_FD _IOWR(VDUSE_BASE, 0x10, struct vduse_iotlb_entry)
+
+/*
+ * Get the negotiated virtio features. It's a subset of the features in
+ * struct vduse_dev_config which can be accepted by virtio driver. It's
+ * only valid after FEATURES_OK status bit is set.
+ */
+#define VDUSE_DEV_GET_FEATURES _IOR(VDUSE_BASE, 0x11, __u64)
+
+/**
+ * struct vduse_config_data - data used to update configuration space
+ * @offset: the offset from the beginning of configuration space
+ * @length: the length to write to configuration space
+ * @buffer: the buffer used to write from
+ *
+ * Structure used by VDUSE_DEV_SET_CONFIG ioctl to update device
+ * configuration space.
+ */
+struct vduse_config_data {
+ __u32 offset;
+ __u32 length;
+ __u8 buffer[];
+};
+
+/* Set device configuration space */
+#define VDUSE_DEV_SET_CONFIG _IOW(VDUSE_BASE, 0x12, struct vduse_config_data)
+
+/*
+ * Inject a config interrupt. It's usually used to notify virtio driver
+ * that device configuration space has changed.
+ */
+#define VDUSE_DEV_INJECT_CONFIG_IRQ _IO(VDUSE_BASE, 0x13)
+
+/**
+ * struct vduse_vq_config - basic configuration of a virtqueue
+ * @index: virtqueue index
+ * @max_size: the max size of virtqueue
+ * @reserved: for future use, needs to be initialized to zero
+ *
+ * Structure used by VDUSE_VQ_SETUP ioctl to setup a virtqueue.
+ */
+struct vduse_vq_config {
+ __u32 index;
+ __u16 max_size;
+ __u16 reserved[13];
+};
+
+/*
+ * Setup the specified virtqueue. Make sure all virtqueues have been
+ * configured before the device is attached to vDPA bus.
+ */
+#define VDUSE_VQ_SETUP _IOW(VDUSE_BASE, 0x14, struct vduse_vq_config)
+
+/**
+ * struct vduse_vq_state_split - split virtqueue state
+ * @avail_index: available index
+ */
+struct vduse_vq_state_split {
+ __u16 avail_index;
+};
+
+/**
+ * struct vduse_vq_state_packed - packed virtqueue state
+ * @last_avail_counter: last driver ring wrap counter observed by device
+ * @last_avail_idx: device available index
+ * @last_used_counter: device ring wrap counter
+ * @last_used_idx: used index
+ */
+struct vduse_vq_state_packed {
+ __u16 last_avail_counter;
+ __u16 last_avail_idx;
+ __u16 last_used_counter;
+ __u16 last_used_idx;
+};
+
+/**
+ * struct vduse_vq_info - information of a virtqueue
+ * @index: virtqueue index
+ * @num: the size of virtqueue
+ * @desc_addr: address of desc area
+ * @driver_addr: address of driver area
+ * @device_addr: address of device area
+ * @split: split virtqueue state
+ * @packed: packed virtqueue state
+ * @ready: ready status of virtqueue
+ *
+ * Structure used by VDUSE_VQ_GET_INFO ioctl to get virtqueue's information.
+ */
+struct vduse_vq_info {
+ __u32 index;
+ __u32 num;
+ __u64 desc_addr;
+ __u64 driver_addr;
+ __u64 device_addr;
+ union {
+ struct vduse_vq_state_split split;
+ struct vduse_vq_state_packed packed;
+ };
+ __u8 ready;
+};
+
+/* Get the specified virtqueue's information. Caller should set index field. */
+#define VDUSE_VQ_GET_INFO _IOWR(VDUSE_BASE, 0x15, struct vduse_vq_info)
+
+/**
+ * struct vduse_vq_eventfd - eventfd configuration for a virtqueue
+ * @index: virtqueue index
+ * @fd: eventfd, -1 means de-assigning the eventfd
+ *
+ * Structure used by VDUSE_VQ_SETUP_KICKFD ioctl to setup kick eventfd.
+ */
+struct vduse_vq_eventfd {
+ __u32 index;
+#define VDUSE_EVENTFD_DEASSIGN -1
+ int fd;
+};
+
+/*
+ * Setup kick eventfd for specified virtqueue. The kick eventfd is used
+ * by VDUSE kernel module to notify userspace to consume the avail vring.
+ */
+#define VDUSE_VQ_SETUP_KICKFD _IOW(VDUSE_BASE, 0x16, struct vduse_vq_eventfd)
+
+/*
+ * Inject an interrupt for specific virtqueue. It's used to notify virtio driver
+ * to consume the used vring.
+ */
+#define VDUSE_VQ_INJECT_IRQ _IOW(VDUSE_BASE, 0x17, __u32)
+
+/**
+ * struct vduse_iova_umem - userspace memory configuration for one IOVA region
+ * @uaddr: start address of userspace memory, it must be aligned to page size
+ * @iova: start of the IOVA region
+ * @size: size of the IOVA region
+ * @reserved: for future use, needs to be initialized to zero
+ *
+ * Structure used by VDUSE_IOTLB_REG_UMEM and VDUSE_IOTLB_DEREG_UMEM
+ * ioctls to register/de-register userspace memory for IOVA regions
+ */
+struct vduse_iova_umem {
+ __u64 uaddr;
+ __u64 iova;
+ __u64 size;
+ __u64 reserved[3];
+};
+
+/* Register userspace memory for IOVA regions */
+#define VDUSE_IOTLB_REG_UMEM _IOW(VDUSE_BASE, 0x18, struct vduse_iova_umem)
+
+/* De-register the userspace memory. Caller should set iova and size field. */
+#define VDUSE_IOTLB_DEREG_UMEM _IOW(VDUSE_BASE, 0x19, struct vduse_iova_umem)
+
+/**
+ * struct vduse_iova_info - information of one IOVA region
+ * @start: start of the IOVA region
+ * @last: last of the IOVA region
+ * @capability: capability of the IOVA regsion
+ * @reserved: for future use, needs to be initialized to zero
+ *
+ * Structure used by VDUSE_IOTLB_GET_INFO ioctl to get information of
+ * one IOVA region.
+ */
+struct vduse_iova_info {
+ __u64 start;
+ __u64 last;
+#define VDUSE_IOVA_CAP_UMEM (1 << 0)
+ __u64 capability;
+ __u64 reserved[3];
+};
+
+/*
+ * Find the first IOVA region that overlaps with the range [start, last]
+ * and return some information on it. Caller should set start and last fields.
+ */
+#define VDUSE_IOTLB_GET_INFO _IOWR(VDUSE_BASE, 0x1a, struct vduse_iova_info)
+
+/* The control messages definition for read(2)/write(2) on /dev/vduse/$NAME */
+
+/**
+ * enum vduse_req_type - request type
+ * @VDUSE_GET_VQ_STATE: get the state for specified virtqueue from userspace
+ * @VDUSE_SET_STATUS: set the device status
+ * @VDUSE_UPDATE_IOTLB: Notify userspace to update the memory mapping for
+ * specified IOVA range via VDUSE_IOTLB_GET_FD ioctl
+ */
+enum vduse_req_type {
+ VDUSE_GET_VQ_STATE,
+ VDUSE_SET_STATUS,
+ VDUSE_UPDATE_IOTLB,
+};
+
+/**
+ * struct vduse_vq_state - virtqueue state
+ * @index: virtqueue index
+ * @split: split virtqueue state
+ * @packed: packed virtqueue state
+ */
+struct vduse_vq_state {
+ __u32 index;
+ union {
+ struct vduse_vq_state_split split;
+ struct vduse_vq_state_packed packed;
+ };
+};
+
+/**
+ * struct vduse_dev_status - device status
+ * @status: device status
+ */
+struct vduse_dev_status {
+ __u8 status;
+};
+
+/**
+ * struct vduse_iova_range - IOVA range [start, last]
+ * @start: start of the IOVA range
+ * @last: last of the IOVA range
+ */
+struct vduse_iova_range {
+ __u64 start;
+ __u64 last;
+};
+
+/**
+ * struct vduse_dev_request - control request
+ * @type: request type
+ * @request_id: request id
+ * @reserved: for future use
+ * @vq_state: virtqueue state, only index field is available
+ * @s: device status
+ * @iova: IOVA range for updating
+ * @padding: padding
+ *
+ * Structure used by read(2) on /dev/vduse/$NAME.
+ */
+struct vduse_dev_request {
+ __u32 type;
+ __u32 request_id;
+ __u32 reserved[4];
+ union {
+ struct vduse_vq_state vq_state;
+ struct vduse_dev_status s;
+ struct vduse_iova_range iova;
+ __u32 padding[32];
+ };
+};
+
+/**
+ * struct vduse_dev_response - response to control request
+ * @request_id: corresponding request id
+ * @result: the result of request
+ * @reserved: for future use, needs to be initialized to zero
+ * @vq_state: virtqueue state
+ * @padding: padding
+ *
+ * Structure used by write(2) on /dev/vduse/$NAME.
+ */
+struct vduse_dev_response {
+ __u32 request_id;
+#define VDUSE_REQ_RESULT_OK 0x00
+#define VDUSE_REQ_RESULT_FAILED 0x01
+ __u32 result;
+ __u32 reserved[4];
+ union {
+ struct vduse_vq_state vq_state;
+ __u32 padding[32];
+ };
+};
+
+#endif /* _UAPI_VDUSE_H_ */
diff --git a/dpdk/lib/vhost/meson.build b/dpdk/lib/vhost/meson.build
index 51bcf17244..0004f283bb 100644
--- a/dpdk/lib/vhost/meson.build
+++ b/dpdk/lib/vhost/meson.build
@@ -26,16 +26,13 @@ sources = files(
'iotlb.c',
'socket.c',
'vdpa.c',
+ 'vduse.c',
'vhost.c',
'vhost_crypto.c',
'vhost_user.c',
'virtio_net.c',
'virtio_net_ctrl.c',
)
-if cc.has_header('linux/vduse.h')
- sources += files('vduse.c')
- cflags += '-DVHOST_HAS_VDUSE'
-endif
headers = files(
'rte_vdpa.h',
'rte_vhost.h',
diff --git a/dpdk/lib/vhost/vduse.c b/dpdk/lib/vhost/vduse.c
index 8ba58555f9..eaf3146b95 100644
--- a/dpdk/lib/vhost/vduse.c
+++ b/dpdk/lib/vhost/vduse.c
@@ -8,7 +8,7 @@
#include <fcntl.h>
-#include <linux/vduse.h>
+#include <uapi/linux/vduse.h>
#include <linux/virtio_net.h>
#include <sys/ioctl.h>
diff --git a/dpdk/lib/vhost/vduse.h b/dpdk/lib/vhost/vduse.h
index 0d8f3f1205..47ca97a064 100644
--- a/dpdk/lib/vhost/vduse.h
+++ b/dpdk/lib/vhost/vduse.h
@@ -9,29 +9,7 @@
#define VDUSE_NET_SUPPORTED_FEATURES VIRTIO_NET_SUPPORTED_FEATURES
-#ifdef VHOST_HAS_VDUSE
-
int vduse_device_create(const char *path, bool compliant_ol_flags);
int vduse_device_destroy(const char *path);
-#else
-
-static inline int
-vduse_device_create(const char *path, bool compliant_ol_flags)
-{
- RTE_SET_USED(compliant_ol_flags);
-
- VHOST_CONFIG_LOG(path, ERR, "VDUSE support disabled at build time");
- return -1;
-}
-
-static inline int
-vduse_device_destroy(const char *path)
-{
- VHOST_CONFIG_LOG(path, ERR, "VDUSE support disabled at build time");
- return -1;
-}
-
-#endif /* VHOST_HAS_VDUSE */
-
#endif /* _VDUSE_H */
diff --git a/dpdk/lib/vhost/virtio_net.c b/dpdk/lib/vhost/virtio_net.c
index d764d4bc6a..a340e5a772 100644
--- a/dpdk/lib/vhost/virtio_net.c
+++ b/dpdk/lib/vhost/virtio_net.c
@@ -2823,6 +2823,9 @@ vhost_dequeue_offload(struct virtio_net *dev, struct virtio_net_hdr *hdr,
*/
uint16_t csum = 0, off;
+ if (hdr->csum_start >= rte_pktmbuf_pkt_len(m))
+ return;
+
if (rte_raw_cksum_mbuf(m, hdr->csum_start,
rte_pktmbuf_pkt_len(m) - hdr->csum_start, &csum) < 0)
return;
@@ -3626,6 +3629,8 @@ rte_vhost_dequeue_burst(int vid, uint16_t queue_id,
rte_rwlock_read_unlock(&vq->access_lock);
virtio_dev_vring_translate(dev, vq);
+
+ count = 0;
goto out_no_unlock;
}