VMs running docker can have hundred of virtual network interfaces.
Also, docker creates one virtual network interface 'docker0' with
an IPv4 address. This address is useless outside the VM, and should
not be propagated via GuestInfo, or even as the primary network
address.
This change adds on option for tools.conf to exclude specific
network interface names using patterns with wildcards. This makes
it easy to exclude virtual docker interface names with the option
exclude-nics=docker*,veth*
For convenience, the option is set to docker*,veth* by default,
except for Windows, where it is "vEthernet*". To
send information of all interfaces, including docker* and veth*,
the option needs to be set to an empty value: exclude-nics=
*/
#define CONFNAME_GUESTINFO_ENABLESTATLOGGING "enable-stat-logging"
+/**
+ * Set a comma separated list of network interface names that shall be ignored.
+ *
+ * @note interface names can use wildcards like '*' and '?'
+ *
+ * @param string comma separated list of interface name patterns.
+ */
+
+#define CONFNAME_GUESTINFO_EXCLUDENICS "exclude-nics"
+
/*
* END GuestInfo goodies.
******************************************************************************
GuestInfo_IsEqual_WinsConfigInfo(const WinsConfigInfo *a,
const WinsConfigInfo *b);
+void GuestInfo_SetIfaceExcludeList(char **list);
+
+Bool GuestInfo_IfaceIsExcluded(const char *name);
+
#endif
#include "netutil.h"
#include "wiper.h"
+GPtrArray *gIfaceExcludePatterns = NULL;
/**
* Helper to initialize an opaque struct member.
* Global functions.
*/
+/*
+ ******************************************************************************
+ *
+ * GuestInfo_SetIfaceExcludeList --
+ *
+ * @brief Set list of network interfaces to be ignored.
+ *
+ * @param[in] NULL terminated array of pointers to strings with patterns
+ *
+ * @sa gIfaceExcludePatterns will be set
+ *
+ ******************************************************************************
+ */
+
+void
+GuestInfo_SetIfaceExcludeList(char **list)
+{
+ guint i;
+
+ if (gIfaceExcludePatterns != NULL) {
+ g_ptr_array_free(gIfaceExcludePatterns, TRUE);
+ gIfaceExcludePatterns = NULL;
+ }
+
+ if (list != NULL) {
+ gIfaceExcludePatterns =
+ g_ptr_array_new_with_free_func((GDestroyNotify) &g_pattern_spec_free);
+ for (i = 0; list[i] != NULL; i++) {
+ if (list[i][0] != '\0') {
+ g_ptr_array_add(gIfaceExcludePatterns, g_pattern_spec_new(list[i]));
+ }
+ }
+ }
+}
+
+/*
+ ******************************************************************************
+ *
+ * GuestInfo_IfaceIsExcluded --
+ *
+ * @brief Determine if a specific interface name shall be excluded.
+ *
+ * @param[in] The interface name.
+ *
+ * @retval TRUE if interface name shall be excluded.
+ *
+ ******************************************************************************
+*/
+
+Bool
+GuestInfo_IfaceIsExcluded(const char *name)
+{
+ int i;
+
+ if (gIfaceExcludePatterns != NULL && name != NULL) {
+ for(i = 0; i < gIfaceExcludePatterns->len; i++) {
+ if (g_pattern_match_string(g_ptr_array_index(gIfaceExcludePatterns, i),
+ name)) {
+ g_debug("%s: excluding interface %s because it matched pattern %d",
+ __FUNCTION__, name, i);
+ return TRUE;
+ }
+ }
+ }
+ return FALSE;
+}
/*
******************************************************************************
GuestNicV3 *nic;
struct ifaddrs *ip;
struct sockaddr_ll *sll = (struct sockaddr_ll *)pkt->ifa_addr;
+
+ if (GuestInfo_IfaceIsExcluded(pkt->ifa_name)) {
+ continue;
+ }
+
if (sll != NULL && sll->sll_family == AF_PACKET) {
char macAddress[NICINFO_MAC_LEN];
Str_Sprintf(macAddress, sizeof macAddress,
if (!(curr->ifa_flags & IFF_UP) || curr->ifa_flags & IFF_LOOPBACK) {
continue;
+ } else if (GuestInfo_IfaceIsExcluded(curr->ifa_name)) {
+ continue;
} else if (currFamily == AF_INET || currFamily == AF_INET6) {
ipstr = ValidateConvertAddress(curr->ifa_addr);
} else {
if (entry->intf_link_addr.addr_type == ADDR_TYPE_ETH) {
Str_Sprintf(macAddress, sizeof macAddress, "%s",
addr_ntoa(&entry->intf_link_addr));
+
+ if (GuestInfo_IfaceIsExcluded(entry->intf_name)) {
+ return 0;
+ }
+
nic = GuestInfoAddNicEntry(nicInfo, macAddress, NULL, NULL);
if (NULL == nic) {
/*
struct sockaddr_storage ss;
struct sockaddr *saddr = (struct sockaddr *)&ss;
+ if (GuestInfo_IfaceIsExcluded(entry->intf_name)) {
+ return 0;
+ }
+
memset(&ss, 0, sizeof ss);
addr_ntos(&entry->intf_addr, saddr);
*ipstr = ValidateConvertAddress(saddr);
* @param[in] section Section to look for in the config file.
* @param[in] defValue Default value if the key is not found or error.
*
- * @return value of the key if value was read successfully, else defValue.
+ * @return value of the key if value was read successfully, else a copy
+ * of defValue unless defValue is NULL, in which case it's NULL.
+ * The returned string should be freed with g_free() when no longer needed.
*/
gchar *
}
g_debug("%s: Returning default value for '[%s] %s'=%s.\n",
__FUNCTION__, section, key, defValue ? defValue : "(null)");
- value = defValue;
+ value = g_strdup(defValue);
g_clear_error(&err);
}
return value;
#define GUESTINFO_DEFAULT_DELIMITER ' '
+/**
+ * The default setting for exclude-nics
+ */
+#if defined(_WIN32)
+#define GUESTINFO_DEFAULT_IFACE_EXCLUDES "vEthernet*"
+#else
+#define GUESTINFO_DEFAULT_IFACE_EXCLUDES "docker*,veth*"
+#endif
+
/*
* Define what guest info types and nic info versions could be sent
* to update nic info at VMX. The order defines a sequence of fallback
}
+/*
+ ******************************************************************************
+ * GuestInfoSetNicExcludeList -- */ /**
+ *
+ * Gets exclude-nics setting from the config, and sets the list of exclude
+ * patterns.
+ *
+ * @param[in] ctx The application context.
+ *
+ ******************************************************************************
+ */
+
+static void
+GuestInfoSetNicExcludeList(ToolsAppCtx *ctx)
+{
+ static gchar *ifaceExcludeStringCached = NULL;
+ gchar *ifaceExcludeString;
+
+ /* Check if we want to exclude interfaces based on the name. */
+ ifaceExcludeString = VMTools_ConfigGetString(ctx->config, CONFGROUPNAME_GUESTINFO,
+ CONFNAME_GUESTINFO_EXCLUDENICS,
+ GUESTINFO_DEFAULT_IFACE_EXCLUDES);
+ if (g_strcmp0(ifaceExcludeString, ifaceExcludeStringCached) != 0) {
+ gchar **list = NULL;
+ if (ifaceExcludeString != NULL && ifaceExcludeString[0] != '\0') {
+ list = g_strsplit(ifaceExcludeString, ",", 0);
+ }
+ g_free(ifaceExcludeStringCached);
+ ifaceExcludeStringCached = ifaceExcludeString;
+ GuestInfo_SetIfaceExcludeList(list);
+ g_strfreev(list);
+ }
+}
+
/*
******************************************************************************
* GuestInfoGather -- */ /**
}
/* Get NIC information. */
+
+ GuestInfoSetNicExcludeList(ctx);
+
if (!GuestInfo_GetNicInfo(&nicInfo)) {
g_warning("Failed to get nic info.\n");
/*
{
GuestInfoClearCache();
+ GuestInfo_SetIfaceExcludeList(NULL);
+
if (gatherInfoTimeoutSource != NULL) {
g_source_destroy(gatherInfoTimeoutSource);
gatherInfoTimeoutSource = NULL;