mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-22 00:40:03 +00:00
![Michael Braun](/assets/img/avatar_default.png)
This patch adds a new mode of operation to macvlan, called "source". It allows one to set a list of allowed mac address, which is used to match against source mac address from received frames on underlying interface. This enables creating mac based VLAN associations, instead of standard port or tag based. The feature is useful to deploy 802.1x mac based behavior, where drivers of underlying interfaces doesn't allows that. Configuration is done through the netlink interface using e.g.: ip link add link eth0 name macvlan0 type macvlan mode source ip link add link eth0 name macvlan1 type macvlan mode source ip link set link dev macvlan0 type macvlan macaddr add 00:11:11:11:11:11 ip link set link dev macvlan0 type macvlan macaddr add 00:22:22:22:22:22 ip link set link dev macvlan0 type macvlan macaddr add 00:33:33:33:33:33 ip link set link dev macvlan1 type macvlan macaddr add 00:33:33:33:33:33 ip link set link dev macvlan1 type macvlan macaddr add 00:44:44:44:44:44 This allows clients with MAC addresses 00:11:11:11:11:11, 00:22:22:22:22:22 to be part of only VLAN associated with macvlan0 interface. Clients with MAC addresses 00:44:44:44:44:44 with only VLAN associated with macvlan1 interface. And client with MAC address 00:33:33:33:33:33 to be associated with both VLANs. Based on work of Stefan Gula <steweg@gmail.com> v8: last version of Stefan Gula for Kernel 3.2.1 v9: rework onto linux-next 2014-03-12 by Michael Braun add MACADDR_SET command, enable to configure mac for source mode while creating interface v10: - reduce indention level - rename source_list to source_entry - use aligned 64bit ether address - use hash_64 instead of addr[5] v11: - rebase for 3.14 / linux-next 20.04.2014 v12 - rebase for linux-next 2014-09-25 Signed-off-by: Michael Braun <michael-dev@fami-braun.de> Signed-off-by: David S. Miller <davem@davemloft.net>
115 lines
2.8 KiB
C
115 lines
2.8 KiB
C
#ifndef _LINUX_IF_MACVLAN_H
|
|
#define _LINUX_IF_MACVLAN_H
|
|
|
|
#include <linux/if_link.h>
|
|
#include <linux/if_vlan.h>
|
|
#include <linux/list.h>
|
|
#include <linux/netdevice.h>
|
|
#include <linux/netlink.h>
|
|
#include <net/netlink.h>
|
|
#include <linux/u64_stats_sync.h>
|
|
|
|
#if IS_ENABLED(CONFIG_MACVTAP)
|
|
struct socket *macvtap_get_socket(struct file *);
|
|
#else
|
|
#include <linux/err.h>
|
|
#include <linux/errno.h>
|
|
struct file;
|
|
struct socket;
|
|
static inline struct socket *macvtap_get_socket(struct file *f)
|
|
{
|
|
return ERR_PTR(-EINVAL);
|
|
}
|
|
#endif /* CONFIG_MACVTAP */
|
|
|
|
struct macvlan_port;
|
|
struct macvtap_queue;
|
|
|
|
/*
|
|
* Maximum times a macvtap device can be opened. This can be used to
|
|
* configure the number of receive queue, e.g. for multiqueue virtio.
|
|
*/
|
|
#define MAX_MACVTAP_QUEUES 16
|
|
|
|
#define MACVLAN_MC_FILTER_BITS 8
|
|
#define MACVLAN_MC_FILTER_SZ (1 << MACVLAN_MC_FILTER_BITS)
|
|
|
|
struct macvlan_dev {
|
|
struct net_device *dev;
|
|
struct list_head list;
|
|
struct hlist_node hlist;
|
|
struct macvlan_port *port;
|
|
struct net_device *lowerdev;
|
|
void *fwd_priv;
|
|
struct vlan_pcpu_stats __percpu *pcpu_stats;
|
|
|
|
DECLARE_BITMAP(mc_filter, MACVLAN_MC_FILTER_SZ);
|
|
|
|
netdev_features_t set_features;
|
|
enum macvlan_mode mode;
|
|
u16 flags;
|
|
/* This array tracks active taps. */
|
|
struct macvtap_queue __rcu *taps[MAX_MACVTAP_QUEUES];
|
|
/* This list tracks all taps (both enabled and disabled) */
|
|
struct list_head queue_list;
|
|
int numvtaps;
|
|
int numqueues;
|
|
netdev_features_t tap_features;
|
|
int minor;
|
|
int nest_level;
|
|
#ifdef CONFIG_NET_POLL_CONTROLLER
|
|
struct netpoll *netpoll;
|
|
#endif
|
|
unsigned int macaddr_count;
|
|
};
|
|
|
|
static inline void macvlan_count_rx(const struct macvlan_dev *vlan,
|
|
unsigned int len, bool success,
|
|
bool multicast)
|
|
{
|
|
if (likely(success)) {
|
|
struct vlan_pcpu_stats *pcpu_stats;
|
|
|
|
pcpu_stats = this_cpu_ptr(vlan->pcpu_stats);
|
|
u64_stats_update_begin(&pcpu_stats->syncp);
|
|
pcpu_stats->rx_packets++;
|
|
pcpu_stats->rx_bytes += len;
|
|
if (multicast)
|
|
pcpu_stats->rx_multicast++;
|
|
u64_stats_update_end(&pcpu_stats->syncp);
|
|
} else {
|
|
this_cpu_inc(vlan->pcpu_stats->rx_errors);
|
|
}
|
|
}
|
|
|
|
extern void macvlan_common_setup(struct net_device *dev);
|
|
|
|
extern int macvlan_common_newlink(struct net *src_net, struct net_device *dev,
|
|
struct nlattr *tb[], struct nlattr *data[]);
|
|
|
|
extern void macvlan_count_rx(const struct macvlan_dev *vlan,
|
|
unsigned int len, bool success,
|
|
bool multicast);
|
|
|
|
extern void macvlan_dellink(struct net_device *dev, struct list_head *head);
|
|
|
|
extern int macvlan_link_register(struct rtnl_link_ops *ops);
|
|
|
|
#if IS_ENABLED(CONFIG_MACVLAN)
|
|
static inline struct net_device *
|
|
macvlan_dev_real_dev(const struct net_device *dev)
|
|
{
|
|
struct macvlan_dev *macvlan = netdev_priv(dev);
|
|
|
|
return macvlan->lowerdev;
|
|
}
|
|
#else
|
|
static inline struct net_device *
|
|
macvlan_dev_real_dev(const struct net_device *dev)
|
|
{
|
|
BUG();
|
|
return NULL;
|
|
}
|
|
#endif
|
|
|
|
#endif /* _LINUX_IF_MACVLAN_H */
|