1 /* 2 * drivers/net/ethernet/mellanox/mlxsw/spectrum_flower.c 3 * Copyright (c) 2017 Mellanox Technologies. All rights reserved. 4 * Copyright (c) 2017 Jiri Pirko <jiri@mellanox.com> 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions are met: 8 * 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. Neither the names of the copyright holders nor the names of its 15 * contributors may be used to endorse or promote products derived from 16 * this software without specific prior written permission. 17 * 18 * Alternatively, this software may be distributed under the terms of the 19 * GNU General Public License ("GPL") version 2 as published by the Free 20 * Software Foundation. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 23 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 26 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 27 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 28 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 29 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 30 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 31 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 32 * POSSIBILITY OF SUCH DAMAGE. 33 */ 34 35 #include <linux/kernel.h> 36 #include <linux/errno.h> 37 #include <linux/netdevice.h> 38 #include <net/flow_dissector.h> 39 #include <net/pkt_cls.h> 40 #include <net/tc_act/tc_gact.h> 41 #include <net/tc_act/tc_mirred.h> 42 #include <net/tc_act/tc_vlan.h> 43 44 #include "spectrum.h" 45 #include "core_acl_flex_keys.h" 46 47 static int mlxsw_sp_flower_parse_actions(struct mlxsw_sp *mlxsw_sp, 48 struct net_device *dev, 49 struct mlxsw_sp_acl_rule_info *rulei, 50 struct tcf_exts *exts) 51 { 52 const struct tc_action *a; 53 LIST_HEAD(actions); 54 int err; 55 56 if (tc_no_actions(exts)) 57 return 0; 58 59 /* Count action is inserted first */ 60 err = mlxsw_sp_acl_rulei_act_count(mlxsw_sp, rulei); 61 if (err) 62 return err; 63 64 tcf_exts_to_list(exts, &actions); 65 list_for_each_entry(a, &actions, list) { 66 if (is_tcf_gact_shot(a)) { 67 err = mlxsw_sp_acl_rulei_act_drop(rulei); 68 if (err) 69 return err; 70 } else if (is_tcf_gact_trap(a)) { 71 err = mlxsw_sp_acl_rulei_act_trap(rulei); 72 if (err) 73 return err; 74 } else if (is_tcf_mirred_egress_redirect(a)) { 75 int ifindex = tcf_mirred_ifindex(a); 76 struct net_device *out_dev; 77 struct mlxsw_sp_fid *fid; 78 u16 fid_index; 79 80 fid = mlxsw_sp_acl_dummy_fid(mlxsw_sp); 81 fid_index = mlxsw_sp_fid_index(fid); 82 err = mlxsw_sp_acl_rulei_act_fid_set(mlxsw_sp, rulei, 83 fid_index); 84 if (err) 85 return err; 86 87 out_dev = __dev_get_by_index(dev_net(dev), ifindex); 88 if (out_dev == dev) 89 out_dev = NULL; 90 91 err = mlxsw_sp_acl_rulei_act_fwd(mlxsw_sp, rulei, 92 out_dev); 93 if (err) 94 return err; 95 } else if (is_tcf_vlan(a)) { 96 u16 proto = be16_to_cpu(tcf_vlan_push_proto(a)); 97 u32 action = tcf_vlan_action(a); 98 u8 prio = tcf_vlan_push_prio(a); 99 u16 vid = tcf_vlan_push_vid(a); 100 101 return mlxsw_sp_acl_rulei_act_vlan(mlxsw_sp, rulei, 102 action, vid, 103 proto, prio); 104 } else { 105 dev_err(mlxsw_sp->bus_info->dev, "Unsupported action\n"); 106 return -EOPNOTSUPP; 107 } 108 } 109 return 0; 110 } 111 112 static void mlxsw_sp_flower_parse_ipv4(struct mlxsw_sp_acl_rule_info *rulei, 113 struct tc_cls_flower_offload *f) 114 { 115 struct flow_dissector_key_ipv4_addrs *key = 116 skb_flow_dissector_target(f->dissector, 117 FLOW_DISSECTOR_KEY_IPV4_ADDRS, 118 f->key); 119 struct flow_dissector_key_ipv4_addrs *mask = 120 skb_flow_dissector_target(f->dissector, 121 FLOW_DISSECTOR_KEY_IPV4_ADDRS, 122 f->mask); 123 124 mlxsw_sp_acl_rulei_keymask_u32(rulei, MLXSW_AFK_ELEMENT_SRC_IP4, 125 ntohl(key->src), ntohl(mask->src)); 126 mlxsw_sp_acl_rulei_keymask_u32(rulei, MLXSW_AFK_ELEMENT_DST_IP4, 127 ntohl(key->dst), ntohl(mask->dst)); 128 } 129 130 static void mlxsw_sp_flower_parse_ipv6(struct mlxsw_sp_acl_rule_info *rulei, 131 struct tc_cls_flower_offload *f) 132 { 133 struct flow_dissector_key_ipv6_addrs *key = 134 skb_flow_dissector_target(f->dissector, 135 FLOW_DISSECTOR_KEY_IPV6_ADDRS, 136 f->key); 137 struct flow_dissector_key_ipv6_addrs *mask = 138 skb_flow_dissector_target(f->dissector, 139 FLOW_DISSECTOR_KEY_IPV6_ADDRS, 140 f->mask); 141 size_t addr_half_size = sizeof(key->src) / 2; 142 143 mlxsw_sp_acl_rulei_keymask_buf(rulei, MLXSW_AFK_ELEMENT_SRC_IP6_HI, 144 &key->src.s6_addr[0], 145 &mask->src.s6_addr[0], 146 addr_half_size); 147 mlxsw_sp_acl_rulei_keymask_buf(rulei, MLXSW_AFK_ELEMENT_SRC_IP6_LO, 148 &key->src.s6_addr[addr_half_size], 149 &mask->src.s6_addr[addr_half_size], 150 addr_half_size); 151 mlxsw_sp_acl_rulei_keymask_buf(rulei, MLXSW_AFK_ELEMENT_DST_IP6_HI, 152 &key->dst.s6_addr[0], 153 &mask->dst.s6_addr[0], 154 addr_half_size); 155 mlxsw_sp_acl_rulei_keymask_buf(rulei, MLXSW_AFK_ELEMENT_DST_IP6_LO, 156 &key->dst.s6_addr[addr_half_size], 157 &mask->dst.s6_addr[addr_half_size], 158 addr_half_size); 159 } 160 161 static int mlxsw_sp_flower_parse_ports(struct mlxsw_sp *mlxsw_sp, 162 struct mlxsw_sp_acl_rule_info *rulei, 163 struct tc_cls_flower_offload *f, 164 u8 ip_proto) 165 { 166 struct flow_dissector_key_ports *key, *mask; 167 168 if (!dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_PORTS)) 169 return 0; 170 171 if (ip_proto != IPPROTO_TCP && ip_proto != IPPROTO_UDP) { 172 dev_err(mlxsw_sp->bus_info->dev, "Only UDP and TCP keys are supported\n"); 173 return -EINVAL; 174 } 175 176 key = skb_flow_dissector_target(f->dissector, 177 FLOW_DISSECTOR_KEY_PORTS, 178 f->key); 179 mask = skb_flow_dissector_target(f->dissector, 180 FLOW_DISSECTOR_KEY_PORTS, 181 f->mask); 182 mlxsw_sp_acl_rulei_keymask_u32(rulei, MLXSW_AFK_ELEMENT_DST_L4_PORT, 183 ntohs(key->dst), ntohs(mask->dst)); 184 mlxsw_sp_acl_rulei_keymask_u32(rulei, MLXSW_AFK_ELEMENT_SRC_L4_PORT, 185 ntohs(key->src), ntohs(mask->src)); 186 return 0; 187 } 188 189 static int mlxsw_sp_flower_parse_tcp(struct mlxsw_sp *mlxsw_sp, 190 struct mlxsw_sp_acl_rule_info *rulei, 191 struct tc_cls_flower_offload *f, 192 u8 ip_proto) 193 { 194 struct flow_dissector_key_tcp *key, *mask; 195 196 if (!dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_TCP)) 197 return 0; 198 199 if (ip_proto != IPPROTO_TCP) { 200 dev_err(mlxsw_sp->bus_info->dev, "TCP keys supported only for TCP\n"); 201 return -EINVAL; 202 } 203 204 key = skb_flow_dissector_target(f->dissector, 205 FLOW_DISSECTOR_KEY_TCP, 206 f->key); 207 mask = skb_flow_dissector_target(f->dissector, 208 FLOW_DISSECTOR_KEY_TCP, 209 f->mask); 210 mlxsw_sp_acl_rulei_keymask_u32(rulei, MLXSW_AFK_ELEMENT_TCP_FLAGS, 211 ntohs(key->flags), ntohs(mask->flags)); 212 return 0; 213 } 214 215 static int mlxsw_sp_flower_parse(struct mlxsw_sp *mlxsw_sp, 216 struct net_device *dev, 217 struct mlxsw_sp_acl_rule_info *rulei, 218 struct tc_cls_flower_offload *f) 219 { 220 u16 addr_type = 0; 221 u8 ip_proto = 0; 222 int err; 223 224 if (f->dissector->used_keys & 225 ~(BIT(FLOW_DISSECTOR_KEY_CONTROL) | 226 BIT(FLOW_DISSECTOR_KEY_BASIC) | 227 BIT(FLOW_DISSECTOR_KEY_ETH_ADDRS) | 228 BIT(FLOW_DISSECTOR_KEY_IPV4_ADDRS) | 229 BIT(FLOW_DISSECTOR_KEY_IPV6_ADDRS) | 230 BIT(FLOW_DISSECTOR_KEY_PORTS) | 231 BIT(FLOW_DISSECTOR_KEY_TCP) | 232 BIT(FLOW_DISSECTOR_KEY_VLAN))) { 233 dev_err(mlxsw_sp->bus_info->dev, "Unsupported key\n"); 234 return -EOPNOTSUPP; 235 } 236 237 mlxsw_sp_acl_rulei_priority(rulei, f->prio); 238 239 if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_CONTROL)) { 240 struct flow_dissector_key_control *key = 241 skb_flow_dissector_target(f->dissector, 242 FLOW_DISSECTOR_KEY_CONTROL, 243 f->key); 244 addr_type = key->addr_type; 245 } 246 247 if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_BASIC)) { 248 struct flow_dissector_key_basic *key = 249 skb_flow_dissector_target(f->dissector, 250 FLOW_DISSECTOR_KEY_BASIC, 251 f->key); 252 struct flow_dissector_key_basic *mask = 253 skb_flow_dissector_target(f->dissector, 254 FLOW_DISSECTOR_KEY_BASIC, 255 f->mask); 256 u16 n_proto_key = ntohs(key->n_proto); 257 u16 n_proto_mask = ntohs(mask->n_proto); 258 259 if (n_proto_key == ETH_P_ALL) { 260 n_proto_key = 0; 261 n_proto_mask = 0; 262 } 263 mlxsw_sp_acl_rulei_keymask_u32(rulei, 264 MLXSW_AFK_ELEMENT_ETHERTYPE, 265 n_proto_key, n_proto_mask); 266 267 ip_proto = key->ip_proto; 268 mlxsw_sp_acl_rulei_keymask_u32(rulei, 269 MLXSW_AFK_ELEMENT_IP_PROTO, 270 key->ip_proto, mask->ip_proto); 271 } 272 273 if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_ETH_ADDRS)) { 274 struct flow_dissector_key_eth_addrs *key = 275 skb_flow_dissector_target(f->dissector, 276 FLOW_DISSECTOR_KEY_ETH_ADDRS, 277 f->key); 278 struct flow_dissector_key_eth_addrs *mask = 279 skb_flow_dissector_target(f->dissector, 280 FLOW_DISSECTOR_KEY_ETH_ADDRS, 281 f->mask); 282 283 mlxsw_sp_acl_rulei_keymask_buf(rulei, 284 MLXSW_AFK_ELEMENT_DMAC, 285 key->dst, mask->dst, 286 sizeof(key->dst)); 287 mlxsw_sp_acl_rulei_keymask_buf(rulei, 288 MLXSW_AFK_ELEMENT_SMAC, 289 key->src, mask->src, 290 sizeof(key->src)); 291 } 292 293 if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_VLAN)) { 294 struct flow_dissector_key_vlan *key = 295 skb_flow_dissector_target(f->dissector, 296 FLOW_DISSECTOR_KEY_VLAN, 297 f->key); 298 struct flow_dissector_key_vlan *mask = 299 skb_flow_dissector_target(f->dissector, 300 FLOW_DISSECTOR_KEY_VLAN, 301 f->mask); 302 if (mask->vlan_id != 0) 303 mlxsw_sp_acl_rulei_keymask_u32(rulei, 304 MLXSW_AFK_ELEMENT_VID, 305 key->vlan_id, 306 mask->vlan_id); 307 if (mask->vlan_priority != 0) 308 mlxsw_sp_acl_rulei_keymask_u32(rulei, 309 MLXSW_AFK_ELEMENT_PCP, 310 key->vlan_priority, 311 mask->vlan_priority); 312 } 313 314 if (addr_type == FLOW_DISSECTOR_KEY_IPV4_ADDRS) 315 mlxsw_sp_flower_parse_ipv4(rulei, f); 316 317 if (addr_type == FLOW_DISSECTOR_KEY_IPV6_ADDRS) 318 mlxsw_sp_flower_parse_ipv6(rulei, f); 319 320 err = mlxsw_sp_flower_parse_ports(mlxsw_sp, rulei, f, ip_proto); 321 if (err) 322 return err; 323 err = mlxsw_sp_flower_parse_tcp(mlxsw_sp, rulei, f, ip_proto); 324 if (err) 325 return err; 326 327 return mlxsw_sp_flower_parse_actions(mlxsw_sp, dev, rulei, f->exts); 328 } 329 330 int mlxsw_sp_flower_replace(struct mlxsw_sp_port *mlxsw_sp_port, bool ingress, 331 __be16 protocol, struct tc_cls_flower_offload *f) 332 { 333 struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; 334 struct net_device *dev = mlxsw_sp_port->dev; 335 struct mlxsw_sp_acl_rule_info *rulei; 336 struct mlxsw_sp_acl_ruleset *ruleset; 337 struct mlxsw_sp_acl_rule *rule; 338 int err; 339 340 ruleset = mlxsw_sp_acl_ruleset_get(mlxsw_sp, dev, ingress, 341 MLXSW_SP_ACL_PROFILE_FLOWER); 342 if (IS_ERR(ruleset)) 343 return PTR_ERR(ruleset); 344 345 rule = mlxsw_sp_acl_rule_create(mlxsw_sp, ruleset, f->cookie); 346 if (IS_ERR(rule)) { 347 err = PTR_ERR(rule); 348 goto err_rule_create; 349 } 350 351 rulei = mlxsw_sp_acl_rule_rulei(rule); 352 err = mlxsw_sp_flower_parse(mlxsw_sp, dev, rulei, f); 353 if (err) 354 goto err_flower_parse; 355 356 err = mlxsw_sp_acl_rulei_commit(rulei); 357 if (err) 358 goto err_rulei_commit; 359 360 err = mlxsw_sp_acl_rule_add(mlxsw_sp, rule); 361 if (err) 362 goto err_rule_add; 363 364 mlxsw_sp_acl_ruleset_put(mlxsw_sp, ruleset); 365 return 0; 366 367 err_rule_add: 368 err_rulei_commit: 369 err_flower_parse: 370 mlxsw_sp_acl_rule_destroy(mlxsw_sp, rule); 371 err_rule_create: 372 mlxsw_sp_acl_ruleset_put(mlxsw_sp, ruleset); 373 return err; 374 } 375 376 void mlxsw_sp_flower_destroy(struct mlxsw_sp_port *mlxsw_sp_port, bool ingress, 377 struct tc_cls_flower_offload *f) 378 { 379 struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; 380 struct mlxsw_sp_acl_ruleset *ruleset; 381 struct mlxsw_sp_acl_rule *rule; 382 383 ruleset = mlxsw_sp_acl_ruleset_get(mlxsw_sp, mlxsw_sp_port->dev, 384 ingress, 385 MLXSW_SP_ACL_PROFILE_FLOWER); 386 if (IS_ERR(ruleset)) 387 return; 388 389 rule = mlxsw_sp_acl_rule_lookup(mlxsw_sp, ruleset, f->cookie); 390 if (rule) { 391 mlxsw_sp_acl_rule_del(mlxsw_sp, rule); 392 mlxsw_sp_acl_rule_destroy(mlxsw_sp, rule); 393 } 394 395 mlxsw_sp_acl_ruleset_put(mlxsw_sp, ruleset); 396 } 397 398 int mlxsw_sp_flower_stats(struct mlxsw_sp_port *mlxsw_sp_port, bool ingress, 399 struct tc_cls_flower_offload *f) 400 { 401 struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; 402 struct mlxsw_sp_acl_ruleset *ruleset; 403 struct mlxsw_sp_acl_rule *rule; 404 u64 packets; 405 u64 lastuse; 406 u64 bytes; 407 int err; 408 409 ruleset = mlxsw_sp_acl_ruleset_get(mlxsw_sp, mlxsw_sp_port->dev, 410 ingress, 411 MLXSW_SP_ACL_PROFILE_FLOWER); 412 if (WARN_ON(IS_ERR(ruleset))) 413 return -EINVAL; 414 415 rule = mlxsw_sp_acl_rule_lookup(mlxsw_sp, ruleset, f->cookie); 416 if (!rule) 417 return -EINVAL; 418 419 err = mlxsw_sp_acl_rule_get_stats(mlxsw_sp, rule, &packets, &bytes, 420 &lastuse); 421 if (err) 422 goto err_rule_get_stats; 423 424 tcf_exts_stats_update(f->exts, bytes, packets, lastuse); 425 426 mlxsw_sp_acl_ruleset_put(mlxsw_sp, ruleset); 427 return 0; 428 429 err_rule_get_stats: 430 mlxsw_sp_acl_ruleset_put(mlxsw_sp, ruleset); 431 return err; 432 } 433