xref: /openbmc/linux/include/net/gue.h (revision 4f2c0a4acffbec01079c28f839422e64ddeff004)
1b2441318SGreg Kroah-Hartman /* SPDX-License-Identifier: GPL-2.0 */
237dd0247STom Herbert #ifndef __NET_GUE_H
337dd0247STom Herbert #define __NET_GUE_H
437dd0247STom Herbert 
55024c33aSTom Herbert /* Definitions for the GUE header, standard and private flags, lengths
65024c33aSTom Herbert  * of optional fields are below.
75024c33aSTom Herbert  *
85024c33aSTom Herbert  * Diagram of GUE header:
95024c33aSTom Herbert  *
105024c33aSTom Herbert  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
115024c33aSTom Herbert  * |Ver|C|  Hlen   | Proto/ctype   |        Standard flags       |P|
125024c33aSTom Herbert  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
135024c33aSTom Herbert  * |                                                               |
145024c33aSTom Herbert  * ~                      Fields (optional)                        ~
155024c33aSTom Herbert  * |                                                               |
165024c33aSTom Herbert  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
175024c33aSTom Herbert  * |            Private flags (optional, P bit is set)             |
185024c33aSTom Herbert  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
195024c33aSTom Herbert  * |                                                               |
205024c33aSTom Herbert  * ~                   Private fields (optional)                   ~
215024c33aSTom Herbert  * |                                                               |
225024c33aSTom Herbert  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
235024c33aSTom Herbert  *
2426ac10beSAiden Leong  * C bit indicates control message when set, data message when unset.
255024c33aSTom Herbert  * For a control message, proto/ctype is interpreted as a type of
265024c33aSTom Herbert  * control message. For data messages, proto/ctype is the IP protocol
275024c33aSTom Herbert  * of the next header.
285024c33aSTom Herbert  *
295024c33aSTom Herbert  * P bit indicates private flags field is present. The private flags
305024c33aSTom Herbert  * may refer to options placed after this field.
315024c33aSTom Herbert  */
325024c33aSTom Herbert 
33*949d6b40SJakub Kicinski #include <asm/byteorder.h>
34*949d6b40SJakub Kicinski #include <linux/types.h>
35*949d6b40SJakub Kicinski 
3637dd0247STom Herbert struct guehdr {
3737dd0247STom Herbert 	union {
3837dd0247STom Herbert 		struct {
3937dd0247STom Herbert #if defined(__LITTLE_ENDIAN_BITFIELD)
405024c33aSTom Herbert 			__u8	hlen:5,
415024c33aSTom Herbert 				control:1,
425024c33aSTom Herbert 				version:2;
4337dd0247STom Herbert #elif defined (__BIG_ENDIAN_BITFIELD)
445024c33aSTom Herbert 			__u8	version:2,
455024c33aSTom Herbert 				control:1,
465024c33aSTom Herbert 				hlen:5;
4737dd0247STom Herbert #else
4837dd0247STom Herbert #error  "Please fix <asm/byteorder.h>"
4937dd0247STom Herbert #endif
505024c33aSTom Herbert 			__u8	proto_ctype;
5120080971SXin Long 			__be16	flags;
5237dd0247STom Herbert 		};
5320080971SXin Long 		__be32	word;
5437dd0247STom Herbert 	};
5537dd0247STom Herbert };
5637dd0247STom Herbert 
575024c33aSTom Herbert /* Standard flags in GUE header */
585024c33aSTom Herbert 
595024c33aSTom Herbert #define GUE_FLAG_PRIV	htons(1<<0)	/* Private flags are in options */
605024c33aSTom Herbert #define GUE_LEN_PRIV	4
615024c33aSTom Herbert 
625024c33aSTom Herbert #define GUE_FLAGS_ALL	(GUE_FLAG_PRIV)
635024c33aSTom Herbert 
645024c33aSTom Herbert /* Private flags in the private option extension */
655024c33aSTom Herbert 
6688405680SVandana BN #define GUE_PFLAG_REMCSUM	htonl(1U << 31)
67c1aa8347STom Herbert #define GUE_PLEN_REMCSUM	4
68c1aa8347STom Herbert 
69c1aa8347STom Herbert #define GUE_PFLAGS_ALL	(GUE_PFLAG_REMCSUM)
705024c33aSTom Herbert 
715024c33aSTom Herbert /* Functions to compute options length corresponding to flags.
725024c33aSTom Herbert  * If we ever have a lot of flags this can be potentially be
735024c33aSTom Herbert  * converted to a more optimized algorithm (table lookup
745024c33aSTom Herbert  * for instance).
755024c33aSTom Herbert  */
guehdr_flags_len(__be16 flags)765024c33aSTom Herbert static inline size_t guehdr_flags_len(__be16 flags)
775024c33aSTom Herbert {
785024c33aSTom Herbert 	return ((flags & GUE_FLAG_PRIV) ? GUE_LEN_PRIV : 0);
795024c33aSTom Herbert }
805024c33aSTom Herbert 
guehdr_priv_flags_len(__be32 flags)815024c33aSTom Herbert static inline size_t guehdr_priv_flags_len(__be32 flags)
825024c33aSTom Herbert {
835024c33aSTom Herbert 	return 0;
845024c33aSTom Herbert }
855024c33aSTom Herbert 
865024c33aSTom Herbert /* Validate standard and private flags. Returns non-zero (meaning invalid)
875024c33aSTom Herbert  * if there is an unknown standard or private flags, or the options length for
885024c33aSTom Herbert  * the flags exceeds the options length specific in hlen of the GUE header.
895024c33aSTom Herbert  */
validate_gue_flags(struct guehdr * guehdr,size_t optlen)9020080971SXin Long static inline int validate_gue_flags(struct guehdr *guehdr, size_t optlen)
915024c33aSTom Herbert {
9220080971SXin Long 	__be16 flags = guehdr->flags;
935024c33aSTom Herbert 	size_t len;
945024c33aSTom Herbert 
955024c33aSTom Herbert 	if (flags & ~GUE_FLAGS_ALL)
965024c33aSTom Herbert 		return 1;
975024c33aSTom Herbert 
985024c33aSTom Herbert 	len = guehdr_flags_len(flags);
995024c33aSTom Herbert 	if (len > optlen)
1005024c33aSTom Herbert 		return 1;
1015024c33aSTom Herbert 
1025024c33aSTom Herbert 	if (flags & GUE_FLAG_PRIV) {
1035024c33aSTom Herbert 		/* Private flags are last four bytes accounted in
1045024c33aSTom Herbert 		 * guehdr_flags_len
1055024c33aSTom Herbert 		 */
10620080971SXin Long 		__be32 pflags = *(__be32 *)((void *)&guehdr[1] +
10720080971SXin Long 					    len - GUE_LEN_PRIV);
1085024c33aSTom Herbert 
10920080971SXin Long 		if (pflags & ~GUE_PFLAGS_ALL)
1105024c33aSTom Herbert 			return 1;
1115024c33aSTom Herbert 
11220080971SXin Long 		len += guehdr_priv_flags_len(pflags);
1135024c33aSTom Herbert 		if (len > optlen)
1145024c33aSTom Herbert 			return 1;
1155024c33aSTom Herbert 	}
1165024c33aSTom Herbert 
1175024c33aSTom Herbert 	return 0;
1185024c33aSTom Herbert }
1195024c33aSTom Herbert 
12037dd0247STom Herbert #endif
121