golang实现BFD协议
毫秒级实现状态监测.
参考了aiobfd ,看了协议文档,
协议帧,包编码解码,用了gopacket的bfd.go ,
然后就是实现 状态 init, up, down的监控.
主要的问题是,时间上,需要快速 的检查发送失败,以判断对端为down掉
// 发送超时失败 func (s *Session) DetectFailure() { for { select { case <-s.clientDone: return default: if !(s.DemandMode || s.asyncDetectTime == 0) { if (s.State == layers.BFDStateInit || s.State == layers.BFDStateUp) && ((time.Now().UnixNano()/1e6 - s.LastRxPacketTime) > (int64(s.asyncDetectTime) / 1000)) { // 状态变化,执行回调函数 go s.callFunc(s.Remote, int(s.State), int(layers.BFDStateDown)) s.State = layers.BFDStateDown s.LocalDiag = layers.BFDDiagnosticTimeExpired s.setDesiredMinTxInterval(DesiredMinTXInterval) slogger.Errorf("Detected BFD remote %s going DOWN ", s.Remote) slogger.Infof("Time since last packet: %d ms; Detect Time: %d ms ", (time.Now().UnixNano()/1e6 - s.LastRxPacketTime), int64(s.asyncDetectTime)/1000) //fmt.Printf("Detected BFD remote %s going DOWN \n", s.Remote) fmt.Printf("Time since last packet: %d ms; Detect Time: %d ms \n", (time.Now().UnixNano()/1e6 - s.LastRxPacketTime), int64(s.asyncDetectTime) / 1000) } } time.Sleep(time.Millisecond / 10) // 这里等待时间, 如果太短,cpu占用就大,等待时长,最后的结果不是很准 } } }
时间上要对应得上来.
最后,实现了协议,当然是要用上来。
package gobfd import ( "fmt" "syscall" "testing" "time" ) const ( family = syscall.AF_INET // 默认ipv4 local = "0.0.0.0" passive = false // 是否是被动模式 rxInterval = 400 // 400 毫秒 txInterval = 400 // 400 毫秒 detectMult = 1 // 报文最大失效的个数 ) // 回调函数 func PrintIpBFDState1(ipAddr string, preState, curState int) error { fmt.Println("ipAddr:", ipAddr, ",preState:", preState, ",curState:", curState) return nil } // 回调函数 func PrintIpBFDState2(ipAddr string, preState, curState int) error { fmt.Println("ipAddr:", ipAddr, ",preState:", preState, ",curState:", curState) return nil } // func TestNewControl(t *testing.T) { fmt.Println("start ..") // 启动 control := NewControl(local, family) // 添加监测 remote1 := "192.168.1.244" // 远程ip control.AddSession(remote1, passive, rxInterval, txInterval, detectMult, PrintIpBFDState1) // 添加监测2 remote2 := "192.168.1.185" // 远程ip2 control.AddSession(remote2, passive, rxInterval, txInterval, detectMult, PrintIpBFDState2) fmt.Println("sleep 30 second...") time.Sleep(time.Second * 30) // 删除监测 fmt.Println("del session ...") control.DelSession(remote1) control.DelSession(remote2) time.Sleep(time.Second * 3) }
github 链接: