Commit a32f3e9d authored by Anna Emese Nyiri's avatar Anna Emese Nyiri Committed by Jakub Kicinski
Browse files

sock: support SO_PRIORITY cmsg



The Linux socket API currently allows setting SO_PRIORITY at the
socket level, applying a uniform priority to all packets sent through
that socket. The exception to this is IP_TOS, when the priority value
is calculated during the handling of
ancillary data, as implemented in commit f02db315 ("ipv4: IP_TOS
and IP_TTL can be specified as ancillary data").
However, this is a computed
value, and there is currently no mechanism to set a custom priority
via control messages prior to this patch.

According to this patch, if SO_PRIORITY is specified as ancillary data,
the packet is sent with the priority value set through
sockc->priority, overriding the socket-level values
set via the traditional setsockopt() method. This is analogous to
the existing support for SO_MARK, as implemented in
commit c6af0c22 ("ip: support SO_MARK cmsg").

If both cmsg SO_PRIORITY and IP_TOS are passed, then the one that
takes precedence is the last one in the cmsg list.

This patch has the side effect that raw_send_hdrinc now interprets cmsg
IP_TOS.

Reviewed-by: default avatarWillem de Bruijn <willemb@google.com>
Suggested-by: default avatarFerenc Fejes <fejes@inf.elte.hu>
Signed-off-by: default avatarAnna Emese Nyiri <annaemesenyiri@gmail.com>
Link: https://patch.msgid.link/20241213084457.45120-3-annaemesenyiri@gmail.com


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent 77ec16be
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -172,7 +172,7 @@ struct inet_cork {
	u8			tx_flags;
	__u8			ttl;
	__s16			tos;
	char			priority;
	u32			priority;
	__u16			gso_size;
	u32			ts_opt_id;
	u64			transmit_time;
+1 −1
Original line number Diff line number Diff line
@@ -81,7 +81,6 @@ struct ipcm_cookie {
	__u8			protocol;
	__u8			ttl;
	__s16			tos;
	char			priority;
	__u16			gso_size;
};

@@ -96,6 +95,7 @@ static inline void ipcm_init_sk(struct ipcm_cookie *ipcm,
	ipcm_init(ipcm);

	ipcm->sockc.mark = READ_ONCE(inet->sk.sk_mark);
	ipcm->sockc.priority = READ_ONCE(inet->sk.sk_priority);
	ipcm->sockc.tsflags = READ_ONCE(inet->sk.sk_tsflags);
	ipcm->oif = READ_ONCE(inet->sk.sk_bound_dev_if);
	ipcm->addr = inet->inet_saddr;
+3 −1
Original line number Diff line number Diff line
@@ -1814,13 +1814,15 @@ struct sockcm_cookie {
	u32 mark;
	u32 tsflags;
	u32 ts_opt_id;
	u32 priority;
};

static inline void sockcm_init(struct sockcm_cookie *sockc,
			       const struct sock *sk)
{
	*sockc = (struct sockcm_cookie) {
		.tsflags = READ_ONCE(sk->sk_tsflags)
		.tsflags = READ_ONCE(sk->sk_tsflags),
		.priority = READ_ONCE(sk->sk_priority),
	};
}

+1 −1
Original line number Diff line number Diff line
@@ -962,7 +962,7 @@ static int raw_sendmsg(struct socket *sock, struct msghdr *msg, size_t size)
	}

	skb->dev = dev;
	skb->priority = READ_ONCE(sk->sk_priority);
	skb->priority = sockc.priority;
	skb->mark = READ_ONCE(sk->sk_mark);
	skb->tstamp = sockc.transmit_time;

+7 −0
Original line number Diff line number Diff line
@@ -2947,6 +2947,13 @@ int __sock_cmsg_send(struct sock *sk, struct cmsghdr *cmsg,
	case SCM_RIGHTS:
	case SCM_CREDENTIALS:
		break;
	case SO_PRIORITY:
		if (cmsg->cmsg_len != CMSG_LEN(sizeof(u32)))
			return -EINVAL;
		if (!sk_set_prio_allowed(sk, *(u32 *)CMSG_DATA(cmsg)))
			return -EPERM;
		sockc->priority = *(u32 *)CMSG_DATA(cmsg);
		break;
	default:
		return -EINVAL;
	}
Loading