Some interfaces, such as tap, can set a filter to prevent unwanted packets from interrupting qemu. This patch adds infrastructure for vlan clients to request a set of filtering parameters. The main client interface for this is the new qemu_vlan_rxfilter() function. For simplicity, we restrict the topology that can make use of a filter to exactly two clients on a vlan. To handle hotplug devices, we add vlan_client_added/removed notifiers which can automatically revert back to a shared media protocol. Devices providing filtering can do so via the new fd_rxfilter() interface. Signed-off-by: Alex Williamson <alex.williamson@xxxxxx> --- net.c | 43 ++++++++++++++++++++++++++++++++++++++++++- net.h | 14 ++++++++++++++ 2 files changed, 56 insertions(+), 1 deletions(-) diff --git a/net.c b/net.c index e7c097e..e68cb40 100644 --- a/net.c +++ b/net.c @@ -345,8 +345,11 @@ VLANClientState *qemu_new_vlan_client(VLANState *vlan, vc->next = NULL; pvc = &vlan->first_client; - while (*pvc != NULL) + while (*pvc != NULL) { + if ((*pvc)->vlan_client_added) + (*pvc)->vlan_client_added((*pvc)->opaque); pvc = &(*pvc)->next; + } *pvc = vc; return vc; } @@ -364,6 +367,12 @@ void qemu_del_vlan_client(VLANClientState *vc) break; } else pvc = &(*pvc)->next; + + /* Notify other clients after removal for dependencies on new topology */ + pvc = &vc->vlan->first_client; + while (*pvc != NULL) + if ((*pvc)->vlan_client_removed) + (*pvc)->vlan_client_removed((*pvc)->opaque); } int qemu_can_send_packet(VLANClientState *vc1) @@ -458,6 +467,38 @@ ssize_t qemu_sendv_packet(VLANClientState *vc1, const struct iovec *iov, return max_len; } +/* + * This function allows a qemu vlan client to request filtering on + * it's receiving interface. We only use this for the typical case + * of having exactly two clients on the vlan. Clients making use + * of this function should also implement a vlan_client_added() + * function to be notified when they need to fall back to their own + * filtering or disable filtering setup for a single consumer. + * + * A return value of 1 indicates the entire requested filter set + * is handled by the provided filter. + */ +int qemu_vlan_rxfilter(VLANClientState *vc1, int flags, int count, + uint8_t *buf) +{ + VLANState *vlan = vc1->vlan; + VLANClientState *vc; + + if (vlan->first_client == NULL || vlan->first_client->next == NULL || + vlan->first_client->next->next != NULL) + return 0; + + if (vlan->first_client == vc1) + vc = vc1->next; + else + vc = vlan->first_client; + + if (vc->fd_rxfilter) + return (vc->fd_rxfilter(vc->opaque, flags, count, buf) == count); + + return 0; +} + #if defined(CONFIG_SLIRP) /* slirp network adapter */ diff --git a/net.h b/net.h index 291807a..2090111 100644 --- a/net.h +++ b/net.h @@ -11,13 +11,22 @@ typedef struct VLANClientState VLANClientState; typedef void (LinkStatusChanged)(VLANClientState *); +typedef int (IORXFilter)(void *, unsigned int , int , uint8_t *); + +typedef void (VLANClientAdded)(void *); + +typedef void (VLANClientRemoved)(void *); + struct VLANClientState { IOReadHandler *fd_read; IOReadvHandler *fd_readv; /* Packets may still be sent if this returns zero. It's used to rate-limit the slirp code. */ IOCanRWHandler *fd_can_read; + IORXFilter *fd_rxfilter; LinkStatusChanged *link_status_changed; + VLANClientAdded *vlan_client_added; + VLANClientRemoved *vlan_client_removed; int link_down; void *opaque; struct VLANClientState *next; @@ -51,10 +60,15 @@ void qemu_check_nic_model(NICInfo *nd, const char *model); void qemu_check_nic_model_list(NICInfo *nd, const char * const *models, const char *default_model); void qemu_handler_true(void *opaque); +int qemu_vlan_rxfilter(VLANClientState *vc1, int flags, int count, + uint8_t *buf); void do_info_network(void); int do_set_link(const char *name, const char *up_or_down); +#define QEMU_NET_PROMISC 1 +#define QEMU_NET_ALLMULTI 2 + /* NIC info */ #define MAX_NICS 8 -- To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html