Patchwork libgo patch committed: Use native endianness for GNU/Linux netlink

login
register
mail settings
Submitter Ian Taylor
Date April 20, 2012, 8:11 p.m.
Message ID <mcr4nse88op.fsf@dhcp-172-18-216-180.mtv.corp.google.com>
Download mbox | patch
Permalink /patch/154135/
State New
Headers show

Comments

Ian Taylor - April 20, 2012, 8:11 p.m.
This patch to libgo changes the way that GNU/Linux netlink code is
handled on big-endian systems.  Rather than test whether the system is
big- or little-endian, this code simply uses the native endianness,
whatever it is, via the unsafe package.  Bootstrapped and ran Go
testsuite on x86_64-unknown-linux-gnu and powerpc64-unknown-linux-gnu.
Committed to mainline and 4.7 branch.

Ian

Patch

Index: libgo/configure.ac
===================================================================
--- libgo/configure.ac	(revision 186144)
+++ libgo/configure.ac	(working copy)
@@ -400,12 +400,6 @@  dnl Test if -lrt is required for sched_y
 AC_SEARCH_LIBS([sched_yield], [rt])
 
 AC_C_BIGENDIAN
-case $ac_cv_c_bigendian in
-  yes) GO_BIGENDIAN=true ;;
-  no) GO_BIGENDIAN=false ;;
-  *) AC_MSG_ERROR([unknown endianness]) ;;
-esac
-AC_SUBST(GO_BIGENDIAN)
 
 GCC_CHECK_UNWIND_GETIPINFO
 
Index: libgo/go/net/interface_linux.go
===================================================================
--- libgo/go/net/interface_linux.go	(revision 186123)
+++ libgo/go/net/interface_linux.go	(working copy)
@@ -64,11 +64,7 @@  func newLink(ifim *syscall.IfInfomsg, at
 		case syscall.IFLA_IFNAME:
 			ifi.Name = string(a.Value[:len(a.Value)-1])
 		case syscall.IFLA_MTU:
-			if syscall.BigEndian {
-				ifi.MTU = int(uint32(a.Value[0])<<24 | uint32(a.Value[1])<<16 | uint32(a.Value[2])<<8 | uint32(a.Value[3]))
-			} else {
-				ifi.MTU = int(uint32(a.Value[3])<<24 | uint32(a.Value[2])<<16 | uint32(a.Value[1])<<8 | uint32(a.Value[0]))
-			}
+			ifi.MTU = int(*(*uint32)(unsafe.Pointer(&a.Value[:4][0])))
 		}
 	}
 	return ifi
@@ -197,15 +193,14 @@  func parseProcNetIGMP(path string, ifi *
 			name = f[1]
 		case len(f[0]) == 8:
 			if ifi == nil || name == ifi.Name {
+				// The Linux kernel puts the IP
+				// address in /proc/net/igmp in native
+				// endianness.
 				for i := 0; i+1 < len(f[0]); i += 2 {
 					b[i/2], _ = xtoi2(f[0][i:i+2], 0)
 				}
-				var ifma IPAddr
-				if syscall.BigEndian {
-					ifma = IPAddr{IP: IPv4(b[0], b[1], b[2], b[3])}
-				} else {
-					ifma = IPAddr{IP: IPv4(b[3], b[2], b[1], b[0])}
-				}
+				i := *(*uint32)(unsafe.Pointer(&b[:4][0]))
+				ifma := IPAddr{IP: IPv4(byte(i>>24), byte(i>>16), byte(i>>8), byte(i))}
 				ifmat = append(ifmat, ifma.toAddr())
 			}
 		}
Index: libgo/go/syscall/netlink_linux.go
===================================================================
--- libgo/go/syscall/netlink_linux.go	(revision 186123)
+++ libgo/go/syscall/netlink_linux.go	(working copy)
@@ -30,43 +30,12 @@  type NetlinkRouteRequest struct {
 
 func (rr *NetlinkRouteRequest) toWireFormat() []byte {
 	b := make([]byte, rr.Header.Len)
-	if BigEndian {
-		b[0] = byte(rr.Header.Len >> 24)
-		b[1] = byte(rr.Header.Len >> 16)
-		b[2] = byte(rr.Header.Len >> 8)
-		b[3] = byte(rr.Header.Len)
-		b[4] = byte(rr.Header.Type >> 8)
-		b[5] = byte(rr.Header.Type)
-		b[6] = byte(rr.Header.Flags >> 8)
-		b[7] = byte(rr.Header.Flags)
-		b[8] = byte(rr.Header.Seq >> 24)
-		b[9] = byte(rr.Header.Seq >> 16)
-		b[10] = byte(rr.Header.Seq >> 8)
-		b[11] = byte(rr.Header.Seq)
-		b[12] = byte(rr.Header.Pid >> 24)
-		b[13] = byte(rr.Header.Pid >> 16)
-		b[14] = byte(rr.Header.Pid >> 8)
-		b[15] = byte(rr.Header.Pid)
-		b[16] = byte(rr.Data.Family)
-	} else {
-		b[0] = byte(rr.Header.Len)
-		b[1] = byte(rr.Header.Len >> 8)
-		b[2] = byte(rr.Header.Len >> 16)
-		b[3] = byte(rr.Header.Len >> 24)
-		b[4] = byte(rr.Header.Type)
-		b[5] = byte(rr.Header.Type >> 8)
-		b[6] = byte(rr.Header.Flags)
-		b[7] = byte(rr.Header.Flags >> 8)
-		b[8] = byte(rr.Header.Seq)
-		b[9] = byte(rr.Header.Seq >> 8)
-		b[10] = byte(rr.Header.Seq >> 16)
-		b[11] = byte(rr.Header.Seq >> 24)
-		b[12] = byte(rr.Header.Pid)
-		b[13] = byte(rr.Header.Pid >> 8)
-		b[14] = byte(rr.Header.Pid >> 16)
-		b[15] = byte(rr.Header.Pid >> 24)
-		b[16] = byte(rr.Data.Family)
-	}
+	*(*uint32)(unsafe.Pointer(&b[0:4][0])) = rr.Header.Len
+	*(*uint16)(unsafe.Pointer(&b[4:6][0])) = rr.Header.Type
+	*(*uint16)(unsafe.Pointer(&b[6:8][0])) = rr.Header.Flags
+	*(*uint32)(unsafe.Pointer(&b[8:12][0])) = rr.Header.Seq
+	*(*uint32)(unsafe.Pointer(&b[12:16][0])) = rr.Header.Pid
+	b[16] = byte(rr.Data.Family)
 	return b
 }
 
Index: libgo/Makefile.am
===================================================================
--- libgo/Makefile.am	(revision 186123)
+++ libgo/Makefile.am	(working copy)
@@ -1559,7 +1559,6 @@  s-syscall_arch: Makefile
 	echo "package syscall" > syscall_arch.go.tmp
 	echo 'const ARCH = "'$(GOARCH)'"' >> syscall_arch.go.tmp
 	echo 'const OS = "'$(GOOS)'"' >> syscall_arch.go.tmp
-	echo 'const BigEndian = $(GO_BIGENDIAN)' >> syscall_arch.go.tmp
 	$(SHELL) $(srcdir)/../move-if-change syscall_arch.go.tmp syscall_arch.go
 	$(STAMP) $@