kakkotetsu

vQFX10000 で VXLAN+EVPN (evpn-inter-subnet-forwarding(Symmetric) 編) (original : 2017/01/09)

この記事は某所で 2017/01/09 に書いたもののコピーです。
そのため 2017/05/13 時点ではやや古い情報も含まれています。(以下一例)

  • 201705 に GNS3 ver2.0 stable が出た

.

最初に

先日(vQFX10000 を KVM+GNS3 で動かす)、Juniper vQFX10000(以降 vQFX) の DL 権限を個人で得て GNS3 で軽く動作確認をとり、前回(vQFX10000 で VXLAN+EVPN (L2 over L3 編))、仮想版でも L2VPN 機能が動くことを確認しました。
QFX10000系では EVPN NLRI Type5 Route (参考資料の draft 参照)で Symmetric な evpn-inter-subnet-forwarding ができるようなので、今回は vQFX でそれを試します。(あらすじが長い...)

本項でやること

  • vQFX で VXLAN の Control Plane として EVPN を動かす
  • EVPN NLRI Type5(EVPN Prefix Advertisement) を使って evpn-inter-subnet-forwarding (Symmetric)を動かす
  • 前回の NLRI Type2+3 を使った L2 over L3 も併用できるか確認する
    • 下図の赤い点線部分
    • Type5 を使って VRFtoVRF しているドキュメントでは「セグメントが単一サイト(/部屋)に閉じる場合には」という文言があったりするけれど

f:id:kakkotetsu:20170513134936p:plain

概要構成図

前回に引き続き、下図の感じで。

f:id:kakkotetsu:20170513135024p:plain

余談。
本環境の GNS3 1.5.2 でパケットキャプチャするために、qemu 同士を直結せずに、間に GNS3 の Ethernet Switch を挟む構成にしてます。が、「pelican@ainoniwa.net / GNS3 2.0からはKVM間のパケットキャプチャも取れるようになるぞい」のように GNS3 2.0(2017/01/04 時点では beta 版, 2017/05/13時点ではstable版公開済)を使えば、これが不要になります。やったぜ!

参考資料

構築~動作確認

GNS3 でデプロイ

前回の環境を引き続き使います。先にあげた概要構成図の通り。

疎通確認用 node 設定

以下のような感じで

kotetsu@node11:~$ ip a show dev ens4
3: ens4: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 00:37:c4:e2:60:01 brd ff:ff:ff:ff:ff:ff
    inet 192.168.1.1/24 brd 192.168.1.255 scope global ens4
       valid_lft forever preferred_lft forever
    inet6 fe80::237:c4ff:fee2:6001/64 scope link
       valid_lft forever preferred_lft forever

kotetsu@node11:~$ ip route show dev ens4
192.168.0.0/16 via 192.168.1.254
192.168.1.0/24  proto kernel  scope link  src 192.168.1.1
kotetsu@node21:~$ ip a show dev ens4
3: ens4: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 00:37:c4:46:d8:01 brd ff:ff:ff:ff:ff:ff
    inet 192.168.1.2/24 brd 192.168.1.255 scope global ens4
       valid_lft forever preferred_lft forever
    inet6 fe80::237:c4ff:fe46:d801/64 scope link
       valid_lft forever preferred_lft forever

kotetsu@node21:~$ ip route show dev ens4
192.168.0.0/16 via 192.168.1.254
192.168.1.0/24  proto kernel  scope link  src 192.168.1.2
kotetsu@node22:~$ ip a show dev ens4
3: ens4: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 00:37:c4:3d:e0:01 brd ff:ff:ff:ff:ff:ff
    inet 192.168.2.2/24 brd 192.168.2.255 scope global ens4
       valid_lft forever preferred_lft forever
    inet6 fe80::237:c4ff:fe3d:e001/64 scope link
       valid_lft forever preferred_lft forever

kotetsu@node22:~$ ip route show dev ens4
192.168.0.0/16 via 192.168.2.254
192.168.2.0/24  proto kernel  scope link  src 192.168.2.2
kotetsu@node13:~$ ip a show dev ens4
3: ens4: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 00:37:c4:0d:a8:01 brd ff:ff:ff:ff:ff:ff
    inet 192.168.3.1/24 brd 192.168.3.255 scope global ens4
       valid_lft forever preferred_lft forever
    inet6 fe80::237:c4ff:fe0d:a801/64 scope link
       valid_lft forever preferred_lft forever

kotetsu@node13:~$ ip route show dev ens4
192.168.0.0/16 via 192.168.3.254
192.168.3.0/24  proto kernel  scope link  src 192.168.3.1

vQFX 基本設定ちょいたし

EVPN にこんな設定をして /var/log/evpn.log で追えるようにしときました。flag all にしたらちょっと追いきれない情報量になったので、そこはお好みで...。

set protocols evpn traceoptions file evpn.log
set protocols evpn traceoptions file size 10k
set protocols evpn traceoptions file files 30
set protocols evpn traceoptions flag all

vQFX Inter Subnet Forwarding 設定~確認

Inter Subnet Forwarding 設定

spine11

前回こんな感じの設定を入れてあったので

{master:0}[edit]
kotetsu@spine11# show vlans | display set
set vlans VLAN0100 vlan-id 100
set vlans VLAN0100 vxlan vni 10100
set vlans VLAN0100 vxlan ingress-node-replication
set vlans VLAN0300 vlan-id 300
set vlans VLAN0300 vxlan vni 10300
set vlans VLAN0300 vxlan ingress-node-replication
set vlans default vlan-id 1

以下で IRB 作成 ~ VRF 作成

set interfaces irb unit 100 family inet address 192.168.1.254/24
set interfaces irb unit 100 proxy-macip-advertisement

set interfaces irb unit 300 family inet address 192.168.3.254/24
set interfaces irb unit 300 proxy-macip-advertisement

set vlans VLAN0100 l3-interface irb.100
set vlans VLAN0300 l3-interface irb.300


set interfaces lo0 unit 1 family inet address 198.18.1.11/32

set routing-instances VRF001 instance-type vrf
set routing-instances VRF001 interface irb.100
set routing-instances VRF001 interface irb.300
set routing-instances VRF001 interface lo0.1
set routing-instances VRF001 route-distinguisher 50001:11
set routing-instances VRF001 vrf-target target:64512:50001
set routing-instances VRF001 protocols evpn ip-prefix-routes advertise direct-nexthop
set routing-instances VRF001 protocols evpn ip-prefix-routes encapsulation vxlan
set routing-instances VRF001 protocols evpn ip-prefix-routes vni 50001

ポイントは protocols evpn ip-prefix-routes 周りの設定ですね。
これで VRF to VRF で EVPN NLRI Type5 で IP Prefix や自分の MAC アドレス(Router's MAC) を送信できるようになるはず。

Juniper公式 / ReleaseNotes Junos 15.1X53-D60 for QFX10000 Switches の 19 ページによると

Best practice for EVPN-VXLAN configuration (QFX10000 switches)—Starting with Junos OS Release 15.1X53-D60, in an EVPN-VXLAN configuration on QFX10000 switches, you no longer need to configure vxlan ingress-node-replication.

だそうな。なんでだろ。とにかく Best Practice なら従っておくのがよかろうということで。

delete vlans VLAN0100 vxlan ingress-node-replication
delete vlans VLAN0300 vxlan ingress-node-replication

これを消さずにテストしていた時、なんか EVPN NLRI Type3 を送ってきていない Remote VTEP と VNI の組み合わせに対して BUM を ingress replication 転送してたんだよな...ということで消すのが正解と思います。

あと自分の環境起因かもですが、この辺の設定追加・変更して commit した時に、bb01 と spine[12]1 の間で LLDP や BGP がフラッピングし始めることがありました。ちゃんと追ってないですが、そんな時にはおとなしく request system reboot して落ち着かせました。(雑)

spine21

spine11 とほとんど一緒です。

前回こんな感じの設定を入れてあったので

{master:0}[edit]
kotetsu@spine21# show vlans | display set
set vlans VLAN0100 vlan-id 100
set vlans VLAN0100 vxlan vni 10100
set vlans VLAN0100 vxlan ingress-node-replication
set vlans VLAN0200 vlan-id 200
set vlans VLAN0200 vxlan vni 10200
set vlans VLAN0200 vxlan ingress-node-replication
set vlans default vlan-id 1

以下で IRB 作成 ~ VRF 作成

set interfaces irb unit 100 family inet address 192.168.1.254/24
set interfaces irb unit 100 proxy-macip-advertisement
set interfaces irb unit 200 family inet address 192.168.2.254/24
set interfaces irb unit 200 proxy-macip-advertisement

set vlans VLAN0100 l3-interface irb.100
set vlans VLAN0200 l3-interface irb.200

set interfaces lo0 unit 1 family inet address 198.18.1.21/32

set routing-instances VRF001 instance-type vrf
set routing-instances VRF001 interface irb.100
set routing-instances VRF001 interface irb.200
set routing-instances VRF001 interface lo0.1
set routing-instances VRF001 route-distinguisher 50001:21
set routing-instances VRF001 vrf-target target:64512:50001
set routing-instances VRF001 protocols evpn ip-prefix-routes advertise direct-nexthop
set routing-instances VRF001 protocols evpn ip-prefix-routes encapsulation vxlan
set routing-instances VRF001 protocols evpn ip-prefix-routes vni 50001

前述の通り Best Practice に従っておく。

delete vlans VLAN0100 vxlan ingress-node-replication
delete vlans VLAN0200 vxlan ingress-node-replication

動作確認

IPアドレスMACアドレス情報 整理

ちょっとノード数が増えてきたので、まとめときます。

VLAN IPアドレス MACアドレス ノード インターフェース 備考
100 192.168.1.1/24 00:37:c4:e2:60:01 node11 ens4 spine11 配下
100 192.168.1.2/24 00:37:c4:46:d8:01 node21 ens4 spine21 配下
100 192.168.1.254/24 02:05:86:71:3c:00 spine11 irb
100 192.168.1.254/24 02:05:86:71:d8:00 spine21 irb
200 192.168.2.2/24 00:37:c4:3d:e0:01 node22 ens4 spine21 配下
200 192.168.2.254/24 02:05:86:71:d8:00 spine21 irb
300 192.168.3.1/24 00:37:c4:0d:a8:01 node13 ens4 spine11 配下
300 192.168.3.254/24 02:05:86:71:3c:00 spine11 irb
- 192.0.2.1/30 02:05:86:71:21:03 bb01 xe-0/0/0 spine21
- 192.0.2.2/30 02:05:86:71:3c:03 spine11 xe-0/0/0 bb01
- 192.0.2.5/30 02:05:86:71:21:07 bb01 xe-0/0/1 spine21
- 192.0.2.6/30 02:05:86:71:d8:03 spine21 xe-0/0/0 bb01

spine11 と spine21 の IRB MAC アドレス at VLAN100 は各物理のものになっていて、共有用の仮想 MAC を設定したりはしていないです。
spine11 配下の node11 は spine11 の IRB MACアドレスゲートウェイとして使い、spine21 配下の node21 は spine21 の IRB MACアドレスゲートウェイとして使う...ってな動きになるのか、を見ようという主旨。

node間疎通確認~ARPテーブル確認

4 台の node 間をフルメッシュに ping 簡易疎通確認、とりあえず疎通オールおっけー。
直後 ARP テーブル確認

  • node11(192.168.1.1/24)
kotetsu@node11:~$ ip n show dev ens4
192.168.1.254 lladdr 02:05:86:71:3c:00 REACHABLE  ## spine11 IRB の MACaddr
192.168.1.2 lladdr 00:37:c4:46:d8:01 STALE
  • node21(192.168.1.2/24)
kotetsu@node21:~$ ip n show dev ens4
192.168.1.254 lladdr 02:05:86:71:d8:00 REACHABLE  ## spine21 IRB の MACaddr
192.168.1.1 lladdr 00:37:c4:e2:60:01 REACHABLE
  • node13(192.168.3.1/24)
kotetsu@node13:~$ ip n show dev ens4
192.168.3.254 lladdr 02:05:86:71:3c:00 STALE  ## spine11 IRB の MACaddr
  • node22(192.168.2.2/24)
kotetsu@node22:~$ ip n show dev ens4
192.168.2.254 lladdr 02:05:86:71:d8:00 REACHABLE  ## spine21 IRB の MACaddr

ちなみに spine11 や spine12 から ping を実行しようとしたら、自発パケットを EVPN 方面には流られないっぽいです。そりゃあそうか。

{master:0}
kotetsu@spine21> ping routing-instance VRF001 192.168.1.2
PING 192.168.1.2 (192.168.1.2): 56 data bytes
64 bytes from 192.168.1.2: icmp_seq=0 ttl=64 time=6.448 ms
64 bytes from 192.168.1.2: icmp_seq=1 ttl=64 time=5.700 ms

{master:0}
kotetsu@spine21> ping routing-instance VRF001 192.168.3.1
PING 192.168.3.1 (192.168.3.1): 56 data bytes
ping: sendto: Operation not supported
ping: sendto: Operation not supported


{master:0}
kotetsu@spine21> show route table VRF001.inet.0 192.168.3.0/24

VRF001.inet.0: 8 destinations, 9 routes (8 active, 0 holddown, 0 hidden)
+ = Active Route, - = Last Active, * = Both

192.168.3.0/24     *[EVPN/170] 20:55:03
                    > to 192.0.2.5 via xe-0/0/0.0

パッと見は巧いこと通信できているようですが...ちょっと中身を追っていきます。

vQFXテーブル確認

EVPN

両方の spine につくっている VLAN100(VNI 10100)の MAC 情報だけが Remote から学習したものに含まれ...ってやはり Router's MAC として 192.168.1.254 の実 MAC 2 台分を学習している。

{master:0}
kotetsu@spine11> show evpn database
Instance: default-switch
VLAN  VNI  MAC address        Active source                  Timestamp        IP address
      10100 00:37:c4:46:d8:01  172.16.2.1                     Jan 08 21:35:56
      10100 00:37:c4:e2:60:01  xe-0/0/1.0                     Jan 08 01:30:42  192.168.1.1
      10100 02:05:86:71:3c:00  irb.100                        Jan 08 12:50:23  192.168.1.254
      10100 02:05:86:71:d8:00  172.16.2.1                     Jan 08 12:50:38  192.168.1.254
      10300 00:37:c4:0d:a8:01  xe-0/0/1.0                     Jan 08 01:30:41  192.168.3.1
      10300 02:05:86:71:3c:00  irb.300                        Jan 08 01:27:27  192.168.3.254
{master:0}
kotetsu@spine21> show evpn database
Instance: default-switch
VLAN  VNI  MAC address        Active source                  Timestamp        IP address
      10100 00:37:c4:46:d8:01  xe-0/0/1.0                     Jan 08 01:30:41  192.168.1.2
      10100 00:37:c4:e2:60:01  172.16.1.1                     Jan 08 21:42:10  192.168.1.1
      10100 02:05:86:71:3c:00  172.16.1.1                     Jan 08 12:53:48  192.168.1.254
      10100 02:05:86:71:d8:00  irb.100                        Jan 08 12:54:02  192.168.1.254
      10200 00:37:c4:3d:e0:01  xe-0/0/1.0                     Jan 08 01:30:41  192.168.2.2
      10200 02:05:86:71:d8:00  irb.200                        Jan 08 01:16:21  192.168.2.254

自分が吐いている Type5 情報サマリ

{master:0}
kotetsu@spine11> show evpn l3-context
L3 context                      Type  Adv      Encap  VNI/Label  Router MAC/GW intf
VRF001                          Cfg   Direct   VXLAN  50001      02:05:86:71:3c:00
{master:0}
kotetsu@spine21> show evpn l3-context
L3 context                      Type  Adv      Encap  VNI/Label  Router MAC/GW intf
VRF001                          Cfg   Direct   VXLAN  50001      02:05:86:71:d8:00

Remote から Type 5 で学習した Router's MAC を確認して

{master:0}
kotetsu@spine11> show evpn ip-prefix-database
L3 context: VRF001

IPv4->EVPN Exported Prefixes
Prefix                                       EVPN route status
192.168.1.0/24                               Created
192.168.3.0/24                               Created

EVPN->IPv4 Imported Prefixes
Prefix                                       Etag      IP route status
192.168.1.0/24                               0         Created
  Route distinguisher    St  VNI/Label  Router MAC         Nexthop/Overlay GW/ESI
  50001:21               A   50001      02:05:86:71:d8:00  172.16.2.1
192.168.2.0/24                               0         Created
  Route distinguisher    St  VNI/Label  Router MAC         Nexthop/Overlay GW/ESI
  50001:21               A   50001      02:05:86:71:d8:00  172.16.2.1
{master:0}
kotetsu@spine21> show evpn ip-prefix-database
L3 context: VRF001

IPv4->EVPN Exported Prefixes
Prefix                                       EVPN route status
192.168.1.0/24                               Created
192.168.2.0/24                               Created

EVPN->IPv4 Imported Prefixes
Prefix                                       Etag      IP route status
192.168.1.0/24                               0         Created
  Route distinguisher    St  VNI/Label  Router MAC         Nexthop/Overlay GW/ESI
  50001:11               A   50001      02:05:86:71:3c:00  172.16.1.1
192.168.3.0/24                               0         Created
  Route distinguisher    St  VNI/Label  Router MAC         Nexthop/Overlay GW/ESI
  50001:11               A   50001      02:05:86:71:3c:00  172.16.1.1

Routing Table

当該 VRF の Routing Table サマリーを見て

{master:0}
kotetsu@spine11> show route instance VRF001 extensive
VRF001:
  Router ID: 198.18.1.11
  Type: vrf               State: Active
  Interfaces:
    irb.100
    irb.300
    lo0.1
  Route-distinguisher: 50001:11
  Vrf-import: [ __vrf-import-VRF001-internal__ ]
  Vrf-export: [ __vrf-export-VRF001-internal__ ]
  Vrf-import-target: [ target:64512:50001 ]
  Vrf-export-target: [ target:64512:50001 ]
  Fast-reroute-priority: low
  Tables:
    VRF001.inet.0          : 9 routes (8 active, 0 holddown, 0 hidden)
    VRF001.inet.3          : 0 routes (0 active, 0 holddown, 0 hidden)
    VRF001.iso.0           : 0 routes (0 active, 0 holddown, 0 hidden)
    VRF001.inet6.0         : 0 routes (0 active, 0 holddown, 0 hidden)
    VRF001.inet6.3         : 0 routes (0 active, 0 holddown, 0 hidden)
    VRF001.mdt.0           : 0 routes (0 active, 0 holddown, 0 hidden)
    VRF001.evpn.0          : 4 routes (4 active, 0 holddown, 0 hidden)
{master:0}
kotetsu@spine21> show route instance VRF001 extensive
VRF001:
  Router ID: 198.18.1.21
  Type: vrf               State: Active
  Interfaces:
    irb.100
    irb.200
    lo0.1
  Route-distinguisher: 50001:21
  Vrf-import: [ __vrf-import-VRF001-internal__ ]
  Vrf-export: [ __vrf-export-VRF001-internal__ ]
  Vrf-import-target: [ target:64512:50001 ]
  Vrf-export-target: [ target:64512:50001 ]
  Fast-reroute-priority: low
  Tables:
    VRF001.inet.0          : 9 routes (8 active, 0 holddown, 0 hidden)
    VRF001.inet.3          : 0 routes (0 active, 0 holddown, 0 hidden)
    VRF001.iso.0           : 0 routes (0 active, 0 holddown, 0 hidden)
    VRF001.inet6.0         : 0 routes (0 active, 0 holddown, 0 hidden)
    VRF001.inet6.3         : 0 routes (0 active, 0 holddown, 0 hidden)
    VRF001.mdt.0           : 0 routes (0 active, 0 holddown, 0 hidden)
    VRF001.evpn.0          : 4 routes (4 active, 0 holddown, 0 hidden)

中身のサマリをみる。まずは「bgp.evpn.0 = Junos OS ルーティング プロトコル プロセス(RPD)内のグローバル EVPN ルーティング テーブル」を

{master:0}
kotetsu@spine11> show route table bgp.evpn.0

bgp.evpn.0: 9 destinations, 9 routes (9 active, 0 holddown, 0 hidden)
+ = Active Route, - = Last Active, * = Both

1:172.16.2.1:0::050000fdea0000277400::FFFF:FFFF/304
                   *[BGP/170] 21:18:16, localpref 100, from 172.31.0.1
                      AS path: I, validation-state: unverified
                    > to 192.0.2.1 via xe-0/0/0.0
1:172.16.2.1:0::050000fdea000027d800::FFFF:FFFF/304
                   *[BGP/170] 21:18:16, localpref 100, from 172.31.0.1
                      AS path: I, validation-state: unverified
                    > to 192.0.2.1 via xe-0/0/0.0
2:64512:21::10100::00:37:c4:46:d8:01/304
                   *[BGP/170] 19:24:02, localpref 100, from 172.31.0.1
                      AS path: I, validation-state: unverified
                    > to 192.0.2.1 via xe-0/0/0.0
2:64512:21::10100::02:05:86:71:d8:00/304
                   *[BGP/170] 09:57:37, localpref 100, from 172.31.0.1
                      AS path: I, validation-state: unverified
                    > to 192.0.2.1 via xe-0/0/0.0
2:64512:21::10100::00:37:c4:46:d8:01::192.168.1.2/304
                   *[BGP/170] 09:36:35, localpref 100, from 172.31.0.1
                      AS path: I, validation-state: unverified
                    > to 192.0.2.1 via xe-0/0/0.0
2:64512:21::10100::00:37:c4:46:d8:01::192.168.1.2/304
                   *[BGP/170] 09:36:35, localpref 100, from 172.31.0.1
                      AS path: I, validation-state: unverified
                    > to 192.0.2.1 via xe-0/0/0.0
2:64512:21::10100::02:05:86:71:d8:00::192.168.1.254/304
                   *[BGP/170] 09:57:37, localpref 100, from 172.31.0.1
                      AS path: I, validation-state: unverified
                    > to 192.0.2.1 via xe-0/0/0.0
3:64512:21::10100::172.16.2.1/304
                   *[BGP/170] 19:24:02, localpref 100, from 172.31.0.1
                      AS path: I, validation-state: unverified
                    > to 192.0.2.1 via xe-0/0/0.0
5:50001:21::0::192.168.1.0::24/304
                   *[BGP/170] 21:18:16, localpref 100, from 172.31.0.1
                      AS path: I, validation-state: unverified
                    > to 192.0.2.1 via xe-0/0/0.0
5:50001:21::0::192.168.2.0::24/304
                   *[BGP/170] 21:18:16, localpref 100, from 172.31.0.1
                      AS path: I, validation-state: unverified
                    > to 192.0.2.1 via xe-0/0/0.0
{master:0}
kotetsu@spine21> show route table bgp.evpn.0

bgp.evpn.0: 9 destinations, 9 routes (9 active, 0 holddown, 0 hidden)
+ = Active Route, - = Last Active, * = Both

1:172.16.1.1:0::050000fde90000277400::FFFF:FFFF/304
                   *[BGP/170] 10:02:28, localpref 100, from 172.31.0.1
                      AS path: I, validation-state: unverified
                    > to 192.0.2.5 via xe-0/0/0.0
1:172.16.1.1:0::050000fde90000283c00::FFFF:FFFF/304
                   *[BGP/170] 21:26:18, localpref 100, from 172.31.0.1
                      AS path: I, validation-state: unverified
                    > to 192.0.2.5 via xe-0/0/0.0
2:64512:11::10100::00:37:c4:e2:60:01/304
                   *[BGP/170] 19:32:22, localpref 100, from 172.31.0.1
                      AS path: I, validation-state: unverified
                    > to 192.0.2.5 via xe-0/0/0.0
2:64512:11::10100::02:05:86:71:3c:00/304
                   *[BGP/170] 10:02:28, localpref 100, from 172.31.0.1
                      AS path: I, validation-state: unverified
                    > to 192.0.2.5 via xe-0/0/0.0
2:64512:11::10100::00:37:c4:e2:60:01::192.168.1.1/304
                   *[BGP/170] 10:01:04, localpref 100, from 172.31.0.1
                      AS path: I, validation-state: unverified
                    > to 192.0.2.5 via xe-0/0/0.0
2:64512:11::10100::02:05:86:71:3c:00::192.168.1.254/304
                   *[BGP/170] 10:02:28, localpref 100, from 172.31.0.1
                      AS path: I, validation-state: unverified
                    > to 192.0.2.5 via xe-0/0/0.0
3:64512:11::10100::172.16.1.1/304
                   *[BGP/170] 19:32:21, localpref 100, from 172.31.0.1
                      AS path: I, validation-state: unverified
                    > to 192.0.2.5 via xe-0/0/0.0
5:50001:11::0::192.168.1.0::24/304
                   *[BGP/170] 10:02:29, localpref 100, from 172.31.0.1
                      AS path: I, validation-state: unverified
                    > to 192.0.2.5 via xe-0/0/0.0
5:50001:11::0::192.168.3.0::24/304
                   *[BGP/170] 21:26:18, localpref 100, from 172.31.0.1
                      AS path: I, validation-state: unverified
                    > to 192.0.2.5 via xe-0/0/0.0

次に当該 VRF のさまりー

{master:0}
kotetsu@spine11> show route table VRF001.evpn.0

VRF001.evpn.0: 4 destinations, 4 routes (4 active, 0 holddown, 0 hidden)
+ = Active Route, - = Last Active, * = Both

5:50001:11::0::192.168.1.0::24/304
                   *[EVPN/170] 10:15:34
                      Indirect
5:50001:11::0::192.168.3.0::24/304
                   *[EVPN/170] 21:36:19
                      Indirect
5:50001:21::0::192.168.1.0::24/304
                   *[BGP/170] 21:35:58, localpref 100, from 172.31.0.1
                      AS path: I, validation-state: unverified
                    > to 192.0.2.1 via xe-0/0/0.0
5:50001:21::0::192.168.2.0::24/304
                   *[BGP/170] 21:35:58, localpref 100, from 172.31.0.1
                      AS path: I, validation-state: unverified
                    > to 192.0.2.1 via xe-0/0/0.0


{master:0}
kotetsu@spine11> show route table VRF001.inet.0

VRF001.inet.0: 8 destinations, 9 routes (8 active, 0 holddown, 0 hidden)
+ = Active Route, - = Last Active, * = Both

192.168.1.0/24     *[Direct/0] 10:11:26
                    > via irb.100
                    [EVPN/170] 21:31:50
                    > to 192.0.2.1 via xe-0/0/0.0
192.168.1.1/32     *[EVPN/7] 10:10:01
                    > via irb.100
192.168.1.254/32   *[Local/0] 10:11:27
                      Local via irb.100
192.168.2.0/24     *[EVPN/170] 21:31:50
                    > to 192.0.2.1 via xe-0/0/0.0
192.168.3.0/24     *[Direct/0] 21:32:11
                    > via irb.300
192.168.3.1/32     *[EVPN/7] 21:31:06
                    > via irb.300
192.168.3.254/32   *[Local/0] 21:34:23
                      Local via irb.300
198.18.1.11/32     *[Direct/0] 21:34:23
                    > via lo0.1
{master:0}
kotetsu@spine21> show route table VRF001.evpn.0

VRF001.evpn.0: 4 destinations, 4 routes (4 active, 0 holddown, 0 hidden)
+ = Active Route, - = Last Active, * = Both

5:50001:11::0::192.168.1.0::24/304
                   *[BGP/170] 10:19:12, localpref 100, from 172.31.0.1
                      AS path: I, validation-state: unverified
                    > to 192.0.2.5 via xe-0/0/0.0
5:50001:11::0::192.168.3.0::24/304
                   *[BGP/170] 21:43:01, localpref 100, from 172.31.0.1
                      AS path: I, validation-state: unverified
                    > to 192.0.2.5 via xe-0/0/0.0
5:50001:21::0::192.168.1.0::24/304
                   *[EVPN/170] 10:18:58
                      Indirect
5:50001:21::0::192.168.2.0::24/304
                   *[EVPN/170] 21:54:15
                      Indirect


{master:0}
kotetsu@spine21> show route table VRF001.inet.0

VRF001.inet.0: 8 destinations, 9 routes (8 active, 0 holddown, 0 hidden)
+ = Active Route, - = Last Active, * = Both

192.168.1.0/24     *[Direct/0] 10:16:27
                    > via irb.100
                    [EVPN/170] 10:16:41
                    > to 192.0.2.5 via xe-0/0/0.0
192.168.1.2/32     *[EVPN/7] 10:16:10
                    > via irb.100
192.168.1.254/32   *[Local/0] 10:16:27
                      Local via irb.100
192.168.2.0/24     *[Direct/0] 21:51:44
                    > via irb.200
192.168.2.2/32     *[EVPN/7] 21:39:37
                    > via irb.200
192.168.2.254/32   *[Local/0] 21:54:08
                      Local via irb.200
192.168.3.0/24     *[EVPN/170] 21:40:30
                    > to 192.0.2.5 via xe-0/0/0.0
198.18.1.21/32     *[Direct/0] 21:54:08
                    > via lo0.1

最後に Type 5 route の詳細を見ておく。こいつらは VRF001.evpn.0 にもロードされている。

{master:0}
kotetsu@spine11> show route table bgp.evpn.0 extensive

...

5:50001:21::0::192.168.1.0::24/304 (1 entry, 0 announced)
        *BGP    Preference: 170/-101
                Route Distinguisher: 50001:21
                Next hop type: Indirect, Next hop index: 0
                Address: 0xaa605f0
                Next-hop reference count: 18
                Source: 172.31.0.1
                Protocol next hop: 172.16.2.1
                Indirect next hop: 0x2 no-forward INH Session ID: 0x0
                State: <Active Int Ext>
                Local AS: 65001 Peer AS: 64512
                Age: 21:25:33   Metric2: 0
                Validation State: unverified
                Task: BGP_64512_64512.172.31.0.1
                AS path: I (Originator)
                Cluster list:  172.31.0.1
                Originator ID: 172.16.2.1
                Communities: target:64512:50001 encapsulation0:0:0:0:vxlan router-mac:02:05:86:71:d8:00
                Import Accepted
                Route Label: 50001
                Overlay gateway address: 0.0.0.0
                ESI 00:00:00:00:00:00:00:00:00:00
                Localpref: 100
                Router ID: 172.31.0.1
                Secondary Tables: VRF001.evpn.0
                Indirect next hops: 1
                        Protocol next hop: 172.16.2.1
                        Indirect next hop: 0x2 no-forward INH Session ID: 0x0
                        Indirect path forwarding next hops: 1
                                Next hop type: Router
                                Next hop: 192.0.2.1 via xe-0/0/0.0
                                Session Id: 0x0
                        172.16.2.1/32 Originating RIB: inet.0
                          Node path count: 1
                          Forwarding nexthops: 1
                                Nexthop: 192.0.2.1 via xe-0/0/0.0

5:50001:21::0::192.168.2.0::24/304 (1 entry, 0 announced)
        *BGP    Preference: 170/-101
                Route Distinguisher: 50001:21
                Next hop type: Indirect, Next hop index: 0
                Address: 0xaa605f0
                Next-hop reference count: 18
                Source: 172.31.0.1
                Protocol next hop: 172.16.2.1
                Indirect next hop: 0x2 no-forward INH Session ID: 0x0
                State: <Active Int Ext>
                Local AS: 65001 Peer AS: 64512
                Age: 21:25:33   Metric2: 0
                Validation State: unverified
                Task: BGP_64512_64512.172.31.0.1
                AS path: I (Originator)
                Cluster list:  172.31.0.1
                Originator ID: 172.16.2.1
                Communities: target:64512:50001 encapsulation0:0:0:0:vxlan router-mac:02:05:86:71:d8:00
                Import Accepted
                Route Label: 50001
                Overlay gateway address: 0.0.0.0
                ESI 00:00:00:00:00:00:00:00:00:00
                Localpref: 100
                Router ID: 172.31.0.1
                Secondary Tables: VRF001.evpn.0
                Indirect next hops: 1
                        Protocol next hop: 172.16.2.1
                        Indirect next hop: 0x2 no-forward INH Session ID: 0x0
                        Indirect path forwarding next hops: 1
                                Next hop type: Router
                                Next hop: 192.0.2.1 via xe-0/0/0.0
                                Session Id: 0x0
                        172.16.2.1/32 Originating RIB: inet.0
                          Node path count: 1
                          Forwarding nexthops: 1
                                Nexthop: 192.0.2.1 via xe-0/0/0.0
{master:0}
kotetsu@spine21> show route table bgp.evpn.0 extensive

...

5:50001:11::0::192.168.1.0::24/304 (1 entry, 0 announced)
        *BGP    Preference: 170/-101
                Route Distinguisher: 50001:11
                Next hop type: Indirect, Next hop index: 0
                Address: 0xaa60170
                Next-hop reference count: 18
                Source: 172.31.0.1
                Protocol next hop: 172.16.1.1
                Indirect next hop: 0x2 no-forward INH Session ID: 0x0
                State: <Active Int Ext>
                Local AS: 65002 Peer AS: 64512
                Age: 10:04:02   Metric2: 0
                Validation State: unverified
                Task: BGP_64512_64512.172.31.0.1
                AS path: I (Originator)
                Cluster list:  172.31.0.1
                Originator ID: 172.16.1.1
                Communities: target:64512:50001 encapsulation0:0:0:0:vxlan router-mac:02:05:86:71:3c:00
                Import Accepted
                Route Label: 50001
                Overlay gateway address: 0.0.0.0
                ESI 00:00:00:00:00:00:00:00:00:00
                Localpref: 100
                Router ID: 172.31.0.1
                Secondary Tables: VRF001.evpn.0
                Indirect next hops: 1
                        Protocol next hop: 172.16.1.1
                        Indirect next hop: 0x2 no-forward INH Session ID: 0x0
                        Indirect path forwarding next hops: 1
                                Next hop type: Router
                                Next hop: 192.0.2.5 via xe-0/0/0.0
                                Session Id: 0x0
                        172.16.1.1/32 Originating RIB: inet.0
                          Node path count: 1
                          Forwarding nexthops: 1
                                Nexthop: 192.0.2.5 via xe-0/0/0.0

5:50001:11::0::192.168.3.0::24/304 (1 entry, 0 announced)
        *BGP    Preference: 170/-101
                Route Distinguisher: 50001:11
                Next hop type: Indirect, Next hop index: 0
                Address: 0xaa60170
                Next-hop reference count: 18
                Source: 172.31.0.1
                Protocol next hop: 172.16.1.1
                Indirect next hop: 0x2 no-forward INH Session ID: 0x0
                State: <Active Int Ext>
                Local AS: 65002 Peer AS: 64512
                Age: 21:27:51   Metric2: 0
                Validation State: unverified
                Task: BGP_64512_64512.172.31.0.1
                AS path: I (Originator)
                Cluster list:  172.31.0.1
                Originator ID: 172.16.1.1
                Communities: target:64512:50001 encapsulation0:0:0:0:vxlan router-mac:02:05:86:71:3c:00
                Import Accepted
                Route Label: 50001
                Overlay gateway address: 0.0.0.0
                ESI 00:00:00:00:00:00:00:00:00:00
                Localpref: 100
                Router ID: 172.31.0.1
                Secondary Tables: VRF001.evpn.0
                Indirect next hops: 1
                        Protocol next hop: 172.16.1.1
                        Indirect next hop: 0x2 no-forward INH Session ID: 0x0
                        Indirect path forwarding next hops: 1
                                Next hop type: Router
                                Next hop: 192.0.2.5 via xe-0/0/0.0
                                Session Id: 0x0
                        172.16.1.1/32 Originating RIB: inet.0
                          Node path count: 1
                          Forwarding nexthops: 1
                                Nexthop: 192.0.2.5 via xe-0/0/0.0

MAC アドレステーブル

Type 2 から学習しているのは、両方の VTEP にくっつけている VLAN 100 = VNI 10100 のみ

{master:0}
kotetsu@spine11> show ethernet-switching table

MAC flags (S - static MAC, D - dynamic MAC, L - locally learned, P - Persistent static
           SE - statistics enabled, NM - non configured MAC, R - remote PE MAC, O - ovsdb MAC)


Ethernet switching table : 4 entries, 4 learned
Routing instance : default-switch
   Vlan                MAC                 MAC      Logical                Active
   name                address             flags    interface              source
   VLAN0100            00:37:c4:46:d8:01   D        vtep.32769             172.16.2.1
   VLAN0100            00:37:c4:e2:60:01   D        xe-0/0/1.0
   VLAN0100            02:05:86:71:d8:00   D        vtep.32769             172.16.2.1
   VLAN0300            00:37:c4:0d:a8:01   D        xe-0/0/1.0
{master:0}
kotetsu@spine21> show ethernet-switching table

MAC flags (S - static MAC, D - dynamic MAC, L - locally learned, P - Persistent static
           SE - statistics enabled, NM - non configured MAC, R - remote PE MAC, O - ovsdb MAC)


Ethernet switching table : 4 entries, 4 learned
Routing instance : default-switch
   Vlan                MAC                 MAC      Logical                Active
   name                address             flags    interface              source
   VLAN0100            00:37:c4:46:d8:01   D        xe-0/0/1.0
   VLAN0100            00:37:c4:e2:60:01   D        vtep.32769             172.16.1.1
   VLAN0100            02:05:86:71:3c:00   D        vtep.32769             172.16.1.1
   VLAN0200            00:37:c4:3d:e0:01   D        xe-0/0/1.0

通信確認詳細(DataPlane)

各通信の様子を見ていきます。それぞれ、実行前に sudo ip n flush dev ens4 とかしてます。

L3 Symmetric

node22(192.168.2.2/24) から node13(192.168.3.1/24) へ ping

以下、ICMP Echo request を spine21 と bb01 間で拾ったもの。
VXLANカプセル内の Eth ヘッダを見ると、Type5で学習した spine11 の irb MAC アドレスを Dst に指定されています。

f:id:kakkotetsu:20170513135437p:plain

なお、ICMP Echo Reply も同じ感じです。

L2 over L3

node21(192.168.1.2/24) から node11(192.168.1.1/24) へ ping

これは前回と同様に、単純に VNI 10100 でカプセル化されて通信しているだけ。

f:id:kakkotetsu:20170513135451p:plain

L3 往路 Symmetric 復路 Asymmetric

node11(192.168.1.1/24) から node22(192.168.2.2/24) へ ping

このケースが、どう動くのかイマイチ予測できなかったところです。

  1. 往路 node11 がゲートウェイIPアドレス(192.168.1.254) ARP 解決を試みる
  2. 往路 spine11 が node11 に 自身の irb MAC アドレスを答える (この時「自分が応答したので ARP request を VNI 10100 方面には転送しない」という動作になってくれるのか否かが予想できなかった & 確認したかった)
  3. 往路 spine11 は node11 からの Dst IP(192.168.2.2/24) な ICMP Echo request パケットを受信し、Type5 で得た情報に従い VNI 50001 でカプセル化して spine21 に投げる (Symmetric)
  4. 往路 spine21 は自分の irb direct 配下にいる node22 にフォワードするだけ
  5. 復路 node22 はゲートウェイIPアドレス(192.168.2.254)の ARP 解決をして、spine21 の irb MAC に ICMP Echo Reply 投げる
  6. 復路 spine21 は node22 からの Dst IP(192.168.1.1/24) な ICMP Echo Reply パケットを受信し、Type2 で得た情報に従い VNI 10100 でカプセル化して spine11 に投げる (Asymmetric)
  7. 復路 spine11 は自分の irb direct 配下にいる node11 にフォワードするだけ

という感じに予測して、行きと戻りの VNI が異なる論理的に非対称な通信でちゃんと成り立っているのか、っていうのと太字箇所を見ていきます。いやまあ疎通は確認済なんですが。

まず node11 で拾ったパケットを見ると...はい、上記の太字箇所は期待した動作になっていないですね。
spine11 と spine21 双方の irb から ARP Reply が来ていて(パケットNo.2と4)、たまたま node の仕様的に先に返ってきた spine11 側の MAC アドレスを使っていたに過ぎないようです。

f:id:kakkotetsu:20170513135515p:plain

上記の動作を、今度は spine11 と bb01 間で拾ったパケットで追ってみます。
このパケットNo.16 が「自分が node11 に ARP Reply した直後、ARP Request を VNI 10100 で spine21 方面に Ingress Replication している」やつです。

f:id:kakkotetsu:20170513135531p:plain

当然、spine21 側は通常通り ARP Reply を返してくれるし、それは先ほど node11 側で見た通り node11 にも伝搬されます。

f:id:kakkotetsu:20170513135549p:plain

ということで、ARP Request に対する Reply の動作確認は、自分が期待していたのと違う動きのようです。
構成や設定でどうにか巧いことならないか...ってところは深追いしていません。
(試しに spine[12]1 双方で set interfaces irb unit 100 mac 00:00:5e:00:53:99 とか virtual-gateway-address とか設定して同じ MAC アドレスを持たせてみたりはしましたが...それでも通信は可能だけれど、特に代表動作とかをしないIP/MAC重複状態なので、健全な状態とは言えないかと。)

あ、往路 VNI 50001, 復路 VNI 10100 に関しては、想定通りの動きでした。

f:id:kakkotetsu:20170513135633p:plain f:id:kakkotetsu:20170513135642p:plain

パケットキャプチャ(ControlPlane)

EVPN NLRI Type5 の UPDATE と WithDrawn を軽く見ておきます。

まずは WithDrawn を spine21 から吐かせた時(雑に deactivate routing-instance VRF001 とかで)

f:id:kakkotetsu:20170513135705p:plain f:id:kakkotetsu:20170513135712p:plain

UPDATE を spine21 から吐かせた時(雑に rollback 1 とかで)

f:id:kakkotetsu:20170513135726p:plain

おしまい

  • Juniper vQFX10000 でも EVPN NLRI Type5 が動くことを確認できました
  • VRF to VRF 動作と L2VPN を併用する場合、何らかの工夫が必要そうだということは分かりました
    • 「L3 往路 Symmetric 復路 Asymmetric」の項でウダウダ書いた通り
    • そもそも MX を使って MAC VRF 使う、のが常道なのかもしれませんが

vQFX10000 で VXLAN+EVPN (L2 over L3 編) (original : 2017/01/02)

この記事は某所で 2017/01/02 に書いた記事のコピーです。 そのため 2017/05/11 時点ではやや古い情報も含まれています。(以下一例)

  • Juniper さんの vQFX ダウンロード規約が変わっていそう (詳細は未確認)
  • 201705 に GNS3 ver2.0 stable が出たので KVM 間のパケットキャプチャ用に GNS3 のハブを挟む必要がなくなった

.

最初に

前回(vQFX10000 を KVM+GNS3 で動かす)、Juniper vQFX10000(以降 vQFX) の DL 権限を個人で得て GNS3 で軽く動作確認がとれました。 今回は「仮想版って L2全般/L2VPN 系機能が動かなかったりするけど、vQFX はどうなんだ?...お、EVPN もちゃんと動くやんけ!」ってところまでを見ていきます。

本項でやること

以下をやります。

個人的には、2014/12 時点で VXLAN のマルチキャスト実装を確認した時 (VyOS と Arista で VXLAN 相互接続)に微妙だと思った点にも着目しておきたいです。今回、データプレーン周りはほぼ同じ構成を組んでますので。

  • 上の記事の〆が「マルチキャストルーティングを勉強しよう。」だったのですが、この2年間以下のようにウダウダやっていて、特に進捗はありませんでした。
    • マルチキャスト?えー...?うーん...
    • え?OVSDB でゴリゴリ?あー...hmm...
    • あ?OVSDBを使ったコントローラ導入でユニキャスト?え?NSX?買えるかよ...
    • お?自前でコントローラ実装?ははぁ...
    • ん?MP-BGP使ったEVPN?いかにもネットワーク屋が考えそう&食いつきそうですねぇ...でもまあ釣られてみるかあ(今ここ)
  • 上の記事では VTEP 間の到達性をもたせるのに「VyOS が認識しないといけない Arista 側の VTEP IP アドレスは、Arista の Loopback アドレスになるので、StaticRoute を追加しておきます。#これだと拡張が面倒なので、実環境では DefaultRoute か動的ルーティングを使うことが多い気がします。」とか書いてますが、今回は実環境をある程度想定した例示ができそうです。

概要構成図 / 環境

以下のような構成を組んでいきます。node11 と node21 が L2overL3 で通信するやつです。

f:id:kakkotetsu:20170511232921p:plain

環境は、いずれも前回の通りです。

参考資料

前述の通り、各要素技術の詳細な解説は放棄していますが...こんなニッチな記事を読む人向けなので、まあね?

構築~動作確認

GNS3 で仮想マシンのデプロイ ~ 結線 ~ 起動

前回の通りに、3ペアの vQFX をデプロイして接続していきます。 以下の感じで。

f:id:kakkotetsu:20170511233004p:plain

torSW101atorSW201a というのは、GNS3Ethernet Switch を使っていますが、各環境に合わせて適当な dot1Q 食えるスイッチ置けば良いです。 設定はそれぞれ以下の感じです。(今回は Port 3-4 は使いませんが)

f:id:kakkotetsu:20170511233054p:plain

f:id:kakkotetsu:20170511233114p:plain

node11node21 は、インターフェースに IP アドレス付与するだけなので、適当な疎通確認用ノードなので好きなのをどうぞ。(node12node22 は今回使わないです)

あと captureSW というのは GNS3 1.5.2 では github gns3-gui issues | QEMU link Packet Captures の通り、qemu 同士の結線をパケットキャプチャできないので、「bb01 でポートミラーリング」する手法をとっているために置いているものです。
未試行ですが、RE 同士の結線をしている箇所(bb01spine[12]1)に全て Ethernet Switch を挟めば、ポートミラーリング不要でパケットキャプチャできると思います。(そちらの方がやりやすい筈)

できたら起動して待ちます。

基本設定

各環境に合わせて syslog なり NTP なり ssh key 登録なりしておいて下さい。 あ、今回は BGP のログを /var/log/bgp.log に残すために、以下をやっておくと良いですよ。

set protocols bgp traceoptions file bgp.log
set protocols bgp traceoptions file size 10k
set protocols bgp traceoptions file files 30
set protocols bgp traceoptions flag normal

Underlay 設定~確認 (物理IF と eBGP)

まずは物理 Interface と eBGP 周りを設定して、各 lo0 の IP アドレスを経路交換できたことを確認します。 まあ、長々となってしまいますが、絵にすると単純で以下のような感じです。

f:id:kakkotetsu:20170511233155p:plain

物理IF設定

bb01

set interfaces xe-0/0/0 description "DEV=spine11 IF=xe-0/0/0"
set interfaces xe-0/0/0 unit 0 family inet address 192.0.2.1/30
delete interfaces xe-0/0/0 unit 0 family inet dhcp

set interfaces xe-0/0/1 description "DEV=spine21 IF=xe-0/0/0"
set interfaces xe-0/0/1 unit 0 family inet address 192.0.2.5/30
delete interfaces xe-0/0/1 unit 0 family inet dhcp

set protocols lldp port-id-subtype interface-name
set protocols lldp interface xe-0/0/0
set protocols lldp interface xe-0/0/1

spine11

set interfaces xe-0/0/0 description "DEV=bb01 IF=xe-0/0/0"
set interfaces xe-0/0/0 unit 0 family inet address 192.0.2.2/30
delete interfaces xe-0/0/0 unit 0 family inet dhcp

set protocols lldp port-id-subtype interface-name
set protocols lldp interface xe-0/0/0

spine21

set interfaces xe-0/0/0 description "DEV=bb01 IF=xe-0/0/1"
set interfaces xe-0/0/0 unit 0 family inet address 192.0.2.6/30
delete interfaces xe-0/0/0 unit 0 family inet dhcp

set protocols lldp port-id-subtype interface-name
set protocols lldp interface xe-0/0/0

物理IF疎通確認

リソースをケチったからか RTT 長すぎですね...。

bb01

kotetsu@bb01> show lldp neighbors
Local Interface    Parent Interface    Chassis Id          Port info          System Name
xe-0/0/0           -                   02:05:86:71:84:00   DEV=bb01 IF=xe-0/0/0 spine11            
xe-0/0/1           -                   02:05:86:71:ff:00   DEV=bb01 IF=xe-0/0/1 spine21


kotetsu@bb01> show route

inet.0: 8 destinations, 8 routes (8 active, 0 holddown, 0 hidden)
+ = Active Route, - = Last Active, * = Both

10.0.0.0/24        *[Direct/0] 19:47:39
                    > via em0.0
10.0.0.191/32      *[Local/0] 19:47:39
                      Local via em0.0
169.254.0.0/24     *[Direct/0] 19:57:21
                    > via em1.0
169.254.0.2/32     *[Local/0] 19:57:21
                      Local via em1.0
192.0.2.0/30       *[Direct/0] 00:17:12
                    > via xe-0/0/0.0
192.0.2.1/32       *[Local/0] 00:17:12
                      Local via xe-0/0/0.0
192.0.2.4/30       *[Direct/0] 00:07:04
                    > via xe-0/0/1.0
192.0.2.5/32       *[Local/0] 00:07:04
                      Local via xe-0/0/1.0

inet6.0: 1 destinations, 1 routes (1 active, 0 holddown, 0 hidden)
+ = Active Route, - = Last Active, * = Both

fe80::286:2b0f:fc44:ab00/128
                   *[Direct/0] 19:56:54
                    > via lo0.0

{master:0}
kotetsu@bb01> ping 192.0.2.2
PING 192.0.2.2 (192.0.2.2): 56 data bytes
64 bytes from 192.0.2.2: icmp_seq=1 ttl=64 time=2420.112 ms
64 bytes from 192.0.2.2: icmp_seq=2 ttl=64 time=1027.245 ms
64 bytes from 192.0.2.2: icmp_seq=3 ttl=64 time=1525.667 ms
^C
--- 192.0.2.2 ping statistics ---
5 packets transmitted, 3 packets received, 40% packet loss
round-trip min/avg/max/stddev = 1027.245/1657.675/2420.112/576.246 ms

{master:0}
kotetsu@bb01> ping 192.0.2.6
PING 192.0.2.6 (192.0.2.6): 56 data bytes
64 bytes from 192.0.2.6: icmp_seq=0 ttl=64 time=3378.582 ms
64 bytes from 192.0.2.6: icmp_seq=1 ttl=64 time=1374.159 ms
64 bytes from 192.0.2.6: icmp_seq=2 ttl=64 time=1474.743 ms
^C
--- 192.0.2.6 ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max/stddev = 1374.159/2075.828/3378.582/922.101 ms

spine11

{master:0}
kotetsu@spine11> show lldp neighbors
Local Interface    Parent Interface    Chassis Id          Port info          System Name
xe-0/0/0           -                   02:05:86:71:55:00   DEV=spine11 IF=xe-0/0/0 bb01


{master:0}
kotetsu@spine11> show route

inet.0: 6 destinations, 6 routes (6 active, 0 holddown, 0 hidden)
+ = Active Route, - = Last Active, * = Both

10.0.0.0/24        *[Direct/0] 19:23:06
                    > via em0.0
10.0.0.201/32      *[Local/0] 19:23:06
                      Local via em0.0
169.254.0.0/24     *[Direct/0] 19:22:26
                    > via em1.0
169.254.0.2/32     *[Local/0] 19:22:26
                      Local via em1.0
192.0.2.0/30       *[Direct/0] 00:16:05
                    > via xe-0/0/0.0
192.0.2.2/32       *[Local/0] 00:16:05
                      Local via xe-0/0/0.0

inet6.0: 1 destinations, 1 routes (1 active, 0 holddown, 0 hidden)
+ = Active Route, - = Last Active, * = Both

fe80::286:2b0f:fca1:f500/128
                   *[Direct/0] 19:22:25
                    > via lo0.0


{master:0}
kotetsu@spine11> ping 192.0.2.1
PING 192.0.2.1 (192.0.2.1): 56 data bytes
64 bytes from 192.0.2.1: icmp_seq=0 ttl=64 time=2839.663 ms
64 bytes from 192.0.2.1: icmp_seq=1 ttl=64 time=2463.433 ms
64 bytes from 192.0.2.1: icmp_seq=2 ttl=64 time=2269.077 ms
64 bytes from 192.0.2.1: icmp_seq=3 ttl=64 time=1548.765 ms
64 bytes from 192.0.2.1: icmp_seq=4 ttl=64 time=844.779 ms
64 bytes from 192.0.2.1: icmp_seq=5 ttl=64 time=505.582 ms
64 bytes from 192.0.2.1: icmp_seq=6 ttl=64 time=852.323 ms
64 bytes from 192.0.2.1: icmp_seq=7 ttl=64 time=1724.594 ms
^C
--- 192.0.2.1 ping statistics ---
9 packets transmitted, 8 packets received, 11% packet loss
round-trip min/avg/max/stddev = 505.582/1631.027/2839.663/795.890 ms

spine21

{master:0}
kotetsu@spine21> show lldp neighbors
Local Interface    Parent Interface    Chassis Id          Port info          System Name
xe-0/0/0           -                   02:05:86:71:55:00   DEV=spine21 IF=xe-0/0/0 bb01


{master:0}
kotetsu@spine21> show route

inet.0: 6 destinations, 6 routes (6 active, 0 holddown, 0 hidden)
+ = Active Route, - = Last Active, * = Both

10.0.0.0/24        *[Direct/0] 08:41:29
                    > via em0.0
10.0.0.202/32      *[Local/0] 08:41:30
                      Local via em0.0
169.254.0.0/24     *[Direct/0] 08:46:47
                    > via em1.0
169.254.0.2/32     *[Local/0] 08:46:47
                      Local via em1.0
192.0.2.4/30       *[Direct/0] 00:03:53
                    > via xe-0/0/0.0
192.0.2.6/32       *[Local/0] 00:03:53
                      Local via xe-0/0/0.0

inet6.0: 1 destinations, 1 routes (1 active, 0 holddown, 0 hidden)
+ = Active Route, - = Last Active, * = Both

fe80::286:2b0f:fcd0:9b00/128
                   *[Direct/0] 08:46:47
                    > via lo0.0


{master:0}
kotetsu@spine21> ping 192.0.2.5
PING 192.0.2.5 (192.0.2.5): 56 data bytes
64 bytes from 192.0.2.5: icmp_seq=0 ttl=64 time=427.225 ms
64 bytes from 192.0.2.5: icmp_seq=1 ttl=64 time=709.372 ms
64 bytes from 192.0.2.5: icmp_seq=2 ttl=64 time=1231.701 ms
64 bytes from 192.0.2.5: icmp_seq=3 ttl=64 time=732.131 ms
^C
--- 192.0.2.5 ping statistics ---
4 packets transmitted, 4 packets received, 0% packet loss
round-trip min/avg/max/stddev = 427.225/775.107/1231.701/289.684 ms

lo0 + eBGP 設定

今回、いずれもシングル構成なのでマルチパス関係の設定は入れていませんよ。

bb01

set interfaces lo0 unit 0 family inet address 172.31.0.1/32

set policy-options policy-statement POLICY_EXPORT_LO0 from family inet
set policy-options policy-statement POLICY_EXPORT_LO0 from protocol direct
set policy-options policy-statement POLICY_EXPORT_LO0 from route-filter 0.0.0.0/0 prefix-length-range /32-/32
set policy-options policy-statement POLICY_EXPORT_LO0 then accept

set routing-options router-id 172.31.0.1
set routing-options autonomous-system 65000

set protocols bgp group BGP_UNDERLAY type external
set protocols bgp group BGP_UNDERLAY advertise-peer-as
set protocols bgp group BGP_UNDERLAY family inet unicast loops 2
set protocols bgp group BGP_UNDERLAY export POLICY_EXPORT_LO0
set protocols bgp group BGP_UNDERLAY neighbor 192.0.2.2 description spine11
set protocols bgp group BGP_UNDERLAY neighbor 192.0.2.2 peer-as 65001
set protocols bgp group BGP_UNDERLAY neighbor 192.0.2.6 description spine21
set protocols bgp group BGP_UNDERLAY neighbor 192.0.2.6 peer-as 65002

spine11

set interfaces lo0 unit 0 family inet address 172.16.1.1/32

set policy-options policy-statement POLICY_EXPORT_LO0 from family inet
set policy-options policy-statement POLICY_EXPORT_LO0 from protocol direct
set policy-options policy-statement POLICY_EXPORT_LO0 from route-filter 0.0.0.0/0 prefix-length-range /32-/32
set policy-options policy-statement POLICY_EXPORT_LO0 then accept

set routing-options router-id 172.16.1.1
set routing-options autonomous-system 65001

set protocols bgp group BGP_UNDERLAY type external
set protocols bgp group BGP_UNDERLAY advertise-peer-as
set protocols bgp group BGP_UNDERLAY family inet unicast loops 2
set protocols bgp group BGP_UNDERLAY export POLICY_EXPORT_LO0
set protocols bgp group BGP_UNDERLAY neighbor 192.0.2.1 description bb00
set protocols bgp group BGP_UNDERLAY neighbor 192.0.2.1 peer-as 65000

spine21

set interfaces lo0 unit 0 family inet address 172.16.2.1/32

set policy-options policy-statement POLICY_EXPORT_LO0 from family inet
set policy-options policy-statement POLICY_EXPORT_LO0 from protocol direct
set policy-options policy-statement POLICY_EXPORT_LO0 from route-filter 0.0.0.0/0 prefix-length-range /32-/32
set policy-options policy-statement POLICY_EXPORT_LO0 then accept

set routing-options router-id 172.16.2.1
set routing-options autonomous-system 65002

set protocols bgp group BGP_UNDERLAY type external
set protocols bgp group BGP_UNDERLAY advertise-peer-as
set protocols bgp group BGP_UNDERLAY family inet unicast loops 2
set protocols bgp group BGP_UNDERLAY export POLICY_EXPORT_LO0
set protocols bgp group BGP_UNDERLAY neighbor 192.0.2.5 description bb00
set protocols bgp group BGP_UNDERLAY neighbor 192.0.2.5 peer-as 65000

eBGP確認

それぞれ lo0IPアドレスを相互学習したことを確認します。 この後やる Overlay 用の MP-BGP (iBGP) で bb01 が Route Reflector になるので、実際には bb01spine[12]1 で交換できていれば十分な筈ですが。

bb01

{master:0}
kotetsu@bb01> show bgp summary
Groups: 1 Peers: 2 Down peers: 1
Table          Tot Paths  Act Paths Suppressed    History Damp State    Pending
inet.0
                       1          1          0          0          0          0
Peer                     AS      InPkt     OutPkt    OutQ   Flaps Last Up/Dwn State|#Active/Received/Accepted/Damped...
192.0.2.2             65001          4          4       0       0          20 1/1/1/0              0/0/0/0
192.0.2.6             65002          1          2       0       0        5:57 OpenConfirm

{master:0}
kotetsu@bb01> show bgp summary
Groups: 1 Peers: 2 Down peers: 0
Table          Tot Paths  Act Paths Suppressed    History Damp State    Pending
inet.0
                       2          2          0          0          0          0
Peer                     AS      InPkt     OutPkt    OutQ   Flaps Last Up/Dwn State|#Active/Received/Accepted/Damped...
192.0.2.2             65001          4          5       0       0          25 1/1/1/0              0/0/0/0
192.0.2.6             65002          4          4       0       0           4 1/1/1/0              0/0/0/0

{master:0}
kotetsu@bb01>

{master:0}
kotetsu@bb01> show bgp summary
Groups: 1 Peers: 2 Down peers: 0
Table          Tot Paths  Act Paths Suppressed    History Damp State    Pending
inet.0
                       2          2          0          0          0          0
Peer                     AS      InPkt     OutPkt    OutQ   Flaps Last Up/Dwn State|#Active/Received/Accepted/Damped...
192.0.2.2             65001          4          5       0       0          26 1/1/1/0              0/0/0/0
192.0.2.6             65002          4          4       0       0           5 1/1/1/0              0/0/0/0


{master:0}
kotetsu@bb01> show bgp group BGP_UNDERLAY brief
Group Type: External                               Local AS: 65000
  Name: BGP_UNDERLAY    Index: 0                   Flags: <Export Eval>
  Export: [ POLICY_EXPORT_LO0 ]
  Options: <AdvertisePeerAs>
  Holdtime: 0
  Total peers: 2        Established: 2
  192.0.2.2+56114
  192.0.2.6+49934
  inet.0: 2/2/2/0


{master:0}
kotetsu@bb01> show bgp neighbor
Peer: 192.0.2.2+56114 AS 65001 Local: 192.0.2.1+179 AS 65000
  Description: spine11
  Group: BGP_UNDERLAY          Routing-Instance: master
  Forwarding routing-instance: master
  Type: External    State: Established    Flags: <Sync>
  Last State: OpenConfirm   Last Event: RecvKeepAlive
  Last Error: None
  Export: [ POLICY_EXPORT_LO0 ]
  Options: <Preference AddressFamily PeerAS Refresh>
  Options: <AdvertisePeerAs PeerSpecficLoopsAllowed>
  Address families configured: inet-unicast
  Holdtime: 90 Preference: 170
  Number of flaps: 0
  Peer ID: 172.16.1.1      Local ID: 172.31.0.1        Active Holdtime: 90
  Keepalive Interval: 30         Group index: 0    Peer index: 0
  BFD: disabled, down
  Local Interface: xe-0/0/0.0
  NLRI for restart configured on peer: inet-unicast
  NLRI advertised by peer: inet-unicast
  NLRI for this session: inet-unicast
  Peer supports Refresh capability (2)
  Stale routes from peer are kept for: 300
  Peer does not support Restarter functionality
  Restart flag received from the peer: Notification
  NLRI that restart is negotiated for: inet-unicast
  NLRI of received end-of-rib markers: inet-unicast
  NLRI of all end-of-rib markers sent: inet-unicast
  Peer does not support LLGR Restarter functionality
  Peer supports 4 byte AS extension (peer-as 65001)
  Peer does not support Addpath
  Table inet.0 Bit: 10000
    RIB State: BGP restart is complete
    Send state: in sync
    Active prefixes:              1
    Received prefixes:            1
    Accepted prefixes:            1
    Suppressed due to damping:    0
    Advertised prefixes:          2
  Last traffic (seconds): Received 23   Sent 5    Checked 56
  Input messages:  Total 179    Updates 2       Refreshes 0     Octets 3478
  Output messages: Total 186    Updates 2       Refreshes 0     Octets 3663
  Output Queue[0]: 0            (inet.0, inet-unicast)

Peer: 192.0.2.6+49934 AS 65002 Local: 192.0.2.5+179 AS 65000
  Description: spine21
  Group: BGP_UNDERLAY          Routing-Instance: master
  Forwarding routing-instance: master
  Type: External    State: Established    Flags: <Sync>
  Last State: OpenConfirm   Last Event: RecvKeepAlive
  Last Error: None
  Export: [ POLICY_EXPORT_LO0 ]
  Options: <Preference AddressFamily PeerAS Refresh>
  Options: <AdvertisePeerAs PeerSpecficLoopsAllowed>
  Address families configured: inet-unicast
  Holdtime: 90 Preference: 170
  Number of flaps: 0
  Peer ID: 172.16.2.1      Local ID: 172.31.0.1        Active Holdtime: 90
  Keepalive Interval: 30         Group index: 0    Peer index: 1
  BFD: disabled, down
  Local Interface: xe-0/0/1.0
  NLRI for restart configured on peer: inet-unicast
  NLRI advertised by peer: inet-unicast
  NLRI for this session: inet-unicast
  Peer supports Refresh capability (2)
  Stale routes from peer are kept for: 300
  Peer does not support Restarter functionality
  Restart flag received from the peer: Notification
  NLRI that restart is negotiated for: inet-unicast
  NLRI of received end-of-rib markers: inet-unicast
  NLRI of all end-of-rib markers sent: inet-unicast
  Peer does not support LLGR Restarter functionality
  Peer supports 4 byte AS extension (peer-as 65002)
  Peer does not support Addpath
  Table inet.0 Bit: 10000
    RIB State: BGP restart is complete
    Send state: in sync
    Active prefixes:              1
    Received prefixes:            1
    Accepted prefixes:            1
    Suppressed due to damping:    0
    Advertised prefixes:          2
  Last traffic (seconds): Received 54   Sent 19   Checked 15
  Input messages:  Total 92     Updates 2       Refreshes 0     Octets 1825
  Output messages: Total 184    Updates 2       Refreshes 0     Octets 3625
  Output Queue[0]: 0            (inet.0, inet-unicast)
{master:0}
kotetsu@bb01> show route protocol bgp

inet.0: 11 destinations, 11 routes (11 active, 0 holddown, 0 hidden)
+ = Active Route, - = Last Active, * = Both

172.16.1.1/32      *[BGP/170] 00:02:11, localpref 100
                      AS path: 65001 I, validation-state: unverified
                    > to 192.0.2.2 via xe-0/0/0.0
172.16.2.1/32      *[BGP/170] 00:01:49, localpref 100
                      AS path: 65002 I, validation-state: unverified
                    > to 192.0.2.6 via xe-0/0/1.0

inet6.0: 1 destinations, 1 routes (1 active, 0 holddown, 0 hidden)


{master:0}
kotetsu@bb01> ping 172.16.2.1
PING 172.16.2.1 (172.16.2.1): 56 data bytes
64 bytes from 172.16.2.1: icmp_seq=0 ttl=64 time=908.929 ms
64 bytes from 172.16.2.1: icmp_seq=1 ttl=64 time=1249.259 ms
^C
--- 172.16.2.1 ping statistics ---
3 packets transmitted, 2 packets received, 33% packet loss
round-trip min/avg/max/stddev = 908.929/1079.094/1249.259/170.165 ms


{master:0}
kotetsu@bb01> ping 172.16.1.1
PING 172.16.1.1 (172.16.1.1): 56 data bytes
64 bytes from 172.16.1.1: icmp_seq=0 ttl=64 time=2595.413 ms
64 bytes from 172.16.1.1: icmp_seq=1 ttl=64 time=1406.501 ms
^C
--- 172.16.1.1 ping statistics ---
3 packets transmitted, 2 packets received, 33% packet loss
round-trip min/avg/max/stddev = 1406.501/2000.957/2595.413/594.456 ms

spine11

{master:0}
kotetsu@spine11> show bgp summary
Groups: 1 Peers: 1 Down peers: 0
Table          Tot Paths  Act Paths Suppressed    History Damp State    Pending
inet.0
                       2          2          0          0          0          0
Peer                     AS      InPkt     OutPkt    OutQ   Flaps Last Up/Dwn State|#Active/Received/Accepted/Damped...
192.0.2.1             65000        174        169       0       0     1:16:34 2/2/2/0              0/0/0/0


{master:0}
kotetsu@spine11> show bgp group BGP_UNDERLAY brief
Group Type: External                               Local AS: 65001
  Name: BGP_UNDERLAY    Index: 0                   Flags: <Export Eval>
  Export: [ POLICY_EXPORT_LO0 ]
  Options: <AdvertisePeerAs>
  Holdtime: 0
  Total peers: 1        Established: 1
  192.0.2.1+179
  inet.0: 2/2/2/0


{master:0}
kotetsu@spine11> show bgp neighbor
Peer: 192.0.2.1+179 AS 65000   Local: 192.0.2.2+56114 AS 65001
  Description: bb00
  Group: BGP_UNDERLAY          Routing-Instance: master
  Forwarding routing-instance: master
  Type: External    State: Established    Flags: <Sync>
  Last State: OpenConfirm   Last Event: RecvKeepAlive
  Last Error: None
  Export: [ POLICY_EXPORT_LO0 ]
  Options: <Preference AddressFamily PeerAS Refresh>
  Options: <AdvertisePeerAs PeerSpecficLoopsAllowed>
  Address families configured: inet-unicast
  Holdtime: 90 Preference: 170
  Number of flaps: 0
  Peer ID: 172.31.0.1      Local ID: 172.16.1.1        Active Holdtime: 90
  Keepalive Interval: 30         Group index: 0    Peer index: 0
  BFD: disabled, down
  Local Interface: xe-0/0/0.0
  NLRI for restart configured on peer: inet-unicast
  NLRI advertised by peer: inet-unicast
  NLRI for this session: inet-unicast
  Peer supports Refresh capability (2)
  Stale routes from peer are kept for: 300
  Peer does not support Restarter functionality
  Restart flag received from the peer: Notification
  NLRI that restart is negotiated for: inet-unicast
  NLRI of received end-of-rib markers: inet-unicast
  NLRI of all end-of-rib markers sent: inet-unicast
  Peer does not support LLGR Restarter functionality
  Peer supports 4 byte AS extension (peer-as 65000)
  Peer does not support Addpath
  Table inet.0 Bit: 10000
    RIB State: BGP restart is complete
    Send state: in sync
    Active prefixes:              2
    Received prefixes:            2
    Accepted prefixes:            2
    Suppressed due to damping:    0
    Advertised prefixes:          1
  Last traffic (seconds): Received 9    Sent 7    Checked 50
  Input messages:  Total 182    Updates 3       Refreshes 0     Octets 3524
  Output messages: Total 177    Updates 1       Refreshes 0     Octets 3459
  Output Queue[0]: 0            (inet.0, inet-unicast)
{master:0}
kotetsu@spine11> show route protocol bgp

inet.0: 9 destinations, 9 routes (9 active, 0 holddown, 0 hidden)
+ = Active Route, - = Last Active, * = Both

172.16.2.1/32      *[BGP/170] 01:22:49, localpref 100
                      AS path: 65000 65002 I, validation-state: unverified
                    > to 192.0.2.1 via xe-0/0/0.0
172.31.0.1/32      *[BGP/170] 01:23:10, localpref 100
                      AS path: 65000 I, validation-state: unverified
                    > to 192.0.2.1 via xe-0/0/0.0

inet6.0: 1 destinations, 1 routes (1 active, 0 holddown, 0 hidden)


{master:0}
kotetsu@spine11> ping 172.31.0.1
PING 172.31.0.1 (172.31.0.1): 56 data bytes
64 bytes from 172.31.0.1: icmp_seq=0 ttl=64 time=1597.291 ms
64 bytes from 172.31.0.1: icmp_seq=1 ttl=64 time=1215.306 ms
^C
--- 172.31.0.1 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max/stddev = 1215.306/1406.299/1597.291/190.993 ms

spine21

{master:0}
kotetsu@spine21> show bgp summary
Groups: 1 Peers: 1 Down peers: 0
Table          Tot Paths  Act Paths Suppressed    History Damp State    Pending
inet.0
                       2          2          0          0          0          0
Peer                     AS      InPkt     OutPkt    OutQ   Flaps Last Up/Dwn State|#Active/Received/Accepted/Damped...
192.0.2.5             65000        173         88       0       0       38:05 2/2/2/0              0/0/0/0


{master:0}
kotetsu@spine21> show bgp group BGP_UNDERLAY brief
Group Type: External                               Local AS: 65002
  Name: BGP_UNDERLAY    Index: 0                   Flags: <Export Eval>
  Export: [ POLICY_EXPORT_LO0 ]
  Options: <AdvertisePeerAs>
  Holdtime: 0
  Total peers: 1        Established: 1
  192.0.2.5+179
  inet.0: 2/2/2/0


kotetsu@spine21> show bgp neighbor
Peer: 192.0.2.5+179 AS 65000   Local: 192.0.2.6+49934 AS 65002
  Description: bb00
  Group: BGP_UNDERLAY          Routing-Instance: master
  Forwarding routing-instance: master
  Type: External    State: Established    Flags: <Sync>
  Last State: OpenConfirm   Last Event: RecvKeepAlive
  Last Error: None
  Export: [ POLICY_EXPORT_LO0 ]
  Options: <Preference AddressFamily PeerAS Refresh>
  Options: <AdvertisePeerAs PeerSpecficLoopsAllowed>
  Address families configured: inet-unicast
  Holdtime: 90 Preference: 170
  Number of flaps: 0
  Peer ID: 172.31.0.1      Local ID: 172.16.2.1        Active Holdtime: 90
  Keepalive Interval: 30         Group index: 0    Peer index: 0
  BFD: disabled, down
  Local Interface: xe-0/0/0.0
  NLRI for restart configured on peer: inet-unicast
  NLRI advertised by peer: inet-unicast
  NLRI for this session: inet-unicast
  Peer supports Refresh capability (2)
  Stale routes from peer are kept for: 300
  Peer does not support Restarter functionality
  Restart flag received from the peer: Notification
  NLRI that restart is negotiated for: inet-unicast
  NLRI of received end-of-rib markers: inet-unicast
  NLRI of all end-of-rib markers sent: inet-unicast
  Peer does not support LLGR Restarter functionality
  Peer supports 4 byte AS extension (peer-as 65000)
  Peer does not support Addpath
  Table inet.0 Bit: 10000
    RIB State: BGP restart is complete
    Send state: in sync
    Active prefixes:              2
    Received prefixes:            2
    Accepted prefixes:            2
    Suppressed due to damping:    0
    Advertised prefixes:          1
  Last traffic (seconds): Received 1    Sent 24   Checked 3
  Input messages:  Total 175    Updates 3       Refreshes 0     Octets 3391
  Output messages: Total 88     Updates 1       Refreshes 0     Octets 1768
  Output Queue[0]: 0            (inet.0, inet-unicast)
{master:0}
kotetsu@spine21> show route protocol bgp

inet.0: 9 destinations, 9 routes (9 active, 0 holddown, 0 hidden)
+ = Active Route, - = Last Active, * = Both

172.16.1.1/32      *[BGP/170] 00:41:43, localpref 100
                      AS path: 65000 65001 I, validation-state: unverified
                    > to 192.0.2.5 via xe-0/0/0.0
172.31.0.1/32      *[BGP/170] 00:41:43, localpref 100
                      AS path: 65000 I, validation-state: unverified
                    > to 192.0.2.5 via xe-0/0/0.0

inet6.0: 1 destinations, 1 routes (1 active, 0 holddown, 0 hidden)


{master:0}
kotetsu@spine21> ping 172.31.0.1
PING 172.31.0.1 (172.31.0.1): 56 data bytes
64 bytes from 172.31.0.1: icmp_seq=0 ttl=64 time=691.327 ms
64 bytes from 172.31.0.1: icmp_seq=1 ttl=64 time=1227.117 ms
64 bytes from 172.31.0.1: icmp_seq=2 ttl=64 time=238.494 ms
^C
--- 172.31.0.1 ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max/stddev = 238.494/718.979/1227.117/404.077 ms

Overlay 設定~確認 (MP-BGP)

Underlay eBGP で経路交換した各 lo0 同士で iBGP を組みます。 まあ、長々となってしまいますが、絵にすると単純で以下のような感じです。

f:id:kakkotetsu:20170511233224p:plain

iBGP (MP-BGP )設定

ポイントは1つだけで family evpn signaling を設定して EVPN の NLRI を扱うってとこですかね。

bb01

set protocols bgp group BGP_OVERLAY type internal
set protocols bgp group BGP_OVERLAY local-address 172.31.0.1
set protocols bgp group BGP_OVERLAY family evpn signaling
set protocols bgp group BGP_OVERLAY cluster 172.31.0.1
set protocols bgp group BGP_OVERLAY local-as 64512
set protocols bgp group BGP_OVERLAY neighbor 172.16.1.1 description spine11
set protocols bgp group BGP_OVERLAY neighbor 172.16.2.1 description spine21

spine11

set protocols bgp group BGP_OVERLAY type internal
set protocols bgp group BGP_OVERLAY local-address 172.16.1.1
set protocols bgp group BGP_OVERLAY family evpn signaling
set protocols bgp group BGP_OVERLAY local-as 64512
set protocols bgp group BGP_OVERLAY neighbor 172.31.0.1 description bb01

spine21

set protocols bgp group BGP_OVERLAY type internal
set protocols bgp group BGP_OVERLAY local-address 172.16.2.1
set protocols bgp group BGP_OVERLAY family evpn signaling
set protocols bgp group BGP_OVERLAY local-as 64512
set protocols bgp group BGP_OVERLAY neighbor 172.31.0.1 description bb01

iBGP (MP-BGP) 確認

最初 neighbor IP アドレス設定をタイポしたせいで、Last Error: Open Message Error とか残っているのはご愛敬ということでひとつ...。

bb01

{master:0}
kotetsu@bb01> show bgp summary
Groups: 2 Peers: 4 Down peers: 0
Table          Tot Paths  Act Paths Suppressed    History Damp State    Pending
inet.0
                       2          2          0          0          0          0
bgp.evpn.0
                       0          0          0          0          0          0
Peer                     AS      InPkt     OutPkt    OutQ   Flaps Last Up/Dwn State|#Active/Received/Accepted/Damped...
172.16.1.1            64512          3          3       0       0          25 Establ
  bgp.evpn.0: 0/0/0/0
172.16.2.1            64512          3          2       0       0          12 Establ
  bgp.evpn.0: 0/0/0/0
192.0.2.2             65001        502        518       0       0     3:58:25 1/1/1/0              0/0/0/0
192.0.2.6             65002        257        517       0       0     3:58:04 1/1/1/0              0/0/0/0


{master:0}
kotetsu@bb01> show bgp group BGP_OVERLAY
Group Type: Internal    AS: 64512                  Local AS: 64512
  Name: BGP_OVERLAY     Index: 1                   Flags: <Export Eval>
  Options: <Cluster LocalAS>
  Holdtime: 0 Local AS: 64512 Local System AS: 65000
  Total peers: 2        Established: 2
  172.16.1.1+52050
  172.16.2.1+62794
  Trace options: normal
  Trace file: /var/log/bgp.log size 10240 files 30
  bgp.evpn.0: 0/0/0/0


{master:0}
kotetsu@bb01> show bgp neighbor
Peer: 172.16.1.1+52050 AS 64512 Local: 172.31.0.1+179 AS 64512
  Description: spine11
  Group: BGP_OVERLAY           Routing-Instance: master
  Forwarding routing-instance: master
  Type: Internal    State: Established  (route reflector client)Flags: <Sync>
  Last State: OpenConfirm   Last Event: RecvKeepAlive
  Last Error: Open Message Error
  Options: <Preference LocalAddress Cluster AddressFamily LocalAS Rib-group Refresh>
  Address families configured: evpn
  Local Address: 172.31.0.1 Holdtime: 90 Preference: 170 Local AS: 64512 Local System AS: 65000
  Number of flaps: 0
  Error: 'Open Message Error' Sent: 20 Recv: 0
  Peer ID: 172.16.1.1      Local ID: 172.31.0.1        Active Holdtime: 90
  Keepalive Interval: 30         Group index: 1    Peer index: 0
  BFD: disabled, down
  NLRI for restart configured on peer: evpn
  NLRI advertised by peer: evpn
  NLRI for this session: evpn
  Peer supports Refresh capability (2)
  Stale routes from peer are kept for: 300
  Peer does not support Restarter functionality
  Restart flag received from the peer: Notification
  NLRI that restart is negotiated for: evpn
  NLRI of received end-of-rib markers: evpn
  NLRI of all end-of-rib markers sent: evpn
  Peer does not support LLGR Restarter functionality
  Peer supports 4 byte AS extension (peer-as 64512)
  Peer does not support Addpath
  Table bgp.evpn.0 Bit: 20000
    RIB State: BGP restart is complete
    RIB State: VPN restart is complete
    Send state: in sync
    Active prefixes:              0
    Received prefixes:            0
    Accepted prefixes:            0
    Suppressed due to damping:    0
    Advertised prefixes:          0
  Last traffic (seconds): Received 1    Sent 9    Checked 0
  Input messages:  Total 6      Updates 1       Refreshes 0     Octets 169
  Output messages: Total 6      Updates 0       Refreshes 0     Octets 188
  Output Queue[1]: 0            (bgp.evpn.0, evpn)
  Trace options: normal
  Trace file: /var/log/bgp.log size 10240 files 30

Peer: 172.16.2.1+62794 AS 64512 Local: 172.31.0.1+179 AS 64512
  Description: spine21
  Group: BGP_OVERLAY           Routing-Instance: master
  Forwarding routing-instance: master
  Type: Internal    State: Established  (route reflector client)Flags: <Sync>
  Last State: OpenConfirm   Last Event: RecvKeepAlive
  Last Error: Open Message Error
  Options: <Preference LocalAddress Cluster AddressFamily LocalAS Rib-group Refresh>
  Address families configured: evpn
  Local Address: 172.31.0.1 Holdtime: 90 Preference: 170 Local AS: 64512 Local System AS: 65000
  Number of flaps: 0
  Error: 'Open Message Error' Sent: 20 Recv: 0
  Peer ID: 172.16.2.1      Local ID: 172.31.0.1        Active Holdtime: 90
  Keepalive Interval: 30         Group index: 1    Peer index: 1
  BFD: disabled, down
  NLRI for restart configured on peer: evpn
  NLRI advertised by peer: evpn
  NLRI for this session: evpn
  Peer supports Refresh capability (2)
  Stale routes from peer are kept for: 300
  Peer does not support Restarter functionality
  Restart flag received from the peer: Notification
  NLRI that restart is negotiated for: evpn
  NLRI of received end-of-rib markers: evpn
  NLRI of all end-of-rib markers sent: evpn
  Peer does not support LLGR Restarter functionality
  Peer supports 4 byte AS extension (peer-as 64512)
  Peer does not support Addpath
  Table bgp.evpn.0 Bit: 20000
    RIB State: BGP restart is complete
    RIB State: VPN restart is complete
    Send state: in sync
    Active prefixes:              0
    Received prefixes:            0
    Accepted prefixes:            0
    Suppressed due to damping:    0
    Advertised prefixes:          0
  Last traffic (seconds): Received 46   Sent 0    Checked 9
  Input messages:  Total 10     Updates 1       Refreshes 0     Octets 245
  Output messages: Total 18     Updates 0       Refreshes 0     Octets 416
  Output Queue[1]: 0            (bgp.evpn.0, evpn)
  Trace options: normal
  Trace file: /var/log/bgp.log size 10240 files 30

...

spine11

{master:0}
kotetsu@spine11> show bgp summary
Groups: 2 Peers: 2 Down peers: 0
Table          Tot Paths  Act Paths Suppressed    History Damp State    Pending
inet.0
                       2          2          0          0          0          0
bgp.evpn.0
                       0          0          0          0          0          0
Peer                     AS      InPkt     OutPkt    OutQ   Flaps Last Up/Dwn State|#Active/Received/Accepted/Damped...
172.31.0.1            64512         21         22       0       0        9:07 Establ
  bgp.evpn.0: 0/0/0/0
192.0.2.1             65000        536        521       0       0     3:59:55 2/2/2/0              0/0/0/


{master:0}
kotetsu@spine11> show bgp group BGP_OVERLAY
Group Type: Internal    AS: 64512                  Local AS: 64512
  Name: BGP_OVERLAY     Index: 1                   Flags: <Export Eval>
  Options: <LocalAS>
  Holdtime: 0 Local AS: 64512 Local System AS: 65001
  Total peers: 1        Established: 1
  172.31.0.1+179
  Trace options: normal
  Trace file: /var/log/bgp.log size 10240 files 30
  bgp.evpn.0: 0/0/0/0


{master:0}
kotetsu@spine11> show bgp neighbor
Peer: 172.31.0.1+179 AS 64512  Local: 172.16.1.1+52050 AS 64512
  Description: bb01
  Group: BGP_OVERLAY           Routing-Instance: master
  Forwarding routing-instance: master
  Type: Internal    State: Established    Flags: <Sync>
  Last State: OpenConfirm   Last Event: RecvKeepAlive
  Last Error: None
  Options: <Preference LocalAddress AddressFamily LocalAS Rib-group Refresh>
  Address families configured: evpn
  Local Address: 172.16.1.1 Holdtime: 90 Preference: 170 Local AS: 64512 Local System AS: 65001
  Number of flaps: 0
  Peer ID: 172.31.0.1      Local ID: 172.16.1.1        Active Holdtime: 90
  Keepalive Interval: 30         Group index: 1    Peer index: 1
  BFD: disabled, down
  NLRI for restart configured on peer: evpn
  NLRI advertised by peer: evpn
  NLRI for this session: evpn
  Peer supports Refresh capability (2)
  Stale routes from peer are kept for: 300
  Peer does not support Restarter functionality
  Restart flag received from the peer: Notification
  NLRI that restart is negotiated for: evpn
  NLRI of received end-of-rib markers: evpn
  NLRI of all end-of-rib markers sent: evpn
  Peer does not support LLGR Restarter functionality
  Peer supports 4 byte AS extension (peer-as 64512)
  Peer does not support Addpath
  Table bgp.evpn.0
    RIB State: BGP restart is complete
    RIB State: VPN restart is complete
    Send state: not advertising
    Active prefixes:              0
    Received prefixes:            0
    Accepted prefixes:            0
    Suppressed due to damping:    0
  Last traffic (seconds): Received 1    Sent 8    Checked 46
  Input messages:  Total 34     Updates 1       Refreshes 0     Octets 657
  Output messages: Total 34     Updates 0       Refreshes 0     Octets 720
  Trace options: normal
  Trace file: /var/log/bgp.log size 10240 files 30

...

spine21

{master:0}
kotetsu@spine21> show bgp summary
Groups: 2 Peers: 2 Down peers: 0
Table          Tot Paths  Act Paths Suppressed    History Damp State    Pending
inet.0
                       2          2          0          0          0          0
bgp.evpn.0
                       0          0          0          0          0          0
Peer                     AS      InPkt     OutPkt    OutQ   Flaps Last Up/Dwn State|#Active/Received/Accepted/Damped...
172.31.0.1            64512         34         19       0       0        7:30 Establ
  bgp.evpn.0: 0/0/0/0
192.0.2.5             65000        549        273       0       0     2:02:08 2/2/2/0              0/0/0/0


{master:0}
kotetsu@spine21> show bgp group BGP_OVERLAY
Group Type: Internal    AS: 64512                  Local AS: 64512
  Name: BGP_OVERLAY     Index: 1                   Flags: <Export Eval>
  Options: <LocalAS>
  Holdtime: 0 Local AS: 64512 Local System AS: 65002
  Total peers: 1        Established: 1
  172.31.0.1+179
  Trace options: normal
  Trace file: /var/log/bgp.log size 10240 files 30
  bgp.evpn.0: 0/0/0/0


{master:0}
kotetsu@spine21> show bgp neighbor
Peer: 172.31.0.1+179 AS 64512  Local: 172.16.2.1+62794 AS 64512
  Description: bb01
  Group: BGP_OVERLAY           Routing-Instance: master
  Forwarding routing-instance: master
  Type: Internal    State: Established    Flags: <Sync>
  Last State: OpenConfirm   Last Event: RecvKeepAlive
  Last Error: None
  Options: <Preference LocalAddress AddressFamily LocalAS Rib-group Refresh>
  Address families configured: evpn
  Local Address: 172.16.2.1 Holdtime: 90 Preference: 170 Local AS: 64512 Local System AS: 65002
  Number of flaps: 0
  Peer ID: 172.31.0.1      Local ID: 172.16.2.1        Active Holdtime: 90
  Keepalive Interval: 30         Group index: 1    Peer index: 1
  BFD: disabled, down
  NLRI for restart configured on peer: evpn
  NLRI advertised by peer: evpn
  NLRI for this session: evpn
  Peer supports Refresh capability (2)
  Stale routes from peer are kept for: 300
  Peer does not support Restarter functionality
  Restart flag received from the peer: Notification
  NLRI that restart is negotiated for: evpn
  NLRI of received end-of-rib markers: evpn
  NLRI of all end-of-rib markers sent: evpn
  Peer does not support LLGR Restarter functionality
  Peer supports 4 byte AS extension (peer-as 64512)
  Peer does not support Addpath
  Table bgp.evpn.0
    RIB State: BGP restart is complete
    RIB State: VPN restart is complete
    Send state: not advertising
    Active prefixes:              0
    Received prefixes:            0
    Accepted prefixes:            0
    Suppressed due to damping:    0
  Last traffic (seconds): Received 14   Sent 17   Checked 58
  Input messages:  Total 36     Updates 1       Refreshes 0     Octets 695
  Output messages: Total 20     Updates 0       Refreshes 0     Octets 454
  Trace options: normal
  Trace file: /var/log/bgp.log size 10240 files 30

...

Overlay設定~確認(EVPN+VXLAN)

EVPN の設定と、その Dataplane として使う VXLAN 周りの設定をしていきます。(息切れ)

EVPN+VXLAN 設定

冒頭の全体構成に書いたのですが bb01 はこの辺の挙動に関しては土管に徹しているので登場しません。 VNI1..16777214 まで使えるので、単純に全 spine で VLAN ID と 1:1 で同じ対応付けをさせて、一律で VLAN ID + 10000 の値を振ってます。 あ、VNI 10100 以外は本項ではまだ使いません。

spine11

set vlans VLAN0100 vlan-id 100
set vlans VLAN0100 vxlan vni 10100
set vlans VLAN0100 vxlan ingress-node-replication

set vlans VLAN0300 vlan-id 300
set vlans VLAN0300 vxlan vni 10300
set vlans VLAN0300 vxlan ingress-node-replication

set protocols evpn encapsulation vxlan
set protocols evpn extended-vni-list all
set protocols evpn multicast-mode ingress-replication
set protocols evpn vni-options vni 10100 vrf-target export target:1:10100
set protocols evpn vni-options vni 10300 vrf-target export target:1:10300

set policy-options community COM_10100 members target:1:10100
set policy-options community COM_10300 members target:1:10300
set policy-options community COM_LEAF_ESI members target:9999:9999

set policy-options policy-statement POLICY_VRF_IMPORT term T_10100 from community COM_10100
set policy-options policy-statement POLICY_VRF_IMPORT term T_10100 then accept
set policy-options policy-statement POLICY_VRF_IMPORT term T_10300 from community COM_10300
set policy-options policy-statement POLICY_VRF_IMPORT term T_10300 then accept
set policy-options policy-statement POLICY_VRF_IMPORT term T_99900 from community COM_LEAF_ESI
set policy-options policy-statement POLICY_VRF_IMPORT term T_99900 then accept
set policy-options policy-statement POLICY_VRF_IMPORT term T_99999 then reject

set switch-options vtep-source-interface lo0.0
set switch-options route-distinguisher 64512:11
set switch-options vrf-import POLICY_VRF_IMPORT
set switch-options vrf-target target:9999:9999
set switch-options vrf-target auto 

set interfaces xe-0/0/1 description "DEV=torSW11 IF=1"
set interfaces xe-0/0/1 unit 0 family ethernet-switching interface-mode trunk
set interfaces xe-0/0/1 unit 0 family ethernet-switching vlan members all

spine21

set vlans VLAN0100 vlan-id 100
set vlans VLAN0100 vxlan vni 10100
set vlans VLAN0100 vxlan ingress-node-replication

set vlans VLAN0200 vlan-id 200
set vlans VLAN0200 vxlan vni 10200
set vlans VLAN0200 vxlan ingress-node-replication

set protocols evpn encapsulation vxlan
set protocols evpn extended-vni-list all
set protocols evpn multicast-mode ingress-replication
set protocols evpn vni-options vni 10100 vrf-target export target:1:10100
set protocols evpn vni-options vni 10200 vrf-target export target:1:10200

set policy-options community COM_10100 members target:1:10100
set policy-options community COM_10200 members target:1:10200
set policy-options community COM_LEAF_ESI members target:9999:9999

set policy-options policy-statement POLICY_VRF_IMPORT term T_10100 from community COM_10100
set policy-options policy-statement POLICY_VRF_IMPORT term T_10100 then accept
set policy-options policy-statement POLICY_VRF_IMPORT term T_10200 from community COM_10200
set policy-options policy-statement POLICY_VRF_IMPORT term T_10200 then accept
set policy-options policy-statement POLICY_VRF_IMPORT term T_99900 from community COM_LEAF_ESI
set policy-options policy-statement POLICY_VRF_IMPORT term T_99900 then accept
set policy-options policy-statement POLICY_VRF_IMPORT term T_99999 then reject

set switch-options vtep-source-interface lo0.0
set switch-options route-distinguisher 64512:21
set switch-options vrf-import POLICY_VRF_IMPORT
set switch-options vrf-target target:9999:9999
set switch-options vrf-target auto 

set interfaces xe-0/0/1 description "DEV=torSW21 IF=1"
set interfaces xe-0/0/1 unit 0 family ethernet-switching interface-mode trunk
set interfaces xe-0/0/1 unit 0 family ethernet-switching vlan members all

動作確認

node 同士の疎通確認

  • node11
$ ip a show dev ens4
3: ens4: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 00:86:2b:8d:10:01 brd ff:ff:ff:ff:ff:ff
    inet 192.168.1.1/24 brd 192.168.1.255 scope global ens4
       valid_lft forever preferred_lft forever
    inet6 fe80::286:2bff:fe8d:1001/64 scope link
       valid_lft forever preferred_lft forever

$ ping 192.168.1.2
PING 192.168.1.2 (192.168.1.2) 56(84) bytes of data.
64 bytes from 192.168.1.2: icmp_seq=1 ttl=64 time=975 ms
64 bytes from 192.168.1.2: icmp_seq=2 ttl=64 time=949 ms

$ ip n show dev ens4
192.168.1.2 lladdr 00:86:2b:5c:0d:01 STALE
  • node21
$ ip a show dev ens4
3: ens4: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 00:86:2b:5c:0d:01 brd ff:ff:ff:ff:ff:ff
    inet 192.168.1.2/24 brd 192.168.1.255 scope global ens4
       valid_lft forever preferred_lft forever
    inet6 fe80::286:2bff:fe5c:d01/64 scope link
       valid_lft forever preferred_lft forever

$ ping 192.168.1.1
PING 192.168.1.1 (192.168.1.1) 56(84) bytes of data.
64 bytes from 192.168.1.1: icmp_seq=1 ttl=64 time=639 ms
64 bytes from 192.168.1.1: icmp_seq=2 ttl=64 time=926 ms

$ ip n show dev ens4
192.168.1.1 lladdr 00:86:2b:8d:10:01 STALE

vQFX のテーブル確認

前述の Juniper公式日本語資料 のページ 36 によると

bgp.evpn.0 = Junos OS ルーティング プロトコル プロセス(RPD)内のグローバル EVPN ルーティング テーブル default.switch.evpn.0(QFX5100 の場合) = Junos OS RPD 内のスイッチ レベル EVPN 転送テーブル \<virtual-switch-name>.evpn.0(MX の場合) = Junos OS RPD 内の仮想スイッチ レベル EVPN 転送テーブル

らしいですよ。

spine11

こいつにとっての vtep.32769 てのは spine21 (の VTEP)

{master:0}
kotetsu@spine11> show ethernet-switching table

MAC flags (S - static MAC, D - dynamic MAC, L - locally learned, P - Persistent static
           SE - statistics enabled, NM - non configured MAC, R - remote PE MAC, O - ovsdb MAC)


Ethernet switching table : 2 entries, 2 learned
Routing instance : default-switch
   Vlan                MAC                 MAC      Logical                Active
   name                address             flags    interface              source
   VLAN0100            00:86:2b:5c:0d:01   D        vtep.32769             172.16.2.1
   VLAN0100            00:86:2b:8d:10:01   D        xe-0/0/1.0


{master:0}
kotetsu@spine11> show interfaces vtep.32769
  Logical interface vtep.32769 (Index 566) (SNMP ifIndex 537)
    Flags: Up SNMP-Traps Encapsulation: ENET2
    VXLAN Endpoint Type: Remote, VXLAN Endpoint Address: 172.16.2.1, L2 Routing Instance: default-switch, L3 Routing Instance: default
    Input packets : 4
    Output packets: 4
    Protocol eth-switch, MTU: Unlimited
      Flags: Trunk-Mode

EVPN の Type2(MAC/IP Advertisement route) と Type3(Inclusive Multicast Ethernet Tag route) を spine21 (RD 64512:21)から学習して bgp.evpn.0 から default-switch.evpn.0 にロードされている様子

{master:0}
kotetsu@spine11> show route

...

:vxlan.inet.0: 8 destinations, 8 routes (8 active, 0 holddown, 0 hidden)
+ = Active Route, - = Last Active, * = Both

10.0.0.0/24        *[Direct/0] 00:23:24
                    > via em0.0
10.0.0.201/32      *[Local/0] 00:06:15
                      Local via em0.0
169.254.0.0/24     *[Direct/0] 00:23:24
                    > via em1.0
169.254.0.2/32     *[Local/0] 00:23:24
                      Local via em1.0
172.16.1.1/32      *[Direct/0] 00:23:24
                    > via lo0.0
172.16.2.1/32      *[Static/1] 00:13:22, metric2 0
                    > to 192.0.2.1 via xe-0/0/0.0
192.0.2.0/30       *[Direct/0] 00:23:24
                    > via xe-0/0/0.0
192.0.2.2/32       *[Local/0] 00:23:24
                      Local via xe-0/0/0.0


bgp.evpn.0: 2 destinations, 2 routes (2 active, 0 holddown, 0 hidden)
+ = Active Route, - = Last Active, * = Both

2:64512:21::10100::00:86:2b:5c:0d:01/304
                   *[BGP/170] 00:08:29, localpref 100, from 172.31.0.1
                      AS path: I, validation-state: unverified
                    > to 192.0.2.1 via xe-0/0/0.0
3:64512:21::10100::172.16.2.1/304
                   *[BGP/170] 00:13:23, localpref 100, from 172.31.0.1
                      AS path: I, validation-state: unverified
                    > to 192.0.2.1 via xe-0/0/0.0


default-switch.evpn.0: 5 destinations, 5 routes (5 active, 0 holddown, 0 hidden)
+ = Active Route, - = Last Active, * = Both

2:64512:11::10100::00:86:2b:8d:10:01/304
                   *[EVPN/170] 00:08:33
                      Indirect
2:64512:21::10100::00:86:2b:5c:0d:01/304
                   *[BGP/170] 00:08:29, localpref 100, from 172.31.0.1
                      AS path: I, validation-state: unverified
                    > to 192.0.2.1 via xe-0/0/0.0
3:64512:11::10100::172.16.1.1/304
                   *[EVPN/170] 00:23:27
                      Indirect
3:64512:11::10300::172.16.1.1/304
                   *[EVPN/170] 00:15:11
                      Indirect
3:64512:21::10100::172.16.2.1/304
                   *[BGP/170] 00:13:23, localpref 100, from 172.31.0.1
                      AS path: I, validation-state: unverified
                    > to 192.0.2.1 via xe-0/0/0.0
{master:0}
kotetsu@spine11> show route forwarding-table

...

Routing table: :vxlan.inet
Internet:
Destination        Type RtRef Next hop           Type Index    NhRef Netif
default            perm     0                    rjct     1724     1
0.0.0.0/32         perm     0                    dscd     1722     1
169.254.0.0/24     user     0                    rtbl        1     5
169.254.0.2/32     user     0 169.254.0.2        locl      338     3
172.16.1.1/32      user     0                    rtbl        1     5
172.16.2.1/32      user     0                    indr   131070     3
                              192.0.2.1          ucst     1719     7 xe-0/0/0.0
192.0.2.0/30       user     0                    rtbl        1     5
192.0.2.2/32       user     0 192.0.2.2          locl     1717     3
224.0.0.0/4        perm     0                    mdsc     1723     1
224.0.0.1/32       perm     0 224.0.0.1          mcst     1726     1
255.255.255.255/32 perm     0                    bcst     1727     1

...

Routing table: default-switch.bridge
Bridging domain: VLAN0100.bridge
VPLS:
Destination        Type RtRef Next hop           Type Index    NhRef Netif
00:86:2b:5c:0d:01/48 user     0                  comp     1707     6
00:86:2b:8d:10:01/48 user     0                  ucst     1712     6 xe-0/0/1.0
0x30001/51         user     0                    comp     1739     2
0x30006/51         user     0                    comp     1732     2
0x30002/51         user     0                    comp     1733     2

Routing table: default-switch.bridge
Bridging domain: VLAN0300.bridge
VPLS:
Destination        Type RtRef Next hop           Type Index    NhRef Netif
0x30007/51         user     0                    comp     1741     2
0x30005/51         user     0                    comp     1714     2
0x30003/51         user     0                    comp     1734     2

...

spine21

こいつにとっての vtep.32769 てのは spine11 (の VTEP)

{master:0}
kotetsu@spine21> show ethernet-switching table

MAC flags (S - static MAC, D - dynamic MAC, L - locally learned, P - Persistent static
           SE - statistics enabled, NM - non configured MAC, R - remote PE MAC, O - ovsdb MAC)


Ethernet switching table : 2 entries, 2 learned
Routing instance : default-switch
   Vlan                MAC                 MAC      Logical                Active
   name                address             flags    interface              source
   VLAN0100            00:86:2b:5c:0d:01   D        xe-0/0/1.0
   VLAN0100            00:86:2b:8d:10:01   D        vtep.32769             172.16.1.1

EVPN の Type2(MAC/IP Advertisement route) と Type3(Inclusive Multicast Ethernet Tag route) を spine11 (RD 64512:11)から学習して bgp.evpn.0 から default-switch.evpn.0 にロードされている様子

{master:0}
kotetsu@spine21> show route

...

:vxlan.inet.0: 8 destinations, 8 routes (8 active, 0 holddown, 0 hidden)
+ = Active Route, - = Last Active, * = Both

10.0.0.0/24        *[Direct/0] 00:18:41
                    > via em0.0
10.0.0.202/32      *[Local/0] 00:11:20
                      Local via em0.0
169.254.0.0/24     *[Direct/0] 00:18:41
                    > via em1.0
169.254.0.2/32     *[Local/0] 00:18:41
                      Local via em1.0
172.16.1.1/32      *[Static/1] 00:18:39, metric2 0
                    > to 192.0.2.5 via xe-0/0/0.0
172.16.2.1/32      *[Direct/0] 00:18:41
                    > via lo0.0
192.0.2.4/30       *[Direct/0] 00:18:41
                    > via xe-0/0/0.0
192.0.2.6/32       *[Local/0] 00:18:41
                      Local via xe-0/0/0.0

bgp.evpn.0: 2 destinations, 2 routes (2 active, 0 holddown, 0 hidden)
+ = Active Route, - = Last Active, * = Both

2:64512:11::10100::00:86:2b:8d:10:01/304
                   *[BGP/170] 00:12:17, localpref 100, from 172.31.0.1
                      AS path: I, validation-state: unverified
                    > to 192.0.2.5 via xe-0/0/0.0
3:64512:11::10100::172.16.1.1/304
                   *[BGP/170] 00:18:40, localpref 100, from 172.31.0.1
                      AS path: I, validation-state: unverified
                    > to 192.0.2.5 via xe-0/0/0.0

default-switch.evpn.0: 5 destinations, 5 routes (5 active, 0 holddown, 0 hidden)
+ = Active Route, - = Last Active, * = Both

2:64512:11::10100::00:86:2b:8d:10:01/304
                   *[BGP/170] 00:12:17, localpref 100, from 172.31.0.1
                      AS path: I, validation-state: unverified
                    > to 192.0.2.5 via xe-0/0/0.0
2:64512:21::10100::00:86:2b:5c:0d:01/304
                   *[EVPN/170] 00:12:16
                      Indirect
3:64512:11::10100::172.16.1.1/304
                   *[BGP/170] 00:18:40, localpref 100, from 172.31.0.1
                      AS path: I, validation-state: unverified
                    > to 192.0.2.5 via xe-0/0/0.0
3:64512:21::10100::172.16.2.1/304
                   *[EVPN/170] 00:14:43
                      Indirect
3:64512:21::10200::172.16.2.1/304
                   *[EVPN/170] 00:14:43
                      Indirect
{master:0}
kotetsu@spine21> show route forwarding-table

...

Routing table: :vxlan.inet
Internet:
Destination        Type RtRef Next hop           Type Index    NhRef Netif
default            perm     0                    rjct     1716     1
0.0.0.0/32         perm     0                    dscd     1714     1
169.254.0.0/24     user     0                    rtbl        1     5
169.254.0.2/32     user     0 169.254.0.2        locl      334     3
172.16.1.1/32      user     0                    indr   131070     3
                              192.0.2.5          ucst     1711     7 xe-0/0/0.0
172.16.2.1/32      user     0                    rtbl        1     5
192.0.2.4/30       user     0                    rtbl        1     5
192.0.2.6/32       user     0 192.0.2.6          locl     1709     3
224.0.0.0/4        perm     0                    mdsc     1715     1
224.0.0.1/32       perm     0 224.0.0.1          mcst     1718     1
255.255.255.255/32 perm     0                    bcst     1719     1

...

Routing table: default-switch.bridge
Bridging domain: VLAN0100.bridge
VPLS:
Destination        Type RtRef Next hop           Type Index    NhRef Netif
00:86:2b:5c:0d:01/48 user     0                  ucst     1730     6 xe-0/0/1.0
00:86:2b:8d:10:01/48 user     0                  comp     1723     6
0x30006/51         user     0                    comp     1731     2
0x30004/51         user     0                    comp     1725     2
0x30001/51         user     0                    comp     1726     2

Routing table: default-switch.bridge
Bridging domain: VLAN0200.bridge
VPLS:
Destination        Type RtRef Next hop           Type Index    NhRef Netif
0x30007/51         user     0                    comp     1734     2
0x30005/51         user     0                    comp     1729     2
0x30002/51         user     0                    comp     1728     2


bb01

{master:0}
kotetsu@bb01> show ethernet-switching table

単純に EVPN 経路を reflect する土管なので bgp.evpn.0 にしか載っていない様子

{master:0}
kotetsu@bb01> show route

...

bgp.evpn.0: 6 destinations, 6 routes (6 active, 0 holddown, 0 hidden)
+ = Active Route, - = Last Active, * = Both

2:64512:11::10100::00:86:2b:8d:10:01/304
                   *[BGP/170] 00:31:03, localpref 100, from 172.16.1.1
                      AS path: I, validation-state: unverified
                    > to 192.0.2.2 via xe-0/0/0.0
2:64512:21::10100::00:86:2b:5c:0d:01/304
                   *[BGP/170] 00:31:01, localpref 100, from 172.16.2.1
                      AS path: I, validation-state: unverified
                    > to 192.0.2.6 via xe-0/0/1.0
3:64512:11::10100::172.16.1.1/304
                   *[BGP/170] 00:46:21, localpref 100, from 172.16.1.1
                      AS path: I, validation-state: unverified
                    > to 192.0.2.2 via xe-0/0/0.0
3:64512:11::10300::172.16.1.1/304
                   *[BGP/170] 00:37:52, localpref 100, from 172.16.1.1
                      AS path: I, validation-state: unverified
                    > to 192.0.2.2 via xe-0/0/0.0
3:64512:21::10100::172.16.2.1/304
                   *[BGP/170] 00:36:05, localpref 100, from 172.16.2.1
                      AS path: I, validation-state: unverified
                    > to 192.0.2.6 via xe-0/0/1.0
3:64512:21::10200::172.16.2.1/304
                   *[BGP/170] 00:35:45, localpref 100, from 172.16.2.1
                      AS path: I, validation-state: unverified
                    > to 192.0.2.6 via xe-0/0/1.0


{master:0}
kotetsu@bb01> show route forwarding-table

...

パケットキャプチャ

いくつか特徴的なパケットを拾って眺めていきます。

前述の通り、今回は RE 同士を接続するところで直結構成にしてしまい bb01xe-0/0/2 から captureSW 方面にポートミラーリングして、GNS3 の bb01(RE)captureSW 間のリンクを右クリックして start capture とかやっていきます。
なので bb01 に以下のような設定をして、xe-0/0/0 (spine11 側)の出入りを xe-0/0/2ミラーリングしときます。

set interfaces xe-0/0/2 description "DEV=captureSW IF=1"
set interfaces xe-0/0/2 unit 0 family ethernet-switching

set forwarding-options analyzer ANAL_PORT input ingress interface xe-0/0/0.0
set forwarding-options analyzer ANAL_PORT input egress interface xe-0/0/0.0
set forwarding-options analyzer ANAL_PORT output interface xe-0/0/2.0

見返していて思ったんすが、アナルポートって...ちょっと...

あと、vQFX でも start shell して tcpdump とか使えますよ。Control Plane 宛のトラフィックだけとりたい時とかには。

DataPlane

bb01 で拾った VXLAN のパケットを見ていきます。

node11 から node21ping うった時、最初に出る ARP Request と ARP reply
VXLAN カプセルの IP ヘッダ的にはマルチキャストではなく、spine11 VTEPspine21 VTEP 間のユニキャストになってます。

f:id:kakkotetsu:20170511233328p:plain

f:id:kakkotetsu:20170511233339p:plain

node11node21 間の ICMP echo Request と ICMP echo Reply
これは EVPN 使おうが関係なく、ただの VXLAN ヘッダついたパケットです。

f:id:kakkotetsu:20170511233355p:plain

f:id:kakkotetsu:20170511233404p:plain

ControlPlane

bb01 で拾った EVPN のパケットを見ていきます。

EVPN NLRI Type2(MAC/IP Advertisement route) Update

まずは node11 からの ARP Request を受信した spine11 が advertise する様子
f:id:kakkotetsu:20170511233423p:plain

次に node21 からの ARP Reply を受信した spine21 が advertise したのを bb01spine11 方面に reflect する様子
f:id:kakkotetsu:20170511233441p:plain

EVPN NLRI Type2(MAC/IP Advertisement route) Withdrawn

spine11clear ethernet-switching table して node11MAC を消す
f:id:kakkotetsu:20170511233456p:plain

EVPN NLRI Type3(Inclusive Multicast Ethernet Tag route) Withdrawn

spine21 で以下のような感じで、雑に VLAN 100 = VNI10100 at RD 64512:21 が消えたことを advertise させた時の様子

{master:0}[edit]
kotetsu@spine21# deactivate vlans VLAN0100

{master:0}[edit]
kotetsu@spine21# show | compare
[edit vlans]
!    inactive: VLAN0100 { ... }

{master:0}[edit]
kotetsu@spine21# commit

f:id:kakkotetsu:20170511233515p:plain

次に spine21 で VLAN 100 = VNI10100 at RD 64512:21 ができたことを advertise させた時の様子

{master:0}[edit]
kotetsu@spine21# activate vlans VLAN0100

{master:0}[edit]
kotetsu@spine21# show | compare
[edit vlans]
!    active: VLAN0100 { ... }

{master:0}[edit]
kotetsu@spine21# commit

f:id:kakkotetsu:20170511233529p:plain

おしまい

  • 仮想版でも Juniper vQFX で L2VPN 機能が動くことを確認できました
  • linux kernel で EVPN しゃべるようになりませんかね(MPLS は入ったのだし)
    • 冒頭の絵でいうところの オレンジ領域(L3) は出来るだけエンドまで降りてきて欲しくないですか
      • Juniper の例示では、ToR スイッチ(QFX5100)まではきていますよね
      • そしたら linux kernel まで降りてきて、物理スイッチは MP-BGP の土管になれば...とか思ったわけです

vQFX10000 を KVM+GNS3 で動かす (original : 2017/01/02)

この記事は某所で 2017/01/02 に書いた記事のコピーです。
そのため 2017/05/11 時点ではやや古い情報も含まれています。(以下一例)

  • Juniper さんの vQFX ダウンロード規約が変わっていそう (詳細は未確認)
  • 201705 に GNS3 ver2.0 stable が出た

.

最初に

個人メール/名義で Juniper vQFX10000 trial 版 のダウンロード権限申請をしたら、ちょっとしたメールのやりとりの後に権限を頂けました。
Juniper さんへの感謝を込めて、幾つか記事を投稿しておきます。

本項でやること

  • Juniper QFX10000 シリーズの仮想版であるところの Juniper vQFX10000 を KVM+GNS3 で動かして、簡単な L2 疎通確認をするところまで
  • 公式サイトで案内されている Installation Guide (Juniper 公式 gitbuh | Juniper/vqfx10k-vagrant) では vagrant でのインストール手順のみが公開されている(2016/12/22現在)が、OSイメージとしては vmdk 版も配布されているし(&自分のメイン環境が KVM なので)、という都合
  • KVM や GNS3 の導入手順、Junos 操作の基礎は省略 (ある程度知っている人向け)

Juniper vQFX?

  • Juniper QFX10000 シリーズの仮想版(trial)
  • 少なくとも 2016/07 時点では「github 上に Installation Guide はあがっているけれど、OSイメージは公開されていない」という状況だった
    • 2016/12現在、いつのまにか Free Trial が始まっていたことに気付いた
    • そして上記の Installation Guide が公式なものになっている
  • 例によって、ダウンロードするためには権限申請が必要
    • 今回も個人アカウントで申請したのですが Juniper の方とちょっとしたメールのやりとりで承認して頂けました。本当にありがとうございます。

環境情報

軽く

  • KVM 母艦
    • Ubuntu16.04.1-server-amd64
    • apt で降ってくる KVM と GNS3 一式
  • vQFX10000
    • PFE も RE も 2016/12/22 時点で trial ダウンロード可能な最新版
      • PFE は vqfx10k-pfe-20160609-2.vmdk
      • RE は vqfx10k-re-15.1X53-D60.vmdk
$ uname -a
Linux vkvm02 4.4.0-57-generic #78-Ubuntu SMP Fri Dec 9 23:50:32 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux

$ cat /etc/lsb-release
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=16.04
DISTRIB_CODENAME=xenial
DISTRIB_DESCRIPTION="Ubuntu 16.04.1 LTS"

$ virsh -v
1.3.1

$ qemu-system-x86_64 --version
QEMU emulator version 2.5.0 (Debian 1:2.5+dfsg-5ubuntu10.6), Copyright (c) 2003-2008 Fabrice Bellard

$ gns3 --version
1.5.2

Install 手順

KVM 一式や GNS3 は以下あたりを参考に導入済みであること。(雑)

vQFX イメージファイル入手 ~ 配置 ~ format 変換

イメージファイル入手~KVM母艦に配置

  1. 前述の公式から飛べる vQFX Evaluation - Download Software
  2. 2016/12/22 現在ダウンロード可能な最新版一式(今回は Formatvmdk の 2 ファイルのみで OK)をダウンロード
    • VQFX10K PFE Disk Image
    • VQFX10K RE Disk Image
  3. KVM母艦に配置
$ md5sum vm_images/vqfx10k-pfe-20160609-2.vmdk
faa6905fd8e935c6e97859191143e8c3  vm_images/vqfx10k-pfe-20160609-2.vmdk
$ cat vm_images/vqfx10k-pfe-20160609-2_md5.txt
faa6905fd8e935c6e97859191143e8c3

$ md5sum vm_images/vqfx10k-re-15.1X53-D60.vmdk
758669e88213fbd7943f5da7f6d7bd59  vm_images/vqfx10k-re-15.1X53-D60.vmdk
$ cat vm_images/vqfx10k-re-15.1X53-D60_md5.txt
758669e88213fbd7943f5da7f6d7bd59

vmdk を qcow2 に format 変換

いつも通り

$ cd ~/vm_images/
$ mkdir qemu
$ ls -al
total 917640
drwxrwxr-x  3 kotetsu kotetsu      4096 Dec 25 11:32 .
drwxr-xr-x 12 kotetsu kotetsu      4096 Dec 25 11:08 ..
drwxrwxr-x  2 kotetsu kotetsu      4096 Dec 25 11:32 qemu
-rw-r--r--  1 kotetsu kotetsu        32 Dec 24 10:59 vqfx10k-pfe-20160609-2_md5.txt
-rw-r--r--  1 kotetsu kotetsu 584086528 Dec 24 10:42 vqfx10k-pfe-20160609-2.vmdk
-rw-r--r--  1 kotetsu kotetsu        32 Dec 24 11:00 vqfx10k-re-15.1X53-D60_md5.txt
-rw-r--r--  1 kotetsu kotetsu 355542528 Dec 24 10:50 vqfx10k-re-15.1X53-D60.vmdk

$ qemu-img convert -f vmdk -O qcow2 vqfx10k-pfe-20160609-2.vmdk qemu/vqfx10k-pfe-20160609-2.qcow2
$ qemu-img convert -f vmdk -O qcow2 vqfx10k-re-15.1X53-D60.vmdk qemu/vqfx10k-re-15.1X53-D60.qcow2

$ ls -al qemu/
total 1585044
drwxrwxr-x 2 kotetsu kotetsu       4096 Dec 25 11:37 .
drwxrwxr-x 3 kotetsu kotetsu       4096 Dec 25 11:32 ..
-rw-r--r-- 1 kotetsu kotetsu 1144782848 Dec 25 11:37 vqfx10k-pfe-20160609-2.qcow2
-rw-r--r-- 1 kotetsu kotetsu  478412800 Dec 25 11:37 vqfx10k-re-15.1X53-D60.qcow2

GNS3 上でテンプレートイメージとして登録

ここは、各人が使っている KVM 管理ソフトウェアに読み替えて下さい。 CPU/Memory の要件は、前述の Installation Guide に書いてあります。

PFE

以下でとりあえず(自分の検証用途では問題なく)動いてます。

f:id:kakkotetsu:20170511222203p:plain

RE

以下でとりあえず(自分の検証用途では問題なく)動いてます。 ここの Adapters 数は、最低 2 個必要で 4 個目からが xe-0/0/0~マッピングされます。上限数はちゃんと確認していないものの、6 個しか割り当てなくても固定で xe-0/0/11 まで見えるし、12個の筈。

f:id:kakkotetsu:20170511222238p:plain

GNS3 でテンプレートからデプロイ ~ 結線 ~ 起動

登録したテンプレートから PFE と RE を 1 セットドラッグアンドドロップでデプロイします。 一応、ついでに適当な疎通確認用のノードも 2 個くらい作っておきました。

結線時、各仮想マシンの外から見える Adapters のカウントと OS 内のインターフェース対応は以下の感じです。PFE の 2 個目と RE の 2 個目を接続しておけば、最低限 PFE を認識するところまでは動きます。

コンポーネント 外から見えるインターフェース番号(GNS3 デフォルト名) OSでの使われ方 備考
PFE 1 (Ethernet0) eth0 初期設定で DHCP になっている管理インターフェースなので、必要に応じて外界と接続
PFE 2 (Ethernet1) eth1 (169.254.0.1/24) RE との Dedicated Link
RE 1 (Ethernet0) em0 初期設定で DHCP になっている管理インターフェースなので、必要に応じて外界と接続したり固定アドレスに変更したり
RE 2 (Ethernet1) em1 (169.254.0.2/24) PFE との Dedicated Link
RE 3 (Ethernet2) 不明 使ったことないけどたぶん em2 かと
RE 4~ (Ethernet3~) xe-0/0/0~

というわけで、例えば以下の感じで。

f:id:kakkotetsu:20170511222305p:plain

絵でいうところの SW1Cloud というやつは外界 (母艦KVMlinux bridge へ)に接続して、既存環境と相互通信(管理用)させています。その辺はまあ、環境に合わせて。

余談ですが、GNS3 1.5.2 では github gns3-gui issues | QEMU link Packet Captures の通り qemu 同士の結線ではパケットキャプチャできないので、複数デプロイして RE 同士を接続する場合には、間に GNS3 の Ethernet Switch を挟んだり、vQFX 側で port mirroring したりとかの工夫をすることになるかと思います。(ということで GNS3 2.0 stable 以降を使おう!)

あとは RE と PFE を GNS3 から Start してしばらく待ちます。 RE が起動してから結構待つと、PFE と勝手に繋がって PFE が見えるようになります。気長に待ちましょう。

~$ ps aux | grep [Q]FX
root      4819 56.8  7.0 1907744 1165860 pts/10 Sl+ Dec25  63:24 /usr/bin/qemu-system-x86_64 -name vQFX_RE_15.1X53-D60-1 -m 1024M -smp cpus=1 -enable-kvm -boot order=c -drive file=/home/kotetsu/GNS3/projects/vqfx/project-files/qemu/f8b3330f-b59c-4035-970e-77368631a1f5/hda_disk.qcow2,if=ide,index=0,media=disk -serial telnet:127.0.0.1:5001,server,nowait -monitor tcp:127.0.0.1:55276,server,nowait -net none -device e1000,mac=00:86:2b:a1:f5:00,netdev=gns3-0 -netdev socket,id=gns3-0,udp=127.0.0.1:10011,localaddr=127.0.0.1:10010 -device e1000,mac=00:86:2b:a1:f5:01,netdev=gns3-1 -netdev socket,id=gns3-1,udp=127.0.0.1:10000,localaddr=127.0.0.1:10005 -device e1000,mac=00:86:2b:a1:f5:02 -device e1000,mac=00:86:2b:a1:f5:03 -device e1000,mac=00:86:2b:a1:f5:04,netdev=gns3-4 -netdev socket,id=gns3-4,udp=127.0.0.1:10004,localaddr=127.0.0.1:10003 -device e1000,mac=00:86:2b:a1:f5:05,netdev=gns3-5 -netdev socket,id=gns3-5,udp=127.0.0.1:10002,localaddr=127.0.0.1:10001 -nographic

root      4826 99.3  9.3 2468864 1533164 pts/10 Sl+ Dec25 110:45 /usr/bin/qemu-system-x86_64 -name vQFX_PFE_20160609-1 -m 1536M -smp cpus=1 -enable-kvm -boot order=c -drive file=/home/kotetsu/GNS3/projects/vqfx/project-files/qemu/21773ec6-55f8-4c3f-9cfb-fedd5f0f38da/hda_disk.qcow2,if=ide,index=0,media=disk -serial telnet:127.0.0.1:5000,server,nowait -monitor tcp:127.0.0.1:44622,server,nowait -net none -device e1000,mac=00:86:2b:38:da:00 -device e1000,mac=00:86:2b:38:da:01,netdev=gns3-1 -netdev socket,id=gns3-1,udp=127.0.0.1:10005,localaddr=127.0.0.1:10000 -nographic

Junos 側の確認

RE 確認

Juniper 公式 gitbuh | Juniper/vqfx10k-vagrant にも書いてありますが、アカウント: root パスワード: Juniper でログインしたら、いつも通り cli コマンドで JUNOS shell へ入ります。

基本情報を確認... QFX3500 とか書いてある...けど、本質ではないので無視。

{master:0}
root@vqfx-re> show chassis hardware
Hardware inventory:
Item             Version  Part number  Serial number     Description
Chassis                                84425636318       QFX3500


{master:0}
root@vqfx-re> show version
fpc0:
--------------------------------------------------------------------------
Hostname: vqfx-re
Model: vqfx-10000
Junos: 15.1X53-D60.4
JUNOS Base OS boot [15.1X53-D60.4]
JUNOS Base OS Software Suite [15.1X53-D60.4]
JUNOS Crypto Software Suite [15.1X53-D60.4]
JUNOS Online Documentation [15.1X53-D60.4]
JUNOS Kernel Software Suite [15.1X53-D60.4]
JUNOS Packet Forwarding Engine Support (qfx-10-f) [15.1X53-D60.4]
JUNOS Routing Software Suite [15.1X53-D60.4]
JUNOS Enterprise Software Suite [15.1X53-D60.4]
JUNOS Web Management [15.1X53-D60.4]
JUNOS py-base-i386 [15.1X53-D60.4]


{master:0}
root@vqfx-re> show system license
License usage: none

Licenses installed: none
root@vqfx-re:RE:0% uname -a
JUNOS vqfx-re 15.1X53-D60.4 JUNOS 15.1X53-D60.4 #0: 2016-08-26 23:07:01 UTC     builder@mayland.juniper.net:/volume/build/junos/15.1/service/15.1X53-D60.4/obj/i386/junos/bsd/kernels/JUNIPER-QFX/kernel  i386

root@vqfx-re:RE:0% python --version
Python 2.7.8

PFE とつながって、認識されたことを確認。

{master:0}
root@vqfx-re> show pfe terse
fpc0:
--------------------------------------------------------------------------
Slot Type Slot      State     Uptime
 0   FXPC Present   Online    01:23:47


{master:0}
root@vqfx-re> show chassis fpc
                     Temp  CPU Utilization (%)   CPU Utilization (%)  Memory    Utilization (%)
Slot State            (C)  Total  Interrupt      1min   5min   15min  DRAM (MB) Heap     Buffer
  0  Online           Testing  17        12        0      0      0    1024        0         66
  1  Empty
  2  Empty
  3  Empty
  4  Empty
  5  Empty
  6  Empty
  7  Empty
  8  Empty
  9  Empty


{master:0}
root@vqfx-re> show interfaces em1
Physical interface: em1    , Enabled, Physical link is Up
  Interface index: 9, SNMP ifIndex: 23
  Type: Ethernet, Link-level type: Ethernet, MTU: 1514, Speed: 1000mbps
  Device flags   : Present Running
  Interface flags: SNMP-Traps
  Link type      : Full-Duplex
  Current address: 00:86:2b:a1:f5:01, Hardware address: 00:86:2b:a1:f5:01
  Last flapped   : 2016-12-25 13:21:12 UTC (01:25:04 ago)
    Input packets : 614505
    Output packets: 957499

  Logical interface em1.0 (Index 6) (SNMP ifIndex 24)
    Flags: Up SNMP-Traps 0x4000000 Encapsulation: ENET2
    Input packets : 614547
    Output packets: 957499
    Protocol inet, MTU: 1500
      Flags: Sendbcast-pkt-to-re
      Addresses, Flags: Is-Preferred Is-Primary
        Destination: 169.254.0/24, Local: 169.254.0.2, Broadcast: 169.254.0.255


{master:0}
root@vqfx-re> show arp
MAC Address       Address         Name                      Interface               Flags
52:54:00:07:30:c0 10.0.0.65       10.0.0.65                 em0.0                   none
00:a0:de:c0:55:80 10.0.0.254      10.0.0.254                em0.0                   none
00:86:2b:38:da:01 169.254.0.1     169.254.0.1               em1.0                   none
Total entries: 3

当該 RE 仮想マシンに割り当てた Adapters は 6 個だけでしたが、固定で xe-0/0/0xe-0/0/11 まで出来てますねえ...しかも何故か全て Linkup 状態

{master:0}
root@vqfx-re> show interfaces terse
Interface               Admin Link Proto    Local                 Remote
gr-0/0/0                up    up
pfe-0/0/0               up    up
pfe-0/0/0.16383         up    up   inet
                                   inet6
pfh-0/0/0               up    up
pfh-0/0/0.16383         up    up   inet
pfh-0/0/0.16384         up    up   inet
xe-0/0/0                up    up
xe-0/0/0.0              up    up   inet
xe-0/0/1                up    up
xe-0/0/1.0              up    up   eth-switch
xe-0/0/2                up    up
xe-0/0/2.0              up    up   eth-switch
xe-0/0/3                up    up
xe-0/0/3.0              up    up   eth-switch
xe-0/0/4                up    up
xe-0/0/4.0              up    up   eth-switch
xe-0/0/5                up    up
xe-0/0/5.0              up    up   eth-switch
xe-0/0/6                up    up
xe-0/0/6.0              up    up   inet
xe-0/0/7                up    up
xe-0/0/7.0              up    up   inet
xe-0/0/8                up    up
xe-0/0/8.0              up    up   inet
xe-0/0/9                up    up
xe-0/0/9.0              up    up   inet
xe-0/0/10               up    up
xe-0/0/10.0             up    up   inet
xe-0/0/11               up    up
xe-0/0/11.0             up    up   inet
bme0                    up    up
bme0.0                  up    up   inet     128.0.0.1/2
                                            128.0.0.4/2
                                            128.0.0.16/2
                                            128.0.0.63/2
cbp0                    up    up
dsc                     up    up
em0                     up    up
em0.0                   up    up   inet     10.0.0.201/24
em1                     up    up
em1.0                   up    up   inet     169.254.0.2/24
em2                     up    up
em2.32768               up    up   inet     192.168.1.2/24
em3                     up    up
em4                     up    up
em5                     up    up
esi                     up    up
gre                     up    up
ipip                    up    up
irb                     up    up
lo0                     up    up
lo0.0                   up    up   inet
                                   inet6    fe80::286:2b0f:fca1:f500
lo0.16385               up    up   inet
lsi                     up    up
mtun                    up    up
pimd                    up    up
pime                    up    up
pip0                    up    up
tap                     up    up
vme                     up    down
vtep                    up    up

何も設定していない状況でのリソース状況とかを見ていく。

root@vqfx-re:RE:0% vmstat
 procs      memory      page                   disk   faults      cpu
 r b w     avm    fre  flt  re  pi  po  fr  sr ad0   in   sy  cs us sy id
 2 0 0 4940056 289632   79   1   6   0  84   0   0  853 2822 1917  0 29 70


root@vqfx-re:RE:0% df -h
Filesystem             Size    Used   Avail Capacity  Mounted on
/dev/ad0s1a            2.4G    405M    1.8G    18%    /
devfs                  1.0K    1.0K      0B   100%    /dev
/dev/md0                87M     87M      0B   100%    /packages/mnt/jbase
/dev/md1               527M    527M      0B   100%    /packages/mnt/jkernel-qfx-x86-32-15.1X53-D60.4
/dev/md2                31M     31M      0B   100%    /packages/mnt/jpfe-qfx-10-f-15.1X53-D60.4
/dev/md3                11M     11M      0B   100%    /packages/mnt/jdocs-dc-re-15.1X53-D60.4
/dev/md4               215M    215M      0B   100%    /packages/mnt/jroute-qfx-x86-32-15.1X53-D60.4
/dev/md5                32M     32M      0B   100%    /packages/mnt/jcrypto-dc-re-15.1X53-D60.4
/dev/md6                53M     53M      0B   100%    /packages/mnt/jswitch-qfx-x86-32-15.1X53-D60.4
/dev/md7                25M     25M      0B   100%    /packages/mnt/jweb-qfx-15.1X53-D60.4
/var/jail/etc          2.4G    405M    1.8G    18%    /packages/mnt/jweb-qfx-15.1X53-D60.4/jail/var/etc
/var/jail/run          2.4G    405M    1.8G    18%    /packages/mnt/jweb-qfx-15.1X53-D60.4/jail/var/run
/var/jail/tmp          2.4G    405M    1.8G    18%    /packages/mnt/jweb-qfx-15.1X53-D60.4/jail/var/tmp
/var/tmp               2.4G    405M    1.8G    18%    /packages/mnt/jweb-qfx-15.1X53-D60.4/jail/var/tmp/uploads
devfs                  1.0K    1.0K      0B   100%    /packages/mnt/jweb-qfx-15.1X53-D60.4/jail/dev
/var/jail/jweb-app     2.4G    405M    1.8G    18%    /packages/mnt/jweb-qfx-15.1X53-D60.4/jail/var/jweb-app
/dev/md8                12M     12M      0B   100%    /packages/mnt/py-base-i386-15.1X53-D60.4
/dev/md9               1.0G     10K    926M     0%    /tmp
procfs                 4.0K    4.0K      0B   100%    /proc
/dev/ad0s1e            604M    110K    555M     0%    /config
/var/jails/rest-api    2.4G    405M    1.8G    18%    /packages/mnt/jroute-qfx-x86-32-15.1X53-D60.4/web-api/var

start shell して top

last pid:  1882;  load averages:  0.20,  0.30,  0.31                                                                         up 0+01:17:00  14:36:02
73 processes:  1 running, 71 sleeping, 1 zombie
CPU states:  0.0% user,  0.0% nice,  4.5% system,  9.8% interrupt, 85.7% idle
Mem: 564M Active, 51M Inact, 66M Wired, 89M Cache, 69M Buf, 203M Free
Swap: 1024M Total, 1024M Free

  PID USERNAME  THR PRI NICE   SIZE    RES STATE    TIME   WCPU COMMAND
 1452 root        4  96    0   336M   231M select   7:28  3.76% olive-ultimat.elf

起動直後のところだけ dmesg を抜粋。

root@vqfx-re:RE:0% dmesg | more
Copyright (c) 1996-2016, Juniper Networks, Inc.
All rights reserved.
Copyright (c) 1992-2007 The FreeBSD Project.
Copyright (c) 1979, 1980, 1983, 1986, 1988, 1989, 1991, 1992, 1993, 1994
        The Regents of the University of California. All rights reserved.
FreeBSD is a registered trademark of The FreeBSD Foundation.
JUNOS 15.1X53-D60.4 #0: 2016-08-26 23:07:01 UTC
    builder@mayland.juniper.net:/volume/build/junos/15.1/service/15.1X53-D60.4/obj/i386/junos/bsd/kernels/JUNIPER-QFX/kernel
can't re-use a leaf (fe_storm_timeout)!
can't re-use a leaf (alt_break_to_debugger)!
can't re-use a leaf (break_to_debugger)!
Timecounter "i8254" frequency 1193182 Hz quality 0
CPU: QEMU Virtual CPU version 2.5+ (3096.49-MHz 686-class CPU)
  Origin = "GenuineIntel"  Id = 0x663  Stepping = 3
  Features=0x783fbfd<FPU,DE,PSE,TSC,MSR,PAE,MCE,CX8,APIC,SEP,MTRR,PGE,MCA,CMOV,PAT,PSE36,MMX,FXSR,SSE,SSE2>
  Features2=0x80202021<SSE3,VMX,CX16,x2APIC,<b31>>
  AMD Features=0x20100800<SYSCALL,NX,LM>
  AMD Features2=0x1<LAHF>
real memory  = 1073741824 (1024 MB)
avail memory = 1017835520 (970 MB)
MPTable: <BOCHSCPU 0.1         >
Security policy loaded: Junos MAC/veriexec (mac_veriexec)
MAC/veriexec fingerprint module loaded: SHA256
MAC/veriexec fingerprint module loaded: SHA1
ioapic0: Assuming intbase of 0
ioapic0 <Version 1.1> irqs 0-23 on motherboard
ETHERNET SOCKET BRIDGE initialising
fpga driver loaded, 0 (null)
FXPCI warning: hw.pci.enable_static_config is not set.
Initializing Kernel PVIDB.
Initializing DCF X86 platform properties ..
Calling dcf_ng_hw_init for platform hw vecs initialization
    ACPI-0314: *** Error: Invalid signature where RSDP indicates RSDT/XSDT should be located
    ACPI-0325: *** Error: Looking for RSDT (RSDP->Rev < 2)
    ACPI-0181: *** Error: AcpiLoadTables: Could not load RSDT: AE_BAD_SIGNATURE
    ACPI-0213: *** Error: AcpiLoadTables: Could not load tables: AE_BAD_SIGNATURE
ACPI: table load failed: AE_BAD_SIGNATURE
cpu0 on motherboard
pcib0: <MPTable Host-PCI bridge> pcibus 0 on motherboard
pci0: <PCI bus> on pcib0
Correcting Natoma config for non-SMP
isab0: <PCI-ISA bridge> at device 1.0 on pci0
isa0: <ISA bus> on isab0
atapci0: <Intel PIIX3 WDMA2 controller> port 0x1f0-0x1f7,0x3f6,0x170-0x177,0x376,0xc180-0xc18f at device 1.1 on pci0
ata0: <ATA channel 0> on atapci0
ata1: <ATA channel 1> on atapci0
smb0: <Intel 82371AB SMB controller> irq 9 at device 1.3 on pci0
pci0: <display, VGA> at device 2.0 (no driver attached)
pci0: <network, ethernet> at device 3.0 (no driver attached)
pci0: <network, ethernet> at device 4.0 (no driver attached)
pci0: <network, ethernet> at device 5.0 (no driver attached)

PFE 確認

Juniper 公式 gitbuh | Juniper/vqfx10k-vagrant にも書いてありますが、アカウント: root パスワード: no でログインできます。あまり入ることないですが。

root@localhost:~# uname -a
Linux localhost 3.10.62-ltsi-WR6.0.0.21_standard #1 SMP PREEMPT Mon Nov 30 07:26:43 PST 2015 x86_64 x86_64 x86_64 GNU/Linux


root@localhost:~# ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
    link/ether 00:86:2b:38:da:00 brd ff:ff:ff:ff:ff:ff
    inet6 fe80::286:2bff:fe38:da00/64 scope link
       valid_lft forever preferred_lft forever
3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
    link/ether 00:86:2b:38:da:01 brd ff:ff:ff:ff:ff:ff
    inet 169.254.0.1/24 brd 169.254.0.255 scope global eth1
       valid_lft forever preferred_lft forever
    inet6 fe80::286:2bff:fe38:da01/64 scope link
       valid_lft forever preferred_lft forever
4: sit0: <NOARP> mtu 1480 qdisc noop state DOWN
    link/sit 0.0.0.0 brd 0.0.0.0

root@localhost:~# ip route
169.254.0.0/24 dev eth1  proto kernel  scope link  src 169.254.0.1

root@localhost:~# cat /etc/network/interfaces
# /etc/network/interfaces -- configuration file for ifup(8), ifdown(8)

# The loopback interface
auto lo
iface lo inet loopback
auto eth0
iface eth0 inet dhcp
auto eth1
iface eth1 inet static
address 169.254.0.1
netmask 255.255.255.0

デフォルト状態だとさほどメモリ持っていかれないようです。

root@localhost:~# vmstat
procs -----------memory---------- ---swap-- -----io---- -system-- ----cpu----
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa
 2  0      0 367600  11748 498320    0    0    37    37 1188  445 76 24  1  0


root@localhost:~# free
             total       used       free     shared    buffers     cached
Mem:       1533320    1165648     367672          0      11708     498332
-/+ buffers/cache:     655608     877712
Swap:          972          0        972


root@localhost:~# df -h
Filesystem      Size  Used Avail Use% Mounted on
rootfs          1.9G  837M  941M  48% /
udev            732M     0  732M   0% /dev
none            732M     0  732M   0% /dev
tmpfs           749M  240K  749M   1% /run
/dev/sda3       1.9G  837M  941M  48% /
/dev/sda5       597M   52M  502M  10% /var
tmpfs           749M  240K  749M   1% /run
tmpfs           749M     0  749M   0% /var/volatile
/dev/sda1       1.2G  210M 1004M  18% /boot
/dev/sda2       103M  1.6M   94M   2% /app_disk
tmpfs           749M  240K  749M   1% /run/named-chroot/var/run/named
tmpfs           749M  240K  749M   1% /run/named-chroot/var/run/bind
none            732M     0  732M   0% /run/named-chroot/dev/random
none            732M     0  732M   0% /run/named-chroot/dev/zero
none            732M     0  732M   0% /run/named-chroot/dev/null

簡易疎通確認

前の絵でノードを 2 個繋いでいるので、適当にその物理IFに access vlan 100 を割り当てて疎通確認しました。(雑)

{master:0}
root@vqfx-re> show ethernet-switching interface
Routing Instance Name : default-switch
Logical Interface flags (DL - disable learning, AD - packet action drop,
                         LH - MAC limit hit, DN - interface down,
                         MMAS - Mac-move action shutdown,
                         SCTL - shutdown by Storm-control )

Logical          Vlan          TAG     MAC         STP         Logical           Tagging
interface        members               limit       state       interface flags
xe-0/0/1.0                             8192                                       untagged
                 VLAN0100      100     1024        Forwarding                     untagged
Routing Instance Name : default-switch
Logical Interface flags (DL - disable learning, AD - packet action drop,
                         LH - MAC limit hit, DN - interface down,
                         MMAS - Mac-move action shutdown,
                         SCTL - shutdown by Storm-control )

Logical          Vlan          TAG     MAC         STP         Logical           Tagging
interface        members               limit       state       interface flags
xe-0/0/2.0                             8192                                       untagged
                 VLAN0100      100     1024        Forwarding                     untagged



{master:0}
root@vqfx-re> show ethernet-switching table

MAC flags (S - static MAC, D - dynamic MAC, L - locally learned, P - Persistent static, C - Control MAC
           SE - statistics enabled, NM - non configured MAC, R - remote PE MAC, O - ovsdb MAC)


Ethernet switching table : 2 entries, 2 learned
Routing instance : default-switch
    Vlan                MAC                 MAC         Age    Logical                NH        RTR
    name                address             flags              interface              Index     ID
    VLAN0100            00:86:2b:47:b6:01   D             -   xe-0/0/2.0             0         0
    VLAN0100            00:86:2b:8d:10:01   D             -   xe-0/0/1.0             0         0

おしまい

  • インストールしただけなので別に...
  • Juniper さんありがとうございます!感謝を込めて、vQFX で試した内容を追っていくつか纏めておきます。

参考書籍

Juniper QFX10000 の独自プロセッサ開発経緯や特徴・Architecture(HW/SW) の結構詳しい説明・MPLS/VXLAN+EVPNの設計ポイントなど、非常に良い本なので、こんなニッチな記事を読んでいる人におススメ!

Juniper QFX10000 Series: A Comprehensive Guide to Building Next-Generation Data Centers

Juniper QFX10000 Series: A Comprehensive Guide to Building Next-Generation Data Centers

Juniper QFX10000 Series: A Comprehensive Guide to Building Next-Generation Data Centers (English Edition)

Juniper QFX10000 Series: A Comprehensive Guide to Building Next-Generation Data Centers (English Edition)

NW 機器の自前構成情報管理 (ruby-nmap+SNMP で Discovery ~ Ansible Dynamic Inventory 連携) (original : 2015/12/15)

この記事は某所で 2015/12/15 に書いたもののコピーです。
そのため 2017/05/13 時点ではやや古い情報も含まれています。(以下一例)

  • Ansible のバージョン 1.8 系、今となっては古い

.

概要

NetOpsCoding Advent Calendar 2015 の 2015/12/15 分エントリです。 Ansible Dynamic Inventory で検索してこれにぶつかった人、ごめんなさい。そこはオマケ程度です。

本項でやること

  • Nmap と SNMPruby で操作して、手っ取り早く NW 機器の構成情報を取得~ JSON 形式で吐き出す
    • 最後に書いているが、自前で書かなくても OSS で同じことは出来るものはある
    • Nmap の ruby 版ライブラリ紹介
  • 上記ファイルを構成情報マスタとみなして、Ansible の dynamic inventory と連携する

モチベーション

  • 仮想マシンの構成管理ソフトは割とあるけれど、物理含めた NW 機器も統合的に…となると選択肢は少ない…
  • Nmap の fingerprint (OS検出)みたいなことも NW 機器相手に高精度でやりたい
  • 色々なミドルウェアで hosts ファイル的な異なるフォーマットの設定ファイルを求めてくるが、手っ取り早く生成したい
  • 大袈裟な仕組みは使いたくない
  • 2015/11/19 に Nmap 7.0 がリリースされたので使わなきゃ(使命感)

前段

Nmap

言わずと知れた OSS ツールで、以下のような機能があります。超優れもの!

  • Host Discovery | 公式
    • 対象 NW を ARG で食わせたり、テキストファイルに羅列して食わせたり
    • 出力は xml ファイルや stdout
    • ついでに名前解決(逆引き)までしてくれる(hosts ファイルでも DNS サーバでも resolve 設定に従う感じで)
  • OS Detection(fingerprint) | 公式
    • ポートスキャンの結果などから、対象機器の OS を類推する
  • etc etc

まあ 公式ドキュメントのイントロ を見れば分かるでしょう。
インフラ屋さんだと、ファイアウォールやら iptables やらのテストや、簡易な脆弱性診断で使ったりで馴染み深いのでは。
監視ソフトの Discovery 機能なんかでも、内部的に Nmap を呼んでいるものがあります。  

基本的にはシェルから扱うのですが、GUI ツールであるZenmapもあります。

ruby-nmap

上記公式からの抜粋↓

A Rubyful interface to the Nmap exploration tool and security / port scanner.

以下のようなことができる Nmap の ruby 版ライブラリです。(作者は異なるものの、同じような機能を持つ Python 版や Perl 版ライブラリも存在する)

  • Host Discovery のオプション群を分かりやすい表現で書ける
  • Host Discovery で生成された xml をパース
    • xml のパースを自前でやらなくて済むってだけで、嬉しくないですか。僕は嬉しい。

公式の Examples を見ると一目瞭然でしょう。

Ruby SNMP

SNMP を扱える ruby 版ライブラリです。(雑)
割と日本語記事も多いし、メジャーなやつでしょう。

Ansible Dynamic Inventory

他の場所に構成管理マスタがあり、Ansible の hosts ファイルを静的に書くと二重管理になるような環境で、構成管理マスタから hosts 情報をとってくる…という機能。

Discovery 環境準備

Discovery サーバ環境情報

Discovery を動かすサーバは以下です。

$ cat /etc/lsb-release
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=14.04
DISTRIB_CODENAME=trusty
DISTRIB_DESCRIPTION="Ubuntu 14.04.3 LTS"

$ ruby -v
ruby 2.2.3p173 (2015-08-18 revision 51636) [x86_64-linux]

$ gem list

*** LOCAL GEMS ***

bigdecimal (1.2.6)
bundler (1.10.6)
io-console (0.4.3)
json (1.8.1)
minitest (5.4.3)
power_assert (0.2.2)
psych (2.0.8)
rake (10.4.2)
rdoc (4.2.0)
test-unit (3.0.8)

あと、このサーバから network reachable な NW 機器をいくらか動かしておきます。(本項では同一セグメント)

Nmap 7.0 インストール

以下公式手順に従います。

Download は以下から。

こんな感じでいけるでしょう。

$ sudo -E apt-get install libssl-dev
$ cd /var/tmp/
$ wget https://nmap.org/dist/nmap-7.00.tar.bz2
$ bzip2 -cd nmap-7.00.tar.bz2 | tar xvf -

$ ls -al
total 8724
drwxrwxrwt  3 root  root     4096 Dec  5 14:38 .
drwxr-xr-x 11 root  root     4096 Nov  7 17:42 ..
drwxr-xr-x 22 kotetsu kotetsu  4096 Nov 20 01:19 nmap-7.00
-rw-rw-r--  1 kotetsu kotetsu 8918906 Nov 20 05:23 nmap-7.00.tar.bz2

$ cd nmap-7.00/
$ ./configure
$ make
$ sudo -E make install

(略)

NMAP SUCCESSFULLY INSTALLED

$ nmap --version

Nmap version 7.00 ( https://nmap.org )
Platform: x86_64-unknown-linux-gnu
Compiled with: nmap-liblua-5.2.3 openssl-1.0.1f nmap-libpcre-7.6 nmap-libpcap-1.7.3 nmap-libdnet-1.12 ipv6
Compiled without:
Available nsock engines: epoll poll select

ruby-nmap / snmp の gem インストール

どちらも gem install 一発で入ります。
ruby-nmapxml を扱う関係上、依存関係に Nokogiri があります。なので、インストールで躓いたらググって解決して下さい。

以下は bundler を使った場合の手順です。

$ cd
$ mkdir discovery
$ cd discovery/
$ bundle init
Writing new Gemfile to /home/kotetsu/discovery/Gemfile

Gemfile を以下のように編集

$ cat Gemfile
# A sample Gemfile
source "https://rubygems.org"

#
gem 'ruby-nmap'
gem `snmp`


$ bundle install --path vendor/bundle
$ cat Gemfile.lock
GEM
  remote: https://rubygems.org/
  specs:
  mini_portile2 (2.0.0)
  nokogiri (1.6.7)
    mini_portile2 (~> 2.0.0.rc2)
  rprogram (0.3.2)
  ruby-nmap (0.8.0)
    nokogiri (~> 1.3)
    rprogram (~> 0.3)
  snmp (1.2.0)

PLATFORMS
  ruby

DEPENDENCIES
  ruby-nmap
  snmp

BUNDLED WITH
   1.10.6

NW 機器側の SNMP 設定

今回、OS検知もどきとして SNMP Get で NW 機器の sysDescr を取得します。
機種依存なく NW 機器の OS を知りたいならば、まあこれしかないでしょう、ってことで。

あと、ラック情報とかも纏めて取れるようにしておくと良いよね、ってことでそれは sysLocation に設定しておきます(本項では全部仮想環境なのでアレな感じですが)。

何機種分か設定例を。

  • JUNOS 例

snmp description とかを設定していると、OS 情報(デフォルト値)をとれなくなってしまうので注意。

kotetsu@vsrx01> show configuration | display set | match snmp
set snmp location KotetsuNoteVB
set snmp community KOTETSU_NW
  • Arista 例
vEOS-spine001#show run | inc snmp
snmp-server location KotetsuNoteVB
snmp-server community KOTETSU_NW ro
  • VyOS 例
kotetsu@vtep-vyos01:~$ show configuration commands | match snmp
set service snmp community 'KOTETSU_NW'
set service snmp location 'KotetsuNoteVB'

Discovery スクリプト作成~配置

ディレクト

以下のように適当なディレクトリを用意して、

$ mkdir scripts
$ cd scripts/

後述の 3 つのファイルを配置します。

スクリプト本体

ruby-nmapRuby SNMP を使って NW 機器の構成情報を収集して、JSON ファイルに吐き出すサンプルスクリプトです。

# encoding: utf-8

#
# Usage:
#  bundle exec ruby discovery_nwdevs.rb <setting.yml>
#

require 'nmap/program'
require 'nmap/xml'
require 'snmp'
require 'yaml'
require 'json'


#
# SNMP Get method
#
def snmp_get_system(target_ip, snmp_params)
  manager = SNMP::Manager.new(
    :host => target_ip,
    :port => 161,
    :version => :SNMPv2c,
    :community => snmp_params["community"],
    :timeout => 1,
    :retries => 1
  )

  # sysName にはホスト名
  # sysDescr には機種やバージョン情報
  # sysLocation は(設定していれば)設置場所
  # が入っている筈なので、それをとる
  ret = Hash::new
  ret[:sysname] = manager.get_value(snmp_params["oid_sysname"]).to_s rescue ""
  ret[:sysdesc] = manager.get_value(snmp_params["oid_sysdesc"]).to_s rescue ""
  ret[:syslocation] = manager.get_value(snmp_params["oid_syslocation"]).to_s rescue ""
  manager.close

  return ret
end



#
# main
#
begin

  # 外出ししている情報 YAML ファイルをロード
  params = YAML.load_file(ARGV[0])

  # Nmap の Host Discovery をして xml ファイルに書き出す
  # ポートスキャンは UDP/161 のみに限定して、SNMP Get で情報が取得可能かどうかを見ておく
  # NW 機器なんて Nmap の fingerprint 機能に頼るよりは、SNMP Get で見た方が確実なので、fingerprint もしない
  Nmap::Program.scan do |nmap|
    nmap.syn_scan = false
    nmap.udp_scan = true
    nmap.service_scan = false
    nmap.os_fingerprint = false

    nmap.xml = params["nmap_params"]["xml_file"]
    nmap.verbose = true

    nmap.ports = []
    unless params["nmap_params"]["scan_udp_ports"].nil? then
      params["nmap_params"]["scan_udp_ports"].each do |port|
        nmap.ports << port["port"]
      end
    end

    # Discovery の対象とする NW アドレスを羅列したファイル
    nmap.target_file = params["nmap_params"]["scan_target_files"]["targetfile"]
  end


  # 反応があったノード(up host)の情報(Hash)を格納
  array_hosts = []

  # Nmap の Host Discovery で生成された xml ファイルを走査
  # 反応があったノード(up host)を取得し、
  # UDP/161 が Open 判定されていたら SNMP で追加情報取得する
  Nmap::XML.new(params["nmap_params"]["xml_file"]) do |xml|
    xml.each_up_host do |host|
      hash_host = {}
      hash_snmp_info = {}

      hash_host[:ipaddr] = host.ipv4
      hash_host[:ptr] = host.hostname
      hash_host[:sysname] = ""
      hash_host[:sysdesc] = ""
      hash_host[:syslocation] = ""

      host.each_port do |port|
        if (port.number == 161) && (port.state == :open) then
          hash_snmp_info = snmp_get_system(host.ipv4, params["snmp_params"])
          unless hash_snmp_info.nil? then
            hash_host[:sysname] = hash_snmp_info[:sysname]
            hash_host[:sysdesc] = hash_snmp_info[:sysdesc]
            hash_host[:syslocation] = hash_snmp_info[:syslocation]
          end
        end
      end
      array_hosts << hash_host
    end
  end


  # 収集したノードの情報を JSON 形式ファイルで吐き出す
  unless array_hosts.nil? then
    dir_result = File.expand_path(params["nmap_params"]["output_directory"])

    json_hosts = JSON.pretty_unparse(array_hosts)
    File.open("#{dir_result}/list_nwdev.json","w") do |file|
      file.write(json_hosts)
    end
  end


# なんか適切にエラーハンドリングしてください
rescue SNMP::RequestTimeout => e
  #
rescue StandardError => e
  puts e
  puts e.backtrace
ensure
  #
end

スクリプトの設定ファイル

前述のスクリプトに食わせる設定ファイルです。
別環境でスクリプトに手を加えず、設定ファイルだけ書き換えて使う…みたいなことを考えていたのですが…「標準 MIB の OID が変わるっていうのか?」なんて突っ込みは不可。

setting_discovery_nwdevs.yml

nmap_params :
  # nmap の -iL オプションで渡す discovery 対象を記載したファイル
  scan_target_files :
    targetfile : './target_nw.txt'
  # nmap の -PU -p オプションで渡す UDP ポートスキャン対象
  scan_udp_ports :
    - port : 161
  # nmap の -oX オプションで渡す、Host Discovery の output である xml ファイル
  xml_file : './scan.xml'
  # スクリプトの最終 output である JSON ファイルを生成するディレクトリ(nmap に渡すオプションではないので、nmap_params 配下にいるのは違和感ありますね…)
  output_directory : './'
snmp_params :
  # 動かす環境の NW 機器に設定してある SNMP community
  # 同じ環境の community ならきっと統一されているだろう、という前提のもと…
  community       : 'KOTETSU_NW'
  # SNMP Get 対象の OID たち
  oid_sysname     : '1.3.6.1.2.1.1.5.0'
  oid_sysdesc     : '1.3.6.1.2.1.1.1.0'
  oid_syslocation : '1.3.6.1.2.1.1.6.0'

Nmap input file

Nmap で Host Discovery する対象を羅列したファイル。
ruby-nmap は内部的に nmap に -iL オプションで食わせているだけなので、記法は Target Specification | Nmap 公式 を参照。

target_nw.txt

192.168.101.0/24  # mgmt NW

Discovery 実行~出力確認

スクリプト実行

こんな感じで。
Nmap でポートスキャンするには基本的には root 権限が必要なので、sudo しています。(以下公式の参考資料)

Discoveryスクリプト実行

$ sudo -E bundle exec ruby discovery_nwdevs.rb setting_discovery_nwdevs.yml

Starting Nmap 7.00 ( https://nmap.org ) at 2015-12-05 14:11 JST
Initiating ARP Ping Scan at 14:11
Scanning 255 hosts [1 port/host]
Completed ARP Ping Scan at 14:11, 1.64s elapsed (255 total hosts)

Initiating Parallel DNS resolution of 255 hosts. at 14:11
Completed Parallel DNS resolution of 255 hosts. at 14:11, 0.04s elapsed

(略)

Read data files from: /usr/local/bin/../share/nmap
Nmap done: 256 IP addresses (5 hosts up) scanned in 2.14 seconds
           Raw packets sent: 513 (14.784KB) | Rcvd: 11 (836B)

生成ファイル確認

生成されたファイル

Nmap が生成した scan.xml と、スクリプトが生成した list_nwdev.jsonroot:root で吐き出されています。

$ ls -al
total 60
drwxrwxr-x 2 kotetsu kotetsu  4096 Dec  6 14:11 .
drwxrwxr-x 5 kotetsu kotetsu  4096 Dec  6 14:08 ..
-rw-r--r-- 1 kotetsu kotetsu  3129 Dec  6 14:04 discovery_nwdevs.rb
-rw-r--r-- 1 root    root      643 Dec  6 14:11 list_nwdev.json
-rw-r--r-- 1 root    root    34690 Dec  6 14:11 scan.xml
-rw-r--r-- 1 kotetsu kotetsu   281 Dec  6 14:01 setting_discovery_nwdevs.yml
-rw-rw-r-- 1 kotetsu kotetsu    28 Dec  6 11:07 target_nw.txt

Nmap が生成した xml ファイル

scan.xml の中身を軽く見ていきます。(この辺は、Nmap を使っている人ならよく知っているのでは)

  • 最初のほうで、実際に ruby-nmap が実行したコマンドオプションや Nmap の実行バージョン、実行時刻などが分かる
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE nmaprun>
<?xml-stylesheet href="file:///usr/local/bin/../share/nmap/nmap.xsl" type="text/xsl"?>
<!-- Nmap 7.00 scan initiated Wed Dec  6 14:11:37 2015 as: /usr/local/bin/nmap -sU -oX ./scan.xml -v -p 161 -iL ./target_nw.txt -->
<nmaprun scanner="nmap" args="/usr/local/bin/nmap -sU -oX ./scan.xml -v -p 161 -iL ./target_nw.txt" start="1449637897" startstr="Sat Dec  6 14:11:37 2015" version="7.00" xmloutputversion="1.04">
<scaninfo type="udp" protocol="udp" numservices="1" services="161"/>
<verbose level="1"/>
<debugging level="0"/>
<taskbegin task="ARP Ping Scan" time="1449378697"/>
<taskend task="ARP Ping Scan" time="1449378699" extrainfo="255 total hosts"/>
<taskbegin task="Parallel DNS resolution of 255 hosts." time="1449378699"/>
<taskend task="Parallel DNS resolution of 255 hosts." time="1449378699"/>
  • Down しているホストの情報が続く
<host><status state="down" reason="no-response" reason_ttl="0"/>
<address addr="192.168.101.3" addrtype="ipv4"/>
</host>
<host><status state="down" reason="no-response" reason_ttl="0"/>
<address addr="192.168.101.4" addrtype="ipv4"/>
</host>
  • Up しているホストの情報が続く
<host starttime="1449378697" endtime="1449378699"><status state="up" reason="arp-response" reason_ttl="0"/>
<address addr="192.168.101.30" addrtype="ipv4"/>
<address addr="52:54:00:76:24:2C" addrtype="mac" vendor="QEMU virtual NIC"/>
<hostnames>
<hostname name="vsrx01" type="PTR"/>
</hostnames>
<ports><port protocol="udp" portid="161"><state state="open" reason="udp-response" reason_ttl="64"/><service name="snmp" method="table" conf="3"/></port>
</ports>
<times srtt="24054" rttvar="34787" to="163202"/>
</host>

スクリプトが生成した JSON ファイル

  • Nmap が名前解決出来たもの(以下例では 192.168.101.30 のみ名前登録してあった)は xmlhostnameptr に格納
  • sysnamesysdescsyslocationSNMP Get で取得した情報
  • Nmap で UDP 161 が Open していないと判断した 192.168.101.172 に関しては、ほとんど情報は取得できていない
    • まあ、その IP アドレスが何らかの機器に使われている、ということくらい

list_nwdev.json

[
  {
    "ipaddr": "192.168.101.30",
    "ptr": "vsrx01",
    "sysname": "vsrx01",
    "sysdesc": "Juniper Networks, Inc. vsrx internet router, kernel JUNOS 15.1X49-D15.4, Build date: 2015-07-31 03:30:01 UTC Copyright (c) 1996-2015 Juniper Networks, Inc.",
    "syslocation": "KotetsuNoteVB"
  },
  {
    "ipaddr": "192.168.101.50",
    "ptr": null,
    "sysname": "vEOS-spine001",
    "sysdesc": "Arista Networks EOS version 4.14.8M running on an Arista Networks vEOS",
    "syslocation": "KotetsuNoteVB"
  },
  {
    "ipaddr": "192.168.101.52",
    "ptr": null,
    "sysname": "vEOS-leaf001",
    "sysdesc": "Arista Networks EOS version 4.14.8M running on an Arista Networks vEOS",
    "syslocation": "KotetsuNoteVB"
  },
  {
    "ipaddr": "192.168.101.71",
    "ptr": null,
    "sysname": "vtep-vyos01",
    "sysdesc": "Vyatta VyOS 1.1.1",
    "syslocation": "KotetsuNoteVB"
  },
  {
    "ipaddr": "192.168.101.172",
    "ptr": null,
    "sysname": "",
    "sysdesc": "",
    "syslocation": ""
  }
]

連携例 ~Ansible の Dynamic Inventory~

やること

先に生成した JSON ファイルを「構成情報マスタ」とみなして連携する例として Ansible の Dynamic Inventory で使ってみます。
NW 機器の中から Arista だけを抜き出して、Arista 用の Role を使った Playbook を実行するです。

環境

横着して、昔(2014/12)作った以下環境を流用して Arista をターゲットに使います。

2015/12 現在だと、Ansible は 2.1.0 とかまで出ているし、ansible-eos (Arista 用の Role)もかなり更新が入っていますが…。

Dynamic Inventory サンプルスクリプト

先に作った JSON ファイルをパースして、最低限動くだけのサンプルです。   要するに sysDescr で機種を仕分けているだけ。

dynamic_nwdevs.rb

#! /usr/bin/env ruby
# encoding: utf-8

require 'json'

FILE_INVENTORY = '/home/kotetsu/discovery/scripts/list_nwdev.json'


begin
  
  if (ARGV[0] && ARGV[0] == '--list') then
    ret = {}
    
    list_junos = []
    list_arista = []
    list_vyos = []

    JSON.load(File.open(FILE_INVENTORY).read).each do |nwdev|
      case nwdev["sysdesc"]
      when /^Juniper.*JUNOS.*/
        list_junos << nwdev["ipaddr"]
      when /^Arista Networks EOS.*/
        list_arista << nwdev["ipaddr"]
      when /^Vyatta VyOS/
        list_vyos << nwdev["ipaddr"]
      else
        #
      end
    end

    ret["junos_all"] = list_junos.dup unless list_junos.size == 0
    ret["arista_all"] = list_arista.dup unless list_arista.size == 0
    ret["vyos_all"] = list_vyos.dup unless list_vyos.size == 0
    puts JSON.pretty_unparse(ret)

  elsif (ARGV[1] && ARGV[0] == "--host") then
    JSON.load(File.open(FILE_INVENTORY).read).each do |nwdev|
      if (
        nwdev["sysname"] =~ Regexp.new(ARGV[1]) ||
        nwdev["ipaddr"] =~ Regexp.new(ARGV[1]) ||
        nwdev["ptr"] =~ Regexp.new(ARGV[1])
      ) then
        puts JSON.pretty_unparse(nwdev)
      end
    end
  end


rescue Exception => e
  puts e
  puts e.backtrace
end

公式のサンプルスクリプトでは Python が圧倒的に多いですが、よくある「所定の引数をつけて実行した時に、所定のOutputを返せば良い」系のやつなので、言語は何で書いても良いです。(この程度ならシェルスクリプトでも)

で、これを実行すると以下の感じ。

$ ./dynamic_nwdevs.rb --list
{
  "junos_all": [
    "192.168.101.30"
  ],
  "arista_all": [
    "192.168.101.50",
    "192.168.101.52"
  ],
  "vyos_all": [
    "192.168.101.71"
  ]
}

$ ./dynamic_nwdevs.rb --host vEOS-spine001
{
  "ipaddr": "192.168.101.50",
  "ptr": null,
  "sysname": "vEOS-spine001",
  "sysdesc": "Arista Networks EOS version 4.14.8M running on an Arista Networks vEOS",
  "syslocation": "KotetsuNoteVB"
}

_meta を出さないので、無駄な処理が走るのですがね。まあローカルのファイル読んでいるテスト環境なので…(モゴモゴ)
その辺は Ansible meetuptokyo 2015 Dynamic Inventory | SlideShare のスライド 10~12 を見ましょう。

Arista 用のサンプル Playbook

  • role で Arista 公式の Role を呼んでいる完全に Arista 専用の Playbook
  • hosts では先の ./dynamic_nwdevs.rb --list で出力された arista_all という Arista 全台グループを指定
  • show version して stdout するだけ

playbook_sample_arista.yml

- name: eos nodes
  hosts: arista_all
  gather_facts: no
  sudo: true

  vars:
    eapi_username: kotetsu
    eapi_password: kotetsu
    eapi_protocol: http

  roles:
    - role: arista.eos

  tasks:
    - name: show version
      action: eos_command
      args: {
         commands: [
           "show version"
         ],
         eapi_username: "{{ eapi_username }}",
         eapi_password: "{{ eapi_password }}",
         eapi_protocol: "{{ eapi_protocol }}"
      }
      register: output_version

    - debug: var=output_version

Playbook 実行

レッツゴー
(-i で呼んでいるのが hosts ファイルではなくて、先の dynamic_nwdevs.rb なのがポイント)

DynamicInventoryでPlaybook実行

$ ansible-playbook playbook_sample_arista.yml -f 10 -u ansible -i dynamic_nwdevs.rb

PLAY [eos nodes] **************************************************************

TASK: [arista.eos | check if running on eos node] *****************************
ok: [192.168.101.50]
ok: [192.168.101.52]

TASK: [arista.eos | collect eos facts] ****************************************
ok: [192.168.101.50]
ok: [192.168.101.52]

TASK: [arista.eos | include eos variables] ************************************
ok: [192.168.101.50]
ok: [192.168.101.52]

TASK: [arista.eos | check for working directory] ******************************
ok: [192.168.101.52]
ok: [192.168.101.50]

TASK: [arista.eos | create source] ********************************************
skipping: [192.168.101.52]
skipping: [192.168.101.50]

TASK: [arista.eos | check if pip is installed] ********************************
ok: [192.168.101.50]
ok: [192.168.101.52]

TASK: [arista.eos | copy pip extension to node] *******************************
skipping: [192.168.101.50]
skipping: [192.168.101.52]

TASK: [arista.eos | create tmp config file to load pip] ***********************
skipping: [192.168.101.50]
skipping: [192.168.101.52]

TASK: [arista.eos | load pip eos extension] ***********************************
skipping: [192.168.101.52]
skipping: [192.168.101.50]

TASK: [arista.eos | copy required libraries to node] **************************
ok: [192.168.101.50] => (item=eapilib-0.1.0.tar.gz)
ok: [192.168.101.52] => (item=eapilib-0.1.0.tar.gz)

TASK: [arista.eos | install required libraries] *******************************
ok: [192.168.101.50] => (item=eapilib-0.1.0.tar.gz)
ok: [192.168.101.52] => (item=eapilib-0.1.0.tar.gz)

TASK: [arista.eos | install jsonrpclib] ***************************************
skipping: [192.168.101.50]
skipping: [192.168.101.52]

TASK: [arista.eos | install required libraries and dependencies] **************
skipping: [192.168.101.50] => (item=eapilib-0.1.0.tar.gz)
skipping: [192.168.101.52] => (item=eapilib-0.1.0.tar.gz)

TASK: [show version] **********************************************************
ok: [192.168.101.52]
ok: [192.168.101.50]

TASK: [debug var=output_version] **********************************************
ok: [192.168.101.50] => {
    "output_version": {
        "changed": false,
        "invocation": {
            "module_args": "",
            "module_name": "eos_command"
        },
        "output": [
            {
                "command": "show version",
                "response": {
                    "architecture": "i386",
                    "bootupTimestamp": 1449902847.6,
                    "hardwareRevision": "",
                    "internalBuildId": "a6bbeeb3-95b7-42bc-9721-266f9bff424e",
                    "internalVersion": "4.14.8M-2475814.4148M",
                    "memFree": 20516,
                    "memTotal": 996140,
                    "modelName": "vEOS",
                    "serialNumber": "",
                    "systemMacAddress": "08:00:27:31:60:65",
                    "version": "4.14.8M"
                }
            }
        ]
    }
}
ok: [192.168.101.52] => {
    "output_version": {
        "changed": false,
        "invocation": {
            "module_args": "",
            "module_name": "eos_command"
        },
        "output": [
            {
                "command": "show version",
                "response": {
                    "architecture": "i386",
                    "bootupTimestamp": 1449902847.71,
                    "hardwareRevision": "",
                    "internalBuildId": "a6bbeeb3-95b7-42bc-9721-266f9bff424e",
                    "internalVersion": "4.14.8M-2475814.4148M",
                    "memFree": 46872,
                    "memTotal": 996140,
                    "modelName": "vEOS",
                    "serialNumber": "",
                    "systemMacAddress": "08:00:27:e2:d0:f4",
                    "version": "4.14.8M"
                }
            }
        ]
    }
}

PLAY RECAP ********************************************************************
192.168.101.50             : ok=10   changed=0    unreachable=0    failed=0
192.168.101.52             : ok=10   changed=0    unreachable=0    failed=0

Arista だけに処理が走りました。

おしまい

plus one

今回は Discovery との連携例として Ansible の Dynamic Inventory を使いましたが、Discovery は Nmap/SNMP だけの超単純な仕組みなので、他の仕組みとの連携も面倒なくいけるんですよな。
例えば、こんなのはよくやっているのではないでしょうか。

  • ここで生成した JSON ファイルをロードして
    • sysDescrcase で分けて、機種に応じた処理
      • 詳細な inventory 情報取得(シリアル番号とかラインカード/SFP構成とか)
        • expect で show inventory とか netconf の <get-inventory> とか SNMP Get とか独自 API とか
          • 必要に応じて事前にポートスキャンで TCP/830 とか TCP/22 もしておくとか
          • たまにシリアル番号を CLI でしか取得できないポンコツ箱があるんだよなぁ…
      • config 取得 (後述の rancid 方式でもよい)
        • discovery ~ config 取得 ~ バージョン管理コマンドも cron で回しておくと、増えた機器が勝手にバックアップ・バージョン管理される
      • 各種ミドルウェアの設定ファイル生成(サンプルスクリプトのアウトプットを JSON でなく、設定ファイル形式にするでも)
        • rancid
        • Ansible
          • hosts ファイル
          • Dynamic Inventory と連携
            • 本項で軽くやったやつ
        • 監視ソフト(auto discovery 的な機能がない)
          • 機種に応じた自前の plugin を指定して…とかも自動でやれる
      • 特定バージョンを対象とした
        • OS ファイル転送
        • 設定撒き
    • ptr が空で sysname を取得できたものに関して、内部 DNS コンテンツの設定生成(~追加)
    • sysDescsysname の組み合わせで条件付けて、待機系機器のみ云々
  • JSON ファイルに書き出した情報を SQL に放り込んで、WebUI なり API なりを提供
    • 前述の内容を実現するのに、踏み台サーバや監視サーバからも inventory 情報を取得したい、って思ったり
      • 別に rsync とかで撒いてもよいが
    • 実機から取得できる情報には限界があるし、人間が入力・更新したい情報もあるのでは(商用環境だと保守期限とか)
    • ありもの製品の WebUI は実運用要件を充たすようにカスタマイズできないから、自前で簡易で運用要件を充たすものを立てたほうが楽、とか
      • そういう思いから自前で作り込まれた社内システムとかには、文句たらたらで「ありもののパッケージ使えよ」とか言うのにね

所感

  • まあ、なんというか「何をマスタ情報にして、他コンポーネントとどういう連携をするか」は環境次第なので、こんな方法もあるよ、ってだけですな
  • 超メジャーな Nmap を使った Inventory の生成、なんてのは割とポピュラーな手法で、以下のようなものを使えば同じこと+アルファが出来ます(いずれも内部的には Nmap を使っている模様)
    • Open-AudIT
      • JSON, xlsx, pdf 形式などで情報をエクスポートできるらしい
      • 本項の Discovery レベルの話は全部できそう
    • ローレベルディスカバリ | Zabbix 2.2
      • SNMP 連携できるディスカバリって点では、物理 NW 機器を一元管理する場合には、これがマッチする気がする
  • ただまあ、もっと手軽に…とか、アウトプットの書式を任意に作りたい(他のミドルウェアで使う設定ファイル生成とか)とかのケースでは、使えるのではないでしょうかね
    • 生で Nmap 叩いて xml をサクッとパースすればライブラリさえ使う必要ないのですが…
  • Nmap 7.0 の新機能を一切触ってないじゃねぇか!

Juniper vSRX(15.1X) を VirtualBox で動かす (original : 2015/12/11)

この記事は某所で 2015/12/11 に書いたもののコピーです。
そのため 2017/05/13 時点ではやや古い情報も含まれています。

  • Juniper さんの vSRX ダウンロード規約が変わっていそう (詳細は未確認)

.

概要

本項でやること

  • KVMVMware ESX 向けの 60 日間 trial 版が公開されている Juniper vSRX を VirtualBox に入れる
  • 公式にはサポートされない手順なので、自己責任で
  • JUNOS の基本的な操作は省略(ある程度知っている人向け)

環境情報

vSRX?

手順

vSRX イメージファイル取得

ovf 形式にファイル変換

  • 取得したovaファイルを ovf 形式にする (以下例では VMwarePlayer などに同梱されている ovftool を使用)
>ovftool.exe media-srx-ffp-vsrx-vmdisk-15.1X49-D15.4.ide.ova \convert\media-srx-ffp-vsrx-vmdisk-15.1X49-D15.4.ide.ovf
Opening OVA source: media-srx-ffp-vsrx-vmdisk-15.1X49-D15.4.ide.ova
The manifest validates
Opening OVF target: \convert\media-srx-ffp-vsrx-vmdisk-15.1X49-D15.4.ide.ovf
Writing OVF package: \convert\media-srx-ffp-vsrx-vmdisk-15.1X49-D15.4.ide.ovf
Transfer Completed
Source is signed but could not verify certificate (possibly self-signed)
Completed successfully
media-srx-ffp-vsrx-vmdisk-15.1X49-D15.4.ide.ovf
media-srx-ffp-vsrx-vmdisk-15.1X49-D15.4.ide-disk1.vmdk
media-srx-ffp-vsrx-vmdisk-15.1X49-D15.4.ide.mf

変換したファイルに小細工(インポートエラーが出ないように)

  • media-srx-ffp-vsrx-vmdisk-15.1X49-D15.4.ide.mf ファイルは別ディレクトリに除外しておく
  • media-srx-ffp-vsrx-vmdisk-15.1X49-D15.4.ide.ovf の line 82 を以下のように上書き編集(%iid% -> 2)

編集前

            <Item ovf:configuration="4GvRAM">
              <rasd:AllocationUnits>byte * 2^20</rasd:AllocationUnits>
              <rasd:Description>Memory Size</rasd:Description>
              <rasd:ElementName>Memory</rasd:ElementName>
              <rasd:InstanceID>%iid%</rasd:InstanceID>
              <rasd:ResourceType>4</rasd:ResourceType>
              <rasd:VirtualQuantity>4096</rasd:VirtualQuantity>

編集後

            <Item ovf:configuration="4GvRAM">
              <rasd:AllocationUnits>byte * 2^20</rasd:AllocationUnits>
              <rasd:Description>Memory Size</rasd:Description>
              <rasd:ElementName>Memory</rasd:ElementName>
              <rasd:InstanceID>2</rasd:InstanceID>
              <rasd:ResourceType>4</rasd:ResourceType>
              <rasd:VirtualQuantity>4096</rasd:VirtualQuantity>

VirtualBox に ovf をインポート

  • ファイル -> 仮想マシンのインポート で先の編集した ovf ファイルを指定

f:id:kakkotetsu:20170513145149j:plain f:id:kakkotetsu:20170513145201j:plain

  • 以降の画面キャプチャはインポート後の設定からとってきたもの

f:id:kakkotetsu:20170513145216j:plain

f:id:kakkotetsu:20170513145222j:plain

f:id:kakkotetsu:20170513145227j:plain

f:id:kakkotetsu:20170513145235j:plain

f:id:kakkotetsu:20170513145240j:plain

f:id:kakkotetsu:20170513145245j:plain

  • どうやらアダプタータイプ は一回起動したあとは勝手に準仮想化ネットワーク(virtio-net)にされるようだ
  • アダプター 1が JUNOS 側から見ると fxp0 (管理用ポート)になる

f:id:kakkotetsu:20170513145259j:plain

f:id:kakkotetsu:20170513145303j:plain

コンソール画面から初期設定

  • 起動する
  • 無事に起動できたら、コンソールログインして以下を設定する
# root password の設定(必須)
set system root-authentication plain-text-password
 -> 対話型で入力

# ユーザ作成とパスワード設定
set system login user <username> class super-user
set system login user <username> authentication plain-text-password

# ssh 有効化
set system services ssh root-login deny
set system services ssh protocol-version v2

ssh して状態確認

--- JUNOS 15.1X49-D15.4 built 2015-07-31 02:20:21 UTC
kotetsu>
kotetsu> show version
Model: vSRX
Junos: 15.1X49-D15.4
JUNOS Software Release [15.1X49-D15.4]

kotetsu> show chassis hardware
Hardware inventory:
Item             Version  Part number  Serial number     Description
Chassis                                5028f7dddeb5      VSRX
Midplane
System IO
Routing Engine                                           VSRX RE
FPC 0                                                    Virtual FPC
  PIC 0                                                  Virtual GE
Power Supply 0

kotetsu> show system license
License usage:
                                 Licenses     Licenses    Licenses    Expiry
  Feature name                       used    installed      needed
  Virtual Appliance                     1            1           0    59 days

Licenses installed:
  License identifier: E420588955
  License version: 4
  Software Serial Number: 20150625
  Customer ID: vSRX-JuniperEval
  Features:
    Virtual Appliance - Virtual Appliance
      count-down, Original validity: 60 days

kotetsu> show configuration | display set
set version 15.1X49-D15.4
set system root-authentication encrypted-password "$1$8FV6oxYf$H0vFbn4hEjZEwb748.JxK0"
set system login user kotetsu uid 2000
set system login user kotetsu class super-user
set system login user kotetsu authentication encrypted-password "$1$w/Ff6i9v$1wW4Wrt8Xy04P8ee63/Hb."
set system services ssh root-login deny
set system services ssh protocol-version v2
set system services web-management http interface fxp0.0
set system syslog user * any emergency
set system syslog file messages any any
set system syslog file messages authorization info
set system syslog file interactive-commands interactive-commands any
set system license autoupdate url https://ae1.juniper.net/junos/key_retrieval
set security forwarding-options family mpls mode packet-based
set interfaces fxp0 unit 0 family inet address 192.168.101.30/24

おわり

  • インストールしただけなので別に…

bagpipe-bgp インストール~簡易動作確認 (original : 2015/11/08)

この記事は某所で 2015/11/08 に書いたもののコピーです。
そのため 2017/05/13 時点ではやや古い情報も含まれています。

概要

本項でやること

  • bagpipe-bgp をインストールして軽く動作確認するところまでです
  • 一般的に OpenStack Neutron と組み合わせて使うようですが、ここでは OpenStack は登場しません
  • OSS で手軽に EVPN を試せそう、というのがモチベーションです

環境情報

$ uname -a
Linux as65000-l1 3.19.0-25-generic #26~14.04.1-Ubuntu SMP Fri Jul 24 21:16:20 UTC 2015 x86_64 x86_64 x86_64 GNU/Linux

$ cat /etc/lsb-release
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=14.04
DISTRIB_CODENAME=trusty
DISTRIB_DESCRIPTION="Ubuntu 14.04.3 LTS"

手順

Python 各種パッケージインストール

  • 必要なパッケージをインストール

  • OS パッケージで入れる例

$ sudo apt-get install python-daemon python-bottle python-netaddr python-pip

bagpipe-bgp インストール

$ cd
$ git clone https://github.com/Orange-OpenSource/bagpipe-bgp.git
$ cd bagpipe-bgp/
$ git show
commit 216fee45fba40663dfd9b48bb31be74f5513f684
Author: Thomas Morin <thomas.morin@orange.com>
Date:   Fri Aug 28 17:00:53 2015 +0200

    devstack plugin fix

    (dumb omission of "then" in a bash statement...)


$ sudo python setup.py install

$ ls -al /usr/local/bin/bagpipe-*
-rwxr-xr-x 1 root root 175 Nov  8 01:28 /usr/local/bin/bagpipe-bgp
-rwxr-xr-x 1 root root 177 Nov  8 01:28 /usr/local/bin/bagpipe-bgp-cleanup
-rwxr-xr-x 1 root root 157 Nov  8 01:28 /usr/local/bin/bagpipe-fakerr
-rwxr-xr-x 1 root root 168 Nov  8 01:28 /usr/local/bin/bagpipe-looking-glass
-rwxr-xr-x 1 root root 166 Nov  8 01:28 /usr/local/bin/bagpipe-rest-attach

$ bagpipe-bgp --help
Usage: bagpipe-bgp [options] (see --help)

Options:
  -h, --help            show this help message and exit
  --config-file=CONFIGFILE
                        Set BGP component configuration file path
  --log-file=LOGFILE    Set logging configuration file path
  --no-daemon           Do not daemonize

bagpipe-bgp service 登録(~自動起動設定)

$ cd bagpipe-bgp/

$ ./install_bagpipe_bgp.sh
*** WARNING: This script must be run as root ***

$ sudo ./install_bagpipe_bgp.sh

$ sudo service bagpipe-bgp status
BGP component is running.
  • 自動起動したい場合は、サンプルが同梱されているので、これを配置すればよかろう(ここでは未実施)
$ ls -al bagpipe-bgp/etc/init.d/
total 16
drwxrwxr-x 2 kotetsu kotetsu 4096 Nov  8 01:25 .
drwxrwxr-x 3 kotetsu kotetsu 4096 Nov  8 01:25 ..
-rwxrwxr-x 1 kotetsu kotetsu 2518 Nov  8 01:25 bagpipe-bgp
-rwxrwxr-x 1 kotetsu kotetsu 1545 Nov  8 01:25 bagpipe-fakerr

bagpipe-bgp 設定ファイルの編集

メイン設定ファイル (/etc/bagpipe-bgp/bgp.conf)

  • /etc/bagpipe-bgp/bgp.conf
  • ネットワーク環境に合わせて [BGP] の項目を編集
    • iBGP しか使えないことに注意
$ ls -al /etc/bagpipe-bgp/
total 24
drwxr-xr-x  2 root root 4096 Nov  8 01:57 .
drwxr-xr-x 83 root root 4096 Nov  8 01:57 ..
-rw-r--r--  1 root root 3099 Nov  8 01:57 bgp.conf
-rw-rw-r--  1 root root 3099 Nov  8 01:25 bgp.conf.template
-rw-r--r--  1 root root 1615 Nov  8 01:57 log.conf
-rw-rw-r--  1 root root 1615 Nov  8 01:25 log.conf.template

$ cat /etc/bagpipe-bgp/bgp.conf
[BGP]
local_address=10.0.1.2
peers=10.0.1.1
my_as=65000
enable_rtc=False

(略)


$ diff /etc/bagpipe-bgp/bgp.conf /etc/bagpipe-bgp/bgp.conf.template
2,5c2,5
< local_address=10.0.1.2
< peers=10.0.1.1
< my_as=65000
< enable_rtc=False
---
> local_address=192.168.100.177
> peers=192.168.0.101
> my_as=64512
> enable_rtc=True

log 出力設定ファイル (/etc/bagpipe-bgp/log.conf)

  • /etc/bagpipe-bgp/log.conf
  • [logger_engine] だけ出力レベルを WARNING から DEBUG に変更(様子を観察するため)
  • デフォルトでは /var/log/bagpipe-bgp/bagpipe-bgp.log に出力される
$ cat /etc/bagpipe-bgp/log.conf

(略)

[logger_engine]
level=DEBUG
propagate=0
qualname=bagpipe.bgp.engine
handlers=rotatingFile
parent=bgp

(略)

$ diff /etc/bagpipe-bgp/log.conf /etc/bagpipe-bgp/log.conf.template
25c25
< level=DEBUG
---
> level=WARNING

bagpipe-bgp 起動~状態確認

ここからの例では起動の前に、適当な iBGP neighbor を用意しておきます。

起動

  • service で普通に扱うだけ
  • 要 root 権限
$ sudo service bagpipe-bgp start
Starting BGP component...

$ sudo service bagpipe-bgp restart
Restarting BGP component... stopping.........starting

$ sudo service bagpipe-bgp status
BGP component is running.

ログ確認

  • デフォルトのログ設定ではさほど出力されないが、前述の通り [logger_engine] の level を DEBUG に変えたので、やたら出ている
$ more /var/log/bagpipe-bgp/bagpipe-bgp.log
2015-11-08 12:18:41,772 BGP-10.0.1.1                   bagpipe.bgp.engine.exabgp_peer_worker.10-0-1-1 INFO     Re-initiating
2015-11-08 12:18:41,773 BGP-10.0.1.1                   bagpipe.bgp.engine.exabgp_peer_worker.10-0-1-1 INFO     Worker BGP-10.0.1.1 BGP FSM transitioned from 'OpenSent' to 'Idle' state
2015-11-08 12:18:41,773 BGP-10.0.1.1                   bagpipe.bgp.engine.bgp_manager DEBUG    push cleanup event for worker BGP-10.0.1.1 to RouteTableManager
2015-11-08 12:18:41,773 RouteTableManager              bagpipe.bgp.engine.route_table_manager DEBUG    RouteTableManager received event WorkerCleanupEvent:BGP-10.0.1.1
2015-11-08 12:18:41,774 RouteTableManager              bagpipe.bgp.engine.route_table_manager INFO     Cleanup for worker BGP-10.0.1.1
2015-11-08 12:18:41,774 RouteTableManager              bagpipe.bgp.engine.route_table_manager INFO     (we had no trace of Worker BGP-10.0.1.1 in _source2entries)
2015-11-08 12:18:41,774 RouteTableManager              bagpipe.bgp.engine.route_table_manager DEBUG    RouteTableManager queue size: 0
2015-11-08 12:18:41,774 RouteTableManager              bagpipe.bgp.engine.route_table_manager DEBUG    RouteTableManager waiting on queue
2015-11-08 12:18:51,788 BGP-10.0.1.1                   bagpipe.bgp.engine.exabgp_peer_worker.10-0-1-1 INFO     Worker BGP-10.0.1.1 BGP FSM transitioned from 'Idle' to 'Connect' state
2015-11-08 12:18:51,788 BGP-10.0.1.1                   bagpipe.bgp.engine.exabgp_peer_worker.10-0-1-1 DEBUG    Initiate ExaBGP connection to 10.0.1.1 from 10.0.1.2
2015-11-08 12:18:51,790 BGP-10.0.1.1                   bagpipe.bgp.engine.exabgp_peer_worker.10-0-1-1 DEBUG    Instantiate ExaBGP Protocol
2015-11-08 12:18:51,791 BGP-10.0.1.1                   bagpipe.bgp.engine.exabgp_peer_worker.10-0-1-1 DEBUG    Send open: [OPEN version=4 asn=65000 hold_time=180 router_id=10.0.1.2 capabilities=[Multiprotocol IPv4 mpls-vpn L2VPN evpn, 4Bytes AS 65000]]
2015-11-08 12:18:51,792 BGP-10.0.1.1                   bagpipe.bgp.engine.exabgp_peer_worker.10-0-1-1 INFO     Worker BGP-10.0.1.1 BGP FSM transitioned from 'Connect' to 'OpenSent' state
2015-11-08 12:18:51,792 BGP-10.0.1.1                   bagpipe.bgp.engine.exabgp_peer_worker.10-0-1-1 DEBUG    Wait for open...
2015-11-08 12:18:51,793 BGP-10.0.1.1                   bagpipe.bgp.engine.exabgp_peer_worker.10-0-1-1 DEBUG    Read message: OPEN version=4 asn=65000 hold_time=90 router_id=192.168.101.170 capabilities=[Multiprotocol L2VPN evpn, Route Refresh, 4Bytes AS 65000]
2015-11-08 12:18:51,793 BGP-10.0.1.1                   bagpipe.bgp.engine.exabgp_peer_worker.10-0-1-1 INFO     changing thread name from BGP-10.0.1.1 to BGP-x192.168.101.170, based on the router-id advertized in Open (different from peerAddress == 10.0.1.1)
2015-11-08 12:18:51,793 BGP-10.0.1.1/192.168.101.170   bagpipe.bgp.engine.exabgp_peer_worker.10-0-1-1 WARNING  Peer does not advertise (IPv4,mpls-vpn) capability
2015-11-08 12:18:51,794 BGP-10.0.1.1/192.168.101.170   bagpipe.bgp.engine.exabgp_peer_worker.10-0-1-1 INFO     Family (L2VPN,evpn) successfully negotiated with peer 10.0.1.1
2015-11-08 12:18:51,795 BGP-10.0.1.1/192.168.101.170   bagpipe.bgp.engine.exabgp_peer_worker.10-0-1-1 WARNING  Peer does not advertise (IPv4,rtc) capability
2015-11-08 12:18:51,795 BGP-10.0.1.1/192.168.101.170   bagpipe.bgp.engine.exabgp_peer_worker.10-0-1-1 INFO     Worker BGP-10.0.1.1/192.168.101.170 BGP FSM transitioned from 'OpenSent' to 'OpenConfirm' state
2015-11-08 12:18:51,795 BGP-10.0.1.1/192.168.101.170   bagpipe.bgp.engine.exabgp_peer_worker.10-0-1-1 DEBUG    Init sendKA timer (30s)
2015-11-08 12:18:51,796 BGP-10.0.1.1/192.168.101.170   bagpipe.bgp.engine.exabgp_peer_worker.10-0-1-1 DEBUG    Init Keepalive reception timer (90s)
2015-11-08 12:18:51,797 BGP-10.0.1.1/192.168.101.170   bagpipe.bgp.engine.exabgp_peer_worker.10-0-1-1 DEBUG    Sending 19 bytes on socket to peer 10.0.1.1
2015-11-08 12:18:51,797 BGP-10.0.1.1/192.168.101.170:receiveLoop bagpipe.bgp.engine.exabgp_peer_worker.10-0-1-1 INFO     Start receive loop
2015-11-08 12:18:51,798 BGP-10.0.1.1/192.168.101.170:receiveLoop bagpipe.bgp.engine.exabgp_peer_worker.10-0-1-1 INFO     Worker BGP-10.0.1.1/192.168.101.170 BGP FSM transitioned from 'OpenConfirm' to 'Established' state
2015-11-08 12:18:51,798 BGP-10.0.1.1/192.168.101.170:receiveLoop bagpipe.bgp.engine.worker      INFO     Subscribe: Subscription [L2VPN/evpn,*] by BGP-10.0.1.1/192.168.101.170
2015-11-08 12:18:51,799 BGP-10.0.1.1/192.168.101.170:receiveLoop bagpipe.bgp.engine.bgp_manager DEBUG    bagpipe.bgp.engine.bgp_manager.Manager method _routeEventSubscribe called with arguments (Subscription [L2VPN/evpn,*] by BGP-10.0.1.1/192.168.101.170,) {}
2015-11-08 12:18:51,799 RouteTableManager              bagpipe.bgp.engine.route_table_manager DEBUG    RouteTableManager received event Subscription [L2VPN/evpn,*] by BGP-10.0.1.1/192.168.101.170
2015-11-08 12:18:51,799 RouteTableManager              bagpipe.bgp.engine.route_table_manager INFO     workerSubscribes: Subscription [L2VPN/evpn,*] by BGP-10.0.1.1/192.168.101.170
2015-11-08 12:18:51,800 RouteTableManager              bagpipe.bgp.engine.route_table_manager DEBUG    RouteTableManager queue size: 0
2015-11-08 12:18:51,800 RouteTableManager              bagpipe.bgp.engine.route_table_manager DEBUG    RouteTableManager waiting on queue
2015-11-08 12:18:51,800 BGP-10.0.1.1/192.168.101.170   bagpipe.bgp.engine.exabgp_peer_worker.10-0-1-1 DEBUG    Keepalive received
2015-11-08 12:18:51,801 BGP-10.0.1.1/192.168.101.170   bagpipe.bgp.engine.exabgp_peer_worker.10-0-1-1 DEBUG    Init Keepalive reception timer (90s)
2015-11-08 12:18:51,800 BGP-10.0.1.1/192.168.101.170:receiveLoop bagpipe.bgp.engine.exabgp_peer_worker.10-0-1-1 DEBUG    Received message: KEEPALIVE
2015-11-08 12:19:21,797 BGP-10.0.1.1/192.168.101.170:sendKATimer bagpipe.bgp.engine.exabgp_peer_worker.10-0-1-1 DEBUG    Trigger send KeepAlive
2015-11-08 12:19:21,798 BGP-10.0.1.1/192.168.101.170   bagpipe.bgp.engine.exabgp_peer_worker.10-0-1-1 DEBUG    Sending 19 bytes on socket to peer 10.0.1.1
2015-11-08 12:19:21,798 BGP-10.0.1.1/192.168.101.170:sendKATimer bagpipe.bgp.engine.exabgp_peer_worker.10-0-1-1 DEBUG    Init sendKA timer (30s)
2015-11-08 12:19:21,800 BGP-10.0.1.1/192.168.101.170:receiveLoop bagpipe.bgp.engine.exabgp_peer_worker.10-0-1-1 DEBUG    Received message: KEEPALIVE
2015-11-08 12:19:21,800 BGP-10.0.1.1/192.168.101.170   bagpipe.bgp.engine.exabgp_peer_worker.10-0-1-1 DEBUG    Keepalive received
2015-11-08 12:19:21,800 BGP-10.0.1.1/192.168.101.170   bagpipe.bgp.engine.exabgp_peer_worker.10-0-1-1 DEBUG    Init Keepalive reception timer (90s)

状態確認(bagpipe-looking-glass)

$ bagpipe-looking-glass bgp peers 10.0.1.1
protocol:
  state: Established
  hold_time: 90
  last_transition_time: 2015-11-08 12:18:51
  previous_state: (OpenConfirm)
name: BGP-10.0.1.1/192.168.101.170
rtc:
  active: False
  enabled: False
as_info:
  peer: 65000
  local: 65000
internals:
  event queue length: 0
  subscriptions:
    * match:L2VPN/evpn,*
peeringAddresses:
  peerAddress: 10.0.1.1
  localAddress: 10.0.1.2
routes:  (...)
active_families:
  * (L2VPN, evpn)
logs:  (...)
  • bagpipe は Openstack Neutron components あたりとの連携して使うのが一般的のようで RESTAPI 制御も可能
  • 適当に別のノードから突いた一例
$ curl -s http://192.168.101.171:8082/looking-glass/bgp/peers/10.0.1.1 | python -m json.tool
{
    "active_families": [
        "(L2VPN, evpn)"
    ],
    "as_info": {
        "local": 65000,
        "peer": 65000
    },
    "internals": {
        "event queue length": 0,
        "subscriptions": [
            "match:L2VPN/evpn,*"
        ]
    },
    "logs": {
        "href": "http://192.168.101.171:8082/looking-glass/bgp/peers/10.0.1.1/logs"
    },
    "name": "BGP-10.0.1.1/192.168.101.170",
    "peeringAddresses": {
        "localAddress": "10.0.1.2",
        "peerAddress": "10.0.1.1"
    },
    "protocol": {
        "hold_time": 90,
        "last_transition_time": "2015-11-08 12:18:51",
        "previous_state": "(OpenConfirm)",
        "state": "Established"
    },
    "routes": {
        "href": "http://192.168.101.171:8082/looking-glass/bgp/peers/10.0.1.1/routes"
    },
    "rtc": {
        "active": false,
        "enabled": false
    }
}

おわり

  • インストールしただけなので、特に…

GoBGP インストール~簡易動作確認 (original : 2015/11/08)

この記事は某所で 2015/11/08 に書いたもののコピーです。
そのため 2017/05/13 時点ではやや古い情報も含まれています。

概要

本項でやること

  • gobgp をインストール~起動~適当なノードとiBGP Peeringするところまでです
  • gobgp 公式 Getting started に従います

環境情報

$ uname -a
Linux as65000-s1 3.19.0-25-generic #26~14.04.1-Ubuntu SMP Fri Jul 24 21:16:20 UTC 2015 x86_64 x86_64 x86_64 GNU/Linux

$ uname -r
3.19.0-25-generic

$ cat /etc/lsb-release
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=14.04
DISTRIB_CODENAME=trusty
DISTRIB_DESCRIPTION="Ubuntu 14.04.3 LTS"

構築手順

Go インストール

$ wget --no-check-certificate https://storage.googleapis.com/golang/go1.5.1.linux-amd64.tar.gz
$ ls -al
total 76060
drwxrwxr-x 2 kotetsu kotetsu     4096 Nov  7 20:53 .
drwxr-xr-x 5 kotetsu kotetsu     4096 Nov  7 20:49 ..
-rw-rw-r-- 1 kotetsu kotetsu 77875767 Sep  9 13:20 go1.5.1.linux-amd64.tar.gz

$ sudo tar -C /usr/local -xzf go1.5.1.linux-amd64.tar.gz
$ ls -al /usr/local/go/
total 136
drwxr-xr-x 11 root root  4096 Sep  9 10:37 .
drwxr-xr-x 11 root root  4096 Nov  7 20:57 ..
drwxr-xr-x  2 root root  4096 Sep  9 10:24 api
-rw-r--r--  1 root root 21146 Sep  9 10:24 AUTHORS
drwxr-xr-x  2 root root  4096 Sep  9 10:37 bin
drwxr-xr-x  4 root root  4096 Sep  9 10:37 blog
-rw-r--r--  1 root root  1107 Sep  9 10:24 CONTRIBUTING.md
-rw-r--r--  1 root root 28953 Sep  9 10:24 CONTRIBUTORS
drwxr-xr-x  8 root root  4096 Sep  9 10:24 doc
-rw-r--r--  1 root root  1150 Sep  9 10:24 favicon.ico
drwxr-xr-x  3 root root  4096 Sep  9 10:24 lib
-rw-r--r--  1 root root  1479 Sep  9 10:24 LICENSE
drwxr-xr-x 13 root root  4096 Sep  9 10:37 misc
-rw-r--r--  1 root root  1303 Sep  9 10:24 PATENTS
drwxr-xr-x  7 root root  4096 Sep  9 10:37 pkg
-rw-r--r--  1 root root  1519 Sep  9 10:24 README.md
-rw-r--r--  1 root root    26 Sep  9 10:24 robots.txt
drwxr-xr-x 43 root root  4096 Sep  9 10:24 src
drwxr-xr-x 16 root root 12288 Sep  9 10:36 test
-rw-r--r--  1 root root     7 Sep  9 10:24 VERSION

$ mkdir $HOME/go
$ echo 'export GOPATH=$HOME/go'  >> $HOME/.profile
$ echo 'export PATH=$PATH:/usr/local/go/bin:$GOPATH/bin' >> $HOME/.profile
$ source $HOME/.profile
$ env | grep PATH
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/usr/local/go/bin:/usr/local/go/bin:/usr/local/go/bin:/home/kotetsu/go/bin
GOPATH=/home/kotetsu/go

$ go version
go version go1.5.1 linux/amd64

gobgp インストール

  • インストールに使う go get コマンドに必要なパッケージを適宜インストール GoGetTools
$ sudo apt-get update
$ sudo apt-get install git mercurial
$ go get github.com/osrg/gobgp/gobgpd
warning: code.google.com is shutting down; import path code.google.com/p/go-uuid/uuid will stop working

$ go get github.com/osrg/gobgp/gobgp

$ ls -al ~/go/bin/
total 29056
drwxrwxr-x 2 kotetsu kotetsu     4096 Nov  7 21:43 .
drwxrwxr-x 5 kotetsu kotetsu     4096 Nov  7 21:36 ..
-rwxr-xr-x 1 kotetsu kotetsu 13801080 Nov  7 21:43 gobgp
-rwxr-xr-x 1 kotetsu kotetsu 15939792 Nov  7 21:36 gobgpd

gobgpd.conf 作成

  • 適当なディレクトリに config ファイルを作成して、適当な設定を書き込む
  • 以下例では iBGP しか設定していないが、eBGP も動く
$ mkdir ~/gobgp
$ touch ~/gobgp/gobgpd.conf

$ cat ~/gobgp/gobgpd.conf
[Global]
  [Global.GlobalConfig]
    As = 65000
    RouterId = "192.168.101.170"

[Neighbors]
  [[Neighbors.NeighborList]]
    [Neighbors.NeighborList.NeighborConfig]
      NeighborAddress = "10.0.1.2"
      PeerAs = 65000
    [Neighbors.NeighborList.AfiSafis]
      [[Neighbors.NeighborList.AfiSafis.AfiSafiList]]
        AfiSafiName = "l2vpn-evpn"

  [[Neighbors.NeighborList]]
    [Neighbors.NeighborList.NeighborConfig]
      NeighborAddress = "10.0.2.2"
      PeerAs = 65000
    [Neighbors.NeighborList.AfiSafis]
      [[Neighbors.NeighborList.AfiSafis.AfiSafiList]]
        AfiSafiName = "l2vpn-evpn"

gobgpd 起動

  • root 権限で実行しないと、IP アドレス bind に失敗する
  • デフォルトではフォアグラウンドで動く
$ gobgpd -f ~/gobgp/gobgpd.conf
{"level":"info","msg":"gobgpd started","time":"2015-11-07T22:11:54+09:00"}
{"level":"info","msg":"finished reading the config file","time":"2015-11-07T22:11:54+09:00"}
{"level":"info","msg":"listen tcp4 :179: bind: permission denied","time":"2015-11-07T22:11:54+09:00"}
{"level":"info","msg":"listen tcp6 :179: bind: permission denied","time":"2015-11-07T22:11:54+09:00"}
{"level":"fatal","msg":"can't listen either v4 and v6","time":"2015-11-07T22:11:54+09:00"}

$ sudo cat /etc/sudoers | grep Defaults
Defaults        env_reset
Defaults        mail_badpass
Defaults        secure_path="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
Defaults        exempt_group="kotetsu"

$ sudo -E gobgpd -f ~/gobgp/gobgpd.conf &
[1] 8242
kotetsu@as65000-1:~$ {"level":"info","msg":"gobgpd started","time":"2015-11-07T22:28:37+09:00"}
{"level":"info","msg":"finished reading the config file","time":"2015-11-07T22:28:37+09:00"}
{"level":"info","msg":"Peer 10.0.1.2 is added","time":"2015-11-07T22:28:37+09:00"}
{"level":"info","msg":"Peer 10.0.2.2 is added","time":"2015-11-07T22:28:37+09:00"}

$ ps au | grep [g]o
root      8242  0.0  0.8  64956  4052 pts/1    S    Nov07   0:00 sudo -E gobgpd -f /home/kotetsu/gobgp/gobgpd.conf
root      8243  0.0  2.1 139396 11004 pts/1    Sl   Nov07   0:01 gobgpd -f /home/kotetsu/gobgp/gobgpd.conf

$ gobgp neighbor --help
Usage:
  gobgp neighbor [flags]

Flags:
  -a, --address-family="": address family
  -t, --transport="": specifying a transport protocol

Global Flags:
      --bash-cmpl-file="gobgp_completion.bash": bash cmpl filename
  -d, --debug[=false]: use debug
  -c, --gen-cmpl[=false]: generate completion file
  -u, --host="127.0.0.1": host
  -j, --json[=false]: use json format to output format
  -p, --port=8080: port
  -q, --quiet[=false]: use quiet

動作確認

適当な neighbor を用意して、動作確認(勿論 gobgp 同士でも可能)

  • neighbor の Peer 確立、切断時などにはデフォルトでは標準出力に以下のような出力
{"Key":"10.0.1.2","Reason":"Peer closed the session","State":6,"Topic":"Peer","level":"info","msg":"Peer Down","time":"2015-11-08T12:18:41+09:00"}
{"Key":"10.0.1.2","Topic":"Peer","level":"warning","msg":"Closed an accepted connection","time":"2015-11-08T12:18:41+09:00"}
{"Key":"10.0.1.2","State":5,"Topic":"Peer","level":"info","msg":"Peer Up","time":"2015-11-08T12:18:51+09:00"}
$ gobgp neighbor
Peer                AS  Up/Down State       |#Advertised Received Accepted
10.0.1.2         65000 02:07:33 Establ      |          0        0        0
10.0.2.2         65000    never Active      |          0        0        0

$ gobgp neighbor 10.0.1.2
BGP neighbor is 10.0.1.2, remote AS 65000
  BGP version 4, remote router ID 10.0.1.2
  BGP state = BGP_FSM_ESTABLISHED, up for 02:07:40
  BGP OutQ = 0, Flops = 0
  Hold time is 0, keepalive interval is 30 seconds
  Configured hold time is 90, keepalive interval is 30 seconds
  Neighbor capabilities:
    BGP_CAP_MULTIPROTOCOL:
        RF_EVPN:        advertised and received
        RF_IPv4_VPN:    received
        RF_RTC_UC:      received
    BGP_CAP_ROUTE_REFRESH:      advertised
    BGP_CAP_FOUR_OCTET_AS_NUMBER:       advertised and received
  Message statistics:
                         Sent       Rcvd
    Opens:                 20         20
    Notifications:          0          0
    Updates:                0          0
    Keepalives:           392        392
    Route Refesh:           0          0
    Discarded:              0          0
    Total:                412        412
  Route statistics:
    Advertised:             0
    Received:               0
    Accepted:               0

おまけ CLI's tab 補完(bash 用) 導入

  • 'gobgp' 各種コマンドを Tab 補完できるようになるので、入れておくと便利
$ cd ~/gobgp
$ wget https://raw.githubusercontent.com/osrg/gobgp/master/tools/completion/gobgp-completion.bash

$ ls -al
total 56
drwxrwxr-x 2 kotetsu kotetsu  4096 Nov  7 23:32 .
drwxr-xr-x 6 kotetsu kotetsu  4096 Nov  7 22:07 ..
-rw-rw-r-- 1 kotetsu kotetsu 41832 Nov  7 23:32 gobgp-completion.bash
-rw-rw-r-- 1 kotetsu kotetsu   354 Nov  7 22:10 gobgpd.conf

$ source ~/gobgp/gobgp-completion.bash

おわり

  • インストールしただけなので別に…