1 // SPDX-License-Identifier: (GPL-2.0 OR MIT) 2 /* Microsemi Ocelot Switch driver 3 * Copyright (c) 2019 Microsemi Corporation 4 */ 5 6 #include <net/pkt_cls.h> 7 #include <net/tc_act/tc_gact.h> 8 9 #include "ocelot_ace.h" 10 11 static int ocelot_flower_parse_action(struct flow_cls_offload *f, 12 struct ocelot_ace_rule *ace) 13 { 14 const struct flow_action_entry *a; 15 s64 burst; 16 u64 rate; 17 int i; 18 19 if (!flow_offload_has_one_action(&f->rule->action)) 20 return -EOPNOTSUPP; 21 22 if (!flow_action_basic_hw_stats_check(&f->rule->action, 23 f->common.extack)) 24 return -EOPNOTSUPP; 25 26 flow_action_for_each(i, a, &f->rule->action) { 27 switch (a->id) { 28 case FLOW_ACTION_DROP: 29 ace->action = OCELOT_ACL_ACTION_DROP; 30 break; 31 case FLOW_ACTION_TRAP: 32 ace->action = OCELOT_ACL_ACTION_TRAP; 33 break; 34 case FLOW_ACTION_POLICE: 35 ace->action = OCELOT_ACL_ACTION_POLICE; 36 rate = a->police.rate_bytes_ps; 37 ace->pol.rate = div_u64(rate, 1000) * 8; 38 burst = rate * PSCHED_NS2TICKS(a->police.burst); 39 ace->pol.burst = div_u64(burst, PSCHED_TICKS_PER_SEC); 40 break; 41 default: 42 return -EOPNOTSUPP; 43 } 44 } 45 46 return 0; 47 } 48 49 static int ocelot_flower_parse(struct flow_cls_offload *f, 50 struct ocelot_ace_rule *ace) 51 { 52 struct flow_rule *rule = flow_cls_offload_flow_rule(f); 53 struct flow_dissector *dissector = rule->match.dissector; 54 55 if (dissector->used_keys & 56 ~(BIT(FLOW_DISSECTOR_KEY_CONTROL) | 57 BIT(FLOW_DISSECTOR_KEY_BASIC) | 58 BIT(FLOW_DISSECTOR_KEY_PORTS) | 59 BIT(FLOW_DISSECTOR_KEY_VLAN) | 60 BIT(FLOW_DISSECTOR_KEY_IPV4_ADDRS) | 61 BIT(FLOW_DISSECTOR_KEY_IPV6_ADDRS) | 62 BIT(FLOW_DISSECTOR_KEY_ETH_ADDRS))) { 63 return -EOPNOTSUPP; 64 } 65 66 if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_CONTROL)) { 67 struct flow_match_control match; 68 69 flow_rule_match_control(rule, &match); 70 } 71 72 if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ETH_ADDRS)) { 73 struct flow_match_eth_addrs match; 74 u16 proto = ntohs(f->common.protocol); 75 76 /* The hw support mac matches only for MAC_ETYPE key, 77 * therefore if other matches(port, tcp flags, etc) are added 78 * then just bail out 79 */ 80 if ((dissector->used_keys & 81 (BIT(FLOW_DISSECTOR_KEY_ETH_ADDRS) | 82 BIT(FLOW_DISSECTOR_KEY_BASIC) | 83 BIT(FLOW_DISSECTOR_KEY_CONTROL))) != 84 (BIT(FLOW_DISSECTOR_KEY_ETH_ADDRS) | 85 BIT(FLOW_DISSECTOR_KEY_BASIC) | 86 BIT(FLOW_DISSECTOR_KEY_CONTROL))) 87 return -EOPNOTSUPP; 88 89 if (proto == ETH_P_IP || 90 proto == ETH_P_IPV6 || 91 proto == ETH_P_ARP) 92 return -EOPNOTSUPP; 93 94 flow_rule_match_eth_addrs(rule, &match); 95 ace->type = OCELOT_ACE_TYPE_ETYPE; 96 ether_addr_copy(ace->frame.etype.dmac.value, 97 match.key->dst); 98 ether_addr_copy(ace->frame.etype.smac.value, 99 match.key->src); 100 ether_addr_copy(ace->frame.etype.dmac.mask, 101 match.mask->dst); 102 ether_addr_copy(ace->frame.etype.smac.mask, 103 match.mask->src); 104 goto finished_key_parsing; 105 } 106 107 if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_BASIC)) { 108 struct flow_match_basic match; 109 110 flow_rule_match_basic(rule, &match); 111 if (ntohs(match.key->n_proto) == ETH_P_IP) { 112 ace->type = OCELOT_ACE_TYPE_IPV4; 113 ace->frame.ipv4.proto.value[0] = 114 match.key->ip_proto; 115 ace->frame.ipv4.proto.mask[0] = 116 match.mask->ip_proto; 117 } 118 if (ntohs(match.key->n_proto) == ETH_P_IPV6) { 119 ace->type = OCELOT_ACE_TYPE_IPV6; 120 ace->frame.ipv6.proto.value[0] = 121 match.key->ip_proto; 122 ace->frame.ipv6.proto.mask[0] = 123 match.mask->ip_proto; 124 } 125 } 126 127 if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_IPV4_ADDRS) && 128 ntohs(f->common.protocol) == ETH_P_IP) { 129 struct flow_match_ipv4_addrs match; 130 u8 *tmp; 131 132 flow_rule_match_ipv4_addrs(rule, &match); 133 tmp = &ace->frame.ipv4.sip.value.addr[0]; 134 memcpy(tmp, &match.key->src, 4); 135 136 tmp = &ace->frame.ipv4.sip.mask.addr[0]; 137 memcpy(tmp, &match.mask->src, 4); 138 139 tmp = &ace->frame.ipv4.dip.value.addr[0]; 140 memcpy(tmp, &match.key->dst, 4); 141 142 tmp = &ace->frame.ipv4.dip.mask.addr[0]; 143 memcpy(tmp, &match.mask->dst, 4); 144 } 145 146 if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_IPV6_ADDRS) && 147 ntohs(f->common.protocol) == ETH_P_IPV6) { 148 return -EOPNOTSUPP; 149 } 150 151 if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_PORTS)) { 152 struct flow_match_ports match; 153 154 flow_rule_match_ports(rule, &match); 155 ace->frame.ipv4.sport.value = ntohs(match.key->src); 156 ace->frame.ipv4.sport.mask = ntohs(match.mask->src); 157 ace->frame.ipv4.dport.value = ntohs(match.key->dst); 158 ace->frame.ipv4.dport.mask = ntohs(match.mask->dst); 159 } 160 161 if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_VLAN)) { 162 struct flow_match_vlan match; 163 164 flow_rule_match_vlan(rule, &match); 165 ace->type = OCELOT_ACE_TYPE_ANY; 166 ace->vlan.vid.value = match.key->vlan_id; 167 ace->vlan.vid.mask = match.mask->vlan_id; 168 ace->vlan.pcp.value[0] = match.key->vlan_priority; 169 ace->vlan.pcp.mask[0] = match.mask->vlan_priority; 170 } 171 172 finished_key_parsing: 173 ace->prio = f->common.prio; 174 ace->id = f->cookie; 175 return ocelot_flower_parse_action(f, ace); 176 } 177 178 static 179 struct ocelot_ace_rule *ocelot_ace_rule_create(struct ocelot *ocelot, int port, 180 struct flow_cls_offload *f) 181 { 182 struct ocelot_ace_rule *ace; 183 184 ace = kzalloc(sizeof(*ace), GFP_KERNEL); 185 if (!ace) 186 return NULL; 187 188 ace->ingress_port_mask = BIT(port); 189 return ace; 190 } 191 192 int ocelot_cls_flower_replace(struct ocelot *ocelot, int port, 193 struct flow_cls_offload *f, bool ingress) 194 { 195 struct ocelot_ace_rule *ace; 196 int ret; 197 198 ace = ocelot_ace_rule_create(ocelot, port, f); 199 if (!ace) 200 return -ENOMEM; 201 202 ret = ocelot_flower_parse(f, ace); 203 if (ret) { 204 kfree(ace); 205 return ret; 206 } 207 208 return ocelot_ace_rule_offload_add(ocelot, ace); 209 } 210 EXPORT_SYMBOL_GPL(ocelot_cls_flower_replace); 211 212 int ocelot_cls_flower_destroy(struct ocelot *ocelot, int port, 213 struct flow_cls_offload *f, bool ingress) 214 { 215 struct ocelot_ace_rule ace; 216 217 ace.prio = f->common.prio; 218 ace.id = f->cookie; 219 220 return ocelot_ace_rule_offload_del(ocelot, &ace); 221 } 222 EXPORT_SYMBOL_GPL(ocelot_cls_flower_destroy); 223 224 int ocelot_cls_flower_stats(struct ocelot *ocelot, int port, 225 struct flow_cls_offload *f, bool ingress) 226 { 227 struct ocelot_ace_rule ace; 228 int ret; 229 230 ace.prio = f->common.prio; 231 ace.id = f->cookie; 232 ret = ocelot_ace_rule_stats_update(ocelot, &ace); 233 if (ret) 234 return ret; 235 236 flow_stats_update(&f->stats, 0x0, ace.stats.pkts, 0x0, 237 FLOW_ACTION_HW_STATS_IMMEDIATE); 238 return 0; 239 } 240 EXPORT_SYMBOL_GPL(ocelot_cls_flower_stats); 241 242 int ocelot_setup_tc_cls_flower(struct ocelot_port_private *priv, 243 struct flow_cls_offload *f, 244 bool ingress) 245 { 246 struct ocelot *ocelot = priv->port.ocelot; 247 int port = priv->chip_port; 248 249 if (!ingress) 250 return -EOPNOTSUPP; 251 252 switch (f->command) { 253 case FLOW_CLS_REPLACE: 254 return ocelot_cls_flower_replace(ocelot, port, f, ingress); 255 case FLOW_CLS_DESTROY: 256 return ocelot_cls_flower_destroy(ocelot, port, f, ingress); 257 case FLOW_CLS_STATS: 258 return ocelot_cls_flower_stats(ocelot, port, f, ingress); 259 default: 260 return -EOPNOTSUPP; 261 } 262 } 263