net: virtual: Hook into packet filter processing

Make sure that we check possible network packet filtering status
before accepting the packet.

Signed-off-by: Jukka Rissanen <jukka.rissanen@nordicsemi.no>
This commit is contained in:
Jukka Rissanen 2025-04-11 09:49:06 +03:00 committed by Benjamin Cabé
commit bd3ce84d91

View file

@ -25,6 +25,7 @@ static enum net_verdict virtual_recv(struct net_if *iface,
{
struct virtual_interface_context *ctx, *tmp;
const struct virtual_interface_api *api;
struct net_if *filtered_iface = NULL;
enum net_verdict verdict;
sys_slist_t *interfaces;
@ -46,6 +47,28 @@ static enum net_verdict virtual_recv(struct net_if *iface,
continue;
}
if (IS_ENABLED(CONFIG_NET_PKT_FILTER)) {
struct net_if *tmp_iface;
tmp_iface = net_pkt_iface(pkt);
net_pkt_set_iface(pkt, ctx->virtual_iface);
if (!net_pkt_filter_recv_ok(pkt)) {
/* We cannot update the statistics here because
* the interface might not be the correct one for
* the packet. We would know that only after the
* call to api->recv() which is too late. So mark
* the interface as filtered and continue and
* update the filter statistics out of the loop.
*/
net_pkt_set_iface(pkt, tmp_iface);
filtered_iface = tmp_iface;
continue;
}
net_pkt_set_iface(pkt, tmp_iface);
}
verdict = api->recv(ctx->virtual_iface, pkt);
if (verdict == NET_CONTINUE) {
continue;
@ -69,14 +92,11 @@ static enum net_verdict virtual_recv(struct net_if *iface,
return verdict;
}
if (IS_ENABLED(CONFIG_NET_STATISTICS)) {
size_t pkt_len;
pkt_len = net_pkt_get_len(pkt);
NET_DBG("Received pkt %p len %zu", pkt, pkt_len);
net_stats_update_bytes_recv(iface, pkt_len);
if (IS_ENABLED(CONFIG_NET_PKT_FILTER) && filtered_iface != NULL) {
/* We need to update the statistics for the filtered iface here.
*/
net_stats_update_filter_rx_drop(filtered_iface);
goto silent_drop;
}
/* If there are no virtual interfaces attached, then pass the packet
@ -89,14 +109,36 @@ static enum net_verdict virtual_recv(struct net_if *iface,
if (!net_if_is_up(iface)) {
NET_DBG("Interface %d is down.", net_if_get_by_iface(iface));
goto drop;
goto silent_drop;
}
return api->recv(iface, pkt);
if (!net_pkt_filter_recv_ok(pkt)) {
net_stats_update_filter_rx_drop(iface);
goto silent_drop;
}
verdict = api->recv(iface, pkt);
if (IS_ENABLED(CONFIG_NET_STATISTICS)) {
size_t pkt_len;
pkt_len = net_pkt_get_len(pkt);
NET_DBG("Received pkt %p len %zu", pkt, pkt_len);
net_stats_update_bytes_recv(iface, pkt_len);
}
if (verdict == NET_DROP) {
net_stats_update_processing_error(iface);
}
return verdict;
drop:
NET_DBG("No handler, dropping pkt %p len %zu", pkt, net_pkt_get_len(pkt));
silent_drop:
return NET_DROP;
}