net: Choose IP corresponding to the same network#102036
net: Choose IP corresponding to the same network#102036henrikbrixandersen merged 1 commit intozephyrproject-rtos:mainfrom
Conversation
dae1a03 to
10d9acf
Compare
2ea1822 to
cf7bdc2
Compare
rlubos
left a comment
There was a problem hiding this comment.
Please use net: arp: For the commit title prefix, it's an ARP-specifc change.
| addr, ipv4->unicast[i].ipv4.address.in_addr.s4_addr))) { | ||
| addr, ipv4->unicast[i].ipv4.address.in_addr.s4_addr)) && | ||
| (!netaddr || | ||
| is_same_net(netaddr->s_addr, | ||
| ipv4->unicast[i].ipv4.address.in_addr.s_addr, | ||
| ipv4->unicast[i].netmask.s_addr))) { |
There was a problem hiding this comment.
So if I read this correctly we'll now have a change in behavior in case there's no subnet match with any of the addresses on the interface. I.e. so far we'd choose any valid address as the source for the ARP request, but now we'd send unspec address as a source on subnet mismatch.
I'm generally fine with the proposed change to prefer addresses on the same subnet, but as I said it should be a preference, not a hard requirement. What if we rewrite the function a bit (which hopefully will improve the clarity as well):
static inline struct net_in_addr *if_get_addr(struct net_if *iface,
const uint8_t *own_addr,
const struct net_in_addr *dst_addr)
{
struct net_if_ipv4 *ipv4 = iface->config.ip.ipv4;
struct net_in_addr *best_match = NULL;
if (!ipv4) {
return NULL;
}
ARRAY_FOR_EACH(ipv4->unicast, i) {
if (ipv4->unicast[i].ipv4.is_used &&
ipv4->unicast[i].ipv4.address.family == NET_AF_INET &&
ipv4->unicast[i].ipv4.addr_state == NET_ADDR_PREFERRED) {
if (own_addr != NULL) {
/* Specific address requested as own address. */
if (!net_ipv4_addr_cmp_raw(
own_addr,
ipv4->unicast[i].ipv4.address.in_addr.s4_addr)) {
/* No match, try next. */
continue;
}
/* Got exact match. */
best_match = &ipv4->unicast[i].ipv4.address.in_addr;
break;
}
/* Prefer address on the same subnet as destination. */
if (dst_addr != NULL &&
is_same_subnet(dst_addr->s_addr,
ipv4->unicast[i].ipv4.address.in_addr.s_addr,
ipv4->unicast[i].netmask.s_addr)) {
/* Got address on the same subnet. */
best_match = &ipv4->unicast[i].ipv4.address.in_addr;
break;
}
/* Fallback to any valid address on hte interface. */
if (best_match == NULL) {
best_match = &ipv4->unicast[i].ipv4.address.in_addr;
}
}
}
return best_match;
}(please note I haven't tested this)
There was a problem hiding this comment.
Do we actually get ARP requests from the upper layer for IP addresses not configured on our interface?
If we do, would that not be a bug in the upper layer?
If we fill in the wrong sender IP in the ARP request, we might get an ARP reply from most devices (as most implementations seem to ignore the sender IP) as before the fix, but we still won't get ARP replies for devices which ignore our request due to the wrong sender IP.
There was a problem hiding this comment.
Upper layer doesn't really care if the address is on the local network or not, it's the ARP layer that makes decision whether to try to resolve address directly, or try to use GW address instead:
https://github.com/zephyrproject-rtos/zephyr/blob/76dd50833fabb56a8de65f01629f205de6c4f155/subsys/net/l2/ethernet/arp.c#L382C22-L401
So in general, yes, we should only be resolving addresses in local network, however there is for example this corner case with LL IPv4 address, if we only have link-local address configured on the interface we still try to resolve the target address as best effort appraoch. And if we force subnet matching, it'd no longer work.
There was a problem hiding this comment.
Ok, I have rewritten to take the IP of the matching subnet, if available and use the same IP as before as a fall back.
cf7bdc2 to
9d7b11b
Compare
9d7b11b to
9fbbfbe
Compare
If we have more than one IP on an interface we should choose the IP corresponding to the same network as the target IP. Signed-off-by: Andreas Huber <andreas.huber@sautergroup.com>
9fbbfbe to
e2999c7
Compare
|



If we have more than one IP on an interface we should choose the IP corresponding to the same network as the target IP. Otherwise we might not get ARP replies from some devices.