[5/8] net/octeontx: add VLAN filter offload support

Message ID 1584351224-23500-6-git-send-email-hkalra@marvell.com (mailing list archive)
State Accepted, archived
Delegated to: Jerin Jacob
Headers
Series add new features to octeontx PMD |

Checks

Context Check Description
ci/checkpatch success coding style OK
ci/Intel-compilation fail Compilation issues

Commit Message

Harman Kalra March 16, 2020, 9:33 a.m. UTC
  From: Vamsi Attunuru <vattunuru@marvell.com>

Patch adds support for vlan filter offload support.
MBOX messages for vlan filter on/off and vlan filter
entry add/rm are added to configure PCAM entries to
filter out the vlan traffic on a given port.

Patch also defines rx_offload_flag for vlan filtering.

Signed-off-by: Vamsi Attunuru <vattunuru@marvell.com>
---
 doc/guides/nics/features/octeontx.ini      |   2 +
 doc/guides/nics/octeontx.rst               |   1 +
 drivers/net/octeontx/Makefile              |   1 +
 drivers/net/octeontx/base/octeontx_pkivf.c |  40 +++++
 drivers/net/octeontx/base/octeontx_pkivf.h |  20 +++
 drivers/net/octeontx/meson.build           |   3 +-
 drivers/net/octeontx/octeontx_ethdev.c     |  10 ++
 drivers/net/octeontx/octeontx_ethdev.h     |  24 ++-
 drivers/net/octeontx/octeontx_ethdev_ops.c | 184 +++++++++++++++++++++
 drivers/net/octeontx/octeontx_rxtx.h       |   1 +
 10 files changed, 284 insertions(+), 2 deletions(-)
 create mode 100644 drivers/net/octeontx/octeontx_ethdev_ops.c
  

Comments

Harman Kalra April 6, 2020, 10:09 a.m. UTC | #1
On Mon, Mar 16, 2020 at 03:03:41PM +0530, Harman Kalra wrote:
> From: Vamsi Attunuru <vattunuru@marvell.com>
> 
> Patch adds support for vlan filter offload support.
> MBOX messages for vlan filter on/off and vlan filter
> entry add/rm are added to configure PCAM entries to
> filter out the vlan traffic on a given port.
> 
> Patch also defines rx_offload_flag for vlan filtering.
> 
> Signed-off-by: Vamsi Attunuru <vattunuru@marvell.com>

Acked-by: Harman Kalra <hkalra@marvell.com>

> ---
>  doc/guides/nics/features/octeontx.ini      |   2 +
>  doc/guides/nics/octeontx.rst               |   1 +
>  drivers/net/octeontx/Makefile              |   1 +
>  drivers/net/octeontx/base/octeontx_pkivf.c |  40 +++++
>  drivers/net/octeontx/base/octeontx_pkivf.h |  20 +++
>  drivers/net/octeontx/meson.build           |   3 +-
>  drivers/net/octeontx/octeontx_ethdev.c     |  10 ++
>  drivers/net/octeontx/octeontx_ethdev.h     |  24 ++-
>  drivers/net/octeontx/octeontx_ethdev_ops.c | 184 +++++++++++++++++++++
>  drivers/net/octeontx/octeontx_rxtx.h       |   1 +
>  10 files changed, 284 insertions(+), 2 deletions(-)
>  create mode 100644 drivers/net/octeontx/octeontx_ethdev_ops.c
> 
> diff --git a/doc/guides/nics/features/octeontx.ini b/doc/guides/nics/features/octeontx.ini
> index e3ee79f0f..53c541f4b 100644
> --- a/doc/guides/nics/features/octeontx.ini
> +++ b/doc/guides/nics/features/octeontx.ini
> @@ -13,6 +13,8 @@ Jumbo frame          = Y
>  Scattered Rx         = Y
>  Promiscuous mode     = Y
>  Unicast MAC filter   = Y
> +VLAN filter          = Y
> +VLAN offload         = P
>  CRC offload          = Y
>  Packet type parsing  = Y
>  Basic stats          = Y
> diff --git a/doc/guides/nics/octeontx.rst b/doc/guides/nics/octeontx.rst
> index ddb626bc3..c8655bf37 100644
> --- a/doc/guides/nics/octeontx.rst
> +++ b/doc/guides/nics/octeontx.rst
> @@ -22,6 +22,7 @@ Features of the OCTEON TX Ethdev PMD are:
>  - Jumbo frames
>  - Scatter-Gather IO support
>  - Link state information
> +- MAC/VLAN filtering
>  - MTU update
>  - SR-IOV VF
>  - Multiple queues for TX
> diff --git a/drivers/net/octeontx/Makefile b/drivers/net/octeontx/Makefile
> index 8ddfc3089..694f403f1 100644
> --- a/drivers/net/octeontx/Makefile
> +++ b/drivers/net/octeontx/Makefile
> @@ -28,6 +28,7 @@ SRCS-$(CONFIG_RTE_LIBRTE_OCTEONTX_PMD) += octeontx_pkovf.c
>  SRCS-$(CONFIG_RTE_LIBRTE_OCTEONTX_PMD) += octeontx_pkivf.c
>  SRCS-$(CONFIG_RTE_LIBRTE_OCTEONTX_PMD) += octeontx_bgx.c
>  SRCS-$(CONFIG_RTE_LIBRTE_OCTEONTX_PMD) += octeontx_ethdev.c
> +SRCS-$(CONFIG_RTE_LIBRTE_OCTEONTX_PMD) += octeontx_ethdev_ops.c
>  
>  ifeq ($(CONFIG_RTE_TOOLCHAIN_GCC),y)
>  CFLAGS_octeontx_rxtx.o += -fno-prefetch-loop-arrays
> diff --git a/drivers/net/octeontx/base/octeontx_pkivf.c b/drivers/net/octeontx/base/octeontx_pkivf.c
> index 8ce041955..0ddff5488 100644
> --- a/drivers/net/octeontx/base/octeontx_pkivf.c
> +++ b/drivers/net/octeontx/base/octeontx_pkivf.c
> @@ -136,6 +136,46 @@ octeontx_pki_port_errchk_config(int port, pki_errchk_cfg_t *cfg)
>  	return res;
>  }
>  
> +int
> +octeontx_pki_port_vlan_fltr_config(int port,
> +				   pki_port_vlan_filter_config_t *fltr_cfg)
> +{
> +	struct octeontx_mbox_hdr hdr;
> +	int res;
> +
> +	pki_port_vlan_filter_config_t cfg = *fltr_cfg;
> +	int len = sizeof(pki_port_vlan_filter_config_t);
> +
> +	hdr.coproc = OCTEONTX_PKI_COPROC;
> +	hdr.msg = MBOX_PKI_PORT_VLAN_FILTER_CONFIG;
> +	hdr.vfid = port;
> +
> +	res = octeontx_mbox_send(&hdr, &cfg, len, NULL, 0);
> +	if (res < 0)
> +		return -EACCES;
> +	return res;
> +}
> +
> +int
> +octeontx_pki_port_vlan_fltr_entry_config(int port,
> +				   pki_port_vlan_filter_entry_config_t *e_cfg)
> +{
> +	struct octeontx_mbox_hdr hdr;
> +	int res;
> +
> +	pki_port_vlan_filter_entry_config_t cfg = *e_cfg;
> +	int len = sizeof(pki_port_vlan_filter_entry_config_t);
> +
> +	hdr.coproc = OCTEONTX_PKI_COPROC;
> +	hdr.msg = MBOX_PKI_PORT_VLAN_FILTER_ENTRY_CONFIG;
> +	hdr.vfid = port;
> +
> +	res = octeontx_mbox_send(&hdr, &cfg, len, NULL, 0);
> +	if (res < 0)
> +		return -EACCES;
> +	return res;
> +}
> +
>  #define PCI_VENDOR_ID_CAVIUM               0x177D
>  #define PCI_DEVICE_ID_OCTEONTX_PKI_VF      0xA0DD
>  
> diff --git a/drivers/net/octeontx/base/octeontx_pkivf.h b/drivers/net/octeontx/base/octeontx_pkivf.h
> index d541dc3bd..d41eaa57e 100644
> --- a/drivers/net/octeontx/base/octeontx_pkivf.h
> +++ b/drivers/net/octeontx/base/octeontx_pkivf.h
> @@ -36,6 +36,8 @@
>  #define MBOX_PKI_PORT_ALLOC_QPG			21
>  #define MBOX_PKI_PORT_FREE_QPG			22
>  #define MBOX_PKI_SET_PORT_CONFIG		23
> +#define MBOX_PKI_PORT_VLAN_FILTER_CONFIG	24
> +#define MBOX_PKI_PORT_VLAN_FILTER_ENTRY_CONFIG	25
>  
>  #define MBOX_PKI_MAX_QOS_ENTRY 64
>  
> @@ -236,6 +238,20 @@ typedef struct pki_port_modify_qos_entry {
>  	struct pki_qos_entry qos_entry;
>  } pki_mod_qos_t;
>  
> +/* pki port VLAN filter config */
> +typedef struct pki_port_vlan_filter_config {
> +	uint8_t port_type;  /* OCTTX_PORT_TYPE_[NET/INT/PCI] */
> +	uint8_t fltr_conf; /* '1' to enable & '0' to disable */
> +} pki_port_vlan_filter_config_t;
> +
> +/* pki port VLAN filter entry config */
> +typedef struct pki_port_vlan_filter_entry_config {
> +	uint8_t port_type;  /* OCTTX_PORT_TYPE_[NET/INT/PCI] */
> +	uint8_t entry_conf; /* '1' to add & '0' to remove */
> +	uint16_t vlan_tpid; /* in host byte-order */
> +	uint16_t vlan_id;   /* in host byte-order */
> +} pki_port_vlan_filter_entry_config_t;
> +
>  static inline int
>  octeontx_pki_port_modify_qos(int port, pki_mod_qos_t *qos_cfg)
>  {
> @@ -348,5 +364,9 @@ int octeontx_pki_port_pktbuf_config(int port, pki_pktbuf_cfg_t *buf_cfg);
>  int octeontx_pki_port_create_qos(int port, pki_qos_cfg_t *qos_cfg);
>  int octeontx_pki_port_close(int port);
>  int octeontx_pki_port_errchk_config(int port, pki_errchk_cfg_t *cfg);
> +int octeontx_pki_port_vlan_fltr_config(int port,
> +				pki_port_vlan_filter_config_t *fltr_cfg);
> +int octeontx_pki_port_vlan_fltr_entry_config(int port,
> +				pki_port_vlan_filter_entry_config_t *entry_cfg);
>  
>  #endif /* __OCTEONTX_PKI_H__ */
> diff --git a/drivers/net/octeontx/meson.build b/drivers/net/octeontx/meson.build
> index 0e249eb98..f7ba6e68b 100644
> --- a/drivers/net/octeontx/meson.build
> +++ b/drivers/net/octeontx/meson.build
> @@ -5,7 +5,8 @@ subdir('base')
>  objs = [base_objs]
>  
>  sources = files('octeontx_rxtx.c',
> -		'octeontx_ethdev.c'
> +		'octeontx_ethdev.c',
> +		'octeontx_ethdev_ops.c'
>  		)
>  
>  allow_experimental_apis = true
> diff --git a/drivers/net/octeontx/octeontx_ethdev.c b/drivers/net/octeontx/octeontx_ethdev.c
> index 91b9ea645..5dd40bc04 100644
> --- a/drivers/net/octeontx/octeontx_ethdev.c
> +++ b/drivers/net/octeontx/octeontx_ethdev.c
> @@ -360,6 +360,12 @@ octeontx_dev_configure(struct rte_eth_dev *dev)
>  		return -EFAULT;
>  	}
>  
> +	ret = octeontx_dev_vlan_offload_init(dev);
> +	if (ret) {
> +		octeontx_log_err("failed to initialize vlan offload");
> +		return -EFAULT;
> +	}
> +
>  	nic->pki.classifier_enable = false;
>  	nic->pki.hash_enable = true;
>  	nic->pki.initialized = false;
> @@ -384,6 +390,8 @@ octeontx_dev_close(struct rte_eth_dev *dev)
>  
>  	rte_event_dev_close(nic->evdev);
>  
> +	octeontx_dev_vlan_offload_fini(dev);
> +
>  	ret = octeontx_pko_channel_close(nic->base_ochan);
>  	if (ret < 0) {
>  		octeontx_log_err("failed to close channel %d VF%d %d %d",
> @@ -1185,6 +1193,8 @@ static const struct eth_dev_ops octeontx_dev_ops = {
>  	.mac_addr_remove	 = octeontx_dev_mac_addr_del,
>  	.mac_addr_add		 = octeontx_dev_mac_addr_add,
>  	.mac_addr_set		 = octeontx_dev_default_mac_addr_set,
> +	.vlan_offload_set	 = octeontx_dev_vlan_offload_set,
> +	.vlan_filter_set	 = octeontx_dev_vlan_filter_set,
>  	.tx_queue_start		 = octeontx_dev_tx_queue_start,
>  	.tx_queue_stop		 = octeontx_dev_tx_queue_stop,
>  	.tx_queue_setup		 = octeontx_dev_tx_queue_setup,
> diff --git a/drivers/net/octeontx/octeontx_ethdev.h b/drivers/net/octeontx/octeontx_ethdev.h
> index 27f6556dd..e7e0d40c7 100644
> --- a/drivers/net/octeontx/octeontx_ethdev.h
> +++ b/drivers/net/octeontx/octeontx_ethdev.h
> @@ -55,7 +55,8 @@
>  
>  #define OCTEONTX_RX_OFFLOADS		(DEV_RX_OFFLOAD_CHECKSUM     | \
>  					 DEV_RX_OFFLOAD_SCATTER	     | \
> -					 DEV_RX_OFFLOAD_JUMBO_FRAME)
> +					 DEV_RX_OFFLOAD_JUMBO_FRAME  | \
> +					 DEV_RX_OFFLOAD_VLAN_FILTER)
>  
>  #define OCTEONTX_TX_OFFLOADS		(DEV_TX_OFFLOAD_MT_LOCKFREE    |  \
>  					 DEV_TX_OFFLOAD_MBUF_FAST_FREE |  \
> @@ -70,6 +71,18 @@ octeontx_pmd_priv(struct rte_eth_dev *dev)
>  extern uint16_t
>  rte_octeontx_pchan_map[OCTEONTX_MAX_BGX_PORTS][OCTEONTX_MAX_LMAC_PER_BGX];
>  
> +struct vlan_entry {
> +	TAILQ_ENTRY(vlan_entry) next;
> +	uint16_t vlan_id;
> +};
> +
> +TAILQ_HEAD(octeontx_vlan_filter_tbl, vlan_entry);
> +
> +struct octeontx_vlan_info {
> +	struct octeontx_vlan_filter_tbl fltr_tbl;
> +	uint8_t filter_on;
> +};
> +
>  /* Octeontx ethdev nic */
>  struct octeontx_nic {
>  	struct rte_eth_dev *dev;
> @@ -107,6 +120,7 @@ struct octeontx_nic {
>  	uint16_t rx_offload_flags;
>  	uint64_t tx_offloads;
>  	uint16_t tx_offload_flags;
> +	struct octeontx_vlan_info vlan_info;
>  } __rte_cache_aligned;
>  
>  struct octeontx_txq {
> @@ -127,4 +141,12 @@ struct octeontx_rxq {
>  
>  void
>  octeontx_set_tx_function(struct rte_eth_dev *dev);
> +
> +/* VLAN */
> +int octeontx_dev_vlan_offload_init(struct rte_eth_dev *dev);
> +int octeontx_dev_vlan_offload_fini(struct rte_eth_dev *eth_dev);
> +int octeontx_dev_vlan_offload_set(struct rte_eth_dev *dev, int mask);
> +int octeontx_dev_vlan_filter_set(struct rte_eth_dev *dev,
> +				 uint16_t vlan_id, int on);
> +
>  #endif /* __OCTEONTX_ETHDEV_H__ */
> diff --git a/drivers/net/octeontx/octeontx_ethdev_ops.c b/drivers/net/octeontx/octeontx_ethdev_ops.c
> new file mode 100644
> index 000000000..8c3065542
> --- /dev/null
> +++ b/drivers/net/octeontx/octeontx_ethdev_ops.c
> @@ -0,0 +1,184 @@
> +/* SPDX-License-Identifier: BSD-3-Clause
> + * Copyright(C) 2020 Marvell International Ltd.
> + */
> +
> +#include <rte_malloc.h>
> +
> +#include "octeontx_ethdev.h"
> +#include "octeontx_logs.h"
> +#include "octeontx_rxtx.h"
> +
> +static int
> +octeontx_vlan_hw_filter(struct octeontx_nic *nic, uint8_t flag)
> +{
> +	struct octeontx_vlan_info *vlan = &nic->vlan_info;
> +	pki_port_vlan_filter_config_t fltr_conf;
> +	int rc = 0;
> +
> +	if (vlan->filter_on == flag)
> +		return rc;
> +
> +	fltr_conf.port_type = OCTTX_PORT_TYPE_NET;
> +	fltr_conf.fltr_conf = flag;
> +
> +	rc = octeontx_pki_port_vlan_fltr_config(nic->port_id, &fltr_conf);
> +	if (rc != 0) {
> +		octeontx_log_err("Fail to configure vlan hw filter for port %d",
> +				 nic->port_id);
> +		goto done;
> +	}
> +
> +	vlan->filter_on = flag;
> +
> +done:
> +	return rc;
> +}
> +
> +int
> +octeontx_dev_vlan_offload_set(struct rte_eth_dev *dev, int mask)
> +{
> +	struct octeontx_nic *nic = octeontx_pmd_priv(dev);
> +	struct rte_eth_rxmode *rxmode;
> +	int rc = 0;
> +
> +	rxmode = &dev->data->dev_conf.rxmode;
> +
> +	if (mask & ETH_VLAN_EXTEND_MASK) {
> +		octeontx_log_err("Extend offload not supported");
> +		return -ENOTSUP;
> +	}
> +
> +	if (mask & ETH_VLAN_STRIP_MASK) {
> +		octeontx_log_err("VLAN strip offload not supported");
> +		return -ENOTSUP;
> +	}
> +
> +	if (mask & ETH_VLAN_FILTER_MASK) {
> +		if (rxmode->offloads & DEV_RX_OFFLOAD_VLAN_FILTER) {
> +			rc = octeontx_vlan_hw_filter(nic, true);
> +			if (rc)
> +				goto done;
> +
> +			nic->rx_offloads |= DEV_RX_OFFLOAD_VLAN_FILTER;
> +			nic->rx_offload_flags |= OCCTX_RX_VLAN_FLTR_F;
> +		} else {
> +			rc = octeontx_vlan_hw_filter(nic, false);
> +			if (rc)
> +				goto done;
> +
> +			nic->rx_offloads &= ~DEV_RX_OFFLOAD_VLAN_FILTER;
> +			nic->rx_offload_flags &= ~OCCTX_RX_VLAN_FLTR_F;
> +		}
> +	}
> +
> +done:
> +	return rc;
> +}
> +
> +int
> +octeontx_dev_vlan_filter_set(struct rte_eth_dev *dev, uint16_t vlan_id, int on)
> +{
> +	struct octeontx_nic *nic = octeontx_pmd_priv(dev);
> +	struct octeontx_vlan_info *vlan = &nic->vlan_info;
> +	pki_port_vlan_filter_entry_config_t fltr_entry;
> +	struct vlan_entry *entry = NULL;
> +	int entry_count = 0;
> +	int rc = -EINVAL;
> +
> +	if (on) {
> +		TAILQ_FOREACH(entry, &vlan->fltr_tbl, next)
> +			if (entry->vlan_id == vlan_id) {
> +				octeontx_log_dbg("Vlan Id is already set");
> +				return 0;
> +			}
> +	} else {
> +		TAILQ_FOREACH(entry, &vlan->fltr_tbl, next)
> +			entry_count++;
> +
> +		if (!entry_count)
> +			return 0;
> +	}
> +
> +	fltr_entry.port_type = OCTTX_PORT_TYPE_NET;
> +	fltr_entry.vlan_tpid = RTE_ETHER_TYPE_VLAN;
> +	fltr_entry.vlan_id = vlan_id;
> +	fltr_entry.entry_conf = on;
> +
> +	if (on) {
> +		entry = rte_zmalloc("octeontx_nic_vlan_entry",
> +				    sizeof(struct vlan_entry), 0);
> +		if (!entry) {
> +			octeontx_log_err("Failed to allocate memory");
> +			return -ENOMEM;
> +		}
> +	}
> +
> +	rc = octeontx_pki_port_vlan_fltr_entry_config(nic->port_id,
> +						      &fltr_entry);
> +	if (rc != 0) {
> +		octeontx_log_err("Fail to configure vlan filter entry "
> +				 "for port %d", nic->port_id);
> +		if (entry)
> +			rte_free(entry);
> +
> +		goto done;
> +	}
> +
> +	if (on) {
> +		entry->vlan_id  = vlan_id;
> +		TAILQ_INSERT_HEAD(&vlan->fltr_tbl, entry, next);
> +	} else {
> +		TAILQ_FOREACH(entry, &vlan->fltr_tbl, next) {
> +			if (entry->vlan_id == vlan_id) {
> +				TAILQ_REMOVE(&vlan->fltr_tbl, entry, next);
> +				rte_free(entry);
> +				break;
> +			}
> +		}
> +	}
> +
> +done:
> +	return rc;
> +}
> +
> +int
> +octeontx_dev_vlan_offload_init(struct rte_eth_dev *dev)
> +{
> +	struct octeontx_nic *nic = octeontx_pmd_priv(dev);
> +	int rc;
> +
> +	TAILQ_INIT(&nic->vlan_info.fltr_tbl);
> +
> +	rc = octeontx_dev_vlan_offload_set(dev, ETH_VLAN_FILTER_MASK);
> +	if (rc)
> +		octeontx_log_err("Failed to set vlan offload rc=%d", rc);
> +
> +	return rc;
> +}
> +
> +int
> +octeontx_dev_vlan_offload_fini(struct rte_eth_dev *dev)
> +{
> +	struct octeontx_nic *nic = octeontx_pmd_priv(dev);
> +	struct octeontx_vlan_info *vlan = &nic->vlan_info;
> +	pki_port_vlan_filter_entry_config_t fltr_entry;
> +	struct vlan_entry *entry;
> +	int rc = 0;
> +
> +	TAILQ_FOREACH(entry, &vlan->fltr_tbl, next) {
> +		fltr_entry.port_type = OCTTX_PORT_TYPE_NET;
> +		fltr_entry.vlan_tpid = RTE_ETHER_TYPE_VLAN;
> +		fltr_entry.vlan_id = entry->vlan_id;
> +		fltr_entry.entry_conf = 0;
> +
> +		rc = octeontx_pki_port_vlan_fltr_entry_config(nic->port_id,
> +							      &fltr_entry);
> +		if (rc != 0) {
> +			octeontx_log_err("Fail to configure vlan filter entry "
> +					 "for port %d", nic->port_id);
> +			break;
> +		}
> +	}
> +
> +	return rc;
> +}
> diff --git a/drivers/net/octeontx/octeontx_rxtx.h b/drivers/net/octeontx/octeontx_rxtx.h
> index 2383a8eb6..cc044dd79 100644
> --- a/drivers/net/octeontx/octeontx_rxtx.h
> +++ b/drivers/net/octeontx/octeontx_rxtx.h
> @@ -19,6 +19,7 @@
>  
>  #define OCCTX_RX_OFFLOAD_NONE		(0)
>  #define OCCTX_RX_OFFLOAD_RSS_F          BIT(0)
> +#define OCCTX_RX_VLAN_FLTR_F            BIT(1)
>  #define OCCTX_RX_MULTI_SEG_F		BIT(15)
>  
>  #define OCCTX_TX_OFFLOAD_NONE		(0)
> -- 
> 2.18.0
>
  

Patch

diff --git a/doc/guides/nics/features/octeontx.ini b/doc/guides/nics/features/octeontx.ini
index e3ee79f0f..53c541f4b 100644
--- a/doc/guides/nics/features/octeontx.ini
+++ b/doc/guides/nics/features/octeontx.ini
@@ -13,6 +13,8 @@  Jumbo frame          = Y
 Scattered Rx         = Y
 Promiscuous mode     = Y
 Unicast MAC filter   = Y
+VLAN filter          = Y
+VLAN offload         = P
 CRC offload          = Y
 Packet type parsing  = Y
 Basic stats          = Y
diff --git a/doc/guides/nics/octeontx.rst b/doc/guides/nics/octeontx.rst
index ddb626bc3..c8655bf37 100644
--- a/doc/guides/nics/octeontx.rst
+++ b/doc/guides/nics/octeontx.rst
@@ -22,6 +22,7 @@  Features of the OCTEON TX Ethdev PMD are:
 - Jumbo frames
 - Scatter-Gather IO support
 - Link state information
+- MAC/VLAN filtering
 - MTU update
 - SR-IOV VF
 - Multiple queues for TX
diff --git a/drivers/net/octeontx/Makefile b/drivers/net/octeontx/Makefile
index 8ddfc3089..694f403f1 100644
--- a/drivers/net/octeontx/Makefile
+++ b/drivers/net/octeontx/Makefile
@@ -28,6 +28,7 @@  SRCS-$(CONFIG_RTE_LIBRTE_OCTEONTX_PMD) += octeontx_pkovf.c
 SRCS-$(CONFIG_RTE_LIBRTE_OCTEONTX_PMD) += octeontx_pkivf.c
 SRCS-$(CONFIG_RTE_LIBRTE_OCTEONTX_PMD) += octeontx_bgx.c
 SRCS-$(CONFIG_RTE_LIBRTE_OCTEONTX_PMD) += octeontx_ethdev.c
+SRCS-$(CONFIG_RTE_LIBRTE_OCTEONTX_PMD) += octeontx_ethdev_ops.c
 
 ifeq ($(CONFIG_RTE_TOOLCHAIN_GCC),y)
 CFLAGS_octeontx_rxtx.o += -fno-prefetch-loop-arrays
diff --git a/drivers/net/octeontx/base/octeontx_pkivf.c b/drivers/net/octeontx/base/octeontx_pkivf.c
index 8ce041955..0ddff5488 100644
--- a/drivers/net/octeontx/base/octeontx_pkivf.c
+++ b/drivers/net/octeontx/base/octeontx_pkivf.c
@@ -136,6 +136,46 @@  octeontx_pki_port_errchk_config(int port, pki_errchk_cfg_t *cfg)
 	return res;
 }
 
+int
+octeontx_pki_port_vlan_fltr_config(int port,
+				   pki_port_vlan_filter_config_t *fltr_cfg)
+{
+	struct octeontx_mbox_hdr hdr;
+	int res;
+
+	pki_port_vlan_filter_config_t cfg = *fltr_cfg;
+	int len = sizeof(pki_port_vlan_filter_config_t);
+
+	hdr.coproc = OCTEONTX_PKI_COPROC;
+	hdr.msg = MBOX_PKI_PORT_VLAN_FILTER_CONFIG;
+	hdr.vfid = port;
+
+	res = octeontx_mbox_send(&hdr, &cfg, len, NULL, 0);
+	if (res < 0)
+		return -EACCES;
+	return res;
+}
+
+int
+octeontx_pki_port_vlan_fltr_entry_config(int port,
+				   pki_port_vlan_filter_entry_config_t *e_cfg)
+{
+	struct octeontx_mbox_hdr hdr;
+	int res;
+
+	pki_port_vlan_filter_entry_config_t cfg = *e_cfg;
+	int len = sizeof(pki_port_vlan_filter_entry_config_t);
+
+	hdr.coproc = OCTEONTX_PKI_COPROC;
+	hdr.msg = MBOX_PKI_PORT_VLAN_FILTER_ENTRY_CONFIG;
+	hdr.vfid = port;
+
+	res = octeontx_mbox_send(&hdr, &cfg, len, NULL, 0);
+	if (res < 0)
+		return -EACCES;
+	return res;
+}
+
 #define PCI_VENDOR_ID_CAVIUM               0x177D
 #define PCI_DEVICE_ID_OCTEONTX_PKI_VF      0xA0DD
 
diff --git a/drivers/net/octeontx/base/octeontx_pkivf.h b/drivers/net/octeontx/base/octeontx_pkivf.h
index d541dc3bd..d41eaa57e 100644
--- a/drivers/net/octeontx/base/octeontx_pkivf.h
+++ b/drivers/net/octeontx/base/octeontx_pkivf.h
@@ -36,6 +36,8 @@ 
 #define MBOX_PKI_PORT_ALLOC_QPG			21
 #define MBOX_PKI_PORT_FREE_QPG			22
 #define MBOX_PKI_SET_PORT_CONFIG		23
+#define MBOX_PKI_PORT_VLAN_FILTER_CONFIG	24
+#define MBOX_PKI_PORT_VLAN_FILTER_ENTRY_CONFIG	25
 
 #define MBOX_PKI_MAX_QOS_ENTRY 64
 
@@ -236,6 +238,20 @@  typedef struct pki_port_modify_qos_entry {
 	struct pki_qos_entry qos_entry;
 } pki_mod_qos_t;
 
+/* pki port VLAN filter config */
+typedef struct pki_port_vlan_filter_config {
+	uint8_t port_type;  /* OCTTX_PORT_TYPE_[NET/INT/PCI] */
+	uint8_t fltr_conf; /* '1' to enable & '0' to disable */
+} pki_port_vlan_filter_config_t;
+
+/* pki port VLAN filter entry config */
+typedef struct pki_port_vlan_filter_entry_config {
+	uint8_t port_type;  /* OCTTX_PORT_TYPE_[NET/INT/PCI] */
+	uint8_t entry_conf; /* '1' to add & '0' to remove */
+	uint16_t vlan_tpid; /* in host byte-order */
+	uint16_t vlan_id;   /* in host byte-order */
+} pki_port_vlan_filter_entry_config_t;
+
 static inline int
 octeontx_pki_port_modify_qos(int port, pki_mod_qos_t *qos_cfg)
 {
@@ -348,5 +364,9 @@  int octeontx_pki_port_pktbuf_config(int port, pki_pktbuf_cfg_t *buf_cfg);
 int octeontx_pki_port_create_qos(int port, pki_qos_cfg_t *qos_cfg);
 int octeontx_pki_port_close(int port);
 int octeontx_pki_port_errchk_config(int port, pki_errchk_cfg_t *cfg);
+int octeontx_pki_port_vlan_fltr_config(int port,
+				pki_port_vlan_filter_config_t *fltr_cfg);
+int octeontx_pki_port_vlan_fltr_entry_config(int port,
+				pki_port_vlan_filter_entry_config_t *entry_cfg);
 
 #endif /* __OCTEONTX_PKI_H__ */
diff --git a/drivers/net/octeontx/meson.build b/drivers/net/octeontx/meson.build
index 0e249eb98..f7ba6e68b 100644
--- a/drivers/net/octeontx/meson.build
+++ b/drivers/net/octeontx/meson.build
@@ -5,7 +5,8 @@  subdir('base')
 objs = [base_objs]
 
 sources = files('octeontx_rxtx.c',
-		'octeontx_ethdev.c'
+		'octeontx_ethdev.c',
+		'octeontx_ethdev_ops.c'
 		)
 
 allow_experimental_apis = true
diff --git a/drivers/net/octeontx/octeontx_ethdev.c b/drivers/net/octeontx/octeontx_ethdev.c
index 91b9ea645..5dd40bc04 100644
--- a/drivers/net/octeontx/octeontx_ethdev.c
+++ b/drivers/net/octeontx/octeontx_ethdev.c
@@ -360,6 +360,12 @@  octeontx_dev_configure(struct rte_eth_dev *dev)
 		return -EFAULT;
 	}
 
+	ret = octeontx_dev_vlan_offload_init(dev);
+	if (ret) {
+		octeontx_log_err("failed to initialize vlan offload");
+		return -EFAULT;
+	}
+
 	nic->pki.classifier_enable = false;
 	nic->pki.hash_enable = true;
 	nic->pki.initialized = false;
@@ -384,6 +390,8 @@  octeontx_dev_close(struct rte_eth_dev *dev)
 
 	rte_event_dev_close(nic->evdev);
 
+	octeontx_dev_vlan_offload_fini(dev);
+
 	ret = octeontx_pko_channel_close(nic->base_ochan);
 	if (ret < 0) {
 		octeontx_log_err("failed to close channel %d VF%d %d %d",
@@ -1185,6 +1193,8 @@  static const struct eth_dev_ops octeontx_dev_ops = {
 	.mac_addr_remove	 = octeontx_dev_mac_addr_del,
 	.mac_addr_add		 = octeontx_dev_mac_addr_add,
 	.mac_addr_set		 = octeontx_dev_default_mac_addr_set,
+	.vlan_offload_set	 = octeontx_dev_vlan_offload_set,
+	.vlan_filter_set	 = octeontx_dev_vlan_filter_set,
 	.tx_queue_start		 = octeontx_dev_tx_queue_start,
 	.tx_queue_stop		 = octeontx_dev_tx_queue_stop,
 	.tx_queue_setup		 = octeontx_dev_tx_queue_setup,
diff --git a/drivers/net/octeontx/octeontx_ethdev.h b/drivers/net/octeontx/octeontx_ethdev.h
index 27f6556dd..e7e0d40c7 100644
--- a/drivers/net/octeontx/octeontx_ethdev.h
+++ b/drivers/net/octeontx/octeontx_ethdev.h
@@ -55,7 +55,8 @@ 
 
 #define OCTEONTX_RX_OFFLOADS		(DEV_RX_OFFLOAD_CHECKSUM     | \
 					 DEV_RX_OFFLOAD_SCATTER	     | \
-					 DEV_RX_OFFLOAD_JUMBO_FRAME)
+					 DEV_RX_OFFLOAD_JUMBO_FRAME  | \
+					 DEV_RX_OFFLOAD_VLAN_FILTER)
 
 #define OCTEONTX_TX_OFFLOADS		(DEV_TX_OFFLOAD_MT_LOCKFREE    |  \
 					 DEV_TX_OFFLOAD_MBUF_FAST_FREE |  \
@@ -70,6 +71,18 @@  octeontx_pmd_priv(struct rte_eth_dev *dev)
 extern uint16_t
 rte_octeontx_pchan_map[OCTEONTX_MAX_BGX_PORTS][OCTEONTX_MAX_LMAC_PER_BGX];
 
+struct vlan_entry {
+	TAILQ_ENTRY(vlan_entry) next;
+	uint16_t vlan_id;
+};
+
+TAILQ_HEAD(octeontx_vlan_filter_tbl, vlan_entry);
+
+struct octeontx_vlan_info {
+	struct octeontx_vlan_filter_tbl fltr_tbl;
+	uint8_t filter_on;
+};
+
 /* Octeontx ethdev nic */
 struct octeontx_nic {
 	struct rte_eth_dev *dev;
@@ -107,6 +120,7 @@  struct octeontx_nic {
 	uint16_t rx_offload_flags;
 	uint64_t tx_offloads;
 	uint16_t tx_offload_flags;
+	struct octeontx_vlan_info vlan_info;
 } __rte_cache_aligned;
 
 struct octeontx_txq {
@@ -127,4 +141,12 @@  struct octeontx_rxq {
 
 void
 octeontx_set_tx_function(struct rte_eth_dev *dev);
+
+/* VLAN */
+int octeontx_dev_vlan_offload_init(struct rte_eth_dev *dev);
+int octeontx_dev_vlan_offload_fini(struct rte_eth_dev *eth_dev);
+int octeontx_dev_vlan_offload_set(struct rte_eth_dev *dev, int mask);
+int octeontx_dev_vlan_filter_set(struct rte_eth_dev *dev,
+				 uint16_t vlan_id, int on);
+
 #endif /* __OCTEONTX_ETHDEV_H__ */
diff --git a/drivers/net/octeontx/octeontx_ethdev_ops.c b/drivers/net/octeontx/octeontx_ethdev_ops.c
new file mode 100644
index 000000000..8c3065542
--- /dev/null
+++ b/drivers/net/octeontx/octeontx_ethdev_ops.c
@@ -0,0 +1,184 @@ 
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(C) 2020 Marvell International Ltd.
+ */
+
+#include <rte_malloc.h>
+
+#include "octeontx_ethdev.h"
+#include "octeontx_logs.h"
+#include "octeontx_rxtx.h"
+
+static int
+octeontx_vlan_hw_filter(struct octeontx_nic *nic, uint8_t flag)
+{
+	struct octeontx_vlan_info *vlan = &nic->vlan_info;
+	pki_port_vlan_filter_config_t fltr_conf;
+	int rc = 0;
+
+	if (vlan->filter_on == flag)
+		return rc;
+
+	fltr_conf.port_type = OCTTX_PORT_TYPE_NET;
+	fltr_conf.fltr_conf = flag;
+
+	rc = octeontx_pki_port_vlan_fltr_config(nic->port_id, &fltr_conf);
+	if (rc != 0) {
+		octeontx_log_err("Fail to configure vlan hw filter for port %d",
+				 nic->port_id);
+		goto done;
+	}
+
+	vlan->filter_on = flag;
+
+done:
+	return rc;
+}
+
+int
+octeontx_dev_vlan_offload_set(struct rte_eth_dev *dev, int mask)
+{
+	struct octeontx_nic *nic = octeontx_pmd_priv(dev);
+	struct rte_eth_rxmode *rxmode;
+	int rc = 0;
+
+	rxmode = &dev->data->dev_conf.rxmode;
+
+	if (mask & ETH_VLAN_EXTEND_MASK) {
+		octeontx_log_err("Extend offload not supported");
+		return -ENOTSUP;
+	}
+
+	if (mask & ETH_VLAN_STRIP_MASK) {
+		octeontx_log_err("VLAN strip offload not supported");
+		return -ENOTSUP;
+	}
+
+	if (mask & ETH_VLAN_FILTER_MASK) {
+		if (rxmode->offloads & DEV_RX_OFFLOAD_VLAN_FILTER) {
+			rc = octeontx_vlan_hw_filter(nic, true);
+			if (rc)
+				goto done;
+
+			nic->rx_offloads |= DEV_RX_OFFLOAD_VLAN_FILTER;
+			nic->rx_offload_flags |= OCCTX_RX_VLAN_FLTR_F;
+		} else {
+			rc = octeontx_vlan_hw_filter(nic, false);
+			if (rc)
+				goto done;
+
+			nic->rx_offloads &= ~DEV_RX_OFFLOAD_VLAN_FILTER;
+			nic->rx_offload_flags &= ~OCCTX_RX_VLAN_FLTR_F;
+		}
+	}
+
+done:
+	return rc;
+}
+
+int
+octeontx_dev_vlan_filter_set(struct rte_eth_dev *dev, uint16_t vlan_id, int on)
+{
+	struct octeontx_nic *nic = octeontx_pmd_priv(dev);
+	struct octeontx_vlan_info *vlan = &nic->vlan_info;
+	pki_port_vlan_filter_entry_config_t fltr_entry;
+	struct vlan_entry *entry = NULL;
+	int entry_count = 0;
+	int rc = -EINVAL;
+
+	if (on) {
+		TAILQ_FOREACH(entry, &vlan->fltr_tbl, next)
+			if (entry->vlan_id == vlan_id) {
+				octeontx_log_dbg("Vlan Id is already set");
+				return 0;
+			}
+	} else {
+		TAILQ_FOREACH(entry, &vlan->fltr_tbl, next)
+			entry_count++;
+
+		if (!entry_count)
+			return 0;
+	}
+
+	fltr_entry.port_type = OCTTX_PORT_TYPE_NET;
+	fltr_entry.vlan_tpid = RTE_ETHER_TYPE_VLAN;
+	fltr_entry.vlan_id = vlan_id;
+	fltr_entry.entry_conf = on;
+
+	if (on) {
+		entry = rte_zmalloc("octeontx_nic_vlan_entry",
+				    sizeof(struct vlan_entry), 0);
+		if (!entry) {
+			octeontx_log_err("Failed to allocate memory");
+			return -ENOMEM;
+		}
+	}
+
+	rc = octeontx_pki_port_vlan_fltr_entry_config(nic->port_id,
+						      &fltr_entry);
+	if (rc != 0) {
+		octeontx_log_err("Fail to configure vlan filter entry "
+				 "for port %d", nic->port_id);
+		if (entry)
+			rte_free(entry);
+
+		goto done;
+	}
+
+	if (on) {
+		entry->vlan_id  = vlan_id;
+		TAILQ_INSERT_HEAD(&vlan->fltr_tbl, entry, next);
+	} else {
+		TAILQ_FOREACH(entry, &vlan->fltr_tbl, next) {
+			if (entry->vlan_id == vlan_id) {
+				TAILQ_REMOVE(&vlan->fltr_tbl, entry, next);
+				rte_free(entry);
+				break;
+			}
+		}
+	}
+
+done:
+	return rc;
+}
+
+int
+octeontx_dev_vlan_offload_init(struct rte_eth_dev *dev)
+{
+	struct octeontx_nic *nic = octeontx_pmd_priv(dev);
+	int rc;
+
+	TAILQ_INIT(&nic->vlan_info.fltr_tbl);
+
+	rc = octeontx_dev_vlan_offload_set(dev, ETH_VLAN_FILTER_MASK);
+	if (rc)
+		octeontx_log_err("Failed to set vlan offload rc=%d", rc);
+
+	return rc;
+}
+
+int
+octeontx_dev_vlan_offload_fini(struct rte_eth_dev *dev)
+{
+	struct octeontx_nic *nic = octeontx_pmd_priv(dev);
+	struct octeontx_vlan_info *vlan = &nic->vlan_info;
+	pki_port_vlan_filter_entry_config_t fltr_entry;
+	struct vlan_entry *entry;
+	int rc = 0;
+
+	TAILQ_FOREACH(entry, &vlan->fltr_tbl, next) {
+		fltr_entry.port_type = OCTTX_PORT_TYPE_NET;
+		fltr_entry.vlan_tpid = RTE_ETHER_TYPE_VLAN;
+		fltr_entry.vlan_id = entry->vlan_id;
+		fltr_entry.entry_conf = 0;
+
+		rc = octeontx_pki_port_vlan_fltr_entry_config(nic->port_id,
+							      &fltr_entry);
+		if (rc != 0) {
+			octeontx_log_err("Fail to configure vlan filter entry "
+					 "for port %d", nic->port_id);
+			break;
+		}
+	}
+
+	return rc;
+}
diff --git a/drivers/net/octeontx/octeontx_rxtx.h b/drivers/net/octeontx/octeontx_rxtx.h
index 2383a8eb6..cc044dd79 100644
--- a/drivers/net/octeontx/octeontx_rxtx.h
+++ b/drivers/net/octeontx/octeontx_rxtx.h
@@ -19,6 +19,7 @@ 
 
 #define OCCTX_RX_OFFLOAD_NONE		(0)
 #define OCCTX_RX_OFFLOAD_RSS_F          BIT(0)
+#define OCCTX_RX_VLAN_FLTR_F            BIT(1)
 #define OCCTX_RX_MULTI_SEG_F		BIT(15)
 
 #define OCCTX_TX_OFFLOAD_NONE		(0)