diff options
author | ISHIDA Wataru <ishida.wataru@lab.ntt.co.jp> | 2016-08-01 08:11:14 +0000 |
---|---|---|
committer | FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> | 2016-08-02 10:48:58 +0900 |
commit | 1890b4c5ef28fde6cff478a78e1ded3a65badd6b (patch) | |
tree | 332875e27ca4e85c3432c884dd038dc161be7dc3 | |
parent | a46e8b6826fe95ff09278d75474faf7a14b5d8b1 (diff) |
config: support unnumbered bgp peering
from configuration file:
```toml
[[neighbors]]
[[neighbors.afi-safis]]
neighbor-interface = "eth0"
peer-as = 65000
```
Signed-off-by: ISHIDA Wataru <ishida.wataru@lab.ntt.co.jp>
-rw-r--r-- | config/bgp_configs.go | 10 | ||||
-rw-r--r-- | config/default.go | 57 | ||||
-rw-r--r-- | server/server.go | 7 | ||||
-rw-r--r-- | tools/pyang_plugins/gobgp.yang | 12 |
4 files changed, 86 insertions, 0 deletions
diff --git a/config/bgp_configs.go b/config/bgp_configs.go index 44afcb82..1636073c 100644 --- a/config/bgp_configs.go +++ b/config/bgp_configs.go @@ -2477,6 +2477,8 @@ type NeighborState struct { EstablishedCount uint32 `mapstructure:"established-count"` // original -> gobgp:flops Flops uint32 `mapstructure:"flops"` + // original -> gobgp:neighbor-interface + NeighborInterface string `mapstructure:"neighbor-interface"` } func (lhs *NeighborState) Equal(rhs *NeighborState) bool { @@ -2551,6 +2553,9 @@ func (lhs *NeighborState) Equal(rhs *NeighborState) bool { if lhs.Flops != rhs.Flops { return false } + if lhs.NeighborInterface != rhs.NeighborInterface { + return false + } return true } @@ -2583,6 +2588,8 @@ type NeighborConfig struct { // original -> gobgp:admin-down //gobgp:admin-down's original type is boolean AdminDown bool `mapstructure:"admin-down"` + // original -> gobgp:neighbor-interface + NeighborInterface string `mapstructure:"neighbor-interface"` } func (lhs *NeighborConfig) Equal(rhs *NeighborConfig) bool { @@ -2622,6 +2629,9 @@ func (lhs *NeighborConfig) Equal(rhs *NeighborConfig) bool { if lhs.AdminDown != rhs.AdminDown { return false } + if lhs.NeighborInterface != rhs.NeighborInterface { + return false + } return true } 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") diff --git a/server/server.go b/server/server.go index 9820f898..036a94ba 100644 --- a/server/server.go +++ b/server/server.go @@ -1730,6 +1730,13 @@ func (s *BgpServer) AddNeighbor(c *config.Neighbor) (err error) { func (server *BgpServer) deleteNeighbor(c *config.Neighbor, code, subcode uint8) error { addr := c.Config.NeighborAddress + if intf := c.Config.NeighborInterface; intf != "" { + var err error + addr, err = config.GetIPv6LinkLocalNeighborAddress(intf) + if err != nil { + return err + } + } n, y := server.neighborMap[addr] if !y { return fmt.Errorf("Can't delete a peer configuration for %s", addr) diff --git a/tools/pyang_plugins/gobgp.yang b/tools/pyang_plugins/gobgp.yang index ee158866..98d42729 100644 --- a/tools/pyang_plugins/gobgp.yang +++ b/tools/pyang_plugins/gobgp.yang @@ -655,6 +655,18 @@ module gobgp { } + augment "/bgp:bgp/bgp:neighbors/bgp:neighbor/bgp:config" { + leaf neighbor-interface { + type string; + } + } + + augment "/bgp:bgp/bgp:neighbors/bgp:neighbor/bgp:state" { + leaf neighbor-interface { + type string; + } + } + augment "/bgp:bgp/bgp:neighbors/bgp:neighbor/bgp:transport/bgp:config" { leaf remote-port { type inet:port-number; |