diff options
| author | Thomas Graf <tgraf@suug.ch> | 2013-11-30 07:21:30 -0500 |
|---|---|---|
| committer | Jesse Gross <jesse@nicira.com> | 2014-01-06 18:51:53 -0500 |
| commit | bb9b18fb55b03477fe5bdd3e97245d6d4d3dee4f (patch) | |
| tree | 02d730abd6f31752a842f8c1d9f30d62d185e0b2 | |
| parent | 663efa3696232300a8ad3a46bb10482fc0b861cf (diff) | |
genl: Add genlmsg_new_unicast() for unicast message allocation
Allocates a new sk_buff large enough to cover the specified payload
plus required Netlink headers. Will check receiving socket for
memory mapped i/o capability and use it if enabled. Will fall back
to non-mapped skb if message size exceeds the frame size of the ring.
Signed-of-by: Thomas Graf <tgraf@suug.ch>
Reviewed-by: Daniel Borkmann <dborkman@redhat.com>
Signed-off-by: Jesse Gross <jesse@nicira.com>
| -rw-r--r-- | include/net/genetlink.h | 4 | ||||
| -rw-r--r-- | net/netlink/genetlink.c | 21 |
2 files changed, 25 insertions, 0 deletions
diff --git a/include/net/genetlink.h b/include/net/genetlink.h index 1b177ed803b7..93695f0e22a5 100644 --- a/include/net/genetlink.h +++ b/include/net/genetlink.h | |||
| @@ -73,6 +73,7 @@ struct genl_family { | |||
| 73 | * @attrs: netlink attributes | 73 | * @attrs: netlink attributes |
| 74 | * @_net: network namespace | 74 | * @_net: network namespace |
| 75 | * @user_ptr: user pointers | 75 | * @user_ptr: user pointers |
| 76 | * @dst_sk: destination socket | ||
| 76 | */ | 77 | */ |
| 77 | struct genl_info { | 78 | struct genl_info { |
| 78 | u32 snd_seq; | 79 | u32 snd_seq; |
| @@ -85,6 +86,7 @@ struct genl_info { | |||
| 85 | struct net * _net; | 86 | struct net * _net; |
| 86 | #endif | 87 | #endif |
| 87 | void * user_ptr[2]; | 88 | void * user_ptr[2]; |
| 89 | struct sock * dst_sk; | ||
| 88 | }; | 90 | }; |
| 89 | 91 | ||
| 90 | static inline struct net *genl_info_net(struct genl_info *info) | 92 | static inline struct net *genl_info_net(struct genl_info *info) |
| @@ -177,6 +179,8 @@ void genl_notify(struct genl_family *family, | |||
| 177 | struct sk_buff *skb, struct net *net, u32 portid, | 179 | struct sk_buff *skb, struct net *net, u32 portid, |
| 178 | u32 group, struct nlmsghdr *nlh, gfp_t flags); | 180 | u32 group, struct nlmsghdr *nlh, gfp_t flags); |
| 179 | 181 | ||
| 182 | struct sk_buff *genlmsg_new_unicast(size_t payload, struct genl_info *info, | ||
| 183 | gfp_t flags); | ||
| 180 | void *genlmsg_put(struct sk_buff *skb, u32 portid, u32 seq, | 184 | void *genlmsg_put(struct sk_buff *skb, u32 portid, u32 seq, |
| 181 | struct genl_family *family, int flags, u8 cmd); | 185 | struct genl_family *family, int flags, u8 cmd); |
| 182 | 186 | ||
diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c index 4518a57aa5fe..85bf42e2a943 100644 --- a/net/netlink/genetlink.c +++ b/net/netlink/genetlink.c | |||
| @@ -454,6 +454,26 @@ int genl_unregister_family(struct genl_family *family) | |||
| 454 | EXPORT_SYMBOL(genl_unregister_family); | 454 | EXPORT_SYMBOL(genl_unregister_family); |
| 455 | 455 | ||
| 456 | /** | 456 | /** |
| 457 | * genlmsg_new_unicast - Allocate generic netlink message for unicast | ||
| 458 | * @payload: size of the message payload | ||
| 459 | * @info: information on destination | ||
| 460 | * @flags: the type of memory to allocate | ||
| 461 | * | ||
| 462 | * Allocates a new sk_buff large enough to cover the specified payload | ||
| 463 | * plus required Netlink headers. Will check receiving socket for | ||
| 464 | * memory mapped i/o capability and use it if enabled. Will fall back | ||
| 465 | * to non-mapped skb if message size exceeds the frame size of the ring. | ||
| 466 | */ | ||
| 467 | struct sk_buff *genlmsg_new_unicast(size_t payload, struct genl_info *info, | ||
| 468 | gfp_t flags) | ||
| 469 | { | ||
| 470 | size_t len = nlmsg_total_size(genlmsg_total_size(payload)); | ||
| 471 | |||
| 472 | return netlink_alloc_skb(info->dst_sk, len, info->snd_portid, flags); | ||
| 473 | } | ||
| 474 | EXPORT_SYMBOL_GPL(genlmsg_new_unicast); | ||
| 475 | |||
| 476 | /** | ||
| 457 | * genlmsg_put - Add generic netlink header to netlink message | 477 | * genlmsg_put - Add generic netlink header to netlink message |
| 458 | * @skb: socket buffer holding the message | 478 | * @skb: socket buffer holding the message |
| 459 | * @portid: netlink portid the message is addressed to | 479 | * @portid: netlink portid the message is addressed to |
| @@ -593,6 +613,7 @@ static int genl_family_rcv_msg(struct genl_family *family, | |||
| 593 | info.genlhdr = nlmsg_data(nlh); | 613 | info.genlhdr = nlmsg_data(nlh); |
| 594 | info.userhdr = nlmsg_data(nlh) + GENL_HDRLEN; | 614 | info.userhdr = nlmsg_data(nlh) + GENL_HDRLEN; |
| 595 | info.attrs = attrbuf; | 615 | info.attrs = attrbuf; |
| 616 | info.dst_sk = skb->sk; | ||
| 596 | genl_info_net_set(&info, net); | 617 | genl_info_net_set(&info, net); |
| 597 | memset(&info.user_ptr, 0, sizeof(info.user_ptr)); | 618 | memset(&info.user_ptr, 0, sizeof(info.user_ptr)); |
| 598 | 619 | ||
