diff --git a/docs/schemas/basictypes.rng b/docs/schemas/basictypes.rng
index 34ef6137d9..5fe3a97dae 100644
--- a/docs/schemas/basictypes.rng
+++ b/docs/schemas/basictypes.rng
@@ -397,4 +397,29 @@
+
+
+
+
+
+
+
+
+
+
+
+ unknown
+ notpresent
+ down
+ lowerlayerdown
+ testing
+ dormant
+ up
+
+
+
+
+
+
+
diff --git a/docs/schemas/interface.rng b/docs/schemas/interface.rng
index 3984b630a2..8e2218d1d7 100644
--- a/docs/schemas/interface.rng
+++ b/docs/schemas/interface.rng
@@ -41,6 +41,7 @@
+
diff --git a/src/conf/device_conf.c b/src/conf/device_conf.c
index 317fdf2a58..6412d24d53 100644
--- a/src/conf/device_conf.c
+++ b/src/conf/device_conf.c
@@ -38,6 +38,13 @@ VIR_ENUM_IMPL(virDeviceAddressPCIMulti,
"on",
"off")
+VIR_ENUM_IMPL(virInterfaceState,
+ VIR_INTERFACE_STATE_LAST,
+ "" /* value of zero means no state */,
+ "unknown", "notpresent",
+ "down", "lowerlayerdown",
+ "testing", "dormant", "up")
+
int virDevicePCIAddressIsValid(virDevicePCIAddressPtr addr)
{
/* PCI bus has 32 slots and 8 functions per slot */
@@ -142,3 +149,58 @@ virDevicePCIAddressEqual(virDevicePCIAddress *addr1,
}
return false;
}
+
+int
+virInterfaceLinkParseXML(xmlNodePtr node,
+ virInterfaceLinkPtr lnk)
+{
+ int ret = -1;
+ char *stateStr, *speedStr;
+ int state;
+
+ stateStr = virXMLPropString(node, "state");
+ speedStr = virXMLPropString(node, "speed");
+
+ if (stateStr) {
+ if ((state = virInterfaceStateTypeFromString(stateStr)) < 0) {
+ virReportError(VIR_ERR_XML_ERROR,
+ _("unknown link state: %s"),
+ stateStr);
+ goto cleanup;
+ }
+ lnk->state = state;
+ }
+
+ if (speedStr &&
+ virStrToLong_ui(speedStr, NULL, 10, &lnk->speed) < 0) {
+ virReportError(VIR_ERR_XML_ERROR,
+ _("Unable to parse link speed: %s"),
+ speedStr);
+ goto cleanup;
+ }
+
+ ret = 0;
+ cleanup:
+ VIR_FREE(stateStr);
+ VIR_FREE(speedStr);
+ return ret;
+}
+
+int
+virInterfaceLinkFormat(virBufferPtr buf,
+ const virInterfaceLink *lnk)
+{
+ if (!lnk->speed && !lnk->state) {
+ /* If there's nothing to format, return early. */
+ return 0;
+ }
+
+ virBufferAddLit(buf, "speed)
+ virBufferAsprintf(buf, " speed='%u'", lnk->speed);
+ if (lnk->state)
+ virBufferAsprintf(buf, " state='%s'",
+ virInterfaceStateTypeToString(lnk->state));
+ virBufferAddLit(buf, "/>\n");
+ return 0;
+}
diff --git a/src/conf/device_conf.h b/src/conf/device_conf.h
index d66afd2d69..0c65a5a587 100644
--- a/src/conf/device_conf.h
+++ b/src/conf/device_conf.h
@@ -40,6 +40,21 @@ typedef enum {
VIR_DEVICE_ADDRESS_PCI_MULTI_LAST
} virDeviceAddressPCIMulti;
+VIR_ENUM_DECL(virDeviceAddressPCIMulti)
+
+typedef enum {
+ VIR_INTERFACE_STATE_UNKNOWN = 1,
+ VIR_INTERFACE_STATE_NOT_PRESENT,
+ VIR_INTERFACE_STATE_DOWN,
+ VIR_INTERFACE_STATE_LOWER_LAYER_DOWN,
+ VIR_INTERFACE_STATE_TESTING,
+ VIR_INTERFACE_STATE_DORMANT,
+ VIR_INTERFACE_STATE_UP,
+ VIR_INTERFACE_STATE_LAST
+} virInterfaceState;
+
+VIR_ENUM_DECL(virInterfaceState)
+
typedef struct _virDevicePCIAddress virDevicePCIAddress;
typedef virDevicePCIAddress *virDevicePCIAddressPtr;
struct _virDevicePCIAddress {
@@ -50,6 +65,13 @@ struct _virDevicePCIAddress {
int multi; /* enum virDomainDeviceAddressPCIMulti */
};
+typedef struct _virInterfaceLink virInterfaceLink;
+typedef virInterfaceLink *virInterfaceLinkPtr;
+struct _virInterfaceLink {
+ virInterfaceState state; /* link state */
+ unsigned int speed; /* link speed in Mbits per second */
+};
+
int virDevicePCIAddressIsValid(virDevicePCIAddressPtr addr);
int virDevicePCIAddressParseXML(xmlNodePtr node,
@@ -62,7 +84,10 @@ int virDevicePCIAddressFormat(virBufferPtr buf,
bool virDevicePCIAddressEqual(virDevicePCIAddress *addr1,
virDevicePCIAddress *addr2);
+int virInterfaceLinkParseXML(xmlNodePtr node,
+ virInterfaceLinkPtr lnk);
-VIR_ENUM_DECL(virDeviceAddressPCIMulti)
+int virInterfaceLinkFormat(virBufferPtr buf,
+ const virInterfaceLink *lnk);
#endif /* __DEVICE_CONF_H__ */
diff --git a/src/conf/interface_conf.c b/src/conf/interface_conf.c
index 1f67446eae..2b3f69928e 100644
--- a/src/conf/interface_conf.c
+++ b/src/conf/interface_conf.c
@@ -705,12 +705,19 @@ virInterfaceDefParseXML(xmlXPathContextPtr ctxt, int parentIfType)
}
def->type = type;
switch (type) {
- case VIR_INTERFACE_TYPE_ETHERNET:
+ case VIR_INTERFACE_TYPE_ETHERNET: {
+ xmlNodePtr lnk;
+
if (virInterfaceDefParseName(def, ctxt) < 0)
goto error;
tmp = virXPathString("string(./mac/@address)", ctxt);
if (tmp != NULL)
def->mac = tmp;
+
+ lnk = virXPathNode("./link", ctxt);
+ if (lnk && virInterfaceLinkParseXML(lnk, &def->lnk) < 0)
+ goto error;
+
if (parentIfType == VIR_INTERFACE_TYPE_LAST) {
/* only recognize these in toplevel bond interfaces */
if (virInterfaceDefParseStartMode(def, ctxt) < 0)
@@ -721,6 +728,7 @@ virInterfaceDefParseXML(xmlXPathContextPtr ctxt, int parentIfType)
goto error;
}
break;
+ }
case VIR_INTERFACE_TYPE_BRIDGE: {
xmlNodePtr bridge;
@@ -1088,6 +1096,7 @@ virInterfaceDefDevFormat(virBufferPtr buf, const virInterfaceDef *def)
virInterfaceStartmodeDefFormat(buf, def->startmode);
if (def->mac != NULL)
virBufferAsprintf(buf, "\n", def->mac);
+ virInterfaceLinkFormat(buf, &def->lnk);
if (def->mtu != 0)
virBufferAsprintf(buf, "\n", def->mtu);
virInterfaceProtocolDefFormat(buf, def);
diff --git a/src/conf/interface_conf.h b/src/conf/interface_conf.h
index b3c92b2021..94c18ef022 100644
--- a/src/conf/interface_conf.h
+++ b/src/conf/interface_conf.h
@@ -31,6 +31,7 @@
# include "internal.h"
# include "virutil.h"
# include "virthread.h"
+# include "device_conf.h"
/* There is currently 3 types of interfaces */
@@ -146,6 +147,7 @@ struct _virInterfaceDef {
char *name; /* interface name */
unsigned int mtu; /* maximum transmit size in byte */
char *mac; /* MAC address */
+ virInterfaceLink lnk; /* interface link info */
virInterfaceStartMode startmode; /* how it is started */
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index d1d6ff3f99..7a740abfb1 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -83,6 +83,10 @@ virDevicePCIAddressEqual;
virDevicePCIAddressFormat;
virDevicePCIAddressIsValid;
virDevicePCIAddressParseXML;
+virInterfaceLinkFormat;
+virInterfaceLinkParseXML;
+virInterfaceStateTypeFromString;
+virInterfaceStateTypeToString;
# conf/domain_addr.h
diff --git a/tests/interfaceschemadata/bridge-no-address.xml b/tests/interfaceschemadata/bridge-no-address.xml
index 77575349fd..68b8c94bf1 100644
--- a/tests/interfaceschemadata/bridge-no-address.xml
+++ b/tests/interfaceschemadata/bridge-no-address.xml
@@ -4,6 +4,7 @@
+
diff --git a/tests/interfaceschemadata/bridge.xml b/tests/interfaceschemadata/bridge.xml
index 2535edf94e..c865116548 100644
--- a/tests/interfaceschemadata/bridge.xml
+++ b/tests/interfaceschemadata/bridge.xml
@@ -7,6 +7,7 @@
+
diff --git a/tests/interfaceschemadata/ethernet-dhcp.xml b/tests/interfaceschemadata/ethernet-dhcp.xml
index fe969dfd6c..c124372ff1 100644
--- a/tests/interfaceschemadata/ethernet-dhcp.xml
+++ b/tests/interfaceschemadata/ethernet-dhcp.xml
@@ -1,6 +1,7 @@
+