[libvirt] [PATCH 00/16 v2] Refactor all network device handling code

This is an update to https://www.redhat.com/archives/libvir-list/2011-November/msg00168.html Changes in v2: - Pushed first 17 patches - Rebased remaining patches to current GIT master

From: "Daniel P. Berrange" <berrange@redhat.com> In preparation for code re-organization, rename the Macvtap management APIs to have the following patterns virNetDevMacVLanXXXXX - macvlan/macvtap interface management virNetDevVPortProfileXXXX - virtual port profile management * src/util/macvtap.c, src/util/macvtap.h: Rename APIs * src/conf/domain_conf.c, src/network/bridge_driver.c, src/qemu/qemu_command.c, src/qemu/qemu_command.h, src/qemu/qemu_driver.c, src/qemu/qemu_hotplug.c, src/qemu/qemu_migration.c, src/qemu/qemu_process.c, src/qemu/qemu_process.h: Update for renamed APIs --- src/conf/domain_conf.c | 10 +- src/libvirt_private.syms | 4 +- src/network/bridge_driver.c | 8 +- src/qemu/qemu_command.c | 20 +- src/qemu/qemu_command.h | 4 +- src/qemu/qemu_driver.c | 12 +- src/qemu/qemu_hotplug.c | 12 +- src/qemu/qemu_migration.c | 24 ++-- src/qemu/qemu_process.c | 12 +- src/qemu/qemu_process.h | 2 +- src/util/macvtap.c | 388 ++++++++++++++++++++++--------------------- src/util/macvtap.h | 100 ++++++----- tests/qemuxml2argvtest.c | 2 +- tests/qemuxmlnstest.c | 2 +- 14 files changed, 308 insertions(+), 292 deletions(-) diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 6b78d97..9528697 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -3102,7 +3102,7 @@ virDomainActualNetDefParseXML(xmlNodePtr node, mode = virXPathString("string(./source[1]/@mode)", ctxt); if (mode) { int m; - if ((m = virMacvtapModeTypeFromString(mode)) < 0) { + if ((m = virNetDevMacVLanModeTypeFromString(mode)) < 0) { virDomainReportError(VIR_ERR_INTERNAL_ERROR, _("Unkown mode '%s' in interface <actual> element"), mode); @@ -3416,14 +3416,14 @@ virDomainNetDefParseXML(virCapsPtr caps, if (mode != NULL) { int m; - if ((m = virMacvtapModeTypeFromString(mode)) < 0) { + if ((m = virNetDevMacVLanModeTypeFromString(mode)) < 0) { virDomainReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Unkown mode has been specified")); goto error; } def->data.direct.mode = m; } else - def->data.direct.mode = VIR_MACVTAP_MODE_VEPA; + def->data.direct.mode = VIR_NETDEV_MACVLAN_MODE_VEPA; def->data.direct.virtPortProfile = virtPort; virtPort = NULL; @@ -9713,7 +9713,7 @@ virDomainActualNetDefFormat(virBufferPtr buf, virBufferEscapeString(buf, " dev='%s'", def->data.direct.linkdev); - mode = virMacvtapModeTypeToString(def->data.direct.mode); + mode = virNetDevMacVLanModeTypeToString(def->data.direct.mode); if (!mode) { virDomainReportError(VIR_ERR_INTERNAL_ERROR, _("unexpected source mode %d"), @@ -9818,7 +9818,7 @@ virDomainNetDefFormat(virBufferPtr buf, virBufferEscapeString(buf, " <source dev='%s'", def->data.direct.linkdev); virBufferAsprintf(buf, " mode='%s'", - virMacvtapModeTypeToString(def->data.direct.mode)); + virNetDevMacVLanModeTypeToString(def->data.direct.mode)); virBufferAddLit(buf, "/>\n"); virBufferAdjustIndent(buf, 6); if (virNetDevVPortProfileFormat(def->data.direct.virtPortProfile, buf) < 0) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 7b96a3c..03aa711 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -739,8 +739,8 @@ virLogUnlock; # macvtap.h -virVMOperationTypeFromString; -virVMOperationTypeToString; +virNetDevVPortProfileOpTypeFromString; +virNetDevVPortProfileOpTypeToString; # memory.h diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c index 15b52ce..5c84d86 100644 --- a/src/network/bridge_driver.c +++ b/src/network/bridge_driver.c @@ -2781,16 +2781,16 @@ networkAllocateActualDevice(virDomainNetDefPtr iface) iface->data.network.actual->type = VIR_DOMAIN_NET_TYPE_DIRECT; switch (netdef->forwardType) { case VIR_NETWORK_FORWARD_BRIDGE: - iface->data.network.actual->data.direct.mode = VIR_MACVTAP_MODE_BRIDGE; + iface->data.network.actual->data.direct.mode = VIR_NETDEV_MACVLAN_MODE_BRIDGE; break; case VIR_NETWORK_FORWARD_PRIVATE: - iface->data.network.actual->data.direct.mode = VIR_MACVTAP_MODE_PRIVATE; + iface->data.network.actual->data.direct.mode = VIR_NETDEV_MACVLAN_MODE_PRIVATE; break; case VIR_NETWORK_FORWARD_VEPA: - iface->data.network.actual->data.direct.mode = VIR_MACVTAP_MODE_VEPA; + iface->data.network.actual->data.direct.mode = VIR_NETDEV_MACVLAN_MODE_VEPA; break; case VIR_NETWORK_FORWARD_PASSTHROUGH: - iface->data.network.actual->data.direct.mode = VIR_MACVTAP_MODE_PASSTHRU; + iface->data.network.actual->data.direct.mode = VIR_NETDEV_MACVLAN_MODE_PASSTHRU; break; } diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 2fbf691..db65035 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -138,7 +138,7 @@ qemuPhysIfaceConnect(virDomainDefPtr def, struct qemud_driver *driver, virDomainNetDefPtr net, virBitmapPtr qemuCaps, - enum virVMOperationType vmop) + enum virNetDevVPortProfileOp vmop) { int rc; #if WITH_MACVTAP @@ -149,14 +149,14 @@ qemuPhysIfaceConnect(virDomainDefPtr def, net->model && STREQ(net->model, "virtio")) vnet_hdr = 1; - rc = openMacvtapTap(net->ifname, net->mac, - virDomainNetGetActualDirectDev(net), - virDomainNetGetActualDirectMode(net), - vnet_hdr, def->uuid, - virDomainNetGetActualDirectVirtPortProfile(net), - &res_ifname, - vmop, driver->stateDir, - virDomainNetGetActualBandwidth(net)); + rc = virNetDevMacVLanCreate(net->ifname, net->mac, + virDomainNetGetActualDirectDev(net), + virDomainNetGetActualDirectMode(net), + vnet_hdr, def->uuid, + virDomainNetGetActualDirectVirtPortProfile(net), + &res_ifname, + vmop, driver->stateDir, + virDomainNetGetActualBandwidth(net)); if (rc >= 0) { virDomainAuditNetDevice(def, net, res_ifname, true); VIR_FREE(net->ifname); @@ -3233,7 +3233,7 @@ qemuBuildCommandLine(virConnectPtr conn, const char *migrateFrom, int migrateFd, virDomainSnapshotObjPtr snapshot, - enum virVMOperationType vmop) + enum virNetDevVPortProfileOp vmop) { int i; struct utsname ut; diff --git a/src/qemu/qemu_command.h b/src/qemu/qemu_command.h index bfdaff9..dbe2fb2 100644 --- a/src/qemu/qemu_command.h +++ b/src/qemu/qemu_command.h @@ -50,7 +50,7 @@ virCommandPtr qemuBuildCommandLine(virConnectPtr conn, const char *migrateFrom, int migrateFd, virDomainSnapshotObjPtr current_snapshot, - enum virVMOperationType vmop) + enum virNetDevVPortProfileOp vmop) ATTRIBUTE_NONNULL(1); /* With vlan == -1, use netdev syntax, else old hostnet */ @@ -135,7 +135,7 @@ int qemuPhysIfaceConnect(virDomainDefPtr def, struct qemud_driver *driver, virDomainNetDefPtr net, virBitmapPtr qemuCaps, - enum virVMOperationType vmop); + enum virNetDevVPortProfileOp vmop); int qemuOpenVhostNet(virDomainDefPtr def, virDomainNetDefPtr net, diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 5f4a18d..3e5cbf6 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -1325,7 +1325,7 @@ static virDomainPtr qemudDomainCreate(virConnectPtr conn, const char *xml, if (qemuProcessStart(conn, driver, vm, NULL, (flags & VIR_DOMAIN_START_PAUSED) != 0, (flags & VIR_DOMAIN_START_AUTODESTROY) != 0, - -1, NULL, NULL, VIR_VM_OP_CREATE) < 0) { + -1, NULL, NULL, VIR_NETDEV_VPORT_PROFILE_OP_CREATE) < 0) { virDomainAuditStart(vm, "booted", false); if (qemuDomainObjEndJob(driver, vm) > 0) qemuDomainRemoveInactive(driver, vm); @@ -4099,7 +4099,7 @@ qemuDomainSaveImageStartVM(virConnectPtr conn, /* Set the migration source and start it up. */ ret = qemuProcessStart(conn, driver, vm, "stdio", true, - false, *fd, path, NULL, VIR_VM_OP_RESTORE); + false, *fd, path, NULL, VIR_NETDEV_VPORT_PROFILE_OP_RESTORE); if (intermediatefd != -1) { if (ret < 0) { @@ -4619,7 +4619,7 @@ static char *qemuDomainXMLToNative(virConnectPtr conn, if (!(cmd = qemuBuildCommandLine(conn, driver, def, &monConfig, monitor_json, qemuCaps, - NULL, -1, NULL, VIR_VM_OP_NO_OP))) + NULL, -1, NULL, VIR_NETDEV_VPORT_PROFILE_OP_NO_OP))) goto cleanup; ret = virCommandToString(cmd); @@ -4701,7 +4701,7 @@ qemuDomainObjStart(virConnectPtr conn, } ret = qemuProcessStart(conn, driver, vm, NULL, start_paused, - autodestroy, -1, NULL, NULL, VIR_VM_OP_CREATE); + autodestroy, -1, NULL, NULL, VIR_NETDEV_VPORT_PROFILE_OP_CREATE); virDomainAuditStart(vm, "booted", ret >= 0); if (ret >= 0) { virDomainEventPtr event = @@ -10052,7 +10052,7 @@ static int qemuDomainRevertToSnapshot(virDomainSnapshotPtr snapshot, rc = qemuProcessStart(snapshot->domain->conn, driver, vm, NULL, true, false, -1, NULL, snap, - VIR_VM_OP_CREATE); + VIR_NETDEV_VPORT_PROFILE_OP_CREATE); virDomainAuditStart(vm, "from-snapshot", rc >= 0); detail = VIR_DOMAIN_EVENT_STARTED_FROM_SNAPSHOT; event = virDomainEventNewFromObj(vm, @@ -10142,7 +10142,7 @@ static int qemuDomainRevertToSnapshot(virDomainSnapshotPtr snapshot, qemuDomainEventQueue(driver, event); rc = qemuProcessStart(snapshot->domain->conn, driver, vm, NULL, paused, false, -1, NULL, NULL, - VIR_VM_OP_CREATE); + VIR_NETDEV_VPORT_PROFILE_OP_CREATE); virDomainAuditStart(vm, "from-snapshot", rc >= 0); if (rc < 0) { if (!vm->persistent) { diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c index 959fa85..47ece57 100644 --- a/src/qemu/qemu_hotplug.c +++ b/src/qemu/qemu_hotplug.c @@ -678,7 +678,7 @@ int qemuDomainAttachNetDevice(virConnectPtr conn, } else if (actualType == VIR_DOMAIN_NET_TYPE_DIRECT) { if ((tapfd = qemuPhysIfaceConnect(vm->def, driver, net, priv->qemuCaps, - VIR_VM_OP_CREATE)) < 0) + VIR_NETDEV_VPORT_PROFILE_OP_CREATE)) < 0) goto cleanup; iface_connected = true; if (qemuOpenVhostNet(vm->def, net, priv->qemuCaps, &vhostfd) < 0) @@ -1911,11 +1911,11 @@ int qemuDomainDetachNetDevice(struct qemud_driver *driver, #if WITH_MACVTAP if (virDomainNetGetActualType(detach) == VIR_DOMAIN_NET_TYPE_DIRECT) { - delMacvtap(detach->ifname, detach->mac, - virDomainNetGetActualDirectDev(detach), - virDomainNetGetActualDirectMode(detach), - virDomainNetGetActualDirectVirtPortProfile(detach), - driver->stateDir); + ignore_value(virNetDevMacVLanDelete(detach->ifname, detach->mac, + virDomainNetGetActualDirectDev(detach), + virDomainNetGetActualDirectMode(detach), + virDomainNetGetActualDirectVirtPortProfile(detach), + driver->stateDir)); VIR_FREE(detach->ifname); } #endif diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c index 30f805d..2525210 100644 --- a/src/qemu/qemu_migration.c +++ b/src/qemu/qemu_migration.c @@ -1147,7 +1147,7 @@ qemuMigrationPrepareAny(struct qemud_driver *driver, */ if (qemuProcessStart(dconn, driver, vm, migrateFrom, true, true, dataFD[0], NULL, NULL, - VIR_VM_OP_MIGRATE_IN_START) < 0) { + VIR_NETDEV_VPORT_PROFILE_OP_MIGRATE_IN_START) < 0) { virDomainAuditStart(vm, "migrated", false); /* Note that we don't set an error here because qemuProcessStart * should have already done that. @@ -2522,12 +2522,12 @@ qemuMigrationVPAssociatePortProfiles(virDomainDefPtr def) { for (i = 0; i < def->nnets; i++) { net = def->nets[i]; if (virDomainNetGetActualType(net) == VIR_DOMAIN_NET_TYPE_DIRECT) { - if (vpAssociatePortProfileId(net->ifname, - net->mac, - virDomainNetGetActualDirectDev(net), - virDomainNetGetActualDirectVirtPortProfile(net), - def->uuid, - VIR_VM_OP_MIGRATE_IN_FINISH) < 0) + if (virNetDevVPortProfileAssociate(net->ifname, + virDomainNetGetActualDirectVirtPortProfile(net), + net->mac, + virDomainNetGetActualDirectDev(net), + def->uuid, + VIR_NETDEV_VPORT_PROFILE_OP_MIGRATE_IN_FINISH) < 0) goto err_exit; } last_good_net = i; @@ -2539,11 +2539,11 @@ err_exit: for (i = 0; i < last_good_net; i++) { net = def->nets[i]; if (virDomainNetGetActualType(net) == VIR_DOMAIN_NET_TYPE_DIRECT) { - vpDisassociatePortProfileId(net->ifname, - net->mac, - virDomainNetGetActualDirectDev(net), - virDomainNetGetActualDirectVirtPortProfile(net), - VIR_VM_OP_MIGRATE_IN_FINISH); + ignore_value(virNetDevVPortProfileDisassociate(net->ifname, + virDomainNetGetActualDirectVirtPortProfile(net), + net->mac, + virDomainNetGetActualDirectDev(net), + VIR_NETDEV_VPORT_PROFILE_OP_MIGRATE_IN_FINISH)); } } } diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c index 2882ef8..4dc9357 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -2816,7 +2816,7 @@ int qemuProcessStart(virConnectPtr conn, int stdin_fd, const char *stdin_path, virDomainSnapshotObjPtr snapshot, - enum virVMOperationType vmop) + enum virNetDevVPortProfileOp vmop) { int ret; off_t pos = -1; @@ -3412,11 +3412,11 @@ void qemuProcessStop(struct qemud_driver *driver, virDomainNetDefPtr net = def->nets[i]; #if WITH_MACVTAP if (virDomainNetGetActualType(net) == VIR_DOMAIN_NET_TYPE_DIRECT) { - delMacvtap(net->ifname, net->mac, - virDomainNetGetActualDirectDev(net), - virDomainNetGetActualDirectMode(net), - virDomainNetGetActualDirectVirtPortProfile(net), - driver->stateDir); + ignore_value(virNetDevMacVLanDelete(net->ifname, net->mac, + virDomainNetGetActualDirectDev(net), + virDomainNetGetActualDirectMode(net), + virDomainNetGetActualDirectVirtPortProfile(net), + driver->stateDir)); VIR_FREE(net->ifname); } #endif diff --git a/src/qemu/qemu_process.h b/src/qemu/qemu_process.h index ef422c4..062d79e 100644 --- a/src/qemu/qemu_process.h +++ b/src/qemu/qemu_process.h @@ -53,7 +53,7 @@ int qemuProcessStart(virConnectPtr conn, int stdin_fd, const char *stdin_path, virDomainSnapshotObjPtr snapshot, - enum virVMOperationType vmop); + enum virNetDevVPortProfileOp vmop); void qemuProcessStop(struct qemud_driver *driver, virDomainObjPtr vm, diff --git a/src/util/macvtap.c b/src/util/macvtap.c index bc23520..c793493 100644 --- a/src/util/macvtap.c +++ b/src/util/macvtap.c @@ -52,7 +52,7 @@ #include "macvtap.h" #include "virnetdev.h" -VIR_ENUM_IMPL(virMacvtapMode, VIR_MACVTAP_MODE_LAST, +VIR_ENUM_IMPL(virNetDevMacVLanMode, VIR_NETDEV_MACVLAN_MODE_LAST, "vepa", "private", "bridge", @@ -101,15 +101,17 @@ enum virNetDevVPortProfileLinkOp { # if WITH_MACVTAP -/* Open the macvtap's tap device. +/** + * virNetDevMacVLanTapOpen: + * Open the macvtap's tap device. * @ifname: Name of the macvtap interface * @retries : Number of retries in case udev for example may need to be * waited for to create the tap chardev * Returns negative value in case of error, the file descriptor otherwise. */ static -int openTap(const char *ifname, - int retries) +int virNetDevMacVLanTapOpen(const char *ifname, + int retries) { FILE *file; char path[64]; @@ -173,7 +175,7 @@ int openTap(const char *ifname, /** - * configMacvtapTap: + * virNetDevMacVLanTapSetup: * @tapfd: file descriptor of the macvtap tap * @vnet_hdr: 1 to enable IFF_VNET_HDR, 0 to disable it * @@ -187,7 +189,7 @@ int openTap(const char *ifname, * macvtap device should not be used. */ static int -configMacvtapTap(int tapfd, int vnet_hdr) +virNetDevMacVLanTapSetup(int tapfd, int vnet_hdr) { unsigned int features; struct ifreq ifreq; @@ -233,15 +235,15 @@ configMacvtapTap(int tapfd, int vnet_hdr) } -static const uint32_t modeMap[VIR_MACVTAP_MODE_LAST] = { - [VIR_MACVTAP_MODE_VEPA] = MACVLAN_MODE_VEPA, - [VIR_MACVTAP_MODE_PRIVATE] = MACVLAN_MODE_PRIVATE, - [VIR_MACVTAP_MODE_BRIDGE] = MACVLAN_MODE_BRIDGE, - [VIR_MACVTAP_MODE_PASSTHRU] = MACVLAN_MODE_PASSTHRU, +static const uint32_t modeMap[VIR_NETDEV_MACVLAN_MODE_LAST] = { + [VIR_NETDEV_MACVLAN_MODE_VEPA] = MACVLAN_MODE_VEPA, + [VIR_NETDEV_MACVLAN_MODE_PRIVATE] = MACVLAN_MODE_PRIVATE, + [VIR_NETDEV_MACVLAN_MODE_BRIDGE] = MACVLAN_MODE_BRIDGE, + [VIR_NETDEV_MACVLAN_MODE_PASSTHRU] = MACVLAN_MODE_PASSTHRU, }; /** - * openMacvtapTap: + * virNetDevMacVLanCreate: * Create an instance of a macvtap device and open its tap character * device. * @tgifname: Interface name that the macvtap is supposed to have. May @@ -260,18 +262,17 @@ static const uint32_t modeMap[VIR_MACVTAP_MODE_LAST] = { * negative value otherwise with error reported. * */ -int -openMacvtapTap(const char *tgifname, - const unsigned char *macaddress, - const char *linkdev, - enum virMacvtapMode mode, - int vnet_hdr, - const unsigned char *vmuuid, - virNetDevVPortProfilePtr virtPortProfile, - char **res_ifname, - enum virVMOperationType vmOp, - char *stateDir, - virNetDevBandwidthPtr bandwidth) +int virNetDevMacVLanCreate(const char *tgifname, + const unsigned char *macaddress, + const char *linkdev, + enum virNetDevMacVLanMode mode, + int vnet_hdr, + const unsigned char *vmuuid, + virNetDevVPortProfilePtr virtPortProfile, + char **res_ifname, + enum virNetDevVPortProfileOp vmOp, + char *stateDir, + virNetDevBandwidthPtr bandwidth) { const char *type = "macvtap"; int c, rc; @@ -285,7 +286,7 @@ openMacvtapTap(const char *tgifname, *res_ifname = NULL; - VIR_DEBUG("%s: VM OPERATION: %s", __FUNCTION__, virVMOperationTypeToString(vmOp)); + VIR_DEBUG("%s: VM OPERATION: %s", __FUNCTION__, virNetDevVPortProfileOpTypeToString(vmOp)); /** Note: When using PASSTHROUGH mode with MACVTAP devices the link * device's MAC address must be set to the VMs MAC address. In @@ -294,7 +295,7 @@ openMacvtapTap(const char *tgifname, * This is especially important when using SRIOV capable cards that * emulate their switch in firmware. */ - if (mode == VIR_MACVTAP_MODE_PASSTHRU) { + if (mode == VIR_NETDEV_MACVLAN_MODE_PASSTHRU) { if (ifaceReplaceMacAddress(macaddress, linkdev, stateDir) < 0) { return -1; } @@ -334,11 +335,11 @@ create_name: cr_ifname = ifname; } - if (vpAssociatePortProfileId(cr_ifname, - macaddress, - linkdev, - virtPortProfile, - vmuuid, vmOp) < 0) { + if (virNetDevVPortProfileAssociate(cr_ifname, + virtPortProfile, + macaddress, + linkdev, + vmuuid, vmOp) < 0) { rc = -1; goto link_del_exit; } @@ -348,9 +349,9 @@ create_name: goto disassociate_exit; } - rc = openTap(cr_ifname, 10); + rc = virNetDevMacVLanTapOpen(cr_ifname, 10); if (rc >= 0) { - if (configMacvtapTap(rc, vnet_hdr) < 0) { + if (virNetDevMacVLanTapSetup(rc, vnet_hdr) < 0) { VIR_FORCE_CLOSE(rc); /* sets rc to -1 */ goto disassociate_exit; } @@ -370,11 +371,11 @@ create_name: return rc; disassociate_exit: - vpDisassociatePortProfileId(cr_ifname, - macaddress, - linkdev, - virtPortProfile, - vmOp); + ignore_value(virNetDevVPortProfileDisassociate(cr_ifname, + virtPortProfile, + macaddress, + linkdev, + vmOp)); link_del_exit: ifaceLinkDel(cr_ifname); @@ -393,25 +394,29 @@ link_del_exit: * it with the switch if port profile parameters * were provided. */ -void -delMacvtap(const char *ifname, - const unsigned char *macaddr, - const char *linkdev, - int mode, - virNetDevVPortProfilePtr virtPortProfile, - char *stateDir) +int virNetDevMacVLanDelete(const char *ifname, + const unsigned char *macaddr, + const char *linkdev, + int mode, + virNetDevVPortProfilePtr virtPortProfile, + char *stateDir) { - if (mode == VIR_MACVTAP_MODE_PASSTHRU) { + int ret = 0; + if (mode == VIR_NETDEV_MACVLAN_MODE_PASSTHRU) { ifaceRestoreMacAddress(linkdev, stateDir); } if (ifname) { - vpDisassociatePortProfileId(ifname, macaddr, - linkdev, - virtPortProfile, - VIR_VM_OP_DESTROY); - ifaceLinkDel(ifname); + if (virNetDevVPortProfileDisassociate(ifname, + virtPortProfile, + macaddr, + linkdev, + VIR_NETDEV_VPORT_PROFILE_OP_DESTROY) < 0) + ret = -1; + if (ifaceLinkDel(ifname) < 0) + ret = -1; } + return ret; } # endif /* WITH_MACVTAP */ @@ -425,7 +430,7 @@ static struct nla_policy ifla_port_policy[IFLA_PORT_MAX + 1] = static uint32_t -getLldpadPid(void) { +virNetDevVPortProfileGetLldpadPid(void) { int fd; uint32_t pid = 0; @@ -458,7 +463,7 @@ getLldpadPid(void) { /** - * getPortProfileStatus + * virNetDevVPortProfileGetStatus: * * tb: top level netlink response attributes + values * vf: The virtual function used in the request @@ -470,11 +475,11 @@ getLldpadPid(void) { * case of success, < 0 otherwise with error having been reported */ static int -getPortProfileStatus(struct nlattr **tb, int32_t vf, - const unsigned char *instanceId, - bool nltarget_kernel, - bool is8021Qbg, - uint16_t *status) +virNetDevVPortProfileGetStatus(struct nlattr **tb, int32_t vf, + const unsigned char *instanceId, + bool nltarget_kernel, + bool is8021Qbg, + uint16_t *status) { int rc = -1; const char *msg = NULL; @@ -557,16 +562,16 @@ err_exit: static int -doPortProfileOpSetLink(bool nltarget_kernel, - const char *ifname, int ifindex, - const unsigned char *macaddr, - int vlanid, - const char *profileId, - struct ifla_port_vsi *portVsi, - const unsigned char *instanceId, - const unsigned char *hostUUID, - int32_t vf, - uint8_t op) +virNetDevVPortProfileOpSetLink(const char *ifname, int ifindex, + bool nltarget_kernel, + const unsigned char *macaddr, + int vlanid, + const char *profileId, + struct ifla_port_vsi *portVsi, + const unsigned char *instanceId, + const unsigned char *hostUUID, + int32_t vf, + uint8_t op) { int rc = -1; struct nlmsghdr *resp; @@ -685,7 +690,7 @@ doPortProfileOpSetLink(bool nltarget_kernel, } if (!nltarget_kernel) { - pid = getLldpadPid(); + pid = virNetDevVPortProfileGetLldpadPid(); if (pid == 0) goto err_exit; } @@ -747,16 +752,16 @@ buffer_too_small: /* Returns 0 on success, -1 on general failure, and -2 on timeout */ static int -doPortProfileOpCommon(bool nltarget_kernel, - const char *ifname, int ifindex, - const unsigned char *macaddr, - int vlanid, - const char *profileId, - struct ifla_port_vsi *portVsi, - const unsigned char *instanceId, - const unsigned char *hostUUID, - int32_t vf, - uint8_t op) +virNetDevVPortProfileOpCommon(const char *ifname, int ifindex, + bool nltarget_kernel, + const unsigned char *macaddr, + int vlanid, + const char *profileId, + struct ifla_port_vsi *portVsi, + const unsigned char *instanceId, + const unsigned char *hostUUID, + int32_t vf, + uint8_t op) { int rc; unsigned char *recvbuf = NULL; @@ -765,16 +770,16 @@ doPortProfileOpCommon(bool nltarget_kernel, uint16_t status = 0; bool is8021Qbg = (profileId == NULL); - rc = doPortProfileOpSetLink(nltarget_kernel, - ifname, ifindex, - macaddr, - vlanid, - profileId, - portVsi, - instanceId, - hostUUID, - vf, - op); + rc = virNetDevVPortProfileOpSetLink(ifname, ifindex, + nltarget_kernel, + macaddr, + vlanid, + profileId, + portVsi, + instanceId, + hostUUID, + vf, + op); if (rc < 0) { macvtapError(VIR_ERR_INTERNAL_ERROR, "%s", _("sending of PortProfileRequest failed.")); @@ -783,12 +788,12 @@ doPortProfileOpCommon(bool nltarget_kernel, while (--repeats >= 0) { rc = ifaceMacvtapLinkDump(nltarget_kernel, NULL, ifindex, tb, - &recvbuf, getLldpadPid); + &recvbuf, virNetDevVPortProfileGetLldpadPid); if (rc < 0) goto err_exit; - rc = getPortProfileStatus(tb, vf, instanceId, nltarget_kernel, - is8021Qbg, &status); + rc = virNetDevVPortProfileGetStatus(tb, vf, instanceId, nltarget_kernel, + is8021Qbg, &status); if (rc < 0) goto err_exit; if (status == PORT_PROFILE_RESPONSE_SUCCESS || @@ -828,8 +833,8 @@ err_exit: # ifdef IFLA_VF_PORT_MAX static int -getPhysdevAndVlan(const char *ifname, int *root_ifindex, char *root_ifname, - int *vlanid) +virNetDevVPortProfileGetPhysdevAndVlan(const char *ifname, int *root_ifindex, char *root_ifname, + int *vlanid) { int ret; unsigned int nth; @@ -858,10 +863,10 @@ getPhysdevAndVlan(const char *ifname, int *root_ifindex, char *root_ifname, /* Returns 0 on success, -1 on general failure, and -2 on timeout */ static int -doPortProfileOp8021Qbg(const char *ifname, - const unsigned char *macaddr, - const virNetDevVPortProfilePtr virtPort, - enum virNetDevVPortProfileLinkOp virtPortOp) +virNetDevVPortProfileOp8021Qbg(const char *ifname, + const unsigned char *macaddr, + const virNetDevVPortProfilePtr virtPort, + enum virNetDevVPortProfileLinkOp virtPortOp) { int rc = 0; @@ -888,8 +893,8 @@ doPortProfileOp8021Qbg(const char *ifname, char physdev_ifname[IFNAMSIZ] = { 0, }; int vf = PORT_SELF_VF; - if (getPhysdevAndVlan(ifname, &physdev_ifindex, physdev_ifname, - &vlanid) < 0) { + if (virNetDevVPortProfileGetPhysdevAndVlan(ifname, &physdev_ifindex, physdev_ifname, + &vlanid) < 0) { rc = -1; goto err_exit; } @@ -918,16 +923,16 @@ doPortProfileOp8021Qbg(const char *ifname, goto err_exit; } - rc = doPortProfileOpCommon(nltarget_kernel, - physdev_ifname, physdev_ifindex, - macaddr, - vlanid, - NULL, - &portVsi, - virtPort->u.virtPort8021Qbg.instanceID, - NULL, - vf, - op); + rc = virNetDevVPortProfileOpCommon(physdev_ifname, physdev_ifindex, + nltarget_kernel, + macaddr, + vlanid, + NULL, + &portVsi, + virtPort->u.virtPort8021Qbg.instanceID, + NULL, + vf, + op); err_exit: @@ -939,9 +944,9 @@ err_exit: # ifdef IFLA_VF_PORT_MAX static int -getPhysfnDev(const char *linkdev, - int32_t *vf, - char **physfndev) +virNetDevVPortProfileGetPhysfnDev(const char *linkdev, + int32_t *vf, + char **physfndev) { int rc = -1; @@ -975,11 +980,11 @@ err_exit: /* Returns 0 on success, -1 on general failure, and -2 on timeout */ static int -doPortProfileOp8021Qbh(const char *ifname, - const unsigned char *macaddr, - const virNetDevVPortProfilePtr virtPort, - const unsigned char *vm_uuid, - enum virNetDevVPortProfileLinkOp virtPortOp) +virNetDevVPortProfileOp8021Qbh(const char *ifname, + const unsigned char *macaddr, + const virNetDevVPortProfilePtr virtPort, + const unsigned char *vm_uuid, + enum virNetDevVPortProfileLinkOp virtPortOp) { int rc = 0; @@ -1003,7 +1008,7 @@ doPortProfileOp8021Qbh(const char *ifname, int ifindex; int vlanid = -1; - rc = getPhysfnDev(ifname, &vf, &physfndev); + rc = virNetDevVPortProfileGetPhysfnDev(ifname, &vf, &physfndev); if (rc < 0) goto err_exit; @@ -1020,40 +1025,43 @@ doPortProfileOp8021Qbh(const char *ifname, goto err_exit; } - rc = doPortProfileOpCommon(nltarget_kernel, NULL, ifindex, - macaddr, - vlanid, - virtPort->u.virtPort8021Qbh.profileID, - NULL, - vm_uuid, - hostuuid, - vf, - (virtPortOp == VIR_NETDEV_VPORT_PROFILE_LINK_OP_PREASSOCIATE_RR) ? - PORT_REQUEST_PREASSOCIATE_RR - : PORT_REQUEST_ASSOCIATE); + rc = virNetDevVPortProfileOpCommon(NULL, ifindex, + nltarget_kernel, + macaddr, + vlanid, + virtPort->u.virtPort8021Qbh.profileID, + NULL, + vm_uuid, + hostuuid, + vf, + (virtPortOp == VIR_NETDEV_VPORT_PROFILE_LINK_OP_PREASSOCIATE_RR) ? + PORT_REQUEST_PREASSOCIATE_RR + : PORT_REQUEST_ASSOCIATE); if (rc == -2) /* Association timed out, disassociate */ - doPortProfileOpCommon(nltarget_kernel, NULL, ifindex, - NULL, - vlanid, - NULL, - NULL, - NULL, - NULL, - vf, - PORT_REQUEST_DISASSOCIATE); + virNetDevVPortProfileOpCommon(NULL, ifindex, + nltarget_kernel, + NULL, + vlanid, + NULL, + NULL, + NULL, + NULL, + vf, + PORT_REQUEST_DISASSOCIATE); break; case VIR_NETDEV_VPORT_PROFILE_LINK_OP_DISASSOCIATE: - rc = doPortProfileOpCommon(nltarget_kernel, NULL, ifindex, - NULL, - vlanid, - NULL, - NULL, - NULL, - NULL, - vf, - PORT_REQUEST_DISASSOCIATE); + rc = virNetDevVPortProfileOpCommon(NULL, ifindex, + nltarget_kernel, + NULL, + vlanid, + NULL, + NULL, + NULL, + NULL, + vf, + PORT_REQUEST_DISASSOCIATE); break; default: @@ -1071,7 +1079,7 @@ err_exit: } /** - * vpAssociatePortProfile + * virNetDevVPortProfileAssociate: * * @macvtap_ifname: The name of the macvtap device * @virtPort: pointer to the object holding port profile parameters @@ -1088,21 +1096,21 @@ err_exit: * having been reported. */ int -vpAssociatePortProfileId(const char *macvtap_ifname, - const unsigned char *macvtap_macaddr, - const char *linkdev, - const virNetDevVPortProfilePtr virtPort, - const unsigned char *vmuuid, - enum virVMOperationType vmOp) +virNetDevVPortProfileAssociate(const char *macvtap_ifname, + const virNetDevVPortProfilePtr virtPort, + const unsigned char *macvtap_macaddr, + const char *linkdev, + const unsigned char *vmuuid, + enum virNetDevVPortProfileOp vmOp) { int rc = 0; VIR_DEBUG("Associating port profile '%p' on link device '%s'", virtPort, macvtap_ifname); - VIR_DEBUG("%s: VM OPERATION: %s", __FUNCTION__, virVMOperationTypeToString(vmOp)); + VIR_DEBUG("%s: VM OPERATION: %s", __FUNCTION__, virNetDevVPortProfileOpTypeToString(vmOp)); - if (!virtPort || vmOp == VIR_VM_OP_NO_OP) + if (!virtPort || vmOp == VIR_NETDEV_VPORT_PROFILE_OP_NO_OP) return 0; switch (virtPort->virtPortType) { @@ -1111,20 +1119,20 @@ vpAssociatePortProfileId(const char *macvtap_ifname, break; case VIR_NETDEV_VPORT_PROFILE_8021QBG: - rc = doPortProfileOp8021Qbg(macvtap_ifname, macvtap_macaddr, - virtPort, - (vmOp == VIR_VM_OP_MIGRATE_IN_START) - ? VIR_NETDEV_VPORT_PROFILE_LINK_OP_PREASSOCIATE - : VIR_NETDEV_VPORT_PROFILE_LINK_OP_ASSOCIATE); + rc = virNetDevVPortProfileOp8021Qbg(macvtap_ifname, macvtap_macaddr, + virtPort, + (vmOp == VIR_NETDEV_VPORT_PROFILE_OP_MIGRATE_IN_START) + ? VIR_NETDEV_VPORT_PROFILE_LINK_OP_PREASSOCIATE + : VIR_NETDEV_VPORT_PROFILE_LINK_OP_ASSOCIATE); break; case VIR_NETDEV_VPORT_PROFILE_8021QBH: - rc = doPortProfileOp8021Qbh(linkdev, macvtap_macaddr, - virtPort, vmuuid, - (vmOp == VIR_VM_OP_MIGRATE_IN_START) - ? VIR_NETDEV_VPORT_PROFILE_LINK_OP_PREASSOCIATE_RR - : VIR_NETDEV_VPORT_PROFILE_LINK_OP_ASSOCIATE); - if (vmOp != VIR_VM_OP_MIGRATE_IN_START && !rc) { + rc = virNetDevVPortProfileOp8021Qbh(linkdev, macvtap_macaddr, + virtPort, vmuuid, + (vmOp == VIR_NETDEV_VPORT_PROFILE_OP_MIGRATE_IN_START) + ? VIR_NETDEV_VPORT_PROFILE_LINK_OP_PREASSOCIATE_RR + : VIR_NETDEV_VPORT_PROFILE_LINK_OP_ASSOCIATE); + if (vmOp != VIR_NETDEV_VPORT_PROFILE_OP_MIGRATE_IN_START && !rc) { /* XXX bogus error handling */ ignore_value(virNetDevSetOnline(linkdev, true)); } @@ -1137,7 +1145,7 @@ vpAssociatePortProfileId(const char *macvtap_ifname, /** - * vpDisassociatePortProfile + * virNetDevVPortProfileDisassociate: * * @macvtap_ifname: The name of the macvtap device * @macvtap_macaddr : The MAC address of the macvtap @@ -1148,18 +1156,18 @@ vpAssociatePortProfileId(const char *macvtap_ifname, * having been reported. */ int -vpDisassociatePortProfileId(const char *macvtap_ifname, - const unsigned char *macvtap_macaddr, - const char *linkdev, - const virNetDevVPortProfilePtr virtPort, - enum virVMOperationType vmOp) +virNetDevVPortProfileDisassociate(const char *macvtap_ifname, + const virNetDevVPortProfilePtr virtPort, + const unsigned char *macvtap_macaddr, + const char *linkdev, + enum virNetDevVPortProfileOp vmOp) { int rc = 0; VIR_DEBUG("Disassociating port profile id '%p' on link device '%s' ", virtPort, macvtap_ifname); - VIR_DEBUG("%s: VM OPERATION: %s", __FUNCTION__, virVMOperationTypeToString(vmOp)); + VIR_DEBUG("%s: VM OPERATION: %s", __FUNCTION__, virNetDevVPortProfileOpTypeToString(vmOp)); if (!virtPort) return 0; @@ -1170,18 +1178,18 @@ vpDisassociatePortProfileId(const char *macvtap_ifname, break; case VIR_NETDEV_VPORT_PROFILE_8021QBG: - rc = doPortProfileOp8021Qbg(macvtap_ifname, macvtap_macaddr, - virtPort, VIR_NETDEV_VPORT_PROFILE_LINK_OP_DISASSOCIATE); + rc = virNetDevVPortProfileOp8021Qbg(macvtap_ifname, macvtap_macaddr, + virtPort, VIR_NETDEV_VPORT_PROFILE_LINK_OP_DISASSOCIATE); break; case VIR_NETDEV_VPORT_PROFILE_8021QBH: /* avoid disassociating twice */ - if (vmOp == VIR_VM_OP_MIGRATE_IN_FINISH) + if (vmOp == VIR_NETDEV_VPORT_PROFILE_OP_MIGRATE_IN_FINISH) break; ignore_value(virNetDevSetOnline(linkdev, false)); - rc = doPortProfileOp8021Qbh(linkdev, macvtap_macaddr, - virtPort, NULL, - VIR_NETDEV_VPORT_PROFILE_LINK_OP_DISASSOCIATE); + rc = virNetDevVPortProfileOp8021Qbh(linkdev, macvtap_macaddr, + virtPort, NULL, + VIR_NETDEV_VPORT_PROFILE_LINK_OP_DISASSOCIATE); break; } @@ -1190,12 +1198,12 @@ vpDisassociatePortProfileId(const char *macvtap_ifname, #endif /* WITH_MACVTAP || WITH_VIRTUALPORT */ -VIR_ENUM_IMPL(virVMOperation, VIR_VM_OP_LAST, - "create", - "save", - "restore", - "destroy", - "migrate out", - "migrate in start", - "migrate in finish", - "no-op") +VIR_ENUM_IMPL(virNetDevVPortProfileOp, VIR_NETDEV_VPORT_PROFILE_OP_LAST, + "create", + "save", + "restore", + "destroy", + "migrate out", + "migrate in start", + "migrate in finish", + "no-op") diff --git a/src/util/macvtap.h b/src/util/macvtap.h index a6b00fe..5c5d84a 100644 --- a/src/util/macvtap.h +++ b/src/util/macvtap.h @@ -29,65 +29,73 @@ # include "virnetdevvportprofile.h" /* the mode type for macvtap devices */ -enum virMacvtapMode { - VIR_MACVTAP_MODE_VEPA, - VIR_MACVTAP_MODE_PRIVATE, - VIR_MACVTAP_MODE_BRIDGE, - VIR_MACVTAP_MODE_PASSTHRU, +enum virNetDevMacVLanMode { + VIR_NETDEV_MACVLAN_MODE_VEPA, + VIR_NETDEV_MACVLAN_MODE_PRIVATE, + VIR_NETDEV_MACVLAN_MODE_BRIDGE, + VIR_NETDEV_MACVLAN_MODE_PASSTHRU, - VIR_MACVTAP_MODE_LAST, + VIR_NETDEV_MACVLAN_MODE_LAST, }; -enum virVMOperationType { - VIR_VM_OP_CREATE, - VIR_VM_OP_SAVE, - VIR_VM_OP_RESTORE, - VIR_VM_OP_DESTROY, - VIR_VM_OP_MIGRATE_OUT, - VIR_VM_OP_MIGRATE_IN_START, - VIR_VM_OP_MIGRATE_IN_FINISH, - VIR_VM_OP_NO_OP, +enum virNetDevVPortProfileOp { + VIR_NETDEV_VPORT_PROFILE_OP_CREATE, + VIR_NETDEV_VPORT_PROFILE_OP_SAVE, + VIR_NETDEV_VPORT_PROFILE_OP_RESTORE, + VIR_NETDEV_VPORT_PROFILE_OP_DESTROY, + VIR_NETDEV_VPORT_PROFILE_OP_MIGRATE_OUT, + VIR_NETDEV_VPORT_PROFILE_OP_MIGRATE_IN_START, + VIR_NETDEV_VPORT_PROFILE_OP_MIGRATE_IN_FINISH, + VIR_NETDEV_VPORT_PROFILE_OP_NO_OP, - VIR_VM_OP_LAST + VIR_NETDEV_VPORT_PROFILE_OP_LAST }; # if WITH_MACVTAP -int openMacvtapTap(const char *ifname, - const unsigned char *macaddress, - const char *linkdev, - enum virMacvtapMode mode, - int vnet_hdr, - const unsigned char *vmuuid, - virNetDevVPortProfilePtr virtPortProfile, - char **res_ifname, - enum virVMOperationType vmop, - char *stateDir, - virNetDevBandwidthPtr bandwidth); +int virNetDevMacVLanCreate(const char *ifname, + const unsigned char *macaddress, + const char *linkdev, + enum virNetDevMacVLanMode mode, + int vnet_hdr, + const unsigned char *vmuuid, + virNetDevVPortProfilePtr virtPortProfile, + char **res_ifname, + enum virNetDevVPortProfileOp vmop, + char *stateDir, + virNetDevBandwidthPtr bandwidth) + ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3) ATTRIBUTE_NONNULL(6) + ATTRIBUTE_NONNULL(8) ATTRIBUTE_NONNULL(10) ATTRIBUTE_RETURN_CHECK; -void delMacvtap(const char *ifname, - const unsigned char *macaddress, - const char *linkdev, - int mode, - virNetDevVPortProfilePtr virtPortProfile, - char *stateDir); +int virNetDevMacVLanDelete(const char *ifname, + const unsigned char *macaddress, + const char *linkdev, + int mode, + virNetDevVPortProfilePtr virtPortProfile, + char *stateDir) + ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3) + ATTRIBUTE_NONNULL(6) ATTRIBUTE_RETURN_CHECK; -int vpAssociatePortProfileId(const char *macvtap_ifname, - const unsigned char *macvtap_macaddr, - const char *linkdev, - const virNetDevVPortProfilePtr virtPort, - const unsigned char *vmuuid, - enum virVMOperationType vmOp); +int virNetDevVPortProfileAssociate(const char *ifname, + const virNetDevVPortProfilePtr virtPort, + const unsigned char *macaddr, + const char *linkdev, + const unsigned char *vmuuid, + enum virNetDevVPortProfileOp vmOp) + ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(3) ATTRIBUTE_NONNULL(4) + ATTRIBUTE_NONNULL(5) ATTRIBUTE_RETURN_CHECK; -int vpDisassociatePortProfileId(const char *macvtap_ifname, - const unsigned char *macvtap_macaddr, - const char *linkdev, - const virNetDevVPortProfilePtr virtPort, - enum virVMOperationType vmOp); +int virNetDevVPortProfileDisassociate(const char *ifname, + const virNetDevVPortProfilePtr virtPort, + const unsigned char *macaddr, + const char *linkdev, + enum virNetDevVPortProfileOp vmOp) + ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(3) ATTRIBUTE_NONNULL(4) + ATTRIBUTE_RETURN_CHECK; # endif /* WITH_MACVTAP */ -VIR_ENUM_DECL(virVMOperation) -VIR_ENUM_DECL(virMacvtapMode) +VIR_ENUM_DECL(virNetDevVPortProfileOp) +VIR_ENUM_DECL(virNetDevMacVLanMode) #endif /* __UTIL_MACVTAP_H__ */ diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c index d9a6e8d..5d3b74c 100644 --- a/tests/qemuxml2argvtest.c +++ b/tests/qemuxml2argvtest.c @@ -124,7 +124,7 @@ static int testCompareXMLToArgvFiles(const char *xml, if (!(cmd = qemuBuildCommandLine(conn, &driver, vmdef, &monitor_chr, json, extraFlags, migrateFrom, migrateFd, NULL, - VIR_VM_OP_NO_OP))) + VIR_NETDEV_VPORT_PROFILE_OP_NO_OP))) goto fail; if (!!virGetLastError() != expectError) { diff --git a/tests/qemuxmlnstest.c b/tests/qemuxmlnstest.c index b13b409..ee3ad1b 100644 --- a/tests/qemuxmlnstest.c +++ b/tests/qemuxmlnstest.c @@ -124,7 +124,7 @@ static int testCompareXMLToArgvFiles(const char *xml, if (!(cmd = qemuBuildCommandLine(conn, &driver, vmdef, &monitor_chr, json, extraFlags, migrateFrom, migrateFd, NULL, - VIR_VM_OP_NO_OP))) + VIR_NETDEV_VPORT_PROFILE_OP_NO_OP))) goto fail; if (!!virGetLastError() != expectError) { -- 1.7.6.4

On 11/15/2011 06:14 AM, Daniel P. Berrange wrote:
From: "Daniel P. Berrange"<berrange@redhat.com>
In preparation for code re-organization, rename the Macvtap management APIs to have the following patterns
virNetDevMacVLanXXXXX - macvlan/macvtap interface management virNetDevVPortProfileXXXX - virtual port profile management
* src/util/macvtap.c, src/util/macvtap.h: Rename APIs * src/conf/domain_conf.c, src/network/bridge_driver.c, src/qemu/qemu_command.c, src/qemu/qemu_command.h, src/qemu/qemu_driver.c, src/qemu/qemu_hotplug.c, src/qemu/qemu_migration.c, src/qemu/qemu_process.c, src/qemu/qemu_process.h: Update for renamed APIs --- src/conf/domain_conf.c | 10 +- src/libvirt_private.syms | 4 +- src/network/bridge_driver.c | 8 +- src/qemu/qemu_command.c | 20 +- src/qemu/qemu_command.h | 4 +- src/qemu/qemu_driver.c | 12 +- src/qemu/qemu_hotplug.c | 12 +- src/qemu/qemu_migration.c | 24 ++-- src/qemu/qemu_process.c | 12 +- src/qemu/qemu_process.h | 2 +- src/util/macvtap.c | 388 ++++++++++++++++++++++--------------------- src/util/macvtap.h | 100 ++++++----- tests/qemuxml2argvtest.c | 2 +- tests/qemuxmlnstest.c | 2 +- 14 files changed, 308 insertions(+), 292 deletions(-)
(unless otherwise noted, all of my reviews in this series included a successful run of make && make check && make syntax-check) Looks fairly mechanical. ACK.

From: "Daniel P. Berrange" <berrange@redhat.com> Rename the macvtap.c file to virnetdevmacvlan.c to reflect its functionality. Move the port profile association code out into virnetdevvportprofile.c. Make the APIs available unconditionally to callers * src/util/macvtap.h: rename to src/util/virnetdevmacvlan.h, * src/util/macvtap.c: rename to src/util/virnetdevmacvlan.c * src/util/virnetdevvportprofile.c, src/util/virnetdevvportprofile.h: Pull in vport association code * src/Makefile.am, src/conf/domain_conf.h, src/qemu/qemu_conf.c, src/qemu/qemu_conf.h, src/qemu/qemu_driver.c: Update include paths & remove conditional compilation --- po/POTFILES.in | 3 +- src/Makefile.am | 2 +- src/conf/domain_conf.h | 2 +- src/qemu/qemu_command.c | 11 - src/qemu/qemu_conf.c | 1 - src/qemu/qemu_conf.h | 1 - src/qemu/qemu_driver.c | 1 - src/qemu/qemu_hotplug.c | 2 - src/qemu/qemu_migration.c | 5 - src/qemu/qemu_process.c | 2 - src/util/macvtap.c | 1209 ---------------------------- src/util/virnetdevmacvlan.c | 423 ++++++++++ src/util/{macvtap.h => virnetdevmacvlan.h} | 38 +- src/util/virnetdevvportprofile.c | 823 +++++++++++++++++++ src/util/virnetdevvportprofile.h | 33 +- 15 files changed, 1283 insertions(+), 1273 deletions(-) delete mode 100644 src/util/macvtap.c create mode 100644 src/util/virnetdevmacvlan.c rename src/util/{macvtap.h => virnetdevmacvlan.h} (63%) diff --git a/po/POTFILES.in b/po/POTFILES.in index 810cf68..6797298 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -115,7 +115,6 @@ src/util/iohelper.c src/util/interface.c src/util/iptables.c src/util/json.c -src/util/macvtap.c src/util/netlink.c src/util/pci.c src/util/processinfo.c @@ -128,7 +127,9 @@ src/util/viraudit.c src/util/virfile.c src/util/virnetdev.c src/util/virnetdevbridge.c +src/util/virnetdevmacvlan.c src/util/virnetdevtap.c +src/util/virnetdevvportprofile.c src/util/virpidfile.c src/util/virsocketaddr.c src/util/virterror.c diff --git a/src/Makefile.am b/src/Makefile.am index fbe4c4d..e44c53a 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -67,7 +67,6 @@ UTIL_SOURCES = \ util/dnsmasq.c util/dnsmasq.h \ util/json.c util/json.h \ util/logging.c util/logging.h \ - util/macvtap.c util/macvtap.h \ util/memory.c util/memory.h \ util/netlink.c util/netlink.h \ util/pci.c util/pci.h \ @@ -95,6 +94,7 @@ UTIL_SOURCES = \ util/virnetdev.h util/virnetdev.c \ util/virnetdevbandwidth.h util/virnetdevbandwidth.c \ util/virnetdevbridge.h util/virnetdevbridge.c \ + util/virnetdevmacvlan.c util/virnetdevmacvlan.h \ util/virnetdevtap.h util/virnetdevtap.c \ util/virnetdevveth.h util/virnetdevveth.c \ util/virnetdevvportprofile.h util/virnetdevvportprofile.c \ diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index c360674..9528199 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -38,7 +38,7 @@ # include "virsocketaddr.h" # include "nwfilter_params.h" # include "nwfilter_conf.h" -# include "macvtap.h" +# include "virnetdevmacvlan.h" # include "sysinfo.h" # include "virnetdevvportprofile.h" # include "virnetdevbandwidth.h" diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index db65035..4514713 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -141,7 +141,6 @@ qemuPhysIfaceConnect(virDomainDefPtr def, enum virNetDevVPortProfileOp vmop) { int rc; -#if WITH_MACVTAP char *res_ifname = NULL; int vnet_hdr = 0; @@ -163,16 +162,6 @@ qemuPhysIfaceConnect(virDomainDefPtr def, net->ifname = res_ifname; } -#else - (void)def; - (void)net; - (void)qemuCaps; - (void)driver; - (void)vmop; - qemuReportError(VIR_ERR_INTERNAL_ERROR, - "%s", _("No support for macvtap device")); - rc = -1; -#endif return rc; } diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c index d7e9d7d..9d93371 100644 --- a/src/qemu/qemu_conf.c +++ b/src/qemu/qemu_conf.c @@ -49,7 +49,6 @@ #include "xml.h" #include "nodeinfo.h" #include "logging.h" -#include "macvtap.h" #include "cpu/cpu.h" #include "domain_nwfilter.h" #include "virfile.h" diff --git a/src/qemu/qemu_conf.h b/src/qemu/qemu_conf.h index bbe7e74..e13cd08 100644 --- a/src/qemu/qemu_conf.h +++ b/src/qemu/qemu_conf.h @@ -39,7 +39,6 @@ # include "cpu_conf.h" # include "driver.h" # include "bitmap.h" -# include "macvtap.h" # include "command.h" # include "threadpool.h" # include "locking/lock_manager.h" diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 3e5cbf6..fe2ab85 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -77,7 +77,6 @@ #include "libvirt_internal.h" #include "xml.h" #include "cpu/cpu.h" -#include "macvtap.h" #include "sysinfo.h" #include "domain_nwfilter.h" #include "hooks.h" diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c index 47ece57..bbcf9ca 100644 --- a/src/qemu/qemu_hotplug.c +++ b/src/qemu/qemu_hotplug.c @@ -1909,7 +1909,6 @@ int qemuDomainDetachNetDevice(struct qemud_driver *driver, virDomainConfNWFilterTeardown(detach); -#if WITH_MACVTAP if (virDomainNetGetActualType(detach) == VIR_DOMAIN_NET_TYPE_DIRECT) { ignore_value(virNetDevMacVLanDelete(detach->ifname, detach->mac, virDomainNetGetActualDirectDev(detach), @@ -1918,7 +1917,6 @@ int qemuDomainDetachNetDevice(struct qemud_driver *driver, driver->stateDir)); VIR_FREE(detach->ifname); } -#endif if ((driver->macFilter) && (detach->ifname != NULL)) { if ((errno = networkDisallowMacOnPort(driver, diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c index 2525210..3b50fc6 100644 --- a/src/qemu/qemu_migration.c +++ b/src/qemu/qemu_migration.c @@ -2512,7 +2512,6 @@ qemuMigrationPerform(struct qemud_driver *driver, } } -#if WITH_MACVTAP static void qemuMigrationVPAssociatePortProfiles(virDomainDefPtr def) { int i; @@ -2547,10 +2546,6 @@ err_exit: } } } -#else /* !WITH_MACVTAP */ -static void -qemuMigrationVPAssociatePortProfiles(virDomainDefPtr def ATTRIBUTE_UNUSED) { } -#endif /* WITH_MACVTAP */ virDomainPtr diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c index 4dc9357..f4096f8 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -3410,7 +3410,6 @@ void qemuProcessStop(struct qemud_driver *driver, def = vm->def; for (i = 0; i < def->nnets; i++) { virDomainNetDefPtr net = def->nets[i]; -#if WITH_MACVTAP if (virDomainNetGetActualType(net) == VIR_DOMAIN_NET_TYPE_DIRECT) { ignore_value(virNetDevMacVLanDelete(net->ifname, net->mac, virDomainNetGetActualDirectDev(net), @@ -3419,7 +3418,6 @@ void qemuProcessStop(struct qemud_driver *driver, driver->stateDir)); VIR_FREE(net->ifname); } -#endif /* release the physical device (or any other resources used by * this interface in the network driver */ diff --git a/src/util/macvtap.c b/src/util/macvtap.c deleted file mode 100644 index c793493..0000000 --- a/src/util/macvtap.c +++ /dev/null @@ -1,1209 +0,0 @@ -/* - * Copyright (C) 2010-2011 Red Hat, Inc. - * Copyright (C) 2010 IBM Corporation - * - * 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 - * - * Authors: - * Stefan Berger <stefanb@us.ibm.com> - * - * Notes: - * netlink: http://lovezutto.googlepages.com/netlink.pdf - * iproute2 package - * - */ - -#include <config.h> - -#include <stdint.h> - -#if WITH_MACVTAP || WITH_VIRTUALPORT - -# include <stdio.h> -# include <errno.h> -# include <fcntl.h> -# include <c-ctype.h> -# include <sys/socket.h> -# include <sys/ioctl.h> - -# include <linux/if.h> -# include <linux/if_tun.h> - -/* Older kernels lacked this enum value. */ -# if !HAVE_DECL_MACVLAN_MODE_PASSTHRU -# define MACVLAN_MODE_PASSTHRU 8 -# endif - -#endif /* WITH_MACVTAP || WITH_VIRTUALPORT */ - -#include "util.h" -#include "macvtap.h" -#include "virnetdev.h" - -VIR_ENUM_IMPL(virNetDevMacVLanMode, VIR_NETDEV_MACVLAN_MODE_LAST, - "vepa", - "private", - "bridge", - "passthrough") - -#if WITH_MACVTAP || WITH_VIRTUALPORT - -# include "memory.h" -# include "logging.h" -# include "interface.h" -# include "virterror_internal.h" -# include "uuid.h" -# include "virfile.h" -# include "netlink.h" - -# define VIR_FROM_THIS VIR_FROM_NET - -# define macvtapError(code, ...) \ - virReportErrorHelper(VIR_FROM_NET, code, __FILE__, \ - __FUNCTION__, __LINE__, __VA_ARGS__) - -# define MACVTAP_NAME_PREFIX "macvtap" -# define MACVTAP_NAME_PATTERN "macvtap%d" - -# define MICROSEC_PER_SEC (1000 * 1000) - -# define NLMSGBUF_SIZE 256 -# define RATTBUF_SIZE 64 - -# define STATUS_POLL_TIMEOUT_USEC (10 * MICROSEC_PER_SEC) -# define STATUS_POLL_INTERVL_USEC (MICROSEC_PER_SEC / 8) - - -# define LLDPAD_PID_FILE "/var/run/lldpad.pid" - - -enum virNetDevVPortProfileLinkOp { - VIR_NETDEV_VPORT_PROFILE_LINK_OP_ASSOCIATE = 0x1, - VIR_NETDEV_VPORT_PROFILE_LINK_OP_DISASSOCIATE = 0x2, - VIR_NETDEV_VPORT_PROFILE_LINK_OP_PREASSOCIATE = 0x3, - VIR_NETDEV_VPORT_PROFILE_LINK_OP_PREASSOCIATE_RR = 0x4, -}; - - - - -# if WITH_MACVTAP - -/** - * virNetDevMacVLanTapOpen: - * Open the macvtap's tap device. - * @ifname: Name of the macvtap interface - * @retries : Number of retries in case udev for example may need to be - * waited for to create the tap chardev - * Returns negative value in case of error, the file descriptor otherwise. - */ -static -int virNetDevMacVLanTapOpen(const char *ifname, - int retries) -{ - FILE *file; - char path[64]; - int ifindex; - char tapname[50]; - int tapfd; - - if (snprintf(path, sizeof(path), - "/sys/class/net/%s/ifindex", ifname) >= sizeof(path)) { - virReportSystemError(errno, - "%s", - _("buffer for ifindex path is too small")); - return -1; - } - - file = fopen(path, "r"); - - if (!file) { - virReportSystemError(errno, - _("cannot open macvtap file %s to determine " - "interface index"), path); - return -1; - } - - if (fscanf(file, "%d", &ifindex) != 1) { - virReportSystemError(errno, - "%s",_("cannot determine macvtap's tap device " - "interface index")); - VIR_FORCE_FCLOSE(file); - return -1; - } - - VIR_FORCE_FCLOSE(file); - - if (snprintf(tapname, sizeof(tapname), - "/dev/tap%d", ifindex) >= sizeof(tapname)) { - virReportSystemError(errno, - "%s", - _("internal buffer for tap device is too small")); - return -1; - } - - while (1) { - /* may need to wait for udev to be done */ - tapfd = open(tapname, O_RDWR); - if (tapfd < 0 && retries > 0) { - retries--; - usleep(20000); - continue; - } - break; - } - - if (tapfd < 0) - virReportSystemError(errno, - _("cannot open macvtap tap device %s"), - tapname); - - return tapfd; -} - - -/** - * virNetDevMacVLanTapSetup: - * @tapfd: file descriptor of the macvtap tap - * @vnet_hdr: 1 to enable IFF_VNET_HDR, 0 to disable it - * - * Returns 0 on success, -1 in case of fatal error, error code otherwise. - * - * Turn the IFF_VNET_HDR flag, if requested and available, make sure - * it's off in the other cases. - * A fatal error is defined as the VNET_HDR flag being set but it cannot - * be turned off for some reason. This is reported with -1. Other fatal - * error is not being able to read the interface flags. In that case the - * macvtap device should not be used. - */ -static int -virNetDevMacVLanTapSetup(int tapfd, int vnet_hdr) -{ - unsigned int features; - struct ifreq ifreq; - short new_flags = 0; - int rc_on_fail = 0; - const char *errmsg = NULL; - - memset(&ifreq, 0, sizeof(ifreq)); - - if (ioctl(tapfd, TUNGETIFF, &ifreq) < 0) { - virReportSystemError(errno, "%s", - _("cannot get interface flags on macvtap tap")); - return -1; - } - - new_flags = ifreq.ifr_flags; - - if ((ifreq.ifr_flags & IFF_VNET_HDR) && !vnet_hdr) { - new_flags = ifreq.ifr_flags & ~IFF_VNET_HDR; - rc_on_fail = -1; - errmsg = _("cannot clean IFF_VNET_HDR flag on macvtap tap"); - } else if ((ifreq.ifr_flags & IFF_VNET_HDR) == 0 && vnet_hdr) { - if (ioctl(tapfd, TUNGETFEATURES, &features) < 0) { - virReportSystemError(errno, "%s", - _("cannot get feature flags on macvtap tap")); - return -1; - } - if ((features & IFF_VNET_HDR)) { - new_flags = ifreq.ifr_flags | IFF_VNET_HDR; - errmsg = _("cannot set IFF_VNET_HDR flag on macvtap tap"); - } - } - - if (new_flags != ifreq.ifr_flags) { - ifreq.ifr_flags = new_flags; - if (ioctl(tapfd, TUNSETIFF, &ifreq) < 0) { - virReportSystemError(errno, "%s", errmsg); - return rc_on_fail; - } - } - - return 0; -} - - -static const uint32_t modeMap[VIR_NETDEV_MACVLAN_MODE_LAST] = { - [VIR_NETDEV_MACVLAN_MODE_VEPA] = MACVLAN_MODE_VEPA, - [VIR_NETDEV_MACVLAN_MODE_PRIVATE] = MACVLAN_MODE_PRIVATE, - [VIR_NETDEV_MACVLAN_MODE_BRIDGE] = MACVLAN_MODE_BRIDGE, - [VIR_NETDEV_MACVLAN_MODE_PASSTHRU] = MACVLAN_MODE_PASSTHRU, -}; - -/** - * virNetDevMacVLanCreate: - * Create an instance of a macvtap device and open its tap character - * device. - * @tgifname: Interface name that the macvtap is supposed to have. May - * be NULL if this function is supposed to choose a name - * @macaddress: The MAC address for the macvtap device - * @linkdev: The interface name of the NIC to connect to the external bridge - * @mode: int describing the mode for 'bridge', 'vepa', 'private' or 'passthru'. - * @vnet_hdr: 1 to enable IFF_VNET_HDR, 0 to disable it - * @vmuuid: The UUID of the VM the macvtap belongs to - * @virtPortProfile: pointer to object holding the virtual port profile data - * @res_ifname: Pointer to a string pointer where the actual name of the - * interface will be stored into if everything succeeded. It is up - * to the caller to free the string. - * - * Returns file descriptor of the tap device in case of success, - * negative value otherwise with error reported. - * - */ -int virNetDevMacVLanCreate(const char *tgifname, - const unsigned char *macaddress, - const char *linkdev, - enum virNetDevMacVLanMode mode, - int vnet_hdr, - const unsigned char *vmuuid, - virNetDevVPortProfilePtr virtPortProfile, - char **res_ifname, - enum virNetDevVPortProfileOp vmOp, - char *stateDir, - virNetDevBandwidthPtr bandwidth) -{ - const char *type = "macvtap"; - int c, rc; - char ifname[IFNAMSIZ]; - int retries, do_retry = 0; - uint32_t macvtapMode; - const char *cr_ifname; - int ifindex; - - macvtapMode = modeMap[mode]; - - *res_ifname = NULL; - - VIR_DEBUG("%s: VM OPERATION: %s", __FUNCTION__, virNetDevVPortProfileOpTypeToString(vmOp)); - - /** Note: When using PASSTHROUGH mode with MACVTAP devices the link - * device's MAC address must be set to the VMs MAC address. In - * order to not confuse the first switch or bridge in line this MAC - * address must be reset when the VM is shut down. - * This is especially important when using SRIOV capable cards that - * emulate their switch in firmware. - */ - if (mode == VIR_NETDEV_MACVLAN_MODE_PASSTHRU) { - if (ifaceReplaceMacAddress(macaddress, linkdev, stateDir) < 0) { - return -1; - } - } - - if (tgifname) { - if(ifaceGetIndex(false, tgifname, &ifindex) == 0) { - if (STRPREFIX(tgifname, - MACVTAP_NAME_PREFIX)) { - goto create_name; - } - virReportSystemError(errno, - _("Interface %s already exists"), tgifname); - return -1; - } - cr_ifname = tgifname; - rc = ifaceMacvtapLinkAdd(type, macaddress, 6, tgifname, linkdev, - macvtapMode, &do_retry); - if (rc < 0) - return -1; - } else { -create_name: - retries = 5; - for (c = 0; c < 8192; c++) { - snprintf(ifname, sizeof(ifname), MACVTAP_NAME_PATTERN, c); - if (ifaceGetIndex(false, ifname, &ifindex) == -ENODEV) { - rc = ifaceMacvtapLinkAdd(type, macaddress, 6, ifname, linkdev, - macvtapMode, &do_retry); - if (rc == 0) - break; - - if (do_retry && --retries) - continue; - return -1; - } - } - cr_ifname = ifname; - } - - if (virNetDevVPortProfileAssociate(cr_ifname, - virtPortProfile, - macaddress, - linkdev, - vmuuid, vmOp) < 0) { - rc = -1; - goto link_del_exit; - } - - if (virNetDevSetOnline(cr_ifname, true) < 0) { - rc = -1; - goto disassociate_exit; - } - - rc = virNetDevMacVLanTapOpen(cr_ifname, 10); - if (rc >= 0) { - if (virNetDevMacVLanTapSetup(rc, vnet_hdr) < 0) { - VIR_FORCE_CLOSE(rc); /* sets rc to -1 */ - goto disassociate_exit; - } - *res_ifname = strdup(cr_ifname); - } else - goto disassociate_exit; - - if (virNetDevBandwidthSet(cr_ifname, bandwidth) < 0) { - macvtapError(VIR_ERR_INTERNAL_ERROR, - _("cannot set bandwidth limits on %s"), - cr_ifname); - rc = -1; - goto disassociate_exit; - } - - - return rc; - -disassociate_exit: - ignore_value(virNetDevVPortProfileDisassociate(cr_ifname, - virtPortProfile, - macaddress, - linkdev, - vmOp)); - -link_del_exit: - ifaceLinkDel(cr_ifname); - - return rc; -} - - -/** - * delMacvtap: - * @ifname : The name of the macvtap interface - * @linkdev: The interface name of the NIC to connect to the external bridge - * @virtPortProfile: pointer to object holding the virtual port profile data - * - * Delete an interface given its name. Disassociate - * it with the switch if port profile parameters - * were provided. - */ -int virNetDevMacVLanDelete(const char *ifname, - const unsigned char *macaddr, - const char *linkdev, - int mode, - virNetDevVPortProfilePtr virtPortProfile, - char *stateDir) -{ - int ret = 0; - if (mode == VIR_NETDEV_MACVLAN_MODE_PASSTHRU) { - ifaceRestoreMacAddress(linkdev, stateDir); - } - - if (ifname) { - if (virNetDevVPortProfileDisassociate(ifname, - virtPortProfile, - macaddr, - linkdev, - VIR_NETDEV_VPORT_PROFILE_OP_DESTROY) < 0) - ret = -1; - if (ifaceLinkDel(ifname) < 0) - ret = -1; - } - return ret; -} - -# endif /* WITH_MACVTAP */ - -# ifdef IFLA_PORT_MAX - -static struct nla_policy ifla_port_policy[IFLA_PORT_MAX + 1] = -{ - [IFLA_PORT_RESPONSE] = { .type = NLA_U16 }, -}; - - -static uint32_t -virNetDevVPortProfileGetLldpadPid(void) { - int fd; - uint32_t pid = 0; - - fd = open(LLDPAD_PID_FILE, O_RDONLY); - if (fd >= 0) { - char buffer[10]; - - if (saferead(fd, buffer, sizeof(buffer)) <= sizeof(buffer)) { - unsigned int res; - char *endptr; - - if (virStrToLong_ui(buffer, &endptr, 10, &res) == 0 - && (*endptr == '\0' || c_isspace(*endptr)) - && res != 0) { - pid = res; - } else { - macvtapError(VIR_ERR_INTERNAL_ERROR, "%s", - _("error parsing pid of lldpad")); - } - } - } else { - virReportSystemError(errno, - _("Error opening file %s"), LLDPAD_PID_FILE); - } - - VIR_FORCE_CLOSE(fd); - - return pid; -} - - -/** - * virNetDevVPortProfileGetStatus: - * - * tb: top level netlink response attributes + values - * vf: The virtual function used in the request - * instanceId: instanceId of the interface (vm uuid in case of 802.1Qbh) - * is8021Qbg: whether this function is call for 8021Qbg - * status: pointer to a uint16 where the status will be written into - * - * Get the status from the IFLA_PORT_RESPONSE field; Returns 0 in - * case of success, < 0 otherwise with error having been reported - */ -static int -virNetDevVPortProfileGetStatus(struct nlattr **tb, int32_t vf, - const unsigned char *instanceId, - bool nltarget_kernel, - bool is8021Qbg, - uint16_t *status) -{ - int rc = -1; - const char *msg = NULL; - struct nlattr *tb_port[IFLA_PORT_MAX + 1] = { NULL, }; - - if (vf == PORT_SELF_VF && nltarget_kernel) { - if (tb[IFLA_PORT_SELF]) { - if (nla_parse_nested(tb_port, IFLA_PORT_MAX, tb[IFLA_PORT_SELF], - ifla_port_policy)) { - msg = _("error parsing IFLA_PORT_SELF part"); - goto err_exit; - } - } else { - msg = _("IFLA_PORT_SELF is missing"); - goto err_exit; - } - } else { - if (tb[IFLA_VF_PORTS]) { - int rem; - bool found = false; - struct nlattr *tb_vf_ports = { NULL, }; - - nla_for_each_nested(tb_vf_ports, tb[IFLA_VF_PORTS], rem) { - - if (nla_type(tb_vf_ports) != IFLA_VF_PORT) { - msg = _("error while iterating over IFLA_VF_PORTS part"); - goto err_exit; - } - - if (nla_parse_nested(tb_port, IFLA_PORT_MAX, tb_vf_ports, - ifla_port_policy)) { - msg = _("error parsing IFLA_VF_PORT part"); - goto err_exit; - } - - if (instanceId && - tb_port[IFLA_PORT_INSTANCE_UUID] && - !memcmp(instanceId, - (unsigned char *) - RTA_DATA(tb_port[IFLA_PORT_INSTANCE_UUID]), - VIR_UUID_BUFLEN) && - tb_port[IFLA_PORT_VF] && - vf == *(uint32_t *)RTA_DATA(tb_port[IFLA_PORT_VF])) { - found = true; - break; - } - } - - if (!found) { - msg = _("Could not find netlink response with " - "expected parameters"); - goto err_exit; - } - } else { - msg = _("IFLA_VF_PORTS is missing"); - goto err_exit; - } - } - - if (tb_port[IFLA_PORT_RESPONSE]) { - *status = *(uint16_t *)RTA_DATA(tb_port[IFLA_PORT_RESPONSE]); - rc = 0; - } else { - if (is8021Qbg) { - /* no in-progress here; may be missing */ - *status = PORT_PROFILE_RESPONSE_INPROGRESS; - rc = 0; - } else { - msg = _("no IFLA_PORT_RESPONSE found in netlink message"); - goto err_exit; - } - } - -err_exit: - if (msg) - macvtapError(VIR_ERR_INTERNAL_ERROR, "%s", msg); - - return rc; -} - - -static int -virNetDevVPortProfileOpSetLink(const char *ifname, int ifindex, - bool nltarget_kernel, - const unsigned char *macaddr, - int vlanid, - const char *profileId, - struct ifla_port_vsi *portVsi, - const unsigned char *instanceId, - const unsigned char *hostUUID, - int32_t vf, - uint8_t op) -{ - int rc = -1; - struct nlmsghdr *resp; - struct nlmsgerr *err; - struct ifinfomsg ifinfo = { - .ifi_family = AF_UNSPEC, - .ifi_index = ifindex, - }; - unsigned char *recvbuf = NULL; - unsigned int recvbuflen = 0; - uint32_t pid = 0; - struct nl_msg *nl_msg; - struct nlattr *vfports = NULL, *vfport; - - nl_msg = nlmsg_alloc_simple(RTM_SETLINK, NLM_F_REQUEST); - if (!nl_msg) { - virReportOOMError(); - return rc; - } - - if (nlmsg_append(nl_msg, &ifinfo, sizeof(ifinfo), NLMSG_ALIGNTO) < 0) - goto buffer_too_small; - - if (ifname && - nla_put(nl_msg, IFLA_IFNAME, strlen(ifname)+1, ifname) < 0) - goto buffer_too_small; - - if (macaddr || vlanid >= 0) { - struct nlattr *vfinfolist, *vfinfo; - - if (!(vfinfolist = nla_nest_start(nl_msg, IFLA_VFINFO_LIST))) - goto buffer_too_small; - - if (!(vfinfo = nla_nest_start(nl_msg, IFLA_VF_INFO))) - goto buffer_too_small; - - if (macaddr) { - struct ifla_vf_mac ifla_vf_mac = { - .vf = vf, - .mac = { 0, }, - }; - - memcpy(ifla_vf_mac.mac, macaddr, 6); - - if (nla_put(nl_msg, IFLA_VF_MAC, sizeof(ifla_vf_mac), - &ifla_vf_mac) < 0) - goto buffer_too_small; - } - - if (vlanid >= 0) { - struct ifla_vf_vlan ifla_vf_vlan = { - .vf = vf, - .vlan = vlanid, - .qos = 0, - }; - - if (nla_put(nl_msg, IFLA_VF_VLAN, sizeof(ifla_vf_vlan), - &ifla_vf_vlan) < 0) - goto buffer_too_small; - } - - nla_nest_end(nl_msg, vfinfo); - nla_nest_end(nl_msg, vfinfolist); - } - - if (vf == PORT_SELF_VF && nltarget_kernel) { - if (!(vfport = nla_nest_start(nl_msg, IFLA_PORT_SELF))) - goto buffer_too_small; - } else { - if (!(vfports = nla_nest_start(nl_msg, IFLA_VF_PORTS))) - goto buffer_too_small; - - /* begin nesting vfports */ - if (!(vfport = nla_nest_start(nl_msg, IFLA_VF_PORT))) - goto buffer_too_small; - } - - if (profileId) { - if (nla_put(nl_msg, IFLA_PORT_PROFILE, strlen(profileId) + 1, - profileId) < 0) - goto buffer_too_small; - } - - if (portVsi) { - if (nla_put(nl_msg, IFLA_PORT_VSI_TYPE, sizeof(*portVsi), - portVsi) < 0) - goto buffer_too_small; - } - - if (instanceId) { - if (nla_put(nl_msg, IFLA_PORT_INSTANCE_UUID, VIR_UUID_BUFLEN, - instanceId) < 0) - goto buffer_too_small; - } - - if (hostUUID) { - if (nla_put(nl_msg, IFLA_PORT_HOST_UUID, VIR_UUID_BUFLEN, - hostUUID) < 0) - goto buffer_too_small; - } - - if (vf != PORT_SELF_VF) { - if (nla_put(nl_msg, IFLA_PORT_VF, sizeof(vf), &vf) < 0) - goto buffer_too_small; - } - - if (nla_put(nl_msg, IFLA_PORT_REQUEST, sizeof(op), &op) < 0) - goto buffer_too_small; - - /* end nesting of vport */ - nla_nest_end(nl_msg, vfport); - - if (vfports) { - /* end nesting of vfports */ - nla_nest_end(nl_msg, vfports); - } - - if (!nltarget_kernel) { - pid = virNetDevVPortProfileGetLldpadPid(); - if (pid == 0) - goto err_exit; - } - - if (nlComm(nl_msg, &recvbuf, &recvbuflen, pid) < 0) - goto err_exit; - - if (recvbuflen < NLMSG_LENGTH(0) || recvbuf == NULL) - goto malformed_resp; - - resp = (struct nlmsghdr *)recvbuf; - - switch (resp->nlmsg_type) { - case NLMSG_ERROR: - err = (struct nlmsgerr *)NLMSG_DATA(resp); - if (resp->nlmsg_len < NLMSG_LENGTH(sizeof(*err))) - goto malformed_resp; - - if (err->error) { - virReportSystemError(-err->error, - _("error during virtual port configuration of ifindex %d"), - ifindex); - goto err_exit; - } - break; - - case NLMSG_DONE: - break; - - default: - goto malformed_resp; - } - - rc = 0; - -err_exit: - nlmsg_free(nl_msg); - - VIR_FREE(recvbuf); - - return rc; - -malformed_resp: - nlmsg_free(nl_msg); - - macvtapError(VIR_ERR_INTERNAL_ERROR, "%s", - _("malformed netlink response message")); - VIR_FREE(recvbuf); - return rc; - -buffer_too_small: - nlmsg_free(nl_msg); - - macvtapError(VIR_ERR_INTERNAL_ERROR, "%s", - _("allocated netlink buffer is too small")); - return rc; -} - - -/* Returns 0 on success, -1 on general failure, and -2 on timeout */ -static int -virNetDevVPortProfileOpCommon(const char *ifname, int ifindex, - bool nltarget_kernel, - const unsigned char *macaddr, - int vlanid, - const char *profileId, - struct ifla_port_vsi *portVsi, - const unsigned char *instanceId, - const unsigned char *hostUUID, - int32_t vf, - uint8_t op) -{ - int rc; - unsigned char *recvbuf = NULL; - struct nlattr *tb[IFLA_MAX + 1] = { NULL , }; - int repeats = STATUS_POLL_TIMEOUT_USEC / STATUS_POLL_INTERVL_USEC; - uint16_t status = 0; - bool is8021Qbg = (profileId == NULL); - - rc = virNetDevVPortProfileOpSetLink(ifname, ifindex, - nltarget_kernel, - macaddr, - vlanid, - profileId, - portVsi, - instanceId, - hostUUID, - vf, - op); - if (rc < 0) { - macvtapError(VIR_ERR_INTERNAL_ERROR, "%s", - _("sending of PortProfileRequest failed.")); - return rc; - } - - while (--repeats >= 0) { - rc = ifaceMacvtapLinkDump(nltarget_kernel, NULL, ifindex, tb, - &recvbuf, virNetDevVPortProfileGetLldpadPid); - if (rc < 0) - goto err_exit; - - rc = virNetDevVPortProfileGetStatus(tb, vf, instanceId, nltarget_kernel, - is8021Qbg, &status); - if (rc < 0) - goto err_exit; - if (status == PORT_PROFILE_RESPONSE_SUCCESS || - status == PORT_VDP_RESPONSE_SUCCESS) { - break; - } else if (status == PORT_PROFILE_RESPONSE_INPROGRESS) { - /* keep trying... */ - } else { - virReportSystemError(EINVAL, - _("error %d during port-profile setlink on " - "interface %s (%d)"), - status, ifname, ifindex); - rc = -1; - break; - } - - usleep(STATUS_POLL_INTERVL_USEC); - - VIR_FREE(recvbuf); - } - - if (status == PORT_PROFILE_RESPONSE_INPROGRESS) { - macvtapError(VIR_ERR_INTERNAL_ERROR, "%s", - _("port-profile setlink timed out")); - rc = -2; - } - -err_exit: - VIR_FREE(recvbuf); - - return rc; -} - -# endif /* IFLA_PORT_MAX */ - - -# ifdef IFLA_VF_PORT_MAX - -static int -virNetDevVPortProfileGetPhysdevAndVlan(const char *ifname, int *root_ifindex, char *root_ifname, - int *vlanid) -{ - int ret; - unsigned int nth; - int ifindex = -1; - - *vlanid = -1; - while (1) { - if ((ret = ifaceGetNthParent(ifindex, ifname, 1, - root_ifindex, root_ifname, &nth)) < 0) - return ret; - if (nth == 0) - break; - if (*vlanid == -1) { - if (ifaceGetVlanID(root_ifname, vlanid) < 0) - *vlanid = -1; - } - - ifindex = *root_ifindex; - ifname = NULL; - } - - return 0; -} - -# endif - -/* Returns 0 on success, -1 on general failure, and -2 on timeout */ -static int -virNetDevVPortProfileOp8021Qbg(const char *ifname, - const unsigned char *macaddr, - const virNetDevVPortProfilePtr virtPort, - enum virNetDevVPortProfileLinkOp virtPortOp) -{ - int rc = 0; - -# ifndef IFLA_VF_PORT_MAX - - (void)ifname; - (void)macaddr; - (void)virtPort; - (void)virtPortOp; - macvtapError(VIR_ERR_INTERNAL_ERROR, "%s", - _("Kernel VF Port support was missing at compile time.")); - rc = -1; - -# else /* IFLA_VF_PORT_MAX */ - - int op = PORT_REQUEST_ASSOCIATE; - struct ifla_port_vsi portVsi = { - .vsi_mgr_id = virtPort->u.virtPort8021Qbg.managerID, - .vsi_type_version = virtPort->u.virtPort8021Qbg.typeIDVersion, - }; - bool nltarget_kernel = false; - int vlanid; - int physdev_ifindex = 0; - char physdev_ifname[IFNAMSIZ] = { 0, }; - int vf = PORT_SELF_VF; - - if (virNetDevVPortProfileGetPhysdevAndVlan(ifname, &physdev_ifindex, physdev_ifname, - &vlanid) < 0) { - rc = -1; - goto err_exit; - } - - if (vlanid < 0) - vlanid = 0; - - portVsi.vsi_type_id[2] = virtPort->u.virtPort8021Qbg.typeID >> 16; - portVsi.vsi_type_id[1] = virtPort->u.virtPort8021Qbg.typeID >> 8; - portVsi.vsi_type_id[0] = virtPort->u.virtPort8021Qbg.typeID; - - switch (virtPortOp) { - case VIR_NETDEV_VPORT_PROFILE_LINK_OP_PREASSOCIATE: - op = PORT_REQUEST_PREASSOCIATE; - break; - case VIR_NETDEV_VPORT_PROFILE_LINK_OP_ASSOCIATE: - op = PORT_REQUEST_ASSOCIATE; - break; - case VIR_NETDEV_VPORT_PROFILE_LINK_OP_DISASSOCIATE: - op = PORT_REQUEST_DISASSOCIATE; - break; - default: - macvtapError(VIR_ERR_INTERNAL_ERROR, - _("operation type %d not supported"), virtPortOp); - rc = -1; - goto err_exit; - } - - rc = virNetDevVPortProfileOpCommon(physdev_ifname, physdev_ifindex, - nltarget_kernel, - macaddr, - vlanid, - NULL, - &portVsi, - virtPort->u.virtPort8021Qbg.instanceID, - NULL, - vf, - op); - -err_exit: - -# endif /* IFLA_VF_PORT_MAX */ - - return rc; -} - - -# ifdef IFLA_VF_PORT_MAX -static int -virNetDevVPortProfileGetPhysfnDev(const char *linkdev, - int32_t *vf, - char **physfndev) -{ - int rc = -1; - - if (ifaceIsVirtualFunction(linkdev) == 1) { - /* if linkdev is SR-IOV VF, then set vf = VF index */ - /* and set linkdev = PF device */ - - rc = ifaceGetPhysicalFunction(linkdev, physfndev); - if (!rc) - rc = ifaceGetVirtualFunctionIndex(*physfndev, linkdev, vf); - } else { - - /* Not SR-IOV VF: physfndev is linkdev and VF index - * refers to linkdev self - */ - - *vf = PORT_SELF_VF; - *physfndev = strdup(linkdev); - if (!*physfndev) { - virReportOOMError(); - goto err_exit; - } - rc = 0; - } - -err_exit: - - return rc; -} -# endif /* IFLA_VF_PORT_MAX */ - -/* Returns 0 on success, -1 on general failure, and -2 on timeout */ -static int -virNetDevVPortProfileOp8021Qbh(const char *ifname, - const unsigned char *macaddr, - const virNetDevVPortProfilePtr virtPort, - const unsigned char *vm_uuid, - enum virNetDevVPortProfileLinkOp virtPortOp) -{ - int rc = 0; - -# ifndef IFLA_VF_PORT_MAX - - (void)ifname; - (void)macaddr; - (void)virtPort; - (void)vm_uuid; - (void)virtPortOp; - macvtapError(VIR_ERR_INTERNAL_ERROR, "%s", - _("Kernel VF Port support was missing at compile time.")); - rc = -1; - -# else /* IFLA_VF_PORT_MAX */ - - char *physfndev = NULL; - unsigned char hostuuid[VIR_UUID_BUFLEN]; - int32_t vf; - bool nltarget_kernel = true; - int ifindex; - int vlanid = -1; - - rc = virNetDevVPortProfileGetPhysfnDev(ifname, &vf, &physfndev); - if (rc < 0) - goto err_exit; - - rc = ifaceGetIndex(true, physfndev, &ifindex); - if (rc < 0) - goto err_exit; - - switch (virtPortOp) { - case VIR_NETDEV_VPORT_PROFILE_LINK_OP_PREASSOCIATE_RR: - case VIR_NETDEV_VPORT_PROFILE_LINK_OP_ASSOCIATE: - errno = virGetHostUUID(hostuuid); - if (errno) { - rc = -1; - goto err_exit; - } - - rc = virNetDevVPortProfileOpCommon(NULL, ifindex, - nltarget_kernel, - macaddr, - vlanid, - virtPort->u.virtPort8021Qbh.profileID, - NULL, - vm_uuid, - hostuuid, - vf, - (virtPortOp == VIR_NETDEV_VPORT_PROFILE_LINK_OP_PREASSOCIATE_RR) ? - PORT_REQUEST_PREASSOCIATE_RR - : PORT_REQUEST_ASSOCIATE); - if (rc == -2) - /* Association timed out, disassociate */ - virNetDevVPortProfileOpCommon(NULL, ifindex, - nltarget_kernel, - NULL, - vlanid, - NULL, - NULL, - NULL, - NULL, - vf, - PORT_REQUEST_DISASSOCIATE); - break; - - case VIR_NETDEV_VPORT_PROFILE_LINK_OP_DISASSOCIATE: - rc = virNetDevVPortProfileOpCommon(NULL, ifindex, - nltarget_kernel, - NULL, - vlanid, - NULL, - NULL, - NULL, - NULL, - vf, - PORT_REQUEST_DISASSOCIATE); - break; - - default: - macvtapError(VIR_ERR_INTERNAL_ERROR, - _("operation type %d not supported"), virtPortOp); - rc = -1; - } - -err_exit: - VIR_FREE(physfndev); - -# endif /* IFLA_VF_PORT_MAX */ - - return rc; -} - -/** - * virNetDevVPortProfileAssociate: - * - * @macvtap_ifname: The name of the macvtap device - * @virtPort: pointer to the object holding port profile parameters - * @vmuuid : the UUID of the virtual machine - * @vmOp : The VM operation (i.e., create, no-op) - * - * Associate a port on a swtich with a profile. This function - * may notify a kernel driver or an external daemon to run - * the setup protocol. If profile parameters were not supplied - * by the user, then this function returns without doing - * anything. - * - * Returns 0 in case of success, < 0 otherwise with error - * having been reported. - */ -int -virNetDevVPortProfileAssociate(const char *macvtap_ifname, - const virNetDevVPortProfilePtr virtPort, - const unsigned char *macvtap_macaddr, - const char *linkdev, - const unsigned char *vmuuid, - enum virNetDevVPortProfileOp vmOp) -{ - int rc = 0; - - VIR_DEBUG("Associating port profile '%p' on link device '%s'", - virtPort, macvtap_ifname); - - VIR_DEBUG("%s: VM OPERATION: %s", __FUNCTION__, virNetDevVPortProfileOpTypeToString(vmOp)); - - if (!virtPort || vmOp == VIR_NETDEV_VPORT_PROFILE_OP_NO_OP) - return 0; - - switch (virtPort->virtPortType) { - case VIR_NETDEV_VPORT_PROFILE_NONE: - case VIR_NETDEV_VPORT_PROFILE_LAST: - break; - - case VIR_NETDEV_VPORT_PROFILE_8021QBG: - rc = virNetDevVPortProfileOp8021Qbg(macvtap_ifname, macvtap_macaddr, - virtPort, - (vmOp == VIR_NETDEV_VPORT_PROFILE_OP_MIGRATE_IN_START) - ? VIR_NETDEV_VPORT_PROFILE_LINK_OP_PREASSOCIATE - : VIR_NETDEV_VPORT_PROFILE_LINK_OP_ASSOCIATE); - break; - - case VIR_NETDEV_VPORT_PROFILE_8021QBH: - rc = virNetDevVPortProfileOp8021Qbh(linkdev, macvtap_macaddr, - virtPort, vmuuid, - (vmOp == VIR_NETDEV_VPORT_PROFILE_OP_MIGRATE_IN_START) - ? VIR_NETDEV_VPORT_PROFILE_LINK_OP_PREASSOCIATE_RR - : VIR_NETDEV_VPORT_PROFILE_LINK_OP_ASSOCIATE); - if (vmOp != VIR_NETDEV_VPORT_PROFILE_OP_MIGRATE_IN_START && !rc) { - /* XXX bogus error handling */ - ignore_value(virNetDevSetOnline(linkdev, true)); - } - - break; - } - - return rc; -} - - -/** - * virNetDevVPortProfileDisassociate: - * - * @macvtap_ifname: The name of the macvtap device - * @macvtap_macaddr : The MAC address of the macvtap - * @linkdev: The link device in case of macvtap - * @virtPort: point to object holding port profile parameters - * - * Returns 0 in case of success, != 0 otherwise with error - * having been reported. - */ -int -virNetDevVPortProfileDisassociate(const char *macvtap_ifname, - const virNetDevVPortProfilePtr virtPort, - const unsigned char *macvtap_macaddr, - const char *linkdev, - enum virNetDevVPortProfileOp vmOp) -{ - int rc = 0; - - VIR_DEBUG("Disassociating port profile id '%p' on link device '%s' ", - virtPort, macvtap_ifname); - - VIR_DEBUG("%s: VM OPERATION: %s", __FUNCTION__, virNetDevVPortProfileOpTypeToString(vmOp)); - - if (!virtPort) - return 0; - - switch (virtPort->virtPortType) { - case VIR_NETDEV_VPORT_PROFILE_NONE: - case VIR_NETDEV_VPORT_PROFILE_LAST: - break; - - case VIR_NETDEV_VPORT_PROFILE_8021QBG: - rc = virNetDevVPortProfileOp8021Qbg(macvtap_ifname, macvtap_macaddr, - virtPort, VIR_NETDEV_VPORT_PROFILE_LINK_OP_DISASSOCIATE); - break; - - case VIR_NETDEV_VPORT_PROFILE_8021QBH: - /* avoid disassociating twice */ - if (vmOp == VIR_NETDEV_VPORT_PROFILE_OP_MIGRATE_IN_FINISH) - break; - ignore_value(virNetDevSetOnline(linkdev, false)); - rc = virNetDevVPortProfileOp8021Qbh(linkdev, macvtap_macaddr, - virtPort, NULL, - VIR_NETDEV_VPORT_PROFILE_LINK_OP_DISASSOCIATE); - break; - } - - return rc; -} - -#endif /* WITH_MACVTAP || WITH_VIRTUALPORT */ - -VIR_ENUM_IMPL(virNetDevVPortProfileOp, VIR_NETDEV_VPORT_PROFILE_OP_LAST, - "create", - "save", - "restore", - "destroy", - "migrate out", - "migrate in start", - "migrate in finish", - "no-op") diff --git a/src/util/virnetdevmacvlan.c b/src/util/virnetdevmacvlan.c new file mode 100644 index 0000000..ab111f0 --- /dev/null +++ b/src/util/virnetdevmacvlan.c @@ -0,0 +1,423 @@ +/* + * Copyright (C) 2010-2011 Red Hat, Inc. + * Copyright (C) 2010 IBM Corporation + * + * 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 + * + * Authors: + * Stefan Berger <stefanb@us.ibm.com> + * + * Notes: + * netlink: http://lovezutto.googlepages.com/netlink.pdf + * iproute2 package + * + */ + +#include <config.h> + + +#include "virnetdevmacvlan.h" +#include "util.h" +#include "virterror_internal.h" + +#define VIR_FROM_THIS VIR_FROM_NET + +#define macvtapError(code, ...) \ + virReportErrorHelper(VIR_FROM_NET, code, __FILE__, \ + __FUNCTION__, __LINE__, __VA_ARGS__) + + +VIR_ENUM_IMPL(virNetDevMacVLanMode, VIR_NETDEV_MACVLAN_MODE_LAST, + "vepa", + "private", + "bridge", + "passthrough") + +#if WITH_MACVTAP + +# include <stdint.h> +# include <stdio.h> +# include <errno.h> +# include <fcntl.h> +# include <sys/socket.h> +# include <sys/ioctl.h> + +# include <linux/if.h> +# include <linux/if_tun.h> + +/* Older kernels lacked this enum value. */ +# if !HAVE_DECL_MACVLAN_MODE_PASSTHRU +# define MACVLAN_MODE_PASSTHRU 8 +# endif + +# include "memory.h" +# include "logging.h" +# include "interface.h" +# include "uuid.h" +# include "virfile.h" +# include "netlink.h" +# include "virnetdev.h" + +# define MACVTAP_NAME_PREFIX "macvtap" +# define MACVTAP_NAME_PATTERN "macvtap%d" + +/** + * virNetDevMacVLanTapOpen: + * Open the macvtap's tap device. + * @ifname: Name of the macvtap interface + * @retries : Number of retries in case udev for example may need to be + * waited for to create the tap chardev + * Returns negative value in case of error, the file descriptor otherwise. + */ +static +int virNetDevMacVLanTapOpen(const char *ifname, + int retries) +{ + FILE *file; + char path[64]; + int ifindex; + char tapname[50]; + int tapfd; + + if (snprintf(path, sizeof(path), + "/sys/class/net/%s/ifindex", ifname) >= sizeof(path)) { + virReportSystemError(errno, + "%s", + _("buffer for ifindex path is too small")); + return -1; + } + + file = fopen(path, "r"); + + if (!file) { + virReportSystemError(errno, + _("cannot open macvtap file %s to determine " + "interface index"), path); + return -1; + } + + if (fscanf(file, "%d", &ifindex) != 1) { + virReportSystemError(errno, + "%s",_("cannot determine macvtap's tap device " + "interface index")); + VIR_FORCE_FCLOSE(file); + return -1; + } + + VIR_FORCE_FCLOSE(file); + + if (snprintf(tapname, sizeof(tapname), + "/dev/tap%d", ifindex) >= sizeof(tapname)) { + virReportSystemError(errno, + "%s", + _("internal buffer for tap device is too small")); + return -1; + } + + while (1) { + /* may need to wait for udev to be done */ + tapfd = open(tapname, O_RDWR); + if (tapfd < 0 && retries > 0) { + retries--; + usleep(20000); + continue; + } + break; + } + + if (tapfd < 0) + virReportSystemError(errno, + _("cannot open macvtap tap device %s"), + tapname); + + return tapfd; +} + + +/** + * virNetDevMacVLanTapSetup: + * @tapfd: file descriptor of the macvtap tap + * @vnet_hdr: 1 to enable IFF_VNET_HDR, 0 to disable it + * + * Returns 0 on success, -1 in case of fatal error, error code otherwise. + * + * Turn the IFF_VNET_HDR flag, if requested and available, make sure + * it's off in the other cases. + * A fatal error is defined as the VNET_HDR flag being set but it cannot + * be turned off for some reason. This is reported with -1. Other fatal + * error is not being able to read the interface flags. In that case the + * macvtap device should not be used. + */ +static int +virNetDevMacVLanTapSetup(int tapfd, int vnet_hdr) +{ + unsigned int features; + struct ifreq ifreq; + short new_flags = 0; + int rc_on_fail = 0; + const char *errmsg = NULL; + + memset(&ifreq, 0, sizeof(ifreq)); + + if (ioctl(tapfd, TUNGETIFF, &ifreq) < 0) { + virReportSystemError(errno, "%s", + _("cannot get interface flags on macvtap tap")); + return -1; + } + + new_flags = ifreq.ifr_flags; + + if ((ifreq.ifr_flags & IFF_VNET_HDR) && !vnet_hdr) { + new_flags = ifreq.ifr_flags & ~IFF_VNET_HDR; + rc_on_fail = -1; + errmsg = _("cannot clean IFF_VNET_HDR flag on macvtap tap"); + } else if ((ifreq.ifr_flags & IFF_VNET_HDR) == 0 && vnet_hdr) { + if (ioctl(tapfd, TUNGETFEATURES, &features) < 0) { + virReportSystemError(errno, "%s", + _("cannot get feature flags on macvtap tap")); + return -1; + } + if ((features & IFF_VNET_HDR)) { + new_flags = ifreq.ifr_flags | IFF_VNET_HDR; + errmsg = _("cannot set IFF_VNET_HDR flag on macvtap tap"); + } + } + + if (new_flags != ifreq.ifr_flags) { + ifreq.ifr_flags = new_flags; + if (ioctl(tapfd, TUNSETIFF, &ifreq) < 0) { + virReportSystemError(errno, "%s", errmsg); + return rc_on_fail; + } + } + + return 0; +} + + +static const uint32_t modeMap[VIR_NETDEV_MACVLAN_MODE_LAST] = { + [VIR_NETDEV_MACVLAN_MODE_VEPA] = MACVLAN_MODE_VEPA, + [VIR_NETDEV_MACVLAN_MODE_PRIVATE] = MACVLAN_MODE_PRIVATE, + [VIR_NETDEV_MACVLAN_MODE_BRIDGE] = MACVLAN_MODE_BRIDGE, + [VIR_NETDEV_MACVLAN_MODE_PASSTHRU] = MACVLAN_MODE_PASSTHRU, +}; + +/** + * virNetDevMacVLanCreate: + * Create an instance of a macvtap device and open its tap character + * device. + * @tgifname: Interface name that the macvtap is supposed to have. May + * be NULL if this function is supposed to choose a name + * @macaddress: The MAC address for the macvtap device + * @linkdev: The interface name of the NIC to connect to the external bridge + * @mode: int describing the mode for 'bridge', 'vepa', 'private' or 'passthru'. + * @vnet_hdr: 1 to enable IFF_VNET_HDR, 0 to disable it + * @vmuuid: The UUID of the VM the macvtap belongs to + * @virtPortProfile: pointer to object holding the virtual port profile data + * @res_ifname: Pointer to a string pointer where the actual name of the + * interface will be stored into if everything succeeded. It is up + * to the caller to free the string. + * + * Returns file descriptor of the tap device in case of success, + * negative value otherwise with error reported. + * + */ +int virNetDevMacVLanCreate(const char *tgifname, + const unsigned char *macaddress, + const char *linkdev, + enum virNetDevMacVLanMode mode, + int vnet_hdr, + const unsigned char *vmuuid, + virNetDevVPortProfilePtr virtPortProfile, + char **res_ifname, + enum virNetDevVPortProfileOp vmOp, + char *stateDir, + virNetDevBandwidthPtr bandwidth) +{ + const char *type = "macvtap"; + int c, rc; + char ifname[IFNAMSIZ]; + int retries, do_retry = 0; + uint32_t macvtapMode; + const char *cr_ifname; + int ifindex; + + macvtapMode = modeMap[mode]; + + *res_ifname = NULL; + + VIR_DEBUG("%s: VM OPERATION: %s", __FUNCTION__, virNetDevVPortProfileOpTypeToString(vmOp)); + + /** Note: When using PASSTHROUGH mode with MACVTAP devices the link + * device's MAC address must be set to the VMs MAC address. In + * order to not confuse the first switch or bridge in line this MAC + * address must be reset when the VM is shut down. + * This is especially important when using SRIOV capable cards that + * emulate their switch in firmware. + */ + if (mode == VIR_NETDEV_MACVLAN_MODE_PASSTHRU) { + if (ifaceReplaceMacAddress(macaddress, linkdev, stateDir) < 0) { + return -1; + } + } + + if (tgifname) { + if(ifaceGetIndex(false, tgifname, &ifindex) == 0) { + if (STRPREFIX(tgifname, + MACVTAP_NAME_PREFIX)) { + goto create_name; + } + virReportSystemError(errno, + _("Interface %s already exists"), tgifname); + return -1; + } + cr_ifname = tgifname; + rc = ifaceMacvtapLinkAdd(type, macaddress, 6, tgifname, linkdev, + macvtapMode, &do_retry); + if (rc < 0) + return -1; + } else { +create_name: + retries = 5; + for (c = 0; c < 8192; c++) { + snprintf(ifname, sizeof(ifname), MACVTAP_NAME_PATTERN, c); + if (ifaceGetIndex(false, ifname, &ifindex) == -ENODEV) { + rc = ifaceMacvtapLinkAdd(type, macaddress, 6, ifname, linkdev, + macvtapMode, &do_retry); + if (rc == 0) + break; + + if (do_retry && --retries) + continue; + return -1; + } + } + cr_ifname = ifname; + } + + if (virNetDevVPortProfileAssociate(cr_ifname, + virtPortProfile, + macaddress, + linkdev, + vmuuid, vmOp) < 0) { + rc = -1; + goto link_del_exit; + } + + if (virNetDevSetOnline(cr_ifname, true) < 0) { + rc = -1; + goto disassociate_exit; + } + + rc = virNetDevMacVLanTapOpen(cr_ifname, 10); + if (rc >= 0) { + if (virNetDevMacVLanTapSetup(rc, vnet_hdr) < 0) { + VIR_FORCE_CLOSE(rc); /* sets rc to -1 */ + goto disassociate_exit; + } + *res_ifname = strdup(cr_ifname); + } else + goto disassociate_exit; + + if (virNetDevBandwidthSet(cr_ifname, bandwidth) < 0) { + macvtapError(VIR_ERR_INTERNAL_ERROR, + _("cannot set bandwidth limits on %s"), + cr_ifname); + rc = -1; + goto disassociate_exit; + } + + + return rc; + +disassociate_exit: + ignore_value(virNetDevVPortProfileDisassociate(cr_ifname, + virtPortProfile, + macaddress, + linkdev, + vmOp)); + +link_del_exit: + ifaceLinkDel(cr_ifname); + + return rc; +} + + +/** + * delMacvtap: + * @ifname : The name of the macvtap interface + * @linkdev: The interface name of the NIC to connect to the external bridge + * @virtPortProfile: pointer to object holding the virtual port profile data + * + * Delete an interface given its name. Disassociate + * it with the switch if port profile parameters + * were provided. + */ +int virNetDevMacVLanDelete(const char *ifname, + const unsigned char *macaddr, + const char *linkdev, + int mode, + virNetDevVPortProfilePtr virtPortProfile, + char *stateDir) +{ + int ret = 0; + if (mode == VIR_NETDEV_MACVLAN_MODE_PASSTHRU) { + ifaceRestoreMacAddress(linkdev, stateDir); + } + + if (ifname) { + if (virNetDevVPortProfileDisassociate(ifname, + virtPortProfile, + macaddr, + linkdev, + VIR_NETDEV_VPORT_PROFILE_OP_DESTROY) < 0) + ret = -1; + if (ifaceLinkDel(ifname) < 0) + ret = -1; + } + return ret; +} + +#else /* ! WITH_MACVTAP */ +int virNetDevMacVLanCreate(const char *ifname ATTRIBUTE_UNUSED, + const unsigned char *macaddress ATTRIBUTE_UNUSED, + const char *linkdev ATTRIBUTE_UNUSED, + enum virNetDevMacVLanMode mode ATTRIBUTE_UNUSED, + int vnet_hdr ATTRIBUTE_UNUSED, + const unsigned char *vmuuid ATTRIBUTE_UNUSED, + virNetDevVPortProfilePtr virtPortProfile ATTRIBUTE_UNUSED, + char **res_ifname ATTRIBUTE_UNUSED, + enum virNetDevVPortProfileOp vmop ATTRIBUTE_UNUSED, + char *stateDir ATTRIBUTE_UNUSED, + virNetDevBandwidthPtr bandwidth ATTRIBUTE_UNUSED) +{ + virReportSystemError(ENOSYS, "%s", + _("Cannot create macvlan devices on this platform")); + return -1; +} + +int virNetDevMacVLanDelete(const char *ifname ATTRIBUTE_UNUSED, + const unsigned char *macaddress ATTRIBUTE_UNUSED, + const char *linkdev ATTRIBUTE_UNUSED, + int mode ATTRIBUTE_UNUSED, + virNetDevVPortProfilePtr virtPortProfile ATTRIBUTE_UNUSED, + char *stateDir ATTRIBUTE_UNUSED) +{ + virReportSystemError(ENOSYS, "%s", + _("Cannot create macvlan devices on this platform")); + return -1; +} +#endif /* ! WITH_MACVTAP */ diff --git a/src/util/macvtap.h b/src/util/virnetdevmacvlan.h similarity index 63% rename from src/util/macvtap.h rename to src/util/virnetdevmacvlan.h index 5c5d84a..f3277f9 100644 --- a/src/util/macvtap.h +++ b/src/util/virnetdevmacvlan.h @@ -37,21 +37,7 @@ enum virNetDevMacVLanMode { VIR_NETDEV_MACVLAN_MODE_LAST, }; - -enum virNetDevVPortProfileOp { - VIR_NETDEV_VPORT_PROFILE_OP_CREATE, - VIR_NETDEV_VPORT_PROFILE_OP_SAVE, - VIR_NETDEV_VPORT_PROFILE_OP_RESTORE, - VIR_NETDEV_VPORT_PROFILE_OP_DESTROY, - VIR_NETDEV_VPORT_PROFILE_OP_MIGRATE_OUT, - VIR_NETDEV_VPORT_PROFILE_OP_MIGRATE_IN_START, - VIR_NETDEV_VPORT_PROFILE_OP_MIGRATE_IN_FINISH, - VIR_NETDEV_VPORT_PROFILE_OP_NO_OP, - - VIR_NETDEV_VPORT_PROFILE_OP_LAST -}; - -# if WITH_MACVTAP +VIR_ENUM_DECL(virNetDevMacVLanMode) int virNetDevMacVLanCreate(const char *ifname, const unsigned char *macaddress, @@ -76,26 +62,4 @@ int virNetDevMacVLanDelete(const char *ifname, ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3) ATTRIBUTE_NONNULL(6) ATTRIBUTE_RETURN_CHECK; -int virNetDevVPortProfileAssociate(const char *ifname, - const virNetDevVPortProfilePtr virtPort, - const unsigned char *macaddr, - const char *linkdev, - const unsigned char *vmuuid, - enum virNetDevVPortProfileOp vmOp) - ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(3) ATTRIBUTE_NONNULL(4) - ATTRIBUTE_NONNULL(5) ATTRIBUTE_RETURN_CHECK; - -int virNetDevVPortProfileDisassociate(const char *ifname, - const virNetDevVPortProfilePtr virtPort, - const unsigned char *macaddr, - const char *linkdev, - enum virNetDevVPortProfileOp vmOp) - ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(3) ATTRIBUTE_NONNULL(4) - ATTRIBUTE_RETURN_CHECK; - -# endif /* WITH_MACVTAP */ - -VIR_ENUM_DECL(virNetDevVPortProfileOp) -VIR_ENUM_DECL(virNetDevMacVLanMode) - #endif /* __UTIL_MACVTAP_H__ */ diff --git a/src/util/virnetdevvportprofile.c b/src/util/virnetdevvportprofile.c index 6aecd52..ec86e2c 100644 --- a/src/util/virnetdevvportprofile.c +++ b/src/util/virnetdevvportprofile.c @@ -23,6 +23,65 @@ #include <config.h> #include "virnetdevvportprofile.h" +#include "virterror_internal.h" + +#define VIR_FROM_THIS VIR_FROM_NET + +#define virNetDevError(code, ...) \ + virReportErrorHelper(VIR_FROM_NET, code, __FILE__, \ + __FUNCTION__, __LINE__, __VA_ARGS__) + + +VIR_ENUM_IMPL(virNetDevVPortProfileOp, VIR_NETDEV_VPORT_PROFILE_OP_LAST, + "create", + "save", + "restore", + "destroy", + "migrate out", + "migrate in start", + "migrate in finish", + "no-op") + +#if WITH_VIRTUALPORT + +# include <stdint.h> +# include <stdio.h> +# include <errno.h> +# include <fcntl.h> +# include <c-ctype.h> +# include <sys/socket.h> +# include <sys/ioctl.h> + +# include <linux/if.h> +# include <linux/if_tun.h> + +# include "netlink.h" +# include "virfile.h" +# include "memory.h" +# include "interface.h" +# include "logging.h" +# include "virnetdev.h" + +# define MICROSEC_PER_SEC (1000 * 1000) + +# define NLMSGBUF_SIZE 256 +# define RATTBUF_SIZE 64 + + +# define STATUS_POLL_TIMEOUT_USEC (10 * MICROSEC_PER_SEC) +# define STATUS_POLL_INTERVL_USEC (MICROSEC_PER_SEC / 8) + +# define LLDPAD_PID_FILE "/var/run/lldpad.pid" + + +enum virNetDevVPortProfileLinkOp { + VIR_NETDEV_VPORT_PROFILE_LINK_OP_ASSOCIATE = 0x1, + VIR_NETDEV_VPORT_PROFILE_LINK_OP_DISASSOCIATE = 0x2, + VIR_NETDEV_VPORT_PROFILE_LINK_OP_PREASSOCIATE = 0x3, + VIR_NETDEV_VPORT_PROFILE_LINK_OP_PREASSOCIATE_RR = 0x4, +}; + +#endif bool virNetDevVPortProfileEqual(virNetDevVPortProfilePtr a, virNetDevVPortProfilePtr b) @@ -60,3 +119,767 @@ virNetDevVPortProfileEqual(virNetDevVPortProfilePtr a, virNetDevVPortProfilePtr return true; } + + +#ifdef WITH_VIRTUALPORT + +static struct nla_policy ifla_port_policy[IFLA_PORT_MAX + 1] = +{ + [IFLA_PORT_RESPONSE] = { .type = NLA_U16 }, +}; + + +static uint32_t +virNetDevVPortProfileGetLldpadPid(void) { + int fd; + uint32_t pid = 0; + + fd = open(LLDPAD_PID_FILE, O_RDONLY); + if (fd >= 0) { + char buffer[10]; + + if (saferead(fd, buffer, sizeof(buffer)) <= sizeof(buffer)) { + unsigned int res; + char *endptr; + + if (virStrToLong_ui(buffer, &endptr, 10, &res) == 0 + && (*endptr == '\0' || c_isspace(*endptr)) + && res != 0) { + pid = res; + } else { + virNetDevError(VIR_ERR_INTERNAL_ERROR, "%s", + _("error parsing pid of lldpad")); + } + } + } else { + virReportSystemError(errno, + _("Error opening file %s"), LLDPAD_PID_FILE); + } + + VIR_FORCE_CLOSE(fd); + + return pid; +} + + +/** + * virNetDevVPortProfileGetStatus: + * + * tb: top level netlink response attributes + values + * vf: The virtual function used in the request + * instanceId: instanceId of the interface (vm uuid in case of 802.1Qbh) + * is8021Qbg: whether this function is call for 8021Qbg + * status: pointer to a uint16 where the status will be written into + * + * Get the status from the IFLA_PORT_RESPONSE field; Returns 0 in + * case of success, < 0 otherwise with error having been reported + */ +static int +virNetDevVPortProfileGetStatus(struct nlattr **tb, int32_t vf, + const unsigned char *instanceId, + bool nltarget_kernel, + bool is8021Qbg, + uint16_t *status) +{ + int rc = -1; + const char *msg = NULL; + struct nlattr *tb_port[IFLA_PORT_MAX + 1] = { NULL, }; + + if (vf == PORT_SELF_VF && nltarget_kernel) { + if (tb[IFLA_PORT_SELF]) { + if (nla_parse_nested(tb_port, IFLA_PORT_MAX, tb[IFLA_PORT_SELF], + ifla_port_policy)) { + msg = _("error parsing IFLA_PORT_SELF part"); + goto err_exit; + } + } else { + msg = _("IFLA_PORT_SELF is missing"); + goto err_exit; + } + } else { + if (tb[IFLA_VF_PORTS]) { + int rem; + bool found = false; + struct nlattr *tb_vf_ports = { NULL, }; + + nla_for_each_nested(tb_vf_ports, tb[IFLA_VF_PORTS], rem) { + + if (nla_type(tb_vf_ports) != IFLA_VF_PORT) { + msg = _("error while iterating over IFLA_VF_PORTS part"); + goto err_exit; + } + + if (nla_parse_nested(tb_port, IFLA_PORT_MAX, tb_vf_ports, + ifla_port_policy)) { + msg = _("error parsing IFLA_VF_PORT part"); + goto err_exit; + } + + if (instanceId && + tb_port[IFLA_PORT_INSTANCE_UUID] && + !memcmp(instanceId, + (unsigned char *) + RTA_DATA(tb_port[IFLA_PORT_INSTANCE_UUID]), + VIR_UUID_BUFLEN) && + tb_port[IFLA_PORT_VF] && + vf == *(uint32_t *)RTA_DATA(tb_port[IFLA_PORT_VF])) { + found = true; + break; + } + } + + if (!found) { + msg = _("Could not find netlink response with " + "expected parameters"); + goto err_exit; + } + } else { + msg = _("IFLA_VF_PORTS is missing"); + goto err_exit; + } + } + + if (tb_port[IFLA_PORT_RESPONSE]) { + *status = *(uint16_t *)RTA_DATA(tb_port[IFLA_PORT_RESPONSE]); + rc = 0; + } else { + if (is8021Qbg) { + /* no in-progress here; may be missing */ + *status = PORT_PROFILE_RESPONSE_INPROGRESS; + rc = 0; + } else { + msg = _("no IFLA_PORT_RESPONSE found in netlink message"); + goto err_exit; + } + } + +err_exit: + if (msg) + virNetDevError(VIR_ERR_INTERNAL_ERROR, "%s", msg); + + return rc; +} + + +static int +virNetDevVPortProfileOpSetLink(const char *ifname, int ifindex, + bool nltarget_kernel, + const unsigned char *macaddr, + int vlanid, + const char *profileId, + struct ifla_port_vsi *portVsi, + const unsigned char *instanceId, + const unsigned char *hostUUID, + int32_t vf, + uint8_t op) +{ + int rc = -1; + struct nlmsghdr *resp; + struct nlmsgerr *err; + struct ifinfomsg ifinfo = { + .ifi_family = AF_UNSPEC, + .ifi_index = ifindex, + }; + unsigned char *recvbuf = NULL; + unsigned int recvbuflen = 0; + uint32_t pid = 0; + struct nl_msg *nl_msg; + struct nlattr *vfports = NULL, *vfport; + + nl_msg = nlmsg_alloc_simple(RTM_SETLINK, NLM_F_REQUEST); + if (!nl_msg) { + virReportOOMError(); + return rc; + } + + if (nlmsg_append(nl_msg, &ifinfo, sizeof(ifinfo), NLMSG_ALIGNTO) < 0) + goto buffer_too_small; + + if (ifname && + nla_put(nl_msg, IFLA_IFNAME, strlen(ifname)+1, ifname) < 0) + goto buffer_too_small; + + if (macaddr || vlanid >= 0) { + struct nlattr *vfinfolist, *vfinfo; + + if (!(vfinfolist = nla_nest_start(nl_msg, IFLA_VFINFO_LIST))) + goto buffer_too_small; + + if (!(vfinfo = nla_nest_start(nl_msg, IFLA_VF_INFO))) + goto buffer_too_small; + + if (macaddr) { + struct ifla_vf_mac ifla_vf_mac = { + .vf = vf, + .mac = { 0, }, + }; + + memcpy(ifla_vf_mac.mac, macaddr, 6); + + if (nla_put(nl_msg, IFLA_VF_MAC, sizeof(ifla_vf_mac), + &ifla_vf_mac) < 0) + goto buffer_too_small; + } + + if (vlanid >= 0) { + struct ifla_vf_vlan ifla_vf_vlan = { + .vf = vf, + .vlan = vlanid, + .qos = 0, + }; + + if (nla_put(nl_msg, IFLA_VF_VLAN, sizeof(ifla_vf_vlan), + &ifla_vf_vlan) < 0) + goto buffer_too_small; + } + + nla_nest_end(nl_msg, vfinfo); + nla_nest_end(nl_msg, vfinfolist); + } + + if (vf == PORT_SELF_VF && nltarget_kernel) { + if (!(vfport = nla_nest_start(nl_msg, IFLA_PORT_SELF))) + goto buffer_too_small; + } else { + if (!(vfports = nla_nest_start(nl_msg, IFLA_VF_PORTS))) + goto buffer_too_small; + + /* begin nesting vfports */ + if (!(vfport = nla_nest_start(nl_msg, IFLA_VF_PORT))) + goto buffer_too_small; + } + + if (profileId) { + if (nla_put(nl_msg, IFLA_PORT_PROFILE, strlen(profileId) + 1, + profileId) < 0) + goto buffer_too_small; + } + + if (portVsi) { + if (nla_put(nl_msg, IFLA_PORT_VSI_TYPE, sizeof(*portVsi), + portVsi) < 0) + goto buffer_too_small; + } + + if (instanceId) { + if (nla_put(nl_msg, IFLA_PORT_INSTANCE_UUID, VIR_UUID_BUFLEN, + instanceId) < 0) + goto buffer_too_small; + } + + if (hostUUID) { + if (nla_put(nl_msg, IFLA_PORT_HOST_UUID, VIR_UUID_BUFLEN, + hostUUID) < 0) + goto buffer_too_small; + } + + if (vf != PORT_SELF_VF) { + if (nla_put(nl_msg, IFLA_PORT_VF, sizeof(vf), &vf) < 0) + goto buffer_too_small; + } + + if (nla_put(nl_msg, IFLA_PORT_REQUEST, sizeof(op), &op) < 0) + goto buffer_too_small; + + /* end nesting of vport */ + nla_nest_end(nl_msg, vfport); + + if (vfports) { + /* end nesting of vfports */ + nla_nest_end(nl_msg, vfports); + } + + if (!nltarget_kernel) { + pid = virNetDevVPortProfileGetLldpadPid(); + if (pid == 0) + goto err_exit; + } + + if (nlComm(nl_msg, &recvbuf, &recvbuflen, pid) < 0) + goto err_exit; + + if (recvbuflen < NLMSG_LENGTH(0) || recvbuf == NULL) + goto malformed_resp; + + resp = (struct nlmsghdr *)recvbuf; + + switch (resp->nlmsg_type) { + case NLMSG_ERROR: + err = (struct nlmsgerr *)NLMSG_DATA(resp); + if (resp->nlmsg_len < NLMSG_LENGTH(sizeof(*err))) + goto malformed_resp; + + if (err->error) { + virReportSystemError(-err->error, + _("error during virtual port configuration of ifindex %d"), + ifindex); + goto err_exit; + } + break; + + case NLMSG_DONE: + break; + + default: + goto malformed_resp; + } + + rc = 0; + +err_exit: + nlmsg_free(nl_msg); + + VIR_FREE(recvbuf); + + return rc; + +malformed_resp: + nlmsg_free(nl_msg); + + virNetDevError(VIR_ERR_INTERNAL_ERROR, "%s", + _("malformed netlink response message")); + VIR_FREE(recvbuf); + return rc; + +buffer_too_small: + nlmsg_free(nl_msg); + + virNetDevError(VIR_ERR_INTERNAL_ERROR, "%s", + _("allocated netlink buffer is too small")); + return rc; +} + + +/* Returns 0 on success, -1 on general failure, and -2 on timeout */ +static int +virNetDevVPortProfileOpCommon(const char *ifname, int ifindex, + bool nltarget_kernel, + const unsigned char *macaddr, + int vlanid, + const char *profileId, + struct ifla_port_vsi *portVsi, + const unsigned char *instanceId, + const unsigned char *hostUUID, + int32_t vf, + uint8_t op) +{ + int rc; + unsigned char *recvbuf = NULL; + struct nlattr *tb[IFLA_MAX + 1] = { NULL , }; + int repeats = STATUS_POLL_TIMEOUT_USEC / STATUS_POLL_INTERVL_USEC; + uint16_t status = 0; + bool is8021Qbg = (profileId == NULL); + + rc = virNetDevVPortProfileOpSetLink(ifname, ifindex, + nltarget_kernel, + macaddr, + vlanid, + profileId, + portVsi, + instanceId, + hostUUID, + vf, + op); + if (rc < 0) { + virNetDevError(VIR_ERR_INTERNAL_ERROR, "%s", + _("sending of PortProfileRequest failed.")); + return rc; + } + + while (--repeats >= 0) { + rc = ifaceMacvtapLinkDump(nltarget_kernel, NULL, ifindex, tb, + &recvbuf, virNetDevVPortProfileGetLldpadPid); + if (rc < 0) + goto err_exit; + + rc = virNetDevVPortProfileGetStatus(tb, vf, instanceId, nltarget_kernel, + is8021Qbg, &status); + if (rc < 0) + goto err_exit; + if (status == PORT_PROFILE_RESPONSE_SUCCESS || + status == PORT_VDP_RESPONSE_SUCCESS) { + break; + } else if (status == PORT_PROFILE_RESPONSE_INPROGRESS) { + /* keep trying... */ + } else { + virReportSystemError(EINVAL, + _("error %d during port-profile setlink on " + "interface %s (%d)"), + status, ifname, ifindex); + rc = -1; + break; + } + + usleep(STATUS_POLL_INTERVL_USEC); + + VIR_FREE(recvbuf); + } + + if (status == PORT_PROFILE_RESPONSE_INPROGRESS) { + virNetDevError(VIR_ERR_INTERNAL_ERROR, "%s", + _("port-profile setlink timed out")); + rc = -2; + } + +err_exit: + VIR_FREE(recvbuf); + + return rc; +} + + +static int +virNetDevVPortProfileGetPhysdevAndVlan(const char *ifname, int *root_ifindex, char *root_ifname, + int *vlanid) +{ + int ret; + unsigned int nth; + int ifindex = -1; + + *vlanid = -1; + while (1) { + if ((ret = ifaceGetNthParent(ifindex, ifname, 1, + root_ifindex, root_ifname, &nth)) < 0) + return ret; + if (nth == 0) + break; + if (*vlanid == -1) { + if (ifaceGetVlanID(root_ifname, vlanid) < 0) + *vlanid = -1; + } + + ifindex = *root_ifindex; + ifname = NULL; + } + + return 0; +} + +/* Returns 0 on success, -1 on general failure, and -2 on timeout */ +static int +virNetDevVPortProfileOp8021Qbg(const char *ifname, + const unsigned char *macaddr, + const virNetDevVPortProfilePtr virtPort, + enum virNetDevVPortProfileLinkOp virtPortOp) +{ + int rc = 0; + int op = PORT_REQUEST_ASSOCIATE; + struct ifla_port_vsi portVsi = { + .vsi_mgr_id = virtPort->u.virtPort8021Qbg.managerID, + .vsi_type_version = virtPort->u.virtPort8021Qbg.typeIDVersion, + }; + bool nltarget_kernel = false; + int vlanid; + int physdev_ifindex = 0; + char physdev_ifname[IFNAMSIZ] = { 0, }; + int vf = PORT_SELF_VF; + + if (virNetDevVPortProfileGetPhysdevAndVlan(ifname, &physdev_ifindex, physdev_ifname, + &vlanid) < 0) { + rc = -1; + goto err_exit; + } + + if (vlanid < 0) + vlanid = 0; + + portVsi.vsi_type_id[2] = virtPort->u.virtPort8021Qbg.typeID >> 16; + portVsi.vsi_type_id[1] = virtPort->u.virtPort8021Qbg.typeID >> 8; + portVsi.vsi_type_id[0] = virtPort->u.virtPort8021Qbg.typeID; + + switch (virtPortOp) { + case VIR_NETDEV_VPORT_PROFILE_LINK_OP_PREASSOCIATE: + op = PORT_REQUEST_PREASSOCIATE; + break; + case VIR_NETDEV_VPORT_PROFILE_LINK_OP_ASSOCIATE: + op = PORT_REQUEST_ASSOCIATE; + break; + case VIR_NETDEV_VPORT_PROFILE_LINK_OP_DISASSOCIATE: + op = PORT_REQUEST_DISASSOCIATE; + break; + default: + virNetDevError(VIR_ERR_INTERNAL_ERROR, + _("operation type %d not supported"), virtPortOp); + rc = -1; + goto err_exit; + } + + rc = virNetDevVPortProfileOpCommon(physdev_ifname, physdev_ifindex, + nltarget_kernel, + macaddr, + vlanid, + NULL, + &portVsi, + virtPort->u.virtPort8021Qbg.instanceID, + NULL, + vf, + op); + +err_exit: + + return rc; +} + + +static int +virNetDevVPortProfileGetPhysfnDev(const char *linkdev, + int32_t *vf, + char **physfndev) +{ + int rc = -1; + + if (ifaceIsVirtualFunction(linkdev) == 1) { + /* if linkdev is SR-IOV VF, then set vf = VF index */ + /* and set linkdev = PF device */ + + rc = ifaceGetPhysicalFunction(linkdev, physfndev); + if (!rc) + rc = ifaceGetVirtualFunctionIndex(*physfndev, linkdev, vf); + } else { + + /* Not SR-IOV VF: physfndev is linkdev and VF index + * refers to linkdev self + */ + + *vf = PORT_SELF_VF; + *physfndev = strdup(linkdev); + if (!*physfndev) { + virReportOOMError(); + goto err_exit; + } + rc = 0; + } + +err_exit: + + return rc; +} + + +/* Returns 0 on success, -1 on general failure, and -2 on timeout */ +static int +virNetDevVPortProfileOp8021Qbh(const char *ifname, + const unsigned char *macaddr, + const virNetDevVPortProfilePtr virtPort, + const unsigned char *vm_uuid, + enum virNetDevVPortProfileLinkOp virtPortOp) +{ + int rc = 0; + char *physfndev = NULL; + unsigned char hostuuid[VIR_UUID_BUFLEN]; + int32_t vf; + bool nltarget_kernel = true; + int ifindex; + int vlanid = -1; + + rc = virNetDevVPortProfileGetPhysfnDev(ifname, &vf, &physfndev); + if (rc < 0) + goto err_exit; + + rc = ifaceGetIndex(true, physfndev, &ifindex); + if (rc < 0) + goto err_exit; + + switch (virtPortOp) { + case VIR_NETDEV_VPORT_PROFILE_LINK_OP_PREASSOCIATE_RR: + case VIR_NETDEV_VPORT_PROFILE_LINK_OP_ASSOCIATE: + errno = virGetHostUUID(hostuuid); + if (errno) { + rc = -1; + goto err_exit; + } + + rc = virNetDevVPortProfileOpCommon(NULL, ifindex, + nltarget_kernel, + macaddr, + vlanid, + virtPort->u.virtPort8021Qbh.profileID, + NULL, + vm_uuid, + hostuuid, + vf, + (virtPortOp == + VIR_NETDEV_VPORT_PROFILE_LINK_OP_PREASSOCIATE_RR) ? + PORT_REQUEST_PREASSOCIATE_RR + : PORT_REQUEST_ASSOCIATE); + if (rc == -2) + /* Association timed out, disassociate */ + virNetDevVPortProfileOpCommon(NULL, ifindex, + nltarget_kernel, + NULL, + vlanid, + NULL, + NULL, + NULL, + NULL, + vf, + PORT_REQUEST_DISASSOCIATE); + break; + + case VIR_NETDEV_VPORT_PROFILE_LINK_OP_DISASSOCIATE: + rc = virNetDevVPortProfileOpCommon(NULL, ifindex, + nltarget_kernel, + NULL, + vlanid, + NULL, + NULL, + NULL, + NULL, + vf, + PORT_REQUEST_DISASSOCIATE); + break; + + default: + virNetDevError(VIR_ERR_INTERNAL_ERROR, + _("operation type %d not supported"), virtPortOp); + rc = -1; + } + +err_exit: + VIR_FREE(physfndev); + return rc; +} + +/** + * virNetDevVPortProfileAssociate: + * + * @macvtap_ifname: The name of the macvtap device + * @virtPort: pointer to the object holding port profile parameters + * @vmuuid : the UUID of the virtual machine + * @vmOp : The VM operation (i.e., create, no-op) + * + * Associate a port on a swtich with a profile. This function + * may notify a kernel driver or an external daemon to run + * the setup protocol. If profile parameters were not supplied + * by the user, then this function returns without doing + * anything. + * + * Returns 0 in case of success, < 0 otherwise with error + * having been reported. + */ +int +virNetDevVPortProfileAssociate(const char *macvtap_ifname, + const virNetDevVPortProfilePtr virtPort, + const unsigned char *macvtap_macaddr, + const char *linkdev, + const unsigned char *vmuuid, + enum virNetDevVPortProfileOp vmOp) +{ + int rc = 0; + + VIR_DEBUG("Associating port profile '%p' on link device '%s'", + virtPort, macvtap_ifname); + + VIR_DEBUG("%s: VM OPERATION: %s", __FUNCTION__, virNetDevVPortProfileOpTypeToString(vmOp)); + + if (!virtPort || vmOp == VIR_NETDEV_VPORT_PROFILE_OP_NO_OP) + return 0; + + switch (virtPort->virtPortType) { + case VIR_NETDEV_VPORT_PROFILE_NONE: + case VIR_NETDEV_VPORT_PROFILE_LAST: + break; + + case VIR_NETDEV_VPORT_PROFILE_8021QBG: + rc = virNetDevVPortProfileOp8021Qbg(macvtap_ifname, macvtap_macaddr, + virtPort, + (vmOp == VIR_NETDEV_VPORT_PROFILE_OP_MIGRATE_IN_START) + ? VIR_NETDEV_VPORT_PROFILE_LINK_OP_PREASSOCIATE + : VIR_NETDEV_VPORT_PROFILE_LINK_OP_ASSOCIATE); + break; + + case VIR_NETDEV_VPORT_PROFILE_8021QBH: + rc = virNetDevVPortProfileOp8021Qbh(linkdev, macvtap_macaddr, + virtPort, vmuuid, + (vmOp == VIR_NETDEV_VPORT_PROFILE_OP_MIGRATE_IN_START) + ? VIR_NETDEV_VPORT_PROFILE_LINK_OP_PREASSOCIATE_RR + : VIR_NETDEV_VPORT_PROFILE_LINK_OP_ASSOCIATE); + if (vmOp != VIR_NETDEV_VPORT_PROFILE_OP_MIGRATE_IN_START && !rc) { + /* XXX bogus error handling */ + ignore_value(virNetDevSetOnline(linkdev, true)); + } + + break; + } + + return rc; +} + + +/** + * virNetDevVPortProfileDisassociate: + * + * @macvtap_ifname: The name of the macvtap device + * @macvtap_macaddr : The MAC address of the macvtap + * @linkdev: The link device in case of macvtap + * @virtPort: point to object holding port profile parameters + * + * Returns 0 in case of success, != 0 otherwise with error + * having been reported. + */ +int +virNetDevVPortProfileDisassociate(const char *macvtap_ifname, + const virNetDevVPortProfilePtr virtPort, + const unsigned char *macvtap_macaddr, + const char *linkdev, + enum virNetDevVPortProfileOp vmOp) +{ + int rc = 0; + + VIR_DEBUG("Disassociating port profile id '%p' on link device '%s' ", + virtPort, macvtap_ifname); + + VIR_DEBUG("%s: VM OPERATION: %s", __FUNCTION__, virNetDevVPortProfileOpTypeToString(vmOp)); + + if (!virtPort) + return 0; + + switch (virtPort->virtPortType) { + case VIR_NETDEV_VPORT_PROFILE_NONE: + case VIR_NETDEV_VPORT_PROFILE_LAST: + break; + + case VIR_NETDEV_VPORT_PROFILE_8021QBG: + rc = virNetDevVPortProfileOp8021Qbg(macvtap_ifname, macvtap_macaddr, + virtPort, + VIR_NETDEV_VPORT_PROFILE_LINK_OP_DISASSOCIATE); + break; + + case VIR_NETDEV_VPORT_PROFILE_8021QBH: + /* avoid disassociating twice */ + if (vmOp == VIR_NETDEV_VPORT_PROFILE_OP_MIGRATE_IN_FINISH) + break; + ignore_value(virNetDevSetOnline(linkdev, false)); + rc = virNetDevVPortProfileOp8021Qbh(linkdev, macvtap_macaddr, + virtPort, NULL, + VIR_NETDEV_VPORT_PROFILE_LINK_OP_DISASSOCIATE); + break; + } + + return rc; +} + +#else /* ! WITH_VIRTUALPORT */ +int virNetDevVPortProfileAssociate(const char *macvtap_ifname ATTRIBUTE_UNUSED, + const virNetDevVPortProfilePtr virtPort ATTRIBUTE_UNUSED, + const unsigned char *macvtap_macaddr ATTRIBUTE_UNUSED, + const char *linkdev ATTRIBUTE_UNUSED, + const unsigned char *vmuuid ATTRIBUTE_UNUSED, + enum virNetDevVPortProfileOp vmOp ATTRIBUTE_UNUSED) +{ + virReportSystemError(ENOSYS, "%s", + _("Virtual port profile association not supported on this platform")); + return -1; +} + +int virNetDevVPortProfileDisassociate(const char *macvtap_ifname ATTRIBUTE_UNUSED, + const virNetDevVPortProfilePtr virtPort ATTRIBUTE_UNUSED, + const unsigned char *macvtap_macaddr ATTRIBUTE_UNUSED, + const char *linkdev ATTRIBUTE_UNUSED, + enum virNetDevVPortProfileOp vmOp ATTRIBUTE_UNUSED) +{ + virReportSystemError(ENOSYS, "%s", + _("Virtual port profile association not supported on this platform")); + return -1; +} +#endif /* ! WITH_VIRTUALPORT */ diff --git a/src/util/virnetdevvportprofile.h b/src/util/virnetdevvportprofile.h index 36e8fd7..92df005 100644 --- a/src/util/virnetdevvportprofile.h +++ b/src/util/virnetdevvportprofile.h @@ -36,9 +36,22 @@ enum virNetDevVPortProfile { VIR_NETDEV_VPORT_PROFILE_LAST, }; - VIR_ENUM_DECL(virNetDevVPort) +enum virNetDevVPortProfileOp { + VIR_NETDEV_VPORT_PROFILE_OP_CREATE, + VIR_NETDEV_VPORT_PROFILE_OP_SAVE, + VIR_NETDEV_VPORT_PROFILE_OP_RESTORE, + VIR_NETDEV_VPORT_PROFILE_OP_DESTROY, + VIR_NETDEV_VPORT_PROFILE_OP_MIGRATE_OUT, + VIR_NETDEV_VPORT_PROFILE_OP_MIGRATE_IN_START, + VIR_NETDEV_VPORT_PROFILE_OP_MIGRATE_IN_FINISH, + VIR_NETDEV_VPORT_PROFILE_OP_NO_OP, + + VIR_NETDEV_VPORT_PROFILE_OP_LAST +}; +VIR_ENUM_DECL(virNetDevVPortProfileOp) + /* profile data for macvtap (VEPA) */ typedef struct _virNetDevVPortProfile virNetDevVPortProfile; typedef virNetDevVPortProfile *virNetDevVPortProfilePtr; @@ -61,4 +74,22 @@ struct _virNetDevVPortProfile { bool virNetDevVPortProfileEqual(virNetDevVPortProfilePtr a, virNetDevVPortProfilePtr b); +int virNetDevVPortProfileAssociate(const char *ifname, + const virNetDevVPortProfilePtr virtPort, + const unsigned char *macaddr, + const char *linkdev, + const unsigned char *vmuuid, + enum virNetDevVPortProfileOp vmOp) + ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(3) ATTRIBUTE_NONNULL(4) + ATTRIBUTE_NONNULL(5) ATTRIBUTE_RETURN_CHECK; + +int virNetDevVPortProfileDisassociate(const char *ifname, + const virNetDevVPortProfilePtr virtPort, + const unsigned char *macaddr, + const char *linkdev, + enum virNetDevVPortProfileOp vmOp) + ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(3) ATTRIBUTE_NONNULL(4) + ATTRIBUTE_RETURN_CHECK; + + #endif /* __VIR_NETDEV_VPORT_PROFILE_H__ */ -- 1.7.6.4

On 11/15/2011 06:14 AM, Daniel P. Berrange wrote:
From: "Daniel P. Berrange"<berrange@redhat.com>
Rename the macvtap.c file to virnetdevmacvlan.c to reflect its functionality. Move the port profile association code out into virnetdevvportprofile.c. Make the APIs available unconditionally to callers
One concern I have after reading this sentence - do you changes have any implications for systems that don't have the correct version of libnl, and thus cannot have macvtap enabled? (e.g. RHEL5) Assuming that the answer to the above is "no", and going on faith (and the fact that make && make check passed) that the gigantic diff really is just moving identical code between files (except for removing the #ifdef MACVTAPs in several places) - ACK. (It might be a useful exercise to build on some system with no macvtap|libnl support to make sure nothing blows up).

On Thu, Nov 17, 2011 at 05:49:10AM -0500, Laine Stump wrote:
On 11/15/2011 06:14 AM, Daniel P. Berrange wrote:
From: "Daniel P. Berrange"<berrange@redhat.com>
Rename the macvtap.c file to virnetdevmacvlan.c to reflect its functionality. Move the port profile association code out into virnetdevvportprofile.c. Make the APIs available unconditionally to callers
One concern I have after reading this sentence - do you changes have any implications for systems that don't have the correct version of libnl, and thus cannot have macvtap enabled? (e.g. RHEL5)
Assuming that the answer to the above is "no", and going on faith (and the fact that make && make check passed) that the gigantic diff really is just moving identical code between files (except for removing the #ifdef MACVTAPs in several places) - ACK.
The goal of this entire series, is that all *header* files definitions should be unconditionally available. The idea is that callers (eg the QEMU driver) can then avoid be littered with conditionals like #ifdef MACVTAP The implementation source files will be the sole place where the conditionals live, in the #else clauses providing stubs for every API which simply raise a libvirt error with ENOSYS Overall this should make our code more robust wrt the various different conditional compile options Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|

From: "Daniel P. Berrange" <berrange@redhat.com> Rename virNetDevMacVLanCreate to virNetDevMacVLanCreateWithVPortProfile and virNetDevMacVLanDelete to virNetDevMacVLanDeleteWithVPortProfile To make way for renaming the other macvlan creation APIs in interface.c * util/virnetdevmacvlan.c, util/virnetdevmacvlan.h, qemu/qemu_command.c, qemu/qemu_hotplug.c, qemu/qemu_process.c: Rename APIs --- src/qemu/qemu_command.c | 17 +++++----- src/qemu/qemu_hotplug.c | 11 +++--- src/qemu/qemu_process.c | 11 +++--- src/util/virnetdevmacvlan.c | 72 +++++++++++++++++++++--------------------- src/util/virnetdevmacvlan.h | 34 ++++++++++---------- 5 files changed, 74 insertions(+), 71 deletions(-) diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 4514713..9806c23 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -148,14 +148,15 @@ qemuPhysIfaceConnect(virDomainDefPtr def, net->model && STREQ(net->model, "virtio")) vnet_hdr = 1; - rc = virNetDevMacVLanCreate(net->ifname, net->mac, - virDomainNetGetActualDirectDev(net), - virDomainNetGetActualDirectMode(net), - vnet_hdr, def->uuid, - virDomainNetGetActualDirectVirtPortProfile(net), - &res_ifname, - vmop, driver->stateDir, - virDomainNetGetActualBandwidth(net)); + rc = virNetDevMacVLanCreateWithVPortProfile( + net->ifname, net->mac, + virDomainNetGetActualDirectDev(net), + virDomainNetGetActualDirectMode(net), + vnet_hdr, def->uuid, + virDomainNetGetActualDirectVirtPortProfile(net), + &res_ifname, + vmop, driver->stateDir, + virDomainNetGetActualBandwidth(net)); if (rc >= 0) { virDomainAuditNetDevice(def, net, res_ifname, true); VIR_FREE(net->ifname); diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c index bbcf9ca..96c0070 100644 --- a/src/qemu/qemu_hotplug.c +++ b/src/qemu/qemu_hotplug.c @@ -1910,11 +1910,12 @@ int qemuDomainDetachNetDevice(struct qemud_driver *driver, virDomainConfNWFilterTeardown(detach); if (virDomainNetGetActualType(detach) == VIR_DOMAIN_NET_TYPE_DIRECT) { - ignore_value(virNetDevMacVLanDelete(detach->ifname, detach->mac, - virDomainNetGetActualDirectDev(detach), - virDomainNetGetActualDirectMode(detach), - virDomainNetGetActualDirectVirtPortProfile(detach), - driver->stateDir)); + ignore_value(virNetDevMacVLanDeleteWithVPortProfile( + detach->ifname, detach->mac, + virDomainNetGetActualDirectDev(detach), + virDomainNetGetActualDirectMode(detach), + virDomainNetGetActualDirectVirtPortProfile(detach), + driver->stateDir)); VIR_FREE(detach->ifname); } diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c index f4096f8..04fcdef 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -3411,11 +3411,12 @@ void qemuProcessStop(struct qemud_driver *driver, for (i = 0; i < def->nnets; i++) { virDomainNetDefPtr net = def->nets[i]; if (virDomainNetGetActualType(net) == VIR_DOMAIN_NET_TYPE_DIRECT) { - ignore_value(virNetDevMacVLanDelete(net->ifname, net->mac, - virDomainNetGetActualDirectDev(net), - virDomainNetGetActualDirectMode(net), - virDomainNetGetActualDirectVirtPortProfile(net), - driver->stateDir)); + ignore_value(virNetDevMacVLanDeleteWithVPortProfile( + net->ifname, net->mac, + virDomainNetGetActualDirectDev(net), + virDomainNetGetActualDirectMode(net), + virDomainNetGetActualDirectVirtPortProfile(net), + driver->stateDir)); VIR_FREE(net->ifname); } /* release the physical device (or any other resources used by diff --git a/src/util/virnetdevmacvlan.c b/src/util/virnetdevmacvlan.c index ab111f0..a322ece 100644 --- a/src/util/virnetdevmacvlan.c +++ b/src/util/virnetdevmacvlan.c @@ -215,7 +215,7 @@ static const uint32_t modeMap[VIR_NETDEV_MACVLAN_MODE_LAST] = { }; /** - * virNetDevMacVLanCreate: + * virNetDevMacVLanCreateWithVPortProfile: * Create an instance of a macvtap device and open its tap character * device. * @tgifname: Interface name that the macvtap is supposed to have. May @@ -234,17 +234,17 @@ static const uint32_t modeMap[VIR_NETDEV_MACVLAN_MODE_LAST] = { * negative value otherwise with error reported. * */ -int virNetDevMacVLanCreate(const char *tgifname, - const unsigned char *macaddress, - const char *linkdev, - enum virNetDevMacVLanMode mode, - int vnet_hdr, - const unsigned char *vmuuid, - virNetDevVPortProfilePtr virtPortProfile, - char **res_ifname, - enum virNetDevVPortProfileOp vmOp, - char *stateDir, - virNetDevBandwidthPtr bandwidth) +int virNetDevMacVLanCreateWithVPortProfile(const char *tgifname, + const unsigned char *macaddress, + const char *linkdev, + enum virNetDevMacVLanMode mode, + int vnet_hdr, + const unsigned char *vmuuid, + virNetDevVPortProfilePtr virtPortProfile, + char **res_ifname, + enum virNetDevVPortProfileOp vmOp, + char *stateDir, + virNetDevBandwidthPtr bandwidth) { const char *type = "macvtap"; int c, rc; @@ -357,7 +357,7 @@ link_del_exit: /** - * delMacvtap: + * virNetDevMacVLanDeleteWithVPortProfile: * @ifname : The name of the macvtap interface * @linkdev: The interface name of the NIC to connect to the external bridge * @virtPortProfile: pointer to object holding the virtual port profile data @@ -366,12 +366,12 @@ link_del_exit: * it with the switch if port profile parameters * were provided. */ -int virNetDevMacVLanDelete(const char *ifname, - const unsigned char *macaddr, - const char *linkdev, - int mode, - virNetDevVPortProfilePtr virtPortProfile, - char *stateDir) +int virNetDevMacVLanDeleteWithVPortProfile(const char *ifname, + const unsigned char *macaddr, + const char *linkdev, + int mode, + virNetDevVPortProfilePtr virtPortProfile, + char *stateDir) { int ret = 0; if (mode == VIR_NETDEV_MACVLAN_MODE_PASSTHRU) { @@ -392,29 +392,29 @@ int virNetDevMacVLanDelete(const char *ifname, } #else /* ! WITH_MACVTAP */ -int virNetDevMacVLanCreate(const char *ifname ATTRIBUTE_UNUSED, - const unsigned char *macaddress ATTRIBUTE_UNUSED, - const char *linkdev ATTRIBUTE_UNUSED, - enum virNetDevMacVLanMode mode ATTRIBUTE_UNUSED, - int vnet_hdr ATTRIBUTE_UNUSED, - const unsigned char *vmuuid ATTRIBUTE_UNUSED, - virNetDevVPortProfilePtr virtPortProfile ATTRIBUTE_UNUSED, - char **res_ifname ATTRIBUTE_UNUSED, - enum virNetDevVPortProfileOp vmop ATTRIBUTE_UNUSED, - char *stateDir ATTRIBUTE_UNUSED, - virNetDevBandwidthPtr bandwidth ATTRIBUTE_UNUSED) +int virNetDevMacVLanCreateWithVPortProfile(const char *ifname ATTRIBUTE_UNUSED, + const unsigned char *macaddress ATTRIBUTE_UNUSED, + const char *linkdev ATTRIBUTE_UNUSED, + enum virNetDevMacVLanMode mode ATTRIBUTE_UNUSED, + int vnet_hdr ATTRIBUTE_UNUSED, + const unsigned char *vmuuid ATTRIBUTE_UNUSED, + virNetDevVPortProfilePtr virtPortProfile ATTRIBUTE_UNUSED, + char **res_ifname ATTRIBUTE_UNUSED, + enum virNetDevVPortProfileOp vmop ATTRIBUTE_UNUSED, + char *stateDir ATTRIBUTE_UNUSED, + virNetDevBandwidthPtr bandwidth ATTRIBUTE_UNUSED) { virReportSystemError(ENOSYS, "%s", _("Cannot create macvlan devices on this platform")); return -1; } -int virNetDevMacVLanDelete(const char *ifname ATTRIBUTE_UNUSED, - const unsigned char *macaddress ATTRIBUTE_UNUSED, - const char *linkdev ATTRIBUTE_UNUSED, - int mode ATTRIBUTE_UNUSED, - virNetDevVPortProfilePtr virtPortProfile ATTRIBUTE_UNUSED, - char *stateDir ATTRIBUTE_UNUSED) +int virNetDevMacVLanDeleteWithVPortProfile(const char *ifname ATTRIBUTE_UNUSED, + const unsigned char *macaddress ATTRIBUTE_UNUSED, + const char *linkdev ATTRIBUTE_UNUSED, + int mode ATTRIBUTE_UNUSED, + virNetDevVPortProfilePtr virtPortProfile ATTRIBUTE_UNUSED, + char *stateDir ATTRIBUTE_UNUSED) { virReportSystemError(ENOSYS, "%s", _("Cannot create macvlan devices on this platform")); diff --git a/src/util/virnetdevmacvlan.h b/src/util/virnetdevmacvlan.h index f3277f9..9498f7b 100644 --- a/src/util/virnetdevmacvlan.h +++ b/src/util/virnetdevmacvlan.h @@ -39,26 +39,26 @@ enum virNetDevMacVLanMode { }; VIR_ENUM_DECL(virNetDevMacVLanMode) -int virNetDevMacVLanCreate(const char *ifname, - const unsigned char *macaddress, - const char *linkdev, - enum virNetDevMacVLanMode mode, - int vnet_hdr, - const unsigned char *vmuuid, - virNetDevVPortProfilePtr virtPortProfile, - char **res_ifname, - enum virNetDevVPortProfileOp vmop, - char *stateDir, - virNetDevBandwidthPtr bandwidth) +int virNetDevMacVLanCreateWithVPortProfile(const char *ifname, + const unsigned char *macaddress, + const char *linkdev, + enum virNetDevMacVLanMode mode, + int vnet_hdr, + const unsigned char *vmuuid, + virNetDevVPortProfilePtr virtPortProfile, + char **res_ifname, + enum virNetDevVPortProfileOp vmop, + char *stateDir, + virNetDevBandwidthPtr bandwidth) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3) ATTRIBUTE_NONNULL(6) ATTRIBUTE_NONNULL(8) ATTRIBUTE_NONNULL(10) ATTRIBUTE_RETURN_CHECK; -int virNetDevMacVLanDelete(const char *ifname, - const unsigned char *macaddress, - const char *linkdev, - int mode, - virNetDevVPortProfilePtr virtPortProfile, - char *stateDir) +int virNetDevMacVLanDeleteWithVPortProfile(const char *ifname, + const unsigned char *macaddress, + const char *linkdev, + int mode, + virNetDevVPortProfilePtr virtPortProfile, + char *stateDir) ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3) ATTRIBUTE_NONNULL(6) ATTRIBUTE_RETURN_CHECK; -- 1.7.6.4

On 11/15/2011 06:14 AM, Daniel P. Berrange wrote:
From: "Daniel P. Berrange"<berrange@redhat.com>
Rename virNetDevMacVLanCreate to virNetDevMacVLanCreateWithVPortProfile and virNetDevMacVLanDelete to virNetDevMacVLanDeleteWithVPortProfile
To make way for renaming the other macvlan creation APIs in interface.c
* util/virnetdevmacvlan.c, util/virnetdevmacvlan.h, qemu/qemu_command.c, qemu/qemu_hotplug.c, qemu/qemu_process.c: Rename APIs
Again mechanical and doesn't break the build. (I have to admit I haven't looked to see if the new function names in all of these make sense to me, but I'm sure they're at least as good as the previous names :-) ACK.

From: "Daniel P. Berrange" <berrange@redhat.com> Rename ifaceMacvtapLinkAdd to virNetDevMacVLanCreate and ifaceLinkDel to virNetDevMacVLanDelete. Strictly speaking the latter isn't restricted to macvlan devices, but that's the only use libvirt has for it. * util/interface.c, util/interface.h, util/virnetdevmacvlan.c: Rename APIs --- src/libvirt_private.syms | 4 ++-- src/util/interface.c | 41 ++++++++++++++++++----------------------- src/util/interface.h | 19 +++++++++++-------- src/util/virnetdevmacvlan.c | 12 ++++++------ 4 files changed, 37 insertions(+), 39 deletions(-) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 03aa711..dcbc8b8 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -583,8 +583,8 @@ ifaceGetPhysicalFunction; ifaceGetVirtualFunctionIndex; ifaceGetVlanID; ifaceIsVirtualFunction; -ifaceLinkDel; -ifaceMacvtapLinkAdd; +virNetDevMacVLanCreate; +virNetDevMacVLanDelete; ifaceMacvtapLinkDump; ifaceReplaceMacAddress; ifaceRestoreMacAddress; diff --git a/src/util/interface.c b/src/util/interface.c index 63e6bf7..a1c56f5 100644 --- a/src/util/interface.c +++ b/src/util/interface.c @@ -313,12 +313,11 @@ ifaceGetIPAddress(const char *ifname ATTRIBUTE_UNUSED, #endif /* __linux__ */ /** - * ifaceLinkAdd + * virNetDevMacVLanCreate: * + * @ifname: The name the interface is supposed to have; optional parameter * @type: The type of device, i.e., "macvtap" * @macaddress: The MAC address of the device - * @macaddrsize: The size of the MAC address, typically '6' - * @ifname: The name the interface is supposed to have; optional parameter * @srcdev: The name of the 'link' device * @macvlan_mode: The macvlan mode to use * @retry: Pointer to integer that will be '1' upon return if an interface @@ -331,12 +330,12 @@ ifaceGetIPAddress(const char *ifname ATTRIBUTE_UNUSED, */ #if defined(__linux__) && WITH_MACVTAP int -ifaceMacvtapLinkAdd(const char *type, - const unsigned char *macaddress, int macaddrsize, - const char *ifname, - const char *srcdev, - uint32_t macvlan_mode, - int *retry) +virNetDevMacVLanCreate(const char *ifname, + const char *type, + const unsigned char *macaddress, + const char *srcdev, + uint32_t macvlan_mode, + int *retry) { int rc = 0; struct nlmsghdr *resp; @@ -366,7 +365,7 @@ ifaceMacvtapLinkAdd(const char *type, if (nla_put_u32(nl_msg, IFLA_LINK, ifindex) < 0) goto buffer_too_small; - if (nla_put(nl_msg, IFLA_ADDRESS, macaddrsize, macaddress) < 0) + if (nla_put(nl_msg, IFLA_ADDRESS, VIR_MAC_BUFLEN, macaddress) < 0) goto buffer_too_small; if (ifname && @@ -458,14 +457,12 @@ buffer_too_small: #else -int -ifaceMacvtapLinkAdd(const char *type ATTRIBUTE_UNUSED, - const unsigned char *macaddress ATTRIBUTE_UNUSED, - int macaddrsize ATTRIBUTE_UNUSED, - const char *ifname ATTRIBUTE_UNUSED, - const char *srcdev ATTRIBUTE_UNUSED, - uint32_t macvlan_mode ATTRIBUTE_UNUSED, - int *retry ATTRIBUTE_UNUSED) +int virNetDevMacVLanCreate(const char *ifname ATTRIBUTE_UNUSED, + const char *type ATTRIBUTE_UNUSED, + const unsigned char *macaddress ATTRIBUTE_UNUSED, + const char *srcdev ATTRIBUTE_UNUSED, + uint32_t macvlan_mode ATTRIBUTE_UNUSED, + int *retry ATTRIBUTE_UNUSED) { ifaceError(VIR_ERR_INTERNAL_ERROR, "%s", # if defined(__linux__) && !WITH_MACVTAP @@ -483,7 +480,7 @@ ifaceMacvtapLinkAdd(const char *type ATTRIBUTE_UNUSED, /** - * ifaceLinkDel + * virNetDevMacVLanDelete: * * @ifname: Name of the interface * @@ -492,8 +489,7 @@ ifaceMacvtapLinkAdd(const char *type ATTRIBUTE_UNUSED, * Returns 0 on success, -1 on fatal error. */ #if defined( __linux__) && WITH_MACVTAP -int -ifaceLinkDel(const char *ifname) +int virNetDevMacVLanDelete(const char *ifname) { int rc = 0; struct nlmsghdr *resp; @@ -572,8 +568,7 @@ buffer_too_small: #else -int -ifaceLinkDel(const char *ifname ATTRIBUTE_UNUSED) +int virNetDevMacVLanDelete(const char *ifname ATTRIBUTE_UNUSED) { ifaceError(VIR_ERR_INTERNAL_ERROR, "%s", # if defined(__linux__) && !WITH_MACVTAP diff --git a/src/util/interface.h b/src/util/interface.h index 4adc601..a62f26a 100644 --- a/src/util/interface.h +++ b/src/util/interface.h @@ -39,14 +39,17 @@ int ifaceGetVlanID(const char *vlanifname, int *vlanid); int ifaceGetIPAddress(const char *ifname, virSocketAddrPtr addr); -int ifaceMacvtapLinkAdd(const char *type, - const unsigned char *macaddress, int macaddrsize, - const char *ifname, - const char *srcdev, - uint32_t macvlan_mode, - int *retry); - -int ifaceLinkDel(const char *ifname); +int virNetDevMacVLanCreate(const char *ifname, + const char *type, + const unsigned char *macaddress, + const char *srcdev, + uint32_t macvlan_mode, + int *retry) + ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3) ATTRIBUTE_NONNULL(4) + ATTRIBUTE_RETURN_CHECK; + +int virNetDevMacVLanDelete(const char *ifname) + ATTRIBUTE_NONNULL(1) ATTRIBUTE_RETURN_CHECK; int ifaceMacvtapLinkDump(bool nltarget_kernel, const char *ifname, int ifindex, struct nlattr **tb, unsigned char **recvbuf, diff --git a/src/util/virnetdevmacvlan.c b/src/util/virnetdevmacvlan.c index a322ece..ab552af 100644 --- a/src/util/virnetdevmacvlan.c +++ b/src/util/virnetdevmacvlan.c @@ -284,8 +284,8 @@ int virNetDevMacVLanCreateWithVPortProfile(const char *tgifname, return -1; } cr_ifname = tgifname; - rc = ifaceMacvtapLinkAdd(type, macaddress, 6, tgifname, linkdev, - macvtapMode, &do_retry); + rc = virNetDevMacVLanCreate(tgifname, type, macaddress, linkdev, + macvtapMode, &do_retry); if (rc < 0) return -1; } else { @@ -294,8 +294,8 @@ create_name: for (c = 0; c < 8192; c++) { snprintf(ifname, sizeof(ifname), MACVTAP_NAME_PATTERN, c); if (ifaceGetIndex(false, ifname, &ifindex) == -ENODEV) { - rc = ifaceMacvtapLinkAdd(type, macaddress, 6, ifname, linkdev, - macvtapMode, &do_retry); + rc = virNetDevMacVLanCreate(ifname, type, macaddress, linkdev, + macvtapMode, &do_retry); if (rc == 0) break; @@ -350,7 +350,7 @@ disassociate_exit: vmOp)); link_del_exit: - ifaceLinkDel(cr_ifname); + ignore_value(virNetDevMacVLanDelete(cr_ifname)); return rc; } @@ -385,7 +385,7 @@ int virNetDevMacVLanDeleteWithVPortProfile(const char *ifname, linkdev, VIR_NETDEV_VPORT_PROFILE_OP_DESTROY) < 0) ret = -1; - if (ifaceLinkDel(ifname) < 0) + if (virNetDevMacVLanDelete(ifname) < 0) ret = -1; } return ret; -- 1.7.6.4

On 11/15/2011 06:14 AM, Daniel P. Berrange wrote:
From: "Daniel P. Berrange"<berrange@redhat.com>
Rename ifaceMacvtapLinkAdd to virNetDevMacVLanCreate and ifaceLinkDel to virNetDevMacVLanDelete. Strictly speaking the latter isn't restricted to macvlan devices, but that's the only use libvirt has for it.
Also removed the macaddrsize arg from virNetDevMacVLanCreate. This is bringing back some memory of a network device type that had a mac address > 6 bytes in length, but I can't recall what it was, and anyway everything else in libvirt assumes VIR_MAC_BUFLEN (6) anyway. ACK.

On Thu, Nov 17, 2011 at 06:04:32AM -0500, Laine Stump wrote:
On 11/15/2011 06:14 AM, Daniel P. Berrange wrote:
From: "Daniel P. Berrange"<berrange@redhat.com>
Rename ifaceMacvtapLinkAdd to virNetDevMacVLanCreate and ifaceLinkDel to virNetDevMacVLanDelete. Strictly speaking the latter isn't restricted to macvlan devices, but that's the only use libvirt has for it.
Also removed the macaddrsize arg from virNetDevMacVLanCreate. This is bringing back some memory of a network device type that had a mac address > 6 bytes in length, but I can't recall what it was, and anyway everything else in libvirt assumes VIR_MAC_BUFLEN (6) anyway.
Yes, I should have mentioned that. Although the API had a macaddr length parameter, the caller had hardcoded '6' as the length. Given that everything in libvirt presumes VIR_MAC_BUFLEN, I didn't see the point in keeping macaddr length configurable for this one API. Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|

From: "Daniel P. Berrange" <berrange@redhat.com> Move the low level macvlan creation APIs into the virnetdevmacvlan.c file where they more naturally belong * util/interface.c, util/interface.h: Remove virNetDevMacVLanCreate and virNetDevMacVLanDelete * util/virnetdevmacvlan.c, util/virnetdevmacvlan.h: Add virNetDevMacVLanCreate and virNetDevMacVLanDelete --- src/util/interface.c | 270 ------------------------------------------- src/util/interface.h | 12 -- src/util/virnetdevmacvlan.c | 256 ++++++++++++++++++++++++++++++++++++++++- src/util/virnetdevmacvlan.h | 12 ++ 4 files changed, 264 insertions(+), 286 deletions(-) diff --git a/src/util/interface.c b/src/util/interface.c index a1c56f5..e757c6f 100644 --- a/src/util/interface.c +++ b/src/util/interface.c @@ -312,276 +312,6 @@ ifaceGetIPAddress(const char *ifname ATTRIBUTE_UNUSED, #endif /* __linux__ */ -/** - * virNetDevMacVLanCreate: - * - * @ifname: The name the interface is supposed to have; optional parameter - * @type: The type of device, i.e., "macvtap" - * @macaddress: The MAC address of the device - * @srcdev: The name of the 'link' device - * @macvlan_mode: The macvlan mode to use - * @retry: Pointer to integer that will be '1' upon return if an interface - * with the same name already exists and it is worth to try - * again with a different name - * - * Create a macvtap device with the given properties. - * - * Returns 0 on success, -1 on fatal error. - */ -#if defined(__linux__) && WITH_MACVTAP -int -virNetDevMacVLanCreate(const char *ifname, - const char *type, - const unsigned char *macaddress, - const char *srcdev, - uint32_t macvlan_mode, - int *retry) -{ - int rc = 0; - struct nlmsghdr *resp; - struct nlmsgerr *err; - struct ifinfomsg ifinfo = { .ifi_family = AF_UNSPEC }; - int ifindex; - unsigned char *recvbuf = NULL; - unsigned int recvbuflen; - struct nl_msg *nl_msg; - struct nlattr *linkinfo, *info_data; - - if (ifaceGetIndex(true, srcdev, &ifindex) < 0) - return -1; - - *retry = 0; - - nl_msg = nlmsg_alloc_simple(RTM_NEWLINK, - NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL); - if (!nl_msg) { - virReportOOMError(); - return -1; - } - - if (nlmsg_append(nl_msg, &ifinfo, sizeof(ifinfo), NLMSG_ALIGNTO) < 0) - goto buffer_too_small; - - if (nla_put_u32(nl_msg, IFLA_LINK, ifindex) < 0) - goto buffer_too_small; - - if (nla_put(nl_msg, IFLA_ADDRESS, VIR_MAC_BUFLEN, macaddress) < 0) - goto buffer_too_small; - - if (ifname && - nla_put(nl_msg, IFLA_IFNAME, strlen(ifname)+1, ifname) < 0) - goto buffer_too_small; - - if (!(linkinfo = nla_nest_start(nl_msg, IFLA_LINKINFO))) - goto buffer_too_small; - - if (nla_put(nl_msg, IFLA_INFO_KIND, strlen(type), type) < 0) - goto buffer_too_small; - - if (macvlan_mode > 0) { - if (!(info_data = nla_nest_start(nl_msg, IFLA_INFO_DATA))) - goto buffer_too_small; - - if (nla_put(nl_msg, IFLA_MACVLAN_MODE, sizeof(macvlan_mode), - &macvlan_mode) < 0) - goto buffer_too_small; - - nla_nest_end(nl_msg, info_data); - } - - nla_nest_end(nl_msg, linkinfo); - - if (nlComm(nl_msg, &recvbuf, &recvbuflen, 0) < 0) { - rc = -1; - goto cleanup; - } - - if (recvbuflen < NLMSG_LENGTH(0) || recvbuf == NULL) - goto malformed_resp; - - resp = (struct nlmsghdr *)recvbuf; - - switch (resp->nlmsg_type) { - case NLMSG_ERROR: - err = (struct nlmsgerr *)NLMSG_DATA(resp); - if (resp->nlmsg_len < NLMSG_LENGTH(sizeof(*err))) - goto malformed_resp; - - switch (err->error) { - - case 0: - break; - - case -EEXIST: - *retry = 1; - rc = -1; - break; - - default: - virReportSystemError(-err->error, - _("error creating %s type of interface"), - type); - rc = -1; - } - break; - - case NLMSG_DONE: - break; - - default: - goto malformed_resp; - } - -cleanup: - nlmsg_free(nl_msg); - - VIR_FREE(recvbuf); - - return rc; - -malformed_resp: - nlmsg_free(nl_msg); - - ifaceError(VIR_ERR_INTERNAL_ERROR, "%s", - _("malformed netlink response message")); - VIR_FREE(recvbuf); - return -1; - -buffer_too_small: - nlmsg_free(nl_msg); - - ifaceError(VIR_ERR_INTERNAL_ERROR, "%s", - _("allocated netlink buffer is too small")); - return -1; -} - -#else - -int virNetDevMacVLanCreate(const char *ifname ATTRIBUTE_UNUSED, - const char *type ATTRIBUTE_UNUSED, - const unsigned char *macaddress ATTRIBUTE_UNUSED, - const char *srcdev ATTRIBUTE_UNUSED, - uint32_t macvlan_mode ATTRIBUTE_UNUSED, - int *retry ATTRIBUTE_UNUSED) -{ - ifaceError(VIR_ERR_INTERNAL_ERROR, "%s", -# if defined(__linux__) && !WITH_MACVTAP - _("ifaceMacvtapLinkAdd is not supported since the include " - "files were too old")); -# else - _("ifaceMacvtapLinkAdd is not supported on non-linux " - "platforms")); -# endif - - return -1; -} - -#endif - - -/** - * virNetDevMacVLanDelete: - * - * @ifname: Name of the interface - * - * Tear down an interface with the given name. - * - * Returns 0 on success, -1 on fatal error. - */ -#if defined( __linux__) && WITH_MACVTAP -int virNetDevMacVLanDelete(const char *ifname) -{ - int rc = 0; - struct nlmsghdr *resp; - struct nlmsgerr *err; - struct ifinfomsg ifinfo = { .ifi_family = AF_UNSPEC }; - unsigned char *recvbuf = NULL; - unsigned int recvbuflen; - struct nl_msg *nl_msg; - - nl_msg = nlmsg_alloc_simple(RTM_DELLINK, - NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL); - if (!nl_msg) { - virReportOOMError(); - return -1; - } - - if (nlmsg_append(nl_msg, &ifinfo, sizeof(ifinfo), NLMSG_ALIGNTO) < 0) - goto buffer_too_small; - - if (nla_put(nl_msg, IFLA_IFNAME, strlen(ifname)+1, ifname) < 0) - goto buffer_too_small; - - if (nlComm(nl_msg, &recvbuf, &recvbuflen, 0) < 0) { - rc = -1; - goto cleanup; - } - - if (recvbuflen < NLMSG_LENGTH(0) || recvbuf == NULL) - goto malformed_resp; - - resp = (struct nlmsghdr *)recvbuf; - - switch (resp->nlmsg_type) { - case NLMSG_ERROR: - err = (struct nlmsgerr *)NLMSG_DATA(resp); - if (resp->nlmsg_len < NLMSG_LENGTH(sizeof(*err))) - goto malformed_resp; - - if (err->error) { - virReportSystemError(-err->error, - _("error destroying %s interface"), - ifname); - rc = -1; - } - break; - - case NLMSG_DONE: - break; - - default: - goto malformed_resp; - } - -cleanup: - nlmsg_free(nl_msg); - - VIR_FREE(recvbuf); - - return rc; - -malformed_resp: - nlmsg_free(nl_msg); - - ifaceError(VIR_ERR_INTERNAL_ERROR, "%s", - _("malformed netlink response message")); - VIR_FREE(recvbuf); - return -1; - -buffer_too_small: - nlmsg_free(nl_msg); - - ifaceError(VIR_ERR_INTERNAL_ERROR, "%s", - _("allocated netlink buffer is too small")); - return -1; -} - -#else - -int virNetDevMacVLanDelete(const char *ifname ATTRIBUTE_UNUSED) -{ - ifaceError(VIR_ERR_INTERNAL_ERROR, "%s", -# if defined(__linux__) && !WITH_MACVTAP - _("ifaceLinkDel is not supported since the include files " - "were too old")); -# else - _("ifaceLinkDel is not supported on non-linux platforms")); -# endif - return -1; -} - -#endif - #if defined(__linux__) && defined(IFLA_PORT_MAX) diff --git a/src/util/interface.h b/src/util/interface.h index a62f26a..1dd8f35 100644 --- a/src/util/interface.h +++ b/src/util/interface.h @@ -39,18 +39,6 @@ int ifaceGetVlanID(const char *vlanifname, int *vlanid); int ifaceGetIPAddress(const char *ifname, virSocketAddrPtr addr); -int virNetDevMacVLanCreate(const char *ifname, - const char *type, - const unsigned char *macaddress, - const char *srcdev, - uint32_t macvlan_mode, - int *retry) - ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3) ATTRIBUTE_NONNULL(4) - ATTRIBUTE_RETURN_CHECK; - -int virNetDevMacVLanDelete(const char *ifname) - ATTRIBUTE_NONNULL(1) ATTRIBUTE_RETURN_CHECK; - int ifaceMacvtapLinkDump(bool nltarget_kernel, const char *ifname, int ifindex, struct nlattr **tb, unsigned char **recvbuf, uint32_t (*getPidFunc)(void)); diff --git a/src/util/virnetdevmacvlan.c b/src/util/virnetdevmacvlan.c index ab552af..6919d5e 100644 --- a/src/util/virnetdevmacvlan.c +++ b/src/util/virnetdevmacvlan.c @@ -34,7 +34,7 @@ #define VIR_FROM_THIS VIR_FROM_NET -#define macvtapError(code, ...) \ +#define virNetDevError(code, ...) \ virReportErrorHelper(VIR_FROM_NET, code, __FILE__, \ __FUNCTION__, __LINE__, __VA_ARGS__) @@ -74,6 +74,235 @@ VIR_ENUM_IMPL(virNetDevMacVLanMode, VIR_NETDEV_MACVLAN_MODE_LAST, # define MACVTAP_NAME_PATTERN "macvtap%d" /** + * virNetDevMacVLanCreate: + * + * @ifname: The name the interface is supposed to have; optional parameter + * @type: The type of device, i.e., "macvtap" + * @macaddress: The MAC address of the device + * @srcdev: The name of the 'link' device + * @macvlan_mode: The macvlan mode to use + * @retry: Pointer to integer that will be '1' upon return if an interface + * with the same name already exists and it is worth to try + * again with a different name + * + * Create a macvtap device with the given properties. + * + * Returns 0 on success, -1 on fatal error. + */ +int +virNetDevMacVLanCreate(const char *ifname, + const char *type, + const unsigned char *macaddress, + const char *srcdev, + uint32_t macvlan_mode, + int *retry) +{ + int rc = 0; + struct nlmsghdr *resp; + struct nlmsgerr *err; + struct ifinfomsg ifinfo = { .ifi_family = AF_UNSPEC }; + int ifindex; + unsigned char *recvbuf = NULL; + unsigned int recvbuflen; + struct nl_msg *nl_msg; + struct nlattr *linkinfo, *info_data; + + if (ifaceGetIndex(true, srcdev, &ifindex) < 0) + return -1; + + *retry = 0; + + nl_msg = nlmsg_alloc_simple(RTM_NEWLINK, + NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL); + if (!nl_msg) { + virReportOOMError(); + return -1; + } + + if (nlmsg_append(nl_msg, &ifinfo, sizeof(ifinfo), NLMSG_ALIGNTO) < 0) + goto buffer_too_small; + + if (nla_put_u32(nl_msg, IFLA_LINK, ifindex) < 0) + goto buffer_too_small; + + if (nla_put(nl_msg, IFLA_ADDRESS, VIR_MAC_BUFLEN, macaddress) < 0) + goto buffer_too_small; + + if (ifname && + nla_put(nl_msg, IFLA_IFNAME, strlen(ifname)+1, ifname) < 0) + goto buffer_too_small; + + if (!(linkinfo = nla_nest_start(nl_msg, IFLA_LINKINFO))) + goto buffer_too_small; + + if (nla_put(nl_msg, IFLA_INFO_KIND, strlen(type), type) < 0) + goto buffer_too_small; + + if (macvlan_mode > 0) { + if (!(info_data = nla_nest_start(nl_msg, IFLA_INFO_DATA))) + goto buffer_too_small; + + if (nla_put(nl_msg, IFLA_MACVLAN_MODE, sizeof(macvlan_mode), + &macvlan_mode) < 0) + goto buffer_too_small; + + nla_nest_end(nl_msg, info_data); + } + + nla_nest_end(nl_msg, linkinfo); + + if (nlComm(nl_msg, &recvbuf, &recvbuflen, 0) < 0) { + rc = -1; + goto cleanup; + } + + if (recvbuflen < NLMSG_LENGTH(0) || recvbuf == NULL) + goto malformed_resp; + + resp = (struct nlmsghdr *)recvbuf; + + switch (resp->nlmsg_type) { + case NLMSG_ERROR: + err = (struct nlmsgerr *)NLMSG_DATA(resp); + if (resp->nlmsg_len < NLMSG_LENGTH(sizeof(*err))) + goto malformed_resp; + + switch (err->error) { + + case 0: + break; + + case -EEXIST: + *retry = 1; + rc = -1; + break; + + default: + virReportSystemError(-err->error, + _("error creating %s type of interface"), + type); + rc = -1; + } + break; + + case NLMSG_DONE: + break; + + default: + goto malformed_resp; + } + +cleanup: + nlmsg_free(nl_msg); + + VIR_FREE(recvbuf); + + return rc; + +malformed_resp: + nlmsg_free(nl_msg); + + virNetDevError(VIR_ERR_INTERNAL_ERROR, "%s", + _("malformed netlink response message")); + VIR_FREE(recvbuf); + return -1; + +buffer_too_small: + nlmsg_free(nl_msg); + + virNetDevError(VIR_ERR_INTERNAL_ERROR, "%s", + _("allocated netlink buffer is too small")); + return -1; +} + +/** + * virNetDevMacVLanDelete: + * + * @ifname: Name of the interface + * + * Tear down an interface with the given name. + * + * Returns 0 on success, -1 on fatal error. + */ +int virNetDevMacVLanDelete(const char *ifname) +{ + int rc = 0; + struct nlmsghdr *resp; + struct nlmsgerr *err; + struct ifinfomsg ifinfo = { .ifi_family = AF_UNSPEC }; + unsigned char *recvbuf = NULL; + unsigned int recvbuflen; + struct nl_msg *nl_msg; + + nl_msg = nlmsg_alloc_simple(RTM_DELLINK, + NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL); + if (!nl_msg) { + virReportOOMError(); + return -1; + } + + if (nlmsg_append(nl_msg, &ifinfo, sizeof(ifinfo), NLMSG_ALIGNTO) < 0) + goto buffer_too_small; + + if (nla_put(nl_msg, IFLA_IFNAME, strlen(ifname)+1, ifname) < 0) + goto buffer_too_small; + + if (nlComm(nl_msg, &recvbuf, &recvbuflen, 0) < 0) { + rc = -1; + goto cleanup; + } + + if (recvbuflen < NLMSG_LENGTH(0) || recvbuf == NULL) + goto malformed_resp; + + resp = (struct nlmsghdr *)recvbuf; + + switch (resp->nlmsg_type) { + case NLMSG_ERROR: + err = (struct nlmsgerr *)NLMSG_DATA(resp); + if (resp->nlmsg_len < NLMSG_LENGTH(sizeof(*err))) + goto malformed_resp; + + if (err->error) { + virReportSystemError(-err->error, + _("error destroying %s interface"), + ifname); + rc = -1; + } + break; + + case NLMSG_DONE: + break; + + default: + goto malformed_resp; + } + +cleanup: + nlmsg_free(nl_msg); + + VIR_FREE(recvbuf); + + return rc; + +malformed_resp: + nlmsg_free(nl_msg); + + virNetDevError(VIR_ERR_INTERNAL_ERROR, "%s", + _("malformed netlink response message")); + VIR_FREE(recvbuf); + return -1; + +buffer_too_small: + nlmsg_free(nl_msg); + + virNetDevError(VIR_ERR_INTERNAL_ERROR, "%s", + _("allocated netlink buffer is too small")); + return -1; +} + + +/** * virNetDevMacVLanTapOpen: * Open the macvtap's tap device. * @ifname: Name of the macvtap interface @@ -332,9 +561,9 @@ create_name: goto disassociate_exit; if (virNetDevBandwidthSet(cr_ifname, bandwidth) < 0) { - macvtapError(VIR_ERR_INTERNAL_ERROR, - _("cannot set bandwidth limits on %s"), - cr_ifname); + virNetDevError(VIR_ERR_INTERNAL_ERROR, + _("cannot set bandwidth limits on %s"), + cr_ifname); rc = -1; goto disassociate_exit; } @@ -392,6 +621,25 @@ int virNetDevMacVLanDeleteWithVPortProfile(const char *ifname, } #else /* ! WITH_MACVTAP */ +int virNetDevMacVLanCreate(const char *ifname ATTRIBUTE_UNUSED, + const char *type ATTRIBUTE_UNUSED, + const unsigned char *macaddress ATTRIBUTE_UNUSED, + const char *srcdev ATTRIBUTE_UNUSED, + uint32_t macvlan_mode ATTRIBUTE_UNUSED, + int *retry ATTRIBUTE_UNUSED) +{ + virReportSystemError(ENOSYS, "%s", + _("Cannot create macvlan devices on this platform")); + return -1; +} + +int virNetDevMacVLanDelete(const char *ifname ATTRIBUTE_UNUSED) +{ + virReportSystemError(ENOSYS, "%s", + _("Cannot create macvlan devices on this platform")); + return -1; +} + int virNetDevMacVLanCreateWithVPortProfile(const char *ifname ATTRIBUTE_UNUSED, const unsigned char *macaddress ATTRIBUTE_UNUSED, const char *linkdev ATTRIBUTE_UNUSED, diff --git a/src/util/virnetdevmacvlan.h b/src/util/virnetdevmacvlan.h index 9498f7b..73918b8 100644 --- a/src/util/virnetdevmacvlan.h +++ b/src/util/virnetdevmacvlan.h @@ -39,6 +39,18 @@ enum virNetDevMacVLanMode { }; VIR_ENUM_DECL(virNetDevMacVLanMode) +int virNetDevMacVLanCreate(const char *ifname, + const char *type, + const unsigned char *macaddress, + const char *srcdev, + uint32_t macvlan_mode, + int *retry) + ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3) ATTRIBUTE_NONNULL(4) + ATTRIBUTE_RETURN_CHECK; + +int virNetDevMacVLanDelete(const char *ifname) + ATTRIBUTE_NONNULL(1) ATTRIBUTE_RETURN_CHECK; + int virNetDevMacVLanCreateWithVPortProfile(const char *ifname, const unsigned char *macaddress, const char *linkdev, -- 1.7.6.4

On 11/15/2011 06:14 AM, Daniel P. Berrange wrote:
From: "Daniel P. Berrange"<berrange@redhat.com>
Move the low level macvlan creation APIs into the virnetdevmacvlan.c file where they more naturally belong
* util/interface.c, util/interface.h: Remove virNetDevMacVLanCreate and virNetDevMacVLanDelete * util/virnetdevmacvlan.c, util/virnetdevmacvlan.h: Add virNetDevMacVLanCreate and virNetDevMacVLanDelete --- src/util/interface.c | 270 ------------------------------------------- src/util/interface.h | 12 -- src/util/virnetdevmacvlan.c | 256 ++++++++++++++++++++++++++++++++++++++++- src/util/virnetdevmacvlan.h | 12 ++ 4 files changed, 264 insertions(+), 286 deletions(-)
ACK.

From: "Daniel P. Berrange" <berrange@redhat.com> Rename ifaceReplaceMacAddress to virNetDevReplaceMacAddress and ifaceRestoreMacAddress to virNetDevRestoreMacAddress. * util/interface.c, util/interface.h, util/virnetdevmacvlan.c: Rename APIs --- src/libvirt_private.syms | 4 ++-- src/util/interface.c | 14 +++++++------- src/util/interface.h | 15 +++++++++------ src/util/virnetdevmacvlan.c | 5 ++--- 4 files changed, 20 insertions(+), 18 deletions(-) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index dcbc8b8..d71186b 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -586,8 +586,8 @@ ifaceIsVirtualFunction; virNetDevMacVLanCreate; virNetDevMacVLanDelete; ifaceMacvtapLinkDump; -ifaceReplaceMacAddress; -ifaceRestoreMacAddress; +virNetDevReplaceMacAddress; +virNetDevRestoreMacAddress; # interface_conf.h diff --git a/src/util/interface.c b/src/util/interface.c index e757c6f..df2aa88 100644 --- a/src/util/interface.c +++ b/src/util/interface.c @@ -554,7 +554,7 @@ ifaceGetNthParent(int ifindex ATTRIBUTE_UNUSED, #endif /** - * ifaceReplaceMacAddress: + * virNetDevReplaceMacAddress: * @macaddress: new MAC address for interface * @linkdev: name of interface * @stateDir: directory to store old MAC address @@ -563,9 +563,9 @@ ifaceGetNthParent(int ifindex ATTRIBUTE_UNUSED, * */ int -ifaceReplaceMacAddress(const unsigned char *macaddress, - const char *linkdev, - const char *stateDir) +virNetDevReplaceMacAddress(const char *linkdev, + const unsigned char *macaddress, + const char *stateDir) { unsigned char oldmac[6]; char *path = NULL; @@ -595,7 +595,7 @@ ifaceReplaceMacAddress(const unsigned char *macaddress, } /** - * ifaceRestoreMacAddress: + * virNetDevRestoreMacAddress: * @linkdev: name of interface * @stateDir: directory containing old MAC address * @@ -603,8 +603,8 @@ ifaceReplaceMacAddress(const unsigned char *macaddress, * */ int -ifaceRestoreMacAddress(const char *linkdev, - const char *stateDir) +virNetDevRestoreMacAddress(const char *linkdev, + const char *stateDir) { int rc; char *oldmacname = NULL; diff --git a/src/util/interface.h b/src/util/interface.h index 1dd8f35..6a4631c 100644 --- a/src/util/interface.h +++ b/src/util/interface.h @@ -49,12 +49,15 @@ int ifaceGetNthParent(int ifindex, const char *ifname, unsigned int nthParent, ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(4) ATTRIBUTE_NONNULL(5) ATTRIBUTE_NONNULL(6); -int ifaceReplaceMacAddress(const unsigned char *macaddress, - const char *linkdev, - const char *stateDir); - -int ifaceRestoreMacAddress(const char *linkdev, - const char *stateDir); +int virNetDevReplaceMacAddress(const char *linkdev, + const unsigned char *macaddress, + const char *stateDir) + ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3) + ATTRIBUTE_RETURN_CHECK; + +int virNetDevRestoreMacAddress(const char *linkdev, + const char *stateDir) + ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_RETURN_CHECK; int ifaceIsVirtualFunction(const char *ifname); diff --git a/src/util/virnetdevmacvlan.c b/src/util/virnetdevmacvlan.c index 6919d5e..8e2e737 100644 --- a/src/util/virnetdevmacvlan.c +++ b/src/util/virnetdevmacvlan.c @@ -497,9 +497,8 @@ int virNetDevMacVLanCreateWithVPortProfile(const char *tgifname, * emulate their switch in firmware. */ if (mode == VIR_NETDEV_MACVLAN_MODE_PASSTHRU) { - if (ifaceReplaceMacAddress(macaddress, linkdev, stateDir) < 0) { + if (virNetDevReplaceMacAddress(linkdev, macaddress, stateDir) < 0) return -1; - } } if (tgifname) { @@ -604,7 +603,7 @@ int virNetDevMacVLanDeleteWithVPortProfile(const char *ifname, { int ret = 0; if (mode == VIR_NETDEV_MACVLAN_MODE_PASSTHRU) { - ifaceRestoreMacAddress(linkdev, stateDir); + ignore_value(virNetDevRestoreMacAddress(linkdev, stateDir)); } if (ifname) { -- 1.7.6.4

On 11/15/2011 06:14 AM, Daniel P. Berrange wrote:
From: "Daniel P. Berrange"<berrange@redhat.com>
Rename ifaceReplaceMacAddress to virNetDevReplaceMacAddress and ifaceRestoreMacAddress to virNetDevRestoreMacAddress.
* util/interface.c, util/interface.h, util/virnetdevmacvlan.c: Rename APIs --- src/libvirt_private.syms | 4 ++-- src/util/interface.c | 14 +++++++------- src/util/interface.h | 15 +++++++++------ src/util/virnetdevmacvlan.c | 5 ++--- 4 files changed, 20 insertions(+), 18 deletions(-)
ACK.

From: "Daniel P. Berrange" <berrange@redhat.com> Move virNetDevReplaceMacAddress and virNetDevRestoreMacAddress to the virnetdev.c file where they naturally belong * util/interface.c, util/interface.h: Remove virNetDevReplaceMacAddress and virNetDevRestoreMacAddress * util/virnetdev.c, util/virnetdev.h: Add virNetDevReplaceMacAddress and virNetDevRestoreMacAddress --- src/util/interface.c | 84 ---------------------------------------------- src/util/interface.h | 10 ----- src/util/virnetdev.c | 91 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/util/virnetdev.h | 12 ++++++ 4 files changed, 103 insertions(+), 94 deletions(-) diff --git a/src/util/interface.c b/src/util/interface.c index df2aa88..ebe537e 100644 --- a/src/util/interface.c +++ b/src/util/interface.c @@ -553,90 +553,6 @@ ifaceGetNthParent(int ifindex ATTRIBUTE_UNUSED, #endif -/** - * virNetDevReplaceMacAddress: - * @macaddress: new MAC address for interface - * @linkdev: name of interface - * @stateDir: directory to store old MAC address - * - * Returns 0 on success, -1 on failure - * - */ -int -virNetDevReplaceMacAddress(const char *linkdev, - const unsigned char *macaddress, - const char *stateDir) -{ - unsigned char oldmac[6]; - char *path = NULL; - char macstr[VIR_MAC_STRING_BUFLEN]; - - if (virNetDevGetMAC(linkdev, oldmac) < 0) - return -1; - - - if (virAsprintf(&path, "%s/%s", - stateDir, - linkdev) < 0) { - virReportOOMError(); - return -1; - } - virFormatMacAddr(oldmac, macstr); - if (virFileWriteStr(path, macstr, O_CREAT|O_TRUNC|O_WRONLY) < 0) { - virReportSystemError(errno, _("Unable to preserve mac for %s"), - linkdev); - return -1; - } - - if (virNetDevSetMAC(linkdev, macaddress) < 0) - return -1; - - return 0; -} - -/** - * virNetDevRestoreMacAddress: - * @linkdev: name of interface - * @stateDir: directory containing old MAC address - * - * Returns 0 on success, -errno on failure. - * - */ -int -virNetDevRestoreMacAddress(const char *linkdev, - const char *stateDir) -{ - int rc; - char *oldmacname = NULL; - char *macstr = NULL; - char *path = NULL; - unsigned char oldmac[6]; - - if (virAsprintf(&path, "%s/%s", - stateDir, - linkdev) < 0) { - virReportOOMError(); - return -1; - } - - if (virFileReadAll(path, VIR_MAC_STRING_BUFLEN, &macstr) < 0) - return -1; - - if (virParseMacAddr(macstr, &oldmac[0]) != 0) { - ifaceError(VIR_ERR_INTERNAL_ERROR, - _("Cannot parse MAC address from '%s'"), - oldmacname); - VIR_FREE(macstr); - return -1; - } - - /*reset mac and remove file-ignore results*/ - rc = virNetDevSetMAC(linkdev, oldmac); - ignore_value(unlink(path)); - VIR_FREE(macstr); - - return rc; -} #ifdef __linux__ static int diff --git a/src/util/interface.h b/src/util/interface.h index 6a4631c..e322a21 100644 --- a/src/util/interface.h +++ b/src/util/interface.h @@ -49,16 +49,6 @@ int ifaceGetNthParent(int ifindex, const char *ifname, unsigned int nthParent, ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(4) ATTRIBUTE_NONNULL(5) ATTRIBUTE_NONNULL(6); -int virNetDevReplaceMacAddress(const char *linkdev, - const unsigned char *macaddress, - const char *stateDir) - ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3) - ATTRIBUTE_RETURN_CHECK; - -int virNetDevRestoreMacAddress(const char *linkdev, - const char *stateDir) - ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_RETURN_CHECK; - int ifaceIsVirtualFunction(const char *ifname); int ifaceGetVirtualFunctionIndex(const char *pfname, const char *vfname, diff --git a/src/util/virnetdev.c b/src/util/virnetdev.c index 28aa1fb..230dbeb 100644 --- a/src/util/virnetdev.c +++ b/src/util/virnetdev.c @@ -32,8 +32,12 @@ #ifdef HAVE_NET_IF_H # include <net/if.h> #endif +#include <fcntl.h> #define VIR_FROM_THIS VIR_FROM_NONE +#define virNetDevError(code, ...) \ + virReportErrorHelper(VIR_FROM_THIS, code, __FILE__, \ + __FUNCTION__, __LINE__, __VA_ARGS__) #ifdef HAVE_NET_IF_H static int virNetDevSetupControlFull(const char *ifname, @@ -223,6 +227,93 @@ int virNetDevGetMAC(const char *ifname, #endif + +/** + * virNetDevReplaceMacAddress: + * @macaddress: new MAC address for interface + * @linkdev: name of interface + * @stateDir: directory to store old MAC address + * + * Returns 0 on success, -1 on failure + * + */ +int +virNetDevReplaceMacAddress(const char *linkdev, + const unsigned char *macaddress, + const char *stateDir) +{ + unsigned char oldmac[6]; + char *path = NULL; + char macstr[VIR_MAC_STRING_BUFLEN]; + + if (virNetDevGetMAC(linkdev, oldmac) < 0) + return -1; + + + if (virAsprintf(&path, "%s/%s", + stateDir, + linkdev) < 0) { + virReportOOMError(); + return -1; + } + virFormatMacAddr(oldmac, macstr); + if (virFileWriteStr(path, macstr, O_CREAT|O_TRUNC|O_WRONLY) < 0) { + virReportSystemError(errno, _("Unable to preserve mac for %s"), + linkdev); + return -1; + } + + if (virNetDevSetMAC(linkdev, macaddress) < 0) + return -1; + + return 0; +} + +/** + * virNetDevRestoreMacAddress: + * @linkdev: name of interface + * @stateDir: directory containing old MAC address + * + * Returns 0 on success, -errno on failure. + * + */ +int +virNetDevRestoreMacAddress(const char *linkdev, + const char *stateDir) +{ + int rc; + char *oldmacname = NULL; + char *macstr = NULL; + char *path = NULL; + unsigned char oldmac[6]; + + if (virAsprintf(&path, "%s/%s", + stateDir, + linkdev) < 0) { + virReportOOMError(); + return -1; + } + + if (virFileReadAll(path, VIR_MAC_STRING_BUFLEN, &macstr) < 0) + return -1; + + if (virParseMacAddr(macstr, &oldmac[0]) != 0) { + virNetDevError(VIR_ERR_INTERNAL_ERROR, + _("Cannot parse MAC address from '%s'"), + oldmacname); + VIR_FREE(macstr); + return -1; + } + + /*reset mac and remove file-ignore results*/ + rc = virNetDevSetMAC(linkdev, oldmac); + ignore_value(unlink(path)); + VIR_FREE(macstr); + + return rc; +} + + #ifdef SIOCGIFMTU /** * virNetDevGetMTU: diff --git a/src/util/virnetdev.h b/src/util/virnetdev.h index 0b0db84..84966d7 100644 --- a/src/util/virnetdev.h +++ b/src/util/virnetdev.h @@ -51,6 +51,18 @@ int virNetDevSetMAC(const char *ifname, int virNetDevGetMAC(const char *ifname, unsigned char *macaddr) ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_RETURN_CHECK; + +int virNetDevReplaceMacAddress(const char *linkdev, + const unsigned char *macaddress, + const char *stateDir) + ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3) + ATTRIBUTE_RETURN_CHECK; + +int virNetDevRestoreMacAddress(const char *linkdev, + const char *stateDir) + ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_RETURN_CHECK; + + int virNetDevSetMTU(const char *ifname, int mtu) ATTRIBUTE_NONNULL(1) ATTRIBUTE_RETURN_CHECK; -- 1.7.6.4

On 11/15/2011 06:14 AM, Daniel P. Berrange wrote:
Move virNetDevReplaceMacAddress and virNetDevRestoreMacAddress to the virnetdev.c file where they naturally belong
* util/interface.c, util/interface.h: Remove virNetDevReplaceMacAddress and virNetDevRestoreMacAddress * util/virnetdev.c, util/virnetdev.h: Add virNetDevReplaceMacAddress and virNetDevRestoreMacAddress --- src/util/interface.c | 84 ---------------------------------------------- src/util/interface.h | 10 ----- src/util/virnetdev.c | 91 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/util/virnetdev.h | 12 ++++++ 4 files changed, 103 insertions(+), 94 deletions(-)
ACK.

From: "Daniel P. Berrange" <berrange@redhat.com> Rename the ifaceGetIndex method to virNetDevGetIndex and ifaceGetVlanID to virNetDevGetVLanID. Also change the error reporting behaviour to always raise errors and return -1 on failure * util/interface.c, util/interface.h: Rename ifaceGetIndex and ifaceGetVLAN * nwfilter/nwfilter_gentech_driver.c, nwfilter/nwfilter_learnipaddr.c, nwfilter/nwfilter_learnipaddr.c, util/virnetdevvportprofile.c: Update for API renames and error handling changes --- src/libvirt_private.syms | 4 +- src/nwfilter/nwfilter_gentech_driver.c | 13 +++-- src/nwfilter/nwfilter_learnipaddr.c | 22 ++++--- src/util/interface.c | 103 ++++++++++++++++---------------- src/util/interface.h | 6 +- src/util/virnetdevmacvlan.c | 17 ++++-- src/util/virnetdevvportprofile.c | 6 +- 7 files changed, 92 insertions(+), 79 deletions(-) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index d71186b..e621f79 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -576,12 +576,12 @@ virHookPresent; # interface.h ifaceCheck; -ifaceGetIndex; +virNetDevGetIndex; ifaceGetIPAddress; ifaceGetNthParent; ifaceGetPhysicalFunction; ifaceGetVirtualFunctionIndex; -ifaceGetVlanID; +virNetDevGetVLanID; ifaceIsVirtualFunction; virNetDevMacVLanCreate; virNetDevMacVLanDelete; diff --git a/src/nwfilter/nwfilter_gentech_driver.c b/src/nwfilter/nwfilter_gentech_driver.c index 899bd32..9f44aef 100644 --- a/src/nwfilter/nwfilter_gentech_driver.c +++ b/src/nwfilter/nwfilter_gentech_driver.c @@ -903,9 +903,10 @@ _virNWFilterInstantiateFilter(virConnectPtr conn, /* after grabbing the filter update lock check for the interface; if it's not there anymore its filters will be or are being removed (while holding the lock) and we don't want to build new ones */ - if (ifaceGetIndex(false, net->ifname, &ifindex) < 0) { + if (virNetDevGetIndex(net->ifname, &ifindex) < 0) { /* interfaces / VMs can disappear during filter instantiation; don't mark it as an error */ + virResetLastError(); rc = 0; goto cleanup; } @@ -1021,8 +1022,9 @@ int virNWFilterRollbackUpdateFilter(virConnectPtr conn, } /* don't tear anything while the address is being learned */ - if (ifaceGetIndex(true, net->ifname, &ifindex) == 0 && - virNWFilterLookupLearnReq(ifindex) != NULL) + if (virNetDevGetIndex(net->ifname, &ifindex) < 0) + virResetLastError(); + else if (virNWFilterLookupLearnReq(ifindex) != NULL) return 0; return techdriver->tearNewRules(conn, net->ifname); @@ -1047,8 +1049,9 @@ virNWFilterTearOldFilter(virConnectPtr conn, } /* don't tear anything while the address is being learned */ - if (ifaceGetIndex(true, net->ifname, &ifindex) == 0 && - virNWFilterLookupLearnReq(ifindex) != NULL) + if (virNetDevGetIndex(net->ifname, &ifindex) < 0) + virResetLastError(); + else if (virNWFilterLookupLearnReq(ifindex) != NULL) return 0; return techdriver->tearOldRules(conn, net->ifname); diff --git a/src/nwfilter/nwfilter_learnipaddr.c b/src/nwfilter/nwfilter_learnipaddr.c index 68bdcfc..9a51fc2 100644 --- a/src/nwfilter/nwfilter_learnipaddr.c +++ b/src/nwfilter/nwfilter_learnipaddr.c @@ -252,21 +252,23 @@ virNWFilterTerminateLearnReq(const char *ifname) { int ifindex; virNWFilterIPAddrLearnReqPtr req; - if (ifaceGetIndex(false, ifname, &ifindex) == 0) { - - IFINDEX2STR(ifindex_str, ifindex); + if (virNetDevGetIndex(ifname, &ifindex) < 0) { + virResetLastError(); + return rc; + } - virMutexLock(&pendingLearnReqLock); + IFINDEX2STR(ifindex_str, ifindex); - req = virHashLookup(pendingLearnReq, ifindex_str); - if (req) { - rc = 0; - req->terminate = true; - } + virMutexLock(&pendingLearnReqLock); - virMutexUnlock(&pendingLearnReqLock); + req = virHashLookup(pendingLearnReq, ifindex_str); + if (req) { + rc = 0; + req->terminate = true; } + virMutexUnlock(&pendingLearnReqLock); + return rc; } diff --git a/src/util/interface.c b/src/util/interface.c index ebe537e..af1def2 100644 --- a/src/util/interface.c +++ b/src/util/interface.c @@ -115,8 +115,9 @@ ifaceCheck(bool reportError, const char *ifname, } if (ifindex != -1) { - rc = ifaceGetIndex(reportError, ifname, &idx); - if (rc == 0 && idx != ifindex) + if (virNetDevGetIndex(ifname, &idx) < 0) + virResetLastError(); + else if (idx != ifindex) rc = -ENODEV; } @@ -141,114 +142,112 @@ ifaceCheck(bool reportError ATTRIBUTE_UNUSED, /** - * ifaceGetIndex - * - * @reportError: whether to report errors or keep silent + * virNetDevGetIndex * @ifname : Name of the interface whose index is to be found * @ifindex: Pointer to int where the index will be written into * * Get the index of an interface given its name. * - * Returns 0 on success, -errno on failure. - * -ENODEV : if interface with given name does not exist - * -EINVAL : if interface name is invalid (too long) + * Returns 0 on success, -1 on failure */ #ifdef __linux__ int -ifaceGetIndex(bool reportError, const char *ifname, int *ifindex) +virNetDevGetIndex(const char *ifname, int *ifindex) { - int rc = 0; + int ret = -1; struct ifreq ifreq; int fd = socket(PF_PACKET, SOCK_DGRAM, 0); - if (fd < 0) - return -errno; + if (fd < 0) { + virReportSystemError(errno, "%s", + _("Unable to open control socket")); + return -1; + } memset(&ifreq, 0, sizeof(ifreq)); if (virStrncpy(ifreq.ifr_name, ifname, strlen(ifname), sizeof(ifreq.ifr_name)) == NULL) { - if (reportError) - ifaceError(VIR_ERR_INTERNAL_ERROR, - _("invalid interface name %s"), - ifname); - rc = -EINVAL; + virReportSystemError(ERANGE, + _("invalid interface name %s"), + ifname); goto cleanup; } - if (ioctl(fd, SIOCGIFINDEX, &ifreq) >= 0) - *ifindex = ifreq.ifr_ifindex; - else { - if (reportError) - ifaceError(VIR_ERR_INTERNAL_ERROR, - _("interface %s does not exist"), - ifname); - rc = -ENODEV; + if (ioctl(fd, SIOCGIFINDEX, &ifreq) < 0) { + virReportSystemError(errno, + _("Unable to get index for interface %s"), ifname); + goto cleanup; } + *ifindex = ifreq.ifr_ifindex; + ret = 0; + cleanup: VIR_FORCE_CLOSE(fd); - - return rc; + return ret; } #else int -ifaceGetIndex(bool reportError, - const char *ifname ATTRIBUTE_UNUSED, - int *ifindex ATTRIBUTE_UNUSED) +virNetDevGetIndex(const char *ifname ATTRIBUTE_UNUSED, + int *ifindex ATTRIBUTE_UNUSED) { - if (reportError) { - ifaceError(VIR_ERR_INTERNAL_ERROR, "%s", - _("ifaceGetIndex is not supported on non-linux platforms")); - } - - return -ENOSYS; + virReportSystemError(ENOSYS, "%s", + _("Unable to get interface index on this platform")); + return -1; } #endif /* __linux__ */ #ifdef __linux__ int -ifaceGetVlanID(const char *vlanifname, int *vlanid) { +virNetDevGetVLanID(const char *ifname, int *vlanid) +{ struct vlan_ioctl_args vlanargs = { .cmd = GET_VLAN_VID_CMD, }; - int rc = 0; + int ret = -1; int fd = socket(PF_PACKET, SOCK_DGRAM, 0); - if (fd < 0) - return -errno; + if (fd < 0) { + virReportSystemError(errno, "%s", + _("Unable to open control socket")); + return -1; + } - if (virStrcpyStatic(vlanargs.device1, vlanifname) == NULL) { - rc = -EINVAL; + if (virStrcpyStatic(vlanargs.device1, ifname) == NULL) { + virReportSystemError(ERANGE, + _("invalid interface name %s"), + ifname); goto cleanup; } if (ioctl(fd, SIOCGIFVLAN, &vlanargs) != 0) { - rc = -errno; + virReportSystemError(errno, + _("Unable to get VLAN for interface %s"), ifname); goto cleanup; } *vlanid = vlanargs.u.VID; + ret = 0; cleanup: VIR_FORCE_CLOSE(fd); - return rc; + return ret; } #else int -ifaceGetVlanID(const char *vlanifname ATTRIBUTE_UNUSED, - int *vlanid ATTRIBUTE_UNUSED) { - - ifaceError(VIR_ERR_INTERNAL_ERROR, "%s", - _("ifaceGetVlanID is not supported on non-linux platforms")); - - return -ENOSYS; +virNetDevGetVLanID(const char *ifname ATTRIBUTE_UNUSED, + int *vlanid ATTRIBUTE_UNUSED) +{ + virReportSystemError(ENOSYS, "%s", + _("Unable to get VLAN on this platform")); + return -1; } #endif /* __linux__ */ @@ -496,7 +495,7 @@ ifaceGetNthParent(int ifindex, const char *ifname, unsigned int nthParent, *nth = 0; - if (ifindex <= 0 && ifaceGetIndex(true, ifname, &ifindex) < 0) + if (ifindex <= 0 && virNetDevGetIndex(ifname, &ifindex) < 0) return -1; while (!end && i <= nthParent) { diff --git a/src/util/interface.h b/src/util/interface.h index e322a21..51d5c28 100644 --- a/src/util/interface.h +++ b/src/util/interface.h @@ -33,9 +33,11 @@ struct nlattr; int ifaceCheck(bool reportError, const char *ifname, const unsigned char *macaddr, int ifindex); -int ifaceGetIndex(bool reportError, const char *ifname, int *ifindex); +int virNetDevGetIndex(const char *ifname, int *ifindex) + ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_RETURN_CHECK; -int ifaceGetVlanID(const char *vlanifname, int *vlanid); +int virNetDevGetVLanID(const char *ifname, int *vlanid) + ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_RETURN_CHECK; int ifaceGetIPAddress(const char *ifname, virSocketAddrPtr addr); diff --git a/src/util/virnetdevmacvlan.c b/src/util/virnetdevmacvlan.c index 8e2e737..e3f90dd 100644 --- a/src/util/virnetdevmacvlan.c +++ b/src/util/virnetdevmacvlan.c @@ -107,7 +107,7 @@ virNetDevMacVLanCreate(const char *ifname, struct nl_msg *nl_msg; struct nlattr *linkinfo, *info_data; - if (ifaceGetIndex(true, srcdev, &ifindex) < 0) + if (virNetDevGetIndex(srcdev, &ifindex) < 0) return -1; *retry = 0; @@ -481,7 +481,7 @@ int virNetDevMacVLanCreateWithVPortProfile(const char *tgifname, int retries, do_retry = 0; uint32_t macvtapMode; const char *cr_ifname; - int ifindex; + int ret; macvtapMode = modeMap[mode]; @@ -502,13 +502,16 @@ int virNetDevMacVLanCreateWithVPortProfile(const char *tgifname, } if (tgifname) { - if(ifaceGetIndex(false, tgifname, &ifindex) == 0) { + if ((ret = virNetDevExists(tgifname)) < 0) + return -1; + + if (ret) { if (STRPREFIX(tgifname, MACVTAP_NAME_PREFIX)) { goto create_name; } - virReportSystemError(errno, - _("Interface %s already exists"), tgifname); + virReportSystemError(EEXIST, + _("Unable to create macvlan device %s"), tgifname); return -1; } cr_ifname = tgifname; @@ -521,7 +524,9 @@ create_name: retries = 5; for (c = 0; c < 8192; c++) { snprintf(ifname, sizeof(ifname), MACVTAP_NAME_PATTERN, c); - if (ifaceGetIndex(false, ifname, &ifindex) == -ENODEV) { + if ((ret = virNetDevExists(ifname)) < 0) + return -1; + if (!ret) { rc = virNetDevMacVLanCreate(ifname, type, macaddress, linkdev, macvtapMode, &do_retry); if (rc == 0) diff --git a/src/util/virnetdevvportprofile.c b/src/util/virnetdevvportprofile.c index ec86e2c..c49d514 100644 --- a/src/util/virnetdevvportprofile.c +++ b/src/util/virnetdevvportprofile.c @@ -544,8 +544,10 @@ virNetDevVPortProfileGetPhysdevAndVlan(const char *ifname, int *root_ifindex, ch if (nth == 0) break; if (*vlanid == -1) { - if (ifaceGetVlanID(root_ifname, vlanid) < 0) + if (virNetDevGetVLanID(root_ifname, vlanid) < 0) { + virResetLastError(); *vlanid = -1; + } } ifindex = *root_ifindex; @@ -676,7 +678,7 @@ virNetDevVPortProfileOp8021Qbh(const char *ifname, if (rc < 0) goto err_exit; - rc = ifaceGetIndex(true, physfndev, &ifindex); + rc = virNetDevGetIndex(physfndev, &ifindex); if (rc < 0) goto err_exit; -- 1.7.6.4

On 11/15/2011 06:14 AM, Daniel P. Berrange wrote:
From: "Daniel P. Berrange"<berrange@redhat.com>
Rename the ifaceGetIndex method to virNetDevGetIndex and ifaceGetVlanID to virNetDevGetVLanID. Also change the error reporting behaviour to always raise errors and return -1 on failure
* util/interface.c, util/interface.h: Rename ifaceGetIndex and ifaceGetVLAN * nwfilter/nwfilter_gentech_driver.c, nwfilter/nwfilter_learnipaddr.c, nwfilter/nwfilter_learnipaddr.c, util/virnetdevvportprofile.c: Update for API renames and error handling changes --- src/libvirt_private.syms | 4 +- src/nwfilter/nwfilter_gentech_driver.c | 13 +++-- src/nwfilter/nwfilter_learnipaddr.c | 22 ++++--- src/util/interface.c | 103 ++++++++++++++++---------------- src/util/interface.h | 6 +- src/util/virnetdevmacvlan.c | 17 ++++-- src/util/virnetdevvportprofile.c | 6 +- 7 files changed, 92 insertions(+), 79 deletions(-)
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index d71186b..e621f79 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -576,12 +576,12 @@ virHookPresent;
# interface.h ifaceCheck; -ifaceGetIndex; +virNetDevGetIndex; ifaceGetIPAddress; ifaceGetNthParent; ifaceGetPhysicalFunction; ifaceGetVirtualFunctionIndex; -ifaceGetVlanID; +virNetDevGetVLanID; ifaceIsVirtualFunction; virNetDevMacVLanCreate; virNetDevMacVLanDelete; diff --git a/src/nwfilter/nwfilter_gentech_driver.c b/src/nwfilter/nwfilter_gentech_driver.c index 899bd32..9f44aef 100644 --- a/src/nwfilter/nwfilter_gentech_driver.c +++ b/src/nwfilter/nwfilter_gentech_driver.c @@ -903,9 +903,10 @@ _virNWFilterInstantiateFilter(virConnectPtr conn, /* after grabbing the filter update lock check for the interface; if it's not there anymore its filters will be or are being removed (while holding the lock) and we don't want to build new ones */ - if (ifaceGetIndex(false, net->ifname,&ifindex)< 0) { + if (virNetDevGetIndex(net->ifname,&ifindex)< 0) { /* interfaces / VMs can disappear during filter instantiation; don't mark it as an error */ + virResetLastError();
But since the error has already been logged, it isn't really being ignored. Based on past experience with other "errors that aren't really errors", I'm betting this will lead to bogus bug reports (unless it's *extremely* rare, and requires doing something way out of the ordinary such that the admin might expect to get spurious error messages). Maybe virNetDevGetIndex could have some sort of "allow/ignore/dontreport failure" flag added?
diff --git a/src/nwfilter/nwfilter_learnipaddr.c b/src/nwfilter/nwfilter_learnipaddr.c index 68bdcfc..9a51fc2 100644 --- a/src/nwfilter/nwfilter_learnipaddr.c +++ b/src/nwfilter/nwfilter_learnipaddr.c @@ -252,21 +252,23 @@ virNWFilterTerminateLearnReq(const char *ifname) { int ifindex; virNWFilterIPAddrLearnReqPtr req;
- if (ifaceGetIndex(false, ifname,&ifindex) == 0) { - - IFINDEX2STR(ifindex_str, ifindex); + if (virNetDevGetIndex(ifname,&ifindex)< 0) { + virResetLastError(); + return rc; + }
- virMutexLock(&pendingLearnReqLock); + IFINDEX2STR(ifindex_str, ifindex);
- req = virHashLookup(pendingLearnReq, ifindex_str); - if (req) { - rc = 0; - req->terminate = true; - } + virMutexLock(&pendingLearnReqLock);
- virMutexUnlock(&pendingLearnReqLock); + req = virHashLookup(pendingLearnReq, ifindex_str); + if (req) { + rc = 0; + req->terminate = true; }
+ virMutexUnlock(&pendingLearnReqLock); + return rc;
git/diff didn't go to any pains to make *that* hunk easy to follow :-/ original: if (ifaceGetIndex(false, ifname,&ifindex) == 0) { IFINDEX2STR(ifindex_str, ifindex); virMutexLock(&pendingLearnReqLock); req = virHashLookup(pendingLearnReq, ifindex_str); if (req) { rc = 0; req->terminate = true; } virMutexUnlock(&pendingLearnReqLock); } return rc; vs new: if (virNetDevGetIndex(ifname,&ifindex)< 0) { virResetLastError(); return rc; } IFINDEX2STR(ifindex_str, ifindex); virMutexLock(&pendingLearnReqLock); req = virHashLookup(pendingLearnReq, ifindex_str); if (req) { rc = 0; req->terminate = true; } virMutexUnlock(&pendingLearnReqLock); return rc; so that looks okay (modulo the issue with virNetDevGetIndex errors being logged rather than ignored). I'm uncomfortable enough with the change in error behavior that I don't want to ACK this as-is.

On Thu, Nov 17, 2011 at 06:55:34AM -0500, Laine Stump wrote:
On 11/15/2011 06:14 AM, Daniel P. Berrange wrote:
From: "Daniel P. Berrange"<berrange@redhat.com>
Rename the ifaceGetIndex method to virNetDevGetIndex and ifaceGetVlanID to virNetDevGetVLanID. Also change the error reporting behaviour to always raise errors and return -1 on failure
* util/interface.c, util/interface.h: Rename ifaceGetIndex and ifaceGetVLAN * nwfilter/nwfilter_gentech_driver.c, nwfilter/nwfilter_learnipaddr.c, nwfilter/nwfilter_learnipaddr.c, util/virnetdevvportprofile.c: Update for API renames and error handling changes --- src/libvirt_private.syms | 4 +- src/nwfilter/nwfilter_gentech_driver.c | 13 +++-- src/nwfilter/nwfilter_learnipaddr.c | 22 ++++--- src/util/interface.c | 103 ++++++++++++++++---------------- src/util/interface.h | 6 +- src/util/virnetdevmacvlan.c | 17 ++++-- src/util/virnetdevvportprofile.c | 6 +- 7 files changed, 92 insertions(+), 79 deletions(-)
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index d71186b..e621f79 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -576,12 +576,12 @@ virHookPresent;
# interface.h ifaceCheck; -ifaceGetIndex; +virNetDevGetIndex; ifaceGetIPAddress; ifaceGetNthParent; ifaceGetPhysicalFunction; ifaceGetVirtualFunctionIndex; -ifaceGetVlanID; +virNetDevGetVLanID; ifaceIsVirtualFunction; virNetDevMacVLanCreate; virNetDevMacVLanDelete; diff --git a/src/nwfilter/nwfilter_gentech_driver.c b/src/nwfilter/nwfilter_gentech_driver.c index 899bd32..9f44aef 100644 --- a/src/nwfilter/nwfilter_gentech_driver.c +++ b/src/nwfilter/nwfilter_gentech_driver.c @@ -903,9 +903,10 @@ _virNWFilterInstantiateFilter(virConnectPtr conn, /* after grabbing the filter update lock check for the interface; if it's not there anymore its filters will be or are being removed (while holding the lock) and we don't want to build new ones */ - if (ifaceGetIndex(false, net->ifname,&ifindex)< 0) { + if (virNetDevGetIndex(net->ifname,&ifindex)< 0) { /* interfaces / VMs can disappear during filter instantiation; don't mark it as an error */ + virResetLastError();
But since the error has already been logged, it isn't really being ignored. Based on past experience with other "errors that aren't really errors", I'm betting this will lead to bogus bug reports (unless it's *extremely* rare, and requires doing something way out of the ordinary such that the admin might expect to get spurious error messages). Maybe virNetDevGetIndex could have some sort of "allow/ignore/dontreport failure" flag added?
The 'allow/ignore/dontreport' parameters are exactly the kind of thing I killed off in this patch server, because they end up polluting huge calls of functions. To avoid the log message in the ENODEV case it is easy enough to just add in a virNetDevExists() check to this block. Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|

From: "Daniel P. Berrange" <berrange@redhat.com> Move virNetDevGetIndex & virNetDevGetVLanID to virnetdev.c to suit their functional purpose * util/interface.c, util/interface.h: Remove virNetDevGetIndex & virNetDevGetVLanID * util/virnetdev.c, util/virnetdev.h: Add virNetDevGetIndex & virNetDevGetVLanID --- src/nwfilter/nwfilter_learnipaddr.c | 1 + src/util/interface.c | 111 ----------------------------------- src/util/interface.h | 6 -- src/util/virnetdev.c | 109 ++++++++++++++++++++++++++++++++++ src/util/virnetdev.h | 7 ++ 5 files changed, 117 insertions(+), 117 deletions(-) diff --git a/src/nwfilter/nwfilter_learnipaddr.c b/src/nwfilter/nwfilter_learnipaddr.c index 9a51fc2..319f317 100644 --- a/src/nwfilter/nwfilter_learnipaddr.c +++ b/src/nwfilter/nwfilter_learnipaddr.c @@ -46,6 +46,7 @@ #include "logging.h" #include "datatypes.h" #include "interface.h" +#include "virnetdev.h" #include "virterror_internal.h" #include "threads.h" #include "conf/nwfilter_params.h" diff --git a/src/util/interface.c b/src/util/interface.c index af1def2..9762145 100644 --- a/src/util/interface.c +++ b/src/util/interface.c @@ -142,117 +142,6 @@ ifaceCheck(bool reportError ATTRIBUTE_UNUSED, /** - * virNetDevGetIndex - * @ifname : Name of the interface whose index is to be found - * @ifindex: Pointer to int where the index will be written into - * - * Get the index of an interface given its name. - * - * Returns 0 on success, -1 on failure - */ -#ifdef __linux__ -int -virNetDevGetIndex(const char *ifname, int *ifindex) -{ - int ret = -1; - struct ifreq ifreq; - int fd = socket(PF_PACKET, SOCK_DGRAM, 0); - - if (fd < 0) { - virReportSystemError(errno, "%s", - _("Unable to open control socket")); - return -1; - } - - memset(&ifreq, 0, sizeof(ifreq)); - - if (virStrncpy(ifreq.ifr_name, ifname, strlen(ifname), - sizeof(ifreq.ifr_name)) == NULL) { - virReportSystemError(ERANGE, - _("invalid interface name %s"), - ifname); - goto cleanup; - } - - if (ioctl(fd, SIOCGIFINDEX, &ifreq) < 0) { - virReportSystemError(errno, - _("Unable to get index for interface %s"), ifname); - goto cleanup; - } - - *ifindex = ifreq.ifr_ifindex; - ret = 0; - -cleanup: - VIR_FORCE_CLOSE(fd); - return ret; -} - -#else - -int -virNetDevGetIndex(const char *ifname ATTRIBUTE_UNUSED, - int *ifindex ATTRIBUTE_UNUSED) -{ - virReportSystemError(ENOSYS, "%s", - _("Unable to get interface index on this platform")); - return -1; -} - -#endif /* __linux__ */ - -#ifdef __linux__ -int -virNetDevGetVLanID(const char *ifname, int *vlanid) -{ - struct vlan_ioctl_args vlanargs = { - .cmd = GET_VLAN_VID_CMD, - }; - int ret = -1; - int fd = socket(PF_PACKET, SOCK_DGRAM, 0); - - if (fd < 0) { - virReportSystemError(errno, "%s", - _("Unable to open control socket")); - return -1; - } - - if (virStrcpyStatic(vlanargs.device1, ifname) == NULL) { - virReportSystemError(ERANGE, - _("invalid interface name %s"), - ifname); - goto cleanup; - } - - if (ioctl(fd, SIOCGIFVLAN, &vlanargs) != 0) { - virReportSystemError(errno, - _("Unable to get VLAN for interface %s"), ifname); - goto cleanup; - } - - *vlanid = vlanargs.u.VID; - ret = 0; - - cleanup: - VIR_FORCE_CLOSE(fd); - - return ret; -} - -#else - -int -virNetDevGetVLanID(const char *ifname ATTRIBUTE_UNUSED, - int *vlanid ATTRIBUTE_UNUSED) -{ - virReportSystemError(ENOSYS, "%s", - _("Unable to get VLAN on this platform")); - return -1; -} -#endif /* __linux__ */ - - -/** * ifaceGetIPAddress: * @ifname: name of the interface whose IP address we want * @macaddr: MAC address (VIR_MAC_BUFLEN in size) diff --git a/src/util/interface.h b/src/util/interface.h index 51d5c28..aa70192 100644 --- a/src/util/interface.h +++ b/src/util/interface.h @@ -33,12 +33,6 @@ struct nlattr; int ifaceCheck(bool reportError, const char *ifname, const unsigned char *macaddr, int ifindex); -int virNetDevGetIndex(const char *ifname, int *ifindex) - ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_RETURN_CHECK; - -int virNetDevGetVLanID(const char *ifname, int *vlanid) - ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_RETURN_CHECK; - int ifaceGetIPAddress(const char *ifname, virSocketAddrPtr addr); int ifaceMacvtapLinkDump(bool nltarget_kernel, const char *ifname, int ifindex, diff --git a/src/util/virnetdev.c b/src/util/virnetdev.c index 230dbeb..c2a0f57 100644 --- a/src/util/virnetdev.c +++ b/src/util/virnetdev.c @@ -34,6 +34,11 @@ #endif #include <fcntl.h> +#ifdef __linux__ +# include <linux/sockios.h> +# include <linux/if_vlan.h> +#endif + #define VIR_FROM_THIS VIR_FROM_NONE #define virNetDevError(code, ...) \ virReportErrorHelper(VIR_FROM_THIS, code, __FILE__, \ @@ -612,6 +617,110 @@ int virNetDevIsOnline(const char *ifname, /** + * virNetDevGetIndex: + * @ifname : Name of the interface whose index is to be found + * @ifindex: Pointer to int where the index will be written into + * + * Get the index of an interface given its name. + * + * Returns 0 on success, -1 on failure + */ +#ifdef __linux__ +int virNetDevGetIndex(const char *ifname, int *ifindex) +{ + int ret = -1; + struct ifreq ifreq; + int fd = socket(PF_PACKET, SOCK_DGRAM, 0); + + if (fd < 0) { + virReportSystemError(errno, "%s", + _("Unable to open control socket")); + return -1; + } + + memset(&ifreq, 0, sizeof(ifreq)); + + if (virStrncpy(ifreq.ifr_name, ifname, strlen(ifname), + sizeof(ifreq.ifr_name)) == NULL) { + virReportSystemError(ERANGE, + _("invalid interface name %s"), + ifname); + goto cleanup; + } + + if (ioctl(fd, SIOCGIFINDEX, &ifreq) < 0) { + virReportSystemError(errno, + _("Unable to get index for interface %s"), ifname); + goto cleanup; + } + + *ifindex = ifreq.ifr_ifindex; + ret = 0; + +cleanup: + VIR_FORCE_CLOSE(fd); + return ret; +} +#else /* ! __linux__ */ +int virNetDevGetIndex(const char *ifname ATTRIBUTE_UNUSED, + int *ifindex ATTRIBUTE_UNUSED) +{ + virReportSystemError(ENOSYS, "%s", + _("Unable to get interface index on this platform")); + return -1; +} +#endif /* ! __linux__ */ + + +#ifdef __linux__ +int virNetDevGetVLanID(const char *ifname, int *vlanid) +{ + struct vlan_ioctl_args vlanargs = { + .cmd = GET_VLAN_VID_CMD, + }; + int ret = -1; + int fd = socket(PF_PACKET, SOCK_DGRAM, 0); + + if (fd < 0) { + virReportSystemError(errno, "%s", + _("Unable to open control socket")); + return -1; + } + + if (virStrcpyStatic(vlanargs.device1, ifname) == NULL) { + virReportSystemError(ERANGE, + _("invalid interface name %s"), + ifname); + goto cleanup; + } + + if (ioctl(fd, SIOCGIFVLAN, &vlanargs) != 0) { + virReportSystemError(errno, + _("Unable to get VLAN for interface %s"), ifname); + goto cleanup; + } + + *vlanid = vlanargs.u.VID; + ret = 0; + + cleanup: + VIR_FORCE_CLOSE(fd); + + return ret; +} +#else /* ! __linux__ */ +int virNetDevGetVLanID(const char *ifname ATTRIBUTE_UNUSED, + int *vlanid ATTRIBUTE_UNUSED) +{ + virReportSystemError(ENOSYS, "%s", + _("Unable to get VLAN on this platform")); + return -1; +} +#endif /* ! __linux__ */ + + + +/** * virNetDevSetIPv4Address: * @ifname: the interface name * @addr: the IP address (IPv4 or IPv6) diff --git a/src/util/virnetdev.h b/src/util/virnetdev.h index 84966d7..8c1d7c6 100644 --- a/src/util/virnetdev.h +++ b/src/util/virnetdev.h @@ -76,4 +76,11 @@ int virNetDevSetNamespace(const char *ifname, int pidInNs) int virNetDevSetName(const char *ifname, const char *newifname) ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_RETURN_CHECK; +int virNetDevGetIndex(const char *ifname, int *ifindex) + ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_RETURN_CHECK; + +int virNetDevGetVLanID(const char *ifname, int *vlanid) + ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_RETURN_CHECK; + + #endif /* __VIR_NETDEV_H__ */ -- 1.7.6.4

On 11/15/2011 06:14 AM, Daniel P. Berrange wrote:
From: "Daniel P. Berrange"<berrange@redhat.com>
Move virNetDevGetIndex& virNetDevGetVLanID to virnetdev.c to suit their functional purpose
* util/interface.c, util/interface.h: Remove virNetDevGetIndex& virNetDevGetVLanID * util/virnetdev.c, util/virnetdev.h: Add virNetDevGetIndex& virNetDevGetVLanID --- src/nwfilter/nwfilter_learnipaddr.c | 1 + src/util/interface.c | 111 ----------------------------------- src/util/interface.h | 6 -- src/util/virnetdev.c | 109 ++++++++++++++++++++++++++++++++++ src/util/virnetdev.h | 7 ++ 5 files changed, 117 insertions(+), 117 deletions(-)
ACK.

From: "Daniel P. Berrange" <berrange@redhat.com> To match up with the existing virNetDevSetIPv4Address, rename ifaceGetIPAddress to virNetDevGetIPv4Address * util/interface.h, util/interface.c: Rename API * network/bridge_driver.c: Update for API rename --- src/libvirt_private.syms | 2 +- src/network/bridge_driver.c | 11 +++------ src/util/interface.c | 46 +++++++++++++++++++++++------------------- src/util/interface.h | 3 +- 4 files changed, 32 insertions(+), 30 deletions(-) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index e621f79..13b3d27 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -577,7 +577,7 @@ virHookPresent; # interface.h ifaceCheck; virNetDevGetIndex; -ifaceGetIPAddress; +virNetDevGetIPv4Address; ifaceGetNthParent; ifaceGetPhysicalFunction; ifaceGetVirtualFunctionIndex; diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c index 5c84d86..f19bf51 100644 --- a/src/network/bridge_driver.c +++ b/src/network/bridge_driver.c @@ -3148,13 +3148,10 @@ networkGetNetworkAddress(const char *netname, char **netaddr) } if (dev_name) { - if (ifaceGetIPAddress(dev_name, &addr)) { - virReportSystemError(errno, - _("Failed to get IP address for '%s' (network '%s')"), - dev_name, netdef->name); - } else { - addrptr = &addr; - } + if (virNetDevGetIPv4Address(dev_name, &addr) < 0) + goto cleanup; + + addrptr = &addr; } if (addrptr && diff --git a/src/util/interface.c b/src/util/interface.c index 9762145..4e1ee25 100644 --- a/src/util/interface.c +++ b/src/util/interface.c @@ -142,60 +142,64 @@ ifaceCheck(bool reportError ATTRIBUTE_UNUSED, /** - * ifaceGetIPAddress: + * virNetDevGetIPv4Address: * @ifname: name of the interface whose IP address we want - * @macaddr: MAC address (VIR_MAC_BUFLEN in size) + * @addr: filled with the IPv4 address * - * This function gets the @macaddr for a given interface @ifname. + * This function gets the IPv4 address for the interface @ifname + * and stores it in @addr * * Returns 0 on success, -errno on failure. */ #ifdef __linux__ -int -ifaceGetIPAddress(const char *ifname, - virSocketAddrPtr addr) +int virNetDevGetIPv4Address(const char *ifname, + virSocketAddrPtr addr) { struct ifreq ifr; int fd; int rc = 0; - if (!ifname || !addr) - return -EINVAL; - memset (addr, 0, sizeof(*addr)); addr->data.stor.ss_family = AF_UNSPEC; fd = socket(AF_INET, SOCK_STREAM, 0); - if (fd < 0) - return -errno; + if (fd < 0) { + virReportSystemError(errno, "%s", + _("Unable to open control socket")); + return -1; + } memset(&ifr, 0, sizeof(struct ifreq)); if (virStrcpyStatic(ifr.ifr_name, ifname) == NULL) { - rc = -EINVAL; - goto err_exit; + virReportSystemError(ERANGE, + _("invalid interface name %s"), + ifname); + goto cleanup; } - if (ioctl(fd, SIOCGIFADDR, (char *)&ifr) != 0) { - rc = -errno; - goto err_exit; + if (ioctl(fd, SIOCGIFADDR, (char *)&ifr) < 0) { + virReportSystemError(errno, + _("Unable to get IPv4 address for interface %s"), ifname); + goto cleanup; } addr->data.stor.ss_family = AF_INET; addr->len = sizeof(addr->data.inet4); memcpy(&addr->data.inet4, &ifr.ifr_addr, addr->len); -err_exit: +cleanup: VIR_FORCE_CLOSE(fd); return rc; } #else -int -ifaceGetIPAddress(const char *ifname ATTRIBUTE_UNUSED, - virSocketAddrPtr addr ATTRIBUTE_UNUSED) +int virNetDevGetIPv4Address(const char *ifname ATTRIBUTE_UNUSED, + virSocketAddrPtr addr ATTRIBUTE_UNUSED) { - return -ENOSYS; + virReportSystemError(ENOSYS, "%s", + _("Unable to get IPv4 address on this platform")); + return -1; } #endif /* __linux__ */ diff --git a/src/util/interface.h b/src/util/interface.h index aa70192..0a11ecd 100644 --- a/src/util/interface.h +++ b/src/util/interface.h @@ -33,7 +33,8 @@ struct nlattr; int ifaceCheck(bool reportError, const char *ifname, const unsigned char *macaddr, int ifindex); -int ifaceGetIPAddress(const char *ifname, virSocketAddrPtr addr); +int virNetDevGetIPv4Address(const char *ifname, virSocketAddrPtr addr) + ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_RETURN_CHECK; int ifaceMacvtapLinkDump(bool nltarget_kernel, const char *ifname, int ifindex, struct nlattr **tb, unsigned char **recvbuf, -- 1.7.6.4

On 11/15/2011 06:14 AM, Daniel P. Berrange wrote:
From: "Daniel P. Berrange"<berrange@redhat.com>
To match up with the existing virNetDevSetIPv4Address, rename ifaceGetIPAddress to virNetDevGetIPv4Address
* util/interface.h, util/interface.c: Rename API * network/bridge_driver.c: Update for API rename --- src/libvirt_private.syms | 2 +- src/network/bridge_driver.c | 11 +++------ src/util/interface.c | 46 +++++++++++++++++++++++------------------- src/util/interface.h | 3 +- 4 files changed, 32 insertions(+), 30 deletions(-)
ACK.

From: "Daniel P. Berrange" <berrange@redhat.com> Move the virNetDevGetIPv4Address function to virnetdev.c * util/interface.c, util/interface.h: Remove virNetDevGetIPv4Address * util/virnetdev.c, util/virnetdev.h: Add virNetDevGetIPv4Address --- src/util/interface.c | 63 -------------------------------------------------- src/util/interface.h | 3 -- src/util/virnetdev.c | 53 ++++++++++++++++++++++++++++++++++++++++++ src/util/virnetdev.h | 2 + 4 files changed, 55 insertions(+), 66 deletions(-) diff --git a/src/util/interface.c b/src/util/interface.c index 4e1ee25..e86d183 100644 --- a/src/util/interface.c +++ b/src/util/interface.c @@ -141,69 +141,6 @@ ifaceCheck(bool reportError ATTRIBUTE_UNUSED, #endif /* __linux__ */ -/** - * virNetDevGetIPv4Address: - * @ifname: name of the interface whose IP address we want - * @addr: filled with the IPv4 address - * - * This function gets the IPv4 address for the interface @ifname - * and stores it in @addr - * - * Returns 0 on success, -errno on failure. - */ -#ifdef __linux__ -int virNetDevGetIPv4Address(const char *ifname, - virSocketAddrPtr addr) -{ - struct ifreq ifr; - int fd; - int rc = 0; - - memset (addr, 0, sizeof(*addr)); - addr->data.stor.ss_family = AF_UNSPEC; - - fd = socket(AF_INET, SOCK_STREAM, 0); - if (fd < 0) { - virReportSystemError(errno, "%s", - _("Unable to open control socket")); - return -1; - } - - memset(&ifr, 0, sizeof(struct ifreq)); - if (virStrcpyStatic(ifr.ifr_name, ifname) == NULL) { - virReportSystemError(ERANGE, - _("invalid interface name %s"), - ifname); - goto cleanup; - } - - if (ioctl(fd, SIOCGIFADDR, (char *)&ifr) < 0) { - virReportSystemError(errno, - _("Unable to get IPv4 address for interface %s"), ifname); - goto cleanup; - } - - addr->data.stor.ss_family = AF_INET; - addr->len = sizeof(addr->data.inet4); - memcpy(&addr->data.inet4, &ifr.ifr_addr, addr->len); - -cleanup: - VIR_FORCE_CLOSE(fd); - return rc; -} - -#else - -int virNetDevGetIPv4Address(const char *ifname ATTRIBUTE_UNUSED, - virSocketAddrPtr addr ATTRIBUTE_UNUSED) -{ - virReportSystemError(ENOSYS, "%s", - _("Unable to get IPv4 address on this platform")); - return -1; -} - -#endif /* __linux__ */ - #if defined(__linux__) && defined(IFLA_PORT_MAX) diff --git a/src/util/interface.h b/src/util/interface.h index 0a11ecd..afe417d 100644 --- a/src/util/interface.h +++ b/src/util/interface.h @@ -33,9 +33,6 @@ struct nlattr; int ifaceCheck(bool reportError, const char *ifname, const unsigned char *macaddr, int ifindex); -int virNetDevGetIPv4Address(const char *ifname, virSocketAddrPtr addr) - ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_RETURN_CHECK; - int ifaceMacvtapLinkDump(bool nltarget_kernel, const char *ifname, int ifindex, struct nlattr **tb, unsigned char **recvbuf, uint32_t (*getPidFunc)(void)); diff --git a/src/util/virnetdev.c b/src/util/virnetdev.c index c2a0f57..8a26d4a 100644 --- a/src/util/virnetdev.c +++ b/src/util/virnetdev.c @@ -803,3 +803,56 @@ cleanup: virCommandFree(cmd); return ret; } + + +/** + * virNetDevGetIPv4Address: + * @ifname: name of the interface whose IP address we want + * @addr: filled with the IPv4 address + * + * This function gets the IPv4 address for the interface @ifname + * and stores it in @addr + * + * Returns 0 on success, -errno on failure. + */ +#ifdef __linux__ +int virNetDevGetIPv4Address(const char *ifname, + virSocketAddrPtr addr) +{ + int fd = -1; + int ret = -1; + struct ifreq ifr; + + memset(addr, 0, sizeof(*addr)); + addr->data.stor.ss_family = AF_UNSPEC; + + if ((fd = virNetDevSetupControl(ifname, &ifr)) < 0) + return -1; + + if (ioctl(fd, SIOCGIFADDR, (char *)&ifr) < 0) { + virReportSystemError(errno, + _("Unable to get IPv4 address for interface %s"), ifname); + goto cleanup; + } + + addr->data.stor.ss_family = AF_INET; + addr->len = sizeof(addr->data.inet4); + memcpy(&addr->data.inet4, &ifr.ifr_addr, addr->len); + ret = 0; + +cleanup: + VIR_FORCE_CLOSE(fd); + return ret; +} + +#else + +int virNetDevGetIPv4Address(const char *ifname ATTRIBUTE_UNUSED, + virSocketAddrPtr addr ATTRIBUTE_UNUSED) +{ + virReportSystemError(ENOSYS, "%s", + _("Unable to get IPv4 address on this platform")); + return -1; +} + +#endif /* __linux__ */ diff --git a/src/util/virnetdev.h b/src/util/virnetdev.h index 8c1d7c6..08bbcbf 100644 --- a/src/util/virnetdev.h +++ b/src/util/virnetdev.h @@ -43,6 +43,8 @@ int virNetDevClearIPv4Address(const char *ifname, virSocketAddr *addr, unsigned int prefix) ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_RETURN_CHECK; +int virNetDevGetIPv4Address(const char *ifname, virSocketAddrPtr addr) + ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_RETURN_CHECK; int virNetDevSetMAC(const char *ifname, -- 1.7.6.4

On 11/15/2011 06:14 AM, Daniel P. Berrange wrote:
Move the virNetDevGetIPv4Address function to virnetdev.c
* util/interface.c, util/interface.h: Remove virNetDevGetIPv4Address * util/virnetdev.c, util/virnetdev.h: Add virNetDevGetIPv4Address --- src/util/interface.c | 63 -------------------------------------------------- src/util/interface.h | 3 -- src/util/virnetdev.c | 53 ++++++++++++++++++++++++++++++++++++++++++ src/util/virnetdev.h | 2 + 4 files changed, 55 insertions(+), 66 deletions(-)
ACK.

From: "Daniel P. Berrange" <berrange@redhat.com> Rename the ifaceCheck method to virNetDevValidateConfig and change so that it always raises an error and returns -1 on error. * src/util/interface.c, src/util/interface.h: Rename ifaceCheck to virNetDevValidateConfig * src/nwfilter/nwfilter_gentech_driver.c, src/nwfilter/nwfilter_learnipaddr.c: Update for API rename --- src/libvirt_private.syms | 2 +- src/nwfilter/nwfilter_gentech_driver.c | 6 ++- src/nwfilter/nwfilter_learnipaddr.c | 6 ++- src/util/interface.c | 83 ++++++++++++++++--------------- src/util/interface.h | 5 +- 5 files changed, 55 insertions(+), 47 deletions(-) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 13b3d27..761194b 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -575,7 +575,7 @@ virHookPresent; # interface.h -ifaceCheck; +virNetDevValidateConfig; virNetDevGetIndex; virNetDevGetIPv4Address; ifaceGetNthParent; diff --git a/src/nwfilter/nwfilter_gentech_driver.c b/src/nwfilter/nwfilter_gentech_driver.c index 9f44aef..9dffdc5 100644 --- a/src/nwfilter/nwfilter_gentech_driver.c +++ b/src/nwfilter/nwfilter_gentech_driver.c @@ -715,7 +715,8 @@ virNWFilterInstantiate(virConnectPtr conn, if (teardownOld && rc == 0) techdriver->tearOldRules(conn, ifname); - if (rc == 0 && (ifaceCheck(false, ifname, NULL, ifindex) < 0)) { + if (rc == 0 && (virNetDevValidateConfig(ifname, NULL, ifindex) <= 0)) { + virResetLastError(); /* interface changed/disppeared */ techdriver->allTeardown(ifname); rc = 1; @@ -963,8 +964,9 @@ virNWFilterInstantiateFilterLate(virConnectPtr conn, &foundNewFilter); if (rc) { /* something went wrong... 'DOWN' the interface */ - if ((ifaceCheck(false, ifname, NULL, ifindex) < 0) || + if ((virNetDevValidateConfig(ifname, NULL, ifindex) <= 0) || (virNetDevSetOnline(ifname, false) < 0)) { + virResetLastError(); /* assuming interface disappeared... */ _virNWFilterTeardownFilter(ifname); } diff --git a/src/nwfilter/nwfilter_learnipaddr.c b/src/nwfilter/nwfilter_learnipaddr.c index 319f317..03716ea 100644 --- a/src/nwfilter/nwfilter_learnipaddr.c +++ b/src/nwfilter/nwfilter_learnipaddr.c @@ -434,7 +434,8 @@ learnIPAddressThread(void *arg) req->status = 0; /* anything change to the VM's interface -- check at least once */ - if (ifaceCheck(false, req->ifname, NULL, req->ifindex) < 0) { + if (virNetDevValidateConfig(req->ifname, NULL, req->ifindex) <= 0) { + virResetLastError(); req->status = ENODEV; goto done; } @@ -504,7 +505,8 @@ learnIPAddressThread(void *arg) } /* check whether VM's dev is still there */ - if (ifaceCheck(false, req->ifname, NULL, req->ifindex) < 0) { + if (virNetDevValidateConfig(req->ifname, NULL, req->ifindex) <= 0) { + virResetLastError(); req->status = ENODEV; showError = false; break; diff --git a/src/util/interface.c b/src/util/interface.c index e86d183..16ad155 100644 --- a/src/util/interface.c +++ b/src/util/interface.c @@ -56,9 +56,7 @@ __FUNCTION__, __LINE__, __VA_ARGS__) /** - * ifaceCheck - * - * @reportError: whether to report errors or keep silent + * virNetDevValidateConfig: * @ifname: Name of the interface * @macaddr: expected MAC address of the interface; not checked if NULL * @ifindex: expected index of the interface; not checked if '-1' @@ -67,78 +65,83 @@ * it must have the given MAC address and if an interface index is * passed, it must also match the interface index. * - * Returns 0 on success, -errno on failure. - * -ENODEV : if interface with given name does not exist or its interface - * index is different than the one passed - * -EINVAL : if interface name is invalid (too long) + * Returns 1 if the config matches, 0 if the config does not match, or interface does not exist, -1 on error */ #ifdef __linux__ -int -ifaceCheck(bool reportError, const char *ifname, - const unsigned char *macaddr, int ifindex) +int virNetDevValidateConfig(const char *ifname, + const unsigned char *macaddr, int ifindex) { - struct ifreq ifr; int fd = -1; - int rc = 0; + int ret = -1; + struct ifreq ifr; int idx; + int rc; + + if ((rc = virNetDevExists(ifname)) < 0) + return -1; + if (rc == 0) { + ret = 0; + goto cleanup; + } if (macaddr != NULL) { fd = socket(PF_PACKET, SOCK_DGRAM, 0); - if (fd < 0) - return -errno; + if (fd < 0) { + virReportSystemError(errno, "%s", + _("Unable to open control socket")); + return -1; + } memset(&ifr, 0, sizeof(ifr)); if (virStrncpy(ifr.ifr_name, ifname, strlen(ifname), sizeof(ifr.ifr_name)) == NULL) { - if (reportError) - ifaceError(VIR_ERR_INTERNAL_ERROR, - _("invalid interface name %s"), - ifname); - rc = -EINVAL; + virReportSystemError(ERANGE, + _("invalid interface name %s"), + ifname); goto cleanup; } if (ioctl(fd, SIOCGIFHWADDR, &ifr) < 0) { - if (reportError) - ifaceError(VIR_ERR_INTERNAL_ERROR, - _("coud not get MAC address of interface %s"), - ifname); - rc = -errno; + if (errno == ENODEV) { + ret = 0; + goto cleanup; + } + virReportSystemError(errno, + _("coud not get MAC address of interface %s"), + ifname); goto cleanup; } if (memcmp(&ifr.ifr_hwaddr.sa_data, macaddr, VIR_MAC_BUFLEN) != 0) { - rc = -ENODEV; + ret = 0; goto cleanup; } } if (ifindex != -1) { if (virNetDevGetIndex(ifname, &idx) < 0) - virResetLastError(); - else if (idx != ifindex) - rc = -ENODEV; + goto cleanup; + else if (idx != ifindex) { + ret = 0; + goto cleanup; + } } + ret = 1; + cleanup: VIR_FORCE_CLOSE(fd); - - return rc; + return ret; } - -#else - -int -ifaceCheck(bool reportError ATTRIBUTE_UNUSED, - const char *ifname ATTRIBUTE_UNUSED, - const unsigned char *macaddr ATTRIBUTE_UNUSED, - int ifindex ATTRIBUTE_UNUSED) +#else /* ! __linux__ */ +int virNetDevValidateConfig(const char *ifname ATTRIBUTE_UNUSED, + const unsigned char *macaddr ATTRIBUTE_UNUSED, + int ifindex ATTRIBUTE_UNUSED) { return -ENOSYS; } - -#endif /* __linux__ */ +#endif /* ! __linux__ */ diff --git a/src/util/interface.h b/src/util/interface.h index afe417d..c230264 100644 --- a/src/util/interface.h +++ b/src/util/interface.h @@ -30,8 +30,9 @@ struct nlattr; # define NET_SYSFS "/sys/class/net/" -int ifaceCheck(bool reportError, const char *ifname, - const unsigned char *macaddr, int ifindex); +int virNetDevValidateConfig(const char *ifname, + const unsigned char *macaddr, int ifindex) + ATTRIBUTE_NONNULL(1) ATTRIBUTE_RETURN_CHECK; int ifaceMacvtapLinkDump(bool nltarget_kernel, const char *ifname, int ifindex, struct nlattr **tb, unsigned char **recvbuf, -- 1.7.6.4

On 11/15/2011 06:14 AM, Daniel P. Berrange wrote:
Rename the ifaceCheck method to virNetDevValidateConfig and change so that it always raises an error and returns -1 on error.
* src/util/interface.c, src/util/interface.h: Rename ifaceCheck to virNetDevValidateConfig * src/nwfilter/nwfilter_gentech_driver.c, src/nwfilter/nwfilter_learnipaddr.c: Update for API rename --- src/libvirt_private.syms | 2 +- src/nwfilter/nwfilter_gentech_driver.c | 6 ++- src/nwfilter/nwfilter_learnipaddr.c | 6 ++- src/util/interface.c | 83 ++++++++++++++++--------------- src/util/interface.h | 5 +- 5 files changed, 55 insertions(+), 47 deletions(-)
ACK. I just noticed that all of these patches rename the functions in libvirt_private.syms in place, so when it's all done, the functions aren't properly aligned with the .h file they're in, and are no longer in alphabetical order. There should be an extra patch ended at the end of the series to clean this up.

On Thu, Nov 17, 2011 at 07:01:52AM -0500, Laine Stump wrote:
On 11/15/2011 06:14 AM, Daniel P. Berrange wrote:
Rename the ifaceCheck method to virNetDevValidateConfig and change so that it always raises an error and returns -1 on error.
* src/util/interface.c, src/util/interface.h: Rename ifaceCheck to virNetDevValidateConfig * src/nwfilter/nwfilter_gentech_driver.c, src/nwfilter/nwfilter_learnipaddr.c: Update for API rename --- src/libvirt_private.syms | 2 +- src/nwfilter/nwfilter_gentech_driver.c | 6 ++- src/nwfilter/nwfilter_learnipaddr.c | 6 ++- src/util/interface.c | 83 ++++++++++++++++--------------- src/util/interface.h | 5 +- 5 files changed, 55 insertions(+), 47 deletions(-)
ACK.
I just noticed that all of these patches rename the functions in libvirt_private.syms in place, so when it's all done, the functions aren't properly aligned with the .h file they're in, and are no longer in alphabetical order. There should be an extra patch ended at the end of the series to clean this up.
Yes, I'll clean this up Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|

From: "Daniel P. Berrange" <berrange@redhat.com> * src/util/interface.c, src/util/interface.h: Remove virNetDevValidateConfig * src/util/virnetdev.c, src/util/virnetdev.h: Add virNetDevValidateConfig --- src/util/interface.c | 89 -------------------------------------------------- src/util/interface.h | 4 -- src/util/virnetdev.c | 77 +++++++++++++++++++++++++++++++++++++++++++ src/util/virnetdev.h | 4 ++ 4 files changed, 81 insertions(+), 93 deletions(-) diff --git a/src/util/interface.c b/src/util/interface.c index 16ad155..8264e7c 100644 --- a/src/util/interface.c +++ b/src/util/interface.c @@ -55,95 +55,6 @@ virReportErrorHelper(VIR_FROM_NET, code, __FILE__, \ __FUNCTION__, __LINE__, __VA_ARGS__) -/** - * virNetDevValidateConfig: - * @ifname: Name of the interface - * @macaddr: expected MAC address of the interface; not checked if NULL - * @ifindex: expected index of the interface; not checked if '-1' - * - * Determine whether a given interface is still available. If so, - * it must have the given MAC address and if an interface index is - * passed, it must also match the interface index. - * - * Returns 1 if the config matches, 0 if the config does not match, or interface does not exist, -1 on error - */ -#ifdef __linux__ -int virNetDevValidateConfig(const char *ifname, - const unsigned char *macaddr, int ifindex) -{ - int fd = -1; - int ret = -1; - struct ifreq ifr; - int idx; - int rc; - - if ((rc = virNetDevExists(ifname)) < 0) - return -1; - if (rc == 0) { - ret = 0; - goto cleanup; - } - - if (macaddr != NULL) { - fd = socket(PF_PACKET, SOCK_DGRAM, 0); - if (fd < 0) { - virReportSystemError(errno, "%s", - _("Unable to open control socket")); - return -1; - } - - memset(&ifr, 0, sizeof(ifr)); - - if (virStrncpy(ifr.ifr_name, - ifname, strlen(ifname), sizeof(ifr.ifr_name)) == NULL) { - virReportSystemError(ERANGE, - _("invalid interface name %s"), - ifname); - goto cleanup; - } - - if (ioctl(fd, SIOCGIFHWADDR, &ifr) < 0) { - if (errno == ENODEV) { - ret = 0; - goto cleanup; - } - virReportSystemError(errno, - _("coud not get MAC address of interface %s"), - ifname); - goto cleanup; - } - - if (memcmp(&ifr.ifr_hwaddr.sa_data, macaddr, VIR_MAC_BUFLEN) != 0) { - ret = 0; - goto cleanup; - } - } - - if (ifindex != -1) { - if (virNetDevGetIndex(ifname, &idx) < 0) - goto cleanup; - else if (idx != ifindex) { - ret = 0; - goto cleanup; - } - } - - ret = 1; - - cleanup: - VIR_FORCE_CLOSE(fd); - return ret; -} -#else /* ! __linux__ */ -int virNetDevValidateConfig(const char *ifname ATTRIBUTE_UNUSED, - const unsigned char *macaddr ATTRIBUTE_UNUSED, - int ifindex ATTRIBUTE_UNUSED) -{ - return -ENOSYS; -} -#endif /* ! __linux__ */ - - #if defined(__linux__) && defined(IFLA_PORT_MAX) diff --git a/src/util/interface.h b/src/util/interface.h index c230264..4256f29 100644 --- a/src/util/interface.h +++ b/src/util/interface.h @@ -30,10 +30,6 @@ struct nlattr; # define NET_SYSFS "/sys/class/net/" -int virNetDevValidateConfig(const char *ifname, - const unsigned char *macaddr, int ifindex) - ATTRIBUTE_NONNULL(1) ATTRIBUTE_RETURN_CHECK; - int ifaceMacvtapLinkDump(bool nltarget_kernel, const char *ifname, int ifindex, struct nlattr **tb, unsigned char **recvbuf, uint32_t (*getPidFunc)(void)); diff --git a/src/util/virnetdev.c b/src/util/virnetdev.c index 8a26d4a..4ad7883 100644 --- a/src/util/virnetdev.c +++ b/src/util/virnetdev.c @@ -856,3 +856,80 @@ int virNetDevGetIPv4Address(const char *ifname ATTRIBUTE_UNUSED, } #endif /* __linux__ */ + + +/** + * virNetDevValidateConfig: + * @ifname: Name of the interface + * @macaddr: expected MAC address of the interface; not checked if NULL + * @ifindex: expected index of the interface; not checked if '-1' + * + * Determine whether a given interface is still available. If so, + * it must have the given MAC address and if an interface index is + * passed, it must also match the interface index. + * + * Returns 1 if the config matches, 0 if the config does not match, or interface does not exist, -1 on error + */ +#ifdef __linux__ +int virNetDevValidateConfig(const char *ifname, + const unsigned char *macaddr, int ifindex) +{ + int fd = -1; + int ret = -1; + struct ifreq ifr; + int idx; + int rc; + + if ((rc = virNetDevExists(ifname)) < 0) + return -1; + if (rc == 0) { + ret = 0; + goto cleanup; + } + + if (macaddr != NULL) { + if ((fd = virNetDevSetupControl(ifname, &ifr)) < 0) + return -1; + + if (ioctl(fd, SIOCGIFHWADDR, &ifr) < 0) { + if (errno == ENODEV) { + ret = 0; + goto cleanup; + } + virReportSystemError(errno, + _("coud not get MAC address of interface %s"), + ifname); + goto cleanup; + } + + if (memcmp(&ifr.ifr_hwaddr.sa_data, macaddr, VIR_MAC_BUFLEN) != 0) { + ret = 0; + goto cleanup; + } + } + + if (ifindex != -1) { + if (virNetDevGetIndex(ifname, &idx) < 0) + goto cleanup; + else if (idx != ifindex) { + ret = 0; + goto cleanup; + } + } + + ret = 1; + + cleanup: + VIR_FORCE_CLOSE(fd); + return ret; +} +#else /* ! __linux__ */ +int virNetDevValidateConfig(const char *ifname ATTRIBUTE_UNUSED, + const unsigned char *macaddr ATTRIBUTE_UNUSED, + int ifindex ATTRIBUTE_UNUSED) +{ + virReportSystemError(ENOSYS, "%s", + _("Unable to check interface config on this platform")); + return -1; +} +#endif /* ! __linux__ */ diff --git a/src/util/virnetdev.h b/src/util/virnetdev.h index 08bbcbf..8628072 100644 --- a/src/util/virnetdev.h +++ b/src/util/virnetdev.h @@ -84,5 +84,9 @@ int virNetDevGetIndex(const char *ifname, int *ifindex) int virNetDevGetVLanID(const char *ifname, int *vlanid) ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_RETURN_CHECK; +int virNetDevValidateConfig(const char *ifname, + const unsigned char *macaddr, int ifindex) + ATTRIBUTE_NONNULL(1) ATTRIBUTE_RETURN_CHECK; + #endif /* __VIR_NETDEV_H__ */ -- 1.7.6.4

On 11/15/2011 06:14 AM, Daniel P. Berrange wrote:
* src/util/interface.c, src/util/interface.h: Remove virNetDevValidateConfig * src/util/virnetdev.c, src/util/virnetdev.h: Add virNetDevValidateConfig --- src/util/interface.c | 89 -------------------------------------------------- src/util/interface.h | 4 -- src/util/virnetdev.c | 77 +++++++++++++++++++++++++++++++++++++++++++ src/util/virnetdev.h | 4 ++ 4 files changed, 81 insertions(+), 93 deletions(-)
ACK.

From: "Daniel P. Berrange" <berrange@redhat.com> Rename ifaceIsVirtualFunction to virNetDevIsVirtualFunction, ifaceGetVirtualFunctionIndex to virNetDevGetVirtualFunctionIndex and ifaceGetPhysicalFunction to virNetDevGetPhysicalFunction * src/util/interface.c, src/util/interface.h: Rename APIs * src/util/virnetdevvportprofile.c: Update for API rename --- src/libvirt_private.syms | 6 ++-- src/util/interface.c | 54 +++++++++++++++++-------------------- src/util/interface.h | 12 +++++--- src/util/virnetdevvportprofile.c | 6 ++-- 4 files changed, 39 insertions(+), 39 deletions(-) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 761194b..0189875 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -579,10 +579,10 @@ virNetDevValidateConfig; virNetDevGetIndex; virNetDevGetIPv4Address; ifaceGetNthParent; -ifaceGetPhysicalFunction; -ifaceGetVirtualFunctionIndex; +virNetDevGetPhysicalFunction; +virNetDevGetVirtualFunctionIndex; virNetDevGetVLanID; -ifaceIsVirtualFunction; +virNetDevIsVirtualFunction; virNetDevMacVLanCreate; virNetDevMacVLanDelete; ifaceMacvtapLinkDump; diff --git a/src/util/interface.c b/src/util/interface.c index 8264e7c..2882511 100644 --- a/src/util/interface.c +++ b/src/util/interface.c @@ -299,7 +299,7 @@ ifaceGetNthParent(int ifindex ATTRIBUTE_UNUSED, #ifdef __linux__ static int -ifaceSysfsFile(char **pf_sysfs_device_link, const char *ifname, +virNetDevSysfsFile(char **pf_sysfs_device_link, const char *ifname, const char *file) { @@ -313,7 +313,7 @@ ifaceSysfsFile(char **pf_sysfs_device_link, const char *ifname, } static int -ifaceSysfsDeviceFile(char **pf_sysfs_device_link, const char *ifname, +virNetDevSysfsDeviceFile(char **pf_sysfs_device_link, const char *ifname, const char *file) { @@ -327,8 +327,7 @@ ifaceSysfsDeviceFile(char **pf_sysfs_device_link, const char *ifname, } /** - * ifaceIsVirtualFunction - * + * virNetDevIsVirtualFunction: * @ifname : name of the interface * * Checks if an interface is a SRIOV virtual function. @@ -337,12 +336,12 @@ ifaceSysfsDeviceFile(char **pf_sysfs_device_link, const char *ifname, * */ int -ifaceIsVirtualFunction(const char *ifname) +virNetDevIsVirtualFunction(const char *ifname) { char *if_sysfs_device_link = NULL; int ret = -1; - if (ifaceSysfsFile(&if_sysfs_device_link, ifname, "device") < 0) + if (virNetDevSysfsFile(&if_sysfs_device_link, ifname, "device") < 0) return ret; ret = pciDeviceIsVirtualFunction(if_sysfs_device_link); @@ -353,7 +352,7 @@ ifaceIsVirtualFunction(const char *ifname) } /** - * ifaceGetVirtualFunctionIndex + * virNetDevGetVirtualFunctionIndex * * @pfname : name of the physical function interface name * @vfname : name of the virtual function interface name @@ -364,16 +363,16 @@ ifaceIsVirtualFunction(const char *ifname) * */ int -ifaceGetVirtualFunctionIndex(const char *pfname, const char *vfname, - int *vf_index) +virNetDevGetVirtualFunctionIndex(const char *pfname, const char *vfname, + int *vf_index) { char *pf_sysfs_device_link = NULL, *vf_sysfs_device_link = NULL; int ret = -1; - if (ifaceSysfsFile(&pf_sysfs_device_link, pfname, "device") < 0) + if (virNetDevSysfsFile(&pf_sysfs_device_link, pfname, "device") < 0) return ret; - if (ifaceSysfsFile(&vf_sysfs_device_link, vfname, "device") < 0) { + if (virNetDevSysfsFile(&vf_sysfs_device_link, vfname, "device") < 0) { VIR_FREE(pf_sysfs_device_link); return ret; } @@ -389,7 +388,7 @@ ifaceGetVirtualFunctionIndex(const char *pfname, const char *vfname, } /** - * ifaceGetPhysicalFunction + * virNetDevGetPhysicalFunction * * @ifname : name of the physical function interface name * @pfname : Contains sriov physical function for interface ifname @@ -399,12 +398,12 @@ ifaceGetVirtualFunctionIndex(const char *pfname, const char *vfname, * */ int -ifaceGetPhysicalFunction(const char *ifname, char **pfname) +virNetDevGetPhysicalFunction(const char *ifname, char **pfname) { char *physfn_sysfs_path = NULL; int ret = -1; - if (ifaceSysfsDeviceFile(&physfn_sysfs_path, ifname, "physfn") < 0) + if (virNetDevSysfsDeviceFile(&physfn_sysfs_path, ifname, "physfn") < 0) return ret; ret = pciDeviceNetName(physfn_sysfs_path, pfname); @@ -413,34 +412,31 @@ ifaceGetPhysicalFunction(const char *ifname, char **pfname) return ret; } -#else +#else /* !__linux__ */ int -ifaceIsVirtualFunction(const char *ifname ATTRIBUTE_UNUSED) +virNetDevIsVirtualFunction(const char *ifname ATTRIBUTE_UNUSED) { - ifaceError(VIR_ERR_INTERNAL_ERROR, "%s", - _("ifaceIsVirtualFunction is not supported on non-linux " - "platforms")); + virReportSystemError(ENOSYS, "%s", + _("Unable to check virtual function status on this platfornm")); return -1; } int -ifaceGetVirtualFunctionIndex(const char *pfname ATTRIBUTE_UNUSED, +virNetDevGetVirtualFunctionIndex(const char *pfname ATTRIBUTE_UNUSED, const char *vfname ATTRIBUTE_UNUSED, int *vf_index ATTRIBUTE_UNUSED) { - ifaceError(VIR_ERR_INTERNAL_ERROR, "%s", - _("ifaceGetVirtualFunctionIndex is not supported on non-linux " - "platforms")); + virReportSystemError(ENOSYS, "%s", + _("Unable to get virtual function index on this platfornm")); return -1; } int -ifaceGetPhysicalFunction(const char *ifname ATTRIBUTE_UNUSED, - char **pfname ATTRIBUTE_UNUSED) +virNetDevGetPhysicalFunction(const char *ifname ATTRIBUTE_UNUSED, + char **pfname ATTRIBUTE_UNUSED) { - ifaceError(VIR_ERR_INTERNAL_ERROR, "%s", - _("ifaceGetPhysicalFunction is not supported on non-linux " - "platforms")); + virReportSystemError(ENOSYS, "%s", + _("Unable to get physical function status on this platfornm")); return -1; } -#endif /* __linux__ */ +#endif /* !__linux__ */ diff --git a/src/util/interface.h b/src/util/interface.h index 4256f29..86f9aac 100644 --- a/src/util/interface.h +++ b/src/util/interface.h @@ -40,11 +40,15 @@ int ifaceGetNthParent(int ifindex, const char *ifname, unsigned int nthParent, ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(4) ATTRIBUTE_NONNULL(5) ATTRIBUTE_NONNULL(6); -int ifaceIsVirtualFunction(const char *ifname); +int virNetDevIsVirtualFunction(const char *ifname) + ATTRIBUTE_NONNULL(1) ATTRIBUTE_RETURN_CHECK; -int ifaceGetVirtualFunctionIndex(const char *pfname, const char *vfname, - int *vf_index); +int virNetDevGetVirtualFunctionIndex(const char *pfname, const char *vfname, + int *vf_index) + ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3) + ATTRIBUTE_RETURN_CHECK; -int ifaceGetPhysicalFunction(const char *ifname, char **pfname); +int virNetDevGetPhysicalFunction(const char *ifname, char **pfname) + ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_RETURN_CHECK; #endif /* __VIR_INTERFACE_H__ */ diff --git a/src/util/virnetdevvportprofile.c b/src/util/virnetdevvportprofile.c index c49d514..9315281 100644 --- a/src/util/virnetdevvportprofile.c +++ b/src/util/virnetdevvportprofile.c @@ -630,13 +630,13 @@ virNetDevVPortProfileGetPhysfnDev(const char *linkdev, { int rc = -1; - if (ifaceIsVirtualFunction(linkdev) == 1) { + if (virNetDevIsVirtualFunction(linkdev) == 1) { /* if linkdev is SR-IOV VF, then set vf = VF index */ /* and set linkdev = PF device */ - rc = ifaceGetPhysicalFunction(linkdev, physfndev); + rc = virNetDevGetPhysicalFunction(linkdev, physfndev); if (!rc) - rc = ifaceGetVirtualFunctionIndex(*physfndev, linkdev, vf); + rc = virNetDevGetVirtualFunctionIndex(*physfndev, linkdev, vf); } else { /* Not SR-IOV VF: physfndev is linkdev and VF index -- 1.7.6.4

On 11/15/2011 06:14 AM, Daniel P. Berrange wrote:
Rename ifaceIsVirtualFunction to virNetDevIsVirtualFunction, ifaceGetVirtualFunctionIndex to virNetDevGetVirtualFunctionIndex and ifaceGetPhysicalFunction to virNetDevGetPhysicalFunction
* src/util/interface.c, src/util/interface.h: Rename APIs * src/util/virnetdevvportprofile.c: Update for API rename --- src/libvirt_private.syms | 6 ++-- src/util/interface.c | 54 +++++++++++++++++-------------------- src/util/interface.h | 12 +++++--- src/util/virnetdevvportprofile.c | 6 ++-- 4 files changed, 39 insertions(+), 39 deletions(-)
ACK.

From: "Daniel P. Berrange" <berrange@redhat.com> Move virNetDevIsVirtualFunction, virNetDevGetVirtualFunctionIndex and virNetDevGetPhysicalFunction to virnetdev.c * src/util/interface.c, src/util/interface.h, src/util/virnetdev.c, src/util/virnetdev.h: Move APIs --- src/util/interface.c | 146 ------------------------------------------------- src/util/interface.h | 13 ----- src/util/virnetdev.c | 148 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/util/virnetdev.h | 10 ++++ 4 files changed, 158 insertions(+), 159 deletions(-) diff --git a/src/util/interface.c b/src/util/interface.c index 2882511..00a873e 100644 --- a/src/util/interface.c +++ b/src/util/interface.c @@ -45,7 +45,6 @@ #include "virfile.h" #include "memory.h" #include "netlink.h" -#include "pci.h" #include "logging.h" #include "virnetdev.h" @@ -295,148 +294,3 @@ ifaceGetNthParent(int ifindex ATTRIBUTE_UNUSED, } #endif - - -#ifdef __linux__ -static int -virNetDevSysfsFile(char **pf_sysfs_device_link, const char *ifname, - const char *file) -{ - - if (virAsprintf(pf_sysfs_device_link, NET_SYSFS "%s/%s", - ifname, file) < 0) { - virReportOOMError(); - return -1; - } - - return 0; -} - -static int -virNetDevSysfsDeviceFile(char **pf_sysfs_device_link, const char *ifname, - const char *file) -{ - - if (virAsprintf(pf_sysfs_device_link, NET_SYSFS "%s/device/%s", - ifname, file) < 0) { - virReportOOMError(); - return -1; - } - - return 0; -} - -/** - * virNetDevIsVirtualFunction: - * @ifname : name of the interface - * - * Checks if an interface is a SRIOV virtual function. - * - * Returns 1 if interface is SRIOV virtual function, 0 if not and -1 if error - * - */ -int -virNetDevIsVirtualFunction(const char *ifname) -{ - char *if_sysfs_device_link = NULL; - int ret = -1; - - if (virNetDevSysfsFile(&if_sysfs_device_link, ifname, "device") < 0) - return ret; - - ret = pciDeviceIsVirtualFunction(if_sysfs_device_link); - - VIR_FREE(if_sysfs_device_link); - - return ret; -} - -/** - * virNetDevGetVirtualFunctionIndex - * - * @pfname : name of the physical function interface name - * @vfname : name of the virtual function interface name - * @vf_index : Pointer to int. Contains vf index of interface upon successful - * return - * - * Returns 0 on success, -1 on failure - * - */ -int -virNetDevGetVirtualFunctionIndex(const char *pfname, const char *vfname, - int *vf_index) -{ - char *pf_sysfs_device_link = NULL, *vf_sysfs_device_link = NULL; - int ret = -1; - - if (virNetDevSysfsFile(&pf_sysfs_device_link, pfname, "device") < 0) - return ret; - - if (virNetDevSysfsFile(&vf_sysfs_device_link, vfname, "device") < 0) { - VIR_FREE(pf_sysfs_device_link); - return ret; - } - - ret = pciGetVirtualFunctionIndex(pf_sysfs_device_link, - vf_sysfs_device_link, - vf_index); - - VIR_FREE(pf_sysfs_device_link); - VIR_FREE(vf_sysfs_device_link); - - return ret; -} - -/** - * virNetDevGetPhysicalFunction - * - * @ifname : name of the physical function interface name - * @pfname : Contains sriov physical function for interface ifname - * upon successful return - * - * Returns 0 on success, -1 on failure - * - */ -int -virNetDevGetPhysicalFunction(const char *ifname, char **pfname) -{ - char *physfn_sysfs_path = NULL; - int ret = -1; - - if (virNetDevSysfsDeviceFile(&physfn_sysfs_path, ifname, "physfn") < 0) - return ret; - - ret = pciDeviceNetName(physfn_sysfs_path, pfname); - - VIR_FREE(physfn_sysfs_path); - - return ret; -} -#else /* !__linux__ */ -int -virNetDevIsVirtualFunction(const char *ifname ATTRIBUTE_UNUSED) -{ - virReportSystemError(ENOSYS, "%s", - _("Unable to check virtual function status on this platfornm")); - return -1; -} - -int -virNetDevGetVirtualFunctionIndex(const char *pfname ATTRIBUTE_UNUSED, - const char *vfname ATTRIBUTE_UNUSED, - int *vf_index ATTRIBUTE_UNUSED) -{ - virReportSystemError(ENOSYS, "%s", - _("Unable to get virtual function index on this platfornm")); - return -1; -} - -int -virNetDevGetPhysicalFunction(const char *ifname ATTRIBUTE_UNUSED, - char **pfname ATTRIBUTE_UNUSED) -{ - virReportSystemError(ENOSYS, "%s", - _("Unable to get physical function status on this platfornm")); - return -1; -} -#endif /* !__linux__ */ diff --git a/src/util/interface.h b/src/util/interface.h index 86f9aac..141d19c 100644 --- a/src/util/interface.h +++ b/src/util/interface.h @@ -27,8 +27,6 @@ struct nlattr; # include "datatypes.h" # include "virsocketaddr.h" -# define NET_SYSFS "/sys/class/net/" - int ifaceMacvtapLinkDump(bool nltarget_kernel, const char *ifname, int ifindex, struct nlattr **tb, unsigned char **recvbuf, @@ -40,15 +38,4 @@ int ifaceGetNthParent(int ifindex, const char *ifname, unsigned int nthParent, ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(4) ATTRIBUTE_NONNULL(5) ATTRIBUTE_NONNULL(6); -int virNetDevIsVirtualFunction(const char *ifname) - ATTRIBUTE_NONNULL(1) ATTRIBUTE_RETURN_CHECK; - -int virNetDevGetVirtualFunctionIndex(const char *pfname, const char *vfname, - int *vf_index) - ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3) - ATTRIBUTE_RETURN_CHECK; - -int virNetDevGetPhysicalFunction(const char *ifname, char **pfname) - ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_RETURN_CHECK; - #endif /* __VIR_INTERFACE_H__ */ diff --git a/src/util/virnetdev.c b/src/util/virnetdev.c index 4ad7883..86196a1 100644 --- a/src/util/virnetdev.c +++ b/src/util/virnetdev.c @@ -27,6 +27,7 @@ #include "virterror_internal.h" #include "command.h" #include "memory.h" +#include "pci.h" #include <sys/ioctl.h> #ifdef HAVE_NET_IF_H @@ -933,3 +934,150 @@ int virNetDevValidateConfig(const char *ifname ATTRIBUTE_UNUSED, return -1; } #endif /* ! __linux__ */ + + +#ifdef __linux__ +# define NET_SYSFS "/sys/class/net/" + +static int +virNetDevSysfsFile(char **pf_sysfs_device_link, const char *ifname, + const char *file) +{ + + if (virAsprintf(pf_sysfs_device_link, NET_SYSFS "%s/%s", + ifname, file) < 0) { + virReportOOMError(); + return -1; + } + + return 0; +} + +static int +virNetDevSysfsDeviceFile(char **pf_sysfs_device_link, const char *ifname, + const char *file) +{ + + if (virAsprintf(pf_sysfs_device_link, NET_SYSFS "%s/device/%s", + ifname, file) < 0) { + virReportOOMError(); + return -1; + } + + return 0; +} + +/** + * virNetDevIsVirtualFunction: + * @ifname : name of the interface + * + * Checks if an interface is a SRIOV virtual function. + * + * Returns 1 if interface is SRIOV virtual function, 0 if not and -1 if error + * + */ +int +virNetDevIsVirtualFunction(const char *ifname) +{ + char *if_sysfs_device_link = NULL; + int ret = -1; + + if (virNetDevSysfsFile(&if_sysfs_device_link, ifname, "device") < 0) + return ret; + + ret = pciDeviceIsVirtualFunction(if_sysfs_device_link); + + VIR_FREE(if_sysfs_device_link); + + return ret; +} + +/** + * virNetDevGetVirtualFunctionIndex + * + * @pfname : name of the physical function interface name + * @vfname : name of the virtual function interface name + * @vf_index : Pointer to int. Contains vf index of interface upon successful + * return + * + * Returns 0 on success, -1 on failure + * + */ +int +virNetDevGetVirtualFunctionIndex(const char *pfname, const char *vfname, + int *vf_index) +{ + char *pf_sysfs_device_link = NULL, *vf_sysfs_device_link = NULL; + int ret = -1; + + if (virNetDevSysfsFile(&pf_sysfs_device_link, pfname, "device") < 0) + return ret; + + if (virNetDevSysfsFile(&vf_sysfs_device_link, vfname, "device") < 0) { + VIR_FREE(pf_sysfs_device_link); + return ret; + } + + ret = pciGetVirtualFunctionIndex(pf_sysfs_device_link, + vf_sysfs_device_link, + vf_index); + + VIR_FREE(pf_sysfs_device_link); + VIR_FREE(vf_sysfs_device_link); + + return ret; +} + +/** + * virNetDevGetPhysicalFunction + * + * @ifname : name of the physical function interface name + * @pfname : Contains sriov physical function for interface ifname + * upon successful return + * + * Returns 0 on success, -1 on failure + * + */ +int +virNetDevGetPhysicalFunction(const char *ifname, char **pfname) +{ + char *physfn_sysfs_path = NULL; + int ret = -1; + + if (virNetDevSysfsDeviceFile(&physfn_sysfs_path, ifname, "physfn") < 0) + return ret; + + ret = pciDeviceNetName(physfn_sysfs_path, pfname); + + VIR_FREE(physfn_sysfs_path); + + return ret; +} +#else /* !__linux__ */ +int +virNetDevIsVirtualFunction(const char *ifname ATTRIBUTE_UNUSED) +{ + virReportSystemError(ENOSYS, "%s", + _("Unable to check virtual function status on this platfornm")); + return -1; +} + +int +virNetDevGetVirtualFunctionIndex(const char *pfname ATTRIBUTE_UNUSED, + const char *vfname ATTRIBUTE_UNUSED, + int *vf_index ATTRIBUTE_UNUSED) +{ + virReportSystemError(ENOSYS, "%s", + _("Unable to get virtual function index on this platfornm")); + return -1; +} + +int +virNetDevGetPhysicalFunction(const char *ifname ATTRIBUTE_UNUSED, + char **pfname ATTRIBUTE_UNUSED) +{ + virReportSystemError(ENOSYS, "%s", + _("Unable to get physical function status on this platfornm")); + return -1; +} +#endif /* !__linux__ */ diff --git a/src/util/virnetdev.h b/src/util/virnetdev.h index 8628072..13ba1da 100644 --- a/src/util/virnetdev.h +++ b/src/util/virnetdev.h @@ -88,5 +88,15 @@ int virNetDevValidateConfig(const char *ifname, const unsigned char *macaddr, int ifindex) ATTRIBUTE_NONNULL(1) ATTRIBUTE_RETURN_CHECK; +int virNetDevIsVirtualFunction(const char *ifname) + ATTRIBUTE_NONNULL(1) ATTRIBUTE_RETURN_CHECK; + +int virNetDevGetVirtualFunctionIndex(const char *pfname, const char *vfname, + int *vf_index) + ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3) + ATTRIBUTE_RETURN_CHECK; + +int virNetDevGetPhysicalFunction(const char *ifname, char **pfname) + ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_RETURN_CHECK; #endif /* __VIR_NETDEV_H__ */ -- 1.7.6.4

On 11/15/2011 06:14 AM, Daniel P. Berrange wrote:
Move virNetDevIsVirtualFunction, virNetDevGetVirtualFunctionIndex and virNetDevGetPhysicalFunction to virnetdev.c
* src/util/interface.c, src/util/interface.h, src/util/virnetdev.c, src/util/virnetdev.h: Move APIs --- src/util/interface.c | 146 ------------------------------------------------- src/util/interface.h | 13 ----- src/util/virnetdev.c | 148 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/util/virnetdev.h | 10 ++++ 4 files changed, 158 insertions(+), 159 deletions(-)
ACK.

From: "Daniel P. Berrange" <berrange@redhat.com> Move the ifaceMacvtapLinkDump and ifaceGetNthParent functions into virnetdevvportprofile.c since they are specific to that code. This avoids polluting the headers with the Linux specific netlink data types * src/util/interface.c, src/util/interface.h: Move ifaceMacvtapLinkDump and ifaceGetNthParent functions and delete remaining file * src/util/virnetdevvportprofile.c: Add ifaceMacvtapLinkDump and ifaceGetNthParent functions * src/network/bridge_driver.c, src/nwfilter/nwfilter_gentech_driver.c, src/nwfilter/nwfilter_learnipaddr.c, src/util/virnetdevmacvlan.c: Remove include of interface.h --- po/POTFILES.in | 1 - src/Makefile.am | 1 - src/libvirt_private.syms | 2 - src/network/bridge_driver.c | 1 - src/nwfilter/nwfilter_gentech_driver.c | 2 +- src/nwfilter/nwfilter_learnipaddr.c | 1 - src/util/interface.c | 296 -------------------------------- src/util/interface.h | 41 ----- src/util/virnetdevmacvlan.c | 1 - src/util/virnetdevvportprofile.c | 199 +++++++++++++++++++++- 10 files changed, 195 insertions(+), 350 deletions(-) delete mode 100644 src/util/interface.c delete mode 100644 src/util/interface.h diff --git a/po/POTFILES.in b/po/POTFILES.in index 6797298..403d94b 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -112,7 +112,6 @@ src/util/hash.c src/util/hooks.c src/util/hostusb.c src/util/iohelper.c -src/util/interface.c src/util/iptables.c src/util/json.c src/util/netlink.c diff --git a/src/Makefile.am b/src/Makefile.am index e44c53a..f82be78 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -72,7 +72,6 @@ UTIL_SOURCES = \ util/pci.c util/pci.h \ util/processinfo.c util/processinfo.h \ util/hostusb.c util/hostusb.h \ - util/interface.c util/interface.h \ util/qparams.c util/qparams.h \ util/sexpr.c util/sexpr.h \ util/stats_linux.c util/stats_linux.h \ diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 0189875..131d856 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -578,14 +578,12 @@ virHookPresent; virNetDevValidateConfig; virNetDevGetIndex; virNetDevGetIPv4Address; -ifaceGetNthParent; virNetDevGetPhysicalFunction; virNetDevGetVirtualFunctionIndex; virNetDevGetVLanID; virNetDevIsVirtualFunction; virNetDevMacVLanCreate; virNetDevMacVLanDelete; -ifaceMacvtapLinkDump; virNetDevReplaceMacAddress; virNetDevRestoreMacAddress; diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c index f19bf51..7bea465 100644 --- a/src/network/bridge_driver.c +++ b/src/network/bridge_driver.c @@ -55,7 +55,6 @@ #include "memory.h" #include "uuid.h" #include "iptables.h" -#include "interface.h" #include "logging.h" #include "dnsmasq.h" #include "configmake.h" diff --git a/src/nwfilter/nwfilter_gentech_driver.c b/src/nwfilter/nwfilter_gentech_driver.c index 9dffdc5..c9c1415 100644 --- a/src/nwfilter/nwfilter_gentech_driver.c +++ b/src/nwfilter/nwfilter_gentech_driver.c @@ -28,13 +28,13 @@ #include "memory.h" #include "logging.h" -#include "interface.h" #include "domain_conf.h" #include "virterror_internal.h" #include "nwfilter_gentech_driver.h" #include "nwfilter_ebiptables_driver.h" #include "nwfilter_learnipaddr.h" #include "virnetdev.h" +#include "datatypes.h" #define VIR_FROM_THIS VIR_FROM_NWFILTER diff --git a/src/nwfilter/nwfilter_learnipaddr.c b/src/nwfilter/nwfilter_learnipaddr.c index 03716ea..1843c98 100644 --- a/src/nwfilter/nwfilter_learnipaddr.c +++ b/src/nwfilter/nwfilter_learnipaddr.c @@ -45,7 +45,6 @@ #include "memory.h" #include "logging.h" #include "datatypes.h" -#include "interface.h" #include "virnetdev.h" #include "virterror_internal.h" #include "threads.h" diff --git a/src/util/interface.c b/src/util/interface.c deleted file mode 100644 index 00a873e..0000000 --- a/src/util/interface.c +++ /dev/null @@ -1,296 +0,0 @@ -/* - * interface.c: interface support functions - * - * Copyright (C) 2011 Red Hat, Inc. - * Copyright (C) 2010 IBM Corp. - * Copyright (C) 2010 Stefan Berger - * - * 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 - * - * chgIfaceFlags originated from bridge.c - * - * Author: Stefan Berger <stefanb@us.ibm.com> - */ - -#include <config.h> - -#include <sys/socket.h> -#include <sys/ioctl.h> -#include <fcntl.h> -#include <netinet/in.h> - -#ifdef __linux__ -# include <linux/if.h> -# include <linux/sockios.h> -# include <linux/if_vlan.h> -#endif - -#include "internal.h" - -#include "util.h" -#include "interface.h" -#include "virterror_internal.h" -#include "virfile.h" -#include "memory.h" -#include "netlink.h" -#include "logging.h" -#include "virnetdev.h" - -#define VIR_FROM_THIS VIR_FROM_NET - -#define ifaceError(code, ...) \ - virReportErrorHelper(VIR_FROM_NET, code, __FILE__, \ - __FUNCTION__, __LINE__, __VA_ARGS__) - - -#if defined(__linux__) && defined(IFLA_PORT_MAX) - -static struct nla_policy ifla_policy[IFLA_MAX + 1] = -{ - [IFLA_VF_PORTS] = { .type = NLA_NESTED }, -}; - -/** - * ifaceMacvtapLinkDump - * - * @nltarget_kernel: whether to send the message to the kernel or another - * process - * @ifname: The name of the interface; only use if ifindex < 0 - * @ifindex: The interface index; may be < 0 if ifname is given - * @nlattr: pointer to a pointer of netlink attributes that will contain - * the results - * @recvbuf: Pointer to the buffer holding the returned netlink response - * message; free it, once not needed anymore - * @getPidFunc: Pointer to a function that will be invoked if the kernel - * is not the target of the netlink message but it is to be - * sent to another process. - * - * Get information about an interface given its name or index. - * - * Returns 0 on success, -1 on fatal error. - */ -int -ifaceMacvtapLinkDump(bool nltarget_kernel, const char *ifname, int ifindex, - struct nlattr **tb, unsigned char **recvbuf, - uint32_t (*getPidFunc)(void)) -{ - int rc = 0; - struct nlmsghdr *resp; - struct nlmsgerr *err; - struct ifinfomsg ifinfo = { - .ifi_family = AF_UNSPEC, - .ifi_index = ifindex - }; - unsigned int recvbuflen; - uint32_t pid = 0; - struct nl_msg *nl_msg; - - *recvbuf = NULL; - - nl_msg = nlmsg_alloc_simple(RTM_GETLINK, NLM_F_REQUEST); - if (!nl_msg) { - virReportOOMError(); - return -1; - } - - if (nlmsg_append(nl_msg, &ifinfo, sizeof(ifinfo), NLMSG_ALIGNTO) < 0) - goto buffer_too_small; - - if (ifindex < 0 && ifname) { - if (nla_put(nl_msg, IFLA_IFNAME, strlen(ifname)+1, ifname) < 0) - goto buffer_too_small; - } - - if (!nltarget_kernel) { - pid = getPidFunc(); - if (pid == 0) { - rc = -1; - goto cleanup; - } - } - - if (nlComm(nl_msg, recvbuf, &recvbuflen, pid) < 0) { - rc = -1; - goto cleanup; - } - - if (recvbuflen < NLMSG_LENGTH(0) || *recvbuf == NULL) - goto malformed_resp; - - resp = (struct nlmsghdr *)*recvbuf; - - switch (resp->nlmsg_type) { - case NLMSG_ERROR: - err = (struct nlmsgerr *)NLMSG_DATA(resp); - if (resp->nlmsg_len < NLMSG_LENGTH(sizeof(*err))) - goto malformed_resp; - - if (err->error) { - virReportSystemError(-err->error, - _("error dumping %s (%d) interface"), - ifname, ifindex); - rc = -1; - } - break; - - case GENL_ID_CTRL: - case NLMSG_DONE: - if (nlmsg_parse(resp, sizeof(struct ifinfomsg), - tb, IFLA_MAX, ifla_policy)) { - goto malformed_resp; - } - break; - - default: - goto malformed_resp; - } - - if (rc != 0) - VIR_FREE(*recvbuf); - -cleanup: - nlmsg_free(nl_msg); - - return rc; - -malformed_resp: - nlmsg_free(nl_msg); - - ifaceError(VIR_ERR_INTERNAL_ERROR, "%s", - _("malformed netlink response message")); - VIR_FREE(*recvbuf); - return -1; - -buffer_too_small: - nlmsg_free(nl_msg); - - ifaceError(VIR_ERR_INTERNAL_ERROR, "%s", - _("allocated netlink buffer is too small")); - return -1; -} - -#else - -int -ifaceMacvtapLinkDump(bool nltarget_kernel ATTRIBUTE_UNUSED, - const char *ifname ATTRIBUTE_UNUSED, - int ifindex ATTRIBUTE_UNUSED, - struct nlattr **tb ATTRIBUTE_UNUSED, - unsigned char **recvbuf ATTRIBUTE_UNUSED, - uint32_t (*getPidFunc)(void) ATTRIBUTE_UNUSED) -{ - ifaceError(VIR_ERR_INTERNAL_ERROR, "%s", -# if defined(__linux__) && !defined(IFLA_PORT_MAX) - _("ifaceMacvtapLinkDump is not supported since the include " - "files were too old")); -# else - _("ifaceMacvtapLinkDump is not supported on non-linux " - "platforms")); -# endif - - return -1; -} - -#endif - - -/** - * ifaceGetNthParent - * - * @ifindex : the index of the interface or -1 if ifname is given - * @ifname : the name of the interface; ignored if ifindex is valid - * @nthParent : the nth parent interface to get - * @parent_ifindex : pointer to int - * @parent_ifname : pointer to buffer of size IFNAMSIZ - * @nth : the nth parent that is actually returned; if for example eth0.100 - * was given and the 100th parent is to be returned, then eth0 will - * most likely be returned with nth set to 1 since the chain does - * not have more interfaces - * - * Get the nth parent interface of the given interface. 0 is the interface - * itself. - * - * Return 0 on success, < 0 otherwise - */ -#if defined(__linux__) && WITH_MACVTAP -int -ifaceGetNthParent(int ifindex, const char *ifname, unsigned int nthParent, - int *parent_ifindex, char *parent_ifname, - unsigned int *nth) -{ - int rc; - struct nlattr *tb[IFLA_MAX + 1] = { NULL, }; - unsigned char *recvbuf = NULL; - bool end = false; - unsigned int i = 0; - - *nth = 0; - - if (ifindex <= 0 && virNetDevGetIndex(ifname, &ifindex) < 0) - return -1; - - while (!end && i <= nthParent) { - rc = ifaceMacvtapLinkDump(true, ifname, ifindex, tb, &recvbuf, NULL); - if (rc < 0) - break; - - if (tb[IFLA_IFNAME]) { - if (!virStrcpy(parent_ifname, (char*)RTA_DATA(tb[IFLA_IFNAME]), - IFNAMSIZ)) { - ifaceError(VIR_ERR_INTERNAL_ERROR, "%s", - _("buffer for root interface name is too small")); - VIR_FREE(recvbuf); - return -1; - } - *parent_ifindex = ifindex; - } - - if (tb[IFLA_LINK]) { - ifindex = *(int *)RTA_DATA(tb[IFLA_LINK]); - ifname = NULL; - } else - end = true; - - VIR_FREE(recvbuf); - - i++; - } - - *nth = i - 1; - - return rc; -} - -#else - -int -ifaceGetNthParent(int ifindex ATTRIBUTE_UNUSED, - const char *ifname ATTRIBUTE_UNUSED, - unsigned int nthParent ATTRIBUTE_UNUSED, - int *parent_ifindex ATTRIBUTE_UNUSED, - char *parent_ifname ATTRIBUTE_UNUSED, - unsigned int *nth ATTRIBUTE_UNUSED) -{ - ifaceError(VIR_ERR_INTERNAL_ERROR, "%s", -# if defined(__linux__) && !WITH_MACVTAP - _("ifaceGetNthParent is not supported since the include files " - "were too old")); -# else - _("ifaceGetNthParent is not supported on non-linux platforms")); -# endif - return -1; -} - -#endif diff --git a/src/util/interface.h b/src/util/interface.h deleted file mode 100644 index 141d19c..0000000 --- a/src/util/interface.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * interface.h: interface helper APIs for libvirt - * - * Copyright (C) 2011 Red Hat, Inc. - * Copyright (C) 2010 IBM Corporation, Inc. - * - * See COPYING.LIB for the License of this software - * - * Stefan Berger <stefanb@us.ibm.com> - */ -#ifndef __VIR_INTERFACE_H__ -# define __VIR_INTERFACE_H__ - -# include <stdint.h> - -# if __linux__ - -# include <sys/socket.h> -# include <linux/netlink.h> - -# else - -struct nlattr; - -# endif - -# include "datatypes.h" -# include "virsocketaddr.h" - - -int ifaceMacvtapLinkDump(bool nltarget_kernel, const char *ifname, int ifindex, - struct nlattr **tb, unsigned char **recvbuf, - uint32_t (*getPidFunc)(void)); - -int ifaceGetNthParent(int ifindex, const char *ifname, unsigned int nthParent, - int *parent_ifindex, char *parent_ifname, - unsigned int *nth) - ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(4) ATTRIBUTE_NONNULL(5) - ATTRIBUTE_NONNULL(6); - -#endif /* __VIR_INTERFACE_H__ */ diff --git a/src/util/virnetdevmacvlan.c b/src/util/virnetdevmacvlan.c index e3f90dd..fe2f383 100644 --- a/src/util/virnetdevmacvlan.c +++ b/src/util/virnetdevmacvlan.c @@ -64,7 +64,6 @@ VIR_ENUM_IMPL(virNetDevMacVLanMode, VIR_NETDEV_MACVLAN_MODE_LAST, # include "memory.h" # include "logging.h" -# include "interface.h" # include "uuid.h" # include "virfile.h" # include "netlink.h" diff --git a/src/util/virnetdevvportprofile.c b/src/util/virnetdevvportprofile.c index 9315281..8f7e5b9 100644 --- a/src/util/virnetdevvportprofile.c +++ b/src/util/virnetdevvportprofile.c @@ -58,7 +58,6 @@ VIR_ENUM_IMPL(virNetDevVPortProfileOp, VIR_NETDEV_VPORT_PROFILE_OP_LAST, # include "netlink.h" # include "virfile.h" # include "memory.h" -# include "interface.h" # include "logging.h" # include "virnetdev.h" @@ -127,6 +126,10 @@ static struct nla_policy ifla_port_policy[IFLA_PORT_MAX + 1] = { [IFLA_PORT_RESPONSE] = { .type = NLA_U16 }, }; +static struct nla_policy ifla_policy[IFLA_MAX + 1] = +{ + [IFLA_VF_PORTS] = { .type = NLA_NESTED }, +}; static uint32_t @@ -163,6 +166,125 @@ virNetDevVPortProfileGetLldpadPid(void) { /** + * virNetDevVPortProfileLinkDump: + * + * @ifname: The name of the interface; only use if ifindex < 0 + * @ifindex: The interface index; may be < 0 if ifname is given + * @nltarget_kernel: whether to send the message to the kernel or another + * process + * @nlattr: pointer to a pointer of netlink attributes that will contain + * the results + * @recvbuf: Pointer to the buffer holding the returned netlink response + * message; free it, once not needed anymore + * @getPidFunc: Pointer to a function that will be invoked if the kernel + * is not the target of the netlink message but it is to be + * sent to another process. + * + * Get information about an interface given its name or index. + * + * Returns 0 on success, -1 on fatal error. + */ +static int +virNetDevVPortProfileLinkDump(const char *ifname, int ifindex, bool nltarget_kernel, + struct nlattr **tb, unsigned char **recvbuf, + uint32_t (*getPidFunc)(void)) +{ + int rc = 0; + struct nlmsghdr *resp; + struct nlmsgerr *err; + struct ifinfomsg ifinfo = { + .ifi_family = AF_UNSPEC, + .ifi_index = ifindex + }; + unsigned int recvbuflen; + uint32_t pid = 0; + struct nl_msg *nl_msg; + + *recvbuf = NULL; + + nl_msg = nlmsg_alloc_simple(RTM_GETLINK, NLM_F_REQUEST); + if (!nl_msg) { + virReportOOMError(); + return -1; + } + + if (nlmsg_append(nl_msg, &ifinfo, sizeof(ifinfo), NLMSG_ALIGNTO) < 0) + goto buffer_too_small; + + if (ifindex < 0 && ifname) { + if (nla_put(nl_msg, IFLA_IFNAME, strlen(ifname)+1, ifname) < 0) + goto buffer_too_small; + } + + if (!nltarget_kernel) { + pid = getPidFunc(); + if (pid == 0) { + rc = -1; + goto cleanup; + } + } + + if (nlComm(nl_msg, recvbuf, &recvbuflen, pid) < 0) { + rc = -1; + goto cleanup; + } + + if (recvbuflen < NLMSG_LENGTH(0) || *recvbuf == NULL) + goto malformed_resp; + + resp = (struct nlmsghdr *)*recvbuf; + + switch (resp->nlmsg_type) { + case NLMSG_ERROR: + err = (struct nlmsgerr *)NLMSG_DATA(resp); + if (resp->nlmsg_len < NLMSG_LENGTH(sizeof(*err))) + goto malformed_resp; + + if (err->error) { + virReportSystemError(-err->error, + _("error dumping %s (%d) interface"), + ifname, ifindex); + rc = -1; + } + break; + + case GENL_ID_CTRL: + case NLMSG_DONE: + if (nlmsg_parse(resp, sizeof(struct ifinfomsg), + tb, IFLA_MAX, ifla_policy)) { + goto malformed_resp; + } + break; + + default: + goto malformed_resp; + } + + if (rc != 0) + VIR_FREE(*recvbuf); + +cleanup: + nlmsg_free(nl_msg); + + return rc; + +malformed_resp: + nlmsg_free(nl_msg); + + virNetDevError(VIR_ERR_INTERNAL_ERROR, "%s", + _("malformed netlink response message")); + VIR_FREE(*recvbuf); + return -1; + +buffer_too_small: + nlmsg_free(nl_msg); + + virNetDevError(VIR_ERR_INTERNAL_ERROR, "%s", + _("allocated netlink buffer is too small")); + return -1; +} + +/** * virNetDevVPortProfileGetStatus: * * tb: top level netlink response attributes + values @@ -450,6 +572,73 @@ buffer_too_small: } +/** + * virNetDevVPortProfileGetNthParent + * + * @ifname : the name of the interface; ignored if ifindex is valid + * @ifindex : the index of the interface or -1 if ifname is given + * @nthParent : the nth parent interface to get + * @parent_ifindex : pointer to int + * @parent_ifname : pointer to buffer of size IFNAMSIZ + * @nth : the nth parent that is actually returned; if for example eth0.100 + * was given and the 100th parent is to be returned, then eth0 will + * most likely be returned with nth set to 1 since the chain does + * not have more interfaces + * + * Get the nth parent interface of the given interface. 0 is the interface + * itself. + * + * Return 0 on success, < 0 otherwise + */ +static int +virNetDevVPortProfileGetNthParent(const char *ifname, int ifindex, unsigned int nthParent, + int *parent_ifindex, char *parent_ifname, + unsigned int *nth) +{ + int rc; + struct nlattr *tb[IFLA_MAX + 1] = { NULL, }; + unsigned char *recvbuf = NULL; + bool end = false; + unsigned int i = 0; + + *nth = 0; + + if (ifindex <= 0 && virNetDevGetIndex(ifname, &ifindex) < 0) + return -1; + + while (!end && i <= nthParent) { + rc = virNetDevVPortProfileLinkDump(ifname, ifindex, true, tb, &recvbuf, NULL); + if (rc < 0) + break; + + if (tb[IFLA_IFNAME]) { + if (!virStrcpy(parent_ifname, (char*)RTA_DATA(tb[IFLA_IFNAME]), + IFNAMSIZ)) { + virNetDevError(VIR_ERR_INTERNAL_ERROR, "%s", + _("buffer for root interface name is too small")); + VIR_FREE(recvbuf); + return -1; + } + *parent_ifindex = ifindex; + } + + if (tb[IFLA_LINK]) { + ifindex = *(int *)RTA_DATA(tb[IFLA_LINK]); + ifname = NULL; + } else + end = true; + + VIR_FREE(recvbuf); + + i++; + } + + *nth = i - 1; + + return rc; +} + + /* Returns 0 on success, -1 on general failure, and -2 on timeout */ static int virNetDevVPortProfileOpCommon(const char *ifname, int ifindex, @@ -487,8 +676,8 @@ virNetDevVPortProfileOpCommon(const char *ifname, int ifindex, } while (--repeats >= 0) { - rc = ifaceMacvtapLinkDump(nltarget_kernel, NULL, ifindex, tb, - &recvbuf, virNetDevVPortProfileGetLldpadPid); + rc = virNetDevVPortProfileLinkDump(NULL, ifindex, nltarget_kernel, tb, + &recvbuf, virNetDevVPortProfileGetLldpadPid); if (rc < 0) goto err_exit; @@ -538,8 +727,8 @@ virNetDevVPortProfileGetPhysdevAndVlan(const char *ifname, int *root_ifindex, ch *vlanid = -1; while (1) { - if ((ret = ifaceGetNthParent(ifindex, ifname, 1, - root_ifindex, root_ifname, &nth)) < 0) + if ((ret = virNetDevVPortProfileGetNthParent(ifname, ifindex, 1, + root_ifindex, root_ifname, &nth)) < 0) return ret; if (nth == 0) break; -- 1.7.6.4

On 11/15/2011 06:14 AM, Daniel P. Berrange wrote:
Move the ifaceMacvtapLinkDump and ifaceGetNthParent functions into virnetdevvportprofile.c since they are specific to that code. This avoids polluting the headers with the Linux specific netlink data types
* src/util/interface.c, src/util/interface.h: Move ifaceMacvtapLinkDump and ifaceGetNthParent functions and delete remaining file * src/util/virnetdevvportprofile.c: Add ifaceMacvtapLinkDump and ifaceGetNthParent functions * src/network/bridge_driver.c, src/nwfilter/nwfilter_gentech_driver.c, src/nwfilter/nwfilter_learnipaddr.c, src/util/virnetdevmacvlan.c: Remove include of interface.h --- po/POTFILES.in | 1 - src/Makefile.am | 1 - src/libvirt_private.syms | 2 - src/network/bridge_driver.c | 1 - src/nwfilter/nwfilter_gentech_driver.c | 2 +- src/nwfilter/nwfilter_learnipaddr.c | 1 - src/util/interface.c | 296 -------------------------------- src/util/interface.h | 41 ----- src/util/virnetdevmacvlan.c | 1 - src/util/virnetdevvportprofile.c | 199 +++++++++++++++++++++- 10 files changed, 195 insertions(+), 350 deletions(-) delete mode 100644 src/util/interface.c delete mode 100644 src/util/interface.h
ACK.
participants (2)
-
Daniel P. Berrange
-
Laine Stump