1
0
mirror of https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git synced 2026-01-17 03:50:37 +00:00
torvalds-linux/include/net/inet_dscp.h
Guillaume Nault 1bec9d0c00 ipv4: Convert ->flowi4_tos to dscp_t.
Convert the ->flowic_tos field of struct flowi_common from __u8 to
dscp_t, rename it ->flowic_dscp and propagate these changes to struct
flowi and struct flowi4.

We've had several bugs in the past where ECN bits could interfere with
IPv4 routing, because these bits were not properly cleared when setting
->flowi4_tos. These bugs should be fixed now and the dscp_t type has
been introduced to ensure that variables carrying DSCP values don't
accidentally have any ECN bits set. Several variables and structure
fields have been converted to dscp_t already, but the main IPv4 routing
structure, struct flowi4, is still using a __u8. To avoid any future
regression, this patch converts it to dscp_t.

There are many users to convert at once. Fortunately, around half of
->flowi4_tos users already have a dscp_t value at hand, which they
currently convert to __u8 using inet_dscp_to_dsfield(). For all of
these users, we just need to drop that conversion.

But, although we try to do the __u8 <-> dscp_t conversions at the
boundaries of the network or of user space, some places still store
TOS/DSCP variables as __u8 in core networking code. Those can hardly be
converted either because the data structure is part of UAPI or because
the same variable or field is also used for handling ECN in other parts
of the code. In all of these cases where we don't have a dscp_t
variable at hand, we need to use inet_dsfield_to_dscp() when
interacting with ->flowi4_dscp.

Changes since v1:
  * Fix space alignment in __bpf_redirect_neigh_v4() (Ido).

Signed-off-by: Guillaume Nault <gnault@redhat.com>
Reviewed-by: Ido Schimmel <idosch@nvidia.com>
Link: https://patch.msgid.link/29acecb45e911d17446b9a3dbdb1ab7b821ea371.1756128932.git.gnault@redhat.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2025-08-26 17:34:31 -07:00

64 lines
1.8 KiB
C

/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
* inet_dscp.h: helpers for handling differentiated services codepoints (DSCP)
*
* DSCP is defined in RFC 2474:
*
* 0 1 2 3 4 5 6 7
* +---+---+---+---+---+---+---+---+
* | DSCP | CU |
* +---+---+---+---+---+---+---+---+
*
* DSCP: differentiated services codepoint
* CU: currently unused
*
* The whole DSCP + CU bits form the DS field.
* The DS field is also commonly called TOS or Traffic Class (for IPv6).
*
* Note: the CU bits are now used for Explicit Congestion Notification
* (RFC 3168).
*/
#ifndef _INET_DSCP_H
#define _INET_DSCP_H
#include <linux/types.h>
/* Special type for storing DSCP values.
*
* A dscp_t variable stores a DS field with the CU (ECN) bits cleared.
* Using dscp_t allows to strictly separate DSCP and ECN bits, thus avoiding
* bugs where ECN bits are erroneously taken into account during FIB lookups
* or policy routing.
*
* Note: to get the real DSCP value contained in a dscp_t variable one would
* have to do a bit shift after calling inet_dscp_to_dsfield(). We could have
* a helper for that, but there's currently no users.
*/
typedef u8 __bitwise dscp_t;
#define INET_DSCP_MASK 0xfc
/* A few places in the IPv4 code need to ignore the three high order bits of
* DSCP because of backward compatibility (as these bits used to represent the
* IPv4 Precedence in RFC 791's TOS field and were ignored).
*/
#define INET_DSCP_LEGACY_TOS_MASK ((__force dscp_t)0x1c)
static inline dscp_t inet_dsfield_to_dscp(__u8 dsfield)
{
return (__force dscp_t)(dsfield & INET_DSCP_MASK);
}
static inline __u8 inet_dscp_to_dsfield(dscp_t dscp)
{
return (__force __u8)dscp;
}
static inline bool inet_validate_dscp(__u8 val)
{
return !(val & ~INET_DSCP_MASK);
}
#endif /* _INET_DSCP_H */