af-packet: Use existing netdev reference for bound sockets.
authorBen Greear <greearb@candelatech.com>
Wed, 1 Jun 2011 07:18:53 +0000 (07:18 +0000)
committerDavid S. Miller <davem@davemloft.net>
Sun, 5 Jun 2011 21:16:28 +0000 (14:16 -0700)
This saves a network device lookup on each packet transmitted,
for sockets that are bound to a network device.

Signed-off-by: Ben Greear <greearb@candelatech.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
net/packet/af_packet.c

index 636b75c15a633a008a0ad597c880d795800f57a9..67f6749a0a456b11edb93f39a4d3b439e06e9896 100644 (file)
@@ -974,7 +974,8 @@ static int tpacket_snd(struct packet_sock *po, struct msghdr *msg)
        struct sk_buff *skb;
        struct net_device *dev;
        __be16 proto;
-       int ifindex, err, reserve = 0;
+       bool need_rls_dev = false;
+       int err, reserve = 0;
        void *ph;
        struct sockaddr_ll *saddr = (struct sockaddr_ll *)msg->msg_name;
        int tp_len, size_max;
@@ -986,7 +987,7 @@ static int tpacket_snd(struct packet_sock *po, struct msghdr *msg)
 
        err = -EBUSY;
        if (saddr == NULL) {
-               ifindex = po->ifindex;
+               dev = po->prot_hook.dev;
                proto   = po->num;
                addr    = NULL;
        } else {
@@ -997,12 +998,12 @@ static int tpacket_snd(struct packet_sock *po, struct msghdr *msg)
                                        + offsetof(struct sockaddr_ll,
                                                sll_addr)))
                        goto out;
-               ifindex = saddr->sll_ifindex;
                proto   = saddr->sll_protocol;
                addr    = saddr->sll_addr;
+               dev = dev_get_by_index(sock_net(&po->sk), saddr->sll_ifindex);
+               need_rls_dev = true;
        }
 
-       dev = dev_get_by_index(sock_net(&po->sk), ifindex);
        err = -ENXIO;
        if (unlikely(dev == NULL))
                goto out;
@@ -1088,7 +1089,8 @@ out_status:
        __packet_set_status(po, ph, status);
        kfree_skb(skb);
 out_put:
-       dev_put(dev);
+       if (need_rls_dev)
+               dev_put(dev);
 out:
        mutex_unlock(&po->pg_vec_lock);
        return err;
@@ -1126,8 +1128,9 @@ static int packet_snd(struct socket *sock,
        struct sk_buff *skb;
        struct net_device *dev;
        __be16 proto;
+       bool need_rls_dev = false;
        unsigned char *addr;
-       int ifindex, err, reserve = 0;
+       int err, reserve = 0;
        struct virtio_net_hdr vnet_hdr = { 0 };
        int offset = 0;
        int vnet_hdr_len;
@@ -1139,7 +1142,7 @@ static int packet_snd(struct socket *sock,
         */
 
        if (saddr == NULL) {
-               ifindex = po->ifindex;
+               dev = po->prot_hook.dev;
                proto   = po->num;
                addr    = NULL;
        } else {
@@ -1148,13 +1151,12 @@ static int packet_snd(struct socket *sock,
                        goto out;
                if (msg->msg_namelen < (saddr->sll_halen + offsetof(struct sockaddr_ll, sll_addr)))
                        goto out;
-               ifindex = saddr->sll_ifindex;
                proto   = saddr->sll_protocol;
                addr    = saddr->sll_addr;
+               dev = dev_get_by_index(sock_net(sk), saddr->sll_ifindex);
+               need_rls_dev = true;
        }
 
-
-       dev = dev_get_by_index(sock_net(sk), ifindex);
        err = -ENXIO;
        if (dev == NULL)
                goto out_unlock;
@@ -1285,14 +1287,15 @@ static int packet_snd(struct socket *sock,
        if (err > 0 && (err = net_xmit_errno(err)) != 0)
                goto out_unlock;
 
-       dev_put(dev);
+       if (need_rls_dev)
+               dev_put(dev);
 
        return len;
 
 out_free:
        kfree_skb(skb);
 out_unlock:
-       if (dev)
+       if (dev && need_rls_dev)
                dev_put(dev);
 out:
        return err;