From afe44b681b9eb91ba2e8309b001770dd5a686a48 Mon Sep 17 00:00:00 2001 From: Sepherosa Ziehau Date: Mon, 2 Feb 2009 17:56:48 +0800 Subject: [PATCH] route: Suppress duplicated rtmsgs generated by rtlookup() in rt_setgate() Add 'generate_report' parameter to rt_setgate(). In rt_setgate(), instead of passing RTL_REPORTMSG to rtlookup(), we pass 'generated_report' to rtlookup(). For rtrequset1(RTM_ADD) and rtredirect(), which always go through all CPUs, we only need to generate rtmsg on CPU0. For {arp,atm,nd6}_rtrequest(), there is no need to generated rtmsg. --- sys/net/route.c | 26 ++++++++++++++++++++++---- sys/net/route.h | 2 +- sys/net/rtsock.c | 3 ++- sys/netinet/if_atm.c | 3 ++- sys/netinet/if_ether.c | 3 ++- sys/netinet6/nd6.c | 3 ++- 6 files changed, 31 insertions(+), 9 deletions(-) diff --git a/sys/net/route.c b/sys/net/route.c index 36ae285dd4..016b1cb21d 100644 --- a/sys/net/route.c +++ b/sys/net/route.c @@ -472,7 +472,10 @@ create: */ rt->rt_flags |= RTF_MODIFIED; flags |= RTF_MODIFIED; - rt_setgate(rt, rt_key(rt), gateway); + + /* We only need to report rtmsg on CPU0 */ + rt_setgate(rt, rt_key(rt), gateway, + mycpuid == 0 ? RTL_REPORTMSG : RTL_DONTREPORT); error = 0; stat = &rtstat.rts_newgateway; } @@ -815,6 +818,7 @@ rtrequest1(int req, struct rt_addrinfo *rtinfo, struct rtentry **ret_nrt) struct radix_node_head *rnh; struct ifaddr *ifa; struct sockaddr *ndst; + boolean_t reportmsg; int error = 0; #define gotoerr(x) { error = x ; goto bad; } @@ -930,7 +934,19 @@ makeroute: bzero(rt, sizeof(struct rtentry)); rt->rt_flags = RTF_UP | rtinfo->rti_flags; rt->rt_cpuid = mycpuid; - error = rt_setgate(rt, dst, rtinfo->rti_info[RTAX_GATEWAY]); + + if (mycpuid != 0 && req == RTM_ADD) { + /* For RTM_ADD, we have already sent rtmsg on CPU0. */ + reportmsg = RTL_DONTREPORT; + } else { + /* + * For RTM_ADD, we only send rtmsg on CPU0. + * For RTM_RESOLVE, we always send rtmsg. XXX + */ + reportmsg = RTL_REPORTMSG; + } + error = rt_setgate(rt, dst, rtinfo->rti_info[RTAX_GATEWAY], + reportmsg); if (error != 0) { Free(rt); gotoerr(error); @@ -1186,7 +1202,8 @@ rt_fixchange(struct radix_node *rn, void *vp) #define ROUNDUP(a) (a>0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long)) int -rt_setgate(struct rtentry *rt0, struct sockaddr *dst, struct sockaddr *gate) +rt_setgate(struct rtentry *rt0, struct sockaddr *dst, struct sockaddr *gate, + boolean_t generate_report) { char *space, *oldspace; int dlen = ROUNDUP(dst->sa_len), glen = ROUNDUP(gate->sa_len); @@ -1266,7 +1283,8 @@ rt_setgate(struct rtentry *rt0, struct sockaddr *dst, struct sockaddr *gate) * * This breaks TTCP for hosts outside the gateway! XXX JH */ - rt->rt_gwroute = _rtlookup(gate, RTL_REPORTMSG, RTF_PRCLONING); + rt->rt_gwroute = _rtlookup(gate, generate_report, + RTF_PRCLONING); if (rt->rt_gwroute == rt) { rt->rt_gwroute = NULL; --rt->rt_refcnt; diff --git a/sys/net/route.h b/sys/net/route.h index 581821d688..863d1836bd 100644 --- a/sys/net/route.h +++ b/sys/net/route.h @@ -343,7 +343,7 @@ void rt_newaddrmsg (int, struct ifaddr *, int, struct rtentry *); void rt_newmaddrmsg (int, struct ifmultiaddr *); void rt_rtmsg(int cmd, struct rtentry *rt, struct ifnet *ifp, int error); int rt_setgate (struct rtentry *, - struct sockaddr *, struct sockaddr *); + struct sockaddr *, struct sockaddr *, boolean_t); void rtalloc (struct route *); void rtalloc_ign (struct route *, u_long); diff --git a/sys/net/rtsock.c b/sys/net/rtsock.c index 054f2f8df4..353c2b4fb2 100644 --- a/sys/net/rtsock.c +++ b/sys/net/rtsock.c @@ -682,7 +682,8 @@ route_output_change_callback(int cmd, struct rt_addrinfo *rtinfo, goto done; } if (rtinfo->rti_gateway != NULL) { - error = rt_setgate(rt, rt_key(rt), rtinfo->rti_gateway); + error = rt_setgate(rt, rt_key(rt), rtinfo->rti_gateway, + RTL_REPORTMSG); if (error != 0) goto done; } diff --git a/sys/netinet/if_atm.c b/sys/netinet/if_atm.c index 7d1639d214..a228a058ef 100644 --- a/sys/netinet/if_atm.c +++ b/sys/netinet/if_atm.c @@ -106,7 +106,8 @@ atm_rtrequest(int req, struct rtentry *rt, struct rt_addrinfo *info) */ if ((rt->rt_flags & RTF_HOST) == 0) { - rt_setgate(rt,rt_key(rt),(struct sockaddr *)&null_sdl); + rt_setgate(rt,rt_key(rt),(struct sockaddr *)&null_sdl, + RTL_DONTREPORT); gate = rt->rt_gateway; SDL(gate)->sdl_type = rt->rt_ifp->if_type; SDL(gate)->sdl_index = rt->rt_ifp->if_index; diff --git a/sys/netinet/if_ether.c b/sys/netinet/if_ether.c index a8a0c8d5a6..6621f423cb 100644 --- a/sys/netinet/if_ether.c +++ b/sys/netinet/if_ether.c @@ -220,7 +220,8 @@ arp_rtrequest(int req, struct rtentry *rt, struct rt_addrinfo *info) * Case 1: This route should come from a route to iface. */ rt_setgate(rt, rt_key(rt), - (struct sockaddr *)&null_sdl); + (struct sockaddr *)&null_sdl, + RTL_DONTREPORT); gate = rt->rt_gateway; SDL(gate)->sdl_type = rt->rt_ifp->if_type; SDL(gate)->sdl_index = rt->rt_ifp->if_index; diff --git a/sys/netinet6/nd6.c b/sys/netinet6/nd6.c index 8c4fb11a8d..c38caf9ee1 100644 --- a/sys/netinet6/nd6.c +++ b/sys/netinet6/nd6.c @@ -1113,7 +1113,8 @@ nd6_rtrequest(int req, struct rtentry *rt, * treated as on-link. */ rt_setgate(rt, rt_key(rt), - (struct sockaddr *)&null_sdl); + (struct sockaddr *)&null_sdl, + RTL_DONTREPORT); gate = rt->rt_gateway; SDL(gate)->sdl_type = ifp->if_type; SDL(gate)->sdl_index = ifp->if_index; -- 2.41.0