Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

IB/core: Add rdma netlink helper functions

This patch adds a function to check if listeners for a netlink multicast
group are present. It also adds a function to receive netlink response
messages.

Signed-off-by: Kaike Wan <kaike.wan@intel.com>
Signed-off-by: John Fleck <john.fleck@intel.com>
Signed-off-by: Ira Weiny <ira.weiny@intel.com>
Signed-off-by: Doug Ledford <dledford@redhat.com>

authored by

Kaike Wan and committed by
Doug Ledford
bc10ed7d 6431eb87

+62
+55
drivers/infiniband/core/netlink.c
··· 49 49 static struct sock *nls; 50 50 static LIST_HEAD(client_list); 51 51 52 + int ibnl_chk_listeners(unsigned int group) 53 + { 54 + if (netlink_has_listeners(nls, group) == 0) 55 + return -1; 56 + return 0; 57 + } 58 + EXPORT_SYMBOL(ibnl_chk_listeners); 59 + 52 60 int ibnl_add_client(int index, int nops, 53 61 const struct ibnl_client_cbs cb_table[]) 54 62 { ··· 159 151 !client->cb_table[op].dump) 160 152 return -EINVAL; 161 153 154 + /* 155 + * For response or local service set_timeout request, 156 + * there is no need to use netlink_dump_start. 157 + */ 158 + if (!(nlh->nlmsg_flags & NLM_F_REQUEST) || 159 + (index == RDMA_NL_LS && 160 + op == RDMA_NL_LS_OP_SET_TIMEOUT)) { 161 + struct netlink_callback cb = { 162 + .skb = skb, 163 + .nlh = nlh, 164 + .dump = client->cb_table[op].dump, 165 + .module = client->cb_table[op].module, 166 + }; 167 + 168 + return cb.dump(skb, &cb); 169 + } 170 + 162 171 { 163 172 struct netlink_dump_control c = { 164 173 .dump = client->cb_table[op].dump, ··· 190 165 return -EINVAL; 191 166 } 192 167 168 + static void ibnl_rcv_reply_skb(struct sk_buff *skb) 169 + { 170 + struct nlmsghdr *nlh; 171 + int msglen; 172 + 173 + /* 174 + * Process responses until there is no more message or the first 175 + * request. Generally speaking, it is not recommended to mix responses 176 + * with requests. 177 + */ 178 + while (skb->len >= nlmsg_total_size(0)) { 179 + nlh = nlmsg_hdr(skb); 180 + 181 + if (nlh->nlmsg_len < NLMSG_HDRLEN || skb->len < nlh->nlmsg_len) 182 + return; 183 + 184 + /* Handle response only */ 185 + if (nlh->nlmsg_flags & NLM_F_REQUEST) 186 + return; 187 + 188 + ibnl_rcv_msg(skb, nlh); 189 + 190 + msglen = NLMSG_ALIGN(nlh->nlmsg_len); 191 + if (msglen > skb->len) 192 + msglen = skb->len; 193 + skb_pull(skb, msglen); 194 + } 195 + } 196 + 193 197 static void ibnl_rcv(struct sk_buff *skb) 194 198 { 195 199 mutex_lock(&ibnl_mutex); 200 + ibnl_rcv_reply_skb(skb); 196 201 netlink_rcv_skb(skb, &ibnl_rcv_msg); 197 202 mutex_unlock(&ibnl_mutex); 198 203 }
+7
include/rdma/rdma_netlink.h
··· 77 77 int ibnl_multicast(struct sk_buff *skb, struct nlmsghdr *nlh, 78 78 unsigned int group, gfp_t flags); 79 79 80 + /** 81 + * Check if there are any listeners to the netlink group 82 + * @group: the netlink group ID 83 + * Returns 0 on success or a negative for no listeners. 84 + */ 85 + int ibnl_chk_listeners(unsigned int group); 86 + 80 87 #endif /* _RDMA_NETLINK_H */