[libvirt] [PATCH] more interface functions; some needed for VEPA

In the attached patch I am refactoring the function that changes the flags on an interface to call a separate function to first read the flags on the interface. This function that reads the flags then becomes public. I am also adding a function that test whether an interface is currently up. This prevents other code to have to include interface related include files. Then there is a new function that reads the VLANid of a VLAN interface via an ioctl(). This one will be needed by upcoming VEPA related patches. On cygwin for example none of the newly added functions are available. The flags related function could not be exported due to missing PF_PACKET -- or maybe other type of protocol that needs to be used when opening the socket for running the ioctl() on. Signed-off-by: Stefan Berger <stefanb@us.ibm.com> --- src/libvirt_private.syms | 2 + src/util/interface.c | 76 ++++++++++++++++++++++++++++++++++++++++------- src/util/interface.h | 3 + 3 files changed, 70 insertions(+), 11 deletions(-) Index: libvirt-acl/src/util/interface.c =================================================================== --- libvirt-acl.orig/src/util/interface.c +++ libvirt-acl/src/util/interface.c @@ -30,6 +30,8 @@ #ifdef __linux__ # include <linux/if.h> +# include <linux/sockios.h> +# include <linux/if_vlan.h> #endif #include "internal.h" @@ -42,6 +44,85 @@ virReportErrorHelper(NULL, VIR_FROM_NET, code, __FILE__, \ __FUNCTION__, __LINE__, __VA_ARGS__) +#if __linux__ +static int +getFlags(int fd, const char *ifname, struct ifreq *ifr) { + + memset(ifr, 0, sizeof(*ifr)); + + if (virStrncpy(ifr->ifr_name, + ifname, strlen(ifname), sizeof(ifr->ifr_name)) == NULL) + return ENODEV; + + if (ioctl(fd, SIOCGIFFLAGS, ifr) < 0) + return errno; + + return 0; +} + + +/** + * ifaceGetFlags + * + * @ifname : name of the interface + * @flags : pointer to short holding the flags on success + * + * Get the flags of the interface. Returns 0 on success, error code on failure. + */ +int +ifaceGetFlags(const char *ifname, short *flags) { + struct ifreq ifr; + int rc; + int fd = socket(PF_PACKET, SOCK_DGRAM, 0); + + if (fd < 0) + return errno; + + rc = getFlags(fd, ifname, &ifr); + + *flags = ifr.ifr_flags; + + close(fd); + + return rc; +} + + +int +ifaceIsUp(const char *ifname, bool *up) { + short flags; + int rc = ifaceGetFlags(ifname, &flags); + + if (rc) + return rc; + + *up = ((flags & IFF_UP) == IFF_UP); + + return 0; +} +#else + +/* Note: Showstopper on cygwin is only missing PF_PACKET */ + +int +ifaceGetFlags(const char *ifname ATTRIBUTE_UNUSED, + short *flags ATTRIBUTE_UNUSED) { + ifaceError(VIR_ERR_INTERNAL_ERROR, "%s", + _("ifaceGetFlags is not supported on non-linux platforms")); + return ENOSYS; +} + +int +ifaceIsUp(const char *ifname ATTRIBUTE_UNUSED, + bool *up ATTRIBUTE_UNUSED) { + + ifaceError(VIR_ERR_INTERNAL_ERROR, "%s", + _("ifaceIsUp is not supported on non-linux platforms")); + return ENOSYS; +} + +#endif /* __linux__ */ + /* * chgIfaceFlags: Change flags on an interface * @@ -59,23 +140,16 @@ static int chgIfaceFlags(const char *ifname, short flagclear, short flagset) { struct ifreq ifr; int rc = 0; - int flags; + short flags; short flagmask = (~0 ^ flagclear); int fd = socket(PF_PACKET, SOCK_DGRAM, 0); if (fd < 0) return errno; - if (virStrncpy(ifr.ifr_name, - ifname, strlen(ifname), sizeof(ifr.ifr_name)) == NULL) { - rc = ENODEV; + rc = getFlags(fd, ifname, &ifr); + if (rc != 0) goto err_exit; - } - - if (ioctl(fd, SIOCGIFFLAGS, &ifr) < 0) { - rc = errno; - goto err_exit; - } flags = (ifr.ifr_flags & flagmask) | flagset; @@ -151,6 +225,8 @@ ifaceCheck(bool reportError, const char if (fd < 0) return errno; + memset(&ifr, 0, sizeof(ifr)); + if (virStrncpy(ifr.ifr_name, ifname, strlen(ifname), sizeof(ifr.ifr_name)) == NULL) { if (reportError) @@ -227,6 +303,8 @@ ifaceGetIndex(bool reportError, const ch if (fd < 0) return errno; + memset(&ifreq, 0, sizeof(ifreq)); + if (virStrncpy(ifreq.ifr_name, ifname, strlen(ifname), sizeof(ifreq.ifr_name)) == NULL) { if (reportError) @@ -269,3 +347,46 @@ ifaceGetIndex(bool reportError, } #endif /* __linux__ */ + +#ifdef __linux__ +int +ifaceGetVlanID(const char *vlanifname, int *vlanid) { + struct vlan_ioctl_args vlanargs = { + .cmd = GET_VLAN_VID_CMD, + }; + int rc = 0; + int fd = socket(PF_PACKET, SOCK_DGRAM, 0); + + if (fd < 0) + return errno; + + if (virStrcpyStatic(vlanargs.device1, vlanifname) == NULL) { + rc = EINVAL; + goto err_exit; + } + + if (ioctl(fd, SIOCGIFVLAN, &vlanargs) != 0) { + rc = errno; + goto err_exit; + } + + *vlanid = vlanargs.u.VID; + + err_exit: + close(fd); + + return rc; +} + +#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; +} +#endif /* __linux__ */ Index: libvirt-acl/src/util/interface.h =================================================================== --- libvirt-acl.orig/src/util/interface.h +++ libvirt-acl/src/util/interface.h @@ -12,6 +12,9 @@ # include "datatypes.h" +int ifaceGetFlags(const char *name, short *flags); +int ifaceIsUp(const char *name, bool *up); + int ifaceCtrl(const char *name, bool up); static inline int ifaceUp(const char *name) { @@ -27,4 +30,6 @@ int ifaceCheck(bool reportError, const c int ifaceGetIndex(bool reportError, const char *ifname, int *ifindex); +int ifaceGetVlanID(const char *vlanifname, int *vlanid); + #endif /* __VIR_INTERFACE_H__ */ Index: libvirt-acl/src/libvirt_private.syms =================================================================== --- libvirt-acl.orig/src/libvirt_private.syms +++ libvirt-acl/src/libvirt_private.syms @@ -685,6 +685,9 @@ virArgvToString; ifaceCtrl; ifaceCheck; ifaceGetIndex; +ifaceGetFlags; +ifaceIsUp; +ifaceGetVlanID; # usb.h usbGetDevice;

On Fri, 7 May 2010, Stefan Berger wrote:
Then there is a new function that reads the VLANid of a VLAN interface via an ioctl(). This one will be needed by upcoming VEPA related patches.
Yes, this is needed by VEPA. With this patch it should be possible to collect all the components required for the VEPA (for VSI discovery protocol). As per your/David's earlier RFC for sending the netlink message to the VSI engine (LLDPAD), the netlink message will need to contain: 1. 'Port profile' comprising of : VSI Manager ID 1 octet VSI Type ID 3 octets VSI Type ID Version 1 octet VSI Instance ID 16 octets Therefore need to extend the domain xml to take the above 4 values. reference, Pg 50 of the proposal here http://www.ieee802.org/1/files/public/docs2010/bg-joint-evb-0410v1.pdf 2. MAC address (of the virtual interface) 3. VLAN tag (associtaed with the virtual interface) thanks Vivek
On cygwin for example none of the newly added functions are available. The flags related function could not be exported due to missing PF_PACKET -- or maybe other type of protocol that needs to be used when opening the socket for running the ioctl() on.
Signed-off-by: Stefan Berger <stefanb@us.ibm.com>
<..snip>
+ +#ifdef __linux__ +int +ifaceGetVlanID(const char *vlanifname, int *vlanid) { + struct vlan_ioctl_args vlanargs = { + .cmd = GET_VLAN_VID_CMD, + }; + int rc = 0; + int fd = socket(PF_PACKET, SOCK_DGRAM, 0); + + if (fd < 0) + return errno; + + if (virStrcpyStatic(vlanargs.device1, vlanifname) == NULL) { + rc = EINVAL; + goto err_exit; + } + + if (ioctl(fd, SIOCGIFVLAN, &vlanargs) != 0) { + rc = errno; + goto err_exit; + } + + *vlanid = vlanargs.u.VID; + + err_exit: + close(fd); + + return rc; +} + +#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; +} +#endif /* __linux__ */ Index: libvirt-acl/src/util/interface.h =================================================================== --- libvirt-acl.orig/src/util/interface.h +++ libvirt-acl/src/util/interface.h @@ -12,6 +12,9 @@
# include "datatypes.h"
+int ifaceGetFlags(const char *name, short *flags); +int ifaceIsUp(const char *name, bool *up); + int ifaceCtrl(const char *name, bool up);
static inline int ifaceUp(const char *name) { @@ -27,4 +30,6 @@ int ifaceCheck(bool reportError, const c
int ifaceGetIndex(bool reportError, const char *ifname, int *ifindex);
+int ifaceGetVlanID(const char *vlanifname, int *vlanid); + #endif /* __VIR_INTERFACE_H__ */ Index: libvirt-acl/src/libvirt_private.syms =================================================================== --- libvirt-acl.orig/src/libvirt_private.syms +++ libvirt-acl/src/libvirt_private.syms @@ -685,6 +685,9 @@ virArgvToString; ifaceCtrl; ifaceCheck; ifaceGetIndex; +ifaceGetFlags; +ifaceIsUp; +ifaceGetVlanID;
# usb.h usbGetDevice;
-- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list

[image removed]
Re: [libvirt] [PATCH] more interface functions; some needed for VEPA
kashyapv
to:
Stefan Berger
05/07/2010 03:22 PM
Cc:
libvir-list
On Fri, 7 May 2010, Stefan Berger wrote:
Then there is a new function that reads the VLANid of a VLAN interface via an ioctl(). This one will be needed by upcoming VEPA related patches.
Yes, this is needed by VEPA. With this patch it should be possible to collect all the components required for the VEPA (for VSI discovery
kashyapv@linux.vnet.ibm.com wrote on 05/07/2010 03:21:53 PM: protocol).
As per your/David's earlier RFC for sending the netlink message to the VSI engine (LLDPAD), the netlink message will need to contain:
1. 'Port profile' comprising of : VSI Manager ID 1 octet VSI Type ID 3 octets VSI Type ID Version 1 octet VSI Instance ID 16 octets
Therefore need to extend the domain xml to take the above 4 values.
reference, Pg 50 of the proposal here
http://www.ieee802.org/1/files/public/docs2010/bg-joint-evb-0410v1.pdf Gerhard and I defined the following XML for the above: <interface type='direct'> <source dev='static' mode='vepa'/> --> <vsi managerid='12' typeid='1193046' typeidversion='1' instanceid='fa9b7fff-b0a0-4893-8e0e-beef4ff18f8f'/> <-- </interface> (whether above node is called 'vsi' or 'vdp' -- I don't care either way, but 'vsi' for now) following this schema and corresponding (self-explanatory) data types: + <define name="vsiProfile"> + <element name="vsi"> + <attribute name="managerid"> + <ref name="uint8range"/> + </attribute> + <attribute name="typeid"> + <ref name="uint24range"/> + </attribute> + <attribute name="typeidversion"> + <ref name="uint8range"/> + </attribute> + <attribute name="instanceid"> + <ref name="UUID"/> + </attribute> + </element> + </define> So the previous switchport and profile are gone. Regards, Stefan
2. MAC address (of the virtual interface)
3. VLAN tag (associtaed with the virtual interface)
thanks Vivek
On cygwin for example none of the newly added functions are available. The flags related function could not be exported due to missing PF_PACKET -- or maybe other type of protocol that needs to be used
when
opening the socket for running the ioctl() on.
Signed-off-by: Stefan Berger <stefanb@us.ibm.com>
+ +#ifdef __linux__ +int +ifaceGetVlanID(const char *vlanifname, int *vlanid) { + struct vlan_ioctl_args vlanargs = { + .cmd = GET_VLAN_VID_CMD, + }; + int rc = 0; + int fd = socket(PF_PACKET, SOCK_DGRAM, 0); + + if (fd < 0) + return errno; + + if (virStrcpyStatic(vlanargs.device1, vlanifname) == NULL) { + rc = EINVAL; + goto err_exit; + } + + if (ioctl(fd, SIOCGIFVLAN, &vlanargs) != 0) { + rc = errno; + goto err_exit; + } + + *vlanid = vlanargs.u.VID; + + err_exit: + close(fd); + + return rc; +} + +#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
<..snip> platforms"));
+ + return ENOSYS; +} +#endif /* __linux__ */ Index: libvirt-acl/src/util/interface.h =================================================================== --- libvirt-acl.orig/src/util/interface.h +++ libvirt-acl/src/util/interface.h @@ -12,6 +12,9 @@
# include "datatypes.h"
+int ifaceGetFlags(const char *name, short *flags); +int ifaceIsUp(const char *name, bool *up); + int ifaceCtrl(const char *name, bool up);
static inline int ifaceUp(const char *name) { @@ -27,4 +30,6 @@ int ifaceCheck(bool reportError, const c
int ifaceGetIndex(bool reportError, const char *ifname, int *ifindex);
+int ifaceGetVlanID(const char *vlanifname, int *vlanid); + #endif /* __VIR_INTERFACE_H__ */ Index: libvirt-acl/src/libvirt_private.syms =================================================================== --- libvirt-acl.orig/src/libvirt_private.syms +++ libvirt-acl/src/libvirt_private.syms @@ -685,6 +685,9 @@ virArgvToString; ifaceCtrl; ifaceCheck; ifaceGetIndex; +ifaceGetFlags; +ifaceIsUp; +ifaceGetVlanID;
# usb.h usbGetDevice;
-- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list

1. 'Port profile' comprising of : VSI Manager ID 1 octet VSI Type ID 3 octets VSI Type ID Version 1 octet VSI Instance ID 16 octets
Therefore need to extend the domain xml to take the above 4 values.
reference, Pg 50 of the proposal here http://www.ieee802.org/1/files/public/docs2010/bg-joint-evb-0410v1.pdf
Gerhard and I defined the following XML for the above:
<interface type='direct'> <source dev='static' mode='vepa'/> --> <vsi managerid='12' typeid='1193046' typeidversion='1' instanceid='fa9b7fff-b0a0-4893-8e0e-beef4ff18f8f'/> <-- </interface>
(whether above node is called 'vsi' or 'vdp' -- I don't care either way, but 'vsi' for now)
yes, vsi is fine.
following this schema and corresponding (self-explanatory) data types:
+ <define name="vsiProfile"> + <element name="vsi"> + <attribute name="managerid"> + <ref name="uint8range"/> + </attribute> + <attribute name="typeid"> + <ref name="uint24range"/> + </attribute> + <attribute name="typeidversion"> + <ref name="uint8range"/> + </attribute> + <attribute name="instanceid"> + <ref name="UUID"/> + </attribute> + </element> + </define>
So the previous switchport and profile are gone.
yes, nice. thanks! Vivek
Regards, Stefan
2. MAC address (of the virtual interface)
3. VLAN tag (associtaed with the virtual interface)
thanks Vivek
On cygwin for example none of the newly added functions are available. The flags related function could not be exported due to missing PF_PACKET -- or maybe other type of protocol that needs to be used when opening the socket for running the ioctl() on.
Signed-off-by: Stefan Berger <stefanb@us.ibm.com>
+ +#ifdef __linux__ +int +ifaceGetVlanID(const char *vlanifname, int *vlanid) { + struct vlan_ioctl_args vlanargs = { + .cmd = GET_VLAN_VID_CMD, + }; + int rc = 0; + int fd = socket(PF_PACKET, SOCK_DGRAM, 0); + + if (fd < 0) + return errno; + + if (virStrcpyStatic(vlanargs.device1, vlanifname) == NULL) { + rc = EINVAL; + goto err_exit; + } + + if (ioctl(fd, SIOCGIFVLAN, &vlanargs) != 0) { + rc = errno; + goto err_exit; + } + + *vlanid = vlanargs.u.VID; + + err_exit: + close(fd); + + return rc; +} + +#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
<..snip> platforms"));
+ + return ENOSYS; +} +#endif /* __linux__ */ Index: libvirt-acl/src/util/interface.h =================================================================== --- libvirt-acl.orig/src/util/interface.h +++ libvirt-acl/src/util/interface.h @@ -12,6 +12,9 @@
# include "datatypes.h"
+int ifaceGetFlags(const char *name, short *flags); +int ifaceIsUp(const char *name, bool *up); + int ifaceCtrl(const char *name, bool up);
static inline int ifaceUp(const char *name) { @@ -27,4 +30,6 @@ int ifaceCheck(bool reportError, const c
int ifaceGetIndex(bool reportError, const char *ifname, int *ifindex);
+int ifaceGetVlanID(const char *vlanifname, int *vlanid); + #endif /* __VIR_INTERFACE_H__ */ Index: libvirt-acl/src/libvirt_private.syms =================================================================== --- libvirt-acl.orig/src/libvirt_private.syms +++ libvirt-acl/src/libvirt_private.syms @@ -685,6 +685,9 @@ virArgvToString; ifaceCtrl; ifaceCheck; ifaceGetIndex; +ifaceGetFlags; +ifaceIsUp; +ifaceGetVlanID;
# usb.h usbGetDevice;
-- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
participants (2)
-
Stefan Berger
-
Vivek Kashyap