Skip to content

Conversation

@anhuba
Copy link

@anhuba anhuba commented Jan 9, 2026

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.

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]>
@sonarqubecloud
Copy link

sonarqubecloud bot commented Jan 9, 2026

Copy link
Contributor

@rlubos rlubos left a 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,
Copy link
Contributor

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));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
return((addr1 & netmask) == (addr2 & netmask));
return ((addr1 & netmask) == (addr2 & netmask));

Comment on lines -246 to +258
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))) {
Copy link
Contributor

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)

Comment on lines +239 to +240
const uint8_t *addr,
const struct net_in_addr *netaddr)
Copy link
Contributor

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).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants