]> git.proxmox.com Git - mirror_ovs.git/blame - datapath/genl_exec.c
vlog: Change the default timestamp structure.
[mirror_ovs.git] / datapath / genl_exec.c
CommitLineData
b9c15df9
PS
1/*
2 * Copyright (c) 2007-2012 Nicira Networks.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of version 2 of the GNU General Public
6 * License as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
16 * 02110-1301, USA
17 */
18
19#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
20
21#include <linux/version.h>
22#include <net/genetlink.h>
23#include "genl_exec.h"
24
25#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35)
26
27static DEFINE_MUTEX(genl_exec_lock);
28
29static genl_exec_func_t genl_exec_function;
30static int genl_exec_function_ret;
31static void *genl_exec_data;
32static struct completion done;
33
34static struct sk_buff *genlmsg_skb;
35
36static int genl_exec_cmd(struct sk_buff *dummy, struct genl_info *dummy2)
37{
38 genl_exec_function_ret = genl_exec_function(genl_exec_data);
39 complete(&done);
40 return 0;
41}
42
43enum exec_cmd {
44 GENL_EXEC_UNSPEC,
45 GENL_EXEC_RUN,
46};
47
48static struct genl_family genl_exec_family = {
49 .id = GENL_ID_GENERATE,
50 .name = "ovs_genl_exec",
51 .version = 1,
52};
53
54static struct genl_ops genl_exec_ops[] = {
55 {
56 .cmd = GENL_EXEC_RUN,
57 .doit = genl_exec_cmd,
58 .flags = CAP_NET_ADMIN,
59 },
60};
61
62int genl_exec_init(void)
63{
64 int err;
65
66 err = genl_register_family_with_ops(&genl_exec_family,
67 genl_exec_ops, ARRAY_SIZE(genl_exec_ops));
68
69 if (err)
70 return err;
71
72 genlmsg_skb = genlmsg_new(0, GFP_KERNEL);
73 if (!genlmsg_skb) {
74 genl_unregister_family(&genl_exec_family);
75 return -ENOMEM;
76 }
77 return 0;
78}
79
80void genl_exec_exit(void)
81{
82 kfree_skb(genlmsg_skb);
83 genl_unregister_family(&genl_exec_family);
84}
85
86/* genl_lock() is not exported from older kernel.
87 * Following function allows any function to be executed with
88 * genl_mutex held. */
89
90int genl_exec(genl_exec_func_t func, void *data)
91{
92 int ret;
93
94 mutex_lock(&genl_exec_lock);
95
96 init_completion(&done);
97 skb_get(genlmsg_skb);
98 genlmsg_put(genlmsg_skb, 0, 0, &genl_exec_family,
99 NLM_F_REQUEST, GENL_EXEC_RUN);
100
101 genl_exec_function = func;
102 genl_exec_data = data;
103 ret = genlmsg_unicast(&init_net, genlmsg_skb, 0);
104
105 if (!ret) {
106 wait_for_completion(&done);
107 ret = genl_exec_function_ret;
108 } else {
109 pr_err("genl_exec send error %d\n", ret);
110 }
111
112 /* Wait for genetlink to kfree skb. */
113 while (skb_shared(genlmsg_skb))
114 cpu_relax();
115
116 genlmsg_skb->data = genlmsg_skb->head;
117 skb_reset_tail_pointer(genlmsg_skb);
118
119 mutex_unlock(&genl_exec_lock);
120
121 return ret;
122}
123
124#else
125
126int genl_exec(genl_exec_func_t func, void *data)
127{
128 int ret;
129
130 genl_lock();
131 ret = func(data);
132 genl_unlock();
133 return ret;
134}
135
136int genl_exec_init(void)
137{
138 return 0;
139}
140
141void genl_exec_exit(void)
142{
143}
144#endif