summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--api/gobgp.pb.go132
-rw-r--r--api/gobgp.proto33
-rw-r--r--gobgp/main.go63
-rw-r--r--packet/bgp.go42
-rw-r--r--server/fsm.go21
-rw-r--r--server/peer.go16
6 files changed, 254 insertions, 53 deletions
diff --git a/api/gobgp.pb.go b/api/gobgp.pb.go
index da4e61df..e552e363 100644
--- a/api/gobgp.pb.go
+++ b/api/gobgp.pb.go
@@ -13,6 +13,9 @@ It has these top-level messages:
Arguments
ModPathArguments
AddressFamily
+ GracefulRestartTuple
+ GracefulRestart
+ Capability
Aggregator
ExtendedCommunity
EVPNNlri
@@ -140,6 +143,44 @@ func (x SAFI) String() string {
return proto.EnumName(SAFI_name, int32(x))
}
+type BGP_CAPABILITY int32
+
+const (
+ BGP_CAPABILITY_UNKNOWN_CAP BGP_CAPABILITY = 0
+ BGP_CAPABILITY_MULTIPROTOCOL BGP_CAPABILITY = 1
+ BGP_CAPABILITY_ROUTE_REFRESH BGP_CAPABILITY = 2
+ BGP_CAPABILITY_CARRYING_LABEL_INFO BGP_CAPABILITY = 4
+ BGP_CAPABILITY_GRACEFUL_RESTART BGP_CAPABILITY = 64
+ BGP_CAPABILITY_FOUR_OCTET_AS_NUMBER BGP_CAPABILITY = 65
+ BGP_CAPABILITY_ENHANCED_ROUTE_REFRESH BGP_CAPABILITY = 70
+ BGP_CAPABILITY_ROUTE_REFRESH_CISCO BGP_CAPABILITY = 128
+)
+
+var BGP_CAPABILITY_name = map[int32]string{
+ 0: "UNKNOWN_CAP",
+ 1: "MULTIPROTOCOL",
+ 2: "ROUTE_REFRESH",
+ 4: "CARRYING_LABEL_INFO",
+ 64: "GRACEFUL_RESTART",
+ 65: "FOUR_OCTET_AS_NUMBER",
+ 70: "ENHANCED_ROUTE_REFRESH",
+ 128: "ROUTE_REFRESH_CISCO",
+}
+var BGP_CAPABILITY_value = map[string]int32{
+ "UNKNOWN_CAP": 0,
+ "MULTIPROTOCOL": 1,
+ "ROUTE_REFRESH": 2,
+ "CARRYING_LABEL_INFO": 4,
+ "GRACEFUL_RESTART": 64,
+ "FOUR_OCTET_AS_NUMBER": 65,
+ "ENHANCED_ROUTE_REFRESH": 70,
+ "ROUTE_REFRESH_CISCO": 128,
+}
+
+func (x BGP_CAPABILITY) String() string {
+ return proto.EnumName(BGP_CAPABILITY_name, int32(x))
+}
+
type Origin int32
const (
@@ -444,6 +485,64 @@ func (m *AddressFamily) Reset() { *m = AddressFamily{} }
func (m *AddressFamily) String() string { return proto.CompactTextString(m) }
func (*AddressFamily) ProtoMessage() {}
+type GracefulRestartTuple struct {
+ Af *AddressFamily `protobuf:"bytes,1,opt,name=af" json:"af,omitempty"`
+ Flags uint32 `protobuf:"varint,2,opt,name=flags" json:"flags,omitempty"`
+}
+
+func (m *GracefulRestartTuple) Reset() { *m = GracefulRestartTuple{} }
+func (m *GracefulRestartTuple) String() string { return proto.CompactTextString(m) }
+func (*GracefulRestartTuple) ProtoMessage() {}
+
+func (m *GracefulRestartTuple) GetAf() *AddressFamily {
+ if m != nil {
+ return m.Af
+ }
+ return nil
+}
+
+type GracefulRestart struct {
+ Flags uint32 `protobuf:"varint,1,opt,name=flags" json:"flags,omitempty"`
+ Time uint32 `protobuf:"varint,2,opt,name=time" json:"time,omitempty"`
+ Tuples []*GracefulRestartTuple `protobuf:"bytes,3,rep,name=tuples" json:"tuples,omitempty"`
+}
+
+func (m *GracefulRestart) Reset() { *m = GracefulRestart{} }
+func (m *GracefulRestart) String() string { return proto.CompactTextString(m) }
+func (*GracefulRestart) ProtoMessage() {}
+
+func (m *GracefulRestart) GetTuples() []*GracefulRestartTuple {
+ if m != nil {
+ return m.Tuples
+ }
+ return nil
+}
+
+type Capability struct {
+ Code BGP_CAPABILITY `protobuf:"varint,1,opt,name=code,enum=api.BGP_CAPABILITY" json:"code,omitempty"`
+ MultiProtocol *AddressFamily `protobuf:"bytes,2,opt,name=multi_protocol" json:"multi_protocol,omitempty"`
+ GracefulRestart *GracefulRestart `protobuf:"bytes,3,opt,name=graceful_restart" json:"graceful_restart,omitempty"`
+ Asn uint32 `protobuf:"varint,4,opt,name=asn" json:"asn,omitempty"`
+}
+
+func (m *Capability) Reset() { *m = Capability{} }
+func (m *Capability) String() string { return proto.CompactTextString(m) }
+func (*Capability) ProtoMessage() {}
+
+func (m *Capability) GetMultiProtocol() *AddressFamily {
+ if m != nil {
+ return m.MultiProtocol
+ }
+ return nil
+}
+
+func (m *Capability) GetGracefulRestart() *GracefulRestart {
+ if m != nil {
+ return m.GracefulRestart
+ }
+ return nil
+}
+
type Aggregator struct {
As uint32 `protobuf:"varint,1,opt,name=as" json:"as,omitempty"`
Address string `protobuf:"bytes,2,opt,name=address" json:"address,omitempty"`
@@ -663,21 +762,35 @@ func (m *Destination) GetPaths() []*Path {
}
type PeerConf struct {
- RemoteIp string `protobuf:"bytes,1,opt,name=remote_ip" json:"remote_ip,omitempty"`
- Id string `protobuf:"bytes,2,opt,name=id" json:"id,omitempty"`
- RemoteAs uint32 `protobuf:"varint,3,opt,name=remote_as" json:"remote_as,omitempty"`
- CapRefresh bool `protobuf:"varint,4,opt,name=cap_refresh" json:"cap_refresh,omitempty"`
- CapEnhancedRefresh bool `protobuf:"varint,5,opt,name=cap_enhanced_refresh" json:"cap_enhanced_refresh,omitempty"`
- RemoteCap []int32 `protobuf:"varint,6,rep,name=remote_cap" json:"remote_cap,omitempty"`
- LocalCap []int32 `protobuf:"varint,7,rep,name=local_cap" json:"local_cap,omitempty"`
- Holdtime uint32 `protobuf:"varint,8,opt,name=holdtime" json:"holdtime,omitempty"`
- KeepaliveInterval uint32 `protobuf:"varint,9,opt,name=keepalive_interval" json:"keepalive_interval,omitempty"`
+ RemoteIp string `protobuf:"bytes,1,opt,name=remote_ip" json:"remote_ip,omitempty"`
+ Id string `protobuf:"bytes,2,opt,name=id" json:"id,omitempty"`
+ RemoteAs uint32 `protobuf:"varint,3,opt,name=remote_as" json:"remote_as,omitempty"`
+ CapRefresh bool `protobuf:"varint,4,opt,name=cap_refresh" json:"cap_refresh,omitempty"`
+ CapEnhancedRefresh bool `protobuf:"varint,5,opt,name=cap_enhanced_refresh" json:"cap_enhanced_refresh,omitempty"`
+ RemoteCap []*Capability `protobuf:"bytes,6,rep,name=remote_cap" json:"remote_cap,omitempty"`
+ LocalCap []*Capability `protobuf:"bytes,7,rep,name=local_cap" json:"local_cap,omitempty"`
+ Holdtime uint32 `protobuf:"varint,8,opt,name=holdtime" json:"holdtime,omitempty"`
+ KeepaliveInterval uint32 `protobuf:"varint,9,opt,name=keepalive_interval" json:"keepalive_interval,omitempty"`
}
func (m *PeerConf) Reset() { *m = PeerConf{} }
func (m *PeerConf) String() string { return proto.CompactTextString(m) }
func (*PeerConf) ProtoMessage() {}
+func (m *PeerConf) GetRemoteCap() []*Capability {
+ if m != nil {
+ return m.RemoteCap
+ }
+ return nil
+}
+
+func (m *PeerConf) GetLocalCap() []*Capability {
+ if m != nil {
+ return m.LocalCap
+ }
+ return nil
+}
+
type PeerInfo struct {
BgpState string `protobuf:"bytes,1,opt,name=bgp_state" json:"bgp_state,omitempty"`
AdminState string `protobuf:"bytes,2,opt,name=admin_state" json:"admin_state,omitempty"`
@@ -739,6 +852,7 @@ func init() {
proto.RegisterEnum("api.Resource", Resource_name, Resource_value)
proto.RegisterEnum("api.AFI", AFI_name, AFI_value)
proto.RegisterEnum("api.SAFI", SAFI_name, SAFI_value)
+ proto.RegisterEnum("api.BGP_CAPABILITY", BGP_CAPABILITY_name, BGP_CAPABILITY_value)
proto.RegisterEnum("api.Origin", Origin_name, Origin_value)
proto.RegisterEnum("api.EXTENDED_COMMUNITIE_TYPE", EXTENDED_COMMUNITIE_TYPE_name, EXTENDED_COMMUNITIE_TYPE_value)
proto.RegisterEnum("api.EXTENDED_COMMUNITIE_SUBTYPE", EXTENDED_COMMUNITIE_SUBTYPE_name, EXTENDED_COMMUNITIE_SUBTYPE_value)
diff --git a/api/gobgp.proto b/api/gobgp.proto
index 239c933d..a3f4228d 100644
--- a/api/gobgp.proto
+++ b/api/gobgp.proto
@@ -86,6 +86,35 @@ message AddressFamily {
SAFI Safi = 2;
}
+enum BGP_CAPABILITY {
+ UNKNOWN_CAP = 0;
+ MULTIPROTOCOL = 1;
+ ROUTE_REFRESH = 2;
+ CARRYING_LABEL_INFO = 4;
+ GRACEFUL_RESTART = 64;
+ FOUR_OCTET_AS_NUMBER = 65;
+ ENHANCED_ROUTE_REFRESH = 70;
+ ROUTE_REFRESH_CISCO = 128;
+}
+
+message GracefulRestartTuple {
+ AddressFamily af = 1;
+ uint32 flags = 2;
+}
+
+message GracefulRestart {
+ uint32 flags = 1;
+ uint32 time = 2;
+ repeated GracefulRestartTuple tuples = 3;
+}
+
+message Capability {
+ BGP_CAPABILITY code = 1;
+ AddressFamily multi_protocol = 2;
+ GracefulRestart graceful_restart = 3;
+ uint32 asn = 4;
+}
+
enum Origin {
IGP = 0;
EGP = 1;
@@ -250,8 +279,8 @@ message PeerConf {
uint32 remote_as = 3;
bool cap_refresh = 4;
bool cap_enhanced_refresh = 5;
- repeated int32 remote_cap = 6;
- repeated int32 local_cap = 7;
+ repeated Capability remote_cap = 6;
+ repeated Capability local_cap = 7;
uint32 holdtime = 8;
uint32 keepalive_interval = 9;
}
diff --git a/gobgp/main.go b/gobgp/main.go
index 244e1f01..d63e7c68 100644
--- a/gobgp/main.go
+++ b/gobgp/main.go
@@ -622,6 +622,20 @@ func showNeighbors() error {
return nil
}
+type capabilities []*api.Capability
+
+func (c capabilities) Len() int {
+ return len(c)
+}
+
+func (c capabilities) Swap(i, j int) {
+ c[i], c[j] = c[j], c[i]
+}
+
+func (c capabilities) Less(i, j int) bool {
+ return c[i].Code < c[j].Code
+}
+
func showNeighbor(args []string) error {
id := &api.Arguments{
RouterId: args[0],
@@ -646,54 +660,47 @@ func showNeighbor(args []string) error {
fmt.Printf(" Configured hold time is %d, keepalive interval is %d seconds\n", p.Conf.Holdtime, p.Conf.KeepaliveInterval)
fmt.Printf(" Neighbor capabilities:\n")
- caps := []int32{}
- lookup := func(val int32, l []int32) bool {
+ caps := capabilities{}
+ lookup := func(val *api.Capability, l capabilities) *api.Capability {
for _, v := range l {
- if v == val {
- return true
+ if v.Code == val.Code {
+ if v.Code == api.BGP_CAPABILITY_MULTIPROTOCOL {
+ if v.MultiProtocol.Equal(val.MultiProtocol) {
+ return v
+ }
+ continue
+ }
+ return v
}
}
- return false
+ return nil
}
caps = append(caps, p.Conf.LocalCap...)
for _, v := range p.Conf.RemoteCap {
- if !lookup(v, caps) {
+ if lookup(v, caps) == nil {
caps = append(caps, v)
}
}
- toInt := func(arg []int32) []int {
- ret := make([]int, 0, len(arg))
- for _, v := range arg {
- ret = append(ret, int(v))
- }
- return ret
- }
+ sort.Sort(caps)
- sort.Sort(sort.IntSlice(toInt(caps)))
- capdict := map[int]string{1: "MULTIPROTOCOL",
- 2: "ROUTE_REFRESH",
- 4: "CARRYING_LABEL_INFO",
- 64: "GRACEFUL_RESTART",
- 65: "FOUR_OCTET_AS_NUMBER",
- 70: "ENHANCED_ROUTE_REFRESH",
- 128: "ROUTE_REFRESH_CISCO"}
for _, c := range caps {
- k, found := capdict[int(c)]
- if !found {
- k = "UNKNOWN (" + fmt.Sprint(c) + ")"
- }
support := ""
- if lookup(c, p.Conf.LocalCap) {
+ if m := lookup(c, p.Conf.LocalCap); m != nil {
support += "advertised"
}
- if lookup(c, p.Conf.RemoteCap) {
+ if lookup(c, p.Conf.RemoteCap) != nil {
if len(support) != 0 {
support += " and "
}
support += "received"
}
- fmt.Printf(" %s: %s\n", k, support)
+
+ if c.Code != api.BGP_CAPABILITY_MULTIPROTOCOL {
+ fmt.Printf(" %s: %s\n", c.Code, support)
+ } else {
+ fmt.Printf(" %s(%s,%s): %s\n", c.Code, c.MultiProtocol.Afi, c.MultiProtocol.Safi, support)
+ }
}
fmt.Print(" Message statistics:\n")
fmt.Print(" Sent Rcvd\n")
diff --git a/packet/bgp.go b/packet/bgp.go
index 8c719d8d..0cc8aca9 100644
--- a/packet/bgp.go
+++ b/packet/bgp.go
@@ -171,6 +171,7 @@ type ParameterCapabilityInterface interface {
Serialize() ([]byte, error)
Len() int
Code() BGPCapabilityCode
+ ToApiStruct() *api.Capability
}
type DefaultParameterCapability struct {
@@ -206,6 +207,12 @@ func (c *DefaultParameterCapability) Len() int {
return int(c.CapLen + 2)
}
+func (c *DefaultParameterCapability) ToApiStruct() *api.Capability {
+ return &api.Capability{
+ Code: api.BGP_CAPABILITY(c.Code()),
+ }
+}
+
type CapMultiProtocolValue struct {
AFI uint16
SAFI uint8
@@ -235,6 +242,13 @@ func (c *CapMultiProtocol) Serialize() ([]byte, error) {
return c.DefaultParameterCapability.Serialize()
}
+func (c *CapMultiProtocol) ToApiStruct() *api.Capability {
+ return &api.Capability{
+ Code: api.BGP_CAPABILITY(c.Code()),
+ MultiProtocol: &api.AddressFamily{api.AFI(c.CapValue.AFI), api.SAFI(c.CapValue.SAFI)},
+ }
+}
+
func NewCapMultiProtocol(afi uint16, safi uint8) *CapMultiProtocol {
return &CapMultiProtocol{
DefaultParameterCapability{
@@ -310,6 +324,27 @@ func (c *CapGracefulRestart) Serialize() ([]byte, error) {
return c.DefaultParameterCapability.Serialize()
}
+func (c *CapGracefulRestart) ToApiStruct() *api.Capability {
+ value := &api.GracefulRestart{
+ Flags: uint32(c.CapValue.Flags),
+ Time: uint32(c.CapValue.Time),
+ }
+ tuples := []*api.GracefulRestartTuple{}
+ for _, t := range c.CapValue.Tuples {
+ tuple := &api.GracefulRestartTuple{
+ Af: &api.AddressFamily{api.AFI(t.AFI), api.SAFI(t.SAFI)},
+ Flags: uint32(t.Flags),
+ }
+ tuples = append(tuples, tuple)
+
+ }
+ value.Tuples = tuples
+ return &api.Capability{
+ Code: api.BGP_CAPABILITY(c.Code()),
+ GracefulRestart: value,
+ }
+}
+
func NewCapGracefulRestart(flags uint8, time uint16, tuples []CapGracefulRestartTuples) *CapGracefulRestart {
return &CapGracefulRestart{
DefaultParameterCapability{
@@ -345,6 +380,13 @@ func (c *CapFourOctetASNumber) Serialize() ([]byte, error) {
return c.DefaultParameterCapability.Serialize()
}
+func (c *CapFourOctetASNumber) ToApiStruct() *api.Capability {
+ return &api.Capability{
+ Code: api.BGP_CAPABILITY(c.Code()),
+ Asn: c.CapValue,
+ }
+}
+
func NewCapFourOctetASNumber(asnum uint32) *CapFourOctetASNumber {
return &CapFourOctetASNumber{
DefaultParameterCapability{
diff --git a/server/fsm.go b/server/fsm.go
index 53cfc55c..fc7cded9 100644
--- a/server/fsm.go
+++ b/server/fsm.go
@@ -300,25 +300,28 @@ func (h *FSMHandler) active() bgp.FSMState {
}
}
-func buildopen(global *config.Global, peerConf *config.Neighbor) *bgp.BGPMessage {
- p1 := bgp.NewOptionParameterCapability(
- []bgp.ParameterCapabilityInterface{bgp.NewCapRouteRefresh()})
- c := []bgp.ParameterCapabilityInterface{}
+func capabilitiesFromConfig(global *config.Global, peerConf *config.Neighbor) []bgp.ParameterCapabilityInterface {
+ caps := make([]bgp.ParameterCapabilityInterface, 0, 4)
+ caps = append(caps, bgp.NewCapRouteRefresh())
for _, rf := range peerConf.AfiSafiList {
k, _ := bgp.GetRouteFamily(rf.AfiSafiName)
afi, safi := bgp.RouteFamilyToAfiSafi(k)
- c = append(c, bgp.NewCapMultiProtocol(afi, safi))
+ caps = append(caps, bgp.NewCapMultiProtocol(afi, safi))
}
- p2 := bgp.NewOptionParameterCapability(c)
- p3 := bgp.NewOptionParameterCapability(
- []bgp.ParameterCapabilityInterface{bgp.NewCapFourOctetASNumber(global.As)})
+ caps = append(caps, bgp.NewCapFourOctetASNumber(global.As))
+ return caps
+}
+
+func buildopen(global *config.Global, peerConf *config.Neighbor) *bgp.BGPMessage {
+ caps := capabilitiesFromConfig(global, peerConf)
+ opt := bgp.NewOptionParameterCapability(caps)
holdTime := uint16(peerConf.Timers.HoldTime)
as := global.As
if as > (1<<16)-1 {
as = bgp.AS_TRANS
}
return bgp.NewBGPOpenMessage(uint16(as), holdTime, global.RouterId.String(),
- []bgp.OptionParameterInterface{p1, p2, p3})
+ []bgp.OptionParameterInterface{opt})
}
func readAll(conn net.Conn, length int) ([]byte, error) {
diff --git a/server/peer.go b/server/peer.go
index 604be36b..ccb2538b 100644
--- a/server/peer.go
+++ b/server/peer.go
@@ -944,17 +944,23 @@ func (peer *Peer) ToApiStruct() *api.Peer {
f := peer.fsm
c := f.peerConfig
- capList := make([]int32, 0, len(peer.capMap))
- for k, _ := range peer.capMap {
- capList = append(capList, int32(k))
+ remoteCap := make([]*api.Capability, 0, len(peer.capMap))
+ for _, c := range peer.capMap {
+ remoteCap = append(remoteCap, c.ToApiStruct())
+ }
+
+ caps := capabilitiesFromConfig(&peer.globalConfig, &peer.peerConfig)
+ localCap := make([]*api.Capability, 0, len(caps))
+ for _, c := range caps {
+ localCap = append(localCap, c.ToApiStruct())
}
conf := &api.PeerConf{
RemoteIp: c.NeighborAddress.String(),
Id: peer.peerInfo.ID.To4().String(),
RemoteAs: c.PeerAs,
- RemoteCap: capList,
- LocalCap: []int32{int32(bgp.BGP_CAP_MULTIPROTOCOL), int32(bgp.BGP_CAP_ROUTE_REFRESH), int32(bgp.BGP_CAP_FOUR_OCTET_AS_NUMBER)},
+ RemoteCap: remoteCap,
+ LocalCap: localCap,
KeepaliveInterval: uint32(peer.fsm.peerConfig.Timers.KeepaliveInterval),
Holdtime: uint32(peer.fsm.peerConfig.Timers.HoldTime),
}