LoginSignup
10
5

More than 5 years have passed since last update.

GoBGPのオプション機能"GoBGP as a Go Native BGP library"を試してみる

Posted at

最近、GoBGPのドキュメンテーションに、オプション機能"GoBGP as a Go Native BGP library"なるものが記載されていることに気が付きました。
「これは、何なんだろう?」という素朴な疑問を、私なりの解釈で解き明かしてみたいと思います。

◼︎ まずは、GoBGP構築準備から ...

次のようなGoBGP環境を作成します。なお、対向BGP Routerに、GoBGPを配備しても問題ありません。

                +---------+ (eth1)         iBGP                 +--------+
... ----------+ |  GoBGP  | +---------------------------------+ |  BGP   | +---- ...
                |         | 192.168.0.1/24       192.168.0.2/24 | Router |
                +---------+                                     +--------+
                < AS65000 >                                     < AS65000 >

             <---  Target  --->                            <-- out of scope -->

以下、"GoBGP"側の構築手順を記述します。

(1) Linux基本設定

  • Linuxネットワーク設定
$ sudo vi /etc/network/interfaces

...(snip)
auto eth1
iface eth1 inet static
address 192.168.0.1
netmask 255.255.255.0

  • golangのインストール
$ vi $HOME/.profile

...(snip)
export GOPATH=$HOME/golang
export PATH=$GOPATH/bin:/usr/local/go/bin:$PATH

$ wget --no-check-certificate https://storage.googleapis.com/golang/go1.6.2.linux-amd64.tar.gz
$ sudo tar -C /usr/local -xzf go1.6.2.linux-amd64.tar.gz
$ mkdir $HOME/golang
$ source .profile

$ go version
go version go1.6.2 linux/amd64

(2) GoBGPインストール

  • GoBGPをインストールします。
$ sudo apt-get update
$ sudo apt-get install git
$ go get github.com/osrg/gobgp/gobgpd
$ go get github.com/osrg/gobgp/gobgp

◼︎ いろいろな方法で、GoBGPを動作させてみる

GoBGPを動作させたことがある方にとっては、GoBGP設定ファイルを用いたGoBGP起動方法を思い浮かべることだと思います。
ここでは、いろいろなGoBGP起動方法について、GoBGP動作結果を比較してみたいと思います。

(GoBGP起動方法1) gobgp設定ファイルから、GoBGP起動してBGPピアを開設してみる

こちらは、オーソドックスなGoBGP起動方法ですよね。

  • 事前に、GoBGP設定ファイルを作成しておきます
$HOME/golang/bin/gobgpd.conf
[[neighbors]]
[neighbors.config]
 neighbor-address = "192.168.0.2"
 peer-as = 65000
 local-as = 65000

[global.config]
 as = 65000
 router-id = "192.168.0.1"
  • gobgpdを起動します
$ cd $GOPATH/bin
$ sudo ./gobgpd -f gobgpd.conf -l debug -p
INFO[0000] gobgpd started
INFO[0000] finished reading the config file
INFO[0000] Peer 192.168.0.2 is added
INFO[0000] Add a peer configuration for 192.168.0.2
DEBU[0000] IdleHoldTimer expired                         Duration=0 Key=192.168.0.2 Topic=Peer
DEBU[0000] state changed                                 Key=192.168.0.2 Topic=Peer new=BGP_FSM_ACTIVE old=BGP_FSM_IDLE reason=idle-hold-timer-expired
DEBU[0013] state changed                                 Key=192.168.0.2 Topic=Peer new=BGP_FSM_OPENSENT old=BGP_FSM_ACTIVE reason=new-connection
DEBU[0013] state changed                                 Key=192.168.0.2 Topic=Peer new=BGP_FSM_OPENCONFIRM old=BGP_FSM_OPENSENT reason=open-msg-received
INFO[0013] Peer Up                                       Key=192.168.0.2 State=BGP_FSM_OPENCONFIRM Topic=Peer
DEBU[0013] state changed                                 Key=192.168.0.2 Topic=Peer new=BGP_FSM_ESTABLISHED old=BGP_FSM_OPENCONFIRM reason=open-msg-negotiated
DEBU[0013] received update                               Key=192.168.0.2 Topic=Peer attributes=[{Origin: ?}  {Nexthop: 192.168.0.2} {LocalPref: 100}] nlri=[20.20.20.0/24] withdrawals=[]
DEBU[0013] create Destination                            Key=20.20.20.0/24 Topic=Table
DEBU[0013] Processing destination                        Key=20.20.20.0/24 Topic=table
DEBU[0013] computeKnownBestPath known pathlist: 1
DEBU[0013] From same AS, ignore.                         Data={ 20.20.20.0/24 | src: { 192.168.0.2 | as: 65000, id: 192.168.0.2 }, nh: 192.168.0.2 } Key=192.168.0.2 Topic=Peer
DEBU[0043] sent                                          Key=192.168.0.2 State=BGP_FSM_ESTABLISHED Topic=Peer data=&{Header:{Marker:[] Len:19 Type:4} Body:0x1234d78}
DEBU[0073] sent                                          Key=192.168.0.2 State=BGP_FSM_ESTABLISHED Topic=Peer data=&{Header:{Marker:[] Len:19 Type:4} Body:0x1234d78}
DEBU[0103] sent                                          Key=192.168.0.2 State=BGP_FSM_ESTABLISHED Topic=Peer data=&{Header:{Marker:[] Len:19 Type:4} Body:0x1234d78}
  • gobgpコマンドから、Peer情報を確認してみます
$ gobgp neighbor 192.168.0.2
BGP neighbor is 192.168.0.2, remote AS 65000
  BGP version 4, remote router ID 192.168.0.2
  BGP state = BGP_FSM_ESTABLISHED, up for 00:00:10
  BGP OutQ = 0, Flops = 0
  Hold time is 90, keepalive interval is 30 seconds
  Configured hold time is 90, keepalive interval is 30 seconds
  Neighbor capabilities:
    BGP_CAP_MULTIPROTOCOL:
        ipv4-unicast:   advertised and received
        l2vpn-evpn:     received
    BGP_CAP_ROUTE_REFRESH:      advertised and received
    BGP_CAP_FOUR_OCTET_AS_NUMBER:       advertised and received
  Message statistics:
                         Sent       Rcvd
    Opens:                  1          1
    Notifications:          0          0
    Updates:                0          1
    Keepalives:             1          1
    Route Refesh:           0          0
    Discarded:              0          0
    Total:                  2          3
  Route statistics:
    Advertised:             0
    Received:               1
    Accepted:               1
  • gobgpコマンドから、rib情報を確認してみます
$ gobgp global rib 
    Network             Next Hop             AS_PATH              Age        Attrs
*>  20.20.20.0/24       192.168.0.2                               00:00:38   [{Origin: ?} {LocalPref: 100}]

(GoBGP起動方法2) gobgpコマンドから、BGPピアを開設してみる

続いての起動方法は、GoBGP設定ファイルを使用せずに、gobgpコマンドで、BGPピア開設に必要な設定情報を投入する方法です。

  • gobgpdを起動します
$ cd $GOPATH/bin
$ sudo ./gobgpd -l debug -p
INFO[0000] gobgpd started
  • gobgpコマンドから、Global情報を設定します
$ gobgp global as 65000 router-id 192.168.0.1
  • gobgpコマンドから、BGP Peer情報を設定します
$ gobgp neighbor add 192.168.0.2 as 65000
  • 先ほど起動したgobgpdプロセスのログ出力を確認しておきます
$ sudo ./gobgpd -l debug -p
INFO[0000] gobgpd started
INFO[0007] Add a peer configuration for 192.168.0.2
DEBU[0007] IdleHoldTimer expired                         Duration=0 Key=192.168.0.2 Topic=Peer
DEBU[0007] state changed                                 Key=192.168.0.2 Topic=Peer new=BGP_FSM_ACTIVE old=BGP_FSM_IDLE reason=idle-hold-timer-expired
DEBU[0012] accepted a new passive connection from 192.168.0.2
DEBU[0012] state changed                                 Key=192.168.0.2 Topic=Peer new=BGP_FSM_OPENSENT old=BGP_FSM_ACTIVE reason=new-connection
DEBU[0012] state changed                                 Key=192.168.0.2 Topic=Peer new=BGP_FSM_OPENCONFIRM old=BGP_FSM_OPENSENT reason=open-msg-received
INFO[0012] Peer Up                                       Key=192.168.0.2 State=BGP_FSM_OPENCONFIRM Topic=Peer
DEBU[0012] state changed                                 Key=192.168.0.2 Topic=Peer new=BGP_FSM_ESTABLISHED old=BGP_FSM_OPENCONFIRM reason=open-msg-negotiated
DEBU[0012] received update                               Key=192.168.0.2 Topic=Peer attributes=[{Origin: ?}  {Nexthop: 192.168.0.2} {LocalPref: 100}] nlri=[20.20.20.0/24] withdrawals=[]
DEBU[0012] create Destination                            Key=20.20.20.0/24 Topic=Table
DEBU[0012] Processing destination                        Key=20.20.20.0/24 Topic=table
DEBU[0012] computeKnownBestPath known pathlist: 1
DEBU[0012] From same AS, ignore.                         Data={ 20.20.20.0/24 | src: { 192.168.0.2 | as: 65000, id: 192.168.0.2 }, nh: 192.168.0.2 } Key=192.168.0.2 Topic=Peer
DEBU[0042] sent                                          Key=192.168.0.2 State=BGP_FSM_ESTABLISHED Topic=Peer data=&{Header:{Marker:[] Len:19 Type:4} Body:0x1234d78}
DEBU[0072] sent                                          Key=192.168.0.2 State=BGP_FSM_ESTABLISHED Topic=Peer data=&{Header:{Marker:[] Len:19 Type:4} Body:0x1234d78}
DEBU[0102] sent                                          Key=192.168.0.2 State=BGP_FSM_ESTABLISHED Topic=Peer data=&{Header:{Marker:[] Len:19 Type:4} Body:0x1234d78}
  • gobgpコマンドから、Peer情報を確認してみます
$ gobgp neighbor 192.168.0.2
BGP neighbor is 192.168.0.2, remote AS 65000
  BGP version 4, remote router ID 192.168.0.2
  BGP state = BGP_FSM_ESTABLISHED, up for 00:03:29
  BGP OutQ = 0, Flops = 0
  Hold time is 90, keepalive interval is 30 seconds
  Configured hold time is 90, keepalive interval is 30 seconds
  Neighbor capabilities:
    BGP_CAP_MULTIPROTOCOL:
        ipv4-unicast:   advertised and received
        l2vpn-evpn:     received
    BGP_CAP_ROUTE_REFRESH:      advertised and received
    BGP_CAP_FOUR_OCTET_AS_NUMBER:       advertised and received
  Message statistics:
                         Sent       Rcvd
    Opens:                  1          1
    Notifications:          0          0
    Updates:                0          1
    Keepalives:             7          7
    Route Refesh:           0          0
    Discarded:              0          0
    Total:                  8          9
  Route statistics:
    Advertised:             0
    Received:               1
    Accepted:               1
  • gobgpコマンドから、rib情報を確認してみます
$ gobgp global rib 
    Network             Next Hop             AS_PATH              Age        Attrs
*>  20.20.20.0/24       192.168.0.2                               00:04:38   [{Origin: ?} {LocalPref: 100}]

(GoBGP起動方法3) "GoBGP as a Go Native BGP library"活用により、BGPピアを開設してみる

最後の起動方法として、全く馴染みがない"GoBGP as a Go Native BGP library"を活用して、GoBGPを起動してみます。

  • 事前に、サンプルコードを準備しておきます
$HOME/golang/bin/example_code.go
package main

import (
    log "github.com/Sirupsen/logrus"
    api "github.com/osrg/gobgp/api"
    "github.com/osrg/gobgp/gobgp/cmd"
    "github.com/osrg/gobgp/packet/bgp"
    gobgp "github.com/osrg/gobgp/server"
)

func main() {
    log.SetLevel(log.DebugLevel)
    s := gobgp.NewBgpServer()
    go s.Serve()

    // start grpc api server. this is not mandatory
    // but you will be able to use `gobgp` cmd with this.
    g := gobgp.NewGrpcServer(":50051", s.GrpcReqCh)
    go g.Serve()

    // global configuration
    req := gobgp.NewGrpcRequest(gobgp.REQ_START_SERVER, "", bgp.RouteFamily(0), &api.StartServerRequest{
        Global: &api.Global{
            As:         65000,
            RouterId:   "192.168.0.1",
            ListenPort: -1, // gobgp won't listen on tcp:179
        },
    })
    s.GrpcReqCh <- req
    res := <-req.ResponseCh
    if err := res.Err(); err != nil {
        log.Fatal(err)
    }

    // neighbor configuration
    req = gobgp.NewGrpcRequest(gobgp.REQ_GRPC_ADD_NEIGHBOR, "", bgp.RouteFamily(0), &api.AddNeighborRequest{
        Peer: &api.Peer{
            Conf: &api.PeerConf{
                NeighborAddress: "192.168.0.2",
                PeerAs:          65000,
            },
            Transport: &api.Transport{
                LocalAddress: "192.168.0.1",
            },
        },
    })
    s.GrpcReqCh <- req
    res = <-req.ResponseCh
    if err := res.Err(); err != nil {
        log.Fatal(err)
    }

    // monitor new routes
    req = gobgp.NewGrpcRequest(gobgp.REQ_MONITOR_RIB, "", bgp.RF_IPv4_UC, &api.Table{
        Type: api.Resource_GLOBAL,
    })
    s.GrpcReqCh <- req
    for res := range req.ResponseCh {
        p, _ := cmd.ApiStruct2Path(res.Data.(*api.Destination).Paths[0])
        cmd.ShowRoute(p, false, false, false, true, false)
    }
}
  • example codeを起動します
$ cd $GOPATH/bin
$ go run example_code.go 
INFO[0000] Add a peer configuration for 192.168.0.2     
DEBU[0000] IdleHoldTimer expired                         Duration=0 Key=192.168.0.2 Topic=Peer
DEBU[0000] state changed                                 Key=192.168.0.2 Topic=Peer new=BGP_FSM_ACTIVE old=BGP_FSM_IDLE reason=idle-hold-timer-expired
DEBU[0010] state changed                                 Key=192.168.0.2 Topic=Peer new=BGP_FSM_OPENSENT old=BGP_FSM_ACTIVE reason=new-connection
DEBU[0010] state changed                                 Key=192.168.0.2 Topic=Peer new=BGP_FSM_OPENCONFIRM old=BGP_FSM_OPENSENT reason=open-msg-received
INFO[0010] Peer Up                                       Key=192.168.0.2 State=BGP_FSM_OPENCONFIRM Topic=Peer
DEBU[0010] state changed                                 Key=192.168.0.2 Topic=Peer new=BGP_FSM_ESTABLISHED old=BGP_FSM_OPENCONFIRM reason=open-msg-negotiated
DEBU[0010] received update                               Key=192.168.0.2 Topic=Peer attributes=[{Origin: ?}  {Nexthop: 192.168.0.2} {LocalPref: 100}] nlri=[20.20.20.0/24] withdrawals=[]
DEBU[0010] create Destination                            Key=20.20.20.0/24 Topic=Table
DEBU[0010] Processing destination                        Key=20.20.20.0/24 Topic=table
DEBU[0010] computeKnownBestPath known pathlist: 1       
DEBU[0010] From same AS, ignore.                         Data={ 20.20.20.0/24 | src: { 192.168.0.2 | as: 65000, id: 192.168.0.2 }, nh: 192.168.0.2 } Key=192.168.0.2 Topic=Peer
[ROUTE] 20.20.20.0/24 via 192.168.0.2 aspath [] attrs [{Origin: ?} {LocalPref: 100}]
DEBU[0040] sent                                          Key=192.168.0.2 State=BGP_FSM_ESTABLISHED Topic=Peer data=&{Header:{Marker:[] Len:19 Type:4} Body:0x1148878}
DEBU[0070] sent                                          Key=192.168.0.2 State=BGP_FSM_ESTABLISHED Topic=Peer data=&{Header:{Marker:[] Len:19 Type:4} Body:0x1148878}
DEBU[0100] sent                                          Key=192.168.0.2 State=BGP_FSM_ESTABLISHED Topic=Peer data=&{Header:{Marker:[] Len:19 Type:4} Body:0x1148878}
  • gobgpコマンドから、Peer情報を確認してみます
$ gobgp neighbor 192.168.0.2
BGP neighbor is 192.168.0.2, remote AS 65000
  BGP version 4, remote router ID 192.168.0.2
  BGP state = BGP_FSM_ESTABLISHED, up for 00:02:13
  BGP OutQ = 0, Flops = 0
  Hold time is 90, keepalive interval is 30 seconds
  Configured hold time is 90, keepalive interval is 30 seconds
  Neighbor capabilities:
    BGP_CAP_MULTIPROTOCOL:
        ipv4-unicast:   advertised and received
        l2vpn-evpn:     received
    BGP_CAP_ROUTE_REFRESH:      advertised and received
    BGP_CAP_FOUR_OCTET_AS_NUMBER:       advertised and received
  Message statistics:
                         Sent       Rcvd
    Opens:                  1          1
    Notifications:          0          0
    Updates:                0          1
    Keepalives:             5          5
    Route Refesh:           0          0
    Discarded:              0          0
    Total:                  6          7
  Route statistics:
    Advertised:             0
    Received:               1
    Accepted:               1
  • gobgpコマンドから、rib情報を確認してみます
$ gobgp global rib 
    Network             Next Hop             AS_PATH              Age        Attrs
*>  20.20.20.0/24       192.168.0.2                               00:02:48   [{Origin: ?} {LocalPref: 100}]

以上、3つのGoBGP起動方法を試してみました。GoBGP動作結果を比較してみると、概ね、どれも同じ結果になりました。

◼︎ GoBGP起動方法を、DeepDiveしてみる

gobgpdは、"grpcServer"と"bgpServer"から構成されていて、実際のBGP動作に関わる機能ブロックは、"bgpServer"が担っています。そして、BGPピア開設に必要な設定情報を"bgpServer"に伝えるためには、"GrpcReqCh"チャネルを経由することになります。

各々のGoBGP起動方法の全体動作イメージを、簡単にまとめてみました。

(1) gobgp設定ファイルからのBGP Peer設定

GoBGP設定ファイルを、gobgpd起動時に取り込んで、"GrpcReqCh"チャネルに渡してあげると、"bgpServer"は、BGP開設処理が行わるようです。
なお、別途、"grpcServer"も起動しているので、gobgpコマンドから、bgpServer動作状態を確認することも可能です。

goBGP Deep Dive.005.jpeg

(2) gobgpコマンドからのBGP Peer設定

gobgpコマンドで投入された情報は、grpc経由で、gobgpdに伝えられることになります。
そして、"GrpcReqCh"チャネルに渡してあげると、"bgpServer"は、BGP開設処理が行わるようです。

goBGP Deep Dive.006.jpeg

(3) "GoBGP as a Go Native BGP library"活用によるBGP Peer設定

こちらは、Example Codeから、直接"GrpcReqCh"チャネルに渡してあげると、"bgpServer"は、BGP開設処理が行わるようです。
なお、別途、"grpcServer"も起動しているので、gobgpコマンドから、bgpServer動作状態を確認することも可能です。

goBGP Deep Dive.007.jpeg

どのGoBGP起動方法でも、動作原理は、共通している印象がありますね。

◼︎ 最後に、、、

GoBGPのオプション機能"GoBGP as a Go Native BGP library"では、BGP処理に関わるAPIリファレンス的なドキュメントは、一切、提供されていません。GoBGPコードリーディングを通じて、内部動作を理解しながら、カスタマイズ方法を模索していく必要があるのが、難点ですね。
しかしながら、APIリファレンス的な作法を克服してしまえば、GoBGPを自分の好みに応じて、自由にカスタマイズできますというメリットがあります。
まぁ、使い手の判断に委ねられるところですかね。

10
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10
5