2008-06-26 16:07:48 +00:00
|
|
|
/*
|
2014-02-20 00:32:19 +00:00
|
|
|
* Copyright (C) 2010-2014 Red Hat, Inc.
|
2008-06-26 16:07:48 +00:00
|
|
|
* Copyright IBM Corp. 2008
|
|
|
|
*
|
2011-11-02 16:03:09 +00:00
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
|
|
* License as published by the Free Software Foundation; either
|
|
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This library is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* Lesser General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
2012-09-20 22:30:55 +00:00
|
|
|
* License along with this library. If not, see
|
2012-07-21 10:06:23 +00:00
|
|
|
* <http://www.gnu.org/licenses/>.
|
2008-06-26 16:07:48 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include <config.h>
|
|
|
|
|
2011-11-02 16:03:09 +00:00
|
|
|
#include "virnetdevveth.h"
|
2012-12-12 18:06:53 +00:00
|
|
|
#include "viralloc.h"
|
2012-12-12 17:59:27 +00:00
|
|
|
#include "virlog.h"
|
2012-12-12 16:27:01 +00:00
|
|
|
#include "vircommand.h"
|
2012-12-13 18:21:53 +00:00
|
|
|
#include "virerror.h"
|
2013-05-09 18:59:04 +00:00
|
|
|
#include "virfile.h"
|
2013-04-03 10:36:23 +00:00
|
|
|
#include "virstring.h"
|
2013-10-02 11:18:49 +00:00
|
|
|
#include "virnetdev.h"
|
2020-12-16 06:01:05 +00:00
|
|
|
#include "virnetlink.h"
|
2010-07-23 17:25:56 +00:00
|
|
|
|
2011-11-02 15:53:39 +00:00
|
|
|
#define VIR_FROM_THIS VIR_FROM_NONE
|
2010-07-23 17:25:56 +00:00
|
|
|
|
2014-02-28 12:16:17 +00:00
|
|
|
VIR_LOG_INIT("util.netdevveth");
|
|
|
|
|
2008-06-26 16:07:48 +00:00
|
|
|
|
2020-12-16 06:01:05 +00:00
|
|
|
#if defined(WITH_LIBNL)
|
|
|
|
static int
|
|
|
|
virNetDevVethCreateInternal(const char *veth1, const char *veth2)
|
|
|
|
{
|
|
|
|
int status; /* Just ignore it */
|
|
|
|
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)
|
|
|
|
{
|
|
|
|
g_autoptr(virCommand) cmd = virCommandNew("ip");
|
|
|
|
virCommandAddArgList(cmd, "link", "add", veth1, "type", "veth",
|
|
|
|
"peer", "name", veth2, NULL);
|
|
|
|
|
|
|
|
return virCommandRun(cmd, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
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 */
|
|
|
|
|
2008-06-26 16:07:48 +00:00
|
|
|
/**
|
2011-11-02 15:53:39 +00:00
|
|
|
* virNetDevVethCreate:
|
2020-12-16 06:01:05 +00:00
|
|
|
* @veth1: pointer to name for one end of veth pair
|
|
|
|
* @veth2: pointer to name for another end of veth pair
|
2008-06-26 16:07:48 +00:00
|
|
|
*
|
2020-12-16 06:01:05 +00:00
|
|
|
* Creates a veth device pair.
|
2010-08-31 22:04:46 +00:00
|
|
|
*
|
2008-06-26 16:07:48 +00:00
|
|
|
* NOTE: If veth1 and veth2 names are not specified, ip will auto assign
|
|
|
|
* names. There seems to be two problems here -
|
|
|
|
* 1) There doesn't seem to be a way to determine the names of the
|
|
|
|
* devices that it creates. They show up in ip link show and
|
|
|
|
* under /sys/class/net/ however there is no guarantee that they
|
|
|
|
* are the devices that this process just created.
|
|
|
|
* 2) Once one of the veth devices is moved to another namespace, it
|
|
|
|
* is no longer visible in the parent namespace. This seems to
|
|
|
|
* confuse the name assignment causing it to fail with File exists.
|
2010-08-31 22:04:46 +00:00
|
|
|
* Because of these issues, this function currently allocates names
|
|
|
|
* prior to using the ip command, and returns any allocated names
|
|
|
|
* to the caller.
|
2008-06-26 16:07:48 +00:00
|
|
|
*
|
|
|
|
* Returns 0 on success or -1 in case of error
|
|
|
|
*/
|
2020-12-16 06:01:05 +00:00
|
|
|
int virNetDevVethCreate(char **veth1, char **veth2)
|
2008-06-26 16:07:48 +00:00
|
|
|
{
|
2020-12-16 06:01:05 +00:00
|
|
|
const char *orig1 = *veth1;
|
|
|
|
const char *orig2 = *veth2;
|
2013-10-02 11:18:49 +00:00
|
|
|
|
2020-12-16 06:01:05 +00:00
|
|
|
if (virNetDevGenerateName(veth1, VIR_NET_DEV_GEN_NAME_VNET) < 0)
|
|
|
|
goto cleanup;
|
2013-10-02 11:18:49 +00:00
|
|
|
|
2020-12-16 06:01:05 +00:00
|
|
|
if (virNetDevGenerateName(veth2, VIR_NET_DEV_GEN_NAME_VNET) < 0)
|
|
|
|
goto cleanup;
|
2020-12-14 01:50:35 +00:00
|
|
|
|
2020-12-16 06:01:05 +00:00
|
|
|
if (virNetDevVethCreateInternal(*veth1, *veth2) < 0)
|
|
|
|
goto cleanup;
|
2011-03-17 15:54:24 +00:00
|
|
|
|
2020-12-16 06:01:05 +00:00
|
|
|
VIR_DEBUG("Create Host: %s guest: %s", *veth1, *veth2);
|
|
|
|
return 0;
|
2008-06-26 16:07:48 +00:00
|
|
|
|
2020-12-16 06:01:05 +00:00
|
|
|
cleanup:
|
|
|
|
if (orig1 == NULL)
|
|
|
|
VIR_FREE(*veth1);
|
2020-12-14 01:50:35 +00:00
|
|
|
|
2020-12-16 06:01:05 +00:00
|
|
|
if (orig2 == NULL)
|
|
|
|
VIR_FREE(*veth2);
|
2011-03-17 15:54:24 +00:00
|
|
|
|
2020-12-16 06:01:05 +00:00
|
|
|
return -1;
|
2008-06-26 16:07:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2011-11-02 15:53:39 +00:00
|
|
|
* virNetDevVethDelete:
|
2008-06-26 16:07:48 +00:00
|
|
|
* @veth: name for one end of veth pair
|
|
|
|
*
|
|
|
|
* This will delete both veth devices in a pair. Only one end needs to
|
|
|
|
* be specified. The ip command will identify and delete the other veth
|
|
|
|
* device as well.
|
|
|
|
* ip link del veth
|
|
|
|
*
|
|
|
|
* Returns 0 on success or -1 in case of error
|
|
|
|
*/
|
2011-11-02 15:53:39 +00:00
|
|
|
int virNetDevVethDelete(const char *veth)
|
2008-06-26 16:07:48 +00:00
|
|
|
{
|
2020-12-16 06:01:05 +00:00
|
|
|
return virNetDevVethDeleteInternal(veth);
|
2008-06-26 16:07:48 +00:00
|
|
|
}
|