yusuke@watakushi-tsukuba-1-gw1:~$ ls /etc/systemd/network
10-eth0.link  10-eth0.network  11-dummy1.netdev  11-dummy1.network  12-lo.network
yusuke@watakushi-tsukuba-1-gw1:~$ cat /etc/systemd/network/10-eth0.link
[Match]
MACAddress=dc:a6:32:bf:8e:80

[Link]
Name=eth0

yusuke@watakushi-tsukuba-1-gw1:~$ cat /etc/systemd/network/10-eth0.network
[Match]
Name=eth0

[Network]
Address=103.41.60.187/27
Gateway=103.41.60.164

Address=2401:af80:2917::21/64
# Gateway=2401:af80:2917::4

Address=2a10:2f00:18a::/48
Address=2a10:2f00:18a:2000::/64
Address=2a10:2f00:18a:1001::1/64

DNS=1.1.1.1
DNS=1.0.0.1
DNS=8.8.8.8
DNS=8.8.4.4

# ルーティングループ防止
# BIRD の挙動がいまいちわかっていないところがあり怖いので systemd-networkd で設定を仕込んでおく
[Route]
Destination=2a10:2f00:18a::/48
Type=blackhole
yusuke@watakushi-tsukuba-1-gw1:~$ cat /etc/systemd/network/11-dummy1.net
cat: /etc/systemd/network/11-dummy1.net: No such file or directory
yusuke@watakushi-tsukuba-1-gw1:~$ cat /etc/systemd/network/11-dummy1.netdev
[NetDev]
Name=dummy1
Kind=bridge
yusuke@watakushi-tsukuba-1-gw1:~$ cat /etc/systemd/network/11-dummy1.network
[Match]
Name=dummy1

[Network]
Address=2a10:2f00:18a::/48
Address=2a10:2f00:18a:1001::1/64
Address=2a10:2f00:18a:2000::/64
yusuke@watakushi-tsukuba-1-gw1:~$ cat /etc/systemd/network/12-lo.network
[Match]
Name=lo

[Route]
Type=local
Destination=2a10:2f00:18a:2000::/64
yusuke@watakushi-tsukuba-1-gw1:~$ sudo cat /etc/bird/bird.conf
[sudo] password for yusuke:
# Please refer to the BIRD User's Guide documentation, which is also available
# online at http://bird.network.cz/ in HTML format, for more information on
# configuring BIRD and adding routing protocols.

# Configure logging
log syslog all;
# log "/var/log/bird.log" { debug, trace, info, remote, warning, error, auth, fatal, bug };

define WatakushiASN = 213164;
# Upstream
define SoftEtherASN = 59103;

define BOGON_PREFIXES = [
    # https://www.janog.gr.jp/doc/janog-comment/jc1001.txt
    # 0.0.0.0/0,
    # 10.0.0.0/8+,
    # 172.16.0.0/12+,
    # 192.168.0.0/16+,
    # 100.64.0.0/10,
    # 127.0.0.0/8+,
    # 169.254.0.0/16+,
    # 192.0.2.0/24+,
    # 198.18.0.0/15+,
    # 198.51.100.0/24+,
    # 203.0.113.0/24+,
    # 224.0.0.0/3+,

    # https://www.janog.gr.jp/doc/janog-comment/jc1006.txt
    ::/0,
    ::/96+,
    ::/128,
    ::1/128,
    ::ffff:0:0/96+,
    100::/64+,
    2001:2::/48+,
    2001:db8::/32+,
    fc00::/7+,
    fe80::/10+,
    fec0::/10+,
    ff00::/8+
];

# Rejects prefixes that is assumed as bogons.
function reject_bogon_prefixes() {
    if (net ~ BOGON_PREFIXES) then reject;
}

define TOO_LONG_LENGTH_PREFIXES = [
    # 0.0.0.0/0{25,32},
    ::/0{65,128}
];

# Rejects prefixes that is not suitable for eBGP.
function reject_too_long_length_prefixes() {
    if (net ~ TOO_LONG_LENGTH_PREFIXES ) then reject;
}

# Returns true if the given prefix (net) is owned by AS213164.
# AS213164 is maintained by Watakushi-NOC.
function is_prefix_of_as213164() {
    return net ~ [
        2a10:2f00:18a::/48
    ];
}

# Accepts all routes except for invalid prefixes.
filter bgp_59103_import {
    reject_bogon_prefixes();
    reject_too_long_length_prefixes();
    accept;
}

# Accepts prefixes of AS213164.
filter bgp_59103_export {
    reject_bogon_prefixes();
    reject_too_long_length_prefixes();
    if (is_prefix_of_as213164()) then accept;
    reject;
}

ipv6 table kernel_v6;
ipv6 table bgp_v6;

protocol device device1 {
    interface "eth0";
    scan time 100;
}

protocol direct direct1 {
    ipv6 {
        table kernel_v6;
    };

    interface "eth0";
}

protocol kernel k_v6 {
    ipv6 {
        table kernel_v6;
        import none;
        export all;
    };

    # main table
    kernel table 254;
}

protocol static static_v6_kernel_v6 {
    ipv6 {
        table kernel_v6;
        import all;
        export none;
    };
}

protocol static static_v6_advertised_prefixes {
    ipv6 {
        table bgp_v6;
        import all;
        export none;
    };

    route 2a10:2f00:18a::/48 blackhole;
}

# Specified IPv4 address configured for eth0
router id 103.41.60.187;

# Template
# template bgp AS213164v4 {
#      local 103.41.60.187 as WatakushiASN;
#
#      graceful restart on;
#
#      ipv4 {
#          export none;
#          import all;
#      };
# }

template bgp AS213164v6 {
    local 2401:af80:2917::21 as WatakushiASN;
    graceful restart on;
}

# Transit
# template bgp SEv4 from AS213164v4 {
#      password "microsoft";
#      hold time 30;
#      startup hold time 30;
#      keepalive time 10;
#
#      # こちら側
#      source address 103.41.60.187;
# }
template bgp SEv6 from AS213164v6 {
    password "microsoft";
    hold time 30;
    startup hold time 30;
    keepalive time 10;

    ipv6 {
        table bgp_v6;
        import filter bgp_59103_import;
        export filter bgp_59103_export;
    };

    # こちら側
    source address 2401:af80:2917::21;
}

# protocol bgp SEv4Primary from SEv4 {
#      description "SoftEther Primary v4";
#      # 相手方
#      neighbor 103.41.60.164 as SoftEtherASN;
# }
# protocol bgp SEv4Secondary from SEv4 {
#      description "SoftEther Secondary v4";
#      # 相手方
#      neighbor 103.41.60.165 as SoftEtherASN;
# }
protocol bgp SEv6Primary from SEv6 {
    description "SoftEther Primary v6";
    # 相手方
    neighbor 2401:af80:2917::4 as SoftEtherASN;
}
protocol bgp SEv6Secondary from SEv6 {
    description "SoftEther Secondary v6";
    # 相手方
    neighbor 2401:af80:2917::5 as SoftEtherASN;
}

protocol pipe pipe_bgp_v6_kernel_v6 {
    table bgp_v6;
    peer table kernel_v6;

    import none;
    export filter {
        if (proto = "static_v6_advertised_prefixes") then reject;
        accept;
    };
}