aboutsummaryrefslogtreecommitdiffstats
path: root/net/llc
diff options
context:
space:
mode:
authorOctavian Purdila <opurdila@ixiacom.com>2009-12-26 06:51:03 -0500
committerDavid S. Miller <davem@davemloft.net>2009-12-26 23:42:29 -0500
commit0f7b67dd9e1192976f5e5a78934c7a339ff7c45f (patch)
tree123fd1196cea045dcd2b0e2870381f4949cd62db /net/llc
parentb76f5a8427ac2928c07fa4ff2144bb8db072c240 (diff)
llc: optimize multicast delivery
Optimize multicast delivery by doing the actual delivery without holding the lock. Based on the same approach used in UDP code. Signed-off-by: Octavian Purdila <opurdila@ixiacom.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/llc')
-rw-r--r--net/llc/llc_sap.c36
1 files changed, 28 insertions, 8 deletions
diff --git a/net/llc/llc_sap.c b/net/llc/llc_sap.c
index 39760d013ce2..94790e60d072 100644
--- a/net/llc/llc_sap.c
+++ b/net/llc/llc_sap.c
@@ -355,6 +355,24 @@ static inline bool llc_mcast_match(const struct llc_sap *sap,
355 llc->dev == skb->dev; 355 llc->dev == skb->dev;
356} 356}
357 357
358static void llc_do_mcast(struct llc_sap *sap, struct sk_buff *skb,
359 struct sock **stack, int count)
360{
361 struct sk_buff *skb1;
362 int i;
363
364 for (i = 0; i < count; i++) {
365 skb1 = skb_clone(skb, GFP_ATOMIC);
366 if (!skb1) {
367 sock_put(stack[i]);
368 continue;
369 }
370
371 llc_sap_rcv(sap, skb1, stack[i]);
372 sock_put(stack[i]);
373 }
374}
375
358/** 376/**
359 * llc_sap_mcast - Deliver multicast PDU's to all matching datagram sockets. 377 * llc_sap_mcast - Deliver multicast PDU's to all matching datagram sockets.
360 * @sap: SAP 378 * @sap: SAP
@@ -367,25 +385,27 @@ static void llc_sap_mcast(struct llc_sap *sap,
367 const struct llc_addr *laddr, 385 const struct llc_addr *laddr,
368 struct sk_buff *skb) 386 struct sk_buff *skb)
369{ 387{
370 struct sock *sk; 388 int i = 0, count = 256 / sizeof(struct sock *);
389 struct sock *sk, *stack[count];
371 struct hlist_nulls_node *node; 390 struct hlist_nulls_node *node;
372 391
373 spin_lock_bh(&sap->sk_lock); 392 spin_lock_bh(&sap->sk_lock);
374 sk_nulls_for_each_rcu(sk, node, &sap->sk_list) { 393 sk_nulls_for_each_rcu(sk, node, &sap->sk_list) {
375 struct sk_buff *skb1;
376 394
377 if (!llc_mcast_match(sap, laddr, skb, sk)) 395 if (!llc_mcast_match(sap, laddr, skb, sk))
378 continue; 396 continue;
379 397
380 skb1 = skb_clone(skb, GFP_ATOMIC);
381 if (!skb1)
382 break;
383
384 sock_hold(sk); 398 sock_hold(sk);
385 llc_sap_rcv(sap, skb1, sk); 399 if (i < count)
386 sock_put(sk); 400 stack[i++] = sk;
401 else {
402 llc_do_mcast(sap, skb, stack, i);
403 i = 0;
404 }
387 } 405 }
388 spin_unlock_bh(&sap->sk_lock); 406 spin_unlock_bh(&sap->sk_lock);
407
408 llc_do_mcast(sap, skb, stack, i);
389} 409}
390 410
391 411