openvswitch: Remove Linux bridge compatibility.
[sliver-openvswitch.git] / datapath / linux / compat / genetlink-openvswitch.c
1 #include <net/genetlink.h>
2 #include <linux/version.h>
3
4 #define GENL_FIRST_MCGROUP 16
5 #define GENL_LAST_MCGROUP  31
6
7 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23)
8 #include <linux/mutex.h>
9 #include <linux/openvswitch.h>
10
11 #include "openvswitch/datapath-compat.h"
12
13 static DEFINE_MUTEX(mc_group_mutex);
14
15 int genl_register_mc_group(struct genl_family *family,
16                            struct genl_multicast_group *grp)
17 {
18         static int next_group = GENL_FIRST_MCGROUP;
19
20         grp->family = family;
21
22         if (!strcmp(grp->name, OVS_VPORT_MCGROUP)) {
23                 grp->id = OVS_VPORT_MCGROUP_FALLBACK_ID;
24                 return 0;
25         }
26
27         mutex_lock(&mc_group_mutex);
28         grp->id = next_group;
29
30         if (++next_group > GENL_LAST_MCGROUP)
31                 next_group = GENL_FIRST_MCGROUP;
32         mutex_unlock(&mc_group_mutex);
33
34         return 0;
35 }
36 #endif /* kernel < 2.6.23 */
37
38 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,31)
39 /**
40  * genl_register_family_with_ops - register a generic netlink family
41  * @family: generic netlink family
42  * @ops: operations to be registered
43  * @n_ops: number of elements to register
44  *
45  * Registers the specified family and operations from the specified table.
46  * Only one family may be registered with the same family name or identifier.
47  *
48  * The family id may equal GENL_ID_GENERATE causing an unique id to
49  * be automatically generated and assigned.
50  *
51  * Either a doit or dumpit callback must be specified for every registered
52  * operation or the function will fail. Only one operation structure per
53  * command identifier may be registered.
54  *
55  * See include/net/genetlink.h for more documenation on the operations
56  * structure.
57  *
58  * This is equivalent to calling genl_register_family() followed by
59  * genl_register_ops() for every operation entry in the table taking
60  * care to unregister the family on error path.
61  *
62  * Return 0 on success or a negative error code.
63  */
64 int genl_register_family_with_ops(struct genl_family *family,
65         struct genl_ops *ops, size_t n_ops)
66 {
67         int err, i;
68
69         err = genl_register_family(family);
70         if (err)
71                 return err;
72
73         for (i = 0; i < n_ops; ++i, ++ops) {
74                 err = genl_register_ops(family, ops);
75                 if (err)
76                         goto err_out;
77         }
78         return 0;
79 err_out:
80         genl_unregister_family(family);
81         return err;
82 }
83 #endif
84
85 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)
86 /**
87  * nlmsg_notify - send a notification netlink message
88  * @sk: netlink socket to use
89  * @skb: notification message
90  * @portid: destination netlink portid for reports or 0
91  * @group: destination multicast group or 0
92  * @report: 1 to report back, 0 to disable
93  * @flags: allocation flags
94  */
95 int nlmsg_notify(struct sock *sk, struct sk_buff *skb, u32 portid,
96                  unsigned int group, int report, gfp_t flags)
97 {
98         int err = 0;
99
100         if (group) {
101                 int exclude_portid = 0;
102
103                 if (report) {
104                         atomic_inc(&skb->users);
105                         exclude_portid = portid;
106                 }
107
108                 /* errors reported via destination sk->sk_err, but propagate
109                  * delivery errors if NETLINK_BROADCAST_ERROR flag is set */
110                 err = nlmsg_multicast(sk, skb, exclude_portid, group, flags);
111         }
112
113         if (report) {
114                 int err2;
115
116                 err2 = nlmsg_unicast(sk, skb, portid);
117                 if (!err || err == -ESRCH)
118                         err = err2;
119         }
120
121         return err;
122 }
123 #endif
124
125 /* This is analogous to rtnl_notify() but uses genl_sock instead of rtnl.
126  *
127  * This is not (yet) in any upstream kernel. */
128 void genl_notify(struct sk_buff *skb, struct net *net, u32 portid, u32 group,
129                  struct nlmsghdr *nlh, gfp_t flags)
130 {
131 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,32)
132         struct sock *sk = net->genl_sock;
133 #else
134         struct sock *sk = genl_sock;
135 #endif
136         int report = 0;
137
138         if (nlh)
139                 report = nlmsg_report(nlh);
140
141         nlmsg_notify(sk, skb, portid, group, report, flags);
142 }
143
144 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30)
145 /* This function wasn't exported before 2.6.30.  Lose! */
146 void netlink_set_err(struct sock *ssk, u32 portid, u32 group, int code)
147 {
148 }
149 #endif