Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/tools/testing/selftests/drivers/net/hw/ipsec_vxlan.py
216637 views
1
#!/usr/bin/env python3
2
# SPDX-License-Identifier: GPL-2.0
3
"""Traffic test for VXLAN + IPsec crypto-offload."""
4
5
import os
6
7
from lib.py import ksft_run, ksft_exit, ksft_eq, ksft_ge
8
from lib.py import ksft_variants, KsftNamedVariant, KsftSkipEx
9
from lib.py import CmdExitFailure, NetDrvEpEnv, cmd, defer, ethtool, ip
10
from lib.py import Iperf3Runner
11
12
# Inner tunnel addresses - TEST-NET-2 (RFC 5737) / doc prefix (RFC 3849)
13
INNER_V4_LOCAL = "198.51.100.1"
14
INNER_V4_REMOTE = "198.51.100.2"
15
INNER_V6_LOCAL = "2001:db8:100::1"
16
INNER_V6_REMOTE = "2001:db8:100::2"
17
18
# ESP parameters
19
SPI_OUT = "0x1000"
20
SPI_IN = "0x1001"
21
# 128-bit key + 32-bit salt = 20 bytes hex, 128-bit ICV
22
ESP_AEAD = "aead 'rfc4106(gcm(aes))' 0x" + "01" * 20 + " 128"
23
24
25
def xfrm(args, host=None):
26
"""Runs 'ip xfrm' via shell to preserve parentheses in algo names."""
27
cmd(f"ip xfrm {args}", shell=True, host=host)
28
29
30
def check_xfrm_offload_support():
31
"""Skips if iproute2 lacks xfrm offload support."""
32
out = cmd("ip xfrm state help", fail=False)
33
if "offload" not in out.stdout + out.stderr:
34
raise KsftSkipEx("iproute2 too old, missing xfrm offload")
35
36
37
def check_esp_hw_offload(cfg):
38
"""Skips if device lacks esp-hw-offload support."""
39
check_xfrm_offload_support()
40
try:
41
feat = ethtool(f"-k {cfg.ifname}", json=True)[0]
42
except (CmdExitFailure, IndexError) as e:
43
raise KsftSkipEx(f"can't query features: {e}") from e
44
if not feat.get("esp-hw-offload", {}).get("active"):
45
raise KsftSkipEx("Device does not support esp-hw-offload")
46
47
48
def get_tx_drops(cfg):
49
"""Returns TX dropped counter from the physical device."""
50
stats = ip("-s -s link show dev " + cfg.ifname, json=True)[0]
51
return stats["stats64"]["tx"]["dropped"]
52
53
54
def setup_vxlan_ipsec(cfg, outer_ipver, inner_ipver):
55
"""Sets up VXLAN tunnel with IPsec transport-mode crypto-offload."""
56
vxlan_name = f"vx{os.getpid()}"
57
local_addr = cfg.addr_v[outer_ipver]
58
remote_addr = cfg.remote_addr_v[outer_ipver]
59
60
if inner_ipver == "4":
61
inner_local = f"{INNER_V4_LOCAL}/24"
62
inner_remote = f"{INNER_V4_REMOTE}/24"
63
addr_extra = ""
64
else:
65
inner_local = f"{INNER_V6_LOCAL}/64"
66
inner_remote = f"{INNER_V6_REMOTE}/64"
67
addr_extra = " nodad"
68
69
if outer_ipver == "6":
70
vxlan_opts = "udp6zerocsumtx udp6zerocsumrx"
71
else:
72
vxlan_opts = "noudpcsum"
73
74
# VXLAN tunnel - local side
75
ip(f"link add {vxlan_name} type vxlan id 100 dstport 4789 {vxlan_opts} "
76
f"local {local_addr} remote {remote_addr} dev {cfg.ifname}")
77
defer(ip, f"link del {vxlan_name}")
78
ip(f"addr add {inner_local} dev {vxlan_name}{addr_extra}")
79
ip(f"link set {vxlan_name} up")
80
81
# VXLAN tunnel - remote side
82
ip(f"link add {vxlan_name} type vxlan id 100 dstport 4789 {vxlan_opts} "
83
f"local {remote_addr} remote {local_addr} dev {cfg.remote_ifname}",
84
host=cfg.remote)
85
defer(ip, f"link del {vxlan_name}", host=cfg.remote)
86
ip(f"addr add {inner_remote} dev {vxlan_name}{addr_extra}",
87
host=cfg.remote)
88
ip(f"link set {vxlan_name} up", host=cfg.remote)
89
90
# xfrm state - local outbound SA
91
xfrm(f"state add src {local_addr} dst {remote_addr} "
92
f"proto esp spi {SPI_OUT} "
93
f"{ESP_AEAD} "
94
f"mode transport offload crypto dev {cfg.ifname} dir out")
95
defer(xfrm, f"state del src {local_addr} dst {remote_addr} "
96
f"proto esp spi {SPI_OUT}")
97
98
# xfrm state - local inbound SA
99
xfrm(f"state add src {remote_addr} dst {local_addr} "
100
f"proto esp spi {SPI_IN} "
101
f"{ESP_AEAD} "
102
f"mode transport offload crypto dev {cfg.ifname} dir in")
103
defer(xfrm, f"state del src {remote_addr} dst {local_addr} "
104
f"proto esp spi {SPI_IN}")
105
106
# xfrm state - remote outbound SA (mirror, software crypto)
107
xfrm(f"state add src {remote_addr} dst {local_addr} "
108
f"proto esp spi {SPI_IN} "
109
f"{ESP_AEAD} "
110
f"mode transport",
111
host=cfg.remote)
112
defer(xfrm, f"state del src {remote_addr} dst {local_addr} "
113
f"proto esp spi {SPI_IN}", host=cfg.remote)
114
115
# xfrm state - remote inbound SA (mirror, software crypto)
116
xfrm(f"state add src {local_addr} dst {remote_addr} "
117
f"proto esp spi {SPI_OUT} "
118
f"{ESP_AEAD} "
119
f"mode transport",
120
host=cfg.remote)
121
defer(xfrm, f"state del src {local_addr} dst {remote_addr} "
122
f"proto esp spi {SPI_OUT}", host=cfg.remote)
123
124
# xfrm policy - local out
125
xfrm(f"policy add src {local_addr} dst {remote_addr} "
126
f"proto udp dport 4789 dir out "
127
f"tmpl src {local_addr} dst {remote_addr} proto esp mode transport")
128
defer(xfrm, f"policy del src {local_addr} dst {remote_addr} "
129
f"proto udp dport 4789 dir out")
130
131
# xfrm policy - local in
132
xfrm(f"policy add src {remote_addr} dst {local_addr} "
133
f"proto udp dport 4789 dir in "
134
f"tmpl src {remote_addr} dst {local_addr} proto esp mode transport")
135
defer(xfrm, f"policy del src {remote_addr} dst {local_addr} "
136
f"proto udp dport 4789 dir in")
137
138
# xfrm policy - remote out
139
xfrm(f"policy add src {remote_addr} dst {local_addr} "
140
f"proto udp dport 4789 dir out "
141
f"tmpl src {remote_addr} dst {local_addr} proto esp mode transport",
142
host=cfg.remote)
143
defer(xfrm, f"policy del src {remote_addr} dst {local_addr} "
144
f"proto udp dport 4789 dir out", host=cfg.remote)
145
146
# xfrm policy - remote in
147
xfrm(f"policy add src {local_addr} dst {remote_addr} "
148
f"proto udp dport 4789 dir in "
149
f"tmpl src {local_addr} dst {remote_addr} proto esp mode transport",
150
host=cfg.remote)
151
defer(xfrm, f"policy del src {local_addr} dst {remote_addr} "
152
f"proto udp dport 4789 dir in", host=cfg.remote)
153
154
155
def _vxlan_ipsec_variants():
156
"""Generates outer/inner IP version variants."""
157
for outer in ["4", "6"]:
158
for inner in ["4", "6"]:
159
yield KsftNamedVariant(f"outer_v{outer}_inner_v{inner}", outer, inner)
160
161
162
@ksft_variants(_vxlan_ipsec_variants())
163
def test_vxlan_ipsec_crypto_offload(cfg, outer_ipver, inner_ipver):
164
"""Tests VXLAN+IPsec crypto-offload has no TX drops."""
165
cfg.require_ipver(outer_ipver)
166
check_esp_hw_offload(cfg)
167
168
setup_vxlan_ipsec(cfg, outer_ipver, inner_ipver)
169
170
if inner_ipver == "4":
171
inner_local = INNER_V4_LOCAL
172
inner_remote = INNER_V4_REMOTE
173
ping = "ping"
174
else:
175
inner_local = INNER_V6_LOCAL
176
inner_remote = INNER_V6_REMOTE
177
ping = "ping -6"
178
179
cmd(f"{ping} -c 1 -W 2 {inner_remote}")
180
181
drops_before = get_tx_drops(cfg)
182
183
runner = Iperf3Runner(cfg, server_ip=inner_local,
184
client_ip=inner_remote)
185
bw_gbps = runner.measure_bandwidth(reverse=True)
186
187
cfg.wait_hw_stats_settle()
188
drops_after = get_tx_drops(cfg)
189
190
ksft_eq(drops_after - drops_before, 0,
191
comment="TX drops during VXLAN+IPsec")
192
ksft_ge(bw_gbps, 0.1,
193
comment="Minimum 100Mbps over VXLAN+IPsec")
194
195
196
def main():
197
"""Runs VXLAN+IPsec crypto-offload GSO selftest."""
198
with NetDrvEpEnv(__file__, nsim_test=False) as cfg:
199
ksft_run([test_vxlan_ipsec_crypto_offload], args=(cfg,))
200
ksft_exit()
201
202
203
if __name__ == "__main__":
204
main()
205
206