From 10e23b5642bdd02137043dfb1c14f351fcc35894 Mon Sep 17 00:00:00 2001 From: Martin/Geno Date: Sat, 18 May 2019 23:33:13 +0200 Subject: [PATCH] babel at neighbours --- respond/daemon/babel.go | 77 ++++++++++++++++++++++++++++++++++++ respond/daemon/config.go | 7 +++- respond/daemon/main.go | 4 ++ respond/daemon/neighbours.go | 53 +++++++++++++++++++++++++ 4 files changed, 139 insertions(+), 2 deletions(-) create mode 100644 respond/daemon/babel.go diff --git a/respond/daemon/babel.go b/respond/daemon/babel.go new file mode 100644 index 0000000..4a19094 --- /dev/null +++ b/respond/daemon/babel.go @@ -0,0 +1,77 @@ +package respondd + +import ( + "bufio" + "fmt" + "io" + "net" + "time" + + "github.com/Vivena/babelweb2/parser" + "github.com/bdlm/log" +) + +func (d *Daemon) babelConnect() { + var conn net.Conn + var err error + + for { + log.Debug("Trying", d.Babel) + for { + conn, err = net.Dial("tcp6", d.Babel) + if err != nil { + log.Println(err) + time.Sleep(time.Second * 5) + } else { + break + } + } + log.Info("Connected to ", d.Babel) + closeConn := func() { + conn.Close() + log.Infof("Connection to %v closed\n", d.Babel) + } + defer closeConn() + fmt.Fprintf(conn, "monitor\n") + r := bufio.NewReader(conn) + s := parser.NewScanner(r) + desc := parser.NewBabelDesc() + err = desc.Fill(s) + if err == io.EOF { + log.Warnf("Something wrong with %v:\n\tcouldn't get router id.\n", d.Babel) + } else if err != nil { + // Don't you even dare to reconnect to this unholy node! + log.Warnf("Oh, boy! %v is doomed:\n\t%v.\t", d.Babel, err) + return + } else { + d.babelData = desc + err := d.babelDescListen(s) + if err != nil { + log.Warnf("Babel listen stopped: %s", err) + } + d.babelData = nil + } + closeConn() + } +} + +func (d *Daemon) babelDescListen(s *parser.Scanner) error { + for { + upd, err := d.babelData.ParseAction(s) + if err != nil && err != io.EOF && err.Error() != "EOL" { + return err + } + if err == io.EOF { + break + } + //TODO maybe keep upd.action != none + if !(d.babelData.CheckUpdate(upd)) { + continue + } + err = d.babelData.Update(upd) + if err != nil { + return err + } + } + return nil +} diff --git a/respond/daemon/config.go b/respond/daemon/config.go index 3948fb9..01d6a0c 100644 --- a/respond/daemon/config.go +++ b/respond/daemon/config.go @@ -6,6 +6,8 @@ import ( "github.com/FreifunkBremen/yanic/data" "github.com/FreifunkBremen/yanic/lib/duration" + + babelParser "github.com/Vivena/babelweb2/parser" ) func trim(s string) string { @@ -20,8 +22,9 @@ type Daemon struct { Port int `toml:"port"` } `toml:"listen"` - Batman []string `toml:"batman"` - Babel string `toml:"babel"` + Batman []string `toml:"batman"` + Babel string `toml:"babel"` + babelData *babelParser.BabelDesc `toml:"-"` dataByInterface map[string]*data.ResponseData diff --git a/respond/daemon/main.go b/respond/daemon/main.go index 5641a63..ac25176 100644 --- a/respond/daemon/main.go +++ b/respond/daemon/main.go @@ -19,6 +19,10 @@ func (d *Daemon) Start() { d.updateData() go d.updateWorker() + if d.Babel != "" { + go d.babelConnect() + } + for _, listen := range d.Listen { var socket *net.UDPConn var err error diff --git a/respond/daemon/neighbours.go b/respond/daemon/neighbours.go index 87a96c9..1b1a91c 100644 --- a/respond/daemon/neighbours.go +++ b/respond/daemon/neighbours.go @@ -1,6 +1,11 @@ package respondd import ( + "errors" + + "github.com/Vivena/babelweb2/parser" + "github.com/bdlm/log" + "github.com/FreifunkBremen/yanic/data" ) @@ -20,4 +25,52 @@ func (d *Daemon) updateNeighbours(iface string, resp *data.ResponseData) { resp.Neighbours.Batadv[bfaceAddr] = n } } + + if d.babelData == nil { + return + } + + log.Warn(d.babelData.String()) + + resp.Neighbours.Babel = make(map[string]data.BabelNeighbours) + d.babelData.Iter(func(bu parser.BabelUpdate) error { + sbu := bu.ToSUpdate() + if sbu.TableId != "interface" { + return nil + } + if sbu.EntryData["up"].(bool) { + addr := sbu.EntryData["ipv6"].(string) + resp.Neighbours.Babel[string(sbu.EntryId)] = data.BabelNeighbours{ + Protocol: "babel", + LinkLocalAddress: addr, + Neighbours: make(map[string]data.BabelLink), + } + } + return nil + }) + + d.babelData.Iter(func(bu parser.BabelUpdate) error { + sbu := bu.ToSUpdate() + if sbu.TableId != "neighbour" { + return nil + } + ifname, ok := sbu.EntryData["if"].(string) + if !ok { + return errors.New("neighbour without if") + } + addr := sbu.EntryData["address"].(string) + if !ok { + return errors.New("neighbour without address") + } + if bIfname, ok := resp.Neighbours.Babel[ifname]; ok { + link := data.BabelLink{ + RXCost: int(sbu.EntryData["rxcost"].(uint64)), + TXCost: int(sbu.EntryData["txcost"].(uint64)), + Cost: int(sbu.EntryData["cost"].(uint64)), + } + bIfname.Neighbours[addr] = link + return nil + } + return errors.New("ifname not found during parsing") + }) }