From: "D. Herrendoerfer" <d.herrendoerfer@xxxxxxxxxxxxxxxxxx> Make macvtap setup code register a callback to handle link status changes sent by lldpad. This is prototype code for reference only. Signed-off-by: D. Herrendoerfer <d.herrendoerfer@xxxxxxxxxxxxxxxxxx> --- src/util/virnetdevmacvlan.c | 161 ++++++++++++++++++++++++++++++++++++++++++- src/util/virnetdevmacvlan.h | 1 + 2 files changed, 161 insertions(+), 1 deletions(-) diff --git a/src/util/virnetdevmacvlan.c b/src/util/virnetdevmacvlan.c index 5e55b72..e4a280b 100644 --- a/src/util/virnetdevmacvlan.c +++ b/src/util/virnetdevmacvlan.c @@ -46,7 +46,6 @@ VIR_ENUM_IMPL(virNetDevMacVLanMode, VIR_NETDEV_MACVLAN_MODE_LAST, "passthrough") #if WITH_MACVTAP - # include <stdint.h> # include <stdio.h> # include <errno.h> @@ -57,6 +56,8 @@ VIR_ENUM_IMPL(virNetDevMacVLanMode, VIR_NETDEV_MACVLAN_MODE_LAST, # include <linux/if.h> # include <linux/if_tun.h> +# include <c-ctype.h> + /* Older kernels lacked this enum value. */ # if !HAVE_DECL_MACVLAN_MODE_PASSTHRU # define MACVLAN_MODE_PASSTHRU 8 @@ -67,6 +68,7 @@ VIR_ENUM_IMPL(virNetDevMacVLanMode, VIR_NETDEV_MACVLAN_MODE_LAST, # include "uuid.h" # include "virfile.h" # include "netlink.h" +# include "netlink-event.h" # include "virnetdev.h" # define MACVTAP_NAME_PREFIX "macvtap" @@ -75,6 +77,7 @@ VIR_ENUM_IMPL(virNetDevMacVLanMode, VIR_NETDEV_MACVLAN_MODE_LAST, # define MACVLAN_NAME_PREFIX "macvlan" # define MACVLAN_NAME_PATTERN "macvlan%d" + /** * virNetDevMacVLanCreate: * @@ -445,6 +448,142 @@ static const uint32_t modeMap[VIR_NETDEV_MACVLAN_MODE_LAST] = { [VIR_NETDEV_MACVLAN_MODE_PASSTHRU] = MACVLAN_MODE_PASSTHRU, }; +# define LLDPAD_PID_FILE "/var/run/lldpad.pid" + +static uint32_t +GetLldpadPid(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; +} + +/* Struct to hold the state and configuration of a 802.1qbg port */ +struct netlinkCallbackData { + char cr_ifname[64]; + virNetDevVPortProfilePtr virtPortProfile; + const unsigned char *macaddress; + const char *linkdev; + const unsigned char *vmuuid; + enum virNetDevVPortProfileOp vmOp; + unsigned int linkState; +}; +typedef struct netlinkCallbackData *netlinkCallbackDataPtr; + +/** + * virNetDevMacVLanVPortProfileCallback: + * + * @msg: The buffer containing the received netlink message + * @length: The length of the received netlink message. + * @peer: The netling sockaddr containing the peer information + * @handeled: Contains information if the message has been replied to yet + * @opaque: Contains vital information regarding the associated vm an interface + * + * This function is called when a netlink message is received. The function + * reads the message and responds if it is pertinent to the running VMs + * network interface. + */ + +static void +virNetDevMacVLanVPortProfileCallback( unsigned char *msg, + int length, + struct sockaddr_nl *peer, + int *handled, + void *opaque) +{ + /* ToDo : There is no valid lldpad message yet :( + * + * */ + + struct nlmsghdr *hdr; + void *data; + int i=0; + netlinkCallbackDataPtr calld = opaque; + + VIR_INFO("Netlink message received from nl_sockaddr: %p", peer); + + hdr = (struct nlmsghdr *) msg; + data = nlmsg_data(hdr); + + /* Quickly decide if we want this or not */ + if (hdr->nlmsg_pid != GetLldpadPid()) + return; // we only care for lldpad messages + if (hdr->nlmsg_type != RTM_SETLINK) + return; // we only care for RTM_SETLINK + if (handled != 0) + return; // if it has been handeled - dont handle again + + /* DEBUG start */ + VIR_INFO("buffer length=%d",length); + VIR_INFO("nlmsg_type = 0x%02x",hdr->nlmsg_type); + VIR_INFO("nlmsg_len = 0x%04x",hdr->nlmsg_len ); + VIR_INFO("nlmsg_pid = %d",hdr->nlmsg_pid ); + VIR_INFO("nlmsg_seq = 0x%08x",hdr->nlmsg_seq ); + VIR_INFO("nlmsg_flags = 0x%04x",hdr->nlmsg_flags ); + + switch (hdr->nlmsg_type) { + case RTM_NEWLINK: + case RTM_DELLINK: + case RTM_SETLINK: + case RTM_GETLINK: + VIR_INFO(" IFINFOMSG\n"); + VIR_INFO(" ifi_family = 0x%02x\n", + ((struct ifinfomsg *)data)->ifi_family); + VIR_INFO(" ifi_type = 0x%x\n", + ((struct ifinfomsg *)data)->ifi_type); + VIR_INFO(" ifi_index = %i\n", + ((struct ifinfomsg *)data)->ifi_index); + VIR_INFO(" ifi_flags = 0x%04x\n", + ((struct ifinfomsg *)data)->ifi_flags); + VIR_INFO(" ifi_change = 0x%04x\n", + ((struct ifinfomsg *)data)->ifi_change); + } + /* DEBUG end */ + + + /* FAKE (try) */ + VIR_INFO("Re-Send associate request:"); + + VIR_INFO(" if: %s",calld->cr_ifname ); + VIR_INFO(" lf: %s",calld->linkdev ); + VIR_INFO(" mac: %04x:%04x:%04x:%04x:%04x:%04x",calld->macaddress[0], + calld->macaddress[1], + calld->macaddress[2], + calld->macaddress[3], + calld->macaddress[4], + calld->macaddress[5] ); + /* ToDo : Send an associate to lldpad + * + * */ + + handled++; + return; +} + /** * virNetDevMacVLanCreateWithVPortProfile: * Create an instance of a macvtap device and open its tap character @@ -589,6 +728,23 @@ create_name: goto disassociate_exit; } + if (netlinkEventServiceStart() == 0) { + netlinkCallbackDataPtr calld; + + if (VIR_ALLOC(calld) < 0) { + virReportOOMError(); + goto disassociate_exit; + } + + strncpy(calld->cr_ifname,cr_ifname,64); + calld->virtPortProfile=virtPortProfile; + calld->macaddress=macaddress; + calld->linkdev=linkdev; + calld->vmuuid=vmuuid; + calld->vmOp=vmOp; + + netlinkEventAddClient(virNetDevMacVLanVPortProfileCallback, calld, macaddress); + } return rc; @@ -638,6 +794,9 @@ int virNetDevMacVLanDeleteWithVPortProfile(const char *ifname, if (virNetDevMacVLanDelete(ifname) < 0) ret = -1; } + + netlinkEventRemoveClient(0,macaddr); + return ret; } diff --git a/src/util/virnetdevmacvlan.h b/src/util/virnetdevmacvlan.h index 130ecea..fe54cae 100644 --- a/src/util/virnetdevmacvlan.h +++ b/src/util/virnetdevmacvlan.h @@ -24,6 +24,7 @@ # define __UTIL_MACVTAP_H__ # include "internal.h" +# include "netlink.h" # include "virsocketaddr.h" # include "virnetdevbandwidth.h" # include "virnetdevvportprofile.h" -- 1.7.7.5 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list