1 // SPDX-License-Identifier: GPL-2.0+ 2 /* Microchip VCAP TC 3 * 4 * Copyright (c) 2023 Microchip Technology Inc. and its subsidiaries. 5 */ 6 7 #include <net/flow_offload.h> 8 #include <net/ipv6.h> 9 #include <net/tcp.h> 10 11 #include "vcap_api_client.h" 12 #include "vcap_tc.h" 13 14 enum vcap_is2_arp_opcode { 15 VCAP_IS2_ARP_REQUEST, 16 VCAP_IS2_ARP_REPLY, 17 VCAP_IS2_RARP_REQUEST, 18 VCAP_IS2_RARP_REPLY, 19 }; 20 21 enum vcap_arp_opcode { 22 VCAP_ARP_OP_RESERVED, 23 VCAP_ARP_OP_REQUEST, 24 VCAP_ARP_OP_REPLY, 25 }; 26 27 int vcap_tc_flower_handler_ethaddr_usage(struct vcap_tc_flower_parse_usage *st) 28 { 29 enum vcap_key_field smac_key = VCAP_KF_L2_SMAC; 30 enum vcap_key_field dmac_key = VCAP_KF_L2_DMAC; 31 struct flow_match_eth_addrs match; 32 struct vcap_u48_key smac, dmac; 33 int err = 0; 34 35 flow_rule_match_eth_addrs(st->frule, &match); 36 37 if (!is_zero_ether_addr(match.mask->src)) { 38 vcap_netbytes_copy(smac.value, match.key->src, ETH_ALEN); 39 vcap_netbytes_copy(smac.mask, match.mask->src, ETH_ALEN); 40 err = vcap_rule_add_key_u48(st->vrule, smac_key, &smac); 41 if (err) 42 goto out; 43 } 44 45 if (!is_zero_ether_addr(match.mask->dst)) { 46 vcap_netbytes_copy(dmac.value, match.key->dst, ETH_ALEN); 47 vcap_netbytes_copy(dmac.mask, match.mask->dst, ETH_ALEN); 48 err = vcap_rule_add_key_u48(st->vrule, dmac_key, &dmac); 49 if (err) 50 goto out; 51 } 52 53 st->used_keys |= BIT(FLOW_DISSECTOR_KEY_ETH_ADDRS); 54 55 return err; 56 57 out: 58 NL_SET_ERR_MSG_MOD(st->fco->common.extack, "eth_addr parse error"); 59 return err; 60 } 61 EXPORT_SYMBOL_GPL(vcap_tc_flower_handler_ethaddr_usage); 62 63 int vcap_tc_flower_handler_ipv4_usage(struct vcap_tc_flower_parse_usage *st) 64 { 65 int err = 0; 66 67 if (st->l3_proto == ETH_P_IP) { 68 struct flow_match_ipv4_addrs mt; 69 70 flow_rule_match_ipv4_addrs(st->frule, &mt); 71 if (mt.mask->src) { 72 err = vcap_rule_add_key_u32(st->vrule, 73 VCAP_KF_L3_IP4_SIP, 74 be32_to_cpu(mt.key->src), 75 be32_to_cpu(mt.mask->src)); 76 if (err) 77 goto out; 78 } 79 if (mt.mask->dst) { 80 err = vcap_rule_add_key_u32(st->vrule, 81 VCAP_KF_L3_IP4_DIP, 82 be32_to_cpu(mt.key->dst), 83 be32_to_cpu(mt.mask->dst)); 84 if (err) 85 goto out; 86 } 87 } 88 89 st->used_keys |= BIT(FLOW_DISSECTOR_KEY_IPV4_ADDRS); 90 91 return err; 92 93 out: 94 NL_SET_ERR_MSG_MOD(st->fco->common.extack, "ipv4_addr parse error"); 95 return err; 96 } 97 EXPORT_SYMBOL_GPL(vcap_tc_flower_handler_ipv4_usage); 98 99 int vcap_tc_flower_handler_ipv6_usage(struct vcap_tc_flower_parse_usage *st) 100 { 101 int err = 0; 102 103 if (st->l3_proto == ETH_P_IPV6) { 104 struct flow_match_ipv6_addrs mt; 105 struct vcap_u128_key sip; 106 struct vcap_u128_key dip; 107 108 flow_rule_match_ipv6_addrs(st->frule, &mt); 109 /* Check if address masks are non-zero */ 110 if (!ipv6_addr_any(&mt.mask->src)) { 111 vcap_netbytes_copy(sip.value, mt.key->src.s6_addr, 16); 112 vcap_netbytes_copy(sip.mask, mt.mask->src.s6_addr, 16); 113 err = vcap_rule_add_key_u128(st->vrule, 114 VCAP_KF_L3_IP6_SIP, &sip); 115 if (err) 116 goto out; 117 } 118 if (!ipv6_addr_any(&mt.mask->dst)) { 119 vcap_netbytes_copy(dip.value, mt.key->dst.s6_addr, 16); 120 vcap_netbytes_copy(dip.mask, mt.mask->dst.s6_addr, 16); 121 err = vcap_rule_add_key_u128(st->vrule, 122 VCAP_KF_L3_IP6_DIP, &dip); 123 if (err) 124 goto out; 125 } 126 } 127 st->used_keys |= BIT(FLOW_DISSECTOR_KEY_IPV6_ADDRS); 128 return err; 129 out: 130 NL_SET_ERR_MSG_MOD(st->fco->common.extack, "ipv6_addr parse error"); 131 return err; 132 } 133 EXPORT_SYMBOL_GPL(vcap_tc_flower_handler_ipv6_usage); 134 135 int vcap_tc_flower_handler_portnum_usage(struct vcap_tc_flower_parse_usage *st) 136 { 137 struct flow_match_ports mt; 138 u16 value, mask; 139 int err = 0; 140 141 flow_rule_match_ports(st->frule, &mt); 142 143 if (mt.mask->src) { 144 value = be16_to_cpu(mt.key->src); 145 mask = be16_to_cpu(mt.mask->src); 146 err = vcap_rule_add_key_u32(st->vrule, VCAP_KF_L4_SPORT, value, 147 mask); 148 if (err) 149 goto out; 150 } 151 152 if (mt.mask->dst) { 153 value = be16_to_cpu(mt.key->dst); 154 mask = be16_to_cpu(mt.mask->dst); 155 err = vcap_rule_add_key_u32(st->vrule, VCAP_KF_L4_DPORT, value, 156 mask); 157 if (err) 158 goto out; 159 } 160 161 st->used_keys |= BIT(FLOW_DISSECTOR_KEY_PORTS); 162 163 return err; 164 165 out: 166 NL_SET_ERR_MSG_MOD(st->fco->common.extack, "port parse error"); 167 return err; 168 } 169 EXPORT_SYMBOL_GPL(vcap_tc_flower_handler_portnum_usage); 170 171 int vcap_tc_flower_handler_cvlan_usage(struct vcap_tc_flower_parse_usage *st) 172 { 173 enum vcap_key_field vid_key = VCAP_KF_8021Q_VID0; 174 enum vcap_key_field pcp_key = VCAP_KF_8021Q_PCP0; 175 struct flow_match_vlan mt; 176 u16 tpid; 177 int err; 178 179 flow_rule_match_cvlan(st->frule, &mt); 180 181 tpid = be16_to_cpu(mt.key->vlan_tpid); 182 183 if (tpid == ETH_P_8021Q) { 184 vid_key = VCAP_KF_8021Q_VID1; 185 pcp_key = VCAP_KF_8021Q_PCP1; 186 } 187 188 if (mt.mask->vlan_id) { 189 err = vcap_rule_add_key_u32(st->vrule, vid_key, 190 mt.key->vlan_id, 191 mt.mask->vlan_id); 192 if (err) 193 goto out; 194 } 195 196 if (mt.mask->vlan_priority) { 197 err = vcap_rule_add_key_u32(st->vrule, pcp_key, 198 mt.key->vlan_priority, 199 mt.mask->vlan_priority); 200 if (err) 201 goto out; 202 } 203 204 st->used_keys |= BIT(FLOW_DISSECTOR_KEY_CVLAN); 205 206 return 0; 207 out: 208 NL_SET_ERR_MSG_MOD(st->fco->common.extack, "cvlan parse error"); 209 return err; 210 } 211 EXPORT_SYMBOL_GPL(vcap_tc_flower_handler_cvlan_usage); 212 213 int vcap_tc_flower_handler_vlan_usage(struct vcap_tc_flower_parse_usage *st, 214 enum vcap_key_field vid_key, 215 enum vcap_key_field pcp_key) 216 { 217 struct flow_match_vlan mt; 218 int err; 219 220 flow_rule_match_vlan(st->frule, &mt); 221 222 if (mt.mask->vlan_id) { 223 err = vcap_rule_add_key_u32(st->vrule, vid_key, 224 mt.key->vlan_id, 225 mt.mask->vlan_id); 226 if (err) 227 goto out; 228 } 229 230 if (mt.mask->vlan_priority) { 231 err = vcap_rule_add_key_u32(st->vrule, pcp_key, 232 mt.key->vlan_priority, 233 mt.mask->vlan_priority); 234 if (err) 235 goto out; 236 } 237 238 st->used_keys |= BIT(FLOW_DISSECTOR_KEY_VLAN); 239 240 return 0; 241 out: 242 NL_SET_ERR_MSG_MOD(st->fco->common.extack, "vlan parse error"); 243 return err; 244 } 245 EXPORT_SYMBOL_GPL(vcap_tc_flower_handler_vlan_usage); 246 247 int vcap_tc_flower_handler_tcp_usage(struct vcap_tc_flower_parse_usage *st) 248 { 249 struct flow_match_tcp mt; 250 u16 tcp_flags_mask; 251 u16 tcp_flags_key; 252 enum vcap_bit val; 253 int err = 0; 254 255 flow_rule_match_tcp(st->frule, &mt); 256 tcp_flags_key = be16_to_cpu(mt.key->flags); 257 tcp_flags_mask = be16_to_cpu(mt.mask->flags); 258 259 if (tcp_flags_mask & TCPHDR_FIN) { 260 val = VCAP_BIT_0; 261 if (tcp_flags_key & TCPHDR_FIN) 262 val = VCAP_BIT_1; 263 err = vcap_rule_add_key_bit(st->vrule, VCAP_KF_L4_FIN, val); 264 if (err) 265 goto out; 266 } 267 268 if (tcp_flags_mask & TCPHDR_SYN) { 269 val = VCAP_BIT_0; 270 if (tcp_flags_key & TCPHDR_SYN) 271 val = VCAP_BIT_1; 272 err = vcap_rule_add_key_bit(st->vrule, VCAP_KF_L4_SYN, val); 273 if (err) 274 goto out; 275 } 276 277 if (tcp_flags_mask & TCPHDR_RST) { 278 val = VCAP_BIT_0; 279 if (tcp_flags_key & TCPHDR_RST) 280 val = VCAP_BIT_1; 281 err = vcap_rule_add_key_bit(st->vrule, VCAP_KF_L4_RST, val); 282 if (err) 283 goto out; 284 } 285 286 if (tcp_flags_mask & TCPHDR_PSH) { 287 val = VCAP_BIT_0; 288 if (tcp_flags_key & TCPHDR_PSH) 289 val = VCAP_BIT_1; 290 err = vcap_rule_add_key_bit(st->vrule, VCAP_KF_L4_PSH, val); 291 if (err) 292 goto out; 293 } 294 295 if (tcp_flags_mask & TCPHDR_ACK) { 296 val = VCAP_BIT_0; 297 if (tcp_flags_key & TCPHDR_ACK) 298 val = VCAP_BIT_1; 299 err = vcap_rule_add_key_bit(st->vrule, VCAP_KF_L4_ACK, val); 300 if (err) 301 goto out; 302 } 303 304 if (tcp_flags_mask & TCPHDR_URG) { 305 val = VCAP_BIT_0; 306 if (tcp_flags_key & TCPHDR_URG) 307 val = VCAP_BIT_1; 308 err = vcap_rule_add_key_bit(st->vrule, VCAP_KF_L4_URG, val); 309 if (err) 310 goto out; 311 } 312 313 st->used_keys |= BIT(FLOW_DISSECTOR_KEY_TCP); 314 315 return err; 316 317 out: 318 NL_SET_ERR_MSG_MOD(st->fco->common.extack, "tcp_flags parse error"); 319 return err; 320 } 321 EXPORT_SYMBOL_GPL(vcap_tc_flower_handler_tcp_usage); 322 323 int vcap_tc_flower_handler_arp_usage(struct vcap_tc_flower_parse_usage *st) 324 { 325 struct flow_match_arp mt; 326 u16 value, mask; 327 u32 ipval, ipmsk; 328 int err; 329 330 flow_rule_match_arp(st->frule, &mt); 331 332 if (mt.mask->op) { 333 mask = 0x3; 334 if (st->l3_proto == ETH_P_ARP) { 335 value = mt.key->op == VCAP_ARP_OP_REQUEST ? 336 VCAP_IS2_ARP_REQUEST : 337 VCAP_IS2_ARP_REPLY; 338 } else { /* RARP */ 339 value = mt.key->op == VCAP_ARP_OP_REQUEST ? 340 VCAP_IS2_RARP_REQUEST : 341 VCAP_IS2_RARP_REPLY; 342 } 343 err = vcap_rule_add_key_u32(st->vrule, VCAP_KF_ARP_OPCODE, 344 value, mask); 345 if (err) 346 goto out; 347 } 348 349 /* The IS2 ARP keyset does not support ARP hardware addresses */ 350 if (!is_zero_ether_addr(mt.mask->sha) || 351 !is_zero_ether_addr(mt.mask->tha)) { 352 err = -EINVAL; 353 goto out; 354 } 355 356 if (mt.mask->sip) { 357 ipval = be32_to_cpu((__force __be32)mt.key->sip); 358 ipmsk = be32_to_cpu((__force __be32)mt.mask->sip); 359 360 err = vcap_rule_add_key_u32(st->vrule, VCAP_KF_L3_IP4_SIP, 361 ipval, ipmsk); 362 if (err) 363 goto out; 364 } 365 366 if (mt.mask->tip) { 367 ipval = be32_to_cpu((__force __be32)mt.key->tip); 368 ipmsk = be32_to_cpu((__force __be32)mt.mask->tip); 369 370 err = vcap_rule_add_key_u32(st->vrule, VCAP_KF_L3_IP4_DIP, 371 ipval, ipmsk); 372 if (err) 373 goto out; 374 } 375 376 st->used_keys |= BIT(FLOW_DISSECTOR_KEY_ARP); 377 378 return 0; 379 380 out: 381 NL_SET_ERR_MSG_MOD(st->fco->common.extack, "arp parse error"); 382 return err; 383 } 384 EXPORT_SYMBOL_GPL(vcap_tc_flower_handler_arp_usage); 385 386 int vcap_tc_flower_handler_ip_usage(struct vcap_tc_flower_parse_usage *st) 387 { 388 struct flow_match_ip mt; 389 int err = 0; 390 391 flow_rule_match_ip(st->frule, &mt); 392 393 if (mt.mask->tos) { 394 err = vcap_rule_add_key_u32(st->vrule, VCAP_KF_L3_TOS, 395 mt.key->tos, 396 mt.mask->tos); 397 if (err) 398 goto out; 399 } 400 401 st->used_keys |= BIT(FLOW_DISSECTOR_KEY_IP); 402 403 return err; 404 405 out: 406 NL_SET_ERR_MSG_MOD(st->fco->common.extack, "ip_tos parse error"); 407 return err; 408 } 409 EXPORT_SYMBOL_GPL(vcap_tc_flower_handler_ip_usage); 410