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

net/packet: remove po->xmit

Use PACKET_SOCK_QDISC_BYPASS atomic bit instead of a pointer.

This removes one indirect call in fast path,
and READ_ONCE()/WRITE_ONCE() annotations as well.

Signed-off-by: Eric Dumazet <edumazet@google.com>
Suggested-by: Willem de Bruijn <willemb@google.com>
Cc: Daniel Borkmann <daniel@iogearbox.net>
Reviewed-by: Willem de Bruijn <willemb@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Eric Dumazet and committed by
David S. Miller
105a201e 72abf217

+10 -16
+9 -15
net/packet/af_packet.c
··· 270 270 } 271 271 #endif 272 272 273 - static int packet_direct_xmit(struct sk_buff *skb) 273 + static int packet_xmit(const struct packet_sock *po, struct sk_buff *skb) 274 274 { 275 + if (!packet_sock_flag(po, PACKET_SOCK_QDISC_BYPASS)) 276 + return dev_queue_xmit(skb); 277 + 275 278 #ifdef CONFIG_NETFILTER_EGRESS 276 279 if (nf_hook_egress_active()) { 277 280 skb = nf_hook_direct_egress(skb); ··· 306 303 static void packet_cached_dev_reset(struct packet_sock *po) 307 304 { 308 305 RCU_INIT_POINTER(po->cached_dev, NULL); 309 - } 310 - 311 - static bool packet_use_direct_xmit(const struct packet_sock *po) 312 - { 313 - /* Paired with WRITE_ONCE() in packet_setsockopt() */ 314 - return READ_ONCE(po->xmit) == packet_direct_xmit; 315 306 } 316 307 317 308 static u16 packet_pick_tx_queue(struct sk_buff *skb) ··· 2869 2872 packet_inc_pending(&po->tx_ring); 2870 2873 2871 2874 status = TP_STATUS_SEND_REQUEST; 2872 - /* Paired with WRITE_ONCE() in packet_setsockopt() */ 2873 - err = READ_ONCE(po->xmit)(skb); 2875 + err = packet_xmit(po, skb); 2874 2876 if (unlikely(err != 0)) { 2875 2877 if (err > 0) 2876 2878 err = net_xmit_errno(err); ··· 3072 3076 virtio_net_hdr_set_proto(skb, &vnet_hdr); 3073 3077 } 3074 3078 3075 - /* Paired with WRITE_ONCE() in packet_setsockopt() */ 3076 - err = READ_ONCE(po->xmit)(skb); 3079 + err = packet_xmit(po, skb); 3080 + 3077 3081 if (unlikely(err != 0)) { 3078 3082 if (err > 0) 3079 3083 err = net_xmit_errno(err); ··· 3355 3359 init_completion(&po->skb_completion); 3356 3360 sk->sk_family = PF_PACKET; 3357 3361 po->num = proto; 3358 - po->xmit = dev_queue_xmit; 3359 3362 3360 3363 err = packet_alloc_pending(po); 3361 3364 if (err) ··· 4005 4010 if (copy_from_sockptr(&val, optval, sizeof(val))) 4006 4011 return -EFAULT; 4007 4012 4008 - /* Paired with all lockless reads of po->xmit */ 4009 - WRITE_ONCE(po->xmit, val ? packet_direct_xmit : dev_queue_xmit); 4013 + packet_sock_flag_set(po, PACKET_SOCK_QDISC_BYPASS, val); 4010 4014 return 0; 4011 4015 } 4012 4016 default: ··· 4120 4126 val = packet_sock_flag(po, PACKET_SOCK_TX_HAS_OFF); 4121 4127 break; 4122 4128 case PACKET_QDISC_BYPASS: 4123 - val = packet_use_direct_xmit(po); 4129 + val = packet_sock_flag(po, PACKET_SOCK_QDISC_BYPASS); 4124 4130 break; 4125 4131 default: 4126 4132 return -ENOPROTOOPT;
+1 -1
net/packet/internal.h
··· 128 128 unsigned int tp_tstamp; 129 129 struct completion skb_completion; 130 130 struct net_device __rcu *cached_dev; 131 - int (*xmit)(struct sk_buff *skb); 132 131 struct packet_type prot_hook ____cacheline_aligned_in_smp; 133 132 atomic_t tp_drops ____cacheline_aligned_in_smp; 134 133 }; ··· 142 143 PACKET_SOCK_HAS_VNET_HDR, 143 144 PACKET_SOCK_RUNNING, 144 145 PACKET_SOCK_PRESSURE, 146 + PACKET_SOCK_QDISC_BYPASS, 145 147 }; 146 148 147 149 static inline void packet_sock_flag_set(struct packet_sock *po,