From: Xu Wang <cngesaint(a)gmail.com>
Signed-off-by: Xu Wang <gesaint(a)linux.vnet.ibm.com>
---
libxkutil/device_parsing.c | 301 +++++++++++++++++++++++++++++++--------------
libxkutil/device_parsing.h | 1 +
2 files changed, 211 insertions(+), 91 deletions(-)
diff --git a/libxkutil/device_parsing.c b/libxkutil/device_parsing.c
index 940b105..8b39cda 100644
--- a/libxkutil/device_parsing.c
+++ b/libxkutil/device_parsing.c
@@ -148,6 +148,7 @@ static void cleanup_net_device(struct net_device *dev)
free(dev->poolid);
cleanup_vsi_device(&dev->vsi);
cleanup_device_address(&dev->address);
+ cleanup_others(dev->others);
}
static void cleanup_emu_device(struct emu_device *dev)
@@ -429,30 +430,6 @@ int add_device_address_property(struct device_address *devaddr,
return 0;
}
-
-static int parse_device_address(xmlNode *anode, struct device_address *devaddr)
-{
- xmlAttr *attr = NULL;
- char *name = NULL;
- char *value = NULL;
-
- for (attr = anode->properties; attr != NULL; attr = attr->next) {
- name = (char*) attr->name;
- value = get_attr_value(anode, name);
- if (!add_device_address_property(devaddr, name, value))
- goto err;
- free(value);
- }
-
- return 1;
-
- err:
- cleanup_device_address(devaddr);
- free(value);
-
- return 0;
-}
-
/*
* Device addresses can have many forms based on the 'type' field, so rather
* than try to create a function that could parse each particular option, we
@@ -1222,92 +1199,234 @@ static int parse_net_device(xmlNode *inode, struct virt_device
**vdevs)
{
struct virt_device *vdev = NULL;
struct net_device *ndev = NULL;
- xmlNode *child = NULL;
+
+ CU_DEBUG("Enter parse_net_device().");
vdev = calloc(1, sizeof(*vdev));
- if (vdev == NULL)
+ if (vdev == NULL) {
+ CU_DEBUG("calloc failed.");
goto err;
+ }
ndev = &(vdev->dev.net);
- ndev->type = get_attr_value(inode, "type");
- if (ndev->type == NULL)
+ ndev->others = parse_data_to_others(ndev->others,
+ inode,
+ 0,
+ BAD_CAST "devices");
+ if (ndev->others == NULL) {
+ CU_DEBUG("parse xml data to others failed.");
goto err;
+ }
+
+ /* fetch out <interface> tag from others. It will be removed
+ * after others management finished. */
+ fetch_from_others(&ndev->others,
+ -1,
+ "interface",
+ TYPE_NODE,
+ -1,
+ "devices");
+
+ ndev->type = fetch_from_others(&ndev->others,
+ -1,
+ "type",
+ TYPE_PROP,
+ -1,
+ (char *)inode->name);
+
+ if (ndev->type == NULL) {
+ CU_DEBUG("no type");
+ goto err;
+ }
+
+ if (seek_in_others(&ndev->others,
+ -1,
+ "mac",
+ TYPE_NODE,
+ -1,
+ (char *)inode->name)) {
+ ndev->mac = fetch_from_others(&ndev->others,
+ -1,
+ "address",
+ TYPE_PROP,
+ -1,
+ "mac");
+
+ if (ndev->mac == NULL) {
+ CU_DEBUG("no mac address");
+ goto err;
+ }
+ }
+
+ if (seek_in_others(&ndev->others,
+ -1,
+ "source",
+ TYPE_NODE,
+ -1,
+ (char *)inode->name)) {
+ ndev->source = fetch_from_others(&ndev->others,
+ -1,
+ "bridge",
+ TYPE_PROP,
+ -1,
+ "source");
+
+ if (ndev->source == NULL) {
+ ndev->source = fetch_from_others(&ndev->others,
+ -1,
+ "network",
+ TYPE_PROP,
+ -1,
+ "source");
- for (child = inode->children; child != NULL; child = child->next) {
- if (XSTREQ(child->name, "mac")) {
- ndev->mac = get_attr_value(child, "address");
- if (ndev->mac == NULL)
- goto err;
- } else if (XSTREQ(child->name, "source")) {
- ndev->source = get_attr_value(child, "bridge");
- if (ndev->source != NULL)
- continue;
- ndev->source = get_attr_value(child, "network");
if (ndev->source != NULL) {
- int ret = asprintf(&ndev->poolid,
+ int ret = asprintf(&ndev->poolid,
"NetworkPool/%s",
ndev->source);
+
if (ret == -1) {
- CU_DEBUG("Failed to get network"
- " poolid");
+ CU_DEBUG("Failed to get network
poolid");
+ goto err;
}
- continue;
+ } else {
+ ndev->source =
fetch_from_others(&ndev->others,
+ -1,
+ "dev",
+ TYPE_PROP,
+ -1,
+ "source");
+
+ ndev->net_mode =
fetch_from_others(&ndev->others,
+ -1,
+ "mode",
+ TYPE_PROP,
+ -1,
+ "source");
+
+ if ((ndev->source == NULL) || (ndev->net_mode ==
NULL)) {
+ CU_DEBUG("source %s, mode %s",
ndev->source, ndev->net_mode);
+ goto err;
+ }
+
}
- ndev->source = get_attr_value(child, "dev");
- ndev->net_mode = get_attr_value(child, "mode");
- if ((ndev->source != NULL) && (ndev->net_mode !=
NULL))
- continue;
+ }
+ }
+
+ if (seek_in_others(&ndev->others,
+ -1,
+ "target",
+ TYPE_NODE,
+ -1,
+ (char *)inode->name)) {
+ ndev->device = fetch_from_others(&ndev->others,
+ -1,
+ "dev",
+ TYPE_PROP,
+ -1,
+ "target");
+
+ if (ndev->device == NULL) {
+ CU_DEBUG("no dev in target.");
goto err;
- } else if (XSTREQ(child->name, "target")) {
- ndev->device = get_attr_value(child, "dev");
- if (ndev->device == NULL)
- goto err;
- } else if (XSTREQ(child->name, "model")) {
- ndev->model = get_attr_value(child, "type");
- if (ndev->model == NULL)
- goto err;
- } else if (XSTREQ(child->name, "filterref")) {
- ndev->filter_ref = get_attr_value(child, "filter");
- } else if (XSTREQ(child->name, "virtualport")) {
- parse_vsi_device(child, ndev);
- } else if (XSTREQ(child->name, "address")) {
- parse_device_address(child, &ndev->address);
+ }
+ }
+
+ if (seek_in_others(&ndev->others,
+ -1,
+ "model",
+ TYPE_NODE,
+ -1,
+ (char *)inode->name)) {
+ ndev->model = fetch_from_others(&ndev->others,
+ -1,
+ "type",
+ TYPE_PROP,
+ -1,
+ "model");
+ if (ndev->model == NULL) {
+ CU_DEBUG("no model type.");
+ goto err;
+ }
+ }
+
+ if (seek_in_others(&ndev->others,
+ -1,
+ "filterref",
+ TYPE_NODE,
+ -1,
+ (char *)inode->name)) {
+ ndev->filter_ref = fetch_from_others(&ndev->others,
+ -1,
+ "filter",
+ TYPE_PROP,
+ -1,
+ "filterref");
+ }
+
+ if (seek_in_others(&ndev->others, -1, "virtualport",
+ TYPE_NODE, -1, (char *)inode->name)) {
+ parse_vsi_device(&ndev->others, ndev);
+ }
+
+ if (seek_in_others(&ndev->others,
+ -1,
+ "address",
+ TYPE_NODE,
+ -1,
+ (char *)inode->name)) {
+ if (!fetch_device_address_from_others(&ndev->others,
+ &ndev->address)) {
+ CU_DEBUG("error fetching device address");
+ goto err;
+ }
+ }
+
#if LIBVIR_VERSION_NUMBER >= 9000
- } else if (XSTREQ(child->name, "bandwidth")) {
- /* Network QoS bandwidth support */
- xmlNode *grandchild = NULL;
- for (grandchild = child->children;
- grandchild != NULL;
- grandchild = grandchild->next) {
- if (XSTREQ(grandchild->name, "inbound")) {
- /* Only expose inbound bandwidth */
- char *val;
-
- val = get_attr_value(grandchild,
- "average");
- if (val != NULL) {
- sscanf(val, "%" PRIu64,
- &ndev->reservation);
- free(val);
- } else
- ndev->reservation = 0;
-
- val = get_attr_value(grandchild,
- "peak");
- if (val != NULL) {
- sscanf(val, "%" PRIu64,
- &ndev->limit);
- free(val);
- } else
- ndev->limit = 0;
- break;
- }
- }
+ /* Network QoS bandwidth support */
+ /* Only expose inbound bandwidth */
+ char *val;
+ if (seek_in_others(&ndev->others,
+ -1,
+ "bandwidth",
+ TYPE_NODE,
+ -1,
+ (char *)inode->name) &&
+ seek_in_others(&ndev->others,
+ -1,
+ "inbound",
+ TYPE_NODE,
+ -1,
+ "bandwidth")) {
+ val = fetch_from_others(&ndev->others,
+ -1,
+ "average",
+ TYPE_PROP,
+ -1,
+ "inbound");
+
+ if (val != NULL) {
+ sscanf(val, "%" PRIu64, &ndev->reservation);
+ free(val);
+ } else {
+ ndev->reservation = 0;
}
-#endif
+ val = fetch_from_others(&ndev->others,
+ -1,
+ "peak",
+ TYPE_PROP,
+ -1,
+ "inbound");
+
+ if (val != NULL) {
+ sscanf(val, "%" PRIu64, &ndev->limit);
+ free(val);
+ } else {
+ ndev->limit = 0;
+ }
}
+#endif
if (ndev->source == NULL)
CU_DEBUG("No network source defined, leaving blank\n");
diff --git a/libxkutil/device_parsing.h b/libxkutil/device_parsing.h
index 6e8fe25..4d26fc8 100644
--- a/libxkutil/device_parsing.h
+++ b/libxkutil/device_parsing.h
@@ -100,6 +100,7 @@ struct net_device {
uint64_t limit;
struct vsi_device vsi;
struct device_address address;
+ struct others *others;
};
struct mem_device {
--
1.8.3.1