mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-12-23 21:34:54 +03:00
netdevmacvlan: Use helper function to create unique macvlan/macvtap name
Simplify ReserveName/GenerateName for macvlan and macvtap by using common functions. Signed-off-by: Shi Lei <shi_lei@massclouds.com> Reviewed-by: Laine Stump <laine@redhat.com>
This commit is contained in:
parent
c36cad1a31
commit
9b5d741a9d
@ -2658,7 +2658,6 @@ virNetDevMacVLanDelete;
|
||||
virNetDevMacVLanDeleteWithVPortProfile;
|
||||
virNetDevMacVLanIsMacvtap;
|
||||
virNetDevMacVLanModeTypeFromString;
|
||||
virNetDevMacVLanReserveName;
|
||||
virNetDevMacVLanRestartWithVPortProfile;
|
||||
virNetDevMacVLanTapOpen;
|
||||
virNetDevMacVLanTapSetup;
|
||||
|
@ -365,7 +365,7 @@ libxlReconnectNotifyNets(virDomainDefPtr def)
|
||||
* impolite.
|
||||
*/
|
||||
if (virDomainNetGetActualType(net) == VIR_DOMAIN_NET_TYPE_DIRECT)
|
||||
virNetDevMacVLanReserveName(net->ifname);
|
||||
virNetDevReserveName(net->ifname);
|
||||
|
||||
if (net->type == VIR_DOMAIN_NET_TYPE_NETWORK) {
|
||||
if (!conn && !(conn = virGetConnectNetwork()))
|
||||
|
@ -3391,7 +3391,7 @@ qemuProcessNotifyNets(virDomainDefPtr def)
|
||||
*/
|
||||
switch (virDomainNetGetActualType(net)) {
|
||||
case VIR_DOMAIN_NET_TYPE_DIRECT:
|
||||
virNetDevMacVLanReserveName(net->ifname);
|
||||
virNetDevReserveName(net->ifname);
|
||||
break;
|
||||
case VIR_DOMAIN_NET_TYPE_BRIDGE:
|
||||
case VIR_DOMAIN_NET_TYPE_NETWORK:
|
||||
|
@ -45,7 +45,6 @@ VIR_ENUM_IMPL(virNetDevMacVLanMode,
|
||||
|
||||
# include <net/if.h>
|
||||
# include <linux/if_tun.h>
|
||||
# include <math.h>
|
||||
|
||||
# include "viralloc.h"
|
||||
# include "virlog.h"
|
||||
@ -59,129 +58,6 @@ VIR_ENUM_IMPL(virNetDevMacVLanMode,
|
||||
|
||||
VIR_LOG_INIT("util.netdevmacvlan");
|
||||
|
||||
# define VIR_NET_GENERATED_MACVTAP_PATTERN VIR_NET_GENERATED_MACVTAP_PREFIX "%d"
|
||||
# define VIR_NET_GENERATED_MACVLAN_PATTERN VIR_NET_GENERATED_MACVLAN_PREFIX "%d"
|
||||
# define VIR_NET_GENERATED_PREFIX \
|
||||
((flags & VIR_NETDEV_MACVLAN_CREATE_WITH_TAP) ? \
|
||||
VIR_NET_GENERATED_MACVTAP_PREFIX : VIR_NET_GENERATED_MACVLAN_PREFIX)
|
||||
|
||||
|
||||
virMutex virNetDevMacVLanCreateMutex = VIR_MUTEX_INITIALIZER;
|
||||
static int virNetDevMacVTapLastID = -1;
|
||||
static int virNetDevMacVLanLastID = -1;
|
||||
|
||||
|
||||
static void
|
||||
virNetDevMacVLanReserveNameInternal(const char *name)
|
||||
{
|
||||
unsigned int id;
|
||||
const char *idstr = NULL;
|
||||
int *lastID = NULL;
|
||||
int len;
|
||||
|
||||
if (STRPREFIX(name, VIR_NET_GENERATED_MACVTAP_PREFIX)) {
|
||||
lastID = &virNetDevMacVTapLastID;
|
||||
len = strlen(VIR_NET_GENERATED_MACVTAP_PREFIX);
|
||||
} else if (STRPREFIX(name, VIR_NET_GENERATED_MACVLAN_PREFIX)) {
|
||||
lastID = &virNetDevMacVTapLastID;
|
||||
len = strlen(VIR_NET_GENERATED_MACVLAN_PREFIX);
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
VIR_INFO("marking device in use: '%s'", name);
|
||||
|
||||
idstr = name + len;
|
||||
|
||||
if (virStrToLong_ui(idstr, NULL, 10, &id) >= 0) {
|
||||
if (*lastID < (int)id)
|
||||
*lastID = id;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* virNetDevMacVLanReserveName:
|
||||
* @name: name of an existing macvtap/macvlan device
|
||||
*
|
||||
* Set the value of virNetDevMacV(Lan|Tap)LastID to assure that any
|
||||
* new device created with an autogenerated name will use a number
|
||||
* higher than the number in the given device name.
|
||||
*
|
||||
* Returns nothing.
|
||||
*/
|
||||
void
|
||||
virNetDevMacVLanReserveName(const char *name)
|
||||
{
|
||||
virMutexLock(&virNetDevMacVLanCreateMutex);
|
||||
virNetDevMacVLanReserveNameInternal(name);
|
||||
virMutexUnlock(&virNetDevMacVLanCreateMutex);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* virNetDevMacVLanGenerateName:
|
||||
* @ifname: pointer to pointer to string containing template
|
||||
* @lastID: counter to add to the template to form the name
|
||||
*
|
||||
* generate a new (currently unused) name for a new macvtap/macvlan
|
||||
* device based on the template string in @ifname - replace %d with
|
||||
* ++(*counter), and keep trying new values until one is found
|
||||
* that doesn't already exist, or we've tried 10000 different
|
||||
* names. Once a usable name is found, replace the template with the
|
||||
* actual name.
|
||||
*
|
||||
* Returns 0 on success, -1 on failure.
|
||||
*/
|
||||
static int
|
||||
virNetDevMacVLanGenerateName(char **ifname, unsigned int flags)
|
||||
{
|
||||
const char *prefix;
|
||||
const char *iftemplate;
|
||||
int *lastID;
|
||||
int id;
|
||||
double maxIDd;
|
||||
int maxID = INT_MAX;
|
||||
int attempts = 0;
|
||||
|
||||
if (flags & VIR_NETDEV_MACVLAN_CREATE_WITH_TAP) {
|
||||
prefix = VIR_NET_GENERATED_MACVTAP_PREFIX;
|
||||
iftemplate = VIR_NET_GENERATED_MACVTAP_PREFIX "%d";
|
||||
lastID = &virNetDevMacVTapLastID;
|
||||
} else {
|
||||
prefix = VIR_NET_GENERATED_MACVLAN_PREFIX;
|
||||
iftemplate = VIR_NET_GENERATED_MACVLAN_PREFIX "%d";
|
||||
lastID = &virNetDevMacVLanLastID;
|
||||
}
|
||||
|
||||
maxIDd = pow(10, IFNAMSIZ - 1 - strlen(prefix));
|
||||
if (maxIDd <= (double)INT_MAX)
|
||||
maxID = (int)maxIDd;
|
||||
|
||||
do {
|
||||
g_autofree char *try = NULL;
|
||||
|
||||
id = ++(*lastID);
|
||||
|
||||
/* reset before overflow */
|
||||
if (*lastID == maxID)
|
||||
*lastID = -1;
|
||||
|
||||
try = g_strdup_printf(iftemplate, id);
|
||||
|
||||
if (!virNetDevExists(try)) {
|
||||
g_free(*ifname);
|
||||
*ifname = g_steal_pointer(&try);
|
||||
return 0;
|
||||
}
|
||||
} while (++attempts < 10000);
|
||||
|
||||
virReportError(VIR_ERR_INTERNAL_ERROR,
|
||||
_("no unused %s names available"),
|
||||
*ifname);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* virNetDevMacVLanIsMacvtap:
|
||||
@ -209,13 +85,10 @@ virNetDevMacVLanIsMacvtap(const char *ifname)
|
||||
* virNetDevMacVLanCreate:
|
||||
*
|
||||
* @ifname: The name the interface is supposed to have; optional parameter
|
||||
* @type: The type of device, i.e., "macvtap", "macvlan"
|
||||
* @macaddress: The MAC address of the device
|
||||
* @srcdev: The name of the 'link' device
|
||||
* @macvlan_mode: The macvlan mode to use
|
||||
* @retry: Pointer to integer that will be '1' upon return if an interface
|
||||
* with the same name already exists and it is worth to try
|
||||
* again with a different name
|
||||
* @flags: OR of virNetDevMacVLanCreateFlags.
|
||||
*
|
||||
* Create a macvtap device with the given properties.
|
||||
*
|
||||
@ -223,19 +96,20 @@ virNetDevMacVLanIsMacvtap(const char *ifname)
|
||||
*/
|
||||
int
|
||||
virNetDevMacVLanCreate(const char *ifname,
|
||||
const char *type,
|
||||
const virMacAddr *macaddress,
|
||||
const char *srcdev,
|
||||
uint32_t macvlan_mode)
|
||||
uint32_t macvlan_mode,
|
||||
unsigned int flags)
|
||||
{
|
||||
int error = 0;
|
||||
int ifindex = 0;
|
||||
const char *type = (flags & VIR_NETDEV_MACVLAN_CREATE_WITH_TAP ?
|
||||
"macvtap" : "macvlan");
|
||||
virNetlinkNewLinkData data = {
|
||||
.macvlan_mode = &macvlan_mode,
|
||||
.mac = macaddress,
|
||||
};
|
||||
|
||||
|
||||
if (virNetDevGetIndex(srcdev, &ifindex) < 0)
|
||||
return -1;
|
||||
|
||||
@ -795,7 +669,6 @@ virNetDevMacVLanCreateWithVPortProfile(const char *ifnameRequested,
|
||||
size_t tapfdSize,
|
||||
unsigned int flags)
|
||||
{
|
||||
const char *type = VIR_NET_GENERATED_PREFIX;
|
||||
g_autofree char *ifname = NULL;
|
||||
uint32_t macvtapMode;
|
||||
int vf = -1;
|
||||
@ -832,8 +705,6 @@ virNetDevMacVLanCreateWithVPortProfile(const char *ifnameRequested,
|
||||
return -1;
|
||||
}
|
||||
|
||||
virMutexLock(&virNetDevMacVLanCreateMutex);
|
||||
|
||||
if (ifnameRequested) {
|
||||
int rc;
|
||||
bool isAutoName
|
||||
@ -842,10 +713,8 @@ virNetDevMacVLanCreateWithVPortProfile(const char *ifnameRequested,
|
||||
|
||||
VIR_INFO("Requested macvtap device name: %s", ifnameRequested);
|
||||
|
||||
if ((rc = virNetDevExists(ifnameRequested)) < 0) {
|
||||
virMutexUnlock(&virNetDevMacVLanCreateMutex);
|
||||
if ((rc = virNetDevExists(ifnameRequested)) < 0)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (rc) {
|
||||
/* ifnameRequested is already being used */
|
||||
@ -854,17 +723,16 @@ virNetDevMacVLanCreateWithVPortProfile(const char *ifnameRequested,
|
||||
virReportSystemError(EEXIST,
|
||||
_("Unable to create device '%s'"),
|
||||
ifnameRequested);
|
||||
virMutexUnlock(&virNetDevMacVLanCreateMutex);
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
|
||||
/* ifnameRequested is available. try to open it */
|
||||
|
||||
virNetDevMacVLanReserveNameInternal(ifnameRequested);
|
||||
virNetDevReserveName(ifnameRequested);
|
||||
|
||||
if (virNetDevMacVLanCreate(ifnameRequested, type, macaddress,
|
||||
linkdev, macvtapMode) == 0) {
|
||||
if (virNetDevMacVLanCreate(ifnameRequested, macaddress,
|
||||
linkdev, macvtapMode, flags) == 0) {
|
||||
|
||||
/* virNetDevMacVLanCreate() was successful - use this name */
|
||||
ifname = g_strdup(ifnameRequested);
|
||||
@ -874,7 +742,6 @@ virNetDevMacVLanCreateWithVPortProfile(const char *ifnameRequested,
|
||||
* autogenerated named, so there is nothing else to
|
||||
* try - fail and return.
|
||||
*/
|
||||
virMutexUnlock(&virNetDevMacVLanCreateMutex);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@ -885,16 +752,19 @@ virNetDevMacVLanCreateWithVPortProfile(const char *ifnameRequested,
|
||||
* autogenerated name, so now we look for an unused
|
||||
* autogenerated name.
|
||||
*/
|
||||
if (virNetDevMacVLanGenerateName(&ifname, flags) < 0 ||
|
||||
virNetDevMacVLanCreate(ifname, type, macaddress,
|
||||
linkdev, macvtapMode) < 0) {
|
||||
virMutexUnlock(&virNetDevMacVLanCreateMutex);
|
||||
virNetDevGenNameType type;
|
||||
if (flags & VIR_NETDEV_MACVLAN_CREATE_WITH_TAP)
|
||||
type = VIR_NET_DEV_GEN_NAME_MACVTAP;
|
||||
else
|
||||
type = VIR_NET_DEV_GEN_NAME_MACVLAN;
|
||||
|
||||
if (virNetDevGenerateName(&ifname, type) < 0 ||
|
||||
virNetDevMacVLanCreate(ifname, macaddress,
|
||||
linkdev, macvtapMode, flags) < 0)
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* all done creating the device */
|
||||
virMutexUnlock(&virNetDevMacVLanCreateMutex);
|
||||
|
||||
if (virNetDevVPortProfileAssociate(ifname,
|
||||
virtPortProfile,
|
||||
@ -1050,10 +920,10 @@ bool virNetDevMacVLanIsMacvtap(const char *ifname G_GNUC_UNUSED)
|
||||
}
|
||||
|
||||
int virNetDevMacVLanCreate(const char *ifname G_GNUC_UNUSED,
|
||||
const char *type G_GNUC_UNUSED,
|
||||
const virMacAddr *macaddress G_GNUC_UNUSED,
|
||||
const char *srcdev G_GNUC_UNUSED,
|
||||
uint32_t macvlan_mode G_GNUC_UNUSED)
|
||||
uint32_t macvlan_mode G_GNUC_UNUSED,
|
||||
unsigned int fflags G_GNUC_UNUSED)
|
||||
{
|
||||
virReportSystemError(ENOSYS, "%s",
|
||||
_("Cannot create macvlan devices on this platform"));
|
||||
@ -1141,10 +1011,4 @@ int virNetDevMacVLanVPortProfileRegisterCallback(const char *ifname G_GNUC_UNUSE
|
||||
_("Cannot create macvlan devices on this platform"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
void virNetDevMacVLanReserveName(const char *name G_GNUC_UNUSED)
|
||||
{
|
||||
virReportSystemError(ENOSYS, "%s",
|
||||
_("Cannot create macvlan devices on this platform"));
|
||||
}
|
||||
#endif /* ! WITH_LIBNL */
|
||||
|
@ -48,23 +48,15 @@ typedef enum {
|
||||
VIR_NETDEV_MACVLAN_VNET_HDR = 1 << 2,
|
||||
} virNetDevMacVLanCreateFlags;
|
||||
|
||||
/* libvirt will start macvtap/macvlan interface names with one of
|
||||
* these prefixes when it auto-generates the name
|
||||
*/
|
||||
#define VIR_NET_GENERATED_MACVTAP_PREFIX "macvtap"
|
||||
#define VIR_NET_GENERATED_MACVLAN_PREFIX "macvlan"
|
||||
|
||||
void virNetDevMacVLanReserveName(const char *name);
|
||||
|
||||
bool virNetDevMacVLanIsMacvtap(const char *ifname)
|
||||
ATTRIBUTE_NONNULL(1) G_GNUC_WARN_UNUSED_RESULT G_GNUC_NO_INLINE;
|
||||
|
||||
int virNetDevMacVLanCreate(const char *ifname,
|
||||
const char *type,
|
||||
const virMacAddr *macaddress,
|
||||
const char *srcdev,
|
||||
uint32_t macvlan_mode)
|
||||
ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3) ATTRIBUTE_NONNULL(4)
|
||||
uint32_t macvlan_mode,
|
||||
unsigned int flags)
|
||||
ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3)
|
||||
G_GNUC_WARN_UNUSED_RESULT;
|
||||
|
||||
int virNetDevMacVLanDelete(const char *ifname)
|
||||
|
Loading…
Reference in New Issue
Block a user