diff options
Diffstat (limited to 'config/default.go')
-rw-r--r-- | config/default.go | 57 |
1 files changed, 57 insertions, 0 deletions
diff --git a/config/default.go b/config/default.go index ef3da7f1..e4cfeb4c 100644 --- a/config/default.go +++ b/config/default.go @@ -6,6 +6,7 @@ import ( "github.com/osrg/gobgp/packet/bmp" "github.com/osrg/gobgp/packet/rtr" "github.com/spf13/viper" + "github.com/vishvananda/netlink" "net" ) @@ -71,6 +72,54 @@ func getIPv6LinkLocalAddress(ifname string) (string, error) { return "", fmt.Errorf("no ipv6 link local address for %s", ifname) } +func isLocalLinkLocalAddress(ifindex int, addr net.IP) (bool, error) { + ifi, err := net.InterfaceByIndex(ifindex) + if err != nil { + return false, err + } + addrs, err := ifi.Addrs() + if err != nil { + return false, err + } + for _, a := range addrs { + if ip, _, _ := net.ParseCIDR(a.String()); addr.Equal(ip) { + return true, nil + } + } + return false, nil +} + +func GetIPv6LinkLocalNeighborAddress(ifname string) (string, error) { + ifi, err := net.InterfaceByName(ifname) + if err != nil { + return "", err + } + neighs, err := netlink.NeighList(ifi.Index, netlink.FAMILY_V6) + if err != nil { + return "", err + } + cnt := 0 + var addr net.IP + for _, neigh := range neighs { + local, err := isLocalLinkLocalAddress(ifi.Index, neigh.IP) + if err != nil { + return "", err + } + if neigh.IP.IsLinkLocalUnicast() && !local { + addr = neigh.IP + cnt += 1 + } + } + + if cnt == 0 { + return "", fmt.Errorf("no ipv6 link-local neighbor found") + } else if cnt > 1 { + return "", fmt.Errorf("found %d link-local neighbors. only support p2p link", cnt) + } + + return fmt.Sprintf("%s%%%s", addr, ifname), nil +} + func SetDefaultNeighborConfigValues(n *Neighbor, asn uint32) error { return setDefaultNeighborConfigValuesWithViper(nil, n, asn) } @@ -103,6 +152,14 @@ func setDefaultNeighborConfigValuesWithViper(v *viper.Viper, n *Neighbor, asn ui n.Timers.Config.IdleHoldTimeAfterReset = float64(DEFAULT_IDLE_HOLDTIME_AFTER_RESET) } + if n.Config.NeighborInterface != "" { + addr, err := GetIPv6LinkLocalNeighborAddress(n.Config.NeighborInterface) + if err != nil { + return err + } + n.Config.NeighborAddress = addr + } + if n.Transport.Config.LocalAddress == "" { if n.Config.NeighborAddress == "" { return fmt.Errorf("no neighbor address/interface specified") |