1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright 2020 Mellanox Technologies, Ltd 3 */ 4 5 #include "mlx5_flow_os.h" 6 7 #include <rte_thread.h> 8 9 /* Key of thread specific flow workspace data. */ 10 static rte_thread_key key_workspace; 11 /* Flow workspace global list head for garbage collector. */ 12 static struct mlx5_flow_workspace *gc_head; 13 /* Spinlock for operating flow workspace list. */ 14 static rte_spinlock_t mlx5_flow_workspace_lock = RTE_SPINLOCK_INITIALIZER; 15 16 int 17 mlx5_flow_os_validate_item_esp(const struct rte_eth_dev *dev, 18 const struct rte_flow_item *item, 19 uint64_t item_flags, 20 uint8_t target_protocol, 21 struct rte_flow_error *error) 22 { 23 const struct rte_flow_item_esp *mask = item->mask; 24 const int tunnel = !!(item_flags & MLX5_FLOW_LAYER_TUNNEL); 25 const uint64_t l3m = tunnel ? MLX5_FLOW_LAYER_INNER_L3 : 26 MLX5_FLOW_LAYER_OUTER_L3; 27 const uint64_t l4m = tunnel ? MLX5_FLOW_LAYER_INNER_L4 : 28 MLX5_FLOW_LAYER_OUTER_L4; 29 int ret; 30 31 if (!mlx5_hws_active(dev)) { 32 if (!(item_flags & l3m)) 33 return rte_flow_error_set(error, EINVAL, 34 RTE_FLOW_ERROR_TYPE_ITEM, 35 item, "L3 is mandatory to filter on L4"); 36 } 37 if (item_flags & l4m) 38 return rte_flow_error_set(error, EINVAL, 39 RTE_FLOW_ERROR_TYPE_ITEM, item, 40 "multiple L4 layers not supported"); 41 if (target_protocol != 0xff && target_protocol != IPPROTO_ESP) 42 return rte_flow_error_set(error, EINVAL, 43 RTE_FLOW_ERROR_TYPE_ITEM, item, 44 "protocol filtering not compatible" 45 " with ESP layer"); 46 if (!mask) 47 mask = &rte_flow_item_esp_mask; 48 ret = mlx5_flow_item_acceptable 49 (dev, item, (const uint8_t *)mask, 50 (const uint8_t *)&rte_flow_item_esp_mask, 51 sizeof(struct rte_flow_item_esp), MLX5_ITEM_RANGE_NOT_ACCEPTED, 52 error); 53 if (ret < 0) 54 return ret; 55 return 0; 56 } 57 58 void 59 mlx5_flow_os_workspace_gc_add(struct mlx5_flow_workspace *ws) 60 { 61 rte_spinlock_lock(&mlx5_flow_workspace_lock); 62 ws->gc = gc_head; 63 gc_head = ws; 64 rte_spinlock_unlock(&mlx5_flow_workspace_lock); 65 } 66 67 static void 68 mlx5_flow_os_workspace_gc_release(void) 69 { 70 while (gc_head) { 71 struct mlx5_flow_workspace *wks = gc_head; 72 73 gc_head = wks->gc; 74 flow_release_workspace(wks); 75 } 76 } 77 78 int 79 mlx5_flow_os_init_workspace_once(void) 80 { 81 if (rte_thread_key_create(&key_workspace, NULL)) { 82 DRV_LOG(ERR, "Can't create flow workspace data thread key."); 83 rte_errno = ENOMEM; 84 return -rte_errno; 85 } 86 return 0; 87 } 88 89 void * 90 mlx5_flow_os_get_specific_workspace(void) 91 { 92 return rte_thread_value_get(key_workspace); 93 } 94 95 int 96 mlx5_flow_os_set_specific_workspace(struct mlx5_flow_workspace *data) 97 { 98 return rte_thread_value_set(key_workspace, data); 99 } 100 101 void 102 mlx5_flow_os_release_workspace(void) 103 { 104 rte_thread_key_delete(key_workspace); 105 mlx5_flow_os_workspace_gc_release(); 106 } 107