From: "D. Herrendoerfer" <d.herrendoerfer(a)herrendoerfer.name>
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(a)herrendoerfer.name>
---
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