@@ -25,6 +25,7 @@
#include "src/shared/queue.h"
#include "src/shared/util.h"
#include "src/shared/mgmt.h"
+#include "src/shared/timeout.h"
struct mgmt {
int ref_count;
@@ -49,6 +50,7 @@ struct mgmt {
};
struct mgmt_request {
+ struct mgmt *mgmt;
unsigned int id;
uint16_t opcode;
uint16_t index;
@@ -57,6 +59,8 @@ struct mgmt_request {
mgmt_request_func_t callback;
mgmt_destroy_func_t destroy;
void *user_data;
+ int timeout;
+ unsigned int timeout_id;
};
struct mgmt_notify {
@@ -81,6 +85,9 @@ static void destroy_request(void *data)
if (request->destroy)
request->destroy(request->user_data);
+ if (request->timeout_id)
+ timeout_remove(request->timeout_id);
+
free(request->buf);
free(request);
}
@@ -150,6 +157,26 @@ static void write_watch_destroy(void *user_data)
mgmt->writer_active = false;
}
+static bool request_timeout(void *data)
+{
+ struct mgmt_request *request = data;
+
+ if (!request)
+ return false;
+
+ request->timeout_id = 0;
+
+ queue_remove_if(request->mgmt->pending_list, NULL, request);
+
+ if (request->callback)
+ request->callback(MGMT_STATUS_TIMEOUT, 0, NULL,
+ request->user_data);
+
+ destroy_request(request);
+
+ return false;
+}
+
static bool send_request(struct mgmt *mgmt, struct mgmt_request *request)
{
struct iovec iov;
@@ -169,6 +196,12 @@ static bool send_request(struct mgmt *mgmt, struct mgmt_request *request)
return false;
}
+ if (request->timeout)
+ request->timeout_id = timeout_add_seconds(request->timeout,
+ request_timeout,
+ request,
+ NULL);
+
util_debug(mgmt->debug_callback, mgmt->debug_data,
"[0x%04x] command 0x%04x",
request->index, request->opcode);
@@ -566,7 +599,8 @@ bool mgmt_set_close_on_unref(struct mgmt *mgmt, bool do_close)
static struct mgmt_request *create_request(struct mgmt *mgmt, uint16_t opcode,
uint16_t index, uint16_t length,
const void *param, mgmt_request_func_t callback,
- void *user_data, mgmt_destroy_func_t destroy)
+ void *user_data, mgmt_destroy_func_t destroy,
+ int timeout)
{
struct mgmt_request *request;
struct mgmt_hdr *hdr;
@@ -598,12 +632,18 @@ static struct mgmt_request *create_request(struct mgmt *mgmt, uint16_t opcode,
hdr->index = htobs(index);
hdr->len = htobs(length);
+ /* Use a weak reference so requests don't prevent mgmt_unref to
+ * cancel requests and free in case of the last reference is dropped by
+ * the user.
+ */
+ request->mgmt = mgmt;
request->opcode = opcode;
request->index = index;
request->callback = callback;
request->destroy = destroy;
request->user_data = user_data;
+ request->timeout = timeout;
return request;
}
@@ -735,10 +775,11 @@ unsigned int mgmt_send_tlv(struct mgmt *mgmt, uint16_t opcode, uint16_t index,
return ret;
}
-unsigned int mgmt_send(struct mgmt *mgmt, uint16_t opcode, uint16_t index,
- uint16_t length, const void *param,
- mgmt_request_func_t callback,
- void *user_data, mgmt_destroy_func_t destroy)
+unsigned int mgmt_send_timeout(struct mgmt *mgmt, uint16_t opcode,
+ uint16_t index, uint16_t length,
+ const void *param, mgmt_request_func_t callback,
+ void *user_data, mgmt_destroy_func_t destroy,
+ int timeout)
{
struct mgmt_request *request;
@@ -746,7 +787,7 @@ unsigned int mgmt_send(struct mgmt *mgmt, uint16_t opcode, uint16_t index,
return 0;
request = create_request(mgmt, opcode, index, length, param,
- callback, user_data, destroy);
+ callback, user_data, destroy, timeout);
if (!request)
return 0;
@@ -766,6 +807,15 @@ unsigned int mgmt_send(struct mgmt *mgmt, uint16_t opcode, uint16_t index,
return request->id;
}
+unsigned int mgmt_send(struct mgmt *mgmt, uint16_t opcode, uint16_t index,
+ uint16_t length, const void *param,
+ mgmt_request_func_t callback,
+ void *user_data, mgmt_destroy_func_t destroy)
+{
+ return mgmt_send_timeout(mgmt, opcode, index, length, param, callback,
+ user_data, destroy, 0);
+}
+
unsigned int mgmt_send_nowait(struct mgmt *mgmt, uint16_t opcode, uint16_t index,
uint16_t length, const void *param,
mgmt_request_func_t callback,
@@ -777,7 +827,8 @@ unsigned int mgmt_send_nowait(struct mgmt *mgmt, uint16_t opcode, uint16_t index
return 0;
request = create_request(mgmt, opcode, index, length, param,
- callback, user_data, destroy);
+ callback, user_data, destroy,
+ 0);
if (!request)
return 0;
@@ -792,10 +843,11 @@ unsigned int mgmt_send_nowait(struct mgmt *mgmt, uint16_t opcode, uint16_t index
return request->id;
}
-unsigned int mgmt_reply(struct mgmt *mgmt, uint16_t opcode, uint16_t index,
- uint16_t length, const void *param,
- mgmt_request_func_t callback,
- void *user_data, mgmt_destroy_func_t destroy)
+unsigned int mgmt_reply_timeout(struct mgmt *mgmt, uint16_t opcode,
+ uint16_t index, uint16_t length,
+ const void *param, mgmt_request_func_t callback,
+ void *user_data, mgmt_destroy_func_t destroy,
+ int timeout)
{
struct mgmt_request *request;
@@ -803,7 +855,7 @@ unsigned int mgmt_reply(struct mgmt *mgmt, uint16_t opcode, uint16_t index,
return 0;
request = create_request(mgmt, opcode, index, length, param,
- callback, user_data, destroy);
+ callback, user_data, destroy, timeout);
if (!request)
return 0;
@@ -823,6 +875,15 @@ unsigned int mgmt_reply(struct mgmt *mgmt, uint16_t opcode, uint16_t index,
return request->id;
}
+unsigned int mgmt_reply(struct mgmt *mgmt, uint16_t opcode, uint16_t index,
+ uint16_t length, const void *param,
+ mgmt_request_func_t callback,
+ void *user_data, mgmt_destroy_func_t destroy)
+{
+ return mgmt_reply_timeout(mgmt, opcode, index, length, param, callback,
+ user_data, destroy, 0);
+}
+
bool mgmt_cancel(struct mgmt *mgmt, unsigned int id)
{
struct mgmt_request *request;
@@ -55,6 +55,11 @@ unsigned int mgmt_send(struct mgmt *mgmt, uint16_t opcode, uint16_t index,
uint16_t length, const void *param,
mgmt_request_func_t callback,
void *user_data, mgmt_destroy_func_t destroy);
+unsigned int mgmt_send_timeout(struct mgmt *mgmt, uint16_t opcode,
+ uint16_t index, uint16_t length,
+ const void *param, mgmt_request_func_t callback,
+ void *user_data, mgmt_destroy_func_t destroy,
+ int timeout);
unsigned int mgmt_send_nowait(struct mgmt *mgmt, uint16_t opcode, uint16_t index,
uint16_t length, const void *param,
mgmt_request_func_t callback,
@@ -63,6 +68,11 @@ unsigned int mgmt_reply(struct mgmt *mgmt, uint16_t opcode, uint16_t index,
uint16_t length, const void *param,
mgmt_request_func_t callback,
void *user_data, mgmt_destroy_func_t destroy);
+unsigned int mgmt_reply_timeout(struct mgmt *mgmt, uint16_t opcode,
+ uint16_t index, uint16_t length,
+ const void *param, mgmt_request_func_t callback,
+ void *user_data, mgmt_destroy_func_t destroy,
+ int timeout);
bool mgmt_cancel(struct mgmt *mgmt, unsigned int id);
bool mgmt_cancel_index(struct mgmt *mgmt, uint16_t index);
bool mgmt_cancel_all(struct mgmt *mgmt);
From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com> This adds request timeout handling when using mgmt_send_timeout and mgmt_reply_timeout, the timeout is applied to the request only when it is actually transmitted and not while queued. --- v2: Remove default timeout so the likes of mgmt_send/mgmt_reply use 0 instead which disables the timeout handling. v3: Keep comments explaining why certain requests need a timeout. src/shared/mgmt.c | 85 ++++++++++++++++++++++++++++++++++++++++------- src/shared/mgmt.h | 10 ++++++ 2 files changed, 83 insertions(+), 12 deletions(-)