]> Pileus Git - ~andy/linux/blobdiff - net/packet/af_packet.c
Merge remote-tracking branch 'regulator/fix/da9063' into regulator-linus
[~andy/linux] / net / packet / af_packet.c
index 4b66c752eae5d99b2bfe5fa7832a1301d20519ef..2e8286b47c28e5bef7cb80162e12ddb8ca4b358e 100644 (file)
@@ -88,7 +88,7 @@
 #include <linux/virtio_net.h>
 #include <linux/errqueue.h>
 #include <linux/net_tstamp.h>
-
+#include <linux/reciprocal_div.h>
 #ifdef CONFIG_INET
 #include <net/inet_common.h>
 #endif
@@ -1135,7 +1135,7 @@ static unsigned int fanout_demux_hash(struct packet_fanout *f,
                                      struct sk_buff *skb,
                                      unsigned int num)
 {
-       return (((u64)skb->rxhash) * num) >> 32;
+       return reciprocal_divide(skb->rxhash, num);
 }
 
 static unsigned int fanout_demux_lb(struct packet_fanout *f,
@@ -1158,6 +1158,13 @@ static unsigned int fanout_demux_cpu(struct packet_fanout *f,
        return smp_processor_id() % num;
 }
 
+static unsigned int fanout_demux_rnd(struct packet_fanout *f,
+                                    struct sk_buff *skb,
+                                    unsigned int num)
+{
+       return reciprocal_divide(prandom_u32(), num);
+}
+
 static unsigned int fanout_demux_rollover(struct packet_fanout *f,
                                          struct sk_buff *skb,
                                          unsigned int idx, unsigned int skip,
@@ -1215,6 +1222,9 @@ static int packet_rcv_fanout(struct sk_buff *skb, struct net_device *dev,
        case PACKET_FANOUT_CPU:
                idx = fanout_demux_cpu(f, skb, num);
                break;
+       case PACKET_FANOUT_RND:
+               idx = fanout_demux_rnd(f, skb, num);
+               break;
        case PACKET_FANOUT_ROLLOVER:
                idx = fanout_demux_rollover(f, skb, 0, (unsigned int) -1, num);
                break;
@@ -1284,6 +1294,7 @@ static int fanout_add(struct sock *sk, u16 id, u16 type_flags)
        case PACKET_FANOUT_HASH:
        case PACKET_FANOUT_LB:
        case PACKET_FANOUT_CPU:
+       case PACKET_FANOUT_RND:
                break;
        default:
                return -EINVAL;
@@ -2181,7 +2192,7 @@ static struct sk_buff *packet_alloc_skb(struct sock *sk, size_t prepad,
                linear = len;
 
        skb = sock_alloc_send_pskb(sk, prepad + linear, len - linear, noblock,
-                                  err);
+                                  err, 0);
        if (!skb)
                return NULL;
 
@@ -2638,51 +2649,6 @@ out:
        return err;
 }
 
-static int packet_recv_error(struct sock *sk, struct msghdr *msg, int len)
-{
-       struct sock_exterr_skb *serr;
-       struct sk_buff *skb, *skb2;
-       int copied, err;
-
-       err = -EAGAIN;
-       skb = skb_dequeue(&sk->sk_error_queue);
-       if (skb == NULL)
-               goto out;
-
-       copied = skb->len;
-       if (copied > len) {
-               msg->msg_flags |= MSG_TRUNC;
-               copied = len;
-       }
-       err = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);
-       if (err)
-               goto out_free_skb;
-
-       sock_recv_timestamp(msg, sk, skb);
-
-       serr = SKB_EXT_ERR(skb);
-       put_cmsg(msg, SOL_PACKET, PACKET_TX_TIMESTAMP,
-                sizeof(serr->ee), &serr->ee);
-
-       msg->msg_flags |= MSG_ERRQUEUE;
-       err = copied;
-
-       /* Reset and regenerate socket error */
-       spin_lock_bh(&sk->sk_error_queue.lock);
-       sk->sk_err = 0;
-       if ((skb2 = skb_peek(&sk->sk_error_queue)) != NULL) {
-               sk->sk_err = SKB_EXT_ERR(skb2)->ee.ee_errno;
-               spin_unlock_bh(&sk->sk_error_queue.lock);
-               sk->sk_error_report(sk);
-       } else
-               spin_unlock_bh(&sk->sk_error_queue.lock);
-
-out_free_skb:
-       kfree_skb(skb);
-out:
-       return err;
-}
-
 /*
  *     Pull a packet from our receive queue and hand it to the user.
  *     If necessary we block.
@@ -2708,7 +2674,8 @@ static int packet_recvmsg(struct kiocb *iocb, struct socket *sock,
 #endif
 
        if (flags & MSG_ERRQUEUE) {
-               err = packet_recv_error(sk, msg, len);
+               err = sock_recv_errqueue(sk, msg, len,
+                                        SOL_PACKET, PACKET_TX_TIMESTAMP);
                goto out;
        }
 
@@ -3259,9 +3226,11 @@ static int packet_getsockopt(struct socket *sock, int level, int optname,
 
                if (po->tp_version == TPACKET_V3) {
                        lv = sizeof(struct tpacket_stats_v3);
+                       st.stats3.tp_packets += st.stats3.tp_drops;
                        data = &st.stats3;
                } else {
                        lv = sizeof(struct tpacket_stats);
+                       st.stats1.tp_packets += st.stats1.tp_drops;
                        data = &st.stats1;
                }