diff options
author | Hiroshi Yokoi <yokoi.hiroshi@po.ntts.co.jp> | 2015-08-26 18:11:38 +0900 |
---|---|---|
committer | Hiroshi Yokoi <yokoi.hiroshi@po.ntts.co.jp> | 2015-09-01 19:42:02 +0900 |
commit | cc51c48a4934bde8f5a5555632633c3c8486b797 (patch) | |
tree | 14998dac3531e6a609bb414d2816f7f7d2ba1d5f /server | |
parent | f8d437ec0ea65656ca4c6d81ec48fe0f7099c60e (diff) |
zebra: distribute routes from zebra
Signed-off-by: Hiroshi Yokoi <yokoi.hiroshi@po.ntts.co.jp>
Diffstat (limited to 'server')
-rw-r--r-- | server/server.go | 22 | ||||
-rw-r--r-- | server/zclient.go | 63 | ||||
-rw-r--r-- | server/zclient_test.go | 104 |
3 files changed, 184 insertions, 5 deletions
diff --git a/server/server.go b/server/server.go index 92e3d178..971cc517 100644 --- a/server/server.go +++ b/server/server.go @@ -231,7 +231,10 @@ func (server *BgpServer) Serve() { case rmsg := <-server.roaClient.recieveROA(): server.roaClient.handleRTRMsg(rmsg) case zmsg := <-zapiMsgCh: - handleZapiMsg(zmsg) + m := handleZapiMsg(zmsg, server) + if len(m) > 0 { + senderMsgs = append(senderMsgs, m...) + } case conn := <-acceptCh: remoteAddr, _, _ := net.SplitHostPort(conn.RemoteAddr().String()) peer, found := server.neighborMap[remoteAddr] @@ -548,9 +551,16 @@ func applyPolicies(peer *Peer, loc *LocalRib, d Direction, pathList []*table.Pat func (server *BgpServer) broadcastBests(bests []*table.Path) { for _, path := range bests { - z := newBroadcastZapiBestMsg(server.zclient, path) - if z != nil { - server.broadcastMsgs = append(server.broadcastMsgs, z) + if !path.IsFromZebra { + z := newBroadcastZapiBestMsg(server.zclient, path) + if z != nil { + server.broadcastMsgs = append(server.broadcastMsgs, z) + log.WithFields(log.Fields{ + "Topic": "Server", + "Client": z.client, + "Message": z.msg, + }).Debug("Default policy applied and rejected.") + } } result := &GrpcResponse{ @@ -654,6 +664,7 @@ func (server *BgpServer) propagateUpdate(peer *Peer, pathList []*table.Path) []* } targetPeer.adjRib.UpdateOut(f) msgList := table.CreateUpdateMsgFromPaths(f) + msgs = append(msgs, newSenderMsg(targetPeer, msgList)) } } @@ -2322,6 +2333,9 @@ func (server *BgpServer) NewZclient(url string) error { return err } cli.SendHello() + cli.SendRouterIDAdd() + cli.SendInterfaceAdd() + cli.SendRedistribute() server.zclient = cli return nil } diff --git a/server/zclient.go b/server/zclient.go index 7c1b9a42..ab163b37 100644 --- a/server/zclient.go +++ b/server/zclient.go @@ -16,12 +16,14 @@ package server import ( + log "github.com/Sirupsen/logrus" "github.com/osrg/gobgp/packet" "github.com/osrg/gobgp/table" "github.com/osrg/gobgp/zebra" "net" "strconv" "strings" + "time" ) type broadcastZapiMsg struct { @@ -84,6 +86,49 @@ func newIPRouteMessage(path *table.Path) *zebra.Message { } } +func createPathFromIPRouteMessage(m *zebra.Message, peerInfo *table.PeerInfo) *table.Path { + + header := m.Header + body := m.Body.(*zebra.IPRouteBody) + isV4 := header.Command == zebra.IPV4_ROUTE_ADD || header.Command == zebra.IPV4_ROUTE_DELETE + + var nlri bgp.AddrPrefixInterface + pattr := make([]bgp.PathAttributeInterface, 0) + var mpnlri *bgp.PathAttributeMpReachNLRI + var isWithdraw bool = header.Command == zebra.IPV4_ROUTE_DELETE || header.Command == zebra.IPV6_ROUTE_DELETE + + origin := bgp.NewPathAttributeOrigin(bgp.BGP_ORIGIN_ATTR_TYPE_IGP) + pattr = append(pattr, origin) + + log.WithFields(log.Fields{ + "Topic": "Zebra", + "RouteType": body.Type.String(), + "Flag": body.Flags.String(), + "Message": body.Message, + "Prefix": body.Prefix, + "PrefixLength": body.PrefixLength, + "Nexthop": body.Nexthops, + "api": header.Command.String(), + }).Debugf("create path from ip route message.") + + if isV4 { + nlri = bgp.NewNLRInfo(body.PrefixLength, body.Prefix.String()) + nexthop := bgp.NewPathAttributeNextHop("0.0.0.0") + pattr = append(pattr, nexthop) + } else { + nlri = bgp.NewIPv6AddrPrefix(body.PrefixLength, body.Prefix.String()) + mpnlri = bgp.NewPathAttributeMpReachNLRI("::", []bgp.AddrPrefixInterface{nlri}) + pattr = append(pattr, mpnlri) + } + + med := bgp.NewPathAttributeMultiExitDisc(body.Metric) + pattr = append(pattr, med) + + p := table.NewPath(peerInfo, nlri, isWithdraw, pattr, false, time.Now(), true) + p.IsFromZebra = true + return p +} + func newBroadcastZapiBestMsg(cli *zebra.Client, path *table.Path) *broadcastZapiMsg { if cli == nil { return nil @@ -98,5 +143,21 @@ func newBroadcastZapiBestMsg(cli *zebra.Client, path *table.Path) *broadcastZapi } } -func handleZapiMsg(msg *zebra.Message) { +func handleZapiMsg(msg *zebra.Message, server *BgpServer) []*SenderMsg { + + switch b := msg.Body.(type) { + case *zebra.IPRouteBody: + pi := &table.PeerInfo{ + AS: server.bgpConfig.Global.GlobalConfig.As, + LocalID: server.bgpConfig.Global.GlobalConfig.RouterId, + } + + if b.Prefix != nil && len(b.Nexthops) > 0 && b.Type != zebra.ROUTE_KERNEL { + p := createPathFromIPRouteMessage(msg, pi) + msgs := server.propagateUpdate("", false, []*table.Path{p}) + return msgs + } + } + + return nil } diff --git a/server/zclient_test.go b/server/zclient_test.go new file mode 100644 index 00000000..257a1d06 --- /dev/null +++ b/server/zclient_test.go @@ -0,0 +1,104 @@ +// Copyright (C) 2014 Nippon Telegraph and Telephone Corporation. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +// implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package server +import ( + "github.com/stretchr/testify/assert" + "github.com/osrg/gobgp/zebra" + "github.com/osrg/gobgp/table" + "testing" + "net" +) + +func Test_createPathFromIPRouteMessage(t *testing.T) { + assert := assert.New(t) + + m := &zebra.Message{} + h := &zebra.Header{ + Len: zebra.HEADER_SIZE, + Marker: zebra.HEADER_MARKER, + Version: zebra.VERSION, + Command: zebra.IPV4_ROUTE_ADD, + } + + b := &zebra.IPRouteBody{ + Type: zebra.ROUTE_TYPE(zebra.ROUTE_STATIC), + Flags: zebra.FLAG(zebra.FLAG_SELECTED), + Message: zebra.MESSAGE_NEXTHOP | zebra.MESSAGE_DISTANCE | zebra.MESSAGE_METRIC, + SAFI: zebra.SAFI(zebra.SAFI_UNICAST), + Prefix: net.ParseIP("192.168.100.0"), + PrefixLength :uint8(24), + Nexthops : []net.IP{net.ParseIP("0.0.0.0")}, + Ifindexs : []uint32{1}, + Distance: uint8(0), + Metric : uint32(100), + Api : zebra.API_TYPE(zebra.IPV4_ROUTE_ADD), + } + + m.Header = *h + m.Body = b + + pi := &table.PeerInfo{ + AS: 65000, + LocalID: net.ParseIP("10.0.0.1"), + } + p := createPathFromIPRouteMessage(m, pi) + assert.NotEqual(nil, p) + assert.Equal("0.0.0.0", p.GetNexthop().String()) + assert.Equal("192.168.100.0/24",p.GetNlri().String()) + assert.True(p.IsFromZebra) + assert.False(p.IsWithdraw) + + // withdraw + h.Command = zebra.IPV4_ROUTE_DELETE + m.Header = *h + p = createPathFromIPRouteMessage(m, pi) + assert.NotEqual(nil, p) + assert.Equal("0.0.0.0", p.GetNexthop().String()) + assert.Equal("192.168.100.0/24",p.GetNlri().String()) + med, _ := p.GetMed() + assert.Equal(uint32(100), med) + assert.True(p.IsFromZebra) + assert.True(p.IsWithdraw) + + + // IPv6 + h.Command = zebra.IPV6_ROUTE_ADD + b.Prefix = net.ParseIP("2001:db8:0:f101::") + b.PrefixLength = uint8(64) + b.Nexthops = []net.IP{net.ParseIP("::")} + m.Header = *h + m.Body = b + + p = createPathFromIPRouteMessage(m, pi) + assert.NotEqual(nil, p) + assert.Equal("::", p.GetNexthop().String()) + assert.Equal("2001:db8:0:f101::/64",p.GetNlri().String()) + med, _ = p.GetMed() + assert.Equal(uint32(100), med) + assert.True(p.IsFromZebra) + assert.False(p.IsWithdraw) + + // withdraw + h.Command = zebra.IPV6_ROUTE_DELETE + m.Header = *h + p = createPathFromIPRouteMessage(m, pi) + assert.NotEqual(nil, p) + assert.Equal("::", p.GetNexthop().String()) + assert.Equal("2001:db8:0:f101::/64",p.GetNlri().String()) + assert.True(p.IsFromZebra) + assert.True(p.IsWithdraw) + +}
\ No newline at end of file |