[ovs-dev] [PATCH] lib/netdev-linux.c: Prevent receiving of sent packets

Simon Horman horms at verge.net.au
Thu Jun 13 07:41:37 UTC 2013


On Wed, Jun 12, 2013 at 07:30:44PM -0700, Murphy McCauley wrote:
> Commit 796223f5 (netdev: Add new "struct netdev_rx" for capturing packets
> from a netdev) refactored send and receive into separate netdevs.  As a
> result, send and receive now use different socket descriptors (except for tap
> interfaces which are treated specially).  An unintended side effect was that
> all sent packets are looped back and received, which had previously been
> avoided as the kernel specifically prevents this from happening on a single
> socket descriptor.
> 
> To resolve the situation, a socket filter is added to the receive socket
> so that it only accepts inbound packets.
> 
> Simon Horman co-discovered and initially reported this issue.
> 
> Signed-off-by: Murphy McCauley <murphy.mccauley at gmail.com>

Reviewed-by: Simon Horman <horms at verge.net.au>

> ---
> Discussed on ovs-dev under the subject "Possible Regression in 'netdev:
> Add new "struct netdev_rx" for capturing packets from a netdev.'"
> 
>  lib/netdev-linux.c | 18 ++++++++++++++++++
>  1 file changed, 18 insertions(+)
> 
> diff --git a/lib/netdev-linux.c b/lib/netdev-linux.c
> index d73115b..2753878 100644
> --- a/lib/netdev-linux.c
> +++ b/lib/netdev-linux.c
> @@ -744,6 +744,14 @@ netdev_linux_rx_open(struct netdev *netdev_, struct netdev_rx **rxp)
>      } else {
>          struct sockaddr_ll sll;
>          int ifindex;
> +        /* Result of tcpdump -dd inbound */
> +        static struct sock_filter filt[] = {
> +            { 0x28, 0, 0, 0xfffff004 },
> +            { 0x15, 0, 1, 0x00000004 },
> +            { 0x6, 0, 0, 0x00000000 },
> +            { 0x6, 0, 0, 0x0000ffff }
> +        };
> +        static struct sock_fprog fprog = {len: ARRAY_SIZE(filt), filter: filt};
>  
>          /* Create file descriptor. */
>          fd = socket(PF_PACKET, SOCK_RAW, 0);
> @@ -776,6 +784,16 @@ netdev_linux_rx_open(struct netdev *netdev_, struct netdev_rx **rxp)
>                       netdev_get_name(netdev_), strerror(error));
>              goto error;
>          }
> +
> +        /* Filter for only inbound packets. */
> +        error = setsockopt(fd, SOL_SOCKET, SO_ATTACH_FILTER, &fprog,
> +                           sizeof fprog);
> +        if (error) {
> +            error = errno;
> +            VLOG_ERR("%s: failed attach filter (%s)",
> +                     netdev_get_name(netdev_), strerror(error));
> +            goto error;
> +        }
>      }
>  
>      rx = xmalloc(sizeof *rx);
> @@ -910,7 +928,8 @@ netdev_linux_send(struct netdev *netdev_, const void *data, size_t size)
>              /* Use the tap fd to send to this device.  This is essential for
>               * tap devices, because packets sent to a tap device with an
>               * AF_PACKET socket will loop back to be *received* again on the
> -             * tap device. */
> +             * tap device.  This doesn't occur on other interface types
> +             * because we attach a socket filter to the rx socket. */
>              struct netdev_linux *netdev = netdev_linux_cast(netdev_);
>  
>              retval = write(netdev->state.tap.fd, data, size);
> -- 
> 1.8.1.2
> 
> _______________________________________________
> dev mailing list
> dev at openvswitch.org
> http://openvswitch.org/mailman/listinfo/dev
> 



More information about the dev mailing list