]> git.proxmox.com Git - mirror_ovs.git/blame - datapath/genl_exec.c
socket-util: export set_dscp()
[mirror_ovs.git] / datapath / genl_exec.c
CommitLineData
b9c15df9 1/*
e0edde6f 2 * Copyright (c) 2007-2012 Nicira, Inc.
b9c15df9
PS
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>
b9975b29 22#include <linux/completion.h>
b9c15df9
PS
23#include <net/genetlink.h>
24#include "genl_exec.h"
25
26#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35)
27
28static DEFINE_MUTEX(genl_exec_lock);
29
30static genl_exec_func_t genl_exec_function;
31static int genl_exec_function_ret;
32static void *genl_exec_data;
33static struct completion done;
34
35static struct sk_buff *genlmsg_skb;
36
37static int genl_exec_cmd(struct sk_buff *dummy, struct genl_info *dummy2)
38{
39 genl_exec_function_ret = genl_exec_function(genl_exec_data);
40 complete(&done);
41 return 0;
42}
43
44enum exec_cmd {
45 GENL_EXEC_UNSPEC,
46 GENL_EXEC_RUN,
47};
48
49static struct genl_family genl_exec_family = {
50 .id = GENL_ID_GENERATE,
51 .name = "ovs_genl_exec",
52 .version = 1,
53};
54
55static struct genl_ops genl_exec_ops[] = {
56 {
57 .cmd = GENL_EXEC_RUN,
58 .doit = genl_exec_cmd,
59 .flags = CAP_NET_ADMIN,
60 },
61};
62
63int genl_exec_init(void)
64{
65 int err;
66
67 err = genl_register_family_with_ops(&genl_exec_family,
68 genl_exec_ops, ARRAY_SIZE(genl_exec_ops));
69
70 if (err)
71 return err;
72
73 genlmsg_skb = genlmsg_new(0, GFP_KERNEL);
74 if (!genlmsg_skb) {
75 genl_unregister_family(&genl_exec_family);
76 return -ENOMEM;
77 }
78 return 0;
79}
80
81void genl_exec_exit(void)
82{
83 kfree_skb(genlmsg_skb);
84 genl_unregister_family(&genl_exec_family);
85}
86
87/* genl_lock() is not exported from older kernel.
88 * Following function allows any function to be executed with
89 * genl_mutex held. */
90
91int genl_exec(genl_exec_func_t func, void *data)
92{
93 int ret;
94
95 mutex_lock(&genl_exec_lock);
96
97 init_completion(&done);
98 skb_get(genlmsg_skb);
99 genlmsg_put(genlmsg_skb, 0, 0, &genl_exec_family,
100 NLM_F_REQUEST, GENL_EXEC_RUN);
101
102 genl_exec_function = func;
103 genl_exec_data = data;
2a4999f3
PS
104
105 /* There is no need to send msg to current namespace. */
b9c15df9
PS
106 ret = genlmsg_unicast(&init_net, genlmsg_skb, 0);
107
108 if (!ret) {
109 wait_for_completion(&done);
110 ret = genl_exec_function_ret;
111 } else {
112 pr_err("genl_exec send error %d\n", ret);
113 }
114
115 /* Wait for genetlink to kfree skb. */
116 while (skb_shared(genlmsg_skb))
117 cpu_relax();
118
119 genlmsg_skb->data = genlmsg_skb->head;
120 skb_reset_tail_pointer(genlmsg_skb);
121
122 mutex_unlock(&genl_exec_lock);
123
124 return ret;
125}
126
127#else
128
129int genl_exec(genl_exec_func_t func, void *data)
130{
131 int ret;
132
133 genl_lock();
134 ret = func(data);
135 genl_unlock();
136 return ret;
137}
138
139int genl_exec_init(void)
140{
141 return 0;
142}
143
144void genl_exec_exit(void)
145{
146}
147#endif