-
Notifications
You must be signed in to change notification settings - Fork 8.5k
net: Choose IP corresponding to the same network #102036
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
net: Choose IP corresponding to the same network #102036
Conversation
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 <[email protected]>
dae1a03 to
10d9acf
Compare
2ea1822 to
cf7bdc2
Compare
|
rlubos
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please use net: arp: For the commit title prefix, it's an ARP-specifc change.
| k_mutex_unlock(&arp_mutex); | ||
| } | ||
|
|
||
| static inline bool is_same_net(uint32_t addr1, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is_same_subnet would be more descriptive IMO. Also please fix the indentation, it's off the charts.
| uint32_t addr2, | ||
| uint32_t netmask) | ||
| { | ||
| return((addr1 & netmask) == (addr2 & netmask)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| return((addr1 & netmask) == (addr2 & netmask)); | |
| return ((addr1 & netmask) == (addr2 & netmask)); |
| 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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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)
| const uint8_t *addr, | ||
| const struct net_in_addr *netaddr) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We have two address variables now, it's hard to tell which one represents what. I suggest we call them own_addr and dst_addr for more clarity (the ARP code is already pretty complex enough to follow).



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.