[net-next-2.6 PATCH 0/8 RFC v2] macvlan: MAC Address filtering support for passthru mode

STALE5410d

25 messages, 4 authors, 2011-11-17 · open the first message on its own page

[net-next-2.6 PATCH 0/8 RFC v2] macvlan: MAC Address filtering support for passthru mode

From: Roopa Prabhu <hidden>
Date: 2011-10-19 06:25:54

v1 version of this RFC patch was posted at http://www.spinics.net/lists/netdev/msg174245.html

Today macvtap used in virtualized environment does not have support to 
propagate MAC, VLAN and interface flags from guest to lowerdev.
Which means to be able to register additional VLANs, unicast and multicast
addresses or change pkt filter flags in the guest, the lowerdev has to be
put in promisocous mode. Today the only macvlan mode that supports this is 
the PASSTHRU mode and it puts the lower dev in promiscous mode.

PASSTHRU mode was added primarily for the SRIOV usecase. In PASSTHRU mode 
there is a 1-1 mapping between macvtap and physical NIC or VF.

There are two problems with putting the lowerdev in promiscous mode (ie SRIOV 
VF's):
	- Some SRIOV cards dont support promiscous mode today (Thread on Intel
	driver indicates that http://lists.openwall.net/netdev/2011/09/27/6)
	- For the SRIOV NICs that support it, Putting the lowerdev in 
	promiscous mode leads to additional traffic being sent up to the 
	guest virtio-net to filter result in extra overheads.
	
Both the above problems can be solved by offloading filtering to the 
lowerdev hw. ie lowerdev does not need to be in promiscous mode as 
long as the guest filters are passed down to the lowerdev. 

This patch basically adds the infrastructure to set and get MAC and VLAN 
filters on an interface via rtnetlink. And adds support in macvlan and macvtap
to allow set and get filter operations.

Earlier version of this patch provided the TUNSETTXFILTER macvtap interface 
for setting address filtering. In response to feedback, This version 
introduces a netlink interface for the same.

Response to some of the questions raised during v1:

- Netlink interface:
	This patch provides the following netlink interface to set mac and vlan
	filters :
	[IFLA_RX_FILTER] = {
		[IFLA_ADDR_FILTER] = {
			[IFLA_ADDR_FILTER_FLAGS]
			[IFLA_ADDR_FILTER_UC_LIST] = {
				[IFLA_ADDR_LIST_ENTRY]
			}
			[IFLA_ADDR_FILTER_MC_LIST] = {
				[IFLA_ADDR_LIST_ENTRY]
			}
		}
		[IFLA_VLAN_FILTER] = {
			[IFLA_VLAN_BITMAP]
		}
	}

	Note: The IFLA_VLAN_FILTER is a nested attribute and contains only 
	IFLA_VLAN_BITMAP today. The idea is that the IFLA_VLAN_FILTER can
	be extended tomorrow to use a vlan list option if some implementations 
	prefer a list instead. 

	And it provides the following rtnl_link_ops to set/get MAC/VLAN filters:

       int                     (*set_rx_addr_filter)(struct net_device *dev,
                                               struct nlattr *tb[]);
       int                     (*set_rx_vlan_filter)(struct net_device *dev,
                                                struct nlattr *tb[]);
       size_t                  (*get_rx_addr_filter_size)(const struct 
					net_device *dev);
       size_t                  (*get_rx_vlan_filter_size)(const struct 
					net_device *dev);
       int                     (*fill_rx_addr_filter)(struct sk_buff *skb,
                                                const struct net_device *dev);
       int                     (*fill_rx_vlan_filter)(struct sk_buff *skb,
                                                const struct net_device *dev);


	Note: The choice of rtnl_link_ops was because I saw the use case for 
	this in virtual devices that need  to do filtering in sw like macvlan 
	and tun. Hw devices usually have filtering in hw with netdev->uc and 
	mc lists to indicate active filters. But I can move from rtnl_link_ops 
	to netdev_ops if that is the preferred way to go and if there is a 
	need to support this interface on all kinds of interfaces. 
	Please suggest.
	
- Protection against address spoofing:
	- This patch adds filtering support only for macvtap PASSTHRU 
	Mode. PASSTHRU mode is used mainly with SRIOV VF's. And SRIOV VF's 
	come with anti mac/vlan spoofing support. (Recently added 
	IFLA_VF_SPOOFCHK). In 802.1Qbh case the port profile has a knob to
	enable/disable anti spoof check. Lowerdevice drivers also enforce limits
	on the number of address registrations allowed.

- Support for multiqueue devices: Enable filtering on individual queues (?):
	AFAIK, there is no netdev interface to install per queue hw 
	filters for a multi queue interface. And also I dont know of any hw 
	that provides an interface to set hw filters on a per queue basis.
	A multi queue device appears as a single lowerdev (ie netdev) and
	uses the same uc and mc lists to setup unicast and multicast hw filters.
	So i dont see a huge problem with this patch coming in the way for
	multi queue devices.

- Support for non-PASSTHRU mode:
	I started implementing this. But there are a couple of problems.	
	- The lowerdev may not be a SRIOV VF and may not have 
	anti spoof capability
	- Today, in non-PASSTHRU cases macvlan_handle_frame assumes that 
	every macvlan device on top of the lowerdev has a single unique mac.
	And the macvlans are hashed on that single mac address. 
	To support filtering for non-PASSTHRU mode in addition to this 
	patch the following needs to be done:
		- non-passthru mode with a single macvlan over a lower dev
		can be treated as PASSTHRU case
		- For non-PASSTHRU mode with multiple macvlans over a single 
		lower dev:  
			- Multiple unicast mac's now need to be hashed to the 
			same macvlan device. The macvlan hash needs to change 
			for lookup based on any one of the multiple unicast 
			addresses a macvlan is interested in
			- We need to consider vlans during the lookup too
			- So the macvlan device hash needs to hash on both mac 
			and vlan
		- But the support for filtering in non-PASSTHRU mode can be 
		built on this patch

This patch series implements the following 
01/8 rtnetlink: Netlink interface for setting MAC and VLAN filters
02/8 rtnetlink: Add rtnl link operations for MAC address and VLAN filtering
03/8 rtnetlink: Add support to set MAC/VLAN filters
04/8 rtnetlink: Add support to get MAC/VLAN filters
05/8 macvlan: Add support to set MAC/VLAN filter rtnl link operations
06/8 macvlan: Add support to get MAC/VLAN filter rtnl link operations
07/8 macvtap: Add support to set MAC/VLAN filter rtnl link operations
08/8 macvtap: Add support to get MAC/VLAN filter rtnl link operations

Please comment. Thanks.

Signed-off-by: Roopa Prabhu <redacted>
Signed-off-by: Christian Benvenuti <redacted>
Signed-off-by: David Wang <redacted>

[net-next-2.6 PATCH 1/8 RFC v2] rtnetlink: Netlink interface for setting MAC and VLAN filters

From: Roopa Prabhu <hidden>
Date: 2011-10-19 06:25:59

From: Roopa Prabhu <redacted>

This patch introduces the following netlink interface to set
MAC and VLAN filters on an network interface

[IFLA_RX_FILTER] = {
                [IFLA_ADDR_FILTER] = {
                        [IFLA_ADDR_FILTER_FLAGS]
                        [IFLA_ADDR_FILTER_UC_LIST] = {
                                [IFLA_ADDR_LIST_ENTRY]
                        }
                        [IFLA_ADDR_FILTER_MC_LIST] = {
                                [IFLA_ADDR_LIST_ENTRY]
                        }
                }
                [IFLA_VLAN_FILTER] = {
                        [IFLA_VLAN_BITMAP]
                }
}

Signed-off-by: Roopa Prabhu <redacted>
Signed-off-by: Christian Benvenuti <redacted>
Signed-off-by: David Wang <redacted>
---
 include/linux/if_link.h |   39 +++++++++++++++++++++++++++++++++++++++
 net/core/rtnetlink.c    |   18 ++++++++++++++++++
 2 files changed, 57 insertions(+), 0 deletions(-)

diff --git a/include/linux/if_link.h b/include/linux/if_link.h
index c52d4b5..41dbcbe 100644
--- a/include/linux/if_link.h
+++ b/include/linux/if_link.h
@@ -137,6 +137,7 @@ enum {
 	IFLA_AF_SPEC,
 	IFLA_GROUP,		/* Group the device belongs to */
 	IFLA_NET_NS_FD,
+	IFLA_RX_FILTER,
 	__IFLA_MAX
 };
 
@@ -390,4 +391,42 @@ struct ifla_port_vsi {
 	__u8 pad[3];
 };
 
+/* Addr filters */
+enum {
+	IFLA_RX_FILTER_UNSPEC,
+	IFLA_RX_ADDR_FILTER,
+	IFLA_RX_VLAN_FILTER,
+	__IFLA_RX_FILTER_MAX,
+};
+#define IFLA_RX_FILTER_MAX (__IFLA_RX_FILTER_MAX - 1)
+
+enum {
+	IFLA_ADDR_FILTER_UNSPEC,
+	IFLA_ADDR_FILTER_FLAGS,
+	IFLA_ADDR_FILTER_UC_LIST,
+	IFLA_ADDR_FILTER_MC_LIST,
+	__IFLA_ADDR_FILTER_MAX,
+};
+#define IFLA_ADDR_FILTER_MAX (__IFLA_ADDR_FILTER_MAX - 1)
+
+#define RX_FILTER_FLAGS (IFF_UP | IFF_BROADCAST | IFF_MULTICAST | \
+				IFF_PROMISC | IFF_ALLMULTI)
+
+enum {
+	IFLA_ADDR_LIST_UNSPEC,
+	IFLA_ADDR_LIST_ENTRY,
+	__IFLA_ADDR_LIST_MAX,
+};
+#define IFLA_ADDR_LIST_MAX (__IFLA_ADDR_LIST_MAX - 1)
+
+enum {
+	IFLA_VLAN_FILTER_UNSPEC,
+	IFLA_VLAN_BITMAP,
+	__IFLA_VLAN_FILTER_MAX,
+};
+#define IFLA_VLAN_FILTER_MAX (__IFLA_VLAN_FILTER_MAX - 1)
+
+#define VLAN_BITMAP_SPLIT_MAX 8
+#define VLAN_BITMAP_SIZE	(VLAN_N_VID/VLAN_BITMAP_SPLIT_MAX)
+
 #endif /* _LINUX_IF_LINK_H */
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index 9083e82..a3b213f 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -42,6 +42,7 @@
 
 #include <linux/inet.h>
 #include <linux/netdevice.h>
+#include <linux/if_vlan.h>
 #include <net/ip.h>
 #include <net/protocol.h>
 #include <net/arp.h>
@@ -1097,9 +1098,26 @@ const struct nla_policy ifla_policy[IFLA_MAX+1] = {
 	[IFLA_VF_PORTS]		= { .type = NLA_NESTED },
 	[IFLA_PORT_SELF]	= { .type = NLA_NESTED },
 	[IFLA_AF_SPEC]		= { .type = NLA_NESTED },
+	[IFLA_RX_FILTER]	= { .type = NLA_NESTED },
 };
 EXPORT_SYMBOL(ifla_policy);
 
+static const struct nla_policy ifla_rx_filter_policy[IFLA_RX_FILTER_MAX+1] = {
+	[IFLA_RX_ADDR_FILTER]	= { .type = NLA_NESTED },
+	[IFLA_RX_VLAN_FILTER]	 = { .type = NLA_NESTED },
+};
+
+static const struct nla_policy ifla_addr_filter_policy[IFLA_ADDR_FILTER_MAX+1] = {
+	[IFLA_ADDR_FILTER_FLAGS] = { .type = NLA_U32 },
+	[IFLA_ADDR_FILTER_UC_LIST] = { .type = NLA_NESTED },
+	[IFLA_ADDR_FILTER_MC_LIST] = { .type = NLA_NESTED },
+};
+
+static const struct nla_policy ifla_vlan_filter_policy[IFLA_VLAN_FILTER_MAX+1] = {
+	[IFLA_VLAN_BITMAP]	 = { .type = NLA_BINARY,
+				     .len = VLAN_BITMAP_SIZE },
+};
+
 static const struct nla_policy ifla_info_policy[IFLA_INFO_MAX+1] = {
 	[IFLA_INFO_KIND]	= { .type = NLA_STRING },
 	[IFLA_INFO_DATA]	= { .type = NLA_NESTED },

[net-next-2.6 PATCH 2/8 RFC v2] rtnetlink: Add rtnl link operations for MAC address and VLAN filtering

From: Roopa Prabhu <hidden>
Date: 2011-10-19 06:26:04

From: Roopa Prabhu <redacted>

This patch adds the following rtnl_link_ops to set and get MAC and VLAN
filters

set_rx_addr_filter - to set address filter
set_rx_vlan_filter - To set vlan filter
get_rx_addr_filter_size - To get address filter size
get_rx_vlan_filter_size - To get vlan filter size
fill_rx_addr_filter - To fill addr filter
fill_rx_vlan_filter - To fill vlan filter

Signed-off-by: Roopa Prabhu <redacted>
Signed-off-by: Christian Benvenuti <redacted>
Signed-off-by: David Wang <redacted>
---
 include/net/rtnetlink.h |   13 +++++++++++++
 1 files changed, 13 insertions(+), 0 deletions(-)

diff --git a/include/net/rtnetlink.h b/include/net/rtnetlink.h
index 678f1ff..dcb26bd 100644
--- a/include/net/rtnetlink.h
+++ b/include/net/rtnetlink.h
@@ -78,6 +78,19 @@ struct rtnl_link_ops {
 	int			(*get_tx_queues)(struct net *net, struct nlattr *tb[],
 						 unsigned int *tx_queues,
 						 unsigned int *real_tx_queues);
+
+	int			(*set_rx_addr_filter)(struct net_device *dev,
+						      struct nlattr *tb[]);
+	int			(*set_rx_vlan_filter)(struct net_device *dev,
+						      struct nlattr *tb[]);
+	size_t			(*get_rx_addr_filter_size)(
+						const struct net_device *dev);
+	size_t			(*get_rx_vlan_filter_size)(
+						const struct net_device *dev);
+	int			(*fill_rx_addr_filter)(struct sk_buff *skb,
+						const struct net_device *dev);
+	int			(*fill_rx_vlan_filter)(struct sk_buff *skb,
+						const struct net_device *dev);
 };
 
 extern int	__rtnl_link_register(struct rtnl_link_ops *ops);

[net-next-2.6 PATCH 3/8 RFC v2] rtnetlink: Add support to set MAC/VLAN filters

From: Roopa Prabhu <hidden>
Date: 2011-10-19 06:26:09

From: Roopa Prabhu <redacted>

This patch adds support in rtnetlink for IFLA_RX_FILTER set.
It adds code in do_setlink to parse IFLA_RX_FILTER and call
the rtnl_link_ops->set_rx_addr_filter and
rtnl_link_ops->set_rx_vlan_filter to set MAC and VLAN filters.

Signed-off-by: Roopa Prabhu <redacted>
Signed-off-by: Christian Benvenuti <redacted>
Signed-off-by: David Wang <redacted>
---
 net/core/rtnetlink.c |   67 ++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 67 insertions(+), 0 deletions(-)

diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index a3b213f..bc1074d 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -1296,6 +1296,7 @@ static int do_setlink(struct net_device *dev, struct ifinfomsg *ifm,
 		      struct nlattr **tb, char *ifname, int modified)
 {
 	const struct net_device_ops *ops = dev->netdev_ops;
+	const struct rtnl_link_ops *rtnl_ops;
 	int send_addr_notify = 0;
 	int err;
 
@@ -1513,6 +1514,72 @@ static int do_setlink(struct net_device *dev, struct ifinfomsg *ifm,
 			modified = 1;
 		}
 	}
+
+	if (tb[IFLA_RX_FILTER]) {
+		struct nlattr *filters[IFLA_RX_FILTER_MAX+1];
+
+		err = -EOPNOTSUPP;
+		rtnl_ops = dev->rtnl_link_ops;
+		if (!rtnl_ops)
+			goto errout;
+
+		err = nla_parse_nested(filters,
+			IFLA_RX_FILTER_MAX, tb[IFLA_RX_FILTER],
+			ifla_rx_filter_policy);
+		if (err < 0)
+			goto errout;
+
+		if (filters[IFLA_RX_ADDR_FILTER]) {
+			struct nlattr *addr_filters[IFLA_ADDR_FILTER_MAX+1];
+
+			if (!rtnl_ops->set_rx_addr_filter) {
+				err = -EOPNOTSUPP;
+				goto errout;
+			}
+
+			err = nla_parse_nested(addr_filters,
+				IFLA_ADDR_FILTER_MAX,
+				filters[IFLA_RX_ADDR_FILTER],
+				ifla_addr_filter_policy);
+			if (err < 0)
+				goto errout;
+
+			if (addr_filters[IFLA_ADDR_FILTER_FLAGS]) {
+				unsigned int flags = nla_get_u32(
+					addr_filters[IFLA_ADDR_FILTER_FLAGS]);
+				if (flags & ~RX_FILTER_FLAGS) {
+					err = -EINVAL;
+					goto errout;
+				}
+			}
+
+			err = rtnl_ops->set_rx_addr_filter(dev, addr_filters);
+			if (err < 0)
+				goto errout;
+			modified = 1;
+		}
+
+		if (filters[IFLA_RX_VLAN_FILTER]) {
+			struct nlattr *vlan_filters[IFLA_VLAN_FILTER_MAX+1];
+
+			if (!rtnl_ops->set_rx_vlan_filter) {
+				err = -EOPNOTSUPP;
+				goto errout;
+			}
+
+			err = nla_parse_nested(vlan_filters,
+				IFLA_VLAN_FILTER_MAX,
+				filters[IFLA_RX_VLAN_FILTER],
+				ifla_vlan_filter_policy);
+			if (err < 0)
+				goto errout;
+
+			err = rtnl_ops->set_rx_vlan_filter(dev, vlan_filters);
+			if (err < 0)
+				goto errout;
+			modified = 1;
+		}
+	}
 	err = 0;
 
 errout:

[net-next-2.6 PATCH 4/8 RFC v2] rtnetlink: Add support to get MAC/VLAN filters

From: Roopa Prabhu <hidden>
Date: 2011-10-19 06:26:15

From: Roopa Prabhu <redacted>

This patch adds support in rtnetlink for IFLA_RX_FILTER get.
It adds new function rtnl_rx_filter_get_size to get the size
of rx filters by calling rtnl_link_ops->get_rx_addr_filter_size
and rtnl_link_ops->get_rx_vlan_filter_size

Signed-off-by: Roopa Prabhu <redacted>
Signed-off-by: Christian Benvenuti <redacted>
Signed-off-by: David Wang <redacted>
---
 net/core/rtnetlink.c |   90 +++++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 89 insertions(+), 1 deletions(-)

diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index bc1074d..6a709db 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -475,6 +475,37 @@ static size_t rtnl_link_get_af_size(const struct net_device *dev)
 	return size;
 }
 
+static size_t rtnl_rx_filter_get_size(const struct net_device *dev)
+{
+	const struct rtnl_link_ops *ops = dev->rtnl_link_ops;
+	size_t size;
+
+	if (!ops)
+		return 0;
+
+	size = nla_total_size(sizeof(struct nlattr)); /* IFLA_RX_FILTER */
+
+	if (ops->get_rx_addr_filter_size) {
+		size_t rx_addr_filter_size = ops->get_rx_addr_filter_size(dev);
+
+		if (rx_addr_filter_size)
+			/* IFLA_RX_ADDR_FILTER */
+			size += nla_total_size(sizeof(struct nlattr)) +
+					rx_addr_filter_size;
+	}
+
+	if (ops->get_rx_vlan_filter_size) {
+		size_t rx_vlan_filter_size = ops->get_rx_vlan_filter_size(dev);
+
+		if (rx_vlan_filter_size)
+			/* IFLA_RX_VLAN_FILTER */
+			size += nla_total_size(sizeof(struct nlattr)) +
+					rx_vlan_filter_size;
+	}
+
+	return size;
+}
+
 static int rtnl_link_fill(struct sk_buff *skb, const struct net_device *dev)
 {
 	const struct rtnl_link_ops *ops = dev->rtnl_link_ops;
@@ -513,6 +544,59 @@ out:
 	return err;
 }
 
+static int rtnl_rx_filter_fill(struct sk_buff *skb,
+			       const struct net_device *dev)
+{
+	const struct rtnl_link_ops *ops = dev->rtnl_link_ops;
+	struct nlattr *rx_filter, *uninitialized_var(addr_filter);
+	struct nlattr *uninitialized_var(vlan_filter);
+	int err = -EMSGSIZE;
+
+	rx_filter = nla_nest_start(skb, IFLA_RX_FILTER);
+	if (rx_filter == NULL)
+		goto out;
+
+	if (ops->fill_rx_addr_filter) {
+		addr_filter = nla_nest_start(skb, IFLA_RX_ADDR_FILTER);
+		if (addr_filter == NULL)
+			goto err_cancel_rx_filter;
+		err = ops->fill_rx_addr_filter(skb, dev);
+		if (err == -ENODATA)
+			nla_nest_cancel(skb, addr_filter);
+		else if (err < 0)
+			goto err_cancel_addr_filter;
+		else
+			nla_nest_end(skb, addr_filter);
+	}
+
+	if (ops->fill_rx_vlan_filter) {
+		vlan_filter = nla_nest_start(skb, IFLA_RX_VLAN_FILTER);
+		if (vlan_filter == NULL)
+			goto err_cancel_addr_filter;
+		err = ops->fill_rx_vlan_filter(skb, dev);
+		if (err == -ENODATA)
+			nla_nest_cancel(skb, vlan_filter);
+		else if (err)
+			goto err_cancel_vlan_filter;
+		else
+			nla_nest_end(skb, vlan_filter);
+	}
+	nla_nest_end(skb, rx_filter);
+
+	return 0;
+
+err_cancel_vlan_filter:
+	if (ops->fill_rx_vlan_filter)
+		nla_nest_cancel(skb, vlan_filter);
+err_cancel_addr_filter:
+	if (ops->fill_rx_addr_filter)
+		nla_nest_cancel(skb, addr_filter);
+err_cancel_rx_filter:
+	nla_nest_cancel(skb, rx_filter);
+out:
+	return err;
+}
+
 static const int rtm_min[RTM_NR_FAMILIES] =
 {
 	[RTM_FAM(RTM_NEWLINK)]      = NLMSG_LENGTH(sizeof(struct ifinfomsg)),
@@ -786,7 +870,8 @@ static noinline size_t if_nlmsg_size(const struct net_device *dev)
 	       + rtnl_vfinfo_size(dev) /* IFLA_VFINFO_LIST */
 	       + rtnl_port_size(dev) /* IFLA_VF_PORTS + IFLA_PORT_SELF */
 	       + rtnl_link_get_size(dev) /* IFLA_LINKINFO */
-	       + rtnl_link_get_af_size(dev); /* IFLA_AF_SPEC */
+	       + rtnl_link_get_af_size(dev) /* IFLA_AF_SPEC */
+	       + rtnl_rx_filter_get_size(dev); /* IFLA_RX_FILTER */
 }
 
 static int rtnl_vf_ports_fill(struct sk_buff *skb, struct net_device *dev)
@@ -997,6 +1082,9 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev,
 		goto nla_put_failure;
 
 	if (dev->rtnl_link_ops) {
+		if (rtnl_rx_filter_fill(skb, dev) < 0)
+			goto nla_put_failure;
+
 		if (rtnl_link_fill(skb, dev) < 0)
 			goto nla_put_failure;
 	}

[net-next-2.6 PATCH 5/8 RFC v2] macvlan: Add support to set MAC/VLAN filter rtnl link operations

From: Roopa Prabhu <hidden>
Date: 2011-10-19 06:26:21

From: Roopa Prabhu <redacted>

This patch adds support to set MAC and VLAN filter rtnl_link_ops
on a macvlan interface. It adds support for set_rx_addr_filter and
set_rx_vlan_filter rtnl link operations. It currently supports
only macvlan PASSTHRU mode.

For passthru mode,
	 - Address filters: macvlan netdev uc and mc lists are
	updated to reflect the addresses in the filter.

	- VLAN filter: Currently applied vlan bitmap is maintained in
	struct macvlan_dev->vlan_filter. This vlan bitmap is updated to
	reflect the new bitmap that came in the netlink msg.
	lowerdev hw vlan filter is updated using macvlan netdev operations
	ndo_vlan_rx_add_vid and ndo_vlan_rx_kill_vid (which inturn call
	lowerdev vlan add/kill netdev ops)

Signed-off-by: Roopa Prabhu <redacted>
Signed-off-by: Christian Benvenuti <redacted>
Signed-off-by: David Wang <redacted>
---
 drivers/net/macvlan.c      |  296 ++++++++++++++++++++++++++++++++++++++++----
 include/linux/if_macvlan.h |    8 +
 2 files changed, 279 insertions(+), 25 deletions(-)

diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c
index 24cf942..dbb2e30 100644
--- a/drivers/net/macvlan.c
+++ b/drivers/net/macvlan.c
@@ -299,30 +299,36 @@ static int macvlan_open(struct net_device *dev)
 	struct net_device *lowerdev = vlan->lowerdev;
 	int err;
 
-	if (vlan->port->passthru) {
-		dev_set_promiscuity(lowerdev, 1);
-		goto hash_add;
-	}
+	if (!vlan->port->passthru) {
+		err = -EBUSY;
+		if (macvlan_addr_busy(vlan->port, dev->dev_addr))
+			goto out;
 
-	err = -EBUSY;
-	if (macvlan_addr_busy(vlan->port, dev->dev_addr))
-		goto out;
+		err = dev_uc_add(lowerdev, dev->dev_addr);
+		if (err < 0)
+			goto out;
+	}
 
-	err = dev_uc_add(lowerdev, dev->dev_addr);
-	if (err < 0)
-		goto out;
 	if (dev->flags & IFF_ALLMULTI) {
 		err = dev_set_allmulti(lowerdev, 1);
 		if (err < 0)
 			goto del_unicast;
 	}
+	if (dev->flags & IFF_PROMISC) {
+		err = dev_set_promiscuity(lowerdev, 1);
+		if (err < 0)
+			goto unset_allmulti;
+	}
 
-hash_add:
 	macvlan_hash_add(vlan);
 	return 0;
 
+unset_allmulti:
+	dev_set_allmulti(lowerdev, -1);
+
 del_unicast:
-	dev_uc_del(lowerdev, dev->dev_addr);
+	if (!vlan->port->passthru)
+		dev_uc_del(lowerdev, dev->dev_addr);
 out:
 	return err;
 }
@@ -332,18 +338,16 @@ static int macvlan_stop(struct net_device *dev)
 	struct macvlan_dev *vlan = netdev_priv(dev);
 	struct net_device *lowerdev = vlan->lowerdev;
 
-	if (vlan->port->passthru) {
-		dev_set_promiscuity(lowerdev, -1);
-		goto hash_del;
-	}
-
+	dev_uc_unsync(lowerdev, dev);
 	dev_mc_unsync(lowerdev, dev);
 	if (dev->flags & IFF_ALLMULTI)
 		dev_set_allmulti(lowerdev, -1);
+	if (dev->flags & IFF_PROMISC)
+		dev_set_promiscuity(lowerdev, -1);
 
-	dev_uc_del(lowerdev, dev->dev_addr);
+	if (!vlan->port->passthru)
+		dev_uc_del(lowerdev, dev->dev_addr);
 
-hash_del:
 	macvlan_hash_del(vlan, !dev->dismantle);
 	return 0;
 }
@@ -384,12 +388,16 @@ static void macvlan_change_rx_flags(struct net_device *dev, int change)
 
 	if (change & IFF_ALLMULTI)
 		dev_set_allmulti(lowerdev, dev->flags & IFF_ALLMULTI ? 1 : -1);
+	if (change & IFF_PROMISC)
+		dev_set_promiscuity(lowerdev,
+			dev->flags & IFF_PROMISC ? 1 : -1);
 }
 
-static void macvlan_set_multicast_list(struct net_device *dev)
+static void macvlan_set_rx_mode(struct net_device *dev)
 {
 	struct macvlan_dev *vlan = netdev_priv(dev);
 
+	dev_uc_sync(vlan->lowerdev, dev);
 	dev_mc_sync(vlan->lowerdev, dev);
 }
 
@@ -562,7 +570,7 @@ static const struct net_device_ops macvlan_netdev_ops = {
 	.ndo_change_mtu		= macvlan_change_mtu,
 	.ndo_change_rx_flags	= macvlan_change_rx_flags,
 	.ndo_set_mac_address	= macvlan_set_mac_address,
-	.ndo_set_rx_mode	= macvlan_set_multicast_list,
+	.ndo_set_rx_mode	= macvlan_set_rx_mode,
 	.ndo_get_stats64	= macvlan_dev_get_stats64,
 	.ndo_validate_addr	= eth_validate_addr,
 	.ndo_vlan_rx_add_vid	= macvlan_vlan_rx_add_vid,
@@ -574,6 +582,7 @@ void macvlan_common_setup(struct net_device *dev)
 	ether_setup(dev);
 
 	dev->priv_flags	       &= ~(IFF_XMIT_DST_RELEASE | IFF_TX_SKB_SHARING);
+	dev->priv_flags	       |= IFF_UNICAST_FLT;
 	dev->netdev_ops		= &macvlan_netdev_ops;
 	dev->destructor		= free_netdev;
 	dev->header_ops		= &macvlan_hard_header_ops,
@@ -701,6 +710,8 @@ int macvlan_common_newlink(struct net *src_net, struct net_device *dev,
 	if (data && data[IFLA_MACVLAN_MODE])
 		vlan->mode = nla_get_u32(data[IFLA_MACVLAN_MODE]);
 
+	memset(vlan->vlan_filter, 0, VLAN_BITMAP_SIZE);
+
 	if (vlan->mode == MACVLAN_MODE_PASSTHRU) {
 		if (port->count)
 			return -EINVAL;
@@ -770,6 +781,239 @@ nla_put_failure:
 	return -EMSGSIZE;
 }
 
+static inline void macvlan_set_filter_vlan(struct net_device *dev, int vid)
+{
+	struct macvlan_dev *vlan = netdev_priv(dev);
+
+	set_bit(vid, vlan->vlan_filter);
+	macvlan_vlan_rx_add_vid(dev, vid);
+}
+
+static inline void macvlan_clear_filter_vlan(struct net_device *dev, int vid)
+{
+	struct macvlan_dev *vlan = netdev_priv(dev);
+
+	clear_bit(vid, vlan->vlan_filter);
+	macvlan_vlan_rx_kill_vid(dev, vid);
+}
+
+static int macvlan_set_rx_vlan_filter_passthru(struct net_device *dev,
+					       unsigned long *vlans)
+{
+	struct macvlan_dev *vlan = netdev_priv(dev);
+	u16 vid;
+
+	/*
+	 *	Clear vlans that are not present in the new filter
+	 */
+	for_each_set_bit(vid, vlan->vlan_filter, VLAN_N_VID) {
+		if (!test_bit(vid, vlans))
+			macvlan_clear_filter_vlan(dev, vid);
+	}
+
+	/*
+	 *	Set new vlans that came in the filter
+	 */
+	for_each_set_bit(vid, vlans, VLAN_N_VID) {
+		if (!test_bit(vid, vlan->vlan_filter))
+			macvlan_set_filter_vlan(dev, vid);
+	}
+
+	return 0;
+}
+
+int macvlan_set_rx_vlan_filter(struct net_device *dev,
+	struct nlattr *tb[])
+{
+	struct macvlan_dev *vlan = netdev_priv(dev);
+	int err;
+
+	switch (vlan->mode) {
+	case MACVLAN_MODE_PASSTHRU:
+		if (tb[IFLA_VLAN_BITMAP])
+			return macvlan_set_rx_vlan_filter_passthru(dev,
+					nla_data(tb[IFLA_VLAN_BITMAP]));
+		break;
+	default:
+		err = -EOPNOTSUPP;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL(macvlan_set_rx_vlan_filter);
+
+static int macvlan_addr_in_hw_list(struct netdev_hw_addr_list *list,
+	u8 *addr, int addrlen)
+{
+	struct netdev_hw_addr *ha;
+
+	netdev_hw_addr_list_for_each(ha, list) {
+		if (!memcmp(ha->addr, addr, addrlen))
+			return 1;
+	}
+
+	return 0;
+}
+
+static int macvlan_addr_in_attrs(struct nlattr *addr_list, u8 *addr,
+	int addrlen)
+{
+	struct nlattr *addr_attr;
+	int addr_rem;
+
+	nla_for_each_nested(addr_attr, addr_list, addr_rem) {
+		if (!memcmp(nla_data(addr_attr), addr, addrlen))
+			return 1;
+	}
+
+	return 0;
+}
+
+static int macvlan_update_hw_addr_list(struct net_device *dev,
+	struct netdev_hw_addr_list *curr_addr_list, int addr_list_type,
+	struct nlattr *new_addr_attrs)
+{
+	struct nlattr *addr_attr;
+	int addr_rem;
+	u8 *addr;
+	int alen, i;
+	int err = 0;
+
+	if (!netdev_hw_addr_list_empty(curr_addr_list)) {
+		struct netdev_hw_addr *ha;
+		u8 *del_addrlist;
+		int del_addr_count = 0;
+
+		alen = ETH_ALEN * netdev_hw_addr_list_count(curr_addr_list);
+		del_addrlist = kmalloc(alen, GFP_KERNEL);
+		if (!del_addrlist) {
+			err = -ENOMEM;
+			goto err_out;
+		}
+
+		/*
+		 *	Get the addresses that need to be deleted
+		 */
+		netdev_hw_addr_list_for_each(ha, curr_addr_list) {
+			if (!macvlan_addr_in_attrs(new_addr_attrs, ha->addr,
+				ETH_ALEN))
+				memcpy(del_addrlist + (del_addr_count++ *
+					ETH_ALEN), ha->addr, ETH_ALEN);
+		}
+
+		/*
+		 * Delete addresses
+		 */
+		for (i = 0, addr = del_addrlist; i < del_addr_count && addr;
+			i++, addr += ETH_ALEN) {
+			if (addr_list_type == NETDEV_HW_ADDR_T_UNICAST)
+				dev_uc_del(dev, addr);
+			else if (addr_list_type == NETDEV_HW_ADDR_T_MULTICAST)
+				dev_mc_del(dev, addr);
+		}
+		kfree(del_addrlist);
+	}
+
+	/* Add new addresses */
+	nla_for_each_nested(addr_attr, new_addr_attrs, addr_rem) {
+		if (!macvlan_addr_in_hw_list(curr_addr_list,
+			nla_data(addr_attr), ETH_ALEN)) {
+			if (addr_list_type == NETDEV_HW_ADDR_T_UNICAST)
+				dev_uc_add(dev, nla_data(addr_attr));
+			else if (addr_list_type == NETDEV_HW_ADDR_T_MULTICAST)
+				dev_mc_add(dev, nla_data(addr_attr));
+		}
+	}
+
+	return 0;
+
+err_out:
+	return err;
+}
+
+static int macvlan_set_rx_addr_filter_passthru(struct net_device *dev,
+	struct nlattr *filter_flags, struct nlattr *uc_list,
+	struct nlattr *mc_list)
+{
+	unsigned int flags, flags_changed;
+	int err;
+
+	if (filter_flags) {
+		flags = nla_get_u32(filter_flags);
+
+		flags_changed = (dev->flags ^ flags) & RX_FILTER_FLAGS;
+		if (flags_changed)
+			dev_change_flags(dev, dev->flags ^ flags_changed);
+	}
+
+	if (uc_list) {
+		err = macvlan_update_hw_addr_list(dev, &dev->uc,
+					NETDEV_HW_ADDR_T_UNICAST, uc_list);
+		if (err)
+			return err;
+	}
+
+	if (mc_list) {
+		err = macvlan_update_hw_addr_list(dev, &dev->mc,
+					NETDEV_HW_ADDR_T_MULTICAST, mc_list);
+		if (err)
+			return err;
+	}
+
+	return 0;
+}
+
+static int macvlan_validate_rx_addr_filter(struct net_device *dev,
+	struct nlattr *tb[])
+{
+	struct nlattr *addr_attr;
+	int addr_rem;
+
+	if (tb[IFLA_ADDR_FILTER_UC_LIST]) {
+		nla_for_each_nested(addr_attr, tb[IFLA_ADDR_FILTER_UC_LIST],
+				    addr_rem) {
+			if ((nla_type(addr_attr) != IFLA_ADDR_LIST_ENTRY) ||
+				!is_unicast_ether_addr(nla_data(addr_attr)))
+				return -EINVAL;
+		}
+	}
+
+	if (tb[IFLA_ADDR_FILTER_MC_LIST]) {
+		nla_for_each_nested(addr_attr, tb[IFLA_ADDR_FILTER_MC_LIST],
+				    addr_rem) {
+			if ((nla_type(addr_attr) != IFLA_ADDR_LIST_ENTRY) ||
+				!is_multicast_ether_addr(nla_data(addr_attr)))
+				return -EINVAL;
+		}
+	}
+
+	return 0;
+}
+
+int macvlan_set_rx_addr_filter(struct net_device *dev,
+	struct nlattr *tb[])
+{
+	struct macvlan_dev *vlan = netdev_priv(dev);
+	int err;
+
+	err = macvlan_validate_rx_addr_filter(dev, tb);
+	if (err)
+		return err;
+
+	switch (vlan->mode) {
+	case MACVLAN_MODE_PASSTHRU:
+		return macvlan_set_rx_addr_filter_passthru(dev,
+			tb[IFLA_ADDR_FILTER_FLAGS],
+			tb[IFLA_ADDR_FILTER_UC_LIST],
+			tb[IFLA_ADDR_FILTER_MC_LIST]);
+	default:
+		return -EOPNOTSUPP;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL(macvlan_set_rx_addr_filter);
+
 static const struct nla_policy macvlan_policy[IFLA_MACVLAN_MAX + 1] = {
 	[IFLA_MACVLAN_MODE] = { .type = NLA_U32 },
 };
@@ -790,10 +1034,12 @@ int macvlan_link_register(struct rtnl_link_ops *ops)
 EXPORT_SYMBOL_GPL(macvlan_link_register);
 
 static struct rtnl_link_ops macvlan_link_ops = {
-	.kind		= "macvlan",
-	.setup		= macvlan_setup,
-	.newlink	= macvlan_newlink,
-	.dellink	= macvlan_dellink,
+	.kind				= "macvlan",
+	.setup				= macvlan_setup,
+	.newlink			= macvlan_newlink,
+	.dellink			= macvlan_dellink,
+	.set_rx_addr_filter		= macvlan_set_rx_addr_filter,
+	.set_rx_vlan_filter		= macvlan_set_rx_vlan_filter,
 };
 
 static int macvlan_device_event(struct notifier_block *unused,
diff --git a/include/linux/if_macvlan.h b/include/linux/if_macvlan.h
index e28b2e4..d203293 100644
--- a/include/linux/if_macvlan.h
+++ b/include/linux/if_macvlan.h
@@ -7,6 +7,7 @@
 #include <linux/netlink.h>
 #include <net/netlink.h>
 #include <linux/u64_stats_sync.h>
+#include <linux/if_vlan.h>
 
 #if defined(CONFIG_MACVTAP) || defined(CONFIG_MACVTAP_MODULE)
 struct socket *macvtap_get_socket(struct file *);
@@ -64,6 +65,7 @@ struct macvlan_dev {
 	int (*forward)(struct net_device *dev, struct sk_buff *skb);
 	struct macvtap_queue	*taps[MAX_MACVTAP_QUEUES];
 	int			numvtaps;
+	unsigned long		vlan_filter[BITS_TO_LONGS(VLAN_N_VID)];
 };
 
 static inline void macvlan_count_rx(const struct macvlan_dev *vlan,
@@ -104,4 +106,10 @@ extern int macvlan_link_register(struct rtnl_link_ops *ops);
 extern netdev_tx_t macvlan_start_xmit(struct sk_buff *skb,
 				      struct net_device *dev);
 
+extern int macvlan_set_rx_addr_filter(struct net_device *dev,
+				      struct nlattr *tb[]);
+
+extern int macvlan_set_rx_vlan_filter(struct net_device *dev,
+				      struct nlattr *tb[]);
+
 #endif /* _LINUX_IF_MACVLAN_H */

[net-next-2.6 PATCH 6/8 RFC v2] macvlan: Add support to get MAC/VLAN filter rtnl link operations

From: Roopa Prabhu <hidden>
Date: 2011-10-19 06:26:26

From: Roopa Prabhu <redacted>

This patch adds support to get MAC and VLAN filter rtnl_link_ops
on a macvlan interface. It adds support for get_rx_addr_filter_size,
get_rx_vlan_filter_size, fill_rx_addr_filter and fill_rx_vlan_filter
rtnl link operations.

Signed-off-by: Roopa Prabhu <redacted>
Signed-off-by: Christian Benvenuti <redacted>
Signed-off-by: David Wang <redacted>
---
 drivers/net/macvlan.c      |  126 ++++++++++++++++++++++++++++++++++++++++++++
 include/linux/if_macvlan.h |   10 +++
 2 files changed, 136 insertions(+), 0 deletions(-)

diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c
index dbb2e30..23636e6 100644
--- a/drivers/net/macvlan.c
+++ b/drivers/net/macvlan.c
@@ -1014,6 +1014,128 @@ int macvlan_set_rx_addr_filter(struct net_device *dev,
 }
 EXPORT_SYMBOL(macvlan_set_rx_addr_filter);
 
+static size_t macvlan_get_rx_addr_filter_passthru_size(
+				const struct net_device *dev)
+{
+	size_t size;
+
+	/* IFLA_ADDR_FILTER_FLAGS */
+	size = nla_total_size(sizeof(u32));
+
+	if (netdev_uc_count(dev))
+		/* IFLA_ADDR_FILTER_UC_LIST */
+		size += nla_total_size(netdev_uc_count(dev) *
+				       ETH_ALEN * sizeof(struct nlattr));
+
+	if (netdev_mc_count(dev))
+		/* IFLA_ADDR_FILTER_MC_LIST */
+		size += nla_total_size(netdev_mc_count(dev) *
+				       ETH_ALEN * sizeof(struct nlattr));
+
+	return size;
+}
+
+size_t macvlan_get_rx_addr_filter_size(const struct net_device *dev)
+{
+	struct macvlan_dev *vlan = netdev_priv(dev);
+
+	switch (vlan->mode) {
+	case MACVLAN_MODE_PASSTHRU:
+		return macvlan_get_rx_addr_filter_passthru_size(dev);
+	default:
+		return 0;
+	}
+}
+EXPORT_SYMBOL(macvlan_get_rx_addr_filter_size);
+
+size_t macvlan_get_rx_vlan_filter_size(const struct net_device *dev)
+{
+	struct macvlan_dev *vlan = netdev_priv(dev);
+
+	switch (vlan->mode) {
+	case MACVLAN_MODE_PASSTHRU:
+		/* IFLA_VLAN_BITMAP */
+		return nla_total_size(VLAN_BITMAP_SIZE);
+	default:
+		return 0;
+	}
+}
+EXPORT_SYMBOL(macvlan_get_rx_vlan_filter_size);
+
+static int macvlan_fill_rx_addr_filter_passthru(struct sk_buff *skb,
+						const struct net_device *dev)
+{
+	struct nlattr *uninitialized_var(uc_list), *mc_list;
+	struct netdev_hw_addr *ha;
+
+	NLA_PUT_U32(skb, IFLA_ADDR_FILTER_FLAGS, dev->flags & RX_FILTER_FLAGS);
+
+	if (netdev_uc_count(dev)) {
+		uc_list = nla_nest_start(skb, IFLA_ADDR_FILTER_UC_LIST);
+		if (uc_list == NULL)
+			goto nla_put_failure;
+
+		netdev_for_each_uc_addr(ha, dev) {
+			NLA_PUT(skb, IFLA_ADDR_LIST_ENTRY, ETH_ALEN, ha->addr);
+		}
+		nla_nest_end(skb, uc_list);
+	}
+
+	if (netdev_mc_count(dev)) {
+		mc_list = nla_nest_start(skb, IFLA_ADDR_FILTER_MC_LIST);
+		if (mc_list == NULL)
+			goto nla_uc_list_cancel;
+
+		netdev_for_each_mc_addr(ha, dev) {
+			NLA_PUT(skb, IFLA_ADDR_LIST_ENTRY, ETH_ALEN, ha->addr);
+		}
+		nla_nest_end(skb, mc_list);
+	}
+
+	return 0;
+
+nla_uc_list_cancel:
+	if (netdev_uc_count(dev))
+		nla_nest_cancel(skb, uc_list);
+nla_put_failure:
+	return -EMSGSIZE;
+}
+
+int macvlan_fill_rx_addr_filter(struct sk_buff *skb,
+				const struct net_device *dev)
+{
+	struct macvlan_dev *vlan = netdev_priv(dev);
+
+	switch (vlan->mode) {
+	case MACVLAN_MODE_PASSTHRU:
+		return macvlan_fill_rx_addr_filter_passthru(skb, dev);
+	default:
+		return -ENODATA; /* No data to Fill */
+	}
+}
+EXPORT_SYMBOL(macvlan_fill_rx_addr_filter);
+
+int macvlan_fill_rx_vlan_filter(struct sk_buff *skb,
+				const struct net_device *dev)
+{
+	struct macvlan_dev *vlan = netdev_priv(dev);
+
+	switch (vlan->mode) {
+	case MACVLAN_MODE_PASSTHRU:
+		NLA_PUT(skb, IFLA_VLAN_BITMAP, VLAN_BITMAP_SIZE,
+			vlan->vlan_filter);
+		break;
+	default:
+		return -ENODATA; /* No data to Fill */
+	}
+
+	return 0;
+
+nla_put_failure:
+	return -EMSGSIZE;
+}
+EXPORT_SYMBOL(macvlan_fill_rx_vlan_filter);
+
 static const struct nla_policy macvlan_policy[IFLA_MACVLAN_MAX + 1] = {
 	[IFLA_MACVLAN_MODE] = { .type = NLA_U32 },
 };
@@ -1040,6 +1162,10 @@ static struct rtnl_link_ops macvlan_link_ops = {
 	.dellink			= macvlan_dellink,
 	.set_rx_addr_filter		= macvlan_set_rx_addr_filter,
 	.set_rx_vlan_filter		= macvlan_set_rx_vlan_filter,
+	.get_rx_addr_filter_size	= macvlan_get_rx_addr_filter_size,
+	.get_rx_vlan_filter_size	= macvlan_get_rx_vlan_filter_size,
+	.fill_rx_addr_filter		= macvlan_fill_rx_addr_filter,
+	.fill_rx_vlan_filter		= macvlan_fill_rx_vlan_filter,
 };
 
 static int macvlan_device_event(struct notifier_block *unused,
diff --git a/include/linux/if_macvlan.h b/include/linux/if_macvlan.h
index d203293..700db8b 100644
--- a/include/linux/if_macvlan.h
+++ b/include/linux/if_macvlan.h
@@ -112,4 +112,14 @@ extern int macvlan_set_rx_addr_filter(struct net_device *dev,
 extern int macvlan_set_rx_vlan_filter(struct net_device *dev,
 				      struct nlattr *tb[]);
 
+extern int macvlan_fill_rx_addr_filter(struct sk_buff *skb,
+				       const struct net_device *dev);
+
+extern int macvlan_fill_rx_vlan_filter(struct sk_buff *skb,
+				       const struct net_device *dev);
+
+extern size_t macvlan_get_rx_addr_filter_size(const struct net_device *dev);
+
+extern size_t macvlan_get_rx_vlan_filter_size(const struct net_device *dev);
+
 #endif /* _LINUX_IF_MACVLAN_H */

[net-next-2.6 PATCH 7/8 RFC v2] macvtap: Add support to set MAC/VLAN filter rtnl link operations

From: Roopa Prabhu <hidden>
Date: 2011-10-19 06:26:30

From: Roopa Prabhu <redacted>

This patch adds support to set MAC and VLAN filter rtnl_link_ops
on a macvtap interface. It adds support for set_rx_addr_filter and
set_rx_vlan_filter rtnl link operations. These operations inturn call the
equivalent operations defined in macvlan

Signed-off-by: Roopa Prabhu <redacted>
Signed-off-by: Christian Benvenuti <redacted>
Signed-off-by: David Wang <redacted>
---
 drivers/net/macvtap.c |   22 ++++++++++++++++++----
 1 files changed, 18 insertions(+), 4 deletions(-)

diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c
index 3da5578..8a2cb59 100644
--- a/drivers/net/macvtap.c
+++ b/drivers/net/macvtap.c
@@ -273,6 +273,18 @@ static int macvtap_receive(struct sk_buff *skb)
 	return macvtap_forward(skb->dev, skb);
 }
 
+static int macvtap_set_rx_addr_filter(struct net_device *dev,
+	struct nlattr *tb[])
+{
+	return macvlan_set_rx_addr_filter(dev, tb);
+}
+
+static int macvtap_set_rx_vlan_filter(struct net_device *dev,
+	struct nlattr *tb[])
+{
+	return macvlan_set_rx_vlan_filter(dev, tb);
+}
+
 static int macvtap_newlink(struct net *src_net,
 			   struct net_device *dev,
 			   struct nlattr *tb[],
@@ -317,10 +329,12 @@ static void macvtap_setup(struct net_device *dev)
 }
 
 static struct rtnl_link_ops macvtap_link_ops __read_mostly = {
-	.kind		= "macvtap",
-	.setup		= macvtap_setup,
-	.newlink	= macvtap_newlink,
-	.dellink	= macvtap_dellink,
+	.kind				= "macvtap",
+	.setup				= macvtap_setup,
+	.newlink			= macvtap_newlink,
+	.dellink			= macvtap_dellink,
+	.set_rx_addr_filter		= macvtap_set_rx_addr_filter,
+	.set_rx_vlan_filter		= macvtap_set_rx_vlan_filter,
 };
 
 

[net-next-2.6 PATCH 8/8 RFC v2] macvtap: Add support to get MAC/VLAN filter rtnl link operations

From: Roopa Prabhu <hidden>
Date: 2011-10-19 06:26:36

From: Roopa Prabhu <redacted>

This patch adds support to get MAC and VLAN filter rtnl_link_ops
on a macvtap interface. It adds support for get_rx_addr_filter_size,
get_rx_vlan_filter_size, fill_rx_addr_filter and fill_rx_vlan_filter
rtnl link operations. Calls equivalent macvlan operations.

Signed-off-by: Roopa Prabhu <redacted>
Signed-off-by: Christian Benvenuti <redacted>
Signed-off-by: David Wang <redacted>
---
 drivers/net/macvtap.c |   27 +++++++++++++++++++++++++++
 1 files changed, 27 insertions(+), 0 deletions(-)

diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c
index 8a2cb59..9b40de7 100644
--- a/drivers/net/macvtap.c
+++ b/drivers/net/macvtap.c
@@ -285,6 +285,29 @@ static int macvtap_set_rx_vlan_filter(struct net_device *dev,
 	return macvlan_set_rx_vlan_filter(dev, tb);
 }
 
+static int macvtap_fill_rx_addr_filter(struct sk_buff *skb,
+	const struct net_device *dev)
+{
+	return macvlan_fill_rx_addr_filter(skb, dev);
+}
+
+static int macvtap_fill_rx_vlan_filter(struct sk_buff *skb,
+	const struct net_device *dev)
+{
+	return macvlan_fill_rx_vlan_filter(skb, dev);
+}
+
+static size_t macvtap_get_rx_addr_filter_size(const struct net_device *dev)
+{
+	return macvlan_get_rx_addr_filter_size(dev);
+}
+
+static size_t macvtap_get_rx_vlan_filter_size(const struct net_device *dev)
+{
+	return macvlan_get_rx_vlan_filter_size(dev);
+}
+
+
 static int macvtap_newlink(struct net *src_net,
 			   struct net_device *dev,
 			   struct nlattr *tb[],
@@ -335,6 +358,10 @@ static struct rtnl_link_ops macvtap_link_ops __read_mostly = {
 	.dellink			= macvtap_dellink,
 	.set_rx_addr_filter		= macvtap_set_rx_addr_filter,
 	.set_rx_vlan_filter		= macvtap_set_rx_vlan_filter,
+	.get_rx_addr_filter_size	= macvtap_get_rx_addr_filter_size,
+	.get_rx_vlan_filter_size	= macvtap_get_rx_vlan_filter_size,
+	.fill_rx_addr_filter		= macvtap_fill_rx_addr_filter,
+	.fill_rx_vlan_filter		= macvtap_fill_rx_vlan_filter,
 };
 
 

RE: [net-next-2.6 PATCH 0/8 RFC v2] macvlan: MAC Address filtering support for passthru mode

From: Rose, Gregory V <hidden>
Date: 2011-10-19 21:06:42

-----Original Message-----
From: netdev-owner@vger.kernel.org [mailto:netdev-owner@vger.kernel.org]
On Behalf Of Roopa Prabhu
Sent: Tuesday, October 18, 2011 11:26 PM
To: netdev@vger.kernel.org
Cc: sri@us.ibm.com; dragos.tatulea@gmail.com; arnd@arndb.de;
kvm@vger.kernel.org; mst@redhat.com; davem@davemloft.net;
mchan@broadcom.com; dwang2@cisco.com; shemminger@vyatta.com;
eric.dumazet@gmail.com; kaber@trash.net; benve@cisco.com
Subject: [net-next-2.6 PATCH 0/8 RFC v2] macvlan: MAC Address filtering
support for passthru mode
 
[snip...]

	Note: The choice of rtnl_link_ops was because I saw the use case for
	this in virtual devices that need  to do filtering in sw like macvlan
	and tun. Hw devices usually have filtering in hw with netdev->uc and
	mc lists to indicate active filters. But I can move from rtnl_link_ops
	to netdev_ops if that is the preferred way to go and if there is a
	need to support this interface on all kinds of interfaces.
	Please suggest.
I'm still digesting the rest of the RFC patches but I did want to quickly jump
in and push for adding this support in netdev_ops.  I would like to see these
features available in more devices than just macvtap and macvlan.  I can conceive
of use cases for multiple HW MAC and VLAN filters for a VF device that isn't
owned by a macvlan/macvtap interface and only has netdev_ops support.  In this
case it would be necessary to program the filters directly to the VF device
interface or PF interface (or lowerdev as you refer to it) instead of going
through macvlan/macvtap.

This work dovetails nicely with some work I've been doing and I'd be very interested
in helping move this forward if we could work out the details that would allow support
of the features we (and the community) require.

- Greg Rose
LAN Access Division
Intel Corp.

Re: [net-next-2.6 PATCH 0/8 RFC v2] macvlan: MAC Address filtering support for passthru mode

From: Roopa Prabhu <hidden>
Date: 2011-10-19 22:30:18



On 10/19/11 2:06 PM, "Rose, Gregory V" [off-list ref] wrote:
quoted
-----Original Message-----
From: netdev-owner@vger.kernel.org [mailto:netdev-owner@vger.kernel.org]
On Behalf Of Roopa Prabhu
Sent: Tuesday, October 18, 2011 11:26 PM
To: netdev@vger.kernel.org
Cc: sri@us.ibm.com; dragos.tatulea@gmail.com; arnd@arndb.de;
kvm@vger.kernel.org; mst@redhat.com; davem@davemloft.net;
mchan@broadcom.com; dwang2@cisco.com; shemminger@vyatta.com;
eric.dumazet@gmail.com; kaber@trash.net; benve@cisco.com
Subject: [net-next-2.6 PATCH 0/8 RFC v2] macvlan: MAC Address filtering
support for passthru mode
 
[snip...]
quoted

Note: The choice of rtnl_link_ops was because I saw the use case for
this in virtual devices that need  to do filtering in sw like macvlan
and tun. Hw devices usually have filtering in hw with netdev->uc and
mc lists to indicate active filters. But I can move from rtnl_link_ops
to netdev_ops if that is the preferred way to go and if there is a
need to support this interface on all kinds of interfaces.
Please suggest.
I'm still digesting the rest of the RFC patches but I did want to quickly jump
in and push for adding this support in netdev_ops.  I would like to see these
features available in more devices than just macvtap and macvlan.  I can
conceive
of use cases for multiple HW MAC and VLAN filters for a VF device that isn't
owned by a macvlan/macvtap interface and only has netdev_ops support.  In this
case it would be necessary to program the filters directly to the VF device
interface or PF interface (or lowerdev as you refer to it) instead of going
through macvlan/macvtap.

This work dovetails nicely with some work I've been doing and I'd be very
interested
in helping move this forward if we could work out the details that would allow
support
of the features we (and the community) require.
Great. Thanks. I will definitely be interested to get this patch working for
any other use case you have.

Moving the ops to netdev should be trivial. You probably want the ops to
work on the VF via the PF, like the existing ndo_set_vf_mac etc.
Yes, lets work out the details and I can move this to netdev->ops. Let me
know.

Thanks,
Roopa

RE: [net-next-2.6 PATCH 0/8 RFC v2] macvlan: MAC Address filtering support for passthru mode

From: Rose, Gregory V <hidden>
Date: 2011-10-20 20:43:39

-----Original Message-----
From: Roopa Prabhu [mailto:roprabhu@cisco.com]
Sent: Wednesday, October 19, 2011 3:30 PM
To: Rose, Gregory V; netdev@vger.kernel.org
Cc: sri@us.ibm.com; dragos.tatulea@gmail.com; arnd@arndb.de;
kvm@vger.kernel.org; mst@redhat.com; davem@davemloft.net;
mchan@broadcom.com; dwang2@cisco.com; shemminger@vyatta.com;
eric.dumazet@gmail.com; kaber@trash.net; benve@cisco.com
Subject: Re: [net-next-2.6 PATCH 0/8 RFC v2] macvlan: MAC Address
filtering support for passthru mode




On 10/19/11 2:06 PM, "Rose, Gregory V" [off-list ref] wrote:
quoted
quoted
-----Original Message-----
From: netdev-owner@vger.kernel.org [mailto:netdev-
owner@vger.kernel.org]
quoted
quoted
On Behalf Of Roopa Prabhu
Sent: Tuesday, October 18, 2011 11:26 PM
To: netdev@vger.kernel.org
Cc: sri@us.ibm.com; dragos.tatulea@gmail.com; arnd@arndb.de;
kvm@vger.kernel.org; mst@redhat.com; davem@davemloft.net;
mchan@broadcom.com; dwang2@cisco.com; shemminger@vyatta.com;
eric.dumazet@gmail.com; kaber@trash.net; benve@cisco.com
Subject: [net-next-2.6 PATCH 0/8 RFC v2] macvlan: MAC Address filtering
support for passthru mode
[snip...]
quoted

Note: The choice of rtnl_link_ops was because I saw the use case for
this in virtual devices that need  to do filtering in sw like macvlan
and tun. Hw devices usually have filtering in hw with netdev->uc and
mc lists to indicate active filters. But I can move from rtnl_link_ops
to netdev_ops if that is the preferred way to go and if there is a
need to support this interface on all kinds of interfaces.
Please suggest.
I'm still digesting the rest of the RFC patches but I did want to
quickly jump
quoted
in and push for adding this support in netdev_ops.  I would like to see
these
quoted
features available in more devices than just macvtap and macvlan.  I can
conceive
of use cases for multiple HW MAC and VLAN filters for a VF device that
isn't
quoted
owned by a macvlan/macvtap interface and only has netdev_ops support.
In this
quoted
case it would be necessary to program the filters directly to the VF
device
quoted
interface or PF interface (or lowerdev as you refer to it) instead of
going
quoted
through macvlan/macvtap.

This work dovetails nicely with some work I've been doing and I'd be
very
quoted
interested
in helping move this forward if we could work out the details that would
allow
quoted
support
of the features we (and the community) require.
Great. Thanks. I will definitely be interested to get this patch working
for
any other use case you have.

Moving the ops to netdev should be trivial. You probably want the ops to
work on the VF via the PF, like the existing ndo_set_vf_mac etc.
That is correct, so we would need to add some way to pass the VF number to the op.
In addition, there are use cases for multiple MAC address filters for the Physical
Function (PF) so we would like to be able to identify to the netdev op that it is
supposed to perform the action on the PF filters instead of a VF.

An example of this would be when an administrator has created some number of VFs
for a given PF but is also running the PF in bridged (i.e. promiscuous) mode so that it
can support purely SW emulated network connections in some VMs that have low network
latency and bandwidth requirements while reserving the VFs for VMs that require the low latency, high throughput that directly assigned VFs can provide.  In this case an
emulated SW interface in a VM is unable to properly communicate with VFs on the same
PF because the emulated SW interface's MAC address isn't programmed into the HW filters
on the PF.  If we could use this op to program the MAC address and VLAN filters of
the emulated SW interfaces into the PF HW a VF could then properly communicate across
the NIC's internal VEB to the emulated SW interfaces.
Yes, lets work out the details and I can move this to netdev->ops. Let me
know.
I think essentially if you could add some parameter to the ops to specify whether it
is addressing a VF or the PF and then if it is a VF further specify the VF number we
would be very close to addressing the requirements of many valuable use cases in
addition to the ones you have identified in your RFC.

Does that sound reasonable?

Thanks,

- Greg

RE: [net-next-2.6 PATCH 0/8 RFC v2] macvlan: MAC Address filtering support for passthru mode

From: Rose, Gregory V <hidden>
Date: 2011-10-20 20:47:22

-----Original Message-----
From: netdev-owner@vger.kernel.org [mailto:netdev-owner@vger.kernel.org]
On Behalf Of Rose, Gregory V
Sent: Thursday, October 20, 2011 1:44 PM
To: Roopa Prabhu; netdev@vger.kernel.org
Cc: sri@us.ibm.com; dragos.tatulea@gmail.com; arnd@arndb.de;
kvm@vger.kernel.org; mst@redhat.com; davem@davemloft.net;
mchan@broadcom.com; dwang2@cisco.com; shemminger@vyatta.com;
eric.dumazet@gmail.com; kaber@trash.net; benve@cisco.com
Subject: RE: [net-next-2.6 PATCH 0/8 RFC v2] macvlan: MAC Address
filtering support for passthru mode
quoted
-----Original Message-----
From: Roopa Prabhu [mailto:roprabhu@cisco.com]
Sent: Wednesday, October 19, 2011 3:30 PM
To: Rose, Gregory V; netdev@vger.kernel.org
Cc: sri@us.ibm.com; dragos.tatulea@gmail.com; arnd@arndb.de;
kvm@vger.kernel.org; mst@redhat.com; davem@davemloft.net;
mchan@broadcom.com; dwang2@cisco.com; shemminger@vyatta.com;
eric.dumazet@gmail.com; kaber@trash.net; benve@cisco.com
Subject: Re: [net-next-2.6 PATCH 0/8 RFC v2] macvlan: MAC Address
filtering support for passthru mode




On 10/19/11 2:06 PM, "Rose, Gregory V" [off-list ref] wrote:
quoted
quoted
-----Original Message-----
From: netdev-owner@vger.kernel.org [mailto:netdev-
owner@vger.kernel.org]
quoted
quoted
On Behalf Of Roopa Prabhu
Sent: Tuesday, October 18, 2011 11:26 PM
To: netdev@vger.kernel.org
Cc: sri@us.ibm.com; dragos.tatulea@gmail.com; arnd@arndb.de;
kvm@vger.kernel.org; mst@redhat.com; davem@davemloft.net;
mchan@broadcom.com; dwang2@cisco.com; shemminger@vyatta.com;
eric.dumazet@gmail.com; kaber@trash.net; benve@cisco.com
Subject: [net-next-2.6 PATCH 0/8 RFC v2] macvlan: MAC Address
filtering
quoted
quoted
quoted
support for passthru mode
[snip...]
quoted

Note: The choice of rtnl_link_ops was because I saw the use case for
this in virtual devices that need  to do filtering in sw like macvlan
and tun. Hw devices usually have filtering in hw with netdev->uc and
mc lists to indicate active filters. But I can move from
rtnl_link_ops
quoted
quoted
quoted
to netdev_ops if that is the preferred way to go and if there is a
need to support this interface on all kinds of interfaces.
Please suggest.
I'm still digesting the rest of the RFC patches but I did want to
quickly jump
quoted
in and push for adding this support in netdev_ops.  I would like to
see
quoted
these
quoted
features available in more devices than just macvtap and macvlan.  I
can
quoted
quoted
conceive
of use cases for multiple HW MAC and VLAN filters for a VF device that
isn't
quoted
owned by a macvlan/macvtap interface and only has netdev_ops support.
In this
quoted
case it would be necessary to program the filters directly to the VF
device
quoted
interface or PF interface (or lowerdev as you refer to it) instead of
going
quoted
through macvlan/macvtap.

This work dovetails nicely with some work I've been doing and I'd be
very
quoted
interested
in helping move this forward if we could work out the details that
would
quoted
allow
quoted
support
of the features we (and the community) require.
Great. Thanks. I will definitely be interested to get this patch working
for
any other use case you have.

Moving the ops to netdev should be trivial. You probably want the ops to
work on the VF via the PF, like the existing ndo_set_vf_mac etc.
That is correct, so we would need to add some way to pass the VF number to
the op.
In addition, there are use cases for multiple MAC address filters for the
Physical
Function (PF) so we would like to be able to identify to the netdev op
that it is
supposed to perform the action on the PF filters instead of a VF.

An example of this would be when an administrator has created some number of VFs
for a given PF but is also running the PF in bridged (i.e. promiscuous)mode so
that it can support purely SW emulated network connections in some VMs that have
low network latency and bandwidth requirements while reserving the VFs for VMs that
  ^^^
That should be "no", not low...

- Greg

Re: [net-next-2.6 PATCH 0/8 RFC v2] macvlan: MAC Address filtering support for passthru mode

From: Roopa Prabhu <hidden>
Date: 2011-10-20 21:06:51



On 10/20/11 1:43 PM, "Rose, Gregory V" [off-list ref] wrote:
quoted
-----Original Message-----
From: Roopa Prabhu [mailto:roprabhu@cisco.com]
Sent: Wednesday, October 19, 2011 3:30 PM
To: Rose, Gregory V; netdev@vger.kernel.org
Cc: sri@us.ibm.com; dragos.tatulea@gmail.com; arnd@arndb.de;
kvm@vger.kernel.org; mst@redhat.com; davem@davemloft.net;
mchan@broadcom.com; dwang2@cisco.com; shemminger@vyatta.com;
eric.dumazet@gmail.com; kaber@trash.net; benve@cisco.com
Subject: Re: [net-next-2.6 PATCH 0/8 RFC v2] macvlan: MAC Address
filtering support for passthru mode




On 10/19/11 2:06 PM, "Rose, Gregory V" [off-list ref] wrote:
quoted
quoted
-----Original Message-----
From: netdev-owner@vger.kernel.org [mailto:netdev-
owner@vger.kernel.org]
quoted
quoted
On Behalf Of Roopa Prabhu
Sent: Tuesday, October 18, 2011 11:26 PM
To: netdev@vger.kernel.org
Cc: sri@us.ibm.com; dragos.tatulea@gmail.com; arnd@arndb.de;
kvm@vger.kernel.org; mst@redhat.com; davem@davemloft.net;
mchan@broadcom.com; dwang2@cisco.com; shemminger@vyatta.com;
eric.dumazet@gmail.com; kaber@trash.net; benve@cisco.com
Subject: [net-next-2.6 PATCH 0/8 RFC v2] macvlan: MAC Address filtering
support for passthru mode
[snip...]
quoted

Note: The choice of rtnl_link_ops was because I saw the use case for
this in virtual devices that need  to do filtering in sw like macvlan
and tun. Hw devices usually have filtering in hw with netdev->uc and
mc lists to indicate active filters. But I can move from rtnl_link_ops
to netdev_ops if that is the preferred way to go and if there is a
need to support this interface on all kinds of interfaces.
Please suggest.
I'm still digesting the rest of the RFC patches but I did want to
quickly jump
quoted
in and push for adding this support in netdev_ops.  I would like to see
these
quoted
features available in more devices than just macvtap and macvlan.  I can
conceive
of use cases for multiple HW MAC and VLAN filters for a VF device that
isn't
quoted
owned by a macvlan/macvtap interface and only has netdev_ops support.
In this
quoted
case it would be necessary to program the filters directly to the VF
device
quoted
interface or PF interface (or lowerdev as you refer to it) instead of
going
quoted
through macvlan/macvtap.

This work dovetails nicely with some work I've been doing and I'd be
very
quoted
interested
in helping move this forward if we could work out the details that would
allow
quoted
support
of the features we (and the community) require.
Great. Thanks. I will definitely be interested to get this patch working
for
any other use case you have.

Moving the ops to netdev should be trivial. You probably want the ops to
work on the VF via the PF, like the existing ndo_set_vf_mac etc.
That is correct, so we would need to add some way to pass the VF number to the
op.
In addition, there are use cases for multiple MAC address filters for the
Physical
Function (PF) so we would like to be able to identify to the netdev op that it
is
supposed to perform the action on the PF filters instead of a VF.

An example of this would be when an administrator has created some number of
VFs
for a given PF but is also running the PF in bridged (i.e. promiscuous) mode
so that it
can support purely SW emulated network connections in some VMs that have low
network
latency and bandwidth requirements while reserving the VFs for VMs that
require the low latency, high throughput that directly assigned VFs can
provide.  In this case an
emulated SW interface in a VM is unable to properly communicate with VFs on
the same
PF because the emulated SW interface's MAC address isn't programmed into the
HW filters
on the PF.  If we could use this op to program the MAC address and VLAN
filters of
the emulated SW interfaces into the PF HW a VF could then properly communicate
across
the NIC's internal VEB to the emulated SW interfaces.
quoted
Yes, lets work out the details and I can move this to netdev->ops. Let me
know.
I think essentially if you could add some parameter to the ops to specify
whether it
is addressing a VF or the PF and then if it is a VF further specify the VF
number we
would be very close to addressing the requirements of many valuable use cases
in
addition to the ones you have identified in your RFC.

Does that sound reasonable?
Thanks for the details Greg. Sounds good. I will change it to provide netdev
ops with a vf argument and respin.

Thanks,
Roopa

Re: [net-next-2.6 PATCH 0/8 RFC v2] macvlan: MAC Address filtering support for passthru mode

From: "Michael S. Tsirkin" <mst@redhat.com>
Date: 2011-10-24 05:46:20

On Tue, Oct 18, 2011 at 11:25:54PM -0700, Roopa Prabhu wrote:
v1 version of this RFC patch was posted at http://www.spinics.net/lists/netdev/msg174245.html

Today macvtap used in virtualized environment does not have support to 
propagate MAC, VLAN and interface flags from guest to lowerdev.
Which means to be able to register additional VLANs, unicast and multicast
addresses or change pkt filter flags in the guest, the lowerdev has to be
put in promisocous mode. Today the only macvlan mode that supports this is 
the PASSTHRU mode and it puts the lower dev in promiscous mode.

PASSTHRU mode was added primarily for the SRIOV usecase. In PASSTHRU mode 
there is a 1-1 mapping between macvtap and physical NIC or VF.

There are two problems with putting the lowerdev in promiscous mode (ie SRIOV 
VF's):
	- Some SRIOV cards dont support promiscous mode today (Thread on Intel
	driver indicates that http://lists.openwall.net/netdev/2011/09/27/6)
	- For the SRIOV NICs that support it, Putting the lowerdev in 
	promiscous mode leads to additional traffic being sent up to the 
	guest virtio-net to filter result in extra overheads.
	
Both the above problems can be solved by offloading filtering to the 
lowerdev hw. ie lowerdev does not need to be in promiscous mode as 
long as the guest filters are passed down to the lowerdev. 

This patch basically adds the infrastructure to set and get MAC and VLAN 
filters on an interface via rtnetlink. And adds support in macvlan and macvtap
to allow set and get filter operations.
Looks sane to me. Some minor comments below.
Earlier version of this patch provided the TUNSETTXFILTER macvtap interface 
for setting address filtering. In response to feedback, This version 
introduces a netlink interface for the same.

Response to some of the questions raised during v1:

- Netlink interface:
	This patch provides the following netlink interface to set mac and vlan
	filters :
	[IFLA_RX_FILTER] = {
		[IFLA_ADDR_FILTER] = {
			[IFLA_ADDR_FILTER_FLAGS]
			[IFLA_ADDR_FILTER_UC_LIST] = {
				[IFLA_ADDR_LIST_ENTRY]
			}
			[IFLA_ADDR_FILTER_MC_LIST] = {
				[IFLA_ADDR_LIST_ENTRY]
			}
		}
		[IFLA_VLAN_FILTER] = {
			[IFLA_VLAN_BITMAP]
		}
	}

	Note: The IFLA_VLAN_FILTER is a nested attribute and contains only 
	IFLA_VLAN_BITMAP today. The idea is that the IFLA_VLAN_FILTER can
	be extended tomorrow to use a vlan list option if some implementations 
	prefer a list instead. 

	And it provides the following rtnl_link_ops to set/get MAC/VLAN filters:

       int                     (*set_rx_addr_filter)(struct net_device *dev,
                                               struct nlattr *tb[]);
       int                     (*set_rx_vlan_filter)(struct net_device *dev,
                                                struct nlattr *tb[]);
       size_t                  (*get_rx_addr_filter_size)(const struct 
					net_device *dev);
       size_t                  (*get_rx_vlan_filter_size)(const struct 
					net_device *dev);
       int                     (*fill_rx_addr_filter)(struct sk_buff *skb,
                                                const struct net_device *dev);
       int                     (*fill_rx_vlan_filter)(struct sk_buff *skb,
                                                const struct net_device *dev);


	Note: The choice of rtnl_link_ops was because I saw the use case for 
	this in virtual devices that need  to do filtering in sw like macvlan 
	and tun. Hw devices usually have filtering in hw with netdev->uc and 
	mc lists to indicate active filters. But I can move from rtnl_link_ops 
	to netdev_ops if that is the preferred way to go and if there is a 
	need to support this interface on all kinds of interfaces. 
	Please suggest.
	
- Protection against address spoofing:
	- This patch adds filtering support only for macvtap PASSTHRU 
	Mode. PASSTHRU mode is used mainly with SRIOV VF's. And SRIOV VF's 
	come with anti mac/vlan spoofing support. (Recently added 
	IFLA_VF_SPOOFCHK). In 802.1Qbh case the port profile has a knob to
	enable/disable anti spoof check. Lowerdevice drivers also enforce limits
	on the number of address registrations allowed.

- Support for multiqueue devices: Enable filtering on individual queues (?):
	AFAIK, there is no netdev interface to install per queue hw 
	filters for a multi queue interface. And also I dont know of any hw 
	that provides an interface to set hw filters on a per queue basis.
VMDq hardware would support this, no?
	A multi queue device appears as a single lowerdev (ie netdev) and
	uses the same uc and mc lists to setup unicast and multicast hw filters.
	So i dont see a huge problem with this patch coming in the way for
	multi queue devices.

- Support for non-PASSTHRU mode:
	I started implementing this. But there are a couple of problems.	
	- The lowerdev may not be a SRIOV VF and may not have 
	anti spoof capability
Anti-spoofing a really a separate feature, isn't it?
	- Today, in non-PASSTHRU cases macvlan_handle_frame assumes that 
	every macvlan device on top of the lowerdev has a single unique mac.
	And the macvlans are hashed on that single mac address. 
	To support filtering for non-PASSTHRU mode in addition to this 
	patch the following needs to be done:
		- non-passthru mode with a single macvlan over a lower dev
		can be treated as PASSTHRU case
		- For non-PASSTHRU mode with multiple macvlans over a single 
		lower dev:  
			- Multiple unicast mac's now need to be hashed to the 
			same macvlan device. The macvlan hash needs to change 
			for lookup based on any one of the multiple unicast 
			addresses a macvlan is interested in
			- We need to consider vlans during the lookup too
			- So the macvlan device hash needs to hash on both mac 
			and vlan
It might be useful to expose the filters to the device.
		- But the support for filtering in non-PASSTHRU mode can be 
		built on this patch

Agree, this can be added gradually.
This patch series implements the following 
01/8 rtnetlink: Netlink interface for setting MAC and VLAN filters
02/8 rtnetlink: Add rtnl link operations for MAC address and VLAN filtering
03/8 rtnetlink: Add support to set MAC/VLAN filters
04/8 rtnetlink: Add support to get MAC/VLAN filters
05/8 macvlan: Add support to set MAC/VLAN filter rtnl link operations
06/8 macvlan: Add support to get MAC/VLAN filter rtnl link operations
07/8 macvtap: Add support to set MAC/VLAN filter rtnl link operations
08/8 macvtap: Add support to get MAC/VLAN filter rtnl link operations

Please comment. Thanks.

Signed-off-by: Roopa Prabhu <redacted>
Signed-off-by: Christian Benvenuti <redacted>
Signed-off-by: David Wang <redacted>

Re: [net-next-2.6 PATCH 8/8 RFC v2] macvtap: Add support to get MAC/VLAN filter rtnl link operations

From: "Michael S. Tsirkin" <mst@redhat.com>
Date: 2011-10-24 05:56:34

On Tue, Oct 18, 2011 at 11:26:36PM -0700, Roopa Prabhu wrote:
quoted hunk
From: Roopa Prabhu <redacted>

This patch adds support to get MAC and VLAN filter rtnl_link_ops
on a macvtap interface. It adds support for get_rx_addr_filter_size,
get_rx_vlan_filter_size, fill_rx_addr_filter and fill_rx_vlan_filter
rtnl link operations. Calls equivalent macvlan operations.

Signed-off-by: Roopa Prabhu <redacted>
Signed-off-by: Christian Benvenuti <redacted>
Signed-off-by: David Wang <redacted>
---
 drivers/net/macvtap.c |   27 +++++++++++++++++++++++++++
 1 files changed, 27 insertions(+), 0 deletions(-)

diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c
index 8a2cb59..9b40de7 100644
--- a/drivers/net/macvtap.c
+++ b/drivers/net/macvtap.c
@@ -285,6 +285,29 @@ static int macvtap_set_rx_vlan_filter(struct net_device *dev,
 	return macvlan_set_rx_vlan_filter(dev, tb);
 }
 
+static int macvtap_fill_rx_addr_filter(struct sk_buff *skb,
+	const struct net_device *dev)
+{
+	return macvlan_fill_rx_addr_filter(skb, dev);
+}
+
+static int macvtap_fill_rx_vlan_filter(struct sk_buff *skb,
+	const struct net_device *dev)
+{
+	return macvlan_fill_rx_vlan_filter(skb, dev);
+}
+
+static size_t macvtap_get_rx_addr_filter_size(const struct net_device *dev)
+{
+	return macvlan_get_rx_addr_filter_size(dev);
+}
+
+static size_t macvtap_get_rx_vlan_filter_size(const struct net_device *dev)
+{
+	return macvlan_get_rx_vlan_filter_size(dev);
+}
So why do we need the above wrappers? Can't use macvlanXXX directly?
+
+
don't add double emoty lines pls.
quoted hunk
 static int macvtap_newlink(struct net *src_net,
 			   struct net_device *dev,
 			   struct nlattr *tb[],
@@ -335,6 +358,10 @@ static struct rtnl_link_ops macvtap_link_ops __read_mostly = {
 	.dellink			= macvtap_dellink,
 	.set_rx_addr_filter		= macvtap_set_rx_addr_filter,
 	.set_rx_vlan_filter		= macvtap_set_rx_vlan_filter,
+	.get_rx_addr_filter_size	= macvtap_get_rx_addr_filter_size,
+	.get_rx_vlan_filter_size	= macvtap_get_rx_vlan_filter_size,
+	.fill_rx_addr_filter		= macvtap_fill_rx_addr_filter,
+	.fill_rx_vlan_filter		= macvtap_fill_rx_vlan_filter,
 };
 
 

Re: [net-next-2.6 PATCH 7/8 RFC v2] macvtap: Add support to set MAC/VLAN filter rtnl link operations

From: "Michael S. Tsirkin" <mst@redhat.com>
Date: 2011-10-24 05:57:25

On Tue, Oct 18, 2011 at 11:26:30PM -0700, Roopa Prabhu wrote:
quoted hunk
From: Roopa Prabhu <redacted>

This patch adds support to set MAC and VLAN filter rtnl_link_ops
on a macvtap interface. It adds support for set_rx_addr_filter and
set_rx_vlan_filter rtnl link operations. These operations inturn call the
equivalent operations defined in macvlan

Signed-off-by: Roopa Prabhu <redacted>
Signed-off-by: Christian Benvenuti <redacted>
Signed-off-by: David Wang <redacted>
---
 drivers/net/macvtap.c |   22 ++++++++++++++++++----
 1 files changed, 18 insertions(+), 4 deletions(-)

diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c
index 3da5578..8a2cb59 100644
--- a/drivers/net/macvtap.c
+++ b/drivers/net/macvtap.c
@@ -273,6 +273,18 @@ static int macvtap_receive(struct sk_buff *skb)
 	return macvtap_forward(skb->dev, skb);
 }
 
+static int macvtap_set_rx_addr_filter(struct net_device *dev,
+	struct nlattr *tb[])
+{
+	return macvlan_set_rx_addr_filter(dev, tb);
+}
+
+static int macvtap_set_rx_vlan_filter(struct net_device *dev,
+	struct nlattr *tb[])
+{
+	return macvlan_set_rx_vlan_filter(dev, tb);
+}
+
 static int macvtap_newlink(struct net *src_net,
 			   struct net_device *dev,
 			   struct nlattr *tb[],

Can use macvlanXXX directly here? Why wrap it?
quoted hunk
@@ -317,10 +329,12 @@ static void macvtap_setup(struct net_device *dev)
 }
 
 static struct rtnl_link_ops macvtap_link_ops __read_mostly = {
-	.kind		= "macvtap",
-	.setup		= macvtap_setup,
-	.newlink	= macvtap_newlink,
-	.dellink	= macvtap_dellink,
+	.kind				= "macvtap",
+	.setup				= macvtap_setup,
+	.newlink			= macvtap_newlink,
+	.dellink			= macvtap_dellink,
+	.set_rx_addr_filter		= macvtap_set_rx_addr_filter,
+	.set_rx_vlan_filter		= macvtap_set_rx_vlan_filter,
 };
 
 

Re: [net-next-2.6 PATCH 0/8 RFC v2] macvlan: MAC Address filtering support for passthru mode

From: Roopa Prabhu <hidden>
Date: 2011-10-24 18:15:10

On 10/23/11 10:47 PM, "Michael S. Tsirkin" [off-list ref] wrote:
On Tue, Oct 18, 2011 at 11:25:54PM -0700, Roopa Prabhu wrote:
quoted
v1 version of this RFC patch was posted at
http://www.spinics.net/lists/netdev/msg174245.html

Today macvtap used in virtualized environment does not have support to
propagate MAC, VLAN and interface flags from guest to lowerdev.
Which means to be able to register additional VLANs, unicast and multicast
addresses or change pkt filter flags in the guest, the lowerdev has to be
put in promisocous mode. Today the only macvlan mode that supports this is
the PASSTHRU mode and it puts the lower dev in promiscous mode.

PASSTHRU mode was added primarily for the SRIOV usecase. In PASSTHRU mode
there is a 1-1 mapping between macvtap and physical NIC or VF.

There are two problems with putting the lowerdev in promiscous mode (ie SRIOV
VF's):
- Some SRIOV cards dont support promiscous mode today (Thread on Intel
driver indicates that http://lists.openwall.net/netdev/2011/09/27/6)
- For the SRIOV NICs that support it, Putting the lowerdev in
promiscous mode leads to additional traffic being sent up to the
guest virtio-net to filter result in extra overheads.

Both the above problems can be solved by offloading filtering to the
lowerdev hw. ie lowerdev does not need to be in promiscous mode as
long as the guest filters are passed down to the lowerdev.

This patch basically adds the infrastructure to set and get MAC and VLAN
filters on an interface via rtnetlink. And adds support in macvlan and
macvtap
to allow set and get filter operations.
Looks sane to me. Some minor comments below.
quoted
Earlier version of this patch provided the TUNSETTXFILTER macvtap interface
for setting address filtering. In response to feedback, This version
introduces a netlink interface for the same.

Response to some of the questions raised during v1:

- Netlink interface:
This patch provides the following netlink interface to set mac and vlan
filters :
[IFLA_RX_FILTER] = {
[IFLA_ADDR_FILTER] = {
[IFLA_ADDR_FILTER_FLAGS]
[IFLA_ADDR_FILTER_UC_LIST] = {
[IFLA_ADDR_LIST_ENTRY]
}
[IFLA_ADDR_FILTER_MC_LIST] = {
[IFLA_ADDR_LIST_ENTRY]
}
}
[IFLA_VLAN_FILTER] = {
[IFLA_VLAN_BITMAP]
}
}

Note: The IFLA_VLAN_FILTER is a nested attribute and contains only
IFLA_VLAN_BITMAP today. The idea is that the IFLA_VLAN_FILTER can
be extended tomorrow to use a vlan list option if some implementations
prefer a list instead.

And it provides the following rtnl_link_ops to set/get MAC/VLAN filters:

       int                     (*set_rx_addr_filter)(struct net_device *dev,
                                               struct nlattr *tb[]);
       int                     (*set_rx_vlan_filter)(struct net_device *dev,
                                                struct nlattr *tb[]);
       size_t                  (*get_rx_addr_filter_size)(const struct
net_device *dev);
       size_t                  (*get_rx_vlan_filter_size)(const struct
net_device *dev);
       int                     (*fill_rx_addr_filter)(struct sk_buff *skb,
                                                const struct net_device
*dev);
       int                     (*fill_rx_vlan_filter)(struct sk_buff *skb,
                                                const struct net_device
*dev);


Note: The choice of rtnl_link_ops was because I saw the use case for
this in virtual devices that need  to do filtering in sw like macvlan
and tun. Hw devices usually have filtering in hw with netdev->uc and
mc lists to indicate active filters. But I can move from rtnl_link_ops
to netdev_ops if that is the preferred way to go and if there is a
need to support this interface on all kinds of interfaces.
Please suggest.

- Protection against address spoofing:
- This patch adds filtering support only for macvtap PASSTHRU
Mode. PASSTHRU mode is used mainly with SRIOV VF's. And SRIOV VF's
come with anti mac/vlan spoofing support. (Recently added
IFLA_VF_SPOOFCHK). In 802.1Qbh case the port profile has a knob to
enable/disable anti spoof check. Lowerdevice drivers also enforce limits
on the number of address registrations allowed.

- Support for multiqueue devices: Enable filtering on individual queues (?):
AFAIK, there is no netdev interface to install per queue hw
filters for a multi queue interface. And also I dont know of any hw
that provides an interface to set hw filters on a per queue basis.
VMDq hardware would support this, no?
Am not really sure. This patch uses netdev to pass filters to hw. And I
don't see any netdev infrastructure that would support per queue filters.
Maybe Greg (CC'ed) or anyone else from Intel can answer this.
Greg, michael had brought up this question during first version of these
patches as well. Will be nice to get the VMDq requirements for propagating
guest filters to hw clarified. Do you see any special VMDq nic requirement
we can cover in this patch. This is for VMDq queues directly connected to
guest nics. Thanks.

quoted
A multi queue device appears as a single lowerdev (ie netdev) and
uses the same uc and mc lists to setup unicast and multicast hw filters.
So i dont see a huge problem with this patch coming in the way for
multi queue devices.

- Support for non-PASSTHRU mode:
I started implementing this. But there are a couple of problems. 
- The lowerdev may not be a SRIOV VF and may not have
anti spoof capability
Anti-spoofing a really a separate feature, isn't it?
Yes that is correct. It really should not be a concern with implementing
support for non-PASSTHRU mode. The only intent of adding the above line was
that eventually we should probably think of supporting anti-spoof feature on
Non-sriov devices if they are accepting filters from the guest.
I think I will move the above line to some place else more appropriate in
the comment log instead of covering it as part of the non-passthru macvlan
implementation.
 
quoted
- Today, in non-PASSTHRU cases macvlan_handle_frame assumes that
every macvlan device on top of the lowerdev has a single unique mac.
And the macvlans are hashed on that single mac address.
To support filtering for non-PASSTHRU mode in addition to this
patch the following needs to be done:
- non-passthru mode with a single macvlan over a lower dev
can be treated as PASSTHRU case
- For non-PASSTHRU mode with multiple macvlans over a single
lower dev:  
- Multiple unicast mac's now need to be hashed to the
same macvlan device. The macvlan hash needs to change
for lookup based on any one of the multiple unicast
addresses a macvlan is interested in
- We need to consider vlans during the lookup too
- So the macvlan device hash needs to hash on both mac
and vlan
It might be useful to expose the filters to the device.
Yes
quoted
- But the support for filtering in non-PASSTHRU mode can be
built on this patch

Agree, this can be added gradually.
Ok thanks. Currently testing newer version of these patches, will post them
Sometime this week.

RE: [net-next-2.6 PATCH 0/8 RFC v2] macvlan: MAC Address filtering support for passthru mode

From: Rose, Gregory V <hidden>
Date: 2011-10-24 21:51:29

-----Original Message-----
From: netdev-owner@vger.kernel.org [mailto:netdev-owner@vger.kernel.org]
On Behalf Of Roopa Prabhu
Sent: Monday, October 24, 2011 11:15 AM
To: Michael S. Tsirkin
Cc: netdev@vger.kernel.org; sri@us.ibm.com; dragos.tatulea@gmail.com;
arnd@arndb.de; kvm@vger.kernel.org; davem@davemloft.net;
mchan@broadcom.com; dwang2@cisco.com; shemminger@vyatta.com;
eric.dumazet@gmail.com; kaber@trash.net; benve@cisco.com; Rose, Gregory V
Subject: Re: [net-next-2.6 PATCH 0/8 RFC v2] macvlan: MAC Address
filtering support for passthru mode

On 10/23/11 10:47 PM, "Michael S. Tsirkin" [off-list ref] wrote:
quoted
quoted
AFAIK, there is no netdev interface to install per queue hw
filters for a multi queue interface. And also I dont know of any hw
that provides an interface to set hw filters on a per queue basis.
VMDq hardware would support this, no?
Am not really sure. This patch uses netdev to pass filters to hw. And I
don't see any netdev infrastructure that would support per queue filters.
Maybe Greg (CC'ed) or anyone else from Intel can answer this.
Greg, michael had brought up this question during first version of these
patches as well. Will be nice to get the VMDq requirements for propagating
guest filters to hw clarified. Do you see any special VMDq nic requirement
we can cover in this patch. This is for VMDq queues directly connected to
guest nics. Thanks.
So far as I know there is no support for VMDq in the Linux kernel and while I know some folks have been working on it I can't really speak to that work or their plans.  Much would depend on the implementation.

For now it makes sense to me to get support for multiple MAC and VLAN filters per virtual function (or virtual nic) and it seems to me you're going in the right direction for this.  We'll have a look at your next set of patches and take it from there.

- Greg

Re: [net-next-2.6 PATCH 0/8 RFC v2] macvlan: MAC Address filtering support for passthru mode

From: "Michael S. Tsirkin" <mst@redhat.com>
Date: 2011-10-25 15:46:23

On Mon, Oct 24, 2011 at 11:15:05AM -0700, Roopa Prabhu wrote:
quoted
quoted
... And also I dont know of any hw
that provides an interface to set hw filters on a per queue basis.
VMDq hardware would support this, no?
Am not really sure. This patch uses netdev to pass filters to hw. And I
don't see any netdev infrastructure that would support per queue filters.
Sure. I was only saying that as far as I understand,
VMDq hardware does support this functionality.
Right, Greg?

-- 
MST

RE: [net-next-2.6 PATCH 0/8 RFC v2] macvlan: MAC Address filtering support for passthru mode

From: Rose, Gregory V <hidden>
Date: 2011-10-25 15:59:43

-----Original Message-----
From: Michael S. Tsirkin [mailto:mst@redhat.com]
Sent: Tuesday, October 25, 2011 8:46 AM
To: Roopa Prabhu
Cc: netdev@vger.kernel.org; sri@us.ibm.com; dragos.tatulea@gmail.com;
arnd@arndb.de; kvm@vger.kernel.org; davem@davemloft.net;
mchan@broadcom.com; dwang2@cisco.com; shemminger@vyatta.com;
eric.dumazet@gmail.com; kaber@trash.net; benve@cisco.com; Rose, Gregory V
Subject: Re: [net-next-2.6 PATCH 0/8 RFC v2] macvlan: MAC Address
filtering support for passthru mode

On Mon, Oct 24, 2011 at 11:15:05AM -0700, Roopa Prabhu wrote:
quoted
quoted
quoted
... And also I dont know of any hw
that provides an interface to set hw filters on a per queue basis.
VMDq hardware would support this, no?
Am not really sure. This patch uses netdev to pass filters to hw. And I
don't see any netdev infrastructure that would support per queue
filters.

Sure. I was only saying that as far as I understand,
VMDq hardware does support this functionality.
Right, Greg?
In the case of Intel HW yes.  I'll refrain from speaking for other HW vendors although I'm guessing it would be true in their cases also.  YMMV, caveat emptor, etc. etc.

- Greg
--
MST

Re: [net-next-2.6 PATCH 8/8 RFC v2] macvtap: Add support to get MAC/VLAN filter rtnl link operations

From: Roopa Prabhu <hidden>
Date: 2011-10-28 18:24:21



On 10/23/11 10:56 PM, "Michael S. Tsirkin" [off-list ref] wrote:
On Tue, Oct 18, 2011 at 11:26:36PM -0700, Roopa Prabhu wrote:
quoted
From: Roopa Prabhu <redacted>

This patch adds support to get MAC and VLAN filter rtnl_link_ops
on a macvtap interface. It adds support for get_rx_addr_filter_size,
get_rx_vlan_filter_size, fill_rx_addr_filter and fill_rx_vlan_filter
rtnl link operations. Calls equivalent macvlan operations.

Signed-off-by: Roopa Prabhu <redacted>
Signed-off-by: Christian Benvenuti <redacted>
Signed-off-by: David Wang <redacted>
---
 drivers/net/macvtap.c |   27 +++++++++++++++++++++++++++
 1 files changed, 27 insertions(+), 0 deletions(-)

diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c
index 8a2cb59..9b40de7 100644
--- a/drivers/net/macvtap.c
+++ b/drivers/net/macvtap.c
@@ -285,6 +285,29 @@ static int macvtap_set_rx_vlan_filter(struct net_device
*dev,
return macvlan_set_rx_vlan_filter(dev, tb);
 }
 
+static int macvtap_fill_rx_addr_filter(struct sk_buff *skb,
+ const struct net_device *dev)
+{
+ return macvlan_fill_rx_addr_filter(skb, dev);
+}
+
+static int macvtap_fill_rx_vlan_filter(struct sk_buff *skb,
+ const struct net_device *dev)
+{
+ return macvlan_fill_rx_vlan_filter(skb, dev);
+}
+
+static size_t macvtap_get_rx_addr_filter_size(const struct net_device *dev)
+{
+ return macvlan_get_rx_addr_filter_size(dev);
+}
+
+static size_t macvtap_get_rx_vlan_filter_size(const struct net_device *dev)
+{
+ return macvlan_get_rx_vlan_filter_size(dev);
+}
So why do we need the above wrappers? Can't use macvlanXXX directly?
I had followed the existing macvtap rtnl_link_ops convention here.
It seems cleaner this way. You can define the macvtap ops static and
Call equivalent macvlan functions from it if required. It  also gives you
flexibility in adding any macvtap specific stuff before or after you call
the macvlan equivalent function (like some of the macvtap rtnl link ops
already do today)

In any case this part and the below empty line error goes away in the new
version.

Thanks,
Roopa

quoted
+
+
don't add double emoty lines pls.
quoted
 static int macvtap_newlink(struct net *src_net,
  struct net_device *dev,
  struct nlattr *tb[],
@@ -335,6 +358,10 @@ static struct rtnl_link_ops macvtap_link_ops
__read_mostly = {
.dellink   = macvtap_dellink,
.set_rx_addr_filter  = macvtap_set_rx_addr_filter,
.set_rx_vlan_filter  = macvtap_set_rx_vlan_filter,
+ .get_rx_addr_filter_size = macvtap_get_rx_addr_filter_size,
+ .get_rx_vlan_filter_size = macvtap_get_rx_vlan_filter_size,
+ .fill_rx_addr_filter  = macvtap_fill_rx_addr_filter,
+ .fill_rx_vlan_filter  = macvtap_fill_rx_vlan_filter,
 };
 
 

RE: [net-next-2.6 PATCH 0/8 RFC v2] macvlan: MAC Address filtering support for passthru mode

From: Rose, Gregory V <hidden>
Date: 2011-11-08 18:31:35

-----Original Message-----
From: netdev-owner@vger.kernel.org [mailto:netdev-owner@vger.kernel.org]
On Behalf Of Roopa Prabhu
Sent: Tuesday, October 18, 2011 11:26 PM
To: netdev@vger.kernel.org
Cc: sri@us.ibm.com; dragos.tatulea@gmail.com; arnd@arndb.de;
kvm@vger.kernel.org; mst@redhat.com; davem@davemloft.net;
mchan@broadcom.com; dwang2@cisco.com; shemminger@vyatta.com;
eric.dumazet@gmail.com; kaber@trash.net; benve@cisco.com
Subject: [net-next-2.6 PATCH 0/8 RFC v2] macvlan: MAC Address filtering
support for passthru mode

v1 version of this RFC patch was posted at
http://www.spinics.net/lists/netdev/msg174245.html

Today macvtap used in virtualized environment does not have support to
propagate MAC, VLAN and interface flags from guest to lowerdev.
Which means to be able to register additional VLANs, unicast and multicast
addresses or change pkt filter flags in the guest, the lowerdev has to be
put in promisocous mode. Today the only macvlan mode that supports this is
the PASSTHRU mode and it puts the lower dev in promiscous mode.

PASSTHRU mode was added primarily for the SRIOV usecase. In PASSTHRU mode
there is a 1-1 mapping between macvtap and physical NIC or VF.

There are two problems with putting the lowerdev in promiscous mode (ie
SRIOV
VF's):
	- Some SRIOV cards dont support promiscous mode today (Thread on
Intel
	driver indicates that http://lists.openwall.net/netdev/2011/09/27/6)
	- For the SRIOV NICs that support it, Putting the lowerdev in
	promiscous mode leads to additional traffic being sent up to the
	guest virtio-net to filter result in extra overheads.

Both the above problems can be solved by offloading filtering to the
lowerdev hw. ie lowerdev does not need to be in promiscous mode as
long as the guest filters are passed down to the lowerdev.

This patch basically adds the infrastructure to set and get MAC and VLAN
filters on an interface via rtnetlink. And adds support in macvlan and
macvtap
to allow set and get filter operations.

Earlier version of this patch provided the TUNSETTXFILTER macvtap
interface
for setting address filtering. In response to feedback, This version
introduces a netlink interface for the same.

Response to some of the questions raised during v1:

- Netlink interface:
	This patch provides the following netlink interface to set mac and
vlan
	filters :
	[IFLA_RX_FILTER] = {
		[IFLA_ADDR_FILTER] = {
			[IFLA_ADDR_FILTER_FLAGS]
			[IFLA_ADDR_FILTER_UC_LIST] = {
				[IFLA_ADDR_LIST_ENTRY]
			}
			[IFLA_ADDR_FILTER_MC_LIST] = {
				[IFLA_ADDR_LIST_ENTRY]
			}
		}
		[IFLA_VLAN_FILTER] = {
			[IFLA_VLAN_BITMAP]
		}
	}

	Note: The IFLA_VLAN_FILTER is a nested attribute and contains only
	IFLA_VLAN_BITMAP today. The idea is that the IFLA_VLAN_FILTER can
	be extended tomorrow to use a vlan list option if some
implementations
	prefer a list instead.

	And it provides the following rtnl_link_ops to set/get MAC/VLAN
filters:

       int                     (*set_rx_addr_filter)(struct net_device
*dev,
                                               struct nlattr *tb[]);
       int                     (*set_rx_vlan_filter)(struct net_device
*dev,
                                                struct nlattr *tb[]);
       size_t                  (*get_rx_addr_filter_size)(const struct
					net_device *dev);
       size_t                  (*get_rx_vlan_filter_size)(const struct
					net_device *dev);
       int                     (*fill_rx_addr_filter)(struct sk_buff *skb,
                                                const struct net_device
*dev);
       int                     (*fill_rx_vlan_filter)(struct sk_buff *skb,
                                                const struct net_device
*dev);


	Note: The choice of rtnl_link_ops was because I saw the use case for
	this in virtual devices that need  to do filtering in sw like
macvlan
	and tun. Hw devices usually have filtering in hw with netdev->uc and
	mc lists to indicate active filters. But I can move from
rtnl_link_ops
	to netdev_ops if that is the preferred way to go and if there is a
	need to support this interface on all kinds of interfaces.
	Please suggest.

- Protection against address spoofing:
	- This patch adds filtering support only for macvtap PASSTHRU
	Mode. PASSTHRU mode is used mainly with SRIOV VF's. And SRIOV VF's
	come with anti mac/vlan spoofing support. (Recently added
	IFLA_VF_SPOOFCHK). In 802.1Qbh case the port profile has a knob to
	enable/disable anti spoof check. Lowerdevice drivers also enforce
limits
	on the number of address registrations allowed.

- Support for multiqueue devices: Enable filtering on individual queues
(?):
	AFAIK, there is no netdev interface to install per queue hw
	filters for a multi queue interface. And also I dont know of any hw
	that provides an interface to set hw filters on a per queue basis.
	A multi queue device appears as a single lowerdev (ie netdev) and
	uses the same uc and mc lists to setup unicast and multicast hw
filters.
	So i dont see a huge problem with this patch coming in the way for
	multi queue devices.

- Support for non-PASSTHRU mode:
	I started implementing this. But there are a couple of problems.
	- The lowerdev may not be a SRIOV VF and may not have
	anti spoof capability
	- Today, in non-PASSTHRU cases macvlan_handle_frame assumes that
	every macvlan device on top of the lowerdev has a single unique mac.
	And the macvlans are hashed on that single mac address.
	To support filtering for non-PASSTHRU mode in addition to this
	patch the following needs to be done:
		- non-passthru mode with a single macvlan over a lower dev
		can be treated as PASSTHRU case
		- For non-PASSTHRU mode with multiple macvlans over a single
		lower dev:
			- Multiple unicast mac's now need to be hashed to the
			same macvlan device. The macvlan hash needs to change
			for lookup based on any one of the multiple unicast
			addresses a macvlan is interested in
			- We need to consider vlans during the lookup too
			- So the macvlan device hash needs to hash on both mac
			and vlan
		- But the support for filtering in non-PASSTHRU mode can be
		built on this patch

This patch series implements the following
01/8 rtnetlink: Netlink interface for setting MAC and VLAN filters
02/8 rtnetlink: Add rtnl link operations for MAC address and VLAN
filtering
03/8 rtnetlink: Add support to set MAC/VLAN filters
04/8 rtnetlink: Add support to get MAC/VLAN filters
05/8 macvlan: Add support to set MAC/VLAN filter rtnl link operations
06/8 macvlan: Add support to get MAC/VLAN filter rtnl link operations
07/8 macvtap: Add support to set MAC/VLAN filter rtnl link operations
08/8 macvtap: Add support to get MAC/VLAN filter rtnl link operations

Please comment. Thanks.
I have finished my preliminary evaluation and testing of these RFC patches and find that the features that we would require are present and functional.  I haven't fully fleshed out the 'get' operations in my own driver yet but the 'set' routines are all doing what we need them to do.

Thanks for your work on this Roopa!

- Greg
Signed-off-by: Roopa Prabhu <redacted>
Signed-off-by: Christian Benvenuti <redacted>
Signed-off-by: David Wang <redacted>
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

RE: [net-next-2.6 PATCH 0/8 RFC v2] macvlan: MAC Address filtering support for passthru mode

From: Ben Hutchings <hidden>
Date: 2011-11-17 23:37:21

On Thu, 2011-10-20 at 13:43 -0700, Rose, Gregory V wrote:
quoted
-----Original Message-----
From: Roopa Prabhu [mailto:roprabhu@cisco.com]
[...]
quoted
Moving the ops to netdev should be trivial. You probably want the ops to
work on the VF via the PF, like the existing ndo_set_vf_mac etc.
That is correct, so we would need to add some way to pass the VF number to the op.
In addition, there are use cases for multiple MAC address filters for the Physical
Function (PF) so we would like to be able to identify to the netdev op that it is
supposed to perform the action on the PF filters instead of a VF.

An example of this would be when an administrator has created some number of VFs
for a given PF but is also running the PF in bridged (i.e. promiscuous) mode so that it
can support purely SW emulated network connections in some VMs that have low network
latency and bandwidth requirements while reserving the VFs for VMs that require the low latency, high throughput that directly assigned VFs can provide.  In this case an
emulated SW interface in a VM is unable to properly communicate with VFs on the same
PF because the emulated SW interface's MAC address isn't programmed into the HW filters
on the PF.  If we could use this op to program the MAC address and VLAN filters of
the emulated SW interfaces into the PF HW a VF could then properly communicate across
the NIC's internal VEB to the emulated SW interfaces.
[...]

This would also be good for Solarflare's VF plugin architecture.  The VF
driver works as a plugin for virtio or xen_netfront and can refuse
packets that need to be bridged to another (physically) local address.
The PF driver has to tell VFs what the local addresses are and currently
relies on some custom scripting to know about those extra addresses.

(No, none of that is upstream - I'm preparing for that now.)

Ben.

-- 
Ben Hutchings, Staff Engineer, Solarflare
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.

RE: [net-next-2.6 PATCH 0/8 RFC v2] macvlan: MAC Address filtering support for passthru mode

From: Ben Hutchings <hidden>
Date: 2011-11-17 23:43:41

On Tue, 2011-10-25 at 08:59 -0700, Rose, Gregory V wrote:
quoted
-----Original Message-----
From: Michael S. Tsirkin [mailto:mst@redhat.com]
Sent: Tuesday, October 25, 2011 8:46 AM
To: Roopa Prabhu
Cc: netdev@vger.kernel.org; sri@us.ibm.com; dragos.tatulea@gmail.com;
arnd@arndb.de; kvm@vger.kernel.org; davem@davemloft.net;
mchan@broadcom.com; dwang2@cisco.com; shemminger@vyatta.com;
eric.dumazet@gmail.com; kaber@trash.net; benve@cisco.com; Rose, Gregory V
Subject: Re: [net-next-2.6 PATCH 0/8 RFC v2] macvlan: MAC Address
filtering support for passthru mode

On Mon, Oct 24, 2011 at 11:15:05AM -0700, Roopa Prabhu wrote:
quoted
quoted
quoted
... And also I dont know of any hw
that provides an interface to set hw filters on a per queue basis.
VMDq hardware would support this, no?
Am not really sure. This patch uses netdev to pass filters to hw. And I
don't see any netdev infrastructure that would support per queue
filters.

Sure. I was only saying that as far as I understand,
VMDq hardware does support this functionality.
Right, Greg?
In the case of Intel HW yes.  I'll refrain from speaking for other HW
vendors although I'm guessing it would be true in their cases also.
YMMV, caveat emptor, etc. etc.
Current Solarflare hardware supports:
- RX MAC address filters for queue selection (steering), which can be
  combined with RSS (flow hashing)
- TX MAC address filters to prevent spoofing
Multiple filters can be associated with a single queue.

Ben.

-- 
Ben Hutchings, Staff Engineer, Solarflare
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help