[libvirt] new API to get list of *all* interfaces matching a MAC

Laine Stump laine at laine.org
Mon Aug 24 19:24:13 UTC 2009


(This probably seems like overanalysis of a simple problem. That's what 
I'm best at ;-)

Due to oversight, the function virInterfaceLookupByMACString() can only 
return a single interface, but it's possible that a host may have more 
than one interface with the same MAC. Since the API had already been 
released by the time we realized this, the existing function will remain 
and a new one added that can return a list of interfaces. This new API 
will need to deal with the fact that the list length is effectively 
unbounded. I can see three ways of dealing with this, and want to learn 
which is preferred by others before spending time on the implementation.


1) The array containing the list is allocated by libvirt, freed by caller.

         int virInterfaceLookupAllByMACString(virConnectPtr conn, const 
char *mac, virInterfacePtr **matches);

      "matches" will point to an array of virInterfacePtr, and that 
array's length will be the return value. This array will be
      allocated by libvirt, but must be freed by the application when 
it's finished.

     Usage (ignoring errors, of course :-):

         virInterfacePtr *matches;
         int matchCt;

         matchCt = virInterfaceLookupAllByMACString(conn, 
"00:01:02:03:04:05", &matches);
         for (i = 0; i < matchCt; i++) {
                /* do something with an interface */
               virInterfaceFree(matches[i]);
         }
         free(matches);

2) The array containing the list is allocated by the application, and 
its length sent to libvirt. Libvirt then returns the actual number of 
matches, which may be greater than the max length sent by the 
application, but only copies as many as the application asked for. If 
the application sends 0 as maxMatches and/or a NULL pointer instead of a 
pointer to an array, libvirt will return the actual length, but not the 
list itself.

For example, if there are 3 interfaces matching, and maxMatches is set 
to 2, the function will still return 3, but only set two items in the 
matches array.

         int virInterfaceLookupAllByMACString(virConnectPtr conn, const 
char *mac, virInterfacePtr **matches, int maxMatches);

This puts all the functionality needed in a single API function, but it 
will generally need to be called twice - once to learn the length, and 
the second (after allocating an array of appropriate size) to retrieve 
the list.

         virInterfacePtr *matches;
         int matchCtA, matchCtB;

         matchCtA = virInterfaceLookupAllByMACString(conn, 
"00:01:02:03:04:05", NULL, 0);
         matches = malloc (matchCt * sizeof(virInterfacePtr));
         matchCtB = virInterfaceLookupAllByMACString(conn, 
"00:01:02:03:04:05", &matches, matchCt);
         for (i = 0; i < min(matchCtA, matchCtB); i++) {
                /* do something with an interface */
               virInterfaceFree(matches[i]);
         }
         free(matches);



3) Again, the array containing the list is allocated by the application, 
but it learns the proper length to allocate by calling a different API 
function.  The lookup function itself returns the number of interfaces 
delivered in the array, rather than the number of matches it *wanted* to 
put in the array.

         int virInterfaceCountAllByMACString(virConnectPtr conn, const 
char *mac);
         int virInterfaceLookupAllByMACString(virConnectPtr conn, const 
char *mac, virInterfacePtr **matches, int maxMatches);


   Usage:

         virInterfacePtr *matches;
         int matchCt;

         matchCt = virInterfaceCountAllByMACString(conn, 
"00:01:02:03:04:05");
         matches = malloc (matchCt * sizeof(virInterfacePtr));
         matchCt = virInterfaceLookupAllByMACString(conn, 
"00:01:02:03:04:05", &matches, matchCt);
         for (i = 0; i < matchCt; i++) {
                /* do something with an interface */
               virInterfaceFree(matches[i]);
         }
         free(matches);

*******

(3) is closest to behavior of other libvirt APIs, but requires more 
functions in the API, and could lead to situations where newly added 
interfaces aren't in the list (if a new interface is added between 
calling the Count function and the Lookup function) . (2) has a more 
compact API (one which matches the netcf API exactly), but has the same 
problems with potential bad counts. (1) seems like the cleanest API, but 
I don't know what others' opinions are on having libvirt allocate the 
array (since that's not how its done for other similar things, eg 
virConnectListInterface, virConnectListNetworks, etc), or maybe there's 
some limitation of the RPC I haven't considered that makes it unfeasible.


Which should I implement?









More information about the libvir-list mailing list