diff options
author | ISHIDA Wataru <ishida.wataru@lab.ntt.co.jp> | 2015-04-29 17:49:51 +0000 |
---|---|---|
committer | ISHIDA Wataru <ishida.wataru@lab.ntt.co.jp> | 2015-05-10 04:26:48 +0000 |
commit | 23d1d4322199bbaae52c52aa0db8db9b000944fe (patch) | |
tree | 64ad12096d8bfcdd2bce990f02e1f42f542f11bc | |
parent | 7cbb6bbd32ad37ceae89c23bc79ff9cf5fe6a01d (diff) |
api/gobgp: show multiprotocol capabilities in detail
/home/vagrant% gobgp -u 192.168.10.4 neighbor 192.168.10.2
BGP neighbor is 192.168.10.2, remote AS 65001
BGP version 4, remote router ID 192.168.10.2
BGP state = BGP_FSM_ESTABLISHED, up for 00:12:57
BGP OutQ = 0, Flops = 0
Neighbor capabilities:
MULTIPROTOCOL(IP,UNICAST): advertised
MULTIPROTOCOL(L2VPN,EVPN): advertised
MULTIPROTOCOL(IP,ENCAP): advertised
MULTIPROTOCOL(IP,ROUTE_TARGET_CONSTRTAINS): received
ROUTE_REFRESH: advertised
FOUR_OCTET_AS_NUMBER: advertised and received
Message statistics:
Sent Rcvd
Opens: 1 1
Notifications: 0 0
Updates: 0 0
Keepalives: 26 26
Route Refesh: 0 0
Discarded: 0 0
Total: 27 27
Signed-off-by: ISHIDA Wataru <ishida.wataru@lab.ntt.co.jp>
-rw-r--r-- | api/gobgp.pb.go | 132 | ||||
-rw-r--r-- | api/gobgp.proto | 33 | ||||
-rw-r--r-- | gobgp/main.go | 63 | ||||
-rw-r--r-- | packet/bgp.go | 42 | ||||
-rw-r--r-- | server/fsm.go | 21 | ||||
-rw-r--r-- | server/peer.go | 16 |
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), } |