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