aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c27
-rwxr-xr-xtools/testing/selftests/drivers/net/mlxsw/blackhole_routes.sh200
2 files changed, 225 insertions, 2 deletions
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
index 230e1f6e192b..6754061d9b72 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
@@ -364,6 +364,7 @@ enum mlxsw_sp_fib_entry_type {
364 MLXSW_SP_FIB_ENTRY_TYPE_REMOTE, 364 MLXSW_SP_FIB_ENTRY_TYPE_REMOTE,
365 MLXSW_SP_FIB_ENTRY_TYPE_LOCAL, 365 MLXSW_SP_FIB_ENTRY_TYPE_LOCAL,
366 MLXSW_SP_FIB_ENTRY_TYPE_TRAP, 366 MLXSW_SP_FIB_ENTRY_TYPE_TRAP,
367 MLXSW_SP_FIB_ENTRY_TYPE_BLACKHOLE,
367 368
368 /* This is a special case of local delivery, where a packet should be 369 /* This is a special case of local delivery, where a packet should be
369 * decapsulated on reception. Note that there is no corresponding ENCAP, 370 * decapsulated on reception. Note that there is no corresponding ENCAP,
@@ -3928,6 +3929,7 @@ mlxsw_sp_fib_entry_should_offload(const struct mlxsw_sp_fib_entry *fib_entry)
3928 return !!nh_group->adj_index_valid; 3929 return !!nh_group->adj_index_valid;
3929 case MLXSW_SP_FIB_ENTRY_TYPE_LOCAL: 3930 case MLXSW_SP_FIB_ENTRY_TYPE_LOCAL:
3930 return !!nh_group->nh_rif; 3931 return !!nh_group->nh_rif;
3932 case MLXSW_SP_FIB_ENTRY_TYPE_BLACKHOLE:
3931 case MLXSW_SP_FIB_ENTRY_TYPE_IPIP_DECAP: 3933 case MLXSW_SP_FIB_ENTRY_TYPE_IPIP_DECAP:
3932 case MLXSW_SP_FIB_ENTRY_TYPE_NVE_DECAP: 3934 case MLXSW_SP_FIB_ENTRY_TYPE_NVE_DECAP:
3933 return true; 3935 return true;
@@ -3963,6 +3965,7 @@ mlxsw_sp_fib4_entry_offload_set(struct mlxsw_sp_fib_entry *fib_entry)
3963 int i; 3965 int i;
3964 3966
3965 if (fib_entry->type == MLXSW_SP_FIB_ENTRY_TYPE_LOCAL || 3967 if (fib_entry->type == MLXSW_SP_FIB_ENTRY_TYPE_LOCAL ||
3968 fib_entry->type == MLXSW_SP_FIB_ENTRY_TYPE_BLACKHOLE ||
3966 fib_entry->type == MLXSW_SP_FIB_ENTRY_TYPE_IPIP_DECAP || 3969 fib_entry->type == MLXSW_SP_FIB_ENTRY_TYPE_IPIP_DECAP ||
3967 fib_entry->type == MLXSW_SP_FIB_ENTRY_TYPE_NVE_DECAP) { 3970 fib_entry->type == MLXSW_SP_FIB_ENTRY_TYPE_NVE_DECAP) {
3968 nh_grp->nexthops->key.fib_nh->nh_flags |= RTNH_F_OFFLOAD; 3971 nh_grp->nexthops->key.fib_nh->nh_flags |= RTNH_F_OFFLOAD;
@@ -4004,7 +4007,8 @@ mlxsw_sp_fib6_entry_offload_set(struct mlxsw_sp_fib_entry *fib_entry)
4004 fib6_entry = container_of(fib_entry, struct mlxsw_sp_fib6_entry, 4007 fib6_entry = container_of(fib_entry, struct mlxsw_sp_fib6_entry,
4005 common); 4008 common);
4006 4009
4007 if (fib_entry->type == MLXSW_SP_FIB_ENTRY_TYPE_LOCAL) { 4010 if (fib_entry->type == MLXSW_SP_FIB_ENTRY_TYPE_LOCAL ||
4011 fib_entry->type == MLXSW_SP_FIB_ENTRY_TYPE_BLACKHOLE) {
4008 list_first_entry(&fib6_entry->rt6_list, struct mlxsw_sp_rt6, 4012 list_first_entry(&fib6_entry->rt6_list, struct mlxsw_sp_rt6,
4009 list)->rt->fib6_nh.nh_flags |= RTNH_F_OFFLOAD; 4013 list)->rt->fib6_nh.nh_flags |= RTNH_F_OFFLOAD;
4010 return; 4014 return;
@@ -4172,6 +4176,19 @@ static int mlxsw_sp_fib_entry_op_trap(struct mlxsw_sp *mlxsw_sp,
4172 return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ralue), ralue_pl); 4176 return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ralue), ralue_pl);
4173} 4177}
4174 4178
4179static int mlxsw_sp_fib_entry_op_blackhole(struct mlxsw_sp *mlxsw_sp,
4180 struct mlxsw_sp_fib_entry *fib_entry,
4181 enum mlxsw_reg_ralue_op op)
4182{
4183 enum mlxsw_reg_ralue_trap_action trap_action;
4184 char ralue_pl[MLXSW_REG_RALUE_LEN];
4185
4186 trap_action = MLXSW_REG_RALUE_TRAP_ACTION_DISCARD_ERROR;
4187 mlxsw_sp_fib_entry_ralue_pack(ralue_pl, fib_entry, op);
4188 mlxsw_reg_ralue_act_local_pack(ralue_pl, trap_action, 0, 0);
4189 return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ralue), ralue_pl);
4190}
4191
4175static int 4192static int
4176mlxsw_sp_fib_entry_op_ipip_decap(struct mlxsw_sp *mlxsw_sp, 4193mlxsw_sp_fib_entry_op_ipip_decap(struct mlxsw_sp *mlxsw_sp,
4177 struct mlxsw_sp_fib_entry *fib_entry, 4194 struct mlxsw_sp_fib_entry *fib_entry,
@@ -4211,6 +4228,8 @@ static int __mlxsw_sp_fib_entry_op(struct mlxsw_sp *mlxsw_sp,
4211 return mlxsw_sp_fib_entry_op_local(mlxsw_sp, fib_entry, op); 4228 return mlxsw_sp_fib_entry_op_local(mlxsw_sp, fib_entry, op);
4212 case MLXSW_SP_FIB_ENTRY_TYPE_TRAP: 4229 case MLXSW_SP_FIB_ENTRY_TYPE_TRAP:
4213 return mlxsw_sp_fib_entry_op_trap(mlxsw_sp, fib_entry, op); 4230 return mlxsw_sp_fib_entry_op_trap(mlxsw_sp, fib_entry, op);
4231 case MLXSW_SP_FIB_ENTRY_TYPE_BLACKHOLE:
4232 return mlxsw_sp_fib_entry_op_blackhole(mlxsw_sp, fib_entry, op);
4214 case MLXSW_SP_FIB_ENTRY_TYPE_IPIP_DECAP: 4233 case MLXSW_SP_FIB_ENTRY_TYPE_IPIP_DECAP:
4215 return mlxsw_sp_fib_entry_op_ipip_decap(mlxsw_sp, 4234 return mlxsw_sp_fib_entry_op_ipip_decap(mlxsw_sp,
4216 fib_entry, op); 4235 fib_entry, op);
@@ -4279,8 +4298,10 @@ mlxsw_sp_fib4_entry_type_set(struct mlxsw_sp *mlxsw_sp,
4279 case RTN_BROADCAST: 4298 case RTN_BROADCAST:
4280 fib_entry->type = MLXSW_SP_FIB_ENTRY_TYPE_TRAP; 4299 fib_entry->type = MLXSW_SP_FIB_ENTRY_TYPE_TRAP;
4281 return 0; 4300 return 0;
4301 case RTN_BLACKHOLE:
4302 fib_entry->type = MLXSW_SP_FIB_ENTRY_TYPE_BLACKHOLE;
4303 return 0;
4282 case RTN_UNREACHABLE: /* fall through */ 4304 case RTN_UNREACHABLE: /* fall through */
4283 case RTN_BLACKHOLE: /* fall through */
4284 case RTN_PROHIBIT: 4305 case RTN_PROHIBIT:
4285 /* Packets hitting these routes need to be trapped, but 4306 /* Packets hitting these routes need to be trapped, but
4286 * can do so with a lower priority than packets directed 4307 * can do so with a lower priority than packets directed
@@ -5229,6 +5250,8 @@ static void mlxsw_sp_fib6_entry_type_set(struct mlxsw_sp *mlxsw_sp,
5229 */ 5250 */
5230 if (rt->fib6_flags & (RTF_LOCAL | RTF_ANYCAST)) 5251 if (rt->fib6_flags & (RTF_LOCAL | RTF_ANYCAST))
5231 fib_entry->type = MLXSW_SP_FIB_ENTRY_TYPE_TRAP; 5252 fib_entry->type = MLXSW_SP_FIB_ENTRY_TYPE_TRAP;
5253 else if (rt->fib6_type == RTN_BLACKHOLE)
5254 fib_entry->type = MLXSW_SP_FIB_ENTRY_TYPE_BLACKHOLE;
5232 else if (rt->fib6_flags & RTF_REJECT) 5255 else if (rt->fib6_flags & RTF_REJECT)
5233 fib_entry->type = MLXSW_SP_FIB_ENTRY_TYPE_LOCAL; 5256 fib_entry->type = MLXSW_SP_FIB_ENTRY_TYPE_LOCAL;
5234 else if (mlxsw_sp_rt6_is_gateway(mlxsw_sp, rt)) 5257 else if (mlxsw_sp_rt6_is_gateway(mlxsw_sp, rt))
diff --git a/tools/testing/selftests/drivers/net/mlxsw/blackhole_routes.sh b/tools/testing/selftests/drivers/net/mlxsw/blackhole_routes.sh
new file mode 100755
index 000000000000..5ba5bef44d5b
--- /dev/null
+++ b/tools/testing/selftests/drivers/net/mlxsw/blackhole_routes.sh
@@ -0,0 +1,200 @@
1#!/bin/bash
2# SPDX-License-Identifier: GPL-2.0
3#
4# Test that blackhole routes are marked as offloaded and that packets hitting
5# them are dropped by the ASIC and not by the kernel.
6#
7# +---------------------------------+
8# | H1 (vrf) |
9# | + $h1 |
10# | | 192.0.2.1/24 |
11# | | 2001:db8:1::1/64 |
12# | | |
13# | | default via 192.0.2.2 |
14# | | default via 2001:db8:1::2 |
15# +----|----------------------------+
16# |
17# +----|----------------------------------------------------------------------+
18# | SW | |
19# | + $rp1 |
20# | 192.0.2.2/24 |
21# | 2001:db8:1::2/64 |
22# | |
23# | 2001:db8:2::2/64 |
24# | 198.51.100.2/24 |
25# | + $rp2 |
26# | | |
27# +----|----------------------------------------------------------------------+
28# |
29# +----|----------------------------+
30# | | default via 198.51.100.2 |
31# | | default via 2001:db8:2::2 |
32# | | |
33# | | 2001:db8:2::1/64 |
34# | | 198.51.100.1/24 |
35# | + $h2 |
36# | H2 (vrf) |
37# +---------------------------------+
38
39lib_dir=$(dirname $0)/../../../net/forwarding
40
41ALL_TESTS="
42 ping_ipv4
43 ping_ipv6
44 blackhole_ipv4
45 blackhole_ipv6
46"
47NUM_NETIFS=4
48source $lib_dir/tc_common.sh
49source $lib_dir/lib.sh
50
51h1_create()
52{
53 simple_if_init $h1 192.0.2.1/24 2001:db8:1::1/64
54
55 ip -4 route add default vrf v$h1 nexthop via 192.0.2.2
56 ip -6 route add default vrf v$h1 nexthop via 2001:db8:1::2
57}
58
59h1_destroy()
60{
61 ip -6 route del default vrf v$h1 nexthop via 2001:db8:1::2
62 ip -4 route del default vrf v$h1 nexthop via 192.0.2.2
63
64 simple_if_fini $h1 192.0.2.1/24 2001:db8:1::1/64
65}
66
67h2_create()
68{
69 simple_if_init $h2 198.51.100.1/24 2001:db8:2::1/64
70
71 ip -4 route add default vrf v$h2 nexthop via 198.51.100.2
72 ip -6 route add default vrf v$h2 nexthop via 2001:db8:2::2
73}
74
75h2_destroy()
76{
77 ip -6 route del default vrf v$h2 nexthop via 2001:db8:2::2
78 ip -4 route del default vrf v$h2 nexthop via 198.51.100.2
79
80 simple_if_fini $h2 198.51.100.1/24 2001:db8:2::1/64
81}
82
83router_create()
84{
85 ip link set dev $rp1 up
86 ip link set dev $rp2 up
87
88 tc qdisc add dev $rp1 clsact
89
90 __addr_add_del $rp1 add 192.0.2.2/24 2001:db8:1::2/64
91 __addr_add_del $rp2 add 198.51.100.2/24 2001:db8:2::2/64
92}
93
94router_destroy()
95{
96 __addr_add_del $rp2 del 198.51.100.2/24 2001:db8:2::2/64
97 __addr_add_del $rp1 del 192.0.2.2/24 2001:db8:1::2/64
98
99 tc qdisc del dev $rp1 clsact
100
101 ip link set dev $rp2 down
102 ip link set dev $rp1 down
103}
104
105ping_ipv4()
106{
107 ping_test $h1 198.51.100.1 ": h1->h2"
108}
109
110ping_ipv6()
111{
112 ping6_test $h1 2001:db8:2::1 ": h1->h2"
113}
114
115blackhole_ipv4()
116{
117 # Transmit packets from H1 to H2 and make sure they are dropped by the
118 # ASIC and not by the kernel
119 RET=0
120
121 ip -4 route add blackhole 198.51.100.0/30
122 tc filter add dev $rp1 ingress protocol ip pref 1 handle 101 flower \
123 skip_hw dst_ip 198.51.100.1 src_ip 192.0.2.1 ip_proto icmp \
124 action pass
125
126 ip -4 route show 198.51.100.0/30 | grep -q offload
127 check_err $? "route not marked as offloaded when should"
128
129 ping_do $h1 198.51.100.1
130 check_fail $? "ping passed when should not"
131
132 tc_check_packets "dev $rp1 ingress" 101 0
133 check_err $? "packets trapped and not dropped by ASIC"
134
135 log_test "IPv4 blackhole route"
136
137 tc filter del dev $rp1 ingress protocol ip pref 1 handle 101 flower
138 ip -4 route del blackhole 198.51.100.0/30
139}
140
141blackhole_ipv6()
142{
143 RET=0
144
145 ip -6 route add blackhole 2001:db8:2::/120
146 tc filter add dev $rp1 ingress protocol ipv6 pref 1 handle 101 flower \
147 skip_hw dst_ip 2001:db8:2::1 src_ip 2001:db8:1::1 \
148 ip_proto icmpv6 action pass
149
150 ip -6 route show 2001:db8:2::/120 | grep -q offload
151 check_err $? "route not marked as offloaded when should"
152
153 ping6_do $h1 2001:db8:2::1
154 check_fail $? "ping passed when should not"
155
156 tc_check_packets "dev $rp1 ingress" 101 0
157 check_err $? "packets trapped and not dropped by ASIC"
158
159 log_test "IPv6 blackhole route"
160
161 tc filter del dev $rp1 ingress protocol ipv6 pref 1 handle 101 flower
162 ip -6 route del blackhole 2001:db8:2::/120
163}
164
165setup_prepare()
166{
167 h1=${NETIFS[p1]}
168 rp1=${NETIFS[p2]}
169
170 rp2=${NETIFS[p3]}
171 h2=${NETIFS[p4]}
172
173 vrf_prepare
174 forwarding_enable
175
176 h1_create
177 h2_create
178 router_create
179}
180
181cleanup()
182{
183 pre_cleanup
184
185 router_destroy
186 h2_destroy
187 h1_destroy
188
189 forwarding_restore
190 vrf_cleanup
191}
192
193trap cleanup EXIT
194
195setup_prepare
196setup_wait
197
198tests_run
199
200exit $EXIT_STATUS