When netlink is supported, use netlink to create veth device pair rather than 'ip link' command. Signed-off-by: Shi Lei <shi_lei@xxxxxxxxxxxxxx> --- src/util/virnetdevveth.c | 85 ++++++++++++++++++++++++++-------------- 1 file changed, 56 insertions(+), 29 deletions(-) diff --git a/src/util/virnetdevveth.c b/src/util/virnetdevveth.c index b3eee1af..b4074371 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 @@ -75,6 +76,55 @@ static int virNetDevVethGetFreeNum(int startDev) return -1; } +#if defined(WITH_LIBNL) +static int +virNetDevVethCreateInternal(const char *veth1, const char *veth2, int *status) +{ + virNetlinkNewLinkData data = { .veth_peer = veth2 }; + + return virNetlinkNewLink(veth1, "veth", &data, status); +} + +static int +virNetDevVethDeleteInternal(const char *veth) +{ + return virNetlinkDelLink(veth, NULL); +} +#else +static int +virNetDevVethCreateInternal(const char *veth1, const char *veth2, int *status) +{ + g_autoptr(virCommand) cmd = virCommandNew("ip"); + virCommandAddArgList(cmd, "link", "add", veth1, "type", "veth", + "peer", "name", veth2, NULL); + + return virCommandRun(cmd, status); +} + +static int +virNetDevVethDeleteInternal(const 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; +} +#endif /* WITH_LIBNL */ + /** * virNetDevVethCreate: * @veth1: pointer to name for parent end of veth pair @@ -100,7 +150,7 @@ static int virNetDevVethGetFreeNum(int startDev) * * Returns 0 on success or -1 in case of error */ -int virNetDevVethCreate(char** veth1, char** veth2) +int virNetDevVethCreate(char **veth1, char **veth2) { int ret = -1; int vethNum = 0; @@ -116,9 +166,8 @@ 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; + int status = 0; if (!*veth1) { int veth1num; if ((veth1num = virNetDevVethGetFreeNum(vethNum)) < 0) @@ -136,14 +185,9 @@ 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 (virCommandRun(cmd, &status) < 0) + if (virNetDevVethCreateInternal(*veth1 ? *veth1 : veth1auto, + *veth2 ? *veth2 : veth2auto, + &status) < 0) goto cleanup; if (status == 0) { @@ -188,22 +232,5 @@ int virNetDevVethCreate(char** veth1, char** veth2) */ int virNetDevVethDelete(const 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; + return virNetDevVethDeleteInternal(veth); } -- 2.25.1