| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104 |
- // Copyright 2019 Yunion
- //
- // Licensed under the Apache License, Version 2.0 (the "License");
- // you may not use this file except in compliance with the License.
- // You may obtain a copy of the License at
- //
- // http://www.apache.org/licenses/LICENSE-2.0
- //
- // Unless required by applicable law or agreed to in writing, software
- // distributed under the License is distributed on an "AS IS" BASIS,
- // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- // See the License for the specific language governing permissions and
- // limitations under the License.
- package misc
- import (
- "fmt"
- "net"
- "time"
- "github.com/tatsushid/go-fastping"
- "yunion.io/x/pkg/errors"
- )
- type SPingResult struct {
- addr string
- rtt []time.Duration
- count int
- }
- func NewPingResult(addr string, count int) *SPingResult {
- return &SPingResult{
- addr: addr,
- rtt: make([]time.Duration, 0),
- count: count,
- }
- }
- func (pr *SPingResult) Add(rtt time.Duration) {
- pr.rtt = append(pr.rtt, rtt)
- }
- func (pr SPingResult) Rtt() (min time.Duration, avg time.Duration, max time.Duration) {
- sum := time.Duration(0)
- max = time.Duration(-1)
- min = time.Duration(-1)
- for _, d := range pr.rtt {
- sum += d
- if max < 0 || max < d {
- max = d
- }
- if min < 0 || min > d {
- min = d
- }
- }
- if len(pr.rtt) > 0 {
- avg = sum / time.Duration(len(pr.rtt))
- }
- return
- }
- func (pr SPingResult) Loss() int {
- return 100 - len(pr.rtt)*100/pr.count
- }
- func (pr SPingResult) String() string {
- min, avg, max := pr.Rtt()
- return fmt.Sprintf("%d packets transmitted, %d received, %d%% packet loss, rtt min/avg/max = %d/%d/%d ms", pr.count, len(pr.rtt), pr.Loss(), min/time.Millisecond, avg/time.Millisecond, max/time.Millisecond)
- }
- func Ping(addrList []string, probeCount, timeoutSecond int, debug bool) (map[string]*SPingResult, error) {
- p := fastping.NewPinger()
- count := probeCount
- timeout := time.Second * time.Duration(timeoutSecond)
- p.MaxRTT = timeout
- p.Size = 64
- p.Debug = debug
- result := make(map[string]*SPingResult)
- for _, addr := range addrList {
- result[addr] = NewPingResult(addr, count)
- p.AddIP(addr)
- }
- p.OnRecv = func(addr *net.IPAddr, rtt time.Duration) {
- result[addr.String()].Add(rtt)
- }
- p.OnIdle = func() {
- }
- p.RunLoop()
- defer p.Stop()
- ticker := time.NewTicker(time.Duration(count) * timeout)
- defer ticker.Stop()
- select {
- case <-p.Done():
- if err := p.Err(); err != nil {
- return nil, errors.Wrap(err, "ping error")
- }
- break
- case <-ticker.C:
- break
- }
- return result, nil
- }
|