summaryrefslogtreecommitdiffstats
path: root/sys/net/flowtable.c
diff options
context:
space:
mode:
authorkmacy <kmacy@FreeBSD.org>2009-04-20 16:16:43 +0000
committerkmacy <kmacy@FreeBSD.org>2009-04-20 16:16:43 +0000
commit6033ad3037c1f12a56a736f100f719cb4c42e7f6 (patch)
treeb6e0643607579ab98a1aafc8f81be361a0a4c74a /sys/net/flowtable.c
parenteb422ada74096ff9364e6e87dfe2b2a7390a437e (diff)
downloadFreeBSD-src-6033ad3037c1f12a56a736f100f719cb4c42e7f6.zip
FreeBSD-src-6033ad3037c1f12a56a736f100f719cb4c42e7f6.tar.gz
simplify code by removing bit_fns and replacing with the use of a temporary mask
Diffstat (limited to 'sys/net/flowtable.c')
-rw-r--r--sys/net/flowtable.c76
1 files changed, 20 insertions, 56 deletions
diff --git a/sys/net/flowtable.c b/sys/net/flowtable.c
index 53514c9..6a7ba48 100644
--- a/sys/net/flowtable.c
+++ b/sys/net/flowtable.c
@@ -300,9 +300,11 @@ struct flowtable {
fl_rtalloc_t *ft_rtalloc;
struct mtx *ft_locks;
- struct flowtable *ft_next;
+
union flentryp ft_table;
bitstr_t *ft_masks[MAXCPU];
+ bitstr_t *ft_tmpmask;
+ struct flowtable *ft_next;
};
static struct proc *flowcleanerproc;
@@ -317,6 +319,7 @@ static uma_zone_t ipv6_zone;
* to avoid extra cache evictions caused by incrementing a shared
* counter
* - add IPv6 support to flow lookup
+ * - add sysctls to resize && flush flow tables
* - Add per flowtable sysctls for statistics and configuring timeouts
* - add saturation counter to rtentry to support per-packet load-balancing
* add flag to indicate round-robin flow, add list lookup from head
@@ -872,6 +875,7 @@ flowtable_alloc(int nentry, int flags)
ft->ft_masks[0] = bit_alloc(nentry);
}
+ ft->ft_tmpmask = bit_alloc(nentry);
/*
* In the local transmit case the table truly is
@@ -888,6 +892,7 @@ flowtable_alloc(int nentry, int flags)
ft->ft_syn_idle = ft->ft_tcp_idle = 30;
}
+
/*
* hook in to the cleaner list
*/
@@ -936,65 +941,24 @@ fle_free(struct flentry *fle)
uma_zfree((fle->f_flags & FL_IPV6) ? ipv6_zone : ipv4_zone, fle);
}
-/*
- * Find the next bit set where lastbit is the last bit index
- * that was set, mask is a pointer to a uint8_t that stores
- * the current temporary mask because the caller can't clear
- * bits in name and the lookup granularity is 1 byte
- *
- * This could be improved (4x reduction in overhead) for the sparse
- * case by replacing bit_ffs with a more efficient function that works
- * at the 4-byte granularity and change *mask to a uint32_t
- *
- */
-static __inline int
-bit_fns(bitstr_t *name, int nbits, int lastbit, uint8_t *mask)
-{
- bitstr_t *bitstr_start = &name[lastbit/8];
- int value = 0;
- int bitsleft = nbits - lastbit;
-
- if (bitsleft <= 0)
- return (-1);
- /*
- * Note that not only is bit_ffs inefficient,
- * but it doesn't call the first bit set 1
- */
- if ((lastbit & 0x7) == 0) {
- bit_ffs(bitstr_start, bitsleft, &value);
- *mask = *bitstr_start;
- if (value > 0)
- bit_clear(mask, value);
- } else {
- bit_ffs(mask, 8, &value);
- if (value == -1 && bitsleft > 8) {
- lastbit = (lastbit & ~0x7) + 8;
- bit_ffs((bitstr_start + 1),
- ((bitsleft - 1) & ~0x7), &value);
- if (value > 0) {
- *mask = (bitstr_start + 1)[value/8];
- bit_clear(mask, (value % 8));
- }
- } else {
- bit_clear(mask, value);
- }
- }
-
- return (value > 0) ? (value + lastbit) : (-1);
-}
-
static void
flowtable_free_stale(struct flowtable *ft)
{
int curbit = 0, count;
struct flentry *fle, **flehead, *fleprev;
struct flentry *flefreehead, *flefreetail, *fletmp;
- bitstr_t *mask;
- uint8_t mask_tmp;
+ bitstr_t *mask, *tmpmask;
flefreehead = flefreetail = NULL;
mask = flowtable_mask(ft);
- while ((curbit = bit_fns(mask, ft->ft_size, curbit, &mask_tmp)) != -1) {
+ tmpmask = ft->ft_tmpmask;
+ memcpy(tmpmask, mask, ft->ft_size/8);
+ /*
+ * XXX Note to self, bit_ffs operates at the byte level
+ * and thus adds gratuitous overhead
+ */
+ bit_ffs(tmpmask, ft->ft_size, &curbit);
+ while (curbit != -1) {
if (curbit >= ft->ft_size || curbit < -1) {
log(LOG_ALERT,
"warning: bad curbit value %d \n",
@@ -1050,7 +1014,8 @@ flowtable_free_stale(struct flowtable *ft)
if (*flehead == NULL)
bit_clear(mask, curbit);
FL_ENTRY_UNLOCK(ft, curbit);
- curbit++;
+ bit_clear(tmpmask, curbit);
+ bit_ffs(tmpmask, ft->ft_size, &curbit);
}
count = 0;
while ((fle = flefreehead) != NULL) {
@@ -1074,10 +1039,7 @@ flowtable_cleaner(void)
while (1) {
ft = flow_list_head;
while (ft != NULL) {
- if ((ft->ft_flags & FL_PCPU) == 0) {
- flowtable_free_stale(ft);
- } else {
-
+ if (ft->ft_flags & FL_PCPU) {
for (i = 0; i <= mp_maxid; i++) {
if (CPU_ABSENT(i))
continue;
@@ -1092,6 +1054,8 @@ flowtable_cleaner(void)
sched_unbind(curthread);
thread_unlock(curthread);
}
+ } else {
+ flowtable_free_stale(ft);
}
ft = ft->ft_next;
}
OpenPOWER on IntegriCloud