2 * Copyright (C) 2010-2013 Red Hat, Inc.
3 * Copyright (C) 2010-2012 IBM Corporation
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library. If not, see
17 * <http://www.gnu.org/licenses/>.
20 * Stefan Berger <stefanb@us.ibm.com>
23 * netlink: http://lovezutto.googlepages.com/netlink.pdf
30 #include "virnetdevmacvlan.h"
31 #include "virmacaddr.h"
33 #include "virthread.h"
34 #include "virstring.h"
36 #define VIR_FROM_THIS VIR_FROM_NET
38 VIR_ENUM_IMPL(virNetDevMacVLanMode, VIR_NETDEV_MACVLAN_MODE_LAST,
49 # include <sys/socket.h>
50 # include <sys/ioctl.h>
53 # include <linux/if_tun.h>
55 /* Older kernels lacked this enum value. */
56 # if !HAVE_DECL_MACVLAN_MODE_PASSTHRU
57 # define MACVLAN_MODE_PASSTHRU 8
60 # include "viralloc.h"
64 # include "virnetlink.h"
65 # include "virnetdev.h"
66 # include "virpidfile.h"
68 VIR_LOG_INIT("util.netdevmacvlan");
70 # define MACVTAP_NAME_PREFIX "macvtap"
71 # define MACVTAP_NAME_PATTERN "macvtap%d"
73 # define MACVLAN_NAME_PREFIX "macvlan"
74 # define MACVLAN_NAME_PATTERN "macvlan%d"
76 virMutex virNetDevMacVLanCreateMutex = VIR_MUTEX_INITIALIZER;
79 * virNetDevMacVLanCreate:
81 * @ifname: The name the interface is supposed to have; optional parameter
82 * @type: The type of device, i.e., "macvtap", "macvlan"
83 * @macaddress: The MAC address of the device
84 * @srcdev: The name of the 'link' device
85 * @macvlan_mode: The macvlan mode to use
86 * @retry: Pointer to integer that will be '1' upon return if an interface
87 * with the same name already exists and it is worth to try
88 * again with a different name
90 * Create a macvtap device with the given properties.
92 * Returns 0 on success, -1 on fatal error.
95 virNetDevMacVLanCreate(const char *ifname,
97 const virMacAddr *macaddress,
99 uint32_t macvlan_mode,
103 struct nlmsghdr *resp = NULL;
104 struct nlmsgerr *err;
105 struct ifinfomsg ifinfo = { .ifi_family = AF_UNSPEC };
107 unsigned int recvbuflen;
108 struct nl_msg *nl_msg;
109 struct nlattr *linkinfo, *info_data;
111 if (virNetDevGetIndex(srcdev, &ifindex) < 0)
116 nl_msg = nlmsg_alloc_simple(RTM_NEWLINK,
117 NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL);
123 if (nlmsg_append(nl_msg, &ifinfo, sizeof(ifinfo), NLMSG_ALIGNTO) < 0)
124 goto buffer_too_small;
126 if (nla_put_u32(nl_msg, IFLA_LINK, ifindex) < 0)
127 goto buffer_too_small;
129 if (nla_put(nl_msg, IFLA_ADDRESS, VIR_MAC_BUFLEN, macaddress) < 0)
130 goto buffer_too_small;
133 nla_put(nl_msg, IFLA_IFNAME, strlen(ifname)+1, ifname) < 0)
134 goto buffer_too_small;
136 if (!(linkinfo = nla_nest_start(nl_msg, IFLA_LINKINFO)))
137 goto buffer_too_small;
139 if (nla_put(nl_msg, IFLA_INFO_KIND, strlen(type), type) < 0)
140 goto buffer_too_small;
142 if (macvlan_mode > 0) {
143 if (!(info_data = nla_nest_start(nl_msg, IFLA_INFO_DATA)))
144 goto buffer_too_small;
146 if (nla_put(nl_msg, IFLA_MACVLAN_MODE, sizeof(macvlan_mode),
148 goto buffer_too_small;
150 nla_nest_end(nl_msg, info_data);
153 nla_nest_end(nl_msg, linkinfo);
155 if (virNetlinkCommand(nl_msg, &resp, &recvbuflen, 0, 0,
156 NETLINK_ROUTE, 0) < 0) {
160 if (recvbuflen < NLMSG_LENGTH(0) || resp == NULL)
163 switch (resp->nlmsg_type) {
165 err = (struct nlmsgerr *)NLMSG_DATA(resp);
166 if (resp->nlmsg_len < NLMSG_LENGTH(sizeof(*err)))
169 switch (err->error) {
179 virReportSystemError(-err->error,
180 _("error creating %s type of interface attach to %s"),
200 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
201 _("malformed netlink response message"));
205 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
206 _("allocated netlink buffer is too small"));
211 * virNetDevMacVLanDelete:
213 * @ifname: Name of the interface
215 * Tear down an interface with the given name.
217 * Returns 0 on success, -1 on fatal error.
219 int virNetDevMacVLanDelete(const char *ifname)
222 struct nlmsghdr *resp = NULL;
223 struct nlmsgerr *err;
224 struct ifinfomsg ifinfo = { .ifi_family = AF_UNSPEC };
225 unsigned int recvbuflen;
226 struct nl_msg *nl_msg;
228 nl_msg = nlmsg_alloc_simple(RTM_DELLINK,
229 NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL);
235 if (nlmsg_append(nl_msg, &ifinfo, sizeof(ifinfo), NLMSG_ALIGNTO) < 0)
236 goto buffer_too_small;
238 if (nla_put(nl_msg, IFLA_IFNAME, strlen(ifname)+1, ifname) < 0)
239 goto buffer_too_small;
241 if (virNetlinkCommand(nl_msg, &resp, &recvbuflen, 0, 0,
242 NETLINK_ROUTE, 0) < 0) {
246 if (recvbuflen < NLMSG_LENGTH(0) || resp == NULL)
249 switch (resp->nlmsg_type) {
251 err = (struct nlmsgerr *)NLMSG_DATA(resp);
252 if (resp->nlmsg_len < NLMSG_LENGTH(sizeof(*err)))
256 virReportSystemError(-err->error,
257 _("error destroying %s interface"),
277 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
278 _("malformed netlink response message"));
282 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
283 _("allocated netlink buffer is too small"));
289 * virNetDevMacVLanTapOpen:
290 * Open the macvtap's tap device.
291 * @ifname: Name of the macvtap interface
292 * @retries : Number of retries in case udev for example may need to be
293 * waited for to create the tap chardev
294 * Returns negative value in case of error, the file descriptor otherwise.
297 int virNetDevMacVLanTapOpen(const char *ifname,
306 if (snprintf(path, sizeof(path),
307 "/sys/class/net/%s/ifindex", ifname) >= sizeof(path)) {
308 virReportSystemError(errno,
310 _("buffer for ifindex path is too small"));
314 file = fopen(path, "r");
317 virReportSystemError(errno,
318 _("cannot open macvtap file %s to determine "
319 "interface index"), path);
323 if (fscanf(file, "%d", &ifindex) != 1) {
324 virReportSystemError(errno,
325 "%s", _("cannot determine macvtap's tap device "
327 VIR_FORCE_FCLOSE(file);
331 VIR_FORCE_FCLOSE(file);
333 if (snprintf(tapname, sizeof(tapname),
334 "/dev/tap%d", ifindex) >= sizeof(tapname)) {
335 virReportSystemError(errno,
337 _("internal buffer for tap device is too small"));
342 /* may need to wait for udev to be done */
343 tapfd = open(tapname, O_RDWR);
344 if (tapfd < 0 && retries > 0) {
353 virReportSystemError(errno,
354 _("cannot open macvtap tap device %s"),
362 * virNetDevMacVLanTapSetup:
363 * @tapfd: file descriptor of the macvtap tap
364 * @vnet_hdr: 1 to enable IFF_VNET_HDR, 0 to disable it
366 * Returns 0 on success, -1 in case of fatal error, error code otherwise.
368 * Turn the IFF_VNET_HDR flag, if requested and available, make sure
369 * it's off in the other cases.
370 * A fatal error is defined as the VNET_HDR flag being set but it cannot
371 * be turned off for some reason. This is reported with -1. Other fatal
372 * error is not being able to read the interface flags. In that case the
373 * macvtap device should not be used.
376 virNetDevMacVLanTapSetup(int tapfd, int vnet_hdr)
378 unsigned int features;
382 const char *errmsg = NULL;
384 memset(&ifreq, 0, sizeof(ifreq));
386 if (ioctl(tapfd, TUNGETIFF, &ifreq) < 0) {
387 virReportSystemError(errno, "%s",
388 _("cannot get interface flags on macvtap tap"));
392 new_flags = ifreq.ifr_flags;
394 if ((ifreq.ifr_flags & IFF_VNET_HDR) && !vnet_hdr) {
395 new_flags = ifreq.ifr_flags & ~IFF_VNET_HDR;
397 errmsg = _("cannot clean IFF_VNET_HDR flag on macvtap tap");
398 } else if ((ifreq.ifr_flags & IFF_VNET_HDR) == 0 && vnet_hdr) {
399 if (ioctl(tapfd, TUNGETFEATURES, &features) < 0) {
400 virReportSystemError(errno, "%s",
401 _("cannot get feature flags on macvtap tap"));
404 if ((features & IFF_VNET_HDR)) {
405 new_flags = ifreq.ifr_flags | IFF_VNET_HDR;
406 errmsg = _("cannot set IFF_VNET_HDR flag on macvtap tap");
410 if (new_flags != ifreq.ifr_flags) {
411 ifreq.ifr_flags = new_flags;
412 if (ioctl(tapfd, TUNSETIFF, &ifreq) < 0) {
413 virReportSystemError(errno, "%s", errmsg);
422 static const uint32_t modeMap[VIR_NETDEV_MACVLAN_MODE_LAST] = {
423 [VIR_NETDEV_MACVLAN_MODE_VEPA] = MACVLAN_MODE_VEPA,
424 [VIR_NETDEV_MACVLAN_MODE_PRIVATE] = MACVLAN_MODE_PRIVATE,
425 [VIR_NETDEV_MACVLAN_MODE_BRIDGE] = MACVLAN_MODE_BRIDGE,
426 [VIR_NETDEV_MACVLAN_MODE_PASSTHRU] = MACVLAN_MODE_PASSTHRU,
429 /* Struct to hold the state and configuration of a 802.1qbg port */
430 struct virNetlinkCallbackData {
432 virNetDevVPortProfilePtr virtPortProfile;
433 virMacAddr macaddress;
436 unsigned char vmuuid[VIR_UUID_BUFLEN];
437 virNetDevVPortProfileOp vmOp;
438 unsigned int linkState;
441 typedef struct virNetlinkCallbackData *virNetlinkCallbackDataPtr;
443 # define INSTANCE_STRLEN 36
445 static int instance2str(const unsigned char *p, char *dst, size_t size)
447 if (dst && size > INSTANCE_STRLEN) {
448 snprintf(dst, size, "%02x%02x%02x%02x-%02x%02x-%02x%02x-"
449 "%02x%02x-%02x%02x%02x%02x%02x%02x",
450 p[0], p[1], p[2], p[3],
451 p[4], p[5], p[6], p[7],
452 p[8], p[9], p[10], p[11], p[12], p[13], p[14], p[15]);
458 # define LLDPAD_PID_FILE "/var/run/lldpad.pid"
459 # define VIRIP_PID_FILE "/var/run/virip.pid"
462 * virNetDevMacVLanVPortProfileCallback:
464 * @hdr: The buffer containing the received netlink header + payload
465 * @length: The length of the received netlink message.
466 * @peer: The netling sockaddr containing the peer information
467 * @handled: Contains information if the message has been replied to yet
468 * @opaque: Contains vital information regarding the associated vm an interface
470 * This function is called when a netlink message is received. The function
471 * reads the message and responds if it is pertinent to the running VMs
476 virNetDevMacVLanVPortProfileCallback(struct nlmsghdr *hdr,
478 struct sockaddr_nl *peer,
482 struct nla_policy ifla_vf_policy[IFLA_VF_MAX + 1] = {
483 [IFLA_VF_MAC] = {.minlen = sizeof(struct ifla_vf_mac),
484 .maxlen = sizeof(struct ifla_vf_mac)},
485 [IFLA_VF_VLAN] = {.minlen = sizeof(struct ifla_vf_vlan),
486 .maxlen = sizeof(struct ifla_vf_vlan)},
489 struct nla_policy ifla_port_policy[IFLA_PORT_MAX + 1] = {
490 [IFLA_PORT_RESPONSE] = {.type = NLA_U16},
493 struct nlattr *tb[IFLA_MAX + 1], *tb3[IFLA_PORT_MAX + 1],
494 *tb_vfinfo[IFLA_VF_MAX + 1], *tb_vfinfo_list;
496 struct ifinfomsg ifinfo;
500 bool indicate = false;
501 virNetlinkCallbackDataPtr calld = opaque;
502 pid_t lldpad_pid = 0;
504 char macaddr[VIR_MAC_STRING_BUFLEN];
506 data = nlmsg_data(hdr);
508 /* Quickly decide if we want this or not */
510 if (virPidFileReadPath(LLDPAD_PID_FILE, &lldpad_pid) < 0)
513 ignore_value(virPidFileReadPath(VIRIP_PID_FILE, &virip_pid));
515 if (hdr->nlmsg_pid != lldpad_pid && hdr->nlmsg_pid != virip_pid)
516 return; /* we only care for lldpad and virip messages */
517 if (hdr->nlmsg_type != RTM_SETLINK)
518 return; /* we only care for RTM_SETLINK */
520 return; /* if it has been handled - dont handle again */
523 VIR_INFO("netlink message nl_sockaddr: %p len: %d", peer, length);
524 VIR_DEBUG("nlmsg_type = 0x%02x", hdr->nlmsg_type);
525 VIR_DEBUG("nlmsg_len = 0x%04x", hdr->nlmsg_len);
526 VIR_DEBUG("nlmsg_pid = %d", hdr->nlmsg_pid);
527 VIR_DEBUG("nlmsg_seq = 0x%08x", hdr->nlmsg_seq);
528 VIR_DEBUG("nlmsg_flags = 0x%04x", hdr->nlmsg_flags);
530 VIR_DEBUG("lldpad pid = %d", lldpad_pid);
532 switch (hdr->nlmsg_type) {
537 VIR_DEBUG(" IFINFOMSG\n");
538 VIR_DEBUG(" ifi_family = 0x%02x\n",
539 ((struct ifinfomsg *)data)->ifi_family);
540 VIR_DEBUG(" ifi_type = 0x%x\n",
541 ((struct ifinfomsg *)data)->ifi_type);
542 VIR_DEBUG(" ifi_index = %i\n",
543 ((struct ifinfomsg *)data)->ifi_index);
544 VIR_DEBUG(" ifi_flags = 0x%04x\n",
545 ((struct ifinfomsg *)data)->ifi_flags);
546 VIR_DEBUG(" ifi_change = 0x%04x\n",
547 ((struct ifinfomsg *)data)->ifi_change);
551 /* Parse netlink message assume a setlink with vfports */
552 memcpy(&ifinfo, NLMSG_DATA(hdr), sizeof(ifinfo));
553 VIR_DEBUG("family:%#x type:%#x index:%d flags:%#x change:%#x",
554 ifinfo.ifi_family, ifinfo.ifi_type, ifinfo.ifi_index,
555 ifinfo.ifi_flags, ifinfo.ifi_change);
556 if (nlmsg_parse(hdr, sizeof(ifinfo),
557 (struct nlattr **)&tb, IFLA_MAX, NULL)) {
558 VIR_DEBUG("error parsing request...");
562 if (tb[IFLA_VFINFO_LIST]) {
563 VIR_DEBUG("FOUND IFLA_VFINFO_LIST!");
565 nla_for_each_nested(tb_vfinfo_list, tb[IFLA_VFINFO_LIST], rem) {
566 if (nla_type(tb_vfinfo_list) != IFLA_VF_INFO) {
567 VIR_DEBUG("nested parsing of"
568 "IFLA_VFINFO_LIST failed.");
571 if (nla_parse_nested(tb_vfinfo, IFLA_VF_MAX,
572 tb_vfinfo_list, ifla_vf_policy)) {
573 VIR_DEBUG("nested parsing of "
574 "IFLA_VF_INFO failed.");
579 if (tb_vfinfo[IFLA_VF_MAC]) {
580 struct ifla_vf_mac *mac = RTA_DATA(tb_vfinfo[IFLA_VF_MAC]);
581 unsigned char *m = mac->mac;
583 VIR_DEBUG("IFLA_VF_MAC = %2x:%2x:%2x:%2x:%2x:%2x",
584 m[0], m[1], m[2], m[3], m[4], m[5]);
586 if (virMacAddrCmpRaw(&calld->macaddress, mac->mac))
588 /* Repeat the same check for a broadcast mac */
591 for (i = 0; i < VIR_MAC_BUFLEN; i++) {
592 if (calld->macaddress.addr[i] != 0xff) {
593 VIR_DEBUG("MAC address match failed (wasn't broadcast)");
600 if (tb_vfinfo[IFLA_VF_VLAN]) {
601 struct ifla_vf_vlan *vlan = RTA_DATA(tb_vfinfo[IFLA_VF_VLAN]);
603 VIR_DEBUG("IFLA_VF_VLAN = %d", vlan->vlan);
607 if (tb[IFLA_IFNAME]) {
608 ifname = (char *)RTA_DATA(tb[IFLA_IFNAME]);
609 VIR_DEBUG("IFLA_IFNAME = %s\n", ifname);
612 if (tb[IFLA_OPERSTATE]) {
613 rem = *(unsigned short *)RTA_DATA(tb[IFLA_OPERSTATE]);
614 VIR_DEBUG("IFLA_OPERSTATE = %d\n", rem);
617 if (tb[IFLA_VF_PORTS]) {
618 struct nlattr *tb_vf_ports;
620 VIR_DEBUG("found IFLA_VF_PORTS\n");
621 nla_for_each_nested(tb_vf_ports, tb[IFLA_VF_PORTS], rem) {
623 VIR_DEBUG("iterating\n");
624 if (nla_type(tb_vf_ports) != IFLA_VF_PORT) {
625 VIR_DEBUG("not a IFLA_VF_PORT. skipping\n");
628 if (nla_parse_nested(tb3, IFLA_PORT_MAX, tb_vf_ports,
630 VIR_DEBUG("nested parsing on level 2"
633 if (tb3[IFLA_PORT_VF]) {
634 VIR_DEBUG("IFLA_PORT_VF = %d",
635 *(uint32_t *) (RTA_DATA(tb3[IFLA_PORT_VF])));
637 if (tb3[IFLA_PORT_PROFILE]) {
638 VIR_DEBUG("IFLA_PORT_PROFILE = %s",
639 (char *) RTA_DATA(tb3[IFLA_PORT_PROFILE]));
642 if (tb3[IFLA_PORT_VSI_TYPE]) {
643 struct ifla_port_vsi *pvsi;
646 pvsi = (struct ifla_port_vsi *)
647 RTA_DATA(tb3[IFLA_PORT_VSI_TYPE]);
648 tid = ((pvsi->vsi_type_id[2] << 16) |
649 (pvsi->vsi_type_id[1] << 8) |
650 pvsi->vsi_type_id[0]);
652 VIR_DEBUG("mgr_id: %d", pvsi->vsi_mgr_id);
653 VIR_DEBUG("type_id: %d", tid);
654 VIR_DEBUG("type_version: %d",
655 pvsi->vsi_type_version);
658 if (tb3[IFLA_PORT_INSTANCE_UUID]) {
659 char instance[INSTANCE_STRLEN + 2];
662 uuid = (unsigned char *)
663 RTA_DATA(tb3[IFLA_PORT_INSTANCE_UUID]);
664 instance2str(uuid, instance, sizeof(instance));
665 VIR_DEBUG("IFLA_PORT_INSTANCE_UUID = %s\n",
669 if (tb3[IFLA_PORT_REQUEST]) {
670 uint8_t req = *(uint8_t *) RTA_DATA(tb3[IFLA_PORT_REQUEST]);
671 VIR_DEBUG("IFLA_PORT_REQUEST = %d", req);
673 if (req == PORT_REQUEST_DISASSOCIATE) {
674 VIR_DEBUG("Set dissaccociated.");
679 if (tb3[IFLA_PORT_RESPONSE]) {
680 VIR_DEBUG("IFLA_PORT_RESPONSE = %d\n", *(uint16_t *)
681 RTA_DATA(tb3[IFLA_PORT_RESPONSE]));
690 VIR_INFO("Re-send 802.1qbg associate request:");
691 VIR_INFO(" if: %s", calld->cr_ifname);
692 VIR_INFO(" lf: %s", calld->linkdev);
693 VIR_INFO(" mac: %s", virMacAddrFormat(&calld->macaddress, macaddr));
694 ignore_value(virNetDevVPortProfileAssociate(calld->cr_ifname,
695 calld->virtPortProfile,
706 * virNetlinkCallbackDataFree
708 * @calld: pointer to a virNetlinkCallbackData object to free
710 * This function frees all the data associated with a virNetlinkCallbackData object
711 * as well as the object itself. If called with NULL, it does nothing.
716 virNetlinkCallbackDataFree(virNetlinkCallbackDataPtr calld)
719 VIR_FREE(calld->cr_ifname);
720 VIR_FREE(calld->virtPortProfile);
721 VIR_FREE(calld->linkdev);
727 * virNetDevMacVLanVPortProfileDestroyCallback:
729 * @watch: watch whose handle to remove
730 * @macaddr: macaddr whose handle to remove
731 * @opaque: Contains vital information regarding the associated vm
733 * This function is called when a netlink message handler is terminated.
734 * The function frees locally allocated data referenced in the opaque
735 * data, and the opaque object itself.
738 virNetDevMacVLanVPortProfileDestroyCallback(int watch ATTRIBUTE_UNUSED,
739 const virMacAddr *macaddr ATTRIBUTE_UNUSED,
742 virNetlinkCallbackDataFree((virNetlinkCallbackDataPtr)opaque);
746 virNetDevMacVLanVPortProfileRegisterCallback(const char *ifname,
747 const virMacAddr *macaddress,
749 const unsigned char *vmuuid,
750 virNetDevVPortProfilePtr virtPortProfile,
751 virNetDevVPortProfileOp vmOp)
753 virNetlinkCallbackDataPtr calld = NULL;
755 if (virtPortProfile && virNetlinkEventServiceIsRunning(NETLINK_ROUTE)) {
756 if (VIR_ALLOC(calld) < 0)
758 if (VIR_STRDUP(calld->cr_ifname, ifname) < 0)
760 if (VIR_ALLOC(calld->virtPortProfile) < 0)
762 memcpy(calld->virtPortProfile, virtPortProfile, sizeof(*virtPortProfile));
763 virMacAddrSet(&calld->macaddress, macaddress);
764 if (VIR_STRDUP(calld->linkdev, linkdev) < 0)
766 memcpy(calld->vmuuid, vmuuid, sizeof(calld->vmuuid));
770 if (virNetlinkEventAddClient(virNetDevMacVLanVPortProfileCallback,
771 virNetDevMacVLanVPortProfileDestroyCallback,
772 calld, macaddress, NETLINK_ROUTE) < 0)
779 virNetlinkCallbackDataFree(calld);
785 * virNetDevMacVLanCreateWithVPortProfile:
786 * Create an instance of a macvtap device and open its tap character
788 * @tgifname: Interface name that the macvtap is supposed to have. May
789 * be NULL if this function is supposed to choose a name
790 * @macaddress: The MAC address for the macvtap device
791 * @linkdev: The interface name of the NIC to connect to the external bridge
792 * @mode: int describing the mode for 'bridge', 'vepa', 'private' or 'passthru'.
793 * @vnet_hdr: 1 to enable IFF_VNET_HDR, 0 to disable it
794 * @vmuuid: The UUID of the VM the macvtap belongs to
795 * @virtPortProfile: pointer to object holding the virtual port profile data
796 * @res_ifname: Pointer to a string pointer where the actual name of the
797 * interface will be stored into if everything succeeded. It is up
798 * to the caller to free the string.
800 * Returns file descriptor of the tap device in case of success with @withTap,
801 * otherwise returns 0; returns -1 on error.
803 int virNetDevMacVLanCreateWithVPortProfile(const char *tgifname,
804 const virMacAddr *macaddress,
806 virNetDevMacVLanMode mode,
809 const unsigned char *vmuuid,
810 virNetDevVPortProfilePtr virtPortProfile,
812 virNetDevVPortProfileOp vmOp,
814 virNetDevBandwidthPtr bandwidth)
816 const char *type = withTap ? "macvtap" : "macvlan";
817 const char *prefix = withTap ? MACVTAP_NAME_PREFIX : MACVLAN_NAME_PREFIX;
818 const char *pattern = withTap ? MACVTAP_NAME_PATTERN : MACVLAN_NAME_PATTERN;
820 char ifname[IFNAMSIZ];
821 int retries, do_retry = 0;
822 uint32_t macvtapMode;
823 const char *cr_ifname = NULL;
827 macvtapMode = modeMap[mode];
831 VIR_DEBUG("%s: VM OPERATION: %s", __FUNCTION__, virNetDevVPortProfileOpTypeToString(vmOp));
833 /** Note: When using PASSTHROUGH mode with MACVTAP devices the link
834 * device's MAC address must be set to the VMs MAC address. In
835 * order to not confuse the first switch or bridge in line this MAC
836 * address must be reset when the VM is shut down.
837 * This is especially important when using SRIOV capable cards that
838 * emulate their switch in firmware.
840 if (mode == VIR_NETDEV_MACVLAN_MODE_PASSTHRU) {
841 if (virNetDevReplaceMacAddress(linkdev, macaddress, stateDir) < 0)
846 if ((ret = virNetDevExists(tgifname)) < 0)
850 if (STRPREFIX(tgifname, prefix)) {
853 virReportSystemError(EEXIST,
854 _("Unable to create macvlan device %s"), tgifname);
857 cr_ifname = tgifname;
858 rc = virNetDevMacVLanCreate(tgifname, type, macaddress, linkdev,
859 macvtapMode, &do_retry);
865 virMutexLock(&virNetDevMacVLanCreateMutex);
866 for (c = 0; c < 8192; c++) {
867 snprintf(ifname, sizeof(ifname), pattern, c);
868 if ((ret = virNetDevExists(ifname)) < 0) {
869 virMutexUnlock(&virNetDevMacVLanCreateMutex);
873 rc = virNetDevMacVLanCreate(ifname, type, macaddress, linkdev,
874 macvtapMode, &do_retry);
880 if (do_retry && --retries)
886 virMutexUnlock(&virNetDevMacVLanCreateMutex);
891 if (virNetDevVPortProfileAssociate(cr_ifname,
896 vmuuid, vmOp, false) < 0) {
901 if (virNetDevSetOnline(cr_ifname, true) < 0) {
903 goto disassociate_exit;
907 if ((rc = virNetDevMacVLanTapOpen(cr_ifname, 10)) < 0)
908 goto disassociate_exit;
910 if (virNetDevMacVLanTapSetup(rc, vnet_hdr) < 0) {
911 VIR_FORCE_CLOSE(rc); /* sets rc to -1 */
912 goto disassociate_exit;
914 if (VIR_STRDUP(*res_ifname, cr_ifname) < 0) {
915 VIR_FORCE_CLOSE(rc); /* sets rc to -1 */
916 goto disassociate_exit;
919 if (VIR_STRDUP(*res_ifname, cr_ifname) < 0)
920 goto disassociate_exit;
924 if (virNetDevBandwidthSet(cr_ifname, bandwidth, false) < 0) {
925 virReportError(VIR_ERR_INTERNAL_ERROR,
926 _("cannot set bandwidth limits on %s"),
929 VIR_FORCE_CLOSE(rc); /* sets rc to -1 */
932 goto disassociate_exit;
935 if (vmOp == VIR_NETDEV_VPORT_PROFILE_OP_CREATE ||
936 vmOp == VIR_NETDEV_VPORT_PROFILE_OP_RESTORE) {
937 /* Only directly register upon a create or restore (restarting
938 * a saved image) - migration and libvirtd restart are handled
941 if (virNetDevMacVLanVPortProfileRegisterCallback(cr_ifname, macaddress,
945 goto disassociate_exit;
951 ignore_value(virNetDevVPortProfileDisassociate(cr_ifname,
959 ignore_value(virNetDevMacVLanDelete(cr_ifname));
966 * virNetDevMacVLanDeleteWithVPortProfile:
967 * @ifname : The name of the macvtap interface
968 * @linkdev: The interface name of the NIC to connect to the external bridge
969 * @virtPortProfile: pointer to object holding the virtual port profile data
971 * Delete an interface given its name. Disassociate
972 * it with the switch if port profile parameters
975 int virNetDevMacVLanDeleteWithVPortProfile(const char *ifname,
976 const virMacAddr *macaddr,
979 virNetDevVPortProfilePtr virtPortProfile,
985 if (mode == VIR_NETDEV_MACVLAN_MODE_PASSTHRU) {
986 ignore_value(virNetDevRestoreMacAddress(linkdev, stateDir));
990 if (virNetDevVPortProfileDisassociate(ifname,
995 VIR_NETDEV_VPORT_PROFILE_OP_DESTROY) < 0)
997 if (virNetDevMacVLanDelete(ifname) < 0)
1001 virNetlinkEventRemoveClient(0, macaddr, NETLINK_ROUTE);
1007 * virNetDevMacVLanRestartWithVPortProfile:
1008 * Register a port profile callback handler for a VM that
1009 * is already running
1011 * @cr_ifname: Interface name that the macvtap has.
1012 * @macaddress: The MAC address for the macvtap device
1013 * @linkdev: The interface name of the NIC to connect to the external bridge
1014 * @vmuuid: The UUID of the VM the macvtap belongs to
1015 * @virtPortProfile: pointer to object holding the virtual port profile data
1016 * @vmOp: Operation to use during setup of the association
1018 * Returns 0; returns -1 on error.
1020 int virNetDevMacVLanRestartWithVPortProfile(const char *cr_ifname,
1021 const virMacAddr *macaddress,
1022 const char *linkdev,
1023 const unsigned char *vmuuid,
1024 virNetDevVPortProfilePtr virtPortProfile,
1025 virNetDevVPortProfileOp vmOp)
1029 rc = virNetDevMacVLanVPortProfileRegisterCallback(cr_ifname, macaddress,
1031 virtPortProfile, vmOp);
1035 ignore_value(virNetDevVPortProfileAssociate(cr_ifname,
1048 #else /* ! WITH_MACVTAP */
1049 int virNetDevMacVLanCreate(const char *ifname ATTRIBUTE_UNUSED,
1050 const char *type ATTRIBUTE_UNUSED,
1051 const virMacAddr *macaddress ATTRIBUTE_UNUSED,
1052 const char *srcdev ATTRIBUTE_UNUSED,
1053 uint32_t macvlan_mode ATTRIBUTE_UNUSED,
1054 int *retry ATTRIBUTE_UNUSED)
1056 virReportSystemError(ENOSYS, "%s",
1057 _("Cannot create macvlan devices on this platform"));
1061 int virNetDevMacVLanDelete(const char *ifname ATTRIBUTE_UNUSED)
1063 virReportSystemError(ENOSYS, "%s",
1064 _("Cannot create macvlan devices on this platform"));
1068 int virNetDevMacVLanCreateWithVPortProfile(const char *ifname ATTRIBUTE_UNUSED,
1069 const virMacAddr *macaddress ATTRIBUTE_UNUSED,
1070 const char *linkdev ATTRIBUTE_UNUSED,
1071 virNetDevMacVLanMode mode ATTRIBUTE_UNUSED,
1072 bool withTap ATTRIBUTE_UNUSED,
1073 int vnet_hdr ATTRIBUTE_UNUSED,
1074 const unsigned char *vmuuid ATTRIBUTE_UNUSED,
1075 virNetDevVPortProfilePtr virtPortProfile ATTRIBUTE_UNUSED,
1076 char **res_ifname ATTRIBUTE_UNUSED,
1077 virNetDevVPortProfileOp vmop ATTRIBUTE_UNUSED,
1078 char *stateDir ATTRIBUTE_UNUSED,
1079 virNetDevBandwidthPtr bandwidth ATTRIBUTE_UNUSED)
1081 virReportSystemError(ENOSYS, "%s",
1082 _("Cannot create macvlan devices on this platform"));
1086 int virNetDevMacVLanDeleteWithVPortProfile(const char *ifname ATTRIBUTE_UNUSED,
1087 const virMacAddr *macaddress ATTRIBUTE_UNUSED,
1088 const char *linkdev ATTRIBUTE_UNUSED,
1089 int mode ATTRIBUTE_UNUSED,
1090 virNetDevVPortProfilePtr virtPortProfile ATTRIBUTE_UNUSED,
1091 char *stateDir ATTRIBUTE_UNUSED)
1093 virReportSystemError(ENOSYS, "%s",
1094 _("Cannot create macvlan devices on this platform"));
1098 int virNetDevMacVLanRestartWithVPortProfile(const char *cr_ifname ATTRIBUTE_UNUSED,
1099 const virMacAddr *macaddress ATTRIBUTE_UNUSED,
1100 const char *linkdev ATTRIBUTE_UNUSED,
1101 const unsigned char *vmuuid ATTRIBUTE_UNUSED,
1102 virNetDevVPortProfilePtr virtPortProfile ATTRIBUTE_UNUSED,
1103 virNetDevVPortProfileOp vmOp ATTRIBUTE_UNUSED)
1105 virReportSystemError(ENOSYS, "%s",
1106 _("Cannot create macvlan devices on this platform"));
1110 int virNetDevMacVLanVPortProfileRegisterCallback(const char *ifname ATTRIBUTE_UNUSED,
1111 const virMacAddr *macaddress ATTRIBUTE_UNUSED,
1112 const char *linkdev ATTRIBUTE_UNUSED,
1113 const unsigned char *vmuuid ATTRIBUTE_UNUSED,
1114 virNetDevVPortProfilePtr virtPortProfile ATTRIBUTE_UNUSED,
1115 virNetDevVPortProfileOp vmOp ATTRIBUTE_UNUSED)
1117 virReportSystemError(ENOSYS, "%s",
1118 _("Cannot create macvlan devices on this platform"));
1121 #endif /* ! WITH_MACVTAP */