mirror of
https://github.com/openvswitch/ovs
synced 2025-10-19 14:37:21 +00:00
net_namespace-device can get registered after module init, e.g. vxlan registers name-space-device on port add. On kernel without namespace support __net_init is defined as __init which cause panic on vxlan port add. Following patch fixes it. BUG: unable to handle kernel paging request at ffffffffa02b6293 IP: [<ffffffffa02b6293>] 0xffffffffa02b6293 PGD 1a87067 PUD 1a8b063 PMD 8371de067 PTE 0 Oops: 0010 [#1] SMP Process ovs-vswitchd (pid: 10330, threadinfo ffff8808367fe000, task f880839e16aa0) Stack: Call Trace: [<ffffffff8144b254>] ? register_pernet_gen_device+0x74/0xd0 [<ffffffffa027e220>] ? vxlan_rcv+0x0/0x60 [openvswitch] [<ffffffffa0280a7b>] vxlan_handler_add+0x3cb/0x480 [openvswitch] [<ffffffffa027e1f4>] vxlan_tnl_create+0xc4/0xf0 [openvswitch] [<ffffffffa027b6f3>] ovs_vport_add+0x53/0xb0 [openvswitch] [<ffffffffa0273bc6>] new_vport+0x16/0x60 [openvswitch] [<ffffffffa0276399>] ovs_vport_cmd_new+0x109/0x210 [openvswitch] [<ffffffff81478f80>] genl_rcv_msg+0x1d0/0x210 [<ffffffff81477e29>] netlink_rcv_skb+0xa9/0xd0 [<ffffffff81478d95>] genl_rcv+0x25/0x40 [<ffffffff81477a63>] netlink_unicast+0x283/0x2d0 [<ffffffff814783de>] netlink_sendmsg+0x1fe/0x2e0 [<ffffffff8143c8d3>] sock_sendmsg+0x123/0x150 [<ffffffff8143e0b6>] __sys_sendmsg+0x406/0x420 [<ffffffff8143e2d9>] sys_sendmsg+0x49/0x90 [<ffffffff8100b072>] system_call_fastpath+0x16/0x1b Code: Bad RIP value. RIP [<ffffffffa02b6293>] 0xffffffffa02b6293 Signed-off-by: Pravin B Shelar <pshelar@nicira.com> Acked-by: Jesse Gross <jesse@nicira.com> Bug #19178
76 lines
1.5 KiB
C
76 lines
1.5 KiB
C
#include <linux/if_vlan.h>
|
|
#include <linux/netdevice.h>
|
|
#include <net/net_namespace.h>
|
|
#include <net/netns/generic.h>
|
|
|
|
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33)
|
|
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,32)
|
|
static int net_assign_generic(struct net *net, int id, void *data);
|
|
#endif
|
|
|
|
int compat_init_net(struct net *net, struct rpl_pernet_operations *pnet)
|
|
{
|
|
int err;
|
|
void *ovs_net = kzalloc(pnet->size, GFP_KERNEL);
|
|
|
|
if (!ovs_net)
|
|
return -ENOMEM;
|
|
|
|
err = net_assign_generic(net, *pnet->id, ovs_net);
|
|
if (err)
|
|
goto err;
|
|
|
|
if (pnet->init) {
|
|
err = pnet->init(net);
|
|
if (err)
|
|
goto err;
|
|
}
|
|
|
|
return 0;
|
|
err:
|
|
kfree(ovs_net);
|
|
return err;
|
|
}
|
|
|
|
void compat_exit_net(struct net *net, struct rpl_pernet_operations *pnet)
|
|
{
|
|
void *ovs_net = net_generic(net, *pnet->id);
|
|
|
|
if (pnet->exit)
|
|
pnet->exit(net);
|
|
kfree(ovs_net);
|
|
}
|
|
#endif
|
|
|
|
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,32)
|
|
#define MAX_DATA_COUNT 2
|
|
static struct net *net;
|
|
|
|
static void *__ovs_net_data[MAX_DATA_COUNT];
|
|
static int count;
|
|
|
|
static int net_assign_generic(struct net *net, int id, void *data)
|
|
{
|
|
BUG_ON(id >= MAX_DATA_COUNT);
|
|
__ovs_net_data[id] = data;
|
|
return 0;
|
|
}
|
|
|
|
void *net_generic(const struct net *net, int id)
|
|
{
|
|
return __ovs_net_data[id];
|
|
}
|
|
|
|
int rpl_register_pernet_gen_device(struct rpl_pernet_operations *rpl_pnet)
|
|
{
|
|
*rpl_pnet->id = count++;
|
|
return compat_init_net(net, rpl_pnet);
|
|
}
|
|
|
|
void rpl_unregister_pernet_gen_device(struct rpl_pernet_operations *rpl_pnet)
|
|
{
|
|
compat_exit_net(net, rpl_pnet);
|
|
}
|
|
|
|
#endif
|