diff options
author | qingli <qingli@FreeBSD.org> | 2009-10-01 20:32:29 +0000 |
---|---|---|
committer | qingli <qingli@FreeBSD.org> | 2009-10-01 20:32:29 +0000 |
commit | 42eac0e4cd282f481832c740708479326b81f790 (patch) | |
tree | 4db02a39f3df6fba7d79e3f3032208d6ad0e2bb9 /sys/net/flowtable.c | |
parent | 81d3ae4acc9a2163ee2f7986b1e4b298bbc2d213 (diff) | |
download | FreeBSD-src-42eac0e4cd282f481832c740708479326b81f790.zip FreeBSD-src-42eac0e4cd282f481832c740708479326b81f790.tar.gz |
The flow-table associates TCP/UDP flows and IP destinations with
specific routes. When the routing table changes, for example,
when a new route with a more specific prefix is inserted into the
routing table, the flow-table is not updated to reflect that change.
As such existing connections cannot take advantage of the new path.
In some cases the path is broken. This patch will update the affected
flow-table entries when a more specific route is added. The route
entry is properly marked when a route is deleted from the table.
In this case, when the flow-table performs a search, the stale
entry is updated automatically. Therefore this patch is not
necessary for route deletion.
Submitted by: simon, phk
Reviewed by: bz, kmacy
MFC after: 3 days
Diffstat (limited to 'sys/net/flowtable.c')
-rw-r--r-- | sys/net/flowtable.c | 40 |
1 files changed, 35 insertions, 5 deletions
diff --git a/sys/net/flowtable.c b/sys/net/flowtable.c index 22cab54..b85ae26 100644 --- a/sys/net/flowtable.c +++ b/sys/net/flowtable.c @@ -830,7 +830,7 @@ fle_free(struct flentry *fle) } static void -flowtable_free_stale(struct flowtable *ft) +flowtable_free_stale(struct flowtable *ft, struct rtentry *rt) { int curbit = 0, count; struct flentry *fle, **flehead, *fleprev; @@ -866,8 +866,14 @@ flowtable_free_stale(struct flowtable *ft) curbit); } #endif - while (fle != NULL) { - if (!flow_stale(ft, fle)) { + while (fle != NULL) { + if (rt != NULL) { + if (__DEVOLATILE(struct rtentry *, fle->f_rt) != rt) { + fleprev = fle; + fle = fle->f_next; + continue; + } + } else if (!flow_stale(ft, fle)) { fleprev = fle; fle = fle->f_next; continue; @@ -916,6 +922,30 @@ flowtable_free_stale(struct flowtable *ft) log(LOG_DEBUG, "freed %d flow entries\n", count); } +void +flowtable_route_flush(struct flowtable *ft, struct rtentry *rt) +{ + int i; + if (ft->ft_flags & FL_PCPU) { + for (i = 0; i <= mp_maxid; i++) { + if (CPU_ABSENT(i)) + continue; + + thread_lock(curthread); + sched_bind(curthread, i); + thread_unlock(curthread); + + flowtable_free_stale(ft, rt); + + thread_lock(curthread); + sched_unbind(curthread); + thread_unlock(curthread); + } + } else { + flowtable_free_stale(ft, rt); + } +} + static void flowtable_clean_vnet(void) { @@ -933,14 +963,14 @@ flowtable_clean_vnet(void) sched_bind(curthread, i); thread_unlock(curthread); - flowtable_free_stale(ft); + flowtable_free_stale(ft, NULL); thread_lock(curthread); sched_unbind(curthread); thread_unlock(curthread); } } else { - flowtable_free_stale(ft); + flowtable_free_stale(ft, NULL); } ft = ft->ft_next; } |