* [NET 00/02]: MACVLAN driver
@ 2007-06-19 13:08 Patrick McHardy
2007-06-19 13:08 ` [ETHERNET 01/02]: Validate new address in eth_mac_addr Patrick McHardy
` (2 more replies)
0 siblings, 3 replies; 13+ messages in thread
From: Patrick McHardy @ 2007-06-19 13:08 UTC (permalink / raw)
To: davem; +Cc: netdev, Patrick McHardy
These patches add a rewritten version of Ben's macvlan driver, which
allows to create virtual ethernet devices. The underlying device is
put in promiscous mode and packets are demuxed based on MAC address.
It behaves similar to bridge devices in that packets are visible on
the real device before delivery to the macvlan driver. The driver
supports all features of the underlying device except VLAN
acceleration, this is currently very hard to support. I might look
into this in the future.
The main downside of this driver is that it adds another hook in
netif_receive_skb, unfortunately that is unavoidable. When not
compiled in the hook vanishes of course.
Usage is simple:
# ip link add link eth0 type macvlan
Will create a macvlan0 device with a random MAC address on top of
eth0. No iproute patches are required.
Please apply, thanks.
MAINTAINERS | 6 +
drivers/net/Kconfig | 10 +
drivers/net/Makefile | 1 +
drivers/net/macvlan.c | 468 ++++++++++++++++++++++++++++++++++++++++++++
include/linux/if_macvlan.h | 9 +
include/linux/netdevice.h | 2 +
net/core/dev.c | 26 +++
net/ethernet/eth.c | 3 +
8 files changed, 525 insertions(+), 0 deletions(-)
create mode 100644 drivers/net/macvlan.c
create mode 100644 include/linux/if_macvlan.h
Patrick McHardy (2):
[ETHERNET]: Validate new address in eth_mac_addr
[NET]: Add MACVLAN driver
^ permalink raw reply [flat|nested] 13+ messages in thread* [ETHERNET 01/02]: Validate new address in eth_mac_addr 2007-06-19 13:08 [NET 00/02]: MACVLAN driver Patrick McHardy @ 2007-06-19 13:08 ` Patrick McHardy 2007-06-19 13:08 ` [NET 02/02]: Add MACVLAN driver Patrick McHardy 2007-06-19 16:00 ` [NET 00/02]: " Stephen Hemminger 2 siblings, 0 replies; 13+ messages in thread From: Patrick McHardy @ 2007-06-19 13:08 UTC (permalink / raw) To: davem; +Cc: netdev, Patrick McHardy [ETHERNET]: Validate new address in eth_mac_addr Signed-off-by: Patrick McHardy <kaber@trash.net> --- commit c92ac42cd3badaf120e97223ac4798abf5226424 tree 824d080a4748fcd6f025bbe7b9466feee46e3303 parent 45da27ba265dba3c740c45d47f584c30d7066f82 author Patrick McHardy <kaber@trash.net> Mon, 18 Jun 2007 16:15:32 +0200 committer Patrick McHardy <kaber@trash.net> Mon, 18 Jun 2007 16:15:32 +0200 net/ethernet/eth.c | 3 +++ 1 files changed, 3 insertions(+), 0 deletions(-) diff --git a/net/ethernet/eth.c b/net/ethernet/eth.c index 0ac2524..9298a2c 100644 --- a/net/ethernet/eth.c +++ b/net/ethernet/eth.c @@ -266,8 +266,11 @@ void eth_header_cache_update(struct hh_cache *hh, struct net_device *dev, static int eth_mac_addr(struct net_device *dev, void *p) { struct sockaddr *addr = p; + if (netif_running(dev)) return -EBUSY; + if (!is_valid_ether_addr(addr->sa_data)) + return -EINVAL; memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); return 0; } ^ permalink raw reply related [flat|nested] 13+ messages in thread
* [NET 02/02]: Add MACVLAN driver 2007-06-19 13:08 [NET 00/02]: MACVLAN driver Patrick McHardy 2007-06-19 13:08 ` [ETHERNET 01/02]: Validate new address in eth_mac_addr Patrick McHardy @ 2007-06-19 13:08 ` Patrick McHardy 2007-06-19 16:00 ` [NET 00/02]: " Stephen Hemminger 2 siblings, 0 replies; 13+ messages in thread From: Patrick McHardy @ 2007-06-19 13:08 UTC (permalink / raw) To: davem; +Cc: netdev, Patrick McHardy [NET]: Add MACVLAN driver Add macvlan driver, which allows to create virtual ethernet devices based on MAC address. Signed-off-by: Patrick McHardy <kaber@trash.net> --- commit 890e2ae4ef5599ee34f280af4882f97c2dcfcb7b tree a41a8564a8add18a2095a18d4a3f1a2ce0c25997 parent c92ac42cd3badaf120e97223ac4798abf5226424 author Patrick McHardy <kaber@trash.net> Tue, 19 Jun 2007 15:01:06 +0200 committer Patrick McHardy <kaber@trash.net> Tue, 19 Jun 2007 15:01:06 +0200 MAINTAINERS | 6 + drivers/net/Kconfig | 10 + drivers/net/Makefile | 1 drivers/net/macvlan.c | 468 ++++++++++++++++++++++++++++++++++++++++++++ include/linux/if_macvlan.h | 9 + include/linux/netdevice.h | 2 net/core/dev.c | 26 ++ 7 files changed, 522 insertions(+), 0 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index 4c715a7..7d61360 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2320,6 +2320,12 @@ W: http://linuxwireless.org/ T: git kernel.org:/pub/scm/linux/kernel/git/jbenc/mac80211.git S: Maintained +MACVLAN DRIVER +P: Patrick McHardy +M: kaber@trash.net +L: netdev@vger.kernel.org +S: Maintained + MARVELL YUKON / SYSKONNECT DRIVER P: Mirko Lindner M: mlindner@syskonnect.de diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 7d57f4a..6c3c1f0 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -77,6 +77,16 @@ config BONDING To compile this driver as a module, choose M here: the module will be called bonding. +config MACVLAN + tristate "MAC-VLAN support (EXPERIMENTAL)" + depends on EXPERIMENTAL + ---help--- + This allows one to create virtual interfaces that map packets to + or from specific MAC addresses to a particular interface. + + To compile this driver as a module, choose M here: the module + will be called macvlan. + config EQUALIZER tristate "EQL (serial line load balancing) support" ---help--- diff --git a/drivers/net/Makefile b/drivers/net/Makefile index a77affa..fc10e37 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -125,6 +125,7 @@ obj-$(CONFIG_SLHC) += slhc.o obj-$(CONFIG_DUMMY) += dummy.o obj-$(CONFIG_IFB) += ifb.o +obj-$(CONFIG_MACVLAN) += macvlan.o obj-$(CONFIG_DE600) += de600.o obj-$(CONFIG_DE620) += de620.o obj-$(CONFIG_LANCE) += lance.o diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c new file mode 100644 index 0000000..39ca0a2 --- /dev/null +++ b/drivers/net/macvlan.c @@ -0,0 +1,468 @@ +/* + * Copyright (c) 2007 Patrick McHardy <kaber@trash.net> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * The code this is based on carried the following copyright notice: + * --- + * (C) Copyright 2001-2006 + * Alex Zeffertt, Cambridge Broadband Ltd, ajz@cambridgebroadband.com + * Re-worked by Ben Greear <greearb@candelatech.com> + * --- + */ +#include <linux/kernel.h> +#include <linux/types.h> +#include <linux/module.h> +#include <linux/init.h> +#include <linux/errno.h> +#include <linux/slab.h> +#include <linux/string.h> +#include <linux/list.h> +#include <linux/notifier.h> +#include <linux/netdevice.h> +#include <linux/etherdevice.h> +#include <linux/ethtool.h> +#include <linux/if_arp.h> +#include <linux/if_link.h> +#include <linux/if_macvlan.h> +#include <net/rtnetlink.h> + +#define MACVLAN_HASH_SIZE (1 << BITS_PER_BYTE) + +struct macvlan_port { + struct list_head list; + struct net_device *dev; + struct hlist_head vlan_hash[MACVLAN_HASH_SIZE]; + struct list_head vlans; +}; + +struct macvlan_dev { + struct net_device *dev; + struct list_head list; + struct hlist_node hlist; + struct macvlan_port *port; + struct net_device *lowerdev; +}; + + +static struct macvlan_dev *macvlan_hash_lookup(const struct macvlan_port *port, + const unsigned char *addr) +{ + struct macvlan_dev *vlan; + struct hlist_node *n; + + hlist_for_each_entry_rcu(vlan, n, &port->vlan_hash[addr[5]], hlist) { + if (!compare_ether_addr(vlan->dev->dev_addr, addr)) + return vlan; + } + return NULL; +} + +static void macvlan_broadcast(struct sk_buff *skb, + const struct macvlan_port *port) +{ + const struct ethhdr *eth = eth_hdr(skb); + const struct macvlan_dev *vlan; + struct hlist_node *n; + struct net_device *dev; + struct sk_buff *nskb; + unsigned int i; + + for (i = 0; i < MACVLAN_HASH_SIZE; i++) { + hlist_for_each_entry_rcu(vlan, n, &port->vlan_hash[i], hlist) { + dev = vlan->dev; + if (unlikely(!(dev->flags & IFF_UP))) + continue; + + nskb = skb_clone(skb, GFP_ATOMIC); + if (nskb == NULL) { + dev->stats.rx_errors++; + dev->stats.rx_dropped++; + continue; + } + + dev->stats.rx_bytes += skb->len + ETH_HLEN; + dev->stats.rx_packets++; + dev->stats.multicast++; + dev->last_rx = jiffies; + + nskb->dev = dev; + if (!compare_ether_addr(eth->h_dest, dev->broadcast)) + nskb->pkt_type = PACKET_BROADCAST; + else + nskb->pkt_type = PACKET_MULTICAST; + + netif_rx(nskb); + } + } +} + +/* called under rcu_read_lock() from netif_receive_skb() */ +static struct sk_buff *macvlan_handle_frame(struct sk_buff *skb) +{ + const struct ethhdr *eth = eth_hdr(skb); + const struct macvlan_port *port; + const struct macvlan_dev *vlan; + struct net_device *dev; + + port = rcu_dereference(skb->dev->macvlan_port); + if (port == NULL) + return skb; + + if (is_multicast_ether_addr(eth->h_dest)) { + macvlan_broadcast(skb, port); + return skb; + } + + vlan = macvlan_hash_lookup(port, eth->h_dest); + if (vlan == NULL) + return skb; + + dev = vlan->dev; + if (unlikely(!(dev->flags & IFF_UP))) { + kfree_skb(skb); + return NULL; + } + + skb = skb_share_check(skb, GFP_ATOMIC); + if (skb == NULL) { + dev->stats.rx_errors++; + dev->stats.rx_dropped++; + return NULL; + } + + dev->stats.rx_bytes += skb->len + ETH_HLEN; + dev->stats.rx_packets++; + dev->last_rx = jiffies; + + skb->dev = dev; + skb->pkt_type = PACKET_HOST; + + netif_rx(skb); + return NULL; +} + +static int macvlan_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) +{ + const struct macvlan_dev *vlan = netdev_priv(dev); + unsigned int len = skb->len; + int ret; + + skb->dev = vlan->lowerdev; + ret = dev_queue_xmit(skb); + + if (likely(ret == NET_XMIT_SUCCESS)) { + dev->stats.tx_packets++; + dev->stats.tx_bytes += len; + } else { + dev->stats.tx_errors++; + dev->stats.tx_aborted_errors++; + } + return NETDEV_TX_OK; +} + +static int macvlan_hard_header(struct sk_buff *skb, struct net_device *dev, + unsigned short type, void *daddr, void *saddr, + unsigned len) +{ + const struct macvlan_dev *vlan = netdev_priv(dev); + struct net_device *lowerdev = vlan->lowerdev; + + return lowerdev->hard_header(skb, lowerdev, type, daddr, + saddr ? : dev->dev_addr, len); +} + +static int macvlan_open(struct net_device *dev) +{ + struct macvlan_dev *vlan = netdev_priv(dev); + struct macvlan_port *port = vlan->port; + + hlist_add_head_rcu(&vlan->hlist, &port->vlan_hash[dev->dev_addr[5]]); + dev_set_promiscuity(vlan->lowerdev, 1); + return 0; +} + +static int macvlan_stop(struct net_device *dev) +{ + struct macvlan_dev *vlan = netdev_priv(dev); + + dev_set_promiscuity(vlan->lowerdev, -1); + hlist_del_rcu(&vlan->hlist); + synchronize_rcu(); + return 0; +} + +static int macvlan_change_mtu(struct net_device *dev, int new_mtu) +{ + struct macvlan_dev *vlan = netdev_priv(dev); + + if (new_mtu < 68 || vlan->lowerdev->mtu < new_mtu) + return -EINVAL; + dev->mtu = new_mtu; + return 0; +} + +/* + * macvlan network devices have devices nesting below it and are a special + * "super class" of normal network devices; split their locks off into a + * separate class since they always nest. + */ +static struct lock_class_key macvlan_netdev_xmit_lock_key; + +#define MACVLAN_FEATURES \ + (NETIF_F_SG | NETIF_F_ALL_CSUM | NETIF_F_HIGHDMA | NETIF_F_FRAGLIST | \ + NETIF_F_GSO | NETIF_F_TSO | NETIF_F_UFO | NETIF_F_GSO_ROBUST | \ + NETIF_F_TSO_ECN | NETIF_F_TSO6) + +#define MACVLAN_STATE_MASK \ + ((1<<__LINK_STATE_NOCARRIER) | (1<<__LINK_STATE_DORMANT)) + +static int macvlan_init(struct net_device *dev) +{ + struct macvlan_dev *vlan = netdev_priv(dev); + struct net_device *lowerdev = vlan->lowerdev; + + dev->state = (dev->state & ~MACVLAN_STATE_MASK) | + (lowerdev->state & MACVLAN_STATE_MASK); + dev->features = lowerdev->features & MACVLAN_FEATURES; + dev->iflink = lowerdev->ifindex; + + lockdep_set_class(&dev->_xmit_lock, &macvlan_netdev_xmit_lock_key); + return 0; +} + +static void macvlan_ethtool_get_drvinfo(struct net_device *dev, + struct ethtool_drvinfo *drvinfo) +{ + snprintf(drvinfo->driver, 32, "macvlan"); + snprintf(drvinfo->version, 32, "0.1"); +} + +static u32 macvlan_ethtool_get_rx_csum(struct net_device *dev) +{ + const struct macvlan_dev *vlan = netdev_priv(dev); + struct net_device *lowerdev = vlan->lowerdev; + + if (lowerdev->ethtool_ops->get_rx_csum == NULL) + return 0; + return lowerdev->ethtool_ops->get_rx_csum(lowerdev); +} + +static const struct ethtool_ops macvlan_ethtool_ops = { + .get_link = ethtool_op_get_link, + .get_rx_csum = macvlan_ethtool_get_rx_csum, + .get_tx_csum = ethtool_op_get_tx_csum, + .get_tso = ethtool_op_get_tso, + .get_ufo = ethtool_op_get_ufo, + .get_sg = ethtool_op_get_sg, + .get_drvinfo = macvlan_ethtool_get_drvinfo, +}; + +static void macvlan_setup(struct net_device *dev) +{ + ether_setup(dev); + + dev->init = macvlan_init; + dev->open = macvlan_open; + dev->stop = macvlan_stop; + dev->change_mtu = macvlan_change_mtu; + dev->hard_header = macvlan_hard_header; + dev->hard_start_xmit = macvlan_hard_start_xmit; + dev->destructor = free_netdev; + dev->ethtool_ops = &macvlan_ethtool_ops; + dev->tx_queue_len = 0; + + random_ether_addr(dev->dev_addr); +} + +static LIST_HEAD(port_list); + +static int macvlan_port_create(struct net_device *dev) +{ + struct macvlan_port *port; + unsigned int i; + + if (dev->type != ARPHRD_ETHER || dev->flags & IFF_LOOPBACK) + return -EINVAL; + + port = kzalloc(sizeof(*port), GFP_KERNEL); + if (port == NULL) + return -ENOMEM; + + port->dev = dev; + INIT_LIST_HEAD(&port->vlans); + for (i = 0; i < MACVLAN_HASH_SIZE; i++) + INIT_HLIST_HEAD(&port->vlan_hash[i]); + rcu_assign_pointer(dev->macvlan_port, port); + + list_add_tail(&port->list, &port_list); + return 0; +} + +static void macvlan_dellink(struct net_device *dev); + +static void macvlan_port_cleanup(struct net_device *dev) +{ + struct macvlan_port *port = dev->macvlan_port; + struct macvlan_dev *vlan, *next; + + list_for_each_entry_safe(vlan, next, &port->vlans, list) + macvlan_dellink(vlan->dev); + + rcu_assign_pointer(dev->macvlan_port, NULL); + synchronize_rcu(); + + list_del(&port->list); + kfree(port); +} + +static void macvlan_transfer_operstate(struct net_device *dev) +{ + struct macvlan_dev *vlan = netdev_priv(dev); + const struct net_device *lowerdev = vlan->lowerdev; + + if (lowerdev->operstate == IF_OPER_DORMANT) + netif_dormant_on(dev); + else + netif_dormant_off(dev); + + if (netif_carrier_ok(lowerdev)) { + if (!netif_carrier_ok(dev)) + netif_carrier_on(dev); + } else { + if (netif_carrier_ok(lowerdev)) + netif_carrier_off(dev); + } +} + +static int macvlan_newlink(struct net_device *dev, + struct nlattr *tb[], struct nlattr *data[]) +{ + struct macvlan_dev *vlan = netdev_priv(dev); + struct macvlan_port *port; + struct net_device *lowerdev; + int err; + + if (!tb[IFLA_LINK]) + return -EINVAL; + + lowerdev = __dev_get_by_index(nla_get_u32(tb[IFLA_LINK])); + if (lowerdev == NULL) + return -ENODEV; + + if (!tb[IFLA_MTU]) + dev->mtu = lowerdev->mtu; + else if (dev->mtu > lowerdev->mtu) + return -EINVAL; + + if (lowerdev->macvlan_port == NULL) { + err = macvlan_port_create(lowerdev); + if (err < 0) + return err; + } + port = lowerdev->macvlan_port; + + vlan->lowerdev = lowerdev; + vlan->dev = dev; + vlan->port = port; + + err = register_netdevice(dev); + if (err < 0) + return err; + + list_add_tail(&vlan->list, &port->vlans); + macvlan_transfer_operstate(dev); + return 0; +} + +static void macvlan_dellink(struct net_device *dev) +{ + struct macvlan_dev *vlan = netdev_priv(dev); + + list_del(&vlan->list); + unregister_netdevice(dev); +} + +static struct rtnl_link_ops macvlan_link_ops __read_mostly = { + .kind = "macvlan", + .priv_size = sizeof(struct macvlan_dev), + .setup = macvlan_setup, + .newlink = macvlan_newlink, + .dellink = macvlan_dellink, +}; + +static int macvlan_device_event(struct notifier_block *unused, + unsigned long event, void *ptr) +{ + struct net_device *dev = ptr; + struct macvlan_dev *vlan; + struct macvlan_port *port; + + port = dev->macvlan_port; + if (port == NULL) + goto out; + + switch (event) { + case NETDEV_CHANGE: + list_for_each_entry(vlan, &port->vlans, list) + macvlan_transfer_operstate(vlan->dev); + break; + case NETDEV_FEAT_CHANGE: + list_for_each_entry(vlan, &port->vlans, list) { + vlan->dev->features = dev->features & MACVLAN_FEATURES; + netdev_features_change(vlan->dev); + } + break; + case NETDEV_UNREGISTER: + macvlan_port_cleanup(dev); + break; + } +out: + return NOTIFY_DONE; +} + +static struct notifier_block macvlan_notifier_block __read_mostly = { + .notifier_call = macvlan_device_event, +}; + +static int __init macvlan_init_module(void) +{ + int err; + + register_netdevice_notifier(&macvlan_notifier_block); + macvlan_handle_frame_hook = macvlan_handle_frame; + + err = rtnl_link_register(&macvlan_link_ops); + if (err < 0) + goto err1; + return 0; +err1: + macvlan_handle_frame_hook = macvlan_handle_frame; + unregister_netdevice_notifier(&macvlan_notifier_block); + return err; +} + +static void __exit macvlan_cleanup_module(void) +{ + struct macvlan_port *port, *next; + + rtnl_lock(); + list_for_each_entry_safe(port, next, &port_list, list) + macvlan_port_cleanup(port->dev); + __rtnl_link_unregister(&macvlan_link_ops); + rtnl_unlock(); + + macvlan_handle_frame_hook = NULL; + unregister_netdevice_notifier(&macvlan_notifier_block); +} + +module_init(macvlan_init_module); +module_exit(macvlan_cleanup_module); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>"); +MODULE_DESCRIPTION("Driver for MAC address based VLANs"); +MODULE_ALIAS_RTNL_LINK("macvlan"); diff --git a/include/linux/if_macvlan.h b/include/linux/if_macvlan.h new file mode 100644 index 0000000..0d9d7ea --- /dev/null +++ b/include/linux/if_macvlan.h @@ -0,0 +1,9 @@ +#ifndef _LINUX_IF_MACVLAN_H +#define _LINUX_IF_MACVLAN_H + +#ifdef __KERNEL__ + +extern struct sk_buff *(*macvlan_handle_frame_hook)(struct sk_buff *); + +#endif /* __KERNEL__ */ +#endif /* _LINUX_IF_MACVLAN_H */ diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index e7913ee..868140d 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -535,6 +535,8 @@ struct net_device /* bridge stuff */ struct net_bridge_port *br_port; + /* macvlan */ + struct macvlan_port *macvlan_port; /* class/net/name entry */ struct device dev; diff --git a/net/core/dev.c b/net/core/dev.c index 2609062..5974e5b 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -98,6 +98,7 @@ #include <linux/seq_file.h> #include <linux/stat.h> #include <linux/if_bridge.h> +#include <linux/if_macvlan.h> #include <net/dst.h> #include <net/pkt_sched.h> #include <net/checksum.h> @@ -1793,6 +1794,28 @@ static inline struct sk_buff *handle_bridge(struct sk_buff *skb, #define handle_bridge(skb, pt_prev, ret, orig_dev) (skb) #endif +#if defined(CONFIG_MACVLAN) || defined(CONFIG_MACVLAN_MODULE) +struct sk_buff *(*macvlan_handle_frame_hook)(struct sk_buff *skb) __read_mostly; +EXPORT_SYMBOL_GPL(macvlan_handle_frame_hook); + +static inline struct sk_buff *handle_macvlan(struct sk_buff *skb, + struct packet_type **pt_prev, + int *ret, + struct net_device *orig_dev) +{ + if (skb->dev->macvlan_port == NULL) + return skb; + + if (*pt_prev) { + *ret = deliver_skb(skb, *pt_prev, orig_dev); + *pt_prev = NULL; + } + return macvlan_handle_frame_hook(skb); +} +#else +#define handle_macvlan(skb, pt_prev, ret, orig_dev) (skb) +#endif + #ifdef CONFIG_NET_CLS_ACT /* TODO: Maybe we should just force sch_ingress to be compiled in * when CONFIG_NET_CLS_ACT is? otherwise some useless instructions @@ -1900,6 +1923,9 @@ ncls: skb = handle_bridge(skb, &pt_prev, &ret, orig_dev); if (!skb) goto out; + skb = handle_macvlan(skb, &pt_prev, &ret, orig_dev); + if (!skb) + goto out; type = skb->protocol; list_for_each_entry_rcu(ptype, &ptype_base[ntohs(type)&15], list) { ^ permalink raw reply related [flat|nested] 13+ messages in thread
* Re: [NET 00/02]: MACVLAN driver 2007-06-19 13:08 [NET 00/02]: MACVLAN driver Patrick McHardy 2007-06-19 13:08 ` [ETHERNET 01/02]: Validate new address in eth_mac_addr Patrick McHardy 2007-06-19 13:08 ` [NET 02/02]: Add MACVLAN driver Patrick McHardy @ 2007-06-19 16:00 ` Stephen Hemminger 2007-06-19 19:53 ` Chris Leech 2007-06-19 21:14 ` Patrick McHardy 2 siblings, 2 replies; 13+ messages in thread From: Stephen Hemminger @ 2007-06-19 16:00 UTC (permalink / raw) To: Patrick McHardy; +Cc: davem, netdev, Patrick McHardy On Tue, 19 Jun 2007 15:08:41 +0200 (MEST) Patrick McHardy <kaber@trash.net> wrote: > These patches add a rewritten version of Ben's macvlan driver, which > allows to create virtual ethernet devices. The underlying device is > put in promiscous mode and packets are demuxed based on MAC address. > It behaves similar to bridge devices in that packets are visible on > the real device before delivery to the macvlan driver. The driver > supports all features of the underlying device except VLAN > acceleration, this is currently very hard to support. I might look > into this in the future. > > The main downside of this driver is that it adds another hook in > netif_receive_skb, unfortunately that is unavoidable. When not > compiled in the hook vanishes of course. > > Usage is simple: > > # ip link add link eth0 type macvlan > > Will create a macvlan0 device with a random MAC address on top of > eth0. No iproute patches are required. > > > Please apply, thanks. > Looks good. I have some changes to allow devices with multiple MAC addresses (never finished). This device could use that. -- Stephen Hemminger <shemminger@linux-foundation.org> ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [NET 00/02]: MACVLAN driver 2007-06-19 16:00 ` [NET 00/02]: " Stephen Hemminger @ 2007-06-19 19:53 ` Chris Leech 2007-06-19 21:14 ` Patrick McHardy 1 sibling, 0 replies; 13+ messages in thread From: Chris Leech @ 2007-06-19 19:53 UTC (permalink / raw) To: Stephen Hemminger; +Cc: netdev On 6/19/07, Stephen Hemminger <shemminger@linux-foundation.org> wrote: > Looks good. I have some changes to allow devices with multiple MAC addresses > (never finished). This device could use that. Stephen, Is this patch available somewhere? I'd be interested in taking a look at it. - Chris ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [NET 00/02]: MACVLAN driver 2007-06-19 16:00 ` [NET 00/02]: " Stephen Hemminger 2007-06-19 19:53 ` Chris Leech @ 2007-06-19 21:14 ` Patrick McHardy 2007-06-19 22:29 ` Stephen Hemminger 2007-06-19 22:48 ` David Miller 1 sibling, 2 replies; 13+ messages in thread From: Patrick McHardy @ 2007-06-19 21:14 UTC (permalink / raw) To: Stephen Hemminger; +Cc: davem, netdev Stephen Hemminger wrote: > Looks good. I have some changes to allow devices with multiple MAC addresses > (never finished). This device could use that. How would the driver do that? I was thinking about using dev_add_mc, but wasn't sure if that would work with all drivers for non-multicast addresses. ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [NET 00/02]: MACVLAN driver 2007-06-19 21:14 ` Patrick McHardy @ 2007-06-19 22:29 ` Stephen Hemminger 2007-06-19 22:48 ` David Miller 1 sibling, 0 replies; 13+ messages in thread From: Stephen Hemminger @ 2007-06-19 22:29 UTC (permalink / raw) To: Patrick McHardy; +Cc: davem, netdev On Tue, 19 Jun 2007 23:14:21 +0200 Patrick McHardy <kaber@trash.net> wrote: > Stephen Hemminger wrote: > > Looks good. I have some changes to allow devices with multiple MAC addresses > > (never finished). This device could use that. > > > How would the driver do that? I was thinking about using dev_add_mc, > but wasn't sure if that would work with all drivers for non-multicast > addresses. > Basically, add a new dev_add_addr hook to netdevice. Drivers that can do it, would add the hook. If driver didn't have hook, then core would put device into promiscuous. Most devices with multicast allow non-multicast addresses, so it could be a simple extension. Rather than doing it for all devices, wanted to go in one by one and test. -- Stephen Hemminger <shemminger@linux-foundation.org> ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [NET 00/02]: MACVLAN driver 2007-06-19 21:14 ` Patrick McHardy 2007-06-19 22:29 ` Stephen Hemminger @ 2007-06-19 22:48 ` David Miller 2007-06-19 23:44 ` Patrick McHardy 2007-06-20 6:34 ` Jeff Garzik 1 sibling, 2 replies; 13+ messages in thread From: David Miller @ 2007-06-19 22:48 UTC (permalink / raw) To: kaber; +Cc: shemminger, netdev From: Patrick McHardy <kaber@trash.net> Date: Tue, 19 Jun 2007 23:14:21 +0200 > Stephen Hemminger wrote: > > Looks good. I have some changes to allow devices with multiple MAC addresses > > (never finished). This device could use that. > > > How would the driver do that? I was thinking about using dev_add_mc, > but wasn't sure if that would work with all drivers for non-multicast > addresses. This is actually a real issue for virtualization, and many if not all current generation ethernet chips support programming several unicast ethernet addresses in the MAC. Networking switches in domain0 on virtualization hosts use this feature to support seperate MACs per guest node, and if the chip doesn't support this the chip is put into promiscuous mode. We don't have any clean interfaces by which to do this MAC programming, and we do need something for it soon. ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [NET 00/02]: MACVLAN driver 2007-06-19 22:48 ` David Miller @ 2007-06-19 23:44 ` Patrick McHardy 2007-06-20 6:34 ` Jeff Garzik 1 sibling, 0 replies; 13+ messages in thread From: Patrick McHardy @ 2007-06-19 23:44 UTC (permalink / raw) To: David Miller; +Cc: shemminger, netdev David Miller wrote: > From: Patrick McHardy <kaber@trash.net> > Date: Tue, 19 Jun 2007 23:14:21 +0200 > > >> Stephen Hemminger wrote: >> >>> Looks good. I have some changes to allow devices with multiple MAC addresses >>> (never finished). This device could use that. >>> >> How would the driver do that? I was thinking about using dev_add_mc, >> but wasn't sure if that would work with all drivers for non-multicast >> addresses. >> > > This is actually a real issue for virtualization, and many > if not all current generation ethernet chips support > programming several unicast ethernet addresses in the MAC. > > Networking switches in domain0 on virtualization hosts use > this feature to support seperate MACs per guest node, > and if the chip doesn't support this the chip is put into > promiscuous mode. > > We don't have any clean interfaces by which to do this MAC > programming, and we do need something for it soon. > Stephen's suggestion sounds reasonable and easily implementable, I'll see if I can come up with a patch. ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [NET 00/02]: MACVLAN driver 2007-06-19 22:48 ` David Miller 2007-06-19 23:44 ` Patrick McHardy @ 2007-06-20 6:34 ` Jeff Garzik 2007-06-20 19:35 ` Prafulla Deuskar 1 sibling, 1 reply; 13+ messages in thread From: Jeff Garzik @ 2007-06-20 6:34 UTC (permalink / raw) To: David Miller, kaber; +Cc: shemminger, netdev David Miller wrote: > This is actually a real issue for virtualization, and many > if not all current generation ethernet chips support > programming several unicast ethernet addresses in the MAC. > > Networking switches in domain0 on virtualization hosts use > this feature to support seperate MACs per guest node, > and if the chip doesn't support this the chip is put into > promiscuous mode. > > We don't have any clean interfaces by which to do this MAC > programming, and we do need something for it soon. Yep, that's been on my long term wish list for a while, as well. Overall I would like to see a more flexible way of allowing the net stack to learn each NIC's RX filter capabilities, and exploiting them. Plenty of NICs, even 100Mbps ones, support RX filter management that allows scanning for $hw_limit unicast addresses, before having to put the hardware into promisc mode. Jeff ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [NET 00/02]: MACVLAN driver 2007-06-20 6:34 ` Jeff Garzik @ 2007-06-20 19:35 ` Prafulla Deuskar 2007-06-21 14:57 ` Patrick McHardy 0 siblings, 1 reply; 13+ messages in thread From: Prafulla Deuskar @ 2007-06-20 19:35 UTC (permalink / raw) To: Jeff Garzik; +Cc: David Miller, kaber, shemminger, netdev On 6/19/07, Jeff Garzik <jeff@garzik.org> wrote: > David Miller wrote: > > This is actually a real issue for virtualization, and many > > if not all current generation ethernet chips support > > programming several unicast ethernet addresses in the MAC. > > > > Networking switches in domain0 on virtualization hosts use > > this feature to support seperate MACs per guest node, > > and if the chip doesn't support this the chip is put into > > promiscuous mode. > > > > We don't have any clean interfaces by which to do this MAC > > programming, and we do need something for it soon. > > > Yep, that's been on my long term wish list for a while, as well. > > Overall I would like to see a more flexible way of allowing the net > stack to learn each NIC's RX filter capabilities, and exploiting them. > Plenty of NICs, even 100Mbps ones, support RX filter management that > allows scanning for $hw_limit unicast addresses, before having to put > the hardware into promisc mode. > > Jeff So how do we manage mac address to RX queue association? Ideally we should extend ethtool to do that rather than inventing a new tool - Is that acceptable? -Prafulla ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [NET 00/02]: MACVLAN driver 2007-06-20 19:35 ` Prafulla Deuskar @ 2007-06-21 14:57 ` Patrick McHardy 0 siblings, 0 replies; 13+ messages in thread From: Patrick McHardy @ 2007-06-21 14:57 UTC (permalink / raw) To: Prafulla Deuskar; +Cc: Jeff Garzik, David Miller, shemminger, netdev Prafulla Deuskar wrote: > On 6/19/07, Jeff Garzik <jeff@garzik.org> wrote: >> David Miller wrote: >> > This is actually a real issue for virtualization, and many >> > if not all current generation ethernet chips support >> > programming several unicast ethernet addresses in the MAC. >> > >> > Networking switches in domain0 on virtualization hosts use >> > this feature to support seperate MACs per guest node, >> > and if the chip doesn't support this the chip is put into >> > promiscuous mode. >> > >> > We don't have any clean interfaces by which to do this MAC >> > programming, and we do need something for it soon. >> >> >> Yep, that's been on my long term wish list for a while, as well. >> >> Overall I would like to see a more flexible way of allowing the net >> stack to learn each NIC's RX filter capabilities, and exploiting them. >> Plenty of NICs, even 100Mbps ones, support RX filter management that >> allows scanning for $hw_limit unicast addresses, before having to put >> the hardware into promisc mode. >> >> Jeff > > So how do we manage mac address to RX queue association? This is not about multiple RX queues but filtering multiple unicast addresses without going to promiscous mode. The addresses are used by something outside the driver, like macvlan. ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [NET 00/02]: MACVLAN driver @ 2007-06-24 4:52 Mark Smith 0 siblings, 0 replies; 13+ messages in thread From: Mark Smith @ 2007-06-24 4:52 UTC (permalink / raw) To: Jeff Garzik; +Cc: netdev (Applogies for not maintaining thread id, I'm not subscribed.) >> We don't have any clean interfaces by which to do this MAC >> programming, and we do need something for it soon. >Yep, that's been on my long term wish list for a while, as well. >Overall I would like to see a more flexible way of allowing the net >stack to learn each NIC's RX filter capabilities, and exploiting them. >Plenty of NICs, even 100Mbps ones, support RX filter management that >allows scanning for $hw_limit unicast addresses, before having to put >the hardware into promisc mode. > A thought I had when I discovered this ability in the Natsemi/NS83815 chip was to use these RX filters for perfect multicast DA matching until they ran out, and then reverting to the normal Multicast DA matching mechanisms. Another alternative use I thought of was to use these filters to filter out different ethernet protocol types e.g. if an interface is only going to be processing IPv4 packets, program these filters to only accept frames with type 0800 for IP and 0806 for ARP, reverting to non-filtering if there are too many protocol types, as per the way the interfaces operate today. I think it could be useful to expose the ability to have the NIC ignore broadcast packets, or more generally, expose the three catagories of address recognition that NICs seem to allow to be enabled / disabled - unicast, multicast and broadcast. If an interface then didn't need to have broadcast reception enabled e.g. an IPv6 only interface (or Appletalk), then it wouldn't be, preventing the host from having to process broadcasts it's going to ignore anyway. A future common scenario where this ability might be useful would be LANs with a mix of IPv4 only, IPv4/IPv6 and IPv6-only nodes. The ability to enable/disable unicast, multicast and broadcast address recognition individually on a NIC seems to be widespread - I've found that the original early to mid 90s Ne2K chip, the NS8390D, the Netgear FA311/FA312 chip, the NS83815 and the SMC Epic/100 chip all have specific individual register values for those three types of addresses. Regards, Mark. ^ permalink raw reply [flat|nested] 13+ messages in thread
end of thread, other threads:[~2007-06-24 5:44 UTC | newest] Thread overview: 13+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2007-06-19 13:08 [NET 00/02]: MACVLAN driver Patrick McHardy 2007-06-19 13:08 ` [ETHERNET 01/02]: Validate new address in eth_mac_addr Patrick McHardy 2007-06-19 13:08 ` [NET 02/02]: Add MACVLAN driver Patrick McHardy 2007-06-19 16:00 ` [NET 00/02]: " Stephen Hemminger 2007-06-19 19:53 ` Chris Leech 2007-06-19 21:14 ` Patrick McHardy 2007-06-19 22:29 ` Stephen Hemminger 2007-06-19 22:48 ` David Miller 2007-06-19 23:44 ` Patrick McHardy 2007-06-20 6:34 ` Jeff Garzik 2007-06-20 19:35 ` Prafulla Deuskar 2007-06-21 14:57 ` Patrick McHardy -- strict thread matches above, loose matches on Subject: below -- 2007-06-24 4:52 Mark Smith
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).