Discussion:
tap(4) interface management
(too old to reply)
der Mouse
2009-05-13 14:16:58 UTC
Permalink
Extending the tap driver would be less invasive but unfortunately the
tap IO is carried out on a file descriptor so is no way (?) to do out
of band communication (socket control messages would have been great
for this), the best I can come up with is to have an ioctl enable
(eg) SIGUSR to be raised on informational changes and have the daemon
check.
thoughts and suggestions?
I would be inclined to do it in the tap driver. I would probably do
this by providing a tap-specific ioctl which puts it into a mode where
data, at least tap->user, has a header that (possibly among other
things) allows userland to distinguish between packets and other
ancillary data. The default, of course, would be no header and no
out-of-band data.

Whether the mode applies to the fd or to the tap device is an open
question. The former makes more sense; I would expect the latter to be
easier to do. In practice I don't expect there's much difference.

Another possibility would be a (tap-specific) ioctl which opens and
returns another file descriptor for the out-of-band data. I'm not sure
which of these two I prefer - probably whichever looks easier to
implement.

/~\ The ASCII Mouse
\ / Ribbon Campaign
X Against HTML ***@rodents-montreal.org
/ \ Email! 7D C8 61 52 5D E7 2D 39 4E F1 31 3E E8 B3 27 4B

--
Posted automagically by a mail2news gateway at muc.de e.V.
Please direct questions, flames, donations, etc. to news-***@muc.de
Quentin Garnier
2009-05-13 14:28:39 UTC
Permalink
Post by der Mouse
Extending the tap driver would be less invasive but unfortunately the
tap IO is carried out on a file descriptor so is no way (?) to do out
of band communication (socket control messages would have been great
for this), the best I can come up with is to have an ioctl enable
(eg) SIGUSR to be raised on informational changes and have the daemon
check.
thoughts and suggestions?
I would be inclined to do it in the tap driver. I would probably do
this by providing a tap-specific ioctl which puts it into a mode where
data, at least tap->user, has a header that (possibly among other
things) allows userland to distinguish between packets and other
ancillary data. The default, of course, would be no header and no
out-of-band data.
Whether the mode applies to the fd or to the tap device is an open
question. The former makes more sense; I would expect the latter to be
easier to do. In practice I don't expect there's much difference.
Another possibility would be a (tap-specific) ioctl which opens and
returns another file descriptor for the out-of-band data. I'm not sure
which of these two I prefer - probably whichever looks easier to
implement.
I think you can do all that using tap-specific kqueue filters. (See
kqueue(2), kfilter_register(9) and knote(9).)
--
Quentin Garnier - ***@cubidou.net - ***@NetBSD.org
"See the look on my face from staying too long in one place
[...] every time the morning breaks I know I'm closer to falling"
KT Tunstall, Saving My Face, Drastic Fantastic, 2007.
der Mouse
2009-05-13 14:42:07 UTC
Permalink
Post by Quentin Garnier
Post by der Mouse
I would be inclined to do it in the tap driver. I would probably do
this by providing a [] mode where data, at least tap->user, has a
header [...]
Another possibility would be a (tap-specific) ioctl which opens and
returns another file descriptor for the out-of-band data.
I think you can do all that using tap-specific kqueue filters. (See
kqueue(2), kfilter_register(9) and knote(9).)
Probably. I see no particular reason to prefer either over the other,
unless your userland code design would prefer the file descriptor
interface over the kqueue interface, or vice versa. Either way, some
kernel support needs to be written, and code that depends on it will be
nonportable to other OSes. I'd probably go with the fds, if only
because they're easier to backport, but since I'm probably not going to
be the one doing the work, that doesn't mean much.

/~\ The ASCII Mouse
\ / Ribbon Campaign
X Against HTML ***@rodents-montreal.org
/ \ Email! 7D C8 61 52 5D E7 2D 39 4E F1 31 3E E8 B3 27 4B

--
Posted automagically by a mail2news gateway at muc.de e.V.
Please direct questions, flames, donations, etc. to news-***@muc.de
Manuel Bouyer
2009-05-13 17:50:23 UTC
Permalink
Hi,
regarding btpand(8) which uses a tap(4) device to provide Ethernet over
Bluetooth services, I have been looking at adding some features relating
to the daemon actively monitoring the interface for various settings
rather than having them fixed at startup or requiring a config file. Such
1. btpand currently exits in client mode if the connection is lost, but I
also wanted it to exit if the interface is marked down locally.
2. btpand running as a server registers a service record with the service
discovery daemon, including protocols available and subnet masks for
IPv4 and IPv6. I want to provide the actual values in use.
3. the BNEP protocol has filtering options (mandatory to support) to cut
out unwanted ethernet packet types on a limited bandwidth connection.
btpand could monitor the address families configured on the tap interface
and enable/disable protocols as required.
Some of this can be handled as-is with a routing socket (as per attached
patch) but not quite all as it only notifies changes to the IFF_UP flag
and interface addresses and I would additionally like to notice changes to
other flags (IFF_NOARP at least, possibly IFF_LINKn etc later) and the
interface media settings (which can map to elements in the service
record).
So, I'm thinking of how to get where I'm wanting to be, the options seem
to be either extending the routing socket to provide additional messages,
or extending the tap driver to be able to signal changes to its owner.
Extending the routing socket is possible although its a global
interface. A RTM_IFINFO message is currently sent out when interface
status is changed, but it does contain the entire if_flags field and is
not only for IFF_UP changes (so, extra messages are not problematic). Its
fairly simple to emit messages for SIOCSIFFLAGS (as per second attached
patch) but I haven't found any way to get the media settings this way, it
would require adding a RTM_MEDIA message type which I haven't looked into.
Extending the tap driver would be less invasive but unfortunately the
tap IO is carried out on a file descriptor so is no way (?) to do out of
band communication (socket control messages would have been great for
this), the best I can come up with is to have an ioctl enable (eg) SIGUSR
to be raised on informational changes and have the daemon check.
thoughts and suggestions?
I think extending the routing socket isn't a bad idea. This is usefull for
other interfaces than tap, and could be used by other softwares.
Nothing in what you need here looks tap-specific.
--
Manuel Bouyer <***@antioche.eu.org>
NetBSD: 26 ans d'experience feront toujours la difference
--

--
Posted automagically by a mail2news gateway at muc.de e.V.
Please direct questions, flames, donations, etc. to news-***@muc.de
David Young
2009-05-13 20:44:31 UTC
Permalink
Hi,
regarding btpand(8) which uses a tap(4) device to provide Ethernet over
Bluetooth services, I have been looking at adding some features relating
to the daemon actively monitoring the interface for various settings
rather than having them fixed at startup or requiring a config file. Such
1. btpand currently exits in client mode if the connection is lost, but I
also wanted it to exit if the interface is marked down locally.
2. btpand running as a server registers a service record with the service
discovery daemon, including protocols available and subnet masks for
IPv4 and IPv6. I want to provide the actual values in use.
3. the BNEP protocol has filtering options (mandatory to support) to cut
out unwanted ethernet packet types on a limited bandwidth connection.
btpand could monitor the address families configured on the tap interface
and enable/disable protocols as required.
Some of this can be handled as-is with a routing socket (as per attached
patch) but not quite all as it only notifies changes to the IFF_UP flag
and interface addresses and I would additionally like to notice changes to
other flags (IFF_NOARP at least, possibly IFF_LINKn etc later) and the
interface media settings (which can map to elements in the service
record).
So, I'm thinking of how to get where I'm wanting to be, the options seem
to be either extending the routing socket to provide additional messages,
or extending the tap driver to be able to signal changes to its owner.
Extending the routing socket is possible although its a global
interface. A RTM_IFINFO message is currently sent out when interface
status is changed, but it does contain the entire if_flags field and is
not only for IFF_UP changes (so, extra messages are not problematic). Its
fairly simple to emit messages for SIOCSIFFLAGS (as per second attached
patch) but I haven't found any way to get the media settings this way, it
would require adding a RTM_MEDIA message type which I haven't looked into.
+/* rtmsg sockaddr alignment from src/sys/net/rtsock.c */
+#define ROUNDUP(a) \
+ ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
FWIW, <net/route.h> defines this as RT_ROUNDUP().
Common subdirectories: /usr/src/sys/net/agr/CVS and agr/CVS
--- /usr/src/sys/net/if.c 2009-02-24 10:05:47.000000000 +0000
+++ if.c 2009-04-06 17:12:15.000000000 +0100
@@ -1481,8 +1481,12 @@ ifioctl_common(struct ifnet *ifp, u_long
if_up(ifp);
splx(s);
}
- ifp->if_flags = (ifp->if_flags & IFF_CANTCHANGE) |
- (ifr->ifr_flags &~ IFF_CANTCHANGE);
+ if (((ifr->ifr_flags ^ ifp->if_flags) & ~IFF_CANTCHANGE)) {
+ ifp->if_flags = (ifp->if_flags & IFF_CANTCHANGE)
+ | (ifr->ifr_flags & ~IFF_CANTCHANGE);
+
+ rt_ifmsg(ifp);
+ }
break;
ifr = data;
if_up() and if_down() call rt_ifmsg(), too, so that if IFF_UP changes,
you will get two routing messages instead of one. Not a big deal, but
probably not what you intended. This may do DTRT:

case SIOCSIFFLAGS:
ifr = data;
if (ifp->if_flags & IFF_UP && (ifr->ifr_flags & IFF_UP) == 0) {
s = splnet();
if_down(ifp);
splx(s);
} else if (ifr->ifr_flags & IFF_UP &&
(ifp->if_flags & IFF_UP) == 0) {
s = splnet();
if_up(ifp);
splx(s);
} else if (((ifr->ifr_flags ^ ifp->if_flags) & ~IFF_CANTCHANGE))
rt_ifmsg(ifp);
ifp->if_flags = (ifp->if_flags & IFF_CANTCHANGE) |
(ifr->ifr_flags &~ IFF_CANTCHANGE);
break;

Dave
--
David Young OJC Technologies
***@ojctech.com Urbana, IL * (217) 278-3933

--
Posted automagically by a mail2news gateway at muc.de e.V.
Please direct questions, flames, donations, etc. to news-***@muc.de
Iain Hibbert
2009-05-13 21:21:47 UTC
Permalink
Post by David Young
+/* rtmsg sockaddr alignment from src/sys/net/rtsock.c */
+#define ROUNDUP(a) \
+ ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
FWIW, <net/route.h> defines this as RT_ROUNDUP().
Awesome! (but that wasn't there a few short weeks ago :)
Post by David Young
Common subdirectories: /usr/src/sys/net/agr/CVS and agr/CVS
--- /usr/src/sys/net/if.c 2009-02-24 10:05:47.000000000 +0000
+++ if.c 2009-04-06 17:12:15.000000000 +0100
@@ -1481,8 +1481,12 @@ ifioctl_common(struct ifnet *ifp, u_long
if_up(ifp);
splx(s);
}
- ifp->if_flags = (ifp->if_flags & IFF_CANTCHANGE) |
- (ifr->ifr_flags &~ IFF_CANTCHANGE);
+ if (((ifr->ifr_flags ^ ifp->if_flags) & ~IFF_CANTCHANGE)) {
+ ifp->if_flags = (ifp->if_flags & IFF_CANTCHANGE)
+ | (ifr->ifr_flags & ~IFF_CANTCHANGE);
+
+ rt_ifmsg(ifp);
+ }
break;
ifr = data;
if_up() and if_down() call rt_ifmsg(), too, so that if IFF_UP changes,
you will get two routing messages instead of one.
It never has in practice (that I've noticed) but I guess it could depend
on the interface? Any IFF_UP change has already happened at this stage, so
unless some other ~CANTCHANGE flags were modified by the up/down code it
won't be triggered.

Also, I didn't check that if_flags is changed from other code paths so it
could be that its not the whole story.

iain

--
Posted automagically by a mail2news gateway at muc.de e.V.
Please direct questions, flames, donations, etc. to news-***@muc.de
David Young
2009-05-13 21:37:53 UTC
Permalink
Post by Iain Hibbert
Post by David Young
if_up() and if_down() call rt_ifmsg(), too, so that if IFF_UP changes,
you will get two routing messages instead of one.
It never has in practice (that I've noticed) but I guess it could depend
on the interface? Any IFF_UP change has already happened at this stage, so
unless some other ~CANTCHANGE flags were modified by the up/down code it
won't be triggered.
You are right, of course. I had misinterpreted the code.

Dave
--
David Young OJC Technologies
***@ojctech.com Urbana, IL * (217) 278-3933

--
Posted automagically by a mail2news gateway at muc.de e.V.
Please direct questions, flames, donations, etc. to news-***@muc.de
Iain Hibbert
2009-05-13 20:48:05 UTC
Permalink
Post by Quentin Garnier
Post by der Mouse
Extending the tap driver would be less invasive but unfortunately the
tap IO is carried out on a file descriptor so is no way (?) to do out
of band communication (socket control messages would have been great
for this), the best I can come up with is to have an ioctl enable
(eg) SIGUSR to be raised on informational changes and have the daemon
check.
thoughts and suggestions?
I would be inclined to do it in the tap driver. I would probably do
this by providing a tap-specific ioctl which puts it into a mode where
data, at least tap->user, has a header that (possibly among other
things) allows userland to distinguish between packets and other
ancillary data. The default, of course, would be no header and no
out-of-band data.
Mm, this sounds interesting and it would actually be quite simple to
process a header (in btpand) as its already doing the ethernet header.
Post by Quentin Garnier
Post by der Mouse
Whether the mode applies to the fd or to the tap device is an open
question. The former makes more sense; I would expect the latter to be
easier to do. In practice I don't expect there's much difference.
I think there is no difference because there can be only one fd per
device with tap anyway
Post by Quentin Garnier
Post by der Mouse
Another possibility would be a (tap-specific) ioctl which opens and
returns another file descriptor for the out-of-band data. I'm not sure
which of these two I prefer - probably whichever looks easier to
implement.
I didn't think of that either, it would be easier to pass complete
information on a separate descriptor (and would save a bunch of fiddling
around trying to fetch information) though it starts to look just like
route(4) but private to tap(4)
Post by Quentin Garnier
I think you can do all that using tap-specific kqueue filters. (See
kqueue(2), kfilter_register(9) and knote(9).)
I guess so, though I'm not desperately keen on that as btpand is using the
event(3) API and although that does internally use kqueue (by default), I
don't think there is a way to add events that would trigger from a custom
kevent..

iain

--
Posted automagically by a mail2news gateway at muc.de e.V.
Please direct questions, flames, donations, etc. to news-***@muc.de
der Mouse
2009-05-13 21:18:55 UTC
Permalink
Post by Iain Hibbert
Post by der Mouse
Whether the mode applies to the fd or to the tap device is an open
question. The former makes more sense; I would expect the latter
to be easier to do. In practice I don't expect there's much
difference.
I think there is no difference because there can be only one fd per
device with tap anyway
Not quite; consider dup() and fork().

However, there actually are three places the mode could, in principle,
be kept: (1) the fd; (2) the open file entry; (3) the tap device.
dup() and fork() and friends create new fds referring to the same open
file entry (the difference between fds and open file entries is not
very visible; the commonest case I can think of where it's visible is
that a seekable fd's lseek pointer is kept in the opne file entry
rather than the fd).

If tap control devices are exclusive-open, then assuming there is at
most one open file entry per tap device is reasonable, in which case
not worrying about the distinction between (2) and (3) is equally
reasonable.

/~\ The ASCII Mouse
\ / Ribbon Campaign
X Against HTML ***@rodents-montreal.org
/ \ Email! 7D C8 61 52 5D E7 2D 39 4E F1 31 3E E8 B3 27 4B

--
Posted automagically by a mail2news gateway at muc.de e.V.
Please direct questions, flames, donations, etc. to news-***@muc.de
David Laight
2009-05-13 21:49:58 UTC
Permalink
Post by der Mouse
Post by Iain Hibbert
I think there is no difference because there can be only one fd per
device with tap anyway
Not quite; consider dup() and fork().
Both dup() and fork() have the same effect - extra 'fd' referencing the 'file'.
open("/dev/fd/n", ...) will give you a 2nd kernel file structure.

while (open("/dev/fd/0", ...) != -1);
is a good local user DoS attack :-)

David
--
David Laight: ***@l8s.co.uk

--
Posted automagically by a mail2news gateway at muc.de e.V.
Please direct questions, flames, donations, etc. to news-***@muc.de
Loading...