linux/include/net/inet_dscp.h
Guillaume Nault a410a0cf98 ipv6: Define dscp_t and stop taking ECN bits into account in fib6-rules
Define a dscp_t type and its appropriate helpers that ensure ECN bits
are not taken into account when handling DSCP.

Use this new type to replace the tclass field of struct fib6_rule, so
that fib6-rules don't get influenced by ECN bits anymore.

Before this patch, fib6-rules didn't make any distinction between the
DSCP and ECN bits. Therefore, rules specifying a DSCP (tos or dsfield
options in iproute2) stopped working as soon a packets had at least one
of its ECN bits set (as a work around one could create four rules for
each DSCP value to match, one for each possible ECN value).

After this patch fib6-rules only compare the DSCP bits. ECN doesn't
influence the result anymore. Also, fib6-rules now must have the ECN
bits cleared or they will be rejected.

Signed-off-by: Guillaume Nault <gnault@redhat.com>
Acked-by: David Ahern <dsahern@kernel.org>
Reviewed-by: Toke Høiland-Jørgensen <toke@redhat.com>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2022-02-07 20:12:45 -08:00

58 lines
1.6 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
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 */