X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=lib%2Flibrte_pmd_ixgbe%2Fixgbe_ethdev.c;h=6e7a1ab378df1aacaba2b8468b738828493adb2d;hb=54292e9520e0;hp=e36cdf541b080ad94cb522f2e96e894f0cdf5b55;hpb=4e4510dfff548eab47da112b8fb7c48a33f0f959;p=dpdk.git diff --git a/lib/librte_pmd_ixgbe/ixgbe_ethdev.c b/lib/librte_pmd_ixgbe/ixgbe_ethdev.c index e36cdf541b..6e7a1ab378 100644 --- a/lib/librte_pmd_ixgbe/ixgbe_ethdev.c +++ b/lib/librte_pmd_ixgbe/ixgbe_ethdev.c @@ -226,19 +226,26 @@ static void ixgbevf_add_mac_addr(struct rte_eth_dev *dev, struct ether_addr *mac_addr, uint32_t index, uint32_t pool); static void ixgbevf_remove_mac_addr(struct rte_eth_dev *dev, uint32_t index); -static int ixgbe_add_syn_filter(struct rte_eth_dev *dev, - struct rte_syn_filter *filter, uint16_t rx_queue); -static int ixgbe_remove_syn_filter(struct rte_eth_dev *dev); -static int ixgbe_get_syn_filter(struct rte_eth_dev *dev, - struct rte_syn_filter *filter, uint16_t *rx_queue); -static int ixgbe_add_5tuple_filter(struct rte_eth_dev *dev, uint16_t index, - struct rte_5tuple_filter *filter, uint16_t rx_queue); -static int ixgbe_remove_5tuple_filter(struct rte_eth_dev *dev, - uint16_t index); -static int ixgbe_get_5tuple_filter(struct rte_eth_dev *dev, uint16_t index, - struct rte_5tuple_filter *filter, uint16_t *rx_queue); - -static int ixgbevf_dev_set_mtu(struct rte_eth_dev *dev, uint16_t mtu); +static int ixgbe_syn_filter_set(struct rte_eth_dev *dev, + struct rte_eth_syn_filter *filter, + bool add); +static int ixgbe_syn_filter_get(struct rte_eth_dev *dev, + struct rte_eth_syn_filter *filter); +static int ixgbe_syn_filter_handle(struct rte_eth_dev *dev, + enum rte_filter_op filter_op, + void *arg); +static int ixgbe_add_5tuple_filter(struct rte_eth_dev *dev, + struct ixgbe_5tuple_filter *filter); +static void ixgbe_remove_5tuple_filter(struct rte_eth_dev *dev, + struct ixgbe_5tuple_filter *filter); +static int ixgbe_add_del_ntuple_filter(struct rte_eth_dev *dev, + struct rte_eth_ntuple_filter *filter, + bool add); +static int ixgbe_ntuple_filter_handle(struct rte_eth_dev *dev, + enum rte_filter_op filter_op, + void *arg); +static int ixgbe_get_ntuple_filter(struct rte_eth_dev *dev, + struct rte_eth_ntuple_filter *filter); static int ixgbe_add_del_ethertype_filter(struct rte_eth_dev *dev, struct rte_eth_ethertype_filter *filter, bool add); @@ -251,6 +258,7 @@ static int ixgbe_dev_filter_ctrl(struct rte_eth_dev *dev, enum rte_filter_type filter_type, enum rte_filter_op filter_op, void *arg); +static int ixgbevf_dev_set_mtu(struct rte_eth_dev *dev, uint16_t mtu); /* * Define VF Stats MACRO for Non "cleared on read" register @@ -360,14 +368,6 @@ static struct eth_dev_ops ixgbe_eth_dev_ops = { .set_vf_vlan_filter = ixgbe_set_pool_vlan_filter, .set_queue_rate_limit = ixgbe_set_queue_rate_limit, .set_vf_rate_limit = ixgbe_set_vf_rate_limit, - .fdir_add_signature_filter = ixgbe_fdir_add_signature_filter, - .fdir_update_signature_filter = ixgbe_fdir_update_signature_filter, - .fdir_remove_signature_filter = ixgbe_fdir_remove_signature_filter, - .fdir_infos_get = ixgbe_fdir_info_get, - .fdir_add_perfect_filter = ixgbe_fdir_add_perfect_filter, - .fdir_update_perfect_filter = ixgbe_fdir_update_perfect_filter, - .fdir_remove_perfect_filter = ixgbe_fdir_remove_perfect_filter, - .fdir_set_masks = ixgbe_fdir_set_masks, .reta_update = ixgbe_dev_rss_reta_update, .reta_query = ixgbe_dev_rss_reta_query, #ifdef RTE_NIC_BYPASS @@ -383,13 +383,7 @@ static struct eth_dev_ops ixgbe_eth_dev_ops = { #endif /* RTE_NIC_BYPASS */ .rss_hash_update = ixgbe_dev_rss_hash_update, .rss_hash_conf_get = ixgbe_dev_rss_hash_conf_get, - .add_syn_filter = ixgbe_add_syn_filter, - .remove_syn_filter = ixgbe_remove_syn_filter, - .get_syn_filter = ixgbe_get_syn_filter, - .add_5tuple_filter = ixgbe_add_5tuple_filter, - .remove_5tuple_filter = ixgbe_remove_5tuple_filter, - .get_5tuple_filter = ixgbe_get_5tuple_filter, - .filter_ctrl = ixgbe_dev_filter_ctrl, + .filter_ctrl = ixgbe_dev_filter_ctrl, }; /* @@ -736,6 +730,8 @@ eth_ixgbe_dev_init(__attribute__((unused)) struct eth_driver *eth_drv, IXGBE_DEV_PRIVATE_TO_HWSTRIP_BITMAP(eth_dev->data->dev_private); struct ixgbe_dcb_config *dcb_config = IXGBE_DEV_PRIVATE_TO_DCB_CFG(eth_dev->data->dev_private); + struct ixgbe_filter_info *filter_info = + IXGBE_DEV_PRIVATE_TO_FILTER_INFO(eth_dev->data->dev_private); uint32_t ctrl_ext; uint16_t csum; int diag, i; @@ -917,6 +913,11 @@ eth_ixgbe_dev_init(__attribute__((unused)) struct eth_driver *eth_drv, /* enable support intr */ ixgbe_enable_intr(eth_dev); + /* initialize 5tuple filter list */ + TAILQ_INIT(&filter_info->fivetuple_list); + memset(filter_info->fivetuple_mask, 0, + sizeof(uint32_t) * IXGBE_5TUPLE_ARRAY_SIZE); + return 0; } @@ -1495,7 +1496,16 @@ ixgbe_dev_start(struct rte_eth_dev *dev) goto error; } - ixgbe_dev_rxtx_start(dev); + err = ixgbe_dev_rxtx_start(dev); + if (err < 0) { + PMD_INIT_LOG(ERR, "Unable to start rxtx queues"); + goto error; + } + + /* Skip link setup if loopback mode is enabled for 82599. */ + if (hw->mac.type == ixgbe_mac_82599EB && + dev->data->dev_conf.lpbk_mode == IXGBE_LPBK_82599_TX_RX) + goto skip_link_setup; if (ixgbe_is_sfp(hw) && hw->phy.multispeed_fiber) { err = hw->mac.ops.setup_sfp(hw); @@ -1506,14 +1516,11 @@ ixgbe_dev_start(struct rte_eth_dev *dev) /* Turn on the laser */ ixgbe_enable_tx_laser(hw); - /* Skip link setup if loopback mode is enabled for 82599. */ - if (hw->mac.type == ixgbe_mac_82599EB && - dev->data->dev_conf.lpbk_mode == IXGBE_LPBK_82599_TX_RX) - goto skip_link_setup; - err = ixgbe_check_link(hw, &speed, &link_up, 0); if (err) goto error; + dev->data->dev_link.link_status = link_up; + err = ixgbe_get_link_capabilities(hw, &speed, &negotiate); if (err) goto error; @@ -1606,6 +1613,9 @@ ixgbe_dev_stop(struct rte_eth_dev *dev) IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); struct ixgbe_vf_info *vfinfo = *IXGBE_DEV_PRIVATE_TO_P_VFDATA(dev->data->dev_private); + struct ixgbe_filter_info *filter_info = + IXGBE_DEV_PRIVATE_TO_FILTER_INFO(dev->data->dev_private); + struct ixgbe_5tuple_filter *p_5tuple, *p_5tuple_next; int vf; PMD_INIT_FUNC_TRACE(); @@ -1635,6 +1645,18 @@ ixgbe_dev_stop(struct rte_eth_dev *dev) /* Clear recorded link status */ memset(&link, 0, sizeof(link)); rte_ixgbe_dev_atomic_write_link_status(dev, &link); + + /* Remove all ntuple filters of the device */ + for (p_5tuple = TAILQ_FIRST(&filter_info->fivetuple_list); + p_5tuple != NULL; p_5tuple = p_5tuple_next) { + p_5tuple_next = TAILQ_NEXT(p_5tuple, entries); + TAILQ_REMOVE(&filter_info->fivetuple_list, + p_5tuple, entries); + rte_free(p_5tuple); + } + memset(filter_info->fivetuple_mask, 0, + sizeof(uint32_t) * IXGBE_5TUPLE_ARRAY_SIZE); + } /* @@ -2017,6 +2039,7 @@ ixgbe_dev_info_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info) ETH_TXQ_FLAGS_NOOFFLOADS, }; dev_info->reta_size = ETH_RSS_RETA_SIZE_128; + dev_info->flow_type_rss_offloads = IXGBE_RSS_OFFLOAD_ALL; } static void @@ -3676,107 +3699,104 @@ ixgbevf_remove_mac_addr(struct rte_eth_dev *dev, uint32_t index) } } -/* - * add syn filter - * - * @param - * dev: Pointer to struct rte_eth_dev. - * filter: ponter to the filter that will be added. - * rx_queue: the queue id the filter assigned to. - * - * @return - * - On success, zero. - * - On failure, a negative value. - */ +#define MAC_TYPE_FILTER_SUP(type) do {\ + if ((type) != ixgbe_mac_82599EB && (type) != ixgbe_mac_X540 &&\ + (type) != ixgbe_mac_X550)\ + return -ENOTSUP;\ +} while (0) + static int -ixgbe_add_syn_filter(struct rte_eth_dev *dev, - struct rte_syn_filter *filter, uint16_t rx_queue) +ixgbe_syn_filter_set(struct rte_eth_dev *dev, + struct rte_eth_syn_filter *filter, + bool add) { struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); uint32_t synqf; - if (hw->mac.type != ixgbe_mac_82599EB) - return -ENOSYS; - - if (rx_queue >= IXGBE_MAX_RX_QUEUE_NUM) + if (filter->queue >= IXGBE_MAX_RX_QUEUE_NUM) return -EINVAL; synqf = IXGBE_READ_REG(hw, IXGBE_SYNQF); - if (synqf & IXGBE_SYN_FILTER_ENABLE) - return -EINVAL; - - synqf = (uint32_t)(((rx_queue << IXGBE_SYN_FILTER_QUEUE_SHIFT) & - IXGBE_SYN_FILTER_QUEUE) | IXGBE_SYN_FILTER_ENABLE); - - if (filter->hig_pri) - synqf |= IXGBE_SYN_FILTER_SYNQFP; - else - synqf &= ~IXGBE_SYN_FILTER_SYNQFP; + if (add) { + if (synqf & IXGBE_SYN_FILTER_ENABLE) + return -EINVAL; + synqf = (uint32_t)(((filter->queue << IXGBE_SYN_FILTER_QUEUE_SHIFT) & + IXGBE_SYN_FILTER_QUEUE) | IXGBE_SYN_FILTER_ENABLE); + if (filter->hig_pri) + synqf |= IXGBE_SYN_FILTER_SYNQFP; + else + synqf &= ~IXGBE_SYN_FILTER_SYNQFP; + } else { + if (!(synqf & IXGBE_SYN_FILTER_ENABLE)) + return -ENOENT; + synqf &= ~(IXGBE_SYN_FILTER_QUEUE | IXGBE_SYN_FILTER_ENABLE); + } IXGBE_WRITE_REG(hw, IXGBE_SYNQF, synqf); + IXGBE_WRITE_FLUSH(hw); return 0; } -/* - * remove syn filter - * - * @param - * dev: Pointer to struct rte_eth_dev. - * - * @return - * - On success, zero. - * - On failure, a negative value. - */ static int -ixgbe_remove_syn_filter(struct rte_eth_dev *dev) +ixgbe_syn_filter_get(struct rte_eth_dev *dev, + struct rte_eth_syn_filter *filter) { struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); - uint32_t synqf; + uint32_t synqf = IXGBE_READ_REG(hw, IXGBE_SYNQF); - if (hw->mac.type != ixgbe_mac_82599EB) - return -ENOSYS; - - synqf = IXGBE_READ_REG(hw, IXGBE_SYNQF); - - synqf &= ~(IXGBE_SYN_FILTER_QUEUE | IXGBE_SYN_FILTER_ENABLE); - - IXGBE_WRITE_REG(hw, IXGBE_SYNQF, synqf); - return 0; + if (synqf & IXGBE_SYN_FILTER_ENABLE) { + filter->hig_pri = (synqf & IXGBE_SYN_FILTER_SYNQFP) ? 1 : 0; + filter->queue = (uint16_t)((synqf & IXGBE_SYN_FILTER_QUEUE) >> 1); + return 0; + } + return -ENOENT; } -/* - * get the syn filter's info - * - * @param - * dev: Pointer to struct rte_eth_dev. - * filter: ponter to the filter that returns. - * *rx_queue: pointer to the queue id the filter assigned to. - * - * @return - * - On success, zero. - * - On failure, a negative value. - */ static int -ixgbe_get_syn_filter(struct rte_eth_dev *dev, - struct rte_syn_filter *filter, uint16_t *rx_queue) - +ixgbe_syn_filter_handle(struct rte_eth_dev *dev, + enum rte_filter_op filter_op, + void *arg) { struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); - uint32_t synqf; + int ret; - if (hw->mac.type != ixgbe_mac_82599EB) - return -ENOSYS; + MAC_TYPE_FILTER_SUP(hw->mac.type); - synqf = IXGBE_READ_REG(hw, IXGBE_SYNQF); - if (synqf & IXGBE_SYN_FILTER_ENABLE) { - filter->hig_pri = (synqf & IXGBE_SYN_FILTER_SYNQFP) ? 1 : 0; - *rx_queue = (uint16_t)((synqf & IXGBE_SYN_FILTER_QUEUE) >> 1); + if (filter_op == RTE_ETH_FILTER_NOP) return 0; + + if (arg == NULL) { + PMD_DRV_LOG(ERR, "arg shouldn't be NULL for operation %u", + filter_op); + return -EINVAL; } - return -ENOENT; + + switch (filter_op) { + case RTE_ETH_FILTER_ADD: + ret = ixgbe_syn_filter_set(dev, + (struct rte_eth_syn_filter *)arg, + TRUE); + break; + case RTE_ETH_FILTER_DELETE: + ret = ixgbe_syn_filter_set(dev, + (struct rte_eth_syn_filter *)arg, + FALSE); + break; + case RTE_ETH_FILTER_GET: + ret = ixgbe_syn_filter_get(dev, + (struct rte_eth_syn_filter *)arg); + break; + default: + PMD_DRV_LOG(ERR, "unsupported operation %u\n", filter_op); + ret = -EINVAL; + break; + } + + return ret; } + static inline enum ixgbe_5tuple_protocol convert_protocol_type(uint8_t protocol_value) { @@ -3817,62 +3837,69 @@ revert_protocol_type(enum ixgbe_5tuple_protocol protocol) * - On failure, a negative value. */ static int -ixgbe_add_5tuple_filter(struct rte_eth_dev *dev, uint16_t index, - struct rte_5tuple_filter *filter, uint16_t rx_queue) +ixgbe_add_5tuple_filter(struct rte_eth_dev *dev, + struct ixgbe_5tuple_filter *filter) { struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); - uint32_t ftqf, sdpqf = 0; + struct ixgbe_filter_info *filter_info = + IXGBE_DEV_PRIVATE_TO_FILTER_INFO(dev->data->dev_private); + int i, idx, shift; + uint32_t ftqf, sdpqf; uint32_t l34timir = 0; uint8_t mask = 0xff; - if (hw->mac.type != ixgbe_mac_82599EB) + /* + * look for an unused 5tuple filter index, + * and insert the filter to list. + */ + for (i = 0; i < IXGBE_MAX_FTQF_FILTERS; i++) { + idx = i / (sizeof(uint32_t) * NBBY); + shift = i % (sizeof(uint32_t) * NBBY); + if (!(filter_info->fivetuple_mask[idx] & (1 << shift))) { + filter_info->fivetuple_mask[idx] |= 1 << shift; + filter->index = i; + TAILQ_INSERT_TAIL(&filter_info->fivetuple_list, + filter, + entries); + break; + } + } + if (i >= IXGBE_MAX_FTQF_FILTERS) { + PMD_DRV_LOG(ERR, "5tuple filters are full."); return -ENOSYS; - - if (index >= IXGBE_MAX_FTQF_FILTERS || - rx_queue >= IXGBE_MAX_RX_QUEUE_NUM || - filter->priority > IXGBE_5TUPLE_MAX_PRI || - filter->priority < IXGBE_5TUPLE_MIN_PRI) - return -EINVAL; /* filter index is out of range. */ - - if (filter->tcp_flags) { - PMD_INIT_LOG(INFO, "82599EB not tcp flags in 5tuple"); - return -EINVAL; } - ftqf = IXGBE_READ_REG(hw, IXGBE_FTQF(index)); - if (ftqf & IXGBE_FTQF_QUEUE_ENABLE) - return -EINVAL; /* filter index is in use. */ + sdpqf = (uint32_t)(filter->filter_info.dst_port << + IXGBE_SDPQF_DSTPORT_SHIFT); + sdpqf = sdpqf | (filter->filter_info.src_port & IXGBE_SDPQF_SRCPORT); - ftqf = 0; - sdpqf = (uint32_t)(filter->dst_port << IXGBE_SDPQF_DSTPORT_SHIFT); - sdpqf = sdpqf | (filter->src_port & IXGBE_SDPQF_SRCPORT); - - ftqf |= (uint32_t)(convert_protocol_type(filter->protocol) & + ftqf = (uint32_t)(filter->filter_info.proto & IXGBE_FTQF_PROTOCOL_MASK); - ftqf |= (uint32_t)((filter->priority & IXGBE_FTQF_PRIORITY_MASK) << - IXGBE_FTQF_PRIORITY_SHIFT); - if (filter->src_ip_mask == 0) /* 0 means compare. */ + ftqf |= (uint32_t)((filter->filter_info.priority & + IXGBE_FTQF_PRIORITY_MASK) << IXGBE_FTQF_PRIORITY_SHIFT); + if (filter->filter_info.src_ip_mask == 0) /* 0 means compare. */ mask &= IXGBE_FTQF_SOURCE_ADDR_MASK; - if (filter->dst_ip_mask == 0) + if (filter->filter_info.dst_ip_mask == 0) mask &= IXGBE_FTQF_DEST_ADDR_MASK; - if (filter->src_port_mask == 0) + if (filter->filter_info.src_port_mask == 0) mask &= IXGBE_FTQF_SOURCE_PORT_MASK; - if (filter->dst_port_mask == 0) + if (filter->filter_info.dst_port_mask == 0) mask &= IXGBE_FTQF_DEST_PORT_MASK; - if (filter->protocol_mask == 0) + if (filter->filter_info.proto_mask == 0) mask &= IXGBE_FTQF_PROTOCOL_COMP_MASK; ftqf |= mask << IXGBE_FTQF_5TUPLE_MASK_SHIFT; ftqf |= IXGBE_FTQF_POOL_MASK_EN; ftqf |= IXGBE_FTQF_QUEUE_ENABLE; - IXGBE_WRITE_REG(hw, IXGBE_DAQF(index), filter->dst_ip); - IXGBE_WRITE_REG(hw, IXGBE_SAQF(index), filter->src_ip); - IXGBE_WRITE_REG(hw, IXGBE_SDPQF(index), sdpqf); - IXGBE_WRITE_REG(hw, IXGBE_FTQF(index), ftqf); + IXGBE_WRITE_REG(hw, IXGBE_DAQF(idx), filter->filter_info.dst_ip); + IXGBE_WRITE_REG(hw, IXGBE_SAQF(idx), filter->filter_info.src_ip); + IXGBE_WRITE_REG(hw, IXGBE_SDPQF(idx), sdpqf); + IXGBE_WRITE_REG(hw, IXGBE_FTQF(idx), ftqf); l34timir |= IXGBE_L34T_IMIR_RESERVE; - l34timir |= (uint32_t)(rx_queue << IXGBE_L34T_IMIR_QUEUE_SHIFT); - IXGBE_WRITE_REG(hw, IXGBE_L34T_IMIR(index), l34timir); + l34timir |= (uint32_t)(filter->queue << + IXGBE_L34T_IMIR_QUEUE_SHIFT); + IXGBE_WRITE_REG(hw, IXGBE_L34T_IMIR(i), l34timir); return 0; } @@ -3881,92 +3908,27 @@ ixgbe_add_5tuple_filter(struct rte_eth_dev *dev, uint16_t index, * * @param * dev: Pointer to struct rte_eth_dev. - * index: the index the filter allocates. - * - * @return - * - On success, zero. - * - On failure, a negative value. + * filter: the pointer of the filter will be removed. */ -static int +static void ixgbe_remove_5tuple_filter(struct rte_eth_dev *dev, - uint16_t index) + struct ixgbe_5tuple_filter *filter) { struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); + struct ixgbe_filter_info *filter_info = + IXGBE_DEV_PRIVATE_TO_FILTER_INFO(dev->data->dev_private); + uint16_t index = filter->index; - if (hw->mac.type != ixgbe_mac_82599EB) - return -ENOSYS; - - if (index >= IXGBE_MAX_FTQF_FILTERS) - return -EINVAL; /* filter index is out of range. */ + filter_info->fivetuple_mask[index / (sizeof(uint32_t) * NBBY)] &= + ~(1 << (index % (sizeof(uint32_t) * NBBY))); + TAILQ_REMOVE(&filter_info->fivetuple_list, filter, entries); + rte_free(filter); IXGBE_WRITE_REG(hw, IXGBE_DAQF(index), 0); IXGBE_WRITE_REG(hw, IXGBE_SAQF(index), 0); IXGBE_WRITE_REG(hw, IXGBE_SDPQF(index), 0); IXGBE_WRITE_REG(hw, IXGBE_FTQF(index), 0); IXGBE_WRITE_REG(hw, IXGBE_L34T_IMIR(index), 0); - return 0; -} - -/* - * get a 5tuple filter - * - * @param - * dev: Pointer to struct rte_eth_dev. - * index: the index the filter allocates - * filter: ponter to the filter that returns. - * *rx_queue: pointer of the queue id the filter assigned to. - * - * @return - * - On success, zero. - * - On failure, a negative value. - */ -static int -ixgbe_get_5tuple_filter(struct rte_eth_dev *dev, uint16_t index, - struct rte_5tuple_filter *filter, uint16_t *rx_queue) -{ - struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); - uint32_t sdpqf, ftqf, l34timir; - uint8_t mask; - enum ixgbe_5tuple_protocol proto; - - if (hw->mac.type != ixgbe_mac_82599EB) - return -ENOSYS; - - if (index >= IXGBE_MAX_FTQF_FILTERS) - return -EINVAL; /* filter index is out of range. */ - - ftqf = IXGBE_READ_REG(hw, IXGBE_FTQF(index)); - if (ftqf & IXGBE_FTQF_QUEUE_ENABLE) { - proto = (enum ixgbe_5tuple_protocol)(ftqf & IXGBE_FTQF_PROTOCOL_MASK); - filter->protocol = revert_protocol_type(proto); - filter->priority = (ftqf >> IXGBE_FTQF_PRIORITY_SHIFT) & - IXGBE_FTQF_PRIORITY_MASK; - mask = (uint8_t)((ftqf >> IXGBE_FTQF_5TUPLE_MASK_SHIFT) & - IXGBE_FTQF_5TUPLE_MASK_MASK); - filter->src_ip_mask = - (mask & IXGBE_FTQF_SOURCE_ADDR_MASK) ? 1 : 0; - filter->dst_ip_mask = - (mask & IXGBE_FTQF_DEST_ADDR_MASK) ? 1 : 0; - filter->src_port_mask = - (mask & IXGBE_FTQF_SOURCE_PORT_MASK) ? 1 : 0; - filter->dst_port_mask = - (mask & IXGBE_FTQF_DEST_PORT_MASK) ? 1 : 0; - filter->protocol_mask = - (mask & IXGBE_FTQF_PROTOCOL_COMP_MASK) ? 1 : 0; - - sdpqf = IXGBE_READ_REG(hw, IXGBE_SDPQF(index)); - filter->dst_port = (sdpqf & IXGBE_SDPQF_DSTPORT) >> - IXGBE_SDPQF_DSTPORT_SHIFT; - filter->src_port = sdpqf & IXGBE_SDPQF_SRCPORT; - filter->dst_ip = IXGBE_READ_REG(hw, IXGBE_DAQF(index)); - filter->src_ip = IXGBE_READ_REG(hw, IXGBE_SAQF(index)); - - l34timir = IXGBE_READ_REG(hw, IXGBE_L34T_IMIR(index)); - *rx_queue = (l34timir & IXGBE_L34T_IMIR_QUEUE) >> - IXGBE_L34T_IMIR_QUEUE_SHIFT; - return 0; - } - return -ENOENT; } static int @@ -4003,12 +3965,263 @@ ixgbevf_dev_set_mtu(struct rte_eth_dev *dev, uint16_t mtu) return 0; } -#define MAC_TYPE_FILTER_SUP(type) do {\ - if ((type) != ixgbe_mac_82599EB && (type) != ixgbe_mac_X540 &&\ - (type) != ixgbe_mac_X550)\ +#define MAC_TYPE_FILTER_SUP_EXT(type) do {\ + if ((type) != ixgbe_mac_82599EB && (type) != ixgbe_mac_X540)\ return -ENOTSUP;\ } while (0) +static inline struct ixgbe_5tuple_filter * +ixgbe_5tuple_filter_lookup(struct ixgbe_5tuple_filter_list *filter_list, + struct ixgbe_5tuple_filter_info *key) +{ + struct ixgbe_5tuple_filter *it; + + TAILQ_FOREACH(it, filter_list, entries) { + if (memcmp(key, &it->filter_info, + sizeof(struct ixgbe_5tuple_filter_info)) == 0) { + return it; + } + } + return NULL; +} + +/* translate elements in struct rte_eth_ntuple_filter to struct ixgbe_5tuple_filter_info*/ +static inline int +ntuple_filter_to_5tuple(struct rte_eth_ntuple_filter *filter, + struct ixgbe_5tuple_filter_info *filter_info) +{ + if (filter->queue >= IXGBE_MAX_RX_QUEUE_NUM || + filter->priority > IXGBE_5TUPLE_MAX_PRI || + filter->priority < IXGBE_5TUPLE_MIN_PRI) + return -EINVAL; + + switch (filter->dst_ip_mask) { + case UINT32_MAX: + filter_info->dst_ip_mask = 0; + filter_info->dst_ip = filter->dst_ip; + break; + case 0: + filter_info->dst_ip_mask = 1; + break; + default: + PMD_DRV_LOG(ERR, "invalid dst_ip mask."); + return -EINVAL; + } + + switch (filter->src_ip_mask) { + case UINT32_MAX: + filter_info->src_ip_mask = 0; + filter_info->src_ip = filter->src_ip; + break; + case 0: + filter_info->src_ip_mask = 1; + break; + default: + PMD_DRV_LOG(ERR, "invalid src_ip mask."); + return -EINVAL; + } + + switch (filter->dst_port_mask) { + case UINT16_MAX: + filter_info->dst_port_mask = 0; + filter_info->dst_port = filter->dst_port; + break; + case 0: + filter_info->dst_port_mask = 1; + break; + default: + PMD_DRV_LOG(ERR, "invalid dst_port mask."); + return -EINVAL; + } + + switch (filter->src_port_mask) { + case UINT16_MAX: + filter_info->src_port_mask = 0; + filter_info->src_port = filter->src_port; + break; + case 0: + filter_info->src_port_mask = 1; + break; + default: + PMD_DRV_LOG(ERR, "invalid src_port mask."); + return -EINVAL; + } + + switch (filter->proto_mask) { + case UINT8_MAX: + filter_info->proto_mask = 0; + filter_info->proto = + convert_protocol_type(filter->proto); + break; + case 0: + filter_info->proto_mask = 1; + break; + default: + PMD_DRV_LOG(ERR, "invalid protocol mask."); + return -EINVAL; + } + + filter_info->priority = (uint8_t)filter->priority; + return 0; +} + +/* + * add or delete a ntuple filter + * + * @param + * dev: Pointer to struct rte_eth_dev. + * ntuple_filter: Pointer to struct rte_eth_ntuple_filter + * add: if true, add filter, if false, remove filter + * + * @return + * - On success, zero. + * - On failure, a negative value. + */ +static int +ixgbe_add_del_ntuple_filter(struct rte_eth_dev *dev, + struct rte_eth_ntuple_filter *ntuple_filter, + bool add) +{ + struct ixgbe_filter_info *filter_info = + IXGBE_DEV_PRIVATE_TO_FILTER_INFO(dev->data->dev_private); + struct ixgbe_5tuple_filter_info filter_5tuple; + struct ixgbe_5tuple_filter *filter; + int ret; + + if (ntuple_filter->flags != RTE_5TUPLE_FLAGS) { + PMD_DRV_LOG(ERR, "only 5tuple is supported."); + return -EINVAL; + } + + memset(&filter_5tuple, 0, sizeof(struct ixgbe_5tuple_filter_info)); + ret = ntuple_filter_to_5tuple(ntuple_filter, &filter_5tuple); + if (ret < 0) + return ret; + + filter = ixgbe_5tuple_filter_lookup(&filter_info->fivetuple_list, + &filter_5tuple); + if (filter != NULL && add) { + PMD_DRV_LOG(ERR, "filter exists."); + return -EEXIST; + } + if (filter == NULL && !add) { + PMD_DRV_LOG(ERR, "filter doesn't exist."); + return -ENOENT; + } + + if (add) { + filter = rte_zmalloc("ixgbe_5tuple_filter", + sizeof(struct ixgbe_5tuple_filter), 0); + if (filter == NULL) + return -ENOMEM; + (void)rte_memcpy(&filter->filter_info, + &filter_5tuple, + sizeof(struct ixgbe_5tuple_filter_info)); + filter->queue = ntuple_filter->queue; + ret = ixgbe_add_5tuple_filter(dev, filter); + if (ret < 0) { + rte_free(filter); + return ret; + } + } else + ixgbe_remove_5tuple_filter(dev, filter); + + return 0; +} + +/* + * get a ntuple filter + * + * @param + * dev: Pointer to struct rte_eth_dev. + * ntuple_filter: Pointer to struct rte_eth_ntuple_filter + * + * @return + * - On success, zero. + * - On failure, a negative value. + */ +static int +ixgbe_get_ntuple_filter(struct rte_eth_dev *dev, + struct rte_eth_ntuple_filter *ntuple_filter) +{ + struct ixgbe_filter_info *filter_info = + IXGBE_DEV_PRIVATE_TO_FILTER_INFO(dev->data->dev_private); + struct ixgbe_5tuple_filter_info filter_5tuple; + struct ixgbe_5tuple_filter *filter; + int ret; + + if (ntuple_filter->flags != RTE_5TUPLE_FLAGS) { + PMD_DRV_LOG(ERR, "only 5tuple is supported."); + return -EINVAL; + } + + memset(&filter_5tuple, 0, sizeof(struct ixgbe_5tuple_filter_info)); + ret = ntuple_filter_to_5tuple(ntuple_filter, &filter_5tuple); + if (ret < 0) + return ret; + + filter = ixgbe_5tuple_filter_lookup(&filter_info->fivetuple_list, + &filter_5tuple); + if (filter == NULL) { + PMD_DRV_LOG(ERR, "filter doesn't exist."); + return -ENOENT; + } + ntuple_filter->queue = filter->queue; + return 0; +} + +/* + * ixgbe_ntuple_filter_handle - Handle operations for ntuple filter. + * @dev: pointer to rte_eth_dev structure + * @filter_op:operation will be taken. + * @arg: a pointer to specific structure corresponding to the filter_op + * + * @return + * - On success, zero. + * - On failure, a negative value. + */ +static int +ixgbe_ntuple_filter_handle(struct rte_eth_dev *dev, + enum rte_filter_op filter_op, + void *arg) +{ + struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); + int ret; + + MAC_TYPE_FILTER_SUP_EXT(hw->mac.type); + + if (filter_op == RTE_ETH_FILTER_NOP) + return 0; + + if (arg == NULL) { + PMD_DRV_LOG(ERR, "arg shouldn't be NULL for operation %u.", + filter_op); + return -EINVAL; + } + + switch (filter_op) { + case RTE_ETH_FILTER_ADD: + ret = ixgbe_add_del_ntuple_filter(dev, + (struct rte_eth_ntuple_filter *)arg, + TRUE); + break; + case RTE_ETH_FILTER_DELETE: + ret = ixgbe_add_del_ntuple_filter(dev, + (struct rte_eth_ntuple_filter *)arg, + FALSE); + break; + case RTE_ETH_FILTER_GET: + ret = ixgbe_get_ntuple_filter(dev, + (struct rte_eth_ntuple_filter *)arg); + break; + default: + PMD_DRV_LOG(ERR, "unsupported operation %u.", filter_op); + ret = -EINVAL; + break; + } + return ret; +} + static inline int ixgbe_ethertype_filter_lookup(struct ixgbe_filter_info *filter_info, uint16_t ethertype) @@ -4204,9 +4417,18 @@ ixgbe_dev_filter_ctrl(struct rte_eth_dev *dev, int ret = -EINVAL; switch (filter_type) { + case RTE_ETH_FILTER_NTUPLE: + ret = ixgbe_ntuple_filter_handle(dev, filter_op, arg); + break; case RTE_ETH_FILTER_ETHERTYPE: ret = ixgbe_ethertype_filter_handle(dev, filter_op, arg); break; + case RTE_ETH_FILTER_SYN: + ret = ixgbe_syn_filter_handle(dev, filter_op, arg); + break; + case RTE_ETH_FILTER_FDIR: + ret = ixgbe_fdir_ctrl_func(dev, filter_op, arg); + break; default: PMD_DRV_LOG(WARNING, "Filter type (%d) not supported", filter_type);