提交 aa2cc721 编写于 作者: C Cédric Bosdonnat

Domain conf: allow more than one IP address for net devices

Add the possibility to have more than one IP address configured for a
domain network interface. IP addresses can also have a prefix to define
the corresponding netmask.
上级 c9ebdf9b
......@@ -4321,6 +4321,29 @@ qemu-kvm -net nic,model=? /dev/null
<span class="since">Since 0.9.5</span>
</p>
<h5><a name="ipconfig">IP configuration</a></h5>
<pre>
...
&lt;devices&gt;
&lt;interface type='network'&gt;
&lt;source network='default'/&gt;
&lt;target dev='vnet0'/&gt;
<b>&lt;ip family='ipv4' address='192.168.122.5' prefix='24'/&gt;</b>
&lt;/interface&gt;
&lt;/devices&gt;
...
</pre>
<p>
<span class="since">Since 1.2.12</span> the network devices and host devices
with network capabilities can be provided zero or more IP addresses to set
on the target device. Note that some hypervisors or network device types
will simply ignore them or only use the first one. The <code>family</code>
attribute can be set to either <code>ipv4</code> or <code>ipv6</code>, the
<code>address</code> attribute holds the IP address. The <code>prefix</code>
is not mandatory since some hypervisors do not handle it.
</p>
<h5><a name="elementVhostuser">vhost-user interface</a></h5>
<p>
......
......@@ -2311,14 +2311,24 @@
<empty/>
</element>
</optional>
<optional>
<zeroOrMore>
<element name="ip">
<attribute name="address">
<ref name="ipv4Addr"/>
<ref name="ipAddr"/>
</attribute>
<optional>
<attribute name="family">
<ref name="addr-family"/>
</attribute>
</optional>
<optional>
<attribute name="prefix">
<ref name="ipPrefix"/>
</attribute>
</optional>
<empty/>
</element>
</optional>
</zeroOrMore>
<optional>
<element name="script">
<attribute name="path">
......
......@@ -1414,6 +1414,8 @@ virDomainActualNetDefFree(virDomainActualNetDefPtr def)
void virDomainNetDefFree(virDomainNetDefPtr def)
{
size_t i;
if (!def)
return;
......@@ -1422,7 +1424,6 @@ void virDomainNetDefFree(virDomainNetDefPtr def)
switch (def->type) {
case VIR_DOMAIN_NET_TYPE_ETHERNET:
VIR_FREE(def->data.ethernet.dev);
VIR_FREE(def->data.ethernet.ipaddr);
break;
case VIR_DOMAIN_NET_TYPE_VHOSTUSER:
......@@ -1443,7 +1444,6 @@ void virDomainNetDefFree(virDomainNetDefPtr def)
case VIR_DOMAIN_NET_TYPE_BRIDGE:
VIR_FREE(def->data.bridge.brname);
VIR_FREE(def->data.bridge.ipaddr);
break;
case VIR_DOMAIN_NET_TYPE_INTERNAL:
......@@ -1471,6 +1471,10 @@ void virDomainNetDefFree(virDomainNetDefPtr def)
VIR_FREE(def->ifname_guest);
VIR_FREE(def->ifname_guest_actual);
for (i = 0; i < def->nips; i++)
VIR_FREE(def->ips[i]);
VIR_FREE(def->ips);
virDomainDeviceInfoClear(&def->info);
VIR_FREE(def->filter);
......@@ -4770,6 +4774,58 @@ virDomainHostdevDefParseXMLSubsys(xmlNodePtr node,
return ret;
}
static virDomainNetIpDefPtr
virDomainNetIpParseXML(xmlNodePtr node)
{
/* Parse the prefix in every case */
virDomainNetIpDefPtr ip = NULL;
char *prefixStr = NULL;
unsigned int prefixValue = 0;
char *familyStr = NULL;
int family = AF_UNSPEC;
char *address = NULL;
if (!(prefixStr = virXMLPropString(node, "prefix")) ||
(virStrToLong_ui(prefixStr, NULL, 10, &prefixValue) < 0)) {
// Don't shout, as some old config may not have a prefix
VIR_DEBUG("Missing or invalid network prefix");
}
if (!(address = virXMLPropString(node, "address"))) {
virReportError(VIR_ERR_INVALID_ARG, "%s",
_("Missing network address"));
goto error;
}
familyStr = virXMLPropString(node, "family");
if (familyStr && STREQ(familyStr, "ipv4"))
family = AF_INET;
else if (familyStr && STREQ(familyStr, "ipv6"))
family = AF_INET6;
else
family = virSocketAddrNumericFamily(address);
if (VIR_ALLOC(ip) < 0)
goto error;
if (virSocketAddrParse(&ip->address, address, family) < 0) {
virReportError(VIR_ERR_INVALID_ARG,
_("Failed to parse IP address: '%s'"),
address);
goto error;
}
ip->prefix = prefixValue;
return ip;
error:
VIR_FREE(prefixStr);
VIR_FREE(familyStr);
VIR_FREE(address);
VIR_FREE(ip);
return NULL;
}
static int
virDomainHostdevDefParseXMLCaps(xmlNodePtr node ATTRIBUTE_UNUSED,
xmlXPathContextPtr ctxt,
......@@ -7208,6 +7264,31 @@ virDomainActualNetDefParseXML(xmlNodePtr node,
#define NET_MODEL_CHARS \
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-"
int
virDomainNetAppendIpAddress(virDomainNetDefPtr def,
const char *address,
int family,
unsigned int prefix)
{
virDomainNetIpDefPtr ipDef = NULL;
if (VIR_ALLOC(ipDef) < 0)
return -1;
if (virSocketAddrParse(&ipDef->address, address, family) < 0)
goto error;
ipDef->prefix = prefix;
if (VIR_APPEND_ELEMENT(def->ips, def->nips, ipDef) < 0)
goto error;
return 0;
error:
VIR_FREE(ipDef);
return -1;
}
/* Parse the XML definition for a network interface
* @param node XML nodeset to parse for net definition
* @return 0 on success, -1 on failure
......@@ -7255,6 +7336,9 @@ virDomainNetDefParseXML(virDomainXMLOptionPtr xmlopt,
virDomainActualNetDefPtr actual = NULL;
xmlNodePtr oldnode = ctxt->node;
int ret, val;
size_t i;
size_t nips = 0;
virDomainNetIpDefPtr *ips = NULL;
if (VIR_ALLOC(def) < 0)
return NULL;
......@@ -7343,11 +7427,14 @@ virDomainNetDefParseXML(virDomainXMLOptionPtr xmlopt,
xmlStrEqual(cur->name, BAD_CAST "source")) {
address = virXMLPropString(cur, "address");
port = virXMLPropString(cur, "port");
} else if (!address &&
(def->type == VIR_DOMAIN_NET_TYPE_ETHERNET ||
def->type == VIR_DOMAIN_NET_TYPE_BRIDGE) &&
xmlStrEqual(cur->name, BAD_CAST "ip")) {
address = virXMLPropString(cur, "address");
} else if (xmlStrEqual(cur->name, BAD_CAST "ip")) {
virDomainNetIpDefPtr ip = NULL;
if (!(ip = virDomainNetIpParseXML(cur)))
goto error;
if (VIR_APPEND_ELEMENT(ips, nips, ip) < 0)
goto error;
} else if (!ifname &&
xmlStrEqual(cur->name, BAD_CAST "target")) {
ifname = virXMLPropString(cur, "dev");
......@@ -7547,10 +7634,6 @@ virDomainNetDefParseXML(virDomainXMLOptionPtr xmlopt,
def->data.ethernet.dev = dev;
dev = NULL;
}
if (address != NULL) {
def->data.ethernet.ipaddr = address;
address = NULL;
}
break;
case VIR_DOMAIN_NET_TYPE_BRIDGE:
......@@ -7562,10 +7645,6 @@ virDomainNetDefParseXML(virDomainXMLOptionPtr xmlopt,
}
def->data.bridge.brname = bridge;
bridge = NULL;
if (address != NULL) {
def->data.bridge.ipaddr = address;
address = NULL;
}
break;
case VIR_DOMAIN_NET_TYPE_CLIENT:
......@@ -7662,6 +7741,11 @@ virDomainNetDefParseXML(virDomainXMLOptionPtr xmlopt,
break;
}
for (i = 0; i < nips; i++) {
if (VIR_APPEND_ELEMENT(def->ips, def->nips, ips[i]) < 0)
goto error;
}
if (script != NULL) {
def->script = script;
script = NULL;
......@@ -7924,6 +8008,7 @@ virDomainNetDefParseXML(virDomainXMLOptionPtr xmlopt,
VIR_FREE(linkstate);
VIR_FREE(addrtype);
VIR_FREE(trustGuestRxFilters);
VIR_FREE(ips);
virNWFilterHashTableFree(filterparams);
return def;
......@@ -17042,6 +17127,30 @@ virDomainFSDefFormat(virBufferPtr buf,
return 0;
}
static void
virDomainNetIpsFormat(virBufferPtr buf, virDomainNetIpDefPtr *ips, size_t nips)
{
size_t i;
/* Output IP addresses */
for (i = 0; i < nips; i++) {
virSocketAddrPtr address = &ips[i]->address;
char *ipStr = virSocketAddrFormat(address);
const char *familyStr = NULL;
if (VIR_SOCKET_ADDR_IS_FAMILY(address, AF_INET6))
familyStr = "ipv6";
else if (VIR_SOCKET_ADDR_IS_FAMILY(address, AF_INET))
familyStr = "ipv4";
virBufferAsprintf(buf, "<ip address='%s'",
ipStr);
if (familyStr)
virBufferAsprintf(buf, " family='%s'", familyStr);
if (ips[i]->prefix != 0)
virBufferAsprintf(buf, " prefix='%u'", ips[i]->prefix);
virBufferAddLit(buf, "/>\n");
}
}
static int
virDomainHostdevDefFormatSubsys(virBufferPtr buf,
virDomainHostdevDefPtr def,
......@@ -17274,7 +17383,6 @@ virDomainActualNetDefContentsFormat(virBufferPtr buf,
return 0;
}
/* virDomainActualNetDefFormat() - format the ActualNetDef
* info inside an <actual> element, as required for internal storage
* of domain status
......@@ -17511,9 +17619,6 @@ virDomainNetDefFormat(virBufferPtr buf,
case VIR_DOMAIN_NET_TYPE_ETHERNET:
virBufferEscapeString(buf, "<source dev='%s'/>\n",
def->data.ethernet.dev);
if (def->data.ethernet.ipaddr)
virBufferAsprintf(buf, "<ip address='%s'/>\n",
def->data.ethernet.ipaddr);
break;
case VIR_DOMAIN_NET_TYPE_VHOSTUSER:
......@@ -17531,10 +17636,6 @@ virDomainNetDefFormat(virBufferPtr buf,
case VIR_DOMAIN_NET_TYPE_BRIDGE:
virBufferEscapeString(buf, "<source bridge='%s'/>\n",
def->data.bridge.brname);
if (def->data.bridge.ipaddr) {
virBufferAsprintf(buf, "<ip address='%s'/>\n",
def->data.bridge.ipaddr);
}
break;
case VIR_DOMAIN_NET_TYPE_SERVER:
......@@ -17582,6 +17683,8 @@ virDomainNetDefFormat(virBufferPtr buf,
return -1;
}
virDomainNetIpsFormat(buf, def->ips, def->nips);
virBufferEscapeString(buf, "<script path='%s'/>\n",
def->script);
if (def->ifname &&
......
......@@ -478,6 +478,13 @@ typedef enum {
VIR_DOMAIN_HOSTDEV_CAPS_TYPE_LAST
} virDomainHostdevCapsType;
typedef struct _virDomainNetIpDef virDomainNetIpDef;
typedef virDomainNetIpDef *virDomainNetIpDefPtr;
struct _virDomainNetIpDef {
virSocketAddr address; /* ipv4 or ipv6 address */
unsigned int prefix; /* number of 1 bits in the net mask */
};
typedef struct _virDomainHostdevCaps virDomainHostdevCaps;
typedef virDomainHostdevCaps *virDomainHostdevCapsPtr;
struct _virDomainHostdevCaps {
......@@ -941,7 +948,6 @@ struct _virDomainNetDef {
union {
struct {
char *dev;
char *ipaddr;
} ethernet;
virDomainChrSourceDefPtr vhostuser;
struct {
......@@ -963,7 +969,6 @@ struct _virDomainNetDef {
} network;
struct {
char *brname;
char *ipaddr;
} bridge;
struct {
char *name;
......@@ -993,6 +998,8 @@ struct _virDomainNetDef {
virNetDevVlan vlan;
int trustGuestRxFilters; /* enum virTristateBool */
int linkstate;
size_t nips;
virDomainNetIpDefPtr *ips;
};
/* Used for prefix of ifname of any network name generated dynamically
......@@ -2554,6 +2561,10 @@ virNetDevBandwidthPtr
virDomainNetGetActualBandwidth(virDomainNetDefPtr iface);
virNetDevVlanPtr virDomainNetGetActualVlan(virDomainNetDefPtr iface);
bool virDomainNetGetActualTrustGuestRxFilters(virDomainNetDefPtr iface);
int virDomainNetAppendIpAddress(virDomainNetDefPtr def,
const char *address,
int family,
unsigned int prefix);
int virDomainControllerInsert(virDomainDefPtr def,
virDomainControllerDefPtr controller)
......
......@@ -322,6 +322,7 @@ virDomainLockFailureTypeFromString;
virDomainLockFailureTypeToString;
virDomainMemballoonModelTypeFromString;
virDomainMemballoonModelTypeToString;
virDomainNetAppendIpAddress;
virDomainNetDefFormat;
virDomainNetDefFree;
virDomainNetFind;
......
......@@ -230,7 +230,7 @@ openvzReadNetworkConf(virDomainDefPtr def,
goto error;
net->type = VIR_DOMAIN_NET_TYPE_ETHERNET;
if (VIR_STRDUP(net->data.ethernet.ipaddr, token) < 0)
if (virDomainNetAppendIpAddress(net, token, AF_UNSPEC, 0) < 0)
goto error;
if (VIR_APPEND_ELEMENT_COPY(def->nets, def->nnets, net) < 0)
......
......@@ -853,7 +853,7 @@ openvzDomainSetNetwork(virConnectPtr conn, const char *vpsid,
if (net->type == VIR_DOMAIN_NET_TYPE_BRIDGE ||
(net->type == VIR_DOMAIN_NET_TYPE_ETHERNET &&
net->data.ethernet.ipaddr == NULL)) {
net->nips == 0)) {
virBuffer buf = VIR_BUFFER_INITIALIZER;
int veid = openvzGetVEID(vpsid);
......@@ -904,9 +904,10 @@ openvzDomainSetNetwork(virConnectPtr conn, const char *vpsid,
virCommandAddArg(cmd, "--netif_add");
virCommandAddArgBuffer(cmd, &buf);
} else if (net->type == VIR_DOMAIN_NET_TYPE_ETHERNET &&
net->data.ethernet.ipaddr != NULL) {
net->nips > 0) {
/* --ipadd ip */
virCommandAddArgList(cmd, "--ipadd", net->data.ethernet.ipaddr, NULL);
char *ipStr = virSocketAddrFormat(&net->ips[0]->address);
virCommandAddArgList(cmd, "--ipadd", ipStr, NULL);
}
/* TODO: processing NAT and physical device */
......
......@@ -6345,6 +6345,8 @@ static char *qemuConnectDomainXMLToNative(virConnectPtr conn,
(brname = virDomainNetGetActualBridgeName(net))) {
char *brnamecopy;
size_t j;
if (VIR_STRDUP(brnamecopy, brname) < 0)
goto cleanup;
......@@ -6355,20 +6357,29 @@ static char *qemuConnectDomainXMLToNative(virConnectPtr conn,
net->type = VIR_DOMAIN_NET_TYPE_ETHERNET;
net->script = NULL;
net->data.ethernet.dev = brnamecopy;
net->data.ethernet.ipaddr = NULL;
for (j = 0; j < net->nips; j++)
VIR_FREE(net->ips[j]);
VIR_FREE(net->ips);
net->nips = 0;
} else {
/* actualType is either NETWORK or DIRECT. In either
* case, the best we can do is NULL everything out.
*/
size_t j;
virDomainActualNetDefFree(net->data.network.actual);
memset(net, 0, sizeof(*net));
net->type = VIR_DOMAIN_NET_TYPE_ETHERNET;
net->script = NULL;
net->data.ethernet.dev = NULL;
net->data.ethernet.ipaddr = NULL;
for (j = 0; j < net->nips; j++)
VIR_FREE(net->ips[j]);
VIR_FREE(net->ips);
net->nips = 0;
}
} else if (net->type == VIR_DOMAIN_NET_TYPE_DIRECT) {
size_t j;
VIR_FREE(net->data.direct.linkdev);
memset(net, 0, sizeof(*net));
......@@ -6376,18 +6387,23 @@ static char *qemuConnectDomainXMLToNative(virConnectPtr conn,
net->type = VIR_DOMAIN_NET_TYPE_ETHERNET;
net->script = NULL;
net->data.ethernet.dev = NULL;
net->data.ethernet.ipaddr = NULL;
for (j = 0; j < net->nips; j++)
VIR_FREE(net->ips[j]);
VIR_FREE(net->ips);
net->nips = 0;
} else if (net->type == VIR_DOMAIN_NET_TYPE_BRIDGE) {
char *script = net->script;
char *brname = net->data.bridge.brname;
char *ipaddr = net->data.bridge.ipaddr;
size_t nips = net->nips;
virDomainNetIpDefPtr *ips = net->ips;
memset(net, 0, sizeof(*net));
net->type = VIR_DOMAIN_NET_TYPE_ETHERNET;
net->script = script;
net->data.ethernet.dev = brname;
net->data.ethernet.ipaddr = ipaddr;
net->nips = nips;
net->ips = ips;
}
VIR_FREE(net->virtPortProfile);
......
......@@ -2043,8 +2043,9 @@ qemuDomainChangeNet(virQEMUDriverPtr driver,
case VIR_DOMAIN_NET_TYPE_ETHERNET:
if (STRNEQ_NULLABLE(olddev->data.ethernet.dev,
newdev->data.ethernet.dev) ||
STRNEQ_NULLABLE(olddev->data.ethernet.ipaddr,
newdev->data.ethernet.ipaddr)) {
olddev->nips == 0 || newdev->nips == 0 ||
!virSocketAddrEqual(&olddev->ips[0]->address,
&newdev->ips[0]->address)) {
needReconnect = true;
}
break;
......
......@@ -174,7 +174,7 @@ umlBuildCommandLineNet(virConnectPtr conn,
virBufferAddLit(&buf, "tuntap,");
if (def->ifname)
virBufferAdd(&buf, def->ifname, -1);
if (def->data.ethernet.ipaddr) {
if (def->nips > 0) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("IP address not supported for ethernet interface"));
goto error;
......
......@@ -1306,7 +1306,11 @@ vboxAttachNetwork(virDomainDefPtr def, vboxGlobalData *data, IMachine *machine)
} else if (def->nets[i]->type == VIR_DOMAIN_NET_TYPE_BRIDGE) {
VIR_DEBUG("NIC(%zu): brname: %s", i, def->nets[i]->data.bridge.brname);
VIR_DEBUG("NIC(%zu): script: %s", i, def->nets[i]->script);
VIR_DEBUG("NIC(%zu): ipaddr: %s", i, def->nets[i]->data.bridge.ipaddr);
if (def->nets[i]->nips > 0) {
char *ipStr = virSocketAddrFormat(&def->nets[i]->ips[0]->address);
VIR_DEBUG("NIC(%zu): ipaddr: %s", i, ipStr);
VIR_FREE(ipStr);
}
}
gVBoxAPI.UIMachine.GetNetworkAdapter(machine, i, &adapter);
......
......@@ -920,12 +920,9 @@ xenParseVif(virConfPtr conf, virDomainDefPtr def)
if (net->type == VIR_DOMAIN_NET_TYPE_BRIDGE) {
if (bridge[0] && VIR_STRDUP(net->data.bridge.brname, bridge) < 0)
goto cleanup;
if (ip[0] && VIR_STRDUP(net->data.bridge.ipaddr, ip) < 0)
goto cleanup;
} else {
if (ip[0] && VIR_STRDUP(net->data.ethernet.ipaddr, ip) < 0)
goto cleanup;
}
if (ip[0] && virDomainNetAppendIpAddress(net, ip, AF_INET, 0) < 0)
goto cleanup;
if (script && script[0] &&
VIR_STRDUP(net->script, script) < 0)
......@@ -1223,16 +1220,22 @@ xenFormatNet(virConnectPtr conn,
switch (net->type) {
case VIR_DOMAIN_NET_TYPE_BRIDGE:
virBufferAsprintf(&buf, ",bridge=%s", net->data.bridge.brname);
if (net->data.bridge.ipaddr)
virBufferAsprintf(&buf, ",ip=%s", net->data.bridge.ipaddr);
if (net->nips > 0) {
char *ipStr = virSocketAddrFormat(&net->ips[0]->address);
virBufferAsprintf(&buf, ",ip=%s", ipStr);
VIR_FREE(ipStr);
}
virBufferAsprintf(&buf, ",script=%s", DEFAULT_VIF_SCRIPT);
break;
case VIR_DOMAIN_NET_TYPE_ETHERNET:
if (net->script)
virBufferAsprintf(&buf, ",script=%s", net->script);
if (net->data.ethernet.ipaddr)
virBufferAsprintf(&buf, ",ip=%s", net->data.ethernet.ipaddr);
if (net->nips > 0) {
char *ipStr = virSocketAddrFormat(&net->ips[0]->address);
virBufferAsprintf(&buf, ",ip=%s", ipStr);
VIR_FREE(ipStr);
}
break;
case VIR_DOMAIN_NET_TYPE_NETWORK:
......
......@@ -565,14 +565,14 @@ xenParseSxprNets(virDomainDefPtr def,
VIR_STRDUP(net->script, tmp2) < 0)
goto cleanup;
tmp = sexpr_node(node, "device/vif/ip");
if (VIR_STRDUP(net->data.bridge.ipaddr, tmp) < 0)
if (tmp && virDomainNetAppendIpAddress(net, tmp, AF_UNSPEC, 0) < 0)
goto cleanup;
} else {
net->type = VIR_DOMAIN_NET_TYPE_ETHERNET;
if (VIR_STRDUP(net->script, tmp2) < 0)
goto cleanup;
tmp = sexpr_node(node, "device/vif/ip");
if (VIR_STRDUP(net->data.ethernet.ipaddr, tmp) < 0)
if (tmp && virDomainNetAppendIpAddress(net, tmp, AF_UNSPEC, 0) < 0)
goto cleanup;
}
......@@ -1898,8 +1898,11 @@ xenFormatSxprNet(virConnectPtr conn,
script = def->script;
virBufferEscapeSexpr(buf, "(script '%s')", script);
if (def->data.bridge.ipaddr != NULL)
virBufferEscapeSexpr(buf, "(ip '%s')", def->data.bridge.ipaddr);
if (def->nips > 0) {
char *ipStr = virSocketAddrFormat(&def->ips[0]->address);
virBufferEscapeSexpr(buf, "(ip '%s')", ipStr);
VIR_FREE(ipStr);
}
break;
case VIR_DOMAIN_NET_TYPE_NETWORK:
......@@ -1932,8 +1935,11 @@ xenFormatSxprNet(virConnectPtr conn,
if (def->script)
virBufferEscapeSexpr(buf, "(script '%s')",
def->script);
if (def->data.ethernet.ipaddr != NULL)
virBufferEscapeSexpr(buf, "(ip '%s')", def->data.ethernet.ipaddr);
if (def->nips > 0) {
char *ipStr = virSocketAddrFormat(&def->ips[0]->address);
virBufferEscapeSexpr(buf, "(ip '%s')", ipStr);
VIR_FREE(ipStr);
}
break;
case VIR_DOMAIN_NET_TYPE_VHOSTUSER:
......
......@@ -28,6 +28,8 @@
<interface type='bridge'>
<mac address='00:16:3e:0f:ef:8a'/>
<source bridge='bri0'/>
<ip address='192.168.122.12' family='ipv4' prefix='24'/>
<ip address='192.168.122.13' family='ipv4' prefix='24'/>
<target dev='veth0'/>
<guest dev='eth2'/>
</interface>
......
......@@ -93,7 +93,7 @@ testReadNetworkConf(const void *data ATTRIBUTE_UNUSED)
" <devices>\n"
" <interface type='ethernet'>\n"
" <mac address='00:00:00:00:00:00'/>\n"
" <ip address='194.44.18.88'/>\n"
" <ip address='194.44.18.88' family='ipv4'/>\n"
" </interface>\n"
" <interface type='bridge'>\n"
" <mac address='00:18:51:c1:05:ee'/>\n"
......
......@@ -24,7 +24,7 @@
<interface type='bridge'>
<mac address='00:11:22:33:44:55'/>
<source bridge='xenbr2'/>
<ip address='192.0.2.1'/>
<ip address='192.0.2.1' family='ipv4'/>
<script path='vif-bridge'/>
<target dev='vif6.0'/>
</interface>
......
......@@ -23,7 +23,7 @@
</disk>
<interface type='ethernet'>
<mac address='00:11:22:33:44:55'/>
<ip address='172.14.5.6'/>
<ip address='172.14.5.6' family='ipv4'/>
<script path='vif-routed'/>
<target dev='vif6.0'/>
</interface>
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册