[libvirt] [PATCH 0/6] Add disk streaming API to libvirt
by Adam Litke
I've been working with Anthony Liguori and Stefan Hajnoczi to enable data
streaming to copy-on-read disk images in qemu. This work is working its way
through review and I expect it to be upstream soon as part of the support for
the new QED disk image format.
Disk streaming is extremely useful when provisioning domains from a central
repository of template images. Currently the domain must be provisioned by
either: 1) copying the template image to local storage before the VM can be
started or, 2) creating a qcow2 image that backs to a base image in the remote
repository. Option 1 can introduce a significant delay when provisioning large
disks. Option 2 introduces a permanent dependency on a remote service and
increased network load to satisfy disk reads.
Device streaming provides the "instant-on" benefits of option 2 without
introducing a permanent dependency to the image repository. Once the VM is
started, the contents of the disk can be streamed to the local image in
parallel. Once streaming is finished, the domain has a complete and coherent
copy of the image and no longer depends on the central image repository.
Qemu will support two streaming modes: full device and single sector. Full
device streaming is the easiest to use because one command will cause the whole
device to be streamed as fast as possible. Single sector mode can be used if
one wants to throttle streaming to reduce I/O pressure. In this mode, a
management tool issues individual commands to stream single sectors.
To enable this support in libvirt, I propose the following API...
virDomainStreamDisk() will start or stop a full device stream or stream a
single sector of a device. The behavior is controlled by setting
virDomainStreamDiskFlags. When either starting or stopping a full device
stream, the return value is either 0 or -1 to indicate whether the operation
succeeded. For a single sector stream, a device offset is returned (or -1 on
failure). This value can be used to continue streaming with a subsequent call
to virDomainStreamDisk().
virDomainStreamDiskInfo() returns information about active full device streams
(the device alias, current streaming position, and total size).
Adam Litke (6):
Add new API virDomainStreamDisk[Info] to header and drivers
virDomainStreamDisk: Add public symbols to libvirt API
Implement disk streaming in the qemu driver
Add disk streaming support to the remote driver
Add new disk streaming commands to virsh
python: Add python bindings for virDomainStreamDisk[Info]
b/daemon/remote.c | 96 ++++++++++++++++++++
b/daemon/remote_dispatch_args.h | 2
b/daemon/remote_dispatch_prototypes.h | 16 +++
b/daemon/remote_dispatch_ret.h | 2
b/daemon/remote_dispatch_table.h | 10 ++
b/include/libvirt/libvirt.h.in | 34 +++++++
b/python/generator.py | 4
b/python/libvirt-override-api.xml | 5 +
b/python/libvirt-override.c | 46 +++++++++
b/src/driver.h | 11 ++
b/src/esx/esx_driver.c | 2
b/src/libvirt.c | 115 ++++++++++++++++++++++++
b/src/libvirt_public.syms | 5 +
b/src/lxc/lxc_driver.c | 2
b/src/openvz/openvz_driver.c | 2
b/src/phyp/phyp_driver.c | 2
b/src/qemu/qemu_driver.c | 77 +++++++++++++++-
b/src/qemu/qemu_monitor.c | 42 ++++++++
b/src/qemu/qemu_monitor.h | 6 +
b/src/qemu/qemu_monitor_json.c | 108 ++++++++++++++++++++++
b/src/qemu/qemu_monitor_json.h | 7 +
b/src/qemu/qemu_monitor_text.c | 162 ++++++++++++++++++++++++++++++++++
b/src/qemu/qemu_monitor_text.h | 8 +
b/src/remote/remote_driver.c | 87 +++++++++++++++++-
b/src/remote/remote_protocol.c | 63 +++++++++++++
b/src/remote/remote_protocol.h | 51 ++++++++++
b/src/remote/remote_protocol.x | 37 +++++++
b/src/test/test_driver.c | 2
b/src/uml/uml_driver.c | 2
b/src/vbox/vbox_tmpl.c | 2
b/src/vmware/vmware_driver.c | 2
b/src/xen/xen_driver.c | 2
b/tools/virsh.c | 134 +++++++++++++++++++++++++++-
python/generator.py | 3
src/qemu/qemu_driver.c | 2
src/remote/remote_driver.c | 2
36 files changed, 1144 insertions(+), 9 deletions(-)
13 years, 7 months
[libvirt] [PATCH 8/9] add DHCP snooping support to nwfilter
by David L Stevens
This patch adds DHCP Snooping support to libvirt.
Signed-off-by: David L Stevens <dlstevens(a)us.ibm.com>
diff --git a/examples/xml/nwfilter/no-ip-spoofing.xml b/examples/xml/nwfilter/no-ip-spoofing.xml
index 2fccd12..2ae9500 100644
--- a/examples/xml/nwfilter/no-ip-spoofing.xml
+++ b/examples/xml/nwfilter/no-ip-spoofing.xml
@@ -4,4 +4,9 @@
<rule action='return' direction='out'>
<ip match='yes' srcipaddr='$IP' />
</rule>
+ <!-- allow DHCP requests -->
+ <rule action='return' direction='out'>
+ <ip match='yes' srcipaddr='0.0.0.0' protocol='udp' srcportstart='68'
+ srcportend='68' />
+ </rule>
</filter>
diff --git a/src/Makefile.am b/src/Makefile.am
index 1eaa7d1..3da0797 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -386,6 +386,8 @@ NWFILTER_DRIVER_SOURCES = \
nwfilter/nwfilter_driver.h nwfilter/nwfilter_driver.c \
nwfilter/nwfilter_gentech_driver.c \
nwfilter/nwfilter_gentech_driver.h \
+ nwfilter/nwfilter_dhcpsnoop.c \
+ nwfilter/nwfilter_dhcpsnoop.h \
nwfilter/nwfilter_ebiptables_driver.c \
nwfilter/nwfilter_ebiptables_driver.h \
nwfilter/nwfilter_learnipaddr.c \
diff --git a/src/nwfilter/nwfilter_dhcpsnoop.c b/src/nwfilter/nwfilter_dhcpsnoop.c
new file mode 100644
index 0000000..af83149
--- /dev/null
+++ b/src/nwfilter/nwfilter_dhcpsnoop.c
@@ -0,0 +1,582 @@
+
+/*
+ * nwfilter_dhcpsnoop.c: support for DHCP snooping used by a VM
+ * on an interface
+ *
+ * Copyright (C) 2011 IBM Corp.
+ * Copyright (C) 2011 David L Stevens
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Author: David L Stevens <dlstevens(a)us.ibm.com>
+ * Based in part on work by Stefan Berger <stefanb(a)us.ibm.com>
+ */
+
+#include <config.h>
+
+#ifdef HAVE_LIBPCAP
+#include <pcap.h>
+#endif
+
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <signal.h>
+
+#include <arpa/inet.h>
+#include <net/ethernet.h>
+#include <netinet/ip.h>
+#include <netinet/udp.h>
+#include <net/if.h>
+#include <net/if_arp.h>
+#include <intprops.h>
+
+#include "internal.h"
+
+#include "buf.h"
+#include "memory.h"
+#include "logging.h"
+#include "datatypes.h"
+#include "interface.h"
+#include "virterror_internal.h"
+#include "threads.h"
+#include "conf/nwfilter_params.h"
+#include "conf/domain_conf.h"
+#include "nwfilter_gentech_driver.h"
+#include "nwfilter_ebiptables_driver.h"
+#include "nwfilter_dhcpsnoop.h"
+
+#define VIR_FROM_THIS VIR_FROM_NWFILTER
+
+static virHashTablePtr SnoopReqs;
+
+struct virNWFilterSnoopReq {
+ virConnectPtr conn;
+ virNWFilterTechDriverPtr techdriver;
+ enum virDomainNetType nettype;
+ virNWFilterDefPtr filter;
+ const char *ifname;
+ virNWFilterHashTablePtr vars;
+ virNWFilterDriverStatePtr driver;
+ pthread_t thread;
+ /* start and end of lease list, ordered by lease time */
+ struct iplease *start;
+ struct iplease *end;
+ bool die;
+};
+
+#define POLL_INTERVAL 10*1000 /* 10 secs */
+
+struct iplease {
+ uint32_t ipl_ipaddr;
+ uint32_t ipl_server;
+ struct virNWFilterSnoopReq *ipl_req;
+ unsigned int ipl_timeout;
+ /* timer list */
+ struct iplease *ipl_prev;
+ struct iplease *ipl_next;
+};
+
+static struct iplease *ipl_getbyip(struct iplease *start, uint32_t ipaddr);
+static void ipl_update(struct iplease *pl, uint32_t timeout);
+
+
+/*
+ * ipl_tadd - add an IP lease to the timer list
+ */
+static void
+ipl_tadd(struct iplease *plnew)
+{
+ struct virNWFilterSnoopReq *req = plnew->ipl_req;
+ struct iplease *pl;
+
+ plnew->ipl_next = plnew->ipl_prev = 0;
+ if (!req->start) {
+ plnew->ipl_prev = plnew->ipl_next = 0;
+ req->start = req->end = plnew;
+ return;
+ }
+ for (pl = req->end; pl && plnew->ipl_timeout < pl->ipl_timeout;
+ pl = pl->ipl_prev)
+ /* empty */ ;
+ if (!pl) {
+ plnew->ipl_next = req->start;
+ req->start = plnew;
+ } else {
+ plnew->ipl_next = pl->ipl_next;
+ pl->ipl_next = plnew;
+ }
+ plnew->ipl_prev = pl;
+ if (plnew->ipl_next)
+ plnew->ipl_next->ipl_prev = plnew;
+ else
+ req->end = plnew;
+}
+
+/*
+ * ipl_add - create or update an IP lease
+ */
+static void
+ipl_add(struct iplease *plnew)
+{
+ struct iplease *pl;
+ int rc;
+ char ipbuf[20]; /* dotted decimal IP addr string */
+ char *ipstr;
+
+ pl = ipl_getbyip(plnew->ipl_req->start, plnew->ipl_ipaddr);
+ if (pl) {
+ ipl_update(pl, plnew->ipl_timeout);
+ return;
+ }
+ if (VIR_ALLOC(pl) < 0) {
+ virReportOOMError();
+ return;
+ }
+ *pl = *plnew;
+
+ if (!inet_ntop(AF_INET, &pl->ipl_ipaddr, ipbuf, sizeof(ipbuf))) {
+ virNWFilterReportError(VIR_ERR_INTERNAL_ERROR,
+ _("ipl_add inet_ntop " "failed (0x%08X)"),
+ pl->ipl_ipaddr);
+ VIR_FREE(pl);
+ return;
+
+ }
+
+ ipstr = strdup(ipbuf);
+ if (!ipstr) {
+ VIR_FREE(pl);
+ virReportOOMError();
+ return;
+ }
+ rc = virNWFilterChangeVar(pl->ipl_req->conn,
+ pl->ipl_req->techdriver,
+ pl->ipl_req->nettype,
+ pl->ipl_req->filter,
+ pl->ipl_req->ifname,
+ pl->ipl_req->vars,
+ pl->ipl_req->driver, "IP", ipstr, 0);
+ if (rc) {
+ VIR_FREE(ipstr);
+ VIR_FREE(pl);
+ return;
+ }
+ ipl_tadd(pl);
+}
+
+/*
+ * ipl_tdel - remove an IP lease from the timer list
+ */
+static void
+ipl_tdel(struct iplease *ipl)
+{
+ struct virNWFilterSnoopReq *req = ipl->ipl_req;
+
+ if (ipl->ipl_prev)
+ ipl->ipl_prev->ipl_next = ipl->ipl_next;
+ else
+ req->start = ipl->ipl_next;
+ if (ipl->ipl_next)
+ ipl->ipl_next->ipl_prev = ipl->ipl_prev;
+ else
+ req->end = ipl->ipl_prev;
+ ipl->ipl_next = ipl->ipl_prev = 0;
+}
+
+/*
+ * ipl_del - delete an IP lease
+ */
+static void
+ipl_del(struct iplease *ipl)
+{
+ struct virNWFilterSnoopReq *req;
+ char ipbuf[20]; /* dotted decimal IP addr string */
+ char *ipstr;
+
+ if (!ipl)
+ return;
+
+ req = ipl->ipl_req;
+
+ ipl_tdel(ipl);
+
+ if (inet_ntop(AF_INET, &ipl->ipl_ipaddr, ipbuf, sizeof(ipbuf))) {
+ ipstr = strdup(ipbuf);
+ if (virNWFilterChangeVar(req->conn,
+ req->techdriver,
+ req->nettype,
+ req->filter,
+ req->ifname,
+ req->vars, req->driver, "IP", ipstr, 1))
+ virNWFilterReportError(VIR_ERR_INTERNAL_ERROR,
+ _("ipl_del virNWFilterChangeVar failed; "
+ "filter not deleted"));
+ } else
+ virNWFilterReportError(VIR_ERR_INTERNAL_ERROR,
+ _("ipl_del inet_ntop " "failed (0x%08X)"),
+ ipl->ipl_ipaddr);
+ VIR_FREE(ipl);
+}
+
+/*
+ * ipl_update - update the timeout on an IP lease
+ */
+static void
+ipl_update(struct iplease *ipl, uint32_t timeout)
+{
+ ipl_tdel(ipl);
+ ipl->ipl_timeout = timeout;
+ ipl_tadd(ipl);
+ return;
+}
+
+/*
+ * ipl_getbyip - lookup IP lease by IP address
+ */
+static struct iplease *
+ipl_getbyip(struct iplease *start, uint32_t ipaddr)
+{
+ struct iplease *pl;
+
+ for (pl = start; pl && pl->ipl_ipaddr != ipaddr; pl = pl->ipl_next)
+ /* empty */ ;
+ return pl;
+}
+
+#define GRACE 5
+
+/*
+ * ipl_trun - run the IP lease timeout list
+ */
+static unsigned int
+ipl_trun(struct virNWFilterSnoopReq *req)
+{
+ uint32_t now;
+
+ now = time(0);
+ while (req->start && req->start->ipl_timeout <= now)
+ ipl_del(req->start);
+ return 0;
+}
+
+typedef unsigned char Eaddr[6];
+
+struct eth {
+ Eaddr eh_dst;
+ Eaddr eh_src;
+ unsigned short eh_type;
+ unsigned char eh_data[0];
+};
+
+struct dhcp {
+ unsigned char d_op;
+ unsigned char d_htype;
+ unsigned char d_hlen;
+ unsigned char d_hops;
+ unsigned int d_xid;
+ unsigned short d_secs;
+ unsigned short d_flags;
+ unsigned int d_ciaddr;
+ unsigned int d_yiaddr;
+ unsigned int d_siaddr;
+ unsigned int d_giaddr;
+ unsigned char d_chaddr[16];
+ char d_sname[64];
+ char d_file[128];
+ unsigned char d_opts[0];
+};
+
+/* DHCP options */
+
+#define DHCPO_PAD 0
+#define DHCPO_LEASE 51 /* lease time in secs */
+#define DHCPO_MTYPE 53 /* message type */
+#define DHCPO_END 255 /* end of options */
+
+/* DHCP message types */
+#define DHCPDECLINE 4
+#define DHCPACK 5
+#define DHCPRELEASE 7
+
+unsigned char dhcp_magic[4] = { 99, 130, 83, 99 };
+
+static int
+dhcp_getopt(struct dhcp *pd, int len, int *pmtype, int *pleasetime)
+{
+ int oind, olen;
+ int oend;
+
+ olen = len - sizeof *pd;
+ oind = 0;
+
+ if (olen < 4) /* bad magic */
+ return -1;
+ for (oind = 0; oind < sizeof dhcp_magic; ++oind)
+ if (pd->d_opts[oind] != dhcp_magic[oind])
+ return -1; /* bad magic */
+
+ oend = 0;
+
+ *pmtype = *pleasetime = 0;
+
+ while (oind < olen) {
+ switch (pd->d_opts[oind]) {
+ case DHCPO_LEASE:
+ if (olen - oind < 6)
+ goto malformed;
+ if (*pleasetime)
+ return -1; /* duplicate lease time */
+ *pleasetime =
+ ntohl(*(unsigned int *) (pd->d_opts + oind + 2));
+ break;
+ case DHCPO_MTYPE:
+ if (olen - oind < 3)
+ goto malformed;
+ if (*pmtype)
+ return -1; /* duplicate message type */
+ *pmtype = pd->d_opts[oind + 2];
+ break;
+ case DHCPO_PAD:
+ oind++;
+ continue;
+
+ case DHCPO_END:
+ oend = 1;
+ break;
+ default:
+ if (olen - oind < 2)
+ goto malformed;
+ }
+ if (oend)
+ break;
+ oind += pd->d_opts[oind + 1] + 2;
+ }
+ return 0;
+ malformed:
+ VIR_WARN0(_("got lost in the options!"));
+ return -1;
+}
+
+static void
+dhcpdecode(struct virNWFilterSnoopReq *req, struct eth *pep, int len)
+{
+ struct iphdr *pip;
+ struct udphdr *pup;
+ struct dhcp *pd;
+ struct iplease ipl, *pipl;
+ int mtype, leasetime;
+
+ /* go through the protocol headers */
+ pip = (struct iphdr *) pep->eh_data;
+ len -= sizeof(*pep);
+ pup = (struct udphdr *) ((char *) pip + (pip->ihl << 2));
+ len -= pip->ihl << 2;
+ pd = (struct dhcp *) ((char *) pup + sizeof(*pup));
+ len -= sizeof(*pup);
+ if (len < 0)
+ return; /* dhcpdecode: invalid packet length */
+ if (dhcp_getopt(pd, len, &mtype, &leasetime) < 0)
+ return;
+
+ memset(&ipl, 0, sizeof(ipl));
+ ipl.ipl_ipaddr = pd->d_yiaddr;
+ ipl.ipl_server = pd->d_siaddr;
+ if (leasetime == ~0)
+ ipl.ipl_timeout = ~0;
+ else
+ ipl.ipl_timeout = time(0) + leasetime;
+ ipl.ipl_req = req;
+
+ switch (mtype) {
+ case DHCPACK:
+ ipl_add(&ipl);
+ break;
+ case DHCPDECLINE:
+ case DHCPRELEASE:
+ pipl = ipl_getbyip(req->start, ipl.ipl_ipaddr);
+ ipl_del(pipl);
+ break;
+ default:
+ break;
+ }
+}
+
+#define PBUFSIZE 576 /* >= IP/TCP/DHCP headers */
+
+static pcap_t *
+dhcpopen(const char *intf)
+{
+ pcap_t *handle;
+ struct bpf_program fp;
+ char filter[64];
+ char pcap_errbuf[PCAP_ERRBUF_SIZE];
+
+ handle = pcap_open_live(intf, PBUFSIZE, 0, POLL_INTERVAL, pcap_errbuf);
+ if (handle == NULL) {
+ virNWFilterReportError(VIR_ERR_INTERNAL_ERROR,
+ _("pcap_open_live: %s"), pcap_errbuf);
+ return 0;
+ }
+
+ sprintf(filter, "port 67 or dst port 68");
+ if (pcap_compile(handle, &fp, filter, 1, PCAP_NETMASK_UNKNOWN) != 0) {
+ virNWFilterReportError(VIR_ERR_INTERNAL_ERROR,
+ _("pcap_compile: %s"), pcap_geterr(handle));
+ return 0;
+ }
+ if (pcap_setfilter(handle, &fp) != 0) {
+ virNWFilterReportError(VIR_ERR_INTERNAL_ERROR,
+ _("pcap_setfilter: %s"), pcap_geterr(handle));
+ return 0;
+ }
+ pcap_freecode(&fp);
+ return handle;
+}
+
+static void *
+virNWFilterDHCPSnoop(void *req0)
+{
+ struct virNWFilterSnoopReq *req = req0;
+ pcap_t *handle;
+ struct pcap_pkthdr hdr;
+ struct eth *packet;
+ struct iplease *ipl;
+ int ifindex;
+
+ handle = dhcpopen(req->ifname);
+ if (!handle)
+ return 0;
+
+ ifindex = if_nametoindex(req->ifname);
+
+ while (1) {
+ if (req->die)
+ break;
+ ipl_trun(req);
+
+ packet = (struct eth *) pcap_next(handle, &hdr);
+
+ if (!packet) {
+ if (ifaceCheck(false, req->ifname, NULL, ifindex))
+ virNWFilterDHCPSnoopEnd(req->ifname);
+ continue;
+ }
+
+ dhcpdecode(req, packet, hdr.caplen);
+ }
+ /* free all leases */
+ for (ipl = req->start; ipl; ipl = req->start)
+ ipl_del(ipl);
+
+ /* free all req data */
+ VIR_FREE(req->ifname);
+ virNWFilterHashTableFree(req->vars);
+ VIR_FREE(req);
+ return 0;
+}
+
+int
+virNWFilterDHCPSnoopReq(virConnectPtr conn,
+ virNWFilterTechDriverPtr techdriver ATTRIBUTE_UNUSED,
+ enum virDomainNetType nettype ATTRIBUTE_UNUSED,
+ virNWFilterDefPtr filter ATTRIBUTE_UNUSED,
+ const char *ifname ATTRIBUTE_UNUSED,
+ virNWFilterHashTablePtr vars ATTRIBUTE_UNUSED,
+ virNWFilterDriverStatePtr driver ATTRIBUTE_UNUSED)
+{
+ struct virNWFilterSnoopReq *req;
+
+ req = virHashLookup(SnoopReqs, ifname);
+ if (req)
+ return 0;
+ if (VIR_ALLOC(req) < 0) {
+ virReportOOMError();
+ return 1;
+ }
+
+ req->conn = conn;
+ req->techdriver = techdriver;
+ req->nettype = nettype;
+ req->filter = filter;
+ req->ifname = strdup(ifname);
+ req->vars = virNWFilterHashTableCreate(0);
+ if (!req->vars) {
+ virReportOOMError();
+ return 1;
+ }
+ if (virNWFilterHashTablePutAll(vars, req->vars)) {
+ virNWFilterReportError(VIR_ERR_INTERNAL_ERROR,
+ _("virNWFilterDHCPSnoopReq: can't copy variables"
+ " on if %s"), ifname);
+ return 1;
+ }
+ req->driver = driver;
+ req->start = req->end = 0;
+
+ if (virHashAddEntry(SnoopReqs, ifname, req)) {
+ VIR_FREE(req);
+ virNWFilterReportError(VIR_ERR_INTERNAL_ERROR,
+ _("virNWFilterDHCPSnoopReq req add failed on"
+ "interface \"%s\""), ifname);
+ return 1;
+ }
+ if (pthread_create(&req->thread, NULL, virNWFilterDHCPSnoop, req) != 0) {
+ (void) virHashRemoveEntry(SnoopReqs, ifname);
+ VIR_FREE(req);
+ virNWFilterReportError(VIR_ERR_INTERNAL_ERROR,
+ _("virNWFilterDHCPSnoopReq pthread_create failed"
+ " oninterface \"%s\""), ifname);
+ return 1;
+ }
+ return 0;
+}
+
+/*
+ * freeReq - hash table free function to kill a request
+ */
+static void
+freeReq(void *req0, const void *name ATTRIBUTE_UNUSED)
+{
+ struct virNWFilterSnoopReq *req = (struct virNWFilterSnoopReq *) req0;
+
+ if (!req)
+ return;
+
+ req->die = 1;
+}
+
+int
+virNWFilterDHCPSnoopInit(void)
+{
+ if (SnoopReqs)
+ return 0;
+ SnoopReqs = virHashCreate(0, freeReq);
+ if (!SnoopReqs) {
+ virReportOOMError();
+ return -1;
+ }
+ return 0;
+}
+
+void
+virNWFilterDHCPSnoopEnd(const char *ifname)
+{
+ if (!SnoopReqs)
+ return;
+ if (ifname)
+ virHashRemoveEntry(SnoopReqs, ifname);
+ else /* free all of them */
+ virHashFree(SnoopReqs);
+}
diff --git a/src/nwfilter/nwfilter_dhcpsnoop.h b/src/nwfilter/nwfilter_dhcpsnoop.h
new file mode 100644
index 0000000..248b1a0
--- /dev/null
+++ b/src/nwfilter/nwfilter_dhcpsnoop.h
@@ -0,0 +1,36 @@
+/*
+ * nwfilter_dhcpsnoop.h: support DHCP snooping for a VM on an interface
+ *
+ * Copyright (C) 2010 IBM Corp.
+ * Copyright (C) 2010 David L Stevens
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Author: David L Stevens <dlstevens(a)us.ibm.com>
+ */
+
+#ifndef __NWFILTER_DHCPSNOOP_H
+# define __NWFILTER_DHCPSNOOP_H
+
+int virNWFilterDHCPSnoopInit(void);
+int virNWFilterDHCPSnoopReq(virConnectPtr conn,
+ virNWFilterTechDriverPtr techdriver,
+ enum virDomainNetType,
+ virNWFilterDefPtr filter,
+ const char *ifname,
+ virNWFilterHashTablePtr vars,
+ virNWFilterDriverStatePtr driver);
+void virNWFilterDHCPSnoopEnd(const char *ifname);
+#endif /* __NWFILTER_DHCPSNOOP_H */
diff --git a/src/nwfilter/nwfilter_driver.c b/src/nwfilter/nwfilter_driver.c
index 8af3f8a..2e20e59 100644
--- a/src/nwfilter/nwfilter_driver.c
+++ b/src/nwfilter/nwfilter_driver.c
@@ -39,6 +39,7 @@
#include "nwfilter_gentech_driver.h"
#include "configmake.h"
+#include "nwfilter_dhcpsnoop.h"
#include "nwfilter_learnipaddr.h"
#define VIR_FROM_THIS VIR_FROM_NWFILTER
@@ -66,6 +67,8 @@ static int
nwfilterDriverStartup(int privileged) {
char *base = NULL;
+ if (virNWFilterDHCPSnoopInit() < 0)
+ return -1;
if (virNWFilterLearnInit() < 0)
return -1;
@@ -127,6 +130,7 @@ alloc_err_exit:
conf_init_err:
virNWFilterTechDriversShutdown();
+ virNWFilterDHCPSnoopEnd(0);
virNWFilterLearnShutdown();
return -1;
@@ -201,6 +205,7 @@ nwfilterDriverShutdown(void) {
virNWFilterConfLayerShutdown();
virNWFilterTechDriversShutdown();
+ virNWFilterDHCPSnoopEnd(0);
virNWFilterLearnShutdown();
nwfilterDriverLock(driverState);
diff --git a/src/nwfilter/nwfilter_gentech_driver.c b/src/nwfilter/nwfilter_gentech_driver.c
index a459974..c6e6600 100644
--- a/src/nwfilter/nwfilter_gentech_driver.c
+++ b/src/nwfilter/nwfilter_gentech_driver.c
@@ -33,6 +33,7 @@
#include "virterror_internal.h"
#include "nwfilter_gentech_driver.h"
#include "nwfilter_ebiptables_driver.h"
+#include "nwfilter_dhcpsnoop.h"
#include "nwfilter_learnipaddr.h"
@@ -670,13 +671,12 @@ virNWFilterInstantiate(virConnectPtr conn,
virNWFilterDefPtr filter,
const char *ifname,
int ifindex,
- const char *linkdev,
+ const char *linkdev ATTRIBUTE_UNUSED,
virNWFilterHashTablePtr vars,
enum instCase useNewFilter, bool *foundNewFilter,
bool teardownOld,
- const unsigned char *macaddr,
- virNWFilterDriverStatePtr driver,
- bool forceWithPendingReq)
+ const unsigned char *macaddr ATTRIBUTE_UNUSED,
+ virNWFilterDriverStatePtr driver)
{
int rc;
int j, nptrs;
@@ -704,39 +704,38 @@ virNWFilterInstantiate(virConnectPtr conn,
if (virHashSize(missing_vars->hashTable) == 1) {
if (virHashLookup(missing_vars->hashTable,
NWFILTER_STD_VAR_IP) != NULL) {
- if (virNWFilterLookupLearnReq(ifindex) == NULL) {
- rc = virNWFilterLearnIPAddress(techdriver,
- ifname,
- ifindex,
- linkdev,
- nettype, macaddr,
- filter->name,
- vars, driver,
- DETECT_DHCP|DETECT_STATIC);
- }
+
+ rc = _virNWFilterInstantiateRec(conn,
+ techdriver,
+ nettype,
+ filter,
+ ifname,
+ vars,
+ NWFILTER_STD_VAR_IP, 1,
+ &nEntries, &insts,
+ useNewFilter, foundNewFilter,
+ driver);
+ if (!rc)
+ rc = virNWFilterDHCPSnoopReq(conn, techdriver, nettype, filter,
+ ifname, vars, driver);
+ } else
+ rc = 1;
+ if (rc)
goto err_exit;
- }
- rc = 1;
- goto err_exit;
} else if (virHashSize(missing_vars->hashTable) > 1) {
rc = 1;
goto err_exit;
- } else if (!forceWithPendingReq &&
- virNWFilterLookupLearnReq(ifindex) != NULL) {
- goto err_exit;
- }
-
- rc = _virNWFilterInstantiateRec(conn,
- techdriver,
- nettype,
- filter,
- ifname,
- vars,
- 0, 0,
- &nEntries, &insts,
- useNewFilter, foundNewFilter,
- driver);
-
+ } else
+ rc = _virNWFilterInstantiateRec(conn,
+ techdriver,
+ nettype,
+ filter,
+ ifname,
+ vars,
+ 0, 0,
+ &nEntries, &insts,
+ useNewFilter, foundNewFilter,
+ driver);
if (rc)
goto err_exit;
@@ -802,7 +801,6 @@ __virNWFilterInstantiateFilter(virConnectPtr conn,
virNWFilterHashTablePtr filterparams,
enum instCase useNewFilter,
virNWFilterDriverStatePtr driver,
- bool forceWithPendingReq,
bool *foundNewFilter)
{
int rc;
@@ -903,8 +901,7 @@ __virNWFilterInstantiateFilter(virConnectPtr conn,
useNewFilter, foundNewFilter,
teardownOld,
macaddr,
- driver,
- forceWithPendingReq);
+ driver);
virNWFilterHashTableFree(vars);
@@ -950,7 +947,6 @@ _virNWFilterInstantiateFilter(virConnectPtr conn,
net->filterparams,
useNewFilter,
conn->nwfilterPrivateData,
- false,
foundNewFilter);
virNWFilterUnlockFilterUpdates();
@@ -986,7 +982,6 @@ virNWFilterInstantiateFilterLate(virConnectPtr conn,
filterparams,
INSTANTIATE_ALWAYS,
driver,
- true,
&foundNewFilter);
if (rc) {
/* something went wrong... 'DOWN' the interface */
@@ -1098,6 +1093,8 @@ _virNWFilterTeardownFilter(const char *ifname)
return 1;
}
+ virNWFilterDHCPSnoopEnd(ifname);
+
virNWFilterTerminateLearnReq(ifname);
if (virNWFilterLockIface(ifname))
13 years, 7 months
[libvirt] [PATCH 4/9] add DHCP snooping support to nwfilter
by David L Stevens
This patch simplifies the table rules by setting the protocol chains policy to
be "DROP" and removes the explicit "-j DROP" entries that the protocol rules
had previously. It also makes "no-other-rarp-traffic.xml" obsolete.
Signed-off-by: David L Stevens <dlstevens(a)us.ibm.com>
diff --git a/examples/xml/nwfilter/Makefile.am b/examples/xml/nwfilter/Makefile.am
index 8ef9a71..60301c9 100644
--- a/examples/xml/nwfilter/Makefile.am
+++ b/examples/xml/nwfilter/Makefile.am
@@ -14,7 +14,6 @@ FILTERS = \
no-mac-broadcast.xml \
no-mac-spoofing.xml \
no-other-l2-traffic.xml \
- no-other-rarp-traffic.xml \
qemu-announce-self.xml \
qemu-announce-self-rarp.xml
diff --git a/examples/xml/nwfilter/no-arpip-spoofing.xml b/examples/xml/nwfilter/no-arpip-spoofing.xml
index ee42d40..7ef6f0f 100644
--- a/examples/xml/nwfilter/no-arpip-spoofing.xml
+++ b/examples/xml/nwfilter/no-arpip-spoofing.xml
@@ -7,6 +7,4 @@
<rule action='return' direction='out' priority='410' >
<arp match='yes' arpsrcipaddr='0.0.0.0' />
</rule>
- <!-- drop everything else -->
- <rule action='drop' direction='out' priority='1000' />
</filter>
diff --git a/examples/xml/nwfilter/no-arpmac-spoofing.xml b/examples/xml/nwfilter/no-arpmac-spoofing.xml
index 90499d3..3834047 100644
--- a/examples/xml/nwfilter/no-arpmac-spoofing.xml
+++ b/examples/xml/nwfilter/no-arpmac-spoofing.xml
@@ -2,6 +2,4 @@
<rule action='return' direction='out' priority='350' >
<arp match='yes' arpsrcmacaddr='$MAC'/>
</rule>
- <!-- drop everything else -->
- <rule action='drop' direction='out' priority='1000' />
</filter>
diff --git a/examples/xml/nwfilter/no-ip-spoofing.xml b/examples/xml/nwfilter/no-ip-spoofing.xml
index 84e8a5e..2fccd12 100644
--- a/examples/xml/nwfilter/no-ip-spoofing.xml
+++ b/examples/xml/nwfilter/no-ip-spoofing.xml
@@ -4,6 +4,4 @@
<rule action='return' direction='out'>
<ip match='yes' srcipaddr='$IP' />
</rule>
- <!-- drop any that don't match the source IP list -->
- <rule action='drop' direction='out' />
</filter>
diff --git a/examples/xml/nwfilter/no-mac-spoofing.xml b/examples/xml/nwfilter/no-mac-spoofing.xml
index aee56c7..e2e8c03 100644
--- a/examples/xml/nwfilter/no-mac-spoofing.xml
+++ b/examples/xml/nwfilter/no-mac-spoofing.xml
@@ -4,6 +4,4 @@
<rule action='return' direction='out' priority='350' >
<mac match='yes' srcmacaddr='$MAC'/>
</rule>
- <!-- drop everything else -->
- <rule action='drop' direction='out' priority='1000' />
</filter>
diff --git a/examples/xml/nwfilter/no-other-rarp-traffic.xml b/examples/xml/nwfilter/no-other-rarp-traffic.xml
deleted file mode 100644
index 7729996..0000000
--- a/examples/xml/nwfilter/no-other-rarp-traffic.xml
+++ /dev/null
@@ -1,3 +0,0 @@
-<filter name='no-other-rarp-traffic' chain='rarp'>
- <rule action='drop' direction='inout' priority='1000'/>
-</filter>
diff --git a/examples/xml/nwfilter/qemu-announce-self.xml b/examples/xml/nwfilter/qemu-announce-self.xml
index 352db50..12957b5 100644
--- a/examples/xml/nwfilter/qemu-announce-self.xml
+++ b/examples/xml/nwfilter/qemu-announce-self.xml
@@ -8,6 +8,5 @@
<!-- accept if it was changed to rarp -->
<filterref filter='qemu-announce-self-rarp'/>
- <filterref filter='no-other-rarp-traffic'/>
</filter>
diff --git a/src/nwfilter/nwfilter_ebiptables_driver.c b/src/nwfilter/nwfilter_ebiptables_driver.c
index fa6f719..dc0ad2e 100644
--- a/src/nwfilter/nwfilter_ebiptables_driver.c
+++ b/src/nwfilter/nwfilter_ebiptables_driver.c
@@ -2783,7 +2783,7 @@ ebtablesCreateTmpSubChain(virBufferPtr buf,
protostr[0] = '\0';
virBufferVSprintf(buf,
- CMD_DEF("%s -t %s -N %s") CMD_SEPARATOR
+ CMD_DEF("%s -t %s -N %s -P DROP") CMD_SEPARATOR
CMD_EXEC
"%s"
CMD_DEF("%s -t %s -A %s %s -j %s") CMD_SEPARATOR
@@ -3006,14 +3006,6 @@ ebtablesApplyBasicRules(const char *ifname,
ebtablesCreateTmpRootChain(&buf, 1, ifname, 1);
PRINT_ROOT_CHAIN(chain, chainPrefix, ifname);
- virBufferVSprintf(&buf,
- CMD_DEF("%s -t %s -A %s -s ! %s -j DROP") CMD_SEPARATOR
- CMD_EXEC
- "%s",
-
- ebtables_cmd_path, EBTABLES_DEFAULT_TABLE,
- chain, macaddr_str,
- CMD_STOPONERR(1));
virBufferVSprintf(&buf,
CMD_DEF("%s -t %s -A %s -p IPv4 -j ACCEPT") CMD_SEPARATOR
13 years, 7 months
[libvirt] [PATCH 3/9] add DHCP snooping support to nwfilter
by David L Stevens
This patch changes rules of the form:
if ! addr drop
accept
to:
if addr return
...
drop
The patch adds a "mac" chain to do a mac address list and separates the "arp"
chain into separate "arpmac" and "arpip" chains that can check multiple MAC
or IP addresses in any combination. This patch itself does not support multiple
addresses via the MAC and IP variables, but only changes the form of the rules
to allow multiple addresses in the future.
Signed-off-by: David L Stevens <dlstevens(a)us.ibm.com>
diff --git a/examples/xml/nwfilter/Makefile.am b/examples/xml/nwfilter/Makefile.am
index 439e7b8..8ef9a71 100644
--- a/examples/xml/nwfilter/Makefile.am
+++ b/examples/xml/nwfilter/Makefile.am
@@ -7,6 +7,8 @@ FILTERS = \
allow-ipv4.xml \
clean-traffic.xml \
no-arp-spoofing.xml \
+ no-arpmac-spoofing.xml \
+ no-arpip-spoofing.xml \
no-ip-multicast.xml \
no-ip-spoofing.xml \
no-mac-broadcast.xml \
diff --git a/examples/xml/nwfilter/allow-arp.xml b/examples/xml/nwfilter/allow-arp.xml
index 63a92b2..006bb54 100644
--- a/examples/xml/nwfilter/allow-arp.xml
+++ b/examples/xml/nwfilter/allow-arp.xml
@@ -1,3 +1,6 @@
-<filter name='allow-arp' chain='arp'>
+<filter name='allow-arp' chain='arpmac'>
+ <rule direction='inout' action='accept'/>
+</filter>
+<filter name='allow-arp' chain='arpip'>
<rule direction='inout' action='accept'/>
</filter>
diff --git a/examples/xml/nwfilter/clean-traffic.xml b/examples/xml/nwfilter/clean-traffic.xml
index 40f0ecb..9cee799 100644
--- a/examples/xml/nwfilter/clean-traffic.xml
+++ b/examples/xml/nwfilter/clean-traffic.xml
@@ -11,10 +11,10 @@
<!-- preventing ARP spoofing/poisoning -->
<filterref filter='no-arp-spoofing'/>
- <!-- preventing any other traffic than IPv4 and ARP -->
- <filterref filter='no-other-l2-traffic'/>
-
<!-- allow qemu to send a self-announce upon migration end -->
<filterref filter='qemu-announce-self'/>
+ <!-- preventing any other traffic than IPv4 and ARP -->
+ <filterref filter='no-other-l2-traffic'/>
+
</filter>
diff --git a/examples/xml/nwfilter/no-arp-spoofing.xml b/examples/xml/nwfilter/no-arp-spoofing.xml
index fdd4e60..1979b20 100644
--- a/examples/xml/nwfilter/no-arp-spoofing.xml
+++ b/examples/xml/nwfilter/no-arp-spoofing.xml
@@ -1,17 +1,4 @@
-<filter name='no-arp-spoofing' chain='arp'>
- <uuid>f88f1932-debf-4aa1-9fbe-f10d3aa4bc95</uuid>
- <rule action='drop' direction='out' priority='300' >
- <mac match='no' srcmacaddr='$MAC'/>
- </rule>
-
- <!-- no arp spoofing -->
- <!-- drop if ipaddr or macaddr does not belong to guest -->
- <rule action='drop' direction='out' priority='350' >
- <arp match='no' arpsrcmacaddr='$MAC'/>
- </rule>
- <rule action='drop' direction='out' priority='400' >
- <arp match='no' arpsrcipaddr='$IP' />
- </rule>
- <!-- drop everything else -->
- <rule action='drop' direction='out' priority='1000' />
+<filter name='no-arp-spoofing'>
+ <filterref filter='no-arpmac-spoofing' />
+ <filterref filter='no-arpip-spoofing' />
</filter>
diff --git a/examples/xml/nwfilter/no-arpip-spoofing.xml b/examples/xml/nwfilter/no-arpip-spoofing.xml
new file mode 100644
index 0000000..ee42d40
--- /dev/null
+++ b/examples/xml/nwfilter/no-arpip-spoofing.xml
@@ -0,0 +1,12 @@
+<filter name='no-arpip-spoofing' chain='arpip'>
+ <!-- no arp spoofing -->
+ <!-- drop if ipaddr does not belong to guest -->
+ <rule action='return' direction='out' priority='400' >
+ <arp match='yes' arpsrcipaddr='$IP' />
+ </rule>
+ <rule action='return' direction='out' priority='410' >
+ <arp match='yes' arpsrcipaddr='0.0.0.0' />
+ </rule>
+ <!-- drop everything else -->
+ <rule action='drop' direction='out' priority='1000' />
+</filter>
diff --git a/examples/xml/nwfilter/no-arpmac-spoofing.xml b/examples/xml/nwfilter/no-arpmac-spoofing.xml
new file mode 100644
index 0000000..90499d3
--- /dev/null
+++ b/examples/xml/nwfilter/no-arpmac-spoofing.xml
@@ -0,0 +1,7 @@
+<filter name='no-arpmac-spoofing' chain='arpmac'>
+ <rule action='return' direction='out' priority='350' >
+ <arp match='yes' arpsrcmacaddr='$MAC'/>
+ </rule>
+ <!-- drop everything else -->
+ <rule action='drop' direction='out' priority='1000' />
+</filter>
diff --git a/examples/xml/nwfilter/no-ip-spoofing.xml b/examples/xml/nwfilter/no-ip-spoofing.xml
index b8c94c8..84e8a5e 100644
--- a/examples/xml/nwfilter/no-ip-spoofing.xml
+++ b/examples/xml/nwfilter/no-ip-spoofing.xml
@@ -1,7 +1,9 @@
<filter name='no-ip-spoofing' chain='ipv4'>
<!-- drop if srcipaddr is not the IP address of the guest -->
- <rule action='drop' direction='out'>
- <ip match='no' srcipaddr='$IP' />
+ <rule action='return' direction='out'>
+ <ip match='yes' srcipaddr='$IP' />
</rule>
+ <!-- drop any that don't match the source IP list -->
+ <rule action='drop' direction='out' />
</filter>
diff --git a/examples/xml/nwfilter/no-mac-spoofing.xml b/examples/xml/nwfilter/no-mac-spoofing.xml
index f210623..aee56c7 100644
--- a/examples/xml/nwfilter/no-mac-spoofing.xml
+++ b/examples/xml/nwfilter/no-mac-spoofing.xml
@@ -1,5 +1,9 @@
-<filter name='no-mac-spoofing' chain='ipv4'>
- <rule action='drop' direction='out' priority='10'>
- <mac match='no' srcmacaddr='$MAC' />
- </rule>
+<filter name='no-mac-spoofing' chain='mac'>
+ <!-- no mac spoofing -->
+ <!-- drop if macaddr does not belong to guest -->
+ <rule action='return' direction='out' priority='350' >
+ <mac match='yes' srcmacaddr='$MAC'/>
+ </rule>
+ <!-- drop everything else -->
+ <rule action='drop' direction='out' priority='1000' />
</filter>
diff --git a/examples/xml/nwfilter/no-other-l2-traffic.xml b/examples/xml/nwfilter/no-other-l2-traffic.xml
index 8bad86e..0501b1a 100644
--- a/examples/xml/nwfilter/no-other-l2-traffic.xml
+++ b/examples/xml/nwfilter/no-other-l2-traffic.xml
@@ -1,7 +1,12 @@
-<filter name='no-other-l2-traffic'>
+<filter name='no-other-l2-traffic' chain='root'>
- <!-- drop all other l2 traffic than for which rules have been
- written for; i.e., drop all other than arp and ipv4 traffic -->
- <rule action='drop' direction='inout' priority='1000'/>
+ <!-- drop all other than arp and ipv4 traffic -->
+ <rule action='accept' direction='inout'>
+ <mac protocolid='0x800' />
+ </rule>
+ <rule action='accept' direction='inout'>
+ <mac protocolid='0x806' />
+ </rule>
+ <rule action='drop' direction='inout' priority='1000' />
</filter>
diff --git a/src/conf/nwfilter_conf.c b/src/conf/nwfilter_conf.c
index c5705c1..df1a012 100644
--- a/src/conf/nwfilter_conf.c
+++ b/src/conf/nwfilter_conf.c
@@ -82,7 +82,9 @@ VIR_ENUM_IMPL(virNWFilterEbtablesTable, VIR_NWFILTER_EBTABLES_TABLE_LAST,
VIR_ENUM_IMPL(virNWFilterChainSuffix, VIR_NWFILTER_CHAINSUFFIX_LAST,
"root",
- "arp",
+ "mac",
+ "arpmac",
+ "arpip",
"rarp",
"ipv4",
"ipv6");
diff --git a/src/conf/nwfilter_conf.h b/src/conf/nwfilter_conf.h
index ef60b6b..4d60751 100644
--- a/src/conf/nwfilter_conf.h
+++ b/src/conf/nwfilter_conf.h
@@ -425,7 +425,9 @@ struct _virNWFilterEntry {
enum virNWFilterChainSuffixType {
VIR_NWFILTER_CHAINSUFFIX_ROOT = 0,
- VIR_NWFILTER_CHAINSUFFIX_ARP,
+ VIR_NWFILTER_CHAINSUFFIX_MAC,
+ VIR_NWFILTER_CHAINSUFFIX_ARPMAC,
+ VIR_NWFILTER_CHAINSUFFIX_ARPIP,
VIR_NWFILTER_CHAINSUFFIX_RARP,
VIR_NWFILTER_CHAINSUFFIX_IPv4,
VIR_NWFILTER_CHAINSUFFIX_IPv6,
diff --git a/src/nwfilter/nwfilter_ebiptables_driver.c b/src/nwfilter/nwfilter_ebiptables_driver.c
index 39bd4a5..fa6f719 100644
--- a/src/nwfilter/nwfilter_ebiptables_driver.c
+++ b/src/nwfilter/nwfilter_ebiptables_driver.c
@@ -129,20 +129,24 @@ struct ushort_map {
enum l3_proto_idx {
- L3_PROTO_IPV4_IDX = 0,
- L3_PROTO_IPV6_IDX,
- L3_PROTO_ARP_IDX,
+ L3_PROTO_MAC_IDX = 0,
+ L3_PROTO_ARPMAC_IDX,
+ L3_PROTO_ARPIP_IDX,
L3_PROTO_RARP_IDX,
+ L3_PROTO_IPV4_IDX,
+ L3_PROTO_IPV6_IDX,
L3_PROTO_LAST_IDX
};
#define USHORTMAP_ENTRY_IDX(IDX, ATT, VAL) [IDX] = { .attr = ATT, .val = VAL }
static const struct ushort_map l3_protocols[] = {
- USHORTMAP_ENTRY_IDX(L3_PROTO_IPV4_IDX, ETHERTYPE_IP , "ipv4"),
- USHORTMAP_ENTRY_IDX(L3_PROTO_IPV6_IDX, ETHERTYPE_IPV6 , "ipv6"),
- USHORTMAP_ENTRY_IDX(L3_PROTO_ARP_IDX , ETHERTYPE_ARP , "arp"),
- USHORTMAP_ENTRY_IDX(L3_PROTO_RARP_IDX, ETHERTYPE_REVARP, "rarp"),
+ USHORTMAP_ENTRY_IDX(L3_PROTO_MAC_IDX, 0 , "mac"),
+ USHORTMAP_ENTRY_IDX(L3_PROTO_IPV4_IDX, ETHERTYPE_IP , "ipv4"),
+ USHORTMAP_ENTRY_IDX(L3_PROTO_IPV6_IDX, ETHERTYPE_IPV6 , "ipv6"),
+ USHORTMAP_ENTRY_IDX(L3_PROTO_ARPMAC_IDX,ETHERTYPE_ARP , "arpmac"),
+ USHORTMAP_ENTRY_IDX(L3_PROTO_ARPIP_IDX, ETHERTYPE_ARP , "arpip"),
+ USHORTMAP_ENTRY_IDX(L3_PROTO_RARP_IDX, ETHERTYPE_REVARP, "rarp"),
USHORTMAP_ENTRY_IDX(L3_PROTO_LAST_IDX, 0 , NULL),
};
@@ -1946,7 +1950,7 @@ ebtablesCreateRuleInstance(char chainPrefix,
virBufferVSprintf(&buf, " -p 0x%x",
(rule->prtclType == VIR_NWFILTER_RULE_PROTOCOL_ARP)
- ? l3_protocols[L3_PROTO_ARP_IDX].attr
+ ? l3_protocols[L3_PROTO_ARPMAC_IDX].attr
: l3_protocols[L3_PROTO_RARP_IDX].attr);
if (HAS_ENTRY_ITEM(&rule->p.arpHdrFilter.dataHWType)) {
@@ -2767,15 +2771,22 @@ ebtablesCreateTmpSubChain(virBufferPtr buf,
char rootchain[MAX_CHAINNAME_LENGTH], chain[MAX_CHAINNAME_LENGTH];
char chainPrefix = (incoming) ? CHAINPREFIX_HOST_IN_TEMP
: CHAINPREFIX_HOST_OUT_TEMP;
+ char protostr[16];
PRINT_ROOT_CHAIN(rootchain, chainPrefix, ifname);
PRINT_CHAIN(chain, chainPrefix, ifname, l3_protocols[protoidx].val);
+ if (l3_protocols[protoidx].attr)
+ snprintf(protostr, sizeof(protostr), "-p 0x%04x ",
+ l3_protocols[protoidx].attr);
+ else
+ protostr[0] = '\0';
+
virBufferVSprintf(buf,
CMD_DEF("%s -t %s -N %s") CMD_SEPARATOR
CMD_EXEC
"%s"
- CMD_DEF("%s -t %s -A %s -p 0x%x -j %s") CMD_SEPARATOR
+ CMD_DEF("%s -t %s -A %s %s -j %s") CMD_SEPARATOR
CMD_EXEC
"%s",
@@ -2784,7 +2795,7 @@ ebtablesCreateTmpSubChain(virBufferPtr buf,
CMD_STOPONERR(stopOnError),
ebtables_cmd_path, EBTABLES_DEFAULT_TABLE,
- rootchain, l3_protocols[protoidx].attr, chain,
+ rootchain, protostr, chain,
CMD_STOPONERR(stopOnError));
@@ -3357,6 +3368,11 @@ ebiptablesApplyNewRules(virConnectPtr conn ATTRIBUTE_UNUSED,
if (chains_out != 0)
ebtablesCreateTmpRootChain(&buf, 0, ifname, 1);
+ if (chains_in & (1 << VIR_NWFILTER_CHAINSUFFIX_MAC))
+ ebtablesCreateTmpSubChain(&buf, 1, ifname, L3_PROTO_MAC_IDX, 1);
+ if (chains_out & (1 << VIR_NWFILTER_CHAINSUFFIX_MAC))
+ ebtablesCreateTmpSubChain(&buf, 0, ifname, L3_PROTO_MAC_IDX, 1);
+
if (chains_in & (1 << VIR_NWFILTER_CHAINSUFFIX_IPv4))
ebtablesCreateTmpSubChain(&buf, 1, ifname, L3_PROTO_IPV4_IDX, 1);
if (chains_out & (1 << VIR_NWFILTER_CHAINSUFFIX_IPv4))
@@ -3368,10 +3384,14 @@ ebiptablesApplyNewRules(virConnectPtr conn ATTRIBUTE_UNUSED,
ebtablesCreateTmpSubChain(&buf, 0, ifname, L3_PROTO_IPV6_IDX, 1);
/* keep arp,rarp as last */
- if (chains_in & (1 << VIR_NWFILTER_CHAINSUFFIX_ARP))
- ebtablesCreateTmpSubChain(&buf, 1, ifname, L3_PROTO_ARP_IDX, 1);
- if (chains_out & (1 << VIR_NWFILTER_CHAINSUFFIX_ARP))
- ebtablesCreateTmpSubChain(&buf, 0, ifname, L3_PROTO_ARP_IDX, 1);
+ if (chains_in & (1 << VIR_NWFILTER_CHAINSUFFIX_ARPMAC))
+ ebtablesCreateTmpSubChain(&buf, 1, ifname, L3_PROTO_ARPMAC_IDX, 1);
+ if (chains_in & (1 << VIR_NWFILTER_CHAINSUFFIX_ARPIP))
+ ebtablesCreateTmpSubChain(&buf, 1, ifname, L3_PROTO_ARPIP_IDX, 1);
+ if (chains_out & (1 << VIR_NWFILTER_CHAINSUFFIX_ARPMAC))
+ ebtablesCreateTmpSubChain(&buf, 0, ifname, L3_PROTO_ARPMAC_IDX, 1);
+ if (chains_out & (1 << VIR_NWFILTER_CHAINSUFFIX_ARPIP))
+ ebtablesCreateTmpSubChain(&buf, 0, ifname, L3_PROTO_ARPIP_IDX, 1);
if (chains_in & (1 << VIR_NWFILTER_CHAINSUFFIX_RARP))
ebtablesCreateTmpSubChain(&buf, 1, ifname, L3_PROTO_RARP_IDX, 1);
if (chains_out & (1 << VIR_NWFILTER_CHAINSUFFIX_RARP))
13 years, 7 months
[libvirt] [PATCH 0/9] add DHCP snooping support to nwfilter
by David L Stevens
The following series of patches replaces IP address learning in
network filtering with DHCP snooping. The existing address learning capability
does not provide security since it relies on addresses used in initial packets
sent by the guest to determine an IP address. A spoofing guest can simply
arrange to send packets using the target address early on.
With DHCP snooping, only addresses acknowledged by a DHCP server can
be used by the guest, and only for the given lease time if the address lease
is not renewed.
The patches also add support for multiple IP addresses per interface.
The split:
p1 -add return & continue support
Add support for "return" and "continue" in filters.
p2 -fix ARP input checks
Fix a bug that breaks correct use of ARP by overfiltering.
p3 -add MAC check; split ARP intp ARPMAC and ARPIP
Support for multiple IP addresses in ARP checks, and allow for
multiple MAC addresses in the future.
p4 -set default protocol policy to "DROP"; edit filters
Change default protocol policy to "DROP", rather than adding explicit
"DROP" rules at the end of all of them. This is for multiple address
support.
p5 -optional "modify" (don't use temp, generate placeholder rules)
Add support to dynamically add and remove filters without re-installing
an entire chain.
p6 -addRules
Add support for adding new rules to a chain incrementally. Remove
support was already there.
p7 -ChangeVar support
Add support to change chains that have a matching variable substitution
to either add or delete rules with the given variable value (e.g., "IP")
p8 -add DHCP snooping
The DHCP snooping code itself.
p9 -delete learnipaddr
Clean up remaining learnipaddr infrastructure.
13 years, 7 months
[libvirt] [PATCH 1/2] build: remove some dead assignments
by Eric Blake
No syntactic effect; this merely silences some clang warnings.
* src/libxl/libxl_driver.c (libxlDomainSetVcpusFlags): Drop
redundant ret=0 statement.
* src/qemu/qemu_monitor_text.c (qemuMonitorTextDriveDel):
Likewise.
---
More clang fallout, found by switching over to rawhide.
src/libxl/libxl_driver.c | 1 -
src/qemu/qemu_monitor_text.c | 1 -
2 files changed, 0 insertions(+), 2 deletions(-)
diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c
index dec4f43..5355b57 100644
--- a/src/libxl/libxl_driver.c
+++ b/src/libxl/libxl_driver.c
@@ -1659,7 +1659,6 @@ libxlDomainSetVcpusFlags(virDomainPtr dom, unsigned int nvcpus,
def->maxvcpus = nvcpus;
if (nvcpus < def->vcpus)
def->vcpus = nvcpus;
- ret = 0;
break;
case VIR_DOMAIN_VCPU_CONFIG:
diff --git a/src/qemu/qemu_monitor_text.c b/src/qemu/qemu_monitor_text.c
index 53781c8..7ace95f 100644
--- a/src/qemu/qemu_monitor_text.c
+++ b/src/qemu/qemu_monitor_text.c
@@ -2396,7 +2396,6 @@ int qemuMonitorTextDriveDel(qemuMonitorPtr mon,
} else if (STRPREFIX(reply, "Device '") && (strstr(reply, "not found"))) {
/* NB: device not found errors mean the drive was auto-deleted and we
* ignore the error */
- ret = 0;
} else if (STRNEQ(reply, "")) {
qemuReportError(VIR_ERR_OPERATION_FAILED,
_("deleting %s drive failed: %s"), drivestr, reply);
--
1.7.4.4
13 years, 7 months
[libvirt] [PATCH] maint: avoid double-close bug in gnulib
by Eric Blake
Regression introduced in commit 9d8e01a1d.
* .gnulib: Update to latest, for fclose fix.
---
Solves the issue raised here:
https://www.redhat.com/archives/libvir-list/2011-May/msg00580.html
* .gnulib a6676cc...112b21e (19):
> fclose: avoid double close race when possible
> openat: correct new comment
> openat: add comments
> openat: reduce syscalls in first probe of /proc
> autoupdate
> maint.mk: change semantics/name of tight_scope variables
> maint.mk: fix oops
> maint.mk: tweak new rule's name not to impinge
> maint.mk: add a syntax-check rule to ensure tightly-scoped symbols
> gc: Remove gl_PREREQ_GC (not used).
> Comments.
> glob: Remove obsolete macro.
> intprops: Sun C 5.11 supports __typeof__
> intprops: switch to usual gnulib indenting and naming
> maint.mk: suppress "Entering/Leaving directory" diag in announcement
> tzset: Fix gettimeofday wrapper on Solaris 2.6.
> ignore-value, verify: Omit include files from lib_SOURCES.
> fclose: Simplify autoconf macro.
> canonicalize-lgpl: Fix autoconf macro ordering bug.
.gnulib | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/.gnulib b/.gnulib
index a6676cc..112b21e 160000
--- a/.gnulib
+++ b/.gnulib
@@ -1 +1 @@
-Subproject commit a6676cca6498ce67c5a3c8d7221b8d6c30b61dc4
+Subproject commit 112b21e3861a4887731b61888d1388127957ba93
--
1.7.4.4
13 years, 7 months
[libvirt] [PATCH] tests: avoid crash when run under gcov
by Eric Blake
Running ./autobuild.sh failed when gcov is installed, because
commandtest ended up crashing during gcov's getenv() call after
exit() had already started. I traced this nasty bug back to
a scoping issue present since the test introduction.
* tests/commandtest.c (mymain): Move newenv...
(newenv): ...to a scope that is still useful during exit().
---
Pushing under the build-breaker rule.
tests/commandtest.c | 25 ++++++++++++++-----------
1 files changed, 14 insertions(+), 11 deletions(-)
diff --git a/tests/commandtest.c b/tests/commandtest.c
index caad698..429a026 100644
--- a/tests/commandtest.c
+++ b/tests/commandtest.c
@@ -748,6 +748,18 @@ cleanup:
return ret;
}
+static const char *const newenv[] = {
+ "PATH=/usr/bin:/bin",
+ "HOSTNAME=test",
+ "LANG=C",
+ "HOME=/home/test",
+ "USER=test",
+ "LOGNAME=test"
+ "TMPDIR=/tmp",
+ "DISPLAY=:0.0",
+ NULL
+};
+
static int
mymain(void)
{
@@ -771,18 +783,9 @@ mymain(void)
virInitialize();
- const char *const newenv[] = {
- "PATH=/usr/bin:/bin",
- "HOSTNAME=test",
- "LANG=C",
- "HOME=/home/test",
- "USER=test",
- "LOGNAME=test"
- "TMPDIR=/tmp",
- "DISPLAY=:0.0",
- NULL
- };
environ = (char **)newenv;
# define DO_TEST(NAME) \
if (virtTestRun("Command Exec " #NAME " test", \
--
1.7.4.4
13 years, 7 months
[libvirt] CfP 6th Workshop on Virtualization in High-Performance Cloud Computing (VHPC'11) - Deadline Extension
by VHPC 11
Due to several requests, the deadline has been extended to the 20th of
June.
--
=================================================================
CALL FOR PAPERS
6th Workshop on
Virtualization in High-Performance Cloud Computing
VHPC'11
as part of Euro-Par 2011, Bordeaux, France
=================================================================
Date: August 30, 2011
Euro-Par 2011: http://europar2011.bordeaux.inria.fr/
Workshop URL: http://vhpc.org
SUBMISSION DEADLINE:
Full Paper: June 20, 2011 (extended)
Scope:
Virtualization has become a common abstraction layer in modern data
centers, enabling resource owners to manage complex infrastructure
independently of their applications. Conjointly virtualization is
becoming a driving technology for a manifold of industry grade IT
services. The cloud concept includes the notion of a separation
between resource owners and users, adding services such as hosted
application frameworks and queuing. Utilizing the same infrastructure,
clouds carry significant potential for use in high-performance
scientific computing. The ability of clouds to provide for
requests and releases of vast computing resource dynamically and
close to the marginal cost of providing the services is unprecedented
in the history of scientific and commercial computing.
Distributed computing concepts that leverage federated resource access
are popular within the grid community, but have not seen previously
desired deployed levels so far. Also, many of the scientific
datacenters have not adopted virtualization or cloud concepts yet.
This workshop aims to bring together industrial providers with the
scientific community in order to foster discussion, collaboration and
mutual exchange of knowledge and experience.
The workshop will be one day in length, composed of 20 min paper
presentations, each followed by 10 min discussion sections.
Presentations may be accompanied by interactive demonstrations. It
concludes with a 30 min panel discussion by presenters.
TOPICS
Topics include, but are not limited to, the following subjects:
- Virtualization in cloud, cluster and grid environments
- VM-based cloud performance modeling
- Workload characterizations for VM-based environments
- Software as a Service (SaaS)
- Cloud reliability, fault-tolerance, and security
- Cloud, cluster and grid filesystems
- QoS and and service levels
- Cross-layer VM optimizations
- Virtualized I/O and storage
- Virtualization and HPC architectures including NUMA
- System and process/bytecode VM convergence
- Paravirtualized driver development
- Research and education use cases
- VM cloud, cluster distribution algorithms
- MPI on virtual machines and clouds
- Cloud frameworks and API sets
- Checkpointing of large compute jobs
- Cloud load balancing
- Accelerator virtualization
- Instrumentation interfaces and languages
- Hardware support for virtualization
- High-performance network virtualization
- Auto-tuning of VMM and VM parameters
- High-speed interconnects
- Hypervisor extensions and tools for cluster and grid computing
- VMMs/Hypervisors
- Cloud use cases including optimizations
- Performance modeling
- Fault tolerant VM environments
- VMM performance tuning on various load types
- Cloud provisioning
- Virtual machine monitor platforms
- Pass-through VM device access
- Management, deployment of VM-based environments
PAPER SUBMISSION
Papers submitted to the workshop will be reviewed by at least two
members of the program committee and external reviewers. Submissions
should include abstract, key words, the e-mail address of the
corresponding author, and must not exceed 10 pages, including tables
and figures at a main font size no smaller than 11 point. Submission
of a paper should be regarded as a commitment that, should the paper
be accepted, at least one of the authors will register and attend the
conference to present the work.
Accepted papers will be published in the Springer LNCS series - the
format must be according to the Springer LNCS Style. Initial
submissions are in PDF, accepted papers will be requested to provided
source files.
Format Guidelines: http://www.springer.de/comp/lncs/authors.html
Submission Link: http://edas.info/newPaper.php?c=10155
IMPORTANT DATES
June 20 2011 - Full paper submission (extended)
July 15 2011 - Acceptance notification
August 3 2011 - Camera-ready version due
August 30 2011 - September 2 - conference
CHAIR
Michael Alexander (chair), IBM, Austria
Gianluigi Zanetti (co-chair), CRS4, Italy
PROGRAM COMMITTEE
Paolo Anedda, CRS4, Italy
Volker Buege, University of Karlsruhe, Germany
Giovanni Busonera, CRS4, Italy
Roberto Canonico, University of Napoli, Italy
Tommaso Cucinotta, Scuola Superiore Sant'Anna, Italy
William Gardner, University of Guelph, Canada
Werner Fischer, Thomas-Krenn AG, Germany
Wolfgang Gentzsch, Max Planck Gesellschaft, Germany
Marcus Hardt, Forschungszentrum Karlsruhe, Germany
Sverre Jarp, CERN, Switzerland
Shantenu Sjha, Louisiana State University, USA
Xuxian Jiang, NC State, USA
Kenji Kaneda, Google, USA
Simone Leo, CRS4, Italy
Ignancio Llorente, Universidad Complutense de Madrid, Spain,
Naoya Maruyama, Tokyo Institute of Technology, Japan
Jean-Marc Menaud, Ecole des Mines de Nantes, France
Anastassios Nanos, National Technical University of Athens, Greece
Jose Renato Santos, HP Labs, USA
Deepak Singh, Amazon Webservices, USA
Boria Sotomayor, University of Chicago, USA
Yoshio Turner, HP Labs, USA
Kurt Tutschku, University of Vienna, Austria
Lizhe Wang, Indiana University, USA
Chao-Tung Yang, Tunghai University, China
DURATION: Workshop Duration is one day.
GENERAL INFORMATION
The workshop will be held as part of Euro-Par 2011,
organized by INRIA, CNRS and the University of Bordeaux I, II, France.
Euro-Par 2011: http://europar2011.bordeaux.inria.fr/
13 years, 7 months
[libvirt] [PATCH 0/2] More graceful handing of monitor failures
by Daniel P. Berrange
Currently when libvirt has a serious error doing I/O and/or parsing
of the QEMU monitor, it will kill off the guest. Application developers
have expressed a desire for more graceful handling of this scenario.
In particular to allow the guest OS to continue to run, without any
further monitor interactons, and then kill/restart it at a time which
is convenient to the guest admin/apps.
This is a proof of concept of that.
13 years, 7 months