Skip to content

Commit 4797cbd

Browse files
committed
Handle ethernet network interface types
These are used in the CI and were previously working when passing the network device by tap name.
1 parent 0f63b0c commit 4797cbd

3 files changed

Lines changed: 155 additions & 3 deletions

File tree

src/ch/ch_interface.c

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,133 @@
1515

1616
VIR_LOG_INIT("ch.ch_interface");
1717

18+
/* chInterfaceEthernetConnect:
19+
* @def: the definition of the VM
20+
* @driver: ch driver data
21+
* @net: pointer to the VM's interface description
22+
* @tapfd: array of file descriptor return value for the new device
23+
* @tapfdsize: number of file descriptors in @tapfd
24+
*
25+
* Called *only* called if actualType is VIR_DOMAIN_NET_TYPE_ETHERNET
26+
* (i.e. if the connection is made with a tap device)
27+
*/
28+
int
29+
chInterfaceEthernetConnect(virDomainDefPtr def,
30+
virCHDriverPtr driver,
31+
virDomainNetDefPtr net,
32+
int *tapfd,
33+
size_t tapfdSize)
34+
{
35+
virMacAddr tapmac;
36+
int ret = -1;
37+
unsigned int tap_create_flags = VIR_NETDEV_TAP_CREATE_IFUP;
38+
bool template_ifname = false;
39+
virCHDriverConfigPtr cfg = virCHDriverGetConfig(driver);
40+
const char *tunpath = "/dev/net/tun";
41+
const char *auditdev = tunpath;
42+
43+
if (net->backend.tap) {
44+
tunpath = net->backend.tap;
45+
if (!driver->privileged) {
46+
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
47+
_("cannot use custom tap device in session mode"));
48+
goto cleanup;
49+
}
50+
}
51+
52+
if (virDomainNetIsVirtioModel(net))
53+
tap_create_flags |= VIR_NETDEV_TAP_CREATE_VNET_HDR;
54+
55+
if (net->managed_tap == VIR_TRISTATE_BOOL_NO) {
56+
if (!net->ifname) {
57+
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
58+
_("target dev must be supplied when managed='no'"));
59+
goto cleanup;
60+
}
61+
if (virNetDevExists(net->ifname) != 1) {
62+
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
63+
_("target managed='no' but specified dev doesn't exist"));
64+
goto cleanup;
65+
}
66+
if (virNetDevMacVLanIsMacvtap(net->ifname)) {
67+
auditdev = net->ifname;
68+
if (virNetDevMacVLanTapOpen(net->ifname, tapfd, tapfdSize) < 0)
69+
goto cleanup;
70+
if (virNetDevMacVLanTapSetup(tapfd, tapfdSize,
71+
virDomainNetIsVirtioModel(net)) < 0) {
72+
goto cleanup;
73+
}
74+
} else {
75+
if (virNetDevTapCreate(&net->ifname, tunpath, tapfd, tapfdSize,
76+
tap_create_flags) < 0)
77+
goto cleanup;
78+
}
79+
} else {
80+
if (!net->ifname ||
81+
STRPREFIX(net->ifname, VIR_NET_GENERATED_TAP_PREFIX) ||
82+
strchr(net->ifname, '%')) {
83+
g_free(net->ifname);
84+
net->ifname = g_strdup(VIR_NET_GENERATED_TAP_PREFIX "%d");
85+
/* avoid exposing vnet%d in getXMLDesc or error outputs */
86+
template_ifname = true;
87+
}
88+
if (virNetDevTapCreate(&net->ifname, tunpath, tapfd, tapfdSize,
89+
tap_create_flags) < 0) {
90+
goto cleanup;
91+
}
92+
93+
/* The tap device's MAC address cannot match the MAC address
94+
* used by the guest. This results in "received packet on
95+
* vnetX with own address as source address" error logs from
96+
* the kernel.
97+
*/
98+
virMacAddrSet(&tapmac, &net->mac);
99+
if (tapmac.addr[0] == 0xFE)
100+
tapmac.addr[0] = 0xFA;
101+
else
102+
tapmac.addr[0] = 0xFE;
103+
104+
if (virNetDevSetMAC(net->ifname, &tapmac) < 0)
105+
goto cleanup;
106+
107+
if (virNetDevSetOnline(net->ifname, true) < 0)
108+
goto cleanup;
109+
}
110+
111+
if (net->script &&
112+
virNetDevRunEthernetScript(net->ifname, net->script) < 0)
113+
goto cleanup;
114+
115+
if (cfg->macFilter &&
116+
ebtablesAddForwardAllowIn(driver->ebtables,
117+
net->ifname,
118+
&net->mac) < 0)
119+
goto cleanup;
120+
121+
if (net->filter &&
122+
virDomainConfNWFilterInstantiate(def->name, def->uuid, net, false) < 0) {
123+
goto cleanup;
124+
}
125+
126+
virDomainAuditNetDevice(def, net, auditdev, true);
127+
128+
ret = 0;
129+
130+
cleanup:
131+
if (ret < 0) {
132+
size_t i;
133+
134+
virDomainAuditNetDevice(def, net, auditdev, false);
135+
for (i = 0; i < tapfdSize && tapfd[i] >= 0; i++)
136+
VIR_FORCE_CLOSE(tapfd[i]);
137+
if (template_ifname)
138+
g_free(net->ifname);
139+
}
140+
virObjectUnref(cfg);
141+
142+
return ret;
143+
}
144+
18145
/* chInterfaceBridgeConnect:
19146
* @def: the definition of the VM
20147
* @driver: qemu driver data

src/ch/ch_interface.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,15 @@
11
#include "domain_conf.h"
22
#include "ch_conf.h"
33

4+
int
5+
chInterfaceEthernetConnect(virDomainDefPtr def,
6+
virCHDriverPtr driver,
7+
virDomainNetDefPtr net,
8+
int *tapfd,
9+
size_t tapfdSize);
10+
411
int chInterfaceBridgeConnect(virDomainDefPtr def,
512
virCHDriverPtr driver,
613
virDomainNetDefPtr net,
714
int *tapfd,
8-
size_t *tapfdSize);
15+
size_t *tapfdSize);

src/ch/ch_process.c

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -589,10 +589,11 @@ chProcessNetworkPrepareDevices(virCHDriverPtr driver, virDomainObjPtr vm)
589589
} else if (actualType == VIR_DOMAIN_NET_TYPE_USER ) {
590590
virReportError(VIR_ERR_INTERNAL_ERROR,
591591
_("VIR_DOMAIN_NET_TYPE_USER is not a supported Network type"));
592-
} else if (actualType == VIR_DOMAIN_NET_TYPE_NETWORK ) {
592+
} else if (actualType == VIR_DOMAIN_NET_TYPE_NETWORK) {
593593
tapfdSize = net->driver.virtio.queues;
594594
if (!tapfdSize)
595595
tapfdSize = 1;
596+
VIR_ERROR("tapfd: %lu", tapfdSize);
596597

597598
tapfd = g_new(int, tapfdSize);
598599

@@ -606,7 +607,24 @@ chProcessNetworkPrepareDevices(virCHDriverPtr driver, virDomainObjPtr vm)
606607
// This info will be used while generating Network Json
607608
priv->tapfd = g_steal_pointer(&tapfd);
608609
priv->tapfdSize = tapfdSize;
609-
}
610+
} else if (actualType == VIR_DOMAIN_NET_TYPE_ETHERNET) {
611+
tapfdSize = net->driver.virtio.queues;
612+
if (!tapfdSize)
613+
tapfdSize = 1;
614+
615+
tapfd = g_new(int, tapfdSize);
616+
617+
memset(tapfd, -1, tapfdSize * sizeof(tapfd[0]));
618+
619+
if (chInterfaceEthernetConnect(def, driver, net,
620+
tapfd, tapfdSize) < 0)
621+
goto cleanup;
622+
623+
// Store tap information in Private Data
624+
// This info will be used while generating Network Json
625+
priv->tapfd = g_steal_pointer(&tapfd);
626+
priv->tapfdSize = tapfdSize;
627+
}
610628
}
611629

612630
return 0;

0 commit comments

Comments
 (0)