- Selectors: 'is', 'spec' and 'mask'. 'last' is not supported
- In total, up to 64 bytes of mask is allowed across all headers
-- **1400 and later series VICS with advanced filters enabled**
-
- All the above plus:
-
- - Action: count
-
The VIC performs packet matching after applying VLAN strip. If VLAN
stripping is enabled, EtherType in the ETH item corresponds to the
stripped VLAN header's EtherType. Stripping does not affect the VLAN
void (*free_consistent)(void *priv,
size_t size, void *vaddr,
dma_addr_t dma_handle);
- struct vnic_counter_counts *flow_counters;
- dma_addr_t flow_counters_pa;
- u8 flow_counters_dma_active;
};
#define VNIC_MAX_RES_HDR_SIZE \
sizeof(struct vnic_resource) * RES_TYPE_MAX)
#define VNIC_RES_STRIDE 128
-#define VNIC_MAX_FLOW_COUNTERS 2048
-
void *vnic_dev_priv(struct vnic_dev *vdev)
{
return vdev->priv;
return vnic_dev_cmd(vdev, CMD_STATS_DUMP, &a0, &a1, wait);
}
-/*
- * Configure counter DMA
- */
-int vnic_dev_counter_dma_cfg(struct vnic_dev *vdev, u32 period,
- u32 num_counters)
-{
- u64 args[3];
- int wait = 1000;
- int err;
-
- if (num_counters > VNIC_MAX_FLOW_COUNTERS)
- return -ENOMEM;
- if (period > 0 && (period < VNIC_COUNTER_DMA_MIN_PERIOD ||
- num_counters == 0))
- return -EINVAL;
-
- args[0] = num_counters;
- args[1] = vdev->flow_counters_pa;
- args[2] = period;
- err = vnic_dev_cmd_args(vdev, CMD_COUNTER_DMA_CONFIG, args, 3, wait);
-
- /* record if DMAs need to be stopped on close */
- if (!err)
- vdev->flow_counters_dma_active = (num_counters != 0 &&
- period != 0);
-
- return err;
-}
-
int vnic_dev_close(struct vnic_dev *vdev)
{
u64 a0 = 0, a1 = 0;
return vdev->stats == NULL ? -ENOMEM : 0;
}
-/*
- * Initialize for up to VNIC_MAX_FLOW_COUNTERS
- */
-int vnic_dev_alloc_counter_mem(struct vnic_dev *vdev)
-{
- char name[NAME_MAX];
- static u32 instance;
-
- snprintf((char *)name, sizeof(name), "vnic_flow_ctrs-%u", instance++);
- vdev->flow_counters = vdev->alloc_consistent(vdev->priv,
- sizeof(struct vnic_counter_counts)
- * VNIC_MAX_FLOW_COUNTERS,
- &vdev->flow_counters_pa,
- (u8 *)name);
- vdev->flow_counters_dma_active = 0;
- return vdev->flow_counters == NULL ? -ENOMEM : 0;
-}
-
void vnic_dev_unregister(struct vnic_dev *vdev)
{
if (vdev) {
vdev->free_consistent(vdev->priv,
sizeof(struct vnic_stats),
vdev->stats, vdev->stats_pa);
- if (vdev->flow_counters) {
- /* turn off counter DMAs before freeing memory */
- if (vdev->flow_counters_dma_active)
- vnic_dev_counter_dma_cfg(vdev, 0, 0);
-
- vdev->free_consistent(vdev->priv,
- sizeof(struct vnic_counter_counts)
- * VNIC_MAX_FLOW_COUNTERS,
- vdev->flow_counters, vdev->flow_counters_pa);
- }
if (vdev->fw_info)
vdev->free_consistent(vdev->priv,
sizeof(struct vnic_devcmd_fw_info),
(a1 & (FEATURE_VXLAN_IPV6 | FEATURE_VXLAN_MULTI_WQ)) ==
(FEATURE_VXLAN_IPV6 | FEATURE_VXLAN_MULTI_WQ);
}
-
-bool vnic_dev_counter_alloc(struct vnic_dev *vdev, uint32_t *idx)
-{
- u64 a0 = 0;
- u64 a1 = 0;
- int wait = 1000;
-
- if (vnic_dev_cmd(vdev, CMD_COUNTER_ALLOC, &a0, &a1, wait))
- return false;
- *idx = (uint32_t)a0;
- return true;
-}
-
-bool vnic_dev_counter_free(struct vnic_dev *vdev, uint32_t idx)
-{
- u64 a0 = idx;
- u64 a1 = 0;
- int wait = 1000;
-
- return vnic_dev_cmd(vdev, CMD_COUNTER_FREE, &a0, &a1,
- wait) == 0;
-}
-
-bool vnic_dev_counter_query(struct vnic_dev *vdev, uint32_t idx,
- bool reset, uint64_t *packets, uint64_t *bytes)
-{
- u64 a0 = idx;
- u64 a1 = reset ? 1 : 0;
- int wait = 1000;
-
- if (reset) {
- /* query/reset returns updated counters */
- if (vnic_dev_cmd(vdev, CMD_COUNTER_QUERY, &a0, &a1, wait))
- return false;
- *packets = a0;
- *bytes = a1;
- } else {
- /* Get values DMA'd from the adapter */
- *packets = vdev->flow_counters[idx].vcc_packets;
- *bytes = vdev->flow_counters[idx].vcc_bytes;
- }
- return true;
-}
void *value);
int vnic_dev_stats_clear(struct vnic_dev *vdev);
int vnic_dev_stats_dump(struct vnic_dev *vdev, struct vnic_stats **stats);
-int vnic_dev_counter_dma_cfg(struct vnic_dev *vdev, u32 period,
- u32 num_counters);
int vnic_dev_hang_notify(struct vnic_dev *vdev);
int vnic_dev_packet_filter(struct vnic_dev *vdev, int directed, int multicast,
int broadcast, int promisc, int allmulti);
unsigned int num_bars);
struct rte_pci_device *vnic_dev_get_pdev(struct vnic_dev *vdev);
int vnic_dev_alloc_stats_mem(struct vnic_dev *vdev);
-int vnic_dev_alloc_counter_mem(struct vnic_dev *vdev);
int vnic_dev_cmd_init(struct vnic_dev *vdev, int fallback);
int vnic_dev_get_size(void);
int vnic_dev_int13(struct vnic_dev *vdev, u64 arg, u32 op);
int vnic_dev_overlay_offload_cfg(struct vnic_dev *vdev, u8 overlay,
u16 vxlan_udp_port_number);
int vnic_dev_capable_vxlan(struct vnic_dev *vdev);
-bool vnic_dev_counter_alloc(struct vnic_dev *vdev, uint32_t *idx);
-bool vnic_dev_counter_free(struct vnic_dev *vdev, uint32_t idx);
-bool vnic_dev_counter_query(struct vnic_dev *vdev, uint32_t idx,
- bool reset, uint64_t *packets, uint64_t *bytes);
-
#endif /* _VNIC_DEV_H_ */
* a3 = bitmask of supported actions
*/
CMD_ADD_ADV_FILTER = _CMDC(_CMD_DIR_RW, _CMD_VTYPE_ENET, 77),
-
- /*
- * Allocate a counter for use with CMD_ADD_FILTER
- * out:(u32) a0 = counter index
- */
- CMD_COUNTER_ALLOC = _CMDC(_CMD_DIR_READ, _CMD_VTYPE_ENET, 85),
-
- /*
- * Free a counter
- * in: (u32) a0 = counter_id
- */
- CMD_COUNTER_FREE = _CMDC(_CMD_DIR_WRITE, _CMD_VTYPE_ENET, 86),
-
- /*
- * Read a counter
- * in: (u32) a0 = counter_id
- * (u32) a1 = clear counter if non-zero
- * out:(u64) a0 = packet count
- * (u64) a1 = byte count
- */
- CMD_COUNTER_QUERY = _CMDC(_CMD_DIR_RW, _CMD_VTYPE_ENET, 87),
-
- /*
- * Configure periodic counter DMA. This will trigger an immediate
- * DMA of the counters (unless period == 0), and then schedule a DMA
- * of the counters every <period> seconds until disdabled.
- * Each new COUNTER_DMA_CONFIG will override all previous commands on
- * this vnic.
- * Setting a2 (period) = 0 will disable periodic DMAs
- * If a0 (num_counters) != 0, an immediate DMA will always be done,
- * irrespective of the value in a2.
- * in: (u32) a0 = number of counters to DMA
- * (u64) a1 = host target DMA address
- * (u32) a2 = DMA period in milliseconds (0 to disable)
- */
- CMD_COUNTER_DMA_CONFIG = _CMDC(_CMD_DIR_WRITE, _CMD_VTYPE_ENET, 88),
-#define VNIC_COUNTER_DMA_MIN_PERIOD 500
-
- /*
- * Clear all counters on a vnic
- */
- CMD_COUNTER_CLEAR_ALL = _CMDC(_CMD_DIR_NONE, _CMD_VTYPE_ENET, 89),
};
/* Modes for exchanging advanced filter capabilities. The modes supported by
#define FILTER_ACTION_RQ_STEERING_FLAG (1 << 0)
#define FILTER_ACTION_FILTER_ID_FLAG (1 << 1)
#define FILTER_ACTION_DROP_FLAG (1 << 2)
-#define FILTER_ACTION_COUNTER_FLAG (1 << 3)
#define FILTER_ACTION_V2_ALL (FILTER_ACTION_RQ_STEERING_FLAG \
- | FILTER_ACTION_FILTER_ID_FLAG \
| FILTER_ACTION_DROP_FLAG \
- | FILTER_ACTION_COUNTER_FLAG)
+ | FILTER_ACTION_FILTER_ID_FLAG)
/* Version 2 of filter action must be a strict extension of struct filter_action
* where the first fields exactly match in size and meaning.
u32 rq_idx;
u32 flags; /* use FILTER_ACTION_XXX_FLAG defines */
u16 filter_id;
- u32 counter_index;
- uint8_t reserved[28]; /* for future expansion */
+ uint8_t reserved[32]; /* for future expansion */
} __attribute__((packed));
/* Specifies the filter type. */
GRPINTR_UPD_VECT,
} grpintr_subcmd_t;
-/*
- * Structure for counter DMA
- * (DMAed by CMD_COUNTER_DMA_CONFIG)
- */
-struct vnic_counter_counts {
- u64 vcc_packets;
- u64 vcc_bytes;
-};
-
#endif /* _VNIC_DEVCMD_H_ */
#define PAGE_ROUND_UP(x) \
((((unsigned long)(x)) + ENIC_PAGE_SIZE-1) & (~(ENIC_PAGE_SIZE-1)))
-/* must be >= VNIC_COUNTER_DMA_MIN_PERIOD */
-#define VNIC_FLOW_COUNTER_UPDATE_MSECS 500
-
#define ENICPMD_VFIO_PATH "/dev/vfio/vfio"
/*#define ENIC_DESC_COUNT_MAKE_ODD (x) do{if ((~(x)) & 1) { (x)--; } }while(0)*/
LIST_ENTRY(rte_flow) next;
u16 enic_filter_id;
struct filter_v2 enic_filter;
- int counter_idx; /* NIC allocated counter index (-1 = invalid) */
};
/* Per-instance private data structure */
rte_spinlock_t mtu_lock;
LIST_HEAD(enic_flows, rte_flow) flows;
- int max_flow_counter;
rte_spinlock_t flows_lock;
/* RSS */
RTE_FLOW_ACTION_TYPE_END,
};
-static const enum rte_flow_action_type enic_supported_actions_v2_count[] = {
- RTE_FLOW_ACTION_TYPE_QUEUE,
- RTE_FLOW_ACTION_TYPE_MARK,
- RTE_FLOW_ACTION_TYPE_FLAG,
- RTE_FLOW_ACTION_TYPE_DROP,
- RTE_FLOW_ACTION_TYPE_COUNT,
- RTE_FLOW_ACTION_TYPE_RSS,
- RTE_FLOW_ACTION_TYPE_PASSTHRU,
- RTE_FLOW_ACTION_TYPE_END,
-};
-
/** Action capabilities indexed by NIC version information */
static const struct enic_action_cap enic_action_cap[] = {
[FILTER_ACTION_RQ_STEERING_FLAG] = {
.actions = enic_supported_actions_v2_drop,
.copy_fn = enic_copy_action_v2,
},
- [FILTER_ACTION_COUNTER_FLAG] = {
- .actions = enic_supported_actions_v2_count,
- .copy_fn = enic_copy_action_v2,
- },
};
static int
enic_action->flags |= FILTER_ACTION_DROP_FLAG;
break;
}
- case RTE_FLOW_ACTION_TYPE_COUNT: {
- enic_action->flags |= FILTER_ACTION_COUNTER_FLAG;
- break;
- }
case RTE_FLOW_ACTION_TYPE_RSS: {
const struct rte_flow_action_rss *rss =
(const struct rte_flow_action_rss *)
uint8_t actions;
actions = enic->filter_actions;
- if (actions & FILTER_ACTION_COUNTER_FLAG)
- ea = &enic_action_cap[FILTER_ACTION_COUNTER_FLAG];
- else if (actions & FILTER_ACTION_DROP_FLAG)
+ if (actions & FILTER_ACTION_DROP_FLAG)
ea = &enic_action_cap[FILTER_ACTION_DROP_FLAG];
else if (actions & FILTER_ACTION_FILTER_ID_FLAG)
ea = &enic_action_cap[FILTER_ACTION_FILTER_ID_FLAG];
{
struct rte_flow *flow;
int err;
- uint16_t entry;
- int ctr_idx;
- int last_max_flow_ctr;
+ u16 entry;
FLOW_TRACE();
return NULL;
}
- flow->counter_idx = -1;
- last_max_flow_ctr = -1;
- if (enic_action->flags & FILTER_ACTION_COUNTER_FLAG) {
- if (!vnic_dev_counter_alloc(enic->vdev, (uint32_t *)&ctr_idx)) {
- rte_flow_error_set(error, ENOMEM,
- RTE_FLOW_ERROR_TYPE_ACTION_CONF,
- NULL, "cannot allocate counter");
- goto unwind_flow_alloc;
- }
- flow->counter_idx = ctr_idx;
- enic_action->counter_index = ctr_idx;
-
- /* If index is the largest, increase the counter DMA size */
- if (ctr_idx > enic->max_flow_counter) {
- err = vnic_dev_counter_dma_cfg(enic->vdev,
- VNIC_FLOW_COUNTER_UPDATE_MSECS,
- ctr_idx + 1);
- if (err) {
- rte_flow_error_set(error, -err,
- RTE_FLOW_ERROR_TYPE_ACTION_CONF,
- NULL, "counter DMA config failed");
- goto unwind_ctr_alloc;
- }
- last_max_flow_ctr = enic->max_flow_counter;
- enic->max_flow_counter = ctr_idx;
- }
- }
-
/* entry[in] is the queue id, entry[out] is the filter Id for delete */
entry = enic_action->rq_idx;
err = vnic_dev_classifier(enic->vdev, CLSF_ADD, &entry, enic_filter,
if (err) {
rte_flow_error_set(error, -err, RTE_FLOW_ERROR_TYPE_HANDLE,
NULL, "vnic_dev_classifier error");
- goto unwind_ctr_dma_cfg;
+ rte_free(flow);
+ return NULL;
}
flow->enic_filter_id = entry;
flow->enic_filter = *enic_filter;
-
return flow;
-
-/* unwind if there are errors */
-unwind_ctr_dma_cfg:
- if (last_max_flow_ctr != -1) {
- /* reduce counter DMA size */
- vnic_dev_counter_dma_cfg(enic->vdev,
- VNIC_FLOW_COUNTER_UPDATE_MSECS,
- last_max_flow_ctr + 1);
- enic->max_flow_counter = last_max_flow_ctr;
- }
-unwind_ctr_alloc:
- if (flow->counter_idx != -1)
- vnic_dev_counter_free(enic->vdev, ctr_idx);
-unwind_flow_alloc:
- rte_free(flow);
- return NULL;
}
/**
NULL, "vnic_dev_classifier failed");
return -err;
}
-
- if (flow->counter_idx != -1) {
- if (!vnic_dev_counter_free(enic->vdev, flow->counter_idx))
- dev_err(enic, "counter free failed, idx: %d\n",
- flow->counter_idx);
- flow->counter_idx = -1;
- }
return 0;
}
return 0;
}
-static int
-enic_flow_query_count(struct rte_eth_dev *dev,
- struct rte_flow *flow, void *data,
- struct rte_flow_error *error)
-{
- struct enic *enic = pmd_priv(dev);
- struct rte_flow_query_count *query;
- uint64_t packets, bytes;
-
- FLOW_TRACE();
-
- if (flow->counter_idx == -1) {
- return rte_flow_error_set(error, ENOTSUP,
- RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
- NULL,
- "flow does not have counter");
- }
- query = (struct rte_flow_query_count *)data;
- if (!vnic_dev_counter_query(enic->vdev, flow->counter_idx,
- !!query->reset, &packets, &bytes)) {
- return rte_flow_error_set
- (error, EINVAL,
- RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
- NULL,
- "cannot read counter");
- }
- query->hits_set = 1;
- query->bytes_set = 1;
- query->hits = packets;
- query->bytes = bytes;
- return 0;
-}
-
-static int
-enic_flow_query(struct rte_eth_dev *dev,
- struct rte_flow *flow,
- const struct rte_flow_action *actions,
- void *data,
- struct rte_flow_error *error)
-{
- int ret = 0;
-
- FLOW_TRACE();
-
- for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++) {
- switch (actions->type) {
- case RTE_FLOW_ACTION_TYPE_VOID:
- break;
- case RTE_FLOW_ACTION_TYPE_COUNT:
- ret = enic_flow_query_count(dev, flow, data, error);
- break;
- default:
- return rte_flow_error_set(error, ENOTSUP,
- RTE_FLOW_ERROR_TYPE_ACTION,
- actions,
- "action not supported");
- }
- if (ret < 0)
- return ret;
- }
- return 0;
-}
-
/**
* Flow callback registration.
*
.create = enic_flow_create,
.destroy = enic_flow_destroy,
.flush = enic_flow_flush,
- .query = enic_flow_query,
};
LIST_INIT(&enic->flows);
rte_spinlock_init(&enic->flows_lock);
- enic->max_flow_counter = -1;
/* set up link status checking */
vnic_dev_notify_set(enic->vdev, -1); /* No Intr for notify */
enic_free_consistent);
/*
- * Allocate the consistent memory for stats and counters upfront so
- * both primary and secondary processes can access them.
+ * Allocate the consistent memory for stats upfront so both primary and
+ * secondary processes can dump stats.
*/
err = vnic_dev_alloc_stats_mem(enic->vdev);
if (err) {
dev_err(enic, "Failed to allocate cmd memory, aborting\n");
goto err_out_unregister;
}
- err = vnic_dev_alloc_counter_mem(enic->vdev);
- if (err) {
- dev_err(enic, "Failed to allocate counter memory, aborting\n");
- goto err_out_unregister;
- }
-
/* Issue device open to get device in known state */
err = enic_dev_open(enic);
if (err) {
vnic_dev_capable_udp_rss_weak(enic->vdev, &enic->nic_cfg_chk,
&enic->udp_rss_weak);
- dev_info(enic, "Flow api filter mode: %s Actions: %s%s%s%s\n",
+ dev_info(enic, "Flow api filter mode: %s Actions: %s%s%s\n",
((enic->flow_filter_mode == FILTER_DPDK_1) ? "DPDK" :
((enic->flow_filter_mode == FILTER_USNIC_IP) ? "USNIC" :
((enic->flow_filter_mode == FILTER_IPV4_5TUPLE) ? "5TUPLE" :
((enic->filter_actions & FILTER_ACTION_FILTER_ID_FLAG) ?
"tag " : ""),
((enic->filter_actions & FILTER_ACTION_DROP_FLAG) ?
- "drop " : ""),
- ((enic->filter_actions & FILTER_ACTION_COUNTER_FLAG) ?
- "count " : ""));
+ "drop " : ""));
c->wq_desc_count =
min_t(u32, ENIC_MAX_WQ_DESCS,