Skip to content

Commit

Permalink
support neighbor belongs to VRF
Browse files Browse the repository at this point in the history
$ gobgp vrf add red rd 100:100 rt both 100:100
$ gobgp neighbor add 10.0.0.1 as 2 vrf red
$ gobgp vrf red neighbor
Peer     AS  Up/Down State       |#Advertised Received Accepted
10.0.0.1 2   never   Active      |          0        0        0

Signed-off-by: Wataru Ishida <[email protected]>
  • Loading branch information
Wataru Ishida authored and fujita committed Nov 4, 2016
1 parent 97bc9dd commit a178321
Show file tree
Hide file tree
Showing 21 changed files with 774 additions and 400 deletions.
5 changes: 5 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,11 @@ matrix:
sudo: required
services:
- docker
- env:
- TEST=vrf_neighbor_test.py
sudo: required
services:
- docker

cache:
pip: true
Expand Down
699 changes: 349 additions & 350 deletions api/gobgp.pb.go

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions api/gobgp.proto
Original file line number Diff line number Diff line change
Expand Up @@ -569,6 +569,7 @@ message PeerConf {
repeated PrefixLimit prefix_limits = 14;
string local_address = 15;
string neighbor_interface = 16;
string vrf = 17;
}

message EbgpMultihop {
Expand Down
2 changes: 2 additions & 0 deletions api/grpc_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ func (s *Server) GetNeighbor(ctx context.Context, arg *GetNeighborRequest) (*Get
PrefixLimits: prefixLimits,
LocalAddress: localAddress,
NeighborInterface: pconf.Config.NeighborInterface,
Vrf: pconf.Config.Vrf,
},
Info: &PeerState{
BgpState: bgp.FSMState(s.SessionState.ToInt()).String(),
Expand Down Expand Up @@ -777,6 +778,7 @@ func (s *Server) AddNeighbor(ctx context.Context, arg *AddNeighborRequest) (*Add
pconf.Config.PeerGroup = a.Conf.PeerGroup
pconf.Config.NeighborAddress = a.Conf.NeighborAddress
pconf.Config.NeighborInterface = a.Conf.NeighborInterface
pconf.Config.Vrf = a.Conf.Vrf
}
if a.Timers != nil && a.Timers.Config != nil {
pconf.Timers.Config.ConnectRetry = float64(a.Timers.Config.ConnectRetry)
Expand Down
10 changes: 10 additions & 0 deletions config/bgp_configs.go
Original file line number Diff line number Diff line change
Expand Up @@ -2522,6 +2522,8 @@ type NeighborState struct {
Flops uint32 `mapstructure:"flops"`
// original -> gobgp:neighbor-interface
NeighborInterface string `mapstructure:"neighbor-interface"`
// original -> gobgp:vrf
Vrf string `mapstructure:"vrf"`
// original -> gobgp:remote-router-id
RemoteRouterId string `mapstructure:"remote-router-id"`
}
Expand Down Expand Up @@ -2601,6 +2603,9 @@ func (lhs *NeighborState) Equal(rhs *NeighborState) bool {
if lhs.NeighborInterface != rhs.NeighborInterface {
return false
}
if lhs.Vrf != rhs.Vrf {
return false
}
if lhs.RemoteRouterId != rhs.RemoteRouterId {
return false
}
Expand Down Expand Up @@ -2638,6 +2643,8 @@ type NeighborConfig struct {
AdminDown bool `mapstructure:"admin-down"`
// original -> gobgp:neighbor-interface
NeighborInterface string `mapstructure:"neighbor-interface"`
// original -> gobgp:vrf
Vrf string `mapstructure:"vrf"`
}

func (lhs *NeighborConfig) Equal(rhs *NeighborConfig) bool {
Expand Down Expand Up @@ -2680,6 +2687,9 @@ func (lhs *NeighborConfig) Equal(rhs *NeighborConfig) bool {
if lhs.NeighborInterface != rhs.NeighborInterface {
return false
}
if lhs.Vrf != rhs.Vrf {
return false
}
return true
}

Expand Down
2 changes: 2 additions & 0 deletions gobgp/cmd/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,7 @@ type PeerConf struct {
LocalIp string `json:"local_ip,omitempty"`
Interface string `json:"interface,omitempty"`
Description string `json:"description,omitempty"`
VRF string `json:"vrf,omitempty"`
}

type Peer struct {
Expand Down Expand Up @@ -209,6 +210,7 @@ func ApiStruct2Peer(p *gobgpapi.Peer) *Peer {
LocalIp: localIp.String(),
Interface: p.Conf.NeighborInterface,
Description: p.Conf.Description,
VRF: p.Conf.Vrf,
}
return &Peer{
Conf: conf,
Expand Down
23 changes: 14 additions & 9 deletions gobgp/cmd/neighbor.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ import (
"time"
)

func getNeighbors() (peers, error) {
func getNeighbors(vrf string) (peers, error) {
r, e := client.GetNeighbor(context.Background(), &api.GetNeighborRequest{})
if e != nil {
fmt.Println(e)
Expand All @@ -51,13 +51,16 @@ func getNeighbors() (peers, error) {
}
}
}
if vrf != "" && p.Conf.Vrf != vrf {
continue
}
m = append(m, ApiStruct2Peer(p))
}
return m, nil
}

func getNeighbor(name string) (*Peer, error) {
l, e := getNeighbors()
l, e := getNeighbors("")
if e != nil {
return nil, e
}
Expand All @@ -69,8 +72,8 @@ func getNeighbor(name string) (*Peer, error) {
return nil, fmt.Errorf("Neighbor %v doesn't exist.", name)
}

func showNeighbors() error {
m, err := getNeighbors()
func showNeighbors(vrf string) error {
m, err := getNeighbors(vrf)
if err != nil {
return err
}
Expand Down Expand Up @@ -536,7 +539,6 @@ func showNeighborRib(r string, name string, args []string) error {
resource = api.Resource_ADJ_OUT
case CMD_VRF:
def = bgp.RF_IPv4_UC
showLabel = true
resource = api.Resource_VRF
}
rf, err := checkAddressFamily(def)
Expand Down Expand Up @@ -801,13 +803,13 @@ func modNeighborPolicy(remoteIP, policyType, cmdType string, args []string) erro
}

func modNeighbor(cmdType string, args []string) error {
m := extractReserved(args, []string{"interface", "as"})
m := extractReserved(args, []string{"interface", "as", "vrf"})
usage := fmt.Sprintf("usage: gobgp neighbor %s [<neighbor-address>| interface <neighbor-interface>]", cmdType)
if cmdType == CMD_ADD {
usage += " as <VALUE>"
usage += " as <VALUE> [ vrf <vrf-name> ]"
}

if len(m[""]) < 1 && len(m["interface"]) < 1 {
if (len(m[""]) != 1 && len(m["interface"]) != 1) || len(m["as"]) > 1 || len(m["vrf"]) > 1 {
return fmt.Errorf("%s", usage)
}
unnumbered := len(m["interface"]) > 0
Expand All @@ -828,6 +830,9 @@ func modNeighbor(cmdType string, args []string) error {
} else {
peer.Conf.NeighborAddress = m[""][0]
}
if len(m["vrf"]) == 1 {
peer.Conf.Vrf = m["vrf"][0]
}
return peer
}
var err error
Expand Down Expand Up @@ -965,7 +970,7 @@ func NewNeighborCmd() *cobra.Command {
Run: func(cmd *cobra.Command, args []string) {
var err error
if len(args) == 0 {
err = showNeighbors()
err = showNeighbors("")
} else if len(args) == 1 {
err = showNeighbor(args)
} else {
Expand Down
35 changes: 33 additions & 2 deletions gobgp/cmd/vrf.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ func modVrf(typ string, args []string) error {
case CMD_ADD:
a := extractReserved(args, []string{"rd", "rt", "id"})
if len(a[""]) != 1 || len(a["rd"]) != 1 || len(a["rt"]) < 2 || len(a["id"]) > 1 {
return fmt.Errorf("Usage: gobgp vrf add <vrf name> id <id> rd <rd> rt { import | export | both } <rt>...")
return fmt.Errorf("Usage: gobgp vrf add <vrf name> [ id <id> ] rd <rd> rt { import | export | both } <rt>...")
}
name := a[""][0]
rd, err := bgp.ParseRouteDistinguisher(a["rd"][0])
Expand Down Expand Up @@ -196,8 +196,39 @@ func NewVrfCmd() *cobra.Command {
ribCmd.AddCommand(cmd)
}

neighborCmd := &cobra.Command{
Use: CMD_NEIGHBOR,
Run: func(cmd *cobra.Command, args []string) {
var err error
if len(args) == 1 {
var vs vrfs
vs, err = getVrfs()
if err != nil {
exitWithError(err)
}
found := false
for _, v := range vs {
if v.Name == args[0] {
found = true
break
}
}
if !found {
err = fmt.Errorf("vrf %s not found", args[0])
} else {
err = showNeighbors(args[0])
}
} else {
err = fmt.Errorf("usage: gobgp vrf <vrf-name> neighbor")
}
if err != nil {
exitWithError(err)
}
},
}

vrfCmdImpl := &cobra.Command{}
vrfCmdImpl.AddCommand(ribCmd)
vrfCmdImpl.AddCommand(ribCmd, neighborCmd)

vrfCmd := &cobra.Command{
Use: CMD_VRF,
Expand Down
13 changes: 10 additions & 3 deletions gobgpd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -265,15 +265,22 @@ func main() {

for i, p := range added {
log.Infof("Peer %v is added", p.Config.NeighborAddress)
bgpServer.AddNeighbor(&added[i])
if err := bgpServer.AddNeighbor(&added[i]); err != nil {
log.Warn(err)
}
}
for i, p := range deleted {
log.Infof("Peer %v is deleted", p.Config.NeighborAddress)
bgpServer.DeleteNeighbor(&deleted[i])
if err := bgpServer.DeleteNeighbor(&deleted[i]); err != nil {
log.Warn(err)
}
}
for i, p := range updated {
log.Infof("Peer %v is updated", p.Config.NeighborAddress)
u, _ := bgpServer.UpdateNeighbor(&updated[i])
u, err := bgpServer.UpdateNeighbor(&updated[i])
if err != nil {
log.Warn(err)
}
updatePolicy = updatePolicy || u
}

Expand Down
6 changes: 5 additions & 1 deletion packet/bgp/bgp.go
Original file line number Diff line number Diff line change
Expand Up @@ -1395,8 +1395,12 @@ func (l *LabeledVPNIPAddrPrefix) SAFI() uint8 {
}

func (l *LabeledVPNIPAddrPrefix) String() string {
return fmt.Sprintf("%s:%s", l.RD, l.IPPrefix())
}

func (l *LabeledVPNIPAddrPrefix) IPPrefix() string {
masklen := l.IPAddrPrefixDefault.Length - uint8(8*(l.Labels.Len()+l.RD.Len()))
return fmt.Sprintf("%s:%s/%d", l.RD, l.IPAddrPrefixDefault.Prefix, masklen)
return fmt.Sprintf("%s/%d", l.IPAddrPrefixDefault.Prefix, masklen)
}

func (l *LabeledVPNIPAddrPrefix) MarshalJSON() ([]byte, error) {
Expand Down
16 changes: 16 additions & 0 deletions server/peer.go
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,22 @@ func (peer *Peer) filterpath(path *table.Path, withdrawals []*table.Path) *table
}
}
}

// only allow vpnv4 and vpnv6 paths to be advertised to VRFed neighbors.
// also check we can import this path using table.CanImportToVrf()
// if we can, make it local path by calling (*Path).ToLocal()
if path != nil && peer.fsm.pConf.Config.Vrf != "" {
if f := path.GetRouteFamily(); f != bgp.RF_IPv4_VPN && f != bgp.RF_IPv6_VPN {
return nil
}
vrf := peer.localRib.Vrfs[peer.fsm.pConf.Config.Vrf]
if table.CanImportToVrf(vrf, path) {
path = path.ToLocal()
} else {
return nil
}
}

if path = filterpath(peer, path, withdrawals); path == nil {
return nil
}
Expand Down
35 changes: 33 additions & 2 deletions server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -816,8 +816,13 @@ func (server *BgpServer) handleFSMMessage(peer *Peer, e *FsmMsg) {
}

if len(pathList) > 0 {
var altered []*table.Path
altered = server.propagateUpdate(peer, pathList)
if v := peer.fsm.pConf.Config.Vrf; v != "" {
vrf := server.globalRib.Vrfs[v]
for idx, path := range pathList {
pathList[idx] = path.ToGlobal(vrf)
}
}
altered := server.propagateUpdate(peer, pathList)
if server.isWatched(WATCH_EVENT_TYPE_POST_UPDATE) {
_, y := peer.fsm.capMap[bgp.BGP_CAP_FOUR_OCTET_AS_NUMBER]
l, _ := peer.fsm.LocalHostPort()
Expand Down Expand Up @@ -1288,6 +1293,13 @@ func (s *BgpServer) DeleteVrf(name string) (err error) {
s.mgmtCh <- func() {
defer close(ch)

for _, n := range s.neighborMap {
if n.fsm.pConf.Config.Vrf == name {
err = fmt.Errorf("failed to delete VRF %s: neighbor %s is in use", name, n.ID())
return
}
}

pathList, err := s.globalRib.DeleteVrf(name)
if err == nil && len(pathList) > 0 {
s.propagateUpdate(nil, pathList)
Expand Down Expand Up @@ -1644,6 +1656,25 @@ func (server *BgpServer) addNeighbor(c *config.Neighbor) error {
return fmt.Errorf("Can't overwrite the existing peer: %s", addr)
}

if vrf := c.Config.Vrf; vrf != "" {
if c.RouteServer.Config.RouteServerClient {
return fmt.Errorf("route server client can't be enslaved to VRF")
}
if c.RouteReflector.Config.RouteReflectorClient {
return fmt.Errorf("route reflector client can't be enslaved to VRF")
}
families, _ := config.AfiSafis(c.AfiSafis).ToRfList()
for _, f := range families {
if f != bgp.RF_IPv4_UC && f != bgp.RF_IPv6_UC {
return fmt.Errorf("%s is not supported for VRF enslaved neighbor", f)
}
}
_, y := server.globalRib.Vrfs[vrf]
if !y {
return fmt.Errorf("VRF not found: %s", vrf)
}
}

if server.bgpConfig.Global.Config.Port > 0 {
for _, l := range server.Listeners(addr) {
if err := SetTcpMD5SigSockopts(l, addr, c.Config.AuthPassword); err != nil {
Expand Down
2 changes: 1 addition & 1 deletion table/destination.go
Original file line number Diff line number Diff line change
Expand Up @@ -906,7 +906,7 @@ func (old *Destination) Select(option ...DestinationSelectOption) *Destination {
ps := make([]*Path, 0, len(paths))
for _, p := range paths {
if CanImportToVrf(vrf, p) {
ps = append(ps, p)
ps = append(ps, p.ToLocal())
}
}
paths = ps
Expand Down
Loading

0 comments on commit a178321

Please sign in to comment.