36
* @veth: name for veth device (NULL to find first open)
37
* @maxLen: max length of veth name
37
* @veth: pointer to store returned name for veth device
38
38
* @startDev: device number to start at (x in vethx)
40
40
* Looks in /sys/class/net/ to find the first available veth device
43
* Returns 0 on success or -1 in case of error
43
* Returns non-negative device number on success or -1 in case of error
45
static int getFreeVethName(char *veth, int maxLen, int startDev)
45
static int getFreeVethName(char **veth, int startDev)
48
47
int devNum = startDev-1;
53
snprintf(path, PATH_MAX, "/sys/class/net/veth%d/", devNum);
53
if (virAsprintf(&path, "/sys/class/net/veth%d/", devNum) < 0) {
54
57
} while (virFileExists(path));
56
snprintf(veth, maxLen, "veth%d", devNum);
60
if (virAsprintf(veth, "veth%d", devNum) < 0) {
65
* @veth1: name for one end of veth pair
66
* @veth1MaxLen: max length of veth1 name
67
* @veth2: name for one end of veth pair
68
* @veth2MaxLen: max length of veth1 name
69
* @veth1: pointer to name for parent end of veth pair
70
* @veth2: pointer to return name for container end of veth pair
70
72
* Creates a veth device pair using the ip command:
71
73
* ip link add veth1 type veth peer name veth2
74
* If veth1 points to NULL on entry, it will be a valid interface on
75
* return. veth2 should point to NULL on entry.
72
77
* NOTE: If veth1 and veth2 names are not specified, ip will auto assign
73
78
* names. There seems to be two problems here -
74
79
* 1) There doesn't seem to be a way to determine the names of the
78
83
* 2) Once one of the veth devices is moved to another namespace, it
79
84
* is no longer visible in the parent namespace. This seems to
80
85
* confuse the name assignment causing it to fail with File exists.
81
* Because of these issues, this function currently forces the caller
82
* to fully specify the veth device names.
86
* Because of these issues, this function currently allocates names
87
* prior to using the ip command, and returns any allocated names
84
90
* Returns 0 on success or -1 in case of error
86
int vethCreate(char* veth1, int veth1MaxLen,
87
char* veth2, int veth2MaxLen)
92
int vethCreate(char** veth1, char** veth2)
90
95
const char *argv[] = {
91
"ip", "link", "add", veth1, "type", "veth", "peer", "name", veth2, NULL
96
"ip", "link", "add", NULL, "type", "veth", "peer", "name", NULL, NULL
96
DEBUG("veth1: %s veth2: %s", veth1, veth2);
98
while ((1 > strlen(veth1)) || STREQ(veth1, veth2)) {
99
vethDev = getFreeVethName(veth1, veth1MaxLen, 0);
101
DEBUG("Assigned veth1: %s", veth1);
104
while ((1 > strlen(veth2)) || STREQ(veth1, veth2)) {
105
vethDev = getFreeVethName(veth2, veth2MaxLen, vethDev);
107
DEBUG("Assigned veth2: %s", veth2);
110
DEBUG("veth1: %s veth2: %s", veth1, veth2);
100
bool veth1_alloc = false;
102
DEBUG("veth1: %s veth2: %s", NULLSTR(*veth1), NULLSTR(*veth2));
104
if (*veth1 == NULL) {
105
vethDev = getFreeVethName(veth1, vethDev);
108
DEBUG("Assigned veth1: %s", *veth1);
113
while (*veth2 == NULL || STREQ(*veth1, *veth2)) {
115
vethDev = getFreeVethName(veth2, vethDev + 1);
121
DEBUG("Assigned veth2: %s", *veth2);
125
DEBUG("veth1: %s veth2: %s", *veth1, *veth2);
111
126
rc = virRun(argv, &cmdResult);
114
129
(WIFEXITED(cmdResult) && WEXITSTATUS(cmdResult) != 0)) {
115
130
vethError(VIR_ERR_INTERNAL_ERROR,
116
131
_("Failed to create veth device pair '%s', '%s': %d"),
117
veth1, veth2, WEXITSTATUS(cmdResult));
132
*veth1, *veth2, WEXITSTATUS(cmdResult));