aboutsummaryrefslogtreecommitdiffstats
path: root/net/packet
diff options
context:
space:
mode:
authorPavel Emelyanov <xemul@parallels.com>2012-08-16 01:36:48 -0400
committerDavid S. Miller <davem@davemloft.net>2012-08-20 05:23:14 -0400
commitfff3321d75b1a18231876a1aceb36eacbbf6221e (patch)
treeff7d423fae980191ed922038ce5e1d0a05e19fab /net/packet
parent16f01365fa01150bf3606fe702a80a03ec87953a (diff)
packet: Report fanout status via diag engine
Reported value is the same reported by the FANOUT getsockoption, but unlike it, the absent fanout setup results in absent nlattr, rather than in nlattr with zero value. This is done so, since zero fanout report may mean both -- no fanout, and fanout with both id and type zero. Signed-off-by: Pavel Emelyanov <xemul@parallels.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/packet')
-rw-r--r--net/packet/af_packet.c23
-rw-r--r--net/packet/diag.c20
-rw-r--r--net/packet/internal.h20
3 files changed, 42 insertions, 21 deletions
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
index 8a1605ae4029..226b2cdfc339 100644
--- a/net/packet/af_packet.c
+++ b/net/packet/af_packet.c
@@ -207,24 +207,6 @@ static void prb_fill_vlan_info(struct tpacket_kbdq_core *,
207 struct tpacket3_hdr *); 207 struct tpacket3_hdr *);
208static void packet_flush_mclist(struct sock *sk); 208static void packet_flush_mclist(struct sock *sk);
209 209
210#define PACKET_FANOUT_MAX 256
211
212struct packet_fanout {
213#ifdef CONFIG_NET_NS
214 struct net *net;
215#endif
216 unsigned int num_members;
217 u16 id;
218 u8 type;
219 u8 defrag;
220 atomic_t rr_cur;
221 struct list_head list;
222 struct sock *arr[PACKET_FANOUT_MAX];
223 spinlock_t lock;
224 atomic_t sk_ref;
225 struct packet_type prot_hook ____cacheline_aligned_in_smp;
226};
227
228struct packet_skb_cb { 210struct packet_skb_cb {
229 unsigned int origlen; 211 unsigned int origlen;
230 union { 212 union {
@@ -1148,7 +1130,8 @@ static int packet_rcv_fanout(struct sk_buff *skb, struct net_device *dev,
1148 return po->prot_hook.func(skb, dev, &po->prot_hook, orig_dev); 1130 return po->prot_hook.func(skb, dev, &po->prot_hook, orig_dev);
1149} 1131}
1150 1132
1151static DEFINE_MUTEX(fanout_mutex); 1133DEFINE_MUTEX(fanout_mutex);
1134EXPORT_SYMBOL_GPL(fanout_mutex);
1152static LIST_HEAD(fanout_list); 1135static LIST_HEAD(fanout_list);
1153 1136
1154static void __fanout_link(struct sock *sk, struct packet_sock *po) 1137static void __fanout_link(struct sock *sk, struct packet_sock *po)
@@ -1260,9 +1243,9 @@ static void fanout_release(struct sock *sk)
1260 if (!f) 1243 if (!f)
1261 return; 1244 return;
1262 1245
1246 mutex_lock(&fanout_mutex);
1263 po->fanout = NULL; 1247 po->fanout = NULL;
1264 1248
1265 mutex_lock(&fanout_mutex);
1266 if (atomic_dec_and_test(&f->sk_ref)) { 1249 if (atomic_dec_and_test(&f->sk_ref)) {
1267 list_del(&f->list); 1250 list_del(&f->list);
1268 dev_remove_pack(&f->prot_hook); 1251 dev_remove_pack(&f->prot_hook);
diff --git a/net/packet/diag.c b/net/packet/diag.c
index e3975e4d458c..bc33fbe8a5ef 100644
--- a/net/packet/diag.c
+++ b/net/packet/diag.c
@@ -109,6 +109,22 @@ static int pdiag_put_rings_cfg(struct packet_sock *po, struct sk_buff *skb)
109 return ret; 109 return ret;
110} 110}
111 111
112static int pdiag_put_fanout(struct packet_sock *po, struct sk_buff *nlskb)
113{
114 int ret = 0;
115
116 mutex_lock(&fanout_mutex);
117 if (po->fanout) {
118 u32 val;
119
120 val = (u32)po->fanout->id | ((u32)po->fanout->type << 16);
121 ret = nla_put_u32(nlskb, PACKET_DIAG_FANOUT, val);
122 }
123 mutex_unlock(&fanout_mutex);
124
125 return ret;
126}
127
112static int sk_diag_fill(struct sock *sk, struct sk_buff *skb, struct packet_diag_req *req, 128static int sk_diag_fill(struct sock *sk, struct sk_buff *skb, struct packet_diag_req *req,
113 u32 pid, u32 seq, u32 flags, int sk_ino) 129 u32 pid, u32 seq, u32 flags, int sk_ino)
114{ 130{
@@ -139,6 +155,10 @@ static int sk_diag_fill(struct sock *sk, struct sk_buff *skb, struct packet_diag
139 pdiag_put_rings_cfg(po, skb)) 155 pdiag_put_rings_cfg(po, skb))
140 goto out_nlmsg_trim; 156 goto out_nlmsg_trim;
141 157
158 if ((req->pdiag_show & PACKET_SHOW_FANOUT) &&
159 pdiag_put_fanout(po, skb))
160 goto out_nlmsg_trim;
161
142 return nlmsg_end(skb, nlh); 162 return nlmsg_end(skb, nlh);
143 163
144out_nlmsg_trim: 164out_nlmsg_trim:
diff --git a/net/packet/internal.h b/net/packet/internal.h
index 2c5fca28b242..44945f6b7252 100644
--- a/net/packet/internal.h
+++ b/net/packet/internal.h
@@ -67,7 +67,25 @@ struct packet_ring_buffer {
67 atomic_t pending; 67 atomic_t pending;
68}; 68};
69 69
70struct packet_fanout; 70extern struct mutex fanout_mutex;
71#define PACKET_FANOUT_MAX 256
72
73struct packet_fanout {
74#ifdef CONFIG_NET_NS
75 struct net *net;
76#endif
77 unsigned int num_members;
78 u16 id;
79 u8 type;
80 u8 defrag;
81 atomic_t rr_cur;
82 struct list_head list;
83 struct sock *arr[PACKET_FANOUT_MAX];
84 spinlock_t lock;
85 atomic_t sk_ref;
86 struct packet_type prot_hook ____cacheline_aligned_in_smp;
87};
88
71struct packet_sock { 89struct packet_sock {
72 /* struct sock has to be the first member of packet_sock */ 90 /* struct sock has to be the first member of packet_sock */
73 struct sock sk; 91 struct sock sk;