diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c
index fd1010a..3c24040 100644
--- a/lib/librte_ether/rte_ethdev.c
+++ b/lib/librte_ether/rte_ethdev.c
@@ -928,6 +928,7 @@ rte_eth_rx_queue_setup(uint8_t port_id, uint16_t rx_queue_id,
 	struct rte_eth_dev *dev;
 	struct rte_pktmbuf_pool_private *mbp_priv;
 	struct rte_eth_dev_info dev_info;
+	const struct rte_eth_rxconf *conf;
 
 	/* This function is only safe when called from the primary process
 	 * in a multi-process setup*/
@@ -937,6 +938,16 @@ rte_eth_rx_queue_setup(uint8_t port_id, uint16_t rx_queue_id,
 		PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
 		return (-EINVAL);
 	}
+
+	conf = rx_conf;
+	if (conf == NULL) {
+		conf = rte_eth_rxconf_defaults(port_id, NULL);
+		if (conf == NULL) {
+			PMD_DEBUG_TRACE("Invalid RX port configuration\n");
+			return (-EINVAL);
+		}
+	}
+
 	dev = &rte_eth_devices[port_id];
 	if (rx_queue_id >= dev->data->nb_rx_queues) {
 		PMD_DEBUG_TRACE("Invalid RX queue_id=%d\n", rx_queue_id);
@@ -997,6 +1008,7 @@ rte_eth_tx_queue_setup(uint8_t port_id, uint16_t tx_queue_id,
 		       const struct rte_eth_txconf *tx_conf)
 {
 	struct rte_eth_dev *dev;
+	const struct rte_eth_txconf *conf;
 
 	/* This function is only safe when called from the primary process
 	 * in a multi-process setup*/
@@ -1006,6 +1018,16 @@ rte_eth_tx_queue_setup(uint8_t port_id, uint16_t tx_queue_id,
 		PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
 		return (-EINVAL);
 	}
+
+	conf = tx_conf;
+	if (conf == NULL) {
+		conf = rte_eth_txconf_defaults(port_id, NULL);
+		if (conf == NULL) {
+			PMD_DEBUG_TRACE("Invalid TX port configuration\n");
+			return (-EINVAL);
+		}
+	}
+
 	dev = &rte_eth_devices[port_id];
 	if (tx_queue_id >= dev->data->nb_tx_queues) {
 		PMD_DEBUG_TRACE("Invalid TX queue_id=%d\n", tx_queue_id);
@@ -3002,3 +3024,49 @@ rte_eth_dev_get_flex_filter(uint8_t port_id, uint16_t index,
 	return (*dev->dev_ops->get_flex_filter)(dev, index, filter,
 						rx_queue);
 }
+
+const struct rte_eth_rxconf *
+rte_eth_rxconf_defaults(uint8_t port_id, struct rte_eth_rxconf *conf)
+{
+	struct rte_eth_dev *dev;
+	static const struct rte_eth_rxconf defaults;
+
+	if (port_id >= nb_ports) {
+		PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
+		return NULL;
+	}
+
+	dev = &rte_eth_devices[port_id];
+
+	if (dev->dev_ops->rxconf_defaults) {
+		return (*dev->dev_ops->rxconf_defaults)(conf);
+	} else {
+		if (conf == NULL)
+			return &defaults;
+		*conf = defaults;
+	}
+	return conf;
+}
+
+const struct rte_eth_txconf *
+rte_eth_txconf_defaults(uint8_t port_id, struct rte_eth_txconf *conf)
+{
+	struct rte_eth_dev *dev;
+	static const struct rte_eth_txconf defaults;
+
+	if (port_id >= nb_ports) {
+		PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
+		return NULL;
+	}
+
+	dev = &rte_eth_devices[port_id];
+
+	if (dev->dev_ops->txconf_defaults) {
+		return (*dev->dev_ops->txconf_defaults)(conf);
+	} else {
+		if (conf == NULL)
+			return &defaults;
+		*conf = defaults;
+	}
+	return conf;
+}
diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h
index 50df654..70026fd 100644
--- a/lib/librte_ether/rte_ethdev.h
+++ b/lib/librte_ether/rte_ethdev.h
@@ -1361,6 +1361,12 @@ typedef int (*eth_get_flex_filter_t)(struct rte_eth_dev *dev,
 			uint16_t *rx_queue);
 /**< @internal Get a flex filter rule on an Ethernet device */
 
+typedef const struct rte_eth_rxconf * (*eth_rxconf_defaults_t) (struct rte_eth_rxconf *conf);
+/**< @internal Get the default RX port configuration on an Ethernet device */
+
+typedef const struct rte_eth_txconf * (*eth_txconf_defaults_t) (struct rte_eth_txconf *conf);
+/**< @internal Get the default TX port configuration on an Ethernet device */
+
 /**
  * @internal A structure containing the functions exported by an Ethernet driver.
  */
@@ -1467,6 +1473,8 @@ struct eth_dev_ops {
 	eth_add_flex_filter_t          add_flex_filter;      /**< add flex filter. */
 	eth_remove_flex_filter_t       remove_flex_filter;   /**< remove flex filter. */
 	eth_get_flex_filter_t          get_flex_filter;      /**< get flex filter. */
+	eth_rxconf_defaults_t          rxconf_defaults;      /**< get default RX configuration. */
+	eth_txconf_defaults_t          txconf_defaults;      /**< get default TX configuration. */
 };
 
 /**
@@ -3557,6 +3565,27 @@ int rte_eth_dev_remove_flex_filter(uint8_t port_id, uint16_t index);
 int rte_eth_dev_get_flex_filter(uint8_t port_id, uint16_t index,
 			struct rte_flex_filter *filter, uint16_t *rx_queue);
 
+/**
+ * Get default port configuration.
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+ * @param port_conf_default
+ *   Pointer to get the struct rte_eth_conf
+ * @param rx_conf_default
+ *   Pointer to get the struct rte_eth_rxconf
+ * @param tx_conf_default:
+ *   Pointer to get the struct rte_eth_txconf
+ * @param burst_size
+ *   Pointer to get the default burst size
+ * @return
+ *   - (0) if successful.
+ *   - (-ENODEV) if *port_id* invalid.
+ */
+const struct rte_eth_rxconf *rte_eth_rxconf_defaults(uint8_t port_id,
+			struct rte_eth_rxconf *conf);
+
+const struct rte_eth_txconf *rte_eth_txconf_defaults(uint8_t port_id,
+			struct rte_eth_txconf *conf);
 #ifdef __cplusplus
 }
 #endif
diff --git a/lib/librte_pmd_e1000/igb_ethdev.c b/lib/librte_pmd_e1000/igb_ethdev.c
index 3187d92..30f1ee3 100644
--- a/lib/librte_pmd_e1000/igb_ethdev.c
+++ b/lib/librte_pmd_e1000/igb_ethdev.c
@@ -57,6 +57,18 @@
 #include "e1000/e1000_api.h"
 #include "e1000_ethdev.h"
 
+/**
+ *  Default values for port configuration
+ */
+#define IGB_DEFAULT_RX_FREE_THRESH  32
+#define IGB_DEFAULT_RX_PTHRESH      8
+#define IGB_DEFAULT_RX_HTHRESH      8
+#define IGB_DEFAULT_RX_WTHRESH      0
+
+#define IGB_DEFAULT_TX_PTHRESH      32
+#define IGB_DEFAULT_TX_HTHRESH      0
+#define IGB_DEFAULT_TX_WTHRESH      0
+
 static int  eth_igb_configure(struct rte_eth_dev *dev);
 static int  eth_igb_start(struct rte_eth_dev *dev);
 static void eth_igb_stop(struct rte_eth_dev *dev);
@@ -165,7 +177,8 @@ static int eth_igb_remove_5tuple_filter(struct rte_eth_dev *dev,
 static int eth_igb_get_5tuple_filter(struct rte_eth_dev *dev,
 			uint16_t index,
 			struct rte_5tuple_filter *filter, uint16_t *rx_queue);
-
+static const struct rte_eth_rxconf *eth_igb_rxconf_defaults(struct rte_eth_rxconf *conf);
+static const struct rte_eth_txconf *eth_igb_txconf_defaults(struct rte_eth_txconf *conf);
 /*
  * Define VF Stats MACRO for Non "cleared on read" register
  */
@@ -255,6 +268,8 @@ static struct eth_dev_ops eth_igb_ops = {
 	.add_5tuple_filter       = eth_igb_add_5tuple_filter,
 	.remove_5tuple_filter    = eth_igb_remove_5tuple_filter,
 	.get_5tuple_filter       = eth_igb_get_5tuple_filter,
+	.rxconf_defaults         = eth_igb_rxconf_defaults,
+	.txconf_defaults         = eth_igb_txconf_defaults,
 };
 
 /*
@@ -3008,6 +3023,45 @@ eth_igb_get_5tuple_filter(struct rte_eth_dev *dev, uint16_t index,
 	return -ENOENT;
 }
 
+static const struct rte_eth_rxconf *
+eth_igb_rxconf_defaults(struct rte_eth_rxconf *conf)
+{
+	static const struct rte_eth_rxconf defaults = {
+		.rx_thresh = {
+			.pthresh = IGB_DEFAULT_RX_PTHRESH,
+			.hthresh = IGB_DEFAULT_RX_HTHRESH,
+			.wthresh = IGB_DEFAULT_RX_WTHRESH,
+		},
+		.rx_free_thresh = IGB_DEFAULT_RX_FREE_THRESH,
+		.rx_drop_en = 0,
+	};
+
+	if (conf == NULL)
+		return &defaults;
+	*conf = defaults;
+
+	return conf;
+}
+
+static const struct rte_eth_txconf *
+eth_igb_txconf_defaults(struct rte_eth_txconf *conf)
+{
+	static const struct rte_eth_txconf defaults = {
+		.tx_thresh = {
+			.pthresh = IGB_DEFAULT_TX_PTHRESH,
+			.hthresh = IGB_DEFAULT_TX_HTHRESH,
+			.wthresh = IGB_DEFAULT_TX_WTHRESH,
+		},
+		.txq_flags = 0,
+	};
+
+	if (conf == NULL)
+		return &defaults;
+	*conf = defaults;
+
+	return conf;
+}
+
 static int
 eth_igb_mtu_set(struct rte_eth_dev *dev, uint16_t mtu)
 {
diff --git a/lib/librte_pmd_i40e/i40e_ethdev.c b/lib/librte_pmd_i40e/i40e_ethdev.c
index 9ed31b5..b89b896 100644
--- a/lib/librte_pmd_i40e/i40e_ethdev.c
+++ b/lib/librte_pmd_i40e/i40e_ethdev.c
@@ -58,6 +58,17 @@
 #include "i40e_rxtx.h"
 #include "i40e_pf.h"
 
+#define I40E_DEFAULT_RX_FREE_THRESH  32
+#define I40E_DEFAULT_RX_PTHRESH      8
+#define I40E_DEFAULT_RX_HTHRESH      8
+#define I40E_DEFAULT_RX_WTHRESH      0
+
+#define I40E_DEFAULT_TX_FREE_THRESH  32
+#define I40E_DEFAULT_TX_PTHRESH      32
+#define I40E_DEFAULT_TX_HTHRESH      0
+#define I40E_DEFAULT_TX_WTHRESH      0
+#define I40E_DEFAULT_TX_RSBIT_THRESH 32
+
 /* Maximun number of MAC addresses */
 #define I40E_NUM_MACADDR_MAX       64
 #define I40E_CLEAR_PXE_WAIT_MS     200
@@ -203,6 +214,8 @@ static int i40e_dev_rss_hash_update(struct rte_eth_dev *dev,
 				    struct rte_eth_rss_conf *rss_conf);
 static int i40e_dev_rss_hash_conf_get(struct rte_eth_dev *dev,
 				      struct rte_eth_rss_conf *rss_conf);
+static const struct rte_eth_rxconf *i40e_rxconf_defaults(struct rte_eth_rxconf *conf);
+static const struct rte_eth_txconf *i40e_txconf_defaults(struct rte_eth_txconf *conf);
 
 /* Default hash key buffer for RSS */
 static uint32_t rss_key_default[I40E_PFQF_HKEY_MAX_INDEX + 1];
@@ -248,6 +261,8 @@ static struct eth_dev_ops i40e_eth_dev_ops = {
 	.reta_query                   = i40e_dev_rss_reta_query,
 	.rss_hash_update              = i40e_dev_rss_hash_update,
 	.rss_hash_conf_get            = i40e_dev_rss_hash_conf_get,
+	.rxconf_defaults              = i40e_rxconf_defaults,
+	.txconf_defaults              = i40e_txconf_defaults,
 };
 
 static struct eth_driver rte_i40e_pmd = {
@@ -3956,3 +3971,44 @@ i40e_pf_config_mq_rx(struct i40e_pf *pf)
 
 	return 0;
 }
+
+static const struct rte_eth_rxconf *
+i40e_rxconf_defaults(struct rte_eth_rxconf *conf)
+{
+	static const struct rte_eth_rxconf defaults = {
+		.rx_thresh = {
+			.pthresh = I40E_DEFAULT_RX_PTHRESH,
+			.hthresh = I40E_DEFAULT_RX_HTHRESH,
+			.wthresh = I40E_DEFAULT_RX_WTHRESH,
+		},
+		.rx_free_thresh = I40E_DEFAULT_RX_FREE_THRESH,
+		.rx_drop_en = 0,
+	};
+
+	if (conf == NULL)
+		return &defaults;
+	*conf = defaults;
+
+	return conf;
+}
+
+static const struct rte_eth_txconf *
+i40e_txconf_defaults(struct rte_eth_txconf *conf)
+{
+	static const struct rte_eth_txconf defaults = {
+		.tx_thresh = {
+			.pthresh = I40E_DEFAULT_TX_PTHRESH,
+			.hthresh = I40E_DEFAULT_TX_HTHRESH,
+			.wthresh = I40E_DEFAULT_TX_WTHRESH,
+		},
+		.tx_free_thresh = I40E_DEFAULT_TX_FREE_THRESH,
+		.tx_rs_thresh = I40E_DEFAULT_TX_RSBIT_THRESH,
+		.txq_flags = ETH_TXQ_FLAGS_NOMULTSEGS | ETH_TXQ_FLAGS_NOOFFLOADS,
+	};
+
+	if (conf == NULL)
+		return &defaults;
+	*conf = defaults;
+
+	return conf;
+}
diff --git a/lib/librte_pmd_ixgbe/ixgbe_ethdev.c b/lib/librte_pmd_ixgbe/ixgbe_ethdev.c
index 59122a1..7f61d00 100644
--- a/lib/librte_pmd_ixgbe/ixgbe_ethdev.c
+++ b/lib/librte_pmd_ixgbe/ixgbe_ethdev.c
@@ -92,6 +92,20 @@
 #define IXGBE_MMW_SIZE_DEFAULT        0x4
 #define IXGBE_MMW_SIZE_JUMBO_FRAME    0x14
 
+/**
+ *  Default values for RX/TX configuration
+ */
+#define IXGBE_DEFAULT_RX_FREE_THRESH  32
+#define IXGBE_DEFAULT_RX_PTHRESH      8
+#define IXGBE_DEFAULT_RX_HTHRESH      8
+#define IXGBE_DEFAULT_RX_WTHRESH      0
+
+#define IXGBE_DEFAULT_TX_FREE_THRESH  32
+#define IXGBE_DEFAULT_TX_PTHRESH      32
+#define IXGBE_DEFAULT_TX_HTHRESH      0
+#define IXGBE_DEFAULT_TX_WTHRESH      0
+#define IXGBE_DEFAULT_TX_RSBIT_THRESH 32
+
 #define IXGBEVF_PMD_NAME "rte_ixgbevf_pmd" /* PMD name */
 
 #define IXGBE_QUEUE_STAT_COUNTERS (sizeof(hw_stats->qprc) / sizeof(hw_stats->qprc[0]))
@@ -219,6 +233,8 @@ 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 const struct rte_eth_rxconf *ixgbe_rxconf_defaults(struct rte_eth_rxconf *conf);
+static const struct rte_eth_txconf *ixgbe_txconf_defaults(struct rte_eth_txconf *conf);
 
 static int ixgbevf_dev_set_mtu(struct rte_eth_dev *dev, uint16_t mtu);
 
@@ -362,6 +378,8 @@ static struct eth_dev_ops ixgbe_eth_dev_ops = {
 	.add_5tuple_filter       = ixgbe_add_5tuple_filter,
 	.remove_5tuple_filter    = ixgbe_remove_5tuple_filter,
 	.get_5tuple_filter       = ixgbe_get_5tuple_filter,
+	.rxconf_defaults         = ixgbe_rxconf_defaults,
+	.txconf_defaults         = ixgbe_txconf_defaults,
 };
 
 /*
@@ -388,6 +406,8 @@ static struct eth_dev_ops ixgbevf_eth_dev_ops = {
 	.tx_queue_release     = ixgbe_dev_tx_queue_release,
 	.mac_addr_add         = ixgbevf_add_mac_addr,
 	.mac_addr_remove      = ixgbevf_remove_mac_addr,
+	.rxconf_defaults      = ixgbe_rxconf_defaults,
+	.txconf_defaults      = ixgbe_txconf_defaults,
 };
 
 /**
@@ -3940,6 +3960,45 @@ ixgbe_get_5tuple_filter(struct rte_eth_dev *dev, uint16_t index,
 	return -ENOENT;
 }
 
+const struct rte_eth_rxconf *
+ixgbe_rxconf_defaults(struct rte_eth_rxconf *conf)
+{
+	static const struct rte_eth_rxconf defaults = {
+			.rx_thresh = {
+				.pthresh = IXGBE_DEFAULT_RX_PTHRESH,
+				.hthresh = IXGBE_DEFAULT_RX_HTHRESH,
+				.wthresh = IXGBE_DEFAULT_RX_WTHRESH,
+			},
+			.rx_free_thresh = IXGBE_DEFAULT_RX_FREE_THRESH,
+			.rx_drop_en = 0,
+	};
+	if (conf == NULL)
+		return &defaults;
+	*conf = defaults;
+
+	return conf;
+}
+
+const struct rte_eth_txconf *
+ixgbe_txconf_defaults(struct rte_eth_txconf *conf)
+{
+	static const struct rte_eth_txconf defaults = {
+			.tx_thresh = {
+				.pthresh = IXGBE_DEFAULT_TX_PTHRESH,
+				.hthresh = IXGBE_DEFAULT_TX_HTHRESH,
+				.wthresh = IXGBE_DEFAULT_TX_WTHRESH,
+			},
+			.tx_free_thresh = IXGBE_DEFAULT_TX_FREE_THRESH,
+			.tx_rs_thresh = IXGBE_DEFAULT_TX_RSBIT_THRESH,
+			.txq_flags = ETH_TXQ_FLAGS_NOMULTSEGS | ETH_TXQ_FLAGS_NOOFFLOADS,
+	};
+	if (conf == NULL)
+		return &defaults;
+	*conf = defaults;
+
+	return conf;
+}
+
 static int
 ixgbevf_dev_set_mtu(struct rte_eth_dev *dev, uint16_t mtu)
 {
