From owner-svn-src-all@FreeBSD.ORG Fri Feb 14 10:56:27 2014 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) (using TLSv1 with cipher ADH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id 9BC684A6; Fri, 14 Feb 2014 10:56:27 +0000 (UTC) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.freebsd.org (Postfix) with ESMTPS id 7A87B1A41; Fri, 14 Feb 2014 10:56:27 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.8/8.14.8) with ESMTP id s1EAuRba086750; Fri, 14 Feb 2014 10:56:27 GMT (envelope-from glebius@svn.freebsd.org) Received: (from glebius@localhost) by svn.freebsd.org (8.14.8/8.14.8/Submit) id s1EAuQHK086747; Fri, 14 Feb 2014 10:56:26 GMT (envelope-from glebius@svn.freebsd.org) Message-Id: <201402141056.s1EAuQHK086747@svn.freebsd.org> From: Gleb Smirnoff Date: Fri, 14 Feb 2014 10:56:26 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r261883 - in head: sys/net usr.bin/netstat X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.17 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 14 Feb 2014 10:56:27 -0000 Author: glebius Date: Fri Feb 14 10:56:26 2014 New Revision: 261883 URL: http://svnweb.freebsd.org/changeset/base/261883 Log: Whenever flowtable lookup fails, we do route lookup and then try to insert flow entry. During the route lookup the critical section is exited. It may happen, that after route lookup we will be executed on an other CPU that already has such flowentry. Before this change we simply freed the flowentry and returned to ip_output() with failure. Actually there is nothing wrong with using previously allocated flow entry, updating it properly. Thus, make flowentry_insert() return the new either old fle, and make use of it. Count reuses as "collisions" and real inserts as "inserts". Reviewed by: adrian Sponsored by: Netflix Sponsored by: Nginx, Inc. Modified: head/sys/net/flowtable.c head/sys/net/flowtable.h head/usr.bin/netstat/flowtable.c Modified: head/sys/net/flowtable.c ============================================================================== --- head/sys/net/flowtable.c Fri Feb 14 10:05:21 2014 (r261882) +++ head/sys/net/flowtable.c Fri Feb 14 10:56:26 2014 (r261883) @@ -716,21 +716,39 @@ flow_full(struct flowtable *ft) } static int +flow_matches(struct flentry *fle, uint32_t hash, uint32_t *key, uint8_t + proto, uint32_t fibnum) +{ + + if (fle->f_fhash == hash && + bcmp(&fle->f_flow, key, KEYLEN(fle->f_flags)) == 0 && + proto == fle->f_proto && fibnum == fle->f_fibnum && + (fle->f_rt->rt_flags & RTF_UP) && + fle->f_rt->rt_ifp != NULL && + (fle->f_lle->la_flags & LLE_VALID)) + return (1); + + return (0); +} + +static struct flentry * flowtable_insert(struct flowtable *ft, uint32_t hash, uint32_t *key, uint32_t fibnum, struct route *ro, uint16_t flags) { struct flist *flist; struct flentry *fle, *iter; - int depth; bitstr_t *mask; + int depth; + uint8_t proto; fle = uma_zalloc(flow_zone, M_NOWAIT | M_ZERO); if (fle == NULL) - return (ENOMEM); + return (NULL); + proto = flags_to_proto(flags); bcopy(key, &fle->f_flow, KEYLEN(flags)); fle->f_flags |= (flags & FL_IPV6); - fle->f_proto = flags_to_proto(flags); + fle->f_proto = proto; fle->f_rt = ro->ro_rt; fle->f_lle = ro->ro_lle; fle->f_fhash = hash; @@ -748,21 +766,24 @@ flowtable_insert(struct flowtable *ft, u } depth = 0; - FLOWSTAT_INC(ft, ft_collisions); /* * find end of list and make sure that we were not * preempted by another thread handling this flow */ SLIST_FOREACH(iter, flist, f_next) { - if (iter->f_fhash == hash && !flow_stale(ft, iter)) { + if (flow_matches(iter, hash, key, proto, fibnum)) { /* - * there was either a hash collision - * or we lost a race to insert + * We probably migrated to an other CPU after + * lookup in flowtable_lookup_common() failed. + * It appeared that this CPU already has flow + * entry. */ + iter->f_uptime = time_uptime; + iter->f_flags |= flags; critical_exit(); + FLOWSTAT_INC(ft, ft_collisions); uma_zfree(flow_zone, fle); - - return (EEXIST); + return (iter); } depth++; } @@ -773,8 +794,9 @@ flowtable_insert(struct flowtable *ft, u SLIST_INSERT_HEAD(flist, fle, f_next); skip: critical_exit(); + FLOWSTAT_INC(ft, ft_inserts); - return (0); + return (fle); } struct flentry * @@ -885,12 +907,7 @@ flowtable_lookup_common(struct flowtable critical_enter(); flist = flowtable_list(ft, hash); SLIST_FOREACH(fle, flist, f_next) - if (fle->f_fhash == hash && bcmp(&fle->f_flow, key, - KEYLEN(fle->f_flags)) == 0 && - proto == fle->f_proto && fibnum == fle->f_fibnum && - (fle->f_rt->rt_flags & RTF_UP) && - fle->f_rt->rt_ifp != NULL && - (fle->f_lle->la_flags & LLE_VALID)) { + if (flow_matches(fle, hash, key, proto, fibnum)) { fle->f_uptime = time_uptime; fle->f_flags |= flags; critical_exit(); @@ -977,17 +994,19 @@ flowtable_lookup_common(struct flowtable ro->ro_lle = lle; - if (flowtable_insert(ft, hash, key, fibnum, ro, flags) != 0) { + fle = flowtable_insert(ft, hash, key, fibnum, ro, flags); + if (fle == NULL) { RTFREE(rt); LLE_FREE(lle); return (NULL); } success: - if (fle != NULL && (m->m_flags & M_FLOWID) == 0) { + if (m->m_flags & M_FLOWID) { m->m_flags |= M_FLOWID; m->m_pkthdr.flowid = fle->f_fhash; } + return (fle); } Modified: head/sys/net/flowtable.h ============================================================================== --- head/sys/net/flowtable.h Fri Feb 14 10:05:21 2014 (r261882) +++ head/sys/net/flowtable.h Fri Feb 14 10:56:26 2014 (r261883) @@ -40,6 +40,7 @@ struct flowtable_stat { uint64_t ft_hits; uint64_t ft_lookups; uint64_t ft_fail_lle_invalid; + uint64_t ft_inserts; }; #ifdef _KERNEL Modified: head/usr.bin/netstat/flowtable.c ============================================================================== --- head/usr.bin/netstat/flowtable.c Fri Feb 14 10:05:21 2014 (r261882) +++ head/usr.bin/netstat/flowtable.c Fri Feb 14 10:56:26 2014 (r261883) @@ -52,10 +52,12 @@ print_stats(struct flowtable_stat *stat) p(ft_lookups, "\t%ju lookup%s\n"); p(ft_hits, "\t%ju hit%s\n"); p2(ft_misses, "\t%ju miss%s\n"); + p(ft_inserts, "\t%ju insert%s\n"); p(ft_collisions, "\t%ju collision%s\n"); p(ft_free_checks, "\t%ju free check%s\n"); p(ft_frees, "\t%ju free%s\n"); - p(ft_fail_lle_invalid, "\t%ju lookups w/ no resolved Layer 2 address%s\n"); + p(ft_fail_lle_invalid, + "\t%ju lookup%s with not resolved Layer 2 address\n"); #undef p2 #undef p