Lines Matching +full:pre +full:- +full:verified
1 // SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
2 /* Copyright (C) 2017-2018 Netronome Systems, Inc. */
103 key_len = nfp_flow->meta.key_len; in nfp_flower_xmit_flow()
104 mask_len = nfp_flow->meta.mask_len; in nfp_flower_xmit_flow()
105 act_len = nfp_flow->meta.act_len; in nfp_flower_xmit_flow()
112 nfp_flow->meta.key_len >>= NFP_FL_LW_SIZ; in nfp_flower_xmit_flow()
113 nfp_flow->meta.mask_len >>= NFP_FL_LW_SIZ; in nfp_flower_xmit_flow()
114 nfp_flow->meta.act_len >>= NFP_FL_LW_SIZ; in nfp_flower_xmit_flow()
118 return -ENOMEM; in nfp_flower_xmit_flow()
121 memcpy(msg, &nfp_flow->meta, meta_len); in nfp_flower_xmit_flow()
122 memcpy(&msg[meta_len], nfp_flow->unmasked_data, key_len); in nfp_flower_xmit_flow()
123 memcpy(&msg[meta_len + key_len], nfp_flow->mask_data, mask_len); in nfp_flower_xmit_flow()
125 nfp_flow->action_data, act_len); in nfp_flower_xmit_flow()
130 nfp_flow->meta.key_len <<= NFP_FL_LW_SIZ; in nfp_flower_xmit_flow()
131 nfp_flow->meta.mask_len <<= NFP_FL_LW_SIZ; in nfp_flower_xmit_flow()
132 nfp_flow->meta.act_len <<= NFP_FL_LW_SIZ; in nfp_flower_xmit_flow()
134 nfp_ctrl_tx(app->ctrl, skb); in nfp_flower_xmit_flow()
158 if (enc_opts->len > NFP_FL_MAX_GENEVE_OPT_KEY || in nfp_flower_calc_opt_layer()
159 (ipv6 && enc_opts->len > NFP_FL_MAX_GENEVE_OPT_KEY_V6)) { in nfp_flower_calc_opt_layer()
161 return -EOPNOTSUPP; in nfp_flower_calc_opt_layer()
164 if (enc_opts->len > 0) { in nfp_flower_calc_opt_layer()
182 switch (enc_ports->dst) { in nfp_flower_calc_udp_tun_layer()
198 return -EOPNOTSUPP; in nfp_flower_calc_udp_tun_layer()
202 if (!(priv->flower_ext_feats & NFP_FL_FEATS_GENEVE)) { in nfp_flower_calc_udp_tun_layer()
204 return -EOPNOTSUPP; in nfp_flower_calc_udp_tun_layer()
220 if (!(priv->flower_ext_feats & NFP_FL_FEATS_GENEVE_OPT)) { in nfp_flower_calc_udp_tun_layer()
222 return -EOPNOTSUPP; in nfp_flower_calc_udp_tun_layer()
231 return -EOPNOTSUPP; in nfp_flower_calc_udp_tun_layer()
245 struct flow_dissector *dissector = rule->match.dissector; in nfp_flower_calculate_key_layers()
247 struct nfp_flower_priv *priv = app->priv; in nfp_flower_calculate_key_layers()
253 if (dissector->used_keys & ~NFP_FLOWER_WHITELIST_DISSECTOR) { in nfp_flower_calculate_key_layers()
255 return -EOPNOTSUPP; in nfp_flower_calculate_key_layers()
259 if (dissector->used_keys & NFP_FLOWER_WHITELIST_TUN_DISSECTOR && in nfp_flower_calculate_key_layers()
260 (dissector->used_keys & NFP_FLOWER_WHITELIST_TUN_DISSECTOR_V6_R) in nfp_flower_calculate_key_layers()
262 (dissector->used_keys & NFP_FLOWER_WHITELIST_TUN_DISSECTOR_R) in nfp_flower_calculate_key_layers()
265 return -EOPNOTSUPP; in nfp_flower_calculate_key_layers()
283 if (!(priv->flower_ext_feats & NFP_FL_FEATS_VLAN_PCP) && in nfp_flower_calculate_key_layers()
284 vlan.key->vlan_priority) { in nfp_flower_calculate_key_layers()
286 return -EOPNOTSUPP; in nfp_flower_calculate_key_layers()
288 if (priv->flower_ext_feats & NFP_FL_FEATS_VLAN_QINQ && in nfp_flower_calculate_key_layers()
300 if (!(priv->flower_ext_feats & NFP_FL_FEATS_VLAN_QINQ)) { in nfp_flower_calculate_key_layers()
302 return -EOPNOTSUPP; in nfp_flower_calculate_key_layers()
324 if (enc_ctl.mask->addr_type != 0xffff) { in nfp_flower_calculate_key_layers()
326 return -EOPNOTSUPP; in nfp_flower_calculate_key_layers()
329 ipv6_tun = enc_ctl.key->addr_type == in nfp_flower_calculate_key_layers()
332 !(priv->flower_ext_feats & NFP_FL_FEATS_IPV6_TUN)) { in nfp_flower_calculate_key_layers()
334 return -EOPNOTSUPP; in nfp_flower_calculate_key_layers()
338 enc_ctl.key->addr_type != FLOW_DISSECTOR_KEY_IPV4_ADDRS) { in nfp_flower_calculate_key_layers()
340 return -EOPNOTSUPP; in nfp_flower_calculate_key_layers()
345 if (memchr_inv(&ipv6_addrs.mask->dst, 0xff, in nfp_flower_calculate_key_layers()
346 sizeof(ipv6_addrs.mask->dst))) { in nfp_flower_calculate_key_layers()
348 return -EOPNOTSUPP; in nfp_flower_calculate_key_layers()
352 if (ipv4_addrs.mask->dst != cpu_to_be32(~0)) { in nfp_flower_calculate_key_layers()
354 return -EOPNOTSUPP; in nfp_flower_calculate_key_layers()
364 …ack, "unsupported offload: an exact match on L4 destination port is required for non-GRE tunnels"); in nfp_flower_calculate_key_layers()
365 return -EOPNOTSUPP; in nfp_flower_calculate_key_layers()
384 return -EOPNOTSUPP; in nfp_flower_calculate_key_layers()
388 if (enc_ports.mask->dst != cpu_to_be16(~0)) { in nfp_flower_calculate_key_layers()
390 return -EOPNOTSUPP; in nfp_flower_calculate_key_layers()
408 return -EOPNOTSUPP; in nfp_flower_calculate_key_layers()
416 if (basic.mask && basic.mask->n_proto) { in nfp_flower_calculate_key_layers()
418 switch (basic.key->n_proto) { in nfp_flower_calculate_key_layers()
434 return -EOPNOTSUPP; in nfp_flower_calculate_key_layers()
450 return -EOPNOTSUPP; in nfp_flower_calculate_key_layers()
454 return -EOPNOTSUPP; in nfp_flower_calculate_key_layers()
457 if (basic.mask && basic.mask->ip_proto) { in nfp_flower_calculate_key_layers()
458 switch (basic.key->ip_proto) { in nfp_flower_calculate_key_layers()
473 return -EOPNOTSUPP; in nfp_flower_calculate_key_layers()
481 tcp_flags = be16_to_cpu(tcp.key->flags); in nfp_flower_calculate_key_layers()
485 return -EOPNOTSUPP; in nfp_flower_calculate_key_layers()
494 return -EOPNOTSUPP; in nfp_flower_calculate_key_layers()
503 return -EOPNOTSUPP; in nfp_flower_calculate_key_layers()
508 switch (basic.key->n_proto) { in nfp_flower_calculate_key_layers()
521 return -EOPNOTSUPP; in nfp_flower_calculate_key_layers()
530 if (ctl.key->flags & ~NFP_FLOWER_SUPPORTED_CTLFLAGS) { in nfp_flower_calculate_key_layers()
532 return -EOPNOTSUPP; in nfp_flower_calculate_key_layers()
536 ret_key_ls->key_layer = key_layer; in nfp_flower_calculate_key_layers()
537 ret_key_ls->key_layer_two = key_layer_two; in nfp_flower_calculate_key_layers()
538 ret_key_ls->key_size = key_size; in nfp_flower_calculate_key_layers()
552 flow_pay->meta.key_len = key_layer->key_size; in nfp_flower_allocate_new()
553 flow_pay->unmasked_data = kmalloc(key_layer->key_size, GFP_KERNEL); in nfp_flower_allocate_new()
554 if (!flow_pay->unmasked_data) in nfp_flower_allocate_new()
557 flow_pay->meta.mask_len = key_layer->key_size; in nfp_flower_allocate_new()
558 flow_pay->mask_data = kmalloc(key_layer->key_size, GFP_KERNEL); in nfp_flower_allocate_new()
559 if (!flow_pay->mask_data) in nfp_flower_allocate_new()
562 flow_pay->action_data = kmalloc(NFP_FL_MAX_A_SIZ, GFP_KERNEL); in nfp_flower_allocate_new()
563 if (!flow_pay->action_data) in nfp_flower_allocate_new()
566 flow_pay->nfp_tun_ipv4_addr = 0; in nfp_flower_allocate_new()
567 flow_pay->nfp_tun_ipv6 = NULL; in nfp_flower_allocate_new()
568 flow_pay->meta.flags = 0; in nfp_flower_allocate_new()
569 INIT_LIST_HEAD(&flow_pay->linked_flows); in nfp_flower_allocate_new()
570 flow_pay->in_hw = false; in nfp_flower_allocate_new()
571 flow_pay->pre_tun_rule.dev = NULL; in nfp_flower_allocate_new()
576 kfree(flow_pay->mask_data); in nfp_flower_allocate_new()
578 kfree(flow_pay->unmasked_data); in nfp_flower_allocate_new()
604 while (act_off < flow->meta.act_len) { in nfp_flower_update_merge_with_actions()
605 a = (struct nfp_fl_act_head *)&flow->action_data[act_off]; in nfp_flower_update_merge_with_actions()
606 act_id = a->jump_id; in nfp_flower_update_merge_with_actions()
615 if (push_vlan->vlan_tci) in nfp_flower_update_merge_with_actions()
616 merge->tci = cpu_to_be16(0xffff); in nfp_flower_update_merge_with_actions()
619 merge->tci = cpu_to_be16(0); in nfp_flower_update_merge_with_actions()
623 eth_broadcast_addr(&merge->l2.mac_dst[0]); in nfp_flower_update_merge_with_actions()
624 eth_broadcast_addr(&merge->l2.mac_src[0]); in nfp_flower_update_merge_with_actions()
625 memset(&merge->l4, 0xff, in nfp_flower_update_merge_with_actions()
628 memset(&merge->ipv6, 0xff, in nfp_flower_update_merge_with_actions()
631 memset(&merge->ipv4, 0xff, in nfp_flower_update_merge_with_actions()
637 merge->l2.mac_dst[i] |= eth->eth_addr_mask[i]; in nfp_flower_update_merge_with_actions()
639 merge->l2.mac_src[i] |= in nfp_flower_update_merge_with_actions()
640 eth->eth_addr_mask[ETH_ALEN + i]; in nfp_flower_update_merge_with_actions()
644 merge->ipv4.ipv4_src |= ipv4_add->ipv4_src_mask; in nfp_flower_update_merge_with_actions()
645 merge->ipv4.ipv4_dst |= ipv4_add->ipv4_dst_mask; in nfp_flower_update_merge_with_actions()
649 merge->ipv4.ip_ext.ttl |= ipv4_ttl_tos->ipv4_ttl_mask; in nfp_flower_update_merge_with_actions()
650 merge->ipv4.ip_ext.tos |= ipv4_ttl_tos->ipv4_tos_mask; in nfp_flower_update_merge_with_actions()
655 merge->ipv6.ipv6_src.in6_u.u6_addr32[i] |= in nfp_flower_update_merge_with_actions()
656 ipv6_add->ipv6[i].mask; in nfp_flower_update_merge_with_actions()
661 merge->ipv6.ipv6_dst.in6_u.u6_addr32[i] |= in nfp_flower_update_merge_with_actions()
662 ipv6_add->ipv6[i].mask; in nfp_flower_update_merge_with_actions()
666 merge->ipv6.ip_ext.ttl |= in nfp_flower_update_merge_with_actions()
667 ipv6_tc_hl_fl->ipv6_hop_limit_mask; in nfp_flower_update_merge_with_actions()
668 merge->ipv6.ip_ext.tos |= ipv6_tc_hl_fl->ipv6_tc_mask; in nfp_flower_update_merge_with_actions()
669 merge->ipv6.ipv6_flow_label_exthdr |= in nfp_flower_update_merge_with_actions()
670 ipv6_tc_hl_fl->ipv6_label_mask; in nfp_flower_update_merge_with_actions()
675 ports = (u8 *)&merge->l4.port_src; in nfp_flower_update_merge_with_actions()
677 ports[i] |= tport->tp_port_mask[i]; in nfp_flower_update_merge_with_actions()
681 ipv6_tun = be16_to_cpu(pre_tun->flags) & in nfp_flower_update_merge_with_actions()
688 return -EOPNOTSUPP; in nfp_flower_update_merge_with_actions()
691 act_off += a->len_lw << NFP_FL_LW_SIZ; in nfp_flower_update_merge_with_actions()
706 u8 *mask = flow->mask_data; in nfp_flower_populate_merge_match()
712 key_layer = meta_tci->nfp_flow_key_layer; in nfp_flower_populate_merge_match()
715 return -EOPNOTSUPP; in nfp_flower_populate_merge_match()
717 merge->tci = meta_tci->tci; in nfp_flower_populate_merge_match()
727 memcpy(&merge->l2, mask, match_size); in nfp_flower_populate_merge_match()
733 memcpy(&merge->l4, mask, match_size); in nfp_flower_populate_merge_match()
739 memcpy(&merge->ipv4, mask, match_size); in nfp_flower_populate_merge_match()
744 memcpy(&merge->ipv6, mask, match_size); in nfp_flower_populate_merge_match()
780 return -EOPNOTSUPP; in nfp_flower_can_merge()
789 return -EINVAL; in nfp_flower_can_merge()
804 act_len = a->len_lw << NFP_FL_LW_SIZ; in nfp_flower_copy_pre_actions()
805 act_id = a->jump_id; in nfp_flower_copy_pre_actions()
834 if (a->jump_id == NFP_FL_ACTION_OPCODE_PUSH_VLAN && !act_off) in nfp_fl_verify_post_tun_acts()
836 else if (a->jump_id != NFP_FL_ACTION_OPCODE_OUTPUT) in nfp_fl_verify_post_tun_acts()
837 return -EOPNOTSUPP; in nfp_fl_verify_post_tun_acts()
839 act_off += a->len_lw << NFP_FL_LW_SIZ; in nfp_fl_verify_post_tun_acts()
844 return -EOPNOTSUPP; in nfp_fl_verify_post_tun_acts()
859 if (a->jump_id == NFP_FL_ACTION_OPCODE_SET_TUNNEL) { in nfp_fl_push_vlan_after_tun()
861 tun->outer_vlan_tpid = vlan->vlan_tpid; in nfp_fl_push_vlan_after_tun()
862 tun->outer_vlan_tci = vlan->vlan_tci; in nfp_fl_push_vlan_after_tun()
867 act_off += a->len_lw << NFP_FL_LW_SIZ; in nfp_fl_push_vlan_after_tun()
871 return -EOPNOTSUPP; in nfp_fl_push_vlan_after_tun()
885 /* The last action of sub_flow1 must be output - do not merge this. */ in nfp_flower_merge_action()
886 sub1_act_len = sub_flow1->meta.act_len - sizeof(struct nfp_fl_output); in nfp_flower_merge_action()
887 sub2_act_len = sub_flow2->meta.act_len; in nfp_flower_merge_action()
890 return -EINVAL; in nfp_flower_merge_action()
893 return -EINVAL; in nfp_flower_merge_action()
897 merge_flow->meta.shortcut = cpu_to_be32(NFP_FL_SC_ACT_NULL); in nfp_flower_merge_action()
899 merge_flow->meta.shortcut = sub_flow2->meta.shortcut; in nfp_flower_merge_action()
901 merge_flow->meta.act_len = sub1_act_len + sub2_act_len; in nfp_flower_merge_action()
902 merge_act = merge_flow->action_data; in nfp_flower_merge_action()
904 /* Copy any pre-actions to the start of merge flow action list. */ in nfp_flower_merge_action()
906 sub_flow1->action_data, in nfp_flower_merge_action()
909 sub1_act_len -= pre_off1; in nfp_flower_merge_action()
911 sub_flow2->action_data, in nfp_flower_merge_action()
914 sub2_act_len -= pre_off2; in nfp_flower_merge_action()
921 char *post_tun_acts = &sub_flow2->action_data[pre_off2]; in nfp_flower_merge_action()
930 sub2_act_len -= sizeof(*post_tun_push_vlan); in nfp_flower_merge_action()
935 memcpy(merge_act, sub_flow1->action_data + pre_off1, sub1_act_len); in nfp_flower_merge_action()
944 merge_flow->meta.act_len -= sizeof(*post_tun_push_vlan); in nfp_flower_merge_action()
948 memcpy(merge_act, sub_flow2->action_data + pre_off2, sub2_act_len); in nfp_flower_merge_action()
956 list_del(&link->merge_flow.list); in nfp_flower_unlink_flow()
957 list_del(&link->sub_flow.list); in nfp_flower_unlink_flow()
966 list_for_each_entry(link, &merge_flow->linked_flows, merge_flow.list) in nfp_flower_unlink_flows()
967 if (link->sub_flow.flow == sub_flow) { in nfp_flower_unlink_flows()
980 return -ENOMEM; in nfp_flower_link_flows()
982 link->merge_flow.flow = merge_flow; in nfp_flower_link_flows()
983 list_add_tail(&link->merge_flow.list, &merge_flow->linked_flows); in nfp_flower_link_flows()
984 link->sub_flow.flow = sub_flow; in nfp_flower_link_flows()
985 list_add_tail(&link->sub_flow.list, &sub_flow->linked_flows); in nfp_flower_link_flows()
991 * nfp_flower_merge_offloaded_flows() - Merge 2 existing flows to single flow.
1005 struct nfp_flower_priv *priv = app->priv; in nfp_flower_merge_offloaded_flows()
1017 return -EINVAL; in nfp_flower_merge_offloaded_flows()
1020 parent_ctx = (u64)(be32_to_cpu(sub_flow1->meta.host_ctx_id)) << 32; in nfp_flower_merge_offloaded_flows()
1021 parent_ctx |= (u64)(be32_to_cpu(sub_flow2->meta.host_ctx_id)); in nfp_flower_merge_offloaded_flows()
1022 if (rhashtable_lookup_fast(&priv->merge_table, in nfp_flower_merge_offloaded_flows()
1032 merge_key_ls.key_size = sub_flow1->meta.key_len; in nfp_flower_merge_offloaded_flows()
1036 return -ENOMEM; in nfp_flower_merge_offloaded_flows()
1038 merge_flow->tc_flower_cookie = (unsigned long)merge_flow; in nfp_flower_merge_offloaded_flows()
1039 merge_flow->ingress_dev = sub_flow1->ingress_dev; in nfp_flower_merge_offloaded_flows()
1041 memcpy(merge_flow->unmasked_data, sub_flow1->unmasked_data, in nfp_flower_merge_offloaded_flows()
1042 sub_flow1->meta.key_len); in nfp_flower_merge_offloaded_flows()
1043 memcpy(merge_flow->mask_data, sub_flow1->mask_data, in nfp_flower_merge_offloaded_flows()
1044 sub_flow1->meta.mask_len); in nfp_flower_merge_offloaded_flows()
1058 err = nfp_compile_flow_metadata(app, merge_flow->tc_flower_cookie, merge_flow, in nfp_flower_merge_offloaded_flows()
1059 merge_flow->ingress_dev, NULL); in nfp_flower_merge_offloaded_flows()
1063 err = rhashtable_insert_fast(&priv->flow_table, &merge_flow->fl_node, in nfp_flower_merge_offloaded_flows()
1070 err = -ENOMEM; in nfp_flower_merge_offloaded_flows()
1073 merge_info->parent_ctx = parent_ctx; in nfp_flower_merge_offloaded_flows()
1074 err = rhashtable_insert_fast(&priv->merge_table, &merge_info->ht_node, in nfp_flower_merge_offloaded_flows()
1084 merge_flow->in_hw = true; in nfp_flower_merge_offloaded_flows()
1085 sub_flow1->in_hw = false; in nfp_flower_merge_offloaded_flows()
1090 WARN_ON_ONCE(rhashtable_remove_fast(&priv->merge_table, in nfp_flower_merge_offloaded_flows()
1091 &merge_info->ht_node, in nfp_flower_merge_offloaded_flows()
1096 WARN_ON_ONCE(rhashtable_remove_fast(&priv->flow_table, in nfp_flower_merge_offloaded_flows()
1097 &merge_flow->fl_node, in nfp_flower_merge_offloaded_flows()
1106 kfree(merge_flow->action_data); in nfp_flower_merge_offloaded_flows()
1107 kfree(merge_flow->mask_data); in nfp_flower_merge_offloaded_flows()
1108 kfree(merge_flow->unmasked_data); in nfp_flower_merge_offloaded_flows()
1120 * Verifies the flow as a pre-tunnel rule.
1122 * Return: negative value on error, 0 if verified.
1130 struct nfp_flower_priv *priv = app->priv; in nfp_flower_validate_pre_tun_rule()
1133 u8 *ext = flow->unmasked_data; in nfp_flower_validate_pre_tun_rule()
1135 u8 *mask = flow->mask_data; in nfp_flower_validate_pre_tun_rule()
1140 meta_tci = (struct nfp_flower_meta_tci *)flow->unmasked_data; in nfp_flower_validate_pre_tun_rule()
1141 key_layer = key_ls->key_layer; in nfp_flower_validate_pre_tun_rule()
1142 if (!(priv->flower_ext_feats & NFP_FL_FEATS_VLAN_QINQ)) { in nfp_flower_validate_pre_tun_rule()
1143 if (meta_tci->tci & cpu_to_be16(NFP_FLOWER_MASK_VLAN_PRESENT)) { in nfp_flower_validate_pre_tun_rule()
1144 u16 vlan_tci = be16_to_cpu(meta_tci->tci); in nfp_flower_validate_pre_tun_rule()
1147 flow->pre_tun_rule.vlan_tci = cpu_to_be16(vlan_tci); in nfp_flower_validate_pre_tun_rule()
1150 flow->pre_tun_rule.vlan_tci = cpu_to_be16(0xffff); in nfp_flower_validate_pre_tun_rule()
1155 NL_SET_ERR_MSG_MOD(extack, "unsupported pre-tunnel rule: too many match fields"); in nfp_flower_validate_pre_tun_rule()
1156 return -EOPNOTSUPP; in nfp_flower_validate_pre_tun_rule()
1157 } else if (key_ls->key_layer_two & ~NFP_FLOWER_LAYER2_QINQ) { in nfp_flower_validate_pre_tun_rule()
1158 NL_SET_ERR_MSG_MOD(extack, "unsupported pre-tunnel rule: non-vlan in extended match fields"); in nfp_flower_validate_pre_tun_rule()
1159 return -EOPNOTSUPP; in nfp_flower_validate_pre_tun_rule()
1163 NL_SET_ERR_MSG_MOD(extack, "unsupported pre-tunnel rule: MAC fields match required"); in nfp_flower_validate_pre_tun_rule()
1164 return -EOPNOTSUPP; in nfp_flower_validate_pre_tun_rule()
1169 …NL_SET_ERR_MSG_MOD(extack, "unsupported pre-tunnel rule: match on ipv4/ipv6 eth_type must be prese… in nfp_flower_validate_pre_tun_rule()
1170 return -EOPNOTSUPP; in nfp_flower_validate_pre_tun_rule()
1174 flow->pre_tun_rule.is_ipv6 = true; in nfp_flower_validate_pre_tun_rule()
1176 flow->pre_tun_rule.is_ipv6 = false; in nfp_flower_validate_pre_tun_rule()
1181 if (key_ls->key_layer_two) { in nfp_flower_validate_pre_tun_rule()
1190 if (!is_broadcast_ether_addr(&mac->mac_dst[0])) { in nfp_flower_validate_pre_tun_rule()
1191 NL_SET_ERR_MSG_MOD(extack, "unsupported pre-tunnel rule: dest MAC field must not be masked"); in nfp_flower_validate_pre_tun_rule()
1192 return -EOPNOTSUPP; in nfp_flower_validate_pre_tun_rule()
1199 if (priv->flower_ext_feats & NFP_FL_FEATS_DECAP_V2) { in nfp_flower_validate_pre_tun_rule()
1201 if (!is_broadcast_ether_addr(&mac->mac_src[0])) { in nfp_flower_validate_pre_tun_rule()
1203 "unsupported pre-tunnel rule: source MAC field must not be masked"); in nfp_flower_validate_pre_tun_rule()
1204 return -EOPNOTSUPP; in nfp_flower_validate_pre_tun_rule()
1208 if (mac->mpls_lse) { in nfp_flower_validate_pre_tun_rule()
1209 NL_SET_ERR_MSG_MOD(extack, "unsupported pre-tunnel rule: MPLS not supported"); in nfp_flower_validate_pre_tun_rule()
1210 return -EOPNOTSUPP; in nfp_flower_validate_pre_tun_rule()
1215 if (memcmp(&mac->mac_dst[0], flow->pre_tun_rule.dev->dev_addr, 6)) { in nfp_flower_validate_pre_tun_rule()
1217 "unsupported pre-tunnel rule: dest MAC must match output dev MAC"); in nfp_flower_validate_pre_tun_rule()
1218 return -EOPNOTSUPP; in nfp_flower_validate_pre_tun_rule()
1222 memcpy(&flow->pre_tun_rule.loc_mac, &mac->mac_dst[0], ETH_ALEN); in nfp_flower_validate_pre_tun_rule()
1223 memcpy(&flow->pre_tun_rule.rem_mac, &mac->mac_src[0], ETH_ALEN); in nfp_flower_validate_pre_tun_rule()
1243 …NL_SET_ERR_MSG_MOD(extack, "unsupported pre-tunnel rule: only flags and proto can be matched in ip… in nfp_flower_validate_pre_tun_rule()
1244 return -EOPNOTSUPP; in nfp_flower_validate_pre_tun_rule()
1250 if ((priv->flower_ext_feats & NFP_FL_FEATS_VLAN_QINQ)) { in nfp_flower_validate_pre_tun_rule()
1251 if (key_ls->key_layer_two & NFP_FLOWER_LAYER2_QINQ) { in nfp_flower_validate_pre_tun_rule()
1258 vlan_tci = be16_to_cpu(vlan_tags->outer_tci); in nfp_flower_validate_pre_tun_rule()
1259 vlan_tpid = be16_to_cpu(vlan_tags->outer_tpid); in nfp_flower_validate_pre_tun_rule()
1262 flow->pre_tun_rule.vlan_tci = cpu_to_be16(vlan_tci); in nfp_flower_validate_pre_tun_rule()
1263 flow->pre_tun_rule.vlan_tpid = cpu_to_be16(vlan_tpid); in nfp_flower_validate_pre_tun_rule()
1266 flow->pre_tun_rule.vlan_tci = cpu_to_be16(0xffff); in nfp_flower_validate_pre_tun_rule()
1267 flow->pre_tun_rule.vlan_tpid = cpu_to_be16(0xffff); in nfp_flower_validate_pre_tun_rule()
1273 act = (struct nfp_fl_act_head *)&flow->action_data[act_offset]; in nfp_flower_validate_pre_tun_rule()
1275 if (act->jump_id != NFP_FL_ACTION_OPCODE_POP_VLAN) { in nfp_flower_validate_pre_tun_rule()
1276 …NL_SET_ERR_MSG_MOD(extack, "unsupported pre-tunnel rule: match on VLAN must have VLAN pop as first… in nfp_flower_validate_pre_tun_rule()
1277 return -EOPNOTSUPP; in nfp_flower_validate_pre_tun_rule()
1280 act_offset += act->len_lw << NFP_FL_LW_SIZ; in nfp_flower_validate_pre_tun_rule()
1281 act = (struct nfp_fl_act_head *)&flow->action_data[act_offset]; in nfp_flower_validate_pre_tun_rule()
1284 if (act->jump_id != NFP_FL_ACTION_OPCODE_OUTPUT) { in nfp_flower_validate_pre_tun_rule()
1285 …NL_SET_ERR_MSG_MOD(extack, "unsupported pre-tunnel rule: non egress action detected where egress w… in nfp_flower_validate_pre_tun_rule()
1286 return -EOPNOTSUPP; in nfp_flower_validate_pre_tun_rule()
1289 act_offset += act->len_lw << NFP_FL_LW_SIZ; in nfp_flower_validate_pre_tun_rule()
1292 if (act_offset != flow->meta.act_len) { in nfp_flower_validate_pre_tun_rule()
1293 NL_SET_ERR_MSG_MOD(extack, "unsupported pre-tunnel rule: egress is not the last action"); in nfp_flower_validate_pre_tun_rule()
1294 return -EOPNOTSUPP; in nfp_flower_validate_pre_tun_rule()
1303 struct flow_dissector *dissector = rule->match.dissector; in offload_pre_check()
1306 if (dissector->used_keys & BIT(FLOW_DISSECTOR_KEY_CT)) { in offload_pre_check()
1313 if (flow->common.chain_index) in offload_pre_check()
1320 * nfp_flower_add_offload() - Adds a new flow to hardware.
1335 struct nfp_flower_priv *priv = app->priv; in nfp_flower_add_offload()
1342 extack = flow->common.extack; in nfp_flower_add_offload()
1353 return -EOPNOTSUPP; in nfp_flower_add_offload()
1357 return -ENOMEM; in nfp_flower_add_offload()
1366 err = -ENOMEM; in nfp_flower_add_offload()
1379 if (flow_pay->pre_tun_rule.dev) { in nfp_flower_add_offload()
1385 err = nfp_compile_flow_metadata(app, flow->cookie, flow_pay, netdev, extack); in nfp_flower_add_offload()
1389 flow_pay->tc_flower_cookie = flow->cookie; in nfp_flower_add_offload()
1390 err = rhashtable_insert_fast(&priv->flow_table, &flow_pay->fl_node, in nfp_flower_add_offload()
1397 if (flow_pay->pre_tun_rule.dev) { in nfp_flower_add_offload()
1398 if (priv->flower_ext_feats & NFP_FL_FEATS_DECAP_V2) { in nfp_flower_add_offload()
1403 err = -ENOMEM; in nfp_flower_add_offload()
1406 predt->flow_pay = flow_pay; in nfp_flower_add_offload()
1407 INIT_LIST_HEAD(&predt->nn_list); in nfp_flower_add_offload()
1408 spin_lock_bh(&priv->predt_lock); in nfp_flower_add_offload()
1409 list_add(&predt->list_head, &priv->predt_list); in nfp_flower_add_offload()
1410 flow_pay->pre_tun_rule.predt = predt; in nfp_flower_add_offload()
1412 spin_unlock_bh(&priv->predt_lock); in nfp_flower_add_offload()
1425 port->tc_offload_cnt++; in nfp_flower_add_offload()
1427 flow_pay->in_hw = true; in nfp_flower_add_offload()
1435 WARN_ON_ONCE(rhashtable_remove_fast(&priv->flow_table, in nfp_flower_add_offload()
1436 &flow_pay->fl_node, in nfp_flower_add_offload()
1441 if (flow_pay->nfp_tun_ipv6) in nfp_flower_add_offload()
1442 nfp_tunnel_put_ipv6_off(app, flow_pay->nfp_tun_ipv6); in nfp_flower_add_offload()
1443 kfree(flow_pay->action_data); in nfp_flower_add_offload()
1444 kfree(flow_pay->mask_data); in nfp_flower_add_offload()
1445 kfree(flow_pay->unmasked_data); in nfp_flower_add_offload()
1457 struct nfp_flower_priv *priv = app->priv; in nfp_flower_remove_merge_flow()
1465 link = list_first_entry(&merge_flow->linked_flows, in nfp_flower_remove_merge_flow()
1467 origin = link->sub_flow.flow; in nfp_flower_remove_merge_flow()
1469 /* Re-add rule the merge had overwritten if it has not been deleted. */ in nfp_flower_remove_merge_flow()
1492 origin->in_hw = true; in nfp_flower_remove_merge_flow()
1497 list_for_each_entry_safe(link, temp, &merge_flow->linked_flows, in nfp_flower_remove_merge_flow()
1499 u32 ctx_id = be32_to_cpu(link->sub_flow.flow->meta.host_ctx_id); in nfp_flower_remove_merge_flow()
1505 merge_info = rhashtable_lookup_fast(&priv->merge_table, in nfp_flower_remove_merge_flow()
1509 WARN_ON_ONCE(rhashtable_remove_fast(&priv->merge_table, in nfp_flower_remove_merge_flow()
1510 &merge_info->ht_node, in nfp_flower_remove_merge_flow()
1515 kfree(merge_flow->action_data); in nfp_flower_remove_merge_flow()
1516 kfree(merge_flow->mask_data); in nfp_flower_remove_merge_flow()
1517 kfree(merge_flow->unmasked_data); in nfp_flower_remove_merge_flow()
1518 WARN_ON_ONCE(rhashtable_remove_fast(&priv->flow_table, in nfp_flower_remove_merge_flow()
1519 &merge_flow->fl_node, in nfp_flower_remove_merge_flow()
1531 list_for_each_entry_safe(link, temp, &sub_flow->linked_flows, in nfp_flower_del_linked_merge_flows()
1534 link->merge_flow.flow); in nfp_flower_del_linked_merge_flows()
1538 * nfp_flower_del_offload() - Removes a flow from hardware.
1552 struct nfp_flower_priv *priv = app->priv; in nfp_flower_del_offload()
1559 extack = flow->common.extack; in nfp_flower_del_offload()
1564 ct_map_ent = rhashtable_lookup_fast(&priv->ct_map_table, &flow->cookie, in nfp_flower_del_offload()
1571 nfp_flow = nfp_flower_search_fl_table(app, flow->cookie, netdev); in nfp_flower_del_offload()
1574 return -ENOENT; in nfp_flower_del_offload()
1581 if (nfp_flow->nfp_tun_ipv4_addr) in nfp_flower_del_offload()
1582 nfp_tunnel_del_ipv4_off(app, nfp_flow->nfp_tun_ipv4_addr); in nfp_flower_del_offload()
1584 if (nfp_flow->nfp_tun_ipv6) in nfp_flower_del_offload()
1585 nfp_tunnel_put_ipv6_off(app, nfp_flow->nfp_tun_ipv6); in nfp_flower_del_offload()
1587 if (!nfp_flow->in_hw) { in nfp_flower_del_offload()
1592 if (nfp_flow->pre_tun_rule.dev) { in nfp_flower_del_offload()
1593 if (priv->flower_ext_feats & NFP_FL_FEATS_DECAP_V2) { in nfp_flower_del_offload()
1596 predt = nfp_flow->pre_tun_rule.predt; in nfp_flower_del_offload()
1598 spin_lock_bh(&priv->predt_lock); in nfp_flower_del_offload()
1600 list_del(&predt->list_head); in nfp_flower_del_offload()
1601 spin_unlock_bh(&priv->predt_lock); in nfp_flower_del_offload()
1616 port->tc_offload_cnt--; in nfp_flower_del_offload()
1617 kfree(nfp_flow->action_data); in nfp_flower_del_offload()
1618 kfree(nfp_flow->mask_data); in nfp_flower_del_offload()
1619 kfree(nfp_flow->unmasked_data); in nfp_flower_del_offload()
1620 WARN_ON_ONCE(rhashtable_remove_fast(&priv->flow_table, in nfp_flower_del_offload()
1621 &nfp_flow->fl_node, in nfp_flower_del_offload()
1631 struct nfp_flower_priv *priv = app->priv; in __nfp_flower_update_merge_stats()
1637 ctx_id = be32_to_cpu(merge_flow->meta.host_ctx_id); in __nfp_flower_update_merge_stats()
1638 pkts = priv->stats[ctx_id].pkts; in __nfp_flower_update_merge_stats()
1642 bytes = priv->stats[ctx_id].bytes; in __nfp_flower_update_merge_stats()
1643 used = priv->stats[ctx_id].used; in __nfp_flower_update_merge_stats()
1646 priv->stats[ctx_id].pkts = 0; in __nfp_flower_update_merge_stats()
1647 priv->stats[ctx_id].bytes = 0; in __nfp_flower_update_merge_stats()
1653 list_for_each_entry(link, &merge_flow->linked_flows, merge_flow.list) { in __nfp_flower_update_merge_stats()
1654 sub_flow = link->sub_flow.flow; in __nfp_flower_update_merge_stats()
1655 ctx_id = be32_to_cpu(sub_flow->meta.host_ctx_id); in __nfp_flower_update_merge_stats()
1656 priv->stats[ctx_id].pkts += pkts; in __nfp_flower_update_merge_stats()
1657 priv->stats[ctx_id].bytes += bytes; in __nfp_flower_update_merge_stats()
1658 priv->stats[ctx_id].used = max_t(u64, used, in __nfp_flower_update_merge_stats()
1659 priv->stats[ctx_id].used); in __nfp_flower_update_merge_stats()
1670 list_for_each_entry(link, &sub_flow->linked_flows, sub_flow.list) in nfp_flower_update_merge_stats()
1671 __nfp_flower_update_merge_stats(app, link->merge_flow.flow); in nfp_flower_update_merge_stats()
1675 * nfp_flower_get_stats() - Populates flow stats obtained from hardware.
1689 struct nfp_flower_priv *priv = app->priv; in nfp_flower_get_stats()
1696 ct_map_ent = rhashtable_lookup_fast(&priv->ct_map_table, &flow->cookie, in nfp_flower_get_stats()
1701 extack = flow->common.extack; in nfp_flower_get_stats()
1702 nfp_flow = nfp_flower_search_fl_table(app, flow->cookie, netdev); in nfp_flower_get_stats()
1705 return -EINVAL; in nfp_flower_get_stats()
1708 ctx_id = be32_to_cpu(nfp_flow->meta.host_ctx_id); in nfp_flower_get_stats()
1710 spin_lock_bh(&priv->stats_lock); in nfp_flower_get_stats()
1712 if (!list_empty(&nfp_flow->linked_flows)) in nfp_flower_get_stats()
1715 flow_stats_update(&flow->stats, priv->stats[ctx_id].bytes, in nfp_flower_get_stats()
1716 priv->stats[ctx_id].pkts, 0, priv->stats[ctx_id].used, in nfp_flower_get_stats()
1719 priv->stats[ctx_id].pkts = 0; in nfp_flower_get_stats()
1720 priv->stats[ctx_id].bytes = 0; in nfp_flower_get_stats()
1721 spin_unlock_bh(&priv->stats_lock); in nfp_flower_get_stats()
1730 if (!eth_proto_is_802_3(flower->common.protocol)) in nfp_flower_repr_offload()
1731 return -EOPNOTSUPP; in nfp_flower_repr_offload()
1733 switch (flower->command) { in nfp_flower_repr_offload()
1741 return -EOPNOTSUPP; in nfp_flower_repr_offload()
1751 if (!tc_can_offload_extack(repr->netdev, common->extack)) in nfp_flower_setup_tc_block_cb()
1752 return -EOPNOTSUPP; in nfp_flower_setup_tc_block_cb()
1756 return nfp_flower_repr_offload(repr->app, repr->netdev, in nfp_flower_setup_tc_block_cb()
1759 return nfp_flower_setup_qos_offload(repr->app, repr->netdev, in nfp_flower_setup_tc_block_cb()
1762 return -EOPNOTSUPP; in nfp_flower_setup_tc_block_cb()
1775 if (f->binder_type != FLOW_BLOCK_BINDER_TYPE_CLSACT_INGRESS) in nfp_flower_setup_tc_block()
1776 return -EOPNOTSUPP; in nfp_flower_setup_tc_block()
1778 repr_priv = repr->app_priv; in nfp_flower_setup_tc_block()
1779 repr_priv->block_shared = f->block_shared; in nfp_flower_setup_tc_block()
1780 f->driver_block_list = &nfp_block_cb_list; in nfp_flower_setup_tc_block()
1782 switch (f->command) { in nfp_flower_setup_tc_block()
1786 return -EBUSY; in nfp_flower_setup_tc_block()
1794 list_add_tail(&block_cb->driver_list, &nfp_block_cb_list); in nfp_flower_setup_tc_block()
1797 block_cb = flow_block_cb_lookup(f->block, in nfp_flower_setup_tc_block()
1801 return -ENOENT; in nfp_flower_setup_tc_block()
1804 list_del(&block_cb->driver_list); in nfp_flower_setup_tc_block()
1807 return -EOPNOTSUPP; in nfp_flower_setup_tc_block()
1818 return -EOPNOTSUPP; in nfp_flower_setup_tc()
1833 struct nfp_flower_priv *priv = app->priv; in nfp_flower_indr_block_cb_priv_lookup()
1835 list_for_each_entry(cb_priv, &priv->indr_block_cb_priv, list) in nfp_flower_indr_block_cb_priv_lookup()
1836 if (cb_priv->netdev == netdev) in nfp_flower_indr_block_cb_priv_lookup()
1849 return nfp_flower_repr_offload(priv->app, priv->netdev, in nfp_flower_setup_indr_block_cb()
1852 return -EOPNOTSUPP; in nfp_flower_setup_indr_block_cb()
1860 list_del(&priv->list); in nfp_flower_setup_indr_tc_release()
1870 struct nfp_flower_priv *priv = app->priv; in nfp_flower_setup_indr_tc_block()
1873 if ((f->binder_type != FLOW_BLOCK_BINDER_TYPE_CLSACT_INGRESS && in nfp_flower_setup_indr_tc_block()
1875 (f->binder_type != FLOW_BLOCK_BINDER_TYPE_CLSACT_EGRESS && in nfp_flower_setup_indr_tc_block()
1877 return -EOPNOTSUPP; in nfp_flower_setup_indr_tc_block()
1879 switch (f->command) { in nfp_flower_setup_indr_tc_block()
1886 return -EBUSY; in nfp_flower_setup_indr_tc_block()
1890 return -ENOMEM; in nfp_flower_setup_indr_tc_block()
1892 cb_priv->netdev = netdev; in nfp_flower_setup_indr_tc_block()
1893 cb_priv->app = app; in nfp_flower_setup_indr_tc_block()
1894 list_add(&cb_priv->list, &priv->indr_block_cb_priv); in nfp_flower_setup_indr_tc_block()
1901 list_del(&cb_priv->list); in nfp_flower_setup_indr_tc_block()
1907 list_add_tail(&block_cb->driver_list, &nfp_block_cb_list); in nfp_flower_setup_indr_tc_block()
1912 return -ENOENT; in nfp_flower_setup_indr_tc_block()
1914 block_cb = flow_block_cb_lookup(f->block, in nfp_flower_setup_indr_tc_block()
1918 return -ENOENT; in nfp_flower_setup_indr_tc_block()
1921 list_del(&block_cb->driver_list); in nfp_flower_setup_indr_tc_block()
1924 return -EOPNOTSUPP; in nfp_flower_setup_indr_tc_block()
1933 return -EOPNOTSUPP; in nfp_setup_tc_no_dev()
1939 return -EOPNOTSUPP; in nfp_setup_tc_no_dev()
1953 return -EOPNOTSUPP; in nfp_flower_indr_setup_tc_cb()
1960 return -EOPNOTSUPP; in nfp_flower_indr_setup_tc_cb()