github.com/Cloud-Foundations/Dominator@v0.3.4/lib/net/api.go (about) 1 package net 2 3 import ( 4 "net" 5 "os" 6 "time" 7 8 "github.com/Cloud-Foundations/Dominator/lib/log" 9 "github.com/Cloud-Foundations/Dominator/lib/log/nulllogger" 10 ) 11 12 const ( 13 InterfaceTypeBonding = 1 << iota 14 InterfaceTypeBridge 15 InterfaceTypeEtherNet 16 InterfaceTypeVlan 17 InterfaceTypeTunTap 18 ) 19 20 // CpuSharer defines the interface for types which can be used to 21 // co-operatively share CPUs. 22 type CpuSharer interface { 23 GrabCpu() 24 ReleaseCpu() 25 } 26 27 // Dialer defines a dialer that can be use to create connections. 28 type Dialer interface { 29 Dial(network, address string) (net.Conn, error) 30 } 31 32 type TCPConn interface { 33 net.Conn 34 SetKeepAlive(keepalive bool) error 35 SetKeepAlivePeriod(d time.Duration) error 36 } 37 38 // BindAndDial is similar to the net.Dial function from the standard library 39 // except it binds the underlying network socket to a specified local address. 40 // This gives control over the local port number of the connection, rather than 41 // a randomly assigned port number. 42 func BindAndDial(network, localAddr, remoteAddr string, timeout time.Duration) ( 43 net.Conn, error) { 44 return bindAndDial(network, localAddr, remoteAddr, timeout) 45 } 46 47 // CreateTapDevice will create a "tap" network device with a randomly chosen 48 // interface name. The tap device file and the interface name are returned on 49 // success, else an error is returned. The device will be destroyed when the 50 // file is closed. 51 func CreateTapDevice() (*os.File, string, error) { 52 return createTapDevice() 53 } 54 55 // GetBridgeVlanId will get the VLAN Id associated with the uplink EtherNet 56 // interface for the specified bridge interface. If there is no uplink then the 57 // returned VLAN Id will be -1. 58 func GetBridgeVlanId(bridgeIf string) (int, error) { 59 return getBridgeVlanId(bridgeIf) 60 } 61 62 // ListBridgePorts will return a list of names of interfaces plugged into the 63 // specified bridge interface. An error is returned if the specified interface 64 // does not exist or is not a bridge. 65 func ListBridgePorts(bridge string) ([]string, error) { 66 return listBridgePorts(bridge) 67 } 68 69 // ListBridges will return a list of EtherNet (layer 2) bridges. 70 func ListBridges() ([]net.Interface, error) { 71 bl, _, err := listBroadcastInterfaces(InterfaceTypeBridge, nulllogger.New()) 72 return bl, err 73 } 74 75 // ListBroadcastInterfaces will return a list of broadcast (EtherNet, bridge, 76 // vlan) interfaces. Debugging progress messages are logged to logger. 77 func ListBroadcastInterfaces(interfaceType uint, logger log.DebugLogger) ( 78 []net.Interface, map[string]net.Interface, error) { 79 return listBroadcastInterfaces(interfaceType, logger) 80 } 81 82 // ListenWithReuse is similar to the net.Listen function from the standard 83 // library but sets the SO_REUSEADDR and SO_REUSEPORT options on the underlying 84 // socket. This is needed if using BindAndDial to specify the same local address 85 // as with the listener. 86 func ListenWithReuse(network, address string) (net.Listener, error) { 87 return listenWithReuse(network, address) 88 } 89 90 // NewCpuSharingDialer wraps dialer and returns a new Dialer which uses the 91 // cpuSharer to limit concurrent CPU usage. 92 // Whenever a blocking operation is about to commence (such a Dial or Read or 93 // Write for the connection) the cpuSharer.ReleaseCpu method is called, allowing 94 // the blocking operation to run concurrently. 95 // When the blocking operation completes, the cpuSharer.GrabCpu method is 96 // called, limiting the number of running goroutines that have to compete for 97 // the CPU. 98 // This helps avoid the thundering herd problem where large numbers of 99 // goroutines processing network transactions overwhelm the CPU and affect the 100 // responsiveness of other goroutines such as dashboards and health checks. 101 func NewCpuSharingDialer(dialer Dialer, cpuSharer CpuSharer) Dialer { 102 return newCpuSharingDialer(dialer, cpuSharer) 103 } 104 105 // TestCarrier will return true if the interface has a carrier signal. 106 func TestCarrier(name string) bool { 107 return testCarrier(name) 108 } 109 110 // MeasuringConnection implements the net.Conn interface. Additionally it has 111 // methods to return the cumulative time spent blocking in the Read or Write 112 // methods. 113 type MeasuringConnection struct { 114 net.Conn 115 cumulativeReadTime time.Duration 116 cumulativeWriteTime time.Duration 117 } 118 119 // CumulativeReadTime returns the cumulative time spent blocking on Read. 120 func (conn *MeasuringConnection) CumulativeReadTime() time.Duration { 121 return conn.cumulativeReadTime 122 } 123 124 // CumulativeReadTime returns the cumulative time spent blocking on Write. 125 func (conn *MeasuringConnection) CumulativeWriteTime() time.Duration { 126 return conn.cumulativeWriteTime 127 } 128 129 func (conn *MeasuringConnection) Read(b []byte) (n int, err error) { 130 return conn.read(b) 131 } 132 133 func (conn *MeasuringConnection) Write(b []byte) (n int, err error) { 134 return conn.write(b) 135 } 136 137 // MeasuringDialer implements the Dialer interface. Additionally it has 138 // methods to return the cumulative time spent blocking in the Dial method. 139 type MeasuringDialer struct { 140 dialer Dialer 141 cumulativeDialTime time.Duration 142 } 143 144 // NewMeasuringDialer wraps dialer and returns a dialer that can be used to 145 // measure the time spent in blocking operations. 146 func NewMeasuringDialer(dialer Dialer) *MeasuringDialer { 147 return newMeasuringDialer(dialer) 148 } 149 150 // CumulativeDialTime returns the cumulative time spent blocking on Dial. 151 func (d *MeasuringDialer) CumulativeDialTime() time.Duration { 152 return d.cumulativeDialTime 153 }