
On 11/17/20 1:48 AM, Shi Lei wrote:
When netlink is supported, use netlink to create veth device pair rather than 'ip link' command.
Signed-off-by: Shi Lei <shi_lei@massclouds.com> --- src/util/virnetdevveth.c | 39 ++++++++++++++++++++++++++++++--------- 1 file changed, 30 insertions(+), 9 deletions(-)
diff --git a/src/util/virnetdevveth.c b/src/util/virnetdevveth.c index b3eee1af..996bf5dd 100644 --- a/src/util/virnetdevveth.c +++ b/src/util/virnetdevveth.c @@ -27,6 +27,7 @@ #include "virfile.h" #include "virstring.h" #include "virnetdev.h" +#include "virnetlink.h" #define VIR_FROM_THIS VIR_FROM_NONE @@ -116,7 +117,6 @@ int virNetDevVethCreate(char** veth1, char** veth2) for (i = 0; i < MAX_VETH_RETRIES; i++) { g_autofree char *veth1auto = NULL; g_autofree char *veth2auto = NULL; - g_autoptr(virCommand) cmd = NULL; int status; if (!*veth1) { @@ -136,15 +136,32 @@ int virNetDevVethCreate(char** veth1, char** veth2) vethNum = veth2num + 1; } - cmd = virCommandNew("ip"); - virCommandAddArgList(cmd, "link", "add", - *veth1 ? *veth1 : veth1auto, - "type", "veth", "peer", "name", - *veth2 ? *veth2 : veth2auto, - NULL); +#if defined(WITH_LIBNL) + { + int error = 0; + virNetlinkNewLinkData data = { + .veth_peer = *veth2 ? *veth2 : veth2auto, + }; - if (virCommandRun(cmd, &status) < 0) - goto cleanup; + status = virNetlinkNewLink(*veth1 ? *veth1 : veth1auto, + "veth", &data, &error); + if (status < 0) + goto cleanup; + } +#else + { + g_autoptr(virCommand) cmd = NULL; + cmd = virCommandNew("ip"); + virCommandAddArgList(cmd, "link", "add", + *veth1 ? *veth1 : veth1auto, + "type", "veth", "peer", "name", + *veth2 ? *veth2 : veth2auto, + NULL); + + if (virCommandRun(cmd, &status) < 0) + goto cleanup; + } +#endif /* WITH_LIBNL */
Although it isn't a hard/fast rule, we generally prefer to have complete functions within an #ifdefs rather then putting #ifdefs in the middle of a function. Could you put these bits into smaller functions, patterned like below, and then call the vir*Internal() functions from the existing functions?
(other than that this looks fine, although I haven't actually tried *running* it yet :-))
Okay. It looks fine.
#if defined(WITH_LIBNL)
int
virNetDevVethCreateInternal(char *veth1, char *veth2)
{
int error;
virNetlinkNewLinkData data = { .veth_peer = veth2 };
return virNetlinkNewLink(veth1, "veth", &data, &error);
}
int
virNetDevVethDeleteInternal(char *veth)
{
return virNetlinkDelLink(veth, NULL);
}
#else
int
virNetDevVethCreateInternal(char *veth1, char *veth2)
{
g_autoptr(virCommand) cmd = virCommandNew("ip");
virCommandAddArgList(cmd, "link", "add", veth1, veth2);
return virCommandRun(cmd, NULL);
}
int
virNetDevVethDeleteInternal(char *veth)
{
int status; g_autoptr(virCommand) cmd = virCommandNewArgList("ip", "link", "del", veth, NULL);
if (virCommandRun(cmd, &status) < 0) return -1;
if (status != 0) { if (!virNetDevExists(veth)) { VIR_DEBUG("Device %s already deleted (by kernel namespace cleanup)", veth); return 0; } virReportError(VIR_ERR_INTERNAL_ERROR, _("Failed to delete veth device %s"), veth); return -1; }
return 0; }
if (status == 0) { if (veth1auto) { @@ -188,6 +205,9 @@ int virNetDevVethCreate(char** veth1, char** veth2) */ int virNetDevVethDelete(const char *veth) { +#if defined(WITH_LIBNL) + return virNetlinkDelLink(veth, NULL); +#else int status; g_autoptr(virCommand) cmd = virCommandNewArgList("ip", "link", "del", veth, NULL); @@ -206,4 +226,5 @@ int virNetDevVethDelete(const char *veth) } return 0; +#endif /* WITH_LIBNL */ }
(Aside from this, it looks like veth interface naming could benefit from the same simplifications that I did to tap and macvtap awhile back (basically changing the auto-generated names to never re-use a name - commit 95089f481 and commit d7f38beb2e). But that isn't something for this series, just another thing to add to the to-do list :-))
Oh. Perhaps I can try it in another series. Thanks! Shi Lei