# include <net/if.h>
# include <linux/if_tun.h>
-# include <math.h>
# include "viralloc.h"
# include "virlog.h"
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:
* 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.
*
*/
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;
size_t tapfdSize,
unsigned int flags)
{
- const char *type = VIR_NET_GENERATED_PREFIX;
g_autofree char *ifname = NULL;
uint32_t macvtapMode;
int vf = -1;
return -1;
}
- virMutexLock(&virNetDevMacVLanCreateMutex);
-
if (ifnameRequested) {
int rc;
bool isAutoName
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 */
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);
* autogenerated named, so there is nothing else to
* try - fail and return.
*/
- virMutexUnlock(&virNetDevMacVLanCreateMutex);
return -1;
}
}
* 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,
}
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"));
_("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 */