aboutsummaryrefslogtreecommitdiffstats
path: root/net/packet
diff options
context:
space:
mode:
authorVincent Whitchurch <vincent.whitchurch@axis.com>2018-09-03 10:23:36 -0400
committerDavid S. Miller <davem@davemloft.net>2018-09-06 01:09:37 -0400
commitfa788d986a3aac5069378ed04697bd06f83d3488 (patch)
treee335abac12b88e196f4c7c9e1012a66e93f53830 /net/packet
parent05dcc71298643256948a2e17db7dbecc748719d2 (diff)
packet: add sockopt to ignore outgoing packets
Currently, the only way to ignore outgoing packets on a packet socket is via the BPF filter. With MSG_ZEROCOPY, packets that are looped into AF_PACKET are copied in dev_queue_xmit_nit(), and this copy happens even if the filter run from packet_rcv() would reject them. So the presence of a packet socket on the interface takes away the benefits of MSG_ZEROCOPY, even if the packet socket is not interested in outgoing packets. (Even when MSG_ZEROCOPY is not used, the skb is unnecessarily cloned, but the cost for that is much lower.) Add a socket option to allow AF_PACKET sockets to ignore outgoing packets to solve this. Note that the *BSDs already have something similar: BIOCSSEESENT/BIOCSDIRECTION and BIOCSDIRFILT. The first intended user is lldpd. Signed-off-by: Vincent Whitchurch <vincent.whitchurch@axis.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/packet')
-rw-r--r--net/packet/af_packet.c17
1 files changed, 17 insertions, 0 deletions
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
index 75c92a87e7b2..f85f67b5c1f4 100644
--- a/net/packet/af_packet.c
+++ b/net/packet/af_packet.c
@@ -3805,6 +3805,20 @@ packet_setsockopt(struct socket *sock, int level, int optname, char __user *optv
3805 3805
3806 return fanout_set_data(po, optval, optlen); 3806 return fanout_set_data(po, optval, optlen);
3807 } 3807 }
3808 case PACKET_IGNORE_OUTGOING:
3809 {
3810 int val;
3811
3812 if (optlen != sizeof(val))
3813 return -EINVAL;
3814 if (copy_from_user(&val, optval, sizeof(val)))
3815 return -EFAULT;
3816 if (val < 0 || val > 1)
3817 return -EINVAL;
3818
3819 po->prot_hook.ignore_outgoing = !!val;
3820 return 0;
3821 }
3808 case PACKET_TX_HAS_OFF: 3822 case PACKET_TX_HAS_OFF:
3809 { 3823 {
3810 unsigned int val; 3824 unsigned int val;
@@ -3928,6 +3942,9 @@ static int packet_getsockopt(struct socket *sock, int level, int optname,
3928 ((u32)po->fanout->flags << 24)) : 3942 ((u32)po->fanout->flags << 24)) :
3929 0); 3943 0);
3930 break; 3944 break;
3945 case PACKET_IGNORE_OUTGOING:
3946 val = po->prot_hook.ignore_outgoing;
3947 break;
3931 case PACKET_ROLLOVER_STATS: 3948 case PACKET_ROLLOVER_STATS:
3932 if (!po->rollover) 3949 if (!po->rollover)
3933 return -EINVAL; 3950 return -EINVAL;