]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
add support for netcf XML import and export
authorDaniel Veillard <veillard@redhat.com>
Wed, 15 Jul 2009 17:34:04 +0000 (19:34 +0200)
committerDaniel Veillard <veillard@redhat.com>
Wed, 15 Jul 2009 18:16:26 +0000 (20:16 +0200)
* src/interface_conf.c src/interface_conf.h: the import and export
  routines and the internal APIs
* src/Makefile.am: hook the new file in the makefiles
* src/libvirt_private.syms: export a few private symbols internally
* po/POTFILES.in: the new file contains translatable strings

po/POTFILES.in
src/Makefile.am
src/interface_conf.c [new file with mode: 0644]
src/interface_conf.h [new file with mode: 0644]
src/libvirt_private.syms

index 357cd70d3c2c213643d31fb4f8596e1773c0b508..1700ab58acfc9c27c893950914d4eefc20da8626 100644 (file)
@@ -5,6 +5,7 @@ src/conf.c
 src/console.c
 src/datatypes.c
 src/domain_conf.c
+src/interface_conf.c
 src/iptables.c
 src/libvirt.c
 src/lxc_container.c
index 0c284c0e595779722085a3e3801f18b0dc365b6c..889ede4b7dd44043540f25b21265ca091d295b29 100644 (file)
@@ -85,6 +85,9 @@ NETWORK_CONF_SOURCES =                                                \
 STORAGE_CONF_SOURCES =                                         \
                storage_conf.h storage_conf.c
 
+# Interface driver generic impl APIs
+INTERFACE_CONF_SOURCES =                                       \
+               interface_conf.c interface_conf.h
 
 # The remote RPC driver, covering domains, storage, networks, etc
 REMOTE_DRIVER_SOURCES =                                                \
@@ -225,6 +228,7 @@ libvirt_driver_la_SOURCES =                                 \
                $(DOMAIN_CONF_SOURCES)                          \
                $(NETWORK_CONF_SOURCES)                         \
                $(STORAGE_CONF_SOURCES)                         \
+               $(INTERFACE_CONF_SOURCES)                       \
                $(NODE_DEVICE_CONF_SOURCES)
 
 libvirt_driver_la_CFLAGS = $(XEN_CFLAGS) $(NUMACTL_CFLAGS)
diff --git a/src/interface_conf.c b/src/interface_conf.c
new file mode 100644 (file)
index 0000000..0b73c97
--- /dev/null
@@ -0,0 +1,1139 @@
+/*
+ * interface_conf.c: interfaces XML handling
+ *
+ * Copyright (C) 2006-2009 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
+ *
+ * Author: Daniel Veillard <veillard@redhat.com>
+ *         Laine Stump <laine@redhat.com>
+ */
+
+#include <config.h>
+#include "virterror_internal.h"
+#include "datatypes.h"
+
+#include "interface_conf.h"
+
+#include "memory.h"
+#include "xml.h"
+#include "uuid.h"
+#include "util.h"
+#include "buf.h"
+
+#define VIR_FROM_THIS VIR_FROM_INTERFACE
+
+VIR_ENUM_IMPL(virInterface,
+              VIR_INTERFACE_TYPE_LAST,
+              "ethernet", "bridge", "bond", "vlan" )
+
+#define virInterfaceReportError(conn, code, fmt...)                            \
+        virReportErrorHelper(conn, VIR_FROM_INTERFACE, code, __FILE__,       \
+                               __FUNCTION__, __LINE__, fmt)
+
+static
+void virInterfaceBareDefFree(virInterfaceBareDefPtr def) {
+    if (def == NULL)
+        return;
+    VIR_FREE(def->name);
+    VIR_FREE(def->mac_or_tag);
+    VIR_FREE(def->devname);
+    VIR_FREE(def);
+}
+
+void virInterfaceDefFree(virInterfaceDefPtr def)
+{
+    int i;
+
+    if (def == NULL)
+        return;
+
+    VIR_FREE(def->name);
+    VIR_FREE(def->mac);
+
+    switch (def->type) {
+        case VIR_INTERFACE_TYPE_BRIDGE:
+            for (i = 0;i < def->data.bridge.nbItf;i++) {
+                if (def->data.bridge.itf[i] != NULL)
+                    virInterfaceBareDefFree(def->data.bridge.itf[i]);
+                else
+                    break; /* to cope with half parsed data on errors */
+            }
+            VIR_FREE(def->data.bridge.itf);
+            break;
+        case VIR_INTERFACE_TYPE_BOND:
+            VIR_FREE(def->data.bond.target);
+            for (i = 0;i < def->data.bond.nbItf;i++) {
+                if (def->data.bond.itf[i] != NULL)
+                    virInterfaceBareDefFree(def->data.bond.itf[i]);
+                else
+                    break; /* to cope with half parsed data on errors */
+            }
+            VIR_FREE(def->data.bond.itf);
+            break;
+        case VIR_INTERFACE_TYPE_VLAN:
+            VIR_FREE(def->data.vlan.tag);
+            VIR_FREE(def->data.vlan.devname);
+            break;
+    }
+
+    VIR_FREE(def->proto.family);
+    VIR_FREE(def->proto.address);
+    VIR_FREE(def->proto.gateway);
+
+    VIR_FREE(def);
+}
+
+static int
+virInterfaceDefParseBasicAttrs(virConnectPtr conn, virInterfaceDefPtr def,
+                               xmlXPathContextPtr ctxt) {
+    char *tmp;
+    unsigned long mtu;
+    int ret;
+
+    tmp = virXPathString(conn, "string(./@name)", ctxt);
+    if (tmp == NULL) {
+        virInterfaceReportError(conn, VIR_ERR_XML_ERROR,
+                              "%s",  _("interface has no name"));
+        return(-1);
+    }
+    def->name = tmp;
+
+    ret = virXPathULong(conn, "string(./mtu/@size)", ctxt, &mtu);
+    if ((ret == -2) || ((ret == 0) && (mtu > 100000))) {
+        virInterfaceReportError(conn, VIR_ERR_XML_ERROR,
+                         "%s", _("interface mtu value is improper"));
+        return(-1);
+    } else if (ret == 0) {
+        def->mtu = (unsigned int) mtu;
+    }
+    return(0);
+}
+
+static int
+virInterfaceDefParseStartMode(virConnectPtr conn, virInterfaceDefPtr def,
+                              xmlXPathContextPtr ctxt) {
+    char *tmp;
+
+    tmp = virXPathString(conn, "string(./start/@mode)", ctxt);
+    if (tmp == NULL) {
+        virInterfaceReportError(conn, VIR_ERR_XML_ERROR,
+                        "%s", _("interface misses the start mode attribute"));
+        return(-1);
+    }
+    if (STREQ(tmp, "onboot"))
+        def->startmode = VIR_INTERFACE_START_ONBOOT;
+    else if (STREQ(tmp, "hotplug"))
+        def->startmode = VIR_INTERFACE_START_HOTPLUG;
+    else if (STREQ(tmp, "none"))
+        def->startmode = VIR_INTERFACE_START_NONE;
+    else {
+        virInterfaceReportError(conn, VIR_ERR_XML_ERROR,
+                                _("unknown interface startmode %s"), tmp);
+        VIR_FREE(tmp);
+        return(-1);
+    }
+    VIR_FREE(tmp);
+    return(0);
+}
+
+static int
+virInterfaceDefParseBondMode(virConnectPtr conn, xmlXPathContextPtr ctxt) {
+    char *tmp;
+    int ret = 0;
+
+    tmp = virXPathString(conn, "string(./@mode)", ctxt);
+    if (tmp == NULL)
+        return(VIR_INTERFACE_BOND_NONE);
+    if (STREQ(tmp, "balance-rr"))
+        ret = VIR_INTERFACE_BOND_BALRR;
+    else if (STREQ(tmp, "active-backup"))
+        ret = VIR_INTERFACE_BOND_ABACKUP;
+    else if (STREQ(tmp, "balance-xor"))
+        ret = VIR_INTERFACE_BOND_BALXOR;
+    else if (STREQ(tmp, "broadcast"))
+        ret = VIR_INTERFACE_BOND_BCAST;
+    else if (STREQ(tmp, "802.3ad"))
+        ret = VIR_INTERFACE_BOND_8023AD;
+    else if (STREQ(tmp, "balance-tlb"))
+        ret = VIR_INTERFACE_BOND_BALTLB;
+    else if (STREQ(tmp, "balance-alb"))
+        ret = VIR_INTERFACE_BOND_BALALB;
+    else {
+        virInterfaceReportError(conn, VIR_ERR_XML_ERROR,
+                                _("unknown bonding mode %s"), tmp);
+        ret = -1;
+    }
+    VIR_FREE(tmp);
+    return(ret);
+}
+
+static int
+virInterfaceDefParseBondMiiCarrier(virConnectPtr conn, xmlXPathContextPtr ctxt) {
+    char *tmp;
+    int ret = 0;
+
+    tmp = virXPathString(conn, "string(./miimon/@carrier)", ctxt);
+    if (tmp == NULL)
+        return(VIR_INTERFACE_BOND_MII_NONE);
+    if (STREQ(tmp, "ioctl"))
+        ret = VIR_INTERFACE_BOND_MII_IOCTL;
+    else if (STREQ(tmp, "netif"))
+        ret = VIR_INTERFACE_BOND_MII_NETIF;
+    else {
+        virInterfaceReportError(conn, VIR_ERR_XML_ERROR,
+                                _("unknown mii bonding carrier %s"), tmp);
+        ret = -1;
+    }
+    VIR_FREE(tmp);
+    return(ret);
+}
+
+static int
+virInterfaceDefParseBondArpValid(virConnectPtr conn, xmlXPathContextPtr ctxt) {
+    char *tmp;
+    int ret = 0;
+
+    tmp = virXPathString(conn, "string(./arpmon/@validate)", ctxt);
+    if (tmp == NULL)
+        return(VIR_INTERFACE_BOND_ARP_NONE);
+    if (STREQ(tmp, "active"))
+        ret = VIR_INTERFACE_BOND_ARP_ACTIVE;
+    else if (STREQ(tmp, "backup"))
+        ret = VIR_INTERFACE_BOND_ARP_BACKUP;
+    else if (STREQ(tmp, "all"))
+        ret = VIR_INTERFACE_BOND_ARP_ALL;
+    else {
+        virInterfaceReportError(conn, VIR_ERR_XML_ERROR,
+                                _("unknown arp bonding validate %s"), tmp);
+        ret = -1;
+    }
+    VIR_FREE(tmp);
+    return(ret);
+}
+
+static int
+virInterfaceDefParseDhcp(virConnectPtr conn, virInterfaceDefPtr def,
+                         xmlNodePtr dhcp, xmlXPathContextPtr ctxt) {
+    char *tmp;
+    xmlNodePtr old;
+    int ret = 0;
+
+    def->proto.dhcp = 1;
+    old = ctxt->node;
+    ctxt->node = dhcp;
+    /* Not much to do in the current version */
+    tmp = virXPathString(conn, "string(./@peerdns)", ctxt);
+    if (tmp) {
+        if (STREQ(tmp, "yes"))
+            def->proto.peerdns = 1;
+        else if (STREQ(tmp, "no"))
+            def->proto.peerdns = 0;
+        else {
+            virInterfaceReportError(conn, VIR_ERR_XML_ERROR,
+                              _("unknown dhcp peerdns value %s"), tmp);
+            ret = -1;
+        }
+        VIR_FREE(tmp);
+    } else
+        def->proto.peerdns = -1;
+
+    return(ret);
+}
+
+static int
+virInterfaceDefParseIp(virConnectPtr conn, virInterfaceDefPtr def,
+                   xmlNodePtr ip ATTRIBUTE_UNUSED, xmlXPathContextPtr ctxt) {
+    int ret = 0;
+    char *tmp;
+    long l;
+
+    tmp = virXPathString(conn, "string(./ip[1]/@address)", ctxt);
+    def->proto.address = tmp;
+    if (tmp != NULL) {
+        ret = virXPathLong(conn, "string(./ip[1]/@prefix)", ctxt, &l);
+        if (ret == 0)
+            def->proto.prefix = (int) l;
+        else if (ret == -2) {
+            virInterfaceReportError(conn, VIR_ERR_XML_ERROR,
+                              "%s", _("Invalid ip address prefix value"));
+            return(-1);
+        }
+    }
+    tmp = virXPathString(conn, "string(./route[1]/@gateway)", ctxt);
+    def->proto.gateway = tmp;
+
+    return(0);
+}
+
+static int
+virInterfaceDefParseProtoIPv4(virConnectPtr conn, virInterfaceDefPtr def,
+                              xmlXPathContextPtr ctxt) {
+    xmlNodePtr cur;
+    int ret;
+
+    cur = virXPathNode(conn, "./dhcp", ctxt);
+    if (cur != NULL)
+        ret = virInterfaceDefParseDhcp(conn, def, cur, ctxt);
+    else {
+        cur = virXPathNode(conn, "./ip", ctxt);
+        if (cur != NULL)
+            ret = virInterfaceDefParseIp(conn, def, cur, ctxt);
+        else {
+            virInterfaceReportError(conn, VIR_ERR_XML_ERROR,
+                                "%s", _("interface miss dhcp or ip adressing"));
+            ret = -1;
+        }
+    }
+    return(ret);
+}
+
+static int
+virInterfaceDefParseIfAdressing(virConnectPtr conn, virInterfaceDefPtr def,
+                                xmlXPathContextPtr ctxt) {
+    xmlNodePtr cur, save;
+    int ret;
+    char *tmp;
+
+    cur = virXPathNode(conn, "./protocol[1]", ctxt);
+    if (cur == NULL)
+        return(0);
+    save = ctxt->node;
+    ctxt->node = cur;
+    tmp = virXPathString(conn, "string(./@family)", ctxt);
+    if (tmp == NULL) {
+        virInterfaceReportError(conn, VIR_ERR_XML_ERROR,
+                            "%s", _("protocol misses the family attribute"));
+        ret = -1;
+        goto done;
+    }
+    if (STREQ(tmp, "ipv4")) {
+        def->proto.family = tmp;
+        ret = virInterfaceDefParseProtoIPv4(conn, def, ctxt);
+    } else {
+        virInterfaceReportError(conn, VIR_ERR_XML_ERROR,
+                            _("unsupported protocol family '%s'"), tmp);
+        ret = -1;
+        VIR_FREE(tmp);
+    }
+
+done:
+    ctxt->node = save;
+    return(ret);
+
+}
+
+static virInterfaceBareDefPtr
+virInterfaceDefParseBareInterface(virConnectPtr conn, xmlXPathContextPtr ctxt,
+                                  int ethernet_only) {
+    int t;
+    char *name = NULL;
+    char *type = NULL;
+    char *mac_or_tag = NULL;
+    char *devname = NULL;
+    virInterfaceBareDefPtr ret = NULL;
+
+    type = virXPathString(conn, "string(./@type)", ctxt);
+    if (type == NULL) {
+        virInterfaceReportError(conn, VIR_ERR_XML_ERROR,
+                            "%s", _("interface has no type"));
+        goto error;
+    }
+    if (STREQ(type, "ethernet")) {
+        t = VIR_INTERFACE_TYPE_ETHERNET;
+        name = virXPathString(conn, "string(./@name)", ctxt);
+        mac_or_tag = virXPathString(conn, "string(./mac/@address)", ctxt);
+    } else if ((STREQ(type, "vlan")) && (ethernet_only == 0)) {
+        t = VIR_INTERFACE_TYPE_VLAN;
+        name = virXPathString(conn, "string(./@name)", ctxt);
+        mac_or_tag = virXPathString(conn, "string(./vlan/@tag)", ctxt);
+        devname = virXPathString(conn, "string(./vlan/interface/@name)", ctxt);
+    } else {
+        virInterfaceReportError(conn, VIR_ERR_XML_ERROR,
+                            _("interface has unsupported type '%s'"), type);
+        VIR_FREE(type);
+        goto error;
+    }
+    VIR_FREE(type);
+    if (name == NULL) {
+        virInterfaceReportError(conn, VIR_ERR_XML_ERROR,
+                            "%s", _("interface has no name"));
+        goto error;
+    }
+    if (t == VIR_INTERFACE_TYPE_VLAN) {
+        if (mac_or_tag == NULL) {
+            virInterfaceReportError(conn, VIR_ERR_XML_ERROR,
+                                _("vlan %s has no tag"), name);
+            goto error;
+        }
+        if (devname == NULL) {
+            virInterfaceReportError(conn, VIR_ERR_XML_ERROR,
+                                _("vlan %s has interface name"), name);
+            goto error;
+        }
+    }
+    if (VIR_ALLOC(ret) < 0) {
+        virReportOOMError(conn);
+        goto error;
+    }
+    ret->type = t;
+    ret->name = name;
+    ret->mac_or_tag = mac_or_tag;
+    ret->devname = devname;
+    return(ret);
+
+error:
+     VIR_FREE(name);
+     VIR_FREE(type);
+     VIR_FREE(name);
+     VIR_FREE(name);
+     VIR_FREE(ret);
+     return(NULL);
+}
+
+static int
+virInterfaceDefParseBridge(virConnectPtr conn, virInterfaceDefPtr def,
+                           xmlXPathContextPtr ctxt) {
+    xmlNodePtr *interfaces = NULL;
+    xmlNodePtr bridge;
+    virInterfaceBareDefPtr itf;
+    int nbItf, i;
+    int ret = 0;
+
+    bridge = ctxt->node;
+    nbItf = virXPathNodeSet(conn, "./interface", ctxt, &interfaces);
+    if (nbItf <= 0) {
+        virInterfaceReportError(conn, VIR_ERR_XML_ERROR,
+                                "%s", _("bridge has no interfaces"));
+        ret = -1;
+        goto error;
+    }
+    if (VIR_ALLOC_N(def->data.bridge.itf, nbItf) < 0) {
+        virReportOOMError(conn);
+        ret = -1;
+        goto error;
+    }
+    def->data.bridge.nbItf = nbItf;
+
+    for (i = 0; i < nbItf;i++) {
+        ctxt->node = interfaces[i];
+        itf = virInterfaceDefParseBareInterface(conn, ctxt, 0);
+        if (itf == NULL) {
+            ret = -1;
+            def->data.bridge.nbItf = i;
+            goto error;
+        }
+        def->data.bridge.itf[i] = itf;
+    }
+
+error:
+    VIR_FREE(interfaces);
+    ctxt->node = bridge;
+    return(ret);
+}
+
+static int
+virInterfaceDefParseBondItfs(virConnectPtr conn, virInterfaceDefPtr def,
+                             xmlXPathContextPtr ctxt) {
+    xmlNodePtr *interfaces = NULL;
+    xmlNodePtr bond = ctxt->node;
+    virInterfaceBareDefPtr itf;
+    int nbItf, i;
+    int ret = 0;
+
+    nbItf = virXPathNodeSet(conn, "./interface", ctxt, &interfaces);
+    if (nbItf <= 0) {
+        virInterfaceReportError(conn, VIR_ERR_XML_ERROR,
+                                "%s", _("bond has no interfaces"));
+        ret = -1;
+        goto error;
+    }
+    if (VIR_ALLOC_N(def->data.bond.itf, nbItf) < 0) {
+        virReportOOMError(conn);
+        ret = -1;
+        goto error;
+    }
+    def->data.bond.nbItf = nbItf;
+
+    for (i = 0; i < nbItf;i++) {
+        ctxt->node = interfaces[i];
+        itf = virInterfaceDefParseBareInterface(conn, ctxt, 1);
+        if (itf == NULL) {
+            ret = -1;
+            def->data.bond.nbItf = i;
+            goto error;
+        }
+        def->data.bond.itf[i] = itf;
+    }
+
+error:
+    VIR_FREE(interfaces);
+    ctxt->node = bond;
+    return(ret);
+}
+
+static int
+virInterfaceDefParseBond(virConnectPtr conn, virInterfaceDefPtr def,
+                         xmlXPathContextPtr ctxt) {
+    xmlNodePtr node;
+    int ret = 0;
+    unsigned long tmp;
+
+    def->data.bond.mode = virInterfaceDefParseBondMode(conn, ctxt);
+    if (def->data.bond.mode < 0)
+        goto error;
+
+    node = virXPathNode(conn, "./miimon[1]", ctxt);
+    if (node != NULL) {
+        def->data.bond.monit = VIR_INTERFACE_BOND_MONIT_MII;
+
+        ret = virXPathULong(conn, "string(./miimon/@freq)", ctxt, &tmp);
+        if ((ret == -2) || (ret == -1)) {
+            virInterfaceReportError(conn, VIR_ERR_XML_ERROR,
+                     "%s", _("bond interface miimon freq missing or invalid"));
+            goto error;
+        }
+        def->data.bond.frequency = (int) tmp;
+
+        ret = virXPathULong(conn, "string(./miimon/@downdelay)", ctxt, &tmp);
+        if (ret == -2) {
+            virInterfaceReportError(conn, VIR_ERR_XML_ERROR,
+                     "%s", _("bond interface miimon downdelay invalid"));
+            goto error;
+        } else if (ret == 0) {
+            def->data.bond.downdelay = (int) tmp;
+        }
+
+        ret = virXPathULong(conn, "string(./miimon/@updelay)", ctxt, &tmp);
+        if (ret == -2) {
+            virInterfaceReportError(conn, VIR_ERR_XML_ERROR,
+                     "%s", _("bond interface miimon updelay invalid"));
+            goto error;
+        } else if (ret == 0) {
+            def->data.bond.updelay = (int) tmp;
+        }
+
+        def->data.bond.carrier = virInterfaceDefParseBondMiiCarrier(conn, ctxt);
+        if (def->data.bond.carrier < 0)
+            goto error;
+
+        ret = virInterfaceDefParseBondItfs(conn, def, ctxt);
+
+        goto done;
+    }
+    node = virXPathNode(conn, "./arpmon[1]", ctxt);
+    if (node != NULL) {
+        def->data.bond.monit = VIR_INTERFACE_BOND_MONIT_ARP;
+
+        ret = virXPathULong(conn, "string(./arpmon/@interval)", ctxt, &tmp);
+        if ((ret == -2) || (ret == -1)) {
+            virInterfaceReportError(conn, VIR_ERR_XML_ERROR,
+                 "%s", _("bond interface arpmon interval missing or invalid"));
+            goto error;
+        }
+        def->data.bond.interval = (int) tmp;
+
+        def->data.bond.target =
+            virXPathString(conn, "string(./arpmon/@target)", ctxt);
+        if (def->data.bond.target == NULL) {
+            virInterfaceReportError(conn, VIR_ERR_XML_ERROR,
+                 "%s", _("bond interface arpmon target missing"));
+            goto error;
+        }
+
+        def->data.bond.validate = virInterfaceDefParseBondArpValid(conn, ctxt);
+        if (def->data.bond.validate < 0)
+            goto error;
+
+        ret = virInterfaceDefParseBondItfs(conn, def, ctxt);
+
+        goto done;
+    }
+
+    virInterfaceReportError(conn, VIR_ERR_XML_ERROR,
+                "%s", _("bond interface need miimon or arpmon element"));
+error:
+    ret = -1;
+done:
+    return(ret);
+}
+
+static int
+virInterfaceDefParseVlan(virConnectPtr conn, virInterfaceDefPtr def,
+                         xmlXPathContextPtr ctxt) {
+    def->data.vlan.tag = virXPathString(conn, "string(./@tag)", ctxt);
+    if (def->data.vlan.tag == NULL) {
+        virInterfaceReportError(conn, VIR_ERR_XML_ERROR,
+                    "%s", _("vlan interface misses the tag attribute"));
+        return(-1);
+    }
+
+    def->data.vlan.devname =
+         virXPathString(conn, "string(./interface/@name)", ctxt);
+    if (def->data.vlan.devname == NULL) {
+        virInterfaceReportError(conn, VIR_ERR_XML_ERROR,
+                    "%s", _("vlan interface misses name attribute"));
+        return(-1);
+    }
+    return(0);
+}
+
+static virInterfaceDefPtr
+virInterfaceDefParseXML(virConnectPtr conn, xmlXPathContextPtr ctxt) {
+    virInterfaceDefPtr def;
+    int type;
+    char *tmp;
+    xmlNodePtr cur = ctxt->node;
+
+    /* check @type */
+    tmp = virXPathString(conn, "string(./@type)", ctxt);
+    if (tmp == NULL) {
+        virInterfaceReportError(conn, VIR_ERR_XML_ERROR,
+                                _("interface misses the type attribute"));
+        return(NULL);
+    }
+    type = virInterfaceTypeFromString(tmp);
+    if (type == -1) {
+        virInterfaceReportError(conn, VIR_ERR_XML_ERROR,
+                                _("unknown interface type %s"), tmp);
+        VIR_FREE(tmp);
+        return(NULL);
+    }
+    VIR_FREE(tmp);
+
+    if (VIR_ALLOC(def) < 0) {
+        virReportOOMError(conn);
+        return NULL;
+    }
+    def->type = type;
+    switch (type) {
+        case VIR_INTERFACE_TYPE_ETHERNET:
+            if (virInterfaceDefParseBasicAttrs(conn, def, ctxt) < 0)
+                goto error;
+            tmp = virXPathString(conn, "string(./mac/@address)", ctxt);
+            if (tmp != NULL)
+                def->mac = tmp;
+            if (virInterfaceDefParseStartMode(conn, def, ctxt) < 0)
+                goto error;
+            if (virInterfaceDefParseIfAdressing(conn, def, ctxt) < 0)
+                goto error;
+            break;
+        case VIR_INTERFACE_TYPE_BRIDGE: {
+            xmlNodePtr bridge;
+
+            if (virInterfaceDefParseStartMode(conn, def, ctxt) < 0)
+                goto error;
+            if (virInterfaceDefParseBasicAttrs(conn, def, ctxt) < 0)
+                goto error;
+            if (virInterfaceDefParseIfAdressing(conn, def, ctxt) < 0)
+                goto error;
+
+            bridge = virXPathNode(conn, "./bridge[1]", ctxt);
+            if (bridge == NULL) {
+                virInterfaceReportError(conn, VIR_ERR_XML_ERROR,
+                            _("bridge interface misses the bridge element"));
+                goto error;
+            }
+            tmp = virXMLPropString(bridge, "stp");
+            def->data.bridge.stp = -1;
+            if (tmp != NULL) {
+                if (STREQ(tmp, "on")) {
+                    def->data.bridge.stp = 1;
+                } else if (STREQ(tmp, "off")) {
+                    def->data.bridge.stp = 0;
+                } else {
+                    virInterfaceReportError(conn, VIR_ERR_XML_ERROR,
+                          _("bridge interface stp should be on or off got %s"),
+                                            tmp);
+                    VIR_FREE(tmp);
+                    goto error;
+                }
+                VIR_FREE(tmp);
+            }
+            ctxt->node = bridge;
+            virInterfaceDefParseBridge(conn, def, ctxt);
+            break;
+        }
+        case VIR_INTERFACE_TYPE_BOND: {
+            xmlNodePtr bond;
+
+            if (virInterfaceDefParseBasicAttrs(conn, def, ctxt) < 0)
+                goto error;
+            if (virInterfaceDefParseStartMode(conn, def, ctxt) < 0)
+                goto error;
+            if (virInterfaceDefParseIfAdressing(conn, def, ctxt) < 0)
+                goto error;
+            bond = virXPathNode(conn, "./bond[1]", ctxt);
+            if (bond == NULL) {
+                virInterfaceReportError(conn, VIR_ERR_XML_ERROR,
+                            "%s", _("bond interface misses the bond element"));
+                goto error;
+            }
+            ctxt->node = bond;
+            if (virInterfaceDefParseBond(conn, def, ctxt)  < 0)
+                goto error;
+            break;
+        }
+        case VIR_INTERFACE_TYPE_VLAN: {
+            xmlNodePtr vlan;
+
+            tmp = virXPathString(conn, "string(./@name)", ctxt);
+            if (tmp != NULL)
+                def->name = tmp;
+            if (virInterfaceDefParseStartMode(conn, def, ctxt) < 0)
+                goto error;
+            if (virInterfaceDefParseIfAdressing(conn, def, ctxt) < 0)
+                goto error;
+            vlan = virXPathNode(conn, "./vlan[1]", ctxt);
+            if (vlan == NULL) {
+                virInterfaceReportError(conn, VIR_ERR_XML_ERROR,
+                            "%s", _("vlan interface misses the vlan element"));
+                goto error;
+            }
+            ctxt->node = vlan;
+            if (virInterfaceDefParseVlan(conn, def, ctxt)  < 0)
+                goto error;
+            break;
+        }
+
+    }
+
+    ctxt->node = cur;
+    return def;
+
+error:
+    ctxt->node = cur;
+    virInterfaceDefFree(def);
+    return NULL;
+}
+
+virInterfaceDefPtr virInterfaceDefParseNode(virConnectPtr conn,
+                                        xmlDocPtr xml,
+                                        xmlNodePtr root)
+{
+    xmlXPathContextPtr ctxt = NULL;
+    virInterfaceDefPtr def = NULL;
+
+    if (!xmlStrEqual(root->name, BAD_CAST "interface")) {
+        virInterfaceReportError(conn, VIR_ERR_INTERNAL_ERROR,
+                              "%s", _("incorrect root element"));
+        return NULL;
+    }
+
+    ctxt = xmlXPathNewContext(xml);
+    if (ctxt == NULL) {
+        virReportOOMError(conn);
+        goto cleanup;
+    }
+
+    ctxt->node = root;
+    def = virInterfaceDefParseXML(conn, ctxt);
+
+cleanup:
+    xmlXPathFreeContext(ctxt);
+    return def;
+}
+
+/* Called from SAX on parsing errors in the XML. */
+static void
+catchXMLError (void *ctx, const char *msg ATTRIBUTE_UNUSED, ...)
+{
+    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
+
+    if (ctxt) {
+        virConnectPtr conn = ctxt->_private;
+
+        if (conn &&
+            conn->err.code == VIR_ERR_NONE &&
+            ctxt->lastError.level == XML_ERR_FATAL &&
+            ctxt->lastError.message != NULL) {
+            virInterfaceReportError (conn, VIR_ERR_XML_DETAIL,
+                                     _("at line %d: %s"),
+                                     ctxt->lastError.line,
+                                     ctxt->lastError.message);
+        }
+    }
+}
+
+virInterfaceDefPtr virInterfaceDefParseString(virConnectPtr conn,
+                                          const char *xmlStr)
+{
+    xmlParserCtxtPtr pctxt;
+    xmlDocPtr xml = NULL;
+    xmlNodePtr root;
+    virInterfaceDefPtr def = NULL;
+
+    /* Set up a parser context so we can catch the details of XML errors. */
+    pctxt = xmlNewParserCtxt ();
+    if (!pctxt || !pctxt->sax)
+        goto cleanup;
+    pctxt->sax->error = catchXMLError;
+    pctxt->_private = conn;
+
+    if (conn) virResetError (&conn->err);
+    xml = xmlCtxtReadDoc (pctxt, BAD_CAST xmlStr, "interface.xml", NULL,
+                          XML_PARSE_NOENT | XML_PARSE_NONET |
+                          XML_PARSE_NOWARNING);
+    if (!xml) {
+        if (conn && conn->err.code == VIR_ERR_NONE)
+              virInterfaceReportError(conn, VIR_ERR_XML_ERROR,
+                                    "%s", _("failed to parse xml document"));
+        goto cleanup;
+    }
+
+    if ((root = xmlDocGetRootElement(xml)) == NULL) {
+        virInterfaceReportError(conn, VIR_ERR_INTERNAL_ERROR,
+                              "%s", _("missing root element"));
+        goto cleanup;
+    }
+
+    def = virInterfaceDefParseNode(conn, xml, root);
+
+cleanup:
+    xmlFreeParserCtxt (pctxt);
+    xmlFreeDoc (xml);
+    return def;
+}
+
+virInterfaceDefPtr virInterfaceDefParseFile(virConnectPtr conn,
+                                        const char *filename)
+{
+    xmlParserCtxtPtr pctxt;
+    xmlDocPtr xml = NULL;
+    xmlNodePtr root;
+    virInterfaceDefPtr def = NULL;
+
+    /* Set up a parser context so we can catch the details of XML errors. */
+    pctxt = xmlNewParserCtxt ();
+    if (!pctxt || !pctxt->sax)
+        goto cleanup;
+    pctxt->sax->error = catchXMLError;
+    pctxt->_private = conn;
+
+    if (conn) virResetError (&conn->err);
+    xml = xmlCtxtReadFile (pctxt, filename, NULL,
+                           XML_PARSE_NOENT | XML_PARSE_NONET |
+                           XML_PARSE_NOWARNING);
+    if (!xml) {
+        if (conn && conn->err.code == VIR_ERR_NONE)
+              virInterfaceReportError(conn, VIR_ERR_XML_ERROR,
+                                    "%s", _("failed to parse xml document"));
+        goto cleanup;
+    }
+
+    if ((root = xmlDocGetRootElement(xml)) == NULL) {
+        virInterfaceReportError(conn, VIR_ERR_INTERNAL_ERROR,
+                              "%s", _("missing root element"));
+        goto cleanup;
+    }
+
+    def = virInterfaceDefParseNode(conn, xml, root);
+
+cleanup:
+    xmlFreeParserCtxt (pctxt);
+    xmlFreeDoc (xml);
+    return def;
+}
+
+static int
+virInterfaceBareDevDefFormat(virConnectPtr conn ATTRIBUTE_UNUSED,
+                             virBufferPtr buf,
+                             const virInterfaceBareDefPtr def) {
+    if (def->type == VIR_INTERFACE_TYPE_ETHERNET) {
+        if (def->name == NULL) {
+            virInterfaceReportError(conn, VIR_ERR_INTERNAL_ERROR,
+                                    "%s", _("bare ethernet has no name"));
+            return(-1);
+        }
+        virBufferVSprintf(buf, "    <interface type='ethernet' name='%s'",
+                          def->name);
+        if (def->mac_or_tag != NULL) {
+            virBufferVSprintf(buf, ">\n      <mac address='%s'/>\n",
+                              def->mac_or_tag);
+            virBufferAddLit(buf, "    </interface>\n");
+        } else {
+            virBufferAddLit(buf, "/>\n");
+        }
+    } else if (def->type == VIR_INTERFACE_TYPE_VLAN) {
+        virBufferAddLit(buf, "    <interface type='vlan'");
+        if (def->name != NULL)
+            virBufferVSprintf(buf, " name='%s'", def->name);
+        if (def->mac_or_tag != NULL) {
+            virBufferAddLit(buf, ">\n");
+            virBufferVSprintf(buf, "      <vlan tag='%s'", def->mac_or_tag);
+            if (def->devname != NULL) {
+                virBufferAddLit(buf, ">\n");
+                virBufferVSprintf(buf, "        <interface  name='%s'/>\n",
+                                  def->devname);
+                virBufferAddLit(buf, "      </vlan>\n");
+            } else
+                virBufferAddLit(buf, "/>\n");
+            virBufferAddLit(buf, "    </interface>\n");
+        } else {
+            virBufferAddLit(buf, "/>\n");
+        }
+    } else {
+        virInterfaceReportError(conn, VIR_ERR_INTERNAL_ERROR,
+                                _("bare interface type %d unknown"),
+                                def->type);
+        return(-1);
+    }
+    return(0);
+}
+
+static int
+virInterfaceBridgeDefFormat(virConnectPtr conn, virBufferPtr buf,
+                            const virInterfaceDefPtr def) {
+    int i;
+    int ret = 0;
+
+    if (def->data.bridge.stp == 1)
+        virBufferAddLit(buf, "  <bridge stp='on'>\n");
+    else if (def->data.bridge.stp == 0)
+        virBufferAddLit(buf, "  <bridge stp='off'>\n");
+    else
+        virBufferAddLit(buf, "  <bridge>\n");
+
+    for (i = 0;i < def->data.bridge.nbItf;i++) {
+        if (virInterfaceBareDevDefFormat(conn, buf, def->data.bridge.itf[i])
+            < 0)
+            ret = -1;
+    }
+
+    virBufferAddLit(buf, "  </bridge>\n");
+    return(ret);
+}
+
+static int
+virInterfaceBondDefFormat(virConnectPtr conn, virBufferPtr buf,
+                            const virInterfaceDefPtr def) {
+    int i;
+    int ret = 0;
+
+    virBufferAddLit(buf, "  <bond");
+    if (def->data.bond.mode == VIR_INTERFACE_BOND_BALRR)
+        virBufferAddLit(buf, " mode='balance-rr'");
+    else if (def->data.bond.mode == VIR_INTERFACE_BOND_ABACKUP)
+        virBufferAddLit(buf, " mode='active-backup'");
+    else if (def->data.bond.mode == VIR_INTERFACE_BOND_BALXOR)
+        virBufferAddLit(buf, " mode='balance-xor'");
+    else if (def->data.bond.mode == VIR_INTERFACE_BOND_BCAST)
+        virBufferAddLit(buf, " mode='broadcast'");
+    else if (def->data.bond.mode == VIR_INTERFACE_BOND_8023AD)
+        virBufferAddLit(buf, " mode='802.3ad'");
+    else if (def->data.bond.mode == VIR_INTERFACE_BOND_BALTLB)
+        virBufferAddLit(buf, " mode='balance-tlb'");
+    else if (def->data.bond.mode == VIR_INTERFACE_BOND_BALALB)
+        virBufferAddLit(buf, " mode='balance-alb'");
+    virBufferAddLit(buf, ">\n");
+
+    if (def->data.bond.monit == VIR_INTERFACE_BOND_MONIT_MII) {
+        virBufferVSprintf(buf, "    <miimon freq='%d'",
+                          def->data.bond.frequency);
+        if (def->data.bond.downdelay > 0)
+            virBufferVSprintf(buf, " downdelay='%d'", def->data.bond.downdelay);
+        if (def->data.bond.updelay > 0)
+            virBufferVSprintf(buf, " updelay='%d'", def->data.bond.updelay);
+        if (def->data.bond.carrier == VIR_INTERFACE_BOND_MII_IOCTL)
+            virBufferAddLit(buf, " carrier='ioctl'");
+        else if (def->data.bond.carrier == VIR_INTERFACE_BOND_MII_NETIF)
+            virBufferAddLit(buf, " carrier='netif'");
+        virBufferAddLit(buf, "/>\n");
+    } else if (def->data.bond.monit == VIR_INTERFACE_BOND_MONIT_ARP) {
+        if (def->data.bond.target == NULL) {
+            virInterfaceReportError(conn, VIR_ERR_INTERNAL_ERROR,
+                          "%s", _("bond arp monitoring has no target"));
+            return(-1);
+        }
+        virBufferVSprintf(buf, "    <arpmon interval='%d' target='%s'",
+                          def->data.bond.interval, def->data.bond.target);
+        if (def->data.bond.validate == VIR_INTERFACE_BOND_ARP_ACTIVE)
+            virBufferAddLit(buf, " validate='active'");
+        else if (def->data.bond.validate == VIR_INTERFACE_BOND_ARP_BACKUP)
+            virBufferAddLit(buf, " validate='backup'");
+        else if (def->data.bond.validate == VIR_INTERFACE_BOND_ARP_ALL)
+            virBufferAddLit(buf, " validate='all'");
+        virBufferAddLit(buf, "/>\n");
+    } else {
+        virInterfaceReportError(conn, VIR_ERR_INTERNAL_ERROR,
+                                _("bond monitoring type %d unknown"),
+                                def->data.bond.monit);
+        return(-1);
+    }
+    for (i = 0;i < def->data.bond.nbItf;i++) {
+        if (virInterfaceBareDevDefFormat(conn, buf, def->data.bond.itf[i]) < 0)
+            ret = -1;
+    }
+
+    virBufferAddLit(buf, "  </bond>\n");
+    return(ret);
+}
+
+static int
+virInterfaceVlanDefFormat(virConnectPtr conn, virBufferPtr buf,
+                            const virInterfaceDefPtr def) {
+    if (def->data.vlan.tag == NULL) {
+        virInterfaceReportError(conn, VIR_ERR_INTERNAL_ERROR,
+                                "%s", _("vlan misses the tag name"));
+        return(-1);
+    }
+
+    virBufferVSprintf(buf, "  <vlan tag='%s'", def->data.vlan.tag);
+    if (def->data.vlan.devname != NULL) {
+        virBufferAddLit(buf, ">\n");
+        virBufferVSprintf(buf, "    <interface name='%s'/>\n",
+                          def->data.vlan.devname);
+        virBufferAddLit(buf, "  </vlan>\n");
+    } else
+        virBufferAddLit(buf, "/>\n");
+    return(0);
+}
+
+static int
+virInterfaceProtocolDefFormat(virConnectPtr conn ATTRIBUTE_UNUSED,
+                              virBufferPtr buf, const virInterfaceDefPtr def) {
+    if (def->proto.family == NULL)
+        return(0);
+    virBufferVSprintf(buf, "  <protocol family='%s'>\n", def->proto.family);
+    if (def->proto.dhcp) {
+        if (def->proto.peerdns == 0)
+            virBufferAddLit(buf, "    <dhcp peerdns='no'/>\n");
+        else if (def->proto.peerdns == 1)
+            virBufferAddLit(buf, "    <dhcp peerdns='yes'/>\n");
+        else
+            virBufferAddLit(buf, "    <dhcp/>\n");
+    } else {
+        /* theorically if we don't have dhcp we should have an address */
+        if (def->proto.address != NULL) {
+            if (def->proto.prefix != 0)
+                virBufferVSprintf(buf, "    <ip address='%s' prefix='%d'/>\n",
+                                  def->proto.address, def->proto.prefix);
+            else
+                virBufferVSprintf(buf, "    <ip address='%s'/>\n",
+                                  def->proto.address);
+        }
+        if (def->proto.gateway != NULL) {
+            virBufferVSprintf(buf, "    <route gateway='%s'/>\n",
+                              def->proto.gateway);
+        }
+    }
+    virBufferAddLit(buf, "  </protocol>\n");
+    return(0);
+}
+
+static int
+virInterfaceStartmodeDefFormat(virConnectPtr conn, virBufferPtr buf,
+                               enum virInterfaceStartMode startmode) {
+    const char *mode;
+    switch (startmode) {
+        case VIR_INTERFACE_START_NONE:
+            mode = "none";
+            break;
+        case VIR_INTERFACE_START_ONBOOT:
+            mode = "onboot";
+            break;
+        case VIR_INTERFACE_START_HOTPLUG:
+            mode = "hotplug";
+            break;
+        default:
+            virInterfaceReportError(conn, VIR_ERR_INTERNAL_ERROR,
+                        "%s", _("virInterfaceDefFormat unknown startmode"));
+            return -1;
+    }
+    virBufferVSprintf(buf, "  <start mode='%s'/>\n", mode);
+    return(0);
+}
+
+char *virInterfaceDefFormat(virConnectPtr conn,
+                          const virInterfaceDefPtr def)
+{
+    virBuffer buf = VIR_BUFFER_INITIALIZER;
+    const char *type = NULL, *tmp;
+
+    if ((def == NULL) ||
+        ((def->name == NULL) && (def->type != VIR_INTERFACE_TYPE_VLAN))) {
+        virInterfaceReportError(conn, VIR_ERR_INTERNAL_ERROR,
+                        "%s", _("virInterfaceDefFormat argument problems"));
+        goto cleanup;
+    }
+
+    if (!(type = virInterfaceTypeToString(def->type))) {
+        virInterfaceReportError(conn, VIR_ERR_INTERNAL_ERROR,
+                        _("unexpected interface type %d"), def->type);
+        goto cleanup;
+    }
+
+    virBufferVSprintf(&buf, "<interface type='%s' ", type);
+    if (def->name != NULL)
+        virBufferEscapeString(&buf, "name='%s'", def->name);
+    virBufferAddLit(&buf, ">\n");
+
+    switch (def->type) {
+        case VIR_INTERFACE_TYPE_ETHERNET:
+            virInterfaceStartmodeDefFormat(conn, &buf, def->startmode);
+            if (def->mac != NULL)
+                virBufferVSprintf(&buf, "  <mac address='%s'/>\n", def->mac);
+            if (def->mtu != 0)
+                virBufferVSprintf(&buf, "  <mtu size='%d'/>\n", def->mtu);
+            virInterfaceProtocolDefFormat(conn, &buf, def);
+            break;
+        case VIR_INTERFACE_TYPE_BRIDGE:
+            virInterfaceStartmodeDefFormat(conn, &buf, def->startmode);
+            if (def->mtu != 0)
+                virBufferVSprintf(&buf, "  <mtu size='%d'/>\n", def->mtu);
+            virInterfaceProtocolDefFormat(conn, &buf, def);
+            virInterfaceBridgeDefFormat(conn, &buf, def);
+            break;
+        case VIR_INTERFACE_TYPE_BOND:
+            virInterfaceStartmodeDefFormat(conn, &buf, def->startmode);
+            if (def->mtu != 0)
+                virBufferVSprintf(&buf, "  <mtu size='%d'/>\n", def->mtu);
+            virInterfaceProtocolDefFormat(conn, &buf, def);
+            virInterfaceBondDefFormat(conn, &buf, def);
+            break;
+        case VIR_INTERFACE_TYPE_VLAN:
+            virInterfaceStartmodeDefFormat(conn, &buf, def->startmode);
+            if (def->mac != NULL)
+                virBufferVSprintf(&buf, "  <mac address='%s'/>\n", def->mac);
+            if (def->mtu != 0)
+                virBufferVSprintf(&buf, "  <mtu size='%d'/>\n", def->mtu);
+            virInterfaceProtocolDefFormat(conn, &buf, def);
+            virInterfaceVlanDefFormat(conn, &buf, def);
+            break;
+    }
+
+    virBufferAddLit(&buf, "</interface>\n");
+
+    if (virBufferError(&buf))
+        goto no_memory;
+    return virBufferContentAndReset(&buf);
+
+no_memory:
+    virReportOOMError(conn);
+cleanup:
+    tmp = virBufferContentAndReset(&buf);
+    VIR_FREE(tmp);
+    return NULL;
+}
+
+void virInterfaceObjLock(virInterfaceObjPtr obj)
+{
+    virMutexLock(&obj->lock);
+}
+
+void virInterfaceObjUnlock(virInterfaceObjPtr obj)
+{
+    virMutexUnlock(&obj->lock);
+}
diff --git a/src/interface_conf.h b/src/interface_conf.h
new file mode 100644 (file)
index 0000000..c77a230
--- /dev/null
@@ -0,0 +1,203 @@
+/*
+ * interface_conf.h: interface XML handling entry points
+ *
+ * Copyright (C) 2006-2009 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
+ *
+ * Author: Daniel Veillard <veillard@redhat.com>
+ *         Laine Stump <laine@redhat.com>
+ */
+
+#ifndef __INTERFACE_CONF_H__
+#define __INTERFACE_CONF_H__
+
+#include <libxml/parser.h>
+#include <libxml/tree.h>
+#include <libxml/xpath.h>
+
+#include "internal.h"
+#include "util.h"
+#include "threads.h"
+
+/* There is currently 3 types of interfaces */
+
+enum virInterfaceType {
+    VIR_INTERFACE_TYPE_ETHERNET,  /* simple ethernet */
+    VIR_INTERFACE_TYPE_BRIDGE,    /* bridge interface */
+    VIR_INTERFACE_TYPE_BOND,      /* bonding interface */
+    VIR_INTERFACE_TYPE_VLAN,      /* vlan description */
+
+    VIR_INTERFACE_TYPE_LAST,
+};
+
+VIR_ENUM_DECL(virInterface)
+
+/* types of start mode */
+
+enum virInterfaceStartMode {
+    VIR_INTERFACE_START_NONE = 0, /* not defined */
+    VIR_INTERFACE_START_ONBOOT,   /* startup at boot */
+    VIR_INTERFACE_START_HOTPLUG,  /* on hotplug */
+};
+
+enum virInterfaceBondMode {
+    VIR_INTERFACE_BOND_NONE = 0,
+    VIR_INTERFACE_BOND_BALRR,     /* balance-rr */
+    VIR_INTERFACE_BOND_ABACKUP,   /* active backup */
+    VIR_INTERFACE_BOND_BALXOR,    /* balance-xor */
+    VIR_INTERFACE_BOND_BCAST,     /* broadcast */
+    VIR_INTERFACE_BOND_8023AD,    /* 802.3ad */
+    VIR_INTERFACE_BOND_BALTLB,    /* balance-tlb */
+    VIR_INTERFACE_BOND_BALALB,    /* balance-alb */
+};
+
+enum virInterfaceBondMonit {
+    VIR_INTERFACE_BOND_MONIT_NONE = 0,
+    VIR_INTERFACE_BOND_MONIT_MII, /* mii based monitoring */
+    VIR_INTERFACE_BOND_MONIT_ARP, /* arp based monitoring */
+};
+
+enum virInterfaceBondMiiCarrier {
+    VIR_INTERFACE_BOND_MII_NONE = 0,
+    VIR_INTERFACE_BOND_MII_IOCTL, /* mii/ethtool ioctl */
+    VIR_INTERFACE_BOND_MII_NETIF, /* netif_carrier_ok */
+};
+
+enum virInterfaceBondArpValid {
+    VIR_INTERFACE_BOND_ARP_NONE = 0,
+    VIR_INTERFACE_BOND_ARP_ACTIVE, /* validate active */
+    VIR_INTERFACE_BOND_ARP_BACKUP, /* validate backup */
+    VIR_INTERFACE_BOND_ARP_ALL,    /* validate all */
+};
+
+typedef struct _virInterfaceBareDef virInterfaceBareDef;
+typedef virInterfaceBareDef *virInterfaceBareDefPtr;
+struct _virInterfaceBareDef {
+    int type;                /* should be only ethernet or vlan */
+    char *name;              /* the interface name */
+    char *mac_or_tag;        /* MAC address for ethernet, TAG for vlan */
+    char *devname;           /* device name for vlan */
+};
+
+typedef struct _virInterfaceBridgeDef virInterfaceBridgeDef;
+typedef virInterfaceBridgeDef *virInterfaceBridgeDefPtr;
+struct _virInterfaceBridgeDef {
+    int stp;         /* 0, 1 or -1 if undefined */
+    int nbItf;       /* number of defined interfaces */
+    virInterfaceBareDefPtr *itf;/* interfaces */
+};
+
+typedef struct _virInterfaceBondDef virInterfaceBondDef;
+typedef virInterfaceBondDef *virInterfaceBondDefPtr;
+struct _virInterfaceBondDef {
+    int mode;                    /* virInterfaceBondMode */
+    int monit;                   /* virInterfaceBondMonit */
+    int frequency;               /* miimon frequency in ms */
+    int downdelay;               /* miimon downdelay */
+    int updelay;                 /* miimon updelay */
+    int carrier;                 /* virInterfaceBondMiiCarrier */
+    int interval;                /* arp monitoring interval */
+    char *target;                /* arp monitoring target */
+    int validate;                /* virInterfaceBondArpmValid */
+    int nbItf;                   /* number of defined interfaces */
+    virInterfaceBareDefPtr *itf; /* interfaces ethernet only */
+};
+
+typedef struct _virInterfaceVlanDef virInterfaceVlanDef;
+typedef virInterfaceVlanDef *virInterfaceVlanDefPtr;
+struct _virInterfaceVlanDef {
+    char *tag;       /* TAG for vlan */
+    char *devname;   /* device name for vlan */
+};
+
+typedef struct _virInterfaceProtocolDef virInterfaceProtocolDef;
+typedef virInterfaceProtocolDef *virInterfaceProtocolDefPtr;
+struct _virInterfaceProtocolDef {
+    char *family;    /* ipv4 only right now */
+    int dhcp;        /* use dhcp */
+    int peerdns;     /* dhcp peerdns ? */
+    char *address;   /* ip address */
+    int prefix;      /* ip prefix */
+    char *gateway;   /* route gateway */
+};
+
+
+typedef struct _virInterfaceDef virInterfaceDef;
+typedef virInterfaceDef *virInterfaceDefPtr;
+struct _virInterfaceDef {
+    int type;                /* interface type */
+    char *name;              /* interface name */
+    unsigned int mtu;        /* maximum transmit size in byte */
+    char *mac;               /* MAC address */
+
+    enum virInterfaceStartMode startmode; /* how it is started */
+
+    union {
+        virInterfaceBridgeDef bridge;
+        virInterfaceVlanDef vlan;
+        virInterfaceBondDef bond;
+    } data;
+
+    /* separated as we may allow multiple of those in the future */
+    virInterfaceProtocolDef proto;
+};
+
+typedef struct _virInterfaceObj virInterfaceObj;
+typedef virInterfaceObj *virInterfaceObjPtr;
+struct _virInterfaceObj {
+    virMutex lock;
+
+    virInterfaceDefPtr def; /* The interface definition */
+};
+
+typedef struct _virInterfaceObjList virInterfaceObjList;
+typedef virInterfaceObjList *virInterfaceObjListPtr;
+struct _virInterfaceObjList {
+    unsigned int count;
+    virInterfaceObjPtr *objs;
+};
+
+virInterfaceObjPtr virInterfaceFindByMACString(const virInterfaceObjListPtr interfaces,
+                                               const char *mac);
+virInterfaceObjPtr virInterfaceFindByName(const virInterfaceObjListPtr interfaces,
+                                          const char *name);
+
+
+void virInterfaceDefFree(virInterfaceDefPtr def);
+void virInterfaceObjFree(virInterfaceObjPtr interface);
+void virInterfaceObjListFree(virInterfaceObjListPtr vms);
+
+virInterfaceObjPtr virInterfaceAssignDef(virConnectPtr conn,
+                                         virInterfaceObjListPtr interfaces,
+                                         const virInterfaceDefPtr def);
+void virInterfaceRemove(virInterfaceObjListPtr interfaces,
+                        const virInterfaceObjPtr interface);
+
+virInterfaceDefPtr virInterfaceDefParseString(virConnectPtr conn,
+                                              const char *xmlStr);
+virInterfaceDefPtr virInterfaceDefParseFile(virConnectPtr conn,
+                                            const char *filename);
+virInterfaceDefPtr virInterfaceDefParseNode(virConnectPtr conn,
+                                            xmlDocPtr xml,
+                                            xmlNodePtr root);
+
+char *virInterfaceDefFormat(virConnectPtr conn,
+                            const virInterfaceDefPtr def);
+
+void virInterfaceObjLock(virInterfaceObjPtr obj);
+void virInterfaceObjUnlock(virInterfaceObjPtr obj);
+
+#endif /* __INTERFACE_CONF_H__ */
index d43620fca6c368bb3e86fcb2aa81ad8f3a6f6cf3..0534d53a48ed60f0bd439c3f6b7d9781444aee8e 100644 (file)
@@ -155,6 +155,13 @@ virHashSearch;
 virHashSize;
 
 
+# interface_conf.h
+virInterfaceDefFormat;
+virInterfaceDefParseFile;
+virInterfaceDefParseString;
+virInterfaceDefFree;
+
+
 # iptables.h
 iptablesAddForwardAllowCross;
 iptablesAddForwardAllowIn;