Module Name: src Committed By: ozaki-r Date: Wed Aug 31 09:14:47 UTC 2016
Modified Files: src/sys/netinet: ip_input.c src/sys/netinet6: ip6_forward.c ip6_input.c Log Message: Make ipforward_rt and ip6_forward_rt percpu Sharing one rtcache between CPUs is just a bad idea. Reviewed by knakahara@ To generate a diff of this commit: cvs rdiff -u -r1.339 -r1.340 src/sys/netinet/ip_input.c cvs rdiff -u -r1.80 -r1.81 src/sys/netinet6/ip6_forward.c cvs rdiff -u -r1.166 -r1.167 src/sys/netinet6/ip6_input.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/netinet/ip_input.c diff -u src/sys/netinet/ip_input.c:1.339 src/sys/netinet/ip_input.c:1.340 --- src/sys/netinet/ip_input.c:1.339 Mon Aug 1 03:15:30 2016 +++ src/sys/netinet/ip_input.c Wed Aug 31 09:14:47 2016 @@ -1,4 +1,4 @@ -/* $NetBSD: ip_input.c,v 1.339 2016/08/01 03:15:30 ozaki-r Exp $ */ +/* $NetBSD: ip_input.c,v 1.340 2016/08/31 09:14:47 ozaki-r Exp $ */ /* * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. @@ -91,7 +91,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: ip_input.c,v 1.339 2016/08/01 03:15:30 ozaki-r Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ip_input.c,v 1.340 2016/08/31 09:14:47 ozaki-r Exp $"); #ifdef _KERNEL_OPT #include "opt_inet.h" @@ -225,7 +225,7 @@ pfil_head_t * inet_pfil_hook __read_mo ipid_state_t * ip_ids __read_mostly; percpu_t * ipstat_percpu __read_mostly; -static struct route ipforward_rt __cacheline_aligned; +static percpu_t *ipforward_rt_percpu __cacheline_aligned; uint16_t ip_id; @@ -345,6 +345,10 @@ ip_init(void) #endif /* MBUFTRACE */ ipstat_percpu = percpu_alloc(sizeof(uint64_t) * IP_NSTATS); + + ipforward_rt_percpu = percpu_alloc(sizeof(struct route)); + if (ipforward_rt_percpu == NULL) + panic("failed to allocate ipforward_rt_percpu"); } static struct in_ifaddr * @@ -1163,11 +1167,14 @@ ip_rtaddr(struct in_addr dst) struct sockaddr dst; struct sockaddr_in dst4; } u; + struct route *ro; sockaddr_in_init(&u.dst4, &dst, 0); SOFTNET_LOCK(); - rt = rtcache_lookup(&ipforward_rt, &u.dst); + ro = percpu_getref(ipforward_rt_percpu); + rt = rtcache_lookup(ro, &u.dst); + percpu_putref(ipforward_rt_percpu); SOFTNET_UNLOCK(); if (rt == NULL) return NULL; @@ -1300,6 +1307,7 @@ ip_forward(struct mbuf *m, int srcrt, st struct sockaddr_in dst4; } u; uint64_t *ips; + struct route *ro; KASSERTMSG(cpu_softintr_p(), "ip_forward: not in the software " "interrupt handler; synchronization assumptions violated"); @@ -1331,7 +1339,9 @@ ip_forward(struct mbuf *m, int srcrt, st sockaddr_in_init(&u.dst4, &ip->ip_dst, 0); - if ((rt = rtcache_lookup(&ipforward_rt, &u.dst)) == NULL) { + ro = percpu_getref(ipforward_rt_percpu); + if ((rt = rtcache_lookup(ro, &u.dst)) == NULL) { + percpu_putref(ipforward_rt_percpu); icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_NET, dest, 0); SOFTNET_UNLOCK(); return; @@ -1376,7 +1386,7 @@ ip_forward(struct mbuf *m, int srcrt, st } } - error = ip_output(m, NULL, &ipforward_rt, + error = ip_output(m, NULL, ro, (IP_FORWARDING | (ip_directedbcast ? IP_ALLOWBROADCAST : 0)), NULL, NULL); @@ -1398,17 +1408,19 @@ ip_forward(struct mbuf *m, int srcrt, st if (mcopy) { #ifdef GATEWAY if (mcopy->m_flags & M_CANFASTFWD) - ipflow_create(&ipforward_rt, mcopy); + ipflow_create(ro, mcopy); #endif m_freem(mcopy); } + percpu_putref(ipforward_rt_percpu); SOFTNET_UNLOCK(); return; redirect: error: if (mcopy == NULL) { + percpu_putref(ipforward_rt_percpu); SOFTNET_UNLOCK(); return; } @@ -1432,7 +1444,7 @@ error: type = ICMP_UNREACH; code = ICMP_UNREACH_NEEDFRAG; - if ((rt = rtcache_validate(&ipforward_rt)) != NULL) + if ((rt = rtcache_validate(ro)) != NULL) destmtu = rt->rt_ifp->if_mtu; #ifdef IPSEC if (ipsec_used) @@ -1450,10 +1462,12 @@ error: */ if (mcopy) m_freem(mcopy); + percpu_putref(ipforward_rt_percpu); SOFTNET_UNLOCK(); return; } icmp_error(mcopy, type, code, dest, destmtu); + percpu_putref(ipforward_rt_percpu); SOFTNET_UNLOCK(); } Index: src/sys/netinet6/ip6_forward.c diff -u src/sys/netinet6/ip6_forward.c:1.80 src/sys/netinet6/ip6_forward.c:1.81 --- src/sys/netinet6/ip6_forward.c:1.80 Tue Jun 28 02:02:56 2016 +++ src/sys/netinet6/ip6_forward.c Wed Aug 31 09:14:47 2016 @@ -1,4 +1,4 @@ -/* $NetBSD: ip6_forward.c,v 1.80 2016/06/28 02:02:56 ozaki-r Exp $ */ +/* $NetBSD: ip6_forward.c,v 1.81 2016/08/31 09:14:47 ozaki-r Exp $ */ /* $KAME: ip6_forward.c,v 1.109 2002/09/11 08:10:17 sakane Exp $ */ /* @@ -31,7 +31,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: ip6_forward.c,v 1.80 2016/06/28 02:02:56 ozaki-r Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ip6_forward.c,v 1.81 2016/08/31 09:14:47 ozaki-r Exp $"); #ifdef _KERNEL_OPT #include "opt_gateway.h" @@ -48,6 +48,7 @@ __KERNEL_RCSID(0, "$NetBSD: ip6_forward. #include <sys/time.h> #include <sys/kernel.h> #include <sys/syslog.h> +#include <sys/percpu.h> #include <net/if.h> #include <net/route.h> @@ -72,7 +73,7 @@ __KERNEL_RCSID(0, "$NetBSD: ip6_forward. #include <net/net_osdep.h> -struct route ip6_forward_rt; +extern percpu_t *ip6_forward_rt_percpu; extern pfil_head_t *inet6_pfil_hook; /* XXX */ @@ -135,6 +136,7 @@ ip6_forward(struct mbuf *m, int srcrt) struct in6_addr src_in6, dst_in6; struct ifnet *rcvif = NULL; struct psref psref; + struct route *ro; #ifdef IPSEC int needipsec = 0; struct secpolicy *sp = NULL; @@ -203,6 +205,7 @@ ip6_forward(struct mbuf *m, int srcrt) } #endif /* IPSEC */ + ro = percpu_getref(ip6_forward_rt_percpu); if (srcrt) { union { struct sockaddr dst; @@ -210,17 +213,18 @@ ip6_forward(struct mbuf *m, int srcrt) } u; sockaddr_in6_init(&u.dst6, &ip6->ip6_dst, 0, 0, 0); - if ((rt = rtcache_lookup(&ip6_forward_rt, &u.dst)) == NULL) { + if ((rt = rtcache_lookup(ro, &u.dst)) == NULL) { IP6_STATINC(IP6_STAT_NOROUTE); /* XXX in6_ifstat_inc(rt->rt_ifp, ifs6_in_noroute) */ if (mcopy) { icmp6_error(mcopy, ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_NOROUTE, 0); } + percpu_putref(ip6_forward_rt_percpu); goto drop; } - } else if ((rt = rtcache_validate(&ip6_forward_rt)) == NULL && - (rt = rtcache_update(&ip6_forward_rt, 1)) == NULL) { + } else if ((rt = rtcache_validate(ro)) == NULL && + (rt = rtcache_update(ro, 1)) == NULL) { /* * rtcache_getdst(ip6_forward_rt)->sin6_addr was equal to * ip6->ip6_dst @@ -231,9 +235,11 @@ ip6_forward(struct mbuf *m, int srcrt) icmp6_error(mcopy, ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_NOROUTE, 0); } + percpu_putref(ip6_forward_rt_percpu); goto drop; } - dst = satocsin6(rtcache_getdst(&ip6_forward_rt)); + dst = satocsin6(rtcache_getdst(ro)); + percpu_putref(ip6_forward_rt_percpu); /* * Source scope check: if a packet can't be delivered to its @@ -318,10 +324,11 @@ ip6_forward(struct mbuf *m, int srcrt) */ if (rt->rt_ifp == rcvif && !srcrt && ip6_sendredirects && (rt->rt_flags & (RTF_DYNAMIC|RTF_MODIFIED)) == 0) { + ro = percpu_getref(ip6_forward_rt_percpu); if ((rt->rt_ifp->if_flags & IFF_POINTOPOINT) && - nd6_is_addr_neighbor( - satocsin6(rtcache_getdst(&ip6_forward_rt)), - rt->rt_ifp)) { + nd6_is_addr_neighbor(satocsin6(rtcache_getdst(ro)), + rt->rt_ifp)) { + percpu_putref(ip6_forward_rt_percpu); /* * If the incoming interface is equal to the outgoing * one, the link attached to the interface is @@ -341,6 +348,7 @@ ip6_forward(struct mbuf *m, int srcrt) ICMP6_DST_UNREACH_ADDR, 0); goto drop; } + percpu_putref(ip6_forward_rt_percpu); type = ND_REDIRECT; } @@ -409,8 +417,10 @@ ip6_forward(struct mbuf *m, int srcrt) IP6_STATINC(IP6_STAT_REDIRECTSENT); else { #ifdef GATEWAY + ro = percpu_getref(ip6_forward_rt_percpu); if (m->m_flags & M_CANFASTFWD) - ip6flow_create(&ip6_forward_rt, m); + ip6flow_create(ro, m); + percpu_putref(ip6_forward_rt_percpu); #endif if (mcopy) goto freecopy; Index: src/sys/netinet6/ip6_input.c diff -u src/sys/netinet6/ip6_input.c:1.166 src/sys/netinet6/ip6_input.c:1.167 --- src/sys/netinet6/ip6_input.c:1.166 Tue Aug 2 04:50:16 2016 +++ src/sys/netinet6/ip6_input.c Wed Aug 31 09:14:47 2016 @@ -1,4 +1,4 @@ -/* $NetBSD: ip6_input.c,v 1.166 2016/08/02 04:50:16 knakahara Exp $ */ +/* $NetBSD: ip6_input.c,v 1.167 2016/08/31 09:14:47 ozaki-r Exp $ */ /* $KAME: ip6_input.c,v 1.188 2001/03/29 05:34:31 itojun Exp $ */ /* @@ -62,7 +62,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: ip6_input.c,v 1.166 2016/08/02 04:50:16 knakahara Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ip6_input.c,v 1.167 2016/08/31 09:14:47 ozaki-r Exp $"); #ifdef _KERNEL_OPT #include "opt_gateway.h" @@ -87,6 +87,7 @@ __KERNEL_RCSID(0, "$NetBSD: ip6_input.c, #include <sys/proc.h> #include <sys/sysctl.h> #include <sys/cprng.h> +#include <sys/percpu.h> #include <net/if.h> #include <net/if_types.h> @@ -143,6 +144,8 @@ pfil_head_t *inet6_pfil_hook; percpu_t *ip6stat_percpu; +percpu_t *ip6_forward_rt_percpu __cacheline_aligned; + static void ip6_init2(void); static void ip6intr(void *); static struct m_tag *ip6_setdstifaddr(struct mbuf *, const struct in6_ifaddr *); @@ -194,6 +197,10 @@ ip6_init(void) KASSERT(inet6_pfil_hook != NULL); ip6stat_percpu = percpu_alloc(sizeof(uint64_t) * IP6_NSTATS); + + ip6_forward_rt_percpu = percpu_alloc(sizeof(struct route)); + if (ip6_forward_rt_percpu == NULL) + panic("failed to alllocate ip6_forward_rt_percpu"); } static void @@ -239,8 +246,6 @@ ip6intr(void *arg __unused) mutex_exit(softnet_lock); } -extern struct route ip6_forward_rt; - void ip6_input(struct mbuf *m, struct ifnet *rcvif) { @@ -256,6 +261,7 @@ ip6_input(struct mbuf *m, struct ifnet * struct sockaddr dst; struct sockaddr_in6 dst6; } u; + struct route *ro; /* * make sure we don't have onion peering information into m_tag. @@ -461,7 +467,9 @@ ip6_input(struct mbuf *m, struct ifnet * /* * Unicast check */ - rt = rtcache_lookup2(&ip6_forward_rt, &u.dst, 1, &hit); + ro = percpu_getref(ip6_forward_rt_percpu); + rt = rtcache_lookup2(ro, &u.dst, 1, &hit); + percpu_putref(ip6_forward_rt_percpu); if (hit) IP6_STATINC(IP6_STAT_FORWARD_CACHEHIT); else