diff options
Diffstat (limited to 'sys')
-rw-r--r-- | sys/net/flowtable.c | 40 | ||||
-rw-r--r-- | sys/net/flowtable.h | 2 | ||||
-rw-r--r-- | sys/net/route.c | 61 |
3 files changed, 98 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; } diff --git a/sys/net/flowtable.h b/sys/net/flowtable.h index afc8fb7..7d7abdf 100644 --- a/sys/net/flowtable.h +++ b/sys/net/flowtable.h @@ -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 diff --git a/sys/net/route.c b/sys/net/route.c index fc76c92..1ab039f 100644 --- a/sys/net/route.c +++ b/sys/net/route.c @@ -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> @@ -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; @@ -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); /* @@ -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 |