CML2.8 Free TierでEVPN-VXLAN(non-multicast, eBGP)

@trustywolfさんの素敵なクリスマスプレゼント「[IOLを用いてEVPN-VXLANを検証してみた](https://qiita.com/trustywolf/items/20525b9c2526f49ada56#_reference-41111ed596e9751020f1)」によって家庭でも簡単にEVPN-VXLAN環境を作ることができるようになりました。ところが冬休みなので以下のような気持ちになる方もいるでしょう。

- iBGPよりeBGPにロマンを感じる (意訳: eBGP越しでEVPN-VXLANをしたい)
- multicastはオシャレすぎる (意訳: ingress-replicationでunicast forwardしたい)

Cisco公式ドキュメントで最初に目にする多くはiBGPかつmulticastを用いたものだと思いますが、本記事ではeBGP + unicastでこれを実現します。

# 構成
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/30938/46f2342a-9a0a-0c7b-6df5-67740b0a3228.png)

- RT1,2,3は`L2 IOL`です。(IOLL3の場合は後述します)
- AS65001を拠点A, AS65002を拠点Zと見立てて、A-Z間でvlan100を延伸したいとします
- AS65003はIPパケットのみをトランジットするASと見なします。EVPN, VXLANに関わる設定は一切入れません。multicastは透過しないとします

# Configや設定変更
[github](https://github.com/recuraki/ciscoCmlLabAutomation/tree/main/vxlanEvpnIOLSW)にあります。[過去の記事](https://qiita.com/recuraki/items/167b354310377f12d8d1)の用にCMLの構築は自動化されています。一部のConfigがAnsibleで入らなかったので[config](https://github.com/recuraki/ciscoCmlLabAutomation/tree/main/vxlanEvpnIOLSW/config)はこのディレクトリのConfigを流し込みます。
```bash
python3 10_createLab.py
python 20_inventory.py
ansible-playbook -i inventory.yaml 30_setconfig.yaml
! ここでRT1,2,3にConfigを手動で流し込みBGP upをまつ。
ansible-playbook -i inventory.yaml 40_testping.yaml
```

# 設定のポイント: RT1-RT3間

- iBGPでEVPN-VXLANの実験をする際、`route-target auto vni`によりRTを自動生成するとASNUM:VNIをベースにRTが生成されます。importするときのfilterも自動で書かれます。eBGPの場合はASNUMが異なるVTEP Leaf間でeVPN経路を交換するため、ここは手動で合わせる必要があります
- トンネリング系の一般的な注意点ですが、この構成においてはlo1でunicastアドレスを広告しないように(つまり、underlay側の経路を交換しないように)します

# 設定のポイント: RT1 / RT2
[config](https://github.com/recuraki/ciscoCmlLabAutomation/blob/main/vxlanEvpnIOLSW/config/RT3)

## EVPN

`replication-type ingress`にすることとRTを明示的に書きます。

```bash
l2vpn evpn
 logging peer state
 replication-type ingress
 router-id Loopback1
 route-target auto vni ! VNIに対するRTを自動で付与するASNUM:VNIをベースに生成
l2vpn evpn instance 1 vlan-based
 encapsulation vxlan
 route-target export 65000:1 ! RTを手動で追加している。65000:1とする。
 route-target import 65000:1
 replication-type ingress ! マルチキャスト系をIPマルチキャストではなくUnicast複製にする
```

## VXLAN(IOLL2の場合)

特に注意事項はありません。interface nve1の中でもingress-replicationの記述は必要です。なお、この例は、IOLL2であることに注意します。IOLL3の場合は文末に差分を記載しました。

```bash
vlan configuration 100
 member evpn-instance 1 vni 10100 ! vlan 100をEVPNに紐付ける
!
interface Ethernet0/2
 description PC1
 switchport access vlan 100
 switchport mode access
!
interface nve1 ! VTEPの設定(Vxlan IPv4, port4789)
 no ip address
 source-interface Loopback1 ! sourceはLo1を使う
 host-reachability protocol bgp
 member vni 10100 ingress-replication
 ```
 
## BGP

`next-hop-unchanged`はこの構成では不要ですが入れています。underlayとoverlayに注意しながら必要なAFIだけを有効にしましょう。

```bash
router bgp 65001
 no bgp default ipv4-unicast ! いれなくてもいいがlo1は no ipv4 uniすること。
 neighbor 192.168.1.1 remote-as 65003 ! underlay
 neighbor 192.168.254.2 remote-as 65002 ! lo1間のpeer
 neighbor 192.168.254.2 ebgp-multihop 255 ! overlayはmultihopになるのでTTLを増やす
 neighbor 192.168.254.2 update-source Loopback1
 !
 address-family ipv4
  redistribute connected
  neighbor 192.168.1.1 activate ! underlay向け
  neighbor 192.168.1.1 soft-reconfiguration inbound
  ! no bgp default ipv4-unicast しない場合はここでno neigh 192.168.254.2 activateが必要
 exit-address-family
 !
 address-family l2vpn evpn
  ! overlay
  neighbor 192.168.254.2 activate
  neighbor 192.168.254.2 send-community both
  neighbor 192.168.254.2 next-hop-unchanged ! for multihop eBGP peer
  neighbor 192.168.254.2 soft-reconfiguration inbound
 exit-address-family
```


# 設定のポイント: RT3
[config](https://github.com/recuraki/ciscoCmlLabAutomation/blob/main/vxlanEvpnIOLSW/config/RT3)

単にipv4 unicastのみをA-Z間で交換してルーティングします。

# 結果

```
pc1:~$ ping 10.100.0.2 -c 1
64 bytes from 10.100.0.2: seq=0 ttl=42 time=2.691 ms
1 packets transmitted, 1 packets received, 0% packet los
```

できました！

```text
! autoとstatic両方が降られていることがわかる
rt1#show l2vpn evpn route-target
Route Target           EVPN Instances
65000:1                1
65001:10100            1

rt1#show l2vpn evpn evi 1 detail
EVPN instance:       1 (VLAN Based)
  RD:                192.168.254.1:1 (auto)
  Import-RTs:        65000:1 65001:10100 ! autoとstatic両方が降られていることがわかる
  Export-RTs:        65000:1 65001:10100 ! autoとstatic両方が降られていることがわかる
  Per-EVI Label:     none
  State:             Established
  Replication Type:  Ingress
  Encapsulation:     vxlan
  IP Local Learn:    Enabled (global)
  Adv. Def. Gateway: Disabled (global)
  Re-originate RT5:  Disabled
  Adv. Multicast:    Disabled (global)
  AR Flood Suppress: Enabled (global)
  Vlan:              100
    Protected:       False
    Ethernet-Tag:    0
    State:           Established
    Flood Suppress:  Attached
    Core If:
    Access If:
    NVE If:          nve1
    RMAC:            0000.0000.0000
    Core Vlan:       0
    L2 VNI:          10100
    L3 VNI:          0
    VTEP IP:         192.168.254.1
    Pseudoports:
    
rt1#show l2vpn evpn peers
Interface VNI      Peer-IP                                 Num routes eVNI     UP time
nve1      10100    192.168.254.2                           4          10100    00:49:03


rt1#show nve vni
Interface  VNI        Multicast-group  VNI state  Mode  VLAN  cfg vrf
nve1       10100      N/A              Up         L2CP  100   CLI N/A

rt1#show bgp l2vpn evpn
     Network          Next Hop            Metric LocPrf Weight Path
Route Distinguisher: 192.168.254.1:1
 *>   [2][192.168.254.1:1][0][48][525400187BED][0][*]/20
                      0.0.0.0                            32768 ?
 *>   [2][192.168.254.1:1][0][48][525400187BED][32][10.100.0.1]/24
                      0.0.0.0                            32768 ?
 *>   [2][192.168.254.1:1][0][48][525400187BED][128][FE80::5054:FF:FE18:7BED]/36
                      0.0.0.0                            32768 ?
 *>   [2][192.168.254.1:1][0][48][5254005E6168][0][*]/20
                      192.168.254.2            0             0 65002 ?
 *>   [2][192.168.254.1:1][0][48][5254005E6168][32][10.100.0.2]/24
                      192.168.254.2            0             0 65002 ?
 *>   [2][192.168.254.1:1][0][48][5254005E6168][128][FE80::5054:FF:FE5E:6168]/36
                      192.168.254.2            0             0 65002 ?
Route Distinguisher: 192.168.254.2:1
 *>   [2][192.168.254.2:1][0][48][5254005E6168][0][*]/20
                      192.168.254.2            0             0 65002 ?
 *>   [2][192.168.254.2:1][0][48][5254005E6168][32][10.100.0.2]/24
     Network          Next Hop            Metric LocPrf Weight Path
                      192.168.254.2            0             0 65002 ?
 *>   [2][192.168.254.2:1][0][48][5254005E6168][128][FE80::5054:FF:FE5E:6168]/36
                      192.168.254.2            0             0 65002 ?
Route Distinguisher: 192.168.254.1:1
 *>   [3][192.168.254.1:1][0][32][192.168.254.1]/17
                      0.0.0.0                            32768 ?
 *>   [3][192.168.254.1:1][0][32][192.168.254.2]/17
                      192.168.254.2            0             0 65002 ?
Route Distinguisher: 192.168.254.2:1
 *>   [3][192.168.254.2:1][0][32][192.168.254.2]/17
                      192.168.254.2            0             0 65002 ?
```

# TIPS 2バイトASと4バイトAS　と　auto vni
このシナリオにおいて、4byte AS番号を用いていると` route-target export/import`は不要です。なぜなら、23456:<vni>にmapされ経路はimport/exportされます。しかし、2byte AS番号では<ASN>:<vni>にmapされるため、その経路は学習されません。
<img src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/30938/53d20cfd-eee5-e49a-afa1-9ee248b35a71.png width=50%><img src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/30938/f70650a3-d620-c6e0-8744-cd4e50e4b31f.png width=50%>

# IOLL2ではなくIOLL3を使う
IOL(Router)を使って同様の環境(L2延伸)を作ろうとする場合にはbridge-domainを使用しなければなりません。この方法を説明します。

[config IOLL3](https://github.com/recuraki/ciscoCmlLabAutomation/tree/main/vxlanEvpnIOL3/config)

### L2の場合(IOL-L2)
```bash
vlan configuration 100
 member evpn-instance 1 vni 10100
!
interface Ethernet0/2
 description PC1
 switchport access vlan 100
 switchport mode access
!
interface nve1
 no ip address
 source-interface Loopback1
 host-reachability protocol bgp
 member vni 10100 ingress-replication
 ```

### L3の場合(IOL)

```bash
bridge-domain 100
 member Ethernet0/2 service-instance 100
 member evpn-instance 1 vni 10100
!
interface BDI100
 no shut ! これが重要。BDIを作り no shutしないといけない
!
interface Ethernet0/2
 no shut
 no ip address
 bridge-group 100
 service instance 100 ethernet
  encapsulation untagged ! ここも重要。taggedしなくてもuntagを明記しないといけない
! ここは変化なし
interface nve1
 no ip address
 source-interface Loopback1
 host-reachability protocol bgp
 member vni 10100 ingress-replication 
```



# まとめ
CML2.8 Free Tier上にIPv4 Only Underlay上でEVPN-VXLANを張りました。Cisco公式ドキュメントで最初に目にする多くはiBGPかつmulticastを用いたものですが本記事ではeBGP + unicastでこれを実現します。どんどんEVPN-VXLANであそびましょう！