Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ip: support SO_MARK cmsg

Enable setting skb->mark for UDP and RAW sockets using cmsg.

This is analogous to existing support for TOS, TTL, txtime, etc.

Packet sockets already support this as of commit c7d39e32632e
("packet: support per-packet fwmark for af_packet sendmsg").

Similar to other fields, implement by
1. initialize the sockcm_cookie.mark from socket option sk_mark
2. optionally overwrite this in ip_cmsg_send/ip6_datagram_send_ctl
3. initialize inet_cork.mark from sockcm_cookie.mark
4. initialize each (usually just one) skb->mark from inet_cork.mark

Step 1 is handled in one location for most protocols by ipcm_init_sk
as of commit 351782067b6b ("ipv4: ipcm_cookie initializers").

Signed-off-by: Willem de Bruijn <willemb@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Willem de Bruijn and committed by
David S. Miller
c6af0c22 823eb2a3

+15 -8
+1
include/net/inet_sock.h
··· 160 160 char priority; 161 161 __u16 gso_size; 162 162 u64 transmit_time; 163 + u32 mark; 163 164 }; 164 165 165 166 struct inet_cork_full {
+1
include/net/ip.h
··· 88 88 { 89 89 ipcm_init(ipcm); 90 90 91 + ipcm->sockc.mark = inet->sk.sk_mark; 91 92 ipcm->sockc.tsflags = inet->sk.sk_tsflags; 92 93 ipcm->oif = inet->sk.sk_bound_dev_if; 93 94 ipcm->addr = inet->inet_saddr;
+2 -1
net/ipv4/ip_output.c
··· 1266 1266 cork->length = 0; 1267 1267 cork->ttl = ipc->ttl; 1268 1268 cork->tos = ipc->tos; 1269 + cork->mark = ipc->sockc.mark; 1269 1270 cork->priority = ipc->priority; 1270 1271 cork->transmit_time = ipc->sockc.transmit_time; 1271 1272 cork->tx_flags = 0; ··· 1530 1529 } 1531 1530 1532 1531 skb->priority = (cork->tos != -1) ? cork->priority: sk->sk_priority; 1533 - skb->mark = sk->sk_mark; 1532 + skb->mark = cork->mark; 1534 1533 skb->tstamp = cork->transmit_time; 1535 1534 /* 1536 1535 * Steal rt from cork.dst to avoid a pair of atomic_inc/atomic_dec
+1 -1
net/ipv4/ping.c
··· 781 781 } else if (!ipc.oif) 782 782 ipc.oif = inet->uc_index; 783 783 784 - flowi4_init_output(&fl4, ipc.oif, sk->sk_mark, tos, 784 + flowi4_init_output(&fl4, ipc.oif, ipc.sockc.mark, tos, 785 785 RT_SCOPE_UNIVERSE, sk->sk_protocol, 786 786 inet_sk_flowi_flags(sk), faddr, saddr, 0, 0, 787 787 sk->sk_uid);
+2 -2
net/ipv4/raw.c
··· 375 375 skb_reserve(skb, hlen); 376 376 377 377 skb->priority = sk->sk_priority; 378 - skb->mark = sk->sk_mark; 378 + skb->mark = sockc->mark; 379 379 skb->tstamp = sockc->transmit_time; 380 380 skb_dst_set(skb, &rt->dst); 381 381 *rtp = NULL; ··· 623 623 } 624 624 } 625 625 626 - flowi4_init_output(&fl4, ipc.oif, sk->sk_mark, tos, 626 + flowi4_init_output(&fl4, ipc.oif, ipc.sockc.mark, tos, 627 627 RT_SCOPE_UNIVERSE, 628 628 hdrincl ? IPPROTO_RAW : sk->sk_protocol, 629 629 inet_sk_flowi_flags(sk) |
+1 -1
net/ipv4/udp.c
··· 1130 1130 1131 1131 fl4 = &fl4_stack; 1132 1132 1133 - flowi4_init_output(fl4, ipc.oif, sk->sk_mark, tos, 1133 + flowi4_init_output(fl4, ipc.oif, ipc.sockc.mark, tos, 1134 1134 RT_SCOPE_UNIVERSE, sk->sk_protocol, 1135 1135 flow_flags, 1136 1136 faddr, saddr, dport, inet->inet_sport,
+2 -1
net/ipv6/ip6_output.c
··· 1294 1294 cork->base.fragsize = mtu; 1295 1295 cork->base.gso_size = ipc6->gso_size; 1296 1296 cork->base.tx_flags = 0; 1297 + cork->base.mark = ipc6->sockc.mark; 1297 1298 sock_tx_timestamp(sk, ipc6->sockc.tsflags, &cork->base.tx_flags); 1298 1299 1299 1300 if (dst_allfrag(xfrm_dst_path(&rt->dst))) ··· 1765 1764 hdr->daddr = *final_dst; 1766 1765 1767 1766 skb->priority = sk->sk_priority; 1768 - skb->mark = sk->sk_mark; 1767 + skb->mark = cork->base.mark; 1769 1768 1770 1769 skb->tstamp = cork->base.transmit_time; 1771 1770
+3 -1
net/ipv6/raw.c
··· 646 646 647 647 skb->protocol = htons(ETH_P_IPV6); 648 648 skb->priority = sk->sk_priority; 649 - skb->mark = sk->sk_mark; 649 + skb->mark = sockc->mark; 650 650 skb->tstamp = sockc->transmit_time; 651 651 652 652 skb_put(skb, length); ··· 810 810 811 811 ipcm6_init(&ipc6); 812 812 ipc6.sockc.tsflags = sk->sk_tsflags; 813 + ipc6.sockc.mark = sk->sk_mark; 813 814 814 815 if (sin6) { 815 816 if (addr_len < SIN6_LEN_RFC2133) ··· 892 891 opt = ipv6_fixup_options(&opt_space, opt); 893 892 894 893 fl6.flowi6_proto = proto; 894 + fl6.flowi6_mark = ipc6.sockc.mark; 895 895 896 896 if (!hdrincl) { 897 897 rfv.msg = msg;
+2 -1
net/ipv6/udp.c
··· 1230 1230 ipcm6_init(&ipc6); 1231 1231 ipc6.gso_size = up->gso_size; 1232 1232 ipc6.sockc.tsflags = sk->sk_tsflags; 1233 + ipc6.sockc.mark = sk->sk_mark; 1233 1234 1234 1235 /* destination address check */ 1235 1236 if (sin6) { ··· 1353 1352 if (!fl6.flowi6_oif) 1354 1353 fl6.flowi6_oif = np->sticky_pktinfo.ipi6_ifindex; 1355 1354 1356 - fl6.flowi6_mark = sk->sk_mark; 1355 + fl6.flowi6_mark = ipc6.sockc.mark; 1357 1356 fl6.flowi6_uid = sk->sk_uid; 1358 1357 1359 1358 if (msg->msg_controllen) {