[libvirt] [PATCH v4] npiv: Auto-generate WWN if it's not specified

The auto-generated WWN comply with the new addressing schema of WWN: <quote> the first nibble is either hex 5 or 6 followed by a 3-byte vendor identifier and 36 bits for a vendor-specified serial number. </quote> We choose hex 5 for the first nibble. And use Qumranet's OUI (00:1A:4A) as the 3-byte vendor indentifier. The last 36 bits are auto-generated. v3 - v4: * No changes, rebasing according the files reorgnization. --- src/conf/node_device_conf.c | 35 ++++++++++++++++++----------------- src/libvirt_private.syms | 1 + src/util/virrandom.c | 25 +++++++++++++++++++++++++ src/util/virrandom.h | 1 + 4 files changed, 45 insertions(+), 17 deletions(-) diff --git a/src/conf/node_device_conf.c b/src/conf/node_device_conf.c index d9dc9ac..6812ee9 100644 --- a/src/conf/node_device_conf.c +++ b/src/conf/node_device_conf.c @@ -63,19 +63,12 @@ VIR_ENUM_IMPL(virNodeDevHBACap, VIR_NODE_DEV_CAP_HBA_LAST, static int virNodeDevCapsDefParseString(const char *xpath, xmlXPathContextPtr ctxt, - char **string, - virNodeDeviceDefPtr def, - const char *missing_error_fmt) + char **string) { char *s; - s = virXPathString(xpath, ctxt); - if (s == NULL) { - virNodeDeviceReportError(VIR_ERR_INTERNAL_ERROR, - missing_error_fmt, - def->name); + if (!(s = virXPathString(xpath, ctxt))) return -1; - } *string = s; return 0; @@ -763,18 +756,26 @@ virNodeDevCapScsiHostParseXML(xmlXPathContextPtr ctxt, if (virNodeDevCapsDefParseString("string(./wwnn[1])", ctxt, - &data->scsi_host.wwnn, - def, - _("no WWNN supplied for '%s'")) < 0) { - goto out; + &data->scsi_host.wwnn) < 0) { + if (virWWNGenerate(&data->scsi_host.wwnn) < 0) { + virNodeDeviceReportError(VIR_ERR_INTERNAL_ERROR, + _("no WWNN supplied for '%s', and " + "auto-generation failed"), + def->name); + goto out; + } } if (virNodeDevCapsDefParseString("string(./wwpn[1])", ctxt, - &data->scsi_host.wwpn, - def, - _("no WWPN supplied for '%s'")) < 0) { - goto out; + &data->scsi_host.wwpn) < 0) { + if (virWWNGenerate(&data->scsi_host.wwpn) < 0) { + virNodeDeviceReportError(VIR_ERR_INTERNAL_ERROR, + _("no WWPN supplied for '%s', and " + "auto-generation failed"), + def->name); + goto out; + } } ctxt->node = orignode2; diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index e300f06..0d5758f 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -1374,6 +1374,7 @@ virPidFileDeletePath; # virrandom.h virRandomBits; virRandomInitialize; +virWWNGenerate; # virsocketaddr.h diff --git a/src/util/virrandom.c b/src/util/virrandom.c index ec0cf03..3839989 100644 --- a/src/util/virrandom.c +++ b/src/util/virrandom.c @@ -26,6 +26,10 @@ #include "virrandom.h" #include "threads.h" #include "count-one-bits.h" +#include "util.h" +#include "virterror_internal.h" + +#define VIR_FROM_THIS VIR_FROM_NONE static char randomState[128]; static struct random_data randomData; @@ -79,3 +83,24 @@ uint64_t virRandomBits(int nbits) virMutexUnlock(&randomLock); return ret; } + +#define QUMRANET_OUI "001a4a" + +int virWWNGenerate(char **wwn) { + int suffix[5]; + + suffix[0] = virRandomBits(16); + suffix[1] = virRandomBits(256); + suffix[2] = virRandomBits(256); + suffix[3] = virRandomBits(256); + suffix[4] = virRandomBits(256); + + if (virAsprintf(wwn, "%x%s%x%02x%02x%02x%02x", 0x5, QUMRANET_OUI, + suffix[0], suffix[1], suffix[2], + suffix[3], suffix[4]) < 0) { + virReportOOMError(); + return -1; + } + + return 0; +} diff --git a/src/util/virrandom.h b/src/util/virrandom.h index e180a2f..5e2cdcf 100644 --- a/src/util/virrandom.h +++ b/src/util/virrandom.h @@ -27,5 +27,6 @@ int virRandomInitialize(uint32_t seed) ATTRIBUTE_RETURN_CHECK; uint64_t virRandomBits(int nbits); +int virWWNGenerate(char **wwn); #endif /* __VIR_RANDOM_H__ */ -- 1.7.7.3

On 02/03/2012 04:17 AM, Osier Yang wrote:
The auto-generated WWN comply with the new addressing schema of WWN:
<quote> the first nibble is either hex 5 or 6 followed by a 3-byte vendor identifier and 36 bits for a vendor-specified serial number. </quote>
We choose hex 5 for the first nibble. And use Qumranet's OUI (00:1A:4A) as the 3-byte vendor indentifier. The last 36 bits are auto-generated.
+++ b/src/libvirt_private.syms @@ -1374,6 +1374,7 @@ virPidFileDeletePath; # virrandom.h virRandomBits; virRandomInitialize; +virWWNGenerate;
This should be named with a virRandom prefix; I like virRandomGenerateWWN
+#define QUMRANET_OUI "001a4a" + +int virWWNGenerate(char **wwn) {
Formatting, I would do: int virRandomGenerateWWN(char **wwn) {
+ int suffix[5]; + + suffix[0] = virRandomBits(16);
Eep. That's a waste of random bits (generating a uint16_t for just 4 bits).
+ suffix[1] = virRandomBits(256);
And that's a usage error. virRandomBits takes an argument 1-64, not larger.
+ suffix[2] = virRandomBits(256); + suffix[3] = virRandomBits(256); + suffix[4] = virRandomBits(256); + + if (virAsprintf(wwn, "%x%s%x%02x%02x%02x%02x", 0x5, QUMRANET_OUI,
Why not just: if (virAsprintf(wwn, "5" QUMRANET_OUI "%010llx", (unsigned long long) virRandomBits(36)) < 0) and skip going through a temporary array. -- Eric Blake eblake@redhat.com +1-919-301-3266 Libvirt virtualization library http://libvirt.org

On 02/03/2012 11:05 AM, Eric Blake wrote:
+ if (virAsprintf(wwn, "%x%s%x%02x%02x%02x%02x", 0x5, QUMRANET_OUI,
Why not just:
if (virAsprintf(wwn, "5" QUMRANET_OUI "%010llx", (unsigned long long) virRandomBits(36)) < 0)
Correction - %09llx, for 36 bits of output from your random number. I suppose you could also use "5" QUMRANET_OUI "%09" PRIx64, virRandomBits(36) to avoid the cast. -- Eric Blake eblake@redhat.com +1-919-301-3266 Libvirt virtualization library http://libvirt.org
participants (2)
-
Eric Blake
-
Osier Yang