aboutsummaryrefslogtreecommitdiffstats
path: root/include/linux/netfilter
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2011-04-19 14:24:06 -0400
committerDavid S. Miller <davem@davemloft.net>2011-04-19 14:24:06 -0400
commit4805347c1eb12cfe79f42a12a5442ee01590a9c0 (patch)
treecb9d8b3cfc78d8411f0cea7b06c6472cdd35bb9a /include/linux/netfilter
parente1943424e43974f85b82bb31eaf832823bf49ce7 (diff)
parent91eb7c08c6cb3b8eeba1c61f5753c56dcb77f018 (diff)
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/kaber/nf-next-2.6
Diffstat (limited to 'include/linux/netfilter')
-rw-r--r--include/linux/netfilter/ipset/ip_set_getport.h2
-rw-r--r--include/linux/netfilter/x_tables.h96
2 files changed, 44 insertions, 54 deletions
diff --git a/include/linux/netfilter/ipset/ip_set_getport.h b/include/linux/netfilter/ipset/ip_set_getport.h
index 5aebd170f89..90d09300e95 100644
--- a/include/linux/netfilter/ipset/ip_set_getport.h
+++ b/include/linux/netfilter/ipset/ip_set_getport.h
@@ -22,7 +22,9 @@ static inline bool ip_set_proto_with_ports(u8 proto)
22{ 22{
23 switch (proto) { 23 switch (proto) {
24 case IPPROTO_TCP: 24 case IPPROTO_TCP:
25 case IPPROTO_SCTP:
25 case IPPROTO_UDP: 26 case IPPROTO_UDP:
27 case IPPROTO_UDPLITE:
26 return true; 28 return true;
27 } 29 }
28 return false; 30 return false;
diff --git a/include/linux/netfilter/x_tables.h b/include/linux/netfilter/x_tables.h
index 37219525ff6..32cddf78b13 100644
--- a/include/linux/netfilter/x_tables.h
+++ b/include/linux/netfilter/x_tables.h
@@ -456,72 +456,60 @@ extern void xt_proto_fini(struct net *net, u_int8_t af);
456extern struct xt_table_info *xt_alloc_table_info(unsigned int size); 456extern struct xt_table_info *xt_alloc_table_info(unsigned int size);
457extern void xt_free_table_info(struct xt_table_info *info); 457extern void xt_free_table_info(struct xt_table_info *info);
458 458
459/* 459/**
460 * Per-CPU spinlock associated with per-cpu table entries, and 460 * xt_recseq - recursive seqcount for netfilter use
461 * with a counter for the "reading" side that allows a recursive 461 *
462 * reader to avoid taking the lock and deadlocking. 462 * Packet processing changes the seqcount only if no recursion happened
463 * 463 * get_counters() can use read_seqcount_begin()/read_seqcount_retry(),
464 * "reading" is used by ip/arp/ip6 tables rule processing which runs per-cpu. 464 * because we use the normal seqcount convention :
465 * It needs to ensure that the rules are not being changed while the packet 465 * Low order bit set to 1 if a writer is active.
466 * is being processed. In some cases, the read lock will be acquired
467 * twice on the same CPU; this is okay because of the count.
468 *
469 * "writing" is used when reading counters.
470 * During replace any readers that are using the old tables have to complete
471 * before freeing the old table. This is handled by the write locking
472 * necessary for reading the counters.
473 */ 466 */
474struct xt_info_lock { 467DECLARE_PER_CPU(seqcount_t, xt_recseq);
475 seqlock_t lock;
476 unsigned char readers;
477};
478DECLARE_PER_CPU(struct xt_info_lock, xt_info_locks);
479 468
480/* 469/**
481 * Note: we need to ensure that preemption is disabled before acquiring 470 * xt_write_recseq_begin - start of a write section
482 * the per-cpu-variable, so we do it as a two step process rather than
483 * using "spin_lock_bh()".
484 *
485 * We _also_ need to disable bottom half processing before updating our
486 * nesting count, to make sure that the only kind of re-entrancy is this
487 * code being called by itself: since the count+lock is not an atomic
488 * operation, we can allow no races.
489 * 471 *
490 * _Only_ that special combination of being per-cpu and never getting 472 * Begin packet processing : all readers must wait the end
491 * re-entered asynchronously means that the count is safe. 473 * 1) Must be called with preemption disabled
474 * 2) softirqs must be disabled too (or we should use irqsafe_cpu_add())
475 * Returns :
476 * 1 if no recursion on this cpu
477 * 0 if recursion detected
492 */ 478 */
493static inline void xt_info_rdlock_bh(void) 479static inline unsigned int xt_write_recseq_begin(void)
494{ 480{
495 struct xt_info_lock *lock; 481 unsigned int addend;
496 482
497 local_bh_disable(); 483 /*
498 lock = &__get_cpu_var(xt_info_locks); 484 * Low order bit of sequence is set if we already
499 if (likely(!lock->readers++)) 485 * called xt_write_recseq_begin().
500 write_seqlock(&lock->lock); 486 */
501} 487 addend = (__this_cpu_read(xt_recseq.sequence) + 1) & 1;
502 488
503static inline void xt_info_rdunlock_bh(void) 489 /*
504{ 490 * This is kind of a write_seqcount_begin(), but addend is 0 or 1
505 struct xt_info_lock *lock = &__get_cpu_var(xt_info_locks); 491 * We dont check addend value to avoid a test and conditional jump,
492 * since addend is most likely 1
493 */
494 __this_cpu_add(xt_recseq.sequence, addend);
495 smp_wmb();
506 496
507 if (likely(!--lock->readers)) 497 return addend;
508 write_sequnlock(&lock->lock);
509 local_bh_enable();
510} 498}
511 499
512/* 500/**
513 * The "writer" side needs to get exclusive access to the lock, 501 * xt_write_recseq_end - end of a write section
514 * regardless of readers. This must be called with bottom half 502 * @addend: return value from previous xt_write_recseq_begin()
515 * processing (and thus also preemption) disabled. 503 *
504 * End packet processing : all readers can proceed
505 * 1) Must be called with preemption disabled
506 * 2) softirqs must be disabled too (or we should use irqsafe_cpu_add())
516 */ 507 */
517static inline void xt_info_wrlock(unsigned int cpu) 508static inline void xt_write_recseq_end(unsigned int addend)
518{
519 write_seqlock(&per_cpu(xt_info_locks, cpu).lock);
520}
521
522static inline void xt_info_wrunlock(unsigned int cpu)
523{ 509{
524 write_sequnlock(&per_cpu(xt_info_locks, cpu).lock); 510 /* this is kind of a write_seqcount_end(), but addend is 0 or 1 */
511 smp_wmb();
512 __this_cpu_add(xt_recseq.sequence, addend);
525} 513}
526 514
527/* 515/*