summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorIWASE Yusuke <iwase.yusuke0@gmail.com>2018-04-27 11:28:32 +0900
committerFUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>2018-05-10 21:12:30 +0900
commit32f7faa8e7f83c20e50a37e44ba01a498939f574 (patch)
tree014b7755fb5cd873f2ea7bfd9ece4c9f846475ad
parent0f88373949e2eed7a9dbcd1ebac64d76e54f6d40 (diff)
config: Enable to configure VRF via config file
This patch enables to configure VRF tables by using config file. This feature is useful when using VRF-Neighbor feature. Example of Usage: ```toml [[vrfs]] [vrfs.config] name = "vrf1" id = 1 rd = "65000:100" both-rt-list = ["65000:100"] ``` Signed-off-by: IWASE Yusuke <iwase.yusuke0@gmail.com>
-rw-r--r--config/bgp_configs.go124
-rw-r--r--config/default.go76
-rw-r--r--config/serve.go6
-rw-r--r--docs/sources/configuration.md12
-rw-r--r--gobgpd/main.go25
-rw-r--r--tools/pyang_plugins/gobgp.yang93
6 files changed, 331 insertions, 5 deletions
diff --git a/config/bgp_configs.go b/config/bgp_configs.go
index 402bff40..062ef8f7 100644
--- a/config/bgp_configs.go
+++ b/config/bgp_configs.go
@@ -1250,6 +1250,112 @@ func (lhs *Mrt) Equal(rhs *Mrt) bool {
}
// struct for container gobgp:state.
+// Configured states of VRF.
+type VrfState struct {
+ // original -> gobgp:name
+ // Unique name among all VRF instances.
+ Name string `mapstructure:"name" json:"name,omitempty"`
+ // original -> gobgp:id
+ // Unique identifier among all VRF instances.
+ Id uint32 `mapstructure:"id" json:"id,omitempty"`
+ // original -> gobgp:rd
+ // Route Distinguisher for this VRF.
+ Rd string `mapstructure:"rd" json:"rd,omitempty"`
+ // original -> gobgp:import-rt
+ // List of import Route Targets for this VRF.
+ ImportRtList []string `mapstructure:"import-rt-list" json:"import-rt-list,omitempty"`
+ // original -> gobgp:export-rt
+ // List of export Route Targets for this VRF.
+ ExportRtList []string `mapstructure:"export-rt-list" json:"export-rt-list,omitempty"`
+}
+
+// struct for container gobgp:config.
+// Configuration parameters for VRF.
+type VrfConfig struct {
+ // original -> gobgp:name
+ // Unique name among all VRF instances.
+ Name string `mapstructure:"name" json:"name,omitempty"`
+ // original -> gobgp:id
+ // Unique identifier among all VRF instances.
+ Id uint32 `mapstructure:"id" json:"id,omitempty"`
+ // original -> gobgp:rd
+ // Route Distinguisher for this VRF.
+ Rd string `mapstructure:"rd" json:"rd,omitempty"`
+ // original -> gobgp:import-rt
+ // List of import Route Targets for this VRF.
+ ImportRtList []string `mapstructure:"import-rt-list" json:"import-rt-list,omitempty"`
+ // original -> gobgp:export-rt
+ // List of export Route Targets for this VRF.
+ ExportRtList []string `mapstructure:"export-rt-list" json:"export-rt-list,omitempty"`
+ // original -> gobgp:both-rt
+ // List of both import and export Route Targets for this VRF. Each
+ // configuration for import and export Route Targets will be preferred.
+ BothRtList []string `mapstructure:"both-rt-list" json:"both-rt-list,omitempty"`
+}
+
+func (lhs *VrfConfig) Equal(rhs *VrfConfig) bool {
+ if lhs == nil || rhs == nil {
+ return false
+ }
+ if lhs.Name != rhs.Name {
+ return false
+ }
+ if lhs.Id != rhs.Id {
+ return false
+ }
+ if lhs.Rd != rhs.Rd {
+ return false
+ }
+ if len(lhs.ImportRtList) != len(rhs.ImportRtList) {
+ return false
+ }
+ for idx, l := range lhs.ImportRtList {
+ if l != rhs.ImportRtList[idx] {
+ return false
+ }
+ }
+ if len(lhs.ExportRtList) != len(rhs.ExportRtList) {
+ return false
+ }
+ for idx, l := range lhs.ExportRtList {
+ if l != rhs.ExportRtList[idx] {
+ return false
+ }
+ }
+ if len(lhs.BothRtList) != len(rhs.BothRtList) {
+ return false
+ }
+ for idx, l := range lhs.BothRtList {
+ if l != rhs.BothRtList[idx] {
+ return false
+ }
+ }
+ return true
+}
+
+// struct for container gobgp:vrf.
+// VRF instance configurations on the local system.
+type Vrf struct {
+ // original -> gobgp:name
+ // original -> gobgp:vrf-config
+ // Configuration parameters for VRF.
+ Config VrfConfig `mapstructure:"config" json:"config,omitempty"`
+ // original -> gobgp:vrf-state
+ // Configured states of VRF.
+ State VrfState `mapstructure:"state" json:"state,omitempty"`
+}
+
+func (lhs *Vrf) Equal(rhs *Vrf) bool {
+ if lhs == nil || rhs == nil {
+ return false
+ }
+ if !lhs.Config.Equal(&(rhs.Config)) {
+ return false
+ }
+ return true
+}
+
+// struct for container gobgp:state.
// Configuration parameters relating to BMP server.
type BmpServerState struct {
// original -> gobgp:address
@@ -4785,6 +4891,8 @@ type Bgp struct {
RpkiServers []RpkiServer `mapstructure:"rpki-servers" json:"rpki-servers,omitempty"`
// original -> gobgp:bmp-servers
BmpServers []BmpServer `mapstructure:"bmp-servers" json:"bmp-servers,omitempty"`
+ // original -> gobgp:vrfs
+ Vrfs []Vrf `mapstructure:"vrfs" json:"vrfs,omitempty"`
// original -> gobgp:mrt-dump
MrtDump []Mrt `mapstructure:"mrt-dump" json:"mrt-dump,omitempty"`
// original -> gobgp:zebra
@@ -4866,6 +4974,22 @@ func (lhs *Bgp) Equal(rhs *Bgp) bool {
}
}
}
+ if len(lhs.Vrfs) != len(rhs.Vrfs) {
+ return false
+ }
+ {
+ lmap := make(map[string]*Vrf)
+ for i, l := range lhs.Vrfs {
+ lmap[mapkey(i, string(l.Config.Name))] = &lhs.Vrfs[i]
+ }
+ for i, r := range rhs.Vrfs {
+ if l, y := lmap[mapkey(i, string(r.Config.Name))]; !y {
+ return false
+ } else if !r.Equal(l) {
+ return false
+ }
+ }
+ }
if len(lhs.MrtDump) != len(rhs.MrtDump) {
return false
}
diff --git a/config/default.go b/config/default.go
index 5c472909..f5bf809e 100644
--- a/config/default.go
+++ b/config/default.go
@@ -2,13 +2,15 @@ package config
import (
"fmt"
+ "math"
"net"
"reflect"
+ "github.com/spf13/viper"
+
"github.com/osrg/gobgp/packet/bgp"
"github.com/osrg/gobgp/packet/bmp"
"github.com/osrg/gobgp/packet/rtr"
- "github.com/spf13/viper"
)
const (
@@ -265,6 +267,43 @@ func SetDefaultGlobalConfigValues(g *Global) error {
return nil
}
+func setDefaultVrfConfigValues(v *Vrf) error {
+ if v == nil {
+ return fmt.Errorf("cannot set default values for nil vrf config")
+ }
+
+ if v.Config.Name == "" {
+ return fmt.Errorf("specify vrf name")
+ }
+
+ _, err := bgp.ParseRouteDistinguisher(v.Config.Rd)
+ if err != nil {
+ return fmt.Errorf("invalid rd for vrf %s: %s", v.Config.Name, v.Config.Rd)
+ }
+
+ if len(v.Config.ImportRtList) == 0 {
+ v.Config.ImportRtList = v.Config.BothRtList
+ }
+ for _, rtString := range v.Config.ImportRtList {
+ _, err := bgp.ParseRouteTarget(rtString)
+ if err != nil {
+ return fmt.Errorf("invalid import rt for vrf %s: %s", v.Config.Name, rtString)
+ }
+ }
+
+ if len(v.Config.ExportRtList) == 0 {
+ v.Config.ExportRtList = v.Config.BothRtList
+ }
+ for _, rtString := range v.Config.ExportRtList {
+ _, err := bgp.ParseRouteTarget(rtString)
+ if err != nil {
+ return fmt.Errorf("invalid export rt for vrf %s: %s", v.Config.Name, rtString)
+ }
+ }
+
+ return nil
+}
+
func SetDefaultConfigValues(b *BgpConfigSet) error {
return setDefaultConfigValuesWithViper(nil, b)
}
@@ -309,6 +348,41 @@ func setDefaultConfigValuesWithViper(v *viper.Viper, b *BgpConfigSet) error {
b.BmpServers[idx] = server
}
+ vrfNames := make(map[string]struct{})
+ vrfIDs := make(map[uint32]struct{})
+ for idx, vrf := range b.Vrfs {
+ if err := setDefaultVrfConfigValues(&vrf); err != nil {
+ return err
+ }
+
+ if _, ok := vrfNames[vrf.Config.Name]; ok {
+ return fmt.Errorf("duplicated vrf name: %s", vrf.Config.Name)
+ }
+ vrfNames[vrf.Config.Name] = struct{}{}
+
+ if vrf.Config.Id != 0 {
+ if _, ok := vrfIDs[vrf.Config.Id]; ok {
+ return fmt.Errorf("duplicated vrf id: %d", vrf.Config.Id)
+ }
+ vrfIDs[vrf.Config.Id] = struct{}{}
+ }
+
+ b.Vrfs[idx] = vrf
+ }
+ // Auto assign VRF identifier
+ for idx, vrf := range b.Vrfs {
+ if vrf.Config.Id == 0 {
+ for id := uint32(1); id < math.MaxUint32; id++ {
+ if _, ok := vrfIDs[id]; !ok {
+ vrf.Config.Id = id
+ vrfIDs[id] = struct{}{}
+ break
+ }
+ }
+ }
+ b.Vrfs[idx] = vrf
+ }
+
if b.Zebra.Config.Url == "" {
b.Zebra.Config.Url = "unix:/var/run/quagga/zserv.api"
}
diff --git a/config/serve.go b/config/serve.go
index 45c70ea9..7705b1f8 100644
--- a/config/serve.go
+++ b/config/serve.go
@@ -1,11 +1,12 @@
package config
import (
- log "github.com/sirupsen/logrus"
- "github.com/spf13/viper"
"os"
"os/signal"
"syscall"
+
+ log "github.com/sirupsen/logrus"
+ "github.com/spf13/viper"
)
type BgpConfigSet struct {
@@ -14,6 +15,7 @@ type BgpConfigSet struct {
PeerGroups []PeerGroup `mapstructure:"peer-groups"`
RpkiServers []RpkiServer `mapstructure:"rpki-servers"`
BmpServers []BmpServer `mapstructure:"bmp-servers"`
+ Vrfs []Vrf `mapstructure:"vrfs"`
MrtDump []Mrt `mapstructure:"mrt-dump"`
Zebra Zebra `mapstructure:"zebra"`
Collector Collector `mapstructure:"collector"`
diff --git a/docs/sources/configuration.md b/docs/sources/configuration.md
index 15a86761..9bef5ec3 100644
--- a/docs/sources/configuration.md
+++ b/docs/sources/configuration.md
@@ -30,6 +30,18 @@
route-monitoring-policy = "pre-policy"
statistics-timeout = 3600
+[[vrfs]]
+ [vrfs.config]
+ name = "vrf1"
+ # If id is omitted, automatically assigned.
+ id = 1
+ rd = "65000:100"
+ # Each configuration for import and export RTs;
+ # import-rt-list
+ # export-rt-list
+ # are preferred than both-rt-list.
+ both-rt-list = ["65000:100"]
+
[[mrt-dump]]
[mrt-dump.config]
dump-type = "updates"
diff --git a/gobgpd/main.go b/gobgpd/main.go
index fdfb8cca..9b504441 100644
--- a/gobgpd/main.go
+++ b/gobgpd/main.go
@@ -188,6 +188,31 @@ func main() {
log.Fatalf("failed to set bmp config: %s", err)
}
}
+ for _, vrf := range newConfig.Vrfs {
+ rd, err := bgp.ParseRouteDistinguisher(vrf.Config.Rd)
+ if err != nil {
+ log.Fatalf("failed to load vrf rd config: %s", err)
+ }
+ importRtList := make([]bgp.ExtendedCommunityInterface, 0, len(vrf.Config.ImportRtList))
+ for _, rtString := range vrf.Config.ImportRtList {
+ rt, err := bgp.ParseRouteTarget(rtString)
+ if err != nil {
+ log.Fatalf("failed to load vrf import rt config: %s", err)
+ }
+ importRtList = append(importRtList, rt)
+ }
+ exportRtList := make([]bgp.ExtendedCommunityInterface, 0, len(vrf.Config.ExportRtList))
+ for _, rtString := range vrf.Config.ExportRtList {
+ rt, err := bgp.ParseRouteTarget(rtString)
+ if err != nil {
+ log.Fatalf("failed to load vrf export rt config: %s", err)
+ }
+ exportRtList = append(exportRtList, rt)
+ }
+ if err := bgpServer.AddVrf(vrf.Config.Name, vrf.Config.Id, rd, importRtList, exportRtList); err != nil {
+ log.Fatalf("failed to set vrf config: %s", err)
+ }
+ }
for i, _ := range newConfig.MrtDump {
if len(newConfig.MrtDump[i].Config.FileName) == 0 {
continue
diff --git a/tools/pyang_plugins/gobgp.yang b/tools/pyang_plugins/gobgp.yang
index 9022d680..053ef0a0 100644
--- a/tools/pyang_plugins/gobgp.yang
+++ b/tools/pyang_plugins/gobgp.yang
@@ -618,6 +618,90 @@ module gobgp {
}
}
}
+ grouping gobgp-vrf-common {
+ description
+ "Common parameters for VRF configuration and state.";
+
+ leaf name {
+ description
+ "Unique name among all VRF instances.";
+ type string;
+ }
+
+ leaf id {
+ description
+ "Unique identifier among all VRF instances.";
+ type uint32;
+ }
+
+ leaf rd {
+ description
+ "Route Distinguisher for this VRF.";
+ type string;
+ }
+
+ leaf-list import-rt {
+ description
+ "List of import Route Targets for this VRF.";
+ type string;
+ }
+
+ leaf-list export-rt {
+ description
+ "List of export Route Targets for this VRF.";
+ type string;
+ }
+ }
+
+ grouping gobgp-vrf-config {
+ description
+ "Configuration parameters for VRF.";
+
+ leaf-list both-rt {
+ description
+ "List of both import and export Route Targets for this VRF. Each
+ configuration for import and export Route Targets will be preferred.";
+ type string;
+ }
+ }
+
+ grouping gobgp-vrf-set {
+ description "Set of VRF instance configuration and state";
+
+ container config {
+ description
+ "Configuration parameters for VRF.";
+ uses gobgp-vrf-common;
+ uses gobgp-vrf-config;
+ }
+
+ container state {
+ description
+ "Configured states of VRF.";
+ uses gobgp-vrf-common;
+ }
+ }
+
+ grouping gobgp-vrfs {
+ description
+ "Virtual Routing and Forwarding (VRF) instances.";
+
+ container vrfs {
+ list vrf {
+ description
+ "VRF instance configurations on the local system.";
+
+ key "name";
+ leaf name {
+ type leafref {
+ path "../config/name";
+ }
+ }
+
+ uses gobgp-vrf-set;
+ }
+ }
+ }
grouping long-lived-graceful-restart {
container long-lived-graceful-restart {
@@ -1025,15 +1109,20 @@ module gobgp {
}
augment "/bgp:bgp" {
- description "additional rpki configuration and state";
+ description "Additional RPKI configuration and state";
uses gobgp-rpki-servers;
}
augment "/bgp:bgp" {
- description "additional bmp configuration";
+ description "Additional BMP configuration and state";
uses gobgp-bmp-servers;
}
+ augment "/bgp:bgp" {
+ description "Additional VRF configuration and state";
+ uses gobgp-vrfs;
+ }
+
typedef mrt-type {
type enumeration {
enum UPDATES {