Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 46 additions & 5 deletions doc/connectivity/networking/api/net_pkt_filter.rst
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,9 @@ Overview

The Network Packet Filtering facility provides the infrastructure to
construct custom rules for accepting and/or denying packet transmission
and reception. This can be used to create a basic firewall, control
network traffic, etc.
and reception. It also allows to modify the priority of incoming
network packets. This can be used to create a basic firewall, control network
traffic, etc.

The :kconfig:option:`CONFIG_NET_PKT_FILTER` must be set in order to enable the
relevant APIs.
Expand All @@ -25,8 +26,13 @@ for a given rule are true then the packet outcome is immediately determined
as specified by the current rule and no more rules are considered. If one
condition is false then the next rule in the list is considered.

Packet outcome is either ``NET_OK`` to accept the packet or ``NET_DROP`` to
drop it.
Packet outcome is either ``NET_OK`` to accept the packet, ``NET_DROP`` to
drop it or ``NET_CONTINUE`` to modify its priority on the fly.

When the outcome is ``NET_CONTINUE`` the priority is updated but the final
outcome is not yet determined and processing continues. If all conditions of
multiple rules are true, then the packet gets the priority of the rule last
considered.

A rule is represented by a :c:struct:`npf_rule` object. It can be inserted to,
appended to or removed from a rule list contained in a
Expand All @@ -47,7 +53,8 @@ retrieve the outer structure from the provided ``npf_test`` structure pointer.

Convenience macros are provided in :zephyr_file:`include/zephyr/net/net_pkt_filter.h`
to statically define condition instances for various conditions, and
:c:macro:`NPF_RULE()` to create a rule instance to tie them.
:c:macro:`NPF_RULE()` and :c:macro:`NPF_PRIORITY()` to create a rule instance
with an immediate outcome or a priority change.

Examples
********
Expand Down Expand Up @@ -86,6 +93,40 @@ Another (less efficient) way to achieve the same result could be:
npf_append_recv_rule(&npf_default_ok);
}

This example assigns priorities to different network traffic. It gives network
control priority (``NET_PRIORITY_NC``) to the ``ptp`` packets, critical
applications priority (``NET_PRIORITY_CA``) to the internet traffic of version
6, excellent effort (``NET_PRIORITY_EE``) for internet protocol version 4
traffic, and the lowest background priority (``NET_PRIORITY_BK``) to ``lldp``
and ``arp``.

Priority rules are only really useful if multiple traffic class queues are
enabled in the project configuration :kconfig:option:`CONFIG_NET_TC_RX_COUNT`.
The mapping from the priority of the packet to the traffic class queue is in
accordance with the standard 802.1Q and depends on the
:kconfig:option:`CONFIG_NET_TC_RX_COUNT`.

.. code-block:: c

static NPF_ETH_TYPE_MATCH(is_arp, NET_ETH_PTYPE_ARP);
static NPF_ETH_TYPE_MATCH(is_lldp, NET_ETH_PTYPE_LLDP);
static NPF_ETH_TYPE_MATCH(is_ptp, NET_ETH_PTYPE_PTP);
static NPF_ETH_TYPE_MATCH(is_ipv4, NET_ETH_PTYPE_IP);
static NPF_ETH_TYPE_MATCH(is_ipv6, NET_ETH_PTYPE_IPV6);

static NPF_PRIORITY(priority_bk, NET_PRIORITY_BK, is_arp, is_lldp);
static NPF_PRIORITY(priority_ee, NET_PRIORITY_EE, is_ipv4);
static NPF_PRIORITY(priority_ca, NET_PRIORITY_CA, is_ipv6);
static NPF_PRIORITY(priority_nc, NET_PRIORITY_NC, is_ptp);

void install_my_filter(void) {
npf_append_recv_rule(&priority_bk);
npf_append_recv_rule(&priority_ee);
npf_append_recv_rule(&priority_ca);
npf_append_recv_rule(&priority_nc);
npf_append_recv_rule(&npf_default_ok);
}

API Reference
*************

Expand Down
17 changes: 13 additions & 4 deletions include/zephyr/net/net_pkt_filter.h
Original file line number Diff line number Diff line change
Expand Up @@ -85,10 +85,11 @@ struct npf_test {

/** @brief filter rule structure */
struct npf_rule {
sys_snode_t node; /**< Slist rule list node */
enum net_verdict result; /**< result if all tests pass */
uint32_t nb_tests; /**< number of tests for this rule */
struct npf_test *tests[]; /**< pointers to @ref npf_test instances */
sys_snode_t node; /**< Slist rule list node */
enum net_verdict result; /**< result if all tests pass */
enum net_priority priority; /**< priority in case of NET_CONTINUE */
uint32_t nb_tests; /**< number of tests for this rule */
struct npf_test *tests[]; /**< pointers to @ref npf_test instances */
};

/** @brief Default rule list termination for accepting a packet */
Expand Down Expand Up @@ -242,6 +243,14 @@ bool npf_remove_all_rules(struct npf_rule_list *rules);
.tests = { FOR_EACH(Z_NPF_TEST_ADDR, (,), __VA_ARGS__) }, \
}

#define NPF_PRIORITY(_name, _priority, ...) \
struct npf_rule _name = { \
.result = NET_CONTINUE, \
.priority = (_priority), \
.nb_tests = NUM_VA_ARGS_LESS_1(__VA_ARGS__) + 1, \
.tests = {FOR_EACH(Z_NPF_TEST_ADDR, (,), __VA_ARGS__)}, \
}

#define Z_NPF_TEST_ADDR(arg) &arg.test

/** @} */
Expand Down
12 changes: 12 additions & 0 deletions samples/net/pkt_filter/prj.conf
Original file line number Diff line number Diff line change
Expand Up @@ -51,4 +51,16 @@ CONFIG_NET_CONFIG_PEER_IPV4_ADDR="192.0.2.2"

# Logging
CONFIG_LOG=y
CONFIG_LOG_MODE_DEFERRED=y
CONFIG_LOG_BUFFER_SIZE=4096

# VLAN settings. We will have two VLANs in this sample.
CONFIG_NET_VLAN=y
CONFIG_NET_VLAN_COUNT=2
CONFIG_NET_IF_MAX_IPV4_COUNT=3
CONFIG_NET_IF_MAX_IPV6_COUNT=3

# Network traffic class queues
CONFIG_NET_TC_THREAD_PREEMPTIVE=y
CONFIG_NET_TC_RX_COUNT=2
CONFIG_NET_TC_RX_SKIP_FOR_HIGH_PRIO=y
59 changes: 38 additions & 21 deletions samples/net/pkt_filter/src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,27 +26,38 @@ static NPF_IFACE_MATCH(match_iface_vlan1, NULL);
static NPF_IFACE_MATCH(match_iface_vlan2, NULL);
static NPF_IFACE_MATCH(match_iface_eth, NULL);

/* Allow all traffic to Ethernet interface, drop VLAN traffic except
* couple of exceptions for IPv4 and IPv6
*/
static NPF_RULE(eth_iface_rule, NET_OK, match_iface_eth);

/* Match ethernet packets for the precision time protocol (PTP) */
static NPF_ETH_TYPE_MATCH(match_ptype_ptp, NET_ETH_PTYPE_PTP);
/* Match ethernet packets for the virtual local area network (VLAN) */
static NPF_ETH_TYPE_MATCH(match_ptype_vlan, NET_ETH_PTYPE_VLAN);
/* Match max size rule */
static NPF_SIZE_MAX(maxsize_200, 200);
static NPF_ETH_VLAN_TYPE_MATCH(ipv4_packet1, NET_ETH_PTYPE_IP);
static NPF_RULE(small_ipv4_pkt, NET_OK, ipv4_packet1, maxsize_200,
match_iface_vlan1);

static NPF_SIZE_MAX(match_smaller_200, 200);
/* Match min size rule */
static NPF_SIZE_MIN(minsize_100, 100);
static NPF_ETH_VLAN_TYPE_MATCH(ipv4_packet2, NET_ETH_PTYPE_IP);
static NPF_RULE(large_ipv4_pkt, NET_OK, ipv4_packet2, minsize_100,
match_iface_vlan2);
static NPF_SIZE_MIN(match_bigger_100, 100);
/* Match virtual internet protocol traffic */
static NPF_ETH_VLAN_TYPE_MATCH(match_ipv4_vlan, NET_ETH_PTYPE_IP);
/* Match virtual address resolution protocol (ARP) traffic */
static NPF_ETH_VLAN_TYPE_MATCH(match_arp_vlan, NET_ETH_PTYPE_ARP);

/* Allow ARP for VLAN interface */
static NPF_ETH_VLAN_TYPE_MATCH(arp_packet, NET_ETH_PTYPE_ARP);
static NPF_RULE(arp_pkt_vlan1, NET_OK, arp_packet, match_iface_vlan1);
static NPF_RULE(arp_pkt_vlan2, NET_OK, arp_packet, match_iface_vlan2);
/* Allow all traffic to Ethernet interface */
static NPF_RULE(eth_iface_rule, NET_OK, match_iface_eth);
/* Maximal priority for ptp traffic */
static NPF_PRIORITY(eth_priority_ptp, NET_PRIORITY_NC, match_iface_eth, match_ptype_ptp);
/* Prioritize VLAN traffic on Ethernet interface */
static NPF_PRIORITY(eth_priority_vlan, NET_PRIORITY_EE, match_iface_eth, match_ptype_vlan);
/* Deprioritize all other traffic */
static NPF_PRIORITY(eth_priority_default, NET_PRIORITY_BK, match_iface_eth);

/* Allow only small ipv4 packets to the first VLAN interface */
static NPF_RULE(small_ipv4_pkt, NET_OK, match_iface_vlan1, match_ipv4_vlan, match_smaller_200);
/* Allow only ipv4 packets of minimum size to the second VLAN interface */
static NPF_RULE(large_ipv4_pkt, NET_OK, match_iface_vlan2, match_ipv4_vlan, match_bigger_100);
/* Allow ARP for both VLAN interfaces */
static NPF_RULE(arp_pkt_vlan1, NET_OK, match_iface_vlan1, match_arp_vlan);
static NPF_RULE(arp_pkt_vlan2, NET_OK, match_iface_vlan2, match_arp_vlan);
/* But give ARP the lowest priority */
static NPF_PRIORITY(arp_priority_vlan1, NET_PRIORITY_BK, match_iface_vlan1, match_arp_vlan);
static NPF_PRIORITY(arp_priority_vlan2, NET_PRIORITY_BK, match_iface_vlan2, match_arp_vlan);

static void iface_cb(struct net_if *iface, void *user_data)
{
Expand Down Expand Up @@ -106,7 +117,15 @@ static void init_app(void)
* optional interfaces (if VLAN is enabled).
* We allow all traffic to the Ethernet interface, but have
* filters for the VLAN interfaces.
*
* First append the priority rules, so that they get evaluated before
* deciding on the final verdict for the packet.
*/
npf_append_recv_rule(&eth_priority_default);
npf_append_recv_rule(&eth_priority_ptp);
npf_append_recv_rule(&eth_priority_vlan);
npf_append_recv_rule(&arp_priority_vlan1);
npf_append_recv_rule(&arp_priority_vlan2);

/* We allow small IPv4 packets to the VLAN interface 1 */
npf_append_recv_rule(&small_ipv4_pkt);
Expand All @@ -117,10 +136,8 @@ static void init_app(void)
/* We allow all traffic to the Ethernet interface */
npf_append_recv_rule(&eth_iface_rule);

/* We allow ARP traffic to the VLAN 1 interface */
/* We allow ARP traffic to both VLAN interfaces */
npf_append_recv_rule(&arp_pkt_vlan1);

/* We allow ARP traffic to the VLAN 2 interface */
npf_append_recv_rule(&arp_pkt_vlan2);

/* The remaining packets that do not match are dropped */
Expand Down
5 changes: 5 additions & 0 deletions samples/net/qos/QoS.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
.. zephyr:code-sample-category:: QoS
:name: Quality of Service
:show-listing:

These samples demonstrate packet filters for Quality of Service (QoS).
9 changes: 9 additions & 0 deletions samples/net/qos/ethernet/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# SPDX-License-Identifier: Apache-2.0

cmake_minimum_required(VERSION 3.20.0)

find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
project(ethernet_qos_demo)

FILE(GLOB app_sources src/*.c)
target_sources(app PRIVATE ${app_sources})
Loading