search
LoginSignup
0
Help us understand the problem. What are the problem?

More than 1 year has passed since last update.

SONiC Advent Calendar 2020 Day 8

posted at

SONiCと静的経路

はじめに

SONiCの設定例を見ると、経路に関してはBGPにまつわる設定ばかりで静的経路について言及されているものはほとんどありません。実際のところ静的経路が扱えるのか、調査してみましたので、それを共有したいと思います。

設計ドキュメントでの言及

SONiC VRF support design spec draftによると、config_db.json"STATIC_ROUTE"という設定項目の追加について言及されています。設定例を転記します。

"STATIC_ROUTE": {
    "11.11.11.0/24": {
        "distance": "10",
        "nexthop": "1.1.1.1"
    },

    "Vrf-blue|22.11.11.0/24": {
        "distance": "10",
        "nexthop-vrf": "Vrf-red",
        "nexthop": "2.1.1.1"
    },

    "Vrf-red|11.11.11.0/24": {
        "nexthop": "1.1.1.1"
    }
}

しかし、SONiCのソースコードを探しても"STATIC_ROUTE"なるキーワードはどこにも記述されていません。つまり、上記のような設定をconfig_db.jsonに記述しても無視されます

CLI実装

SONiCのコマンドリファレンスには言及がありませんが、ヘルプメッセージ(下記に一部抜粋)にあるとおり、config routeというコマンドが存在しています。

  qos                     QoS-related configuration tasks
  reload                  Clear current configuration and import a previous...
  route                   route-related configuration tasks
  save                    Export current config DB to a file on disk.
  sflow                   sFlow-related configuration tasks

config routeコマンドの詳細を確認してみます。

admin@sonic:~$ sudo config route
Usage: config route [OPTIONS] COMMAND [ARGS]...

  route-related configuration tasks

Options:
  -?, -h, --help  Show this message and exit.

Commands:
  add  Add route command
  del  Del route command
admin@sonic:~$ sudo config route add
Usage: config route add [OPTIONS] prefix [vrf <vrf_name>] <A.B.C.D/M> nexthop
                        <[vrf <vrf_name>] <A.B.C.D>>|<dev <dev_name>>
Try "config route add -h" for help.

Error: argument is not in pattern prefix [vrf <vrf_name>] <A.B.C.D/M> nexthop <[vrf <vrf_name>] <A.B.C.D>>|<dev <dev_name>>!
admin@sonic:~$ 

なにやら動いてくれそうな感じですので、実際にコマンドを実行してみます。

admin@sonic:~$ show ip route
admin@sonic:~$ sudo config interface ip add Ethernet0 192.168.0.1/24
admin@sonic:~$ sudo config route add prefix 172.21.0.0/24 nexthop 192.168.0.254
admin@sonic:~$ show ip route
Codes: K - kernel route, C - connected, S - static, R - RIP,
       O - OSPF, I - IS-IS, B - BGP, E - EIGRP, N - NHRP,
       T - Table, v - VNC, V - VNC-Direct, A - Babel, D - SHARP,
       F - PBR, f - OpenFabric,
       > - selected route, * - FIB route, q - queued route, r - rejected route

S>* 172.21.0.0/24 [1/0] via 192.168.0.254, Ethernet0, 00:00:04
C>* 192.168.0.0/24 is directly connected, Ethernet0, 00:00:15
admin@sonic:~$ 

動いてくれました!
では、設定はどうなっているのかチェックしてみます。

admin@sonic:~$ show runningconfiguration all|grep 172
admin@sonic:~$ 

あれ???

BGP dockerの中も確認してみます。

admin@sonic:~$ docker exec -it bgp bash
root@sonic:/# grep 172 /etc/frr/*.conf
root@sonic:/# 

えーと?
よくわからないのでconfig routeのプログラムの中身を見てみます。

中身
src/sonic-utilities/config/main.py
@route.command('add', context_settings={"ignore_unknown_options":True})
@click.argument('command_str', metavar='prefix [vrf <vrf_name>] <A.B.C.D/M> next
hop <[vrf <vrf_name>] <A.B.C.D>>|<dev <dev_name>>', nargs=-1, type=click.Path())
@click.pass_context
def add_route(ctx, command_str):
    """Add route command"""
    if len(command_str) < 4 or len(command_str) > 9:
        ctx.fail("argument is not in pattern prefix [vrf <vrf_name>] <A.B.C.D/M>
 nexthop <[vrf <vrf_name>] <A.B.C.D>>|<dev <dev_name>>!")
    if "prefix" not in command_str:
        ctx.fail("argument is incomplete, prefix not found!")
    if "nexthop" not in command_str:
        ctx.fail("argument is incomplete, nexthop not found!")
    for i in range(0, len(command_str)):
        if "nexthop" == command_str[i]:
            prefix_str = command_str[:i]
            nexthop_str = command_str[i:]
    vrf_name = ""
    cmd = 'sudo vtysh -c "configure terminal" -c "ip route'
    if prefix_str:
        if len(prefix_str) == 2:
            prefix_mask = prefix_str[1]
            cmd += ' {}'.format(prefix_mask)
        elif len(prefix_str) == 4:
            vrf_name = prefix_str[2]
            prefix_mask = prefix_str[3]
            cmd += ' {}'.format(prefix_mask)
        else:
            ctx.fail("prefix is not in pattern!")
    if nexthop_str:
        if len(nexthop_str) == 2:
            ip = nexthop_str[1]
            if vrf_name == "":
                cmd += ' {}'.format(ip)
            else:
                cmd += ' {} vrf {}'.format(ip, vrf_name)
        elif len(nexthop_str) == 3:
            dev_name = nexthop_str[2]
            if vrf_name == "":
                cmd += ' {}'.format(dev_name)
            else:
                cmd += ' {} vrf {}'.format(dev_name, vrf_name)
        elif len(nexthop_str) == 4:
            vrf_name_dst = nexthop_str[2]
            ip = nexthop_str[3]
            if vrf_name == "":
                cmd += ' {} nexthop-vrf {}'.format(ip, vrf_name_dst)
            else:
                cmd += ' {} vrf {} nexthop-vrf {}'.format(ip, vrf_name, vrf_name_dst)
        else:
            ctx.fail("nexthop is not in pattern!")
    cmd += '"'
    clicommon.run_command(cmd)

なるほど。vtyshコマンドで設定をFRRに叩き込んでるだけ、データベースに記録しない、つまり静的経路は設定できるがその場限りで、再起動すると失われる、ということのようです。将来に渡ってこのままはわかりませんが、現状はこのような状況でした。

このような実装だったので、おそらくCLI以外で静的経路を設定することは現時点では不可能と思われます。

おわりに

静的経路の投入を必要とする場合、実装されるのを待つか、あるいは問題提起して実装を促すか、それとも自分で実装してしまうか、CLIで毎回設定投入することを許容するか、はたまたSONiC以外の利用を検討するか。悩ましいですが、個人的にはまったく使えないよりはいくぶんマシだという感想を持ちました。現場からは以上です。

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
What you can do with signing up
0
Help us understand the problem. What are the problem?