~james-page/ubuntu/saucy/openvswitch/1.12-snapshot

« back to all changes in this revision

Viewing changes to datapath/genl_exec.c

  • Committer: James Page
  • Date: 2013-08-21 10:16:57 UTC
  • mfrom: (1.1.20)
  • Revision ID: james.page@canonical.com-20130821101657-3o0z0qeiv5zkwlzi
New upstream snapshot

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * Copyright (c) 2007-2012 Nicira, Inc.
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 <linux/completion.h>
23
 
#include <net/genetlink.h>
24
 
#include "genl_exec.h"
25
 
 
26
 
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35)
27
 
 
28
 
static DEFINE_MUTEX(genl_exec_lock);
29
 
 
30
 
static genl_exec_func_t  genl_exec_function;
31
 
static int               genl_exec_function_ret;
32
 
static void             *genl_exec_data;
33
 
static struct completion done;
34
 
 
35
 
static struct sk_buff *genlmsg_skb;
36
 
 
37
 
static 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
 
 
44
 
enum exec_cmd {
45
 
        GENL_EXEC_UNSPEC,
46
 
        GENL_EXEC_RUN,
47
 
};
48
 
 
49
 
static struct genl_family genl_exec_family = {
50
 
        .id = GENL_ID_GENERATE,
51
 
        .name = "ovs_genl_exec",
52
 
        .version = 1,
53
 
};
54
 
 
55
 
static 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
 
 
63
 
int 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
 
 
81
 
void 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
 
 
91
 
int 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;
104
 
 
105
 
        /* There is no need to send msg to current namespace. */
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
 
 
129
 
int 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
 
 
139
 
int genl_exec_init(void)
140
 
{
141
 
        return 0;
142
 
}
143
 
 
144
 
void genl_exec_exit(void)
145
 
{
146
 
}
147
 
#endif