Skip to content

Commit

Permalink
MFC r197687
Browse files Browse the repository at this point in the history
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.

Reviewed by:	bz, kmacy
Approved by:	re
  • Loading branch information
qingli authored and qingli committed Oct 6, 2009
1 parent 7ad890b commit f9d6140
Show file tree
Hide file tree
Showing 3 changed files with 98 additions and 5 deletions.
40 changes: 35 additions & 5 deletions sys/net/flowtable.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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)
{
Expand All @@ -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;
}
Expand Down
2 changes: 2 additions & 0 deletions sys/net/flowtable.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,5 +51,7 @@ struct flowtable *flowtable_alloc(int nentry, int flags);
int flowtable_lookup(struct flowtable *ft, struct mbuf *m,
struct route *ro, uint32_t fibnum);

void flowtable_route_flush(struct flowtable *ft, struct rtentry *rt);

#endif /* _KERNEL */
#endif
61 changes: 61 additions & 0 deletions sys/net/route.c
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@
#include <net/if_dl.h>
#include <net/route.h>
#include <net/vnet.h>
#include <net/flowtable.h>

#ifdef RADIX_MPATH
#include <net/radix_mpath.h>
Expand Down Expand Up @@ -996,6 +997,9 @@ rtrequest1_fib(int req, struct rt_addrinfo *info, struct rtentry **ret_nrt,
{
int error = 0, needlock = 0;
register struct rtentry *rt;
#ifdef FLOWTABLE
register struct rtentry *rt0;
#endif
register struct radix_node *rn;
register struct radix_node_head *rnh;
struct ifaddr *ifa;
Expand Down Expand Up @@ -1153,6 +1157,53 @@ rtrequest1_fib(int req, struct rt_addrinfo *info, struct rtentry **ret_nrt,
}
#endif

#ifdef FLOWTABLE
rt0 = NULL;
/* XXX
* "flow-table" only support IPv4 at the moment.
*/
if (dst->sa_family == AF_INET) {
rn = rnh->rnh_matchaddr(dst, rnh);
if (rn && ((rn->rn_flags & RNF_ROOT) == 0)) {
struct sockaddr *mask;
u_char *m, *n;
int len;

/*
* compare mask to see if the new route is
* more specific than the existing one
*/
rt0 = RNTORT(rn);
RT_LOCK(rt0);
RT_ADDREF(rt0);
RT_UNLOCK(rt0);
/*
* A host route is already present, so
* leave the flow-table entries as is.
*/
if (rt0->rt_flags & RTF_HOST) {
RTFREE(rt0);
rt0 = NULL;
} else if (!(flags & RTF_HOST) && netmask) {
mask = rt_mask(rt0);
len = mask->sa_len;
m = (u_char *)mask;
n = (u_char *)netmask;
while (len-- > 0) {
if (*n != *m)
break;
n++;
m++;
}
if (len == 0 || (*n < *m)) {
RTFREE(rt0);
rt0 = NULL;
}
}
}
}
#endif

/* XXX mtu manipulation will be done in rnh_addaddr -- itojun */
rn = rnh->rnh_addaddr(ndst, netmask, rnh, rt->rt_nodes);
/*
Expand All @@ -1165,8 +1216,18 @@ rtrequest1_fib(int req, struct rt_addrinfo *info, struct rtentry **ret_nrt,
Free(rt_key(rt));
RT_LOCK_DESTROY(rt);
uma_zfree(V_rtzone, rt);
#ifdef FLOWTABLE
if (rt0 != NULL)
RTFREE(rt0);
#endif
senderr(EEXIST);
}
#ifdef FLOWTABLE
else if (rt0 != NULL) {
flowtable_route_flush(V_ip_ft, rt0);
RTFREE(rt0);
}
#endif

/*
* If this protocol has something to add to this then
Expand Down

0 comments on commit f9d6140

Please sign in to comment.