Hi guys,
I have a new link driver that registers a rtnl_link_ops. For many
things, the rtnl interfaces are perfectly suited: I can use netlink in
userspace to check out packet counts, adjust interface parameters, and
all sorts of things. There is even the "fill_info" function exporting
interface-specific types of data to userspace through the standard
netlink interfaces. I'm glad this is here, because it's exactly what I
want.
Problem: sometimes I want to export a *lot* of data to userspace. When
this happens, even if I make the netlink socket receive buffer really
huge, this code path is still reached in rtnetlink.c:
err = rtnl_fill_ifinfo(skb, dev, RTM_NEWLINK,
NETLINK_CB(cb->skb).portid,
cb->nlh->nlmsg_seq, 0,
NLM_F_MULTI,
ext_filter_mask);
/* If we ran out of room on the first message,
* we're in trouble
*/
WARN_ON((err == -EMSGSIZE) && (skb->len == 0));
That is -- it tries to fill the skb (for sending it back to
userspace), but doesn't have enough room, so it returns -EMSGSIZE.
That seems like reasonable behavior, but it doesn't really help me
obtain my goal. I'd like to send quite a bit of data back to userspace
for a network interface, and I'd like to do it using the standard
netlink APIs. Is this possible?
Thanks,
Jason
On Wed, Aug 19, 2015 at 5:47 PM, Jason A. Donenfeld <[email protected]> wrote:
> Hi guys,
>
> I have a new link driver that registers a rtnl_link_ops. For many
> things, the rtnl interfaces are perfectly suited: I can use netlink in
> userspace to check out packet counts, adjust interface parameters, and
> all sorts of things. There is even the "fill_info" function exporting
> interface-specific types of data to userspace through the standard
> netlink interfaces. I'm glad this is here, because it's exactly what I
> want.
>
> Problem: sometimes I want to export a *lot* of data to userspace. When
> this happens, even if I make the netlink socket receive buffer really
> huge, this code path is still reached in rtnetlink.c:
>
> err = rtnl_fill_ifinfo(skb, dev, RTM_NEWLINK,
> NETLINK_CB(cb->skb).portid,
> cb->nlh->nlmsg_seq, 0,
> NLM_F_MULTI,
> ext_filter_mask);
> /* If we ran out of room on the first message,
> * we're in trouble
> */
> WARN_ON((err == -EMSGSIZE) && (skb->len == 0));
>
> That is -- it tries to fill the skb (for sending it back to
> userspace), but doesn't have enough room, so it returns -EMSGSIZE.
> That seems like reasonable behavior, but it doesn't really help me
> obtain my goal. I'd like to send quite a bit of data back to userspace
> for a network interface, and I'd like to do it using the standard
> netlink APIs. Is this possible?
What kind of data are you sending up? Maybe there is an alternate interface.
On Thu, Aug 20, 2015 at 7:59 AM, Scott Feldman <[email protected]> wrote:
>
> What kind of data are you sending up? Maybe there is an alternate interface.
This is what I'm wondering about: alternative interfaces, that are
still kosher in the netlink/rtnl world. Each interface is associated
with a certain set of "peers". I want to get a list of all these
peers. Sometimes there are lots of them. It's structured data that
fits well into netlink messages, but it's just that there are
potentially a lot of entries.
Hi folks,
Just a follow-up on this thread...
The basic issue is that for a given net device, I want to export to
userspace more data than what can fit in a netlink sk_buff. On first
glance, using RTM_GETLINK with the ops->fill_info() hook seemed
perfect. It provides a simple interface for my rtnetlink driver to
provide additional information back to userspace. Unfortunately, the
size of messages it can export back to userspace is limited, as
mentioned.
So, I see two options from here:
One is registering a new type of netlink message for a new PF, with
rtnl_register(). Inside of this, I'd have a more clean API of sending
back information in chunks, which can fit inside a netlink packet.
The other is to implement ops->ndo_do_ioctl() with a very simple
mechanism of copying structs back to userspace, directly into
userspace-allocated buffers. This would be _much_ simpler and easier
to implement, and probably less prone to race-conditions too.
So I want to add the ioctl. I can practically already see the code in
my head. But everywhere I look, folks are turning to netlink. It's
hard to imagine a new driver passing review on this mailing list if it
adds "yet another" ioctl interface. So, I'm then pushed toward doing
the awkward netlink dance, because "all the cool kids are doing it."
But, before I succumb to what is potentially a false dichotomy, I
thought I'd write in here to get some opinions on the best way
forward. To repeat, the basic idea is - I need to return lots of
per-interface information to userspace from a netdevice. RTM_GETLINK
has a maximum message size, so it won't do. What's the cleanest and
most acceptable way forward?
Thanks,
Jason