[libvirt] [PATCH 3/5] Implement RPC part of interface config API.

Laine Stump laine at laine.org
Tue May 19 16:51:25 UTC 2009


---
 qemud/remote.c                     |  235 ++++++++++++++++++++++++
 qemud/remote_dispatch_args.h       |    8 +
 qemud/remote_dispatch_prototypes.h |   63 +++++++
 qemud/remote_dispatch_ret.h        |    6 +
 qemud/remote_dispatch_table.h      |   45 +++++
 qemud/remote_protocol.c            |  147 +++++++++++++++
 qemud/remote_protocol.h            |  123 +++++++++++++
 qemud/remote_protocol.x            |   86 +++++++++-
 src/datatypes.c                    |  160 ++++++++++++++++
 src/datatypes.h                    |    6 +
 src/libvirt.c                      |   10 -
 src/remote_internal.c              |  352 ++++++++++++++++++++++++++++++++++++
 12 files changed, 1230 insertions(+), 11 deletions(-)

diff --git a/qemud/remote.c b/qemud/remote.c
index a92dea9..4881fc2 100644
--- a/qemud/remote.c
+++ b/qemud/remote.c
@@ -60,10 +60,12 @@ static void remoteDispatchFormatError (remote_error *rerr,
     ATTRIBUTE_FORMAT(printf, 2, 3);
 static virDomainPtr get_nonnull_domain (virConnectPtr conn, remote_nonnull_domain domain);
 static virNetworkPtr get_nonnull_network (virConnectPtr conn, remote_nonnull_network network);
+static virInterfacePtr get_nonnull_interface (virConnectPtr conn, remote_nonnull_interface interface);
 static virStoragePoolPtr get_nonnull_storage_pool (virConnectPtr conn, remote_nonnull_storage_pool pool);
 static virStorageVolPtr get_nonnull_storage_vol (virConnectPtr conn, remote_nonnull_storage_vol vol);
 static void make_nonnull_domain (remote_nonnull_domain *dom_dst, virDomainPtr dom_src);
 static void make_nonnull_network (remote_nonnull_network *net_dst, virNetworkPtr net_src);
+static void make_nonnull_interface (remote_nonnull_interface *interface_dst, virInterfacePtr interface_src);
 static void make_nonnull_storage_pool (remote_nonnull_storage_pool *pool_dst, virStoragePoolPtr pool_src);
 static void make_nonnull_storage_vol (remote_nonnull_storage_vol *vol_dst, virStorageVolPtr vol_src);
 static void make_nonnull_node_device (remote_nonnull_node_device *dev_dst, virNodeDevicePtr dev_src);
@@ -2559,6 +2561,225 @@ remoteDispatchNumOfNetworks (struct qemud_server *server ATTRIBUTE_UNUSED,
 }
 
 
+/*-------------------------------------------------------------*/
+static int
+remoteDispatchNumOfInterfaces (struct qemud_server *server ATTRIBUTE_UNUSED,
+                               struct qemud_client *client ATTRIBUTE_UNUSED,
+                               virConnectPtr conn,
+                               remote_error *rerr,
+                               void *args ATTRIBUTE_UNUSED,
+                               remote_num_of_interfaces_ret *ret)
+{
+
+    ret->num = virConnectNumOfInterfaces (conn);
+    if (ret->num == -1) {
+        remoteDispatchConnError(rerr, conn);
+        return -1;
+    }
+
+    return 0;
+}
+
+static int
+remoteDispatchListInterfaces (struct qemud_server *server ATTRIBUTE_UNUSED,
+                              struct qemud_client *client ATTRIBUTE_UNUSED,
+                              virConnectPtr conn,
+                              remote_error *rerr,
+                              remote_list_interfaces_args *args,
+                              remote_list_interfaces_ret *ret)
+{
+
+    if (args->maxnames > REMOTE_INTERFACE_NAME_LIST_MAX) {
+        remoteDispatchFormatError (rerr,
+                                   "%s", _("maxnames > REMOTE_INTERFACE_NAME_LIST_MAX"));
+        return -1;
+    }
+
+    /* Allocate return buffer. */
+    if (VIR_ALLOC_N(ret->names.names_val, args->maxnames) < 0) {
+        remoteDispatchOOMError(rerr);
+        return -1;
+    }
+
+    ret->names.names_len =
+        virConnectListInterfaces (conn,
+                                  ret->names.names_val, args->maxnames);
+    if (ret->names.names_len == -1) {
+        VIR_FREE(ret->names.names_len);
+        remoteDispatchConnError(rerr, conn);
+        return -1;
+    }
+
+    return 0;
+}
+
+static int
+remoteDispatchInterfaceLookupByName (struct qemud_server *server ATTRIBUTE_UNUSED,
+                                     struct qemud_client *client ATTRIBUTE_UNUSED,
+                                     virConnectPtr conn,
+                                     remote_error *rerr,
+                                     remote_interface_lookup_by_name_args *args,
+                                     remote_interface_lookup_by_name_ret *ret)
+{
+    virInterfacePtr interface;
+
+    interface = virInterfaceLookupByName (conn, args->name);
+    if (interface == NULL) {
+        remoteDispatchConnError(rerr, conn);
+        return -1;
+    }
+
+    make_nonnull_interface (&ret->interface, interface);
+    virInterfaceFree(interface);
+    return 0;
+}
+
+static int
+remoteDispatchInterfaceLookupByMacString (struct qemud_server *server ATTRIBUTE_UNUSED,
+                                          struct qemud_client *client ATTRIBUTE_UNUSED,
+                                          virConnectPtr conn,
+                                          remote_error *rerr,
+                                          remote_interface_lookup_by_mac_string_args *args,
+                                          remote_interface_lookup_by_mac_string_ret *ret)
+{
+    virInterfacePtr interface;
+
+    interface = virInterfaceLookupByMACString (conn, args->mac);
+    if (interface == NULL) {
+        remoteDispatchConnError(rerr, conn);
+        return -1;
+    }
+
+    make_nonnull_interface (&ret->interface, interface);
+    virInterfaceFree(interface);
+    return 0;
+}
+
+static int
+remoteDispatchInterfaceGetXmlDesc (struct qemud_server *server ATTRIBUTE_UNUSED,
+                                   struct qemud_client *client ATTRIBUTE_UNUSED,
+                                   virConnectPtr conn,
+                                   remote_error *rerr,
+                                   remote_interface_get_xml_desc_args *args,
+                                   remote_interface_get_xml_desc_ret *ret)
+{
+    virInterfacePtr interface;
+
+    interface = get_nonnull_interface (conn, args->interface);
+    if (interface == NULL) {
+        remoteDispatchConnError(rerr, conn);
+        return -1;
+    }
+
+    /* remoteDispatchClientRequest will free this. */
+    ret->xml = virInterfaceGetXMLDesc (interface, args->flags);
+    if (!ret->xml) {
+        virInterfaceFree(interface);
+        remoteDispatchConnError(rerr, conn);
+        return -1;
+    }
+    virInterfaceFree(interface);
+    return 0;
+}
+
+static int
+remoteDispatchInterfaceDefineXml (struct qemud_server *server ATTRIBUTE_UNUSED,
+                                  struct qemud_client *client ATTRIBUTE_UNUSED,
+                                  virConnectPtr conn,
+                                  remote_error *rerr,
+                                  remote_interface_define_xml_args *args,
+                                  remote_interface_define_xml_ret *ret)
+{
+    virInterfacePtr interface;
+
+    interface = virInterfaceDefineXML (conn, args->xml, args->flags);
+    if (interface == NULL) {
+        remoteDispatchConnError(rerr, conn);
+        return -1;
+    }
+
+    make_nonnull_interface (&ret->interface, interface);
+    virInterfaceFree(interface);
+    return 0;
+}
+
+static int
+remoteDispatchInterfaceUndefine (struct qemud_server *server ATTRIBUTE_UNUSED,
+                               struct qemud_client *client ATTRIBUTE_UNUSED,
+                               virConnectPtr conn,
+                               remote_error *rerr,
+                               remote_interface_undefine_args *args,
+                               void *ret ATTRIBUTE_UNUSED)
+{
+    virInterfacePtr interface;
+
+    interface = get_nonnull_interface (conn, args->interface);
+    if (interface == NULL) {
+        remoteDispatchConnError(rerr, conn);
+        return -1;
+    }
+
+    if (virInterfaceUndefine (interface) == -1) {
+        virInterfaceFree(interface);
+        remoteDispatchConnError(rerr, conn);
+        return -1;
+    }
+    virInterfaceFree(interface);
+    return 0;
+}
+
+static int
+remoteDispatchInterfaceCreate (struct qemud_server *server ATTRIBUTE_UNUSED,
+                             struct qemud_client *client ATTRIBUTE_UNUSED,
+                             virConnectPtr conn,
+                             remote_error *rerr,
+                             remote_interface_create_args *args,
+                             void *ret ATTRIBUTE_UNUSED)
+{
+    virInterfacePtr interface;
+
+    interface = get_nonnull_interface (conn, args->interface);
+    if (interface == NULL) {
+        remoteDispatchConnError(rerr, conn);
+        return -1;
+    }
+
+    if (virInterfaceCreate (interface, args->flags) == -1) {
+        virInterfaceFree(interface);
+        remoteDispatchConnError(rerr, conn);
+        return -1;
+    }
+    virInterfaceFree(interface);
+    return 0;
+}
+
+static int
+remoteDispatchInterfaceDestroy (struct qemud_server *server ATTRIBUTE_UNUSED,
+                              struct qemud_client *client ATTRIBUTE_UNUSED,
+                              virConnectPtr conn,
+                              remote_error *rerr,
+                              remote_interface_destroy_args *args,
+                              void *ret ATTRIBUTE_UNUSED)
+{
+    virInterfacePtr interface;
+
+    interface = get_nonnull_interface (conn, args->interface);
+    if (interface == NULL) {
+        remoteDispatchConnError(rerr, conn);
+        return -1;
+    }
+
+    if (virInterfaceDestroy (interface, args->flags) == -1) {
+        virInterfaceFree(interface);
+        remoteDispatchConnError(rerr, conn);
+        return -1;
+    }
+    virInterfaceFree(interface);
+    return 0;
+}
+
+/*-------------------------------------------------------------*/
+
 static int
 remoteDispatchAuthList (struct qemud_server *server,
                         struct qemud_client *client,
@@ -4561,6 +4782,12 @@ get_nonnull_network (virConnectPtr conn, remote_nonnull_network network)
     return virGetNetwork (conn, network.name, BAD_CAST network.uuid);
 }
 
+static virInterfacePtr
+get_nonnull_interface (virConnectPtr conn, remote_nonnull_interface interface)
+{
+    return virGetInterface (conn, interface.name, interface.mac);
+}
+
 static virStoragePoolPtr
 get_nonnull_storage_pool (virConnectPtr conn, remote_nonnull_storage_pool pool)
 {
@@ -4592,6 +4819,14 @@ make_nonnull_network (remote_nonnull_network *net_dst, virNetworkPtr net_src)
 }
 
 static void
+make_nonnull_interface (remote_nonnull_interface *interface_dst,
+                        virInterfacePtr interface_src)
+{
+    interface_dst->name = strdup (interface_src->name);
+    interface_dst->mac = strdup (interface_src->mac);
+}
+
+static void
 make_nonnull_storage_pool (remote_nonnull_storage_pool *pool_dst, virStoragePoolPtr pool_src)
 {
     pool_dst->name = strdup (pool_src->name);
diff --git a/qemud/remote_dispatch_args.h b/qemud/remote_dispatch_args.h
index 8f8b05b..27b840f 100644
--- a/qemud/remote_dispatch_args.h
+++ b/qemud/remote_dispatch_args.h
@@ -106,3 +106,11 @@
     remote_node_device_create_xml_args val_remote_node_device_create_xml_args;
     remote_node_device_destroy_args val_remote_node_device_destroy_args;
     remote_storage_vol_create_xml_from_args val_remote_storage_vol_create_xml_from_args;
+    remote_list_interfaces_args val_remote_list_interfaces_args;
+    remote_interface_lookup_by_name_args val_remote_interface_lookup_by_name_args;
+    remote_interface_lookup_by_mac_string_args val_remote_interface_lookup_by_mac_string_args;
+    remote_interface_get_xml_desc_args val_remote_interface_get_xml_desc_args;
+    remote_interface_define_xml_args val_remote_interface_define_xml_args;
+    remote_interface_undefine_args val_remote_interface_undefine_args;
+    remote_interface_create_args val_remote_interface_create_args;
+    remote_interface_destroy_args val_remote_interface_destroy_args;
diff --git a/qemud/remote_dispatch_prototypes.h b/qemud/remote_dispatch_prototypes.h
index 1a2d98b..9918aee 100644
--- a/qemud/remote_dispatch_prototypes.h
+++ b/qemud/remote_dispatch_prototypes.h
@@ -408,6 +408,55 @@ static int remoteDispatchGetVersion(
     remote_error *err,
     void *args,
     remote_get_version_ret *ret);
+static int remoteDispatchInterfaceCreate(
+    struct qemud_server *server,
+    struct qemud_client *client,
+    virConnectPtr conn,
+    remote_error *err,
+    remote_interface_create_args *args,
+    void *ret);
+static int remoteDispatchInterfaceDefineXml(
+    struct qemud_server *server,
+    struct qemud_client *client,
+    virConnectPtr conn,
+    remote_error *err,
+    remote_interface_define_xml_args *args,
+    remote_interface_define_xml_ret *ret);
+static int remoteDispatchInterfaceDestroy(
+    struct qemud_server *server,
+    struct qemud_client *client,
+    virConnectPtr conn,
+    remote_error *err,
+    remote_interface_destroy_args *args,
+    void *ret);
+static int remoteDispatchInterfaceGetXmlDesc(
+    struct qemud_server *server,
+    struct qemud_client *client,
+    virConnectPtr conn,
+    remote_error *err,
+    remote_interface_get_xml_desc_args *args,
+    remote_interface_get_xml_desc_ret *ret);
+static int remoteDispatchInterfaceLookupByMacString(
+    struct qemud_server *server,
+    struct qemud_client *client,
+    virConnectPtr conn,
+    remote_error *err,
+    remote_interface_lookup_by_mac_string_args *args,
+    remote_interface_lookup_by_mac_string_ret *ret);
+static int remoteDispatchInterfaceLookupByName(
+    struct qemud_server *server,
+    struct qemud_client *client,
+    virConnectPtr conn,
+    remote_error *err,
+    remote_interface_lookup_by_name_args *args,
+    remote_interface_lookup_by_name_ret *ret);
+static int remoteDispatchInterfaceUndefine(
+    struct qemud_server *server,
+    struct qemud_client *client,
+    virConnectPtr conn,
+    remote_error *err,
+    remote_interface_undefine_args *args,
+    void *ret);
 static int remoteDispatchListDefinedDomains(
     struct qemud_server *server,
     struct qemud_client *client,
@@ -436,6 +485,13 @@ static int remoteDispatchListDomains(
     remote_error *err,
     remote_list_domains_args *args,
     remote_list_domains_ret *ret);
+static int remoteDispatchListInterfaces(
+    struct qemud_server *server,
+    struct qemud_client *client,
+    virConnectPtr conn,
+    remote_error *err,
+    remote_list_interfaces_args *args,
+    remote_list_interfaces_ret *ret);
 static int remoteDispatchListNetworks(
     struct qemud_server *server,
     struct qemud_client *client,
@@ -667,6 +723,13 @@ static int remoteDispatchNumOfDomains(
     remote_error *err,
     void *args,
     remote_num_of_domains_ret *ret);
+static int remoteDispatchNumOfInterfaces(
+    struct qemud_server *server,
+    struct qemud_client *client,
+    virConnectPtr conn,
+    remote_error *err,
+    void *args,
+    remote_num_of_interfaces_ret *ret);
 static int remoteDispatchNumOfNetworks(
     struct qemud_server *server,
     struct qemud_client *client,
diff --git a/qemud/remote_dispatch_ret.h b/qemud/remote_dispatch_ret.h
index 75e2ca6..4502182 100644
--- a/qemud/remote_dispatch_ret.h
+++ b/qemud/remote_dispatch_ret.h
@@ -90,3 +90,9 @@
     remote_node_get_security_model_ret val_remote_node_get_security_model_ret;
     remote_node_device_create_xml_ret val_remote_node_device_create_xml_ret;
     remote_storage_vol_create_xml_from_ret val_remote_storage_vol_create_xml_from_ret;
+    remote_num_of_interfaces_ret val_remote_num_of_interfaces_ret;
+    remote_list_interfaces_ret val_remote_list_interfaces_ret;
+    remote_interface_lookup_by_name_ret val_remote_interface_lookup_by_name_ret;
+    remote_interface_lookup_by_mac_string_ret val_remote_interface_lookup_by_mac_string_ret;
+    remote_interface_get_xml_desc_ret val_remote_interface_get_xml_desc_ret;
+    remote_interface_define_xml_ret val_remote_interface_define_xml_ret;
diff --git a/qemud/remote_dispatch_table.h b/qemud/remote_dispatch_table.h
index e601a6c..92e0d40 100644
--- a/qemud/remote_dispatch_table.h
+++ b/qemud/remote_dispatch_table.h
@@ -632,3 +632,48 @@
     .args_filter = (xdrproc_t) xdr_remote_storage_vol_create_xml_from_args,
     .ret_filter = (xdrproc_t) xdr_remote_storage_vol_create_xml_from_ret,
 },
+{   /* NumOfInterfaces => 126 */
+    .fn = (dispatch_fn) remoteDispatchNumOfInterfaces,
+    .args_filter = (xdrproc_t) xdr_void,
+    .ret_filter = (xdrproc_t) xdr_remote_num_of_interfaces_ret,
+},
+{   /* ListInterfaces => 127 */
+    .fn = (dispatch_fn) remoteDispatchListInterfaces,
+    .args_filter = (xdrproc_t) xdr_remote_list_interfaces_args,
+    .ret_filter = (xdrproc_t) xdr_remote_list_interfaces_ret,
+},
+{   /* InterfaceLookupByName => 128 */
+    .fn = (dispatch_fn) remoteDispatchInterfaceLookupByName,
+    .args_filter = (xdrproc_t) xdr_remote_interface_lookup_by_name_args,
+    .ret_filter = (xdrproc_t) xdr_remote_interface_lookup_by_name_ret,
+},
+{   /* InterfaceLookupByMacString => 129 */
+    .fn = (dispatch_fn) remoteDispatchInterfaceLookupByMacString,
+    .args_filter = (xdrproc_t) xdr_remote_interface_lookup_by_mac_string_args,
+    .ret_filter = (xdrproc_t) xdr_remote_interface_lookup_by_mac_string_ret,
+},
+{   /* InterfaceGetXmlDesc => 130 */
+    .fn = (dispatch_fn) remoteDispatchInterfaceGetXmlDesc,
+    .args_filter = (xdrproc_t) xdr_remote_interface_get_xml_desc_args,
+    .ret_filter = (xdrproc_t) xdr_remote_interface_get_xml_desc_ret,
+},
+{   /* InterfaceDefineXml => 131 */
+    .fn = (dispatch_fn) remoteDispatchInterfaceDefineXml,
+    .args_filter = (xdrproc_t) xdr_remote_interface_define_xml_args,
+    .ret_filter = (xdrproc_t) xdr_remote_interface_define_xml_ret,
+},
+{   /* InterfaceUndefine => 132 */
+    .fn = (dispatch_fn) remoteDispatchInterfaceUndefine,
+    .args_filter = (xdrproc_t) xdr_remote_interface_undefine_args,
+    .ret_filter = (xdrproc_t) xdr_void,
+},
+{   /* InterfaceCreate => 133 */
+    .fn = (dispatch_fn) remoteDispatchInterfaceCreate,
+    .args_filter = (xdrproc_t) xdr_remote_interface_create_args,
+    .ret_filter = (xdrproc_t) xdr_void,
+},
+{   /* InterfaceDestroy => 134 */
+    .fn = (dispatch_fn) remoteDispatchInterfaceDestroy,
+    .args_filter = (xdrproc_t) xdr_remote_interface_destroy_args,
+    .ret_filter = (xdrproc_t) xdr_void,
+},
diff --git a/qemud/remote_protocol.c b/qemud/remote_protocol.c
index e9b84aa..a15db31 100644
--- a/qemud/remote_protocol.c
+++ b/qemud/remote_protocol.c
@@ -60,6 +60,17 @@ xdr_remote_nonnull_network (XDR *xdrs, remote_nonnull_network *objp)
 }
 
 bool_t
+xdr_remote_nonnull_interface (XDR *xdrs, remote_nonnull_interface *objp)
+{
+
+         if (!xdr_remote_nonnull_string (xdrs, &objp->name))
+                 return FALSE;
+         if (!xdr_remote_nonnull_string (xdrs, &objp->mac))
+                 return FALSE;
+        return TRUE;
+}
+
+bool_t
 xdr_remote_nonnull_storage_pool (XDR *xdrs, remote_nonnull_storage_pool *objp)
 {
 
@@ -1478,6 +1489,142 @@ xdr_remote_network_set_autostart_args (XDR *xdrs, remote_network_set_autostart_a
 }
 
 bool_t
+xdr_remote_num_of_interfaces_ret (XDR *xdrs, remote_num_of_interfaces_ret *objp)
+{
+
+         if (!xdr_int (xdrs, &objp->num))
+                 return FALSE;
+        return TRUE;
+}
+
+bool_t
+xdr_remote_list_interfaces_args (XDR *xdrs, remote_list_interfaces_args *objp)
+{
+
+         if (!xdr_int (xdrs, &objp->maxnames))
+                 return FALSE;
+        return TRUE;
+}
+
+bool_t
+xdr_remote_list_interfaces_ret (XDR *xdrs, remote_list_interfaces_ret *objp)
+{
+        char **objp_cpp0 = (char **) (void *) &objp->names.names_val;
+
+         if (!xdr_array (xdrs, objp_cpp0, (u_int *) &objp->names.names_len, REMOTE_INTERFACE_NAME_LIST_MAX,
+                sizeof (remote_nonnull_string), (xdrproc_t) xdr_remote_nonnull_string))
+                 return FALSE;
+        return TRUE;
+}
+
+bool_t
+xdr_remote_interface_lookup_by_name_args (XDR *xdrs, remote_interface_lookup_by_name_args *objp)
+{
+
+         if (!xdr_remote_nonnull_string (xdrs, &objp->name))
+                 return FALSE;
+        return TRUE;
+}
+
+bool_t
+xdr_remote_interface_lookup_by_name_ret (XDR *xdrs, remote_interface_lookup_by_name_ret *objp)
+{
+
+         if (!xdr_remote_nonnull_interface (xdrs, &objp->interface))
+                 return FALSE;
+        return TRUE;
+}
+
+bool_t
+xdr_remote_interface_lookup_by_mac_string_args (XDR *xdrs, remote_interface_lookup_by_mac_string_args *objp)
+{
+
+         if (!xdr_remote_nonnull_string (xdrs, &objp->mac))
+                 return FALSE;
+        return TRUE;
+}
+
+bool_t
+xdr_remote_interface_lookup_by_mac_string_ret (XDR *xdrs, remote_interface_lookup_by_mac_string_ret *objp)
+{
+
+         if (!xdr_remote_nonnull_interface (xdrs, &objp->interface))
+                 return FALSE;
+        return TRUE;
+}
+
+bool_t
+xdr_remote_interface_get_xml_desc_args (XDR *xdrs, remote_interface_get_xml_desc_args *objp)
+{
+
+         if (!xdr_remote_nonnull_interface (xdrs, &objp->interface))
+                 return FALSE;
+         if (!xdr_u_int (xdrs, &objp->flags))
+                 return FALSE;
+        return TRUE;
+}
+
+bool_t
+xdr_remote_interface_get_xml_desc_ret (XDR *xdrs, remote_interface_get_xml_desc_ret *objp)
+{
+
+         if (!xdr_remote_nonnull_string (xdrs, &objp->xml))
+                 return FALSE;
+        return TRUE;
+}
+
+bool_t
+xdr_remote_interface_define_xml_args (XDR *xdrs, remote_interface_define_xml_args *objp)
+{
+
+         if (!xdr_remote_nonnull_string (xdrs, &objp->xml))
+                 return FALSE;
+         if (!xdr_u_int (xdrs, &objp->flags))
+                 return FALSE;
+        return TRUE;
+}
+
+bool_t
+xdr_remote_interface_define_xml_ret (XDR *xdrs, remote_interface_define_xml_ret *objp)
+{
+
+         if (!xdr_remote_nonnull_interface (xdrs, &objp->interface))
+                 return FALSE;
+        return TRUE;
+}
+
+bool_t
+xdr_remote_interface_undefine_args (XDR *xdrs, remote_interface_undefine_args *objp)
+{
+
+         if (!xdr_remote_nonnull_interface (xdrs, &objp->interface))
+                 return FALSE;
+        return TRUE;
+}
+
+bool_t
+xdr_remote_interface_create_args (XDR *xdrs, remote_interface_create_args *objp)
+{
+
+         if (!xdr_remote_nonnull_interface (xdrs, &objp->interface))
+                 return FALSE;
+         if (!xdr_u_int (xdrs, &objp->flags))
+                 return FALSE;
+        return TRUE;
+}
+
+bool_t
+xdr_remote_interface_destroy_args (XDR *xdrs, remote_interface_destroy_args *objp)
+{
+
+         if (!xdr_remote_nonnull_interface (xdrs, &objp->interface))
+                 return FALSE;
+         if (!xdr_u_int (xdrs, &objp->flags))
+                 return FALSE;
+        return TRUE;
+}
+
+bool_t
 xdr_remote_auth_list_ret (XDR *xdrs, remote_auth_list_ret *objp)
 {
         char **objp_cpp0 = (char **) (void *) &objp->types.types_val;
diff --git a/qemud/remote_protocol.h b/qemud/remote_protocol.h
index 9ee17a9..280cba6 100644
--- a/qemud/remote_protocol.h
+++ b/qemud/remote_protocol.h
@@ -28,6 +28,7 @@ typedef remote_nonnull_string *remote_string;
 #define REMOTE_CPUMAPS_MAX 16384
 #define REMOTE_MIGRATE_COOKIE_MAX 256
 #define REMOTE_NETWORK_NAME_LIST_MAX 256
+#define REMOTE_INTERFACE_NAME_LIST_MAX 256
 #define REMOTE_STORAGE_POOL_NAME_LIST_MAX 256
 #define REMOTE_STORAGE_VOL_NAME_LIST_MAX 1024
 #define REMOTE_NODE_DEVICE_NAME_LIST_MAX 16384
@@ -57,6 +58,12 @@ struct remote_nonnull_network {
 };
 typedef struct remote_nonnull_network remote_nonnull_network;
 
+struct remote_nonnull_interface {
+        remote_nonnull_string name;
+        remote_nonnull_string mac;
+};
+typedef struct remote_nonnull_interface remote_nonnull_interface;
+
 struct remote_nonnull_storage_pool {
         remote_nonnull_string name;
         remote_uuid uuid;
@@ -822,6 +829,83 @@ struct remote_network_set_autostart_args {
 };
 typedef struct remote_network_set_autostart_args remote_network_set_autostart_args;
 
+struct remote_num_of_interfaces_ret {
+        int num;
+};
+typedef struct remote_num_of_interfaces_ret remote_num_of_interfaces_ret;
+
+struct remote_list_interfaces_args {
+        int maxnames;
+};
+typedef struct remote_list_interfaces_args remote_list_interfaces_args;
+
+struct remote_list_interfaces_ret {
+        struct {
+                u_int names_len;
+                remote_nonnull_string *names_val;
+        } names;
+};
+typedef struct remote_list_interfaces_ret remote_list_interfaces_ret;
+
+struct remote_interface_lookup_by_name_args {
+        remote_nonnull_string name;
+};
+typedef struct remote_interface_lookup_by_name_args remote_interface_lookup_by_name_args;
+
+struct remote_interface_lookup_by_name_ret {
+        remote_nonnull_interface interface;
+};
+typedef struct remote_interface_lookup_by_name_ret remote_interface_lookup_by_name_ret;
+
+struct remote_interface_lookup_by_mac_string_args {
+        remote_nonnull_string mac;
+};
+typedef struct remote_interface_lookup_by_mac_string_args remote_interface_lookup_by_mac_string_args;
+
+struct remote_interface_lookup_by_mac_string_ret {
+        remote_nonnull_interface interface;
+};
+typedef struct remote_interface_lookup_by_mac_string_ret remote_interface_lookup_by_mac_string_ret;
+
+struct remote_interface_get_xml_desc_args {
+        remote_nonnull_interface interface;
+        u_int flags;
+};
+typedef struct remote_interface_get_xml_desc_args remote_interface_get_xml_desc_args;
+
+struct remote_interface_get_xml_desc_ret {
+        remote_nonnull_string xml;
+};
+typedef struct remote_interface_get_xml_desc_ret remote_interface_get_xml_desc_ret;
+
+struct remote_interface_define_xml_args {
+        remote_nonnull_string xml;
+        u_int flags;
+};
+typedef struct remote_interface_define_xml_args remote_interface_define_xml_args;
+
+struct remote_interface_define_xml_ret {
+        remote_nonnull_interface interface;
+};
+typedef struct remote_interface_define_xml_ret remote_interface_define_xml_ret;
+
+struct remote_interface_undefine_args {
+        remote_nonnull_interface interface;
+};
+typedef struct remote_interface_undefine_args remote_interface_undefine_args;
+
+struct remote_interface_create_args {
+        remote_nonnull_interface interface;
+        u_int flags;
+};
+typedef struct remote_interface_create_args remote_interface_create_args;
+
+struct remote_interface_destroy_args {
+        remote_nonnull_interface interface;
+        u_int flags;
+};
+typedef struct remote_interface_destroy_args remote_interface_destroy_args;
+
 struct remote_auth_list_ret {
         struct {
                 u_int types_len;
@@ -1429,6 +1513,15 @@ enum remote_procedure {
         REMOTE_PROC_NODE_DEVICE_CREATE_XML = 123,
         REMOTE_PROC_NODE_DEVICE_DESTROY = 124,
         REMOTE_PROC_STORAGE_VOL_CREATE_XML_FROM = 125,
+        REMOTE_PROC_NUM_OF_INTERFACES = 126,
+        REMOTE_PROC_LIST_INTERFACES = 127,
+        REMOTE_PROC_INTERFACE_LOOKUP_BY_NAME = 128,
+        REMOTE_PROC_INTERFACE_LOOKUP_BY_MAC_STRING = 129,
+        REMOTE_PROC_INTERFACE_GET_XML_DESC = 130,
+        REMOTE_PROC_INTERFACE_DEFINE_XML = 131,
+        REMOTE_PROC_INTERFACE_UNDEFINE = 132,
+        REMOTE_PROC_INTERFACE_CREATE = 133,
+        REMOTE_PROC_INTERFACE_DESTROY = 134,
 };
 typedef enum remote_procedure remote_procedure;
 
@@ -1464,6 +1557,7 @@ extern  bool_t xdr_remote_string (XDR *, remote_string*);
 extern  bool_t xdr_remote_uuid (XDR *, remote_uuid);
 extern  bool_t xdr_remote_nonnull_domain (XDR *, remote_nonnull_domain*);
 extern  bool_t xdr_remote_nonnull_network (XDR *, remote_nonnull_network*);
+extern  bool_t xdr_remote_nonnull_interface (XDR *, remote_nonnull_interface*);
 extern  bool_t xdr_remote_nonnull_storage_pool (XDR *, remote_nonnull_storage_pool*);
 extern  bool_t xdr_remote_nonnull_storage_vol (XDR *, remote_nonnull_storage_vol*);
 extern  bool_t xdr_remote_nonnull_node_device (XDR *, remote_nonnull_node_device*);
@@ -1587,6 +1681,20 @@ extern  bool_t xdr_remote_network_get_bridge_name_ret (XDR *, remote_network_get
 extern  bool_t xdr_remote_network_get_autostart_args (XDR *, remote_network_get_autostart_args*);
 extern  bool_t xdr_remote_network_get_autostart_ret (XDR *, remote_network_get_autostart_ret*);
 extern  bool_t xdr_remote_network_set_autostart_args (XDR *, remote_network_set_autostart_args*);
+extern  bool_t xdr_remote_num_of_interfaces_ret (XDR *, remote_num_of_interfaces_ret*);
+extern  bool_t xdr_remote_list_interfaces_args (XDR *, remote_list_interfaces_args*);
+extern  bool_t xdr_remote_list_interfaces_ret (XDR *, remote_list_interfaces_ret*);
+extern  bool_t xdr_remote_interface_lookup_by_name_args (XDR *, remote_interface_lookup_by_name_args*);
+extern  bool_t xdr_remote_interface_lookup_by_name_ret (XDR *, remote_interface_lookup_by_name_ret*);
+extern  bool_t xdr_remote_interface_lookup_by_mac_string_args (XDR *, remote_interface_lookup_by_mac_string_args*);
+extern  bool_t xdr_remote_interface_lookup_by_mac_string_ret (XDR *, remote_interface_lookup_by_mac_string_ret*);
+extern  bool_t xdr_remote_interface_get_xml_desc_args (XDR *, remote_interface_get_xml_desc_args*);
+extern  bool_t xdr_remote_interface_get_xml_desc_ret (XDR *, remote_interface_get_xml_desc_ret*);
+extern  bool_t xdr_remote_interface_define_xml_args (XDR *, remote_interface_define_xml_args*);
+extern  bool_t xdr_remote_interface_define_xml_ret (XDR *, remote_interface_define_xml_ret*);
+extern  bool_t xdr_remote_interface_undefine_args (XDR *, remote_interface_undefine_args*);
+extern  bool_t xdr_remote_interface_create_args (XDR *, remote_interface_create_args*);
+extern  bool_t xdr_remote_interface_destroy_args (XDR *, remote_interface_destroy_args*);
 extern  bool_t xdr_remote_auth_list_ret (XDR *, remote_auth_list_ret*);
 extern  bool_t xdr_remote_auth_sasl_init_ret (XDR *, remote_auth_sasl_init_ret*);
 extern  bool_t xdr_remote_auth_sasl_start_args (XDR *, remote_auth_sasl_start_args*);
@@ -1680,6 +1788,7 @@ extern bool_t xdr_remote_string ();
 extern bool_t xdr_remote_uuid ();
 extern bool_t xdr_remote_nonnull_domain ();
 extern bool_t xdr_remote_nonnull_network ();
+extern bool_t xdr_remote_nonnull_interface ();
 extern bool_t xdr_remote_nonnull_storage_pool ();
 extern bool_t xdr_remote_nonnull_storage_vol ();
 extern bool_t xdr_remote_nonnull_node_device ();
@@ -1803,6 +1912,20 @@ extern bool_t xdr_remote_network_get_bridge_name_ret ();
 extern bool_t xdr_remote_network_get_autostart_args ();
 extern bool_t xdr_remote_network_get_autostart_ret ();
 extern bool_t xdr_remote_network_set_autostart_args ();
+extern bool_t xdr_remote_num_of_interfaces_ret ();
+extern bool_t xdr_remote_list_interfaces_args ();
+extern bool_t xdr_remote_list_interfaces_ret ();
+extern bool_t xdr_remote_interface_lookup_by_name_args ();
+extern bool_t xdr_remote_interface_lookup_by_name_ret ();
+extern bool_t xdr_remote_interface_lookup_by_mac_string_args ();
+extern bool_t xdr_remote_interface_lookup_by_mac_string_ret ();
+extern bool_t xdr_remote_interface_get_xml_desc_args ();
+extern bool_t xdr_remote_interface_get_xml_desc_ret ();
+extern bool_t xdr_remote_interface_define_xml_args ();
+extern bool_t xdr_remote_interface_define_xml_ret ();
+extern bool_t xdr_remote_interface_undefine_args ();
+extern bool_t xdr_remote_interface_create_args ();
+extern bool_t xdr_remote_interface_destroy_args ();
 extern bool_t xdr_remote_auth_list_ret ();
 extern bool_t xdr_remote_auth_sasl_init_ret ();
 extern bool_t xdr_remote_auth_sasl_start_args ();
diff --git a/qemud/remote_protocol.x b/qemud/remote_protocol.x
index 1f27350..0bd7e6f 100644
--- a/qemud/remote_protocol.x
+++ b/qemud/remote_protocol.x
@@ -79,6 +79,9 @@ const REMOTE_MIGRATE_COOKIE_MAX = 256;
 /* Upper limit on lists of network names. */
 const REMOTE_NETWORK_NAME_LIST_MAX = 256;
 
+/* Upper limit on lists of interface names. */
+const REMOTE_INTERFACE_NAME_LIST_MAX = 256;
+
 /* Upper limit on lists of storage pool names. */
 const REMOTE_STORAGE_POOL_NAME_LIST_MAX = 256;
 
@@ -146,6 +149,12 @@ struct remote_nonnull_network {
     remote_uuid uuid;
 };
 
+/* An interface which may not be NULL. */
+struct remote_nonnull_interface {
+    remote_nonnull_string name;
+    remote_nonnull_string mac;
+};
+
 /* A storage pool which may not be NULL. */
 struct remote_nonnull_storage_pool {
     remote_nonnull_string name;
@@ -770,6 +779,71 @@ struct remote_network_set_autostart_args {
 };
 
 
+/* Interface calls: */
+
+struct remote_num_of_interfaces_ret {
+    int num;
+};
+
+struct remote_list_interfaces_args {
+    int maxnames;
+};
+
+struct remote_list_interfaces_ret {
+    remote_nonnull_string names<REMOTE_INTERFACE_NAME_LIST_MAX>;
+};
+
+struct remote_interface_lookup_by_name_args {
+    remote_nonnull_string name;
+};
+
+struct remote_interface_lookup_by_name_ret {
+    remote_nonnull_interface interface;
+};
+
+struct remote_interface_lookup_by_mac_string_args {
+    remote_nonnull_string mac;
+};
+
+struct remote_interface_lookup_by_mac_string_ret {
+    remote_nonnull_interface interface;
+};
+
+struct remote_interface_get_xml_desc_args {
+    remote_nonnull_interface interface;
+    unsigned int flags;
+};
+
+struct remote_interface_get_xml_desc_ret {
+    remote_nonnull_string xml;
+};
+
+struct remote_interface_define_xml_args {
+    remote_nonnull_string xml;
+    unsigned int flags;
+};
+
+struct remote_interface_define_xml_ret {
+    remote_nonnull_interface interface;
+};
+
+struct remote_interface_undefine_args {
+    remote_nonnull_interface interface;
+};
+
+struct remote_interface_create_args {
+    remote_nonnull_interface interface;
+    unsigned int flags;
+};
+
+struct remote_interface_destroy_args {
+    remote_nonnull_interface interface;
+    unsigned int flags;
+};
+
+
+/* Auth calls: */
+
 struct remote_auth_list_ret {
     remote_auth_type types<REMOTE_AUTH_TYPE_LIST_MAX>;
 };
@@ -1299,7 +1373,17 @@ enum remote_procedure {
     REMOTE_PROC_NODE_DEVICE_CREATE_XML = 123,
     REMOTE_PROC_NODE_DEVICE_DESTROY = 124,
 
-    REMOTE_PROC_STORAGE_VOL_CREATE_XML_FROM = 125
+    REMOTE_PROC_STORAGE_VOL_CREATE_XML_FROM = 125,
+
+    REMOTE_PROC_NUM_OF_INTERFACES = 126,
+    REMOTE_PROC_LIST_INTERFACES = 127,
+    REMOTE_PROC_INTERFACE_LOOKUP_BY_NAME = 128,
+    REMOTE_PROC_INTERFACE_LOOKUP_BY_MAC_STRING = 129,
+    REMOTE_PROC_INTERFACE_GET_XML_DESC = 130,
+    REMOTE_PROC_INTERFACE_DEFINE_XML = 131,
+    REMOTE_PROC_INTERFACE_UNDEFINE = 132,
+    REMOTE_PROC_INTERFACE_CREATE = 133,
+    REMOTE_PROC_INTERFACE_DESTROY = 134
 };
 
 /* Custom RPC structure. */
diff --git a/src/datatypes.c b/src/datatypes.c
index eceb839..e1227aa 100644
--- a/src/datatypes.c
+++ b/src/datatypes.c
@@ -67,6 +67,20 @@ virNetworkFreeName(virNetworkPtr network, const char *name ATTRIBUTE_UNUSED)
 }
 
 /**
+ * virInterfaceFreeName:
+ * @interface: a interface object
+ *
+ * Destroy the interface object, this is just used by the interface hash callback.
+ *
+ * Returns 0 in case of success and -1 in case of failure.
+ */
+static int
+virInterfaceFreeName(virInterfacePtr interface, const char *name ATTRIBUTE_UNUSED)
+{
+    return (virUnrefInterface(interface));
+}
+
+/**
  * virStoragePoolFreeName:
  * @pool: a pool object
  *
@@ -119,12 +133,16 @@ virGetConnect(void) {
     ret->networkDriver = NULL;
     ret->privateData = NULL;
     ret->networkPrivateData = NULL;
+    ret->interfacePrivateData = NULL;
     ret->domains = virHashCreate(20);
     if (ret->domains == NULL)
         goto failed;
     ret->networks = virHashCreate(20);
     if (ret->networks == NULL)
         goto failed;
+    ret->interfaces = virHashCreate(20);
+    if (ret->interfaces == NULL)
+        goto failed;
     ret->storagePools = virHashCreate(20);
     if (ret->storagePools == NULL)
         goto failed;
@@ -144,6 +162,8 @@ failed:
             virHashFree(ret->domains, (virHashDeallocator) virDomainFreeName);
         if (ret->networks != NULL)
             virHashFree(ret->networks, (virHashDeallocator) virNetworkFreeName);
+        if (ret->interfaces != NULL)
+           virHashFree(ret->interfaces, (virHashDeallocator) virInterfaceFreeName);
         if (ret->storagePools != NULL)
             virHashFree(ret->storagePools, (virHashDeallocator) virStoragePoolFreeName);
         if (ret->storageVols != NULL)
@@ -173,6 +193,8 @@ virReleaseConnect(virConnectPtr conn) {
         virHashFree(conn->domains, (virHashDeallocator) virDomainFreeName);
     if (conn->networks != NULL)
         virHashFree(conn->networks, (virHashDeallocator) virNetworkFreeName);
+    if (conn->interfaces != NULL)
+        virHashFree(conn->interfaces, (virHashDeallocator) virInterfaceFreeName);
     if (conn->storagePools != NULL)
         virHashFree(conn->storagePools, (virHashDeallocator) virStoragePoolFreeName);
     if (conn->storageVols != NULL)
@@ -488,6 +510,144 @@ virUnrefNetwork(virNetworkPtr network) {
 
 
 /**
+ * virGetInterface:
+ * @conn: the hypervisor connection
+ * @name: pointer to the interface name
+ * @mac: pointer to the mac
+ *
+ * Lookup if the interface is already registered for that connection,
+ * if yes return a new pointer to it, if no allocate a new structure,
+ * and register it in the table. In any case a corresponding call to
+ * virUnrefInterface() is needed to not leak data.
+ *
+ * Returns a pointer to the interface, or NULL in case of failure
+ */
+virInterfacePtr
+virGetInterface(virConnectPtr conn, const char *name, const char *mac) {
+    virInterfacePtr ret = NULL;
+
+    if ((!VIR_IS_CONNECT(conn)) || (name == NULL) || (mac == NULL)) {
+        virLibConnError(NULL, VIR_ERR_INVALID_ARG, __FUNCTION__);
+        return(NULL);
+    }
+    virMutexLock(&conn->lock);
+
+    /* TODO search by MAC first as they are better differentiators */
+
+    ret = (virInterfacePtr) virHashLookup(conn->interfaces, name);
+    /* TODO check the MAC */
+    if (ret == NULL) {
+        if (VIR_ALLOC(ret) < 0) {
+            virReportOOMError(conn);
+            goto error;
+        }
+        ret->name = strdup(name);
+        if (ret->name == NULL) {
+            virReportOOMError(conn);
+            goto error;
+        }
+        ret->mac = strdup(mac);
+        if (ret->mac == NULL) {
+            virReportOOMError(conn);
+            goto error;
+        }
+
+        ret->magic = VIR_INTERFACE_MAGIC;
+        ret->conn = conn;
+
+        if (virHashAddEntry(conn->interfaces, name, ret) < 0) {
+            virLibConnError(conn, VIR_ERR_INTERNAL_ERROR,
+                            _("failed to add interface to connection hash table"));
+            goto error;
+        }
+        conn->refs++;
+    }
+    ret->refs++;
+    virMutexUnlock(&conn->lock);
+    return(ret);
+
+ error:
+    virMutexUnlock(&conn->lock);
+    if (ret != NULL) {
+        VIR_FREE(ret->name);
+        VIR_FREE(ret->mac);
+        VIR_FREE(ret);
+    }
+    return(NULL);
+}
+
+/**
+ * virReleaseInterface:
+ * @interface: the interface to release
+ *
+ * Unconditionally release all memory associated with a interface.
+ * The conn.lock mutex must be held prior to calling this, and will
+ * be released prior to this returning. The interface obj must not
+ * be used once this method returns.
+ *
+ * It will also unreference the associated connection object,
+ * which may also be released if its ref count hits zero.
+ */
+static void
+virReleaseInterface(virInterfacePtr interface) {
+    virConnectPtr conn = interface->conn;
+    DEBUG("release interface %p %s", interface, interface->name);
+
+    /* TODO search by MAC first as they are better differenciators */
+    if (virHashRemoveEntry(conn->interfaces, interface->name, NULL) < 0)
+        virLibConnError(conn, VIR_ERR_INTERNAL_ERROR,
+                        _("interface missing from connection hash table"));
+
+    interface->magic = -1;
+    VIR_FREE(interface->name);
+    VIR_FREE(interface->mac);
+    VIR_FREE(interface);
+
+    DEBUG("unref connection %p %d", conn, conn->refs);
+    conn->refs--;
+    if (conn->refs == 0) {
+        virReleaseConnect(conn);
+        /* Already unlocked mutex */
+        return;
+    }
+
+    virMutexUnlock(&conn->lock);
+}
+
+
+/**
+ * virUnrefInterface:
+ * @interface: the interface to unreference
+ *
+ * Unreference the interface. If the use count drops to zero, the structure is
+ * actually freed.
+ *
+ * Returns the reference count or -1 in case of failure.
+ */
+int
+virUnrefInterface(virInterfacePtr interface) {
+    int refs;
+
+    if (!VIR_IS_CONNECTED_INTERFACE(interface)) {
+        virLibConnError(NULL, VIR_ERR_INVALID_ARG, __FUNCTION__);
+        return(-1);
+    }
+    virMutexLock(&interface->conn->lock);
+    DEBUG("unref interface %p %s %d", interface, interface->name, interface->refs);
+    interface->refs--;
+    refs = interface->refs;
+    if (refs == 0) {
+        virReleaseInterface(interface);
+        /* Already unlocked mutex */
+        return (0);
+    }
+
+    virMutexUnlock(&interface->conn->lock);
+    return (refs);
+}
+
+
+/**
  * virGetStoragePool:
  * @conn: the hypervisor connection
  * @name: pointer to the storage pool name
diff --git a/src/datatypes.h b/src/datatypes.h
index 756e0a5..a83777a 100644
--- a/src/datatypes.h
+++ b/src/datatypes.h
@@ -145,6 +145,7 @@ struct _virConnect {
 
     virHashTablePtr domains;  /* hash table for known domains */
     virHashTablePtr networks; /* hash table for known domains */
+    virHashTablePtr interfaces; /* hash table for known interfaces */
     virHashTablePtr storagePools;/* hash table for known storage pools */
     virHashTablePtr storageVols;/* hash table for known storage vols */
     virHashTablePtr nodeDevices; /* hash table for known node devices */
@@ -250,6 +251,11 @@ virNetworkPtr virGetNetwork(virConnectPtr conn,
                               const unsigned char *uuid);
 int virUnrefNetwork(virNetworkPtr network);
 
+virInterfacePtr virGetInterface(virConnectPtr conn,
+                                const char *name,
+                                const char *mac);
+int virUnrefInterface(virInterfacePtr interface);
+
 virStoragePoolPtr virGetStoragePool(virConnectPtr conn,
                                       const char *name,
                                       const unsigned char *uuid);
diff --git a/src/libvirt.c b/src/libvirt.c
index f63a47b..97b92d0 100644
--- a/src/libvirt.c
+++ b/src/libvirt.c
@@ -5870,18 +5870,8 @@ virInterfaceFree(virInterfacePtr interface)
         virLibInterfaceError(NULL, VIR_ERR_INVALID_INTERFACE, __FUNCTION__);
         return (-1);
     }
-#if 0
-    /*
-     * FIXME: This needs to be uncommented when the stubs are replaced
-     *  with actual functionality.
-     */
-
     if (virUnrefInterface(interface) < 0)
         return (-1);
-#else
-    interface->refs--;
-#endif
-
     return(0);
 }
 
diff --git a/src/remote_internal.c b/src/remote_internal.c
index 1ca7784..513ff17 100644
--- a/src/remote_internal.c
+++ b/src/remote_internal.c
@@ -1,3 +1,4 @@
+
 /*
  * remote_internal.c: driver to provide access to libvirtd running
  *   on a remote machine
@@ -211,11 +212,13 @@ static void errorf (virConnectPtr conn, virErrorNumber code,
 static void server_error (virConnectPtr conn, remote_error *err);
 static virDomainPtr get_nonnull_domain (virConnectPtr conn, remote_nonnull_domain domain);
 static virNetworkPtr get_nonnull_network (virConnectPtr conn, remote_nonnull_network network);
+static virInterfacePtr get_nonnull_interface (virConnectPtr conn, remote_nonnull_interface interface);
 static virStoragePoolPtr get_nonnull_storage_pool (virConnectPtr conn, remote_nonnull_storage_pool pool);
 static virStorageVolPtr get_nonnull_storage_vol (virConnectPtr conn, remote_nonnull_storage_vol vol);
 static virNodeDevicePtr get_nonnull_node_device (virConnectPtr conn, remote_nonnull_node_device dev);
 static void make_nonnull_domain (remote_nonnull_domain *dom_dst, virDomainPtr dom_src);
 static void make_nonnull_network (remote_nonnull_network *net_dst, virNetworkPtr net_src);
+static void make_nonnull_interface (remote_nonnull_interface *interface_dst, virInterfacePtr interface_src);
 static void make_nonnull_storage_pool (remote_nonnull_storage_pool *pool_dst, virStoragePoolPtr vol_src);
 static void make_nonnull_storage_vol (remote_nonnull_storage_vol *vol_dst, virStorageVolPtr vol_src);
 void remoteDomainEventFired(int watch, int fd, int event, void *data);
@@ -3675,6 +3678,325 @@ done:
 /*----------------------------------------------------------------------*/
 
 static virDrvOpenStatus
+remoteInterfaceOpen (virConnectPtr conn,
+                   virConnectAuthPtr auth,
+                   int flags)
+{
+    if (inside_daemon)
+        return VIR_DRV_OPEN_DECLINED;
+
+    if (conn &&
+        conn->driver &&
+        STREQ (conn->driver->name, "remote")) {
+        struct private_data *priv;
+
+       /* If we're here, the remote driver is already
+         * in use due to a) a QEMU uri, or b) a remote
+         * URI. So we can re-use existing connection
+         */
+        priv = conn->privateData;
+        remoteDriverLock(priv);
+        priv->localUses++;
+        conn->interfacePrivateData = priv;
+        remoteDriverUnlock(priv);
+        return VIR_DRV_OPEN_SUCCESS;
+    } else {
+        /* Using a non-remote driver, so we need to open a
+         * new connection for interface APIs, forcing it to
+         * use the UNIX transport. This handles Xen driver
+         * which doesn't have its own impl of the interface APIs.
+         */
+        struct private_data *priv;
+        int ret;
+        ret = remoteOpenSecondaryDriver(conn,
+                                        auth,
+                                        flags,
+                                        &priv);
+        if (ret == VIR_DRV_OPEN_SUCCESS)
+            conn->interfacePrivateData = priv;
+        return ret;
+    }
+}
+
+static int
+remoteInterfaceClose (virConnectPtr conn)
+{
+    int rv = 0;
+    struct private_data *priv = conn->interfacePrivateData;
+
+    remoteDriverLock(priv);
+    priv->localUses--;
+    if (!priv->localUses) {
+        rv = doRemoteClose(conn, priv);
+        conn->interfacePrivateData = NULL;
+        remoteDriverUnlock(priv);
+        virMutexDestroy(&priv->lock);
+        VIR_FREE(priv);
+    }
+    if (priv)
+        remoteDriverUnlock(priv);
+    return rv;
+}
+
+static int
+remoteNumOfInterfaces (virConnectPtr conn)
+{
+    int rv = -1;
+    remote_num_of_interfaces_ret ret;
+    struct private_data *priv = conn->interfacePrivateData;
+
+    remoteDriverLock(priv);
+
+    memset (&ret, 0, sizeof ret);
+    if (call (conn, priv, 0, REMOTE_PROC_NUM_OF_INTERFACES,
+              (xdrproc_t) xdr_void, (char *) NULL,
+              (xdrproc_t) xdr_remote_num_of_interfaces_ret, (char *) &ret) == -1)
+        goto done;
+
+    rv = ret.num;
+
+done:
+    remoteDriverUnlock(priv);
+    return rv;
+}
+
+static int
+remoteListInterfaces (virConnectPtr conn, char **const names, int maxnames)
+{
+    int rv = -1;
+    int i;
+    remote_list_interfaces_args args;
+    remote_list_interfaces_ret ret;
+    struct private_data *priv = conn->interfacePrivateData;
+
+    remoteDriverLock(priv);
+
+    if (maxnames > REMOTE_INTERFACE_NAME_LIST_MAX) {
+        errorf (conn, VIR_ERR_RPC,
+                _("too many remote interfaces: %d > %d"),
+                maxnames, REMOTE_INTERFACE_NAME_LIST_MAX);
+        goto done;
+    }
+    args.maxnames = maxnames;
+
+    memset (&ret, 0, sizeof ret);
+    if (call (conn, priv, 0, REMOTE_PROC_LIST_INTERFACES,
+              (xdrproc_t) xdr_remote_list_interfaces_args, (char *) &args,
+              (xdrproc_t) xdr_remote_list_interfaces_ret, (char *) &ret) == -1)
+        goto done;
+
+    if (ret.names.names_len > maxnames) {
+        errorf (conn, VIR_ERR_RPC,
+                _("too many remote interfaces: %d > %d"),
+                ret.names.names_len, maxnames);
+        goto cleanup;
+    }
+
+    /* This call is caller-frees (although that isn't clear from
+     * the documentation).  However xdr_free will free up both the
+     * names and the list of pointers, so we have to strdup the
+     * names here.
+     */
+    for (i = 0; i < ret.names.names_len; ++i)
+        names[i] = strdup (ret.names.names_val[i]);
+
+    rv = ret.names.names_len;
+
+cleanup:
+    xdr_free ((xdrproc_t) xdr_remote_list_interfaces_ret, (char *) &ret);
+
+done:
+    remoteDriverUnlock(priv);
+    return rv;
+}
+
+static virInterfacePtr
+remoteInterfaceLookupByName (virConnectPtr conn,
+                             const char *name)
+{
+    virInterfacePtr interface = NULL;
+    remote_interface_lookup_by_name_args args;
+    remote_interface_lookup_by_name_ret ret;
+    struct private_data *priv = conn->interfacePrivateData;
+
+    remoteDriverLock(priv);
+
+    args.name = (char *) name;
+
+    memset (&ret, 0, sizeof ret);
+    if (call (conn, priv, 0, REMOTE_PROC_INTERFACE_LOOKUP_BY_NAME,
+              (xdrproc_t) xdr_remote_interface_lookup_by_name_args, (char *) &args,
+              (xdrproc_t) xdr_remote_interface_lookup_by_name_ret, (char *) &ret) == -1)
+        goto done;
+
+    interface = get_nonnull_interface (conn, ret.interface);
+    xdr_free ((xdrproc_t) &xdr_remote_interface_lookup_by_name_ret, (char *) &ret);
+
+done:
+    remoteDriverUnlock(priv);
+    return interface;
+}
+
+static virInterfacePtr
+remoteInterfaceLookupByMACString (virConnectPtr conn,
+                                  const char *mac)
+{
+    virInterfacePtr interface = NULL;
+    remote_interface_lookup_by_mac_string_args args;
+    remote_interface_lookup_by_mac_string_ret ret;
+    struct private_data *priv = conn->interfacePrivateData;
+
+    remoteDriverLock(priv);
+
+    args.mac = (char *) mac;
+
+    memset (&ret, 0, sizeof ret);
+    if (call (conn, priv, 0, REMOTE_PROC_INTERFACE_LOOKUP_BY_MAC_STRING,
+              (xdrproc_t) xdr_remote_interface_lookup_by_mac_string_args, (char *) &args,
+              (xdrproc_t) xdr_remote_interface_lookup_by_mac_string_ret, (char *) &ret) == -1)
+        goto done;
+
+    interface = get_nonnull_interface (conn, ret.interface);
+    xdr_free ((xdrproc_t) &xdr_remote_interface_lookup_by_mac_string_ret, (char *) &ret);
+
+done:
+    remoteDriverUnlock(priv);
+    return interface;
+}
+
+static char *
+remoteInterfaceGetXMLDesc (virInterfacePtr interface,
+                           unsigned int flags)
+{
+    char *rv = NULL;
+    remote_interface_get_xml_desc_args args;
+    remote_interface_get_xml_desc_ret ret;
+    struct private_data *priv = interface->conn->interfacePrivateData;
+
+    remoteDriverLock(priv);
+
+    make_nonnull_interface (&args.interface, interface);
+    args.flags = flags;
+
+    memset (&ret, 0, sizeof ret);
+    if (call (interface->conn, priv, 0, REMOTE_PROC_INTERFACE_GET_XML_DESC,
+              (xdrproc_t) xdr_remote_interface_get_xml_desc_args, (char *) &args,
+              (xdrproc_t) xdr_remote_interface_get_xml_desc_ret, (char *) &ret) == -1)
+        goto done;
+
+    /* Caller frees. */
+    rv = ret.xml;
+
+done:
+    remoteDriverUnlock(priv);
+    return rv;
+}
+
+static virInterfacePtr
+remoteInterfaceDefineXML (virConnectPtr conn,
+                          const char *xmlDesc,
+                          unsigned int flags)
+{
+    virInterfacePtr interface = NULL;
+    remote_interface_define_xml_args args;
+    remote_interface_define_xml_ret ret;
+    struct private_data *priv = conn->interfacePrivateData;
+
+    remoteDriverLock(priv);
+
+    args.xml = (char *) xmlDesc;
+    args.flags = flags;
+
+    memset (&ret, 0, sizeof ret);
+    if (call (conn, priv, 0, REMOTE_PROC_INTERFACE_DEFINE_XML,
+              (xdrproc_t) xdr_remote_interface_define_xml_args, (char *) &args,
+              (xdrproc_t) xdr_remote_interface_define_xml_ret, (char *) &ret) == -1)
+        goto done;
+
+    interface = get_nonnull_interface (conn, ret.interface);
+    xdr_free ((xdrproc_t) &xdr_remote_interface_define_xml_ret, (char *) &ret);
+
+done:
+    remoteDriverUnlock(priv);
+    return interface;
+}
+
+static int
+remoteInterfaceUndefine (virInterfacePtr interface)
+{
+    int rv = -1;
+    remote_interface_undefine_args args;
+    struct private_data *priv = interface->conn->interfacePrivateData;
+
+    remoteDriverLock(priv);
+
+    make_nonnull_interface (&args.interface, interface);
+
+    if (call (interface->conn, priv, 0, REMOTE_PROC_INTERFACE_UNDEFINE,
+              (xdrproc_t) xdr_remote_interface_undefine_args, (char *) &args,
+              (xdrproc_t) xdr_void, (char *) NULL) == -1)
+        goto done;
+
+    rv = 0;
+
+done:
+    remoteDriverUnlock(priv);
+    return rv;
+}
+
+static int
+remoteInterfaceCreate (virInterfacePtr interface,
+                       unsigned int flags)
+{
+    int rv = -1;
+    remote_interface_create_args args;
+    struct private_data *priv = interface->conn->interfacePrivateData;
+
+    remoteDriverLock(priv);
+
+    make_nonnull_interface (&args.interface, interface);
+    args.flags = flags;
+
+    if (call (interface->conn, priv, 0, REMOTE_PROC_INTERFACE_CREATE,
+              (xdrproc_t) xdr_remote_interface_create_args, (char *) &args,
+              (xdrproc_t) xdr_void, (char *) NULL) == -1)
+        goto done;
+
+    rv = 0;
+
+done:
+    remoteDriverUnlock(priv);
+    return rv;
+}
+
+static int
+remoteInterfaceDestroy (virInterfacePtr interface,
+                        unsigned int flags)
+{
+    int rv = -1;
+    remote_interface_destroy_args args;
+    struct private_data *priv = interface->conn->interfacePrivateData;
+
+    remoteDriverLock(priv);
+
+    make_nonnull_interface (&args.interface, interface);
+    args.flags = flags;
+
+    if (call (interface->conn, priv, 0, REMOTE_PROC_INTERFACE_DESTROY,
+              (xdrproc_t) xdr_remote_interface_destroy_args, (char *) &args,
+              (xdrproc_t) xdr_void, (char *) NULL) == -1)
+        goto done;
+
+    rv = 0;
+
+done:
+    remoteDriverUnlock(priv);
+    return rv;
+}
+
+/*----------------------------------------------------------------------*/
+
+static virDrvOpenStatus
 remoteStorageOpen (virConnectPtr conn,
                    virConnectAuthPtr auth,
                    int flags)
@@ -6874,6 +7196,12 @@ get_nonnull_network (virConnectPtr conn, remote_nonnull_network network)
     return virGetNetwork (conn, network.name, BAD_CAST network.uuid);
 }
 
+static virInterfacePtr
+get_nonnull_interface (virConnectPtr conn, remote_nonnull_interface interface)
+{
+    return virGetInterface (conn, interface.name, interface.mac);
+}
+
 static virStoragePoolPtr
 get_nonnull_storage_pool (virConnectPtr conn, remote_nonnull_storage_pool pool)
 {
@@ -6909,6 +7237,14 @@ make_nonnull_network (remote_nonnull_network *net_dst, virNetworkPtr net_src)
 }
 
 static void
+make_nonnull_interface (remote_nonnull_interface *interface_dst,
+                        virInterfacePtr interface_src)
+{
+    interface_dst->name = interface_src->name;
+    interface_dst->mac = interface_src->mac;
+}
+
+static void
 make_nonnull_storage_pool (remote_nonnull_storage_pool *pool_dst, virStoragePoolPtr pool_src)
 {
     pool_dst->name = pool_src->name;
@@ -7019,6 +7355,21 @@ static virNetworkDriver network_driver = {
     .networkSetAutostart = remoteNetworkSetAutostart,
 };
 
+static virInterfaceDriver interface_driver = {
+    .name = "remote",
+    .open = remoteInterfaceOpen,
+    .close = remoteInterfaceClose,
+    .numOfInterfaces = remoteNumOfInterfaces,
+    .listInterfaces = remoteListInterfaces,
+    .interfaceLookupByName = remoteInterfaceLookupByName,
+    .interfaceLookupByMACString = remoteInterfaceLookupByMACString,
+    .interfaceGetXMLDesc = remoteInterfaceGetXMLDesc,
+    .interfaceDefineXML = remoteInterfaceDefineXML,
+    .interfaceUndefine = remoteInterfaceUndefine,
+    .interfaceCreate = remoteInterfaceCreate,
+    .interfaceDestroy = remoteInterfaceDestroy,
+};
+
 static virStorageDriver storage_driver = {
     .name = "remote",
     .open = remoteStorageOpen,
@@ -7091,6 +7442,7 @@ remoteRegister (void)
 {
     if (virRegisterDriver (&driver) == -1) return -1;
     if (virRegisterNetworkDriver (&network_driver) == -1) return -1;
+    if (virRegisterInterfaceDriver (&interface_driver) == -1) return -1;
     if (virRegisterStorageDriver (&storage_driver) == -1) return -1;
     if (virRegisterDeviceMonitor (&dev_monitor) == -1) return -1;
 #ifdef WITH_LIBVIRTD
-- 
1.6.0.6




More information about the libvir-list mailing list