From: Laine Stump <laine@redhat.com> virsh domifannounce is a thin wrapper around the new API virDomainAnnounceInterface(). Syntax: virsh domifannounce guestname [interfacename] [parameters] where the optional interfacename can be either the MAC address of the interface to announce, or the name of the tap device used to connect the domain's interface to the real network (if the connection is with a tap device), and [parameters] is one or more of the following options: --initial [unsigned integer] --max [unsigned integer] --rounds [unsigned integer] --step [unsigned integer] For example: virsh domifannounce myguest 52:54:00:BE:EF:E1 --initial 100 virsh domifannounce other vnet2 virsh domifaanounce Signed-off-by: Laine Stump <laine@redhat.com> --- docs/manpages/virsh.rst | 41 +++++++++++++++++++ tools/virsh-domain.c | 88 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 129 insertions(+) diff --git a/docs/manpages/virsh.rst b/docs/manpages/virsh.rst index d1901c82c2..83ef7dd7dc 100644 --- a/docs/manpages/virsh.rst +++ b/docs/manpages/virsh.rst @@ -2321,6 +2321,47 @@ exclusive. If no flag is specified, behavior is different depending on hypervisor. +domifannounce +------------- + +**Syntax** + +:: + + domifannounce domain [interface-device] [parameters] + + +Request that a domain inject "gratuitous" ARP responses into the +outbound data stream of a specific network interface of the domain (or +if no interface-device is given, inject ARP responses on the outbound +data stream of all interfaces of the domain). This can be helpful to +re-sync network switches in the broadcast domain of said interfaces +when the network topology has changed. This is usually done +automatically when a domain is started, or after it has migrated (for +example, that is the behavior of QEMU), but a more complicated setup +where the topology changes around an already active domain (or +possibly all the plumbing isn't yet connected and passing traffic at +the time the automatic announcement takes place) might benefit from a +manually triggered announce. + +The optional parameters are: + +- *--initial n* + + initial delay before first announcement (milliseconds) default: 50 + +- *--max n* + + maximum delay between announcements (milliseconds) default: 550 + +- *--rounds n* + + total number of announcements default: 5 + +- *--step n* + + increment added to delay (milliseconds) after each announcement default 50 + dominfo ------- diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c index 76369e8694..d9bc3f5a4d 100644 --- a/tools/virsh-domain.c +++ b/tools/virsh-domain.c @@ -3815,6 +3815,88 @@ cmdDomIftune(vshControl *ctl, const vshCmd *cmd) goto cleanup; } + +/* "domifannounce" command + */ +static const vshCmdInfo info_domifannounce = { + .help = N_("trigger domain to announce virtual interface to network"), + .desc = N_("trigger a live domain to announce one or more virtual interfaces to their attached networks"), + +}; + +static const vshCmdOptDef opts_domifannounce[] = { + VIRSH_COMMON_OPT_DOMAIN_FULL(0), + {.name = "interface", + .type = VSH_OT_STRING, + .positional = true, + .completer = virshDomainInterfaceCompleter, + .help = N_("interface device (MAC Address)") + }, + {.name = VIR_DOMAIN_ANNOUNCE_INTERFACE_INITIAL, + .type = VSH_OT_INT, + .help = N_("initial delay before first announcement (milliseconds)")}, + {.name = VIR_DOMAIN_ANNOUNCE_INTERFACE_MAX, + .type = VSH_OT_INT, + .help = N_("maximum delay between announcements (milliseconds)")}, + {.name = VIR_DOMAIN_ANNOUNCE_INTERFACE_ROUNDS, + .type = VSH_OT_INT, + .help = N_("total number of announcements")}, + {.name = VIR_DOMAIN_ANNOUNCE_INTERFACE_STEP, + .type = VSH_OT_INT, + .help = N_("increment added to delay (milliseconds) after each announcement")}, + {.name = NULL} +}; + +static bool +cmdDomIfAnnounce(vshControl *ctl, const vshCmd *cmd) +{ + g_autoptr(virshDomain) dom = NULL; + const char *name = NULL; + const char *device = NULL; + virTypedParameterPtr params = NULL; + int nparams = 0; + int maxparams = 0; + unsigned int val; + bool ret = false; + int rv; + + if (!(dom = virshCommandOptDomain(ctl, cmd, &name))) + return false; + + if (vshCommandOptString(ctl, cmd, "interface", &device) < 0) + return false; + + if ((rv = vshCommandOptUInt(ctl, cmd, VIR_DOMAIN_ANNOUNCE_INTERFACE_INITIAL, &val)) < 0) + goto cleanup; + else if (rv > 0 && virTypedParamsAddUInt(¶ms, &nparams, &maxparams, VIR_DOMAIN_ANNOUNCE_INTERFACE_INITIAL, val) < 0) + goto cleanup; + + if ((rv = vshCommandOptUInt(ctl, cmd, VIR_DOMAIN_ANNOUNCE_INTERFACE_MAX, &val)) < 0) + goto cleanup; + else if (rv > 0 && virTypedParamsAddUInt(¶ms, &nparams, &maxparams, VIR_DOMAIN_ANNOUNCE_INTERFACE_MAX, val) < 0) + goto cleanup; + + if ((rv = vshCommandOptUInt(ctl, cmd, VIR_DOMAIN_ANNOUNCE_INTERFACE_ROUNDS, &val)) < 0) + goto cleanup; + else if (rv > 0 && virTypedParamsAddUInt(¶ms, &nparams, &maxparams, VIR_DOMAIN_ANNOUNCE_INTERFACE_ROUNDS, val) < 0) + goto cleanup; + + if ((rv = vshCommandOptUInt(ctl, cmd, VIR_DOMAIN_ANNOUNCE_INTERFACE_STEP, &val)) < 0) + goto cleanup; + else if (rv > 0 && virTypedParamsAddUInt(¶ms, &nparams, &maxparams, VIR_DOMAIN_ANNOUNCE_INTERFACE_STEP, val) < 0) + goto cleanup; + + if (virDomainAnnounceInterface(dom, device, params, nparams, 0) < 0) + goto cleanup; + + vshPrintExtra(ctl, _("Interface announcement sent for domain '%1$s'"), name); + ret = true; + cleanup: + virTypedParamsFree(params, nparams); + return ret; +} + + /* * "suspend" command */ @@ -14170,6 +14252,12 @@ const vshCmdDef domManagementCmds[] = { .info = &info_domid, .flags = 0 }, + {.name = "domifannounce", + .handler = cmdDomIfAnnounce, + .opts = opts_domifannounce, + .info = &info_domifannounce, + .flags = 0 + }, {.name = "domif-setlink", .handler = cmdDomIfSetLink, .opts = opts_domif_setlink, -- 2.54.0