On Friday February 14, neilb@cse.unsw.edu.au wrote:
>
> It turns out that the problem occurs when send_msg is used to send a
> UDP packet, and the control information contains
> struct in_pktinfo {
> unsigned int ipi_ifindex; /* Interface index */
> struct in_addr ipi_spec_dst; /* Local address */
> struct in_addr ipi_addr; /* Header Destination address */
> };
> specifying the address and interface of the message that we are
> replying to.
Well, I took the plunge and hunted in and around the networking
code....
in net/ipv4/route.c, in ip_route_output_slow there is an if clause:
if (fib_lookup(&key, &res)) {
In my situation, fib_lookup will fail because key contains a
non-zero "oif" (output interface), but that interface does not have a
valid route to key.dst.
What should be done in that case? Well in my situation, the oif is
just a hint, not a requirement (it is, after all, the interface that
the request arrived on. It is not necessarily the interface that the
reply has to go out on). So possibly it should clear oif and try
fib_lookup again. But it doesn't.
This is a branch for "if oif is non-zero", and it is largely a
comment:
if (oldkey->oif) {
/* Apparently, routing tables are wrong. Assume,
that the destination is on link.
WHY? DW.
Because we are allowed to send to iface
even if it has NO routes and NO assigned
addresses. When oif is specified, routing
tables are looked up with only one purpose:
to catch if destination is gatewayed, rather than
direct. Moreover, if MSG_DONTROUTE is set,
we send packet, ignoring both routing tables
and ifaddr state. --ANK
We could make it even if oif is unknown,
likely IPv6, but we do not.
*/
if (key.src == 0)
key.src = inet_select_addr(dev_out, 0,
RT_SCOPE_LINK);
res.type = RTN_UNICAST;
goto make_route;
This comment seems to be considering a case where oif has been set as
an explicit request for the message to go on that interface, which is
not the case for "sendmsg" with an IP_PKTINFO attachment.
Maybe when ip_cmsg_send interprets the IP_PKTINFO and sets ipc->oif,
it should set some flag to say "hint". And then fib_lookup, or
possibly ip_route_output_slow, could test for that hint and re-try
with no oif if the first try fails..
But even that is not a complete solution. We would also need to
modify ip_route_output_key which scans a table of recently computed
routes to avoid having to do fib_lookup for every packet. This table
would need to know about oif's that are hints, and ones that are
requirements.
At about this point it got all a bit too complicated, so I haven't
bothered to try to patch the kernel to make it work right.
Rather, I noticed that if the interface specified does have a route to
the destination, that route will be taken rather than attempting to
directly send to the dest.
So I have added default routes to all of my interfaces, not just the
prefered one, and my symptoms have gone away (and I don't need
proxy-arp on the router any more).
This will satisfy my needs for now, but I feel that something should
be done to fix this problem the "right" way. I'm just not sure what.
NeilBrown
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
This archive was generated by hypermail 2b29 : Sun Feb 23 2003 - 22:00:16 EST