Commit 130e3f9a authored by Mikio Hara's avatar Mikio Hara

net/internal/socktest: add hook for Listen, failed system call counters

Change-Id: Icaac9a48a3b9a3c5542235162e21ab8303592965
Reviewed-on: https://go-review.googlesource.com/8641Reviewed-by: default avatarIan Lance Taylor <iant@golang.org>
parent e629cd0f
......@@ -5,7 +5,10 @@
// Package socktest provides utilities for socket testing.
package socktest
import "sync"
import (
"fmt"
"sync"
)
func switchInit(sw *Switch) {
sw.fltab = make(map[FilterType]Filter)
......@@ -70,7 +73,11 @@ func cookie(family, sotype, proto int) Cookie {
type Status struct {
Cookie Cookie
Err error // error status of socket system call
SocketErr int // error status of socket by SO_ERROR
SocketErr error // error status of socket by SO_ERROR
}
func (so Status) String() string {
return fmt.Sprintf("(%s, %s, %s): syscallerr=%v, socketerr=%v", familyString(so.Cookie.Family()), typeString(so.Cookie.Type()), protocolString(so.Cookie.Protocol()), so.Err, so.SocketErr)
}
// A Stat represents a per-cookie socket statistics.
......@@ -80,9 +87,20 @@ type Stat struct {
Protocol int // protocol number
Opened uint64 // number of sockets opened
Accepted uint64 // number of sockets accepted
Connected uint64 // number of sockets connected
Listened uint64 // number of sockets listened
Accepted uint64 // number of sockets accepted
Closed uint64 // number of sockets closed
OpenFailed uint64 // number of sockets open failed
ConnectFailed uint64 // number of sockets connect failed
ListenFailed uint64 // number of sockets listen failed
AcceptFailed uint64 // number of sockets accept failed
CloseFailed uint64 // number of sockets close failed
}
func (st Stat) String() string {
return fmt.Sprintf("(%s, %s, %s): opened=%d, connected=%d, listened=%d, accepted=%d, closed=%d, openfailed=%d, connectfailed=%d, listenfailed=%d, acceptfailed=%d, closefailed=%d", familyString(st.Family), typeString(st.Type), protocolString(st.Protocol), st.Opened, st.Connected, st.Listened, st.Accepted, st.Closed, st.OpenFailed, st.ConnectFailed, st.ListenFailed, st.AcceptFailed, st.CloseFailed)
}
type stats map[Cookie]*Stat
......@@ -101,8 +119,9 @@ type FilterType int
const (
FilterSocket FilterType = iota // for Socket
FilterAccept // for Accept or Accept4
FilterConnect // for Connect or ConnectEx
FilterListen // for Listen
FilterAccept // for Accept or Accept4
FilterGetsockoptInt // for GetsockoptInt
FilterClose // for Close or Closesocket
)
......
// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build !plan9
package socktest
import (
"fmt"
"syscall"
)
func familyString(family int) string {
switch family {
case syscall.AF_INET:
return "inet4"
case syscall.AF_INET6:
return "inet6"
case syscall.AF_UNIX:
return "local"
default:
return fmt.Sprintf("%d", family)
}
}
func typeString(sotype int) string {
var s string
switch sotype & 0xff {
case syscall.SOCK_STREAM:
s = "stream"
case syscall.SOCK_DGRAM:
s = "datagram"
case syscall.SOCK_RAW:
s = "raw"
case syscall.SOCK_SEQPACKET:
s = "seqpacket"
default:
s = fmt.Sprintf("%d", sotype&0xff)
}
if flags := uint(sotype) & ^uint(0xff); flags != 0 {
s += fmt.Sprintf("|%#x", flags)
}
return s
}
func protocolString(proto int) string {
switch proto {
case 0:
return "default"
case syscall.IPPROTO_TCP:
return "tcp"
case syscall.IPPROTO_UDP:
return "udp"
default:
return fmt.Sprintf("%d", proto)
}
}
......@@ -8,3 +8,9 @@ package socktest
// Sockets maps a socket descriptor to the status of socket.
type Sockets map[int]Status
func familyString(family int) string { return "<nil>" }
func typeString(sotype int) string { return "<nil>" }
func protocolString(proto int) string { return "<nil>" }
......@@ -30,12 +30,13 @@ func (sw *Switch) Accept4(s, flags int) (ns int, sa syscall.Sockaddr, err error)
return -1, nil, err
}
sw.smu.Lock()
defer sw.smu.Unlock()
if so.Err != nil {
sw.stats.getLocked(so.Cookie).AcceptFailed++
return -1, nil, so.Err
}
sw.smu.Lock()
nso := sw.addLocked(ns, so.Cookie.Family(), so.Cookie.Type(), so.Cookie.Protocol())
sw.stats.getLocked(nso.Cookie).Accepted++
sw.smu.Unlock()
return ns, sa, nil
}
......@@ -27,13 +27,14 @@ func (sw *Switch) Socket(family, sotype, proto int) (s int, err error) {
return -1, err
}
sw.smu.Lock()
defer sw.smu.Unlock()
if so.Err != nil {
sw.stats.getLocked(so.Cookie).OpenFailed++
return -1, so.Err
}
sw.smu.Lock()
nso := sw.addLocked(s, family, sotype, proto)
sw.stats.getLocked(nso.Cookie).Opened++
sw.smu.Unlock()
return s, nil
}
......@@ -56,13 +57,14 @@ func (sw *Switch) Close(s int) (err error) {
return err
}
sw.smu.Lock()
defer sw.smu.Unlock()
if so.Err != nil {
sw.stats.getLocked(so.Cookie).CloseFailed++
return so.Err
}
sw.smu.Lock()
delete(sw.sotab, s)
sw.stats.getLocked(so.Cookie).Closed++
sw.smu.Unlock()
return nil
}
......@@ -85,12 +87,42 @@ func (sw *Switch) Connect(s int, sa syscall.Sockaddr) (err error) {
return err
}
sw.smu.Lock()
defer sw.smu.Unlock()
if so.Err != nil {
sw.stats.getLocked(so.Cookie).ConnectFailed++
return so.Err
}
sw.smu.Lock()
sw.stats.getLocked(so.Cookie).Connected++
sw.smu.Unlock()
return nil
}
// Listen wraps syscall.Listen.
func (sw *Switch) Listen(s, backlog int) (err error) {
so := sw.sockso(s)
if so == nil {
return syscall.Listen(s, backlog)
}
sw.fmu.RLock()
f, _ := sw.fltab[FilterListen]
sw.fmu.RUnlock()
af, err := f.apply(so)
if err != nil {
return err
}
so.Err = syscall.Listen(s, backlog)
if err = af.apply(so); err != nil {
return err
}
sw.smu.Lock()
defer sw.smu.Unlock()
if so.Err != nil {
sw.stats.getLocked(so.Cookie).ListenFailed++
return so.Err
}
sw.stats.getLocked(so.Cookie).Listened++
return nil
}
......@@ -116,13 +148,14 @@ func (sw *Switch) Accept(s int) (ns int, sa syscall.Sockaddr, err error) {
return -1, nil, err
}
sw.smu.Lock()
defer sw.smu.Unlock()
if so.Err != nil {
sw.stats.getLocked(so.Cookie).AcceptFailed++
return -1, nil, so.Err
}
sw.smu.Lock()
nso := sw.addLocked(ns, so.Cookie.Family(), so.Cookie.Type(), so.Cookie.Protocol())
sw.stats.getLocked(nso.Cookie).Accepted++
sw.smu.Unlock()
return ns, sa, nil
}
......@@ -140,7 +173,8 @@ func (sw *Switch) GetsockoptInt(s, level, opt int) (soerr int, err error) {
if err != nil {
return -1, err
}
so.SocketErr, so.Err = syscall.GetsockoptInt(s, level, opt)
soerr, so.Err = syscall.GetsockoptInt(s, level, opt)
so.SocketErr = syscall.Errno(soerr)
if err = af.apply(so); err != nil {
return -1, err
}
......@@ -148,10 +182,10 @@ func (sw *Switch) GetsockoptInt(s, level, opt int) (soerr int, err error) {
if so.Err != nil {
return -1, so.Err
}
if opt == syscall.SO_ERROR && (so.SocketErr == 0 || syscall.Errno(so.SocketErr) == syscall.EISCONN) {
if opt == syscall.SO_ERROR && (so.SocketErr == syscall.Errno(0) || so.SocketErr == syscall.EISCONN) {
sw.smu.Lock()
sw.stats.getLocked(so.Cookie).Connected++
sw.smu.Unlock()
}
return so.SocketErr, nil
return soerr, nil
}
......@@ -25,13 +25,14 @@ func (sw *Switch) Socket(family, sotype, proto int) (s syscall.Handle, err error
return syscall.InvalidHandle, err
}
sw.smu.Lock()
defer sw.smu.Unlock()
if so.Err != nil {
sw.stats.getLocked(so.Cookie).OpenFailed++
return syscall.InvalidHandle, so.Err
}
sw.smu.Lock()
nso := sw.addLocked(s, family, sotype, proto)
sw.stats.getLocked(nso.Cookie).Opened++
sw.smu.Unlock()
return s, nil
}
......@@ -54,13 +55,14 @@ func (sw *Switch) Closesocket(s syscall.Handle) (err error) {
return err
}
sw.smu.Lock()
defer sw.smu.Unlock()
if so.Err != nil {
sw.stats.getLocked(so.Cookie).CloseFailed++
return so.Err
}
sw.smu.Lock()
delete(sw.sotab, s)
sw.stats.getLocked(so.Cookie).Closed++
sw.smu.Unlock()
return nil
}
......@@ -83,12 +85,13 @@ func (sw *Switch) Connect(s syscall.Handle, sa syscall.Sockaddr) (err error) {
return err
}
sw.smu.Lock()
defer sw.smu.Unlock()
if so.Err != nil {
sw.stats.getLocked(so.Cookie).ConnectFailed++
return so.Err
}
sw.smu.Lock()
sw.stats.getLocked(so.Cookie).Connected++
sw.smu.Unlock()
return nil
}
......@@ -111,11 +114,41 @@ func (sw *Switch) ConnectEx(s syscall.Handle, sa syscall.Sockaddr, b *byte, n ui
return err
}
sw.smu.Lock()
defer sw.smu.Unlock()
if so.Err != nil {
sw.stats.getLocked(so.Cookie).ConnectFailed++
return so.Err
}
sw.smu.Lock()
sw.stats.getLocked(so.Cookie).Connected++
sw.smu.Unlock()
return nil
}
// Listen wraps syscall.Listen.
func (sw *Switch) Listen(s syscall.Handle, backlog int) (err error) {
so := sw.sockso(s)
if so == nil {
return syscall.Listen(s, backlog)
}
sw.fmu.RLock()
f, _ := sw.fltab[FilterListen]
sw.fmu.RUnlock()
af, err := f.apply(so)
if err != nil {
return err
}
so.Err = syscall.Listen(s, backlog)
if err = af.apply(so); err != nil {
return err
}
sw.smu.Lock()
defer sw.smu.Unlock()
if so.Err != nil {
sw.stats.getLocked(so.Cookie).ListenFailed++
return so.Err
}
sw.stats.getLocked(so.Cookie).Listened++
return nil
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment