Skip to content
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

Support multiple IPv4 netmasks per interface #68419

4 changes: 3 additions & 1 deletion drivers/modem/hl7800.c
Expand Up @@ -2168,7 +2168,9 @@ static bool on_cmd_atcmdinfo_ipaddr(struct net_buf **buf, uint16_t len)
LOG_ERR("Cannot set iface IPv4 addr");
}

net_if_ipv4_set_netmask(iface_ctx.iface, &iface_ctx.subnet);
net_if_ipv4_set_netmask_by_addr(iface_ctx.iface,
&new_ipv4_addr,
&iface_ctx.subnet);
net_if_ipv4_set_gw(iface_ctx.iface, &iface_ctx.gateway);
#endif
/* store the new IP addr */
Expand Down
2 changes: 1 addition & 1 deletion drivers/net/loopback.c
Expand Up @@ -50,7 +50,7 @@ static void loopback_init(struct net_if *iface)
LOG_ERR("Failed to register IPv4 loopback address");
}

net_if_ipv4_set_netmask(iface, &netmask);
net_if_ipv4_set_netmask_by_addr(iface, &ipv4_loopback, &netmask);
}

if (IS_ENABLED(CONFIG_NET_IPV6)) {
Expand Down
4 changes: 2 additions & 2 deletions drivers/wifi/esp_at/esp.c
Expand Up @@ -514,13 +514,13 @@ static void esp_ip_addr_work(struct k_work *work)

#if defined(CONFIG_NET_NATIVE_IPV4)
/* update interface addresses */
net_if_ipv4_set_gw(dev->net_iface, &dev->gw);
net_if_ipv4_set_netmask(dev->net_iface, &dev->nm);
#if defined(CONFIG_WIFI_ESP_AT_IP_STATIC)
net_if_ipv4_addr_add(dev->net_iface, &dev->ip, NET_ADDR_MANUAL, 0);
#else
net_if_ipv4_addr_add(dev->net_iface, &dev->ip, NET_ADDR_DHCP, 0);
#endif
net_if_ipv4_set_gw(dev->net_iface, &dev->gw);
net_if_ipv4_set_netmask_by_addr(dev->net_iface, &dev->ip, &dev->nm);
#endif

if (IS_ENABLED(CONFIG_WIFI_ESP_AT_DNS_USE)) {
Expand Down
4 changes: 2 additions & 2 deletions drivers/wifi/eswifi/eswifi_core.c
Expand Up @@ -677,8 +677,8 @@ static int eswifi_mgmt_ap_enable(const struct device *dev,

/* Set IP Address */
for (i = 0; ipv4 && i < NET_IF_MAX_IPV4_ADDR; i++) {
if (ipv4->unicast[i].is_used) {
unicast = &ipv4->unicast[i];
if (ipv4->unicast[i].ipv4.is_used) {
unicast = &ipv4->unicast[i].ipv4;
break;
}
}
Expand Down
71 changes: 62 additions & 9 deletions include/zephyr/net/net_if.h
Expand Up @@ -368,19 +368,28 @@ struct net_if_dhcpv6 {
#endif
/** @endcond */

/**
* @brief Network Interface unicast IPv4 address and netmask
*
* Stores the unicast IPv4 address and related netmask.
*/
struct net_if_addr_ipv4 {
/** IPv4 address */
struct net_if_addr ipv4;
/** Netmask */
struct in_addr netmask;
};
jukkar marked this conversation as resolved.
Show resolved Hide resolved

struct net_if_ipv4 {
/** Unicast IP addresses */
struct net_if_addr unicast[NET_IF_MAX_IPV4_ADDR];
struct net_if_addr_ipv4 unicast[NET_IF_MAX_IPV4_ADDR];

/** Multicast IP addresses */
struct net_if_mcast_addr mcast[NET_IF_MAX_IPV4_MADDR];

/** Gateway */
struct in_addr gw;

/** Netmask */
struct in_addr netmask;

/** IPv4 time-to-live */
uint8_t ttl;

Expand Down Expand Up @@ -2279,34 +2288,78 @@ struct in_addr *net_if_ipv4_get_ll(struct net_if *iface,
struct in_addr *net_if_ipv4_get_global_addr(struct net_if *iface,
enum net_addr_state addr_state);

/**
* @brief Get IPv4 netmask related to an address of an interface.
*
* @param iface Interface to use.
* @param addr IPv4 address to check.
*
* @return The netmask set on the interface related to the give address,
* unspecified address if not found.
*/
struct in_addr net_if_ipv4_get_netmask_by_addr(struct net_if *iface,
const struct in_addr *addr);

/**
* @brief Get IPv4 netmask of an interface.
*
* @deprecated Use net_if_ipv4_get_netmask_by_addr() instead.
*
* @param iface Interface to use.
*
* @return The netmask set on the interface, unspecified address if not found.
*/
struct in_addr net_if_ipv4_get_netmask(struct net_if *iface);
__deprecated struct in_addr net_if_ipv4_get_netmask(struct net_if *iface);

/**
* @brief Set IPv4 netmask for an interface.
*
* @deprecated Use net_if_ipv4_set_netmask_by_addr() instead.
*
* @param iface Interface to use.
* @param netmask IPv4 netmask
*/
void net_if_ipv4_set_netmask(struct net_if *iface,
const struct in_addr *netmask);
__deprecated void net_if_ipv4_set_netmask(struct net_if *iface,
const struct in_addr *netmask);

/**
* @brief Set IPv4 netmask for an interface index.
*
* @deprecated Use net_if_ipv4_set_netmask_by_addr() instead.
*
* @param index Network interface index
* @param netmask IPv4 netmask
*
* @return True if netmask was added, false otherwise.
*/
__deprecated __syscall bool net_if_ipv4_set_netmask_by_index(int index,
const struct in_addr *netmask);

/**
* @brief Set IPv4 netmask for an interface index for a given address.
*
* @param index Network interface index
* @param addr IPv4 address related to this netmask
* @param netmask IPv4 netmask
*
* @return True if netmask was added, false otherwise.
*/
__syscall bool net_if_ipv4_set_netmask_by_addr_by_index(int index,
const struct in_addr *addr,
const struct in_addr *netmask);

/**
* @brief Set IPv4 netmask for an interface index for a given address.
*
* @param iface Network interface
* @param addr IPv4 address related to this netmask
* @param netmask IPv4 netmask
*
* @return True if netmask was added, false otherwise.
*/
__syscall bool net_if_ipv4_set_netmask_by_index(int index,
const struct in_addr *netmask);
bool net_if_ipv4_set_netmask_by_addr(struct net_if *iface,
const struct in_addr *addr,
const struct in_addr *netmask);

/**
* @brief Set IPv4 gateway for an interface.
Expand Down
6 changes: 4 additions & 2 deletions samples/boards/nxp_s32/netc/src/main.c
Expand Up @@ -54,12 +54,14 @@ static int setup_iface(struct net_if *iface, const char *ipv6_addr,
LOG_INF("IPv4 address: %s", ipv4_addr);

if (netmask && netmask[0]) {
if (net_addr_pton(AF_INET, netmask, &addr4)) {
struct in_addr nm;

if (net_addr_pton(AF_INET, netmask, &nm)) {
LOG_ERR("Invalid netmask: %s", netmask);
return -EINVAL;
}

net_if_ipv4_set_netmask(iface, &addr4);
net_if_ipv4_set_netmask_by_addr(iface, &addr4, &nm);
}
}

Expand Down
6 changes: 3 additions & 3 deletions samples/net/dhcpv4_client/src/main.c
Expand Up @@ -50,18 +50,18 @@ static void handler(struct net_mgmt_event_callback *cb,
for (i = 0; i < NET_IF_MAX_IPV4_ADDR; i++) {
char buf[NET_IPV4_ADDR_LEN];

if (iface->config.ip.ipv4->unicast[i].addr_type !=
if (iface->config.ip.ipv4->unicast[i].ipv4.addr_type !=
NET_ADDR_DHCP) {
continue;
}

LOG_INF(" Address[%d]: %s", net_if_get_by_iface(iface),
net_addr_ntop(AF_INET,
&iface->config.ip.ipv4->unicast[i].address.in_addr,
&iface->config.ip.ipv4->unicast[i].ipv4.address.in_addr,
buf, sizeof(buf)));
LOG_INF(" Subnet[%d]: %s", net_if_get_by_iface(iface),
net_addr_ntop(AF_INET,
&iface->config.ip.ipv4->netmask,
&iface->config.ip.ipv4->unicast[i].netmask,
buf, sizeof(buf)));
LOG_INF(" Router[%d]: %s", net_if_get_by_iface(iface),
net_addr_ntop(AF_INET,
Expand Down
8 changes: 5 additions & 3 deletions samples/net/dns_resolve/src/main.c
Expand Up @@ -168,6 +168,7 @@ static void print_dhcpv4_addr(struct net_if *iface, struct net_if_addr *if_addr,
{
bool *found = (bool *)user_data;
char hr_addr[NET_IPV4_ADDR_LEN];
struct in_addr netmask;

if (*found) {
return;
Expand All @@ -181,10 +182,11 @@ static void print_dhcpv4_addr(struct net_if *iface, struct net_if_addr *if_addr,
net_addr_ntop(AF_INET, &if_addr->address.in_addr,
hr_addr, NET_IPV4_ADDR_LEN));
LOG_INF("Lease time: %u seconds", iface->config.dhcpv4.lease_time);

netmask = net_if_ipv4_get_netmask_by_addr(iface,
&if_addr->address.in_addr);
LOG_INF("Subnet: %s",
net_addr_ntop(AF_INET,
&iface->config.ip.ipv4->netmask,
hr_addr, NET_IPV4_ADDR_LEN));
net_addr_ntop(AF_INET, &netmask, hr_addr, NET_IPV4_ADDR_LEN));
LOG_INF("Router: %s",
net_addr_ntop(AF_INET,
&iface->config.ip.ipv4->gw,
Expand Down
8 changes: 6 additions & 2 deletions samples/net/ipv4_autoconf/src/main.c
Expand Up @@ -41,13 +41,17 @@ static void handler(struct net_mgmt_event_callback *cb,
for (i = 0; i < NET_IF_MAX_IPV4_ADDR; i++) {
char buf[NET_IPV4_ADDR_LEN];

if (cfg->ip.ipv4->unicast[i].addr_type != NET_ADDR_AUTOCONF) {
if (cfg->ip.ipv4->unicast[i].ipv4.addr_type != NET_ADDR_AUTOCONF) {
continue;
}

LOG_INF("Your address: %s",
net_addr_ntop(AF_INET,
&cfg->ip.ipv4->unicast[i].address.in_addr,
&cfg->ip.ipv4->unicast[i].ipv4.address.in_addr,
buf, sizeof(buf)));
LOG_INF("Your netmask: %s",
net_addr_ntop(AF_INET,
&cfg->ip.ipv4->unicast[i].netmask,
buf, sizeof(buf)));
}
}
Expand Down
6 changes: 4 additions & 2 deletions samples/net/mdns_responder/src/vlan.c
Expand Up @@ -86,12 +86,14 @@ static int setup_iface(struct net_if *iface, const char *ipv6_addr,
}

if (netmask && netmask[0]) {
if (net_addr_pton(AF_INET, netmask, &addr4)) {
struct in_addr nm;

if (net_addr_pton(AF_INET, netmask, &nm)) {
LOG_ERR("Invalid netmask: %s", ipv4_addr);
return -EINVAL;
}

net_if_ipv4_set_netmask(iface, &addr4);
net_if_ipv4_set_netmask_by_addr(iface, &addr4, &nm);
}
}

Expand Down
6 changes: 4 additions & 2 deletions samples/net/sockets/echo_server/src/vlan.c
Expand Up @@ -86,12 +86,14 @@ static int setup_iface(struct net_if *iface, const char *ipv6_addr,
}

if (netmask && netmask[0]) {
if (net_addr_pton(AF_INET, netmask, &addr4)) {
struct in_addr nm;

if (net_addr_pton(AF_INET, netmask, &nm)) {
LOG_ERR("Invalid netmask: %s", ipv4_addr);
return -EINVAL;
}

net_if_ipv4_set_netmask(iface, &addr4);
net_if_ipv4_set_netmask_by_addr(iface, &addr4, &nm);
}
}

Expand Down
6 changes: 4 additions & 2 deletions samples/net/virtual/src/main.c
Expand Up @@ -302,12 +302,14 @@ static int setup_iface(struct net_if *iface,
}

if (netmask) {
if (net_addr_pton(AF_INET, netmask, &addr4)) {
struct in_addr nm;

if (net_addr_pton(AF_INET, netmask, &nm)) {
LOG_ERR("Invalid netmask: %s", netmask);
return -EINVAL;
}

net_if_ipv4_set_netmask(iface, &addr4);
net_if_ipv4_set_netmask_by_addr(iface, &addr4, &nm);
}

if (!peer4addr || *peer4addr == '\0') {
Expand Down
19 changes: 5 additions & 14 deletions samples/subsys/mgmt/hawkbit/src/dhcp.c
Expand Up @@ -22,24 +22,15 @@ static void handler(struct net_mgmt_event_callback *cb,
uint32_t mgmt_event,
struct net_if *iface)
{
int i;
bool notified = false;

if (mgmt_event != NET_EVENT_IPV4_ADDR_ADD) {
if (mgmt_event != NET_EVENT_IPV4_DHCP_BOUND) {
return;
}

for (i = 0; i < NET_IF_MAX_IPV4_ADDR; i++) {
if (iface->config.ip.ipv4->unicast[i].addr_type !=
NET_ADDR_DHCP) {
continue;
}

if (!notified) {
k_sem_give(&got_address);
notified = true;
}
break;
if (!notified) {
k_sem_give(&got_address);
notified = true;
}
}

Expand All @@ -51,7 +42,7 @@ void app_dhcpv4_startup(void)
struct net_if *iface;

net_mgmt_init_event_callback(&mgmt_cb, handler,
NET_EVENT_IPV4_ADDR_ADD);
NET_EVENT_IPV4_DHCP_BOUND);
net_mgmt_add_event_callback(&mgmt_cb);

iface = net_if_get_default();
Expand Down
4 changes: 3 additions & 1 deletion subsys/net/ip/ipv4_autoconf.c
Expand Up @@ -182,7 +182,9 @@ static inline void ipv4_autoconf_addr_set(struct net_if_ipv4_autoconf *ipv4auto)
return;
}

net_if_ipv4_set_netmask(ipv4auto->iface, &netmask);
net_if_ipv4_set_netmask_by_addr(ipv4auto->iface,
&ipv4auto->requested_ip,
&netmask);

ipv4auto->state = NET_IPV4_AUTOCONF_ASSIGNED;
}
Expand Down