kernel/3.1[02]: add Winbond W25X05 SPI flash support
[openwrt.git] / target / linux / generic / patches-3.12 / 630-packet_socket_type.patch
1 This patch allows the user to specify desired packet types (outgoing,
2 broadcast, unicast, etc.) on packet sockets via setsockopt.
3 This can reduce the load in situations where only a limited number
4 of packet types are necessary
5
6 Signed-off-by: Felix Fietkau <nbd@openwrt.org>
7
8 --- a/include/uapi/linux/if_packet.h
9 +++ b/include/uapi/linux/if_packet.h
10 @@ -29,6 +29,8 @@ struct sockaddr_ll {
11  /* These ones are invisible by user level */
12  #define PACKET_LOOPBACK                5               /* MC/BRD frame looped back */
13  #define PACKET_FASTROUTE       6               /* Fastrouted frame     */
14 +#define PACKET_MASK_ANY                0xffffffff      /* mask for packet type bits */
15 +
16  
17  /* Packet socket options */
18  
19 @@ -51,6 +53,7 @@ struct sockaddr_ll {
20  #define PACKET_TIMESTAMP               17
21  #define PACKET_FANOUT                  18
22  #define PACKET_TX_HAS_OFF              19
23 +#define PACKET_RECV_TYPE               20
24  
25  #define PACKET_FANOUT_HASH             0
26  #define PACKET_FANOUT_LB               1
27 --- a/net/packet/af_packet.c
28 +++ b/net/packet/af_packet.c
29 @@ -1393,6 +1393,7 @@ static int packet_rcv_spkt(struct sk_buf
30  {
31         struct sock *sk;
32         struct sockaddr_pkt *spkt;
33 +       struct packet_sock *po;
34  
35         /*
36          *      When we registered the protocol we saved the socket in the data
37 @@ -1400,6 +1401,7 @@ static int packet_rcv_spkt(struct sk_buf
38          */
39  
40         sk = pt->af_packet_priv;
41 +       po = pkt_sk(sk);
42  
43         /*
44          *      Yank back the headers [hope the device set this
45 @@ -1412,7 +1414,7 @@ static int packet_rcv_spkt(struct sk_buf
46          *      so that this procedure is noop.
47          */
48  
49 -       if (skb->pkt_type == PACKET_LOOPBACK)
50 +       if (!(po->pkt_type & (1 << skb->pkt_type)))
51                 goto out;
52  
53         if (!net_eq(dev_net(dev), sock_net(sk)))
54 @@ -1619,12 +1621,12 @@ static int packet_rcv(struct sk_buff *sk
55         int skb_len = skb->len;
56         unsigned int snaplen, res;
57  
58 -       if (skb->pkt_type == PACKET_LOOPBACK)
59 -               goto drop;
60 -
61         sk = pt->af_packet_priv;
62         po = pkt_sk(sk);
63  
64 +       if (!(po->pkt_type & (1 << skb->pkt_type)))
65 +               goto drop;
66 +
67         if (!net_eq(dev_net(dev), sock_net(sk)))
68                 goto drop;
69  
70 @@ -1737,12 +1739,12 @@ static int tpacket_rcv(struct sk_buff *s
71         struct timespec ts;
72         __u32 ts_status;
73  
74 -       if (skb->pkt_type == PACKET_LOOPBACK)
75 -               goto drop;
76 -
77         sk = pt->af_packet_priv;
78         po = pkt_sk(sk);
79  
80 +       if (!(po->pkt_type & (1 << skb->pkt_type)))
81 +               goto drop;
82 +
83         if (!net_eq(dev_net(dev), sock_net(sk)))
84                 goto drop;
85  
86 @@ -2638,6 +2640,7 @@ static int packet_create(struct net *net
87         spin_lock_init(&po->bind_lock);
88         mutex_init(&po->pg_vec_lock);
89         po->prot_hook.func = packet_rcv;
90 +       po->pkt_type = PACKET_MASK_ANY & ~(1 << PACKET_LOOPBACK);
91  
92         if (sock->type == SOCK_PACKET)
93                 po->prot_hook.func = packet_rcv_spkt;
94 @@ -3204,6 +3207,16 @@ packet_setsockopt(struct socket *sock, i
95                 po->tp_tx_has_off = !!val;
96                 return 0;
97         }
98 +        case PACKET_RECV_TYPE:
99 +        {
100 +                unsigned int val;
101 +                if (optlen != sizeof(val))
102 +                        return -EINVAL;
103 +                if (copy_from_user(&val, optval, sizeof(val)))
104 +                        return -EFAULT;
105 +                po->pkt_type = val & ~PACKET_LOOPBACK;
106 +                return 0;
107 +        }
108         default:
109                 return -ENOPROTOOPT;
110         }
111 @@ -3255,6 +3268,13 @@ static int packet_getsockopt(struct sock
112         case PACKET_VNET_HDR:
113                 val = po->has_vnet_hdr;
114                 break;
115 +       case PACKET_RECV_TYPE:
116 +               if (len > sizeof(unsigned int))
117 +                       len = sizeof(unsigned int);
118 +               val = po->pkt_type;
119 +
120 +               data = &val;
121 +               break;
122         case PACKET_VERSION:
123                 val = po->tp_version;
124                 break;
125 --- a/net/packet/internal.h
126 +++ b/net/packet/internal.h
127 @@ -115,6 +115,7 @@ struct packet_sock {
128         unsigned int            tp_tstamp;
129         struct net_device __rcu *cached_dev;
130         struct packet_type      prot_hook ____cacheline_aligned_in_smp;
131 +       unsigned int            pkt_type;
132  };
133  
134  static struct packet_sock *pkt_sk(struct sock *sk)