[dpdk-dev] eth_dev: make ether dev_ops const

Message ID 1428343496-26532-1-git-send-email-stephen@networkplumber.org (mailing list archive)
State Superseded, archived
Headers

Commit Message

Stephen Hemminger April 6, 2015, 6:04 p.m. UTC
  Ethernet device function tables should be immutable for correctness
and security. Special case for the test code driver.

Also reindent a couple of places where the table was indented
in a non-standard way.

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
 app/test/virtual_pmd.c                       | 78 +++++++++++++++-------------
 lib/librte_ether/rte_ethdev.h                |  2 +-
 lib/librte_pmd_af_packet/rte_eth_af_packet.c |  2 +-
 lib/librte_pmd_e1000/em_ethdev.c             |  2 +-
 lib/librte_pmd_e1000/igb_ethdev.c            |  4 +-
 lib/librte_pmd_enic/enic_ethdev.c            |  2 +-
 lib/librte_pmd_fm10k/fm10k_ethdev.c          |  2 +-
 lib/librte_pmd_i40e/i40e_ethdev.c            |  2 +-
 lib/librte_pmd_i40e/i40e_ethdev_vf.c         |  2 +-
 lib/librte_pmd_ixgbe/ixgbe_ethdev.c          |  5 +-
 lib/librte_pmd_mlx4/mlx4.c                   |  2 +-
 lib/librte_pmd_null/rte_eth_null.c           | 24 ++++-----
 lib/librte_pmd_pcap/rte_eth_pcap.c           | 26 +++++-----
 lib/librte_pmd_ring/rte_eth_ring.c           | 32 ++++++------
 lib/librte_pmd_virtio/virtio_ethdev.c        |  2 +-
 lib/librte_pmd_vmxnet3/vmxnet3_ethdev.c      |  2 +-
 lib/librte_pmd_xenvirt/rte_eth_xenvirt.c     | 26 +++++-----
 17 files changed, 111 insertions(+), 104 deletions(-)
  

Comments

don provan April 7, 2015, 5:21 p.m. UTC | #1
-----Original Message-----
>From: Stephen Hemminger [mailto:stephen@networkplumber.org] 
>Sent: Monday, April 06, 2015 11:05 AM
>To: dev@dpdk.org
>Subject: [dpdk-dev] [PATCH] eth_dev: make ether dev_ops const
>
>Ethernet device function tables should be immutable for correctness and security. Special case for the test code driver.
...
>diff --git a/app/test/virtual_pmd.c b/app/test/virtual_pmd.c index f163562..f579558 100644
>--- a/app/test/virtual_pmd.c
>+++ b/app/test/virtual_pmd.c
...
>+/* This driver uses private mutable eth_dev_ops for each
>+ * instance so it is safe to override const here.
>+ */
>+#pragma GCC diagnostic push
>+#pragma GCC diagnostic ignored "-Wcast-qual"
> void
> virtual_ethdev_start_fn_set_success(uint8_t port_id, uint8_t success)  {
> 	struct rte_eth_dev *vrtl_eth_dev = &rte_eth_devices[port_id];
>+	struct eth_dev_ops *dev_ops
>+		= (struct eth_dev_ops *) vrtl_eth_dev->dev_ops;
 ...

If this is really safe, then you should be able to accomplish it
without disabling a bunch of protection. I suggest adding a
pointer that isn't const to the private data block and adjusting
the allocated dispatch table through that instead of through
the pointer to the immutable dispatch table you've established
in struct rte_eth_dev. That reinforces the fact that modifying
the dispatch table is a private matter within the driver while
showing structurally exactly why it's safe to change it.

And it's not nearly so ugly.

-don provan
dprovan@bivio.net
  
Stephen Hemminger April 7, 2015, 6:46 p.m. UTC | #2
On Tue, Apr 7, 2015 at 10:21 AM, Don Provan <dprovan@bivio.net> wrote:

> -----Original Message-----
> >From: Stephen Hemminger [mailto:stephen@networkplumber.org]
> >Sent: Monday, April 06, 2015 11:05 AM
> >To: dev@dpdk.org
> >Subject: [dpdk-dev] [PATCH] eth_dev: make ether dev_ops const
> >
> >Ethernet device function tables should be immutable for correctness and
> security. Special case for the test code driver.
> ...
> >diff --git a/app/test/virtual_pmd.c b/app/test/virtual_pmd.c index
> f163562..f579558 100644
> >--- a/app/test/virtual_pmd.c
> >+++ b/app/test/virtual_pmd.c
> ...
> >+/* This driver uses private mutable eth_dev_ops for each
> >+ * instance so it is safe to override const here.
> >+ */
> >+#pragma GCC diagnostic push
> >+#pragma GCC diagnostic ignored "-Wcast-qual"
> > void
> > virtual_ethdev_start_fn_set_success(uint8_t port_id, uint8_t success)  {
> >       struct rte_eth_dev *vrtl_eth_dev = &rte_eth_devices[port_id];
> >+      struct eth_dev_ops *dev_ops
> >+              = (struct eth_dev_ops *) vrtl_eth_dev->dev_ops;
>  ...
>
> If this is really safe, then you should be able to accomplish it
> without disabling a bunch of protection. I suggest adding a
> pointer that isn't const to the private data block and adjusting
> the allocated dispatch table through that instead of through
> the pointer to the immutable dispatch table you've established
> in struct rte_eth_dev. That reinforces the fact that modifying
> the dispatch table is a private matter within the driver while
> showing structurally exactly why it's safe to change it.
>
> And it's not nearly so ugly.
>
> -don provan
> dprovan@bivio.net
>
>
In this case it is safe, but only because this dummy driver used in testing
does non-standard things.
It copies a base template for ops into a allocated area of memory, then
modifies it.
Not the best design, but did not want to hold back the ethernet dev_ops.
Probably the private pointer is a better way.
  
Nissim Nisimov April 8, 2015, 5:45 a.m. UTC | #3
Hi,

Is there any limit to work with dpdk within different pthreads in parallel to multi-process system

For example, I will have a system with one primary processes with 4 pthreads and in addition I will have another 4 secondary processes 

All of the above will call to dpdk APIs. Is it possible in today code?


Thx
Nissim
  

Patch

diff --git a/app/test/virtual_pmd.c b/app/test/virtual_pmd.c
index f163562..f579558 100644
--- a/app/test/virtual_pmd.c
+++ b/app/test/virtual_pmd.c
@@ -241,33 +241,39 @@  virtual_ethdev_promiscuous_mode_disable(struct rte_eth_dev *dev __rte_unused)
 {}
 
 
-static struct eth_dev_ops virtual_ethdev_default_dev_ops = {
-		.dev_configure = virtual_ethdev_configure_success,
-		.dev_start = virtual_ethdev_start_success,
-		.dev_stop = virtual_ethdev_stop,
-		.dev_close = virtual_ethdev_close,
-		.dev_infos_get = virtual_ethdev_info_get,
-		.rx_queue_setup = virtual_ethdev_rx_queue_setup_success,
-		.tx_queue_setup = virtual_ethdev_tx_queue_setup_success,
-		.rx_queue_release = virtual_ethdev_rx_queue_release,
-		.tx_queue_release = virtual_ethdev_tx_queue_release,
-		.link_update = virtual_ethdev_link_update_success,
-		.stats_get = virtual_ethdev_stats_get,
-		.stats_reset = virtual_ethdev_stats_reset,
-		.promiscuous_enable = virtual_ethdev_promiscuous_mode_enable,
-		.promiscuous_disable = virtual_ethdev_promiscuous_mode_disable
+static const struct eth_dev_ops virtual_ethdev_default_dev_ops = {
+	.dev_configure = virtual_ethdev_configure_success,
+	.dev_start = virtual_ethdev_start_success,
+	.dev_stop = virtual_ethdev_stop,
+	.dev_close = virtual_ethdev_close,
+	.dev_infos_get = virtual_ethdev_info_get,
+	.rx_queue_setup = virtual_ethdev_rx_queue_setup_success,
+	.tx_queue_setup = virtual_ethdev_tx_queue_setup_success,
+	.rx_queue_release = virtual_ethdev_rx_queue_release,
+	.tx_queue_release = virtual_ethdev_tx_queue_release,
+	.link_update = virtual_ethdev_link_update_success,
+	.stats_get = virtual_ethdev_stats_get,
+	.stats_reset = virtual_ethdev_stats_reset,
+	.promiscuous_enable = virtual_ethdev_promiscuous_mode_enable,
+	.promiscuous_disable = virtual_ethdev_promiscuous_mode_disable
 };
 
-
+/* This driver uses private mutable eth_dev_ops for each
+ * instance so it is safe to override const here.
+ */
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wcast-qual"
 void
 virtual_ethdev_start_fn_set_success(uint8_t port_id, uint8_t success)
 {
 	struct rte_eth_dev *vrtl_eth_dev = &rte_eth_devices[port_id];
+	struct eth_dev_ops *dev_ops
+		= (struct eth_dev_ops *) vrtl_eth_dev->dev_ops;
 
 	if (success)
-		vrtl_eth_dev->dev_ops->dev_start = virtual_ethdev_start_success;
+		dev_ops->dev_start = virtual_ethdev_start_success;
 	else
-		vrtl_eth_dev->dev_ops->dev_start = virtual_ethdev_start_fail;
+		dev_ops->dev_start = virtual_ethdev_start_fail;
 
 }
 
@@ -275,50 +281,54 @@  void
 virtual_ethdev_configure_fn_set_success(uint8_t port_id, uint8_t success)
 {
 	struct rte_eth_dev *vrtl_eth_dev = &rte_eth_devices[port_id];
+	struct eth_dev_ops *dev_ops
+		= (struct eth_dev_ops *) vrtl_eth_dev->dev_ops;
 
 	if (success)
-		vrtl_eth_dev->dev_ops->dev_configure = virtual_ethdev_configure_success;
+		dev_ops->dev_configure = virtual_ethdev_configure_success;
 	else
-		vrtl_eth_dev->dev_ops->dev_configure = virtual_ethdev_configure_fail;
+		dev_ops->dev_configure = virtual_ethdev_configure_fail;
 }
 
 void
 virtual_ethdev_rx_queue_setup_fn_set_success(uint8_t port_id, uint8_t success)
 {
 	struct rte_eth_dev *vrtl_eth_dev = &rte_eth_devices[port_id];
+	struct eth_dev_ops *dev_ops
+		= (struct eth_dev_ops *) vrtl_eth_dev->dev_ops;
 
 	if (success)
-		vrtl_eth_dev->dev_ops->rx_queue_setup =
-				virtual_ethdev_rx_queue_setup_success;
+		dev_ops->rx_queue_setup = virtual_ethdev_rx_queue_setup_success;
 	else
-		vrtl_eth_dev->dev_ops->rx_queue_setup =
-				virtual_ethdev_rx_queue_setup_fail;
+		dev_ops->rx_queue_setup = virtual_ethdev_rx_queue_setup_fail;
 }
 
 void
 virtual_ethdev_tx_queue_setup_fn_set_success(uint8_t port_id, uint8_t success)
 {
 	struct rte_eth_dev *vrtl_eth_dev = &rte_eth_devices[port_id];
+	struct eth_dev_ops *dev_ops
+		= (struct eth_dev_ops *) vrtl_eth_dev->dev_ops;
 
 	if (success)
-		vrtl_eth_dev->dev_ops->tx_queue_setup =
-				virtual_ethdev_tx_queue_setup_success;
+		dev_ops->tx_queue_setup = virtual_ethdev_tx_queue_setup_success;
 	else
-		vrtl_eth_dev->dev_ops->tx_queue_setup =
-				virtual_ethdev_tx_queue_setup_fail;
+		dev_ops->tx_queue_setup = virtual_ethdev_tx_queue_setup_fail;
 }
 
 void
 virtual_ethdev_link_update_fn_set_success(uint8_t port_id, uint8_t success)
 {
 	struct rte_eth_dev *vrtl_eth_dev = &rte_eth_devices[port_id];
+	struct eth_dev_ops *dev_ops
+		= (struct eth_dev_ops *) vrtl_eth_dev->dev_ops;
 
 	if (success)
-		vrtl_eth_dev->dev_ops->link_update = virtual_ethdev_link_update_success;
+		dev_ops->link_update = virtual_ethdev_link_update_success;
 	else
-		vrtl_eth_dev->dev_ops->link_update = virtual_ethdev_link_update_fail;
+		dev_ops->link_update = virtual_ethdev_link_update_fail;
 }
-
+#pragma GCC diagnostic pop
 
 static uint16_t
 virtual_ethdev_rx_burst_success(void *queue __rte_unused,
@@ -620,11 +630,9 @@  virtual_ethdev_create(const char *name, struct ether_addr *mac_addr,
 
 	eth_dev->data->dev_private = dev_private;
 
-	eth_dev->dev_ops = dev_ops;
-
 	/* Copy default device operation functions */
-	memcpy(eth_dev->dev_ops, &virtual_ethdev_default_dev_ops,
-			sizeof(*eth_dev->dev_ops));
+	*dev_ops = virtual_ethdev_default_dev_ops;
+	eth_dev->dev_ops = dev_ops;
 
 	eth_dev->pci_dev = pci_dev;
 	eth_dev->pci_dev->driver = &eth_drv->pci_drv;
diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h
index e8df027..46a55ff 100644
--- a/lib/librte_ether/rte_ethdev.h
+++ b/lib/librte_ether/rte_ethdev.h
@@ -1472,7 +1472,7 @@  struct rte_eth_dev {
 	eth_tx_burst_t tx_pkt_burst; /**< Pointer to PMD transmit function. */
 	struct rte_eth_dev_data *data;  /**< Pointer to device data */
 	const struct eth_driver *driver;/**< Driver for this device */
-	struct eth_dev_ops *dev_ops;    /**< Functions exported by PMD */
+	const struct eth_dev_ops *dev_ops; /**< Functions exported by PMD */
 	struct rte_pci_device *pci_dev; /**< PCI info. supplied by probing */
 	/** User application callbacks for NIC interrupts */
 	struct rte_eth_dev_cb_list link_intr_cbs;
diff --git a/lib/librte_pmd_af_packet/rte_eth_af_packet.c b/lib/librte_pmd_af_packet/rte_eth_af_packet.c
index 2ac50ba..1bea12f 100644
--- a/lib/librte_pmd_af_packet/rte_eth_af_packet.c
+++ b/lib/librte_pmd_af_packet/rte_eth_af_packet.c
@@ -384,7 +384,7 @@  eth_tx_queue_setup(struct rte_eth_dev *dev,
 	return 0;
 }
 
-static struct eth_dev_ops ops = {
+static const struct eth_dev_ops ops = {
 	.dev_start = eth_dev_start,
 	.dev_stop = eth_dev_stop,
 	.dev_close = eth_dev_close,
diff --git a/lib/librte_pmd_e1000/em_ethdev.c b/lib/librte_pmd_e1000/em_ethdev.c
index 76f45c9..12ecf5f 100644
--- a/lib/librte_pmd_e1000/em_ethdev.c
+++ b/lib/librte_pmd_e1000/em_ethdev.c
@@ -133,7 +133,7 @@  static struct rte_pci_id pci_id_em_map[] = {
 {.device_id = 0},
 };
 
-static struct eth_dev_ops eth_em_ops = {
+static const struct eth_dev_ops eth_em_ops = {
 	.dev_configure        = eth_em_configure,
 	.dev_start            = eth_em_start,
 	.dev_stop             = eth_em_stop,
diff --git a/lib/librte_pmd_e1000/igb_ethdev.c b/lib/librte_pmd_e1000/igb_ethdev.c
index b3892a5..1ea2d38 100644
--- a/lib/librte_pmd_e1000/igb_ethdev.c
+++ b/lib/librte_pmd_e1000/igb_ethdev.c
@@ -235,7 +235,7 @@  static struct rte_pci_id pci_id_igbvf_map[] = {
 {.device_id = 0},
 };
 
-static struct eth_dev_ops eth_igb_ops = {
+static const struct eth_dev_ops eth_igb_ops = {
 	.dev_configure        = eth_igb_configure,
 	.dev_start            = eth_igb_start,
 	.dev_stop             = eth_igb_stop,
@@ -275,7 +275,7 @@  static struct eth_dev_ops eth_igb_ops = {
  * dev_ops for virtual function, bare necessities for basic vf
  * operation have been implemented
  */
-static struct eth_dev_ops igbvf_eth_dev_ops = {
+static const struct eth_dev_ops igbvf_eth_dev_ops = {
 	.dev_configure        = igbvf_dev_configure,
 	.dev_start            = igbvf_dev_start,
 	.dev_stop             = igbvf_dev_stop,
diff --git a/lib/librte_pmd_enic/enic_ethdev.c b/lib/librte_pmd_enic/enic_ethdev.c
index 4950ede..742925a 100644
--- a/lib/librte_pmd_enic/enic_ethdev.c
+++ b/lib/librte_pmd_enic/enic_ethdev.c
@@ -503,7 +503,7 @@  static uint16_t enicpmd_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts,
 	return work_done;
 }
 
-static struct eth_dev_ops enicpmd_eth_dev_ops = {
+static const struct eth_dev_ops enicpmd_eth_dev_ops = {
 	.dev_configure        = enicpmd_dev_configure,
 	.dev_start            = enicpmd_dev_start,
 	.dev_stop             = enicpmd_dev_stop,
diff --git a/lib/librte_pmd_fm10k/fm10k_ethdev.c b/lib/librte_pmd_fm10k/fm10k_ethdev.c
index 0c7a80c..1a96cf2 100644
--- a/lib/librte_pmd_fm10k/fm10k_ethdev.c
+++ b/lib/librte_pmd_fm10k/fm10k_ethdev.c
@@ -1651,7 +1651,7 @@  fm10k_close_mbx_service(struct fm10k_hw *hw)
 	hw->mbx.ops.disconnect(hw, &hw->mbx);
 }
 
-static struct eth_dev_ops fm10k_eth_dev_ops = {
+static const struct eth_dev_ops fm10k_eth_dev_ops = {
 	.dev_configure		= fm10k_dev_configure,
 	.dev_start		= fm10k_dev_start,
 	.dev_stop		= fm10k_dev_stop,
diff --git a/lib/librte_pmd_i40e/i40e_ethdev.c b/lib/librte_pmd_i40e/i40e_ethdev.c
index 6b8f96e..dc44764 100644
--- a/lib/librte_pmd_i40e/i40e_ethdev.c
+++ b/lib/librte_pmd_i40e/i40e_ethdev.c
@@ -218,7 +218,7 @@  static struct rte_pci_id pci_id_i40e_map[] = {
 { .vendor_id = 0, /* sentinel */ },
 };
 
-static struct eth_dev_ops i40e_eth_dev_ops = {
+static const struct eth_dev_ops i40e_eth_dev_ops = {
 	.dev_configure                = i40e_dev_configure,
 	.dev_start                    = i40e_dev_start,
 	.dev_stop                     = i40e_dev_stop,
diff --git a/lib/librte_pmd_i40e/i40e_ethdev_vf.c b/lib/librte_pmd_i40e/i40e_ethdev_vf.c
index c985e4a..4581c5b 100644
--- a/lib/librte_pmd_i40e/i40e_ethdev_vf.c
+++ b/lib/librte_pmd_i40e/i40e_ethdev_vf.c
@@ -148,7 +148,7 @@  static int i40evf_dev_rss_hash_conf_get(struct rte_eth_dev *dev,
 /* Default hash key buffer for RSS */
 static uint32_t rss_key_default[I40E_VFQF_HKEY_MAX_INDEX + 1];
 
-static struct eth_dev_ops i40evf_eth_dev_ops = {
+static const struct eth_dev_ops i40evf_eth_dev_ops = {
 	.dev_configure        = i40evf_dev_configure,
 	.dev_start            = i40evf_dev_start,
 	.dev_stop             = i40evf_dev_stop,
diff --git a/lib/librte_pmd_ixgbe/ixgbe_ethdev.c b/lib/librte_pmd_ixgbe/ixgbe_ethdev.c
index 5caee22..a7ac866 100644
--- a/lib/librte_pmd_ixgbe/ixgbe_ethdev.c
+++ b/lib/librte_pmd_ixgbe/ixgbe_ethdev.c
@@ -317,7 +317,7 @@  static struct rte_pci_id pci_id_ixgbevf_map[] = {
 
 };
 
-static struct eth_dev_ops ixgbe_eth_dev_ops = {
+static const struct eth_dev_ops ixgbe_eth_dev_ops = {
 	.dev_configure        = ixgbe_dev_configure,
 	.dev_start            = ixgbe_dev_start,
 	.dev_stop             = ixgbe_dev_stop,
@@ -387,8 +387,7 @@  static struct eth_dev_ops ixgbe_eth_dev_ops = {
  * dev_ops for virtual function, bare necessities for basic vf
  * operation have been implemented
  */
-static struct eth_dev_ops ixgbevf_eth_dev_ops = {
-
+static const struct eth_dev_ops ixgbevf_eth_dev_ops = {
 	.dev_configure        = ixgbevf_dev_configure,
 	.dev_start            = ixgbevf_dev_start,
 	.dev_stop             = ixgbevf_dev_stop,
diff --git a/lib/librte_pmd_mlx4/mlx4.c b/lib/librte_pmd_mlx4/mlx4.c
index fa749f4..d4d600a 100644
--- a/lib/librte_pmd_mlx4/mlx4.c
+++ b/lib/librte_pmd_mlx4/mlx4.c
@@ -4162,7 +4162,7 @@  mlx4_vlan_filter_set(struct rte_eth_dev *dev, uint16_t vlan_id, int on)
 	return -ret;
 }
 
-static struct eth_dev_ops mlx4_dev_ops = {
+static const struct eth_dev_ops mlx4_dev_ops = {
 	.dev_configure = mlx4_dev_configure,
 	.dev_start = mlx4_dev_start,
 	.dev_stop = mlx4_dev_stop,
diff --git a/lib/librte_pmd_null/rte_eth_null.c b/lib/librte_pmd_null/rte_eth_null.c
index 0e18502..c78c0c1 100644
--- a/lib/librte_pmd_null/rte_eth_null.c
+++ b/lib/librte_pmd_null/rte_eth_null.c
@@ -363,18 +363,18 @@  static int
 eth_link_update(struct rte_eth_dev *dev __rte_unused,
 		int wait_to_complete __rte_unused) { return 0; }
 
-static struct eth_dev_ops ops = {
-		.dev_start = eth_dev_start,
-		.dev_stop = eth_dev_stop,
-		.dev_configure = eth_dev_configure,
-		.dev_infos_get = eth_dev_info,
-		.rx_queue_setup = eth_rx_queue_setup,
-		.tx_queue_setup = eth_tx_queue_setup,
-		.rx_queue_release = eth_queue_release,
-		.tx_queue_release = eth_queue_release,
-		.link_update = eth_link_update,
-		.stats_get = eth_stats_get,
-		.stats_reset = eth_stats_reset,
+static const struct eth_dev_ops ops = {
+	.dev_start = eth_dev_start,
+	.dev_stop = eth_dev_stop,
+	.dev_configure = eth_dev_configure,
+	.dev_infos_get = eth_dev_info,
+	.rx_queue_setup = eth_rx_queue_setup,
+	.tx_queue_setup = eth_tx_queue_setup,
+	.rx_queue_release = eth_queue_release,
+	.tx_queue_release = eth_queue_release,
+	.link_update = eth_link_update,
+	.stats_get = eth_stats_get,
+	.stats_reset = eth_stats_reset,
 };
 
 static int
diff --git a/lib/librte_pmd_pcap/rte_eth_pcap.c b/lib/librte_pmd_pcap/rte_eth_pcap.c
index 204ae68..a4f4d36 100644
--- a/lib/librte_pmd_pcap/rte_eth_pcap.c
+++ b/lib/librte_pmd_pcap/rte_eth_pcap.c
@@ -483,19 +483,19 @@  eth_tx_queue_setup(struct rte_eth_dev *dev,
 	return 0;
 }
 
-static struct eth_dev_ops ops = {
-		.dev_start = eth_dev_start,
-		.dev_stop =	eth_dev_stop,
-		.dev_close = eth_dev_close,
-		.dev_configure = eth_dev_configure,
-		.dev_infos_get = eth_dev_info,
-		.rx_queue_setup = eth_rx_queue_setup,
-		.tx_queue_setup = eth_tx_queue_setup,
-		.rx_queue_release = eth_queue_release,
-		.tx_queue_release = eth_queue_release,
-		.link_update = eth_link_update,
-		.stats_get = eth_stats_get,
-		.stats_reset = eth_stats_reset,
+static const struct eth_dev_ops ops = {
+	.dev_start = eth_dev_start,
+	.dev_stop =	eth_dev_stop,
+	.dev_close = eth_dev_close,
+	.dev_configure = eth_dev_configure,
+	.dev_infos_get = eth_dev_info,
+	.rx_queue_setup = eth_rx_queue_setup,
+	.tx_queue_setup = eth_tx_queue_setup,
+	.rx_queue_release = eth_queue_release,
+	.tx_queue_release = eth_queue_release,
+	.link_update = eth_link_update,
+	.stats_get = eth_stats_get,
+	.stats_reset = eth_stats_reset,
 };
 
 static struct eth_driver rte_pcap_pmd = {
diff --git a/lib/librte_pmd_ring/rte_eth_ring.c b/lib/librte_pmd_ring/rte_eth_ring.c
index 1e66d4e..efb50d0 100644
--- a/lib/librte_pmd_ring/rte_eth_ring.c
+++ b/lib/librte_pmd_ring/rte_eth_ring.c
@@ -234,22 +234,22 @@  static int
 eth_link_update(struct rte_eth_dev *dev __rte_unused,
 		int wait_to_complete __rte_unused) { return 0; }
 
-static struct eth_dev_ops ops = {
-		.dev_start = eth_dev_start,
-		.dev_stop = eth_dev_stop,
-		.dev_set_link_up = eth_dev_set_link_up,
-		.dev_set_link_down = eth_dev_set_link_down,
-		.dev_configure = eth_dev_configure,
-		.dev_infos_get = eth_dev_info,
-		.rx_queue_setup = eth_rx_queue_setup,
-		.tx_queue_setup = eth_tx_queue_setup,
-		.rx_queue_release = eth_queue_release,
-		.tx_queue_release = eth_queue_release,
-		.link_update = eth_link_update,
-		.stats_get = eth_stats_get,
-		.stats_reset = eth_stats_reset,
-		.mac_addr_remove = eth_mac_addr_remove,
-		.mac_addr_add = eth_mac_addr_add,
+static const struct eth_dev_ops ops = {
+	.dev_start = eth_dev_start,
+	.dev_stop = eth_dev_stop,
+	.dev_set_link_up = eth_dev_set_link_up,
+	.dev_set_link_down = eth_dev_set_link_down,
+	.dev_configure = eth_dev_configure,
+	.dev_infos_get = eth_dev_info,
+	.rx_queue_setup = eth_rx_queue_setup,
+	.tx_queue_setup = eth_tx_queue_setup,
+	.rx_queue_release = eth_queue_release,
+	.tx_queue_release = eth_queue_release,
+	.link_update = eth_link_update,
+	.stats_get = eth_stats_get,
+	.stats_reset = eth_stats_reset,
+	.mac_addr_remove = eth_mac_addr_remove,
+	.mac_addr_add = eth_mac_addr_add,
 };
 
 int
diff --git a/lib/librte_pmd_virtio/virtio_ethdev.c b/lib/librte_pmd_virtio/virtio_ethdev.c
index 7b83d9b..ffa26a0 100644
--- a/lib/librte_pmd_virtio/virtio_ethdev.c
+++ b/lib/librte_pmd_virtio/virtio_ethdev.c
@@ -499,7 +499,7 @@  virtio_dev_allmulticast_disable(struct rte_eth_dev *dev)
 /*
  * dev_ops for virtio, bare necessities for basic operation
  */
-static struct eth_dev_ops virtio_eth_dev_ops = {
+static const struct eth_dev_ops virtio_eth_dev_ops = {
 	.dev_configure           = virtio_dev_configure,
 	.dev_start               = virtio_dev_start,
 	.dev_stop                = virtio_dev_stop,
diff --git a/lib/librte_pmd_vmxnet3/vmxnet3_ethdev.c b/lib/librte_pmd_vmxnet3/vmxnet3_ethdev.c
index 458dce5..577e0f9 100644
--- a/lib/librte_pmd_vmxnet3/vmxnet3_ethdev.c
+++ b/lib/librte_pmd_vmxnet3/vmxnet3_ethdev.c
@@ -99,7 +99,7 @@  static struct rte_pci_id pci_id_vmxnet3_map[] = {
 { .vendor_id = 0, /* sentinel */ },
 };
 
-static struct eth_dev_ops vmxnet3_eth_dev_ops = {
+static const struct eth_dev_ops vmxnet3_eth_dev_ops = {
 	.dev_configure        = vmxnet3_dev_configure,
 	.dev_start            = vmxnet3_dev_start,
 	.dev_stop             = vmxnet3_dev_stop,
diff --git a/lib/librte_pmd_xenvirt/rte_eth_xenvirt.c b/lib/librte_pmd_xenvirt/rte_eth_xenvirt.c
index bc403d6..4396141 100644
--- a/lib/librte_pmd_xenvirt/rte_eth_xenvirt.c
+++ b/lib/librte_pmd_xenvirt/rte_eth_xenvirt.c
@@ -526,19 +526,19 @@  eth_tx_queue_setup(struct rte_eth_dev *dev, uint16_t tx_queue_id,
 
 
 
-static struct eth_dev_ops ops = {
-		.dev_start = eth_dev_start,
-		.dev_stop = eth_dev_stop,
-		.dev_close = eth_dev_close,
-		.dev_configure = eth_dev_configure,
-		.dev_infos_get = eth_dev_info,
-		.rx_queue_setup = eth_rx_queue_setup,
-		.tx_queue_setup = eth_tx_queue_setup,
-		.rx_queue_release = eth_queue_release,
-		.tx_queue_release = eth_queue_release,
-		.link_update = eth_link_update,
-		.stats_get = eth_stats_get,
-		.stats_reset = eth_stats_reset,
+static const struct eth_dev_ops ops = {
+	.dev_start = eth_dev_start,
+	.dev_stop = eth_dev_stop,
+	.dev_close = eth_dev_close,
+	.dev_configure = eth_dev_configure,
+	.dev_infos_get = eth_dev_info,
+	.rx_queue_setup = eth_rx_queue_setup,
+	.tx_queue_setup = eth_tx_queue_setup,
+	.rx_queue_release = eth_queue_release,
+	.tx_queue_release = eth_queue_release,
+	.link_update = eth_link_update,
+	.stats_get = eth_stats_get,
+	.stats_reset = eth_stats_reset,
 };