On Friday 27 February 2015 13:50:55 Lankswert, Patrick wrote:
> BSD sockets as the standard for IP communication clearly expresses UDP
> packet
> routing and interface expression. However, it is expressed several ways.
>
> 1) They are bound BEFORE use, but given it is bound to all interfaces
> (inaddr_any), you can send via any interface as long as the routing tables
> agree.
> 2) However, binding to inaddr_any does not work for multicast as the IP
> stack
> select only one interface as the default multicast interface. You usually
> bind
> multiple sockets to each multicast interface to control which one to use.
> 3) Receiving is even more complicated but not hard.
Right.
> So, how would we suggest proceeding. Assuming that we are just talking about
> broadcast/multicast/discovery operations, it may be nice to have an old
> select() style mask where you can enumerate your interfaces by index and use
> a
> bitmask on broadcast/multicast/discovery operations. In this world, the
> (crude)
> interface might look like (pick on the approach/thought, not the code,
> please):
>
> // The following struct COULD be one of the standard netlink or BSD structs
> // This is just for example purposes
> struct iface {
> uint8_t wan : 1;
> uint8_t wireless : 1;
> uint8_t secure: 1;
> char name[8];
> // blah
> }
There is a macro with the maximum name length (IFNAMESIZE), so we can use
that.
What are the bits supposed to mean? Detecting the WAN interface may not be so
simple. It might be possible to do this on the majority of cases by scanning
the routing table, but it will fail on edge cases (e.g., my laptop when
connected to both Intel office's wired and wireless). But that same algorithm
would conclude that my regular wireless on my laptop is WAN.
That said, I do agree we should provide a heuristic approach to trying to
detect which interface is connected to the outside world, if we can. We just
need to document the assumptions so people know when it may fail.
Why does the user care if the interface is wired or not? How about the bridge
interface that is both wired and wireless?
What is secure?
> int getIFaceCount(); // Returns the max index
> struct iface* getIFace(int index); // Returns NULL or iface record
Good idea. But remember that interface indexes don't have to be contiguous (my
router has 1-9 and 12-16).
Unless you meant our own interface numbers, separate from the interface index
from the OS, which would be used on sin6_scope_id in the IPv6 sockets.
> // If there is not a convenience method to get the mask for non-wan
> interfaces
> // The following would build the mask from scratch
> int mask = 0;
>
> for (int index = 0; index < MAX_IFACE && index < getIFaceCount(); ++index) {
> struct iface* temp = getIFace(index);
> if (temp && temp.wan != 0) {
> mask |= 1<<index;
> }
> }
>
> sendToAll(buffer, <blah>, <blah>, mask);
>
> // If you want to send to all use some macro like ALL_INTERFACE which is
> 0xFF
Interface numbers can easily go above 32 or even 64, so a number representing
a bitfield may not be enough. We'd need something like fd_set for that.
So select / fd_set isn't a bad idea, but it won't be in a plain integer.
It should also support operating on "negative mode": all interfaces except the
ones added to the set.
> Does that make sense? I think that this approach handles some of the issues
> that
> Thiago raised including multiple radios of the same type (ie. eth0, eth1,
> wan0, wan1, etc.)
FYI, here's what my router reports:
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode
DEFAULT group default
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP
mode DEFAULT group default qlen 1000
3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP
mode DEFAULT group default qlen 1000
4: sit0: <NOARP> mtu 1480 qdisc noop state DOWN mode DEFAULT group default
5: ifb0: <BROADCAST,NOARP> mtu 1500 qdisc noop state DOWN mode DEFAULT group
default qlen 32
6: ifb1: <BROADCAST,NOARP> mtu 1500 qdisc noop state DOWN mode DEFAULT group
default qlen 32
7: gre0: <NOARP> mtu 1476 qdisc noop state DOWN mode DEFAULT group default
8: gretap0: <BROADCAST,MULTICAST> mtu 1476 qdisc noop state DOWN mode DEFAULT
group default qlen 1000
9: teql0: <NOARP> mtu 1500 qdisc noop state DOWN mode DEFAULT group default
qlen 100
12: br-lan: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP
mode DEFAULT group default
13: eth0.1 at eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue
master br-lan state UP mode DEFAULT group default
14: wlan0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq master br-lan
state UP mode DEFAULT group default qlen 1000
15: wlan1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq master br-lan
state UP mode DEFAULT group default qlen 1000
16: wlan0-1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP mode
DEFAULT group default qlen 1000
I have no idea what ifb0, ifb1, teql0 are. I know sit0 is the IPv4-in-IPv6
interface, while "GRE" is a tunnelling protocol so I assume gre0 and gretap0
are interfaces for that.
eth1 is connected to the WAN port on the router, while eth0 is connected to
the internal switch, which is why there's an eth0.1 at eth0 (a VLAN interface).
wlan0 is the 2.4 GHz radio and wlan1 is the 5 GHz one; wlan0-1 is the second
SSID on the 2.4 GHz radio (guest / free network).
Finally, br-lan is the bridge interface, linking eth0, wlan0 and wlan1
together.
--
Thiago Macieira - thiago.macieira (AT) intel.com
Software Architect - Intel Open Source Technology Center