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.mccau...@gmail.com>
Reviewed-by: Simon Horman <ho...@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@openvswitch.org > http://openvswitch.org/mailman/listinfo/dev > _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev