Date: Wed, 15 Mar 2017 12:53:20 +1100 (EST) From: Bruce Evans <brde@optusnet.com.au> To: Eric van Gyzen <vangyzen@freebsd.org> Cc: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: Re: svn commit: r315277 - in head/sys: dev/cxgb/ulp/iw_cxgb netinet Message-ID: <20170315110727.M964@besplex.bde.org> In-Reply-To: <201703141827.v2EIRmLv080307@repo.freebsd.org> References: <201703141827.v2EIRmLv080307@repo.freebsd.org>
next in thread | previous in thread | raw e-mail | index | archive | help
On Tue, 14 Mar 2017, Eric van Gyzen wrote: > Log: > KTR: log IPv4 addresses in hex rather than dotted-quad > > When I made the changes in r313821, I fell victim to one of the > classic blunders, the most famous of which is: never get involved > in a land war in Asia. But only slightly less well known is this: > Keep your brain turned on and engaged when making a tedious, sweeping, > mechanical change. KTR can correctly log the immediate integral values > passed to it, as well as constant strings, but not non-constant strings, > since they might change by the time ktrdump retrieves them. > > Reported by: glebius > MFC after: 3 days > Sponsored by: Dell EMC The new format is too raw. Hex is just as easy to read as dotted-quad, but inet_ntoa() also does the equivalent of htonl(). Due to not using it, addresses are now printed reversed in most but not all cases on little-endian arches. They should be converted to host byte order using ntohl() except when they are already in host byte order. Old code already prints some addresses using the bad format %lx or worse (this should be 0x%08x like new code) and still does this conversion. This conversion is still correct, except it doesn't do the reversal on little-endian arches, so users would have to guess which cases are reversed. Addresses are sometimes in host byte order to begin with. Old code might print these in hex without conversion, but when it called inet_ntoa() it first converted to network byte order using htonl(). This now gives consistent reversals on little-endian arches. This commit also fixes the style bug of messes from using the badly-designed API inet_ntoa_r(), but not nearby style bugs. > Modified: head/sys/dev/cxgb/ulp/iw_cxgb/iw_cxgb_cm.c > ============================================================================== > --- head/sys/dev/cxgb/ulp/iw_cxgb/iw_cxgb_cm.c Tue Mar 14 18:08:32 2017 (r315276) > +++ head/sys/dev/cxgb/ulp/iw_cxgb/iw_cxgb_cm.c Tue Mar 14 18:27:48 2017 (r315277) > @@ -1481,9 +1478,8 @@ process_data(struct iwch_ep *ep) > */ > in_getsockaddr(ep->com.so, (struct sockaddr **)&local); > in_getpeeraddr(ep->com.so, (struct sockaddr **)&remote); > - CTR3(KTR_IW_CXGB, "%s local %s remote %s", __FUNCTION__, > - inet_ntoa_r(local->sin_addr, local_str), > - inet_ntoa_r(remote->sin_addr, remote_str)); > + CTR3(KTR_IW_CXGB, "%s local 0x%08x remote 0x%08x", __FUNCTION__, > + local->sin_addr.s_addr, remote->sin_addr.s_addr); > ep->com.local_addr = *local; > ep->com.remote_addr = *remote; > free(local, M_SONAME); Still has 3 style bugs: - continuation indent of 8 instead of KNF 4 - obfuscates the function name by not using a string literal - doesn't even spell the obfuscation using its C99 name __func__. CTR*() uses obfuscated macros which prevent checking for printf() format errors. The macros convert all args to u_long, so all formats except %lx are technically broken. Using htonl() would also convert to a consistent type that is technically correct. htonl() used to return long, but it now returns uint32_t, and the type hacks for CTR*() depend on much the same magic as long sort of being the same as uint32_t for the purposes of htonl(). But changing the type of htonl() broke lots of printf() formats, expecially in code that was careful enough to use the right format to print longs. [... another instances of the above style bugs, and more __FUNCTION__'s visible in unchanged code. > Modified: head/sys/netinet/igmp.c > ============================================================================== > --- head/sys/netinet/igmp.c Tue Mar 14 18:08:32 2017 (r315276) > +++ head/sys/netinet/igmp.c Tue Mar 14 18:27:48 2017 (r315277) > @@ -312,17 +312,6 @@ igmp_scrub_context(struct mbuf *m) > m->m_pkthdr.flowid = 0; > } > > -#ifdef KTR > -static __inline char * > -inet_ntoa_haddr(in_addr_t haddr, char *addrbuf) > -{ > - struct in_addr ia; > - > - ia.s_addr = htonl(haddr); > - return (inet_ntoa_r(ia, addrbuf)); > -} > -#endif This did a double reversal on little-endian arches. The first reversal is now done directly. So the order is even more confusing but less MD than I first thought. I think the address now ends up looking consistently backwards on little-endian arches (provided all callers remember to do the above conversion iff their address starts in host byte order). > @@ -875,9 +861,9 @@ igmp_input_v2_query(struct ifnet *ifp, c > */ > inm = inm_lookup(ifp, igmp->igmp_group); > if (inm != NULL) { > - CTR3(KTR_IGMPV3, "process v2 query %s on ifp %p(%s)", > - inet_ntoa_r(igmp->igmp_group, addrbuf), ifp, > - ifp->if_xname); > + CTR3(KTR_IGMPV3, > + "process v2 query 0x%08x on ifp %p(%s)", > + igmp->igmp_group.s_addr, ifp, ifp->if_xname); > igmp_v2_update_group(inm, timer); > } > } This doesn't have the obfuscations to print the function's name, since it doesn't print the name. Like for KASSERT(), the function name probably shouldn't supplied explicitly or omitted explicity fby the caller, but should be supplied automatically like for assert(3), but not as badly implemented as for assert(3). It can be recovered from the program counter in a way that shouldn't pessimize for space or time. For KTR, it seems to be necessary to pessimize in the generated record (if the user wants function names). The program counter would have to be recorded. Always recording it would be shorter than usually recording pointers to the function's name or literal strings. > @@ -907,12 +893,9 @@ out_locked: > static void > igmp_v2_update_group(struct in_multi *inm, const int timer) > { > -#ifdef KTR > - char addrbuf[INET_ADDRSTRLEN]; > -#endif > > - CTR4(KTR_IGMPV3, "%s: %s/%s timer=%d", __func__, > - inet_ntoa_r(inm->inm_addr, addrbuf), inm->inm_ifp->if_xname, timer); > + CTR4(KTR_IGMPV3, "0x%08x: %s/%s timer=%d", __func__, > + inm->inm_addr.s_addr, inm->inm_ifp->if_xname, timer); This uses the usual obfuscation of the function's name. > ... Most calls print the function name using the __func__ obfuscation, and don't have indentation errors, and are prefectly backwards for htonl()/ ntohl(). > ... > Modified: head/sys/netinet/ip_mroute.c > ============================================================================== > --- head/sys/netinet/ip_mroute.c Tue Mar 14 18:08:32 2017 (r315276) > +++ head/sys/netinet/ip_mroute.c Tue Mar 14 18:27:48 2017 (r315277) > @@ -1066,8 +1060,8 @@ add_mfc(struct mfcctl2 *mfccp) > > /* If an entry already exists, just update the fields */ > if (rt) { > - CTR4(KTR_IPMF, "%s: update mfc orig %s group %lx parent %x", > - __func__, inet_ntoa_r(mfccp->mfcc_origin, addrbuf), > + CTR4(KTR_IPMF, "%s: update mfc orig 0x%08x group %lx parent %x", > + __func__, mfccp->mfcc_origin.s_addr, > (u_long)ntohl(mfccp->mfcc_mcastgrp.s_addr), > mfccp->mfcc_parent); > update_mfc_params(rt, mfccp); This one already printed 1 address in confusing hex format with a not-so bogus cast and a confusing host/network conversion for the printing, and and another confusing hex format. The old hex formats are missing 0x prefixes, so are more confusing that before now that there is a hex format not missing the prefix on the same line. ntohl() no longer returns long, but is cast to u_long for portability. This might be best for printf(), but CTR*() does the same cast. The 'l' in %lx is also technically needed and it is not having 'l' for %x in all CTR*() is technically wrong, (ktrdump copies the args to an array of u_long's and then applies the format string to this, and %x's instead of %lx's in it usually work magically) but it is best to consistently omit casts and consistently use wrong %x formats. Finally, the ntohl() is confusing. I think it is actually correct, and is what this commit should have added where inet_ntoa() was used with no htonl() before it. Apparently the variable is in network byte order, and we need to fudge it into host byte order because printf() will convert from host byte order to network byte order. printf() actually converts host integers in host byte order to big-endian order for printing, but since network byte order is big endian this is like htonl() to reverse the ntohl() in the above. Bruce
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20170315110727.M964>