net/packet: convert po->has_vnet_hdr to an atomic flag
authorEric Dumazet <edumazet@google.com>
Thu, 16 Mar 2023 01:10:12 +0000 (01:10 +0000)
committerDavid S. Miller <davem@davemloft.net>
Fri, 17 Mar 2023 08:52:05 +0000 (08:52 +0000)
po->has_vnet_hdr can be read locklessly.

Signed-off-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
net/packet/af_packet.c
net/packet/diag.c
net/packet/internal.h

index 119063c..5a6b05e 100644 (file)
@@ -2309,7 +2309,7 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev,
                netoff = TPACKET_ALIGN(po->tp_hdrlen +
                                       (maclen < 16 ? 16 : maclen)) +
                                       po->tp_reserve;
-               if (po->has_vnet_hdr) {
+               if (packet_sock_flag(po, PACKET_SOCK_HAS_VNET_HDR)) {
                        netoff += sizeof(struct virtio_net_hdr);
                        do_vnet = true;
                }
@@ -2780,7 +2780,8 @@ static int tpacket_snd(struct packet_sock *po, struct msghdr *msg)
        size_max = po->tx_ring.frame_size
                - (po->tp_hdrlen - sizeof(struct sockaddr_ll));
 
-       if ((size_max > dev->mtu + reserve + VLAN_HLEN) && !po->has_vnet_hdr)
+       if ((size_max > dev->mtu + reserve + VLAN_HLEN) &&
+           !packet_sock_flag(po, PACKET_SOCK_HAS_VNET_HDR))
                size_max = dev->mtu + reserve + VLAN_HLEN;
 
        reinit_completion(&po->skb_completion);
@@ -2809,7 +2810,7 @@ static int tpacket_snd(struct packet_sock *po, struct msghdr *msg)
                status = TP_STATUS_SEND_REQUEST;
                hlen = LL_RESERVED_SPACE(dev);
                tlen = dev->needed_tailroom;
-               if (po->has_vnet_hdr) {
+               if (packet_sock_flag(po, PACKET_SOCK_HAS_VNET_HDR)) {
                        vnet_hdr = data;
                        data += sizeof(*vnet_hdr);
                        tp_len -= sizeof(*vnet_hdr);
@@ -2837,7 +2838,7 @@ static int tpacket_snd(struct packet_sock *po, struct msghdr *msg)
                                          addr, hlen, copylen, &sockc);
                if (likely(tp_len >= 0) &&
                    tp_len > dev->mtu + reserve &&
-                   !po->has_vnet_hdr &&
+                   !packet_sock_flag(po, PACKET_SOCK_HAS_VNET_HDR) &&
                    !packet_extra_vlan_len_allowed(dev, skb))
                        tp_len = -EMSGSIZE;
 
@@ -2856,7 +2857,7 @@ tpacket_error:
                        }
                }
 
-               if (po->has_vnet_hdr) {
+               if (packet_sock_flag(po, PACKET_SOCK_HAS_VNET_HDR)) {
                        if (virtio_net_hdr_to_skb(skb, vnet_hdr, vio_le())) {
                                tp_len = -EINVAL;
                                goto tpacket_error;
@@ -2991,7 +2992,7 @@ static int packet_snd(struct socket *sock, struct msghdr *msg, size_t len)
 
        if (sock->type == SOCK_RAW)
                reserve = dev->hard_header_len;
-       if (po->has_vnet_hdr) {
+       if (packet_sock_flag(po, PACKET_SOCK_HAS_VNET_HDR)) {
                err = packet_snd_vnet_parse(msg, &len, &vnet_hdr);
                if (err)
                        goto out_unlock;
@@ -3451,7 +3452,7 @@ static int packet_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
 
        packet_rcv_try_clear_pressure(pkt_sk(sk));
 
-       if (pkt_sk(sk)->has_vnet_hdr) {
+       if (packet_sock_flag(pkt_sk(sk), PACKET_SOCK_HAS_VNET_HDR)) {
                err = packet_rcv_vnet(msg, skb, &len);
                if (err)
                        goto out_free;
@@ -3931,7 +3932,7 @@ packet_setsockopt(struct socket *sock, int level, int optname, sockptr_t optval,
                if (po->rx_ring.pg_vec || po->tx_ring.pg_vec) {
                        ret = -EBUSY;
                } else {
-                       po->has_vnet_hdr = !!val;
+                       packet_sock_flag_set(po, PACKET_SOCK_HAS_VNET_HDR, val);
                        ret = 0;
                }
                release_sock(sk);
@@ -4065,7 +4066,7 @@ static int packet_getsockopt(struct socket *sock, int level, int optname,
                val = packet_sock_flag(po, PACKET_SOCK_ORIGDEV);
                break;
        case PACKET_VNET_HDR:
-               val = po->has_vnet_hdr;
+               val = packet_sock_flag(po, PACKET_SOCK_HAS_VNET_HDR);
                break;
        case PACKET_VERSION:
                val = po->tp_version;
index 8bb4ce6..56240aa 100644 (file)
@@ -27,7 +27,7 @@ static int pdiag_put_info(const struct packet_sock *po, struct sk_buff *nlskb)
                pinfo.pdi_flags |= PDI_AUXDATA;
        if (packet_sock_flag(po, PACKET_SOCK_ORIGDEV))
                pinfo.pdi_flags |= PDI_ORIGDEV;
-       if (po->has_vnet_hdr)
+       if (packet_sock_flag(po, PACKET_SOCK_HAS_VNET_HDR))
                pinfo.pdi_flags |= PDI_VNETHDR;
        if (packet_sock_flag(po, PACKET_SOCK_TP_LOSS))
                pinfo.pdi_flags |= PDI_LOSS;
index 9d406a9..2521176 100644 (file)
@@ -118,7 +118,6 @@ struct packet_sock {
        struct mutex            pg_vec_lock;
        unsigned long           flags;
        unsigned int            running;        /* bind_lock must be held */
-       unsigned int            has_vnet_hdr:1; /* writer must hold sock lock */
        int                     pressure;
        int                     ifindex;        /* bound device         */
        __be16                  num;
@@ -146,6 +145,7 @@ enum packet_sock_flags {
        PACKET_SOCK_AUXDATA,
        PACKET_SOCK_TX_HAS_OFF,
        PACKET_SOCK_TP_LOSS,
+       PACKET_SOCK_HAS_VNET_HDR,
 };
 
 static inline void packet_sock_flag_set(struct packet_sock *po,