mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-09-12 05:48:40 +00:00
![Eric W. Biederman](/assets/img/avatar_default.png)
On systems that create and delete lots of dynamic devices the 31bit linux ifindex fails to fit in the 16bit macvtap minor, resulting in unusable macvtap devices. I have systems running automated tests that that hit this condition in just a few days. Use a linux idr allocator to track which mavtap minor numbers are available and and to track the association between macvtap minor numbers and macvtap network devices. Remove the unnecessary unneccessary check to see if the network device we have found is indeed a macvtap device. With macvtap specific data structures it is impossible to find any other kind of networking device. Increase the macvtap minor range from 65536 to the full 20 bits that is supported by linux device numbers. It doesn't solve the original problem but there is no penalty for a larger minor device range. Signed-off-by: Eric W. Biederman <ebiederm@xmission.com> Signed-off-by: David S. Miller <davem@davemloft.net>
108 lines
2.9 KiB
C
108 lines
2.9 KiB
C
#ifndef _LINUX_IF_MACVLAN_H
|
|
#define _LINUX_IF_MACVLAN_H
|
|
|
|
#include <linux/if_link.h>
|
|
#include <linux/list.h>
|
|
#include <linux/netdevice.h>
|
|
#include <linux/netlink.h>
|
|
#include <net/netlink.h>
|
|
#include <linux/u64_stats_sync.h>
|
|
|
|
#if defined(CONFIG_MACVTAP) || defined(CONFIG_MACVTAP_MODULE)
|
|
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;
|
|
|
|
/**
|
|
* struct macvlan_pcpu_stats - MACVLAN percpu stats
|
|
* @rx_packets: number of received packets
|
|
* @rx_bytes: number of received bytes
|
|
* @rx_multicast: number of received multicast packets
|
|
* @tx_packets: number of transmitted packets
|
|
* @tx_bytes: number of transmitted bytes
|
|
* @syncp: synchronization point for 64bit counters
|
|
* @rx_errors: number of rx errors
|
|
* @tx_dropped: number of tx dropped packets
|
|
*/
|
|
struct macvlan_pcpu_stats {
|
|
u64 rx_packets;
|
|
u64 rx_bytes;
|
|
u64 rx_multicast;
|
|
u64 tx_packets;
|
|
u64 tx_bytes;
|
|
struct u64_stats_sync syncp;
|
|
u32 rx_errors;
|
|
u32 tx_dropped;
|
|
};
|
|
|
|
/*
|
|
* 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 (NR_CPUS < 16 ? NR_CPUS : 16)
|
|
|
|
struct macvlan_dev {
|
|
struct net_device *dev;
|
|
struct list_head list;
|
|
struct hlist_node hlist;
|
|
struct macvlan_port *port;
|
|
struct net_device *lowerdev;
|
|
struct macvlan_pcpu_stats __percpu *pcpu_stats;
|
|
enum macvlan_mode mode;
|
|
int (*receive)(struct sk_buff *skb);
|
|
int (*forward)(struct net_device *dev, struct sk_buff *skb);
|
|
struct macvtap_queue *taps[MAX_MACVTAP_QUEUES];
|
|
int numvtaps;
|
|
int minor;
|
|
};
|
|
|
|
static inline void macvlan_count_rx(const struct macvlan_dev *vlan,
|
|
unsigned int len, bool success,
|
|
bool multicast)
|
|
{
|
|
if (likely(success)) {
|
|
struct macvlan_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[],
|
|
int (*receive)(struct sk_buff *skb),
|
|
int (*forward)(struct net_device *dev,
|
|
struct sk_buff *skb));
|
|
|
|
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);
|
|
|
|
extern netdev_tx_t macvlan_start_xmit(struct sk_buff *skb,
|
|
struct net_device *dev);
|
|
|
|
#endif /* _LINUX_IF_MACVLAN_H */
|