mirror of
https://github.com/linux-msm/laptops-kernel.git
synced 2026-08-13 14:19:53 -07:00
openvswitch: Add support for network namespaces.
Following patch adds support for network namespace to openvswitch. Since it must release devices when namespaces are destroyed, a side effect of this patch is that the module no longer keeps a refcount but instead cleans up any state when it is unloaded. Signed-off-by: Pravin B Shelar <pshelar@nicira.com> Signed-off-by: Jesse Gross <jesse@nicira.com>
This commit is contained in:
committed by
Jesse Gross
parent
0d7614f09c
commit
46df7b8145
+162
-107
File diff suppressed because it is too large
Load Diff
@@ -27,8 +27,7 @@
|
||||
#include <linux/u64_stats_sync.h>
|
||||
|
||||
#include "flow.h"
|
||||
|
||||
struct vport;
|
||||
#include "vport.h"
|
||||
|
||||
#define DP_MAX_PORTS 1024
|
||||
#define SAMPLE_ACTION_DEPTH 3
|
||||
@@ -63,6 +62,7 @@ struct dp_stats_percpu {
|
||||
* @port_list: List of all ports in @ports in arbitrary order. RTNL required
|
||||
* to iterate or modify.
|
||||
* @stats_percpu: Per-CPU datapath statistics.
|
||||
* @net: Reference to net namespace.
|
||||
*
|
||||
* Context: See the comment on locking at the top of datapath.c for additional
|
||||
* locking information.
|
||||
@@ -80,6 +80,11 @@ struct datapath {
|
||||
|
||||
/* Stats. */
|
||||
struct dp_stats_percpu __percpu *stats_percpu;
|
||||
|
||||
#ifdef CONFIG_NET_NS
|
||||
/* Network namespace ref. */
|
||||
struct net *net;
|
||||
#endif
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -108,6 +113,16 @@ struct dp_upcall_info {
|
||||
u32 pid;
|
||||
};
|
||||
|
||||
static inline struct net *ovs_dp_get_net(struct datapath *dp)
|
||||
{
|
||||
return read_pnet(&dp->net);
|
||||
}
|
||||
|
||||
static inline void ovs_dp_set_net(struct datapath *dp, struct net *net)
|
||||
{
|
||||
write_pnet(&dp->net, net);
|
||||
}
|
||||
|
||||
extern struct notifier_block ovs_dp_device_notifier;
|
||||
extern struct genl_multicast_group ovs_dp_vport_multicast_group;
|
||||
|
||||
|
||||
@@ -41,19 +41,21 @@ static int dp_device_event(struct notifier_block *unused, unsigned long event,
|
||||
case NETDEV_UNREGISTER:
|
||||
if (!ovs_is_internal_dev(dev)) {
|
||||
struct sk_buff *notify;
|
||||
struct datapath *dp = vport->dp;
|
||||
|
||||
notify = ovs_vport_cmd_build_info(vport, 0, 0,
|
||||
OVS_VPORT_CMD_DEL);
|
||||
ovs_dp_detach_port(vport);
|
||||
if (IS_ERR(notify)) {
|
||||
netlink_set_err(init_net.genl_sock, 0,
|
||||
netlink_set_err(ovs_dp_get_net(dp)->genl_sock, 0,
|
||||
ovs_dp_vport_multicast_group.id,
|
||||
PTR_ERR(notify));
|
||||
break;
|
||||
}
|
||||
|
||||
genlmsg_multicast(notify, 0, ovs_dp_vport_multicast_group.id,
|
||||
GFP_KERNEL);
|
||||
genlmsg_multicast_netns(ovs_dp_get_net(dp), notify, 0,
|
||||
ovs_dp_vport_multicast_group.id,
|
||||
GFP_KERNEL);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -144,7 +144,7 @@ static void do_setup(struct net_device *netdev)
|
||||
netdev->tx_queue_len = 0;
|
||||
|
||||
netdev->features = NETIF_F_LLTX | NETIF_F_SG | NETIF_F_FRAGLIST |
|
||||
NETIF_F_HIGHDMA | NETIF_F_HW_CSUM | NETIF_F_TSO;
|
||||
NETIF_F_HIGHDMA | NETIF_F_HW_CSUM | NETIF_F_TSO;
|
||||
|
||||
netdev->vlan_features = netdev->features;
|
||||
netdev->features |= NETIF_F_HW_VLAN_TX;
|
||||
@@ -175,9 +175,14 @@ static struct vport *internal_dev_create(const struct vport_parms *parms)
|
||||
goto error_free_vport;
|
||||
}
|
||||
|
||||
dev_net_set(netdev_vport->dev, ovs_dp_get_net(vport->dp));
|
||||
internal_dev = internal_dev_priv(netdev_vport->dev);
|
||||
internal_dev->vport = vport;
|
||||
|
||||
/* Restrict bridge port to current netns. */
|
||||
if (vport->port_no == OVSP_LOCAL)
|
||||
netdev_vport->dev->features |= NETIF_F_NETNS_LOCAL;
|
||||
|
||||
err = register_netdevice(netdev_vport->dev);
|
||||
if (err)
|
||||
goto error_free_netdev;
|
||||
|
||||
@@ -83,7 +83,7 @@ static struct vport *netdev_create(const struct vport_parms *parms)
|
||||
|
||||
netdev_vport = netdev_vport_priv(vport);
|
||||
|
||||
netdev_vport->dev = dev_get_by_name(&init_net, parms->name);
|
||||
netdev_vport->dev = dev_get_by_name(ovs_dp_get_net(vport->dp), parms->name);
|
||||
if (!netdev_vport->dev) {
|
||||
err = -ENODEV;
|
||||
goto error_free_vport;
|
||||
|
||||
+14
-8
@@ -16,10 +16,10 @@
|
||||
* 02110-1301, USA
|
||||
*/
|
||||
|
||||
#include <linux/dcache.h>
|
||||
#include <linux/etherdevice.h>
|
||||
#include <linux/if.h>
|
||||
#include <linux/if_vlan.h>
|
||||
#include <linux/jhash.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/mutex.h>
|
||||
@@ -27,7 +27,9 @@
|
||||
#include <linux/rcupdate.h>
|
||||
#include <linux/rtnetlink.h>
|
||||
#include <linux/compat.h>
|
||||
#include <net/net_namespace.h>
|
||||
|
||||
#include "datapath.h"
|
||||
#include "vport.h"
|
||||
#include "vport-internal_dev.h"
|
||||
|
||||
@@ -67,9 +69,9 @@ void ovs_vport_exit(void)
|
||||
kfree(dev_table);
|
||||
}
|
||||
|
||||
static struct hlist_head *hash_bucket(const char *name)
|
||||
static struct hlist_head *hash_bucket(struct net *net, const char *name)
|
||||
{
|
||||
unsigned int hash = full_name_hash(name, strlen(name));
|
||||
unsigned int hash = jhash(name, strlen(name), (unsigned long) net);
|
||||
return &dev_table[hash & (VPORT_HASH_BUCKETS - 1)];
|
||||
}
|
||||
|
||||
@@ -80,14 +82,15 @@ static struct hlist_head *hash_bucket(const char *name)
|
||||
*
|
||||
* Must be called with RTNL or RCU read lock.
|
||||
*/
|
||||
struct vport *ovs_vport_locate(const char *name)
|
||||
struct vport *ovs_vport_locate(struct net *net, const char *name)
|
||||
{
|
||||
struct hlist_head *bucket = hash_bucket(name);
|
||||
struct hlist_head *bucket = hash_bucket(net, name);
|
||||
struct vport *vport;
|
||||
struct hlist_node *node;
|
||||
|
||||
hlist_for_each_entry_rcu(vport, node, bucket, hash_node)
|
||||
if (!strcmp(name, vport->ops->get_name(vport)))
|
||||
if (!strcmp(name, vport->ops->get_name(vport)) &&
|
||||
net_eq(ovs_dp_get_net(vport->dp), net))
|
||||
return vport;
|
||||
|
||||
return NULL;
|
||||
@@ -170,14 +173,17 @@ struct vport *ovs_vport_add(const struct vport_parms *parms)
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(vport_ops_list); i++) {
|
||||
if (vport_ops_list[i]->type == parms->type) {
|
||||
struct hlist_head *bucket;
|
||||
|
||||
vport = vport_ops_list[i]->create(parms);
|
||||
if (IS_ERR(vport)) {
|
||||
err = PTR_ERR(vport);
|
||||
goto out;
|
||||
}
|
||||
|
||||
hlist_add_head_rcu(&vport->hash_node,
|
||||
hash_bucket(vport->ops->get_name(vport)));
|
||||
bucket = hash_bucket(ovs_dp_get_net(vport->dp),
|
||||
vport->ops->get_name(vport));
|
||||
hlist_add_head_rcu(&vport->hash_node, bucket);
|
||||
return vport;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#define VPORT_H 1
|
||||
|
||||
#include <linux/list.h>
|
||||
#include <linux/netlink.h>
|
||||
#include <linux/openvswitch.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/spinlock.h>
|
||||
@@ -38,7 +39,7 @@ void ovs_vport_exit(void);
|
||||
struct vport *ovs_vport_add(const struct vport_parms *);
|
||||
void ovs_vport_del(struct vport *);
|
||||
|
||||
struct vport *ovs_vport_locate(const char *name);
|
||||
struct vport *ovs_vport_locate(struct net *net, const char *name);
|
||||
|
||||
void ovs_vport_get_stats(struct vport *, struct ovs_vport_stats *);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user