From c82308da6f34cfb086b789381b6ca4d907f1f02e Mon Sep 17 00:00:00 2001 From: Trekkie Coder Date: Mon, 19 Feb 2024 18:35:57 +0900 Subject: [PATCH] bfd: Added bind option to select source --- loxinet/cluster.go | 36 ++++++++++++++++++++---------------- loxinet/loxinet.go | 4 ++-- loxinet/utils.go | 18 ++++++++++++------ options/options.go | 2 +- proto/bfd.go | 45 ++++++++++++++++++++++++++++++++------------- 5 files changed, 67 insertions(+), 38 deletions(-) diff --git a/loxinet/cluster.go b/loxinet/cluster.go index 6190939a..602a493d 100644 --- a/loxinet/cluster.go +++ b/loxinet/cluster.go @@ -36,13 +36,6 @@ const ( CIStateErr ) -// Config related constants -const ( - KAConfigFile = "/etc/keepalived/keepalived.conf" - KAPidFile1 = "/var/run/keepalived.pid" - KAPidFile2 = "/var/run/vrrp.pid" -) - // ClusterInstance - Struct for Cluster Instance information type ClusterInstance struct { State int @@ -56,11 +49,20 @@ type ClusterNode struct { Status DpStatusT } +// CIKAArgs - Struct for cluster BFD args +type CIKAArgs struct { + SpawnKa bool + RemoteIP net.IP + SourceIP net.IP + Interval int64 +} + // CIStateH - Cluster context handler type CIStateH struct { SpawnKa bool RemoteIP net.IP - KaArgsVal int64 + SourceIP net.IP + Interval int64 ClusterMap map[string]*ClusterInstance StateMap map[string]int NodeMap map[string]*ClusterNode @@ -93,17 +95,18 @@ func (ci *CIStateH) startBFDProto() { time.Sleep(KAInitTiVal * time.Second) txInterval := uint32(bfd.BFDDflSysTXIntervalUs) - if ci.KaArgsVal != 0 && ci.KaArgsVal >= bfd.BFDMinSysTXIntervalUs { - txInterval = uint32(ci.KaArgsVal) + if ci.Interval != 0 && ci.Interval >= bfd.BFDMinSysTXIntervalUs { + txInterval = uint32(ci.Interval) } bs := bfd.StructNew(3784) - err := bs.BFDAddRemote(ci.RemoteIP.String(), 3784, txInterval, 3, cmn.CIDefault, ci) + bfdSessConfigArgs := bfd.ConfigArgs{RemoteIP: ci.RemoteIP.String(), SourceIP: ci.SourceIP.String(), Port: 3784, Interval: txInterval, Multi: 3, Instance: cmn.CIDefault} + err := bs.BFDAddRemote(bfdSessConfigArgs, ci) if err != nil { tk.LogIt(tk.LogCritical, "KA - Cant add BFD remote\n") os.Exit(1) } - tk.LogIt(tk.LogInfo, "KA - Added BFD remote %s:%vus\n", ci.RemoteIP.String(), txInterval) + tk.LogIt(tk.LogInfo, "KA - Added BFD remote %s:%s:%vus\n", ci.RemoteIP.String(), ci.SourceIP.String(), txInterval) } // CITicker - Periodic ticker for Cluster module @@ -119,7 +122,7 @@ func (ci *CIStateH) CISpawn() { } // CIInit - routine to initialize Cluster context -func CIInit(spawnKa bool, remoteIP net.IP, extArgs int64) *CIStateH { +func CIInit(args CIKAArgs) *CIStateH { var nCIh = new(CIStateH) nCIh.StateMap = make(map[string]int) nCIh.StateMap["MASTER"] = cmn.CIStateMaster @@ -127,9 +130,10 @@ func CIInit(spawnKa bool, remoteIP net.IP, extArgs int64) *CIStateH { nCIh.StateMap["FAULT"] = cmn.CIStateConflict nCIh.StateMap["STOP"] = cmn.CIStateNotDefined nCIh.StateMap["NOT_DEFINED"] = cmn.CIStateNotDefined - nCIh.SpawnKa = spawnKa - nCIh.RemoteIP = remoteIP - nCIh.KaArgsVal = extArgs + nCIh.SpawnKa = args.SpawnKa + nCIh.RemoteIP = args.RemoteIP + nCIh.SourceIP = args.SourceIP + nCIh.Interval = args.Interval nCIh.ClusterMap = make(map[string]*ClusterInstance) if _, ok := nCIh.ClusterMap[cmn.CIDefault]; !ok { diff --git a/loxinet/loxinet.go b/loxinet/loxinet.go index 388733e5..fdc3ffbd 100644 --- a/loxinet/loxinet.go +++ b/loxinet/loxinet.go @@ -182,7 +182,7 @@ var mh loxiNetH func loxiNetInit() { var rpcMode int - spawnKa, kaMode, kaExtArgs := KAString2Mode(opts.Opts.Ka) + kaArgs := KAString2Mode(opts.Opts.Ka) clusterMode := false if opts.Opts.ClusterNodes != "none" { clusterMode = true @@ -249,7 +249,7 @@ func loxiNetInit() { } // Initialize the clustering subsystem - mh.has = CIInit(spawnKa, kaMode, kaExtArgs) + mh.has = CIInit(kaArgs) if clusterMode { if opts.Opts.Bgp { tk.LogIt(tk.LogInfo, "init-wait cluster mode\n") diff --git a/loxinet/utils.go b/loxinet/utils.go index d9ad9ee7..2ef64554 100644 --- a/loxinet/utils.go +++ b/loxinet/utils.go @@ -139,26 +139,32 @@ func LogString2Level(logStr string) tk.LogLevelT { } // KAString2Mode - Convert ka mode in string opts to spawn/KAMode -func KAString2Mode(kaStr string) (bool, net.IP, int64) { +func KAString2Mode(kaStr string) CIKAArgs { spawnKa := false - kaExtraArgs := int64(0) + interval := int64(0) + sourceIP := net.ParseIP("0.0.0.0") if kaStr == "none" { - return spawnKa, nil, kaExtraArgs + return CIKAArgs{SpawnKa: spawnKa, RemoteIP: nil, Interval: interval} } kaArgs := strings.Split(kaStr, ":") remote := net.ParseIP(kaArgs[0]) if remote == nil { - return spawnKa, remote, kaExtraArgs + return CIKAArgs{SpawnKa: spawnKa, RemoteIP: nil, SourceIP: nil, Interval: interval} } if len(kaArgs) > 1 { - kaExtraArgs, _ = strconv.ParseInt(kaArgs[1], 10, 32) + sourceIP = net.ParseIP(kaArgs[1]) + } + + if len(kaArgs) > 2 { + interval, _ = strconv.ParseInt(kaArgs[2], 10, 32) } spawnKa = true - return spawnKa, remote, kaExtraArgs + return CIKAArgs{SpawnKa: spawnKa, RemoteIP: remote, SourceIP: sourceIP, Interval: interval} + } // HTTPSProber - Do a https probe for given url diff --git a/options/options.go b/options/options.go index 04b2ac7d..27f63bd3 100644 --- a/options/options.go +++ b/options/options.go @@ -6,7 +6,7 @@ import ( var Opts struct { Bgp bool `short:"b" long:"bgp" description:"Connect and Sync with GoBGP server"` - Ka string `short:"k" long:"ka" description:"KeepAlive/BFD RemoteIP" default:"none"` + Ka string `short:"k" long:"ka" description:"KeepAlive/BFD RemoteIP:SourceIP:Interval" default:"none"` Version bool `short:"v" long:"version" description:"Show loxilb version"` NoAPI bool `short:"a" long:"api" description:"Run Rest API server"` NoNlp bool `short:"n" long:"nonlp" description:"Do not register with nlp"` diff --git a/proto/bfd.go b/proto/bfd.go index 3db14b2f..e6e5f8bd 100644 --- a/proto/bfd.go +++ b/proto/bfd.go @@ -42,6 +42,15 @@ const ( BFDMinSysRXIntervalUs = 200000 ) +type ConfigArgs struct { + RemoteIP string + SourceIP string + Port uint16 + Interval uint32 + Multi uint8 + Instance string +} + type WireRaw struct { Version uint8 Length uint8 @@ -94,37 +103,37 @@ func StructNew(port uint16) *Struct { return bfdStruct } -func (bs *Struct) BFDAddRemote(remoteIP string, port uint16, interval uint32, multi uint8, instance string, cbs Notifer) error { +func (bs *Struct) BFDAddRemote(args ConfigArgs, cbs Notifer) error { bs.BFDMtx.Lock() defer bs.BFDMtx.Unlock() - sess := bs.BFDSessMap[remoteIP] + sess := bs.BFDSessMap[args.RemoteIP] if sess != nil { return errors.New("bfd existing session") } - if interval < BFDMinSysTXIntervalUs || multi == 0 { + if args.Interval < BFDMinSysTXIntervalUs || args.Multi == 0 { return errors.New("bfd malformed args") } sess = new(bfdSession) - sess.Instance = instance + sess.Instance = args.Instance sess.Notify = cbs - err := sess.initialize(remoteIP, port, interval, multi) + err := sess.initialize(args.RemoteIP, args.SourceIP, args.Port, args.Interval, args.Multi) if err != nil { return errors.New("bfd failed to init session") } - bs.BFDSessMap[remoteIP] = sess + bs.BFDSessMap[args.RemoteIP] = sess return nil } -func (bs *Struct) BFDDeleteRemote(remoteIP string, port uint16) error { +func (bs *Struct) BFDDeleteRemote(args ConfigArgs) error { bs.BFDMtx.Lock() defer bs.BFDMtx.Unlock() - sess := bs.BFDSessMap[remoteIP] + sess := bs.BFDSessMap[args.RemoteIP] if sess == nil { return errors.New("no bfd session") } @@ -132,8 +141,6 @@ func (bs *Struct) BFDDeleteRemote(remoteIP string, port uint16) error { sess.destruct() delete(bs.BFDSessMap, sess.RemoteName) - bs.BFDSessMap[remoteIP] = sess - return nil } @@ -318,6 +325,7 @@ func getMyDisc(ip net.IP) net.IP { // check if IPv4 or IPv6 is not nil if ipnet.IP.To4() != nil || ipnet.IP.To16() != nil { if ipnet.Contains(ip) { + tk.LogIt(tk.LogDebug, "bfd mydisc : %s\n", ipnet.IP.String()) return ipnet.IP } if first == nil { @@ -327,10 +335,12 @@ func getMyDisc(ip net.IP) net.IP { } } + tk.LogIt(tk.LogDebug, "bfd mydisc : %s\n", first.String()) + return first } -func (b *bfdSession) initialize(remoteIP string, port uint16, interval uint32, multi uint8) error { +func (b *bfdSession) initialize(remoteIP string, sourceIP string, port uint16, interval uint32, multi uint8) error { var err error b.RemoteName = fmt.Sprintf("%s:%d", remoteIP, port) @@ -339,9 +349,18 @@ func (b *bfdSession) initialize(remoteIP string, port uint16, interval uint32, m return errors.New("address malformed") } - myIP := getMyDisc(ip) + myIP := net.ParseIP(sourceIP) if myIP == nil { - return errors.New("my discriminator not found") + return errors.New("source address malformed") + } + + if myIP.IsUnspecified() { + myIP = getMyDisc(ip) + if myIP == nil { + return errors.New("my discriminator not found") + } + } else { + tk.LogIt(tk.LogDebug, "using bfd bind mydisc : %s\n", myIP.String()) } b.MyDisc = tk.IPtonl(myIP) b.RemDisc = 0 //tk.IPtonl(ip)