summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorFUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>2015-07-26 21:40:16 +0900
committerFUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>2015-07-26 21:40:16 +0900
commitd9cbb32c3e917d5a208e58f49785da8fe3863e1c (patch)
treee0a6460b9ca9c935ab2f947be74185f98e3aa6e2
parent96002fd5c4344579b998558b3ad5f929b23ee650 (diff)
server: add zebra api support to configure linux network stack
Install route information to linux network stack via quagga's zebra. $ gobgpd --enable-zapi By default, 'unix:/var/run/quagga/zserv.api' for is used for zapi endpoint. It's not the case in your environment, use '--zapi-url' option. Note that only ipv4 support now. Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
-rw-r--r--gobgpd/main.go13
-rw-r--r--server/server.go29
-rw-r--r--server/zapi.go89
3 files changed, 131 insertions, 0 deletions
diff --git a/gobgpd/main.go b/gobgpd/main.go
index 62503d50..89cd0cb8 100644
--- a/gobgpd/main.go
+++ b/gobgpd/main.go
@@ -44,6 +44,8 @@ func main() {
UseSyslog string `short:"s" long:"syslog" description:"use syslogd"`
Facility string `long:"syslog-facility" description:"specify syslog facility"`
DisableStdlog bool `long:"disable-stdlog" description:"disable standard logging"`
+ EnableZapi bool `short:"z" long:"enable-zapi" description:"enable zebra api"`
+ ZapiURL string `long:"zapi-url" description:"specify zebra api url"`
}
_, err := flags.Parse(&opts)
if err != nil {
@@ -146,6 +148,17 @@ func main() {
grpcServer := server.NewGrpcServer(server.GRPC_PORT, bgpServer.GrpcReqCh)
go grpcServer.Serve()
+ if opts.EnableZapi == true {
+ if opts.ZapiURL == "" {
+ opts.ZapiURL = "unix:/var/run/quagga/zserv.api"
+ }
+ err := bgpServer.NewZclient(opts.ZapiURL)
+ if err != nil {
+ log.Error(err)
+ os.Exit(1)
+ }
+ }
+
var bgpConfig *config.Bgp = nil
var policyConfig *config.RoutingPolicy = nil
for {
diff --git a/server/server.go b/server/server.go
index a2f25391..ef0b2ce3 100644
--- a/server/server.go
+++ b/server/server.go
@@ -23,10 +23,12 @@ import (
"github.com/osrg/gobgp/packet"
"github.com/osrg/gobgp/policy"
"github.com/osrg/gobgp/table"
+ zebra "github.com/osrg/gozebra"
"gopkg.in/tomb.v2"
"net"
"os"
"strconv"
+ "strings"
"time"
)
@@ -76,6 +78,7 @@ type BgpServer struct {
broadcastMsgs []broadcastMsg
neighborMap map[string]*Peer
localRibMap map[string]*LocalRib
+ zclient *zebra.Client
}
func NewBgpServer(port int) *BgpServer {
@@ -191,6 +194,11 @@ func (server *BgpServer) Serve() {
incoming := make(chan *fsmMsg, 4096)
var senderMsgs []*SenderMsg
+
+ var zapiMsgCh chan *zebra.Message
+ if server.zclient != nil {
+ zapiMsgCh = server.zclient.Recieve()
+ }
for {
var firstMsg *SenderMsg
var sCh chan *SenderMsg
@@ -206,6 +214,8 @@ func (server *BgpServer) Serve() {
}
select {
+ case zmsg := <-zapiMsgCh:
+ handleZapiMsg(zmsg)
case conn := <-acceptCh:
remoteAddr, _, _ := net.SplitHostPort(conn.RemoteAddr().String())
peer, found := server.neighborMap[remoteAddr]
@@ -472,6 +482,11 @@ 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)
+ }
+
result := &GrpcResponse{
Data: path.ToApiStruct(),
}
@@ -2032,3 +2047,17 @@ func (server *BgpServer) mkMrtRibMsgs(rf bgp.RouteFamily, t uint32) ([]*bgp.MRTM
}
return msgs, nil
}
+
+func (server *BgpServer) NewZclient(url string) error {
+ l := strings.SplitN(url, ":", 2)
+ if len(l) != 2 {
+ return fmt.Errorf("unsupported url: %s", url)
+ }
+ cli, err := zebra.NewClient(l[0], l[1], zebra.ROUTE_BGP)
+ if err != nil {
+ return err
+ }
+ cli.SendHello()
+ server.zclient = cli
+ return nil
+}
diff --git a/server/zapi.go b/server/zapi.go
new file mode 100644
index 00000000..bd80dba9
--- /dev/null
+++ b/server/zapi.go
@@ -0,0 +1,89 @@
+// Copyright (C) 2015 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/osrg/gobgp/packet"
+ "github.com/osrg/gobgp/table"
+ zebra "github.com/osrg/gozebra"
+ "net"
+ "strconv"
+ "strings"
+)
+
+type broadcastZapiMsg struct {
+ client *zebra.Client
+ msg *zebra.Message
+}
+
+func (m *broadcastZapiMsg) send() {
+ m.client.Send(m.msg)
+}
+
+func newIPRouteMessage(path *table.Path) *zebra.Message {
+ var command zebra.API_TYPE
+ switch path.GetRouteFamily() {
+ case bgp.RF_IPv4_UC:
+ if path.IsWithdraw == true {
+ command = zebra.IPV4_ROUTE_DELETE
+ } else {
+ command = zebra.IPV4_ROUTE_ADD
+ }
+ case bgp.RF_IPv6_UC:
+ if path.IsWithdraw == true {
+ command = zebra.IPV6_ROUTE_DELETE
+ } else {
+ command = zebra.IPV6_ROUTE_ADD
+ }
+ default:
+ return nil
+ }
+
+ l := strings.SplitN(path.GetNlri().String(), "/", 2)
+ plen, _ := strconv.Atoi(l[1])
+ med, _ := path.GetMed()
+ return &zebra.Message{
+ Header: zebra.Header{
+ Command: command,
+ },
+ Body: &zebra.IPv4RouteBody{
+ Type: zebra.ROUTE_BGP,
+ SAFI: zebra.SAFI_UNICAST,
+ Message: zebra.MESSAGE_NEXTHOP,
+ Prefix: net.ParseIP(l[0]),
+ PrefixLength: uint8(plen),
+ Nexthops: []net.IP{path.GetNexthop()},
+ Metric: med,
+ },
+ }
+}
+
+func newBroadcastZapiBestMsg(cli *zebra.Client, path *table.Path) *broadcastZapiMsg {
+ if cli == nil {
+ return nil
+ }
+ m := newIPRouteMessage(path)
+ if m == nil {
+ return nil
+ }
+ return &broadcastZapiMsg{
+ client: cli,
+ msg: m,
+ }
+}
+
+func handleZapiMsg(msg *zebra.Message) {
+}