From: "Dr. David Alan Gilbert" <dgilb...@redhat.com> Previously there was a single instance of the timer used by monitor triggered announces, that's OK, but when combined with the previous change that lets you have announces for subsets of interfaces it's a bit restrictive if you want to do different things to different interfaces.
Add an 'id' field to the announce, and maintain a list of the timers based on id. This allows you to for example: a) Start an announce going on interface eth0 for a long time b) Start an announce going on interface eth1 for a long time c) Kill the announce on eth0 while leaving eth1 going. Signed-off-by: Dr. David Alan Gilbert <dgilb...@redhat.com> --- hw/net/virtio-net.c | 4 ++-- include/net/announce.h | 8 +++++-- net/announce.c | 46 ++++++++++++++++++++++++++++++++++------- net/trace-events | 3 ++- qapi/net.json | 9 ++++++-- tests/virtio-net-test.c | 2 +- 6 files changed, 57 insertions(+), 15 deletions(-) diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c index ffe0872fff..120248bbf6 100644 --- a/hw/net/virtio-net.c +++ b/hw/net/virtio-net.c @@ -2359,7 +2359,7 @@ static int virtio_net_post_load_device(void *opaque, int version_id) timer_mod(n->announce_timer.tm, qemu_clock_get_ms(n->announce_timer.type)); } else { - qemu_announce_timer_del(&n->announce_timer); + qemu_announce_timer_del(&n->announce_timer, false); } } @@ -2783,7 +2783,7 @@ static void virtio_net_device_unrealize(DeviceState *dev, Error **errp) virtio_net_del_queue(n, i); } - qemu_announce_timer_del(&n->announce_timer); + qemu_announce_timer_del(&n->announce_timer, false); g_free(n->vqs); qemu_del_nic(n->nic); virtio_net_rsc_cleanup(n); diff --git a/include/net/announce.h b/include/net/announce.h index 3ebffe517e..9cf7a4f835 100644 --- a/include/net/announce.h +++ b/include/net/announce.h @@ -23,8 +23,12 @@ struct AnnounceTimer { /* Returns: update the timer to the next time point */ int64_t qemu_announce_timer_step(AnnounceTimer *timer); -/* Delete the underlying timer and other data */ -void qemu_announce_timer_del(AnnounceTimer *timer); +/* + * Delete the underlying timer and other datas + * If 'free_named' true and the timer is a named timer, then remove + * it from the list of named timers and free the AnnounceTimer itself. + */ +void qemu_announce_timer_del(AnnounceTimer *timer, bool free_named); /* * Under BQL/main thread diff --git a/net/announce.c b/net/announce.c index 1ce42b571d..4d4e2c22a1 100644 --- a/net/announce.c +++ b/net/announce.c @@ -15,6 +15,8 @@ #include "qapi/qapi-commands-net.h" #include "trace.h" +static GData *named_timers; + int64_t qemu_announce_timer_step(AnnounceTimer *timer) { int64_t step; @@ -31,8 +33,13 @@ int64_t qemu_announce_timer_step(AnnounceTimer *timer) return step; } -void qemu_announce_timer_del(AnnounceTimer *timer) +/* + * If 'free_named' is true, then remove the timer from the list + * and free the timer itself. + */ +void qemu_announce_timer_del(AnnounceTimer *timer, bool free_named) { + bool free_timer = false; if (timer->tm) { timer_del(timer->tm); timer_free(timer->tm); @@ -40,6 +47,18 @@ void qemu_announce_timer_del(AnnounceTimer *timer) } qapi_free_strList(timer->params.interfaces); timer->params.interfaces = NULL; + if (free_named && timer->params.has_id) { + free_timer = timer == + g_datalist_get_data(&named_timers, timer->params.id); + g_datalist_remove_data(&named_timers, timer->params.id); + } + trace_qemu_announce_timer_del(free_named, free_timer, timer->params.id); + g_free(timer->params.id); + timer->params.id = NULL; + + if (free_timer) { + g_free(timer); + } } /* @@ -56,7 +75,7 @@ void qemu_announce_timer_reset(AnnounceTimer *timer, * We're under the BQL, so the current timer can't * be firing, so we should be able to delete it. */ - qemu_announce_timer_del(timer); + qemu_announce_timer_del(timer, false); QAPI_CLONE_MEMBERS(AnnounceParameters, &timer->params, params); timer->round = params->rounds; @@ -120,7 +139,8 @@ static void qemu_announce_self_iter(NICState *nic, void *opaque) skip = false; } - trace_qemu_announce_self_iter(nic->ncs->name, + trace_qemu_announce_self_iter(timer->params.has_id ? timer->params.id : "_", + nic->ncs->name, qemu_ether_ntoa(&nic->conf->macaddr), skip); if (!skip) { @@ -143,7 +163,7 @@ static void qemu_announce_self_once(void *opaque) if (--timer->round) { qemu_announce_timer_step(timer); } else { - qemu_announce_timer_del(timer); + qemu_announce_timer_del(timer, true); } } @@ -154,12 +174,24 @@ void qemu_announce_self(AnnounceTimer *timer, AnnounceParameters *params) if (params->rounds) { qemu_announce_self_once(timer); } else { - qemu_announce_timer_del(timer); + qemu_announce_timer_del(timer, true); } } void qmp_announce_self(AnnounceParameters *params, Error **errp) { - static AnnounceTimer announce_timer; - qemu_announce_self(&announce_timer, params); + AnnounceTimer *named_timer; + if (!params->has_id) { + params->id = g_strdup(""); + params->has_id = true; + } + + named_timer = g_datalist_get_data(&named_timers, params->id); + + if (!named_timer) { + named_timer = g_new0(AnnounceTimer, 1); + g_datalist_set_data(&named_timers, params->id, named_timer); + } + + qemu_announce_self(named_timer, params); } diff --git a/net/trace-events b/net/trace-events index 875ef2a0f3..ac57056497 100644 --- a/net/trace-events +++ b/net/trace-events @@ -1,7 +1,8 @@ # See docs/devel/tracing.txt for syntax documentation. # announce.c -qemu_announce_self_iter(const char *name, const char *mac, int skip) "%s:%s skip: %d" +qemu_announce_self_iter(const char *id, const char *name, const char *mac, int skip) "%s:%s:%s skip: %d" +qemu_announce_timer_del(bool free_named, bool free_timer, char *id) "free named: %d free timer: %d id: %s" # vhost-user.c vhost_user_event(const char *chr, int event) "chr: %s got event: %d" diff --git a/qapi/net.json b/qapi/net.json index ee9bf2c5f5..9da9b5bbc5 100644 --- a/qapi/net.json +++ b/qapi/net.json @@ -702,6 +702,10 @@ # @interfaces: An optional list of interface names, which restrict the # announcment to the listed interfaces. (Since 4.1) # +# @id: A name to be used to identify an instance of announce-timers +# and to allow it to modified later. Not for use as +# part of the migration paramters. (Since 4.1) +# # Since: 4.0 ## @@ -710,7 +714,8 @@ 'max': 'int', 'rounds': 'int', 'step': 'int', - '*interfaces': ['str'] } } + '*interfaces': ['str'], + '*id' : 'str' } } ## # @announce-self: @@ -725,7 +730,7 @@ # -> { "execute": "announce-self", # "arguments": { # "initial": 50, "max": 550, "rounds": 10, "step": 50, -# "interfaces": ["vn2","vn3"] } } +# "interfaces": ["vn2","vn3"], "id": "bob" } } # <- { "return": {} } # # Since: 4.0 diff --git a/tests/virtio-net-test.c b/tests/virtio-net-test.c index 163126cf07..7184e2bff4 100644 --- a/tests/virtio-net-test.c +++ b/tests/virtio-net-test.c @@ -186,7 +186,7 @@ static void announce_self(void *obj, void *data, QGuestAllocator *t_alloc) rsp = qmp("{ 'execute' : 'announce-self', " " 'arguments': {" " 'initial': 50, 'max': 550," - " 'rounds': 10, 'step': 50 } }"); + " 'rounds': 10, 'step': 50, 'id': 'bob' } }"); assert(!qdict_haskey(rsp, "error")); qobject_unref(rsp); -- 2.21.0