return -1;
}
+/* The general purpose function virNWFilterVarValueEqual returns a
+ * bool, but the comparison callback for virHashEqual (called below)
+ * needs to return an int of 0 for == and non-0 for !=
+ */
+static int
+virNWFilterVarValueCompare(const void *a, const void *b)
+{
+ return virNWFilterVarValueEqual((const virNWFilterVarValuePtr) a,
+ (const virNWFilterVarValuePtr) b) ? 0 : 1;
+}
+
+bool
+virNWFilterHashTableEqual(virNWFilterHashTablePtr a,
+ virNWFilterHashTablePtr b)
+{
+ if (!(a || b))
+ return true;
+ if (!(a && b))
+ return false;
+ return virHashEqual(a->hashTable, b->hashTable, virNWFilterVarValueCompare);
+}
static bool
isValidVarName(const char *var)
/*
* nwfilter_params.h: parsing and data maintenance of filter parameters
*
- * Copyright (C) 2011 Red Hat, Inc.
+ * Copyright (C) 2011-2012 Red Hat, Inc.
* Copyright (C) 2010 IBM Corporation
*
* This library is free software; you can redistribute it and/or
const char *name);
int virNWFilterHashTablePutAll(virNWFilterHashTablePtr src,
virNWFilterHashTablePtr dest);
+bool virNWFilterHashTableEqual(virNWFilterHashTablePtr a,
+ virNWFilterHashTablePtr b);
# define VALID_VARNAME \
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_"
return ret;
}
+static int
+qemuDomainChangeNetFilter(virConnectPtr conn,
+ virDomainObjPtr vm,
+ virDomainNetDefPtr olddev,
+ virDomainNetDefPtr newdev)
+{
+ /* make sure this type of device supports filters. */
+ switch (virDomainNetGetActualType(newdev)) {
+ case VIR_DOMAIN_NET_TYPE_ETHERNET:
+ case VIR_DOMAIN_NET_TYPE_BRIDGE:
+ case VIR_DOMAIN_NET_TYPE_NETWORK:
+ break;
+ default:
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("filters not supported on interfaces of type %s"),
+ virDomainNetTypeToString(virDomainNetGetActualType(newdev)));
+ return -1;
+ }
+
+ virDomainConfNWFilterTeardown(olddev);
+
+ if (virDomainConfNWFilterInstantiate(conn, vm->def->uuid, newdev) < 0) {
+ virErrorPtr errobj;
+
+ virReportError(VIR_ERR_OPERATION_FAILED,
+ _("failed to add new filter rules to '%s' "
+ "- attempting to restore old rules"),
+ olddev->ifname);
+ errobj = virSaveLastError();
+ ignore_value(virDomainConfNWFilterInstantiate(conn, vm->def->uuid, olddev));
+ virSetError(errobj);
+ virFreeError(errobj);
+ return -1;
+ }
+ return 0;
+}
+
int qemuDomainChangeNetLinkState(virQEMUDriverPtr driver,
virDomainObjPtr vm,
virDomainNetDefPtr dev,
int oldType, newType;
bool needReconnect = false;
bool needBridgeChange = false;
+ bool needFilterChange = false;
bool needLinkStateChange = false;
bool needReplaceDevDef = false;
int ret = -1;
}
/* (end of device info checks) */
- if (STRNEQ_NULLABLE(olddev->filter, newdev->filter))
- needReconnect = true;
+ if (STRNEQ_NULLABLE(olddev->filter, newdev->filter) ||
+ !virNWFilterHashTableEqual(olddev->filterparams, newdev->filterparams)) {
+ needFilterChange = true;
+ }
/* bandwidth can be modified, and will be checked later */
/* vlan can be modified, and will be checked later */
goto cleanup;
/* we successfully switched to the new bridge, and we've
* determined that the rest of newdev is equivalent to olddev,
- * so move newdev into place, so that the */
+ * so move newdev into place */
+ needReplaceDevDef = true;
+ }
+
+ if (needFilterChange) {
+ if (qemuDomainChangeNetFilter(dom->conn, vm, olddev, newdev) < 0)
+ goto cleanup;
+ /* we successfully switched to the new filter, and we've
+ * determined that the rest of newdev is equivalent to olddev,
+ * so move newdev into place */
needReplaceDevDef = true;
}