| .. | .. |
|---|
| 4 | 4 | #include <linux/kernel.h> |
|---|
| 5 | 5 | #include <linux/errno.h> |
|---|
| 6 | 6 | #include <linux/netdevice.h> |
|---|
| 7 | +#include <linux/log2.h> |
|---|
| 7 | 8 | #include <net/net_namespace.h> |
|---|
| 8 | 9 | #include <net/flow_dissector.h> |
|---|
| 9 | 10 | #include <net/pkt_cls.h> |
|---|
| .. | .. |
|---|
| 15 | 16 | #include "core_acl_flex_keys.h" |
|---|
| 16 | 17 | |
|---|
| 17 | 18 | static int mlxsw_sp_flower_parse_actions(struct mlxsw_sp *mlxsw_sp, |
|---|
| 18 | | - struct mlxsw_sp_acl_block *block, |
|---|
| 19 | + struct mlxsw_sp_flow_block *block, |
|---|
| 19 | 20 | struct mlxsw_sp_acl_rule_info *rulei, |
|---|
| 20 | | - struct tcf_exts *exts, |
|---|
| 21 | + struct flow_action *flow_action, |
|---|
| 21 | 22 | struct netlink_ext_ack *extack) |
|---|
| 22 | 23 | { |
|---|
| 23 | | - const struct tc_action *a; |
|---|
| 24 | + const struct flow_action_entry *act; |
|---|
| 25 | + int mirror_act_count = 0; |
|---|
| 26 | + int police_act_count = 0; |
|---|
| 24 | 27 | int err, i; |
|---|
| 25 | 28 | |
|---|
| 26 | | - if (!tcf_exts_has_actions(exts)) |
|---|
| 29 | + if (!flow_action_has_entries(flow_action)) |
|---|
| 27 | 30 | return 0; |
|---|
| 31 | + if (!flow_action_mixed_hw_stats_check(flow_action, extack)) |
|---|
| 32 | + return -EOPNOTSUPP; |
|---|
| 28 | 33 | |
|---|
| 29 | | - /* Count action is inserted first */ |
|---|
| 30 | | - err = mlxsw_sp_acl_rulei_act_count(mlxsw_sp, rulei, extack); |
|---|
| 31 | | - if (err) |
|---|
| 32 | | - return err; |
|---|
| 34 | + act = flow_action_first_entry_get(flow_action); |
|---|
| 35 | + if (act->hw_stats & FLOW_ACTION_HW_STATS_DISABLED) { |
|---|
| 36 | + /* Nothing to do */ |
|---|
| 37 | + } else if (act->hw_stats & FLOW_ACTION_HW_STATS_IMMEDIATE) { |
|---|
| 38 | + /* Count action is inserted first */ |
|---|
| 39 | + err = mlxsw_sp_acl_rulei_act_count(mlxsw_sp, rulei, extack); |
|---|
| 40 | + if (err) |
|---|
| 41 | + return err; |
|---|
| 42 | + } else { |
|---|
| 43 | + NL_SET_ERR_MSG_MOD(extack, "Unsupported action HW stats type"); |
|---|
| 44 | + return -EOPNOTSUPP; |
|---|
| 45 | + } |
|---|
| 33 | 46 | |
|---|
| 34 | | - tcf_exts_for_each_action(i, a, exts) { |
|---|
| 35 | | - if (is_tcf_gact_ok(a)) { |
|---|
| 47 | + flow_action_for_each(i, act, flow_action) { |
|---|
| 48 | + switch (act->id) { |
|---|
| 49 | + case FLOW_ACTION_ACCEPT: |
|---|
| 36 | 50 | err = mlxsw_sp_acl_rulei_act_terminate(rulei); |
|---|
| 37 | 51 | if (err) { |
|---|
| 38 | 52 | NL_SET_ERR_MSG_MOD(extack, "Cannot append terminate action"); |
|---|
| 39 | 53 | return err; |
|---|
| 40 | 54 | } |
|---|
| 41 | | - } else if (is_tcf_gact_shot(a)) { |
|---|
| 42 | | - err = mlxsw_sp_acl_rulei_act_drop(rulei); |
|---|
| 55 | + break; |
|---|
| 56 | + case FLOW_ACTION_DROP: { |
|---|
| 57 | + bool ingress; |
|---|
| 58 | + |
|---|
| 59 | + if (mlxsw_sp_flow_block_is_mixed_bound(block)) { |
|---|
| 60 | + NL_SET_ERR_MSG_MOD(extack, "Drop action is not supported when block is bound to ingress and egress"); |
|---|
| 61 | + return -EOPNOTSUPP; |
|---|
| 62 | + } |
|---|
| 63 | + ingress = mlxsw_sp_flow_block_is_ingress_bound(block); |
|---|
| 64 | + err = mlxsw_sp_acl_rulei_act_drop(rulei, ingress, |
|---|
| 65 | + act->cookie, extack); |
|---|
| 43 | 66 | if (err) { |
|---|
| 44 | 67 | NL_SET_ERR_MSG_MOD(extack, "Cannot append drop action"); |
|---|
| 45 | 68 | return err; |
|---|
| 46 | 69 | } |
|---|
| 47 | | - } else if (is_tcf_gact_trap(a)) { |
|---|
| 70 | + |
|---|
| 71 | + /* Forbid block with this rulei to be bound |
|---|
| 72 | + * to ingress/egress in future. Ingress rule is |
|---|
| 73 | + * a blocker for egress and vice versa. |
|---|
| 74 | + */ |
|---|
| 75 | + if (ingress) |
|---|
| 76 | + rulei->egress_bind_blocker = 1; |
|---|
| 77 | + else |
|---|
| 78 | + rulei->ingress_bind_blocker = 1; |
|---|
| 79 | + } |
|---|
| 80 | + break; |
|---|
| 81 | + case FLOW_ACTION_TRAP: |
|---|
| 48 | 82 | err = mlxsw_sp_acl_rulei_act_trap(rulei); |
|---|
| 49 | 83 | if (err) { |
|---|
| 50 | 84 | NL_SET_ERR_MSG_MOD(extack, "Cannot append trap action"); |
|---|
| 51 | 85 | return err; |
|---|
| 52 | 86 | } |
|---|
| 53 | | - } else if (is_tcf_gact_goto_chain(a)) { |
|---|
| 54 | | - u32 chain_index = tcf_gact_goto_chain_index(a); |
|---|
| 87 | + break; |
|---|
| 88 | + case FLOW_ACTION_GOTO: { |
|---|
| 89 | + u32 chain_index = act->chain_index; |
|---|
| 55 | 90 | struct mlxsw_sp_acl_ruleset *ruleset; |
|---|
| 56 | 91 | u16 group_id; |
|---|
| 57 | 92 | |
|---|
| .. | .. |
|---|
| 67 | 102 | NL_SET_ERR_MSG_MOD(extack, "Cannot append jump action"); |
|---|
| 68 | 103 | return err; |
|---|
| 69 | 104 | } |
|---|
| 70 | | - } else if (is_tcf_mirred_egress_redirect(a)) { |
|---|
| 105 | + } |
|---|
| 106 | + break; |
|---|
| 107 | + case FLOW_ACTION_REDIRECT: { |
|---|
| 71 | 108 | struct net_device *out_dev; |
|---|
| 72 | 109 | struct mlxsw_sp_fid *fid; |
|---|
| 73 | 110 | u16 fid_index; |
|---|
| 111 | + |
|---|
| 112 | + if (mlxsw_sp_flow_block_is_egress_bound(block)) { |
|---|
| 113 | + NL_SET_ERR_MSG_MOD(extack, "Redirect action is not supported on egress"); |
|---|
| 114 | + return -EOPNOTSUPP; |
|---|
| 115 | + } |
|---|
| 116 | + |
|---|
| 117 | + /* Forbid block with this rulei to be bound |
|---|
| 118 | + * to egress in future. |
|---|
| 119 | + */ |
|---|
| 120 | + rulei->egress_bind_blocker = 1; |
|---|
| 74 | 121 | |
|---|
| 75 | 122 | fid = mlxsw_sp_acl_dummy_fid(mlxsw_sp); |
|---|
| 76 | 123 | fid_index = mlxsw_sp_fid_index(fid); |
|---|
| .. | .. |
|---|
| 79 | 126 | if (err) |
|---|
| 80 | 127 | return err; |
|---|
| 81 | 128 | |
|---|
| 82 | | - out_dev = tcf_mirred_dev(a); |
|---|
| 129 | + out_dev = act->dev; |
|---|
| 83 | 130 | err = mlxsw_sp_acl_rulei_act_fwd(mlxsw_sp, rulei, |
|---|
| 84 | 131 | out_dev, extack); |
|---|
| 85 | 132 | if (err) |
|---|
| 86 | 133 | return err; |
|---|
| 87 | | - } else if (is_tcf_mirred_egress_mirror(a)) { |
|---|
| 88 | | - struct net_device *out_dev = tcf_mirred_dev(a); |
|---|
| 134 | + } |
|---|
| 135 | + break; |
|---|
| 136 | + case FLOW_ACTION_MIRRED: { |
|---|
| 137 | + struct net_device *out_dev = act->dev; |
|---|
| 138 | + |
|---|
| 139 | + if (mirror_act_count++) { |
|---|
| 140 | + NL_SET_ERR_MSG_MOD(extack, "Multiple mirror actions per rule are not supported"); |
|---|
| 141 | + return -EOPNOTSUPP; |
|---|
| 142 | + } |
|---|
| 89 | 143 | |
|---|
| 90 | 144 | err = mlxsw_sp_acl_rulei_act_mirror(mlxsw_sp, rulei, |
|---|
| 91 | 145 | block, out_dev, |
|---|
| 92 | 146 | extack); |
|---|
| 93 | 147 | if (err) |
|---|
| 94 | 148 | 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); |
|---|
| 149 | + } |
|---|
| 150 | + break; |
|---|
| 151 | + case FLOW_ACTION_VLAN_MANGLE: { |
|---|
| 152 | + u16 proto = be16_to_cpu(act->vlan.proto); |
|---|
| 153 | + u8 prio = act->vlan.prio; |
|---|
| 154 | + u16 vid = act->vlan.vid; |
|---|
| 100 | 155 | |
|---|
| 101 | 156 | err = mlxsw_sp_acl_rulei_act_vlan(mlxsw_sp, rulei, |
|---|
| 102 | | - action, vid, |
|---|
| 157 | + act->id, vid, |
|---|
| 103 | 158 | proto, prio, extack); |
|---|
| 104 | 159 | if (err) |
|---|
| 105 | 160 | return err; |
|---|
| 106 | | - } else { |
|---|
| 161 | + break; |
|---|
| 162 | + } |
|---|
| 163 | + case FLOW_ACTION_PRIORITY: |
|---|
| 164 | + err = mlxsw_sp_acl_rulei_act_priority(mlxsw_sp, rulei, |
|---|
| 165 | + act->priority, |
|---|
| 166 | + extack); |
|---|
| 167 | + if (err) |
|---|
| 168 | + return err; |
|---|
| 169 | + break; |
|---|
| 170 | + case FLOW_ACTION_MANGLE: { |
|---|
| 171 | + enum flow_action_mangle_base htype = act->mangle.htype; |
|---|
| 172 | + __be32 be_mask = (__force __be32) act->mangle.mask; |
|---|
| 173 | + __be32 be_val = (__force __be32) act->mangle.val; |
|---|
| 174 | + u32 offset = act->mangle.offset; |
|---|
| 175 | + u32 mask = be32_to_cpu(be_mask); |
|---|
| 176 | + u32 val = be32_to_cpu(be_val); |
|---|
| 177 | + |
|---|
| 178 | + err = mlxsw_sp_acl_rulei_act_mangle(mlxsw_sp, rulei, |
|---|
| 179 | + htype, offset, |
|---|
| 180 | + mask, val, extack); |
|---|
| 181 | + if (err) |
|---|
| 182 | + return err; |
|---|
| 183 | + break; |
|---|
| 184 | + } |
|---|
| 185 | + case FLOW_ACTION_POLICE: { |
|---|
| 186 | + u32 burst; |
|---|
| 187 | + |
|---|
| 188 | + if (police_act_count++) { |
|---|
| 189 | + NL_SET_ERR_MSG_MOD(extack, "Multiple police actions per rule are not supported"); |
|---|
| 190 | + return -EOPNOTSUPP; |
|---|
| 191 | + } |
|---|
| 192 | + |
|---|
| 193 | + /* The kernel might adjust the requested burst size so |
|---|
| 194 | + * that it is not exactly a power of two. Re-adjust it |
|---|
| 195 | + * here since the hardware only supports burst sizes |
|---|
| 196 | + * that are a power of two. |
|---|
| 197 | + */ |
|---|
| 198 | + burst = roundup_pow_of_two(act->police.burst); |
|---|
| 199 | + err = mlxsw_sp_acl_rulei_act_police(mlxsw_sp, rulei, |
|---|
| 200 | + act->police.index, |
|---|
| 201 | + act->police.rate_bytes_ps, |
|---|
| 202 | + burst, extack); |
|---|
| 203 | + if (err) |
|---|
| 204 | + return err; |
|---|
| 205 | + break; |
|---|
| 206 | + } |
|---|
| 207 | + default: |
|---|
| 107 | 208 | NL_SET_ERR_MSG_MOD(extack, "Unsupported action"); |
|---|
| 108 | 209 | dev_err(mlxsw_sp->bus_info->dev, "Unsupported action\n"); |
|---|
| 109 | 210 | return -EOPNOTSUPP; |
|---|
| .. | .. |
|---|
| 112 | 213 | return 0; |
|---|
| 113 | 214 | } |
|---|
| 114 | 215 | |
|---|
| 115 | | -static void mlxsw_sp_flower_parse_ipv4(struct mlxsw_sp_acl_rule_info *rulei, |
|---|
| 116 | | - struct tc_cls_flower_offload *f) |
|---|
| 216 | +static int mlxsw_sp_flower_parse_meta(struct mlxsw_sp_acl_rule_info *rulei, |
|---|
| 217 | + struct flow_cls_offload *f, |
|---|
| 218 | + struct mlxsw_sp_flow_block *block) |
|---|
| 117 | 219 | { |
|---|
| 118 | | - struct flow_dissector_key_ipv4_addrs *key = |
|---|
| 119 | | - skb_flow_dissector_target(f->dissector, |
|---|
| 120 | | - FLOW_DISSECTOR_KEY_IPV4_ADDRS, |
|---|
| 121 | | - f->key); |
|---|
| 122 | | - struct flow_dissector_key_ipv4_addrs *mask = |
|---|
| 123 | | - skb_flow_dissector_target(f->dissector, |
|---|
| 124 | | - FLOW_DISSECTOR_KEY_IPV4_ADDRS, |
|---|
| 125 | | - f->mask); |
|---|
| 220 | + struct flow_rule *rule = flow_cls_offload_flow_rule(f); |
|---|
| 221 | + struct mlxsw_sp_port *mlxsw_sp_port; |
|---|
| 222 | + struct net_device *ingress_dev; |
|---|
| 223 | + struct flow_match_meta match; |
|---|
| 224 | + |
|---|
| 225 | + if (!flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_META)) |
|---|
| 226 | + return 0; |
|---|
| 227 | + |
|---|
| 228 | + flow_rule_match_meta(rule, &match); |
|---|
| 229 | + if (match.mask->ingress_ifindex != 0xFFFFFFFF) { |
|---|
| 230 | + NL_SET_ERR_MSG_MOD(f->common.extack, "Unsupported ingress ifindex mask"); |
|---|
| 231 | + return -EINVAL; |
|---|
| 232 | + } |
|---|
| 233 | + |
|---|
| 234 | + ingress_dev = __dev_get_by_index(block->net, |
|---|
| 235 | + match.key->ingress_ifindex); |
|---|
| 236 | + if (!ingress_dev) { |
|---|
| 237 | + NL_SET_ERR_MSG_MOD(f->common.extack, "Can't find specified ingress port to match on"); |
|---|
| 238 | + return -EINVAL; |
|---|
| 239 | + } |
|---|
| 240 | + |
|---|
| 241 | + if (!mlxsw_sp_port_dev_check(ingress_dev)) { |
|---|
| 242 | + NL_SET_ERR_MSG_MOD(f->common.extack, "Can't match on non-mlxsw ingress port"); |
|---|
| 243 | + return -EINVAL; |
|---|
| 244 | + } |
|---|
| 245 | + |
|---|
| 246 | + mlxsw_sp_port = netdev_priv(ingress_dev); |
|---|
| 247 | + if (mlxsw_sp_port->mlxsw_sp != block->mlxsw_sp) { |
|---|
| 248 | + NL_SET_ERR_MSG_MOD(f->common.extack, "Can't match on a port from different device"); |
|---|
| 249 | + return -EINVAL; |
|---|
| 250 | + } |
|---|
| 251 | + |
|---|
| 252 | + mlxsw_sp_acl_rulei_keymask_u32(rulei, |
|---|
| 253 | + MLXSW_AFK_ELEMENT_SRC_SYS_PORT, |
|---|
| 254 | + mlxsw_sp_port->local_port, |
|---|
| 255 | + 0xFFFFFFFF); |
|---|
| 256 | + return 0; |
|---|
| 257 | +} |
|---|
| 258 | + |
|---|
| 259 | +static void mlxsw_sp_flower_parse_ipv4(struct mlxsw_sp_acl_rule_info *rulei, |
|---|
| 260 | + struct flow_cls_offload *f) |
|---|
| 261 | +{ |
|---|
| 262 | + struct flow_match_ipv4_addrs match; |
|---|
| 263 | + |
|---|
| 264 | + flow_rule_match_ipv4_addrs(f->rule, &match); |
|---|
| 126 | 265 | |
|---|
| 127 | 266 | mlxsw_sp_acl_rulei_keymask_buf(rulei, MLXSW_AFK_ELEMENT_SRC_IP_0_31, |
|---|
| 128 | | - (char *) &key->src, |
|---|
| 129 | | - (char *) &mask->src, 4); |
|---|
| 267 | + (char *) &match.key->src, |
|---|
| 268 | + (char *) &match.mask->src, 4); |
|---|
| 130 | 269 | mlxsw_sp_acl_rulei_keymask_buf(rulei, MLXSW_AFK_ELEMENT_DST_IP_0_31, |
|---|
| 131 | | - (char *) &key->dst, |
|---|
| 132 | | - (char *) &mask->dst, 4); |
|---|
| 270 | + (char *) &match.key->dst, |
|---|
| 271 | + (char *) &match.mask->dst, 4); |
|---|
| 133 | 272 | } |
|---|
| 134 | 273 | |
|---|
| 135 | 274 | static void mlxsw_sp_flower_parse_ipv6(struct mlxsw_sp_acl_rule_info *rulei, |
|---|
| 136 | | - struct tc_cls_flower_offload *f) |
|---|
| 275 | + struct flow_cls_offload *f) |
|---|
| 137 | 276 | { |
|---|
| 138 | | - struct flow_dissector_key_ipv6_addrs *key = |
|---|
| 139 | | - skb_flow_dissector_target(f->dissector, |
|---|
| 140 | | - FLOW_DISSECTOR_KEY_IPV6_ADDRS, |
|---|
| 141 | | - f->key); |
|---|
| 142 | | - struct flow_dissector_key_ipv6_addrs *mask = |
|---|
| 143 | | - skb_flow_dissector_target(f->dissector, |
|---|
| 144 | | - FLOW_DISSECTOR_KEY_IPV6_ADDRS, |
|---|
| 145 | | - f->mask); |
|---|
| 277 | + struct flow_match_ipv6_addrs match; |
|---|
| 278 | + |
|---|
| 279 | + flow_rule_match_ipv6_addrs(f->rule, &match); |
|---|
| 146 | 280 | |
|---|
| 147 | 281 | mlxsw_sp_acl_rulei_keymask_buf(rulei, MLXSW_AFK_ELEMENT_SRC_IP_96_127, |
|---|
| 148 | | - &key->src.s6_addr[0x0], |
|---|
| 149 | | - &mask->src.s6_addr[0x0], 4); |
|---|
| 282 | + &match.key->src.s6_addr[0x0], |
|---|
| 283 | + &match.mask->src.s6_addr[0x0], 4); |
|---|
| 150 | 284 | mlxsw_sp_acl_rulei_keymask_buf(rulei, MLXSW_AFK_ELEMENT_SRC_IP_64_95, |
|---|
| 151 | | - &key->src.s6_addr[0x4], |
|---|
| 152 | | - &mask->src.s6_addr[0x4], 4); |
|---|
| 285 | + &match.key->src.s6_addr[0x4], |
|---|
| 286 | + &match.mask->src.s6_addr[0x4], 4); |
|---|
| 153 | 287 | mlxsw_sp_acl_rulei_keymask_buf(rulei, MLXSW_AFK_ELEMENT_SRC_IP_32_63, |
|---|
| 154 | | - &key->src.s6_addr[0x8], |
|---|
| 155 | | - &mask->src.s6_addr[0x8], 4); |
|---|
| 288 | + &match.key->src.s6_addr[0x8], |
|---|
| 289 | + &match.mask->src.s6_addr[0x8], 4); |
|---|
| 156 | 290 | mlxsw_sp_acl_rulei_keymask_buf(rulei, MLXSW_AFK_ELEMENT_SRC_IP_0_31, |
|---|
| 157 | | - &key->src.s6_addr[0xC], |
|---|
| 158 | | - &mask->src.s6_addr[0xC], 4); |
|---|
| 291 | + &match.key->src.s6_addr[0xC], |
|---|
| 292 | + &match.mask->src.s6_addr[0xC], 4); |
|---|
| 159 | 293 | mlxsw_sp_acl_rulei_keymask_buf(rulei, MLXSW_AFK_ELEMENT_DST_IP_96_127, |
|---|
| 160 | | - &key->dst.s6_addr[0x0], |
|---|
| 161 | | - &mask->dst.s6_addr[0x0], 4); |
|---|
| 294 | + &match.key->dst.s6_addr[0x0], |
|---|
| 295 | + &match.mask->dst.s6_addr[0x0], 4); |
|---|
| 162 | 296 | mlxsw_sp_acl_rulei_keymask_buf(rulei, MLXSW_AFK_ELEMENT_DST_IP_64_95, |
|---|
| 163 | | - &key->dst.s6_addr[0x4], |
|---|
| 164 | | - &mask->dst.s6_addr[0x4], 4); |
|---|
| 297 | + &match.key->dst.s6_addr[0x4], |
|---|
| 298 | + &match.mask->dst.s6_addr[0x4], 4); |
|---|
| 165 | 299 | mlxsw_sp_acl_rulei_keymask_buf(rulei, MLXSW_AFK_ELEMENT_DST_IP_32_63, |
|---|
| 166 | | - &key->dst.s6_addr[0x8], |
|---|
| 167 | | - &mask->dst.s6_addr[0x8], 4); |
|---|
| 300 | + &match.key->dst.s6_addr[0x8], |
|---|
| 301 | + &match.mask->dst.s6_addr[0x8], 4); |
|---|
| 168 | 302 | mlxsw_sp_acl_rulei_keymask_buf(rulei, MLXSW_AFK_ELEMENT_DST_IP_0_31, |
|---|
| 169 | | - &key->dst.s6_addr[0xC], |
|---|
| 170 | | - &mask->dst.s6_addr[0xC], 4); |
|---|
| 303 | + &match.key->dst.s6_addr[0xC], |
|---|
| 304 | + &match.mask->dst.s6_addr[0xC], 4); |
|---|
| 171 | 305 | } |
|---|
| 172 | 306 | |
|---|
| 173 | 307 | static int mlxsw_sp_flower_parse_ports(struct mlxsw_sp *mlxsw_sp, |
|---|
| 174 | 308 | struct mlxsw_sp_acl_rule_info *rulei, |
|---|
| 175 | | - struct tc_cls_flower_offload *f, |
|---|
| 309 | + struct flow_cls_offload *f, |
|---|
| 176 | 310 | u8 ip_proto) |
|---|
| 177 | 311 | { |
|---|
| 178 | | - struct flow_dissector_key_ports *key, *mask; |
|---|
| 312 | + const struct flow_rule *rule = flow_cls_offload_flow_rule(f); |
|---|
| 313 | + struct flow_match_ports match; |
|---|
| 179 | 314 | |
|---|
| 180 | | - if (!dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_PORTS)) |
|---|
| 315 | + if (!flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_PORTS)) |
|---|
| 181 | 316 | return 0; |
|---|
| 182 | 317 | |
|---|
| 183 | 318 | if (ip_proto != IPPROTO_TCP && ip_proto != IPPROTO_UDP) { |
|---|
| .. | .. |
|---|
| 186 | 321 | return -EINVAL; |
|---|
| 187 | 322 | } |
|---|
| 188 | 323 | |
|---|
| 189 | | - key = skb_flow_dissector_target(f->dissector, |
|---|
| 190 | | - FLOW_DISSECTOR_KEY_PORTS, |
|---|
| 191 | | - f->key); |
|---|
| 192 | | - mask = skb_flow_dissector_target(f->dissector, |
|---|
| 193 | | - FLOW_DISSECTOR_KEY_PORTS, |
|---|
| 194 | | - f->mask); |
|---|
| 324 | + flow_rule_match_ports(rule, &match); |
|---|
| 195 | 325 | mlxsw_sp_acl_rulei_keymask_u32(rulei, MLXSW_AFK_ELEMENT_DST_L4_PORT, |
|---|
| 196 | | - ntohs(key->dst), ntohs(mask->dst)); |
|---|
| 326 | + ntohs(match.key->dst), |
|---|
| 327 | + ntohs(match.mask->dst)); |
|---|
| 197 | 328 | mlxsw_sp_acl_rulei_keymask_u32(rulei, MLXSW_AFK_ELEMENT_SRC_L4_PORT, |
|---|
| 198 | | - ntohs(key->src), ntohs(mask->src)); |
|---|
| 329 | + ntohs(match.key->src), |
|---|
| 330 | + ntohs(match.mask->src)); |
|---|
| 199 | 331 | return 0; |
|---|
| 200 | 332 | } |
|---|
| 201 | 333 | |
|---|
| 202 | 334 | static int mlxsw_sp_flower_parse_tcp(struct mlxsw_sp *mlxsw_sp, |
|---|
| 203 | 335 | struct mlxsw_sp_acl_rule_info *rulei, |
|---|
| 204 | | - struct tc_cls_flower_offload *f, |
|---|
| 336 | + struct flow_cls_offload *f, |
|---|
| 205 | 337 | u8 ip_proto) |
|---|
| 206 | 338 | { |
|---|
| 207 | | - struct flow_dissector_key_tcp *key, *mask; |
|---|
| 339 | + const struct flow_rule *rule = flow_cls_offload_flow_rule(f); |
|---|
| 340 | + struct flow_match_tcp match; |
|---|
| 208 | 341 | |
|---|
| 209 | | - if (!dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_TCP)) |
|---|
| 342 | + if (!flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_TCP)) |
|---|
| 210 | 343 | return 0; |
|---|
| 211 | 344 | |
|---|
| 212 | 345 | if (ip_proto != IPPROTO_TCP) { |
|---|
| .. | .. |
|---|
| 215 | 348 | return -EINVAL; |
|---|
| 216 | 349 | } |
|---|
| 217 | 350 | |
|---|
| 218 | | - key = skb_flow_dissector_target(f->dissector, |
|---|
| 219 | | - FLOW_DISSECTOR_KEY_TCP, |
|---|
| 220 | | - f->key); |
|---|
| 221 | | - mask = skb_flow_dissector_target(f->dissector, |
|---|
| 222 | | - FLOW_DISSECTOR_KEY_TCP, |
|---|
| 223 | | - f->mask); |
|---|
| 351 | + flow_rule_match_tcp(rule, &match); |
|---|
| 352 | + |
|---|
| 353 | + if (match.mask->flags & htons(0x0E00)) { |
|---|
| 354 | + NL_SET_ERR_MSG_MOD(f->common.extack, "TCP flags match not supported on reserved bits"); |
|---|
| 355 | + dev_err(mlxsw_sp->bus_info->dev, "TCP flags match not supported on reserved bits\n"); |
|---|
| 356 | + return -EINVAL; |
|---|
| 357 | + } |
|---|
| 358 | + |
|---|
| 224 | 359 | mlxsw_sp_acl_rulei_keymask_u32(rulei, MLXSW_AFK_ELEMENT_TCP_FLAGS, |
|---|
| 225 | | - ntohs(key->flags), ntohs(mask->flags)); |
|---|
| 360 | + ntohs(match.key->flags), |
|---|
| 361 | + ntohs(match.mask->flags)); |
|---|
| 226 | 362 | return 0; |
|---|
| 227 | 363 | } |
|---|
| 228 | 364 | |
|---|
| 229 | 365 | static int mlxsw_sp_flower_parse_ip(struct mlxsw_sp *mlxsw_sp, |
|---|
| 230 | 366 | struct mlxsw_sp_acl_rule_info *rulei, |
|---|
| 231 | | - struct tc_cls_flower_offload *f, |
|---|
| 367 | + struct flow_cls_offload *f, |
|---|
| 232 | 368 | u16 n_proto) |
|---|
| 233 | 369 | { |
|---|
| 234 | | - struct flow_dissector_key_ip *key, *mask; |
|---|
| 370 | + const struct flow_rule *rule = flow_cls_offload_flow_rule(f); |
|---|
| 371 | + struct flow_match_ip match; |
|---|
| 235 | 372 | |
|---|
| 236 | | - if (!dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_IP)) |
|---|
| 373 | + if (!flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_IP)) |
|---|
| 237 | 374 | return 0; |
|---|
| 238 | 375 | |
|---|
| 239 | 376 | if (n_proto != ETH_P_IP && n_proto != ETH_P_IPV6) { |
|---|
| .. | .. |
|---|
| 242 | 379 | return -EINVAL; |
|---|
| 243 | 380 | } |
|---|
| 244 | 381 | |
|---|
| 245 | | - key = skb_flow_dissector_target(f->dissector, |
|---|
| 246 | | - FLOW_DISSECTOR_KEY_IP, |
|---|
| 247 | | - f->key); |
|---|
| 248 | | - mask = skb_flow_dissector_target(f->dissector, |
|---|
| 249 | | - FLOW_DISSECTOR_KEY_IP, |
|---|
| 250 | | - f->mask); |
|---|
| 382 | + flow_rule_match_ip(rule, &match); |
|---|
| 383 | + |
|---|
| 251 | 384 | mlxsw_sp_acl_rulei_keymask_u32(rulei, MLXSW_AFK_ELEMENT_IP_TTL_, |
|---|
| 252 | | - key->ttl, mask->ttl); |
|---|
| 385 | + match.key->ttl, match.mask->ttl); |
|---|
| 253 | 386 | |
|---|
| 254 | 387 | mlxsw_sp_acl_rulei_keymask_u32(rulei, MLXSW_AFK_ELEMENT_IP_ECN, |
|---|
| 255 | | - key->tos & 0x3, mask->tos & 0x3); |
|---|
| 388 | + match.key->tos & 0x3, |
|---|
| 389 | + match.mask->tos & 0x3); |
|---|
| 256 | 390 | |
|---|
| 257 | 391 | mlxsw_sp_acl_rulei_keymask_u32(rulei, MLXSW_AFK_ELEMENT_IP_DSCP, |
|---|
| 258 | | - key->tos >> 6, mask->tos >> 6); |
|---|
| 392 | + match.key->tos >> 2, |
|---|
| 393 | + match.mask->tos >> 2); |
|---|
| 259 | 394 | |
|---|
| 260 | 395 | return 0; |
|---|
| 261 | 396 | } |
|---|
| 262 | 397 | |
|---|
| 263 | 398 | static int mlxsw_sp_flower_parse(struct mlxsw_sp *mlxsw_sp, |
|---|
| 264 | | - struct mlxsw_sp_acl_block *block, |
|---|
| 399 | + struct mlxsw_sp_flow_block *block, |
|---|
| 265 | 400 | struct mlxsw_sp_acl_rule_info *rulei, |
|---|
| 266 | | - struct tc_cls_flower_offload *f) |
|---|
| 401 | + struct flow_cls_offload *f) |
|---|
| 267 | 402 | { |
|---|
| 403 | + struct flow_rule *rule = flow_cls_offload_flow_rule(f); |
|---|
| 404 | + struct flow_dissector *dissector = rule->match.dissector; |
|---|
| 268 | 405 | u16 n_proto_mask = 0; |
|---|
| 269 | 406 | u16 n_proto_key = 0; |
|---|
| 270 | 407 | u16 addr_type = 0; |
|---|
| 271 | 408 | u8 ip_proto = 0; |
|---|
| 272 | 409 | int err; |
|---|
| 273 | 410 | |
|---|
| 274 | | - if (f->dissector->used_keys & |
|---|
| 275 | | - ~(BIT(FLOW_DISSECTOR_KEY_CONTROL) | |
|---|
| 411 | + if (dissector->used_keys & |
|---|
| 412 | + ~(BIT(FLOW_DISSECTOR_KEY_META) | |
|---|
| 413 | + BIT(FLOW_DISSECTOR_KEY_CONTROL) | |
|---|
| 276 | 414 | BIT(FLOW_DISSECTOR_KEY_BASIC) | |
|---|
| 277 | 415 | BIT(FLOW_DISSECTOR_KEY_ETH_ADDRS) | |
|---|
| 278 | 416 | BIT(FLOW_DISSECTOR_KEY_IPV4_ADDRS) | |
|---|
| .. | .. |
|---|
| 288 | 426 | |
|---|
| 289 | 427 | mlxsw_sp_acl_rulei_priority(rulei, f->common.prio); |
|---|
| 290 | 428 | |
|---|
| 291 | | - if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_CONTROL)) { |
|---|
| 292 | | - struct flow_dissector_key_control *key = |
|---|
| 293 | | - skb_flow_dissector_target(f->dissector, |
|---|
| 294 | | - FLOW_DISSECTOR_KEY_CONTROL, |
|---|
| 295 | | - f->key); |
|---|
| 296 | | - addr_type = key->addr_type; |
|---|
| 429 | + err = mlxsw_sp_flower_parse_meta(rulei, f, block); |
|---|
| 430 | + if (err) |
|---|
| 431 | + return err; |
|---|
| 432 | + |
|---|
| 433 | + if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_CONTROL)) { |
|---|
| 434 | + struct flow_match_control match; |
|---|
| 435 | + |
|---|
| 436 | + flow_rule_match_control(rule, &match); |
|---|
| 437 | + addr_type = match.key->addr_type; |
|---|
| 297 | 438 | } |
|---|
| 298 | 439 | |
|---|
| 299 | | - if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_BASIC)) { |
|---|
| 300 | | - struct flow_dissector_key_basic *key = |
|---|
| 301 | | - skb_flow_dissector_target(f->dissector, |
|---|
| 302 | | - FLOW_DISSECTOR_KEY_BASIC, |
|---|
| 303 | | - f->key); |
|---|
| 304 | | - struct flow_dissector_key_basic *mask = |
|---|
| 305 | | - skb_flow_dissector_target(f->dissector, |
|---|
| 306 | | - FLOW_DISSECTOR_KEY_BASIC, |
|---|
| 307 | | - f->mask); |
|---|
| 308 | | - n_proto_key = ntohs(key->n_proto); |
|---|
| 309 | | - n_proto_mask = ntohs(mask->n_proto); |
|---|
| 440 | + if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_BASIC)) { |
|---|
| 441 | + struct flow_match_basic match; |
|---|
| 442 | + |
|---|
| 443 | + flow_rule_match_basic(rule, &match); |
|---|
| 444 | + n_proto_key = ntohs(match.key->n_proto); |
|---|
| 445 | + n_proto_mask = ntohs(match.mask->n_proto); |
|---|
| 310 | 446 | |
|---|
| 311 | 447 | if (n_proto_key == ETH_P_ALL) { |
|---|
| 312 | 448 | n_proto_key = 0; |
|---|
| .. | .. |
|---|
| 316 | 452 | MLXSW_AFK_ELEMENT_ETHERTYPE, |
|---|
| 317 | 453 | n_proto_key, n_proto_mask); |
|---|
| 318 | 454 | |
|---|
| 319 | | - ip_proto = key->ip_proto; |
|---|
| 455 | + ip_proto = match.key->ip_proto; |
|---|
| 320 | 456 | mlxsw_sp_acl_rulei_keymask_u32(rulei, |
|---|
| 321 | 457 | MLXSW_AFK_ELEMENT_IP_PROTO, |
|---|
| 322 | | - key->ip_proto, mask->ip_proto); |
|---|
| 458 | + match.key->ip_proto, |
|---|
| 459 | + match.mask->ip_proto); |
|---|
| 323 | 460 | } |
|---|
| 324 | 461 | |
|---|
| 325 | | - if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_ETH_ADDRS)) { |
|---|
| 326 | | - struct flow_dissector_key_eth_addrs *key = |
|---|
| 327 | | - skb_flow_dissector_target(f->dissector, |
|---|
| 328 | | - FLOW_DISSECTOR_KEY_ETH_ADDRS, |
|---|
| 329 | | - f->key); |
|---|
| 330 | | - struct flow_dissector_key_eth_addrs *mask = |
|---|
| 331 | | - skb_flow_dissector_target(f->dissector, |
|---|
| 332 | | - FLOW_DISSECTOR_KEY_ETH_ADDRS, |
|---|
| 333 | | - f->mask); |
|---|
| 462 | + if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ETH_ADDRS)) { |
|---|
| 463 | + struct flow_match_eth_addrs match; |
|---|
| 334 | 464 | |
|---|
| 465 | + flow_rule_match_eth_addrs(rule, &match); |
|---|
| 335 | 466 | mlxsw_sp_acl_rulei_keymask_buf(rulei, |
|---|
| 336 | 467 | MLXSW_AFK_ELEMENT_DMAC_32_47, |
|---|
| 337 | | - key->dst, mask->dst, 2); |
|---|
| 468 | + match.key->dst, |
|---|
| 469 | + match.mask->dst, 2); |
|---|
| 338 | 470 | mlxsw_sp_acl_rulei_keymask_buf(rulei, |
|---|
| 339 | 471 | MLXSW_AFK_ELEMENT_DMAC_0_31, |
|---|
| 340 | | - key->dst + 2, mask->dst + 2, 4); |
|---|
| 472 | + match.key->dst + 2, |
|---|
| 473 | + match.mask->dst + 2, 4); |
|---|
| 341 | 474 | mlxsw_sp_acl_rulei_keymask_buf(rulei, |
|---|
| 342 | 475 | MLXSW_AFK_ELEMENT_SMAC_32_47, |
|---|
| 343 | | - key->src, mask->src, 2); |
|---|
| 476 | + match.key->src, |
|---|
| 477 | + match.mask->src, 2); |
|---|
| 344 | 478 | mlxsw_sp_acl_rulei_keymask_buf(rulei, |
|---|
| 345 | 479 | MLXSW_AFK_ELEMENT_SMAC_0_31, |
|---|
| 346 | | - key->src + 2, mask->src + 2, 4); |
|---|
| 480 | + match.key->src + 2, |
|---|
| 481 | + match.mask->src + 2, 4); |
|---|
| 347 | 482 | } |
|---|
| 348 | 483 | |
|---|
| 349 | | - if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_VLAN)) { |
|---|
| 350 | | - struct flow_dissector_key_vlan *key = |
|---|
| 351 | | - skb_flow_dissector_target(f->dissector, |
|---|
| 352 | | - FLOW_DISSECTOR_KEY_VLAN, |
|---|
| 353 | | - f->key); |
|---|
| 354 | | - struct flow_dissector_key_vlan *mask = |
|---|
| 355 | | - skb_flow_dissector_target(f->dissector, |
|---|
| 356 | | - FLOW_DISSECTOR_KEY_VLAN, |
|---|
| 357 | | - f->mask); |
|---|
| 484 | + if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_VLAN)) { |
|---|
| 485 | + struct flow_match_vlan match; |
|---|
| 358 | 486 | |
|---|
| 359 | | - if (mlxsw_sp_acl_block_is_egress_bound(block)) { |
|---|
| 487 | + flow_rule_match_vlan(rule, &match); |
|---|
| 488 | + if (mlxsw_sp_flow_block_is_egress_bound(block)) { |
|---|
| 360 | 489 | NL_SET_ERR_MSG_MOD(f->common.extack, "vlan_id key is not supported on egress"); |
|---|
| 361 | 490 | return -EOPNOTSUPP; |
|---|
| 362 | 491 | } |
|---|
| 363 | | - if (mask->vlan_id != 0) |
|---|
| 492 | + |
|---|
| 493 | + /* Forbid block with this rulei to be bound |
|---|
| 494 | + * to egress in future. |
|---|
| 495 | + */ |
|---|
| 496 | + rulei->egress_bind_blocker = 1; |
|---|
| 497 | + |
|---|
| 498 | + if (match.mask->vlan_id != 0) |
|---|
| 364 | 499 | mlxsw_sp_acl_rulei_keymask_u32(rulei, |
|---|
| 365 | 500 | MLXSW_AFK_ELEMENT_VID, |
|---|
| 366 | | - key->vlan_id, |
|---|
| 367 | | - mask->vlan_id); |
|---|
| 368 | | - if (mask->vlan_priority != 0) |
|---|
| 501 | + match.key->vlan_id, |
|---|
| 502 | + match.mask->vlan_id); |
|---|
| 503 | + if (match.mask->vlan_priority != 0) |
|---|
| 369 | 504 | mlxsw_sp_acl_rulei_keymask_u32(rulei, |
|---|
| 370 | 505 | MLXSW_AFK_ELEMENT_PCP, |
|---|
| 371 | | - key->vlan_priority, |
|---|
| 372 | | - mask->vlan_priority); |
|---|
| 506 | + match.key->vlan_priority, |
|---|
| 507 | + match.mask->vlan_priority); |
|---|
| 373 | 508 | } |
|---|
| 374 | 509 | |
|---|
| 375 | 510 | if (addr_type == FLOW_DISSECTOR_KEY_IPV4_ADDRS) |
|---|
| .. | .. |
|---|
| 389 | 524 | if (err) |
|---|
| 390 | 525 | return err; |
|---|
| 391 | 526 | |
|---|
| 392 | | - return mlxsw_sp_flower_parse_actions(mlxsw_sp, block, rulei, f->exts, |
|---|
| 527 | + return mlxsw_sp_flower_parse_actions(mlxsw_sp, block, rulei, |
|---|
| 528 | + &f->rule->action, |
|---|
| 393 | 529 | f->common.extack); |
|---|
| 394 | 530 | } |
|---|
| 395 | 531 | |
|---|
| 532 | +static int mlxsw_sp_flower_mall_prio_check(struct mlxsw_sp_flow_block *block, |
|---|
| 533 | + struct flow_cls_offload *f) |
|---|
| 534 | +{ |
|---|
| 535 | + bool ingress = mlxsw_sp_flow_block_is_ingress_bound(block); |
|---|
| 536 | + unsigned int mall_min_prio; |
|---|
| 537 | + unsigned int mall_max_prio; |
|---|
| 538 | + int err; |
|---|
| 539 | + |
|---|
| 540 | + err = mlxsw_sp_mall_prio_get(block, f->common.chain_index, |
|---|
| 541 | + &mall_min_prio, &mall_max_prio); |
|---|
| 542 | + if (err) { |
|---|
| 543 | + if (err == -ENOENT) |
|---|
| 544 | + /* No matchall filters installed on this chain. */ |
|---|
| 545 | + return 0; |
|---|
| 546 | + NL_SET_ERR_MSG(f->common.extack, "Failed to get matchall priorities"); |
|---|
| 547 | + return err; |
|---|
| 548 | + } |
|---|
| 549 | + if (ingress && f->common.prio <= mall_min_prio) { |
|---|
| 550 | + NL_SET_ERR_MSG(f->common.extack, "Failed to add in front of existing matchall rules"); |
|---|
| 551 | + return -EOPNOTSUPP; |
|---|
| 552 | + } |
|---|
| 553 | + if (!ingress && f->common.prio >= mall_max_prio) { |
|---|
| 554 | + NL_SET_ERR_MSG(f->common.extack, "Failed to add behind of existing matchall rules"); |
|---|
| 555 | + return -EOPNOTSUPP; |
|---|
| 556 | + } |
|---|
| 557 | + return 0; |
|---|
| 558 | +} |
|---|
| 559 | + |
|---|
| 396 | 560 | int mlxsw_sp_flower_replace(struct mlxsw_sp *mlxsw_sp, |
|---|
| 397 | | - struct mlxsw_sp_acl_block *block, |
|---|
| 398 | | - struct tc_cls_flower_offload *f) |
|---|
| 561 | + struct mlxsw_sp_flow_block *block, |
|---|
| 562 | + struct flow_cls_offload *f) |
|---|
| 399 | 563 | { |
|---|
| 400 | 564 | struct mlxsw_sp_acl_rule_info *rulei; |
|---|
| 401 | 565 | struct mlxsw_sp_acl_ruleset *ruleset; |
|---|
| 402 | 566 | struct mlxsw_sp_acl_rule *rule; |
|---|
| 403 | 567 | int err; |
|---|
| 568 | + |
|---|
| 569 | + err = mlxsw_sp_flower_mall_prio_check(block, f); |
|---|
| 570 | + if (err) |
|---|
| 571 | + return err; |
|---|
| 404 | 572 | |
|---|
| 405 | 573 | ruleset = mlxsw_sp_acl_ruleset_get(mlxsw_sp, block, |
|---|
| 406 | 574 | f->common.chain_index, |
|---|
| .. | .. |
|---|
| 408 | 576 | if (IS_ERR(ruleset)) |
|---|
| 409 | 577 | return PTR_ERR(ruleset); |
|---|
| 410 | 578 | |
|---|
| 411 | | - rule = mlxsw_sp_acl_rule_create(mlxsw_sp, ruleset, f->cookie, |
|---|
| 579 | + rule = mlxsw_sp_acl_rule_create(mlxsw_sp, ruleset, f->cookie, NULL, |
|---|
| 412 | 580 | f->common.extack); |
|---|
| 413 | 581 | if (IS_ERR(rule)) { |
|---|
| 414 | 582 | err = PTR_ERR(rule); |
|---|
| .. | .. |
|---|
| 441 | 609 | } |
|---|
| 442 | 610 | |
|---|
| 443 | 611 | void mlxsw_sp_flower_destroy(struct mlxsw_sp *mlxsw_sp, |
|---|
| 444 | | - struct mlxsw_sp_acl_block *block, |
|---|
| 445 | | - struct tc_cls_flower_offload *f) |
|---|
| 612 | + struct mlxsw_sp_flow_block *block, |
|---|
| 613 | + struct flow_cls_offload *f) |
|---|
| 446 | 614 | { |
|---|
| 447 | 615 | struct mlxsw_sp_acl_ruleset *ruleset; |
|---|
| 448 | 616 | struct mlxsw_sp_acl_rule *rule; |
|---|
| .. | .. |
|---|
| 463 | 631 | } |
|---|
| 464 | 632 | |
|---|
| 465 | 633 | int mlxsw_sp_flower_stats(struct mlxsw_sp *mlxsw_sp, |
|---|
| 466 | | - struct mlxsw_sp_acl_block *block, |
|---|
| 467 | | - struct tc_cls_flower_offload *f) |
|---|
| 634 | + struct mlxsw_sp_flow_block *block, |
|---|
| 635 | + struct flow_cls_offload *f) |
|---|
| 468 | 636 | { |
|---|
| 637 | + enum flow_action_hw_stats used_hw_stats = FLOW_ACTION_HW_STATS_DISABLED; |
|---|
| 469 | 638 | struct mlxsw_sp_acl_ruleset *ruleset; |
|---|
| 470 | 639 | struct mlxsw_sp_acl_rule *rule; |
|---|
| 471 | 640 | u64 packets; |
|---|
| 472 | 641 | u64 lastuse; |
|---|
| 473 | 642 | u64 bytes; |
|---|
| 643 | + u64 drops; |
|---|
| 474 | 644 | int err; |
|---|
| 475 | 645 | |
|---|
| 476 | 646 | ruleset = mlxsw_sp_acl_ruleset_get(mlxsw_sp, block, |
|---|
| .. | .. |
|---|
| 484 | 654 | return -EINVAL; |
|---|
| 485 | 655 | |
|---|
| 486 | 656 | err = mlxsw_sp_acl_rule_get_stats(mlxsw_sp, rule, &packets, &bytes, |
|---|
| 487 | | - &lastuse); |
|---|
| 657 | + &drops, &lastuse, &used_hw_stats); |
|---|
| 488 | 658 | if (err) |
|---|
| 489 | 659 | goto err_rule_get_stats; |
|---|
| 490 | 660 | |
|---|
| 491 | | - tcf_exts_stats_update(f->exts, bytes, packets, lastuse); |
|---|
| 661 | + flow_stats_update(&f->stats, bytes, packets, drops, lastuse, |
|---|
| 662 | + used_hw_stats); |
|---|
| 492 | 663 | |
|---|
| 493 | 664 | mlxsw_sp_acl_ruleset_put(mlxsw_sp, ruleset); |
|---|
| 494 | 665 | return 0; |
|---|
| .. | .. |
|---|
| 499 | 670 | } |
|---|
| 500 | 671 | |
|---|
| 501 | 672 | int mlxsw_sp_flower_tmplt_create(struct mlxsw_sp *mlxsw_sp, |
|---|
| 502 | | - struct mlxsw_sp_acl_block *block, |
|---|
| 503 | | - struct tc_cls_flower_offload *f) |
|---|
| 673 | + struct mlxsw_sp_flow_block *block, |
|---|
| 674 | + struct flow_cls_offload *f) |
|---|
| 504 | 675 | { |
|---|
| 505 | 676 | struct mlxsw_sp_acl_ruleset *ruleset; |
|---|
| 506 | 677 | struct mlxsw_sp_acl_rule_info rulei; |
|---|
| .. | .. |
|---|
| 520 | 691 | } |
|---|
| 521 | 692 | |
|---|
| 522 | 693 | void mlxsw_sp_flower_tmplt_destroy(struct mlxsw_sp *mlxsw_sp, |
|---|
| 523 | | - struct mlxsw_sp_acl_block *block, |
|---|
| 524 | | - struct tc_cls_flower_offload *f) |
|---|
| 694 | + struct mlxsw_sp_flow_block *block, |
|---|
| 695 | + struct flow_cls_offload *f) |
|---|
| 525 | 696 | { |
|---|
| 526 | 697 | struct mlxsw_sp_acl_ruleset *ruleset; |
|---|
| 527 | 698 | |
|---|
| .. | .. |
|---|
| 534 | 705 | mlxsw_sp_acl_ruleset_put(mlxsw_sp, ruleset); |
|---|
| 535 | 706 | mlxsw_sp_acl_ruleset_put(mlxsw_sp, ruleset); |
|---|
| 536 | 707 | } |
|---|
| 708 | + |
|---|
| 709 | +int mlxsw_sp_flower_prio_get(struct mlxsw_sp *mlxsw_sp, |
|---|
| 710 | + struct mlxsw_sp_flow_block *block, |
|---|
| 711 | + u32 chain_index, unsigned int *p_min_prio, |
|---|
| 712 | + unsigned int *p_max_prio) |
|---|
| 713 | +{ |
|---|
| 714 | + struct mlxsw_sp_acl_ruleset *ruleset; |
|---|
| 715 | + |
|---|
| 716 | + ruleset = mlxsw_sp_acl_ruleset_lookup(mlxsw_sp, block, |
|---|
| 717 | + chain_index, |
|---|
| 718 | + MLXSW_SP_ACL_PROFILE_FLOWER); |
|---|
| 719 | + if (IS_ERR(ruleset)) |
|---|
| 720 | + /* In case there are no flower rules, the caller |
|---|
| 721 | + * receives -ENOENT to indicate there is no need |
|---|
| 722 | + * to check the priorities. |
|---|
| 723 | + */ |
|---|
| 724 | + return PTR_ERR(ruleset); |
|---|
| 725 | + mlxsw_sp_acl_ruleset_prio_get(ruleset, p_min_prio, p_max_prio); |
|---|
| 726 | + return 0; |
|---|
| 727 | +} |
|---|